@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/dist/slash-commands.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { select, confirm, text } from '@clack/prompts';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import ora from 'ora';
|
|
4
4
|
import fs from 'fs/promises';
|
|
5
5
|
import path from 'path';
|
|
6
6
|
import { ExecutionMode, AuthType } from './types.js';
|
|
7
|
+
import { fetchDefaultModels } from './ai-client/providers/remote.js';
|
|
7
8
|
import { getToolRegistry } from './tools.js';
|
|
8
9
|
import { getAgentManager } from './agents.js';
|
|
9
10
|
import { getMemoryManager } from './memory.js';
|
|
@@ -11,10 +12,11 @@ import { getMCPManager } from './mcp.js';
|
|
|
11
12
|
import { getCheckpointManager } from './checkpoint.js';
|
|
12
13
|
import { getConfigManager } from './config.js';
|
|
13
14
|
import { getLogger } from './logger.js';
|
|
14
|
-
import { getContextCompressor } from './context-compressor.js';
|
|
15
|
+
import { getContextCompressor, } from './context-compressor.js';
|
|
15
16
|
import { getConversationManager } from './conversation.js';
|
|
16
17
|
import { icons, colors } from './theme.js';
|
|
17
|
-
import {
|
|
18
|
+
import { ensureTtySane } from './terminal.js';
|
|
19
|
+
import { AuthService, selectAuthType, THIRD_PARTY_PROVIDERS, VLM_PROVIDERS } from './auth.js';
|
|
18
20
|
const logger = getLogger();
|
|
19
21
|
export class SlashCommandHandler {
|
|
20
22
|
configManager;
|
|
@@ -27,6 +29,8 @@ export class SlashCommandHandler {
|
|
|
27
29
|
conversationHistory = [];
|
|
28
30
|
onClearCallback = null;
|
|
29
31
|
onSystemPromptUpdate = null;
|
|
32
|
+
onConfigUpdate = null;
|
|
33
|
+
remoteAIClient = null; // Reference to InteractiveSession's remoteAIClient
|
|
30
34
|
constructor() {
|
|
31
35
|
this.configManager = getConfigManager(process.cwd());
|
|
32
36
|
this.agentManager = getAgentManager(process.cwd());
|
|
@@ -36,6 +40,12 @@ export class SlashCommandHandler {
|
|
|
36
40
|
this.contextCompressor = getContextCompressor();
|
|
37
41
|
this.conversationManager = getConversationManager();
|
|
38
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Set remote AI client reference (called from InteractiveSession)
|
|
45
|
+
*/
|
|
46
|
+
setRemoteAIClient(client) {
|
|
47
|
+
this.remoteAIClient = client;
|
|
48
|
+
}
|
|
39
49
|
/**
|
|
40
50
|
* Set callback for clearing conversation
|
|
41
51
|
*/
|
|
@@ -48,6 +58,12 @@ export class SlashCommandHandler {
|
|
|
48
58
|
setSystemPromptUpdateCallback(callback) {
|
|
49
59
|
this.onSystemPromptUpdate = callback;
|
|
50
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Set callback for config update (called after /auth changes config)
|
|
63
|
+
*/
|
|
64
|
+
setConfigUpdateCallback(callback) {
|
|
65
|
+
this.onConfigUpdate = callback;
|
|
66
|
+
}
|
|
51
67
|
/**
|
|
52
68
|
* Set current conversation history (includes all user/assistant/tool messages)
|
|
53
69
|
*/
|
|
@@ -91,8 +107,11 @@ export class SlashCommandHandler {
|
|
|
91
107
|
case 'mcp':
|
|
92
108
|
await this.handleMcp(args);
|
|
93
109
|
break;
|
|
94
|
-
case '
|
|
95
|
-
await this.
|
|
110
|
+
case 'skill':
|
|
111
|
+
await this.handleSkill(args);
|
|
112
|
+
break;
|
|
113
|
+
case 'model':
|
|
114
|
+
await this.handleModel();
|
|
96
115
|
break;
|
|
97
116
|
case 'memory':
|
|
98
117
|
await this.handleMemory(args);
|
|
@@ -118,9 +137,14 @@ export class SlashCommandHandler {
|
|
|
118
137
|
case 'compress':
|
|
119
138
|
await this.handleCompress(args);
|
|
120
139
|
break;
|
|
140
|
+
case 'update':
|
|
141
|
+
await this.handleUpdate();
|
|
142
|
+
break;
|
|
121
143
|
default:
|
|
122
144
|
logger.warn(`Unknown command: /${command}`, 'Type /help for available commands');
|
|
123
145
|
}
|
|
146
|
+
// Ensure stdin is in raw mode for proper input handling after @clack/prompts usage
|
|
147
|
+
ensureTtySane();
|
|
124
148
|
return true;
|
|
125
149
|
}
|
|
126
150
|
async showHelp() {
|
|
@@ -128,7 +152,10 @@ export class SlashCommandHandler {
|
|
|
128
152
|
console.log('');
|
|
129
153
|
console.log(colors.primaryBright('╔════════════════════════════════════════════════════════════╗'));
|
|
130
154
|
console.log(colors.primaryBright('║') + ' '.repeat(56) + colors.primaryBright('║'));
|
|
131
|
-
console.log(' '.repeat(14) +
|
|
155
|
+
console.log(' '.repeat(14) +
|
|
156
|
+
colors.gradient('📚 XAGENT CLI Help') +
|
|
157
|
+
' '.repeat(31) +
|
|
158
|
+
colors.primaryBright('║'));
|
|
132
159
|
console.log(colors.primaryBright('║') + ' '.repeat(56) + colors.primaryBright('║'));
|
|
133
160
|
console.log(colors.primaryBright('╚════════════════════════════════════════════════════════════╝'));
|
|
134
161
|
console.log('');
|
|
@@ -146,20 +173,20 @@ export class SlashCommandHandler {
|
|
|
146
173
|
cmd: '/help [command]',
|
|
147
174
|
desc: 'Show help information',
|
|
148
175
|
detail: 'View all available commands or detailed description of specific command',
|
|
149
|
-
example: '/help\n/help mode'
|
|
176
|
+
example: '/help\n/help mode',
|
|
150
177
|
},
|
|
151
178
|
{
|
|
152
179
|
cmd: '/clear',
|
|
153
180
|
desc: 'Clear conversation history',
|
|
154
181
|
detail: 'Clear all conversation records of current session, start new conversation',
|
|
155
|
-
example: '/clear'
|
|
182
|
+
example: '/clear',
|
|
156
183
|
},
|
|
157
184
|
{
|
|
158
185
|
cmd: '/exit',
|
|
159
186
|
desc: 'Exit program',
|
|
160
187
|
detail: 'Safely exit XAGENT CLI',
|
|
161
|
-
example: '/exit'
|
|
162
|
-
}
|
|
188
|
+
example: '/exit',
|
|
189
|
+
},
|
|
163
190
|
]);
|
|
164
191
|
// Project Management
|
|
165
192
|
this.showHelpCategory('Project Management', [
|
|
@@ -167,14 +194,14 @@ export class SlashCommandHandler {
|
|
|
167
194
|
cmd: '/init',
|
|
168
195
|
desc: 'Initialize project context',
|
|
169
196
|
detail: 'Create XAGENT.md file in current directory, used to store project context information',
|
|
170
|
-
example: '/init'
|
|
197
|
+
example: '/init',
|
|
171
198
|
},
|
|
172
199
|
{
|
|
173
200
|
cmd: '/memory [show|clear]',
|
|
174
201
|
desc: 'Manage project memory',
|
|
175
202
|
detail: 'View or clear memory (global, current, all, or filename)',
|
|
176
|
-
example: '/memory show\n/memory clear\n/memory clear global\n/memory clear all'
|
|
177
|
-
}
|
|
203
|
+
example: '/memory show\n/memory clear\n/memory clear global\n/memory clear all',
|
|
204
|
+
},
|
|
178
205
|
]);
|
|
179
206
|
// Authentication & Configuration
|
|
180
207
|
this.showHelpCategory('Authentication & Configuration', [
|
|
@@ -182,7 +209,7 @@ export class SlashCommandHandler {
|
|
|
182
209
|
cmd: '/auth',
|
|
183
210
|
desc: 'Configure authentication information',
|
|
184
211
|
detail: 'Change or view current authentication configuration',
|
|
185
|
-
example: '/auth'
|
|
212
|
+
example: '/auth',
|
|
186
213
|
},
|
|
187
214
|
{
|
|
188
215
|
cmd: '/mode [mode]',
|
|
@@ -194,14 +221,14 @@ export class SlashCommandHandler {
|
|
|
194
221
|
'accept_edits - Automatically accept edit operations',
|
|
195
222
|
'plan - Plan before executing',
|
|
196
223
|
'default - Safe execution, requires confirmation',
|
|
197
|
-
'smart - Smart approval (recommended)'
|
|
198
|
-
]
|
|
224
|
+
'smart - Smart approval (recommended)',
|
|
225
|
+
],
|
|
199
226
|
},
|
|
200
227
|
{
|
|
201
228
|
cmd: '/think [on|off|display]',
|
|
202
229
|
desc: 'Control thinking mode',
|
|
203
230
|
detail: 'Enable/disable AI thinking process display',
|
|
204
|
-
example: '/think on\n/think off\n/think display compact'
|
|
231
|
+
example: '/think on\n/think off\n/think display compact',
|
|
205
232
|
},
|
|
206
233
|
// {
|
|
207
234
|
// cmd: '/language [zh|en]',
|
|
@@ -213,8 +240,8 @@ export class SlashCommandHandler {
|
|
|
213
240
|
cmd: '/theme',
|
|
214
241
|
desc: 'Switch theme',
|
|
215
242
|
detail: 'Change UI theme style',
|
|
216
|
-
example: '/theme'
|
|
217
|
-
}
|
|
243
|
+
example: '/theme',
|
|
244
|
+
},
|
|
218
245
|
]);
|
|
219
246
|
// Feature Extensions
|
|
220
247
|
this.showHelpCategory('Feature Extensions', [
|
|
@@ -222,13 +249,19 @@ export class SlashCommandHandler {
|
|
|
222
249
|
cmd: '/agents [list|online|install|remove]',
|
|
223
250
|
desc: 'Manage sub-agents',
|
|
224
251
|
detail: 'View, install or remove specialized AI sub-agents',
|
|
225
|
-
example: '/agents list\n/agents online\n/agents install explore-agent'
|
|
252
|
+
example: '/agents list\n/agents online\n/agents install explore-agent',
|
|
226
253
|
},
|
|
227
254
|
{
|
|
228
255
|
cmd: '/mcp [list|add|remove|refresh]',
|
|
229
256
|
desc: 'Manage MCP servers',
|
|
230
257
|
detail: 'Manage Model Context Protocol servers',
|
|
231
|
-
example: '/mcp list\n/mcp add server-name'
|
|
258
|
+
example: '/mcp list\n/mcp add server-name',
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
cmd: '/skill [list|add|remove]',
|
|
262
|
+
desc: 'Manage skills',
|
|
263
|
+
detail: 'Install, list, or remove skills from ~/.xagent/skills',
|
|
264
|
+
example: '/skill list\n/skill add ./my-skill\n/skill add owner/repo\n/skill remove my-skill'
|
|
232
265
|
},
|
|
233
266
|
{
|
|
234
267
|
cmd: '/vlm',
|
|
@@ -236,12 +269,18 @@ export class SlashCommandHandler {
|
|
|
236
269
|
detail: 'Configure Vision-Language Model for browser/desktop automation',
|
|
237
270
|
example: '/vlm'
|
|
238
271
|
},
|
|
272
|
+
{
|
|
273
|
+
cmd: '/model',
|
|
274
|
+
desc: 'Configure LLM/VLM models',
|
|
275
|
+
detail: 'Configure or switch LLM and VLM models for remote mode',
|
|
276
|
+
example: '/model',
|
|
277
|
+
},
|
|
239
278
|
{
|
|
240
279
|
cmd: '/tools [verbose|simple]',
|
|
241
280
|
desc: 'Manage tool display',
|
|
242
281
|
detail: 'View available tools or switch tool call display mode',
|
|
243
|
-
example: '/tools\n/tools verbose\n/tools simple'
|
|
244
|
-
}
|
|
282
|
+
example: '/tools\n/tools verbose\n/tools simple',
|
|
283
|
+
},
|
|
245
284
|
]);
|
|
246
285
|
// Advanced Features
|
|
247
286
|
this.showHelpCategory('Advanced Features', [
|
|
@@ -249,26 +288,32 @@ export class SlashCommandHandler {
|
|
|
249
288
|
cmd: '/restore',
|
|
250
289
|
desc: 'Restore from checkpoint',
|
|
251
290
|
detail: 'Restore conversation state from historical checkpoints',
|
|
252
|
-
example: '/restore'
|
|
291
|
+
example: '/restore',
|
|
253
292
|
},
|
|
254
293
|
{
|
|
255
294
|
cmd: '/compress [on|off|max_message|max_token|exec]',
|
|
256
295
|
desc: 'Manage context compression',
|
|
257
296
|
detail: 'Configure compression settings or execute compression manually',
|
|
258
|
-
example: '/compress\n/compress exec\n/compress on\n/compress max_message 50\n/compress max_token 1500000'
|
|
297
|
+
example: '/compress\n/compress exec\n/compress on\n/compress max_message 50\n/compress max_token 1500000',
|
|
259
298
|
},
|
|
260
299
|
{
|
|
261
300
|
cmd: '/stats',
|
|
262
301
|
desc: 'Show session statistics',
|
|
263
302
|
detail: 'View statistics information of current session',
|
|
264
|
-
example: '/stats'
|
|
303
|
+
example: '/stats',
|
|
265
304
|
},
|
|
266
305
|
{
|
|
267
306
|
cmd: '/about',
|
|
268
307
|
desc: 'Show version information',
|
|
269
308
|
detail: 'View version and related information of XAGENT CLI',
|
|
270
|
-
example: '/about'
|
|
271
|
-
}
|
|
309
|
+
example: '/about',
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
cmd: '/update',
|
|
313
|
+
desc: 'Check for updates',
|
|
314
|
+
detail: 'Check for new versions and update xAgent CLI',
|
|
315
|
+
example: '/update',
|
|
316
|
+
},
|
|
272
317
|
]);
|
|
273
318
|
// Keyboard Shortcuts
|
|
274
319
|
console.log('');
|
|
@@ -287,18 +332,18 @@ export class SlashCommandHandler {
|
|
|
287
332
|
console.log(colors.primaryBright(title));
|
|
288
333
|
console.log(colors.border(separator));
|
|
289
334
|
console.log('');
|
|
290
|
-
commands.forEach(cmd => {
|
|
335
|
+
commands.forEach((cmd) => {
|
|
291
336
|
console.log(colors.primaryBright(` ${cmd.cmd}`));
|
|
292
337
|
console.log(colors.textDim(` ${cmd.desc}`));
|
|
293
338
|
console.log(colors.textMuted(` ${cmd.detail}`));
|
|
294
339
|
if (cmd.modes) {
|
|
295
340
|
console.log(colors.textDim(` Available modes:`));
|
|
296
|
-
cmd.modes.forEach(mode => {
|
|
341
|
+
cmd.modes.forEach((mode) => {
|
|
297
342
|
console.log(colors.textDim(` • ${mode}`));
|
|
298
343
|
});
|
|
299
344
|
}
|
|
300
345
|
console.log(colors.accent(` Examples:`));
|
|
301
|
-
cmd.example.split('\n').forEach(ex => {
|
|
346
|
+
cmd.example.split('\n').forEach((ex) => {
|
|
302
347
|
console.log(colors.codeText(` ${ex}`));
|
|
303
348
|
});
|
|
304
349
|
console.log('');
|
|
@@ -317,9 +362,9 @@ export class SlashCommandHandler {
|
|
|
317
362
|
async handleClear() {
|
|
318
363
|
// Clear local conversation history
|
|
319
364
|
this.conversationHistory = [];
|
|
320
|
-
// Clear ConversationManager
|
|
365
|
+
// Clear current conversation in ConversationManager
|
|
321
366
|
await this.conversationManager.clearCurrentConversation();
|
|
322
|
-
// Call callback to notify InteractiveSession
|
|
367
|
+
// Call callback to notify InteractiveSession to clear conversation
|
|
323
368
|
if (this.onClearCallback) {
|
|
324
369
|
this.onClearCallback();
|
|
325
370
|
}
|
|
@@ -331,37 +376,131 @@ export class SlashCommandHandler {
|
|
|
331
376
|
}
|
|
332
377
|
async handleAuth() {
|
|
333
378
|
logger.section('Authentication Management');
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}
|
|
345
|
-
|
|
379
|
+
// Show current authentication configuration
|
|
380
|
+
const authConfig = this.configManager.getAuthConfig();
|
|
381
|
+
const isRemote = authConfig.type === AuthType.OAUTH_XAGENT;
|
|
382
|
+
const currentType = isRemote ? 'xAgent (Remote)' : 'Third-party API (Local)';
|
|
383
|
+
console.log(chalk.cyan('\n📋 Current Authentication Configuration:\n'));
|
|
384
|
+
console.log(` ${chalk.yellow('Mode:')} ${currentType}`);
|
|
385
|
+
if (isRemote) {
|
|
386
|
+
// Remote mode: show remote_llmModelName and remote_vlmModelName
|
|
387
|
+
const llmModel = authConfig.remote_llmModelName || 'Not set';
|
|
388
|
+
const vlmModel = authConfig.remote_vlmModelName || 'Not set';
|
|
389
|
+
console.log(` ${chalk.yellow('LLM Model:')} ${llmModel}`);
|
|
390
|
+
console.log(` ${chalk.yellow('VLM Model:')} ${vlmModel}`);
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
// Local mode: show modelName (LLM) and guiSubagentModel (VLM)
|
|
394
|
+
const llmModel = authConfig.modelName || 'Not set';
|
|
395
|
+
const vlmModel = this.configManager.get('guiSubagentModel') || 'Not set';
|
|
396
|
+
console.log(` ${chalk.yellow('LLM Model:')} ${llmModel}`);
|
|
397
|
+
console.log(` ${chalk.yellow('VLM Model:')} ${vlmModel}`);
|
|
398
|
+
}
|
|
399
|
+
console.log('');
|
|
400
|
+
const action = await select({
|
|
401
|
+
message: 'Select action:',
|
|
402
|
+
options: [
|
|
403
|
+
{ value: 'switch', label: 'Switch authentication method' },
|
|
404
|
+
{ value: 'back', label: 'Back' },
|
|
405
|
+
],
|
|
406
|
+
});
|
|
346
407
|
if (action === 'back') {
|
|
347
408
|
return;
|
|
348
409
|
}
|
|
349
|
-
if (action === '
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
410
|
+
if (action === 'switch') {
|
|
411
|
+
// Use the same selection UI as initial setup
|
|
412
|
+
const confirmSwitch = await confirm({
|
|
413
|
+
message: `Switch from "${currentType}" to another authentication method?`,
|
|
414
|
+
});
|
|
415
|
+
if (confirmSwitch === false || confirmSwitch === undefined) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
// Select authentication type (same as initial setup)
|
|
419
|
+
const authType = await selectAuthType();
|
|
420
|
+
if (authType === AuthType.OAUTH_XAGENT) {
|
|
421
|
+
// Switch to xAgent (Remote mode)
|
|
422
|
+
const authService = new AuthService({
|
|
423
|
+
type: AuthType.OAUTH_XAGENT,
|
|
424
|
+
apiKey: '',
|
|
425
|
+
baseUrl: '',
|
|
426
|
+
xagentApiBaseUrl: authConfig.xagentApiBaseUrl,
|
|
427
|
+
});
|
|
428
|
+
const success = await authService.authenticate();
|
|
429
|
+
if (success) {
|
|
430
|
+
const newAuthConfig = authService.getAuthConfig();
|
|
431
|
+
this.configManager.setAuthConfig({
|
|
432
|
+
selectedAuthType: newAuthConfig.type,
|
|
433
|
+
apiKey: newAuthConfig.apiKey,
|
|
434
|
+
refreshToken: newAuthConfig.refreshToken,
|
|
435
|
+
baseUrl: newAuthConfig.baseUrl,
|
|
436
|
+
modelName: '',
|
|
437
|
+
xagentApiBaseUrl: newAuthConfig.xagentApiBaseUrl,
|
|
438
|
+
guiSubagentModel: '',
|
|
439
|
+
guiSubagentBaseUrl: 'https://www.xagent-colife.net/v3',
|
|
440
|
+
guiSubagentApiKey: '',
|
|
441
|
+
});
|
|
442
|
+
// Set default remote model settings if not already set
|
|
443
|
+
// Fetch default models from /models/default endpoint
|
|
444
|
+
const webBaseUrl = newAuthConfig.xagentApiBaseUrl || 'https://www.xagent-colife.net';
|
|
445
|
+
let defaultLlmName = '';
|
|
446
|
+
let defaultVlmName = '';
|
|
447
|
+
try {
|
|
448
|
+
console.log(chalk.cyan('\n📊 Fetching default models from remote server...'));
|
|
449
|
+
const defaults = await fetchDefaultModels(newAuthConfig.apiKey || '', webBaseUrl);
|
|
450
|
+
if (defaults.llm?.name) {
|
|
451
|
+
defaultLlmName = defaults.llm.name;
|
|
452
|
+
console.log(chalk.cyan(` LLM Model: ${defaults.llm.name}`));
|
|
453
|
+
}
|
|
454
|
+
if (defaults.vlm?.name) {
|
|
455
|
+
defaultVlmName = defaults.vlm.name;
|
|
456
|
+
console.log(chalk.cyan(` VLM Model: ${defaults.vlm.name}`));
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
catch (error) {
|
|
460
|
+
console.log(chalk.yellow(` ⚠️ Failed to fetch default models: ${error.message}`));
|
|
461
|
+
console.log(chalk.yellow(' ⚠️ Use /model command to select models manually.'));
|
|
462
|
+
}
|
|
463
|
+
console.log('');
|
|
464
|
+
this.configManager.set('remote_llmModelName', defaultLlmName);
|
|
465
|
+
this.configManager.set('remote_vlmModelName', defaultVlmName);
|
|
466
|
+
this.configManager.save('global');
|
|
467
|
+
// Notify InteractiveSession to update aiClient config
|
|
468
|
+
if (this.onConfigUpdate) {
|
|
469
|
+
this.onConfigUpdate();
|
|
470
|
+
}
|
|
471
|
+
console.log(chalk.green('\n✅ Authentication switched to xAgent (Remote mode)!'));
|
|
472
|
+
// Removed: logging partial token for security
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
// Switch to Third-party API (Local mode)
|
|
477
|
+
const authService = new AuthService({
|
|
478
|
+
type: AuthType.OPENAI_COMPATIBLE,
|
|
479
|
+
apiKey: '',
|
|
480
|
+
baseUrl: '',
|
|
481
|
+
modelName: '',
|
|
482
|
+
});
|
|
483
|
+
const success = await authService.authenticate();
|
|
484
|
+
if (success) {
|
|
485
|
+
const newAuthConfig = authService.getAuthConfig();
|
|
486
|
+
this.configManager.setAuthConfig({
|
|
487
|
+
selectedAuthType: newAuthConfig.type,
|
|
488
|
+
apiKey: newAuthConfig.apiKey,
|
|
489
|
+
baseUrl: newAuthConfig.baseUrl,
|
|
490
|
+
modelName: newAuthConfig.modelName,
|
|
491
|
+
xagentApiBaseUrl: '',
|
|
492
|
+
refreshToken: '',
|
|
493
|
+
guiSubagentModel: '',
|
|
494
|
+
guiSubagentBaseUrl: '',
|
|
495
|
+
guiSubagentApiKey: '',
|
|
496
|
+
});
|
|
497
|
+
this.configManager.save('global');
|
|
498
|
+
// Notify InteractiveSession to update aiClient config
|
|
499
|
+
if (this.onConfigUpdate) {
|
|
500
|
+
this.onConfigUpdate();
|
|
501
|
+
}
|
|
502
|
+
console.log(chalk.green('\n✅ Authentication switched to Third-party API (Local mode)!'));
|
|
361
503
|
}
|
|
362
|
-
]);
|
|
363
|
-
if (selectAuthType) {
|
|
364
|
-
logger.warn('Please restart xAgent CLI and run /auth again', 'Authentication changes require restart');
|
|
365
504
|
}
|
|
366
505
|
}
|
|
367
506
|
}
|
|
@@ -371,39 +510,36 @@ export class SlashCommandHandler {
|
|
|
371
510
|
const currentAuthType = authConfig.type;
|
|
372
511
|
if (currentAuthType !== AuthType.OAUTH_XAGENT) {
|
|
373
512
|
console.log(chalk.yellow('\n⚠️ Current authentication type is not OAuth xAgent.'));
|
|
374
|
-
const
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
message: 'Do you want to switch to OAuth xAgent authentication?',
|
|
379
|
-
default: false
|
|
380
|
-
}
|
|
381
|
-
]);
|
|
382
|
-
if (!proceed) {
|
|
513
|
+
const proceed = await confirm({
|
|
514
|
+
message: 'Do you want to switch to OAuth xAgent authentication?',
|
|
515
|
+
});
|
|
516
|
+
if (proceed === false || proceed === undefined) {
|
|
383
517
|
return;
|
|
384
518
|
}
|
|
385
519
|
// Switch to OAuth xAgent
|
|
386
|
-
|
|
520
|
+
this.configManager.setAuthConfig({
|
|
387
521
|
selectedAuthType: AuthType.OAUTH_XAGENT,
|
|
388
522
|
apiKey: '',
|
|
389
523
|
refreshToken: '',
|
|
390
|
-
baseUrl: ''
|
|
524
|
+
baseUrl: '',
|
|
391
525
|
});
|
|
392
|
-
|
|
526
|
+
this.configManager.save('global');
|
|
393
527
|
console.log(chalk.green('✅ Switched to OAuth xAgent authentication.'));
|
|
394
528
|
}
|
|
395
529
|
console.log(chalk.cyan('\n🔐 Starting OAuth xAgent login...'));
|
|
396
530
|
console.log(chalk.gray(' A browser will open for you to complete authentication.\n'));
|
|
397
531
|
try {
|
|
532
|
+
// Get xagentApiBaseUrl from config (respects XAGENT_BASE_URL env var)
|
|
533
|
+
const config = this.configManager.getAuthConfig();
|
|
398
534
|
const authService = new AuthService({
|
|
399
535
|
type: AuthType.OAUTH_XAGENT,
|
|
400
536
|
apiKey: '',
|
|
401
537
|
baseUrl: '',
|
|
402
|
-
refreshToken: ''
|
|
538
|
+
refreshToken: '',
|
|
539
|
+
xagentApiBaseUrl: config.xagentApiBaseUrl,
|
|
403
540
|
});
|
|
404
541
|
const success = await authService.authenticate();
|
|
405
542
|
if (success) {
|
|
406
|
-
const newConfig = this.configManager.getAuthConfig();
|
|
407
543
|
console.log(chalk.green('\n✅ Login successful!'));
|
|
408
544
|
console.log(chalk.cyan(` Token saved to: ~/.xagent/settings.json`));
|
|
409
545
|
console.log(chalk.gray(' You can now use xAgent CLI with remote AI services.\n'));
|
|
@@ -416,75 +552,320 @@ export class SlashCommandHandler {
|
|
|
416
552
|
console.log(chalk.red(`\n❌ Login error: ${error.message || 'Unknown error'}`));
|
|
417
553
|
}
|
|
418
554
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
console.log(` Base URL: ${chalk.yellow(currentVlmConfig.baseUrl || 'Not configured')}`);
|
|
430
|
-
console.log(` API Key: ${chalk.yellow(currentVlmConfig.apiKey || 'Not configured')}`);
|
|
431
|
-
console.log();
|
|
432
|
-
const { action } = await inquirer.prompt([
|
|
433
|
-
{
|
|
434
|
-
type: 'list',
|
|
435
|
-
name: 'action',
|
|
436
|
-
message: 'Select action:',
|
|
437
|
-
choices: [
|
|
438
|
-
{ name: 'Configure VLM', value: 'configure' },
|
|
439
|
-
{ name: 'Remove VLM configuration', value: 'remove' },
|
|
440
|
-
{ name: 'Back', value: 'back' }
|
|
441
|
-
]
|
|
442
|
-
}
|
|
443
|
-
]);
|
|
444
|
-
if (action === 'back') {
|
|
445
|
-
return;
|
|
555
|
+
/**
|
|
556
|
+
* Handle /model command - Configure LLM/VLM models
|
|
557
|
+
* Supports both remote mode (xAgent) and local mode (third-party API)
|
|
558
|
+
*/
|
|
559
|
+
async handleModel() {
|
|
560
|
+
const authConfig = this.configManager.getAuthConfig();
|
|
561
|
+
// Determine mode and show appropriate UI
|
|
562
|
+
if (authConfig.type === AuthType.OAUTH_XAGENT) {
|
|
563
|
+
// Remote mode - use backend models
|
|
564
|
+
await this.handleRemoteModel();
|
|
446
565
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
566
|
+
else {
|
|
567
|
+
// Local mode - configure third-party API directly
|
|
568
|
+
await this.handleLocalModel();
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Handle /model command for remote mode - Configure models from backend
|
|
573
|
+
*/
|
|
574
|
+
async handleRemoteModel() {
|
|
575
|
+
const authConfig = this.configManager.getAuthConfig();
|
|
576
|
+
// Auto-fetch default models if not set
|
|
577
|
+
let currentLlm = authConfig.remote_llmModelName;
|
|
578
|
+
let currentVlm = authConfig.remote_vlmModelName;
|
|
579
|
+
if (!currentLlm || !currentVlm) {
|
|
580
|
+
console.log(chalk.cyan('\n📊 Fetching default models from remote server...'));
|
|
581
|
+
// Try to use RemoteAIClient first, otherwise fetch directly
|
|
582
|
+
let defaults = null;
|
|
583
|
+
if (this.remoteAIClient) {
|
|
584
|
+
try {
|
|
585
|
+
defaults = await this.remoteAIClient.getDefaultModels();
|
|
586
|
+
}
|
|
587
|
+
catch (error) {
|
|
588
|
+
console.log(chalk.yellow(` ⚠️ Failed to get defaults from RemoteAIClient: ${error.message}`));
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
// If RemoteAIClient failed or not available, fetch directly
|
|
592
|
+
if (!defaults) {
|
|
593
|
+
try {
|
|
594
|
+
const webBaseUrl = authConfig.xagentApiBaseUrl || 'https://www.xagent-colife.net';
|
|
595
|
+
defaults = await fetchDefaultModels(authConfig.apiKey || '', webBaseUrl);
|
|
596
|
+
}
|
|
597
|
+
catch (error) {
|
|
598
|
+
console.log(chalk.yellow(` ⚠️ Failed to fetch default models: ${error.message}`));
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
if (defaults) {
|
|
602
|
+
if (!currentLlm && defaults.llm?.name) {
|
|
603
|
+
currentLlm = defaults.llm.name;
|
|
604
|
+
this.configManager.set('remote_llmModelName', currentLlm);
|
|
605
|
+
console.log(chalk.cyan(` Default LLM: ${defaults.llm.displayName || currentLlm}`));
|
|
606
|
+
}
|
|
607
|
+
if (!currentVlm && defaults.vlm?.name) {
|
|
608
|
+
currentVlm = defaults.vlm.name;
|
|
609
|
+
this.configManager.set('remote_vlmModelName', currentVlm);
|
|
610
|
+
console.log(chalk.cyan(` Default VLM: ${defaults.vlm.displayName || currentVlm}`));
|
|
454
611
|
}
|
|
455
|
-
|
|
456
|
-
if (confirm) {
|
|
457
|
-
await this.configManager.set('guiSubagentModel', '');
|
|
458
|
-
await this.configManager.set('guiSubagentBaseUrl', '');
|
|
459
|
-
await this.configManager.set('guiSubagentApiKey', '');
|
|
460
|
-
await this.configManager.save('global');
|
|
461
|
-
console.log(chalk.green('✅ VLM configuration removed successfully!'));
|
|
612
|
+
this.configManager.save('global');
|
|
462
613
|
}
|
|
614
|
+
else {
|
|
615
|
+
console.log(chalk.yellow(' ⚠️ Use /auth to configure remote mode first.'));
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
// Get RemoteAIClient instance (from InteractiveSession) for model selection
|
|
620
|
+
const remoteClient = this.remoteAIClient;
|
|
621
|
+
// Display current configuration
|
|
622
|
+
console.log(chalk.cyan('\n📊 Current Model Configuration:\n'));
|
|
623
|
+
console.log(` ${chalk.yellow('LLM Model:')} ${currentLlm || 'Not set'}`);
|
|
624
|
+
console.log(` ${chalk.yellow('VLM Model:')} ${currentVlm || 'Not set'}`);
|
|
625
|
+
console.log('');
|
|
626
|
+
// Main menu
|
|
627
|
+
const action = await select({
|
|
628
|
+
message: 'Select action:',
|
|
629
|
+
options: [
|
|
630
|
+
{ value: 'llm', label: 'Change LLM model' },
|
|
631
|
+
{ value: 'vlm', label: 'Change VLM model' },
|
|
632
|
+
{ value: 'back', label: 'Back' },
|
|
633
|
+
],
|
|
634
|
+
});
|
|
635
|
+
if (action === 'back' || typeof action === 'symbol') {
|
|
463
636
|
return;
|
|
464
637
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
638
|
+
// Restore stdin raw mode after @clack/prompts interaction
|
|
639
|
+
ensureTtySane();
|
|
640
|
+
// Get and display provider list
|
|
641
|
+
try {
|
|
642
|
+
const models = await remoteClient.getRemoteModels();
|
|
643
|
+
const modelList = action === 'llm' ? models.llm : models.vlm;
|
|
644
|
+
if (modelList.length === 0) {
|
|
645
|
+
console.log(chalk.yellow('\n⚠️ No models available.'));
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
// Build choice list
|
|
649
|
+
const choices = modelList.map((m) => ({
|
|
650
|
+
name: `${m.displayName} (${m.name})`,
|
|
651
|
+
value: m.name
|
|
652
|
+
}));
|
|
653
|
+
const selectedModel = await select({
|
|
654
|
+
message: action === 'llm' ? 'Select LLM Model:' : 'Select VLM Model:',
|
|
655
|
+
options: choices
|
|
472
656
|
});
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
console.log(chalk.cyan(
|
|
657
|
+
if (typeof selectedModel !== 'string') {
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
const configKey = action === 'llm' ? 'remote_llmModelName' : 'remote_vlmModelName';
|
|
661
|
+
this.configManager.set(configKey, selectedModel);
|
|
662
|
+
this.configManager.save('global');
|
|
663
|
+
// Clear conversation history to avoid tool call ID conflicts between providers
|
|
664
|
+
if (this.onClearCallback) {
|
|
665
|
+
this.onClearCallback();
|
|
666
|
+
console.log(chalk.cyan(' Conversation cleared to avoid tool call ID conflicts between models.'));
|
|
667
|
+
}
|
|
668
|
+
// Notify InteractiveSession to update aiClient config
|
|
669
|
+
if (this.onConfigUpdate) {
|
|
670
|
+
this.onConfigUpdate();
|
|
671
|
+
}
|
|
672
|
+
console.log(chalk.green('\n✅ Model updated successfully!'));
|
|
673
|
+
console.log(` ${action === 'llm' ? 'LLM' : 'VLM'}: ${selectedModel}`);
|
|
674
|
+
}
|
|
675
|
+
catch (error) {
|
|
676
|
+
console.log(chalk.red(`\n❌ Failed to get models: ${error.message}`));
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Handle /model command for local mode - Configure third-party API directly
|
|
681
|
+
* Reuses code from initial setup flow (authenticateWithOpenAICompatible and configureAndValidateVLM)
|
|
682
|
+
*/
|
|
683
|
+
async handleLocalModel() {
|
|
684
|
+
// Display current configuration
|
|
685
|
+
const currentLlmModel = this.configManager.get('modelName') || this.configManager.getAuthConfig().modelName;
|
|
686
|
+
const currentVlmModel = this.configManager.get('guiSubagentModel');
|
|
687
|
+
console.log(chalk.cyan('\n📊 Current Local Model Configuration:\n'));
|
|
688
|
+
console.log(` ${chalk.yellow('LLM Model:')} ${currentLlmModel || 'Not set'}`);
|
|
689
|
+
console.log(` ${chalk.yellow('VLM Model:')} ${currentVlmModel || 'Not set'}`);
|
|
690
|
+
console.log('');
|
|
691
|
+
// Main menu - choose to configure LLM or VLM
|
|
692
|
+
const action = await select({
|
|
693
|
+
message: 'Select action:',
|
|
694
|
+
options: [
|
|
695
|
+
{ value: 'llm', label: 'Change LLM (select provider and API)' },
|
|
696
|
+
{ value: 'vlm', label: 'Change VLM (for GUI automation)' },
|
|
697
|
+
{ value: 'back', label: 'Back' },
|
|
698
|
+
],
|
|
699
|
+
});
|
|
700
|
+
if (action === 'back' || typeof action === 'symbol') {
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
if (action === 'llm') {
|
|
704
|
+
await this.configureLocalLLM();
|
|
705
|
+
}
|
|
706
|
+
else if (action === 'vlm') {
|
|
707
|
+
await this.configureLocalVLM();
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Configure LLM for local mode - Reuses authenticateWithOpenAICompatible logic
|
|
712
|
+
*/
|
|
713
|
+
async configureLocalLLM() {
|
|
714
|
+
// THIRD_PARTY_PROVIDERS already imported at top level
|
|
715
|
+
const provider = await select({
|
|
716
|
+
message: 'Select third-party model provider:',
|
|
717
|
+
options: THIRD_PARTY_PROVIDERS.map((p) => ({
|
|
718
|
+
value: p,
|
|
719
|
+
label: `${p.name} - ${p.description}`,
|
|
720
|
+
})),
|
|
721
|
+
});
|
|
722
|
+
if (typeof provider === 'symbol') {
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
const selectedProvider = provider;
|
|
726
|
+
let baseUrl = selectedProvider.baseUrl;
|
|
727
|
+
let modelName = selectedProvider.defaultModel;
|
|
728
|
+
if (selectedProvider.name === 'Custom') {
|
|
729
|
+
baseUrl = (await import('@clack/prompts').then(m => m.text({
|
|
730
|
+
message: 'Enter API Base URL:',
|
|
731
|
+
defaultValue: 'https://api.openai.com/v1',
|
|
732
|
+
validate: (value) => {
|
|
733
|
+
if (!value || value.trim().length === 0) {
|
|
734
|
+
return 'Base URL cannot be empty';
|
|
735
|
+
}
|
|
736
|
+
return undefined;
|
|
737
|
+
},
|
|
738
|
+
})));
|
|
739
|
+
modelName = (await import('@clack/prompts').then(m => m.text({
|
|
740
|
+
message: 'Enter model name:',
|
|
741
|
+
defaultValue: 'gpt-4',
|
|
742
|
+
validate: (value) => {
|
|
743
|
+
if (!value || value.trim().length === 0) {
|
|
744
|
+
return 'Model name cannot be empty';
|
|
745
|
+
}
|
|
746
|
+
return undefined;
|
|
747
|
+
},
|
|
748
|
+
})));
|
|
749
|
+
baseUrl = baseUrl.trim();
|
|
750
|
+
modelName = modelName.trim();
|
|
751
|
+
}
|
|
752
|
+
else {
|
|
753
|
+
console.log(chalk.cyan(`\nSelected: ${selectedProvider.name}`));
|
|
754
|
+
console.log(chalk.cyan(`API URL: ${baseUrl}`));
|
|
755
|
+
if (selectedProvider.models && selectedProvider.models.length > 0) {
|
|
756
|
+
console.log(chalk.cyan(`Available models: ${selectedProvider.models.join(', ')}`));
|
|
757
|
+
const selectedModel = await select({
|
|
758
|
+
message: 'Select model:',
|
|
759
|
+
options: selectedProvider.models.map((model) => ({
|
|
760
|
+
value: model,
|
|
761
|
+
label: model === selectedProvider.defaultModel ? `${model} (default)` : model,
|
|
762
|
+
})),
|
|
763
|
+
});
|
|
764
|
+
if (typeof selectedModel === 'symbol') {
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
modelName = selectedModel;
|
|
483
768
|
}
|
|
484
769
|
else {
|
|
485
|
-
console.log(chalk.
|
|
770
|
+
console.log(chalk.cyan(`Default model: ${modelName}`));
|
|
771
|
+
const confirmModel = (await import('@clack/prompts').then(m => m.text({
|
|
772
|
+
message: `Enter model name (press Enter to use default value ${modelName}):`,
|
|
773
|
+
defaultValue: modelName,
|
|
774
|
+
validate: (value) => {
|
|
775
|
+
if (!value || value.trim().length === 0) {
|
|
776
|
+
return 'Model name cannot be empty';
|
|
777
|
+
}
|
|
778
|
+
return undefined;
|
|
779
|
+
},
|
|
780
|
+
})));
|
|
781
|
+
modelName = confirmModel.trim();
|
|
486
782
|
}
|
|
487
783
|
}
|
|
784
|
+
const apiKey = (await import('@clack/prompts').then(m => m.password({
|
|
785
|
+
message: `Enter ${selectedProvider.name} API Key:`,
|
|
786
|
+
validate: (value) => {
|
|
787
|
+
if (!value || value.trim().length === 0) {
|
|
788
|
+
return 'API Key cannot be empty';
|
|
789
|
+
}
|
|
790
|
+
return undefined;
|
|
791
|
+
},
|
|
792
|
+
})));
|
|
793
|
+
// Update config
|
|
794
|
+
this.configManager.set('baseUrl', baseUrl);
|
|
795
|
+
this.configManager.set('apiKey', apiKey.trim());
|
|
796
|
+
this.configManager.set('modelName', modelName);
|
|
797
|
+
this.configManager.save('global');
|
|
798
|
+
console.log(chalk.green('\n✅ LLM configuration updated successfully!'));
|
|
799
|
+
console.log(chalk.cyan(` Provider: ${selectedProvider.name}`));
|
|
800
|
+
console.log(chalk.cyan(` Model: ${modelName}`));
|
|
801
|
+
console.log(chalk.cyan(` API URL: ${baseUrl}`));
|
|
802
|
+
// Clear conversation and notify config update
|
|
803
|
+
if (this.onClearCallback) {
|
|
804
|
+
this.onClearCallback();
|
|
805
|
+
}
|
|
806
|
+
if (this.onConfigUpdate) {
|
|
807
|
+
this.onConfigUpdate();
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Configure VLM for local mode - Select provider and modelName (baseUrl from VLM_PROVIDERS)
|
|
812
|
+
*/
|
|
813
|
+
async configureLocalVLM() {
|
|
814
|
+
// Get current VLM config
|
|
815
|
+
const currentModel = this.configManager.get('guiSubagentModel');
|
|
816
|
+
const currentBaseUrl = this.configManager.get('guiSubagentBaseUrl');
|
|
817
|
+
console.log(chalk.cyan('\n📊 Current VLM Configuration:\n'));
|
|
818
|
+
console.log(` ${chalk.yellow('Model:')} ${currentModel || 'Not set'}`);
|
|
819
|
+
console.log(` ${chalk.yellow('Base URL:')} ${currentBaseUrl || 'Not set'}`);
|
|
820
|
+
console.log('');
|
|
821
|
+
// Step 1: Select VLM provider
|
|
822
|
+
const provider = await select({
|
|
823
|
+
message: 'Select VLM provider:',
|
|
824
|
+
options: VLM_PROVIDERS.map((p) => ({
|
|
825
|
+
value: p,
|
|
826
|
+
label: `${p.name} - ${p.defaultModel}`,
|
|
827
|
+
})),
|
|
828
|
+
});
|
|
829
|
+
// User cancelled
|
|
830
|
+
if (typeof provider === 'symbol') {
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
const selectedProvider = provider;
|
|
834
|
+
// Step 2: Select model from provider's models list
|
|
835
|
+
const model = await select({
|
|
836
|
+
message: 'Select VLM Model:',
|
|
837
|
+
options: selectedProvider.models.map((m) => ({
|
|
838
|
+
value: m,
|
|
839
|
+
label: m,
|
|
840
|
+
})),
|
|
841
|
+
});
|
|
842
|
+
// User cancelled
|
|
843
|
+
if (typeof model === 'symbol') {
|
|
844
|
+
return;
|
|
845
|
+
}
|
|
846
|
+
// Step 3: Get API Key
|
|
847
|
+
const apiKey = (await text({
|
|
848
|
+
message: `Enter ${selectedProvider.name} API Key:`,
|
|
849
|
+
validate: (value) => {
|
|
850
|
+
if (!value || value.trim().length === 0) {
|
|
851
|
+
return 'API Key cannot be empty';
|
|
852
|
+
}
|
|
853
|
+
return undefined;
|
|
854
|
+
},
|
|
855
|
+
}));
|
|
856
|
+
// Save configuration
|
|
857
|
+
this.configManager.set('guiSubagentModel', model);
|
|
858
|
+
this.configManager.set('guiSubagentBaseUrl', selectedProvider.baseUrl);
|
|
859
|
+
this.configManager.set('guiSubagentApiKey', apiKey);
|
|
860
|
+
this.configManager.save('global');
|
|
861
|
+
console.log(chalk.green('\n✅ VLM configuration updated successfully!'));
|
|
862
|
+
console.log(chalk.cyan(` Provider: ${selectedProvider.name}`));
|
|
863
|
+
console.log(chalk.cyan(` Model: ${model}`));
|
|
864
|
+
console.log(chalk.cyan(` Base URL: ${selectedProvider.baseUrl}`));
|
|
865
|
+
// Notify config update
|
|
866
|
+
if (this.onConfigUpdate) {
|
|
867
|
+
this.onConfigUpdate();
|
|
868
|
+
}
|
|
488
869
|
}
|
|
489
870
|
async handleMode(args) {
|
|
490
871
|
const modes = Object.values(ExecutionMode);
|
|
@@ -493,7 +874,7 @@ export class SlashCommandHandler {
|
|
|
493
874
|
const newMode = args[0].toLowerCase();
|
|
494
875
|
if (modes.includes(newMode)) {
|
|
495
876
|
this.configManager.setApprovalMode(newMode);
|
|
496
|
-
|
|
877
|
+
this.configManager.save('global');
|
|
497
878
|
console.log(chalk.green(`✅ Approval mode changed to: ${newMode}`));
|
|
498
879
|
}
|
|
499
880
|
else {
|
|
@@ -509,7 +890,7 @@ export class SlashCommandHandler {
|
|
|
509
890
|
{ mode: 'accept_edits', desc: 'Accept all edits automatically' },
|
|
510
891
|
{ mode: 'plan', desc: 'Plan before executing' },
|
|
511
892
|
{ mode: 'default', desc: 'Safe execution with confirmations' },
|
|
512
|
-
{ mode: 'smart', desc: 'Smart approval with intelligent security checks' }
|
|
893
|
+
{ mode: 'smart', desc: 'Smart approval with intelligent security checks' },
|
|
513
894
|
];
|
|
514
895
|
descriptions.forEach(({ mode, desc }) => {
|
|
515
896
|
const current = mode === currentMode ? chalk.green(' [current]') : '';
|
|
@@ -526,13 +907,13 @@ export class SlashCommandHandler {
|
|
|
526
907
|
if (action === 'on' || action === 'true' || action === '1') {
|
|
527
908
|
thinkingConfig.enabled = true;
|
|
528
909
|
this.configManager.setThinkingConfig(thinkingConfig);
|
|
529
|
-
|
|
910
|
+
this.configManager.save('global');
|
|
530
911
|
console.log(chalk.green('✅ Thinking mode enabled'));
|
|
531
912
|
}
|
|
532
913
|
else if (action === 'off' || action === 'false' || action === '0') {
|
|
533
914
|
thinkingConfig.enabled = false;
|
|
534
915
|
this.configManager.setThinkingConfig(thinkingConfig);
|
|
535
|
-
|
|
916
|
+
this.configManager.save('global');
|
|
536
917
|
console.log(chalk.green('✅ Thinking mode disabled'));
|
|
537
918
|
}
|
|
538
919
|
else if (action === 'display' && args[1]) {
|
|
@@ -540,9 +921,9 @@ export class SlashCommandHandler {
|
|
|
540
921
|
const validModes = ['full', 'compact', 'indicator'];
|
|
541
922
|
if (validModes.includes(displayMode)) {
|
|
542
923
|
thinkingConfig.displayMode = displayMode;
|
|
543
|
-
thinkingConfig.enabled = true;
|
|
924
|
+
thinkingConfig.enabled = true;
|
|
544
925
|
this.configManager.setThinkingConfig(thinkingConfig);
|
|
545
|
-
|
|
926
|
+
this.configManager.save('global');
|
|
546
927
|
console.log(chalk.green(`✅ Thinking display mode set to: ${displayMode}`));
|
|
547
928
|
}
|
|
548
929
|
else {
|
|
@@ -650,7 +1031,9 @@ export class SlashCommandHandler {
|
|
|
650
1031
|
const status = isConnected ? chalk.green('✓ Connected') : chalk.red('✗ Disconnected');
|
|
651
1032
|
const tools = server?.getToolNames() || [];
|
|
652
1033
|
const transport = serverConfig?.transport || serverConfig?.type || 'unknown';
|
|
653
|
-
const command = serverConfig?.command
|
|
1034
|
+
const command = serverConfig?.command
|
|
1035
|
+
? `${serverConfig.command} ${(serverConfig.args || []).join(' ')}`
|
|
1036
|
+
: serverConfig?.url || 'N/A';
|
|
654
1037
|
console.log('');
|
|
655
1038
|
console.log(` ${chalk.cyan(serverName)} ${status}`);
|
|
656
1039
|
console.log(` Transport: ${transport}`);
|
|
@@ -661,80 +1044,87 @@ export class SlashCommandHandler {
|
|
|
661
1044
|
logger.info(`Total: ${serverConfigs.length} server(s)`);
|
|
662
1045
|
}
|
|
663
1046
|
async addMcpServerInteractive(serverName) {
|
|
664
|
-
const
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
validate: (input) => {
|
|
671
|
-
if (!input.trim()) {
|
|
672
|
-
return 'Server name is required';
|
|
673
|
-
}
|
|
674
|
-
const servers = this.mcpManager.getAllServers();
|
|
675
|
-
if (servers.some((s) => s.config?.name === input)) {
|
|
676
|
-
return 'Server with this name already exists';
|
|
677
|
-
}
|
|
678
|
-
return true;
|
|
1047
|
+
const name = (await text({
|
|
1048
|
+
message: 'Enter MCP server name:',
|
|
1049
|
+
defaultValue: serverName,
|
|
1050
|
+
validate: (value) => {
|
|
1051
|
+
if (!value || !value.trim()) {
|
|
1052
|
+
return 'Server name is required';
|
|
679
1053
|
}
|
|
1054
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(value)) {
|
|
1055
|
+
return 'Server name must contain only alphanumeric characters, hyphens, and underscores';
|
|
1056
|
+
}
|
|
1057
|
+
const servers = this.mcpManager.getAllServers();
|
|
1058
|
+
if (servers.some((s) => s.config?.name === value)) {
|
|
1059
|
+
return 'Server with this name already exists';
|
|
1060
|
+
}
|
|
1061
|
+
return undefined;
|
|
680
1062
|
},
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
1063
|
+
}));
|
|
1064
|
+
const transport = await select({
|
|
1065
|
+
message: 'Select transport type:',
|
|
1066
|
+
options: [
|
|
1067
|
+
{ value: 'stdio', label: 'Stdio (stdin/stdout)' },
|
|
1068
|
+
{ value: 'sse', label: 'HTTP/SSE' },
|
|
1069
|
+
{ value: 'http', label: 'HTTP (POST)' },
|
|
1070
|
+
],
|
|
1071
|
+
});
|
|
1072
|
+
if (typeof transport === 'symbol') {
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
let command = '';
|
|
1076
|
+
let serverArgs = [];
|
|
1077
|
+
let url = '';
|
|
1078
|
+
let authToken = '';
|
|
1079
|
+
let headers;
|
|
1080
|
+
if (transport === 'stdio') {
|
|
1081
|
+
command = (await text({
|
|
695
1082
|
message: 'Enter command (for stdio transport):',
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
{
|
|
700
|
-
type: 'input',
|
|
701
|
-
name: 'args',
|
|
1083
|
+
validate: (value) => value && value.trim() ? undefined : 'Command is required',
|
|
1084
|
+
}));
|
|
1085
|
+
const argsInput = (await text({
|
|
702
1086
|
message: 'Enter arguments (comma-separated, for stdio transport):',
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
1087
|
+
defaultValue: '',
|
|
1088
|
+
}));
|
|
1089
|
+
if (argsInput.trim()) {
|
|
1090
|
+
serverArgs = argsInput.split(',').map((a) => a.trim());
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
else {
|
|
1094
|
+
url = (await text({
|
|
709
1095
|
message: 'Enter server URL (for HTTP/SSE/HTTP transport):',
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
type: 'password',
|
|
715
|
-
name: 'authToken',
|
|
716
|
-
message: 'Enter authentication token (optional):',
|
|
717
|
-
when: (answers) => answers.transport === 'sse' || answers.transport === 'http'
|
|
718
|
-
},
|
|
719
|
-
{
|
|
720
|
-
type: 'input',
|
|
721
|
-
name: 'headers',
|
|
722
|
-
message: 'Enter custom headers as JSON (optional, e.g., {"Authorization": "Bearer token"}):',
|
|
723
|
-
when: (answers) => answers.transport === 'sse' || answers.transport === 'http',
|
|
724
|
-
filter: (input) => {
|
|
725
|
-
if (!input.trim())
|
|
726
|
-
return undefined;
|
|
1096
|
+
validate: (value) => {
|
|
1097
|
+
if (!value || !value.trim()) {
|
|
1098
|
+
return 'URL is required';
|
|
1099
|
+
}
|
|
727
1100
|
try {
|
|
728
|
-
|
|
1101
|
+
new URL(value);
|
|
1102
|
+
return undefined;
|
|
729
1103
|
}
|
|
730
1104
|
catch {
|
|
731
|
-
return
|
|
1105
|
+
return 'Invalid URL format (e.g., https://example.com)';
|
|
732
1106
|
}
|
|
1107
|
+
},
|
|
1108
|
+
}));
|
|
1109
|
+
authToken = (await text({
|
|
1110
|
+
message: 'Enter authentication token (optional):',
|
|
1111
|
+
defaultValue: '',
|
|
1112
|
+
}));
|
|
1113
|
+
const headersInput = (await text({
|
|
1114
|
+
message: 'Enter custom headers as JSON (optional, e.g., {"Authorization": "Bearer token"}):',
|
|
1115
|
+
defaultValue: '',
|
|
1116
|
+
}));
|
|
1117
|
+
if (headersInput.trim()) {
|
|
1118
|
+
try {
|
|
1119
|
+
headers = JSON.parse(headersInput);
|
|
1120
|
+
}
|
|
1121
|
+
catch {
|
|
1122
|
+
headers = undefined;
|
|
733
1123
|
}
|
|
734
1124
|
}
|
|
735
|
-
|
|
1125
|
+
}
|
|
736
1126
|
const config = {
|
|
737
|
-
transport: transport
|
|
1127
|
+
transport: transport,
|
|
738
1128
|
};
|
|
739
1129
|
if (transport === 'stdio') {
|
|
740
1130
|
config.command = command;
|
|
@@ -744,30 +1134,37 @@ export class SlashCommandHandler {
|
|
|
744
1134
|
}
|
|
745
1135
|
else {
|
|
746
1136
|
config.url = url;
|
|
747
|
-
|
|
748
|
-
|
|
1137
|
+
// Handle user input that mistakenly puts Bearer token in headers field
|
|
1138
|
+
// Detect pattern: headers looks like "Bearer xxx.yyy.zzz" (JWT token)
|
|
1139
|
+
let resolvedAuthToken = authToken;
|
|
1140
|
+
let resolvedHeaders = headers;
|
|
1141
|
+
if (headers && typeof headers === 'string' && !authToken) {
|
|
1142
|
+
const trimmedHeaders = headers.trim();
|
|
1143
|
+
if (trimmedHeaders.startsWith('Bearer ') && trimmedHeaders.split('.').length === 3) {
|
|
1144
|
+
// User mistakenly put token in headers field - extract it
|
|
1145
|
+
resolvedAuthToken = trimmedHeaders;
|
|
1146
|
+
resolvedHeaders = undefined;
|
|
1147
|
+
console.log('[MCP] Note: Detected Bearer token in headers field, moved to authToken');
|
|
1148
|
+
}
|
|
749
1149
|
}
|
|
750
|
-
if (
|
|
751
|
-
config.
|
|
1150
|
+
if (resolvedAuthToken) {
|
|
1151
|
+
config.authToken = resolvedAuthToken;
|
|
1152
|
+
}
|
|
1153
|
+
if (resolvedHeaders) {
|
|
1154
|
+
config.headers = resolvedHeaders;
|
|
752
1155
|
}
|
|
753
1156
|
}
|
|
754
1157
|
try {
|
|
755
|
-
// Save to config file
|
|
756
1158
|
this.configManager.addMcpServer(name, config);
|
|
757
|
-
|
|
758
|
-
// Register to MCP Manager
|
|
1159
|
+
this.configManager.save('global');
|
|
759
1160
|
this.mcpManager.registerServer(name, config);
|
|
760
|
-
// Connect to server (with error handling)
|
|
761
|
-
let connected = false;
|
|
762
1161
|
try {
|
|
763
1162
|
await this.mcpManager.connectServer(name);
|
|
764
|
-
connected = true;
|
|
765
1163
|
}
|
|
766
1164
|
catch (error) {
|
|
767
|
-
// Connection failed - cleanup
|
|
768
1165
|
this.mcpManager.disconnectServer(name);
|
|
769
1166
|
this.configManager.removeMcpServer(name);
|
|
770
|
-
|
|
1167
|
+
this.configManager.save('global');
|
|
771
1168
|
throw new Error(`Connection failed: ${error.message}`);
|
|
772
1169
|
}
|
|
773
1170
|
// Register MCP tools with simple names
|
|
@@ -790,30 +1187,25 @@ export class SlashCommandHandler {
|
|
|
790
1187
|
logger.warn('No MCP servers configured', 'Use /mcp add to add servers');
|
|
791
1188
|
return;
|
|
792
1189
|
}
|
|
793
|
-
const
|
|
1190
|
+
const serverOptions = servers.map((s) => {
|
|
794
1191
|
const tools = s.getToolNames();
|
|
795
1192
|
const status = s.isServerConnected() ? '✓' : '✗';
|
|
796
1193
|
return {
|
|
797
|
-
|
|
798
|
-
|
|
1194
|
+
value: s.config?.name,
|
|
1195
|
+
label: `${status} ${s.config?.name || 'unknown'} (${tools.length} tools)`,
|
|
799
1196
|
};
|
|
800
1197
|
});
|
|
801
|
-
const
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
]);
|
|
1198
|
+
const serverName = (await select({
|
|
1199
|
+
message: 'Select MCP server to remove:',
|
|
1200
|
+
options: serverOptions,
|
|
1201
|
+
}));
|
|
1202
|
+
if (typeof serverName === 'symbol') {
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
809
1205
|
await this.removeMcpServer(serverName);
|
|
810
1206
|
}
|
|
811
1207
|
async removeMcpServer(serverName) {
|
|
812
1208
|
try {
|
|
813
|
-
// Get server info before disconnecting to notify LLM
|
|
814
|
-
const server = this.mcpManager.getServer(serverName);
|
|
815
|
-
const removedTools = server ? server.getToolNames() : [];
|
|
816
|
-
const removedToolNames = removedTools.map((t) => `${serverName}__${t}`).join(', ');
|
|
817
1209
|
// Disconnect
|
|
818
1210
|
this.mcpManager.disconnectServer(serverName);
|
|
819
1211
|
// Unregister MCP tools for this server
|
|
@@ -821,7 +1213,7 @@ export class SlashCommandHandler {
|
|
|
821
1213
|
toolRegistry.unregisterMCPTools(serverName);
|
|
822
1214
|
// Remove from config
|
|
823
1215
|
this.configManager.removeMcpServer(serverName);
|
|
824
|
-
|
|
1216
|
+
this.configManager.save('global');
|
|
825
1217
|
// Update system prompt to reflect removed MCP tools
|
|
826
1218
|
if (this.onSystemPromptUpdate) {
|
|
827
1219
|
await this.onSystemPromptUpdate();
|
|
@@ -914,8 +1306,7 @@ export class SlashCommandHandler {
|
|
|
914
1306
|
return;
|
|
915
1307
|
}
|
|
916
1308
|
// Clear specific file by filename or path
|
|
917
|
-
const targetMemory = memoryFiles.find((m) => path.basename(m.path) === target ||
|
|
918
|
-
m.path === target);
|
|
1309
|
+
const targetMemory = memoryFiles.find((m) => path.basename(m.path) === target || m.path === target);
|
|
919
1310
|
if (targetMemory) {
|
|
920
1311
|
try {
|
|
921
1312
|
await fs.unlink(targetMemory.path);
|
|
@@ -949,22 +1340,20 @@ export class SlashCommandHandler {
|
|
|
949
1340
|
logger.info(`Directory: ${memoriesDir}`);
|
|
950
1341
|
console.log('');
|
|
951
1342
|
memoryFiles.forEach((file) => {
|
|
952
|
-
const level = file.level === 'global'
|
|
953
|
-
|
|
954
|
-
|
|
1343
|
+
const level = file.level === 'global'
|
|
1344
|
+
? chalk.blue('[global]')
|
|
1345
|
+
: file.level === 'project'
|
|
1346
|
+
? chalk.green('[project]')
|
|
1347
|
+
: chalk.yellow('[subdirectory]');
|
|
955
1348
|
logger.info(` ${level} ${path.basename(file.path)}`);
|
|
956
1349
|
});
|
|
957
1350
|
console.log('');
|
|
958
1351
|
// logger.info('Usage: /memory clear [global|current|all|<filename>]');
|
|
959
1352
|
}
|
|
960
1353
|
async addMemory() {
|
|
961
|
-
const
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
name: 'entry',
|
|
965
|
-
message: 'Enter memory entry (opens editor):'
|
|
966
|
-
}
|
|
967
|
-
]);
|
|
1354
|
+
const entry = (await text({
|
|
1355
|
+
message: 'Enter memory entry (opens editor):',
|
|
1356
|
+
}));
|
|
968
1357
|
if (entry && entry.trim()) {
|
|
969
1358
|
await this.memoryManager.addMemoryEntry(entry.trim());
|
|
970
1359
|
console.log(chalk.green('✅ Memory entry added'));
|
|
@@ -1001,18 +1390,17 @@ export class SlashCommandHandler {
|
|
|
1001
1390
|
}
|
|
1002
1391
|
}
|
|
1003
1392
|
else {
|
|
1004
|
-
const
|
|
1005
|
-
|
|
1006
|
-
|
|
1393
|
+
const checkpointOptions = checkpoints.map((cp) => ({
|
|
1394
|
+
value: cp.id,
|
|
1395
|
+
label: `${new Date(cp.timestamp).toLocaleString()} - ${cp.description}`,
|
|
1007
1396
|
}));
|
|
1008
|
-
const
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
]);
|
|
1397
|
+
const checkpointId = await select({
|
|
1398
|
+
message: 'Select checkpoint to restore:',
|
|
1399
|
+
options: checkpointOptions,
|
|
1400
|
+
});
|
|
1401
|
+
if (typeof checkpointId === 'symbol') {
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1016
1404
|
try {
|
|
1017
1405
|
await this.checkpointManager.restoreCheckpoint(checkpointId);
|
|
1018
1406
|
logger.success(`Checkpoint ${checkpointId} restored successfully!`);
|
|
@@ -1026,7 +1414,7 @@ export class SlashCommandHandler {
|
|
|
1026
1414
|
const toolRegistry = getToolRegistry();
|
|
1027
1415
|
const tools = toolRegistry.getAll();
|
|
1028
1416
|
logger.section('Available Tools');
|
|
1029
|
-
tools.forEach(tool => {
|
|
1417
|
+
tools.forEach((tool) => {
|
|
1030
1418
|
logger.info(` ${tool.name}`);
|
|
1031
1419
|
logger.info(` ${tool.description}`);
|
|
1032
1420
|
});
|
|
@@ -1045,12 +1433,12 @@ export class SlashCommandHandler {
|
|
|
1045
1433
|
const mode = args[0].toLowerCase();
|
|
1046
1434
|
if (mode === 'verbose' || mode === 'detail' || mode === 'true' || mode === 'on') {
|
|
1047
1435
|
this.configManager.set('showToolDetails', true);
|
|
1048
|
-
|
|
1436
|
+
this.configManager.save('global');
|
|
1049
1437
|
logger.success('Tool display mode switched to verbose mode', 'Will show complete tool call information');
|
|
1050
1438
|
}
|
|
1051
1439
|
else if (mode === 'simple' || mode === 'concise' || mode === 'false' || mode === 'off') {
|
|
1052
1440
|
this.configManager.set('showToolDetails', false);
|
|
1053
|
-
|
|
1441
|
+
this.configManager.save('global');
|
|
1054
1442
|
logger.success('Tool display mode switched to simple mode', 'Only show tool execution status');
|
|
1055
1443
|
}
|
|
1056
1444
|
else {
|
|
@@ -1059,6 +1447,8 @@ export class SlashCommandHandler {
|
|
|
1059
1447
|
}
|
|
1060
1448
|
async handleStats() {
|
|
1061
1449
|
logger.section('Session Statistics');
|
|
1450
|
+
const authConfig = this.configManager.getAuthConfig();
|
|
1451
|
+
logger.info(` Base URL: ${authConfig.baseUrl}`);
|
|
1062
1452
|
logger.info(` Execution Mode: ${this.configManager.getExecutionMode()}`);
|
|
1063
1453
|
logger.info(` Language: ${this.configManager.getLanguage()}`);
|
|
1064
1454
|
logger.info(` Checkpointing: ${this.checkpointManager.isEnabled() ? 'Enabled' : 'Disabled'}`);
|
|
@@ -1069,17 +1459,16 @@ export class SlashCommandHandler {
|
|
|
1069
1459
|
logger.warn('Theme switching not implemented yet', 'Check back later for updates');
|
|
1070
1460
|
}
|
|
1071
1461
|
async handleLanguage() {
|
|
1072
|
-
const
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
]);
|
|
1462
|
+
const language = (await select({
|
|
1463
|
+
message: 'Select language:',
|
|
1464
|
+
options: [
|
|
1465
|
+
{ value: 'zh', label: 'Chinese' },
|
|
1466
|
+
{ value: 'en', label: 'English' },
|
|
1467
|
+
],
|
|
1468
|
+
}));
|
|
1469
|
+
if (typeof language === 'symbol') {
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1083
1472
|
this.configManager.setLanguage(language);
|
|
1084
1473
|
logger.success(`Language changed to: ${language === 'zh' ? 'Chinese' : 'English'}`, 'Restart CLI to apply changes');
|
|
1085
1474
|
}
|
|
@@ -1091,6 +1480,45 @@ export class SlashCommandHandler {
|
|
|
1091
1480
|
logger.link('Documentation', 'https://platform.xagent.cn/');
|
|
1092
1481
|
logger.link('GitHub', 'https://github.com/xagent-ai/xagent-cli');
|
|
1093
1482
|
}
|
|
1483
|
+
async handleUpdate() {
|
|
1484
|
+
const separator = icons.separator.repeat(Math.min(40, process.stdout.columns || 80));
|
|
1485
|
+
console.log('');
|
|
1486
|
+
console.log(colors.primaryBright(`${icons.rocket} Update Check`));
|
|
1487
|
+
console.log(colors.border(separator));
|
|
1488
|
+
console.log('');
|
|
1489
|
+
try {
|
|
1490
|
+
const { getUpdateManager } = await import('./update.js');
|
|
1491
|
+
const updateManager = getUpdateManager();
|
|
1492
|
+
const versionInfo = await updateManager.checkForUpdates();
|
|
1493
|
+
console.log(` ${icons.info} ${colors.textMuted('Current version:')} ${colors.primaryBright(versionInfo.currentVersion)}`);
|
|
1494
|
+
console.log(` ${icons.code} ${colors.textMuted('Latest version:')} ${colors.primaryBright(versionInfo.latestVersion)}`);
|
|
1495
|
+
console.log('');
|
|
1496
|
+
if (versionInfo.updateAvailable) {
|
|
1497
|
+
console.log(colors.success(` 📦 A new version is available!`));
|
|
1498
|
+
console.log('');
|
|
1499
|
+
if (versionInfo.releaseNotes) {
|
|
1500
|
+
console.log(colors.textMuted(' Release Notes:'));
|
|
1501
|
+
console.log(colors.textDim(` ${versionInfo.releaseNotes}`));
|
|
1502
|
+
console.log('');
|
|
1503
|
+
}
|
|
1504
|
+
const shouldUpdate = await confirm({
|
|
1505
|
+
message: 'Do you want to update now?',
|
|
1506
|
+
});
|
|
1507
|
+
if (shouldUpdate === true) {
|
|
1508
|
+
console.log('');
|
|
1509
|
+
await updateManager.autoUpdate();
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
else {
|
|
1513
|
+
console.log(colors.success(` ✅ You are using the latest version`));
|
|
1514
|
+
console.log('');
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
catch (error) {
|
|
1518
|
+
console.log(colors.error(` ❌ Failed to check for updates: ${error.message}`));
|
|
1519
|
+
console.log('');
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1094
1522
|
async handleCompress(args) {
|
|
1095
1523
|
const config = this.configManager.getContextCompressionConfig();
|
|
1096
1524
|
// If there are arguments, process config or execute
|
|
@@ -1106,15 +1534,11 @@ export class SlashCommandHandler {
|
|
|
1106
1534
|
// Display current configuration
|
|
1107
1535
|
console.log(chalk.cyan('\n📦 Context Compression:\n'));
|
|
1108
1536
|
console.log(` Status: ${config.enabled ? chalk.green('Enabled') : chalk.red('Disabled')}`);
|
|
1109
|
-
console.log(` Max Messages: ${chalk.yellow(config.maxMessages.toString())}`);
|
|
1110
|
-
console.log(` Max Tokens: ${chalk.yellow(config.maxContextSize.toString())}`);
|
|
1111
1537
|
console.log('');
|
|
1112
1538
|
console.log(chalk.gray('Usage:'));
|
|
1113
1539
|
console.log(chalk.gray(' /compress - Show current configuration'));
|
|
1114
1540
|
console.log(chalk.gray(' /compress exec - Execute compression now'));
|
|
1115
1541
|
console.log(chalk.gray(' /compress on|off - Enable/disable compression'));
|
|
1116
|
-
console.log(chalk.gray(' /compress max_message <n> - Set max messages before compression'));
|
|
1117
|
-
console.log(chalk.gray(' /compress max_token <n> - Set max tokens before compression'));
|
|
1118
1542
|
console.log('');
|
|
1119
1543
|
}
|
|
1120
1544
|
async executeCompression(config) {
|
|
@@ -1133,7 +1557,7 @@ export class SlashCommandHandler {
|
|
|
1133
1557
|
const spinner = ora({
|
|
1134
1558
|
text: 'Compressing context...',
|
|
1135
1559
|
spinner: 'dots',
|
|
1136
|
-
color: 'cyan'
|
|
1560
|
+
color: 'cyan',
|
|
1137
1561
|
}).start();
|
|
1138
1562
|
try {
|
|
1139
1563
|
const result = await this.contextCompressor.compressContext(messages, 'You are a helpful AI assistant.', config);
|
|
@@ -1159,56 +1583,241 @@ export class SlashCommandHandler {
|
|
|
1159
1583
|
case 'on':
|
|
1160
1584
|
config.enabled = true;
|
|
1161
1585
|
this.configManager.setContextCompressionConfig(config);
|
|
1162
|
-
|
|
1586
|
+
this.configManager.save('global');
|
|
1163
1587
|
console.log(chalk.green('✅ Context compression enabled'));
|
|
1164
1588
|
break;
|
|
1165
1589
|
case 'off':
|
|
1166
1590
|
config.enabled = false;
|
|
1167
1591
|
this.configManager.setContextCompressionConfig(config);
|
|
1168
|
-
|
|
1592
|
+
this.configManager.save('global');
|
|
1169
1593
|
console.log(chalk.green('✅ Context compression disabled'));
|
|
1170
1594
|
break;
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1595
|
+
default:
|
|
1596
|
+
console.log(chalk.red(`❌ Unknown action: ${action}`));
|
|
1597
|
+
console.log(chalk.gray('Available actions: on, off, exec'));
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
async handleSkill(args) {
|
|
1601
|
+
const os = await import('os');
|
|
1602
|
+
const path = await import('path');
|
|
1603
|
+
const { promises: fs } = await import('fs');
|
|
1604
|
+
const action = args[0] || 'list';
|
|
1605
|
+
const userSkillsPath = this.configManager.getUserSkillsPath() || path.join(os.homedir(), '.xagent', 'skills');
|
|
1606
|
+
switch (action) {
|
|
1607
|
+
case 'list':
|
|
1608
|
+
await this.listUserSkills(userSkillsPath, fs, path);
|
|
1609
|
+
break;
|
|
1610
|
+
case 'add':
|
|
1611
|
+
await this.addSkill(args[1], userSkillsPath, fs, path);
|
|
1612
|
+
break;
|
|
1613
|
+
case 'remove':
|
|
1614
|
+
await this.removeSkill(args[1], userSkillsPath, fs, path);
|
|
1615
|
+
break;
|
|
1616
|
+
default:
|
|
1617
|
+
console.log(chalk.cyan('\n🔧 Skills:\n'));
|
|
1618
|
+
console.log(` Skills directory: ${chalk.yellow(userSkillsPath)}\n`);
|
|
1619
|
+
console.log(chalk.gray('Available commands:'));
|
|
1620
|
+
console.log(chalk.gray(' /skill list - List installed skills'));
|
|
1621
|
+
console.log(chalk.gray(' /skill add <source> - Add a skill (local path or remote URL)'));
|
|
1622
|
+
console.log(chalk.gray(' /skill remove <name> - Remove a user-installed skill'));
|
|
1623
|
+
console.log();
|
|
1624
|
+
console.log(chalk.gray('Examples:'));
|
|
1625
|
+
console.log(chalk.gray(' /skill add ./my-skill - Local path'));
|
|
1626
|
+
console.log(chalk.gray(' /skill add owner/repo - GitHub shorthand'));
|
|
1627
|
+
console.log(chalk.gray(' /skill add https://github.com/owner/repo - GitHub URL'));
|
|
1628
|
+
console.log();
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
async listUserSkills(userSkillsPath, fs, path) {
|
|
1632
|
+
console.log(chalk.cyan('\n🔧 Skills:\n'));
|
|
1633
|
+
try {
|
|
1634
|
+
const entries = await fs.readdir(userSkillsPath, { withFileTypes: true });
|
|
1635
|
+
const skills = entries.filter((e) => e.isDirectory());
|
|
1636
|
+
if (skills.length === 0) {
|
|
1637
|
+
console.log(chalk.gray(' No skills installed'));
|
|
1638
|
+
console.log(chalk.cyan('\n To add a skill, use:'));
|
|
1639
|
+
console.log(chalk.cyan(' /skill add <path-to-skill>\n'));
|
|
1640
|
+
return;
|
|
1641
|
+
}
|
|
1642
|
+
for (const skill of skills) {
|
|
1643
|
+
const skillPath = path.join(userSkillsPath, skill.name);
|
|
1644
|
+
const skillMdPath = path.join(skillPath, 'SKILL.md');
|
|
1645
|
+
try {
|
|
1646
|
+
const content = await fs.readFile(skillMdPath, 'utf-8');
|
|
1647
|
+
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
1648
|
+
const descMatch = content.match(/^description:\s*(.+)$/m);
|
|
1649
|
+
const name = nameMatch ? nameMatch[1].trim() : skill.name;
|
|
1650
|
+
const description = descMatch ? descMatch[1].trim() : 'No description';
|
|
1651
|
+
console.log(` ${chalk.cyan('•')} ${chalk.yellow(name)}`);
|
|
1652
|
+
console.log(` ${chalk.gray(description)}`);
|
|
1653
|
+
console.log();
|
|
1654
|
+
}
|
|
1655
|
+
catch {
|
|
1656
|
+
console.log(` ${chalk.cyan('•')} ${chalk.yellow(skill.name)}`);
|
|
1657
|
+
console.log(` ${chalk.gray('(Missing SKILL.md)')}`);
|
|
1658
|
+
console.log();
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
console.log(chalk.gray(` Skills directory: ${userSkillsPath}`));
|
|
1662
|
+
console.log();
|
|
1663
|
+
}
|
|
1664
|
+
catch (error) {
|
|
1665
|
+
if (error.code === 'ENOENT') {
|
|
1666
|
+
console.log(chalk.gray(' No skills installed'));
|
|
1667
|
+
console.log(chalk.cyan('\n To add a skill, use:'));
|
|
1668
|
+
console.log(chalk.cyan(' /skill add <path-to-skill>\n'));
|
|
1669
|
+
}
|
|
1670
|
+
else {
|
|
1671
|
+
console.log(chalk.red(` Error: ${error.message}`));
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
async addSkill(source, userSkillsPath, fs, path) {
|
|
1676
|
+
if (!source) {
|
|
1677
|
+
console.log(chalk.yellow('\n⚠️ Please specify a skill source'));
|
|
1678
|
+
console.log(chalk.cyan(' Usage: /skill add <source>\n'));
|
|
1679
|
+
console.log(chalk.gray(' Examples:'));
|
|
1680
|
+
console.log(chalk.gray(' /skill add ./my-skill - Local path'));
|
|
1681
|
+
console.log(chalk.gray(' /skill add owner/repo - GitHub shorthand'));
|
|
1682
|
+
console.log(chalk.gray(' /skill add https://github.com/owner/repo'));
|
|
1683
|
+
console.log();
|
|
1684
|
+
return;
|
|
1685
|
+
}
|
|
1686
|
+
const { parseSource, installSkill } = await import('./skill-installer.js');
|
|
1687
|
+
const parsed = parseSource(source.trim());
|
|
1688
|
+
const isLocal = parsed.type === 'local';
|
|
1689
|
+
if (isLocal) {
|
|
1690
|
+
// Local installation
|
|
1691
|
+
const resolvedPath = path.resolve(source);
|
|
1692
|
+
const skillName = path.basename(resolvedPath);
|
|
1693
|
+
const destPath = path.join(userSkillsPath, skillName);
|
|
1694
|
+
try {
|
|
1695
|
+
// Check if source exists
|
|
1696
|
+
await fs.access(resolvedPath);
|
|
1697
|
+
// Check if SKILL.md exists
|
|
1698
|
+
const skillMdPath = path.join(resolvedPath, 'SKILL.md');
|
|
1699
|
+
try {
|
|
1700
|
+
await fs.access(skillMdPath);
|
|
1701
|
+
}
|
|
1702
|
+
catch {
|
|
1703
|
+
console.log(chalk.red(`\n❌ SKILL.md not found in ${resolvedPath}`));
|
|
1704
|
+
console.log(chalk.gray(' Each skill must have a SKILL.md file\n'));
|
|
1705
|
+
return;
|
|
1706
|
+
}
|
|
1707
|
+
// Check if skill already exists
|
|
1708
|
+
try {
|
|
1709
|
+
await fs.access(destPath);
|
|
1710
|
+
console.log(chalk.yellow(`\n⚠️ Skill "${skillName}" already installed`));
|
|
1711
|
+
console.log(chalk.cyan(` Use: /skill remove ${skillName} to remove it first\n`));
|
|
1712
|
+
return;
|
|
1713
|
+
}
|
|
1714
|
+
catch {
|
|
1715
|
+
// Doesn't exist, proceed
|
|
1716
|
+
}
|
|
1717
|
+
// Ensure skills directory exists
|
|
1718
|
+
await fs.mkdir(userSkillsPath, { recursive: true });
|
|
1719
|
+
// Copy the skill
|
|
1720
|
+
await this.copyDirectory(resolvedPath, destPath);
|
|
1721
|
+
console.log(chalk.green('\n✅ Skill installed successfully'));
|
|
1722
|
+
console.log(chalk.gray(` Name: ${skillName}`));
|
|
1723
|
+
console.log(chalk.gray(` Location: ${destPath}`));
|
|
1724
|
+
console.log(chalk.gray(` Type: Local`));
|
|
1725
|
+
console.log();
|
|
1726
|
+
// Trigger system prompt update
|
|
1727
|
+
this.onSystemPromptUpdate?.();
|
|
1728
|
+
}
|
|
1729
|
+
catch (error) {
|
|
1730
|
+
if (error.code === 'ENOENT') {
|
|
1731
|
+
console.log(chalk.red(`\n❌ Skill not found: ${source}\n`));
|
|
1182
1732
|
}
|
|
1183
1733
|
else {
|
|
1184
|
-
console.log(chalk.
|
|
1734
|
+
console.log(chalk.red(`\n❌ Error installing skill: ${error.message}\n`));
|
|
1185
1735
|
}
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
console.log(chalk.green(
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
else {
|
|
1739
|
+
// Remote installation
|
|
1740
|
+
console.log(chalk.cyan('\n📦 Installing skill from remote source...\n'));
|
|
1741
|
+
console.log(chalk.gray(` Source: ${source}`));
|
|
1742
|
+
console.log(chalk.gray(` Type: Remote`));
|
|
1743
|
+
console.log();
|
|
1744
|
+
try {
|
|
1745
|
+
const result = await installSkill(source);
|
|
1746
|
+
if (result.success) {
|
|
1747
|
+
console.log(chalk.green('✅ Skill installed successfully'));
|
|
1748
|
+
console.log(chalk.gray(` Name: ${result.skillName}`));
|
|
1749
|
+
console.log(chalk.gray(` Location: ${result.skillPath}`));
|
|
1750
|
+
console.log(chalk.gray(' Type: Remote'));
|
|
1751
|
+
console.log();
|
|
1752
|
+
// Trigger system prompt update - skill is immediately available
|
|
1753
|
+
this.onSystemPromptUpdate?.();
|
|
1198
1754
|
}
|
|
1199
1755
|
else {
|
|
1200
|
-
console.log(chalk.
|
|
1756
|
+
console.log(chalk.red(`\n❌ Failed to install skill: ${result.error}\n`));
|
|
1201
1757
|
}
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
console.log(chalk.red(
|
|
1205
|
-
|
|
1758
|
+
}
|
|
1759
|
+
catch (error) {
|
|
1760
|
+
console.log(chalk.red(`\n❌ Error installing skill: ${error.message}\n`));
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
async removeSkill(skillName, userSkillsPath, fs, path) {
|
|
1765
|
+
if (!skillName) {
|
|
1766
|
+
console.log(chalk.yellow('\n⚠️ Please specify a skill name'));
|
|
1767
|
+
console.log(chalk.cyan(' Usage: /skill remove <skill-name>\n'));
|
|
1768
|
+
return;
|
|
1769
|
+
}
|
|
1770
|
+
// Protect find-skills from deletion
|
|
1771
|
+
if (skillName === 'find-skills') {
|
|
1772
|
+
console.log(chalk.red('\n❌ Cannot remove protected skill: find-skills'));
|
|
1773
|
+
console.log(chalk.gray(' find-skills is a built-in skill that helps you discover and install other skills.\n'));
|
|
1774
|
+
return;
|
|
1775
|
+
}
|
|
1776
|
+
const skillPath = path.join(userSkillsPath, skillName);
|
|
1777
|
+
try {
|
|
1778
|
+
await fs.access(skillPath);
|
|
1779
|
+
// Verify it's in skills path
|
|
1780
|
+
if (!skillPath.startsWith(userSkillsPath)) {
|
|
1781
|
+
console.log(chalk.red(`\n❌ Cannot remove skill outside user directory\n`));
|
|
1782
|
+
return;
|
|
1783
|
+
}
|
|
1784
|
+
// Remove the skill directory
|
|
1785
|
+
await fs.rm(skillPath, { recursive: true, force: true });
|
|
1786
|
+
console.log(chalk.green('\n✅ Skill removed successfully'));
|
|
1787
|
+
console.log();
|
|
1788
|
+
// Trigger system prompt update
|
|
1789
|
+
this.onSystemPromptUpdate?.();
|
|
1790
|
+
}
|
|
1791
|
+
catch (error) {
|
|
1792
|
+
if (error.code === 'ENOENT' || error.code === 'ENOENT') {
|
|
1793
|
+
console.log(chalk.yellow(`\n⚠️ Skill not found: ${skillName}\n`));
|
|
1794
|
+
}
|
|
1795
|
+
else {
|
|
1796
|
+
console.log(chalk.red(`\n❌ Error removing skill: ${error.message}\n`));
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
async copyDirectory(src, dest) {
|
|
1801
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
1802
|
+
await fs.mkdir(dest, { recursive: true });
|
|
1803
|
+
for (const entry of entries) {
|
|
1804
|
+
// Skip node_modules to keep dependencies isolated
|
|
1805
|
+
// if (entry.name === 'node_modules') continue;
|
|
1806
|
+
const srcPath = path.join(src, entry.name);
|
|
1807
|
+
const destPath = path.join(dest, entry.name);
|
|
1808
|
+
if (entry.isDirectory()) {
|
|
1809
|
+
await this.copyDirectory(srcPath, destPath);
|
|
1810
|
+
}
|
|
1811
|
+
else if (entry.isFile()) {
|
|
1812
|
+
await fs.copyFile(srcPath, destPath);
|
|
1813
|
+
}
|
|
1206
1814
|
}
|
|
1207
1815
|
}
|
|
1208
1816
|
}
|
|
1209
|
-
export function parseInput(input) {
|
|
1817
|
+
export async function parseInput(input) {
|
|
1210
1818
|
const inputs = [];
|
|
1211
1819
|
let remaining = input;
|
|
1820
|
+
// Match @ followed by any non-whitespace sequence
|
|
1212
1821
|
const fileRefRegex = /@([^\s]+)/g;
|
|
1213
1822
|
let match;
|
|
1214
1823
|
while ((match = fileRefRegex.exec(remaining)) !== null) {
|
|
@@ -1218,7 +1827,15 @@ export function parseInput(input) {
|
|
|
1218
1827
|
if (beforeMatch.trim()) {
|
|
1219
1828
|
inputs.push({ type: 'text', content: beforeMatch.trim() });
|
|
1220
1829
|
}
|
|
1221
|
-
|
|
1830
|
+
// Only treat as file reference if the file actually exists
|
|
1831
|
+
const exists = await fileExists(filePath);
|
|
1832
|
+
if (exists) {
|
|
1833
|
+
inputs.push({ type: 'file', content: filePath });
|
|
1834
|
+
}
|
|
1835
|
+
else {
|
|
1836
|
+
// Not a file, treat as regular text (preserving the @ symbol)
|
|
1837
|
+
inputs.push({ type: 'text', content: '@' + filePath });
|
|
1838
|
+
}
|
|
1222
1839
|
remaining = afterMatch;
|
|
1223
1840
|
}
|
|
1224
1841
|
if (remaining.trim()) {
|
|
@@ -1231,6 +1848,18 @@ export function parseInput(input) {
|
|
|
1231
1848
|
}
|
|
1232
1849
|
return inputs;
|
|
1233
1850
|
}
|
|
1851
|
+
// Helper function to check if a file path exists
|
|
1852
|
+
async function fileExists(filePath) {
|
|
1853
|
+
try {
|
|
1854
|
+
// Resolve to absolute path
|
|
1855
|
+
const absolutePath = path.resolve(filePath);
|
|
1856
|
+
await fs.access(absolutePath);
|
|
1857
|
+
return true;
|
|
1858
|
+
}
|
|
1859
|
+
catch {
|
|
1860
|
+
return false;
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1234
1863
|
export function detectImageInput(input) {
|
|
1235
1864
|
return input.includes('[Pasted image') || input.includes('<image');
|
|
1236
1865
|
}
|