@cjhyy/code-shell-core 0.7.1 → 0.8.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 +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 +7 -3
- package/dist/context/compaction.d.ts +39 -3
- package/dist/context/compaction.js +151 -39
- package/dist/context/manager.d.ts +17 -1
- package/dist/context/manager.js +36 -1
- package/dist/credentials/access.d.ts +3 -1
- package/dist/credentials/access.js +24 -3
- package/dist/credentials/index.d.ts +1 -1
- package/dist/credentials/index.js +1 -1
- package/dist/credentials/oauth.d.ts +4 -1
- package/dist/credentials/oauth.js +14 -0
- package/dist/credentials/store.d.ts +15 -1
- package/dist/credentials/store.js +17 -4
- package/dist/credentials/types.d.ts +24 -0
- 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 +254 -195
- package/dist/engine/engine.js +1812 -2041
- 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/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 +49 -10
- package/dist/engine/turn-loop.js +370 -104
- package/dist/engine/types.d.ts +30 -3
- package/dist/engine/types.js +1 -1
- package/dist/{engine/goal.d.ts → goal/lifecycle.d.ts} +76 -4
- package/dist/goal/lifecycle.js +482 -0
- package/dist/hooks/events.d.ts +24 -10
- package/dist/hooks/goal-stop-hook.d.ts +17 -28
- package/dist/hooks/goal-stop-hook.js +110 -465
- package/dist/hooks/registry.js +1 -1
- package/dist/index.d.ts +48 -108
- 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 +34 -123
- 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 +60 -0
- 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/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 +6 -0
- package/dist/plugins/pluginCommandHook.js +25 -8
- 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 +64 -1
- package/dist/protocol/chat-session-manager.js +104 -0
- package/dist/protocol/chat-session.d.ts +61 -10
- package/dist/protocol/chat-session.js +135 -25
- package/dist/protocol/client.d.ts +33 -3
- package/dist/protocol/client.js +96 -5
- 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 +127 -3
- package/dist/protocol/server.js +1309 -182
- package/dist/protocol/types.d.ts +152 -34
- package/dist/protocol/types.js +16 -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.js +10 -1
- package/dist/services/memory-orchestrator.js +6 -2
- package/dist/services/oauth.js +4 -1
- 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 +182 -28
- package/dist/session/session-manager.js +910 -130
- package/dist/session/session-message.d.ts +22 -0
- package/dist/session/session-message.js +1 -0
- package/dist/session/transcript.d.ts +46 -5
- package/dist/session/transcript.js +159 -3
- 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 +274 -33
- package/dist/tool-system/builtin/background-jobs.d.ts +55 -2
- package/dist/tool-system/builtin/background-jobs.js +96 -4
- package/dist/tool-system/builtin/background-work.d.ts +6 -0
- package/dist/tool-system/builtin/background-work.js +8 -1
- package/dist/tool-system/builtin/bash.js +5 -2
- package/dist/tool-system/builtin/browser-tools.d.ts +6 -3
- 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.js +2 -6
- 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.js +26 -7
- package/dist/tool-system/builtin/grep.js +2 -2
- package/dist/tool-system/builtin/image-uploader.js +7 -1
- package/dist/tool-system/builtin/index.d.ts +32 -7
- package/dist/tool-system/builtin/index.js +237 -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/web-fetch.js +17 -13
- package/dist/tool-system/builtin/web-search.js +1 -3
- 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 +77 -19
- package/dist/tool-system/executor.js +75 -50
- 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 +11 -1
- package/dist/tool-system/mcp-manager.js +19 -4
- 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.js +99 -2
- package/dist/tool-system/permission.d.ts +26 -0
- package/dist/tool-system/permission.js +46 -0
- package/dist/tool-system/registry.d.ts +12 -1
- package/dist/tool-system/registry.js +31 -7
- 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 +186 -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 -45
- package/dist/arena/arena.js +0 -362
- 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 -25
- package/dist/arena/phases/adjudication.js +0 -142
- package/dist/arena/phases/build-consensus.d.ts +0 -30
- package/dist/arena/phases/build-consensus.js +0 -85
- 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 -47
- package/dist/arena/phases/cross-review.js +0 -224
- package/dist/arena/phases/debate-rounds.d.ts +0 -28
- package/dist/arena/phases/debate-rounds.js +0 -161
- package/dist/arena/phases/participant-research.d.ts +0 -39
- package/dist/arena/phases/participant-research.js +0 -316
- package/dist/arena/phases/planning-detail-expansion.d.ts +0 -39
- package/dist/arena/phases/planning-detail-expansion.js +0 -120
- package/dist/arena/planner.d.ts +0 -28
- package/dist/arena/planner.js +0 -312
- 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 -518
- 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 -72
- package/dist/git/worktree/crud.js +0 -235
- 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 -87
- 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 -43
- package/dist/git/worktree/query.js +0 -128
- 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 -416
- 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 -363
- /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,306 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { mkdir, readFile, realpath, rm, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import { extname, join, resolve, sep } from "node:path";
|
|
4
|
+
import { CANONICAL_PLUGIN_MANIFEST_FILE, CODESHELL_PLUGIN_OVERLAY_FILE, CanonicalPluginManifest, CodeShellPluginOverlay, CodexPluginManifest, PluginInterfaceMetadata, PluginAutomationsManifest, } from "./types.js";
|
|
5
|
+
import { validateSchedule } from "../../automation/scheduler.js";
|
|
6
|
+
const CANONICAL_PLUGIN_ASSET_DIR = ".cs-plugin-assets";
|
|
7
|
+
const MAX_PLUGIN_BRAND_ASSET_BYTES = 2 * 1024 * 1024;
|
|
8
|
+
const MAX_PLUGIN_SCREENSHOT_BYTES = 5 * 1024 * 1024;
|
|
9
|
+
const MAX_PLUGIN_IMAGE_DIMENSION = 8192;
|
|
10
|
+
const MAX_PLUGIN_IMAGE_PIXELS = 40_000_000;
|
|
11
|
+
const MAX_PLUGIN_MANIFEST_BYTES = 1024 * 1024;
|
|
12
|
+
function manifestPath(sourceRoot, format) {
|
|
13
|
+
return join(sourceRoot, format === "codex" ? ".codex-plugin" : ".claude-plugin", "plugin.json");
|
|
14
|
+
}
|
|
15
|
+
function isContained(root, candidate) {
|
|
16
|
+
const withSep = root.endsWith(sep) ? root : `${root}${sep}`;
|
|
17
|
+
return candidate.startsWith(withSep);
|
|
18
|
+
}
|
|
19
|
+
function safeAuthorAssetPath(value, field) {
|
|
20
|
+
if (value !== value.trim() ||
|
|
21
|
+
!value.startsWith("./") ||
|
|
22
|
+
value.includes("\\") ||
|
|
23
|
+
value.includes("\0") ||
|
|
24
|
+
value.includes("?") ||
|
|
25
|
+
value.includes("#")) {
|
|
26
|
+
throw new Error(`${field} must be a ./ relative path inside the plugin root`);
|
|
27
|
+
}
|
|
28
|
+
const relative = value.slice(2);
|
|
29
|
+
if (!relative ||
|
|
30
|
+
relative.split("/").some((segment) => segment === "" || segment === "." || segment === "..")) {
|
|
31
|
+
throw new Error(`${field} must be a safe relative path inside the plugin root`);
|
|
32
|
+
}
|
|
33
|
+
return relative;
|
|
34
|
+
}
|
|
35
|
+
function readUInt24LE(bytes, offset) {
|
|
36
|
+
return bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16);
|
|
37
|
+
}
|
|
38
|
+
function pngDimensions(bytes) {
|
|
39
|
+
if (bytes.length < 24 ||
|
|
40
|
+
!bytes.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])) ||
|
|
41
|
+
bytes.readUInt32BE(8) !== 13 ||
|
|
42
|
+
bytes.toString("ascii", 12, 16) !== "IHDR") {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return { width: bytes.readUInt32BE(16), height: bytes.readUInt32BE(20) };
|
|
46
|
+
}
|
|
47
|
+
function jpegDimensions(bytes) {
|
|
48
|
+
if (bytes.length < 4 || bytes[0] !== 0xff || bytes[1] !== 0xd8)
|
|
49
|
+
return null;
|
|
50
|
+
let offset = 2;
|
|
51
|
+
while (offset + 4 <= bytes.length) {
|
|
52
|
+
while (offset < bytes.length && bytes[offset] === 0xff)
|
|
53
|
+
offset += 1;
|
|
54
|
+
if (offset >= bytes.length)
|
|
55
|
+
break;
|
|
56
|
+
const marker = bytes[offset];
|
|
57
|
+
offset += 1;
|
|
58
|
+
if (marker === 0xd8 ||
|
|
59
|
+
marker === 0xd9 ||
|
|
60
|
+
marker === 0x01 ||
|
|
61
|
+
(marker >= 0xd0 && marker <= 0xd7)) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (offset + 2 > bytes.length)
|
|
65
|
+
return null;
|
|
66
|
+
const length = bytes.readUInt16BE(offset);
|
|
67
|
+
if (length < 2 || offset + length > bytes.length)
|
|
68
|
+
return null;
|
|
69
|
+
const isStartOfFrame = marker >= 0xc0 && marker <= 0xcf && ![0xc4, 0xc8, 0xcc].includes(marker);
|
|
70
|
+
if (isStartOfFrame) {
|
|
71
|
+
if (length < 7)
|
|
72
|
+
return null;
|
|
73
|
+
return {
|
|
74
|
+
width: bytes.readUInt16BE(offset + 5),
|
|
75
|
+
height: bytes.readUInt16BE(offset + 3),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
offset += length;
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
function webpDimensions(bytes) {
|
|
83
|
+
if (bytes.length < 30 ||
|
|
84
|
+
bytes.toString("ascii", 0, 4) !== "RIFF" ||
|
|
85
|
+
bytes.toString("ascii", 8, 12) !== "WEBP" ||
|
|
86
|
+
bytes.readUInt32LE(4) + 8 > bytes.length) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const chunk = bytes.toString("ascii", 12, 16);
|
|
90
|
+
if (chunk === "VP8X") {
|
|
91
|
+
return {
|
|
92
|
+
width: readUInt24LE(bytes, 24) + 1,
|
|
93
|
+
height: readUInt24LE(bytes, 27) + 1,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (chunk === "VP8L" && bytes[20] === 0x2f) {
|
|
97
|
+
return {
|
|
98
|
+
width: 1 + (((bytes[22] & 0x3f) << 8) | bytes[21]),
|
|
99
|
+
height: 1 + (((bytes[24] & 0x0f) << 10) | (bytes[23] << 2) | (bytes[22] >> 6)),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (chunk === "VP8 " && bytes[23] === 0x9d && bytes[24] === 0x01 && bytes[25] === 0x2a) {
|
|
103
|
+
return {
|
|
104
|
+
width: bytes.readUInt16LE(26) & 0x3fff,
|
|
105
|
+
height: bytes.readUInt16LE(28) & 0x3fff,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
function detectRaster(bytes) {
|
|
111
|
+
const png = pngDimensions(bytes);
|
|
112
|
+
if (png)
|
|
113
|
+
return { mediaType: "image/png", ...png };
|
|
114
|
+
const jpeg = jpegDimensions(bytes);
|
|
115
|
+
if (jpeg)
|
|
116
|
+
return { mediaType: "image/jpeg", ...jpeg };
|
|
117
|
+
const webp = webpDimensions(bytes);
|
|
118
|
+
if (webp)
|
|
119
|
+
return { mediaType: "image/webp", ...webp };
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
function expectedMediaType(relativePath) {
|
|
123
|
+
switch (extname(relativePath).toLowerCase()) {
|
|
124
|
+
case ".png":
|
|
125
|
+
return "image/png";
|
|
126
|
+
case ".jpg":
|
|
127
|
+
case ".jpeg":
|
|
128
|
+
return "image/jpeg";
|
|
129
|
+
case ".webp":
|
|
130
|
+
return "image/webp";
|
|
131
|
+
default:
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async function validateRasterAsset(sourceRoot, sourceRootReal, declaredPath, field, maxBytes, screenshot) {
|
|
136
|
+
const relativePath = safeAuthorAssetPath(declaredPath, field);
|
|
137
|
+
if (screenshot &&
|
|
138
|
+
(!relativePath.startsWith("assets/") || extname(relativePath).toLowerCase() !== ".png")) {
|
|
139
|
+
throw new Error(`${field} must be a PNG file under ./assets/`);
|
|
140
|
+
}
|
|
141
|
+
const expected = expectedMediaType(relativePath);
|
|
142
|
+
if (!expected || (screenshot && expected !== "image/png")) {
|
|
143
|
+
throw new Error(`${field} must be PNG, JPEG, or WebP`);
|
|
144
|
+
}
|
|
145
|
+
const candidate = resolve(sourceRoot, ...relativePath.split("/"));
|
|
146
|
+
let target;
|
|
147
|
+
try {
|
|
148
|
+
target = await realpath(candidate);
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
throw new Error(`${field} does not exist: ${declaredPath}`);
|
|
152
|
+
}
|
|
153
|
+
if (!isContained(sourceRootReal, target)) {
|
|
154
|
+
throw new Error(`${field} escapes the plugin root: ${declaredPath}`);
|
|
155
|
+
}
|
|
156
|
+
const info = await stat(target);
|
|
157
|
+
if (!info.isFile())
|
|
158
|
+
throw new Error(`${field} is not a file: ${declaredPath}`);
|
|
159
|
+
if (info.size > maxBytes) {
|
|
160
|
+
throw new Error(`${field} exceeds the ${Math.floor(maxBytes / 1024 / 1024)} MiB limit`);
|
|
161
|
+
}
|
|
162
|
+
const bytes = await readFile(target);
|
|
163
|
+
const detected = detectRaster(bytes);
|
|
164
|
+
if (!detected || detected.mediaType !== expected) {
|
|
165
|
+
throw new Error(`${field} content does not match its supported raster extension`);
|
|
166
|
+
}
|
|
167
|
+
if (detected.width <= 0 ||
|
|
168
|
+
detected.height <= 0 ||
|
|
169
|
+
detected.width > MAX_PLUGIN_IMAGE_DIMENSION ||
|
|
170
|
+
detected.height > MAX_PLUGIN_IMAGE_DIMENSION ||
|
|
171
|
+
detected.width * detected.height > MAX_PLUGIN_IMAGE_PIXELS) {
|
|
172
|
+
throw new Error(`${field} dimensions exceed ${MAX_PLUGIN_IMAGE_DIMENSION}px / ${MAX_PLUGIN_IMAGE_PIXELS} pixels`);
|
|
173
|
+
}
|
|
174
|
+
return { bytes, mediaType: detected.mediaType };
|
|
175
|
+
}
|
|
176
|
+
function canonicalAssetExtension(mediaType) {
|
|
177
|
+
if (mediaType === "image/jpeg")
|
|
178
|
+
return "jpeg";
|
|
179
|
+
if (mediaType === "image/webp")
|
|
180
|
+
return "webp";
|
|
181
|
+
return "png";
|
|
182
|
+
}
|
|
183
|
+
async function normalizeInterfaceAssets(sourceRoot, destinationRoot, metadata) {
|
|
184
|
+
const hasDeclaredAssets = Boolean(metadata.composerIcon || metadata.logo || metadata.logoDark) ||
|
|
185
|
+
metadata.screenshots !== undefined;
|
|
186
|
+
if (!hasDeclaredAssets)
|
|
187
|
+
return metadata;
|
|
188
|
+
const sourceRootReal = await realpath(sourceRoot);
|
|
189
|
+
const declared = [
|
|
190
|
+
["composerIcon", metadata.composerIcon, "composer-icon"],
|
|
191
|
+
["logo", metadata.logo, "logo"],
|
|
192
|
+
["logoDark", metadata.logoDark, "logo-dark"],
|
|
193
|
+
];
|
|
194
|
+
const brandAssets = await Promise.all(declared.map(async ([field, value, canonicalName]) => {
|
|
195
|
+
if (!value)
|
|
196
|
+
return null;
|
|
197
|
+
const asset = await validateRasterAsset(sourceRoot, sourceRootReal, value, `interface.${field}`, MAX_PLUGIN_BRAND_ASSET_BYTES, false);
|
|
198
|
+
return { field, canonicalName, asset };
|
|
199
|
+
}));
|
|
200
|
+
const screenshots = await Promise.all((metadata.screenshots ?? []).map(async (value, index) => ({
|
|
201
|
+
canonicalName: `screenshot-${index + 1}`,
|
|
202
|
+
asset: await validateRasterAsset(sourceRoot, sourceRootReal, value, `interface.screenshots[${index}]`, MAX_PLUGIN_SCREENSHOT_BYTES, true),
|
|
203
|
+
})));
|
|
204
|
+
const assetRoot = join(destinationRoot, CANONICAL_PLUGIN_ASSET_DIR);
|
|
205
|
+
await rm(assetRoot, { recursive: true, force: true });
|
|
206
|
+
const hasAssets = brandAssets.some(Boolean) || screenshots.length > 0;
|
|
207
|
+
if (hasAssets)
|
|
208
|
+
await mkdir(assetRoot, { recursive: true });
|
|
209
|
+
const normalized = { ...metadata };
|
|
210
|
+
for (const entry of brandAssets) {
|
|
211
|
+
if (!entry)
|
|
212
|
+
continue;
|
|
213
|
+
const relativePath = `${CANONICAL_PLUGIN_ASSET_DIR}/${entry.canonicalName}.${canonicalAssetExtension(entry.asset.mediaType)}`;
|
|
214
|
+
await writeFile(join(destinationRoot, relativePath), entry.asset.bytes);
|
|
215
|
+
normalized[entry.field] = relativePath;
|
|
216
|
+
}
|
|
217
|
+
if (metadata.screenshots !== undefined) {
|
|
218
|
+
normalized.screenshots = [];
|
|
219
|
+
for (const entry of screenshots) {
|
|
220
|
+
const relativePath = `${CANONICAL_PLUGIN_ASSET_DIR}/${entry.canonicalName}.png`;
|
|
221
|
+
await writeFile(join(destinationRoot, relativePath), entry.asset.bytes);
|
|
222
|
+
normalized.screenshots.push(relativePath);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return normalized;
|
|
226
|
+
}
|
|
227
|
+
async function readCodeShellOverlay(sourceRoot) {
|
|
228
|
+
const file = join(sourceRoot, CODESHELL_PLUGIN_OVERLAY_FILE);
|
|
229
|
+
if (!existsSync(file))
|
|
230
|
+
return null;
|
|
231
|
+
const info = await stat(file);
|
|
232
|
+
if (!info.isFile() || info.size > MAX_PLUGIN_MANIFEST_BYTES) {
|
|
233
|
+
throw new Error(`${CODESHELL_PLUGIN_OVERLAY_FILE} must be a regular file no larger than ${MAX_PLUGIN_MANIFEST_BYTES} bytes`);
|
|
234
|
+
}
|
|
235
|
+
const raw = JSON.parse(await readFile(file, "utf-8"));
|
|
236
|
+
if (raw.panels !== undefined) {
|
|
237
|
+
throw new Error("Agent Plugin packages cannot declare panels; package Desktop UI as a separate " +
|
|
238
|
+
".codeshell-panel/panel.json Panel App");
|
|
239
|
+
}
|
|
240
|
+
return CodeShellPluginOverlay.parse(raw);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Normalize an Agent Plugin into the runtime manifest. Desktop Panel Apps have
|
|
244
|
+
* their own package and installer, so a Plugin declaration cannot contain UI.
|
|
245
|
+
*/
|
|
246
|
+
export async function normalizePluginManifest(sourceRoot, options) {
|
|
247
|
+
const authorPath = manifestPath(sourceRoot, options.format);
|
|
248
|
+
let raw = {};
|
|
249
|
+
if (existsSync(authorPath)) {
|
|
250
|
+
const info = await stat(authorPath);
|
|
251
|
+
if (!info.isFile() || info.size > MAX_PLUGIN_MANIFEST_BYTES) {
|
|
252
|
+
throw new Error(`plugin manifest must be a regular file no larger than ${MAX_PLUGIN_MANIFEST_BYTES} bytes`);
|
|
253
|
+
}
|
|
254
|
+
raw = JSON.parse(await readFile(authorPath, "utf-8"));
|
|
255
|
+
}
|
|
256
|
+
const parsed = options.format === "codex"
|
|
257
|
+
? CodexPluginManifest.parse(raw)
|
|
258
|
+
: {
|
|
259
|
+
description: typeof raw.description === "string" ? raw.description : undefined,
|
|
260
|
+
interface: undefined,
|
|
261
|
+
};
|
|
262
|
+
const overlay = await readCodeShellOverlay(sourceRoot);
|
|
263
|
+
if (raw.panels !== undefined) {
|
|
264
|
+
throw new Error("Agent Plugin packages cannot declare panels; package Desktop UI as a separate " +
|
|
265
|
+
".codeshell-panel/panel.json Panel App");
|
|
266
|
+
}
|
|
267
|
+
const automations = overlay?.automations
|
|
268
|
+
? PluginAutomationsManifest.parse(overlay.automations)
|
|
269
|
+
: undefined;
|
|
270
|
+
for (const template of automations?.templates ?? []) {
|
|
271
|
+
try {
|
|
272
|
+
validateSchedule(template.schedule, template.timezone);
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
throw new Error(`automation template '${template.id}' has an invalid schedule: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
const parsedInterface = parsed.interface
|
|
279
|
+
? PluginInterfaceMetadata.parse(parsed.interface)
|
|
280
|
+
: undefined;
|
|
281
|
+
const normalizedInterface = parsedInterface
|
|
282
|
+
? await normalizeInterfaceAssets(sourceRoot, options.destinationRoot, parsedInterface)
|
|
283
|
+
: undefined;
|
|
284
|
+
const canonical = CanonicalPluginManifest.parse({
|
|
285
|
+
schemaVersion: 1,
|
|
286
|
+
name: options.name,
|
|
287
|
+
version: options.version ?? (typeof raw.version === "string" ? raw.version : undefined),
|
|
288
|
+
description: parsed.description,
|
|
289
|
+
interface: normalizedInterface,
|
|
290
|
+
automations,
|
|
291
|
+
});
|
|
292
|
+
await mkdir(options.destinationRoot, { recursive: true });
|
|
293
|
+
await writeFile(join(options.destinationRoot, CANONICAL_PLUGIN_MANIFEST_FILE), `${JSON.stringify(canonical, null, 2)}\n`, "utf-8");
|
|
294
|
+
return canonical;
|
|
295
|
+
}
|
|
296
|
+
export async function readCanonicalPluginManifest(installRoot) {
|
|
297
|
+
const file = join(installRoot, CANONICAL_PLUGIN_MANIFEST_FILE);
|
|
298
|
+
if (!existsSync(file))
|
|
299
|
+
return null;
|
|
300
|
+
try {
|
|
301
|
+
return CanonicalPluginManifest.parse(JSON.parse(await readFile(file, "utf-8")));
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const MAX_NPM_TARBALL_BYTES: number;
|
|
2
|
+
export declare const MAX_NPM_TAR_EXTRACTED_BYTES: number;
|
|
3
|
+
export declare const MAX_NPM_TAR_FILE_BYTES: number;
|
|
4
|
+
export declare const MAX_NPM_TAR_ENTRIES = 10000;
|
|
5
|
+
export declare const MAX_NPM_TAR_PATH_BYTES = 1024;
|
|
6
|
+
export declare const MAX_NPM_TAR_DEPTH = 32;
|
|
7
|
+
/** Inflate the npm .tgz into a bounded private tar file. */
|
|
8
|
+
export declare function gunzipNpmTarball(tgzPath: string, tarPath: string): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Extract only regular files/directories from an already-bounded tar.
|
|
11
|
+
* Links, devices, FIFOs, sparse files and every other special type fail closed.
|
|
12
|
+
*/
|
|
13
|
+
export declare function extractNpmTar(tarPath: string, destDir: string): Promise<void>;
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { createReadStream, createWriteStream } from "node:fs";
|
|
2
|
+
import { lstat, mkdir, open, readdir, stat } from "node:fs/promises";
|
|
3
|
+
import { dirname, join, normalize, sep } from "node:path";
|
|
4
|
+
import { Transform } from "node:stream";
|
|
5
|
+
import { pipeline } from "node:stream/promises";
|
|
6
|
+
import { createGunzip } from "node:zlib";
|
|
7
|
+
import { PluginInstallError } from "./types.js";
|
|
8
|
+
export const MAX_NPM_TARBALL_BYTES = 64 * 1024 * 1024;
|
|
9
|
+
export const MAX_NPM_TAR_EXTRACTED_BYTES = 256 * 1024 * 1024;
|
|
10
|
+
export const MAX_NPM_TAR_FILE_BYTES = 64 * 1024 * 1024;
|
|
11
|
+
export const MAX_NPM_TAR_ENTRIES = 10_000;
|
|
12
|
+
export const MAX_NPM_TAR_PATH_BYTES = 1_024;
|
|
13
|
+
export const MAX_NPM_TAR_DEPTH = 32;
|
|
14
|
+
const TAR_BLOCK = 512;
|
|
15
|
+
const MAX_PAX_BYTES = 64 * 1024;
|
|
16
|
+
const utf8 = new TextDecoder("utf-8", { fatal: true });
|
|
17
|
+
function installError(message, cause) {
|
|
18
|
+
const suffix = cause instanceof Error ? `: ${cause.message}` : "";
|
|
19
|
+
return new PluginInstallError(`${message}${suffix}`);
|
|
20
|
+
}
|
|
21
|
+
/** Inflate the npm .tgz into a bounded private tar file. */
|
|
22
|
+
export async function gunzipNpmTarball(tgzPath, tarPath) {
|
|
23
|
+
const compressed = await stat(tgzPath);
|
|
24
|
+
if (!compressed.isFile() || compressed.size > MAX_NPM_TARBALL_BYTES) {
|
|
25
|
+
throw new PluginInstallError(`npm plugin tarball must be a regular file no larger than ${MAX_NPM_TARBALL_BYTES} bytes`);
|
|
26
|
+
}
|
|
27
|
+
let expanded = 0;
|
|
28
|
+
const limiter = new Transform({
|
|
29
|
+
transform(chunk, _encoding, callback) {
|
|
30
|
+
expanded += chunk.length;
|
|
31
|
+
if (expanded > MAX_NPM_TAR_EXTRACTED_BYTES) {
|
|
32
|
+
callback(new PluginInstallError(`npm plugin tarball expands beyond ${MAX_NPM_TAR_EXTRACTED_BYTES} bytes`));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
callback(null, chunk);
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
try {
|
|
39
|
+
await pipeline(createReadStream(tgzPath), createGunzip(), limiter, createWriteStream(tarPath, { flags: "wx", mode: 0o600 }));
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error instanceof PluginInstallError)
|
|
43
|
+
throw error;
|
|
44
|
+
throw installError("cannot decompress npm plugin tarball", error);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function isZeroBlock(block) {
|
|
48
|
+
for (const byte of block)
|
|
49
|
+
if (byte !== 0)
|
|
50
|
+
return false;
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
function decodeField(block, start, length, label) {
|
|
54
|
+
const field = block.subarray(start, start + length);
|
|
55
|
+
const nul = field.indexOf(0);
|
|
56
|
+
const value = nul < 0 ? field : field.subarray(0, nul);
|
|
57
|
+
try {
|
|
58
|
+
return utf8.decode(value);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
throw installError(`npm tar has invalid UTF-8 in ${label}`, error);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function parseOctal(block, start, length, label) {
|
|
65
|
+
const field = block.subarray(start, start + length);
|
|
66
|
+
if ((field[0] ?? 0) & 0x80) {
|
|
67
|
+
throw new PluginInstallError(`npm tar uses unsupported base-256 ${label}`);
|
|
68
|
+
}
|
|
69
|
+
const raw = field.toString("ascii").replace(/\0.*$/, "").trim();
|
|
70
|
+
if (!/^[0-7]+$/.test(raw)) {
|
|
71
|
+
throw new PluginInstallError(`npm tar has invalid ${label}`);
|
|
72
|
+
}
|
|
73
|
+
const value = Number.parseInt(raw, 8);
|
|
74
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
75
|
+
throw new PluginInstallError(`npm tar ${label} is out of range`);
|
|
76
|
+
}
|
|
77
|
+
return value;
|
|
78
|
+
}
|
|
79
|
+
function assertHeaderChecksum(block) {
|
|
80
|
+
const expected = parseOctal(block, 148, 8, "header checksum");
|
|
81
|
+
let actual = 0;
|
|
82
|
+
for (let i = 0; i < block.length; i += 1) {
|
|
83
|
+
actual += i >= 148 && i < 156 ? 0x20 : (block[i] ?? 0);
|
|
84
|
+
}
|
|
85
|
+
if (actual !== expected) {
|
|
86
|
+
throw new PluginInstallError("npm tar header checksum mismatch");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function safeTarPath(destDir, rawName) {
|
|
90
|
+
if (rawName.length === 0 ||
|
|
91
|
+
Buffer.byteLength(rawName, "utf8") > MAX_NPM_TAR_PATH_BYTES ||
|
|
92
|
+
rawName.includes("\0") ||
|
|
93
|
+
rawName.includes("\\") ||
|
|
94
|
+
rawName.startsWith("/") ||
|
|
95
|
+
/^[A-Za-z]:/.test(rawName)) {
|
|
96
|
+
throw new PluginInstallError(`refusing unsafe npm tar path: ${rawName}`);
|
|
97
|
+
}
|
|
98
|
+
const segments = rawName.replace(/\/+$/, "").split("/");
|
|
99
|
+
if (segments.length === 0 ||
|
|
100
|
+
segments.length > MAX_NPM_TAR_DEPTH ||
|
|
101
|
+
segments.some((segment) => segment === "" || segment === "." || segment === "..")) {
|
|
102
|
+
throw new PluginInstallError(`refusing unsafe npm tar path: ${rawName}`);
|
|
103
|
+
}
|
|
104
|
+
const target = normalize(join(destDir, ...segments));
|
|
105
|
+
const root = normalize(destDir.endsWith(sep) ? destDir : destDir + sep);
|
|
106
|
+
if (target !== normalize(destDir) && !target.startsWith(root)) {
|
|
107
|
+
throw new PluginInstallError(`npm tar path escapes extraction root: ${rawName}`);
|
|
108
|
+
}
|
|
109
|
+
// Reject names that collide on the default case-insensitive macOS/Windows
|
|
110
|
+
// filesystems even when tests run on a case-sensitive volume.
|
|
111
|
+
return { target, portableKey: segments.join("/").toLowerCase() };
|
|
112
|
+
}
|
|
113
|
+
async function readExactly(handle, position, length) {
|
|
114
|
+
const value = Buffer.alloc(length);
|
|
115
|
+
let offset = 0;
|
|
116
|
+
while (offset < length) {
|
|
117
|
+
const { bytesRead } = await handle.read(value, offset, length - offset, position + offset);
|
|
118
|
+
if (bytesRead === 0)
|
|
119
|
+
throw new PluginInstallError("npm tar is truncated");
|
|
120
|
+
offset += bytesRead;
|
|
121
|
+
}
|
|
122
|
+
return value;
|
|
123
|
+
}
|
|
124
|
+
function parsePax(data) {
|
|
125
|
+
let cursor = 0;
|
|
126
|
+
const result = {};
|
|
127
|
+
while (cursor < data.length) {
|
|
128
|
+
const space = data.indexOf(0x20, cursor);
|
|
129
|
+
if (space < 0)
|
|
130
|
+
throw new PluginInstallError("npm tar has malformed PAX metadata");
|
|
131
|
+
const lengthText = data.subarray(cursor, space).toString("ascii");
|
|
132
|
+
if (!/^[1-9][0-9]*$/.test(lengthText)) {
|
|
133
|
+
throw new PluginInstallError("npm tar has malformed PAX record length");
|
|
134
|
+
}
|
|
135
|
+
const length = Number(lengthText);
|
|
136
|
+
if (!Number.isSafeInteger(length) ||
|
|
137
|
+
length <= space - cursor + 2 ||
|
|
138
|
+
cursor + length > data.length) {
|
|
139
|
+
throw new PluginInstallError("npm tar has out-of-range PAX record length");
|
|
140
|
+
}
|
|
141
|
+
const record = data.subarray(space + 1, cursor + length);
|
|
142
|
+
if (record[record.length - 1] !== 0x0a) {
|
|
143
|
+
throw new PluginInstallError("npm tar PAX record is not newline terminated");
|
|
144
|
+
}
|
|
145
|
+
let text;
|
|
146
|
+
try {
|
|
147
|
+
text = utf8.decode(record.subarray(0, -1));
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
throw installError("npm tar has invalid UTF-8 in PAX metadata", error);
|
|
151
|
+
}
|
|
152
|
+
const equals = text.indexOf("=");
|
|
153
|
+
if (equals <= 0)
|
|
154
|
+
throw new PluginInstallError("npm tar has malformed PAX metadata");
|
|
155
|
+
const key = text.slice(0, equals);
|
|
156
|
+
const value = text.slice(equals + 1);
|
|
157
|
+
if (key === "path")
|
|
158
|
+
result.path = value;
|
|
159
|
+
if (key === "linkpath") {
|
|
160
|
+
throw new PluginInstallError("npm tar link metadata is forbidden");
|
|
161
|
+
}
|
|
162
|
+
if (key === "size") {
|
|
163
|
+
throw new PluginInstallError("npm tar PAX size overrides are unsupported");
|
|
164
|
+
}
|
|
165
|
+
cursor += length;
|
|
166
|
+
}
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
async function copyFilePayload(source, sourceOffset, target, size) {
|
|
170
|
+
await mkdir(dirname(target), { recursive: true, mode: 0o700 });
|
|
171
|
+
const output = await open(target, "wx", 0o600);
|
|
172
|
+
try {
|
|
173
|
+
let copied = 0;
|
|
174
|
+
while (copied < size) {
|
|
175
|
+
const chunkSize = Math.min(64 * 1024, size - copied);
|
|
176
|
+
const chunk = await readExactly(source, sourceOffset + copied, chunkSize);
|
|
177
|
+
await output.write(chunk, 0, chunk.length, copied);
|
|
178
|
+
copied += chunk.length;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
finally {
|
|
182
|
+
await output.close();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Extract only regular files/directories from an already-bounded tar.
|
|
187
|
+
* Links, devices, FIFOs, sparse files and every other special type fail closed.
|
|
188
|
+
*/
|
|
189
|
+
export async function extractNpmTar(tarPath, destDir) {
|
|
190
|
+
await mkdir(destDir, { recursive: true, mode: 0o700 });
|
|
191
|
+
const destination = await lstat(destDir);
|
|
192
|
+
if (!destination.isDirectory() || destination.isSymbolicLink()) {
|
|
193
|
+
throw new PluginInstallError("npm tar extraction destination must be a real directory");
|
|
194
|
+
}
|
|
195
|
+
if ((await readdir(destDir)).length !== 0) {
|
|
196
|
+
throw new PluginInstallError("npm tar extraction destination must be empty");
|
|
197
|
+
}
|
|
198
|
+
const archive = await stat(tarPath);
|
|
199
|
+
if (!archive.isFile() || archive.size > MAX_NPM_TAR_EXTRACTED_BYTES) {
|
|
200
|
+
throw new PluginInstallError("npm tar is not a bounded regular file");
|
|
201
|
+
}
|
|
202
|
+
const input = await open(tarPath, "r");
|
|
203
|
+
const seen = new Set();
|
|
204
|
+
let entries = 0;
|
|
205
|
+
let materializedBytes = 0;
|
|
206
|
+
let position = 0;
|
|
207
|
+
let zeroBlocks = 0;
|
|
208
|
+
let nextPath;
|
|
209
|
+
try {
|
|
210
|
+
while (position < archive.size) {
|
|
211
|
+
if (position + TAR_BLOCK > archive.size) {
|
|
212
|
+
throw new PluginInstallError("npm tar has a partial header block");
|
|
213
|
+
}
|
|
214
|
+
const header = await readExactly(input, position, TAR_BLOCK);
|
|
215
|
+
position += TAR_BLOCK;
|
|
216
|
+
if (isZeroBlock(header)) {
|
|
217
|
+
zeroBlocks += 1;
|
|
218
|
+
if (zeroBlocks >= 2)
|
|
219
|
+
break;
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
if (zeroBlocks !== 0) {
|
|
223
|
+
throw new PluginInstallError("npm tar has data after an end marker");
|
|
224
|
+
}
|
|
225
|
+
assertHeaderChecksum(header);
|
|
226
|
+
entries += 1;
|
|
227
|
+
if (entries > MAX_NPM_TAR_ENTRIES) {
|
|
228
|
+
throw new PluginInstallError(`npm tar contains more than ${MAX_NPM_TAR_ENTRIES} entries`);
|
|
229
|
+
}
|
|
230
|
+
const name = decodeField(header, 0, 100, "entry name");
|
|
231
|
+
const prefix = decodeField(header, 345, 155, "entry prefix");
|
|
232
|
+
const headerPath = prefix ? `${prefix}/${name}` : name;
|
|
233
|
+
const size = parseOctal(header, 124, 12, "entry size");
|
|
234
|
+
const typeByte = header[156] ?? 0;
|
|
235
|
+
const type = typeByte === 0 ? "0" : String.fromCharCode(typeByte);
|
|
236
|
+
const padded = Math.ceil(size / TAR_BLOCK) * TAR_BLOCK;
|
|
237
|
+
if (position + padded > archive.size) {
|
|
238
|
+
throw new PluginInstallError("npm tar entry payload is truncated");
|
|
239
|
+
}
|
|
240
|
+
if (type === "x") {
|
|
241
|
+
if (size > MAX_PAX_BYTES)
|
|
242
|
+
throw new PluginInstallError("npm tar PAX metadata is too large");
|
|
243
|
+
const pax = parsePax(await readExactly(input, position, size));
|
|
244
|
+
nextPath = pax.path;
|
|
245
|
+
position += padded;
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (type === "g") {
|
|
249
|
+
if (size > MAX_PAX_BYTES)
|
|
250
|
+
throw new PluginInstallError("npm tar PAX metadata is too large");
|
|
251
|
+
parsePax(await readExactly(input, position, size));
|
|
252
|
+
position += padded;
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
if (type === "L") {
|
|
256
|
+
if (size === 0 || size > MAX_NPM_TAR_PATH_BYTES + 1) {
|
|
257
|
+
throw new PluginInstallError("npm tar GNU long path is out of bounds");
|
|
258
|
+
}
|
|
259
|
+
const longName = await readExactly(input, position, size);
|
|
260
|
+
const nul = longName.indexOf(0);
|
|
261
|
+
try {
|
|
262
|
+
nextPath = utf8.decode(nul < 0 ? longName : longName.subarray(0, nul));
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
throw installError("npm tar has invalid UTF-8 in GNU long path", error);
|
|
266
|
+
}
|
|
267
|
+
position += padded;
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
const effectivePath = nextPath ?? headerPath;
|
|
271
|
+
nextPath = undefined;
|
|
272
|
+
if (type !== "0" && type !== "5") {
|
|
273
|
+
const labels = {
|
|
274
|
+
"1": "hardlink",
|
|
275
|
+
"2": "symlink",
|
|
276
|
+
"3": "character device",
|
|
277
|
+
"4": "block device",
|
|
278
|
+
"6": "FIFO",
|
|
279
|
+
};
|
|
280
|
+
throw new PluginInstallError(`npm tar ${labels[type] ?? `special entry type ${JSON.stringify(type)}`} is forbidden: ${effectivePath}`);
|
|
281
|
+
}
|
|
282
|
+
const safe = safeTarPath(destDir, effectivePath);
|
|
283
|
+
if (seen.has(safe.portableKey)) {
|
|
284
|
+
throw new PluginInstallError(`npm tar contains a duplicate path: ${effectivePath}`);
|
|
285
|
+
}
|
|
286
|
+
seen.add(safe.portableKey);
|
|
287
|
+
if (type === "5") {
|
|
288
|
+
if (size !== 0)
|
|
289
|
+
throw new PluginInstallError("npm tar directory has a non-zero payload");
|
|
290
|
+
await mkdir(safe.target, { recursive: true, mode: 0o700 });
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
if (size > MAX_NPM_TAR_FILE_BYTES) {
|
|
294
|
+
throw new PluginInstallError(`npm tar file exceeds ${MAX_NPM_TAR_FILE_BYTES} bytes`);
|
|
295
|
+
}
|
|
296
|
+
materializedBytes += size;
|
|
297
|
+
if (materializedBytes > MAX_NPM_TAR_EXTRACTED_BYTES) {
|
|
298
|
+
throw new PluginInstallError(`npm tar files exceed ${MAX_NPM_TAR_EXTRACTED_BYTES} extracted bytes`);
|
|
299
|
+
}
|
|
300
|
+
await copyFilePayload(input, position, safe.target, size);
|
|
301
|
+
}
|
|
302
|
+
position += padded;
|
|
303
|
+
}
|
|
304
|
+
if (zeroBlocks < 2)
|
|
305
|
+
throw new PluginInstallError("npm tar is missing its end marker");
|
|
306
|
+
while (position < archive.size) {
|
|
307
|
+
const remaining = Math.min(TAR_BLOCK, archive.size - position);
|
|
308
|
+
const trailing = await readExactly(input, position, remaining);
|
|
309
|
+
if (!isZeroBlock(trailing)) {
|
|
310
|
+
throw new PluginInstallError("npm tar has non-zero trailing data");
|
|
311
|
+
}
|
|
312
|
+
position += remaining;
|
|
313
|
+
}
|
|
314
|
+
if (nextPath !== undefined) {
|
|
315
|
+
throw new PluginInstallError("npm tar ends with unapplied path metadata");
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
finally {
|
|
319
|
+
await input.close();
|
|
320
|
+
}
|
|
321
|
+
}
|
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
export type ParsedSource = {
|
|
10
10
|
kind: "local";
|
|
11
11
|
path: string;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "npm";
|
|
14
|
+
packageName: string;
|
|
15
|
+
selector: string;
|
|
16
|
+
selectorKind: "exact" | "tag";
|
|
17
|
+
raw: string;
|
|
18
|
+
inferredName: string;
|
|
12
19
|
} | {
|
|
13
20
|
kind: "remote";
|
|
14
21
|
url: string;
|
|
@@ -20,4 +27,8 @@ export type ParsedSource = {
|
|
|
20
27
|
export interface ParseSourceOptions {
|
|
21
28
|
allowUnsafeTransport?: boolean;
|
|
22
29
|
}
|
|
30
|
+
/** Parse the intentionally small npm Phase-A source grammar. */
|
|
31
|
+
export declare function parseNpmPluginSource(input: string): Extract<ParsedSource, {
|
|
32
|
+
kind: "npm";
|
|
33
|
+
}>;
|
|
23
34
|
export declare function parseSource(input: string, options?: ParseSourceOptions): ParsedSource;
|