@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,1268 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { promisify } from 'node:util';
|
|
6
|
+
import fs from 'fs-extra';
|
|
7
|
+
import { renderResolvedHooksArtifact } from './hooks.js';
|
|
8
|
+
import { buildGeneratedName } from './shared.js';
|
|
9
|
+
import { applyFileRules } from '../utils/file-rules.js';
|
|
10
|
+
import { calculateFileDigest } from '../utils/bundle-integrity.js';
|
|
11
|
+
import { resolveCanonicalRuntimeSourceIdentity } from '../utils/catalog-runtime-projection.js';
|
|
12
|
+
import { getArtifactSourceBundleRelativePath } from '../utils/artifact-sources.js';
|
|
13
|
+
import { resolvePlatformHookDefinitions } from '../utils/hooks-contract.js';
|
|
14
|
+
import { assertManifestPlatformSupport, assertPluginInputTree, createBundleSourceManifest, createPlatformManifestBase, isIgnoredPluginInputDirectory, normalizePluginRelativePath, readPluginManifest, } from '../utils/manifest.js';
|
|
15
|
+
import { writeJsonFile } from '../utils/json.js';
|
|
16
|
+
import { resolveSupportedPlatforms } from '../utils/platform-support.js';
|
|
17
|
+
import { renderTemplate } from '../utils/template-engine.js';
|
|
18
|
+
import { resolvePlatformEntries } from '../utils/platform-entries.js';
|
|
19
|
+
import { scanNodeImportContract } from '../utils/plugin-script-contract.js';
|
|
20
|
+
import { isSkillAuthorOnlyPath, isSkillCollectionAuthorOnlyPath, } from '../utils/skill-authoring.js';
|
|
21
|
+
import { assertTestWritablePath } from '../utils/test-path-fence.js';
|
|
22
|
+
import { resolveCliPackageRoot } from '../utils/paths.js';
|
|
23
|
+
import { validateRuntimeSkillClosuresRoot, validateSkillRuntimeProjectionFreshness, } from '../utils/runtime-skill-closure.js';
|
|
24
|
+
import { validatePortableSkillDirectoriesRoot } from '../utils/dynamic-skill-tree.js';
|
|
25
|
+
import { renderClaudeSlashCommand, renderCodexSlashCommandOpenAiYaml, renderCodexSlashCommandSkillMarkdown, resolveSlashCommands, } from '../utils/slash-commands.js';
|
|
26
|
+
const execFileAsync = promisify(execFile);
|
|
27
|
+
const requireFromCli = createRequire(import.meta.url);
|
|
28
|
+
const NODE_RUNTIME_EXTENSIONS = new Set(['.js', '.mjs', '.cjs']);
|
|
29
|
+
const INSTALL_SCRIPT_NAMES = ['preinstall', 'install', 'postinstall', 'prepare'];
|
|
30
|
+
const PLATFORM_ORDER = ['claude', 'codex'];
|
|
31
|
+
const PLATFORM_MANIFEST_DIRS = {
|
|
32
|
+
claude: '.claude-plugin',
|
|
33
|
+
codex: '.codex-plugin',
|
|
34
|
+
};
|
|
35
|
+
const EXACT_PNPM_PACKAGE_MANAGER_PATTERN = /^pnpm@\d+\.\d+\.\d+$/u;
|
|
36
|
+
function assertLocalPluginStagingPathForTests(targetPath, source) {
|
|
37
|
+
return assertTestWritablePath(targetPath, source, '用 createIsolatedTestEnv() 生成默认 TMPDIR,或通过 registerWritableStateRoot() 登记 local plugin staging 路径。');
|
|
38
|
+
}
|
|
39
|
+
const preparedBuildImportProjections = new WeakMap();
|
|
40
|
+
export async function validateStagingPackageManager(packageRoot) {
|
|
41
|
+
const [cliPackageJson, packageJson] = await Promise.all([
|
|
42
|
+
readJsonObject(path.join(resolveCliPackageRoot(), 'package.json'), '@lesliechan721/aw package.json'),
|
|
43
|
+
readJsonObject(path.join(packageRoot, 'package.json'), 'scripts.node.packageRoot.package.json'),
|
|
44
|
+
]);
|
|
45
|
+
const supportedPackageManager = cliPackageJson.packageManager;
|
|
46
|
+
if (typeof supportedPackageManager !== 'string'
|
|
47
|
+
|| !EXACT_PNPM_PACKAGE_MANAGER_PATTERN.test(supportedPackageManager)) {
|
|
48
|
+
throw new Error('Invalid @lesliechan721/aw packageManager: expected an exact "pnpm@<version>" declaration.');
|
|
49
|
+
}
|
|
50
|
+
if (packageJson.packageManager !== supportedPackageManager) {
|
|
51
|
+
throw new Error('Invalid scripts.node.packageRoot.package.json.packageManager: '
|
|
52
|
+
+ `expected "${supportedPackageManager}".`);
|
|
53
|
+
}
|
|
54
|
+
return supportedPackageManager;
|
|
55
|
+
}
|
|
56
|
+
async function resolveFixedPnpmEntry(supportedPackageManager, env) {
|
|
57
|
+
const configuredEntry = env.npm_execpath?.trim();
|
|
58
|
+
if (!configuredEntry || !path.isAbsolute(configuredEntry)) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
const entryPath = await fs.realpath(configuredEntry).catch(() => undefined);
|
|
62
|
+
if (!entryPath) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
let current = path.dirname(entryPath);
|
|
66
|
+
while (true) {
|
|
67
|
+
const packageJson = await fs.readJson(path.join(current, 'package.json')).catch(() => undefined);
|
|
68
|
+
if (packageJson?.name === 'pnpm') {
|
|
69
|
+
return `pnpm@${packageJson.version}` === supportedPackageManager
|
|
70
|
+
? entryPath
|
|
71
|
+
: undefined;
|
|
72
|
+
}
|
|
73
|
+
const parent = path.dirname(current);
|
|
74
|
+
if (parent === current) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
current = parent;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function resolveRuntimePnpmEntry(supportedPackageManager) {
|
|
81
|
+
const packageJsonPath = (() => {
|
|
82
|
+
try {
|
|
83
|
+
return requireFromCli.resolve('pnpm');
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
})();
|
|
89
|
+
if (!packageJsonPath) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
const packageJson = await fs.readJson(packageJsonPath).catch(() => undefined);
|
|
93
|
+
if (packageJson?.name !== 'pnpm'
|
|
94
|
+
|| `pnpm@${packageJson.version}` !== supportedPackageManager) {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
const entryPath = path.join(path.dirname(packageJsonPath), 'bin', 'pnpm.cjs');
|
|
98
|
+
const stats = await fs.stat(entryPath).catch(() => undefined);
|
|
99
|
+
return stats?.isFile() ? entryPath : undefined;
|
|
100
|
+
}
|
|
101
|
+
const defaultStagingRunner = {
|
|
102
|
+
async installPackageRoot(packageRoot) {
|
|
103
|
+
const supportedPackageManager = await validateStagingPackageManager(packageRoot);
|
|
104
|
+
const fixedPnpmEntry = await resolveFixedPnpmEntry(supportedPackageManager, process.env)
|
|
105
|
+
?? await resolveRuntimePnpmEntry(supportedPackageManager);
|
|
106
|
+
if (!fixedPnpmEntry) {
|
|
107
|
+
throw new Error(`Cannot stage scripts.node.packageRoot: missing bundled ${supportedPackageManager} runtime dependency.`);
|
|
108
|
+
}
|
|
109
|
+
const args = [
|
|
110
|
+
fixedPnpmEntry,
|
|
111
|
+
'install',
|
|
112
|
+
'--frozen-lockfile',
|
|
113
|
+
'--ignore-scripts',
|
|
114
|
+
];
|
|
115
|
+
await execFileAsync(process.execPath, args, {
|
|
116
|
+
cwd: packageRoot,
|
|
117
|
+
env: process.env,
|
|
118
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
119
|
+
});
|
|
120
|
+
},
|
|
121
|
+
async runNodeBuild({ pluginRoot, scriptPath, args, env }) {
|
|
122
|
+
await execFileAsync(process.execPath, [path.join(pluginRoot, stripDotSlash(scriptPath)), ...args], {
|
|
123
|
+
cwd: pluginRoot,
|
|
124
|
+
env,
|
|
125
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
126
|
+
});
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
function stripDotSlash(value) {
|
|
130
|
+
return value.startsWith('./') ? value.slice(2) : value;
|
|
131
|
+
}
|
|
132
|
+
function toPlatformRelativePath(value, platform) {
|
|
133
|
+
return `./${platform}/${stripDotSlash(value)}`;
|
|
134
|
+
}
|
|
135
|
+
function isTextFile(filePath) {
|
|
136
|
+
return /\.(md|markdown|txt|json|yaml|yml|toml|rules)$/i.test(filePath);
|
|
137
|
+
}
|
|
138
|
+
function isMacOsMetadataName(name) {
|
|
139
|
+
return name === '.DS_Store';
|
|
140
|
+
}
|
|
141
|
+
async function listFilesRecursively(rootDir) {
|
|
142
|
+
const entries = await fs.readdir(rootDir, { withFileTypes: true });
|
|
143
|
+
const files = [];
|
|
144
|
+
for (const entry of entries) {
|
|
145
|
+
if (isMacOsMetadataName(entry.name))
|
|
146
|
+
continue;
|
|
147
|
+
if (isIgnoredPluginInputDirectory(entry.name))
|
|
148
|
+
continue;
|
|
149
|
+
if (entry.name === '.agents-plugin' || entry.name === '.claude-plugin' || entry.name === '.codex-plugin') {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
const entryPath = path.join(rootDir, entry.name);
|
|
153
|
+
if (entry.isDirectory()) {
|
|
154
|
+
const nestedFiles = await listFilesRecursively(entryPath);
|
|
155
|
+
files.push(...nestedFiles.map((nestedFile) => path.join(entry.name, nestedFile).split(path.sep).join('/')));
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
files.push(entry.name);
|
|
159
|
+
}
|
|
160
|
+
return files.sort();
|
|
161
|
+
}
|
|
162
|
+
async function listFilesRecursivelyIncludingManaged(rootDir) {
|
|
163
|
+
const entries = await fs.readdir(rootDir, { withFileTypes: true }).catch(() => []);
|
|
164
|
+
const files = [];
|
|
165
|
+
for (const entry of entries) {
|
|
166
|
+
if (isIgnoredPluginInputDirectory(entry.name) || isMacOsMetadataName(entry.name)) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const entryPath = path.join(rootDir, entry.name);
|
|
170
|
+
if (entry.isDirectory()) {
|
|
171
|
+
const nestedFiles = await listFilesRecursivelyIncludingManaged(entryPath);
|
|
172
|
+
files.push(...nestedFiles.map((nestedFile) => path.join(entry.name, nestedFile).split(path.sep).join('/')));
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
files.push(entry.name);
|
|
176
|
+
}
|
|
177
|
+
return files.sort();
|
|
178
|
+
}
|
|
179
|
+
async function collectFilesForPath(pluginRoot, relativePath) {
|
|
180
|
+
const absolutePath = path.join(pluginRoot, stripDotSlash(relativePath));
|
|
181
|
+
const stats = await fs.stat(absolutePath).catch(() => null);
|
|
182
|
+
if (!stats) {
|
|
183
|
+
throw new Error(`Missing source path "${relativePath}".`);
|
|
184
|
+
}
|
|
185
|
+
if (stats.isDirectory()) {
|
|
186
|
+
const nestedFiles = await listFilesRecursively(absolutePath);
|
|
187
|
+
return nestedFiles.map((filePath) => path.join(stripDotSlash(relativePath), filePath).split(path.sep).join('/'));
|
|
188
|
+
}
|
|
189
|
+
return [stripDotSlash(relativePath).split(path.sep).join('/')];
|
|
190
|
+
}
|
|
191
|
+
function renderClaudeAgentContent(agent) {
|
|
192
|
+
const frontmatterLines = ['---', `name: ${JSON.stringify(agent.name)}`, `description: ${JSON.stringify(agent.description)}`];
|
|
193
|
+
if (agent.tools && agent.tools.length > 0) {
|
|
194
|
+
frontmatterLines.push('tools:');
|
|
195
|
+
for (const tool of agent.tools) {
|
|
196
|
+
frontmatterLines.push(` - ${tool}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
frontmatterLines.push('---', '');
|
|
200
|
+
return `${frontmatterLines.join('\n')}${agent.prompt.trim()}\n`;
|
|
201
|
+
}
|
|
202
|
+
async function writeTextFile(filePath, content) {
|
|
203
|
+
await fs.ensureDir(path.dirname(filePath));
|
|
204
|
+
await fs.writeFile(filePath, content, 'utf8');
|
|
205
|
+
}
|
|
206
|
+
async function copyFileWithTemplateSupport(pluginRoot, outputRoot, sourceRelativePath, platform, templatePatterns, templateVars) {
|
|
207
|
+
const normalizedSource = sourceRelativePath.split(path.sep).join('/');
|
|
208
|
+
const sourcePath = path.join(pluginRoot, normalizedSource);
|
|
209
|
+
const targetPath = path.join(outputRoot, platform, normalizedSource);
|
|
210
|
+
await fs.ensureDir(path.dirname(targetPath));
|
|
211
|
+
const shouldRenderTemplate = isTextFile(normalizedSource) &&
|
|
212
|
+
templatePatterns.length > 0 &&
|
|
213
|
+
applyFileRules([normalizedSource], templatePatterns, []).length > 0;
|
|
214
|
+
if (!shouldRenderTemplate) {
|
|
215
|
+
await fs.copyFile(sourcePath, targetPath);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const content = await fs.readFile(sourcePath, 'utf8');
|
|
219
|
+
await fs.writeFile(targetPath, renderTemplate(content, templateVars, platform), 'utf8');
|
|
220
|
+
}
|
|
221
|
+
async function copyBundleRootFile(pluginRoot, outputRoot, relativePath) {
|
|
222
|
+
const normalized = stripDotSlash(relativePath).split(path.sep).join('/');
|
|
223
|
+
const sourcePath = path.join(pluginRoot, normalized);
|
|
224
|
+
const targetPath = path.join(outputRoot, normalized);
|
|
225
|
+
await fs.ensureDir(path.dirname(targetPath));
|
|
226
|
+
await fs.copyFile(sourcePath, targetPath);
|
|
227
|
+
}
|
|
228
|
+
async function assertArtifactSourceTreePortable(rootDir, fieldName, relativeRoot = '') {
|
|
229
|
+
const rootStats = await fs.lstat(rootDir);
|
|
230
|
+
if (rootStats.isSymbolicLink() || !rootStats.isDirectory()) {
|
|
231
|
+
throw new Error(`Invalid ${fieldName}: source root must be a regular directory.`);
|
|
232
|
+
}
|
|
233
|
+
const entries = await fs.readdir(rootDir, { withFileTypes: true });
|
|
234
|
+
for (const entry of entries) {
|
|
235
|
+
const relativePath = relativeRoot
|
|
236
|
+
? path.posix.join(relativeRoot, entry.name)
|
|
237
|
+
: entry.name;
|
|
238
|
+
if (isSkillAuthorOnlyPath(relativePath))
|
|
239
|
+
continue;
|
|
240
|
+
if (isMacOsMetadataName(entry.name))
|
|
241
|
+
continue;
|
|
242
|
+
const entryPath = path.join(rootDir, entry.name);
|
|
243
|
+
if (entry.isSymbolicLink()) {
|
|
244
|
+
throw new Error(`Invalid ${fieldName}: symbolic links are not supported (${entry.name}).`);
|
|
245
|
+
}
|
|
246
|
+
if (entry.isDirectory()) {
|
|
247
|
+
await assertArtifactSourceTreePortable(entryPath, fieldName, relativePath);
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
if (!entry.isFile()) {
|
|
251
|
+
throw new Error(`Invalid ${fieldName}: only regular files and directories are supported (${entry.name}).`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
async function copyArtifactSourceDirectories(plugin, outputRoot) {
|
|
256
|
+
for (const [targetIndex, target] of (plugin.manifest.artifacts?.targets ?? []).entries()) {
|
|
257
|
+
for (const [sourceIndex, sourceDir] of (target.sourceDirs ?? []).entries()) {
|
|
258
|
+
const sourcePath = path.join(plugin.rootDir, stripDotSlash(sourceDir));
|
|
259
|
+
await assertArtifactSourceTreePortable(sourcePath, `artifacts.targets[${targetIndex}].sourceDirs[${sourceIndex}]`);
|
|
260
|
+
await fs.copy(sourcePath, path.join(outputRoot, getArtifactSourceBundleRelativePath({
|
|
261
|
+
platform: target.platform,
|
|
262
|
+
distribution: target.distribution,
|
|
263
|
+
artifactId: target.id,
|
|
264
|
+
index: sourceIndex,
|
|
265
|
+
})), {
|
|
266
|
+
overwrite: true,
|
|
267
|
+
dereference: false,
|
|
268
|
+
filter: (source) => !isMacOsMetadataName(path.basename(source))
|
|
269
|
+
&& !isSkillAuthorOnlyPath(path.relative(sourcePath, source)),
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
async function copyPortableStaticSkills(plugin, outputRoot) {
|
|
275
|
+
const skillsPath = plugin.manifest.distributions?.agentSkills?.skills;
|
|
276
|
+
if (!skillsPath)
|
|
277
|
+
return;
|
|
278
|
+
const sourceRoot = path.join(plugin.rootDir, stripDotSlash(skillsPath));
|
|
279
|
+
const targetRoot = path.join(outputRoot, 'agent-skills', 'skills');
|
|
280
|
+
await assertArtifactSourceTreePortable(sourceRoot, 'distributions.agentSkills.skills');
|
|
281
|
+
await fs.copy(sourceRoot, targetRoot, {
|
|
282
|
+
dereference: false,
|
|
283
|
+
filter: (source) => {
|
|
284
|
+
const relative = path.relative(sourceRoot, source).split(path.sep).join('/');
|
|
285
|
+
return !isMacOsMetadataName(path.basename(source))
|
|
286
|
+
&& !isSkillCollectionAuthorOnlyPath(relative);
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
async function resolveArtifactRuntimeImports(options) {
|
|
291
|
+
const manifest = createBundleSourceManifest(options.plugin);
|
|
292
|
+
for (const [targetIndex, target] of (manifest.artifacts?.targets ?? []).entries()) {
|
|
293
|
+
for (const [importIndex, runtimeImport] of (target.runtimeImports ?? []).entries()) {
|
|
294
|
+
if (!options.resolver) {
|
|
295
|
+
throw new Error(`Cannot resolve artifacts.targets[${targetIndex}].runtimeImports[${importIndex}]: catalog runtime import resolver is required.`);
|
|
296
|
+
}
|
|
297
|
+
const resolution = await options.resolver.resolve({
|
|
298
|
+
consumer: options.plugin,
|
|
299
|
+
reference: runtimeImport,
|
|
300
|
+
purpose: 'artifact-runtime',
|
|
301
|
+
});
|
|
302
|
+
const relativePath = `./.agents-plugin/runtime-imports/${target.id}/${runtimeImport.name}`;
|
|
303
|
+
const targetPath = path.join(options.outputRoot, stripDotSlash(relativePath));
|
|
304
|
+
await fs.ensureDir(path.dirname(targetPath));
|
|
305
|
+
await fs.copyFile(resolution.sourcePath, targetPath);
|
|
306
|
+
const digest = await calculateFileDigest(targetPath);
|
|
307
|
+
if (digest !== resolution.sourceDigest) {
|
|
308
|
+
throw new Error(`Artifact runtime import digest mismatch at "${target.id}/${runtimeImport.name}".`);
|
|
309
|
+
}
|
|
310
|
+
runtimeImport.resolved = {
|
|
311
|
+
path: relativePath,
|
|
312
|
+
digest,
|
|
313
|
+
providerPluginId: resolution.provider,
|
|
314
|
+
providerVersion: resolution.providerVersion,
|
|
315
|
+
source: resolution.source,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (manifest.distributions?.agentSkills?.skills) {
|
|
320
|
+
manifest.distributions.agentSkills.skills = './agent-skills/skills';
|
|
321
|
+
}
|
|
322
|
+
return manifest;
|
|
323
|
+
}
|
|
324
|
+
async function copySlashCommandAsset(pluginRoot, outputRoot, skillName, sourceRelativePath, generatedRelativePath) {
|
|
325
|
+
const sourcePath = path.join(pluginRoot, sourceRelativePath);
|
|
326
|
+
const targetPath = path.join(outputRoot, 'codex', 'skills', skillName, stripDotSlash(generatedRelativePath));
|
|
327
|
+
await fs.ensureDir(path.dirname(targetPath));
|
|
328
|
+
await fs.copyFile(sourcePath, targetPath);
|
|
329
|
+
}
|
|
330
|
+
async function addDeclaredPathFiles(plugin, platform, relativePath, targetFiles) {
|
|
331
|
+
if (!relativePath) {
|
|
332
|
+
return undefined;
|
|
333
|
+
}
|
|
334
|
+
const files = await collectFilesForPath(plugin.rootDir, relativePath);
|
|
335
|
+
for (const filePath of files) {
|
|
336
|
+
targetFiles.add(filePath);
|
|
337
|
+
}
|
|
338
|
+
return toPlatformRelativePath(relativePath, platform);
|
|
339
|
+
}
|
|
340
|
+
async function addDeclaredSkillPathFiles(plugin, platform, relativePath, targetFiles) {
|
|
341
|
+
if (!relativePath)
|
|
342
|
+
return undefined;
|
|
343
|
+
const root = stripDotSlash(relativePath);
|
|
344
|
+
const dynamicSkillKeys = new Set((plugin.manifest.artifacts?.targets ?? [])
|
|
345
|
+
.filter((target) => target.platform === platform &&
|
|
346
|
+
(target.target === 'codex.skill' || target.target === 'claude.skill') &&
|
|
347
|
+
target.skillKey)
|
|
348
|
+
.map((target) => target.skillKey));
|
|
349
|
+
const files = await collectFilesForPath(plugin.rootDir, relativePath);
|
|
350
|
+
let added = false;
|
|
351
|
+
for (const filePath of files) {
|
|
352
|
+
const skillCollectionPath = path.posix.relative(root.split(path.sep).join('/'), filePath.split(path.sep).join('/'));
|
|
353
|
+
const [skillKey] = skillCollectionPath.split('/');
|
|
354
|
+
if (!dynamicSkillKeys.has(skillKey ?? '') &&
|
|
355
|
+
!isSkillCollectionAuthorOnlyPath(skillCollectionPath)) {
|
|
356
|
+
targetFiles.add(filePath);
|
|
357
|
+
added = true;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return added ? toPlatformRelativePath(relativePath, platform) : undefined;
|
|
361
|
+
}
|
|
362
|
+
function relativePathInside(root, candidate) {
|
|
363
|
+
const relative = path.posix.relative(root, candidate);
|
|
364
|
+
if (relative === '..' || relative.startsWith('../') || path.posix.isAbsolute(relative)) {
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
return relative;
|
|
368
|
+
}
|
|
369
|
+
function isDeclaredSkillAuthorOnlyFile(plugin, filePath) {
|
|
370
|
+
const normalizedFile = filePath.split(path.sep).join('/');
|
|
371
|
+
if (normalizedFile === 'reports' || normalizedFile.startsWith('reports/'))
|
|
372
|
+
return true;
|
|
373
|
+
if (plugin.manifest.skills) {
|
|
374
|
+
const staticRoot = stripDotSlash(plugin.manifest.skills).split(path.sep).join('/');
|
|
375
|
+
const staticRelative = relativePathInside(staticRoot, normalizedFile);
|
|
376
|
+
if (staticRelative && isSkillCollectionAuthorOnlyPath(staticRelative))
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
for (const target of plugin.manifest.artifacts?.targets ?? []) {
|
|
380
|
+
if ((target.target !== 'codex.skill' && target.target !== 'claude.skill') ||
|
|
381
|
+
!target.skillKey)
|
|
382
|
+
continue;
|
|
383
|
+
const dynamicRoot = `skills/${target.skillKey}`;
|
|
384
|
+
const dynamicRelative = relativePathInside(dynamicRoot, normalizedFile);
|
|
385
|
+
if (dynamicRelative && isSkillAuthorOnlyPath(dynamicRelative))
|
|
386
|
+
return true;
|
|
387
|
+
for (const sourceDir of target.sourceDirs ?? []) {
|
|
388
|
+
const sourceRelative = relativePathInside(stripDotSlash(sourceDir).split(path.sep).join('/'), normalizedFile);
|
|
389
|
+
if (sourceRelative && isSkillAuthorOnlyPath(sourceRelative))
|
|
390
|
+
return true;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
function isDynamicSkillSourceFile(plugin, platform, filePath) {
|
|
396
|
+
const normalizedFile = filePath.split(path.sep).join('/');
|
|
397
|
+
return (plugin.manifest.artifacts?.targets ?? []).some((target) => {
|
|
398
|
+
if (target.platform !== platform ||
|
|
399
|
+
(target.target !== 'codex.skill' && target.target !== 'claude.skill') ||
|
|
400
|
+
!target.skillKey)
|
|
401
|
+
return false;
|
|
402
|
+
return relativePathInside(`skills/${target.skillKey}`, normalizedFile) !== null;
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
async function addDeclaredLspServerFiles(plugin, value, targetFiles) {
|
|
406
|
+
if (value === undefined) {
|
|
407
|
+
return undefined;
|
|
408
|
+
}
|
|
409
|
+
if (typeof value === 'string') {
|
|
410
|
+
const normalized = normalizePluginRelativePath(plugin.rootDir, value, 'buildConfig.manifestOverrides.claude.lspServers');
|
|
411
|
+
const files = await collectFilesForPath(plugin.rootDir, normalized);
|
|
412
|
+
for (const filePath of files) {
|
|
413
|
+
targetFiles.add(filePath);
|
|
414
|
+
}
|
|
415
|
+
return toPlatformRelativePath(normalized, 'claude');
|
|
416
|
+
}
|
|
417
|
+
if (Array.isArray(value)) {
|
|
418
|
+
const rendered = [];
|
|
419
|
+
for (const entry of value) {
|
|
420
|
+
if (typeof entry === 'string') {
|
|
421
|
+
const normalized = normalizePluginRelativePath(plugin.rootDir, entry, 'buildConfig.manifestOverrides.claude.lspServers');
|
|
422
|
+
const files = await collectFilesForPath(plugin.rootDir, normalized);
|
|
423
|
+
for (const filePath of files) {
|
|
424
|
+
targetFiles.add(filePath);
|
|
425
|
+
}
|
|
426
|
+
rendered.push(toPlatformRelativePath(normalized, 'claude'));
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
rendered.push(entry);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return rendered;
|
|
433
|
+
}
|
|
434
|
+
return value;
|
|
435
|
+
}
|
|
436
|
+
function isNodeRuntimeEntry(entry) {
|
|
437
|
+
return entry.runner === 'node' || (entry.runner === 'auto' &&
|
|
438
|
+
NODE_RUNTIME_EXTENSIONS.has(path.posix.extname(entry.path).toLowerCase()));
|
|
439
|
+
}
|
|
440
|
+
function addLifecycleRuntimeEntries(plugin, rootFiles, nodeEntries) {
|
|
441
|
+
const lifecycle = plugin.manifest.scripts?.lifecycle;
|
|
442
|
+
if (!lifecycle) {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
for (const selector of Object.values(lifecycle)) {
|
|
446
|
+
if (!selector) {
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
for (const entry of Object.values(selector)) {
|
|
450
|
+
if (!entry) {
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
const filePath = stripDotSlash(entry.path);
|
|
454
|
+
rootFiles.add(filePath);
|
|
455
|
+
if (isNodeRuntimeEntry(entry)) {
|
|
456
|
+
nodeEntries.add(filePath);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
function addHelperRuntimeEntries(plugin, rootFiles, nodeEntries) {
|
|
462
|
+
const configHelper = plugin.manifest.scripts?.helpers?.config;
|
|
463
|
+
if (!configHelper) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
const filePath = stripDotSlash(configHelper);
|
|
467
|
+
rootFiles.add(filePath);
|
|
468
|
+
nodeEntries.add(filePath);
|
|
469
|
+
}
|
|
470
|
+
function addArtifactRendererRuntimeEntry(plugin, rootFiles, nodeEntries) {
|
|
471
|
+
const renderer = plugin.manifest.scripts?.artifacts?.render;
|
|
472
|
+
if (!renderer) {
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
const filePath = stripDotSlash(renderer.path);
|
|
476
|
+
rootFiles.add(filePath);
|
|
477
|
+
nodeEntries.add(filePath);
|
|
478
|
+
}
|
|
479
|
+
async function readJsonObject(filePath, fieldName) {
|
|
480
|
+
const content = await fs.readJson(filePath);
|
|
481
|
+
if (!content || typeof content !== 'object' || Array.isArray(content)) {
|
|
482
|
+
throw new Error(`Invalid ${fieldName}: expected a JSON object.`);
|
|
483
|
+
}
|
|
484
|
+
return content;
|
|
485
|
+
}
|
|
486
|
+
function readDependencyNames(packageJson, fieldName) {
|
|
487
|
+
const dependencies = packageJson[fieldName];
|
|
488
|
+
if (!dependencies || typeof dependencies !== 'object' || Array.isArray(dependencies)) {
|
|
489
|
+
return [];
|
|
490
|
+
}
|
|
491
|
+
return Object.keys(dependencies).sort();
|
|
492
|
+
}
|
|
493
|
+
async function readPackageRootDependencySets(plugin) {
|
|
494
|
+
const packageRoot = plugin.manifest.scripts?.node?.packageRoot;
|
|
495
|
+
if (!packageRoot) {
|
|
496
|
+
return { dependencies: [], devDependencies: [] };
|
|
497
|
+
}
|
|
498
|
+
const packageJson = await readJsonObject(path.join(plugin.rootDir, stripDotSlash(packageRoot), 'package.json'), 'scripts.node.packageRoot.package.json');
|
|
499
|
+
return {
|
|
500
|
+
dependencies: readDependencyNames(packageJson, 'dependencies'),
|
|
501
|
+
devDependencies: readDependencyNames(packageJson, 'devDependencies'),
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
async function collectRuntimeClosureFiles(plugin, entryFiles) {
|
|
505
|
+
if (entryFiles.length === 0) {
|
|
506
|
+
return [];
|
|
507
|
+
}
|
|
508
|
+
const allFiles = await listFilesRecursivelyIncludingManaged(plugin.rootDir);
|
|
509
|
+
const scanFiles = {};
|
|
510
|
+
await Promise.all(allFiles
|
|
511
|
+
.filter((filePath) => (NODE_RUNTIME_EXTENSIONS.has(path.posix.extname(filePath).toLowerCase())
|
|
512
|
+
|| path.posix.basename(filePath) === 'package.json'))
|
|
513
|
+
.map(async (filePath) => {
|
|
514
|
+
scanFiles[filePath] = await fs.readFile(path.join(plugin.rootDir, filePath), 'utf8');
|
|
515
|
+
}));
|
|
516
|
+
const { dependencies, devDependencies } = await readPackageRootDependencySets(plugin);
|
|
517
|
+
const scan = scanNodeImportContract({
|
|
518
|
+
files: scanFiles,
|
|
519
|
+
filePaths: allFiles,
|
|
520
|
+
entryFiles,
|
|
521
|
+
dependencies,
|
|
522
|
+
devDependencies,
|
|
523
|
+
});
|
|
524
|
+
if (scan.errors.length > 0) {
|
|
525
|
+
throw new Error(`Invalid scripts.node runtime imports:\n${scan.errors.join('\n')}`);
|
|
526
|
+
}
|
|
527
|
+
return scan.files;
|
|
528
|
+
}
|
|
529
|
+
async function collectAwRuntimeFiles(plugin) {
|
|
530
|
+
const rootFiles = new Set();
|
|
531
|
+
const nodeEntries = new Set();
|
|
532
|
+
addLifecycleRuntimeEntries(plugin, rootFiles, nodeEntries);
|
|
533
|
+
addHelperRuntimeEntries(plugin, rootFiles, nodeEntries);
|
|
534
|
+
addArtifactRendererRuntimeEntry(plugin, rootFiles, nodeEntries);
|
|
535
|
+
for (const filePath of await collectRuntimeClosureFiles(plugin, [...nodeEntries])) {
|
|
536
|
+
rootFiles.add(filePath);
|
|
537
|
+
}
|
|
538
|
+
return [...rootFiles].sort();
|
|
539
|
+
}
|
|
540
|
+
function packageRootPath(plugin) {
|
|
541
|
+
const packageRoot = plugin.manifest.scripts?.node?.packageRoot;
|
|
542
|
+
return packageRoot ? path.join(plugin.rootDir, stripDotSlash(packageRoot)) : undefined;
|
|
543
|
+
}
|
|
544
|
+
async function findInstalledPackageDir(packageRoot, importerDir, packageName) {
|
|
545
|
+
let current = importerDir;
|
|
546
|
+
const packageRootParent = path.dirname(packageRoot);
|
|
547
|
+
while (current.startsWith(packageRootParent)) {
|
|
548
|
+
const candidate = path.join(current, 'node_modules', ...packageName.split('/'));
|
|
549
|
+
const stats = await fs.stat(candidate).catch(() => null);
|
|
550
|
+
if (stats?.isDirectory()) {
|
|
551
|
+
return fs.realpath(candidate);
|
|
552
|
+
}
|
|
553
|
+
if (current === packageRoot) {
|
|
554
|
+
break;
|
|
555
|
+
}
|
|
556
|
+
current = path.dirname(current);
|
|
557
|
+
}
|
|
558
|
+
return undefined;
|
|
559
|
+
}
|
|
560
|
+
async function collectInstalledDependencyClosure(packageRoot, rootDependencies) {
|
|
561
|
+
const packageRootReal = await fs.realpath(packageRoot);
|
|
562
|
+
const queue = rootDependencies.map((dependencyName) => ({
|
|
563
|
+
packageName: dependencyName,
|
|
564
|
+
importerDir: packageRootReal,
|
|
565
|
+
requirement: 'required',
|
|
566
|
+
}));
|
|
567
|
+
const visitedEntries = new Set();
|
|
568
|
+
const visitedPackageDirs = new Set();
|
|
569
|
+
const packageJsonByDir = new Map();
|
|
570
|
+
const packages = [];
|
|
571
|
+
while (queue.length > 0) {
|
|
572
|
+
const next = queue.shift();
|
|
573
|
+
if (!next) {
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
const dependencyDir = await findInstalledPackageDir(packageRootReal, next.importerDir, next.packageName);
|
|
577
|
+
if (!dependencyDir) {
|
|
578
|
+
if (next.requirement === 'optional-peer') {
|
|
579
|
+
continue;
|
|
580
|
+
}
|
|
581
|
+
if (next.requirement === 'optional-dependency') {
|
|
582
|
+
throw new Error(`Invalid scripts.node.packageRoot: missing transitive optional dependency "${next.packageName}" in node_modules; cross-platform staging cannot prove that all supported runtime operating systems exclude it.`);
|
|
583
|
+
}
|
|
584
|
+
throw new Error(`Invalid scripts.node.packageRoot: missing production dependency "${next.packageName}" in node_modules.`);
|
|
585
|
+
}
|
|
586
|
+
const entryKey = JSON.stringify([next.importerDir, next.packageName, dependencyDir]);
|
|
587
|
+
if (visitedEntries.has(entryKey)) {
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
visitedEntries.add(entryKey);
|
|
591
|
+
let packageJson = packageJsonByDir.get(dependencyDir);
|
|
592
|
+
if (!packageJson) {
|
|
593
|
+
packageJson = await readJsonObject(path.join(dependencyDir, 'package.json'), `${next.packageName} package.json`);
|
|
594
|
+
packageJsonByDir.set(dependencyDir, packageJson);
|
|
595
|
+
}
|
|
596
|
+
packages.push({
|
|
597
|
+
importerDir: next.importerDir,
|
|
598
|
+
packageName: next.packageName,
|
|
599
|
+
packageDir: dependencyDir,
|
|
600
|
+
packageJson,
|
|
601
|
+
});
|
|
602
|
+
if (visitedPackageDirs.has(dependencyDir)) {
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
visitedPackageDirs.add(dependencyDir);
|
|
606
|
+
const optionalDependencies = new Set(readDependencyNames(packageJson, 'optionalDependencies'));
|
|
607
|
+
for (const childDependency of readDependencyNames(packageJson, 'dependencies')) {
|
|
608
|
+
if (optionalDependencies.has(childDependency)) {
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
queue.push({
|
|
612
|
+
packageName: childDependency,
|
|
613
|
+
importerDir: dependencyDir,
|
|
614
|
+
requirement: 'required',
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
for (const childDependency of optionalDependencies) {
|
|
618
|
+
queue.push({
|
|
619
|
+
packageName: childDependency,
|
|
620
|
+
importerDir: dependencyDir,
|
|
621
|
+
requirement: 'optional-dependency',
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
const peerDependenciesMeta = packageJson.peerDependenciesMeta;
|
|
625
|
+
const peerMeta = peerDependenciesMeta && typeof peerDependenciesMeta === 'object'
|
|
626
|
+
&& !Array.isArray(peerDependenciesMeta)
|
|
627
|
+
? peerDependenciesMeta
|
|
628
|
+
: {};
|
|
629
|
+
for (const peerDependency of readDependencyNames(packageJson, 'peerDependencies')) {
|
|
630
|
+
const metadata = peerMeta[peerDependency];
|
|
631
|
+
const optional = metadata !== null
|
|
632
|
+
&& typeof metadata === 'object'
|
|
633
|
+
&& !Array.isArray(metadata)
|
|
634
|
+
&& metadata.optional === true;
|
|
635
|
+
queue.push({
|
|
636
|
+
packageName: peerDependency,
|
|
637
|
+
importerDir: dependencyDir,
|
|
638
|
+
requirement: optional ? 'optional-peer' : 'required',
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
return packages;
|
|
643
|
+
}
|
|
644
|
+
async function readProductionDependencyClosure(packageRoot) {
|
|
645
|
+
const rootPackageJson = await readJsonObject(path.join(packageRoot, 'package.json'), 'scripts.node.packageRoot.package.json');
|
|
646
|
+
return collectInstalledDependencyClosure(packageRoot, readDependencyNames(rootPackageJson, 'dependencies'));
|
|
647
|
+
}
|
|
648
|
+
async function assertNoProductionInstallScripts(packageRoot) {
|
|
649
|
+
for (const dependency of await readProductionDependencyClosure(packageRoot)) {
|
|
650
|
+
const scripts = dependency.packageJson.scripts;
|
|
651
|
+
if (!scripts || typeof scripts !== 'object' || Array.isArray(scripts)) {
|
|
652
|
+
continue;
|
|
653
|
+
}
|
|
654
|
+
for (const scriptName of INSTALL_SCRIPT_NAMES) {
|
|
655
|
+
if (typeof scripts[scriptName] === 'string') {
|
|
656
|
+
throw new Error(`Invalid scripts.node.packageRoot: production dependency "${dependency.packageName}" declares unsupported "${scriptName}" script.`);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
async function copyProductionDependencyClosure(sourcePackageRoot, targetPackageRoot) {
|
|
662
|
+
const targetNodeModules = path.join(targetPackageRoot, 'node_modules');
|
|
663
|
+
const sourcePackageRootReal = await fs.realpath(sourcePackageRoot);
|
|
664
|
+
const productionDependencies = await readProductionDependencyClosure(sourcePackageRoot);
|
|
665
|
+
const dependenciesByImporter = new Map();
|
|
666
|
+
for (const dependency of productionDependencies) {
|
|
667
|
+
const importerDependencies = dependenciesByImporter.get(dependency.importerDir) ?? [];
|
|
668
|
+
importerDependencies.push(dependency);
|
|
669
|
+
dependenciesByImporter.set(dependency.importerDir, importerDependencies);
|
|
670
|
+
}
|
|
671
|
+
await fs.remove(targetNodeModules);
|
|
672
|
+
await fs.ensureDir(targetNodeModules);
|
|
673
|
+
async function materializeDependency(dependency, targetPackageDir, ancestorResolutions) {
|
|
674
|
+
await fs.copy(dependency.packageDir, targetPackageDir, {
|
|
675
|
+
filter(source) {
|
|
676
|
+
return path.basename(source) !== 'node_modules'
|
|
677
|
+
&& !isMacOsMetadataName(path.basename(source));
|
|
678
|
+
},
|
|
679
|
+
});
|
|
680
|
+
const childDependencies = dependenciesByImporter.get(dependency.packageDir) ?? [];
|
|
681
|
+
const childResolutions = new Map(childDependencies.map((child) => [child.packageName, child.packageDir]));
|
|
682
|
+
for (const child of childDependencies) {
|
|
683
|
+
const ancestorPackageDir = ancestorResolutions
|
|
684
|
+
.map((resolutions) => resolutions.get(child.packageName))
|
|
685
|
+
.find((packageDir) => packageDir !== undefined);
|
|
686
|
+
if (ancestorPackageDir === child.packageDir) {
|
|
687
|
+
continue;
|
|
688
|
+
}
|
|
689
|
+
await materializeDependency(child, path.join(targetPackageDir, 'node_modules', ...child.packageName.split('/')), [childResolutions, ...ancestorResolutions]);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
const rootDependencies = dependenciesByImporter.get(sourcePackageRootReal) ?? [];
|
|
693
|
+
const rootResolutions = new Map(rootDependencies.map((dependency) => [dependency.packageName, dependency.packageDir]));
|
|
694
|
+
for (const dependency of rootDependencies) {
|
|
695
|
+
await materializeDependency(dependency, path.join(targetNodeModules, ...dependency.packageName.split('/')), [rootResolutions]);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
async function copyProductionPackageRoot(plugin, outputRoot) {
|
|
699
|
+
const declaredPackageRoot = plugin.manifest.scripts?.node?.packageRoot;
|
|
700
|
+
if (!declaredPackageRoot) {
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
const sourcePackageRoot = path.join(plugin.rootDir, stripDotSlash(declaredPackageRoot));
|
|
704
|
+
const targetPackageRoot = path.join(outputRoot, stripDotSlash(declaredPackageRoot));
|
|
705
|
+
await fs.ensureDir(targetPackageRoot);
|
|
706
|
+
await fs.copyFile(path.join(sourcePackageRoot, 'package.json'), path.join(targetPackageRoot, 'package.json'));
|
|
707
|
+
await fs.copyFile(path.join(sourcePackageRoot, 'pnpm-lock.yaml'), path.join(targetPackageRoot, 'pnpm-lock.yaml'));
|
|
708
|
+
const sourceNodeModules = path.join(sourcePackageRoot, 'node_modules');
|
|
709
|
+
if (!(await fs.pathExists(sourceNodeModules))) {
|
|
710
|
+
throw new Error('Invalid scripts.node.packageRoot: missing production node_modules after staging install.');
|
|
711
|
+
}
|
|
712
|
+
await copyProductionDependencyClosure(sourcePackageRoot, targetPackageRoot);
|
|
713
|
+
}
|
|
714
|
+
function toRuntimeImportProvenance(resolution) {
|
|
715
|
+
return {
|
|
716
|
+
provider: resolution.provider,
|
|
717
|
+
providerVersion: resolution.providerVersion,
|
|
718
|
+
name: resolution.name,
|
|
719
|
+
source: resolution.source,
|
|
720
|
+
sourceDigest: resolution.sourceDigest,
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
async function resolveOwnSkillRuntimeSource(plugin, source) {
|
|
724
|
+
const canonicalSource = await resolveCanonicalRuntimeSourceIdentity(plugin.rootDir, source, 'buildConfig.skillRuntimeFiles source');
|
|
725
|
+
return {
|
|
726
|
+
sourcePath: canonicalSource.sourceRealPath,
|
|
727
|
+
sourceDigest: await calculateFileDigest(canonicalSource.sourceRealPath),
|
|
728
|
+
canonicalSource,
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
async function assertSkillRuntimeTargetAbsent(skillRoot, target, fieldName) {
|
|
732
|
+
let current = skillRoot;
|
|
733
|
+
const segments = target.split('/');
|
|
734
|
+
for (const [index, segment] of segments.entries()) {
|
|
735
|
+
current = path.join(current, segment);
|
|
736
|
+
const stats = await fs.lstat(current).catch(() => undefined);
|
|
737
|
+
if (!stats)
|
|
738
|
+
return;
|
|
739
|
+
if (stats.isSymbolicLink()) {
|
|
740
|
+
throw new Error(`Invalid ${fieldName}: target path contains a symbolic link (${target}).`);
|
|
741
|
+
}
|
|
742
|
+
if (index < segments.length - 1 && !stats.isDirectory()) {
|
|
743
|
+
throw new Error(`Invalid ${fieldName}: target parent is not a directory (${target}).`);
|
|
744
|
+
}
|
|
745
|
+
if (index === segments.length - 1) {
|
|
746
|
+
throw new Error(`Invalid ${fieldName}: staged Skill already contains "${target}".`);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
async function assertSkillRuntimeProjectionTargets(plugin) {
|
|
751
|
+
for (const [index, entry] of (plugin.manifest.buildConfig?.skillRuntimeFiles ?? []).entries()) {
|
|
752
|
+
const roots = [];
|
|
753
|
+
if (entry.platforms !== undefined || entry.distributions === undefined) {
|
|
754
|
+
roots.push(path.join(plugin.rootDir, 'skills', entry.skill));
|
|
755
|
+
}
|
|
756
|
+
if (entry.distributions?.includes('agent-skills')) {
|
|
757
|
+
const portableRoot = plugin.manifest.distributions?.agentSkills?.skills;
|
|
758
|
+
if (!portableRoot) {
|
|
759
|
+
throw new Error(`Invalid buildConfig.skillRuntimeFiles[${index}].distributions: agent-skills is not declared.`);
|
|
760
|
+
}
|
|
761
|
+
roots.push(path.join(plugin.rootDir, stripDotSlash(portableRoot), entry.skill));
|
|
762
|
+
}
|
|
763
|
+
for (const skillRoot of roots) {
|
|
764
|
+
const skillRootStats = await fs.lstat(skillRoot).catch(() => undefined);
|
|
765
|
+
if (!skillRootStats?.isDirectory() || skillRootStats.isSymbolicLink()) {
|
|
766
|
+
throw new Error(`Invalid buildConfig.skillRuntimeFiles[${index}].skill: "${entry.skill}" is not a declared static Skill key.`);
|
|
767
|
+
}
|
|
768
|
+
await assertSkillRuntimeTargetAbsent(skillRoot, entry.target, `buildConfig.skillRuntimeFiles[${index}].target`);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
async function validateGeneratedSkillRuntimeFiles(plugin, outputRoot, supportedPlatforms) {
|
|
773
|
+
for (const [index, entry] of (plugin.manifest.buildConfig?.generatedSkillRuntimeFiles ?? []).entries()) {
|
|
774
|
+
const surfaces = [];
|
|
775
|
+
if (entry.distributions === undefined) {
|
|
776
|
+
surfaces.push(...supportedPlatforms);
|
|
777
|
+
}
|
|
778
|
+
surfaces.push(...(entry.distributions ?? []));
|
|
779
|
+
for (const surface of surfaces) {
|
|
780
|
+
const targetPath = path.join(outputRoot, surface, 'skills', entry.skill, ...entry.target.split('/'));
|
|
781
|
+
const stats = await fs.lstat(targetPath).catch(() => undefined);
|
|
782
|
+
if (!stats?.isFile() || stats.isSymbolicLink()) {
|
|
783
|
+
throw new Error(`Invalid buildConfig.generatedSkillRuntimeFiles[${index}]: build did not create regular final target "${surface}:${entry.skill}/${entry.target}".`);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
async function projectSkillRuntimeFiles(options) {
|
|
789
|
+
const projections = [];
|
|
790
|
+
const claims = new Set();
|
|
791
|
+
for (const [index, entry] of (options.plugin.manifest.buildConfig?.skillRuntimeFiles ?? []).entries()) {
|
|
792
|
+
const surfaces = [];
|
|
793
|
+
if (entry.platforms !== undefined || entry.distributions === undefined) {
|
|
794
|
+
surfaces.push(...(entry.platforms ?? [...options.supportedPlatforms]).map((platform) => ({ platform })));
|
|
795
|
+
}
|
|
796
|
+
surfaces.push(...(entry.distributions ?? []).map((distribution) => ({ distribution })));
|
|
797
|
+
for (const surface of surfaces) {
|
|
798
|
+
const { platform, distribution } = surface;
|
|
799
|
+
if (platform) {
|
|
800
|
+
if (!options.supportedPlatforms.has(platform)) {
|
|
801
|
+
throw new Error(`Invalid buildConfig.skillRuntimeFiles[${index}].platforms: plugin does not support "${platform}".`);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
const claim = `${platform ?? distribution}:${entry.skill}/${entry.target}`;
|
|
805
|
+
if (claims.has(claim)) {
|
|
806
|
+
throw new Error(`Invalid buildConfig.skillRuntimeFiles: target collision at "${claim}".`);
|
|
807
|
+
}
|
|
808
|
+
claims.add(claim);
|
|
809
|
+
let sourcePath;
|
|
810
|
+
let sourceDigest;
|
|
811
|
+
let canonicalSource;
|
|
812
|
+
let bindingKey;
|
|
813
|
+
let runtimeProvenance;
|
|
814
|
+
if (entry.source) {
|
|
815
|
+
const ownSource = await resolveOwnSkillRuntimeSource(options.plugin, entry.source);
|
|
816
|
+
sourcePath = ownSource.sourcePath;
|
|
817
|
+
sourceDigest = ownSource.sourceDigest;
|
|
818
|
+
canonicalSource = ownSource.canonicalSource;
|
|
819
|
+
bindingKey = `source:${entry.source}`;
|
|
820
|
+
runtimeProvenance = {
|
|
821
|
+
provider: options.plugin.manifest.name,
|
|
822
|
+
providerVersion: options.plugin.manifest.version,
|
|
823
|
+
name: entry.source,
|
|
824
|
+
source: entry.source,
|
|
825
|
+
sourceDigest,
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
else {
|
|
829
|
+
if (!entry.import || !options.resolver) {
|
|
830
|
+
throw new Error(`Cannot resolve buildConfig.skillRuntimeFiles[${index}].import for plugin "${options.plugin.manifest.name}": catalog runtime import resolver is required.`);
|
|
831
|
+
}
|
|
832
|
+
const resolution = await options.resolver.resolve({
|
|
833
|
+
consumer: options.plugin,
|
|
834
|
+
reference: entry.import,
|
|
835
|
+
purpose: 'skill-runtime-file',
|
|
836
|
+
platform,
|
|
837
|
+
});
|
|
838
|
+
sourcePath = resolution.sourcePath;
|
|
839
|
+
sourceDigest = resolution.sourceDigest;
|
|
840
|
+
canonicalSource = resolution.canonicalSource;
|
|
841
|
+
bindingKey = `import:${entry.import.plugin}/${entry.import.export}`;
|
|
842
|
+
runtimeProvenance = toRuntimeImportProvenance(resolution);
|
|
843
|
+
}
|
|
844
|
+
const targetPath = path.join(options.outputRoot, platform ?? distribution, 'skills', entry.skill, ...entry.target.split('/'));
|
|
845
|
+
if (await fs.pathExists(targetPath)) {
|
|
846
|
+
throw new Error(`Invalid buildConfig.skillRuntimeFiles: bundle target already exists at "${claim}".`);
|
|
847
|
+
}
|
|
848
|
+
await fs.ensureDir(path.dirname(targetPath));
|
|
849
|
+
await fs.copyFile(sourcePath, targetPath);
|
|
850
|
+
const targetDigest = await calculateFileDigest(targetPath);
|
|
851
|
+
if (sourceDigest !== targetDigest) {
|
|
852
|
+
throw new Error(`Invalid buildConfig.skillRuntimeFiles: digest mismatch at "${claim}".`);
|
|
853
|
+
}
|
|
854
|
+
projections.push({
|
|
855
|
+
bindingKey,
|
|
856
|
+
canonicalSource,
|
|
857
|
+
provenance: {
|
|
858
|
+
...runtimeProvenance,
|
|
859
|
+
platform,
|
|
860
|
+
distribution,
|
|
861
|
+
skill: entry.skill,
|
|
862
|
+
target: entry.target,
|
|
863
|
+
targetDigest,
|
|
864
|
+
},
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
return projections;
|
|
869
|
+
}
|
|
870
|
+
function hasSameCanonicalSource(left, right) {
|
|
871
|
+
return left.rootPath === right.rootPath
|
|
872
|
+
&& left.rootRealPath === right.rootRealPath
|
|
873
|
+
&& left.relativePath === right.relativePath
|
|
874
|
+
&& left.sourceRealPath === right.sourceRealPath;
|
|
875
|
+
}
|
|
876
|
+
async function validateSkillRuntimeProjectionSources(projections) {
|
|
877
|
+
const bindings = new Map();
|
|
878
|
+
for (const projection of projections) {
|
|
879
|
+
const existing = bindings.get(projection.bindingKey);
|
|
880
|
+
if (existing
|
|
881
|
+
&& (existing.provenance.provider !== projection.provenance.provider
|
|
882
|
+
|| existing.provenance.providerVersion !== projection.provenance.providerVersion
|
|
883
|
+
|| existing.provenance.name !== projection.provenance.name
|
|
884
|
+
|| existing.provenance.source !== projection.provenance.source
|
|
885
|
+
|| existing.provenance.sourceDigest !== projection.provenance.sourceDigest
|
|
886
|
+
|| !hasSameCanonicalSource(existing.canonicalSource, projection.canonicalSource))) {
|
|
887
|
+
throw new Error(`Canonical source "${projection.provenance.source}" changed during runtime Skill projection.`);
|
|
888
|
+
}
|
|
889
|
+
bindings.set(projection.bindingKey, projection);
|
|
890
|
+
}
|
|
891
|
+
for (const projection of projections) {
|
|
892
|
+
let currentSource;
|
|
893
|
+
try {
|
|
894
|
+
currentSource = await resolveCanonicalRuntimeSourceIdentity(projection.canonicalSource.rootPath, projection.canonicalSource.relativePath, 'runtime Skill projection canonical source');
|
|
895
|
+
}
|
|
896
|
+
catch {
|
|
897
|
+
throw new Error(`Canonical source "${projection.provenance.source}" changed during runtime Skill projection.`);
|
|
898
|
+
}
|
|
899
|
+
if (!hasSameCanonicalSource(projection.canonicalSource, currentSource)
|
|
900
|
+
|| await calculateFileDigest(currentSource.sourceRealPath) !== projection.provenance.sourceDigest) {
|
|
901
|
+
throw new Error(`Canonical source "${projection.provenance.source}" changed during runtime Skill projection.`);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
async function validateBuildImportProjectionSources(projections) {
|
|
906
|
+
const bindings = new Map();
|
|
907
|
+
for (const projection of projections) {
|
|
908
|
+
const existing = bindings.get(projection.bindingKey);
|
|
909
|
+
if (existing
|
|
910
|
+
&& (existing.provenance.provider !== projection.provenance.provider
|
|
911
|
+
|| existing.provenance.providerVersion !== projection.provenance.providerVersion
|
|
912
|
+
|| existing.provenance.name !== projection.provenance.name
|
|
913
|
+
|| existing.provenance.source !== projection.provenance.source
|
|
914
|
+
|| existing.provenance.sourceDigest !== projection.provenance.sourceDigest
|
|
915
|
+
|| !hasSameCanonicalSource(existing.canonicalSource, projection.canonicalSource))) {
|
|
916
|
+
throw new Error(`Catalog runtime import "${projection.provenance.provider}/${projection.provenance.name}" changed during build import projection.`);
|
|
917
|
+
}
|
|
918
|
+
bindings.set(projection.bindingKey, projection);
|
|
919
|
+
}
|
|
920
|
+
for (const projection of projections) {
|
|
921
|
+
try {
|
|
922
|
+
const currentSource = await resolveCanonicalRuntimeSourceIdentity(projection.canonicalSource.rootPath, projection.canonicalSource.relativePath, 'build import projection canonical source');
|
|
923
|
+
if (!hasSameCanonicalSource(projection.canonicalSource, currentSource)
|
|
924
|
+
|| await calculateFileDigest(currentSource.sourceRealPath) !== projection.provenance.sourceDigest) {
|
|
925
|
+
throw new Error('stale canonical source');
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
catch {
|
|
929
|
+
throw new Error(`Catalog runtime import "${projection.provenance.provider}/${projection.provenance.name}" changed during build import projection.`);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
async function createStagedPlugin(plugin, runner, resolver) {
|
|
934
|
+
const stagingRoot = await fs.mkdtemp(assertLocalPluginStagingPathForTests(path.join(os.tmpdir(), 'aw-plugin-staging-'), 'local plugin bundle staging root'));
|
|
935
|
+
const stagingPluginRoot = assertLocalPluginStagingPathForTests(path.join(stagingRoot, 'plugin'), 'local plugin staged plugin root');
|
|
936
|
+
try {
|
|
937
|
+
await fs.copy(plugin.rootDir, stagingPluginRoot, {
|
|
938
|
+
filter(source) {
|
|
939
|
+
return !isIgnoredPluginInputDirectory(path.basename(source))
|
|
940
|
+
&& !isMacOsMetadataName(path.basename(source));
|
|
941
|
+
},
|
|
942
|
+
});
|
|
943
|
+
const sourceBuild = plugin.manifest.scripts?.node?.build;
|
|
944
|
+
const declaredBuildImports = plugin.manifest.buildConfig?.buildImports ?? [];
|
|
945
|
+
if (declaredBuildImports.length > 0 && !sourceBuild) {
|
|
946
|
+
throw new Error(`Invalid plugin "${plugin.manifest.name}": buildConfig.buildImports requires scripts.node.build.`);
|
|
947
|
+
}
|
|
948
|
+
const buildEnv = { ...process.env };
|
|
949
|
+
const buildImportProvenance = [];
|
|
950
|
+
const buildImportProjections = [];
|
|
951
|
+
for (const buildImport of declaredBuildImports) {
|
|
952
|
+
if (!resolver) {
|
|
953
|
+
throw new Error(`Cannot resolve buildConfig.buildImports for plugin "${plugin.manifest.name}": catalog runtime import resolver is required.`);
|
|
954
|
+
}
|
|
955
|
+
if (Object.hasOwn(process.env, buildImport.env)) {
|
|
956
|
+
throw new Error(`Invalid buildConfig.buildImports env "${buildImport.env}": refusing to overwrite an existing environment variable.`);
|
|
957
|
+
}
|
|
958
|
+
const resolution = await resolver.resolve({
|
|
959
|
+
consumer: plugin,
|
|
960
|
+
reference: buildImport,
|
|
961
|
+
purpose: 'build',
|
|
962
|
+
});
|
|
963
|
+
const importPath = path.join(stagingRoot, 'build-imports', buildImport.env);
|
|
964
|
+
await fs.ensureDir(path.dirname(importPath));
|
|
965
|
+
await fs.copyFile(resolution.sourcePath, importPath);
|
|
966
|
+
await fs.chmod(importPath, 0o444);
|
|
967
|
+
if (await calculateFileDigest(importPath) !== resolution.sourceDigest) {
|
|
968
|
+
throw new Error(`Catalog runtime import "${buildImport.plugin}/${buildImport.export}" changed while it was materialized.`);
|
|
969
|
+
}
|
|
970
|
+
buildEnv[buildImport.env] = importPath;
|
|
971
|
+
const provenance = toRuntimeImportProvenance(resolution);
|
|
972
|
+
buildImportProvenance.push(provenance);
|
|
973
|
+
buildImportProjections.push({
|
|
974
|
+
provenance,
|
|
975
|
+
bindingKey: `${buildImport.plugin}/${buildImport.export}`,
|
|
976
|
+
canonicalSource: resolution.canonicalSource,
|
|
977
|
+
});
|
|
978
|
+
}
|
|
979
|
+
await validateBuildImportProjectionSources(buildImportProjections);
|
|
980
|
+
if (sourceBuild) {
|
|
981
|
+
const sourcePackageRoot = packageRootPath({
|
|
982
|
+
...plugin,
|
|
983
|
+
rootDir: stagingPluginRoot,
|
|
984
|
+
});
|
|
985
|
+
if (sourcePackageRoot) {
|
|
986
|
+
await runner.installPackageRoot(sourcePackageRoot);
|
|
987
|
+
}
|
|
988
|
+
await runner.runNodeBuild({
|
|
989
|
+
pluginRoot: stagingPluginRoot,
|
|
990
|
+
scriptPath: sourceBuild.path,
|
|
991
|
+
args: sourceBuild.args ?? [],
|
|
992
|
+
env: buildEnv,
|
|
993
|
+
});
|
|
994
|
+
await validateBuildImportProjectionSources(buildImportProjections);
|
|
995
|
+
}
|
|
996
|
+
const stagedPlugin = await readPluginManifest(stagingPluginRoot);
|
|
997
|
+
if (stagedPlugin.manifest.name !== plugin.manifest.name) {
|
|
998
|
+
throw new Error(`Invalid scripts.node.build: build changed plugin name from "${plugin.manifest.name}" to "${stagedPlugin.manifest.name}".`);
|
|
999
|
+
}
|
|
1000
|
+
const finalPackageRoot = packageRootPath(stagedPlugin);
|
|
1001
|
+
if (finalPackageRoot) {
|
|
1002
|
+
await runner.installPackageRoot(finalPackageRoot);
|
|
1003
|
+
await assertNoProductionInstallScripts(finalPackageRoot);
|
|
1004
|
+
}
|
|
1005
|
+
const runtimeContext = {
|
|
1006
|
+
resolver,
|
|
1007
|
+
buildImports: buildImportProvenance,
|
|
1008
|
+
};
|
|
1009
|
+
preparedBuildImportProjections.set(runtimeContext, buildImportProjections);
|
|
1010
|
+
return {
|
|
1011
|
+
plugin: stagedPlugin,
|
|
1012
|
+
runtimeContext,
|
|
1013
|
+
cleanup: () => fs.remove(stagingRoot),
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
catch (error) {
|
|
1017
|
+
await fs.remove(stagingRoot);
|
|
1018
|
+
throw error;
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
async function resolveBuildPlugin(plugin, options) {
|
|
1022
|
+
if (options.buildMode === 'prepared') {
|
|
1023
|
+
if (((plugin.manifest.buildConfig?.buildImports?.length ?? 0) > 0
|
|
1024
|
+
|| (plugin.manifest.buildConfig?.skillRuntimeFiles ?? []).some((entry) => entry.import))
|
|
1025
|
+
&& !options.preparedRuntimeContext) {
|
|
1026
|
+
throw new Error(`Cannot bundle prepared plugin "${plugin.manifest.name}": prepared runtime import context is required.`);
|
|
1027
|
+
}
|
|
1028
|
+
return {
|
|
1029
|
+
plugin,
|
|
1030
|
+
runtimeContext: options.preparedRuntimeContext ?? {
|
|
1031
|
+
resolver: options.runtimeResolver,
|
|
1032
|
+
buildImports: [],
|
|
1033
|
+
},
|
|
1034
|
+
cleanup: async () => { },
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
if (options.buildMode === 'build-free') {
|
|
1038
|
+
if (plugin.manifest.scripts?.node || (plugin.manifest.buildConfig?.buildImports?.length ?? 0) > 0) {
|
|
1039
|
+
throw new Error(`Cannot bundle plugin "${plugin.manifest.name}" in build-free mode because scripts.node requires staging build mode.`);
|
|
1040
|
+
}
|
|
1041
|
+
return {
|
|
1042
|
+
plugin,
|
|
1043
|
+
runtimeContext: { resolver: options.runtimeResolver, buildImports: [] },
|
|
1044
|
+
cleanup: async () => { },
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
return createStagedPlugin(plugin, options.stagingRunner, options.runtimeResolver);
|
|
1048
|
+
}
|
|
1049
|
+
export async function prepareLocalPluginBundleSource(plugin, options = {}) {
|
|
1050
|
+
await assertPluginInputTree(plugin.rootDir);
|
|
1051
|
+
const buildOptions = {
|
|
1052
|
+
buildMode: options.buildMode ?? 'staging',
|
|
1053
|
+
stagingRunner: options.stagingRunner ?? defaultStagingRunner,
|
|
1054
|
+
runtimeResolver: options.runtimeResolver,
|
|
1055
|
+
preparedRuntimeContext: undefined,
|
|
1056
|
+
};
|
|
1057
|
+
return resolveBuildPlugin(plugin, buildOptions);
|
|
1058
|
+
}
|
|
1059
|
+
export async function bundleLocalPlugin(plugin, outputRoot, options = {}) {
|
|
1060
|
+
const buildOptions = {
|
|
1061
|
+
buildMode: options.buildMode ?? 'build-free',
|
|
1062
|
+
stagingRunner: options.stagingRunner ?? defaultStagingRunner,
|
|
1063
|
+
runtimeResolver: options.runtimeResolver,
|
|
1064
|
+
preparedRuntimeContext: options.preparedRuntimeContext,
|
|
1065
|
+
};
|
|
1066
|
+
await assertPluginInputTree(plugin.rootDir);
|
|
1067
|
+
await fs.remove(outputRoot);
|
|
1068
|
+
const buildPlugin = await resolveBuildPlugin(plugin, buildOptions);
|
|
1069
|
+
try {
|
|
1070
|
+
plugin = buildPlugin.plugin;
|
|
1071
|
+
assertManifestPlatformSupport(plugin.manifest.name, plugin.manifest);
|
|
1072
|
+
await fs.ensureDir(outputRoot);
|
|
1073
|
+
const supportedPlatforms = resolveSupportedPlatforms(plugin.manifest);
|
|
1074
|
+
await assertSkillRuntimeProjectionTargets(plugin);
|
|
1075
|
+
const platformFiles = {};
|
|
1076
|
+
const platformManifests = {};
|
|
1077
|
+
const buildConfig = plugin.manifest.buildConfig;
|
|
1078
|
+
const templatePatterns = buildConfig?.templates?.include ?? [];
|
|
1079
|
+
const templateVars = buildConfig?.templates?.vars ?? {};
|
|
1080
|
+
const resolvedSlashCommands = await resolveSlashCommands(plugin.rootDir, plugin.manifest, {
|
|
1081
|
+
targetPlatforms: supportedPlatforms,
|
|
1082
|
+
});
|
|
1083
|
+
for (const platform of PLATFORM_ORDER) {
|
|
1084
|
+
if (!supportedPlatforms.has(platform)) {
|
|
1085
|
+
continue;
|
|
1086
|
+
}
|
|
1087
|
+
platformFiles[platform] = new Set();
|
|
1088
|
+
platformManifests[platform] = createPlatformManifestBase(plugin);
|
|
1089
|
+
}
|
|
1090
|
+
for (const platform of PLATFORM_ORDER) {
|
|
1091
|
+
const manifest = platformManifests[platform];
|
|
1092
|
+
const files = platformFiles[platform];
|
|
1093
|
+
if (!manifest || !files) {
|
|
1094
|
+
continue;
|
|
1095
|
+
}
|
|
1096
|
+
manifest.skills = await addDeclaredSkillPathFiles(plugin, platform, plugin.manifest.skills, files);
|
|
1097
|
+
manifest.mcpServers = await addDeclaredPathFiles(plugin, platform, plugin.manifest.mcpServers, files);
|
|
1098
|
+
}
|
|
1099
|
+
const codexManifest = platformManifests.codex;
|
|
1100
|
+
const codexFiles = platformFiles.codex;
|
|
1101
|
+
if (codexManifest && codexFiles) {
|
|
1102
|
+
codexManifest.apps = await addDeclaredPathFiles(plugin, 'codex', plugin.manifest.apps, codexFiles);
|
|
1103
|
+
const hooksArtifact = renderResolvedHooksArtifact(resolvePlatformHookDefinitions(plugin.manifest, 'codex'), 'codex');
|
|
1104
|
+
if (hooksArtifact) {
|
|
1105
|
+
codexManifest.hooks = hooksArtifact.content;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
const claudeManifest = platformManifests.claude;
|
|
1109
|
+
const claudeFiles = platformFiles.claude;
|
|
1110
|
+
if (claudeManifest && claudeFiles) {
|
|
1111
|
+
const claudeOverrides = buildConfig?.manifestOverrides?.claude;
|
|
1112
|
+
claudeManifest.outputStyles = await addDeclaredPathFiles(plugin, 'claude', claudeOverrides?.outputStyles, claudeFiles);
|
|
1113
|
+
claudeManifest.lspServers = await addDeclaredLspServerFiles(plugin, claudeOverrides?.lspServers, claudeFiles);
|
|
1114
|
+
claudeManifest.userConfig = claudeOverrides?.userConfig;
|
|
1115
|
+
claudeManifest.channels = claudeOverrides?.channels;
|
|
1116
|
+
const hooksArtifact = renderResolvedHooksArtifact(resolvePlatformHookDefinitions(plugin.manifest, 'claude'), 'claude');
|
|
1117
|
+
if (hooksArtifact) {
|
|
1118
|
+
const hooksPath = path.join(outputRoot, 'claude', 'hooks', 'hooks.json');
|
|
1119
|
+
await writeJsonFile(hooksPath, hooksArtifact.content);
|
|
1120
|
+
claudeManifest.hooks = './claude/hooks/hooks.json';
|
|
1121
|
+
}
|
|
1122
|
+
const claudeAgents = resolvePlatformEntries(plugin.manifest.extensions?.agents, 'claude');
|
|
1123
|
+
if (claudeAgents.length > 0) {
|
|
1124
|
+
claudeManifest.agents = [];
|
|
1125
|
+
for (const agent of claudeAgents) {
|
|
1126
|
+
const generatedName = buildGeneratedName(plugin.manifest.name, agent.name);
|
|
1127
|
+
const relativePath = `./claude/agents/${generatedName}.md`;
|
|
1128
|
+
claudeManifest.agents.push(relativePath);
|
|
1129
|
+
await writeTextFile(path.join(outputRoot, stripDotSlash(relativePath)), renderClaudeAgentContent(agent));
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
const sourceFiles = (await listFilesRecursively(plugin.rootDir)).filter((filePath) => !isDeclaredSkillAuthorOnlyFile(plugin, filePath));
|
|
1134
|
+
if (claudeFiles && buildConfig?.fileRules?.claude) {
|
|
1135
|
+
for (const filePath of applyFileRules(sourceFiles.filter((filePath) => !isDynamicSkillSourceFile(plugin, 'claude', filePath)), buildConfig.fileRules.claude.include, buildConfig.fileRules.claude.exclude)) {
|
|
1136
|
+
if (resolvedSlashCommands &&
|
|
1137
|
+
filePath === stripDotSlash(resolvedSlashCommands.rootRelativePath)) {
|
|
1138
|
+
continue;
|
|
1139
|
+
}
|
|
1140
|
+
if (resolvedSlashCommands &&
|
|
1141
|
+
filePath.startsWith(`${stripDotSlash(resolvedSlashCommands.rootRelativePath)}/`)) {
|
|
1142
|
+
continue;
|
|
1143
|
+
}
|
|
1144
|
+
claudeFiles.add(filePath);
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
if (codexFiles && buildConfig?.fileRules?.codex) {
|
|
1148
|
+
for (const filePath of applyFileRules(sourceFiles.filter((filePath) => !isDynamicSkillSourceFile(plugin, 'codex', filePath)), buildConfig.fileRules.codex.include, buildConfig.fileRules.codex.exclude)) {
|
|
1149
|
+
if (resolvedSlashCommands &&
|
|
1150
|
+
filePath === stripDotSlash(resolvedSlashCommands.rootRelativePath)) {
|
|
1151
|
+
continue;
|
|
1152
|
+
}
|
|
1153
|
+
if (resolvedSlashCommands &&
|
|
1154
|
+
filePath.startsWith(`${stripDotSlash(resolvedSlashCommands.rootRelativePath)}/`)) {
|
|
1155
|
+
continue;
|
|
1156
|
+
}
|
|
1157
|
+
codexFiles.add(filePath);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
for (const platform of PLATFORM_ORDER) {
|
|
1161
|
+
const files = platformFiles[platform];
|
|
1162
|
+
if (!files) {
|
|
1163
|
+
continue;
|
|
1164
|
+
}
|
|
1165
|
+
for (const filePath of files) {
|
|
1166
|
+
await copyFileWithTemplateSupport(plugin.rootDir, outputRoot, filePath, platform, templatePatterns, templateVars);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
if (resolvedSlashCommands) {
|
|
1170
|
+
if (claudeManifest) {
|
|
1171
|
+
claudeManifest.commands = './claude/commands';
|
|
1172
|
+
}
|
|
1173
|
+
if (codexManifest) {
|
|
1174
|
+
codexManifest.skills ??= './codex/skills';
|
|
1175
|
+
}
|
|
1176
|
+
for (const command of resolvedSlashCommands.commands) {
|
|
1177
|
+
if (claudeManifest && command.claude) {
|
|
1178
|
+
await writeTextFile(path.join(outputRoot, 'claude', 'commands', `${command.name}.md`), renderClaudeSlashCommand(command));
|
|
1179
|
+
}
|
|
1180
|
+
if (codexManifest && command.codex) {
|
|
1181
|
+
await writeTextFile(path.join(outputRoot, 'codex', 'skills', command.name, 'SKILL.md'), renderCodexSlashCommandSkillMarkdown(command));
|
|
1182
|
+
await writeTextFile(path.join(outputRoot, 'codex', 'skills', command.name, 'agents', 'openai.yaml'), renderCodexSlashCommandOpenAiYaml(command));
|
|
1183
|
+
for (const asset of command.codex.assets) {
|
|
1184
|
+
await copySlashCommandAsset(plugin.rootDir, outputRoot, command.name, asset.sourceRelativePath, asset.generatedRelativePath);
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
const skillRuntimeFileProjections = await projectSkillRuntimeFiles({
|
|
1190
|
+
plugin,
|
|
1191
|
+
outputRoot,
|
|
1192
|
+
supportedPlatforms,
|
|
1193
|
+
resolver: buildPlugin.runtimeContext.resolver,
|
|
1194
|
+
});
|
|
1195
|
+
const skillRuntimeFiles = skillRuntimeFileProjections.map(({ provenance }) => provenance);
|
|
1196
|
+
const portableRuntimeFiles = skillRuntimeFiles
|
|
1197
|
+
.filter((entry) => entry.distribution === 'agent-skills')
|
|
1198
|
+
.map((entry) => ({
|
|
1199
|
+
skill: entry.skill,
|
|
1200
|
+
target: entry.target,
|
|
1201
|
+
path: `./agent-skills/skills/${entry.skill}/${entry.target}`,
|
|
1202
|
+
digest: entry.targetDigest,
|
|
1203
|
+
provider: entry.provider,
|
|
1204
|
+
providerVersion: entry.providerVersion,
|
|
1205
|
+
exportName: entry.name,
|
|
1206
|
+
source: entry.source,
|
|
1207
|
+
sourceDigest: entry.sourceDigest,
|
|
1208
|
+
}));
|
|
1209
|
+
await copyPortableStaticSkills(plugin, outputRoot);
|
|
1210
|
+
if (await fs.pathExists(path.join(plugin.rootDir, 'README.md'))) {
|
|
1211
|
+
await copyBundleRootFile(plugin.rootDir, outputRoot, 'README.md');
|
|
1212
|
+
}
|
|
1213
|
+
for (const filePath of await collectAwRuntimeFiles(plugin)) {
|
|
1214
|
+
await copyBundleRootFile(plugin.rootDir, outputRoot, filePath);
|
|
1215
|
+
}
|
|
1216
|
+
await copyArtifactSourceDirectories(plugin, outputRoot);
|
|
1217
|
+
await copyProductionPackageRoot(plugin, outputRoot);
|
|
1218
|
+
const bundleManifest = await resolveArtifactRuntimeImports({
|
|
1219
|
+
plugin,
|
|
1220
|
+
outputRoot,
|
|
1221
|
+
resolver: buildPlugin.runtimeContext.resolver,
|
|
1222
|
+
});
|
|
1223
|
+
await writeJsonFile(path.join(outputRoot, '.agents-plugin', 'plugin.json'), bundleManifest);
|
|
1224
|
+
if (portableRuntimeFiles.length > 0) {
|
|
1225
|
+
await writeJsonFile(path.join(outputRoot, '.agents-plugin', 'portable-runtime-files.json'), portableRuntimeFiles);
|
|
1226
|
+
}
|
|
1227
|
+
for (const platform of PLATFORM_ORDER) {
|
|
1228
|
+
const manifest = platformManifests[platform];
|
|
1229
|
+
if (!manifest) {
|
|
1230
|
+
continue;
|
|
1231
|
+
}
|
|
1232
|
+
await writeJsonFile(path.join(outputRoot, PLATFORM_MANIFEST_DIRS[platform], 'plugin.json'), manifest);
|
|
1233
|
+
}
|
|
1234
|
+
await validateSkillRuntimeProjectionSources(skillRuntimeFileProjections);
|
|
1235
|
+
await validateSkillRuntimeProjectionFreshness(outputRoot, skillRuntimeFiles.filter((entry) => entry.platform !== undefined));
|
|
1236
|
+
await validateGeneratedSkillRuntimeFiles(plugin, outputRoot, supportedPlatforms);
|
|
1237
|
+
if ((options.runtimeSkillClosureValidation ?? 'current') === 'current') {
|
|
1238
|
+
for (const platform of PLATFORM_ORDER) {
|
|
1239
|
+
const skillsPath = platformManifests[platform]?.skills;
|
|
1240
|
+
if (!skillsPath)
|
|
1241
|
+
continue;
|
|
1242
|
+
await validateRuntimeSkillClosuresRoot(path.join(outputRoot, stripDotSlash(skillsPath)));
|
|
1243
|
+
}
|
|
1244
|
+
if (plugin.manifest.distributions?.agentSkills?.skills) {
|
|
1245
|
+
await validatePortableSkillDirectoriesRoot(path.join(outputRoot, 'agent-skills', 'skills'));
|
|
1246
|
+
await validateRuntimeSkillClosuresRoot(path.join(outputRoot, 'agent-skills', 'skills'));
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
await validateBuildImportProjectionSources(preparedBuildImportProjections.get(buildPlugin.runtimeContext) ?? []);
|
|
1250
|
+
return {
|
|
1251
|
+
outputRoot,
|
|
1252
|
+
plugin,
|
|
1253
|
+
platformManifests,
|
|
1254
|
+
runtimeProjection: {
|
|
1255
|
+
buildImports: buildPlugin.runtimeContext.buildImports,
|
|
1256
|
+
skillRuntimeFiles,
|
|
1257
|
+
},
|
|
1258
|
+
};
|
|
1259
|
+
}
|
|
1260
|
+
catch (error) {
|
|
1261
|
+
await fs.remove(outputRoot);
|
|
1262
|
+
throw error;
|
|
1263
|
+
}
|
|
1264
|
+
finally {
|
|
1265
|
+
await buildPlugin.cleanup();
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
//# sourceMappingURL=local-plugin.js.map
|