@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,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 数字人仓库(catalog):从 git 仓库读取一批数字人定义。
|
|
3
|
+
*
|
|
4
|
+
* 与插件市场并列而非寄生:数字人有自己的一等分发原语(导入/导出 + 本仓库),
|
|
5
|
+
* 不需要先成为插件。仓库布局与 cjhyy/mimi-humans 一致:
|
|
6
|
+
*
|
|
7
|
+
* humans.json —— 目录清单(name/label/description/category/tags)
|
|
8
|
+
* humans/<name>/profile.json —— WorkspaceProfile 定义(含可选 requires)
|
|
9
|
+
*
|
|
10
|
+
* 本模块只做**读取与校验**,克隆/更新由 host 驱动(涉及网络与磁盘写入)。
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { WorkspaceProfileSchema } from "./types.js";
|
|
15
|
+
/** `owner/repo`,与 SKILL_REPO_RE 同源,供仓库地址复用。 */
|
|
16
|
+
export const CATALOG_REPO_RE = /^[A-Za-z0-9][A-Za-z0-9-]{0,38}\/[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
|
|
17
|
+
/** 单个目录段的安全名,挡住 `..`、分隔符与 NUL。 */
|
|
18
|
+
const SAFE_SEGMENT_RE = /^[a-z0-9][a-z0-9_-]{0,63}$/;
|
|
19
|
+
/**
|
|
20
|
+
* `owner/repo` → 一个安全的目录段。小写化保证同一仓库不同大小写写法命中同一份
|
|
21
|
+
* 缓存;斜杠换成 `-` 后仍需通过 SAFE_SEGMENT_RE,杜绝路径逃逸。
|
|
22
|
+
*/
|
|
23
|
+
export function sourceToRepoKey(repo) {
|
|
24
|
+
if (!CATALOG_REPO_RE.test(repo)) {
|
|
25
|
+
throw new Error(`invalid digital-human repo "${repo}" (expected owner/repo)`);
|
|
26
|
+
}
|
|
27
|
+
const key = repo
|
|
28
|
+
.toLowerCase()
|
|
29
|
+
.replace(/\.git$/, "")
|
|
30
|
+
.replace("/", "-");
|
|
31
|
+
if (!SAFE_SEGMENT_RE.test(key)) {
|
|
32
|
+
throw new Error(`digital-human repo "${repo}" does not map to a safe directory name`);
|
|
33
|
+
}
|
|
34
|
+
return key;
|
|
35
|
+
}
|
|
36
|
+
/** 解析 humans.json。缺 humans 数组按空目录处理;JSON 坏了才抛。 */
|
|
37
|
+
export function parseHumansManifest(raw) {
|
|
38
|
+
const value = JSON.parse(raw);
|
|
39
|
+
const rawHumans = Array.isArray(value.humans) ? value.humans : [];
|
|
40
|
+
const humans = [];
|
|
41
|
+
for (const item of rawHumans) {
|
|
42
|
+
if (!item || typeof item !== "object" || Array.isArray(item))
|
|
43
|
+
continue;
|
|
44
|
+
const entry = item;
|
|
45
|
+
if (typeof entry.name !== "string" || !entry.name)
|
|
46
|
+
continue;
|
|
47
|
+
humans.push({
|
|
48
|
+
name: entry.name,
|
|
49
|
+
...(typeof entry.label === "string" ? { label: entry.label } : {}),
|
|
50
|
+
...(typeof entry.description === "string" ? { description: entry.description } : {}),
|
|
51
|
+
...(typeof entry.category === "string" ? { category: entry.category } : {}),
|
|
52
|
+
tags: Array.isArray(entry.tags)
|
|
53
|
+
? entry.tags.filter((t) => typeof t === "string")
|
|
54
|
+
: [],
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const rawTeams = Array.isArray(value.teams) ? value.teams : [];
|
|
58
|
+
const teams = [];
|
|
59
|
+
for (const item of rawTeams) {
|
|
60
|
+
if (!item || typeof item !== "object" || Array.isArray(item))
|
|
61
|
+
continue;
|
|
62
|
+
const entry = item;
|
|
63
|
+
if (typeof entry.id !== "string" || !entry.id)
|
|
64
|
+
continue;
|
|
65
|
+
if (typeof entry.name !== "string" || !entry.name)
|
|
66
|
+
continue;
|
|
67
|
+
const rawMembers = Array.isArray(entry.members) ? entry.members : [];
|
|
68
|
+
const members = rawMembers.filter((m) => typeof m === "string" && m.length > 0);
|
|
69
|
+
if (members.length < 2)
|
|
70
|
+
continue;
|
|
71
|
+
teams.push({
|
|
72
|
+
id: entry.id,
|
|
73
|
+
name: entry.name,
|
|
74
|
+
...(typeof entry.description === "string" ? { description: entry.description } : {}),
|
|
75
|
+
members,
|
|
76
|
+
...(typeof entry.lead === "string" && entry.lead ? { lead: entry.lead } : {}),
|
|
77
|
+
...(typeof entry.playbook === "string" && entry.playbook ? { playbook: entry.playbook } : {}),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
...(typeof value.name === "string" ? { name: value.name } : {}),
|
|
82
|
+
...(typeof value.description === "string" ? { description: value.description } : {}),
|
|
83
|
+
humans,
|
|
84
|
+
teams,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** 读取一个已克隆的数字人仓库目录。 */
|
|
88
|
+
export function readCatalogFromDir(dir, sourceRepo) {
|
|
89
|
+
const manifestPath = join(dir, "humans.json");
|
|
90
|
+
if (!existsSync(manifestPath)) {
|
|
91
|
+
return { entries: [], teams: [], errors: [`${sourceRepo}: humans.json not found`] };
|
|
92
|
+
}
|
|
93
|
+
let manifest;
|
|
94
|
+
try {
|
|
95
|
+
manifest = parseHumansManifest(readFileSync(manifestPath, "utf-8"));
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
return {
|
|
99
|
+
entries: [],
|
|
100
|
+
teams: [],
|
|
101
|
+
errors: [`${sourceRepo}: humans.json is not valid JSON (${describe(error)})`],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const entries = [];
|
|
105
|
+
const errors = [];
|
|
106
|
+
for (const item of manifest.humans) {
|
|
107
|
+
// The manifest is untrusted input from a cloned repo — never join a name
|
|
108
|
+
// that could climb out of the humans/ directory.
|
|
109
|
+
if (!SAFE_SEGMENT_RE.test(item.name)) {
|
|
110
|
+
errors.push(`${sourceRepo}: entry "${item.name}" has an unsafe name`);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const profilePath = join(dir, "humans", item.name, "profile.json");
|
|
114
|
+
try {
|
|
115
|
+
const profile = WorkspaceProfileSchema.parse(JSON.parse(readFileSync(profilePath, "utf-8")));
|
|
116
|
+
entries.push({
|
|
117
|
+
profile,
|
|
118
|
+
sourceRepo,
|
|
119
|
+
...(item.category ? { category: item.category } : {}),
|
|
120
|
+
tags: item.tags ?? [],
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
errors.push(`${sourceRepo}: "${item.name}" is invalid (${describe(error)})`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// A team is only usable if every member ships in this same repo — otherwise
|
|
128
|
+
// summoning it would create Sessions bound to digital humans that do not exist.
|
|
129
|
+
const shipped = new Set(entries.map((entry) => entry.profile.name));
|
|
130
|
+
const teams = [];
|
|
131
|
+
for (const team of manifest.teams) {
|
|
132
|
+
if (!SAFE_SEGMENT_RE.test(team.id)) {
|
|
133
|
+
errors.push(`${sourceRepo}: team "${team.id}" has an unsafe id`);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
const missing = team.members.filter((member) => !shipped.has(member));
|
|
137
|
+
if (missing.length > 0) {
|
|
138
|
+
errors.push(`${sourceRepo}: team "${team.id}" references missing ${missing.join(", ")}`);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (team.lead && !team.members.includes(team.lead)) {
|
|
142
|
+
errors.push(`${sourceRepo}: team "${team.id}" lead is not one of its members`);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
teams.push({ ...team, sourceRepo });
|
|
146
|
+
}
|
|
147
|
+
return { entries, teams, errors };
|
|
148
|
+
}
|
|
149
|
+
function describe(error) {
|
|
150
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
151
|
+
return message.length > 200 ? `${message.slice(0, 200)}…` : message;
|
|
152
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { SKILL_REPO_RE, WORKSPACE_PROFILE_NAME_RE, WorkspaceProfileRequirementsSchema, WorkspaceProfileSchema, type SkillRequirement, type ToolRequirement, type WorkspaceProfile, type WorkspaceProfileInput, type WorkspaceProfileRequirements, } from "./types.js";
|
|
2
|
+
export { CATALOG_REPO_RE, parseHumansManifest, readCatalogFromDir, sourceToRepoKey, type CatalogEntry as DigitalHumanCatalogSourceEntry, type CatalogTeam as DigitalHumanCatalogTeam, type HumansManifestTeam, type CatalogReadResult, type HumansManifest, type HumansManifestEntry, } from "./catalog.js";
|
|
3
|
+
export { addHumanRepo, humanRepoDir, humanReposRoot, listHumanRepoDetails, listHumanRepos, readAllHumanRepoEntries, removeHumanRepo, type HumanRepoListEntry, type RegisteredHumanRepo, } from "./catalog-store.js";
|
|
4
|
+
export { buildSkillInstallArgs, planProfileRequirements, summarizeSkillConflicts, type KnownSkill, type MissingTool, type PlannedSkillInstall, type ProfileRequirementPlan, type SkillConflict, } from "./requirements.js";
|
|
5
|
+
export { deleteWorkspaceProfile, listWorkspaceProfiles, readWorkspaceProfile, saveWorkspaceProfile, workspaceProfileDir, workspaceProfilesRoot, } from "./store.js";
|
|
6
|
+
export { activateWorkspaceProfile, deactivateWorkspaceProfile, profileOverridesFromDefinition, type InstalledCapabilityNames, type WorkspaceProfileSubtree, } from "./activation.js";
|
|
7
|
+
export { resolveActiveWorkspaceProfile, workspaceProfilePresetFor, type ResolveActiveWorkspaceProfileInput, } from "./resolve.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { SKILL_REPO_RE, WORKSPACE_PROFILE_NAME_RE, WorkspaceProfileRequirementsSchema, WorkspaceProfileSchema, } from "./types.js";
|
|
2
|
+
export { CATALOG_REPO_RE, parseHumansManifest, readCatalogFromDir, sourceToRepoKey, } from "./catalog.js";
|
|
3
|
+
export { addHumanRepo, humanRepoDir, humanReposRoot, listHumanRepoDetails, listHumanRepos, readAllHumanRepoEntries, removeHumanRepo, } from "./catalog-store.js";
|
|
4
|
+
export { buildSkillInstallArgs, planProfileRequirements, summarizeSkillConflicts, } from "./requirements.js";
|
|
5
|
+
export { deleteWorkspaceProfile, listWorkspaceProfiles, readWorkspaceProfile, saveWorkspaceProfile, workspaceProfileDir, workspaceProfilesRoot, } from "./store.js";
|
|
6
|
+
export { activateWorkspaceProfile, deactivateWorkspaceProfile, profileOverridesFromDefinition, } from "./activation.js";
|
|
7
|
+
export { resolveActiveWorkspaceProfile, workspaceProfilePresetFor, } from "./resolve.js";
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 数字人依赖:把 profile.requires 解析成「将要发生什么」的计划,供 UI 先展示、
|
|
3
|
+
* 用户确认后再执行。
|
|
4
|
+
*
|
|
5
|
+
* 为什么需要这一层:plugins/skills/mcp/agents 四个字段只是 force-enable 开关,
|
|
6
|
+
* 只能打开磁盘上已存在的能力。没有获取步骤,一个声明了 skill 的数字人在新机器上
|
|
7
|
+
* 会静默变成空壳(能力名写着,实际什么都没启用)。
|
|
8
|
+
*
|
|
9
|
+
* 安全边界:安装会克隆远程仓库并执行 `npx skills add`,属于运行远程代码。本模块
|
|
10
|
+
* 只负责**计划与校验**,从不自行执行;执行由 host 在拿到用户确认后驱动
|
|
11
|
+
* ({@link buildSkillInstallArgs} 给出确切 argv)。
|
|
12
|
+
*/
|
|
13
|
+
import type { SkillRequirement, WorkspaceProfileRequirements } from "./types.js";
|
|
14
|
+
/** scanner 已发现的一条 skill(`plugin:skill` 形式代表插件来源)。 */
|
|
15
|
+
export interface KnownSkill {
|
|
16
|
+
name: string;
|
|
17
|
+
source: "project" | "user" | "plugin" | "panel-app";
|
|
18
|
+
}
|
|
19
|
+
export interface SkillConflict {
|
|
20
|
+
name: string;
|
|
21
|
+
/** 已占用该名字的来源。安装到 project 根后它会被遮蔽。 */
|
|
22
|
+
existingSource: KnownSkill["source"];
|
|
23
|
+
}
|
|
24
|
+
export interface PlannedSkillInstall {
|
|
25
|
+
requirement: SkillRequirement;
|
|
26
|
+
/** 具名子集里确实缺失的那些;整仓安装(--all)时为 undefined。 */
|
|
27
|
+
missing?: string[];
|
|
28
|
+
}
|
|
29
|
+
export type MissingToolReason = "not-found" | "too-old";
|
|
30
|
+
export interface MissingTool {
|
|
31
|
+
bin: string;
|
|
32
|
+
reason: MissingToolReason;
|
|
33
|
+
/** reason=too-old 时实际探到的版本。 */
|
|
34
|
+
found?: string;
|
|
35
|
+
/** reason=too-old 时 profile 要求的版本。 */
|
|
36
|
+
required?: string;
|
|
37
|
+
hint?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface ProfileRequirementPlan {
|
|
40
|
+
skillInstalls: PlannedSkillInstall[];
|
|
41
|
+
missingTools: MissingTool[];
|
|
42
|
+
conflicts: SkillConflict[];
|
|
43
|
+
/** 是否有需要用户确认后执行的安装动作。 */
|
|
44
|
+
needsInstall: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface PlanRequirementsContext {
|
|
47
|
+
/** 当前 scanner 能看到的全部 skill。 */
|
|
48
|
+
installedSkills: readonly KnownSkill[];
|
|
49
|
+
/** 探测一个外部命令的版本输出;不存在返回 null。 */
|
|
50
|
+
toolProbe: (bin: string) => string | null;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 组装 `npx skills add` 的 argv。
|
|
54
|
+
*
|
|
55
|
+
* 两条硬约束:
|
|
56
|
+
* 1. **绝不加 `-g`** —— 全局安装落在 `~/.claude/skills`,而 scanner 只读
|
|
57
|
+
* `<cwd>/.code-shell/skills`、`<cwd>/.agents/skills`、`~/.code-shell/skills`
|
|
58
|
+
* 三个根。装了却扫不到,就是又一个"配了等于没配"。
|
|
59
|
+
* 2. repo 与 skill 名各自占独立 argv 槽,不拼 shell 字符串;配合 schema 的
|
|
60
|
+
* `SKILL_REPO_RE` 挡住 `--flag` / `../` / `;rm -rf` 一类注入。
|
|
61
|
+
*/
|
|
62
|
+
export declare function buildSkillInstallArgs(requirement: SkillRequirement): string[];
|
|
63
|
+
/** 从 `--version` 输出里取第一个点分版本号。 */
|
|
64
|
+
export declare function parseToolVersion(output: string): string | undefined;
|
|
65
|
+
/** 按数字段比较;返回 <0 / 0 / >0。缺省段视为 0,故 "22" == "22.0.0"。 */
|
|
66
|
+
export declare function compareToolVersions(a: string, b: string): number;
|
|
67
|
+
/**
|
|
68
|
+
* 找出即将安装的裸名与已有 skill 的撞名。
|
|
69
|
+
*
|
|
70
|
+
* scanner 的去重是「先到先得且静默」——同名后来者直接被丢弃,不告警。所以要在
|
|
71
|
+
* 安装前把遮蔽关系摊开给用户看。插件 skill 带 `plugin:` 命名空间、走独立 dedup
|
|
72
|
+
* 集合,永远不会与裸名互相覆盖,故排除。
|
|
73
|
+
*/
|
|
74
|
+
export declare function summarizeSkillConflicts(incoming: readonly string[], installed: readonly KnownSkill[]): SkillConflict[];
|
|
75
|
+
/** 纯函数:不碰磁盘、不起进程,全部输入经 context 注入,便于测试。 */
|
|
76
|
+
export declare function planProfileRequirements(requires: WorkspaceProfileRequirements | undefined, context: PlanRequirementsContext): ProfileRequirementPlan;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 组装 `npx skills add` 的 argv。
|
|
3
|
+
*
|
|
4
|
+
* 两条硬约束:
|
|
5
|
+
* 1. **绝不加 `-g`** —— 全局安装落在 `~/.claude/skills`,而 scanner 只读
|
|
6
|
+
* `<cwd>/.code-shell/skills`、`<cwd>/.agents/skills`、`~/.code-shell/skills`
|
|
7
|
+
* 三个根。装了却扫不到,就是又一个"配了等于没配"。
|
|
8
|
+
* 2. repo 与 skill 名各自占独立 argv 槽,不拼 shell 字符串;配合 schema 的
|
|
9
|
+
* `SKILL_REPO_RE` 挡住 `--flag` / `../` / `;rm -rf` 一类注入。
|
|
10
|
+
*/
|
|
11
|
+
export function buildSkillInstallArgs(requirement) {
|
|
12
|
+
const args = ["skills", "add", requirement.repo];
|
|
13
|
+
if (requirement.skills && requirement.skills.length > 0) {
|
|
14
|
+
// 具名子集:只装需要的,避免把整个仓库几十个 skill 都拖进项目。
|
|
15
|
+
args.push("--skill", requirement.skills.join(","), "--agent", "*", "--yes");
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
// --all === --skill '*' --agent '*' -y
|
|
19
|
+
args.push("--all");
|
|
20
|
+
}
|
|
21
|
+
if (requirement.fullDepth)
|
|
22
|
+
args.push("--full-depth");
|
|
23
|
+
return args;
|
|
24
|
+
}
|
|
25
|
+
/** 从 `--version` 输出里取第一个点分版本号。 */
|
|
26
|
+
export function parseToolVersion(output) {
|
|
27
|
+
const match = /(\d+(?:\.\d+){0,2})/.exec(output);
|
|
28
|
+
return match?.[1];
|
|
29
|
+
}
|
|
30
|
+
/** 按数字段比较;返回 <0 / 0 / >0。缺省段视为 0,故 "22" == "22.0.0"。 */
|
|
31
|
+
export function compareToolVersions(a, b) {
|
|
32
|
+
const pa = a.split(".").map(Number);
|
|
33
|
+
const pb = b.split(".").map(Number);
|
|
34
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
35
|
+
const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
36
|
+
if (diff !== 0)
|
|
37
|
+
return diff;
|
|
38
|
+
}
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 找出即将安装的裸名与已有 skill 的撞名。
|
|
43
|
+
*
|
|
44
|
+
* scanner 的去重是「先到先得且静默」——同名后来者直接被丢弃,不告警。所以要在
|
|
45
|
+
* 安装前把遮蔽关系摊开给用户看。插件 skill 带 `plugin:` 命名空间、走独立 dedup
|
|
46
|
+
* 集合,永远不会与裸名互相覆盖,故排除。
|
|
47
|
+
*/
|
|
48
|
+
export function summarizeSkillConflicts(incoming, installed) {
|
|
49
|
+
const conflicts = [];
|
|
50
|
+
for (const name of incoming) {
|
|
51
|
+
const hit = installed.find((s) => s.source !== "plugin" && s.name === name);
|
|
52
|
+
if (hit)
|
|
53
|
+
conflicts.push({ name, existingSource: hit.source });
|
|
54
|
+
}
|
|
55
|
+
return conflicts;
|
|
56
|
+
}
|
|
57
|
+
/** 纯函数:不碰磁盘、不起进程,全部输入经 context 注入,便于测试。 */
|
|
58
|
+
export function planProfileRequirements(requires, context) {
|
|
59
|
+
const skillInstalls = [];
|
|
60
|
+
const conflicts = [];
|
|
61
|
+
const missingTools = [];
|
|
62
|
+
for (const requirement of requires?.skills ?? []) {
|
|
63
|
+
if (requirement.skills && requirement.skills.length > 0) {
|
|
64
|
+
// 只有落在 project 根(安装目标)的同名 skill 才算"已具备";命中更低优先级的
|
|
65
|
+
// user 根不算——那份会被这次安装遮蔽,属于要提示的冲突而非可跳过的满足。
|
|
66
|
+
const satisfied = (name) => context.installedSkills.some((s) => s.name === name && s.source === "project");
|
|
67
|
+
const missing = requirement.skills.filter((name) => !satisfied(name));
|
|
68
|
+
const shadowed = summarizeSkillConflicts(requirement.skills.filter((name) => !satisfied(name)), context.installedSkills);
|
|
69
|
+
conflicts.push(...shadowed);
|
|
70
|
+
// 具名子集全在了就不必再跑安装。
|
|
71
|
+
if (missing.length === 0)
|
|
72
|
+
continue;
|
|
73
|
+
// Keep the reviewed command and the executed argv aligned: if part of a
|
|
74
|
+
// multi-Skill requirement is already present, only pass the genuinely
|
|
75
|
+
// missing names to the installer. Re-sending the full authored subset
|
|
76
|
+
// could unnecessarily replace a working project Skill while the UI said
|
|
77
|
+
// it was only going to install the missing one.
|
|
78
|
+
skillInstalls.push({
|
|
79
|
+
requirement: { ...requirement, skills: missing },
|
|
80
|
+
missing,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
// 整仓安装无法预判会带来哪些名字,只能照跑;`skills add` 自身是幂等的。
|
|
85
|
+
skillInstalls.push({ requirement });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
for (const tool of requires?.tools ?? []) {
|
|
89
|
+
const output = context.toolProbe(tool.bin);
|
|
90
|
+
if (output === null) {
|
|
91
|
+
missingTools.push({
|
|
92
|
+
bin: tool.bin,
|
|
93
|
+
reason: "not-found",
|
|
94
|
+
...(tool.hint ? { hint: tool.hint } : {}),
|
|
95
|
+
});
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (!tool.minVersion)
|
|
99
|
+
continue;
|
|
100
|
+
const found = parseToolVersion(output);
|
|
101
|
+
if (found && compareToolVersions(found, tool.minVersion) < 0) {
|
|
102
|
+
missingTools.push({
|
|
103
|
+
bin: tool.bin,
|
|
104
|
+
reason: "too-old",
|
|
105
|
+
found,
|
|
106
|
+
required: tool.minVersion,
|
|
107
|
+
...(tool.hint ? { hint: tool.hint } : {}),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
skillInstalls,
|
|
113
|
+
missingTools,
|
|
114
|
+
conflicts,
|
|
115
|
+
needsInstall: skillInstalls.length > 0,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SettingsManager } from "../settings/manager.js";
|
|
2
|
+
import type { WorkspaceProfile } from "./types.js";
|
|
3
|
+
export interface ResolveActiveWorkspaceProfileInput {
|
|
4
|
+
/** Session-bound digital-human profile; wins over the project default. */
|
|
5
|
+
sessionProfile?: string;
|
|
6
|
+
cwd: string;
|
|
7
|
+
settings: SettingsManager;
|
|
8
|
+
}
|
|
9
|
+
export declare function resolveActiveWorkspaceProfile(input: ResolveActiveWorkspaceProfileInput): WorkspaceProfile | undefined;
|
|
10
|
+
/** preset 解析用的快照读取(优先级:agent.preset > 本值 > capability 默认)。 */
|
|
11
|
+
export declare function workspaceProfilePresetFor(settings: SettingsManager, cwd: string): string | undefined;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* “当前激活的是谁 + 它的活字段”的唯一入口。除 overrides 折叠
|
|
3
|
+
* (读 settings 持久化快照,见 overlay.ts)之外,任何代码不得自行读
|
|
4
|
+
* profile.active 拼路径。Session 绑定的 profile 显式优先于项目默认,
|
|
5
|
+
* 让同一项目内的 PM / UI / 工程 Session 可以各自持有稳定数字人身份。
|
|
6
|
+
*/
|
|
7
|
+
import { logger } from "../logging/logger.js";
|
|
8
|
+
import { readWorkspaceProfile } from "./store.js";
|
|
9
|
+
function readSubtree(settings, cwd) {
|
|
10
|
+
try {
|
|
11
|
+
return settings.getForScope("project", cwd).profile;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function resolveActiveWorkspaceProfile(input) {
|
|
18
|
+
const name = input.sessionProfile ?? readSubtree(input.settings, input.cwd)?.active;
|
|
19
|
+
if (!name)
|
|
20
|
+
return undefined;
|
|
21
|
+
let workspaceProfile;
|
|
22
|
+
try {
|
|
23
|
+
workspaceProfile = readWorkspaceProfile(name);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
logger.warn("profile.active_invalid", {
|
|
27
|
+
cat: "profile",
|
|
28
|
+
name,
|
|
29
|
+
error: error instanceof Error ? error.message : String(error),
|
|
30
|
+
});
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
if (!workspaceProfile) {
|
|
34
|
+
logger.warn("profile.active_missing_from_library", { cat: "profile", name });
|
|
35
|
+
}
|
|
36
|
+
return workspaceProfile;
|
|
37
|
+
}
|
|
38
|
+
/** preset 解析用的快照读取(优先级:agent.preset > 本值 > capability 默认)。 */
|
|
39
|
+
export function workspaceProfilePresetFor(settings, cwd) {
|
|
40
|
+
return readSubtree(settings, cwd)?.preset;
|
|
41
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type WorkspaceProfile, type WorkspaceProfileInput } from "./types.js";
|
|
2
|
+
export declare function workspaceProfilesRoot(): string;
|
|
3
|
+
/** 该数字人的根目录 —— 同时也是它可移植记忆层的 MemoryManager baseDir。 */
|
|
4
|
+
export declare function workspaceProfileDir(name: string): string;
|
|
5
|
+
export declare function readWorkspaceProfile(name: string): WorkspaceProfile | undefined;
|
|
6
|
+
export declare function listWorkspaceProfiles(): WorkspaceProfile[];
|
|
7
|
+
/**
|
|
8
|
+
* 原子写(tmp+rename),与 SettingsManager 的写法一致。
|
|
9
|
+
*
|
|
10
|
+
* 接收 `WorkspaceProfileInput`(而不是解析后的 `WorkspaceProfile`):这个函数
|
|
11
|
+
* 本来就会 `parse()`,所以带 default 的字段由 schema 负责填。用输出类型标注会
|
|
12
|
+
* 让调用方必须手写它们,也会在 schema 新增带 default 的字段时把所有调用方一起
|
|
13
|
+
* 弄红——尽管运行时完全没变。
|
|
14
|
+
*/
|
|
15
|
+
export declare function saveWorkspaceProfile(profile: WorkspaceProfileInput): void;
|
|
16
|
+
/** 删除前再次执行目录 containment 校验;不会跟随 profile 目录 symlink。 */
|
|
17
|
+
export declare function deleteWorkspaceProfile(name: string): boolean;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 全局数字人库:~/.code-shell/profiles/<name>/profile.json。
|
|
3
|
+
* 路径一律经 codeShellHome() 解析(CODE_SHELL_HOME / identity dataRoot 生效)。
|
|
4
|
+
* core 不内置任何领域 profile;样例见 docs/examples/workspace-profile-sample.md。
|
|
5
|
+
*/
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
7
|
+
import { lstatSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync, } from "node:fs";
|
|
8
|
+
import { isAbsolute, join, relative, sep } from "node:path";
|
|
9
|
+
import { logger } from "../logging/logger.js";
|
|
10
|
+
import { codeShellHome } from "../session/session-manager.js";
|
|
11
|
+
import { WORKSPACE_PROFILE_NAME_RE, WorkspaceProfileSchema, } from "./types.js";
|
|
12
|
+
export function workspaceProfilesRoot() {
|
|
13
|
+
return join(codeShellHome(), "profiles");
|
|
14
|
+
}
|
|
15
|
+
/** 该数字人的根目录 —— 同时也是它可移植记忆层的 MemoryManager baseDir。 */
|
|
16
|
+
export function workspaceProfileDir(name) {
|
|
17
|
+
return join(workspaceProfilesRoot(), name);
|
|
18
|
+
}
|
|
19
|
+
function isContained(root, target) {
|
|
20
|
+
const rel = relative(root, target);
|
|
21
|
+
return rel === "" || (!rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute(rel));
|
|
22
|
+
}
|
|
23
|
+
function lstatIfPresent(path) {
|
|
24
|
+
try {
|
|
25
|
+
return lstatSync(path);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
if (error.code === "ENOENT")
|
|
29
|
+
return undefined;
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function checkedProfilesRoot(create = false) {
|
|
34
|
+
const root = workspaceProfilesRoot();
|
|
35
|
+
let info = lstatIfPresent(root);
|
|
36
|
+
if (!info && create) {
|
|
37
|
+
mkdirSync(root, { recursive: true, mode: 0o700 });
|
|
38
|
+
info = lstatSync(root);
|
|
39
|
+
}
|
|
40
|
+
if (!info)
|
|
41
|
+
return undefined;
|
|
42
|
+
if (info.isSymbolicLink() || !info.isDirectory()) {
|
|
43
|
+
throw new Error(`Invalid workspace profiles root: ${root}`);
|
|
44
|
+
}
|
|
45
|
+
return root;
|
|
46
|
+
}
|
|
47
|
+
function checkedProfileDirectory(name, create = false) {
|
|
48
|
+
const root = checkedProfilesRoot(create);
|
|
49
|
+
if (!root)
|
|
50
|
+
return undefined;
|
|
51
|
+
const dir = join(root, name);
|
|
52
|
+
let info = lstatIfPresent(dir);
|
|
53
|
+
if (!info && create) {
|
|
54
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
55
|
+
info = lstatSync(dir);
|
|
56
|
+
}
|
|
57
|
+
if (!info)
|
|
58
|
+
return undefined;
|
|
59
|
+
if (info.isSymbolicLink() || !info.isDirectory()) {
|
|
60
|
+
throw new Error(`Invalid workspace profile directory: ${dir}`);
|
|
61
|
+
}
|
|
62
|
+
if (!isContained(realpathSync(root), realpathSync(dir))) {
|
|
63
|
+
throw new Error(`Workspace profile directory escapes the profiles root: ${dir}`);
|
|
64
|
+
}
|
|
65
|
+
return dir;
|
|
66
|
+
}
|
|
67
|
+
function checkedProfileFile(name) {
|
|
68
|
+
const dir = checkedProfileDirectory(name);
|
|
69
|
+
if (!dir)
|
|
70
|
+
return undefined;
|
|
71
|
+
const path = join(dir, "profile.json");
|
|
72
|
+
const info = lstatIfPresent(path);
|
|
73
|
+
if (!info)
|
|
74
|
+
return undefined;
|
|
75
|
+
if (info.isSymbolicLink() || !info.isFile()) {
|
|
76
|
+
throw new Error(`Invalid workspace profile file: ${path}`);
|
|
77
|
+
}
|
|
78
|
+
return path;
|
|
79
|
+
}
|
|
80
|
+
export function readWorkspaceProfile(name) {
|
|
81
|
+
if (!WORKSPACE_PROFILE_NAME_RE.test(name))
|
|
82
|
+
return undefined;
|
|
83
|
+
const path = join(workspaceProfileDir(name), "profile.json");
|
|
84
|
+
try {
|
|
85
|
+
const checkedPath = checkedProfileFile(name);
|
|
86
|
+
if (!checkedPath)
|
|
87
|
+
return undefined;
|
|
88
|
+
return WorkspaceProfileSchema.parse(JSON.parse(readFileSync(checkedPath, "utf-8")));
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
throw new Error(`Invalid workspace profile "${name}" at ${path}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export function listWorkspaceProfiles() {
|
|
95
|
+
const root = checkedProfilesRoot();
|
|
96
|
+
if (!root)
|
|
97
|
+
return [];
|
|
98
|
+
const out = [];
|
|
99
|
+
for (const entry of readdirSync(root, { withFileTypes: true })) {
|
|
100
|
+
if (!entry.isDirectory()) {
|
|
101
|
+
if (entry.isSymbolicLink()) {
|
|
102
|
+
logger.warn("profile.library_entry_invalid", {
|
|
103
|
+
cat: "profile",
|
|
104
|
+
name: entry.name,
|
|
105
|
+
error: "symbolic links are not allowed",
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
const profile = readWorkspaceProfile(entry.name);
|
|
112
|
+
if (profile)
|
|
113
|
+
out.push(profile);
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
logger.warn("profile.library_entry_invalid", {
|
|
117
|
+
cat: "profile",
|
|
118
|
+
name: entry.name,
|
|
119
|
+
error: error instanceof Error ? error.message : String(error),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return out.sort((a, b) => a.name.localeCompare(b.name));
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* 原子写(tmp+rename),与 SettingsManager 的写法一致。
|
|
127
|
+
*
|
|
128
|
+
* 接收 `WorkspaceProfileInput`(而不是解析后的 `WorkspaceProfile`):这个函数
|
|
129
|
+
* 本来就会 `parse()`,所以带 default 的字段由 schema 负责填。用输出类型标注会
|
|
130
|
+
* 让调用方必须手写它们,也会在 schema 新增带 default 的字段时把所有调用方一起
|
|
131
|
+
* 弄红——尽管运行时完全没变。
|
|
132
|
+
*/
|
|
133
|
+
export function saveWorkspaceProfile(profile) {
|
|
134
|
+
const parsed = WorkspaceProfileSchema.parse(profile);
|
|
135
|
+
const dir = checkedProfileDirectory(parsed.name, true);
|
|
136
|
+
if (!dir)
|
|
137
|
+
throw new Error(`Could not create workspace profile directory for "${parsed.name}"`);
|
|
138
|
+
const path = join(dir, "profile.json");
|
|
139
|
+
const existing = lstatIfPresent(path);
|
|
140
|
+
if (existing) {
|
|
141
|
+
if (existing.isSymbolicLink() || !existing.isFile()) {
|
|
142
|
+
throw new Error(`Invalid workspace profile file: ${path}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const tmp = `${path}.${process.pid}.${randomUUID()}.tmp`;
|
|
146
|
+
try {
|
|
147
|
+
writeFileSync(tmp, `${JSON.stringify(parsed, null, 2)}\n`, {
|
|
148
|
+
encoding: "utf-8",
|
|
149
|
+
mode: 0o600,
|
|
150
|
+
flag: "wx",
|
|
151
|
+
});
|
|
152
|
+
renameSync(tmp, path);
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
rmSync(tmp, { force: true });
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/** 删除前再次执行目录 containment 校验;不会跟随 profile 目录 symlink。 */
|
|
159
|
+
export function deleteWorkspaceProfile(name) {
|
|
160
|
+
if (!WORKSPACE_PROFILE_NAME_RE.test(name))
|
|
161
|
+
return false;
|
|
162
|
+
const dir = checkedProfileDirectory(name);
|
|
163
|
+
if (!dir)
|
|
164
|
+
return false;
|
|
165
|
+
rmSync(dir, { recursive: true, force: true });
|
|
166
|
+
return true;
|
|
167
|
+
}
|