From 8a4bf54fff7c70fcdcd62a639e94d008bfb65d50 Mon Sep 17 00:00:00 2001 From: Petr Mironychev <9195189+Palm1r@users.noreply.github.com> Date: Mon, 20 Oct 2025 19:16:00 +0200 Subject: [PATCH] feat: Improve tools guidelines --- ChatView/ClientInterface.cpp | 40 ++++++++++++++++++++++- tools/EditProjectFileTool.cpp | 58 ++++++++++++---------------------- tools/FindFileTool.cpp | 20 +++--------- tools/FindSymbolTool.cpp | 22 ++----------- tools/GetIssuesListTool.cpp | 6 ++-- tools/ListProjectFilesTool.cpp | 7 ++-- tools/ReadFileByPathTool.cpp | 8 ++--- tools/ReadVisibleFilesTool.cpp | 6 ++-- tools/SearchInProjectTool.cpp | 19 +++-------- 9 files changed, 79 insertions(+), 107 deletions(-) diff --git a/ChatView/ClientInterface.cpp b/ChatView/ClientInterface.cpp index 65d4715..8782fbd 100644 --- a/ChatView/ClientInterface.cpp +++ b/ChatView/ClientInterface.cpp @@ -83,16 +83,54 @@ void ClientInterface::sendMessage( LLMCore::ContextData context; + // Build system prompt with tools usage guidelines if (chatAssistantSettings.useSystemPrompt()) { QString systemPrompt = chatAssistantSettings.systemPrompt(); + // Add tools usage guidelines only if tools are enabled + if (Settings::generalSettings().useTools()) { + systemPrompt += "\n\n# Tool Usage Guidelines\n\n" + "You have access to powerful tools for project analysis and modification. " + "Use them proactively to provide accurate, context-aware assistance.\n\n" + "## Philosophy\n\n" + "- **Be Proactive**: Use tools when they help answer questions - don't ask permission first\n" + "- **Chain Tools**: Combine tools logically to gather complete context\n" + "- **Verify First**: Always read and understand code before proposing changes\n" + "- **Concrete Solutions**: Analyze and propose specific solutions, not just suggestions\n\n" + "## Discovery & Analysis\n\n" + "- Start with `list_project_files` or `find_file` to understand project structure\n" + "- Use `find_cpp_symbol` to locate classes, functions, enums, variables, namespaces\n" + "- Use `search_in_project` for text/pattern searches across files\n\n" + "## Reading Files\n\n" + "- `read_visible_files` - currently open editor tabs (no parameters)\n" + "- `read_project_file_by_path` - specific file by absolute path\n" + "- Always read files before proposing edits to understand context\n\n" + "## Making Changes\n\n" + "- `edit_project_file` - propose file modifications (requires user approval)\n" + "- Choose appropriate edit mode: replace, insert_before, insert_after, append\n" + "- For complex changes, use multiple sequential edits rather than one large edit\n\n" + "## Debugging\n\n" + "- `get_issues_list` - see compiler errors, warnings, and diagnostics\n" + "- Filter by severity: 'error', 'warning', or 'all'\n" + "- Use this when debugging to see actual problems\n\n" + "## Common Workflows\n\n" + "**Understanding codebase:**\n" + "list_project_files → find_cpp_symbol → read_project_file_by_path\n\n" + "**Fixing bugs:**\n" + "get_issues_list → read_project_file_by_path → edit_project_file\n\n" + "**Refactoring:**\n" + "search_in_project → read_project_file_by_path (multiple) → edit_project_file (multiple)\n\n" + "**Adding features:**\n" + "find_cpp_symbol → read_project_file_by_path → edit_project_file\n"; + } + auto project = LLMCore::RulesLoader::getActiveProject(); if (project) { QString projectRules = LLMCore::RulesLoader::loadRulesForProject(project, LLMCore::RulesContext::Chat); if (!projectRules.isEmpty()) { - systemPrompt += "\n\n# Project Rules\n\n" + projectRules; + systemPrompt += "\n# Project Rules\n\n" + projectRules; } } diff --git a/tools/EditProjectFileTool.cpp b/tools/EditProjectFileTool.cpp index 774f85b..b242314 100644 --- a/tools/EditProjectFileTool.cpp +++ b/tools/EditProjectFileTool.cpp @@ -53,42 +53,10 @@ QString EditProjectFileTool::stringName() const QString EditProjectFileTool::description() const { - return "Edit the content of a specific file in the current project. This tool proposes file " - "changes that will be shown to the user for approval.\n\n" - "**Edit Modes (choose the most precise mode for the change):**\n" - "1. 'replace' - Replace exact multi-line text blocks (use for substantial changes)\n" - "2. 'insert_before' - Insert new lines before a specific line number (preferred for " - "adding imports, comments, or new code)\n" - "3. 'insert_after' - Insert new lines after a specific line number (preferred for " - "adding code after existing lines)\n" - "4. 'append' - Append new content to the end of file\n\n" - "**Best Practices:**\n" - "- For single-line changes: use 'replace' mode with exact line content\n" - "- For adding new lines: prefer 'insert_before' or 'insert_after' over 'replace'\n" - "- For adding imports/includes: use 'insert_after' at the end of import section\n" - "- For multi-line refactoring: use 'replace' mode\n" - "- Keep search_text as small as possible while remaining unique\n\n" - "**Input Parameters:**\n" - "- 'filename' (required): Name or relative path of the file to edit\n" - "- 'mode' (required): Edit mode - 'replace', 'insert_before', 'insert_after', or " - "'append'\n" - "- 'search_text' (optional): Exact text to find (required for 'replace' mode)\n" - "- 'new_text' (required): New text to insert or use as replacement\n" - "- 'line_number' (optional): Line number for insert operations (required for " - "'insert_before' and 'insert_after' modes)\n\n" - "**Usage Examples:**\n" - "- Single line fix: {\"filename\": \"main.cpp\", \"mode\": \"replace\", " - "\"search_text\": \" Test test = new Test();\", \"new_text\": \" Test test;\"}\n" - "- Add import: {\"filename\": \"main.cpp\", \"mode\": \"insert_after\", " - "\"line_number\": 4, \"new_text\": \"#include \"}\n" - "- Add function: {\"filename\": \"main.cpp\", \"mode\": \"insert_before\", " - "\"line_number\": 20, \"new_text\": \"void helper() {\\n // code\\n}\\n\"}\n\n" - "**Important Notes:**\n" - "- Files excluded by .qodeassistignore cannot be edited\n" - "- Changes will be shown to user with diff for approval before applying\n" - "- For 'replace' mode, search_text must match exactly (including whitespace)\n" - "- Line numbers are 1-based\n" - "- User will see a visual diff and can approve or reject the change"; + return "Edit a project file using different modes: replace text, insert before/after line, or append. " + "Changes require user approval and show a diff preview. " + "Files excluded by .qodeassistignore cannot be edited. " + "Line numbers are 1-based."; } QJsonObject EditProjectFileTool::getDefinition(LLMCore::ToolSchemaFormat format) const @@ -344,12 +312,26 @@ void EditProjectFileTool::extractContext( int bestMatch = -1; int maxScore = -1; + QStringList searchLines = searchText.split('\n'); + for (int i = 0; i < lines.size(); ++i) { - if (lines[i].contains(searchText)) { + bool matches = true; + if (i + searchLines.size() > lines.size()) { + continue; + } + + for (int j = 0; j < searchLines.size(); ++j) { + if (lines[i + j] != searchLines[j]) { + matches = false; + break; + } + } + + if (matches) { int score = 0; for (int offset = 1; offset <= contextLines; ++offset) { if (i - offset >= 0) score++; - if (i + offset < lines.size()) score++; + if (i + searchLines.size() + offset - 1 < lines.size()) score++; } if (score > maxScore) { diff --git a/tools/FindFileTool.cpp b/tools/FindFileTool.cpp index 86f733c..1165477 100644 --- a/tools/FindFileTool.cpp +++ b/tools/FindFileTool.cpp @@ -47,22 +47,10 @@ QString FindFileTool::stringName() const QString FindFileTool::description() const { - return "Search for files in the current project by filename, partial filename, or path " - "(relative or absolute). " - "This tool searches for files within the project scope and supports:\n" - "- Exact filename match (e.g., 'main.cpp')\n" - "- Partial filename match (e.g., 'main' will find 'main.cpp', 'main.h', etc.)\n" - "- Relative path from project root (e.g., 'src/utils/helper.cpp')\n" - "- Partial path matching (e.g., 'utils/helper' will find matching paths)\n" - "- File extension filtering (e.g., '*.cpp', '*.h')\n" - "- Case-insensitive search\n" - "Input parameters:\n" - "- 'query' (required): the filename, partial name, or path to search for\n" - "- 'file_pattern' (optional): filter by file extension (e.g., '*.cpp', '*.h')\n" - "- 'max_results' (optional): maximum number of results to return (default: 50)\n" - "Returns a list of matching files with their absolute paths and relative paths from " - "project root, " - "or an error if no files are found or if the file is outside the project scope."; + return "Search for files in the project by filename, partial name, or path. " + "Supports exact/partial filename match, relative/absolute paths, file extension filtering, " + "and case-insensitive search. " + "Returns matching files with absolute and relative paths."; } QJsonObject FindFileTool::getDefinition(LLMCore::ToolSchemaFormat format) const diff --git a/tools/FindSymbolTool.cpp b/tools/FindSymbolTool.cpp index 3fe7d06..b30b2cb 100644 --- a/tools/FindSymbolTool.cpp +++ b/tools/FindSymbolTool.cpp @@ -55,25 +55,9 @@ QString FindSymbolTool::stringName() const QString FindSymbolTool::description() const { - return "Find C++ symbols (classes, functions, enums, variables, typedefs, namespaces) in the " - "current project. " - "Returns file paths, line numbers, qualified names, and optionally the source code of " - "found symbols. " - "Supports exact match, wildcard patterns, and regular expressions.\n" - "Input parameters:\n" - "- 'symbol_name' (required): Name or pattern of the symbol to find\n" - "- 'symbol_type' (optional): Type of symbol to search for: 'all', 'class', 'function', " - "'enum', 'variable', 'typedef', 'namespace'. Default is 'all'\n" - "- 'scope_filter' (optional): Filter results by scope (e.g., 'MyNamespace', " - "'MyClass'). Only symbols within this scope will be returned\n" - "- 'case_sensitive' (optional): Enable case-sensitive search. Default is true\n" - "- 'use_regex' (optional): Treat symbol_name as regular expression. Default is false\n" - "- 'use_wildcard' (optional): Treat symbol_name as wildcard pattern (e.g., 'find*', " - "'*Symbol', '*find*'). Default is false\n" - "- 'include_code' (optional): Whether to include the source code of found symbols. " - "Default is false\n" - "- 'max_results' (optional): Maximum number of results to return. Default is 10\n" - "- 'group_by' (optional): How to group results: 'type' (default), 'file', or 'scope'"; + return "Find C++ symbols (classes, functions, enums, variables, typedefs, namespaces) in the project. " + "Returns file paths, line numbers, qualified names, and optionally source code. " + "Supports exact match, wildcard patterns, and regular expressions."; } QJsonObject FindSymbolTool::getDefinition(LLMCore::ToolSchemaFormat format) const diff --git a/tools/GetIssuesListTool.cpp b/tools/GetIssuesListTool.cpp index 9487f0b..344ee0c 100644 --- a/tools/GetIssuesListTool.cpp +++ b/tools/GetIssuesListTool.cpp @@ -138,9 +138,9 @@ QString GetIssuesListTool::stringName() const QString GetIssuesListTool::description() const { - return "Get list of errors, warnings and other issues from Qt Creator's Issues panel. " - "Returns information about compilation errors, static analysis warnings, and other " - "diagnostic messages."; + return "Get compilation errors, warnings, and diagnostics from Qt Creator's Issues panel. " + "Filter by severity ('error', 'warning', or 'all'). " + "Returns issue descriptions with file paths and line numbers."; } QJsonObject GetIssuesListTool::getDefinition(LLMCore::ToolSchemaFormat format) const diff --git a/tools/ListProjectFilesTool.cpp b/tools/ListProjectFilesTool.cpp index c3df2f5..16e8c78 100644 --- a/tools/ListProjectFilesTool.cpp +++ b/tools/ListProjectFilesTool.cpp @@ -48,11 +48,8 @@ QString ListProjectFilesTool::stringName() const QString ListProjectFilesTool::description() const { - return "Get a list of all source files in the current project. " - "Returns a structured list of files with the absolute path to the project root " - "and relative paths for each file. " - "Useful for understanding project structure and finding specific files. " - "No parameters required."; + return "Get a list of all source files in the current project with absolute and relative paths. " + "Useful for understanding project structure. No parameters required."; } QJsonObject ListProjectFilesTool::getDefinition(LLMCore::ToolSchemaFormat format) const diff --git a/tools/ReadFileByPathTool.cpp b/tools/ReadFileByPathTool.cpp index eec5192..71c6169 100644 --- a/tools/ReadFileByPathTool.cpp +++ b/tools/ReadFileByPathTool.cpp @@ -51,12 +51,8 @@ QString ReadProjectFileByPathTool::stringName() const QString ReadProjectFileByPathTool::description() const { - return "Read the content of a specific file from the current project by providing its " - "absolute file path. " - "The file must exist, be within the project scope, and not excluded by " - ".qodeassistignore.\n" - "Input parameter: 'filepath' - the absolute path to the file (e.g., " - "'/path/to/project/src/main.cpp').\n"; + return "Read content of a specific project file by its absolute path. " + "File must exist, be within project scope, and not excluded by .qodeassistignore."; } QJsonObject ReadProjectFileByPathTool::getDefinition(LLMCore::ToolSchemaFormat format) const diff --git a/tools/ReadVisibleFilesTool.cpp b/tools/ReadVisibleFilesTool.cpp index ddb7220..d0b960f 100644 --- a/tools/ReadVisibleFilesTool.cpp +++ b/tools/ReadVisibleFilesTool.cpp @@ -46,10 +46,8 @@ QString ReadVisibleFilesTool::stringName() const QString ReadVisibleFilesTool::description() const { - return "Read the content of all currently visible files in editor tabs. " - "Returns content from all open tabs that are currently visible, including unsaved " - "changes. " - "No parameters required."; + return "Read content from all currently visible editor tabs, including unsaved changes. " + "Returns file paths and content. No parameters required."; } QJsonObject ReadVisibleFilesTool::getDefinition(LLMCore::ToolSchemaFormat format) const diff --git a/tools/SearchInProjectTool.cpp b/tools/SearchInProjectTool.cpp index 555010f..f76d9d4 100644 --- a/tools/SearchInProjectTool.cpp +++ b/tools/SearchInProjectTool.cpp @@ -50,21 +50,10 @@ QString SearchInProjectTool::stringName() const QString SearchInProjectTool::description() const { - return "Search for text or patterns across all project files. Supports:\n" - "- Plain text search (default)\n" - "- Regular expression patterns\n" - "- Case-sensitive/insensitive search\n" - "- Whole word matching\n" - "- File pattern filtering (e.g., '*.cpp', '*.h')\n" - "Returns matching lines with file paths, line numbers, and surrounding context.\n" - "Input parameters:\n" - "- 'query' (required): Text or regex pattern to search for\n" - "- 'case_sensitive' (optional): true for case-sensitive search, default is false\n" - "- 'use_regex' (optional): true to treat query as regex pattern, default is false\n" - "- 'whole_words' (optional): true to match whole words only, default is false\n" - "- 'file_pattern' (optional): Filter files by pattern (e.g., '*.cpp'), default is all " - "files\n" - "- 'max_results' (optional): Maximum number of results to return, default is 50"; + return "Search for text or patterns across all project files. " + "Returns matching lines with file paths, line numbers, and context. " + "Supports plain text, regex, case-sensitive/insensitive search, whole word matching, " + "and file pattern filtering."; } QJsonObject SearchInProjectTool::getDefinition(LLMCore::ToolSchemaFormat format) const