@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,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ToolExecutionOptions } from "./types.ts";
|
|
3
|
+
export declare const SkillTool: {
|
|
4
|
+
name: "Skill";
|
|
5
|
+
};
|
|
6
|
+
declare const inputSchema: z.ZodObject<{
|
|
7
|
+
skill: z.ZodString;
|
|
8
|
+
args: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
type SkillInputSchema = z.infer<typeof inputSchema>;
|
|
11
|
+
export declare function createSkillTool(): Promise<{
|
|
12
|
+
toolDef: {
|
|
13
|
+
description: string;
|
|
14
|
+
inputSchema: z.ZodObject<{
|
|
15
|
+
skill: z.ZodString;
|
|
16
|
+
args: z.ZodOptional<z.ZodString>;
|
|
17
|
+
}, z.core.$strip>;
|
|
18
|
+
};
|
|
19
|
+
display({ skill: skillName }: SkillInputSchema): string;
|
|
20
|
+
execute({ skill: skillName, args }: SkillInputSchema, { abortSignal }: ToolExecutionOptions): Promise<string>;
|
|
21
|
+
}>;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=skill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../source/tools/skill.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,eAAO,MAAM,SAAS;;CAErB,CAAC;AAEF,QAAA,MAAM,WAAW;;;iBAKf,CAAC;AAEH,KAAK,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEpD,wBAAsB,eAAe;;;;;;;;kCAWH,gBAAgB,GAAG,MAAM;wCAIzB,gBAAgB,mBAC3B,oBAAoB,GACpC,OAAO,CAAC,MAAM,CAAC;GA4CrB"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { loadSkills } from "../skills/index.js";
|
|
5
|
+
import style from "../terminal/style.js";
|
|
6
|
+
import { replaceArgumentPlaceholders } from "../utils/templates.js";
|
|
7
|
+
export const SkillTool = {
|
|
8
|
+
name: "Skill",
|
|
9
|
+
};
|
|
10
|
+
const inputSchema = z.object({
|
|
11
|
+
skill: z
|
|
12
|
+
.string()
|
|
13
|
+
.describe('The skill name. E.g., "commit", "review-pr", or "pdf"'),
|
|
14
|
+
args: z.string().optional().describe("Optional arguments for the skill"),
|
|
15
|
+
});
|
|
16
|
+
export async function createSkillTool() {
|
|
17
|
+
const skills = await loadSkills();
|
|
18
|
+
const modelInvocableSkills = skills.getModelInvocable();
|
|
19
|
+
const description = "Run a skill (e.g., commit, review-pr).";
|
|
20
|
+
return {
|
|
21
|
+
toolDef: {
|
|
22
|
+
description,
|
|
23
|
+
inputSchema,
|
|
24
|
+
},
|
|
25
|
+
display({ skill: skillName }) {
|
|
26
|
+
return style.cyan(skillName);
|
|
27
|
+
},
|
|
28
|
+
async execute({ skill: skillName, args }, { abortSignal }) {
|
|
29
|
+
try {
|
|
30
|
+
if (abortSignal?.aborted) {
|
|
31
|
+
throw new Error("Skill execution aborted");
|
|
32
|
+
}
|
|
33
|
+
// Find the skill
|
|
34
|
+
const skill = modelInvocableSkills.find((s) => s.name === skillName);
|
|
35
|
+
if (!skill) {
|
|
36
|
+
const availableSkillNames = modelInvocableSkills
|
|
37
|
+
.map((s) => s.name)
|
|
38
|
+
.join(", ");
|
|
39
|
+
const errorMsg = `Skill "${skillName}" not found. Available skills: ${availableSkillNames}`;
|
|
40
|
+
return errorMsg;
|
|
41
|
+
}
|
|
42
|
+
if (skill.disableModelInvocation) {
|
|
43
|
+
return `Skill "${skillName}" is not available for model invocation.`;
|
|
44
|
+
}
|
|
45
|
+
// Read the skill file
|
|
46
|
+
const content = await readFile(skill.filePath, "utf8");
|
|
47
|
+
let result = `# Skill Name: ${skill.name}`;
|
|
48
|
+
result += `\n**Base directory**: ${dirname(skill.filePath)}\n\n`;
|
|
49
|
+
result +=
|
|
50
|
+
"Relative paths in this skill (e.g., scripts/, reference/) are relative to this base directory.\n";
|
|
51
|
+
// Parse frontmatter and body
|
|
52
|
+
const yamlStart = content.indexOf("---");
|
|
53
|
+
const yamlEnd = content.indexOf("---", yamlStart + 3);
|
|
54
|
+
const body = yamlEnd !== -1 ? content.slice(yamlEnd + 3).trim() : content;
|
|
55
|
+
const argsArray = args ? args.split(/\s+/).filter(Boolean) : [];
|
|
56
|
+
result += replaceArgumentPlaceholders(body, argsArray);
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
const errorMsg = `${error.message}`;
|
|
61
|
+
return errorMsg;
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"think.d.ts","sourceRoot":"","sources":["../../source/tools/think.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,eAAO,MAAM,SAAS;;CAErB,CAAC;
|
|
1
|
+
{"version":3,"file":"think.d.ts","sourceRoot":"","sources":["../../source/tools/think.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,eAAO,MAAM,SAAS;;CAErB,CAAC;AAIF,QAAA,MAAM,WAAW;;iBAEf,CAAC;AAGH,eAAO,MAAM,eAAe;;;;;;;;yBAUT,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,mBACvB,oBAAoB,GACpC,OAAO,CAAC,MAAM,CAAC;CAUrB,CAAC"}
|
package/dist/tools/think.js
CHANGED
|
@@ -2,14 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
export const ThinkTool = {
|
|
3
3
|
name: "Think",
|
|
4
4
|
};
|
|
5
|
-
const toolDescription =
|
|
6
|
-
Common use cases:
|
|
7
|
-
1. When exploring a repository and discovering the source of a bug, call this tool to brainstorm several unique ways of fixing the bug, and assess which change(s) are likely to be simplest and most effective
|
|
8
|
-
2. After receiving test results, use this tool to brainstorm ways to fix failing tests
|
|
9
|
-
3. When planning a complex refactoring, use this tool to outline different approaches and their tradeoffs
|
|
10
|
-
4. When designing a new feature, use this tool to think through architecture decisions and implementation details
|
|
11
|
-
5. When debugging a complex issue, use this tool to organize your thoughts and hypotheses
|
|
12
|
-
The tool simply logs your thought process for better transparency and does not execute any code or make changes.`;
|
|
5
|
+
const toolDescription = "Think through a problem step-by-step.";
|
|
13
6
|
const inputSchema = z.object({
|
|
14
7
|
thought: z.string().describe("Your thought"),
|
|
15
8
|
});
|
|
@@ -21,7 +14,7 @@ export const createThinkTool = () => {
|
|
|
21
14
|
inputSchema,
|
|
22
15
|
},
|
|
23
16
|
display() {
|
|
24
|
-
return "
|
|
17
|
+
return "Logging thought";
|
|
25
18
|
},
|
|
26
19
|
async execute({ thought }, { abortSignal }) {
|
|
27
20
|
if (abortSignal?.aborted) {
|
package/dist/tools/utils.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { Tool } from "ai";
|
|
2
|
+
import type { CompleteToolSet, CompleteTools } from "./index.ts";
|
|
3
|
+
export declare function toAiSdkTools(tools: CompleteToolSet, includeExecute?: boolean): CompleteTools;
|
|
2
4
|
export declare function prepareTools(tools: {
|
|
3
5
|
[toolName: string]: Tool;
|
|
4
6
|
}): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../source/tools/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../source/tools/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAuB,MAAM,IAAI,CAAC;AAGpD,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEjE,wBAAgB,YAAY,CAC1B,KAAK,EAAE,eAAe,EACtB,cAAc,UAAO,GACpB,aAAa,CAYf;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG;IACjE,KAAK,EACD,SAAS,GACT,KAAK,CAAC;QACJ,IAAI,EAAE,UAAU,CAAC;QACjB,QAAQ,EAAE;YACR,IAAI,EAAE,MAAM,CAAC;YACb,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;YAChC,UAAU,EAAE,OAAO,CAAC;SACrB,CAAC;KACH,CAAC,CAAC;CACR,CAuBA"}
|
package/dist/tools/utils.js
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
|
+
import { tool } from "ai";
|
|
1
2
|
import z from "zod";
|
|
3
|
+
export function toAiSdkTools(tools, includeExecute = true) {
|
|
4
|
+
return Object.fromEntries(Object.entries(tools).map(([name, toolObj]) => [
|
|
5
|
+
name,
|
|
6
|
+
tool({
|
|
7
|
+
...toolObj.toolDef,
|
|
8
|
+
execute: (includeExecute
|
|
9
|
+
? toolObj.execute
|
|
10
|
+
: undefined),
|
|
11
|
+
}),
|
|
12
|
+
]));
|
|
13
|
+
}
|
|
2
14
|
export function prepareTools(tools) {
|
|
3
15
|
const openaiCompatTools = [];
|
|
4
16
|
for (const tool of Object.entries(tools)) {
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ToolExecutionOptions } from "./types.ts";
|
|
3
|
+
export declare const WebFetchTool: {
|
|
4
|
+
name: "WebFetch";
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Input schema for the web fetch tool
|
|
8
|
+
*/
|
|
9
|
+
declare const inputSchema: z.ZodObject<{
|
|
10
|
+
url: z.ZodString;
|
|
11
|
+
output: z.ZodDefault<z.ZodEnum<{
|
|
12
|
+
markdown: "markdown";
|
|
13
|
+
text: "text";
|
|
14
|
+
html: "html";
|
|
15
|
+
json: "json";
|
|
16
|
+
}>>;
|
|
17
|
+
jina: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | null, unknown>, z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
18
|
+
timeout: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | null, unknown>, z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
19
|
+
headers: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | null, unknown>, z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
20
|
+
}, z.core.$strip>;
|
|
21
|
+
type WebFetchInputSchema = z.infer<typeof inputSchema>;
|
|
22
|
+
/**
|
|
23
|
+
* Execute web fetch
|
|
24
|
+
*/
|
|
25
|
+
export declare function executeWebFetch(options: WebFetchInputSchema, executionOptions: ToolExecutionOptions): Promise<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Create the web fetch tool
|
|
28
|
+
*/
|
|
29
|
+
export declare const createWebFetchTool: () => Promise<{
|
|
30
|
+
toolDef: {
|
|
31
|
+
description: string;
|
|
32
|
+
inputSchema: z.ZodObject<{
|
|
33
|
+
url: z.ZodString;
|
|
34
|
+
output: z.ZodDefault<z.ZodEnum<{
|
|
35
|
+
markdown: "markdown";
|
|
36
|
+
text: "text";
|
|
37
|
+
html: "html";
|
|
38
|
+
json: "json";
|
|
39
|
+
}>>;
|
|
40
|
+
jina: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | null, unknown>, z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
41
|
+
timeout: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | null, unknown>, z.ZodNullable<z.ZodCoercedNumber<unknown>>>>;
|
|
42
|
+
headers: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | null, unknown>, z.ZodNullable<z.ZodCoercedBoolean<unknown>>>>;
|
|
43
|
+
}, z.core.$strip>;
|
|
44
|
+
};
|
|
45
|
+
display({ url }: WebFetchInputSchema): string;
|
|
46
|
+
execute(options: WebFetchInputSchema, executionOptions: ToolExecutionOptions): Promise<string>;
|
|
47
|
+
}>;
|
|
48
|
+
export type WebFetchTool = Awaited<ReturnType<typeof createWebFetchTool>>;
|
|
49
|
+
export {};
|
|
50
|
+
//# sourceMappingURL=web-fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-fetch.d.ts","sourceRoot":"","sources":["../../source/tools/web-fetch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,eAAO,MAAM,YAAY;;CAExB,CAAC;AAQF;;GAEG;AACH,QAAA,MAAM,WAAW;;;;;;;;;;;iBAkBf,CAAC;AAEH,KAAK,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AA6bvD;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,mBAAmB,EAC5B,gBAAgB,EAAE,oBAAoB,GACrC,OAAO,CAAC,MAAM,CAAC,CAiEjB;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;qBAQV,mBAAmB;qBAIzB,mBAAmB,oBACV,oBAAoB,GACrC,OAAO,CAAC,MAAM,CAAC;EAIrB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
import { load } from "cheerio";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import style from "../terminal/style.js";
|
|
4
|
+
export const WebFetchTool = {
|
|
5
|
+
name: "WebFetch",
|
|
6
|
+
};
|
|
7
|
+
// Constants
|
|
8
|
+
const DEFAULT_TIMEOUT = 30000; // 30 seconds
|
|
9
|
+
const MAX_REDIRECTS = 5;
|
|
10
|
+
const MAX_URL_LENGTH = 2048;
|
|
11
|
+
const JINA_API_BASE = "https://r.jina.ai";
|
|
12
|
+
/**
|
|
13
|
+
* Input schema for the web fetch tool
|
|
14
|
+
*/
|
|
15
|
+
const inputSchema = z.object({
|
|
16
|
+
url: z.string().describe("URL to fetch"),
|
|
17
|
+
output: z
|
|
18
|
+
.enum(["text", "html", "markdown", "json"])
|
|
19
|
+
.default("text")
|
|
20
|
+
.describe("Output format (default: text)"),
|
|
21
|
+
jina: z
|
|
22
|
+
.preprocess((val) => convertNullString(val), z.coerce.boolean().nullable())
|
|
23
|
+
.optional()
|
|
24
|
+
.describe("Use Jina AI for HTML cleaning"),
|
|
25
|
+
timeout: z
|
|
26
|
+
.preprocess((val) => convertNullString(val), z.coerce.number().nullable())
|
|
27
|
+
.optional()
|
|
28
|
+
.describe(`Timeout in milliseconds (default: ${DEFAULT_TIMEOUT}ms)`),
|
|
29
|
+
headers: z
|
|
30
|
+
.preprocess((val) => convertNullString(val), z.coerce.boolean().nullable())
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("Include HTTP headers in output"),
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* Convert null/undefined to string for preprocessing
|
|
36
|
+
*/
|
|
37
|
+
function convertNullString(val) {
|
|
38
|
+
if (val === null ||
|
|
39
|
+
val === undefined ||
|
|
40
|
+
val === "null" ||
|
|
41
|
+
val === "undefined") {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return String(val);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Count tokens (simple estimation: 4 characters per token)
|
|
48
|
+
*/
|
|
49
|
+
function countTokens(text) {
|
|
50
|
+
return Math.ceil(text.length / 4);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Validate URL
|
|
54
|
+
*/
|
|
55
|
+
function isValidUrl(url) {
|
|
56
|
+
try {
|
|
57
|
+
if (typeof url !== "string" || url.length === 0)
|
|
58
|
+
return false;
|
|
59
|
+
if (url.length > MAX_URL_LENGTH)
|
|
60
|
+
return false;
|
|
61
|
+
const parsed = new URL(url);
|
|
62
|
+
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Factory function for creating abort handlers.
|
|
70
|
+
* Defined at module level to avoid capturing closure scope.
|
|
71
|
+
*/
|
|
72
|
+
function createAbortHandler(ctrl, signal) {
|
|
73
|
+
return () => {
|
|
74
|
+
ctrl.abort(signal?.reason ?? new Error("Aborted"));
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Create an AbortSignal that combines a timeout with an optional parent signal
|
|
79
|
+
*/
|
|
80
|
+
function createTimeoutSignal(timeoutMs, parentSignal) {
|
|
81
|
+
const controller = new AbortController();
|
|
82
|
+
// Use bind() to avoid capturing scope in timeout callback
|
|
83
|
+
const abort = controller.abort.bind(controller);
|
|
84
|
+
const timeoutId = setTimeout(() => abort(new Error(`Request timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
85
|
+
// Create abort handler using factory to avoid capturing scope
|
|
86
|
+
const abortHandler = createAbortHandler(controller, parentSignal);
|
|
87
|
+
if (parentSignal) {
|
|
88
|
+
if (parentSignal.aborted) {
|
|
89
|
+
abortHandler();
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
parentSignal.addEventListener("abort", abortHandler, { once: true });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
signal: controller.signal,
|
|
97
|
+
cleanup: () => {
|
|
98
|
+
clearTimeout(timeoutId);
|
|
99
|
+
if (parentSignal) {
|
|
100
|
+
parentSignal.removeEventListener("abort", abortHandler);
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get content type from response headers
|
|
107
|
+
*/
|
|
108
|
+
function getContentType(response) {
|
|
109
|
+
const header = response.headers.get("content-type") || "text/plain";
|
|
110
|
+
return header.split(";")[0].trim();
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* HTML Cleaner class using Cheerio
|
|
114
|
+
*/
|
|
115
|
+
class HtmlCleaner {
|
|
116
|
+
html;
|
|
117
|
+
constructor(html) {
|
|
118
|
+
this.html = html;
|
|
119
|
+
}
|
|
120
|
+
static new(html) {
|
|
121
|
+
return new HtmlCleaner(html);
|
|
122
|
+
}
|
|
123
|
+
clean(options = { simplify: true, empty: true }) {
|
|
124
|
+
const { simplify, empty } = options;
|
|
125
|
+
const $ = load(this.html);
|
|
126
|
+
this.removeUnnecessaryElements($);
|
|
127
|
+
if (simplify) {
|
|
128
|
+
this.simplifyStructure($);
|
|
129
|
+
}
|
|
130
|
+
if (empty) {
|
|
131
|
+
this.removeEmptyElements($);
|
|
132
|
+
}
|
|
133
|
+
return $.html()
|
|
134
|
+
.trim()
|
|
135
|
+
.replace(/^\s*[\r\n]/gm, "");
|
|
136
|
+
}
|
|
137
|
+
removeUnnecessaryElements($) {
|
|
138
|
+
$("script").remove();
|
|
139
|
+
$("noscript").remove();
|
|
140
|
+
$("style").remove();
|
|
141
|
+
$('link[rel="stylesheet"]').remove();
|
|
142
|
+
$('link[rel="preload"]').remove();
|
|
143
|
+
$("link").remove();
|
|
144
|
+
$("form").remove();
|
|
145
|
+
$("*")
|
|
146
|
+
.contents()
|
|
147
|
+
.each((_, element) => {
|
|
148
|
+
if (element.type === "comment") {
|
|
149
|
+
$(element).remove();
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
$("[style]").removeAttr("style");
|
|
153
|
+
$("[class]").removeAttr("class");
|
|
154
|
+
$("[id]").removeAttr("id");
|
|
155
|
+
}
|
|
156
|
+
simplifyStructure($) {
|
|
157
|
+
$("div div").each((_, element) => {
|
|
158
|
+
const $element = $(element);
|
|
159
|
+
const parent = $element.parent();
|
|
160
|
+
if (parent.children().length === 1 && parent.get(0)?.tagName === "div") {
|
|
161
|
+
$element.unwrap();
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
$("span").each((_, element) => {
|
|
165
|
+
const $element = $(element);
|
|
166
|
+
if (!$element.attr() || Object.keys($element.attr() ?? {}).length === 0) {
|
|
167
|
+
const h = $element.html();
|
|
168
|
+
if (h) {
|
|
169
|
+
$element.replaceWith(h);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
removeEmptyElements($) {
|
|
175
|
+
$(":empty").remove();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Convert HTML to Markdown
|
|
180
|
+
*/
|
|
181
|
+
function htmlToMarkdown(html) {
|
|
182
|
+
return html
|
|
183
|
+
.replace(/<h1>(.*?)<\/h1>/g, "# $1\n\n")
|
|
184
|
+
.replace(/<h2>(.*?)<\/h2>/g, "## $1\n\n")
|
|
185
|
+
.replace(/<h3>(.*?)<\/h3>/g, "### $1\n\n")
|
|
186
|
+
.replace(/<h4>(.*?)<\/h4>/g, "#### $1\n\n")
|
|
187
|
+
.replace(/<h5>(.*?)<\/h5>/g, "##### $1\n\n")
|
|
188
|
+
.replace(/<h6>(.*?)<\/h6>/g, "###### $1\n\n")
|
|
189
|
+
.replace(/<p>(.*?)<\/p>/g, "$1\n\n")
|
|
190
|
+
.replace(/<br\s*\/?>/g, "\n")
|
|
191
|
+
.replace(/<strong>(.*?)<\/strong>/g, "**$1**")
|
|
192
|
+
.replace(/<b>(.*?)<\/b>/g, "**$1**")
|
|
193
|
+
.replace(/<em>(.*?)<\/em>/g, "*$1*")
|
|
194
|
+
.replace(/<i>(.*?)<\/i>/g, "*$1*")
|
|
195
|
+
.replace(/<a[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/g, "[$2]($1)")
|
|
196
|
+
.replace(/<li>(.*?)<\/li>/g, "- $1\n")
|
|
197
|
+
.replace(/<ul[^>]*>/g, "\n")
|
|
198
|
+
.replace(/<\/ul>/g, "\n")
|
|
199
|
+
.replace(/<ol[^>]*>/g, "\n")
|
|
200
|
+
.replace(/<\/ol>/g, "\n")
|
|
201
|
+
.replace(/<code>(.*?)<\/code>/g, "`$1`")
|
|
202
|
+
.replace(/<pre>(.*?)<\/pre>/gs, "```\n$1\n```\n")
|
|
203
|
+
.replace(/<[^>]*>/g, "")
|
|
204
|
+
.replace(/\n\n\n+/g, "\n\n")
|
|
205
|
+
.trim();
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Fetch using Jina AI reader
|
|
209
|
+
*/
|
|
210
|
+
async function fetchWithJina(url, signal) {
|
|
211
|
+
const apiKey = process.env["JINA_READER_API_KEY"];
|
|
212
|
+
if (!apiKey) {
|
|
213
|
+
throw new Error("JINA_READER_API_KEY environment variable is not set");
|
|
214
|
+
}
|
|
215
|
+
const jinaUrl = `${JINA_API_BASE}/${encodeURIComponent(url)}`;
|
|
216
|
+
const response = await fetch(jinaUrl, {
|
|
217
|
+
method: "GET",
|
|
218
|
+
headers: {
|
|
219
|
+
// biome-ignore lint/style/useNamingConvention: HTTP header names are case-sensitive
|
|
220
|
+
Authorization: `Bearer ${apiKey}`,
|
|
221
|
+
"X-With-Generated-Alt": "true",
|
|
222
|
+
"X-With-Links-Summary": "true",
|
|
223
|
+
},
|
|
224
|
+
signal,
|
|
225
|
+
});
|
|
226
|
+
if (!response.ok) {
|
|
227
|
+
const errorText = await response.text();
|
|
228
|
+
throw new Error(`Jina API error: ${response.status} - ${errorText}`);
|
|
229
|
+
}
|
|
230
|
+
const content = await response.text();
|
|
231
|
+
const tokenCount = countTokens(content);
|
|
232
|
+
return {
|
|
233
|
+
content,
|
|
234
|
+
contentType: "text/html",
|
|
235
|
+
sourceUrl: url,
|
|
236
|
+
tokenCount,
|
|
237
|
+
success: true,
|
|
238
|
+
provider: "jina",
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Handle HTML response
|
|
243
|
+
*/
|
|
244
|
+
async function handleHtmlResponse(response, useJina, signal, verbose = false) {
|
|
245
|
+
const html = await response.text();
|
|
246
|
+
if (useJina) {
|
|
247
|
+
try {
|
|
248
|
+
const jinaResult = await fetchWithJina(response.url, signal);
|
|
249
|
+
return jinaResult;
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
if (verbose) {
|
|
253
|
+
console.error(`Jina AI failed: ${error instanceof Error ? error.message : String(error)}, falling back to local cleaning`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const cleaner = HtmlCleaner.new(html);
|
|
258
|
+
const cleaned = cleaner.clean();
|
|
259
|
+
const tokenCount = countTokens(cleaned);
|
|
260
|
+
return {
|
|
261
|
+
content: cleaned,
|
|
262
|
+
contentType: "text/html",
|
|
263
|
+
sourceUrl: response.url,
|
|
264
|
+
tokenCount,
|
|
265
|
+
success: true,
|
|
266
|
+
provider: "local",
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Handle image response (convert to base64 data URL)
|
|
271
|
+
*/
|
|
272
|
+
async function handleImageResponse(response, contentType) {
|
|
273
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
274
|
+
const base64 = Buffer.from(arrayBuffer).toString("base64");
|
|
275
|
+
const base64Url = `data:${contentType};base64,${base64}`;
|
|
276
|
+
return {
|
|
277
|
+
content: base64Url,
|
|
278
|
+
contentType,
|
|
279
|
+
sourceUrl: response.url,
|
|
280
|
+
tokenCount: 0,
|
|
281
|
+
success: true,
|
|
282
|
+
provider: "direct",
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Handle text response
|
|
287
|
+
*/
|
|
288
|
+
async function handleTextResponse(response, contentType) {
|
|
289
|
+
const text = await response.text();
|
|
290
|
+
const tokenCount = countTokens(text);
|
|
291
|
+
return {
|
|
292
|
+
content: text,
|
|
293
|
+
contentType,
|
|
294
|
+
sourceUrl: response.url,
|
|
295
|
+
tokenCount,
|
|
296
|
+
success: true,
|
|
297
|
+
provider: "direct",
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Main fetch function with redirect handling
|
|
302
|
+
*/
|
|
303
|
+
async function fetchUrl(url, options) {
|
|
304
|
+
const { useJina = false, timeout = DEFAULT_TIMEOUT, verbose = false, headers: includeHeaders = false, abortSignal, } = options;
|
|
305
|
+
let redirectCount = 0;
|
|
306
|
+
let currentUrl = url;
|
|
307
|
+
while (redirectCount < MAX_REDIRECTS) {
|
|
308
|
+
const { signal, cleanup } = createTimeoutSignal(timeout, abortSignal);
|
|
309
|
+
try {
|
|
310
|
+
// Standard browser headers to avoid 403 errors on bot-protected sites
|
|
311
|
+
const requestHeaders = {
|
|
312
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
313
|
+
// biome-ignore lint/style/useNamingConvention: HTTP header name must match specification
|
|
314
|
+
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
|
|
315
|
+
"Accept-Language": "en-US,en;q=0.9",
|
|
316
|
+
"Accept-Encoding": "gzip, deflate, br",
|
|
317
|
+
// biome-ignore lint/style/useNamingConvention: HTTP header name must match specification
|
|
318
|
+
Connection: "keep-alive",
|
|
319
|
+
"Upgrade-Insecure-Requests": "1",
|
|
320
|
+
"Sec-Fetch-Dest": "document",
|
|
321
|
+
"Sec-Fetch-Mode": "navigate",
|
|
322
|
+
"Sec-Fetch-Site": "none",
|
|
323
|
+
"Sec-Fetch-User": "?1",
|
|
324
|
+
"Cache-Control": "max-age=0",
|
|
325
|
+
};
|
|
326
|
+
const response = await fetch(currentUrl, {
|
|
327
|
+
signal,
|
|
328
|
+
redirect: "manual",
|
|
329
|
+
headers: requestHeaders,
|
|
330
|
+
});
|
|
331
|
+
// Handle redirects
|
|
332
|
+
if (response.status >= 300 && response.status < 400) {
|
|
333
|
+
const location = response.headers.get("location");
|
|
334
|
+
if (location) {
|
|
335
|
+
const redirectUrl = new URL(location, currentUrl).toString();
|
|
336
|
+
if (verbose) {
|
|
337
|
+
console.error(`Redirecting to: ${redirectUrl}`);
|
|
338
|
+
}
|
|
339
|
+
currentUrl = redirectUrl;
|
|
340
|
+
redirectCount++;
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (!response.ok) {
|
|
345
|
+
throw new Error(`HTTP error! status: ${response.status} ${response.statusText}`);
|
|
346
|
+
}
|
|
347
|
+
const contentType = getContentType(response);
|
|
348
|
+
const responseHeaders = {};
|
|
349
|
+
if (includeHeaders) {
|
|
350
|
+
response.headers.forEach((value, key) => {
|
|
351
|
+
responseHeaders[key] = value;
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
let result;
|
|
355
|
+
if (contentType.includes("text/html")) {
|
|
356
|
+
result = await handleHtmlResponse(response, useJina, signal, verbose);
|
|
357
|
+
}
|
|
358
|
+
else if (contentType.startsWith("image/")) {
|
|
359
|
+
result = await handleImageResponse(response, contentType);
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
result = await handleTextResponse(response, contentType);
|
|
363
|
+
}
|
|
364
|
+
if (includeHeaders) {
|
|
365
|
+
result.headers = responseHeaders;
|
|
366
|
+
}
|
|
367
|
+
return result;
|
|
368
|
+
}
|
|
369
|
+
finally {
|
|
370
|
+
cleanup();
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
throw new Error(`Too many redirects (max: ${MAX_REDIRECTS})`);
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Execute web fetch
|
|
377
|
+
*/
|
|
378
|
+
export async function executeWebFetch(options, executionOptions) {
|
|
379
|
+
const { url, output = "text", jina = false, timeout, headers = false, } = options;
|
|
380
|
+
if (executionOptions.abortSignal?.aborted) {
|
|
381
|
+
throw new Error("Web fetch aborted");
|
|
382
|
+
}
|
|
383
|
+
if (!isValidUrl(url)) {
|
|
384
|
+
throw new Error("Invalid URL format. URL must start with http:// or https:// and be less than 2048 characters");
|
|
385
|
+
}
|
|
386
|
+
const effectiveTimeout = timeout ?? DEFAULT_TIMEOUT;
|
|
387
|
+
const effectiveJina = jina ?? false;
|
|
388
|
+
const effectiveHeaders = headers ?? false;
|
|
389
|
+
let result;
|
|
390
|
+
try {
|
|
391
|
+
result = await fetchUrl(url, {
|
|
392
|
+
useJina: effectiveJina,
|
|
393
|
+
timeout: effectiveTimeout,
|
|
394
|
+
verbose: false,
|
|
395
|
+
headers: effectiveHeaders,
|
|
396
|
+
abortSignal: executionOptions.abortSignal,
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
catch (error) {
|
|
400
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
401
|
+
throw new Error(`Web fetch failed: ${errorMessage}`);
|
|
402
|
+
}
|
|
403
|
+
switch (output) {
|
|
404
|
+
case "json": {
|
|
405
|
+
const jsonOutput = {
|
|
406
|
+
content: result.content,
|
|
407
|
+
contentType: result.contentType,
|
|
408
|
+
sourceUrl: result.sourceUrl,
|
|
409
|
+
tokenCount: result.tokenCount,
|
|
410
|
+
success: result.success,
|
|
411
|
+
provider: result.provider,
|
|
412
|
+
};
|
|
413
|
+
if (headers && result.headers) {
|
|
414
|
+
jsonOutput["headers"] = result["headers"];
|
|
415
|
+
}
|
|
416
|
+
return JSON.stringify(jsonOutput, null, 2);
|
|
417
|
+
}
|
|
418
|
+
case "html":
|
|
419
|
+
return result.content;
|
|
420
|
+
case "markdown":
|
|
421
|
+
if (result.contentType.includes("text/html")) {
|
|
422
|
+
return htmlToMarkdown(result.content);
|
|
423
|
+
}
|
|
424
|
+
return result.content;
|
|
425
|
+
default:
|
|
426
|
+
return result.content;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Create the web fetch tool
|
|
431
|
+
*/
|
|
432
|
+
export const createWebFetchTool = async () => {
|
|
433
|
+
const toolDescription = "Fetch and extract content from a URL.";
|
|
434
|
+
return {
|
|
435
|
+
toolDef: {
|
|
436
|
+
description: toolDescription,
|
|
437
|
+
inputSchema,
|
|
438
|
+
},
|
|
439
|
+
display({ url }) {
|
|
440
|
+
return `🌐 ${style.cyan(url)}`;
|
|
441
|
+
},
|
|
442
|
+
async execute(options, executionOptions) {
|
|
443
|
+
return executeWebFetch(options, executionOptions);
|
|
444
|
+
},
|
|
445
|
+
};
|
|
446
|
+
};
|