@lesliechan721/aw 0.1.0-beta.7 → 0.1.0-beta.9
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/scripts/add-skill.mjs +4 -4
- package/dist/authoring/scripts/add-skill.mjs.map +1 -1
- package/dist/authoring/scripts/init-plugin.mjs +8 -37
- 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 +77 -90
- package/dist/authoring/scripts/lib/skill-scaffold.mjs +99 -120
- package/dist/authoring/scripts/lib/skill-scaffold.mjs.map +1 -1
- package/dist/authoring/scripts/plugin-status.mjs +8 -11
- package/dist/authoring/scripts/plugin-status.mjs.map +1 -1
- package/dist/authoring/scripts/remove-plugin.mjs +2 -1
- package/dist/authoring/scripts/remove-plugin.mjs.map +1 -1
- package/dist/authoring/scripts/validate-plugin.mjs +64 -758
- package/dist/authoring/scripts/validate-plugin.mjs.map +1 -1
- package/dist/scripts/aw-skill-eval-materializer.d.ts +24 -0
- package/dist/scripts/{plugin-eval-materializer.js → aw-skill-eval-materializer.js} +34 -145
- package/dist/scripts/aw-skill-eval-materializer.js.map +1 -0
- package/dist/scripts/bundle-plugins.d.ts +1 -0
- package/dist/scripts/bundle-plugins.js +2 -1
- package/dist/scripts/bundle-plugins.js.map +1 -1
- package/dist/scripts/plugin-staging.d.ts +6 -8
- package/dist/scripts/plugin-staging.js +15 -28
- package/dist/scripts/plugin-staging.js.map +1 -1
- package/dist/scripts/test-plugin-scripts.js +2 -33
- package/dist/scripts/test-plugin-scripts.js.map +1 -1
- package/dist/src/adapters/helpers.js +2 -2
- package/dist/src/adapters/helpers.js.map +1 -1
- package/dist/src/authoring/workspace-commands.d.ts +17 -1
- package/dist/src/authoring/workspace-commands.js +21 -4
- package/dist/src/authoring/workspace-commands.js.map +1 -1
- package/dist/src/commands/aw-capabilities.d.ts +78 -0
- package/dist/src/commands/aw-capabilities.js +254 -0
- package/dist/src/commands/aw-capabilities.js.map +1 -0
- package/dist/src/commands/catalog-dev-source.d.ts +118 -0
- package/dist/src/commands/catalog-dev-source.js +417 -0
- package/dist/src/commands/catalog-dev-source.js.map +1 -0
- package/dist/src/commands/catalog-generation.d.ts +13 -0
- package/dist/src/commands/catalog-generation.js +13 -0
- package/dist/src/commands/catalog-generation.js.map +1 -0
- package/dist/src/commands/catalog-publication-inspection.d.ts +29 -28
- package/dist/src/commands/catalog-publication-inspection.js +138 -50
- package/dist/src/commands/catalog-publication-inspection.js.map +1 -1
- package/dist/src/commands/catalog-publication-journal.d.ts +49 -0
- package/dist/src/commands/catalog-publication-journal.js +147 -0
- package/dist/src/commands/catalog-publication-journal.js.map +1 -0
- package/dist/src/commands/catalog-publication-target.d.ts +18 -0
- package/dist/src/commands/catalog-publication-target.js +95 -0
- package/dist/src/commands/catalog-publication-target.js.map +1 -0
- package/dist/src/commands/catalog-publish.d.ts +58 -15
- package/dist/src/commands/catalog-publish.js +590 -210
- package/dist/src/commands/catalog-publish.js.map +1 -1
- package/dist/src/commands/catalog-source.d.ts +12 -15
- package/dist/src/commands/catalog-source.js +61 -86
- package/dist/src/commands/catalog-source.js.map +1 -1
- package/dist/src/commands/catalog-status.d.ts +18 -22
- package/dist/src/commands/catalog-status.js +81 -115
- package/dist/src/commands/catalog-status.js.map +1 -1
- package/dist/src/commands/catalog-workspace-resolution.d.ts +13 -0
- package/dist/src/commands/catalog-workspace-resolution.js +42 -0
- package/dist/src/commands/catalog-workspace-resolution.js.map +1 -0
- package/dist/src/commands/dependency-operation-plan.d.ts +88 -9
- package/dist/src/commands/dependency-operation-plan.js +331 -6
- package/dist/src/commands/dependency-operation-plan.js.map +1 -1
- package/dist/src/commands/init.d.ts +5 -11
- package/dist/src/commands/init.js +30 -51
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/offline-cleanup-evidence.d.ts +43 -0
- package/dist/src/commands/offline-cleanup-evidence.js +116 -0
- package/dist/src/commands/offline-cleanup-evidence.js.map +1 -0
- package/dist/src/commands/options.d.ts +7 -1
- package/dist/src/commands/options.js +65 -6
- package/dist/src/commands/options.js.map +1 -1
- package/dist/src/commands/plugin-capabilities.js +5 -1
- package/dist/src/commands/plugin-capabilities.js.map +1 -1
- package/dist/src/commands/rebuild-command.d.ts +27 -13
- package/dist/src/commands/rebuild-command.js +1472 -471
- package/dist/src/commands/rebuild-command.js.map +1 -1
- package/dist/src/commands/rebuild-integration.d.ts +63 -8
- package/dist/src/commands/rebuild-integration.js +761 -439
- package/dist/src/commands/rebuild-integration.js.map +1 -1
- package/dist/src/commands/rebuild-operations.d.ts +2 -8
- package/dist/src/commands/rebuild-operations.js +48 -132
- package/dist/src/commands/rebuild-operations.js.map +1 -1
- package/dist/src/commands/runtime.js +21 -34
- package/dist/src/commands/runtime.js.map +1 -1
- package/dist/src/commands/skill-eval.d.ts +33 -0
- package/dist/src/commands/skill-eval.js +363 -0
- package/dist/src/commands/skill-eval.js.map +1 -0
- package/dist/src/commands/status-v6.d.ts +202 -0
- package/dist/src/commands/status-v6.js +1938 -0
- package/dist/src/commands/status-v6.js.map +1 -0
- package/dist/src/commands/sync-command.d.ts +21 -0
- package/dist/src/commands/sync-command.js +206 -0
- package/dist/src/commands/sync-command.js.map +1 -0
- package/dist/src/commands/wizard.d.ts +2 -2
- package/dist/src/commands/wizard.js +2 -2
- package/dist/src/commands/wizard.js.map +1 -1
- package/dist/src/commands/write-commands.js +33 -19
- package/dist/src/commands/write-commands.js.map +1 -1
- package/dist/src/constants.d.ts +7 -1
- package/dist/src/constants.js +7 -1
- package/dist/src/constants.js.map +1 -1
- package/dist/src/eval/manifest-v1.d.ts +66 -0
- package/dist/src/eval/manifest-v1.js +326 -0
- package/dist/src/eval/manifest-v1.js.map +1 -0
- package/dist/src/generators/local-plugin.d.ts +3 -0
- package/dist/src/generators/local-plugin.js +167 -45
- package/dist/src/generators/local-plugin.js.map +1 -1
- package/dist/src/index.d.ts +6 -1
- package/dist/src/index.js +863 -126
- package/dist/src/index.js.map +1 -1
- package/dist/src/output/command-receipt.d.ts +58 -8
- package/dist/src/output/command-receipt.js +141 -11
- package/dist/src/output/command-receipt.js.map +1 -1
- package/dist/src/output/model.d.ts +3 -44
- package/dist/src/output/model.js +1 -144
- package/dist/src/output/model.js.map +1 -1
- package/dist/src/output/rebuild-progress.js +0 -3
- package/dist/src/output/rebuild-progress.js.map +1 -1
- package/dist/src/portable/commands.d.ts +6 -2
- package/dist/src/portable/commands.js +57 -6
- package/dist/src/portable/commands.js.map +1 -1
- package/dist/src/portable/materializer.d.ts +4 -4
- package/dist/src/portable/materializer.js +61 -12
- package/dist/src/portable/materializer.js.map +1 -1
- package/dist/src/tui/catalog-generation.d.ts +35 -0
- package/dist/src/tui/catalog-generation.js +85 -0
- package/dist/src/tui/catalog-generation.js.map +1 -0
- package/dist/src/tui/components.js +1 -2
- package/dist/src/tui/components.js.map +1 -1
- package/dist/src/tui/console-app-v4.d.ts +1 -1
- package/dist/src/tui/console-app-v4.js +647 -196
- package/dist/src/tui/console-app-v4.js.map +1 -1
- package/dist/src/tui/controller-runtime.d.ts +6 -2
- package/dist/src/tui/controller-runtime.js +646 -137
- package/dist/src/tui/controller-runtime.js.map +1 -1
- package/dist/src/tui/controller.d.ts +77 -15
- package/dist/src/tui/controller.js +647 -306
- package/dist/src/tui/controller.js.map +1 -1
- package/dist/src/tui/diagnostics.d.ts +1 -2
- package/dist/src/tui/diagnostics.js.map +1 -1
- package/dist/src/tui/index.d.ts +1 -0
- package/dist/src/tui/index.js +1 -0
- package/dist/src/tui/index.js.map +1 -1
- package/dist/src/tui/input-display.d.ts +8 -0
- package/dist/src/tui/input-display.js +36 -0
- package/dist/src/tui/input-display.js.map +1 -0
- package/dist/src/tui/model.d.ts +102 -14
- package/dist/src/tui/model.js +630 -139
- package/dist/src/tui/model.js.map +1 -1
- package/dist/src/tui/router.d.ts +35 -0
- package/dist/src/tui/router.js.map +1 -1
- package/dist/src/tui/source-ref-presets.d.ts +3 -0
- package/dist/src/tui/source-ref-presets.js +11 -0
- package/dist/src/tui/source-ref-presets.js.map +1 -0
- package/dist/src/tui/views.js +31 -3
- package/dist/src/tui/views.js.map +1 -1
- package/dist/src/types.d.ts +104 -13
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/agent-version.d.ts +7 -1
- package/dist/src/utils/agent-version.js +41 -8
- package/dist/src/utils/agent-version.js.map +1 -1
- package/dist/src/utils/aw-home-mutation-lock.d.ts +1 -0
- package/dist/src/utils/aw-home-mutation-lock.js +32 -4
- package/dist/src/utils/aw-home-mutation-lock.js.map +1 -1
- package/dist/src/utils/bundle-integrity.d.ts +0 -1
- package/dist/src/utils/bundle-integrity.js +0 -25
- package/dist/src/utils/bundle-integrity.js.map +1 -1
- package/dist/src/utils/bundle-layout.js +8 -6
- package/dist/src/utils/bundle-layout.js.map +1 -1
- package/dist/src/utils/catalog-digests.d.ts +7 -0
- package/dist/src/utils/catalog-digests.js +40 -2
- package/dist/src/utils/catalog-digests.js.map +1 -1
- package/dist/src/utils/catalog-generation-control-snapshot.d.ts +11 -0
- package/dist/src/utils/catalog-generation-control-snapshot.js +45 -0
- package/dist/src/utils/catalog-generation-control-snapshot.js.map +1 -0
- package/dist/src/utils/catalog-generation-error.d.ts +13 -0
- package/dist/src/utils/catalog-generation-error.js +28 -0
- package/dist/src/utils/catalog-generation-error.js.map +1 -0
- package/dist/src/utils/catalog-generation-resolver.d.ts +20 -0
- package/dist/src/utils/catalog-generation-resolver.js +143 -0
- package/dist/src/utils/catalog-generation-resolver.js.map +1 -0
- package/dist/src/utils/catalog-generation-service.d.ts +43 -0
- package/dist/src/utils/catalog-generation-service.js +306 -0
- package/dist/src/utils/catalog-generation-service.js.map +1 -0
- package/dist/src/utils/catalog-generation-state.d.ts +17 -0
- package/dist/src/utils/catalog-generation-state.js +168 -0
- package/dist/src/utils/catalog-generation-state.js.map +1 -0
- package/dist/src/utils/catalog-generation-store.d.ts +34 -0
- package/dist/src/utils/catalog-generation-store.js +251 -0
- package/dist/src/utils/catalog-generation-store.js.map +1 -0
- package/dist/src/utils/catalog-manifest-v6.d.ts +5 -0
- package/dist/src/utils/{catalog-manifest-v4.js → catalog-manifest-v6.js} +35 -43
- package/dist/src/utils/catalog-manifest-v6.js.map +1 -0
- package/dist/src/utils/catalog-operation-context.d.ts +20 -0
- package/dist/src/utils/catalog-operation-context.js +141 -0
- package/dist/src/utils/catalog-operation-context.js.map +1 -0
- package/dist/src/utils/catalog-public-error.d.ts +7 -3
- package/dist/src/utils/catalog-public-error.js +21 -8
- package/dist/src/utils/catalog-public-error.js.map +1 -1
- package/dist/src/utils/catalog-runtime-projection.d.ts +3 -0
- package/dist/src/utils/catalog-runtime-projection.js +5 -40
- package/dist/src/utils/catalog-runtime-projection.js.map +1 -1
- package/dist/src/utils/catalog-snapshot.d.ts +5 -3
- package/dist/src/utils/catalog-snapshot.js +11 -3
- package/dist/src/utils/catalog-snapshot.js.map +1 -1
- package/dist/src/utils/catalog-source-identity.d.ts +1 -0
- package/dist/src/utils/catalog-source-identity.js +21 -2
- package/dist/src/utils/catalog-source-identity.js.map +1 -1
- package/dist/src/utils/catalog-source-references.d.ts +7 -0
- package/dist/src/utils/catalog-source-references.js +44 -55
- package/dist/src/utils/catalog-source-references.js.map +1 -1
- package/dist/src/utils/catalog-sources.d.ts +1 -0
- package/dist/src/utils/catalog-sources.js +55 -20
- package/dist/src/utils/catalog-sources.js.map +1 -1
- package/dist/src/utils/codex-config.d.ts +2 -0
- package/dist/src/utils/codex-config.js +26 -5
- package/dist/src/utils/codex-config.js.map +1 -1
- package/dist/src/utils/codex-manager.d.ts +81 -0
- package/dist/src/utils/codex-manager.js +810 -0
- package/dist/src/utils/codex-manager.js.map +1 -0
- package/dist/src/utils/codex-reconciler.d.ts +131 -0
- package/dist/src/utils/codex-reconciler.js +327 -0
- package/dist/src/utils/codex-reconciler.js.map +1 -0
- package/dist/src/utils/codex-shared-native.d.ts +56 -0
- package/dist/src/utils/codex-shared-native.js +87 -0
- package/dist/src/utils/codex-shared-native.js.map +1 -0
- package/dist/src/utils/codex-skill-staging.d.ts +2 -0
- package/dist/src/utils/codex-skill-staging.js.map +1 -1
- package/dist/src/utils/codex-surface-analysis.d.ts +44 -0
- package/dist/src/utils/codex-surface-analysis.js +247 -0
- package/dist/src/utils/codex-surface-analysis.js.map +1 -0
- package/dist/src/utils/dynamic-skill-tree.d.ts +4 -0
- package/dist/src/utils/dynamic-skill-tree.js +35 -5
- package/dist/src/utils/dynamic-skill-tree.js.map +1 -1
- package/dist/src/utils/git-catalog-provider.js +66 -140
- package/dist/src/utils/git-catalog-provider.js.map +1 -1
- package/dist/src/utils/lifecycle-active-store.d.ts +0 -28
- package/dist/src/utils/lifecycle-active-store.js +35 -247
- package/dist/src/utils/lifecycle-active-store.js.map +1 -1
- package/dist/src/utils/manifest.d.ts +1 -3
- package/dist/src/utils/manifest.js +1 -3
- package/dist/src/utils/manifest.js.map +1 -1
- package/dist/src/utils/multi-source-catalog.d.ts +3 -9
- package/dist/src/utils/multi-source-catalog.js +53 -110
- package/dist/src/utils/multi-source-catalog.js.map +1 -1
- package/dist/src/utils/native-cli.d.ts +49 -6
- package/dist/src/utils/native-cli.js +116 -33
- package/dist/src/utils/native-cli.js.map +1 -1
- package/dist/src/utils/orphan-marketplace-cleanup.js +1 -3
- package/dist/src/utils/orphan-marketplace-cleanup.js.map +1 -1
- package/dist/src/utils/ownership.d.ts +10 -11
- package/dist/src/utils/ownership.js +55 -112
- package/dist/src/utils/ownership.js.map +1 -1
- package/dist/src/utils/path-catalog-provider.d.ts +1 -1
- package/dist/src/utils/path-catalog-provider.js +52 -65
- package/dist/src/utils/path-catalog-provider.js.map +1 -1
- package/dist/src/utils/paths.d.ts +0 -1
- package/dist/src/utils/paths.js +0 -1
- package/dist/src/utils/paths.js.map +1 -1
- package/dist/src/utils/plugin-config-write.js +18 -40
- package/dist/src/utils/plugin-config-write.js.map +1 -1
- package/dist/src/utils/plugin-config.d.ts +1 -12
- package/dist/src/utils/plugin-config.js +107 -226
- package/dist/src/utils/plugin-config.js.map +1 -1
- package/dist/src/utils/plugin-intent-state.d.ts +39 -0
- package/dist/src/utils/plugin-intent-state.js +325 -0
- package/dist/src/utils/plugin-intent-state.js.map +1 -0
- package/dist/src/utils/plugin-scripts.d.ts +1 -1
- package/dist/src/utils/plugin-scripts.js +1 -1
- package/dist/src/utils/plugin-scripts.js.map +1 -1
- package/dist/src/utils/state-paths.js +7 -2
- package/dist/src/utils/state-paths.js.map +1 -1
- package/dist/src/utils/target-eligibility.d.ts +8 -2
- package/dist/src/utils/target-eligibility.js +9 -5
- package/dist/src/utils/target-eligibility.js.map +1 -1
- package/package.json +6 -4
- package/dist/authoring/scripts/check-plugin-versions.d.mts +0 -2
- package/dist/authoring/scripts/check-plugin-versions.mjs +0 -5
- package/dist/authoring/scripts/check-plugin-versions.mjs.map +0 -1
- package/dist/scripts/aw-skill-eval-engine.d.ts +0 -13
- package/dist/scripts/aw-skill-eval-engine.js +0 -31
- package/dist/scripts/aw-skill-eval-engine.js.map +0 -1
- package/dist/scripts/codex-eval-app-server.d.ts +0 -89
- package/dist/scripts/codex-eval-app-server.js +0 -1228
- package/dist/scripts/codex-eval-app-server.js.map +0 -1
- package/dist/scripts/codex-eval-isolation.d.ts +0 -61
- package/dist/scripts/codex-eval-isolation.js +0 -318
- package/dist/scripts/codex-eval-isolation.js.map +0 -1
- package/dist/scripts/codex-eval-process-management.d.ts +0 -8
- package/dist/scripts/codex-eval-process-management.js +0 -69
- package/dist/scripts/codex-eval-process-management.js.map +0 -1
- package/dist/scripts/codex-eval-process-tree.d.ts +0 -38
- package/dist/scripts/codex-eval-process-tree.js +0 -803
- package/dist/scripts/codex-eval-process-tree.js.map +0 -1
- package/dist/scripts/codex-eval-runtime-config.d.ts +0 -62
- package/dist/scripts/codex-eval-runtime-config.js +0 -843
- package/dist/scripts/codex-eval-runtime-config.js.map +0 -1
- package/dist/scripts/codex-trigger-eval.d.ts +0 -84
- package/dist/scripts/codex-trigger-eval.js +0 -968
- package/dist/scripts/codex-trigger-eval.js.map +0 -1
- package/dist/scripts/eval-plugin-skills-audited.d.ts +0 -6
- package/dist/scripts/eval-plugin-skills-audited.js +0 -261
- package/dist/scripts/eval-plugin-skills-audited.js.map +0 -1
- package/dist/scripts/eval-plugin-skills.d.ts +0 -45
- package/dist/scripts/eval-plugin-skills.js +0 -1586
- package/dist/scripts/eval-plugin-skills.js.map +0 -1
- package/dist/scripts/eval-run-layout.d.ts +0 -17
- package/dist/scripts/eval-run-layout.js +0 -26
- package/dist/scripts/eval-run-layout.js.map +0 -1
- package/dist/scripts/plugin-eval-contract.d.ts +0 -185
- package/dist/scripts/plugin-eval-contract.js +0 -695
- package/dist/scripts/plugin-eval-contract.js.map +0 -1
- package/dist/scripts/plugin-eval-materializer.d.ts +0 -13
- package/dist/scripts/plugin-eval-materializer.js.map +0 -1
- package/dist/scripts/skill-reporting.d.ts +0 -212
- package/dist/scripts/skill-reporting.js +0 -922
- package/dist/scripts/skill-reporting.js.map +0 -1
- package/dist/src/commands/status-v4.d.ts +0 -123
- package/dist/src/commands/status-v4.js +0 -905
- package/dist/src/commands/status-v4.js.map +0 -1
- package/dist/src/commands/status.d.ts +0 -93
- package/dist/src/commands/status.js +0 -442
- package/dist/src/commands/status.js.map +0 -1
- package/dist/src/utils/active-marketplace-runtime-lock.d.ts +0 -12
- package/dist/src/utils/active-marketplace-runtime-lock.js +0 -133
- package/dist/src/utils/active-marketplace-runtime-lock.js.map +0 -1
- package/dist/src/utils/catalog-manifest-v3.d.ts +0 -2
- package/dist/src/utils/catalog-manifest-v3.js +0 -3
- package/dist/src/utils/catalog-manifest-v3.js.map +0 -1
- package/dist/src/utils/catalog-manifest-v4.d.ts +0 -5
- package/dist/src/utils/catalog-manifest-v4.js.map +0 -1
- package/dist/src/utils/catalog-source-cache.d.ts +0 -62
- package/dist/src/utils/catalog-source-cache.js +0 -296
- package/dist/src/utils/catalog-source-cache.js.map +0 -1
- package/dist/src/utils/codex-project-surface.d.ts +0 -3
- package/dist/src/utils/codex-project-surface.js +0 -49
- package/dist/src/utils/codex-project-surface.js.map +0 -1
- package/dist/src/utils/plugin-release.d.ts +0 -2
- package/dist/src/utils/plugin-release.js +0 -2
- package/dist/src/utils/plugin-release.js.map +0 -1
package/dist/src/tui/model.js
CHANGED
|
@@ -3,18 +3,156 @@ function compareText(left, right) {
|
|
|
3
3
|
return left.localeCompare(right, 'en');
|
|
4
4
|
}
|
|
5
5
|
function targetHealth(target) {
|
|
6
|
+
if (target.actual?.state === 'ready')
|
|
7
|
+
return 'ready';
|
|
8
|
+
if (target.actual?.state === 'needsSync'
|
|
9
|
+
|| target.actual?.state === 'drifted'
|
|
10
|
+
|| target.actual?.state === 'conflict'
|
|
11
|
+
|| target.actual?.state === 'orphaned'
|
|
12
|
+
|| target.actual?.state === 'unresolved')
|
|
13
|
+
return 'incomplete';
|
|
6
14
|
if (target.state === 'present')
|
|
7
15
|
return 'ready';
|
|
8
16
|
if (target.state === 'partial')
|
|
9
17
|
return 'incomplete';
|
|
10
18
|
return 'error';
|
|
11
19
|
}
|
|
20
|
+
export function isPureNativeCodexTarget(target) {
|
|
21
|
+
return target.platform === 'codex'
|
|
22
|
+
&& target.sharedNative?.shared === true
|
|
23
|
+
&& (target.extensions?.kinds.length ?? 0) === 0;
|
|
24
|
+
}
|
|
25
|
+
function isPureNativeCodexPlacement(placement) {
|
|
26
|
+
return placement.platform === 'codex'
|
|
27
|
+
&& placement.state === 'installed'
|
|
28
|
+
&& placement.sharedNative?.shared === true
|
|
29
|
+
&& (placement.extensions?.kinds.length ?? 0) === 0;
|
|
30
|
+
}
|
|
31
|
+
function parsedScopedUninstallRecovery(recovery, expectedPlatform) {
|
|
32
|
+
if (recovery.command !== 'uninstall' || !recovery.scope)
|
|
33
|
+
return undefined;
|
|
34
|
+
const match = /(?:^|\s)aw uninstall ([^\s]+) --platform (codex|claude) --scope (user|project)(?:,|,|\s|$)/u
|
|
35
|
+
.exec(recovery.description);
|
|
36
|
+
if (!match || match[2] !== expectedPlatform || match[3] !== recovery.scope)
|
|
37
|
+
return undefined;
|
|
38
|
+
return { pluginId: match[1], scope: recovery.scope, description: recovery.description };
|
|
39
|
+
}
|
|
40
|
+
function scopeConflictRecoveryMenuActions(placement) {
|
|
41
|
+
if (placement.actualState !== 'conflict')
|
|
42
|
+
return [];
|
|
43
|
+
return (placement.recovery ?? []).flatMap((recovery) => {
|
|
44
|
+
const parsed = parsedScopedUninstallRecovery(recovery, placement.platform);
|
|
45
|
+
return parsed ? [{
|
|
46
|
+
id: 'resolveScopeConflict',
|
|
47
|
+
pluginId: parsed.pluginId,
|
|
48
|
+
platform: placement.platform,
|
|
49
|
+
scope: parsed.scope,
|
|
50
|
+
keepScope: parsed.scope === 'user' ? 'project' : 'user',
|
|
51
|
+
description: parsed.description,
|
|
52
|
+
}] : [];
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function missingPureNativeScopes(plugin, placement) {
|
|
56
|
+
if (!isPureNativeCodexPlacement(placement) || placement.actualState !== 'ready')
|
|
57
|
+
return [];
|
|
58
|
+
const supported = plugin.supportedScopes?.codex ?? ['user', 'project'];
|
|
59
|
+
return supported.filter((scope) => !placement.desiredScopes?.includes(scope) && placement.activation?.[scope] !== true);
|
|
60
|
+
}
|
|
12
61
|
function isInstalledScopeEvidence(target) {
|
|
13
|
-
return target.
|
|
62
|
+
return target.desired?.enabled === true
|
|
63
|
+
|| target.state === 'present'
|
|
64
|
+
|| target.state === 'partial';
|
|
65
|
+
}
|
|
66
|
+
function dependencyAssignmentExplanation(assignmentSource, requiredBy) {
|
|
67
|
+
const consumer = requiredBy[0];
|
|
68
|
+
return {
|
|
69
|
+
root: '根插件位置',
|
|
70
|
+
default: '推荐使用当前项目',
|
|
71
|
+
existingWiderTarget: '复用健康的所有项目安装',
|
|
72
|
+
userOverride: '你选择的位置',
|
|
73
|
+
consumerPromotion: consumer
|
|
74
|
+
? `因 ${consumer} 的位置而一并调整`
|
|
75
|
+
: '因上游依赖位置而一并调整',
|
|
76
|
+
platformRequirement: '平台只支持这个位置',
|
|
77
|
+
}[assignmentSource];
|
|
78
|
+
}
|
|
79
|
+
export function dependencyPlacementTargets(plan) {
|
|
80
|
+
return plan.targets.filter((target) => target.relation === 'dependency').map((target) => ({
|
|
81
|
+
key: `${target.pluginId}\0${target.platform}`,
|
|
82
|
+
pluginId: target.pluginId,
|
|
83
|
+
displayName: target.pluginName,
|
|
84
|
+
platform: target.platform,
|
|
85
|
+
relation: plan.dependencyEdges.some((edge) => plan.requestedPluginIds.includes(edge.from)
|
|
86
|
+
&& edge.to === target.pluginId
|
|
87
|
+
&& edge.platform === target.platform)
|
|
88
|
+
? 'direct'
|
|
89
|
+
: 'transitive',
|
|
90
|
+
scope: target.resolvedScope,
|
|
91
|
+
minimumScope: target.minimumScope,
|
|
92
|
+
allowedScopes: [...target.allowedScopes],
|
|
93
|
+
locked: (target.locked && target.lockReason !== 'dependencyScopeOverride')
|
|
94
|
+
|| target.allowedScopes.filter((scope) => target.minimumScope === 'project' || scope === 'user').length < 2,
|
|
95
|
+
requiredBy: [...target.requiredBy],
|
|
96
|
+
assignmentSource: target.assignmentSource,
|
|
97
|
+
explanation: dependencyAssignmentExplanation(target.assignmentSource, target.requiredBy),
|
|
98
|
+
affectsOtherProjects: target.affectsOtherProjects,
|
|
99
|
+
action: target.action,
|
|
100
|
+
}));
|
|
14
101
|
}
|
|
15
102
|
function dependencyPluginIdFromMessage(message) {
|
|
16
103
|
return message.match(/(?:[a-z0-9]+(?:-[a-z0-9]+)*)\/(?:[a-z0-9]+(?:-[a-z0-9]+)*)/u)?.[0];
|
|
17
104
|
}
|
|
105
|
+
function rootPlacementFromIssueId(issueId, fallback) {
|
|
106
|
+
if (issueId) {
|
|
107
|
+
for (const platform of ['claude', 'codex']) {
|
|
108
|
+
for (const scope of ['project', 'user']) {
|
|
109
|
+
if (issueId.includes(`:${platform}:${scope}:`)
|
|
110
|
+
|| issueId.endsWith(`:${platform}:${scope}`))
|
|
111
|
+
return { platform, scope };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return fallback;
|
|
116
|
+
}
|
|
117
|
+
function rootPluginIdFromIssueId(issueId, rootIssueCode) {
|
|
118
|
+
if (!issueId || !rootIssueCode || !issueId.startsWith(`${rootIssueCode}:`))
|
|
119
|
+
return undefined;
|
|
120
|
+
for (const platform of ['claude', 'codex']) {
|
|
121
|
+
for (const scope of ['project', 'user']) {
|
|
122
|
+
const marker = `:${platform}:${scope}`;
|
|
123
|
+
const markerIndex = issueId.indexOf(marker, rootIssueCode.length + 1);
|
|
124
|
+
if (markerIndex > rootIssueCode.length + 1) {
|
|
125
|
+
return issueId.slice(rootIssueCode.length + 1, markerIndex);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
function targetIssueRelationship(options) {
|
|
132
|
+
const consumer = options.error?.rootIssueId !== undefined
|
|
133
|
+
&& options.error.rootIssueCode !== undefined
|
|
134
|
+
&& (options.error.code !== options.error.rootIssueCode
|
|
135
|
+
|| options.dependencyPluginId !== undefined
|
|
136
|
+
&& options.dependencyPluginId !== options.target.pluginId);
|
|
137
|
+
if (!consumer) {
|
|
138
|
+
return {
|
|
139
|
+
relationship: 'direct',
|
|
140
|
+
rootEntity: {
|
|
141
|
+
pluginId: options.target.pluginId,
|
|
142
|
+
platform: options.target.platform,
|
|
143
|
+
scope: options.target.scope,
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const placement = rootPlacementFromIssueId(options.error?.rootIssueId, options.target);
|
|
148
|
+
return {
|
|
149
|
+
relationship: 'consumer',
|
|
150
|
+
rootEntity: {
|
|
151
|
+
pluginId: rootPluginIdFromIssueId(options.error?.rootIssueId, options.error?.rootIssueCode) ?? options.dependencyPluginId ?? options.target.pluginId,
|
|
152
|
+
...placement,
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
18
156
|
export function projectPlatformPlacement(platform, targets, revisions = []) {
|
|
19
157
|
const revisionFor = (target) => revisions.find((entry) => entry.pluginId === target.pluginId
|
|
20
158
|
&& entry.platform === target.platform
|
|
@@ -23,6 +161,9 @@ export function projectPlatformPlacement(platform, targets, revisions = []) {
|
|
|
23
161
|
const supportedScopes = [...new Set(targets.map((target) => target.scope))];
|
|
24
162
|
const installed = targets.filter(isInstalledScopeEvidence);
|
|
25
163
|
if (installed.length === 0) {
|
|
164
|
+
if (targets.some((target) => target.errors.some((error) => error.code === 'artifactCollision' && error.severity === 'blocking'))) {
|
|
165
|
+
return { platform, state: 'blocked', supportedScopes, reason: 'artifactCollision' };
|
|
166
|
+
}
|
|
26
167
|
const errorTarget = targets.find((target) => target.state === 'error');
|
|
27
168
|
if (!errorTarget)
|
|
28
169
|
return { platform, state: 'notInstalled', supportedScopes };
|
|
@@ -36,12 +177,25 @@ export function projectPlatformPlacement(platform, targets, revisions = []) {
|
|
|
36
177
|
}
|
|
37
178
|
if (installed.length === 1) {
|
|
38
179
|
const target = installed[0];
|
|
180
|
+
const blockingReason = target.errors.some((error) => error.code === 'artifactCollision' && error.severity === 'blocking')
|
|
181
|
+
? 'artifactCollision'
|
|
182
|
+
: undefined;
|
|
39
183
|
return {
|
|
40
184
|
platform,
|
|
41
185
|
state: 'installed',
|
|
42
186
|
scope: target.scope,
|
|
43
187
|
health: targetHealth(target),
|
|
44
188
|
revision: revisionFor(target),
|
|
189
|
+
...(target.desired ? {
|
|
190
|
+
desiredScopes: [...target.desired.scopes],
|
|
191
|
+
relation: target.desired.relation,
|
|
192
|
+
} : {}),
|
|
193
|
+
...(target.actual ? { actualState: target.actual.state } : {}),
|
|
194
|
+
...(target.activation ? { activation: target.activation } : {}),
|
|
195
|
+
...(target.sharedNative ? { sharedNative: target.sharedNative } : {}),
|
|
196
|
+
...(target.extensions ? { extensions: target.extensions } : {}),
|
|
197
|
+
...(target.recovery ? { recovery: [...target.recovery] } : {}),
|
|
198
|
+
...(blockingReason ? { blockingReason } : {}),
|
|
45
199
|
};
|
|
46
200
|
}
|
|
47
201
|
return {
|
|
@@ -56,11 +210,17 @@ export function projectPlatformPlacement(platform, targets, revisions = []) {
|
|
|
56
210
|
}
|
|
57
211
|
function hasIncompletePlacement(plugin) {
|
|
58
212
|
return plugin.installedPlacements.some((placement) => placement.state === 'scopeConflict'
|
|
59
|
-
|| placement.state === 'installed'
|
|
213
|
+
|| placement.state === 'installed'
|
|
214
|
+
&& (placement.health !== 'ready' || placement.blockingReason !== undefined));
|
|
60
215
|
}
|
|
61
216
|
function hasMissingPlatform(plugin) {
|
|
62
217
|
return plugin.supportedPlatforms.some((platform) => plugin.installedPlacements.find((placement) => placement.platform === platform)?.state === 'notInstalled');
|
|
63
218
|
}
|
|
219
|
+
function allSupportedPlatformsBlocked(plugin) {
|
|
220
|
+
return plugin.supportedPlatforms.length > 0 && plugin.supportedPlatforms.every((platform) => plugin.installedPlacements.some((placement) => placement.platform === platform
|
|
221
|
+
&& (placement.state === 'blocked'
|
|
222
|
+
|| placement.state === 'installed' && placement.blockingReason === 'artifactCollision')));
|
|
223
|
+
}
|
|
64
224
|
function capabilityActions(plugin) {
|
|
65
225
|
return [
|
|
66
226
|
...(plugin.portableSkills ? [{ id: 'portableSkills' }] : []),
|
|
@@ -73,12 +233,22 @@ export function buildPluginPreviewActions(plugin) {
|
|
|
73
233
|
if (plugin.aggregateStatus === 'unavailable') {
|
|
74
234
|
return [{ id: 'sourceProblem' }, ...(installed ? [{ id: 'manage' }] : [])];
|
|
75
235
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
236
|
+
if (allSupportedPlatformsBlocked(plugin)) {
|
|
237
|
+
return [
|
|
238
|
+
{ id: 'outputCollision' },
|
|
239
|
+
...(hasInstalledPlacement(plugin) ? [{ id: 'manage' }] : []),
|
|
240
|
+
{ id: 'source' },
|
|
241
|
+
{ id: 'about' },
|
|
242
|
+
];
|
|
243
|
+
}
|
|
244
|
+
const collisionWithInstallablePlatform = hasMissingPlatform(plugin)
|
|
245
|
+
&& plugin.installedPlacements.some((placement) => placement.state === 'blocked'
|
|
246
|
+
|| placement.state === 'installed' && placement.blockingReason === 'artifactCollision');
|
|
247
|
+
const primary = collisionWithInstallablePlatform
|
|
248
|
+
? { id: 'add' }
|
|
249
|
+
: hasIncompletePlacement(plugin) || (plugin.dependencySummary?.issueCount ?? 0) > 0
|
|
250
|
+
? { id: 'repair' }
|
|
251
|
+
: installed && !hasMissingPlatform(plugin) ? { id: 'manage' } : { id: 'add' };
|
|
82
252
|
return [primary, ...capabilityActions(plugin), { id: 'source' }];
|
|
83
253
|
}
|
|
84
254
|
export function buildPluginDetailActions(plugin) {
|
|
@@ -92,9 +262,12 @@ export function buildPluginDetailActions(plugin) {
|
|
|
92
262
|
];
|
|
93
263
|
}
|
|
94
264
|
return [
|
|
95
|
-
...plugin.installedPlacements.
|
|
96
|
-
|
|
97
|
-
|
|
265
|
+
...plugin.installedPlacements.flatMap((placement) => [
|
|
266
|
+
...(placement.state === 'installed' ? scopeConflictRecoveryMenuActions(placement) : []),
|
|
267
|
+
placement.state === 'scopeConflict'
|
|
268
|
+
? { id: 'scopeConflict', platform: placement.platform }
|
|
269
|
+
: { id: 'platform', platform: placement.platform },
|
|
270
|
+
]),
|
|
98
271
|
...((plugin.dependencySummary?.totalCount ?? 0) > 0 ? [{ id: 'dependencies' }] : []),
|
|
99
272
|
...(plugin.portableSkills ? [{ id: 'portableSkills' }] : []),
|
|
100
273
|
...(plugin.configFieldCount > 0 ? [{ id: 'settings' }] : []),
|
|
@@ -106,13 +279,35 @@ export function buildPlatformActions(plugin, platform) {
|
|
|
106
279
|
return [{ id: 'sourceProblem' }, { id: 'refreshSource' }];
|
|
107
280
|
}
|
|
108
281
|
const placement = plugin.installedPlacements.find((entry) => entry.platform === platform);
|
|
282
|
+
if (placement?.state === 'blocked') {
|
|
283
|
+
return [{ id: 'outputCollision' }, { id: 'source' }, { id: 'about' }];
|
|
284
|
+
}
|
|
109
285
|
if (!placement || placement.state === 'notInstalled')
|
|
110
286
|
return [{ id: 'add' }, { id: 'about' }];
|
|
111
287
|
if (placement.state === 'scopeConflict')
|
|
112
288
|
return [{ id: 'scopeConflict', platform }];
|
|
289
|
+
const scopedRecovery = scopeConflictRecoveryMenuActions(placement);
|
|
290
|
+
if (scopedRecovery.length > 0)
|
|
291
|
+
return [...scopedRecovery, { id: 'technical' }];
|
|
292
|
+
if (placement.blockingReason === 'artifactCollision') {
|
|
293
|
+
return [
|
|
294
|
+
{ id: 'outputCollision' },
|
|
295
|
+
{ id: 'remove', platform, scope: placement.scope },
|
|
296
|
+
{ id: 'technical' },
|
|
297
|
+
];
|
|
298
|
+
}
|
|
113
299
|
if (placement.health === 'error')
|
|
114
300
|
return [{ id: 'technical' }, { id: 'back' }];
|
|
115
301
|
if (placement.health === 'incomplete') {
|
|
302
|
+
if (platform === 'codex'
|
|
303
|
+
&& (placement.actualState === 'needsSync' || placement.actualState === 'drifted'
|
|
304
|
+
|| placement.recovery?.some((action) => action.command === 'sync'))) {
|
|
305
|
+
return [
|
|
306
|
+
{ id: 'sync' },
|
|
307
|
+
{ id: 'technical' },
|
|
308
|
+
{ id: 'remove', platform, scope: placement.scope },
|
|
309
|
+
];
|
|
310
|
+
}
|
|
116
311
|
return [
|
|
117
312
|
{ id: 'reinstall', platform, scope: placement.scope },
|
|
118
313
|
{ id: 'technical' },
|
|
@@ -120,6 +315,9 @@ export function buildPlatformActions(plugin, platform) {
|
|
|
120
315
|
];
|
|
121
316
|
}
|
|
122
317
|
return [
|
|
318
|
+
...missingPureNativeScopes(plugin, placement).map((scope) => ({
|
|
319
|
+
id: 'addScope', platform, scope,
|
|
320
|
+
})),
|
|
123
321
|
...(placement.revision.state === 'upgradeAvailable'
|
|
124
322
|
? [{
|
|
125
323
|
id: 'upgrade',
|
|
@@ -134,63 +332,111 @@ export function buildPlatformActions(plugin, platform) {
|
|
|
134
332
|
];
|
|
135
333
|
}
|
|
136
334
|
export function hasInstalledPlacement(plugin) {
|
|
137
|
-
return plugin.installedPlacements.some((placement) => placement.state
|
|
335
|
+
return plugin.installedPlacements.some((placement) => placement.state === 'installed' || placement.state === 'scopeConflict');
|
|
138
336
|
}
|
|
139
337
|
function sourceState(source, health) {
|
|
140
338
|
if (health?.state === 'ready')
|
|
141
339
|
return 'ready';
|
|
142
|
-
if (health?.state === 'path')
|
|
143
|
-
return 'path';
|
|
144
|
-
if (health?.state === 'degraded')
|
|
145
|
-
return 'cache';
|
|
146
340
|
if (health?.state === 'unavailable')
|
|
147
341
|
return 'error';
|
|
148
342
|
if (source.error)
|
|
149
343
|
return 'error';
|
|
150
|
-
|
|
151
|
-
return 'path';
|
|
152
|
-
return source.freshness === 'cache' ? 'cache' : 'ready';
|
|
344
|
+
return 'ready';
|
|
153
345
|
}
|
|
154
346
|
function sourceIssue(health, impactedTargets = 0) {
|
|
155
|
-
if (health.state !== '
|
|
347
|
+
if (health.state !== 'unavailable')
|
|
156
348
|
return undefined;
|
|
157
|
-
const
|
|
158
|
-
const issueId = health.issueId ?? `source:${health.sourceId}:${cached ? 'cache' : 'unavailable'}`;
|
|
349
|
+
const issueId = health.issueId ?? `source:${health.sourceId}:unavailable`;
|
|
159
350
|
return {
|
|
160
351
|
issueId,
|
|
161
|
-
category:
|
|
162
|
-
title: `${health.sourceId} ·
|
|
163
|
-
explanation:
|
|
164
|
-
|
|
165
|
-
: '来源检查失败,并且没有可用缓存数据。',
|
|
166
|
-
impact: [cached ? '插件仍可浏览,但数据可能不是最新。' : '当前不能浏览或安装这个来源的插件。',
|
|
352
|
+
category: 'sourceUnavailable',
|
|
353
|
+
title: `${health.sourceId} · 来源不可用`,
|
|
354
|
+
explanation: '来源检查失败。',
|
|
355
|
+
impact: ['当前不能浏览或安装这个来源的插件。',
|
|
167
356
|
...(impactedTargets > 0 ? [`${impactedTargets} 个安装位置受此来源根问题影响。`] : [])],
|
|
168
357
|
entity: { kind: 'source', id: health.sourceId },
|
|
169
358
|
sourceId: health.sourceId,
|
|
170
|
-
actions:
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
]
|
|
176
|
-
: [
|
|
177
|
-
{ id: 'editSource', label: '编辑来源', description: '检查 URL、路径或 ref' },
|
|
178
|
-
{ id: 'refreshSource', label: '稍后重试', description: '只重新检查来源' },
|
|
179
|
-
{ id: 'viewTechnical', label: '技术详情' },
|
|
180
|
-
],
|
|
359
|
+
actions: [
|
|
360
|
+
{ id: 'editSource', label: '编辑来源', description: '检查 URL、路径或 ref' },
|
|
361
|
+
{ id: 'refreshSource', label: '稍后重试', description: '只重新检查来源' },
|
|
362
|
+
{ id: 'viewTechnical', label: '技术详情' },
|
|
363
|
+
],
|
|
181
364
|
technicalDetails: [{
|
|
182
|
-
code:
|
|
183
|
-
message:
|
|
365
|
+
code: 'catalogSourceUnavailable',
|
|
366
|
+
message: '来源检查失败。',
|
|
184
367
|
}],
|
|
185
368
|
};
|
|
186
369
|
}
|
|
187
370
|
function targetIssues(payload) {
|
|
188
371
|
const issues = [];
|
|
189
372
|
const byPlacement = new Map();
|
|
373
|
+
const canonicalRootsByEntity = new Map();
|
|
374
|
+
for (const target of payload.targets) {
|
|
375
|
+
for (const error of target.errors) {
|
|
376
|
+
if (!error.rootIssueId || !error.rootIssueCode)
|
|
377
|
+
continue;
|
|
378
|
+
const dependencyPluginId = error.dependencyPluginId
|
|
379
|
+
?? dependencyPluginIdFromMessage(error.message);
|
|
380
|
+
const relationship = targetIssueRelationship({ target, error, dependencyPluginId });
|
|
381
|
+
if (relationship.relationship !== 'consumer')
|
|
382
|
+
continue;
|
|
383
|
+
const key = [
|
|
384
|
+
error.rootIssueCode,
|
|
385
|
+
relationship.rootEntity.pluginId,
|
|
386
|
+
relationship.rootEntity.platform,
|
|
387
|
+
relationship.rootEntity.scope,
|
|
388
|
+
].join('\0');
|
|
389
|
+
const current = canonicalRootsByEntity.get(key);
|
|
390
|
+
if (!current || compareText(error.rootIssueId, current) < 0) {
|
|
391
|
+
canonicalRootsByEntity.set(key, error.rootIssueId);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
190
395
|
for (const target of payload.targets) {
|
|
191
396
|
const key = `${target.pluginId}\0${target.platform}`;
|
|
192
397
|
byPlacement.set(key, [...(byPlacement.get(key) ?? []), target]);
|
|
193
|
-
|
|
398
|
+
const scopedConflictRecovery = target.actual?.state === 'conflict'
|
|
399
|
+
? target.recovery.flatMap((recovery) => {
|
|
400
|
+
const parsed = parsedScopedUninstallRecovery(recovery, target.platform);
|
|
401
|
+
return parsed ? [{ ...parsed, keepScope: parsed.scope === 'user'
|
|
402
|
+
? 'project' : 'user' }] : [];
|
|
403
|
+
})
|
|
404
|
+
: [];
|
|
405
|
+
if (scopedConflictRecovery.length > 0) {
|
|
406
|
+
issues.push({
|
|
407
|
+
issueId: `scope:${target.pluginId}:${target.platform}`,
|
|
408
|
+
category: 'scopeConflict',
|
|
409
|
+
title: `${target.pluginId} · ${target.platform === 'codex' ? 'Codex' : 'Claude Code'} · 扩展位置冲突`,
|
|
410
|
+
explanation: 'AW-only 扩展不能同时使用所有项目和当前项目位置。',
|
|
411
|
+
impact: ['选择一条 root uninstall 路径,然后按该路径同步保留的 scope。'],
|
|
412
|
+
entity: { kind: 'plugin', id: target.pluginId },
|
|
413
|
+
pluginId: target.pluginId,
|
|
414
|
+
platform: target.platform,
|
|
415
|
+
scope: target.scope,
|
|
416
|
+
sourceId: target.sourceId,
|
|
417
|
+
sourceIdentity: target.sourceIdentity,
|
|
418
|
+
placements: [...target.desired.scopes].sort(compareText),
|
|
419
|
+
actions: [
|
|
420
|
+
...scopedConflictRecovery.map((recovery) => ({
|
|
421
|
+
id: recovery.keepScope === 'user' ? 'keepUserScope' : 'keepProjectScope',
|
|
422
|
+
label: `保留${recovery.keepScope === 'user' ? '所有项目' : '当前项目'}`,
|
|
423
|
+
description: recovery.description,
|
|
424
|
+
pluginId: recovery.pluginId,
|
|
425
|
+
platform: target.platform,
|
|
426
|
+
scope: recovery.scope,
|
|
427
|
+
writeAction: 'uninstall',
|
|
428
|
+
})),
|
|
429
|
+
{ id: 'viewTechnical', label: '查看冲突详情' },
|
|
430
|
+
],
|
|
431
|
+
technicalDetails: [{
|
|
432
|
+
code: 'codexExtensionScopeConflict',
|
|
433
|
+
message: 'mixed 或 AW-only 扩展同时使用两个 scope。',
|
|
434
|
+
}],
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
if (target.state !== 'partial' && target.state !== 'error'
|
|
438
|
+
&& !target.errors.some((error) => error.code === 'artifactCollision'
|
|
439
|
+
|| error.dependencyPluginId !== undefined && error.rootIssueId !== undefined))
|
|
194
440
|
continue;
|
|
195
441
|
const codes = new Set(target.errors.map((error) => error.code));
|
|
196
442
|
const dependencyCodes = [
|
|
@@ -200,41 +446,66 @@ function targetIssues(payload) {
|
|
|
200
446
|
'dependencyStillRequired',
|
|
201
447
|
'dependencyGraphInvalid',
|
|
202
448
|
];
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
449
|
+
const dependencyRootMap = new Map();
|
|
450
|
+
for (const error of target.errors) {
|
|
451
|
+
if (!dependencyCodes.includes(error.code))
|
|
452
|
+
continue;
|
|
453
|
+
if (error.rootIssueCode === 'artifactCollision') {
|
|
454
|
+
dependencyRootMap.set(error.rootIssueId ?? `artifactCollision\0${error.dependencyPluginId ?? ''}`, {
|
|
455
|
+
code: 'artifactCollision',
|
|
456
|
+
category: 'artifactCollision',
|
|
457
|
+
mergeEligible: false,
|
|
458
|
+
error,
|
|
459
|
+
dependencyPluginId: error.dependencyPluginId,
|
|
460
|
+
});
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
const code = error.code;
|
|
464
|
+
const dependencyPluginId = error.dependencyPluginId ?? dependencyPluginIdFromMessage(error.message);
|
|
465
|
+
dependencyRootMap.set(`${code}\0${dependencyPluginId ?? ''}`, {
|
|
466
|
+
code,
|
|
467
|
+
category: code,
|
|
468
|
+
mergeEligible: false,
|
|
469
|
+
error,
|
|
470
|
+
dependencyPluginId,
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
const dependencyRoots = [...dependencyRootMap.values()];
|
|
474
|
+
const directCollision = target.errors.find((error) => error.code === 'artifactCollision');
|
|
475
|
+
const projectedCollisionRoots = dependencyRoots.filter((root) => root.code === 'artifactCollision');
|
|
476
|
+
const ordinaryDependencyRoots = dependencyRoots.filter((root) => root.code !== 'artifactCollision');
|
|
477
|
+
const roots = codes.has('sourceMissing')
|
|
478
|
+
? [{ code: 'sourceMissing', category: 'sourceMissing', mergeEligible: false }]
|
|
479
|
+
: directCollision || projectedCollisionRoots.length > 0
|
|
480
|
+
? [{
|
|
481
|
+
code: 'artifactCollision',
|
|
482
|
+
category: 'artifactCollision',
|
|
483
|
+
mergeEligible: false,
|
|
484
|
+
error: directCollision ?? projectedCollisionRoots[0].error,
|
|
485
|
+
dependencyPluginId: projectedCollisionRoots[0]?.dependencyPluginId,
|
|
486
|
+
}]
|
|
487
|
+
: codes.has('sourceChanged')
|
|
488
|
+
? [{ code: 'sourceChanged', category: 'sourceIdentityChanged', mergeEligible: false }]
|
|
489
|
+
: codes.has('catalogSourceUnavailable') || codes.has('bundleUnavailable')
|
|
490
|
+
? [
|
|
225
491
|
...(codes.has('catalogSourceUnavailable')
|
|
226
492
|
? [{ code: 'catalogSourceUnavailable', category: 'sourceUnavailable', mergeEligible: true }]
|
|
227
493
|
: []),
|
|
228
494
|
...(codes.has('bundleUnavailable')
|
|
229
495
|
? [{ code: 'bundleUnavailable', category: 'sourceUnavailable', mergeEligible: false }]
|
|
230
496
|
: []),
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
497
|
+
]
|
|
498
|
+
: ordinaryDependencyRoots.length > 0
|
|
499
|
+
? ordinaryDependencyRoots
|
|
500
|
+
: target.state === 'partial'
|
|
501
|
+
? [{ code: 'partial', category: 'incompleteInstallation', mergeEligible: false }]
|
|
502
|
+
: [
|
|
503
|
+
{ code: 'targetDiagnostic', category: 'diagnostic', mergeEligible: false },
|
|
504
|
+
];
|
|
235
505
|
for (const root of roots) {
|
|
236
506
|
const rootError = root.error ?? target.errors.find((error) => error.code === root.code);
|
|
237
507
|
const dependencyPluginId = root.dependencyPluginId
|
|
508
|
+
?? rootError?.dependencyPluginId
|
|
238
509
|
?? (rootError ? dependencyPluginIdFromMessage(rootError.message) : undefined);
|
|
239
510
|
const dependencyCategory = root.category.startsWith('dependency');
|
|
240
511
|
const actions = root.category === 'dependencyMissing'
|
|
@@ -259,60 +530,98 @@ function targetIssues(payload) {
|
|
|
259
530
|
{ id: 'viewDependencies', label: '查看依赖关系' },
|
|
260
531
|
{ id: 'viewTechnical', label: '技术详情' },
|
|
261
532
|
]
|
|
262
|
-
: root.category === '
|
|
533
|
+
: root.category === 'artifactCollision'
|
|
263
534
|
? [
|
|
264
|
-
{ id: '
|
|
265
|
-
{ id: '
|
|
266
|
-
{ id: 'viewTechnical', label: '技术详情' },
|
|
535
|
+
{ id: 'viewTechnical', label: '查看冲突原因' },
|
|
536
|
+
{ id: 'retryLater', label: '处理冲突后重试' },
|
|
267
537
|
]
|
|
268
|
-
: root.category === '
|
|
538
|
+
: root.category === 'incompleteInstallation'
|
|
269
539
|
? [
|
|
270
|
-
{ id: '
|
|
540
|
+
{ id: 'reinstall', label: '重新安装', description: '保留插件设置,重新生成缺失内容' },
|
|
541
|
+
{ id: 'remove', label: '移除安装', description: '保留插件设置' },
|
|
271
542
|
{ id: 'viewTechnical', label: '技术详情' },
|
|
272
543
|
]
|
|
273
|
-
: root.category === '
|
|
544
|
+
: root.category === 'sourceMissing'
|
|
274
545
|
? [
|
|
275
|
-
{ id: '
|
|
546
|
+
{ id: 'cleanup', label: '清理已安装内容', description: '只清理 matching owner 的现场内容;保留插件设置', writeAction: 'cleanup' },
|
|
547
|
+
{ id: 'reAddSource', label: '重新添加同一来源', description: '保留来源 ID;来源类型和位置由你选择' },
|
|
276
548
|
{ id: 'viewTechnical', label: '技术详情' },
|
|
277
549
|
]
|
|
278
|
-
: root.category === '
|
|
550
|
+
: root.category === 'sourceIdentityChanged'
|
|
279
551
|
? [
|
|
280
|
-
|
|
281
|
-
id: 'cleanup',
|
|
282
|
-
label: '清理已安装内容',
|
|
283
|
-
description: '只清理 AW 管理的现场内容;保留插件设置',
|
|
284
|
-
writeAction: 'cleanup',
|
|
285
|
-
}] : []),
|
|
286
|
-
{ id: 'editSource', label: '查看来源', description: root.code === 'bundleUnavailable' ? '检查当前 Catalog 或稍后重试' : '修复来源配置或稍后重试' },
|
|
552
|
+
{ id: 'viewSourceChange', label: '查看来源变更', description: '不会自动覆盖现场状态' },
|
|
287
553
|
{ id: 'viewTechnical', label: '技术详情' },
|
|
288
554
|
]
|
|
289
|
-
:
|
|
290
|
-
|
|
555
|
+
: root.category === 'sourceUnavailable'
|
|
556
|
+
? [
|
|
557
|
+
...(root.code === 'bundleUnavailable' ? [{
|
|
558
|
+
id: 'cleanup',
|
|
559
|
+
label: '清理已安装内容',
|
|
560
|
+
description: '只清理 AW 管理的现场内容;保留插件设置',
|
|
561
|
+
writeAction: 'cleanup',
|
|
562
|
+
}] : []),
|
|
563
|
+
{ id: 'editSource', label: '查看来源', description: root.code === 'bundleUnavailable' ? '检查当前 Catalog 或稍后重试' : '修复来源配置或稍后重试' },
|
|
564
|
+
{ id: 'viewTechnical', label: '技术详情' },
|
|
565
|
+
]
|
|
566
|
+
: [{ id: 'viewTechnical', label: '技术详情' }, { id: 'retryLater', label: '稍后重试' }];
|
|
291
567
|
const bundleUnavailable = root.code === 'bundleUnavailable';
|
|
568
|
+
const relationship = targetIssueRelationship({
|
|
569
|
+
target,
|
|
570
|
+
error: rootError,
|
|
571
|
+
dependencyPluginId,
|
|
572
|
+
});
|
|
573
|
+
const directRootCode = root.code === 'partial' ? 'incompleteInstallation'
|
|
574
|
+
: root.code === 'targetDiagnostic' ? 'diagnostic'
|
|
575
|
+
: undefined;
|
|
576
|
+
const canonicalRoot = relationship.relationship === 'direct' && directRootCode
|
|
577
|
+
? canonicalRootsByEntity.get([
|
|
578
|
+
directRootCode,
|
|
579
|
+
relationship.rootEntity.pluginId,
|
|
580
|
+
relationship.rootEntity.platform,
|
|
581
|
+
relationship.rootEntity.scope,
|
|
582
|
+
].join('\0'))
|
|
583
|
+
: undefined;
|
|
584
|
+
const issueId = rootError?.rootIssueId
|
|
585
|
+
?? canonicalRoot
|
|
586
|
+
?? (directRootCode
|
|
587
|
+
? `${directRootCode}:${target.pluginId}:${target.platform}:${target.scope}`
|
|
588
|
+
: `target:${target.pluginId}:${target.platform}:${target.scope}:${target.state}${roots.length > 1 ? `:${root.code}` : ''}${dependencyPluginId ? `:${dependencyPluginId}` : ''}`);
|
|
292
589
|
issues.push({
|
|
293
590
|
issueId,
|
|
294
591
|
category: root.category,
|
|
295
592
|
rootCode: root.code,
|
|
296
593
|
mergeEligible: root.mergeEligible,
|
|
297
|
-
|
|
594
|
+
relationship: relationship.relationship,
|
|
595
|
+
rootEntity: relationship.rootEntity,
|
|
596
|
+
affectedTargets: [{
|
|
597
|
+
pluginId: target.pluginId,
|
|
598
|
+
platform: target.platform,
|
|
599
|
+
scope: target.scope,
|
|
600
|
+
relationship: relationship.relationship,
|
|
601
|
+
}],
|
|
602
|
+
title: `${target.pluginId} · ${target.platform === 'codex' ? 'Codex' : 'Claude Code'} · ${root.category === 'artifactCollision' ? '输出冲突' : dependencyCategory ? {
|
|
298
603
|
dependencyMissing: '缺少依赖',
|
|
299
604
|
dependencyNotReady: '依赖安装不完整',
|
|
300
605
|
dependencyTargetUnsupported: '依赖目标不兼容',
|
|
301
606
|
dependencyStillRequired: '依赖仍被使用',
|
|
302
607
|
dependencyGraphInvalid: '依赖关系无效',
|
|
303
608
|
}[root.category] : target.state === 'partial' ? '安装不完整' : bundleUnavailable ? '当前 Catalog 不再包含此插件' : '检查失败'}`,
|
|
304
|
-
explanation:
|
|
305
|
-
?
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
609
|
+
explanation: root.category === 'artifactCollision'
|
|
610
|
+
? '目标位置已有不属于当前插件的内容。AW 不会覆盖或删除这些内容。'
|
|
611
|
+
: dependencyCategory
|
|
612
|
+
? dependencyPluginId
|
|
613
|
+
? `${dependencyPluginId} 导致当前依赖检查不能通过。`
|
|
614
|
+
: '当前依赖检查不能安全通过。'
|
|
615
|
+
: target.state === 'partial'
|
|
616
|
+
? '必要内容缺失,插件可能不能稳定运行。'
|
|
617
|
+
: bundleUnavailable
|
|
618
|
+
? '当前 Catalog 不再包含此插件,但仍发现 AW 管理的已安装内容。'
|
|
619
|
+
: '当前目标不能安全分类为正常安装。',
|
|
620
|
+
impact: [root.category === 'artifactCollision'
|
|
621
|
+
? '请先移除或迁移冲突内容,然后重试安装或重新安装。'
|
|
310
622
|
: bundleUnavailable
|
|
311
|
-
? '
|
|
312
|
-
: '
|
|
313
|
-
impact: [bundleUnavailable
|
|
314
|
-
? '可以清理可信的 AW 现场;这不表示来源缓存整体不可用。'
|
|
315
|
-
: '写操作前需要重新检查这个目标。'],
|
|
623
|
+
? '可以清理可信的 AW 现场;这不表示来源整体可用。'
|
|
624
|
+
: '写操作前需要重新检查这个目标。'],
|
|
316
625
|
entity: { kind: 'plugin', id: target.pluginId },
|
|
317
626
|
pluginId: target.pluginId,
|
|
318
627
|
...(dependencyPluginId ? { dependencyPluginId } : {}),
|
|
@@ -324,8 +633,18 @@ function targetIssues(payload) {
|
|
|
324
633
|
technicalDetails: target.errors.length > 0
|
|
325
634
|
? target.errors.filter((error) => root.code === 'targetDiagnostic'
|
|
326
635
|
|| root.code === 'partial'
|
|
327
|
-
|| error.code === root.code
|
|
328
|
-
|
|
636
|
+
|| error.code === root.code
|
|
637
|
+
|| error.rootIssueId === issueId)
|
|
638
|
+
.map((error) => ({
|
|
639
|
+
code: error.code,
|
|
640
|
+
message: error.collision
|
|
641
|
+
? ({
|
|
642
|
+
ownerMismatch: '目标由其他 owner 占用。',
|
|
643
|
+
unownedContent: '目标包含没有 AW owner 标记的内容。',
|
|
644
|
+
typeMismatch: '目标节点类型不符合预期。',
|
|
645
|
+
})[error.collision.reason]
|
|
646
|
+
: '状态检查报告了这个安全错误代码。',
|
|
647
|
+
}))
|
|
329
648
|
: [{ code: 'targetStateError', message: '目标状态异常。' }],
|
|
330
649
|
});
|
|
331
650
|
}
|
|
@@ -459,6 +778,39 @@ function configIssues(pluginSummaries) {
|
|
|
459
778
|
}];
|
|
460
779
|
});
|
|
461
780
|
}
|
|
781
|
+
function dependencyOverviewIssues(overviews, pluginSummaries, status) {
|
|
782
|
+
const summaryById = new Map(pluginSummaries.map((summary) => [summary.pluginId, summary]));
|
|
783
|
+
return overviews.flatMap((overview) => overview.blockers.flatMap((blocker) => {
|
|
784
|
+
if (blocker.code !== 'dependencyGraphInvalid'
|
|
785
|
+
&& blocker.code !== 'dependencyTargetUnsupported')
|
|
786
|
+
return [];
|
|
787
|
+
if (status.targets.some((target) => target.pluginId === overview.pluginId
|
|
788
|
+
&& target.errors.some((error) => error.code === blocker.code)))
|
|
789
|
+
return [];
|
|
790
|
+
const summary = summaryById.get(overview.pluginId);
|
|
791
|
+
const sourceId = overview.pluginId.slice(0, overview.pluginId.indexOf('/'));
|
|
792
|
+
const category = blocker.code;
|
|
793
|
+
return [{
|
|
794
|
+
issueId: `dependency:${overview.pluginId}:${blocker.code}`,
|
|
795
|
+
category,
|
|
796
|
+
rootCode: category,
|
|
797
|
+
mergeEligible: false,
|
|
798
|
+
title: `${summary?.displayName ?? summary?.pluginName ?? overview.pluginId} · ${blocker.title}`,
|
|
799
|
+
explanation: blocker.explanation,
|
|
800
|
+
impact: [category === 'dependencyGraphInvalid'
|
|
801
|
+
? '修复依赖关系后才能安全计算安装顺序。'
|
|
802
|
+
: '当前不能在所有声明的平台上安全安装这个插件。'],
|
|
803
|
+
entity: { kind: 'plugin', id: overview.pluginId },
|
|
804
|
+
pluginId: overview.pluginId,
|
|
805
|
+
sourceId,
|
|
806
|
+
actions: [
|
|
807
|
+
{ id: 'viewDependencies', label: '查看依赖关系' },
|
|
808
|
+
{ id: 'viewTechnical', label: '技术详情' },
|
|
809
|
+
],
|
|
810
|
+
technicalDetails: [{ code: blocker.code, message: blocker.explanation }],
|
|
811
|
+
}];
|
|
812
|
+
}));
|
|
813
|
+
}
|
|
462
814
|
function enrichDependencyIssuePlacements(issues, overviews) {
|
|
463
815
|
const overviewById = new Map(overviews.map((overview) => [overview.pluginId, overview]));
|
|
464
816
|
return issues.map((issue) => {
|
|
@@ -506,46 +858,39 @@ function enrichDependencyIssuePlacements(issues, overviews) {
|
|
|
506
858
|
}
|
|
507
859
|
function issueDiagnostic(issue, sourceDetails) {
|
|
508
860
|
const source = issue.sourceId ? sourceDetails.get(issue.sourceId) : undefined;
|
|
509
|
-
const sourceDegraded = issue.category === 'sourceDegraded';
|
|
510
861
|
const sourceUnavailable = issue.category === 'sourceUnavailable' && issue.entity.kind === 'source';
|
|
511
862
|
const configUnavailable = issue.category === 'diagnostic' && issue.issueId.startsWith('config:');
|
|
512
863
|
const configInvalid = issue.category === 'requiredConfigMissing';
|
|
513
864
|
const dependency = issue.category.startsWith('dependency');
|
|
514
865
|
const platformState = issue.issueId.startsWith('status:') || issue.rootCode === 'targetDiagnostic';
|
|
515
|
-
const preserved =
|
|
866
|
+
const preserved = sourceUnavailable
|
|
516
867
|
? '已安装插件和已保存设置不会被删除。'
|
|
517
868
|
: configUnavailable
|
|
518
869
|
? '已保存的设置保持不变。'
|
|
519
870
|
: '现有安装和已保存设置不会因本页自动改变。';
|
|
520
|
-
const impact =
|
|
871
|
+
const impact = sourceUnavailable
|
|
521
872
|
? [
|
|
522
|
-
{ state: '
|
|
873
|
+
{ state: 'blocked', message: '当前不能浏览或安装这个来源中的插件。' },
|
|
523
874
|
{ state: 'preserved', message: preserved },
|
|
524
875
|
]
|
|
525
|
-
:
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
:
|
|
531
|
-
|
|
532
|
-
state: dependency || configUnavailable || configInvalid || platformState ? 'blocked' : 'degraded',
|
|
533
|
-
message,
|
|
534
|
-
})),
|
|
535
|
-
{ state: 'preserved', message: preserved },
|
|
536
|
-
];
|
|
876
|
+
: [
|
|
877
|
+
...issue.impact.map((message) => ({
|
|
878
|
+
state: dependency || configUnavailable || configInvalid || platformState ? 'blocked' : 'degraded',
|
|
879
|
+
message,
|
|
880
|
+
})),
|
|
881
|
+
{ state: 'preserved', message: preserved },
|
|
882
|
+
];
|
|
537
883
|
const primaryAction = issue.actions.find((action) => action.id !== 'viewTechnical');
|
|
538
884
|
const nextStep = primaryAction
|
|
539
885
|
? `${primaryAction.label},然后重新检查当前状态。`
|
|
540
886
|
: '打开技术详情,记录安全错误代码后重新检查。';
|
|
541
|
-
const sourceDiagnostic =
|
|
887
|
+
const sourceDiagnostic = sourceUnavailable;
|
|
542
888
|
const rawCode = sourceDiagnostic
|
|
543
889
|
? source?.errorCode ?? issue.technicalDetails[0]?.code
|
|
544
890
|
: issue.technicalDetails[0]?.code;
|
|
545
|
-
const code = safeDiagnosticCode(rawCode,
|
|
546
|
-
? '
|
|
547
|
-
|
|
548
|
-
const stage = sourceDegraded || sourceUnavailable ? 'resolve-source'
|
|
891
|
+
const code = safeDiagnosticCode(rawCode, sourceUnavailable
|
|
892
|
+
? 'catalogSourceUnavailable' : 'diagnosticUnavailable');
|
|
893
|
+
const stage = sourceUnavailable ? 'resolve-source'
|
|
549
894
|
: configUnavailable ? 'read-config'
|
|
550
895
|
: configInvalid ? 'validate-config'
|
|
551
896
|
: dependency ? 'resolve-dependencies'
|
|
@@ -557,9 +902,6 @@ function issueDiagnostic(issue, sourceDetails) {
|
|
|
557
902
|
: []),
|
|
558
903
|
...(issue.platform ? [{ key: 'platform', value: issue.platform }] : []),
|
|
559
904
|
...(issue.scope ? [{ key: 'scope', value: issue.scope }] : []),
|
|
560
|
-
...(sourceDiagnostic && source?.freshness
|
|
561
|
-
? [{ key: 'freshness', value: source.freshness }]
|
|
562
|
-
: []),
|
|
563
905
|
...(issue.requiredFields?.slice(0, 1).map((field) => ({
|
|
564
906
|
key: 'field',
|
|
565
907
|
value: field.title,
|
|
@@ -573,7 +915,7 @@ function issueDiagnostic(issue, sourceDetails) {
|
|
|
573
915
|
'按技术详情使用受支持命令或人工处理。',
|
|
574
916
|
'再次运行状态检查。',
|
|
575
917
|
]
|
|
576
|
-
:
|
|
918
|
+
: sourceUnavailable
|
|
577
919
|
? ['检查 Git URL、ref 或本地目录。', '确认当前终端具备来源授权。', '运行“重新检查来源”验证修复。']
|
|
578
920
|
: dependency
|
|
579
921
|
? ['检查依赖关系和依赖插件状态。', '完成恢复动作后重新检查根插件。']
|
|
@@ -583,7 +925,7 @@ function issueDiagnostic(issue, sourceDetails) {
|
|
|
583
925
|
? ['完成或修正列出的设置字段。', '重新检查插件设置。']
|
|
584
926
|
: ['检查目标平台配置和访问权限。', '完成恢复动作后重新运行状态检查。'];
|
|
585
927
|
return {
|
|
586
|
-
severity:
|
|
928
|
+
severity: 'error',
|
|
587
929
|
title: issue.title,
|
|
588
930
|
userMessage: issue.explanation,
|
|
589
931
|
impact,
|
|
@@ -594,14 +936,110 @@ function issueDiagnostic(issue, sourceDetails) {
|
|
|
594
936
|
...(sourceDiagnostic && issue.sourceId ? { sourceId: issue.sourceId } : {}),
|
|
595
937
|
...(sourceDiagnostic && source?.requestedRef ? { requestedRef: source.requestedRef } : {}),
|
|
596
938
|
...(sourceDiagnostic && source?.resolvedCommit ? { resolvedCommit: source.resolvedCommit } : {}),
|
|
597
|
-
...(sourceDegraded || sourceUnavailable
|
|
598
|
-
? { lastGood: sourceDegraded ? 'available' : 'unavailable' }
|
|
599
|
-
: {}),
|
|
600
939
|
...(context.length > 0 ? { context } : {}),
|
|
601
940
|
checks,
|
|
602
941
|
},
|
|
603
942
|
};
|
|
604
943
|
}
|
|
944
|
+
const issueGroupOrder = {
|
|
945
|
+
sourceRemoved: 0,
|
|
946
|
+
artifactCollision: 1,
|
|
947
|
+
sourceUnavailable: 2,
|
|
948
|
+
dependency: 3,
|
|
949
|
+
scope: 4,
|
|
950
|
+
config: 5,
|
|
951
|
+
installation: 6,
|
|
952
|
+
diagnostic: 7,
|
|
953
|
+
};
|
|
954
|
+
function issueGroup(issue) {
|
|
955
|
+
if (issue.category === 'sourceMissing')
|
|
956
|
+
return 'sourceRemoved';
|
|
957
|
+
if (issue.category === 'artifactCollision')
|
|
958
|
+
return 'artifactCollision';
|
|
959
|
+
if (issue.category === 'sourceUnavailable'
|
|
960
|
+
|| issue.category === 'sourceIdentityChanged')
|
|
961
|
+
return 'sourceUnavailable';
|
|
962
|
+
if (issue.category.startsWith('dependency'))
|
|
963
|
+
return 'dependency';
|
|
964
|
+
if (issue.category === 'scopeConflict')
|
|
965
|
+
return 'scope';
|
|
966
|
+
if (issue.category === 'requiredConfigMissing')
|
|
967
|
+
return 'config';
|
|
968
|
+
if (issue.category === 'incompleteInstallation')
|
|
969
|
+
return 'installation';
|
|
970
|
+
return 'diagnostic';
|
|
971
|
+
}
|
|
972
|
+
function primaryAttentionCode(issue) {
|
|
973
|
+
if (issue.category === 'requiredConfigMissing') {
|
|
974
|
+
return issue.requiredFields?.some((field) => field.type === 'invalid-config')
|
|
975
|
+
? 'invalidConfig'
|
|
976
|
+
: 'requiredConfigMissing';
|
|
977
|
+
}
|
|
978
|
+
if (issue.category === 'incompleteInstallation')
|
|
979
|
+
return 'incompleteInstallation';
|
|
980
|
+
if (issue.category === 'sourceIdentityChanged')
|
|
981
|
+
return 'sourceUnavailable';
|
|
982
|
+
return issue.rootCode ?? issue.category;
|
|
983
|
+
}
|
|
984
|
+
function issueReasonPriority(issue) {
|
|
985
|
+
const code = primaryAttentionCode(issue);
|
|
986
|
+
return {
|
|
987
|
+
sourceMissing: 0,
|
|
988
|
+
artifactCollision: 1,
|
|
989
|
+
sourceUnavailable: 2,
|
|
990
|
+
catalogSourceUnavailable: 2,
|
|
991
|
+
bundleUnavailable: 2,
|
|
992
|
+
dependencyGraphInvalid: 3,
|
|
993
|
+
dependencyTargetUnsupported: 4,
|
|
994
|
+
dependencyNotReady: 5,
|
|
995
|
+
dependencyMissing: 5,
|
|
996
|
+
scopeConflict: 6,
|
|
997
|
+
requiredConfigMissing: 7,
|
|
998
|
+
invalidConfig: 7,
|
|
999
|
+
incompleteInstallation: 8,
|
|
1000
|
+
diagnostic: 9,
|
|
1001
|
+
}[code] ?? 9;
|
|
1002
|
+
}
|
|
1003
|
+
function collapseRootIssues(issues) {
|
|
1004
|
+
const byId = new Map();
|
|
1005
|
+
for (const issue of issues)
|
|
1006
|
+
byId.set(issue.issueId, [...(byId.get(issue.issueId) ?? []), issue]);
|
|
1007
|
+
return [...byId.values()].map((group) => {
|
|
1008
|
+
const ordered = [...group].sort((left, right) => Number(right.relationship === 'direct') - Number(left.relationship === 'direct')
|
|
1009
|
+
|| compareText(left.pluginId ?? '', right.pluginId ?? '')
|
|
1010
|
+
|| compareText(left.platform ?? '', right.platform ?? '')
|
|
1011
|
+
|| compareText(left.scope ?? '', right.scope ?? ''));
|
|
1012
|
+
const primary = ordered[0];
|
|
1013
|
+
const direct = ordered.find((issue) => issue.relationship === 'direct');
|
|
1014
|
+
const rootEntity = direct?.rootEntity ?? ordered.map((issue) => issue.rootEntity)
|
|
1015
|
+
.filter((entity) => entity !== undefined)
|
|
1016
|
+
.sort((left, right) => compareText(left.pluginId, right.pluginId)
|
|
1017
|
+
|| compareText(left.platform, right.platform)
|
|
1018
|
+
|| compareText(left.scope, right.scope))[0];
|
|
1019
|
+
const affectedTargets = [...new Map(ordered.flatMap((issue) => issue.affectedTargets ?? [])
|
|
1020
|
+
.map((target) => [`${target.pluginId}\0${target.platform}\0${target.scope}`, target])).values()]
|
|
1021
|
+
.sort((left, right) => compareText(left.pluginId, right.pluginId)
|
|
1022
|
+
|| compareText(left.platform, right.platform)
|
|
1023
|
+
|| compareText(left.scope, right.scope));
|
|
1024
|
+
const projected = rootEntity && !direct ? {
|
|
1025
|
+
...primary,
|
|
1026
|
+
title: `${rootEntity.pluginId} · ${rootEntity.platform === 'codex' ? 'Codex' : 'Claude Code'} · ${primary.category === 'artifactCollision' ? '输出冲突' : primary.title.split(' · ').at(-1) ?? primary.title}`,
|
|
1027
|
+
entity: { kind: 'plugin', id: rootEntity.pluginId },
|
|
1028
|
+
pluginId: rootEntity.pluginId,
|
|
1029
|
+
platform: rootEntity.platform,
|
|
1030
|
+
scope: rootEntity.scope,
|
|
1031
|
+
sourceId: rootEntity.pluginId.split('/', 1)[0],
|
|
1032
|
+
} : primary;
|
|
1033
|
+
return {
|
|
1034
|
+
...projected,
|
|
1035
|
+
...(rootEntity ? { rootEntity } : {}),
|
|
1036
|
+
...(affectedTargets.length > 0 ? { affectedTargets } : {}),
|
|
1037
|
+
impact: [...new Set(ordered.flatMap((issue) => issue.impact))],
|
|
1038
|
+
technicalDetails: [...new Map(ordered.flatMap((issue) => issue.technicalDetails)
|
|
1039
|
+
.map((detail) => [`${detail.code}\0${detail.message}`, detail])).values()],
|
|
1040
|
+
};
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
605
1043
|
export function buildTuiViewModel(options) {
|
|
606
1044
|
const dependencyById = new Map((options.dependencyOverviews ?? [])
|
|
607
1045
|
.map((overview) => [overview.pluginId, overview]));
|
|
@@ -622,9 +1060,11 @@ export function buildTuiViewModel(options) {
|
|
|
622
1060
|
: [];
|
|
623
1061
|
});
|
|
624
1062
|
const attention = placements.some((placement) => placement.state === 'scopeConflict'
|
|
625
|
-
|| (placement.state === 'installed'
|
|
626
|
-
|
|
627
|
-
const
|
|
1063
|
+
|| (placement.state === 'installed'
|
|
1064
|
+
&& (placement.health !== 'ready' || placement.blockingReason !== undefined)));
|
|
1065
|
+
const installed = placements.some((placement) => placement.state === 'installed' || placement.state === 'scopeConflict');
|
|
1066
|
+
const unavailable = options.sourceHealth?.get(sourceId)?.state === 'unavailable'
|
|
1067
|
+
|| (summary?.missingCapabilities?.length ?? 0) > 0;
|
|
628
1068
|
return {
|
|
629
1069
|
pluginId,
|
|
630
1070
|
sourceId,
|
|
@@ -639,9 +1079,16 @@ export function buildTuiViewModel(options) {
|
|
|
639
1079
|
supportedPlatforms: summary?.supportedTargets
|
|
640
1080
|
? ['codex', 'claude'].filter((platform) => summary.supportedTargets[platform].length > 0)
|
|
641
1081
|
: placements.map((placement) => placement.platform),
|
|
1082
|
+
...(summary?.supportedTargets ? { supportedScopes: {
|
|
1083
|
+
codex: [...summary.supportedTargets.codex],
|
|
1084
|
+
claude: [...summary.supportedTargets.claude],
|
|
1085
|
+
} } : {}),
|
|
642
1086
|
installedPlacements: placements,
|
|
643
1087
|
aggregateStatus: unavailable ? 'unavailable' : attention ? 'needsAttention' : installed ? 'installed' : 'available',
|
|
644
1088
|
portableSkills: options.portablePluginIds?.includes(pluginId) ?? false,
|
|
1089
|
+
...(summary?.missingCapabilities
|
|
1090
|
+
? { missingCapabilities: summary.missingCapabilities }
|
|
1091
|
+
: {}),
|
|
645
1092
|
...(dependencyById.get(pluginId)
|
|
646
1093
|
? { dependencySummary: dependencyById.get(pluginId).summary }
|
|
647
1094
|
: summary && (summary.dependencyTotalCount ?? 0) > 0
|
|
@@ -672,7 +1119,7 @@ export function buildTuiViewModel(options) {
|
|
|
672
1119
|
state: sourceState(source, options.sourceHealth?.get(source.id)),
|
|
673
1120
|
}));
|
|
674
1121
|
const sourceRootIds = new Set([...(options.sourceHealth?.values() ?? [])]
|
|
675
|
-
.filter((health) => health.state === '
|
|
1122
|
+
.filter((health) => health.state === 'unavailable')
|
|
676
1123
|
.map((health) => health.sourceId));
|
|
677
1124
|
const allTargetIssues = targetIssues(options.status);
|
|
678
1125
|
const targetImpactCounts = new Map();
|
|
@@ -687,27 +1134,51 @@ export function buildTuiViewModel(options) {
|
|
|
687
1134
|
|| !issue.sourceId || !sourceRootIds.has(issue.sourceId)),
|
|
688
1135
|
...statusIssues(options.status),
|
|
689
1136
|
...configIssues(options.pluginSummaries),
|
|
1137
|
+
...dependencyOverviewIssues(options.dependencyOverviews ?? [], options.pluginSummaries, options.status),
|
|
690
1138
|
...[...(options.sourceHealth?.values() ?? [])].flatMap((health) => sourceIssue(health, targetImpactCounts.get(health.sourceId) ?? 0) ?? []),
|
|
691
1139
|
], options.dependencyOverviews ?? []);
|
|
692
|
-
const
|
|
1140
|
+
const stableIssueDrafts = collapseRootIssues(issueDrafts).sort((left, right) => issueGroupOrder[issueGroup(left)] - issueGroupOrder[issueGroup(right)]
|
|
1141
|
+
|| issueReasonPriority(left) - issueReasonPriority(right)
|
|
1142
|
+
|| compareText(primaryAttentionCode(left), primaryAttentionCode(right))
|
|
1143
|
+
|| compareText(left.issueId, right.issueId));
|
|
1144
|
+
const issues = stableIssueDrafts.map((issue) => ({
|
|
693
1145
|
...issue,
|
|
1146
|
+
group: issueGroup(issue),
|
|
694
1147
|
diagnostic: issueDiagnostic(issue, sourceDetails),
|
|
695
1148
|
}));
|
|
1149
|
+
const pluginsWithAttention = plugins.map((plugin) => {
|
|
1150
|
+
const primary = stableIssueDrafts.filter((issue) => issue.pluginId === plugin.pluginId
|
|
1151
|
+
|| issue.dependencyPluginId === plugin.pluginId
|
|
1152
|
+
|| issue.affectedTargets?.some((target) => target.pluginId === plugin.pluginId)
|
|
1153
|
+
|| issue.entity.kind === 'source' && issue.sourceId === plugin.sourceId)
|
|
1154
|
+
.sort((left, right) => issueReasonPriority(left) - issueReasonPriority(right)
|
|
1155
|
+
|| compareText(primaryAttentionCode(left), primaryAttentionCode(right))
|
|
1156
|
+
|| compareText(left.issueId, right.issueId))[0];
|
|
1157
|
+
if (!primary)
|
|
1158
|
+
return plugin;
|
|
1159
|
+
return {
|
|
1160
|
+
...plugin,
|
|
1161
|
+
primaryAttention: {
|
|
1162
|
+
severity: 'error',
|
|
1163
|
+
code: primaryAttentionCode(primary),
|
|
1164
|
+
message: primary.explanation,
|
|
1165
|
+
},
|
|
1166
|
+
};
|
|
1167
|
+
});
|
|
696
1168
|
return {
|
|
697
|
-
plugins,
|
|
1169
|
+
plugins: pluginsWithAttention,
|
|
698
1170
|
sourceTabs,
|
|
699
1171
|
sourceDetails: (options.sourceDetails ?? []).map((detail) => ({
|
|
700
1172
|
...detail,
|
|
701
|
-
pluginCount:
|
|
1173
|
+
pluginCount: pluginsWithAttention.filter((plugin) => plugin.sourceId === detail.id).length,
|
|
702
1174
|
})),
|
|
703
1175
|
issues,
|
|
704
1176
|
dependencyOverviews: options.dependencyOverviews ?? [],
|
|
705
1177
|
home: {
|
|
706
|
-
availablePlugins:
|
|
707
|
-
installedPlugins:
|
|
1178
|
+
availablePlugins: pluginsWithAttention.filter((plugin) => plugin.aggregateStatus === 'available').length,
|
|
1179
|
+
installedPlugins: pluginsWithAttention.filter(hasInstalledPlacement).length,
|
|
708
1180
|
issueCount: issues.length,
|
|
709
1181
|
sourceCount: sourceTabs.length,
|
|
710
|
-
cachedSourceCount: sourceTabs.filter((source) => source.state === 'cache').length,
|
|
711
1182
|
unavailableSourceCount: sourceTabs.filter((source) => source.state === 'error').length,
|
|
712
1183
|
},
|
|
713
1184
|
};
|
|
@@ -737,6 +1208,7 @@ export function buildConfigGroups(options) {
|
|
|
737
1208
|
const entryByKey = new Map(options.read.fields.map((field) => [field.key, field]));
|
|
738
1209
|
const effectiveEntryByKey = new Map((options.effectiveRead ?? options.read).fields.map((field) => [field.key, field]));
|
|
739
1210
|
const effectivePage = options.read.scope === 'effective';
|
|
1211
|
+
const layerEntry = (layer, key) => options.layerReads?.[layer].fields.find((field) => field.key === key);
|
|
740
1212
|
const fieldModel = (key) => {
|
|
741
1213
|
const schema = options.schema.schema[key];
|
|
742
1214
|
const entry = entryByKey.get(key);
|
|
@@ -762,6 +1234,16 @@ export function buildConfigGroups(options) {
|
|
|
762
1234
|
&& effectiveEntry.effectiveValue !== undefined
|
|
763
1235
|
&& effectiveEntry.effectiveValue !== null
|
|
764
1236
|
&& (effectiveEntry.valueState === 'configured' || effectiveEntry.valueState === 'default');
|
|
1237
|
+
const omittedLayer = options.read.scope === 'user'
|
|
1238
|
+
? 'user'
|
|
1239
|
+
: options.read.projectLayer === 'local' ? 'local' : 'project';
|
|
1240
|
+
const fallback = ['local', 'project', 'user']
|
|
1241
|
+
.filter((layer) => layer !== omittedLayer)
|
|
1242
|
+
.map((layer) => ({ layer, entry: layerEntry(layer, key) }))
|
|
1243
|
+
.find((candidate) => candidate.entry?.storedSourceLayer !== undefined);
|
|
1244
|
+
const fallbackValue = fallback?.entry?.storedValue ?? schema.default;
|
|
1245
|
+
const fallbackConfigured = fallback !== undefined || schema.default !== undefined;
|
|
1246
|
+
const fallbackSource = fallback?.layer ?? (schema.default !== undefined ? 'default' : undefined);
|
|
765
1247
|
return {
|
|
766
1248
|
key,
|
|
767
1249
|
title: schema.title ?? key,
|
|
@@ -788,6 +1270,15 @@ export function buildConfigGroups(options) {
|
|
|
788
1270
|
value: effectiveEntry?.effectiveValue,
|
|
789
1271
|
}),
|
|
790
1272
|
effectiveSourceLabel: configSourceLabel(effectiveEntry?.sourceLayer ?? null),
|
|
1273
|
+
...(!effectivePage && configured ? {
|
|
1274
|
+
fallbackDisplayValue: displayConfigValue({
|
|
1275
|
+
privateValue,
|
|
1276
|
+
inherited: false,
|
|
1277
|
+
configured: fallbackConfigured,
|
|
1278
|
+
value: fallbackValue,
|
|
1279
|
+
}),
|
|
1280
|
+
fallbackSourceLabel: fallbackSource ? configSourceLabel(fallbackSource) : '未设置',
|
|
1281
|
+
} : {}),
|
|
791
1282
|
...(!privateValue && selectedValue !== undefined
|
|
792
1283
|
? { value: selectedValue }
|
|
793
1284
|
: {}),
|