@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,25 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { PluginInstallError } from "./types.js";
|
|
4
|
+
function userHome() {
|
|
5
|
+
return process.env.HOME ?? homedir();
|
|
6
|
+
}
|
|
7
|
+
/** A plugin name must be a single safe path segment — no separators, no traversal. */
|
|
8
|
+
export function assertSafePluginName(name) {
|
|
9
|
+
if (!name || name === "." || name === "..") {
|
|
10
|
+
throw new PluginInstallError(`invalid plugin name: ${JSON.stringify(name)}`);
|
|
11
|
+
}
|
|
12
|
+
if (name.includes("/") || name.includes("\\") || name.includes("\0")) {
|
|
13
|
+
throw new PluginInstallError(`plugin name must be a single path segment: ${JSON.stringify(name)}`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function pluginsRoot() {
|
|
17
|
+
return join(userHome(), ".code-shell", "plugins");
|
|
18
|
+
}
|
|
19
|
+
export function pluginInstallDir(name) {
|
|
20
|
+
assertSafePluginName(name);
|
|
21
|
+
return join(pluginsRoot(), name);
|
|
22
|
+
}
|
|
23
|
+
export function pluginMetaPath(name) {
|
|
24
|
+
return join(pluginInstallDir(name), ".cs-meta.json");
|
|
25
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prune a plugin's orphaned entries from a settings object's `disabledSkills`
|
|
3
|
+
* (entries shaped `name:skill`) and `disabledPlugins` (bare `name`). Called on
|
|
4
|
+
* uninstall so a removed plugin leaves no dangling disable flags behind.
|
|
5
|
+
*
|
|
6
|
+
* Pure + immutable: returns a NEW object (shallow clone) with the two arrays
|
|
7
|
+
* replaced by filtered copies. Settings lacking these fields pass through
|
|
8
|
+
* unchanged. A plugin name that is a prefix of another (`mimi-video` vs
|
|
9
|
+
* `mimi-video-pro`) only matches its own exact name / `name:` prefix.
|
|
10
|
+
*/
|
|
11
|
+
export interface PrunableSettings {
|
|
12
|
+
disabledSkills?: string[];
|
|
13
|
+
disabledPlugins?: string[];
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
export declare function pruneDisabledEntriesForPlugin<T extends PrunableSettings>(settings: T, pluginName: string): T;
|
|
17
|
+
/**
|
|
18
|
+
* Read the user settings.json (under {@link userHome}, so HOME-isolated tests
|
|
19
|
+
* are honored), prune the plugin's orphaned disable entries, and write back —
|
|
20
|
+
* only when something actually changed. Never throws: a missing/corrupt file or
|
|
21
|
+
* any IO error is swallowed (uninstall already succeeded; settings cleanup is
|
|
22
|
+
* best-effort). Atomic write via .tmp + rename mirrors SettingsManager.
|
|
23
|
+
*/
|
|
24
|
+
export declare function pruneDisabledSettingsForPlugin(pluginName: string): void;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prune a plugin's orphaned entries from a settings object's `disabledSkills`
|
|
3
|
+
* (entries shaped `name:skill`) and `disabledPlugins` (bare `name`). Called on
|
|
4
|
+
* uninstall so a removed plugin leaves no dangling disable flags behind.
|
|
5
|
+
*
|
|
6
|
+
* Pure + immutable: returns a NEW object (shallow clone) with the two arrays
|
|
7
|
+
* replaced by filtered copies. Settings lacking these fields pass through
|
|
8
|
+
* unchanged. A plugin name that is a prefix of another (`mimi-video` vs
|
|
9
|
+
* `mimi-video-pro`) only matches its own exact name / `name:` prefix.
|
|
10
|
+
*/
|
|
11
|
+
import { writeFileSync, mkdirSync, existsSync, readFileSync, renameSync } from "node:fs";
|
|
12
|
+
import { join, dirname } from "node:path";
|
|
13
|
+
import { homedir } from "node:os";
|
|
14
|
+
/**
|
|
15
|
+
* Resolve the user's home dir, preferring `process.env.HOME` so HOME-isolated
|
|
16
|
+
* tests (and runtime overrides) take effect — same contract as
|
|
17
|
+
* SettingsManager.userHome and installer/paths.ts, without dragging in the
|
|
18
|
+
* settings module's heavier transitive deps.
|
|
19
|
+
*/
|
|
20
|
+
function userHome() {
|
|
21
|
+
return process.env.HOME ?? homedir();
|
|
22
|
+
}
|
|
23
|
+
export function pruneDisabledEntriesForPlugin(settings, pluginName) {
|
|
24
|
+
const skillPrefix = `${pluginName}:`;
|
|
25
|
+
const out = { ...settings };
|
|
26
|
+
if (Array.isArray(settings.disabledSkills)) {
|
|
27
|
+
out.disabledSkills = settings.disabledSkills.filter((s) => !s.startsWith(skillPrefix));
|
|
28
|
+
}
|
|
29
|
+
if (Array.isArray(settings.disabledPlugins)) {
|
|
30
|
+
out.disabledPlugins = settings.disabledPlugins.filter((p) => p !== pluginName);
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Read the user settings.json (under {@link userHome}, so HOME-isolated tests
|
|
36
|
+
* are honored), prune the plugin's orphaned disable entries, and write back —
|
|
37
|
+
* only when something actually changed. Never throws: a missing/corrupt file or
|
|
38
|
+
* any IO error is swallowed (uninstall already succeeded; settings cleanup is
|
|
39
|
+
* best-effort). Atomic write via .tmp + rename mirrors SettingsManager.
|
|
40
|
+
*/
|
|
41
|
+
export function pruneDisabledSettingsForPlugin(pluginName) {
|
|
42
|
+
try {
|
|
43
|
+
const path = join(userHome(), ".code-shell", "settings.json");
|
|
44
|
+
if (!existsSync(path))
|
|
45
|
+
return;
|
|
46
|
+
let current;
|
|
47
|
+
try {
|
|
48
|
+
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
49
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
50
|
+
return;
|
|
51
|
+
current = parsed;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return; // corrupt file — leave it alone
|
|
55
|
+
}
|
|
56
|
+
const pruned = pruneDisabledEntriesForPlugin(current, pluginName);
|
|
57
|
+
const changed = JSON.stringify(pruned.disabledSkills) !== JSON.stringify(current.disabledSkills) ||
|
|
58
|
+
JSON.stringify(pruned.disabledPlugins) !== JSON.stringify(current.disabledPlugins);
|
|
59
|
+
if (!changed)
|
|
60
|
+
return;
|
|
61
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
62
|
+
const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
63
|
+
// mode 0o600 — settings.json can hold plaintext API keys, so the pruned
|
|
64
|
+
// rewrite must stay owner-only (matching settings/manager.ts), not fall back
|
|
65
|
+
// to the umask default 0o644 (world-readable). The tmp IS the final file
|
|
66
|
+
// after renameSync, so the mode must be set at create time, not via chmod.
|
|
67
|
+
writeFileSync(tmp, JSON.stringify(pruned, null, 2), { encoding: "utf-8", mode: 0o600 });
|
|
68
|
+
renameSync(tmp, path);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// best-effort cleanup — never fail the uninstall over settings IO
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Codex `.codex-plugin/plugin.json`. v1 reads required fields; unknowns pass through. */
|
|
3
|
+
export declare const CodexPluginManifest: z.ZodObject<{
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
version: z.ZodString;
|
|
6
|
+
description: z.ZodOptional<z.ZodString>;
|
|
7
|
+
mcpServers: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodAny>]>>;
|
|
8
|
+
skills: z.ZodOptional<z.ZodString>;
|
|
9
|
+
agents: z.ZodOptional<z.ZodString>;
|
|
10
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
11
|
+
name: z.ZodString;
|
|
12
|
+
version: z.ZodString;
|
|
13
|
+
description: z.ZodOptional<z.ZodString>;
|
|
14
|
+
mcpServers: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodAny>]>>;
|
|
15
|
+
skills: z.ZodOptional<z.ZodString>;
|
|
16
|
+
agents: z.ZodOptional<z.ZodString>;
|
|
17
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
18
|
+
name: z.ZodString;
|
|
19
|
+
version: z.ZodString;
|
|
20
|
+
description: z.ZodOptional<z.ZodString>;
|
|
21
|
+
mcpServers: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodAny>]>>;
|
|
22
|
+
skills: z.ZodOptional<z.ZodString>;
|
|
23
|
+
agents: z.ZodOptional<z.ZodString>;
|
|
24
|
+
}, z.ZodTypeAny, "passthrough">>;
|
|
25
|
+
export type CodexPluginManifest = z.infer<typeof CodexPluginManifest>;
|
|
26
|
+
/** `.cs-meta.json` written into every installed plugin dir. */
|
|
27
|
+
export declare const CSMeta: z.ZodObject<{
|
|
28
|
+
name: z.ZodString;
|
|
29
|
+
format: z.ZodEnum<["cc", "codex"]>;
|
|
30
|
+
version: z.ZodOptional<z.ZodString>;
|
|
31
|
+
source: z.ZodString;
|
|
32
|
+
installedAt: z.ZodString;
|
|
33
|
+
commit: z.ZodOptional<z.ZodString>;
|
|
34
|
+
}, "strip", z.ZodTypeAny, {
|
|
35
|
+
source: string;
|
|
36
|
+
name: string;
|
|
37
|
+
format: "cc" | "codex";
|
|
38
|
+
installedAt: string;
|
|
39
|
+
version?: string | undefined;
|
|
40
|
+
commit?: string | undefined;
|
|
41
|
+
}, {
|
|
42
|
+
source: string;
|
|
43
|
+
name: string;
|
|
44
|
+
format: "cc" | "codex";
|
|
45
|
+
installedAt: string;
|
|
46
|
+
version?: string | undefined;
|
|
47
|
+
commit?: string | undefined;
|
|
48
|
+
}>;
|
|
49
|
+
export type CSMeta = z.infer<typeof CSMeta>;
|
|
50
|
+
export declare class PluginInstallError extends Error {
|
|
51
|
+
constructor(message: string);
|
|
52
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Codex `.codex-plugin/plugin.json`. v1 reads required fields; unknowns pass through. */
|
|
3
|
+
export const CodexPluginManifest = z
|
|
4
|
+
.object({
|
|
5
|
+
name: z.string(),
|
|
6
|
+
version: z.string(),
|
|
7
|
+
description: z.string().optional(),
|
|
8
|
+
// string → relative path to a .mcp.json; object → inline mcpServers map
|
|
9
|
+
mcpServers: z.union([z.string(), z.record(z.any())]).optional(),
|
|
10
|
+
skills: z.string().optional(),
|
|
11
|
+
agents: z.string().optional(),
|
|
12
|
+
})
|
|
13
|
+
.passthrough();
|
|
14
|
+
/** `.cs-meta.json` written into every installed plugin dir. */
|
|
15
|
+
export const CSMeta = z.object({
|
|
16
|
+
name: z.string(),
|
|
17
|
+
format: z.enum(["cc", "codex"]),
|
|
18
|
+
version: z.string().optional(),
|
|
19
|
+
source: z.string(),
|
|
20
|
+
installedAt: z.string(),
|
|
21
|
+
commit: z.string().optional(), // remote (git) source: the HEAD SHA we installed
|
|
22
|
+
});
|
|
23
|
+
export class PluginInstallError extends Error {
|
|
24
|
+
constructor(message) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.name = "PluginInstallError";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { existsSync, rmSync } from "node:fs";
|
|
2
|
+
import { pluginInstallDir, assertSafePluginName } from "./paths.js";
|
|
3
|
+
import { removeInstallEntries, pluginInstallKey } from "../installedPlugins.js";
|
|
4
|
+
import { PluginInstallError } from "./types.js";
|
|
5
|
+
import { pruneDisabledSettingsForPlugin } from "./pruneDisabled.js";
|
|
6
|
+
/** Remove a locally-installed plugin dir + its installed_plugins.json entry. */
|
|
7
|
+
export function uninstallPluginByName(name) {
|
|
8
|
+
assertSafePluginName(name);
|
|
9
|
+
const dir = pluginInstallDir(name);
|
|
10
|
+
if (!existsSync(dir)) {
|
|
11
|
+
throw new PluginInstallError(`no plugin named '${name}'`);
|
|
12
|
+
}
|
|
13
|
+
rmSync(dir, { recursive: true, force: true });
|
|
14
|
+
removeInstallEntries(pluginInstallKey(name, "local"));
|
|
15
|
+
// Clear orphaned disable flags (disabledSkills "name:skill" /
|
|
16
|
+
// disabledPlugins "name") so a removed plugin leaves no dangling entries.
|
|
17
|
+
pruneDisabledSettingsForPlugin(name);
|
|
18
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reject path traversal ("zip slip"): a malicious archive can carry entries
|
|
3
|
+
* like `../../etc/foo` that escape the extraction root. We normalize and
|
|
4
|
+
* require the resolved path to stay within `destDir`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function safeJoin(destDir: string, entryName: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Extract a .zip into destDir (must already exist). Streams each entry to disk
|
|
9
|
+
* so a large archive doesn't buffer in memory. Directory entries (trailing
|
|
10
|
+
* "/") just create the dir; symlinks and other special entries are skipped —
|
|
11
|
+
* we only materialize regular files and directories, which is all a plugin
|
|
12
|
+
* needs and keeps the surface safe.
|
|
13
|
+
*/
|
|
14
|
+
export declare function extractZip(zipPath: string, destDir: string): Promise<void>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { createWriteStream } from "node:fs";
|
|
3
|
+
import { mkdir } from "node:fs/promises";
|
|
4
|
+
import { dirname, join, normalize, sep } from "node:path";
|
|
5
|
+
import { pipeline } from "node:stream/promises";
|
|
6
|
+
import { PluginInstallError } from "./types.js";
|
|
7
|
+
let _yauzl;
|
|
8
|
+
function yauzl() {
|
|
9
|
+
if (!_yauzl) {
|
|
10
|
+
_yauzl = createRequire(import.meta.url ?? __filename)("yauzl");
|
|
11
|
+
}
|
|
12
|
+
return _yauzl;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Reject path traversal ("zip slip"): a malicious archive can carry entries
|
|
16
|
+
* like `../../etc/foo` that escape the extraction root. We normalize and
|
|
17
|
+
* require the resolved path to stay within `destDir`.
|
|
18
|
+
*/
|
|
19
|
+
export function safeJoin(destDir, entryName) {
|
|
20
|
+
// Zip entries always use forward slashes; normalize to the host separator.
|
|
21
|
+
const target = normalize(join(destDir, entryName));
|
|
22
|
+
const root = normalize(destDir.endsWith(sep) ? destDir : destDir + sep);
|
|
23
|
+
if (target !== normalize(destDir) && !target.startsWith(root)) {
|
|
24
|
+
throw new PluginInstallError(`refusing zip entry that escapes target: ${entryName}`);
|
|
25
|
+
}
|
|
26
|
+
return target;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Extract a .zip into destDir (must already exist). Streams each entry to disk
|
|
30
|
+
* so a large archive doesn't buffer in memory. Directory entries (trailing
|
|
31
|
+
* "/") just create the dir; symlinks and other special entries are skipped —
|
|
32
|
+
* we only materialize regular files and directories, which is all a plugin
|
|
33
|
+
* needs and keeps the surface safe.
|
|
34
|
+
*/
|
|
35
|
+
export async function extractZip(zipPath, destDir) {
|
|
36
|
+
const zip = await openZip(zipPath);
|
|
37
|
+
try {
|
|
38
|
+
await drainEntries(zip, destDir);
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
zip.close();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function openZip(zipPath) {
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
yauzl().open(zipPath, { lazyEntries: true }, (err, z) => {
|
|
47
|
+
if (err || !z) {
|
|
48
|
+
reject(new PluginInstallError(`cannot open zip: ${err?.message ?? "unknown"}`));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
resolve(z);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function drainEntries(zip, destDir) {
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
zip.on("error", (e) => reject(e));
|
|
58
|
+
zip.on("end", () => resolve());
|
|
59
|
+
zip.on("entry", (entry) => {
|
|
60
|
+
const onErr = (e) => reject(e);
|
|
61
|
+
// Directory entry — yauzl signals these with a trailing slash.
|
|
62
|
+
if (/\/$/.test(entry.fileName)) {
|
|
63
|
+
mkdir(safeJoin(destDir, entry.fileName), { recursive: true })
|
|
64
|
+
.then(() => zip.readEntry())
|
|
65
|
+
.catch(onErr);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const outPath = safeJoin(destDir, entry.fileName);
|
|
69
|
+
zip.openReadStream(entry, (err, stream) => {
|
|
70
|
+
if (err || !stream) {
|
|
71
|
+
onErr(new PluginInstallError(`cannot read zip entry ${entry.fileName}: ${err?.message ?? "unknown"}`));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
mkdir(dirname(outPath), { recursive: true })
|
|
75
|
+
.then(() => pipeline(stream, createWriteStream(outPath)))
|
|
76
|
+
.then(() => zip.readEntry())
|
|
77
|
+
.catch(onErr);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
zip.readEntry();
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface UpdateResult {
|
|
2
|
+
updated: boolean;
|
|
3
|
+
reason: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Reinstall a plugin atomically: a failed update leaves the OLD plugin intact.
|
|
7
|
+
*
|
|
8
|
+
* The installers (installPluginFromPath / installPluginFromSource) build into a
|
|
9
|
+
* temp dir then rename into pluginInstallDir(name), and THROW if the final dir
|
|
10
|
+
* already exists. So we must free the final dir *before* installing — we do that
|
|
11
|
+
* by renaming the live dir to a sibling backup. On success we drop the backup;
|
|
12
|
+
* on failure we delete any partial install and rename the backup back.
|
|
13
|
+
*
|
|
14
|
+
* Async fs only — this runs in the Electron main process, so we never block the
|
|
15
|
+
* event loop with sync fs. process.pid (not Date.now(), unavailable here) makes
|
|
16
|
+
* the backup name unique.
|
|
17
|
+
*/
|
|
18
|
+
export declare function reinstallAtomic(name: string, source: string, doInstall: () => Promise<unknown>): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Reinstall a plugin from its recorded source.
|
|
21
|
+
*
|
|
22
|
+
* - Local source: reinstall when the source version changed, or when `force`.
|
|
23
|
+
* CC plugins have no version → only `force` updates them.
|
|
24
|
+
* - Remote (git) source: re-clone and reinstall every time — git sources carry
|
|
25
|
+
* no local version file to compare, so update is always a fresh pull
|
|
26
|
+
* (equivalent to `--force`; cheap and reliable). See spec §9.
|
|
27
|
+
*/
|
|
28
|
+
export declare function updatePluginByName(name: string, installedAt: string, force: boolean): Promise<UpdateResult>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { rename, rm } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { detectPluginFormat } from "./detectFormat.js";
|
|
5
|
+
import { pluginInstallDir } from "./paths.js";
|
|
6
|
+
import { installPluginFromPath } from "./install.js";
|
|
7
|
+
import { installPluginFromSource } from "./installFromSource.js";
|
|
8
|
+
import { parseSource } from "./parseSource.js";
|
|
9
|
+
import { pluginInstallKey, readInstalledPlugins, removeInstallEntries, writeInstalledPlugins } from "../installedPlugins.js";
|
|
10
|
+
import { CodexPluginManifest, CSMeta, PluginInstallError } from "./types.js";
|
|
11
|
+
/**
|
|
12
|
+
* Reinstall a plugin atomically: a failed update leaves the OLD plugin intact.
|
|
13
|
+
*
|
|
14
|
+
* The installers (installPluginFromPath / installPluginFromSource) build into a
|
|
15
|
+
* temp dir then rename into pluginInstallDir(name), and THROW if the final dir
|
|
16
|
+
* already exists. So we must free the final dir *before* installing — we do that
|
|
17
|
+
* by renaming the live dir to a sibling backup. On success we drop the backup;
|
|
18
|
+
* on failure we delete any partial install and rename the backup back.
|
|
19
|
+
*
|
|
20
|
+
* Async fs only — this runs in the Electron main process, so we never block the
|
|
21
|
+
* event loop with sync fs. process.pid (not Date.now(), unavailable here) makes
|
|
22
|
+
* the backup name unique.
|
|
23
|
+
*/
|
|
24
|
+
export async function reinstallAtomic(name, source, doInstall) {
|
|
25
|
+
const dir = pluginInstallDir(name);
|
|
26
|
+
const backup = `${dir}.bak-${process.pid}`;
|
|
27
|
+
// Capture the existing install_plugins.json entries so a failed reinstall can
|
|
28
|
+
// restore them (uninstall-then-install used to drop them on failure; here the
|
|
29
|
+
// old plugin survives, so its registration must survive too).
|
|
30
|
+
const key = pluginInstallKey(name, "local");
|
|
31
|
+
const savedEntries = readInstalledPlugins().plugins[key];
|
|
32
|
+
await rm(backup, { recursive: true, force: true });
|
|
33
|
+
await rename(dir, backup);
|
|
34
|
+
// The installer re-adds the entry on success; remove the stale one first so a
|
|
35
|
+
// successful reinstall doesn't accumulate a duplicate.
|
|
36
|
+
removeInstallEntries(key);
|
|
37
|
+
try {
|
|
38
|
+
await doInstall();
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
// Roll back: drop any partial install, restore the old dir + its entries.
|
|
42
|
+
await rm(dir, { recursive: true, force: true });
|
|
43
|
+
await rename(backup, dir);
|
|
44
|
+
if (savedEntries) {
|
|
45
|
+
// Restore in a single read-modify-write rather than one append per entry,
|
|
46
|
+
// which both narrows the race window against any concurrent writer and
|
|
47
|
+
// avoids re-appending onto whatever partial state doInstall() may have
|
|
48
|
+
// left for this key.
|
|
49
|
+
const data = readInstalledPlugins();
|
|
50
|
+
data.plugins[key] = savedEntries;
|
|
51
|
+
writeInstalledPlugins(data);
|
|
52
|
+
}
|
|
53
|
+
throw new PluginInstallError(`update failed; the old version of '${name}' was kept: ` +
|
|
54
|
+
`${err instanceof Error ? err.message : String(err)}. Source: ${source}.`);
|
|
55
|
+
}
|
|
56
|
+
// Success — drop the backup (best-effort; a leftover backup is harmless but
|
|
57
|
+
// we clean it up so it never shows up in the plugins root).
|
|
58
|
+
await rm(backup, { recursive: true, force: true });
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Reinstall a plugin from its recorded source.
|
|
62
|
+
*
|
|
63
|
+
* - Local source: reinstall when the source version changed, or when `force`.
|
|
64
|
+
* CC plugins have no version → only `force` updates them.
|
|
65
|
+
* - Remote (git) source: re-clone and reinstall every time — git sources carry
|
|
66
|
+
* no local version file to compare, so update is always a fresh pull
|
|
67
|
+
* (equivalent to `--force`; cheap and reliable). See spec §9.
|
|
68
|
+
*/
|
|
69
|
+
export async function updatePluginByName(name, installedAt, force) {
|
|
70
|
+
const dir = pluginInstallDir(name);
|
|
71
|
+
const metaPath = join(dir, ".cs-meta.json");
|
|
72
|
+
if (!existsSync(metaPath))
|
|
73
|
+
throw new PluginInstallError(`no plugin named '${name}'`);
|
|
74
|
+
const meta = CSMeta.parse(JSON.parse(readFileSync(metaPath, "utf-8")));
|
|
75
|
+
const parsed = parseSource(meta.source);
|
|
76
|
+
if (parsed.kind === "remote") {
|
|
77
|
+
// No local version to diff against — always re-clone and reinstall.
|
|
78
|
+
await reinstallAtomic(name, meta.source, () => installPluginFromSource(parsed, name, installedAt));
|
|
79
|
+
return { updated: true, reason: "reinstalled from git source" };
|
|
80
|
+
}
|
|
81
|
+
if (!existsSync(meta.source)) {
|
|
82
|
+
throw new PluginInstallError(`source no longer exists: ${meta.source}`);
|
|
83
|
+
}
|
|
84
|
+
if (!force) {
|
|
85
|
+
if (detectPluginFormat(meta.source) === "codex") {
|
|
86
|
+
const manifest = CodexPluginManifest.parse(JSON.parse(readFileSync(join(meta.source, ".codex-plugin", "plugin.json"), "utf-8")));
|
|
87
|
+
if (manifest.version === meta.version) {
|
|
88
|
+
return { updated: false, reason: "already up to date" };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
return { updated: false, reason: "CC plugin needs --force to reinstall" };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
await reinstallAtomic(name, meta.source, () => installPluginFromPath(meta.source, name, installedAt));
|
|
96
|
+
return { updated: true, reason: "reinstalled" };
|
|
97
|
+
}
|
|
@@ -42,11 +42,64 @@
|
|
|
42
42
|
* Errors are swallowed per-plugin: a malformed hooks.json from one plugin
|
|
43
43
|
* must not block other plugins from loading.
|
|
44
44
|
*/
|
|
45
|
+
import type { HookEventName } from "../hooks/events.js";
|
|
45
46
|
import type { HookRegistry } from "../hooks/registry.js";
|
|
47
|
+
/**
|
|
48
|
+
* Stable identity for ONE plugin-provided hook, used as the record key in
|
|
49
|
+
* `capabilityOverrides.pluginHooks` (per-hook project off-switch). Derived
|
|
50
|
+
* from content (`plugin:RawEvent:command`) rather than scan order so it
|
|
51
|
+
* survives plugin reinstalls and hooks.json reordering. Two entries that
|
|
52
|
+
* differ only by matcher collide — acceptable: toggling one toggles both,
|
|
53
|
+
* and identical commands on the same event are in practice the same hook.
|
|
54
|
+
*/
|
|
55
|
+
export declare function pluginHookKey(hook: {
|
|
56
|
+
plugin: string;
|
|
57
|
+
rawEvent: string;
|
|
58
|
+
command: string;
|
|
59
|
+
}): string;
|
|
46
60
|
/**
|
|
47
61
|
* Walk installed plugins and register their command hooks. Safe to call
|
|
48
62
|
* multiple times — the caller is responsible for not double-registering
|
|
49
63
|
* (HookRegistry has no de-dup; the engine constructor calls this exactly
|
|
50
64
|
* once after creating the registry).
|
|
65
|
+
*
|
|
66
|
+
* `disabledPlugins` is the coarse "plugin total switch" — bare plugin names
|
|
67
|
+
* (no `@marketplace`, no `:` suffix), matching scanSkills' semantics. A
|
|
68
|
+
* disabled plugin contributes NO hooks, so e.g. disabling "superpowers"
|
|
69
|
+
* also suppresses its SessionStart injection — not just its Skill-tool
|
|
70
|
+
* entries. Without this, `disabledPlugins` only filtered the skill list and
|
|
71
|
+
* the plugin's hooks still fired regardless.
|
|
72
|
+
*
|
|
73
|
+
* `disabledPluginHooks` is the fine-grained per-hook switch — a list of
|
|
74
|
+
* {@link pluginHookKey} keys (folded from the project's
|
|
75
|
+
* `capabilityOverrides.pluginHooks` by readDisabledLists). A matching hook
|
|
76
|
+
* is skipped while the rest of the plugin keeps working.
|
|
77
|
+
*/
|
|
78
|
+
export declare function loadPluginHooks(registry: HookRegistry, disabledPlugins?: string[], disabledPluginHooks?: string[]): void;
|
|
79
|
+
/** A single plugin-provided hook, surfaced read-only to the settings UI. */
|
|
80
|
+
export interface PluginHookEntry {
|
|
81
|
+
/** Source plugin name (bare, no @marketplace). */
|
|
82
|
+
plugin: string;
|
|
83
|
+
/** Mapped codeshell event name. */
|
|
84
|
+
event: HookEventName;
|
|
85
|
+
/** Original CC event name as written in hooks.json (for display). */
|
|
86
|
+
rawEvent: string;
|
|
87
|
+
/** The shell command the hook runs. */
|
|
88
|
+
command: string;
|
|
89
|
+
/** Optional matcher (regex) from the hooks.json group. */
|
|
90
|
+
matcher?: string;
|
|
91
|
+
/** Whether the owning plugin is currently disabled (its hooks don't fire). */
|
|
92
|
+
disabled: boolean;
|
|
93
|
+
/** Stable per-hook identity ({@link pluginHookKey}) — the record key the
|
|
94
|
+
* UI writes to `capabilityOverrides.pluginHooks` to toggle just this hook. */
|
|
95
|
+
key: string;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Read-only counterpart to {@link loadPluginHooks}: scan installed plugins and
|
|
99
|
+
* RETURN their command hooks (instead of registering them), so the settings
|
|
100
|
+
* "钩子" page can show plugin-provided hooks alongside the user's hand-written
|
|
101
|
+
* ones, labelled by owner plugin. `disabledPlugins` doesn't filter the list —
|
|
102
|
+
* disabled plugins are still listed but flagged `disabled:true` (so the UI can
|
|
103
|
+
* show "由 xxx 插件提供(已禁用)"); pass it so that flag is accurate.
|
|
51
104
|
*/
|
|
52
|
-
export declare function
|
|
105
|
+
export declare function listPluginHooks(disabledPlugins?: string[]): PluginHookEntry[];
|
|
@@ -109,15 +109,42 @@ function pluginNameFromKey(key) {
|
|
|
109
109
|
const at = key.lastIndexOf("@");
|
|
110
110
|
return at > 0 ? key.slice(0, at) : key;
|
|
111
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Stable identity for ONE plugin-provided hook, used as the record key in
|
|
114
|
+
* `capabilityOverrides.pluginHooks` (per-hook project off-switch). Derived
|
|
115
|
+
* from content (`plugin:RawEvent:command`) rather than scan order so it
|
|
116
|
+
* survives plugin reinstalls and hooks.json reordering. Two entries that
|
|
117
|
+
* differ only by matcher collide — acceptable: toggling one toggles both,
|
|
118
|
+
* and identical commands on the same event are in practice the same hook.
|
|
119
|
+
*/
|
|
120
|
+
export function pluginHookKey(hook) {
|
|
121
|
+
return `${hook.plugin}:${hook.rawEvent}:${hook.command}`;
|
|
122
|
+
}
|
|
112
123
|
/**
|
|
113
124
|
* Walk installed plugins and register their command hooks. Safe to call
|
|
114
125
|
* multiple times — the caller is responsible for not double-registering
|
|
115
126
|
* (HookRegistry has no de-dup; the engine constructor calls this exactly
|
|
116
127
|
* once after creating the registry).
|
|
128
|
+
*
|
|
129
|
+
* `disabledPlugins` is the coarse "plugin total switch" — bare plugin names
|
|
130
|
+
* (no `@marketplace`, no `:` suffix), matching scanSkills' semantics. A
|
|
131
|
+
* disabled plugin contributes NO hooks, so e.g. disabling "superpowers"
|
|
132
|
+
* also suppresses its SessionStart injection — not just its Skill-tool
|
|
133
|
+
* entries. Without this, `disabledPlugins` only filtered the skill list and
|
|
134
|
+
* the plugin's hooks still fired regardless.
|
|
135
|
+
*
|
|
136
|
+
* `disabledPluginHooks` is the fine-grained per-hook switch — a list of
|
|
137
|
+
* {@link pluginHookKey} keys (folded from the project's
|
|
138
|
+
* `capabilityOverrides.pluginHooks` by readDisabledLists). A matching hook
|
|
139
|
+
* is skipped while the rest of the plugin keeps working.
|
|
117
140
|
*/
|
|
118
|
-
export function loadPluginHooks(registry) {
|
|
141
|
+
export function loadPluginHooks(registry, disabledPlugins = [], disabledPluginHooks = []) {
|
|
119
142
|
const data = readInstalledPlugins();
|
|
143
|
+
const disabledSet = new Set(disabledPlugins);
|
|
144
|
+
const disabledHookSet = new Set(disabledPluginHooks);
|
|
120
145
|
for (const [key, entries] of Object.entries(data.plugins)) {
|
|
146
|
+
if (disabledSet.has(pluginNameFromKey(key)))
|
|
147
|
+
continue;
|
|
121
148
|
for (const entry of entries) {
|
|
122
149
|
const installPath = entry.installPath;
|
|
123
150
|
if (!installPath || !existsSync(installPath))
|
|
@@ -140,6 +167,13 @@ export function loadPluginHooks(registry) {
|
|
|
140
167
|
if (cmd.type !== "command" || typeof cmd.command !== "string") {
|
|
141
168
|
continue;
|
|
142
169
|
}
|
|
170
|
+
if (disabledHookSet.has(pluginHookKey({
|
|
171
|
+
plugin: pluginNameFromKey(key),
|
|
172
|
+
rawEvent: eventNameRaw,
|
|
173
|
+
command: cmd.command,
|
|
174
|
+
}))) {
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
143
177
|
const commandLine = cmd.command;
|
|
144
178
|
const timeoutMs = cmd.timeout_ms;
|
|
145
179
|
const matcher = group.matcher;
|
|
@@ -160,3 +194,51 @@ export function loadPluginHooks(registry) {
|
|
|
160
194
|
}
|
|
161
195
|
}
|
|
162
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Read-only counterpart to {@link loadPluginHooks}: scan installed plugins and
|
|
199
|
+
* RETURN their command hooks (instead of registering them), so the settings
|
|
200
|
+
* "钩子" page can show plugin-provided hooks alongside the user's hand-written
|
|
201
|
+
* ones, labelled by owner plugin. `disabledPlugins` doesn't filter the list —
|
|
202
|
+
* disabled plugins are still listed but flagged `disabled:true` (so the UI can
|
|
203
|
+
* show "由 xxx 插件提供(已禁用)"); pass it so that flag is accurate.
|
|
204
|
+
*/
|
|
205
|
+
export function listPluginHooks(disabledPlugins = []) {
|
|
206
|
+
const data = readInstalledPlugins();
|
|
207
|
+
const disabledSet = new Set(disabledPlugins);
|
|
208
|
+
const out = [];
|
|
209
|
+
for (const [key, entries] of Object.entries(data.plugins)) {
|
|
210
|
+
const plugin = pluginNameFromKey(key);
|
|
211
|
+
const disabled = disabledSet.has(plugin);
|
|
212
|
+
for (const entry of entries) {
|
|
213
|
+
const installPath = entry.installPath;
|
|
214
|
+
if (!installPath || !existsSync(installPath))
|
|
215
|
+
continue;
|
|
216
|
+
const raw = readHooksJson(installPath);
|
|
217
|
+
if (!raw?.hooks)
|
|
218
|
+
continue;
|
|
219
|
+
for (const [eventNameRaw, groups] of Object.entries(raw.hooks)) {
|
|
220
|
+
const mapped = EVENT_NAME_MAP[eventNameRaw];
|
|
221
|
+
if (mapped === null || mapped === undefined)
|
|
222
|
+
continue;
|
|
223
|
+
if (!Array.isArray(groups))
|
|
224
|
+
continue;
|
|
225
|
+
for (const group of groups) {
|
|
226
|
+
for (const cmd of group.hooks ?? []) {
|
|
227
|
+
if (cmd.type !== "command" || typeof cmd.command !== "string")
|
|
228
|
+
continue;
|
|
229
|
+
out.push({
|
|
230
|
+
plugin,
|
|
231
|
+
event: mapped,
|
|
232
|
+
rawEvent: eventNameRaw,
|
|
233
|
+
command: cmd.command,
|
|
234
|
+
matcher: group.matcher,
|
|
235
|
+
disabled,
|
|
236
|
+
key: pluginHookKey({ plugin, rawEvent: eventNameRaw, command: cmd.command }),
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return out;
|
|
244
|
+
}
|