mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-05-30 02:49:12 -04:00
refactor: Separate and simplified tools (#340)
This commit is contained in:
@@ -151,7 +151,8 @@ add_qtc_plugin(QodeAssist
|
|||||||
tools/BuildProjectTool.hpp tools/BuildProjectTool.cpp
|
tools/BuildProjectTool.hpp tools/BuildProjectTool.cpp
|
||||||
tools/ExecuteTerminalCommandTool.hpp tools/ExecuteTerminalCommandTool.cpp
|
tools/ExecuteTerminalCommandTool.hpp tools/ExecuteTerminalCommandTool.cpp
|
||||||
tools/ProjectSearchTool.hpp tools/ProjectSearchTool.cpp
|
tools/ProjectSearchTool.hpp tools/ProjectSearchTool.cpp
|
||||||
tools/FindAndReadFileTool.hpp tools/FindAndReadFileTool.cpp
|
tools/FindFileTool.hpp tools/FindFileTool.cpp
|
||||||
|
tools/ReadFileTool.hpp tools/ReadFileTool.cpp
|
||||||
tools/FileSearchUtils.hpp tools/FileSearchUtils.cpp
|
tools/FileSearchUtils.hpp tools/FileSearchUtils.cpp
|
||||||
tools/TodoTool.hpp tools/TodoTool.cpp
|
tools/TodoTool.hpp tools/TodoTool.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -99,14 +99,17 @@ const char CA_ENABLE_CHAT_IN_BOTTOM_TOOLBAR[] = "QodeAssist.caEnableChatInBottom
|
|||||||
const char CA_ENABLE_CHAT_IN_NAVIGATION_PANEL[] = "QodeAssist.caEnableChatInNavigationPanel";
|
const char CA_ENABLE_CHAT_IN_NAVIGATION_PANEL[] = "QodeAssist.caEnableChatInNavigationPanel";
|
||||||
const char CA_ENABLE_CHAT_TOOLS[] = "QodeAssist.caEnableChatTools";
|
const char CA_ENABLE_CHAT_TOOLS[] = "QodeAssist.caEnableChatTools";
|
||||||
const char CA_USE_TOOLS[] = "QodeAssist.caUseTools";
|
const char CA_USE_TOOLS[] = "QodeAssist.caUseTools";
|
||||||
const char CA_ALLOW_FILE_SYSTEM_READ[] = "QodeAssist.caAllowFileSystemRead";
|
|
||||||
const char CA_ALLOW_FILE_SYSTEM_WRITE[] = "QodeAssist.caAllowFileSystemWrite";
|
|
||||||
const char CA_ALLOW_NETWORK_ACCESS[] = "QodeAssist.caAllowNetworkAccess";
|
|
||||||
const char CA_ALLOW_ACCESS_OUTSIDE_PROJECT[] = "QodeAssist.caAllowAccessOutsideProject";
|
const char CA_ALLOW_ACCESS_OUTSIDE_PROJECT[] = "QodeAssist.caAllowAccessOutsideProject";
|
||||||
const char CA_ENABLE_EDIT_FILE_TOOL[] = "QodeAssist.caEnableEditFileTool";
|
const char CA_ENABLE_LIST_PROJECT_FILES_TOOL[] = "QodeAssist.caEnableListProjectFilesTool";
|
||||||
const char CA_ENABLE_BUILD_PROJECT_TOOL[] = "QodeAssist.caEnableBuildProjectTool";
|
const char CA_ENABLE_FIND_FILE_TOOL[] = "QodeAssist.caEnableFindFileTool";
|
||||||
const char CA_ENABLE_TERMINAL_COMMAND_TOOL[] = "QodeAssist.caEnableTerminalCommandTool";
|
const char CA_ENABLE_READ_FILE_TOOL[] = "QodeAssist.caEnableReadFileTool";
|
||||||
const char CA_ENABLE_TODO_TOOL[] = "QodeAssist.caEnableTodoTool";
|
const char CA_ENABLE_PROJECT_SEARCH_TOOL[] = "QodeAssist.caEnableProjectSearchTool";
|
||||||
|
const char CA_ENABLE_CREATE_NEW_FILE_TOOL[] = "QodeAssist.caEnableCreateNewFileTool";
|
||||||
|
const char CA_ENABLE_GET_ISSUES_LIST_TOOL[] = "QodeAssist.caEnableGetIssuesListTool";
|
||||||
|
const char CA_ENABLE_EDIT_FILE_TOOL[] = "QodeAssist.caEnableEditFileToolV2";
|
||||||
|
const char CA_ENABLE_BUILD_PROJECT_TOOL[] = "QodeAssist.caEnableBuildProjectToolV2";
|
||||||
|
const char CA_ENABLE_TERMINAL_COMMAND_TOOL[] = "QodeAssist.caEnableTerminalCommandToolV2";
|
||||||
|
const char CA_ENABLE_TODO_TOOL[] = "QodeAssist.caEnableTodoToolV2";
|
||||||
const char CA_ALLOWED_TERMINAL_COMMANDS[] = "QodeAssist.caAllowedTerminalCommands";
|
const char CA_ALLOWED_TERMINAL_COMMANDS[] = "QodeAssist.caAllowedTerminalCommands";
|
||||||
const char CA_ALLOWED_TERMINAL_COMMANDS_LINUX[] = "QodeAssist.caAllowedTerminalCommandsLinux";
|
const char CA_ALLOWED_TERMINAL_COMMANDS_LINUX[] = "QodeAssist.caAllowedTerminalCommandsLinux";
|
||||||
const char CA_ALLOWED_TERMINAL_COMMANDS_MACOS[] = "QodeAssist.caAllowedTerminalCommandsMacOS";
|
const char CA_ALLOWED_TERMINAL_COMMANDS_MACOS[] = "QodeAssist.caAllowedTerminalCommandsMacOS";
|
||||||
|
|||||||
@@ -42,66 +42,80 @@ ToolsSettings::ToolsSettings()
|
|||||||
|
|
||||||
setDisplayName(Tr::tr("Tools"));
|
setDisplayName(Tr::tr("Tools"));
|
||||||
|
|
||||||
allowFileSystemRead.setSettingsKey(Constants::CA_ALLOW_FILE_SYSTEM_READ);
|
|
||||||
allowFileSystemRead.setLabelText(Tr::tr("Allow File System Read Access for tools"));
|
|
||||||
allowFileSystemRead.setToolTip(
|
|
||||||
Tr::tr("Allow tools to read files from disk (project files, open editors)"));
|
|
||||||
allowFileSystemRead.setDefaultValue(true);
|
|
||||||
|
|
||||||
allowFileSystemWrite.setSettingsKey(Constants::CA_ALLOW_FILE_SYSTEM_WRITE);
|
|
||||||
allowFileSystemWrite.setLabelText(Tr::tr("Allow File System Write Access for tools"));
|
|
||||||
allowFileSystemWrite.setToolTip(
|
|
||||||
Tr::tr("Allow tools to write and modify files on disk (WARNING: Use with caution!)"));
|
|
||||||
allowFileSystemWrite.setDefaultValue(false);
|
|
||||||
|
|
||||||
allowNetworkAccess.setSettingsKey(Constants::CA_ALLOW_NETWORK_ACCESS);
|
|
||||||
allowNetworkAccess.setLabelText(Tr::tr("Allow Network Access for tools"));
|
|
||||||
allowNetworkAccess.setToolTip(
|
|
||||||
Tr::tr("Allow tools to make network requests (e.g., execute commands like git, curl, wget). "
|
|
||||||
"Required for ExecuteTerminalCommandTool with network-capable commands."));
|
|
||||||
allowNetworkAccess.setDefaultValue(false);
|
|
||||||
|
|
||||||
allowAccessOutsideProject.setSettingsKey(Constants::CA_ALLOW_ACCESS_OUTSIDE_PROJECT);
|
allowAccessOutsideProject.setSettingsKey(Constants::CA_ALLOW_ACCESS_OUTSIDE_PROJECT);
|
||||||
allowAccessOutsideProject.setLabelText(Tr::tr("Allow file access outside project"));
|
allowAccessOutsideProject.setLabelText(Tr::tr("Allow file access outside project"));
|
||||||
allowAccessOutsideProject.setToolTip(
|
allowAccessOutsideProject.setToolTip(
|
||||||
Tr::tr("Allow tools to access (read/write) files outside the project scope (system "
|
Tr::tr("Allow tools to read, write, and create files outside the project scope "
|
||||||
"headers, Qt files, external libraries)"));
|
"(system headers, Qt files, external libraries)."));
|
||||||
allowAccessOutsideProject.setDefaultValue(true);
|
allowAccessOutsideProject.setDefaultValue(false);
|
||||||
|
|
||||||
autoApplyFileEdits.setSettingsKey(Constants::CA_AUTO_APPLY_FILE_EDITS);
|
autoApplyFileEdits.setSettingsKey(Constants::CA_AUTO_APPLY_FILE_EDITS);
|
||||||
autoApplyFileEdits.setLabelText(Tr::tr("Automatically apply file edits"));
|
autoApplyFileEdits.setLabelText(Tr::tr("Automatically apply file edits"));
|
||||||
autoApplyFileEdits.setToolTip(
|
autoApplyFileEdits.setToolTip(
|
||||||
Tr::tr("When enabled, file edits suggested by AI will be applied automatically. "
|
Tr::tr("When enabled, file edits suggested by AI are applied immediately. "
|
||||||
"When disabled, you will need to manually approve each edit."));
|
"When disabled, each edit is staged for manual approval."));
|
||||||
autoApplyFileEdits.setDefaultValue(false);
|
autoApplyFileEdits.setDefaultValue(false);
|
||||||
|
|
||||||
|
enableListProjectFilesTool.setSettingsKey(Constants::CA_ENABLE_LIST_PROJECT_FILES_TOOL);
|
||||||
|
enableListProjectFilesTool.setLabelText(Tr::tr("List Project Files"));
|
||||||
|
enableListProjectFilesTool.setToolTip(
|
||||||
|
Tr::tr("Lists every source file tracked by the active Qt Creator project(s)."));
|
||||||
|
enableListProjectFilesTool.setDefaultValue(true);
|
||||||
|
|
||||||
|
enableFindFileTool.setSettingsKey(Constants::CA_ENABLE_FIND_FILE_TOOL);
|
||||||
|
enableFindFileTool.setLabelText(Tr::tr("Find File"));
|
||||||
|
enableFindFileTool.setToolTip(
|
||||||
|
Tr::tr("Locates a file in the project by name or partial path. Returns paths only, "
|
||||||
|
"without file content."));
|
||||||
|
enableFindFileTool.setDefaultValue(true);
|
||||||
|
|
||||||
|
enableReadFileTool.setSettingsKey(Constants::CA_ENABLE_READ_FILE_TOOL);
|
||||||
|
enableReadFileTool.setLabelText(Tr::tr("Read File"));
|
||||||
|
enableReadFileTool.setToolTip(
|
||||||
|
Tr::tr("Reads the content of a file by absolute path or path relative to the project root."));
|
||||||
|
enableReadFileTool.setDefaultValue(true);
|
||||||
|
|
||||||
|
enableProjectSearchTool.setSettingsKey(Constants::CA_ENABLE_PROJECT_SEARCH_TOOL);
|
||||||
|
enableProjectSearchTool.setLabelText(Tr::tr("Search in Project"));
|
||||||
|
enableProjectSearchTool.setToolTip(
|
||||||
|
Tr::tr("Searches project files for text occurrences or C++ symbol definitions."));
|
||||||
|
enableProjectSearchTool.setDefaultValue(true);
|
||||||
|
|
||||||
|
enableCreateNewFileTool.setSettingsKey(Constants::CA_ENABLE_CREATE_NEW_FILE_TOOL);
|
||||||
|
enableCreateNewFileTool.setLabelText(Tr::tr("Create New File"));
|
||||||
|
enableCreateNewFileTool.setToolTip(
|
||||||
|
Tr::tr("Creates a new empty file at the given absolute path, making missing directories."));
|
||||||
|
enableCreateNewFileTool.setDefaultValue(true);
|
||||||
|
|
||||||
enableEditFileTool.setSettingsKey(Constants::CA_ENABLE_EDIT_FILE_TOOL);
|
enableEditFileTool.setSettingsKey(Constants::CA_ENABLE_EDIT_FILE_TOOL);
|
||||||
enableEditFileTool.setLabelText(Tr::tr("Enable Edit File Tool (Experimental)"));
|
enableEditFileTool.setLabelText(Tr::tr("Edit File"));
|
||||||
enableEditFileTool.setToolTip(
|
enableEditFileTool.setToolTip(
|
||||||
Tr::tr("Enable the experimental edit_file tool that allows AI to directly modify files. "
|
Tr::tr("Applies find-and-replace edits to files. See \"Automatically apply file edits\" "
|
||||||
"This feature is under testing and may have unexpected behavior."));
|
"to control whether edits apply immediately or wait for review."));
|
||||||
enableEditFileTool.setDefaultValue(false);
|
enableEditFileTool.setDefaultValue(true);
|
||||||
|
|
||||||
enableBuildProjectTool.setSettingsKey(Constants::CA_ENABLE_BUILD_PROJECT_TOOL);
|
enableBuildProjectTool.setSettingsKey(Constants::CA_ENABLE_BUILD_PROJECT_TOOL);
|
||||||
enableBuildProjectTool.setLabelText(Tr::tr("Enable Build Project Tool (Experimental)"));
|
enableBuildProjectTool.setLabelText(Tr::tr("Build Project"));
|
||||||
enableBuildProjectTool.setToolTip(
|
enableBuildProjectTool.setToolTip(
|
||||||
Tr::tr("Enable the experimental build_project tool that allows AI to build the current "
|
Tr::tr("Triggers a build of the active Qt Creator project and reports the result."));
|
||||||
"project. This feature is under testing and may have unexpected behavior."));
|
enableBuildProjectTool.setDefaultValue(true);
|
||||||
enableBuildProjectTool.setDefaultValue(false);
|
|
||||||
|
enableGetIssuesListTool.setSettingsKey(Constants::CA_ENABLE_GET_ISSUES_LIST_TOOL);
|
||||||
|
enableGetIssuesListTool.setLabelText(Tr::tr("Get Issues List"));
|
||||||
|
enableGetIssuesListTool.setToolTip(
|
||||||
|
Tr::tr("Reads compiler/clang diagnostics from Qt Creator's Issues panel."));
|
||||||
|
enableGetIssuesListTool.setDefaultValue(true);
|
||||||
|
|
||||||
enableTerminalCommandTool.setSettingsKey(Constants::CA_ENABLE_TERMINAL_COMMAND_TOOL);
|
enableTerminalCommandTool.setSettingsKey(Constants::CA_ENABLE_TERMINAL_COMMAND_TOOL);
|
||||||
enableTerminalCommandTool.setLabelText(Tr::tr("Enable Terminal Command Tool (Experimental)"));
|
enableTerminalCommandTool.setLabelText(Tr::tr("Execute Terminal Command"));
|
||||||
enableTerminalCommandTool.setToolTip(
|
enableTerminalCommandTool.setToolTip(
|
||||||
Tr::tr("Enable the experimental execute_terminal_command tool that allows AI to execute "
|
Tr::tr("Runs a command from the OS-specific allowed list below, in the project directory."));
|
||||||
"terminal commands from the allowed list. This feature is under testing and may have "
|
enableTerminalCommandTool.setDefaultValue(true);
|
||||||
"unexpected behavior."));
|
|
||||||
enableTerminalCommandTool.setDefaultValue(false);
|
|
||||||
|
|
||||||
enableTodoTool.setSettingsKey(Constants::CA_ENABLE_TODO_TOOL);
|
enableTodoTool.setSettingsKey(Constants::CA_ENABLE_TODO_TOOL);
|
||||||
enableTodoTool.setLabelText(Tr::tr("Enable Todo Tool"));
|
enableTodoTool.setLabelText(Tr::tr("Todo"));
|
||||||
enableTodoTool.setToolTip(
|
enableTodoTool.setToolTip(
|
||||||
Tr::tr("Enable the todo_tool that helps AI track and organize multi-step tasks. "
|
Tr::tr("Lets the AI maintain a session-scoped todo list for multi-step workflows."));
|
||||||
"Useful for complex refactoring, debugging, and feature implementation workflows."));
|
|
||||||
enableTodoTool.setDefaultValue(true);
|
enableTodoTool.setDefaultValue(true);
|
||||||
|
|
||||||
allowedTerminalCommandsLinux.setSettingsKey(Constants::CA_ALLOWED_TERMINAL_COMMANDS_LINUX);
|
allowedTerminalCommandsLinux.setSettingsKey(Constants::CA_ALLOWED_TERMINAL_COMMANDS_LINUX);
|
||||||
@@ -159,24 +173,30 @@ ToolsSettings::ToolsSettings()
|
|||||||
Row{Stretch{1}, resetToDefaults},
|
Row{Stretch{1}, resetToDefaults},
|
||||||
Space{8},
|
Space{8},
|
||||||
Group{
|
Group{
|
||||||
title(Tr::tr("Tool Settings")),
|
title(Tr::tr("Tools")),
|
||||||
Column{
|
|
||||||
allowFileSystemRead,
|
|
||||||
allowFileSystemWrite,
|
|
||||||
allowNetworkAccess,
|
|
||||||
allowAccessOutsideProject
|
|
||||||
}},
|
|
||||||
Space{8},
|
|
||||||
Group{
|
|
||||||
title(Tr::tr("Experimental Features")),
|
|
||||||
Column{
|
Column{
|
||||||
|
enableListProjectFilesTool,
|
||||||
|
enableFindFileTool,
|
||||||
|
enableReadFileTool,
|
||||||
|
enableProjectSearchTool,
|
||||||
|
enableCreateNewFileTool,
|
||||||
enableEditFileTool,
|
enableEditFileTool,
|
||||||
enableBuildProjectTool,
|
enableBuildProjectTool,
|
||||||
|
enableGetIssuesListTool,
|
||||||
enableTerminalCommandTool,
|
enableTerminalCommandTool,
|
||||||
enableTodoTool,
|
enableTodoTool}},
|
||||||
currentOsCommands,
|
Space{8},
|
||||||
terminalCommandTimeout,
|
Group{
|
||||||
autoApplyFileEdits}},
|
title(Tr::tr("Tool Settings")),
|
||||||
|
Column{
|
||||||
|
allowAccessOutsideProject,
|
||||||
|
Space{4},
|
||||||
|
Group{
|
||||||
|
title(Tr::tr("Edit File")),
|
||||||
|
Column{autoApplyFileEdits}},
|
||||||
|
Group{
|
||||||
|
title(Tr::tr("Execute Terminal Command")),
|
||||||
|
Column{currentOsCommands, terminalCommandTimeout}}}},
|
||||||
Stretch{1}};
|
Stretch{1}};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -200,13 +220,16 @@ void ToolsSettings::resetSettingsToDefaults()
|
|||||||
QMessageBox::Yes | QMessageBox::No);
|
QMessageBox::Yes | QMessageBox::No);
|
||||||
|
|
||||||
if (reply == QMessageBox::Yes) {
|
if (reply == QMessageBox::Yes) {
|
||||||
resetAspect(allowFileSystemRead);
|
|
||||||
resetAspect(allowFileSystemWrite);
|
|
||||||
resetAspect(allowNetworkAccess);
|
|
||||||
resetAspect(allowAccessOutsideProject);
|
resetAspect(allowAccessOutsideProject);
|
||||||
resetAspect(autoApplyFileEdits);
|
resetAspect(autoApplyFileEdits);
|
||||||
|
resetAspect(enableListProjectFilesTool);
|
||||||
|
resetAspect(enableFindFileTool);
|
||||||
|
resetAspect(enableReadFileTool);
|
||||||
|
resetAspect(enableProjectSearchTool);
|
||||||
|
resetAspect(enableCreateNewFileTool);
|
||||||
resetAspect(enableEditFileTool);
|
resetAspect(enableEditFileTool);
|
||||||
resetAspect(enableBuildProjectTool);
|
resetAspect(enableBuildProjectTool);
|
||||||
|
resetAspect(enableGetIssuesListTool);
|
||||||
resetAspect(enableTerminalCommandTool);
|
resetAspect(enableTerminalCommandTool);
|
||||||
resetAspect(enableTodoTool);
|
resetAspect(enableTodoTool);
|
||||||
resetAspect(allowedTerminalCommandsLinux);
|
resetAspect(allowedTerminalCommandsLinux);
|
||||||
|
|||||||
@@ -32,21 +32,24 @@ public:
|
|||||||
|
|
||||||
ButtonAspect resetToDefaults{this};
|
ButtonAspect resetToDefaults{this};
|
||||||
|
|
||||||
Utils::BoolAspect allowFileSystemRead{this};
|
|
||||||
Utils::BoolAspect allowFileSystemWrite{this};
|
|
||||||
Utils::BoolAspect allowNetworkAccess{this};
|
|
||||||
Utils::BoolAspect allowAccessOutsideProject{this};
|
Utils::BoolAspect allowAccessOutsideProject{this};
|
||||||
|
Utils::BoolAspect autoApplyFileEdits{this};
|
||||||
|
|
||||||
// Experimental features
|
Utils::BoolAspect enableListProjectFilesTool{this};
|
||||||
|
Utils::BoolAspect enableFindFileTool{this};
|
||||||
|
Utils::BoolAspect enableReadFileTool{this};
|
||||||
|
Utils::BoolAspect enableProjectSearchTool{this};
|
||||||
|
Utils::BoolAspect enableCreateNewFileTool{this};
|
||||||
Utils::BoolAspect enableEditFileTool{this};
|
Utils::BoolAspect enableEditFileTool{this};
|
||||||
Utils::BoolAspect enableBuildProjectTool{this};
|
Utils::BoolAspect enableBuildProjectTool{this};
|
||||||
|
Utils::BoolAspect enableGetIssuesListTool{this};
|
||||||
Utils::BoolAspect enableTerminalCommandTool{this};
|
Utils::BoolAspect enableTerminalCommandTool{this};
|
||||||
Utils::BoolAspect enableTodoTool{this};
|
Utils::BoolAspect enableTodoTool{this};
|
||||||
|
|
||||||
Utils::StringAspect allowedTerminalCommandsLinux{this};
|
Utils::StringAspect allowedTerminalCommandsLinux{this};
|
||||||
Utils::StringAspect allowedTerminalCommandsMacOS{this};
|
Utils::StringAspect allowedTerminalCommandsMacOS{this};
|
||||||
Utils::StringAspect allowedTerminalCommandsWindows{this};
|
Utils::StringAspect allowedTerminalCommandsWindows{this};
|
||||||
Utils::IntegerAspect terminalCommandTimeout{this};
|
Utils::IntegerAspect terminalCommandTimeout{this};
|
||||||
Utils::BoolAspect autoApplyFileEdits{this};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupConnections();
|
void setupConnections();
|
||||||
|
|||||||
@@ -71,13 +71,10 @@ QString BuildProjectTool::displayName() const
|
|||||||
|
|
||||||
QString BuildProjectTool::description() const
|
QString BuildProjectTool::description() const
|
||||||
{
|
{
|
||||||
return "Build the current project in Qt Creator and wait for completion. "
|
return "Build the active Qt Creator project using its current build configuration and block "
|
||||||
"Optionally run the project after successful build. "
|
"until the build finishes. Returns success/failure along with the full compiler output "
|
||||||
"Returns build status (success/failure) and any compilation errors/warnings after "
|
"(stdout + stderr). Use `get_issues_list` afterwards to get structured diagnostics. "
|
||||||
"the build finishes. "
|
"This call is blocking and may take a long time for large projects.";
|
||||||
"Optional 'rebuild' parameter: set to true to force a clean rebuild (default: false). "
|
|
||||||
"Optional 'run_after_build' parameter: set to true to run the project after successful build (default: false). "
|
|
||||||
"Note: This operation may take some time depending on project size.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject BuildProjectTool::parametersSchema() const
|
QJsonObject BuildProjectTool::parametersSchema() const
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ QString CreateNewFileTool::displayName() const
|
|||||||
|
|
||||||
QString CreateNewFileTool::description() const
|
QString CreateNewFileTool::description() const
|
||||||
{
|
{
|
||||||
return "Create a new empty file at the specified path. "
|
return "Create a new empty file at the given absolute path. Any missing parent directories "
|
||||||
"If the directory path does not exist, it will be created automatically. "
|
"are created automatically. The file is written to disk only — it is NOT added to the "
|
||||||
"Provide absolute file path. After creating files, add the file "
|
"project's build system automatically; the user must register it in CMakeLists.txt or "
|
||||||
"to the project file";
|
"the equivalent project file. Use `edit_file` afterwards to populate its content.";
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject CreateNewFileTool::parametersSchema() const
|
QJsonObject CreateNewFileTool::parametersSchema() const
|
||||||
@@ -61,7 +61,9 @@ QJsonObject CreateNewFileTool::parametersSchema() const
|
|||||||
|
|
||||||
QJsonObject filepathProperty;
|
QJsonObject filepathProperty;
|
||||||
filepathProperty["type"] = "string";
|
filepathProperty["type"] = "string";
|
||||||
filepathProperty["description"] = "The absolute path where the new file should be created";
|
filepathProperty["description"]
|
||||||
|
= "Absolute path where the new file should be created. Parent directories are made if "
|
||||||
|
"missing. Relative paths are rejected.";
|
||||||
properties["filepath"] = filepathProperty;
|
properties["filepath"] = filepathProperty;
|
||||||
|
|
||||||
QJsonObject definition;
|
QJsonObject definition;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ QString EditFileTool::description() const
|
|||||||
"and new_content to replace it with. Changes are applied immediately if auto-apply "
|
"and new_content to replace it with. Changes are applied immediately if auto-apply "
|
||||||
"is enabled in settings. The user can undo or reapply changes at any time. "
|
"is enabled in settings. The user can undo or reapply changes at any time. "
|
||||||
"\n\nIMPORTANT:"
|
"\n\nIMPORTANT:"
|
||||||
"\n- ALWAYS read the current file content before editing to ensure accuracy."
|
"\n- ALWAYS use read_file to get current file content before editing to ensure accuracy."
|
||||||
"\n- Path can be absolute (e.g., /path/to/file.cpp) or relative to project root (e.g., src/main.cpp)."
|
"\n- Path can be absolute (e.g., /path/to/file.cpp) or relative to project root (e.g., src/main.cpp)."
|
||||||
"\n- For EMPTY files: use empty old_content (empty string or omit parameter)."
|
"\n- For EMPTY files: use empty old_content (empty string or omit parameter)."
|
||||||
"\n- To append at the END of file: use empty old_content."
|
"\n- To append at the END of file: use empty old_content."
|
||||||
|
|||||||
@@ -1,125 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2025 Petr Mironychev
|
|
||||||
*
|
|
||||||
* This file is part of QodeAssist.
|
|
||||||
*
|
|
||||||
* QodeAssist is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* QodeAssist is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with QodeAssist. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "FindAndReadFileTool.hpp"
|
|
||||||
|
|
||||||
#include <LLMQore/ToolExceptions.hpp>
|
|
||||||
|
|
||||||
#include <logger/Logger.hpp>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QtConcurrent>
|
|
||||||
|
|
||||||
namespace QodeAssist::Tools {
|
|
||||||
|
|
||||||
FindAndReadFileTool::FindAndReadFileTool(QObject *parent)
|
|
||||||
: BaseTool(parent)
|
|
||||||
, m_ignoreManager(new Context::IgnoreManager(this))
|
|
||||||
{}
|
|
||||||
|
|
||||||
QString FindAndReadFileTool::id() const
|
|
||||||
{
|
|
||||||
return "find_and_read_file";
|
|
||||||
}
|
|
||||||
|
|
||||||
QString FindAndReadFileTool::displayName() const
|
|
||||||
{
|
|
||||||
return "Finding and reading file";
|
|
||||||
}
|
|
||||||
|
|
||||||
QString FindAndReadFileTool::description() const
|
|
||||||
{
|
|
||||||
return "Search for a file by name/path and optionally read its content. "
|
|
||||||
"Returns the best matching file and its content.";
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject FindAndReadFileTool::parametersSchema() const
|
|
||||||
{
|
|
||||||
QJsonObject properties;
|
|
||||||
|
|
||||||
properties["query"] = QJsonObject{
|
|
||||||
{"type", "string"},
|
|
||||||
{"description", "Filename, partial name, or path to search for (case-insensitive)"}};
|
|
||||||
|
|
||||||
properties["file_pattern"] = QJsonObject{
|
|
||||||
{"type", "string"}, {"description", "File pattern filter (e.g., '*.cpp', '*.h', '*.qml')"}};
|
|
||||||
|
|
||||||
properties["read_content"] = QJsonObject{
|
|
||||||
{"type", "boolean"},
|
|
||||||
{"description", "Read file content in addition to finding path (default: true)"}};
|
|
||||||
|
|
||||||
QJsonObject definition;
|
|
||||||
definition["type"] = "object";
|
|
||||||
definition["properties"] = properties;
|
|
||||||
definition["required"] = QJsonArray{"query"};
|
|
||||||
|
|
||||||
return definition;
|
|
||||||
}
|
|
||||||
|
|
||||||
QFuture<LLMQore::ToolResult> FindAndReadFileTool::executeAsync(const QJsonObject &input)
|
|
||||||
{
|
|
||||||
return QtConcurrent::run([this, input]() -> LLMQore::ToolResult {
|
|
||||||
QString query = input["query"].toString().trimmed();
|
|
||||||
if (query.isEmpty()) {
|
|
||||||
throw LLMQore::ToolInvalidArgument("Query parameter is required");
|
|
||||||
}
|
|
||||||
|
|
||||||
QString filePattern = input["file_pattern"].toString();
|
|
||||||
bool readContent = input["read_content"].toBool(true);
|
|
||||||
|
|
||||||
LOG_MESSAGE(QString("FindAndReadFileTool: Searching for '%1' (pattern: %2, read: %3)")
|
|
||||||
.arg(query, filePattern.isEmpty() ? "none" : filePattern)
|
|
||||||
.arg(readContent));
|
|
||||||
|
|
||||||
FileSearchUtils::FileMatch bestMatch = FileSearchUtils::findBestMatch(
|
|
||||||
query, filePattern, 10, m_ignoreManager);
|
|
||||||
|
|
||||||
if (bestMatch.absolutePath.isEmpty()) {
|
|
||||||
return LLMQore::ToolResult::text(QString("No file found matching '%1'").arg(query));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (readContent) {
|
|
||||||
bestMatch.content = FileSearchUtils::readFileContent(bestMatch.absolutePath);
|
|
||||||
if (bestMatch.content.isNull()) {
|
|
||||||
bestMatch.error = "Could not read file";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return LLMQore::ToolResult::text(formatResult(bestMatch, readContent));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QString FindAndReadFileTool::formatResult(const FileSearchUtils::FileMatch &match,
|
|
||||||
bool readContent) const
|
|
||||||
{
|
|
||||||
QString result
|
|
||||||
= QString("Found file: %1\nAbsolute path: %2").arg(match.relativePath, match.absolutePath);
|
|
||||||
|
|
||||||
if (readContent) {
|
|
||||||
if (!match.error.isEmpty()) {
|
|
||||||
result += QString("\nError: %1").arg(match.error);
|
|
||||||
} else {
|
|
||||||
result += QString("\n\n=== Content ===\n%1").arg(match.content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace QodeAssist::Tools
|
|
||||||
108
tools/FindFileTool.cpp
Normal file
108
tools/FindFileTool.cpp
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2026 Petr Mironychev
|
||||||
|
*
|
||||||
|
* This file is part of QodeAssist.
|
||||||
|
*
|
||||||
|
* QodeAssist is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* QodeAssist is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with QodeAssist. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FindFileTool.hpp"
|
||||||
|
|
||||||
|
#include "FileSearchUtils.hpp"
|
||||||
|
|
||||||
|
#include <LLMQore/ToolExceptions.hpp>
|
||||||
|
|
||||||
|
#include <logger/Logger.hpp>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QtConcurrent>
|
||||||
|
|
||||||
|
namespace QodeAssist::Tools {
|
||||||
|
|
||||||
|
FindFileTool::FindFileTool(QObject *parent)
|
||||||
|
: BaseTool(parent)
|
||||||
|
, m_ignoreManager(new Context::IgnoreManager(this))
|
||||||
|
{}
|
||||||
|
|
||||||
|
QString FindFileTool::id() const
|
||||||
|
{
|
||||||
|
return "find_file";
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FindFileTool::displayName() const
|
||||||
|
{
|
||||||
|
return "Finding file";
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FindFileTool::description() const
|
||||||
|
{
|
||||||
|
return "Find a file in the current project(s) by name or partial path. "
|
||||||
|
"Returns the absolute path, project-relative path, and the name of the project "
|
||||||
|
"that contains the match. Does NOT read file content — use `read_file` separately "
|
||||||
|
"when you need the content. Use this when you know part of the filename but not "
|
||||||
|
"the exact location.";
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject FindFileTool::parametersSchema() const
|
||||||
|
{
|
||||||
|
QJsonObject properties;
|
||||||
|
|
||||||
|
properties["query"] = QJsonObject{
|
||||||
|
{"type", "string"},
|
||||||
|
{"description",
|
||||||
|
"Filename, partial filename, or partial path to look for. Case-insensitive. "
|
||||||
|
"Exact filename matches rank highest, then path matches, then partial name matches."}};
|
||||||
|
|
||||||
|
properties["file_pattern"] = QJsonObject{
|
||||||
|
{"type", "string"},
|
||||||
|
{"description",
|
||||||
|
"Optional wildcard filter applied to the filename. Examples: '*.cpp', '*.h', '*.qml'. "
|
||||||
|
"Leave empty to match any extension."}};
|
||||||
|
|
||||||
|
QJsonObject definition;
|
||||||
|
definition["type"] = "object";
|
||||||
|
definition["properties"] = properties;
|
||||||
|
definition["required"] = QJsonArray{"query"};
|
||||||
|
|
||||||
|
return definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFuture<LLMQore::ToolResult> FindFileTool::executeAsync(const QJsonObject &input)
|
||||||
|
{
|
||||||
|
return QtConcurrent::run([this, input]() -> LLMQore::ToolResult {
|
||||||
|
QString query = input["query"].toString().trimmed();
|
||||||
|
if (query.isEmpty()) {
|
||||||
|
throw LLMQore::ToolInvalidArgument("'query' parameter is required and cannot be empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString filePattern = input["file_pattern"].toString();
|
||||||
|
|
||||||
|
LOG_MESSAGE(QString("FindFileTool: Searching for '%1' (pattern: %2)")
|
||||||
|
.arg(query, filePattern.isEmpty() ? "none" : filePattern));
|
||||||
|
|
||||||
|
FileSearchUtils::FileMatch match
|
||||||
|
= FileSearchUtils::findBestMatch(query, filePattern, 10, m_ignoreManager);
|
||||||
|
|
||||||
|
if (match.absolutePath.isEmpty()) {
|
||||||
|
return LLMQore::ToolResult::text(QString("No file found matching '%1'").arg(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString result = QString("Found file: %1\nAbsolute path: %2\nProject: %3")
|
||||||
|
.arg(match.relativePath, match.absolutePath, match.projectName);
|
||||||
|
|
||||||
|
return LLMQore::ToolResult::text(result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QodeAssist::Tools
|
||||||
@@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "FileSearchUtils.hpp"
|
|
||||||
|
|
||||||
#include <context/IgnoreManager.hpp>
|
#include <context/IgnoreManager.hpp>
|
||||||
#include <LLMQore/BaseTool.hpp>
|
#include <LLMQore/BaseTool.hpp>
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
@@ -29,12 +27,12 @@
|
|||||||
|
|
||||||
namespace QodeAssist::Tools {
|
namespace QodeAssist::Tools {
|
||||||
|
|
||||||
class FindAndReadFileTool : public ::LLMQore::BaseTool
|
class FindFileTool : public ::LLMQore::BaseTool
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FindAndReadFileTool(QObject *parent = nullptr);
|
explicit FindFileTool(QObject *parent = nullptr);
|
||||||
|
|
||||||
QString id() const override;
|
QString id() const override;
|
||||||
QString displayName() const override;
|
QString displayName() const override;
|
||||||
@@ -43,8 +41,6 @@ public:
|
|||||||
QFuture<LLMQore::ToolResult> executeAsync(const QJsonObject &input) override;
|
QFuture<LLMQore::ToolResult> executeAsync(const QJsonObject &input) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString formatResult(const FileSearchUtils::FileMatch &match, bool readContent) const;
|
|
||||||
|
|
||||||
Context::IgnoreManager *m_ignoreManager;
|
Context::IgnoreManager *m_ignoreManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -133,9 +133,10 @@ QString GetIssuesListTool::displayName() const
|
|||||||
|
|
||||||
QString GetIssuesListTool::description() const
|
QString GetIssuesListTool::description() const
|
||||||
{
|
{
|
||||||
return "Get compilation errors, warnings, and diagnostics from Qt Creator's Issues panel. "
|
return "Read diagnostics from Qt Creator's Issues panel, including the latest build output and "
|
||||||
"Returns issue descriptions with file paths and line numbers. "
|
"live clang-codemodel warnings/errors for open files. Each issue includes file path, "
|
||||||
"Optional severity filter: 'error', 'warning', or 'all' (default).";
|
"line number, severity, and message. Run `build_project` first if you need fresh build "
|
||||||
|
"diagnostics.";
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject GetIssuesListTool::parametersSchema() const
|
QJsonObject GetIssuesListTool::parametersSchema() const
|
||||||
|
|||||||
@@ -50,8 +50,10 @@ QString ListProjectFilesTool::displayName() const
|
|||||||
|
|
||||||
QString ListProjectFilesTool::description() const
|
QString ListProjectFilesTool::description() const
|
||||||
{
|
{
|
||||||
return "Get a list of all source files in the current project with absolute and relative paths. "
|
return "List every source file tracked by the active Qt Creator project(s), filtered by "
|
||||||
"Useful for understanding project structure. No parameters required.";
|
".qodeassistignore. Returns absolute and project-relative paths grouped by project. "
|
||||||
|
"Useful for discovering the project layout before running focused searches or reads. "
|
||||||
|
"Takes no parameters.";
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject ListProjectFilesTool::parametersSchema() const
|
QJsonObject ListProjectFilesTool::parametersSchema() const
|
||||||
|
|||||||
@@ -56,39 +56,50 @@ QString ProjectSearchTool::displayName() const
|
|||||||
|
|
||||||
QString ProjectSearchTool::description() const
|
QString ProjectSearchTool::description() const
|
||||||
{
|
{
|
||||||
return "Search project for text content or C++ symbols. "
|
return "Search across all open Qt Creator project(s) for text occurrences or C++ symbol "
|
||||||
"Text mode: finds text patterns in files. "
|
"definitions. 'text' mode scans source files line-by-line for literal text or regex. "
|
||||||
"Symbol mode: finds C++ definitions (classes, functions, etc).";
|
"'symbol' mode uses Qt Creator's C++ code model and works only for C++ "
|
||||||
|
"(not QML, Python, or plain text). Respects .qodeassistignore. "
|
||||||
|
"Use `find_file` for locating files by name, not this tool.";
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject ProjectSearchTool::parametersSchema() const
|
QJsonObject ProjectSearchTool::parametersSchema() const
|
||||||
{
|
{
|
||||||
QJsonObject properties;
|
QJsonObject properties;
|
||||||
|
|
||||||
properties["query"]
|
properties["query"] = QJsonObject{
|
||||||
= QJsonObject{{"type", "string"}, {"description", "Text or symbol name to search for"}};
|
{"type", "string"},
|
||||||
|
{"description", "Text string or symbol name to search for. In text mode with "
|
||||||
|
"use_regex=true, this is a regular expression."}};
|
||||||
|
|
||||||
properties["search_type"] = QJsonObject{
|
properties["search_type"] = QJsonObject{
|
||||||
{"type", "string"},
|
{"type", "string"},
|
||||||
{"enum", QJsonArray{"text", "symbol"}},
|
{"enum", QJsonArray{"text", "symbol"}},
|
||||||
{"description", "Search mode: 'text' for content, 'symbol' for C++ definitions"}};
|
{"description", "Search mode: 'text' scans file contents, 'symbol' looks up C++ "
|
||||||
|
"declarations via the code model."}};
|
||||||
|
|
||||||
properties["symbol_type"] = QJsonObject{
|
properties["symbol_type"] = QJsonObject{
|
||||||
{"type", "string"},
|
{"type", "string"},
|
||||||
{"enum", QJsonArray{"all", "class", "function", "enum", "variable", "namespace"}},
|
{"enum", QJsonArray{"all", "class", "function", "enum", "variable", "namespace"}},
|
||||||
{"description", "Symbol type filter (symbol mode only)"}};
|
{"description", "Filter for symbol mode. Default: 'all'. Ignored in text mode."}};
|
||||||
|
|
||||||
properties["case_sensitive"]
|
properties["case_sensitive"] = QJsonObject{
|
||||||
= QJsonObject{{"type", "boolean"}, {"description", "Case-sensitive search"}};
|
{"type", "boolean"},
|
||||||
|
{"description", "Case-sensitive matching. Default: false."}};
|
||||||
|
|
||||||
properties["use_regex"]
|
properties["use_regex"] = QJsonObject{
|
||||||
= QJsonObject{{"type", "boolean"}, {"description", "Use regex patterns"}};
|
{"type", "boolean"},
|
||||||
|
{"description", "Treat the query as a regular expression. Default: false."}};
|
||||||
|
|
||||||
properties["whole_words"]
|
properties["whole_words"] = QJsonObject{
|
||||||
= QJsonObject{{"type", "boolean"}, {"description", "Match whole words only (text mode)"}};
|
{"type", "boolean"},
|
||||||
|
{"description", "Match whole words only. Text mode only; ignored in symbol mode. "
|
||||||
|
"Default: false."}};
|
||||||
|
|
||||||
properties["file_pattern"] = QJsonObject{
|
properties["file_pattern"] = QJsonObject{
|
||||||
{"type", "string"}, {"description", "File filter pattern (e.g., '*.cpp', '*.h')"}};
|
{"type", "string"},
|
||||||
|
{"description", "Wildcard to restrict which files are searched in text mode, e.g. "
|
||||||
|
"'*.cpp' or '*.h'. Default: all files."}};
|
||||||
|
|
||||||
QJsonObject definition;
|
QJsonObject definition;
|
||||||
definition["type"] = "object";
|
definition["type"] = "object";
|
||||||
|
|||||||
122
tools/ReadFileTool.cpp
Normal file
122
tools/ReadFileTool.cpp
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2026 Petr Mironychev
|
||||||
|
*
|
||||||
|
* This file is part of QodeAssist.
|
||||||
|
*
|
||||||
|
* QodeAssist is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* QodeAssist is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with QodeAssist. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ReadFileTool.hpp"
|
||||||
|
|
||||||
|
#include "FileSearchUtils.hpp"
|
||||||
|
|
||||||
|
#include <LLMQore/ToolExceptions.hpp>
|
||||||
|
|
||||||
|
#include <context/ProjectUtils.hpp>
|
||||||
|
#include <logger/Logger.hpp>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QtConcurrent>
|
||||||
|
|
||||||
|
namespace QodeAssist::Tools {
|
||||||
|
|
||||||
|
ReadFileTool::ReadFileTool(QObject *parent)
|
||||||
|
: BaseTool(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
QString ReadFileTool::id() const
|
||||||
|
{
|
||||||
|
return "read_file";
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ReadFileTool::displayName() const
|
||||||
|
{
|
||||||
|
return "Reading file";
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ReadFileTool::description() const
|
||||||
|
{
|
||||||
|
return "Read the text content of a file. Accepts either an absolute path or a path "
|
||||||
|
"relative to the project root. Reading files outside the active project requires "
|
||||||
|
"the 'Allow file access outside project' option in settings. Use `find_file` first "
|
||||||
|
"if you only know a partial filename.";
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject ReadFileTool::parametersSchema() const
|
||||||
|
{
|
||||||
|
QJsonObject properties;
|
||||||
|
|
||||||
|
properties["file_path"] = QJsonObject{
|
||||||
|
{"type", "string"},
|
||||||
|
{"description",
|
||||||
|
"Absolute path (e.g. /path/to/file.cpp) or project-relative path (e.g. src/main.cpp). "
|
||||||
|
"Relative paths are resolved against the root of the active project."}};
|
||||||
|
|
||||||
|
QJsonObject definition;
|
||||||
|
definition["type"] = "object";
|
||||||
|
definition["properties"] = properties;
|
||||||
|
definition["required"] = QJsonArray{"file_path"};
|
||||||
|
|
||||||
|
return definition;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFuture<LLMQore::ToolResult> ReadFileTool::executeAsync(const QJsonObject &input)
|
||||||
|
{
|
||||||
|
return QtConcurrent::run([input]() -> LLMQore::ToolResult {
|
||||||
|
QString rawPath = input["file_path"].toString().trimmed();
|
||||||
|
if (rawPath.isEmpty()) {
|
||||||
|
throw LLMQore::ToolInvalidArgument(
|
||||||
|
"'file_path' parameter is required and cannot be empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileInfo pathInfo(rawPath);
|
||||||
|
QString absolutePath;
|
||||||
|
if (pathInfo.isAbsolute()) {
|
||||||
|
absolutePath = rawPath;
|
||||||
|
} else {
|
||||||
|
QString projectRoot = Context::ProjectUtils::getProjectRoot();
|
||||||
|
if (projectRoot.isEmpty()) {
|
||||||
|
throw LLMQore::ToolRuntimeError(
|
||||||
|
QString("Cannot resolve relative path '%1': no project is open. "
|
||||||
|
"Provide an absolute path or open a project.")
|
||||||
|
.arg(rawPath));
|
||||||
|
}
|
||||||
|
absolutePath = QDir(projectRoot).absoluteFilePath(rawPath);
|
||||||
|
LOG_MESSAGE(QString("ReadFileTool: Resolved relative path '%1' to '%2'")
|
||||||
|
.arg(rawPath, absolutePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileInfo finalInfo(absolutePath);
|
||||||
|
if (!finalInfo.exists() || !finalInfo.isFile()) {
|
||||||
|
throw LLMQore::ToolRuntimeError(QString("File does not exist: %1").arg(absolutePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString content = FileSearchUtils::readFileContent(absolutePath);
|
||||||
|
if (content.isNull()) {
|
||||||
|
throw LLMQore::ToolRuntimeError(
|
||||||
|
QString("Cannot read file '%1'. It may be outside the project scope "
|
||||||
|
"(enable 'Allow file access outside project' in settings), unreadable, "
|
||||||
|
"or use an unsupported encoding.")
|
||||||
|
.arg(absolutePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString result = QString("File: %1\n\n%2").arg(absolutePath, content);
|
||||||
|
return LLMQore::ToolResult::text(result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QodeAssist::Tools
|
||||||
43
tools/ReadFileTool.hpp
Normal file
43
tools/ReadFileTool.hpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2025 Petr Mironychev
|
||||||
|
*
|
||||||
|
* This file is part of QodeAssist.
|
||||||
|
*
|
||||||
|
* QodeAssist is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* QodeAssist is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with QodeAssist. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LLMQore/BaseTool.hpp>
|
||||||
|
#include <QFuture>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace QodeAssist::Tools {
|
||||||
|
|
||||||
|
class ReadFileTool : public ::LLMQore::BaseTool
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ReadFileTool(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
QString id() const override;
|
||||||
|
QString displayName() const override;
|
||||||
|
QString description() const override;
|
||||||
|
QJsonObject parametersSchema() const override;
|
||||||
|
QFuture<LLMQore::ToolResult> executeAsync(const QJsonObject &input) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QodeAssist::Tools
|
||||||
@@ -21,29 +21,62 @@
|
|||||||
|
|
||||||
#include <LLMQore/ToolsManager.hpp>
|
#include <LLMQore/ToolsManager.hpp>
|
||||||
|
|
||||||
|
#include <settings/ToolsSettings.hpp>
|
||||||
|
#include <utils/aspects.h>
|
||||||
|
|
||||||
#include "BuildProjectTool.hpp"
|
#include "BuildProjectTool.hpp"
|
||||||
#include "CreateNewFileTool.hpp"
|
#include "CreateNewFileTool.hpp"
|
||||||
#include "EditFileTool.hpp"
|
#include "EditFileTool.hpp"
|
||||||
#include "ExecuteTerminalCommandTool.hpp"
|
#include "ExecuteTerminalCommandTool.hpp"
|
||||||
#include "FindAndReadFileTool.hpp"
|
#include "FindFileTool.hpp"
|
||||||
#include "GetIssuesListTool.hpp"
|
#include "GetIssuesListTool.hpp"
|
||||||
#include "ListProjectFilesTool.hpp"
|
#include "ListProjectFilesTool.hpp"
|
||||||
#include "ProjectSearchTool.hpp"
|
#include "ProjectSearchTool.hpp"
|
||||||
|
#include "ReadFileTool.hpp"
|
||||||
#include "TodoTool.hpp"
|
#include "TodoTool.hpp"
|
||||||
|
|
||||||
namespace QodeAssist::Tools {
|
namespace QodeAssist::Tools {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template<typename ToolT>
|
||||||
|
void wireTool(::LLMQore::ToolsManager *manager,
|
||||||
|
Utils::BoolAspect &aspect,
|
||||||
|
const QString &toolId)
|
||||||
|
{
|
||||||
|
auto sync = [manager, toolId, &aspect]() {
|
||||||
|
const bool wanted = aspect.volatileValue();
|
||||||
|
const bool present = manager->tool(toolId) != nullptr;
|
||||||
|
if (wanted && !present) {
|
||||||
|
manager->addTool(new ToolT(manager));
|
||||||
|
} else if (!wanted && present) {
|
||||||
|
manager->removeTool(toolId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
sync();
|
||||||
|
|
||||||
|
QObject::connect(&aspect, &Utils::BoolAspect::volatileValueChanged, manager, sync);
|
||||||
|
QObject::connect(&aspect, &Utils::BaseAspect::changed, manager, sync);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void registerQodeAssistTools(::LLMQore::ToolsManager *manager)
|
void registerQodeAssistTools(::LLMQore::ToolsManager *manager)
|
||||||
{
|
{
|
||||||
manager->addTool(new ListProjectFilesTool(manager));
|
auto &s = Settings::toolsSettings();
|
||||||
manager->addTool(new GetIssuesListTool(manager));
|
|
||||||
manager->addTool(new CreateNewFileTool(manager));
|
wireTool<ListProjectFilesTool>(manager, s.enableListProjectFilesTool, "list_project_files");
|
||||||
manager->addTool(new EditFileTool(manager));
|
wireTool<FindFileTool>(manager, s.enableFindFileTool, "find_file");
|
||||||
manager->addTool(new BuildProjectTool(manager));
|
wireTool<ReadFileTool>(manager, s.enableReadFileTool, "read_file");
|
||||||
manager->addTool(new ExecuteTerminalCommandTool(manager));
|
wireTool<ProjectSearchTool>(manager, s.enableProjectSearchTool, "search_project");
|
||||||
manager->addTool(new ProjectSearchTool(manager));
|
wireTool<CreateNewFileTool>(manager, s.enableCreateNewFileTool, "create_new_file");
|
||||||
manager->addTool(new FindAndReadFileTool(manager));
|
wireTool<EditFileTool>(manager, s.enableEditFileTool, "edit_file");
|
||||||
manager->addTool(new TodoTool(manager));
|
wireTool<BuildProjectTool>(manager, s.enableBuildProjectTool, "build_project");
|
||||||
|
wireTool<GetIssuesListTool>(manager, s.enableGetIssuesListTool, "get_issues_list");
|
||||||
|
wireTool<ExecuteTerminalCommandTool>(
|
||||||
|
manager, s.enableTerminalCommandTool, "execute_terminal_command");
|
||||||
|
wireTool<TodoTool>(manager, s.enableTodoTool, "todo_tool");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace QodeAssist::Tools
|
} // namespace QodeAssist::Tools
|
||||||
|
|||||||
Reference in New Issue
Block a user