@lesliechan721/aw 0.1.0-beta.63 → 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 +457 -1634
- 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 +11 -2
- package/dist/src/utils/plugin-config-references.js +85 -90
- 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
|
@@ -2,17 +2,16 @@ import crypto from 'node:crypto';
|
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import fs from 'fs-extra';
|
|
5
|
-
import {
|
|
6
|
-
import { resolveCatalogOperationContext
|
|
5
|
+
import { isPortablePlatformTarget } from '@lesliechan721/aw-plugin-core';
|
|
6
|
+
import { resolveCatalogOperationContext } from '../utils/catalog-operation-context.js';
|
|
7
7
|
import { readCatalogSourcesConfigSnapshot } from '../utils/catalog-sources.js';
|
|
8
8
|
import { parsePluginId } from '../utils/multi-source-catalog.js';
|
|
9
9
|
import { resolveAwProjectRoot } from '../utils/plugin-config.js';
|
|
10
10
|
import { getClaudeHome, getCodexHome, resolveAwHome } from '../utils/paths.js';
|
|
11
|
-
import { canonicalizePathThroughExistingAncestor, ensureRegularDirectoryPath
|
|
12
|
-
import { materializePortableSkillsFromCatalog, resolvePortableCatalogBindingInput
|
|
11
|
+
import { canonicalizePathThroughExistingAncestor, ensureRegularDirectoryPath } from '../utils/state-paths.js';
|
|
12
|
+
import { assertPortablePlatform, materializePortableSkillsFromCatalog, resolvePortableCatalogBindingInput } from './materializer.js';
|
|
13
13
|
import { AW_SOURCE_BINDING_FILENAME, writeAwSourceBinding } from '../review/source-binding.js';
|
|
14
|
-
|
|
15
|
-
export { SKILLS_CLI_SUPPORTED_VERSION_LABEL, } from './skills-cli.js';
|
|
14
|
+
export const SKILLS_CLI_SUPPORTED_VERSION_LABEL = 'AW Portable writer';
|
|
16
15
|
export class PortableCommandError extends Error {
|
|
17
16
|
code;
|
|
18
17
|
constructor(code, message) {
|
|
@@ -28,40 +27,21 @@ export function setPortableCommandTestHooksForTests(hooks) {
|
|
|
28
27
|
function digest(value) {
|
|
29
28
|
return `sha256:${crypto.createHash('sha256').update(JSON.stringify(value)).digest('hex')}`;
|
|
30
29
|
}
|
|
31
|
-
function toPublicInstalledRecord(record) {
|
|
32
|
-
return {
|
|
33
|
-
name: record.name,
|
|
34
|
-
...(record.scope !== undefined ? { scope: record.scope } : {}),
|
|
35
|
-
agents: [...record.agents],
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
function publicInstalledRecords(records) {
|
|
39
|
-
return records.map(toPublicInstalledRecord);
|
|
40
|
-
}
|
|
41
30
|
function assertScope(scope) {
|
|
42
|
-
if (scope !== 'project' && scope !== 'user')
|
|
31
|
+
if (scope !== 'project' && scope !== 'user')
|
|
43
32
|
throw new Error('scope 必须是 project 或 user。');
|
|
44
|
-
}
|
|
45
33
|
}
|
|
46
34
|
export function normalizePortableAgents(values) {
|
|
47
35
|
if (values === undefined)
|
|
48
36
|
return undefined;
|
|
49
|
-
if (values.length === 0 || values.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const result = [];
|
|
53
|
-
const seen = new Set();
|
|
54
|
-
for (const raw of values) {
|
|
55
|
-
const value = raw.trim();
|
|
56
|
-
if (!value || value.length > 128 || value.startsWith('-') || /[\s\p{Cc}]/u.test(value)) {
|
|
57
|
-
throw new PortableCommandError('portableInvalidAgentSelection', `无效 Agent ID:${JSON.stringify(raw)}。`);
|
|
58
|
-
}
|
|
59
|
-
if (!seen.has(value)) {
|
|
60
|
-
seen.add(value);
|
|
61
|
-
result.push(value);
|
|
62
|
-
}
|
|
37
|
+
if (values.length === 0 || new Set(values).size !== values.length
|
|
38
|
+
|| values.some((value) => !isPortablePlatformTarget(value))) {
|
|
39
|
+
throw new PortableCommandError('portableInvalidAgentSelection', '请选择有效的 Portable 平台。');
|
|
63
40
|
}
|
|
64
|
-
return
|
|
41
|
+
return [...values];
|
|
42
|
+
}
|
|
43
|
+
function removedPortableWorkflow() {
|
|
44
|
+
throw new PortableCommandError('portableUnsupported', '此旧安装流程已移除。请设置本机 targets,再使用统一 install 或 sync。');
|
|
65
45
|
}
|
|
66
46
|
function selectCandidates(candidates, requested) {
|
|
67
47
|
if (candidates.length === 0) {
|
|
@@ -81,530 +61,23 @@ function selectCandidates(candidates, requested) {
|
|
|
81
61
|
}
|
|
82
62
|
return selected;
|
|
83
63
|
}
|
|
84
|
-
function
|
|
85
|
-
|
|
86
|
-
throw error;
|
|
87
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
88
|
-
if (message.includes('does not declare distributions.agentSkills')) {
|
|
89
|
-
throw new PortableCommandError('portableUnsupported', '插件不支持 Agent Skills distribution。');
|
|
90
|
-
}
|
|
91
|
-
if (message.includes('Portable materialization config is invalid')) {
|
|
92
|
-
throw new PortableCommandError('requiredConfigMissing', '插件缺少生成内容所需的设置,或设置无效。');
|
|
93
|
-
}
|
|
94
|
-
if (message.includes('name collision')) {
|
|
95
|
-
throw new PortableCommandError('portableSkillNameConflict', message);
|
|
96
|
-
}
|
|
97
|
-
if (message.includes('sensitive config') || message.includes('unresolved template')) {
|
|
98
|
-
throw new PortableCommandError('portableSensitiveOutput', 'portable 输出包含敏感值或未解析模板。');
|
|
99
|
-
}
|
|
100
|
-
if (message.includes('runtime import')) {
|
|
101
|
-
throw new PortableCommandError('portableRuntimeImportMissing', 'portable runtime import 缺失或无效。');
|
|
102
|
-
}
|
|
103
|
-
if (message.toLowerCase().includes('renderer')) {
|
|
104
|
-
throw new PortableCommandError('portableRendererFailed', 'portable renderer 执行失败。');
|
|
105
|
-
}
|
|
106
|
-
if (message.includes('Skill') || message.includes('SKILL.md')) {
|
|
107
|
-
throw new PortableCommandError('portableSkillInvalid', 'portable Skill 内容无效。');
|
|
108
|
-
}
|
|
109
|
-
throw error;
|
|
110
|
-
}
|
|
111
|
-
async function createMaterialization(options) {
|
|
112
|
-
try {
|
|
113
|
-
return await materializePortableSkillsFromCatalog({
|
|
114
|
-
selector: options.selector,
|
|
115
|
-
scope: options.scope,
|
|
116
|
-
cwd: options.cwd,
|
|
117
|
-
cliVersion: options.cliVersion,
|
|
118
|
-
env: options.env,
|
|
119
|
-
signal: options.signal,
|
|
120
|
-
configSnapshot: options.configSnapshot,
|
|
121
|
-
catalogOperationContext: options.catalogOperationContext,
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
catch (error) {
|
|
125
|
-
if (options.signal?.aborted)
|
|
126
|
-
options.signal.throwIfAborted();
|
|
127
|
-
classifyMaterializationError(error);
|
|
128
|
-
}
|
|
64
|
+
export async function preparePortableInstall(_options) {
|
|
65
|
+
return removedPortableWorkflow();
|
|
129
66
|
}
|
|
130
|
-
async function
|
|
131
|
-
|
|
132
|
-
const configSnapshot = await readCatalogSourcesConfigSnapshot(options.env);
|
|
133
|
-
const materialized = await createMaterialization({ ...options, configSnapshot });
|
|
134
|
-
try {
|
|
135
|
-
const skillsCli = await probeSkillsCli({ cwd: executionCwd, env: options.env, signal: options.signal });
|
|
136
|
-
const selected = selectCandidates(materialized.candidates, options.requestedSkills);
|
|
137
|
-
const installed = await listInstalledSkills({
|
|
138
|
-
cwd: executionCwd,
|
|
139
|
-
env: options.env,
|
|
140
|
-
signal: options.signal,
|
|
141
|
-
global: options.scope === 'user',
|
|
142
|
-
});
|
|
143
|
-
const names = new Set(selected.map((candidate) => candidate.name));
|
|
144
|
-
const collisions = installed
|
|
145
|
-
.filter((entry) => names.has(entry.name))
|
|
146
|
-
.map((entry) => ({ ...toPublicInstalledRecord(entry), requestedName: entry.name }));
|
|
147
|
-
const evidence = {
|
|
148
|
-
pluginId: materialized.pluginId,
|
|
149
|
-
sourceId: materialized.sourceId,
|
|
150
|
-
sourceIdentity: materialized.sourceIdentity,
|
|
151
|
-
pluginVersion: materialized.pluginVersion,
|
|
152
|
-
scope: options.scope,
|
|
153
|
-
selected,
|
|
154
|
-
requestedSkills: options.requestedSkills,
|
|
155
|
-
agentMode: options.agents ? 'explicit' : 'automatic',
|
|
156
|
-
requestedAgents: options.agents ?? [],
|
|
157
|
-
skillsCliVersion: skillsCli.version,
|
|
158
|
-
collisions,
|
|
159
|
-
dependencies: materialized.dependencyPluginIds,
|
|
160
|
-
materializationDigest: materialized.digest,
|
|
161
|
-
configDigest: digest({
|
|
162
|
-
catalogSources: configSnapshot.digest,
|
|
163
|
-
pluginConfig: materialized.configDigest,
|
|
164
|
-
}),
|
|
165
|
-
generationSetDigest: options.catalogOperationContext.generationSetDigest,
|
|
166
|
-
};
|
|
167
|
-
return {
|
|
168
|
-
materialized,
|
|
169
|
-
review: { ...evidence, evidenceDigest: digest(evidence) },
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
catch (error) {
|
|
173
|
-
await materialized.cleanup();
|
|
174
|
-
throw error;
|
|
175
|
-
}
|
|
67
|
+
export async function installPortableSkills(_options) {
|
|
68
|
+
return removedPortableWorkflow();
|
|
176
69
|
}
|
|
177
|
-
export async function
|
|
178
|
-
|
|
179
|
-
const catalogOperationContext = options.catalogOperationContext
|
|
180
|
-
?? await resolveCatalogOperationContext({
|
|
181
|
-
...(parsePluginId(options.selector).sourceId
|
|
182
|
-
? { sourceIds: [parsePluginId(options.selector).sourceId] }
|
|
183
|
-
: {}),
|
|
184
|
-
env: options.env,
|
|
185
|
-
...(options.signal ? { signal: options.signal } : {}),
|
|
186
|
-
});
|
|
187
|
-
const collected = await collectEvidence({ ...options, agents, catalogOperationContext });
|
|
188
|
-
try {
|
|
189
|
-
return structuredClone(collected.review);
|
|
190
|
-
}
|
|
191
|
-
finally {
|
|
192
|
-
await collected.materialized.cleanup();
|
|
193
|
-
}
|
|
70
|
+
export async function recheckPortableInstall(_options) {
|
|
71
|
+
return removedPortableWorkflow();
|
|
194
72
|
}
|
|
195
|
-
export function
|
|
196
|
-
return
|
|
197
|
-
`插件:${review.pluginId}${review.pluginVersion ? ` @ ${review.pluginVersion}` : ''}`,
|
|
198
|
-
`范围:${review.scope}`,
|
|
199
|
-
`Skill:${review.selected.map((entry) => `${entry.name}(${entry.providerPluginId})`).join(', ')}`,
|
|
200
|
-
review.agentMode === 'automatic'
|
|
201
|
-
? 'Agent:自动选择检测到的 Agent;未检测到时可能选择全部 Agent'
|
|
202
|
-
: `Agent:${review.requestedAgents.join(', ')}`,
|
|
203
|
-
`依赖:${review.dependencies.length > 0 ? review.dependencies.join(', ') : '无'}`,
|
|
204
|
-
`同名覆盖:${review.collisions.length > 0
|
|
205
|
-
? review.collisions.map((entry) => `${entry.name} [${entry.agents.join(', ') || 'unknown'}]`).join('; ')
|
|
206
|
-
: '无'}`,
|
|
207
|
-
];
|
|
73
|
+
export async function preparePortableRetry(_options) {
|
|
74
|
+
return removedPortableWorkflow();
|
|
208
75
|
}
|
|
209
|
-
function
|
|
210
|
-
return
|
|
211
|
-
receiptSchemaVersion: 5,
|
|
212
|
-
command: 'skill:install',
|
|
213
|
-
ok: false,
|
|
214
|
-
status,
|
|
215
|
-
plugin: {
|
|
216
|
-
id: review.pluginId,
|
|
217
|
-
...(review.sourceId ? { sourceId: review.sourceId } : {}),
|
|
218
|
-
...(review.sourceIdentity ? { sourceIdentity: review.sourceIdentity } : {}),
|
|
219
|
-
...(review.pluginVersion ? { version: review.pluginVersion } : {}),
|
|
220
|
-
},
|
|
221
|
-
scope: review.scope,
|
|
222
|
-
selectedSkills: review.selected,
|
|
223
|
-
...(review.requestedSkills ? { requestedSkills: review.requestedSkills } : {}),
|
|
224
|
-
agentMode: review.agentMode,
|
|
225
|
-
requestedAgents: review.requestedAgents,
|
|
226
|
-
skillsCliVersion: review.skillsCliVersion,
|
|
227
|
-
collisions: review.collisions,
|
|
228
|
-
dependencies: review.dependencies,
|
|
229
|
-
materializationDigest: review.materializationDigest,
|
|
230
|
-
verification: {
|
|
231
|
-
...verification,
|
|
232
|
-
records: publicInstalledRecords(verification.records),
|
|
233
|
-
},
|
|
234
|
-
...(attemptedTargets ? { attemptedTargets } : {}),
|
|
235
|
-
warnings: [],
|
|
236
|
-
failures: [{
|
|
237
|
-
code,
|
|
238
|
-
message: code === 'portableSkillsCliInstallFailed'
|
|
239
|
-
? 'skills add 执行失败,可能已写入部分目标。'
|
|
240
|
-
: 'skills add 已完成,但安装验证缺少目标。',
|
|
241
|
-
recovery: '修复问题后重新运行 aw skill install;也可使用 skills remove 清理外部安装。',
|
|
242
|
-
}],
|
|
243
|
-
};
|
|
76
|
+
export async function executePortableRetry(_options) {
|
|
77
|
+
return removedPortableWorkflow();
|
|
244
78
|
}
|
|
245
|
-
export
|
|
246
|
-
|
|
247
|
-
const scope = options.scope;
|
|
248
|
-
const agents = normalizePortableAgents(options.requestedAgents);
|
|
249
|
-
await options.onProgress?.('prepare');
|
|
250
|
-
const parsedSelector = parsePluginId(options.selector);
|
|
251
|
-
const initialCatalogOperation = await resolveCatalogOperationContext({
|
|
252
|
-
...(parsedSelector.sourceId ? { sourceIds: [parsedSelector.sourceId] } : {}),
|
|
253
|
-
env: options.env,
|
|
254
|
-
});
|
|
255
|
-
if (options.expectedGenerationSetDigest
|
|
256
|
-
&& initialCatalogOperation.generationSetDigest !== options.expectedGenerationSetDigest) {
|
|
257
|
-
throw new PortableCommandError('reviewStale', '确认后 Active Catalog generation 已变化。');
|
|
258
|
-
}
|
|
259
|
-
const initial = await collectEvidence({
|
|
260
|
-
...options,
|
|
261
|
-
scope,
|
|
262
|
-
agents,
|
|
263
|
-
catalogOperationContext: initialCatalogOperation,
|
|
264
|
-
});
|
|
265
|
-
options.onReview?.(initial.review);
|
|
266
|
-
try {
|
|
267
|
-
if (!options.yes) {
|
|
268
|
-
if (!options.confirm) {
|
|
269
|
-
throw new PortableCommandError('confirmationRequired', '安装需要交互确认或 --yes。');
|
|
270
|
-
}
|
|
271
|
-
const confirmed = await options.confirm(initial.review);
|
|
272
|
-
if (confirmed.cancelled || confirmed.value !== true) {
|
|
273
|
-
throw new PortableCommandError('confirmationRequired', '用户未确认安装。');
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
finally {
|
|
278
|
-
await initial.materialized.cleanup();
|
|
279
|
-
}
|
|
280
|
-
return withAwHomeMutationLock({
|
|
281
|
-
env: options.env,
|
|
282
|
-
action: async () => {
|
|
283
|
-
let current;
|
|
284
|
-
try {
|
|
285
|
-
const currentCatalogOperation = await resolveCatalogOperationContext({
|
|
286
|
-
...(parsedSelector.sourceId ? { sourceIds: [parsedSelector.sourceId] } : {}),
|
|
287
|
-
env: options.env,
|
|
288
|
-
});
|
|
289
|
-
if (currentCatalogOperation.generationSetDigest
|
|
290
|
-
!== initialCatalogOperation.generationSetDigest
|
|
291
|
-
|| options.expectedGenerationSetDigest
|
|
292
|
-
&& currentCatalogOperation.generationSetDigest !== options.expectedGenerationSetDigest) {
|
|
293
|
-
throw new PortableCommandError('reviewStale', '确认后 Active Catalog generation 已变化。');
|
|
294
|
-
}
|
|
295
|
-
current = await collectEvidence({
|
|
296
|
-
...options,
|
|
297
|
-
scope,
|
|
298
|
-
agents,
|
|
299
|
-
catalogOperationContext: currentCatalogOperation,
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
catch (error) {
|
|
303
|
-
if (error instanceof PortableCommandError && error.code === 'portableNoSkillsSelected') {
|
|
304
|
-
throw new PortableCommandError('reviewStale', '确认后的所选 Skill 已消失。');
|
|
305
|
-
}
|
|
306
|
-
throw error;
|
|
307
|
-
}
|
|
308
|
-
try {
|
|
309
|
-
const initialNames = new Set(initial.review.selected.map((entry) => entry.name));
|
|
310
|
-
const currentNames = new Set(current.review.selected.map((entry) => entry.name));
|
|
311
|
-
if ([...initialNames].some((name) => !currentNames.has(name))) {
|
|
312
|
-
throw new PortableCommandError('reviewStale', '确认后的所选 Skill 已消失。');
|
|
313
|
-
}
|
|
314
|
-
if (options.expectedEvidenceDigest
|
|
315
|
-
&& current.review.evidenceDigest !== options.expectedEvidenceDigest) {
|
|
316
|
-
throw new PortableCommandError('reviewStale', '确认后的安装证据已变化。');
|
|
317
|
-
}
|
|
318
|
-
if (current.review.evidenceDigest !== initial.review.evidenceDigest && !options.yes) {
|
|
319
|
-
options.onReview?.(current.review);
|
|
320
|
-
const confirmed = await options.confirm?.(current.review);
|
|
321
|
-
if (!confirmed || confirmed.cancelled || confirmed.value !== true) {
|
|
322
|
-
throw new PortableCommandError('reviewStale', '安装证据已变化,且新 Review 未确认。');
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
const executionCwd = options.scope === 'project' ? resolveAwProjectRoot(options.cwd) : options.cwd;
|
|
326
|
-
let addFailure;
|
|
327
|
-
try {
|
|
328
|
-
await options.onProgress?.('add');
|
|
329
|
-
await addSkills({
|
|
330
|
-
rootDir: current.materialized.rootDir,
|
|
331
|
-
skills: current.review.selected.map((entry) => entry.name),
|
|
332
|
-
...(agents ? { agents } : {}),
|
|
333
|
-
global: options.scope === 'user',
|
|
334
|
-
cwd: executionCwd,
|
|
335
|
-
env: options.env,
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
catch (error) {
|
|
339
|
-
if (error instanceof SkillsCliError && error.code === 'portableSkillsCliInstallFailed') {
|
|
340
|
-
addFailure = error;
|
|
341
|
-
}
|
|
342
|
-
else {
|
|
343
|
-
throw error;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
await options.onProgress?.('verify');
|
|
347
|
-
const verification = await verifySkills({
|
|
348
|
-
skills: current.review.selected.map((entry) => entry.name),
|
|
349
|
-
...(agents ? { agents } : {}),
|
|
350
|
-
global: options.scope === 'user',
|
|
351
|
-
cwd: executionCwd,
|
|
352
|
-
env: options.env,
|
|
353
|
-
});
|
|
354
|
-
if (verification.unknown.length > 0) {
|
|
355
|
-
const receipt = installFailureReceipt(current.review, addFailure?.code ?? 'portableSkillsCliVerificationFailed', 'partial', verification);
|
|
356
|
-
receipt.warnings.push('skills list 验证失败,部分目标的结果无法确认。');
|
|
357
|
-
if (!addFailure)
|
|
358
|
-
receipt.failures = [];
|
|
359
|
-
receipt.failures.push({
|
|
360
|
-
code: 'portableSkillsCliVerificationFailed',
|
|
361
|
-
message: 'skills list 验证失败,部分安装结果为 unknown。',
|
|
362
|
-
recovery: '修复 Skills CLI 后先重新检查结果,再决定是否重试或清理外部安装。',
|
|
363
|
-
});
|
|
364
|
-
return receipt;
|
|
365
|
-
}
|
|
366
|
-
if (addFailure) {
|
|
367
|
-
const expectedCount = current.review.selected.length * (agents?.length ?? 1);
|
|
368
|
-
return installFailureReceipt(current.review, addFailure.code, verification.missing.length === expectedCount ? 'failed' : 'partial', verification);
|
|
369
|
-
}
|
|
370
|
-
if (verification.missing.length > 0) {
|
|
371
|
-
return installFailureReceipt(current.review, 'portableSkillsCliVerificationFailed', 'partial', verification);
|
|
372
|
-
}
|
|
373
|
-
return {
|
|
374
|
-
...installFailureReceipt(current.review, '', 'failed', verification),
|
|
375
|
-
ok: true,
|
|
376
|
-
status: 'succeeded',
|
|
377
|
-
failures: [],
|
|
378
|
-
};
|
|
379
|
-
}
|
|
380
|
-
finally {
|
|
381
|
-
await current.materialized.cleanup();
|
|
382
|
-
}
|
|
383
|
-
},
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
function receiptTargets(receipt) {
|
|
387
|
-
if (receipt.attemptedTargets)
|
|
388
|
-
return receipt.attemptedTargets.map((target) => ({ ...target }));
|
|
389
|
-
const skills = receipt.selectedSkills.map((candidate) => candidate.name);
|
|
390
|
-
if (receipt.agentMode === 'explicit') {
|
|
391
|
-
return receipt.requestedAgents.flatMap((agent) => skills.map((skill) => ({ skill, agent })));
|
|
392
|
-
}
|
|
393
|
-
return skills.map((skill) => ({ skill }));
|
|
394
|
-
}
|
|
395
|
-
function verificationStatus(targets, verification) {
|
|
396
|
-
if (verification.unknown.length > 0)
|
|
397
|
-
return 'partial';
|
|
398
|
-
if (verification.missing.length === 0)
|
|
399
|
-
return 'succeeded';
|
|
400
|
-
return verification.missing.length === targets.length ? 'failed' : 'partial';
|
|
401
|
-
}
|
|
402
|
-
function recheckedReceipt(receipt, skillsCliVersion, verification) {
|
|
403
|
-
const targets = receiptTargets(receipt);
|
|
404
|
-
const status = verificationStatus(targets, verification);
|
|
405
|
-
const unknown = verification.unknown.length > 0;
|
|
406
|
-
const missing = verification.missing.length > 0;
|
|
407
|
-
return {
|
|
408
|
-
...receipt,
|
|
409
|
-
ok: status === 'succeeded',
|
|
410
|
-
status,
|
|
411
|
-
skillsCliVersion,
|
|
412
|
-
verification: {
|
|
413
|
-
...verification,
|
|
414
|
-
records: publicInstalledRecords(verification.records),
|
|
415
|
-
},
|
|
416
|
-
warnings: unknown ? ['skills list 验证失败,部分目标的结果无法确认。'] : [],
|
|
417
|
-
failures: unknown ? [{
|
|
418
|
-
code: 'portableSkillsCliVerificationFailed',
|
|
419
|
-
message: 'skills list 验证失败,部分安装结果为 unknown。',
|
|
420
|
-
recovery: '修复 Skills CLI 后先重新检查结果,再决定是否重试或清理外部安装。',
|
|
421
|
-
}] : missing ? [{
|
|
422
|
-
code: 'portableSkillsCliVerificationFailed',
|
|
423
|
-
message: '只读检查确认部分目标缺失。',
|
|
424
|
-
recovery: '重新准备后只重试明确缺失的 Skill 与 Agent 组合。',
|
|
425
|
-
}] : [],
|
|
426
|
-
};
|
|
427
|
-
}
|
|
428
|
-
export async function recheckPortableInstall(options) {
|
|
429
|
-
assertScope(options.receipt.scope);
|
|
430
|
-
const executionCwd = options.receipt.scope === 'project'
|
|
431
|
-
? resolveAwProjectRoot(options.cwd)
|
|
432
|
-
: options.cwd;
|
|
433
|
-
const skillsCli = await probeSkillsCli({
|
|
434
|
-
cwd: executionCwd,
|
|
435
|
-
env: options.env,
|
|
436
|
-
signal: options.signal,
|
|
437
|
-
});
|
|
438
|
-
const verification = await verifySkillTargets({
|
|
439
|
-
targets: receiptTargets(options.receipt),
|
|
440
|
-
global: options.receipt.scope === 'user',
|
|
441
|
-
cwd: executionCwd,
|
|
442
|
-
env: options.env,
|
|
443
|
-
signal: options.signal,
|
|
444
|
-
});
|
|
445
|
-
return recheckedReceipt(options.receipt, skillsCli.version, verification);
|
|
446
|
-
}
|
|
447
|
-
function normalizeRetryPairs(receipt) {
|
|
448
|
-
if ((receipt.verification.unknown?.length ?? 0) > 0) {
|
|
449
|
-
throw new PortableCommandError('portableRetryNotExact', '存在无法确认的目标;必须先只读复查,不能猜测重试目标。');
|
|
450
|
-
}
|
|
451
|
-
if (receipt.verification.missing.length === 0) {
|
|
452
|
-
throw new PortableCommandError('portableNoRetryTargets', '没有已确认缺失的目标可重试。');
|
|
453
|
-
}
|
|
454
|
-
if (receipt.agentMode !== 'explicit') {
|
|
455
|
-
throw new PortableCommandError('portableRetryNotExact', '自动 Agent 结果没有精确 Agent 身份;只能先只读复查。');
|
|
456
|
-
}
|
|
457
|
-
const selected = new Set(receipt.selectedSkills.map((candidate) => candidate.name));
|
|
458
|
-
const agents = new Set(receipt.requestedAgents);
|
|
459
|
-
const result = [];
|
|
460
|
-
const seen = new Set();
|
|
461
|
-
for (const target of receipt.verification.missing) {
|
|
462
|
-
if (!target.agent || !selected.has(target.skill) || !agents.has(target.agent)) {
|
|
463
|
-
throw new PortableCommandError('portableRetryNotExact', '缺失结果不能绑定到原请求中的精确 Skill 与 Agent。');
|
|
464
|
-
}
|
|
465
|
-
const key = `${target.skill}\0${target.agent}`;
|
|
466
|
-
if (!seen.has(key)) {
|
|
467
|
-
seen.add(key);
|
|
468
|
-
result.push({ skill: target.skill, agent: target.agent });
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
return result;
|
|
472
|
-
}
|
|
473
|
-
function retryTargetGroups(pairs) {
|
|
474
|
-
const groups = new Map();
|
|
475
|
-
for (const pair of pairs) {
|
|
476
|
-
if (!pair.agent) {
|
|
477
|
-
throw new PortableCommandError('portableRetryNotExact', '重试目标缺少精确 Agent。');
|
|
478
|
-
}
|
|
479
|
-
const skills = groups.get(pair.agent) ?? [];
|
|
480
|
-
skills.push(pair.skill);
|
|
481
|
-
groups.set(pair.agent, skills);
|
|
482
|
-
}
|
|
483
|
-
return [...groups].map(([agent, skills]) => ({ agent, skills }));
|
|
484
|
-
}
|
|
485
|
-
function createRetryReview(review, retryPairs) {
|
|
486
|
-
const targetGroups = retryTargetGroups(retryPairs);
|
|
487
|
-
const baseEvidenceDigest = review.evidenceDigest;
|
|
488
|
-
return {
|
|
489
|
-
...review,
|
|
490
|
-
baseEvidenceDigest,
|
|
491
|
-
retryPairs: retryPairs.map((pair) => ({ ...pair })),
|
|
492
|
-
targetGroups,
|
|
493
|
-
evidenceDigest: digest({ baseEvidenceDigest, retryPairs, targetGroups }),
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
async function collectRetryEvidence(options) {
|
|
497
|
-
const skills = [...new Set(options.retryPairs.map((pair) => pair.skill))];
|
|
498
|
-
const agents = [...new Set(options.retryPairs.map((pair) => pair.agent))];
|
|
499
|
-
const parsedSelector = parsePluginId(options.receipt.plugin.id);
|
|
500
|
-
const catalogOperationContext = options.catalogOperationContext
|
|
501
|
-
?? await resolveCatalogOperationContext({
|
|
502
|
-
...(parsedSelector.sourceId ? { sourceIds: [parsedSelector.sourceId] } : {}),
|
|
503
|
-
env: options.env,
|
|
504
|
-
...(options.signal ? { signal: options.signal } : {}),
|
|
505
|
-
});
|
|
506
|
-
const collected = await collectEvidence({
|
|
507
|
-
selector: options.receipt.plugin.id,
|
|
508
|
-
scope: options.receipt.scope,
|
|
509
|
-
requestedSkills: skills,
|
|
510
|
-
agents,
|
|
511
|
-
cwd: options.cwd,
|
|
512
|
-
cliVersion: options.cliVersion,
|
|
513
|
-
env: options.env,
|
|
514
|
-
signal: options.signal,
|
|
515
|
-
catalogOperationContext,
|
|
516
|
-
});
|
|
517
|
-
return { ...collected, review: createRetryReview(collected.review, options.retryPairs) };
|
|
518
|
-
}
|
|
519
|
-
export async function preparePortableRetry(options) {
|
|
520
|
-
const checked = await recheckPortableInstall(options);
|
|
521
|
-
const retryPairs = normalizeRetryPairs(checked);
|
|
522
|
-
const collected = await collectRetryEvidence({ ...options, receipt: checked, retryPairs });
|
|
523
|
-
try {
|
|
524
|
-
return structuredClone(collected.review);
|
|
525
|
-
}
|
|
526
|
-
finally {
|
|
527
|
-
await collected.materialized.cleanup();
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
export async function executePortableRetry(options) {
|
|
531
|
-
if (options.expectedEvidenceDigest !== options.review.evidenceDigest) {
|
|
532
|
-
throw new PortableCommandError('reviewStale', 'Portable 重试票据不匹配。');
|
|
533
|
-
}
|
|
534
|
-
await options.onProgress?.('prepare');
|
|
535
|
-
return withAwHomeMutationLock({
|
|
536
|
-
env: options.env,
|
|
537
|
-
action: async () => {
|
|
538
|
-
const checked = await recheckPortableInstall({
|
|
539
|
-
receipt: options.receipt,
|
|
540
|
-
cwd: options.cwd,
|
|
541
|
-
env: options.env,
|
|
542
|
-
signal: options.signal,
|
|
543
|
-
});
|
|
544
|
-
const retryPairs = normalizeRetryPairs(checked);
|
|
545
|
-
const collected = await collectRetryEvidence({ ...options, receipt: checked, retryPairs });
|
|
546
|
-
try {
|
|
547
|
-
if (collected.review.evidenceDigest !== options.expectedEvidenceDigest) {
|
|
548
|
-
throw new PortableCommandError('reviewStale', '确认后的 Portable 重试证据已变化。');
|
|
549
|
-
}
|
|
550
|
-
const executionCwd = checked.scope === 'project'
|
|
551
|
-
? resolveAwProjectRoot(options.cwd)
|
|
552
|
-
: options.cwd;
|
|
553
|
-
let addFailed = false;
|
|
554
|
-
await options.onProgress?.('add');
|
|
555
|
-
for (const group of collected.review.targetGroups) {
|
|
556
|
-
try {
|
|
557
|
-
await addSkills({
|
|
558
|
-
rootDir: collected.materialized.rootDir,
|
|
559
|
-
skills: group.skills,
|
|
560
|
-
agents: [group.agent],
|
|
561
|
-
global: checked.scope === 'user',
|
|
562
|
-
cwd: executionCwd,
|
|
563
|
-
env: options.env,
|
|
564
|
-
signal: options.signal,
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
catch (error) {
|
|
568
|
-
if (error instanceof SkillsCliError && error.code === 'portableSkillsCliInstallFailed') {
|
|
569
|
-
addFailed = true;
|
|
570
|
-
continue;
|
|
571
|
-
}
|
|
572
|
-
throw error;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
await options.onProgress?.('verify');
|
|
576
|
-
const verification = await verifySkillTargets({
|
|
577
|
-
targets: collected.review.retryPairs,
|
|
578
|
-
global: checked.scope === 'user',
|
|
579
|
-
cwd: executionCwd,
|
|
580
|
-
env: options.env,
|
|
581
|
-
signal: options.signal,
|
|
582
|
-
});
|
|
583
|
-
const status = verificationStatus(collected.review.retryPairs, verification);
|
|
584
|
-
if (!addFailed && status === 'succeeded') {
|
|
585
|
-
return {
|
|
586
|
-
...installFailureReceipt(collected.review, '', 'failed', verification, collected.review.retryPairs),
|
|
587
|
-
ok: true,
|
|
588
|
-
status: 'succeeded',
|
|
589
|
-
failures: [],
|
|
590
|
-
};
|
|
591
|
-
}
|
|
592
|
-
const receipt = installFailureReceipt(collected.review, addFailed ? 'portableSkillsCliInstallFailed' : 'portableSkillsCliVerificationFailed', status === 'failed' ? 'failed' : 'partial', verification, collected.review.retryPairs);
|
|
593
|
-
if (verification.unknown.length > 0) {
|
|
594
|
-
receipt.warnings.push('skills list 验证失败,部分目标的结果无法确认。');
|
|
595
|
-
receipt.failures.push({
|
|
596
|
-
code: 'portableSkillsCliVerificationFailed',
|
|
597
|
-
message: 'skills list 验证失败,部分重试结果为 unknown。',
|
|
598
|
-
recovery: '修复 Skills CLI 后先重新检查结果,再决定是否重试。',
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
return receipt;
|
|
602
|
-
}
|
|
603
|
-
finally {
|
|
604
|
-
await collected.materialized.cleanup();
|
|
605
|
-
}
|
|
606
|
-
},
|
|
607
|
-
});
|
|
79
|
+
export function renderPortableReview(_review) {
|
|
80
|
+
return removedPortableWorkflow();
|
|
608
81
|
}
|
|
609
82
|
async function assertNoSymlinks(root) {
|
|
610
83
|
const stats = await fs.lstat(root);
|
|
@@ -638,7 +111,7 @@ async function assertSafeOutputPath(target, options) {
|
|
|
638
111
|
throw new PortableCommandError('portableOutputConflict', '输出目标范围过宽。');
|
|
639
112
|
}
|
|
640
113
|
}
|
|
641
|
-
async function prepareExistingOutput(target, pluginId, sourceIdentity, scope) {
|
|
114
|
+
async function prepareExistingOutput(target, pluginId, sourceIdentity, scope, platform) {
|
|
642
115
|
if (!await fs.pathExists(target))
|
|
643
116
|
return;
|
|
644
117
|
await assertNoSymlinks(target);
|
|
@@ -652,8 +125,9 @@ async function prepareExistingOutput(target, pluginId, sourceIdentity, scope) {
|
|
|
652
125
|
|| marker.plugin?.id !== pluginId
|
|
653
126
|
|| sourceIdentity === undefined
|
|
654
127
|
|| marker.plugin?.sourceIdentity !== sourceIdentity
|
|
655
|
-
|| marker.scope !== scope
|
|
656
|
-
|
|
128
|
+
|| marker.scope !== scope
|
|
129
|
+
|| marker.platform !== platform) {
|
|
130
|
+
throw new PortableCommandError('portableOutputConflict', '已有输出的 pluginId、sourceIdentity、platform 或 scope 不匹配。');
|
|
657
131
|
}
|
|
658
132
|
}
|
|
659
133
|
async function commitOutput(staging, target, expected) {
|
|
@@ -662,7 +136,7 @@ async function commitOutput(staging, target, expected) {
|
|
|
662
136
|
if (existing) {
|
|
663
137
|
await fs.rename(target, backup);
|
|
664
138
|
try {
|
|
665
|
-
await prepareExistingOutput(backup, expected.pluginId, expected.sourceIdentity, expected.scope);
|
|
139
|
+
await prepareExistingOutput(backup, expected.pluginId, expected.sourceIdentity, expected.scope, expected.platform);
|
|
666
140
|
}
|
|
667
141
|
catch {
|
|
668
142
|
const replacement = await fs.lstat(target).catch(() => undefined);
|
|
@@ -685,6 +159,7 @@ async function commitOutput(staging, target, expected) {
|
|
|
685
159
|
await fs.remove(backup).catch(() => undefined);
|
|
686
160
|
}
|
|
687
161
|
export async function materializePortableSkillsToDirectory(options) {
|
|
162
|
+
assertPortablePlatform(options.platform);
|
|
688
163
|
assertScope(options.scope);
|
|
689
164
|
const scope = options.scope;
|
|
690
165
|
const rawTarget = path.resolve(options.cwd, options.out);
|
|
@@ -696,28 +171,33 @@ export async function materializePortableSkillsToDirectory(options) {
|
|
|
696
171
|
await assertSafeOutputPath(target, options);
|
|
697
172
|
const configSnapshot = await readCatalogSourcesConfigSnapshot(options.env);
|
|
698
173
|
const parsedSelector = parsePluginId(options.selector);
|
|
699
|
-
const catalogOperationContext = await resolveCatalogOperationContext({
|
|
174
|
+
const catalogOperationContext = options.catalogOperationContext ?? await resolveCatalogOperationContext({
|
|
700
175
|
...(parsedSelector.sourceId ? { sourceIds: [parsedSelector.sourceId] } : {}),
|
|
701
176
|
env: options.env,
|
|
702
177
|
});
|
|
703
|
-
const materialized = await
|
|
178
|
+
const materialized = await materializePortableSkillsFromCatalog({
|
|
704
179
|
...options,
|
|
705
180
|
scope,
|
|
706
181
|
configSnapshot,
|
|
707
182
|
catalogOperationContext,
|
|
708
183
|
});
|
|
709
184
|
try {
|
|
710
|
-
const selected =
|
|
711
|
-
|
|
185
|
+
const selected = options.allowEmpty && options.requestedSkills === undefined && materialized.candidates.length === 0
|
|
186
|
+
? [] : selectCandidates(materialized.candidates, options.requestedSkills);
|
|
187
|
+
await prepareExistingOutput(target, materialized.pluginId, materialized.sourceIdentity, options.scope, options.platform);
|
|
712
188
|
try {
|
|
713
189
|
await ensureRegularDirectoryPath(path.dirname(target), 'portable output parent');
|
|
714
190
|
}
|
|
715
191
|
catch {
|
|
716
192
|
throw new PortableCommandError('portableOutputConflict', '输出目标的父目录不是安全的普通目录。');
|
|
717
193
|
}
|
|
718
|
-
const
|
|
194
|
+
const stagingPrefix = path.join(path.dirname(target), `.${path.basename(target)}.aw-stage-`);
|
|
195
|
+
// Node's mkdtemp does not add the Windows extended-length prefix itself.
|
|
196
|
+
const createdStaging = await fs.mkdtemp(path.toNamespacedPath(stagingPrefix));
|
|
197
|
+
const staging = path.join(path.dirname(target), path.basename(createdStaging));
|
|
719
198
|
let committed = false;
|
|
720
199
|
try {
|
|
200
|
+
await fs.ensureDir(path.join(staging, 'skills'));
|
|
721
201
|
for (const candidate of selected) {
|
|
722
202
|
await fs.copy(path.join(materialized.rootDir, 'skills', candidate.name), path.join(staging, 'skills', candidate.name), { dereference: false, errorOnExist: true });
|
|
723
203
|
}
|
|
@@ -737,6 +217,7 @@ export async function materializePortableSkillsToDirectory(options) {
|
|
|
737
217
|
...(materialized.sourceIdentity ? { sourceIdentity: materialized.sourceIdentity } : {}),
|
|
738
218
|
...(materialized.pluginVersion ? { version: materialized.pluginVersion } : {}),
|
|
739
219
|
},
|
|
220
|
+
platform: options.platform,
|
|
740
221
|
scope: options.scope,
|
|
741
222
|
out: target,
|
|
742
223
|
selectedSkills: selected,
|
|
@@ -766,7 +247,8 @@ export async function materializePortableSkillsToDirectory(options) {
|
|
|
766
247
|
subject: { plugin: materialized.pluginId.split('/').at(-1) },
|
|
767
248
|
profile: {
|
|
768
249
|
kind: 'portable',
|
|
769
|
-
id:
|
|
250
|
+
id: `${options.platform}-${scope}`,
|
|
251
|
+
platform: options.platform,
|
|
770
252
|
scope,
|
|
771
253
|
inputDigest: materialized.configDigest,
|
|
772
254
|
},
|
|
@@ -786,6 +268,7 @@ export async function materializePortableSkillsToDirectory(options) {
|
|
|
786
268
|
});
|
|
787
269
|
const currentBinding = await resolvePortableCatalogBindingInput({
|
|
788
270
|
selector: options.selector,
|
|
271
|
+
platform: options.platform,
|
|
789
272
|
scope,
|
|
790
273
|
cwd: options.cwd,
|
|
791
274
|
cliVersion: options.cliVersion,
|
|
@@ -801,6 +284,7 @@ export async function materializePortableSkillsToDirectory(options) {
|
|
|
801
284
|
await commitOutput(staging, target, {
|
|
802
285
|
pluginId: materialized.pluginId,
|
|
803
286
|
sourceIdentity: materialized.sourceIdentity,
|
|
287
|
+
platform: options.platform,
|
|
804
288
|
scope: options.scope,
|
|
805
289
|
});
|
|
806
290
|
committed = true;
|