@compilr-dev/cli 0.5.0 → 0.5.2
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/LICENSE +108 -0
- package/README.md +237 -69
- package/dist/.tsbuildinfo.app +1 -0
- package/dist/.tsbuildinfo.data +1 -0
- package/dist/.tsbuildinfo.domain +1 -0
- package/dist/.tsbuildinfo.foundation +1 -0
- package/dist/agent.d.ts +61 -4
- package/dist/agent.js +241 -245
- package/dist/anchors/index.d.ts +1 -1
- package/dist/anchors/index.js +1 -1
- package/dist/anchors/project-anchors.d.ts +2 -2
- package/dist/anchors/project-anchors.js +1 -1
- package/dist/auth/api-client.d.ts +124 -0
- package/dist/auth/api-client.js +261 -0
- package/dist/auth/index.d.ts +172 -0
- package/dist/auth/index.js +545 -0
- package/dist/auth/storage.d.ts +52 -0
- package/dist/auth/storage.js +118 -0
- package/dist/changelog/index.d.ts +16 -0
- package/dist/changelog/index.js +24 -0
- package/dist/changelog/releases.d.ts +17 -0
- package/dist/changelog/releases.js +63 -0
- package/dist/commands-v2/handlers/auth.d.ts +10 -0
- package/dist/commands-v2/handlers/auth.js +118 -0
- package/dist/commands-v2/handlers/background.d.ts +14 -0
- package/dist/commands-v2/handlers/background.js +276 -0
- package/dist/commands-v2/handlers/context.js +286 -81
- package/dist/commands-v2/handlers/core.d.ts +1 -0
- package/dist/commands-v2/handlers/core.js +133 -8
- package/dist/commands-v2/handlers/debug.js +18 -0
- package/dist/commands-v2/handlers/delegations.d.ts +8 -0
- package/dist/commands-v2/handlers/delegations.js +29 -0
- package/dist/commands-v2/handlers/files.d.ts +8 -0
- package/dist/commands-v2/handlers/files.js +162 -0
- package/dist/commands-v2/handlers/filter.d.ts +9 -0
- package/dist/commands-v2/handlers/filter.js +130 -0
- package/dist/commands-v2/handlers/games.d.ts +7 -0
- package/dist/commands-v2/handlers/games.js +57 -0
- package/dist/commands-v2/handlers/index.d.ts +13 -0
- package/dist/commands-v2/handlers/index.js +39 -0
- package/dist/commands-v2/handlers/mcp.d.ts +8 -0
- package/dist/commands-v2/handlers/mcp.js +39 -0
- package/dist/commands-v2/handlers/notifications.d.ts +9 -0
- package/dist/commands-v2/handlers/notifications.js +34 -0
- package/dist/commands-v2/handlers/project.js +295 -31
- package/dist/commands-v2/handlers/reset.d.ts +11 -0
- package/dist/commands-v2/handlers/reset.js +118 -0
- package/dist/commands-v2/handlers/session.d.ts +161 -0
- package/dist/commands-v2/handlers/session.js +805 -0
- package/dist/commands-v2/handlers/settings.d.ts +2 -0
- package/dist/commands-v2/handlers/settings.js +217 -35
- package/dist/commands-v2/handlers/tasks.d.ts +5 -0
- package/dist/commands-v2/handlers/tasks.js +36 -0
- package/dist/commands-v2/handlers/team.d.ts +9 -0
- package/dist/commands-v2/handlers/team.js +549 -0
- package/dist/commands-v2/handlers/terminals.d.ts +9 -0
- package/dist/commands-v2/handlers/terminals.js +34 -0
- package/dist/commands-v2/index.d.ts +3 -2
- package/dist/commands-v2/index.js +4 -1
- package/dist/commands-v2/registry.d.ts +15 -0
- package/dist/commands-v2/registry.js +34 -0
- package/dist/commands-v2/types.d.ts +81 -3
- package/dist/commands.js +13 -0
- package/dist/compilr-diff-companion.vsix +0 -0
- package/dist/db/index.js +98 -4
- package/dist/db/repositories/document-repository.d.ts +2 -0
- package/dist/db/repositories/document-repository.js +6 -1
- package/dist/db/repositories/index.d.ts +2 -0
- package/dist/db/repositories/index.js +1 -0
- package/dist/db/repositories/plan-repository.d.ts +101 -0
- package/dist/db/repositories/plan-repository.js +275 -0
- package/dist/db/repositories/project-repository.d.ts +6 -0
- package/dist/db/repositories/project-repository.js +41 -0
- package/dist/db/repositories/work-item-repository.d.ts +15 -0
- package/dist/db/repositories/work-item-repository.js +69 -4
- package/dist/db/schema.d.ts +40 -3
- package/dist/db/schema.js +66 -3
- package/dist/episodes/index.d.ts +20 -0
- package/dist/episodes/index.js +27 -0
- package/dist/episodes/recorder.d.ts +51 -0
- package/dist/episodes/recorder.js +195 -0
- package/dist/episodes/significant-work.d.ts +21 -0
- package/dist/episodes/significant-work.js +56 -0
- package/dist/episodes/store.d.ts +38 -0
- package/dist/episodes/store.js +199 -0
- package/dist/episodes/types.d.ts +35 -0
- package/dist/episodes/types.js +6 -0
- package/dist/episodes/work-at-risk.d.ts +12 -0
- package/dist/episodes/work-at-risk.js +38 -0
- package/dist/episodes/work-summary-anchor.d.ts +23 -0
- package/dist/episodes/work-summary-anchor.js +73 -0
- package/dist/games/coins.d.ts +66 -0
- package/dist/games/coins.js +165 -0
- package/dist/games/game-base.d.ts +84 -0
- package/dist/games/game-base.js +204 -0
- package/dist/games/index.d.ts +16 -0
- package/dist/games/index.js +49 -0
- package/dist/games/scores.d.ts +69 -0
- package/dist/games/scores.js +191 -0
- package/dist/games/tetris/board.d.ts +59 -0
- package/dist/games/tetris/board.js +170 -0
- package/dist/games/tetris/index.d.ts +109 -0
- package/dist/games/tetris/index.js +610 -0
- package/dist/games/tetris/pieces.d.ts +44 -0
- package/dist/games/tetris/pieces.js +271 -0
- package/dist/games/tetris/renderer.d.ts +26 -0
- package/dist/games/tetris/renderer.js +77 -0
- package/dist/guide/guide-content.d.ts +23 -0
- package/dist/guide/guide-content.js +196 -0
- package/dist/guide/index.d.ts +8 -0
- package/dist/guide/index.js +7 -0
- package/dist/guide/shared-content.d.ts +37 -0
- package/dist/guide/shared-content.js +1272 -0
- package/dist/guide/tutorial-helpers.d.ts +57 -0
- package/dist/guide/tutorial-helpers.js +147 -0
- package/dist/handlers/ask-user-handlers.d.ts +32 -0
- package/dist/handlers/ask-user-handlers.js +104 -0
- package/dist/handlers/delegation-handlers.d.ts +34 -0
- package/dist/handlers/delegation-handlers.js +291 -0
- package/dist/handlers/permission-handler.d.ts +30 -0
- package/dist/handlers/permission-handler.js +205 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.js +448 -271
- package/dist/input-handlers/memory-handler.d.ts +1 -1
- package/dist/input-handlers/memory-handler.js +2 -1
- package/dist/models/index.d.ts +10 -0
- package/dist/models/index.js +12 -0
- package/dist/models/model-registry.d.ts +38 -0
- package/dist/models/model-registry.js +69 -0
- package/dist/models/model-tiers.d.ts +28 -0
- package/dist/models/model-tiers.js +71 -0
- package/dist/models/model-validation.d.ts +25 -0
- package/dist/models/model-validation.js +291 -0
- package/dist/models/ollama-models.d.ts +73 -0
- package/dist/models/ollama-models.js +178 -0
- package/dist/models/provider-types.d.ts +6 -0
- package/dist/models/provider-types.js +1 -0
- package/dist/models/providers.d.ts +35 -0
- package/dist/models/providers.js +58 -0
- package/dist/models/types.d.ts +4 -0
- package/dist/models/types.js +4 -0
- package/dist/multi-agent/activity.d.ts +21 -0
- package/dist/multi-agent/activity.js +34 -0
- package/dist/multi-agent/agent-selection.d.ts +55 -0
- package/dist/multi-agent/agent-selection.js +90 -0
- package/dist/multi-agent/artifacts.d.ts +197 -0
- package/dist/multi-agent/artifacts.js +379 -0
- package/dist/multi-agent/checkpointer.d.ts +138 -0
- package/dist/multi-agent/checkpointer.js +471 -0
- package/dist/multi-agent/collision-utils.d.ts +16 -0
- package/dist/multi-agent/collision-utils.js +28 -0
- package/dist/multi-agent/context-resolver.d.ts +97 -0
- package/dist/multi-agent/context-resolver.js +316 -0
- package/dist/multi-agent/custom-agents.d.ts +83 -0
- package/dist/multi-agent/custom-agents.js +227 -0
- package/dist/multi-agent/delegation-tracker.d.ts +157 -0
- package/dist/multi-agent/delegation-tracker.js +243 -0
- package/dist/multi-agent/file-lock-hook.d.ts +29 -0
- package/dist/multi-agent/file-lock-hook.js +97 -0
- package/dist/multi-agent/file-locks.d.ts +58 -0
- package/dist/multi-agent/file-locks.js +194 -0
- package/dist/multi-agent/index.d.ts +24 -0
- package/dist/multi-agent/index.js +30 -0
- package/dist/multi-agent/mention-parser.d.ts +64 -0
- package/dist/multi-agent/mention-parser.js +146 -0
- package/dist/multi-agent/notification-manager.d.ts +84 -0
- package/dist/multi-agent/notification-manager.js +224 -0
- package/dist/multi-agent/pending-requests.d.ts +122 -0
- package/dist/multi-agent/pending-requests.js +155 -0
- package/dist/multi-agent/session-registry.d.ts +139 -0
- package/dist/multi-agent/session-registry.js +514 -0
- package/dist/multi-agent/shared-context.d.ts +293 -0
- package/dist/multi-agent/shared-context.js +671 -0
- package/dist/multi-agent/skill-requirements.d.ts +66 -0
- package/dist/multi-agent/skill-requirements.js +178 -0
- package/dist/multi-agent/task-assignment.d.ts +69 -0
- package/dist/multi-agent/task-assignment.js +123 -0
- package/dist/multi-agent/task-suggestion.d.ts +31 -0
- package/dist/multi-agent/task-suggestion.js +72 -0
- package/dist/multi-agent/team-agent.d.ts +201 -0
- package/dist/multi-agent/team-agent.js +488 -0
- package/dist/multi-agent/team.d.ts +286 -0
- package/dist/multi-agent/team.js +610 -0
- package/dist/multi-agent/tool-config.d.ts +110 -0
- package/dist/multi-agent/tool-config.js +661 -0
- package/dist/multi-agent/types.d.ts +211 -0
- package/dist/multi-agent/types.js +617 -0
- package/dist/prompts/plan-mode-prompt.d.ts +11 -0
- package/dist/prompts/plan-mode-prompt.js +95 -0
- package/dist/repl-helpers.js +5 -2
- package/dist/repl-v2.d.ts +401 -2
- package/dist/repl-v2.js +2588 -65
- package/dist/session/index.d.ts +6 -0
- package/dist/session/index.js +6 -0
- package/dist/session/project-session-manager.d.ts +158 -0
- package/dist/session/project-session-manager.js +650 -0
- package/dist/settings/index.d.ts +133 -13
- package/dist/settings/index.js +329 -24
- package/dist/settings/mcp-config.d.ts +76 -0
- package/dist/settings/mcp-config.js +143 -0
- package/dist/settings/paths.d.ts +4 -0
- package/dist/settings/paths.js +6 -0
- package/dist/shared-handlers.d.ts +62 -0
- package/dist/shared-handlers.js +48 -0
- package/dist/system-prompt/builder.d.ts +5 -0
- package/dist/system-prompt/builder.js +4 -0
- package/dist/system-prompt/index.d.ts +18 -0
- package/dist/system-prompt/index.js +18 -0
- package/dist/system-prompt/modules.d.ts +5 -0
- package/dist/system-prompt/modules.js +4 -0
- package/dist/tabbed-menu.js +2 -1
- package/dist/templates/compilr-md-import.d.ts +16 -0
- package/dist/templates/compilr-md-import.js +241 -0
- package/dist/templates/compilr-md.js +10 -61
- package/dist/templates/config-json.d.ts +1 -25
- package/dist/templates/index.d.ts +2 -0
- package/dist/templates/index.js +34 -73
- package/dist/tool-names.d.ts +113 -0
- package/dist/tool-names.js +239 -0
- package/dist/tools/ask-user-simple.d.ts +1 -1
- package/dist/tools/ask-user-simple.js +2 -1
- package/dist/tools/ask-user.d.ts +1 -1
- package/dist/tools/ask-user.js +2 -1
- package/dist/tools/backlog.d.ts +2 -2
- package/dist/tools/backlog.js +1 -1
- package/dist/tools/db-tools.d.ts +13 -61
- package/dist/tools/db-tools.js +12 -13
- package/dist/tools/delegate-background.d.ts +27 -0
- package/dist/tools/delegate-background.js +115 -0
- package/dist/tools/delegate.d.ts +22 -0
- package/dist/tools/delegate.js +97 -0
- package/dist/tools/delegation-status.d.ts +16 -0
- package/dist/tools/delegation-status.js +128 -0
- package/dist/tools/guide-tool.d.ts +12 -0
- package/dist/tools/guide-tool.js +59 -0
- package/dist/tools/handoff.d.ts +25 -0
- package/dist/tools/handoff.js +99 -0
- package/dist/tools/meta-tools.d.ts +26 -0
- package/dist/tools/meta-tools.js +47 -0
- package/dist/tools/platform-adapter.d.ts +35 -0
- package/dist/tools/platform-adapter.js +404 -0
- package/dist/tools/project-db.d.ts +5 -73
- package/dist/tools/project-db.js +5 -336
- package/dist/tools.d.ts +67 -2
- package/dist/tools.js +240 -48
- package/dist/ui/autocomplete-controller.d.ts +42 -0
- package/dist/ui/autocomplete-controller.js +384 -0
- package/dist/ui/base/index.d.ts +1 -1
- package/dist/ui/base/index.js +1 -1
- package/dist/ui/base/overlay-base-v2.d.ts +10 -0
- package/dist/ui/base/overlay-base-v2.js +14 -0
- package/dist/ui/base/render-utils.d.ts +19 -0
- package/dist/ui/base/render-utils.js +25 -0
- package/dist/ui/base/tabbed-list-overlay-v2.d.ts +16 -1
- package/dist/ui/base/tabbed-list-overlay-v2.js +19 -1
- package/dist/ui/constants/labels.d.ts +14 -0
- package/dist/ui/constants/labels.js +52 -0
- package/dist/ui/conversation-store.d.ts +55 -0
- package/dist/ui/conversation-store.js +107 -0
- package/dist/ui/conversation.js +11 -13
- package/dist/ui/diff.d.ts +7 -1
- package/dist/ui/diff.js +85 -48
- package/dist/ui/ephemeral.js +3 -9
- package/dist/ui/file-autocomplete.d.ts +24 -0
- package/dist/ui/file-autocomplete.js +56 -0
- package/dist/ui/footer-renderer.d.ts +69 -0
- package/dist/ui/footer-renderer.js +431 -0
- package/dist/ui/footer.d.ts +74 -7
- package/dist/ui/footer.js +173 -16
- package/dist/ui/input-controller.d.ts +51 -0
- package/dist/ui/input-controller.js +176 -0
- package/dist/ui/input-prompt.d.ts +19 -0
- package/dist/ui/input-prompt.js +206 -14
- package/dist/ui/keyboard-handler.d.ts +57 -0
- package/dist/ui/keyboard-handler.js +557 -0
- package/dist/ui/live-region-facade.d.ts +42 -0
- package/dist/ui/live-region-facade.js +205 -0
- package/dist/ui/live-region.d.ts +0 -4
- package/dist/ui/live-region.js +6 -14
- package/dist/ui/mascot/renderer.d.ts +1 -1
- package/dist/ui/mascot/renderer.js +37 -2
- package/dist/ui/overlay/data/tutorial-content.d.ts +9 -0
- package/dist/ui/overlay/data/tutorial-content.js +9 -0
- package/dist/ui/overlay/data/tutorial-registry.d.ts +12 -0
- package/dist/ui/overlay/data/tutorial-registry.js +116 -0
- package/dist/ui/overlay/data/tutorial-types.d.ts +35 -0
- package/dist/ui/overlay/data/tutorial-types.js +6 -0
- package/dist/ui/overlay/data/tutorials/basics/first-conversation.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/basics/first-conversation.js +220 -0
- package/dist/ui/overlay/data/tutorials/basics/first-project.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/basics/first-project.js +284 -0
- package/dist/ui/overlay/data/tutorials/basics/navigation.d.ts +8 -0
- package/dist/ui/overlay/data/tutorials/basics/navigation.js +22 -0
- package/dist/ui/overlay/data/tutorials/basics/welcome.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/basics/welcome.js +174 -0
- package/dist/ui/overlay/data/tutorials/config/context-management.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/config/context-management.js +158 -0
- package/dist/ui/overlay/data/tutorials/config/mcp-servers.d.ts +8 -0
- package/dist/ui/overlay/data/tutorials/config/mcp-servers.js +155 -0
- package/dist/ui/overlay/data/tutorials/config/model-selection.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/config/model-selection.js +162 -0
- package/dist/ui/overlay/data/tutorials/config/permissions-safety.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/config/permissions-safety.js +163 -0
- package/dist/ui/overlay/data/tutorials/config/settings-config.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/config/settings-config.js +166 -0
- package/dist/ui/overlay/data/tutorials/planning/arch.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/arch.js +168 -0
- package/dist/ui/overlay/data/tutorials/planning/backlog.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/backlog.js +103 -0
- package/dist/ui/overlay/data/tutorials/planning/build.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/build.js +173 -0
- package/dist/ui/overlay/data/tutorials/planning/design.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/design.js +205 -0
- package/dist/ui/overlay/data/tutorials/planning/docs.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/docs.js +143 -0
- package/dist/ui/overlay/data/tutorials/planning/prd.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/prd.js +173 -0
- package/dist/ui/overlay/data/tutorials/planning/scaffold.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/scaffold.js +164 -0
- package/dist/ui/overlay/data/tutorials/planning/sketch.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/planning/sketch.js +58 -0
- package/dist/ui/overlay/data/tutorials/projects/anchors.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/projects/anchors.js +248 -0
- package/dist/ui/overlay/data/tutorials/projects/import-project.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/projects/import-project.js +172 -0
- package/dist/ui/overlay/data/tutorials/projects/managing-projects.d.ts +8 -0
- package/dist/ui/overlay/data/tutorials/projects/managing-projects.js +212 -0
- package/dist/ui/overlay/data/tutorials/projects/new-project.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/projects/new-project.js +251 -0
- package/dist/ui/overlay/data/tutorials/projects/session-management.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/projects/session-management.js +169 -0
- package/dist/ui/overlay/data/tutorials/teams/background-execution.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/teams/background-execution.js +171 -0
- package/dist/ui/overlay/data/tutorials/teams/multi-terminal.d.ts +8 -0
- package/dist/ui/overlay/data/tutorials/teams/multi-terminal.js +147 -0
- package/dist/ui/overlay/data/tutorials/teams/task-assignment.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/teams/task-assignment.js +204 -0
- package/dist/ui/overlay/data/tutorials/teams/team-overview.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/teams/team-overview.js +165 -0
- package/dist/ui/overlay/data/tutorials/teams/working-with-agents.d.ts +7 -0
- package/dist/ui/overlay/data/tutorials/teams/working-with-agents.js +172 -0
- package/dist/ui/overlay/impl/agents-overlay-v2.js +6 -17
- package/dist/ui/overlay/impl/anchors-overlay-v2.js +30 -64
- package/dist/ui/overlay/impl/artifact-detail-overlay-v2.d.ts +43 -0
- package/dist/ui/overlay/impl/artifact-detail-overlay-v2.js +232 -0
- package/dist/ui/overlay/impl/artifact-overlay-v2.d.ts +40 -0
- package/dist/ui/overlay/impl/artifact-overlay-v2.js +115 -0
- package/dist/ui/overlay/impl/ask-user-overlay-v2.js +2 -5
- package/dist/ui/overlay/impl/background-overlay-v2.d.ts +40 -0
- package/dist/ui/overlay/impl/background-overlay-v2.js +147 -0
- package/dist/ui/overlay/impl/backlog-overlay-v2.d.ts +4 -1
- package/dist/ui/overlay/impl/backlog-overlay-v2.js +55 -16
- package/dist/ui/overlay/impl/changelog-overlay-v2.d.ts +44 -0
- package/dist/ui/overlay/impl/changelog-overlay-v2.js +165 -0
- package/dist/ui/overlay/impl/commands-overlay-v2.js +4 -6
- package/dist/ui/overlay/impl/config-overlay-v2.d.ts +12 -1
- package/dist/ui/overlay/impl/config-overlay-v2.js +164 -100
- package/dist/ui/overlay/impl/custom-agent-form-overlay-v2.d.ts +83 -0
- package/dist/ui/overlay/impl/custom-agent-form-overlay-v2.js +711 -0
- package/dist/ui/overlay/impl/dashboard-overlay-v2.d.ts +2 -0
- package/dist/ui/overlay/impl/dashboard-overlay-v2.js +26 -3
- package/dist/ui/overlay/impl/delegations-overlay-v2.d.ts +28 -0
- package/dist/ui/overlay/impl/delegations-overlay-v2.js +279 -0
- package/dist/ui/overlay/impl/docs-overlay-v2.js +12 -9
- package/dist/ui/overlay/impl/document-detail-overlay-v2.d.ts +7 -0
- package/dist/ui/overlay/impl/document-detail-overlay-v2.js +119 -78
- package/dist/ui/overlay/impl/filter-overlay-v2.d.ts +41 -0
- package/dist/ui/overlay/impl/filter-overlay-v2.js +110 -0
- package/dist/ui/overlay/impl/games-overlay-v2.d.ts +31 -0
- package/dist/ui/overlay/impl/games-overlay-v2.js +135 -0
- package/dist/ui/overlay/impl/help-overlay-v2.d.ts +26 -3
- package/dist/ui/overlay/impl/help-overlay-v2.js +20 -42
- package/dist/ui/overlay/impl/login-overlay-v2.d.ts +49 -0
- package/dist/ui/overlay/impl/login-overlay-v2.js +277 -0
- package/dist/ui/overlay/impl/mcp-overlay-v2.d.ts +63 -0
- package/dist/ui/overlay/impl/mcp-overlay-v2.js +907 -0
- package/dist/ui/overlay/impl/model-overlay-v2.d.ts +57 -13
- package/dist/ui/overlay/impl/model-overlay-v2.js +1086 -61
- package/dist/ui/overlay/impl/new-overlay-v2.d.ts +37 -6
- package/dist/ui/overlay/impl/new-overlay-v2.js +715 -65
- package/dist/ui/overlay/impl/notifications-overlay-v2.d.ts +20 -0
- package/dist/ui/overlay/impl/notifications-overlay-v2.js +116 -0
- package/dist/ui/overlay/impl/onboarding-wizard-overlay-v2.d.ts +76 -0
- package/dist/ui/overlay/impl/onboarding-wizard-overlay-v2.js +728 -0
- package/dist/ui/overlay/impl/pending-overlay-v2.d.ts +51 -0
- package/dist/ui/overlay/impl/pending-overlay-v2.js +445 -0
- package/dist/ui/overlay/impl/permission-overlay-v2.js +5 -5
- package/dist/ui/overlay/impl/permissions-overlay-v2.d.ts +85 -0
- package/dist/ui/overlay/impl/permissions-overlay-v2.js +820 -0
- package/dist/ui/overlay/impl/plan-approval-overlay-v2.d.ts +35 -0
- package/dist/ui/overlay/impl/plan-approval-overlay-v2.js +181 -0
- package/dist/ui/overlay/impl/project-edit-overlay-v2.d.ts +36 -0
- package/dist/ui/overlay/impl/project-edit-overlay-v2.js +195 -0
- package/dist/ui/overlay/impl/projects-overlay-v2.d.ts +1 -0
- package/dist/ui/overlay/impl/projects-overlay-v2.js +278 -44
- package/dist/ui/overlay/impl/reset-overlay-v2.d.ts +39 -0
- package/dist/ui/overlay/impl/reset-overlay-v2.js +107 -0
- package/dist/ui/overlay/impl/resume-overlay-v2.d.ts +60 -0
- package/dist/ui/overlay/impl/resume-overlay-v2.js +414 -0
- package/dist/ui/overlay/impl/session-mode-overlay-v2.d.ts +43 -0
- package/dist/ui/overlay/impl/session-mode-overlay-v2.js +124 -0
- package/dist/ui/overlay/impl/tasks-overlay-v2.d.ts +28 -0
- package/dist/ui/overlay/impl/tasks-overlay-v2.js +283 -0
- package/dist/ui/overlay/impl/team-overlay-v2.d.ts +86 -0
- package/dist/ui/overlay/impl/team-overlay-v2.js +692 -0
- package/dist/ui/overlay/impl/terminals-overlay-v2.d.ts +26 -0
- package/dist/ui/overlay/impl/terminals-overlay-v2.js +217 -0
- package/dist/ui/overlay/impl/tools-overlay-v2.js +3 -7
- package/dist/ui/overlay/impl/tutorial-overlay-v2.d.ts +30 -16
- package/dist/ui/overlay/impl/tutorial-overlay-v2.js +133 -956
- package/dist/ui/overlay/impl/workflow-overlay-v2.d.ts +1 -0
- package/dist/ui/overlay/impl/workflow-overlay-v2.js +10 -4
- package/dist/ui/overlay/index.d.ts +20 -1
- package/dist/ui/overlay/index.js +19 -0
- package/dist/ui/overlay/types.d.ts +5 -0
- package/dist/ui/overlay-manager.d.ts +43 -0
- package/dist/ui/overlay-manager.js +238 -0
- package/dist/ui/overlays.js +4 -16
- package/dist/ui/permission-overlay.js +6 -5
- package/dist/ui/status-bar-controller.d.ts +33 -0
- package/dist/ui/status-bar-controller.js +99 -0
- package/dist/ui/subagent-renderer.js +3 -19
- package/dist/ui/terminal-autocomplete-utils.d.ts +23 -0
- package/dist/ui/terminal-autocomplete-utils.js +83 -0
- package/dist/ui/terminal-line-builders.d.ts +17 -0
- package/dist/ui/terminal-line-builders.js +42 -0
- package/dist/ui/terminal-render-item.d.ts +16 -0
- package/dist/ui/terminal-render-item.js +267 -0
- package/dist/ui/terminal-renderer.d.ts +7 -8
- package/dist/ui/terminal-renderer.js +7 -8
- package/dist/ui/terminal-types.d.ts +179 -0
- package/dist/ui/terminal-types.js +34 -0
- package/dist/ui/terminal-ui.d.ts +144 -276
- package/dist/ui/terminal-ui.js +384 -1861
- package/dist/ui/todo-zone.d.ts +19 -1
- package/dist/ui/todo-zone.js +71 -13
- package/dist/ui/tool-formatters.js +696 -1
- package/dist/ui/turn-metrics.d.ts +56 -0
- package/dist/ui/turn-metrics.js +75 -0
- package/dist/ui/types.d.ts +28 -0
- package/dist/ui/types.js +1 -0
- package/dist/ui/vscode-diff-ipc.d.ts +102 -0
- package/dist/ui/vscode-diff-ipc.js +385 -0
- package/dist/utils/credentials.d.ts +24 -5
- package/dist/utils/credentials.js +123 -9
- package/dist/utils/format-tokens.d.ts +13 -0
- package/dist/utils/format-tokens.js +18 -0
- package/dist/utils/git-config.d.ts +26 -0
- package/dist/utils/git-config.js +54 -0
- package/dist/utils/message-utils.d.ts +61 -0
- package/dist/utils/message-utils.js +72 -0
- package/dist/utils/model-tiers.d.ts +8 -1
- package/dist/utils/model-tiers.js +38 -16
- package/dist/utils/open-browser.d.ts +5 -0
- package/dist/utils/open-browser.js +32 -0
- package/dist/utils/path-safety.js +3 -2
- package/dist/utils/project-detection.d.ts +58 -0
- package/dist/utils/project-detection.js +424 -0
- package/dist/utils/project-memory.js +2 -1
- package/dist/utils/project-status.d.ts +2 -2
- package/dist/utils/startup-perf.d.ts +18 -0
- package/dist/utils/startup-perf.js +60 -0
- package/dist/utils/token-tracker.d.ts +62 -0
- package/dist/utils/token-tracker.js +150 -0
- package/dist/utils/token-types.d.ts +23 -0
- package/dist/utils/token-types.js +18 -0
- package/dist/utils/types/config-types.d.ts +32 -0
- package/dist/utils/types/config-types.js +8 -0
- package/dist/utils/update-checker.d.ts +28 -0
- package/dist/utils/update-checker.js +106 -0
- package/dist/utils/version.d.ts +7 -0
- package/dist/utils/version.js +10 -0
- package/dist/utils/vscode-detect.d.ts +39 -0
- package/dist/utils/vscode-detect.js +137 -0
- package/package.json +27 -13
- package/dist/commands/handler-types.d.ts +0 -68
- package/dist/commands/handler-types.js +0 -8
- package/dist/commands/handlers/agent-commands.d.ts +0 -13
- package/dist/commands/handlers/agent-commands.js +0 -305
- package/dist/commands/handlers/design-commands.d.ts +0 -15
- package/dist/commands/handlers/design-commands.js +0 -334
- package/dist/commands/handlers/index.d.ts +0 -20
- package/dist/commands/handlers/index.js +0 -43
- package/dist/commands/handlers/overlay-commands.d.ts +0 -21
- package/dist/commands/handlers/overlay-commands.js +0 -287
- package/dist/commands/handlers/project-commands.d.ts +0 -11
- package/dist/commands/handlers/project-commands.js +0 -167
- package/dist/commands/handlers/simple-commands.d.ts +0 -19
- package/dist/commands/handlers/simple-commands.js +0 -144
- package/dist/commands/registry.d.ts +0 -50
- package/dist/commands/registry.js +0 -75
- package/dist/index.old.d.ts +0 -7
- package/dist/index.old.js +0 -1014
- package/dist/repl.d.ts +0 -149
- package/dist/repl.js +0 -1151
- package/dist/templates/claude-md.d.ts +0 -7
- package/dist/templates/claude-md.js +0 -189
- package/dist/test-autocomplete.d.ts +0 -7
- package/dist/test-autocomplete.js +0 -85
- package/dist/test-tabbed-menu.d.ts +0 -7
- package/dist/test-tabbed-menu.js +0 -25
- package/dist/tool-selector.d.ts +0 -71
- package/dist/tool-selector.js +0 -184
- package/dist/tools/anchor-tools.d.ts +0 -31
- package/dist/tools/anchor-tools.js +0 -255
- package/dist/tools/backlog-wrappers.d.ts +0 -54
- package/dist/tools/backlog-wrappers.js +0 -338
- package/dist/tools/document-db.d.ts +0 -43
- package/dist/tools/document-db.js +0 -220
- package/dist/tools/workitem-db.d.ts +0 -103
- package/dist/tools/workitem-db.js +0 -549
- package/dist/ui/agents-overlay-v2.d.ts +0 -43
- package/dist/ui/agents-overlay-v2.js +0 -809
- package/dist/ui/agents-overlay.d.ts +0 -12
- package/dist/ui/agents-overlay.js +0 -863
- package/dist/ui/anchors-overlay.d.ts +0 -12
- package/dist/ui/anchors-overlay.js +0 -775
- package/dist/ui/arch-type-overlay.d.ts +0 -15
- package/dist/ui/arch-type-overlay.js +0 -201
- package/dist/ui/ask-user-overlay-v2.d.ts +0 -26
- package/dist/ui/ask-user-overlay-v2.js +0 -555
- package/dist/ui/ask-user-simple-overlay-v2.d.ts +0 -25
- package/dist/ui/ask-user-simple-overlay-v2.js +0 -215
- package/dist/ui/backlog-overlay.d.ts +0 -32
- package/dist/ui/backlog-overlay.js +0 -652
- package/dist/ui/commands-overlay-v2.d.ts +0 -33
- package/dist/ui/commands-overlay-v2.js +0 -441
- package/dist/ui/commands-overlay.d.ts +0 -16
- package/dist/ui/commands-overlay.js +0 -439
- package/dist/ui/config-overlay.d.ts +0 -35
- package/dist/ui/config-overlay.js +0 -707
- package/dist/ui/docs-overlay.d.ts +0 -17
- package/dist/ui/docs-overlay.js +0 -303
- package/dist/ui/footer-v2.d.ts +0 -222
- package/dist/ui/footer-v2.js +0 -1349
- package/dist/ui/help-overlay-v2.d.ts +0 -34
- package/dist/ui/help-overlay-v2.js +0 -309
- package/dist/ui/help-overlay.d.ts +0 -16
- package/dist/ui/help-overlay.js +0 -316
- package/dist/ui/init-overlay-v2.d.ts +0 -34
- package/dist/ui/init-overlay-v2.js +0 -600
- package/dist/ui/init-overlay.d.ts +0 -34
- package/dist/ui/init-overlay.js +0 -604
- package/dist/ui/input-prompt-v2.d.ts +0 -180
- package/dist/ui/input-prompt-v2.js +0 -999
- package/dist/ui/iteration-limit-overlay-v2.d.ts +0 -21
- package/dist/ui/iteration-limit-overlay-v2.js +0 -114
- package/dist/ui/keys-overlay-v2.d.ts +0 -41
- package/dist/ui/keys-overlay-v2.js +0 -248
- package/dist/ui/mascot-overlay-v2.d.ts +0 -41
- package/dist/ui/mascot-overlay-v2.js +0 -138
- package/dist/ui/mascot-overlay.d.ts +0 -21
- package/dist/ui/mascot-overlay.js +0 -146
- package/dist/ui/model-overlay-v2.d.ts +0 -49
- package/dist/ui/model-overlay-v2.js +0 -118
- package/dist/ui/model-overlay.d.ts +0 -27
- package/dist/ui/model-overlay.js +0 -221
- package/dist/ui/model-warning-overlay.d.ts +0 -30
- package/dist/ui/model-warning-overlay.js +0 -169
- package/dist/ui/new-overlay.d.ts +0 -34
- package/dist/ui/new-overlay.js +0 -604
- package/dist/ui/overlay/impl/init-overlay-v2.d.ts +0 -77
- package/dist/ui/overlay/impl/init-overlay-v2.js +0 -593
- package/dist/ui/overlay/overlay-types.d.ts +0 -128
- package/dist/ui/overlay/overlay-types.js +0 -22
- package/dist/ui/overlays/help-overlay-v2.d.ts +0 -28
- package/dist/ui/overlays/help-overlay-v2.js +0 -198
- package/dist/ui/overlays/index.d.ts +0 -11
- package/dist/ui/overlays/index.js +0 -11
- package/dist/ui/permission-overlay-v2.d.ts +0 -36
- package/dist/ui/permission-overlay-v2.js +0 -380
- package/dist/ui/projects-overlay.d.ts +0 -19
- package/dist/ui/projects-overlay.js +0 -484
- package/dist/ui/theme-overlay-v2.d.ts +0 -42
- package/dist/ui/theme-overlay-v2.js +0 -135
- package/dist/ui/theme-overlay.d.ts +0 -24
- package/dist/ui/theme-overlay.js +0 -127
- package/dist/ui/tools-overlay-v2.d.ts +0 -47
- package/dist/ui/tools-overlay-v2.js +0 -218
- package/dist/ui/tools-overlay.d.ts +0 -34
- package/dist/ui/tools-overlay.js +0 -230
- package/dist/ui/tutorial-overlay-v2.d.ts +0 -31
- package/dist/ui/tutorial-overlay-v2.js +0 -1035
- package/dist/ui/tutorial-overlay.d.ts +0 -11
- package/dist/ui/tutorial-overlay.js +0 -1034
- package/dist/ui/workflow-overlay.d.ts +0 -22
- package/dist/ui/workflow-overlay.js +0 -636
|
@@ -0,0 +1,907 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Overlay V2
|
|
3
|
+
*
|
|
4
|
+
* Shows connected MCP servers and their tools.
|
|
5
|
+
* Extends TabbedListOverlayV2 for consistent UI.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Single tab (all servers)
|
|
9
|
+
* - Server list with status and tool count
|
|
10
|
+
* - Detail view with tool list
|
|
11
|
+
* - Restart/disconnect actions
|
|
12
|
+
* - Add server form (with hot-reload)
|
|
13
|
+
* - Empty state with config file instructions
|
|
14
|
+
*/
|
|
15
|
+
import { TabbedListOverlayV2, BaseScreen, stay, pushScreen, popScreen, closeOverlay, isEscape, isCtrlC, isQuit, isEnter, isSpace, isTab, isShiftTab, isBackspace, isDelete, isLeftArrow, isRightArrow, isUpArrow, isDownArrow, isHome, isEnd, isCtrlA, isCtrlE, isPrintable, getPrintableChar, renderBorder, truncate, wrapText, } from '../../base/index.js';
|
|
16
|
+
import { getMCPConfigPath, saveMCPServer, getExistingServerNames, } from '../../../settings/mcp-config.js';
|
|
17
|
+
// =============================================================================
|
|
18
|
+
// Constants
|
|
19
|
+
// =============================================================================
|
|
20
|
+
const PAGE_SIZE = 8;
|
|
21
|
+
// =============================================================================
|
|
22
|
+
// Detail Screen
|
|
23
|
+
// =============================================================================
|
|
24
|
+
class ServerDetailScreen extends BaseScreen {
|
|
25
|
+
item;
|
|
26
|
+
manager;
|
|
27
|
+
styles;
|
|
28
|
+
getWidth;
|
|
29
|
+
onRefresh;
|
|
30
|
+
message = null;
|
|
31
|
+
selectedToolIndex = 0;
|
|
32
|
+
toolScrollOffset = 0;
|
|
33
|
+
/** Max tools visible in the scrollable list area */
|
|
34
|
+
static TOOL_PAGE_SIZE = 8;
|
|
35
|
+
constructor(item, manager, styles, getWidth, onRefresh) {
|
|
36
|
+
super();
|
|
37
|
+
this.item = item;
|
|
38
|
+
this.manager = manager;
|
|
39
|
+
this.styles = styles;
|
|
40
|
+
this.getWidth = getWidth;
|
|
41
|
+
this.onRefresh = onRefresh;
|
|
42
|
+
}
|
|
43
|
+
getMinHeight() {
|
|
44
|
+
return 20;
|
|
45
|
+
}
|
|
46
|
+
render() {
|
|
47
|
+
const s = this.styles;
|
|
48
|
+
const cols = this.getWidth();
|
|
49
|
+
const border = renderBorder(cols, s);
|
|
50
|
+
const lines = [];
|
|
51
|
+
// Re-read status from client (may have changed after restart/disconnect)
|
|
52
|
+
const currentStatus = this.item.client.status;
|
|
53
|
+
const statusDisplay = formatStatus(currentStatus, s);
|
|
54
|
+
// Header
|
|
55
|
+
lines.push(border);
|
|
56
|
+
lines.push(` ${s.primaryBold(`MCP Server: ${this.item.name}`)}`);
|
|
57
|
+
lines.push('');
|
|
58
|
+
// Server info
|
|
59
|
+
lines.push(` ${s.secondary('Status:')} ${statusDisplay}`);
|
|
60
|
+
lines.push(` ${s.secondary('Transport:')} ${this.item.transport} ${s.muted(`\u2014 ${this.item.transportDetail}`)}`);
|
|
61
|
+
lines.push('');
|
|
62
|
+
// Message (after restart/disconnect)
|
|
63
|
+
if (this.message) {
|
|
64
|
+
lines.push(` ${s.secondary(this.message)}`);
|
|
65
|
+
lines.push('');
|
|
66
|
+
}
|
|
67
|
+
// Tools
|
|
68
|
+
const tools = this.item.tools;
|
|
69
|
+
if (tools.length > 0) {
|
|
70
|
+
lines.push(` ${s.secondary(`Tools (${String(tools.length)}):`)}`);
|
|
71
|
+
// Clamp selection
|
|
72
|
+
if (this.selectedToolIndex >= tools.length) {
|
|
73
|
+
this.selectedToolIndex = tools.length - 1;
|
|
74
|
+
}
|
|
75
|
+
// Adjust scroll offset to keep selection visible
|
|
76
|
+
const pageSize = ServerDetailScreen.TOOL_PAGE_SIZE;
|
|
77
|
+
if (this.selectedToolIndex < this.toolScrollOffset) {
|
|
78
|
+
this.toolScrollOffset = this.selectedToolIndex;
|
|
79
|
+
}
|
|
80
|
+
else if (this.selectedToolIndex >= this.toolScrollOffset + pageSize) {
|
|
81
|
+
this.toolScrollOffset = this.selectedToolIndex - pageSize + 1;
|
|
82
|
+
}
|
|
83
|
+
// Render visible tools
|
|
84
|
+
const visibleEnd = Math.min(this.toolScrollOffset + pageSize, tools.length);
|
|
85
|
+
// Scroll indicator (top)
|
|
86
|
+
if (this.toolScrollOffset > 0) {
|
|
87
|
+
lines.push(` ${s.muted(`\u2191 ${String(this.toolScrollOffset)} more above`)}`);
|
|
88
|
+
}
|
|
89
|
+
for (let i = this.toolScrollOffset; i < visibleEnd; i++) {
|
|
90
|
+
const tool = tools[i];
|
|
91
|
+
const isSelected = i === this.selectedToolIndex;
|
|
92
|
+
const prefix = isSelected ? s.primary(' \u25ba ') : ' ';
|
|
93
|
+
const toolName = truncate(tool.name, 30);
|
|
94
|
+
const desc = tool.description
|
|
95
|
+
? s.muted(` \u2014 ${truncate(tool.description, Math.max(cols - 42, 20))}`)
|
|
96
|
+
: '';
|
|
97
|
+
const name = isSelected ? s.primary(toolName) : toolName;
|
|
98
|
+
lines.push(`${prefix}${name}${desc}`);
|
|
99
|
+
}
|
|
100
|
+
// Scroll indicator (bottom)
|
|
101
|
+
const remaining = tools.length - visibleEnd;
|
|
102
|
+
if (remaining > 0) {
|
|
103
|
+
lines.push(` ${s.muted(`\u2193 ${String(remaining)} more below`)}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else if (currentStatus === 'connected') {
|
|
107
|
+
lines.push(` ${s.muted('No tools discovered.')}`);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
lines.push(` ${s.muted('Server not connected \u2014 tools unavailable.')}`);
|
|
111
|
+
}
|
|
112
|
+
lines.push('');
|
|
113
|
+
// Pad to consistent height
|
|
114
|
+
while (lines.length < 16) {
|
|
115
|
+
lines.push('');
|
|
116
|
+
}
|
|
117
|
+
// Footer
|
|
118
|
+
lines.push(border);
|
|
119
|
+
const footerHint = tools.length > 0
|
|
120
|
+
? '\u2191\u2193/jk Navigate \u00b7 Enter Details \u00b7 r Restart \u00b7 d Disconnect \u00b7 q/Esc Back'
|
|
121
|
+
: 'r Restart \u00b7 d Disconnect \u00b7 q/Esc Back';
|
|
122
|
+
lines.push(s.muted(` ${footerHint}`));
|
|
123
|
+
return lines;
|
|
124
|
+
}
|
|
125
|
+
handleKey(data) {
|
|
126
|
+
if (isCtrlC(data)) {
|
|
127
|
+
return closeOverlay({ viewed: true });
|
|
128
|
+
}
|
|
129
|
+
if (isEscape(data) || isQuit(data)) {
|
|
130
|
+
return popScreen();
|
|
131
|
+
}
|
|
132
|
+
const char = data.toString();
|
|
133
|
+
const tools = this.item.tools;
|
|
134
|
+
// Tool navigation — Up/Down/j/k
|
|
135
|
+
if (tools.length > 0) {
|
|
136
|
+
if (isUpArrow(data) || char === 'k') {
|
|
137
|
+
if (this.selectedToolIndex > 0) {
|
|
138
|
+
this.selectedToolIndex--;
|
|
139
|
+
}
|
|
140
|
+
return stay(true);
|
|
141
|
+
}
|
|
142
|
+
if (isDownArrow(data) || char === 'j') {
|
|
143
|
+
if (this.selectedToolIndex < tools.length - 1) {
|
|
144
|
+
this.selectedToolIndex++;
|
|
145
|
+
}
|
|
146
|
+
return stay(true);
|
|
147
|
+
}
|
|
148
|
+
// Enter — push tool detail screen
|
|
149
|
+
if (isEnter(data)) {
|
|
150
|
+
const selectedTool = tools[this.selectedToolIndex];
|
|
151
|
+
return pushScreen(new MCPToolDetailScreen(selectedTool, this.item.name, this.styles, this.getWidth));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Restart
|
|
155
|
+
if (char === 'r') {
|
|
156
|
+
this.message = 'Restarting...';
|
|
157
|
+
this.onRefresh();
|
|
158
|
+
void (async () => {
|
|
159
|
+
try {
|
|
160
|
+
const client = this.item.client;
|
|
161
|
+
await client.disconnect();
|
|
162
|
+
await client.connect();
|
|
163
|
+
const newTools = await client.listTools();
|
|
164
|
+
this.item.tools = newTools;
|
|
165
|
+
this.item.toolCount = newTools.length;
|
|
166
|
+
this.selectedToolIndex = 0;
|
|
167
|
+
this.toolScrollOffset = 0;
|
|
168
|
+
this.message = `Restarted \u2014 ${String(newTools.length)} tools discovered`;
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
this.message = 'Restart failed';
|
|
172
|
+
}
|
|
173
|
+
this.onRefresh();
|
|
174
|
+
})();
|
|
175
|
+
return stay(false);
|
|
176
|
+
}
|
|
177
|
+
// Disconnect
|
|
178
|
+
if (char === 'd') {
|
|
179
|
+
this.message = 'Disconnecting...';
|
|
180
|
+
this.onRefresh();
|
|
181
|
+
void (async () => {
|
|
182
|
+
try {
|
|
183
|
+
await this.item.client.disconnect();
|
|
184
|
+
this.item.tools = [];
|
|
185
|
+
this.item.toolCount = 0;
|
|
186
|
+
this.selectedToolIndex = 0;
|
|
187
|
+
this.toolScrollOffset = 0;
|
|
188
|
+
this.message = 'Disconnected';
|
|
189
|
+
this.onRefresh();
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
this.message = 'Disconnect failed';
|
|
193
|
+
}
|
|
194
|
+
this.onRefresh();
|
|
195
|
+
})();
|
|
196
|
+
return stay(false);
|
|
197
|
+
}
|
|
198
|
+
return stay(false);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// =============================================================================
|
|
202
|
+
// Tool Detail Screen
|
|
203
|
+
// =============================================================================
|
|
204
|
+
/**
|
|
205
|
+
* Full-screen detail view for a single MCP tool.
|
|
206
|
+
* Shows name, description (word-wrapped), and input schema parameters.
|
|
207
|
+
* Follows the same pattern as ToolDetailScreen in tools-overlay-v2.
|
|
208
|
+
*/
|
|
209
|
+
class MCPToolDetailScreen extends BaseScreen {
|
|
210
|
+
tool;
|
|
211
|
+
serverName;
|
|
212
|
+
styles;
|
|
213
|
+
getWidth;
|
|
214
|
+
constructor(tool, serverName, styles, getWidth) {
|
|
215
|
+
super();
|
|
216
|
+
this.tool = tool;
|
|
217
|
+
this.serverName = serverName;
|
|
218
|
+
this.styles = styles;
|
|
219
|
+
this.getWidth = getWidth;
|
|
220
|
+
}
|
|
221
|
+
render() {
|
|
222
|
+
const s = this.styles;
|
|
223
|
+
const cols = this.getWidth();
|
|
224
|
+
const border = renderBorder(cols, s);
|
|
225
|
+
const maxLineWidth = cols - 2;
|
|
226
|
+
const lines = [];
|
|
227
|
+
// Header
|
|
228
|
+
lines.push(border);
|
|
229
|
+
lines.push(` ${s.primaryBold('MCP Tool Details')}`);
|
|
230
|
+
lines.push('');
|
|
231
|
+
// Tool name (prefixed with server name)
|
|
232
|
+
lines.push(` ${s.muted('Name:')} ${s.primaryBold(`mcp_${this.serverName}_${this.tool.name}`)}`);
|
|
233
|
+
lines.push(` ${s.muted('Server:')} ${this.serverName}`);
|
|
234
|
+
lines.push('');
|
|
235
|
+
// Description (word-wrapped, never truncated)
|
|
236
|
+
lines.push(` ${s.muted('Description:')}`);
|
|
237
|
+
const description = this.tool.description ?? 'No description available.';
|
|
238
|
+
const wrappedDesc = wrapText(description, Math.min(maxLineWidth - 4, 70));
|
|
239
|
+
for (const line of wrappedDesc) {
|
|
240
|
+
lines.push(` ${s.secondary(line)}`);
|
|
241
|
+
}
|
|
242
|
+
lines.push('');
|
|
243
|
+
// Input schema parameters
|
|
244
|
+
const props = this.tool.inputSchema.properties;
|
|
245
|
+
const required = new Set(this.tool.inputSchema.required ?? []);
|
|
246
|
+
if (props && Object.keys(props).length > 0) {
|
|
247
|
+
const entries = Object.entries(props);
|
|
248
|
+
// Sort: required first, then optional
|
|
249
|
+
entries.sort(([a], [b]) => {
|
|
250
|
+
const aReq = required.has(a);
|
|
251
|
+
const bReq = required.has(b);
|
|
252
|
+
if (aReq && !bReq)
|
|
253
|
+
return -1;
|
|
254
|
+
if (!aReq && bReq)
|
|
255
|
+
return 1;
|
|
256
|
+
return 0;
|
|
257
|
+
});
|
|
258
|
+
lines.push(` ${s.muted('Parameters:')}`);
|
|
259
|
+
for (const [paramName, paramDef] of entries) {
|
|
260
|
+
const def = paramDef;
|
|
261
|
+
const paramType = typeof def.type === 'string' ? def.type : 'any';
|
|
262
|
+
const isRequired = required.has(paramName);
|
|
263
|
+
const reqLabel = isRequired ? s.warning('*') : ' ';
|
|
264
|
+
const typeStr = s.muted(`(${paramType})`);
|
|
265
|
+
lines.push(` ${reqLabel} ${s.secondary(paramName)} ${typeStr}`);
|
|
266
|
+
// Parameter description (word-wrapped under the param name)
|
|
267
|
+
if (typeof def.description === 'string') {
|
|
268
|
+
const paramDescWrapped = wrapText(def.description, Math.min(maxLineWidth - 10, 64));
|
|
269
|
+
for (const pdLine of paramDescWrapped) {
|
|
270
|
+
lines.push(` ${s.muted(pdLine)}`);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
lines.push('');
|
|
275
|
+
lines.push(` ${s.muted('* = required')}`);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
lines.push(` ${s.muted('Parameters:')} ${s.muted('None')}`);
|
|
279
|
+
}
|
|
280
|
+
lines.push('');
|
|
281
|
+
// Footer
|
|
282
|
+
lines.push(border);
|
|
283
|
+
lines.push(` ${s.muted('q/Esc Back')}`);
|
|
284
|
+
return lines;
|
|
285
|
+
}
|
|
286
|
+
handleKey(data) {
|
|
287
|
+
if (isCtrlC(data)) {
|
|
288
|
+
return closeOverlay({ viewed: true });
|
|
289
|
+
}
|
|
290
|
+
if (isEscape(data) || isQuit(data)) {
|
|
291
|
+
return popScreen();
|
|
292
|
+
}
|
|
293
|
+
return stay(false);
|
|
294
|
+
}
|
|
295
|
+
getMinHeight() {
|
|
296
|
+
return 20;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Form screen for adding a new MCP server.
|
|
301
|
+
* Text fields accept character input; cycle fields toggle with Enter/Space.
|
|
302
|
+
* Follows the same navigation pattern as /config overlay.
|
|
303
|
+
*/
|
|
304
|
+
class AddServerScreen extends BaseScreen {
|
|
305
|
+
agent;
|
|
306
|
+
getManager;
|
|
307
|
+
styles;
|
|
308
|
+
getWidth;
|
|
309
|
+
onServerAdded;
|
|
310
|
+
onRefresh;
|
|
311
|
+
projectRoot;
|
|
312
|
+
formState;
|
|
313
|
+
existingNames;
|
|
314
|
+
constructor(agent, getManager, styles, getWidth, onServerAdded, onRefresh, projectRoot) {
|
|
315
|
+
super();
|
|
316
|
+
this.agent = agent;
|
|
317
|
+
this.getManager = getManager;
|
|
318
|
+
this.styles = styles;
|
|
319
|
+
this.getWidth = getWidth;
|
|
320
|
+
this.onServerAdded = onServerAdded;
|
|
321
|
+
this.onRefresh = onRefresh;
|
|
322
|
+
this.projectRoot = projectRoot;
|
|
323
|
+
this.existingNames = getExistingServerNames(projectRoot);
|
|
324
|
+
const items = [
|
|
325
|
+
{ type: 'text', id: 'name', label: 'Name', value: '', hint: 'Unique server name (e.g., filesystem)' },
|
|
326
|
+
{ type: 'cycle', id: 'transport', label: 'Transport', value: 'stdio', options: ['stdio', 'http'] },
|
|
327
|
+
{ type: 'text', id: 'command', label: 'Command', value: '', hint: 'Command to run (e.g., npx)' },
|
|
328
|
+
{ type: 'text', id: 'args', label: 'Args', value: '', hint: 'Space-separated arguments (optional)' },
|
|
329
|
+
];
|
|
330
|
+
// Add scope toggle only when a project is bound
|
|
331
|
+
if (this.projectRoot) {
|
|
332
|
+
items.push({ type: 'cycle', id: 'scope', label: 'Scope', value: 'Global', options: ['Global', 'Project'] });
|
|
333
|
+
}
|
|
334
|
+
this.formState = {
|
|
335
|
+
items,
|
|
336
|
+
activeIndex: 0,
|
|
337
|
+
cursorPos: 0,
|
|
338
|
+
saving: false,
|
|
339
|
+
message: null,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
getMinHeight() {
|
|
343
|
+
return 20;
|
|
344
|
+
}
|
|
345
|
+
// ── helpers ──────────────────────────────────────────────────────────────
|
|
346
|
+
get activeItem() { return this.formState.items[this.formState.activeIndex]; }
|
|
347
|
+
get isTextItem() { return this.activeItem.type === 'text'; }
|
|
348
|
+
get transport() {
|
|
349
|
+
const t = this.formState.items.find((i) => i.id === 'transport');
|
|
350
|
+
return t ? t.value : 'stdio';
|
|
351
|
+
}
|
|
352
|
+
get scope() {
|
|
353
|
+
const s = this.formState.items.find((i) => i.id === 'scope');
|
|
354
|
+
return s ? s.value : 'Global';
|
|
355
|
+
}
|
|
356
|
+
get itemCount() { return this.formState.items.length; }
|
|
357
|
+
// ── render ───────────────────────────────────────────────────────────────
|
|
358
|
+
render() {
|
|
359
|
+
const s = this.styles;
|
|
360
|
+
const cols = this.getWidth();
|
|
361
|
+
const border = renderBorder(cols, s);
|
|
362
|
+
const lines = [];
|
|
363
|
+
const labelWidth = 12;
|
|
364
|
+
// Header
|
|
365
|
+
lines.push(border);
|
|
366
|
+
lines.push(` ${s.primaryBold('Add MCP Server')}`);
|
|
367
|
+
lines.push('');
|
|
368
|
+
for (let i = 0; i < this.formState.items.length; i++) {
|
|
369
|
+
const item = this.formState.items[i];
|
|
370
|
+
const isActive = i === this.formState.activeIndex && !this.formState.saving;
|
|
371
|
+
const prefix = isActive ? s.primary(' \u276f ') : ' ';
|
|
372
|
+
const label = isActive
|
|
373
|
+
? s.primary(item.label.padEnd(labelWidth))
|
|
374
|
+
: s.secondary(item.label.padEnd(labelWidth));
|
|
375
|
+
// Skip args/headers row when it doesn't apply
|
|
376
|
+
if (item.id === 'args' && this.transport === 'http')
|
|
377
|
+
continue;
|
|
378
|
+
if (item.type === 'text') {
|
|
379
|
+
if (isActive) {
|
|
380
|
+
const before = item.value.slice(0, this.formState.cursorPos);
|
|
381
|
+
const after = item.value.slice(this.formState.cursorPos);
|
|
382
|
+
const cursor = s.primaryBold('\u2502');
|
|
383
|
+
lines.push(`${prefix}${label}${before}${cursor}${after}`);
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
const display = item.value || s.muted(item.hint);
|
|
387
|
+
lines.push(`${prefix}${label}${display}`);
|
|
388
|
+
}
|
|
389
|
+
if (item.error) {
|
|
390
|
+
lines.push(` ${''.padEnd(labelWidth)}${s.error(item.error)}`);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
// Cycle toggle — render all options, highlight current
|
|
395
|
+
const optionStr = item.options
|
|
396
|
+
.map((opt) => (opt === item.value ? s.primary(opt) : s.muted(opt)))
|
|
397
|
+
.join(s.muted(' / '));
|
|
398
|
+
lines.push(`${prefix}${label}${optionStr}`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
lines.push('');
|
|
402
|
+
// Status message
|
|
403
|
+
if (this.formState.message) {
|
|
404
|
+
lines.push(` ${this.formState.saving ? s.warning(this.formState.message) : s.success(this.formState.message)}`);
|
|
405
|
+
}
|
|
406
|
+
// Pad to consistent height
|
|
407
|
+
while (lines.length < 16) {
|
|
408
|
+
lines.push('');
|
|
409
|
+
}
|
|
410
|
+
// Footer
|
|
411
|
+
lines.push(border);
|
|
412
|
+
const hint = this.isTextItem
|
|
413
|
+
? '\u2191\u2193 Navigate \u00b7 Type to edit \u00b7 Enter Submit \u00b7 Esc Cancel'
|
|
414
|
+
: '\u2191\u2193 Navigate \u00b7 Space Toggle \u00b7 Enter Submit \u00b7 Esc Cancel';
|
|
415
|
+
lines.push(s.muted(` ${hint}`));
|
|
416
|
+
return lines;
|
|
417
|
+
}
|
|
418
|
+
// ── key handling ─────────────────────────────────────────────────────────
|
|
419
|
+
handleKey(data) {
|
|
420
|
+
if (isCtrlC(data)) {
|
|
421
|
+
return closeOverlay({ viewed: true });
|
|
422
|
+
}
|
|
423
|
+
if (this.formState.saving) {
|
|
424
|
+
return stay(false);
|
|
425
|
+
}
|
|
426
|
+
if (isEscape(data)) {
|
|
427
|
+
return popScreen();
|
|
428
|
+
}
|
|
429
|
+
// Navigation — Up/Down (always available)
|
|
430
|
+
if (isUpArrow(data) || isShiftTab(data)) {
|
|
431
|
+
return this.navigate(-1);
|
|
432
|
+
}
|
|
433
|
+
if (isDownArrow(data) || isTab(data)) {
|
|
434
|
+
return this.navigate(1);
|
|
435
|
+
}
|
|
436
|
+
// Enter always submits, regardless of active field
|
|
437
|
+
if (isEnter(data)) {
|
|
438
|
+
return this.handleSubmit();
|
|
439
|
+
}
|
|
440
|
+
// ── Cycle items: Space toggles ──────────────────────────────────────
|
|
441
|
+
if (this.activeItem.type === 'cycle') {
|
|
442
|
+
if (isSpace(data)) {
|
|
443
|
+
return this.cycleValue();
|
|
444
|
+
}
|
|
445
|
+
// Cycle items don't accept other input
|
|
446
|
+
return stay(false);
|
|
447
|
+
}
|
|
448
|
+
// At this point activeItem is guaranteed to be 'text' (cycle returned early above)
|
|
449
|
+
return this.handleTextInput(data);
|
|
450
|
+
return stay(false);
|
|
451
|
+
}
|
|
452
|
+
// ── text input handling ───────────────────────────────────────────────────
|
|
453
|
+
handleTextInput(data) {
|
|
454
|
+
const item = this.formState.items[this.formState.activeIndex];
|
|
455
|
+
if (item.type !== 'text')
|
|
456
|
+
return stay(false);
|
|
457
|
+
if (isBackspace(data)) {
|
|
458
|
+
if (this.formState.cursorPos > 0) {
|
|
459
|
+
item.value = item.value.slice(0, this.formState.cursorPos - 1) + item.value.slice(this.formState.cursorPos);
|
|
460
|
+
this.formState.cursorPos--;
|
|
461
|
+
item.error = undefined;
|
|
462
|
+
}
|
|
463
|
+
return stay(true);
|
|
464
|
+
}
|
|
465
|
+
if (isDelete(data)) {
|
|
466
|
+
if (this.formState.cursorPos < item.value.length) {
|
|
467
|
+
item.value = item.value.slice(0, this.formState.cursorPos) + item.value.slice(this.formState.cursorPos + 1);
|
|
468
|
+
item.error = undefined;
|
|
469
|
+
}
|
|
470
|
+
return stay(true);
|
|
471
|
+
}
|
|
472
|
+
if (isLeftArrow(data)) {
|
|
473
|
+
if (this.formState.cursorPos > 0)
|
|
474
|
+
this.formState.cursorPos--;
|
|
475
|
+
return stay(true);
|
|
476
|
+
}
|
|
477
|
+
if (isRightArrow(data)) {
|
|
478
|
+
if (this.formState.cursorPos < item.value.length)
|
|
479
|
+
this.formState.cursorPos++;
|
|
480
|
+
return stay(true);
|
|
481
|
+
}
|
|
482
|
+
if (isHome(data) || isCtrlA(data)) {
|
|
483
|
+
this.formState.cursorPos = 0;
|
|
484
|
+
return stay(true);
|
|
485
|
+
}
|
|
486
|
+
if (isEnd(data) || isCtrlE(data)) {
|
|
487
|
+
this.formState.cursorPos = item.value.length;
|
|
488
|
+
return stay(true);
|
|
489
|
+
}
|
|
490
|
+
if (isPrintable(data)) {
|
|
491
|
+
const ch = getPrintableChar(data);
|
|
492
|
+
if (ch) {
|
|
493
|
+
item.value = item.value.slice(0, this.formState.cursorPos) + ch + item.value.slice(this.formState.cursorPos);
|
|
494
|
+
this.formState.cursorPos++;
|
|
495
|
+
item.error = undefined;
|
|
496
|
+
}
|
|
497
|
+
return stay(true);
|
|
498
|
+
}
|
|
499
|
+
return stay(false);
|
|
500
|
+
}
|
|
501
|
+
// ── navigation helpers ───────────────────────────────────────────────────
|
|
502
|
+
navigate(direction) {
|
|
503
|
+
let next = this.formState.activeIndex + direction;
|
|
504
|
+
// Skip hidden items (args when transport is http)
|
|
505
|
+
while (next >= 0 && next < this.itemCount) {
|
|
506
|
+
const item = this.formState.items[next];
|
|
507
|
+
if (item.id === 'args' && this.transport === 'http') {
|
|
508
|
+
next += direction;
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
511
|
+
break;
|
|
512
|
+
}
|
|
513
|
+
if (next < 0 || next >= this.itemCount) {
|
|
514
|
+
return stay(false);
|
|
515
|
+
}
|
|
516
|
+
this.formState.activeIndex = next;
|
|
517
|
+
// Set cursor to end of text value when entering a text field
|
|
518
|
+
const newItem = this.formState.items[next];
|
|
519
|
+
if (newItem.type === 'text') {
|
|
520
|
+
this.formState.cursorPos = newItem.value.length;
|
|
521
|
+
}
|
|
522
|
+
return stay(true);
|
|
523
|
+
}
|
|
524
|
+
cycleValue() {
|
|
525
|
+
const item = this.activeItem;
|
|
526
|
+
if (item.type !== 'cycle')
|
|
527
|
+
return stay(false);
|
|
528
|
+
const currentIdx = item.options.indexOf(item.value);
|
|
529
|
+
const nextIdx = (currentIdx + 1) % item.options.length;
|
|
530
|
+
item.value = item.options[nextIdx];
|
|
531
|
+
// When transport changes, update the command/url field labels
|
|
532
|
+
if (item.id === 'transport') {
|
|
533
|
+
this.onTransportChange();
|
|
534
|
+
}
|
|
535
|
+
return stay(true);
|
|
536
|
+
}
|
|
537
|
+
onTransportChange() {
|
|
538
|
+
const isHttp = this.transport === 'http';
|
|
539
|
+
const cmdField = this.formState.items.find((i) => i.id === 'command' || i.id === 'url');
|
|
540
|
+
if (cmdField && cmdField.type === 'text') {
|
|
541
|
+
cmdField.id = isHttp ? 'url' : 'command';
|
|
542
|
+
cmdField.label = isHttp ? 'URL' : 'Command';
|
|
543
|
+
cmdField.hint = isHttp
|
|
544
|
+
? 'Server URL (e.g., http://localhost:3000/mcp)'
|
|
545
|
+
: 'Command to run (e.g., npx)';
|
|
546
|
+
cmdField.error = undefined;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
getTextItem(id) {
|
|
550
|
+
const item = this.formState.items.find((i) => i.id === id);
|
|
551
|
+
return item?.type === 'text' ? item : undefined;
|
|
552
|
+
}
|
|
553
|
+
handleSubmit() {
|
|
554
|
+
const nameField = this.getTextItem('name');
|
|
555
|
+
const cmdField = this.getTextItem('command') ?? this.getTextItem('url');
|
|
556
|
+
if (!nameField || !cmdField)
|
|
557
|
+
return stay(false);
|
|
558
|
+
let hasError = false;
|
|
559
|
+
const transport = this.transport;
|
|
560
|
+
// Name validation
|
|
561
|
+
const name = nameField.value.trim();
|
|
562
|
+
if (!name) {
|
|
563
|
+
nameField.error = 'Name is required';
|
|
564
|
+
hasError = true;
|
|
565
|
+
}
|
|
566
|
+
else if (this.existingNames.has(name)) {
|
|
567
|
+
nameField.error = 'Name already exists';
|
|
568
|
+
hasError = true;
|
|
569
|
+
}
|
|
570
|
+
else if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
|
|
571
|
+
nameField.error = 'Only letters, numbers, hyphens, underscores';
|
|
572
|
+
hasError = true;
|
|
573
|
+
}
|
|
574
|
+
// Command/URL validation
|
|
575
|
+
const commandOrUrl = cmdField.value.trim();
|
|
576
|
+
if (!commandOrUrl) {
|
|
577
|
+
cmdField.error = `${transport === 'stdio' ? 'Command' : 'URL'} is required`;
|
|
578
|
+
hasError = true;
|
|
579
|
+
}
|
|
580
|
+
if (hasError)
|
|
581
|
+
return stay(true);
|
|
582
|
+
// Build config entry
|
|
583
|
+
const entry = {};
|
|
584
|
+
if (transport === 'stdio') {
|
|
585
|
+
entry.command = commandOrUrl;
|
|
586
|
+
const argsField = this.getTextItem('args');
|
|
587
|
+
const argsStr = argsField?.value.trim();
|
|
588
|
+
if (argsStr) {
|
|
589
|
+
entry.args = argsStr.split(/\s+/);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
else {
|
|
593
|
+
entry.url = commandOrUrl;
|
|
594
|
+
}
|
|
595
|
+
const scope = this.scope === 'Project' ? 'project' : 'global';
|
|
596
|
+
// Save and connect
|
|
597
|
+
this.formState.saving = true;
|
|
598
|
+
this.formState.message = 'Connecting...';
|
|
599
|
+
this.onRefresh();
|
|
600
|
+
void (async () => {
|
|
601
|
+
try {
|
|
602
|
+
// 1. Save to config file
|
|
603
|
+
saveMCPServer(name, entry, scope, this.projectRoot);
|
|
604
|
+
// 2. Get or create manager
|
|
605
|
+
const manager = await this.getManager();
|
|
606
|
+
// 3. Add server and connect
|
|
607
|
+
const client = await manager.addServer({
|
|
608
|
+
name,
|
|
609
|
+
transport: transport,
|
|
610
|
+
command: entry.command,
|
|
611
|
+
args: entry.args,
|
|
612
|
+
url: entry.url,
|
|
613
|
+
});
|
|
614
|
+
// 4. Discover tools
|
|
615
|
+
let tools = [];
|
|
616
|
+
try {
|
|
617
|
+
tools = await client.listTools();
|
|
618
|
+
}
|
|
619
|
+
catch {
|
|
620
|
+
// Tools may not be available yet
|
|
621
|
+
}
|
|
622
|
+
// 5. Register tools with agent
|
|
623
|
+
if (this.agent && tools.length > 0) {
|
|
624
|
+
const agentTools = await manager.discoverToolsFrom(name);
|
|
625
|
+
this.agent.registerTools(agentTools);
|
|
626
|
+
}
|
|
627
|
+
// 6. Build server item for the list
|
|
628
|
+
const newItem = {
|
|
629
|
+
tabId: 'all',
|
|
630
|
+
name,
|
|
631
|
+
status: client.status,
|
|
632
|
+
transport,
|
|
633
|
+
transportDetail: entry.command ?? entry.url ?? '',
|
|
634
|
+
toolCount: tools.length,
|
|
635
|
+
tools,
|
|
636
|
+
client,
|
|
637
|
+
};
|
|
638
|
+
// 7. Notify parent overlay
|
|
639
|
+
this.onServerAdded(newItem);
|
|
640
|
+
this.formState.saving = false;
|
|
641
|
+
this.formState.message = `Added "${name}" \u2014 ${String(tools.length)} tools`;
|
|
642
|
+
this.onRefresh();
|
|
643
|
+
}
|
|
644
|
+
catch (err) {
|
|
645
|
+
this.formState.saving = false;
|
|
646
|
+
this.formState.message = `Failed: ${err instanceof Error ? err.message : 'Unknown error'}`;
|
|
647
|
+
this.onRefresh();
|
|
648
|
+
}
|
|
649
|
+
})();
|
|
650
|
+
return stay(true);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
// =============================================================================
|
|
654
|
+
// Helpers
|
|
655
|
+
// =============================================================================
|
|
656
|
+
function formatStatus(status, s) {
|
|
657
|
+
switch (status) {
|
|
658
|
+
case 'connected':
|
|
659
|
+
return s.success('connected');
|
|
660
|
+
case 'connecting':
|
|
661
|
+
return s.warning('connecting');
|
|
662
|
+
case 'error':
|
|
663
|
+
return s.error('error');
|
|
664
|
+
case 'disconnected':
|
|
665
|
+
return s.muted('disconnected');
|
|
666
|
+
default:
|
|
667
|
+
return s.muted(status);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
async function buildServerItems(manager) {
|
|
671
|
+
const items = [];
|
|
672
|
+
for (const client of manager.getServers()) {
|
|
673
|
+
let tools = [];
|
|
674
|
+
try {
|
|
675
|
+
if (client.isConnected) {
|
|
676
|
+
tools = await client.listTools();
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
catch {
|
|
680
|
+
// Failed to list tools — show 0
|
|
681
|
+
}
|
|
682
|
+
// Determine transport info from the client name
|
|
683
|
+
// We don't have direct access to config, so use what we can
|
|
684
|
+
const transport = client.isConnected ? 'stdio/http' : 'unknown';
|
|
685
|
+
items.push({
|
|
686
|
+
tabId: 'all',
|
|
687
|
+
name: client.name,
|
|
688
|
+
status: client.status,
|
|
689
|
+
transport,
|
|
690
|
+
transportDetail: '',
|
|
691
|
+
toolCount: tools.length,
|
|
692
|
+
tools,
|
|
693
|
+
client,
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
return items;
|
|
697
|
+
}
|
|
698
|
+
// =============================================================================
|
|
699
|
+
// MCP Overlay V2
|
|
700
|
+
// =============================================================================
|
|
701
|
+
export class MCPOverlayV2 extends TabbedListOverlayV2 {
|
|
702
|
+
type = 'inline';
|
|
703
|
+
id = 'mcp-overlay-v2';
|
|
704
|
+
manager;
|
|
705
|
+
agent;
|
|
706
|
+
getManager;
|
|
707
|
+
projectRoot;
|
|
708
|
+
initialized = false;
|
|
709
|
+
listMessage = null;
|
|
710
|
+
constructor(manager, agent, getManager, projectRoot) {
|
|
711
|
+
const tabs = [
|
|
712
|
+
{ id: 'all', label: 'All' },
|
|
713
|
+
];
|
|
714
|
+
super({
|
|
715
|
+
title: 'MCP Servers',
|
|
716
|
+
tabs,
|
|
717
|
+
items: [],
|
|
718
|
+
pageSize: PAGE_SIZE,
|
|
719
|
+
filterByTab: () => true,
|
|
720
|
+
getSearchText: (item) => `${item.name} ${item.status} ${item.tools.map((t) => t.name).join(' ')}`,
|
|
721
|
+
renderItem: (item, isSelected, styles) => {
|
|
722
|
+
const prefix = isSelected ? styles.primary(' \u25ba ') : ' ';
|
|
723
|
+
const namePadded = item.name.padEnd(20);
|
|
724
|
+
const statusPadded = formatStatus(item.status, styles).padEnd(20);
|
|
725
|
+
const toolInfo = item.status === 'connected'
|
|
726
|
+
? styles.muted(`${String(item.toolCount)} tools`)
|
|
727
|
+
: styles.muted('\u2014');
|
|
728
|
+
const name = isSelected ? styles.primary(namePadded) : namePadded;
|
|
729
|
+
return `${prefix}${name} ${statusPadded} ${toolInfo}`;
|
|
730
|
+
},
|
|
731
|
+
footerHints: (searchMode) => {
|
|
732
|
+
if (searchMode) {
|
|
733
|
+
return 'Type to filter \u00b7 \u2191\u2193/jk Navigate \u00b7 Enter Details \u00b7 Esc Exit search';
|
|
734
|
+
}
|
|
735
|
+
return '\u2191\u2193/jk \u00b7 / Search \u00b7 Enter Details \u00b7 a Add \u00b7 r Restart \u00b7 d Disconnect \u00b7 q/Esc Close';
|
|
736
|
+
},
|
|
737
|
+
emptyMessage: '', // We handle empty state in render()
|
|
738
|
+
noResultsMessage: 'No servers match the search.',
|
|
739
|
+
showCount: false,
|
|
740
|
+
});
|
|
741
|
+
this.manager = manager;
|
|
742
|
+
this.agent = agent;
|
|
743
|
+
this.getManager = getManager;
|
|
744
|
+
this.projectRoot = projectRoot;
|
|
745
|
+
this.minHeight = 18;
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* Load server data on first render.
|
|
749
|
+
*/
|
|
750
|
+
async loadItems() {
|
|
751
|
+
if (this.initialized)
|
|
752
|
+
return;
|
|
753
|
+
this.initialized = true;
|
|
754
|
+
if (!this.manager)
|
|
755
|
+
return;
|
|
756
|
+
const items = await buildServerItems(this.manager);
|
|
757
|
+
this.state.items = items;
|
|
758
|
+
this.state.filteredItems = [...items];
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* Override render to load items on first call and handle empty state.
|
|
762
|
+
*/
|
|
763
|
+
render(context) {
|
|
764
|
+
this.styles = context.styles;
|
|
765
|
+
this.termWidth = context.width;
|
|
766
|
+
// Async load — render loading state first, then re-render
|
|
767
|
+
if (!this.initialized) {
|
|
768
|
+
void this.loadItems().then(() => {
|
|
769
|
+
this.renderCallback?.();
|
|
770
|
+
});
|
|
771
|
+
const s = this.getStyles();
|
|
772
|
+
const border = renderBorder(context.width, s);
|
|
773
|
+
return {
|
|
774
|
+
lines: [
|
|
775
|
+
border,
|
|
776
|
+
` ${s.primaryBold('MCP Servers')}`,
|
|
777
|
+
'',
|
|
778
|
+
` ${s.muted('Loading...')}`,
|
|
779
|
+
'',
|
|
780
|
+
border,
|
|
781
|
+
s.muted(' q/Esc Close'),
|
|
782
|
+
],
|
|
783
|
+
minHeight: 18,
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
// Empty state — show config instructions (but allow 'a' to add)
|
|
787
|
+
if (this.state.items.length === 0 && this.screenStack.size() <= 1) {
|
|
788
|
+
return this.renderEmptyState(context);
|
|
789
|
+
}
|
|
790
|
+
// Inject list message if present (shown after add)
|
|
791
|
+
const result = super.render(context);
|
|
792
|
+
if (this.listMessage) {
|
|
793
|
+
const s = this.getStyles();
|
|
794
|
+
// Insert message before the footer border
|
|
795
|
+
const msg = ` ${s.success(this.listMessage)}`;
|
|
796
|
+
result.lines.splice(-3, 0, msg);
|
|
797
|
+
// Clear message after a brief display
|
|
798
|
+
setTimeout(() => {
|
|
799
|
+
this.listMessage = null;
|
|
800
|
+
this.renderCallback?.();
|
|
801
|
+
}, 3000);
|
|
802
|
+
}
|
|
803
|
+
return result;
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Render helpful empty state with config file instructions.
|
|
807
|
+
*/
|
|
808
|
+
renderEmptyState(context) {
|
|
809
|
+
const s = this.getStyles();
|
|
810
|
+
const border = renderBorder(context.width, s);
|
|
811
|
+
const configPath = getMCPConfigPath();
|
|
812
|
+
const lines = [
|
|
813
|
+
border,
|
|
814
|
+
` ${s.primaryBold('MCP Servers')} ${s.muted('(0 configured)')}`,
|
|
815
|
+
'',
|
|
816
|
+
` ${s.muted('No MCP servers configured.')}`,
|
|
817
|
+
'',
|
|
818
|
+
` ${s.secondary('Press')} ${s.primary('a')} ${s.secondary('to add a server, or edit the config file:')}`,
|
|
819
|
+
` ${s.muted(configPath)}`,
|
|
820
|
+
'',
|
|
821
|
+
` ${s.muted('{')}`,
|
|
822
|
+
` ${s.muted(' "mcpServers": {')}`,
|
|
823
|
+
` ${s.muted(' "filesystem": {')}`,
|
|
824
|
+
` ${s.muted(' "command": "npx",')}`,
|
|
825
|
+
` ${s.muted(' "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]')}`,
|
|
826
|
+
` ${s.muted(' }')}`,
|
|
827
|
+
` ${s.muted(' }')}`,
|
|
828
|
+
` ${s.muted('}')}`,
|
|
829
|
+
'',
|
|
830
|
+
border,
|
|
831
|
+
s.muted(' a Add \u00b7 q/Esc Close'),
|
|
832
|
+
];
|
|
833
|
+
return { lines, minHeight: 18 };
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* Handle custom keys (a/r/d) on the list screen.
|
|
837
|
+
* Only intercepts when the screen stack is at the root list screen.
|
|
838
|
+
*/
|
|
839
|
+
handleKey(key) {
|
|
840
|
+
const char = key.raw.toString();
|
|
841
|
+
// Only handle custom keys when on the list screen (not on detail/add screens)
|
|
842
|
+
if (this.screenStack.size() <= 1 && !this.state.searchMode) {
|
|
843
|
+
// Add server
|
|
844
|
+
if (char === 'a') {
|
|
845
|
+
const styles = this.getStyles();
|
|
846
|
+
const addScreen = new AddServerScreen(this.agent, this.getManager, styles, () => this.termWidth, (newItem) => {
|
|
847
|
+
// Callback: add new server to list, refresh
|
|
848
|
+
this.state.items.push(newItem);
|
|
849
|
+
this.state.filteredItems = [...this.state.items];
|
|
850
|
+
}, () => {
|
|
851
|
+
this.renderCallback?.();
|
|
852
|
+
}, this.projectRoot);
|
|
853
|
+
this.screenStack.push(addScreen);
|
|
854
|
+
return this.rerender();
|
|
855
|
+
}
|
|
856
|
+
// Restart/disconnect only when items exist
|
|
857
|
+
if (this.state.filteredItems.length > 0) {
|
|
858
|
+
const selectedItem = this.state.filteredItems[this.state.selectedIndex];
|
|
859
|
+
// Restart selected server
|
|
860
|
+
if (char === 'r') {
|
|
861
|
+
void (async () => {
|
|
862
|
+
try {
|
|
863
|
+
const client = selectedItem.client;
|
|
864
|
+
await client.disconnect();
|
|
865
|
+
await client.connect();
|
|
866
|
+
const tools = await client.listTools();
|
|
867
|
+
selectedItem.tools = tools;
|
|
868
|
+
selectedItem.toolCount = tools.length;
|
|
869
|
+
selectedItem.status = client.status;
|
|
870
|
+
}
|
|
871
|
+
catch {
|
|
872
|
+
selectedItem.status = selectedItem.client.status;
|
|
873
|
+
}
|
|
874
|
+
this.renderCallback?.();
|
|
875
|
+
})();
|
|
876
|
+
return this.rerender();
|
|
877
|
+
}
|
|
878
|
+
// Disconnect selected server
|
|
879
|
+
if (char === 'd') {
|
|
880
|
+
void (async () => {
|
|
881
|
+
try {
|
|
882
|
+
await selectedItem.client.disconnect();
|
|
883
|
+
selectedItem.tools = [];
|
|
884
|
+
selectedItem.toolCount = 0;
|
|
885
|
+
selectedItem.status = 'disconnected';
|
|
886
|
+
}
|
|
887
|
+
catch {
|
|
888
|
+
selectedItem.status = selectedItem.client.status;
|
|
889
|
+
}
|
|
890
|
+
this.renderCallback?.();
|
|
891
|
+
})();
|
|
892
|
+
return this.rerender();
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
return super.handleKey(key);
|
|
897
|
+
}
|
|
898
|
+
createDetailScreen(item) {
|
|
899
|
+
if (!this.manager)
|
|
900
|
+
return null;
|
|
901
|
+
const styles = this.getStyles();
|
|
902
|
+
return new ServerDetailScreen(item, this.manager, styles, () => this.termWidth, () => {
|
|
903
|
+
// Refresh list items after restart/disconnect in detail screen
|
|
904
|
+
this.renderCallback?.();
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
}
|