@travisennis/acai 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +190 -19
- package/bin/acai-wrapper.js +26 -0
- package/dist/agent/index.d.ts +132 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +434 -0
- package/dist/api/exa/index.js +1 -1
- package/dist/cli.d.ts +4 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +67 -40
- package/dist/commands/add-directory-command.d.ts +3 -0
- package/dist/commands/add-directory-command.d.ts.map +1 -0
- package/dist/commands/add-directory-command.js +54 -0
- package/dist/commands/application-log-command.d.ts +1 -1
- package/dist/commands/application-log-command.d.ts.map +1 -1
- package/dist/commands/application-log-command.js +18 -20
- package/dist/commands/clear-command.d.ts +1 -1
- package/dist/commands/clear-command.d.ts.map +1 -1
- package/dist/commands/clear-command.js +7 -3
- package/dist/commands/compact-command.d.ts.map +1 -1
- package/dist/commands/compact-command.js +9 -5
- package/dist/commands/context-command.d.ts +3 -0
- package/dist/commands/context-command.d.ts.map +1 -0
- package/dist/commands/context-command.js +124 -0
- package/dist/commands/copy-command.d.ts.map +1 -1
- package/dist/commands/copy-command.js +14 -5
- package/dist/commands/edit-command.d.ts +1 -1
- package/dist/commands/edit-command.d.ts.map +1 -1
- package/dist/commands/edit-command.js +21 -34
- package/dist/commands/edit-prompt-command.d.ts +1 -1
- package/dist/commands/edit-prompt-command.d.ts.map +1 -1
- package/dist/commands/edit-prompt-command.js +18 -15
- package/dist/commands/exit-command.d.ts +1 -4
- package/dist/commands/exit-command.d.ts.map +1 -1
- package/dist/commands/exit-command.js +9 -5
- package/dist/commands/files-command.d.ts +1 -1
- package/dist/commands/files-command.d.ts.map +1 -1
- package/dist/commands/files-command.js +20 -16
- package/dist/commands/generate-rules-command.d.ts +1 -1
- package/dist/commands/generate-rules-command.d.ts.map +1 -1
- package/dist/commands/generate-rules-command.js +307 -39
- package/dist/commands/handoff-command.d.ts +3 -0
- package/dist/commands/handoff-command.d.ts.map +1 -0
- package/dist/commands/handoff-command.js +191 -0
- package/dist/commands/health-command.d.ts +1 -1
- package/dist/commands/health-command.d.ts.map +1 -1
- package/dist/commands/health-command.js +49 -27
- package/dist/commands/help-command.d.ts +1 -1
- package/dist/commands/help-command.d.ts.map +1 -1
- package/dist/commands/help-command.js +25 -5
- package/dist/commands/history-command.d.ts +3 -0
- package/dist/commands/history-command.d.ts.map +1 -0
- package/dist/commands/history-command.js +458 -0
- package/dist/commands/init-command.d.ts +1 -1
- package/dist/commands/init-command.d.ts.map +1 -1
- package/dist/commands/init-command.js +40 -22
- package/dist/commands/last-log-command.d.ts +1 -1
- package/dist/commands/last-log-command.d.ts.map +1 -1
- package/dist/commands/last-log-command.js +15 -15
- package/dist/commands/list-directories-command.d.ts +3 -0
- package/dist/commands/list-directories-command.d.ts.map +1 -0
- package/dist/commands/list-directories-command.js +35 -0
- package/dist/commands/list-tools-command.d.ts.map +1 -1
- package/dist/commands/list-tools-command.js +61 -21
- package/dist/commands/manager.d.ts +9 -4
- package/dist/commands/manager.d.ts.map +1 -1
- package/dist/commands/manager.js +64 -39
- package/dist/commands/model-command.d.ts.map +1 -1
- package/dist/commands/model-command.js +201 -66
- package/dist/commands/paste-command.d.ts +1 -1
- package/dist/commands/paste-command.d.ts.map +1 -1
- package/dist/commands/paste-command.js +23 -9
- package/dist/commands/pickup-command.d.ts +3 -0
- package/dist/commands/pickup-command.d.ts.map +1 -0
- package/dist/commands/pickup-command.js +109 -0
- package/dist/commands/prompt-command.d.ts +19 -1
- package/dist/commands/prompt-command.d.ts.map +1 -1
- package/dist/commands/prompt-command.js +191 -98
- package/dist/commands/remove-directory-command.d.ts +3 -0
- package/dist/commands/remove-directory-command.d.ts.map +1 -0
- package/dist/commands/remove-directory-command.js +55 -0
- package/dist/commands/reset-command.d.ts +1 -1
- package/dist/commands/reset-command.d.ts.map +1 -1
- package/dist/commands/reset-command.js +8 -5
- package/dist/commands/rules-command.d.ts +1 -1
- package/dist/commands/rules-command.d.ts.map +1 -1
- package/dist/commands/rules-command.js +25 -22
- package/dist/commands/save-command.d.ts +1 -1
- package/dist/commands/save-command.d.ts.map +1 -1
- package/dist/commands/save-command.js +8 -3
- package/dist/commands/shell-command.d.ts.map +1 -1
- package/dist/commands/shell-command.js +45 -24
- package/dist/commands/types.d.ts +9 -7
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/usage-command.d.ts +1 -1
- package/dist/commands/usage-command.d.ts.map +1 -1
- package/dist/commands/usage-command.js +18 -7
- package/dist/config.d.ts +21 -11
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +90 -63
- package/dist/execution/index.d.ts +17 -2
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/index.js +62 -20
- package/dist/formatting.d.ts +127 -0
- package/dist/formatting.d.ts.map +1 -1
- package/dist/formatting.js +201 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +263 -102
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +47 -18
- package/dist/mentions.d.ts +2 -1
- package/dist/mentions.d.ts.map +1 -1
- package/dist/mentions.js +16 -1
- package/dist/messages.d.ts +11 -0
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +122 -21
- package/dist/middleware/cache.d.ts +3 -0
- package/dist/middleware/cache.d.ts.map +1 -0
- package/dist/middleware/cache.js +53 -0
- package/dist/middleware/index.d.ts +1 -0
- package/dist/middleware/index.d.ts.map +1 -1
- package/dist/middleware/index.js +1 -0
- package/dist/models/ai-config.d.ts +4 -2
- package/dist/models/ai-config.d.ts.map +1 -1
- package/dist/models/ai-config.js +12 -2
- package/dist/models/anthropic-provider.d.ts.map +1 -1
- package/dist/models/anthropic-provider.js +3 -67
- package/dist/models/deepseek-provider.d.ts.map +1 -1
- package/dist/models/deepseek-provider.js +0 -2
- package/dist/models/google-provider.d.ts.map +1 -1
- package/dist/models/google-provider.js +0 -3
- package/dist/models/groq-provider.d.ts.map +1 -1
- package/dist/models/groq-provider.js +0 -1
- package/dist/models/manager.d.ts +2 -1
- package/dist/models/manager.d.ts.map +1 -1
- package/dist/models/manager.js +26 -2
- package/dist/models/openai-provider.d.ts.map +1 -1
- package/dist/models/openai-provider.js +0 -4
- package/dist/models/openrouter-provider.d.ts +16 -22
- package/dist/models/openrouter-provider.d.ts.map +1 -1
- package/dist/models/openrouter-provider.js +175 -236
- package/dist/models/providers.d.ts +4 -14
- package/dist/models/providers.d.ts.map +1 -1
- package/dist/models/providers.js +1 -57
- package/dist/models/xai-provider.d.ts.map +1 -1
- package/dist/models/xai-provider.js +0 -2
- package/dist/prompts.d.ts +10 -4
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +447 -70
- package/dist/repl/project-status-line.d.ts +3 -0
- package/dist/repl/project-status-line.d.ts.map +1 -0
- package/dist/repl/project-status-line.js +61 -0
- package/dist/repl/tool-call-repair.d.ts.map +1 -1
- package/dist/repl/tool-call-repair.js +8 -4
- package/dist/repl-new.d.ts +51 -0
- package/dist/repl-new.d.ts.map +1 -0
- package/dist/repl-new.js +354 -0
- package/dist/skills.d.ts +20 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +192 -0
- package/dist/terminal/control.d.ts +55 -0
- package/dist/terminal/control.d.ts.map +1 -0
- package/dist/terminal/control.js +109 -0
- package/dist/terminal/default-theme.d.ts +1 -1
- package/dist/terminal/default-theme.d.ts.map +1 -1
- package/dist/terminal/default-theme.js +24 -28
- package/dist/terminal/formatting.d.ts +23 -25
- package/dist/terminal/formatting.d.ts.map +1 -1
- package/dist/terminal/formatting.js +35 -52
- package/dist/terminal/highlight/index.d.ts.map +1 -1
- package/dist/terminal/highlight/index.js +3 -6
- package/dist/terminal/highlight/theme.d.ts.map +1 -1
- package/dist/terminal/highlight/theme.js +2 -6
- package/dist/terminal/index.d.ts +2 -94
- package/dist/terminal/index.d.ts.map +1 -1
- package/dist/terminal/index.js +2 -370
- package/dist/terminal/markdown.js +10 -5
- package/dist/terminal/select-prompt.d.ts +2 -2
- package/dist/terminal/select-prompt.d.ts.map +1 -1
- package/dist/terminal/select-prompt.js +47 -39
- package/dist/terminal/strip-ansi.js +4 -4
- package/dist/terminal/table/cell.d.ts +114 -0
- package/dist/terminal/table/cell.d.ts.map +1 -0
- package/dist/terminal/table/cell.js +407 -0
- package/dist/terminal/table/debug.d.ts +15 -0
- package/dist/terminal/table/debug.d.ts.map +1 -0
- package/dist/terminal/table/debug.js +32 -0
- package/dist/terminal/table/index.d.ts +3 -0
- package/dist/terminal/table/index.d.ts.map +1 -0
- package/dist/terminal/table/index.js +2 -0
- package/dist/terminal/table/layout-manager.d.ts +27 -0
- package/dist/terminal/table/layout-manager.d.ts.map +1 -0
- package/dist/terminal/table/layout-manager.js +257 -0
- package/dist/terminal/table/table.d.ts +9 -0
- package/dist/terminal/table/table.d.ts.map +1 -0
- package/dist/terminal/table/table.js +97 -0
- package/dist/terminal/table/utils.d.ts +63 -0
- package/dist/terminal/table/utils.d.ts.map +1 -0
- package/dist/terminal/table/utils.js +326 -0
- package/dist/tokens/threshold.d.ts +20 -0
- package/dist/tokens/threshold.d.ts.map +1 -0
- package/dist/tokens/threshold.js +67 -0
- package/dist/tools/advanced-edit-file.d.ts +69 -0
- package/dist/tools/advanced-edit-file.d.ts.map +1 -0
- package/dist/tools/advanced-edit-file.js +285 -0
- package/dist/tools/agent.d.ts +16 -5
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/agent.js +86 -59
- package/dist/tools/bash.d.ts +23 -12
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +243 -128
- package/dist/tools/batch.d.ts +34 -0
- package/dist/tools/batch.d.ts.map +1 -0
- package/dist/tools/batch.js +174 -0
- package/dist/tools/code-interpreter.d.ts +21 -9
- package/dist/tools/code-interpreter.d.ts.map +1 -1
- package/dist/tools/code-interpreter.js +151 -134
- package/dist/tools/delete-file.d.ts +17 -10
- package/dist/tools/delete-file.d.ts.map +1 -1
- package/dist/tools/delete-file.js +60 -97
- package/dist/tools/directory-tree.d.ts +17 -12
- package/dist/tools/directory-tree.d.ts.map +1 -1
- package/dist/tools/directory-tree.js +57 -48
- package/dist/tools/dynamic-tool-loader.d.ts +16 -10
- package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
- package/dist/tools/dynamic-tool-loader.js +122 -130
- package/dist/tools/dynamic-tool-parser.d.ts +1 -0
- package/dist/tools/dynamic-tool-parser.d.ts.map +1 -1
- package/dist/tools/dynamic-tool-parser.js +1 -0
- package/dist/tools/edit-file.d.ts +35 -15
- package/dist/tools/edit-file.d.ts.map +1 -1
- package/dist/tools/edit-file.js +127 -114
- package/dist/tools/glob.d.ts +36 -0
- package/dist/tools/glob.d.ts.map +1 -0
- package/dist/tools/glob.js +154 -0
- package/dist/tools/grep.d.ts +73 -12
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +425 -165
- package/dist/tools/index.d.ts +220 -126
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +284 -135
- package/dist/tools/llm-edit-fixer.d.ts +24 -0
- package/dist/tools/llm-edit-fixer.d.ts.map +1 -0
- package/dist/tools/llm-edit-fixer.js +136 -0
- package/dist/tools/move-file.d.ts +19 -7
- package/dist/tools/move-file.d.ts.map +1 -1
- package/dist/tools/move-file.js +48 -34
- package/dist/tools/read-file.d.ts +47 -9
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +84 -70
- package/dist/tools/read-multiple-files.d.ts +17 -6
- package/dist/tools/read-multiple-files.d.ts.map +1 -1
- package/dist/tools/read-multiple-files.js +132 -72
- package/dist/tools/save-file.d.ts +45 -12
- package/dist/tools/save-file.d.ts.map +1 -1
- package/dist/tools/save-file.js +76 -101
- package/dist/tools/think.d.ts +15 -7
- package/dist/tools/think.d.ts.map +1 -1
- package/dist/tools/think.js +34 -20
- package/dist/tools/types.d.ts +8 -10
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js +9 -0
- package/dist/tools/utils.d.ts +14 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +16 -0
- package/dist/tools/web-fetch.d.ts +11 -4
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +39 -38
- package/dist/tools/web-search.d.ts +15 -6
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +64 -31
- package/dist/tui/autocomplete.d.ts +44 -0
- package/dist/tui/autocomplete.d.ts.map +1 -0
- package/dist/tui/autocomplete.js +466 -0
- package/dist/tui/components/assistant-message.d.ts +18 -0
- package/dist/tui/components/assistant-message.d.ts.map +1 -0
- package/dist/tui/components/assistant-message.js +29 -0
- package/dist/tui/components/box.d.ts +20 -0
- package/dist/tui/components/box.d.ts.map +1 -0
- package/dist/tui/components/box.js +81 -0
- package/dist/tui/components/editor.d.ts +106 -0
- package/dist/tui/components/editor.d.ts.map +1 -0
- package/dist/tui/components/editor.js +1220 -0
- package/dist/tui/components/footer.d.ts +12 -0
- package/dist/tui/components/footer.d.ts.map +1 -0
- package/dist/tui/components/footer.js +209 -0
- package/dist/tui/components/header.d.ts +21 -0
- package/dist/tui/components/header.d.ts.map +1 -0
- package/dist/tui/components/header.js +63 -0
- package/dist/tui/components/input.d.ts +14 -0
- package/dist/tui/components/input.d.ts.map +1 -0
- package/dist/tui/components/input.js +122 -0
- package/dist/tui/components/loader.d.ts +23 -0
- package/dist/tui/components/loader.d.ts.map +1 -0
- package/dist/tui/components/loader.js +45 -0
- package/dist/tui/components/markdown.d.ts +106 -0
- package/dist/tui/components/markdown.d.ts.map +1 -0
- package/dist/tui/components/markdown.js +586 -0
- package/dist/tui/components/modal.d.ts +29 -0
- package/dist/tui/components/modal.d.ts.map +1 -0
- package/dist/tui/components/modal.js +263 -0
- package/dist/tui/components/progress-bar.d.ts +19 -0
- package/dist/tui/components/progress-bar.d.ts.map +1 -0
- package/dist/tui/components/progress-bar.js +78 -0
- package/dist/tui/components/prompt-status.d.ts +17 -0
- package/dist/tui/components/prompt-status.d.ts.map +1 -0
- package/dist/tui/components/prompt-status.js +26 -0
- package/dist/tui/components/select-list.d.ts +48 -0
- package/dist/tui/components/select-list.d.ts.map +1 -0
- package/dist/tui/components/select-list.js +207 -0
- package/dist/tui/components/spacer.d.ts +16 -0
- package/dist/tui/components/spacer.d.ts.map +1 -0
- package/dist/tui/components/spacer.js +27 -0
- package/dist/tui/components/table.d.ts +27 -0
- package/dist/tui/components/table.d.ts.map +1 -0
- package/dist/tui/components/table.js +125 -0
- package/dist/tui/components/text.d.ts +26 -0
- package/dist/tui/components/text.d.ts.map +1 -0
- package/dist/tui/components/text.js +143 -0
- package/dist/tui/components/thinking-block.d.ts +14 -0
- package/dist/tui/components/thinking-block.d.ts.map +1 -0
- package/dist/tui/components/thinking-block.js +33 -0
- package/dist/tui/components/tool-execution.d.ts +21 -0
- package/dist/tui/components/tool-execution.d.ts.map +1 -0
- package/dist/tui/components/tool-execution.js +161 -0
- package/dist/tui/components/user-message.d.ts +9 -0
- package/dist/tui/components/user-message.d.ts.map +1 -0
- package/dist/tui/components/user-message.js +23 -0
- package/dist/tui/components/welcome.d.ts +6 -0
- package/dist/tui/components/welcome.d.ts.map +1 -0
- package/dist/tui/components/welcome.js +30 -0
- package/dist/tui/index.d.ts +18 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +22 -0
- package/dist/tui/terminal.d.ts +38 -0
- package/dist/tui/terminal.d.ts.map +1 -0
- package/dist/tui/terminal.js +94 -0
- package/dist/tui/tui.d.ts +69 -0
- package/dist/tui/tui.d.ts.map +1 -0
- package/dist/tui/tui.js +204 -0
- package/dist/tui/utils.d.ts +24 -0
- package/dist/tui/utils.d.ts.map +1 -0
- package/dist/tui/utils.js +111 -0
- package/dist/utils/bash.d.ts +7 -0
- package/dist/utils/bash.d.ts.map +1 -0
- package/dist/{tools/bash-utils.js → utils/bash.js} +31 -12
- package/dist/utils/{filesystem.d.ts → filesystem/operations.d.ts} +1 -1
- package/dist/utils/filesystem/operations.d.ts.map +1 -0
- package/dist/utils/filesystem/security.d.ts +9 -0
- package/dist/utils/filesystem/security.d.ts.map +1 -0
- package/dist/{tools/filesystem-utils.js → utils/filesystem/security.js} +93 -21
- package/dist/utils/funcs.d.ts +6 -0
- package/dist/utils/funcs.d.ts.map +1 -0
- package/dist/utils/funcs.js +6 -0
- package/dist/utils/generators.d.ts +3 -0
- package/dist/utils/generators.d.ts.map +1 -0
- package/dist/utils/generators.js +25 -0
- package/dist/{tools/git-utils.d.ts → utils/git.d.ts} +1 -1
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/{tools/git-utils.js → utils/git.js} +0 -6
- package/dist/utils/glob.js +1 -1
- package/dist/utils/iterables.d.ts +2 -0
- package/dist/utils/iterables.d.ts.map +1 -0
- package/dist/utils/iterables.js +6 -0
- package/dist/utils/{zod-utils.d.ts → zod.d.ts} +1 -1
- package/dist/utils/zod.d.ts.map +1 -0
- package/package.json +21 -21
- package/dist/conversation-analyzer.d.ts +0 -11
- package/dist/conversation-analyzer.d.ts.map +0 -1
- package/dist/conversation-analyzer.js +0 -88
- package/dist/repl/display-tool-messages.d.ts +0 -4
- package/dist/repl/display-tool-messages.d.ts.map +0 -1
- package/dist/repl/display-tool-messages.js +0 -55
- package/dist/repl/display-tool-use.d.ts +0 -14
- package/dist/repl/display-tool-use.d.ts.map +0 -1
- package/dist/repl/display-tool-use.js +0 -63
- package/dist/repl/get-prompt-header.d.ts +0 -8
- package/dist/repl/get-prompt-header.d.ts.map +0 -1
- package/dist/repl/get-prompt-header.js +0 -38
- package/dist/repl-prompt.d.ts +0 -15
- package/dist/repl-prompt.d.ts.map +0 -1
- package/dist/repl-prompt.js +0 -147
- package/dist/repl.d.ts +0 -31
- package/dist/repl.d.ts.map +0 -1
- package/dist/repl.js +0 -310
- package/dist/terminal/checkbox-prompt.d.ts +0 -36
- package/dist/terminal/checkbox-prompt.d.ts.map +0 -1
- package/dist/terminal/checkbox-prompt.js +0 -362
- package/dist/terminal/editor-prompt.d.ts +0 -10
- package/dist/terminal/editor-prompt.d.ts.map +0 -1
- package/dist/terminal/editor-prompt.js +0 -61
- package/dist/terminal/errors.d.ts +0 -19
- package/dist/terminal/errors.d.ts.map +0 -1
- package/dist/terminal/errors.js +0 -37
- package/dist/terminal/input-prompt.d.ts +0 -16
- package/dist/terminal/input-prompt.d.ts.map +0 -1
- package/dist/terminal/input-prompt.js +0 -181
- package/dist/terminal/search-prompt.d.ts +0 -20
- package/dist/terminal/search-prompt.d.ts.map +0 -1
- package/dist/terminal/search-prompt.js +0 -279
- package/dist/terminal/types.d.ts +0 -35
- package/dist/terminal/types.d.ts.map +0 -1
- package/dist/terminal/types.js +0 -1
- package/dist/tokens/manage-output.d.ts +0 -34
- package/dist/tokens/manage-output.d.ts.map +0 -1
- package/dist/tokens/manage-output.js +0 -44
- package/dist/tool-executor.d.ts +0 -28
- package/dist/tool-executor.d.ts.map +0 -1
- package/dist/tool-executor.js +0 -74
- package/dist/tools/bash-utils.d.ts +0 -7
- package/dist/tools/bash-utils.d.ts.map +0 -1
- package/dist/tools/file-editing-utils.d.ts +0 -2
- package/dist/tools/file-editing-utils.d.ts.map +0 -1
- package/dist/tools/file-editing-utils.js +0 -135
- package/dist/tools/filesystem-utils.d.ts +0 -7
- package/dist/tools/filesystem-utils.d.ts.map +0 -1
- package/dist/tools/git-utils.d.ts.map +0 -1
- package/dist/utils/filesystem.d.ts.map +0 -1
- package/dist/utils/zod-utils.d.ts.map +0 -1
- /package/dist/utils/{filesystem.js → filesystem/operations.js} +0 -0
- /package/dist/utils/{zod-utils.js → zod.js} +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
2
3
|
import path from "node:path";
|
|
3
|
-
import {
|
|
4
|
+
import { isPathWithinAllowedDirs } from "./filesystem/security.js";
|
|
4
5
|
// Validate path arguments to ensure they're within the project
|
|
5
|
-
export function validatePaths(command,
|
|
6
|
+
export function validatePaths(command, allowedDirs, cwd) {
|
|
6
7
|
// Simple tokenization - split on spaces but respect quotes
|
|
7
8
|
const tokens = [];
|
|
8
9
|
let current = "";
|
|
@@ -43,7 +44,7 @@ export function validatePaths(command, baseDir, cwd) {
|
|
|
43
44
|
// Skip if it's clearly not a path
|
|
44
45
|
if (cleanToken.startsWith("-") ||
|
|
45
46
|
cleanToken.includes("://") ||
|
|
46
|
-
!cleanToken.includes("/")) {
|
|
47
|
+
(!cleanToken.includes("/") && cleanToken !== "~")) {
|
|
47
48
|
continue;
|
|
48
49
|
}
|
|
49
50
|
// Skip git commit messages and other special cases
|
|
@@ -52,11 +53,16 @@ export function validatePaths(command, baseDir, cwd) {
|
|
|
52
53
|
continue;
|
|
53
54
|
}
|
|
54
55
|
try {
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
// Expand ~ to home directory for proper validation
|
|
57
|
+
const expandedToken = cleanToken.startsWith("~/") || cleanToken === "~"
|
|
58
|
+
? path.join(os.homedir(), cleanToken.slice(1))
|
|
59
|
+
: cleanToken;
|
|
60
|
+
const resolvedPath = path.resolve(cwd, expandedToken);
|
|
61
|
+
// Allow access to explicitly allowed paths
|
|
62
|
+
if (!isPathWithinAllowedDirs(resolvedPath, allowedDirs)) {
|
|
57
63
|
return {
|
|
58
64
|
isValid: false,
|
|
59
|
-
error: `Path '${cleanToken}' resolves outside the
|
|
65
|
+
error: `Path '${cleanToken}' resolves outside the allowed directories (${resolvedPath}). All paths must be within ${allowedDirs.join(", ")}`,
|
|
60
66
|
};
|
|
61
67
|
}
|
|
62
68
|
}
|
|
@@ -64,8 +70,12 @@ export function validatePaths(command, baseDir, cwd) {
|
|
|
64
70
|
}
|
|
65
71
|
return { isValid: true };
|
|
66
72
|
}
|
|
67
|
-
export const resolveCwd = (cwdInput, workingDir) => {
|
|
68
|
-
|
|
73
|
+
export const resolveCwd = (cwdInput, workingDir, allowedDirs) => {
|
|
74
|
+
// Determine which directory to use as the base for resolving relative paths
|
|
75
|
+
// If allowedDirs is provided and non-empty, use the first allowed directory
|
|
76
|
+
// Otherwise use the workingDir parameter (backward compatibility)
|
|
77
|
+
const baseDirForResolution = allowedDirs && allowedDirs.length > 0 ? allowedDirs[0] : workingDir;
|
|
78
|
+
const projectRootAbs = path.resolve(baseDirForResolution);
|
|
69
79
|
let projectRoot = projectRootAbs;
|
|
70
80
|
try {
|
|
71
81
|
projectRoot = fs.realpathSync(projectRootAbs);
|
|
@@ -84,10 +94,19 @@ export const resolveCwd = (cwdInput, workingDir) => {
|
|
|
84
94
|
catch {
|
|
85
95
|
// If the path doesn't exist entirely, validate intended path
|
|
86
96
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
97
|
+
// Check if within allowed directories if provided, otherwise check project root
|
|
98
|
+
if (allowedDirs && allowedDirs.length > 0) {
|
|
99
|
+
if (!isPathWithinAllowedDirs(target, allowedDirs)) {
|
|
100
|
+
throw new Error(`Working directory must be within the allowed directories: ${allowedDirs.join(", ")}. Received: ${cwdInput ?? "<default>"} -> ${target}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// Fallback to original behavior: check within project root
|
|
105
|
+
const rel = path.relative(projectRoot, target);
|
|
106
|
+
const inside = rel === "" || (!rel.startsWith("..") && !path.isAbsolute(rel));
|
|
107
|
+
if (!inside) {
|
|
108
|
+
throw new Error(`Working directory must be within the project directory: ${projectRoot}. Received: ${cwdInput ?? "<default>"} -> ${target}`);
|
|
109
|
+
}
|
|
91
110
|
}
|
|
92
111
|
// Check existence and that it's a directory
|
|
93
112
|
let stats;
|
|
@@ -20,4 +20,4 @@ export declare function isDirectory(filePath: URL | string): Promise<boolean>;
|
|
|
20
20
|
* @throws Error if directory cannot be cleared or if path is invalid/unsafe
|
|
21
21
|
*/
|
|
22
22
|
export declare function clearDirectory(directoryPath: URL | string): Promise<void>;
|
|
23
|
-
//# sourceMappingURL=
|
|
23
|
+
//# sourceMappingURL=operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../../source/utils/filesystem/operations.ts"],"names":[],"mappings":"AAIA,wBAAgB,MAAM,CAAC,SAAS,EAAE,GAAG,GAAG,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAS/C;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,GAAG,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAmB1E;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,aAAa,EAAE,GAAG,GAAG,MAAM,GAC1B,OAAO,CAAC,IAAI,CAAC,CAuGf"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ProjectConfig } from "../../config.ts";
|
|
2
|
+
export declare function joinWorkingDir(userPath: string, workingDir: string): string;
|
|
3
|
+
export declare function isPathWithinAllowedDirs(requestedPath: string, allowedDirs: string[]): boolean;
|
|
4
|
+
export declare function validatePath(requestedPath: string, allowedDirectory: string | string[], options?: {
|
|
5
|
+
requireExistence?: boolean;
|
|
6
|
+
abortSignal?: AbortSignal;
|
|
7
|
+
}): Promise<string>;
|
|
8
|
+
export declare function validateFileNotReadOnly(filePath: string, config: ProjectConfig, workingDir: string): void;
|
|
9
|
+
//# sourceMappingURL=security.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../source/utils/filesystem/security.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAsCrD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAK3E;AAoCD,wBAAgB,uBAAuB,CACrC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EAAE,GACpB,OAAO,CAIT;AAGD,wBAAsB,YAAY,CAChC,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,GAAG,MAAM,EAAE,EACnC,OAAO,GAAE;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,WAAW,CAAA;CAAO,GACtE,OAAO,CAAC,MAAM,CAAC,CA6HjB;AA8BD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,MAAM,GACjB,IAAI,CAIN"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { realpathSync } from "node:fs";
|
|
1
|
+
import { realpathSync, statSync } from "node:fs";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
@@ -6,6 +6,36 @@ import path from "node:path";
|
|
|
6
6
|
function normalizePath(p) {
|
|
7
7
|
return path.normalize(p);
|
|
8
8
|
}
|
|
9
|
+
// Resolve symlinks for existing ancestors of a path.
|
|
10
|
+
// Walks up the directory tree until an existing directory is found, resolves its real path,
|
|
11
|
+
// and appends the remaining relative path. Permission errors are treated as non-existence.
|
|
12
|
+
function resolveExistingAncestorSync(filePath) {
|
|
13
|
+
let current = filePath;
|
|
14
|
+
while (true) {
|
|
15
|
+
try {
|
|
16
|
+
const stats = statSync(current);
|
|
17
|
+
if (stats.isDirectory()) {
|
|
18
|
+
const realCurrent = realpathSync(current);
|
|
19
|
+
const remaining = path.relative(current, filePath);
|
|
20
|
+
return remaining === ""
|
|
21
|
+
? realCurrent
|
|
22
|
+
: path.join(realCurrent, remaining);
|
|
23
|
+
}
|
|
24
|
+
// If current exists but is not a directory, move up
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// current doesn't exist or we lack permission to stat it
|
|
28
|
+
}
|
|
29
|
+
const parent = path.dirname(current);
|
|
30
|
+
if (parent === current) {
|
|
31
|
+
// Reached root, cannot resolve further
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
current = parent;
|
|
35
|
+
}
|
|
36
|
+
// No existing ancestor found, return original path
|
|
37
|
+
return filePath;
|
|
38
|
+
}
|
|
9
39
|
// Handle path joining with working directory
|
|
10
40
|
export function joinWorkingDir(userPath, workingDir) {
|
|
11
41
|
if (path.isAbsolute(userPath)) {
|
|
@@ -20,7 +50,7 @@ function expandHome(filepath) {
|
|
|
20
50
|
return filepath;
|
|
21
51
|
}
|
|
22
52
|
// Ensure path is within base directory (handles '.', relative paths, and symlinks)
|
|
23
|
-
|
|
53
|
+
function isPathWithinBaseDir(requestedPath, baseDir) {
|
|
24
54
|
const baseAbs = path.resolve(baseDir);
|
|
25
55
|
let baseReal = baseAbs;
|
|
26
56
|
try {
|
|
@@ -37,11 +67,16 @@ export function isPathWithinBaseDir(requestedPath, baseDir) {
|
|
|
37
67
|
target = realpathSync(abs);
|
|
38
68
|
}
|
|
39
69
|
catch {
|
|
40
|
-
// If target doesn't fully exist,
|
|
70
|
+
// If target doesn't fully exist, resolve existing ancestors
|
|
71
|
+
target = resolveExistingAncestorSync(abs);
|
|
41
72
|
}
|
|
42
73
|
const rel = path.relative(baseReal, target);
|
|
43
74
|
return rel === "" || (!rel.startsWith("..") && !path.isAbsolute(rel));
|
|
44
75
|
}
|
|
76
|
+
// Check if path is within any of the allowed directories
|
|
77
|
+
export function isPathWithinAllowedDirs(requestedPath, allowedDirs) {
|
|
78
|
+
return allowedDirs.some((allowedDir) => isPathWithinBaseDir(requestedPath, allowedDir));
|
|
79
|
+
}
|
|
45
80
|
// Security utilities
|
|
46
81
|
export async function validatePath(requestedPath, allowedDirectory, options = {}) {
|
|
47
82
|
const { requireExistence = true, abortSignal } = options;
|
|
@@ -53,27 +88,37 @@ export async function validatePath(requestedPath, allowedDirectory, options = {}
|
|
|
53
88
|
? path.resolve(expandedPath)
|
|
54
89
|
: path.resolve(process.cwd(), expandedPath);
|
|
55
90
|
const normalizedRequested = normalizePath(absolute);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
91
|
+
// Handle both single directory and array of directories
|
|
92
|
+
const allowedDirectories = Array.isArray(allowedDirectory)
|
|
93
|
+
? allowedDirectory
|
|
94
|
+
: [allowedDirectory];
|
|
95
|
+
// Resolve and normalize all allowed directories
|
|
96
|
+
const normalizedAllowedDirs = await Promise.all(allowedDirectories.map(async (dir) => {
|
|
97
|
+
let normalizedDir = normalizePath(path.resolve(dir));
|
|
98
|
+
// Try to resolve real path for allowedDirectory when it exists to handle symlinked roots
|
|
99
|
+
try {
|
|
100
|
+
const stats = await fs.stat(normalizedDir);
|
|
101
|
+
if (stats.isDirectory()) {
|
|
102
|
+
const allowedReal = await fs.realpath(normalizedDir);
|
|
103
|
+
normalizedDir = normalizePath(allowedReal);
|
|
104
|
+
}
|
|
63
105
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
106
|
+
catch (_err) {
|
|
107
|
+
// If allowedDirectory doesn't exist, keep normalizedDir as-is
|
|
108
|
+
}
|
|
109
|
+
return normalizedDir;
|
|
110
|
+
}));
|
|
111
|
+
// Helper to check if a path is within any allowed directory using path.relative
|
|
69
112
|
const isWithinAllowed = (targetPath) => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
113
|
+
return normalizedAllowedDirs.some((normalizedAllowed) => {
|
|
114
|
+
const rel = path.relative(normalizedAllowed, targetPath);
|
|
115
|
+
// Allow the allowed directory itself (rel === "") and any descendant paths
|
|
116
|
+
return rel === "" || (!rel.startsWith("..") && !path.isAbsolute(rel));
|
|
117
|
+
});
|
|
73
118
|
};
|
|
74
|
-
// Check intended path is within allowed directory
|
|
119
|
+
// Check intended path is within any allowed directory
|
|
75
120
|
if (!isWithinAllowed(normalizedRequested)) {
|
|
76
|
-
throw new Error(`Access denied - path outside allowed directories: ${absolute} not in ${
|
|
121
|
+
throw new Error(`Access denied - path outside allowed directories: ${absolute} not in any of ${allowedDirectories.join(", ")}`);
|
|
77
122
|
}
|
|
78
123
|
let validatedPath;
|
|
79
124
|
// Try to resolve real path for existing targets to handle symlinks safely
|
|
@@ -105,7 +150,11 @@ export async function validatePath(requestedPath, allowedDirectory, options = {}
|
|
|
105
150
|
foundValidAncestor = true;
|
|
106
151
|
break;
|
|
107
152
|
}
|
|
108
|
-
catch (
|
|
153
|
+
catch (err) {
|
|
154
|
+
// If it's a security denial, rethrow
|
|
155
|
+
if (err instanceof Error && err.message.startsWith("Access denied")) {
|
|
156
|
+
throw err;
|
|
157
|
+
}
|
|
109
158
|
// If we reached the filesystem root, break to fallback check
|
|
110
159
|
const parent = path.dirname(current);
|
|
111
160
|
if (parent === current) {
|
|
@@ -137,3 +186,26 @@ export async function validatePath(requestedPath, allowedDirectory, options = {}
|
|
|
137
186
|
}
|
|
138
187
|
return validatedPath;
|
|
139
188
|
}
|
|
189
|
+
// Check if a file is read-only based on config
|
|
190
|
+
function isFileReadOnly(filePath, readOnlyFiles, workingDir) {
|
|
191
|
+
if (readOnlyFiles.length === 0) {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
const normalizedFilePath = normalizePath(path.resolve(workingDir, filePath));
|
|
195
|
+
return readOnlyFiles.some((readOnlyPattern) => {
|
|
196
|
+
// Handle absolute paths
|
|
197
|
+
if (path.isAbsolute(readOnlyPattern)) {
|
|
198
|
+
const normalizedPattern = normalizePath(path.resolve(readOnlyPattern));
|
|
199
|
+
return normalizedFilePath === normalizedPattern;
|
|
200
|
+
}
|
|
201
|
+
// Handle relative paths (relative to working directory)
|
|
202
|
+
const normalizedRelativePattern = normalizePath(path.resolve(workingDir, readOnlyPattern));
|
|
203
|
+
return normalizedFilePath === normalizedRelativePattern;
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
// Validate that a file is not read-only before modification
|
|
207
|
+
export function validateFileNotReadOnly(filePath, config, workingDir) {
|
|
208
|
+
if (isFileReadOnly(filePath, config.readOnlyFiles, workingDir)) {
|
|
209
|
+
throw new Error(`File is read-only and cannot be modified: ${filePath}`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"funcs.d.ts","sourceRoot":"","sources":["../../source/utils/funcs.ts"],"names":[],"mappings":"AACA;;;GAGG;AACH,eAAO,MAAM,EAAE,GAAI,CAAC,EAAE,OAAO,CAAC,KAAG,CAAU,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function exhaustGenerator<T, TReturn, TNext>(generator: Generator<T, TReturn, TNext>): TReturn;
|
|
2
|
+
export declare function exhaustGenerator<T, TReturn, TNext>(generator: AsyncGenerator<T, TReturn, TNext>): Promise<TReturn>;
|
|
3
|
+
//# sourceMappingURL=generators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../source/utils/generators.ts"],"names":[],"mappings":"AASA,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAChD,SAAS,EAAE,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,GACtC,OAAO,CAAC;AAGX,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAChD,SAAS,EAAE,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,GAC3C,OAAO,CAAC,OAAO,CAAC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
function isPromiseLike(value) {
|
|
2
|
+
return (typeof value === "object" &&
|
|
3
|
+
value !== null &&
|
|
4
|
+
typeof value.then === "function");
|
|
5
|
+
}
|
|
6
|
+
// biome-ignore lint/style/useNamingConvention: temp
|
|
7
|
+
export function exhaustGenerator(generator) {
|
|
8
|
+
const firstResult = generator.next();
|
|
9
|
+
if (isPromiseLike(firstResult)) {
|
|
10
|
+
const asyncGenerator = generator;
|
|
11
|
+
return (async () => {
|
|
12
|
+
let result = await firstResult;
|
|
13
|
+
while (!result.done) {
|
|
14
|
+
result = await asyncGenerator.next();
|
|
15
|
+
}
|
|
16
|
+
return result.value;
|
|
17
|
+
})();
|
|
18
|
+
}
|
|
19
|
+
const syncGenerator = generator;
|
|
20
|
+
let result = firstResult;
|
|
21
|
+
while (!result.done) {
|
|
22
|
+
result = syncGenerator.next();
|
|
23
|
+
}
|
|
24
|
+
return result.value;
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../source/utils/git.ts"],"names":[],"mappings":"AAIA,wBAAsB,WAAW;;;;GAyDhC;AAED,wBAAsB,YAAY;;;;;GAmCjC;AAED,eAAO,MAAM,cAAc,QAAqB,OAAO,CAAC,OAAO,CAS7D,CAAC;AAEH;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,CAY9D;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkB/D"}
|
|
@@ -103,9 +103,6 @@ export const inGitDirectory = memoize(async () => {
|
|
|
103
103
|
* Check if there are uncommitted changes
|
|
104
104
|
*/
|
|
105
105
|
export async function hasUncommittedChanges() {
|
|
106
|
-
if (!(await inGitDirectory())) {
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
109
106
|
try {
|
|
110
107
|
const result = await executeCommand(["git", "status", "--porcelain"], {
|
|
111
108
|
cwd: process.cwd(),
|
|
@@ -122,9 +119,6 @@ export async function hasUncommittedChanges() {
|
|
|
122
119
|
* Get the current git branch name
|
|
123
120
|
*/
|
|
124
121
|
export async function getCurrentBranch() {
|
|
125
|
-
if (!(await inGitDirectory())) {
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
122
|
try {
|
|
129
123
|
const result = await executeCommand(["git", "rev-parse", "--abbrev-ref", "HEAD"], {
|
|
130
124
|
cwd: process.cwd(),
|
package/dist/utils/glob.js
CHANGED
|
@@ -3,7 +3,7 @@ import { readFile } from "node:fs/promises";
|
|
|
3
3
|
import path, * as nodePath from "node:path";
|
|
4
4
|
import * as process from "node:process";
|
|
5
5
|
import fg from "fast-glob";
|
|
6
|
-
import { isDirectory, slash, toPath } from "./filesystem.js";
|
|
6
|
+
import { isDirectory, slash, toPath } from "./filesystem/operations.js";
|
|
7
7
|
import { Ignore } from "./ignore.js";
|
|
8
8
|
// Cache for ignore patterns to avoid repeated IO
|
|
9
9
|
const ignoreCache = new Map();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iterables.d.ts","sourceRoot":"","sources":["../../source/utils/iterables.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAAC,CAAC,CAAC,CAQ5E"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { ZodType } from "zod";
|
|
2
2
|
export declare function isZodSchema(obj: unknown): obj is ZodType<unknown>;
|
|
3
3
|
export declare function zodToJsonSchema(schema: ZodType<unknown>): Record<string, unknown>;
|
|
4
|
-
//# sourceMappingURL=zod
|
|
4
|
+
//# sourceMappingURL=zod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod.d.ts","sourceRoot":"","sources":["../../source/utils/zod.ts"],"names":[],"mappings":"AAAA,OAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAEjC,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAEjE;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzB"}
|
package/package.json
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travisennis/acai",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "An AI assistant for developing software.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"bin": {
|
|
9
|
-
"acai": "
|
|
10
|
-
"@travisennis/acai": "
|
|
9
|
+
"acai": "bin/acai-wrapper.js",
|
|
10
|
+
"@travisennis/acai": "bin/acai-wrapper.js"
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
13
|
"dist",
|
|
14
|
+
"bin",
|
|
14
15
|
"README.md",
|
|
15
16
|
"LICENSE"
|
|
16
17
|
],
|
|
@@ -48,40 +49,39 @@
|
|
|
48
49
|
"typecheck:staged": "npm run typecheck"
|
|
49
50
|
},
|
|
50
51
|
"dependencies": {
|
|
51
|
-
"@ai-sdk/anthropic": "^2.0.
|
|
52
|
-
"@ai-sdk/deepseek": "^1.0.
|
|
53
|
-
"@ai-sdk/google": "^2.0.
|
|
54
|
-
"@ai-sdk/groq": "^2.0.
|
|
55
|
-
"@ai-sdk/openai": "^2.0.
|
|
56
|
-
"@ai-sdk/openai-compatible": "^1.0.
|
|
52
|
+
"@ai-sdk/anthropic": "^2.0.56",
|
|
53
|
+
"@ai-sdk/deepseek": "^1.0.32",
|
|
54
|
+
"@ai-sdk/google": "^2.0.46",
|
|
55
|
+
"@ai-sdk/groq": "^2.0.33",
|
|
56
|
+
"@ai-sdk/openai": "^2.0.86",
|
|
57
|
+
"@ai-sdk/openai-compatible": "^1.0.29",
|
|
57
58
|
"@crosscopy/clipboard": "^0.2.8",
|
|
58
|
-
"@openrouter/ai-sdk-provider": "^1.
|
|
59
|
+
"@openrouter/ai-sdk-provider": "^1.5.3",
|
|
59
60
|
"@travisennis/stdlib": "^0.0.14",
|
|
60
|
-
"ai": "^5.0.
|
|
61
|
+
"ai": "^5.0.113",
|
|
61
62
|
"cheerio": "^1.1.2",
|
|
62
|
-
"cli-table3": "^0.6.5",
|
|
63
63
|
"diff": "^8.0.2",
|
|
64
64
|
"duck-duck-scrape": "^2.2.7",
|
|
65
65
|
"fast-glob": "^3.3.3",
|
|
66
66
|
"highlight.js": "^11.11.1",
|
|
67
67
|
"jsonrepair": "^3.13.1",
|
|
68
|
-
"marked": "
|
|
69
|
-
"p-throttle": "^8.
|
|
68
|
+
"marked": "17.0.1",
|
|
69
|
+
"p-throttle": "^8.1.0",
|
|
70
70
|
"parse5": "^8.0.0",
|
|
71
71
|
"parse5-htmlparser2-tree-adapter": "^8.0.0",
|
|
72
|
-
"pino": "^10.
|
|
73
|
-
"pino-pretty": "^13.1.
|
|
72
|
+
"pino": "^10.1.0",
|
|
73
|
+
"pino-pretty": "^13.1.3",
|
|
74
74
|
"pino-roll": "^4.0.0",
|
|
75
75
|
"tiktoken": "^1.0.22",
|
|
76
|
-
"zod": "^4.1.
|
|
76
|
+
"zod": "^4.1.13"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@ai-sdk/provider": "^2.0.0",
|
|
80
|
-
"@biomejs/biome": "2.
|
|
81
|
-
"@commitlint/config-conventional": "^20.
|
|
82
|
-
"@types/node": "^
|
|
80
|
+
"@biomejs/biome": "2.3.8",
|
|
81
|
+
"@commitlint/config-conventional": "^20.2.0",
|
|
82
|
+
"@types/node": "^25.0.2",
|
|
83
83
|
"c8": "^10.1.3",
|
|
84
|
-
"commitlint": "^20.
|
|
84
|
+
"commitlint": "^20.2.0",
|
|
85
85
|
"domhandler": "^5.0.3",
|
|
86
86
|
"husky": "^9.1.7",
|
|
87
87
|
"typescript": "^5.9.3"
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { type ModelMessage } from "ai";
|
|
2
|
-
import type { ModelManager } from "./models/manager.ts";
|
|
3
|
-
import type { Terminal } from "./terminal/index.ts";
|
|
4
|
-
import type { TokenTracker } from "./tokens/tracker.ts";
|
|
5
|
-
export declare function analyzeConversation({ modelManager, messages, tokenTracker, }: {
|
|
6
|
-
modelManager: ModelManager;
|
|
7
|
-
messages: ModelMessage[];
|
|
8
|
-
terminal?: Terminal | undefined;
|
|
9
|
-
tokenTracker: TokenTracker;
|
|
10
|
-
}): Promise<string[]>;
|
|
11
|
-
//# sourceMappingURL=conversation-analyzer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-analyzer.d.ts","sourceRoot":"","sources":["../source/conversation-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,IAAI,CAAC;AAGrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAyCxD,wBAAsB,mBAAmB,CAAC,EACxC,YAAY,EACZ,QAAQ,EACR,YAAY,GACb,EAAE;IACD,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC,YAAY,EAAE,YAAY,CAAC;CAC5B,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA0DpB"}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { generateText } from "ai";
|
|
2
|
-
import { config } from "./config.js";
|
|
3
|
-
import { createUserMessage } from "./messages.js";
|
|
4
|
-
import { systemPrompt } from "./prompts.js";
|
|
5
|
-
// Modified System Prompt
|
|
6
|
-
const system = async () => `You are an expert analyst reviewing conversations between a coding agent and a software engineer. Your goal is to identify instances where the engineer corrected the agent's approach or understanding in a way that reveals a *generalizable principle* for improving the agent's future behavior across *different* tasks.
|
|
7
|
-
|
|
8
|
-
**Your Task:**
|
|
9
|
-
1. Analyze the conversation provided.
|
|
10
|
-
2. Identify significant corrections or redirections from the engineer. Ignore minor clarifications or task-specific adjustments.
|
|
11
|
-
3. For each significant correction, infer a *single, concise, broadly applicable, actionable rule* (starting with 'Always' or 'Never') that captures the underlying principle the agent should follow in the future.
|
|
12
|
-
4. Ensure the rule is general enough to be useful in various scenarios, not just the specific context of this conversation.
|
|
13
|
-
5. Provide a brief, illustrative quote or example from the conversation in parentheses after the rule.
|
|
14
|
-
6. List only the inferred rules in Markdown bullet points. Do not include explanations, summaries, or conversational filler.
|
|
15
|
-
|
|
16
|
-
**Crucially, AVOID generating rules that are:**
|
|
17
|
-
- Overly specific to the files, functions, or variables discussed (e.g., "Always check for null in the 'processUserData' function"). Instead, generalize (e.g., "Always validate data from external sources before processing").
|
|
18
|
-
- Merely restatements of the task requirements.
|
|
19
|
-
- Too narrow to be useful outside the immediate context.
|
|
20
|
-
- Related to minor typos or formatting preferences unless they represent a consistent pattern requested by the user.
|
|
21
|
-
|
|
22
|
-
**Good General Rule Examples:**
|
|
23
|
-
<examples>
|
|
24
|
-
- Always ask for clarification if the user's request is ambiguous.
|
|
25
|
-
- Never make assumptions about file paths without confirmation.
|
|
26
|
-
- Always follow the user's explicitly stated formatting preferences.
|
|
27
|
-
- Never provide incomplete code snippets without indicating they are partial.
|
|
28
|
-
- Always check for potential null or undefined values before accessing properties.
|
|
29
|
-
</examples>
|
|
30
|
-
|
|
31
|
-
**Bad Specific Rule Examples (Avoid These):**
|
|
32
|
-
<bad-examples>
|
|
33
|
-
- Always use 'const' instead of 'let' for the 'userId' variable in 'auth.ts'.
|
|
34
|
-
- Never forget to pass the 'config' object to the 'initializeDb' function.
|
|
35
|
-
- Always add a try-catch block around the 'api.fetchData()' call in 'dataService.ts'.
|
|
36
|
-
</bad-examples>
|
|
37
|
-
|
|
38
|
-
This is the original system prompt the agent operated under:
|
|
39
|
-
<systemPrompt>
|
|
40
|
-
${await systemPrompt()}
|
|
41
|
-
</systemPrompt>`;
|
|
42
|
-
export async function analyzeConversation({ modelManager, messages, tokenTracker, }) {
|
|
43
|
-
const learnedRules = await config.readCachedLearnedRulesFile();
|
|
44
|
-
// Modified User Message within analyzeConversation
|
|
45
|
-
messages.push(createUserMessage([
|
|
46
|
-
`Analyze this conversation based on the system instructions. Identify points where the user made significant corrections revealing general principles for agent improvement. Infer concise, broadly applicable rules (Always/Never) based *only* on these corrections.
|
|
47
|
-
|
|
48
|
-
**Key Requirements:**
|
|
49
|
-
- Focus on *generalizable* rules applicable to future, different tasks.
|
|
50
|
-
- Avoid rules tied to the specifics of *this* conversation.
|
|
51
|
-
- Ensure rules don't already exist in <existing-rules>.
|
|
52
|
-
- If no *new, general* rules can be inferred, return an empty list or response.
|
|
53
|
-
- Return *only* the Markdown list of rules, with no preamble or explanation.
|
|
54
|
-
|
|
55
|
-
<existing-rules>
|
|
56
|
-
${learnedRules}
|
|
57
|
-
</existing-rules>`,
|
|
58
|
-
]));
|
|
59
|
-
const { text, usage } = await generateText({
|
|
60
|
-
model: modelManager.getModel("conversation-analyzer"),
|
|
61
|
-
maxOutputTokens: 8192,
|
|
62
|
-
system: await system(),
|
|
63
|
-
messages: messages,
|
|
64
|
-
});
|
|
65
|
-
tokenTracker.trackUsage("conversation-analyzer", usage);
|
|
66
|
-
// Trim whitespace and check if the response is effectively empty or just whitespace
|
|
67
|
-
const potentialRulesText = text.trim();
|
|
68
|
-
// Basic check to prevent adding empty lines or just formatting
|
|
69
|
-
if (!potentialRulesText || potentialRulesText.length === 0) {
|
|
70
|
-
return []; // Return empty array if no valid rules generated
|
|
71
|
-
}
|
|
72
|
-
// Split into individual rules, filter out empty lines
|
|
73
|
-
const potentialRulesList = potentialRulesText
|
|
74
|
-
.split("\n")
|
|
75
|
-
.map((rule) => rule.trim())
|
|
76
|
-
.filter((rule) => rule.length > 0);
|
|
77
|
-
if (potentialRulesList.length === 0) {
|
|
78
|
-
return []; // Return empty array if splitting results in no rules
|
|
79
|
-
}
|
|
80
|
-
// Further validation could be added here (e.g., check if it starts with '- ', etc.)
|
|
81
|
-
// before writing to the file.
|
|
82
|
-
// Append only if there are non-empty potential rules
|
|
83
|
-
const updatedRules = learnedRules.endsWith("\n") || learnedRules.length === 0
|
|
84
|
-
? `${learnedRules}${potentialRulesList.join("\n")}`
|
|
85
|
-
: `${learnedRules}\n${potentialRulesList.join("\n")}`;
|
|
86
|
-
await config.writeCachedLearnedRulesFile(updatedRules);
|
|
87
|
-
return potentialRulesList; // Return the list of rules that were added
|
|
88
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"display-tool-messages.d.ts","sourceRoot":"","sources":["../../source/repl/display-tool-messages.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,QAAQ,QAiC1E"}
|