plugsuits 1.0.0
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/cli.js +3 -0
- package/dist/agent-reasoning-default.test.d.ts +2 -0
- package/dist/agent-reasoning-default.test.d.ts.map +1 -0
- package/dist/agent-reasoning-default.test.js +38 -0
- package/dist/agent-reasoning-default.test.js.map +1 -0
- package/dist/agent.d.ts +61 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +308 -0
- package/dist/agent.js.map +1 -0
- package/dist/agent.test.d.ts +2 -0
- package/dist/agent.test.d.ts.map +1 -0
- package/dist/agent.test.js +38 -0
- package/dist/agent.test.js.map +1 -0
- package/dist/cli-args.d.ts +15 -0
- package/dist/cli-args.d.ts.map +1 -0
- package/dist/cli-args.js +63 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli-args.test.d.ts +2 -0
- package/dist/cli-args.test.d.ts.map +1 -0
- package/dist/cli-args.test.js +105 -0
- package/dist/cli-args.test.js.map +1 -0
- package/dist/commands/aliases-and-tool-fallback.test.d.ts +2 -0
- package/dist/commands/aliases-and-tool-fallback.test.d.ts.map +1 -0
- package/dist/commands/aliases-and-tool-fallback.test.js +132 -0
- package/dist/commands/aliases-and-tool-fallback.test.js.map +1 -0
- package/dist/commands/clear.d.ts +3 -0
- package/dist/commands/clear.d.ts.map +1 -0
- package/dist/commands/clear.js +12 -0
- package/dist/commands/clear.js.map +1 -0
- package/dist/commands/factories/create-toggle-command.d.ts +13 -0
- package/dist/commands/factories/create-toggle-command.d.ts.map +1 -0
- package/dist/commands/factories/create-toggle-command.js +38 -0
- package/dist/commands/factories/create-toggle-command.js.map +1 -0
- package/dist/commands/help.d.ts +3 -0
- package/dist/commands/help.d.ts.map +1 -0
- package/dist/commands/help.js +23 -0
- package/dist/commands/help.js.map +1 -0
- package/dist/commands/index.d.ts +18 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +82 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/model.d.ts +15 -0
- package/dist/commands/model.d.ts.map +1 -0
- package/dist/commands/model.js +100 -0
- package/dist/commands/model.js.map +1 -0
- package/dist/commands/reasoning-mode.d.ts +3 -0
- package/dist/commands/reasoning-mode.d.ts.map +1 -0
- package/dist/commands/reasoning-mode.js +47 -0
- package/dist/commands/reasoning-mode.js.map +1 -0
- package/dist/commands/render.d.ts +19 -0
- package/dist/commands/render.d.ts.map +1 -0
- package/dist/commands/render.js +140 -0
- package/dist/commands/render.js.map +1 -0
- package/dist/commands/render.test.d.ts +2 -0
- package/dist/commands/render.test.d.ts.map +1 -0
- package/dist/commands/render.test.js +36 -0
- package/dist/commands/render.test.js.map +1 -0
- package/dist/commands/tool-fallback.d.ts +3 -0
- package/dist/commands/tool-fallback.d.ts.map +1 -0
- package/dist/commands/tool-fallback.js +38 -0
- package/dist/commands/tool-fallback.js.map +1 -0
- package/dist/commands/translate.d.ts +3 -0
- package/dist/commands/translate.d.ts.map +1 -0
- package/dist/commands/translate.js +12 -0
- package/dist/commands/translate.js.map +1 -0
- package/dist/commands/translate.test.d.ts +2 -0
- package/dist/commands/translate.test.d.ts.map +1 -0
- package/dist/commands/translate.test.js +49 -0
- package/dist/commands/translate.test.js.map +1 -0
- package/dist/commands/types.d.ts +17 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +2 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/context/environment-context.d.ts +2 -0
- package/dist/context/environment-context.d.ts.map +1 -0
- package/dist/context/environment-context.js +11 -0
- package/dist/context/environment-context.js.map +1 -0
- package/dist/context/paths.d.ts +3 -0
- package/dist/context/paths.d.ts.map +1 -0
- package/dist/context/paths.js +3 -0
- package/dist/context/paths.js.map +1 -0
- package/dist/context/session.d.ts +4 -0
- package/dist/context/session.d.ts.map +1 -0
- package/dist/context/session.js +16 -0
- package/dist/context/session.js.map +1 -0
- package/dist/context/skill-command-prefix.d.ts +4 -0
- package/dist/context/skill-command-prefix.d.ts.map +1 -0
- package/dist/context/skill-command-prefix.js +15 -0
- package/dist/context/skill-command-prefix.js.map +1 -0
- package/dist/context/skills-integration.test.d.ts +2 -0
- package/dist/context/skills-integration.test.d.ts.map +1 -0
- package/dist/context/skills-integration.test.js +87 -0
- package/dist/context/skills-integration.test.js.map +1 -0
- package/dist/context/skills.d.ts +18 -0
- package/dist/context/skills.d.ts.map +1 -0
- package/dist/context/skills.js +431 -0
- package/dist/context/skills.js.map +1 -0
- package/dist/context/skills.test.d.ts +2 -0
- package/dist/context/skills.test.d.ts.map +1 -0
- package/dist/context/skills.test.js +20 -0
- package/dist/context/skills.test.js.map +1 -0
- package/dist/context/system-prompt.d.ts +2 -0
- package/dist/context/system-prompt.d.ts.map +1 -0
- package/dist/context/system-prompt.js +100 -0
- package/dist/context/system-prompt.js.map +1 -0
- package/dist/context/translation-integration.test.d.ts +2 -0
- package/dist/context/translation-integration.test.d.ts.map +1 -0
- package/dist/context/translation-integration.test.js +138 -0
- package/dist/context/translation-integration.test.js.map +1 -0
- package/dist/context/translation.d.ts +21 -0
- package/dist/context/translation.d.ts.map +1 -0
- package/dist/context/translation.js +82 -0
- package/dist/context/translation.js.map +1 -0
- package/dist/context/translation.test.d.ts +2 -0
- package/dist/context/translation.test.d.ts.map +1 -0
- package/dist/context/translation.test.js +129 -0
- package/dist/context/translation.test.js.map +1 -0
- package/dist/entrypoints/cli-input-rendering.test.d.ts +2 -0
- package/dist/entrypoints/cli-input-rendering.test.d.ts.map +1 -0
- package/dist/entrypoints/cli-input-rendering.test.js +192 -0
- package/dist/entrypoints/cli-input-rendering.test.js.map +1 -0
- package/dist/entrypoints/cli.d.ts +3 -0
- package/dist/entrypoints/cli.d.ts.map +1 -0
- package/dist/entrypoints/cli.js +1268 -0
- package/dist/entrypoints/cli.js.map +1 -0
- package/dist/entrypoints/headless-agent-config.d.ts +21 -0
- package/dist/entrypoints/headless-agent-config.d.ts.map +1 -0
- package/dist/entrypoints/headless-agent-config.js +15 -0
- package/dist/entrypoints/headless-agent-config.js.map +1 -0
- package/dist/entrypoints/headless-agent-config.test.d.ts +2 -0
- package/dist/entrypoints/headless-agent-config.test.d.ts.map +1 -0
- package/dist/entrypoints/headless-agent-config.test.js +63 -0
- package/dist/entrypoints/headless-agent-config.test.js.map +1 -0
- package/dist/entrypoints/headless.d.ts +3 -0
- package/dist/entrypoints/headless.d.ts.map +1 -0
- package/dist/entrypoints/headless.js +396 -0
- package/dist/entrypoints/headless.js.map +1 -0
- package/dist/env.d.ts +8 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +14 -0
- package/dist/env.js.map +1 -0
- package/dist/friendli-models.d.ts +21 -0
- package/dist/friendli-models.d.ts.map +1 -0
- package/dist/friendli-models.js +57 -0
- package/dist/friendli-models.js.map +1 -0
- package/dist/friendli-reasoning.d.ts +10 -0
- package/dist/friendli-reasoning.d.ts.map +1 -0
- package/dist/friendli-reasoning.js +181 -0
- package/dist/friendli-reasoning.js.map +1 -0
- package/dist/friendli-reasoning.test.d.ts +2 -0
- package/dist/friendli-reasoning.test.d.ts.map +1 -0
- package/dist/friendli-reasoning.test.js +77 -0
- package/dist/friendli-reasoning.test.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/interaction/colors.d.ts +22 -0
- package/dist/interaction/colors.d.ts.map +1 -0
- package/dist/interaction/colors.js +24 -0
- package/dist/interaction/colors.js.map +1 -0
- package/dist/interaction/pi-tui-stream-renderer.d.ts +19 -0
- package/dist/interaction/pi-tui-stream-renderer.d.ts.map +1 -0
- package/dist/interaction/pi-tui-stream-renderer.js +1509 -0
- package/dist/interaction/pi-tui-stream-renderer.js.map +1 -0
- package/dist/interaction/pi-tui-stream-renderer.test.d.ts +2 -0
- package/dist/interaction/pi-tui-stream-renderer.test.d.ts.map +1 -0
- package/dist/interaction/pi-tui-stream-renderer.test.js +1314 -0
- package/dist/interaction/pi-tui-stream-renderer.test.js.map +1 -0
- package/dist/interaction/spinner.d.ts +13 -0
- package/dist/interaction/spinner.d.ts.map +1 -0
- package/dist/interaction/spinner.js +51 -0
- package/dist/interaction/spinner.js.map +1 -0
- package/dist/middleware/index.d.ts +7 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +15 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/todo-continuation.d.ts +11 -0
- package/dist/middleware/todo-continuation.d.ts.map +1 -0
- package/dist/middleware/todo-continuation.js +103 -0
- package/dist/middleware/todo-continuation.js.map +1 -0
- package/dist/middleware/trim-leading-newlines.d.ts +3 -0
- package/dist/middleware/trim-leading-newlines.d.ts.map +1 -0
- package/dist/middleware/trim-leading-newlines.js +49 -0
- package/dist/middleware/trim-leading-newlines.js.map +1 -0
- package/dist/reasoning-mode.d.ts +5 -0
- package/dist/reasoning-mode.d.ts.map +1 -0
- package/dist/reasoning-mode.js +30 -0
- package/dist/reasoning-mode.js.map +1 -0
- package/dist/reasoning-mode.test.d.ts +2 -0
- package/dist/reasoning-mode.test.d.ts.map +1 -0
- package/dist/reasoning-mode.test.js +22 -0
- package/dist/reasoning-mode.test.js.map +1 -0
- package/dist/tool-fallback-mode.d.ts +6 -0
- package/dist/tool-fallback-mode.d.ts.map +1 -0
- package/dist/tool-fallback-mode.js +25 -0
- package/dist/tool-fallback-mode.js.map +1 -0
- package/dist/tools/execute/shell-execute.d.ts +17 -0
- package/dist/tools/execute/shell-execute.d.ts.map +1 -0
- package/dist/tools/execute/shell-execute.js +55 -0
- package/dist/tools/execute/shell-execute.js.map +1 -0
- package/dist/tools/execute/shell-execute.test.d.ts +2 -0
- package/dist/tools/execute/shell-execute.test.d.ts.map +1 -0
- package/dist/tools/execute/shell-execute.test.js +86 -0
- package/dist/tools/execute/shell-execute.test.js.map +1 -0
- package/dist/tools/execute/shell-interact.d.ts +10 -0
- package/dist/tools/execute/shell-interact.d.ts.map +1 -0
- package/dist/tools/execute/shell-interact.js +122 -0
- package/dist/tools/execute/shell-interact.js.map +1 -0
- package/dist/tools/execute/shell-interact.test.d.ts +2 -0
- package/dist/tools/execute/shell-interact.test.d.ts.map +1 -0
- package/dist/tools/execute/shell-interact.test.js +175 -0
- package/dist/tools/execute/shell-interact.test.js.map +1 -0
- package/dist/tools/explore/glob.d.ts +15 -0
- package/dist/tools/explore/glob.d.ts.map +1 -0
- package/dist/tools/explore/glob.js +107 -0
- package/dist/tools/explore/glob.js.map +1 -0
- package/dist/tools/explore/glob.test.d.ts +2 -0
- package/dist/tools/explore/glob.test.d.ts.map +1 -0
- package/dist/tools/explore/glob.test.js +183 -0
- package/dist/tools/explore/glob.test.js.map +1 -0
- package/dist/tools/explore/grep.d.ts +27 -0
- package/dist/tools/explore/grep.d.ts.map +1 -0
- package/dist/tools/explore/grep.js +203 -0
- package/dist/tools/explore/grep.js.map +1 -0
- package/dist/tools/explore/grep.test.d.ts +2 -0
- package/dist/tools/explore/grep.test.d.ts.map +1 -0
- package/dist/tools/explore/grep.test.js +132 -0
- package/dist/tools/explore/grep.test.js.map +1 -0
- package/dist/tools/explore/read-file.d.ts +23 -0
- package/dist/tools/explore/read-file.d.ts.map +1 -0
- package/dist/tools/explore/read-file.js +84 -0
- package/dist/tools/explore/read-file.js.map +1 -0
- package/dist/tools/explore/read-file.test.d.ts +2 -0
- package/dist/tools/explore/read-file.test.d.ts.map +1 -0
- package/dist/tools/explore/read-file.test.js +278 -0
- package/dist/tools/explore/read-file.test.js.map +1 -0
- package/dist/tools/index.d.ts +71 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +26 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/modify/delete-file.d.ts +19 -0
- package/dist/tools/modify/delete-file.d.ts.map +1 -0
- package/dist/tools/modify/delete-file.js +71 -0
- package/dist/tools/modify/delete-file.js.map +1 -0
- package/dist/tools/modify/delete-file.test.d.ts +2 -0
- package/dist/tools/modify/delete-file.test.d.ts.map +1 -0
- package/dist/tools/modify/delete-file.test.js +136 -0
- package/dist/tools/modify/delete-file.test.js.map +1 -0
- package/dist/tools/modify/edit-file-diagnostics.d.ts +17 -0
- package/dist/tools/modify/edit-file-diagnostics.d.ts.map +1 -0
- package/dist/tools/modify/edit-file-diagnostics.js +157 -0
- package/dist/tools/modify/edit-file-diagnostics.js.map +1 -0
- package/dist/tools/modify/edit-file-repair.d.ts +13 -0
- package/dist/tools/modify/edit-file-repair.d.ts.map +1 -0
- package/dist/tools/modify/edit-file-repair.js +135 -0
- package/dist/tools/modify/edit-file-repair.js.map +1 -0
- package/dist/tools/modify/edit-file-stress.test.d.ts +2 -0
- package/dist/tools/modify/edit-file-stress.test.d.ts.map +1 -0
- package/dist/tools/modify/edit-file-stress.test.js +163 -0
- package/dist/tools/modify/edit-file-stress.test.js.map +1 -0
- package/dist/tools/modify/edit-file-validation.d.ts +9 -0
- package/dist/tools/modify/edit-file-validation.d.ts.map +1 -0
- package/dist/tools/modify/edit-file-validation.js +86 -0
- package/dist/tools/modify/edit-file-validation.js.map +1 -0
- package/dist/tools/modify/edit-file-whitespace.test.d.ts +2 -0
- package/dist/tools/modify/edit-file-whitespace.test.d.ts.map +1 -0
- package/dist/tools/modify/edit-file-whitespace.test.js +90 -0
- package/dist/tools/modify/edit-file-whitespace.test.js.map +1 -0
- package/dist/tools/modify/edit-file.d.ts +33 -0
- package/dist/tools/modify/edit-file.d.ts.map +1 -0
- package/dist/tools/modify/edit-file.js +177 -0
- package/dist/tools/modify/edit-file.js.map +1 -0
- package/dist/tools/modify/edit-file.test.d.ts +2 -0
- package/dist/tools/modify/edit-file.test.d.ts.map +1 -0
- package/dist/tools/modify/edit-file.test.js +948 -0
- package/dist/tools/modify/edit-file.test.js.map +1 -0
- package/dist/tools/modify/write-file.d.ts +17 -0
- package/dist/tools/modify/write-file.d.ts.map +1 -0
- package/dist/tools/modify/write-file.js +39 -0
- package/dist/tools/modify/write-file.js.map +1 -0
- package/dist/tools/modify/write-file.test.d.ts +2 -0
- package/dist/tools/modify/write-file.test.d.ts.map +1 -0
- package/dist/tools/modify/write-file.test.js +168 -0
- package/dist/tools/modify/write-file.test.js.map +1 -0
- package/dist/tools/planning/load-skill.d.ts +13 -0
- package/dist/tools/planning/load-skill.d.ts.map +1 -0
- package/dist/tools/planning/load-skill.js +101 -0
- package/dist/tools/planning/load-skill.js.map +1 -0
- package/dist/tools/planning/load-skill.test.d.ts +2 -0
- package/dist/tools/planning/load-skill.test.d.ts.map +1 -0
- package/dist/tools/planning/load-skill.test.js +37 -0
- package/dist/tools/planning/load-skill.test.js.map +1 -0
- package/dist/tools/planning/todo-write.d.ts +49 -0
- package/dist/tools/planning/todo-write.d.ts.map +1 -0
- package/dist/tools/planning/todo-write.js +118 -0
- package/dist/tools/planning/todo-write.js.map +1 -0
- package/dist/tools/planning/todo-write.test.d.ts +2 -0
- package/dist/tools/planning/todo-write.test.d.ts.map +1 -0
- package/dist/tools/planning/todo-write.test.js +82 -0
- package/dist/tools/planning/todo-write.test.js.map +1 -0
- package/dist/tools/utils/execute/format-utils.d.ts +4 -0
- package/dist/tools/utils/execute/format-utils.d.ts.map +1 -0
- package/dist/tools/utils/execute/format-utils.js +31 -0
- package/dist/tools/utils/execute/format-utils.js.map +1 -0
- package/dist/tools/utils/execute/format-utils.test.d.ts +2 -0
- package/dist/tools/utils/execute/format-utils.test.d.ts.map +1 -0
- package/dist/tools/utils/execute/format-utils.test.js +40 -0
- package/dist/tools/utils/execute/format-utils.test.js.map +1 -0
- package/dist/tools/utils/execute/noninteractive-wrapper.d.ts +12 -0
- package/dist/tools/utils/execute/noninteractive-wrapper.d.ts.map +1 -0
- package/dist/tools/utils/execute/noninteractive-wrapper.js +269 -0
- package/dist/tools/utils/execute/noninteractive-wrapper.js.map +1 -0
- package/dist/tools/utils/execute/noninteractive-wrapper.test.d.ts +2 -0
- package/dist/tools/utils/execute/noninteractive-wrapper.test.d.ts.map +1 -0
- package/dist/tools/utils/execute/noninteractive-wrapper.test.js +233 -0
- package/dist/tools/utils/execute/noninteractive-wrapper.test.js.map +1 -0
- package/dist/tools/utils/execute/output-handler.d.ts +14 -0
- package/dist/tools/utils/execute/output-handler.d.ts.map +1 -0
- package/dist/tools/utils/execute/output-handler.js +71 -0
- package/dist/tools/utils/execute/output-handler.js.map +1 -0
- package/dist/tools/utils/execute/output-handler.test.d.ts +2 -0
- package/dist/tools/utils/execute/output-handler.test.d.ts.map +1 -0
- package/dist/tools/utils/execute/output-handler.test.js +58 -0
- package/dist/tools/utils/execute/output-handler.test.js.map +1 -0
- package/dist/tools/utils/execute/process-manager.d.ts +17 -0
- package/dist/tools/utils/execute/process-manager.d.ts.map +1 -0
- package/dist/tools/utils/execute/process-manager.js +229 -0
- package/dist/tools/utils/execute/process-manager.js.map +1 -0
- package/dist/tools/utils/execute/process-manager.test.d.ts +2 -0
- package/dist/tools/utils/execute/process-manager.test.d.ts.map +1 -0
- package/dist/tools/utils/execute/process-manager.test.js +139 -0
- package/dist/tools/utils/execute/process-manager.test.js.map +1 -0
- package/dist/tools/utils/execute/shell-detection.d.ts +3 -0
- package/dist/tools/utils/execute/shell-detection.d.ts.map +1 -0
- package/dist/tools/utils/execute/shell-detection.js +56 -0
- package/dist/tools/utils/execute/shell-detection.js.map +1 -0
- package/dist/tools/utils/execute/shell-detection.test.d.ts +2 -0
- package/dist/tools/utils/execute/shell-detection.test.d.ts.map +1 -0
- package/dist/tools/utils/execute/shell-detection.test.js +86 -0
- package/dist/tools/utils/execute/shell-detection.test.js.map +1 -0
- package/dist/tools/utils/hashline/autocorrect-replacement-lines.d.ts +5 -0
- package/dist/tools/utils/hashline/autocorrect-replacement-lines.d.ts.map +1 -0
- package/dist/tools/utils/hashline/autocorrect-replacement-lines.js +113 -0
- package/dist/tools/utils/hashline/autocorrect-replacement-lines.js.map +1 -0
- package/dist/tools/utils/hashline/constants.d.ts +5 -0
- package/dist/tools/utils/hashline/constants.d.ts.map +1 -0
- package/dist/tools/utils/hashline/constants.js +11 -0
- package/dist/tools/utils/hashline/constants.js.map +1 -0
- package/dist/tools/utils/hashline/diff-utils.d.ts +7 -0
- package/dist/tools/utils/hashline/diff-utils.d.ts.map +1 -0
- package/dist/tools/utils/hashline/diff-utils.js +50 -0
- package/dist/tools/utils/hashline/diff-utils.js.map +1 -0
- package/dist/tools/utils/hashline/diff-utils.test.d.ts +2 -0
- package/dist/tools/utils/hashline/diff-utils.test.d.ts.map +1 -0
- package/dist/tools/utils/hashline/diff-utils.test.js +46 -0
- package/dist/tools/utils/hashline/diff-utils.test.js.map +1 -0
- package/dist/tools/utils/hashline/edit-deduplication.d.ts +6 -0
- package/dist/tools/utils/hashline/edit-deduplication.d.ts.map +1 -0
- package/dist/tools/utils/hashline/edit-deduplication.js +32 -0
- package/dist/tools/utils/hashline/edit-deduplication.js.map +1 -0
- package/dist/tools/utils/hashline/edit-operation-primitives.d.ts +11 -0
- package/dist/tools/utils/hashline/edit-operation-primitives.d.ts.map +1 -0
- package/dist/tools/utils/hashline/edit-operation-primitives.js +93 -0
- package/dist/tools/utils/hashline/edit-operation-primitives.js.map +1 -0
- package/dist/tools/utils/hashline/edit-operations.d.ts +9 -0
- package/dist/tools/utils/hashline/edit-operations.d.ts.map +1 -0
- package/dist/tools/utils/hashline/edit-operations.js +101 -0
- package/dist/tools/utils/hashline/edit-operations.js.map +1 -0
- package/dist/tools/utils/hashline/edit-operations.test.d.ts +2 -0
- package/dist/tools/utils/hashline/edit-operations.test.d.ts.map +1 -0
- package/dist/tools/utils/hashline/edit-operations.test.js +135 -0
- package/dist/tools/utils/hashline/edit-operations.test.js.map +1 -0
- package/dist/tools/utils/hashline/edit-ordering.d.ts +5 -0
- package/dist/tools/utils/hashline/edit-ordering.d.ts.map +1 -0
- package/dist/tools/utils/hashline/edit-ordering.js +54 -0
- package/dist/tools/utils/hashline/edit-ordering.js.map +1 -0
- package/dist/tools/utils/hashline/edit-text-normalization.d.ts +9 -0
- package/dist/tools/utils/hashline/edit-text-normalization.d.ts.map +1 -0
- package/dist/tools/utils/hashline/edit-text-normalization.js +135 -0
- package/dist/tools/utils/hashline/edit-text-normalization.js.map +1 -0
- package/dist/tools/utils/hashline/file-text-canonicalization.d.ts +8 -0
- package/dist/tools/utils/hashline/file-text-canonicalization.d.ts.map +1 -0
- package/dist/tools/utils/hashline/file-text-canonicalization.js +42 -0
- package/dist/tools/utils/hashline/file-text-canonicalization.js.map +1 -0
- package/dist/tools/utils/hashline/hash-computation.d.ts +14 -0
- package/dist/tools/utils/hashline/hash-computation.d.ts.map +1 -0
- package/dist/tools/utils/hashline/hash-computation.js +158 -0
- package/dist/tools/utils/hashline/hash-computation.js.map +1 -0
- package/dist/tools/utils/hashline/hash-computation.test.d.ts +2 -0
- package/dist/tools/utils/hashline/hash-computation.test.d.ts.map +1 -0
- package/dist/tools/utils/hashline/hash-computation.test.js +63 -0
- package/dist/tools/utils/hashline/hash-computation.test.js.map +1 -0
- package/dist/tools/utils/hashline/hashline-chunk-formatter.d.ts +11 -0
- package/dist/tools/utils/hashline/hashline-chunk-formatter.d.ts.map +1 -0
- package/dist/tools/utils/hashline/hashline-chunk-formatter.js +41 -0
- package/dist/tools/utils/hashline/hashline-chunk-formatter.js.map +1 -0
- package/dist/tools/utils/hashline/hashline-edit-diff.d.ts +2 -0
- package/dist/tools/utils/hashline/hashline-edit-diff.d.ts.map +1 -0
- package/dist/tools/utils/hashline/hashline-edit-diff.js +27 -0
- package/dist/tools/utils/hashline/hashline-edit-diff.js.map +1 -0
- package/dist/tools/utils/hashline/index.d.ts +14 -0
- package/dist/tools/utils/hashline/index.d.ts.map +1 -0
- package/dist/tools/utils/hashline/index.js +11 -0
- package/dist/tools/utils/hashline/index.js.map +1 -0
- package/dist/tools/utils/hashline/merge-expansion.d.ts +4 -0
- package/dist/tools/utils/hashline/merge-expansion.d.ts.map +1 -0
- package/dist/tools/utils/hashline/merge-expansion.js +105 -0
- package/dist/tools/utils/hashline/merge-expansion.js.map +1 -0
- package/dist/tools/utils/hashline/normalize-edits.d.ts +11 -0
- package/dist/tools/utils/hashline/normalize-edits.d.ts.map +1 -0
- package/dist/tools/utils/hashline/normalize-edits.js +81 -0
- package/dist/tools/utils/hashline/normalize-edits.js.map +1 -0
- package/dist/tools/utils/hashline/types.d.ts +18 -0
- package/dist/tools/utils/hashline/types.d.ts.map +1 -0
- package/dist/tools/utils/hashline/types.js +2 -0
- package/dist/tools/utils/hashline/types.js.map +1 -0
- package/dist/tools/utils/hashline/validation.d.ts +19 -0
- package/dist/tools/utils/hashline/validation.d.ts.map +1 -0
- package/dist/tools/utils/hashline/validation.js +161 -0
- package/dist/tools/utils/hashline/validation.js.map +1 -0
- package/dist/tools/utils/hashline/validation.test.d.ts +2 -0
- package/dist/tools/utils/hashline/validation.test.d.ts.map +1 -0
- package/dist/tools/utils/hashline/validation.test.js +86 -0
- package/dist/tools/utils/hashline/validation.test.js.map +1 -0
- package/dist/tools/utils/safety-utils.d.ts +66 -0
- package/dist/tools/utils/safety-utils.d.ts.map +1 -0
- package/dist/tools/utils/safety-utils.js +681 -0
- package/dist/tools/utils/safety-utils.js.map +1 -0
- package/dist/utils/tools-manager.d.ts +16 -0
- package/dist/utils/tools-manager.d.ts.map +1 -0
- package/dist/utils/tools-manager.js +257 -0
- package/dist/utils/tools-manager.js.map +1 -0
- package/package.json +49 -0
- package/src/AGENTS.md +52 -0
- package/src/agent-reasoning-default.test.ts +48 -0
- package/src/agent.test.ts +49 -0
- package/src/agent.ts +455 -0
- package/src/cli-args.test.ts +152 -0
- package/src/cli-args.ts +90 -0
- package/src/commands/aliases-and-tool-fallback.test.ts +172 -0
- package/src/commands/clear.ts +14 -0
- package/src/commands/factories/create-toggle-command.ts +68 -0
- package/src/commands/help.ts +30 -0
- package/src/commands/index.ts +125 -0
- package/src/commands/model.ts +146 -0
- package/src/commands/reasoning-mode.ts +55 -0
- package/src/commands/render.test.ts +47 -0
- package/src/commands/render.ts +205 -0
- package/src/commands/tool-fallback.ts +47 -0
- package/src/commands/translate.test.ts +62 -0
- package/src/commands/translate.ts +14 -0
- package/src/commands/types.ts +18 -0
- package/src/context/environment-context.ts +11 -0
- package/src/context/paths.ts +2 -0
- package/src/context/session.ts +18 -0
- package/src/context/skill-command-prefix.ts +18 -0
- package/src/context/skills-integration.test.ts +113 -0
- package/src/context/skills.test.ts +25 -0
- package/src/context/skills.ts +566 -0
- package/src/context/system-prompt.ts +100 -0
- package/src/context/translation-integration.test.ts +194 -0
- package/src/context/translation.test.ts +186 -0
- package/src/context/translation.ts +122 -0
- package/src/entrypoints/AGENTS.md +33 -0
- package/src/entrypoints/cli-input-rendering.test.ts +236 -0
- package/src/entrypoints/cli.ts +1845 -0
- package/src/entrypoints/headless-agent-config.test.ts +82 -0
- package/src/entrypoints/headless-agent-config.ts +42 -0
- package/src/entrypoints/headless.ts +622 -0
- package/src/env.ts +14 -0
- package/src/friendli-models.ts +81 -0
- package/src/friendli-reasoning.test.ts +147 -0
- package/src/friendli-reasoning.ts +280 -0
- package/src/index.ts +3 -0
- package/src/interaction/colors.ts +24 -0
- package/src/interaction/pi-tui-stream-renderer.test.ts +1471 -0
- package/src/interaction/pi-tui-stream-renderer.ts +2150 -0
- package/src/interaction/spinner.ts +61 -0
- package/src/middleware/index.ts +32 -0
- package/src/middleware/todo-continuation.ts +128 -0
- package/src/middleware/trim-leading-newlines.ts +66 -0
- package/src/reasoning-mode.test.ts +24 -0
- package/src/reasoning-mode.ts +40 -0
- package/src/skills/example/SKILL.md +44 -0
- package/src/skills/example/references/api.md +37 -0
- package/src/skills/example/scripts/setup.sh +13 -0
- package/src/skills/git-workflow.md +405 -0
- package/src/tool-fallback-mode.ts +34 -0
- package/src/tools/AGENTS.md +44 -0
- package/src/tools/execute/shell-execute.test.ts +114 -0
- package/src/tools/execute/shell-execute.ts +74 -0
- package/src/tools/execute/shell-execute.txt +27 -0
- package/src/tools/execute/shell-interact.test.ts +236 -0
- package/src/tools/execute/shell-interact.ts +151 -0
- package/src/tools/execute/shell-interact.txt +15 -0
- package/src/tools/explore/glob-files.txt +8 -0
- package/src/tools/explore/glob.test.ts +217 -0
- package/src/tools/explore/glob.ts +137 -0
- package/src/tools/explore/grep-files.txt +12 -0
- package/src/tools/explore/grep.test.ts +183 -0
- package/src/tools/explore/grep.ts +266 -0
- package/src/tools/explore/read-file.test.ts +355 -0
- package/src/tools/explore/read-file.ts +102 -0
- package/src/tools/explore/read-file.txt +24 -0
- package/src/tools/index.ts +29 -0
- package/src/tools/modify/AGENTS.md +38 -0
- package/src/tools/modify/delete-file.test.ts +200 -0
- package/src/tools/modify/delete-file.ts +95 -0
- package/src/tools/modify/delete-file.txt +9 -0
- package/src/tools/modify/edit-file-diagnostics.ts +210 -0
- package/src/tools/modify/edit-file-repair.ts +183 -0
- package/src/tools/modify/edit-file-stress.test.ts +200 -0
- package/src/tools/modify/edit-file-validation.ts +134 -0
- package/src/tools/modify/edit-file-whitespace.test.ts +117 -0
- package/src/tools/modify/edit-file.test.ts +1231 -0
- package/src/tools/modify/edit-file.ts +252 -0
- package/src/tools/modify/edit-file.txt +73 -0
- package/src/tools/modify/write-file.test.ts +240 -0
- package/src/tools/modify/write-file.ts +56 -0
- package/src/tools/modify/write-file.txt +9 -0
- package/src/tools/planning/load-skill.test.ts +48 -0
- package/src/tools/planning/load-skill.ts +136 -0
- package/src/tools/planning/load-skill.txt +6 -0
- package/src/tools/planning/todo-write.test.ts +91 -0
- package/src/tools/planning/todo-write.ts +141 -0
- package/src/tools/planning/todo-write.txt +7 -0
- package/src/tools/utils/execute/format-utils.test.ts +53 -0
- package/src/tools/utils/execute/format-utils.ts +37 -0
- package/src/tools/utils/execute/noninteractive-wrapper.test.ts +306 -0
- package/src/tools/utils/execute/noninteractive-wrapper.ts +314 -0
- package/src/tools/utils/execute/output-handler.test.ts +72 -0
- package/src/tools/utils/execute/output-handler.ts +101 -0
- package/src/tools/utils/execute/process-manager.test.ts +175 -0
- package/src/tools/utils/execute/process-manager.ts +310 -0
- package/src/tools/utils/execute/shell-detection.test.ts +112 -0
- package/src/tools/utils/execute/shell-detection.ts +72 -0
- package/src/tools/utils/hashline/autocorrect-replacement-lines.ts +159 -0
- package/src/tools/utils/hashline/constants.ts +13 -0
- package/src/tools/utils/hashline/diff-utils.test.ts +61 -0
- package/src/tools/utils/hashline/diff-utils.ts +64 -0
- package/src/tools/utils/hashline/edit-deduplication.ts +40 -0
- package/src/tools/utils/hashline/edit-operation-primitives.ts +149 -0
- package/src/tools/utils/hashline/edit-operations.test.ts +154 -0
- package/src/tools/utils/hashline/edit-operations.ts +132 -0
- package/src/tools/utils/hashline/edit-ordering.ts +60 -0
- package/src/tools/utils/hashline/edit-text-normalization.ts +180 -0
- package/src/tools/utils/hashline/file-text-canonicalization.ts +58 -0
- package/src/tools/utils/hashline/hash-computation.test.ts +82 -0
- package/src/tools/utils/hashline/hash-computation.ts +199 -0
- package/src/tools/utils/hashline/hashline-chunk-formatter.ts +61 -0
- package/src/tools/utils/hashline/hashline-edit-diff.ts +35 -0
- package/src/tools/utils/hashline/index.ts +55 -0
- package/src/tools/utils/hashline/merge-expansion.ts +120 -0
- package/src/tools/utils/hashline/normalize-edits.ts +127 -0
- package/src/tools/utils/hashline/types.ts +20 -0
- package/src/tools/utils/hashline/validation.test.ts +109 -0
- package/src/tools/utils/hashline/validation.ts +212 -0
- package/src/tools/utils/safety-utils.ts +938 -0
- package/src/utils/tools-manager.ts +353 -0
|
@@ -0,0 +1,1268 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { stripVTControlCharacters } from "node:util";
|
|
3
|
+
import { MANUAL_TOOL_LOOP_MAX_STEPS, MessageHistory, shouldContinueManualToolLoop, } from "@ai-sdk-tool/harness";
|
|
4
|
+
import { CombinedAutocompleteProvider, Container, Editor, Input, isKeyRelease, isKeyRepeat, Key, Loader, Markdown, matchesKey, ProcessTerminal, SelectList, Spacer, Text, TUI, } from "@mariozechner/pi-tui";
|
|
5
|
+
import { agentManager } from "../agent";
|
|
6
|
+
import { parseProviderArg, parseReasoningCliOption, parseToolFallbackCliOption, parseTranslateCliOption, } from "../cli-args";
|
|
7
|
+
import { executeCommand, getCommands, isCommand, isSkillCommandResult, parseCommand, registerCommand, resolveRegisteredCommandName, } from "../commands";
|
|
8
|
+
import { createClearCommand } from "../commands/clear";
|
|
9
|
+
import { applyModelSelection, createModelCommand, findModelBySelection, getAvailableModels, } from "../commands/model";
|
|
10
|
+
import { createReasoningModeCommand } from "../commands/reasoning-mode";
|
|
11
|
+
import { createRenderCommand } from "../commands/render";
|
|
12
|
+
import { createToolFallbackCommand } from "../commands/tool-fallback";
|
|
13
|
+
import { createTranslateCommand } from "../commands/translate";
|
|
14
|
+
import { getSessionId, initializeSession } from "../context/session";
|
|
15
|
+
import { toPromptsCommandName } from "../context/skill-command-prefix";
|
|
16
|
+
import { loadAllSkills } from "../context/skills";
|
|
17
|
+
import { isNonEnglish, translateToEnglish } from "../context/translation";
|
|
18
|
+
import { env } from "../env";
|
|
19
|
+
import { renderFullStreamWithPiTui } from "../interaction/pi-tui-stream-renderer";
|
|
20
|
+
import { setSpinnerOutputEnabled } from "../interaction/spinner";
|
|
21
|
+
import { buildTodoContinuationUserMessage, getIncompleteTodos, } from "../middleware/todo-continuation";
|
|
22
|
+
import { DEFAULT_REASONING_MODE, parseReasoningMode, } from "../reasoning-mode";
|
|
23
|
+
import { DEFAULT_TOOL_FALLBACK_MODE, parseToolFallbackMode, TOOL_FALLBACK_MODES, } from "../tool-fallback-mode";
|
|
24
|
+
import { cleanup } from "../tools/utils/execute/process-manager";
|
|
25
|
+
import { initializeTools } from "../utils/tools-manager";
|
|
26
|
+
const ANSI_RESET = "\x1b[0m";
|
|
27
|
+
const ANSI_BLACK = "\x1b[30m";
|
|
28
|
+
const ANSI_BOLD = "\x1b[1m";
|
|
29
|
+
const ANSI_DIM = "\x1b[2m";
|
|
30
|
+
const ANSI_ITALIC = "\x1b[3m";
|
|
31
|
+
const ANSI_UNDERLINE = "\x1b[4m";
|
|
32
|
+
const ANSI_BG_GRAY = "\x1b[100m";
|
|
33
|
+
const ANSI_BG_SOFT_LIGHT = "\x1b[48;5;249m";
|
|
34
|
+
const ANSI_GREEN = "\x1b[92m";
|
|
35
|
+
const ANSI_YELLOW = "\x1b[93m";
|
|
36
|
+
const ANSI_MAGENTA = "\x1b[95m";
|
|
37
|
+
const ANSI_CYAN = "\x1b[36m";
|
|
38
|
+
const ANSI_BRIGHT_CYAN = "\x1b[96m";
|
|
39
|
+
const ANSI_GRAY = "\x1b[90m";
|
|
40
|
+
const CTRL_C_ETX = "\u0003";
|
|
41
|
+
const CTRL_C_EXIT_WINDOW_MS = 500;
|
|
42
|
+
const messageHistory = new MessageHistory();
|
|
43
|
+
let cachedSkills = [];
|
|
44
|
+
let shouldExit = false;
|
|
45
|
+
let activeStreamController = null;
|
|
46
|
+
let streamInterruptRequested = false;
|
|
47
|
+
let activeUiForSignals = null;
|
|
48
|
+
let requestedProcessExitCode = null;
|
|
49
|
+
let signalShutdownRequested = false;
|
|
50
|
+
const cancelActiveStream = () => {
|
|
51
|
+
if (!activeStreamController || activeStreamController.signal.aborted) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
streamInterruptRequested = true;
|
|
55
|
+
activeStreamController.abort("User requested stream interruption");
|
|
56
|
+
return true;
|
|
57
|
+
};
|
|
58
|
+
const clearActiveStreamController = (streamController) => {
|
|
59
|
+
if (activeStreamController === streamController) {
|
|
60
|
+
activeStreamController = null;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const style = (prefix, text) => {
|
|
64
|
+
return `${prefix}${text}${ANSI_RESET}`;
|
|
65
|
+
};
|
|
66
|
+
const sanitizeCodeFence = (text) => {
|
|
67
|
+
return text.replaceAll("```", "` ` `");
|
|
68
|
+
};
|
|
69
|
+
const stripAnsi = (value) => {
|
|
70
|
+
if (typeof stripVTControlCharacters === "function") {
|
|
71
|
+
return stripVTControlCharacters(value);
|
|
72
|
+
}
|
|
73
|
+
let output = "";
|
|
74
|
+
let index = 0;
|
|
75
|
+
while (index < value.length) {
|
|
76
|
+
const char = value[index];
|
|
77
|
+
if (char === "\u001b") {
|
|
78
|
+
index += 1;
|
|
79
|
+
if (index < value.length && value[index] === "[") {
|
|
80
|
+
index += 1;
|
|
81
|
+
while (index < value.length) {
|
|
82
|
+
const code = value.charCodeAt(index);
|
|
83
|
+
index += 1;
|
|
84
|
+
if (code >= 0x40 && code <= 0x7e) {
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
output += char;
|
|
92
|
+
index += 1;
|
|
93
|
+
}
|
|
94
|
+
return output;
|
|
95
|
+
};
|
|
96
|
+
const createMarkdownTheme = () => {
|
|
97
|
+
return {
|
|
98
|
+
heading: (text) => style(`${ANSI_BOLD}${ANSI_BRIGHT_CYAN}`, text),
|
|
99
|
+
link: (text) => style(`${ANSI_UNDERLINE}${ANSI_CYAN}`, text),
|
|
100
|
+
linkUrl: (text) => style(ANSI_GRAY, text),
|
|
101
|
+
code: (text) => style(ANSI_YELLOW, text),
|
|
102
|
+
codeBlock: (text) => style(ANSI_GREEN, text),
|
|
103
|
+
codeBlockBorder: (text) => style(ANSI_GRAY, text),
|
|
104
|
+
quote: (text) => style(`${ANSI_ITALIC}${ANSI_GRAY}`, text),
|
|
105
|
+
quoteBorder: (text) => style(ANSI_GRAY, text),
|
|
106
|
+
hr: (text) => style(ANSI_GRAY, text),
|
|
107
|
+
listBullet: (text) => style(ANSI_MAGENTA, text),
|
|
108
|
+
bold: (text) => style(ANSI_BOLD, text),
|
|
109
|
+
italic: (text) => style(ANSI_ITALIC, text),
|
|
110
|
+
strikethrough: (text) => style(ANSI_DIM, text),
|
|
111
|
+
underline: (text) => style(ANSI_UNDERLINE, text),
|
|
112
|
+
codeBlockIndent: " ",
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
const createEditorTheme = () => {
|
|
116
|
+
return {
|
|
117
|
+
borderColor: (text) => style(ANSI_GRAY, text),
|
|
118
|
+
selectList: {
|
|
119
|
+
selectedPrefix: (text) => style(`${ANSI_BOLD}${ANSI_CYAN}`, text),
|
|
120
|
+
selectedText: (text) => style(ANSI_CYAN, text),
|
|
121
|
+
description: (text) => style(ANSI_GRAY, text),
|
|
122
|
+
scrollInfo: (text) => style(ANSI_DIM, text),
|
|
123
|
+
noMatch: (text) => style(ANSI_DIM, text),
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
const addUserMessage = (chatContainer, markdownTheme, message) => {
|
|
128
|
+
chatContainer.addChild(new Spacer(1));
|
|
129
|
+
chatContainer.addChild(new Markdown(message, 1, 1, markdownTheme, {
|
|
130
|
+
bgColor: (text) => style(`${ANSI_BG_SOFT_LIGHT}${ANSI_BLACK}`, text),
|
|
131
|
+
}));
|
|
132
|
+
};
|
|
133
|
+
const addTranslatedMessage = (chatContainer, markdownTheme, message) => {
|
|
134
|
+
chatContainer.addChild(new Spacer(1));
|
|
135
|
+
chatContainer.addChild(new Markdown(message, 1, 1, markdownTheme, {
|
|
136
|
+
bgColor: (text) => style(ANSI_BG_GRAY, text),
|
|
137
|
+
}));
|
|
138
|
+
};
|
|
139
|
+
const addSystemMessage = (chatContainer, message) => {
|
|
140
|
+
const cleaned = stripAnsi(message).trimEnd();
|
|
141
|
+
if (cleaned.length === 0) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
chatContainer.addChild(new Spacer(1));
|
|
145
|
+
chatContainer.addChild(new Text(style(ANSI_GRAY, sanitizeCodeFence(cleaned)), 1, 0));
|
|
146
|
+
};
|
|
147
|
+
const addNewSessionMessage = (chatContainer) => {
|
|
148
|
+
chatContainer.addChild(new Spacer(1));
|
|
149
|
+
chatContainer.addChild(new Text(style(ANSI_BRIGHT_CYAN, "✓ New session started"), 1, 1));
|
|
150
|
+
};
|
|
151
|
+
const SKILL_LABEL_MAX_WIDTH = 24;
|
|
152
|
+
const MODEL_LABEL_MAX_WIDTH = 26;
|
|
153
|
+
const MODEL_NAME_MAX_WIDTH = 28;
|
|
154
|
+
const truncateAutocompleteLabel = (value, maxWidth) => {
|
|
155
|
+
if (value.length <= maxWidth) {
|
|
156
|
+
return value;
|
|
157
|
+
}
|
|
158
|
+
if (maxWidth <= 1) {
|
|
159
|
+
return "…";
|
|
160
|
+
}
|
|
161
|
+
return `${value.slice(0, maxWidth - 1)}…`;
|
|
162
|
+
};
|
|
163
|
+
const toAutocompleteEntryValue = (entry) => {
|
|
164
|
+
return "name" in entry ? entry.name : entry.value;
|
|
165
|
+
};
|
|
166
|
+
const buildModelSelectorDescription = (modelName, providerLabel) => {
|
|
167
|
+
if (!modelName) {
|
|
168
|
+
return providerLabel;
|
|
169
|
+
}
|
|
170
|
+
const truncatedName = truncateAutocompleteLabel(modelName, MODEL_NAME_MAX_WIDTH);
|
|
171
|
+
return `${truncatedName} - ${providerLabel}`;
|
|
172
|
+
};
|
|
173
|
+
const buildModelSelectorLabel = (modelId, isCurrent) => {
|
|
174
|
+
const currentMarker = isCurrent ? "* " : " ";
|
|
175
|
+
const truncatedModelId = truncateAutocompleteLabel(modelId, MODEL_LABEL_MAX_WIDTH);
|
|
176
|
+
return `${currentMarker}${truncatedModelId}`;
|
|
177
|
+
};
|
|
178
|
+
const buildCurrentIndicatorLabel = (label, isCurrent) => {
|
|
179
|
+
const currentMarker = isCurrent ? "* " : " ";
|
|
180
|
+
return `${currentMarker}${label}`;
|
|
181
|
+
};
|
|
182
|
+
const createAutocompleteCommands = (skills) => {
|
|
183
|
+
const createCommandSuggestion = (command, name, description) => {
|
|
184
|
+
const suggestions = command.argumentSuggestions;
|
|
185
|
+
return {
|
|
186
|
+
name,
|
|
187
|
+
description,
|
|
188
|
+
getArgumentCompletions: suggestions && suggestions.length > 0
|
|
189
|
+
? (argumentPrefix) => {
|
|
190
|
+
const matches = suggestions.filter((suggestion) => suggestion
|
|
191
|
+
.toLowerCase()
|
|
192
|
+
.startsWith(argumentPrefix.toLowerCase()));
|
|
193
|
+
if (matches.length === 0) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
return matches.map((match) => ({
|
|
197
|
+
value: match,
|
|
198
|
+
label: match,
|
|
199
|
+
}));
|
|
200
|
+
}
|
|
201
|
+
: undefined,
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
const commandSuggestions = Array.from(getCommands().values()).map((command) => {
|
|
205
|
+
const aliases = "aliases" in command && Array.isArray(command.aliases)
|
|
206
|
+
? command.aliases
|
|
207
|
+
: [];
|
|
208
|
+
const aliasSuffix = aliases.length > 0 ? ` (aliases: ${aliases.join(", ")})` : "";
|
|
209
|
+
return createCommandSuggestion(command, command.name, `${command.description}${aliasSuffix}`);
|
|
210
|
+
});
|
|
211
|
+
const skillSuggestions = skills.map((skill) => {
|
|
212
|
+
const commandName = toPromptsCommandName(skill.id);
|
|
213
|
+
return {
|
|
214
|
+
value: commandName,
|
|
215
|
+
label: truncateAutocompleteLabel(commandName, SKILL_LABEL_MAX_WIDTH),
|
|
216
|
+
description: skill.description,
|
|
217
|
+
};
|
|
218
|
+
});
|
|
219
|
+
const suggestions = [
|
|
220
|
+
...commandSuggestions,
|
|
221
|
+
...skillSuggestions,
|
|
222
|
+
];
|
|
223
|
+
const seenNames = new Set();
|
|
224
|
+
const uniqueSuggestions = [];
|
|
225
|
+
for (const suggestion of suggestions) {
|
|
226
|
+
const normalizedName = toAutocompleteEntryValue(suggestion).toLowerCase();
|
|
227
|
+
if (seenNames.has(normalizedName)) {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
seenNames.add(normalizedName);
|
|
231
|
+
uniqueSuggestions.push(suggestion);
|
|
232
|
+
}
|
|
233
|
+
return uniqueSuggestions;
|
|
234
|
+
};
|
|
235
|
+
const toAutocompleteItem = (suggestion) => ({
|
|
236
|
+
value: suggestion.name,
|
|
237
|
+
label: suggestion.name,
|
|
238
|
+
...(suggestion.description ? { description: suggestion.description } : {}),
|
|
239
|
+
});
|
|
240
|
+
const buildCommandSuggestionsByName = (slashCommands) => {
|
|
241
|
+
const commandSuggestionsByName = new Map();
|
|
242
|
+
for (const suggestion of slashCommands) {
|
|
243
|
+
if (!("name" in suggestion)) {
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
commandSuggestionsByName.set(suggestion.name.toLowerCase(), suggestion);
|
|
247
|
+
}
|
|
248
|
+
return commandSuggestionsByName;
|
|
249
|
+
};
|
|
250
|
+
const buildAliasToCanonicalNameMap = () => {
|
|
251
|
+
const aliasToCanonicalName = new Map();
|
|
252
|
+
for (const command of getCommands().values()) {
|
|
253
|
+
const canonicalName = command.name.toLowerCase();
|
|
254
|
+
for (const alias of command.aliases ?? []) {
|
|
255
|
+
const normalizedAlias = alias.toLowerCase();
|
|
256
|
+
if (normalizedAlias === canonicalName) {
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
aliasToCanonicalName.set(normalizedAlias, canonicalName);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return aliasToCanonicalName;
|
|
263
|
+
};
|
|
264
|
+
const getAliasArgumentSuggestions = (textBeforeCursor, commandSuggestionsByName) => {
|
|
265
|
+
const spaceIndex = textBeforeCursor.indexOf(" ");
|
|
266
|
+
if (spaceIndex < 0) {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
const commandName = textBeforeCursor.slice(1, spaceIndex).toLowerCase();
|
|
270
|
+
const resolvedName = resolveRegisteredCommandName(commandName);
|
|
271
|
+
if (resolvedName === commandName) {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
const command = commandSuggestionsByName.get(resolvedName);
|
|
275
|
+
if (!command?.getArgumentCompletions) {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
const argumentPrefix = textBeforeCursor.slice(spaceIndex + 1);
|
|
279
|
+
const items = command.getArgumentCompletions(argumentPrefix);
|
|
280
|
+
if (!items || items.length === 0) {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
items,
|
|
285
|
+
prefix: argumentPrefix,
|
|
286
|
+
};
|
|
287
|
+
};
|
|
288
|
+
const getAliasMatches = (query, aliasToCanonicalName, commandSuggestionsByName) => {
|
|
289
|
+
const aliasMatches = [];
|
|
290
|
+
const seenCanonicalNames = new Set();
|
|
291
|
+
for (const [alias, canonicalName] of aliasToCanonicalName) {
|
|
292
|
+
if (!alias.startsWith(query) || seenCanonicalNames.has(canonicalName)) {
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
const suggestion = commandSuggestionsByName.get(canonicalName);
|
|
296
|
+
if (!suggestion) {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
seenCanonicalNames.add(canonicalName);
|
|
300
|
+
aliasMatches.push(toAutocompleteItem(suggestion));
|
|
301
|
+
}
|
|
302
|
+
return aliasMatches;
|
|
303
|
+
};
|
|
304
|
+
const mergeAutocompleteItems = (prioritizedItems, fallbackItems = []) => {
|
|
305
|
+
const mergedItems = [];
|
|
306
|
+
const seenValues = new Set();
|
|
307
|
+
for (const item of [...prioritizedItems, ...fallbackItems]) {
|
|
308
|
+
const normalizedValue = item.value.toLowerCase();
|
|
309
|
+
if (seenValues.has(normalizedValue)) {
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
seenValues.add(normalizedValue);
|
|
313
|
+
mergedItems.push(item);
|
|
314
|
+
}
|
|
315
|
+
return mergedItems;
|
|
316
|
+
};
|
|
317
|
+
const createAliasAwareAutocompleteProvider = (skills) => {
|
|
318
|
+
const slashCommands = createAutocompleteCommands(skills);
|
|
319
|
+
const fallbackProvider = new CombinedAutocompleteProvider(slashCommands, process.cwd());
|
|
320
|
+
const commandSuggestionsByName = buildCommandSuggestionsByName(slashCommands);
|
|
321
|
+
const aliasToCanonicalName = buildAliasToCanonicalNameMap();
|
|
322
|
+
return {
|
|
323
|
+
getSuggestions: (lines, cursorLine, cursorCol) => {
|
|
324
|
+
const currentLine = lines[cursorLine] ?? "";
|
|
325
|
+
const textBeforeCursor = currentLine.slice(0, cursorCol);
|
|
326
|
+
if (!textBeforeCursor.startsWith("/")) {
|
|
327
|
+
return fallbackProvider.getSuggestions(lines, cursorLine, cursorCol);
|
|
328
|
+
}
|
|
329
|
+
const aliasArgumentSuggestions = getAliasArgumentSuggestions(textBeforeCursor, commandSuggestionsByName);
|
|
330
|
+
if (aliasArgumentSuggestions) {
|
|
331
|
+
return aliasArgumentSuggestions;
|
|
332
|
+
}
|
|
333
|
+
const defaultSuggestions = fallbackProvider.getSuggestions(lines, cursorLine, cursorCol);
|
|
334
|
+
if (textBeforeCursor.includes(" ")) {
|
|
335
|
+
return defaultSuggestions;
|
|
336
|
+
}
|
|
337
|
+
const query = textBeforeCursor.slice(1).toLowerCase();
|
|
338
|
+
if (query.length === 0) {
|
|
339
|
+
return defaultSuggestions;
|
|
340
|
+
}
|
|
341
|
+
const aliasMatches = getAliasMatches(query, aliasToCanonicalName, commandSuggestionsByName);
|
|
342
|
+
if (aliasMatches.length === 0) {
|
|
343
|
+
return defaultSuggestions;
|
|
344
|
+
}
|
|
345
|
+
return {
|
|
346
|
+
items: mergeAutocompleteItems(aliasMatches, defaultSuggestions?.items),
|
|
347
|
+
prefix: textBeforeCursor,
|
|
348
|
+
};
|
|
349
|
+
},
|
|
350
|
+
applyCompletion: (lines, cursorLine, cursorCol, item, prefix) => fallbackProvider.applyCompletion(lines, cursorLine, cursorCol, item, prefix),
|
|
351
|
+
};
|
|
352
|
+
};
|
|
353
|
+
const createCliUi = (skills) => {
|
|
354
|
+
const markdownTheme = createMarkdownTheme();
|
|
355
|
+
const terminal = new ProcessTerminal();
|
|
356
|
+
const tui = new TUI(terminal);
|
|
357
|
+
tui.setClearOnShrink(true);
|
|
358
|
+
const headerContainer = new Container();
|
|
359
|
+
const chatContainer = new Container();
|
|
360
|
+
const statusContainer = new Container();
|
|
361
|
+
const editorContainer = new Container();
|
|
362
|
+
const title = new Text("", 1, 0);
|
|
363
|
+
const help = new Text(style(ANSI_DIM, "Enter to submit, Shift+Enter for newline, /help for commands, Ctrl+C clears input, Ctrl+C again exits"), 1, 0);
|
|
364
|
+
const updateHeader = () => {
|
|
365
|
+
const sessionId = getSessionId();
|
|
366
|
+
const provider = agentManager.getProvider();
|
|
367
|
+
const model = agentManager.getModelId();
|
|
368
|
+
title.setText(`${style(`${ANSI_BOLD}${ANSI_BRIGHT_CYAN}`, "Code Editing Agent")} ${style(ANSI_DIM, `${provider}/${model}`)}\n${style(ANSI_DIM, `Session: ${sessionId}`)}`);
|
|
369
|
+
tui.requestRender();
|
|
370
|
+
};
|
|
371
|
+
headerContainer.addChild(new Spacer(1));
|
|
372
|
+
headerContainer.addChild(title);
|
|
373
|
+
headerContainer.addChild(help);
|
|
374
|
+
headerContainer.addChild(new Spacer(1));
|
|
375
|
+
const editorTheme = createEditorTheme();
|
|
376
|
+
const editor = new Editor(tui, editorTheme, {
|
|
377
|
+
paddingX: 1,
|
|
378
|
+
autocompleteMaxVisible: 8,
|
|
379
|
+
});
|
|
380
|
+
editor.setAutocompleteProvider(createAliasAwareAutocompleteProvider(skills));
|
|
381
|
+
editorContainer.addChild(editor);
|
|
382
|
+
tui.addChild(headerContainer);
|
|
383
|
+
tui.addChild(chatContainer);
|
|
384
|
+
tui.addChild(statusContainer);
|
|
385
|
+
tui.addChild(editorContainer);
|
|
386
|
+
tui.setFocus(editor);
|
|
387
|
+
let loader = null;
|
|
388
|
+
let inputResolver = null;
|
|
389
|
+
let pendingExitConfirmation = false;
|
|
390
|
+
let lastCtrlCPressAt = 0;
|
|
391
|
+
let activeModalCancel = null;
|
|
392
|
+
const clearStatus = () => {
|
|
393
|
+
if (loader) {
|
|
394
|
+
loader.stop();
|
|
395
|
+
statusContainer.removeChild(loader);
|
|
396
|
+
loader = null;
|
|
397
|
+
}
|
|
398
|
+
statusContainer.clear();
|
|
399
|
+
tui.requestRender();
|
|
400
|
+
};
|
|
401
|
+
const showLoader = (message) => {
|
|
402
|
+
clearStatus();
|
|
403
|
+
loader = new Loader(tui, (text) => style(ANSI_CYAN, text), (text) => style(ANSI_DIM, text), message);
|
|
404
|
+
statusContainer.addChild(loader);
|
|
405
|
+
loader.start();
|
|
406
|
+
tui.requestRender();
|
|
407
|
+
};
|
|
408
|
+
const clearPromptInput = () => {
|
|
409
|
+
editor.setText("");
|
|
410
|
+
tui.setFocus(editor);
|
|
411
|
+
tui.requestRender();
|
|
412
|
+
};
|
|
413
|
+
const clearPendingExitConfirmation = () => {
|
|
414
|
+
pendingExitConfirmation = false;
|
|
415
|
+
};
|
|
416
|
+
const setActiveModalCancel = (cancel) => {
|
|
417
|
+
activeModalCancel = cancel;
|
|
418
|
+
};
|
|
419
|
+
const dismissActiveModal = () => {
|
|
420
|
+
if (!activeModalCancel) {
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
const cancel = activeModalCancel;
|
|
424
|
+
activeModalCancel = null;
|
|
425
|
+
cancel();
|
|
426
|
+
};
|
|
427
|
+
const shouldClearPendingExitConfirmation = (data) => {
|
|
428
|
+
if (!pendingExitConfirmation) {
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
if (isCtrlCInput(data)) {
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
if (isKeyRelease(data) || isKeyRepeat(data)) {
|
|
435
|
+
return false;
|
|
436
|
+
}
|
|
437
|
+
return true;
|
|
438
|
+
};
|
|
439
|
+
const isCtrlCInput = (data) => {
|
|
440
|
+
return data === CTRL_C_ETX || matchesKey(data, Key.ctrl("c"));
|
|
441
|
+
};
|
|
442
|
+
const handleCtrlCPress = () => {
|
|
443
|
+
const now = Date.now();
|
|
444
|
+
// Double press within window: request graceful shutdown immediately.
|
|
445
|
+
if (now - lastCtrlCPressAt < CTRL_C_EXIT_WINDOW_MS) {
|
|
446
|
+
lastCtrlCPressAt = 0;
|
|
447
|
+
dismissActiveModal();
|
|
448
|
+
requestExit();
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
lastCtrlCPressAt = now;
|
|
452
|
+
// First press: try to cancel active stream
|
|
453
|
+
const canceled = cancelActiveStream();
|
|
454
|
+
if (canceled) {
|
|
455
|
+
pendingExitConfirmation = true;
|
|
456
|
+
clearStatus();
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
// First press, no active stream: clear prompt
|
|
460
|
+
pendingExitConfirmation = true;
|
|
461
|
+
dismissActiveModal();
|
|
462
|
+
clearPromptInput();
|
|
463
|
+
};
|
|
464
|
+
const showReasoningModeSelector = async (currentMode) => {
|
|
465
|
+
clearStatus();
|
|
466
|
+
const selectableModes = agentManager.getSelectableReasoningModes();
|
|
467
|
+
const descriptions = {
|
|
468
|
+
off: "Disable reasoning mode",
|
|
469
|
+
on: "Enable reasoning if supported",
|
|
470
|
+
interleaved: "Enable interleaved reasoning field mode",
|
|
471
|
+
preserved: "Enable preserved interleaved reasoning mode",
|
|
472
|
+
};
|
|
473
|
+
const selectorContainer = new Container();
|
|
474
|
+
selectorContainer.addChild(new Text(style(ANSI_DIM, "Select reasoning execution"), 1, 0));
|
|
475
|
+
selectorContainer.addChild(new Spacer(1));
|
|
476
|
+
const selectList = new SelectList(selectableModes.map((mode) => ({
|
|
477
|
+
value: mode,
|
|
478
|
+
label: buildCurrentIndicatorLabel(mode, currentMode === mode),
|
|
479
|
+
description: descriptions[mode],
|
|
480
|
+
})), 2, editorTheme.selectList);
|
|
481
|
+
const selectedIndex = selectableModes.indexOf(currentMode);
|
|
482
|
+
selectList.setSelectedIndex(selectedIndex >= 0 ? selectedIndex : 0);
|
|
483
|
+
selectorContainer.addChild(selectList);
|
|
484
|
+
statusContainer.addChild(selectorContainer);
|
|
485
|
+
tui.requestRender();
|
|
486
|
+
return await new Promise((resolve) => {
|
|
487
|
+
let removeSelectorInputListener = () => undefined;
|
|
488
|
+
let done = false;
|
|
489
|
+
const cleanup = () => {
|
|
490
|
+
removeSelectorInputListener();
|
|
491
|
+
statusContainer.removeChild(selectorContainer);
|
|
492
|
+
tui.requestRender();
|
|
493
|
+
};
|
|
494
|
+
const finish = (value) => {
|
|
495
|
+
if (done) {
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
done = true;
|
|
499
|
+
setActiveModalCancel(null);
|
|
500
|
+
cleanup();
|
|
501
|
+
resolve(value);
|
|
502
|
+
};
|
|
503
|
+
setActiveModalCancel(() => {
|
|
504
|
+
finish(null);
|
|
505
|
+
});
|
|
506
|
+
selectList.onSelect = (item) => {
|
|
507
|
+
const selectedMode = parseReasoningMode(item.value);
|
|
508
|
+
finish(selectedMode ?? DEFAULT_REASONING_MODE);
|
|
509
|
+
};
|
|
510
|
+
selectList.onCancel = () => {
|
|
511
|
+
finish(null);
|
|
512
|
+
};
|
|
513
|
+
removeSelectorInputListener = tui.addInputListener((data) => {
|
|
514
|
+
if (isCtrlCInput(data)) {
|
|
515
|
+
handleCtrlCPress();
|
|
516
|
+
finish(null);
|
|
517
|
+
return { consume: true };
|
|
518
|
+
}
|
|
519
|
+
if (shouldClearPendingExitConfirmation(data)) {
|
|
520
|
+
clearPendingExitConfirmation();
|
|
521
|
+
}
|
|
522
|
+
selectList.handleInput(data);
|
|
523
|
+
tui.requestRender();
|
|
524
|
+
return { consume: true };
|
|
525
|
+
});
|
|
526
|
+
});
|
|
527
|
+
};
|
|
528
|
+
const showToolFallbackSelector = async (currentMode) => {
|
|
529
|
+
clearStatus();
|
|
530
|
+
const selectorContainer = new Container();
|
|
531
|
+
selectorContainer.addChild(new Text(style(ANSI_DIM, "Select tool fallback mode"), 1, 0));
|
|
532
|
+
selectorContainer.addChild(new Spacer(1));
|
|
533
|
+
const selectList = new SelectList([
|
|
534
|
+
{
|
|
535
|
+
value: "disable",
|
|
536
|
+
label: buildCurrentIndicatorLabel("disable", currentMode === "disable"),
|
|
537
|
+
description: "Use native tool support only",
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
value: "morphxml",
|
|
541
|
+
label: buildCurrentIndicatorLabel("morphxml", currentMode === "morphxml"),
|
|
542
|
+
description: "XML tags per tool (MorphXML protocol)",
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
value: "hermes",
|
|
546
|
+
label: buildCurrentIndicatorLabel("hermes", currentMode === "hermes"),
|
|
547
|
+
description: "Hermes JSON-in-XML tool_call format",
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
value: "qwen3coder",
|
|
551
|
+
label: buildCurrentIndicatorLabel("qwen3coder", currentMode === "qwen3coder"),
|
|
552
|
+
description: "Qwen3Coder function-tag tool_call format",
|
|
553
|
+
},
|
|
554
|
+
], 4, editorTheme.selectList);
|
|
555
|
+
const currentModeIndex = TOOL_FALLBACK_MODES.indexOf(currentMode);
|
|
556
|
+
if (currentModeIndex >= 0) {
|
|
557
|
+
selectList.setSelectedIndex(currentModeIndex);
|
|
558
|
+
}
|
|
559
|
+
selectorContainer.addChild(selectList);
|
|
560
|
+
statusContainer.addChild(selectorContainer);
|
|
561
|
+
tui.requestRender();
|
|
562
|
+
return await new Promise((resolve) => {
|
|
563
|
+
let removeSelectorInputListener = () => undefined;
|
|
564
|
+
let done = false;
|
|
565
|
+
const cleanup = () => {
|
|
566
|
+
removeSelectorInputListener();
|
|
567
|
+
statusContainer.removeChild(selectorContainer);
|
|
568
|
+
tui.requestRender();
|
|
569
|
+
};
|
|
570
|
+
const finish = (value) => {
|
|
571
|
+
if (done) {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
done = true;
|
|
575
|
+
setActiveModalCancel(null);
|
|
576
|
+
cleanup();
|
|
577
|
+
resolve(value);
|
|
578
|
+
};
|
|
579
|
+
setActiveModalCancel(() => {
|
|
580
|
+
finish(null);
|
|
581
|
+
});
|
|
582
|
+
selectList.onSelect = (item) => {
|
|
583
|
+
const parsedMode = parseToolFallbackMode(item.value);
|
|
584
|
+
finish(parsedMode);
|
|
585
|
+
};
|
|
586
|
+
selectList.onCancel = () => {
|
|
587
|
+
finish(null);
|
|
588
|
+
};
|
|
589
|
+
removeSelectorInputListener = tui.addInputListener((data) => {
|
|
590
|
+
if (isCtrlCInput(data)) {
|
|
591
|
+
handleCtrlCPress();
|
|
592
|
+
finish(null);
|
|
593
|
+
return { consume: true };
|
|
594
|
+
}
|
|
595
|
+
if (shouldClearPendingExitConfirmation(data)) {
|
|
596
|
+
clearPendingExitConfirmation();
|
|
597
|
+
}
|
|
598
|
+
selectList.handleInput(data);
|
|
599
|
+
tui.requestRender();
|
|
600
|
+
return { consume: true };
|
|
601
|
+
});
|
|
602
|
+
});
|
|
603
|
+
};
|
|
604
|
+
const showTranslateModeSelector = async (currentEnabled) => {
|
|
605
|
+
clearStatus();
|
|
606
|
+
const selectorContainer = new Container();
|
|
607
|
+
selectorContainer.addChild(new Text(style(ANSI_DIM, "Select translation mode"), 1, 0));
|
|
608
|
+
selectorContainer.addChild(new Spacer(1));
|
|
609
|
+
const selectList = new SelectList([
|
|
610
|
+
{
|
|
611
|
+
value: "on",
|
|
612
|
+
label: buildCurrentIndicatorLabel("on", currentEnabled),
|
|
613
|
+
description: "Auto-translate non-English prompts",
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
value: "off",
|
|
617
|
+
label: buildCurrentIndicatorLabel("off", !currentEnabled),
|
|
618
|
+
description: "Use prompts as entered",
|
|
619
|
+
},
|
|
620
|
+
], 2, editorTheme.selectList);
|
|
621
|
+
selectList.setSelectedIndex(currentEnabled ? 0 : 1);
|
|
622
|
+
selectorContainer.addChild(selectList);
|
|
623
|
+
statusContainer.addChild(selectorContainer);
|
|
624
|
+
tui.requestRender();
|
|
625
|
+
return await new Promise((resolve) => {
|
|
626
|
+
let removeSelectorInputListener = () => undefined;
|
|
627
|
+
let done = false;
|
|
628
|
+
const cleanup = () => {
|
|
629
|
+
removeSelectorInputListener();
|
|
630
|
+
statusContainer.removeChild(selectorContainer);
|
|
631
|
+
tui.requestRender();
|
|
632
|
+
};
|
|
633
|
+
const finish = (value) => {
|
|
634
|
+
if (done) {
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
done = true;
|
|
638
|
+
setActiveModalCancel(null);
|
|
639
|
+
cleanup();
|
|
640
|
+
resolve(value);
|
|
641
|
+
};
|
|
642
|
+
setActiveModalCancel(() => {
|
|
643
|
+
finish(null);
|
|
644
|
+
});
|
|
645
|
+
selectList.onSelect = (item) => {
|
|
646
|
+
finish(item.value === "on");
|
|
647
|
+
};
|
|
648
|
+
selectList.onCancel = () => {
|
|
649
|
+
finish(null);
|
|
650
|
+
};
|
|
651
|
+
removeSelectorInputListener = tui.addInputListener((data) => {
|
|
652
|
+
if (isCtrlCInput(data)) {
|
|
653
|
+
handleCtrlCPress();
|
|
654
|
+
finish(null);
|
|
655
|
+
return { consume: true };
|
|
656
|
+
}
|
|
657
|
+
if (shouldClearPendingExitConfirmation(data)) {
|
|
658
|
+
clearPendingExitConfirmation();
|
|
659
|
+
}
|
|
660
|
+
selectList.handleInput(data);
|
|
661
|
+
tui.requestRender();
|
|
662
|
+
return { consume: true };
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
};
|
|
666
|
+
const showModelSelector = async (models, currentModelId, currentProvider, initialFilter = "") => {
|
|
667
|
+
clearStatus();
|
|
668
|
+
const selectorContainer = new Container();
|
|
669
|
+
const searchInput = new Input();
|
|
670
|
+
searchInput.focused = true;
|
|
671
|
+
searchInput.setValue(initialFilter);
|
|
672
|
+
selectorContainer.addChild(searchInput);
|
|
673
|
+
selectorContainer.addChild(new Spacer(1));
|
|
674
|
+
const modelMap = new Map();
|
|
675
|
+
const items = models.map((model) => {
|
|
676
|
+
const key = `${model.provider}:${model.id}`;
|
|
677
|
+
modelMap.set(key, model);
|
|
678
|
+
const providerLabel = model.provider === "anthropic" ? "Anthropic" : "FriendliAI";
|
|
679
|
+
const isCurrent = model.id === currentModelId && model.provider === currentProvider;
|
|
680
|
+
return {
|
|
681
|
+
value: key,
|
|
682
|
+
label: buildModelSelectorLabel(model.id, isCurrent),
|
|
683
|
+
description: buildModelSelectorDescription(model.name, providerLabel),
|
|
684
|
+
};
|
|
685
|
+
});
|
|
686
|
+
const selectList = new SelectList(items, 10, editorTheme.selectList);
|
|
687
|
+
const currentIndex = items.findIndex((item) => item.value === `${currentProvider}:${currentModelId}`);
|
|
688
|
+
if (currentIndex >= 0) {
|
|
689
|
+
selectList.setSelectedIndex(currentIndex);
|
|
690
|
+
}
|
|
691
|
+
if (initialFilter.length > 0) {
|
|
692
|
+
selectList.setFilter(initialFilter);
|
|
693
|
+
}
|
|
694
|
+
selectorContainer.addChild(selectList);
|
|
695
|
+
selectorContainer.addChild(new Spacer(1));
|
|
696
|
+
selectorContainer.addChild(new Text(style(ANSI_DIM, "Type to filter, Enter to select, Esc to cancel"), 1, 0));
|
|
697
|
+
statusContainer.addChild(selectorContainer);
|
|
698
|
+
tui.requestRender();
|
|
699
|
+
return await new Promise((resolve) => {
|
|
700
|
+
let removeSelectorInputListener = () => undefined;
|
|
701
|
+
let done = false;
|
|
702
|
+
const cleanup = () => {
|
|
703
|
+
removeSelectorInputListener();
|
|
704
|
+
statusContainer.removeChild(selectorContainer);
|
|
705
|
+
searchInput.focused = false;
|
|
706
|
+
tui.requestRender();
|
|
707
|
+
};
|
|
708
|
+
const finish = (value) => {
|
|
709
|
+
if (done) {
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
done = true;
|
|
713
|
+
setActiveModalCancel(null);
|
|
714
|
+
cleanup();
|
|
715
|
+
resolve(value);
|
|
716
|
+
};
|
|
717
|
+
setActiveModalCancel(() => {
|
|
718
|
+
finish(null);
|
|
719
|
+
});
|
|
720
|
+
const selectCurrent = () => {
|
|
721
|
+
const selectedItem = selectList.getSelectedItem();
|
|
722
|
+
if (!selectedItem) {
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
finish(modelMap.get(selectedItem.value) ?? null);
|
|
726
|
+
};
|
|
727
|
+
selectList.onSelect = (item) => {
|
|
728
|
+
finish(modelMap.get(item.value) ?? null);
|
|
729
|
+
};
|
|
730
|
+
selectList.onCancel = () => {
|
|
731
|
+
finish(null);
|
|
732
|
+
};
|
|
733
|
+
searchInput.onSubmit = () => {
|
|
734
|
+
selectCurrent();
|
|
735
|
+
};
|
|
736
|
+
searchInput.onEscape = () => {
|
|
737
|
+
finish(null);
|
|
738
|
+
};
|
|
739
|
+
removeSelectorInputListener = tui.addInputListener((data) => {
|
|
740
|
+
if (isCtrlCInput(data)) {
|
|
741
|
+
handleCtrlCPress();
|
|
742
|
+
finish(null);
|
|
743
|
+
return { consume: true };
|
|
744
|
+
}
|
|
745
|
+
if (shouldClearPendingExitConfirmation(data)) {
|
|
746
|
+
clearPendingExitConfirmation();
|
|
747
|
+
}
|
|
748
|
+
if (matchesKey(data, Key.up) ||
|
|
749
|
+
matchesKey(data, Key.down) ||
|
|
750
|
+
matchesKey(data, Key.enter) ||
|
|
751
|
+
matchesKey(data, Key.escape)) {
|
|
752
|
+
selectList.handleInput(data);
|
|
753
|
+
tui.requestRender();
|
|
754
|
+
return { consume: true };
|
|
755
|
+
}
|
|
756
|
+
searchInput.handleInput(data);
|
|
757
|
+
selectList.setFilter(searchInput.getValue());
|
|
758
|
+
tui.requestRender();
|
|
759
|
+
return { consume: true };
|
|
760
|
+
});
|
|
761
|
+
});
|
|
762
|
+
};
|
|
763
|
+
const requestExit = () => {
|
|
764
|
+
pendingExitConfirmation = false;
|
|
765
|
+
shouldExit = true;
|
|
766
|
+
lastCtrlCPressAt = 0;
|
|
767
|
+
cancelActiveStream();
|
|
768
|
+
clearStatus();
|
|
769
|
+
dismissActiveModal();
|
|
770
|
+
if (inputResolver) {
|
|
771
|
+
const resolve = inputResolver;
|
|
772
|
+
inputResolver = null;
|
|
773
|
+
resolve(null);
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
const onSigInt = () => {
|
|
777
|
+
handleCtrlCPress();
|
|
778
|
+
};
|
|
779
|
+
const onTerminalResize = () => {
|
|
780
|
+
tui.requestRender(true);
|
|
781
|
+
};
|
|
782
|
+
const removeInputListener = tui.addInputListener((data) => {
|
|
783
|
+
if (isCtrlCInput(data)) {
|
|
784
|
+
handleCtrlCPress();
|
|
785
|
+
return { consume: true };
|
|
786
|
+
}
|
|
787
|
+
if (shouldClearPendingExitConfirmation(data)) {
|
|
788
|
+
clearPendingExitConfirmation();
|
|
789
|
+
}
|
|
790
|
+
return undefined;
|
|
791
|
+
});
|
|
792
|
+
process.on("SIGINT", onSigInt);
|
|
793
|
+
process.stdout.on("resize", onTerminalResize);
|
|
794
|
+
editor.onSubmit = (text) => {
|
|
795
|
+
if (!inputResolver) {
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
pendingExitConfirmation = false;
|
|
799
|
+
lastCtrlCPressAt = 0;
|
|
800
|
+
const resolve = inputResolver;
|
|
801
|
+
inputResolver = null;
|
|
802
|
+
resolve(text);
|
|
803
|
+
};
|
|
804
|
+
const waitForInput = () => {
|
|
805
|
+
return new Promise((resolve) => {
|
|
806
|
+
inputResolver = resolve;
|
|
807
|
+
tui.setFocus(editor);
|
|
808
|
+
tui.requestRender();
|
|
809
|
+
});
|
|
810
|
+
};
|
|
811
|
+
const dispose = async () => {
|
|
812
|
+
clearStatus();
|
|
813
|
+
if (inputResolver) {
|
|
814
|
+
const resolve = inputResolver;
|
|
815
|
+
inputResolver = null;
|
|
816
|
+
resolve(null);
|
|
817
|
+
}
|
|
818
|
+
// Release module-level refs to allow GC after UI teardown
|
|
819
|
+
activeStreamController = null;
|
|
820
|
+
streamInterruptRequested = false;
|
|
821
|
+
dismissActiveModal();
|
|
822
|
+
removeInputListener();
|
|
823
|
+
process.off("SIGINT", onSigInt);
|
|
824
|
+
process.stdout.off("resize", onTerminalResize);
|
|
825
|
+
try {
|
|
826
|
+
await terminal.drainInput();
|
|
827
|
+
}
|
|
828
|
+
finally {
|
|
829
|
+
tui.stop();
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
updateHeader();
|
|
833
|
+
tui.start();
|
|
834
|
+
return {
|
|
835
|
+
tui,
|
|
836
|
+
editor,
|
|
837
|
+
chatContainer,
|
|
838
|
+
markdownTheme,
|
|
839
|
+
updateHeader,
|
|
840
|
+
waitForInput,
|
|
841
|
+
requestExit,
|
|
842
|
+
showLoader,
|
|
843
|
+
showModelSelector,
|
|
844
|
+
showToolFallbackSelector,
|
|
845
|
+
showReasoningModeSelector,
|
|
846
|
+
showTranslateModeSelector,
|
|
847
|
+
clearStatus,
|
|
848
|
+
dispose,
|
|
849
|
+
};
|
|
850
|
+
};
|
|
851
|
+
registerCommand(createRenderCommand(async () => ({
|
|
852
|
+
model: agentManager.getModelId(),
|
|
853
|
+
modelType: agentManager.getModelType(),
|
|
854
|
+
instructions: await agentManager.getInstructions(),
|
|
855
|
+
tools: agentManager.getTools(),
|
|
856
|
+
messages: messageHistory.toModelMessages(),
|
|
857
|
+
reasoningMode: agentManager.getReasoningMode(),
|
|
858
|
+
toolFallbackMode: agentManager.getToolFallbackMode(),
|
|
859
|
+
})));
|
|
860
|
+
registerCommand(createModelCommand());
|
|
861
|
+
registerCommand(createClearCommand());
|
|
862
|
+
registerCommand(createReasoningModeCommand());
|
|
863
|
+
registerCommand(createToolFallbackCommand());
|
|
864
|
+
registerCommand(createTranslateCommand());
|
|
865
|
+
const parseCliArgs = () => {
|
|
866
|
+
const args = process.argv.slice(2);
|
|
867
|
+
let reasoningMode = null;
|
|
868
|
+
let toolFallbackMode = DEFAULT_TOOL_FALLBACK_MODE;
|
|
869
|
+
let model = null;
|
|
870
|
+
let provider = null;
|
|
871
|
+
let translateUserPrompts = true;
|
|
872
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
873
|
+
const arg = args[i];
|
|
874
|
+
const reasoningOption = parseReasoningCliOption(args, i);
|
|
875
|
+
if (reasoningOption) {
|
|
876
|
+
reasoningMode = reasoningOption.mode;
|
|
877
|
+
i += reasoningOption.consumedArgs;
|
|
878
|
+
continue;
|
|
879
|
+
}
|
|
880
|
+
const toolFallbackOption = parseToolFallbackCliOption(args, i);
|
|
881
|
+
if (toolFallbackOption) {
|
|
882
|
+
toolFallbackMode = toolFallbackOption.mode;
|
|
883
|
+
i += toolFallbackOption.consumedArgs;
|
|
884
|
+
continue;
|
|
885
|
+
}
|
|
886
|
+
if (arg === "--model" && i + 1 < args.length) {
|
|
887
|
+
model = args[i + 1];
|
|
888
|
+
i += 1;
|
|
889
|
+
continue;
|
|
890
|
+
}
|
|
891
|
+
if (arg === "--provider" && i + 1 < args.length) {
|
|
892
|
+
provider = parseProviderArg(args[i + 1]) ?? provider;
|
|
893
|
+
i += 1;
|
|
894
|
+
continue;
|
|
895
|
+
}
|
|
896
|
+
const translateOption = parseTranslateCliOption(arg);
|
|
897
|
+
if (translateOption !== null) {
|
|
898
|
+
translateUserPrompts = translateOption;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
return {
|
|
902
|
+
reasoningMode,
|
|
903
|
+
toolFallbackMode,
|
|
904
|
+
model,
|
|
905
|
+
provider,
|
|
906
|
+
translateUserPrompts,
|
|
907
|
+
};
|
|
908
|
+
};
|
|
909
|
+
const setupAgent = () => {
|
|
910
|
+
const { reasoningMode, toolFallbackMode, model, provider, translateUserPrompts, } = parseCliArgs();
|
|
911
|
+
if (provider) {
|
|
912
|
+
agentManager.setProvider(provider);
|
|
913
|
+
}
|
|
914
|
+
if (model) {
|
|
915
|
+
agentManager.setModelId(model);
|
|
916
|
+
}
|
|
917
|
+
if (reasoningMode !== null) {
|
|
918
|
+
agentManager.setReasoningMode(reasoningMode);
|
|
919
|
+
}
|
|
920
|
+
agentManager.setToolFallbackMode(toolFallbackMode);
|
|
921
|
+
agentManager.setTranslationEnabled(translateUserPrompts);
|
|
922
|
+
};
|
|
923
|
+
const processAgentResponse = async (ui) => {
|
|
924
|
+
let manualToolLoopCount = 0;
|
|
925
|
+
while (true) {
|
|
926
|
+
ui.showLoader("Working...");
|
|
927
|
+
const streamAbortController = new AbortController();
|
|
928
|
+
activeStreamController = streamAbortController;
|
|
929
|
+
streamInterruptRequested = false;
|
|
930
|
+
try {
|
|
931
|
+
const stream = await agentManager.stream(messageHistory.toModelMessages(), { abortSignal: streamAbortController.signal });
|
|
932
|
+
let hasClearedStreamingLoader = false;
|
|
933
|
+
const clearStreamingLoader = () => {
|
|
934
|
+
if (hasClearedStreamingLoader) {
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
hasClearedStreamingLoader = true;
|
|
938
|
+
ui.clearStatus();
|
|
939
|
+
};
|
|
940
|
+
await renderFullStreamWithPiTui(stream.fullStream, {
|
|
941
|
+
ui: ui.tui,
|
|
942
|
+
chatContainer: ui.chatContainer,
|
|
943
|
+
markdownTheme: ui.markdownTheme,
|
|
944
|
+
onFirstVisiblePart: clearStreamingLoader,
|
|
945
|
+
showReasoning: true,
|
|
946
|
+
showSteps: false,
|
|
947
|
+
showToolResults: true,
|
|
948
|
+
showFiles: false,
|
|
949
|
+
showSources: false,
|
|
950
|
+
showFinishReason: env.DEBUG_SHOW_FINISH_REASON,
|
|
951
|
+
});
|
|
952
|
+
clearStreamingLoader();
|
|
953
|
+
const [response, finishReason] = await Promise.all([
|
|
954
|
+
stream.response,
|
|
955
|
+
stream.finishReason,
|
|
956
|
+
]);
|
|
957
|
+
if (streamInterruptRequested || streamAbortController.signal.aborted) {
|
|
958
|
+
addSystemMessage(ui.chatContainer, "[agent] Stream interrupted by user. Waiting for input.");
|
|
959
|
+
ui.tui.requestRender();
|
|
960
|
+
return "interrupted";
|
|
961
|
+
}
|
|
962
|
+
messageHistory.addModelMessages(response.messages);
|
|
963
|
+
if (!shouldContinueManualToolLoop(finishReason)) {
|
|
964
|
+
return "completed";
|
|
965
|
+
}
|
|
966
|
+
manualToolLoopCount += 1;
|
|
967
|
+
if (manualToolLoopCount >= MANUAL_TOOL_LOOP_MAX_STEPS) {
|
|
968
|
+
addSystemMessage(ui.chatContainer, `[agent] Manual tool loop safety cap reached (${MANUAL_TOOL_LOOP_MAX_STEPS}); waiting for input.`);
|
|
969
|
+
ui.tui.requestRender();
|
|
970
|
+
return "completed";
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
catch (error) {
|
|
974
|
+
if (streamInterruptRequested || streamAbortController.signal.aborted) {
|
|
975
|
+
addSystemMessage(ui.chatContainer, "[agent] Stream interrupted by user. Waiting for input.");
|
|
976
|
+
ui.tui.requestRender();
|
|
977
|
+
return "interrupted";
|
|
978
|
+
}
|
|
979
|
+
throw error;
|
|
980
|
+
}
|
|
981
|
+
finally {
|
|
982
|
+
clearActiveStreamController(streamAbortController);
|
|
983
|
+
streamInterruptRequested = false;
|
|
984
|
+
ui.clearStatus();
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
};
|
|
988
|
+
const handleAgentResponse = async (ui) => {
|
|
989
|
+
while (true) {
|
|
990
|
+
const result = await processAgentResponse(ui);
|
|
991
|
+
if (result === "interrupted") {
|
|
992
|
+
return;
|
|
993
|
+
}
|
|
994
|
+
const incompleteTodos = await getIncompleteTodos();
|
|
995
|
+
if (incompleteTodos.length === 0) {
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
998
|
+
const reminder = buildTodoContinuationUserMessage(incompleteTodos);
|
|
999
|
+
messageHistory.addUserMessage(reminder);
|
|
1000
|
+
}
|
|
1001
|
+
};
|
|
1002
|
+
const renderCommandMessage = (ui, message) => {
|
|
1003
|
+
addSystemMessage(ui.chatContainer, message);
|
|
1004
|
+
ui.updateHeader();
|
|
1005
|
+
ui.tui.requestRender();
|
|
1006
|
+
};
|
|
1007
|
+
const handleModelCommand = async (ui, commandInput, parsed) => {
|
|
1008
|
+
if (parsed?.name !== "model") {
|
|
1009
|
+
return null;
|
|
1010
|
+
}
|
|
1011
|
+
const models = getAvailableModels();
|
|
1012
|
+
if (models.length === 0) {
|
|
1013
|
+
const result = await executeCommand(commandInput);
|
|
1014
|
+
if (result?.message) {
|
|
1015
|
+
renderCommandMessage(ui, result.message);
|
|
1016
|
+
return true;
|
|
1017
|
+
}
|
|
1018
|
+
return false;
|
|
1019
|
+
}
|
|
1020
|
+
const searchTerm = parsed.args[0]?.trim() ?? "";
|
|
1021
|
+
const exactMatch = searchTerm.length > 0
|
|
1022
|
+
? findModelBySelection(searchTerm, models)
|
|
1023
|
+
: undefined;
|
|
1024
|
+
if (parsed.args.length > 0 && exactMatch) {
|
|
1025
|
+
return null;
|
|
1026
|
+
}
|
|
1027
|
+
const selectedModel = await ui.showModelSelector(models, agentManager.getModelId(), agentManager.getProvider(), searchTerm);
|
|
1028
|
+
if (!selectedModel) {
|
|
1029
|
+
return true;
|
|
1030
|
+
}
|
|
1031
|
+
const selectionResult = applyModelSelection(selectedModel);
|
|
1032
|
+
if (selectionResult.message) {
|
|
1033
|
+
renderCommandMessage(ui, selectionResult.message);
|
|
1034
|
+
return true;
|
|
1035
|
+
}
|
|
1036
|
+
ui.updateHeader();
|
|
1037
|
+
ui.tui.requestRender();
|
|
1038
|
+
return true;
|
|
1039
|
+
};
|
|
1040
|
+
const resolveToolFallbackCommandInput = async (ui, commandInput, parsed) => {
|
|
1041
|
+
if (parsed?.name !== "tool-fallback" || parsed.args.length > 0) {
|
|
1042
|
+
return commandInput;
|
|
1043
|
+
}
|
|
1044
|
+
const selected = await ui.showToolFallbackSelector(agentManager.getToolFallbackMode());
|
|
1045
|
+
if (!selected) {
|
|
1046
|
+
return null;
|
|
1047
|
+
}
|
|
1048
|
+
return `/tool-fallback ${selected}`;
|
|
1049
|
+
};
|
|
1050
|
+
const resolveReasoningModeCommandInput = async (ui, commandInput, parsed) => {
|
|
1051
|
+
if (!parsed ||
|
|
1052
|
+
(parsed.name !== "think" && parsed.name !== "reasoning-mode") ||
|
|
1053
|
+
parsed.args.length > 0) {
|
|
1054
|
+
return commandInput;
|
|
1055
|
+
}
|
|
1056
|
+
const selected = await ui.showReasoningModeSelector(agentManager.getReasoningMode());
|
|
1057
|
+
if (!selected) {
|
|
1058
|
+
return null;
|
|
1059
|
+
}
|
|
1060
|
+
return `/reasoning-mode ${selected}`;
|
|
1061
|
+
};
|
|
1062
|
+
const resolveTranslateCommandInput = async (ui, commandInput, parsed) => {
|
|
1063
|
+
if (parsed?.name !== "translate" || parsed.args.length > 0) {
|
|
1064
|
+
return commandInput;
|
|
1065
|
+
}
|
|
1066
|
+
const selected = await ui.showTranslateModeSelector(agentManager.isTranslationEnabled());
|
|
1067
|
+
if (selected === null) {
|
|
1068
|
+
return null;
|
|
1069
|
+
}
|
|
1070
|
+
return `/translate ${selected ? "on" : "off"}`;
|
|
1071
|
+
};
|
|
1072
|
+
const handleCommand = async (ui, input) => {
|
|
1073
|
+
let commandInput = input;
|
|
1074
|
+
const initialParsed = parseCommand(commandInput);
|
|
1075
|
+
const modelHandled = await handleModelCommand(ui, commandInput, initialParsed);
|
|
1076
|
+
if (modelHandled !== null) {
|
|
1077
|
+
return modelHandled;
|
|
1078
|
+
}
|
|
1079
|
+
const toolFallbackCommandInput = await resolveToolFallbackCommandInput(ui, commandInput, initialParsed);
|
|
1080
|
+
if (!toolFallbackCommandInput) {
|
|
1081
|
+
return true;
|
|
1082
|
+
}
|
|
1083
|
+
commandInput = toolFallbackCommandInput;
|
|
1084
|
+
const reasoningModeCommandInput = await resolveReasoningModeCommandInput(ui, commandInput, initialParsed);
|
|
1085
|
+
if (!reasoningModeCommandInput) {
|
|
1086
|
+
return true;
|
|
1087
|
+
}
|
|
1088
|
+
commandInput = reasoningModeCommandInput;
|
|
1089
|
+
const translateCommandInput = await resolveTranslateCommandInput(ui, commandInput, initialParsed);
|
|
1090
|
+
if (!translateCommandInput) {
|
|
1091
|
+
return true;
|
|
1092
|
+
}
|
|
1093
|
+
commandInput = translateCommandInput;
|
|
1094
|
+
const parsed = parseCommand(commandInput);
|
|
1095
|
+
const resolvedCommandName = parsed
|
|
1096
|
+
? resolveRegisteredCommandName(parsed.name)
|
|
1097
|
+
: null;
|
|
1098
|
+
const isNativeCommand = resolvedCommandName === "clear" ||
|
|
1099
|
+
resolvedCommandName === "reasoning-mode" ||
|
|
1100
|
+
resolvedCommandName === "tool-fallback" ||
|
|
1101
|
+
resolvedCommandName === "translate";
|
|
1102
|
+
if (!isNativeCommand) {
|
|
1103
|
+
ui.showLoader("Working...");
|
|
1104
|
+
}
|
|
1105
|
+
const result = await executeCommand(commandInput);
|
|
1106
|
+
if (!isNativeCommand) {
|
|
1107
|
+
ui.clearStatus();
|
|
1108
|
+
}
|
|
1109
|
+
if (result?.action === "new-session") {
|
|
1110
|
+
ui.clearStatus();
|
|
1111
|
+
initializeSession();
|
|
1112
|
+
messageHistory.clear();
|
|
1113
|
+
ui.chatContainer.clear();
|
|
1114
|
+
addNewSessionMessage(ui.chatContainer);
|
|
1115
|
+
ui.updateHeader();
|
|
1116
|
+
ui.tui.requestRender();
|
|
1117
|
+
return true;
|
|
1118
|
+
}
|
|
1119
|
+
if (isSkillCommandResult(result)) {
|
|
1120
|
+
const skillMessage = `<command-name>/${result.skillId}</command-name>\n\n${result.skillContent}`;
|
|
1121
|
+
messageHistory.addUserMessage(skillMessage);
|
|
1122
|
+
await handleAgentResponse(ui);
|
|
1123
|
+
return true;
|
|
1124
|
+
}
|
|
1125
|
+
if (result?.message) {
|
|
1126
|
+
renderCommandMessage(ui, result.message);
|
|
1127
|
+
return true;
|
|
1128
|
+
}
|
|
1129
|
+
return false;
|
|
1130
|
+
};
|
|
1131
|
+
const processInput = async (ui, input) => {
|
|
1132
|
+
const trimmed = input.trim();
|
|
1133
|
+
if (shouldExit || trimmed.length === 0 || trimmed.toLowerCase() === "exit") {
|
|
1134
|
+
return false;
|
|
1135
|
+
}
|
|
1136
|
+
ui.editor.disableSubmit = true;
|
|
1137
|
+
try {
|
|
1138
|
+
if (isCommand(trimmed)) {
|
|
1139
|
+
addUserMessage(ui.chatContainer, ui.markdownTheme, trimmed);
|
|
1140
|
+
ui.tui.requestRender();
|
|
1141
|
+
return await handleCommand(ui, trimmed);
|
|
1142
|
+
}
|
|
1143
|
+
let contentForModel = trimmed;
|
|
1144
|
+
let originalContent;
|
|
1145
|
+
let translationError;
|
|
1146
|
+
if (agentManager.isTranslationEnabled()) {
|
|
1147
|
+
const shouldShowTranslationLoader = isNonEnglish(trimmed);
|
|
1148
|
+
if (shouldShowTranslationLoader) {
|
|
1149
|
+
addUserMessage(ui.chatContainer, ui.markdownTheme, trimmed);
|
|
1150
|
+
ui.tui.requestRender();
|
|
1151
|
+
}
|
|
1152
|
+
if (shouldShowTranslationLoader) {
|
|
1153
|
+
ui.showLoader("Translating...");
|
|
1154
|
+
}
|
|
1155
|
+
try {
|
|
1156
|
+
const translationResult = await translateToEnglish(trimmed, agentManager);
|
|
1157
|
+
contentForModel = translationResult.text;
|
|
1158
|
+
originalContent = translationResult.originalText;
|
|
1159
|
+
translationError = translationResult.error;
|
|
1160
|
+
}
|
|
1161
|
+
finally {
|
|
1162
|
+
if (shouldShowTranslationLoader) {
|
|
1163
|
+
ui.clearStatus();
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
if (!(isNonEnglish(trimmed) && agentManager.isTranslationEnabled())) {
|
|
1168
|
+
addUserMessage(ui.chatContainer, ui.markdownTheme, contentForModel);
|
|
1169
|
+
}
|
|
1170
|
+
else if (originalContent) {
|
|
1171
|
+
addTranslatedMessage(ui.chatContainer, ui.markdownTheme, contentForModel);
|
|
1172
|
+
}
|
|
1173
|
+
if (translationError) {
|
|
1174
|
+
addSystemMessage(ui.chatContainer, `[translation] Failed to translate input: ${translationError}. Using original text.`);
|
|
1175
|
+
}
|
|
1176
|
+
messageHistory.addUserMessage(contentForModel, originalContent);
|
|
1177
|
+
ui.tui.requestRender();
|
|
1178
|
+
await handleAgentResponse(ui);
|
|
1179
|
+
return true;
|
|
1180
|
+
}
|
|
1181
|
+
catch (error) {
|
|
1182
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1183
|
+
addSystemMessage(ui.chatContainer, `Error: ${errorMessage}`);
|
|
1184
|
+
ui.tui.requestRender();
|
|
1185
|
+
return true;
|
|
1186
|
+
}
|
|
1187
|
+
finally {
|
|
1188
|
+
ui.editor.disableSubmit = false;
|
|
1189
|
+
ui.editor.setText("");
|
|
1190
|
+
ui.tui.setFocus(ui.editor);
|
|
1191
|
+
ui.tui.requestRender();
|
|
1192
|
+
}
|
|
1193
|
+
};
|
|
1194
|
+
const run = async () => {
|
|
1195
|
+
await initializeTools();
|
|
1196
|
+
cachedSkills = await loadAllSkills();
|
|
1197
|
+
setSpinnerOutputEnabled(false);
|
|
1198
|
+
initializeSession();
|
|
1199
|
+
setupAgent();
|
|
1200
|
+
const ui = createCliUi(cachedSkills);
|
|
1201
|
+
activeUiForSignals = ui;
|
|
1202
|
+
try {
|
|
1203
|
+
while (!shouldExit) {
|
|
1204
|
+
const input = await ui.waitForInput();
|
|
1205
|
+
if (input === null) {
|
|
1206
|
+
break;
|
|
1207
|
+
}
|
|
1208
|
+
const shouldContinue = await processInput(ui, input);
|
|
1209
|
+
if (!shouldContinue) {
|
|
1210
|
+
break;
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
finally {
|
|
1215
|
+
activeUiForSignals = null;
|
|
1216
|
+
await ui.dispose();
|
|
1217
|
+
cleanupExecutionResources();
|
|
1218
|
+
setSpinnerOutputEnabled(true);
|
|
1219
|
+
}
|
|
1220
|
+
if (requestedProcessExitCode !== null) {
|
|
1221
|
+
process.exit(requestedProcessExitCode);
|
|
1222
|
+
}
|
|
1223
|
+
};
|
|
1224
|
+
const cleanupExecutionResources = () => {
|
|
1225
|
+
cleanup();
|
|
1226
|
+
};
|
|
1227
|
+
const exitWithCleanup = (code) => {
|
|
1228
|
+
cleanup(true);
|
|
1229
|
+
process.exit(code);
|
|
1230
|
+
};
|
|
1231
|
+
const requestSignalShutdown = (code) => {
|
|
1232
|
+
if (signalShutdownRequested) {
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
signalShutdownRequested = true;
|
|
1236
|
+
requestedProcessExitCode = code;
|
|
1237
|
+
shouldExit = true;
|
|
1238
|
+
if (activeUiForSignals) {
|
|
1239
|
+
activeUiForSignals.requestExit();
|
|
1240
|
+
return;
|
|
1241
|
+
}
|
|
1242
|
+
exitWithCleanup(code);
|
|
1243
|
+
};
|
|
1244
|
+
process.once("exit", () => {
|
|
1245
|
+
cleanupExecutionResources();
|
|
1246
|
+
});
|
|
1247
|
+
process.once("SIGTERM", () => {
|
|
1248
|
+
requestSignalShutdown(143);
|
|
1249
|
+
});
|
|
1250
|
+
process.once("SIGHUP", () => {
|
|
1251
|
+
requestSignalShutdown(129);
|
|
1252
|
+
});
|
|
1253
|
+
process.once("SIGQUIT", () => {
|
|
1254
|
+
requestSignalShutdown(131);
|
|
1255
|
+
});
|
|
1256
|
+
process.once("uncaughtException", (error) => {
|
|
1257
|
+
console.error("Fatal error:", error);
|
|
1258
|
+
exitWithCleanup(1);
|
|
1259
|
+
});
|
|
1260
|
+
process.once("unhandledRejection", (reason) => {
|
|
1261
|
+
console.error("Unhandled rejection:", reason);
|
|
1262
|
+
exitWithCleanup(1);
|
|
1263
|
+
});
|
|
1264
|
+
run().catch((error) => {
|
|
1265
|
+
console.error("Fatal error:", error);
|
|
1266
|
+
exitWithCleanup(1);
|
|
1267
|
+
});
|
|
1268
|
+
//# sourceMappingURL=cli.js.map
|