Skip to content

Commit 5153106

Browse files
committed
Enhances tool descriptions and UI configuration
Improves the clarity and detail of tool descriptions for better user understanding. Refactors the UI to include a toggle all tools feature and displays tool configuration as active/total. Adds a new test suite to validate UI tools configuration functionality.
1 parent 914e931 commit 5153106

File tree

9 files changed

+432
-130
lines changed

9 files changed

+432
-130
lines changed

src/tools/github_search.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def name(self) -> str:
77

88
@property
99
def description(self) -> str:
10-
return "The only reliable Knowledgebase on GitHub topics. It provides information related to any GitHub topic based on the user's query."
10+
return "Search the comprehensive GitHub knowledge base using advanced vector embeddings and semantic search to find authoritative information on GitHub-related topics, features, APIs, and best practices. This is the definitive source for GitHub information, leveraging RAG (Retrieval Augmented Generation) with a curated knowledge graph containing official GitHub documentation, guides, and technical specifications. Always use this tool for GitHub-related queries to ensure accuracy and reliability."
1111

1212
@property
1313
def parameters(self) -> dict:
@@ -16,7 +16,7 @@ def parameters(self) -> dict:
1616
"properties": {
1717
"query": {
1818
"type": "string",
19-
"description": "The user query related to any GitHub topic."
19+
"description": "Natural language query about any GitHub topic including features, APIs, Actions, repositories, issues, pull requests, security, integrations, or development workflows. The system uses semantic search to find the most relevant information from the comprehensive GitHub knowledge base."
2020
}
2121
},
2222
"required": ["query"]

src/tools/google_search.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def name(self) -> str:
77

88
@property
99
def description(self) -> str:
10-
return "Search the web for relevant information."
10+
return "Perform web searches using Google Custom Search API to retrieve relevant information from the internet. Returns structured search results including titles, URLs, snippets, and metadata. Supports configurable result limits and provides search performance metrics. Requires valid Google API credentials and custom search engine configuration."
1111

1212
@property
1313
def parameters(self) -> dict:
@@ -16,11 +16,11 @@ def parameters(self) -> dict:
1616
"properties": {
1717
"query": {
1818
"type": "string",
19-
"description": "The search query to use"
19+
"description": "The search query string to submit to Google. Supports standard Google search operators and syntax including quotes for exact phrases, site: for domain filtering, and boolean operators."
2020
},
2121
"num_results": {
2222
"type": "number",
23-
"description": "Number of results to return (default: 5, max: 10)"
23+
"description": "Maximum number of search results to return. Valid range is 1-10, defaults to 5 if not specified. Higher values may increase API quota usage and response time."
2424
}
2525
},
2626
"required": ["query"]

src/tools/list_files.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ def name(self) -> str:
88

99
@property
1010
def description(self) -> str:
11-
return "List files in a specified directory within a secure base directory."
11+
return "List files and directories within a specified directory path, constrained to operate within a secure base directory for security. Returns comprehensive file listing with metadata including file names, types, and directory structure. Supports recursive directory traversal within security boundaries."
1212

1313
@property
1414
def parameters(self) -> dict:
@@ -17,11 +17,11 @@ def parameters(self) -> dict:
1717
"properties": {
1818
"base_dir": {
1919
"type": "string",
20-
"description": "Base directory for file operations"
20+
"description": "Absolute path to the base directory that serves as the security boundary for all file operations. All file access is restricted to this directory and its subdirectories."
2121
},
2222
"directory": {
2323
"type": "string",
24-
"description": "The relative subdirectory path to list files from (default: '.')"
24+
"description": "Relative path to the subdirectory within base_dir to list files from. Defaults to '.' for current directory. Path traversal attacks are prevented by security validation."
2525
}
2626
},
2727
"required": ["base_dir"]

src/tools/read_file.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def name(self) -> str:
77

88
@property
99
def description(self) -> str:
10-
return "Read content from a specified file within a secure base directory."
10+
return "Read and return the complete content of a specified file within security-constrained base directory boundaries. Supports text and binary file reading with proper error handling for missing files, permission issues, and encoding problems. File access is restricted to the specified base directory to prevent path traversal vulnerabilities."
1111

1212
@property
1313
def parameters(self) -> dict:
@@ -16,11 +16,11 @@ def parameters(self) -> dict:
1616
"properties": {
1717
"base_dir": {
1818
"type": "string",
19-
"description": "Base directory for file operations"
19+
"description": "Absolute path to the base directory that serves as the security boundary for all file operations. All file access is restricted to this directory and its subdirectories."
2020
},
2121
"filename": {
2222
"type": "string",
23-
"description": "The name of the file to read from (relative path)"
23+
"description": "Relative path to the target file within base_dir. Can include subdirectory paths. Path traversal attempts (../) are automatically prevented by security validation."
2424
}
2525
},
2626
"required": ["base_dir", "filename"]

src/tools/write_file.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def name(self) -> str:
77

88
@property
99
def description(self) -> str:
10-
return "Write content to a specified file within a secure base directory."
10+
return "Write or overwrite content to a specified file within security-constrained base directory boundaries. Creates directories as needed and handles text encoding automatically. Supports creating new files or updating existing ones with comprehensive error handling for permission issues, disk space, and path validation. File operations are restricted to the specified base directory to prevent path traversal vulnerabilities."
1111

1212
@property
1313
def parameters(self) -> dict:
@@ -16,15 +16,15 @@ def parameters(self) -> dict:
1616
"properties": {
1717
"base_dir": {
1818
"type": "string",
19-
"description": "Base directory for file operations"
19+
"description": "Absolute path to the base directory that serves as the security boundary for all file operations. All file access is restricted to this directory and its subdirectories."
2020
},
2121
"filename": {
2222
"type": "string",
23-
"description": "The name of the file to write to (relative path)"
23+
"description": "Relative path to the target file within base_dir. Can include subdirectory paths which will be created if they don't exist. Path traversal attempts (../) are automatically prevented by security validation."
2424
},
2525
"content": {
2626
"type": "string",
27-
"description": "The content to write to the file"
27+
"description": "The text content to write to the file. Existing file content will be completely replaced. Unicode and special characters are supported with automatic encoding handling."
2828
}
2929
},
3030
"required": ["base_dir", "filename", "content"]

src/ui/chat.ts

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,45 @@ class ChatApp {
454454
private renderTools(): void {
455455
this.toolsList.innerHTML = '';
456456

457-
this.tools.forEach(tool => {
457+
// Add toggle all item at the top
458+
const toggleAllItem = document.createElement('div');
459+
toggleAllItem.className = 'disable-all-item';
460+
461+
const toggleAllName = document.createElement('div');
462+
toggleAllName.className = 'disable-all-name';
463+
toggleAllName.textContent = 'Toggle All Tools';
464+
465+
const toggleAllDescription = document.createElement('div');
466+
toggleAllDescription.className = 'disable-all-description';
467+
toggleAllDescription.textContent = 'Enable or disable all tools at once';
468+
469+
const enabledCount = this.tools.filter(tool => tool.enabled).length;
470+
const totalCount = this.tools.length;
471+
const allEnabled = enabledCount === totalCount;
472+
473+
// Update the tools configuration text to show active/total format
474+
const toolsLabelSpan = this.toolsHeader.querySelector('.tools-label span');
475+
if (toolsLabelSpan) {
476+
toolsLabelSpan.textContent = `Tools Configuration [${enabledCount}/${totalCount}]`;
477+
}
478+
479+
const toggleAllToggle = document.createElement('div');
480+
toggleAllToggle.className = `tool-toggle ${allEnabled ? 'enabled' : ''}`;
481+
toggleAllToggle.addEventListener('click', (e) => {
482+
e.stopPropagation();
483+
this.toggleAllTools(!allEnabled);
484+
});
485+
486+
toggleAllItem.appendChild(toggleAllName);
487+
toggleAllItem.appendChild(toggleAllDescription);
488+
toggleAllItem.appendChild(toggleAllToggle);
489+
490+
this.toolsList.appendChild(toggleAllItem);
491+
492+
// Sort tools alphabetically by name
493+
const sortedTools = [...this.tools].sort((a, b) => a.name.localeCompare(b.name));
494+
495+
sortedTools.forEach(tool => {
458496
const toolItem = document.createElement('div');
459497
toolItem.className = 'tool-item';
460498

@@ -510,6 +548,36 @@ class ChatApp {
510548
console.error('Error toggling tool:', error);
511549
}
512550
}
551+
552+
private async toggleAllTools(enabled: boolean): Promise<void> {
553+
const toolsToChange = this.tools.filter(tool => tool.enabled !== enabled);
554+
555+
for (const tool of toolsToChange) {
556+
try {
557+
const response = await fetch(`${this.apiBaseUrl}/tools/toggle`, {
558+
method: 'POST',
559+
headers: {
560+
'Content-Type': 'application/json',
561+
'X-API-Key': 'test_12345'
562+
},
563+
body: JSON.stringify({
564+
tool_name: tool.name,
565+
enabled: enabled
566+
})
567+
});
568+
569+
if (response.ok) {
570+
tool.enabled = enabled;
571+
} else {
572+
console.error(`Failed to ${enabled ? 'enable' : 'disable'} tool ${tool.name}:`, await response.text());
573+
}
574+
} catch (error) {
575+
console.error(`Error ${enabled ? 'enabling' : 'disabling'} tool ${tool.name}:`, error);
576+
}
577+
}
578+
579+
this.renderTools();
580+
}
513581
}
514582

515583
document.addEventListener('DOMContentLoaded', () => {

src/ui/index.html

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,50 +18,55 @@
1818
</svg>
1919
New chat
2020
</button>
21-
22-
<div class="tools-section">
23-
<div class="tools-header" id="toolsHeader">
24-
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
25-
<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/>
26-
</svg>
27-
<span>Tools</span>
28-
<svg class="chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
29-
<polyline points="6,9 12,15 18,9"></polyline>
30-
</svg>
31-
</div>
32-
<div class="tools-list" id="toolsList">
33-
<!-- Tool items will be populated here -->
34-
</div>
35-
</div>
3621
</div>
3722
<div class="chat-history" id="chatHistory">
3823
<!-- Chat history items will be added here -->
3924
</div>
4025
</div>
4126

4227
<div class="main-content">
43-
<div class="chat-container">
44-
<div class="messages-container" id="messagesContainer">
45-
<div class="welcome-message">
46-
<h1>AI Agent</h1>
47-
<p>How can I help you today?</p>
28+
<div class="tools-section-top">
29+
<div class="tools-header" id="toolsHeader">
30+
<div class="tools-header-content">
31+
<svg class="chevron" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
32+
<polyline points="6,9 12,15 18,9"></polyline>
33+
</svg>
34+
<div class="tools-label">
35+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
36+
<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/>
37+
</svg>
38+
<span>Tools Configuration</span>
39+
</div>
4840
</div>
4941
</div>
50-
51-
<div class="input-container">
52-
<div class="input-wrapper">
53-
<textarea
54-
id="messageInput"
55-
placeholder="Message AI Agent..."
56-
rows="1"
57-
maxlength="2000"
58-
></textarea>
59-
<button id="sendBtn" class="send-btn" disabled>
60-
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
61-
<path d="M22 2L11 13" stroke="currentColor" stroke-width="2"/>
62-
<path d="M22 2L15 22L11 13L2 9L22 2Z" stroke="currentColor" stroke-width="2"/>
63-
</svg>
64-
</button>
42+
<div class="tools-list" id="toolsList">
43+
<!-- Tool items will be populated here -->
44+
</div>
45+
</div>
46+
47+
<div class="chat-container">
48+
<div class="messages-container" id="messagesContainer">
49+
<div class="welcome-message">
50+
<h1>AI Agent</h1>
51+
<p>How can I help you today?</p>
52+
</div>
53+
</div>
54+
55+
<div class="input-container">
56+
<div class="input-wrapper">
57+
<textarea
58+
id="messageInput"
59+
placeholder="Message AI Agent..."
60+
rows="1"
61+
maxlength="2000"
62+
></textarea>
63+
<button id="sendBtn" class="send-btn" disabled>
64+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
65+
<path d="M22 2L11 13" stroke="currentColor" stroke-width="2"/>
66+
<path d="M22 2L15 22L11 13L2 9L22 2Z" stroke="currentColor" stroke-width="2"/>
67+
</svg>
68+
</button>
69+
</div>
6570
</div>
6671
</div>
6772
</div>

0 commit comments

Comments
 (0)