@cjhyy/code-shell-core 0.5.0-rc.1 → 0.6.0-rc.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/README.md +13 -10
- package/dist/agent/agent-definition-registry.d.ts +21 -3
- package/dist/agent/agent-definition-registry.js +49 -18
- package/dist/agent/agent-definition.d.ts +32 -0
- package/dist/agent/agent-definition.js +49 -4
- package/dist/arena/arena.js +11 -12
- package/dist/arena/context/context-tools.js +47 -6
- package/dist/arena/context/within-root.d.ts +7 -0
- package/dist/arena/context/within-root.js +15 -0
- package/dist/arena/iterate/phases/argue.js +8 -2
- package/dist/arena/iterate/phases/revise.js +1 -1
- package/dist/arena/iterate/phases/tournament.js +3 -3
- package/dist/arena/ledger.js +9 -1
- package/dist/arena/phases/adjudication.js +1 -4
- package/dist/arena/phases/build-consensus.js +1 -4
- package/dist/arena/phases/cross-review.js +2 -8
- package/dist/arena/phases/debate-rounds.js +1 -4
- package/dist/arena/phases/participant-research.js +1 -4
- package/dist/arena/phases/planning-detail-expansion.js +8 -10
- package/dist/arena/planner.js +0 -1
- package/dist/arena/providers/docs.d.ts +1 -0
- package/dist/arena/providers/docs.js +5 -2
- package/dist/arena/providers/repo.d.ts +1 -0
- package/dist/arena/providers/repo.js +5 -2
- package/dist/arena/strategies/utils.d.ts +1 -4
- package/dist/arena/strategies/utils.js +7 -51
- package/dist/arena/transitions.d.ts +7 -2
- package/dist/arena/transitions.js +9 -4
- package/dist/arena/types.d.ts +8 -2
- package/dist/automation/cron-expr.d.ts +41 -0
- package/dist/automation/cron-expr.js +169 -0
- package/dist/automation/index.d.ts +41 -0
- package/dist/automation/index.js +39 -0
- package/dist/automation/runner.d.ts +84 -0
- package/dist/automation/runner.js +92 -0
- package/dist/automation/scheduler.d.ts +194 -0
- package/dist/automation/scheduler.js +623 -0
- package/dist/automation/store.d.ts +39 -0
- package/dist/automation/store.js +122 -0
- package/dist/automation/write-policy.d.ts +34 -0
- package/dist/automation/write-policy.js +113 -0
- package/dist/automation/write-run.d.ts +51 -0
- package/dist/automation/write-run.js +38 -0
- package/dist/capability-control/disabled-lists.d.ts +25 -0
- package/dist/capability-control/disabled-lists.js +57 -0
- package/dist/capability-control/index.d.ts +5 -0
- package/dist/capability-control/index.js +3 -0
- package/dist/capability-control/overlay.d.ts +64 -0
- package/dist/capability-control/overlay.js +116 -0
- package/dist/capability-control/project.d.ts +65 -0
- package/dist/capability-control/project.js +147 -0
- package/dist/capability-control/service.d.ts +70 -0
- package/dist/capability-control/service.js +147 -0
- package/dist/capability-control/types.d.ts +62 -0
- package/dist/capability-control/types.js +17 -0
- package/dist/cc-orchestrator/agent-adapter.d.ts +50 -0
- package/dist/cc-orchestrator/agent-adapter.js +133 -0
- package/dist/cc-orchestrator/cc-capability.d.ts +19 -0
- package/dist/cc-orchestrator/cc-capability.js +53 -0
- package/dist/cc-orchestrator/codex-session-discovery.d.ts +24 -0
- package/dist/cc-orchestrator/codex-session-discovery.js +191 -0
- package/dist/cc-orchestrator/codex-session-history.d.ts +25 -0
- package/dist/cc-orchestrator/codex-session-history.js +187 -0
- package/dist/cc-orchestrator/external-agent-changes.d.ts +19 -0
- package/dist/cc-orchestrator/external-agent-changes.js +214 -0
- package/dist/cc-orchestrator/external-agent-driver.d.ts +18 -0
- package/dist/cc-orchestrator/external-agent-driver.js +69 -0
- package/dist/cc-orchestrator/index.d.ts +8 -0
- package/dist/cc-orchestrator/index.js +8 -0
- package/dist/cc-orchestrator/relevance-judge.d.ts +15 -0
- package/dist/cc-orchestrator/relevance-judge.js +29 -0
- package/dist/cc-orchestrator/session-discovery.d.ts +46 -0
- package/dist/cc-orchestrator/session-discovery.js +125 -0
- package/dist/cc-orchestrator/session-history.d.ts +19 -0
- package/dist/cc-orchestrator/session-history.js +67 -0
- package/dist/cli/agent-server-stdio.d.ts +26 -1
- package/dist/cli/agent-server-stdio.js +221 -28
- package/dist/cli/agent-server-tcp.d.ts +20 -0
- package/dist/cli/agent-server-tcp.js +134 -0
- package/dist/cli/graceful-shutdown.d.ts +27 -0
- package/dist/cli/graceful-shutdown.js +30 -0
- package/dist/context/compaction.d.ts +56 -0
- package/dist/context/compaction.js +209 -15
- package/dist/context/manager.d.ts +0 -20
- package/dist/context/manager.js +25 -41
- package/dist/cost-tracker.js +5 -61
- package/dist/credentials/cipher.d.ts +49 -0
- package/dist/credentials/cipher.js +45 -0
- package/dist/credentials/cookie-jar.d.ts +24 -0
- package/dist/credentials/cookie-jar.js +40 -0
- package/dist/credentials/index.d.ts +7 -0
- package/dist/credentials/index.js +5 -0
- package/dist/credentials/inject-credential-tool.d.ts +20 -0
- package/dist/credentials/inject-credential-tool.js +130 -0
- package/dist/credentials/store.d.ts +72 -0
- package/dist/credentials/store.js +184 -0
- package/dist/credentials/types.d.ts +56 -0
- package/dist/credentials/use-credential-tool.d.ts +29 -0
- package/dist/credentials/use-credential-tool.js +205 -0
- package/dist/credentials/use-gate.d.ts +56 -0
- package/dist/credentials/use-gate.js +52 -0
- package/dist/cron/cron-runtime.d.ts +2 -0
- package/dist/cron/cron-runtime.js +2 -0
- package/dist/cron/cron-store.d.ts +2 -0
- package/dist/cron/cron-store.js +2 -0
- package/dist/cron/scheduler.d.ts +5 -32
- package/dist/cron/scheduler.js +5 -113
- package/dist/data/model-metadata.d.ts +77 -0
- package/dist/data/model-metadata.js +56 -0
- package/dist/data/model-metadata.json +216 -0
- package/dist/data/openrouter-models.d.ts +18 -7
- package/dist/data/openrouter-models.js +35 -8
- package/dist/data/openrouter-sync.js +1 -1
- package/dist/engine/aux-key.d.ts +10 -0
- package/dist/engine/aux-key.js +11 -0
- package/dist/engine/dynamic-tool-defs.d.ts +19 -0
- package/dist/engine/dynamic-tool-defs.js +36 -0
- package/dist/engine/engine.d.ts +431 -108
- package/dist/engine/engine.js +1630 -279
- package/dist/engine/friendly-error.d.ts +18 -0
- package/dist/engine/friendly-error.js +63 -0
- package/dist/engine/goal.d.ts +187 -0
- package/dist/engine/goal.js +196 -0
- package/dist/engine/image-compression.d.ts +81 -0
- package/dist/engine/image-compression.js +186 -0
- package/dist/engine/image-policy.d.ts +165 -0
- package/dist/engine/image-policy.js +189 -0
- package/dist/engine/model-connections-pool.d.ts +17 -0
- package/dist/engine/model-connections-pool.js +66 -0
- package/dist/engine/model-facade.d.ts +10 -0
- package/dist/engine/model-facade.js +25 -0
- package/dist/engine/patch-orphaned-tools.js +3 -0
- package/dist/engine/reactive-threshold.d.ts +13 -0
- package/dist/engine/reactive-threshold.js +17 -0
- package/dist/engine/resolve-llm-config.d.ts +16 -0
- package/dist/engine/resolve-llm-config.js +44 -0
- package/dist/engine/runtime.js +9 -1
- package/dist/engine/sandbox-cache-key.d.ts +10 -0
- package/dist/engine/sandbox-cache-key.js +9 -0
- package/dist/engine/sandbox-config.d.ts +31 -0
- package/dist/engine/sandbox-config.js +38 -0
- package/dist/engine/session-title.d.ts +13 -0
- package/dist/engine/session-title.js +34 -0
- package/dist/engine/session-usage.d.ts +19 -0
- package/dist/engine/session-usage.js +25 -0
- package/dist/engine/steer-queue.d.ts +32 -0
- package/dist/engine/steer-queue.js +26 -0
- package/dist/engine/streaming-tool-queue.d.ts +12 -0
- package/dist/engine/streaming-tool-queue.js +50 -10
- package/dist/engine/turn-loop.d.ts +94 -9
- package/dist/engine/turn-loop.js +775 -342
- package/dist/engine/types.d.ts +175 -0
- package/dist/engine/types.js +13 -0
- package/dist/external-agents/config.d.ts +2 -0
- package/dist/external-agents/config.js +15 -0
- package/dist/external-agents/types.d.ts +31 -0
- package/dist/external-agents/types.js +1 -0
- package/dist/git/parse-log.d.ts +13 -0
- package/dist/git/parse-log.js +21 -0
- package/dist/git/utils.d.ts +8 -6
- package/dist/git/utils.js +62 -26
- package/dist/git/worktree.d.ts +48 -0
- package/dist/git/worktree.js +111 -20
- package/dist/hooks/events.d.ts +23 -1
- package/dist/hooks/goal-stop-hook.d.ts +58 -0
- package/dist/hooks/goal-stop-hook.js +279 -0
- package/dist/hooks/hook-output.d.ts +33 -0
- package/dist/hooks/hook-output.js +79 -0
- package/dist/hooks/registry.d.ts +15 -0
- package/dist/hooks/registry.js +57 -1
- package/dist/hooks/shell-runner.d.ts +2 -0
- package/dist/hooks/shell-runner.js +48 -18
- package/dist/index.d.ts +79 -11
- package/dist/index.js +89 -6
- package/dist/llm/capabilities/param-specs.d.ts +14 -0
- package/dist/llm/capabilities/param-specs.js +62 -0
- package/dist/llm/capabilities/reasoning-control.d.ts +24 -0
- package/dist/llm/capabilities/reasoning-control.js +38 -0
- package/dist/llm/capabilities/rules.js +37 -3
- package/dist/llm/capabilities/types.d.ts +32 -2
- package/dist/llm/clamp-max-tokens.d.ts +11 -0
- package/dist/llm/clamp-max-tokens.js +17 -0
- package/dist/llm/client-base.d.ts +69 -5
- package/dist/llm/client-base.js +185 -25
- package/dist/llm/client-factory.d.ts +3 -3
- package/dist/llm/client-factory.js +2 -2
- package/dist/llm/model-cache.js +4 -2
- package/dist/llm/model-pool.d.ts +29 -11
- package/dist/llm/model-pool.js +36 -20
- package/dist/llm/provider-auth.d.ts +41 -0
- package/dist/llm/provider-auth.js +76 -0
- package/dist/llm/provider-catalog.d.ts +6 -2
- package/dist/llm/providers/anthropic.d.ts +32 -2
- package/dist/llm/providers/anthropic.js +207 -18
- package/dist/llm/providers/openai.d.ts +47 -2
- package/dist/llm/providers/openai.js +478 -71
- package/dist/llm/reasoning-setting.d.ts +51 -0
- package/dist/llm/reasoning-setting.js +40 -0
- package/dist/llm/stop-reason.d.ts +13 -0
- package/dist/llm/stop-reason.js +21 -0
- package/dist/llm/stream-watchdog.js +5 -1
- package/dist/llm/strip-vision.d.ts +32 -0
- package/dist/llm/strip-vision.js +94 -0
- package/dist/llm/token-counter.js +9 -2
- package/dist/llm/types.d.ts +9 -6
- package/dist/logging/logger.js +18 -4
- package/dist/logging/sanitize-messages.d.ts +10 -0
- package/dist/logging/sanitize-messages.js +112 -0
- package/dist/lsp/client.js +28 -8
- package/dist/lsp/manager.d.ts +1 -1
- package/dist/lsp/manager.js +42 -11
- package/dist/lsp/root-path.d.ts +9 -0
- package/dist/lsp/root-path.js +12 -0
- package/dist/model-catalog/builtin.d.ts +12 -0
- package/dist/model-catalog/builtin.js +407 -0
- package/dist/model-catalog/gen-connections.d.ts +20 -0
- package/dist/model-catalog/gen-connections.js +28 -0
- package/dist/model-catalog/index.d.ts +41 -0
- package/dist/model-catalog/index.js +90 -0
- package/dist/model-catalog/params.d.ts +20 -0
- package/dist/model-catalog/params.js +45 -0
- package/dist/model-catalog/resolve.d.ts +48 -0
- package/dist/model-catalog/resolve.js +33 -0
- package/dist/model-catalog/save-entry.d.ts +32 -0
- package/dist/model-catalog/save-entry.js +104 -0
- package/dist/model-catalog/types.d.ts +561 -0
- package/dist/model-catalog/types.js +93 -0
- package/dist/model-catalog/upsert.d.ts +9 -0
- package/dist/model-catalog/upsert.js +8 -0
- package/dist/onboarding.d.ts +12 -82
- package/dist/onboarding.js +75 -333
- package/dist/plugins/gitOps.d.ts +53 -0
- package/dist/plugins/gitOps.js +130 -5
- package/dist/plugins/installer/checkUpdate.d.ts +16 -0
- package/dist/plugins/installer/checkUpdate.js +32 -0
- package/dist/plugins/installer/codex/convertAgents.d.ts +7 -0
- package/dist/plugins/installer/codex/convertAgents.js +55 -0
- package/dist/plugins/installer/codex/convertCommands.d.ts +19 -0
- package/dist/plugins/installer/codex/convertCommands.js +46 -0
- package/dist/plugins/installer/codex/convertMcp.d.ts +11 -0
- package/dist/plugins/installer/codex/convertMcp.js +85 -0
- package/dist/plugins/installer/codex/convertSkills.d.ts +12 -0
- package/dist/plugins/installer/codex/convertSkills.js +33 -0
- package/dist/plugins/installer/detectFormat.d.ts +2 -0
- package/dist/plugins/installer/detectFormat.js +6 -0
- package/dist/plugins/installer/install.d.ts +7 -0
- package/dist/plugins/installer/install.js +123 -0
- package/dist/plugins/installer/installFromArchive.d.ts +43 -0
- package/dist/plugins/installer/installFromArchive.js +134 -0
- package/dist/plugins/installer/installFromSource.d.ts +13 -0
- package/dist/plugins/installer/installFromSource.js +51 -0
- package/dist/plugins/installer/list.d.ts +9 -0
- package/dist/plugins/installer/list.js +30 -0
- package/dist/plugins/installer/loadPluginAgents.d.ts +3 -0
- package/dist/plugins/installer/loadPluginAgents.js +27 -0
- package/dist/plugins/installer/loadPluginMcp.d.ts +14 -0
- package/dist/plugins/installer/loadPluginMcp.js +107 -0
- package/dist/plugins/installer/parseSource.d.ts +20 -0
- package/dist/plugins/installer/parseSource.js +74 -0
- package/dist/plugins/installer/paths.d.ts +5 -0
- package/dist/plugins/installer/paths.js +25 -0
- package/dist/plugins/installer/pruneDisabled.d.ts +24 -0
- package/dist/plugins/installer/pruneDisabled.js +73 -0
- package/dist/plugins/installer/types.d.ts +52 -0
- package/dist/plugins/installer/types.js +28 -0
- package/dist/plugins/installer/uninstall.d.ts +2 -0
- package/dist/plugins/installer/uninstall.js +18 -0
- package/dist/plugins/installer/unzip.d.ts +14 -0
- package/dist/plugins/installer/unzip.js +82 -0
- package/dist/plugins/installer/update.d.ts +28 -0
- package/dist/plugins/installer/update.js +97 -0
- package/dist/plugins/loadPluginHooks.d.ts +54 -1
- package/dist/plugins/loadPluginHooks.js +83 -1
- package/dist/plugins/marketplaceManager.d.ts +15 -1
- package/dist/plugins/marketplaceManager.js +58 -4
- package/dist/plugins/pluginCommandHook.js +34 -14
- package/dist/plugins/pluginContent.d.ts +30 -0
- package/dist/plugins/pluginContent.js +83 -0
- package/dist/plugins/pluginInstaller.d.ts +34 -0
- package/dist/plugins/pluginInstaller.js +168 -35
- package/dist/plugins/schemas.js +41 -6
- package/dist/plugins/types.d.ts +10 -0
- package/dist/preset/index.d.ts +7 -1
- package/dist/preset/index.js +112 -6
- package/dist/product/types.d.ts +1 -1
- package/dist/prompt/composer.d.ts +31 -0
- package/dist/prompt/composer.js +95 -25
- package/dist/prompt/instruction-scanner.js +5 -3
- package/dist/prompt/section-loader.js +1 -0
- package/dist/prompt/sections/base.md +1 -0
- package/dist/prompt/sections/browser.md +10 -0
- package/dist/prompt/sections/coding.md +4 -0
- package/dist/prompt/sections/orchestration.md +8 -0
- package/dist/protocol/chat-session-manager.d.ts +15 -2
- package/dist/protocol/chat-session-manager.js +46 -0
- package/dist/protocol/chat-session.d.ts +82 -0
- package/dist/protocol/chat-session.js +121 -1
- package/dist/protocol/client.d.ts +27 -0
- package/dist/protocol/client.js +38 -0
- package/dist/protocol/redact.d.ts +50 -0
- package/dist/protocol/redact.js +71 -0
- package/dist/protocol/server.d.ts +153 -2
- package/dist/protocol/server.js +807 -39
- package/dist/protocol/tcp-transport.d.ts +45 -0
- package/dist/protocol/tcp-transport.js +74 -0
- package/dist/protocol/transport.js +3 -2
- package/dist/protocol/types.d.ts +69 -0
- package/dist/protocol/types.js +22 -0
- package/dist/quota/credentials.d.ts +3 -0
- package/dist/quota/credentials.js +80 -0
- package/dist/quota/index.d.ts +36 -0
- package/dist/quota/index.js +155 -0
- package/dist/quota/types.d.ts +48 -0
- package/dist/quota/types.js +13 -0
- package/dist/remote/bridge.d.ts +11 -2
- package/dist/remote/bridge.js +61 -33
- package/dist/review/review-prompt.d.ts +28 -0
- package/dist/review/review-prompt.js +81 -0
- package/dist/run/ArtifactTracker.js +5 -4
- package/dist/run/EngineRunner.d.ts +27 -1
- package/dist/run/EngineRunner.js +46 -8
- package/dist/run/FileRunStore.js +40 -11
- package/dist/run/RunApprovalBackend.js +25 -5
- package/dist/run/RunLock.d.ts +28 -2
- package/dist/run/RunLock.js +49 -7
- package/dist/run/RunManager.d.ts +12 -0
- package/dist/run/RunManager.js +86 -3
- package/dist/run/RunQueue.d.ts +1 -0
- package/dist/run/RunQueue.js +8 -2
- package/dist/run/factory.d.ts +8 -1
- package/dist/run/factory.js +1 -0
- package/dist/run/index.d.ts +2 -2
- package/dist/run/index.js +1 -1
- package/dist/run/redirect-target.d.ts +7 -0
- package/dist/run/redirect-target.js +13 -0
- package/dist/run/types.js +1 -1
- package/dist/runtime/background-shell.d.ts +139 -0
- package/dist/runtime/background-shell.js +495 -0
- package/dist/runtime/output-clean.d.ts +24 -0
- package/dist/runtime/output-clean.js +41 -0
- package/dist/runtime/ring-file.d.ts +64 -0
- package/dist/runtime/ring-file.js +174 -0
- package/dist/runtime/safe-spawn.js +15 -34
- package/dist/runtime/spawn-common.d.ts +148 -0
- package/dist/runtime/spawn-common.js +303 -0
- package/dist/runtime/truncate-output.d.ts +22 -0
- package/dist/runtime/truncate-output.js +49 -0
- package/dist/runtime/utf8-cut.d.ts +11 -0
- package/dist/runtime/utf8-cut.js +23 -0
- package/dist/services/auto-dream.d.ts +4 -0
- package/dist/services/auto-dream.js +26 -26
- package/dist/services/browser-open.d.ts +13 -0
- package/dist/services/browser-open.js +16 -0
- package/dist/services/diagnostics.d.ts +1 -2
- package/dist/services/diagnostics.js +12 -7
- package/dist/services/dream-consolidation.d.ts +57 -0
- package/dist/services/dream-consolidation.js +151 -0
- package/dist/services/extract-memories.d.ts +14 -1
- package/dist/services/extract-memories.js +45 -6
- package/dist/services/memory-orchestrator.d.ts +21 -0
- package/dist/services/memory-orchestrator.js +125 -32
- package/dist/services/notifier.d.ts +8 -0
- package/dist/services/notifier.js +39 -25
- package/dist/services/oauth.js +5 -7
- package/dist/services/session-memory-sort.d.ts +8 -0
- package/dist/services/session-memory-sort.js +9 -0
- package/dist/services/session-memory.js +30 -19
- package/dist/session/file-history.d.ts +124 -1
- package/dist/session/file-history.js +232 -9
- package/dist/session/memory.d.ts +116 -2
- package/dist/session/memory.js +250 -28
- package/dist/session/session-manager.d.ts +63 -1
- package/dist/session/session-manager.js +186 -5
- package/dist/session/simple-diff.d.ts +23 -0
- package/dist/session/simple-diff.js +84 -0
- package/dist/session/transcript.d.ts +25 -1
- package/dist/session/transcript.js +35 -2
- package/dist/session/undo-target.d.ts +67 -0
- package/dist/session/undo-target.js +144 -0
- package/dist/settings/disk-defaults.d.ts +42 -0
- package/dist/settings/disk-defaults.js +33 -0
- package/dist/settings/feature-flags.d.ts +64 -0
- package/dist/settings/feature-flags.js +61 -0
- package/dist/settings/manager.d.ts +101 -1
- package/dist/settings/manager.js +345 -15
- package/dist/settings/migrate-config.d.ts +45 -0
- package/dist/settings/migrate-config.js +125 -0
- package/dist/settings/personalization.d.ts +19 -0
- package/dist/settings/personalization.js +7 -0
- package/dist/settings/schema-export.d.ts +25 -0
- package/dist/settings/schema-export.js +38 -0
- package/dist/settings/schema.d.ts +1827 -396
- package/dist/settings/schema.js +361 -81
- package/dist/skills/scanner.d.ts +9 -0
- package/dist/skills/scanner.js +30 -2
- package/dist/stt/resolve-transcribe.d.ts +31 -0
- package/dist/stt/resolve-transcribe.js +108 -0
- package/dist/stt/transcribe.d.ts +51 -0
- package/dist/stt/transcribe.js +65 -0
- package/dist/tool-system/browser-bridge.d.ts +226 -0
- package/dist/tool-system/browser-bridge.js +163 -0
- package/dist/tool-system/builtin/add-marketplace.d.ts +12 -0
- package/dist/tool-system/builtin/add-marketplace.js +76 -0
- package/dist/tool-system/builtin/agent-heartbeat.d.ts +49 -0
- package/dist/tool-system/builtin/agent-heartbeat.js +89 -0
- package/dist/tool-system/builtin/agent-notifications.d.ts +12 -3
- package/dist/tool-system/builtin/agent-notifications.js +9 -3
- package/dist/tool-system/builtin/agent-output-file.d.ts +38 -0
- package/dist/tool-system/builtin/agent-output-file.js +72 -0
- package/dist/tool-system/builtin/agent-registry.d.ts +23 -0
- package/dist/tool-system/builtin/agent-registry.js +16 -4
- package/dist/tool-system/builtin/agent.d.ts +50 -11
- package/dist/tool-system/builtin/agent.js +576 -73
- package/dist/tool-system/builtin/apply-patch/applier.js +66 -8
- package/dist/tool-system/builtin/apply-patch/backup-targets.d.ts +10 -0
- package/dist/tool-system/builtin/apply-patch/backup-targets.js +30 -0
- package/dist/tool-system/builtin/apply-patch/index.js +7 -3
- package/dist/tool-system/builtin/arena.js +6 -7
- package/dist/tool-system/builtin/background-jobs.d.ts +76 -0
- package/dist/tool-system/builtin/background-jobs.js +124 -0
- package/dist/tool-system/builtin/background-shell-tools.d.ts +20 -0
- package/dist/tool-system/builtin/background-shell-tools.js +108 -0
- package/dist/tool-system/builtin/background-work.d.ts +67 -0
- package/dist/tool-system/builtin/background-work.js +86 -0
- package/dist/tool-system/builtin/bash-output-style.d.ts +32 -0
- package/dist/tool-system/builtin/bash-output-style.js +40 -0
- package/dist/tool-system/builtin/bash.d.ts +5 -2
- package/dist/tool-system/builtin/bash.js +98 -62
- package/dist/tool-system/builtin/browser-tools.d.ts +33 -0
- package/dist/tool-system/builtin/browser-tools.js +312 -0
- package/dist/tool-system/builtin/cancel-goal.d.ts +31 -0
- package/dist/tool-system/builtin/cancel-goal.js +64 -0
- package/dist/tool-system/builtin/check-quota.d.ts +15 -0
- package/dist/tool-system/builtin/check-quota.js +34 -0
- package/dist/tool-system/builtin/complete-goal.d.ts +25 -0
- package/dist/tool-system/builtin/complete-goal.js +45 -0
- package/dist/tool-system/builtin/config.js +7 -0
- package/dist/tool-system/builtin/cron.d.ts +7 -0
- package/dist/tool-system/builtin/cron.js +105 -9
- package/dist/tool-system/builtin/drive-claude-code.d.ts +30 -0
- package/dist/tool-system/builtin/drive-claude-code.js +157 -0
- package/dist/tool-system/builtin/edit-model-catalog.d.ts +3 -0
- package/dist/tool-system/builtin/edit-model-catalog.js +94 -0
- package/dist/tool-system/builtin/edit.d.ts +2 -1
- package/dist/tool-system/builtin/edit.js +21 -12
- package/dist/tool-system/builtin/eol.d.ts +29 -0
- package/dist/tool-system/builtin/eol.js +37 -0
- package/dist/tool-system/builtin/file-cache.d.ts +6 -0
- package/dist/tool-system/builtin/file-cache.js +8 -0
- package/dist/tool-system/builtin/generate-image.d.ts +60 -0
- package/dist/tool-system/builtin/generate-image.js +374 -0
- package/dist/tool-system/builtin/generate-video.d.ts +55 -0
- package/dist/tool-system/builtin/generate-video.js +361 -0
- package/dist/tool-system/builtin/grep.js +6 -2
- package/dist/tool-system/builtin/image-providers.d.ts +86 -0
- package/dist/tool-system/builtin/image-providers.js +190 -0
- package/dist/tool-system/builtin/image-uploader.d.ts +33 -0
- package/dist/tool-system/builtin/image-uploader.js +74 -0
- package/dist/tool-system/builtin/index.d.ts +24 -1
- package/dist/tool-system/builtin/index.js +310 -25
- package/dist/tool-system/builtin/mcp-tools.js +23 -3
- package/dist/tool-system/builtin/memory.js +45 -7
- package/dist/tool-system/builtin/notebook-edit.d.ts +2 -1
- package/dist/tool-system/builtin/notebook-edit.js +1 -1
- package/dist/tool-system/builtin/powershell.js +4 -1
- package/dist/tool-system/builtin/read.d.ts +2 -1
- package/dist/tool-system/builtin/read.js +11 -3
- package/dist/tool-system/builtin/repl.js +4 -1
- package/dist/tool-system/builtin/skill.js +9 -0
- package/dist/tool-system/builtin/sleep.js +12 -5
- package/dist/tool-system/builtin/task.js +4 -1
- package/dist/tool-system/builtin/tool-search.js +25 -7
- package/dist/tool-system/builtin/update-automation-memory.d.ts +24 -0
- package/dist/tool-system/builtin/update-automation-memory.js +60 -0
- package/dist/tool-system/builtin/video-providers.d.ts +154 -0
- package/dist/tool-system/builtin/video-providers.js +235 -0
- package/dist/tool-system/builtin/view-image.d.ts +18 -0
- package/dist/tool-system/builtin/view-image.js +96 -0
- package/dist/tool-system/builtin/web-fetch.js +12 -2
- package/dist/tool-system/builtin/web-search.d.ts +4 -1
- package/dist/tool-system/builtin/web-search.js +57 -10
- package/dist/tool-system/builtin/worktree.d.ts +2 -1
- package/dist/tool-system/builtin/worktree.js +31 -4
- package/dist/tool-system/builtin/write.d.ts +2 -1
- package/dist/tool-system/builtin/write.js +1 -1
- package/dist/tool-system/context.d.ts +166 -6
- package/dist/tool-system/executor.d.ts +3 -2
- package/dist/tool-system/executor.js +197 -119
- package/dist/tool-system/investigation-guard.d.ts +4 -1
- package/dist/tool-system/investigation-guard.js +20 -4
- package/dist/tool-system/mcp-manager.d.ts +78 -16
- package/dist/tool-system/mcp-manager.js +357 -28
- package/dist/tool-system/path-policy.d.ts +99 -0
- package/dist/tool-system/path-policy.js +578 -0
- package/dist/tool-system/permission.d.ts +36 -1
- package/dist/tool-system/permission.js +322 -117
- package/dist/tool-system/plan-mode-allowlist.d.ts +32 -0
- package/dist/tool-system/plan-mode-allowlist.js +65 -0
- package/dist/tool-system/registry.d.ts +1 -0
- package/dist/tool-system/registry.js +26 -1
- package/dist/tool-system/sandbox/index.d.ts +8 -0
- package/dist/tool-system/sandbox/index.js +7 -2
- package/dist/tool-system/validate-tool-metadata.d.ts +36 -0
- package/dist/tool-system/validate-tool-metadata.js +63 -0
- package/dist/tool-system/validation.d.ts +10 -0
- package/dist/tool-system/validation.js +16 -3
- package/dist/types.d.ts +301 -15
- package/dist/updater.js +20 -9
- package/dist/utils/envUtils.d.ts +0 -9
- package/dist/utils/envUtils.js +3 -28
- package/dist/utils/exec.d.ts +40 -0
- package/dist/utils/exec.js +144 -0
- package/dist/utils/format.js +4 -2
- package/dist/utils/json.d.ts +12 -0
- package/dist/utils/json.js +92 -0
- package/dist/utils/lockfile.js +9 -2
- package/dist/utils/theme.d.ts +7 -1
- package/dist/utils/theme.js +5 -3
- package/dist/utils/toolDisplay.js +0 -1
- package/package.json +14 -7
- package/dist/agent/coordinator.d.ts +0 -49
- package/dist/agent/coordinator.js +0 -77
- package/dist/settings/manager.test.js +0 -73
- package/dist/tool-system/builtin/remote-trigger.d.ts +0 -6
- package/dist/tool-system/builtin/remote-trigger.js +0 -54
- package/dist/tool-system/builtin/send-message.d.ts +0 -6
- package/dist/tool-system/builtin/send-message.js +0 -47
- /package/dist/{settings/manager.test.d.ts → credentials/types.js} +0 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { existsSync, statSync } from "node:fs";
|
|
2
|
+
import { mkdir, writeFile, readFile, readdir, cp, rm, rename, } from "node:fs/promises";
|
|
3
|
+
import { join, relative } from "node:path";
|
|
4
|
+
import { detectPluginFormat } from "./detectFormat.js";
|
|
5
|
+
import { pluginInstallDir, pluginsRoot, assertSafePluginName } from "./paths.js";
|
|
6
|
+
import { CodexPluginManifest, PluginInstallError } from "./types.js";
|
|
7
|
+
import { convertCodexAgentToml } from "./codex/convertAgents.js";
|
|
8
|
+
import { resolveCodexMcpServers } from "./codex/convertMcp.js";
|
|
9
|
+
import { copyCodexSkills } from "./codex/convertSkills.js";
|
|
10
|
+
import { copyCodexCommands } from "./codex/convertCommands.js";
|
|
11
|
+
import { appendInstallEntry, pluginInstallKey } from "../installedPlugins.js";
|
|
12
|
+
/**
|
|
13
|
+
* Install a local plugin directory into ~/.code-shell/plugins/<name>/.
|
|
14
|
+
* Builds into a temp sibling dir, then renames into place — a conversion
|
|
15
|
+
* failure leaves nothing behind. `installedAt` is passed in (caller stamps the
|
|
16
|
+
* timestamp) to keep this function pure of the unavailable Date.now().
|
|
17
|
+
*/
|
|
18
|
+
export async function installPluginFromPath(sourceDir, name, installedAt) {
|
|
19
|
+
assertSafePluginName(name);
|
|
20
|
+
if (!existsSync(sourceDir) || !statSync(sourceDir).isDirectory()) {
|
|
21
|
+
throw new PluginInstallError(`source is not a directory: ${sourceDir}`);
|
|
22
|
+
}
|
|
23
|
+
const finalDir = pluginInstallDir(name);
|
|
24
|
+
if (existsSync(finalDir)) {
|
|
25
|
+
throw new PluginInstallError(`plugin '${name}' already installed; uninstall first or rename the source`);
|
|
26
|
+
}
|
|
27
|
+
await mkdir(pluginsRoot(), { recursive: true });
|
|
28
|
+
const tmpDir = join(pluginsRoot(), `.tmp-${name}-${process.pid}`);
|
|
29
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
30
|
+
await mkdir(tmpDir, { recursive: true });
|
|
31
|
+
try {
|
|
32
|
+
const format = detectPluginFormat(sourceDir);
|
|
33
|
+
let meta;
|
|
34
|
+
if (format === "cc") {
|
|
35
|
+
// Async cp: a recursive copy of a whole plugin dir is the dominant cost
|
|
36
|
+
// here; awaiting it yields the event loop so the Electron main process
|
|
37
|
+
// keeps answering IPC (no UI freeze during install).
|
|
38
|
+
await cp(sourceDir, tmpDir, { recursive: true });
|
|
39
|
+
// Read the declared version from .claude-plugin/plugin.json so the
|
|
40
|
+
// install record (and the UI's "installed version" chip) shows e.g.
|
|
41
|
+
// "v0.1.0" instead of falling back to the literal "local". Best-effort:
|
|
42
|
+
// CC plugins commonly omit version, and the file may be absent/malformed.
|
|
43
|
+
const version = await readCcPluginVersion(sourceDir);
|
|
44
|
+
meta = { name, format: "cc", version, source: sourceDir, installedAt };
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const manifest = CodexPluginManifest.parse(JSON.parse(await readFile(join(sourceDir, ".codex-plugin", "plugin.json"), "utf-8")));
|
|
48
|
+
// skills (verbatim copy)
|
|
49
|
+
await copyCodexSkills(sourceDir, tmpDir);
|
|
50
|
+
// agents (TOML → MD)
|
|
51
|
+
await convertAgentsInto(sourceDir, tmpDir, name);
|
|
52
|
+
// prompts/ (+ commands/) → commands/ (Codex slash commands == CC commands)
|
|
53
|
+
await copyCodexCommands(sourceDir, tmpDir);
|
|
54
|
+
// mcp → mcp-servers.json keyed <plugin>:<server>
|
|
55
|
+
const servers = resolveCodexMcpServers(sourceDir, manifest.mcpServers);
|
|
56
|
+
const keyed = {};
|
|
57
|
+
for (const [serverName, cfg] of Object.entries(servers)) {
|
|
58
|
+
const key = `${name}:${serverName}`;
|
|
59
|
+
keyed[key] = { ...cfg, name: key };
|
|
60
|
+
}
|
|
61
|
+
if (Object.keys(keyed).length > 0) {
|
|
62
|
+
await writeFile(join(tmpDir, "mcp-servers.json"), JSON.stringify(keyed, null, 2));
|
|
63
|
+
}
|
|
64
|
+
meta = { name, format: "codex", version: manifest.version, source: sourceDir, installedAt };
|
|
65
|
+
}
|
|
66
|
+
await writeFile(join(tmpDir, ".cs-meta.json"), JSON.stringify(meta, null, 2));
|
|
67
|
+
await rename(tmpDir, finalDir);
|
|
68
|
+
// Register so existing loaders (scanInstalledPlugins / loadPluginHooks)
|
|
69
|
+
// discover this local install. Marketplace tag "local" distinguishes it
|
|
70
|
+
// from cache/marketplace installs.
|
|
71
|
+
appendInstallEntry(pluginInstallKey(name, "local"), {
|
|
72
|
+
scope: "user",
|
|
73
|
+
installPath: finalDir,
|
|
74
|
+
version: meta.version ?? "local",
|
|
75
|
+
installedAt,
|
|
76
|
+
lastUpdated: installedAt,
|
|
77
|
+
});
|
|
78
|
+
return finalDir;
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
82
|
+
throw err;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Best-effort read of a CC plugin's declared version from
|
|
87
|
+
* <sourceDir>/.claude-plugin/plugin.json. Returns undefined when the file is
|
|
88
|
+
* absent, unparseable, or has no string `version` — the caller then records the
|
|
89
|
+
* install without a version (UI shows the source tag instead of a number).
|
|
90
|
+
*/
|
|
91
|
+
async function readCcPluginVersion(sourceDir) {
|
|
92
|
+
try {
|
|
93
|
+
const raw = await readFile(join(sourceDir, ".claude-plugin", "plugin.json"), "utf-8");
|
|
94
|
+
const v = JSON.parse(raw).version;
|
|
95
|
+
return typeof v === "string" && v.length > 0 ? v : undefined;
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/** Walk <sourceDir>/agents/**.toml → <destDir>/agents/**.md (structure preserved). */
|
|
102
|
+
async function convertAgentsInto(sourceDir, destDir, pluginName) {
|
|
103
|
+
const agentsSrc = join(sourceDir, "agents");
|
|
104
|
+
if (!existsSync(agentsSrc))
|
|
105
|
+
return;
|
|
106
|
+
const walk = async (dir) => {
|
|
107
|
+
for (const dirent of await readdir(dir, { withFileTypes: true })) {
|
|
108
|
+
const abs = join(dir, dirent.name);
|
|
109
|
+
if (dirent.isDirectory()) {
|
|
110
|
+
await walk(abs);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (!dirent.name.endsWith(".toml"))
|
|
114
|
+
continue;
|
|
115
|
+
const rel = relative(agentsSrc, abs).replace(/\.toml$/, ".md");
|
|
116
|
+
const outPath = join(destDir, "agents", rel);
|
|
117
|
+
await mkdir(join(outPath, ".."), { recursive: true });
|
|
118
|
+
const md = convertCodexAgentToml(await readFile(abs, "utf-8"), rel, pluginName);
|
|
119
|
+
await writeFile(outPath, md);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
await walk(agentsSrc);
|
|
123
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** Options for the unified local-install entry. */
|
|
2
|
+
export interface InstallLocalOptions {
|
|
3
|
+
/**
|
|
4
|
+
* When the target name is already installed, replace it instead of throwing
|
|
5
|
+
* "already installed". The replace is atomic (rename-backup + rollback via
|
|
6
|
+
* {@link reinstallAtomic}), so a failed overwrite keeps the old version and
|
|
7
|
+
* its registration intact. Unlike a manual uninstall+install, this preserves
|
|
8
|
+
* the user's disable flags in settings (an upgrade is not a removal).
|
|
9
|
+
*/
|
|
10
|
+
overwrite?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Install a local plugin from a .zip archive.
|
|
14
|
+
*
|
|
15
|
+
* Mirrors installFromSource (the git path): extract to a private temp dir,
|
|
16
|
+
* locate the plugin root inside it, hand off to the local installer (which
|
|
17
|
+
* does CC/Codex detect + convert + register), then always clean up the temp
|
|
18
|
+
* dir. On any failure nothing is left behind.
|
|
19
|
+
*
|
|
20
|
+
* `name` is optional — when omitted it is derived from the plugin manifest
|
|
21
|
+
* (`name` field) or, failing that, the archive's top-level directory. The
|
|
22
|
+
* caller stamps `installedAt` to keep this pure of the unavailable Date.now().
|
|
23
|
+
*/
|
|
24
|
+
export declare function installPluginFromArchive(zipPath: string, installedAt: string, name?: string, options?: InstallLocalOptions): Promise<{
|
|
25
|
+
dir: string;
|
|
26
|
+
name: string;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Unified local-install entry for the desktop/UI: takes either a directory or
|
|
30
|
+
* a .zip and installs it as a global plugin, deriving the name when not given.
|
|
31
|
+
* The host (which has Date.now) stamps `installedAt`.
|
|
32
|
+
*
|
|
33
|
+
* For a directory we still run findPluginRoot/deriveName so a user can point at
|
|
34
|
+
* a repo checkout whose plugin sits one level down, and so the name comes from
|
|
35
|
+
* the manifest rather than forcing the caller to guess it.
|
|
36
|
+
*/
|
|
37
|
+
export declare function installLocalPlugin(input: {
|
|
38
|
+
kind: "dir" | "zip";
|
|
39
|
+
path: string;
|
|
40
|
+
}, installedAt: string, name?: string, options?: InstallLocalOptions): Promise<{
|
|
41
|
+
dir: string;
|
|
42
|
+
name: string;
|
|
43
|
+
}>;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { existsSync, statSync } from "node:fs";
|
|
2
|
+
import { mkdtemp, readFile, readdir, rm } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { extractZip } from "./unzip.js";
|
|
6
|
+
import { installPluginFromPath } from "./install.js";
|
|
7
|
+
import { reinstallAtomic } from "./update.js";
|
|
8
|
+
import { pluginInstallDir } from "./paths.js";
|
|
9
|
+
import { PluginInstallError } from "./types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Install `root` as plugin `name`, atomically replacing an already-installed
|
|
12
|
+
* plugin of the same name when `overwrite` is set. When no same-name plugin
|
|
13
|
+
* exists this is a plain install (overwrite is a no-op). `root` must stay valid
|
|
14
|
+
* for the duration of the call (zip callers keep their extracted temp dir alive
|
|
15
|
+
* until this resolves).
|
|
16
|
+
*/
|
|
17
|
+
async function installRootMaybeOverwrite(root, resolvedName, installedAt, overwrite) {
|
|
18
|
+
const finalDir = pluginInstallDir(resolvedName);
|
|
19
|
+
if (overwrite && existsSync(finalDir)) {
|
|
20
|
+
await reinstallAtomic(resolvedName, root, () => installPluginFromPath(root, resolvedName, installedAt));
|
|
21
|
+
return finalDir;
|
|
22
|
+
}
|
|
23
|
+
return installPluginFromPath(root, resolvedName, installedAt);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Install a local plugin from a .zip archive.
|
|
27
|
+
*
|
|
28
|
+
* Mirrors installFromSource (the git path): extract to a private temp dir,
|
|
29
|
+
* locate the plugin root inside it, hand off to the local installer (which
|
|
30
|
+
* does CC/Codex detect + convert + register), then always clean up the temp
|
|
31
|
+
* dir. On any failure nothing is left behind.
|
|
32
|
+
*
|
|
33
|
+
* `name` is optional — when omitted it is derived from the plugin manifest
|
|
34
|
+
* (`name` field) or, failing that, the archive's top-level directory. The
|
|
35
|
+
* caller stamps `installedAt` to keep this pure of the unavailable Date.now().
|
|
36
|
+
*/
|
|
37
|
+
export async function installPluginFromArchive(zipPath, installedAt, name, options) {
|
|
38
|
+
if (!existsSync(zipPath) || !statSync(zipPath).isFile()) {
|
|
39
|
+
throw new PluginInstallError(`archive is not a file: ${zipPath}`);
|
|
40
|
+
}
|
|
41
|
+
const tmp = await mkdtemp(join(tmpdir(), "cs-tmp-zip-"));
|
|
42
|
+
try {
|
|
43
|
+
await extractZip(zipPath, tmp);
|
|
44
|
+
const root = await findPluginRoot(tmp);
|
|
45
|
+
const resolvedName = normalizePluginName(name ?? (await deriveName(root)));
|
|
46
|
+
// Overwrite (when set) runs inside this try so the extracted `root` is still
|
|
47
|
+
// present while reinstallAtomic installs from it; the finally removes tmp.
|
|
48
|
+
const dir = await installRootMaybeOverwrite(root, resolvedName, installedAt, options?.overwrite ?? false);
|
|
49
|
+
return { dir, name: resolvedName };
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
await rm(tmp, { recursive: true, force: true });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Unified local-install entry for the desktop/UI: takes either a directory or
|
|
57
|
+
* a .zip and installs it as a global plugin, deriving the name when not given.
|
|
58
|
+
* The host (which has Date.now) stamps `installedAt`.
|
|
59
|
+
*
|
|
60
|
+
* For a directory we still run findPluginRoot/deriveName so a user can point at
|
|
61
|
+
* a repo checkout whose plugin sits one level down, and so the name comes from
|
|
62
|
+
* the manifest rather than forcing the caller to guess it.
|
|
63
|
+
*/
|
|
64
|
+
export async function installLocalPlugin(input, installedAt, name, options) {
|
|
65
|
+
if (input.kind === "zip") {
|
|
66
|
+
return installPluginFromArchive(input.path, installedAt, name, options);
|
|
67
|
+
}
|
|
68
|
+
if (!existsSync(input.path) || !statSync(input.path).isDirectory()) {
|
|
69
|
+
throw new PluginInstallError(`source is not a directory: ${input.path}`);
|
|
70
|
+
}
|
|
71
|
+
const root = await findPluginRoot(input.path);
|
|
72
|
+
const resolvedName = normalizePluginName(name ?? (await deriveName(root)));
|
|
73
|
+
const dir = await installRootMaybeOverwrite(root, resolvedName, installedAt, options?.overwrite ?? false);
|
|
74
|
+
return { dir, name: resolvedName };
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A plugin root is a dir that holds a recognizable manifest or component dir.
|
|
78
|
+
* Zip archives commonly wrap everything in a single top-level folder, so if
|
|
79
|
+
* `dir` itself isn't a plugin root but contains exactly one subdirectory, dive
|
|
80
|
+
* one level. Only one level — deeper nesting is treated as malformed.
|
|
81
|
+
*/
|
|
82
|
+
async function findPluginRoot(dir) {
|
|
83
|
+
if (looksLikePluginRoot(dir))
|
|
84
|
+
return dir;
|
|
85
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
86
|
+
const subDirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith("."));
|
|
87
|
+
if (subDirs.length === 1) {
|
|
88
|
+
const nested = join(dir, subDirs[0].name);
|
|
89
|
+
if (looksLikePluginRoot(nested))
|
|
90
|
+
return nested;
|
|
91
|
+
}
|
|
92
|
+
throw new PluginInstallError("no plugin found in archive (expected .claude-plugin/plugin.json, .codex-plugin/plugin.json, or a skills/commands/agents/hooks directory)");
|
|
93
|
+
}
|
|
94
|
+
function looksLikePluginRoot(dir) {
|
|
95
|
+
return (existsSync(join(dir, ".claude-plugin", "plugin.json")) ||
|
|
96
|
+
existsSync(join(dir, ".codex-plugin", "plugin.json")) ||
|
|
97
|
+
["skills", "commands", "agents", "hooks"].some((d) => existsSync(join(dir, d))));
|
|
98
|
+
}
|
|
99
|
+
/** Read the `name` field from a CC or Codex manifest; fall back to the dir name. */
|
|
100
|
+
async function deriveName(root) {
|
|
101
|
+
for (const rel of [
|
|
102
|
+
[".claude-plugin", "plugin.json"],
|
|
103
|
+
[".codex-plugin", "plugin.json"],
|
|
104
|
+
]) {
|
|
105
|
+
const manifestPath = join(root, ...rel);
|
|
106
|
+
if (!existsSync(manifestPath))
|
|
107
|
+
continue;
|
|
108
|
+
try {
|
|
109
|
+
const parsed = JSON.parse(await readFile(manifestPath, "utf-8"));
|
|
110
|
+
if (typeof parsed.name === "string" && parsed.name.trim())
|
|
111
|
+
return parsed.name.trim();
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// Malformed manifest → fall through to dir-name derivation.
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return root.split(/[\\/]/).filter(Boolean).pop() ?? "plugin";
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Coerce an arbitrary derived name into a safe single path segment:
|
|
121
|
+
* lowercase, only [a-z0-9._-], collapse the rest to '-'. assertSafePluginName
|
|
122
|
+
* (called by installPluginFromPath) rejects separators outright; this makes a
|
|
123
|
+
* manifest name like "My Plugin" usable instead of erroring.
|
|
124
|
+
*/
|
|
125
|
+
function normalizePluginName(raw) {
|
|
126
|
+
const cleaned = raw
|
|
127
|
+
.trim()
|
|
128
|
+
.toLowerCase()
|
|
129
|
+
.replace(/[^a-z0-9._-]+/g, "-")
|
|
130
|
+
.replace(/^[-.]+|[-.]+$/g, "");
|
|
131
|
+
if (!cleaned)
|
|
132
|
+
throw new PluginInstallError(`cannot derive a valid plugin name from: ${JSON.stringify(raw)}`);
|
|
133
|
+
return cleaned;
|
|
134
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ParsedSource } from "./parseSource.js";
|
|
2
|
+
/**
|
|
3
|
+
* Remote install orchestrator: a thin bridge over the existing pieces. Clone
|
|
4
|
+
* the git source to a private temp dir, hand the (sub)directory to the local
|
|
5
|
+
* installer (which does CC/Codex detect + convert + register), then rewrite
|
|
6
|
+
* the recorded `.cs-meta.json` source back to the original git string so
|
|
7
|
+
* `plugin list`/`update` see the git source instead of the throwaway clone.
|
|
8
|
+
*
|
|
9
|
+
* Guarantees: on any failure nothing is left behind — the temp clone is always
|
|
10
|
+
* removed, and `installPluginFromPath` itself leaves no half-built install dir.
|
|
11
|
+
* See spec docs/superpowers/specs/2026-05-29-plugin-remote-install-design.md.
|
|
12
|
+
*/
|
|
13
|
+
export declare function installPluginFromSource(parsed: ParsedSource, name: string, installedAt: string): Promise<string>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { existsSync, mkdtempSync, readFileSync, writeFileSync, rmSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { gitClone, gitRevParseHead } from "../gitOps.js";
|
|
5
|
+
import { installPluginFromPath } from "./install.js";
|
|
6
|
+
import { pluginMetaPath } from "./paths.js";
|
|
7
|
+
import { PluginInstallError } from "./types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Remote install orchestrator: a thin bridge over the existing pieces. Clone
|
|
10
|
+
* the git source to a private temp dir, hand the (sub)directory to the local
|
|
11
|
+
* installer (which does CC/Codex detect + convert + register), then rewrite
|
|
12
|
+
* the recorded `.cs-meta.json` source back to the original git string so
|
|
13
|
+
* `plugin list`/`update` see the git source instead of the throwaway clone.
|
|
14
|
+
*
|
|
15
|
+
* Guarantees: on any failure nothing is left behind — the temp clone is always
|
|
16
|
+
* removed, and `installPluginFromPath` itself leaves no half-built install dir.
|
|
17
|
+
* See spec docs/superpowers/specs/2026-05-29-plugin-remote-install-design.md.
|
|
18
|
+
*/
|
|
19
|
+
export async function installPluginFromSource(parsed, name, installedAt) {
|
|
20
|
+
if (parsed.kind !== "remote") {
|
|
21
|
+
throw new PluginInstallError("installPluginFromSource expects a remote source");
|
|
22
|
+
}
|
|
23
|
+
const tmp = mkdtempSync(join(tmpdir(), "cs-tmp-clone-"));
|
|
24
|
+
try {
|
|
25
|
+
const clone = await gitClone(parsed.url, tmp, { ref: parsed.ref, full: true });
|
|
26
|
+
if (!clone.ok) {
|
|
27
|
+
throw new PluginInstallError(`clone failed: ${clone.error}`);
|
|
28
|
+
}
|
|
29
|
+
const realSrc = parsed.subdir ? join(tmp, parsed.subdir) : tmp;
|
|
30
|
+
if (!existsSync(realSrc) || !statSync(realSrc).isDirectory()) {
|
|
31
|
+
throw new PluginInstallError(`subdir not found in repo: ${parsed.subdir}`);
|
|
32
|
+
}
|
|
33
|
+
const dir = await installPluginFromPath(realSrc, name, installedAt);
|
|
34
|
+
// Rewrite source: realSrc is the throwaway clone path; record the git
|
|
35
|
+
// string so list/update can re-clone later.
|
|
36
|
+
const metaPath = pluginMetaPath(name);
|
|
37
|
+
const meta = JSON.parse(readFileSync(metaPath, "utf-8"));
|
|
38
|
+
meta.source = parsed.raw;
|
|
39
|
+
// Record the cloned repo's HEAD sha so `checkPluginUpdate` can compare it
|
|
40
|
+
// against `git ls-remote` later. A failed rev-parse only means "can't check
|
|
41
|
+
// updates", never an install failure — so omit commit and carry on.
|
|
42
|
+
const head = await gitRevParseHead(tmp);
|
|
43
|
+
if (head.ok)
|
|
44
|
+
meta.commit = head.stdout;
|
|
45
|
+
writeFileSync(metaPath, JSON.stringify(meta, null, 2));
|
|
46
|
+
return dir;
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface PluginListRow {
|
|
2
|
+
name: string;
|
|
3
|
+
format: "cc" | "codex";
|
|
4
|
+
version?: string;
|
|
5
|
+
source: string;
|
|
6
|
+
installedAt: string;
|
|
7
|
+
}
|
|
8
|
+
/** Read .cs-meta.json from each registered plugin dir that has one (local installs). */
|
|
9
|
+
export declare function listInstalledPlugins(): PluginListRow[];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { readInstalledPlugins } from "../installedPlugins.js";
|
|
4
|
+
import { CSMeta } from "./types.js";
|
|
5
|
+
/** Read .cs-meta.json from each registered plugin dir that has one (local installs). */
|
|
6
|
+
export function listInstalledPlugins() {
|
|
7
|
+
const rows = [];
|
|
8
|
+
const data = readInstalledPlugins();
|
|
9
|
+
for (const entries of Object.values(data.plugins)) {
|
|
10
|
+
for (const entry of entries) {
|
|
11
|
+
const metaPath = join(entry.installPath, ".cs-meta.json");
|
|
12
|
+
if (!existsSync(metaPath))
|
|
13
|
+
continue;
|
|
14
|
+
try {
|
|
15
|
+
const meta = CSMeta.parse(JSON.parse(readFileSync(metaPath, "utf-8")));
|
|
16
|
+
rows.push({
|
|
17
|
+
name: meta.name,
|
|
18
|
+
format: meta.format,
|
|
19
|
+
version: meta.version,
|
|
20
|
+
source: meta.source,
|
|
21
|
+
installedAt: meta.installedAt,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// not a local cs-managed install; skip
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return rows;
|
|
30
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { readInstalledPlugins } from "../installedPlugins.js";
|
|
4
|
+
function pluginNameFromKey(key) {
|
|
5
|
+
const at = key.lastIndexOf("@");
|
|
6
|
+
return at > 0 ? key.slice(0, at) : key;
|
|
7
|
+
}
|
|
8
|
+
/** Agent source dirs contributed by installed plugins (each <installPath>/agents). */
|
|
9
|
+
export function pluginAgentDirs(disabledPlugins = []) {
|
|
10
|
+
const disabled = new Set(disabledPlugins);
|
|
11
|
+
const out = [];
|
|
12
|
+
const data = readInstalledPlugins();
|
|
13
|
+
for (const [key, entries] of Object.entries(data.plugins)) {
|
|
14
|
+
const pluginName = pluginNameFromKey(key);
|
|
15
|
+
if (disabled.has(pluginName))
|
|
16
|
+
continue;
|
|
17
|
+
for (const entry of entries) {
|
|
18
|
+
const dir = join(entry.installPath, "agents");
|
|
19
|
+
// Carry pluginName so a plugin agent's bare skill allowlist
|
|
20
|
+
// (`director-skill`) can be namespaced to `<pluginName>:director-skill`
|
|
21
|
+
// at spawn time — see resolveAgentTypeOverrides.
|
|
22
|
+
if (existsSync(dir))
|
|
23
|
+
out.push({ dir, source: "plugin", pluginName });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { MCPServerConfig, MCPServerOverride } from "../../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Merge each registered plugin's MCP servers into a copy of `base`.
|
|
4
|
+
* Plugin keys are `<plugin>:<server>`. A key already present in `base`
|
|
5
|
+
* (user-configured) is NOT overwritten. Disabled plugins are skipped.
|
|
6
|
+
*
|
|
7
|
+
* `overrides` lets the user *supplement* a plugin server's env/credential
|
|
8
|
+
* fields without editing the plugin's manifest: for a plugin-sourced server,
|
|
9
|
+
* the override's {@link OVERRIDE_FIELDS} are layered on top (override wins),
|
|
10
|
+
* while command/args/url/transport stay from the plugin. Overrides do NOT
|
|
11
|
+
* apply to user-added (base) servers — those are edited via `mcpServers`
|
|
12
|
+
* directly — and an override for an unknown/disabled server has no effect.
|
|
13
|
+
*/
|
|
14
|
+
export declare function mergePluginMcpServers(base: Record<string, MCPServerConfig>, disabledPlugins?: string[], overrides?: Record<string, MCPServerOverride>): Record<string, MCPServerConfig>;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { readInstalledPlugins } from "../installedPlugins.js";
|
|
4
|
+
function pluginNameFromKey(key) {
|
|
5
|
+
const at = key.lastIndexOf("@");
|
|
6
|
+
return at > 0 ? key.slice(0, at) : key;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Layer a user override's supplement fields onto a plugin server config.
|
|
10
|
+
*
|
|
11
|
+
* Only env/credential fields are picked — command/args/url/transport are
|
|
12
|
+
* deliberately NOT carried, because those are the plugin's identity and must
|
|
13
|
+
* keep coming from the plugin manifest so a plugin update can change them
|
|
14
|
+
* without the user being stuck on a stale shadow copy. This explicit pick is
|
|
15
|
+
* defense-in-depth on top of the schema's `.strict()`, so a hand-edited
|
|
16
|
+
* settings file can never smuggle those fields in.
|
|
17
|
+
*/
|
|
18
|
+
function applyOverride(pluginConfig, override) {
|
|
19
|
+
if (!override)
|
|
20
|
+
return pluginConfig;
|
|
21
|
+
const supplement = {};
|
|
22
|
+
if (override.env !== undefined)
|
|
23
|
+
supplement.env = override.env;
|
|
24
|
+
if (override.envVars !== undefined)
|
|
25
|
+
supplement.envVars = override.envVars;
|
|
26
|
+
if (override.credentialRef !== undefined)
|
|
27
|
+
supplement.credentialRef = override.credentialRef;
|
|
28
|
+
if (override.bearerTokenEnvVar !== undefined)
|
|
29
|
+
supplement.bearerTokenEnvVar = override.bearerTokenEnvVar;
|
|
30
|
+
if (override.envHeaders !== undefined)
|
|
31
|
+
supplement.envHeaders = override.envHeaders;
|
|
32
|
+
return { ...pluginConfig, ...supplement };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Read a single plugin's MCP servers, already keyed `<plugin>:<server>`.
|
|
36
|
+
*
|
|
37
|
+
* Two on-disk shapes are supported:
|
|
38
|
+
* - `mcp-servers.json` — the Codex-install product: already keyed + named.
|
|
39
|
+
* - `.mcp.json` — what a CC plugin ships verbatim (Docker's mcp-toolkit etc.).
|
|
40
|
+
* It uses a `{ mcpServers: {...} }` wrapper with bare server names; we unwrap
|
|
41
|
+
* it and apply the `<plugin>:` prefix + `name` so it matches the keyed shape.
|
|
42
|
+
*
|
|
43
|
+
* `mcp-servers.json` wins if both exist. Malformed files yield {} (must not
|
|
44
|
+
* break startup).
|
|
45
|
+
*/
|
|
46
|
+
function readPluginMcp(installPath, pluginName) {
|
|
47
|
+
const keyedPath = join(installPath, "mcp-servers.json");
|
|
48
|
+
if (existsSync(keyedPath)) {
|
|
49
|
+
try {
|
|
50
|
+
return JSON.parse(readFileSync(keyedPath, "utf-8"));
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return {};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const rawPath = join(installPath, ".mcp.json");
|
|
57
|
+
if (existsSync(rawPath)) {
|
|
58
|
+
let parsed;
|
|
59
|
+
try {
|
|
60
|
+
parsed = JSON.parse(readFileSync(rawPath, "utf-8"));
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return {};
|
|
64
|
+
}
|
|
65
|
+
const servers = parsed && typeof parsed === "object" && "mcpServers" in parsed
|
|
66
|
+
? parsed.mcpServers ?? {}
|
|
67
|
+
: parsed ?? {};
|
|
68
|
+
const keyed = {};
|
|
69
|
+
for (const [serverName, cfg] of Object.entries(servers)) {
|
|
70
|
+
const key = `${pluginName}:${serverName}`;
|
|
71
|
+
keyed[key] = { ...cfg, name: key };
|
|
72
|
+
}
|
|
73
|
+
return keyed;
|
|
74
|
+
}
|
|
75
|
+
return {};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Merge each registered plugin's MCP servers into a copy of `base`.
|
|
79
|
+
* Plugin keys are `<plugin>:<server>`. A key already present in `base`
|
|
80
|
+
* (user-configured) is NOT overwritten. Disabled plugins are skipped.
|
|
81
|
+
*
|
|
82
|
+
* `overrides` lets the user *supplement* a plugin server's env/credential
|
|
83
|
+
* fields without editing the plugin's manifest: for a plugin-sourced server,
|
|
84
|
+
* the override's {@link OVERRIDE_FIELDS} are layered on top (override wins),
|
|
85
|
+
* while command/args/url/transport stay from the plugin. Overrides do NOT
|
|
86
|
+
* apply to user-added (base) servers — those are edited via `mcpServers`
|
|
87
|
+
* directly — and an override for an unknown/disabled server has no effect.
|
|
88
|
+
*/
|
|
89
|
+
export function mergePluginMcpServers(base, disabledPlugins = [], overrides = {}) {
|
|
90
|
+
const disabled = new Set(disabledPlugins);
|
|
91
|
+
const merged = { ...base };
|
|
92
|
+
const data = readInstalledPlugins();
|
|
93
|
+
for (const [key, entries] of Object.entries(data.plugins)) {
|
|
94
|
+
const pluginName = pluginNameFromKey(key);
|
|
95
|
+
if (disabled.has(pluginName))
|
|
96
|
+
continue;
|
|
97
|
+
for (const entry of entries) {
|
|
98
|
+
const servers = readPluginMcp(entry.installPath, pluginName);
|
|
99
|
+
for (const [k, cfg] of Object.entries(servers)) {
|
|
100
|
+
if (k in merged)
|
|
101
|
+
continue; // user / earlier wins
|
|
102
|
+
merged[k] = applyOverride(cfg, overrides[k]);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return merged;
|
|
107
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result of classifying a `plugin install <source>` argument. Pure parse — no
|
|
3
|
+
* I/O, no execution. `local` resolves to an absolute path; `remote` carries a
|
|
4
|
+
* git-cloneable URL plus optional ref/subdir and the original raw string
|
|
5
|
+
* (written back into .cs-meta.json so `plugin list`/`update` see the git
|
|
6
|
+
* source, not the throwaway clone path). See spec
|
|
7
|
+
* docs/superpowers/specs/2026-05-29-plugin-remote-install-design.md §4–§5.
|
|
8
|
+
*/
|
|
9
|
+
export type ParsedSource = {
|
|
10
|
+
kind: "local";
|
|
11
|
+
path: string;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "remote";
|
|
14
|
+
url: string;
|
|
15
|
+
ref?: string;
|
|
16
|
+
subdir?: string;
|
|
17
|
+
raw: string;
|
|
18
|
+
inferredName: string;
|
|
19
|
+
};
|
|
20
|
+
export declare function parseSource(input: string): ParsedSource;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { githubRepoToCloneUrl } from "../gitOps.js";
|
|
3
|
+
/** SSH shorthand `git@host:org/repo.git` — has a `:` after the `git@host` part. */
|
|
4
|
+
function isSshUrl(s) {
|
|
5
|
+
return /^[^/]+@[^/]+:/.test(s) && !s.includes("://");
|
|
6
|
+
}
|
|
7
|
+
function isRemote(s) {
|
|
8
|
+
return (s.startsWith("github:") ||
|
|
9
|
+
s.startsWith("https://") ||
|
|
10
|
+
s.startsWith("http://") ||
|
|
11
|
+
s.startsWith("git://") ||
|
|
12
|
+
s.startsWith("file://") ||
|
|
13
|
+
isSshUrl(s));
|
|
14
|
+
}
|
|
15
|
+
/** Last path segment of a repo url/path, with a trailing `.git` stripped. */
|
|
16
|
+
function repoNameFromUrl(url) {
|
|
17
|
+
const noGit = url.replace(/\.git$/, "");
|
|
18
|
+
const seg = noGit.split(/[/:]/).filter(Boolean).pop() ?? noGit;
|
|
19
|
+
return seg;
|
|
20
|
+
}
|
|
21
|
+
/** Last path segment of a subdir. */
|
|
22
|
+
function lastSegment(p) {
|
|
23
|
+
return p.split("/").filter(Boolean).pop() ?? p;
|
|
24
|
+
}
|
|
25
|
+
export function parseSource(input) {
|
|
26
|
+
if (!isRemote(input)) {
|
|
27
|
+
return { kind: "local", path: resolve(input) };
|
|
28
|
+
}
|
|
29
|
+
const raw = input;
|
|
30
|
+
// 1. Split off `#subdir` (last `#`).
|
|
31
|
+
let rest = input;
|
|
32
|
+
let subdir;
|
|
33
|
+
const hashIdx = rest.indexOf("#");
|
|
34
|
+
if (hashIdx >= 0) {
|
|
35
|
+
subdir = rest.slice(hashIdx + 1) || undefined;
|
|
36
|
+
rest = rest.slice(0, hashIdx);
|
|
37
|
+
}
|
|
38
|
+
// 2. Split off `@ref`. SSH form `git@host:...` contains its own `@`, so
|
|
39
|
+
// strip the leading `user@` first, then look for a ref `@` in the tail.
|
|
40
|
+
let ref;
|
|
41
|
+
let base = rest;
|
|
42
|
+
if (isSshUrl(rest)) {
|
|
43
|
+
const at = rest.indexOf("@");
|
|
44
|
+
const head = rest.slice(0, at + 1); // "git@"
|
|
45
|
+
const tail = rest.slice(at + 1); // "host:org/repo.git@ref"
|
|
46
|
+
const tailAt = tail.lastIndexOf("@");
|
|
47
|
+
if (tailAt >= 0) {
|
|
48
|
+
ref = tail.slice(tailAt + 1) || undefined;
|
|
49
|
+
base = head + tail.slice(0, tailAt);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const at = rest.lastIndexOf("@");
|
|
54
|
+
if (at >= 0) {
|
|
55
|
+
ref = rest.slice(at + 1) || undefined;
|
|
56
|
+
base = rest.slice(0, at);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// 3. Normalize url.
|
|
60
|
+
let url;
|
|
61
|
+
if (base.startsWith("github:")) {
|
|
62
|
+
url = githubRepoToCloneUrl(base.slice("github:".length));
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
url = base;
|
|
66
|
+
}
|
|
67
|
+
const inferredName = subdir ? lastSegment(subdir) : repoNameFromUrl(url);
|
|
68
|
+
const result = { kind: "remote", url, raw, inferredName };
|
|
69
|
+
if (ref)
|
|
70
|
+
result.ref = ref;
|
|
71
|
+
if (subdir)
|
|
72
|
+
result.subdir = subdir;
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** A plugin name must be a single safe path segment — no separators, no traversal. */
|
|
2
|
+
export declare function assertSafePluginName(name: string): void;
|
|
3
|
+
export declare function pluginsRoot(): string;
|
|
4
|
+
export declare function pluginInstallDir(name: string): string;
|
|
5
|
+
export declare function pluginMetaPath(name: string): string;
|