Feature/tool restructuring#83
Merged
Merged
Conversation
Most resultWrapper components returned null for tool_request state, which hid pending tools in a batch. With concurrent terminal execution, tools stay in tool_request longer while others are being approved, making the second tool's box invisible and the chat stuck. All resultWrapper components now render a header for tool_request and running_now states. Also removed hardcoded isOpen on CommandTool that prevented collapsing terminal output, and added load_skill to the title/desc/resultWrapper UI mappings.
Electron-main no longer calls availableTools() or knows about chatMode or mcpTools. The browser-layer service (sendLLMMessageService) computes the tool list via availableTools(chatMode, mcpTools) and passes the resolved InternalToolInfo[] across the IPC boundary as 'tools'. This decouples electron-main from tool definitions, enabling the tool descriptions to move from common/ to browser/ in subsequent commits. Also adds the tool-restructuring design doc.
…, registry) Creates browser/tools/toolTypes.tsx with the ToolDefinition<T> type that co-locates all tool segments (description, approval, validate, call, stringify, title, desc, resultWrapper) and ToolCtx for DI services. Creates browser/tools/toolRegistry.tsx with an empty toolDefinitionOfToolName map to be populated incrementally as tools are converted from the old multi-map layout.
First tool migrated to the new per-file definition pattern: - readFile.tool.ts: backend segments (description, validate, call, stringify) - readFile.toolUI.tsx: UI segments (title, desc, resultWrapper) - toolRegistry.ts: stores core definitions (importable from .ts) - toolUIRegistry.tsx: stores full definitions with UI (importable from .tsx) - toolTypes.ts: ToolDefinitionCore, ToolCtx (no JSX) - toolUITypes.tsx: ToolDefinition (extends core with React UI types) toolsService.ts delegates read_file to the registry. ToolResultComponents.tsx delegates title/desc/resultWrapper to the UI registry. SidebarChat.tsx uses getToolResultWrapper() which checks the registry first. Split into .ts/.tsx pairs because this project's tsconfig doesn't allow .ts files to import .tsx files (no JSX in .ts scope).
- Fix EndOfLinePreference import path in readFile.tool.ts (was 4 ../, needs 5) - Remove unused validateStr import from readFile.tool.ts - Remove stale availableTools import from sendLLMMessage.impl.ts
The file was emptied when toolTypes.tsx was renamed to toolUITypes.tsx. Rewrote the content with ToolCtx and ToolDefinitionCore types.
The inline validateParams/callTool/stringOfResult for read_file are now stubs that get overridden by the registry delegation at the end of the constructor. The actual implementation lives in readFile.tool.ts. Also removed unused AUTO_OUTLINE_THRESHOLD import (now in readFile.tool.ts) and stubbed out the title entry in ToolResultComponents.tsx (title now comes from toolUIRegistry). Note: builtinTools.read_file in prompts.ts is kept for now — availableTools() still reads from builtinTools to build the LLM tool list. This will be removed in the cleanup step when availableTools() is updated to pull descriptions from the registry.
…istry The circular import (readFile.toolUI.tsx → ToolResultComponents.tsx → toolUIRegistry.tsx → readFile.toolUI.tsx) crashed the workbench bundle. Fix: ToolResultComponents.tsx no longer imports toolUIRegistry.tsx. SidebarChat.tsx imports toolUIRegistry directly and checks it before falling back to builtinToolNameToComponent. getTitle and toolNameToDesc revert to using the old static maps for now — title/desc delegation will be added in the cleanup step when shared helpers are extracted.
The UI delegation (readFile.toolUI.tsx importing from ToolResultComponents.tsx) created a circular import that crashed the bundle. For the POC, only the backend is delegated to the per-file definition. The UI stays in ToolResultComponents.tsx as-is. Deleted: toolUIRegistry.tsx, readFile.toolUI.tsx, toolUITypes.tsx Reverted: SidebarChat.tsx back to builtinToolNameToComponent directly Reverted: ToolResultComponents.tsx title stub back to real values UI delegation will be added in the cleanup step after shared UI helpers (ToolHeaderWrapper, getTitle, etc.) are extracted to a separate file.
…r at render
Title is now plain strings in readFile.tool.ts (no JSX needed).
ToolDefinitionCore gains a title field: { done: string, proposed: string, running: string }.
getTitle() checks toolDefinitionOfToolName first, applies loadingTitleWrapper to
the running string at render time. Falls back to titleOfBuiltinToolName for
unconverted tools (which already has loadingTitleWrapper baked in).
Converts 8 more tools to the per-file pattern: - ls_dir, get_dir_tree, search_pathnames_only, search_for_files, search_in_file, go_to_definition, go_to_usages, read_lint_errors Each tool file contains: description, params, approvalType, validateParams, callTool, stringOfResult, and title (plain strings, no JSX). The UI (resultWrapper, desc) stays in ToolResultComponents.tsx for now — moving it requires extracting shared UI helpers to break the circular import between tool files and ToolResultComponents.tsx. Also exports shared helpers (validateBoolean, validateOptionalStr, isFalsy, resolveSymbolPosition, validateProposedTerminalId, checkIfIsFolder, validateEdits, stringifyLintErrors) from toolsService.ts, and moves stringifyLintErrors from constructor scope to module level. 9 of 22 tools now converted.
…e.ts Replace the old validateParams/callTool/stringOfResult entries for all 9 converted tools with throw-stubs that get overridden by the registry. Remove unused imports (Position, getDefinitionsAtPosition, getReferencesAtPosition, computeDirectoryTree1Deep, stringifyDirectoryTree1Deep, MAX_CHILDREN_URIs_PAGE). Also remove unused imports in readLintErrors.tool.ts (IMarkerService, URI, MAX_FILE_CHARS_PAGE).
Convert create_file_or_folder, delete_file_or_folder, rename_file_or_folder, edit_file, and rewrite_file to per-file tool definitions following the established pattern. - Export getLintErrors as a module-level function from toolsService.ts (replaces the private _getLintErrors method, now used by editFile.tool.ts and rewriteFile.tool.ts) - Remove dead _getLintErrors private method and unused timeout import - Replace inline validateParams/callTool/stringOfResult entries with throw-stubs for all 5 editing tools - Add delegation blocks in ToolsService constructor - Register all 5 tools in toolRegistry.ts 14 of 22 tools now converted.
Convert the final 8 tools (run_command, run_persistent_command, open_persistent_terminal, kill_persistent_terminal, fetch_url, semantic_search, search_history, load_skill) to per-file tool definitions. All 22 builtin tools are now converted to the per-file pattern. Each tool's description, params, approvalType, validateParams, callTool, stringOfResult, and title live in a single .ts file under browser/tools/. - Replace inline validateParams/callTool/stringOfResult entries with throw-stubs for all 8 remaining tools - Add delegation blocks in ToolsService constructor for all 8 tools - Remove unused imports (MAX_TERMINAL_BG_COMMAND_TIME, MAX_TERMINAL_INACTIVE_TIME, generateUuid, ChatMessage) - Register all 8 tools in toolRegistry.ts The next cleanup step can collapse the 22 repetitive if-blocks into a generic loop, move shared helpers to toolHelpers.ts, and remove Components.tsx.
- Move all shared helper functions (isFalsy, safeFence, validateStr, validateURIWithRoot, validateEdits, resolveSymbolPosition, getFileOutline, stringifyLintErrors, getLintErrors, etc.) from toolsService.ts to a new browser/tools/toolHelpers.ts file - Update all 22 tool files to import from ./toolHelpers.js instead of ../toolsService.js - Slim down toolsService.ts to just the class + type aliases + interface (from ~960 lines to ~235 lines) - Remove dead titleOfBuiltinToolName from ToolResultComponents.tsx (all 22 tools now get titles from the registry) - Simplify getTitle() to use registry directly instead of fallback chain - Update SidebarChat.tsx to use toolDefinitionOfToolName for proposed title - Fix URI/IFileService import paths (5 ../ → 4 ../) to match sibling files The 22 if-blocks in the constructor are intentionally kept as-is: collapsiquires either 'any' casts or 'never' type tricks, both of which violate the project's type safety guidelines.
Replace 22 repetitive if-blocks (132 lines) with a single Object.fromEntries
loop (12 lines) that builds all three dispatch maps from the registry.
TypeScript limitation: Object.entries on a Partial<{ [T in K]: V<T> }>
returns a union of V<T> for each T, and calling .callTool() on a union of
function types requires the intersection of all parameter types (which is
unsatisfiable). Using 'never' (the bottom type) for the lambda params
sidesteps this — 'never' is assignable to every type, so def.callTool(params,
ctx) type-checks. The result cast (as CallBuiltinTool) is standard
Object.fromEntries practice.
validateParams doesn't need this trick because its input is always
RawToolParamsObj (same for all tools).
Remove builtinTools from prompts.ts — the description, params, and name for each tool now live only in the per-file tool definitions (browser/tools/*.tool.ts). Changes: - Delete builtinTools object (~230 lines) from prompts.ts - Move availableTools() from prompts.ts to browser/tools/toolRegistry.ts, where it builds InternalToolInfo[] from toolDefinitionOfToolName - Delete dead helpers (systemToolsXMLPrompt was kept but refactored to accept InternalToolInfo[] instead of chatMode + mcpTools; dead toolCallDefinitionsXMLString was restored as a helper for it) - Delete dead helpers (uriParam, paginationParam, terminalDescHelper, cwdHelper, editsTool_description) from prompts.ts - Define builtinToolNames as explicit array instead of Object.keys(builtinTools) - Derive BuiltinToolParamName from SnakeCaseKeys<BuiltinToolCallParams[T]> instead of builtinToolTypes.ts - Update ChatPromptContext to use tools: InternalToolInfo[] instead of mcpTools + includeXMLToolDefinitions - Update sendLLMMessageService.ts and convertToLLMMessageService.ts to import availableTools from browser/tools/toolRegistry.ts
MXZZ
added a commit
to MXZZ/working-void-editor
that referenced
this pull request
Jul 9, 2026
Feature/tool restructuring (davi0015#83)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.