@lesliechan721/aw 0.1.0-beta.3
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/dist/authoring/assets/aw-config.d.mts +2 -0
- package/dist/authoring/assets/aw-config.mjs +556 -0
- package/dist/authoring/assets/aw-config.mjs.map +1 -0
- package/dist/authoring/scripts/add-skill.d.mts +2 -0
- package/dist/authoring/scripts/add-skill.mjs +355 -0
- package/dist/authoring/scripts/add-skill.mjs.map +1 -0
- package/dist/authoring/scripts/check-plugin-versions.d.mts +2 -0
- package/dist/authoring/scripts/check-plugin-versions.mjs +5 -0
- package/dist/authoring/scripts/check-plugin-versions.mjs.map +1 -0
- package/dist/authoring/scripts/init-plugin.d.mts +2 -0
- package/dist/authoring/scripts/init-plugin.mjs +512 -0
- package/dist/authoring/scripts/init-plugin.mjs.map +1 -0
- package/dist/authoring/scripts/lib/javascript-import-scanner.d.mts +4 -0
- package/dist/authoring/scripts/lib/javascript-import-scanner.mjs +261 -0
- package/dist/authoring/scripts/lib/javascript-import-scanner.mjs.map +1 -0
- package/dist/authoring/scripts/lib/plugin-root.d.mts +26 -0
- package/dist/authoring/scripts/lib/plugin-root.mjs +125 -0
- package/dist/authoring/scripts/lib/plugin-root.mjs.map +1 -0
- package/dist/authoring/scripts/lib/plugin-version-check.d.mts +55 -0
- package/dist/authoring/scripts/lib/plugin-version-check.mjs +777 -0
- package/dist/authoring/scripts/lib/plugin-version-check.mjs.map +1 -0
- package/dist/authoring/scripts/lib/semver.d.mts +9 -0
- package/dist/authoring/scripts/lib/semver.mjs +63 -0
- package/dist/authoring/scripts/lib/semver.mjs.map +1 -0
- package/dist/authoring/scripts/lib/skill-scaffold.d.mts +124 -0
- package/dist/authoring/scripts/lib/skill-scaffold.mjs +374 -0
- package/dist/authoring/scripts/lib/skill-scaffold.mjs.map +1 -0
- package/dist/authoring/scripts/plugin-status.d.mts +2 -0
- package/dist/authoring/scripts/plugin-status.mjs +96 -0
- package/dist/authoring/scripts/plugin-status.mjs.map +1 -0
- package/dist/authoring/scripts/validate-plugin.d.mts +2 -0
- package/dist/authoring/scripts/validate-plugin.mjs +4442 -0
- package/dist/authoring/scripts/validate-plugin.mjs.map +1 -0
- package/dist/authoring/scripts/validate-skill.d.mts +2 -0
- package/dist/authoring/scripts/validate-skill.mjs +126 -0
- package/dist/authoring/scripts/validate-skill.mjs.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/scripts/aw-skill-eval-engine.d.ts +13 -0
- package/dist/scripts/aw-skill-eval-engine.js +31 -0
- package/dist/scripts/aw-skill-eval-engine.js.map +1 -0
- package/dist/scripts/bundle-plugins.d.ts +18 -0
- package/dist/scripts/bundle-plugins.js +123 -0
- package/dist/scripts/bundle-plugins.js.map +1 -0
- package/dist/scripts/codex-eval-app-server.d.ts +89 -0
- package/dist/scripts/codex-eval-app-server.js +1228 -0
- package/dist/scripts/codex-eval-app-server.js.map +1 -0
- package/dist/scripts/codex-eval-isolation.d.ts +61 -0
- package/dist/scripts/codex-eval-isolation.js +318 -0
- package/dist/scripts/codex-eval-isolation.js.map +1 -0
- package/dist/scripts/codex-eval-process-management.d.ts +8 -0
- package/dist/scripts/codex-eval-process-management.js +69 -0
- package/dist/scripts/codex-eval-process-management.js.map +1 -0
- package/dist/scripts/codex-eval-process-tree.d.ts +38 -0
- package/dist/scripts/codex-eval-process-tree.js +803 -0
- package/dist/scripts/codex-eval-process-tree.js.map +1 -0
- package/dist/scripts/codex-eval-runtime-config.d.ts +62 -0
- package/dist/scripts/codex-eval-runtime-config.js +843 -0
- package/dist/scripts/codex-eval-runtime-config.js.map +1 -0
- package/dist/scripts/codex-trigger-eval.d.ts +84 -0
- package/dist/scripts/codex-trigger-eval.js +968 -0
- package/dist/scripts/codex-trigger-eval.js.map +1 -0
- package/dist/scripts/eval-plugin-skills-audited.d.ts +6 -0
- package/dist/scripts/eval-plugin-skills-audited.js +261 -0
- package/dist/scripts/eval-plugin-skills-audited.js.map +1 -0
- package/dist/scripts/eval-plugin-skills.d.ts +45 -0
- package/dist/scripts/eval-plugin-skills.js +1586 -0
- package/dist/scripts/eval-plugin-skills.js.map +1 -0
- package/dist/scripts/eval-run-layout.d.ts +17 -0
- package/dist/scripts/eval-run-layout.js +26 -0
- package/dist/scripts/eval-run-layout.js.map +1 -0
- package/dist/scripts/plugin-eval-contract.d.ts +185 -0
- package/dist/scripts/plugin-eval-contract.js +695 -0
- package/dist/scripts/plugin-eval-contract.js.map +1 -0
- package/dist/scripts/plugin-eval-materializer.d.ts +13 -0
- package/dist/scripts/plugin-eval-materializer.js +421 -0
- package/dist/scripts/plugin-eval-materializer.js.map +1 -0
- package/dist/scripts/plugin-staging.d.ts +43 -0
- package/dist/scripts/plugin-staging.js +196 -0
- package/dist/scripts/plugin-staging.js.map +1 -0
- package/dist/scripts/skill-reporting.d.ts +212 -0
- package/dist/scripts/skill-reporting.js +922 -0
- package/dist/scripts/skill-reporting.js.map +1 -0
- package/dist/scripts/test-plugin-scripts.d.ts +7 -0
- package/dist/scripts/test-plugin-scripts.js +674 -0
- package/dist/scripts/test-plugin-scripts.js.map +1 -0
- package/dist/src/adapters/helpers.d.ts +44 -0
- package/dist/src/adapters/helpers.js +95 -0
- package/dist/src/adapters/helpers.js.map +1 -0
- package/dist/src/authoring/workspace-commands.d.ts +46 -0
- package/dist/src/authoring/workspace-commands.js +133 -0
- package/dist/src/authoring/workspace-commands.js.map +1 -0
- package/dist/src/commands/catalog-publish.d.ts +33 -0
- package/dist/src/commands/catalog-publish.js +374 -0
- package/dist/src/commands/catalog-publish.js.map +1 -0
- package/dist/src/commands/catalog-source.d.ts +111 -0
- package/dist/src/commands/catalog-source.js +266 -0
- package/dist/src/commands/catalog-source.js.map +1 -0
- package/dist/src/commands/console.d.ts +3 -0
- package/dist/src/commands/console.js +44 -0
- package/dist/src/commands/console.js.map +1 -0
- package/dist/src/commands/dependency-operation-plan.d.ts +28 -0
- package/dist/src/commands/dependency-operation-plan.js +15 -0
- package/dist/src/commands/dependency-operation-plan.js.map +1 -0
- package/dist/src/commands/init.d.ts +31 -0
- package/dist/src/commands/init.js +63 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/options.d.ts +68 -0
- package/dist/src/commands/options.js +146 -0
- package/dist/src/commands/options.js.map +1 -0
- package/dist/src/commands/rebuild-command.d.ts +77 -0
- package/dist/src/commands/rebuild-command.js +1681 -0
- package/dist/src/commands/rebuild-command.js.map +1 -0
- package/dist/src/commands/rebuild-integration.d.ts +94 -0
- package/dist/src/commands/rebuild-integration.js +3289 -0
- package/dist/src/commands/rebuild-integration.js.map +1 -0
- package/dist/src/commands/rebuild-operations.d.ts +110 -0
- package/dist/src/commands/rebuild-operations.js +791 -0
- package/dist/src/commands/rebuild-operations.js.map +1 -0
- package/dist/src/commands/review-publication.d.ts +99 -0
- package/dist/src/commands/review-publication.js +904 -0
- package/dist/src/commands/review-publication.js.map +1 -0
- package/dist/src/commands/runtime.d.ts +176 -0
- package/dist/src/commands/runtime.js +746 -0
- package/dist/src/commands/runtime.js.map +1 -0
- package/dist/src/commands/status-v4.d.ts +102 -0
- package/dist/src/commands/status-v4.js +844 -0
- package/dist/src/commands/status-v4.js.map +1 -0
- package/dist/src/commands/status.d.ts +93 -0
- package/dist/src/commands/status.js +442 -0
- package/dist/src/commands/status.js.map +1 -0
- package/dist/src/commands/wizard.d.ts +57 -0
- package/dist/src/commands/wizard.js +58 -0
- package/dist/src/commands/wizard.js.map +1 -0
- package/dist/src/commands/write-commands.d.ts +7 -0
- package/dist/src/commands/write-commands.js +167 -0
- package/dist/src/commands/write-commands.js.map +1 -0
- package/dist/src/constants.d.ts +25 -0
- package/dist/src/constants.js +26 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/generators/agents.d.ts +3 -0
- package/dist/src/generators/agents.js +46 -0
- package/dist/src/generators/agents.js.map +1 -0
- package/dist/src/generators/hooks.d.ts +15 -0
- package/dist/src/generators/hooks.js +76 -0
- package/dist/src/generators/hooks.js.map +1 -0
- package/dist/src/generators/instructions.d.ts +13 -0
- package/dist/src/generators/instructions.js +66 -0
- package/dist/src/generators/instructions.js.map +1 -0
- package/dist/src/generators/local-plugin.d.ts +53 -0
- package/dist/src/generators/local-plugin.js +1268 -0
- package/dist/src/generators/local-plugin.js.map +1 -0
- package/dist/src/generators/permissions.d.ts +10 -0
- package/dist/src/generators/permissions.js +37 -0
- package/dist/src/generators/permissions.js.map +1 -0
- package/dist/src/generators/shared.d.ts +2 -0
- package/dist/src/generators/shared.js +15 -0
- package/dist/src/generators/shared.js.map +1 -0
- package/dist/src/index.d.ts +35 -0
- package/dist/src/index.js +2344 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/output/command-receipt.d.ts +90 -0
- package/dist/src/output/command-receipt.js +129 -0
- package/dist/src/output/command-receipt.js.map +1 -0
- package/dist/src/output/debug-log.d.ts +4 -0
- package/dist/src/output/debug-log.js +97 -0
- package/dist/src/output/debug-log.js.map +1 -0
- package/dist/src/output/equivalent-command.d.ts +9 -0
- package/dist/src/output/equivalent-command.js +39 -0
- package/dist/src/output/equivalent-command.js.map +1 -0
- package/dist/src/output/model.d.ts +117 -0
- package/dist/src/output/model.js +145 -0
- package/dist/src/output/model.js.map +1 -0
- package/dist/src/output/rebuild-progress.d.ts +21 -0
- package/dist/src/output/rebuild-progress.js +138 -0
- package/dist/src/output/rebuild-progress.js.map +1 -0
- package/dist/src/output/redact.d.ts +3 -0
- package/dist/src/output/redact.js +39 -0
- package/dist/src/output/redact.js.map +1 -0
- package/dist/src/output/reporter.d.ts +9 -0
- package/dist/src/output/reporter.js +133 -0
- package/dist/src/output/reporter.js.map +1 -0
- package/dist/src/portable/commands.d.ts +120 -0
- package/dist/src/portable/commands.js +506 -0
- package/dist/src/portable/commands.js.map +1 -0
- package/dist/src/portable/materializer.d.ts +50 -0
- package/dist/src/portable/materializer.js +408 -0
- package/dist/src/portable/materializer.js.map +1 -0
- package/dist/src/portable/skills-cli.d.ts +43 -0
- package/dist/src/portable/skills-cli.js +148 -0
- package/dist/src/portable/skills-cli.js.map +1 -0
- package/dist/src/tui/components.d.ts +32 -0
- package/dist/src/tui/components.js +42 -0
- package/dist/src/tui/components.js.map +1 -0
- package/dist/src/tui/console-app-v4.d.ts +20 -0
- package/dist/src/tui/console-app-v4.js +2613 -0
- package/dist/src/tui/console-app-v4.js.map +1 -0
- package/dist/src/tui/controller-runtime.d.ts +11 -0
- package/dist/src/tui/controller-runtime.js +902 -0
- package/dist/src/tui/controller-runtime.js.map +1 -0
- package/dist/src/tui/controller.d.ts +367 -0
- package/dist/src/tui/controller.js +1724 -0
- package/dist/src/tui/controller.js.map +1 -0
- package/dist/src/tui/index.d.ts +13 -0
- package/dist/src/tui/index.js +14 -0
- package/dist/src/tui/index.js.map +1 -0
- package/dist/src/tui/keys.d.ts +12 -0
- package/dist/src/tui/keys.js +22 -0
- package/dist/src/tui/keys.js.map +1 -0
- package/dist/src/tui/layout.d.ts +12 -0
- package/dist/src/tui/layout.js +19 -0
- package/dist/src/tui/layout.js.map +1 -0
- package/dist/src/tui/model.d.ts +279 -0
- package/dist/src/tui/model.js +652 -0
- package/dist/src/tui/model.js.map +1 -0
- package/dist/src/tui/prompt.d.ts +8 -0
- package/dist/src/tui/prompt.js +242 -0
- package/dist/src/tui/prompt.js.map +1 -0
- package/dist/src/tui/router.d.ts +153 -0
- package/dist/src/tui/router.js +102 -0
- package/dist/src/tui/router.js.map +1 -0
- package/dist/src/tui/runner.d.ts +11 -0
- package/dist/src/tui/runner.js +71 -0
- package/dist/src/tui/runner.js.map +1 -0
- package/dist/src/tui/theme.d.ts +18 -0
- package/dist/src/tui/theme.js +20 -0
- package/dist/src/tui/theme.js.map +1 -0
- package/dist/src/tui/views.d.ts +57 -0
- package/dist/src/tui/views.js +173 -0
- package/dist/src/tui/views.js.map +1 -0
- package/dist/src/tui/wizard.d.ts +11 -0
- package/dist/src/tui/wizard.js +321 -0
- package/dist/src/tui/wizard.js.map +1 -0
- package/dist/src/types.d.ts +313 -0
- package/dist/src/types.js +33 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils/active-marketplace-runtime-lock.d.ts +12 -0
- package/dist/src/utils/active-marketplace-runtime-lock.js +133 -0
- package/dist/src/utils/active-marketplace-runtime-lock.js.map +1 -0
- package/dist/src/utils/agent-version.d.ts +13 -0
- package/dist/src/utils/agent-version.js +172 -0
- package/dist/src/utils/agent-version.js.map +1 -0
- package/dist/src/utils/artifact-plan.d.ts +26 -0
- package/dist/src/utils/artifact-plan.js +444 -0
- package/dist/src/utils/artifact-plan.js.map +1 -0
- package/dist/src/utils/artifact-renderer.d.ts +124 -0
- package/dist/src/utils/artifact-renderer.js +442 -0
- package/dist/src/utils/artifact-renderer.js.map +1 -0
- package/dist/src/utils/artifact-sources.d.ts +8 -0
- package/dist/src/utils/artifact-sources.js +10 -0
- package/dist/src/utils/artifact-sources.js.map +1 -0
- package/dist/src/utils/aw-home-mutation-lock.d.ts +10 -0
- package/dist/src/utils/aw-home-mutation-lock.js +55 -0
- package/dist/src/utils/aw-home-mutation-lock.js.map +1 -0
- package/dist/src/utils/bundle-integrity.d.ts +3 -0
- package/dist/src/utils/bundle-integrity.js +88 -0
- package/dist/src/utils/bundle-integrity.js.map +1 -0
- package/dist/src/utils/bundle-layout.d.ts +4 -0
- package/dist/src/utils/bundle-layout.js +546 -0
- package/dist/src/utils/bundle-layout.js.map +1 -0
- package/dist/src/utils/catalog-digests.d.ts +8 -0
- package/dist/src/utils/catalog-digests.js +108 -0
- package/dist/src/utils/catalog-digests.js.map +1 -0
- package/dist/src/utils/catalog-manifest-v3.d.ts +2 -0
- package/dist/src/utils/catalog-manifest-v3.js +3 -0
- package/dist/src/utils/catalog-manifest-v3.js.map +1 -0
- package/dist/src/utils/catalog-manifest-v4.d.ts +5 -0
- package/dist/src/utils/catalog-manifest-v4.js +106 -0
- package/dist/src/utils/catalog-manifest-v4.js.map +1 -0
- package/dist/src/utils/catalog-public-error.d.ts +15 -0
- package/dist/src/utils/catalog-public-error.js +84 -0
- package/dist/src/utils/catalog-public-error.js.map +1 -0
- package/dist/src/utils/catalog-runtime-projection.d.ts +36 -0
- package/dist/src/utils/catalog-runtime-projection.js +172 -0
- package/dist/src/utils/catalog-runtime-projection.js.map +1 -0
- package/dist/src/utils/catalog-snapshot.d.ts +8 -0
- package/dist/src/utils/catalog-snapshot.js +12 -0
- package/dist/src/utils/catalog-snapshot.js.map +1 -0
- package/dist/src/utils/catalog-source-cache.d.ts +61 -0
- package/dist/src/utils/catalog-source-cache.js +276 -0
- package/dist/src/utils/catalog-source-cache.js.map +1 -0
- package/dist/src/utils/catalog-source-identity.d.ts +4 -0
- package/dist/src/utils/catalog-source-identity.js +118 -0
- package/dist/src/utils/catalog-source-identity.js.map +1 -0
- package/dist/src/utils/catalog-source-presentation.d.ts +1 -0
- package/dist/src/utils/catalog-source-presentation.js +32 -0
- package/dist/src/utils/catalog-source-presentation.js.map +1 -0
- package/dist/src/utils/catalog-source-references.d.ts +65 -0
- package/dist/src/utils/catalog-source-references.js +1418 -0
- package/dist/src/utils/catalog-source-references.js.map +1 -0
- package/dist/src/utils/catalog-sources.d.ts +39 -0
- package/dist/src/utils/catalog-sources.js +293 -0
- package/dist/src/utils/catalog-sources.js.map +1 -0
- package/dist/src/utils/codex-config.d.ts +124 -0
- package/dist/src/utils/codex-config.js +1011 -0
- package/dist/src/utils/codex-config.js.map +1 -0
- package/dist/src/utils/codex-project-surface.d.ts +3 -0
- package/dist/src/utils/codex-project-surface.js +49 -0
- package/dist/src/utils/codex-project-surface.js.map +1 -0
- package/dist/src/utils/codex-roles.d.ts +71 -0
- package/dist/src/utils/codex-roles.js +257 -0
- package/dist/src/utils/codex-roles.js.map +1 -0
- package/dist/src/utils/codex-skill-staging.d.ts +9 -0
- package/dist/src/utils/codex-skill-staging.js +8 -0
- package/dist/src/utils/codex-skill-staging.js.map +1 -0
- package/dist/src/utils/config-value.d.ts +3 -0
- package/dist/src/utils/config-value.js +23 -0
- package/dist/src/utils/config-value.js.map +1 -0
- package/dist/src/utils/dynamic-skill-tree.d.ts +32 -0
- package/dist/src/utils/dynamic-skill-tree.js +436 -0
- package/dist/src/utils/dynamic-skill-tree.js.map +1 -0
- package/dist/src/utils/file-rules.d.ts +1 -0
- package/dist/src/utils/file-rules.js +2 -0
- package/dist/src/utils/file-rules.js.map +1 -0
- package/dist/src/utils/git-catalog-provider.d.ts +7 -0
- package/dist/src/utils/git-catalog-provider.js +510 -0
- package/dist/src/utils/git-catalog-provider.js.map +1 -0
- package/dist/src/utils/hooks-contract.d.ts +1 -0
- package/dist/src/utils/hooks-contract.js +2 -0
- package/dist/src/utils/hooks-contract.js.map +1 -0
- package/dist/src/utils/json.d.ts +4 -0
- package/dist/src/utils/json.js +29 -0
- package/dist/src/utils/json.js.map +1 -0
- package/dist/src/utils/lifecycle-active-store.d.ts +175 -0
- package/dist/src/utils/lifecycle-active-store.js +1276 -0
- package/dist/src/utils/lifecycle-active-store.js.map +1 -0
- package/dist/src/utils/local-marketplace.d.ts +41 -0
- package/dist/src/utils/local-marketplace.js +317 -0
- package/dist/src/utils/local-marketplace.js.map +1 -0
- package/dist/src/utils/manifest.d.ts +14 -0
- package/dist/src/utils/manifest.js +36 -0
- package/dist/src/utils/manifest.js.map +1 -0
- package/dist/src/utils/marketplace.d.ts +3 -0
- package/dist/src/utils/marketplace.js +76 -0
- package/dist/src/utils/marketplace.js.map +1 -0
- package/dist/src/utils/multi-source-catalog.d.ts +72 -0
- package/dist/src/utils/multi-source-catalog.js +402 -0
- package/dist/src/utils/multi-source-catalog.js.map +1 -0
- package/dist/src/utils/native-cli.d.ts +75 -0
- package/dist/src/utils/native-cli.js +435 -0
- package/dist/src/utils/native-cli.js.map +1 -0
- package/dist/src/utils/orphan-marketplace-cleanup.d.ts +18 -0
- package/dist/src/utils/orphan-marketplace-cleanup.js +202 -0
- package/dist/src/utils/orphan-marketplace-cleanup.js.map +1 -0
- package/dist/src/utils/ownership.d.ts +130 -0
- package/dist/src/utils/ownership.js +766 -0
- package/dist/src/utils/ownership.js.map +1 -0
- package/dist/src/utils/path-catalog-provider.d.ts +7 -0
- package/dist/src/utils/path-catalog-provider.js +87 -0
- package/dist/src/utils/path-catalog-provider.js.map +1 -0
- package/dist/src/utils/paths.d.ts +41 -0
- package/dist/src/utils/paths.js +138 -0
- package/dist/src/utils/paths.js.map +1 -0
- package/dist/src/utils/platform-entries.d.ts +1 -0
- package/dist/src/utils/platform-entries.js +2 -0
- package/dist/src/utils/platform-entries.js.map +1 -0
- package/dist/src/utils/platform-support.d.ts +1 -0
- package/dist/src/utils/platform-support.js +2 -0
- package/dist/src/utils/platform-support.js.map +1 -0
- package/dist/src/utils/plugin-authoring-capabilities.d.ts +23 -0
- package/dist/src/utils/plugin-authoring-capabilities.js +37 -0
- package/dist/src/utils/plugin-authoring-capabilities.js.map +1 -0
- package/dist/src/utils/plugin-authoring-capabilities.json +92 -0
- package/dist/src/utils/plugin-config-write.d.ts +107 -0
- package/dist/src/utils/plugin-config-write.js +565 -0
- package/dist/src/utils/plugin-config-write.js.map +1 -0
- package/dist/src/utils/plugin-config.d.ts +396 -0
- package/dist/src/utils/plugin-config.js +1898 -0
- package/dist/src/utils/plugin-config.js.map +1 -0
- package/dist/src/utils/plugin-dependencies.d.ts +12 -0
- package/dist/src/utils/plugin-dependencies.js +162 -0
- package/dist/src/utils/plugin-dependencies.js.map +1 -0
- package/dist/src/utils/plugin-release.d.ts +2 -0
- package/dist/src/utils/plugin-release.js +2 -0
- package/dist/src/utils/plugin-release.js.map +1 -0
- package/dist/src/utils/plugin-script-contract.d.ts +1 -0
- package/dist/src/utils/plugin-script-contract.js +2 -0
- package/dist/src/utils/plugin-script-contract.js.map +1 -0
- package/dist/src/utils/plugin-scripts.d.ts +172 -0
- package/dist/src/utils/plugin-scripts.js +585 -0
- package/dist/src/utils/plugin-scripts.js.map +1 -0
- package/dist/src/utils/process-lock.d.ts +47 -0
- package/dist/src/utils/process-lock.js +532 -0
- package/dist/src/utils/process-lock.js.map +1 -0
- package/dist/src/utils/process-tree.d.ts +2 -0
- package/dist/src/utils/process-tree.js +2 -0
- package/dist/src/utils/process-tree.js.map +1 -0
- package/dist/src/utils/project-boundary.d.ts +21 -0
- package/dist/src/utils/project-boundary.js +95 -0
- package/dist/src/utils/project-boundary.js.map +1 -0
- package/dist/src/utils/rendered-contract.d.ts +8 -0
- package/dist/src/utils/rendered-contract.js +134 -0
- package/dist/src/utils/rendered-contract.js.map +1 -0
- package/dist/src/utils/runtime-skill-closure.d.ts +13 -0
- package/dist/src/utils/runtime-skill-closure.js +863 -0
- package/dist/src/utils/runtime-skill-closure.js.map +1 -0
- package/dist/src/utils/skill-authoring.d.ts +1 -0
- package/dist/src/utils/skill-authoring.js +2 -0
- package/dist/src/utils/skill-authoring.js.map +1 -0
- package/dist/src/utils/skill-frontmatter-capabilities.d.ts +201 -0
- package/dist/src/utils/skill-frontmatter-capabilities.js +5 -0
- package/dist/src/utils/skill-frontmatter-capabilities.js.map +1 -0
- package/dist/src/utils/skill-frontmatter-capabilities.json +200 -0
- package/dist/src/utils/skill-validation.d.ts +37 -0
- package/dist/src/utils/skill-validation.js +326 -0
- package/dist/src/utils/skill-validation.js.map +1 -0
- package/dist/src/utils/slash-commands.d.ts +1 -0
- package/dist/src/utils/slash-commands.js +2 -0
- package/dist/src/utils/slash-commands.js.map +1 -0
- package/dist/src/utils/state-paths.d.ts +13 -0
- package/dist/src/utils/state-paths.js +129 -0
- package/dist/src/utils/state-paths.js.map +1 -0
- package/dist/src/utils/target-eligibility.d.ts +7 -0
- package/dist/src/utils/target-eligibility.js +26 -0
- package/dist/src/utils/target-eligibility.js.map +1 -0
- package/dist/src/utils/target-order.d.ts +7 -0
- package/dist/src/utils/target-order.js +10 -0
- package/dist/src/utils/target-order.js.map +1 -0
- package/dist/src/utils/template-engine.d.ts +1 -0
- package/dist/src/utils/template-engine.js +2 -0
- package/dist/src/utils/template-engine.js.map +1 -0
- package/dist/src/utils/test-path-fence.d.ts +12 -0
- package/dist/src/utils/test-path-fence.js +31 -0
- package/dist/src/utils/test-path-fence.js.map +1 -0
- package/dist/vitest.config.d.ts +2 -0
- package/dist/vitest.config.js +16 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,1681 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import { probeAgentVersion } from '../utils/agent-version.js';
|
|
4
|
+
import { createNoopDebugLogger } from '../output/debug-log.js';
|
|
5
|
+
import { createNoopReporter } from '../output/reporter.js';
|
|
6
|
+
import { getDefaultNativeCliRunner } from '../utils/native-cli.js';
|
|
7
|
+
import { readPluginManifest, resolvePluginsFromCatalog } from '../utils/manifest.js';
|
|
8
|
+
import { resolveAwHome } from '../utils/paths.js';
|
|
9
|
+
import { resolveCliPackageRoot } from '../utils/paths.js';
|
|
10
|
+
import { supportsPlatform } from '../utils/platform-support.js';
|
|
11
|
+
import { hasCodexProjectManagedArtifacts } from '../utils/codex-project-surface.js';
|
|
12
|
+
import { createRebuildActiveStore, executeRebuildOperation, releaseRebuildOperationLease, } from './rebuild-operations.js';
|
|
13
|
+
import { assertNoClaudeUnboundNativeNameCollision, createRebuildIntegration, discoverRebuildTargetNames, inspectNativeMarketplaceRegistrations, } from './rebuild-integration.js';
|
|
14
|
+
import { getNamespacedMarketplaceName } from '../utils/local-marketplace.js';
|
|
15
|
+
import { formatPluginId, parsePluginId, planPluginSelectorSourceIds, preflightDesiredArtifactCollisions, withResolvedMultiSourceCatalog, } from '../utils/multi-source-catalog.js';
|
|
16
|
+
import { assertStrictSemVer } from '../utils/manifest.js';
|
|
17
|
+
import { assertCatalogSourceInventoryComplete, canonicalMarketplaceRegistrationNames, inventoryCatalogSourceReferences, } from '../utils/catalog-source-references.js';
|
|
18
|
+
import { resolveEffectivePluginConfig } from '../utils/plugin-config.js';
|
|
19
|
+
import { cleanupCorruptExclusivePluginDirectory, inspectOwnedComponents, } from '../utils/ownership.js';
|
|
20
|
+
import { getClaudeHome, getCodexHome, resolveCanonicalRepoProjectKey, resolveRepoRootSync, } from '../utils/state-paths.js';
|
|
21
|
+
import { resolvePluginMetaDependencyClosure } from '../utils/plugin-dependencies.js';
|
|
22
|
+
import { createDependencyOperationPlan, } from './dependency-operation-plan.js';
|
|
23
|
+
let rebuildCommandTestHooks;
|
|
24
|
+
async function emitRebuildActionEvent(runtime, event) {
|
|
25
|
+
await Promise.allSettled([
|
|
26
|
+
Promise.resolve().then(() => runtime.reporter.event(event)),
|
|
27
|
+
Promise.resolve().then(() => runtime.debugLogger.log(event)),
|
|
28
|
+
]);
|
|
29
|
+
}
|
|
30
|
+
async function withRebuildActionEvent(options) {
|
|
31
|
+
const source = {
|
|
32
|
+
plugin: options.identity.pluginName,
|
|
33
|
+
platform: options.identity.platform,
|
|
34
|
+
scope: options.identity.scope,
|
|
35
|
+
action: options.command,
|
|
36
|
+
};
|
|
37
|
+
const startedAt = Date.now();
|
|
38
|
+
await emitRebuildActionEvent(options.runtime, {
|
|
39
|
+
type: 'rebuild:action',
|
|
40
|
+
source,
|
|
41
|
+
data: { name: options.name, phase: 'start' },
|
|
42
|
+
});
|
|
43
|
+
let result;
|
|
44
|
+
try {
|
|
45
|
+
result = await options.operation();
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
await emitRebuildActionEvent(options.runtime, {
|
|
49
|
+
type: 'rebuild:action',
|
|
50
|
+
source,
|
|
51
|
+
data: {
|
|
52
|
+
name: options.name,
|
|
53
|
+
phase: 'failure',
|
|
54
|
+
durationMs: Math.max(0, Date.now() - startedAt),
|
|
55
|
+
message: options.name === 'operation.lock'
|
|
56
|
+
? '获取操作锁失败。'
|
|
57
|
+
: '释放操作锁失败。',
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
await emitRebuildActionEvent(options.runtime, {
|
|
63
|
+
type: 'rebuild:action',
|
|
64
|
+
source,
|
|
65
|
+
data: {
|
|
66
|
+
name: options.name,
|
|
67
|
+
phase: 'success',
|
|
68
|
+
durationMs: Math.max(0, Date.now() - startedAt),
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
export function setRebuildCommandTestHooksForTests(hooks) {
|
|
74
|
+
rebuildCommandTestHooks = hooks;
|
|
75
|
+
}
|
|
76
|
+
function selectedPlatforms(selection) {
|
|
77
|
+
return selection === 'both' ? ['codex', 'claude'] : [selection];
|
|
78
|
+
}
|
|
79
|
+
function createSyntheticPlugin(pluginName, env) {
|
|
80
|
+
const rootDir = path.join(resolveAwHome(env), 'plugins', pluginName);
|
|
81
|
+
return {
|
|
82
|
+
rootDir,
|
|
83
|
+
manifestPath: path.join(rootDir, '.agents-plugin', 'plugin.json'),
|
|
84
|
+
manifest: {
|
|
85
|
+
schemaVersion: 1,
|
|
86
|
+
name: pluginName,
|
|
87
|
+
version: '0.0.0',
|
|
88
|
+
description: 'Cleanup-only target for a plugin missing from the current catalog.',
|
|
89
|
+
compatibility: { aw: { minVersion: '0.0.0' } },
|
|
90
|
+
marketplace: {
|
|
91
|
+
category: 'cleanup',
|
|
92
|
+
strict: true,
|
|
93
|
+
policy: { installation: 'AVAILABLE', authentication: 'ON_INSTALL' },
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function failedResult(command, identity, message, phase = 'preflight') {
|
|
99
|
+
return {
|
|
100
|
+
status: 'failed',
|
|
101
|
+
command,
|
|
102
|
+
target: identity,
|
|
103
|
+
actions: phase === 'preflight' ? [] : [{ name: phase, status: 'failed' }],
|
|
104
|
+
cleanupAttempted: false,
|
|
105
|
+
removed: [],
|
|
106
|
+
absent: [],
|
|
107
|
+
residual: [],
|
|
108
|
+
quarantined: [],
|
|
109
|
+
failures: [{ phase, message }],
|
|
110
|
+
error: { phase, message },
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function appendOperationReleaseFailure(result, message) {
|
|
114
|
+
result.actions.push({ name: 'operation.release', status: 'failed' });
|
|
115
|
+
result.failures.push({ phase: 'operation.release', message });
|
|
116
|
+
if (result.status === 'failed')
|
|
117
|
+
return result;
|
|
118
|
+
return {
|
|
119
|
+
...result,
|
|
120
|
+
status: 'failed',
|
|
121
|
+
error: { phase: 'operation.release', message },
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function toTargetResult(result) {
|
|
125
|
+
return {
|
|
126
|
+
target: {
|
|
127
|
+
pluginName: result.target.pluginName,
|
|
128
|
+
...(result.target.sourceId ? {
|
|
129
|
+
sourceId: result.target.sourceId,
|
|
130
|
+
sourceIdentity: result.target.sourceIdentity,
|
|
131
|
+
pluginId: result.target.pluginId,
|
|
132
|
+
} : {}),
|
|
133
|
+
platform: result.target.platform,
|
|
134
|
+
scope: result.target.scope,
|
|
135
|
+
},
|
|
136
|
+
action: result.command,
|
|
137
|
+
state: result.status === 'succeeded' ? 'completed' : 'failed',
|
|
138
|
+
...(result.status === 'failed' ? { message: result.error.message } : {}),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
async function assertAgentVersions(options) {
|
|
142
|
+
const failures = [];
|
|
143
|
+
for (const platform of options.platforms) {
|
|
144
|
+
const result = await probeAgentVersion(platform, {
|
|
145
|
+
cwd: options.cwd,
|
|
146
|
+
env: options.env,
|
|
147
|
+
runner: options.runtime.nativeCliRunner,
|
|
148
|
+
});
|
|
149
|
+
if (result.status !== 'supported')
|
|
150
|
+
failures.push(result);
|
|
151
|
+
}
|
|
152
|
+
if (failures.length > 0) {
|
|
153
|
+
throw new Error(failures.map((failure) => `${failure.command} 版本检查失败:${failure.details ?? failure.status};最低版本 ${failure.requiredMinVersion}。`)
|
|
154
|
+
.join(';'));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async function resolveRequestedNames(options) {
|
|
158
|
+
const result = new Map();
|
|
159
|
+
for (const platform of options.platforms) {
|
|
160
|
+
const names = options.command === 'upgrade' && options.all
|
|
161
|
+
? await discoverRebuildTargetNames({
|
|
162
|
+
cwd: options.cwd,
|
|
163
|
+
env: options.env,
|
|
164
|
+
platform,
|
|
165
|
+
scope: options.scope,
|
|
166
|
+
nativeCliRunner: options.nativeCliRunner,
|
|
167
|
+
nativeFailureMode: 'error',
|
|
168
|
+
})
|
|
169
|
+
: options.pluginNames;
|
|
170
|
+
result.set(platform, [...new Set(names)]);
|
|
171
|
+
}
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
async function runSingleSourceRebuildCommand(options) {
|
|
175
|
+
const runtime = options.runtime?.preparedTarget?.context ?? {
|
|
176
|
+
env: options.runtime?.env ?? process.env,
|
|
177
|
+
nativeCliRunner: options.runtime?.nativeCliRunner ?? getDefaultNativeCliRunner(),
|
|
178
|
+
reporter: options.runtime?.reporter ?? createNoopReporter(),
|
|
179
|
+
debugLogger: options.runtime?.debugLogger ?? createNoopDebugLogger(),
|
|
180
|
+
runtimeLeaseHeld: options.runtime?.runtimeLeaseHeld,
|
|
181
|
+
lifecycleLeaseHeld: options.runtime?.lifecycleLeaseHeld,
|
|
182
|
+
expectedCatalogConfigDigest: options.runtime?.expectedCatalogConfigDigest,
|
|
183
|
+
};
|
|
184
|
+
const env = runtime.env;
|
|
185
|
+
const selected = selectedPlatforms(options.commandOptions.platform);
|
|
186
|
+
const catalog = options.runtime?.catalogResolution;
|
|
187
|
+
if (!catalog)
|
|
188
|
+
throw new Error('Internal error: a resolved catalog source is required.');
|
|
189
|
+
const catalogPlugins = await resolvePluginsFromCatalog(catalog.rootDir, undefined);
|
|
190
|
+
if (options.runtime?.namespacedSource) {
|
|
191
|
+
for (const plugin of catalogPlugins) {
|
|
192
|
+
plugin.sourceId = options.runtime.namespacedSource.sourceId;
|
|
193
|
+
plugin.sourceIdentity = options.runtime.namespacedSource.sourceIdentity;
|
|
194
|
+
plugin.pluginId = formatPluginId({
|
|
195
|
+
sourceId: options.runtime.namespacedSource.sourceId,
|
|
196
|
+
pluginName: plugin.manifest.name,
|
|
197
|
+
});
|
|
198
|
+
plugin.marketplaceName = options.runtime.namespacedSource.marketplaceName;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const catalogByName = new Map(catalogPlugins.map((plugin) => [plugin.manifest.name, plugin]));
|
|
202
|
+
const requestedByPlatform = await resolveRequestedNames({
|
|
203
|
+
command: options.command,
|
|
204
|
+
pluginNames: options.pluginNames,
|
|
205
|
+
all: options.all,
|
|
206
|
+
platforms: selected,
|
|
207
|
+
scope: options.commandOptions.scope,
|
|
208
|
+
cwd: options.commandOptions.cwd,
|
|
209
|
+
env,
|
|
210
|
+
nativeCliRunner: runtime.nativeCliRunner,
|
|
211
|
+
});
|
|
212
|
+
if (options.commandOptions.platform === 'both'
|
|
213
|
+
&& options.command !== 'cleanup'
|
|
214
|
+
&& options.command !== 'uninstall') {
|
|
215
|
+
for (const platform of selected) {
|
|
216
|
+
requestedByPlatform.set(platform, (requestedByPlatform.get(platform) ?? []).filter((pluginName) => {
|
|
217
|
+
const plugin = catalogByName.get(pluginName);
|
|
218
|
+
return !plugin || supportsPlatform(plugin.manifest, platform);
|
|
219
|
+
}));
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const platforms = selected.filter((platform) => (requestedByPlatform.get(platform)?.length ?? 0) > 0);
|
|
223
|
+
await assertAgentVersions({
|
|
224
|
+
platforms,
|
|
225
|
+
cwd: options.commandOptions.cwd,
|
|
226
|
+
env,
|
|
227
|
+
runtime,
|
|
228
|
+
});
|
|
229
|
+
const integration = options.runtime?.preparedTarget
|
|
230
|
+
? {
|
|
231
|
+
driver: options.runtime.preparedTarget.driver,
|
|
232
|
+
buildTarget: async () => options.runtime.preparedTarget.target,
|
|
233
|
+
}
|
|
234
|
+
: createRebuildIntegration({
|
|
235
|
+
context: runtime,
|
|
236
|
+
scriptTimeoutMs: options.commandOptions.scriptTimeoutMs,
|
|
237
|
+
});
|
|
238
|
+
const activeStore = createRebuildActiveStore({
|
|
239
|
+
env,
|
|
240
|
+
loadPlugin: (bundleRoot) => readPluginManifest(bundleRoot, { mode: 'bundle' }),
|
|
241
|
+
isLifecycleLeaseHeld: () => runtime.lifecycleLeaseHeld === true,
|
|
242
|
+
});
|
|
243
|
+
const targets = [];
|
|
244
|
+
const results = [];
|
|
245
|
+
for (const platform of platforms) {
|
|
246
|
+
for (const pluginName of requestedByPlatform.get(platform) ?? []) {
|
|
247
|
+
const currentPlugin = catalogByName.get(pluginName);
|
|
248
|
+
const identity = {
|
|
249
|
+
...(options.runtime?.namespacedSource ?? {}),
|
|
250
|
+
...(options.runtime?.namespacedSource ? {
|
|
251
|
+
pluginId: formatPluginId({
|
|
252
|
+
sourceId: options.runtime.namespacedSource.sourceId,
|
|
253
|
+
pluginName,
|
|
254
|
+
}),
|
|
255
|
+
} : currentPlugin?.pluginId ? { pluginId: currentPlugin.pluginId } : {}),
|
|
256
|
+
pluginName,
|
|
257
|
+
pluginVersion: currentPlugin?.manifest.version ?? '0.0.0',
|
|
258
|
+
platform,
|
|
259
|
+
scope: options.commandOptions.scope,
|
|
260
|
+
cwd: options.commandOptions.cwd,
|
|
261
|
+
};
|
|
262
|
+
if (!currentPlugin && options.command === 'upgrade') {
|
|
263
|
+
results.push(failedResult(options.command, identity, `${pluginName} 当前不在 current catalog 中,不能用历史 bundle 升级。请运行 \`aw cleanup ${pluginName} -p ${platform} -s ${options.commandOptions.scope}\` 清理当前可见 AW 输出。`));
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
if (!currentPlugin && options.command !== 'cleanup' && options.command !== 'uninstall') {
|
|
267
|
+
results.push(failedResult(options.command, identity, `${pluginName} 当前不在 current catalog 中。`));
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
const plugin = currentPlugin ?? createSyntheticPlugin(pluginName, env);
|
|
271
|
+
if (currentPlugin
|
|
272
|
+
&& options.command !== 'cleanup'
|
|
273
|
+
&& options.command !== 'uninstall'
|
|
274
|
+
&& !supportsPlatform(currentPlugin.manifest, platform)) {
|
|
275
|
+
results.push(failedResult(options.command, identity, options.command === 'upgrade'
|
|
276
|
+
? `${pluginName} 当前 catalog 不再支持 ${platform},不能升级这个可见目标。请运行 \`aw cleanup ${pluginName} -p ${platform} -s ${options.commandOptions.scope}\`。`
|
|
277
|
+
: `${pluginName} 当前 catalog 不支持 ${platform}。`));
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
if (currentPlugin
|
|
281
|
+
&& platform === 'codex'
|
|
282
|
+
&& options.commandOptions.scope === 'project'
|
|
283
|
+
&& options.command !== 'cleanup'
|
|
284
|
+
&& options.command !== 'uninstall'
|
|
285
|
+
&& currentPlugin.manifest.apps) {
|
|
286
|
+
results.push(failedResult(options.command, identity, `${pluginName} 声明了 apps;Codex project scope 不支持 apps。`));
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
if (currentPlugin
|
|
290
|
+
&& platform === 'codex'
|
|
291
|
+
&& options.commandOptions.scope === 'project'
|
|
292
|
+
&& options.command !== 'cleanup'
|
|
293
|
+
&& options.command !== 'uninstall'
|
|
294
|
+
&& !hasCodexProjectManagedArtifacts(currentPlugin)) {
|
|
295
|
+
results.push(failedResult(options.command, identity, `${pluginName} 没有 Codex project scope 可生成的 Skills、instructions、roles、MCP、hooks 或 permissions。`));
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
let operationLock;
|
|
299
|
+
if (!options.runtime?.operationLeaseHeld) {
|
|
300
|
+
try {
|
|
301
|
+
await rebuildCommandTestHooks?.beforeOperationLockAcquire?.({
|
|
302
|
+
command: options.command,
|
|
303
|
+
identity,
|
|
304
|
+
});
|
|
305
|
+
operationLock = await withRebuildActionEvent({
|
|
306
|
+
runtime,
|
|
307
|
+
command: options.command,
|
|
308
|
+
identity,
|
|
309
|
+
name: 'operation.lock',
|
|
310
|
+
operation: () => activeStore.acquireOperation(identity),
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
results.push(failedResult(options.command, identity, error instanceof Error ? error.message : String(error), 'operation.lock'));
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
let result;
|
|
319
|
+
try {
|
|
320
|
+
if (options.runtime?.preparedTargetError)
|
|
321
|
+
throw options.runtime.preparedTargetError;
|
|
322
|
+
const target = await integration.buildTarget({
|
|
323
|
+
...(options.runtime?.namespacedSource ?? {}),
|
|
324
|
+
...(options.runtime?.namespacedSource ? {
|
|
325
|
+
pluginId: formatPluginId({
|
|
326
|
+
sourceId: options.runtime.namespacedSource.sourceId,
|
|
327
|
+
pluginName,
|
|
328
|
+
}),
|
|
329
|
+
} : plugin.pluginId ? { pluginId: plugin.pluginId } : {}),
|
|
330
|
+
plugin,
|
|
331
|
+
platform,
|
|
332
|
+
scope: options.commandOptions.scope,
|
|
333
|
+
cwd: options.commandOptions.cwd,
|
|
334
|
+
command: options.command,
|
|
335
|
+
catalog,
|
|
336
|
+
includeHistoricalLifecycleArtifacts: true,
|
|
337
|
+
});
|
|
338
|
+
targets.push(target);
|
|
339
|
+
if (!options.runtime?.targetBuiltHookHandled) {
|
|
340
|
+
await rebuildCommandTestHooks?.afterTargetBuilt?.({
|
|
341
|
+
command: options.command,
|
|
342
|
+
identity,
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
if (!options.runtime?.dependencyReviewPreflightHandled) {
|
|
346
|
+
await options.runtime?.reviewPreflight?.({
|
|
347
|
+
command: options.command,
|
|
348
|
+
identity,
|
|
349
|
+
...options.runtime.resolvedReviewEvidenceByPlugin?.[pluginName],
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
const { acquireOperation: _acquireOperation, ...operationHeldStore } = activeStore;
|
|
353
|
+
result = await executeRebuildOperation({
|
|
354
|
+
command: options.command,
|
|
355
|
+
target,
|
|
356
|
+
driver: integration.driver,
|
|
357
|
+
activeStore: operationHeldStore,
|
|
358
|
+
onActionEvent: (event) => emitRebuildActionEvent(runtime, event),
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
catch (error) {
|
|
362
|
+
result = error.result ?? failedResult(options.command, identity, error instanceof Error ? error.message : String(error), 'preflight');
|
|
363
|
+
}
|
|
364
|
+
result.actions.unshift({ name: 'operation.lock', status: 'succeeded' });
|
|
365
|
+
if (operationLock) {
|
|
366
|
+
try {
|
|
367
|
+
await withRebuildActionEvent({
|
|
368
|
+
runtime,
|
|
369
|
+
command: options.command,
|
|
370
|
+
identity,
|
|
371
|
+
name: 'operation.release',
|
|
372
|
+
operation: () => releaseRebuildOperationLease(operationLock),
|
|
373
|
+
});
|
|
374
|
+
result.actions.push({ name: 'operation.release', status: 'succeeded' });
|
|
375
|
+
}
|
|
376
|
+
catch (error) {
|
|
377
|
+
result = appendOperationReleaseFailure(result, error instanceof Error ? error.message : String(error));
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
results.push(result);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
const successful = results.filter((result) => result.status === 'succeeded');
|
|
384
|
+
const artifacts = targets.flatMap((target) => [...target.artifacts]);
|
|
385
|
+
const nativePlugins = {};
|
|
386
|
+
for (const result of successful) {
|
|
387
|
+
const target = targets.find((entry) => entry.identity.pluginName === result.target.pluginName
|
|
388
|
+
&& entry.identity.platform === result.target.platform
|
|
389
|
+
&& entry.identity.scope === result.target.scope);
|
|
390
|
+
if (target?.requiresNative && options.command !== 'cleanup' && options.command !== 'uninstall') {
|
|
391
|
+
nativePlugins[result.target.platform] ??= [];
|
|
392
|
+
nativePlugins[result.target.platform].push(result.target.pluginName);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return {
|
|
396
|
+
platforms,
|
|
397
|
+
plugins: [...new Set(successful.map((result) => result.target.pluginName))],
|
|
398
|
+
warnings: [],
|
|
399
|
+
rebuildResults: results,
|
|
400
|
+
targetResults: results.map(toTargetResult),
|
|
401
|
+
overallState: results.every((result) => result.status === 'succeeded') ? 'succeeded' : 'failed',
|
|
402
|
+
nativePlugins,
|
|
403
|
+
repoManagedArtifacts: artifacts,
|
|
404
|
+
receiptTargets: results.map((result) => ({
|
|
405
|
+
pluginName: result.target.pluginName,
|
|
406
|
+
...(result.target.sourceId ? {
|
|
407
|
+
sourceId: result.target.sourceId,
|
|
408
|
+
pluginId: result.target.pluginId,
|
|
409
|
+
} : {}),
|
|
410
|
+
platform: result.target.platform,
|
|
411
|
+
scope: result.target.scope,
|
|
412
|
+
})),
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
function resolveRuntimeCliVersion() {
|
|
416
|
+
const value = fs.readJsonSync(path.join(resolveCliPackageRoot(), 'package.json'));
|
|
417
|
+
return assertStrictSemVer(value.version, 'packages/cli/package.json version');
|
|
418
|
+
}
|
|
419
|
+
function toCatalogResolution(source) {
|
|
420
|
+
return {
|
|
421
|
+
rootDir: source.rootDir,
|
|
422
|
+
source: 'local',
|
|
423
|
+
catalogVersion: source.manifest.catalogVersion,
|
|
424
|
+
channel: source.manifest.channel,
|
|
425
|
+
minAwVersion: source.manifest.compatibility.aw.minVersion,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
function mergeRebuildCommandResults(results) {
|
|
429
|
+
const rebuildResults = results.flatMap((result) => result.rebuildResults);
|
|
430
|
+
const platforms = [...new Set(results.flatMap((result) => result.platforms))];
|
|
431
|
+
const nativePlugins = {};
|
|
432
|
+
for (const result of results) {
|
|
433
|
+
for (const platform of ['codex', 'claude']) {
|
|
434
|
+
const names = result.nativePlugins[platform];
|
|
435
|
+
if (names)
|
|
436
|
+
nativePlugins[platform] = [...new Set([...(nativePlugins[platform] ?? []), ...names])];
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return {
|
|
440
|
+
platforms,
|
|
441
|
+
plugins: [...new Set(results.flatMap((result) => result.plugins))],
|
|
442
|
+
warnings: results.flatMap((result) => result.warnings),
|
|
443
|
+
rebuildResults,
|
|
444
|
+
targetResults: results.flatMap((result) => result.targetResults),
|
|
445
|
+
overallState: rebuildResults.every((result) => result.status === 'succeeded')
|
|
446
|
+
? 'succeeded'
|
|
447
|
+
: 'failed',
|
|
448
|
+
nativePlugins,
|
|
449
|
+
repoManagedArtifacts: [],
|
|
450
|
+
receiptTargets: results.flatMap((result) => result.receiptTargets),
|
|
451
|
+
...(results.find((result) => result.dependencyPlan)?.dependencyPlan
|
|
452
|
+
? { dependencyPlan: results.find((result) => result.dependencyPlan).dependencyPlan }
|
|
453
|
+
: {}),
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
function leaseSafeRebuildResult(result) {
|
|
457
|
+
const projectPath = (value) => path.basename(value);
|
|
458
|
+
return {
|
|
459
|
+
...result,
|
|
460
|
+
repoManagedArtifacts: [],
|
|
461
|
+
rebuildResults: result.rebuildResults.map((entry) => ({
|
|
462
|
+
...entry,
|
|
463
|
+
target: { ...entry.target, cwd: '.' },
|
|
464
|
+
removed: entry.removed.map(projectPath),
|
|
465
|
+
absent: entry.absent.map(projectPath),
|
|
466
|
+
residual: entry.residual.map(projectPath),
|
|
467
|
+
quarantined: entry.quarantined.map(projectPath),
|
|
468
|
+
})),
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
function namespacedPreflightError(message, targets, legacyTargets = []) {
|
|
472
|
+
return Object.assign(new Error(message), { namespacedTargets: targets, legacyTargets });
|
|
473
|
+
}
|
|
474
|
+
function selectedLegacyLiveReferences(references, platforms, scope) {
|
|
475
|
+
return references.filter((reference) => (reference.kind === 'legacyOwner' || reference.kind === 'legacyMarketplace')
|
|
476
|
+
&& reference.pluginName
|
|
477
|
+
&& reference.scope === scope
|
|
478
|
+
&& reference.platform
|
|
479
|
+
&& platforms.has(reference.platform));
|
|
480
|
+
}
|
|
481
|
+
function projectLegacyTargets(references) {
|
|
482
|
+
return [...new Map(references.map((reference) => {
|
|
483
|
+
const target = {
|
|
484
|
+
pluginName: reference.pluginName,
|
|
485
|
+
platform: reference.platform,
|
|
486
|
+
scope: reference.scope,
|
|
487
|
+
};
|
|
488
|
+
return [`${target.pluginName}\0${target.platform}\0${target.scope}`, target];
|
|
489
|
+
})).values()];
|
|
490
|
+
}
|
|
491
|
+
function exclusiveSkillRoot(options) {
|
|
492
|
+
if (options.scope === 'user') {
|
|
493
|
+
return path.join(options.platform === 'codex' ? getCodexHome(options.env) : getClaudeHome(options.env), 'skills');
|
|
494
|
+
}
|
|
495
|
+
const repoRoot = resolveRepoRootSync(options.cwd);
|
|
496
|
+
return path.join(repoRoot, options.platform === 'codex' ? '.agents' : '.claude', 'skills');
|
|
497
|
+
}
|
|
498
|
+
function resolveLiveCleanupTargets(options) {
|
|
499
|
+
const visible = options.references.filter((reference) => (reference.kind === 'namespacedOwner'
|
|
500
|
+
|| reference.kind === 'namespacedMarketplace'
|
|
501
|
+
|| reference.kind === 'namespacedLifecycle')
|
|
502
|
+
&& reference.sourceId
|
|
503
|
+
&& reference.sourceIdentity
|
|
504
|
+
&& reference.pluginName
|
|
505
|
+
&& reference.platform
|
|
506
|
+
&& options.platforms.includes(reference.platform)
|
|
507
|
+
&& reference.scope === options.scope);
|
|
508
|
+
const targets = [];
|
|
509
|
+
const selectors = options.selectors.map((value) => {
|
|
510
|
+
const parsed = parsePluginId(value);
|
|
511
|
+
const matchesByTarget = new Map();
|
|
512
|
+
for (const reference of visible.filter((entry) => entry.pluginName === parsed.pluginName
|
|
513
|
+
&& (parsed.sourceId === undefined || entry.sourceId === parsed.sourceId))) {
|
|
514
|
+
const liveNames = new Set(options.references.flatMap((candidate) => candidate.sourceId === reference.sourceId
|
|
515
|
+
&& candidate.sourceIdentity === reference.sourceIdentity
|
|
516
|
+
&& candidate.pluginName === reference.pluginName
|
|
517
|
+
&& candidate.platform === reference.platform
|
|
518
|
+
&& candidate.scope === reference.scope
|
|
519
|
+
&& candidate.marketplaceName
|
|
520
|
+
? [candidate.marketplaceName]
|
|
521
|
+
: []));
|
|
522
|
+
const registeredNames = canonicalMarketplaceRegistrationNames(options.references, reference.sourceId);
|
|
523
|
+
const unboundNativeNames = new Set(options.references.flatMap((candidate) => candidate.kind === 'namespacedMarketplace'
|
|
524
|
+
&& candidate.sourceId === undefined
|
|
525
|
+
&& candidate.pluginName === reference.pluginName
|
|
526
|
+
&& candidate.platform === reference.platform
|
|
527
|
+
&& candidate.scope === reference.scope
|
|
528
|
+
&& candidate.marketplaceName
|
|
529
|
+
? [candidate.marketplaceName]
|
|
530
|
+
: []));
|
|
531
|
+
const marketplaceName = liveNames.size === 1
|
|
532
|
+
? [...liveNames][0]
|
|
533
|
+
: liveNames.size === 0 && registeredNames.length === 1
|
|
534
|
+
? registeredNames[0]
|
|
535
|
+
: undefined;
|
|
536
|
+
const marketplaceIdentityUnresolved = liveNames.size > 1
|
|
537
|
+
|| (liveNames.size === 0 && registeredNames.length > 1)
|
|
538
|
+
|| (liveNames.size === 0 && registeredNames.length === 0 && unboundNativeNames.size > 0);
|
|
539
|
+
const target = {
|
|
540
|
+
pluginId: formatPluginId({ sourceId: reference.sourceId, pluginName: reference.pluginName }),
|
|
541
|
+
pluginName: reference.pluginName,
|
|
542
|
+
sourceId: reference.sourceId,
|
|
543
|
+
sourceIdentity: reference.sourceIdentity,
|
|
544
|
+
platform: reference.platform,
|
|
545
|
+
scope: reference.scope,
|
|
546
|
+
...(marketplaceName ? { marketplaceName } : {}),
|
|
547
|
+
...(marketplaceIdentityUnresolved ? { marketplaceIdentityUnresolved: true } : {}),
|
|
548
|
+
};
|
|
549
|
+
const key = [target.pluginId, target.sourceIdentity, target.platform, target.scope].join('\0');
|
|
550
|
+
const previous = matchesByTarget.get(key);
|
|
551
|
+
matchesByTarget.set(key, previous?.marketplaceName ? previous : target);
|
|
552
|
+
}
|
|
553
|
+
const matches = [...matchesByTarget.values()];
|
|
554
|
+
const identities = [...new Set(matches.map((target) => target.pluginId))];
|
|
555
|
+
if (parsed.sourceId === undefined && identities.length > 1) {
|
|
556
|
+
throw new Error(`pluginSelectorAmbiguous: Plugin "${parsed.pluginName}" has multiple live matches: ${identities.sort().join(', ')}.`);
|
|
557
|
+
}
|
|
558
|
+
targets.push(...matches);
|
|
559
|
+
return identities.length === 1 ? identities[0] : value;
|
|
560
|
+
});
|
|
561
|
+
return {
|
|
562
|
+
selectors,
|
|
563
|
+
targets: [...new Map(targets.map((target) => [[
|
|
564
|
+
target.pluginId, target.sourceIdentity, target.platform, target.scope,
|
|
565
|
+
].join('\0'), target])).values()],
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
async function discoverDamagedExclusiveCleanupTargets(options) {
|
|
569
|
+
const parsed = parsePluginId(options.selector);
|
|
570
|
+
if (!parsed.sourceId)
|
|
571
|
+
return [];
|
|
572
|
+
const targets = [];
|
|
573
|
+
for (const platform of options.platforms) {
|
|
574
|
+
const root = exclusiveSkillRoot({
|
|
575
|
+
platform,
|
|
576
|
+
scope: options.scope,
|
|
577
|
+
cwd: options.cwd,
|
|
578
|
+
env: options.env,
|
|
579
|
+
});
|
|
580
|
+
const entries = await fs.readdir(root, { withFileTypes: true }).catch(() => []);
|
|
581
|
+
for (const entry of entries) {
|
|
582
|
+
if (!entry.isDirectory() || entry.isSymbolicLink())
|
|
583
|
+
continue;
|
|
584
|
+
const markerPath = path.join(root, entry.name, '.agent-workflows-owner.json');
|
|
585
|
+
const markerStats = await fs.lstat(markerPath).catch(() => null);
|
|
586
|
+
if (!markerStats?.isFile() || markerStats.isSymbolicLink())
|
|
587
|
+
continue;
|
|
588
|
+
const raw = await fs.readJson(markerPath).catch(() => null);
|
|
589
|
+
if (!raw
|
|
590
|
+
|| raw.schemaVersion !== 2
|
|
591
|
+
|| raw.owner !== 'agent-workflows'
|
|
592
|
+
|| raw.sourceId !== parsed.sourceId
|
|
593
|
+
|| raw.plugin !== parsed.pluginName
|
|
594
|
+
|| raw.pluginId !== options.selector
|
|
595
|
+
|| raw.platform !== platform
|
|
596
|
+
|| raw.scope !== options.scope)
|
|
597
|
+
continue;
|
|
598
|
+
targets.push({
|
|
599
|
+
pluginId: options.selector,
|
|
600
|
+
pluginName: parsed.pluginName,
|
|
601
|
+
sourceId: parsed.sourceId,
|
|
602
|
+
sourceIdentity: typeof raw.sourceIdentity === 'string'
|
|
603
|
+
&& /^sha256:[0-9a-f]{64}$/u.test(raw.sourceIdentity)
|
|
604
|
+
? raw.sourceIdentity
|
|
605
|
+
: `sha256:${'0'.repeat(64)}`,
|
|
606
|
+
platform,
|
|
607
|
+
scope: raw.scope,
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
return [...new Map(targets.map((target) => [[target.platform, target.scope].join('\0'), target])).values()];
|
|
612
|
+
}
|
|
613
|
+
async function cleanupOfflineOwnedComponents(options) {
|
|
614
|
+
if (options.targets.some((target) => target.marketplaceIdentityUnresolved)) {
|
|
615
|
+
throw namespacedPreflightError('marketplaceIdentityUnavailable: Cannot uniquely recover the native marketplace name from live inventory or a canonical native registration path.', options.targets);
|
|
616
|
+
}
|
|
617
|
+
const results = [];
|
|
618
|
+
const warnings = [];
|
|
619
|
+
const context = {
|
|
620
|
+
env: options.env,
|
|
621
|
+
nativeCliRunner: options.nativeCliRunner ?? getDefaultNativeCliRunner(),
|
|
622
|
+
reporter: createNoopReporter(),
|
|
623
|
+
debugLogger: createNoopDebugLogger(),
|
|
624
|
+
};
|
|
625
|
+
const integration = createRebuildIntegration({ context });
|
|
626
|
+
const activeStore = createRebuildActiveStore({
|
|
627
|
+
env: options.env,
|
|
628
|
+
loadPlugin: (bundleRoot) => readPluginManifest(bundleRoot, { mode: 'bundle' }),
|
|
629
|
+
isLifecycleLeaseHeld: () => context.lifecycleLeaseHeld === true,
|
|
630
|
+
});
|
|
631
|
+
for (const target of options.targets) {
|
|
632
|
+
const exclusiveRecovery = {
|
|
633
|
+
removed: [], absent: [], residual: [], quarantined: [], failures: [],
|
|
634
|
+
};
|
|
635
|
+
if (options.force) {
|
|
636
|
+
const root = exclusiveSkillRoot({
|
|
637
|
+
platform: target.platform,
|
|
638
|
+
scope: target.scope,
|
|
639
|
+
cwd: options.cwd,
|
|
640
|
+
env: options.env,
|
|
641
|
+
});
|
|
642
|
+
const entries = await fs.readdir(root, { withFileTypes: true }).catch(() => []);
|
|
643
|
+
for (const entry of entries) {
|
|
644
|
+
if (!entry.isDirectory() || entry.isSymbolicLink())
|
|
645
|
+
continue;
|
|
646
|
+
const directory = path.join(root, entry.name);
|
|
647
|
+
let recovered;
|
|
648
|
+
try {
|
|
649
|
+
recovered = await cleanupCorruptExclusivePluginDirectory({
|
|
650
|
+
directory,
|
|
651
|
+
allowedRoot: root,
|
|
652
|
+
sourceId: target.sourceId,
|
|
653
|
+
pluginName: target.pluginName,
|
|
654
|
+
platform: target.platform,
|
|
655
|
+
scope: target.scope,
|
|
656
|
+
...options.corruptExclusiveDirectoryOperations,
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
catch (error) {
|
|
660
|
+
recovered = {
|
|
661
|
+
removed: [], absent: [], residual: [directory], quarantined: [],
|
|
662
|
+
failures: [{
|
|
663
|
+
label: directory,
|
|
664
|
+
phase: 'mutation',
|
|
665
|
+
message: error instanceof Error ? error.message : String(error),
|
|
666
|
+
}],
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
if (recovered) {
|
|
670
|
+
exclusiveRecovery.removed.push(...recovered.removed);
|
|
671
|
+
exclusiveRecovery.absent.push(...recovered.absent);
|
|
672
|
+
exclusiveRecovery.residual.push(...recovered.residual);
|
|
673
|
+
exclusiveRecovery.quarantined.push(...recovered.quarantined);
|
|
674
|
+
exclusiveRecovery.failures.push(...recovered.failures);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
const plugin = createSyntheticPlugin(target.pluginName, options.env);
|
|
679
|
+
plugin.sourceId = target.sourceId;
|
|
680
|
+
plugin.sourceIdentity = target.sourceIdentity;
|
|
681
|
+
plugin.pluginId = target.pluginId;
|
|
682
|
+
const marketplaceName = target.marketplaceName ?? 'aw';
|
|
683
|
+
plugin.marketplaceName = marketplaceName;
|
|
684
|
+
const desired = await integration.buildTarget({
|
|
685
|
+
sourceId: target.sourceId,
|
|
686
|
+
sourceIdentity: target.sourceIdentity,
|
|
687
|
+
pluginId: target.pluginId,
|
|
688
|
+
marketplaceName,
|
|
689
|
+
marketplaceRoot: path.join(resolveAwHome(options.env), 'marketplaces', target.sourceId),
|
|
690
|
+
plugin,
|
|
691
|
+
platform: target.platform,
|
|
692
|
+
scope: target.scope,
|
|
693
|
+
cwd: options.cwd,
|
|
694
|
+
command: 'cleanup',
|
|
695
|
+
catalog: {
|
|
696
|
+
rootDir: resolveAwHome(options.env),
|
|
697
|
+
source: 'local',
|
|
698
|
+
catalogVersion: '0.0.0',
|
|
699
|
+
channel: 'beta',
|
|
700
|
+
minAwVersion: '0.0.0',
|
|
701
|
+
},
|
|
702
|
+
includeHistoricalLifecycleArtifacts: false,
|
|
703
|
+
});
|
|
704
|
+
let result;
|
|
705
|
+
const operationLock = await activeStore.acquireOperation(desired.identity);
|
|
706
|
+
try {
|
|
707
|
+
const { acquireOperation: _acquireOperation, ...operationHeldStore } = activeStore;
|
|
708
|
+
result = await executeRebuildOperation({
|
|
709
|
+
command: 'cleanup',
|
|
710
|
+
target: desired,
|
|
711
|
+
driver: integration.driver,
|
|
712
|
+
activeStore: operationHeldStore,
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
finally {
|
|
716
|
+
await releaseRebuildOperationLease(operationLock);
|
|
717
|
+
}
|
|
718
|
+
const exclusiveResidual = (await Promise.all(exclusiveRecovery.residual.map(async (entry) => await fs.pathExists(entry) ? entry : null))).filter((entry) => entry !== null);
|
|
719
|
+
const exclusiveQuarantined = (await Promise.all(exclusiveRecovery.quarantined.map(async (entry) => await fs.pathExists(entry) ? entry : null))).filter((entry) => entry !== null);
|
|
720
|
+
const exclusiveFailures = (await Promise.all(exclusiveRecovery.failures.map(async (failure) => {
|
|
721
|
+
const residualPath = failure.quarantinePath ?? failure.label;
|
|
722
|
+
return await fs.pathExists(residualPath) ? failure : null;
|
|
723
|
+
}))).filter((failure) => failure !== null);
|
|
724
|
+
const removed = [...new Set([...result.removed, ...exclusiveRecovery.removed])];
|
|
725
|
+
const absent = [...new Set([...result.absent, ...exclusiveRecovery.absent])]
|
|
726
|
+
.filter((entry) => !removed.includes(entry));
|
|
727
|
+
result = {
|
|
728
|
+
...result,
|
|
729
|
+
removed,
|
|
730
|
+
absent,
|
|
731
|
+
residual: [...new Set([...result.residual, ...exclusiveResidual])],
|
|
732
|
+
quarantined: [...new Set([...result.quarantined, ...exclusiveQuarantined])],
|
|
733
|
+
};
|
|
734
|
+
if (exclusiveFailures.length > 0) {
|
|
735
|
+
const failures = exclusiveFailures.map((failure) => ({
|
|
736
|
+
phase: 'cleanup.owned',
|
|
737
|
+
label: failure.label,
|
|
738
|
+
message: `exclusiveRecoveryFailed: ${failure.phase} ${failure.label}: ${failure.message}`,
|
|
739
|
+
}));
|
|
740
|
+
const message = failures[0].message;
|
|
741
|
+
result = {
|
|
742
|
+
...result,
|
|
743
|
+
status: 'failed',
|
|
744
|
+
actions: [{ name: 'cleanup.owned', status: 'failed' }],
|
|
745
|
+
failures: [...result.failures, ...failures],
|
|
746
|
+
error: { phase: 'cleanup.owned', message },
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
results.push(result);
|
|
750
|
+
}
|
|
751
|
+
const obsoleteContracts = path.join(resolveAwHome(options.env), 'installation-contracts');
|
|
752
|
+
try {
|
|
753
|
+
await (options.removeObsoleteInstallationContracts ?? fs.remove)(obsoleteContracts);
|
|
754
|
+
}
|
|
755
|
+
catch (error) {
|
|
756
|
+
warnings.push(`obsoleteContractsCleanupFailed: ${error instanceof Error ? error.message : String(error)}`);
|
|
757
|
+
}
|
|
758
|
+
return leaseSafeRebuildResult({
|
|
759
|
+
platforms: [...new Set(results.map((result) => result.target.platform))],
|
|
760
|
+
plugins: results.filter((result) => result.status === 'succeeded').map((result) => result.target.pluginName),
|
|
761
|
+
warnings,
|
|
762
|
+
rebuildResults: results,
|
|
763
|
+
targetResults: results.map(toTargetResult),
|
|
764
|
+
overallState: results.every((result) => result.status === 'succeeded') ? 'succeeded' : 'failed',
|
|
765
|
+
nativePlugins: {}, repoManagedArtifacts: [],
|
|
766
|
+
receiptTargets: results.map((result) => ({
|
|
767
|
+
pluginName: result.target.pluginName,
|
|
768
|
+
pluginId: result.target.pluginId,
|
|
769
|
+
sourceId: result.target.sourceId,
|
|
770
|
+
platform: result.target.platform,
|
|
771
|
+
scope: result.target.scope,
|
|
772
|
+
})),
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
async function assertOfflineCleanupDependents(options) {
|
|
776
|
+
const inventory = await inventoryCatalogSourceReferences({
|
|
777
|
+
cwd: options.cwd,
|
|
778
|
+
env: options.env,
|
|
779
|
+
includeHistoricalProjects: true,
|
|
780
|
+
});
|
|
781
|
+
const currentProjectKey = await resolveCanonicalRepoProjectKey(options.cwd);
|
|
782
|
+
for (const target of options.targets) {
|
|
783
|
+
const pluginsRoot = path.join(resolveAwHome(options.env), 'marketplaces', target.sourceId, 'plugins');
|
|
784
|
+
const entries = await fs.readdir(pluginsRoot, { withFileTypes: true }).catch(() => []);
|
|
785
|
+
for (const entry of entries) {
|
|
786
|
+
if (!entry.isDirectory() || entry.name === target.pluginName)
|
|
787
|
+
continue;
|
|
788
|
+
const consumer = await readPluginManifest(path.join(pluginsRoot, entry.name), { mode: 'bundle' })
|
|
789
|
+
.catch(() => null);
|
|
790
|
+
if (!consumer?.manifest.dependencies?.includes(target.pluginName))
|
|
791
|
+
continue;
|
|
792
|
+
const consumerId = formatPluginId({ sourceId: target.sourceId, pluginName: consumer.manifest.name });
|
|
793
|
+
const live = inventory.references.some((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
|
|
794
|
+
&& reference.sourceId === target.sourceId
|
|
795
|
+
&& reference.sourceIdentity === target.sourceIdentity
|
|
796
|
+
&& reference.pluginName === consumer.manifest.name
|
|
797
|
+
&& reference.platform === target.platform
|
|
798
|
+
&& (target.scope === 'user' || reference.scope === 'project')
|
|
799
|
+
&& (target.scope === 'user' || reference.projectKey === currentProjectKey));
|
|
800
|
+
if (live) {
|
|
801
|
+
throw namespacedPreflightError(`dependencyStillRequired: ${target.pluginId} is required by ${consumerId}.`, options.targets);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
export async function runRebuildCommand(options) {
|
|
807
|
+
if (options.runtime?.catalogResolution && options.runtime.bypassDependencyPlan) {
|
|
808
|
+
return runSingleSourceRebuildCommand(options);
|
|
809
|
+
}
|
|
810
|
+
const runtimeEnv = options.runtime?.env ?? process.env;
|
|
811
|
+
let requestedPluginNames = options.pluginNames;
|
|
812
|
+
const cleanupForce = options.command === 'cleanup'
|
|
813
|
+
&& options.commandOptions.force === true;
|
|
814
|
+
let cleanupInventory;
|
|
815
|
+
let cleanupLiveTargets = [];
|
|
816
|
+
let cleanupHasDamagedExclusiveTarget = false;
|
|
817
|
+
let liveTargets = [];
|
|
818
|
+
let legacyLiveTargets = [];
|
|
819
|
+
if (options.command === 'cleanup' && !options.all) {
|
|
820
|
+
cleanupInventory = await inventoryCatalogSourceReferences({
|
|
821
|
+
cwd: options.commandOptions.cwd,
|
|
822
|
+
env: runtimeEnv,
|
|
823
|
+
});
|
|
824
|
+
const live = resolveLiveCleanupTargets({
|
|
825
|
+
selectors: requestedPluginNames,
|
|
826
|
+
platforms: selectedPlatforms(options.commandOptions.platform),
|
|
827
|
+
scope: options.commandOptions.scope,
|
|
828
|
+
references: cleanupInventory.references,
|
|
829
|
+
});
|
|
830
|
+
requestedPluginNames = live.selectors;
|
|
831
|
+
cleanupLiveTargets = live.targets;
|
|
832
|
+
if (cleanupForce) {
|
|
833
|
+
const damagedTargets = (await Promise.all(requestedPluginNames.map(async (selector) => parsePluginId(selector).sourceId
|
|
834
|
+
? discoverDamagedExclusiveCleanupTargets({
|
|
835
|
+
selector,
|
|
836
|
+
platforms: selectedPlatforms(options.commandOptions.platform),
|
|
837
|
+
scope: options.commandOptions.scope,
|
|
838
|
+
cwd: options.commandOptions.cwd,
|
|
839
|
+
env: runtimeEnv,
|
|
840
|
+
})
|
|
841
|
+
: []))).flat();
|
|
842
|
+
cleanupHasDamagedExclusiveTarget = damagedTargets.length > 0;
|
|
843
|
+
cleanupLiveTargets = [...new Map([
|
|
844
|
+
...damagedTargets,
|
|
845
|
+
...cleanupLiveTargets,
|
|
846
|
+
].map((target) => [[target.pluginId, target.platform, target.scope].join('\0'), target])).values()];
|
|
847
|
+
}
|
|
848
|
+
liveTargets = cleanupLiveTargets;
|
|
849
|
+
}
|
|
850
|
+
if (cleanupHasDamagedExclusiveTarget) {
|
|
851
|
+
return cleanupOfflineOwnedComponents({
|
|
852
|
+
targets: cleanupLiveTargets,
|
|
853
|
+
cwd: options.commandOptions.cwd,
|
|
854
|
+
env: runtimeEnv,
|
|
855
|
+
force: true,
|
|
856
|
+
removeObsoleteInstallationContracts: options.runtime?.removeObsoleteInstallationContracts,
|
|
857
|
+
nativeCliRunner: options.runtime?.nativeCliRunner,
|
|
858
|
+
corruptExclusiveDirectoryOperations: options.runtime?.corruptExclusiveDirectoryOperations,
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
if (options.all) {
|
|
862
|
+
const inventory = await inventoryCatalogSourceReferences({
|
|
863
|
+
cwd: options.commandOptions.cwd,
|
|
864
|
+
env: runtimeEnv,
|
|
865
|
+
});
|
|
866
|
+
if (options.command !== 'cleanup')
|
|
867
|
+
assertCatalogSourceInventoryComplete(inventory);
|
|
868
|
+
const requestedPlatforms = new Set(selectedPlatforms(options.commandOptions.platform));
|
|
869
|
+
legacyLiveTargets = projectLegacyTargets(selectedLegacyLiveReferences(inventory.references, requestedPlatforms, options.commandOptions.scope));
|
|
870
|
+
const live = inventory.references.filter((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
|
|
871
|
+
&& reference.sourceId
|
|
872
|
+
&& reference.pluginName
|
|
873
|
+
&& reference.scope === options.commandOptions.scope
|
|
874
|
+
&& reference.platform
|
|
875
|
+
&& requestedPlatforms.has(reference.platform));
|
|
876
|
+
const projectedTargets = [...new Map(live.map((reference) => {
|
|
877
|
+
const target = {
|
|
878
|
+
pluginId: formatPluginId({
|
|
879
|
+
sourceId: reference.sourceId,
|
|
880
|
+
pluginName: reference.pluginName,
|
|
881
|
+
}),
|
|
882
|
+
pluginName: reference.pluginName,
|
|
883
|
+
sourceId: reference.sourceId,
|
|
884
|
+
sourceIdentity: reference.sourceIdentity ?? 'unavailable',
|
|
885
|
+
platform: reference.platform,
|
|
886
|
+
scope: reference.scope,
|
|
887
|
+
};
|
|
888
|
+
return [[
|
|
889
|
+
target.pluginId,
|
|
890
|
+
target.sourceIdentity,
|
|
891
|
+
target.platform,
|
|
892
|
+
target.scope,
|
|
893
|
+
].join('\0'), target];
|
|
894
|
+
})).values()];
|
|
895
|
+
liveTargets = projectedTargets;
|
|
896
|
+
const identities = new Map();
|
|
897
|
+
for (const reference of live) {
|
|
898
|
+
if (!reference.sourceIdentity) {
|
|
899
|
+
throw namespacedPreflightError(`legacyStateUnsupported: ${reference.location} lacks a schema 2 source identity.`, projectedTargets, legacyLiveTargets);
|
|
900
|
+
}
|
|
901
|
+
const pluginId = formatPluginId({ sourceId: reference.sourceId, pluginName: reference.pluginName });
|
|
902
|
+
const previous = identities.get(pluginId);
|
|
903
|
+
if (previous && previous !== reference.sourceIdentity) {
|
|
904
|
+
throw namespacedPreflightError(`sourceChanged: ${pluginId} live targets have different source identities.`, projectedTargets, legacyLiveTargets);
|
|
905
|
+
}
|
|
906
|
+
identities.set(pluginId, reference.sourceIdentity);
|
|
907
|
+
}
|
|
908
|
+
requestedPluginNames = [...identities.keys()];
|
|
909
|
+
}
|
|
910
|
+
const selectors = requestedPluginNames.map(parsePluginId);
|
|
911
|
+
const sourceIds = planPluginSelectorSourceIds(selectors);
|
|
912
|
+
if (options.all && selectors.length === 0) {
|
|
913
|
+
if (legacyLiveTargets.length > 0) {
|
|
914
|
+
throw namespacedPreflightError(`legacyStateUnsupported: legacy live runtime state exists for ${legacyLiveTargets.map((target) => `${target.pluginName}:${target.platform}/${target.scope}`).join(', ')}.`, [], legacyLiveTargets);
|
|
915
|
+
}
|
|
916
|
+
return mergeRebuildCommandResults([]);
|
|
917
|
+
}
|
|
918
|
+
try {
|
|
919
|
+
const resolvedResult = await withResolvedMultiSourceCatalog({
|
|
920
|
+
cliVersion: resolveRuntimeCliVersion(),
|
|
921
|
+
freshnessPolicy: options.command === 'cleanup' ? 'cacheFirst' : 'requireRemote',
|
|
922
|
+
...(sourceIds ? { sourceIds } : {}),
|
|
923
|
+
env: runtimeEnv,
|
|
924
|
+
consume: async (catalog) => {
|
|
925
|
+
const failedSources = catalog.sources.filter((source) => source.error);
|
|
926
|
+
if (failedSources.length > 0) {
|
|
927
|
+
throw namespacedPreflightError(`Cannot resolve required catalog sources: ${failedSources.map((source) => source.sourceId).join(', ')}.`, liveTargets, legacyLiveTargets);
|
|
928
|
+
}
|
|
929
|
+
const available = (await Promise.all(catalog.sources.map(async (item) => {
|
|
930
|
+
const source = item.resolution;
|
|
931
|
+
const plugins = await resolvePluginsFromCatalog(source.rootDir, undefined);
|
|
932
|
+
return plugins.map((plugin) => {
|
|
933
|
+
const pluginId = formatPluginId({ sourceId: source.sourceId, pluginName: plugin.manifest.name });
|
|
934
|
+
plugin.sourceId = source.sourceId;
|
|
935
|
+
plugin.sourceIdentity = source.sourceIdentity;
|
|
936
|
+
plugin.pluginId = pluginId;
|
|
937
|
+
return { source, plugin, pluginId };
|
|
938
|
+
});
|
|
939
|
+
}))).flat();
|
|
940
|
+
const selected = selectors.map((selector, index) => {
|
|
941
|
+
const matches = available.filter((entry) => entry.plugin.manifest.name === selector.pluginName
|
|
942
|
+
&& (selector.sourceId === undefined || entry.source.sourceId === selector.sourceId));
|
|
943
|
+
if (matches.length === 0) {
|
|
944
|
+
throw new Error(`Plugin "${requestedPluginNames[index]}" does not exist in the required catalog source set.`);
|
|
945
|
+
}
|
|
946
|
+
if (matches.length > 1) {
|
|
947
|
+
throw new Error(`Plugin "${selector.pluginName}" is ambiguous across sources: ${matches.map((entry) => entry.source.sourceId).join(', ')}.`);
|
|
948
|
+
}
|
|
949
|
+
return matches[0];
|
|
950
|
+
});
|
|
951
|
+
const dependencyEnabled = options.command === 'install'
|
|
952
|
+
|| options.command === 'upgrade'
|
|
953
|
+
|| options.command === 'reinstall';
|
|
954
|
+
const selectedIds = new Set(selected.map((entry) => entry.pluginId));
|
|
955
|
+
const resolveClosureEntries = (rootsBySource) => catalog.sources.flatMap((item) => {
|
|
956
|
+
const source = item.resolution;
|
|
957
|
+
const roots = rootsBySource
|
|
958
|
+
.filter((entry) => entry.source.sourceId === source.sourceId)
|
|
959
|
+
.map((entry) => entry.plugin.manifest.name);
|
|
960
|
+
if (roots.length === 0)
|
|
961
|
+
return [];
|
|
962
|
+
const sourcePlugins = available
|
|
963
|
+
.filter((entry) => entry.source.sourceId === source.sourceId)
|
|
964
|
+
.map((entry) => entry.plugin);
|
|
965
|
+
const closure = resolvePluginMetaDependencyClosure(sourcePlugins, roots);
|
|
966
|
+
return closure.map((plugin) => available.find((entry) => entry.source.sourceId === source.sourceId
|
|
967
|
+
&& entry.plugin.manifest.name === plugin.manifest.name));
|
|
968
|
+
});
|
|
969
|
+
const closureEntriesByPlatform = new Map();
|
|
970
|
+
if (dependencyEnabled) {
|
|
971
|
+
for (const platform of selectedPlatforms(options.commandOptions.platform)) {
|
|
972
|
+
const platformRoots = options.commandOptions.platform === 'both'
|
|
973
|
+
? selected.filter((entry) => supportsPlatform(entry.plugin.manifest, platform))
|
|
974
|
+
: selected;
|
|
975
|
+
closureEntriesByPlatform.set(platform, resolveClosureEntries(platformRoots));
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
const closureEntries = dependencyEnabled
|
|
979
|
+
? [...new Map([...closureEntriesByPlatform.values()].flat().map((entry) => [entry.pluginId, entry])).values()]
|
|
980
|
+
: selected;
|
|
981
|
+
const rawExecutionSelections = options.all
|
|
982
|
+
? liveTargets.flatMap((target) => {
|
|
983
|
+
const entry = selected.find((candidate) => candidate.pluginId === target.pluginId);
|
|
984
|
+
if (entry.source.sourceIdentity !== target.sourceIdentity) {
|
|
985
|
+
throw namespacedPreflightError(`sourceChanged: ${target.pluginId} live target has a different source identity.`, liveTargets, legacyLiveTargets);
|
|
986
|
+
}
|
|
987
|
+
const sourcePlugins = available
|
|
988
|
+
.filter((candidate) => candidate.source.sourceId === entry.source.sourceId)
|
|
989
|
+
.map((candidate) => candidate.plugin);
|
|
990
|
+
return resolvePluginMetaDependencyClosure(sourcePlugins, [entry.plugin.manifest.name]).map((plugin) => ({
|
|
991
|
+
entry: available.find((candidate) => candidate.source.sourceId === entry.source.sourceId
|
|
992
|
+
&& candidate.plugin.manifest.name === plugin.manifest.name),
|
|
993
|
+
platform: target.platform,
|
|
994
|
+
}));
|
|
995
|
+
})
|
|
996
|
+
: selectedPlatforms(options.commandOptions.platform).flatMap((platform) => (dependencyEnabled ? closureEntriesByPlatform.get(platform) ?? [] : closureEntries)
|
|
997
|
+
.flatMap((entry) => options.command !== 'cleanup'
|
|
998
|
+
&& options.command !== 'uninstall'
|
|
999
|
+
&& options.commandOptions.platform === 'both'
|
|
1000
|
+
&& !supportsPlatform(entry.plugin.manifest, platform)
|
|
1001
|
+
? []
|
|
1002
|
+
: [{ entry, platform }]));
|
|
1003
|
+
let executionSelections = [...new Map(rawExecutionSelections.map((selection) => [[
|
|
1004
|
+
selection.entry.pluginId,
|
|
1005
|
+
selection.entry.source.sourceIdentity,
|
|
1006
|
+
selection.platform,
|
|
1007
|
+
options.commandOptions.scope,
|
|
1008
|
+
].join('\0'), selection])).values()];
|
|
1009
|
+
const preflightTargets = executionSelections.map(({ entry, platform }) => ({
|
|
1010
|
+
pluginId: entry.pluginId,
|
|
1011
|
+
pluginName: entry.plugin.manifest.name,
|
|
1012
|
+
sourceId: entry.source.sourceId,
|
|
1013
|
+
sourceIdentity: entry.source.sourceIdentity,
|
|
1014
|
+
pluginVersion: entry.plugin.manifest.version,
|
|
1015
|
+
platform,
|
|
1016
|
+
scope: options.commandOptions.scope,
|
|
1017
|
+
}));
|
|
1018
|
+
const stateInventory = await inventoryCatalogSourceReferences({
|
|
1019
|
+
cwd: options.commandOptions.cwd,
|
|
1020
|
+
env: runtimeEnv,
|
|
1021
|
+
});
|
|
1022
|
+
if (options.command !== 'cleanup')
|
|
1023
|
+
assertCatalogSourceInventoryComplete(stateInventory);
|
|
1024
|
+
const commandProjectKey = await resolveCanonicalRepoProjectKey(options.commandOptions.cwd);
|
|
1025
|
+
const selectedLegacy = selectedLegacyLiveReferences(stateInventory.references, new Set(executionSelections.map((selection) => selection.platform)), options.commandOptions.scope);
|
|
1026
|
+
const legacy = options.all
|
|
1027
|
+
? selectedLegacy
|
|
1028
|
+
: selectedLegacy.filter((reference) => executionSelections.some((selection) => selection.entry.plugin.manifest.name === reference.pluginName
|
|
1029
|
+
&& selection.platform === reference.platform));
|
|
1030
|
+
if (legacy.length > 0) {
|
|
1031
|
+
const blockingLegacyTargets = projectLegacyTargets(legacy);
|
|
1032
|
+
throw namespacedPreflightError(`legacyStateUnsupported: legacy live runtime state exists at ${legacy.map((reference) => reference.location).join(', ')}.`, preflightTargets, blockingLegacyTargets);
|
|
1033
|
+
}
|
|
1034
|
+
for (const entry of closureEntries) {
|
|
1035
|
+
const changed = stateInventory.references.find((reference) => reference.sourceId === entry.source.sourceId
|
|
1036
|
+
&& reference.sourceIdentity
|
|
1037
|
+
&& reference.sourceIdentity !== entry.source.sourceIdentity);
|
|
1038
|
+
if (changed) {
|
|
1039
|
+
throw namespacedPreflightError(`sourceChanged: ${entry.source.sourceId} state at ${changed.location} has a different source identity.`, options.all
|
|
1040
|
+
? preflightTargets
|
|
1041
|
+
: preflightTargets.filter((target) => target.pluginId === entry.pluginId));
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
const marketplaceNamesBySource = new Map();
|
|
1045
|
+
for (const entry of new Map(closureEntries.map((candidate) => [
|
|
1046
|
+
candidate.source.sourceId,
|
|
1047
|
+
candidate,
|
|
1048
|
+
])).values()) {
|
|
1049
|
+
const sourceNames = new Set(stateInventory.references.flatMap((reference) => (reference.kind === 'namespacedOwner' || reference.kind === 'namespacedMarketplace')
|
|
1050
|
+
&& reference.sourceId === entry.source.sourceId
|
|
1051
|
+
&& (reference.sourceIdentity === undefined
|
|
1052
|
+
|| reference.sourceIdentity === entry.source.sourceIdentity)
|
|
1053
|
+
&& reference.marketplaceName
|
|
1054
|
+
? [reference.marketplaceName]
|
|
1055
|
+
: []));
|
|
1056
|
+
if (sourceNames.size > 1) {
|
|
1057
|
+
throw new Error('marketplaceIdentityUnavailable: Multiple canonical native marketplace registrations match the source.');
|
|
1058
|
+
}
|
|
1059
|
+
const persistedName = [...sourceNames][0];
|
|
1060
|
+
const marketplaceRoot = path.join(resolveAwHome(runtimeEnv), 'marketplaces', entry.source.sourceId);
|
|
1061
|
+
let marketplaceName = persistedName
|
|
1062
|
+
?? (entry.source.sourceId === catalog.primarySourceId
|
|
1063
|
+
? 'aw'
|
|
1064
|
+
: getNamespacedMarketplaceName(entry.source.sourceId));
|
|
1065
|
+
if (options.command === 'cleanup' || options.command === 'uninstall') {
|
|
1066
|
+
marketplaceNamesBySource.set(entry.source.sourceId, marketplaceName);
|
|
1067
|
+
continue;
|
|
1068
|
+
}
|
|
1069
|
+
let registrations = await inspectNativeMarketplaceRegistrations({
|
|
1070
|
+
marketplaceName,
|
|
1071
|
+
marketplaceRoot,
|
|
1072
|
+
cwd: options.commandOptions.cwd,
|
|
1073
|
+
env: runtimeEnv,
|
|
1074
|
+
});
|
|
1075
|
+
if (!persistedName
|
|
1076
|
+
&& marketplaceName === 'aw'
|
|
1077
|
+
&& Object.values(registrations).includes('foreign')) {
|
|
1078
|
+
marketplaceName = getNamespacedMarketplaceName(entry.source.sourceId);
|
|
1079
|
+
registrations = await inspectNativeMarketplaceRegistrations({
|
|
1080
|
+
marketplaceName,
|
|
1081
|
+
marketplaceRoot,
|
|
1082
|
+
cwd: options.commandOptions.cwd,
|
|
1083
|
+
env: runtimeEnv,
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
const foreignPlatforms = Object.entries(registrations).flatMap(([platform, state]) => state === 'foreign' ? [platform] : []);
|
|
1087
|
+
if (foreignPlatforms.length > 0) {
|
|
1088
|
+
throw new Error(`externalOwnershipPresent: Marketplace ${marketplaceName} is foreign on ${foreignPlatforms.join(', ')}.`);
|
|
1089
|
+
}
|
|
1090
|
+
marketplaceNamesBySource.set(entry.source.sourceId, marketplaceName);
|
|
1091
|
+
}
|
|
1092
|
+
const marketplaceNameFor = (entry, ..._placement) => {
|
|
1093
|
+
const marketplaceName = marketplaceNamesBySource.get(entry.source.sourceId);
|
|
1094
|
+
if (!marketplaceName) {
|
|
1095
|
+
throw new Error('marketplaceIdentityUnavailable: No marketplace name was selected for the source.');
|
|
1096
|
+
}
|
|
1097
|
+
return marketplaceName;
|
|
1098
|
+
};
|
|
1099
|
+
const executionContext = {
|
|
1100
|
+
env: runtimeEnv,
|
|
1101
|
+
nativeCliRunner: options.runtime?.nativeCliRunner ?? getDefaultNativeCliRunner(),
|
|
1102
|
+
reporter: options.runtime?.reporter ?? createNoopReporter(),
|
|
1103
|
+
debugLogger: options.runtime?.debugLogger ?? createNoopDebugLogger(),
|
|
1104
|
+
runtimeLeaseHeld: options.runtime?.runtimeLeaseHeld,
|
|
1105
|
+
lifecycleLeaseHeld: options.runtime?.lifecycleLeaseHeld,
|
|
1106
|
+
expectedCatalogConfigDigest: catalog.configDigest,
|
|
1107
|
+
};
|
|
1108
|
+
const inspection = createRebuildIntegration({
|
|
1109
|
+
context: executionContext,
|
|
1110
|
+
scriptTimeoutMs: options.commandOptions.scriptTimeoutMs,
|
|
1111
|
+
});
|
|
1112
|
+
const createPlan = async () => {
|
|
1113
|
+
const inventory = await inventoryCatalogSourceReferences({
|
|
1114
|
+
cwd: options.commandOptions.cwd,
|
|
1115
|
+
env: runtimeEnv,
|
|
1116
|
+
});
|
|
1117
|
+
if (options.command !== 'cleanup')
|
|
1118
|
+
assertCatalogSourceInventoryComplete(inventory);
|
|
1119
|
+
const targets = [];
|
|
1120
|
+
for (const [order, { entry, platform }] of executionSelections.entries()) {
|
|
1121
|
+
const relation = selectedIds.has(entry.pluginId) ? 'requested' : 'dependency';
|
|
1122
|
+
let resolvedScope = options.commandOptions.scope;
|
|
1123
|
+
const inspectScope = async (scope) => {
|
|
1124
|
+
const marketplaceName = marketplaceNameFor(entry, platform, scope);
|
|
1125
|
+
entry.plugin.marketplaceName = marketplaceName;
|
|
1126
|
+
const desired = await inspection.buildTarget({
|
|
1127
|
+
sourceId: entry.source.sourceId,
|
|
1128
|
+
sourceIdentity: entry.source.sourceIdentity,
|
|
1129
|
+
pluginId: entry.pluginId,
|
|
1130
|
+
marketplaceName,
|
|
1131
|
+
marketplaceRoot: path.join(resolveAwHome(runtimeEnv), 'marketplaces', entry.source.sourceId),
|
|
1132
|
+
plugin: entry.plugin,
|
|
1133
|
+
platform,
|
|
1134
|
+
scope,
|
|
1135
|
+
cwd: options.commandOptions.cwd,
|
|
1136
|
+
command: options.command,
|
|
1137
|
+
catalog: toCatalogResolution(entry.source),
|
|
1138
|
+
includeHistoricalLifecycleArtifacts: false,
|
|
1139
|
+
readOnlyInspectionPlan: true,
|
|
1140
|
+
});
|
|
1141
|
+
const result = await inspectOwnedComponents({
|
|
1142
|
+
components: desired.ownedComponents,
|
|
1143
|
+
nativeProbe: inspection.driver.probeNative,
|
|
1144
|
+
verifyHealth: true,
|
|
1145
|
+
});
|
|
1146
|
+
if (result.state === 'error'
|
|
1147
|
+
|| result.components.some((component) => component.state === 'error'))
|
|
1148
|
+
return result;
|
|
1149
|
+
const required = new Set(desired.desiredOwnedComponents ?? desired.ownedComponents);
|
|
1150
|
+
const optional = new Set(desired.optionalOwnedComponents ?? []);
|
|
1151
|
+
const presentRequired = [...required].every((component) => result.components.some((entry) => entry.component === component && entry.state === 'present'));
|
|
1152
|
+
const hasUnexpectedPresent = result.components.some((entry) => entry.state === 'present' && !required.has(entry.component) && !optional.has(entry.component));
|
|
1153
|
+
const hasPartial = result.components.some((entry) => entry.state === 'partial');
|
|
1154
|
+
const hasAnyPresent = result.components.some((entry) => entry.state === 'present');
|
|
1155
|
+
const state = !hasAnyPresent
|
|
1156
|
+
&& result.components.every((entry) => entry.state === 'absent')
|
|
1157
|
+
? 'absent'
|
|
1158
|
+
: hasPartial || hasUnexpectedPresent || !presentRequired
|
|
1159
|
+
? 'partial'
|
|
1160
|
+
: required.size > 0
|
|
1161
|
+
? 'present'
|
|
1162
|
+
: hasAnyPresent ? 'present' : 'absent';
|
|
1163
|
+
return { ...result, state };
|
|
1164
|
+
};
|
|
1165
|
+
const [requestedInspection, otherInspection] = await Promise.all([
|
|
1166
|
+
inspectScope(resolvedScope),
|
|
1167
|
+
inspectScope(resolvedScope === 'user' ? 'project' : 'user'),
|
|
1168
|
+
]);
|
|
1169
|
+
let state = requestedInspection.state;
|
|
1170
|
+
let action = relation === 'requested'
|
|
1171
|
+
? options.command
|
|
1172
|
+
: options.command === 'reinstall' ? 'reinstall' : 'upgrade';
|
|
1173
|
+
let errorCode;
|
|
1174
|
+
const hasForeignCollision = [...requestedInspection.components, ...otherInspection.components]
|
|
1175
|
+
.some((component) => component.diagnostic?.includes('foreign collision'));
|
|
1176
|
+
if (dependencyEnabled && hasForeignCollision) {
|
|
1177
|
+
action = 'block';
|
|
1178
|
+
errorCode = 'artifactCollision';
|
|
1179
|
+
}
|
|
1180
|
+
else if (dependencyEnabled && relation === 'requested'
|
|
1181
|
+
&& (requestedInspection.state === 'error'
|
|
1182
|
+
|| (requestedInspection.state === 'partial' && options.command !== 'reinstall'))) {
|
|
1183
|
+
action = 'block';
|
|
1184
|
+
errorCode = 'dependencyNotReady';
|
|
1185
|
+
}
|
|
1186
|
+
if (!hasForeignCollision && relation === 'dependency'
|
|
1187
|
+
&& requestedInspection.state === 'present'
|
|
1188
|
+
&& otherInspection.state === 'present') {
|
|
1189
|
+
action = 'block';
|
|
1190
|
+
state = 'partial';
|
|
1191
|
+
errorCode = 'dependencyScopeConflict';
|
|
1192
|
+
}
|
|
1193
|
+
else if (!hasForeignCollision && relation === 'dependency'
|
|
1194
|
+
&& options.commandOptions.scope === 'project'
|
|
1195
|
+
&& otherInspection.state === 'present') {
|
|
1196
|
+
resolvedScope = 'user';
|
|
1197
|
+
state = 'present';
|
|
1198
|
+
}
|
|
1199
|
+
else if (!hasForeignCollision && relation === 'dependency'
|
|
1200
|
+
&& options.commandOptions.scope === 'project'
|
|
1201
|
+
&& (otherInspection.state === 'partial' || otherInspection.state === 'error')) {
|
|
1202
|
+
resolvedScope = 'user';
|
|
1203
|
+
state = otherInspection.state;
|
|
1204
|
+
if (otherInspection.state === 'error') {
|
|
1205
|
+
action = 'block';
|
|
1206
|
+
errorCode = 'dependencyNotReady';
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
else if (!hasForeignCollision && relation === 'dependency'
|
|
1210
|
+
&& options.commandOptions.scope === 'user'
|
|
1211
|
+
&& otherInspection.state !== 'absent') {
|
|
1212
|
+
action = 'block';
|
|
1213
|
+
errorCode = 'dependencyScopeTooNarrow';
|
|
1214
|
+
}
|
|
1215
|
+
const resolvedInspection = resolvedScope === options.commandOptions.scope
|
|
1216
|
+
? requestedInspection
|
|
1217
|
+
: otherInspection;
|
|
1218
|
+
state = resolvedInspection.state;
|
|
1219
|
+
if (!hasForeignCollision && !errorCode
|
|
1220
|
+
&& relation === 'dependency' && options.command === 'install') {
|
|
1221
|
+
action = state === 'present' ? 'keep' : state === 'partial' ? 'reinstall' : 'install';
|
|
1222
|
+
}
|
|
1223
|
+
if (!hasForeignCollision && relation === 'dependency'
|
|
1224
|
+
&& resolvedInspection.state === 'error') {
|
|
1225
|
+
action = 'block';
|
|
1226
|
+
state = resolvedInspection.state;
|
|
1227
|
+
errorCode ??= 'dependencyNotReady';
|
|
1228
|
+
}
|
|
1229
|
+
if (!hasForeignCollision && relation === 'dependency'
|
|
1230
|
+
&& platform === 'codex'
|
|
1231
|
+
&& resolvedScope === 'project'
|
|
1232
|
+
&& (entry.plugin.manifest.apps || !hasCodexProjectManagedArtifacts(entry.plugin))) {
|
|
1233
|
+
action = 'block';
|
|
1234
|
+
errorCode = 'dependencyTargetUnsupported';
|
|
1235
|
+
}
|
|
1236
|
+
if (entry.plugin.manifest.config?.schema
|
|
1237
|
+
&& (action === 'install' || action === 'upgrade' || action === 'reinstall')) {
|
|
1238
|
+
const effective = await resolveEffectivePluginConfig({
|
|
1239
|
+
sourceId: entry.source.sourceId,
|
|
1240
|
+
sourceIdentity: entry.source.sourceIdentity,
|
|
1241
|
+
pluginName: entry.plugin.manifest.name,
|
|
1242
|
+
manifest: entry.plugin.manifest,
|
|
1243
|
+
cwd: options.commandOptions.cwd,
|
|
1244
|
+
env: runtimeEnv,
|
|
1245
|
+
});
|
|
1246
|
+
if (effective.issues.length > 0) {
|
|
1247
|
+
action = 'block';
|
|
1248
|
+
errorCode = 'invalidConfig';
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
targets.push({
|
|
1252
|
+
pluginId: entry.pluginId,
|
|
1253
|
+
pluginName: entry.plugin.manifest.name,
|
|
1254
|
+
platform,
|
|
1255
|
+
requestedScope: options.commandOptions.scope,
|
|
1256
|
+
resolvedScope,
|
|
1257
|
+
relation,
|
|
1258
|
+
requiredBy: executionSelections.filter((candidate) => candidate.platform === platform
|
|
1259
|
+
&& candidate.entry.source.sourceId === entry.source.sourceId
|
|
1260
|
+
&& candidate.entry.plugin.manifest.dependencies?.includes(entry.plugin.manifest.name))
|
|
1261
|
+
.map((candidate) => candidate.entry.pluginId).sort(),
|
|
1262
|
+
state,
|
|
1263
|
+
action,
|
|
1264
|
+
order,
|
|
1265
|
+
...(errorCode ? { errorCode } : {}),
|
|
1266
|
+
});
|
|
1267
|
+
}
|
|
1268
|
+
return createDependencyOperationPlan({
|
|
1269
|
+
requestedPluginIds: selected.map((entry) => entry.pluginId),
|
|
1270
|
+
resolvedPluginIds: closureEntries.map((entry) => entry.pluginId),
|
|
1271
|
+
dependencyEdges: closureEntries.flatMap((entry) => (entry.plugin.manifest.dependencies ?? []).map((dependency) => ({
|
|
1272
|
+
from: entry.pluginId,
|
|
1273
|
+
to: formatPluginId({ sourceId: entry.source.sourceId, pluginName: dependency }),
|
|
1274
|
+
}))),
|
|
1275
|
+
targets,
|
|
1276
|
+
});
|
|
1277
|
+
};
|
|
1278
|
+
if (options.runtime?.previewDependencyPlanOnly) {
|
|
1279
|
+
const initialPlan = await createPlan();
|
|
1280
|
+
const preview = mergeRebuildCommandResults([]);
|
|
1281
|
+
preview.dependencyPlan = initialPlan;
|
|
1282
|
+
return preview;
|
|
1283
|
+
}
|
|
1284
|
+
for (const { entry, platform } of executionSelections.filter((selection) => selectedIds.has(selection.entry.pluginId))) {
|
|
1285
|
+
await options.runtime?.reviewPreflight?.({
|
|
1286
|
+
command: options.command,
|
|
1287
|
+
identity: {
|
|
1288
|
+
sourceId: entry.source.sourceId,
|
|
1289
|
+
sourceIdentity: entry.source.sourceIdentity,
|
|
1290
|
+
pluginId: entry.pluginId,
|
|
1291
|
+
pluginName: entry.plugin.manifest.name,
|
|
1292
|
+
pluginVersion: entry.plugin.manifest.version,
|
|
1293
|
+
platform,
|
|
1294
|
+
scope: options.commandOptions.scope,
|
|
1295
|
+
cwd: options.commandOptions.cwd,
|
|
1296
|
+
},
|
|
1297
|
+
configDigest: catalog.configDigest,
|
|
1298
|
+
sourceId: entry.source.sourceId,
|
|
1299
|
+
sourceIdentity: entry.source.sourceIdentity,
|
|
1300
|
+
resolvedCommit: entry.source.resolvedCommit,
|
|
1301
|
+
manifestDigest: entry.source.manifestDigest,
|
|
1302
|
+
snapshotDigest: entry.source.snapshotDigest,
|
|
1303
|
+
contentDigest: entry.source.manifest.entries.find((candidate) => candidate.name === entry.plugin.manifest.name)?.contentDigest,
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
const lockedPlan = await createPlan();
|
|
1307
|
+
for (const pluginName of new Set(lockedPlan.targets.flatMap((target) => target.platform === 'claude'
|
|
1308
|
+
&& (target.action === 'install'
|
|
1309
|
+
|| target.action === 'upgrade'
|
|
1310
|
+
|| target.action === 'reinstall')
|
|
1311
|
+
? [target.pluginName]
|
|
1312
|
+
: []))) {
|
|
1313
|
+
await assertNoClaudeUnboundNativeNameCollision({
|
|
1314
|
+
pluginName,
|
|
1315
|
+
cwd: options.commandOptions.cwd,
|
|
1316
|
+
env: runtimeEnv,
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
await assertAgentVersions({
|
|
1320
|
+
platforms: [...new Set(executionSelections.flatMap(({ entry, platform }) => supportsPlatform(entry.plugin.manifest, platform) ? [platform] : []))],
|
|
1321
|
+
cwd: options.commandOptions.cwd,
|
|
1322
|
+
env: runtimeEnv,
|
|
1323
|
+
runtime: {
|
|
1324
|
+
env: runtimeEnv,
|
|
1325
|
+
nativeCliRunner: options.runtime?.nativeCliRunner ?? getDefaultNativeCliRunner(),
|
|
1326
|
+
reporter: options.runtime?.reporter ?? createNoopReporter(),
|
|
1327
|
+
debugLogger: options.runtime?.debugLogger ?? createNoopDebugLogger(),
|
|
1328
|
+
},
|
|
1329
|
+
});
|
|
1330
|
+
const preparedTargets = new Map();
|
|
1331
|
+
const preparedTargetErrors = new Map();
|
|
1332
|
+
const lockedCollisionSelections = [];
|
|
1333
|
+
for (const { entry, platform } of executionSelections) {
|
|
1334
|
+
const planned = lockedPlan.targets.find((candidate) => candidate.pluginId === entry.pluginId && candidate.platform === platform);
|
|
1335
|
+
if (planned.action !== 'install'
|
|
1336
|
+
&& planned.action !== 'upgrade'
|
|
1337
|
+
&& planned.action !== 'reinstall')
|
|
1338
|
+
continue;
|
|
1339
|
+
const marketplaceName = marketplaceNameFor(entry, platform, planned.resolvedScope);
|
|
1340
|
+
try {
|
|
1341
|
+
const target = await inspection.buildTarget({
|
|
1342
|
+
sourceId: entry.source.sourceId,
|
|
1343
|
+
sourceIdentity: entry.source.sourceIdentity,
|
|
1344
|
+
pluginId: entry.pluginId,
|
|
1345
|
+
marketplaceName,
|
|
1346
|
+
marketplaceRoot: path.join(resolveAwHome(runtimeEnv), 'marketplaces', entry.source.sourceId),
|
|
1347
|
+
plugin: entry.plugin,
|
|
1348
|
+
platform,
|
|
1349
|
+
scope: planned.resolvedScope,
|
|
1350
|
+
cwd: options.commandOptions.cwd,
|
|
1351
|
+
command: planned.relation === 'dependency' ? planned.action : options.command,
|
|
1352
|
+
catalog: toCatalogResolution(entry.source),
|
|
1353
|
+
includeHistoricalLifecycleArtifacts: true,
|
|
1354
|
+
});
|
|
1355
|
+
preparedTargets.set(`${entry.pluginId}\0${platform}`, {
|
|
1356
|
+
target,
|
|
1357
|
+
driver: inspection.driver,
|
|
1358
|
+
context: executionContext,
|
|
1359
|
+
});
|
|
1360
|
+
if (selectedIds.has(entry.pluginId)) {
|
|
1361
|
+
await rebuildCommandTestHooks?.afterTargetBuilt?.({
|
|
1362
|
+
command: options.command,
|
|
1363
|
+
identity: target.identity,
|
|
1364
|
+
});
|
|
1365
|
+
}
|
|
1366
|
+
lockedCollisionSelections.push({
|
|
1367
|
+
pluginId: entry.pluginId,
|
|
1368
|
+
targetKey: `${platform}/${target.identity.scope}`,
|
|
1369
|
+
artifactKeys: (target.desiredOwnedComponents ?? target.ownedComponents)
|
|
1370
|
+
.filter((component) => !(component.kind === 'shared-config'
|
|
1371
|
+
&& component.identity.artifactKey.startsWith('marketplace-')))
|
|
1372
|
+
.map((component) => 'path' in component
|
|
1373
|
+
? path.resolve(component.path)
|
|
1374
|
+
: component.kind === 'native-plugin'
|
|
1375
|
+
? `native:${component.pluginId}`
|
|
1376
|
+
: `shared:${component.label}`),
|
|
1377
|
+
});
|
|
1378
|
+
}
|
|
1379
|
+
catch (error) {
|
|
1380
|
+
preparedTargetErrors.set(`${entry.pluginId}\0${platform}`, error);
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
const lockedCollisions = preflightDesiredArtifactCollisions(lockedCollisionSelections);
|
|
1384
|
+
if (lockedCollisions.length > 0) {
|
|
1385
|
+
throw namespacedPreflightError(`artifactCollision: ${lockedCollisions.map((collision) => `${collision.targetKey} (${collision.pluginIds.join(', ')})`).join('; ')}`, preflightTargets);
|
|
1386
|
+
}
|
|
1387
|
+
const removalRequiredConsumers = new Map();
|
|
1388
|
+
if ((options.command === 'cleanup' && !cleanupForce) || options.command === 'uninstall') {
|
|
1389
|
+
const removalStateInventory = await inventoryCatalogSourceReferences({
|
|
1390
|
+
cwd: options.commandOptions.cwd,
|
|
1391
|
+
env: runtimeEnv,
|
|
1392
|
+
includeHistoricalProjects: true,
|
|
1393
|
+
});
|
|
1394
|
+
if (options.command !== 'cleanup')
|
|
1395
|
+
assertCatalogSourceInventoryComplete(removalStateInventory);
|
|
1396
|
+
const inspectConsumer = async (options_) => {
|
|
1397
|
+
const marketplaceName = marketplaceNameFor(options_.entry, options_.platform, options_.scope, options_.scope === 'project' ? options_.cwd : null);
|
|
1398
|
+
options_.entry.plugin.marketplaceName = marketplaceName;
|
|
1399
|
+
const consumerTarget = await inspection.buildTarget({
|
|
1400
|
+
sourceId: options_.entry.source.sourceId,
|
|
1401
|
+
sourceIdentity: options_.entry.source.sourceIdentity,
|
|
1402
|
+
pluginId: options_.entry.pluginId,
|
|
1403
|
+
marketplaceName,
|
|
1404
|
+
marketplaceRoot: path.join(resolveAwHome(runtimeEnv), 'marketplaces', options_.entry.source.sourceId),
|
|
1405
|
+
plugin: options_.entry.plugin,
|
|
1406
|
+
platform: options_.platform,
|
|
1407
|
+
scope: options_.scope,
|
|
1408
|
+
cwd: options_.cwd,
|
|
1409
|
+
command: 'cleanup',
|
|
1410
|
+
catalog: toCatalogResolution(options_.entry.source),
|
|
1411
|
+
includeHistoricalLifecycleArtifacts: false,
|
|
1412
|
+
readOnlyInspectionPlan: true,
|
|
1413
|
+
});
|
|
1414
|
+
const consumerInspection = await inspectOwnedComponents({
|
|
1415
|
+
components: consumerTarget.ownedComponents,
|
|
1416
|
+
nativeProbe: inspection.driver.probeNative,
|
|
1417
|
+
verifyHealth: true,
|
|
1418
|
+
});
|
|
1419
|
+
return consumerInspection.state === 'absent' ? 'absent' : 'live';
|
|
1420
|
+
};
|
|
1421
|
+
const currentConsumerCandidates = [...new Map(removalStateInventory.references.flatMap((reference) => {
|
|
1422
|
+
if ((reference.kind !== 'namespacedOwner' && reference.kind !== 'namespacedMarketplace')
|
|
1423
|
+
|| !reference.sourceId
|
|
1424
|
+
|| !reference.sourceIdentity
|
|
1425
|
+
|| !reference.pluginName
|
|
1426
|
+
|| (reference.platform !== 'codex' && reference.platform !== 'claude')
|
|
1427
|
+
|| (reference.scope !== 'user' && reference.scope !== 'project'))
|
|
1428
|
+
return [];
|
|
1429
|
+
const entry = available.find((candidate) => candidate.source.sourceId === reference.sourceId
|
|
1430
|
+
&& candidate.source.sourceIdentity === reference.sourceIdentity
|
|
1431
|
+
&& candidate.plugin.manifest.name === reference.pluginName);
|
|
1432
|
+
if (!entry)
|
|
1433
|
+
return [];
|
|
1434
|
+
if (reference.scope === 'project' && !reference.projectKey) {
|
|
1435
|
+
throw namespacedPreflightError(`dependencyStillRequired: cannot inspect project consumer ${entry.pluginId} without its project identity.`, preflightTargets);
|
|
1436
|
+
}
|
|
1437
|
+
const key = [
|
|
1438
|
+
entry.pluginId,
|
|
1439
|
+
reference.platform,
|
|
1440
|
+
reference.scope,
|
|
1441
|
+
reference.projectKey ?? '',
|
|
1442
|
+
].join('\0');
|
|
1443
|
+
return [[key, {
|
|
1444
|
+
entry,
|
|
1445
|
+
platform: reference.platform,
|
|
1446
|
+
scope: reference.scope,
|
|
1447
|
+
projectKey: reference.projectKey ?? null,
|
|
1448
|
+
}]];
|
|
1449
|
+
})).values()];
|
|
1450
|
+
for (const dependencyTarget of executionSelections) {
|
|
1451
|
+
const dependencyPluginName = dependencyTarget.entry.plugin.manifest.name;
|
|
1452
|
+
for (const consumer of currentConsumerCandidates) {
|
|
1453
|
+
if (consumer.entry.source.sourceId
|
|
1454
|
+
!== dependencyTarget.entry.source.sourceId
|
|
1455
|
+
|| !consumer.entry.plugin.manifest.dependencies?.includes(dependencyPluginName)
|
|
1456
|
+
|| consumer.platform !== dependencyTarget.platform
|
|
1457
|
+
|| (consumer.scope === 'user'
|
|
1458
|
+
&& options.commandOptions.scope !== 'user')
|
|
1459
|
+
|| (options.commandOptions.scope === 'project'
|
|
1460
|
+
&& consumer.scope === 'project'
|
|
1461
|
+
&& consumer.projectKey !== commandProjectKey))
|
|
1462
|
+
continue;
|
|
1463
|
+
const plannedConsumer = executionSelections.find((selection) => selection.entry.pluginId === consumer.entry.pluginId
|
|
1464
|
+
&& selection.platform === consumer.platform
|
|
1465
|
+
&& lockedPlan.targets.some((target) => target.pluginId === selection.entry.pluginId
|
|
1466
|
+
&& target.platform === selection.platform
|
|
1467
|
+
&& target.resolvedScope === consumer.scope
|
|
1468
|
+
&& (consumer.scope === 'user' || consumer.projectKey === commandProjectKey)));
|
|
1469
|
+
if (plannedConsumer) {
|
|
1470
|
+
const dependencyExecutionKey = `${dependencyTarget.entry.pluginId}\0${consumer.platform}`;
|
|
1471
|
+
const required = removalRequiredConsumers.get(dependencyExecutionKey) ?? new Set();
|
|
1472
|
+
required.add(`${consumer.entry.pluginId}\0${consumer.platform}`);
|
|
1473
|
+
removalRequiredConsumers.set(dependencyExecutionKey, required);
|
|
1474
|
+
continue;
|
|
1475
|
+
}
|
|
1476
|
+
try {
|
|
1477
|
+
if (await inspectConsumer({
|
|
1478
|
+
entry: consumer.entry,
|
|
1479
|
+
platform: consumer.platform,
|
|
1480
|
+
scope: consumer.scope,
|
|
1481
|
+
cwd: consumer.projectKey ?? options.commandOptions.cwd,
|
|
1482
|
+
}) !== 'absent') {
|
|
1483
|
+
throw new Error('consumer is present, partial, or unreadable');
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
catch {
|
|
1487
|
+
throw namespacedPreflightError(`dependencyStillRequired: ${dependencyTarget.entry.pluginId} is required by ${consumer.entry.pluginId}.`, preflightTargets);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
const orderedSelections = [];
|
|
1492
|
+
const remaining = new Set(executionSelections);
|
|
1493
|
+
while (remaining.size > 0) {
|
|
1494
|
+
const ready = [...remaining].filter((candidate) => ![...remaining].some((consumer) => consumer.platform === candidate.platform
|
|
1495
|
+
&& consumer.entry.source.sourceId === candidate.entry.source.sourceId
|
|
1496
|
+
&& consumer.entry.plugin.manifest.dependencies?.includes(candidate.entry.plugin.manifest.name)))
|
|
1497
|
+
.sort((left, right) => left.entry.pluginId.localeCompare(right.entry.pluginId, 'en'));
|
|
1498
|
+
if (ready.length === 0) {
|
|
1499
|
+
throw namespacedPreflightError('dependencyGraphInvalid: removal graph contains a cycle.', preflightTargets);
|
|
1500
|
+
}
|
|
1501
|
+
for (const selection of ready) {
|
|
1502
|
+
orderedSelections.push(selection);
|
|
1503
|
+
remaining.delete(selection);
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
executionSelections = orderedSelections;
|
|
1507
|
+
}
|
|
1508
|
+
const results = [];
|
|
1509
|
+
const dependencyStates = new Map();
|
|
1510
|
+
for (const { entry, platform } of executionSelections) {
|
|
1511
|
+
const planned = lockedPlan.targets.find((target) => target.pluginId === entry.pluginId && target.platform === platform);
|
|
1512
|
+
const directDependencyIds = (entry.plugin.manifest.dependencies ?? []).map((pluginName) => formatPluginId({ sourceId: entry.source.sourceId, pluginName }));
|
|
1513
|
+
const failedDependency = directDependencyIds.find((pluginId) => {
|
|
1514
|
+
const state = dependencyStates.get(`${pluginId}\0${platform}`);
|
|
1515
|
+
return state === 'failed' || state === 'skipped';
|
|
1516
|
+
});
|
|
1517
|
+
const failedConsumer = [...(removalRequiredConsumers.get(`${entry.pluginId}\0${platform}`) ?? [])]
|
|
1518
|
+
.find((consumerKey) => {
|
|
1519
|
+
const state = dependencyStates.get(consumerKey);
|
|
1520
|
+
return state === 'failed' || state === 'skipped';
|
|
1521
|
+
});
|
|
1522
|
+
const identity = {
|
|
1523
|
+
sourceId: entry.source.sourceId,
|
|
1524
|
+
sourceIdentity: entry.source.sourceIdentity,
|
|
1525
|
+
pluginId: entry.pluginId,
|
|
1526
|
+
pluginName: entry.plugin.manifest.name,
|
|
1527
|
+
pluginVersion: entry.plugin.manifest.version,
|
|
1528
|
+
platform,
|
|
1529
|
+
scope: planned.resolvedScope,
|
|
1530
|
+
cwd: options.commandOptions.cwd,
|
|
1531
|
+
};
|
|
1532
|
+
if (failedDependency || failedConsumer || planned.action === 'block') {
|
|
1533
|
+
const code = failedConsumer
|
|
1534
|
+
? 'dependencyStillRequired'
|
|
1535
|
+
: failedDependency ? 'dependencyInstallFailed' : planned.errorCode ?? 'dependencyNotReady';
|
|
1536
|
+
const message = `${code}: ${failedConsumer
|
|
1537
|
+
? `${entry.pluginId} retained because consumer ${failedConsumer.split('\0', 1)[0]} was not removed.`
|
|
1538
|
+
: failedDependency
|
|
1539
|
+
? `${entry.pluginId} requires failed dependency ${failedDependency}.`
|
|
1540
|
+
: code === 'artifactCollision'
|
|
1541
|
+
? `${entry.pluginId} has foreign-owned output. Remove or relocate it, then run cleanup and reinstall.`
|
|
1542
|
+
: code === 'dependencyNotReady'
|
|
1543
|
+
? `${entry.pluginId} live state is unreadable. Run cleanup, then reinstall.`
|
|
1544
|
+
: `${entry.pluginId} dependency preflight is blocked.`}`;
|
|
1545
|
+
const result = failedResult(options.command, identity, message);
|
|
1546
|
+
results.push({
|
|
1547
|
+
platforms: [platform], plugins: [], warnings: [], rebuildResults: [result],
|
|
1548
|
+
targetResults: [{
|
|
1549
|
+
target: identity,
|
|
1550
|
+
action: failedDependency || failedConsumer ? 'skipped' : planned.action,
|
|
1551
|
+
state: 'failed',
|
|
1552
|
+
errorCode: code,
|
|
1553
|
+
message,
|
|
1554
|
+
}],
|
|
1555
|
+
overallState: 'failed', nativePlugins: {}, repoManagedArtifacts: [],
|
|
1556
|
+
receiptTargets: [{
|
|
1557
|
+
pluginName: identity.pluginName, pluginId: identity.pluginId,
|
|
1558
|
+
sourceId: identity.sourceId, platform, scope: planned.resolvedScope,
|
|
1559
|
+
}],
|
|
1560
|
+
});
|
|
1561
|
+
dependencyStates.set(`${entry.pluginId}\0${platform}`, failedDependency || failedConsumer ? 'skipped' : 'failed');
|
|
1562
|
+
continue;
|
|
1563
|
+
}
|
|
1564
|
+
if (planned.action === 'keep') {
|
|
1565
|
+
const result = {
|
|
1566
|
+
status: 'succeeded', command: options.command, target: identity, actions: [],
|
|
1567
|
+
cleanupAttempted: false, removed: [], absent: [], residual: [], quarantined: [], failures: [],
|
|
1568
|
+
};
|
|
1569
|
+
results.push({
|
|
1570
|
+
platforms: [platform], plugins: [identity.pluginName], warnings: [], rebuildResults: [result],
|
|
1571
|
+
targetResults: [{ target: identity, action: 'keep', state: 'completed' }],
|
|
1572
|
+
overallState: 'succeeded', nativePlugins: {}, repoManagedArtifacts: [],
|
|
1573
|
+
receiptTargets: [{
|
|
1574
|
+
pluginName: identity.pluginName, pluginId: identity.pluginId,
|
|
1575
|
+
sourceId: identity.sourceId, platform, scope: planned.resolvedScope,
|
|
1576
|
+
}],
|
|
1577
|
+
});
|
|
1578
|
+
dependencyStates.set(`${entry.pluginId}\0${platform}`, 'kept');
|
|
1579
|
+
continue;
|
|
1580
|
+
}
|
|
1581
|
+
const marketplaceName = marketplaceNameFor(entry, platform, planned.resolvedScope);
|
|
1582
|
+
const namespacedSource = {
|
|
1583
|
+
sourceId: entry.source.sourceId,
|
|
1584
|
+
sourceIdentity: entry.source.sourceIdentity,
|
|
1585
|
+
marketplaceName,
|
|
1586
|
+
marketplaceRoot: path.join(resolveAwHome(runtimeEnv), 'marketplaces', entry.source.sourceId),
|
|
1587
|
+
};
|
|
1588
|
+
entry.plugin.marketplaceName = marketplaceName;
|
|
1589
|
+
const executionResult = await runSingleSourceRebuildCommand({
|
|
1590
|
+
...options,
|
|
1591
|
+
command: planned.relation === 'dependency'
|
|
1592
|
+
? planned.action
|
|
1593
|
+
: options.command,
|
|
1594
|
+
pluginNames: [entry.plugin.manifest.name],
|
|
1595
|
+
all: false,
|
|
1596
|
+
commandOptions: { ...options.commandOptions, platform, scope: planned.resolvedScope },
|
|
1597
|
+
runtime: {
|
|
1598
|
+
...options.runtime,
|
|
1599
|
+
env: runtimeEnv,
|
|
1600
|
+
catalogResolution: toCatalogResolution(entry.source),
|
|
1601
|
+
namespacedSource,
|
|
1602
|
+
operationLeaseHeld: true,
|
|
1603
|
+
dependencyReviewPreflightHandled: true,
|
|
1604
|
+
targetBuiltHookHandled: true,
|
|
1605
|
+
preparedTarget: preparedTargets.get(`${entry.pluginId}\0${platform}`),
|
|
1606
|
+
preparedTargetError: preparedTargetErrors.get(`${entry.pluginId}\0${platform}`),
|
|
1607
|
+
expectedCatalogConfigDigest: catalog.configDigest,
|
|
1608
|
+
resolvedReviewEvidenceByPlugin: {
|
|
1609
|
+
[entry.plugin.manifest.name]: {
|
|
1610
|
+
configDigest: catalog.configDigest,
|
|
1611
|
+
sourceId: entry.source.sourceId,
|
|
1612
|
+
sourceIdentity: entry.source.sourceIdentity,
|
|
1613
|
+
resolvedCommit: entry.source.resolvedCommit,
|
|
1614
|
+
manifestDigest: entry.source.manifestDigest,
|
|
1615
|
+
snapshotDigest: entry.source.snapshotDigest,
|
|
1616
|
+
contentDigest: entry.source.manifest.entries.find((candidate) => candidate.name === entry.plugin.manifest.name)?.contentDigest,
|
|
1617
|
+
},
|
|
1618
|
+
},
|
|
1619
|
+
},
|
|
1620
|
+
});
|
|
1621
|
+
results.push(executionResult);
|
|
1622
|
+
dependencyStates.set(`${entry.pluginId}\0${platform}`, executionResult.overallState === 'succeeded' ? 'completed' : 'failed');
|
|
1623
|
+
}
|
|
1624
|
+
const merged = mergeRebuildCommandResults(results);
|
|
1625
|
+
merged.dependencyPlan = lockedPlan;
|
|
1626
|
+
return leaseSafeRebuildResult(merged);
|
|
1627
|
+
},
|
|
1628
|
+
});
|
|
1629
|
+
if (cleanupForce) {
|
|
1630
|
+
try {
|
|
1631
|
+
await (options.runtime?.removeObsoleteInstallationContracts ?? fs.remove)(path.join(resolveAwHome(runtimeEnv), 'installation-contracts'));
|
|
1632
|
+
}
|
|
1633
|
+
catch (error) {
|
|
1634
|
+
resolvedResult.warnings.push(`obsoleteContractsCleanupFailed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
return resolvedResult;
|
|
1638
|
+
}
|
|
1639
|
+
catch (error) {
|
|
1640
|
+
if (options.all && (liveTargets.length > 0 || legacyLiveTargets.length > 0)) {
|
|
1641
|
+
const projected = error;
|
|
1642
|
+
error = namespacedPreflightError(error instanceof Error ? error.message : String(error), projected.namespacedTargets ?? liveTargets, projected.legacyTargets ?? legacyLiveTargets);
|
|
1643
|
+
}
|
|
1644
|
+
if (options.command !== 'cleanup' && options.command !== 'uninstall')
|
|
1645
|
+
throw error;
|
|
1646
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1647
|
+
const catalogUnavailable = message.startsWith('Cannot resolve required catalog sources:')
|
|
1648
|
+
|| message.includes('does not exist in the required catalog source set')
|
|
1649
|
+
|| (message.includes('Catalog source') && message.includes('does not exist'));
|
|
1650
|
+
if (options.command === 'cleanup'
|
|
1651
|
+
&& (catalogUnavailable || message.includes('sourceChanged'))
|
|
1652
|
+
&& cleanupInventory
|
|
1653
|
+
&& cleanupLiveTargets.length > 0) {
|
|
1654
|
+
if (!cleanupForce) {
|
|
1655
|
+
await assertOfflineCleanupDependents({
|
|
1656
|
+
targets: cleanupLiveTargets,
|
|
1657
|
+
cwd: options.commandOptions.cwd,
|
|
1658
|
+
env: runtimeEnv,
|
|
1659
|
+
});
|
|
1660
|
+
}
|
|
1661
|
+
return cleanupOfflineOwnedComponents({
|
|
1662
|
+
targets: cleanupLiveTargets,
|
|
1663
|
+
cwd: options.commandOptions.cwd,
|
|
1664
|
+
env: runtimeEnv,
|
|
1665
|
+
force: cleanupForce,
|
|
1666
|
+
removeObsoleteInstallationContracts: options.runtime?.removeObsoleteInstallationContracts,
|
|
1667
|
+
nativeCliRunner: options.runtime?.nativeCliRunner,
|
|
1668
|
+
corruptExclusiveDirectoryOperations: options.runtime?.corruptExclusiveDirectoryOperations,
|
|
1669
|
+
});
|
|
1670
|
+
}
|
|
1671
|
+
if (options.command === 'uninstall' && catalogUnavailable) {
|
|
1672
|
+
throw namespacedPreflightError(`catalogSourceUnavailable: ${message} Restore the source to run lifecycle uninstall, or use cleanup; use cleanup --force only for exclusively owned damaged output.`, liveTargets, legacyLiveTargets);
|
|
1673
|
+
}
|
|
1674
|
+
if ((message.includes('Catalog source') && message.includes('does not exist'))
|
|
1675
|
+
|| message.includes('does not exist in the required catalog source set')) {
|
|
1676
|
+
throw namespacedPreflightError(`sourceMissing: ${message} Run cleanup for owner recovery, or cleanup --force for an exclusively owned damaged target.`, liveTargets, legacyLiveTargets);
|
|
1677
|
+
}
|
|
1678
|
+
throw error;
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
//# sourceMappingURL=rebuild-command.js.map
|