@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
|
@@ -34,7 +34,11 @@ export const CONSOLE_V4_SCREEN_IDS = [
|
|
|
34
34
|
function pluginMenuActionId(action) {
|
|
35
35
|
return action.id === 'platform' || action.id === 'scopeConflict'
|
|
36
36
|
? `${action.id}:${action.platform}`
|
|
37
|
-
: action.id
|
|
37
|
+
: action.id === 'addScope'
|
|
38
|
+
? `${action.id}:${action.platform}:${action.scope}`
|
|
39
|
+
: action.id === 'resolveScopeConflict'
|
|
40
|
+
? `${action.id}:${action.pluginId}:${action.platform}:${action.scope}`
|
|
41
|
+
: action.id;
|
|
38
42
|
}
|
|
39
43
|
function isCharacterInputMode(route, searchMode) {
|
|
40
44
|
return searchMode
|
|
@@ -122,11 +126,22 @@ function pluginPlacementSummary(plugin) {
|
|
|
122
126
|
const placement = plugin.installedPlacements.find((entry) => entry.platform === platform);
|
|
123
127
|
if (!placement || placement.state === 'notInstalled')
|
|
124
128
|
return `${label} · 未添加`;
|
|
129
|
+
if (placement.state === 'blocked')
|
|
130
|
+
return `${label} · 无法添加 · 输出冲突`;
|
|
125
131
|
if (placement.state === 'scopeConflict')
|
|
126
132
|
return `${label} · 位置冲突`;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
133
|
+
if (placement.blockingReason === 'artifactCollision') {
|
|
134
|
+
return `${label} · ${scopeLabel(placement.scope)} · 输出冲突`;
|
|
135
|
+
}
|
|
136
|
+
const health = placement.actualState === 'needsSync' ? '需要同步'
|
|
137
|
+
: placement.actualState === 'drifted' ? '已漂移'
|
|
138
|
+
: placement.actualState === 'conflict' ? '位置冲突'
|
|
139
|
+
: placement.health === 'ready' ? '可用'
|
|
140
|
+
: placement.health === 'incomplete' ? '需要处理' : '不可用';
|
|
141
|
+
const desired = placement.desiredScopes?.length
|
|
142
|
+
? placement.desiredScopes.map(scopeLabel).join('+')
|
|
143
|
+
: scopeLabel(placement.scope);
|
|
144
|
+
return `${label} · ${desired} · ${health}`;
|
|
130
145
|
}).join(' | ') || '没有可用平台';
|
|
131
146
|
}
|
|
132
147
|
function issueGroupLabel(group) {
|
|
@@ -321,38 +336,38 @@ function configUnavailableDiagnostic(route) {
|
|
|
321
336
|
},
|
|
322
337
|
};
|
|
323
338
|
}
|
|
324
|
-
function sourceDiagnostic(sourceId, state, detail) {
|
|
325
|
-
const degraded = state === 'degraded';
|
|
339
|
+
function sourceDiagnostic(sourceId, state, detail, generation) {
|
|
326
340
|
const unavailable = state === 'unavailable' || state === 'error';
|
|
327
|
-
if (!
|
|
341
|
+
if (!unavailable)
|
|
328
342
|
return undefined;
|
|
343
|
+
const metadataInvalid = generation?.errorCode === 'catalogGenerationMetadataInvalid';
|
|
329
344
|
return {
|
|
330
|
-
severity:
|
|
331
|
-
title:
|
|
332
|
-
userMessage:
|
|
333
|
-
|
|
334
|
-
: '
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
]
|
|
340
|
-
: [
|
|
341
|
-
{ state: 'blocked', message: '当前不能浏览或安装这个来源中的插件。' },
|
|
342
|
-
{ state: 'preserved', message: '已安装插件和已保存设置不会被删除。' },
|
|
343
|
-
],
|
|
344
|
-
nextStep: degraded
|
|
345
|
-
? '重新检查来源;在修复前也可以继续使用匹配缓存。'
|
|
345
|
+
severity: 'error',
|
|
346
|
+
title: 'Catalog 来源不可用',
|
|
347
|
+
userMessage: '当前无法读取这个来源。',
|
|
348
|
+
impact: [
|
|
349
|
+
{ state: 'blocked', message: '当前不能浏览或安装这个来源中的插件。' },
|
|
350
|
+
{ state: 'preserved', message: '已安装插件和已保存设置不会被删除。' },
|
|
351
|
+
],
|
|
352
|
+
nextStep: metadataInvalid && generation.recoveryEntryPath
|
|
353
|
+
? `先安全删除 AW_HOME 下的精确条目 ${generation.recoveryEntryPath},再运行 ${generation.syncInstruction}。`
|
|
346
354
|
: '重新检查来源;如仍失败,请编辑来源 URL、路径或 ref。',
|
|
347
355
|
technical: {
|
|
348
|
-
code: safeDiagnosticCode(detail?.errorCode,
|
|
356
|
+
code: safeDiagnosticCode(generation?.errorCode ?? detail?.errorCode, 'catalogSourceUnavailable'),
|
|
349
357
|
stage: 'resolve-source',
|
|
350
358
|
sourceId,
|
|
351
359
|
...(detail?.requestedRef ? { requestedRef: detail.requestedRef } : {}),
|
|
352
360
|
...(detail?.resolvedCommit ? { resolvedCommit: detail.resolvedCommit } : {}),
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
361
|
+
...(metadataInvalid && generation.recoveryEntryPath
|
|
362
|
+
? { context: [{ key: 'storeEntry', value: generation.recoveryEntryPath }] }
|
|
363
|
+
: {}),
|
|
364
|
+
checks: metadataInvalid && generation.recoveryEntryPath
|
|
365
|
+
? [
|
|
366
|
+
`确认损坏条目为 AW_HOME/${generation.recoveryEntryPath}。`,
|
|
367
|
+
'只删除该精确条目,不删除 Catalog store 根或其它 digest。',
|
|
368
|
+
`运行 ${generation.syncInstruction} 重建 Active。`,
|
|
369
|
+
]
|
|
370
|
+
: ['检查 Git URL、ref 或本地目录。', '确认当前终端具备来源授权。', '运行“重新检查来源”验证修复。'],
|
|
356
371
|
},
|
|
357
372
|
};
|
|
358
373
|
}
|
|
@@ -423,7 +438,7 @@ function SourceTabs(props) {
|
|
|
423
438
|
const state = 'state' in tab ? tab.state : 'ready';
|
|
424
439
|
return (_jsxs(Text, { bold: active, color: active ? tuiTheme.colors.accent
|
|
425
440
|
: state === 'error' ? tuiTheme.statusColors.error
|
|
426
|
-
:
|
|
441
|
+
: tuiTheme.colors.muted, children: [active ? '[' : '', tab.label, state === 'error' ? ' !' : ` ${tab.count ?? ''}`, active ? ']' : '', ' '] }, tab.id));
|
|
427
442
|
})] }));
|
|
428
443
|
}
|
|
429
444
|
function configTabs(page) {
|
|
@@ -455,13 +470,22 @@ function placementStatus(placement) {
|
|
|
455
470
|
if (placement.state === 'notInstalled') {
|
|
456
471
|
return { value: '未添加', status: 'muted', description: '选择使用位置后添加' };
|
|
457
472
|
}
|
|
473
|
+
if (placement.state === 'blocked') {
|
|
474
|
+
return { value: '无法添加', status: 'error', description: '输出冲突;不会覆盖或删除占用内容' };
|
|
475
|
+
}
|
|
458
476
|
if (placement.state === 'scopeConflict') {
|
|
459
477
|
return { value: '位置冲突', status: 'warning', description: '需要先处理两个安装位置' };
|
|
460
478
|
}
|
|
479
|
+
if (placement.blockingReason === 'artifactCollision') {
|
|
480
|
+
return { value: '输出冲突', status: 'error', description: '只允许查看或安全移除受管内容' };
|
|
481
|
+
}
|
|
461
482
|
return {
|
|
462
|
-
value: `${scopeLabel(placement.scope)} · ${placement.health === 'ready' ? '可用' : placement.health === 'incomplete' ? '需要处理' : '不可用'}`,
|
|
463
|
-
status: placement.health === 'ready' ? 'success' : placement.health === 'incomplete' ? 'warning' : 'error',
|
|
464
|
-
description: placement.
|
|
483
|
+
value: `${placement.desiredScopes?.map(scopeLabel).join('+') || scopeLabel(placement.scope)} · ${placement.actualState === 'needsSync' ? '需要同步' : placement.actualState === 'drifted' ? '已漂移' : placement.actualState === 'conflict' ? '位置冲突' : placement.health === 'ready' ? '可用' : placement.health === 'incomplete' ? '需要处理' : '不可用'}`,
|
|
484
|
+
status: placement.actualState === 'conflict' ? 'error' : placement.health === 'ready' ? 'success' : placement.health === 'incomplete' ? 'warning' : 'error',
|
|
485
|
+
description: placement.actualState === 'needsSync' ? 'desired intent 与现场不同;可安全同步'
|
|
486
|
+
: placement.actualState === 'drifted' ? '现场已漂移;查看同步计划'
|
|
487
|
+
: placement.actualState === 'conflict' ? 'mixed 或 AW-only 重叠;查看恢复路径'
|
|
488
|
+
: placement.health === 'ready' ? '当前检查正常' : '查看影响和建议操作',
|
|
465
489
|
};
|
|
466
490
|
}
|
|
467
491
|
function dependencyStatus(item) {
|
|
@@ -475,9 +499,29 @@ function dependencyStatus(item) {
|
|
|
475
499
|
}
|
|
476
500
|
function dependencyPlacementLabel(item) {
|
|
477
501
|
const aggregate = dependencyStatus(item);
|
|
502
|
+
const installed = item.placements.filter((entry) => entry.state === 'installed');
|
|
503
|
+
const modern = installed.filter((entry) => entry.state === 'installed'
|
|
504
|
+
&& (entry.desiredScopes !== undefined || entry.actualState !== undefined));
|
|
505
|
+
if (modern.length > 0) {
|
|
506
|
+
return modern.map((entry) => {
|
|
507
|
+
if (entry.state !== 'installed')
|
|
508
|
+
return '';
|
|
509
|
+
const desired = entry.desiredScopes?.map(scopeLabel).join('+') || scopeLabel(entry.scope);
|
|
510
|
+
const actualScopes = [
|
|
511
|
+
...(entry.activation?.user ? ['所有项目'] : []),
|
|
512
|
+
...(entry.activation?.project ? ['当前项目'] : []),
|
|
513
|
+
];
|
|
514
|
+
const actual = actualScopes.join('+') || scopeLabel(entry.scope);
|
|
515
|
+
const state = entry.actualState === 'needsSync' ? '需同步'
|
|
516
|
+
: entry.actualState === 'drifted' ? '已漂移'
|
|
517
|
+
: entry.actualState === 'conflict' ? '冲突'
|
|
518
|
+
: entry.actualState === 'ready' ? '可用' : aggregate.value;
|
|
519
|
+
return `${platformLabel(entry.platform)} · desired ${desired} · actual ${actual} · ${state}`;
|
|
520
|
+
}).join(' | ');
|
|
521
|
+
}
|
|
478
522
|
if (item.aggregateStatus !== 'ready')
|
|
479
523
|
return aggregate.value;
|
|
480
|
-
const ready =
|
|
524
|
+
const ready = installed.filter((entry) => entry.state === 'installed' && entry.health === 'ready');
|
|
481
525
|
const scopes = new Set(ready.map((entry) => entry.state === 'installed' ? entry.scope : undefined));
|
|
482
526
|
return scopes.size === 1 && ready[0]?.state === 'installed'
|
|
483
527
|
? `${scopeLabel(ready[0].scope)} · ${aggregate.value}`
|
|
@@ -524,7 +568,7 @@ export function resolveConsoleV4ScreenId(snapshot, controller, overlay, tooSmall
|
|
|
524
568
|
return 'G01';
|
|
525
569
|
const route = snapshot.router.current.route;
|
|
526
570
|
if (route.name === 'home')
|
|
527
|
-
return
|
|
571
|
+
return 'G02';
|
|
528
572
|
if (route.name === 'pluginList') {
|
|
529
573
|
const items = controller.listPlugins({ mode: route.mode, sourceId: route.sourceId });
|
|
530
574
|
if (route.mode === 'installed' && items.length === 0)
|
|
@@ -567,6 +611,10 @@ export function resolveConsoleV4ScreenId(snapshot, controller, overlay, tooSmall
|
|
|
567
611
|
return 'D16';
|
|
568
612
|
return controller.getPluginOverview(route.pluginId)?.dependencySummary?.totalCount ? 'D04' : 'P06';
|
|
569
613
|
}
|
|
614
|
+
if (route.name === 'dependencyPlacement')
|
|
615
|
+
return 'D03';
|
|
616
|
+
if (route.name === 'dependencyPlacementEditor')
|
|
617
|
+
return 'D04';
|
|
570
618
|
if (route.name === 'pluginDetail') {
|
|
571
619
|
return controller.getPluginOverview(route.pluginId)?.dependencySummary?.totalCount ? 'D09' : 'P13';
|
|
572
620
|
}
|
|
@@ -582,9 +630,12 @@ export function resolveConsoleV4ScreenId(snapshot, controller, overlay, tooSmall
|
|
|
582
630
|
return 'P16';
|
|
583
631
|
}
|
|
584
632
|
if (route.name === 'reviewPreparing')
|
|
585
|
-
return
|
|
633
|
+
return 'P07';
|
|
634
|
+
if (route.name === 'review' && snapshot.activeReview?.originIssue)
|
|
635
|
+
return 'I10';
|
|
586
636
|
const dependencyOperation = snapshot.activeReview?.operationKind === 'pluginWrite'
|
|
587
|
-
&& Boolean(snapshot.activeReview.changes.some((change) => change.
|
|
637
|
+
&& Boolean(snapshot.activeReview.changes.some((change) => change.relation === 'direct' || change.relation === 'transitive'
|
|
638
|
+
|| change.group === 'dependencies'));
|
|
588
639
|
if (route.name === 'review' && dependencyOperation) {
|
|
589
640
|
return snapshot.activeReview?.pluginAction === 'uninstall' || snapshot.activeReview?.pluginAction === 'cleanup'
|
|
590
641
|
? 'D11' : 'D05';
|
|
@@ -600,8 +651,6 @@ export function resolveConsoleV4ScreenId(snapshot, controller, overlay, tooSmall
|
|
|
600
651
|
return snapshot.result.state === 'succeeded' ? 'D07' : 'D08';
|
|
601
652
|
}
|
|
602
653
|
}
|
|
603
|
-
if (route.name === 'review' && snapshot.activeReview?.originIssue)
|
|
604
|
-
return 'I10';
|
|
605
654
|
if (route.name === 'progress' && snapshot.activeReview?.originIssue)
|
|
606
655
|
return 'I11';
|
|
607
656
|
if (route.name === 'result' && snapshot.result?.originIssue) {
|
|
@@ -617,30 +666,27 @@ export function resolveConsoleV4ScreenId(snapshot, controller, overlay, tooSmall
|
|
|
617
666
|
return snapshot.result.state === 'succeeded' ? 'S12' : 'S13';
|
|
618
667
|
}
|
|
619
668
|
if (route.name === 'review')
|
|
620
|
-
return snapshot.activeReview?.operationKind === '
|
|
621
|
-
: snapshot.activeReview?.operationKind === '
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
669
|
+
return snapshot.activeReview?.operationKind === 'portableInstall' ? 'U06'
|
|
670
|
+
: snapshot.activeReview?.operationKind === 'configSave'
|
|
671
|
+
? 'C12'
|
|
672
|
+
: snapshot.activeReview?.operationKind === 'configReset'
|
|
673
|
+
? 'C16'
|
|
674
|
+
: snapshot.activeReview?.operationKind === 'pluginWrite'
|
|
675
|
+
&& (snapshot.activeReview.pluginAction === 'upgrade' || snapshot.activeReview.pluginAction === 'reinstall')
|
|
676
|
+
? 'P18'
|
|
626
677
|
: snapshot.activeReview?.operationKind === 'pluginWrite'
|
|
627
|
-
&& (snapshot.activeReview.pluginAction === '
|
|
628
|
-
? '
|
|
629
|
-
: snapshot.activeReview?.operationKind === 'pluginWrite'
|
|
630
|
-
&& (snapshot.activeReview.pluginAction === 'uninstall' || snapshot.activeReview.pluginAction === 'cleanup')
|
|
631
|
-
? 'P19' : 'P07';
|
|
678
|
+
&& (snapshot.activeReview.pluginAction === 'uninstall' || snapshot.activeReview.pluginAction === 'cleanup')
|
|
679
|
+
? 'P19' : 'P07';
|
|
632
680
|
if (route.name === 'progress')
|
|
633
|
-
return snapshot.activeReview?.operationKind === '
|
|
634
|
-
: snapshot.activeReview?.operationKind === '
|
|
635
|
-
|
|
636
|
-
|| snapshot.activeReview?.operationKind === 'configReset' ? 'C13' : 'P08';
|
|
681
|
+
return snapshot.activeReview?.operationKind === 'portableInstall' ? 'U07'
|
|
682
|
+
: snapshot.activeReview?.operationKind === 'configSave'
|
|
683
|
+
|| snapshot.activeReview?.operationKind === 'configReset' ? 'C13' : 'P08';
|
|
637
684
|
if (route.name === 'result')
|
|
638
|
-
return snapshot.result?.operationKind === '
|
|
639
|
-
: snapshot.result?.operationKind === '
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
: snapshot.result?.state === 'partial' ? 'P10' : 'P09';
|
|
685
|
+
return snapshot.result?.operationKind === 'portableInstall' ? 'U08'
|
|
686
|
+
: snapshot.result?.operationKind === 'configSave'
|
|
687
|
+
|| snapshot.result?.operationKind === 'configReset'
|
|
688
|
+
? snapshot.result.state === 'succeeded' ? 'C14' : 'C15'
|
|
689
|
+
: snapshot.result?.state === 'partial' ? 'P10' : 'P09';
|
|
644
690
|
if (route.name === 'pluginAbout')
|
|
645
691
|
return 'P20';
|
|
646
692
|
if (route.name === 'pluginTechnical')
|
|
@@ -659,18 +705,10 @@ export function resolveConsoleV4ScreenId(snapshot, controller, overlay, tooSmall
|
|
|
659
705
|
return 'C17';
|
|
660
706
|
if (route.name === 'sourceList')
|
|
661
707
|
return 'S01';
|
|
662
|
-
if (route.name === 'sourceDetail'
|
|
708
|
+
if (route.name === 'sourceDetail')
|
|
663
709
|
return 'K02';
|
|
664
710
|
if (route.name === 'sourceTechnical')
|
|
665
711
|
return 'S03';
|
|
666
|
-
if (route.name === 'catalogRefreshPolicy')
|
|
667
|
-
return 'K04';
|
|
668
|
-
if (route.name === 'catalogRefresh')
|
|
669
|
-
return 'K05';
|
|
670
|
-
if (route.name === 'catalogImmutableViolation')
|
|
671
|
-
return 'K06';
|
|
672
|
-
if (route.name === 'catalogActivationBlocked')
|
|
673
|
-
return 'K07';
|
|
674
712
|
if (route.name === 'sourceAdd')
|
|
675
713
|
return {
|
|
676
714
|
type: 'S04', id: 'S05', location: 'S06', refPolicy: 'S07', ref: 'S08', subdir: 'S09',
|
|
@@ -688,7 +726,6 @@ export function resolveConsoleV4ScreenId(snapshot, controller, overlay, tooSmall
|
|
|
688
726
|
return {
|
|
689
727
|
incompleteInstallation: 'I03',
|
|
690
728
|
artifactCollision: 'I09',
|
|
691
|
-
sourceDegraded: 'I04',
|
|
692
729
|
sourceUnavailable: 'I04',
|
|
693
730
|
sourceMissing: 'I05',
|
|
694
731
|
sourceIdentityChanged: 'I06',
|
|
@@ -729,7 +766,6 @@ export function ConsoleAppV4(props) {
|
|
|
729
766
|
const [dirty, setDirty] = useState(false);
|
|
730
767
|
const [configPage, setConfigPage] = useState();
|
|
731
768
|
const [configLayerCounts, setConfigLayerCounts] = useState({});
|
|
732
|
-
const [configLoadKey, setConfigLoadKey] = useState(0);
|
|
733
769
|
const [draftUpdates, setDraftUpdates] = useState({});
|
|
734
770
|
const [draftRemoves, setDraftRemoves] = useState([]);
|
|
735
771
|
const [inputValue, setInputValue] = useState('');
|
|
@@ -745,6 +781,7 @@ export function ConsoleAppV4(props) {
|
|
|
745
781
|
const [draftOwner, setDraftOwner] = useState();
|
|
746
782
|
const [pendingPresetId, setPendingPresetId] = useState();
|
|
747
783
|
const [pendingLayerFieldKey, setPendingLayerFieldKey] = useState();
|
|
784
|
+
const [confirmedSharedReviewToken, setConfirmedSharedReviewToken] = useState();
|
|
748
785
|
const dynamicMenuFocus = useRef(undefined);
|
|
749
786
|
const exitSent = useRef(false);
|
|
750
787
|
const operationBusy = useRef(false);
|
|
@@ -899,7 +936,7 @@ export function ConsoleAppV4(props) {
|
|
|
899
936
|
}
|
|
900
937
|
});
|
|
901
938
|
return () => abort.abort();
|
|
902
|
-
}, [
|
|
939
|
+
}, [configRoute?.pluginId, configRoute?.layer.scope, configRoute?.layer.projectLayer, props.controller]);
|
|
903
940
|
useEffect(() => {
|
|
904
941
|
if (route.name !== 'configFields' || !currentConfigPage)
|
|
905
942
|
return;
|
|
@@ -1000,13 +1037,6 @@ export function ConsoleAppV4(props) {
|
|
|
1000
1037
|
props.onScreenChange?.(screenId);
|
|
1001
1038
|
}, [props.onScreenChange, screenId]);
|
|
1002
1039
|
const dependencyOverview = (candidate) => candidate ? props.controller.getPluginDependencyOverview(candidate.pluginId) : undefined;
|
|
1003
|
-
const installIntent = (candidate, targets = selectedTargets) => ({
|
|
1004
|
-
kind: 'pluginWrite',
|
|
1005
|
-
action: 'install',
|
|
1006
|
-
pluginId: candidate.pluginId,
|
|
1007
|
-
platform: targets.length === 2 ? 'both' : targets[0],
|
|
1008
|
-
scope,
|
|
1009
|
-
});
|
|
1010
1040
|
let title = '管理你的 Agent 工作流插件';
|
|
1011
1041
|
let description = '为 Codex 和 Claude Code 添加、设置或移除开发能力。';
|
|
1012
1042
|
let breadcrumb = '首页';
|
|
@@ -1044,6 +1074,7 @@ export function ConsoleAppV4(props) {
|
|
|
1044
1074
|
compact: policy.mode === 'compact',
|
|
1045
1075
|
staticRows,
|
|
1046
1076
|
});
|
|
1077
|
+
const dependencyPlacementStaticRows = policy.mode === 'compact' ? 3 : 10;
|
|
1047
1078
|
const responsiveBudget = (compactRows, standardRows) => {
|
|
1048
1079
|
const baseline = policy.mode === 'compact' ? 18 : 24;
|
|
1049
1080
|
const base = policy.mode === 'compact' ? compactRows : standardRows;
|
|
@@ -1074,8 +1105,6 @@ export function ConsoleAppV4(props) {
|
|
|
1074
1105
|
setActionError(undefined);
|
|
1075
1106
|
};
|
|
1076
1107
|
const back = () => {
|
|
1077
|
-
if (route.name === 'catalogRefresh')
|
|
1078
|
-
props.controller.cancelCatalogRefresh(route.sourceId);
|
|
1079
1108
|
if (route.name === 'result')
|
|
1080
1109
|
props.controller.leaveResult();
|
|
1081
1110
|
else
|
|
@@ -1114,6 +1143,18 @@ export function ConsoleAppV4(props) {
|
|
|
1114
1143
|
setFocus(0);
|
|
1115
1144
|
setScrollOffset(0);
|
|
1116
1145
|
};
|
|
1146
|
+
const continueInstallAfterTargets = async (candidate, targets) => {
|
|
1147
|
+
if (props.controller.snapshot.installPlacementDraft?.pluginId !== candidate.pluginId) {
|
|
1148
|
+
props.controller.beginInstallFlow(candidate.pluginId, scope);
|
|
1149
|
+
}
|
|
1150
|
+
props.controller.setInstallPlatforms(targets);
|
|
1151
|
+
const hasConfigurableDependencies = await props.controller.prepareInstallDependencyPlacement();
|
|
1152
|
+
if (hasConfigurableDependencies) {
|
|
1153
|
+
go({ name: 'dependencyPlacement', pluginId: candidate.pluginId });
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
beginReview(props.controller.installPlacementIntent());
|
|
1157
|
+
};
|
|
1117
1158
|
const beginPortable = async (pluginId) => {
|
|
1118
1159
|
try {
|
|
1119
1160
|
await props.controller.preparePortableInstall(pluginId, route.name === 'portableBlocker' ? 'replace' : 'push');
|
|
@@ -1182,6 +1223,24 @@ export function ConsoleAppV4(props) {
|
|
|
1182
1223
|
scope: selectedScope,
|
|
1183
1224
|
});
|
|
1184
1225
|
};
|
|
1226
|
+
const beginSecondScope = (candidate, platform, selectedScope) => {
|
|
1227
|
+
setScope(selectedScope);
|
|
1228
|
+
setSelectedTargets([]);
|
|
1229
|
+
setTargetSelections({});
|
|
1230
|
+
setPreferredTarget(platform);
|
|
1231
|
+
props.controller.beginInstallFlow(candidate.pluginId, selectedScope);
|
|
1232
|
+
go({ name: 'installPlacement', pluginId: candidate.pluginId });
|
|
1233
|
+
};
|
|
1234
|
+
const beginScopeConflictRecovery = (action) => {
|
|
1235
|
+
void beginReview({
|
|
1236
|
+
kind: 'pluginWrite',
|
|
1237
|
+
action: 'uninstall',
|
|
1238
|
+
pluginId: action.pluginId,
|
|
1239
|
+
platform: action.platform,
|
|
1240
|
+
scope: action.scope,
|
|
1241
|
+
recoveryDescription: action.description,
|
|
1242
|
+
});
|
|
1243
|
+
};
|
|
1185
1244
|
const beginAddSource = () => {
|
|
1186
1245
|
const owner = `source-add:${Date.now()}`;
|
|
1187
1246
|
setSourceDraft({ owner, mode: 'add', sourceId: '', type: 'git', location: '', refPolicy: 'cliChannel', ref: '', subdir: '' });
|
|
@@ -1217,6 +1276,9 @@ export function ConsoleAppV4(props) {
|
|
|
1217
1276
|
pluginId,
|
|
1218
1277
|
platform: selectedPlatform,
|
|
1219
1278
|
scope: selectedScope,
|
|
1279
|
+
...(selectedIssue.category === 'scopeConflict' && action.description
|
|
1280
|
+
? { recoveryDescription: action.description }
|
|
1281
|
+
: {}),
|
|
1220
1282
|
originIssue: {
|
|
1221
1283
|
issueId: selectedIssue.issueId,
|
|
1222
1284
|
issueKey: userIssueKey(selectedIssue),
|
|
@@ -1529,27 +1591,14 @@ export function ConsoleAppV4(props) {
|
|
|
1529
1591
|
}
|
|
1530
1592
|
else if (route.name === 'home') {
|
|
1531
1593
|
const home = snapshot.viewModel.home;
|
|
1532
|
-
|
|
1533
|
-
const firstCandidate = candidates[0];
|
|
1534
|
-
context = candidates.length > 0 ? 'Catalog 有更新' : '当前项目';
|
|
1594
|
+
context = '当前项目';
|
|
1535
1595
|
actions = [
|
|
1536
1596
|
{ label: '添加插件', description: '浏览多个来源中的 Agent 能力', meta: String(home.availablePlugins), run: () => go({ name: 'pluginList', mode: 'browse' }) },
|
|
1537
|
-
...(firstCandidate ? [{
|
|
1538
|
-
label: '查看 Catalog 更新…',
|
|
1539
|
-
meta: candidates.length > 1 ? `${candidates.length} 个来源`
|
|
1540
|
-
: firstCandidate.candidate.catalogVersion,
|
|
1541
|
-
status: 'warning',
|
|
1542
|
-
run: () => go({ name: 'catalogCandidate', sourceId: firstCandidate.sourceId }),
|
|
1543
|
-
}] : []),
|
|
1544
1597
|
{ label: '我的插件', description: '查看状态、设置和移除已添加插件', meta: String(home.installedPlugins), run: () => go({ name: 'pluginList', mode: 'installed' }) },
|
|
1545
1598
|
{ label: '需要处理', description: '解决安装、来源或设置问题', meta: String(home.issueCount), status: 'warning', run: () => go({ name: 'issueList' }) },
|
|
1546
1599
|
{ label: '插件来源', description: '管理 Git 仓库和本地目录', meta: String(home.sourceCount), run: () => go({ name: 'sourceList' }) },
|
|
1547
1600
|
];
|
|
1548
|
-
content = _jsxs(Box, { flexDirection: "column", children: [
|
|
1549
|
-
? policy.mode === 'compact'
|
|
1550
|
-
? _jsx(Text, { color: tuiTheme.colors.warning, wrap: "truncate-end", children: `${firstCandidate.sourceId} ${firstCandidate.active?.catalogVersion ?? '未加载'} → ${firstCandidate.candidate.catalogVersion} · 当前操作仍使用 ${props.controller.getSessionCatalogVersion(firstCandidate.sourceId) ?? firstCandidate.active?.catalogVersion ?? '已加载版本'}${candidates.length > 1 ? ` · 另有 ${candidates.length - 1} 个来源` : ''}` })
|
|
1551
|
-
: _jsx(SectionCard, { title: `${firstCandidate.sourceId} ${firstCandidate.active?.catalogVersion ?? '未加载'} → ${firstCandidate.candidate.catalogVersion} · 当前操作仍使用 ${props.controller.getSessionCatalogVersion(firstCandidate.sourceId) ?? firstCandidate.active?.catalogVersion ?? '已加载版本'}`, meta: candidates.length > 1 ? `另有 ${candidates.length - 1} 个来源` : undefined, status: "warning" })
|
|
1552
|
-
: null, _jsxs(StatusCard, { status: home.issueCount > 0 || home.unavailableSourceCount > 0 ? 'warning' : 'success', title: "\u5F53\u524D\u72B6\u6001", children: [_jsx(ResultRow, { title: `${home.installedPlugins} 个插件可用`, status: "success" }), _jsx(ResultRow, { title: `${home.issueCount} 项需要处理`, status: home.issueCount > 0 ? 'warning' : 'muted' }), home.cachedSourceCount > 0 ? _jsx(ResultRow, { title: `${home.cachedSourceCount} 个来源使用缓存`, status: "warning" }) : null, home.unavailableSourceCount > 0 ? _jsx(ResultRow, { title: `${home.unavailableSourceCount} 个来源不可用`, status: "error" }) : null] }), _jsx(SemanticRows, { actions: actions, focus: focus, kind: "task", compact: policy.mode === 'compact' })] });
|
|
1601
|
+
content = _jsxs(Box, { flexDirection: "column", children: [_jsxs(StatusCard, { status: home.issueCount > 0 || home.unavailableSourceCount > 0 ? 'warning' : 'success', title: "\u5F53\u524D\u72B6\u6001", children: [_jsx(ResultRow, { title: `${home.installedPlugins} 个插件可用`, status: "success" }), _jsx(ResultRow, { title: `${home.issueCount} 项需要处理`, status: home.issueCount > 0 ? 'warning' : 'muted' }), home.unavailableSourceCount > 0 ? _jsx(ResultRow, { title: `${home.unavailableSourceCount} 个来源不可用`, status: "error" }) : null] }), _jsx(SemanticRows, { actions: actions, focus: focus, kind: "task", compact: policy.mode === 'compact' })] });
|
|
1553
1602
|
}
|
|
1554
1603
|
else if (route.name === 'pluginList') {
|
|
1555
1604
|
const sourceId = route.sourceId ?? 'all';
|
|
@@ -1572,7 +1621,7 @@ export function ConsoleAppV4(props) {
|
|
|
1572
1621
|
help = `↑↓ 移动 · Enter 查看 · ←→ 来源 · / 搜索${route.mode === 'browse' ? ' · f 未安装' : ''} · Esc 返回`;
|
|
1573
1622
|
const sourceError = sourceId !== 'all' && props.controller.getSourceOverview(sourceId).source?.state === 'error';
|
|
1574
1623
|
actions = sourceError
|
|
1575
|
-
? [{ label: '查看来源问题', description: '
|
|
1624
|
+
? [{ label: '查看来源问题', description: '当前不能浏览这个来源', run: () => go({ name: 'issueDetail', issueId: `source:${sourceId}:unavailable` }) }]
|
|
1576
1625
|
: [];
|
|
1577
1626
|
pluginRows = sourceError ? [] : items.map((item) => ({
|
|
1578
1627
|
pluginId: item.pluginId,
|
|
@@ -1616,7 +1665,7 @@ export function ConsoleAppV4(props) {
|
|
|
1616
1665
|
: _jsxs(_Fragment, { children: [query || '搜索名称、用途或来源…', query ? ' / 编辑' : ''] })] }), route.mode === 'browse'
|
|
1617
1666
|
? _jsxs(Text, { color: tuiTheme.colors.muted, children: ["\u72B6\u6001 ", _jsx(Text, { color: installFilter === 'all' ? tuiTheme.colors.accent : tuiTheme.colors.muted, children: installFilter === 'all' ? '[全部]' : '全部' }), " ", _jsxs(Text, { color: installFilter === 'uninstalled' ? tuiTheme.colors.accent : tuiTheme.colors.muted, children: [installFilter === 'uninstalled' ? '[未安装]' : '未安装', " ", uninstalledCount] }), " f \u5207\u6362"] })
|
|
1618
1667
|
: null, sourceError
|
|
1619
|
-
? _jsx(Callout, { status: "error", title: `${sourceId} 暂时无法提供插件`, description: "\
|
|
1668
|
+
? _jsx(Callout, { status: "error", title: `${sourceId} 暂时无法提供插件`, description: "\u5F53\u524D\u4E0D\u80FD\u6D4F\u89C8\u8FD9\u4E2A\u6765\u6E90\u3002" })
|
|
1620
1669
|
: route.mode === 'installed' && items.length === 0
|
|
1621
1670
|
? _jsx(Callout, { title: "\u5F00\u59CB\u6DFB\u52A0\u7B2C\u4E00\u4E2A\u63D2\u4EF6", description: "\u63D2\u4EF6\u53EF\u4EE5\u5B89\u88C5\u5230 Codex\u3001Claude Code \u6216\u4E24\u8005\u3002" })
|
|
1622
1671
|
: null, pluginRows.length > 0
|
|
@@ -1639,6 +1688,7 @@ export function ConsoleAppV4(props) {
|
|
|
1639
1688
|
setSelectedTargets([]);
|
|
1640
1689
|
setTargetSelections({});
|
|
1641
1690
|
setPreferredTarget(undefined);
|
|
1691
|
+
props.controller.beginInstallFlow(plugin.pluginId, initialScope);
|
|
1642
1692
|
if (available.length > 0)
|
|
1643
1693
|
go({ name: 'installPlacement', pluginId: plugin.pluginId });
|
|
1644
1694
|
else
|
|
@@ -1664,6 +1714,19 @@ export function ConsoleAppV4(props) {
|
|
|
1664
1714
|
return { label: '查看插件设置', description: `${plugin.configFieldCount} 个配置字段及当前来源`, run: () => beginConfigFlow(plugin.pluginId) };
|
|
1665
1715
|
if (action.id === 'sourceProblem')
|
|
1666
1716
|
return { label: '查看来源问题', status: 'warning', run: () => go({ name: 'sourceDetail', sourceId: plugin.sourceId }) };
|
|
1717
|
+
if (action.id === 'outputCollision') {
|
|
1718
|
+
const collision = props.controller.listUserIssues().find((issue) => issue.pluginId === plugin.pluginId && issue.category === 'artifactCollision');
|
|
1719
|
+
return {
|
|
1720
|
+
label: '查看输出冲突',
|
|
1721
|
+
description: '目标位置已有不属于当前插件的内容',
|
|
1722
|
+
status: 'error',
|
|
1723
|
+
run: () => collision
|
|
1724
|
+
? go({ name: 'issueDetail', issueId: collision.issueId })
|
|
1725
|
+
: go({ name: 'pluginTechnical', pluginId: plugin.pluginId }),
|
|
1726
|
+
};
|
|
1727
|
+
}
|
|
1728
|
+
if (action.id === 'about')
|
|
1729
|
+
return { label: '关于', run: () => go({ name: 'pluginAbout', pluginId: plugin.pluginId }) };
|
|
1667
1730
|
return { label: '查看来源', run: () => go({ name: 'sourceDetail', sourceId: plugin.sourceId }) };
|
|
1668
1731
|
};
|
|
1669
1732
|
const previewMenu = dynamicMenu;
|
|
@@ -1906,8 +1969,28 @@ export function ConsoleAppV4(props) {
|
|
|
1906
1969
|
breadcrumb = `${plugin.displayName} / 依赖关系`;
|
|
1907
1970
|
context = overview ? `${overview.summary.totalCount + 1} 个插件` : '只读';
|
|
1908
1971
|
title = hasInstalledPlacement(plugin) ? '依赖与被使用情况' : '安装所需插件';
|
|
1909
|
-
description = '
|
|
1972
|
+
description = '依赖由同一来源快照解析;调整前会进入 Review。';
|
|
1973
|
+
const installedTargets = plugin.installedPlacements.filter((placement) => placement.state === 'installed');
|
|
1910
1974
|
actions = [
|
|
1975
|
+
...(hasInstalledPlacement(plugin) && dependencyCount > 0 && installedTargets.length > 0 ? [{
|
|
1976
|
+
label: '调整依赖位置…',
|
|
1977
|
+
description: '按平台设置 project/user;不会自动清理所有项目内容',
|
|
1978
|
+
run: async () => {
|
|
1979
|
+
const rootScope = installedTargets.some((placement) => placement.desiredScopes?.includes('project') || placement.scope === 'project')
|
|
1980
|
+
? 'project' : 'user';
|
|
1981
|
+
const platforms = [...new Set(installedTargets.map((placement) => placement.platform))];
|
|
1982
|
+
setScope(rootScope);
|
|
1983
|
+
setSelectedTargets(platforms);
|
|
1984
|
+
props.controller.beginInstallFlow(plugin.pluginId, rootScope, { adjustingExisting: true });
|
|
1985
|
+
props.controller.setInstallPlatforms(platforms);
|
|
1986
|
+
const configurable = await props.controller.prepareInstallDependencyPlacement();
|
|
1987
|
+
if (!configurable) {
|
|
1988
|
+
setActionError('当前依赖位置都由约束固定,没有可调整项。');
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
go({ name: 'dependencyPlacement', pluginId: plugin.pluginId });
|
|
1992
|
+
},
|
|
1993
|
+
}] : []),
|
|
1911
1994
|
{ label: '技术详情', description: '显示 canonical pluginId 和安全错误代码', run: () => setShowTechnical((value) => !value) },
|
|
1912
1995
|
];
|
|
1913
1996
|
const rootStatus = plugin.aggregateStatus === 'installed' ? 'success'
|
|
@@ -1959,23 +2042,19 @@ export function ConsoleAppV4(props) {
|
|
|
1959
2042
|
breadcrumb = `${plugin.displayName} / 添加`;
|
|
1960
2043
|
context = '第 1 步,共 2 步';
|
|
1961
2044
|
title = `你希望在哪里使用 ${plugin.displayName}?`;
|
|
1962
|
-
const overview = dependencyOverview(plugin);
|
|
1963
2045
|
const hasDependencies = (plugin.dependencySummary?.totalCount ?? 0) > 0;
|
|
1964
2046
|
description = hasDependencies
|
|
1965
|
-
? '
|
|
2047
|
+
? '这里只选择根插件位置。依赖可以在下一步单独调整;依赖不能比根插件位置更窄。'
|
|
1966
2048
|
: '选择位置后,再选择一个或多个目标平台。';
|
|
1967
2049
|
const availableScopes = ['user', 'project'].filter((candidateScope) => props.controller.listInstallTargets(plugin.pluginId, candidateScope)
|
|
1968
2050
|
.some((entry) => entry.compatible));
|
|
1969
|
-
const reusableDependencies = overview?.dependencies.filter((dependency) => dependency.placements.some((placement) => placement.state === 'installed' && placement.health === 'ready'
|
|
1970
|
-
&& (scope === 'project' || placement.scope === 'user'))).length ?? 0;
|
|
1971
|
-
const missingDependencies = Math.max(0, (overview?.summary.totalCount ?? 0) - reusableDependencies);
|
|
1972
2051
|
actions = [
|
|
1973
2052
|
...availableScopes.map((candidateScope) => ({
|
|
1974
2053
|
label: scopeLabel(candidateScope),
|
|
1975
2054
|
selected: candidateScope === scope,
|
|
1976
2055
|
description: candidateScope === 'user'
|
|
1977
|
-
? hasDependencies ? '
|
|
1978
|
-
: hasDependencies ? '
|
|
2056
|
+
? hasDependencies ? '根插件在任意项目中可用;依赖位置下一步确认' : '在任意项目中可使用,适合个人常用能力'
|
|
2057
|
+
: hasDependencies ? '根插件只在当前项目使用;依赖可单独调整为所有项目' : '仅在当前项目中使用,适合团队共享',
|
|
1979
2058
|
meta: candidateScope === 'user' ? '推荐' : undefined,
|
|
1980
2059
|
run: () => {
|
|
1981
2060
|
const choices = props.controller.listInstallTargets(plugin.pluginId, candidateScope);
|
|
@@ -1989,6 +2068,7 @@ export function ConsoleAppV4(props) {
|
|
|
1989
2068
|
setScope(candidateScope);
|
|
1990
2069
|
setSelectedTargets(next);
|
|
1991
2070
|
setTargetSelections((current) => ({ ...current, [candidateScope]: next }));
|
|
2071
|
+
props.controller.setInstallRootScope(candidateScope);
|
|
1992
2072
|
go({
|
|
1993
2073
|
name: 'installTargets',
|
|
1994
2074
|
pluginId: plugin.pluginId,
|
|
@@ -1997,7 +2077,7 @@ export function ConsoleAppV4(props) {
|
|
|
1997
2077
|
},
|
|
1998
2078
|
})),
|
|
1999
2079
|
];
|
|
2000
|
-
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(SemanticRows, { actions: actions, focus: focus, kind: "choice", compact: policy.mode === 'compact' }), hasDependencies ?
|
|
2080
|
+
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(SemanticRows, { actions: actions, focus: focus, kind: "choice", compact: policy.mode === 'compact' }), hasDependencies ? _jsx(SectionCard, { title: "\u4F9D\u8D56\u4F4D\u7F6E", children: _jsx(StaticRow, { title: `${plugin.dependencySummary?.totalCount ?? 0} 个依赖将在下一步单独确认`, status: "info" }) }) : null] });
|
|
2001
2081
|
}
|
|
2002
2082
|
else if (route.name === 'installTargets' && plugin) {
|
|
2003
2083
|
breadcrumb = `${plugin.displayName} / 添加 / 目标平台`;
|
|
@@ -2005,8 +2085,8 @@ export function ConsoleAppV4(props) {
|
|
|
2005
2085
|
title = '选择目标平台';
|
|
2006
2086
|
const hasDependencies = (plugin.dependencySummary?.totalCount ?? 0) > 0;
|
|
2007
2087
|
description = hasDependencies
|
|
2008
|
-
? '
|
|
2009
|
-
: '
|
|
2088
|
+
? '根插件必须支持所选位置;每个依赖必须至少有一个合法位置。'
|
|
2089
|
+
: '目标平台按所选位置验证;仅含 Codex native 的插件可同时启用两个位置。';
|
|
2010
2090
|
const choices = props.controller.listInstallTargets(plugin.pluginId, scope);
|
|
2011
2091
|
const validSelectedTargets = selectedTargets.filter((platform) => choices.some((choice) => choice.platform === platform && choice.compatible));
|
|
2012
2092
|
const allUnavailable = choices.length > 0 && choices.every((choice) => !choice.compatible);
|
|
@@ -2035,6 +2115,7 @@ export function ConsoleAppV4(props) {
|
|
|
2035
2115
|
? current.filter((platform) => platform !== choice.platform)
|
|
2036
2116
|
: [...current, choice.platform];
|
|
2037
2117
|
setTargetSelections((selections) => ({ ...selections, [scope]: next }));
|
|
2118
|
+
props.controller.setInstallPlatforms(next);
|
|
2038
2119
|
return next;
|
|
2039
2120
|
});
|
|
2040
2121
|
},
|
|
@@ -2047,7 +2128,15 @@ export function ConsoleAppV4(props) {
|
|
|
2047
2128
|
disabled: validSelectedTargets.length === 0 ? '至少选择一个目标平台' : undefined,
|
|
2048
2129
|
run: () => {
|
|
2049
2130
|
setDirty(false);
|
|
2050
|
-
|
|
2131
|
+
if (!hasDependencies) {
|
|
2132
|
+
if (props.controller.snapshot.installPlacementDraft?.pluginId !== plugin.pluginId) {
|
|
2133
|
+
props.controller.beginInstallFlow(plugin.pluginId, scope);
|
|
2134
|
+
}
|
|
2135
|
+
props.controller.setInstallPlatforms(validSelectedTargets);
|
|
2136
|
+
beginReview(props.controller.installPlacementIntent());
|
|
2137
|
+
return;
|
|
2138
|
+
}
|
|
2139
|
+
return continueInstallAfterTargets(plugin, validSelectedTargets);
|
|
2051
2140
|
},
|
|
2052
2141
|
},
|
|
2053
2142
|
{ label: '返回选择位置', run: back },
|
|
@@ -2056,6 +2145,83 @@ export function ConsoleAppV4(props) {
|
|
|
2056
2145
|
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(SemanticRows, { actions: actions, focus: focus, kind: "toggle", compact: policy.mode === 'compact', limit: targetActions.length }), hasDependencies ? _jsx(Callout, { title: "\u76EE\u6807\u5E73\u53F0\u517C\u5BB9\u6027", description: "\u4E0D\u517C\u5BB9\u7684\u76EE\u6807\u5E73\u53F0\u4E0D\u80FD\u9009\u62E9\uFF1B\u8BF7\u67E5\u770B\u4F9D\u8D56\u5173\u7CFB\u4E86\u89E3\u539F\u56E0\u3002" }) : null, _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: policy.mode === 'compact', offset: targetActions.length })] });
|
|
2057
2146
|
}
|
|
2058
2147
|
}
|
|
2148
|
+
else if (route.name === 'dependencyPlacement' && plugin) {
|
|
2149
|
+
const draft = snapshot.installPlacementDraft?.pluginId === plugin.pluginId
|
|
2150
|
+
? snapshot.installPlacementDraft : undefined;
|
|
2151
|
+
breadcrumb = `${plugin.displayName} / 添加 / 依赖位置`;
|
|
2152
|
+
context = '依赖位置';
|
|
2153
|
+
title = '选择每个平台的依赖位置';
|
|
2154
|
+
description = '每个直接或间接依赖都可独立设置。所有项目位置更宽,会影响其他项目和你的用户环境。';
|
|
2155
|
+
const dependencyActions = (draft?.targets ?? []).map((target) => ({
|
|
2156
|
+
label: `${target.displayName} · ${platformLabel(target.platform)}`,
|
|
2157
|
+
description: `${target.relation === 'direct' ? '直接依赖' : '间接依赖'} · ${target.explanation}`,
|
|
2158
|
+
meta: `${scopeLabel(target.scope)}${target.assignmentSource === 'consumerPromotion' ? ' · fixed-point 提升' : ''}`,
|
|
2159
|
+
selected: true,
|
|
2160
|
+
disabled: target.locked ? '位置由平台或上游约束固定' : undefined,
|
|
2161
|
+
run: () => go({
|
|
2162
|
+
name: 'dependencyPlacementEditor',
|
|
2163
|
+
pluginId: plugin.pluginId,
|
|
2164
|
+
dependencyPluginId: target.pluginId,
|
|
2165
|
+
platform: target.platform,
|
|
2166
|
+
}),
|
|
2167
|
+
}));
|
|
2168
|
+
actions = [
|
|
2169
|
+
...dependencyActions,
|
|
2170
|
+
{
|
|
2171
|
+
label: '继续到确认',
|
|
2172
|
+
description: draft?.canContinue ? '使用这些最终位置准备 Review' : undefined,
|
|
2173
|
+
disabled: !draft?.canContinue ? draft?.error?.message ?? '依赖位置尚未就绪' : undefined,
|
|
2174
|
+
run: () => beginReview(props.controller.installPlacementIntent()),
|
|
2175
|
+
},
|
|
2176
|
+
{
|
|
2177
|
+
label: '恢复推荐位置',
|
|
2178
|
+
description: '恢复默认、健康 user 复用和 fixed-point 计算结果',
|
|
2179
|
+
run: () => props.controller.resetDependencyScopes(),
|
|
2180
|
+
},
|
|
2181
|
+
{ label: '返回目标平台', run: back },
|
|
2182
|
+
];
|
|
2183
|
+
const placementViewport = actionViewport(actions, policy.mode === 'compact', focus, scrollOffset, pageActionBudget(dependencyPlacementStaticRows));
|
|
2184
|
+
const userCount = draft?.targets.filter((target) => target.scope === 'user').length ?? 0;
|
|
2185
|
+
const defaultCount = draft?.targets.filter((target) => target.assignmentSource === 'default').length ?? 0;
|
|
2186
|
+
const reusedCount = draft?.targets.filter((target) => target.assignmentSource === 'existingWiderTarget').length ?? 0;
|
|
2187
|
+
const promotedCount = draft?.targets.filter((target) => target.assignmentSource === 'consumerPromotion').length ?? 0;
|
|
2188
|
+
const reasonSummary = [
|
|
2189
|
+
...(defaultCount > 0 ? [`默认 project ${defaultCount} 项`] : []),
|
|
2190
|
+
...(reusedCount > 0 ? [`复用健康的所有项目安装 ${reusedCount} 项`] : []),
|
|
2191
|
+
...(promotedCount > 0 ? [`fixed-point 提升 ${promotedCount} 项`] : []),
|
|
2192
|
+
].join(';');
|
|
2193
|
+
content = _jsxs(Box, { flexDirection: "column", children: [policy.mode === 'compact'
|
|
2194
|
+
? _jsxs(_Fragment, { children: [_jsx(StaticRow, { title: `根插件 · ${plugin.displayName}`, meta: draft ? scopeLabel(draft.rootScope) : '未就绪', compact: true }), _jsx(StaticRow, { title: `位置原因 · ${reasonSummary || '由平台或上游约束固定'}`, status: userCount > 0 ? 'warning' : 'info', compact: true }), _jsx(StaticRow, { title: "\u8303\u56F4\u63D0\u793A \u00B7 \u6240\u6709\u9879\u76EE\u4F4D\u7F6E\u4F1A\u5F71\u54CD\u5176\u4ED6\u9879\u76EE\u548C\u7528\u6237\u73AF\u5883", status: userCount > 0 ? 'warning' : 'muted', compact: true })] })
|
|
2195
|
+
: _jsxs(_Fragment, { children: [_jsx(SectionCard, { title: "\u6839\u63D2\u4EF6\u4F4D\u7F6E", children: _jsx(StaticRow, { title: plugin.displayName, meta: draft ? scopeLabel(draft.rootScope) : '未就绪', compact: true }) }), _jsx(Callout, { status: userCount > 0 ? 'warning' : 'info', title: userCount > 0 ? `${userCount} 个依赖平台目标使用所有项目位置` : '位置计算原因', description: `${reasonSummary || '依赖位置由平台或上游约束固定'}${userCount > 0 ? ';所有项目位置对其他项目也可见,并会改变你的用户环境' : ''}。` })] }), _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: policy.mode === 'compact', offset: placementViewport.offset, limit: placementViewport.limit })] });
|
|
2196
|
+
help = '↑↓ 移动 · Enter 打开/继续 · Esc 返回';
|
|
2197
|
+
}
|
|
2198
|
+
else if (route.name === 'dependencyPlacementEditor' && plugin) {
|
|
2199
|
+
const target = snapshot.installPlacementDraft?.targets.find((entry) => entry.pluginId === route.dependencyPluginId && entry.platform === route.platform);
|
|
2200
|
+
breadcrumb = `${plugin.displayName} / 依赖位置 / ${target?.displayName ?? route.dependencyPluginId}`;
|
|
2201
|
+
context = platformLabel(route.platform);
|
|
2202
|
+
title = `设置 ${target?.displayName ?? route.dependencyPluginId} 的位置`;
|
|
2203
|
+
description = target?.explanation ?? '依赖位置已变化。请返回重新检查。';
|
|
2204
|
+
actions = ['project', 'user'].map((candidateScope) => {
|
|
2205
|
+
const unavailable = !target?.allowedScopes.includes(candidateScope)
|
|
2206
|
+
|| target.minimumScope === 'user' && candidateScope === 'project';
|
|
2207
|
+
return {
|
|
2208
|
+
label: scopeLabel(candidateScope),
|
|
2209
|
+
selected: target?.scope === candidateScope,
|
|
2210
|
+
description: candidateScope === 'user'
|
|
2211
|
+
? '更宽:对其他项目可见,并会改变你的用户环境'
|
|
2212
|
+
: '仅供当前项目使用;适合项目共享 intent',
|
|
2213
|
+
disabled: unavailable ? '这个依赖或上游约束不允许此位置' : undefined,
|
|
2214
|
+
run: async () => {
|
|
2215
|
+
await props.controller.setDependencyScope(route.dependencyPluginId, route.platform, candidateScope);
|
|
2216
|
+
back();
|
|
2217
|
+
},
|
|
2218
|
+
};
|
|
2219
|
+
});
|
|
2220
|
+
content = _jsxs(Box, { flexDirection: "column", children: [target?.assignmentSource === 'consumerPromotion'
|
|
2221
|
+
? _jsx(Callout, { status: "warning", title: "fixed-point \u4F4D\u7F6E\u63D0\u5347", description: `上游依赖需要至少使用${scopeLabel(target.minimumScope)}。` })
|
|
2222
|
+
: null, _jsx(SemanticRows, { actions: actions, focus: focus, kind: "choice", compact: policy.mode === 'compact' })] });
|
|
2223
|
+
help = '↑↓ 移动 · Enter 选择 · Esc 返回';
|
|
2224
|
+
}
|
|
2059
2225
|
else if (route.name === 'pluginDetail' && plugin) {
|
|
2060
2226
|
breadcrumb = `我的插件 / ${plugin.displayName}`;
|
|
2061
2227
|
context = `${plugin.sourceLabel}${plugin.version ? ` · ${plugin.version}` : ''}`;
|
|
@@ -2064,6 +2230,13 @@ export function ConsoleAppV4(props) {
|
|
|
2064
2230
|
const dependencySummary = plugin.dependencySummary;
|
|
2065
2231
|
const detailMenu = dynamicMenu;
|
|
2066
2232
|
actions = detailMenu.map((action) => {
|
|
2233
|
+
if (action.id === 'resolveScopeConflict')
|
|
2234
|
+
return {
|
|
2235
|
+
label: `保留${scopeLabel(action.keepScope)},移除${scopeLabel(action.scope)} root…`,
|
|
2236
|
+
description: action.description,
|
|
2237
|
+
status: 'error',
|
|
2238
|
+
run: () => beginScopeConflictRecovery(action),
|
|
2239
|
+
};
|
|
2067
2240
|
if (action.id === 'platform' || action.id === 'scopeConflict') {
|
|
2068
2241
|
const placement = plugin.installedPlacements.find((entry) => entry.platform === action.platform);
|
|
2069
2242
|
const projected = placementStatus(placement);
|
|
@@ -2109,14 +2282,20 @@ export function ConsoleAppV4(props) {
|
|
|
2109
2282
|
&& candidate.platform === route.platform
|
|
2110
2283
|
&& candidate.scope === placement.scope)
|
|
2111
2284
|
: undefined;
|
|
2285
|
+
const collisionIssue = placement?.state === 'blocked'
|
|
2286
|
+
|| placement?.state === 'installed' && placement.blockingReason === 'artifactCollision'
|
|
2287
|
+
? props.controller.listUserIssues().find((candidate) => candidate.pluginId === plugin.pluginId
|
|
2288
|
+
&& candidate.platform === route.platform
|
|
2289
|
+
&& candidate.category === 'artifactCollision')
|
|
2290
|
+
: undefined;
|
|
2112
2291
|
const sourceIssue = plugin.aggregateStatus === 'unavailable'
|
|
2113
2292
|
? props.controller.listUserIssues().find((candidate) => candidate.entity.kind === 'source' && candidate.sourceId === plugin.sourceId)
|
|
2114
2293
|
: undefined;
|
|
2115
2294
|
const platformAction = (action) => {
|
|
2116
2295
|
if (action.id === 'sourceProblem')
|
|
2117
|
-
return { label: '查看来源问题', description: `${plugin.sourceId}
|
|
2296
|
+
return { label: '查看来源问题', description: `${plugin.sourceId} 当前不可用`, run: () => go({ name: 'issueDetail', issueId: `source:${plugin.sourceId}:unavailable` }) };
|
|
2118
2297
|
if (action.id === 'refreshSource')
|
|
2119
|
-
return { label: '
|
|
2298
|
+
return { label: '重新加载状态', description: `如需同步,先在终端运行 aw catalog source sync ${plugin.sourceId}`, run: async () => { await props.controller.reloadCatalog({ sourceId: plugin.sourceId }); } };
|
|
2120
2299
|
if (action.id === 'add')
|
|
2121
2300
|
return { label: `添加到 ${platformLabel(route.platform)}…`, description: '选择使用位置', run: () => {
|
|
2122
2301
|
const initialScope = placement?.state === 'notInstalled'
|
|
@@ -2126,14 +2305,50 @@ export function ConsoleAppV4(props) {
|
|
|
2126
2305
|
setSelectedTargets([]);
|
|
2127
2306
|
setTargetSelections({});
|
|
2128
2307
|
setPreferredTarget(route.platform);
|
|
2308
|
+
props.controller.beginInstallFlow(plugin.pluginId, initialScope);
|
|
2129
2309
|
go({ name: 'installPlacement', pluginId: plugin.pluginId });
|
|
2130
2310
|
} };
|
|
2311
|
+
if (action.id === 'addScope')
|
|
2312
|
+
return {
|
|
2313
|
+
label: `在${scopeLabel(action.scope)}中启用…`,
|
|
2314
|
+
description: '只增加该 scope 的 activation;shared native 保持复用',
|
|
2315
|
+
run: () => beginSecondScope(plugin, action.platform, action.scope),
|
|
2316
|
+
};
|
|
2131
2317
|
if (action.id === 'about')
|
|
2132
2318
|
return { label: '查看支持信息', description: 'manifest 与平台能力', run: () => go({ name: 'pluginAbout', pluginId: plugin.pluginId }) };
|
|
2319
|
+
if (action.id === 'source')
|
|
2320
|
+
return { label: '查看来源', run: () => go({ name: 'sourceDetail', sourceId: plugin.sourceId }) };
|
|
2321
|
+
if (action.id === 'outputCollision')
|
|
2322
|
+
return {
|
|
2323
|
+
label: '查看输出冲突',
|
|
2324
|
+
description: '不会覆盖或删除占用内容',
|
|
2325
|
+
status: 'error',
|
|
2326
|
+
run: () => collisionIssue
|
|
2327
|
+
? go({ name: 'issueDetail', issueId: collisionIssue.issueId })
|
|
2328
|
+
: go({ name: 'pluginTechnical', pluginId: plugin.pluginId }),
|
|
2329
|
+
};
|
|
2133
2330
|
if (action.id === 'scopeConflict')
|
|
2134
2331
|
return { label: '查看位置冲突问题', run: () => go({ name: 'issueDetail', issueId: `scope:${plugin.pluginId}:${route.platform}` }) };
|
|
2332
|
+
if (action.id === 'resolveScopeConflict')
|
|
2333
|
+
return {
|
|
2334
|
+
label: `保留${scopeLabel(action.keepScope)},移除${scopeLabel(action.scope)} root…`,
|
|
2335
|
+
description: action.description,
|
|
2336
|
+
status: 'error',
|
|
2337
|
+
run: () => beginScopeConflictRecovery(action),
|
|
2338
|
+
};
|
|
2135
2339
|
if (action.id === 'upgrade')
|
|
2136
2340
|
return { label: `升级到 ${action.availableVersion}…`, description: '使用当前来源中的版本重建', run: () => beginReview({ kind: 'pluginWrite', action: 'upgrade', pluginId: plugin.pluginId, platform: action.platform, scope: action.scope }) };
|
|
2341
|
+
if (action.id === 'sync')
|
|
2342
|
+
return {
|
|
2343
|
+
label: '同步 desired intent…',
|
|
2344
|
+
description: placement?.state === 'installed'
|
|
2345
|
+
? placement.recovery?.find((entry) => entry.command === 'sync')?.description
|
|
2346
|
+
?? '进入现有 Review、进度和结果链修复 needsSync 或 drift'
|
|
2347
|
+
: undefined,
|
|
2348
|
+
run: () => placement?.state === 'installed'
|
|
2349
|
+
? beginReview({ kind: 'pluginWrite', action: 'sync', pluginId: plugin.pluginId, platform: route.platform, scope: placement.scope })
|
|
2350
|
+
: undefined,
|
|
2351
|
+
};
|
|
2137
2352
|
if (action.id === 'reinstall')
|
|
2138
2353
|
return { label: placement?.state === 'installed' && placement.health === 'incomplete' ? '重新连接缺失内容…' : '重新安装…', description: '保留现有设置并重新生成受管内容', run: () => beginReview({ kind: 'pluginWrite', action: 'reinstall', pluginId: plugin.pluginId, platform: action.platform, scope: action.scope }) };
|
|
2139
2354
|
if (action.id === 'remove')
|
|
@@ -2145,6 +2360,7 @@ export function ConsoleAppV4(props) {
|
|
|
2145
2360
|
return { label: '返回插件', run: back };
|
|
2146
2361
|
};
|
|
2147
2362
|
breadcrumb = `${plugin.displayName} / ${platformLabel(route.platform)}`;
|
|
2363
|
+
const installedPlacementRows = placement?.state === 'installed' ? _jsxs(_Fragment, { children: [_jsx(StaticRow, { title: "Desired placement", meta: placement.desiredScopes?.map(scopeLabel).join('、') || scopeLabel(placement.scope), compact: true }), _jsx(StaticRow, { title: "Actual scope \u72B6\u6001", meta: placement.actualState ?? placement.health, status: placement.actualState === 'ready' ? 'success' : placement.actualState === 'conflict' ? 'error' : 'warning', compact: true }), placement.sharedNative ? _jsx(StaticRow, { title: "Shared native", meta: placement.sharedNative.state, status: placement.sharedNative.state === 'present' ? 'success' : 'warning', compact: true }) : null, placement.activation ? _jsx(StaticRow, { title: "Activation", meta: `user ${placement.activation.user ? 'on' : 'off'} · project ${placement.activation.project ? 'on' : 'off'}`, compact: true }) : null, placement.extensions ? _jsx(StaticRow, { title: "AW-only extensions", meta: `${placement.extensions.state} · ${placement.extensions.kinds.join('、') || '无'}`, status: placement.extensions.state === 'ready' ? 'success' : placement.extensions.state === 'conflict' ? 'error' : 'warning', compact: true }) : null] }) : null;
|
|
2148
2364
|
if (plugin.aggregateStatus === 'unavailable') {
|
|
2149
2365
|
const sourceOverview = props.controller.getSourceOverview(plugin.sourceId);
|
|
2150
2366
|
const diagnostic = sourceIssue?.diagnostic ?? sourceDiagnostic(plugin.sourceId, sourceOverview.health?.state ?? sourceOverview.source?.state, sourceOverview.detail);
|
|
@@ -2161,6 +2377,15 @@ export function ConsoleAppV4(props) {
|
|
|
2161
2377
|
actions = platformMenu.map(platformAction);
|
|
2162
2378
|
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(StatusCard, { status: "muted", title: "\u672A\u6DFB\u52A0", description: "\u63D2\u4EF6\u8BBE\u7F6E\u4FDD\u6301\u4E0D\u53D8" }), _jsx(SemanticRows, { actions: actions, focus: effectiveFocus, kind: "action", compact: policy.mode === 'compact' })] });
|
|
2163
2379
|
}
|
|
2380
|
+
else if (placement.state === 'blocked'
|
|
2381
|
+
|| placement.state === 'installed' && placement.blockingReason === 'artifactCollision') {
|
|
2382
|
+
title = `${platformLabel(route.platform)} 无法添加`;
|
|
2383
|
+
description = placement.state === 'installed'
|
|
2384
|
+
? '受管内容仍可安全移除;输出位置同时存在冲突内容。'
|
|
2385
|
+
: '输出位置已有不属于当前插件的内容。';
|
|
2386
|
+
actions = platformMenu.map(platformAction);
|
|
2387
|
+
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(StatusCard, { status: "error", title: "\u8F93\u51FA\u51B2\u7A81", description: "AW \u4E0D\u4F1A\u8986\u76D6\u6216\u5220\u9664\u5360\u7528\u5185\u5BB9" }), _jsx(SemanticRows, { actions: actions, focus: effectiveFocus, kind: "action", compact: policy.mode === 'compact' })] });
|
|
2388
|
+
}
|
|
2164
2389
|
else if (placement.state === 'scopeConflict') {
|
|
2165
2390
|
title = '安装位置冲突';
|
|
2166
2391
|
description = '正常状态只能保留一个位置。';
|
|
@@ -2196,14 +2421,17 @@ export function ConsoleAppV4(props) {
|
|
|
2196
2421
|
title = `${platformLabel(route.platform)} ${placement.health === 'incomplete' ? '安装不完整' : '暂时不可用'}`;
|
|
2197
2422
|
description = '缺少一项必要内容,插件可能无法稳定启动。';
|
|
2198
2423
|
actions = platformMenu.map(platformAction);
|
|
2199
|
-
|
|
2424
|
+
const actualTitle = placement.actualState === 'needsSync' ? '需要同步'
|
|
2425
|
+
: placement.actualState === 'drifted' ? '现场已漂移'
|
|
2426
|
+
: placement.actualState === 'conflict' ? '位置与扩展冲突' : '需要处理';
|
|
2427
|
+
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(StatusCard, { status: placement.actualState === 'conflict' ? 'error' : 'warning', title: actualTitle, description: `${scopeLabel(placement.scope)} · ${plugin.sourceLabel}`, children: installedPlacementRows }), _jsx(SemanticRows, { actions: actions, focus: effectiveFocus, kind: "action", compact: policy.mode === 'compact' })] });
|
|
2200
2428
|
}
|
|
2201
2429
|
else {
|
|
2202
2430
|
title = `已安装到${scopeLabel(placement.scope)}`;
|
|
2203
2431
|
const installedVersion = placement.revision.installedVersion;
|
|
2204
2432
|
description = `当前检查正常${installedVersion ? `;已安装版本 ${installedVersion}` : ''}。`;
|
|
2205
2433
|
actions = platformMenu.map(platformAction);
|
|
2206
|
-
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(StatusCard, { status: "success", title: "\u72B6\u6001\u6B63\u5E38", description: `${scopeLabel(placement.scope)}${installedVersion ? ` · 已安装版本 ${installedVersion}` : ''}
|
|
2434
|
+
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(StatusCard, { status: "success", title: "\u72B6\u6001\u6B63\u5E38", description: `${scopeLabel(placement.scope)}${installedVersion ? ` · 已安装版本 ${installedVersion}` : ''}`, children: installedPlacementRows }), _jsx(SemanticRows, { actions: actions, focus: effectiveFocus, kind: "action", compact: policy.mode === 'compact' })] });
|
|
2207
2435
|
}
|
|
2208
2436
|
}
|
|
2209
2437
|
else if (route.name === 'configLayer' && plugin) {
|
|
@@ -2401,11 +2629,7 @@ export function ConsoleAppV4(props) {
|
|
|
2401
2629
|
title = diagnostic.title;
|
|
2402
2630
|
description = '';
|
|
2403
2631
|
actions = [
|
|
2404
|
-
{ label:
|
|
2405
|
-
await props.controller.refreshSource(plugin.sourceId);
|
|
2406
|
-
setConfigLoadKey((value) => value + 1);
|
|
2407
|
-
props.controller.replace({ name: 'configFields', pluginId: plugin.pluginId, layer: route.layer ?? { scope: 'user', projectLayer: 'shared' } });
|
|
2408
|
-
} },
|
|
2632
|
+
{ label: `在终端运行 aw catalog source sync ${plugin.sourceId}`, description: '同步成功后重新加载 TUI', run: back },
|
|
2409
2633
|
{ label: showTechnical ? '返回问题摘要' : '技术详情', description: '查看脱敏错误代码和阶段', run: () => setShowTechnical((value) => !value) },
|
|
2410
2634
|
{ label: '返回', run: back },
|
|
2411
2635
|
];
|
|
@@ -2416,29 +2640,21 @@ export function ConsoleAppV4(props) {
|
|
|
2416
2640
|
title = '插件来源';
|
|
2417
2641
|
description = '单个来源失败不会阻止其他来源继续工作。';
|
|
2418
2642
|
context = `${props.controller.listSources().length} 个来源`;
|
|
2419
|
-
help = '↑↓ 移动 · Enter 打开 ·
|
|
2643
|
+
help = '↑↓ 移动 · Enter 打开 · Esc 返回';
|
|
2420
2644
|
actions = [
|
|
2421
2645
|
...props.controller.listSources().map((source) => {
|
|
2422
2646
|
const overview = props.controller.getSourceOverview(source.id);
|
|
2423
2647
|
const generation = props.controller.getCatalogGeneration(source.id);
|
|
2424
2648
|
const health = overview.health?.state ?? source.state;
|
|
2425
|
-
const status = generation?.
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
: generation?.refreshState === 'immutableViolation' ? '发布异常'
|
|
2429
|
-
: generation?.candidate ? `可用更新 ${generation.candidate.catalogVersion}`
|
|
2430
|
-
: health === 'ready' ? '已从远端加载'
|
|
2431
|
-
: health === 'path' ? '本地目录'
|
|
2432
|
-
: health === 'checking' ? '正在检查'
|
|
2433
|
-
: health === 'cache' || health === 'degraded' ? '使用缓存' : '无法读取';
|
|
2649
|
+
const status = generation?.active ? `Active ${generation.active.catalogVersion}`
|
|
2650
|
+
: health === 'ready' ? '当前使用'
|
|
2651
|
+
: '无法读取';
|
|
2434
2652
|
return {
|
|
2435
2653
|
label: `${source.id}${source.primary ? ' 主来源' : ''}`,
|
|
2436
2654
|
description: `${overview.detail?.type === 'path' ? '本地目录' : 'Git 仓库'} · ${source.count ?? 0} 个插件`,
|
|
2437
2655
|
meta: status,
|
|
2438
|
-
status: generation?.
|
|
2439
|
-
:
|
|
2440
|
-
: health === 'cache' || health === 'degraded' ? 'warning'
|
|
2441
|
-
: source.primary ? 'success' : undefined,
|
|
2656
|
+
status: !generation?.active || health === 'unavailable' ? 'error'
|
|
2657
|
+
: source.primary ? 'success' : undefined,
|
|
2442
2658
|
run: () => go({ name: 'sourceDetail', sourceId: source.id }),
|
|
2443
2659
|
};
|
|
2444
2660
|
}),
|
|
@@ -2451,155 +2667,35 @@ export function ConsoleAppV4(props) {
|
|
|
2451
2667
|
else if (route.name === 'sourceDetail') {
|
|
2452
2668
|
const overview = props.controller.getSourceOverview(route.sourceId);
|
|
2453
2669
|
const detail = overview.detail;
|
|
2454
|
-
const state = overview.health?.state ?? overview.source?.state;
|
|
2455
|
-
const diagnostic = sourceDiagnostic(route.sourceId, state, detail);
|
|
2456
2670
|
const generation = props.controller.getCatalogGeneration(route.sourceId);
|
|
2457
|
-
const
|
|
2458
|
-
|
|
2671
|
+
const activeVersion = generation?.active?.catalogVersion;
|
|
2672
|
+
const metadataInvalid = generation?.errorCode === 'catalogGenerationMetadataInvalid';
|
|
2673
|
+
const damagedEntry = generation?.recoveryEntryPath;
|
|
2459
2674
|
breadcrumb = `插件来源 / ${route.sourceId}`;
|
|
2460
|
-
context = detail?.type === 'path' ? '本地目录'
|
|
2461
|
-
: detail?.freshness === 'remote' ? 'Git · 已连接'
|
|
2462
|
-
: detail?.freshness === 'cache' ? 'Git · 使用缓存' : 'Git';
|
|
2675
|
+
context = detail?.type === 'path' ? '本地目录' : 'Git';
|
|
2463
2676
|
title = route.sourceId;
|
|
2464
|
-
description =
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
};
|
|
2470
|
-
const generationActions = [
|
|
2471
|
-
...(generation?.candidate ? [{
|
|
2472
|
-
label: `使用 ${generation.candidate.catalogVersion}…`,
|
|
2473
|
-
description: '先查看影响;不会自动升级已安装插件',
|
|
2474
|
-
run: () => go({ name: 'catalogCandidate', sourceId: route.sourceId }),
|
|
2475
|
-
}] : []),
|
|
2476
|
-
...(generation?.refreshState === 'immutableViolation' ? [{
|
|
2477
|
-
label: '查看发布异常',
|
|
2478
|
-
description: '旧 Active 已安全保留',
|
|
2479
|
-
status: 'error',
|
|
2480
|
-
run: () => go({ name: 'catalogImmutableViolation', sourceId: route.sourceId }),
|
|
2481
|
-
}] : []),
|
|
2482
|
-
];
|
|
2483
|
-
actions = diagnostic
|
|
2484
|
-
? [
|
|
2485
|
-
...generationActions,
|
|
2486
|
-
{ label: '重新检查来源', description: '读取远端并验证可用 generation', run: openRefresh },
|
|
2487
|
-
...(state === 'degraded' ? [{
|
|
2488
|
-
label: '继续使用缓存',
|
|
2489
|
-
description: '浏览匹配且已验证的缓存数据',
|
|
2490
|
-
run: () => go({ name: 'pluginList', mode: 'browse', sourceId: route.sourceId }),
|
|
2491
|
-
}] : []),
|
|
2492
|
-
{ label: '编辑来源…', description: '检查 URL、路径或 ref', run: () => go({ name: 'sourceEdit', sourceId: route.sourceId }) },
|
|
2493
|
-
{ label: '设为主来源…', description: '只改变默认 marketplace', disabled: detail?.primary ? '当前已经是主来源' : undefined, run: () => beginReview({ kind: 'sourceMutation', action: 'setPrimary', sourceId: route.sourceId, changes: [{ title: '主来源', before: snapshot.viewModel?.sourceTabs.find((source) => source.primary)?.id, after: route.sourceId }] }) },
|
|
2494
|
-
{ label: '移除来源…', description: '移除来源配置', status: 'error', disabled: detail?.primary ? '主来源不能直接移除' : undefined, run: () => beginReview({ kind: 'sourceMutation', action: 'remove', sourceId: route.sourceId, changes: [{ title: `移除来源 ${route.sourceId}` }] }) },
|
|
2495
|
-
{ label: '技术详情', description: '查看脱敏错误代码和解析证据', run: () => go({ name: 'sourceTechnical', sourceId: route.sourceId }) },
|
|
2496
|
-
]
|
|
2497
|
-
: [
|
|
2498
|
-
...generationActions,
|
|
2499
|
-
{ label: '重新检查来源', description: detail?.type === 'path' ? '显式读取本地目录' : '读取远端并准备 Candidate', run: openRefresh },
|
|
2500
|
-
...(generation?.sourceType === 'git' ? [{
|
|
2501
|
-
label: '自动刷新',
|
|
2502
|
-
description: generation.refreshPolicy === 'startup' ? '启动时自动检查' : '仅手动检查',
|
|
2503
|
-
meta: generation.refreshPolicy === 'startup' ? '开启' : '关闭',
|
|
2504
|
-
run: () => go({ name: 'catalogRefreshPolicy', sourceId: route.sourceId }),
|
|
2505
|
-
}] : []),
|
|
2506
|
-
{ label: '编辑来源…', description: 'ID 与类型创建后不可修改', run: () => go({ name: 'sourceEdit', sourceId: route.sourceId }) },
|
|
2507
|
-
{ label: '设为主来源…', description: '只改变默认 marketplace', disabled: detail?.primary ? '当前已经是主来源' : undefined, run: () => beginReview({ kind: 'sourceMutation', action: 'setPrimary', sourceId: route.sourceId, changes: [{ title: '主来源', before: snapshot.viewModel?.sourceTabs.find((source) => source.primary)?.id, after: route.sourceId }] }) },
|
|
2508
|
-
{ label: '移除来源…', description: '移除来源配置', status: 'error', disabled: detail?.primary ? '主来源不能直接移除' : undefined, run: () => beginReview({ kind: 'sourceMutation', action: 'remove', sourceId: route.sourceId, changes: [{ title: `移除来源 ${route.sourceId}` }] }) },
|
|
2509
|
-
{ label: '技术详情', description: '只读身份与解析证据', run: () => go({ name: 'sourceTechnical', sourceId: route.sourceId }) },
|
|
2510
|
-
];
|
|
2511
|
-
const sourceActionViewport = actionViewport(actions, policy.mode === 'compact', focus, scrollOffset, responsiveBudget(2, 5));
|
|
2512
|
-
content = _jsxs(Box, { flexDirection: "column", children: [diagnostic
|
|
2513
|
-
? _jsx(DiagnosticSummary, { diagnostic: diagnostic, compact: policy.mode === 'compact' })
|
|
2514
|
-
: _jsxs(_Fragment, { children: [sessionCatalogVersion ? _jsx(SectionCard, { title: "\u5F53\u524D\u4F7F\u7528", compact: policy.mode === 'compact', children: _jsx(StaticRow, { title: `Catalog ${sessionCatalogVersion}`, meta: `${generation?.active?.channel === 'beta' ? 'Beta' : 'Release'} · 本次会话固定使用`, compact: true }) }) : null, generation?.candidate ? _jsx(SectionCard, { title: "\u53EF\u7528\u66F4\u65B0", status: "warning", compact: policy.mode === 'compact', children: _jsx(StaticRow, { title: `Catalog ${generation.candidate.catalogVersion}`, meta: `已下载并验证 · +${generation.candidate.pluginChanges.added} ~${generation.candidate.pluginChanges.updated} −${generation.candidate.pluginChanges.removed}`, compact: true }) }) : null, policy.mode === 'compact' ? _jsxs(_Fragment, { children: [_jsx(StaticRow, { title: "\u5F15\u7528", meta: generation?.active?.requestedRef ?? detail?.explicitRef ?? detail?.requestedRef ?? '本地目录', compact: true }), _jsx(StaticRow, { title: "\u68C0\u67E5", meta: `${generation?.sourceType === 'git' && generation.refreshPolicy === 'startup' ? '启动时' : '仅手动'} · ${generation?.lastCheckedAt ? '已有记录' : '尚未检查'}`, compact: true })] }) : _jsxs(SectionCard, { title: "\u6765\u6E90\u4E0E\u68C0\u67E5", children: [_jsx(StaticRow, { title: "\u4F4D\u7F6E", meta: detail?.locationSummary ?? '不可用' }), _jsx(StaticRow, { title: "\u5F15\u7528", meta: generation?.active?.requestedRef ?? detail?.explicitRef ?? detail?.requestedRef ?? '本地目录' }), _jsx(StaticRow, { title: "\u81EA\u52A8\u5237\u65B0", meta: generation?.sourceType === 'git' ? generation.refreshPolicy === 'startup' ? '启动时检查' : '仅手动' : '仅手动' }), _jsx(StaticRow, { title: "\u4E0A\u6B21\u68C0\u67E5", meta: generation?.lastCheckedAt ?? '尚未检查' })] })] }), _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: policy.mode === 'compact', offset: sourceActionViewport.offset, limit: sourceActionViewport.limit })] });
|
|
2515
|
-
}
|
|
2516
|
-
else if (route.name === 'catalogCandidate') {
|
|
2517
|
-
const generation = props.controller.getCatalogGeneration(route.sourceId);
|
|
2518
|
-
const candidate = generation?.candidate;
|
|
2519
|
-
breadcrumb = `插件来源 / ${route.sourceId} / Catalog 更新`;
|
|
2520
|
-
context = '已下载并验证';
|
|
2521
|
-
title = candidate ? `使用 ${route.sourceId} Catalog ${candidate.catalogVersion}` : 'Catalog 更新不再可用';
|
|
2522
|
-
description = '切换 generation;不会自动升级已安装插件,也不会修改设置。';
|
|
2523
|
-
actions = candidate ? [
|
|
2524
|
-
{ label: `使用 ${candidate.catalogVersion}…`, description: '进入激活 Review', run: () => {
|
|
2525
|
-
props.controller.beginCatalogActivation({
|
|
2526
|
-
sourceId: route.sourceId,
|
|
2527
|
-
...(dirty ? { dirtyDraft: { kind: 'config', label: '当前设置草稿' } }
|
|
2528
|
-
: sourceDraft ? { dirtyDraft: { kind: 'source', label: '当前来源草稿' } } : {}),
|
|
2529
|
-
});
|
|
2530
|
-
setFocus(0);
|
|
2531
|
-
setScrollOffset(0);
|
|
2532
|
-
} },
|
|
2533
|
-
{ label: `继续使用 ${generation?.active?.catalogVersion ?? '当前版本'}`, run: back },
|
|
2534
|
-
] : [{ label: '返回来源', run: back }];
|
|
2535
|
-
content = candidate ? _jsxs(Box, { flexDirection: "column", children: [_jsxs(SectionCard, { title: "Catalog \u53D8\u5316", children: [_jsx(StaticRow, { title: "\u7248\u672C", meta: `${generation?.active?.catalogVersion ?? '未加载'} → ${candidate.catalogVersion}` }), _jsx(StaticRow, { title: "\u901A\u9053 / \u5F15\u7528", meta: `${candidate.channel === 'beta' ? 'Beta' : 'Release'} · ${candidate.requestedRef}` }), _jsx(StaticRow, { title: "\u63D2\u4EF6\u53D8\u5316", meta: `+${candidate.pluginChanges.added} ~${candidate.pluginChanges.updated} −${candidate.pluginChanges.removed}` })] }), _jsxs(SectionCard, { title: "\u6FC0\u6D3B\u540E", children: [_jsx(StaticRow, { title: "\u91CD\u65B0\u52A0\u8F7D\u63D2\u4EF6\u5217\u8868\u548C\u4F9D\u8D56\u5173\u7CFB", status: "warning" }), _jsx(StaticRow, { title: "\u5DF2\u5B89\u88C5\u63D2\u4EF6\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7", status: "success" }), _jsx(StaticRow, { title: "\u5F53\u524D\u8BBE\u7F6E\u4E0D\u4F1A\u6539\u53D8", status: "success" })] }), _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: true })] }) : _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: true });
|
|
2536
|
-
}
|
|
2537
|
-
else if (route.name === 'catalogRefreshPolicy') {
|
|
2538
|
-
const generation = props.controller.getCatalogGeneration(route.sourceId);
|
|
2539
|
-
breadcrumb = `插件来源 / ${route.sourceId} / 自动刷新`;
|
|
2540
|
-
title = 'Catalog 自动刷新';
|
|
2541
|
-
description = `决定何时检查 ${route.sourceId} 的远端更新。更新不会自动激活。`;
|
|
2542
|
-
actions = [
|
|
2543
|
-
{ label: '启动时自动检查', description: '首屏出现后在后台检查;不会自动切换版本', selected: generation?.refreshPolicy === 'startup', run: async () => props.controller.setCatalogRefreshPolicy(route.sourceId, 'startup') },
|
|
2544
|
-
{ label: '仅手动检查', description: '只有选择“重新检查来源”时访问远端', selected: generation?.refreshPolicy === 'manual', run: async () => props.controller.setCatalogRefreshPolicy(route.sourceId, 'manual') },
|
|
2545
|
-
];
|
|
2546
|
-
content = _jsx(SemanticRows, { actions: actions, focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
2547
|
-
}
|
|
2548
|
-
else if (route.name === 'catalogRefresh') {
|
|
2549
|
-
const generation = props.controller.getCatalogGeneration(route.sourceId);
|
|
2550
|
-
const state = generation?.refreshState ?? 'idle';
|
|
2551
|
-
const activeVersion = props.controller.getSessionCatalogVersion(route.sourceId)
|
|
2552
|
-
?? generation?.active?.catalogVersion ?? '已加载版本';
|
|
2553
|
-
const stage = state === 'checking' || state === 'downloading' ? 1
|
|
2554
|
-
: state === 'validating' ? 2 : 3;
|
|
2555
|
-
const stageState = (index) => state === 'failed' || state === 'immutableViolation'
|
|
2556
|
-
? index === stage ? 'error' : index < stage ? 'complete' : 'pending'
|
|
2557
|
-
: index < stage ? 'complete' : index === stage && stage < 3 ? 'active' : index <= stage ? 'complete' : 'pending';
|
|
2558
|
-
breadcrumb = `插件来源 / ${route.sourceId} / 检查更新`;
|
|
2559
|
-
context = '只读';
|
|
2560
|
-
title = state === 'candidateReady' ? 'Catalog 更新已准备好'
|
|
2561
|
-
: state === 'upToDate' ? 'Catalog 已是最新'
|
|
2562
|
-
: state === 'immutableViolation' ? 'Catalog 发布异常'
|
|
2563
|
-
: state === 'failed' ? 'Catalog 检查失败' : '正在检查 Catalog 更新';
|
|
2564
|
-
description = `当前操作继续使用 Catalog ${activeVersion}。`;
|
|
2565
|
-
help = state === 'checking' || state === 'downloading' || state === 'validating'
|
|
2566
|
-
? 'Esc 取消检查' : 'Enter 返回 · Esc 返回';
|
|
2567
|
-
actions = state === 'immutableViolation'
|
|
2568
|
-
? [{ label: '查看发布异常', run: () => props.controller.replace({ name: 'catalogImmutableViolation', sourceId: route.sourceId }) }, { label: '返回来源', run: back }]
|
|
2569
|
-
: state === 'checking' || state === 'downloading' || state === 'validating'
|
|
2570
|
-
? [] : [{ label: '返回来源', run: back }];
|
|
2571
|
-
content = _jsxs(Box, { flexDirection: "column", children: [_jsxs(SectionCard, { title: "\u68C0\u67E5\u6B65\u9AA4", children: [_jsx(ProgressRow, { title: "\u8BFB\u53D6\u5F53\u524D Active generation", state: "complete", compact: true }), _jsx(ProgressRow, { title: "\u68C0\u67E5\u5E76\u83B7\u53D6\u8FDC\u7AEF generation", state: stageState(1), compact: true }), _jsx(ProgressRow, { title: "\u9A8C\u8BC1 Catalog", state: stageState(2), compact: true }), _jsx(ProgressRow, { title: "\u51C6\u5907 Candidate", state: stageState(3), compact: true })] }), actions.length > 0 ? _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: true }) : null] });
|
|
2572
|
-
}
|
|
2573
|
-
else if (route.name === 'catalogImmutableViolation') {
|
|
2574
|
-
const generation = props.controller.getCatalogGeneration(route.sourceId);
|
|
2575
|
-
breadcrumb = `插件来源 / ${route.sourceId} / 发布异常`;
|
|
2576
|
-
context = '发布异常';
|
|
2577
|
-
title = 'Catalog 版本内容发生变化';
|
|
2578
|
-
description = `远端重新发布了已经存在的 Catalog ${generation?.active?.catalogVersion ?? '版本'}。`;
|
|
2677
|
+
description = activeVersion ? `当前使用 Active Catalog ${activeVersion}。`
|
|
2678
|
+
: metadataInvalid && damagedEntry
|
|
2679
|
+
? `Active Catalog 条目已损坏。先安全删除 AW_HOME 下的精确条目 ${damagedEntry},再运行 ${generation.syncInstruction},然后重新加载 TUI。`
|
|
2680
|
+
: `来源没有可用 Active。请在终端运行 ${generation?.syncInstruction ?? `aw catalog source sync ${route.sourceId}`},然后重新加载 TUI。`;
|
|
2681
|
+
help = '↑↓ 移动 · Enter 选择 · Esc 返回';
|
|
2579
2682
|
actions = [
|
|
2580
|
-
{ label:
|
|
2581
|
-
|
|
2582
|
-
|
|
2683
|
+
{ label: metadataInvalid ? '修复后重新加载 TUI' : '重新加载 TUI', description: metadataInvalid && damagedEntry
|
|
2684
|
+
? `先删除精确条目 ${damagedEntry},再运行 ${generation.syncInstruction}`
|
|
2685
|
+
: `先在终端运行 aw catalog source sync ${route.sourceId},再重新加载 Active`, run: () => props.controller.reloadCatalog({ sourceId: route.sourceId }) },
|
|
2686
|
+
...(!metadataInvalid ? [{ label: '编辑来源…', description: '只修改来源配置;不会访问网络', run: () => go({ name: 'sourceEdit', sourceId: route.sourceId }) }] : []),
|
|
2687
|
+
{ label: '设为主来源…', description: '只改变默认 marketplace', disabled: detail?.primary ? '当前已经是主来源' : undefined, run: () => beginReview({ kind: 'sourceMutation', action: 'setPrimary', sourceId: route.sourceId, changes: [{ title: '主来源', before: snapshot.viewModel?.sourceTabs.find((source) => source.primary)?.id, after: route.sourceId }] }) },
|
|
2688
|
+
{ label: '移除来源…', description: '移除来源配置', status: 'error', disabled: detail?.primary ? '主来源不能直接移除' : undefined, run: () => beginReview({ kind: 'sourceMutation', action: 'remove', sourceId: route.sourceId, changes: [{ title: `移除来源 ${route.sourceId}` }] }) },
|
|
2689
|
+
{ label: '技术详情', description: '查看脱敏错误代码和 Active 证据', run: () => go({ name: 'sourceTechnical', sourceId: route.sourceId }) },
|
|
2583
2690
|
];
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
else if (route.name === 'catalogActivationBlocked') {
|
|
2587
|
-
const generation = props.controller.getCatalogGeneration(route.sourceId);
|
|
2588
|
-
const reason = {
|
|
2589
|
-
configDraft: '当前有未完成的设置修改。', sourceDraft: '当前有未完成的来源修改。', portableDraft: '当前有未完成的 Portable Skills 选择。', activeReview: '当前有待确认的 Review。', reviewPreparation: '当前正在准备 Review。', writeProgress: '当前写操作尚未完成。', sourceMutationProgress: '当前来源修改尚未完成。', refreshProgress: '当前 Catalog 来源刷新尚未完成。',
|
|
2590
|
-
}[route.reason];
|
|
2591
|
-
breadcrumb = `插件来源 / ${route.sourceId} / 使用更新`;
|
|
2592
|
-
context = '暂不可用';
|
|
2593
|
-
title = '暂时不能切换 Catalog';
|
|
2594
|
-
description = reason;
|
|
2595
|
-
actions = [{ label: '返回完成或取消当前操作', run: back }, { label: `继续使用 ${props.controller.getSessionCatalogVersion(route.sourceId) ?? generation?.active?.catalogVersion ?? '当前版本'}`, run: back }];
|
|
2596
|
-
content = _jsxs(Box, { flexDirection: "column", children: [_jsxs(SectionCard, { title: "\u4FDD\u7559\u7684\u5DE5\u4F5C", children: [_jsx(StaticRow, { title: route.preservedLabel ?? reason, status: "success" }), _jsx(StaticRow, { title: `Candidate ${generation?.candidate?.catalogVersion ?? '更新'} 保持已下载状态`, status: "success" })] }), _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: policy.mode === 'compact' })] });
|
|
2691
|
+
const sourceActionViewport = actionViewport(actions, policy.mode === 'compact', focus, scrollOffset, responsiveBudget(2, 5));
|
|
2692
|
+
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(SectionCard, { title: "Active Catalog", status: activeVersion ? 'success' : 'warning', compact: policy.mode === 'compact', children: _jsx(StaticRow, { title: activeVersion ? `Catalog ${activeVersion}` : '未同步', meta: activeVersion ? generation?.active?.digestShort : generation?.syncInstruction, compact: true }) }), _jsxs(SectionCard, { title: "\u6765\u6E90\u914D\u7F6E", compact: policy.mode === 'compact', children: [_jsx(StaticRow, { title: "\u4F4D\u7F6E", meta: detail?.locationSummary ?? '不可用', compact: true }), _jsx(StaticRow, { title: "\u5F15\u7528", meta: generation?.active?.requestedRef ?? detail?.explicitRef ?? detail?.requestedRef ?? '本地目录', compact: true })] }), _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: policy.mode === 'compact', offset: sourceActionViewport.offset, limit: sourceActionViewport.limit })] });
|
|
2597
2693
|
}
|
|
2598
2694
|
else if (route.name === 'sourceTechnical') {
|
|
2599
2695
|
const overview = props.controller.getSourceOverview(route.sourceId);
|
|
2600
2696
|
const detail = overview.detail;
|
|
2601
2697
|
const state = overview.health?.state ?? overview.source?.state;
|
|
2602
|
-
const diagnostic = sourceDiagnostic(route.sourceId, state, detail) ?? {
|
|
2698
|
+
const diagnostic = sourceDiagnostic(route.sourceId, state, detail, props.controller.getCatalogGeneration(route.sourceId)) ?? {
|
|
2603
2699
|
severity: 'warning',
|
|
2604
2700
|
title: '来源解析详情',
|
|
2605
2701
|
userMessage: '来源当前可用。',
|
|
@@ -2611,7 +2707,6 @@ export function ConsoleAppV4(props) {
|
|
|
2611
2707
|
sourceId: route.sourceId,
|
|
2612
2708
|
...(detail?.requestedRef ? { requestedRef: detail.requestedRef } : {}),
|
|
2613
2709
|
...(detail?.resolvedCommit ? { resolvedCommit: detail.resolvedCommit } : {}),
|
|
2614
|
-
...(detail?.freshness ? { context: [{ key: 'freshness', value: detail.freshness }] } : {}),
|
|
2615
2710
|
},
|
|
2616
2711
|
};
|
|
2617
2712
|
breadcrumb = `插件来源 / ${route.sourceId} / 技术详情`;
|
|
@@ -2737,10 +2832,10 @@ export function ConsoleAppV4(props) {
|
|
|
2737
2832
|
label: entry.category.startsWith('dependency')
|
|
2738
2833
|
? `${props.controller.getPluginOverview(entry.pluginId ?? '')?.displayName ?? entry.pluginId ?? entry.title}${entry.platform ? ` · ${platformLabel(entry.platform)}` : ''}`
|
|
2739
2834
|
: entry.title,
|
|
2740
|
-
description:
|
|
2835
|
+
description: entry.category.startsWith('dependency')
|
|
2741
2836
|
? `${props.controller.getPluginOverview(entry.dependencyPluginId ?? '')?.displayName ?? entry.dependencyPluginId ?? entry.explanation} · ${entry.impact[0] ?? ''}`
|
|
2742
|
-
: `${entry.explanation} · ${entry.impact[0] ?? ''}
|
|
2743
|
-
status:
|
|
2837
|
+
: `${entry.explanation} · ${entry.impact[0] ?? ''}`,
|
|
2838
|
+
status: 'error',
|
|
2744
2839
|
run: () => entry.category === 'dependencyStillRequired' && entry.pluginId
|
|
2745
2840
|
? go({ name: 'pluginDependencies', pluginId: entry.pluginId, view: 'removeBlocked',
|
|
2746
2841
|
...(entry.platform ? { platform: entry.platform } : {}),
|
|
@@ -2749,7 +2844,27 @@ export function ConsoleAppV4(props) {
|
|
|
2749
2844
|
}));
|
|
2750
2845
|
}
|
|
2751
2846
|
const viewport = actionViewport(actions, policy.mode === 'compact', focus, scrollOffset, responsiveBudget(8, 12));
|
|
2752
|
-
|
|
2847
|
+
if (issues.length === 0) {
|
|
2848
|
+
content = _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: policy.mode === 'compact', offset: viewport.offset, limit: viewport.limit });
|
|
2849
|
+
}
|
|
2850
|
+
else {
|
|
2851
|
+
const groupCounts = new Map();
|
|
2852
|
+
for (const issueEntry of issues) {
|
|
2853
|
+
groupCounts.set(issueEntry.group, (groupCounts.get(issueEntry.group) ?? 0) + 1);
|
|
2854
|
+
}
|
|
2855
|
+
const visibleGroups = [];
|
|
2856
|
+
const visibleEnd = Math.min(actions.length, viewport.offset + viewport.limit);
|
|
2857
|
+
for (let index = viewport.offset; index < visibleEnd; index += 1) {
|
|
2858
|
+
const group = issues[index].group;
|
|
2859
|
+
const currentGroup = visibleGroups.at(-1);
|
|
2860
|
+
if (!currentGroup || currentGroup.group !== group) {
|
|
2861
|
+
visibleGroups.push({ group, startIndex: index, actions: [actions[index]] });
|
|
2862
|
+
}
|
|
2863
|
+
else
|
|
2864
|
+
currentGroup.actions.push(actions[index]);
|
|
2865
|
+
}
|
|
2866
|
+
content = _jsx(Box, { flexDirection: "column", children: visibleGroups.map((group) => _jsx(SectionCard, { title: issueGroupLabel(group.group), meta: `${groupCounts.get(group.group) ?? group.actions.length} 项`, compact: policy.mode === 'compact', children: _jsx(SemanticRows, { actions: group.actions, focus: focus - group.startIndex, kind: "task", compact: policy.mode === 'compact' }) }, `${group.group}:${group.startIndex}`)) });
|
|
2867
|
+
}
|
|
2753
2868
|
}
|
|
2754
2869
|
else if (route.name === 'issueDetail' && issue) {
|
|
2755
2870
|
breadcrumb = `需要处理 / ${issue.pluginId ?? issue.sourceId ?? issue.entity.id}`;
|
|
@@ -2763,8 +2878,8 @@ export function ConsoleAppV4(props) {
|
|
|
2763
2878
|
return;
|
|
2764
2879
|
}
|
|
2765
2880
|
if (entry.id === 'refreshSource' && issue.sourceId)
|
|
2766
|
-
await props.controller.
|
|
2767
|
-
else if (entry.id === '
|
|
2881
|
+
await props.controller.reloadCatalog({ sourceId: issue.sourceId });
|
|
2882
|
+
else if (entry.id === 'retryLater')
|
|
2768
2883
|
go({ name: 'issueList' });
|
|
2769
2884
|
else if (entry.id === 'editSource' && issue.sourceId)
|
|
2770
2885
|
go(issue.entity.kind === 'source'
|
|
@@ -2803,7 +2918,8 @@ export function ConsoleAppV4(props) {
|
|
|
2803
2918
|
}));
|
|
2804
2919
|
const issuePlugin = issue.pluginId ? props.controller.getPluginOverview(issue.pluginId) : undefined;
|
|
2805
2920
|
const issueOverview = issue.pluginId ? props.controller.getPluginDependencyOverview(issue.pluginId) : undefined;
|
|
2806
|
-
const issueDiagnosticSummary = _jsx(DiagnosticSummary, { diagnostic: issue.diagnostic, technical: showTechnical, compact: policy.mode === 'compact' || issue.category.startsWith('dependency')
|
|
2921
|
+
const issueDiagnosticSummary = _jsx(DiagnosticSummary, { diagnostic: issue.diagnostic, technical: showTechnical, compact: policy.mode === 'compact' || issue.category.startsWith('dependency')
|
|
2922
|
+
|| issue.category === 'scopeConflict' });
|
|
2807
2923
|
const issueActionViewport = actionViewport(actions, policy.mode === 'compact', focus, scrollOffset, pageActionBudget(6));
|
|
2808
2924
|
const compactTechnicalActionViewport = policy.mode === 'compact' && showTechnical
|
|
2809
2925
|
? {
|
|
@@ -2850,12 +2966,15 @@ export function ConsoleAppV4(props) {
|
|
|
2850
2966
|
setScope(issueScope);
|
|
2851
2967
|
setSelectedTargets([entry.platform]);
|
|
2852
2968
|
setTargetSelections((current) => ({ ...current, [issueScope]: [entry.platform] }));
|
|
2969
|
+
props.controller.beginInstallFlow(issuePlugin.pluginId, issueScope);
|
|
2970
|
+
props.controller.setInstallPlatforms([entry.platform]);
|
|
2853
2971
|
go({ name: 'installTargets', pluginId: issuePlugin.pluginId });
|
|
2854
2972
|
} })),
|
|
2855
2973
|
{ label: '返回调整目标平台', run: () => {
|
|
2856
2974
|
setScope(issueScope);
|
|
2857
2975
|
setSelectedTargets([]);
|
|
2858
2976
|
setTargetSelections((current) => ({ ...current, [issueScope]: [] }));
|
|
2977
|
+
props.controller.beginInstallFlow(issuePlugin.pluginId, issueScope);
|
|
2859
2978
|
go({ name: 'installTargets', pluginId: issuePlugin.pluginId });
|
|
2860
2979
|
} },
|
|
2861
2980
|
{ label: '查看依赖关系', run: () => go({ name: 'pluginDependencies', pluginId: issuePlugin.pluginId }) },
|
|
@@ -2891,13 +3010,11 @@ export function ConsoleAppV4(props) {
|
|
|
2891
3010
|
const preparation = snapshot.reviewPreparation;
|
|
2892
3011
|
const labels = preparation.intent.kind === 'portableInstall'
|
|
2893
3012
|
? ['通用 Skills / 安装', '正在准备通用 Skills 安装确认']
|
|
2894
|
-
: preparation.intent.kind === '
|
|
2895
|
-
? ['
|
|
2896
|
-
: preparation.intent.kind === '
|
|
2897
|
-
? ['
|
|
2898
|
-
:
|
|
2899
|
-
? ['插件来源', '正在准备来源变更确认']
|
|
2900
|
-
: ['插件操作', '正在准备插件操作确认'];
|
|
3013
|
+
: preparation.intent.kind === 'configSave' || preparation.intent.kind === 'configReset'
|
|
3014
|
+
? ['设置', '正在准备设置确认']
|
|
3015
|
+
: preparation.intent.kind === 'sourceMutation'
|
|
3016
|
+
? ['插件来源', '正在准备来源变更确认']
|
|
3017
|
+
: ['插件操作', '正在准备插件操作确认'];
|
|
2901
3018
|
breadcrumb = `${labels[0]} / 准备确认`;
|
|
2902
3019
|
context = '只读';
|
|
2903
3020
|
title = preparation.state === 'failed' ? '无法准备确认信息' : labels[1];
|
|
@@ -2921,11 +3038,24 @@ export function ConsoleAppV4(props) {
|
|
|
2921
3038
|
}
|
|
2922
3039
|
else if (route.name === 'review' && snapshot.activeReview) {
|
|
2923
3040
|
const review = snapshot.activeReview;
|
|
3041
|
+
const sharedImpactConfirmed = !review.requiresConfirmation
|
|
3042
|
+
|| confirmedSharedReviewToken === review.reviewToken;
|
|
2924
3043
|
breadcrumb = `${review.subject.name} / ${review.title}`;
|
|
2925
3044
|
title = `${snapshot.result?.state === 'stale' ? '状态已变化 · ' : ''}${review.operationKind === 'portableInstall' ? review.title : `确认${review.title}`} ${review.subject.name}`;
|
|
2926
|
-
description = snapshot.result?.state === 'stale'
|
|
3045
|
+
description = snapshot.result?.state === 'stale'
|
|
3046
|
+
? '当前状态已变化。请检查新的变化后再次确认。'
|
|
3047
|
+
: review.requiresConfirmation ? '' : review.description;
|
|
2927
3048
|
actions = [
|
|
2928
|
-
|
|
3049
|
+
...(review.requiresConfirmation ? [{
|
|
3050
|
+
label: sharedImpactConfirmed ? '已确认 shared impact' : '确认 shared impact',
|
|
3051
|
+
description: review.sharedImpact.warning ?? '此操作会修改多个插件共享的 Codex native 内容',
|
|
3052
|
+
selected: sharedImpactConfirmed,
|
|
3053
|
+
run: () => {
|
|
3054
|
+
setConfirmedSharedReviewToken(review.reviewToken);
|
|
3055
|
+
setFocus(1);
|
|
3056
|
+
},
|
|
3057
|
+
}] : []),
|
|
3058
|
+
{ label: review.primaryLabel, description: '执行前将再次检查当前状态', status: review.destructive ? 'error' : undefined, disabled: sharedImpactConfirmed ? undefined : '请先显式确认 shared impact', run: () => {
|
|
2929
3059
|
if (operationBusy.current)
|
|
2930
3060
|
return;
|
|
2931
3061
|
operationBusy.current = true;
|
|
@@ -2944,9 +3074,16 @@ export function ConsoleAppV4(props) {
|
|
|
2944
3074
|
: back },
|
|
2945
3075
|
];
|
|
2946
3076
|
const groupedChanges = review.changes.some((change) => change.group);
|
|
3077
|
+
const compressedReview = policy.mode === 'compact' || review.requiresConfirmation;
|
|
2947
3078
|
const groupTitle = {
|
|
2948
3079
|
requested: review.operationKind === 'portableInstall' ? '已选择 Skills · 当前插件' : '你选择的插件',
|
|
2949
3080
|
dependencies: review.operationKind === 'portableInstall' ? '已选择 Skills · 来自依赖插件' : '必需依赖',
|
|
3081
|
+
projectIntent: 'Project intent',
|
|
3082
|
+
userIntent: 'User intent',
|
|
3083
|
+
sharedCodexNative: 'Shared Codex native',
|
|
3084
|
+
userActivation: 'User activation',
|
|
3085
|
+
projectActivation: 'Project activation',
|
|
3086
|
+
awExtensions: 'AW extensions',
|
|
2950
3087
|
runtime: 'Codex runtime',
|
|
2951
3088
|
portableTarget: '安装目标',
|
|
2952
3089
|
portableInputs: '准备内容',
|
|
@@ -2958,7 +3095,7 @@ export function ConsoleAppV4(props) {
|
|
|
2958
3095
|
const changeStatus = (change) => change.kind === 'remove' ? 'error'
|
|
2959
3096
|
: change.kind === 'warning' ? 'warning'
|
|
2960
3097
|
: change.kind === 'keep' || change.kind === 'add' ? 'success' : undefined;
|
|
2961
|
-
const groupOrder = ['portableWarnings', 'portableTarget', 'configChanges', 'configImpact', 'requested', 'dependencies', 'runtime', 'preserved', 'portableInputs'];
|
|
3098
|
+
const groupOrder = ['portableWarnings', 'portableTarget', 'configChanges', 'configImpact', 'requested', 'dependencies', 'projectIntent', 'userIntent', 'sharedCodexNative', 'userActivation', 'projectActivation', 'awExtensions', 'runtime', 'preserved', 'portableInputs'];
|
|
2962
3099
|
const groupedSpecs = groupedChanges
|
|
2963
3100
|
? groupOrder.map((group) => ({
|
|
2964
3101
|
key: group,
|
|
@@ -2972,7 +3109,7 @@ export function ConsoleAppV4(props) {
|
|
|
2972
3109
|
{ key: 'changes', label: undefined, protectedCount: false, changes: review.changes.filter((change) => change.kind !== 'warning' && change.kind !== 'keep') },
|
|
2973
3110
|
];
|
|
2974
3111
|
const visibleSpecs = groupedSpecs.filter((group) => group.changes.length > 0);
|
|
2975
|
-
const headingLines =
|
|
3112
|
+
const headingLines = compressedReview ? 0 : visibleSpecs.filter((group) => group.label).length;
|
|
2976
3113
|
const staticRowBudget = Math.max(visibleSpecs.length, responsiveBudget(7, 12) - headingLines);
|
|
2977
3114
|
const allocations = new Map(visibleSpecs.map((group) => [group.key, 1]));
|
|
2978
3115
|
const targetGroup = visibleSpecs.find((group) => group.key === 'portableTarget');
|
|
@@ -2991,7 +3128,7 @@ export function ConsoleAppV4(props) {
|
|
|
2991
3128
|
const changeGroups = visibleSpecs.map((group) => {
|
|
2992
3129
|
const visibleCount = allocations.get(group.key) ?? 1;
|
|
2993
3130
|
const hiddenCount = group.changes.length - visibleCount;
|
|
2994
|
-
return _jsxs(Box, { flexDirection: "column", children: [
|
|
3131
|
+
return _jsxs(Box, { flexDirection: "column", children: [!compressedReview && group.label ? _jsx(Text, { bold: true, color: tuiTheme.colors.muted, children: group.label }) : null, group.changes.slice(0, visibleCount).map((change, index) => {
|
|
2995
3132
|
const retainDescription = change.kind === 'warning' || group.key === 'portableTarget'
|
|
2996
3133
|
|| group.key === 'requested' || group.key === 'dependencies'
|
|
2997
3134
|
|| group.key === 'configChanges' || group.key === 'configImpact';
|
|
@@ -2999,7 +3136,7 @@ export function ConsoleAppV4(props) {
|
|
|
2999
3136
|
const compactGroupLabel = group.key === 'requested' ? '根插件'
|
|
3000
3137
|
: group.key === 'dependencies' ? '依赖'
|
|
3001
3138
|
: group.key === 'preserved' ? '保持' : group.label;
|
|
3002
|
-
const category =
|
|
3139
|
+
const category = compressedReview && index === 0 && compactGroupLabel ? `${compactGroupLabel} · ` : '';
|
|
3003
3140
|
const count = index === visibleCount - 1 && (hiddenCount > 0 || group.protectedCount)
|
|
3004
3141
|
? hiddenCount > 0 ? `另有 ${hiddenCount} 项` : `共 ${group.changes.length} 项`
|
|
3005
3142
|
: undefined;
|
|
@@ -3024,18 +3161,19 @@ export function ConsoleAppV4(props) {
|
|
|
3024
3161
|
return _jsx(ReviewChangeRow, { title: `${category ? `${category} · ` : ''}${reviewSymbol(change)} ${change.title}${change.description ? ` · ${change.description}` : ''}`, meta: index === visibleTechnicalChanges.length - 1 && hiddenTechnicalChanges > 0
|
|
3025
3162
|
? `另有 ${hiddenTechnicalChanges} 项` : undefined, status: changeStatus(change), compact: true }, `${change.title}:${index}`);
|
|
3026
3163
|
});
|
|
3027
|
-
|
|
3164
|
+
const showEquivalentCommand = Boolean(review.equivalentCommand
|
|
3165
|
+
&& (!review.requiresConfirmation || showTechnical));
|
|
3166
|
+
content = _jsx(Box, { flexDirection: "column", children: _jsxs(ReviewCard, { title: review.requiresConfirmation ? undefined : review.subject.name, meta: review.requiresConfirmation ? undefined : `${review.subject.sourceLabel ?? ''} ${review.subject.version ?? ''}`, description: showEquivalentCommand ? review.description : undefined, children: [showEquivalentCommand ? _jsxs(Text, { children: ["\u7B49\u4EF7\u547D\u4EE4\uFF1A", review.equivalentCommand] }) : null, review.catalogBinding ? _jsxs(_Fragment, { children: [_jsx(StaticRow, { title: `Catalog:${review.catalogBinding.sourceId} ${review.catalogBinding.catalogVersion} · 当前使用`, meta: `generation ${review.catalogBinding.generationDigestShort}`, status: "success", compact: true }), _jsx(StaticRow, { title: "\u64CD\u4F5C\u671F\u95F4\u4E0D\u68C0\u67E5\u8FDC\u7AEF Catalog", status: "success", compact: true })] }) : null, review.requiresConfirmation ? _jsx(StaticRow, { title: "! Shared impact \u9700\u8981\u663E\u5F0F\u786E\u8BA4", meta: review.sharedImpact.pluginIds.length > 0 ? `${review.sharedImpact.pluginIds.length} 个插件` : undefined, description: review.sharedImpact.warning, status: "warning", compact: true }) : null, showTechnical ? technicalChanges : changeGroups, _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: true }), compressedReview || showTechnical ? null : _jsx(StaticRow, { title: "\u6280\u672F\u8BE6\u60C5\uFF08d\uFF09", status: "muted" }), showTechnical ? _jsx(TechnicalDetails, { children: visibleTechnicalDetails.map((detail, index) => _jsx(StaticRow, { title: detail, meta: index === visibleTechnicalDetails.length - 1 && hiddenTechnicalDetails > 0 ? `另有 ${hiddenTechnicalDetails} 项` : undefined, compact: true }, detail)) }) : null] }) });
|
|
3028
3167
|
}
|
|
3029
3168
|
else if (route.name === 'progress') {
|
|
3030
|
-
const catalogActivation = snapshot.activeReview?.operationKind === 'catalogActivate';
|
|
3031
3169
|
const portableOperation = snapshot.activeReview?.operationKind === 'portableInstall';
|
|
3032
3170
|
const configOperation = snapshot.activeReview?.operationKind === 'configSave'
|
|
3033
3171
|
|| snapshot.activeReview?.operationKind === 'configReset';
|
|
3034
3172
|
const sourceOperation = snapshot.activeReview?.operationKind === 'sourceMutation';
|
|
3035
3173
|
const issueOperation = snapshot.activeReview?.originIssue;
|
|
3036
|
-
breadcrumb =
|
|
3037
|
-
title =
|
|
3038
|
-
description =
|
|
3174
|
+
breadcrumb = portableOperation ? '通用 Skills / 进度' : issueOperation ? '需要处理 / 进度' : sourceOperation ? '插件来源 / 保存' : configOperation ? '设置 / 进度' : '插件操作 / 进度';
|
|
3175
|
+
title = portableOperation ? '正在安装通用 Skills' : issueOperation ? '正在处理问题' : sourceOperation ? '正在保存来源配置' : configOperation ? '正在保存并应用设置' : '正在执行插件操作';
|
|
3176
|
+
description = issueOperation ? '完成后会使用新的状态 generation 重新检查问题。' : sourceOperation ? '只原子保存来源配置,不访问网络。' : configOperation ? '先保存所选层,再重新应用当前可见安装位置。' : '请勿关闭当前终端。';
|
|
3039
3177
|
help = 'Ctrl-C 完成后退出';
|
|
3040
3178
|
const progress = snapshot.progress;
|
|
3041
3179
|
const elapsedSeconds = Math.max(0, Math.floor(((progress.elapsedMs
|
|
@@ -3135,7 +3273,7 @@ export function ConsoleAppV4(props) {
|
|
|
3135
3273
|
return step === 2 ? '正在安装' : step === 3 ? '正在验证' : step === 1 ? '正在生成' : '正在检查';
|
|
3136
3274
|
};
|
|
3137
3275
|
const compactPortableProgress = policy.mode === 'compact' && showTechnical;
|
|
3138
|
-
content = portableOperation ? _jsxs(StatusCard, { status: failedProgress ? 'error' : 'info', title: "Skills CLI", children: [_jsx(ProgressRow, { title: "\u68C0\u67E5\u63D2\u4EF6\u548C\u4F9D\u8D56", description: `${snapshot.activeReview?.subject.name ?? '当前插件'} · ${portableDraft?.dependencySummary?.directCount ?? 0} 个直接依赖`, meta: portableProgressMeta(0), state: portableProgressState(0), compact: compactPortableProgress }), _jsx(ProgressRow, { title: "\u751F\u6210\u5DF2\u9009\u5019\u9009 Skills", description: `${portableProviderCount} 个 provider 提供 ${portableSelectedCount} 个 Skills`, meta: portableProgressMeta(1), state: portableProgressState(1), compact: compactPortableProgress }), _jsx(ProgressRow, { title: `安装已选择的 ${portableSelectedCount} 个 Skills`, description: `Agent:${portableDraft?.agentMode === 'explicit' ? portableDraft.requestedAgents.join('、') : 'Skills CLI 默认选择'}`, meta: portableProgressMeta(2), state: portableProgressState(2), compact: compactPortableProgress }), _jsx(ProgressRow, { title: "\u9A8C\u8BC1\u7ED3\u679C", description: "\u9010\u9879\u786E\u8BA4\u6240\u9009 Skill \u7684\u5B89\u88C5\u76EE\u6807", meta: portableProgressMeta(3), state: portableProgressState(3), compact: compactPortableProgress }), showTechnical ? _jsxs(TechnicalDetails, { children: [technicalMessages.map((message, index) => _jsx(StaticRow, { title: message, compact: true }, `${index}:${message}`)), hiddenTechnicalMessages > 0 ? _jsx(StaticRow, { title: `另有 ${hiddenTechnicalMessages} 条技术消息`, status: "muted", compact: true }) : null] }) : null] }) : _jsxs(StatusCard, { status: "info", children: [dependencyProgress ? _jsxs(_Fragment, { children: [_jsx(ProgressRow, { title: "\u68C0\u67E5\u4F9D\u8D56\u5173\u7CFB", state: relationStep }), _jsx(ProgressRow, { title: "\u751F\u6210\u6267\u884C\u8BA1\u5212", state: planStep }), _jsx(ProgressRow, { title: "\u6267\u884C\u4F9D\u8D56\u95ED\u5305", description: progress.current?.target ? `当前:${progress.current.target}` : undefined, meta: `${elapsedSeconds}s`, state: closureStep, compact: policy.mode === 'compact' }), _jsx(ProgressRow, { title: "\u9A8C\u8BC1\u5B8C\u6574\u7ED3\u679C", state: verificationStep })] }) : _jsxs(_Fragment, { children: [_jsx(ProgressRow, { title: sourceOperation ? '检查来源操作输入' : configOperation ? '验证设置值' : '检查兼容性', state: !currentPhase ? 'pending' : preflightActive ? 'active' : 'complete' }), _jsx(ProgressRow, { title: progress.current?.phase || (sourceOperation ? '
|
|
3276
|
+
content = portableOperation ? _jsxs(StatusCard, { status: failedProgress ? 'error' : 'info', title: "Skills CLI", children: [_jsx(ProgressRow, { title: "\u68C0\u67E5\u63D2\u4EF6\u548C\u4F9D\u8D56", description: `${snapshot.activeReview?.subject.name ?? '当前插件'} · ${portableDraft?.dependencySummary?.directCount ?? 0} 个直接依赖`, meta: portableProgressMeta(0), state: portableProgressState(0), compact: compactPortableProgress }), _jsx(ProgressRow, { title: "\u751F\u6210\u5DF2\u9009\u5019\u9009 Skills", description: `${portableProviderCount} 个 provider 提供 ${portableSelectedCount} 个 Skills`, meta: portableProgressMeta(1), state: portableProgressState(1), compact: compactPortableProgress }), _jsx(ProgressRow, { title: `安装已选择的 ${portableSelectedCount} 个 Skills`, description: `Agent:${portableDraft?.agentMode === 'explicit' ? portableDraft.requestedAgents.join('、') : 'Skills CLI 默认选择'}`, meta: portableProgressMeta(2), state: portableProgressState(2), compact: compactPortableProgress }), _jsx(ProgressRow, { title: "\u9A8C\u8BC1\u7ED3\u679C", description: "\u9010\u9879\u786E\u8BA4\u6240\u9009 Skill \u7684\u5B89\u88C5\u76EE\u6807", meta: portableProgressMeta(3), state: portableProgressState(3), compact: compactPortableProgress }), showTechnical ? _jsxs(TechnicalDetails, { children: [technicalMessages.map((message, index) => _jsx(StaticRow, { title: message, compact: true }, `${index}:${message}`)), hiddenTechnicalMessages > 0 ? _jsx(StaticRow, { title: `另有 ${hiddenTechnicalMessages} 条技术消息`, status: "muted", compact: true }) : null] }) : null] }) : _jsxs(StatusCard, { status: "info", children: [dependencyProgress ? _jsxs(_Fragment, { children: [_jsx(ProgressRow, { title: "\u68C0\u67E5\u4F9D\u8D56\u5173\u7CFB", state: relationStep }), _jsx(ProgressRow, { title: "\u751F\u6210\u6267\u884C\u8BA1\u5212", state: planStep }), _jsx(ProgressRow, { title: "\u6267\u884C\u4F9D\u8D56\u95ED\u5305", description: progress.current?.target ? `当前:${progress.current.target}` : undefined, meta: `${elapsedSeconds}s`, state: closureStep, compact: policy.mode === 'compact' }), _jsx(ProgressRow, { title: "\u9A8C\u8BC1\u5B8C\u6574\u7ED3\u679C", state: verificationStep })] }) : _jsxs(_Fragment, { children: [_jsx(ProgressRow, { title: sourceOperation ? '检查来源操作输入' : configOperation ? '验证设置值' : '检查兼容性', state: !currentPhase ? 'pending' : preflightActive ? 'active' : 'complete' }), _jsx(ProgressRow, { title: progress.current?.phase || (sourceOperation ? '保存来源配置' : configOperation ? '保存设置层并重新应用' : '连接到所选目标平台'), description: progress.current?.target ? `当前:${progress.current.target}` : undefined, meta: `${elapsedSeconds}s`, state: failedProgress ? 'error' : executionActive ? 'active' : validationActive ? 'complete' : 'pending', compact: policy.mode === 'compact' }), _jsx(ProgressRow, { title: "\u9A8C\u8BC1\u7ED3\u679C", state: failedProgress ? 'error' : validationActive ? 'active' : 'pending' })] }), dependencyProgress ? _jsxs(SectionCard, { title: "\u6267\u884C\u76EE\u6807", meta: `${snapshot.progressTargets.length} 个目标`, children: [visibleProgressTargets.map((entry) => {
|
|
3139
3277
|
const state = progressLabel(entry);
|
|
3140
3278
|
const relation = entry.relation === 'requested' ? '你选择的插件' : entry.relation === 'direct' ? '直接依赖' : '间接依赖';
|
|
3141
3279
|
const title = props.controller.getPluginOverview(entry.pluginId)?.displayName
|
|
@@ -3155,7 +3293,6 @@ export function ConsoleAppV4(props) {
|
|
|
3155
3293
|
: result.state === 'blocked' ? result.summary : undefined;
|
|
3156
3294
|
const action = resultSummary?.action;
|
|
3157
3295
|
const operationKind = 'operationKind' in result ? result.operationKind : undefined;
|
|
3158
|
-
const catalogActivation = operationKind === 'catalogActivate';
|
|
3159
3296
|
const portableOperation = operationKind === 'portableInstall';
|
|
3160
3297
|
const portableReceipt = result.state === 'succeeded' || result.state === 'partial'
|
|
3161
3298
|
? result.summary.portable : undefined;
|
|
@@ -3166,8 +3303,6 @@ export function ConsoleAppV4(props) {
|
|
|
3166
3303
|
? operationKind : undefined;
|
|
3167
3304
|
const successfulConfigOperation = configOperation !== undefined && !blocked && !partial;
|
|
3168
3305
|
const sourceOperation = operationKind === 'sourceMutation';
|
|
3169
|
-
const sourceRefreshWarning = sourceOperation && 'summary' in result
|
|
3170
|
-
&& result.summary?.messages?.some((message) => message.startsWith('警告:'));
|
|
3171
3306
|
const issueOperation = result.originIssue;
|
|
3172
3307
|
const completedTitle = {
|
|
3173
3308
|
install: '✓ 插件添加完成',
|
|
@@ -3175,26 +3310,24 @@ export function ConsoleAppV4(props) {
|
|
|
3175
3310
|
reinstall: '✓ 插件重新安装完成',
|
|
3176
3311
|
uninstall: '✓ 插件移除完成',
|
|
3177
3312
|
cleanup: '✓ 插件清理完成',
|
|
3313
|
+
sync: '✓ 插件同步完成',
|
|
3178
3314
|
}[action ?? 'install'];
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
:
|
|
3183
|
-
?
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
:
|
|
3195
|
-
: partial ? '! 插件操作只完成了一部分'
|
|
3196
|
-
: blocked ? result.code === 'operationFailed' ? '× 插件操作没有完成' : '× 插件操作未完成'
|
|
3197
|
-
: completedTitle;
|
|
3315
|
+
title = portableOperation
|
|
3316
|
+
? blocked ? '× 通用 Skills 安装被阻止'
|
|
3317
|
+
: partial ? '! 通用 Skills 结果未完全完成' : '✓ 通用 Skills 已安装'
|
|
3318
|
+
: blocked && result.writeMayHaveCompleted
|
|
3319
|
+
? '× 写入结果未确认'
|
|
3320
|
+
: issueOperation
|
|
3321
|
+
? blocked || partial ? '× 问题仍未解决' : '✓ 问题已处理'
|
|
3322
|
+
: sourceOperation
|
|
3323
|
+
? blocked ? '× 来源操作未完成' : '✓ 来源配置已保存'
|
|
3324
|
+
: configOperation
|
|
3325
|
+
? blocked
|
|
3326
|
+
? '× 设置未确认保存'
|
|
3327
|
+
: partial ? '! 设置已保存,但部分应用失败' : '✓ 设置已保存并应用'
|
|
3328
|
+
: partial ? '! 插件操作只完成了一部分'
|
|
3329
|
+
: blocked ? result.code === 'operationFailed' ? '× 插件操作没有完成' : '× 插件操作未完成'
|
|
3330
|
+
: completedTitle;
|
|
3198
3331
|
description = portableOperation
|
|
3199
3332
|
? blocked
|
|
3200
3333
|
? result.code === 'operationReviewExpired' || result.code === 'reviewTicketExpired'
|
|
@@ -3218,11 +3351,9 @@ export function ConsoleAppV4(props) {
|
|
|
3218
3351
|
: sourceOperation
|
|
3219
3352
|
? blocked
|
|
3220
3353
|
? result.writeMayHaveCompleted
|
|
3221
|
-
? '
|
|
3354
|
+
? '来源配置可能已保存。请重新检查来源列表。'
|
|
3222
3355
|
: '来源操作未执行。草稿已保留,可返回修改。'
|
|
3223
|
-
:
|
|
3224
|
-
? '来源配置已保留。请根据警告修复来源后重试刷新。'
|
|
3225
|
-
: '来源配置已保存,刷新已完成。'
|
|
3356
|
+
: '来源配置已保存。请在终端运行 aw catalog source sync,然后重新加载 TUI。'
|
|
3226
3357
|
: blocked ? result.message
|
|
3227
3358
|
: configOperation ? '设置层已经更新。' : '状态已刷新。';
|
|
3228
3359
|
const pluginId = resultSummary?.pluginId
|
|
@@ -3504,7 +3635,9 @@ export function ConsoleAppV4(props) {
|
|
|
3504
3635
|
try {
|
|
3505
3636
|
const pending = action.run?.();
|
|
3506
3637
|
if (pending)
|
|
3507
|
-
void pending.catch(() => {
|
|
3638
|
+
void pending.catch((error) => {
|
|
3639
|
+
if (error instanceof Error && error.name === 'AbortError')
|
|
3640
|
+
return;
|
|
3508
3641
|
setActionError('操作未完成。请重新检查后重试。');
|
|
3509
3642
|
});
|
|
3510
3643
|
}
|
|
@@ -3860,14 +3993,12 @@ export function ConsoleAppV4(props) {
|
|
|
3860
3993
|
setScrollOffset(0);
|
|
3861
3994
|
}
|
|
3862
3995
|
else if (input.toLowerCase() === 'r' && route.name === 'sourceDetail') {
|
|
3863
|
-
|
|
3864
|
-
void props.controller.refreshSource(route.sourceId);
|
|
3996
|
+
void props.controller.reloadCatalog({ sourceId: route.sourceId });
|
|
3865
3997
|
}
|
|
3866
3998
|
else if (input.toLowerCase() === 'r' && route.name === 'sourceList') {
|
|
3867
3999
|
const source = props.controller.listSources()[focus];
|
|
3868
4000
|
if (source) {
|
|
3869
|
-
|
|
3870
|
-
void props.controller.refreshSource(source.id);
|
|
4001
|
+
void props.controller.reloadCatalog({ sourceId: source.id });
|
|
3871
4002
|
}
|
|
3872
4003
|
}
|
|
3873
4004
|
else if (route.name === 'pluginList' && (key.leftArrow || key.rightArrow || input === '[' || input === ']')) {
|
|
@@ -3910,7 +4041,7 @@ export function ConsoleAppV4(props) {
|
|
|
3910
4041
|
const viewport = route.name === 'portableSkillSelect' && snapshot.portableDraft
|
|
3911
4042
|
? portableSkillCandidateViewport(actions.slice(0, snapshot.portableDraft.candidates.length), snapshot.portableDraft.candidates, policy.mode === 'compact', next, scrollOffset, pageActionBudget(actions.length - snapshot.portableDraft.candidates.length
|
|
3912
4043
|
+ (portableVariantCandidates.length > 0 ? 3 : 0)))
|
|
3913
|
-
: actionViewport(actions, policy.mode === 'compact', next, scrollOffset, pageActionBudget());
|
|
4044
|
+
: actionViewport(actions, policy.mode === 'compact', next, scrollOffset, pageActionBudget(route.name === 'dependencyPlacement' ? dependencyPlacementStaticRows : 0));
|
|
3914
4045
|
setScrollOffset(viewport.offset);
|
|
3915
4046
|
return next;
|
|
3916
4047
|
});
|
|
@@ -3929,7 +4060,7 @@ export function ConsoleAppV4(props) {
|
|
|
3929
4060
|
const viewport = route.name === 'portableSkillSelect' && snapshot.portableDraft
|
|
3930
4061
|
? portableSkillCandidateViewport(actions.slice(0, snapshot.portableDraft.candidates.length), snapshot.portableDraft.candidates, policy.mode === 'compact', next, scrollOffset, pageActionBudget(actions.length - snapshot.portableDraft.candidates.length
|
|
3931
4062
|
+ (portableVariantCandidates.length > 0 ? 3 : 0)))
|
|
3932
|
-
: actionViewport(actions, policy.mode === 'compact', next, scrollOffset, pageActionBudget());
|
|
4063
|
+
: actionViewport(actions, policy.mode === 'compact', next, scrollOffset, pageActionBudget(route.name === 'dependencyPlacement' ? dependencyPlacementStaticRows : 0));
|
|
3933
4064
|
setScrollOffset(viewport.offset);
|
|
3934
4065
|
return next;
|
|
3935
4066
|
});
|