@travisennis/acai 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +190 -19
- package/bin/acai-wrapper.js +26 -0
- package/dist/agent/index.d.ts +132 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +434 -0
- package/dist/api/exa/index.js +1 -1
- package/dist/cli.d.ts +4 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +67 -40
- package/dist/commands/add-directory-command.d.ts +3 -0
- package/dist/commands/add-directory-command.d.ts.map +1 -0
- package/dist/commands/add-directory-command.js +54 -0
- package/dist/commands/application-log-command.d.ts +1 -1
- package/dist/commands/application-log-command.d.ts.map +1 -1
- package/dist/commands/application-log-command.js +18 -20
- package/dist/commands/clear-command.d.ts +1 -1
- package/dist/commands/clear-command.d.ts.map +1 -1
- package/dist/commands/clear-command.js +7 -3
- package/dist/commands/compact-command.d.ts.map +1 -1
- package/dist/commands/compact-command.js +9 -5
- package/dist/commands/context-command.d.ts +3 -0
- package/dist/commands/context-command.d.ts.map +1 -0
- package/dist/commands/context-command.js +124 -0
- package/dist/commands/copy-command.d.ts.map +1 -1
- package/dist/commands/copy-command.js +14 -5
- package/dist/commands/edit-command.d.ts +1 -1
- package/dist/commands/edit-command.d.ts.map +1 -1
- package/dist/commands/edit-command.js +21 -34
- package/dist/commands/edit-prompt-command.d.ts +1 -1
- package/dist/commands/edit-prompt-command.d.ts.map +1 -1
- package/dist/commands/edit-prompt-command.js +18 -15
- package/dist/commands/exit-command.d.ts +1 -4
- package/dist/commands/exit-command.d.ts.map +1 -1
- package/dist/commands/exit-command.js +9 -5
- package/dist/commands/files-command.d.ts +1 -1
- package/dist/commands/files-command.d.ts.map +1 -1
- package/dist/commands/files-command.js +20 -16
- package/dist/commands/generate-rules-command.d.ts +1 -1
- package/dist/commands/generate-rules-command.d.ts.map +1 -1
- package/dist/commands/generate-rules-command.js +307 -39
- package/dist/commands/handoff-command.d.ts +3 -0
- package/dist/commands/handoff-command.d.ts.map +1 -0
- package/dist/commands/handoff-command.js +191 -0
- package/dist/commands/health-command.d.ts +1 -1
- package/dist/commands/health-command.d.ts.map +1 -1
- package/dist/commands/health-command.js +49 -27
- package/dist/commands/help-command.d.ts +1 -1
- package/dist/commands/help-command.d.ts.map +1 -1
- package/dist/commands/help-command.js +25 -5
- package/dist/commands/history-command.d.ts +3 -0
- package/dist/commands/history-command.d.ts.map +1 -0
- package/dist/commands/history-command.js +458 -0
- package/dist/commands/init-command.d.ts +1 -1
- package/dist/commands/init-command.d.ts.map +1 -1
- package/dist/commands/init-command.js +40 -22
- package/dist/commands/last-log-command.d.ts +1 -1
- package/dist/commands/last-log-command.d.ts.map +1 -1
- package/dist/commands/last-log-command.js +15 -15
- package/dist/commands/list-directories-command.d.ts +3 -0
- package/dist/commands/list-directories-command.d.ts.map +1 -0
- package/dist/commands/list-directories-command.js +35 -0
- package/dist/commands/list-tools-command.d.ts.map +1 -1
- package/dist/commands/list-tools-command.js +61 -21
- package/dist/commands/manager.d.ts +9 -4
- package/dist/commands/manager.d.ts.map +1 -1
- package/dist/commands/manager.js +64 -39
- package/dist/commands/model-command.d.ts.map +1 -1
- package/dist/commands/model-command.js +201 -66
- package/dist/commands/paste-command.d.ts +1 -1
- package/dist/commands/paste-command.d.ts.map +1 -1
- package/dist/commands/paste-command.js +23 -9
- package/dist/commands/pickup-command.d.ts +3 -0
- package/dist/commands/pickup-command.d.ts.map +1 -0
- package/dist/commands/pickup-command.js +109 -0
- package/dist/commands/prompt-command.d.ts +19 -1
- package/dist/commands/prompt-command.d.ts.map +1 -1
- package/dist/commands/prompt-command.js +191 -98
- package/dist/commands/remove-directory-command.d.ts +3 -0
- package/dist/commands/remove-directory-command.d.ts.map +1 -0
- package/dist/commands/remove-directory-command.js +55 -0
- package/dist/commands/reset-command.d.ts +1 -1
- package/dist/commands/reset-command.d.ts.map +1 -1
- package/dist/commands/reset-command.js +8 -5
- package/dist/commands/rules-command.d.ts +1 -1
- package/dist/commands/rules-command.d.ts.map +1 -1
- package/dist/commands/rules-command.js +25 -22
- package/dist/commands/save-command.d.ts +1 -1
- package/dist/commands/save-command.d.ts.map +1 -1
- package/dist/commands/save-command.js +8 -3
- package/dist/commands/shell-command.d.ts.map +1 -1
- package/dist/commands/shell-command.js +45 -24
- package/dist/commands/types.d.ts +9 -7
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/usage-command.d.ts +1 -1
- package/dist/commands/usage-command.d.ts.map +1 -1
- package/dist/commands/usage-command.js +18 -7
- package/dist/config.d.ts +21 -11
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +90 -63
- package/dist/execution/index.d.ts +17 -2
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/index.js +62 -20
- package/dist/formatting.d.ts +127 -0
- package/dist/formatting.d.ts.map +1 -1
- package/dist/formatting.js +201 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +263 -102
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +47 -18
- package/dist/mentions.d.ts +2 -1
- package/dist/mentions.d.ts.map +1 -1
- package/dist/mentions.js +16 -1
- package/dist/messages.d.ts +11 -0
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +122 -21
- package/dist/middleware/cache.d.ts +3 -0
- package/dist/middleware/cache.d.ts.map +1 -0
- package/dist/middleware/cache.js +53 -0
- package/dist/middleware/index.d.ts +1 -0
- package/dist/middleware/index.d.ts.map +1 -1
- package/dist/middleware/index.js +1 -0
- package/dist/models/ai-config.d.ts +4 -2
- package/dist/models/ai-config.d.ts.map +1 -1
- package/dist/models/ai-config.js +12 -2
- package/dist/models/anthropic-provider.d.ts.map +1 -1
- package/dist/models/anthropic-provider.js +3 -67
- package/dist/models/deepseek-provider.d.ts.map +1 -1
- package/dist/models/deepseek-provider.js +0 -2
- package/dist/models/google-provider.d.ts.map +1 -1
- package/dist/models/google-provider.js +0 -3
- package/dist/models/groq-provider.d.ts.map +1 -1
- package/dist/models/groq-provider.js +0 -1
- package/dist/models/manager.d.ts +2 -1
- package/dist/models/manager.d.ts.map +1 -1
- package/dist/models/manager.js +26 -2
- package/dist/models/openai-provider.d.ts.map +1 -1
- package/dist/models/openai-provider.js +0 -4
- package/dist/models/openrouter-provider.d.ts +16 -22
- package/dist/models/openrouter-provider.d.ts.map +1 -1
- package/dist/models/openrouter-provider.js +175 -236
- package/dist/models/providers.d.ts +4 -14
- package/dist/models/providers.d.ts.map +1 -1
- package/dist/models/providers.js +1 -57
- package/dist/models/xai-provider.d.ts.map +1 -1
- package/dist/models/xai-provider.js +0 -2
- package/dist/prompts.d.ts +10 -4
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +447 -70
- package/dist/repl/project-status-line.d.ts +3 -0
- package/dist/repl/project-status-line.d.ts.map +1 -0
- package/dist/repl/project-status-line.js +61 -0
- package/dist/repl/tool-call-repair.d.ts.map +1 -1
- package/dist/repl/tool-call-repair.js +8 -4
- package/dist/repl-new.d.ts +51 -0
- package/dist/repl-new.d.ts.map +1 -0
- package/dist/repl-new.js +354 -0
- package/dist/skills.d.ts +20 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +192 -0
- package/dist/terminal/control.d.ts +55 -0
- package/dist/terminal/control.d.ts.map +1 -0
- package/dist/terminal/control.js +109 -0
- package/dist/terminal/default-theme.d.ts +1 -1
- package/dist/terminal/default-theme.d.ts.map +1 -1
- package/dist/terminal/default-theme.js +24 -28
- package/dist/terminal/formatting.d.ts +23 -25
- package/dist/terminal/formatting.d.ts.map +1 -1
- package/dist/terminal/formatting.js +35 -52
- package/dist/terminal/highlight/index.d.ts.map +1 -1
- package/dist/terminal/highlight/index.js +3 -6
- package/dist/terminal/highlight/theme.d.ts.map +1 -1
- package/dist/terminal/highlight/theme.js +2 -6
- package/dist/terminal/index.d.ts +2 -94
- package/dist/terminal/index.d.ts.map +1 -1
- package/dist/terminal/index.js +2 -370
- package/dist/terminal/markdown.js +10 -5
- package/dist/terminal/select-prompt.d.ts +2 -2
- package/dist/terminal/select-prompt.d.ts.map +1 -1
- package/dist/terminal/select-prompt.js +47 -39
- package/dist/terminal/strip-ansi.js +4 -4
- package/dist/terminal/table/cell.d.ts +114 -0
- package/dist/terminal/table/cell.d.ts.map +1 -0
- package/dist/terminal/table/cell.js +407 -0
- package/dist/terminal/table/debug.d.ts +15 -0
- package/dist/terminal/table/debug.d.ts.map +1 -0
- package/dist/terminal/table/debug.js +32 -0
- package/dist/terminal/table/index.d.ts +3 -0
- package/dist/terminal/table/index.d.ts.map +1 -0
- package/dist/terminal/table/index.js +2 -0
- package/dist/terminal/table/layout-manager.d.ts +27 -0
- package/dist/terminal/table/layout-manager.d.ts.map +1 -0
- package/dist/terminal/table/layout-manager.js +257 -0
- package/dist/terminal/table/table.d.ts +9 -0
- package/dist/terminal/table/table.d.ts.map +1 -0
- package/dist/terminal/table/table.js +97 -0
- package/dist/terminal/table/utils.d.ts +63 -0
- package/dist/terminal/table/utils.d.ts.map +1 -0
- package/dist/terminal/table/utils.js +326 -0
- package/dist/tokens/threshold.d.ts +20 -0
- package/dist/tokens/threshold.d.ts.map +1 -0
- package/dist/tokens/threshold.js +67 -0
- package/dist/tools/advanced-edit-file.d.ts +69 -0
- package/dist/tools/advanced-edit-file.d.ts.map +1 -0
- package/dist/tools/advanced-edit-file.js +285 -0
- package/dist/tools/agent.d.ts +16 -5
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/agent.js +86 -59
- package/dist/tools/bash.d.ts +23 -12
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +243 -128
- package/dist/tools/batch.d.ts +34 -0
- package/dist/tools/batch.d.ts.map +1 -0
- package/dist/tools/batch.js +174 -0
- package/dist/tools/code-interpreter.d.ts +21 -9
- package/dist/tools/code-interpreter.d.ts.map +1 -1
- package/dist/tools/code-interpreter.js +151 -134
- package/dist/tools/delete-file.d.ts +17 -10
- package/dist/tools/delete-file.d.ts.map +1 -1
- package/dist/tools/delete-file.js +60 -97
- package/dist/tools/directory-tree.d.ts +17 -12
- package/dist/tools/directory-tree.d.ts.map +1 -1
- package/dist/tools/directory-tree.js +57 -48
- package/dist/tools/dynamic-tool-loader.d.ts +16 -10
- package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
- package/dist/tools/dynamic-tool-loader.js +122 -130
- package/dist/tools/dynamic-tool-parser.d.ts +1 -0
- package/dist/tools/dynamic-tool-parser.d.ts.map +1 -1
- package/dist/tools/dynamic-tool-parser.js +1 -0
- package/dist/tools/edit-file.d.ts +35 -15
- package/dist/tools/edit-file.d.ts.map +1 -1
- package/dist/tools/edit-file.js +127 -114
- package/dist/tools/glob.d.ts +36 -0
- package/dist/tools/glob.d.ts.map +1 -0
- package/dist/tools/glob.js +154 -0
- package/dist/tools/grep.d.ts +73 -12
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +425 -165
- package/dist/tools/index.d.ts +220 -126
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +284 -135
- package/dist/tools/llm-edit-fixer.d.ts +24 -0
- package/dist/tools/llm-edit-fixer.d.ts.map +1 -0
- package/dist/tools/llm-edit-fixer.js +136 -0
- package/dist/tools/move-file.d.ts +19 -7
- package/dist/tools/move-file.d.ts.map +1 -1
- package/dist/tools/move-file.js +48 -34
- package/dist/tools/read-file.d.ts +47 -9
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +84 -70
- package/dist/tools/read-multiple-files.d.ts +17 -6
- package/dist/tools/read-multiple-files.d.ts.map +1 -1
- package/dist/tools/read-multiple-files.js +132 -72
- package/dist/tools/save-file.d.ts +45 -12
- package/dist/tools/save-file.d.ts.map +1 -1
- package/dist/tools/save-file.js +76 -101
- package/dist/tools/think.d.ts +15 -7
- package/dist/tools/think.d.ts.map +1 -1
- package/dist/tools/think.js +34 -20
- package/dist/tools/types.d.ts +8 -10
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js +9 -0
- package/dist/tools/utils.d.ts +14 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +16 -0
- package/dist/tools/web-fetch.d.ts +11 -4
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +39 -38
- package/dist/tools/web-search.d.ts +15 -6
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +64 -31
- package/dist/tui/autocomplete.d.ts +44 -0
- package/dist/tui/autocomplete.d.ts.map +1 -0
- package/dist/tui/autocomplete.js +466 -0
- package/dist/tui/components/assistant-message.d.ts +18 -0
- package/dist/tui/components/assistant-message.d.ts.map +1 -0
- package/dist/tui/components/assistant-message.js +29 -0
- package/dist/tui/components/box.d.ts +20 -0
- package/dist/tui/components/box.d.ts.map +1 -0
- package/dist/tui/components/box.js +81 -0
- package/dist/tui/components/editor.d.ts +106 -0
- package/dist/tui/components/editor.d.ts.map +1 -0
- package/dist/tui/components/editor.js +1220 -0
- package/dist/tui/components/footer.d.ts +12 -0
- package/dist/tui/components/footer.d.ts.map +1 -0
- package/dist/tui/components/footer.js +209 -0
- package/dist/tui/components/header.d.ts +21 -0
- package/dist/tui/components/header.d.ts.map +1 -0
- package/dist/tui/components/header.js +63 -0
- package/dist/tui/components/input.d.ts +14 -0
- package/dist/tui/components/input.d.ts.map +1 -0
- package/dist/tui/components/input.js +122 -0
- package/dist/tui/components/loader.d.ts +23 -0
- package/dist/tui/components/loader.d.ts.map +1 -0
- package/dist/tui/components/loader.js +45 -0
- package/dist/tui/components/markdown.d.ts +106 -0
- package/dist/tui/components/markdown.d.ts.map +1 -0
- package/dist/tui/components/markdown.js +586 -0
- package/dist/tui/components/modal.d.ts +29 -0
- package/dist/tui/components/modal.d.ts.map +1 -0
- package/dist/tui/components/modal.js +263 -0
- package/dist/tui/components/progress-bar.d.ts +19 -0
- package/dist/tui/components/progress-bar.d.ts.map +1 -0
- package/dist/tui/components/progress-bar.js +78 -0
- package/dist/tui/components/prompt-status.d.ts +17 -0
- package/dist/tui/components/prompt-status.d.ts.map +1 -0
- package/dist/tui/components/prompt-status.js +26 -0
- package/dist/tui/components/select-list.d.ts +48 -0
- package/dist/tui/components/select-list.d.ts.map +1 -0
- package/dist/tui/components/select-list.js +207 -0
- package/dist/tui/components/spacer.d.ts +16 -0
- package/dist/tui/components/spacer.d.ts.map +1 -0
- package/dist/tui/components/spacer.js +27 -0
- package/dist/tui/components/table.d.ts +27 -0
- package/dist/tui/components/table.d.ts.map +1 -0
- package/dist/tui/components/table.js +125 -0
- package/dist/tui/components/text.d.ts +26 -0
- package/dist/tui/components/text.d.ts.map +1 -0
- package/dist/tui/components/text.js +143 -0
- package/dist/tui/components/thinking-block.d.ts +14 -0
- package/dist/tui/components/thinking-block.d.ts.map +1 -0
- package/dist/tui/components/thinking-block.js +33 -0
- package/dist/tui/components/tool-execution.d.ts +21 -0
- package/dist/tui/components/tool-execution.d.ts.map +1 -0
- package/dist/tui/components/tool-execution.js +161 -0
- package/dist/tui/components/user-message.d.ts +9 -0
- package/dist/tui/components/user-message.d.ts.map +1 -0
- package/dist/tui/components/user-message.js +23 -0
- package/dist/tui/components/welcome.d.ts +6 -0
- package/dist/tui/components/welcome.d.ts.map +1 -0
- package/dist/tui/components/welcome.js +30 -0
- package/dist/tui/index.d.ts +18 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +22 -0
- package/dist/tui/terminal.d.ts +38 -0
- package/dist/tui/terminal.d.ts.map +1 -0
- package/dist/tui/terminal.js +94 -0
- package/dist/tui/tui.d.ts +69 -0
- package/dist/tui/tui.d.ts.map +1 -0
- package/dist/tui/tui.js +204 -0
- package/dist/tui/utils.d.ts +24 -0
- package/dist/tui/utils.d.ts.map +1 -0
- package/dist/tui/utils.js +111 -0
- package/dist/utils/bash.d.ts +7 -0
- package/dist/utils/bash.d.ts.map +1 -0
- package/dist/{tools/bash-utils.js → utils/bash.js} +31 -12
- package/dist/utils/{filesystem.d.ts → filesystem/operations.d.ts} +1 -1
- package/dist/utils/filesystem/operations.d.ts.map +1 -0
- package/dist/utils/filesystem/security.d.ts +9 -0
- package/dist/utils/filesystem/security.d.ts.map +1 -0
- package/dist/{tools/filesystem-utils.js → utils/filesystem/security.js} +93 -21
- package/dist/utils/funcs.d.ts +6 -0
- package/dist/utils/funcs.d.ts.map +1 -0
- package/dist/utils/funcs.js +6 -0
- package/dist/utils/generators.d.ts +3 -0
- package/dist/utils/generators.d.ts.map +1 -0
- package/dist/utils/generators.js +25 -0
- package/dist/{tools/git-utils.d.ts → utils/git.d.ts} +1 -1
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/{tools/git-utils.js → utils/git.js} +0 -6
- package/dist/utils/glob.js +1 -1
- package/dist/utils/iterables.d.ts +2 -0
- package/dist/utils/iterables.d.ts.map +1 -0
- package/dist/utils/iterables.js +6 -0
- package/dist/utils/{zod-utils.d.ts → zod.d.ts} +1 -1
- package/dist/utils/zod.d.ts.map +1 -0
- package/package.json +21 -21
- package/dist/conversation-analyzer.d.ts +0 -11
- package/dist/conversation-analyzer.d.ts.map +0 -1
- package/dist/conversation-analyzer.js +0 -88
- package/dist/repl/display-tool-messages.d.ts +0 -4
- package/dist/repl/display-tool-messages.d.ts.map +0 -1
- package/dist/repl/display-tool-messages.js +0 -55
- package/dist/repl/display-tool-use.d.ts +0 -14
- package/dist/repl/display-tool-use.d.ts.map +0 -1
- package/dist/repl/display-tool-use.js +0 -63
- package/dist/repl/get-prompt-header.d.ts +0 -8
- package/dist/repl/get-prompt-header.d.ts.map +0 -1
- package/dist/repl/get-prompt-header.js +0 -38
- package/dist/repl-prompt.d.ts +0 -15
- package/dist/repl-prompt.d.ts.map +0 -1
- package/dist/repl-prompt.js +0 -147
- package/dist/repl.d.ts +0 -31
- package/dist/repl.d.ts.map +0 -1
- package/dist/repl.js +0 -310
- package/dist/terminal/checkbox-prompt.d.ts +0 -36
- package/dist/terminal/checkbox-prompt.d.ts.map +0 -1
- package/dist/terminal/checkbox-prompt.js +0 -362
- package/dist/terminal/editor-prompt.d.ts +0 -10
- package/dist/terminal/editor-prompt.d.ts.map +0 -1
- package/dist/terminal/editor-prompt.js +0 -61
- package/dist/terminal/errors.d.ts +0 -19
- package/dist/terminal/errors.d.ts.map +0 -1
- package/dist/terminal/errors.js +0 -37
- package/dist/terminal/input-prompt.d.ts +0 -16
- package/dist/terminal/input-prompt.d.ts.map +0 -1
- package/dist/terminal/input-prompt.js +0 -181
- package/dist/terminal/search-prompt.d.ts +0 -20
- package/dist/terminal/search-prompt.d.ts.map +0 -1
- package/dist/terminal/search-prompt.js +0 -279
- package/dist/terminal/types.d.ts +0 -35
- package/dist/terminal/types.d.ts.map +0 -1
- package/dist/terminal/types.js +0 -1
- package/dist/tokens/manage-output.d.ts +0 -34
- package/dist/tokens/manage-output.d.ts.map +0 -1
- package/dist/tokens/manage-output.js +0 -44
- package/dist/tool-executor.d.ts +0 -28
- package/dist/tool-executor.d.ts.map +0 -1
- package/dist/tool-executor.js +0 -74
- package/dist/tools/bash-utils.d.ts +0 -7
- package/dist/tools/bash-utils.d.ts.map +0 -1
- package/dist/tools/file-editing-utils.d.ts +0 -2
- package/dist/tools/file-editing-utils.d.ts.map +0 -1
- package/dist/tools/file-editing-utils.js +0 -135
- package/dist/tools/filesystem-utils.d.ts +0 -7
- package/dist/tools/filesystem-utils.d.ts.map +0 -1
- package/dist/tools/git-utils.d.ts.map +0 -1
- package/dist/utils/filesystem.d.ts.map +0 -1
- package/dist/utils/zod-utils.d.ts.map +0 -1
- /package/dist/utils/{filesystem.js → filesystem/operations.js} +0 -0
- /package/dist/utils/{zod-utils.js → zod.js} +0 -0
package/dist/tools/edit-file.js
CHANGED
|
@@ -1,122 +1,84 @@
|
|
|
1
1
|
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
import { tool } from "ai";
|
|
3
2
|
import { createTwoFilesPatch } from "diff";
|
|
4
3
|
import { z } from "zod";
|
|
4
|
+
import { config } from "../config.js";
|
|
5
|
+
import { logger } from "../logger.js";
|
|
6
|
+
import { clearProjectStatusCache } from "../repl/project-status-line.js";
|
|
5
7
|
import style from "../terminal/style.js";
|
|
6
|
-
import { joinWorkingDir, validatePath } from "
|
|
8
|
+
import { joinWorkingDir, validateFileNotReadOnly, validatePath, } from "../utils/filesystem/security.js";
|
|
9
|
+
import { fixLlmEditWithInstruction } from "./llm-edit-fixer.js";
|
|
7
10
|
export const EditFileTool = {
|
|
8
11
|
name: "editFile",
|
|
9
12
|
};
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
const inputSchema = z.object({
|
|
14
|
+
path: z.string().describe("The path of the file to edit."),
|
|
15
|
+
edits: z.array(z.object({
|
|
16
|
+
oldText: z
|
|
17
|
+
.string()
|
|
18
|
+
.describe("Text to search for - must match exactly and enough context must be provided to uniquely match the target text. " +
|
|
19
|
+
"Special characters require JSON escaping: backticks (\\`...\\`), quotes, backslashes. " +
|
|
20
|
+
"For multi-line content, include exact newlines and indentation."),
|
|
21
|
+
newText: z.string().describe("Text to replace with"),
|
|
22
|
+
})),
|
|
23
|
+
});
|
|
24
|
+
export const createEditFileTool = async ({ workingDir, allowedDirs, modelManager, tokenTracker, enableLlmFix = true, }) => {
|
|
25
|
+
const allowedDirectory = allowedDirs ?? [workingDir];
|
|
12
26
|
return {
|
|
13
|
-
|
|
27
|
+
toolDef: {
|
|
14
28
|
description: "Make line-based edits to a text file. Each edit replaces exact line sequences " +
|
|
15
29
|
"with new content. Exact literal matching is used: no whitespace, indentation, escape, or newline normalization is applied when locating matches. " +
|
|
16
30
|
"Provide enough context so the match is unique; otherwise the operation errors. Returns a git-style diff showing the changes made. " +
|
|
17
31
|
"Only works within allowed directories. " +
|
|
18
32
|
"Note: Special characters in oldText must be properly escaped for JSON (e.g., backticks as \\`...\\`). " +
|
|
19
33
|
"Multi-line strings require exact character-by-character matching including whitespace.",
|
|
20
|
-
inputSchema
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
.string()
|
|
25
|
-
.describe("Text to search for - must match exactly and enough context must be provided to uniquely match the target text. " +
|
|
26
|
-
"Special characters require JSON escaping: backticks (\\`...\\`), quotes, backslashes. " +
|
|
27
|
-
"For multi-line content, include exact newlines and indentation."),
|
|
28
|
-
newText: z.string().describe("Text to replace with"),
|
|
29
|
-
})),
|
|
30
|
-
}),
|
|
31
|
-
execute: async ({ path, edits }, { toolCallId, abortSignal }) => {
|
|
32
|
-
// Check if execution has been aborted
|
|
34
|
+
inputSchema,
|
|
35
|
+
},
|
|
36
|
+
async *execute({ path, edits }, { toolCallId, abortSignal }) {
|
|
37
|
+
try {
|
|
33
38
|
if (abortSignal?.aborted) {
|
|
34
39
|
throw new Error("File editing aborted");
|
|
35
40
|
}
|
|
36
|
-
|
|
41
|
+
yield {
|
|
42
|
+
name: EditFileTool.name,
|
|
37
43
|
id: toolCallId,
|
|
38
44
|
event: "tool-init",
|
|
39
|
-
data:
|
|
45
|
+
data: `${style.cyan(path)}`,
|
|
46
|
+
};
|
|
47
|
+
const validPath = await validatePath(joinWorkingDir(path, workingDir), allowedDirectory, { abortSignal });
|
|
48
|
+
// Check if file is read-only
|
|
49
|
+
const projectConfig = await config.getConfig();
|
|
50
|
+
validateFileNotReadOnly(validPath, projectConfig, workingDir);
|
|
51
|
+
const result = await applyFileEdits(validPath, edits, false, abortSignal, {
|
|
52
|
+
modelManager,
|
|
53
|
+
tokenTracker,
|
|
54
|
+
enableLlmFix,
|
|
40
55
|
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (e.name === "AbortError") {
|
|
68
|
-
throw new Error("File editing aborted during user input");
|
|
69
|
-
}
|
|
70
|
-
throw e;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
const { result: userChoice, reason } = userResponse ?? {
|
|
74
|
-
result: "accept",
|
|
75
|
-
};
|
|
76
|
-
terminal.lineBreak();
|
|
77
|
-
if (userChoice === "accept-all") {
|
|
78
|
-
terminal.writeln(style.yellow("✓ Auto-accept mode enabled for all edits"));
|
|
79
|
-
terminal.lineBreak();
|
|
80
|
-
}
|
|
81
|
-
if (userChoice === "accept" || userChoice === "accept-all") {
|
|
82
|
-
const finalEdits = await applyFileEdits(validPath, edits, false, abortSignal);
|
|
83
|
-
// Send completion message indicating success
|
|
84
|
-
sendData?.({
|
|
85
|
-
id: toolCallId,
|
|
86
|
-
event: "tool-completion",
|
|
87
|
-
data: "Edits accepted and applied successfully.",
|
|
88
|
-
});
|
|
89
|
-
return finalEdits;
|
|
90
|
-
}
|
|
91
|
-
terminal.lineBreak();
|
|
92
|
-
// Send completion message indicating rejection
|
|
93
|
-
const rejectionReason = reason || "No reason provided";
|
|
94
|
-
sendData?.({
|
|
95
|
-
id: toolCallId,
|
|
96
|
-
event: "tool-completion",
|
|
97
|
-
data: `Edits rejected by user. Reason: ${rejectionReason}`,
|
|
98
|
-
});
|
|
99
|
-
return `The user rejected these changes. Reason: ${rejectionReason}`;
|
|
100
|
-
}
|
|
101
|
-
const finalEdits = await applyFileEdits(validPath, edits, false, abortSignal);
|
|
102
|
-
// Send completion message indicating success
|
|
103
|
-
sendData?.({
|
|
104
|
-
id: toolCallId,
|
|
105
|
-
event: "tool-completion",
|
|
106
|
-
data: "Edits accepted and applied successfully.",
|
|
107
|
-
});
|
|
108
|
-
return finalEdits;
|
|
109
|
-
}
|
|
110
|
-
catch (error) {
|
|
111
|
-
sendData?.({
|
|
112
|
-
event: "tool-error",
|
|
113
|
-
id: toolCallId,
|
|
114
|
-
data: `Failed to edit file: ${error.message}`,
|
|
115
|
-
});
|
|
116
|
-
return `Failed to edit file: ${error.message}`;
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
}),
|
|
56
|
+
yield {
|
|
57
|
+
name: EditFileTool.name,
|
|
58
|
+
id: toolCallId,
|
|
59
|
+
event: "tool-update",
|
|
60
|
+
data: result.trim(),
|
|
61
|
+
};
|
|
62
|
+
yield {
|
|
63
|
+
name: EditFileTool.name,
|
|
64
|
+
id: toolCallId,
|
|
65
|
+
event: "tool-completion",
|
|
66
|
+
data: `Applied ${edits.length} edits to ${style.cyan(path)}`,
|
|
67
|
+
};
|
|
68
|
+
// Clear project status cache since file operations change git status
|
|
69
|
+
clearProjectStatusCache();
|
|
70
|
+
yield result;
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
yield {
|
|
74
|
+
name: EditFileTool.name,
|
|
75
|
+
event: "tool-error",
|
|
76
|
+
id: toolCallId,
|
|
77
|
+
data: error.message,
|
|
78
|
+
};
|
|
79
|
+
yield `Failed to edit file: ${error.message}`;
|
|
80
|
+
}
|
|
81
|
+
},
|
|
120
82
|
};
|
|
121
83
|
};
|
|
122
84
|
// file editing and diffing utilities
|
|
@@ -129,7 +91,7 @@ function createUnifiedDiff(originalContent, newContent, filepath = "file") {
|
|
|
129
91
|
const normalizedNew = normalizeLineEndings(newContent);
|
|
130
92
|
return createTwoFilesPatch(filepath, filepath, normalizedOriginal, normalizedNew, "original", "modified");
|
|
131
93
|
}
|
|
132
|
-
export async function applyFileEdits(filePath, edits, dryRun = false, abortSignal) {
|
|
94
|
+
export async function applyFileEdits(filePath, edits, dryRun = false, abortSignal, options) {
|
|
133
95
|
if (abortSignal?.aborted) {
|
|
134
96
|
throw new Error("File edit operation aborted");
|
|
135
97
|
}
|
|
@@ -141,26 +103,19 @@ export async function applyFileEdits(filePath, edits, dryRun = false, abortSigna
|
|
|
141
103
|
if (edits.find((edit) => edit.oldText.length === 0)) {
|
|
142
104
|
throw new Error("Invalid oldText in edit. The value of oldText must be at least one character");
|
|
143
105
|
}
|
|
144
|
-
// Apply edits sequentially using
|
|
106
|
+
// Apply edits sequentially using literal matches (allow multiple matches)
|
|
145
107
|
let modifiedContent = originalContent;
|
|
146
108
|
for (const edit of edits) {
|
|
147
109
|
if (abortSignal?.aborted) {
|
|
148
110
|
throw new Error("File edit operation aborted during processing");
|
|
149
111
|
}
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (firstIndex === -1) {
|
|
154
|
-
throw new Error("oldText not found in content");
|
|
112
|
+
const result = await applyEditWithLlmFix(edit, modifiedContent, abortSignal, options);
|
|
113
|
+
if (result.success) {
|
|
114
|
+
modifiedContent = result.content;
|
|
155
115
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
throw new Error("oldText found multiple times and requires more code context to uniquely identify the intended match");
|
|
116
|
+
else {
|
|
117
|
+
throw new Error("oldText not found in content");
|
|
159
118
|
}
|
|
160
|
-
modifiedContent =
|
|
161
|
-
modifiedContent.slice(0, firstIndex) +
|
|
162
|
-
newText +
|
|
163
|
-
modifiedContent.slice(firstIndex + oldText.length);
|
|
164
119
|
}
|
|
165
120
|
// Create unified diff (createUnifiedDiff normalizes line endings internally for diffing)
|
|
166
121
|
const diff = createUnifiedDiff(originalContent, modifiedContent, filePath);
|
|
@@ -169,7 +124,7 @@ export async function applyFileEdits(filePath, edits, dryRun = false, abortSigna
|
|
|
169
124
|
while (diff.includes("`".repeat(numBackticks))) {
|
|
170
125
|
numBackticks++;
|
|
171
126
|
}
|
|
172
|
-
const formattedDiff = `${"`".repeat(numBackticks)}diff\n${diff}${"`".repeat(numBackticks)}
|
|
127
|
+
const formattedDiff = `${"`".repeat(numBackticks)} diff\n${diff}\n${"`".repeat(numBackticks)}`;
|
|
173
128
|
if (!dryRun) {
|
|
174
129
|
if (abortSignal?.aborted) {
|
|
175
130
|
throw new Error("File edit operation aborted before writing");
|
|
@@ -182,3 +137,61 @@ export async function applyFileEdits(filePath, edits, dryRun = false, abortSigna
|
|
|
182
137
|
}
|
|
183
138
|
return formattedDiff;
|
|
184
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Applies a single edit with LLM fix fallback
|
|
142
|
+
*/
|
|
143
|
+
async function applyEditWithLlmFix(edit, content, abortSignal, options) {
|
|
144
|
+
const { oldText, newText } = edit;
|
|
145
|
+
// Try the original edit first
|
|
146
|
+
const originalResult = applyLiteralEdit(content, oldText, newText);
|
|
147
|
+
if (originalResult.matchCount > 0) {
|
|
148
|
+
return { success: true, content: originalResult.content };
|
|
149
|
+
}
|
|
150
|
+
// If LLM fix is enabled and dependencies are available, try to fix the edit
|
|
151
|
+
if (options?.enableLlmFix !== false &&
|
|
152
|
+
options?.modelManager &&
|
|
153
|
+
options?.tokenTracker) {
|
|
154
|
+
try {
|
|
155
|
+
const fixedEdit = await fixLlmEditWithInstruction(options.instruction, oldText, newText, "oldText not found in content", content, options.modelManager ?? undefined, abortSignal);
|
|
156
|
+
if (fixedEdit && !fixedEdit.noChangesRequired) {
|
|
157
|
+
// Retry the edit with the corrected search string
|
|
158
|
+
const correctedResult = applyLiteralEdit(content, fixedEdit.search, fixedEdit.replace);
|
|
159
|
+
if (correctedResult.matchCount > 0) {
|
|
160
|
+
return { success: true, content: correctedResult.content };
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
else if (fixedEdit?.noChangesRequired) {
|
|
164
|
+
// No changes required, skip this edit
|
|
165
|
+
return { success: true, content };
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (llmError) {
|
|
169
|
+
// If LLM fix fails, fall back to original error
|
|
170
|
+
logger.warn(llmError, "LLM edit fix failed:");
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return { success: false, content };
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Applies a literal search and replace operation
|
|
177
|
+
*/
|
|
178
|
+
function applyLiteralEdit(content, search, replace) {
|
|
179
|
+
let modifiedContent = content;
|
|
180
|
+
let matchCount = 0;
|
|
181
|
+
let currentIndex = 0;
|
|
182
|
+
while (currentIndex < modifiedContent.length) {
|
|
183
|
+
const matchIndex = modifiedContent.indexOf(search, currentIndex);
|
|
184
|
+
if (matchIndex === -1) {
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
matchCount++;
|
|
188
|
+
// Apply the replacement
|
|
189
|
+
modifiedContent =
|
|
190
|
+
modifiedContent.slice(0, matchIndex) +
|
|
191
|
+
replace +
|
|
192
|
+
modifiedContent.slice(matchIndex + search.length);
|
|
193
|
+
// Move current index past the replacement
|
|
194
|
+
currentIndex = matchIndex + replace.length;
|
|
195
|
+
}
|
|
196
|
+
return { matchCount, content: modifiedContent };
|
|
197
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ToolCallOptions } from "ai";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { TokenCounter } from "../tokens/counter.ts";
|
|
4
|
+
import type { ToolResult } from "./types.ts";
|
|
5
|
+
export declare const GlobTool: {
|
|
6
|
+
name: "globFiles";
|
|
7
|
+
};
|
|
8
|
+
export declare const inputSchema: z.ZodObject<{
|
|
9
|
+
patterns: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
|
|
10
|
+
path: z.ZodString;
|
|
11
|
+
gitignore: z.ZodNullable<z.ZodCoercedBoolean<unknown>>;
|
|
12
|
+
recursive: z.ZodNullable<z.ZodCoercedBoolean<unknown>>;
|
|
13
|
+
expandDirectories: z.ZodNullable<z.ZodCoercedBoolean<unknown>>;
|
|
14
|
+
ignoreFiles: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
15
|
+
cwd: z.ZodNullable<z.ZodCoercedString<unknown>>;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
type GlobInputSchema = z.infer<typeof inputSchema>;
|
|
18
|
+
export declare const createGlobTool: (options: {
|
|
19
|
+
tokenCounter: TokenCounter;
|
|
20
|
+
}) => {
|
|
21
|
+
toolDef: {
|
|
22
|
+
description: string;
|
|
23
|
+
inputSchema: z.ZodObject<{
|
|
24
|
+
patterns: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
|
|
25
|
+
path: z.ZodString;
|
|
26
|
+
gitignore: z.ZodNullable<z.ZodCoercedBoolean<unknown>>;
|
|
27
|
+
recursive: z.ZodNullable<z.ZodCoercedBoolean<unknown>>;
|
|
28
|
+
expandDirectories: z.ZodNullable<z.ZodCoercedBoolean<unknown>>;
|
|
29
|
+
ignoreFiles: z.ZodNullable<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
30
|
+
cwd: z.ZodNullable<z.ZodCoercedString<unknown>>;
|
|
31
|
+
}, z.core.$strip>;
|
|
32
|
+
};
|
|
33
|
+
execute({ patterns, path, gitignore, recursive, expandDirectories, ignoreFiles, cwd, }: GlobInputSchema, { toolCallId, abortSignal }: ToolCallOptions): AsyncGenerator<ToolResult>;
|
|
34
|
+
};
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=glob.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../source/tools/glob.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAC1C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAMzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,eAAO,MAAM,QAAQ;;CAEpB,CAAC;AAEF,eAAO,MAAM,WAAW;;;;;;;;iBA2BtB,CAAC;AAEH,KAAK,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEnD,eAAO,MAAM,cAAc,GAAI,SAAS;IAAE,YAAY,EAAE,YAAY,CAAA;CAAE;;;;;;;;;;;;;4FAkB7D,eAAe,+BACW,eAAe,GAC3C,cAAc,CAAC,UAAU,CAAC;CAmIhC,CAAC"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as nodePath from "node:path";
|
|
3
|
+
import { inspect } from "node:util";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import style from "../terminal/style.js";
|
|
6
|
+
import { manageTokenLimit, TokenLimitExceededError, } from "../tokens/threshold.js";
|
|
7
|
+
import { glob } from "../utils/glob.js";
|
|
8
|
+
export const GlobTool = {
|
|
9
|
+
name: "globFiles",
|
|
10
|
+
};
|
|
11
|
+
export const inputSchema = z.object({
|
|
12
|
+
patterns: z
|
|
13
|
+
.union([z.string(), z.array(z.string())])
|
|
14
|
+
.describe("Glob patterns to search for (e.g., '*.ts', '**/*.test.ts', 'src/**/*.js')"),
|
|
15
|
+
path: z.string().describe("Base directory to search in"),
|
|
16
|
+
gitignore: z.coerce
|
|
17
|
+
.boolean()
|
|
18
|
+
.nullable()
|
|
19
|
+
.describe("Respect ignore patterns in .gitignore files. (default: true)"),
|
|
20
|
+
recursive: z.coerce
|
|
21
|
+
.boolean()
|
|
22
|
+
.nullable()
|
|
23
|
+
.describe("Search recursively. (default: true)"),
|
|
24
|
+
expandDirectories: z.coerce
|
|
25
|
+
.boolean()
|
|
26
|
+
.nullable()
|
|
27
|
+
.describe("Automatically expand directories to files. (default: true)"),
|
|
28
|
+
ignoreFiles: z
|
|
29
|
+
.union([z.string(), z.array(z.string())])
|
|
30
|
+
.nullable()
|
|
31
|
+
.describe("Glob patterns to look for ignore files. (default: undefined)"),
|
|
32
|
+
cwd: z.coerce
|
|
33
|
+
.string()
|
|
34
|
+
.nullable()
|
|
35
|
+
.describe("Current working directory override. (default: process.cwd())"),
|
|
36
|
+
});
|
|
37
|
+
export const createGlobTool = (options) => {
|
|
38
|
+
const { tokenCounter } = options;
|
|
39
|
+
return {
|
|
40
|
+
toolDef: {
|
|
41
|
+
description: "Search for files using glob patterns (e.g., `*.ts`, `**/*.test.ts`, `src/**/*.js`). Uses the fast-glob library with support for gitignore, recursive searching, and directory expansion.",
|
|
42
|
+
inputSchema,
|
|
43
|
+
},
|
|
44
|
+
async *execute({ patterns, path, gitignore, recursive, expandDirectories, ignoreFiles, cwd, }, { toolCallId, abortSignal }) {
|
|
45
|
+
// Check if execution has been aborted
|
|
46
|
+
if (abortSignal?.aborted) {
|
|
47
|
+
throw new Error("Glob search aborted");
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const patternArray = Array.isArray(patterns) ? patterns : [patterns];
|
|
51
|
+
yield {
|
|
52
|
+
name: GlobTool.name,
|
|
53
|
+
event: "tool-init",
|
|
54
|
+
id: toolCallId,
|
|
55
|
+
data: `${style.cyan(inspect(patternArray))} in ${style.cyan(path)}`,
|
|
56
|
+
};
|
|
57
|
+
// Build glob options
|
|
58
|
+
const globOptions = {
|
|
59
|
+
cwd: cwd || process.cwd(),
|
|
60
|
+
};
|
|
61
|
+
if (gitignore !== null) {
|
|
62
|
+
globOptions["gitignore"] = gitignore;
|
|
63
|
+
}
|
|
64
|
+
if (recursive !== null) {
|
|
65
|
+
globOptions["recursive"] = recursive;
|
|
66
|
+
}
|
|
67
|
+
if (expandDirectories !== null) {
|
|
68
|
+
globOptions["expandDirectories"] = expandDirectories;
|
|
69
|
+
}
|
|
70
|
+
if (ignoreFiles !== null) {
|
|
71
|
+
globOptions["ignoreFiles"] = ignoreFiles;
|
|
72
|
+
}
|
|
73
|
+
// Execute glob search
|
|
74
|
+
const matchingFiles = await glob(patternArray, {
|
|
75
|
+
...globOptions,
|
|
76
|
+
cwd: path,
|
|
77
|
+
});
|
|
78
|
+
// Get file stats and sort by recency then alphabetically
|
|
79
|
+
const filesWithStats = await Promise.all(matchingFiles.map(async (filePath) => {
|
|
80
|
+
const fullPath = nodePath.join(path, filePath);
|
|
81
|
+
try {
|
|
82
|
+
const stats = await fs.promises.stat(fullPath);
|
|
83
|
+
return {
|
|
84
|
+
path: filePath,
|
|
85
|
+
mtime: stats.mtime,
|
|
86
|
+
isRecent: Date.now() - stats.mtime.getTime() < 7 * 24 * 60 * 60 * 1000, // 7 days
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// If stat fails, treat as old file
|
|
91
|
+
return {
|
|
92
|
+
path: filePath,
|
|
93
|
+
mtime: new Date(0),
|
|
94
|
+
isRecent: false,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}));
|
|
98
|
+
// Sort files: recent files first (newest to oldest), then older files alphabetically
|
|
99
|
+
const sortedFiles = filesWithStats
|
|
100
|
+
.sort((a, b) => {
|
|
101
|
+
// Recent files come first
|
|
102
|
+
if (a.isRecent && !b.isRecent)
|
|
103
|
+
return -1;
|
|
104
|
+
if (!a.isRecent && b.isRecent)
|
|
105
|
+
return 1;
|
|
106
|
+
// Both recent: sort by modification time (newest first)
|
|
107
|
+
if (a.isRecent && b.isRecent) {
|
|
108
|
+
return b.mtime.getTime() - a.mtime.getTime();
|
|
109
|
+
}
|
|
110
|
+
// Both old: sort alphabetically by path
|
|
111
|
+
return a.path.localeCompare(b.path);
|
|
112
|
+
})
|
|
113
|
+
.map((file) => file.path);
|
|
114
|
+
// Format results
|
|
115
|
+
const resultContent = sortedFiles.length > 0
|
|
116
|
+
? sortedFiles.join("\n")
|
|
117
|
+
: "No files found matching the specified patterns.";
|
|
118
|
+
try {
|
|
119
|
+
const result = await manageTokenLimit(resultContent, tokenCounter, "Glob", "Use more specific glob patterns or recursive=false to reduce matches");
|
|
120
|
+
const completionMessage = `Found ${style.cyan(sortedFiles.length)} files (${result.tokenCount} tokens)`;
|
|
121
|
+
yield {
|
|
122
|
+
name: GlobTool.name,
|
|
123
|
+
event: "tool-completion",
|
|
124
|
+
id: toolCallId,
|
|
125
|
+
data: completionMessage,
|
|
126
|
+
};
|
|
127
|
+
yield result.content;
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
if (error instanceof TokenLimitExceededError) {
|
|
131
|
+
yield {
|
|
132
|
+
name: GlobTool.name,
|
|
133
|
+
event: "tool-error",
|
|
134
|
+
id: toolCallId,
|
|
135
|
+
data: error.message,
|
|
136
|
+
};
|
|
137
|
+
yield error.message;
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
yield {
|
|
145
|
+
name: GlobTool.name,
|
|
146
|
+
event: "tool-error",
|
|
147
|
+
id: toolCallId,
|
|
148
|
+
data: error.message,
|
|
149
|
+
};
|
|
150
|
+
yield error.message;
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
};
|
package/dist/tools/grep.d.ts
CHANGED
|
@@ -1,22 +1,40 @@
|
|
|
1
|
+
import type { ToolCallOptions } from "ai";
|
|
2
|
+
import { z } from "zod";
|
|
1
3
|
import type { TokenCounter } from "../tokens/counter.ts";
|
|
2
|
-
import type {
|
|
4
|
+
import type { ToolResult } from "./types.ts";
|
|
3
5
|
export declare const GrepTool: {
|
|
4
6
|
name: "grepFiles";
|
|
5
7
|
};
|
|
8
|
+
declare const inputSchema: z.ZodObject<{
|
|
9
|
+
pattern: z.ZodString;
|
|
10
|
+
path: z.ZodString;
|
|
11
|
+
recursive: z.ZodNullable<z.ZodCoercedBoolean<unknown>>;
|
|
12
|
+
ignoreCase: z.ZodNullable<z.ZodCoercedBoolean<unknown>>;
|
|
13
|
+
filePattern: z.ZodNullable<z.ZodCoercedString<unknown>>;
|
|
14
|
+
contextLines: z.ZodNullable<z.ZodCoercedNumber<unknown>>;
|
|
15
|
+
searchIgnored: z.ZodNullable<z.ZodCoercedBoolean<unknown>>;
|
|
16
|
+
literal: z.ZodNullable<z.ZodCoercedBoolean<unknown>>;
|
|
17
|
+
maxResults: z.ZodNullable<z.ZodCoercedNumber<unknown>>;
|
|
18
|
+
}, z.core.$strip>;
|
|
19
|
+
type GrepInputSchema = z.infer<typeof inputSchema>;
|
|
6
20
|
export declare const createGrepTool: (options: {
|
|
7
|
-
sendData?: SendData | undefined;
|
|
8
21
|
tokenCounter: TokenCounter;
|
|
9
22
|
}) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
toolDef: {
|
|
24
|
+
description: string;
|
|
25
|
+
inputSchema: z.ZodObject<{
|
|
26
|
+
pattern: z.ZodString;
|
|
27
|
+
path: z.ZodString;
|
|
28
|
+
recursive: z.ZodNullable<z.ZodCoercedBoolean<unknown>>;
|
|
29
|
+
ignoreCase: z.ZodNullable<z.ZodCoercedBoolean<unknown>>;
|
|
30
|
+
filePattern: z.ZodNullable<z.ZodCoercedString<unknown>>;
|
|
31
|
+
contextLines: z.ZodNullable<z.ZodCoercedNumber<unknown>>;
|
|
32
|
+
searchIgnored: z.ZodNullable<z.ZodCoercedBoolean<unknown>>;
|
|
33
|
+
literal: z.ZodNullable<z.ZodCoercedBoolean<unknown>>;
|
|
34
|
+
maxResults: z.ZodNullable<z.ZodCoercedNumber<unknown>>;
|
|
35
|
+
}, z.core.$strip>;
|
|
36
|
+
};
|
|
37
|
+
execute({ pattern, path, recursive, ignoreCase, filePattern, contextLines, searchIgnored, literal, maxResults, }: GrepInputSchema, { toolCallId, abortSignal }: ToolCallOptions): AsyncGenerator<ToolResult>;
|
|
20
38
|
};
|
|
21
39
|
interface GrepOptions {
|
|
22
40
|
recursive?: boolean | null;
|
|
@@ -25,7 +43,9 @@ interface GrepOptions {
|
|
|
25
43
|
contextLines?: number | null;
|
|
26
44
|
searchIgnored?: boolean | null;
|
|
27
45
|
literal?: boolean | null;
|
|
46
|
+
maxResults?: number | null;
|
|
28
47
|
}
|
|
48
|
+
export declare function likelyUnbalancedRegex(pattern: string): boolean;
|
|
29
49
|
/**
|
|
30
50
|
* Search files for patterns using ripgrep
|
|
31
51
|
*
|
|
@@ -35,5 +55,46 @@ interface GrepOptions {
|
|
|
35
55
|
* @returns The result of the grep command
|
|
36
56
|
*/
|
|
37
57
|
export declare function buildGrepCommand(pattern: string, path: string, options?: GrepOptions): string;
|
|
58
|
+
export interface ParsedMatch {
|
|
59
|
+
file?: string;
|
|
60
|
+
line: number;
|
|
61
|
+
content: string;
|
|
62
|
+
isMatch: boolean;
|
|
63
|
+
isContext?: boolean;
|
|
64
|
+
}
|
|
65
|
+
interface GrepResult {
|
|
66
|
+
rawOutput: string;
|
|
67
|
+
parsedMatches: ParsedMatch[];
|
|
68
|
+
matchCount: number;
|
|
69
|
+
displayedCount?: number;
|
|
70
|
+
contextCount: number;
|
|
71
|
+
hasMatches: boolean;
|
|
72
|
+
isTruncated?: boolean;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Parse ripgrep output and extract structured match information
|
|
76
|
+
*/
|
|
77
|
+
export declare function parseRipgrepOutput(content: string): ParsedMatch[];
|
|
78
|
+
/**
|
|
79
|
+
* Count actual matches (excluding context lines)
|
|
80
|
+
*/
|
|
81
|
+
export declare function countActualMatches(parsed: ParsedMatch[]): number;
|
|
82
|
+
/**
|
|
83
|
+
* Count context lines
|
|
84
|
+
*/
|
|
85
|
+
export declare function countContextLines(parsed: ParsedMatch[]): number;
|
|
86
|
+
/**
|
|
87
|
+
* Truncate matches to a maximum number of results
|
|
88
|
+
*/
|
|
89
|
+
export declare function truncateMatches(matches: ParsedMatch[], maxResults: number | null | undefined): {
|
|
90
|
+
truncated: ParsedMatch[];
|
|
91
|
+
isTruncated: boolean;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Extract matches from content (backwards compatibility wrapper)
|
|
95
|
+
*/
|
|
96
|
+
export declare function extractMatches(content: string): string[];
|
|
97
|
+
export declare function grepFiles(pattern: string, path: string, options?: GrepOptions): string;
|
|
98
|
+
export declare function grepFilesStructured(pattern: string, path: string, options?: GrepOptions): GrepResult;
|
|
38
99
|
export {};
|
|
39
100
|
//# sourceMappingURL=grep.d.ts.map
|
package/dist/tools/grep.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grep.d.ts","sourceRoot":"","sources":["../../source/tools/grep.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"grep.d.ts","sourceRoot":"","sources":["../../source/tools/grep.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAC1C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAKzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,eAAO,MAAM,QAAQ;;CAEpB,CAAC;AAEF,QAAA,MAAM,WAAW;;;;;;;;;;iBA2Cf,CAAC;AAEH,KAAK,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEnD,eAAO,MAAM,cAAc,GAAI,SAAS;IAAE,YAAY,EAAE,YAAY,CAAA;CAAE;;;;;;;;;;;;;;;sHAmB7D,eAAe,+BACW,eAAe,GAC3C,cAAc,CAAC,UAAU,CAAC;CAuJhC,CAAC;AAEF,UAAU,WAAW;IACnB,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/B,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAQD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAiI9D;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,WAAgB,GACxB,MAAM,CAmDR;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,UAAU;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,WAAW,EAAE,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,CA4EjE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAEhE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAE/D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,WAAW,EAAE,EACtB,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACpC;IAAE,SAAS,EAAE,WAAW,EAAE,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CA6BpD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAWxD;AAED,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,WAAgB,GACxB,MAAM,CAGR;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,WAAgB,GACxB,UAAU,CAqDZ"}
|