@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,1418 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import { readClaudeSettings } from '../adapters/helpers.js';
|
|
4
|
+
import { readCodexConfigFile } from './codex-config.js';
|
|
5
|
+
import { readJsonFileIfExists } from './json.js';
|
|
6
|
+
import { getClaudeHome, getCodexHome, canonicalizePathThroughExistingAncestorSync, resolveAwHome, resolveAwHomeCanonical, resolveRepoRootSync, } from './state-paths.js';
|
|
7
|
+
import { OWNED_TEXT_HEADER_PREFIX, parseSharedOwnerToken, parseOwnedTextHeader, readSkillOwnerMarker, SKILL_OWNER_MARKER, } from './ownership.js';
|
|
8
|
+
import { createLifecycleProjectLocationKey, inspectLifecycleActiveSnapshotForInventory, } from './lifecycle-active-store.js';
|
|
9
|
+
import { CodexNativeResidueProbeError, discoverCodexNativeResidueNames, } from '../commands/rebuild-integration.js';
|
|
10
|
+
import { parseCodexSharedHooksFile } from './hooks-contract.js';
|
|
11
|
+
import { sanitizeCatalogSourceErrorMessage } from './catalog-public-error.js';
|
|
12
|
+
import { readPluginManifest } from './manifest.js';
|
|
13
|
+
import { readStrictNamespacedMarketplaceRoot } from './local-marketplace.js';
|
|
14
|
+
export function canonicalMarketplaceRegistrationNames(references, sourceId) {
|
|
15
|
+
return [...new Set(references.flatMap((reference) => reference.kind === 'namespacedMarketplace'
|
|
16
|
+
&& reference.sourceId === sourceId
|
|
17
|
+
&& reference.pluginName === undefined
|
|
18
|
+
&& reference.marketplaceName
|
|
19
|
+
? [reference.marketplaceName]
|
|
20
|
+
: []))];
|
|
21
|
+
}
|
|
22
|
+
function pluginNameFromMarketplaceId(pluginId, marketplaceName) {
|
|
23
|
+
const suffix = `@${marketplaceName}`;
|
|
24
|
+
return pluginId.endsWith(suffix) && pluginId.length > suffix.length
|
|
25
|
+
? pluginId.slice(0, -suffix.length)
|
|
26
|
+
: null;
|
|
27
|
+
}
|
|
28
|
+
function claudeConsumersFromSettings(value, marketplaceName, scope) {
|
|
29
|
+
if (!value)
|
|
30
|
+
return [];
|
|
31
|
+
const output = [];
|
|
32
|
+
for (const pluginId of Object.keys(isRecord(value.enabledPlugins) ? value.enabledPlugins : {})) {
|
|
33
|
+
const pluginName = pluginNameFromMarketplaceId(pluginId, marketplaceName);
|
|
34
|
+
if (pluginName)
|
|
35
|
+
output.push({ pluginName, platform: 'claude', scope });
|
|
36
|
+
}
|
|
37
|
+
const plugins = isRecord(value.plugins) && isRecord(value.plugins.installed)
|
|
38
|
+
? value.plugins.installed
|
|
39
|
+
: {};
|
|
40
|
+
for (const [key, raw] of Object.entries(plugins)) {
|
|
41
|
+
if (!isRecord(raw) || raw.marketplace !== marketplaceName)
|
|
42
|
+
continue;
|
|
43
|
+
const pluginName = typeof raw.name === 'string'
|
|
44
|
+
? raw.name
|
|
45
|
+
: pluginNameFromMarketplaceId(key, marketplaceName) ?? key;
|
|
46
|
+
output.push({ pluginName, platform: 'claude', scope });
|
|
47
|
+
}
|
|
48
|
+
return output;
|
|
49
|
+
}
|
|
50
|
+
function claudeConsumersFromInstalled(value, marketplaceName, currentProject, includeHistoricalProjects) {
|
|
51
|
+
const output = [];
|
|
52
|
+
if (value !== null && !isRecord(value)) {
|
|
53
|
+
throw new Error('Claude installed_plugins must be a JSON object.');
|
|
54
|
+
}
|
|
55
|
+
if (value?.plugins !== undefined && !isRecord(value.plugins)) {
|
|
56
|
+
throw new Error('Claude installed_plugins.plugins must be a JSON object.');
|
|
57
|
+
}
|
|
58
|
+
const plugins = value?.plugins ?? {};
|
|
59
|
+
for (const [key, raw] of Object.entries(plugins)) {
|
|
60
|
+
for (const item of Array.isArray(raw) ? raw : [raw]) {
|
|
61
|
+
if (!isRecord(item)) {
|
|
62
|
+
throw new Error(`Claude installed_plugins record ${key} must be a JSON object.`);
|
|
63
|
+
}
|
|
64
|
+
if (item.marketplace !== undefined
|
|
65
|
+
&& (typeof item.marketplace !== 'string' || item.marketplace.length === 0)) {
|
|
66
|
+
throw new Error(`Claude installed_plugins record ${key} has an invalid marketplace identity.`);
|
|
67
|
+
}
|
|
68
|
+
if (item.name !== undefined && (typeof item.name !== 'string' || item.name.length === 0)) {
|
|
69
|
+
throw new Error(`Claude installed_plugins record ${key} has an invalid plugin identity.`);
|
|
70
|
+
}
|
|
71
|
+
if (item.scope !== undefined
|
|
72
|
+
&& item.scope !== 'user'
|
|
73
|
+
&& item.scope !== 'project'
|
|
74
|
+
&& item.scope !== 'local') {
|
|
75
|
+
throw new Error(`Claude installed_plugins record ${key} has an invalid scope.`);
|
|
76
|
+
}
|
|
77
|
+
if (item.projectPath !== undefined && typeof item.projectPath !== 'string') {
|
|
78
|
+
throw new Error(`Claude installed_plugins record ${key} has an invalid projectPath.`);
|
|
79
|
+
}
|
|
80
|
+
const itemMarketplace = typeof item.marketplace === 'string'
|
|
81
|
+
? item.marketplace
|
|
82
|
+
: pluginNameFromMarketplaceId(key, marketplaceName) ? marketplaceName : undefined;
|
|
83
|
+
if (!itemMarketplace)
|
|
84
|
+
continue;
|
|
85
|
+
if (itemMarketplace !== marketplaceName)
|
|
86
|
+
continue;
|
|
87
|
+
const scope = item.scope === 'project' || item.scope === 'local' ? 'project' : 'user';
|
|
88
|
+
const projectKey = scope === 'project'
|
|
89
|
+
? typeof item.projectPath === 'string' && path.isAbsolute(item.projectPath)
|
|
90
|
+
? canonicalizePathThroughExistingAncestorSync(item.projectPath)
|
|
91
|
+
: null
|
|
92
|
+
: undefined;
|
|
93
|
+
if (!includeHistoricalProjects && scope === 'project' && projectKey !== currentProject)
|
|
94
|
+
continue;
|
|
95
|
+
const pluginName = typeof item.name === 'string'
|
|
96
|
+
? item.name
|
|
97
|
+
: pluginNameFromMarketplaceId(key, marketplaceName) ?? key;
|
|
98
|
+
output.push({ pluginName, platform: 'claude', scope, ...(scope === 'project' ? { projectKey } : {}) });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return output;
|
|
102
|
+
}
|
|
103
|
+
function pathSegmentsWithin(root, location) {
|
|
104
|
+
const relative = path.relative(path.resolve(root), path.resolve(location));
|
|
105
|
+
if (relative === '' || (!relative.startsWith(`..${path.sep}`) && relative !== '..' && !path.isAbsolute(relative))) {
|
|
106
|
+
return relative === '' ? [] : relative.split(path.sep);
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
function inventoryErrorRelevance(location, env, cwd) {
|
|
111
|
+
const repoRoot = resolveRepoRootSync(cwd);
|
|
112
|
+
const awHome = resolveAwHome(env);
|
|
113
|
+
const canonicalRepoRoot = (() => {
|
|
114
|
+
try {
|
|
115
|
+
return fs.realpathSync(repoRoot);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return path.resolve(repoRoot);
|
|
119
|
+
}
|
|
120
|
+
})();
|
|
121
|
+
const canonicalAwHome = (() => {
|
|
122
|
+
try {
|
|
123
|
+
return canonicalizePathThroughExistingAncestorSync(awHome);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return path.resolve(awHome);
|
|
127
|
+
}
|
|
128
|
+
})();
|
|
129
|
+
const projectRoots = [
|
|
130
|
+
[path.join(repoRoot, '.codex'), 'codex'],
|
|
131
|
+
[path.join(repoRoot, '.agents'), 'codex'],
|
|
132
|
+
[path.join(repoRoot, '.claude'), 'claude'],
|
|
133
|
+
];
|
|
134
|
+
for (const [root, platform] of projectRoots) {
|
|
135
|
+
if (pathSegmentsWithin(root, location) !== null) {
|
|
136
|
+
return { global: false, platform, scope: 'project' };
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
for (const fileName of ['installed_plugins.json', 'known_marketplaces.json']) {
|
|
140
|
+
if (pathSegmentsWithin(path.join(getClaudeHome(env), 'plugins', fileName), location) !== null) {
|
|
141
|
+
return { global: false, platform: 'claude' };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (pathSegmentsWithin(getCodexHome(env), location) !== null) {
|
|
145
|
+
return { global: false, platform: 'codex', scope: 'user' };
|
|
146
|
+
}
|
|
147
|
+
if (pathSegmentsWithin(getClaudeHome(env), location) !== null) {
|
|
148
|
+
return { global: false, platform: 'claude', scope: 'user' };
|
|
149
|
+
}
|
|
150
|
+
for (const root of new Set([awHome, canonicalAwHome])) {
|
|
151
|
+
const marketplace = pathSegmentsWithin(path.join(root, 'marketplaces'), location);
|
|
152
|
+
if (marketplace?.[0])
|
|
153
|
+
return { global: false, sourceId: marketplace[0] };
|
|
154
|
+
}
|
|
155
|
+
for (const [root, scope] of [
|
|
156
|
+
[path.join(awHome, 'plugin-config'), 'user'],
|
|
157
|
+
[path.join(canonicalAwHome, 'plugin-config'), 'user'],
|
|
158
|
+
[path.join(repoRoot, '.agent-workflows', 'plugin-config'), 'project'],
|
|
159
|
+
[path.join(repoRoot, '.agent-workflows', 'plugin-config.local'), 'project'],
|
|
160
|
+
[path.join(canonicalRepoRoot, '.agent-workflows', 'plugin-config'), 'project'],
|
|
161
|
+
[path.join(canonicalRepoRoot, '.agent-workflows', 'plugin-config.local'), 'project'],
|
|
162
|
+
]) {
|
|
163
|
+
const segments = pathSegmentsWithin(root, location);
|
|
164
|
+
if (segments !== null) {
|
|
165
|
+
return {
|
|
166
|
+
global: false,
|
|
167
|
+
...(segments[0] ? { sourceId: segments[0] } : {}),
|
|
168
|
+
...(segments[1] ? { pluginName: segments[1] } : {}),
|
|
169
|
+
scope,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
for (const root of new Set([repoRoot, canonicalRepoRoot])) {
|
|
174
|
+
if (pathSegmentsWithin(path.join(root, '.agent-workflows'), location) !== null) {
|
|
175
|
+
return { global: false, scope: 'project' };
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const lifecycle = pathSegmentsWithin(path.join(awHome, 'lifecycle-active'), location);
|
|
179
|
+
if (lifecycle?.[0]) {
|
|
180
|
+
const platform = lifecycle[1] === 'codex' || lifecycle[1] === 'claude'
|
|
181
|
+
? lifecycle[1]
|
|
182
|
+
: undefined;
|
|
183
|
+
const scope = lifecycle[2] === 'user' || lifecycle[2] === 'project'
|
|
184
|
+
? lifecycle[2]
|
|
185
|
+
: undefined;
|
|
186
|
+
const pluginName = platform && scope && lifecycle.length >= 5
|
|
187
|
+
&& (scope === 'project' || lifecycle[3] === 'user')
|
|
188
|
+
? lifecycle[4]
|
|
189
|
+
: undefined;
|
|
190
|
+
return {
|
|
191
|
+
global: false,
|
|
192
|
+
sourceId: lifecycle[0],
|
|
193
|
+
...(pluginName ? { pluginName } : {}),
|
|
194
|
+
...(platform ? { platform } : {}),
|
|
195
|
+
...(scope ? { scope } : {}),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
return { global: true };
|
|
199
|
+
}
|
|
200
|
+
function isAbsentState(error) {
|
|
201
|
+
const code = error.code;
|
|
202
|
+
return code === 'ENOENT';
|
|
203
|
+
}
|
|
204
|
+
function inventoryError(error, location, kind, env, cwd, relevance) {
|
|
205
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
206
|
+
const sensitiveRoots = [getCodexHome(env), getClaudeHome(env), resolveRepoRootSync(cwd)];
|
|
207
|
+
return {
|
|
208
|
+
code: 'stateInventoryFailed',
|
|
209
|
+
kind,
|
|
210
|
+
location: sanitizeCatalogSourceErrorMessage(location, env, sensitiveRoots),
|
|
211
|
+
message: sanitizeCatalogSourceErrorMessage(message, env, sensitiveRoots),
|
|
212
|
+
relevance: relevance ?? inventoryErrorRelevance(location, env, cwd),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
async function inventoryRead(options) {
|
|
216
|
+
try {
|
|
217
|
+
return await options.operation();
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
if (options.reportAbsent || !isAbsentState(error)) {
|
|
221
|
+
options.errors.push(inventoryError(error, options.location, options.kind, options.env, options.cwd));
|
|
222
|
+
}
|
|
223
|
+
return options.absent;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
async function inventoryCanonicalDirectory(options) {
|
|
227
|
+
const stats = await inventoryRead({
|
|
228
|
+
operation: () => fs.lstat(options.location),
|
|
229
|
+
absent: null,
|
|
230
|
+
errors: options.errors,
|
|
231
|
+
location: options.location,
|
|
232
|
+
kind: options.kind,
|
|
233
|
+
env: options.env,
|
|
234
|
+
cwd: options.cwd,
|
|
235
|
+
});
|
|
236
|
+
if (stats === null)
|
|
237
|
+
return false;
|
|
238
|
+
if (!stats.isDirectory() || stats.isSymbolicLink()) {
|
|
239
|
+
options.errors.push(inventoryError(new Error('State namespace root must be a canonical directory.'), options.location, options.kind, options.env, options.cwd));
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
async function inventoryCanonicalDirectoryEntries(options) {
|
|
245
|
+
if (!await inventoryCanonicalDirectory(options))
|
|
246
|
+
return [];
|
|
247
|
+
return inventoryRead({
|
|
248
|
+
operation: () => fs.readdir(options.location, { withFileTypes: true }),
|
|
249
|
+
absent: [],
|
|
250
|
+
errors: options.errors,
|
|
251
|
+
location: options.location,
|
|
252
|
+
kind: options.kind,
|
|
253
|
+
env: options.env,
|
|
254
|
+
cwd: options.cwd,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
async function inventoryCanonicalDescendantDirectory(options) {
|
|
258
|
+
let location = options.root;
|
|
259
|
+
for (const segment of options.segments) {
|
|
260
|
+
location = path.join(location, segment);
|
|
261
|
+
if (!await inventoryCanonicalDirectory({
|
|
262
|
+
errors: options.errors,
|
|
263
|
+
location,
|
|
264
|
+
kind: options.kind,
|
|
265
|
+
env: options.env,
|
|
266
|
+
cwd: options.cwd,
|
|
267
|
+
}))
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
return location;
|
|
271
|
+
}
|
|
272
|
+
async function inventoryPluginConfigRoots(options) {
|
|
273
|
+
const roots = [];
|
|
274
|
+
const rawAwHome = resolveAwHome(options.env);
|
|
275
|
+
const awHome = await inventoryRead({
|
|
276
|
+
operation: () => resolveAwHomeCanonical(options.env),
|
|
277
|
+
absent: null,
|
|
278
|
+
errors: options.errors,
|
|
279
|
+
location: rawAwHome,
|
|
280
|
+
kind: 'configDirectoryRead',
|
|
281
|
+
env: options.env,
|
|
282
|
+
cwd: options.cwd,
|
|
283
|
+
});
|
|
284
|
+
if (awHome && await inventoryCanonicalDirectory({
|
|
285
|
+
errors: options.errors,
|
|
286
|
+
location: awHome,
|
|
287
|
+
kind: 'configDirectoryRead',
|
|
288
|
+
env: options.env,
|
|
289
|
+
cwd: options.cwd,
|
|
290
|
+
})) {
|
|
291
|
+
const userRoot = await inventoryCanonicalDescendantDirectory({
|
|
292
|
+
root: rawAwHome,
|
|
293
|
+
segments: ['plugin-config'],
|
|
294
|
+
errors: options.errors,
|
|
295
|
+
kind: 'configDirectoryRead',
|
|
296
|
+
env: options.env,
|
|
297
|
+
cwd: options.cwd,
|
|
298
|
+
});
|
|
299
|
+
if (userRoot)
|
|
300
|
+
roots.push(userRoot);
|
|
301
|
+
}
|
|
302
|
+
const rawRepoRoot = resolveRepoRootSync(options.cwd);
|
|
303
|
+
const repoRoot = await inventoryRead({
|
|
304
|
+
operation: () => fs.realpath(rawRepoRoot),
|
|
305
|
+
absent: null,
|
|
306
|
+
reportAbsent: true,
|
|
307
|
+
errors: options.errors,
|
|
308
|
+
location: rawRepoRoot,
|
|
309
|
+
kind: 'projectRootRead',
|
|
310
|
+
env: options.env,
|
|
311
|
+
cwd: options.cwd,
|
|
312
|
+
});
|
|
313
|
+
if (repoRoot && await inventoryCanonicalDirectory({
|
|
314
|
+
errors: options.errors,
|
|
315
|
+
location: repoRoot,
|
|
316
|
+
kind: 'projectRootRead',
|
|
317
|
+
env: options.env,
|
|
318
|
+
cwd: options.cwd,
|
|
319
|
+
})) {
|
|
320
|
+
for (const storeName of ['plugin-config', 'plugin-config.local']) {
|
|
321
|
+
const projectRoot = await inventoryCanonicalDescendantDirectory({
|
|
322
|
+
root: rawRepoRoot,
|
|
323
|
+
segments: ['.agent-workflows', storeName],
|
|
324
|
+
errors: options.errors,
|
|
325
|
+
kind: 'configDirectoryRead',
|
|
326
|
+
env: options.env,
|
|
327
|
+
cwd: options.cwd,
|
|
328
|
+
});
|
|
329
|
+
if (projectRoot)
|
|
330
|
+
roots.push(projectRoot);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return roots;
|
|
334
|
+
}
|
|
335
|
+
export async function inventoryLegacyOwnerReferences(options) {
|
|
336
|
+
const env = options.env ?? process.env;
|
|
337
|
+
const awHome = resolveAwHome(env);
|
|
338
|
+
const repoRoot = resolveRepoRootSync(options.cwd);
|
|
339
|
+
const references = [];
|
|
340
|
+
const errors = [];
|
|
341
|
+
const skillRoots = new Set([
|
|
342
|
+
path.join(getCodexHome(env), 'skills'),
|
|
343
|
+
path.join(getClaudeHome(env), 'skills'),
|
|
344
|
+
path.join(repoRoot, '.agents', 'skills'),
|
|
345
|
+
path.join(repoRoot, '.claude', 'skills'),
|
|
346
|
+
]);
|
|
347
|
+
const legacyPluginsRoot = path.join(awHome, 'plugins');
|
|
348
|
+
const legacyPlugins = await inventoryRead({
|
|
349
|
+
operation: () => fs.readdir(legacyPluginsRoot, { withFileTypes: true }),
|
|
350
|
+
absent: [], errors, location: legacyPluginsRoot, kind: 'pluginDirectoryRead', env, cwd: options.cwd,
|
|
351
|
+
});
|
|
352
|
+
for (const plugin of legacyPlugins) {
|
|
353
|
+
if (!plugin.isDirectory() || plugin.isSymbolicLink())
|
|
354
|
+
continue;
|
|
355
|
+
for (const root of await resolveCanonicalPluginSkillRoots(path.join(legacyPluginsRoot, plugin.name), true, errors, env, options.cwd))
|
|
356
|
+
skillRoots.add(root);
|
|
357
|
+
}
|
|
358
|
+
const marketplacesRoot = path.join(awHome, 'marketplaces');
|
|
359
|
+
const marketplaces = await inventoryCanonicalDirectoryEntries({
|
|
360
|
+
errors, location: marketplacesRoot, kind: 'marketplaceDirectoryRead', env, cwd: options.cwd,
|
|
361
|
+
});
|
|
362
|
+
for (const entry of marketplaces) {
|
|
363
|
+
const marketplaceRoot = path.join(marketplacesRoot, entry.name);
|
|
364
|
+
if (!await inventoryCanonicalDirectory({
|
|
365
|
+
errors,
|
|
366
|
+
location: marketplaceRoot,
|
|
367
|
+
kind: 'marketplaceRootValidation',
|
|
368
|
+
env,
|
|
369
|
+
cwd: options.cwd,
|
|
370
|
+
}))
|
|
371
|
+
continue;
|
|
372
|
+
const pluginsRoot = path.join(marketplacesRoot, entry.name, 'plugins');
|
|
373
|
+
const plugins = await inventoryCanonicalDirectoryEntries({
|
|
374
|
+
errors, location: pluginsRoot, kind: 'pluginDirectoryRead', env, cwd: options.cwd,
|
|
375
|
+
});
|
|
376
|
+
for (const plugin of plugins) {
|
|
377
|
+
const pluginRoot = path.join(pluginsRoot, plugin.name);
|
|
378
|
+
if (!await inventoryCanonicalDirectory({
|
|
379
|
+
errors,
|
|
380
|
+
location: pluginRoot,
|
|
381
|
+
kind: 'pluginDirectoryRead',
|
|
382
|
+
env,
|
|
383
|
+
cwd: options.cwd,
|
|
384
|
+
}))
|
|
385
|
+
continue;
|
|
386
|
+
for (const root of await resolveCanonicalPluginSkillRoots(pluginRoot, false, errors, env, options.cwd))
|
|
387
|
+
skillRoots.add(root);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
for (const root of skillRoots) {
|
|
391
|
+
references.push(...await findDirectSkillOwnerMarkers(root, errors, env, options.cwd));
|
|
392
|
+
}
|
|
393
|
+
for (const configRoot of [
|
|
394
|
+
getCodexHome(env),
|
|
395
|
+
getClaudeHome(env),
|
|
396
|
+
path.join(repoRoot, '.codex'),
|
|
397
|
+
path.join(repoRoot, '.claude'),
|
|
398
|
+
]) {
|
|
399
|
+
references.push(...await findOwnedHeadersInDirectory(path.join(configRoot, 'rules'), new Set(['.md', '.rules']), true, errors, env, options.cwd), ...await findOwnedHeadersInDirectory(path.join(configRoot, 'agents'), new Set(['.md', '.toml']), true, errors, env, options.cwd));
|
|
400
|
+
}
|
|
401
|
+
references.push(...await findOwnedHeadersInDirectory(path.join(repoRoot, '.agents', 'rules'), new Set(['.md']), false, errors, env, options.cwd), ...await findOwnedHeadersInDirectory(path.join(repoRoot, '.agents', 'agents'), new Set(['.md']), false, errors, env, options.cwd));
|
|
402
|
+
for (const filePath of [
|
|
403
|
+
path.join(getCodexHome(env), 'AGENTS.md'),
|
|
404
|
+
path.join(repoRoot, '.codex', 'AGENTS.md'),
|
|
405
|
+
]) {
|
|
406
|
+
const reference = await readOwnedHeaderReference(filePath, false, errors, env, options.cwd);
|
|
407
|
+
if (reference)
|
|
408
|
+
references.push(reference);
|
|
409
|
+
}
|
|
410
|
+
const unique = [...new Map(references.map((reference) => [[
|
|
411
|
+
reference.kind,
|
|
412
|
+
reference.location,
|
|
413
|
+
reference.sourceId ?? '',
|
|
414
|
+
reference.sourceIdentity ?? '',
|
|
415
|
+
reference.pluginName ?? '',
|
|
416
|
+
reference.platform ?? '',
|
|
417
|
+
reference.scope ?? '',
|
|
418
|
+
reference.marketplaceName ?? '',
|
|
419
|
+
].join('\0'), reference])).values()];
|
|
420
|
+
unique.sort((left, right) => left.location.localeCompare(right.location));
|
|
421
|
+
return { inventorySchemaVersion: 1, references: unique, errors };
|
|
422
|
+
}
|
|
423
|
+
export async function inventoryLegacyConfigReferences(options) {
|
|
424
|
+
const env = options.env ?? process.env;
|
|
425
|
+
const references = [];
|
|
426
|
+
const errors = [];
|
|
427
|
+
for (const directory of await inventoryPluginConfigRoots({ errors, env, cwd: options.cwd })) {
|
|
428
|
+
const entries = await inventoryRead({
|
|
429
|
+
operation: () => fs.readdir(directory, { withFileTypes: true }),
|
|
430
|
+
absent: [], errors, location: directory, kind: 'configDirectoryRead', env, cwd: options.cwd,
|
|
431
|
+
});
|
|
432
|
+
for (const entry of entries) {
|
|
433
|
+
const entryRoot = path.join(directory, entry.name);
|
|
434
|
+
if (!await inventoryCanonicalDirectory({
|
|
435
|
+
errors, location: entryRoot, kind: 'configNamespaceValidation', env, cwd: options.cwd,
|
|
436
|
+
}))
|
|
437
|
+
continue;
|
|
438
|
+
const legacyFile = path.join(directory, entry.name, 'config.json');
|
|
439
|
+
const stat = await inventoryRead({
|
|
440
|
+
operation: () => fs.stat(legacyFile),
|
|
441
|
+
absent: null, errors, location: legacyFile, kind: 'configFileStat', env, cwd: options.cwd,
|
|
442
|
+
});
|
|
443
|
+
if (stat?.isFile()) {
|
|
444
|
+
references.push({ kind: 'legacyConfig', location: legacyFile, pluginName: entry.name });
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
references.sort((left, right) => left.location.localeCompare(right.location));
|
|
449
|
+
return { inventorySchemaVersion: 1, references, errors };
|
|
450
|
+
}
|
|
451
|
+
function ownerReferenceFromRaw(entryPath, raw) {
|
|
452
|
+
if (raw?.schemaVersion === 1 && raw.owner === 'agent-workflows') {
|
|
453
|
+
return {
|
|
454
|
+
kind: 'legacyOwner',
|
|
455
|
+
location: entryPath,
|
|
456
|
+
...(typeof raw.plugin === 'string' ? { pluginName: raw.plugin } : {}),
|
|
457
|
+
...(typeof raw.platform === 'string' ? { platform: raw.platform } : {}),
|
|
458
|
+
...(typeof raw.scope === 'string' ? { scope: raw.scope } : {}),
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
if (raw?.schemaVersion === 2 && raw.owner === 'agent-workflows'
|
|
462
|
+
&& typeof raw.sourceId === 'string') {
|
|
463
|
+
return {
|
|
464
|
+
kind: 'namespacedOwner',
|
|
465
|
+
location: entryPath,
|
|
466
|
+
sourceId: raw.sourceId,
|
|
467
|
+
...(typeof raw.sourceIdentity === 'string' ? { sourceIdentity: raw.sourceIdentity } : {}),
|
|
468
|
+
...(typeof raw.plugin === 'string' ? { pluginName: raw.plugin } : {}),
|
|
469
|
+
...(typeof raw.platform === 'string' ? { platform: raw.platform } : {}),
|
|
470
|
+
...(typeof raw.scope === 'string' ? { scope: raw.scope } : {}),
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
return null;
|
|
474
|
+
}
|
|
475
|
+
async function readOwnedHeaderReference(filePath, requireGeneratedName, errors, env, cwd) {
|
|
476
|
+
const stats = await inventoryRead({
|
|
477
|
+
operation: () => fs.stat(filePath),
|
|
478
|
+
absent: null,
|
|
479
|
+
errors,
|
|
480
|
+
location: filePath,
|
|
481
|
+
kind: 'ownerHeaderStat',
|
|
482
|
+
env,
|
|
483
|
+
cwd,
|
|
484
|
+
});
|
|
485
|
+
if (!stats?.isFile() || stats.size > 1024 * 1024)
|
|
486
|
+
return null;
|
|
487
|
+
const content = await inventoryRead({
|
|
488
|
+
operation: () => fs.readFile(filePath, 'utf8'),
|
|
489
|
+
absent: null,
|
|
490
|
+
errors,
|
|
491
|
+
location: filePath,
|
|
492
|
+
kind: 'ownerHeaderRead',
|
|
493
|
+
env,
|
|
494
|
+
cwd,
|
|
495
|
+
});
|
|
496
|
+
if (content === null)
|
|
497
|
+
return null;
|
|
498
|
+
if (!content.includes(OWNED_TEXT_HEADER_PREFIX))
|
|
499
|
+
return null;
|
|
500
|
+
let parsed;
|
|
501
|
+
try {
|
|
502
|
+
parsed = parseOwnedTextHeader(content);
|
|
503
|
+
}
|
|
504
|
+
catch (error) {
|
|
505
|
+
errors.push(inventoryError(error, filePath, 'ownerHeaderParse', env, cwd));
|
|
506
|
+
return null;
|
|
507
|
+
}
|
|
508
|
+
if (!parsed)
|
|
509
|
+
return null;
|
|
510
|
+
if (requireGeneratedName
|
|
511
|
+
&& !path.basename(filePath).startsWith(`aw-${parsed.identity.plugin}-`)) {
|
|
512
|
+
errors.push(inventoryError(new Error('Owned text header path does not match its plugin identity.'), filePath, 'ownerHeaderPathValidation', env, cwd));
|
|
513
|
+
return null;
|
|
514
|
+
}
|
|
515
|
+
return ownerReferenceFromRaw(filePath, {
|
|
516
|
+
schemaVersion: parsed.identity.sourceId === undefined ? 1 : 2,
|
|
517
|
+
...parsed.identity,
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
async function findOwnedHeadersInDirectory(directory, extensions, requireGeneratedName, errors, env, cwd) {
|
|
521
|
+
const output = [];
|
|
522
|
+
const entries = await inventoryRead({
|
|
523
|
+
operation: () => fs.readdir(directory, { withFileTypes: true }),
|
|
524
|
+
absent: [],
|
|
525
|
+
errors,
|
|
526
|
+
location: directory,
|
|
527
|
+
kind: 'ownerDirectoryRead',
|
|
528
|
+
env,
|
|
529
|
+
cwd,
|
|
530
|
+
});
|
|
531
|
+
for (const entry of entries) {
|
|
532
|
+
if (!entry.isFile() || entry.isSymbolicLink() || !extensions.has(path.extname(entry.name)))
|
|
533
|
+
continue;
|
|
534
|
+
const reference = await readOwnedHeaderReference(path.join(directory, entry.name), requireGeneratedName, errors, env, cwd);
|
|
535
|
+
if (reference)
|
|
536
|
+
output.push(reference);
|
|
537
|
+
}
|
|
538
|
+
return output;
|
|
539
|
+
}
|
|
540
|
+
function safeRelativeSkillRoot(value) {
|
|
541
|
+
if (typeof value !== 'string' || value.trim() === '')
|
|
542
|
+
return null;
|
|
543
|
+
const normalized = path.posix.normalize(value.replace(/^\.\//u, ''));
|
|
544
|
+
return normalized === '..' || normalized.startsWith('../') || path.isAbsolute(normalized)
|
|
545
|
+
? null
|
|
546
|
+
: normalized;
|
|
547
|
+
}
|
|
548
|
+
async function resolveCanonicalPluginSkillRoots(pluginRoot, includeLegacyFallbacks, errors, env, cwd) {
|
|
549
|
+
const [platformManifest, sourceManifest] = await Promise.all([
|
|
550
|
+
inventoryRead({
|
|
551
|
+
operation: () => fs.readJson(path.join(pluginRoot, '.codex-plugin', 'plugin.json')),
|
|
552
|
+
absent: null,
|
|
553
|
+
errors,
|
|
554
|
+
location: path.join(pluginRoot, '.codex-plugin', 'plugin.json'),
|
|
555
|
+
kind: 'pluginManifestRead',
|
|
556
|
+
env,
|
|
557
|
+
cwd,
|
|
558
|
+
}),
|
|
559
|
+
inventoryRead({
|
|
560
|
+
operation: () => fs.readJson(path.join(pluginRoot, '.agents-plugin', 'plugin.json')),
|
|
561
|
+
absent: null,
|
|
562
|
+
errors,
|
|
563
|
+
location: path.join(pluginRoot, '.agents-plugin', 'plugin.json'),
|
|
564
|
+
kind: 'pluginManifestRead',
|
|
565
|
+
env,
|
|
566
|
+
cwd,
|
|
567
|
+
}),
|
|
568
|
+
]);
|
|
569
|
+
const declared = safeRelativeSkillRoot(platformManifest?.skills ?? sourceManifest?.skills)
|
|
570
|
+
?? 'codex/skills';
|
|
571
|
+
return [...new Set([
|
|
572
|
+
path.join(pluginRoot, ...declared.split('/')),
|
|
573
|
+
...(includeLegacyFallbacks ? [
|
|
574
|
+
path.join(pluginRoot, 'skills'),
|
|
575
|
+
path.join(pluginRoot, 'codex', 'skills'),
|
|
576
|
+
] : []),
|
|
577
|
+
])];
|
|
578
|
+
}
|
|
579
|
+
async function findDirectSkillOwnerMarkers(root, errors, env, cwd) {
|
|
580
|
+
const output = [];
|
|
581
|
+
const entries = await inventoryRead({
|
|
582
|
+
operation: () => fs.readdir(root, { withFileTypes: true }),
|
|
583
|
+
absent: [],
|
|
584
|
+
errors,
|
|
585
|
+
location: root,
|
|
586
|
+
kind: 'skillRootRead',
|
|
587
|
+
env,
|
|
588
|
+
cwd,
|
|
589
|
+
});
|
|
590
|
+
for (const entry of entries) {
|
|
591
|
+
if (!entry.isDirectory() || entry.isSymbolicLink())
|
|
592
|
+
continue;
|
|
593
|
+
const skillRoot = path.join(root, entry.name);
|
|
594
|
+
const markerPath = path.join(root, entry.name, SKILL_OWNER_MARKER);
|
|
595
|
+
const markerStats = await inventoryRead({
|
|
596
|
+
operation: () => fs.lstat(markerPath),
|
|
597
|
+
absent: null,
|
|
598
|
+
errors,
|
|
599
|
+
location: markerPath,
|
|
600
|
+
kind: 'ownerMarkerRead',
|
|
601
|
+
env,
|
|
602
|
+
cwd,
|
|
603
|
+
});
|
|
604
|
+
if (!markerStats)
|
|
605
|
+
continue;
|
|
606
|
+
let marker;
|
|
607
|
+
try {
|
|
608
|
+
marker = await readSkillOwnerMarker({ skillRoot, allowedRoot: root });
|
|
609
|
+
}
|
|
610
|
+
catch (error) {
|
|
611
|
+
if (!isAbsentState(error)) {
|
|
612
|
+
const code = error.code;
|
|
613
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
614
|
+
errors.push(inventoryError(error, markerPath, code !== undefined || message.includes('JSON') ? 'ownerMarkerRead' : 'ownerMarkerValidation', env, cwd));
|
|
615
|
+
}
|
|
616
|
+
continue;
|
|
617
|
+
}
|
|
618
|
+
if (!marker)
|
|
619
|
+
continue;
|
|
620
|
+
const reference = ownerReferenceFromRaw(markerPath, { ...marker });
|
|
621
|
+
if (reference)
|
|
622
|
+
output.push(reference);
|
|
623
|
+
}
|
|
624
|
+
return output;
|
|
625
|
+
}
|
|
626
|
+
function sharedOwnerTokenReferences(filePath, tokens, errors, env, cwd) {
|
|
627
|
+
const output = [];
|
|
628
|
+
for (const token of new Set(tokens)) {
|
|
629
|
+
let identity;
|
|
630
|
+
try {
|
|
631
|
+
identity = parseSharedOwnerToken(token);
|
|
632
|
+
}
|
|
633
|
+
catch (error) {
|
|
634
|
+
errors.push(inventoryError(error, filePath, 'sharedOwnerTokenParse', env, cwd));
|
|
635
|
+
continue;
|
|
636
|
+
}
|
|
637
|
+
if (!identity?.sourceId)
|
|
638
|
+
continue;
|
|
639
|
+
output.push({
|
|
640
|
+
kind: 'namespacedOwner',
|
|
641
|
+
location: filePath,
|
|
642
|
+
sourceId: identity.sourceId,
|
|
643
|
+
sourceIdentity: identity.sourceIdentity,
|
|
644
|
+
pluginName: identity.plugin,
|
|
645
|
+
platform: identity.platform,
|
|
646
|
+
scope: identity.scope,
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
return output;
|
|
650
|
+
}
|
|
651
|
+
async function codexSharedOwnerReferences(filePath, scope, errors, env, cwd) {
|
|
652
|
+
const config = await readCodexConfigFile(filePath);
|
|
653
|
+
const ownerValues = [
|
|
654
|
+
...Object.keys(config.snapshot.developerInstructions.managedBlocks).map((value) => ({
|
|
655
|
+
value,
|
|
656
|
+
location: filePath,
|
|
657
|
+
})),
|
|
658
|
+
...Object.values(config.snapshot.mcpServers).flatMap((server) => {
|
|
659
|
+
const env = server.value?.env;
|
|
660
|
+
const value = isRecord(env) && typeof env.AW_AGENT_WORKFLOWS_OWNER === 'string'
|
|
661
|
+
? env.AW_AGENT_WORKFLOWS_OWNER
|
|
662
|
+
: null;
|
|
663
|
+
return value ? [{ value, location: filePath }] : [];
|
|
664
|
+
}),
|
|
665
|
+
];
|
|
666
|
+
const references = sharedOwnerTokenReferences(filePath, ownerValues.map((entry) => entry.value).filter((value) => value.startsWith('aw-owner-v2:')), errors, env, cwd);
|
|
667
|
+
for (const { value, location } of ownerValues) {
|
|
668
|
+
if (value.startsWith('aw-owner-v2:') || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(value))
|
|
669
|
+
continue;
|
|
670
|
+
references.push({
|
|
671
|
+
kind: 'legacyOwner',
|
|
672
|
+
location,
|
|
673
|
+
pluginName: value,
|
|
674
|
+
platform: 'codex',
|
|
675
|
+
scope,
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
return references;
|
|
679
|
+
}
|
|
680
|
+
async function claudeSharedOwnerReferences(filePath, scope, errors, env, cwd) {
|
|
681
|
+
const settings = await readJsonFileIfExists(filePath);
|
|
682
|
+
const generated = settings && isRecord(settings.awGenerated) ? settings.awGenerated : null;
|
|
683
|
+
const permissions = generated && isRecord(generated.permissions) ? generated.permissions : {};
|
|
684
|
+
const keys = Object.keys(permissions);
|
|
685
|
+
const references = sharedOwnerTokenReferences(filePath, keys.filter((token) => token.startsWith('aw-owner-v2:')), errors, env, cwd);
|
|
686
|
+
for (const key of keys) {
|
|
687
|
+
if (key.startsWith('aw-owner-v2:') || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(key))
|
|
688
|
+
continue;
|
|
689
|
+
references.push({
|
|
690
|
+
kind: 'legacyOwner',
|
|
691
|
+
location: filePath,
|
|
692
|
+
pluginName: key,
|
|
693
|
+
platform: 'claude',
|
|
694
|
+
scope,
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
return references;
|
|
698
|
+
}
|
|
699
|
+
async function codexHookOwnerReferences(filePath, errors, env, cwd) {
|
|
700
|
+
const raw = await readJsonFileIfExists(filePath);
|
|
701
|
+
if (!raw)
|
|
702
|
+
return [];
|
|
703
|
+
const parsed = parseCodexSharedHooksFile(raw);
|
|
704
|
+
const output = [];
|
|
705
|
+
for (const hook of parsed.managedIdentities) {
|
|
706
|
+
if (!hook.command.includes(OWNED_TEXT_HEADER_PREFIX))
|
|
707
|
+
continue;
|
|
708
|
+
let owner;
|
|
709
|
+
try {
|
|
710
|
+
owner = parseOwnedTextHeader(hook.command)?.identity;
|
|
711
|
+
}
|
|
712
|
+
catch (error) {
|
|
713
|
+
errors.push(inventoryError(error, filePath, 'ownerHeaderParse', env, cwd));
|
|
714
|
+
continue;
|
|
715
|
+
}
|
|
716
|
+
if (!owner)
|
|
717
|
+
continue;
|
|
718
|
+
output.push(owner.sourceId ? {
|
|
719
|
+
kind: 'namespacedOwner',
|
|
720
|
+
location: filePath,
|
|
721
|
+
sourceId: owner.sourceId,
|
|
722
|
+
sourceIdentity: owner.sourceIdentity,
|
|
723
|
+
pluginName: owner.plugin,
|
|
724
|
+
platform: owner.platform,
|
|
725
|
+
scope: owner.scope,
|
|
726
|
+
} : {
|
|
727
|
+
kind: 'legacyOwner',
|
|
728
|
+
location: filePath,
|
|
729
|
+
pluginName: owner.plugin,
|
|
730
|
+
platform: owner.platform,
|
|
731
|
+
scope: owner.scope,
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
return output;
|
|
735
|
+
}
|
|
736
|
+
function isRecord(value) {
|
|
737
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
738
|
+
}
|
|
739
|
+
function assertNamespacedConfigEnvelope(value, sourceId, pluginName) {
|
|
740
|
+
if (!isRecord(value)
|
|
741
|
+
|| value.schemaVersion !== 2
|
|
742
|
+
|| typeof value.sourceId !== 'string'
|
|
743
|
+
|| typeof value.sourceIdentity !== 'string'
|
|
744
|
+
|| !/^sha256:[0-9a-f]{64}$/u.test(value.sourceIdentity)
|
|
745
|
+
|| typeof value.pluginName !== 'string'
|
|
746
|
+
|| !isRecord(value.values)
|
|
747
|
+
|| Object.keys(value).some((key) => ![
|
|
748
|
+
'schemaVersion', 'sourceId', 'sourceIdentity', 'pluginName', 'values',
|
|
749
|
+
].includes(key))) {
|
|
750
|
+
throw new Error('Namespaced plugin config is not a valid schema 2 envelope.');
|
|
751
|
+
}
|
|
752
|
+
if (value.sourceId !== sourceId || value.pluginName !== pluginName) {
|
|
753
|
+
throw new Error('Namespaced plugin config identity does not match its directory path.');
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
function hasClaudeMarketplaceConsumer(value) {
|
|
757
|
+
if (Array.isArray(value))
|
|
758
|
+
return value.some(hasClaudeMarketplaceConsumer);
|
|
759
|
+
if (!isRecord(value))
|
|
760
|
+
return false;
|
|
761
|
+
if (value.marketplace === 'aw')
|
|
762
|
+
return true;
|
|
763
|
+
return Object.values(value).some(hasClaudeMarketplaceConsumer);
|
|
764
|
+
}
|
|
765
|
+
function isAwPluginConsumerKey(value) {
|
|
766
|
+
return value.length > '@aw'.length && value.endsWith('@aw');
|
|
767
|
+
}
|
|
768
|
+
function hasAwPluginConsumerKeys(value) {
|
|
769
|
+
return isRecord(value) && Object.keys(value).some(isAwPluginConsumerKey);
|
|
770
|
+
}
|
|
771
|
+
async function oldMarketplaceReferences(env, cwd, errors) {
|
|
772
|
+
const codexPath = path.join(getCodexHome(env), 'config.toml');
|
|
773
|
+
const claudeSettingsPath = path.join(getClaudeHome(env), 'settings.json');
|
|
774
|
+
const claudeKnownPath = path.join(getClaudeHome(env), 'plugins', 'known_marketplaces.json');
|
|
775
|
+
const claudeInstalledPath = path.join(getClaudeHome(env), 'plugins', 'installed_plugins.json');
|
|
776
|
+
const output = [];
|
|
777
|
+
const marketplacesRoot = path.join(resolveAwHome(env), 'marketplaces');
|
|
778
|
+
const namespacedPrimaryRoots = new Set();
|
|
779
|
+
const marketplaceEntries = await inventoryCanonicalDirectoryEntries({
|
|
780
|
+
errors, location: marketplacesRoot, kind: 'marketplaceDirectoryRead', env, cwd,
|
|
781
|
+
});
|
|
782
|
+
for (const entry of marketplaceEntries) {
|
|
783
|
+
const marketplaceRoot = path.join(marketplacesRoot, entry.name);
|
|
784
|
+
if (!await inventoryCanonicalDirectory({
|
|
785
|
+
errors, location: marketplaceRoot, kind: 'marketplaceRootValidation', env, cwd,
|
|
786
|
+
}))
|
|
787
|
+
continue;
|
|
788
|
+
const manifestPath = path.join(marketplacesRoot, entry.name, '.agents', 'plugins', 'marketplace.json');
|
|
789
|
+
const configPath = path.join(marketplacesRoot, entry.name, 'config.json');
|
|
790
|
+
const manifest = await inventoryRead({
|
|
791
|
+
operation: () => fs.readJson(manifestPath), absent: null, errors,
|
|
792
|
+
location: manifestPath, kind: 'marketplaceManifestRead', env, cwd,
|
|
793
|
+
});
|
|
794
|
+
const config = await inventoryRead({
|
|
795
|
+
operation: () => fs.readJson(configPath), absent: null, errors,
|
|
796
|
+
location: configPath, kind: 'marketplaceConfigRead', env, cwd,
|
|
797
|
+
});
|
|
798
|
+
if (manifest?.name === 'aw' && config?.schemaVersion === 2 && config.sourceId === entry.name) {
|
|
799
|
+
namespacedPrimaryRoots.add(path.normalize(path.join(marketplacesRoot, entry.name)));
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
const codex = await inventoryRead({
|
|
803
|
+
operation: () => readCodexConfigFile(codexPath), absent: null, errors,
|
|
804
|
+
location: codexPath, kind: 'nativeStateRead', env, cwd,
|
|
805
|
+
});
|
|
806
|
+
const codexAw = codex?.snapshot.marketplaces.aw;
|
|
807
|
+
const codexAwIsNamespaced = codexAw?.sourceType === 'local'
|
|
808
|
+
&& !codexAw.sourcePointsToManifest
|
|
809
|
+
&& namespacedPrimaryRoots.has(path.normalize(codexAw.source ?? ''));
|
|
810
|
+
if (codex && (Object.hasOwn(codex.snapshot.marketplaces, 'aw') || Object.keys(codex.snapshot.plugins).some(isAwPluginConsumerKey))
|
|
811
|
+
&& !codexAwIsNamespaced) {
|
|
812
|
+
output.push({ kind: 'legacyMarketplace', location: codexPath });
|
|
813
|
+
for (const pluginId of Object.keys(codex.snapshot.plugins)) {
|
|
814
|
+
const pluginName = pluginNameFromMarketplaceId(pluginId, 'aw');
|
|
815
|
+
if (pluginName)
|
|
816
|
+
output.push({
|
|
817
|
+
kind: 'legacyMarketplace',
|
|
818
|
+
location: codexPath,
|
|
819
|
+
pluginName,
|
|
820
|
+
platform: 'codex',
|
|
821
|
+
scope: 'user',
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
const settings = await inventoryRead({
|
|
826
|
+
operation: () => readClaudeSettings(claudeSettingsPath), absent: null, errors,
|
|
827
|
+
location: claudeSettingsPath, kind: 'nativeStateRead', env, cwd,
|
|
828
|
+
});
|
|
829
|
+
const known = await inventoryRead({
|
|
830
|
+
operation: () => readJsonFileIfExists(claudeKnownPath), absent: null, errors,
|
|
831
|
+
location: claudeKnownPath, kind: 'nativeStateRead', env, cwd,
|
|
832
|
+
});
|
|
833
|
+
const declarationPaths = [
|
|
834
|
+
settings?.extraKnownMarketplaces?.aw,
|
|
835
|
+
known?.aw,
|
|
836
|
+
isRecord(known?.marketplaces) ? known.marketplaces.aw : undefined,
|
|
837
|
+
].flatMap((value) => collectMarketplaceDeclarationPaths(value));
|
|
838
|
+
const claudeAwIsNamespaced = declarationPaths.length > 0
|
|
839
|
+
&& declarationPaths.every((entry) => namespacedPrimaryRoots.has(path.normalize(entry)));
|
|
840
|
+
if ((settings && (Object.hasOwn(settings.extraKnownMarketplaces ?? {}, 'aw')
|
|
841
|
+
|| hasAwPluginConsumerKeys(settings.enabledPlugins)
|
|
842
|
+
|| hasAwPluginConsumerKeys(settings.plugins?.installed)
|
|
843
|
+
|| hasClaudeMarketplaceConsumer(settings.plugins?.installed))) && !claudeAwIsNamespaced) {
|
|
844
|
+
output.push({ kind: 'legacyMarketplace', location: claudeSettingsPath });
|
|
845
|
+
for (const consumer of claudeConsumersFromSettings(settings, 'aw', 'user')) {
|
|
846
|
+
output.push({ kind: 'legacyMarketplace', location: claudeSettingsPath, ...consumer });
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
if (known && (Object.hasOwn(known, 'aw')
|
|
850
|
+
|| (isRecord(known.marketplaces) && Object.hasOwn(known.marketplaces, 'aw'))
|
|
851
|
+
|| hasClaudeMarketplaceConsumer(known)) && !claudeAwIsNamespaced) {
|
|
852
|
+
output.push({ kind: 'legacyMarketplace', location: claudeKnownPath });
|
|
853
|
+
}
|
|
854
|
+
const installed = await inventoryRead({
|
|
855
|
+
operation: () => readJsonFileIfExists(claudeInstalledPath), absent: null, errors,
|
|
856
|
+
location: claudeInstalledPath, kind: 'nativeStateRead', env, cwd,
|
|
857
|
+
});
|
|
858
|
+
if (installed && (hasAwPluginConsumerKeys(installed.plugins)
|
|
859
|
+
|| hasClaudeMarketplaceConsumer(installed.plugins)) && !claudeAwIsNamespaced) {
|
|
860
|
+
output.push({ kind: 'legacyMarketplace', location: claudeInstalledPath });
|
|
861
|
+
const canonicalProjectRoot = await inventoryRead({
|
|
862
|
+
operation: () => fs.realpath(resolveRepoRootSync(cwd)),
|
|
863
|
+
absent: path.resolve(resolveRepoRootSync(cwd)), errors,
|
|
864
|
+
location: resolveRepoRootSync(cwd), kind: 'projectRootRead', env, cwd,
|
|
865
|
+
});
|
|
866
|
+
try {
|
|
867
|
+
for (const consumer of claudeConsumersFromInstalled(installed, 'aw', path.normalize(canonicalProjectRoot), false)) {
|
|
868
|
+
output.push({ kind: 'legacyMarketplace', location: claudeInstalledPath, ...consumer });
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
catch (error) {
|
|
872
|
+
errors.push(inventoryError(error, claudeInstalledPath, 'nativeStateRead', env, cwd));
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
const projectSettingsPath = path.join(resolveRepoRootSync(cwd), '.claude', 'settings.json');
|
|
876
|
+
const projectSettings = await inventoryRead({
|
|
877
|
+
operation: () => readJsonFileIfExists(projectSettingsPath), absent: null, errors,
|
|
878
|
+
location: projectSettingsPath, kind: 'nativeStateRead', env, cwd,
|
|
879
|
+
});
|
|
880
|
+
if (!claudeAwIsNamespaced) {
|
|
881
|
+
for (const consumer of claudeConsumersFromSettings(projectSettings, 'aw', 'project')) {
|
|
882
|
+
output.push({ kind: 'legacyMarketplace', location: projectSettingsPath, ...consumer });
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
return output;
|
|
886
|
+
}
|
|
887
|
+
function collectMarketplaceDeclarationPaths(value) {
|
|
888
|
+
if (!isRecord(value))
|
|
889
|
+
return [];
|
|
890
|
+
const output = [];
|
|
891
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
892
|
+
if ((key === 'path' || key === 'installLocation') && typeof entry === 'string') {
|
|
893
|
+
output.push(entry);
|
|
894
|
+
}
|
|
895
|
+
else if (key === 'source' && typeof entry === 'string' && path.isAbsolute(entry)) {
|
|
896
|
+
output.push(entry);
|
|
897
|
+
}
|
|
898
|
+
else if (isRecord(entry)) {
|
|
899
|
+
output.push(...collectMarketplaceDeclarationPaths(entry));
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
return output;
|
|
903
|
+
}
|
|
904
|
+
function marketplaceNamesRegisteredAtRoot(value, marketplaceRoot) {
|
|
905
|
+
if (!isRecord(value))
|
|
906
|
+
return [];
|
|
907
|
+
return Object.entries(value).flatMap(([name, declaration]) => collectMarketplaceDeclarationPaths(declaration).some((candidate) => path.normalize(candidate) === path.normalize(marketplaceRoot))
|
|
908
|
+
? [name]
|
|
909
|
+
: []);
|
|
910
|
+
}
|
|
911
|
+
function sourceIdFromCanonicalMarketplacePath(candidate, marketplacesRoot) {
|
|
912
|
+
if (!path.isAbsolute(candidate))
|
|
913
|
+
return null;
|
|
914
|
+
const resolved = path.resolve(candidate);
|
|
915
|
+
const root = path.resolve(marketplacesRoot);
|
|
916
|
+
if (path.dirname(resolved) !== root)
|
|
917
|
+
return null;
|
|
918
|
+
const sourceId = path.basename(resolved);
|
|
919
|
+
return sourceId !== '' && sourceId !== '.' && sourceId !== '..' ? sourceId : null;
|
|
920
|
+
}
|
|
921
|
+
function registeredMarketplaceRoots(value, marketplacesRoot) {
|
|
922
|
+
if (!isRecord(value))
|
|
923
|
+
return [];
|
|
924
|
+
return Object.entries(value).flatMap(([marketplaceName, declaration]) => collectMarketplaceDeclarationPaths(declaration).flatMap((candidate) => {
|
|
925
|
+
const sourceId = sourceIdFromCanonicalMarketplacePath(candidate, marketplacesRoot);
|
|
926
|
+
return sourceId ? [{ marketplaceName, sourceId }] : [];
|
|
927
|
+
}));
|
|
928
|
+
}
|
|
929
|
+
export async function inventoryCatalogSourceReferences(options) {
|
|
930
|
+
const env = options.env ?? process.env;
|
|
931
|
+
const awHome = resolveAwHome(env);
|
|
932
|
+
const references = [];
|
|
933
|
+
const errors = [];
|
|
934
|
+
const legacyConfig = await inventoryLegacyConfigReferences(options);
|
|
935
|
+
references.push(...legacyConfig.references);
|
|
936
|
+
errors.push(...legacyConfig.errors);
|
|
937
|
+
for (const configRoot of await inventoryPluginConfigRoots({ errors, env, cwd: options.cwd })) {
|
|
938
|
+
const sourceEntries = await inventoryRead({
|
|
939
|
+
operation: () => fs.readdir(configRoot, { withFileTypes: true }),
|
|
940
|
+
absent: [], errors, location: configRoot, kind: 'configDirectoryRead', env, cwd: options.cwd,
|
|
941
|
+
});
|
|
942
|
+
for (const sourceEntry of sourceEntries) {
|
|
943
|
+
const sourceConfigRoot = path.join(configRoot, sourceEntry.name);
|
|
944
|
+
const pluginEntries = await inventoryCanonicalDirectoryEntries({
|
|
945
|
+
errors, location: sourceConfigRoot, kind: 'configNamespaceValidation', env, cwd: options.cwd,
|
|
946
|
+
});
|
|
947
|
+
for (const pluginEntry of pluginEntries) {
|
|
948
|
+
if (pluginEntry.name === 'config.json')
|
|
949
|
+
continue;
|
|
950
|
+
const pluginConfigRoot = path.join(sourceConfigRoot, pluginEntry.name);
|
|
951
|
+
if (!await inventoryCanonicalDirectory({
|
|
952
|
+
errors,
|
|
953
|
+
location: pluginConfigRoot,
|
|
954
|
+
kind: 'configPluginRootValidation',
|
|
955
|
+
env,
|
|
956
|
+
cwd: options.cwd,
|
|
957
|
+
}))
|
|
958
|
+
continue;
|
|
959
|
+
const configPath = path.join(configRoot, sourceEntry.name, pluginEntry.name, 'config.json');
|
|
960
|
+
const configStats = await inventoryRead({
|
|
961
|
+
operation: () => fs.lstat(configPath), absent: null, errors,
|
|
962
|
+
location: configPath, kind: 'configFileRead', env, cwd: options.cwd,
|
|
963
|
+
});
|
|
964
|
+
if (configStats === null)
|
|
965
|
+
continue;
|
|
966
|
+
if (!configStats.isFile() || configStats.isSymbolicLink()) {
|
|
967
|
+
errors.push(inventoryError(new Error('Config inventory target must be a regular file.'), configPath, 'configFileValidation', env, options.cwd));
|
|
968
|
+
continue;
|
|
969
|
+
}
|
|
970
|
+
const value = await inventoryRead({
|
|
971
|
+
operation: () => fs.readJson(configPath), absent: null, errors,
|
|
972
|
+
location: configPath, kind: 'configFileRead', env, cwd: options.cwd,
|
|
973
|
+
});
|
|
974
|
+
if (value === null)
|
|
975
|
+
continue;
|
|
976
|
+
try {
|
|
977
|
+
assertNamespacedConfigEnvelope(value, sourceEntry.name, pluginEntry.name);
|
|
978
|
+
}
|
|
979
|
+
catch (error) {
|
|
980
|
+
errors.push(inventoryError(error, configPath, 'configFileValidation', env, options.cwd));
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
references.push({
|
|
984
|
+
kind: 'namespacedConfig',
|
|
985
|
+
location: configPath,
|
|
986
|
+
sourceId: sourceEntry.name,
|
|
987
|
+
sourceIdentity: value.sourceIdentity,
|
|
988
|
+
pluginName: pluginEntry.name,
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
const lifecycleRoot = path.join(awHome, 'lifecycle-active');
|
|
994
|
+
const lifecycleSources = await inventoryCanonicalDirectoryEntries({
|
|
995
|
+
errors, location: lifecycleRoot, kind: 'lifecycleDirectoryRead', env, cwd: options.cwd,
|
|
996
|
+
});
|
|
997
|
+
for (const platform of ['codex', 'claude']) {
|
|
998
|
+
const legacyRoot = path.join(lifecycleRoot, platform);
|
|
999
|
+
if (!lifecycleSources.some((entry) => entry.name === platform))
|
|
1000
|
+
continue;
|
|
1001
|
+
const legacyEntries = await inventoryCanonicalDirectoryEntries({
|
|
1002
|
+
errors, location: legacyRoot, kind: 'lifecycleNamespaceValidation', env, cwd: options.cwd,
|
|
1003
|
+
});
|
|
1004
|
+
if (legacyEntries.length > 0) {
|
|
1005
|
+
references.push({ kind: 'legacyLifecycle', location: legacyRoot });
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
const canonicalProjectRoot = await inventoryRead({
|
|
1009
|
+
operation: () => fs.realpath(resolveRepoRootSync(options.cwd)),
|
|
1010
|
+
absent: path.resolve(resolveRepoRootSync(options.cwd)), errors,
|
|
1011
|
+
location: resolveRepoRootSync(options.cwd), kind: 'projectRootRead', env, cwd: options.cwd,
|
|
1012
|
+
});
|
|
1013
|
+
const projectLocationKey = createLifecycleProjectLocationKey(canonicalProjectRoot);
|
|
1014
|
+
for (const sourceEntry of lifecycleSources) {
|
|
1015
|
+
if (sourceEntry.name === 'codex' || sourceEntry.name === 'claude')
|
|
1016
|
+
continue;
|
|
1017
|
+
const sourceLifecycleRoot = path.join(lifecycleRoot, sourceEntry.name);
|
|
1018
|
+
if (!await inventoryCanonicalDirectory({
|
|
1019
|
+
errors,
|
|
1020
|
+
location: sourceLifecycleRoot,
|
|
1021
|
+
kind: 'lifecycleNamespaceValidation',
|
|
1022
|
+
env,
|
|
1023
|
+
cwd: options.cwd,
|
|
1024
|
+
}))
|
|
1025
|
+
continue;
|
|
1026
|
+
const relevantRoots = [];
|
|
1027
|
+
for (const platform of ['codex', 'claude']) {
|
|
1028
|
+
const userRoot = await inventoryCanonicalDescendantDirectory({
|
|
1029
|
+
root: sourceLifecycleRoot,
|
|
1030
|
+
segments: [platform, 'user', 'user'],
|
|
1031
|
+
errors,
|
|
1032
|
+
kind: 'lifecycleDirectoryRead',
|
|
1033
|
+
env,
|
|
1034
|
+
cwd: options.cwd,
|
|
1035
|
+
});
|
|
1036
|
+
if (userRoot)
|
|
1037
|
+
relevantRoots.push(userRoot);
|
|
1038
|
+
const projectRoot = await inventoryCanonicalDescendantDirectory({
|
|
1039
|
+
root: sourceLifecycleRoot,
|
|
1040
|
+
segments: [platform, 'project'],
|
|
1041
|
+
errors,
|
|
1042
|
+
kind: 'lifecycleDirectoryRead',
|
|
1043
|
+
env,
|
|
1044
|
+
cwd: options.cwd,
|
|
1045
|
+
});
|
|
1046
|
+
if (!projectRoot)
|
|
1047
|
+
continue;
|
|
1048
|
+
if (options.includeHistoricalProjects) {
|
|
1049
|
+
const projectLocations = await inventoryRead({
|
|
1050
|
+
operation: () => fs.readdir(projectRoot, { withFileTypes: true }),
|
|
1051
|
+
absent: [], errors, location: projectRoot, kind: 'lifecycleDirectoryRead', env, cwd: options.cwd,
|
|
1052
|
+
});
|
|
1053
|
+
for (const location of projectLocations) {
|
|
1054
|
+
const projectLocationRoot = path.join(projectRoot, location.name);
|
|
1055
|
+
if (await inventoryCanonicalDirectory({
|
|
1056
|
+
errors,
|
|
1057
|
+
location: projectLocationRoot,
|
|
1058
|
+
kind: 'lifecycleLocationValidation',
|
|
1059
|
+
env,
|
|
1060
|
+
cwd: options.cwd,
|
|
1061
|
+
}))
|
|
1062
|
+
relevantRoots.push(projectLocationRoot);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
else {
|
|
1066
|
+
const projectLocationRoot = path.join(projectRoot, projectLocationKey);
|
|
1067
|
+
if (await inventoryCanonicalDirectory({
|
|
1068
|
+
errors,
|
|
1069
|
+
location: projectLocationRoot,
|
|
1070
|
+
kind: 'lifecycleLocationValidation',
|
|
1071
|
+
env,
|
|
1072
|
+
cwd: options.cwd,
|
|
1073
|
+
}))
|
|
1074
|
+
relevantRoots.push(projectLocationRoot);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
for (const relevantRoot of relevantRoots) {
|
|
1078
|
+
const pluginEntries = await inventoryRead({
|
|
1079
|
+
operation: () => fs.readdir(relevantRoot, { withFileTypes: true }),
|
|
1080
|
+
absent: [], errors, location: relevantRoot, kind: 'lifecycleDirectoryRead', env, cwd: options.cwd,
|
|
1081
|
+
});
|
|
1082
|
+
const parts = path.relative(sourceLifecycleRoot, relevantRoot).split(path.sep);
|
|
1083
|
+
const platform = parts[0];
|
|
1084
|
+
const scope = parts[1];
|
|
1085
|
+
if ((platform !== 'codex' && platform !== 'claude')
|
|
1086
|
+
|| (scope !== 'user' && scope !== 'project'))
|
|
1087
|
+
continue;
|
|
1088
|
+
for (const pluginEntry of pluginEntries) {
|
|
1089
|
+
const pluginName = pluginEntry.name;
|
|
1090
|
+
const pluginRoot = path.join(relevantRoot, pluginName);
|
|
1091
|
+
if (!await inventoryCanonicalDirectory({
|
|
1092
|
+
errors,
|
|
1093
|
+
location: pluginRoot,
|
|
1094
|
+
kind: 'lifecyclePluginRootValidation',
|
|
1095
|
+
env,
|
|
1096
|
+
cwd: options.cwd,
|
|
1097
|
+
}))
|
|
1098
|
+
continue;
|
|
1099
|
+
const metadataPath = path.join(relevantRoot, pluginName, 'active', 'metadata.json');
|
|
1100
|
+
const raw = await inventoryRead({
|
|
1101
|
+
operation: () => fs.readJson(metadataPath), absent: null, errors,
|
|
1102
|
+
location: metadataPath, kind: 'lifecycleMetadataRead', env, cwd: options.cwd,
|
|
1103
|
+
});
|
|
1104
|
+
if (!raw)
|
|
1105
|
+
continue;
|
|
1106
|
+
if (raw.schemaVersion !== 2 || typeof raw.sourceIdentity !== 'string') {
|
|
1107
|
+
errors.push(inventoryError(new Error('Lifecycle active metadata is not valid schema 2 state.'), metadataPath, 'lifecycleMetadataValidation', env, options.cwd));
|
|
1108
|
+
continue;
|
|
1109
|
+
}
|
|
1110
|
+
const snapshot = await inventoryRead({
|
|
1111
|
+
operation: () => inspectLifecycleActiveSnapshotForInventory({
|
|
1112
|
+
sourceId: sourceEntry.name,
|
|
1113
|
+
sourceIdentity: raw.sourceIdentity,
|
|
1114
|
+
pluginName,
|
|
1115
|
+
platform,
|
|
1116
|
+
scope,
|
|
1117
|
+
cwd: scope === 'project' && typeof raw.projectKey === 'string'
|
|
1118
|
+
? raw.projectKey
|
|
1119
|
+
: options.cwd,
|
|
1120
|
+
env,
|
|
1121
|
+
loadPlugin: (bundleRoot) => readPluginManifest(bundleRoot, { mode: 'bundle' }),
|
|
1122
|
+
}),
|
|
1123
|
+
absent: null,
|
|
1124
|
+
errors,
|
|
1125
|
+
location: metadataPath,
|
|
1126
|
+
kind: 'lifecycleSnapshotValidation',
|
|
1127
|
+
env,
|
|
1128
|
+
cwd: options.cwd,
|
|
1129
|
+
});
|
|
1130
|
+
if (!snapshot)
|
|
1131
|
+
continue;
|
|
1132
|
+
references.push({
|
|
1133
|
+
kind: 'namespacedLifecycle',
|
|
1134
|
+
location: snapshot.activeRoot,
|
|
1135
|
+
sourceId: snapshot.metadata.sourceId,
|
|
1136
|
+
sourceIdentity: snapshot.metadata.sourceIdentity,
|
|
1137
|
+
pluginName: snapshot.metadata.pluginName,
|
|
1138
|
+
platform: snapshot.metadata.platform,
|
|
1139
|
+
scope: snapshot.metadata.scope,
|
|
1140
|
+
projectKey: snapshot.metadata.projectKey,
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
const ownerInventory = await inventoryLegacyOwnerReferences(options);
|
|
1146
|
+
references.push(...ownerInventory.references);
|
|
1147
|
+
errors.push(...ownerInventory.errors);
|
|
1148
|
+
for (const [location, kind, operation] of [
|
|
1149
|
+
[path.join(getCodexHome(env), 'config.toml'), 'nativeStateRead', () => codexSharedOwnerReferences(path.join(getCodexHome(env), 'config.toml'), 'user', errors, env, options.cwd)],
|
|
1150
|
+
[path.join(getClaudeHome(env), 'settings.json'), 'nativeStateRead', () => claudeSharedOwnerReferences(path.join(getClaudeHome(env), 'settings.json'), 'user', errors, env, options.cwd)],
|
|
1151
|
+
[path.join(resolveRepoRootSync(options.cwd), '.codex', 'config.toml'), 'nativeStateRead', () => codexSharedOwnerReferences(path.join(resolveRepoRootSync(options.cwd), '.codex', 'config.toml'), 'project', errors, env, options.cwd)],
|
|
1152
|
+
[path.join(resolveRepoRootSync(options.cwd), '.claude', 'settings.json'), 'nativeStateRead', () => claudeSharedOwnerReferences(path.join(resolveRepoRootSync(options.cwd), '.claude', 'settings.json'), 'project', errors, env, options.cwd)],
|
|
1153
|
+
[path.join(resolveRepoRootSync(options.cwd), '.codex', 'hooks.json'), 'nativeStateRead', () => codexHookOwnerReferences(path.join(resolveRepoRootSync(options.cwd), '.codex', 'hooks.json'), errors, env, options.cwd)],
|
|
1154
|
+
]) {
|
|
1155
|
+
references.push(...await inventoryRead({
|
|
1156
|
+
operation, absent: [], errors, location, kind, env, cwd: options.cwd,
|
|
1157
|
+
}));
|
|
1158
|
+
}
|
|
1159
|
+
references.push(...await oldMarketplaceReferences(env, options.cwd, errors));
|
|
1160
|
+
const marketplacesRoot = path.join(awHome, 'marketplaces');
|
|
1161
|
+
const codexConfigPath = path.join(getCodexHome(env), 'config.toml');
|
|
1162
|
+
const codexConfig = await inventoryRead({
|
|
1163
|
+
operation: () => readCodexConfigFile(codexConfigPath), absent: null, errors,
|
|
1164
|
+
location: codexConfigPath, kind: 'nativeStateRead', env, cwd: options.cwd,
|
|
1165
|
+
});
|
|
1166
|
+
const userClaudeSettingsPath = path.join(getClaudeHome(env), 'settings.json');
|
|
1167
|
+
const userClaudeSettings = await inventoryRead({
|
|
1168
|
+
operation: () => readJsonFileIfExists(userClaudeSettingsPath), absent: null, errors,
|
|
1169
|
+
location: userClaudeSettingsPath, kind: 'nativeStateRead', env, cwd: options.cwd,
|
|
1170
|
+
});
|
|
1171
|
+
const projectClaudeSettingsPath = path.join(resolveRepoRootSync(options.cwd), '.claude', 'settings.json');
|
|
1172
|
+
const projectClaudeSettings = await inventoryRead({
|
|
1173
|
+
operation: () => readJsonFileIfExists(projectClaudeSettingsPath), absent: null, errors,
|
|
1174
|
+
location: projectClaudeSettingsPath, kind: 'nativeStateRead', env, cwd: options.cwd,
|
|
1175
|
+
});
|
|
1176
|
+
const claudeKnownPath = path.join(getClaudeHome(env), 'plugins', 'known_marketplaces.json');
|
|
1177
|
+
const claudeKnown = await inventoryRead({
|
|
1178
|
+
operation: () => readJsonFileIfExists(claudeKnownPath), absent: null, errors,
|
|
1179
|
+
location: claudeKnownPath, kind: 'nativeStateRead', env, cwd: options.cwd,
|
|
1180
|
+
});
|
|
1181
|
+
const claudeInstalledPath = path.join(getClaudeHome(env), 'plugins', 'installed_plugins.json');
|
|
1182
|
+
const claudeInstalled = await inventoryRead({
|
|
1183
|
+
operation: () => readJsonFileIfExists(claudeInstalledPath), absent: null, errors,
|
|
1184
|
+
location: claudeInstalledPath, kind: 'nativeStateRead', env, cwd: options.cwd,
|
|
1185
|
+
});
|
|
1186
|
+
const marketplaceEntries = await inventoryCanonicalDirectoryEntries({
|
|
1187
|
+
errors, location: marketplacesRoot, kind: 'marketplaceDirectoryRead', env, cwd: options.cwd,
|
|
1188
|
+
});
|
|
1189
|
+
for (const pluginId of Object.keys(codexConfig?.snapshot.plugins ?? {})) {
|
|
1190
|
+
const separator = pluginId.lastIndexOf('@');
|
|
1191
|
+
if (separator <= 0 || separator === pluginId.length - 1)
|
|
1192
|
+
continue;
|
|
1193
|
+
references.push({
|
|
1194
|
+
kind: 'namespacedMarketplace',
|
|
1195
|
+
location: codexConfigPath,
|
|
1196
|
+
pluginName: pluginId.slice(0, separator),
|
|
1197
|
+
marketplaceName: pluginId.slice(separator + 1),
|
|
1198
|
+
platform: 'codex',
|
|
1199
|
+
scope: 'user',
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
for (const [location, registrations] of [
|
|
1203
|
+
[codexConfigPath, Object.entries(codexConfig?.snapshot.marketplaces ?? {}).flatMap(([marketplaceName, marketplace]) => {
|
|
1204
|
+
const sourceId = marketplace.sourceType === 'local' && !marketplace.sourcePointsToManifest
|
|
1205
|
+
&& marketplace.source
|
|
1206
|
+
? sourceIdFromCanonicalMarketplacePath(marketplace.source, marketplacesRoot)
|
|
1207
|
+
: null;
|
|
1208
|
+
return sourceId ? [{ marketplaceName, sourceId }] : [];
|
|
1209
|
+
})],
|
|
1210
|
+
[userClaudeSettingsPath, registeredMarketplaceRoots(userClaudeSettings?.extraKnownMarketplaces, marketplacesRoot)],
|
|
1211
|
+
[projectClaudeSettingsPath, registeredMarketplaceRoots(projectClaudeSettings?.extraKnownMarketplaces, marketplacesRoot)],
|
|
1212
|
+
[claudeKnownPath, [
|
|
1213
|
+
...registeredMarketplaceRoots(claudeKnown, marketplacesRoot),
|
|
1214
|
+
...registeredMarketplaceRoots(claudeKnown?.marketplaces, marketplacesRoot),
|
|
1215
|
+
]],
|
|
1216
|
+
]) {
|
|
1217
|
+
for (const registration of registrations)
|
|
1218
|
+
references.push({
|
|
1219
|
+
kind: 'namespacedMarketplace',
|
|
1220
|
+
location,
|
|
1221
|
+
sourceId: registration.sourceId,
|
|
1222
|
+
marketplaceName: registration.marketplaceName,
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
for (const sourceEntry of marketplaceEntries) {
|
|
1226
|
+
const marketplaceRoot = path.join(marketplacesRoot, sourceEntry.name);
|
|
1227
|
+
const configPath = path.join(marketplaceRoot, 'config.json');
|
|
1228
|
+
const agentsManifestPath = path.join(marketplaceRoot, '.agents', 'plugins', 'marketplace.json');
|
|
1229
|
+
const canonicalRoot = await inventoryCanonicalDirectory({
|
|
1230
|
+
errors,
|
|
1231
|
+
location: marketplaceRoot,
|
|
1232
|
+
kind: 'marketplaceRootValidation',
|
|
1233
|
+
env,
|
|
1234
|
+
cwd: options.cwd,
|
|
1235
|
+
});
|
|
1236
|
+
const strictRoot = canonicalRoot
|
|
1237
|
+
? await inventoryRead({
|
|
1238
|
+
operation: () => readStrictNamespacedMarketplaceRoot({
|
|
1239
|
+
rootDir: marketplaceRoot,
|
|
1240
|
+
sourceId: sourceEntry.name,
|
|
1241
|
+
}),
|
|
1242
|
+
absent: null,
|
|
1243
|
+
reportAbsent: true,
|
|
1244
|
+
errors,
|
|
1245
|
+
location: marketplaceRoot,
|
|
1246
|
+
kind: 'marketplaceRootValidation',
|
|
1247
|
+
env,
|
|
1248
|
+
cwd: options.cwd,
|
|
1249
|
+
})
|
|
1250
|
+
: null;
|
|
1251
|
+
const [rawConfig, rawAgentsManifest, rawClaudeManifest] = strictRoot
|
|
1252
|
+
? [strictRoot.config, strictRoot.agentsManifest, strictRoot.claudeManifest]
|
|
1253
|
+
: canonicalRoot ? await Promise.all([
|
|
1254
|
+
fs.readJson(configPath).catch(() => null),
|
|
1255
|
+
fs.readJson(agentsManifestPath).catch(() => null),
|
|
1256
|
+
fs.readJson(path.join(marketplaceRoot, '.claude-plugin', 'marketplace.json'))
|
|
1257
|
+
.catch(() => null),
|
|
1258
|
+
]) : [null, null, null];
|
|
1259
|
+
const candidateMarketplaceNames = new Set();
|
|
1260
|
+
for (const candidate of [
|
|
1261
|
+
rawConfig?.marketplaceName,
|
|
1262
|
+
rawAgentsManifest?.name,
|
|
1263
|
+
rawClaudeManifest?.name,
|
|
1264
|
+
]) {
|
|
1265
|
+
if (typeof candidate === 'string' && candidate.length > 0) {
|
|
1266
|
+
candidateMarketplaceNames.add(candidate);
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
for (const [name, marketplace] of Object.entries(codexConfig?.snapshot.marketplaces ?? {})) {
|
|
1270
|
+
if (marketplace.sourceType === 'local'
|
|
1271
|
+
&& !marketplace.sourcePointsToManifest
|
|
1272
|
+
&& path.normalize(marketplace.source ?? '') === path.normalize(marketplaceRoot)) {
|
|
1273
|
+
candidateMarketplaceNames.add(name);
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
for (const name of [
|
|
1277
|
+
...marketplaceNamesRegisteredAtRoot(userClaudeSettings?.extraKnownMarketplaces, marketplaceRoot),
|
|
1278
|
+
...marketplaceNamesRegisteredAtRoot(projectClaudeSettings?.extraKnownMarketplaces, marketplaceRoot),
|
|
1279
|
+
...marketplaceNamesRegisteredAtRoot(claudeKnown, marketplaceRoot),
|
|
1280
|
+
...marketplaceNamesRegisteredAtRoot(claudeKnown?.marketplaces, marketplaceRoot),
|
|
1281
|
+
])
|
|
1282
|
+
candidateMarketplaceNames.add(name);
|
|
1283
|
+
const marketplaceName = strictRoot?.config.marketplaceName
|
|
1284
|
+
?? (candidateMarketplaceNames.size === 1 ? [...candidateMarketplaceNames][0] : null);
|
|
1285
|
+
const sourceIdentity = typeof rawConfig?.sourceIdentity === 'string'
|
|
1286
|
+
&& /^sha256:[0-9a-f]{64}$/.test(rawConfig.sourceIdentity)
|
|
1287
|
+
? rawConfig.sourceIdentity
|
|
1288
|
+
: undefined;
|
|
1289
|
+
const codexMarketplace = marketplaceName
|
|
1290
|
+
? codexConfig?.snapshot.marketplaces[marketplaceName]
|
|
1291
|
+
: undefined;
|
|
1292
|
+
const codexMarketplaceIsCanonical = codexMarketplace?.sourceType === 'local'
|
|
1293
|
+
&& !codexMarketplace.sourcePointsToManifest
|
|
1294
|
+
&& path.normalize(codexMarketplace.source ?? '') === path.normalize(marketplaceRoot);
|
|
1295
|
+
const consumers = [];
|
|
1296
|
+
if (marketplaceName !== null
|
|
1297
|
+
&& (strictRoot !== null || (canonicalRoot && codexMarketplaceIsCanonical))) {
|
|
1298
|
+
let residueNames = [];
|
|
1299
|
+
try {
|
|
1300
|
+
residueNames = await discoverCodexNativeResidueNames({
|
|
1301
|
+
cwd: options.cwd,
|
|
1302
|
+
env,
|
|
1303
|
+
marketplaceName,
|
|
1304
|
+
marketplaceRoot,
|
|
1305
|
+
});
|
|
1306
|
+
}
|
|
1307
|
+
catch (error) {
|
|
1308
|
+
const residueError = error instanceof CodexNativeResidueProbeError ? error : null;
|
|
1309
|
+
const pluginName = residueError?.pluginName;
|
|
1310
|
+
errors.push(inventoryError(error, residueError?.location ?? configPath, 'nativeStateRead', env, options.cwd, {
|
|
1311
|
+
global: false,
|
|
1312
|
+
sourceId: sourceEntry.name,
|
|
1313
|
+
...(pluginName ? { pluginName } : {}),
|
|
1314
|
+
platform: 'codex',
|
|
1315
|
+
scope: 'user',
|
|
1316
|
+
}));
|
|
1317
|
+
}
|
|
1318
|
+
for (const pluginName of residueNames) {
|
|
1319
|
+
consumers.push({ pluginName, platform: 'codex', scope: 'user' });
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
if (marketplaceName !== null && (strictRoot !== null || codexMarketplaceIsCanonical)) {
|
|
1323
|
+
for (const pluginId of Object.keys(codexConfig?.snapshot.plugins ?? {})) {
|
|
1324
|
+
const pluginName = pluginNameFromMarketplaceId(pluginId, marketplaceName);
|
|
1325
|
+
if (pluginName)
|
|
1326
|
+
consumers.push({ pluginName, platform: 'codex', scope: 'user' });
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
if (marketplaceName !== null) {
|
|
1330
|
+
consumers.push(...claudeConsumersFromSettings(userClaudeSettings, marketplaceName, 'user'), ...claudeConsumersFromSettings(projectClaudeSettings, marketplaceName, 'project'));
|
|
1331
|
+
try {
|
|
1332
|
+
consumers.push(...claudeConsumersFromInstalled(claudeInstalled, marketplaceName, path.normalize(canonicalProjectRoot), options.includeHistoricalProjects === true));
|
|
1333
|
+
}
|
|
1334
|
+
catch (error) {
|
|
1335
|
+
errors.push(inventoryError(error, claudeInstalledPath, 'nativeStateRead', env, options.cwd));
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
if (marketplaceName !== null && strictRoot !== null) {
|
|
1339
|
+
references.push({
|
|
1340
|
+
kind: 'namespacedMarketplace',
|
|
1341
|
+
location: configPath,
|
|
1342
|
+
sourceId: sourceEntry.name,
|
|
1343
|
+
...(sourceIdentity ? { sourceIdentity } : {}),
|
|
1344
|
+
marketplaceName,
|
|
1345
|
+
});
|
|
1346
|
+
}
|
|
1347
|
+
if (marketplaceName !== null) {
|
|
1348
|
+
for (const consumer of consumers)
|
|
1349
|
+
references.push({
|
|
1350
|
+
kind: 'namespacedMarketplace',
|
|
1351
|
+
location: configPath,
|
|
1352
|
+
sourceId: sourceEntry.name,
|
|
1353
|
+
...(sourceIdentity ? { sourceIdentity } : {}),
|
|
1354
|
+
marketplaceName,
|
|
1355
|
+
...consumer,
|
|
1356
|
+
});
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
for (const reference of references) {
|
|
1360
|
+
if (reference.scope === 'project' && reference.projectKey === undefined) {
|
|
1361
|
+
reference.projectKey = canonicalProjectRoot;
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
const unique = [...new Map(references.map((reference) => [[
|
|
1365
|
+
reference.kind,
|
|
1366
|
+
reference.location,
|
|
1367
|
+
reference.sourceId ?? '',
|
|
1368
|
+
reference.sourceIdentity ?? '',
|
|
1369
|
+
reference.pluginName ?? '',
|
|
1370
|
+
reference.platform ?? '',
|
|
1371
|
+
reference.scope ?? '',
|
|
1372
|
+
reference.marketplaceName ?? '',
|
|
1373
|
+
reference.projectKey ?? '',
|
|
1374
|
+
].join('\0'), reference])).values()];
|
|
1375
|
+
unique.sort((left, right) => left.location.localeCompare(right.location));
|
|
1376
|
+
return { inventorySchemaVersion: 1, references: unique, errors };
|
|
1377
|
+
}
|
|
1378
|
+
export class LegacyCatalogStateUnsupportedError extends Error {
|
|
1379
|
+
code = 'legacyStateUnsupported';
|
|
1380
|
+
inventory;
|
|
1381
|
+
constructor(inventory) {
|
|
1382
|
+
super('legacyStateUnsupported: legacy owner, config, lifecycle, or marketplace state must be migrated before catalog source identity changes.');
|
|
1383
|
+
this.name = 'LegacyCatalogStateUnsupportedError';
|
|
1384
|
+
this.inventory = inventory;
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
export class CatalogSourceReferencedError extends Error {
|
|
1388
|
+
code = 'catalogSourceInUse';
|
|
1389
|
+
inventory;
|
|
1390
|
+
constructor(inventory) {
|
|
1391
|
+
super(`catalogSourceInUse: catalog source has active references: ${inventory.references.map((reference) => reference.location).join(', ')}`);
|
|
1392
|
+
this.name = 'CatalogSourceReferencedError';
|
|
1393
|
+
this.inventory = inventory;
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
export class CatalogSourceInventoryIncompleteError extends Error {
|
|
1397
|
+
code = 'stateInventoryFailed';
|
|
1398
|
+
inventory;
|
|
1399
|
+
constructor(inventory) {
|
|
1400
|
+
super(`stateInventoryFailed: catalog source state inventory is incomplete: ${(inventory.errors ?? []).map((error) => `${error.kind}@${error.location}: ${error.message}`).join('; ')}`);
|
|
1401
|
+
this.name = 'CatalogSourceInventoryIncompleteError';
|
|
1402
|
+
this.inventory = inventory;
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
export function assertCatalogSourceInventoryComplete(inventory) {
|
|
1406
|
+
if ((inventory.errors ?? []).length > 0)
|
|
1407
|
+
throw new CatalogSourceInventoryIncompleteError(inventory);
|
|
1408
|
+
}
|
|
1409
|
+
export function assertCatalogSourceReferencesSupported(inventory) {
|
|
1410
|
+
assertCatalogSourceInventoryComplete(inventory);
|
|
1411
|
+
if (inventory.references.length > 0) {
|
|
1412
|
+
if (inventory.references.some((reference) => reference.kind.startsWith('legacy'))) {
|
|
1413
|
+
throw new LegacyCatalogStateUnsupportedError(inventory);
|
|
1414
|
+
}
|
|
1415
|
+
throw new CatalogSourceReferencedError(inventory);
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
//# sourceMappingURL=catalog-source-references.js.map
|