@travisennis/acai 0.0.1
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/.acai/acai.json +9 -0
- package/.acai/prompts/add-openrouter-model.md +13 -0
- package/.acai/prompts/project-status.md +4 -0
- package/.acai/prompts/update-architecture-document.md +9 -0
- package/.acai/rules/learned-rules.md +9 -0
- package/.ai/docs/available-tools.txt +3 -0
- package/.ai/docs/cognitive_complexity_refactoring_progress.md +65 -0
- package/.ai/docs/deleted_tools.md +168 -0
- package/.ai/docs/deleted_tools_88ced9ef.md +56 -0
- package/.ai/docs/image-pasting.md +46 -0
- package/.ai/docs/initialize-app.md +117 -0
- package/.ai/docs/issue-4-plan.md +44 -0
- package/.ai/docs/marked-renderer-debug.md +15 -0
- package/.ai/docs/marked-renderer-refactor-plan.md +64 -0
- package/.ai/docs/memory-use-cases.md +55 -0
- package/.ai/docs/prompt-consistency.md +31 -0
- package/.ai/docs/refactoring-tools.md +98 -0
- package/.ai/docs/system-prompt-update.md +174 -0
- package/.ai/docs/system_prompt.txt +210 -0
- package/.ai/docs/tasks.md +49 -0
- package/.ai/plan.md +131 -0
- package/.ai/prompt.md +1 -0
- package/.ai/scripts/fetch_models.js +27 -0
- package/.ai/scripts/generateSystemPrompt.ts +15 -0
- package/.ai/scripts/list-tools.mjs +4 -0
- package/.ai/scripts/p5_geometric_shapes.js +149 -0
- package/.husky/commit-msg +1 -0
- package/.husky/pre-commit +3 -0
- package/.husky/pre-push +1 -0
- package/.ignore +4 -0
- package/AGENTS.md +25 -0
- package/ARCHITECTURE.md +304 -0
- package/LICENSE +21 -0
- package/README.md +392 -0
- package/TODO.md +2 -0
- package/biome.json +61 -0
- package/commitlint.config.js +3 -0
- package/dist/cli.d.ts +19 -0
- package/dist/cli.js +116 -0
- package/dist/commands/application-log-command.d.ts +2 -0
- package/dist/commands/application-log-command.js +43 -0
- package/dist/commands/clear-command.d.ts +2 -0
- package/dist/commands/clear-command.js +12 -0
- package/dist/commands/compact-command.d.ts +2 -0
- package/dist/commands/compact-command.js +51 -0
- package/dist/commands/copy-command.d.ts +2 -0
- package/dist/commands/copy-command.js +51 -0
- package/dist/commands/edit-command.d.ts +2 -0
- package/dist/commands/edit-command.js +53 -0
- package/dist/commands/edit-prompt-command.d.ts +2 -0
- package/dist/commands/edit-prompt-command.js +25 -0
- package/dist/commands/exit-command.d.ts +2 -0
- package/dist/commands/exit-command.js +14 -0
- package/dist/commands/files-command.d.ts +2 -0
- package/dist/commands/files-command.js +63 -0
- package/dist/commands/generate-rules-command.d.ts +2 -0
- package/dist/commands/generate-rules-command.js +61 -0
- package/dist/commands/help-command.d.ts +2 -0
- package/dist/commands/help-command.js +19 -0
- package/dist/commands/init-command.d.ts +2 -0
- package/dist/commands/init-command.js +40 -0
- package/dist/commands/last-log-command.d.ts +2 -0
- package/dist/commands/last-log-command.js +76 -0
- package/dist/commands/manager.d.ts +22 -0
- package/dist/commands/manager.js +123 -0
- package/dist/commands/model-command.d.ts +2 -0
- package/dist/commands/model-command.js +84 -0
- package/dist/commands/paste-command.d.ts +2 -0
- package/dist/commands/paste-command.js +40 -0
- package/dist/commands/prompt-command.d.ts +2 -0
- package/dist/commands/prompt-command.js +111 -0
- package/dist/commands/reset-command.d.ts +2 -0
- package/dist/commands/reset-command.js +16 -0
- package/dist/commands/rules-command.d.ts +2 -0
- package/dist/commands/rules-command.js +68 -0
- package/dist/commands/save-command.d.ts +2 -0
- package/dist/commands/save-command.js +14 -0
- package/dist/commands/types.d.ts +26 -0
- package/dist/commands/types.js +1 -0
- package/dist/commands/usage-command.d.ts +2 -0
- package/dist/commands/usage-command.js +21 -0
- package/dist/config.d.ts +60 -0
- package/dist/config.js +193 -0
- package/dist/conversation-analyzer.d.ts +10 -0
- package/dist/conversation-analyzer.js +88 -0
- package/dist/dedent.d.ts +3 -0
- package/dist/dedent.js +38 -0
- package/dist/formatting.d.ts +17 -0
- package/dist/formatting.js +103 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +213 -0
- package/dist/logger.d.ts +2 -0
- package/dist/logger.js +24 -0
- package/dist/mentions.d.ts +9 -0
- package/dist/mentions.js +182 -0
- package/dist/messages.d.ts +69 -0
- package/dist/messages.js +261 -0
- package/dist/middleware/audit-message.d.ts +5 -0
- package/dist/middleware/audit-message.js +95 -0
- package/dist/middleware/index.d.ts +2 -0
- package/dist/middleware/index.js +2 -0
- package/dist/middleware/rate-limit.d.ts +4 -0
- package/dist/middleware/rate-limit.js +17 -0
- package/dist/models/ai-config.d.ts +12 -0
- package/dist/models/ai-config.js +87 -0
- package/dist/models/anthropic-provider.d.ts +25 -0
- package/dist/models/anthropic-provider.js +184 -0
- package/dist/models/deepseek-provider.d.ts +20 -0
- package/dist/models/deepseek-provider.js +42 -0
- package/dist/models/google-provider.d.ts +19 -0
- package/dist/models/google-provider.js +56 -0
- package/dist/models/manager.d.ts +15 -0
- package/dist/models/manager.js +48 -0
- package/dist/models/openai-provider.d.ts +22 -0
- package/dist/models/openai-provider.js +70 -0
- package/dist/models/openrouter-provider.d.ts +36 -0
- package/dist/models/openrouter-provider.js +276 -0
- package/dist/models/providers.d.ts +33 -0
- package/dist/models/providers.js +116 -0
- package/dist/models/xai-provider.d.ts +20 -0
- package/dist/models/xai-provider.js +47 -0
- package/dist/parsing.d.ts +2 -0
- package/dist/parsing.js +18 -0
- package/dist/prompts/manager.d.ts +19 -0
- package/dist/prompts/manager.js +71 -0
- package/dist/prompts.d.ts +4 -0
- package/dist/prompts.js +158 -0
- package/dist/repl-prompt.d.ts +14 -0
- package/dist/repl-prompt.js +147 -0
- package/dist/repl.d.ts +27 -0
- package/dist/repl.js +431 -0
- package/dist/source/cli.d.ts +19 -0
- package/dist/source/cli.js +116 -0
- package/dist/source/commands/application-log-command.d.ts +2 -0
- package/dist/source/commands/application-log-command.js +43 -0
- package/dist/source/commands/clear-command.d.ts +2 -0
- package/dist/source/commands/clear-command.js +12 -0
- package/dist/source/commands/compact-command.d.ts +2 -0
- package/dist/source/commands/compact-command.js +51 -0
- package/dist/source/commands/copy-command.d.ts +2 -0
- package/dist/source/commands/copy-command.js +51 -0
- package/dist/source/commands/edit-command.d.ts +2 -0
- package/dist/source/commands/edit-command.js +53 -0
- package/dist/source/commands/edit-prompt-command.d.ts +2 -0
- package/dist/source/commands/edit-prompt-command.js +25 -0
- package/dist/source/commands/exit-command.d.ts +2 -0
- package/dist/source/commands/exit-command.js +14 -0
- package/dist/source/commands/files-command.d.ts +2 -0
- package/dist/source/commands/files-command.js +63 -0
- package/dist/source/commands/generate-rules-command.d.ts +2 -0
- package/dist/source/commands/generate-rules-command.js +61 -0
- package/dist/source/commands/help-command.d.ts +2 -0
- package/dist/source/commands/help-command.js +19 -0
- package/dist/source/commands/init-command.d.ts +2 -0
- package/dist/source/commands/init-command.js +40 -0
- package/dist/source/commands/last-log-command.d.ts +2 -0
- package/dist/source/commands/last-log-command.js +76 -0
- package/dist/source/commands/manager.d.ts +22 -0
- package/dist/source/commands/manager.js +123 -0
- package/dist/source/commands/model-command.d.ts +2 -0
- package/dist/source/commands/model-command.js +84 -0
- package/dist/source/commands/paste-command.d.ts +2 -0
- package/dist/source/commands/paste-command.js +40 -0
- package/dist/source/commands/prompt-command.d.ts +2 -0
- package/dist/source/commands/prompt-command.js +111 -0
- package/dist/source/commands/reset-command.d.ts +2 -0
- package/dist/source/commands/reset-command.js +16 -0
- package/dist/source/commands/rules-command.d.ts +2 -0
- package/dist/source/commands/rules-command.js +68 -0
- package/dist/source/commands/save-command.d.ts +2 -0
- package/dist/source/commands/save-command.js +14 -0
- package/dist/source/commands/types.d.ts +26 -0
- package/dist/source/commands/types.js +1 -0
- package/dist/source/commands/usage-command.d.ts +2 -0
- package/dist/source/commands/usage-command.js +21 -0
- package/dist/source/config.d.ts +60 -0
- package/dist/source/config.js +193 -0
- package/dist/source/conversation-analyzer.d.ts +10 -0
- package/dist/source/conversation-analyzer.js +88 -0
- package/dist/source/dedent.d.ts +3 -0
- package/dist/source/dedent.js +38 -0
- package/dist/source/formatting.d.ts +17 -0
- package/dist/source/formatting.js +103 -0
- package/dist/source/index.d.ts +18 -0
- package/dist/source/index.js +213 -0
- package/dist/source/logger.d.ts +2 -0
- package/dist/source/logger.js +24 -0
- package/dist/source/mentions.d.ts +9 -0
- package/dist/source/mentions.js +182 -0
- package/dist/source/messages.d.ts +69 -0
- package/dist/source/messages.js +261 -0
- package/dist/source/middleware/audit-message.d.ts +5 -0
- package/dist/source/middleware/audit-message.js +95 -0
- package/dist/source/middleware/index.d.ts +2 -0
- package/dist/source/middleware/index.js +2 -0
- package/dist/source/middleware/rate-limit.d.ts +4 -0
- package/dist/source/middleware/rate-limit.js +17 -0
- package/dist/source/models/ai-config.d.ts +12 -0
- package/dist/source/models/ai-config.js +87 -0
- package/dist/source/models/anthropic-provider.d.ts +25 -0
- package/dist/source/models/anthropic-provider.js +184 -0
- package/dist/source/models/deepseek-provider.d.ts +20 -0
- package/dist/source/models/deepseek-provider.js +42 -0
- package/dist/source/models/google-provider.d.ts +19 -0
- package/dist/source/models/google-provider.js +56 -0
- package/dist/source/models/manager.d.ts +15 -0
- package/dist/source/models/manager.js +48 -0
- package/dist/source/models/openai-provider.d.ts +22 -0
- package/dist/source/models/openai-provider.js +70 -0
- package/dist/source/models/openrouter-provider.d.ts +36 -0
- package/dist/source/models/openrouter-provider.js +276 -0
- package/dist/source/models/providers.d.ts +33 -0
- package/dist/source/models/providers.js +116 -0
- package/dist/source/models/xai-provider.d.ts +20 -0
- package/dist/source/models/xai-provider.js +47 -0
- package/dist/source/parsing.d.ts +2 -0
- package/dist/source/parsing.js +18 -0
- package/dist/source/prompts/manager.d.ts +19 -0
- package/dist/source/prompts/manager.js +71 -0
- package/dist/source/prompts.d.ts +4 -0
- package/dist/source/prompts.js +158 -0
- package/dist/source/repl-prompt.d.ts +14 -0
- package/dist/source/repl-prompt.js +147 -0
- package/dist/source/repl.d.ts +27 -0
- package/dist/source/repl.js +431 -0
- package/dist/source/terminal/formatting.d.ts +37 -0
- package/dist/source/terminal/formatting.js +106 -0
- package/dist/source/terminal/index.d.ts +94 -0
- package/dist/source/terminal/index.js +420 -0
- package/dist/source/terminal/markdown-utils.d.ts +2 -0
- package/dist/source/terminal/markdown-utils.js +81 -0
- package/dist/source/terminal/markdown.d.ts +1 -0
- package/dist/source/terminal/markdown.js +111 -0
- package/dist/source/terminal/types.d.ts +71 -0
- package/dist/source/terminal/types.js +1 -0
- package/dist/source/terminal-output.d.ts +8 -0
- package/dist/source/terminal-output.js +213 -0
- package/dist/source/terminal-output.test.d.ts +8 -0
- package/dist/source/terminal-output.test.js +213 -0
- package/dist/source/token-tracker.d.ts +14 -0
- package/dist/source/token-tracker.js +53 -0
- package/dist/source/token-utils.d.ts +7 -0
- package/dist/source/token-utils.js +13 -0
- package/dist/source/tools/agent.d.ts +17 -0
- package/dist/source/tools/agent.js +87 -0
- package/dist/source/tools/bash.d.ts +19 -0
- package/dist/source/tools/bash.js +294 -0
- package/dist/source/tools/code-interpreter.d.ts +12 -0
- package/dist/source/tools/code-interpreter.js +131 -0
- package/dist/source/tools/command-validation.d.ts +8 -0
- package/dist/source/tools/command-validation.js +69 -0
- package/dist/source/tools/delete-file.d.ts +12 -0
- package/dist/source/tools/delete-file.js +56 -0
- package/dist/source/tools/directory-tree.d.ts +12 -0
- package/dist/source/tools/directory-tree.js +38 -0
- package/dist/source/tools/edit-file.d.ts +19 -0
- package/dist/source/tools/edit-file.js +107 -0
- package/dist/source/tools/filesystem-utils.d.ts +22 -0
- package/dist/source/tools/filesystem-utils.js +191 -0
- package/dist/source/tools/git-utils.d.ts +14 -0
- package/dist/source/tools/git-utils.js +64 -0
- package/dist/source/tools/grep.d.ts +17 -0
- package/dist/source/tools/grep.js +138 -0
- package/dist/source/tools/index.d.ts +161 -0
- package/dist/source/tools/index.js +209 -0
- package/dist/source/tools/memory-read.d.ts +13 -0
- package/dist/source/tools/memory-read.js +135 -0
- package/dist/source/tools/memory-write.d.ts +12 -0
- package/dist/source/tools/memory-write.js +83 -0
- package/dist/source/tools/move-file.d.ts +13 -0
- package/dist/source/tools/move-file.js +44 -0
- package/dist/source/tools/read-file.d.ts +17 -0
- package/dist/source/tools/read-file.js +86 -0
- package/dist/source/tools/read-multiple-files.d.ts +14 -0
- package/dist/source/tools/read-multiple-files.js +55 -0
- package/dist/source/tools/save-file.d.ts +17 -0
- package/dist/source/tools/save-file.js +98 -0
- package/dist/source/tools/think.d.ts +11 -0
- package/dist/source/tools/think.js +45 -0
- package/dist/source/tools/types.d.ts +29 -0
- package/dist/source/tools/types.js +14 -0
- package/dist/source/tools/web-fetch.d.ts +47 -0
- package/dist/source/tools/web-fetch.js +246 -0
- package/dist/source/tools/web-search.d.ts +13 -0
- package/dist/source/tools/web-search.js +80 -0
- package/dist/source/utils/process.d.ts +36 -0
- package/dist/source/utils/process.js +75 -0
- package/dist/source/version.d.ts +1 -0
- package/dist/source/version.js +21 -0
- package/dist/terminal/formatting.d.ts +37 -0
- package/dist/terminal/formatting.js +106 -0
- package/dist/terminal/index.d.ts +94 -0
- package/dist/terminal/index.js +420 -0
- package/dist/terminal/markdown-utils.d.ts +2 -0
- package/dist/terminal/markdown-utils.js +81 -0
- package/dist/terminal/markdown.d.ts +1 -0
- package/dist/terminal/markdown.js +111 -0
- package/dist/terminal/types.d.ts +71 -0
- package/dist/terminal/types.js +1 -0
- package/dist/terminal-output.d.ts +8 -0
- package/dist/terminal-output.js +213 -0
- package/dist/token-tracker.d.ts +14 -0
- package/dist/token-tracker.js +53 -0
- package/dist/token-utils.d.ts +7 -0
- package/dist/token-utils.js +13 -0
- package/dist/tools/agent.d.ts +17 -0
- package/dist/tools/agent.js +87 -0
- package/dist/tools/bash.d.ts +19 -0
- package/dist/tools/bash.js +294 -0
- package/dist/tools/code-interpreter.d.ts +12 -0
- package/dist/tools/code-interpreter.js +131 -0
- package/dist/tools/command-validation.d.ts +8 -0
- package/dist/tools/command-validation.js +69 -0
- package/dist/tools/delete-file.d.ts +12 -0
- package/dist/tools/delete-file.js +56 -0
- package/dist/tools/directory-tree.d.ts +12 -0
- package/dist/tools/directory-tree.js +38 -0
- package/dist/tools/edit-file.d.ts +19 -0
- package/dist/tools/edit-file.js +107 -0
- package/dist/tools/filesystem-utils.d.ts +22 -0
- package/dist/tools/filesystem-utils.js +191 -0
- package/dist/tools/git-utils.d.ts +14 -0
- package/dist/tools/git-utils.js +64 -0
- package/dist/tools/grep.d.ts +17 -0
- package/dist/tools/grep.js +138 -0
- package/dist/tools/index.d.ts +161 -0
- package/dist/tools/index.js +209 -0
- package/dist/tools/memory-read.d.ts +13 -0
- package/dist/tools/memory-read.js +135 -0
- package/dist/tools/memory-write.d.ts +12 -0
- package/dist/tools/memory-write.js +83 -0
- package/dist/tools/move-file.d.ts +13 -0
- package/dist/tools/move-file.js +44 -0
- package/dist/tools/read-file.d.ts +17 -0
- package/dist/tools/read-file.js +86 -0
- package/dist/tools/read-multiple-files.d.ts +14 -0
- package/dist/tools/read-multiple-files.js +55 -0
- package/dist/tools/save-file.d.ts +17 -0
- package/dist/tools/save-file.js +98 -0
- package/dist/tools/think.d.ts +11 -0
- package/dist/tools/think.js +45 -0
- package/dist/tools/types.d.ts +29 -0
- package/dist/tools/types.js +14 -0
- package/dist/tools/web-fetch.d.ts +47 -0
- package/dist/tools/web-fetch.js +246 -0
- package/dist/tools/web-search.d.ts +13 -0
- package/dist/tools/web-search.js +80 -0
- package/dist/utils/process.d.ts +36 -0
- package/dist/utils/process.js +75 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +21 -0
- package/knip.json +5 -0
- package/package.json +83 -0
- package/source/cli.ts +172 -0
- package/source/commands/application-log-command.ts +53 -0
- package/source/commands/clear-command.ts +14 -0
- package/source/commands/compact-command.ts +64 -0
- package/source/commands/copy-command.ts +55 -0
- package/source/commands/edit-command.ts +63 -0
- package/source/commands/edit-prompt-command.ts +31 -0
- package/source/commands/exit-command.ts +18 -0
- package/source/commands/files-command.ts +85 -0
- package/source/commands/generate-rules-command.ts +82 -0
- package/source/commands/help-command.ts +27 -0
- package/source/commands/init-command.ts +48 -0
- package/source/commands/last-log-command.ts +88 -0
- package/source/commands/manager.ts +151 -0
- package/source/commands/model-command.ts +123 -0
- package/source/commands/paste-command.ts +62 -0
- package/source/commands/prompt-command.ts +150 -0
- package/source/commands/reset-command.ts +22 -0
- package/source/commands/rules-command.ts +76 -0
- package/source/commands/save-command.ts +20 -0
- package/source/commands/types.ts +28 -0
- package/source/commands/usage-command.ts +26 -0
- package/source/config.ts +223 -0
- package/source/conversation-analyzer.ts +115 -0
- package/source/dedent.ts +53 -0
- package/source/formatting.ts +132 -0
- package/source/index.ts +240 -0
- package/source/logger.ts +29 -0
- package/source/mentions.ts +227 -0
- package/source/messages.ts +360 -0
- package/source/middleware/audit-message.ts +133 -0
- package/source/middleware/index.ts +2 -0
- package/source/middleware/rate-limit.ts +24 -0
- package/source/models/ai-config.ts +109 -0
- package/source/models/anthropic-provider.ts +199 -0
- package/source/models/deepseek-provider.ts +53 -0
- package/source/models/google-provider.ts +68 -0
- package/source/models/manager.ts +84 -0
- package/source/models/openai-provider.ts +81 -0
- package/source/models/openrouter-provider.ts +288 -0
- package/source/models/providers.ts +197 -0
- package/source/models/xai-provider.ts +59 -0
- package/source/parsing.ts +20 -0
- package/source/prompts/manager.ts +90 -0
- package/source/prompts.ts +172 -0
- package/source/repl-prompt.ts +196 -0
- package/source/repl.ts +572 -0
- package/source/terminal/formatting.ts +121 -0
- package/source/terminal/index.ts +518 -0
- package/source/terminal/markdown-utils.ts +89 -0
- package/source/terminal/markdown.ts +155 -0
- package/source/terminal/types.ts +84 -0
- package/source/terminal-output.test.ts +266 -0
- package/source/token-tracker.ts +78 -0
- package/source/token-utils.ts +17 -0
- package/source/tools/agent.ts +107 -0
- package/source/tools/bash.ts +367 -0
- package/source/tools/code-interpreter.ts +172 -0
- package/source/tools/command-validation.ts +81 -0
- package/source/tools/delete-file.ts +71 -0
- package/source/tools/directory-tree.ts +54 -0
- package/source/tools/edit-file.ts +155 -0
- package/source/tools/filesystem-utils.ts +265 -0
- package/source/tools/git-utils.ts +70 -0
- package/source/tools/grep.ts +184 -0
- package/source/tools/index.ts +278 -0
- package/source/tools/memory-read.ts +174 -0
- package/source/tools/memory-write.ts +105 -0
- package/source/tools/move-file.ts +59 -0
- package/source/tools/read-file.ts +129 -0
- package/source/tools/read-multiple-files.ts +80 -0
- package/source/tools/save-file.ts +147 -0
- package/source/tools/think.ts +51 -0
- package/source/tools/types.ts +58 -0
- package/source/tools/web-fetch.ts +327 -0
- package/source/tools/web-search.ts +101 -0
- package/source/utils/process.ts +121 -0
- package/source/version.ts +21 -0
- package/test/commands/copy-command.test.ts +69 -0
- package/test/config.test.ts +200 -0
- package/test/terminal/markdown-utils.test.ts +124 -0
- package/test/tools/bash-tool.test.ts +58 -0
- package/test/tools/code-interpreter.test.ts +91 -0
- package/test/tools/command-validation.test.ts +48 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +30 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TokenCounter } from "../token-utils.ts";
|
|
2
|
+
import type { SendData } from "./types.ts";
|
|
3
|
+
export declare const WebSearchTool: {
|
|
4
|
+
name: "webSearch";
|
|
5
|
+
};
|
|
6
|
+
export declare const createWebSearchTool: ({ sendData, tokenCounter, }: {
|
|
7
|
+
sendData?: SendData;
|
|
8
|
+
tokenCounter: TokenCounter;
|
|
9
|
+
}) => {
|
|
10
|
+
webSearch: import("ai").Tool<{
|
|
11
|
+
query: string;
|
|
12
|
+
}, string>;
|
|
13
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { tool } from "ai";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { SafeSearchType, search } from "duck-duck-scrape";
|
|
4
|
+
import Exa from "exa-js";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
export const WebSearchTool = {
|
|
7
|
+
name: "webSearch",
|
|
8
|
+
};
|
|
9
|
+
export const createWebSearchTool = ({ sendData, tokenCounter, }) => {
|
|
10
|
+
return {
|
|
11
|
+
[WebSearchTool.name]: tool({
|
|
12
|
+
description: "Searches the web and returns match documents with their title, url, and text content. The query should be formulated as a natural language question.",
|
|
13
|
+
inputSchema: z.object({
|
|
14
|
+
query: z.string().describe("The search query."),
|
|
15
|
+
}),
|
|
16
|
+
execute: async ({ query }, { toolCallId }) => {
|
|
17
|
+
sendData?.({
|
|
18
|
+
id: toolCallId,
|
|
19
|
+
event: "tool-init",
|
|
20
|
+
data: `Web search: ${chalk.cyan(query)}`,
|
|
21
|
+
});
|
|
22
|
+
const result = await performSearch(query);
|
|
23
|
+
const sources = result.results.map((source) => `## ${source.title}\nURL: ${source.url}\n\n${source.text}`);
|
|
24
|
+
const resultText = `# Search Results:\n\n${sources.join("\n\n")}`;
|
|
25
|
+
const tokenCount = tokenCounter.count(resultText);
|
|
26
|
+
sendData?.({
|
|
27
|
+
id: toolCallId,
|
|
28
|
+
event: "tool-completion",
|
|
29
|
+
data: `Found ${result.results.length} results. (${tokenCount} tokens)`,
|
|
30
|
+
});
|
|
31
|
+
return resultText;
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
async function performSearch(query) {
|
|
37
|
+
// Check if EXA API key is available
|
|
38
|
+
const hasExaApiKey = process.env["EXA_API_KEY"] && process.env["EXA_API_KEY"].trim() !== "";
|
|
39
|
+
if (hasExaApiKey) {
|
|
40
|
+
// Use Exa search
|
|
41
|
+
try {
|
|
42
|
+
const exa = new Exa(process.env["EXA_API_KEY"]);
|
|
43
|
+
const result = await exa.searchAndContents(query, {
|
|
44
|
+
numResults: 5,
|
|
45
|
+
text: true,
|
|
46
|
+
});
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
// If Exa fails, fall back to duck duck scrape
|
|
51
|
+
console.info("Exa search failed, falling back to DuckDuckGo:", error);
|
|
52
|
+
return await searchWithDuckDuckGo(query);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Use DuckDuckGo search as fallback
|
|
57
|
+
console.info("EXA_API_KEY not set, using DuckDuckGo search");
|
|
58
|
+
return await searchWithDuckDuckGo(query);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async function searchWithDuckDuckGo(query) {
|
|
62
|
+
try {
|
|
63
|
+
const searchResults = await search(query, {
|
|
64
|
+
safeSearch: SafeSearchType.MODERATE,
|
|
65
|
+
});
|
|
66
|
+
// Transform duck-duck-scrape results to match Exa format
|
|
67
|
+
// Take only first 5 results to match Exa behavior
|
|
68
|
+
const results = searchResults.results
|
|
69
|
+
.slice(0, 5)
|
|
70
|
+
.map((result) => ({
|
|
71
|
+
title: result.title,
|
|
72
|
+
url: result.url,
|
|
73
|
+
text: result.description || "",
|
|
74
|
+
}));
|
|
75
|
+
return { results };
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
throw new Error(`Failed to perform web search: ${error}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
interface ExecuteOptions {
|
|
2
|
+
/** Working directory where the command will be executed */
|
|
3
|
+
cwd?: string;
|
|
4
|
+
/** Timeout in milliseconds before killing the process */
|
|
5
|
+
timeout?: number;
|
|
6
|
+
/** AbortSignal to cancel the execution */
|
|
7
|
+
abortSignal?: AbortSignal;
|
|
8
|
+
/** Whether to use shell syntax (defaults to false) */
|
|
9
|
+
shell?: boolean;
|
|
10
|
+
/** Whether to throw an error on non-zero exit codes (defaults to false) */
|
|
11
|
+
throwOnError?: boolean;
|
|
12
|
+
/** Whether to include stdout/stderr in the result even when there's an error (defaults to true) */
|
|
13
|
+
preserveOutputOnError?: boolean;
|
|
14
|
+
/** Maximum buffer size in bytes (defaults to 1MB) */
|
|
15
|
+
maxBuffer?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface ExecuteResult {
|
|
18
|
+
/** Standard output from the command */
|
|
19
|
+
stdout: string;
|
|
20
|
+
/** Standard error from the command */
|
|
21
|
+
stderr: string;
|
|
22
|
+
/** Exit code (0 for success, non-zero for errors) */
|
|
23
|
+
code: number;
|
|
24
|
+
/** The signal that terminated the process, if any */
|
|
25
|
+
signal?: NodeJS.Signals;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Executes a command and returns the result, providing unified error handling
|
|
29
|
+
*
|
|
30
|
+
* @param command Either a string command with arguments or an array where the first item is the command
|
|
31
|
+
* and the rest are arguments
|
|
32
|
+
* @param options Execution options
|
|
33
|
+
* @returns Promise resolving to an object containing stdout, stderr, and exit code
|
|
34
|
+
*/
|
|
35
|
+
export declare function executeCommand(command: string | [string, ...string[]], options?: ExecuteOptions): Promise<ExecuteResult>;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { isUndefined } from "@travisennis/stdlib/typeguards";
|
|
3
|
+
const MS_IN_SECOND = 1000;
|
|
4
|
+
const SECONDS_IN_MINUTE = 60;
|
|
5
|
+
const DEFAULT_TIMEOUT = 2 * SECONDS_IN_MINUTE * MS_IN_SECOND;
|
|
6
|
+
/**
|
|
7
|
+
* Executes a command and returns the result, providing unified error handling
|
|
8
|
+
*
|
|
9
|
+
* @param command Either a string command with arguments or an array where the first item is the command
|
|
10
|
+
* and the rest are arguments
|
|
11
|
+
* @param options Execution options
|
|
12
|
+
* @returns Promise resolving to an object containing stdout, stderr, and exit code
|
|
13
|
+
*/
|
|
14
|
+
export function executeCommand(command, options) {
|
|
15
|
+
const { cwd = process.cwd(), timeout = DEFAULT_TIMEOUT, abortSignal, shell = false, throwOnError = false, preserveOutputOnError = true, maxBuffer = 1_000_000, } = options || {};
|
|
16
|
+
let cmd;
|
|
17
|
+
let args;
|
|
18
|
+
if (Array.isArray(command)) {
|
|
19
|
+
[cmd, ...args] = command;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
const parts = command.split(" ");
|
|
23
|
+
cmd = parts[0] ?? "";
|
|
24
|
+
args = parts.slice(1);
|
|
25
|
+
}
|
|
26
|
+
if (isUndefined(cmd) || cmd.trim() === "") {
|
|
27
|
+
const result = {
|
|
28
|
+
stdout: "",
|
|
29
|
+
stderr: "Missing command",
|
|
30
|
+
code: 1,
|
|
31
|
+
};
|
|
32
|
+
return throwOnError
|
|
33
|
+
? Promise.reject(new Error("Missing command"))
|
|
34
|
+
: Promise.resolve(result);
|
|
35
|
+
}
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
try {
|
|
38
|
+
execFile(cmd, args, {
|
|
39
|
+
cwd,
|
|
40
|
+
timeout,
|
|
41
|
+
signal: abortSignal,
|
|
42
|
+
shell,
|
|
43
|
+
maxBuffer,
|
|
44
|
+
}, (error, stdout, stderr) => {
|
|
45
|
+
if (error) {
|
|
46
|
+
const errorCode = typeof error.code === "number" ? error.code : 1;
|
|
47
|
+
const result = {
|
|
48
|
+
stdout: preserveOutputOnError ? stdout : "",
|
|
49
|
+
stderr: preserveOutputOnError ? stderr : "",
|
|
50
|
+
code: errorCode,
|
|
51
|
+
signal: error.signal ?? undefined,
|
|
52
|
+
};
|
|
53
|
+
if (throwOnError) {
|
|
54
|
+
reject(Object.assign(error, { result }));
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
resolve(result);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
resolve({ stdout, stderr, code: 0 });
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
const result = { stdout: "", stderr: "", code: 1 };
|
|
67
|
+
if (throwOnError) {
|
|
68
|
+
reject(error);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
resolve(result);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getPackageVersion(fallback?: string): string;
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "@travisennis/stdlib/desm";
|
|
3
|
+
export function getPackageVersion(fallback = "unavailable") {
|
|
4
|
+
try {
|
|
5
|
+
const pkgPath = join(import.meta.url, "..", "package.json");
|
|
6
|
+
const pkgRaw = readFileSync(pkgPath, "utf8");
|
|
7
|
+
const parsed = JSON.parse(pkgRaw);
|
|
8
|
+
const v = typeof parsed.version === "string" ? parsed.version : undefined;
|
|
9
|
+
if (v && v.length > 0) {
|
|
10
|
+
return v;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
// ignore
|
|
15
|
+
}
|
|
16
|
+
const envV = process.env["npm_package_version"];
|
|
17
|
+
if (typeof envV === "string" && envV.length > 0) {
|
|
18
|
+
return envV;
|
|
19
|
+
}
|
|
20
|
+
return fallback;
|
|
21
|
+
}
|
package/knip.json
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@travisennis/acai",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "An AI assistant for developing software.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"acai": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"cli",
|
|
11
|
+
"ai",
|
|
12
|
+
"llm",
|
|
13
|
+
"coding",
|
|
14
|
+
"assistant"
|
|
15
|
+
],
|
|
16
|
+
"author": "Travis Ennis",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc --pretty -p tsconfig.build.json",
|
|
20
|
+
"clean": "rm -rf ./dist/",
|
|
21
|
+
"compile": "tsc --pretty -p tsconfig.json",
|
|
22
|
+
"lint": "biome lint",
|
|
23
|
+
"lint:fix": "biome lint --unsafe --write",
|
|
24
|
+
"lint:staged": "biome lint --error-on-warnings --no-errors-on-unmatched --staged",
|
|
25
|
+
"format:staged": "biome check --staged --formatter-enabled=true --linter-enabled=false --no-errors-on-unmatched",
|
|
26
|
+
"prepare": "husky",
|
|
27
|
+
"test": "c8 node --no-warnings --test test/**/*.test.ts",
|
|
28
|
+
"pretest": "npm run compile",
|
|
29
|
+
"format": "biome check --formatter-enabled=true --linter-enabled=false --write ./ && biome format --write",
|
|
30
|
+
"dev": "node --no-warnings --env-file=.env ./source/index.ts",
|
|
31
|
+
"oxlint": "npx oxlint@latest --ignore-path .gitignore --deny correctness --deny suspicous --deny pedantic --deny style --node-plugin",
|
|
32
|
+
"knip": "npx knip",
|
|
33
|
+
"check": "npx npm-check-updates --interactive --format group",
|
|
34
|
+
"cpd": "npx jscpd ./source",
|
|
35
|
+
"typecheck:staged": "tsc --noEmit --pretty -p tsconfig.json"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@ai-sdk/anthropic": "^2.0.2",
|
|
39
|
+
"@ai-sdk/deepseek": "^1.0.6",
|
|
40
|
+
"@ai-sdk/google": "^2.0.5",
|
|
41
|
+
"@ai-sdk/openai": "^2.0.11",
|
|
42
|
+
"@ai-sdk/openai-compatible": "^1.0.6",
|
|
43
|
+
"@crosscopy/clipboard": "^0.2.8",
|
|
44
|
+
"@inquirer/prompts": "^7.8.1",
|
|
45
|
+
"@travisennis/stdlib": "^0.0.13",
|
|
46
|
+
"ai": "^5.0.11",
|
|
47
|
+
"chalk": "^5.5.0",
|
|
48
|
+
"cheerio": "^1.1.2",
|
|
49
|
+
"cli-highlight": "^2.1.11",
|
|
50
|
+
"cli-table3": "^0.6.5",
|
|
51
|
+
"diff": "^8.0.2",
|
|
52
|
+
"duck-duck-scrape": "^2.2.7",
|
|
53
|
+
"exa-js": "^1.8.27",
|
|
54
|
+
"globby": "^14.1.0",
|
|
55
|
+
"ignore": "^7.0.5",
|
|
56
|
+
"log-update": "^6.1.0",
|
|
57
|
+
"marked": "16.1.2",
|
|
58
|
+
"node-notifier": "^10.0.1",
|
|
59
|
+
"ora": "^8.2.0",
|
|
60
|
+
"p-throttle": "^7.0.0",
|
|
61
|
+
"pino": "^9.8.0",
|
|
62
|
+
"pino-pretty": "^13.1.1",
|
|
63
|
+
"pino-roll": "^3.1.0",
|
|
64
|
+
"simple-git": "^3.28.0",
|
|
65
|
+
"tiktoken": "^1.0.22",
|
|
66
|
+
"wrap-ansi": "^9.0.0",
|
|
67
|
+
"zod": "^3.25.75"
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@ai-sdk/provider": "^2.0.0",
|
|
71
|
+
"@biomejs/biome": "2.1.4",
|
|
72
|
+
"@commitlint/config-conventional": "^19.8.1",
|
|
73
|
+
"@types/node": "^24.2.1",
|
|
74
|
+
"@types/node-notifier": "^8.0.5",
|
|
75
|
+
"c8": "^10.1.3",
|
|
76
|
+
"commitlint": "^19.8.1",
|
|
77
|
+
"husky": "^9.1.7",
|
|
78
|
+
"typescript": "^5.9.2"
|
|
79
|
+
},
|
|
80
|
+
"publishConfig": {
|
|
81
|
+
"access": "public"
|
|
82
|
+
}
|
|
83
|
+
}
|
package/source/cli.ts
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { AsyncReturnType } from "@travisennis/stdlib/types";
|
|
2
|
+
import {
|
|
3
|
+
generateObject,
|
|
4
|
+
generateText,
|
|
5
|
+
NoSuchToolError,
|
|
6
|
+
stepCountIs,
|
|
7
|
+
type ToolCallRepairFunction,
|
|
8
|
+
} from "ai";
|
|
9
|
+
import type z from "zod";
|
|
10
|
+
import { logger } from "./logger.ts";
|
|
11
|
+
import type { MessageHistory } from "./messages.ts";
|
|
12
|
+
import { AiConfig } from "./models/ai-config.ts";
|
|
13
|
+
import type { ModelManager } from "./models/manager.js";
|
|
14
|
+
import type { PromptManager } from "./prompts/manager.ts";
|
|
15
|
+
import { minSystemPrompt } from "./prompts.ts";
|
|
16
|
+
import type { TokenTracker } from "./token-tracker.ts";
|
|
17
|
+
import type { TokenCounter } from "./token-utils.ts";
|
|
18
|
+
import { DeleteFileTool } from "./tools/delete-file.ts";
|
|
19
|
+
import { EditFileTool } from "./tools/edit-file.ts";
|
|
20
|
+
import { initCliTools } from "./tools/index.ts";
|
|
21
|
+
import { MoveFileTool } from "./tools/move-file.ts";
|
|
22
|
+
import { SaveFileTool } from "./tools/save-file.ts";
|
|
23
|
+
import { ThinkTool } from "./tools/think.ts";
|
|
24
|
+
|
|
25
|
+
interface CliOptions {
|
|
26
|
+
messageHistory: MessageHistory;
|
|
27
|
+
promptManager: PromptManager;
|
|
28
|
+
modelManager: ModelManager;
|
|
29
|
+
tokenTracker: TokenTracker;
|
|
30
|
+
config: Record<PropertyKey, unknown>;
|
|
31
|
+
tokenCounter: TokenCounter;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type CompleteToolSet = AsyncReturnType<typeof initCliTools>;
|
|
35
|
+
|
|
36
|
+
export class Cli {
|
|
37
|
+
private options: CliOptions;
|
|
38
|
+
constructor(options: CliOptions) {
|
|
39
|
+
this.options = options;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async run() {
|
|
43
|
+
const {
|
|
44
|
+
config,
|
|
45
|
+
promptManager,
|
|
46
|
+
modelManager,
|
|
47
|
+
tokenTracker,
|
|
48
|
+
messageHistory,
|
|
49
|
+
tokenCounter,
|
|
50
|
+
} = this.options;
|
|
51
|
+
|
|
52
|
+
logger.info(config, "Config:");
|
|
53
|
+
|
|
54
|
+
const abortController = new AbortController();
|
|
55
|
+
const { signal } = abortController;
|
|
56
|
+
|
|
57
|
+
const cb = () => {
|
|
58
|
+
abortController.abort();
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Handle Ctrl+C (SIGINT)
|
|
62
|
+
process.on("SIGINT", cb);
|
|
63
|
+
|
|
64
|
+
const langModel = modelManager.getModel("cli");
|
|
65
|
+
const modelConfig = modelManager.getModelMetadata("cli");
|
|
66
|
+
|
|
67
|
+
const userPrompt = promptManager.get();
|
|
68
|
+
|
|
69
|
+
const userMsg = promptManager.getUserMessage();
|
|
70
|
+
|
|
71
|
+
messageHistory.appendUserMessage(userMsg);
|
|
72
|
+
|
|
73
|
+
const finalSystemPrompt = await minSystemPrompt();
|
|
74
|
+
|
|
75
|
+
const aiConfig = new AiConfig({
|
|
76
|
+
modelMetadata: modelConfig,
|
|
77
|
+
prompt: userPrompt,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const maxTokens = aiConfig.getMaxTokens();
|
|
81
|
+
|
|
82
|
+
const tools = modelConfig.supportsToolCalling
|
|
83
|
+
? await initCliTools({ tokenCounter })
|
|
84
|
+
: undefined;
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const result = await generateText({
|
|
88
|
+
model: langModel,
|
|
89
|
+
maxOutputTokens: maxTokens,
|
|
90
|
+
messages: [
|
|
91
|
+
{
|
|
92
|
+
role: "system",
|
|
93
|
+
content: finalSystemPrompt,
|
|
94
|
+
providerOptions: {
|
|
95
|
+
anthropic: { cacheControl: { type: "ephemeral" } },
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
...messageHistory.get(),
|
|
99
|
+
],
|
|
100
|
+
temperature: modelConfig.defaultTemperature,
|
|
101
|
+
stopWhen: stepCountIs(60),
|
|
102
|
+
maxRetries: 2,
|
|
103
|
+
providerOptions: aiConfig.getProviderOptions(),
|
|
104
|
+
tools,
|
|
105
|
+
// biome-ignore lint/style/useNamingConvention: third-party controlled
|
|
106
|
+
experimental_activeTools: [
|
|
107
|
+
EditFileTool.name,
|
|
108
|
+
SaveFileTool.name,
|
|
109
|
+
MoveFileTool.name,
|
|
110
|
+
DeleteFileTool.name,
|
|
111
|
+
ThinkTool.name,
|
|
112
|
+
],
|
|
113
|
+
// biome-ignore lint/style/useNamingConvention: third-party controlled
|
|
114
|
+
experimental_repairToolCall: modelConfig.supportsToolCalling
|
|
115
|
+
? toolCallRepair(modelManager)
|
|
116
|
+
: undefined,
|
|
117
|
+
abortSignal: signal,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (result.response.messages.length > 0) {
|
|
121
|
+
messageHistory.appendResponseMessages(result.response.messages);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// this tracks the usage of every step in the call to streamText. it's a cumulative usage.
|
|
125
|
+
tokenTracker.trackUsage("cli", result.usage);
|
|
126
|
+
|
|
127
|
+
process.stdout.end(
|
|
128
|
+
result.text.endsWith("\n") ? result.text : `${result.text}\n`,
|
|
129
|
+
);
|
|
130
|
+
} catch (e) {
|
|
131
|
+
if (e instanceof Error) {
|
|
132
|
+
logger.error(e);
|
|
133
|
+
} else {
|
|
134
|
+
logger.error(JSON.stringify(e, null, 2));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const toolCallRepair = (modelManager: ModelManager) => {
|
|
141
|
+
const fn: ToolCallRepairFunction<CompleteToolSet> = async ({
|
|
142
|
+
toolCall,
|
|
143
|
+
tools,
|
|
144
|
+
inputSchema,
|
|
145
|
+
error,
|
|
146
|
+
}) => {
|
|
147
|
+
if (NoSuchToolError.isInstance(error)) {
|
|
148
|
+
return null; // do not attempt to fix invalid tool names
|
|
149
|
+
}
|
|
150
|
+
const tool = tools[toolCall.toolName as keyof typeof tools];
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
const { object: repairedArgs } = await generateObject({
|
|
154
|
+
model: modelManager.getModel("tool-repair"),
|
|
155
|
+
schema: tool.inputSchema as z.ZodSchema<unknown>,
|
|
156
|
+
prompt: [
|
|
157
|
+
`The model tried to call the tool "${toolCall.toolName}" with the following arguments:`,
|
|
158
|
+
JSON.stringify(toolCall.input),
|
|
159
|
+
"The tool accepts the following schema:",
|
|
160
|
+
JSON.stringify(inputSchema(toolCall)),
|
|
161
|
+
"Please fix the arguments.",
|
|
162
|
+
].join("\n"),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
return { ...toolCall, args: JSON.stringify(repairedArgs) };
|
|
166
|
+
} catch (err) {
|
|
167
|
+
logger.error(err, `Failed to repair tool call: ${toolCall.toolName}.`);
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
return fn;
|
|
172
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { editor } from "@inquirer/prompts";
|
|
3
|
+
import { config } from "../config.ts";
|
|
4
|
+
import type { CommandOptions, ReplCommand } from "./types.ts";
|
|
5
|
+
|
|
6
|
+
export const applicationLogCommand = ({
|
|
7
|
+
terminal,
|
|
8
|
+
}: CommandOptions): ReplCommand => {
|
|
9
|
+
return {
|
|
10
|
+
command: "/application-logs",
|
|
11
|
+
description:
|
|
12
|
+
"Opens the application log file defined in acai.json in the editor.",
|
|
13
|
+
result: "continue" as const,
|
|
14
|
+
getSubCommands: () => Promise.resolve([]),
|
|
15
|
+
execute: async () => {
|
|
16
|
+
let logFilePath: string | undefined;
|
|
17
|
+
try {
|
|
18
|
+
const projectConfig = await config.readProjectConfig();
|
|
19
|
+
logFilePath = projectConfig.logs?.path;
|
|
20
|
+
|
|
21
|
+
if (!logFilePath) {
|
|
22
|
+
terminal.error(
|
|
23
|
+
"Application log path is not defined in .acai/acai.json under the 'logs.path' key.",
|
|
24
|
+
);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const content = await readFile(logFilePath, { encoding: "utf8" });
|
|
29
|
+
|
|
30
|
+
// Use the editor prompt to display the content (read-only)
|
|
31
|
+
await editor({
|
|
32
|
+
message: `Viewing ${logFilePath}`,
|
|
33
|
+
// Attempt to infer postfix from file extension, default otherwise
|
|
34
|
+
postfix: logFilePath.includes(".")
|
|
35
|
+
? `.${logFilePath.split(".").pop()}`
|
|
36
|
+
: ".log",
|
|
37
|
+
default: content,
|
|
38
|
+
// By not providing an onSubmit or similar handler to write the file,
|
|
39
|
+
// and not calling writeFileSync after, this effectively becomes read-only.
|
|
40
|
+
});
|
|
41
|
+
terminal.info(`Closed log view for: ${logFilePath}`);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
if (logFilePath && (error as NodeJS.ErrnoException).code === "ENOENT") {
|
|
44
|
+
terminal.error(`Application log file not found at: ${logFilePath}`);
|
|
45
|
+
} else {
|
|
46
|
+
terminal.error(
|
|
47
|
+
`Error reading or displaying log file ${logFilePath ?? "specified in config"}: ${error}`,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CommandOptions, ReplCommand } from "./types.ts";
|
|
2
|
+
|
|
3
|
+
export const clearCommand = ({ terminal }: CommandOptions): ReplCommand => {
|
|
4
|
+
return {
|
|
5
|
+
command: "/clear",
|
|
6
|
+
description: "Clears the terminal screen.",
|
|
7
|
+
result: "continue" as const, // Keep the REPL running
|
|
8
|
+
getSubCommands: () => Promise.resolve([]),
|
|
9
|
+
execute: () => {
|
|
10
|
+
terminal.clear();
|
|
11
|
+
return Promise.resolve();
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { generateText } from "ai";
|
|
2
|
+
import { createUserMessage } from "../messages.ts";
|
|
3
|
+
import type { CommandOptions, ReplCommand } from "./types.ts";
|
|
4
|
+
|
|
5
|
+
export const compactCommand = (options: CommandOptions): ReplCommand => {
|
|
6
|
+
return {
|
|
7
|
+
command: "/compact",
|
|
8
|
+
description:
|
|
9
|
+
"Saves, summarizes, and resets the chat history. Optional instructions can be provided for the summary.",
|
|
10
|
+
result: "continue" as const,
|
|
11
|
+
getSubCommands: () => Promise.resolve([]),
|
|
12
|
+
execute: async (args: string[]) => {
|
|
13
|
+
const { messageHistory, terminal } = options;
|
|
14
|
+
if (!messageHistory.isEmpty()) {
|
|
15
|
+
const additionalInstructions = args.join(" ");
|
|
16
|
+
await summarizeAndReset(options, additionalInstructions);
|
|
17
|
+
}
|
|
18
|
+
terminal.info("Message history summarized and reset.");
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
async function summarizeAndReset(
|
|
24
|
+
{ messageHistory, modelManager, tokenTracker }: CommandOptions,
|
|
25
|
+
additionalInstructions?: string,
|
|
26
|
+
) {
|
|
27
|
+
const app = "conversation-summarizer";
|
|
28
|
+
|
|
29
|
+
// save existing message history
|
|
30
|
+
await messageHistory.save();
|
|
31
|
+
|
|
32
|
+
// summarize message history
|
|
33
|
+
let userPrompt = `Your tasks is to provide a detailed summary of our conversation so far. Focus on information that would be helpful for continuing the conversation and the task, including what was the orginal task requested by the user, what we have done so far and why, which files we're working on, and what we're going to do next. Pay special attention to specific user feedback that you received, especially if the user told you to do something differently. You need to provide enough information that another coding agent can you use your summary to pick up where you have left off.
|
|
34
|
+
|
|
35
|
+
Your summary should include the following sections:
|
|
36
|
+
1. Primary Request and Intent: Capture all of the user's explicit requests and intents in detail
|
|
37
|
+
2. Key Technical Concepts: List all important technical concepts, technologies, and frameworks discussed.
|
|
38
|
+
3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.
|
|
39
|
+
4. Errors and fixes: List all errors that you ran into, and how you fixed them. Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
|
|
40
|
+
5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.
|
|
41
|
+
6. All user messages: List ALL user messages that are not tool results. These are critical for understanding the users' feedback and changing intent.
|
|
42
|
+
7. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.
|
|
43
|
+
8. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.
|
|
44
|
+
9. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's explicit requests, and the task you were working on immediately before this summary request. If your last task was concluded, then only list next steps if they are explicitly in line with the users request. Do not start on tangential requests without confirming with the user first.
|
|
45
|
+
|
|
46
|
+
If there is a next step, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no drift in task interpretation.`;
|
|
47
|
+
if (additionalInstructions && additionalInstructions.trim().length > 0) {
|
|
48
|
+
userPrompt += `\n\nAdditional instructions provided by the user: ${additionalInstructions}`;
|
|
49
|
+
}
|
|
50
|
+
messageHistory.appendUserMessage(createUserMessage([], userPrompt));
|
|
51
|
+
const { text, usage } = await generateText({
|
|
52
|
+
model: modelManager.getModel(app),
|
|
53
|
+
system:
|
|
54
|
+
"You are a helpful AI assistant tasked with summarizing conversations so that a coding agent such as yourself can understand what actions have been taken on a code base and what future work still needs to be done.",
|
|
55
|
+
messages: messageHistory.get(),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
tokenTracker.trackUsage(app, usage);
|
|
59
|
+
|
|
60
|
+
//clear messages
|
|
61
|
+
messageHistory.clear();
|
|
62
|
+
|
|
63
|
+
messageHistory.appendUserMessage(createUserMessage([text]));
|
|
64
|
+
}
|