@lesliechan721/aw 0.1.0-beta.64 → 0.1.0-beta.65
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-runtime-config.mjs +3 -3
- package/dist/authoring/assets/aw-runtime-config.mjs.map +1 -1
- package/dist/authoring/scripts/add-skill.mjs +3 -17
- package/dist/authoring/scripts/add-skill.mjs.map +1 -1
- package/dist/authoring/scripts/init-plugin.mjs +1 -0
- package/dist/authoring/scripts/init-plugin.mjs.map +1 -1
- package/dist/authoring/scripts/lib/plugin-version-check.mjs +1 -1
- package/dist/authoring/scripts/lib/skill-scaffold.d.mts +2 -0
- package/dist/authoring/scripts/lib/skill-scaffold.mjs +2 -0
- package/dist/authoring/scripts/lib/skill-scaffold.mjs.map +1 -1
- package/dist/authoring/scripts/validate-plugin.mjs +95 -698
- package/dist/authoring/scripts/validate-plugin.mjs.map +1 -1
- package/dist/scripts/aw-skill-eval-materializer.d.ts +2 -0
- package/dist/scripts/aw-skill-eval-materializer.js +74 -44
- package/dist/scripts/aw-skill-eval-materializer.js.map +1 -1
- package/dist/scripts/bundle-plugins.js +10 -2
- package/dist/scripts/bundle-plugins.js.map +1 -1
- package/dist/scripts/plugin-staging.d.ts +1 -1
- package/dist/scripts/plugin-staging.js +1 -1
- package/dist/scripts/plugin-staging.js.map +1 -1
- package/dist/scripts/test-plugin-scripts.js +31 -31
- package/dist/scripts/test-plugin-scripts.js.map +1 -1
- package/dist/src/commands/aw-capabilities.d.ts +1 -1
- package/dist/src/commands/aw-capabilities.js +2 -0
- package/dist/src/commands/aw-capabilities.js.map +1 -1
- package/dist/src/commands/console.js +4 -3
- package/dist/src/commands/console.js.map +1 -1
- package/dist/src/commands/intent-command.d.ts +30 -0
- package/dist/src/commands/intent-command.js +164 -0
- package/dist/src/commands/intent-command.js.map +1 -0
- package/dist/src/commands/operation-plan.d.ts +2 -0
- package/dist/src/commands/operation-plan.js +2 -1
- package/dist/src/commands/operation-plan.js.map +1 -1
- package/dist/src/commands/options.d.ts +3 -11
- package/dist/src/commands/options.js +11 -17
- package/dist/src/commands/options.js.map +1 -1
- package/dist/src/commands/plugin-capabilities.js +27 -33
- package/dist/src/commands/plugin-capabilities.js.map +1 -1
- package/dist/src/commands/rebuild-command.d.ts +108 -6
- package/dist/src/commands/rebuild-command.js +617 -1549
- package/dist/src/commands/rebuild-command.js.map +1 -1
- package/dist/src/commands/rebuild-integration.d.ts +19 -3
- package/dist/src/commands/rebuild-integration.js +500 -459
- package/dist/src/commands/rebuild-integration.js.map +1 -1
- package/dist/src/commands/rebuild-operations.js +1 -2
- package/dist/src/commands/rebuild-operations.js.map +1 -1
- package/dist/src/commands/review-inspection.d.ts +2 -2
- package/dist/src/commands/review-inspection.js +30 -86
- package/dist/src/commands/review-inspection.js.map +1 -1
- package/dist/src/commands/review-preparation.js +16 -7
- package/dist/src/commands/review-preparation.js.map +1 -1
- package/dist/src/commands/skill-eval.d.ts +2 -0
- package/dist/src/commands/skill-eval.js +15 -9
- package/dist/src/commands/skill-eval.js.map +1 -1
- package/dist/src/commands/status-v6.d.ts +38 -5
- package/dist/src/commands/status-v6.js +269 -102
- package/dist/src/commands/status-v6.js.map +1 -1
- package/dist/src/commands/targets-command.d.ts +27 -0
- package/dist/src/commands/targets-command.js +77 -0
- package/dist/src/commands/targets-command.js.map +1 -0
- package/dist/src/commands/write-commands.js +5 -5
- package/dist/src/commands/write-commands.js.map +1 -1
- package/dist/src/eval/manifest-v1.d.ts +2 -0
- package/dist/src/eval/manifest-v1.js +7 -2
- package/dist/src/eval/manifest-v1.js.map +1 -1
- package/dist/src/generators/local-plugin.d.ts +2 -1
- package/dist/src/generators/local-plugin.js +111 -108
- package/dist/src/generators/local-plugin.js.map +1 -1
- package/dist/src/index.d.ts +10 -17
- package/dist/src/index.js +585 -1349
- package/dist/src/index.js.map +1 -1
- package/dist/src/intent/deployment-preferences.d.ts +63 -0
- package/dist/src/intent/deployment-preferences.js +170 -0
- package/dist/src/intent/deployment-preferences.js.map +1 -0
- package/dist/src/intent/diagnostics.d.ts +11 -0
- package/dist/src/intent/diagnostics.js +14 -0
- package/dist/src/intent/diagnostics.js.map +1 -0
- package/dist/src/intent/intent-codec.d.ts +19 -0
- package/dist/src/intent/intent-codec.js +117 -0
- package/dist/src/intent/intent-codec.js.map +1 -0
- package/dist/src/intent/intent-store.d.ts +43 -0
- package/dist/src/intent/intent-store.js +118 -0
- package/dist/src/intent/intent-store.js.map +1 -0
- package/dist/src/intent/scope-context.d.ts +33 -0
- package/dist/src/intent/scope-context.js +145 -0
- package/dist/src/intent/scope-context.js.map +1 -0
- package/dist/src/intent/work-context.d.ts +13 -0
- package/dist/src/intent/work-context.js +22 -0
- package/dist/src/intent/work-context.js.map +1 -0
- package/dist/src/output/command-receipt.js +16 -9
- package/dist/src/output/command-receipt.js.map +1 -1
- package/dist/src/portable/commands.d.ts +18 -8
- package/dist/src/portable/commands.js +46 -562
- package/dist/src/portable/commands.js.map +1 -1
- package/dist/src/portable/historical-materialization.d.ts +22 -0
- package/dist/src/portable/historical-materialization.js +124 -0
- package/dist/src/portable/historical-materialization.js.map +1 -0
- package/dist/src/portable/materializer.d.ts +8 -0
- package/dist/src/portable/materializer.js +75 -44
- package/dist/src/portable/materializer.js.map +1 -1
- package/dist/src/portable/recovery-layout.d.ts +17 -0
- package/dist/src/portable/recovery-layout.js +55 -0
- package/dist/src/portable/recovery-layout.js.map +1 -0
- package/dist/src/portable/recovery.d.ts +143 -0
- package/dist/src/portable/recovery.js +339 -0
- package/dist/src/portable/recovery.js.map +1 -0
- package/dist/src/portable/writer.d.ts +64 -0
- package/dist/src/portable/writer.js +316 -0
- package/dist/src/portable/writer.js.map +1 -0
- package/dist/src/recovery/coordinator.d.ts +137 -0
- package/dist/src/recovery/coordinator.js +1198 -0
- package/dist/src/recovery/coordinator.js.map +1 -0
- package/dist/src/recovery/demand.d.ts +44 -0
- package/dist/src/recovery/demand.js +178 -0
- package/dist/src/recovery/demand.js.map +1 -0
- package/dist/src/recovery/joint-coordinator.d.ts +24 -0
- package/dist/src/recovery/joint-coordinator.js +770 -0
- package/dist/src/recovery/joint-coordinator.js.map +1 -0
- package/dist/src/recovery/joint-demand.d.ts +68 -0
- package/dist/src/recovery/joint-demand.js +166 -0
- package/dist/src/recovery/joint-demand.js.map +1 -0
- package/dist/src/recovery/receipt.d.ts +81 -0
- package/dist/src/recovery/receipt.js +2 -0
- package/dist/src/recovery/receipt.js.map +1 -0
- package/dist/src/recovery/retirement.d.ts +45 -0
- package/dist/src/recovery/retirement.js +366 -0
- package/dist/src/recovery/retirement.js.map +1 -0
- package/dist/src/recovery/status.d.ts +108 -0
- package/dist/src/recovery/status.js +417 -0
- package/dist/src/recovery/status.js.map +1 -0
- package/dist/src/recovery/types.d.ts +86 -0
- package/dist/src/recovery/types.js +2 -0
- package/dist/src/recovery/types.js.map +1 -0
- package/dist/src/review/review-profile.d.ts +2 -1
- package/dist/src/review/review-profile.js +15 -15
- package/dist/src/review/review-profile.js.map +1 -1
- package/dist/src/review/review-selection.d.ts +1 -2
- package/dist/src/review/review-selection.js +40 -114
- package/dist/src/review/review-selection.js.map +1 -1
- package/dist/src/review/review-types.d.ts +4 -4
- package/dist/src/review/review-types.js.map +1 -1
- package/dist/src/review/skill-materialization.js +15 -6
- package/dist/src/review/skill-materialization.js.map +1 -1
- package/dist/src/review/source-binding.d.ts +14 -4
- package/dist/src/review/source-binding.js +62 -117
- package/dist/src/review/source-binding.js.map +1 -1
- package/dist/src/tui/agent-management.d.ts +23 -0
- package/dist/src/tui/agent-management.js +217 -0
- package/dist/src/tui/agent-management.js.map +1 -0
- package/dist/src/tui/agent-settings.d.ts +44 -0
- package/dist/src/tui/agent-settings.js +98 -0
- package/dist/src/tui/agent-settings.js.map +1 -0
- package/dist/src/tui/components.d.ts +3 -0
- package/dist/src/tui/components.js +10 -1
- package/dist/src/tui/components.js.map +1 -1
- package/dist/src/tui/config-references.d.ts +6 -3
- package/dist/src/tui/config-references.js +17 -12
- package/dist/src/tui/config-references.js.map +1 -1
- package/dist/src/tui/console-app-v4.d.ts +1 -2
- package/dist/src/tui/console-app-v4.js +1533 -1047
- package/dist/src/tui/console-app-v4.js.map +1 -1
- package/dist/src/tui/controller-runtime.d.ts +2 -1
- package/dist/src/tui/controller-runtime.js +405 -1626
- package/dist/src/tui/controller-runtime.js.map +1 -1
- package/dist/src/tui/controller.d.ts +131 -81
- package/dist/src/tui/controller.js +307 -227
- package/dist/src/tui/controller.js.map +1 -1
- package/dist/src/tui/entity-cards.d.ts +2 -2
- package/dist/src/tui/entity-cards.js +98 -20
- package/dist/src/tui/entity-cards.js.map +1 -1
- package/dist/src/tui/glossary.d.ts +2 -0
- package/dist/src/tui/glossary.js +20 -0
- package/dist/src/tui/glossary.js.map +1 -1
- package/dist/src/tui/model.d.ts +28 -10
- package/dist/src/tui/model.js +41 -41
- package/dist/src/tui/model.js.map +1 -1
- package/dist/src/tui/operation-review-planner.d.ts +2 -0
- package/dist/src/tui/operation-review-planner.js +58 -122
- package/dist/src/tui/operation-review-planner.js.map +1 -1
- package/dist/src/tui/plugin-content.js +7 -4
- package/dist/src/tui/plugin-content.js.map +1 -1
- package/dist/src/tui/plugin-detail.d.ts +22 -3
- package/dist/src/tui/plugin-detail.js +113 -26
- package/dist/src/tui/plugin-detail.js.map +1 -1
- package/dist/src/tui/reader.d.ts +1 -0
- package/dist/src/tui/reader.js +3 -1
- package/dist/src/tui/reader.js.map +1 -1
- package/dist/src/tui/router.d.ts +23 -33
- package/dist/src/tui/router.js.map +1 -1
- package/dist/src/tui/scoped-flow.d.ts +45 -0
- package/dist/src/tui/scoped-flow.js +96 -0
- package/dist/src/tui/scoped-flow.js.map +1 -0
- package/dist/src/tui/scoped-inventory.d.ts +122 -0
- package/dist/src/tui/scoped-inventory.js +225 -0
- package/dist/src/tui/scoped-inventory.js.map +1 -0
- package/dist/src/tui/screen-registry.d.ts +25 -25
- package/dist/src/tui/screen-registry.js +3 -7
- package/dist/src/tui/screen-registry.js.map +1 -1
- package/dist/src/tui/session-console-app.js +1 -1
- package/dist/src/tui/session-console-app.js.map +1 -1
- package/dist/src/tui/session-host.js +12 -2
- package/dist/src/tui/session-host.js.map +1 -1
- package/dist/src/types.d.ts +15 -12
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/agent-version.js +2 -0
- package/dist/src/utils/agent-version.js.map +1 -1
- package/dist/src/utils/artifact-plan.js +13 -6
- package/dist/src/utils/artifact-plan.js.map +1 -1
- package/dist/src/utils/artifact-renderer.d.ts +6 -3
- package/dist/src/utils/artifact-renderer.js +27 -32
- package/dist/src/utils/artifact-renderer.js.map +1 -1
- package/dist/src/utils/artifact-request.d.ts +1 -0
- package/dist/src/utils/artifact-request.js +22 -12
- package/dist/src/utils/artifact-request.js.map +1 -1
- package/dist/src/utils/artifact-sources.d.ts +2 -2
- package/dist/src/utils/bundle-layout.js +18 -16
- package/dist/src/utils/bundle-layout.js.map +1 -1
- package/dist/src/utils/catalog-digests.js +2 -0
- package/dist/src/utils/catalog-digests.js.map +1 -1
- package/dist/src/utils/catalog-runtime-projection.d.ts +4 -3
- package/dist/src/utils/catalog-runtime-projection.js.map +1 -1
- package/dist/src/utils/catalog-source-references.d.ts +5 -0
- package/dist/src/utils/catalog-source-references.js +42 -57
- package/dist/src/utils/catalog-source-references.js.map +1 -1
- package/dist/src/utils/claude-native-render-receipt.d.ts +14 -0
- package/dist/src/utils/claude-native-render-receipt.js +26 -0
- package/dist/src/utils/claude-native-render-receipt.js.map +1 -0
- package/dist/src/utils/claude-skills-root.js +14 -3
- package/dist/src/utils/claude-skills-root.js.map +1 -1
- package/dist/src/utils/codex-manager.js +6 -12
- package/dist/src/utils/codex-manager.js.map +1 -1
- package/dist/src/utils/codex-native-observation.js +29 -13
- package/dist/src/utils/codex-native-observation.js.map +1 -1
- package/dist/src/utils/codex-reconciler.d.ts +2 -5
- package/dist/src/utils/codex-reconciler.js +25 -1
- package/dist/src/utils/codex-reconciler.js.map +1 -1
- package/dist/src/utils/codex-surface-analysis.js +5 -3
- package/dist/src/utils/codex-surface-analysis.js.map +1 -1
- package/dist/src/utils/local-marketplace.d.ts +14 -2
- package/dist/src/utils/local-marketplace.js +209 -42
- package/dist/src/utils/local-marketplace.js.map +1 -1
- package/dist/src/utils/managed-command-evidence.js +1 -1
- package/dist/src/utils/managed-command-evidence.js.map +1 -1
- package/dist/src/utils/managed-command-materialization.d.ts +4 -0
- package/dist/src/utils/managed-command-materialization.js +15 -6
- package/dist/src/utils/managed-command-materialization.js.map +1 -1
- package/dist/src/utils/managed-command-store.d.ts +15 -0
- package/dist/src/utils/managed-command-store.js +73 -8
- package/dist/src/utils/managed-command-store.js.map +1 -1
- package/dist/src/utils/native-cli.d.ts +2 -0
- package/dist/src/utils/native-cli.js +22 -0
- package/dist/src/utils/native-cli.js.map +1 -1
- package/dist/src/utils/native-demand.d.ts +10 -0
- package/dist/src/utils/native-demand.js +4 -0
- package/dist/src/utils/native-demand.js.map +1 -0
- package/dist/src/utils/ownership.js +2 -0
- package/dist/src/utils/ownership.js.map +1 -1
- package/dist/src/utils/paths.js +1 -1
- package/dist/src/utils/paths.js.map +1 -1
- package/dist/src/utils/platform-support.d.ts +1 -1
- package/dist/src/utils/platform-support.js +1 -1
- package/dist/src/utils/platform-support.js.map +1 -1
- package/dist/src/utils/plugin-config-impact.d.ts +3 -0
- package/dist/src/utils/plugin-config-impact.js +115 -273
- package/dist/src/utils/plugin-config-impact.js.map +1 -1
- package/dist/src/utils/plugin-config-references.d.ts +9 -2
- package/dist/src/utils/plugin-config-references.js +75 -85
- package/dist/src/utils/plugin-config-references.js.map +1 -1
- package/dist/src/utils/plugin-config-write.d.ts +58 -1
- package/dist/src/utils/plugin-config-write.js +756 -809
- package/dist/src/utils/plugin-config-write.js.map +1 -1
- package/dist/src/utils/plugin-config.d.ts +47 -46
- package/dist/src/utils/plugin-config.js +292 -833
- package/dist/src/utils/plugin-config.js.map +1 -1
- package/dist/src/utils/plugin-scripts.d.ts +11 -6
- package/dist/src/utils/plugin-scripts.js +52 -35
- package/dist/src/utils/plugin-scripts.js.map +1 -1
- package/dist/src/utils/runtime-config.js +5 -4
- package/dist/src/utils/runtime-config.js.map +1 -1
- package/dist/src/utils/runtime-skill-closure.d.ts +2 -2
- package/dist/src/utils/runtime-skill-closure.js.map +1 -1
- package/dist/src/utils/state-paths.d.ts +8 -3
- package/dist/src/utils/state-paths.js +53 -16
- package/dist/src/utils/state-paths.js.map +1 -1
- package/dist/src/utils/windows-npm-shim.d.ts +2 -0
- package/dist/src/utils/windows-npm-shim.js +5 -7
- package/dist/src/utils/windows-npm-shim.js.map +1 -1
- package/dist/vitest.config.js +1 -0
- package/dist/vitest.config.js.map +1 -1
- package/package.json +3 -3
- package/dist/src/commands/sync-command.d.ts +0 -40
- package/dist/src/commands/sync-command.js +0 -254
- package/dist/src/commands/sync-command.js.map +0 -1
- package/dist/src/portable/skills-cli.d.ts +0 -51
- package/dist/src/portable/skills-cli.js +0 -202
- package/dist/src/portable/skills-cli.js.map +0 -1
- package/dist/src/tui/project-inventory.d.ts +0 -68
- package/dist/src/tui/project-inventory.js +0 -203
- package/dist/src/tui/project-inventory.js.map +0 -1
- package/dist/src/utils/plugin-intent-state.d.ts +0 -49
- package/dist/src/utils/plugin-intent-state.js +0 -320
- package/dist/src/utils/plugin-intent-state.js.map +0 -1
|
@@ -6,7 +6,7 @@ import { createRequire } from 'node:module';
|
|
|
6
6
|
import * as os from 'node:os';
|
|
7
7
|
import * as path from 'node:path';
|
|
8
8
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
9
|
-
import { assertPluginConfigReferenceSchemas, AW_RUNTIME_CONFIG_READER_PATH, createNativeToolReaderSource, createRuntimeConfigSnapshot, getPluginAuthoringAcceptedValues as getCorePluginAuthoringAcceptedValues, getSkillFrontmatterCapabilityRegistry, getManagedCommandArtifactTargets, normalizePluginConfigDefinition, parseManagedCommandPlaceholders, replaceManagedCommandPlaceholders, validateCommandEntryFiles, validatePluginConfigCandidate, formatPluginConfigIssue, } from '@lesliechan721/aw-plugin-core/manifest';
|
|
9
|
+
import { assertPluginConfigReferenceSchemas, AW_RUNTIME_CONFIG_READER_PATH, createNativeToolReaderSource, createRuntimeConfigSnapshot, getPluginAuthoringAcceptedValues as getCorePluginAuthoringAcceptedValues, getSkillFrontmatterCapabilityRegistry, getManagedCommandArtifactTargets, normalizePluginConfigDefinition, compilePluginConfigDefinition, resolveSupportedPlatforms, PLATFORM_TARGETS, isPortablePlatformTarget, SOURCE_PLUGIN_MANIFEST_CONTRACT_VERSION, parseManagedCommandPlaceholders, replaceManagedCommandPlaceholders, validateCommandEntryFiles, validatePluginConfigCandidate, formatPluginConfigIssue, } from '@lesliechan721/aw-plugin-core/manifest';
|
|
10
10
|
import { readCatalogWorkspace } from '@lesliechan721/aw-plugin-core';
|
|
11
11
|
import { checkPluginVersions } from './lib/plugin-version-check.mjs';
|
|
12
12
|
import { scanJavaScriptImportSpecifiers } from './lib/javascript-import-scanner.mjs';
|
|
@@ -19,7 +19,6 @@ const CLI_PACKAGE_ROOT = path.basename(authoringRuntimeRoot) === 'dist'
|
|
|
19
19
|
: authoringRuntimeRoot;
|
|
20
20
|
const errors = [];
|
|
21
21
|
const warnings = [];
|
|
22
|
-
const SOURCE_PLUGIN_MANIFEST_CONTRACT_VERSION = 18;
|
|
23
22
|
let capabilityDiagnostic = null;
|
|
24
23
|
const MAX_SKILL_NAME_LEN = 64;
|
|
25
24
|
const MAX_SKILL_DESCRIPTION_LEN = 1024;
|
|
@@ -52,7 +51,7 @@ const CODEX_POLICY_PRODUCTS = new Set([
|
|
|
52
51
|
'codex',
|
|
53
52
|
'CODEX',
|
|
54
53
|
]);
|
|
55
|
-
const
|
|
54
|
+
const MANIFEST_PLATFORMS = new Set(getPluginAuthoringAcceptedValues('manifest', 'platforms'));
|
|
56
55
|
const MARKETPLACE_AUTHENTICATION_POLICIES = new Set(getPluginAuthoringAcceptedValues('manifest', 'marketplace.policy.authentication'));
|
|
57
56
|
const MARKETPLACE_INSTALLATION_POLICIES = new Set(getPluginAuthoringAcceptedValues('manifest', 'marketplace.policy.installation'));
|
|
58
57
|
const PUBLIC_HOOK_EVENTS = new Set(['before_tool', 'after_tool', 'session_start']);
|
|
@@ -128,23 +127,6 @@ const DEFAULT_SLASH_COMMANDS_DIR = 'slash-commands';
|
|
|
128
127
|
const SCRIPT_NODE_EXTENSIONS = new Set(['.js', '.mjs', '.cjs']);
|
|
129
128
|
const SCRIPT_TIMEOUT_MIN_MS = 1000;
|
|
130
129
|
const SCRIPT_TIMEOUT_MAX_MS = 1800000;
|
|
131
|
-
const ARTIFACT_TARGETS = new Set(getPluginAuthoringAcceptedValues('artifacts', 'artifacts.targets[].target'));
|
|
132
|
-
const ARTIFACT_STATES = new Set(getPluginAuthoringAcceptedValues('artifacts', 'artifacts.targets[].states'));
|
|
133
|
-
const ARTIFACT_SCOPES = new Set(['user', 'project']);
|
|
134
|
-
const ARTIFACT_KINDS = new Set(['instruction', 'codexRole', 'skill']);
|
|
135
|
-
const ARTIFACT_PROJECT_MANAGED_KINDS = new Set(['instruction', 'agent', 'skill']);
|
|
136
|
-
const ARTIFACT_KIND_BY_TARGET = {
|
|
137
|
-
'codex.developerInstructionsBlock': 'instruction',
|
|
138
|
-
'codex.agentRole': 'codexRole',
|
|
139
|
-
'codex.skill': 'skill',
|
|
140
|
-
'claude.skill': 'skill',
|
|
141
|
-
'agent-skills.skill': 'skill',
|
|
142
|
-
};
|
|
143
|
-
const ARTIFACT_PROJECT_MANAGED_KIND_BY_TARGET = {
|
|
144
|
-
'codex.developerInstructionsBlock': 'instruction',
|
|
145
|
-
'codex.agentRole': 'agent',
|
|
146
|
-
'codex.skill': 'skill',
|
|
147
|
-
};
|
|
148
130
|
const PLUGIN_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
149
131
|
let yamlParser = null;
|
|
150
132
|
let pluginVersionCheckResult = null;
|
|
@@ -493,167 +475,11 @@ function validateStrictSemVerString(value, fieldName) {
|
|
|
493
475
|
}
|
|
494
476
|
return value;
|
|
495
477
|
}
|
|
496
|
-
function validateManifestLightweight(manifest) {
|
|
497
|
-
const input = expectRecord(manifest, 'plugin manifest');
|
|
498
|
-
if (!input)
|
|
499
|
-
return;
|
|
500
|
-
if (Object.prototype.hasOwnProperty.call(input, 'commands')) {
|
|
501
|
-
error('top-level "commands" has been removed; use "slashCommands" instead');
|
|
502
|
-
}
|
|
503
|
-
validateAllowedKeys(input, 'plugin manifest', [
|
|
504
|
-
'schemaVersion',
|
|
505
|
-
'name',
|
|
506
|
-
'version',
|
|
507
|
-
'description',
|
|
508
|
-
'dependencies',
|
|
509
|
-
'requires',
|
|
510
|
-
'skills',
|
|
511
|
-
'slashCommands',
|
|
512
|
-
'mcpServers',
|
|
513
|
-
'apps',
|
|
514
|
-
'distributions',
|
|
515
|
-
'marketplace',
|
|
516
|
-
'interface',
|
|
517
|
-
'extensions',
|
|
518
|
-
'buildConfig',
|
|
519
|
-
'scripts',
|
|
520
|
-
'config',
|
|
521
|
-
'artifacts',
|
|
522
|
-
'managedCommands',
|
|
523
|
-
]);
|
|
524
|
-
if (manifest.dependencies !== undefined) {
|
|
525
|
-
if (!Array.isArray(manifest.dependencies)) {
|
|
526
|
-
error('dependencies must be an array');
|
|
527
|
-
}
|
|
528
|
-
else if (manifest.dependencies.length > 64) {
|
|
529
|
-
error('dependencies must contain at most 64 direct plugin dependencies');
|
|
530
|
-
}
|
|
531
|
-
else {
|
|
532
|
-
const seen = new Set();
|
|
533
|
-
for (const [index, dependency] of manifest.dependencies.entries()) {
|
|
534
|
-
if (typeof dependency !== 'string' || !PLUGIN_NAME_PATTERN.test(dependency)) {
|
|
535
|
-
error(`dependencies[${index}] must be an ASCII lowercase hyphen-case plugin name`);
|
|
536
|
-
continue;
|
|
537
|
-
}
|
|
538
|
-
if (dependency === manifest.name) {
|
|
539
|
-
error(`plugin "${manifest.name}" cannot depend on itself`);
|
|
540
|
-
}
|
|
541
|
-
if (seen.has(dependency)) {
|
|
542
|
-
error(`dependencies contains duplicate plugin "${dependency}"`);
|
|
543
|
-
}
|
|
544
|
-
seen.add(dependency);
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
for (const field of ['name', 'version', 'description', 'marketplace']) {
|
|
549
|
-
if (!manifest[field]) {
|
|
550
|
-
error(`Missing required field: ${field}`);
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
if (manifest.name && !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(manifest.name)) {
|
|
554
|
-
error(`manifest name "${manifest.name}" is not lowercase-hyphen-case`);
|
|
555
|
-
}
|
|
556
|
-
if (manifest.version) {
|
|
557
|
-
const pluginVersion = parseStrictSemVer(manifest.version);
|
|
558
|
-
if (!pluginVersion) {
|
|
559
|
-
error(`manifest.version must be a strict SemVer 2.0.0 string, got "${manifest.version}"`);
|
|
560
|
-
}
|
|
561
|
-
else if (pluginVersion.prerelease.length > 0 || pluginVersion.build.length > 0) {
|
|
562
|
-
error('manifest.version must be a stable SemVer without prerelease or build metadata');
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
if (manifest.marketplace) {
|
|
566
|
-
const mp = manifest.marketplace;
|
|
567
|
-
if (!mp.category)
|
|
568
|
-
error('marketplace.category is required');
|
|
569
|
-
if (typeof mp.strict !== 'boolean')
|
|
570
|
-
error('marketplace.strict must be a boolean');
|
|
571
|
-
if (!mp.policy || !mp.policy.installation)
|
|
572
|
-
error('marketplace.policy.installation is required');
|
|
573
|
-
else if (!MARKETPLACE_INSTALLATION_POLICIES.has(mp.policy.installation))
|
|
574
|
-
error(`marketplace.policy.installation must be one of ${[...MARKETPLACE_INSTALLATION_POLICIES].map((value) => JSON.stringify(value)).join(', ')}`);
|
|
575
|
-
if (!mp.policy || !mp.policy.authentication)
|
|
576
|
-
error('marketplace.policy.authentication is required');
|
|
577
|
-
else if (!MARKETPLACE_AUTHENTICATION_POLICIES.has(mp.policy.authentication))
|
|
578
|
-
error('marketplace.policy.authentication must be "ON_INSTALL" or "ON_USE"');
|
|
579
|
-
validateManifestPolicyProducts(mp.policy?.products);
|
|
580
|
-
}
|
|
581
|
-
for (const field of ['skills', 'slashCommands', 'mcpServers', 'apps']) {
|
|
582
|
-
if (manifest[field] && !manifest[field].startsWith('./')) {
|
|
583
|
-
error(`${field} path must start with "./", got "${manifest[field]}"`);
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
const claudeCommands = manifest.buildConfig?.manifestOverrides?.claude?.commands;
|
|
587
|
-
if (claudeCommands !== undefined) {
|
|
588
|
-
error('buildConfig.manifestOverrides.claude.commands has been removed; use "slashCommands" instead');
|
|
589
|
-
}
|
|
590
|
-
for (const platform of ['claude', 'codex']) {
|
|
591
|
-
const rules = manifest.buildConfig?.fileRules?.[platform];
|
|
592
|
-
if (!rules)
|
|
593
|
-
continue;
|
|
594
|
-
for (const pattern of [...(rules.include ?? []), ...(rules.exclude ?? [])]) {
|
|
595
|
-
const normalized = String(pattern).replace(/\\/g, '/').replace(/^\.\//, '');
|
|
596
|
-
if (normalized === 'commands' || normalized.startsWith('commands/')) {
|
|
597
|
-
error(`buildConfig.fileRules.${platform} no longer accepts legacy "commands/**" source rules; use "slashCommands" instead`);
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
validateExtensionsLightweight(manifest.extensions);
|
|
602
|
-
validatePlatformFieldSupport(manifest);
|
|
603
|
-
}
|
|
604
|
-
function validatePortableNativeArtifactCapabilityLightweight(manifest) {
|
|
605
|
-
if (manifest.distributions?.agentSkills === undefined)
|
|
606
|
-
return;
|
|
607
|
-
const hasOtherNativeDeclaration = Boolean(manifest.skills
|
|
608
|
-
|| manifest.slashCommands
|
|
609
|
-
|| manifest.mcpServers
|
|
610
|
-
|| manifest.apps
|
|
611
|
-
|| (manifest.extensions?.instructions?.length ?? 0) > 0
|
|
612
|
-
|| (manifest.extensions?.permissions?.length ?? 0) > 0
|
|
613
|
-
|| (manifest.extensions?.hooks?.length ?? 0) > 0
|
|
614
|
-
|| (manifest.extensions?.nativeHooks?.claude?.length ?? 0) > 0
|
|
615
|
-
|| (manifest.extensions?.nativeHooks?.codex?.length ?? 0) > 0
|
|
616
|
-
|| (manifest.extensions?.agents?.length ?? 0) > 0);
|
|
617
|
-
const hasPresentNativeArtifact = (manifest.artifacts?.targets ?? []).some((target) => (target?.platform === 'claude' || target?.platform === 'codex')
|
|
618
|
-
&& Array.isArray(target.states)
|
|
619
|
-
&& target.states.includes('present'));
|
|
620
|
-
if (!hasOtherNativeDeclaration && !hasPresentNativeArtifact) {
|
|
621
|
-
const message = 'Invalid plugin manifest: portable-only plugins are not supported. Declare at least one non-empty native capability.';
|
|
622
|
-
if (!errors.includes(message))
|
|
623
|
-
error(message);
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
function normalizeManifestProductToken(value) {
|
|
627
|
-
return String(value).trim().toUpperCase().replace(/[\s-]+/g, '_');
|
|
628
|
-
}
|
|
629
|
-
function resolveSupportedPlatforms(manifest) {
|
|
630
|
-
const products = manifest.marketplace?.policy?.products;
|
|
631
|
-
if (!Array.isArray(products) || products.length === 0) {
|
|
632
|
-
return new Set(['claude', 'codex']);
|
|
633
|
-
}
|
|
634
|
-
const supported = new Set();
|
|
635
|
-
for (const product of products) {
|
|
636
|
-
const normalized = normalizeManifestProductToken(product);
|
|
637
|
-
if (normalized === 'CLAUDE')
|
|
638
|
-
supported.add('claude');
|
|
639
|
-
if (normalized === 'CODEX')
|
|
640
|
-
supported.add('codex');
|
|
641
|
-
}
|
|
642
|
-
return supported;
|
|
643
|
-
}
|
|
644
478
|
function supportsManifestPlatform(manifest, platform) {
|
|
645
479
|
return resolveSupportedPlatforms(manifest).has(platform);
|
|
646
480
|
}
|
|
647
|
-
function
|
|
648
|
-
|
|
649
|
-
if (!Array.isArray(products) || products.length === 0) {
|
|
650
|
-
return 'marketplace.policy.products=[]';
|
|
651
|
-
}
|
|
652
|
-
const normalized = [...new Set(products.map(normalizeManifestProductToken))];
|
|
653
|
-
return `marketplace.policy.products=[${normalized.join(', ')}]`;
|
|
654
|
-
}
|
|
655
|
-
function platformProductName(platform) {
|
|
656
|
-
return platform === 'claude' ? 'CLAUDE' : 'CODEX';
|
|
481
|
+
function formatManifestPlatformsForError(manifest) {
|
|
482
|
+
return `platforms=[${[...resolveSupportedPlatforms(manifest)].join(', ')}]`;
|
|
657
483
|
}
|
|
658
484
|
function pluginNameForError(manifest) {
|
|
659
485
|
return typeof manifest.name === 'string' && manifest.name.trim()
|
|
@@ -663,30 +489,11 @@ function pluginNameForError(manifest) {
|
|
|
663
489
|
function assertPlatformFieldSupported(manifest, fieldPath, requiredPlatform) {
|
|
664
490
|
if (supportsManifestPlatform(manifest, requiredPlatform))
|
|
665
491
|
return;
|
|
666
|
-
error(`Invalid plugin "${pluginNameForError(manifest)}": ${fieldPath} requires ${
|
|
492
|
+
error(`Invalid plugin "${pluginNameForError(manifest)}": ${fieldPath} requires ${requiredPlatform} support, but ${formatManifestPlatformsForError(manifest)}.`);
|
|
667
493
|
}
|
|
668
494
|
function hasNonEmptyOverride(value) {
|
|
669
495
|
return isRecord(value) && Object.keys(value).length > 0;
|
|
670
496
|
}
|
|
671
|
-
function validateManifestPolicyProducts(products) {
|
|
672
|
-
if (products === undefined)
|
|
673
|
-
return;
|
|
674
|
-
if (!Array.isArray(products)) {
|
|
675
|
-
error('marketplace.policy.products must be an array');
|
|
676
|
-
return;
|
|
677
|
-
}
|
|
678
|
-
for (const [index, product] of products.entries()) {
|
|
679
|
-
const fieldName = `marketplace.policy.products[${index}]`;
|
|
680
|
-
if (typeof product !== 'string' || product.trim() === '') {
|
|
681
|
-
error(`${fieldName} must be a non-empty string`);
|
|
682
|
-
continue;
|
|
683
|
-
}
|
|
684
|
-
const normalized = normalizeManifestProductToken(product);
|
|
685
|
-
if (!MANIFEST_POLICY_PRODUCTS.has(normalized)) {
|
|
686
|
-
error(`${fieldName} must be one of "CODEX" or "CLAUDE"`);
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
497
|
function validatePlatformFieldSupport(manifest) {
|
|
691
498
|
if (manifest.buildConfig?.fileRules?.claude !== undefined) {
|
|
692
499
|
assertPlatformFieldSupported(manifest, 'buildConfig.fileRules.claude', 'claude');
|
|
@@ -1278,7 +1085,7 @@ function targetedPlatforms(manifest) {
|
|
|
1278
1085
|
platforms.push('claude');
|
|
1279
1086
|
if (isCodexTargeted(manifest))
|
|
1280
1087
|
platforms.push('codex');
|
|
1281
|
-
return platforms
|
|
1088
|
+
return platforms;
|
|
1282
1089
|
}
|
|
1283
1090
|
// ---------------------------------------------------------------------------
|
|
1284
1091
|
// Supplemental checks (always run — not covered by CLI validator)
|
|
@@ -1326,7 +1133,7 @@ function validateCanonicalSkillLayout(pluginDir, manifest) {
|
|
|
1326
1133
|
: [])
|
|
1327
1134
|
.filter((target) => target &&
|
|
1328
1135
|
typeof target === 'object' &&
|
|
1329
|
-
(target.target === 'codex.skill' || target.target === 'claude.skill') &&
|
|
1136
|
+
(target.target === 'codex.skill' || target.target === 'claude.skill' || target.target === 'agent-skills.skill') &&
|
|
1330
1137
|
typeof target.skillKey === 'string' &&
|
|
1331
1138
|
Array.isArray(target.sourceDirs) &&
|
|
1332
1139
|
target.sourceDirs.length > 0)
|
|
@@ -1347,18 +1154,6 @@ function validateCanonicalSkillLayout(pluginDir, manifest) {
|
|
|
1347
1154
|
error(`skills/${skill}/README.md must not be empty`);
|
|
1348
1155
|
}
|
|
1349
1156
|
}
|
|
1350
|
-
const portableRoot = manifest.distributions?.agentSkills?.skills;
|
|
1351
|
-
for (const skill of declared.portable) {
|
|
1352
|
-
const skillRoot = path.join(pluginDir, portableRoot, skill);
|
|
1353
|
-
const skillReadme = path.join(skillRoot, 'README.md');
|
|
1354
|
-
if (!fs.statSync(skillReadme, { throwIfNoEntry: false })?.isFile()) {
|
|
1355
|
-
error(`${normalizeRelativePath(path.join(portableRoot, skill, 'README.md'))} is required`);
|
|
1356
|
-
continue;
|
|
1357
|
-
}
|
|
1358
|
-
if (fs.readFileSync(skillReadme, 'utf8').trim() === '') {
|
|
1359
|
-
error(`${normalizeRelativePath(path.join(portableRoot, skill, 'README.md'))} must not be empty`);
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
1157
|
}
|
|
1363
1158
|
function validateDeclaredNativeAssets(pluginDir, manifest) {
|
|
1364
1159
|
const defaults = [
|
|
@@ -1418,21 +1213,9 @@ function collectDeclaredSkillNames(pluginDir, manifest) {
|
|
|
1418
1213
|
.map((target) => target.skillKey.trim())
|
|
1419
1214
|
.sort();
|
|
1420
1215
|
const dynamicSkillNameSet = new Set(dynamicSkillNames);
|
|
1421
|
-
const portableRoot = typeof manifest.distributions?.agentSkills?.skills === 'string'
|
|
1422
|
-
? path.join(pluginDir, manifest.distributions.agentSkills.skills)
|
|
1423
|
-
: null;
|
|
1424
|
-
const portableRootStats = portableRoot
|
|
1425
|
-
? fs.lstatSync(portableRoot, { throwIfNoEntry: false })
|
|
1426
|
-
: null;
|
|
1427
|
-
const portableSkillNameSet = new Set(portableRootStats?.isDirectory() && !portableRootStats.isSymbolicLink()
|
|
1428
|
-
? fs.readdirSync(portableRoot, { withFileTypes: true })
|
|
1429
|
-
.filter((entry) => entry.isDirectory())
|
|
1430
|
-
.map((entry) => entry.name)
|
|
1431
|
-
: []);
|
|
1432
1216
|
return {
|
|
1433
1217
|
static: staticSkillNameSet,
|
|
1434
1218
|
dynamic: dynamicSkillNameSet,
|
|
1435
|
-
portable: portableSkillNameSet,
|
|
1436
1219
|
all: new Set([...staticSkillNames, ...dynamicSkillNames]),
|
|
1437
1220
|
};
|
|
1438
1221
|
}
|
|
@@ -1713,12 +1496,8 @@ function validateConfigSchemaLightweight(config, manifest) {
|
|
|
1713
1496
|
error(validationError instanceof Error ? validationError.message : String(validationError));
|
|
1714
1497
|
}
|
|
1715
1498
|
}
|
|
1716
|
-
function
|
|
1717
|
-
const schema = manifest.config
|
|
1718
|
-
return isRecord(schema) ? new Set(Object.keys(schema)) : new Set();
|
|
1719
|
-
}
|
|
1720
|
-
function defaultConfigValues(manifest) {
|
|
1721
|
-
const schema = manifest.config?.fields;
|
|
1499
|
+
function defaultConfigValues(manifest, platform) {
|
|
1500
|
+
const schema = compilePluginConfigDefinition(manifest.config ?? { fields: {} }, platform).fields;
|
|
1722
1501
|
const values = {};
|
|
1723
1502
|
if (!isRecord(schema))
|
|
1724
1503
|
return values;
|
|
@@ -1749,23 +1528,6 @@ function configFieldContainsSensitiveValue(field) {
|
|
|
1749
1528
|
|| (isRecord(field.additionalProperties)
|
|
1750
1529
|
&& field.additionalProperties.sensitive === true));
|
|
1751
1530
|
}
|
|
1752
|
-
function codexStaticNativeComponentKeys(manifest) {
|
|
1753
|
-
if (!isCodexTargeted(manifest))
|
|
1754
|
-
return [];
|
|
1755
|
-
const keys = [];
|
|
1756
|
-
if (manifest.skills)
|
|
1757
|
-
keys.push('skills');
|
|
1758
|
-
if (manifest.mcpServers)
|
|
1759
|
-
keys.push('mcpServers');
|
|
1760
|
-
if ((Array.isArray(manifest.extensions?.hooks)
|
|
1761
|
-
&& manifest.extensions.hooks.some((hook) => hook?.agentOverrides?.codex !== null))
|
|
1762
|
-
|| (Array.isArray(manifest.extensions?.nativeHooks?.codex)
|
|
1763
|
-
&& manifest.extensions.nativeHooks.codex.length > 0))
|
|
1764
|
-
keys.push('hooks');
|
|
1765
|
-
if (manifest.apps)
|
|
1766
|
-
keys.push('apps');
|
|
1767
|
-
return keys;
|
|
1768
|
-
}
|
|
1769
1531
|
function validateArtifactId(value, fieldName) {
|
|
1770
1532
|
const id = validateManifestString(value, fieldName);
|
|
1771
1533
|
if (!id)
|
|
@@ -1775,33 +1537,6 @@ function validateArtifactId(value, fieldName) {
|
|
|
1775
1537
|
}
|
|
1776
1538
|
return id;
|
|
1777
1539
|
}
|
|
1778
|
-
function validateCodexRoleKey(value, fieldName) {
|
|
1779
|
-
const roleKey = validateManifestString(value, fieldName);
|
|
1780
|
-
if (!roleKey)
|
|
1781
|
-
return null;
|
|
1782
|
-
if (!/^[A-Za-z][A-Za-z0-9_-]*$/.test(roleKey)) {
|
|
1783
|
-
error(`${fieldName}: expected a valid Codex role key`);
|
|
1784
|
-
}
|
|
1785
|
-
return roleKey;
|
|
1786
|
-
}
|
|
1787
|
-
function validateCodexSkillKey(value, fieldName) {
|
|
1788
|
-
const skillKey = validateManifestString(value, fieldName);
|
|
1789
|
-
if (!skillKey)
|
|
1790
|
-
return null;
|
|
1791
|
-
if (!/^[A-Za-z][A-Za-z0-9_-]*$/.test(skillKey)) {
|
|
1792
|
-
error(`${fieldName}: expected a valid Codex skill key`);
|
|
1793
|
-
}
|
|
1794
|
-
return skillKey;
|
|
1795
|
-
}
|
|
1796
|
-
function validatePortableSkillKey(value, fieldName) {
|
|
1797
|
-
const skillKey = validateManifestString(value, fieldName);
|
|
1798
|
-
if (!skillKey)
|
|
1799
|
-
return null;
|
|
1800
|
-
if (skillKey.length > MAX_SKILL_NAME_LEN || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(skillKey)) {
|
|
1801
|
-
error(`${fieldName}: expected at most 64 ASCII lowercase hyphen-case characters`);
|
|
1802
|
-
}
|
|
1803
|
-
return skillKey;
|
|
1804
|
-
}
|
|
1805
1540
|
function validateStringArray(value, fieldName, options = {}) {
|
|
1806
1541
|
if (!Array.isArray(value)) {
|
|
1807
1542
|
error(`${fieldName} must be an array`);
|
|
@@ -1826,323 +1561,8 @@ function validateStringArray(value, fieldName, options = {}) {
|
|
|
1826
1561
|
}
|
|
1827
1562
|
return output;
|
|
1828
1563
|
}
|
|
1829
|
-
function
|
|
1830
|
-
|
|
1831
|
-
const target = expectRecord(entry, fieldName);
|
|
1832
|
-
if (!target)
|
|
1833
|
-
return null;
|
|
1834
|
-
validateAllowedKeys(target, fieldName, [
|
|
1835
|
-
'id',
|
|
1836
|
-
'platform',
|
|
1837
|
-
'distribution',
|
|
1838
|
-
'scopes',
|
|
1839
|
-
'target',
|
|
1840
|
-
'kind',
|
|
1841
|
-
'projectManagedKind',
|
|
1842
|
-
'states',
|
|
1843
|
-
'refreshKeys',
|
|
1844
|
-
'delivery',
|
|
1845
|
-
'requiresCodexProjectConfig',
|
|
1846
|
-
'roleKey',
|
|
1847
|
-
'skillKey',
|
|
1848
|
-
'sourceDirs',
|
|
1849
|
-
'runtimeImports',
|
|
1850
|
-
'runtimeConfig',
|
|
1851
|
-
]);
|
|
1852
|
-
const id = validateArtifactId(target.id, `${fieldName}.id`);
|
|
1853
|
-
const artifactTarget = validateManifestString(target.target, `${fieldName}.target`);
|
|
1854
|
-
if (artifactTarget && !ARTIFACT_TARGETS.has(artifactTarget)) {
|
|
1855
|
-
error(`${fieldName}.target: unsupported artifact target "${artifactTarget}"`);
|
|
1856
|
-
}
|
|
1857
|
-
const portable = artifactTarget === 'agent-skills.skill';
|
|
1858
|
-
let delivery;
|
|
1859
|
-
if (artifactTarget === 'codex.skill') {
|
|
1860
|
-
delivery = expectRecord(target.delivery, `${fieldName}.delivery`);
|
|
1861
|
-
if (delivery) {
|
|
1862
|
-
if (delivery.mode === 'aw-extension') {
|
|
1863
|
-
validateAllowedKeys(delivery, `${fieldName}.delivery`, ['mode']);
|
|
1864
|
-
}
|
|
1865
|
-
else if (delivery.mode === 'codex-native') {
|
|
1866
|
-
validateAllowedKeys(delivery, `${fieldName}.delivery`, ['mode', 'identity', 'renderProfile']);
|
|
1867
|
-
if (delivery.identity !== 'shared') {
|
|
1868
|
-
error(`${fieldName}.delivery.identity: expected "shared"`);
|
|
1869
|
-
}
|
|
1870
|
-
if (delivery.renderProfile !== 'user') {
|
|
1871
|
-
error(`${fieldName}.delivery.renderProfile: expected "user"`);
|
|
1872
|
-
}
|
|
1873
|
-
}
|
|
1874
|
-
else {
|
|
1875
|
-
error(`${fieldName}.delivery.mode: expected "codex-native" or "aw-extension"`);
|
|
1876
|
-
}
|
|
1877
|
-
}
|
|
1878
|
-
}
|
|
1879
|
-
else if (target.delivery !== undefined) {
|
|
1880
|
-
error(`${fieldName}.delivery: delivery is only supported for codex.skill targets`);
|
|
1881
|
-
}
|
|
1882
|
-
const platform = portable || target.platform === undefined
|
|
1883
|
-
? undefined
|
|
1884
|
-
: validateManifestString(target.platform, `${fieldName}.platform`);
|
|
1885
|
-
const distribution = portable || target.distribution !== undefined
|
|
1886
|
-
? validateManifestString(target.distribution, `${fieldName}.distribution`)
|
|
1887
|
-
: undefined;
|
|
1888
|
-
if (portable) {
|
|
1889
|
-
if (distribution !== 'agent-skills') {
|
|
1890
|
-
error(`${fieldName}.distribution: expected "agent-skills"`);
|
|
1891
|
-
}
|
|
1892
|
-
if (target.platform !== undefined) {
|
|
1893
|
-
error(`${fieldName}.platform: distribution targets do not support platform`);
|
|
1894
|
-
}
|
|
1895
|
-
}
|
|
1896
|
-
else {
|
|
1897
|
-
const expectedPlatform = artifactTarget === 'claude.skill' ? 'claude' : 'codex';
|
|
1898
|
-
if (platform && artifactTarget && platform !== expectedPlatform) {
|
|
1899
|
-
error(`${fieldName}.platform: target "${artifactTarget}" must use "${expectedPlatform}"`);
|
|
1900
|
-
}
|
|
1901
|
-
if (target.distribution !== undefined) {
|
|
1902
|
-
error(`${fieldName}.distribution: platform targets do not support distribution`);
|
|
1903
|
-
}
|
|
1904
|
-
}
|
|
1905
|
-
const expectedKind = ARTIFACT_KIND_BY_TARGET[artifactTarget];
|
|
1906
|
-
const kind = target.kind === undefined
|
|
1907
|
-
? expectedKind
|
|
1908
|
-
: validateManifestString(target.kind, `${fieldName}.kind`);
|
|
1909
|
-
if (kind && !ARTIFACT_KINDS.has(kind)) {
|
|
1910
|
-
error(`${fieldName}.kind: unsupported artifact kind "${kind}"`);
|
|
1911
|
-
}
|
|
1912
|
-
if (expectedKind && kind && kind !== expectedKind) {
|
|
1913
|
-
error(`${fieldName}.kind: target "${artifactTarget}" requires kind "${expectedKind}"`);
|
|
1914
|
-
}
|
|
1915
|
-
const expectedProjectManagedKind = ARTIFACT_PROJECT_MANAGED_KIND_BY_TARGET[artifactTarget];
|
|
1916
|
-
const projectManagedKind = target.projectManagedKind === undefined
|
|
1917
|
-
? expectedProjectManagedKind
|
|
1918
|
-
: validateManifestString(target.projectManagedKind, `${fieldName}.projectManagedKind`);
|
|
1919
|
-
if (projectManagedKind && !ARTIFACT_PROJECT_MANAGED_KINDS.has(projectManagedKind)) {
|
|
1920
|
-
error(`${fieldName}.projectManagedKind: unsupported Codex project managed kind "${projectManagedKind}"`);
|
|
1921
|
-
}
|
|
1922
|
-
if (expectedProjectManagedKind &&
|
|
1923
|
-
projectManagedKind &&
|
|
1924
|
-
projectManagedKind !== expectedProjectManagedKind) {
|
|
1925
|
-
error(`${fieldName}.projectManagedKind: target "${artifactTarget}" must map to "${expectedProjectManagedKind}"`);
|
|
1926
|
-
}
|
|
1927
|
-
if (!expectedProjectManagedKind && projectManagedKind) {
|
|
1928
|
-
error(`${fieldName}.projectManagedKind: target "${artifactTarget}" does not support projectManagedKind`);
|
|
1929
|
-
}
|
|
1930
|
-
const scopes = validateStringArray(target.scopes, `${fieldName}.scopes`, {
|
|
1931
|
-
allowed: ARTIFACT_SCOPES,
|
|
1932
|
-
label: 'artifact scope',
|
|
1933
|
-
requireNonEmpty: true,
|
|
1934
|
-
});
|
|
1935
|
-
const states = validateStringArray(target.states, `${fieldName}.states`, {
|
|
1936
|
-
allowed: ARTIFACT_STATES,
|
|
1937
|
-
label: 'artifact state',
|
|
1938
|
-
requireNonEmpty: true,
|
|
1939
|
-
});
|
|
1940
|
-
const refreshKeys = validateStringArray(target.refreshKeys, `${fieldName}.refreshKeys`);
|
|
1941
|
-
const schemaKeys = configSchemaKeys(manifest);
|
|
1942
|
-
for (const [refreshIndex, refreshKey] of refreshKeys.entries()) {
|
|
1943
|
-
if (!schemaKeys.has(refreshKey)) {
|
|
1944
|
-
error(`${fieldName}.refreshKeys[${refreshIndex}]: unknown config key "${refreshKey}"`);
|
|
1945
|
-
continue;
|
|
1946
|
-
}
|
|
1947
|
-
const sensitiveRefreshKey = configFieldContainsSensitiveValue(manifest.config?.fields?.[refreshKey]);
|
|
1948
|
-
const skillTarget = artifactTarget === 'codex.skill'
|
|
1949
|
-
|| artifactTarget === 'claude.skill'
|
|
1950
|
-
|| artifactTarget === 'agent-skills.skill';
|
|
1951
|
-
if (skillTarget && sensitiveRefreshKey) {
|
|
1952
|
-
const native = delivery?.mode === 'codex-native';
|
|
1953
|
-
error(`${native ? 'codexNativeRenderSensitiveRefreshKey' : 'skillRenderSensitiveRefreshKey'}: ` +
|
|
1954
|
-
`${fieldName}.refreshKeys[${refreshIndex}]: ` +
|
|
1955
|
-
`${native ? 'codex-native renderers' : 'Skill renderers'} cannot read sensitive config field "${refreshKey}"`);
|
|
1956
|
-
}
|
|
1957
|
-
}
|
|
1958
|
-
if (target.requiresCodexProjectConfig !== undefined &&
|
|
1959
|
-
typeof target.requiresCodexProjectConfig !== 'boolean') {
|
|
1960
|
-
error(`${fieldName}.requiresCodexProjectConfig must be a boolean`);
|
|
1961
|
-
}
|
|
1962
|
-
if (artifactTarget === 'codex.skill' && target.requiresCodexProjectConfig === true) {
|
|
1963
|
-
error(`${fieldName}.requiresCodexProjectConfig: codex.skill writes the skill runtime and must not require Codex project config preflight`);
|
|
1964
|
-
}
|
|
1965
|
-
if ((platform === 'claude' || portable) && target.requiresCodexProjectConfig !== undefined) {
|
|
1966
|
-
error(`${fieldName}.requiresCodexProjectConfig: this target does not support the field`);
|
|
1967
|
-
}
|
|
1968
|
-
let roleKey;
|
|
1969
|
-
let skillKey;
|
|
1970
|
-
if (artifactTarget === 'codex.agentRole') {
|
|
1971
|
-
roleKey = validateCodexRoleKey(target.roleKey, `${fieldName}.roleKey`);
|
|
1972
|
-
if (!roleKey) {
|
|
1973
|
-
error(`${fieldName}.roleKey: codex.agentRole targets must declare a static roleKey`);
|
|
1974
|
-
}
|
|
1975
|
-
}
|
|
1976
|
-
else if (target.roleKey !== undefined) {
|
|
1977
|
-
error(`${fieldName}.roleKey: roleKey is only supported for codex.agentRole targets`);
|
|
1978
|
-
}
|
|
1979
|
-
if (artifactTarget === 'codex.skill' || artifactTarget === 'claude.skill' || portable) {
|
|
1980
|
-
skillKey = portable
|
|
1981
|
-
? validatePortableSkillKey(target.skillKey, `${fieldName}.skillKey`)
|
|
1982
|
-
: validateCodexSkillKey(target.skillKey, `${fieldName}.skillKey`);
|
|
1983
|
-
if (!skillKey) {
|
|
1984
|
-
error(`${fieldName}.skillKey: ${artifactTarget} targets must declare a static skillKey`);
|
|
1985
|
-
}
|
|
1986
|
-
}
|
|
1987
|
-
else if (target.skillKey !== undefined) {
|
|
1988
|
-
error(`${fieldName}.skillKey: skillKey is only supported for skill targets`);
|
|
1989
|
-
}
|
|
1990
|
-
const normalizedSourceDirs = Array.isArray(target.sourceDirs)
|
|
1991
|
-
? target.sourceDirs
|
|
1992
|
-
.filter((sourceDir) => typeof sourceDir === 'string' && sourceDir.trim() !== '')
|
|
1993
|
-
.map((sourceDir) => path.posix.normalize(sourceDir))
|
|
1994
|
-
: [];
|
|
1995
|
-
if (new Set(normalizedSourceDirs).size !== normalizedSourceDirs.length) {
|
|
1996
|
-
error(`${fieldName}.sourceDirs must not contain duplicate directories`);
|
|
1997
|
-
}
|
|
1998
|
-
const sourceDirs = target.sourceDirs === undefined
|
|
1999
|
-
? []
|
|
2000
|
-
: validateStringArray(target.sourceDirs, `${fieldName}.sourceDirs`);
|
|
2001
|
-
if (sourceDirs.length > 0 && artifactTarget !== 'codex.skill' && artifactTarget !== 'claude.skill' && !portable) {
|
|
2002
|
-
error(`${fieldName}.sourceDirs: sourceDirs are only supported for skill targets`);
|
|
2003
|
-
}
|
|
2004
|
-
for (const [sourceIndex, sourceDir] of sourceDirs.entries()) {
|
|
2005
|
-
const sourceField = `${fieldName}.sourceDirs[${sourceIndex}]`;
|
|
2006
|
-
if (!sourceDir.startsWith('./') || path.posix.isAbsolute(sourceDir)) {
|
|
2007
|
-
error(`${sourceField} must start with "./" and stay inside the plugin root`);
|
|
2008
|
-
continue;
|
|
2009
|
-
}
|
|
2010
|
-
const normalized = path.posix.normalize(sourceDir);
|
|
2011
|
-
if (normalized === '.' || normalized === '..' || normalized.startsWith('../')) {
|
|
2012
|
-
error(`${sourceField} must stay inside the plugin root`);
|
|
2013
|
-
continue;
|
|
2014
|
-
}
|
|
2015
|
-
const stats = fs.lstatSync(path.join(pluginDir, normalized), { throwIfNoEntry: false });
|
|
2016
|
-
if (!stats?.isDirectory() || stats.isSymbolicLink()) {
|
|
2017
|
-
error(`${sourceField} must point to an existing directory`);
|
|
2018
|
-
}
|
|
2019
|
-
if (skillKey && !portable &&
|
|
2020
|
-
normalized !== `skills/${skillKey}` &&
|
|
2021
|
-
!normalized.startsWith(`skills/${skillKey}/`)) {
|
|
2022
|
-
error(`${sourceField} must stay inside "./skills/${skillKey}"`);
|
|
2023
|
-
}
|
|
2024
|
-
if (skillKey && !portable &&
|
|
2025
|
-
isSkillAuthorOnlyPath(path.posix.relative(`skills/${skillKey}`, normalized))) {
|
|
2026
|
-
error(`${sourceField} must not point inside an author-only Skill directory`);
|
|
2027
|
-
}
|
|
2028
|
-
}
|
|
2029
|
-
if (skillKey && !portable &&
|
|
2030
|
-
sourceDirs.length > 0 &&
|
|
2031
|
-
!normalizedSourceDirs.includes(`skills/${skillKey}`)) {
|
|
2032
|
-
error(`${fieldName}.sourceDirs must include "./skills/${skillKey}" so README.md is published`);
|
|
2033
|
-
}
|
|
2034
|
-
return {
|
|
2035
|
-
id,
|
|
2036
|
-
platform,
|
|
2037
|
-
distribution,
|
|
2038
|
-
scopes,
|
|
2039
|
-
target: artifactTarget,
|
|
2040
|
-
kind,
|
|
2041
|
-
projectManagedKind,
|
|
2042
|
-
states,
|
|
2043
|
-
refreshKeys,
|
|
2044
|
-
delivery,
|
|
2045
|
-
roleKey,
|
|
2046
|
-
skillKey,
|
|
2047
|
-
sourceDirs,
|
|
2048
|
-
runtimeConfig: target.runtimeConfig,
|
|
2049
|
-
runtimeImports: Array.isArray(target.runtimeImports) ? target.runtimeImports : [],
|
|
2050
|
-
};
|
|
2051
|
-
}
|
|
2052
|
-
function validateArtifactsConfigLightweight(pluginDir, manifest) {
|
|
2053
|
-
if (manifest.artifacts === undefined)
|
|
2054
|
-
return [];
|
|
2055
|
-
const artifacts = expectRecord(manifest.artifacts, 'artifacts');
|
|
2056
|
-
if (!artifacts)
|
|
2057
|
-
return [];
|
|
2058
|
-
validateAllowedKeys(artifacts, 'artifacts', ['targets']);
|
|
2059
|
-
if (artifacts.targets === undefined)
|
|
2060
|
-
return [];
|
|
2061
|
-
if (!Array.isArray(artifacts.targets)) {
|
|
2062
|
-
error('artifacts.targets must be an array');
|
|
2063
|
-
return [];
|
|
2064
|
-
}
|
|
2065
|
-
const declarations = artifacts.targets
|
|
2066
|
-
.map((entry, index) => validateArtifactTargetEntry(entry, index, manifest, pluginDir))
|
|
2067
|
-
.filter(Boolean);
|
|
2068
|
-
const idsBySurfaceScope = new Map();
|
|
2069
|
-
const nativeIds = new Map();
|
|
2070
|
-
const nativeSkillKeys = new Map();
|
|
2071
|
-
for (const [declarationIndex, declaration] of declarations.entries()) {
|
|
2072
|
-
for (const scope of declaration.scopes) {
|
|
2073
|
-
const surface = declaration.platform ?? declaration.distribution;
|
|
2074
|
-
const key = `${surface}:${scope}:${declaration.id}`;
|
|
2075
|
-
const existing = idsBySurfaceScope.get(key);
|
|
2076
|
-
if (existing !== undefined) {
|
|
2077
|
-
error(`artifacts.targets has duplicate artifact id "${declaration.id}" for surface/scope "${surface}:${scope}" in targets[${existing}] and targets[${declarationIndex}]`);
|
|
2078
|
-
}
|
|
2079
|
-
else {
|
|
2080
|
-
idsBySurfaceScope.set(key, declarationIndex);
|
|
2081
|
-
}
|
|
2082
|
-
}
|
|
2083
|
-
if (declaration.delivery?.mode === 'codex-native') {
|
|
2084
|
-
const existingId = nativeIds.get(declaration.id);
|
|
2085
|
-
if (existingId !== undefined) {
|
|
2086
|
-
error(`artifacts.targets has duplicate codex-native artifact id "${declaration.id}" in the shared projection at targets[${existingId}] and targets[${declarationIndex}]`);
|
|
2087
|
-
}
|
|
2088
|
-
else {
|
|
2089
|
-
nativeIds.set(declaration.id, declarationIndex);
|
|
2090
|
-
}
|
|
2091
|
-
const existingSkillKey = nativeSkillKeys.get(declaration.skillKey);
|
|
2092
|
-
if (existingSkillKey !== undefined) {
|
|
2093
|
-
error(`artifacts.targets has duplicate codex-native skillKey "${declaration.skillKey}" in the shared projection at targets[${existingSkillKey}] and targets[${declarationIndex}]`);
|
|
2094
|
-
}
|
|
2095
|
-
else {
|
|
2096
|
-
nativeSkillKeys.set(declaration.skillKey, declarationIndex);
|
|
2097
|
-
}
|
|
2098
|
-
}
|
|
2099
|
-
}
|
|
2100
|
-
const nativeComponents = codexStaticNativeComponentKeys(manifest).map((key) => ({
|
|
2101
|
-
key,
|
|
2102
|
-
scopes: ['project', 'user'],
|
|
2103
|
-
}));
|
|
2104
|
-
declarations.forEach((declaration, index) => {
|
|
2105
|
-
if (declaration.delivery?.mode === 'codex-native') {
|
|
2106
|
-
nativeComponents.push({ key: `artifacts.targets[${index}]`, scopes: declaration.scopes });
|
|
2107
|
-
}
|
|
2108
|
-
});
|
|
2109
|
-
const expectedNativeComponent = nativeComponents[0];
|
|
2110
|
-
if (expectedNativeComponent) {
|
|
2111
|
-
const canonicalScopes = (component) => [...component.scopes].sort().join(',');
|
|
2112
|
-
const expectedScopes = canonicalScopes(expectedNativeComponent);
|
|
2113
|
-
const mismatch = nativeComponents.find((component) => canonicalScopes(component) !== expectedScopes);
|
|
2114
|
-
if (mismatch) {
|
|
2115
|
-
error(`codexSharedNativeScopeMismatch: Codex native component scope sets must match exactly; ` +
|
|
2116
|
-
`${expectedNativeComponent.key} has {${expectedScopes}} but ${mismatch.key} has ` +
|
|
2117
|
-
`{${canonicalScopes(mismatch)}}`);
|
|
2118
|
-
}
|
|
2119
|
-
}
|
|
2120
|
-
const staticSkillNames = new Set(collectDeclaredSkillNames(pluginDir, manifest).static);
|
|
2121
|
-
for (const [index, declaration] of declarations.entries()) {
|
|
2122
|
-
if (declaration.target === 'codex.skill'
|
|
2123
|
-
&& declaration.delivery?.mode === 'codex-native'
|
|
2124
|
-
&& staticSkillNames.has(declaration.skillKey)) {
|
|
2125
|
-
error(`artifacts.targets[${index}].skillKey: native dynamic Skill "${declaration.skillKey}" conflicts with a static Skill of the same name`);
|
|
2126
|
-
}
|
|
2127
|
-
}
|
|
2128
|
-
const owners = new Map();
|
|
2129
|
-
for (const declaration of declarations) {
|
|
2130
|
-
if ((declaration.target !== 'codex.skill' && declaration.target !== 'claude.skill' && declaration.target !== 'agent-skills.skill') ||
|
|
2131
|
-
!declaration.skillKey) {
|
|
2132
|
-
continue;
|
|
2133
|
-
}
|
|
2134
|
-
for (const scope of declaration.scopes) {
|
|
2135
|
-
const ownerKey = `${declaration.platform ?? declaration.distribution}:${scope}:${declaration.skillKey}`;
|
|
2136
|
-
const existing = owners.get(ownerKey);
|
|
2137
|
-
if (existing) {
|
|
2138
|
-
error(`artifacts.targets has duplicate skill ownership "${ownerKey}" in artifacts "${existing}" and "${declaration.id}"`);
|
|
2139
|
-
}
|
|
2140
|
-
else {
|
|
2141
|
-
owners.set(ownerKey, declaration.id);
|
|
2142
|
-
}
|
|
2143
|
-
}
|
|
2144
|
-
}
|
|
2145
|
-
return declarations;
|
|
1564
|
+
function validateArtifactsConfigLightweight(_pluginDir, manifest) {
|
|
1565
|
+
return (manifest.artifacts?.targets ?? []).map((target) => ({ ...target, sourceDirs: target.sourceDirs ?? [] }));
|
|
2146
1566
|
}
|
|
2147
1567
|
function validateArtifactPlanRefreshKeys(refreshKeys, declaration, fieldName) {
|
|
2148
1568
|
const keys = validateStringArray(refreshKeys, `${fieldName}.refreshKeys`);
|
|
@@ -2168,7 +1588,7 @@ function isSkillAuthorOnlyPath(relativePath) {
|
|
|
2168
1588
|
const [topLevel] = relativePath.split('/').filter(Boolean);
|
|
2169
1589
|
return topLevel === 'evals' || topLevel === 'reports';
|
|
2170
1590
|
}
|
|
2171
|
-
function collectArtifactSourceFiles(rootDir, fieldName, files) {
|
|
1591
|
+
function collectArtifactSourceFiles(rootDir, fieldName, files, transform = (_relative, bytes) => bytes) {
|
|
2172
1592
|
const rootStats = fs.lstatSync(rootDir, { throwIfNoEntry: false });
|
|
2173
1593
|
if (!rootStats?.isDirectory() || rootStats.isSymbolicLink())
|
|
2174
1594
|
return;
|
|
@@ -2192,7 +1612,7 @@ function collectArtifactSourceFiles(rootDir, fieldName, files) {
|
|
|
2192
1612
|
error(`${fieldName} contains unsupported non-regular file "${relativePath}"`);
|
|
2193
1613
|
continue;
|
|
2194
1614
|
}
|
|
2195
|
-
files.set(relativePath, fs.readFileSync(absolutePath));
|
|
1615
|
+
files.set(relativePath, transform(relativePath, fs.readFileSync(absolutePath)));
|
|
2196
1616
|
}
|
|
2197
1617
|
};
|
|
2198
1618
|
visit(rootDir, '');
|
|
@@ -2206,25 +1626,21 @@ function findArtifactFilePrefixConflict(files) {
|
|
|
2206
1626
|
}
|
|
2207
1627
|
return null;
|
|
2208
1628
|
}
|
|
2209
|
-
function authorRuntimeImportKey(artifactId, importIndex) {
|
|
2210
|
-
return `${artifactId}\0${importIndex}`;
|
|
1629
|
+
function authorRuntimeImportKey(artifactId, importIndex, platform) {
|
|
1630
|
+
return `${platform ?? "common"}\0${artifactId}\0${importIndex}`;
|
|
2211
1631
|
}
|
|
2212
1632
|
async function resolveAuthorRuntimeImports(options) {
|
|
2213
1633
|
const artifactImports = (options.manifest.artifacts?.targets ?? []).flatMap((target) => (target.runtimeImports ?? []).map((reference, importIndex) => ({
|
|
2214
|
-
key: authorRuntimeImportKey(target.id, importIndex),
|
|
1634
|
+
key: authorRuntimeImportKey(target.id, importIndex, target.platform),
|
|
2215
1635
|
label: `artifacts target ${JSON.stringify(target.id)} runtime import ${JSON.stringify(reference.name)}`,
|
|
2216
1636
|
purpose: 'artifact-runtime',
|
|
1637
|
+
platforms: target.platform ? [target.platform] : [undefined],
|
|
2217
1638
|
reference,
|
|
2218
1639
|
})));
|
|
2219
1640
|
const skillRuntimeImports = (options.manifest.buildConfig?.skillRuntimeFiles ?? []).flatMap((entry, importIndex) => {
|
|
2220
1641
|
if (!isRecord(entry.import))
|
|
2221
1642
|
return [];
|
|
2222
|
-
const platforms = [
|
|
2223
|
-
...(entry.platforms !== undefined || entry.distributions === undefined
|
|
2224
|
-
? (entry.platforms ?? [...resolveSupportedPlatforms(options.manifest)])
|
|
2225
|
-
: []),
|
|
2226
|
-
...(entry.distributions?.includes('agent-skills') ? [undefined] : []),
|
|
2227
|
-
];
|
|
1643
|
+
const platforms = entry.platforms?.length ? entry.platforms : [...resolveSupportedPlatforms(options.manifest)];
|
|
2228
1644
|
return platforms.length > 0 ? [{
|
|
2229
1645
|
key: importIndex,
|
|
2230
1646
|
label: `buildConfig.skillRuntimeFiles[${importIndex}].import`,
|
|
@@ -2312,10 +1728,10 @@ async function resolveAuthorRuntimeImports(options) {
|
|
|
2312
1728
|
skillRuntimeImports: resolvedSkillRuntimeFiles,
|
|
2313
1729
|
};
|
|
2314
1730
|
}
|
|
2315
|
-
function overlayPortableRuntimeFiles(files, manifest, pluginDir, skillKey, runtimeImports) {
|
|
1731
|
+
function overlayPortableRuntimeFiles(files, manifest, pluginDir, skillKey, runtimeImports, platform) {
|
|
2316
1732
|
for (const [runtimeIndex, runtimeFile] of (manifest.buildConfig?.skillRuntimeFiles ?? []).entries()) {
|
|
2317
1733
|
if (runtimeFile.skill !== skillKey
|
|
2318
|
-
|| !runtimeFile.
|
|
1734
|
+
|| (runtimeFile.platforms?.length && !runtimeFile.platforms.includes(platform)))
|
|
2319
1735
|
continue;
|
|
2320
1736
|
if (typeof runtimeFile.source === 'string') {
|
|
2321
1737
|
const sourcePath = path.join(pluginDir, normalizeRelativePath(runtimeFile.source));
|
|
@@ -2344,10 +1760,12 @@ function validateRenderedSkillTree(options) {
|
|
|
2344
1760
|
}
|
|
2345
1761
|
const files = new Map();
|
|
2346
1762
|
declaration.sourceDirs.forEach((sourceDir, index) => {
|
|
2347
|
-
collectArtifactSourceFiles(path.join(pluginDir, normalizeRelativePath(sourceDir)), `artifacts.targets sourceDirs[${index}] for artifact "${declaration.id}"`, files)
|
|
1763
|
+
collectArtifactSourceFiles(path.join(pluginDir, normalizeRelativePath(sourceDir)), `artifacts.targets sourceDirs[${index}] for artifact "${declaration.id}"`, files, (relative, bytes) => isTemplateTextFile(relative)
|
|
1764
|
+
? Buffer.from(renderTemplateForPlatform(manifest, `${normalizeRelativePath(sourceDir)}/${relative}`, bytes.toString('utf8'), declaration.platform))
|
|
1765
|
+
: bytes);
|
|
2348
1766
|
});
|
|
2349
1767
|
if (declaration.target === 'agent-skills.skill') {
|
|
2350
|
-
overlayPortableRuntimeFiles(files, manifest, pluginDir, declaration.skillKey, options.runtimeImports);
|
|
1768
|
+
overlayPortableRuntimeFiles(files, manifest, pluginDir, declaration.skillKey, options.runtimeImports, declaration.platform);
|
|
2351
1769
|
}
|
|
2352
1770
|
for (const [relativePath, content] of Object.entries(entry.content.files)) {
|
|
2353
1771
|
if (isSkillAuthorOnlyPath(relativePath)) {
|
|
@@ -2433,37 +1851,31 @@ function validateRenderedSkillTree(options) {
|
|
|
2433
1851
|
options.managedTrees?.push({ declaration, files, scope: options.managedScope });
|
|
2434
1852
|
}
|
|
2435
1853
|
function validateStaticPortableFinalTrees(pluginDir, manifest, runtimeImports, skillValidationTools) {
|
|
2436
|
-
|
|
2437
|
-
if (typeof portableRoot !== 'string')
|
|
1854
|
+
if (!manifest.skills)
|
|
2438
1855
|
return;
|
|
2439
|
-
const rootDir = path.join(pluginDir, normalizeRelativePath(
|
|
1856
|
+
const rootDir = path.join(pluginDir, normalizeRelativePath(manifest.skills));
|
|
2440
1857
|
const rootStats = fs.lstatSync(rootDir, { throwIfNoEntry: false });
|
|
2441
1858
|
if (!rootStats?.isDirectory() || rootStats.isSymbolicLink())
|
|
2442
1859
|
return;
|
|
2443
|
-
const dynamicKeys = new Set((manifest.artifacts?.targets ?? [])
|
|
2444
|
-
.filter((target) => target.target === 'agent-skills.skill' && typeof target.skillKey === 'string')
|
|
2445
|
-
.map((target) => target.skillKey));
|
|
2446
1860
|
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'aw-static-portable-final-'));
|
|
2447
1861
|
try {
|
|
2448
|
-
for (const
|
|
2449
|
-
if (!
|
|
1862
|
+
for (const platform of resolveSupportedPlatforms(manifest)) {
|
|
1863
|
+
if (!isPortablePlatformTarget(platform))
|
|
2450
1864
|
continue;
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
skillValidationTools,
|
|
2466
|
-
});
|
|
1865
|
+
const dynamicKeys = new Set((manifest.artifacts?.targets ?? [])
|
|
1866
|
+
.filter((target) => target.platform === platform && target.target === 'agent-skills.skill')
|
|
1867
|
+
.map((target) => target.skillKey));
|
|
1868
|
+
for (const entry of fs.readdirSync(rootDir, { withFileTypes: true })) {
|
|
1869
|
+
if (!entry.isDirectory() || dynamicKeys.has(entry.name))
|
|
1870
|
+
continue;
|
|
1871
|
+
validateRenderedSkillTree({
|
|
1872
|
+
entry: { state: 'present', content: { files: {} } },
|
|
1873
|
+
declaration: { id: `static:${entry.name}`, platform, distribution: 'agent-skills',
|
|
1874
|
+
target: 'agent-skills.skill', skillKey: entry.name, sourceDirs: [`${manifest.skills}/${entry.name}`] },
|
|
1875
|
+
fieldName: `static Portable Skill "${entry.name}" (${platform})`, pluginDir, manifest, runtimeImports,
|
|
1876
|
+
materializedRoot: path.join(tempRoot, platform, entry.name), skillValidationTools,
|
|
1877
|
+
});
|
|
1878
|
+
}
|
|
2467
1879
|
}
|
|
2468
1880
|
}
|
|
2469
1881
|
finally {
|
|
@@ -2525,11 +1937,8 @@ function validateRenderedArtifactPlan(plan, declarations, scopeLabel, options) {
|
|
|
2525
1937
|
if (entry.distribution !== declaration.distribution) {
|
|
2526
1938
|
error(`${fieldName}.distribution: expected "${declaration.distribution}"`);
|
|
2527
1939
|
}
|
|
2528
|
-
if (entry.platform !== undefined) {
|
|
2529
|
-
error(`${fieldName}.platform: distribution artifacts do not support platform`);
|
|
2530
|
-
}
|
|
2531
1940
|
}
|
|
2532
|
-
|
|
1941
|
+
if (entry.platform !== declaration.platform) {
|
|
2533
1942
|
error(`${fieldName}.platform: expected "${declaration.platform}"`);
|
|
2534
1943
|
}
|
|
2535
1944
|
if (entry.kind !== declaration.kind) {
|
|
@@ -2619,68 +2028,53 @@ function validateRenderedArtifactPlan(plan, declarations, scopeLabel, options) {
|
|
|
2619
2028
|
}
|
|
2620
2029
|
}
|
|
2621
2030
|
function resolveArtifactRendererFixtureRequests(declarations, manifest, requiresNonSensitiveArtifactInput) {
|
|
2622
|
-
const
|
|
2623
|
-
const codexNative = new Map();
|
|
2031
|
+
const requests = new Map();
|
|
2624
2032
|
for (const declaration of declarations) {
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
const request = codexNative.get(scope) ?? {
|
|
2628
|
-
kind: 'codex-native',
|
|
2629
|
-
surface: 'codex',
|
|
2630
|
-
scope,
|
|
2631
|
-
configScope: 'user',
|
|
2632
|
-
declarations: [],
|
|
2633
|
-
};
|
|
2634
|
-
request.declarations.push(declaration);
|
|
2635
|
-
codexNative.set(scope, request);
|
|
2636
|
-
continue;
|
|
2637
|
-
}
|
|
2638
|
-
const surface = declaration.surface?.kind === 'aw'
|
|
2639
|
-
? declaration.surface.name
|
|
2640
|
-
: declaration.platform ?? declaration.distribution;
|
|
2033
|
+
const nativeSkill = declaration.target === 'codex.skill' || declaration.target === 'claude.skill';
|
|
2034
|
+
const surface = declaration.surface?.kind === 'aw' ? declaration.surface.name : declaration.platform;
|
|
2641
2035
|
if (!surface)
|
|
2642
2036
|
continue;
|
|
2643
|
-
for (const scope of declaration.scopes) {
|
|
2644
|
-
const key = `${surface}:${scope}`;
|
|
2645
|
-
const request =
|
|
2646
|
-
|
|
2647
|
-
surface,
|
|
2648
|
-
scope,
|
|
2649
|
-
configScope: scope,
|
|
2650
|
-
declarations: [],
|
|
2651
|
-
};
|
|
2037
|
+
for (const scope of nativeSkill ? ['user'] : declaration.scopes) {
|
|
2038
|
+
const key = `${nativeSkill ? 'native' : 'ordinary'}:${surface}:${scope}`;
|
|
2039
|
+
const request = requests.get(key) ?? { kind: nativeSkill ? 'native' : 'ordinary', surface, scope,
|
|
2040
|
+
configScope: nativeSkill ? 'user' : scope, declarations: [] };
|
|
2652
2041
|
request.declarations.push(declaration);
|
|
2653
|
-
|
|
2042
|
+
requests.set(key, request);
|
|
2654
2043
|
}
|
|
2655
2044
|
}
|
|
2656
|
-
|
|
2045
|
+
return [...requests.values()].flatMap((request) => {
|
|
2046
|
+
const definition = compilePluginConfigDefinition(manifest.config ?? { fields: {} }, MANIFEST_PLATFORMS.has(request.surface) ? request.surface : undefined);
|
|
2657
2047
|
const hasNonSensitiveTarget = request.declarations.some(requiresNonSensitiveArtifactInput);
|
|
2658
2048
|
const hasSensitiveOtherTarget = request.declarations.some((declaration) => !requiresNonSensitiveArtifactInput(declaration)
|
|
2659
|
-
&& declaration.refreshKeys.some((key) => configFieldContainsSensitiveValue(
|
|
2049
|
+
&& declaration.refreshKeys.some((key) => configFieldContainsSensitiveValue(definition.fields[key])));
|
|
2660
2050
|
if (!hasNonSensitiveTarget || !hasSensitiveOtherTarget)
|
|
2661
2051
|
return [request];
|
|
2662
|
-
const nonSensitiveDeclarations = request.declarations.filter(requiresNonSensitiveArtifactInput);
|
|
2663
|
-
const otherDeclarations = request.declarations.filter((declaration) => !requiresNonSensitiveArtifactInput(declaration));
|
|
2664
2052
|
return [
|
|
2665
|
-
{ ...request, declarations:
|
|
2666
|
-
{ ...request, declarations:
|
|
2053
|
+
{ ...request, declarations: request.declarations.filter(requiresNonSensitiveArtifactInput) },
|
|
2054
|
+
{ ...request, declarations: request.declarations.filter((declaration) => !requiresNonSensitiveArtifactInput(declaration)) },
|
|
2667
2055
|
];
|
|
2668
2056
|
});
|
|
2669
|
-
return [...partitionedAwOwned, ...codexNative.values()];
|
|
2670
2057
|
}
|
|
2671
2058
|
async function runArtifactRendererFixture(pluginDir, manifest, renderEntry, declarations, resolvedRuntimeImports, skillValidationTools, managedContext, requiresNonSensitiveArtifactInput, referenceContext) {
|
|
2672
2059
|
if (!renderEntry || declarations.length === 0)
|
|
2673
2060
|
return [];
|
|
2674
2061
|
const requests = resolveArtifactRendererFixtureRequests(declarations, manifest, requiresNonSensitiveArtifactInput);
|
|
2675
|
-
const values = defaultConfigValues(manifest);
|
|
2676
2062
|
const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'aw-artifact-render-'));
|
|
2677
2063
|
const returnedArtifacts = [];
|
|
2678
2064
|
try {
|
|
2679
2065
|
for (const [requestIndex, request] of requests.entries()) {
|
|
2680
2066
|
const { kind, surface, scope, configScope, declarations: scopedDeclarations, } = request;
|
|
2681
|
-
const distribution = surface
|
|
2067
|
+
const distribution = isPortablePlatformTarget(surface) ? 'agent-skills' : undefined;
|
|
2682
2068
|
const awSurface = surface === 'managed-commands';
|
|
2683
|
-
const platform =
|
|
2069
|
+
const platform = awSurface ? undefined : surface;
|
|
2070
|
+
const definition = compilePluginConfigDefinition(manifest.config ?? { fields: {} }, platform);
|
|
2071
|
+
const values = defaultConfigValues(manifest, platform);
|
|
2072
|
+
const platformReferences = referenceContext ? { ...referenceContext, platform,
|
|
2073
|
+
plugins: Object.fromEntries(Object.entries(referenceContext.plugins).map(([name, entry]) => {
|
|
2074
|
+
const compiled = compilePluginConfigDefinition(entry.definition, platform);
|
|
2075
|
+
return [name, { ...entry, definition: compiled, values: defaultConfigValues({ config: compiled }) }];
|
|
2076
|
+
})),
|
|
2077
|
+
} : undefined;
|
|
2684
2078
|
const event = distribution ? 'materialize' : 'install';
|
|
2685
2079
|
const requestRoot = path.join(tempRoot, `${requestIndex}-${kind}-${surface}-${scope}`);
|
|
2686
2080
|
const rendererAwHome = path.join(requestRoot, 'aw-home');
|
|
@@ -2689,7 +2083,7 @@ async function runArtifactRendererFixture(pluginDir, manifest, renderEntry, decl
|
|
|
2689
2083
|
fs.mkdirSync(requestRoot, { recursive: true });
|
|
2690
2084
|
const contextPath = path.join(requestRoot, 'context.json');
|
|
2691
2085
|
const runtimeImports = scopedDeclarations.flatMap((target) => (target.runtimeImports ?? []).map((runtimeImport, importIndex) => {
|
|
2692
|
-
const resolved = resolvedRuntimeImports?.artifactImports.get(authorRuntimeImportKey(target.id, importIndex));
|
|
2086
|
+
const resolved = resolvedRuntimeImports?.artifactImports.get(authorRuntimeImportKey(target.id, importIndex, target.platform));
|
|
2693
2087
|
if (!resolved)
|
|
2694
2088
|
return null;
|
|
2695
2089
|
const importPath = path.join(requestRoot, `runtime-${target.id}-${importIndex}`);
|
|
@@ -2704,18 +2098,15 @@ async function runArtifactRendererFixture(pluginDir, manifest, renderEntry, decl
|
|
|
2704
2098
|
};
|
|
2705
2099
|
}).filter(Boolean));
|
|
2706
2100
|
const refreshKeys = [...new Set(scopedDeclarations.flatMap((target) => target.refreshKeys))];
|
|
2707
|
-
const scopedSchema = Object.fromEntries(refreshKeys.flatMap((key) =>
|
|
2708
|
-
? []
|
|
2709
|
-
: [[key, manifest.config.fields[key]]]));
|
|
2101
|
+
const scopedSchema = Object.fromEntries(refreshKeys.flatMap((key) => definition.fields[key] === undefined ? [] : [[key, definition.fields[key]]]));
|
|
2710
2102
|
const scopedValues = Object.fromEntries(refreshKeys.flatMap((key) => Object.prototype.hasOwnProperty.call(values, key) ? [[key, values[key]]] : []));
|
|
2711
2103
|
try {
|
|
2712
2104
|
if (manifest.config) {
|
|
2713
|
-
const issues = validatePluginConfigCandidate(
|
|
2105
|
+
const issues = validatePluginConfigCandidate(definition, values, refreshKeys, platformReferences);
|
|
2714
2106
|
if (issues.length > 0)
|
|
2715
2107
|
throw new Error(formatPluginConfigIssue(issues[0]));
|
|
2716
2108
|
}
|
|
2717
2109
|
for (const target of scopedDeclarations.filter((declaration) => declaration.runtimeConfig)) {
|
|
2718
|
-
const definition = manifest.config;
|
|
2719
2110
|
createRuntimeConfigSnapshot({
|
|
2720
2111
|
installedIdentity: {
|
|
2721
2112
|
sourceId: 'authoring',
|
|
@@ -2724,7 +2115,7 @@ async function runArtifactRendererFixture(pluginDir, manifest, renderEntry, decl
|
|
|
2724
2115
|
pluginName: manifest.name,
|
|
2725
2116
|
pluginVersion: manifest.version,
|
|
2726
2117
|
platform: target.platform,
|
|
2727
|
-
scope: target.
|
|
2118
|
+
scope: target.target === 'codex.skill' || target.target === 'claude.skill' ? 'user' : scope,
|
|
2728
2119
|
configScope,
|
|
2729
2120
|
artifactId: target.id,
|
|
2730
2121
|
skillKey: target.skillKey,
|
|
@@ -2732,7 +2123,7 @@ async function runArtifactRendererFixture(pluginDir, manifest, renderEntry, decl
|
|
|
2732
2123
|
declaration: target.runtimeConfig,
|
|
2733
2124
|
definition,
|
|
2734
2125
|
values,
|
|
2735
|
-
referenceContext,
|
|
2126
|
+
referenceContext: platformReferences,
|
|
2736
2127
|
});
|
|
2737
2128
|
}
|
|
2738
2129
|
}
|
|
@@ -2765,11 +2156,11 @@ async function runArtifactRendererFixture(pluginDir, manifest, renderEntry, decl
|
|
|
2765
2156
|
requestedArtifactIds: scopedDeclarations.map((target) => target.id),
|
|
2766
2157
|
previousArtifacts: [],
|
|
2767
2158
|
artifactSources: declarations.filter((target) => (target.target === 'codex.skill' || target.target === 'claude.skill' || target.target === 'agent-skills.skill')
|
|
2768
|
-
&&
|
|
2159
|
+
&& target.platform === platform
|
|
2769
2160
|
&& target.scopes.includes(scope)).map((target) => ({
|
|
2770
2161
|
id: target.id,
|
|
2771
2162
|
target: target.target,
|
|
2772
|
-
sourceDirs: target.sourceDirs.map((sourceDir) => path.join(pluginDir, normalizeRelativePath(sourceDir))),
|
|
2163
|
+
sourceDirs: (target.sourceDirs ?? []).map((sourceDir) => path.join(pluginDir, normalizeRelativePath(sourceDir))),
|
|
2773
2164
|
})),
|
|
2774
2165
|
commandSources: (managedContext?.manifest.managedCommands?.packages ?? [])
|
|
2775
2166
|
.filter((entry) => scopedDeclarations.some((target) => target.packageKey === entry.key))
|
|
@@ -2798,8 +2189,15 @@ async function runArtifactRendererFixture(pluginDir, manifest, renderEntry, decl
|
|
|
2798
2189
|
fs.mkdirSync(rendererTemp, { recursive: true });
|
|
2799
2190
|
const rendererEnv = {
|
|
2800
2191
|
AW_HOME: rendererAwHome,
|
|
2801
|
-
|
|
2802
|
-
|
|
2192
|
+
CODEX_HOME: rendererCodexHome,
|
|
2193
|
+
CLAUDE_CONFIG_DIR: rendererClaudeHome,
|
|
2194
|
+
HOME: rendererHome,
|
|
2195
|
+
USERPROFILE: rendererHome,
|
|
2196
|
+
XDG_CONFIG_HOME: path.join(requestRoot, 'xdg-config'),
|
|
2197
|
+
XDG_CACHE_HOME: path.join(requestRoot, 'xdg-cache'),
|
|
2198
|
+
XDG_STATE_HOME: path.join(requestRoot, 'xdg-state'),
|
|
2199
|
+
XDG_DATA_HOME: path.join(requestRoot, 'xdg-data'),
|
|
2200
|
+
XDG_RUNTIME_DIR: path.join(requestRoot, 'xdg-runtime'),
|
|
2803
2201
|
PATH: process.env.PATH ?? process.env.Path ?? '',
|
|
2804
2202
|
AW_PLUGIN_CONTEXT: contextPath,
|
|
2805
2203
|
AW_PLUGIN_ROOT: pluginDir,
|
|
@@ -2812,7 +2210,6 @@ async function runArtifactRendererFixture(pluginDir, manifest, renderEntry, decl
|
|
|
2812
2210
|
AW_PLUGIN_SCOPE: scope,
|
|
2813
2211
|
};
|
|
2814
2212
|
if (process.platform === 'win32') {
|
|
2815
|
-
rendererEnv.USERPROFILE = rendererHome;
|
|
2816
2213
|
rendererEnv.TEMP = rendererTemp;
|
|
2817
2214
|
rendererEnv.TMP = rendererTemp;
|
|
2818
2215
|
if (process.env.SystemRoot)
|
|
@@ -2821,7 +2218,6 @@ async function runArtifactRendererFixture(pluginDir, manifest, renderEntry, decl
|
|
|
2821
2218
|
rendererEnv.ComSpec = process.env.ComSpec;
|
|
2822
2219
|
}
|
|
2823
2220
|
else {
|
|
2824
|
-
rendererEnv.HOME = rendererHome;
|
|
2825
2221
|
rendererEnv.TMPDIR = rendererTemp;
|
|
2826
2222
|
}
|
|
2827
2223
|
const result = spawnSync(process.execPath, [path.join(pluginDir, renderEntry.path), ...(renderEntry.args ?? [])], {
|
|
@@ -2957,8 +2353,8 @@ async function validateAuthorManagedCommands(pluginDir, manifest, rendered, cont
|
|
|
2957
2353
|
}
|
|
2958
2354
|
for (const [index, tree] of trees.entries()) {
|
|
2959
2355
|
const { declaration } = tree;
|
|
2960
|
-
const scope = declaration.
|
|
2961
|
-
if (
|
|
2356
|
+
const scope = declaration.target === 'codex.skill' || declaration.target === 'claude.skill' ? 'user' : tree.scope;
|
|
2357
|
+
if (declaration.platform !== 'codex' && declaration.platform !== 'claude')
|
|
2962
2358
|
continue;
|
|
2963
2359
|
const producer = declaration.staticSkill
|
|
2964
2360
|
? { kind: 'static-skill', platform: declaration.platform, skillKey: declaration.skillKey }
|
|
@@ -2975,9 +2371,9 @@ async function validateAuthorManagedCommands(pluginDir, manifest, rendered, cont
|
|
|
2975
2371
|
candidates.push({ producer: await tools.managedCommandProducerIdentity({ plugin, producer, scope, cwd: pluginDir }), sets });
|
|
2976
2372
|
}
|
|
2977
2373
|
for (const tree of trees) {
|
|
2978
|
-
if (
|
|
2374
|
+
if (tree.declaration.platform !== 'codex' && tree.declaration.platform !== 'claude')
|
|
2979
2375
|
continue;
|
|
2980
|
-
const scope = tree.declaration.
|
|
2376
|
+
const scope = tree.declaration.target === 'codex.skill' || tree.declaration.target === 'claude.skill' ? 'user' : tree.scope;
|
|
2981
2377
|
const resolve = await tools.createManagedCommandReferenceResolver({ plugin, platform: tree.declaration.platform, scope, cwd: pluginDir, env, candidates });
|
|
2982
2378
|
for (const [relative, bytes] of tree.files) {
|
|
2983
2379
|
if (!relative.endsWith('.md'))
|
|
@@ -3271,8 +2667,6 @@ function validateSkills(pluginDir, manifest, options, skillValidationTools) {
|
|
|
3271
2667
|
const skillsDir = path.join(pluginDir, manifest.skills);
|
|
3272
2668
|
if (!fs.existsSync(skillsDir))
|
|
3273
2669
|
return;
|
|
3274
|
-
const requiresCodexMetadata = isCodexTargeted(manifest);
|
|
3275
|
-
const targetsClaude = isClaudeTargeted(manifest);
|
|
3276
2670
|
const skillDirs = fs
|
|
3277
2671
|
.readdirSync(skillsDir, { withFileTypes: true })
|
|
3278
2672
|
.filter((d) => d.isDirectory());
|
|
@@ -3280,6 +2674,11 @@ function validateSkills(pluginDir, manifest, options, skillValidationTools) {
|
|
|
3280
2674
|
error('skills directory exists but contains no skill subdirectories');
|
|
3281
2675
|
}
|
|
3282
2676
|
for (const dir of skillDirs) {
|
|
2677
|
+
const staticPlatforms = [...resolveSupportedPlatforms(manifest)].filter((platform) => !(manifest.artifacts?.targets ?? []).some((target) => target.platform === platform && target.skillKey === dir.name));
|
|
2678
|
+
if (staticPlatforms.length === 0)
|
|
2679
|
+
continue;
|
|
2680
|
+
const requiresCodexMetadata = staticPlatforms.includes('codex');
|
|
2681
|
+
const targetsClaude = staticPlatforms.includes('claude');
|
|
3283
2682
|
const skillPath = path.join(skillsDir, dir.name);
|
|
3284
2683
|
const skillMdPath = path.join(skillPath, 'SKILL.md');
|
|
3285
2684
|
const openaiYamlPath = path.join(skillPath, 'agents', 'openai.yaml');
|
|
@@ -3293,7 +2692,7 @@ function validateSkills(pluginDir, manifest, options, skillValidationTools) {
|
|
|
3293
2692
|
if (lineCount >= MAX_SKILL_LINES) {
|
|
3294
2693
|
warn(`skills/${dir.name}/SKILL.md has ${lineCount} lines; Agent Skills recommends keeping SKILL.md under ${MAX_SKILL_LINES} lines`);
|
|
3295
2694
|
}
|
|
3296
|
-
const variants = renderedContentVariants(manifest, skillMdRelativePath, content,
|
|
2695
|
+
const variants = renderedContentVariants(manifest, skillMdRelativePath, content, staticPlatforms);
|
|
3297
2696
|
for (const variant of variants) {
|
|
3298
2697
|
const sourceName = variant.platform
|
|
3299
2698
|
? `skills/${dir.name}/SKILL.md (${variant.platform} render)`
|
|
@@ -3307,7 +2706,7 @@ function validateSkills(pluginDir, manifest, options, skillValidationTools) {
|
|
|
3307
2706
|
error(`${entry.path} [${entry.code}] ${entry.message}`);
|
|
3308
2707
|
}
|
|
3309
2708
|
if (parsed.frontmatter) {
|
|
3310
|
-
const profile = options.strictAgentSkills || !targetsClaude
|
|
2709
|
+
const profile = options.strictAgentSkills || !targetsClaude || isPortablePlatformTarget(variant.platform)
|
|
3311
2710
|
? 'portable-agent-skills'
|
|
3312
2711
|
: options.claudeSkillProfile === 'current'
|
|
3313
2712
|
? 'claude-current'
|
|
@@ -3616,9 +3015,7 @@ async function validatePluginDir(pluginDir, options) {
|
|
|
3616
3015
|
let referenceContext;
|
|
3617
3016
|
try {
|
|
3618
3017
|
normalizedManifest = await cliManifestTools.validateSourcePluginManifest(pluginDir, manifest);
|
|
3619
|
-
|
|
3620
|
-
if (normalizedManifest.config)
|
|
3621
|
-
manifest.config = normalizedManifest.config;
|
|
3018
|
+
manifest = normalizedManifest;
|
|
3622
3019
|
// The Workspace is the sole source of dependency definitions and defaults.
|
|
3623
3020
|
// No installed plugin or user config can complete an author fixture.
|
|
3624
3021
|
if (manifest.config) {
|
|
@@ -3669,9 +3066,9 @@ async function validatePluginDir(pluginDir, options) {
|
|
|
3669
3066
|
}
|
|
3670
3067
|
catch (e) {
|
|
3671
3068
|
error(e.message);
|
|
3069
|
+
return;
|
|
3672
3070
|
}
|
|
3673
3071
|
validatePlatformFieldSupport(manifest);
|
|
3674
|
-
validatePortableNativeArtifactCapabilityLightweight(manifest);
|
|
3675
3072
|
validateNameMatchesDirectory(pluginDir, manifest);
|
|
3676
3073
|
validateNoBuildOutputDirs(pluginDir);
|
|
3677
3074
|
validateDeclaredNativeAssets(pluginDir, manifest);
|