@travisennis/acai 0.0.9 → 0.0.11
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 +51 -760
- package/bin/acai +52 -0
- package/dist/agent/index.d.ts +12 -2
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +380 -199
- package/dist/agent/sub-agent.d.ts +23 -0
- package/dist/agent/sub-agent.d.ts.map +1 -0
- package/dist/agent/sub-agent.js +109 -0
- package/dist/cli/index.d.ts +26 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/{cli.js → cli/index.js} +84 -77
- package/dist/{stdin.d.ts → cli/stdin.d.ts} +2 -1
- package/dist/cli/stdin.d.ts.map +1 -0
- package/dist/{stdin.js → cli/stdin.js} +11 -0
- package/dist/commands/copy/index.js +2 -2
- package/dist/commands/copy/utils.d.ts.map +1 -1
- package/dist/commands/copy/utils.js +15 -13
- package/dist/commands/generate-rules/index.d.ts +1 -1
- package/dist/commands/generate-rules/index.d.ts.map +1 -1
- package/dist/commands/generate-rules/index.js +16 -101
- package/dist/commands/generate-rules/service.d.ts +22 -0
- package/dist/commands/generate-rules/service.d.ts.map +1 -0
- package/dist/commands/generate-rules/service.js +103 -0
- package/dist/commands/handoff/index.js +2 -2
- package/dist/commands/health/index.js +1 -1
- package/dist/commands/health/utils.d.ts +3 -2
- package/dist/commands/health/utils.d.ts.map +1 -1
- package/dist/commands/health/utils.js +6 -0
- package/dist/commands/history/index.d.ts +1 -1
- package/dist/commands/history/index.d.ts.map +1 -1
- package/dist/commands/history/index.js +17 -18
- package/dist/commands/history/types.d.ts +38 -0
- package/dist/commands/history/types.d.ts.map +1 -1
- package/dist/commands/history/utils.d.ts.map +1 -1
- package/dist/commands/history/utils.js +63 -58
- package/dist/commands/init/index.d.ts.map +1 -1
- package/dist/commands/init/index.js +3 -8
- package/dist/commands/init-project/index.d.ts.map +1 -1
- package/dist/commands/init-project/index.js +3 -3
- package/dist/commands/init-project/utils.d.ts +2 -1
- package/dist/commands/init-project/utils.d.ts.map +1 -1
- package/dist/commands/init-project/utils.js +10 -2
- package/dist/commands/list-tools/index.d.ts.map +1 -1
- package/dist/commands/list-tools/index.js +7 -31
- package/dist/commands/manager.d.ts +2 -2
- package/dist/commands/manager.d.ts.map +1 -1
- package/dist/commands/manager.js +55 -33
- package/dist/commands/model/index.d.ts.map +1 -1
- package/dist/commands/model/index.js +20 -151
- package/dist/commands/model/model-panel.d.ts +4 -0
- package/dist/commands/model/model-panel.d.ts.map +1 -0
- package/dist/commands/model/model-panel.js +144 -0
- package/dist/commands/paste/index.d.ts.map +1 -1
- package/dist/commands/paste/index.js +59 -62
- package/dist/commands/paste/utils.d.ts.map +1 -1
- package/dist/commands/paste/utils.js +88 -58
- package/dist/commands/pickup/index.d.ts.map +1 -1
- package/dist/commands/pickup/index.js +6 -3
- package/dist/commands/pickup/utils.js +3 -3
- package/dist/commands/resources/index.d.ts.map +1 -1
- package/dist/commands/resources/index.js +33 -50
- package/dist/commands/review/index.d.ts.map +1 -1
- package/dist/commands/review/index.js +3 -117
- package/dist/commands/review/review-panel.d.ts +3 -0
- package/dist/commands/review/review-panel.d.ts.map +1 -0
- package/dist/commands/review/review-panel.js +186 -0
- package/dist/commands/review/utils.d.ts +15 -1
- package/dist/commands/review/utils.d.ts.map +1 -1
- package/dist/commands/review/utils.js +127 -68
- package/dist/commands/session/index.d.ts +1 -1
- package/dist/commands/session/index.d.ts.map +1 -1
- package/dist/commands/session/index.js +124 -135
- package/dist/commands/shell/index.d.ts.map +1 -1
- package/dist/commands/shell/index.js +16 -1
- package/dist/commands/types.d.ts +2 -2
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/{config.d.ts → config/index.d.ts} +20 -9
- package/dist/config/index.d.ts.map +1 -0
- package/dist/{config.js → config/index.js} +43 -42
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/index.js +75 -55
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +148 -141
- package/dist/middleware/cache.d.ts.map +1 -1
- package/dist/middleware/cache.js +18 -36
- package/dist/models/ai-config.d.ts +1 -0
- package/dist/models/ai-config.d.ts.map +1 -1
- package/dist/models/ai-config.js +4 -3
- package/dist/models/anthropic-provider.d.ts +2 -5
- package/dist/models/anthropic-provider.d.ts.map +1 -1
- package/dist/models/anthropic-provider.js +3 -70
- package/dist/models/deepseek-provider.d.ts +1 -0
- package/dist/models/deepseek-provider.d.ts.map +1 -1
- package/dist/models/google-provider.d.ts +2 -3
- package/dist/models/google-provider.d.ts.map +1 -1
- package/dist/models/google-provider.js +0 -26
- package/dist/models/groq-provider.d.ts +1 -0
- package/dist/models/groq-provider.d.ts.map +1 -1
- package/dist/models/manager.d.ts +13 -2
- package/dist/models/manager.d.ts.map +1 -1
- package/dist/models/manager.js +20 -8
- package/dist/models/openai-provider.d.ts +2 -5
- package/dist/models/openai-provider.d.ts.map +1 -1
- package/dist/models/openai-provider.js +0 -52
- package/dist/models/opencode-go-provider.d.ts +25 -0
- package/dist/models/opencode-go-provider.d.ts.map +1 -0
- package/dist/models/opencode-go-provider.js +78 -0
- package/dist/models/opencode-zen-provider.d.ts +7 -3
- package/dist/models/opencode-zen-provider.d.ts.map +1 -1
- package/dist/models/opencode-zen-provider.js +49 -10
- package/dist/models/openrouter-provider.d.ts +27 -31
- package/dist/models/openrouter-provider.d.ts.map +1 -1
- package/dist/models/openrouter-provider.js +121 -180
- package/dist/models/providers.d.ts +3 -3
- package/dist/models/providers.d.ts.map +1 -1
- package/dist/models/providers.js +6 -0
- package/dist/models/xai-provider.d.ts +4 -3
- package/dist/models/xai-provider.d.ts.map +1 -1
- package/dist/models/xai-provider.js +18 -18
- package/dist/modes/manager.d.ts +24 -0
- package/dist/modes/manager.d.ts.map +1 -0
- package/dist/modes/manager.js +77 -0
- package/dist/modes/prompts.d.ts +2 -0
- package/dist/modes/prompts.d.ts.map +1 -0
- package/dist/modes/prompts.js +142 -0
- package/dist/prompts/mentions.d.ts +11 -0
- package/dist/prompts/mentions.d.ts.map +1 -0
- package/dist/{mentions.js → prompts/mentions.js} +55 -85
- package/dist/{prompts.d.ts → prompts/system-prompt.d.ts} +7 -2
- package/dist/prompts/system-prompt.d.ts.map +1 -0
- package/dist/{prompts.js → prompts/system-prompt.js} +31 -16
- package/dist/repl/index.d.ts +174 -0
- package/dist/repl/index.d.ts.map +1 -0
- package/dist/{repl-new.js → repl/index.js} +397 -76
- package/dist/repl/project-status.d.ts +1 -0
- package/dist/repl/project-status.d.ts.map +1 -1
- package/dist/repl/project-status.js +4 -1
- package/dist/sessions/manager.d.ts +92 -0
- package/dist/sessions/manager.d.ts.map +1 -1
- package/dist/sessions/manager.js +262 -9
- package/dist/sessions/summary.d.ts +4 -0
- package/dist/sessions/summary.d.ts.map +1 -0
- package/dist/sessions/summary.js +30 -0
- package/dist/skills/index.d.ts +29 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +294 -0
- package/dist/subagents/index.d.ts +16 -0
- package/dist/subagents/index.d.ts.map +1 -0
- package/dist/subagents/index.js +231 -0
- package/dist/terminal/control.d.ts +1 -1
- package/dist/terminal/control.d.ts.map +1 -1
- package/dist/terminal/control.js +3 -3
- package/dist/terminal/east-asian-width.d.ts.map +1 -1
- package/dist/terminal/east-asian-width.js +404 -351
- package/dist/terminal/keys.d.ts +17 -0
- package/dist/terminal/keys.d.ts.map +1 -1
- package/dist/terminal/keys.js +37 -0
- package/dist/terminal/select-prompt.d.ts.map +1 -1
- package/dist/terminal/select-prompt.js +24 -12
- package/dist/terminal/string-width.d.ts.map +1 -1
- package/dist/terminal/string-width.js +25 -27
- package/dist/terminal/style.d.ts.map +1 -1
- package/dist/terminal/style.js +4 -7
- package/dist/terminal/supports-color.d.ts.map +1 -1
- package/dist/terminal/supports-color.js +41 -27
- package/dist/terminal/table/cell.d.ts +12 -0
- package/dist/terminal/table/cell.d.ts.map +1 -1
- package/dist/terminal/table/cell.js +40 -25
- package/dist/terminal/table/layout-manager.d.ts.map +1 -1
- package/dist/terminal/table/layout-manager.js +100 -68
- package/dist/terminal/table/utils.d.ts +1 -1
- package/dist/terminal/table/utils.d.ts.map +1 -1
- package/dist/terminal/table/utils.js +17 -10
- package/dist/terminal/wrap-ansi.d.ts.map +1 -1
- package/dist/terminal/wrap-ansi.js +174 -105
- package/dist/tokens/tracker.d.ts +1 -0
- package/dist/tokens/tracker.d.ts.map +1 -1
- package/dist/tokens/tracker.js +3 -0
- package/dist/tools/agent.d.ts +27 -0
- package/dist/tools/agent.d.ts.map +1 -0
- package/dist/tools/agent.js +81 -0
- package/dist/tools/apply-patch.d.ts +62 -0
- package/dist/tools/apply-patch.d.ts.map +1 -0
- package/dist/tools/apply-patch.js +377 -0
- package/dist/tools/bash.d.ts +4 -3
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +349 -141
- package/dist/tools/directory-tree.d.ts +3 -3
- package/dist/tools/directory-tree.d.ts.map +1 -1
- package/dist/tools/directory-tree.js +8 -5
- package/dist/tools/dynamic-tool-loader.d.ts +3 -6
- package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
- package/dist/tools/dynamic-tool-loader.js +20 -4
- package/dist/tools/edit-file.d.ts +7 -7
- package/dist/tools/edit-file.d.ts.map +1 -1
- package/dist/tools/edit-file.js +292 -85
- package/dist/tools/glob.d.ts +6 -6
- package/dist/tools/glob.d.ts.map +1 -1
- package/dist/tools/glob.js +110 -63
- package/dist/tools/grep.d.ts +15 -12
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +315 -193
- package/dist/tools/index.d.ts +114 -9
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +39 -24
- package/dist/tools/ls.d.ts +2 -2
- package/dist/tools/ls.d.ts.map +1 -1
- package/dist/tools/ls.js +7 -5
- package/dist/tools/read-file.d.ts +4 -6
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +84 -39
- package/dist/tools/save-file.d.ts +3 -3
- package/dist/tools/save-file.d.ts.map +1 -1
- package/dist/tools/save-file.js +36 -31
- package/dist/tools/skill.d.ts +23 -0
- package/dist/tools/skill.d.ts.map +1 -0
- package/dist/tools/skill.js +65 -0
- package/dist/tools/think.d.ts.map +1 -1
- package/dist/tools/think.js +2 -9
- package/dist/tools/utils.d.ts +2 -0
- package/dist/tools/utils.d.ts.map +1 -1
- package/dist/tools/utils.js +12 -0
- package/dist/tools/web-fetch.d.ts +50 -0
- package/dist/tools/web-fetch.d.ts.map +1 -0
- package/dist/tools/web-fetch.js +446 -0
- package/dist/tools/web-search.d.ts +44 -0
- package/dist/tools/web-search.d.ts.map +1 -0
- package/dist/tools/web-search.js +226 -0
- package/dist/tui/autocomplete/attachment-provider.d.ts +3 -6
- package/dist/tui/autocomplete/attachment-provider.d.ts.map +1 -1
- package/dist/tui/autocomplete/attachment-provider.js +25 -78
- package/dist/tui/autocomplete/base-provider.d.ts +1 -0
- package/dist/tui/autocomplete/base-provider.d.ts.map +1 -1
- package/dist/tui/autocomplete/combined-provider.d.ts +1 -4
- package/dist/tui/autocomplete/combined-provider.d.ts.map +1 -1
- package/dist/tui/autocomplete/combined-provider.js +3 -17
- package/dist/tui/autocomplete/command-provider.d.ts +1 -0
- package/dist/tui/autocomplete/command-provider.d.ts.map +1 -1
- package/dist/tui/autocomplete/command-provider.js +3 -0
- package/dist/tui/autocomplete/file-search-provider.d.ts +2 -1
- package/dist/tui/autocomplete/file-search-provider.d.ts.map +1 -1
- package/dist/tui/autocomplete/file-search-provider.js +37 -17
- package/dist/tui/autocomplete/skill-provider.d.ts +17 -0
- package/dist/tui/autocomplete/skill-provider.d.ts.map +1 -0
- package/dist/tui/autocomplete/skill-provider.js +49 -0
- package/dist/tui/autocomplete/utils.d.ts +2 -1
- package/dist/tui/autocomplete/utils.d.ts.map +1 -1
- package/dist/tui/autocomplete/utils.js +25 -23
- package/dist/tui/autocomplete.d.ts +2 -2
- package/dist/tui/autocomplete.d.ts.map +1 -1
- package/dist/tui/autocomplete.js +3 -5
- package/dist/tui/components/assistant-message.d.ts.map +1 -1
- package/dist/tui/components/assistant-message.js +0 -4
- package/dist/tui/components/editor.d.ts +18 -3
- package/dist/tui/components/editor.d.ts.map +1 -1
- package/dist/tui/components/editor.js +211 -237
- package/dist/tui/components/footer.d.ts +6 -4
- package/dist/tui/components/footer.d.ts.map +1 -1
- package/dist/tui/components/footer.js +49 -25
- package/dist/tui/components/markdown.d.ts +10 -7
- package/dist/tui/components/markdown.d.ts.map +1 -1
- package/dist/tui/components/markdown.js +57 -39
- package/dist/tui/components/modal.d.ts.map +1 -1
- package/dist/tui/components/modal.js +35 -33
- package/dist/tui/components/notification.d.ts +13 -2
- package/dist/tui/components/notification.d.ts.map +1 -1
- package/dist/tui/components/notification.js +36 -2
- package/dist/tui/components/progress-bar.js +1 -1
- package/dist/tui/components/select-list.d.ts +1 -0
- package/dist/tui/components/select-list.d.ts.map +1 -1
- package/dist/tui/components/select-list.js +14 -11
- package/dist/tui/components/text.d.ts +16 -0
- package/dist/tui/components/text.d.ts.map +1 -1
- package/dist/tui/components/text.js +72 -57
- package/dist/tui/components/thinking-block.d.ts +9 -0
- package/dist/tui/components/thinking-block.d.ts.map +1 -1
- package/dist/tui/components/thinking-block.js +43 -11
- package/dist/tui/components/tool-execution.d.ts +5 -1
- package/dist/tui/components/tool-execution.d.ts.map +1 -1
- package/dist/tui/components/tool-execution.js +19 -10
- package/dist/tui/components/user-message.d.ts.map +1 -1
- package/dist/tui/components/user-message.js +0 -3
- package/dist/tui/components/welcome.d.ts +2 -1
- package/dist/tui/components/welcome.d.ts.map +1 -1
- package/dist/tui/components/welcome.js +2 -2
- package/dist/tui/editor-launcher.d.ts +3 -2
- package/dist/tui/editor-launcher.d.ts.map +1 -1
- package/dist/tui/index.d.ts +0 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/terminal.d.ts.map +1 -1
- package/dist/tui/terminal.js +10 -2
- package/dist/tui/tui.d.ts +43 -0
- package/dist/tui/tui.d.ts.map +1 -1
- package/dist/tui/tui.js +166 -41
- package/dist/tui/utils.d.ts +1 -5
- package/dist/tui/utils.d.ts.map +1 -1
- package/dist/tui/utils.js +271 -44
- package/dist/utils/bash/parse.d.ts +19 -0
- package/dist/utils/bash/parse.d.ts.map +1 -0
- package/dist/utils/bash/parse.js +223 -0
- package/dist/utils/bash/quote.d.ts +6 -0
- package/dist/utils/bash/quote.d.ts.map +1 -0
- package/dist/utils/bash/quote.js +23 -0
- package/dist/utils/bash.d.ts.map +1 -1
- package/dist/utils/bash.js +211 -126
- package/dist/utils/command-protection.d.ts +28 -0
- package/dist/utils/command-protection.d.ts.map +1 -0
- package/dist/utils/command-protection.js +324 -0
- package/dist/utils/dedent.d.ts.map +1 -0
- package/dist/utils/env-expand.d.ts +2 -0
- package/dist/utils/env-expand.d.ts.map +1 -0
- package/dist/utils/env-expand.js +8 -0
- package/dist/utils/filesystem/path-display.d.ts +11 -0
- package/dist/utils/filesystem/path-display.d.ts.map +1 -0
- package/dist/utils/filesystem/path-display.js +32 -0
- package/dist/utils/filesystem/security.d.ts +2 -2
- package/dist/utils/filesystem/security.d.ts.map +1 -1
- package/dist/utils/filesystem/security.js +28 -30
- package/dist/utils/formatting.d.ts.map +1 -0
- package/dist/{formatting.js → utils/formatting.js} +1 -1
- package/dist/utils/git.d.ts +4 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +30 -0
- package/dist/utils/glob.d.ts +1 -1
- package/dist/utils/glob.d.ts.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/{logger.js → utils/logger.js} +1 -1
- package/dist/utils/parsing.d.ts.map +1 -0
- package/dist/utils/process.d.ts.map +1 -1
- package/dist/utils/process.js +90 -37
- package/dist/utils/templates.d.ts +2 -0
- package/dist/utils/templates.d.ts.map +1 -0
- package/dist/utils/templates.js +24 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/{version.js → utils/version.js} +1 -1
- package/package.json +35 -26
- package/dist/cli.d.ts +0 -23
- package/dist/cli.d.ts.map +0 -1
- package/dist/commands/add-directory/types.d.ts +0 -6
- package/dist/commands/add-directory/types.d.ts.map +0 -1
- package/dist/commands/add-directory/types.js +0 -1
- package/dist/commands/copy/types.d.ts +0 -3
- package/dist/commands/copy/types.d.ts.map +0 -1
- package/dist/commands/copy/types.js +0 -1
- package/dist/commands/exit/index.d.ts +0 -10
- package/dist/commands/exit/index.d.ts.map +0 -1
- package/dist/commands/exit/index.js +0 -21
- package/dist/commands/exit/types.d.ts +0 -8
- package/dist/commands/exit/types.d.ts.map +0 -1
- package/dist/commands/exit/types.js +0 -1
- package/dist/commands/exit/utils.d.ts +0 -2
- package/dist/commands/exit/utils.d.ts.map +0 -1
- package/dist/commands/exit/utils.js +0 -13
- package/dist/commands/prompt/index.d.ts +0 -5
- package/dist/commands/prompt/index.d.ts.map +0 -1
- package/dist/commands/prompt/index.js +0 -122
- package/dist/commands/prompt/types.d.ts +0 -15
- package/dist/commands/prompt/types.d.ts.map +0 -1
- package/dist/commands/prompt/types.js +0 -1
- package/dist/commands/prompt/utils.d.ts +0 -12
- package/dist/commands/prompt/utils.d.ts.map +0 -1
- package/dist/commands/prompt/utils.js +0 -107
- package/dist/commands/reset/index.d.ts +0 -3
- package/dist/commands/reset/index.d.ts.map +0 -1
- package/dist/commands/reset/index.js +0 -25
- package/dist/commands/reset/types.d.ts +0 -1
- package/dist/commands/reset/types.d.ts.map +0 -1
- package/dist/commands/reset/types.js +0 -3
- package/dist/commands/review/types.d.ts +0 -12
- package/dist/commands/review/types.d.ts.map +0 -1
- package/dist/commands/review/types.js +0 -1
- package/dist/commands/save/index.d.ts +0 -3
- package/dist/commands/save/index.d.ts.map +0 -1
- package/dist/commands/save/index.js +0 -19
- package/dist/config.d.ts.map +0 -1
- package/dist/dedent.d.ts.map +0 -1
- package/dist/formatting.d.ts.map +0 -1
- package/dist/logger.d.ts.map +0 -1
- package/dist/mentions.d.ts +0 -14
- package/dist/mentions.d.ts.map +0 -1
- package/dist/parsing.d.ts.map +0 -1
- package/dist/prompts.d.ts.map +0 -1
- package/dist/repl-new.d.ts +0 -65
- package/dist/repl-new.d.ts.map +0 -1
- package/dist/skills.d.ts +0 -16
- package/dist/skills.d.ts.map +0 -1
- package/dist/skills.js +0 -233
- package/dist/stdin.d.ts.map +0 -1
- package/dist/tui/autocomplete/path-provider.d.ts +0 -21
- package/dist/tui/autocomplete/path-provider.d.ts.map +0 -1
- package/dist/tui/autocomplete/path-provider.js +0 -164
- package/dist/utils/iterables.d.ts +0 -2
- package/dist/utils/iterables.d.ts.map +0 -1
- package/dist/utils/iterables.js +0 -6
- package/dist/version.d.ts.map +0 -1
- /package/dist/{dedent.d.ts → utils/dedent.d.ts} +0 -0
- /package/dist/{dedent.js → utils/dedent.js} +0 -0
- /package/dist/{formatting.d.ts → utils/formatting.d.ts} +0 -0
- /package/dist/{logger.d.ts → utils/logger.d.ts} +0 -0
- /package/dist/{parsing.d.ts → utils/parsing.d.ts} +0 -0
- /package/dist/{parsing.js → utils/parsing.js} +0 -0
- /package/dist/{version.d.ts → utils/version.d.ts} +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ToolExecutionOptions } from "./types.ts";
|
|
3
|
+
export declare const WebSearchTool: {
|
|
4
|
+
name: "WebSearch";
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Input schema for the web search tool
|
|
8
|
+
*/
|
|
9
|
+
declare const inputSchema: z.ZodObject<{
|
|
10
|
+
query: z.ZodString;
|
|
11
|
+
numResults: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | null, unknown>, z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
12
|
+
timeout: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | null, unknown>, z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
13
|
+
provider: z.ZodOptional<z.ZodEnum<{
|
|
14
|
+
exa: "exa";
|
|
15
|
+
duckduckgo: "duckduckgo";
|
|
16
|
+
}>>;
|
|
17
|
+
}, z.core.$strip>;
|
|
18
|
+
type WebSearchInputSchema = z.infer<typeof inputSchema>;
|
|
19
|
+
/**
|
|
20
|
+
* Execute web search
|
|
21
|
+
*/
|
|
22
|
+
export declare function executeWebSearch(options: WebSearchInputSchema, executionOptions: ToolExecutionOptions): Promise<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Create the web search tool
|
|
25
|
+
*/
|
|
26
|
+
export declare const createWebSearchTool: () => Promise<{
|
|
27
|
+
toolDef: {
|
|
28
|
+
description: string;
|
|
29
|
+
inputSchema: z.ZodObject<{
|
|
30
|
+
query: z.ZodString;
|
|
31
|
+
numResults: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | null, unknown>, z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
32
|
+
timeout: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | null, unknown>, z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
33
|
+
provider: z.ZodOptional<z.ZodEnum<{
|
|
34
|
+
exa: "exa";
|
|
35
|
+
duckduckgo: "duckduckgo";
|
|
36
|
+
}>>;
|
|
37
|
+
}, z.core.$strip>;
|
|
38
|
+
};
|
|
39
|
+
display({ query }: WebSearchInputSchema): string;
|
|
40
|
+
execute(options: WebSearchInputSchema, executionOptions: ToolExecutionOptions): Promise<string>;
|
|
41
|
+
}>;
|
|
42
|
+
export type WebSearchTool = Awaited<ReturnType<typeof createWebSearchTool>>;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=web-search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-search.d.ts","sourceRoot":"","sources":["../../source/tools/web-search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,eAAO,MAAM,aAAa;;CAEzB,CAAC;AAQF;;GAEG;AACH,QAAA,MAAM,WAAW;;;;;;;;iBAkBf,CAAC;AAEH,KAAK,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AA+MxD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,oBAAoB,EAC7B,gBAAgB,EAAE,oBAAoB,GACrC,OAAO,CAAC,MAAM,CAAC,CAwEjB;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;uBAQT,oBAAoB;qBAI5B,oBAAoB,oBACX,oBAAoB,GACrC,OAAO,CAAC,MAAM,CAAC;EAIrB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import style from "../terminal/style.js";
|
|
3
|
+
export const WebSearchTool = {
|
|
4
|
+
name: "WebSearch",
|
|
5
|
+
};
|
|
6
|
+
// Default search options
|
|
7
|
+
const DEFAULT_NUM_RESULTS = 10;
|
|
8
|
+
const DEFAULT_TIMEOUT = 30000; // 30 seconds
|
|
9
|
+
const EXA_API_BASE = "https://api.exa.ai";
|
|
10
|
+
const EXA_API_VERSION = "2024-05-22";
|
|
11
|
+
/**
|
|
12
|
+
* Input schema for the web search tool
|
|
13
|
+
*/
|
|
14
|
+
const inputSchema = z.object({
|
|
15
|
+
query: z.string().describe("The search query to execute"),
|
|
16
|
+
numResults: z
|
|
17
|
+
.preprocess((val) => convertNullString(val), z.coerce.number().nullable())
|
|
18
|
+
.optional()
|
|
19
|
+
.describe(`Number of search results to return (default: ${DEFAULT_NUM_RESULTS}, max: 100)`),
|
|
20
|
+
timeout: z
|
|
21
|
+
.preprocess((val) => convertNullString(val), z.coerce.number().nullable())
|
|
22
|
+
.optional()
|
|
23
|
+
.describe(`Timeout in milliseconds for the search request (default: ${DEFAULT_TIMEOUT}ms)`),
|
|
24
|
+
provider: z
|
|
25
|
+
.enum(["exa", "duckduckgo"])
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("Search provider to use (default: exa with duckduckgo fallback)"),
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Convert null/undefined to string for preprocessing
|
|
31
|
+
*/
|
|
32
|
+
function convertNullString(val) {
|
|
33
|
+
if (val === null ||
|
|
34
|
+
val === undefined ||
|
|
35
|
+
val === "null" ||
|
|
36
|
+
val === "undefined") {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return String(val);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Factory function for creating abort handlers.
|
|
43
|
+
* Defined at module level to avoid capturing closure scope.
|
|
44
|
+
*/
|
|
45
|
+
function createAbortHandler(ctrl, signal) {
|
|
46
|
+
return () => {
|
|
47
|
+
ctrl.abort(signal?.reason ?? new Error("Aborted"));
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Create an AbortSignal that combines a timeout with an optional parent signal
|
|
52
|
+
*/
|
|
53
|
+
function createTimeoutSignal(timeoutMs, parentSignal) {
|
|
54
|
+
const controller = new AbortController();
|
|
55
|
+
// Use bind() to avoid capturing scope in timeout callback
|
|
56
|
+
const abort = controller.abort.bind(controller);
|
|
57
|
+
const timeoutId = setTimeout(() => abort(new Error(`Request timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
58
|
+
// Create abort handler using factory to avoid capturing scope
|
|
59
|
+
const abortHandler = createAbortHandler(controller, parentSignal);
|
|
60
|
+
if (parentSignal) {
|
|
61
|
+
if (parentSignal.aborted) {
|
|
62
|
+
abortHandler();
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
parentSignal.addEventListener("abort", abortHandler, { once: true });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
signal: controller.signal,
|
|
70
|
+
cleanup: () => {
|
|
71
|
+
clearTimeout(timeoutId);
|
|
72
|
+
if (parentSignal) {
|
|
73
|
+
parentSignal.removeEventListener("abort", abortHandler);
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Fetch from Exa API
|
|
80
|
+
*/
|
|
81
|
+
async function fetchExa(query, numResults, signal) {
|
|
82
|
+
const apiKey = process.env["EXA_API_KEY"];
|
|
83
|
+
if (!apiKey) {
|
|
84
|
+
throw new Error("EXA_API_KEY environment variable is not set. Please set it to use Exa API.");
|
|
85
|
+
}
|
|
86
|
+
const response = await fetch(`${EXA_API_BASE}/search`, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: {
|
|
89
|
+
"Content-Type": "application/json",
|
|
90
|
+
"x-api-key": apiKey,
|
|
91
|
+
"exa-version": EXA_API_VERSION,
|
|
92
|
+
},
|
|
93
|
+
body: JSON.stringify({
|
|
94
|
+
query,
|
|
95
|
+
numResults,
|
|
96
|
+
}),
|
|
97
|
+
signal,
|
|
98
|
+
});
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
const errorText = await response.text();
|
|
101
|
+
throw new Error(`Exa API error: ${response.status} - ${errorText}`);
|
|
102
|
+
}
|
|
103
|
+
const data = await response.json();
|
|
104
|
+
return {
|
|
105
|
+
results: data.results.map((result) => ({
|
|
106
|
+
title: result.title,
|
|
107
|
+
url: result.url,
|
|
108
|
+
snippet: result.body,
|
|
109
|
+
publishedDate: result.publishedDate,
|
|
110
|
+
})),
|
|
111
|
+
provider: "exa",
|
|
112
|
+
query,
|
|
113
|
+
totalResults: data.results.length,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Fetch from DuckDuckGo API (using their instant answer API)
|
|
118
|
+
*/
|
|
119
|
+
async function fetchDuckDuckGo(query, numResults, signal) {
|
|
120
|
+
const encodedQuery = encodeURIComponent(query);
|
|
121
|
+
const response = await fetch(`https://api.duckduckgo.com/?q=${encodedQuery}&format=json&no_html=1&skip_disambig=1`, { signal });
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
throw new Error(`DuckDuckGo API error: ${response.status} - ${response.statusText}`);
|
|
124
|
+
}
|
|
125
|
+
const data = await response.json();
|
|
126
|
+
if (!data.RelatedTopics || data.RelatedTopics.length === 0) {
|
|
127
|
+
return {
|
|
128
|
+
results: [],
|
|
129
|
+
provider: "duckduckgo",
|
|
130
|
+
query,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const results = data.RelatedTopics.slice(0, numResults)
|
|
134
|
+
// biome-ignore lint/style/useNamingConvention: DuckDuckGo API response uses PascalCase
|
|
135
|
+
.filter((topic) => topic.Result)
|
|
136
|
+
.map((topic) => {
|
|
137
|
+
// Parse the result format: "<a>Title</a> - Description"
|
|
138
|
+
const resultHtml = topic.Result || "";
|
|
139
|
+
const titleMatch = resultHtml.match(/>([^<]+)</);
|
|
140
|
+
const title = titleMatch ? titleMatch[1] : "No title";
|
|
141
|
+
return {
|
|
142
|
+
title,
|
|
143
|
+
url: topic.FirstURL || "",
|
|
144
|
+
snippet: topic.Text || "",
|
|
145
|
+
};
|
|
146
|
+
});
|
|
147
|
+
return {
|
|
148
|
+
results,
|
|
149
|
+
provider: "duckduckgo",
|
|
150
|
+
query,
|
|
151
|
+
totalResults: data.RelatedTopics.length,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Execute web search
|
|
156
|
+
*/
|
|
157
|
+
export async function executeWebSearch(options, executionOptions) {
|
|
158
|
+
const { query, numResults = DEFAULT_NUM_RESULTS, timeout = DEFAULT_TIMEOUT, provider = "exa", } = options;
|
|
159
|
+
if (executionOptions.abortSignal?.aborted) {
|
|
160
|
+
throw new Error("Web search aborted");
|
|
161
|
+
}
|
|
162
|
+
if (!query || query.trim().length === 0) {
|
|
163
|
+
throw new Error("Search query cannot be empty");
|
|
164
|
+
}
|
|
165
|
+
const effectiveNumResults = Math.min(Math.max(numResults ?? 1, 1), 100);
|
|
166
|
+
const effectiveTimeout = Math.min(Math.max(timeout ?? 1000, 1000), 60000);
|
|
167
|
+
const { signal, cleanup } = createTimeoutSignal(effectiveTimeout, executionOptions.abortSignal);
|
|
168
|
+
try {
|
|
169
|
+
let response;
|
|
170
|
+
if (provider === "duckduckgo") {
|
|
171
|
+
response = await fetchDuckDuckGo(query, effectiveNumResults, signal);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
// Try Exa first, fall back to DuckDuckGo
|
|
175
|
+
try {
|
|
176
|
+
response = await fetchExa(query, effectiveNumResults, signal);
|
|
177
|
+
}
|
|
178
|
+
catch (exaError) {
|
|
179
|
+
// Fall back to DuckDuckGo if Exa fails (but not if aborted)
|
|
180
|
+
if (signal.aborted) {
|
|
181
|
+
throw exaError;
|
|
182
|
+
}
|
|
183
|
+
// Provide more helpful error message about Exa failure
|
|
184
|
+
const errorMsg = exaError instanceof Error ? exaError.message : String(exaError);
|
|
185
|
+
if (errorMsg.includes("fetch failed") ||
|
|
186
|
+
errorMsg.includes("ENOTFOUND") ||
|
|
187
|
+
errorMsg.includes("connect")) {
|
|
188
|
+
throw new Error(`Exa API is not accessible (network error). Try using provider="duckduckgo" instead.`);
|
|
189
|
+
}
|
|
190
|
+
response = await fetchDuckDuckGo(query, effectiveNumResults, signal);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (response.results.length === 0) {
|
|
194
|
+
return `No search results found for "${query}".`;
|
|
195
|
+
}
|
|
196
|
+
const resultsText = response.results
|
|
197
|
+
.map((result, index) => `${index + 1}. [${result.title}](${result.url})\n ${result.snippet.substring(0, 200)}${result.snippet.length > 200 ? "..." : ""}`)
|
|
198
|
+
.join("\n\n");
|
|
199
|
+
return `Search results for "${query}" (${response.provider}):\n\n${resultsText}\n\nTotal results: ${response.totalResults || response.results.length}`;
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
203
|
+
throw new Error(`Web search failed: ${errorMessage}`);
|
|
204
|
+
}
|
|
205
|
+
finally {
|
|
206
|
+
cleanup();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Create the web search tool
|
|
211
|
+
*/
|
|
212
|
+
export const createWebSearchTool = async () => {
|
|
213
|
+
const toolDescription = "Search the web for information.";
|
|
214
|
+
return {
|
|
215
|
+
toolDef: {
|
|
216
|
+
description: toolDescription,
|
|
217
|
+
inputSchema,
|
|
218
|
+
},
|
|
219
|
+
display({ query }) {
|
|
220
|
+
return `🔍 ${style.cyan(query)}`;
|
|
221
|
+
},
|
|
222
|
+
async execute(options, executionOptions) {
|
|
223
|
+
return executeWebSearch(options, executionOptions);
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AutocompleteItem } from "./base-provider.ts";
|
|
2
|
-
import {
|
|
3
|
-
export declare class AttachmentProvider extends
|
|
2
|
+
import { FileSearchProvider } from "./file-search-provider.ts";
|
|
3
|
+
export declare class AttachmentProvider extends FileSearchProvider {
|
|
4
|
+
matchesContext(textBeforeCursor: string): boolean;
|
|
4
5
|
getSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<{
|
|
5
6
|
items: AutocompleteItem[];
|
|
6
7
|
prefix: string;
|
|
@@ -10,9 +11,5 @@ export declare class AttachmentProvider extends PathProvider {
|
|
|
10
11
|
cursorLine: number;
|
|
11
12
|
cursorCol: number;
|
|
12
13
|
};
|
|
13
|
-
getForceFileSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<{
|
|
14
|
-
items: AutocompleteItem[];
|
|
15
|
-
prefix: string;
|
|
16
|
-
} | null>;
|
|
17
14
|
}
|
|
18
15
|
//# sourceMappingURL=attachment-provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attachment-provider.d.ts","sourceRoot":"","sources":["../../../source/tui/autocomplete/attachment-provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"attachment-provider.d.ts","sourceRoot":"","sources":["../../../source/tui/autocomplete/attachment-provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,qBAAa,kBAAmB,SAAQ,kBAAkB;IAC/C,cAAc,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO;IAI3C,cAAc,CAC3B,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IA8BvD,eAAe,CACtB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACb;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;CAmB9D"}
|
|
@@ -1,103 +1,50 @@
|
|
|
1
1
|
import { extname } from "node:path";
|
|
2
|
-
import {
|
|
3
|
-
export class AttachmentProvider extends
|
|
2
|
+
import { FileSearchProvider } from "./file-search-provider.js";
|
|
3
|
+
export class AttachmentProvider extends FileSearchProvider {
|
|
4
|
+
matchesContext(textBeforeCursor) {
|
|
5
|
+
return /(?:^|\s)#[^\s]*$/.test(textBeforeCursor);
|
|
6
|
+
}
|
|
4
7
|
async getSuggestions(lines, cursorLine, cursorCol) {
|
|
5
8
|
const currentLine = lines[cursorLine] || "";
|
|
6
9
|
const textBeforeCursor = currentLine.slice(0, cursorCol);
|
|
7
|
-
|
|
8
|
-
const pathMatch = textBeforeCursor.match(/@([^\s]*)$/);
|
|
10
|
+
const pathMatch = textBeforeCursor.match(/#([^\s]*)$/);
|
|
9
11
|
if (!pathMatch) {
|
|
10
12
|
return null;
|
|
11
13
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
prefix = prefix.slice(1); // Remove the @
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
const suggestions = await this.getFileSuggestions(prefix);
|
|
14
|
+
const prefix = pathMatch[0];
|
|
15
|
+
const searchTerm = pathMatch[1];
|
|
16
|
+
const suggestions = await this.searchFiles(searchTerm);
|
|
21
17
|
if (suggestions.length === 0)
|
|
22
18
|
return null;
|
|
23
|
-
|
|
24
|
-
const filteredSuggestions = [];
|
|
25
|
-
for (const suggestion of suggestions) {
|
|
26
|
-
if (!suggestion.value.endsWith("/") &&
|
|
27
|
-
!isAttachableFile(suggestion.value)) {
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
suggestion.value = `@${suggestion.value}`;
|
|
31
|
-
filteredSuggestions.push(suggestion);
|
|
32
|
-
}
|
|
19
|
+
const filteredSuggestions = suggestions.filter((s) => isAttachableFile(s.value));
|
|
33
20
|
if (filteredSuggestions.length === 0)
|
|
34
21
|
return null;
|
|
22
|
+
for (const suggestion of filteredSuggestions) {
|
|
23
|
+
suggestion.value = `#${suggestion.value}`;
|
|
24
|
+
}
|
|
35
25
|
return {
|
|
36
26
|
items: filteredSuggestions,
|
|
37
|
-
prefix
|
|
27
|
+
prefix,
|
|
38
28
|
};
|
|
39
29
|
}
|
|
40
30
|
applyCompletion(lines, cursorLine, cursorCol, item, prefix) {
|
|
31
|
+
if (!prefix.startsWith("#")) {
|
|
32
|
+
return { lines, cursorLine, cursorCol };
|
|
33
|
+
}
|
|
41
34
|
const currentLine = lines[cursorLine] || "";
|
|
42
35
|
const beforePrefix = currentLine.slice(0, cursorCol - prefix.length);
|
|
43
36
|
const afterCursor = currentLine.slice(cursorCol);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
cursorLine,
|
|
53
|
-
cursorCol: beforePrefix.length + item.value.length + 1, // +1 for space
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
// If not an @ attachment, let other providers handle it
|
|
57
|
-
return { lines, cursorLine, cursorCol };
|
|
58
|
-
}
|
|
59
|
-
// Force file completion (called on Tab key) - always returns suggestions
|
|
60
|
-
async getForceFileSuggestions(lines, cursorLine, cursorCol) {
|
|
61
|
-
const currentLine = lines[cursorLine] || "";
|
|
62
|
-
const textBeforeCursor = currentLine.slice(0, cursorCol);
|
|
63
|
-
// Check for @ file attachment syntax first
|
|
64
|
-
const atMatch = textBeforeCursor.match(/@([^\s]*)$/);
|
|
65
|
-
const pathMatch = atMatch ? atMatch[0] : null;
|
|
66
|
-
console.log("pathMatch", textBeforeCursor, pathMatch);
|
|
67
|
-
if (pathMatch !== null) {
|
|
68
|
-
let prefix = pathMatch; // Includes the @
|
|
69
|
-
// Handle @ file attachment prefix
|
|
70
|
-
if (prefix.startsWith("@")) {
|
|
71
|
-
prefix = prefix.slice(1); // Remove the @
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
const suggestions = await this.getFileSuggestions(prefix);
|
|
77
|
-
if (suggestions.length === 0)
|
|
78
|
-
return null;
|
|
79
|
-
// For @ prefix, filter to only show directories and attachable files
|
|
80
|
-
const filteredSuggestions = [];
|
|
81
|
-
for (const suggestion of suggestions) {
|
|
82
|
-
if (!suggestion.value.endsWith("/") &&
|
|
83
|
-
!isAttachableFile(suggestion.value)) {
|
|
84
|
-
continue;
|
|
85
|
-
}
|
|
86
|
-
suggestion.value = `@${suggestion.value}`;
|
|
87
|
-
filteredSuggestions.push(suggestion);
|
|
88
|
-
}
|
|
89
|
-
if (filteredSuggestions.length === 0)
|
|
90
|
-
return null;
|
|
91
|
-
return {
|
|
92
|
-
items: suggestions,
|
|
93
|
-
prefix: pathMatch,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
return null;
|
|
37
|
+
const newLine = `${beforePrefix + item.value} ${afterCursor}`;
|
|
38
|
+
const newLines = [...lines];
|
|
39
|
+
newLines[cursorLine] = newLine;
|
|
40
|
+
return {
|
|
41
|
+
lines: newLines,
|
|
42
|
+
cursorLine,
|
|
43
|
+
cursorCol: beforePrefix.length + item.value.length + 1,
|
|
44
|
+
};
|
|
97
45
|
}
|
|
98
46
|
}
|
|
99
47
|
function isAttachableFile(filePath) {
|
|
100
|
-
// Check file extension for common text files that might be misidentified
|
|
101
48
|
const textExtensions = [
|
|
102
49
|
".txt",
|
|
103
50
|
".md",
|
|
@@ -4,6 +4,7 @@ export interface AutocompleteItem {
|
|
|
4
4
|
description?: string;
|
|
5
5
|
}
|
|
6
6
|
export interface AutocompleteProvider {
|
|
7
|
+
matchesContext(textBeforeCursor: string): boolean;
|
|
7
8
|
getSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<{
|
|
8
9
|
items: AutocompleteItem[];
|
|
9
10
|
prefix: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-provider.d.ts","sourceRoot":"","sources":["../../../source/tui/autocomplete/base-provider.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IAGnC,cAAc,CACZ,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAIjE,eAAe,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACb;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/D"}
|
|
1
|
+
{"version":3,"file":"base-provider.d.ts","sourceRoot":"","sources":["../../../source/tui/autocomplete/base-provider.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IAGnC,cAAc,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC;IAIlD,cAAc,CACZ,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAIjE,eAAe,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACb;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/D"}
|
|
@@ -2,6 +2,7 @@ import type { AutocompleteItem, AutocompleteProvider } from "./base-provider.ts"
|
|
|
2
2
|
export declare class CombinedProvider implements AutocompleteProvider {
|
|
3
3
|
private providers;
|
|
4
4
|
constructor(providers: AutocompleteProvider[]);
|
|
5
|
+
matchesContext(textBeforeCursor: string): boolean;
|
|
5
6
|
getSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<{
|
|
6
7
|
items: AutocompleteItem[];
|
|
7
8
|
prefix: string;
|
|
@@ -11,10 +12,6 @@ export declare class CombinedProvider implements AutocompleteProvider {
|
|
|
11
12
|
cursorLine: number;
|
|
12
13
|
cursorCol: number;
|
|
13
14
|
};
|
|
14
|
-
getForceFileSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<{
|
|
15
|
-
items: AutocompleteItem[];
|
|
16
|
-
prefix: string;
|
|
17
|
-
} | null>;
|
|
18
15
|
shouldTriggerFileCompletion(lines: string[], cursorLine: number, cursorCol: number): boolean;
|
|
19
16
|
}
|
|
20
17
|
//# sourceMappingURL=combined-provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combined-provider.d.ts","sourceRoot":"","sources":["../../../source/tui/autocomplete/combined-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAE5B,qBAAa,gBAAiB,YAAW,oBAAoB;IAC3D,OAAO,CAAC,SAAS,CAAyB;gBAE9B,SAAS,EAAE,oBAAoB,EAAE;
|
|
1
|
+
{"version":3,"file":"combined-provider.d.ts","sourceRoot":"","sources":["../../../source/tui/autocomplete/combined-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAE5B,qBAAa,gBAAiB,YAAW,oBAAoB;IAC3D,OAAO,CAAC,SAAS,CAAyB;gBAE9B,SAAS,EAAE,oBAAoB,EAAE;IAI7C,cAAc,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO;IAI3C,cAAc,CAClB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAehE,eAAe,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACb;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAwB7D,2BAA2B,CACzB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO;CAmBX"}
|
|
@@ -3,6 +3,9 @@ export class CombinedProvider {
|
|
|
3
3
|
constructor(providers) {
|
|
4
4
|
this.providers = providers;
|
|
5
5
|
}
|
|
6
|
+
matchesContext(textBeforeCursor) {
|
|
7
|
+
return this.providers.some((p) => p.matchesContext(textBeforeCursor));
|
|
8
|
+
}
|
|
6
9
|
async getSuggestions(lines, cursorLine, cursorCol) {
|
|
7
10
|
// Try each provider in order until we get suggestions
|
|
8
11
|
for (const provider of this.providers) {
|
|
@@ -27,23 +30,6 @@ export class CombinedProvider {
|
|
|
27
30
|
// If no provider handled it, return unchanged
|
|
28
31
|
return { lines, cursorLine, cursorCol };
|
|
29
32
|
}
|
|
30
|
-
// Force file completion (called on Tab key) - always returns suggestions
|
|
31
|
-
async getForceFileSuggestions(lines, cursorLine, cursorCol) {
|
|
32
|
-
if (!this.shouldTriggerFileCompletion(lines, cursorLine, cursorCol)) {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
// Try each provider that has getForceFileSuggestions method
|
|
36
|
-
for (const provider of this.providers) {
|
|
37
|
-
if ("getForceFileSuggestions" in provider &&
|
|
38
|
-
typeof provider.getForceFileSuggestions === "function") {
|
|
39
|
-
const result = await provider.getForceFileSuggestions(lines, cursorLine, cursorCol);
|
|
40
|
-
if (result) {
|
|
41
|
-
return result;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
33
|
// Check if we should trigger file completion (called on Tab key)
|
|
48
34
|
shouldTriggerFileCompletion(lines, cursorLine, cursorCol) {
|
|
49
35
|
// Try each provider that has shouldTriggerFileCompletion method
|
|
@@ -7,6 +7,7 @@ export interface SlashCommand {
|
|
|
7
7
|
export declare class CommandProvider<T extends SlashCommand | AutocompleteItem> implements AutocompleteProvider {
|
|
8
8
|
private commands;
|
|
9
9
|
constructor(commands?: T[]);
|
|
10
|
+
matchesContext(textBeforeCursor: string): boolean;
|
|
10
11
|
getSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<{
|
|
11
12
|
items: AutocompleteItem[];
|
|
12
13
|
prefix: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-provider.d.ts","sourceRoot":"","sources":["../../../source/tui/autocomplete/command-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,sBAAsB,CAAC,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAAC;CAC5E;AAED,qBAAa,eAAe,CAAC,CAAC,SAAS,YAAY,GAAG,gBAAgB,CACpE,YAAW,oBAAoB;IAE/B,OAAO,CAAC,QAAQ,CAAM;gBAEV,QAAQ,GAAE,CAAC,EAAO;
|
|
1
|
+
{"version":3,"file":"command-provider.d.ts","sourceRoot":"","sources":["../../../source/tui/autocomplete/command-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,sBAAsB,CAAC,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAAC;CAC5E;AAED,qBAAa,eAAe,CAAC,CAAC,SAAS,YAAY,GAAG,gBAAgB,CACpE,YAAW,oBAAoB;IAE/B,OAAO,CAAC,QAAQ,CAAM;gBAEV,QAAQ,GAAE,CAAC,EAAO;IAI9B,cAAc,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO;IAI3C,cAAc,CAClB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IA8DhE,eAAe,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACb;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;CAwC9D"}
|
|
@@ -3,6 +3,9 @@ export class CommandProvider {
|
|
|
3
3
|
constructor(commands = []) {
|
|
4
4
|
this.commands = commands;
|
|
5
5
|
}
|
|
6
|
+
matchesContext(textBeforeCursor) {
|
|
7
|
+
return textBeforeCursor.trimStart().startsWith("/");
|
|
8
|
+
}
|
|
6
9
|
async getSuggestions(lines, cursorLine, cursorCol) {
|
|
7
10
|
const currentLine = lines[cursorLine] || "";
|
|
8
11
|
const textBeforeCursor = currentLine.slice(0, cursorCol);
|
|
@@ -2,6 +2,7 @@ import type { AutocompleteItem, AutocompleteProvider } from "./base-provider.ts"
|
|
|
2
2
|
export declare class FileSearchProvider implements AutocompleteProvider {
|
|
3
3
|
private maxResults;
|
|
4
4
|
private maxDepth;
|
|
5
|
+
matchesContext(textBeforeCursor: string): boolean;
|
|
5
6
|
getSuggestions(lines: string[], cursorLine: number, cursorCol: number): Promise<{
|
|
6
7
|
items: AutocompleteItem[];
|
|
7
8
|
prefix: string;
|
|
@@ -11,6 +12,6 @@ export declare class FileSearchProvider implements AutocompleteProvider {
|
|
|
11
12
|
cursorLine: number;
|
|
12
13
|
cursorCol: number;
|
|
13
14
|
};
|
|
14
|
-
|
|
15
|
+
protected searchFiles(searchTerm: string): Promise<AutocompleteItem[]>;
|
|
15
16
|
}
|
|
16
17
|
//# sourceMappingURL=file-search-provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-search-provider.d.ts","sourceRoot":"","sources":["../../../source/tui/autocomplete/file-search-provider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"file-search-provider.d.ts","sourceRoot":"","sources":["../../../source/tui/autocomplete/file-search-provider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,oBAAoB,CAAC;AA2C5B,qBAAa,kBAAmB,YAAW,oBAAoB;IAC7D,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,QAAQ,CAAK;IAErB,cAAc,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO;IAI3C,cAAc,CAClB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAuBhE,eAAe,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACb;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;cAqB7C,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAoE7E"}
|
|
@@ -30,13 +30,27 @@ async function loadGitignorePatterns(cwd) {
|
|
|
30
30
|
return [];
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
function fuzzyScore(filename, searchTerm) {
|
|
34
|
+
const lower = filename.toLowerCase();
|
|
35
|
+
if (lower.startsWith(searchTerm))
|
|
36
|
+
return 0;
|
|
37
|
+
const nameWithoutExt = lower.replace(/\.[^.]+$/, "");
|
|
38
|
+
if (nameWithoutExt.startsWith(searchTerm))
|
|
39
|
+
return 1;
|
|
40
|
+
if (lower.includes(searchTerm))
|
|
41
|
+
return 2;
|
|
42
|
+
return 3;
|
|
43
|
+
}
|
|
33
44
|
export class FileSearchProvider {
|
|
34
45
|
maxResults = 20;
|
|
35
|
-
maxDepth =
|
|
46
|
+
maxDepth = 8;
|
|
47
|
+
matchesContext(textBeforeCursor) {
|
|
48
|
+
return /(?:^|\s)@[^\s]*$/.test(textBeforeCursor);
|
|
49
|
+
}
|
|
36
50
|
async getSuggestions(lines, cursorLine, cursorCol) {
|
|
37
51
|
const currentLine = lines[cursorLine] || "";
|
|
38
52
|
const textBeforeCursor = currentLine.slice(0, cursorCol);
|
|
39
|
-
const pathMatch = textBeforeCursor.match(
|
|
53
|
+
const pathMatch = textBeforeCursor.match(/(?<!@)@([^\s]*)$/);
|
|
40
54
|
if (!pathMatch) {
|
|
41
55
|
return null;
|
|
42
56
|
}
|
|
@@ -52,8 +66,8 @@ export class FileSearchProvider {
|
|
|
52
66
|
};
|
|
53
67
|
}
|
|
54
68
|
applyCompletion(lines, cursorLine, cursorCol, item, prefix) {
|
|
55
|
-
// Only handle completions that start with
|
|
56
|
-
if (!prefix.startsWith("
|
|
69
|
+
// Only handle completions that start with @
|
|
70
|
+
if (!prefix.startsWith("@")) {
|
|
57
71
|
return { lines, cursorLine, cursorCol };
|
|
58
72
|
}
|
|
59
73
|
const currentLine = lines[cursorLine] || "";
|
|
@@ -71,7 +85,6 @@ export class FileSearchProvider {
|
|
|
71
85
|
async searchFiles(searchTerm) {
|
|
72
86
|
const results = [];
|
|
73
87
|
const cwd = process.cwd();
|
|
74
|
-
// Build ignore instance with .gitignore patterns + defaults
|
|
75
88
|
const ig = ignore().add(defaultIgnoredPatterns);
|
|
76
89
|
const gitignorePatterns = await loadGitignorePatterns(cwd);
|
|
77
90
|
if (gitignorePatterns.length > 0) {
|
|
@@ -97,22 +110,29 @@ export class FileSearchProvider {
|
|
|
97
110
|
continue;
|
|
98
111
|
}
|
|
99
112
|
const isDirectory = match.endsWith("/");
|
|
100
|
-
const
|
|
101
|
-
?
|
|
102
|
-
:
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
113
|
+
const relativePathWithPrefix = relativePath.startsWith("./")
|
|
114
|
+
? relativePath
|
|
115
|
+
: `./${relativePath}`;
|
|
116
|
+
const relPath = isDirectory
|
|
117
|
+
? `${relativePathWithPrefix}/`
|
|
118
|
+
: relativePathWithPrefix;
|
|
119
|
+
const label = relativePath.split("/").pop() || relativePath;
|
|
120
|
+
const parentPath = relativePath.split("/").slice(0, -1).join("/");
|
|
108
121
|
results.push({
|
|
109
|
-
value: isDirectory ? `${
|
|
122
|
+
value: isDirectory ? `${relPath} ` : relPath,
|
|
110
123
|
label,
|
|
111
124
|
description: parentPath || ".",
|
|
112
125
|
});
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
126
|
+
}
|
|
127
|
+
results.sort((a, b) => {
|
|
128
|
+
const scoreA = fuzzyScore(a.label, lowerSearchTerm);
|
|
129
|
+
const scoreB = fuzzyScore(b.label, lowerSearchTerm);
|
|
130
|
+
if (scoreA !== scoreB)
|
|
131
|
+
return scoreA - scoreB;
|
|
132
|
+
return a.label.localeCompare(b.label);
|
|
133
|
+
});
|
|
134
|
+
if (results.length > this.maxResults) {
|
|
135
|
+
results.length = this.maxResults;
|
|
116
136
|
}
|
|
117
137
|
}
|
|
118
138
|
catch {
|