@lesliechan721/aw 0.1.0-beta.8 → 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 +4 -4
- 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/remove-plugin.mjs +1 -1
- package/dist/authoring/scripts/remove-plugin.mjs.map +1 -1
- package/dist/authoring/scripts/validate-plugin.mjs +34 -778
- 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 +5 -6
- package/dist/scripts/plugin-staging.js +12 -13
- package/dist/scripts/plugin-staging.js.map +1 -1
- package/dist/src/authoring/workspace-commands.d.ts +2 -1
- package/dist/src/authoring/workspace-commands.js.map +1 -1
- package/dist/src/commands/aw-capabilities.d.ts +2 -2
- package/dist/src/commands/aw-capabilities.js +6 -11
- package/dist/src/commands/aw-capabilities.js.map +1 -1
- package/dist/src/commands/catalog-dev-source.d.ts +18 -12
- package/dist/src/commands/catalog-dev-source.js +241 -305
- package/dist/src/commands/catalog-dev-source.js.map +1 -1
- package/dist/src/commands/catalog-generation.d.ts +6 -19
- package/dist/src/commands/catalog-generation.js +10 -11
- package/dist/src/commands/catalog-generation.js.map +1 -1
- package/dist/src/commands/catalog-publication-inspection.d.ts +28 -27
- package/dist/src/commands/catalog-publication-inspection.js +139 -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 +2 -1
- package/dist/src/commands/catalog-publication-target.js +37 -2
- package/dist/src/commands/catalog-publication-target.js.map +1 -1
- package/dist/src/commands/catalog-publish.d.ts +51 -15
- package/dist/src/commands/catalog-publish.js +576 -219
- package/dist/src/commands/catalog-publish.js.map +1 -1
- package/dist/src/commands/catalog-source.d.ts +3 -28
- package/dist/src/commands/catalog-source.js +29 -140
- package/dist/src/commands/catalog-source.js.map +1 -1
- package/dist/src/commands/catalog-status.d.ts +6 -26
- package/dist/src/commands/catalog-status.js +8 -146
- 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 +20 -0
- package/dist/src/commands/offline-cleanup-evidence.js +87 -9
- package/dist/src/commands/offline-cleanup-evidence.js.map +1 -1
- package/dist/src/commands/options.d.ts +6 -1
- package/dist/src/commands/options.js +64 -6
- package/dist/src/commands/options.js.map +1 -1
- package/dist/src/commands/plugin-capabilities.js +4 -0
- package/dist/src/commands/plugin-capabilities.js.map +1 -1
- package/dist/src/commands/rebuild-command.d.ts +10 -8
- package/dist/src/commands/rebuild-command.js +1217 -426
- package/dist/src/commands/rebuild-command.js.map +1 -1
- package/dist/src/commands/rebuild-integration.d.ts +54 -6
- package/dist/src/commands/rebuild-integration.js +691 -364
- package/dist/src/commands/rebuild-integration.js.map +1 -1
- package/dist/src/commands/rebuild-operations.d.ts +2 -0
- package/dist/src/commands/rebuild-operations.js +31 -17
- package/dist/src/commands/rebuild-operations.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-v5.d.ts → status-v6.d.ts} +59 -26
- package/dist/src/commands/{status-v5.js → status-v6.js} +882 -79
- 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/write-commands.js +1 -43
- package/dist/src/commands/write-commands.js.map +1 -1
- package/dist/src/constants.d.ts +5 -4
- package/dist/src/constants.js +5 -4
- 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 +123 -55
- package/dist/src/generators/local-plugin.js.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +412 -152
- 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 -11
- package/dist/src/portable/commands.d.ts +2 -2
- package/dist/src/portable/commands.js +2 -8
- package/dist/src/portable/commands.js.map +1 -1
- package/dist/src/portable/materializer.d.ts +1 -4
- package/dist/src/portable/materializer.js +0 -2
- package/dist/src/portable/materializer.js.map +1 -1
- package/dist/src/tui/catalog-generation.d.ts +20 -41
- package/dist/src/tui/catalog-generation.js +65 -224
- package/dist/src/tui/catalog-generation.js.map +1 -1
- package/dist/src/tui/components.js +1 -2
- package/dist/src/tui/components.js.map +1 -1
- package/dist/src/tui/console-app-v4.js +461 -330
- package/dist/src/tui/console-app-v4.js.map +1 -1
- package/dist/src/tui/controller-runtime.d.ts +3 -5
- package/dist/src/tui/controller-runtime.js +182 -187
- package/dist/src/tui/controller-runtime.js.map +1 -1
- package/dist/src/tui/controller.d.ts +42 -45
- package/dist/src/tui/controller.js +454 -407
- 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 -1
- package/dist/src/tui/index.js +1 -1
- package/dist/src/tui/index.js.map +1 -1
- package/dist/src/tui/model.d.ts +81 -13
- package/dist/src/tui/model.js +378 -95
- package/dist/src/tui/model.js.map +1 -1
- package/dist/src/tui/router.d.ts +9 -0
- package/dist/src/tui/router.js.map +1 -1
- package/dist/src/types.d.ts +54 -47
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/agent-version.d.ts +4 -1
- package/dist/src/utils/agent-version.js +28 -3
- package/dist/src/utils/agent-version.js.map +1 -1
- package/dist/src/utils/catalog-digests.d.ts +7 -0
- package/dist/src/utils/catalog-digests.js +27 -0
- 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 +2 -1
- package/dist/src/utils/catalog-generation-error.js +12 -0
- package/dist/src/utils/catalog-generation-error.js.map +1 -1
- package/dist/src/utils/catalog-generation-resolver.d.ts +10 -3
- package/dist/src/utils/catalog-generation-resolver.js +90 -76
- package/dist/src/utils/catalog-generation-resolver.js.map +1 -1
- package/dist/src/utils/catalog-generation-service.d.ts +24 -33
- package/dist/src/utils/catalog-generation-service.js +253 -567
- package/dist/src/utils/catalog-generation-service.js.map +1 -1
- package/dist/src/utils/catalog-generation-state.d.ts +4 -0
- package/dist/src/utils/catalog-generation-state.js +73 -106
- package/dist/src/utils/catalog-generation-state.js.map +1 -1
- package/dist/src/utils/catalog-generation-store.d.ts +16 -26
- package/dist/src/utils/catalog-generation-store.js +154 -290
- package/dist/src/utils/catalog-generation-store.js.map +1 -1
- package/dist/src/utils/catalog-manifest-v6.d.ts +5 -0
- package/dist/src/utils/{catalog-manifest-v5.js → catalog-manifest-v6.js} +23 -35
- package/dist/src/utils/catalog-manifest-v6.js.map +1 -0
- package/dist/src/utils/catalog-operation-context.d.ts +6 -14
- package/dist/src/utils/catalog-operation-context.js +68 -169
- package/dist/src/utils/catalog-operation-context.js.map +1 -1
- package/dist/src/utils/catalog-public-error.js +1 -4
- 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 +2 -2
- 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.js +25 -9
- 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 +22 -1
- package/dist/src/utils/codex-config.js.map +1 -1
- package/dist/src/utils/codex-manager.d.ts +50 -2
- package/dist/src/utils/codex-manager.js +160 -6
- package/dist/src/utils/codex-manager.js.map +1 -1
- 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-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/git-catalog-provider.js +56 -115
- package/dist/src/utils/git-catalog-provider.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 +1 -10
- package/dist/src/utils/multi-source-catalog.js +8 -175
- package/dist/src/utils/multi-source-catalog.js.map +1 -1
- package/dist/src/utils/native-cli.d.ts +34 -0
- package/dist/src/utils/native-cli.js +91 -0
- package/dist/src/utils/native-cli.js.map +1 -1
- package/dist/src/utils/orphan-marketplace-cleanup.js +1 -0
- package/dist/src/utils/orphan-marketplace-cleanup.js.map +1 -1
- package/dist/src/utils/ownership.d.ts +0 -10
- package/dist/src/utils/ownership.js +3 -88
- 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 +45 -62
- 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 +0 -5
- package/dist/src/utils/plugin-config-write.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/target-eligibility.d.ts +3 -2
- package/dist/src/utils/target-eligibility.js +4 -3
- package/dist/src/utils/target-eligibility.js.map +1 -1
- package/package.json +5 -4
- 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 -91
- package/dist/scripts/codex-eval-app-server.js +0 -1334
- 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 -1589
- 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 -189
- package/dist/scripts/plugin-eval-contract.js +0 -745
- 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/catalog-context.d.ts +0 -52
- package/dist/src/commands/catalog-context.js +0 -156
- package/dist/src/commands/catalog-context.js.map +0 -1
- package/dist/src/commands/status-v5.js.map +0 -1
- package/dist/src/utils/catalog-manifest-v5.d.ts +0 -5
- package/dist/src/utils/catalog-manifest-v5.js.map +0 -1
- package/dist/src/utils/catalog-source-cache.d.ts +0 -62
- package/dist/src/utils/catalog-source-cache.js +0 -321
- 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,64 +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]);
|
|
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
|
+
}
|
|
193
437
|
if (target.state !== 'partial' && target.state !== 'error'
|
|
194
|
-
&& !target.errors.some((error) => error.code === 'artifactCollision'
|
|
438
|
+
&& !target.errors.some((error) => error.code === 'artifactCollision'
|
|
439
|
+
|| error.dependencyPluginId !== undefined && error.rootIssueId !== undefined))
|
|
195
440
|
continue;
|
|
196
441
|
const codes = new Set(target.errors.map((error) => error.code));
|
|
197
442
|
const dependencyCodes = [
|
|
@@ -319,14 +564,41 @@ function targetIssues(payload) {
|
|
|
319
564
|
{ id: 'viewTechnical', label: '技术详情' },
|
|
320
565
|
]
|
|
321
566
|
: [{ id: 'viewTechnical', label: '技术详情' }, { id: 'retryLater', label: '稍后重试' }];
|
|
322
|
-
const issueId = rootError?.rootIssueId
|
|
323
|
-
?? `target:${target.pluginId}:${target.platform}:${target.scope}:${target.state}${roots.length > 1 ? `:${root.code}` : ''}${dependencyPluginId ? `:${dependencyPluginId}` : ''}`;
|
|
324
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}` : ''}`);
|
|
325
589
|
issues.push({
|
|
326
590
|
issueId,
|
|
327
591
|
category: root.category,
|
|
328
592
|
rootCode: root.code,
|
|
329
593
|
mergeEligible: root.mergeEligible,
|
|
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
|
+
}],
|
|
330
602
|
title: `${target.pluginId} · ${target.platform === 'codex' ? 'Codex' : 'Claude Code'} · ${root.category === 'artifactCollision' ? '输出冲突' : dependencyCategory ? {
|
|
331
603
|
dependencyMissing: '缺少依赖',
|
|
332
604
|
dependencyNotReady: '依赖安装不完整',
|
|
@@ -348,7 +620,7 @@ function targetIssues(payload) {
|
|
|
348
620
|
impact: [root.category === 'artifactCollision'
|
|
349
621
|
? '请先移除或迁移冲突内容,然后重试安装或重新安装。'
|
|
350
622
|
: bundleUnavailable
|
|
351
|
-
? '可以清理可信的 AW
|
|
623
|
+
? '可以清理可信的 AW 现场;这不表示来源整体可用。'
|
|
352
624
|
: '写操作前需要重新检查这个目标。'],
|
|
353
625
|
entity: { kind: 'plugin', id: target.pluginId },
|
|
354
626
|
pluginId: target.pluginId,
|
|
@@ -586,46 +858,39 @@ function enrichDependencyIssuePlacements(issues, overviews) {
|
|
|
586
858
|
}
|
|
587
859
|
function issueDiagnostic(issue, sourceDetails) {
|
|
588
860
|
const source = issue.sourceId ? sourceDetails.get(issue.sourceId) : undefined;
|
|
589
|
-
const sourceDegraded = issue.category === 'sourceDegraded';
|
|
590
861
|
const sourceUnavailable = issue.category === 'sourceUnavailable' && issue.entity.kind === 'source';
|
|
591
862
|
const configUnavailable = issue.category === 'diagnostic' && issue.issueId.startsWith('config:');
|
|
592
863
|
const configInvalid = issue.category === 'requiredConfigMissing';
|
|
593
864
|
const dependency = issue.category.startsWith('dependency');
|
|
594
865
|
const platformState = issue.issueId.startsWith('status:') || issue.rootCode === 'targetDiagnostic';
|
|
595
|
-
const preserved =
|
|
866
|
+
const preserved = sourceUnavailable
|
|
596
867
|
? '已安装插件和已保存设置不会被删除。'
|
|
597
868
|
: configUnavailable
|
|
598
869
|
? '已保存的设置保持不变。'
|
|
599
870
|
: '现有安装和已保存设置不会因本页自动改变。';
|
|
600
|
-
const impact =
|
|
871
|
+
const impact = sourceUnavailable
|
|
601
872
|
? [
|
|
602
|
-
{ state: '
|
|
873
|
+
{ state: 'blocked', message: '当前不能浏览或安装这个来源中的插件。' },
|
|
603
874
|
{ state: 'preserved', message: preserved },
|
|
604
875
|
]
|
|
605
|
-
:
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
:
|
|
611
|
-
|
|
612
|
-
state: dependency || configUnavailable || configInvalid || platformState ? 'blocked' : 'degraded',
|
|
613
|
-
message,
|
|
614
|
-
})),
|
|
615
|
-
{ state: 'preserved', message: preserved },
|
|
616
|
-
];
|
|
876
|
+
: [
|
|
877
|
+
...issue.impact.map((message) => ({
|
|
878
|
+
state: dependency || configUnavailable || configInvalid || platformState ? 'blocked' : 'degraded',
|
|
879
|
+
message,
|
|
880
|
+
})),
|
|
881
|
+
{ state: 'preserved', message: preserved },
|
|
882
|
+
];
|
|
617
883
|
const primaryAction = issue.actions.find((action) => action.id !== 'viewTechnical');
|
|
618
884
|
const nextStep = primaryAction
|
|
619
885
|
? `${primaryAction.label},然后重新检查当前状态。`
|
|
620
886
|
: '打开技术详情,记录安全错误代码后重新检查。';
|
|
621
|
-
const sourceDiagnostic =
|
|
887
|
+
const sourceDiagnostic = sourceUnavailable;
|
|
622
888
|
const rawCode = sourceDiagnostic
|
|
623
889
|
? source?.errorCode ?? issue.technicalDetails[0]?.code
|
|
624
890
|
: issue.technicalDetails[0]?.code;
|
|
625
|
-
const code = safeDiagnosticCode(rawCode,
|
|
626
|
-
? '
|
|
627
|
-
|
|
628
|
-
const stage = sourceDegraded || sourceUnavailable ? 'resolve-source'
|
|
891
|
+
const code = safeDiagnosticCode(rawCode, sourceUnavailable
|
|
892
|
+
? 'catalogSourceUnavailable' : 'diagnosticUnavailable');
|
|
893
|
+
const stage = sourceUnavailable ? 'resolve-source'
|
|
629
894
|
: configUnavailable ? 'read-config'
|
|
630
895
|
: configInvalid ? 'validate-config'
|
|
631
896
|
: dependency ? 'resolve-dependencies'
|
|
@@ -637,9 +902,6 @@ function issueDiagnostic(issue, sourceDetails) {
|
|
|
637
902
|
: []),
|
|
638
903
|
...(issue.platform ? [{ key: 'platform', value: issue.platform }] : []),
|
|
639
904
|
...(issue.scope ? [{ key: 'scope', value: issue.scope }] : []),
|
|
640
|
-
...(sourceDiagnostic && source?.freshness
|
|
641
|
-
? [{ key: 'freshness', value: source.freshness }]
|
|
642
|
-
: []),
|
|
643
905
|
...(issue.requiredFields?.slice(0, 1).map((field) => ({
|
|
644
906
|
key: 'field',
|
|
645
907
|
value: field.title,
|
|
@@ -653,7 +915,7 @@ function issueDiagnostic(issue, sourceDetails) {
|
|
|
653
915
|
'按技术详情使用受支持命令或人工处理。',
|
|
654
916
|
'再次运行状态检查。',
|
|
655
917
|
]
|
|
656
|
-
:
|
|
918
|
+
: sourceUnavailable
|
|
657
919
|
? ['检查 Git URL、ref 或本地目录。', '确认当前终端具备来源授权。', '运行“重新检查来源”验证修复。']
|
|
658
920
|
: dependency
|
|
659
921
|
? ['检查依赖关系和依赖插件状态。', '完成恢复动作后重新检查根插件。']
|
|
@@ -663,7 +925,7 @@ function issueDiagnostic(issue, sourceDetails) {
|
|
|
663
925
|
? ['完成或修正列出的设置字段。', '重新检查插件设置。']
|
|
664
926
|
: ['检查目标平台配置和访问权限。', '完成恢复动作后重新运行状态检查。'];
|
|
665
927
|
return {
|
|
666
|
-
severity:
|
|
928
|
+
severity: 'error',
|
|
667
929
|
title: issue.title,
|
|
668
930
|
userMessage: issue.explanation,
|
|
669
931
|
impact,
|
|
@@ -674,9 +936,6 @@ function issueDiagnostic(issue, sourceDetails) {
|
|
|
674
936
|
...(sourceDiagnostic && issue.sourceId ? { sourceId: issue.sourceId } : {}),
|
|
675
937
|
...(sourceDiagnostic && source?.requestedRef ? { requestedRef: source.requestedRef } : {}),
|
|
676
938
|
...(sourceDiagnostic && source?.resolvedCommit ? { resolvedCommit: source.resolvedCommit } : {}),
|
|
677
|
-
...(sourceDegraded || sourceUnavailable
|
|
678
|
-
? { lastGood: sourceDegraded ? 'available' : 'unavailable' }
|
|
679
|
-
: {}),
|
|
680
939
|
...(context.length > 0 ? { context } : {}),
|
|
681
940
|
checks,
|
|
682
941
|
},
|
|
@@ -698,7 +957,6 @@ function issueGroup(issue) {
|
|
|
698
957
|
if (issue.category === 'artifactCollision')
|
|
699
958
|
return 'artifactCollision';
|
|
700
959
|
if (issue.category === 'sourceUnavailable'
|
|
701
|
-
|| issue.category === 'sourceDegraded'
|
|
702
960
|
|| issue.category === 'sourceIdentityChanged')
|
|
703
961
|
return 'sourceUnavailable';
|
|
704
962
|
if (issue.category.startsWith('dependency'))
|
|
@@ -719,8 +977,6 @@ function primaryAttentionCode(issue) {
|
|
|
719
977
|
}
|
|
720
978
|
if (issue.category === 'incompleteInstallation')
|
|
721
979
|
return 'incompleteInstallation';
|
|
722
|
-
if (issue.category === 'sourceDegraded')
|
|
723
|
-
return 'sourceUnavailable';
|
|
724
980
|
if (issue.category === 'sourceIdentityChanged')
|
|
725
981
|
return 'sourceUnavailable';
|
|
726
982
|
return issue.rootCode ?? issue.category;
|
|
@@ -746,21 +1002,43 @@ function issueReasonPriority(issue) {
|
|
|
746
1002
|
}
|
|
747
1003
|
function collapseRootIssues(issues) {
|
|
748
1004
|
const byId = new Map();
|
|
749
|
-
for (const issue of issues)
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
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 ? {
|
|
757
1025
|
...primary,
|
|
758
|
-
|
|
759
|
-
|
|
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)
|
|
760
1039
|
.map((detail) => [`${detail.code}\0${detail.message}`, detail])).values()],
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
return [...byId.values()];
|
|
1040
|
+
};
|
|
1041
|
+
});
|
|
764
1042
|
}
|
|
765
1043
|
export function buildTuiViewModel(options) {
|
|
766
1044
|
const dependencyById = new Map((options.dependencyOverviews ?? [])
|
|
@@ -782,8 +1060,9 @@ export function buildTuiViewModel(options) {
|
|
|
782
1060
|
: [];
|
|
783
1061
|
});
|
|
784
1062
|
const attention = placements.some((placement) => placement.state === 'scopeConflict'
|
|
785
|
-
|| (placement.state === 'installed'
|
|
786
|
-
|
|
1063
|
+
|| (placement.state === 'installed'
|
|
1064
|
+
&& (placement.health !== 'ready' || placement.blockingReason !== undefined)));
|
|
1065
|
+
const installed = placements.some((placement) => placement.state === 'installed' || placement.state === 'scopeConflict');
|
|
787
1066
|
const unavailable = options.sourceHealth?.get(sourceId)?.state === 'unavailable'
|
|
788
1067
|
|| (summary?.missingCapabilities?.length ?? 0) > 0;
|
|
789
1068
|
return {
|
|
@@ -800,6 +1079,10 @@ export function buildTuiViewModel(options) {
|
|
|
800
1079
|
supportedPlatforms: summary?.supportedTargets
|
|
801
1080
|
? ['codex', 'claude'].filter((platform) => summary.supportedTargets[platform].length > 0)
|
|
802
1081
|
: placements.map((placement) => placement.platform),
|
|
1082
|
+
...(summary?.supportedTargets ? { supportedScopes: {
|
|
1083
|
+
codex: [...summary.supportedTargets.codex],
|
|
1084
|
+
claude: [...summary.supportedTargets.claude],
|
|
1085
|
+
} } : {}),
|
|
803
1086
|
installedPlacements: placements,
|
|
804
1087
|
aggregateStatus: unavailable ? 'unavailable' : attention ? 'needsAttention' : installed ? 'installed' : 'available',
|
|
805
1088
|
portableSkills: options.portablePluginIds?.includes(pluginId) ?? false,
|
|
@@ -836,7 +1119,7 @@ export function buildTuiViewModel(options) {
|
|
|
836
1119
|
state: sourceState(source, options.sourceHealth?.get(source.id)),
|
|
837
1120
|
}));
|
|
838
1121
|
const sourceRootIds = new Set([...(options.sourceHealth?.values() ?? [])]
|
|
839
|
-
.filter((health) => health.state === '
|
|
1122
|
+
.filter((health) => health.state === 'unavailable')
|
|
840
1123
|
.map((health) => health.sourceId));
|
|
841
1124
|
const allTargetIssues = targetIssues(options.status);
|
|
842
1125
|
const targetImpactCounts = new Map();
|
|
@@ -866,6 +1149,7 @@ export function buildTuiViewModel(options) {
|
|
|
866
1149
|
const pluginsWithAttention = plugins.map((plugin) => {
|
|
867
1150
|
const primary = stableIssueDrafts.filter((issue) => issue.pluginId === plugin.pluginId
|
|
868
1151
|
|| issue.dependencyPluginId === plugin.pluginId
|
|
1152
|
+
|| issue.affectedTargets?.some((target) => target.pluginId === plugin.pluginId)
|
|
869
1153
|
|| issue.entity.kind === 'source' && issue.sourceId === plugin.sourceId)
|
|
870
1154
|
.sort((left, right) => issueReasonPriority(left) - issueReasonPriority(right)
|
|
871
1155
|
|| compareText(primaryAttentionCode(left), primaryAttentionCode(right))
|
|
@@ -875,7 +1159,7 @@ export function buildTuiViewModel(options) {
|
|
|
875
1159
|
return {
|
|
876
1160
|
...plugin,
|
|
877
1161
|
primaryAttention: {
|
|
878
|
-
severity:
|
|
1162
|
+
severity: 'error',
|
|
879
1163
|
code: primaryAttentionCode(primary),
|
|
880
1164
|
message: primary.explanation,
|
|
881
1165
|
},
|
|
@@ -895,7 +1179,6 @@ export function buildTuiViewModel(options) {
|
|
|
895
1179
|
installedPlugins: pluginsWithAttention.filter(hasInstalledPlacement).length,
|
|
896
1180
|
issueCount: issues.length,
|
|
897
1181
|
sourceCount: sourceTabs.length,
|
|
898
|
-
cachedSourceCount: sourceTabs.filter((source) => source.state === 'cache').length,
|
|
899
1182
|
unavailableSourceCount: sourceTabs.filter((source) => source.state === 'error').length,
|
|
900
1183
|
},
|
|
901
1184
|
};
|