@xagent-ai/cli 1.2.2 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
- package/.github/release.yml +76 -0
- package/.github/workflows/ci.yml +75 -0
- package/.github/workflows/release.yml +103 -0
- package/.gitmodules +3 -3
- package/README.md +326 -280
- package/README_CN.md +325 -279
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +7 -3
- package/dist/agents.js.map +1 -1
- package/dist/ai-client/factory.d.ts +40 -0
- package/dist/ai-client/factory.d.ts.map +1 -0
- package/dist/ai-client/factory.js +100 -0
- package/dist/ai-client/factory.js.map +1 -0
- package/dist/ai-client/index.d.ts +20 -0
- package/dist/ai-client/index.d.ts.map +1 -0
- package/dist/ai-client/index.js +49 -0
- package/dist/ai-client/index.js.map +1 -0
- package/dist/ai-client/providers/anthropic.d.ts +57 -0
- package/dist/ai-client/providers/anthropic.d.ts.map +1 -0
- package/dist/ai-client/providers/anthropic.js +406 -0
- package/dist/ai-client/providers/anthropic.js.map +1 -0
- package/dist/ai-client/providers/openai.d.ts +57 -0
- package/dist/ai-client/providers/openai.d.ts.map +1 -0
- package/dist/ai-client/providers/openai.js +290 -0
- package/dist/ai-client/providers/openai.js.map +1 -0
- package/dist/ai-client/providers/remote.d.ts +110 -0
- package/dist/ai-client/providers/remote.d.ts.map +1 -0
- package/dist/ai-client/providers/remote.js +352 -0
- package/dist/ai-client/providers/remote.js.map +1 -0
- package/dist/ai-client/registry.d.ts +51 -0
- package/dist/ai-client/registry.d.ts.map +1 -0
- package/dist/ai-client/registry.js +81 -0
- package/dist/ai-client/registry.js.map +1 -0
- package/dist/ai-client/types.d.ts +274 -0
- package/dist/ai-client/types.d.ts.map +1 -0
- package/dist/ai-client/types.js +90 -0
- package/dist/ai-client/types.js.map +1 -0
- package/dist/ai-client-factory.d.ts +62 -0
- package/dist/ai-client-factory.d.ts.map +1 -0
- package/dist/ai-client-factory.js +157 -0
- package/dist/ai-client-factory.js.map +1 -0
- package/dist/auth.d.ts +23 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +164 -174
- package/dist/auth.js.map +1 -1
- package/dist/cancellation.d.ts +5 -4
- package/dist/cancellation.d.ts.map +1 -1
- package/dist/cancellation.js +53 -32
- package/dist/cancellation.js.map +1 -1
- package/dist/checkpoint.d.ts +2 -1
- package/dist/checkpoint.d.ts.map +1 -1
- package/dist/checkpoint.js +39 -6
- package/dist/checkpoint.js.map +1 -1
- package/dist/cli.js +742 -29
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +10 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +62 -25
- package/dist/config.js.map +1 -1
- package/dist/context-compressor.d.ts +82 -18
- package/dist/context-compressor.d.ts.map +1 -1
- package/dist/context-compressor.js +718 -154
- package/dist/context-compressor.js.map +1 -1
- package/dist/conversation.d.ts +1 -1
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +8 -7
- package/dist/conversation.js.map +1 -1
- package/dist/gui-subagent/action-parser/actionParser.d.ts.map +1 -1
- package/dist/gui-subagent/action-parser/actionParser.js +6 -4
- package/dist/gui-subagent/action-parser/actionParser.js.map +1 -1
- package/dist/gui-subagent/agent/gui-agent.d.ts +39 -2
- package/dist/gui-subagent/agent/gui-agent.d.ts.map +1 -1
- package/dist/gui-subagent/agent/gui-agent.js +189 -74
- package/dist/gui-subagent/agent/gui-agent.js.map +1 -1
- package/dist/gui-subagent/index.d.ts +23 -1
- package/dist/gui-subagent/index.d.ts.map +1 -1
- package/dist/gui-subagent/index.js +6 -0
- package/dist/gui-subagent/index.js.map +1 -1
- package/dist/gui-subagent/operator/base-operator.d.ts.map +1 -1
- package/dist/gui-subagent/operator/base-operator.js +0 -1
- package/dist/gui-subagent/operator/base-operator.js.map +1 -1
- package/dist/gui-subagent/operator/computer-operator.d.ts.map +1 -1
- package/dist/gui-subagent/operator/computer-operator.js +31 -8
- package/dist/gui-subagent/operator/computer-operator.js.map +1 -1
- package/dist/gui-subagent/types/actions.d.ts +1 -1
- package/dist/gui-subagent/types/actions.d.ts.map +1 -1
- package/dist/gui-subagent/types/actions.js +0 -1
- package/dist/gui-subagent/types/actions.js.map +1 -1
- package/dist/gui-subagent/types/operator.d.ts +1 -1
- package/dist/gui-subagent/types/operator.d.ts.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/input-processor.d.ts.map +1 -1
- package/dist/input-processor.js +8 -5
- package/dist/input-processor.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +1 -1
- package/dist/logger.js.map +1 -1
- package/dist/mcp.d.ts +7 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +157 -49
- package/dist/mcp.js.map +1 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +3 -3
- package/dist/memory.js.map +1 -1
- package/dist/output-util.d.ts +27 -0
- package/dist/output-util.d.ts.map +1 -0
- package/dist/output-util.js +74 -0
- package/dist/output-util.js.map +1 -0
- package/dist/retry.js +1 -1
- package/dist/retry.js.map +1 -1
- package/dist/ripgrep.d.ts +29 -0
- package/dist/ripgrep.d.ts.map +1 -0
- package/dist/ripgrep.js +294 -0
- package/dist/ripgrep.js.map +1 -0
- package/dist/sdk-output-adapter.d.ts +34 -1
- package/dist/sdk-output-adapter.d.ts.map +1 -1
- package/dist/sdk-output-adapter.js +67 -2
- package/dist/sdk-output-adapter.js.map +1 -1
- package/dist/sdk-session.d.ts.map +1 -1
- package/dist/sdk-session.js +2 -0
- package/dist/sdk-session.js.map +1 -1
- package/dist/session-manager.js +3 -3
- package/dist/session-manager.js.map +1 -1
- package/dist/session.d.ts +116 -6
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +1416 -448
- package/dist/session.js.map +1 -1
- package/dist/shell.d.ts +33 -0
- package/dist/shell.d.ts.map +1 -0
- package/dist/shell.js +126 -0
- package/dist/shell.js.map +1 -0
- package/dist/skill-installer.d.ts +38 -0
- package/dist/skill-installer.d.ts.map +1 -0
- package/dist/skill-installer.js +447 -0
- package/dist/skill-installer.js.map +1 -0
- package/dist/skill-invoker.d.ts +8 -2
- package/dist/skill-invoker.d.ts.map +1 -1
- package/dist/skill-invoker.js +36 -15
- package/dist/skill-invoker.js.map +1 -1
- package/dist/skill-loader.d.ts +8 -3
- package/dist/skill-loader.d.ts.map +1 -1
- package/dist/skill-loader.js +51 -48
- package/dist/skill-loader.js.map +1 -1
- package/dist/skill-manager.d.ts +85 -0
- package/dist/skill-manager.d.ts.map +1 -0
- package/dist/skill-manager.js +341 -0
- package/dist/skill-manager.js.map +1 -0
- package/dist/slash-commands.d.ts +39 -2
- package/dist/slash-commands.d.ts.map +1 -1
- package/dist/slash-commands.js +934 -305
- package/dist/slash-commands.js.map +1 -1
- package/dist/smart-approval.d.ts +20 -1
- package/dist/smart-approval.d.ts.map +1 -1
- package/dist/smart-approval.js +125 -56
- package/dist/smart-approval.js.map +1 -1
- package/dist/system-prompt-generator.d.ts +6 -0
- package/dist/system-prompt-generator.d.ts.map +1 -1
- package/dist/system-prompt-generator.js +86 -36
- package/dist/system-prompt-generator.js.map +1 -1
- package/dist/terminal.d.ts +28 -0
- package/dist/terminal.d.ts.map +1 -0
- package/dist/terminal.js +82 -0
- package/dist/terminal.js.map +1 -0
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +8 -7
- package/dist/theme.js.map +1 -1
- package/dist/tools.d.ts +38 -7
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +1249 -617
- package/dist/tools.js.map +1 -1
- package/dist/truncate.d.ts +55 -0
- package/dist/truncate.d.ts.map +1 -0
- package/dist/truncate.js +130 -0
- package/dist/truncate.js.map +1 -0
- package/dist/types.d.ts +84 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +49 -0
- package/dist/types.js.map +1 -1
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +28 -36
- package/dist/update.js.map +1 -1
- package/dist/workflow.d.ts +5 -1
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +61 -49
- package/dist/workflow.js.map +1 -1
- package/docs/architecture/mcp-integration-guide.md +304 -194
- package/docs/architecture/overview.md +169 -169
- package/docs/architecture/tool-system-design.md +134 -134
- package/docs/cli/commands.md +349 -238
- package/docs/smart-mode.md +281 -281
- package/docs/third-party-models.md +440 -439
- package/find-skills/SKILL.md +133 -0
- package/package.json +91 -90
- package/scripts/install-ripgrep.js +241 -0
- package/src/agents.ts +7 -3
- package/src/ai-client/factory.ts +116 -0
- package/src/ai-client/index.ts +61 -0
- package/src/ai-client/providers/anthropic.ts +475 -0
- package/src/ai-client/providers/openai.ts +348 -0
- package/src/ai-client/providers/remote.ts +439 -0
- package/src/ai-client/registry.ts +97 -0
- package/src/ai-client/types.ts +364 -0
- package/src/ai-client-factory.ts +204 -0
- package/src/auth.ts +661 -614
- package/src/cancellation.ts +202 -176
- package/src/checkpoint.ts +255 -219
- package/src/cli.ts +1523 -743
- package/src/config.ts +341 -297
- package/src/context-compressor.ts +987 -290
- package/src/conversation.ts +290 -288
- package/src/gui-subagent/action-parser/actionParser.ts +318 -315
- package/src/gui-subagent/action-parser/constants.ts +14 -14
- package/src/gui-subagent/action-parser/index.ts +8 -8
- package/src/gui-subagent/action-parser/types.ts +31 -31
- package/src/gui-subagent/agent/gui-agent.ts +1234 -1089
- package/src/gui-subagent/agent/index.ts +5 -5
- package/src/gui-subagent/index.ts +185 -163
- package/src/gui-subagent/operator/base-operator.ts +244 -245
- package/src/gui-subagent/operator/computer-operator.ts +541 -520
- package/src/gui-subagent/operator/index.ts +6 -6
- package/src/gui-subagent/types/actions.ts +260 -262
- package/src/gui-subagent/types/index.ts +6 -6
- package/src/gui-subagent/types/operator.ts +106 -106
- package/src/gui-subagent/utils.ts +51 -51
- package/src/index.ts +17 -18
- package/src/input-processor.ts +8 -5
- package/src/logger.ts +436 -438
- package/src/mcp.ts +793 -682
- package/src/memory.ts +343 -344
- package/src/output-util.ts +80 -0
- package/src/retry.ts +1 -1
- package/src/ripgrep.ts +370 -0
- package/src/sdk-output-adapter.ts +842 -0
- package/src/sdk-session.ts +62 -0
- package/src/session-manager.ts +308 -308
- package/src/session.ts +1775 -573
- package/src/shell.ts +134 -0
- package/src/skill-installer.ts +518 -0
- package/src/skill-invoker.ts +959 -935
- package/src/skill-loader.ts +501 -496
- package/src/skill-manager.ts +385 -0
- package/src/slash-commands.ts +2189 -1389
- package/src/smart-approval.ts +193 -74
- package/src/system-prompt-generator.ts +91 -36
- package/src/terminal.ts +96 -0
- package/src/theme.ts +739 -738
- package/src/tools.ts +1790 -931
- package/src/truncate.ts +173 -0
- package/src/types.ts +337 -198
- package/src/update.ts +33 -40
- package/src/workflow.ts +521 -508
- package/test/cli-launch.test.ts +279 -0
- package/tsconfig.json +22 -22
- package/vitest.config.ts +21 -19
- package/dist/ai-client.d.ts +0 -86
- package/dist/ai-client.d.ts.map +0 -1
- package/dist/ai-client.js +0 -1372
- package/dist/ai-client.js.map +0 -1
- package/dist/gui-subagent/operator/browser-operator.d.ts +0 -36
- package/dist/gui-subagent/operator/browser-operator.d.ts.map +0 -1
- package/dist/gui-subagent/operator/browser-operator.js +0 -306
- package/dist/gui-subagent/operator/browser-operator.js.map +0 -1
- package/dist/gui-subagent/operator/desktop-operator.d.ts +0 -55
- package/dist/gui-subagent/operator/desktop-operator.d.ts.map +0 -1
- package/dist/gui-subagent/operator/desktop-operator.js +0 -527
- package/dist/gui-subagent/operator/desktop-operator.js.map +0 -1
- package/dist/hook.d.ts +0 -73
- package/dist/hook.d.ts.map +0 -1
- package/dist/hook.js +0 -156
- package/dist/hook.js.map +0 -1
- package/dist/input-history.d.ts +0 -24
- package/dist/input-history.d.ts.map +0 -1
- package/dist/input-history.js +0 -94
- package/dist/input-history.js.map +0 -1
- package/dist/keyboard-manager.d.ts +0 -151
- package/dist/keyboard-manager.d.ts.map +0 -1
- package/dist/keyboard-manager.js +0 -396
- package/dist/keyboard-manager.js.map +0 -1
- package/dist/print-system-prompt.d.ts +0 -2
- package/dist/print-system-prompt.d.ts.map +0 -1
- package/dist/print-system-prompt.js +0 -40
- package/dist/print-system-prompt.js.map +0 -1
- package/dist/remote-ai-client.d.ts +0 -104
- package/dist/remote-ai-client.d.ts.map +0 -1
- package/dist/remote-ai-client.js +0 -552
- package/dist/remote-ai-client.js.map +0 -1
- package/dist/sdk-session-v2.d.ts +0 -13
- package/dist/sdk-session-v2.d.ts.map +0 -1
- package/dist/sdk-session-v2.js +0 -46
- package/dist/sdk-session-v2.js.map +0 -1
- package/dist/test-boundary-conditions.d.ts.map +0 -1
- package/dist/test-boundary-conditions.js.map +0 -1
- package/dist/test-cancellation-fix.d.ts.map +0 -1
- package/dist/test-cancellation-fix.js.map +0 -1
- package/dist/test-input-history.d.ts.map +0 -1
- package/dist/test-input-history.js.map +0 -1
- package/dist/test-interaction-flow.d.ts.map +0 -1
- package/dist/test-interaction-flow.js.map +0 -1
- package/dist/test-quick.d.ts.map +0 -1
- package/dist/test-quick.js.map +0 -1
- package/dist/test-user-interaction.d.ts.map +0 -1
- package/dist/test-user-interaction.js.map +0 -1
- package/dist/tools/edit-diff.d.ts +0 -32
- package/dist/tools/edit-diff.d.ts.map +0 -1
- package/dist/tools/edit-diff.js +0 -185
- package/dist/tools/edit-diff.js.map +0 -1
- package/dist/tools/edit.d.ts +0 -11
- package/dist/tools/edit.d.ts.map +0 -1
- package/dist/tools/edit.js +0 -129
- package/dist/tools/edit.js.map +0 -1
- package/dist/unified-session.d.ts +0 -42
- package/dist/unified-session.d.ts.map +0 -1
- package/dist/unified-session.js +0 -271
- package/dist/unified-session.js.map +0 -1
- package/skills/.claude-plugin/marketplace.json +0 -45
- package/skills/README.md +0 -94
- package/skills/THIRD_PARTY_NOTICES.md +0 -405
- package/skills/skills/algorithmic-art/LICENSE.txt +0 -202
- package/skills/skills/algorithmic-art/SKILL.md +0 -405
- package/skills/skills/algorithmic-art/templates/generator_template.js +0 -223
- package/skills/skills/algorithmic-art/templates/viewer.html +0 -599
- package/skills/skills/brand-guidelines/LICENSE.txt +0 -202
- package/skills/skills/brand-guidelines/SKILL.md +0 -73
- package/skills/skills/canvas-design/LICENSE.txt +0 -202
- package/skills/skills/canvas-design/SKILL.md +0 -130
- package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +0 -94
- package/skills/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/Italiana-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/Jura-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/Lora-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/skills/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +0 -93
- package/skills/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
- package/skills/skills/doc-coauthoring/SKILL.md +0 -375
- package/skills/skills/docx/LICENSE.txt +0 -30
- package/skills/skills/docx/SKILL.md +0 -197
- package/skills/skills/docx/docx-js.md +0 -350
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
- package/skills/skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
- package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
- package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
- package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
- package/skills/skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
- package/skills/skills/docx/ooxml/schemas/mce/mc.xsd +0 -75
- package/skills/skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
- package/skills/skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
- package/skills/skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
- package/skills/skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
- package/skills/skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
- package/skills/skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
- package/skills/skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
- package/skills/skills/docx/ooxml/scripts/pack.py +0 -159
- package/skills/skills/docx/ooxml/scripts/unpack.py +0 -29
- package/skills/skills/docx/ooxml/scripts/validate.py +0 -69
- package/skills/skills/docx/ooxml/scripts/validation/__init__.py +0 -15
- package/skills/skills/docx/ooxml/scripts/validation/base.py +0 -951
- package/skills/skills/docx/ooxml/scripts/validation/docx.py +0 -274
- package/skills/skills/docx/ooxml/scripts/validation/pptx.py +0 -315
- package/skills/skills/docx/ooxml/scripts/validation/redlining.py +0 -279
- package/skills/skills/docx/ooxml.md +0 -610
- package/skills/skills/docx/scripts/__init__.py +0 -1
- package/skills/skills/docx/scripts/document.py +0 -1276
- package/skills/skills/docx/scripts/templates/comments.xml +0 -3
- package/skills/skills/docx/scripts/templates/commentsExtended.xml +0 -3
- package/skills/skills/docx/scripts/templates/commentsExtensible.xml +0 -3
- package/skills/skills/docx/scripts/templates/commentsIds.xml +0 -3
- package/skills/skills/docx/scripts/templates/people.xml +0 -3
- package/skills/skills/docx/scripts/utilities.py +0 -374
- package/skills/skills/frontend-design/LICENSE.txt +0 -177
- package/skills/skills/frontend-design/SKILL.md +0 -42
- package/skills/skills/internal-comms/LICENSE.txt +0 -202
- package/skills/skills/internal-comms/SKILL.md +0 -32
- package/skills/skills/internal-comms/examples/3p-updates.md +0 -47
- package/skills/skills/internal-comms/examples/company-newsletter.md +0 -65
- package/skills/skills/internal-comms/examples/faq-answers.md +0 -30
- package/skills/skills/internal-comms/examples/general-comms.md +0 -16
- package/skills/skills/mcp-builder/LICENSE.txt +0 -202
- package/skills/skills/mcp-builder/SKILL.md +0 -236
- package/skills/skills/mcp-builder/reference/evaluation.md +0 -602
- package/skills/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
- package/skills/skills/mcp-builder/reference/node_mcp_server.md +0 -970
- package/skills/skills/mcp-builder/reference/python_mcp_server.md +0 -719
- package/skills/skills/mcp-builder/scripts/connections.py +0 -151
- package/skills/skills/mcp-builder/scripts/evaluation.py +0 -373
- package/skills/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
- package/skills/skills/mcp-builder/scripts/requirements.txt +0 -2
- package/skills/skills/pdf/LICENSE.txt +0 -30
- package/skills/skills/pdf/SKILL.md +0 -294
- package/skills/skills/pdf/forms.md +0 -205
- package/skills/skills/pdf/reference.md +0 -612
- package/skills/skills/pdf/scripts/check_bounding_boxes.py +0 -70
- package/skills/skills/pdf/scripts/check_bounding_boxes_test.py +0 -226
- package/skills/skills/pdf/scripts/check_fillable_fields.py +0 -12
- package/skills/skills/pdf/scripts/convert_pdf_to_images.py +0 -35
- package/skills/skills/pdf/scripts/create_validation_image.py +0 -41
- package/skills/skills/pdf/scripts/extract_form_field_info.py +0 -152
- package/skills/skills/pdf/scripts/fill_fillable_fields.py +0 -114
- package/skills/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -108
- package/skills/skills/pptx/LICENSE.txt +0 -30
- package/skills/skills/pptx/SKILL.md +0 -484
- package/skills/skills/pptx/html2pptx.md +0 -625
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -1499
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -146
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -1085
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -11
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -3081
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -23
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -185
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -287
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -1676
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -28
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -144
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -174
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -25
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -18
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -59
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -56
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -195
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -582
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -25
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -4439
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -570
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -509
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -12
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -108
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -96
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -3646
- package/skills/skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -116
- package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -42
- package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -50
- package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -49
- package/skills/skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -33
- package/skills/skills/pptx/ooxml/schemas/mce/mc.xsd +0 -75
- package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +0 -560
- package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +0 -67
- package/skills/skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +0 -14
- package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -20
- package/skills/skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -13
- package/skills/skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -4
- package/skills/skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -8
- package/skills/skills/pptx/ooxml/scripts/pack.py +0 -159
- package/skills/skills/pptx/ooxml/scripts/unpack.py +0 -29
- package/skills/skills/pptx/ooxml/scripts/validate.py +0 -69
- package/skills/skills/pptx/ooxml/scripts/validation/__init__.py +0 -15
- package/skills/skills/pptx/ooxml/scripts/validation/base.py +0 -951
- package/skills/skills/pptx/ooxml/scripts/validation/docx.py +0 -274
- package/skills/skills/pptx/ooxml/scripts/validation/pptx.py +0 -315
- package/skills/skills/pptx/ooxml/scripts/validation/redlining.py +0 -279
- package/skills/skills/pptx/ooxml.md +0 -427
- package/skills/skills/pptx/scripts/html2pptx.js +0 -979
- package/skills/skills/pptx/scripts/inventory.py +0 -1020
- package/skills/skills/pptx/scripts/rearrange.py +0 -231
- package/skills/skills/pptx/scripts/replace.py +0 -385
- package/skills/skills/pptx/scripts/thumbnail.py +0 -450
- package/skills/skills/skill-creator/LICENSE.txt +0 -202
- package/skills/skills/skill-creator/SKILL.md +0 -356
- package/skills/skills/skill-creator/references/output-patterns.md +0 -82
- package/skills/skills/skill-creator/references/workflows.md +0 -28
- package/skills/skills/skill-creator/scripts/init_skill.py +0 -303
- package/skills/skills/skill-creator/scripts/package_skill.py +0 -110
- package/skills/skills/skill-creator/scripts/quick_validate.py +0 -95
- package/skills/skills/slack-gif-creator/LICENSE.txt +0 -202
- package/skills/skills/slack-gif-creator/SKILL.md +0 -254
- package/skills/skills/slack-gif-creator/core/easing.py +0 -234
- package/skills/skills/slack-gif-creator/core/frame_composer.py +0 -176
- package/skills/skills/slack-gif-creator/core/gif_builder.py +0 -269
- package/skills/skills/slack-gif-creator/core/validators.py +0 -136
- package/skills/skills/slack-gif-creator/requirements.txt +0 -4
- package/skills/skills/theme-factory/LICENSE.txt +0 -202
- package/skills/skills/theme-factory/SKILL.md +0 -59
- package/skills/skills/theme-factory/theme-showcase.pdf +0 -0
- package/skills/skills/theme-factory/themes/arctic-frost.md +0 -19
- package/skills/skills/theme-factory/themes/botanical-garden.md +0 -19
- package/skills/skills/theme-factory/themes/desert-rose.md +0 -19
- package/skills/skills/theme-factory/themes/forest-canopy.md +0 -19
- package/skills/skills/theme-factory/themes/golden-hour.md +0 -19
- package/skills/skills/theme-factory/themes/midnight-galaxy.md +0 -19
- package/skills/skills/theme-factory/themes/modern-minimalist.md +0 -19
- package/skills/skills/theme-factory/themes/ocean-depths.md +0 -19
- package/skills/skills/theme-factory/themes/sunset-boulevard.md +0 -19
- package/skills/skills/theme-factory/themes/tech-innovation.md +0 -19
- package/skills/skills/web-artifacts-builder/LICENSE.txt +0 -202
- package/skills/skills/web-artifacts-builder/SKILL.md +0 -74
- package/skills/skills/web-artifacts-builder/scripts/bundle-artifact.sh +0 -54
- package/skills/skills/web-artifacts-builder/scripts/init-artifact.sh +0 -322
- package/skills/skills/webapp-testing/LICENSE.txt +0 -202
- package/skills/skills/webapp-testing/SKILL.md +0 -96
- package/skills/skills/webapp-testing/examples/console_logging.py +0 -35
- package/skills/skills/webapp-testing/examples/element_discovery.py +0 -40
- package/skills/skills/webapp-testing/examples/static_html_automation.py +0 -33
- package/skills/skills/webapp-testing/scripts/with_server.py +0 -106
- package/skills/skills/xlsx/LICENSE.txt +0 -30
- package/skills/skills/xlsx/SKILL.md +0 -289
- package/skills/skills/xlsx/recalc.py +0 -178
- package/skills/spec/agent-skills-spec.md +0 -3
- package/skills/template/SKILL.md +0 -6
- package/src/ai-client.ts +0 -1560
- package/src/remote-ai-client.ts +0 -664
- /package/{.eslintrc.js → .eslintrc.cjs} +0 -0
package/src/slash-commands.ts
CHANGED
|
@@ -1,1389 +1,2189 @@
|
|
|
1
|
-
import
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import ora from 'ora';
|
|
4
|
-
import fs from 'fs/promises';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
import { ExecutionMode, ChatMessage, InputType,
|
|
7
|
-
import {
|
|
8
|
-
import { getToolRegistry } from './tools.js';
|
|
9
|
-
import { getAgentManager } from './agents.js';
|
|
10
|
-
import { getMemoryManager, MemoryFile } from './memory.js';
|
|
11
|
-
import { getMCPManager, MCPServer } from './mcp.js';
|
|
12
|
-
import { getCheckpointManager } from './checkpoint.js';
|
|
13
|
-
import { getConfigManager, ConfigManager } from './config.js';
|
|
14
|
-
import { getLogger } from './logger.js';
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
private
|
|
29
|
-
private
|
|
30
|
-
private
|
|
31
|
-
private
|
|
32
|
-
private
|
|
33
|
-
private
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
this.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
{
|
|
231
|
-
cmd: '/
|
|
232
|
-
desc: '
|
|
233
|
-
detail: '
|
|
234
|
-
example: '/
|
|
235
|
-
}
|
|
236
|
-
]);
|
|
237
|
-
|
|
238
|
-
//
|
|
239
|
-
this.showHelpCategory('
|
|
240
|
-
{
|
|
241
|
-
cmd: '/
|
|
242
|
-
desc: '
|
|
243
|
-
detail: '
|
|
244
|
-
example: '/
|
|
245
|
-
},
|
|
246
|
-
{
|
|
247
|
-
cmd: '/
|
|
248
|
-
desc: '
|
|
249
|
-
detail: '
|
|
250
|
-
example: '/
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
{
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
console.log(chalk.
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
const
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
const
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
default
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
if (
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
const
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
private async
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
const
|
|
967
|
-
|
|
968
|
-
//
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
return;
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
logger.
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
{
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
logger.
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
}
|
|
1
|
+
import { select, confirm, text } from '@clack/prompts';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import fs from 'fs/promises';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { ExecutionMode, ChatMessage, InputType, Checkpoint, AgentConfig, CompressionConfig, AuthType } from './types.js';
|
|
7
|
+
import { fetchDefaultModels } from './ai-client/providers/remote.js';
|
|
8
|
+
import { getToolRegistry } from './tools.js';
|
|
9
|
+
import { getAgentManager } from './agents.js';
|
|
10
|
+
import { getMemoryManager, MemoryFile } from './memory.js';
|
|
11
|
+
import { getMCPManager, MCPServer } from './mcp.js';
|
|
12
|
+
import { getCheckpointManager } from './checkpoint.js';
|
|
13
|
+
import { getConfigManager, ConfigManager } from './config.js';
|
|
14
|
+
import { getLogger } from './logger.js';
|
|
15
|
+
import {
|
|
16
|
+
getContextCompressor,
|
|
17
|
+
ContextCompressor,
|
|
18
|
+
CompressionResult,
|
|
19
|
+
} from './context-compressor.js';
|
|
20
|
+
import { getConversationManager, ConversationManager } from './conversation.js';
|
|
21
|
+
import { icons, colors } from './theme.js';
|
|
22
|
+
import { ensureTtySane } from './terminal.js';
|
|
23
|
+
import { AuthService, selectAuthType, ThirdPartyProvider, THIRD_PARTY_PROVIDERS, VLM_PROVIDERS, VLMProviderInfo } from './auth.js';
|
|
24
|
+
|
|
25
|
+
const logger = getLogger();
|
|
26
|
+
|
|
27
|
+
export class SlashCommandHandler {
|
|
28
|
+
private configManager: ConfigManager;
|
|
29
|
+
private agentManager: any;
|
|
30
|
+
private memoryManager: any;
|
|
31
|
+
private mcpManager: any;
|
|
32
|
+
private checkpointManager: any;
|
|
33
|
+
private contextCompressor: ContextCompressor;
|
|
34
|
+
private conversationManager: ConversationManager;
|
|
35
|
+
private conversationHistory: ChatMessage[] = [];
|
|
36
|
+
private onClearCallback: (() => void) | null = null;
|
|
37
|
+
private onSystemPromptUpdate: (() => Promise<void>) | null = null;
|
|
38
|
+
private onConfigUpdate: (() => void) | null = null;
|
|
39
|
+
private remoteAIClient: any = null; // Reference to InteractiveSession's remoteAIClient
|
|
40
|
+
|
|
41
|
+
constructor() {
|
|
42
|
+
this.configManager = getConfigManager(process.cwd());
|
|
43
|
+
this.agentManager = getAgentManager(process.cwd());
|
|
44
|
+
this.memoryManager = getMemoryManager(process.cwd());
|
|
45
|
+
this.mcpManager = getMCPManager();
|
|
46
|
+
this.checkpointManager = getCheckpointManager(process.cwd());
|
|
47
|
+
this.contextCompressor = getContextCompressor();
|
|
48
|
+
this.conversationManager = getConversationManager();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Set remote AI client reference (called from InteractiveSession)
|
|
53
|
+
*/
|
|
54
|
+
setRemoteAIClient(client: any): void {
|
|
55
|
+
this.remoteAIClient = client;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Set callback for clearing conversation
|
|
60
|
+
*/
|
|
61
|
+
setClearCallback(callback: () => void): void {
|
|
62
|
+
this.onClearCallback = callback;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Set callback for system prompt update
|
|
67
|
+
*/
|
|
68
|
+
setSystemPromptUpdateCallback(callback: () => Promise<void>): void {
|
|
69
|
+
this.onSystemPromptUpdate = callback;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Set callback for config update (called after /auth changes config)
|
|
74
|
+
*/
|
|
75
|
+
setConfigUpdateCallback(callback: () => void): void {
|
|
76
|
+
this.onConfigUpdate = callback;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Set current conversation history (includes all user/assistant/tool messages)
|
|
81
|
+
*/
|
|
82
|
+
setConversationHistory(messages: ChatMessage[]): void {
|
|
83
|
+
this.conversationHistory = messages;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async handleCommand(input: string): Promise<boolean> {
|
|
87
|
+
if (!input.startsWith('/')) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const [command, ...args] = input.slice(1).split(' ');
|
|
92
|
+
|
|
93
|
+
switch (command.toLowerCase()) {
|
|
94
|
+
case 'help':
|
|
95
|
+
await this.showHelp();
|
|
96
|
+
break;
|
|
97
|
+
case 'init':
|
|
98
|
+
await this.handleInit();
|
|
99
|
+
break;
|
|
100
|
+
case 'clear':
|
|
101
|
+
await this.handleClear();
|
|
102
|
+
break;
|
|
103
|
+
case 'exit':
|
|
104
|
+
case 'quit':
|
|
105
|
+
await this.handleExit();
|
|
106
|
+
break;
|
|
107
|
+
case 'auth':
|
|
108
|
+
await this.handleAuth();
|
|
109
|
+
break;
|
|
110
|
+
case 'login':
|
|
111
|
+
await this.handleLogin();
|
|
112
|
+
break;
|
|
113
|
+
case 'mode':
|
|
114
|
+
await this.handleMode(args);
|
|
115
|
+
break;
|
|
116
|
+
case 'think':
|
|
117
|
+
await this.handleThink(args);
|
|
118
|
+
break;
|
|
119
|
+
case 'agents':
|
|
120
|
+
await this.handleAgents(args);
|
|
121
|
+
break;
|
|
122
|
+
case 'mcp':
|
|
123
|
+
await this.handleMcp(args);
|
|
124
|
+
break;
|
|
125
|
+
case 'skill':
|
|
126
|
+
await this.handleSkill(args);
|
|
127
|
+
break;
|
|
128
|
+
case 'model':
|
|
129
|
+
await this.handleModel();
|
|
130
|
+
break;
|
|
131
|
+
case 'memory':
|
|
132
|
+
await this.handleMemory(args);
|
|
133
|
+
break;
|
|
134
|
+
case 'restore':
|
|
135
|
+
await this.handleRestore(args);
|
|
136
|
+
break;
|
|
137
|
+
case 'tools':
|
|
138
|
+
await this.handleToolsVerbose(args);
|
|
139
|
+
break;
|
|
140
|
+
case 'stats':
|
|
141
|
+
await this.handleStats();
|
|
142
|
+
break;
|
|
143
|
+
case 'theme':
|
|
144
|
+
await this.handleTheme();
|
|
145
|
+
break;
|
|
146
|
+
// case 'language':
|
|
147
|
+
// await this.handleLanguage();
|
|
148
|
+
// break;
|
|
149
|
+
case 'about':
|
|
150
|
+
await this.handleAbout();
|
|
151
|
+
break;
|
|
152
|
+
case 'compress':
|
|
153
|
+
await this.handleCompress(args);
|
|
154
|
+
break;
|
|
155
|
+
case 'update':
|
|
156
|
+
await this.handleUpdate();
|
|
157
|
+
break;
|
|
158
|
+
default:
|
|
159
|
+
logger.warn(`Unknown command: /${command}`, 'Type /help for available commands');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Ensure stdin is in raw mode for proper input handling after @clack/prompts usage
|
|
163
|
+
ensureTtySane();
|
|
164
|
+
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private async showHelp(): Promise<void> {
|
|
169
|
+
const separator = icons.separator.repeat(Math.min(60, process.stdout.columns || 80));
|
|
170
|
+
|
|
171
|
+
console.log('');
|
|
172
|
+
console.log(
|
|
173
|
+
colors.primaryBright('╔════════════════════════════════════════════════════════════╗')
|
|
174
|
+
);
|
|
175
|
+
console.log(colors.primaryBright('║') + ' '.repeat(56) + colors.primaryBright('║'));
|
|
176
|
+
console.log(
|
|
177
|
+
' '.repeat(14) +
|
|
178
|
+
colors.gradient('📚 XAGENT CLI Help') +
|
|
179
|
+
' '.repeat(31) +
|
|
180
|
+
colors.primaryBright('║')
|
|
181
|
+
);
|
|
182
|
+
console.log(colors.primaryBright('║') + ' '.repeat(56) + colors.primaryBright('║'));
|
|
183
|
+
console.log(
|
|
184
|
+
colors.primaryBright('╚════════════════════════════════════════════════════════════╝')
|
|
185
|
+
);
|
|
186
|
+
console.log('');
|
|
187
|
+
|
|
188
|
+
// Shortcuts
|
|
189
|
+
console.log(colors.accent('Shortcuts'));
|
|
190
|
+
console.log(colors.border(separator));
|
|
191
|
+
console.log('');
|
|
192
|
+
console.log(
|
|
193
|
+
colors.textDim(` ${colors.accent('!')} - ${colors.textMuted('Enter bash mode')}`)
|
|
194
|
+
);
|
|
195
|
+
console.log(colors.textDim(` ${colors.accent('/')} - ${colors.textMuted('Commands')}`));
|
|
196
|
+
console.log(colors.textDim(` ${colors.accent('@')} - ${colors.textMuted('File paths')}`));
|
|
197
|
+
console.log('');
|
|
198
|
+
|
|
199
|
+
// Basic Commands
|
|
200
|
+
this.showHelpCategory('Basic Commands', [
|
|
201
|
+
{
|
|
202
|
+
cmd: '/help [command]',
|
|
203
|
+
desc: 'Show help information',
|
|
204
|
+
detail: 'View all available commands or detailed description of specific command',
|
|
205
|
+
example: '/help\n/help mode',
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
cmd: '/clear',
|
|
209
|
+
desc: 'Clear conversation history',
|
|
210
|
+
detail: 'Clear all conversation records of current session, start new conversation',
|
|
211
|
+
example: '/clear',
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
cmd: '/exit',
|
|
215
|
+
desc: 'Exit program',
|
|
216
|
+
detail: 'Safely exit XAGENT CLI',
|
|
217
|
+
example: '/exit',
|
|
218
|
+
},
|
|
219
|
+
]);
|
|
220
|
+
|
|
221
|
+
// Project Management
|
|
222
|
+
this.showHelpCategory('Project Management', [
|
|
223
|
+
{
|
|
224
|
+
cmd: '/init',
|
|
225
|
+
desc: 'Initialize project context',
|
|
226
|
+
detail:
|
|
227
|
+
'Create XAGENT.md file in current directory, used to store project context information',
|
|
228
|
+
example: '/init',
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
cmd: '/memory [show|clear]',
|
|
232
|
+
desc: 'Manage project memory',
|
|
233
|
+
detail: 'View or clear memory (global, current, all, or filename)',
|
|
234
|
+
example: '/memory show\n/memory clear\n/memory clear global\n/memory clear all',
|
|
235
|
+
},
|
|
236
|
+
]);
|
|
237
|
+
|
|
238
|
+
// Authentication & Configuration
|
|
239
|
+
this.showHelpCategory('Authentication & Configuration', [
|
|
240
|
+
{
|
|
241
|
+
cmd: '/auth',
|
|
242
|
+
desc: 'Configure authentication information',
|
|
243
|
+
detail: 'Change or view current authentication configuration',
|
|
244
|
+
example: '/auth',
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
cmd: '/mode [mode]',
|
|
248
|
+
desc: 'Switch approval mode',
|
|
249
|
+
detail: 'Switch security approval mode for tool execution',
|
|
250
|
+
example: '/mode\n/mode smart\n/mode yolo',
|
|
251
|
+
modes: [
|
|
252
|
+
'yolo - Execute all operations without restriction',
|
|
253
|
+
'accept_edits - Automatically accept edit operations',
|
|
254
|
+
'plan - Plan before executing',
|
|
255
|
+
'default - Safe execution, requires confirmation',
|
|
256
|
+
'smart - Smart approval (recommended)',
|
|
257
|
+
],
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
cmd: '/think [on|off|display]',
|
|
261
|
+
desc: 'Control thinking mode',
|
|
262
|
+
detail: 'Enable/disable AI thinking process display',
|
|
263
|
+
example: '/think on\n/think off\n/think display compact',
|
|
264
|
+
},
|
|
265
|
+
// {
|
|
266
|
+
// cmd: '/language [zh|en]',
|
|
267
|
+
// desc: 'Switch language',
|
|
268
|
+
// detail: 'Switch between Chinese and English interface',
|
|
269
|
+
// example: '/language zh\n/language en'
|
|
270
|
+
// },
|
|
271
|
+
{
|
|
272
|
+
cmd: '/theme',
|
|
273
|
+
desc: 'Switch theme',
|
|
274
|
+
detail: 'Change UI theme style',
|
|
275
|
+
example: '/theme',
|
|
276
|
+
},
|
|
277
|
+
]);
|
|
278
|
+
|
|
279
|
+
// Feature Extensions
|
|
280
|
+
this.showHelpCategory('Feature Extensions', [
|
|
281
|
+
{
|
|
282
|
+
cmd: '/agents [list|online|install|remove]',
|
|
283
|
+
desc: 'Manage sub-agents',
|
|
284
|
+
detail: 'View, install or remove specialized AI sub-agents',
|
|
285
|
+
example: '/agents list\n/agents online\n/agents install explore-agent',
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
cmd: '/mcp [list|add|remove|refresh]',
|
|
289
|
+
desc: 'Manage MCP servers',
|
|
290
|
+
detail: 'Manage Model Context Protocol servers',
|
|
291
|
+
example: '/mcp list\n/mcp add server-name',
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
cmd: '/skill [list|add|remove]',
|
|
295
|
+
desc: 'Manage skills',
|
|
296
|
+
detail: 'Install, list, or remove skills from ~/.xagent/skills',
|
|
297
|
+
example: '/skill list\n/skill add ./my-skill\n/skill add owner/repo\n/skill remove my-skill'
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
cmd: '/vlm',
|
|
301
|
+
desc: 'Configure VLM for GUI Agent',
|
|
302
|
+
detail: 'Configure Vision-Language Model for browser/desktop automation',
|
|
303
|
+
example: '/vlm'
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
cmd: '/model',
|
|
307
|
+
desc: 'Configure LLM/VLM models',
|
|
308
|
+
detail: 'Configure or switch LLM and VLM models for remote mode',
|
|
309
|
+
example: '/model',
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
cmd: '/tools [verbose|simple]',
|
|
313
|
+
desc: 'Manage tool display',
|
|
314
|
+
detail: 'View available tools or switch tool call display mode',
|
|
315
|
+
example: '/tools\n/tools verbose\n/tools simple',
|
|
316
|
+
},
|
|
317
|
+
]);
|
|
318
|
+
|
|
319
|
+
// Advanced Features
|
|
320
|
+
this.showHelpCategory('Advanced Features', [
|
|
321
|
+
{
|
|
322
|
+
cmd: '/restore',
|
|
323
|
+
desc: 'Restore from checkpoint',
|
|
324
|
+
detail: 'Restore conversation state from historical checkpoints',
|
|
325
|
+
example: '/restore',
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
cmd: '/compress [on|off|max_message|max_token|exec]',
|
|
329
|
+
desc: 'Manage context compression',
|
|
330
|
+
detail: 'Configure compression settings or execute compression manually',
|
|
331
|
+
example:
|
|
332
|
+
'/compress\n/compress exec\n/compress on\n/compress max_message 50\n/compress max_token 1500000',
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
cmd: '/stats',
|
|
336
|
+
desc: 'Show session statistics',
|
|
337
|
+
detail: 'View statistics information of current session',
|
|
338
|
+
example: '/stats',
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
cmd: '/about',
|
|
342
|
+
desc: 'Show version information',
|
|
343
|
+
detail: 'View version and related information of XAGENT CLI',
|
|
344
|
+
example: '/about',
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
cmd: '/update',
|
|
348
|
+
desc: 'Check for updates',
|
|
349
|
+
detail: 'Check for new versions and update xAgent CLI',
|
|
350
|
+
example: '/update',
|
|
351
|
+
},
|
|
352
|
+
]);
|
|
353
|
+
|
|
354
|
+
// Keyboard Shortcuts
|
|
355
|
+
console.log('');
|
|
356
|
+
console.log(colors.border(separator));
|
|
357
|
+
console.log(colors.primaryBright('Keyboard Shortcuts'));
|
|
358
|
+
console.log(colors.border(separator));
|
|
359
|
+
console.log('');
|
|
360
|
+
console.log(colors.textMuted(' ESC - Cancel current operation'));
|
|
361
|
+
console.log(colors.textMuted(' Ctrl+C - Exit program'));
|
|
362
|
+
console.log('');
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
private showHelpCategory(
|
|
366
|
+
title: string,
|
|
367
|
+
commands: Array<{
|
|
368
|
+
cmd: string;
|
|
369
|
+
desc: string;
|
|
370
|
+
detail: string;
|
|
371
|
+
example: string;
|
|
372
|
+
modes?: string[];
|
|
373
|
+
}>
|
|
374
|
+
): void {
|
|
375
|
+
const separator = icons.separator.repeat(Math.min(60, process.stdout.columns || 80));
|
|
376
|
+
|
|
377
|
+
console.log('');
|
|
378
|
+
console.log(colors.border(separator));
|
|
379
|
+
console.log(colors.primaryBright(title));
|
|
380
|
+
console.log(colors.border(separator));
|
|
381
|
+
console.log('');
|
|
382
|
+
|
|
383
|
+
commands.forEach((cmd) => {
|
|
384
|
+
console.log(colors.primaryBright(` ${cmd.cmd}`));
|
|
385
|
+
console.log(colors.textDim(` ${cmd.desc}`));
|
|
386
|
+
console.log(colors.textMuted(` ${cmd.detail}`));
|
|
387
|
+
|
|
388
|
+
if (cmd.modes) {
|
|
389
|
+
console.log(colors.textDim(` Available modes:`));
|
|
390
|
+
cmd.modes.forEach((mode) => {
|
|
391
|
+
console.log(colors.textDim(` • ${mode}`));
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
console.log(colors.accent(` Examples:`));
|
|
396
|
+
cmd.example.split('\n').forEach((ex) => {
|
|
397
|
+
console.log(colors.codeText(` ${ex}`));
|
|
398
|
+
});
|
|
399
|
+
console.log('');
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
private async handleInit(): Promise<void> {
|
|
404
|
+
const spinner = ora('Initializing project...').start();
|
|
405
|
+
|
|
406
|
+
try {
|
|
407
|
+
await this.memoryManager.initializeProject(process.cwd());
|
|
408
|
+
spinner.succeed('Project initialized successfully');
|
|
409
|
+
} catch (error: any) {
|
|
410
|
+
spinner.fail(`Initialization failed: ${error.message}`);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
private async handleClear(): Promise<void> {
|
|
415
|
+
// Clear local conversation history
|
|
416
|
+
this.conversationHistory = [];
|
|
417
|
+
|
|
418
|
+
// Clear current conversation in ConversationManager
|
|
419
|
+
await this.conversationManager.clearCurrentConversation();
|
|
420
|
+
|
|
421
|
+
// Call callback to notify InteractiveSession to clear conversation
|
|
422
|
+
if (this.onClearCallback) {
|
|
423
|
+
this.onClearCallback();
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
logger.success('Conversation history cleared', 'Start a new conversation');
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
private async handleExit(): Promise<void> {
|
|
430
|
+
logger.info('Goodbye!', 'Thank you for using xAgent CLI');
|
|
431
|
+
process.exit(0);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
private async handleAuth(): Promise<void> {
|
|
435
|
+
logger.section('Authentication Management');
|
|
436
|
+
|
|
437
|
+
// Show current authentication configuration
|
|
438
|
+
const authConfig = this.configManager.getAuthConfig();
|
|
439
|
+
const isRemote = authConfig.type === AuthType.OAUTH_XAGENT;
|
|
440
|
+
const currentType = isRemote ? 'xAgent (Remote)' : 'Third-party API (Local)';
|
|
441
|
+
|
|
442
|
+
console.log(chalk.cyan('\n📋 Current Authentication Configuration:\n'));
|
|
443
|
+
console.log(` ${chalk.yellow('Mode:')} ${currentType}`);
|
|
444
|
+
|
|
445
|
+
if (isRemote) {
|
|
446
|
+
// Remote mode: show remote_llmModelName and remote_vlmModelName
|
|
447
|
+
const llmModel = authConfig.remote_llmModelName || 'Not set';
|
|
448
|
+
const vlmModel = authConfig.remote_vlmModelName || 'Not set';
|
|
449
|
+
console.log(` ${chalk.yellow('LLM Model:')} ${llmModel}`);
|
|
450
|
+
console.log(` ${chalk.yellow('VLM Model:')} ${vlmModel}`);
|
|
451
|
+
} else {
|
|
452
|
+
// Local mode: show modelName (LLM) and guiSubagentModel (VLM)
|
|
453
|
+
const llmModel = authConfig.modelName || 'Not set';
|
|
454
|
+
const vlmModel = this.configManager.get('guiSubagentModel') || 'Not set';
|
|
455
|
+
console.log(` ${chalk.yellow('LLM Model:')} ${llmModel}`);
|
|
456
|
+
console.log(` ${chalk.yellow('VLM Model:')} ${vlmModel}`);
|
|
457
|
+
}
|
|
458
|
+
console.log('');
|
|
459
|
+
|
|
460
|
+
const action = await select({
|
|
461
|
+
message: 'Select action:',
|
|
462
|
+
options: [
|
|
463
|
+
{ value: 'switch', label: 'Switch authentication method' },
|
|
464
|
+
{ value: 'back', label: 'Back' },
|
|
465
|
+
],
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
if (action === 'back') {
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (action === 'switch') {
|
|
473
|
+
// Use the same selection UI as initial setup
|
|
474
|
+
const confirmSwitch = await confirm({
|
|
475
|
+
message: `Switch from "${currentType}" to another authentication method?`,
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
if (confirmSwitch === false || confirmSwitch === undefined) {
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// Select authentication type (same as initial setup)
|
|
483
|
+
const authType = await selectAuthType();
|
|
484
|
+
|
|
485
|
+
if (authType === AuthType.OAUTH_XAGENT) {
|
|
486
|
+
// Switch to xAgent (Remote mode)
|
|
487
|
+
const authService = new AuthService({
|
|
488
|
+
type: AuthType.OAUTH_XAGENT,
|
|
489
|
+
apiKey: '',
|
|
490
|
+
baseUrl: '',
|
|
491
|
+
xagentApiBaseUrl: authConfig.xagentApiBaseUrl,
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
const success = await authService.authenticate();
|
|
495
|
+
if (success) {
|
|
496
|
+
const newAuthConfig = authService.getAuthConfig();
|
|
497
|
+
this.configManager.setAuthConfig({
|
|
498
|
+
selectedAuthType: newAuthConfig.type,
|
|
499
|
+
apiKey: newAuthConfig.apiKey,
|
|
500
|
+
refreshToken: newAuthConfig.refreshToken,
|
|
501
|
+
baseUrl: newAuthConfig.baseUrl,
|
|
502
|
+
modelName: '',
|
|
503
|
+
xagentApiBaseUrl: newAuthConfig.xagentApiBaseUrl,
|
|
504
|
+
guiSubagentModel: '',
|
|
505
|
+
guiSubagentBaseUrl: 'https://www.xagent-colife.net/v3',
|
|
506
|
+
guiSubagentApiKey: '',
|
|
507
|
+
});
|
|
508
|
+
// Set default remote model settings if not already set
|
|
509
|
+
// Fetch default models from /models/default endpoint
|
|
510
|
+
const webBaseUrl = newAuthConfig.xagentApiBaseUrl || 'https://www.xagent-colife.net';
|
|
511
|
+
let defaultLlmName = '';
|
|
512
|
+
let defaultVlmName = '';
|
|
513
|
+
|
|
514
|
+
try {
|
|
515
|
+
console.log(chalk.cyan('\n📊 Fetching default models from remote server...'));
|
|
516
|
+
const defaults = await fetchDefaultModels(newAuthConfig.apiKey || '', webBaseUrl);
|
|
517
|
+
|
|
518
|
+
if (defaults.llm?.name) {
|
|
519
|
+
defaultLlmName = defaults.llm.name;
|
|
520
|
+
console.log(chalk.cyan(` LLM Model: ${defaults.llm.name}`));
|
|
521
|
+
}
|
|
522
|
+
if (defaults.vlm?.name) {
|
|
523
|
+
defaultVlmName = defaults.vlm.name;
|
|
524
|
+
console.log(chalk.cyan(` VLM Model: ${defaults.vlm.name}`));
|
|
525
|
+
}
|
|
526
|
+
} catch (error: any) {
|
|
527
|
+
console.log(chalk.yellow(` ⚠️ Failed to fetch default models: ${error.message}`));
|
|
528
|
+
console.log(chalk.yellow(' ⚠️ Use /model command to select models manually.'));
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
console.log('');
|
|
532
|
+
|
|
533
|
+
this.configManager.set('remote_llmModelName', defaultLlmName);
|
|
534
|
+
this.configManager.set('remote_vlmModelName', defaultVlmName);
|
|
535
|
+
this.configManager.save('global');
|
|
536
|
+
|
|
537
|
+
// Notify InteractiveSession to update aiClient config
|
|
538
|
+
if (this.onConfigUpdate) {
|
|
539
|
+
this.onConfigUpdate();
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
console.log(chalk.green('\n✅ Authentication switched to xAgent (Remote mode)!'));
|
|
543
|
+
// Removed: logging partial token for security
|
|
544
|
+
}
|
|
545
|
+
} else {
|
|
546
|
+
// Switch to Third-party API (Local mode)
|
|
547
|
+
const authService = new AuthService({
|
|
548
|
+
type: AuthType.OPENAI_COMPATIBLE,
|
|
549
|
+
apiKey: '',
|
|
550
|
+
baseUrl: '',
|
|
551
|
+
modelName: '',
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
const success = await authService.authenticate();
|
|
555
|
+
if (success) {
|
|
556
|
+
const newAuthConfig = authService.getAuthConfig();
|
|
557
|
+
this.configManager.setAuthConfig({
|
|
558
|
+
selectedAuthType: newAuthConfig.type,
|
|
559
|
+
apiKey: newAuthConfig.apiKey,
|
|
560
|
+
baseUrl: newAuthConfig.baseUrl,
|
|
561
|
+
modelName: newAuthConfig.modelName,
|
|
562
|
+
xagentApiBaseUrl: '',
|
|
563
|
+
refreshToken: '',
|
|
564
|
+
guiSubagentModel: '',
|
|
565
|
+
guiSubagentBaseUrl: '',
|
|
566
|
+
guiSubagentApiKey: '',
|
|
567
|
+
});
|
|
568
|
+
this.configManager.save('global');
|
|
569
|
+
|
|
570
|
+
// Notify InteractiveSession to update aiClient config
|
|
571
|
+
if (this.onConfigUpdate) {
|
|
572
|
+
this.onConfigUpdate();
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
console.log(chalk.green('\n✅ Authentication switched to Third-party API (Local mode)!'));
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
private async handleLogin(): Promise<void> {
|
|
582
|
+
logger.section('Login to xAgent');
|
|
583
|
+
|
|
584
|
+
const authConfig = this.configManager.getAuthConfig();
|
|
585
|
+
const currentAuthType = authConfig.type;
|
|
586
|
+
|
|
587
|
+
if (currentAuthType !== AuthType.OAUTH_XAGENT) {
|
|
588
|
+
console.log(chalk.yellow('\n⚠️ Current authentication type is not OAuth xAgent.'));
|
|
589
|
+
const proceed = await confirm({
|
|
590
|
+
message: 'Do you want to switch to OAuth xAgent authentication?',
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
if (proceed === false || proceed === undefined) {
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// Switch to OAuth xAgent
|
|
598
|
+
this.configManager.setAuthConfig({
|
|
599
|
+
selectedAuthType: AuthType.OAUTH_XAGENT,
|
|
600
|
+
apiKey: '',
|
|
601
|
+
refreshToken: '',
|
|
602
|
+
baseUrl: '',
|
|
603
|
+
});
|
|
604
|
+
this.configManager.save('global');
|
|
605
|
+
console.log(chalk.green('✅ Switched to OAuth xAgent authentication.'));
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
console.log(chalk.cyan('\n🔐 Starting OAuth xAgent login...'));
|
|
609
|
+
console.log(chalk.gray(' A browser will open for you to complete authentication.\n'));
|
|
610
|
+
|
|
611
|
+
try {
|
|
612
|
+
// Get xagentApiBaseUrl from config (respects XAGENT_BASE_URL env var)
|
|
613
|
+
const config = this.configManager.getAuthConfig();
|
|
614
|
+
|
|
615
|
+
const authService = new AuthService({
|
|
616
|
+
type: AuthType.OAUTH_XAGENT,
|
|
617
|
+
apiKey: '',
|
|
618
|
+
baseUrl: '',
|
|
619
|
+
refreshToken: '',
|
|
620
|
+
xagentApiBaseUrl: config.xagentApiBaseUrl,
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
const success = await authService.authenticate();
|
|
624
|
+
|
|
625
|
+
if (success) {
|
|
626
|
+
console.log(chalk.green('\n✅ Login successful!'));
|
|
627
|
+
console.log(chalk.cyan(` Token saved to: ~/.xagent/settings.json`));
|
|
628
|
+
console.log(chalk.gray(' You can now use xAgent CLI with remote AI services.\n'));
|
|
629
|
+
} else {
|
|
630
|
+
console.log(chalk.red('\n❌ Login failed or was cancelled.'));
|
|
631
|
+
}
|
|
632
|
+
} catch (error: any) {
|
|
633
|
+
console.log(chalk.red(`\n❌ Login error: ${error.message || 'Unknown error'}`));
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* Handle /model command - Configure LLM/VLM models
|
|
639
|
+
* Supports both remote mode (xAgent) and local mode (third-party API)
|
|
640
|
+
*/
|
|
641
|
+
private async handleModel(): Promise<void> {
|
|
642
|
+
const authConfig = this.configManager.getAuthConfig();
|
|
643
|
+
|
|
644
|
+
// Determine mode and show appropriate UI
|
|
645
|
+
if (authConfig.type === AuthType.OAUTH_XAGENT) {
|
|
646
|
+
// Remote mode - use backend models
|
|
647
|
+
await this.handleRemoteModel();
|
|
648
|
+
} else {
|
|
649
|
+
// Local mode - configure third-party API directly
|
|
650
|
+
await this.handleLocalModel();
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Handle /model command for remote mode - Configure models from backend
|
|
656
|
+
*/
|
|
657
|
+
private async handleRemoteModel(): Promise<void> {
|
|
658
|
+
const authConfig = this.configManager.getAuthConfig();
|
|
659
|
+
|
|
660
|
+
// Auto-fetch default models if not set
|
|
661
|
+
let currentLlm = authConfig.remote_llmModelName;
|
|
662
|
+
let currentVlm = authConfig.remote_vlmModelName;
|
|
663
|
+
|
|
664
|
+
if (!currentLlm || !currentVlm) {
|
|
665
|
+
console.log(chalk.cyan('\n📊 Fetching default models from remote server...'));
|
|
666
|
+
|
|
667
|
+
// Try to use RemoteAIClient first, otherwise fetch directly
|
|
668
|
+
let defaults: { llm?: { name: string; displayName?: string }; vlm?: { name: string; displayName?: string } } | null = null;
|
|
669
|
+
|
|
670
|
+
if (this.remoteAIClient) {
|
|
671
|
+
try {
|
|
672
|
+
defaults = await this.remoteAIClient.getDefaultModels();
|
|
673
|
+
} catch (error: any) {
|
|
674
|
+
console.log(chalk.yellow(` ⚠️ Failed to get defaults from RemoteAIClient: ${error.message}`));
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// If RemoteAIClient failed or not available, fetch directly
|
|
679
|
+
if (!defaults) {
|
|
680
|
+
try {
|
|
681
|
+
const webBaseUrl = authConfig.xagentApiBaseUrl || 'https://www.xagent-colife.net';
|
|
682
|
+
defaults = await fetchDefaultModels(authConfig.apiKey || '', webBaseUrl);
|
|
683
|
+
} catch (error: any) {
|
|
684
|
+
console.log(chalk.yellow(` ⚠️ Failed to fetch default models: ${error.message}`));
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
if (defaults) {
|
|
689
|
+
if (!currentLlm && defaults.llm?.name) {
|
|
690
|
+
currentLlm = defaults.llm.name;
|
|
691
|
+
this.configManager.set('remote_llmModelName', currentLlm);
|
|
692
|
+
console.log(chalk.cyan(` Default LLM: ${defaults.llm.displayName || currentLlm}`));
|
|
693
|
+
}
|
|
694
|
+
if (!currentVlm && defaults.vlm?.name) {
|
|
695
|
+
currentVlm = defaults.vlm.name;
|
|
696
|
+
this.configManager.set('remote_vlmModelName', currentVlm);
|
|
697
|
+
console.log(chalk.cyan(` Default VLM: ${defaults.vlm.displayName || currentVlm}`));
|
|
698
|
+
}
|
|
699
|
+
this.configManager.save('global');
|
|
700
|
+
} else {
|
|
701
|
+
console.log(chalk.yellow(' ⚠️ Use /auth to configure remote mode first.'));
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
// Get RemoteAIClient instance (from InteractiveSession) for model selection
|
|
707
|
+
const remoteClient = this.remoteAIClient;
|
|
708
|
+
|
|
709
|
+
// Display current configuration
|
|
710
|
+
console.log(chalk.cyan('\n📊 Current Model Configuration:\n'));
|
|
711
|
+
console.log(` ${chalk.yellow('LLM Model:')} ${currentLlm || 'Not set'}`);
|
|
712
|
+
console.log(` ${chalk.yellow('VLM Model:')} ${currentVlm || 'Not set'}`);
|
|
713
|
+
console.log('');
|
|
714
|
+
|
|
715
|
+
// Main menu
|
|
716
|
+
const action = await select({
|
|
717
|
+
message: 'Select action:',
|
|
718
|
+
options: [
|
|
719
|
+
{ value: 'llm', label: 'Change LLM model' },
|
|
720
|
+
{ value: 'vlm', label: 'Change VLM model' },
|
|
721
|
+
{ value: 'back', label: 'Back' },
|
|
722
|
+
],
|
|
723
|
+
}) as string | symbol;
|
|
724
|
+
|
|
725
|
+
if (action === 'back' || typeof action === 'symbol') {
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// Restore stdin raw mode after @clack/prompts interaction
|
|
730
|
+
ensureTtySane();
|
|
731
|
+
|
|
732
|
+
// Get and display provider list
|
|
733
|
+
try {
|
|
734
|
+
const models = await remoteClient.getRemoteModels();
|
|
735
|
+
const modelList = action === 'llm' ? models.llm : models.vlm;
|
|
736
|
+
|
|
737
|
+
if (modelList.length === 0) {
|
|
738
|
+
console.log(chalk.yellow('\n⚠️ No models available.'));
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// Build choice list
|
|
743
|
+
const choices = modelList.map((m: any) => ({
|
|
744
|
+
name: `${m.displayName} (${m.name})`,
|
|
745
|
+
value: m.name
|
|
746
|
+
}));
|
|
747
|
+
|
|
748
|
+
const selectedModel = await select({
|
|
749
|
+
message: action === 'llm' ? 'Select LLM Model:' : 'Select VLM Model:',
|
|
750
|
+
options: choices
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
if (typeof selectedModel !== 'string') {
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
const configKey = action === 'llm' ? 'remote_llmModelName' : 'remote_vlmModelName';
|
|
758
|
+
this.configManager.set(configKey, selectedModel);
|
|
759
|
+
this.configManager.save('global');
|
|
760
|
+
|
|
761
|
+
// Clear conversation history to avoid tool call ID conflicts between providers
|
|
762
|
+
if (this.onClearCallback) {
|
|
763
|
+
this.onClearCallback();
|
|
764
|
+
console.log(
|
|
765
|
+
chalk.cyan(' Conversation cleared to avoid tool call ID conflicts between models.')
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
// Notify InteractiveSession to update aiClient config
|
|
770
|
+
if (this.onConfigUpdate) {
|
|
771
|
+
this.onConfigUpdate();
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
console.log(chalk.green('\n✅ Model updated successfully!'));
|
|
775
|
+
console.log(` ${action === 'llm' ? 'LLM' : 'VLM'}: ${selectedModel}`);
|
|
776
|
+
} catch (error: any) {
|
|
777
|
+
console.log(chalk.red(`\n❌ Failed to get models: ${error.message}`));
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/**
|
|
782
|
+
* Handle /model command for local mode - Configure third-party API directly
|
|
783
|
+
* Reuses code from initial setup flow (authenticateWithOpenAICompatible and configureAndValidateVLM)
|
|
784
|
+
*/
|
|
785
|
+
private async handleLocalModel(): Promise<void> {
|
|
786
|
+
// Display current configuration
|
|
787
|
+
const currentLlmModel = this.configManager.get('modelName') || this.configManager.getAuthConfig().modelName;
|
|
788
|
+
const currentVlmModel = this.configManager.get('guiSubagentModel');
|
|
789
|
+
|
|
790
|
+
console.log(chalk.cyan('\n📊 Current Local Model Configuration:\n'));
|
|
791
|
+
console.log(` ${chalk.yellow('LLM Model:')} ${currentLlmModel || 'Not set'}`);
|
|
792
|
+
console.log(` ${chalk.yellow('VLM Model:')} ${currentVlmModel || 'Not set'}`);
|
|
793
|
+
console.log('');
|
|
794
|
+
|
|
795
|
+
// Main menu - choose to configure LLM or VLM
|
|
796
|
+
const action = await select({
|
|
797
|
+
message: 'Select action:',
|
|
798
|
+
options: [
|
|
799
|
+
{ value: 'llm', label: 'Change LLM (select provider and API)' },
|
|
800
|
+
{ value: 'vlm', label: 'Change VLM (for GUI automation)' },
|
|
801
|
+
{ value: 'back', label: 'Back' },
|
|
802
|
+
],
|
|
803
|
+
}) as string | symbol;
|
|
804
|
+
|
|
805
|
+
if (action === 'back' || typeof action === 'symbol') {
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
if (action === 'llm') {
|
|
810
|
+
await this.configureLocalLLM();
|
|
811
|
+
} else if (action === 'vlm') {
|
|
812
|
+
await this.configureLocalVLM();
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
/**
|
|
817
|
+
* Configure LLM for local mode - Reuses authenticateWithOpenAICompatible logic
|
|
818
|
+
*/
|
|
819
|
+
private async configureLocalLLM(): Promise<void> {
|
|
820
|
+
// THIRD_PARTY_PROVIDERS already imported at top level
|
|
821
|
+
const provider = await select({
|
|
822
|
+
message: 'Select third-party model provider:',
|
|
823
|
+
options: THIRD_PARTY_PROVIDERS.map((p) => ({
|
|
824
|
+
value: p,
|
|
825
|
+
label: `${p.name} - ${p.description}`,
|
|
826
|
+
})),
|
|
827
|
+
}) as ThirdPartyProvider | symbol;
|
|
828
|
+
|
|
829
|
+
if (typeof provider === 'symbol') {
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
const selectedProvider = provider;
|
|
834
|
+
|
|
835
|
+
let baseUrl = selectedProvider.baseUrl;
|
|
836
|
+
let modelName = selectedProvider.defaultModel;
|
|
837
|
+
|
|
838
|
+
if (selectedProvider.name === 'Custom') {
|
|
839
|
+
baseUrl = (await import('@clack/prompts').then(m =>
|
|
840
|
+
m.text({
|
|
841
|
+
message: 'Enter API Base URL:',
|
|
842
|
+
defaultValue: 'https://api.openai.com/v1',
|
|
843
|
+
validate: (value: string | undefined) => {
|
|
844
|
+
if (!value || value.trim().length === 0) {
|
|
845
|
+
return 'Base URL cannot be empty';
|
|
846
|
+
}
|
|
847
|
+
return undefined;
|
|
848
|
+
},
|
|
849
|
+
})
|
|
850
|
+
)) as string;
|
|
851
|
+
|
|
852
|
+
modelName = (await import('@clack/prompts').then(m =>
|
|
853
|
+
m.text({
|
|
854
|
+
message: 'Enter model name:',
|
|
855
|
+
defaultValue: 'gpt-4',
|
|
856
|
+
validate: (value: string | undefined) => {
|
|
857
|
+
if (!value || value.trim().length === 0) {
|
|
858
|
+
return 'Model name cannot be empty';
|
|
859
|
+
}
|
|
860
|
+
return undefined;
|
|
861
|
+
},
|
|
862
|
+
})
|
|
863
|
+
)) as string;
|
|
864
|
+
|
|
865
|
+
baseUrl = baseUrl.trim();
|
|
866
|
+
modelName = modelName.trim();
|
|
867
|
+
} else {
|
|
868
|
+
console.log(chalk.cyan(`\nSelected: ${selectedProvider.name}`));
|
|
869
|
+
console.log(chalk.cyan(`API URL: ${baseUrl}`));
|
|
870
|
+
|
|
871
|
+
if (selectedProvider.models && selectedProvider.models.length > 0) {
|
|
872
|
+
console.log(chalk.cyan(`Available models: ${selectedProvider.models.join(', ')}`));
|
|
873
|
+
|
|
874
|
+
const selectedModel = await select({
|
|
875
|
+
message: 'Select model:',
|
|
876
|
+
options: selectedProvider.models.map((model) => ({
|
|
877
|
+
value: model,
|
|
878
|
+
label: model === selectedProvider.defaultModel ? `${model} (default)` : model,
|
|
879
|
+
})),
|
|
880
|
+
}) as string | symbol;
|
|
881
|
+
|
|
882
|
+
if (typeof selectedModel === 'symbol') {
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
modelName = selectedModel as string;
|
|
887
|
+
} else {
|
|
888
|
+
console.log(chalk.cyan(`Default model: ${modelName}`));
|
|
889
|
+
|
|
890
|
+
const confirmModel = (await import('@clack/prompts').then(m =>
|
|
891
|
+
m.text({
|
|
892
|
+
message: `Enter model name (press Enter to use default value ${modelName}):`,
|
|
893
|
+
defaultValue: modelName,
|
|
894
|
+
validate: (value: string | undefined) => {
|
|
895
|
+
if (!value || value.trim().length === 0) {
|
|
896
|
+
return 'Model name cannot be empty';
|
|
897
|
+
}
|
|
898
|
+
return undefined;
|
|
899
|
+
},
|
|
900
|
+
})
|
|
901
|
+
)) as string;
|
|
902
|
+
|
|
903
|
+
modelName = confirmModel.trim();
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
const apiKey = (await import('@clack/prompts').then(m =>
|
|
908
|
+
m.password({
|
|
909
|
+
message: `Enter ${selectedProvider.name} API Key:`,
|
|
910
|
+
validate: (value: string | undefined) => {
|
|
911
|
+
if (!value || value.trim().length === 0) {
|
|
912
|
+
return 'API Key cannot be empty';
|
|
913
|
+
}
|
|
914
|
+
return undefined;
|
|
915
|
+
},
|
|
916
|
+
})
|
|
917
|
+
)) as string;
|
|
918
|
+
|
|
919
|
+
// Update config
|
|
920
|
+
this.configManager.set('baseUrl', baseUrl);
|
|
921
|
+
this.configManager.set('apiKey', apiKey.trim());
|
|
922
|
+
this.configManager.set('modelName', modelName);
|
|
923
|
+
this.configManager.save('global');
|
|
924
|
+
|
|
925
|
+
console.log(chalk.green('\n✅ LLM configuration updated successfully!'));
|
|
926
|
+
console.log(chalk.cyan(` Provider: ${selectedProvider.name}`));
|
|
927
|
+
console.log(chalk.cyan(` Model: ${modelName}`));
|
|
928
|
+
console.log(chalk.cyan(` API URL: ${baseUrl}`));
|
|
929
|
+
|
|
930
|
+
// Clear conversation and notify config update
|
|
931
|
+
if (this.onClearCallback) {
|
|
932
|
+
this.onClearCallback();
|
|
933
|
+
}
|
|
934
|
+
if (this.onConfigUpdate) {
|
|
935
|
+
this.onConfigUpdate();
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
/**
|
|
940
|
+
* Configure VLM for local mode - Select provider and modelName (baseUrl from VLM_PROVIDERS)
|
|
941
|
+
*/
|
|
942
|
+
private async configureLocalVLM(): Promise<void> {
|
|
943
|
+
// Get current VLM config
|
|
944
|
+
const currentModel = this.configManager.get('guiSubagentModel');
|
|
945
|
+
const currentBaseUrl = this.configManager.get('guiSubagentBaseUrl');
|
|
946
|
+
|
|
947
|
+
console.log(chalk.cyan('\n📊 Current VLM Configuration:\n'));
|
|
948
|
+
console.log(` ${chalk.yellow('Model:')} ${currentModel || 'Not set'}`);
|
|
949
|
+
console.log(` ${chalk.yellow('Base URL:')} ${currentBaseUrl || 'Not set'}`);
|
|
950
|
+
console.log('');
|
|
951
|
+
|
|
952
|
+
// Step 1: Select VLM provider
|
|
953
|
+
const provider = await select({
|
|
954
|
+
message: 'Select VLM provider:',
|
|
955
|
+
options: VLM_PROVIDERS.map((p) => ({
|
|
956
|
+
value: p,
|
|
957
|
+
label: `${p.name} - ${p.defaultModel}`,
|
|
958
|
+
})),
|
|
959
|
+
}) as VLMProviderInfo | symbol;
|
|
960
|
+
|
|
961
|
+
// User cancelled
|
|
962
|
+
if (typeof provider === 'symbol') {
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
const selectedProvider = provider;
|
|
967
|
+
|
|
968
|
+
// Step 2: Select model from provider's models list
|
|
969
|
+
const model = await select({
|
|
970
|
+
message: 'Select VLM Model:',
|
|
971
|
+
options: selectedProvider.models.map((m) => ({
|
|
972
|
+
value: m,
|
|
973
|
+
label: m,
|
|
974
|
+
})),
|
|
975
|
+
}) as string | symbol;
|
|
976
|
+
|
|
977
|
+
// User cancelled
|
|
978
|
+
if (typeof model === 'symbol') {
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
// Step 3: Get API Key
|
|
983
|
+
const apiKey = (await text({
|
|
984
|
+
message: `Enter ${selectedProvider.name} API Key:`,
|
|
985
|
+
validate: (value: string | undefined) => {
|
|
986
|
+
if (!value || value.trim().length === 0) {
|
|
987
|
+
return 'API Key cannot be empty';
|
|
988
|
+
}
|
|
989
|
+
return undefined;
|
|
990
|
+
},
|
|
991
|
+
})) as string;
|
|
992
|
+
|
|
993
|
+
// Save configuration
|
|
994
|
+
this.configManager.set('guiSubagentModel', model);
|
|
995
|
+
this.configManager.set('guiSubagentBaseUrl', selectedProvider.baseUrl);
|
|
996
|
+
this.configManager.set('guiSubagentApiKey', apiKey);
|
|
997
|
+
this.configManager.save('global');
|
|
998
|
+
|
|
999
|
+
console.log(chalk.green('\n✅ VLM configuration updated successfully!'));
|
|
1000
|
+
console.log(chalk.cyan(` Provider: ${selectedProvider.name}`));
|
|
1001
|
+
console.log(chalk.cyan(` Model: ${model}`));
|
|
1002
|
+
console.log(chalk.cyan(` Base URL: ${selectedProvider.baseUrl}`));
|
|
1003
|
+
|
|
1004
|
+
// Notify config update
|
|
1005
|
+
if (this.onConfigUpdate) {
|
|
1006
|
+
this.onConfigUpdate();
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
private async handleMode(args: string[]): Promise<void> {
|
|
1011
|
+
const modes = Object.values(ExecutionMode);
|
|
1012
|
+
const currentMode =
|
|
1013
|
+
this.configManager.getApprovalMode() || this.configManager.getExecutionMode();
|
|
1014
|
+
|
|
1015
|
+
if (args.length > 0) {
|
|
1016
|
+
const newMode = args[0].toLowerCase();
|
|
1017
|
+
if (modes.includes(newMode as ExecutionMode)) {
|
|
1018
|
+
this.configManager.setApprovalMode(newMode as ExecutionMode);
|
|
1019
|
+
this.configManager.save('global');
|
|
1020
|
+
console.log(chalk.green(`✅ Approval mode changed to: ${newMode}`));
|
|
1021
|
+
} else {
|
|
1022
|
+
console.log(chalk.red(`❌ Invalid mode: ${newMode}`));
|
|
1023
|
+
console.log(chalk.gray(`Available modes: ${modes.join(', ')}`));
|
|
1024
|
+
}
|
|
1025
|
+
} else {
|
|
1026
|
+
console.log(chalk.cyan('\n🎯 Approval Modes:\n'));
|
|
1027
|
+
console.log(` Current: ${chalk.green(currentMode)}\n`);
|
|
1028
|
+
|
|
1029
|
+
const descriptions = [
|
|
1030
|
+
{ mode: 'yolo', desc: 'Execute commands without confirmation' },
|
|
1031
|
+
{ mode: 'accept_edits', desc: 'Accept all edits automatically' },
|
|
1032
|
+
{ mode: 'plan', desc: 'Plan before executing' },
|
|
1033
|
+
{ mode: 'default', desc: 'Safe execution with confirmations' },
|
|
1034
|
+
{ mode: 'smart', desc: 'Smart approval with intelligent security checks' },
|
|
1035
|
+
];
|
|
1036
|
+
|
|
1037
|
+
descriptions.forEach(({ mode, desc }) => {
|
|
1038
|
+
const current = mode === currentMode ? chalk.green(' [current]') : '';
|
|
1039
|
+
console.log(` ${chalk.yellow(mode)}${current}`);
|
|
1040
|
+
console.log(` ${chalk.gray(desc)}`);
|
|
1041
|
+
});
|
|
1042
|
+
|
|
1043
|
+
console.log();
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
private async handleThink(args: string[]): Promise<void> {
|
|
1048
|
+
const thinkingConfig = this.configManager.getThinkingConfig();
|
|
1049
|
+
|
|
1050
|
+
if (args.length > 0) {
|
|
1051
|
+
const action = args[0].toLowerCase();
|
|
1052
|
+
|
|
1053
|
+
if (action === 'on' || action === 'true' || action === '1') {
|
|
1054
|
+
thinkingConfig.enabled = true;
|
|
1055
|
+
this.configManager.setThinkingConfig(thinkingConfig);
|
|
1056
|
+
this.configManager.save('global');
|
|
1057
|
+
console.log(chalk.green('✅ Thinking mode enabled'));
|
|
1058
|
+
} else if (action === 'off' || action === 'false' || action === '0') {
|
|
1059
|
+
thinkingConfig.enabled = false;
|
|
1060
|
+
this.configManager.setThinkingConfig(thinkingConfig);
|
|
1061
|
+
this.configManager.save('global');
|
|
1062
|
+
console.log(chalk.green('✅ Thinking mode disabled'));
|
|
1063
|
+
} else if (action === 'display' && args[1]) {
|
|
1064
|
+
const displayMode = args[1].toLowerCase();
|
|
1065
|
+
const validModes = ['full', 'compact', 'indicator'];
|
|
1066
|
+
|
|
1067
|
+
if (validModes.includes(displayMode)) {
|
|
1068
|
+
thinkingConfig.displayMode = displayMode as 'full' | 'compact' | 'indicator';
|
|
1069
|
+
thinkingConfig.enabled = true;
|
|
1070
|
+
this.configManager.setThinkingConfig(thinkingConfig);
|
|
1071
|
+
this.configManager.save('global');
|
|
1072
|
+
console.log(chalk.green(`✅ Thinking display mode set to: ${displayMode}`));
|
|
1073
|
+
} else {
|
|
1074
|
+
console.log(chalk.red(`❌ Invalid display mode: ${displayMode}`));
|
|
1075
|
+
console.log(chalk.gray(`Valid modes: ${validModes.join(', ')}`));
|
|
1076
|
+
}
|
|
1077
|
+
} else {
|
|
1078
|
+
console.log(chalk.red(`❌ Invalid action: ${action}`));
|
|
1079
|
+
console.log(chalk.gray('Usage: /think [on|off|display <mode>]'));
|
|
1080
|
+
}
|
|
1081
|
+
} else {
|
|
1082
|
+
console.log(chalk.cyan('\n🧠 Thinking Mode:\n'));
|
|
1083
|
+
console.log(
|
|
1084
|
+
` Status: ${thinkingConfig.enabled ? chalk.green('Enabled') : chalk.red('Disabled')}`
|
|
1085
|
+
);
|
|
1086
|
+
console.log(` Mode: ${chalk.yellow(thinkingConfig.mode)}`);
|
|
1087
|
+
console.log(` Display: ${chalk.yellow(thinkingConfig.displayMode)}\n`);
|
|
1088
|
+
|
|
1089
|
+
console.log(chalk.gray('Usage:'));
|
|
1090
|
+
console.log(chalk.gray(' /think on - Enable thinking mode'));
|
|
1091
|
+
console.log(chalk.gray(' /think off - Disable thinking mode'));
|
|
1092
|
+
console.log(chalk.gray(' /think display full - Show full thinking process'));
|
|
1093
|
+
console.log(chalk.gray(' /think display compact - Show compact thinking (500 chars)'));
|
|
1094
|
+
console.log(chalk.gray(' /think display indicator - Show only indicator'));
|
|
1095
|
+
console.log();
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
private async handleAgents(args: string[]): Promise<void> {
|
|
1100
|
+
const action = args[0] || 'list';
|
|
1101
|
+
|
|
1102
|
+
switch (action) {
|
|
1103
|
+
case 'list':
|
|
1104
|
+
await this.listAgents();
|
|
1105
|
+
break;
|
|
1106
|
+
case 'online':
|
|
1107
|
+
logger.warn('Online marketplace not implemented yet', 'Check back later for updates');
|
|
1108
|
+
break;
|
|
1109
|
+
case 'install':
|
|
1110
|
+
logger.warn(
|
|
1111
|
+
'Agent installation wizard not implemented yet',
|
|
1112
|
+
'Use /agents install in interactive mode'
|
|
1113
|
+
);
|
|
1114
|
+
break;
|
|
1115
|
+
case 'remove':
|
|
1116
|
+
logger.warn('Agent removal not implemented yet', 'Use /agents remove in interactive mode');
|
|
1117
|
+
break;
|
|
1118
|
+
default:
|
|
1119
|
+
logger.warn(
|
|
1120
|
+
`Unknown agents action: ${action}`,
|
|
1121
|
+
'Use /agents list to see available actions'
|
|
1122
|
+
);
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
private async listAgents(): Promise<void> {
|
|
1127
|
+
const agents = this.agentManager.getAllAgents();
|
|
1128
|
+
|
|
1129
|
+
if (agents.length === 0) {
|
|
1130
|
+
logger.warn('No agents configured', 'Use /agents install to add agents');
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
logger.section('Available Agents');
|
|
1135
|
+
|
|
1136
|
+
agents.forEach((agent: AgentConfig) => {
|
|
1137
|
+
const color = agent.color || '#FFFFFF';
|
|
1138
|
+
logger.info(` ${chalk.hex(color)(agent.name || agent.agentType)}`);
|
|
1139
|
+
logger.info(` Type: ${agent.agentType}`);
|
|
1140
|
+
logger.info(` ${agent.whenToUse}`);
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
private async handleMcp(args: string[]): Promise<void> {
|
|
1145
|
+
const action = args[0] || 'list';
|
|
1146
|
+
|
|
1147
|
+
switch (action) {
|
|
1148
|
+
case 'list':
|
|
1149
|
+
await this.listMcpServers();
|
|
1150
|
+
break;
|
|
1151
|
+
case 'add':
|
|
1152
|
+
if (args[1]) {
|
|
1153
|
+
// Non-interactive mode: use command line arguments
|
|
1154
|
+
await this.addMcpServerInteractive(args[1]);
|
|
1155
|
+
} else {
|
|
1156
|
+
// Interactive mode
|
|
1157
|
+
await this.addMcpServerInteractive();
|
|
1158
|
+
}
|
|
1159
|
+
break;
|
|
1160
|
+
case 'remove':
|
|
1161
|
+
if (args[1]) {
|
|
1162
|
+
// Non-interactive mode
|
|
1163
|
+
await this.removeMcpServer(args[1]);
|
|
1164
|
+
} else {
|
|
1165
|
+
// Interactive mode
|
|
1166
|
+
await this.removeMcpServerInteractive();
|
|
1167
|
+
}
|
|
1168
|
+
break;
|
|
1169
|
+
case 'refresh':
|
|
1170
|
+
await this.refreshMcpServers();
|
|
1171
|
+
break;
|
|
1172
|
+
default:
|
|
1173
|
+
logger.warn(`Unknown MCP action: ${action}`, 'Use /mcp list to see available actions');
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
private async listMcpServers(): Promise<void> {
|
|
1178
|
+
const serverConfigs = this.mcpManager.getAllServerConfigs();
|
|
1179
|
+
|
|
1180
|
+
if (serverConfigs.length === 0) {
|
|
1181
|
+
logger.section('MCP Servers');
|
|
1182
|
+
logger.warn('No MCP servers configured');
|
|
1183
|
+
logger.info('Use /mcp add to add a new MCP server');
|
|
1184
|
+
return;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
logger.section('MCP Servers');
|
|
1188
|
+
|
|
1189
|
+
serverConfigs.forEach(
|
|
1190
|
+
({ name: serverName, config: serverConfig }: { name: string; config: any }) => {
|
|
1191
|
+
const server = this.mcpManager.getServer(serverName);
|
|
1192
|
+
const isConnected = server?.isServerConnected() || false;
|
|
1193
|
+
const status = isConnected ? chalk.green('✓ Connected') : chalk.red('✗ Disconnected');
|
|
1194
|
+
const tools = server?.getToolNames() || [];
|
|
1195
|
+
const transport = serverConfig?.transport || serverConfig?.type || 'unknown';
|
|
1196
|
+
const command = serverConfig?.command
|
|
1197
|
+
? `${serverConfig.command} ${(serverConfig.args || []).join(' ')}`
|
|
1198
|
+
: serverConfig?.url || 'N/A';
|
|
1199
|
+
|
|
1200
|
+
console.log('');
|
|
1201
|
+
console.log(` ${chalk.cyan(serverName)} ${status}`);
|
|
1202
|
+
console.log(` Transport: ${transport}`);
|
|
1203
|
+
console.log(` Command: ${command}`);
|
|
1204
|
+
console.log(
|
|
1205
|
+
` Tools: ${isConnected ? tools.length : 'N/A'} (${isConnected ? tools.join(', ') : 'wait for connection'})`
|
|
1206
|
+
);
|
|
1207
|
+
}
|
|
1208
|
+
);
|
|
1209
|
+
|
|
1210
|
+
console.log('');
|
|
1211
|
+
logger.info(`Total: ${serverConfigs.length} server(s)`);
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
private async addMcpServerInteractive(serverName?: string): Promise<void> {
|
|
1215
|
+
const name = (await text({
|
|
1216
|
+
message: 'Enter MCP server name:',
|
|
1217
|
+
defaultValue: serverName,
|
|
1218
|
+
validate: (value: string | undefined) => {
|
|
1219
|
+
if (!value || !value.trim()) {
|
|
1220
|
+
return 'Server name is required';
|
|
1221
|
+
}
|
|
1222
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(value)) {
|
|
1223
|
+
return 'Server name must contain only alphanumeric characters, hyphens, and underscores';
|
|
1224
|
+
}
|
|
1225
|
+
const servers = this.mcpManager.getAllServers();
|
|
1226
|
+
if (servers.some((s: MCPServer) => (s as any).config?.name === value)) {
|
|
1227
|
+
return 'Server with this name already exists';
|
|
1228
|
+
}
|
|
1229
|
+
return undefined;
|
|
1230
|
+
},
|
|
1231
|
+
})) as string;
|
|
1232
|
+
|
|
1233
|
+
const transport = await select({
|
|
1234
|
+
message: 'Select transport type:',
|
|
1235
|
+
options: [
|
|
1236
|
+
{ value: 'stdio', label: 'Stdio (stdin/stdout)' },
|
|
1237
|
+
{ value: 'sse', label: 'HTTP/SSE' },
|
|
1238
|
+
{ value: 'http', label: 'HTTP (POST)' },
|
|
1239
|
+
],
|
|
1240
|
+
}) as string | symbol;
|
|
1241
|
+
|
|
1242
|
+
if (typeof transport === 'symbol') {
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
let command = '';
|
|
1247
|
+
let serverArgs: string[] = [];
|
|
1248
|
+
let url = '';
|
|
1249
|
+
let authToken = '';
|
|
1250
|
+
let headers: Record<string, string> | string | undefined;
|
|
1251
|
+
|
|
1252
|
+
if (transport === 'stdio') {
|
|
1253
|
+
command = (await text({
|
|
1254
|
+
message: 'Enter command (for stdio transport):',
|
|
1255
|
+
validate: (value: string | undefined) =>
|
|
1256
|
+
value && value.trim() ? undefined : 'Command is required',
|
|
1257
|
+
})) as string;
|
|
1258
|
+
|
|
1259
|
+
const argsInput = (await text({
|
|
1260
|
+
message: 'Enter arguments (comma-separated, for stdio transport):',
|
|
1261
|
+
defaultValue: '',
|
|
1262
|
+
})) as string;
|
|
1263
|
+
|
|
1264
|
+
if (argsInput.trim()) {
|
|
1265
|
+
serverArgs = argsInput.split(',').map((a: string) => a.trim());
|
|
1266
|
+
}
|
|
1267
|
+
} else {
|
|
1268
|
+
url = (await text({
|
|
1269
|
+
message: 'Enter server URL (for HTTP/SSE/HTTP transport):',
|
|
1270
|
+
validate: (value: string | undefined) => {
|
|
1271
|
+
if (!value || !value.trim()) {
|
|
1272
|
+
return 'URL is required';
|
|
1273
|
+
}
|
|
1274
|
+
try {
|
|
1275
|
+
new URL(value);
|
|
1276
|
+
return undefined;
|
|
1277
|
+
} catch {
|
|
1278
|
+
return 'Invalid URL format (e.g., https://example.com)';
|
|
1279
|
+
}
|
|
1280
|
+
},
|
|
1281
|
+
})) as string;
|
|
1282
|
+
|
|
1283
|
+
authToken = (await text({
|
|
1284
|
+
message: 'Enter authentication token (optional):',
|
|
1285
|
+
defaultValue: '',
|
|
1286
|
+
})) as string;
|
|
1287
|
+
|
|
1288
|
+
const headersInput = (await text({
|
|
1289
|
+
message:
|
|
1290
|
+
'Enter custom headers as JSON (optional, e.g., {"Authorization": "Bearer token"}):',
|
|
1291
|
+
defaultValue: '',
|
|
1292
|
+
})) as string;
|
|
1293
|
+
|
|
1294
|
+
if (headersInput.trim()) {
|
|
1295
|
+
try {
|
|
1296
|
+
headers = JSON.parse(headersInput);
|
|
1297
|
+
} catch {
|
|
1298
|
+
headers = undefined;
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
const config: any = {
|
|
1304
|
+
transport: transport as 'stdio' | 'sse' | 'http',
|
|
1305
|
+
};
|
|
1306
|
+
|
|
1307
|
+
if (transport === 'stdio') {
|
|
1308
|
+
config.command = command;
|
|
1309
|
+
if (serverArgs && serverArgs.length > 0) {
|
|
1310
|
+
config.args = serverArgs;
|
|
1311
|
+
}
|
|
1312
|
+
} else {
|
|
1313
|
+
config.url = url;
|
|
1314
|
+
|
|
1315
|
+
// Handle user input that mistakenly puts Bearer token in headers field
|
|
1316
|
+
// Detect pattern: headers looks like "Bearer xxx.yyy.zzz" (JWT token)
|
|
1317
|
+
let resolvedAuthToken = authToken;
|
|
1318
|
+
let resolvedHeaders = headers;
|
|
1319
|
+
|
|
1320
|
+
if (headers && typeof headers === 'string' && !authToken) {
|
|
1321
|
+
const trimmedHeaders = headers.trim();
|
|
1322
|
+
if (trimmedHeaders.startsWith('Bearer ') && trimmedHeaders.split('.').length === 3) {
|
|
1323
|
+
// User mistakenly put token in headers field - extract it
|
|
1324
|
+
resolvedAuthToken = trimmedHeaders;
|
|
1325
|
+
resolvedHeaders = undefined;
|
|
1326
|
+
console.log('[MCP] Note: Detected Bearer token in headers field, moved to authToken');
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
if (resolvedAuthToken) {
|
|
1331
|
+
config.authToken = resolvedAuthToken;
|
|
1332
|
+
}
|
|
1333
|
+
if (resolvedHeaders) {
|
|
1334
|
+
config.headers = resolvedHeaders;
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
try {
|
|
1339
|
+
this.configManager.addMcpServer(name, config);
|
|
1340
|
+
this.configManager.save('global');
|
|
1341
|
+
|
|
1342
|
+
this.mcpManager.registerServer(name, config);
|
|
1343
|
+
|
|
1344
|
+
try {
|
|
1345
|
+
await this.mcpManager.connectServer(name);
|
|
1346
|
+
} catch (error: any) {
|
|
1347
|
+
this.mcpManager.disconnectServer(name);
|
|
1348
|
+
this.configManager.removeMcpServer(name);
|
|
1349
|
+
this.configManager.save('global');
|
|
1350
|
+
throw new Error(`Connection failed: ${error.message}`);
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
// Register MCP tools with simple names
|
|
1354
|
+
const allMcpTools = this.mcpManager.getAllTools();
|
|
1355
|
+
const toolRegistry = getToolRegistry();
|
|
1356
|
+
toolRegistry.registerMCPTools(allMcpTools);
|
|
1357
|
+
|
|
1358
|
+
// Update system prompt to include new MCP tools
|
|
1359
|
+
if (this.onSystemPromptUpdate) {
|
|
1360
|
+
await this.onSystemPromptUpdate();
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
console.log(chalk.green(`✅ MCP server '${name}' added and connected successfully`));
|
|
1364
|
+
} catch (error: any) {
|
|
1365
|
+
console.log(chalk.red(`❌ Failed to add MCP server: ${error.message}`));
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
private async removeMcpServerInteractive(): Promise<void> {
|
|
1370
|
+
const servers = this.mcpManager.getAllServers();
|
|
1371
|
+
|
|
1372
|
+
if (servers.length === 0) {
|
|
1373
|
+
logger.warn('No MCP servers configured', 'Use /mcp add to add servers');
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
const serverOptions = servers.map((s: MCPServer) => {
|
|
1378
|
+
const tools = s.getToolNames();
|
|
1379
|
+
const status = s.isServerConnected() ? '✓' : '✗';
|
|
1380
|
+
return {
|
|
1381
|
+
value: (s as any).config?.name,
|
|
1382
|
+
label: `${status} ${(s as any).config?.name || 'unknown'} (${tools.length} tools)`,
|
|
1383
|
+
};
|
|
1384
|
+
});
|
|
1385
|
+
|
|
1386
|
+
const serverName = (await select({
|
|
1387
|
+
message: 'Select MCP server to remove:',
|
|
1388
|
+
options: serverOptions,
|
|
1389
|
+
})) as string | symbol;
|
|
1390
|
+
|
|
1391
|
+
if (typeof serverName === 'symbol') {
|
|
1392
|
+
return;
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
await this.removeMcpServer(serverName);
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
private async removeMcpServer(serverName: string): Promise<void> {
|
|
1399
|
+
try {
|
|
1400
|
+
// Disconnect
|
|
1401
|
+
this.mcpManager.disconnectServer(serverName);
|
|
1402
|
+
|
|
1403
|
+
// Unregister MCP tools for this server
|
|
1404
|
+
const toolRegistry = getToolRegistry();
|
|
1405
|
+
toolRegistry.unregisterMCPTools(serverName);
|
|
1406
|
+
|
|
1407
|
+
// Remove from config
|
|
1408
|
+
this.configManager.removeMcpServer(serverName);
|
|
1409
|
+
this.configManager.save('global');
|
|
1410
|
+
|
|
1411
|
+
// Update system prompt to reflect removed MCP tools
|
|
1412
|
+
if (this.onSystemPromptUpdate) {
|
|
1413
|
+
await this.onSystemPromptUpdate();
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
console.log(chalk.green(`✅ MCP server '${serverName}' removed successfully`));
|
|
1417
|
+
} catch (error: any) {
|
|
1418
|
+
console.log(chalk.red(`❌ Failed to remove MCP server: ${error.message}`));
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
private async refreshMcpServers(): Promise<void> {
|
|
1423
|
+
const spinner = ora({ text: 'Refreshing MCP servers...', interval: 200 }).start();
|
|
1424
|
+
|
|
1425
|
+
try {
|
|
1426
|
+
// Disconnect all existing connections
|
|
1427
|
+
this.mcpManager.disconnectAllServers();
|
|
1428
|
+
|
|
1429
|
+
// Reconnect all servers
|
|
1430
|
+
await this.mcpManager.connectAllServers();
|
|
1431
|
+
|
|
1432
|
+
spinner.succeed('MCP servers refreshed successfully');
|
|
1433
|
+
|
|
1434
|
+
// Show current server status
|
|
1435
|
+
await this.listMcpServers();
|
|
1436
|
+
} catch (error: any) {
|
|
1437
|
+
spinner.fail(`Failed to refresh MCP servers: ${error.message}`);
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
private async handleMemory(args: string[]): Promise<void> {
|
|
1442
|
+
const action = args[0] || 'show';
|
|
1443
|
+
|
|
1444
|
+
// Load memory files before showing
|
|
1445
|
+
try {
|
|
1446
|
+
await this.memoryManager.loadMemory();
|
|
1447
|
+
} catch (error) {
|
|
1448
|
+
logger.error(
|
|
1449
|
+
'Failed to load memory files',
|
|
1450
|
+
error instanceof Error ? error.message : String(error)
|
|
1451
|
+
);
|
|
1452
|
+
return;
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
switch (action) {
|
|
1456
|
+
case 'show':
|
|
1457
|
+
await this.showMemory();
|
|
1458
|
+
break;
|
|
1459
|
+
case 'clear':
|
|
1460
|
+
await this.clearMemory(args[1]);
|
|
1461
|
+
break;
|
|
1462
|
+
default:
|
|
1463
|
+
logger.warn(
|
|
1464
|
+
`Unknown memory action: ${action}`,
|
|
1465
|
+
'Use /memory show to see available actions'
|
|
1466
|
+
);
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
private async clearMemory(target?: string): Promise<void> {
|
|
1471
|
+
const memoryFiles = this.memoryManager.getMemoryFiles();
|
|
1472
|
+
|
|
1473
|
+
// Handle different clear targets
|
|
1474
|
+
if (!target || target === '.' || target === 'current') {
|
|
1475
|
+
// Clear current project's memory
|
|
1476
|
+
const currentProjectMemory = memoryFiles.find((m: MemoryFile) => m.level === 'project');
|
|
1477
|
+
if (currentProjectMemory) {
|
|
1478
|
+
await fs.unlink(currentProjectMemory.path);
|
|
1479
|
+
logger.success('Project memory cleared');
|
|
1480
|
+
logger.info('Use /init to initialize if needed');
|
|
1481
|
+
} else {
|
|
1482
|
+
logger.warn('No project memory found for current directory');
|
|
1483
|
+
}
|
|
1484
|
+
return;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
if (target === 'all') {
|
|
1488
|
+
// Clear all memories including global
|
|
1489
|
+
let cleared = 0;
|
|
1490
|
+
for (const file of memoryFiles) {
|
|
1491
|
+
await fs.unlink(file.path);
|
|
1492
|
+
cleared++;
|
|
1493
|
+
}
|
|
1494
|
+
logger.success(`Cleared ${cleared} memory file(s)`);
|
|
1495
|
+
|
|
1496
|
+
// Recreate global memory
|
|
1497
|
+
await this.memoryManager.saveMemory(
|
|
1498
|
+
'# Global Context\n\nGlobal preferences and settings will be added here.',
|
|
1499
|
+
'global'
|
|
1500
|
+
);
|
|
1501
|
+
logger.info('Recreated global memory');
|
|
1502
|
+
logger.info('Use /init to initialize project memory if needed');
|
|
1503
|
+
return;
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
if (target === 'global') {
|
|
1507
|
+
// Clear global memory
|
|
1508
|
+
const globalMemory = memoryFiles.find((m: MemoryFile) => m.level === 'global');
|
|
1509
|
+
if (globalMemory) {
|
|
1510
|
+
await fs.unlink(globalMemory.path);
|
|
1511
|
+
logger.success('Global memory cleared');
|
|
1512
|
+
|
|
1513
|
+
// Recreate global memory
|
|
1514
|
+
await this.memoryManager.saveMemory(
|
|
1515
|
+
'# Global Context\n\nGlobal preferences and settings will be added here.',
|
|
1516
|
+
'global'
|
|
1517
|
+
);
|
|
1518
|
+
logger.info('Recreated with default content');
|
|
1519
|
+
} else {
|
|
1520
|
+
logger.warn('No global memory found');
|
|
1521
|
+
}
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
// Clear specific file by filename or path
|
|
1526
|
+
const targetMemory = memoryFiles.find(
|
|
1527
|
+
(m: MemoryFile) => path.basename(m.path) === target || m.path === target
|
|
1528
|
+
);
|
|
1529
|
+
|
|
1530
|
+
if (targetMemory) {
|
|
1531
|
+
try {
|
|
1532
|
+
await fs.unlink(targetMemory.path);
|
|
1533
|
+
const levelLabel = targetMemory.level === 'global' ? 'Global' : 'Project';
|
|
1534
|
+
logger.success(`${levelLabel} memory cleared: ${path.basename(targetMemory.path)}`);
|
|
1535
|
+
|
|
1536
|
+
// Recreate global memory, not project memory
|
|
1537
|
+
if (targetMemory.level === 'global') {
|
|
1538
|
+
await this.memoryManager.saveMemory(
|
|
1539
|
+
'# Global Context\n\nGlobal preferences and settings will be added here.',
|
|
1540
|
+
'global'
|
|
1541
|
+
);
|
|
1542
|
+
logger.info('Recreated with default content');
|
|
1543
|
+
} else {
|
|
1544
|
+
logger.info('Use /init to initialize if needed');
|
|
1545
|
+
}
|
|
1546
|
+
} catch (error) {
|
|
1547
|
+
logger.error(
|
|
1548
|
+
'Failed to clear memory',
|
|
1549
|
+
error instanceof Error ? error.message : String(error)
|
|
1550
|
+
);
|
|
1551
|
+
}
|
|
1552
|
+
} else {
|
|
1553
|
+
logger.warn(`Memory file not found: ${target}`, 'Use /memory show to see available files');
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
private async showMemory(): Promise<void> {
|
|
1558
|
+
const memoryFiles = this.memoryManager.getMemoryFiles();
|
|
1559
|
+
|
|
1560
|
+
if (memoryFiles.length === 0) {
|
|
1561
|
+
logger.warn('No memory files loaded', 'Use /init to initialize project context');
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
const memoriesDir = this.memoryManager.getMemoriesDir();
|
|
1566
|
+
logger.section('Memory Files');
|
|
1567
|
+
logger.info(`Directory: ${memoriesDir}`);
|
|
1568
|
+
console.log('');
|
|
1569
|
+
|
|
1570
|
+
memoryFiles.forEach((file: MemoryFile) => {
|
|
1571
|
+
const level =
|
|
1572
|
+
file.level === 'global'
|
|
1573
|
+
? chalk.blue('[global]')
|
|
1574
|
+
: file.level === 'project'
|
|
1575
|
+
? chalk.green('[project]')
|
|
1576
|
+
: chalk.yellow('[subdirectory]');
|
|
1577
|
+
logger.info(` ${level} ${path.basename(file.path)}`);
|
|
1578
|
+
});
|
|
1579
|
+
|
|
1580
|
+
console.log('');
|
|
1581
|
+
// logger.info('Usage: /memory clear [global|current|all|<filename>]');
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
private async addMemory(): Promise<void> {
|
|
1585
|
+
const entry = (await text({
|
|
1586
|
+
message: 'Enter memory entry (opens editor):',
|
|
1587
|
+
})) as string;
|
|
1588
|
+
|
|
1589
|
+
if (entry && entry.trim()) {
|
|
1590
|
+
await this.memoryManager.addMemoryEntry(entry.trim());
|
|
1591
|
+
console.log(chalk.green('✅ Memory entry added'));
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
private async refreshMemory(): Promise<void> {
|
|
1596
|
+
const spinner = ora({ text: 'Refreshing memory...', interval: 200 }).start();
|
|
1597
|
+
|
|
1598
|
+
try {
|
|
1599
|
+
await this.memoryManager.loadMemory();
|
|
1600
|
+
spinner.succeed('Memory refreshed successfully');
|
|
1601
|
+
} catch (error: any) {
|
|
1602
|
+
spinner.fail(`Failed to refresh memory: ${error.message}`);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
private async handleRestore(args: string[]): Promise<void> {
|
|
1607
|
+
if (!this.checkpointManager.isEnabled()) {
|
|
1608
|
+
logger.warn('Checkpointing is not enabled', 'Enable it with /mode or in settings');
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
const checkpoints = this.checkpointManager.listCheckpoints();
|
|
1613
|
+
|
|
1614
|
+
if (checkpoints.length === 0) {
|
|
1615
|
+
logger.warn('No checkpoints available', 'Create checkpoints during your session');
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
if (args.length > 0) {
|
|
1620
|
+
const checkpointId = args[0];
|
|
1621
|
+
try {
|
|
1622
|
+
await this.checkpointManager.restoreCheckpoint(checkpointId);
|
|
1623
|
+
logger.success(`Checkpoint ${checkpointId} restored successfully!`);
|
|
1624
|
+
} catch (error: any) {
|
|
1625
|
+
logger.error(error.message, 'Check if checkpoint ID is valid');
|
|
1626
|
+
}
|
|
1627
|
+
} else {
|
|
1628
|
+
const checkpointOptions = checkpoints.map((cp: Checkpoint) => ({
|
|
1629
|
+
value: cp.id,
|
|
1630
|
+
label: `${new Date(cp.timestamp).toLocaleString()} - ${cp.description}`,
|
|
1631
|
+
}));
|
|
1632
|
+
|
|
1633
|
+
const checkpointId = await select({
|
|
1634
|
+
message: 'Select checkpoint to restore:',
|
|
1635
|
+
options: checkpointOptions,
|
|
1636
|
+
}) as string | symbol;
|
|
1637
|
+
|
|
1638
|
+
if (typeof checkpointId === 'symbol') {
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
try {
|
|
1643
|
+
await this.checkpointManager.restoreCheckpoint(checkpointId);
|
|
1644
|
+
logger.success(`Checkpoint ${checkpointId} restored successfully!`);
|
|
1645
|
+
} catch (error: any) {
|
|
1646
|
+
logger.error(error.message, 'Check if checkpoint ID is valid');
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
private async handleTools(): Promise<void> {
|
|
1652
|
+
const toolRegistry = getToolRegistry();
|
|
1653
|
+
const tools = toolRegistry.getAll();
|
|
1654
|
+
|
|
1655
|
+
logger.section('Available Tools');
|
|
1656
|
+
|
|
1657
|
+
tools.forEach((tool) => {
|
|
1658
|
+
logger.info(` ${tool.name}`);
|
|
1659
|
+
logger.info(` ${tool.description}`);
|
|
1660
|
+
});
|
|
1661
|
+
|
|
1662
|
+
console.log('');
|
|
1663
|
+
const currentSetting = this.configManager.get('showToolDetails') ? 'verbose' : 'simple';
|
|
1664
|
+
logger.info(`Current tool display mode: ${currentSetting}`);
|
|
1665
|
+
logger.info('Use /tools verbose to switch to verbose mode');
|
|
1666
|
+
logger.info('Use /tools simple to switch to simple mode');
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
private async handleToolsVerbose(args: string[]): Promise<void> {
|
|
1670
|
+
if (args.length === 0) {
|
|
1671
|
+
const currentSetting = this.configManager.get('showToolDetails') ? 'verbose' : 'simple';
|
|
1672
|
+
logger.info(`Current tool display mode: ${currentSetting}`);
|
|
1673
|
+
return;
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
const mode = args[0].toLowerCase();
|
|
1677
|
+
|
|
1678
|
+
if (mode === 'verbose' || mode === 'detail' || mode === 'true' || mode === 'on') {
|
|
1679
|
+
this.configManager.set('showToolDetails', true);
|
|
1680
|
+
this.configManager.save('global');
|
|
1681
|
+
logger.success(
|
|
1682
|
+
'Tool display mode switched to verbose mode',
|
|
1683
|
+
'Will show complete tool call information'
|
|
1684
|
+
);
|
|
1685
|
+
} else if (mode === 'simple' || mode === 'concise' || mode === 'false' || mode === 'off') {
|
|
1686
|
+
this.configManager.set('showToolDetails', false);
|
|
1687
|
+
this.configManager.save('global');
|
|
1688
|
+
logger.success(
|
|
1689
|
+
'Tool display mode switched to simple mode',
|
|
1690
|
+
'Only show tool execution status'
|
|
1691
|
+
);
|
|
1692
|
+
} else {
|
|
1693
|
+
logger.warn('Invalid mode', 'Use verbose or simple');
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
private async handleStats(): Promise<void> {
|
|
1698
|
+
logger.section('Session Statistics');
|
|
1699
|
+
const authConfig = this.configManager.getAuthConfig();
|
|
1700
|
+
logger.info(` Base URL: ${authConfig.baseUrl}`);
|
|
1701
|
+
logger.info(` Execution Mode: ${this.configManager.getExecutionMode()}`);
|
|
1702
|
+
logger.info(` Language: ${this.configManager.getLanguage()}`);
|
|
1703
|
+
logger.info(` Checkpointing: ${this.checkpointManager.isEnabled() ? 'Enabled' : 'Disabled'}`);
|
|
1704
|
+
logger.info(` MCP Servers: ${this.mcpManager.getAllServers().length}`);
|
|
1705
|
+
logger.info(` Agents: ${this.agentManager.getAllAgents().length}`);
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
private async handleTheme(): Promise<void> {
|
|
1709
|
+
logger.warn('Theme switching not implemented yet', 'Check back later for updates');
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
private async handleLanguage(): Promise<void> {
|
|
1713
|
+
const language = (await select({
|
|
1714
|
+
message: 'Select language:',
|
|
1715
|
+
options: [
|
|
1716
|
+
{ value: 'zh', label: 'Chinese' },
|
|
1717
|
+
{ value: 'en', label: 'English' },
|
|
1718
|
+
],
|
|
1719
|
+
})) as 'zh' | 'en' | symbol;
|
|
1720
|
+
|
|
1721
|
+
if (typeof language === 'symbol') {
|
|
1722
|
+
return;
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
this.configManager.setLanguage(language);
|
|
1726
|
+
logger.success(
|
|
1727
|
+
`Language changed to: ${language === 'zh' ? 'Chinese' : 'English'}`,
|
|
1728
|
+
'Restart CLI to apply changes'
|
|
1729
|
+
);
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
private async handleAbout(): Promise<void> {
|
|
1733
|
+
logger.section('xAgent CLI');
|
|
1734
|
+
logger.info('Version: 1.0.0');
|
|
1735
|
+
logger.info('A powerful AI-powered command-line assistant');
|
|
1736
|
+
logger.blank();
|
|
1737
|
+
logger.link('Documentation', 'https://platform.xagent.cn/');
|
|
1738
|
+
logger.link('GitHub', 'https://github.com/xagent-ai/xagent-cli');
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
private async handleUpdate(): Promise<void> {
|
|
1742
|
+
const separator = icons.separator.repeat(Math.min(40, process.stdout.columns || 80));
|
|
1743
|
+
|
|
1744
|
+
console.log('');
|
|
1745
|
+
console.log(colors.primaryBright(`${icons.rocket} Update Check`));
|
|
1746
|
+
console.log(colors.border(separator));
|
|
1747
|
+
console.log('');
|
|
1748
|
+
|
|
1749
|
+
try {
|
|
1750
|
+
const { getUpdateManager } = await import('./update.js');
|
|
1751
|
+
const updateManager = getUpdateManager();
|
|
1752
|
+
const versionInfo = await updateManager.checkForUpdates();
|
|
1753
|
+
|
|
1754
|
+
console.log(` ${icons.info} ${colors.textMuted('Current version:')} ${colors.primaryBright(versionInfo.currentVersion)}`);
|
|
1755
|
+
console.log(` ${icons.code} ${colors.textMuted('Latest version:')} ${colors.primaryBright(versionInfo.latestVersion)}`);
|
|
1756
|
+
console.log('');
|
|
1757
|
+
|
|
1758
|
+
if (versionInfo.updateAvailable) {
|
|
1759
|
+
console.log(colors.success(` 📦 A new version is available!`));
|
|
1760
|
+
console.log('');
|
|
1761
|
+
|
|
1762
|
+
if (versionInfo.releaseNotes) {
|
|
1763
|
+
console.log(colors.textMuted(' Release Notes:'));
|
|
1764
|
+
console.log(colors.textDim(` ${versionInfo.releaseNotes}`));
|
|
1765
|
+
console.log('');
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
const shouldUpdate = await confirm({
|
|
1769
|
+
message: 'Do you want to update now?',
|
|
1770
|
+
});
|
|
1771
|
+
|
|
1772
|
+
if (shouldUpdate === true) {
|
|
1773
|
+
console.log('');
|
|
1774
|
+
await updateManager.autoUpdate();
|
|
1775
|
+
}
|
|
1776
|
+
} else {
|
|
1777
|
+
console.log(colors.success(` ✅ You are using the latest version`));
|
|
1778
|
+
console.log('');
|
|
1779
|
+
}
|
|
1780
|
+
} catch (error: any) {
|
|
1781
|
+
console.log(colors.error(` ❌ Failed to check for updates: ${error.message}`));
|
|
1782
|
+
console.log('');
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
private async handleCompress(args: string[]): Promise<void> {
|
|
1787
|
+
const config = this.configManager.getContextCompressionConfig();
|
|
1788
|
+
|
|
1789
|
+
// If there are arguments, process config or execute
|
|
1790
|
+
if (args.length > 0) {
|
|
1791
|
+
const action = args[0].toLowerCase();
|
|
1792
|
+
|
|
1793
|
+
if (action === 'exec' || action === 'run' || action === 'now') {
|
|
1794
|
+
await this.executeCompression(config);
|
|
1795
|
+
return;
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
await this.setCompressConfig(args);
|
|
1799
|
+
return;
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
// Display current configuration
|
|
1803
|
+
console.log(chalk.cyan('\n📦 Context Compression:\n'));
|
|
1804
|
+
|
|
1805
|
+
console.log(` Status: ${config.enabled ? chalk.green('Enabled') : chalk.red('Disabled')}`);
|
|
1806
|
+
|
|
1807
|
+
console.log('');
|
|
1808
|
+
console.log(chalk.gray('Usage:'));
|
|
1809
|
+
console.log(chalk.gray(' /compress - Show current configuration'));
|
|
1810
|
+
console.log(chalk.gray(' /compress exec - Execute compression now'));
|
|
1811
|
+
console.log(chalk.gray(' /compress on|off - Enable/disable compression'));
|
|
1812
|
+
console.log('');
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
private async executeCompression(config: CompressionConfig): Promise<void> {
|
|
1816
|
+
const messages = this.conversationHistory;
|
|
1817
|
+
|
|
1818
|
+
if (!messages || messages.length === 0) {
|
|
1819
|
+
console.log(chalk.yellow('⚠️ No conversation to compress'));
|
|
1820
|
+
return;
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
const { needsCompression, reason } = this.contextCompressor.needsCompression(messages, config);
|
|
1824
|
+
|
|
1825
|
+
if (!needsCompression) {
|
|
1826
|
+
console.log(chalk.green('✅ No compression needed'));
|
|
1827
|
+
console.log(chalk.gray(` ${reason}`));
|
|
1828
|
+
return;
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
console.log(chalk.cyan('\n🚀 Executing context compression...\n'));
|
|
1832
|
+
|
|
1833
|
+
const spinner = ora({
|
|
1834
|
+
text: 'Compressing context...',
|
|
1835
|
+
spinner: 'dots',
|
|
1836
|
+
color: 'cyan',
|
|
1837
|
+
}).start();
|
|
1838
|
+
|
|
1839
|
+
try {
|
|
1840
|
+
const result: CompressionResult = await this.contextCompressor.compressContext(
|
|
1841
|
+
messages,
|
|
1842
|
+
'You are a helpful AI assistant.',
|
|
1843
|
+
config
|
|
1844
|
+
);
|
|
1845
|
+
|
|
1846
|
+
spinner.succeed(chalk.green('✅ Compression complete'));
|
|
1847
|
+
|
|
1848
|
+
console.log('');
|
|
1849
|
+
console.log(
|
|
1850
|
+
` ${chalk.cyan('Original:')} ${chalk.yellow(result.originalMessageCount.toString())} messages (${result.originalSize} chars)`
|
|
1851
|
+
);
|
|
1852
|
+
console.log(
|
|
1853
|
+
` ${chalk.cyan('Compressed:')} ${chalk.yellow(result.compressedMessageCount.toString())} messages (${result.compressedSize} chars)`
|
|
1854
|
+
);
|
|
1855
|
+
console.log(
|
|
1856
|
+
` ${chalk.cyan('Reduction:')} ${chalk.green(Math.round((1 - result.compressedSize / result.originalSize) * 100) + '%')}`
|
|
1857
|
+
);
|
|
1858
|
+
console.log(` ${chalk.cyan('Method:')} ${chalk.yellow(result.compressionMethod)}`);
|
|
1859
|
+
|
|
1860
|
+
console.log('');
|
|
1861
|
+
console.log(
|
|
1862
|
+
chalk.gray(
|
|
1863
|
+
'Use /clear to start a new conversation, or continue chatting to see the compressed summary.'
|
|
1864
|
+
)
|
|
1865
|
+
);
|
|
1866
|
+
console.log('');
|
|
1867
|
+
} catch (error: any) {
|
|
1868
|
+
spinner.fail(chalk.red('Compression failed'));
|
|
1869
|
+
console.log(chalk.red(` ${error.message}`));
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
private async setCompressConfig(args: string[]): Promise<void> {
|
|
1874
|
+
const config = this.configManager.getContextCompressionConfig();
|
|
1875
|
+
const action = args[0].toLowerCase();
|
|
1876
|
+
|
|
1877
|
+
switch (action) {
|
|
1878
|
+
case 'on':
|
|
1879
|
+
config.enabled = true;
|
|
1880
|
+
this.configManager.setContextCompressionConfig(config);
|
|
1881
|
+
this.configManager.save('global');
|
|
1882
|
+
console.log(chalk.green('✅ Context compression enabled'));
|
|
1883
|
+
break;
|
|
1884
|
+
|
|
1885
|
+
case 'off':
|
|
1886
|
+
config.enabled = false;
|
|
1887
|
+
this.configManager.setContextCompressionConfig(config);
|
|
1888
|
+
this.configManager.save('global');
|
|
1889
|
+
console.log(chalk.green('✅ Context compression disabled'));
|
|
1890
|
+
break;
|
|
1891
|
+
|
|
1892
|
+
default:
|
|
1893
|
+
console.log(chalk.red(`❌ Unknown action: ${action}`));
|
|
1894
|
+
console.log(chalk.gray('Available actions: on, off, exec'));
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
private async handleSkill(args: string[]): Promise<void> {
|
|
1899
|
+
const os = await import('os');
|
|
1900
|
+
const path = await import('path');
|
|
1901
|
+
const { promises: fs } = await import('fs');
|
|
1902
|
+
|
|
1903
|
+
const action = args[0] || 'list';
|
|
1904
|
+
const userSkillsPath = this.configManager.getUserSkillsPath() || path.join(os.homedir(), '.xagent', 'skills');
|
|
1905
|
+
|
|
1906
|
+
switch (action) {
|
|
1907
|
+
case 'list':
|
|
1908
|
+
await this.listUserSkills(userSkillsPath, fs, path);
|
|
1909
|
+
break;
|
|
1910
|
+
case 'add':
|
|
1911
|
+
await this.addSkill(args[1], userSkillsPath, fs, path);
|
|
1912
|
+
break;
|
|
1913
|
+
case 'remove':
|
|
1914
|
+
await this.removeSkill(args[1], userSkillsPath, fs, path);
|
|
1915
|
+
break;
|
|
1916
|
+
default:
|
|
1917
|
+
console.log(chalk.cyan('\n🔧 Skills:\n'));
|
|
1918
|
+
console.log(` Skills directory: ${chalk.yellow(userSkillsPath)}\n`);
|
|
1919
|
+
console.log(chalk.gray('Available commands:'));
|
|
1920
|
+
console.log(chalk.gray(' /skill list - List installed skills'));
|
|
1921
|
+
console.log(chalk.gray(' /skill add <source> - Add a skill (local path or remote URL)'));
|
|
1922
|
+
console.log(chalk.gray(' /skill remove <name> - Remove a user-installed skill'));
|
|
1923
|
+
console.log();
|
|
1924
|
+
console.log(chalk.gray('Examples:'));
|
|
1925
|
+
console.log(chalk.gray(' /skill add ./my-skill - Local path'));
|
|
1926
|
+
console.log(chalk.gray(' /skill add owner/repo - GitHub shorthand'));
|
|
1927
|
+
console.log(chalk.gray(' /skill add https://github.com/owner/repo - GitHub URL'));
|
|
1928
|
+
console.log();
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
private async listUserSkills(userSkillsPath: string, fs: any, path: any): Promise<void> {
|
|
1933
|
+
console.log(chalk.cyan('\n🔧 Skills:\n'));
|
|
1934
|
+
|
|
1935
|
+
try {
|
|
1936
|
+
const entries = await fs.readdir(userSkillsPath, { withFileTypes: true });
|
|
1937
|
+
const skills = entries.filter((e: any) => e.isDirectory());
|
|
1938
|
+
|
|
1939
|
+
if (skills.length === 0) {
|
|
1940
|
+
console.log(chalk.gray(' No skills installed'));
|
|
1941
|
+
console.log(chalk.cyan('\n To add a skill, use:'));
|
|
1942
|
+
console.log(chalk.cyan(' /skill add <path-to-skill>\n'));
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
for (const skill of skills) {
|
|
1947
|
+
const skillPath = path.join(userSkillsPath, skill.name as string);
|
|
1948
|
+
const skillMdPath = path.join(skillPath, 'SKILL.md');
|
|
1949
|
+
|
|
1950
|
+
try {
|
|
1951
|
+
const content = await fs.readFile(skillMdPath, 'utf-8');
|
|
1952
|
+
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
1953
|
+
const descMatch = content.match(/^description:\s*(.+)$/m);
|
|
1954
|
+
const name = nameMatch ? nameMatch[1].trim() : skill.name;
|
|
1955
|
+
const description = descMatch ? descMatch[1].trim() : 'No description';
|
|
1956
|
+
|
|
1957
|
+
console.log(` ${chalk.cyan('•')} ${chalk.yellow(name)}`);
|
|
1958
|
+
console.log(` ${chalk.gray(description)}`);
|
|
1959
|
+
console.log();
|
|
1960
|
+
} catch {
|
|
1961
|
+
console.log(` ${chalk.cyan('•')} ${chalk.yellow(skill.name)}`);
|
|
1962
|
+
console.log(` ${chalk.gray('(Missing SKILL.md)')}`);
|
|
1963
|
+
console.log();
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
console.log(chalk.gray(` Skills directory: ${userSkillsPath}`));
|
|
1968
|
+
console.log();
|
|
1969
|
+
} catch (error: any) {
|
|
1970
|
+
if (error.code === 'ENOENT') {
|
|
1971
|
+
console.log(chalk.gray(' No skills installed'));
|
|
1972
|
+
console.log(chalk.cyan('\n To add a skill, use:'));
|
|
1973
|
+
console.log(chalk.cyan(' /skill add <path-to-skill>\n'));
|
|
1974
|
+
} else {
|
|
1975
|
+
console.log(chalk.red(` Error: ${error.message}`));
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
private async addSkill(source: string, userSkillsPath: string, fs: any, path: any): Promise<void> {
|
|
1981
|
+
if (!source) {
|
|
1982
|
+
console.log(chalk.yellow('\n⚠️ Please specify a skill source'));
|
|
1983
|
+
console.log(chalk.cyan(' Usage: /skill add <source>\n'));
|
|
1984
|
+
console.log(chalk.gray(' Examples:'));
|
|
1985
|
+
console.log(chalk.gray(' /skill add ./my-skill - Local path'));
|
|
1986
|
+
console.log(chalk.gray(' /skill add owner/repo - GitHub shorthand'));
|
|
1987
|
+
console.log(chalk.gray(' /skill add https://github.com/owner/repo'));
|
|
1988
|
+
console.log();
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1992
|
+
const { parseSource, installSkill } = await import('./skill-installer.js');
|
|
1993
|
+
const parsed = parseSource(source.trim());
|
|
1994
|
+
const isLocal = parsed.type === 'local';
|
|
1995
|
+
|
|
1996
|
+
if (isLocal) {
|
|
1997
|
+
// Local installation
|
|
1998
|
+
const resolvedPath = path.resolve(source);
|
|
1999
|
+
const skillName = path.basename(resolvedPath);
|
|
2000
|
+
const destPath = path.join(userSkillsPath, skillName);
|
|
2001
|
+
|
|
2002
|
+
try {
|
|
2003
|
+
// Check if source exists
|
|
2004
|
+
await fs.access(resolvedPath);
|
|
2005
|
+
|
|
2006
|
+
// Check if SKILL.md exists
|
|
2007
|
+
const skillMdPath = path.join(resolvedPath, 'SKILL.md');
|
|
2008
|
+
try {
|
|
2009
|
+
await fs.access(skillMdPath);
|
|
2010
|
+
} catch {
|
|
2011
|
+
console.log(chalk.red(`\n❌ SKILL.md not found in ${resolvedPath}`));
|
|
2012
|
+
console.log(chalk.gray(' Each skill must have a SKILL.md file\n'));
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
// Check if skill already exists
|
|
2017
|
+
try {
|
|
2018
|
+
await fs.access(destPath);
|
|
2019
|
+
console.log(chalk.yellow(`\n⚠️ Skill "${skillName}" already installed`));
|
|
2020
|
+
console.log(chalk.cyan(` Use: /skill remove ${skillName} to remove it first\n`));
|
|
2021
|
+
return;
|
|
2022
|
+
} catch {
|
|
2023
|
+
// Doesn't exist, proceed
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
// Ensure skills directory exists
|
|
2027
|
+
await fs.mkdir(userSkillsPath, { recursive: true });
|
|
2028
|
+
|
|
2029
|
+
// Copy the skill
|
|
2030
|
+
await this.copyDirectory(resolvedPath, destPath);
|
|
2031
|
+
|
|
2032
|
+
console.log(chalk.green('\n✅ Skill installed successfully'));
|
|
2033
|
+
console.log(chalk.gray(` Name: ${skillName}`));
|
|
2034
|
+
console.log(chalk.gray(` Location: ${destPath}`));
|
|
2035
|
+
console.log(chalk.gray(` Type: Local`));
|
|
2036
|
+
console.log();
|
|
2037
|
+
|
|
2038
|
+
// Trigger system prompt update
|
|
2039
|
+
this.onSystemPromptUpdate?.();
|
|
2040
|
+
} catch (error: any) {
|
|
2041
|
+
if (error.code === 'ENOENT') {
|
|
2042
|
+
console.log(chalk.red(`\n❌ Skill not found: ${source}\n`));
|
|
2043
|
+
} else {
|
|
2044
|
+
console.log(chalk.red(`\n❌ Error installing skill: ${error.message}\n`));
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
} else {
|
|
2048
|
+
// Remote installation
|
|
2049
|
+
console.log(chalk.cyan('\n📦 Installing skill from remote source...\n'));
|
|
2050
|
+
console.log(chalk.gray(` Source: ${source}`));
|
|
2051
|
+
console.log(chalk.gray(` Type: Remote`));
|
|
2052
|
+
console.log();
|
|
2053
|
+
|
|
2054
|
+
try {
|
|
2055
|
+
const result = await installSkill(source);
|
|
2056
|
+
|
|
2057
|
+
if (result.success) {
|
|
2058
|
+
console.log(chalk.green('✅ Skill installed successfully'));
|
|
2059
|
+
console.log(chalk.gray(` Name: ${result.skillName}`));
|
|
2060
|
+
console.log(chalk.gray(` Location: ${result.skillPath}`));
|
|
2061
|
+
console.log(chalk.gray(' Type: Remote'));
|
|
2062
|
+
console.log();
|
|
2063
|
+
|
|
2064
|
+
// Trigger system prompt update - skill is immediately available
|
|
2065
|
+
this.onSystemPromptUpdate?.();
|
|
2066
|
+
} else {
|
|
2067
|
+
console.log(chalk.red(`\n❌ Failed to install skill: ${result.error}\n`));
|
|
2068
|
+
}
|
|
2069
|
+
} catch (error: any) {
|
|
2070
|
+
console.log(chalk.red(`\n❌ Error installing skill: ${error.message}\n`));
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
private async removeSkill(skillName: string, userSkillsPath: string, fs: any, path: any): Promise<void> {
|
|
2076
|
+
if (!skillName) {
|
|
2077
|
+
console.log(chalk.yellow('\n⚠️ Please specify a skill name'));
|
|
2078
|
+
console.log(chalk.cyan(' Usage: /skill remove <skill-name>\n'));
|
|
2079
|
+
return;
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2082
|
+
// Protect find-skills from deletion
|
|
2083
|
+
if (skillName === 'find-skills') {
|
|
2084
|
+
console.log(chalk.red('\n❌ Cannot remove protected skill: find-skills'));
|
|
2085
|
+
console.log(chalk.gray(' find-skills is a built-in skill that helps you discover and install other skills.\n'));
|
|
2086
|
+
return;
|
|
2087
|
+
}
|
|
2088
|
+
|
|
2089
|
+
const skillPath = path.join(userSkillsPath, skillName);
|
|
2090
|
+
|
|
2091
|
+
try {
|
|
2092
|
+
await fs.access(skillPath);
|
|
2093
|
+
|
|
2094
|
+
// Verify it's in skills path
|
|
2095
|
+
if (!skillPath.startsWith(userSkillsPath)) {
|
|
2096
|
+
console.log(chalk.red(`\n❌ Cannot remove skill outside user directory\n`));
|
|
2097
|
+
return;
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
// Remove the skill directory
|
|
2101
|
+
await fs.rm(skillPath, { recursive: true, force: true });
|
|
2102
|
+
|
|
2103
|
+
console.log(chalk.green('\n✅ Skill removed successfully'));
|
|
2104
|
+
console.log();
|
|
2105
|
+
|
|
2106
|
+
// Trigger system prompt update
|
|
2107
|
+
this.onSystemPromptUpdate?.();
|
|
2108
|
+
} catch (error: any) {
|
|
2109
|
+
if (error.code === 'ENOENT' || error.code === 'ENOENT') {
|
|
2110
|
+
console.log(chalk.yellow(`\n⚠️ Skill not found: ${skillName}\n`));
|
|
2111
|
+
} else {
|
|
2112
|
+
console.log(chalk.red(`\n❌ Error removing skill: ${error.message}\n`));
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
private async copyDirectory(src: string, dest: string): Promise<void> {
|
|
2118
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
2119
|
+
await fs.mkdir(dest, { recursive: true });
|
|
2120
|
+
|
|
2121
|
+
for (const entry of entries) {
|
|
2122
|
+
// Skip node_modules to keep dependencies isolated
|
|
2123
|
+
// if (entry.name === 'node_modules') continue;
|
|
2124
|
+
|
|
2125
|
+
const srcPath = path.join(src, entry.name);
|
|
2126
|
+
const destPath = path.join(dest, entry.name);
|
|
2127
|
+
|
|
2128
|
+
if (entry.isDirectory()) {
|
|
2129
|
+
await this.copyDirectory(srcPath, destPath);
|
|
2130
|
+
} else if (entry.isFile()) {
|
|
2131
|
+
await fs.copyFile(srcPath, destPath);
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
export async function parseInput(input: string): Promise<InputType[]> {
|
|
2138
|
+
const inputs: InputType[] = [];
|
|
2139
|
+
let remaining = input;
|
|
2140
|
+
|
|
2141
|
+
// Match @ followed by any non-whitespace sequence
|
|
2142
|
+
const fileRefRegex = /@([^\s]+)/g;
|
|
2143
|
+
let match;
|
|
2144
|
+
while ((match = fileRefRegex.exec(remaining)) !== null) {
|
|
2145
|
+
const filePath = match[1];
|
|
2146
|
+
const beforeMatch = remaining.substring(0, match.index);
|
|
2147
|
+
const afterMatch = remaining.substring(match.index + match[0].length);
|
|
2148
|
+
|
|
2149
|
+
if (beforeMatch.trim()) {
|
|
2150
|
+
inputs.push({ type: 'text', content: beforeMatch.trim() });
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
// Only treat as file reference if the file actually exists
|
|
2154
|
+
const exists = await fileExists(filePath);
|
|
2155
|
+
if (exists) {
|
|
2156
|
+
inputs.push({ type: 'file', content: filePath });
|
|
2157
|
+
} else {
|
|
2158
|
+
// Not a file, treat as regular text (preserving the @ symbol)
|
|
2159
|
+
inputs.push({ type: 'text', content: '@' + filePath });
|
|
2160
|
+
}
|
|
2161
|
+
remaining = afterMatch;
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
if (remaining.trim()) {
|
|
2165
|
+
if (remaining.startsWith('!')) {
|
|
2166
|
+
inputs.push({ type: 'command', content: remaining.slice(1).trim() });
|
|
2167
|
+
} else {
|
|
2168
|
+
inputs.push({ type: 'text', content: remaining.trim() });
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
|
|
2172
|
+
return inputs;
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2175
|
+
// Helper function to check if a file path exists
|
|
2176
|
+
async function fileExists(filePath: string): Promise<boolean> {
|
|
2177
|
+
try {
|
|
2178
|
+
// Resolve to absolute path
|
|
2179
|
+
const absolutePath = path.resolve(filePath);
|
|
2180
|
+
await fs.access(absolutePath);
|
|
2181
|
+
return true;
|
|
2182
|
+
} catch {
|
|
2183
|
+
return false;
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2187
|
+
export function detectImageInput(input: string): boolean {
|
|
2188
|
+
return input.includes('[Pasted image') || input.includes('<image');
|
|
2189
|
+
}
|