@cjhyy/code-shell-core 0.7.0 → 0.8.0
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 +36 -23
- package/dist/agent/agent-definition-registry.d.ts +2 -2
- package/dist/agent/agent-definition-registry.js +47 -10
- package/dist/agent/agent-definition.d.ts +5 -0
- package/dist/agent/agent-definition.js +14 -0
- package/dist/automation/index.d.ts +7 -4
- package/dist/automation/index.js +4 -2
- package/dist/automation/runner.js +3 -1
- package/dist/automation/scheduler.d.ts +57 -1
- package/dist/automation/scheduler.js +123 -23
- package/dist/automation/store.d.ts +6 -2
- package/dist/automation/store.js +7 -3
- package/dist/capabilities/index.d.ts +109 -0
- package/dist/capabilities/index.js +80 -0
- package/dist/capability-control/disabled-lists.d.ts +2 -1
- package/dist/capability-control/disabled-lists.js +3 -5
- package/dist/capability-control/overlay.d.ts +14 -1
- package/dist/capability-control/overlay.js +40 -0
- package/dist/capability-control/service.js +6 -4
- package/dist/cli/agent-server-stdio.d.ts +1 -1
- package/dist/cli/agent-server-stdio.js +66 -6
- package/dist/cli/agent-server-tcp.js +20 -5
- package/dist/context/compaction.d.ts +39 -3
- package/dist/context/compaction.js +151 -39
- package/dist/context/manager.d.ts +20 -4
- package/dist/context/manager.js +42 -7
- package/dist/context/token-counter.js +5 -3
- package/dist/context/tool-result-storage.d.ts +6 -0
- package/dist/context/tool-result-storage.js +25 -4
- package/dist/credentials/access.d.ts +13 -2
- package/dist/credentials/access.js +99 -4
- package/dist/credentials/index.d.ts +3 -2
- package/dist/credentials/index.js +2 -1
- package/dist/credentials/oauth.d.ts +9 -1
- package/dist/credentials/oauth.js +80 -1
- package/dist/credentials/store.d.ts +16 -2
- package/dist/credentials/store.js +33 -11
- package/dist/credentials/types.d.ts +62 -1
- package/dist/credentials/types.js +16 -1
- package/dist/credentials/use-credential-tool.js +15 -1
- package/dist/engine/auxiliary-pipeline.d.ts +40 -0
- package/dist/engine/auxiliary-pipeline.js +181 -0
- package/dist/{settings → engine}/disk-defaults.d.ts +2 -2
- package/dist/{settings → engine}/disk-defaults.js +5 -2
- package/dist/engine/dynamic-tool-defs.d.ts +4 -0
- package/dist/engine/dynamic-tool-defs.js +4 -0
- package/dist/engine/engine.d.ts +272 -184
- package/dist/engine/engine.js +1869 -1864
- package/dist/engine/file-history-hook.d.ts +11 -0
- package/dist/engine/file-history-hook.js +31 -0
- package/dist/engine/goal-judge-context.d.ts +9 -0
- package/dist/engine/goal-judge-context.js +234 -0
- package/dist/engine/injected-context-cache.d.ts +6 -0
- package/dist/engine/injected-context-cache.js +13 -0
- package/dist/engine/input-attachments.d.ts +1 -1
- package/dist/engine/model-facade.d.ts +3 -3
- package/dist/engine/model-facade.js +15 -14
- package/dist/engine/permission-controller.d.ts +55 -0
- package/dist/engine/permission-controller.js +148 -0
- package/dist/engine/prompt-cache-diagnostics.d.ts +58 -0
- package/dist/engine/prompt-cache-diagnostics.js +178 -0
- package/dist/engine/run-accounting.d.ts +41 -0
- package/dist/engine/run-accounting.js +126 -0
- package/dist/engine/run-context.d.ts +44 -0
- package/dist/engine/run-context.js +88 -0
- package/dist/engine/run-environment.d.ts +30 -0
- package/dist/engine/run-environment.js +77 -0
- package/dist/engine/run-finalize.d.ts +58 -0
- package/dist/engine/run-finalize.js +245 -0
- package/dist/engine/run-goal.d.ts +58 -0
- package/dist/engine/run-goal.js +188 -0
- package/dist/engine/run-image-input.d.ts +1 -1
- package/dist/engine/run-image-input.js +5 -3
- package/dist/engine/run-session-open.d.ts +41 -0
- package/dist/engine/run-session-open.js +186 -0
- package/dist/engine/run-setup.d.ts +42 -0
- package/dist/engine/run-setup.js +58 -0
- package/dist/engine/run-tooling.d.ts +125 -0
- package/dist/engine/run-tooling.js +283 -0
- package/dist/engine/run-types.d.ts +139 -0
- package/dist/engine/run-types.js +12 -0
- package/dist/engine/run-workspace.d.ts +50 -0
- package/dist/engine/run-workspace.js +114 -0
- package/dist/engine/session-title.d.ts +2 -1
- package/dist/engine/session-title.js +4 -1
- package/dist/engine/steer-queue.d.ts +1 -1
- package/dist/engine/subagent-spawner.d.ts +32 -0
- package/dist/engine/subagent-spawner.js +287 -0
- package/dist/engine/tool-summary.d.ts +2 -2
- package/dist/engine/tool-summary.js +2 -2
- package/dist/engine/turn-loop.d.ts +67 -10
- package/dist/engine/turn-loop.js +538 -97
- package/dist/engine/types.d.ts +35 -4
- package/dist/engine/types.js +1 -1
- package/dist/{engine/goal.d.ts → goal/lifecycle.d.ts} +80 -6
- package/dist/goal/lifecycle.js +482 -0
- package/dist/hooks/events.d.ts +26 -9
- package/dist/hooks/events.js +0 -3
- package/dist/hooks/goal-stop-hook.d.ts +28 -29
- package/dist/hooks/goal-stop-hook.js +344 -144
- package/dist/hooks/registry.js +4 -1
- package/dist/hooks/shell-runner.d.ts +12 -1
- package/dist/hooks/shell-runner.js +160 -9
- package/dist/index.d.ts +51 -110
- package/dist/index.extension.d.ts +51 -0
- package/dist/index.extension.js +39 -0
- package/dist/index.internal.d.ts +86 -0
- package/dist/index.internal.js +92 -0
- package/dist/index.js +37 -125
- package/dist/links/cli.d.ts +48 -0
- package/dist/links/cli.js +617 -0
- package/dist/links/http.d.ts +40 -0
- package/dist/links/http.js +166 -0
- package/dist/links/index.d.ts +4 -0
- package/dist/links/index.js +3 -0
- package/dist/links/link-action-tool.d.ts +5 -0
- package/dist/links/link-action-tool.js +241 -0
- package/dist/links/providers.d.ts +8 -0
- package/dist/links/providers.js +665 -0
- package/dist/links/types.d.ts +44 -0
- package/dist/llm/client-base.d.ts +7 -0
- package/dist/llm/client-base.js +72 -10
- package/dist/llm/model-pool.d.ts +1 -1
- package/dist/llm/model-pool.js +1 -1
- package/dist/llm/providers/anthropic.d.ts +1 -0
- package/dist/llm/providers/anthropic.js +9 -0
- package/dist/llm/providers/openai.d.ts +1 -0
- package/dist/llm/providers/openai.js +17 -0
- package/dist/llm/types.d.ts +12 -5
- package/dist/model-catalog/index.js +15 -2
- package/dist/model-catalog/resolve.d.ts +13 -1
- package/dist/model-catalog/resolve.js +37 -2
- package/dist/model-catalog/types.d.ts +74 -48
- package/dist/model-catalog/types.js +16 -5
- package/dist/model-catalog/upsert.d.ts +3 -1
- package/dist/model-catalog/upsert.js +9 -0
- package/dist/onboarding.d.ts +0 -1
- package/dist/onboarding.js +1 -22
- package/dist/panel-apps/bindings.d.ts +24 -0
- package/dist/panel-apps/bindings.js +69 -0
- package/dist/panel-apps/github-archive.d.ts +21 -0
- package/dist/panel-apps/github-archive.js +98 -0
- package/dist/panel-apps/index.d.ts +4 -0
- package/dist/panel-apps/index.js +4 -0
- package/dist/panel-apps/installer.d.ts +68 -0
- package/dist/panel-apps/installer.js +622 -0
- package/dist/panel-apps/manifest.d.ts +364 -0
- package/dist/panel-apps/manifest.js +189 -0
- package/dist/panel-apps/paths.d.ts +13 -0
- package/dist/panel-apps/paths.js +38 -0
- package/dist/panel-apps/registry.d.ts +51 -0
- package/dist/panel-apps/registry.js +99 -0
- package/dist/panel-apps/runtime.d.ts +80 -0
- package/dist/panel-apps/runtime.js +154 -0
- package/dist/plugins/gitOps.js +8 -1
- package/dist/plugins/installedPlugins.d.ts +2 -1
- package/dist/plugins/installedPlugins.js +146 -8
- package/dist/plugins/installer/codex/convertAgents.d.ts +4 -1
- package/dist/plugins/installer/codex/convertAgents.js +62 -8
- package/dist/plugins/installer/codex/convertCommands.d.ts +5 -5
- package/dist/plugins/installer/codex/convertCommands.js +35 -12
- package/dist/plugins/installer/codex/convertHooks.d.ts +10 -0
- package/dist/plugins/installer/codex/convertHooks.js +82 -0
- package/dist/plugins/installer/codex/convertSkills.js +41 -6
- package/dist/plugins/installer/install.d.ts +7 -1
- package/dist/plugins/installer/install.js +21 -87
- package/dist/plugins/installer/installFromArchive.d.ts +26 -4
- package/dist/plugins/installer/installFromArchive.js +44 -27
- package/dist/plugins/installer/installFromNpm.d.ts +31 -0
- package/dist/plugins/installer/installFromNpm.js +273 -0
- package/dist/plugins/installer/loadPluginAgents.js +17 -4
- package/dist/plugins/installer/loadPluginMcp.d.ts +14 -0
- package/dist/plugins/installer/loadPluginMcp.js +245 -35
- package/dist/plugins/installer/normalizeManifest.d.ts +13 -0
- package/dist/plugins/installer/normalizeManifest.js +306 -0
- package/dist/plugins/installer/npmTar.d.ts +13 -0
- package/dist/plugins/installer/npmTar.js +321 -0
- package/dist/plugins/installer/parseSource.d.ts +11 -0
- package/dist/plugins/installer/parseSource.js +48 -0
- package/dist/plugins/installer/preview.d.ts +101 -0
- package/dist/plugins/installer/preview.js +336 -0
- package/dist/plugins/installer/projectPluginSource.d.ts +14 -0
- package/dist/plugins/installer/projectPluginSource.js +140 -0
- package/dist/plugins/installer/types.d.ts +775 -0
- package/dist/plugins/installer/types.js +100 -0
- package/dist/plugins/installer/unzip.d.ts +11 -0
- package/dist/plugins/installer/unzip.js +123 -9
- package/dist/plugins/installer/update.d.ts +2 -2
- package/dist/plugins/installer/update.js +43 -4
- package/dist/plugins/loadPluginHooks.d.ts +19 -2
- package/dist/plugins/loadPluginHooks.js +97 -86
- package/dist/plugins/pluginAutomationTemplates.d.ts +18 -0
- package/dist/plugins/pluginAutomationTemplates.js +50 -0
- package/dist/plugins/pluginCatalog.d.ts +45 -0
- package/dist/plugins/pluginCatalog.js +87 -0
- package/dist/plugins/pluginCommandHook.d.ts +10 -4
- package/dist/plugins/pluginCommandHook.js +133 -18
- package/dist/plugins/pluginCommandsLoader.d.ts +19 -0
- package/dist/plugins/pluginCommandsLoader.js +181 -7
- package/dist/plugins/pluginContent.d.ts +10 -1
- package/dist/plugins/pluginContent.js +87 -30
- package/dist/plugins/pluginHookApproval.d.ts +30 -0
- package/dist/plugins/pluginHookApproval.js +160 -0
- package/dist/plugins/pluginHookIntegrity.d.ts +69 -0
- package/dist/plugins/pluginHookIntegrity.js +361 -0
- package/dist/plugins/pluginInstaller.js +71 -12
- package/dist/plugins/pluginMcpApproval.d.ts +19 -0
- package/dist/plugins/pluginMcpApproval.js +110 -0
- package/dist/plugins/pluginMcpIntegrity.d.ts +21 -0
- package/dist/plugins/pluginMcpIntegrity.js +74 -0
- package/dist/plugins/types.d.ts +30 -0
- package/dist/plugins/varRewrite.d.ts +9 -5
- package/dist/plugins/varRewrite.js +26 -17
- package/dist/preset/index.d.ts +11 -8
- package/dist/preset/index.js +62 -203
- package/dist/product/define.js +9 -3
- package/dist/product/types.d.ts +0 -2
- package/dist/profile/activation.d.ts +36 -0
- package/dist/profile/activation.js +57 -0
- package/dist/profile/catalog-store.d.ts +77 -0
- package/dist/profile/catalog-store.js +346 -0
- package/dist/profile/catalog.d.ts +54 -0
- package/dist/profile/catalog.js +152 -0
- package/dist/profile/index.d.ts +7 -0
- package/dist/profile/index.js +7 -0
- package/dist/profile/requirements.d.ts +76 -0
- package/dist/profile/requirements.js +117 -0
- package/dist/profile/resolve.d.ts +11 -0
- package/dist/profile/resolve.js +41 -0
- package/dist/profile/store.d.ts +17 -0
- package/dist/profile/store.js +167 -0
- package/dist/profile/types.d.ts +321 -0
- package/dist/profile/types.js +104 -0
- package/dist/prompt/composer.d.ts +46 -7
- package/dist/prompt/composer.js +78 -48
- package/dist/prompt/instruction-scanner.d.ts +6 -5
- package/dist/prompt/instruction-scanner.js +8 -23
- package/dist/prompt/section-loader.d.ts +2 -2
- package/dist/prompt/section-loader.js +7 -4
- package/dist/prompt/sections/browser.md +10 -9
- package/dist/prompt/sections/harness-base.md +9 -0
- package/dist/protocol/chat-session-manager.d.ts +77 -3
- package/dist/protocol/chat-session-manager.js +194 -18
- package/dist/protocol/chat-session.d.ts +72 -9
- package/dist/protocol/chat-session.js +151 -16
- package/dist/protocol/client.d.ts +37 -4
- package/dist/protocol/client.js +118 -6
- package/dist/protocol/index.d.ts +2 -2
- package/dist/protocol/index.js +2 -2
- package/dist/protocol/mobile-remote-types.d.ts +406 -0
- package/dist/protocol/mobile-remote-types.js +1 -0
- package/dist/protocol/server.d.ts +152 -14
- package/dist/protocol/server.js +1574 -229
- package/dist/protocol/types.d.ts +182 -32
- package/dist/protocol/types.js +18 -0
- package/dist/run/ArtifactTracker.d.ts +6 -1
- package/dist/run/ArtifactTracker.js +29 -21
- package/dist/run/EngineRunner.d.ts +2 -0
- package/dist/run/EngineRunner.js +1 -0
- package/dist/run/RunManager.d.ts +26 -0
- package/dist/run/RunManager.js +82 -11
- package/dist/run/factory.d.ts +3 -0
- package/dist/run/factory.js +2 -0
- package/dist/runtime/safe-spawn.d.ts +6 -0
- package/dist/runtime/safe-spawn.js +8 -13
- package/dist/services/auto-dream.d.ts +13 -1
- package/dist/services/auto-dream.js +56 -8
- package/dist/services/dream-consolidation.d.ts +3 -0
- package/dist/services/dream-consolidation.js +14 -2
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/memory-orchestrator.js +6 -2
- package/dist/services/oauth.d.ts +34 -10
- package/dist/services/oauth.js +236 -98
- package/dist/services/session-memory.d.ts +4 -4
- package/dist/services/session-memory.js +13 -10
- package/dist/session/memory.d.ts +26 -7
- package/dist/session/memory.js +79 -21
- package/dist/session/session-manager.d.ts +208 -25
- package/dist/session/session-manager.js +1232 -116
- package/dist/session/session-message.d.ts +22 -0
- package/dist/session/session-message.js +1 -0
- package/dist/session/transcript.d.ts +76 -6
- package/dist/session/transcript.js +278 -7
- package/dist/settings/feature-flags.d.ts +40 -0
- package/dist/settings/feature-flags.js +40 -0
- package/dist/settings/manager.d.ts +39 -1
- package/dist/settings/manager.js +102 -41
- package/dist/settings/migrate-config.js +4 -2
- package/dist/settings/schema.d.ts +511 -177
- package/dist/settings/schema.js +98 -25
- package/dist/skills/scanner.d.ts +6 -2
- package/dist/skills/scanner.js +160 -9
- package/dist/sources/adapter.d.ts +14 -0
- package/dist/sources/adapter.js +7 -0
- package/dist/sources/adapters/local-files.d.ts +10 -0
- package/dist/sources/adapters/local-files.js +127 -0
- package/dist/sources/adapters/mcp-resource.d.ts +17 -0
- package/dist/sources/adapters/mcp-resource.js +41 -0
- package/dist/sources/adapters/mock.d.ts +3 -0
- package/dist/sources/adapters/mock.js +29 -0
- package/dist/sources/binding.d.ts +6 -0
- package/dist/sources/binding.js +24 -0
- package/dist/sources/catalog.d.ts +6 -0
- package/dist/sources/catalog.js +64 -0
- package/dist/sources/context-summary.d.ts +8 -0
- package/dist/sources/context-summary.js +13 -0
- package/dist/sources/credential-status.d.ts +2 -0
- package/dist/sources/credential-status.js +13 -0
- package/dist/sources/index.d.ts +10 -0
- package/dist/sources/index.js +10 -0
- package/dist/sources/resolve.d.ts +28 -0
- package/dist/sources/resolve.js +47 -0
- package/dist/sources/truncate-utf8.d.ts +7 -0
- package/dist/sources/truncate-utf8.js +18 -0
- package/dist/sources/types.d.ts +71 -0
- package/dist/sources/types.js +26 -0
- package/dist/testing/fetch-stub.d.ts +32 -0
- package/dist/testing/fetch-stub.js +24 -0
- package/dist/themes/image.d.ts +18 -0
- package/dist/themes/image.js +117 -0
- package/dist/themes/index.d.ts +4 -0
- package/dist/themes/index.js +4 -0
- package/dist/themes/installer.d.ts +50 -0
- package/dist/themes/installer.js +290 -0
- package/dist/themes/manifest.d.ts +102 -0
- package/dist/themes/manifest.js +86 -0
- package/dist/themes/paths.d.ts +14 -0
- package/dist/themes/paths.js +33 -0
- package/dist/tool-system/browser-bridge.d.ts +53 -11
- package/dist/tool-system/browser-bridge.js +8 -9
- package/dist/tool-system/builtin/agent-heartbeat.d.ts +2 -2
- package/dist/tool-system/builtin/agent-heartbeat.js +20 -6
- package/dist/tool-system/builtin/agent-notifications.d.ts +127 -72
- package/dist/tool-system/builtin/agent-notifications.js +291 -101
- package/dist/tool-system/builtin/agent-output-file.js +1 -3
- package/dist/tool-system/builtin/agent-progress.d.ts +6 -0
- package/dist/tool-system/builtin/agent-progress.js +83 -0
- package/dist/tool-system/builtin/agent-registry.d.ts +38 -2
- package/dist/tool-system/builtin/agent-registry.js +178 -9
- package/dist/tool-system/builtin/agent-transcript-translator.js +1 -1
- package/dist/tool-system/builtin/agent.d.ts +2 -0
- package/dist/tool-system/builtin/agent.js +279 -34
- package/dist/tool-system/builtin/background-jobs.d.ts +63 -7
- package/dist/tool-system/builtin/background-jobs.js +111 -15
- package/dist/tool-system/builtin/background-work.d.ts +12 -1
- package/dist/tool-system/builtin/background-work.js +12 -1
- package/dist/tool-system/builtin/bash.d.ts +3 -5
- package/dist/tool-system/builtin/bash.js +14 -6
- package/dist/tool-system/builtin/browser-tools.d.ts +8 -5
- package/dist/tool-system/builtin/browser-tools.js +89 -23
- package/dist/tool-system/builtin/edit-model-catalog.d.ts +6 -0
- package/dist/tool-system/builtin/edit-model-catalog.js +172 -12
- package/dist/tool-system/builtin/edit.d.ts +2 -1
- package/dist/tool-system/builtin/edit.js +14 -10
- package/dist/tool-system/builtin/file-cache.d.ts +2 -0
- package/dist/tool-system/builtin/file-cache.js +4 -0
- package/dist/tool-system/builtin/generate-image.js +17 -10
- package/dist/tool-system/builtin/generate-video.d.ts +4 -0
- package/dist/tool-system/builtin/generate-video.js +164 -28
- package/dist/tool-system/builtin/glob.d.ts +2 -1
- package/dist/tool-system/builtin/glob.js +28 -3
- package/dist/tool-system/builtin/grep.d.ts +1 -0
- package/dist/tool-system/builtin/grep.js +82 -17
- package/dist/tool-system/builtin/image-uploader.js +7 -1
- package/dist/tool-system/builtin/index.d.ts +57 -18
- package/dist/tool-system/builtin/index.js +280 -167
- package/dist/tool-system/builtin/memory.d.ts +6 -0
- package/dist/tool-system/builtin/memory.js +36 -15
- package/dist/tool-system/builtin/panel.d.ts +9 -0
- package/dist/tool-system/builtin/panel.js +314 -0
- package/dist/tool-system/builtin/read.js +5 -1
- package/dist/tool-system/builtin/send-message-to-session.d.ts +6 -0
- package/dist/tool-system/builtin/send-message-to-session.js +67 -0
- package/dist/tool-system/builtin/sources.d.ts +8 -0
- package/dist/tool-system/builtin/sources.js +137 -0
- package/dist/tool-system/builtin/tool-search.js +7 -2
- package/dist/tool-system/builtin/update-automation-memory.js +2 -0
- package/dist/tool-system/builtin/video-providers.d.ts +12 -15
- package/dist/tool-system/builtin/video-providers.js +1 -0
- package/dist/tool-system/builtin/view-image.d.ts +2 -2
- package/dist/tool-system/builtin/web-fetch.js +60 -15
- package/dist/tool-system/builtin/web-search.js +1 -3
- package/dist/tool-system/builtin/write.d.ts +2 -1
- package/dist/tool-system/builtin/write.js +14 -4
- package/dist/tool-system/capability-module.d.ts +93 -0
- package/dist/tool-system/capability-module.js +53 -0
- package/dist/tool-system/context.d.ts +94 -24
- package/dist/tool-system/executor.js +99 -58
- package/dist/tool-system/external-tool-exposure.d.ts +60 -0
- package/dist/tool-system/external-tool-exposure.js +304 -0
- package/dist/tool-system/mcp-manager.d.ts +17 -1
- package/dist/tool-system/mcp-manager.js +72 -7
- package/dist/tool-system/mcp-tool-policy.d.ts +9 -0
- package/dist/tool-system/mcp-tool-policy.js +34 -0
- package/dist/tool-system/panel-bridge.d.ts +53 -0
- package/dist/tool-system/panel-bridge.js +1 -0
- package/dist/tool-system/path-policy.d.ts +19 -0
- package/dist/tool-system/path-policy.js +62 -1
- package/dist/tool-system/permission.d.ts +69 -3
- package/dist/tool-system/permission.js +429 -30
- package/dist/tool-system/registry.d.ts +15 -3
- package/dist/tool-system/registry.js +82 -40
- package/dist/tool-system/sandbox/index.js +3 -8
- package/dist/tool-system/sandbox/seatbelt.js +2 -6
- package/dist/tool-system/session-tool-host.d.ts +139 -0
- package/dist/tool-system/session-tool-host.js +167 -0
- package/dist/tool-system/testing/tool-registry-harness.d.ts +31 -0
- package/dist/tool-system/testing/tool-registry-harness.js +51 -0
- package/dist/tool-system/validation.d.ts +14 -7
- package/dist/tool-system/validation.js +701 -7
- package/dist/types.d.ts +201 -20
- package/dist/{cc-orchestrator → utils}/cwd-normalize.d.ts +1 -0
- package/dist/{cc-orchestrator → utils}/cwd-normalize.js +1 -0
- package/dist/utils/file-mutex.d.ts +65 -0
- package/dist/utils/file-mutex.js +145 -0
- package/dist/utils/json.d.ts +2 -4
- package/dist/utils/json.js +2 -4
- package/dist/utils/lockfile.d.ts +30 -1
- package/dist/utils/lockfile.js +2 -2
- package/dist/utils/secret-scrubber.d.ts +8 -0
- package/dist/utils/secret-scrubber.js +227 -0
- package/dist/utils/toolDisplay.js +1 -1
- package/package.json +20 -5
- package/THIRD_PARTY_NOTICES.md +0 -206
- package/dist/arena/arena.d.ts +0 -43
- package/dist/arena/arena.js +0 -333
- package/dist/arena/context/context-tools.d.ts +0 -16
- package/dist/arena/context/context-tools.js +0 -272
- package/dist/arena/context/within-root.d.ts +0 -7
- package/dist/arena/context/within-root.js +0 -15
- package/dist/arena/detect-mode.d.ts +0 -20
- package/dist/arena/detect-mode.js +0 -78
- package/dist/arena/digest-builder.d.ts +0 -25
- package/dist/arena/digest-builder.js +0 -120
- package/dist/arena/index.d.ts +0 -29
- package/dist/arena/index.js +0 -29
- package/dist/arena/iterate/convergence.d.ts +0 -25
- package/dist/arena/iterate/convergence.js +0 -103
- package/dist/arena/iterate/formats/index.d.ts +0 -22
- package/dist/arena/iterate/formats/index.js +0 -283
- package/dist/arena/iterate/index.d.ts +0 -11
- package/dist/arena/iterate/index.js +0 -9
- package/dist/arena/iterate/iterative-arena.d.ts +0 -23
- package/dist/arena/iterate/iterative-arena.js +0 -237
- package/dist/arena/iterate/parse.d.ts +0 -42
- package/dist/arena/iterate/parse.js +0 -123
- package/dist/arena/iterate/phases/argue.d.ts +0 -22
- package/dist/arena/iterate/phases/argue.js +0 -165
- package/dist/arena/iterate/phases/revise.d.ts +0 -16
- package/dist/arena/iterate/phases/revise.js +0 -62
- package/dist/arena/iterate/phases/tournament.d.ts +0 -34
- package/dist/arena/iterate/phases/tournament.js +0 -113
- package/dist/arena/iterate/tools/web-tools.d.ts +0 -13
- package/dist/arena/iterate/tools/web-tools.js +0 -54
- package/dist/arena/iterate/types.d.ts +0 -152
- package/dist/arena/iterate/types.js +0 -8
- package/dist/arena/ledger.d.ts +0 -47
- package/dist/arena/ledger.js +0 -159
- package/dist/arena/lenses/architecture.d.ts +0 -5
- package/dist/arena/lenses/architecture.js +0 -22
- package/dist/arena/lenses/engineering.d.ts +0 -5
- package/dist/arena/lenses/engineering.js +0 -22
- package/dist/arena/lenses/general.d.ts +0 -5
- package/dist/arena/lenses/general.js +0 -20
- package/dist/arena/lenses/index.d.ts +0 -16
- package/dist/arena/lenses/index.js +0 -47
- package/dist/arena/lenses/product.d.ts +0 -5
- package/dist/arena/lenses/product.js +0 -22
- package/dist/arena/model-presets.d.ts +0 -23
- package/dist/arena/model-presets.js +0 -44
- package/dist/arena/phases/adjudication.d.ts +0 -24
- package/dist/arena/phases/adjudication.js +0 -141
- package/dist/arena/phases/build-consensus.d.ts +0 -29
- package/dist/arena/phases/build-consensus.js +0 -83
- package/dist/arena/phases/claim-registry.d.ts +0 -26
- package/dist/arena/phases/claim-registry.js +0 -60
- package/dist/arena/phases/cross-review.d.ts +0 -45
- package/dist/arena/phases/cross-review.js +0 -218
- package/dist/arena/phases/debate-rounds.d.ts +0 -27
- package/dist/arena/phases/debate-rounds.js +0 -159
- package/dist/arena/phases/participant-research.d.ts +0 -38
- package/dist/arena/phases/participant-research.js +0 -314
- package/dist/arena/phases/planning-detail-expansion.d.ts +0 -38
- package/dist/arena/phases/planning-detail-expansion.js +0 -119
- package/dist/arena/planner.d.ts +0 -27
- package/dist/arena/planner.js +0 -311
- package/dist/arena/providers/docs.d.ts +0 -7
- package/dist/arena/providers/docs.js +0 -111
- package/dist/arena/providers/git.d.ts +0 -8
- package/dist/arena/providers/git.js +0 -174
- package/dist/arena/providers/index.d.ts +0 -32
- package/dist/arena/providers/index.js +0 -132
- package/dist/arena/providers/none.d.ts +0 -7
- package/dist/arena/providers/none.js +0 -11
- package/dist/arena/providers/repo.d.ts +0 -7
- package/dist/arena/providers/repo.js +0 -258
- package/dist/arena/render/session.d.ts +0 -17
- package/dist/arena/render/session.js +0 -190
- package/dist/arena/render/terminal.d.ts +0 -34
- package/dist/arena/render/terminal.js +0 -286
- package/dist/arena/strategies/discussion.d.ts +0 -25
- package/dist/arena/strategies/discussion.js +0 -143
- package/dist/arena/strategies/index.d.ts +0 -15
- package/dist/arena/strategies/index.js +0 -28
- package/dist/arena/strategies/language-wrapper.d.ts +0 -17
- package/dist/arena/strategies/language-wrapper.js +0 -102
- package/dist/arena/strategies/lens-wrapper.d.ts +0 -16
- package/dist/arena/strategies/lens-wrapper.js +0 -236
- package/dist/arena/strategies/planning.d.ts +0 -30
- package/dist/arena/strategies/planning.js +0 -225
- package/dist/arena/strategies/review.d.ts +0 -26
- package/dist/arena/strategies/review.js +0 -168
- package/dist/arena/strategies/utils.d.ts +0 -36
- package/dist/arena/strategies/utils.js +0 -603
- package/dist/arena/tools/selector.d.ts +0 -17
- package/dist/arena/tools/selector.js +0 -61
- package/dist/arena/transitions.d.ts +0 -53
- package/dist/arena/transitions.js +0 -97
- package/dist/arena/types.d.ts +0 -514
- package/dist/arena/types.js +0 -27
- package/dist/cc-orchestrator/agent-adapter.d.ts +0 -54
- package/dist/cc-orchestrator/agent-adapter.js +0 -143
- package/dist/cc-orchestrator/cc-capability.d.ts +0 -19
- package/dist/cc-orchestrator/cc-capability.js +0 -53
- package/dist/cc-orchestrator/codex-session-discovery.d.ts +0 -24
- package/dist/cc-orchestrator/codex-session-discovery.js +0 -191
- package/dist/cc-orchestrator/codex-session-history.d.ts +0 -38
- package/dist/cc-orchestrator/codex-session-history.js +0 -247
- package/dist/cc-orchestrator/external-agent-bindings.d.ts +0 -27
- package/dist/cc-orchestrator/external-agent-bindings.js +0 -150
- package/dist/cc-orchestrator/external-agent-changes.d.ts +0 -19
- package/dist/cc-orchestrator/external-agent-changes.js +0 -231
- package/dist/cc-orchestrator/external-agent-driver.d.ts +0 -19
- package/dist/cc-orchestrator/external-agent-driver.js +0 -284
- package/dist/cc-orchestrator/external-agent-session-store.d.ts +0 -23
- package/dist/cc-orchestrator/external-agent-session-store.js +0 -146
- package/dist/cc-orchestrator/index.d.ts +0 -8
- package/dist/cc-orchestrator/index.js +0 -8
- package/dist/cc-orchestrator/relevance-judge.d.ts +0 -15
- package/dist/cc-orchestrator/relevance-judge.js +0 -29
- package/dist/cc-orchestrator/session-discovery.d.ts +0 -46
- package/dist/cc-orchestrator/session-discovery.js +0 -125
- package/dist/cc-orchestrator/session-history.d.ts +0 -54
- package/dist/cc-orchestrator/session-history.js +0 -150
- package/dist/cron/cron-runtime.d.ts +0 -2
- package/dist/cron/cron-runtime.js +0 -2
- package/dist/cron/cron-store.d.ts +0 -2
- package/dist/cron/cron-store.js +0 -2
- package/dist/cron/scheduler.d.ts +0 -7
- package/dist/cron/scheduler.js +0 -7
- package/dist/engine/goal.js +0 -206
- package/dist/external-agents/config.d.ts +0 -2
- package/dist/external-agents/config.js +0 -15
- package/dist/external-agents/types.d.ts +0 -31
- package/dist/git/parse-log.d.ts +0 -13
- package/dist/git/parse-log.js +0 -21
- package/dist/git/utils.d.ts +0 -49
- package/dist/git/utils.js +0 -161
- package/dist/git/worktree/crud.d.ts +0 -69
- package/dist/git/worktree/crud.js +0 -206
- package/dist/git/worktree/diff.d.ts +0 -14
- package/dist/git/worktree/diff.js +0 -82
- package/dist/git/worktree/git-exec.d.ts +0 -7
- package/dist/git/worktree/git-exec.js +0 -51
- package/dist/git/worktree/index.d.ts +0 -5
- package/dist/git/worktree/index.js +0 -5
- package/dist/git/worktree/query.d.ts +0 -42
- package/dist/git/worktree/query.js +0 -121
- package/dist/git/worktree/slug.d.ts +0 -11
- package/dist/git/worktree/slug.js +0 -58
- package/dist/git/worktree.d.ts +0 -1
- package/dist/git/worktree.js +0 -5
- package/dist/lsp/client.d.ts +0 -41
- package/dist/lsp/client.js +0 -186
- package/dist/lsp/manager.d.ts +0 -40
- package/dist/lsp/manager.js +0 -155
- package/dist/lsp/root-path.d.ts +0 -9
- package/dist/lsp/root-path.js +0 -12
- package/dist/lsp/servers.d.ts +0 -16
- package/dist/lsp/servers.js +0 -60
- package/dist/prompt/sections/coding.md +0 -35
- package/dist/quota/credentials.d.ts +0 -3
- package/dist/quota/credentials.js +0 -80
- package/dist/quota/index.d.ts +0 -36
- package/dist/quota/index.js +0 -155
- package/dist/quota/types.d.ts +0 -48
- package/dist/quota/types.js +0 -13
- package/dist/review/review-prompt.d.ts +0 -28
- package/dist/review/review-prompt.js +0 -81
- package/dist/state.d.ts +0 -160
- package/dist/state.js +0 -267
- package/dist/tool-system/builtin/apply-patch/applier.d.ts +0 -26
- package/dist/tool-system/builtin/apply-patch/applier.js +0 -308
- package/dist/tool-system/builtin/apply-patch/backup-targets.d.ts +0 -10
- package/dist/tool-system/builtin/apply-patch/backup-targets.js +0 -30
- package/dist/tool-system/builtin/apply-patch/index.d.ts +0 -20
- package/dist/tool-system/builtin/apply-patch/index.js +0 -105
- package/dist/tool-system/builtin/apply-patch/parser.d.ts +0 -17
- package/dist/tool-system/builtin/apply-patch/parser.js +0 -212
- package/dist/tool-system/builtin/apply-patch/seek-sequence.d.ts +0 -18
- package/dist/tool-system/builtin/apply-patch/seek-sequence.js +0 -123
- package/dist/tool-system/builtin/apply-patch/types.d.ts +0 -49
- package/dist/tool-system/builtin/apply-patch/types.js +0 -13
- package/dist/tool-system/builtin/arena.d.ts +0 -31
- package/dist/tool-system/builtin/arena.js +0 -415
- package/dist/tool-system/builtin/brief.d.ts +0 -6
- package/dist/tool-system/builtin/brief.js +0 -41
- package/dist/tool-system/builtin/check-quota.d.ts +0 -15
- package/dist/tool-system/builtin/check-quota.js +0 -34
- package/dist/tool-system/builtin/drive-claude-code.d.ts +0 -51
- package/dist/tool-system/builtin/drive-claude-code.js +0 -698
- package/dist/tool-system/builtin/lsp.d.ts +0 -7
- package/dist/tool-system/builtin/lsp.js +0 -144
- package/dist/tool-system/builtin/notebook-edit.d.ts +0 -7
- package/dist/tool-system/builtin/notebook-edit.js +0 -127
- package/dist/tool-system/builtin/worktree.d.ts +0 -11
- package/dist/tool-system/builtin/worktree.js +0 -345
- /package/dist/{external-agents → links}/types.js +0 -0
- /package/dist/{engine/session-usage.d.ts → session/usage.d.ts} +0 -0
- /package/dist/{engine/session-usage.js → session/usage.js} +0 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { closeSync, constants, fstatSync, lstatSync, openSync, readSync, realpathSync, } from "node:fs";
|
|
3
|
+
import { isAbsolute, join, relative, sep } from "node:path";
|
|
4
|
+
const DIGEST_DOMAIN = "codeshell-plugin-hooks-v1";
|
|
5
|
+
const ABSENT_HOOKS = "<absent>";
|
|
6
|
+
const INVALID_HOOKS = "<invalid>";
|
|
7
|
+
/** Hard limits for one canonical plugin hook definition. */
|
|
8
|
+
export const MAX_PLUGIN_HOOK_FILE_BYTES = 1_048_576;
|
|
9
|
+
export const MAX_PLUGIN_HOOK_EVENTS = 32;
|
|
10
|
+
export const MAX_PLUGIN_HOOK_GROUPS = 128;
|
|
11
|
+
export const MAX_PLUGIN_HOOK_COMMANDS = 256;
|
|
12
|
+
export const MAX_PLUGIN_HOOK_EVENT_NAME_LENGTH = 128;
|
|
13
|
+
export const MAX_PLUGIN_HOOK_COMMAND_LENGTH = 32_768;
|
|
14
|
+
export const MAX_PLUGIN_HOOK_MATCHER_LENGTH = 4_096;
|
|
15
|
+
export const MAX_PLUGIN_HOOK_TIMEOUT_MS = 600_000;
|
|
16
|
+
export const MAX_PLUGIN_HOOK_REVIEW_COMMAND_LENGTH = 4_096;
|
|
17
|
+
export const SUPPORTED_PLUGIN_HOOK_EVENTS = [
|
|
18
|
+
"SessionStart",
|
|
19
|
+
"UserPromptSubmit",
|
|
20
|
+
"PreToolUse",
|
|
21
|
+
"PostToolUse",
|
|
22
|
+
"PreCompact",
|
|
23
|
+
"Notification",
|
|
24
|
+
"Stop",
|
|
25
|
+
"SubagentStop",
|
|
26
|
+
];
|
|
27
|
+
const SUPPORTED_EVENT_SET = new Set(SUPPORTED_PLUGIN_HOOK_EVENTS);
|
|
28
|
+
function digestHooks(payload) {
|
|
29
|
+
return createHash("sha256").update(DIGEST_DOMAIN).update("\0").update(payload).digest("hex");
|
|
30
|
+
}
|
|
31
|
+
function invalidSnapshot(error) {
|
|
32
|
+
return {
|
|
33
|
+
state: "invalid",
|
|
34
|
+
digest: digestHooks(INVALID_HOOKS),
|
|
35
|
+
definition: null,
|
|
36
|
+
hasExecutableHooks: false,
|
|
37
|
+
error,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function absentSnapshot() {
|
|
41
|
+
return {
|
|
42
|
+
state: "absent",
|
|
43
|
+
digest: digestHooks(ABSENT_HOOKS),
|
|
44
|
+
definition: null,
|
|
45
|
+
hasExecutableHooks: false,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function isRecord(value) {
|
|
49
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
50
|
+
}
|
|
51
|
+
function isMissingFileError(error) {
|
|
52
|
+
return (error instanceof Error && "code" in error && error.code === "ENOENT");
|
|
53
|
+
}
|
|
54
|
+
function pathIsWithin(root, target) {
|
|
55
|
+
const rel = relative(root, target);
|
|
56
|
+
return rel === "" || (rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel));
|
|
57
|
+
}
|
|
58
|
+
function readBoundedRegularFile(installPath) {
|
|
59
|
+
const hooksDir = join(installPath, "hooks");
|
|
60
|
+
const hooksPath = join(hooksDir, "hooks.json");
|
|
61
|
+
let rootReal;
|
|
62
|
+
try {
|
|
63
|
+
const rootStat = lstatSync(installPath);
|
|
64
|
+
if (!rootStat.isDirectory())
|
|
65
|
+
return new Error("plugin install path is not a directory");
|
|
66
|
+
rootReal = realpathSync(installPath);
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
return isMissingFileError(error) ? null : error;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const hooksDirStat = lstatSync(hooksDir);
|
|
73
|
+
if (hooksDirStat.isSymbolicLink() || !hooksDirStat.isDirectory()) {
|
|
74
|
+
return new Error("canonical hooks directory must be a regular directory");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
return isMissingFileError(error) ? null : error;
|
|
79
|
+
}
|
|
80
|
+
let pathStat;
|
|
81
|
+
try {
|
|
82
|
+
pathStat = lstatSync(hooksPath);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
return isMissingFileError(error) ? null : error;
|
|
86
|
+
}
|
|
87
|
+
if (pathStat.isSymbolicLink() || !pathStat.isFile()) {
|
|
88
|
+
return new Error("canonical hooks file must be a regular file");
|
|
89
|
+
}
|
|
90
|
+
if (pathStat.size > MAX_PLUGIN_HOOK_FILE_BYTES) {
|
|
91
|
+
return new Error(`canonical hooks file exceeds ${MAX_PLUGIN_HOOK_FILE_BYTES} bytes`);
|
|
92
|
+
}
|
|
93
|
+
let targetReal;
|
|
94
|
+
try {
|
|
95
|
+
targetReal = realpathSync(hooksPath);
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
return error;
|
|
99
|
+
}
|
|
100
|
+
if (!pathIsWithin(rootReal, targetReal)) {
|
|
101
|
+
return new Error("canonical hooks file escapes the plugin install path");
|
|
102
|
+
}
|
|
103
|
+
let fd;
|
|
104
|
+
try {
|
|
105
|
+
fd = openSync(hooksPath, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
106
|
+
const openedStat = fstatSync(fd);
|
|
107
|
+
if (!openedStat.isFile())
|
|
108
|
+
return new Error("canonical hooks file must be a regular file");
|
|
109
|
+
if (openedStat.dev !== pathStat.dev || openedStat.ino !== pathStat.ino) {
|
|
110
|
+
return new Error("canonical hooks file changed while being opened");
|
|
111
|
+
}
|
|
112
|
+
if (openedStat.size > MAX_PLUGIN_HOOK_FILE_BYTES) {
|
|
113
|
+
return new Error(`canonical hooks file exceeds ${MAX_PLUGIN_HOOK_FILE_BYTES} bytes`);
|
|
114
|
+
}
|
|
115
|
+
const chunks = [];
|
|
116
|
+
let total = 0;
|
|
117
|
+
while (true) {
|
|
118
|
+
const remaining = MAX_PLUGIN_HOOK_FILE_BYTES + 1 - total;
|
|
119
|
+
if (remaining <= 0) {
|
|
120
|
+
return new Error(`canonical hooks file exceeds ${MAX_PLUGIN_HOOK_FILE_BYTES} bytes`);
|
|
121
|
+
}
|
|
122
|
+
const chunk = Buffer.allocUnsafe(Math.min(64 * 1024, remaining));
|
|
123
|
+
const bytesRead = readSync(fd, chunk, 0, chunk.length, null);
|
|
124
|
+
if (bytesRead === 0)
|
|
125
|
+
break;
|
|
126
|
+
total += bytesRead;
|
|
127
|
+
if (total > MAX_PLUGIN_HOOK_FILE_BYTES) {
|
|
128
|
+
return new Error(`canonical hooks file exceeds ${MAX_PLUGIN_HOOK_FILE_BYTES} bytes`);
|
|
129
|
+
}
|
|
130
|
+
chunks.push(chunk.subarray(0, bytesRead));
|
|
131
|
+
}
|
|
132
|
+
return Buffer.concat(chunks, total);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
return error;
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
if (fd !== undefined)
|
|
139
|
+
closeSync(fd);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function parseHooksDefinition(bytes) {
|
|
143
|
+
let value;
|
|
144
|
+
try {
|
|
145
|
+
value = JSON.parse(bytes.toString("utf8"));
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
throw new Error(`invalid hooks JSON: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
149
|
+
}
|
|
150
|
+
if (!isRecord(value))
|
|
151
|
+
throw new Error("hooks document must be an object");
|
|
152
|
+
const rawHooks = value.hooks;
|
|
153
|
+
if (rawHooks === undefined)
|
|
154
|
+
return { hooks: {} };
|
|
155
|
+
if (!isRecord(rawHooks))
|
|
156
|
+
throw new Error("hooks must be an object");
|
|
157
|
+
const events = Object.entries(rawHooks);
|
|
158
|
+
if (events.length > MAX_PLUGIN_HOOK_EVENTS) {
|
|
159
|
+
throw new Error(`hooks define more than ${MAX_PLUGIN_HOOK_EVENTS} events`);
|
|
160
|
+
}
|
|
161
|
+
const parsed = { hooks: {} };
|
|
162
|
+
let groupCount = 0;
|
|
163
|
+
let commandCount = 0;
|
|
164
|
+
for (const [eventName, rawGroups] of events) {
|
|
165
|
+
if (eventName.length === 0 || eventName.length > MAX_PLUGIN_HOOK_EVENT_NAME_LENGTH) {
|
|
166
|
+
throw new Error(`hook event names must contain 1-${MAX_PLUGIN_HOOK_EVENT_NAME_LENGTH} characters`);
|
|
167
|
+
}
|
|
168
|
+
if (!Array.isArray(rawGroups)) {
|
|
169
|
+
throw new Error(`hook event "${eventName}" must be an array`);
|
|
170
|
+
}
|
|
171
|
+
groupCount += rawGroups.length;
|
|
172
|
+
if (groupCount > MAX_PLUGIN_HOOK_GROUPS) {
|
|
173
|
+
throw new Error(`hooks define more than ${MAX_PLUGIN_HOOK_GROUPS} groups`);
|
|
174
|
+
}
|
|
175
|
+
const supported = SUPPORTED_EVENT_SET.has(eventName);
|
|
176
|
+
const parsedGroups = [];
|
|
177
|
+
for (const rawGroup of rawGroups) {
|
|
178
|
+
if (!isRecord(rawGroup))
|
|
179
|
+
throw new Error(`hook group for "${eventName}" must be an object`);
|
|
180
|
+
const matcher = rawGroup.matcher;
|
|
181
|
+
if (matcher !== undefined) {
|
|
182
|
+
if (typeof matcher !== "string") {
|
|
183
|
+
throw new Error(`hook matcher for "${eventName}" must be a string`);
|
|
184
|
+
}
|
|
185
|
+
if (matcher.length > MAX_PLUGIN_HOOK_MATCHER_LENGTH) {
|
|
186
|
+
throw new Error(`hook matcher for "${eventName}" exceeds ${MAX_PLUGIN_HOOK_MATCHER_LENGTH} characters`);
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
new RegExp(matcher);
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
throw new Error(`hook matcher for "${eventName}" is not a valid regular expression`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const rawCommands = rawGroup.hooks;
|
|
196
|
+
if (rawCommands !== undefined && !Array.isArray(rawCommands)) {
|
|
197
|
+
throw new Error(`hook commands for "${eventName}" must be an array`);
|
|
198
|
+
}
|
|
199
|
+
const commands = rawCommands ?? [];
|
|
200
|
+
commandCount += commands.length;
|
|
201
|
+
if (commandCount > MAX_PLUGIN_HOOK_COMMANDS) {
|
|
202
|
+
throw new Error(`hooks define more than ${MAX_PLUGIN_HOOK_COMMANDS} commands`);
|
|
203
|
+
}
|
|
204
|
+
const parsedCommands = [];
|
|
205
|
+
for (const rawCommand of commands) {
|
|
206
|
+
if (!isRecord(rawCommand)) {
|
|
207
|
+
throw new Error(`hook command for "${eventName}" must be an object`);
|
|
208
|
+
}
|
|
209
|
+
if (rawCommand.type !== "command")
|
|
210
|
+
continue;
|
|
211
|
+
const command = rawCommand.command;
|
|
212
|
+
if (typeof command !== "string") {
|
|
213
|
+
throw new Error(`command hook for "${eventName}" must include a string command`);
|
|
214
|
+
}
|
|
215
|
+
if (command.length > MAX_PLUGIN_HOOK_COMMAND_LENGTH) {
|
|
216
|
+
throw new Error(`command hook for "${eventName}" exceeds ${MAX_PLUGIN_HOOK_COMMAND_LENGTH} characters`);
|
|
217
|
+
}
|
|
218
|
+
if (rawCommand.async !== undefined && typeof rawCommand.async !== "boolean") {
|
|
219
|
+
throw new Error(`command hook async flag for "${eventName}" must be boolean`);
|
|
220
|
+
}
|
|
221
|
+
const timeoutMs = rawCommand.timeout_ms;
|
|
222
|
+
if (timeoutMs !== undefined &&
|
|
223
|
+
(typeof timeoutMs !== "number" ||
|
|
224
|
+
!Number.isSafeInteger(timeoutMs) ||
|
|
225
|
+
timeoutMs < 1 ||
|
|
226
|
+
timeoutMs > MAX_PLUGIN_HOOK_TIMEOUT_MS)) {
|
|
227
|
+
throw new Error(`command hook timeout for "${eventName}" must be an integer between 1 and ${MAX_PLUGIN_HOOK_TIMEOUT_MS}`);
|
|
228
|
+
}
|
|
229
|
+
if (supported && command.trim().length > 0) {
|
|
230
|
+
parsedCommands.push({
|
|
231
|
+
command,
|
|
232
|
+
...(rawCommand.async === undefined ? {} : { async: rawCommand.async }),
|
|
233
|
+
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (supported) {
|
|
238
|
+
parsedGroups.push({
|
|
239
|
+
...(matcher === undefined ? {} : { matcher: matcher }),
|
|
240
|
+
hooks: parsedCommands,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (supported) {
|
|
245
|
+
parsed.hooks[eventName] = parsedGroups;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return parsed;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Securely read and parse the one canonical hook file. All digest, approval,
|
|
252
|
+
* listing, and runtime decisions consume this snapshot so malformed or
|
|
253
|
+
* replaced files cannot be interpreted differently by separate code paths.
|
|
254
|
+
*/
|
|
255
|
+
export function inspectPluginHooks(installPath) {
|
|
256
|
+
const bytes = readBoundedRegularFile(installPath);
|
|
257
|
+
if (bytes === null)
|
|
258
|
+
return absentSnapshot();
|
|
259
|
+
if (bytes instanceof Error)
|
|
260
|
+
return invalidSnapshot(bytes.message);
|
|
261
|
+
try {
|
|
262
|
+
const definition = parseHooksDefinition(bytes);
|
|
263
|
+
return {
|
|
264
|
+
state: "valid",
|
|
265
|
+
digest: digestHooks(bytes),
|
|
266
|
+
definition,
|
|
267
|
+
hasExecutableHooks: Object.values(definition.hooks).some((groups) => groups?.some((group) => group.hooks.length > 0)),
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
return invalidSnapshot(error instanceof Error ? error.message : String(error));
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Digest the exact canonical hooks file after it passes the bounded parser.
|
|
276
|
+
* Valid and absent definitions preserve the existing v1 digest contract;
|
|
277
|
+
* every invalid definition shares a fail-closed sentinel digest.
|
|
278
|
+
*/
|
|
279
|
+
export function pluginHooksDigest(installPath) {
|
|
280
|
+
return inspectPluginHooks(installPath).digest;
|
|
281
|
+
}
|
|
282
|
+
/** Whether the bounded canonical definition currently contains an executable command hook. */
|
|
283
|
+
export function pluginHasExecutableHooks(installPath) {
|
|
284
|
+
return inspectPluginHooks(installPath).hasExecutableHooks;
|
|
285
|
+
}
|
|
286
|
+
function reviewCommand(command) {
|
|
287
|
+
const truncated = command.length > MAX_PLUGIN_HOOK_REVIEW_COMMAND_LENGTH;
|
|
288
|
+
return {
|
|
289
|
+
command: truncated
|
|
290
|
+
? `${command.slice(0, MAX_PLUGIN_HOOK_REVIEW_COMMAND_LENGTH - 1)}…`
|
|
291
|
+
: command,
|
|
292
|
+
commandDigest: createHash("sha256").update(command).digest("hex"),
|
|
293
|
+
...(truncated ? { commandTruncated: true } : {}),
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
/** Build bounded, non-executable review metadata from one validated snapshot. */
|
|
297
|
+
export function pluginHookReviewSnapshot(snapshot) {
|
|
298
|
+
if (!snapshot.definition)
|
|
299
|
+
return [];
|
|
300
|
+
const out = [];
|
|
301
|
+
for (const rawEvent of Object.keys(snapshot.definition.hooks)) {
|
|
302
|
+
for (const group of snapshot.definition.hooks[rawEvent] ?? []) {
|
|
303
|
+
for (const hook of group.hooks) {
|
|
304
|
+
out.push({
|
|
305
|
+
rawEvent,
|
|
306
|
+
...(group.matcher === undefined ? {} : { matcher: group.matcher }),
|
|
307
|
+
...reviewCommand(hook.command),
|
|
308
|
+
...(hook.async === undefined ? {} : { async: hook.async }),
|
|
309
|
+
...(hook.timeoutMs === undefined ? {} : { timeoutMs: hook.timeoutMs }),
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return out;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Older installed_plugins.json entries predate hook digests and remain
|
|
318
|
+
* compatible as `legacy`. New entries fail closed when their effective hook
|
|
319
|
+
* file no longer matches the bytes approved by install/update.
|
|
320
|
+
*/
|
|
321
|
+
export function verifyPluginHookIntegrity(entry, snapshot = inspectPluginHooks(entry.installPath)) {
|
|
322
|
+
if (!entry.hookDigest)
|
|
323
|
+
return "legacy";
|
|
324
|
+
return snapshot.digest === entry.hookDigest ? "verified" : "changed";
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Runtime trust state for one installed plugin. Legacy entries stay compatible;
|
|
328
|
+
* new entries with executable hooks remain pending until the approved digest
|
|
329
|
+
* matches the install-time digest. Invalid definitions always fail closed as
|
|
330
|
+
* hook-free regardless of legacy state.
|
|
331
|
+
*/
|
|
332
|
+
export function pluginHookApprovalState(entry, snapshot = inspectPluginHooks(entry.installPath)) {
|
|
333
|
+
if (!snapshot.hasExecutableHooks)
|
|
334
|
+
return "none";
|
|
335
|
+
const integrity = verifyPluginHookIntegrity(entry, snapshot);
|
|
336
|
+
if (integrity === "legacy")
|
|
337
|
+
return "legacy";
|
|
338
|
+
if (integrity === "changed")
|
|
339
|
+
return "changed";
|
|
340
|
+
return entry.approvedHookDigest === entry.hookDigest ? "approved" : "pending";
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Integrity fields written at install/update. Hook-free packages approve the
|
|
344
|
+
* absent-hooks digest automatically; executable hooks require explicit trust.
|
|
345
|
+
* A previously approved identical digest remains approved across an update.
|
|
346
|
+
*/
|
|
347
|
+
export function pluginHookInstallRecord(installPath, previousEntries = []) {
|
|
348
|
+
const snapshot = inspectPluginHooks(installPath);
|
|
349
|
+
const previouslyApproved = previousEntries.find((entry) => entry.hookDigest === snapshot.digest && entry.approvedHookDigest === entry.hookDigest);
|
|
350
|
+
const previousReview = previousEntries.find((entry) => entry.approvedHookDigest === entry.hookDigest && entry.approvedHookSnapshot !== undefined)?.approvedHookSnapshot;
|
|
351
|
+
const approved = snapshot.state !== "invalid" && (!snapshot.hasExecutableHooks || previouslyApproved);
|
|
352
|
+
return {
|
|
353
|
+
hookDigest: snapshot.digest,
|
|
354
|
+
...(approved ? { approvedHookDigest: snapshot.digest } : {}),
|
|
355
|
+
...(approved
|
|
356
|
+
? { approvedHookSnapshot: pluginHookReviewSnapshot(snapshot) }
|
|
357
|
+
: previousReview
|
|
358
|
+
? { approvedHookSnapshot: previousReview }
|
|
359
|
+
: {}),
|
|
360
|
+
};
|
|
361
|
+
}
|
|
@@ -5,16 +5,26 @@
|
|
|
5
5
|
* sparse-checkout, no npm/pip.
|
|
6
6
|
*/
|
|
7
7
|
import { existsSync, realpathSync, rmSync, rmdirSync } from "node:fs";
|
|
8
|
-
import { cp, mkdir, mkdtemp, rm } from "node:fs/promises";
|
|
8
|
+
import { cp, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
9
9
|
import { dirname, join, sep } from "node:path";
|
|
10
10
|
import { homedir, tmpdir } from "node:os";
|
|
11
|
-
import { gitClone, gitRevParseHead, gitSparseCheckoutAdd, githubRepoToCloneUrl
|
|
11
|
+
import { gitClone, gitRevParseHead, gitSparseCheckoutAdd, githubRepoToCloneUrl } from "./gitOps.js";
|
|
12
12
|
import { loadMarketplace } from "./marketplaceManager.js";
|
|
13
13
|
import { readKnownMarketplaces } from "./knownMarketplaces.js";
|
|
14
14
|
import { appendInstallEntry, pluginInstallKey, readInstalledPlugins, removeInstallEntries, } from "./installedPlugins.js";
|
|
15
15
|
import { rewritePluginVars } from "./varRewrite.js";
|
|
16
|
+
import { pluginHookInstallRecord } from "./pluginHookIntegrity.js";
|
|
17
|
+
import { pluginMcpInstallRecord } from "./pluginMcpIntegrity.js";
|
|
16
18
|
import { assertSafePluginName } from "./installer/paths.js";
|
|
17
19
|
import { pruneDisabledSettingsForPlugin } from "./installer/pruneDisabled.js";
|
|
20
|
+
import { detectPluginFormat } from "./installer/detectFormat.js";
|
|
21
|
+
import { normalizePluginManifest } from "./installer/normalizeManifest.js";
|
|
22
|
+
import { normalizePluginMcpMap, readPluginMcp } from "./installer/loadPluginMcp.js";
|
|
23
|
+
import { convertCodexAgentsDirectory } from "./installer/codex/convertAgents.js";
|
|
24
|
+
import { copyCodexCommands } from "./installer/codex/convertCommands.js";
|
|
25
|
+
import { copyCodexHooks } from "./installer/codex/convertHooks.js";
|
|
26
|
+
import { resolveCodexMcpServers } from "./installer/codex/convertMcp.js";
|
|
27
|
+
import { CodexPluginManifest } from "./installer/types.js";
|
|
18
28
|
import { resolveContainedPluginSubpath, validateRelativePluginSubpath, } from "./installer/sourcePath.js";
|
|
19
29
|
function userHome() {
|
|
20
30
|
return process.env.HOME ?? homedir();
|
|
@@ -81,6 +91,29 @@ export function resolveSafePluginPath(installPath, cacheRoot) {
|
|
|
81
91
|
return null;
|
|
82
92
|
return resolvedTarget;
|
|
83
93
|
}
|
|
94
|
+
async function projectMarketplacePluginRuntime(pluginDir, pluginName, format) {
|
|
95
|
+
if (format !== "codex")
|
|
96
|
+
return;
|
|
97
|
+
const manifest = CodexPluginManifest.parse(JSON.parse(await readFile(join(pluginDir, ".codex-plugin", "plugin.json"), "utf-8")));
|
|
98
|
+
// Marketplace installs already preserve the complete source package. Add
|
|
99
|
+
// only the CodeShell-native projections that runtime loaders consume.
|
|
100
|
+
await convertCodexAgentsDirectory(pluginDir, pluginDir, pluginName);
|
|
101
|
+
await copyCodexCommands(pluginDir, pluginDir);
|
|
102
|
+
await copyCodexHooks(pluginDir, pluginDir, manifest.hooks);
|
|
103
|
+
const servers = resolveCodexMcpServers(pluginDir, manifest.mcpServers);
|
|
104
|
+
const keyed = {};
|
|
105
|
+
for (const [serverName, config] of Object.entries(servers)) {
|
|
106
|
+
const key = `${pluginName}:${serverName}`;
|
|
107
|
+
keyed[key] = { ...config, name: key };
|
|
108
|
+
}
|
|
109
|
+
if (Object.keys(keyed).length > 0) {
|
|
110
|
+
const normalized = normalizePluginMcpMap(keyed, pluginName, true);
|
|
111
|
+
if (Object.keys(normalized).length !== Object.keys(keyed).length) {
|
|
112
|
+
throw new Error("invalid plugin MCP server declaration");
|
|
113
|
+
}
|
|
114
|
+
await writeFile(join(pluginDir, "mcp-servers.json"), JSON.stringify(normalized, null, 2), "utf-8");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
84
117
|
async function materializePath(marketplaceInstallLocation, relativePath, cacheTarget) {
|
|
85
118
|
const contained = resolveContainedPluginSubpath(marketplaceInstallLocation, relativePath, "plugin source path");
|
|
86
119
|
if (!contained.ok) {
|
|
@@ -240,7 +273,10 @@ async function materialize(source, marketplaceInstallLocation, marketplace, plug
|
|
|
240
273
|
await rm(placeholder, { recursive: true, force: true });
|
|
241
274
|
return { ok: true, cacheDir: finalDir, version, sha: r.sha };
|
|
242
275
|
}
|
|
243
|
-
return {
|
|
276
|
+
return {
|
|
277
|
+
ok: false,
|
|
278
|
+
error: `unsupported source type "${source.source}"`,
|
|
279
|
+
};
|
|
244
280
|
}
|
|
245
281
|
/**
|
|
246
282
|
* Install a plugin from a previously-added marketplace into the user
|
|
@@ -248,6 +284,8 @@ async function materialize(source, marketplaceInstallLocation, marketplace, plug
|
|
|
248
284
|
* cached files and updates the manifest entry.
|
|
249
285
|
*/
|
|
250
286
|
export async function installPlugin(pluginName, marketplaceName) {
|
|
287
|
+
const key = pluginInstallKey(pluginName, marketplaceName);
|
|
288
|
+
const previousEntries = readInstalledPlugins().plugins[key] ?? [];
|
|
251
289
|
const known = readKnownMarketplaces();
|
|
252
290
|
const km = known[marketplaceName];
|
|
253
291
|
if (!km) {
|
|
@@ -265,7 +303,10 @@ export async function installPlugin(pluginName, marketplaceName) {
|
|
|
265
303
|
}
|
|
266
304
|
const entry = manifest.plugins.find((p) => p.name === pluginName);
|
|
267
305
|
if (!entry) {
|
|
268
|
-
return {
|
|
306
|
+
return {
|
|
307
|
+
ok: false,
|
|
308
|
+
error: `plugin "${pluginName}" not found in marketplace "${marketplaceName}".`,
|
|
309
|
+
};
|
|
269
310
|
}
|
|
270
311
|
// materialize() validates every cache path segment (marketplace / plugin /
|
|
271
312
|
// version) and throws a PluginInstallError on an unsafe one. Convert that to
|
|
@@ -281,17 +322,33 @@ export async function installPlugin(pluginName, marketplaceName) {
|
|
|
281
322
|
}
|
|
282
323
|
if (!mat.ok)
|
|
283
324
|
return mat;
|
|
284
|
-
//
|
|
285
|
-
//
|
|
286
|
-
//
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
325
|
+
// Project Codex package components into the same runtime-native layout used
|
|
326
|
+
// by local/direct installs, then validate and freeze the author manifest
|
|
327
|
+
// before the install becomes visible in installed_plugins.json.
|
|
328
|
+
try {
|
|
329
|
+
const format = detectPluginFormat(mat.cacheDir);
|
|
330
|
+
await projectMarketplacePluginRuntime(mat.cacheDir, pluginName, format);
|
|
331
|
+
await normalizePluginManifest(mat.cacheDir, {
|
|
332
|
+
name: pluginName,
|
|
333
|
+
version: entry.version ?? mat.version,
|
|
334
|
+
format,
|
|
335
|
+
destinationRoot: mat.cacheDir,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
await rm(mat.cacheDir, { recursive: true, force: true });
|
|
340
|
+
return {
|
|
341
|
+
ok: false,
|
|
342
|
+
error: `invalid plugin manifest: ${error instanceof Error ? error.message : String(error)}`,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
// Rewrite Claude-specific plugin root/data variables across every text file
|
|
346
|
+
// in the materialized tree. The runtime exposes CodeShell-native names plus
|
|
347
|
+
// Codex aliases, while keeping Claude host-detection variables unset. The
|
|
348
|
+
// breadcrumb documents the rewrite for users debugging upstream diffs.
|
|
291
349
|
const rewriteSummary = rewritePluginVars(mat.cacheDir);
|
|
292
350
|
// Remove old install entries for the same key so we don't pile up
|
|
293
351
|
// historical versions (Phase A: single-scope only).
|
|
294
|
-
const key = pluginInstallKey(pluginName, marketplaceName);
|
|
295
352
|
removeInstallEntries(key);
|
|
296
353
|
const now = new Date().toISOString();
|
|
297
354
|
const installEntry = {
|
|
@@ -301,6 +358,8 @@ export async function installPlugin(pluginName, marketplaceName) {
|
|
|
301
358
|
installedAt: now,
|
|
302
359
|
lastUpdated: now,
|
|
303
360
|
...(mat.sha ? { gitCommitSha: mat.sha } : {}),
|
|
361
|
+
...pluginHookInstallRecord(mat.cacheDir, previousEntries),
|
|
362
|
+
...pluginMcpInstallRecord(mat.cacheDir, Object.keys(readPluginMcp(mat.cacheDir, pluginName)).length > 0, previousEntries),
|
|
304
363
|
};
|
|
305
364
|
appendInstallEntry(key, installEntry);
|
|
306
365
|
return {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type PluginMcpApprovalState } from "./pluginMcpIntegrity.js";
|
|
2
|
+
export interface PluginMcpTrustEntry {
|
|
3
|
+
installKey: string;
|
|
4
|
+
plugin: string;
|
|
5
|
+
serverNames: string[];
|
|
6
|
+
status: PluginMcpApprovalState;
|
|
7
|
+
}
|
|
8
|
+
export interface PluginMcpApprovalResult extends PluginMcpTrustEntry {
|
|
9
|
+
changed: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** List every installed plugin's MCP trust without merging user MCP config. */
|
|
12
|
+
export declare function listPluginMcpTrust(): PluginMcpTrustEntry[];
|
|
13
|
+
/** Approve only the install-time MCP bytes; tampered bytes require update/reinstall. */
|
|
14
|
+
export declare function approvePluginMcp(target: string): PluginMcpApprovalResult[];
|
|
15
|
+
/**
|
|
16
|
+
* Revoke plugin MCP execution. Legacy entries first record their current
|
|
17
|
+
* digest, preventing revocation from falling back to legacy compatibility.
|
|
18
|
+
*/
|
|
19
|
+
export declare function revokePluginMcp(target: string): PluginMcpApprovalResult[];
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { readInstalledPlugins, writeInstalledPlugins } from "./installedPlugins.js";
|
|
2
|
+
import { readPluginMcp } from "./installer/loadPluginMcp.js";
|
|
3
|
+
import { pluginMcpApprovalState, pluginMcpDigest, } from "./pluginMcpIntegrity.js";
|
|
4
|
+
function pluginNameFromKey(key) {
|
|
5
|
+
const at = key.lastIndexOf("@");
|
|
6
|
+
return at > 0 ? key.slice(0, at) : key;
|
|
7
|
+
}
|
|
8
|
+
function matchingInstallKeys(data, target) {
|
|
9
|
+
if (!target.trim())
|
|
10
|
+
throw new Error("plugin MCP approval requires a plugin name or install key");
|
|
11
|
+
if (data.plugins[target])
|
|
12
|
+
return [target];
|
|
13
|
+
const matches = Object.keys(data.plugins).filter((key) => pluginNameFromKey(key) === target);
|
|
14
|
+
if (matches.length === 0)
|
|
15
|
+
throw new Error(`plugin "${target}" is not installed`);
|
|
16
|
+
if (matches.length > 1) {
|
|
17
|
+
throw new Error(`plugin "${target}" has multiple installs; use one of: ${matches.join(", ")}`);
|
|
18
|
+
}
|
|
19
|
+
return matches;
|
|
20
|
+
}
|
|
21
|
+
function trustEntry(installKey, entry, changed) {
|
|
22
|
+
const plugin = pluginNameFromKey(installKey);
|
|
23
|
+
const serverNames = Object.keys(readPluginMcp(entry.installPath, plugin))
|
|
24
|
+
.map((name) => name.slice(plugin.length + 1))
|
|
25
|
+
.sort();
|
|
26
|
+
const base = {
|
|
27
|
+
installKey,
|
|
28
|
+
plugin,
|
|
29
|
+
serverNames,
|
|
30
|
+
status: pluginMcpApprovalState(entry, serverNames.length > 0),
|
|
31
|
+
};
|
|
32
|
+
return changed === undefined ? base : { ...base, changed };
|
|
33
|
+
}
|
|
34
|
+
/** List every installed plugin's MCP trust without merging user MCP config. */
|
|
35
|
+
export function listPluginMcpTrust() {
|
|
36
|
+
const data = readInstalledPlugins();
|
|
37
|
+
const out = [];
|
|
38
|
+
for (const [installKey, entries] of Object.entries(data.plugins)) {
|
|
39
|
+
for (const entry of entries) {
|
|
40
|
+
out.push(trustEntry(installKey, entry));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return out.sort((a, b) => a.installKey.localeCompare(b.installKey));
|
|
44
|
+
}
|
|
45
|
+
/** Approve only the install-time MCP bytes; tampered bytes require update/reinstall. */
|
|
46
|
+
export function approvePluginMcp(target) {
|
|
47
|
+
const data = readInstalledPlugins();
|
|
48
|
+
const keys = matchingInstallKeys(data, target);
|
|
49
|
+
const out = [];
|
|
50
|
+
let writeNeeded = false;
|
|
51
|
+
for (const installKey of keys) {
|
|
52
|
+
for (const entry of data.plugins[installKey] ?? []) {
|
|
53
|
+
let entryChanged = false;
|
|
54
|
+
const currentDigest = pluginMcpDigest(entry.installPath);
|
|
55
|
+
if (entry.mcpDigest && currentDigest !== entry.mcpDigest) {
|
|
56
|
+
throw new Error(`plugin "${installKey}" MCP config changed after install; reinstall or update before approving`);
|
|
57
|
+
}
|
|
58
|
+
if (!entry.mcpDigest) {
|
|
59
|
+
entry.mcpDigest = currentDigest;
|
|
60
|
+
entryChanged = true;
|
|
61
|
+
}
|
|
62
|
+
if (entry.approvedMcpDigest !== entry.mcpDigest) {
|
|
63
|
+
entry.approvedMcpDigest = entry.mcpDigest;
|
|
64
|
+
entryChanged = true;
|
|
65
|
+
}
|
|
66
|
+
writeNeeded ||= entryChanged;
|
|
67
|
+
out.push(trustEntry(installKey, entry, entryChanged));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (writeNeeded)
|
|
71
|
+
writeInstalledPlugins(data);
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Revoke plugin MCP execution. Legacy entries first record their current
|
|
76
|
+
* digest, preventing revocation from falling back to legacy compatibility.
|
|
77
|
+
*/
|
|
78
|
+
export function revokePluginMcp(target) {
|
|
79
|
+
const data = readInstalledPlugins();
|
|
80
|
+
const keys = matchingInstallKeys(data, target);
|
|
81
|
+
const out = [];
|
|
82
|
+
let writeNeeded = false;
|
|
83
|
+
for (const installKey of keys) {
|
|
84
|
+
const plugin = pluginNameFromKey(installKey);
|
|
85
|
+
for (const entry of data.plugins[installKey] ?? []) {
|
|
86
|
+
let entryChanged = false;
|
|
87
|
+
const hasServers = Object.keys(readPluginMcp(entry.installPath, plugin)).length > 0;
|
|
88
|
+
const currentDigest = pluginMcpDigest(entry.installPath);
|
|
89
|
+
if (!entry.mcpDigest) {
|
|
90
|
+
entry.mcpDigest = currentDigest;
|
|
91
|
+
entryChanged = true;
|
|
92
|
+
}
|
|
93
|
+
if (hasServers || currentDigest !== entry.mcpDigest) {
|
|
94
|
+
if (entry.approvedMcpDigest !== undefined) {
|
|
95
|
+
delete entry.approvedMcpDigest;
|
|
96
|
+
entryChanged = true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else if (entry.approvedMcpDigest !== entry.mcpDigest) {
|
|
100
|
+
entry.approvedMcpDigest = entry.mcpDigest;
|
|
101
|
+
entryChanged = true;
|
|
102
|
+
}
|
|
103
|
+
writeNeeded ||= entryChanged;
|
|
104
|
+
out.push(trustEntry(installKey, entry, entryChanged));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (writeNeeded)
|
|
108
|
+
writeInstalledPlugins(data);
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PluginInstallEntry } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Digest the exact effective declaration selected by the runtime. The file
|
|
4
|
+
* name is part of the digest so switching between native and CC shapes cannot
|
|
5
|
+
* inherit approval accidentally.
|
|
6
|
+
*/
|
|
7
|
+
export declare function pluginMcpDigest(installPath: string): string;
|
|
8
|
+
export type PluginMcpIntegrity = "verified" | "changed" | "legacy";
|
|
9
|
+
export type PluginMcpApprovalState = "approved" | "pending" | "changed" | "legacy" | "none";
|
|
10
|
+
export declare function verifyPluginMcpIntegrity(entry: PluginInstallEntry): PluginMcpIntegrity;
|
|
11
|
+
/**
|
|
12
|
+
* Compute trust for one install. The caller supplies whether the declaration
|
|
13
|
+
* currently normalizes to at least one runnable MCP server, keeping the trust
|
|
14
|
+
* layer coupled to the runtime's strict schema rather than a second parser.
|
|
15
|
+
*/
|
|
16
|
+
export declare function pluginMcpApprovalState(entry: PluginInstallEntry, hasMcpServers: boolean): PluginMcpApprovalState;
|
|
17
|
+
/**
|
|
18
|
+
* Fields written at install/update. Installs with runnable MCP servers start
|
|
19
|
+
* pending; an explicitly approved identical digest survives an update.
|
|
20
|
+
*/
|
|
21
|
+
export declare function pluginMcpInstallRecord(installPath: string, hasMcpServers: boolean, previousEntries?: PluginInstallEntry[]): Pick<PluginInstallEntry, "mcpDigest" | "approvedMcpDigest">;
|