@lesliechan721/aw 0.1.0-beta.6 → 0.1.0-beta.8
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/init-plugin.mjs +4 -33
- 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/plugin-status.mjs +8 -11
- package/dist/authoring/scripts/plugin-status.mjs.map +1 -1
- package/dist/authoring/scripts/remove-plugin.mjs +1 -0
- package/dist/authoring/scripts/remove-plugin.mjs.map +1 -1
- package/dist/authoring/scripts/validate-plugin.mjs +104 -54
- package/dist/authoring/scripts/validate-plugin.mjs.map +1 -1
- package/dist/scripts/codex-eval-app-server.d.ts +2 -0
- package/dist/scripts/codex-eval-app-server.js +107 -1
- package/dist/scripts/codex-eval-app-server.js.map +1 -1
- package/dist/scripts/eval-plugin-skills.js +5 -2
- package/dist/scripts/eval-plugin-skills.js.map +1 -1
- package/dist/scripts/plugin-eval-contract.d.ts +5 -1
- package/dist/scripts/plugin-eval-contract.js +54 -4
- package/dist/scripts/plugin-eval-contract.js.map +1 -1
- package/dist/scripts/plugin-staging.d.ts +6 -7
- package/dist/scripts/plugin-staging.js +11 -23
- package/dist/scripts/plugin-staging.js.map +1 -1
- package/dist/scripts/test-plugin-scripts.js +2 -33
- package/dist/scripts/test-plugin-scripts.js.map +1 -1
- package/dist/src/adapters/helpers.js +2 -2
- package/dist/src/adapters/helpers.js.map +1 -1
- package/dist/src/authoring/workspace-commands.d.ts +17 -2
- package/dist/src/authoring/workspace-commands.js +21 -4
- package/dist/src/authoring/workspace-commands.js.map +1 -1
- package/dist/src/commands/aw-capabilities.d.ts +78 -0
- package/dist/src/commands/aw-capabilities.js +259 -0
- package/dist/src/commands/aw-capabilities.js.map +1 -0
- package/dist/src/commands/catalog-context.d.ts +52 -0
- package/dist/src/commands/catalog-context.js +156 -0
- package/dist/src/commands/catalog-context.js.map +1 -0
- package/dist/src/commands/catalog-dev-source.d.ts +112 -0
- package/dist/src/commands/catalog-dev-source.js +481 -0
- package/dist/src/commands/catalog-dev-source.js.map +1 -0
- package/dist/src/commands/catalog-generation.d.ts +26 -0
- package/dist/src/commands/catalog-generation.js +14 -0
- package/dist/src/commands/catalog-generation.js.map +1 -0
- package/dist/src/commands/catalog-publication-inspection.d.ts +1 -1
- package/dist/src/commands/catalog-publication-inspection.js +4 -5
- package/dist/src/commands/catalog-publication-inspection.js.map +1 -1
- package/dist/src/commands/catalog-publication-target.d.ts +17 -0
- package/dist/src/commands/catalog-publication-target.js +60 -0
- package/dist/src/commands/catalog-publication-target.js.map +1 -0
- package/dist/src/commands/catalog-publish.d.ts +8 -1
- package/dist/src/commands/catalog-publish.js +25 -2
- package/dist/src/commands/catalog-publish.js.map +1 -1
- package/dist/src/commands/catalog-source.d.ts +23 -1
- package/dist/src/commands/catalog-source.js +126 -40
- package/dist/src/commands/catalog-source.js.map +1 -1
- package/dist/src/commands/catalog-status.d.ts +18 -2
- package/dist/src/commands/catalog-status.js +122 -18
- package/dist/src/commands/catalog-status.js.map +1 -1
- package/dist/src/commands/init.js +1 -1
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/offline-cleanup-evidence.d.ts +23 -0
- package/dist/src/commands/offline-cleanup-evidence.js +38 -0
- package/dist/src/commands/offline-cleanup-evidence.js.map +1 -0
- package/dist/src/commands/options.d.ts +1 -0
- package/dist/src/commands/options.js +1 -0
- package/dist/src/commands/options.js.map +1 -1
- package/dist/src/commands/plugin-capabilities.js +1 -1
- package/dist/src/commands/plugin-capabilities.js.map +1 -1
- package/dist/src/commands/rebuild-command.d.ts +19 -7
- package/dist/src/commands/rebuild-command.js +415 -205
- package/dist/src/commands/rebuild-command.js.map +1 -1
- package/dist/src/commands/rebuild-integration.d.ts +10 -3
- package/dist/src/commands/rebuild-integration.js +73 -76
- package/dist/src/commands/rebuild-integration.js.map +1 -1
- package/dist/src/commands/rebuild-operations.d.ts +0 -8
- package/dist/src/commands/rebuild-operations.js +17 -115
- package/dist/src/commands/rebuild-operations.js.map +1 -1
- package/dist/src/commands/runtime.js +21 -34
- package/dist/src/commands/runtime.js.map +1 -1
- package/dist/src/commands/{status-v4.d.ts → status-v5.d.ts} +67 -21
- package/dist/src/commands/{status-v4.js → status-v5.js} +260 -30
- package/dist/src/commands/status-v5.js.map +1 -0
- package/dist/src/commands/wizard.d.ts +2 -2
- package/dist/src/commands/wizard.js +2 -2
- package/dist/src/commands/wizard.js.map +1 -1
- package/dist/src/commands/write-commands.js +73 -17
- package/dist/src/commands/write-commands.js.map +1 -1
- package/dist/src/constants.d.ts +6 -1
- package/dist/src/constants.js +6 -1
- package/dist/src/constants.js.map +1 -1
- package/dist/src/generators/local-plugin.js +57 -3
- package/dist/src/generators/local-plugin.js.map +1 -1
- package/dist/src/index.d.ts +4 -1
- package/dist/src/index.js +562 -85
- package/dist/src/index.js.map +1 -1
- package/dist/src/output/model.d.ts +1 -34
- package/dist/src/output/model.js +1 -144
- package/dist/src/output/model.js.map +1 -1
- package/dist/src/output/rebuild-progress.js +0 -3
- package/dist/src/output/rebuild-progress.js.map +1 -1
- package/dist/src/portable/commands.d.ts +4 -0
- package/dist/src/portable/commands.js +61 -4
- package/dist/src/portable/commands.js.map +1 -1
- package/dist/src/portable/materializer.d.ts +3 -0
- package/dist/src/portable/materializer.js +61 -10
- package/dist/src/portable/materializer.js.map +1 -1
- package/dist/src/tui/catalog-generation.d.ts +56 -0
- package/dist/src/tui/catalog-generation.js +244 -0
- package/dist/src/tui/catalog-generation.js.map +1 -0
- package/dist/src/tui/console-app-v4.d.ts +1 -1
- package/dist/src/tui/console-app-v4.js +446 -126
- package/dist/src/tui/console-app-v4.js.map +1 -1
- package/dist/src/tui/controller-runtime.d.ts +8 -2
- package/dist/src/tui/controller-runtime.js +606 -92
- package/dist/src/tui/controller-runtime.js.map +1 -1
- package/dist/src/tui/controller.d.ts +71 -6
- package/dist/src/tui/controller.js +377 -83
- package/dist/src/tui/controller.js.map +1 -1
- package/dist/src/tui/index.d.ts +1 -0
- package/dist/src/tui/index.js +1 -0
- package/dist/src/tui/index.js.map +1 -1
- package/dist/src/tui/input-display.d.ts +8 -0
- package/dist/src/tui/input-display.js +36 -0
- package/dist/src/tui/input-display.js.map +1 -0
- package/dist/src/tui/model.d.ts +27 -7
- package/dist/src/tui/model.js +273 -65
- package/dist/src/tui/model.js.map +1 -1
- package/dist/src/tui/router.d.ts +26 -0
- package/dist/src/tui/router.js.map +1 -1
- package/dist/src/tui/source-ref-presets.d.ts +3 -0
- package/dist/src/tui/source-ref-presets.js +11 -0
- package/dist/src/tui/source-ref-presets.js.map +1 -0
- package/dist/src/tui/views.js +31 -3
- package/dist/src/tui/views.js.map +1 -1
- package/dist/src/types.d.ts +90 -6
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/agent-version.d.ts +3 -0
- package/dist/src/utils/agent-version.js +13 -5
- package/dist/src/utils/agent-version.js.map +1 -1
- package/dist/src/utils/aw-home-mutation-lock.d.ts +1 -0
- package/dist/src/utils/aw-home-mutation-lock.js +32 -4
- package/dist/src/utils/aw-home-mutation-lock.js.map +1 -1
- package/dist/src/utils/bundle-integrity.d.ts +0 -1
- package/dist/src/utils/bundle-integrity.js +0 -25
- package/dist/src/utils/bundle-integrity.js.map +1 -1
- package/dist/src/utils/bundle-layout.js +8 -6
- package/dist/src/utils/bundle-layout.js.map +1 -1
- package/dist/src/utils/catalog-digests.js +13 -2
- package/dist/src/utils/catalog-digests.js.map +1 -1
- package/dist/src/utils/catalog-generation-error.d.ts +12 -0
- package/dist/src/utils/catalog-generation-error.js +16 -0
- package/dist/src/utils/catalog-generation-error.js.map +1 -0
- package/dist/src/utils/catalog-generation-resolver.d.ts +13 -0
- package/dist/src/utils/catalog-generation-resolver.js +129 -0
- package/dist/src/utils/catalog-generation-resolver.js.map +1 -0
- package/dist/src/utils/catalog-generation-service.d.ts +52 -0
- package/dist/src/utils/catalog-generation-service.js +620 -0
- package/dist/src/utils/catalog-generation-service.js.map +1 -0
- package/dist/src/utils/catalog-generation-state.d.ts +13 -0
- package/dist/src/utils/catalog-generation-state.js +201 -0
- package/dist/src/utils/catalog-generation-state.js.map +1 -0
- package/dist/src/utils/catalog-generation-store.d.ts +44 -0
- package/dist/src/utils/catalog-generation-store.js +387 -0
- package/dist/src/utils/catalog-generation-store.js.map +1 -0
- package/dist/src/utils/catalog-manifest-v5.d.ts +5 -0
- package/dist/src/utils/{catalog-manifest-v4.js → catalog-manifest-v5.js} +39 -35
- package/dist/src/utils/{catalog-manifest-v4.js.map → catalog-manifest-v5.js.map} +1 -1
- package/dist/src/utils/catalog-operation-context.d.ts +28 -0
- package/dist/src/utils/catalog-operation-context.js +242 -0
- package/dist/src/utils/catalog-operation-context.js.map +1 -0
- package/dist/src/utils/catalog-public-error.d.ts +7 -3
- package/dist/src/utils/catalog-public-error.js +20 -4
- package/dist/src/utils/catalog-public-error.js.map +1 -1
- package/dist/src/utils/catalog-snapshot.d.ts +5 -3
- package/dist/src/utils/catalog-snapshot.js +11 -3
- package/dist/src/utils/catalog-snapshot.js.map +1 -1
- package/dist/src/utils/catalog-source-cache.d.ts +1 -1
- package/dist/src/utils/catalog-source-cache.js +37 -12
- package/dist/src/utils/catalog-source-cache.js.map +1 -1
- package/dist/src/utils/catalog-source-identity.d.ts +1 -0
- package/dist/src/utils/catalog-source-identity.js +21 -2
- package/dist/src/utils/catalog-source-identity.js.map +1 -1
- package/dist/src/utils/catalog-sources.d.ts +1 -0
- package/dist/src/utils/catalog-sources.js +30 -11
- package/dist/src/utils/catalog-sources.js.map +1 -1
- package/dist/src/utils/codex-config.js +4 -4
- package/dist/src/utils/codex-config.js.map +1 -1
- package/dist/src/utils/codex-manager.d.ts +33 -0
- package/dist/src/utils/codex-manager.js +656 -0
- package/dist/src/utils/codex-manager.js.map +1 -0
- package/dist/src/utils/codex-skill-staging.d.ts +2 -0
- package/dist/src/utils/codex-skill-staging.js.map +1 -1
- package/dist/src/utils/dynamic-skill-tree.d.ts +4 -0
- package/dist/src/utils/dynamic-skill-tree.js +35 -5
- package/dist/src/utils/dynamic-skill-tree.js.map +1 -1
- package/dist/src/utils/git-catalog-provider.js +10 -25
- package/dist/src/utils/git-catalog-provider.js.map +1 -1
- package/dist/src/utils/lifecycle-active-store.d.ts +0 -28
- package/dist/src/utils/lifecycle-active-store.js +35 -247
- package/dist/src/utils/lifecycle-active-store.js.map +1 -1
- package/dist/src/utils/multi-source-catalog.d.ts +3 -0
- package/dist/src/utils/multi-source-catalog.js +120 -10
- package/dist/src/utils/multi-source-catalog.js.map +1 -1
- package/dist/src/utils/native-cli.d.ts +15 -6
- package/dist/src/utils/native-cli.js +31 -39
- package/dist/src/utils/native-cli.js.map +1 -1
- package/dist/src/utils/orphan-marketplace-cleanup.js +0 -3
- package/dist/src/utils/orphan-marketplace-cleanup.js.map +1 -1
- package/dist/src/utils/ownership.d.ts +10 -1
- package/dist/src/utils/ownership.js +52 -24
- package/dist/src/utils/ownership.js.map +1 -1
- package/dist/src/utils/path-catalog-provider.js +12 -8
- package/dist/src/utils/path-catalog-provider.js.map +1 -1
- package/dist/src/utils/plugin-config-write.js +18 -35
- package/dist/src/utils/plugin-config-write.js.map +1 -1
- package/dist/src/utils/plugin-config.d.ts +1 -12
- package/dist/src/utils/plugin-config.js +107 -226
- package/dist/src/utils/plugin-config.js.map +1 -1
- package/dist/src/utils/plugin-scripts.d.ts +1 -1
- package/dist/src/utils/plugin-scripts.js +1 -1
- package/dist/src/utils/plugin-scripts.js.map +1 -1
- package/dist/src/utils/state-paths.js +7 -2
- package/dist/src/utils/state-paths.js.map +1 -1
- package/dist/src/utils/target-eligibility.d.ts +7 -2
- package/dist/src/utils/target-eligibility.js +6 -3
- package/dist/src/utils/target-eligibility.js.map +1 -1
- package/package.json +4 -3
- package/dist/authoring/scripts/check-plugin-versions.d.mts +0 -2
- package/dist/authoring/scripts/check-plugin-versions.mjs +0 -5
- package/dist/authoring/scripts/check-plugin-versions.mjs.map +0 -1
- package/dist/src/commands/status-v4.js.map +0 -1
- package/dist/src/commands/status.d.ts +0 -93
- package/dist/src/commands/status.js +0 -442
- package/dist/src/commands/status.js.map +0 -1
- package/dist/src/utils/active-marketplace-runtime-lock.d.ts +0 -12
- package/dist/src/utils/active-marketplace-runtime-lock.js +0 -133
- package/dist/src/utils/active-marketplace-runtime-lock.js.map +0 -1
- package/dist/src/utils/catalog-manifest-v3.d.ts +0 -2
- package/dist/src/utils/catalog-manifest-v3.js +0 -3
- package/dist/src/utils/catalog-manifest-v3.js.map +0 -1
- package/dist/src/utils/catalog-manifest-v4.d.ts +0 -5
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { Box, Text, useInput, useWindowSize } from 'ink';
|
|
3
3
|
import { useEffect, useRef, useState } from 'react';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
+
import { CATALOG_BETA_REF, CATALOG_LATEST_REF, OFFICIAL_CATALOG_SOURCE_SSH_URL, OFFICIAL_CATALOG_SOURCE_URL, } from '../constants.js';
|
|
5
6
|
import { CATALOG_SOURCE_ID_PATTERN } from '../utils/catalog-sources.js';
|
|
6
7
|
import { canonicalizeCatalogGitUrl } from '../utils/catalog-source-identity.js';
|
|
7
8
|
import { normalizePortableAgents } from '../portable/commands.js';
|
|
@@ -10,6 +11,8 @@ import { ActionRow, Callout, ChoiceRow, DiagnosticSummary, InputCard, PluginList
|
|
|
10
11
|
import { safeDiagnosticCode, sanitizeDiagnosticText, } from './diagnostics.js';
|
|
11
12
|
import { extractPortableError, userIssueKey } from './controller.js';
|
|
12
13
|
import { resolveTuiSizePolicy } from './layout.js';
|
|
14
|
+
import { InputDisplay, removeLastGrapheme } from './input-display.js';
|
|
15
|
+
import { catalogRefPolicyForPreset } from './source-ref-presets.js';
|
|
13
16
|
import { buildPlatformActions, buildPluginDetailActions, buildPluginPreviewActions, hasInstalledPlacement, } from './model.js';
|
|
14
17
|
import { tuiTheme } from './theme.js';
|
|
15
18
|
import { contentRowBudget, rowViewport } from './viewport.js';
|
|
@@ -26,6 +29,7 @@ export const CONSOLE_V4_SCREEN_IDS = [
|
|
|
26
29
|
'D01', 'D02', 'D03', 'D04', 'D05', 'D06', 'D07', 'D08', 'D09',
|
|
27
30
|
'D10', 'D11', 'D12', 'D13', 'D14', 'D15', 'D16', 'D17',
|
|
28
31
|
'U01', 'U02', 'U03', 'U04', 'U05', 'U06', 'U07', 'U08', 'U09', 'U10', 'U11',
|
|
32
|
+
'K01', 'K02', 'K03', 'K04', 'K05', 'K06', 'K07',
|
|
29
33
|
];
|
|
30
34
|
function pluginMenuActionId(action) {
|
|
31
35
|
return action.id === 'platform' || action.id === 'scopeConflict'
|
|
@@ -125,6 +129,18 @@ function pluginPlacementSummary(plugin) {
|
|
|
125
129
|
return `${label} · ${scopeLabel(placement.scope)} · ${health}`;
|
|
126
130
|
}).join(' | ') || '没有可用平台';
|
|
127
131
|
}
|
|
132
|
+
function issueGroupLabel(group) {
|
|
133
|
+
return {
|
|
134
|
+
sourceRemoved: '来源已移除',
|
|
135
|
+
artifactCollision: '输出冲突',
|
|
136
|
+
sourceUnavailable: '来源不可用',
|
|
137
|
+
dependency: '依赖',
|
|
138
|
+
scope: '位置',
|
|
139
|
+
config: '设置',
|
|
140
|
+
installation: '安装',
|
|
141
|
+
diagnostic: '诊断',
|
|
142
|
+
}[group];
|
|
143
|
+
}
|
|
128
144
|
function pluginRowStatus(plugin) {
|
|
129
145
|
if (plugin.aggregateStatus === 'needsAttention')
|
|
130
146
|
return 'warning';
|
|
@@ -508,7 +524,7 @@ export function resolveConsoleV4ScreenId(snapshot, controller, overlay, tooSmall
|
|
|
508
524
|
return 'G01';
|
|
509
525
|
const route = snapshot.router.current.route;
|
|
510
526
|
if (route.name === 'home')
|
|
511
|
-
return 'G02';
|
|
527
|
+
return controller.listCatalogCandidates().length > 0 ? 'K01' : 'G02';
|
|
512
528
|
if (route.name === 'pluginList') {
|
|
513
529
|
const items = controller.listPlugins({ mode: route.mode, sourceId: route.sourceId });
|
|
514
530
|
if (route.mode === 'installed' && items.length === 0)
|
|
@@ -566,7 +582,7 @@ export function resolveConsoleV4ScreenId(snapshot, controller, overlay, tooSmall
|
|
|
566
582
|
return 'P16';
|
|
567
583
|
}
|
|
568
584
|
if (route.name === 'reviewPreparing')
|
|
569
|
-
return 'P07';
|
|
585
|
+
return snapshot.reviewPreparation?.intent.kind === 'catalogActivate' ? 'K03' : 'P07';
|
|
570
586
|
const dependencyOperation = snapshot.activeReview?.operationKind === 'pluginWrite'
|
|
571
587
|
&& Boolean(snapshot.activeReview.changes.some((change) => change.group));
|
|
572
588
|
if (route.name === 'review' && dependencyOperation) {
|
|
@@ -601,27 +617,30 @@ export function resolveConsoleV4ScreenId(snapshot, controller, overlay, tooSmall
|
|
|
601
617
|
return snapshot.result.state === 'succeeded' ? 'S12' : 'S13';
|
|
602
618
|
}
|
|
603
619
|
if (route.name === 'review')
|
|
604
|
-
return snapshot.activeReview?.operationKind === '
|
|
605
|
-
: snapshot.activeReview?.operationKind === '
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
&& (snapshot.activeReview.pluginAction === 'upgrade' || snapshot.activeReview.pluginAction === 'reinstall')
|
|
611
|
-
? 'P18'
|
|
620
|
+
return snapshot.activeReview?.operationKind === 'catalogActivate' ? 'K03'
|
|
621
|
+
: snapshot.activeReview?.operationKind === 'portableInstall' ? 'U06'
|
|
622
|
+
: snapshot.activeReview?.operationKind === 'configSave'
|
|
623
|
+
? 'C12'
|
|
624
|
+
: snapshot.activeReview?.operationKind === 'configReset'
|
|
625
|
+
? 'C16'
|
|
612
626
|
: snapshot.activeReview?.operationKind === 'pluginWrite'
|
|
613
|
-
&& (snapshot.activeReview.pluginAction === '
|
|
614
|
-
? '
|
|
627
|
+
&& (snapshot.activeReview.pluginAction === 'upgrade' || snapshot.activeReview.pluginAction === 'reinstall')
|
|
628
|
+
? 'P18'
|
|
629
|
+
: snapshot.activeReview?.operationKind === 'pluginWrite'
|
|
630
|
+
&& (snapshot.activeReview.pluginAction === 'uninstall' || snapshot.activeReview.pluginAction === 'cleanup')
|
|
631
|
+
? 'P19' : 'P07';
|
|
615
632
|
if (route.name === 'progress')
|
|
616
|
-
return snapshot.activeReview?.operationKind === '
|
|
617
|
-
: snapshot.activeReview?.operationKind === '
|
|
618
|
-
|
|
633
|
+
return snapshot.activeReview?.operationKind === 'catalogActivate' ? 'K03'
|
|
634
|
+
: snapshot.activeReview?.operationKind === 'portableInstall' ? 'U07'
|
|
635
|
+
: snapshot.activeReview?.operationKind === 'configSave'
|
|
636
|
+
|| snapshot.activeReview?.operationKind === 'configReset' ? 'C13' : 'P08';
|
|
619
637
|
if (route.name === 'result')
|
|
620
|
-
return snapshot.result?.operationKind === '
|
|
621
|
-
: snapshot.result?.operationKind === '
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
638
|
+
return snapshot.result?.operationKind === 'catalogActivate' ? 'K03'
|
|
639
|
+
: snapshot.result?.operationKind === 'portableInstall' ? 'U08'
|
|
640
|
+
: snapshot.result?.operationKind === 'configSave'
|
|
641
|
+
|| snapshot.result?.operationKind === 'configReset'
|
|
642
|
+
? snapshot.result.state === 'succeeded' ? 'C14' : 'C15'
|
|
643
|
+
: snapshot.result?.state === 'partial' ? 'P10' : 'P09';
|
|
625
644
|
if (route.name === 'pluginAbout')
|
|
626
645
|
return 'P20';
|
|
627
646
|
if (route.name === 'pluginTechnical')
|
|
@@ -630,6 +649,8 @@ export function resolveConsoleV4ScreenId(snapshot, controller, overlay, tooSmall
|
|
|
630
649
|
return 'C01';
|
|
631
650
|
if (route.name === 'configFields')
|
|
632
651
|
return route.layer.scope === 'effective' ? 'C02' : 'C03';
|
|
652
|
+
if (route.name === 'configFieldAction')
|
|
653
|
+
return 'C04';
|
|
633
654
|
if (route.name === 'configFieldEditor')
|
|
634
655
|
return {
|
|
635
656
|
enum: 'C05', boolean: 'C06', number: 'C07', string: 'C08', path: 'C09', sensitive: 'C10',
|
|
@@ -638,10 +659,18 @@ export function resolveConsoleV4ScreenId(snapshot, controller, overlay, tooSmall
|
|
|
638
659
|
return 'C17';
|
|
639
660
|
if (route.name === 'sourceList')
|
|
640
661
|
return 'S01';
|
|
641
|
-
if (route.name === 'sourceDetail')
|
|
642
|
-
return '
|
|
662
|
+
if (route.name === 'sourceDetail' || route.name === 'catalogCandidate')
|
|
663
|
+
return 'K02';
|
|
643
664
|
if (route.name === 'sourceTechnical')
|
|
644
665
|
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';
|
|
645
674
|
if (route.name === 'sourceAdd')
|
|
646
675
|
return {
|
|
647
676
|
type: 'S04', id: 'S05', location: 'S06', refPolicy: 'S07', ref: 'S08', subdir: 'S09',
|
|
@@ -658,6 +687,7 @@ export function resolveConsoleV4ScreenId(snapshot, controller, overlay, tooSmall
|
|
|
658
687
|
const category = controller.listUserIssues().find((issue) => issue.issueId === route.issueId)?.category;
|
|
659
688
|
return {
|
|
660
689
|
incompleteInstallation: 'I03',
|
|
690
|
+
artifactCollision: 'I09',
|
|
661
691
|
sourceDegraded: 'I04',
|
|
662
692
|
sourceUnavailable: 'I04',
|
|
663
693
|
sourceMissing: 'I05',
|
|
@@ -685,7 +715,7 @@ export function ConsoleAppV4(props) {
|
|
|
685
715
|
const [discardForExit, setDiscardForExit] = useState(false);
|
|
686
716
|
const [focus, setFocus] = useState(0);
|
|
687
717
|
const [scrollOffset, setScrollOffset] = useState(0);
|
|
688
|
-
const [
|
|
718
|
+
const [searchFocus, setSearchFocus] = useState(false);
|
|
689
719
|
const [query, setQuery] = useState('');
|
|
690
720
|
const [installFilter, setInstallFilter] = useState(props.controller.snapshot.router.current.context.installFilter ?? 'all');
|
|
691
721
|
const [scope, setScope] = useState('user');
|
|
@@ -714,6 +744,7 @@ export function ConsoleAppV4(props) {
|
|
|
714
744
|
const [portableAgentInput, setPortableAgentInput] = useState('');
|
|
715
745
|
const [draftOwner, setDraftOwner] = useState();
|
|
716
746
|
const [pendingPresetId, setPendingPresetId] = useState();
|
|
747
|
+
const [pendingLayerFieldKey, setPendingLayerFieldKey] = useState();
|
|
717
748
|
const dynamicMenuFocus = useRef(undefined);
|
|
718
749
|
const exitSent = useRef(false);
|
|
719
750
|
const operationBusy = useRef(false);
|
|
@@ -804,6 +835,7 @@ export function ConsoleAppV4(props) {
|
|
|
804
835
|
}, [route.name]);
|
|
805
836
|
const configRoute = route.name === 'configFields'
|
|
806
837
|
|| route.name === 'configFieldEditor'
|
|
838
|
+
|| route.name === 'configFieldAction'
|
|
807
839
|
? route
|
|
808
840
|
: undefined;
|
|
809
841
|
const currentConfigPage = configPageMatches(configPage, configRoute) ? configPage : undefined;
|
|
@@ -910,7 +942,7 @@ export function ConsoleAppV4(props) {
|
|
|
910
942
|
route.name === 'pluginList' ? route.sourceId : '',
|
|
911
943
|
snapshot.viewModel,
|
|
912
944
|
]);
|
|
913
|
-
const activeField = route.name === 'configFieldEditor'
|
|
945
|
+
const activeField = route.name === 'configFieldEditor' || route.name === 'configFieldAction'
|
|
914
946
|
? currentConfigPage?.groups.flatMap((group) => group.fields).find((field) => field.key === route.fieldKey)
|
|
915
947
|
: undefined;
|
|
916
948
|
useEffect(() => {
|
|
@@ -945,7 +977,7 @@ export function ConsoleAppV4(props) {
|
|
|
945
977
|
setSourceReferenceSummary({ blocked: true, inventoryComplete: false, dependencies: [] }); });
|
|
946
978
|
return () => abort.abort();
|
|
947
979
|
}, [props.controller, route.name, route.name === 'sourceRemoveBlocked' ? route.sourceId : '']);
|
|
948
|
-
const screenId = resolveConsoleV4ScreenId(snapshot, props.controller, overlay, tooSmall,
|
|
980
|
+
const screenId = resolveConsoleV4ScreenId(snapshot, props.controller, overlay, tooSmall, searchFocus);
|
|
949
981
|
const portableVariantCandidates = route.name === 'portableSkillSelect' && snapshot.portableDraft
|
|
950
982
|
? snapshot.portableDraft.candidates.filter(portableScopeVariantsDiffer)
|
|
951
983
|
: [];
|
|
@@ -962,7 +994,7 @@ export function ConsoleAppV4(props) {
|
|
|
962
994
|
|| Boolean(route.name === 'result' && snapshot.result && 'operationKind' in snapshot.result
|
|
963
995
|
&& snapshot.result.operationKind === 'portableInstall');
|
|
964
996
|
const canOpenHelp = !tooSmall
|
|
965
|
-
&& !isCharacterInputMode(route,
|
|
997
|
+
&& !isCharacterInputMode(route, searchFocus)
|
|
966
998
|
&& !(route.name === 'installTargets' && route.view !== 'blocked');
|
|
967
999
|
useEffect(() => {
|
|
968
1000
|
props.onScreenChange?.(screenId);
|
|
@@ -1022,7 +1054,7 @@ export function ConsoleAppV4(props) {
|
|
|
1022
1054
|
props.controller.push(next);
|
|
1023
1055
|
setFocus(0);
|
|
1024
1056
|
setScrollOffset(0);
|
|
1025
|
-
|
|
1057
|
+
setSearchFocus(false);
|
|
1026
1058
|
setShowTechnical(false);
|
|
1027
1059
|
setActionError(undefined);
|
|
1028
1060
|
};
|
|
@@ -1037,11 +1069,13 @@ export function ConsoleAppV4(props) {
|
|
|
1037
1069
|
props.controller.beginConfigFlow(pluginId);
|
|
1038
1070
|
setFocus(0);
|
|
1039
1071
|
setScrollOffset(0);
|
|
1040
|
-
|
|
1072
|
+
setSearchFocus(false);
|
|
1041
1073
|
setShowTechnical(false);
|
|
1042
1074
|
setActionError(undefined);
|
|
1043
1075
|
};
|
|
1044
1076
|
const back = () => {
|
|
1077
|
+
if (route.name === 'catalogRefresh')
|
|
1078
|
+
props.controller.cancelCatalogRefresh(route.sourceId);
|
|
1045
1079
|
if (route.name === 'result')
|
|
1046
1080
|
props.controller.leaveResult();
|
|
1047
1081
|
else
|
|
@@ -1051,7 +1085,7 @@ export function ConsoleAppV4(props) {
|
|
|
1051
1085
|
setScrollOffset(restored.scrollOffset ?? 0);
|
|
1052
1086
|
setQuery(restored.query ?? '');
|
|
1053
1087
|
setInstallFilter(restored.installFilter ?? 'all');
|
|
1054
|
-
|
|
1088
|
+
setSearchFocus(false);
|
|
1055
1089
|
setActionError(undefined);
|
|
1056
1090
|
};
|
|
1057
1091
|
const leaveResult = (target) => {
|
|
@@ -1061,7 +1095,7 @@ export function ConsoleAppV4(props) {
|
|
|
1061
1095
|
setScrollOffset(restored.scrollOffset ?? 0);
|
|
1062
1096
|
setQuery(restored.query ?? '');
|
|
1063
1097
|
setInstallFilter(restored.installFilter ?? 'all');
|
|
1064
|
-
|
|
1098
|
+
setSearchFocus(false);
|
|
1065
1099
|
setShowTechnical(false);
|
|
1066
1100
|
setActionError(undefined);
|
|
1067
1101
|
};
|
|
@@ -1314,6 +1348,12 @@ export function ConsoleAppV4(props) {
|
|
|
1314
1348
|
return next;
|
|
1315
1349
|
});
|
|
1316
1350
|
};
|
|
1351
|
+
const cancelDraftRemoval = (key) => {
|
|
1352
|
+
const nextRemoves = draftRemoves.filter((candidate) => candidate !== key);
|
|
1353
|
+
setDraftRemoves(nextRemoves);
|
|
1354
|
+
setDirty(Object.keys(draftUpdates).length + nextRemoves.length > 0);
|
|
1355
|
+
setConfigActionError(undefined);
|
|
1356
|
+
};
|
|
1317
1357
|
const configFieldTarget = (page, key) => {
|
|
1318
1358
|
if (!key)
|
|
1319
1359
|
return undefined;
|
|
@@ -1384,15 +1424,8 @@ export function ConsoleAppV4(props) {
|
|
|
1384
1424
|
setScrollOffset(0);
|
|
1385
1425
|
return;
|
|
1386
1426
|
}
|
|
1387
|
-
if (field && route.fieldKey)
|
|
1388
|
-
|
|
1389
|
-
name: 'configFieldEditor',
|
|
1390
|
-
pluginId: route.pluginId,
|
|
1391
|
-
layer,
|
|
1392
|
-
fieldKey: route.fieldKey,
|
|
1393
|
-
editor: fieldEditor(field),
|
|
1394
|
-
});
|
|
1395
|
-
}
|
|
1427
|
+
if (field && route.fieldKey)
|
|
1428
|
+
setPendingLayerFieldKey(route.fieldKey);
|
|
1396
1429
|
setFocus(0);
|
|
1397
1430
|
setScrollOffset(0);
|
|
1398
1431
|
};
|
|
@@ -1405,7 +1438,9 @@ export function ConsoleAppV4(props) {
|
|
|
1405
1438
|
key,
|
|
1406
1439
|
title: field?.title ?? key,
|
|
1407
1440
|
before: field?.displayValue ?? '未设置',
|
|
1408
|
-
after: draftRemoves.includes(key)
|
|
1441
|
+
after: draftRemoves.includes(key)
|
|
1442
|
+
? `恢复继承(${field?.fallbackDisplayValue ?? '未设置'} · ${field?.fallbackSourceLabel ?? '未设置'})`
|
|
1443
|
+
: currentFieldDisplay(field),
|
|
1409
1444
|
};
|
|
1410
1445
|
});
|
|
1411
1446
|
};
|
|
@@ -1431,6 +1466,38 @@ export function ConsoleAppV4(props) {
|
|
|
1431
1466
|
setConfigActionError('设置值未通过验证。请重新检查修改。');
|
|
1432
1467
|
}
|
|
1433
1468
|
};
|
|
1469
|
+
useEffect(() => {
|
|
1470
|
+
if (!pendingLayerFieldKey || route.name !== 'configFields'
|
|
1471
|
+
|| route.layer.scope === 'effective' || !currentConfigPage)
|
|
1472
|
+
return;
|
|
1473
|
+
const field = currentConfigPage.groups.flatMap((group) => group.fields)
|
|
1474
|
+
.find((candidate) => candidate.key === pendingLayerFieldKey);
|
|
1475
|
+
setPendingLayerFieldKey(undefined);
|
|
1476
|
+
if (!field)
|
|
1477
|
+
return;
|
|
1478
|
+
const layer = { scope: route.layer.scope, projectLayer: route.layer.projectLayer };
|
|
1479
|
+
props.controller.push(field.configured ? {
|
|
1480
|
+
name: 'configFieldAction',
|
|
1481
|
+
pluginId: route.pluginId,
|
|
1482
|
+
layer,
|
|
1483
|
+
fieldKey: field.key,
|
|
1484
|
+
} : {
|
|
1485
|
+
name: 'configFieldEditor',
|
|
1486
|
+
pluginId: route.pluginId,
|
|
1487
|
+
layer,
|
|
1488
|
+
fieldKey: field.key,
|
|
1489
|
+
editor: fieldEditor(field),
|
|
1490
|
+
});
|
|
1491
|
+
}, [pendingLayerFieldKey, route.name, currentConfigPage]);
|
|
1492
|
+
useEffect(() => {
|
|
1493
|
+
if (!pendingLayerFieldKey)
|
|
1494
|
+
return;
|
|
1495
|
+
if (route.name === 'configFields' && route.layer.scope !== 'effective')
|
|
1496
|
+
return;
|
|
1497
|
+
if (route.name === 'configLayer')
|
|
1498
|
+
return;
|
|
1499
|
+
setPendingLayerFieldKey(undefined);
|
|
1500
|
+
}, [pendingLayerFieldKey, route.name]);
|
|
1434
1501
|
useEffect(() => {
|
|
1435
1502
|
if (!pendingPresetId || route.name !== 'configFields'
|
|
1436
1503
|
|| route.layer.scope === 'effective' || !currentConfigPage)
|
|
@@ -1462,14 +1529,27 @@ export function ConsoleAppV4(props) {
|
|
|
1462
1529
|
}
|
|
1463
1530
|
else if (route.name === 'home') {
|
|
1464
1531
|
const home = snapshot.viewModel.home;
|
|
1465
|
-
|
|
1532
|
+
const candidates = props.controller.listCatalogCandidates();
|
|
1533
|
+
const firstCandidate = candidates[0];
|
|
1534
|
+
context = candidates.length > 0 ? 'Catalog 有更新' : '当前项目';
|
|
1466
1535
|
actions = [
|
|
1467
1536
|
{ 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
|
+
}] : []),
|
|
1468
1544
|
{ label: '我的插件', description: '查看状态、设置和移除已添加插件', meta: String(home.installedPlugins), run: () => go({ name: 'pluginList', mode: 'installed' }) },
|
|
1469
1545
|
{ label: '需要处理', description: '解决安装、来源或设置问题', meta: String(home.issueCount), status: 'warning', run: () => go({ name: 'issueList' }) },
|
|
1470
1546
|
{ label: '插件来源', description: '管理 Git 仓库和本地目录', meta: String(home.sourceCount), run: () => go({ name: 'sourceList' }) },
|
|
1471
1547
|
];
|
|
1472
|
-
content = _jsxs(Box, { flexDirection: "column", children: [
|
|
1548
|
+
content = _jsxs(Box, { flexDirection: "column", children: [firstCandidate
|
|
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' })] });
|
|
1473
1553
|
}
|
|
1474
1554
|
else if (route.name === 'pluginList') {
|
|
1475
1555
|
const sourceId = route.sourceId ?? 'all';
|
|
@@ -1479,6 +1559,12 @@ export function ConsoleAppV4(props) {
|
|
|
1479
1559
|
...(query ? { query } : {}),
|
|
1480
1560
|
installFilter,
|
|
1481
1561
|
});
|
|
1562
|
+
const uninstalledCount = props.controller.listPlugins({
|
|
1563
|
+
mode: route.mode,
|
|
1564
|
+
...(sourceId !== 'all' ? { sourceId } : {}),
|
|
1565
|
+
...(query ? { query } : {}),
|
|
1566
|
+
installFilter: 'uninstalled',
|
|
1567
|
+
}).length;
|
|
1482
1568
|
breadcrumb = route.mode === 'browse' ? '添加插件' : '我的插件';
|
|
1483
1569
|
title = breadcrumb;
|
|
1484
1570
|
description = route.mode === 'browse' ? '选择希望 Agent 获得的能力。' : '查看状态,或选择一个插件进行管理。';
|
|
@@ -1492,7 +1578,9 @@ export function ConsoleAppV4(props) {
|
|
|
1492
1578
|
pluginId: item.pluginId,
|
|
1493
1579
|
name: item.displayName,
|
|
1494
1580
|
sourceLabel: item.sourceLabel,
|
|
1495
|
-
description: item.
|
|
1581
|
+
description: item.primaryAttention
|
|
1582
|
+
? `${item.primaryAttention.code} · ${item.primaryAttention.message}`
|
|
1583
|
+
: item.description,
|
|
1496
1584
|
placementSummary: pluginPlacementSummary(item),
|
|
1497
1585
|
statusLabel: statusText(item),
|
|
1498
1586
|
status: pluginRowStatus(item),
|
|
@@ -1505,7 +1593,9 @@ export function ConsoleAppV4(props) {
|
|
|
1505
1593
|
else if (route.mode === 'browse' && items.length === 0 && !sourceError) {
|
|
1506
1594
|
actions = [{
|
|
1507
1595
|
label: '没有匹配插件',
|
|
1508
|
-
description: installFilter === 'uninstalled'
|
|
1596
|
+
description: installFilter === 'uninstalled'
|
|
1597
|
+
? '当前来源和搜索条件下没有未安装插件;按 f 查看全部,或按 / 编辑搜索'
|
|
1598
|
+
: '按 / 编辑搜索,或切换来源',
|
|
1509
1599
|
disabled: '没有可打开的插件',
|
|
1510
1600
|
}];
|
|
1511
1601
|
}
|
|
@@ -1521,8 +1611,10 @@ export function ConsoleAppV4(props) {
|
|
|
1521
1611
|
if (viewport.hiddenBefore > 0 || viewport.hiddenAfter > 0) {
|
|
1522
1612
|
context = `${items.length} 个插件 · ${viewport.position}/${viewport.total}`;
|
|
1523
1613
|
}
|
|
1524
|
-
content = (_jsxs(Box, { flexDirection: "column", children: [_jsx(SourceTabs, { controller: props.controller, current: sourceId, compact: policy.mode === 'compact', columns: size.columns - 2, mode: route.mode, query: query || undefined, installFilter: installFilter }), _jsxs(Text, { color:
|
|
1525
|
-
|
|
1614
|
+
content = (_jsxs(Box, { flexDirection: "column", children: [_jsx(SourceTabs, { controller: props.controller, current: sourceId, compact: policy.mode === 'compact', columns: size.columns - 2, mode: route.mode, query: query || undefined, installFilter: installFilter }), _jsxs(Text, { color: searchFocus ? tuiTheme.colors.accent : tuiTheme.colors.muted, children: ["\u641C\u7D22 / ", searchFocus
|
|
1615
|
+
? _jsx(InputDisplay, { value: query, placeholder: "\u8F93\u5165\u641C\u7D22\u5185\u5BB9", columns: Math.max(8, size.columns - 14) })
|
|
1616
|
+
: _jsxs(_Fragment, { children: [query || '搜索名称、用途或来源…', query ? ' / 编辑' : ''] })] }), route.mode === 'browse'
|
|
1617
|
+
? _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"] })
|
|
1526
1618
|
: null, sourceError
|
|
1527
1619
|
? _jsx(Callout, { status: "error", title: `${sourceId} 暂时无法提供插件`, description: "\u6CA1\u6709\u53EF\u7528\u7F13\u5B58\uFF0C\u56E0\u6B64\u5F53\u524D\u4E0D\u80FD\u6D4F\u89C8\u8FD9\u4E2A\u6765\u6E90\u3002" })
|
|
1528
1620
|
: route.mode === 'installed' && items.length === 0
|
|
@@ -1718,7 +1810,7 @@ export function ConsoleAppV4(props) {
|
|
|
1718
1810
|
title = '输入 Agent ID';
|
|
1719
1811
|
description = '多个 Agent 可使用逗号或空格分隔。';
|
|
1720
1812
|
help = '输入 Agent ID · Enter 保存 · Esc 返回';
|
|
1721
|
-
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(InputCard, { focused: true, title: portableAgentInput
|
|
1813
|
+
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(InputCard, { focused: true, title: _jsx(InputDisplay, { value: portableAgentInput, columns: Math.max(8, size.columns - 8) }), description: inputError ?? 'Enter 保存并继续 · Esc 返回;q 和 b 会作为输入。', status: inputError ? 'error' : undefined }), _jsx(StaticRow, { title: "\u793A\u4F8B", meta: "cursor, claude-code, codex", status: "muted", compact: true })] });
|
|
1722
1814
|
}
|
|
1723
1815
|
else if (route.name === 'portableScope' && plugin && snapshot.portableDraft) {
|
|
1724
1816
|
breadcrumb = `${plugin.displayName} / 通用 Skills / 范围`;
|
|
@@ -2190,7 +2282,12 @@ export function ConsoleAppV4(props) {
|
|
|
2190
2282
|
fieldKey: field.key,
|
|
2191
2283
|
groupId: activeGroup.id,
|
|
2192
2284
|
})
|
|
2193
|
-
: () => go({
|
|
2285
|
+
: () => go(field.configured ? {
|
|
2286
|
+
name: 'configFieldAction',
|
|
2287
|
+
pluginId: plugin.pluginId,
|
|
2288
|
+
layer: mutableLayer,
|
|
2289
|
+
fieldKey: field.key,
|
|
2290
|
+
} : {
|
|
2194
2291
|
name: 'configFieldEditor',
|
|
2195
2292
|
pluginId: plugin.pluginId,
|
|
2196
2293
|
layer: mutableLayer,
|
|
@@ -2200,13 +2297,27 @@ export function ConsoleAppV4(props) {
|
|
|
2200
2297
|
}));
|
|
2201
2298
|
const operationActions = readonly ? [] : [
|
|
2202
2299
|
{ label: '保存修改', description: dirty ? '查看安全变更汇总' : '当前没有未保存修改', disabled: dirty ? undefined : '当前没有未保存修改', run: beginConfigSave },
|
|
2203
|
-
{
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2300
|
+
...(currentConfigPage.storedCount > 0 ? [{
|
|
2301
|
+
label: route.layer.scope === 'user'
|
|
2302
|
+
? '清空个人默认…'
|
|
2303
|
+
: route.layer.projectLayer === 'local' ? '删除本机设置…' : '清空当前项目共享设置…',
|
|
2304
|
+
description: `删除${configLayerLabel(route.layer)}中的全部值并恢复继承;其他设置层保持不变`,
|
|
2305
|
+
status: 'error',
|
|
2306
|
+
run: () => beginReview({
|
|
2307
|
+
kind: 'configReset',
|
|
2308
|
+
pluginId: plugin.pluginId,
|
|
2309
|
+
scope: route.layer.scope,
|
|
2310
|
+
projectLayer: route.layer.projectLayer,
|
|
2311
|
+
changes: currentConfigPage.groups.flatMap((group) => group.fields)
|
|
2312
|
+
.filter((field) => field.configured)
|
|
2313
|
+
.map((field) => ({
|
|
2314
|
+
key: field.key,
|
|
2315
|
+
title: field.title,
|
|
2316
|
+
before: field.displayValue,
|
|
2317
|
+
after: `恢复继承(${field.fallbackDisplayValue ?? '未设置'} · ${field.fallbackSourceLabel ?? '未设置'})`,
|
|
2318
|
+
})),
|
|
2319
|
+
}),
|
|
2320
|
+
}] : []),
|
|
2210
2321
|
];
|
|
2211
2322
|
actions = [...tabActions, ...operationActions];
|
|
2212
2323
|
const effectiveConfigFocus = Math.min(focus, Math.max(0, actions.length - 1));
|
|
@@ -2226,6 +2337,32 @@ export function ConsoleAppV4(props) {
|
|
|
2226
2337
|
: null] });
|
|
2227
2338
|
}
|
|
2228
2339
|
}
|
|
2340
|
+
else if (route.name === 'configFieldAction' && plugin && activeField) {
|
|
2341
|
+
const layer = configLayerLabel(route.layer);
|
|
2342
|
+
breadcrumb = `${plugin.displayName} / 设置 / ${layer} / ${activeField.title}`;
|
|
2343
|
+
title = activeField.title;
|
|
2344
|
+
description = `这个字段在${layer}中已经有值。`;
|
|
2345
|
+
help = '↑↓ 移动 · Enter 选择 · Esc 返回';
|
|
2346
|
+
const deleteLabel = route.layer.scope === 'user'
|
|
2347
|
+
? '删除个人默认中的值'
|
|
2348
|
+
: route.layer.projectLayer === 'local' ? '删除本机设置中的值' : '删除当前项目中的值';
|
|
2349
|
+
actions = [
|
|
2350
|
+
{
|
|
2351
|
+
label: '修改值…',
|
|
2352
|
+
run: () => go({
|
|
2353
|
+
name: 'configFieldEditor',
|
|
2354
|
+
pluginId: plugin.pluginId,
|
|
2355
|
+
layer: route.layer,
|
|
2356
|
+
fieldKey: activeField.key,
|
|
2357
|
+
editor: fieldEditor(activeField),
|
|
2358
|
+
}),
|
|
2359
|
+
},
|
|
2360
|
+
draftRemoves.includes(activeField.key)
|
|
2361
|
+
? { label: '撤销删除', run: () => { cancelDraftRemoval(activeField.key); back(); } }
|
|
2362
|
+
: { label: deleteLabel, status: 'error', run: () => { removeDraft(activeField.key); back(); } },
|
|
2363
|
+
];
|
|
2364
|
+
content = _jsxs(Box, { flexDirection: "column", children: [_jsxs(SectionCard, { children: [_jsx(StaticRow, { title: `${layer}中的值`, meta: currentFieldDisplay(activeField) }), _jsx(StaticRow, { title: "\u5F53\u524D\u5B9E\u9645\u751F\u6548", meta: `${effectiveFieldDisplay(activeField)} · 来自${activeField.effectiveSourceLabel}` }), _jsx(StaticRow, { title: "\u5220\u9664\u540E\u5C06\u6062\u590D", meta: `${activeField.fallbackDisplayValue ?? '未设置'} · 来自${activeField.fallbackSourceLabel ?? '未设置'}` })] }), _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: policy.mode === 'compact' })] });
|
|
2365
|
+
}
|
|
2229
2366
|
else if (route.name === 'configFieldEditor' && plugin && activeField) {
|
|
2230
2367
|
breadcrumb = `${plugin.displayName} / 设置 / ${activeField.title}`;
|
|
2231
2368
|
help = route.editor === 'enum' || route.editor === 'boolean'
|
|
@@ -2253,10 +2390,8 @@ export function ConsoleAppV4(props) {
|
|
|
2253
2390
|
? `允许范围:${activeField.min ?? '不限'}–${activeField.max ?? '不限'}${activeField.unit ? ` ${activeField.unit}` : ''}。`
|
|
2254
2391
|
: route.editor === 'path' ? `${activeField.type === 'file' ? '文件' : '目录'}路径会在保存前由现有 schema 路径验证。`
|
|
2255
2392
|
: route.editor === 'sensitive' ? '当前值不会回显;留空不会自动删除旧值。' : activeField.description ?? '';
|
|
2256
|
-
const visibleInput = route.editor === '
|
|
2257
|
-
|
|
2258
|
-
: route.editor === 'path' ? privatePathInput(inputValue) : inputValue;
|
|
2259
|
-
content = _jsx(InputCard, { focused: true, title: visibleInput || activeField.placeholder || ' ', description: inputError ?? (route.editor === 'sensitive' ? '输入已隐藏。' : route.editor === 'path' ? '已隐藏父目录;Backspace 仍会编辑原始输入。' : activeField.placeholder ?? '按 Enter 使用输入值。'), status: inputError ? 'error' : undefined });
|
|
2393
|
+
const visibleInput = route.editor === 'path' ? privatePathInput(inputValue) : inputValue;
|
|
2394
|
+
content = _jsx(InputCard, { focused: true, title: _jsx(InputDisplay, { value: visibleInput, sensitive: route.editor === 'sensitive', placeholder: activeField.placeholder, columns: Math.max(8, size.columns - 8) }), description: inputError ?? (route.editor === 'sensitive' ? '输入已隐藏。' : route.editor === 'path' ? '已隐藏父目录;Backspace 仍会编辑原始输入。' : activeField.placeholder ?? '按 Enter 使用输入值。'), status: inputError ? 'error' : undefined });
|
|
2260
2395
|
}
|
|
2261
2396
|
}
|
|
2262
2397
|
else if (route.name === 'configUnavailable' && plugin) {
|
|
@@ -2285,18 +2420,25 @@ export function ConsoleAppV4(props) {
|
|
|
2285
2420
|
actions = [
|
|
2286
2421
|
...props.controller.listSources().map((source) => {
|
|
2287
2422
|
const overview = props.controller.getSourceOverview(source.id);
|
|
2423
|
+
const generation = props.controller.getCatalogGeneration(source.id);
|
|
2288
2424
|
const health = overview.health?.state ?? source.state;
|
|
2289
|
-
const status =
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2425
|
+
const status = generation?.refreshState === 'checking'
|
|
2426
|
+
|| generation?.refreshState === 'downloading'
|
|
2427
|
+
|| generation?.refreshState === 'validating' ? '正在检查'
|
|
2428
|
+
: generation?.refreshState === 'immutableViolation' ? '发布异常'
|
|
2429
|
+
: generation?.candidate ? `可用更新 ${generation.candidate.catalogVersion}`
|
|
2430
|
+
: health === 'ready' ? '已从远端加载'
|
|
2431
|
+
: health === 'path' ? '本地目录'
|
|
2432
|
+
: health === 'checking' ? '正在检查'
|
|
2433
|
+
: health === 'cache' || health === 'degraded' ? '使用缓存' : '无法读取';
|
|
2293
2434
|
return {
|
|
2294
2435
|
label: `${source.id}${source.primary ? ' 主来源' : ''}`,
|
|
2295
2436
|
description: `${overview.detail?.type === 'path' ? '本地目录' : 'Git 仓库'} · ${source.count ?? 0} 个插件`,
|
|
2296
2437
|
meta: status,
|
|
2297
|
-
status: health === 'unavailable' ? 'error'
|
|
2298
|
-
:
|
|
2299
|
-
:
|
|
2438
|
+
status: generation?.refreshState === 'immutableViolation' || health === 'unavailable' ? 'error'
|
|
2439
|
+
: generation?.candidate ? 'warning'
|
|
2440
|
+
: health === 'cache' || health === 'degraded' ? 'warning'
|
|
2441
|
+
: source.primary ? 'success' : undefined,
|
|
2300
2442
|
run: () => go({ name: 'sourceDetail', sourceId: source.id }),
|
|
2301
2443
|
};
|
|
2302
2444
|
}),
|
|
@@ -2311,14 +2453,37 @@ export function ConsoleAppV4(props) {
|
|
|
2311
2453
|
const detail = overview.detail;
|
|
2312
2454
|
const state = overview.health?.state ?? overview.source?.state;
|
|
2313
2455
|
const diagnostic = sourceDiagnostic(route.sourceId, state, detail);
|
|
2456
|
+
const generation = props.controller.getCatalogGeneration(route.sourceId);
|
|
2457
|
+
const sessionCatalogVersion = props.controller.getSessionCatalogVersion(route.sourceId)
|
|
2458
|
+
?? generation?.active?.catalogVersion;
|
|
2314
2459
|
breadcrumb = `插件来源 / ${route.sourceId}`;
|
|
2315
|
-
context = detail?.type === 'path' ? '本地目录'
|
|
2460
|
+
context = detail?.type === 'path' ? '本地目录'
|
|
2461
|
+
: detail?.freshness === 'remote' ? 'Git · 已连接'
|
|
2462
|
+
: detail?.freshness === 'cache' ? 'Git · 使用缓存' : 'Git';
|
|
2316
2463
|
title = route.sourceId;
|
|
2317
|
-
description = diagnostic ? '' : '来源状态可用。';
|
|
2464
|
+
description = diagnostic || generation ? '' : '来源状态可用。';
|
|
2318
2465
|
help = '↑↓ 移动 · Enter 选择 · r 重新检查 · Esc 返回';
|
|
2466
|
+
const openRefresh = () => {
|
|
2467
|
+
go({ name: 'catalogRefresh', sourceId: route.sourceId });
|
|
2468
|
+
void props.controller.refreshSource(route.sourceId);
|
|
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
|
+
];
|
|
2319
2483
|
actions = diagnostic
|
|
2320
2484
|
? [
|
|
2321
|
-
|
|
2485
|
+
...generationActions,
|
|
2486
|
+
{ label: '重新检查来源', description: '读取远端并验证可用 generation', run: openRefresh },
|
|
2322
2487
|
...(state === 'degraded' ? [{
|
|
2323
2488
|
label: '继续使用缓存',
|
|
2324
2489
|
description: '浏览匹配且已验证的缓存数据',
|
|
@@ -2330,16 +2495,105 @@ export function ConsoleAppV4(props) {
|
|
|
2330
2495
|
{ label: '技术详情', description: '查看脱敏错误代码和解析证据', run: () => go({ name: 'sourceTechnical', sourceId: route.sourceId }) },
|
|
2331
2496
|
]
|
|
2332
2497
|
: [
|
|
2333
|
-
|
|
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
|
+
}] : []),
|
|
2334
2506
|
{ label: '编辑来源…', description: 'ID 与类型创建后不可修改', run: () => go({ name: 'sourceEdit', sourceId: route.sourceId }) },
|
|
2335
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 }] }) },
|
|
2336
2508
|
{ label: '移除来源…', description: '移除来源配置', status: 'error', disabled: detail?.primary ? '主来源不能直接移除' : undefined, run: () => beginReview({ kind: 'sourceMutation', action: 'remove', sourceId: route.sourceId, changes: [{ title: `移除来源 ${route.sourceId}` }] }) },
|
|
2337
2509
|
{ label: '技术详情', description: '只读身份与解析证据', run: () => go({ name: 'sourceTechnical', sourceId: route.sourceId }) },
|
|
2338
2510
|
];
|
|
2339
|
-
const sourceActionViewport = actionViewport(actions, policy.mode === 'compact', focus, scrollOffset, responsiveBudget(2,
|
|
2511
|
+
const sourceActionViewport = actionViewport(actions, policy.mode === 'compact', focus, scrollOffset, responsiveBudget(2, 5));
|
|
2340
2512
|
content = _jsxs(Box, { flexDirection: "column", children: [diagnostic
|
|
2341
2513
|
? _jsx(DiagnosticSummary, { diagnostic: diagnostic, compact: policy.mode === 'compact' })
|
|
2342
|
-
: _jsxs(_Fragment, { children: [_jsx(
|
|
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 ?? '版本'}。`;
|
|
2579
|
+
actions = [
|
|
2580
|
+
{ label: '重新检查', description: '不可变性规则仍会生效', run: () => { props.controller.replace({ name: 'catalogRefresh', sourceId: route.sourceId }); void props.controller.refreshSource(route.sourceId); } },
|
|
2581
|
+
{ label: showTechnical ? '隐藏技术详情' : '技术详情', run: () => setShowTechnical((value) => !value) },
|
|
2582
|
+
{ label: '返回来源', run: back },
|
|
2583
|
+
];
|
|
2584
|
+
content = _jsxs(Box, { flexDirection: "column", children: [_jsxs(SectionCard, { title: "\u5F53\u524D\u5904\u7406", children: [_jsx(StaticRow, { title: `继续使用本地已验证的 ${generation?.active?.catalogVersion ?? 'Active'}`, status: "success" }), _jsx(StaticRow, { title: "\u4E0D\u52A0\u8F7D\u8FDC\u7AEF\u53D8\u5316", status: "error" }), _jsx(StaticRow, { title: "\u5DF2\u5B89\u88C5\u63D2\u4EF6\u548C\u8BBE\u7F6E\u4FDD\u6301\u4E0D\u53D8", status: "success" })] }), showTechnical ? _jsxs(TechnicalDetails, { children: [_jsx(StaticRow, { title: "code", meta: generation?.lastCheckCode ?? 'catalogImmutableVersionViolation' }), _jsx(StaticRow, { title: "source", meta: route.sourceId }), _jsx(StaticRow, { title: "digest", meta: generation?.active?.digestShort ?? '不可用' })] }) : null, _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: true })] });
|
|
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' })] });
|
|
2343
2597
|
}
|
|
2344
2598
|
else if (route.name === 'sourceTechnical') {
|
|
2345
2599
|
const overview = props.controller.getSourceOverview(route.sourceId);
|
|
@@ -2383,16 +2637,23 @@ export function ConsoleAppV4(props) {
|
|
|
2383
2637
|
content = _jsx(SemanticRows, { actions: actions, focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
2384
2638
|
}
|
|
2385
2639
|
else if (route.step === 'refPolicy') {
|
|
2386
|
-
title = '
|
|
2387
|
-
description = '
|
|
2640
|
+
title = '选择版本来源';
|
|
2641
|
+
description = 'Release 和 Beta 是固定 Git ref 的显示预设。';
|
|
2642
|
+
const useRefPreset = async (refPolicy, ref) => {
|
|
2643
|
+
const next = { ...sourceDraft, refPolicy, ref };
|
|
2644
|
+
setSourceDraft(next);
|
|
2645
|
+
if (next.mode === 'update')
|
|
2646
|
+
await beginSourceUpdateReview(next);
|
|
2647
|
+
else
|
|
2648
|
+
go({ name: 'sourceAdd', step: 'subdir', owner: route.owner });
|
|
2649
|
+
};
|
|
2388
2650
|
actions = [
|
|
2389
|
-
{ label: '跟随 AW
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
{ label: '固定 Git 引用', description: 'branch、tag 或 commit', run: () => { setSourceDraft({ ...sourceDraft, refPolicy: 'explicit' }); go({ name: 'sourceAdd', step: 'ref', owner: route.owner }); } },
|
|
2651
|
+
{ label: '跟随 AW CLI', description: `当前 CLI ${snapshot.cliChannel === 'beta' ? 'beta' : 'release'} → catalog/${snapshot.cliChannel === 'beta' ? 'beta' : 'latest'}`, selected: sourceDraft.refPolicy === 'cliChannel', run: () => { const policy = catalogRefPolicyForPreset('followCli'); return useRefPreset(policy.type, ''); } },
|
|
2652
|
+
{ label: 'Release', description: '固定读取 catalog/latest', selected: sourceDraft.refPolicy === 'explicit' && sourceDraft.ref === CATALOG_LATEST_REF, run: () => { const policy = catalogRefPolicyForPreset('release'); return useRefPreset(policy.type, policy.type === 'explicit' ? policy.ref : ''); } },
|
|
2653
|
+
{ label: 'Beta', description: '固定读取 catalog/beta', selected: sourceDraft.refPolicy === 'explicit' && sourceDraft.ref === CATALOG_BETA_REF, run: () => { const policy = catalogRefPolicyForPreset('beta'); return useRefPreset(policy.type, policy.type === 'explicit' ? policy.ref : ''); } },
|
|
2654
|
+
{ label: '指定 Git ref…', description: 'branch、tag、完整 ref 或 commit', selected: sourceDraft.refPolicy === 'explicit' && sourceDraft.ref !== CATALOG_LATEST_REF && sourceDraft.ref !== CATALOG_BETA_REF, run: () => { setSourceDraft({ ...sourceDraft, refPolicy: 'explicit' }); go({ name: 'sourceAdd', step: 'ref', owner: route.owner }); } },
|
|
2394
2655
|
];
|
|
2395
|
-
content = _jsx(SemanticRows, { actions: actions, focus: focus, kind: "choice", compact: policy.mode === 'compact' });
|
|
2656
|
+
content = _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: tuiTheme.colors.muted, children: ["\u8DDF\u968F\u542B\u4E49\uFF1A\u5F53\u524D CLI ", snapshot.cliChannel === 'beta' ? 'beta → catalog/beta' : 'release → catalog/latest'] }), _jsx(SemanticRows, { actions: actions, focus: focus, kind: "choice", compact: policy.mode === 'compact' })] });
|
|
2396
2657
|
}
|
|
2397
2658
|
else {
|
|
2398
2659
|
title = route.step === 'id' ? '输入来源 ID' : route.step === 'location' ? `输入 ${sourceDraft.type === 'git' ? 'Git URL' : '绝对路径'}` : route.step === 'ref' ? '输入固定 Git 引用' : '输入 Catalog 子目录';
|
|
@@ -2402,7 +2663,7 @@ export function ConsoleAppV4(props) {
|
|
|
2402
2663
|
: route.step === 'location' && sourceDraft.type === 'path'
|
|
2403
2664
|
? privatePathInput(sourceInput)
|
|
2404
2665
|
: sourceInput;
|
|
2405
|
-
content = _jsx(InputCard, { focused: true, title: displayedInput
|
|
2666
|
+
content = _jsx(InputCard, { focused: true, title: _jsx(InputDisplay, { value: displayedInput, columns: Math.max(8, size.columns - 8) }), description: sourceInputError ?? (route.step === 'location' && sourceDraft.type === 'path' ? '已隐藏父目录;Backspace 仍会编辑原始输入。' : '按 Enter 继续。'), status: sourceInputError ? 'error' : undefined });
|
|
2406
2667
|
}
|
|
2407
2668
|
}
|
|
2408
2669
|
else if (route.name === 'sourceEdit') {
|
|
@@ -2418,12 +2679,35 @@ export function ConsoleAppV4(props) {
|
|
|
2418
2679
|
setDirty(true);
|
|
2419
2680
|
go({ name: 'sourceAdd', step: field === 'location' ? 'location' : field === 'subdir' ? 'subdir' : 'refPolicy', owner });
|
|
2420
2681
|
};
|
|
2682
|
+
const switchOfficialTransport = (location) => {
|
|
2683
|
+
if (!detail || detail.type !== 'git'
|
|
2684
|
+
|| detail.locationSummary === projectCatalogSourceLocation(location))
|
|
2685
|
+
return;
|
|
2686
|
+
const owner = `source-update:${route.sourceId}:location:${Date.now()}`;
|
|
2687
|
+
const next = {
|
|
2688
|
+
owner,
|
|
2689
|
+
mode: 'update',
|
|
2690
|
+
sourceId: route.sourceId,
|
|
2691
|
+
type: 'git',
|
|
2692
|
+
location,
|
|
2693
|
+
refPolicy: detail.refPolicy ?? 'cliChannel',
|
|
2694
|
+
ref: detail.explicitRef ?? '',
|
|
2695
|
+
subdir: detail.subdir ?? '',
|
|
2696
|
+
editField: 'location',
|
|
2697
|
+
};
|
|
2698
|
+
setSourceDraft(next);
|
|
2699
|
+
setDirty(true);
|
|
2700
|
+
void beginSourceUpdateReview(next);
|
|
2701
|
+
};
|
|
2421
2702
|
actions = detail?.type === 'git' ? [
|
|
2422
|
-
|
|
2703
|
+
...(route.sourceId === 'official' ? [
|
|
2704
|
+
{ label: 'HTTPS', description: '使用系统 Git credential helper', selected: detail.locationSummary === projectCatalogSourceLocation(OFFICIAL_CATALOG_SOURCE_URL), run: () => switchOfficialTransport(OFFICIAL_CATALOG_SOURCE_URL) },
|
|
2705
|
+
{ label: 'SSH', description: '使用本机 SSH key;Git 连接使用 BatchMode', selected: detail.locationSummary === projectCatalogSourceLocation(OFFICIAL_CATALOG_SOURCE_SSH_URL), run: () => switchOfficialTransport(OFFICIAL_CATALOG_SOURCE_SSH_URL) },
|
|
2706
|
+
] : [{ label: 'Git URL', description: detail.locationSummary, run: () => startEdit('location') }]),
|
|
2423
2707
|
{ label: '版本引用', description: detail.refPolicy === 'explicit' ? `固定:${detail.explicitRef}` : '跟随 AW 版本通道', run: () => startEdit('refPolicy') },
|
|
2424
2708
|
{ label: 'Catalog 子目录', description: detail.subdir ?? '未设置', run: () => startEdit('subdir') },
|
|
2425
2709
|
] : [{ label: '本地目录', description: '已选择本地目录', run: () => startEdit('location') }];
|
|
2426
|
-
content = _jsx(SemanticRows, { actions: actions, focus: focus, kind: "section", compact: policy.mode === 'compact' });
|
|
2710
|
+
content = _jsxs(Box, { flexDirection: "column", children: [_jsx(SemanticRows, { actions: actions, focus: focus, kind: "section", compact: policy.mode === 'compact' }), route.sourceId === 'official' && detail?.type === 'git' ? _jsxs(SectionCard, { title: "\u6765\u6E90\u8EAB\u4EFD", children: [_jsx(StaticRow, { title: "\u903B\u8F91 Catalog", meta: "lesliechan721-arch/agent-workflow" }), _jsx(StaticRow, { title: "source identity", meta: "HTTPS / SSH \u4FDD\u6301\u4E00\u81F4" }), _jsx(StaticRow, { title: "\u660E\u6587 HTTP", meta: "\u4E0D\u652F\u6301", status: "warning" })] }) : null] });
|
|
2427
2711
|
}
|
|
2428
2712
|
else if (route.name === 'sourceRemoveBlocked') {
|
|
2429
2713
|
breadcrumb = `插件来源 / ${route.sourceId} / 移除`;
|
|
@@ -2453,9 +2737,9 @@ export function ConsoleAppV4(props) {
|
|
|
2453
2737
|
label: entry.category.startsWith('dependency')
|
|
2454
2738
|
? `${props.controller.getPluginOverview(entry.pluginId ?? '')?.displayName ?? entry.pluginId ?? entry.title}${entry.platform ? ` · ${platformLabel(entry.platform)}` : ''}`
|
|
2455
2739
|
: entry.title,
|
|
2456
|
-
description: entry.category.startsWith('dependency')
|
|
2740
|
+
description: `${issueGroupLabel(entry.group)} · ${entry.category.startsWith('dependency')
|
|
2457
2741
|
? `${props.controller.getPluginOverview(entry.dependencyPluginId ?? '')?.displayName ?? entry.dependencyPluginId ?? entry.explanation} · ${entry.impact[0] ?? ''}`
|
|
2458
|
-
: `${entry.explanation} · ${entry.impact[0] ?? ''}`,
|
|
2742
|
+
: `${entry.explanation} · ${entry.impact[0] ?? ''}`}`,
|
|
2459
2743
|
status: entry.category === 'sourceDegraded' ? 'warning' : 'error',
|
|
2460
2744
|
run: () => entry.category === 'dependencyStillRequired' && entry.pluginId
|
|
2461
2745
|
? go({ name: 'pluginDependencies', pluginId: entry.pluginId, view: 'removeBlocked',
|
|
@@ -2595,12 +2879,9 @@ export function ConsoleAppV4(props) {
|
|
|
2595
2879
|
content = _jsxs(Box, { flexDirection: "column", children: [issueDiagnosticSummary, _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: policy.mode === 'compact' })] });
|
|
2596
2880
|
}
|
|
2597
2881
|
else {
|
|
2598
|
-
const
|
|
2599
|
-
? `aw cleanup ${issue.pluginId} --platform ${issue.platform} --scope ${issue.scope}`
|
|
2600
|
-
: undefined;
|
|
2601
|
-
const hasRecoveryEvidence = sourceMissingCleanup || issue.category === 'sourceIdentityChanged'
|
|
2882
|
+
const hasRecoveryEvidence = issue.category === 'sourceIdentityChanged'
|
|
2602
2883
|
|| issue.placements || issue.requiredFields;
|
|
2603
|
-
const recoveryRows = _jsxs(_Fragment, { children: [
|
|
2884
|
+
const recoveryRows = _jsxs(_Fragment, { children: [issue.category === 'sourceIdentityChanged' ? _jsx(StaticRow, { title: "\u6765\u6E90\u8EAB\u4EFD\u5DF2\u53D8\u5316\uFF1B\u8BF7\u786E\u8BA4\u53D8\u66F4\u6216\u6062\u590D\u539F\u6765\u6E90\u3002", status: "warning", compact: true }) : null, issue.placements ? _jsx(StaticRow, { title: "\u4F4D\u7F6E", meta: issue.placements.map(scopeLabel).join('、'), compact: true }) : null, issue.requiredFields ? _jsx(StaticRow, { title: "\u5B57\u6BB5", meta: sanitizeDiagnosticText(issue.requiredFields.map((field) => field.title).join('、')), compact: true }) : null] });
|
|
2604
2885
|
content = _jsxs(Box, { flexDirection: "column", children: [issueDiagnosticSummary, !showTechnical && hasRecoveryEvidence
|
|
2605
2886
|
? policy.mode === 'compact' ? recoveryRows : _jsx(SectionCard, { title: "\u6062\u590D\u8BC1\u636E", children: recoveryRows })
|
|
2606
2887
|
: null, _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: policy.mode === 'compact', offset: issueActionViewport.offset, limit: issueActionViewport.limit })] });
|
|
@@ -2610,11 +2891,13 @@ export function ConsoleAppV4(props) {
|
|
|
2610
2891
|
const preparation = snapshot.reviewPreparation;
|
|
2611
2892
|
const labels = preparation.intent.kind === 'portableInstall'
|
|
2612
2893
|
? ['通用 Skills / 安装', '正在准备通用 Skills 安装确认']
|
|
2613
|
-
: preparation.intent.kind === '
|
|
2614
|
-
? ['
|
|
2615
|
-
: preparation.intent.kind === '
|
|
2616
|
-
? ['
|
|
2617
|
-
:
|
|
2894
|
+
: preparation.intent.kind === 'catalogActivate'
|
|
2895
|
+
? ['插件来源 / Catalog 更新', '正在准备 Catalog 激活确认']
|
|
2896
|
+
: preparation.intent.kind === 'configSave' || preparation.intent.kind === 'configReset'
|
|
2897
|
+
? ['设置', '正在准备设置确认']
|
|
2898
|
+
: preparation.intent.kind === 'sourceMutation'
|
|
2899
|
+
? ['插件来源', '正在准备来源变更确认']
|
|
2900
|
+
: ['插件操作', '正在准备插件操作确认'];
|
|
2618
2901
|
breadcrumb = `${labels[0]} / 准备确认`;
|
|
2619
2902
|
context = '只读';
|
|
2620
2903
|
title = preparation.state === 'failed' ? '无法准备确认信息' : labels[1];
|
|
@@ -2664,15 +2947,18 @@ export function ConsoleAppV4(props) {
|
|
|
2664
2947
|
const groupTitle = {
|
|
2665
2948
|
requested: review.operationKind === 'portableInstall' ? '已选择 Skills · 当前插件' : '你选择的插件',
|
|
2666
2949
|
dependencies: review.operationKind === 'portableInstall' ? '已选择 Skills · 来自依赖插件' : '必需依赖',
|
|
2950
|
+
runtime: 'Codex runtime',
|
|
2667
2951
|
portableTarget: '安装目标',
|
|
2668
2952
|
portableInputs: '准备内容',
|
|
2669
2953
|
portableWarnings: '覆盖冲突',
|
|
2954
|
+
configChanges: '设置变更',
|
|
2955
|
+
configImpact: '应用影响',
|
|
2670
2956
|
preserved: '保持不变',
|
|
2671
2957
|
};
|
|
2672
2958
|
const changeStatus = (change) => change.kind === 'remove' ? 'error'
|
|
2673
2959
|
: change.kind === 'warning' ? 'warning'
|
|
2674
2960
|
: change.kind === 'keep' || change.kind === 'add' ? 'success' : undefined;
|
|
2675
|
-
const groupOrder = ['portableWarnings', 'portableTarget', 'requested', 'dependencies', 'preserved', 'portableInputs'];
|
|
2961
|
+
const groupOrder = ['portableWarnings', 'portableTarget', 'configChanges', 'configImpact', 'requested', 'dependencies', 'runtime', 'preserved', 'portableInputs'];
|
|
2676
2962
|
const groupedSpecs = groupedChanges
|
|
2677
2963
|
? groupOrder.map((group) => ({
|
|
2678
2964
|
key: group,
|
|
@@ -2707,7 +2993,8 @@ export function ConsoleAppV4(props) {
|
|
|
2707
2993
|
const hiddenCount = group.changes.length - visibleCount;
|
|
2708
2994
|
return _jsxs(Box, { flexDirection: "column", children: [policy.mode !== 'compact' && group.label ? _jsx(Text, { bold: true, color: tuiTheme.colors.muted, children: group.label }) : null, group.changes.slice(0, visibleCount).map((change, index) => {
|
|
2709
2995
|
const retainDescription = change.kind === 'warning' || group.key === 'portableTarget'
|
|
2710
|
-
|| group.key === 'requested' || group.key === 'dependencies'
|
|
2996
|
+
|| group.key === 'requested' || group.key === 'dependencies'
|
|
2997
|
+
|| group.key === 'configChanges' || group.key === 'configImpact';
|
|
2711
2998
|
const description = retainDescription ? change.description : undefined;
|
|
2712
2999
|
const compactGroupLabel = group.key === 'requested' ? '根插件'
|
|
2713
3000
|
: group.key === 'dependencies' ? '依赖'
|
|
@@ -2737,17 +3024,18 @@ export function ConsoleAppV4(props) {
|
|
|
2737
3024
|
return _jsx(ReviewChangeRow, { title: `${category ? `${category} · ` : ''}${reviewSymbol(change)} ${change.title}${change.description ? ` · ${change.description}` : ''}`, meta: index === visibleTechnicalChanges.length - 1 && hiddenTechnicalChanges > 0
|
|
2738
3025
|
? `另有 ${hiddenTechnicalChanges} 项` : undefined, status: changeStatus(change), compact: true }, `${change.title}:${index}`);
|
|
2739
3026
|
});
|
|
2740
|
-
content = _jsx(Box, { flexDirection: "column", children: _jsxs(ReviewCard, { title: review.subject.name, meta: `${review.subject.sourceLabel} ${review.subject.version ?? ''}`, description: review.equivalentCommand ? review.description : undefined, children: [review.equivalentCommand ? _jsxs(Text, { children: ["\u7B49\u4EF7\u547D\u4EE4\uFF1A", review.equivalentCommand] }) : null, showTechnical ? technicalChanges : changeGroups, _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: true }), policy.mode === 'compact' || 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] }) });
|
|
3027
|
+
content = _jsx(Box, { flexDirection: "column", children: _jsxs(ReviewCard, { title: review.subject.name, meta: `${review.subject.sourceLabel ?? ''} ${review.subject.version ?? ''}`, description: review.equivalentCommand ? review.description : undefined, children: [review.equivalentCommand ? _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, showTechnical ? technicalChanges : changeGroups, _jsx(SemanticRows, { actions: actions, focus: focus, kind: "action", compact: true }), policy.mode === 'compact' || 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] }) });
|
|
2741
3028
|
}
|
|
2742
3029
|
else if (route.name === 'progress') {
|
|
3030
|
+
const catalogActivation = snapshot.activeReview?.operationKind === 'catalogActivate';
|
|
2743
3031
|
const portableOperation = snapshot.activeReview?.operationKind === 'portableInstall';
|
|
2744
3032
|
const configOperation = snapshot.activeReview?.operationKind === 'configSave'
|
|
2745
3033
|
|| snapshot.activeReview?.operationKind === 'configReset';
|
|
2746
3034
|
const sourceOperation = snapshot.activeReview?.operationKind === 'sourceMutation';
|
|
2747
3035
|
const issueOperation = snapshot.activeReview?.originIssue;
|
|
2748
|
-
breadcrumb = portableOperation ? '通用 Skills / 进度' : issueOperation ? '需要处理 / 进度' : sourceOperation ? '插件来源 / 保存' : configOperation ? '设置 / 进度' : '插件操作 / 进度';
|
|
2749
|
-
title = portableOperation ? '正在安装通用 Skills' : issueOperation ? '正在处理问题' : sourceOperation ? '正在保存并刷新来源' : configOperation ? '正在保存并应用设置' : '正在执行插件操作';
|
|
2750
|
-
description = issueOperation ? '完成后会使用新的状态 generation 重新检查问题。' : sourceOperation ? '先原子保存来源配置,再尽力刷新。刷新失败时配置仍保留并显示警告。' : configOperation ? '先保存所选层,再重新应用当前可见安装位置。' : '请勿关闭当前终端。';
|
|
3036
|
+
breadcrumb = catalogActivation ? '插件来源 / Catalog 更新' : portableOperation ? '通用 Skills / 进度' : issueOperation ? '需要处理 / 进度' : sourceOperation ? '插件来源 / 保存' : configOperation ? '设置 / 进度' : '插件操作 / 进度';
|
|
3037
|
+
title = catalogActivation ? '正在激活已验证的 Catalog generation' : portableOperation ? '正在安装通用 Skills' : issueOperation ? '正在处理问题' : sourceOperation ? '正在保存并刷新来源' : configOperation ? '正在保存并应用设置' : '正在执行插件操作';
|
|
3038
|
+
description = catalogActivation ? '不会重新下载;完成后重新加载插件列表和依赖关系。' : issueOperation ? '完成后会使用新的状态 generation 重新检查问题。' : sourceOperation ? '先原子保存来源配置,再尽力刷新。刷新失败时配置仍保留并显示警告。' : configOperation ? '先保存所选层,再重新应用当前可见安装位置。' : '请勿关闭当前终端。';
|
|
2751
3039
|
help = 'Ctrl-C 完成后退出';
|
|
2752
3040
|
const progress = snapshot.progress;
|
|
2753
3041
|
const elapsedSeconds = Math.max(0, Math.floor(((progress.elapsedMs
|
|
@@ -2867,6 +3155,7 @@ export function ConsoleAppV4(props) {
|
|
|
2867
3155
|
: result.state === 'blocked' ? result.summary : undefined;
|
|
2868
3156
|
const action = resultSummary?.action;
|
|
2869
3157
|
const operationKind = 'operationKind' in result ? result.operationKind : undefined;
|
|
3158
|
+
const catalogActivation = operationKind === 'catalogActivate';
|
|
2870
3159
|
const portableOperation = operationKind === 'portableInstall';
|
|
2871
3160
|
const portableReceipt = result.state === 'succeeded' || result.state === 'partial'
|
|
2872
3161
|
? result.summary.portable : undefined;
|
|
@@ -2887,22 +3176,25 @@ export function ConsoleAppV4(props) {
|
|
|
2887
3176
|
uninstall: '✓ 插件移除完成',
|
|
2888
3177
|
cleanup: '✓ 插件清理完成',
|
|
2889
3178
|
}[action ?? 'install'];
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
:
|
|
2894
|
-
? '×
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
:
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
:
|
|
3179
|
+
breadcrumb = catalogActivation ? '插件来源 / Catalog 更新 / 结果' : breadcrumb;
|
|
3180
|
+
title = catalogActivation
|
|
3181
|
+
? blocked ? '× Catalog 更新未启用' : '✓ Catalog 更新已启用'
|
|
3182
|
+
: portableOperation
|
|
3183
|
+
? blocked ? '× 通用 Skills 安装被阻止'
|
|
3184
|
+
: partial ? '! 通用 Skills 结果未完全完成' : '✓ 通用 Skills 已安装'
|
|
3185
|
+
: blocked && result.writeMayHaveCompleted
|
|
3186
|
+
? '× 写入结果未确认'
|
|
3187
|
+
: issueOperation
|
|
3188
|
+
? blocked || partial ? '× 问题仍未解决' : '✓ 问题已处理'
|
|
3189
|
+
: sourceOperation
|
|
3190
|
+
? blocked ? '× 来源操作未完成' : sourceRefreshWarning ? '! 来源配置已保存,但刷新失败' : '✓ 来源操作完成'
|
|
3191
|
+
: configOperation
|
|
3192
|
+
? blocked
|
|
3193
|
+
? '× 设置未确认保存'
|
|
3194
|
+
: partial ? '! 设置已保存,但部分应用失败' : '✓ 设置已保存并应用'
|
|
3195
|
+
: partial ? '! 插件操作只完成了一部分'
|
|
3196
|
+
: blocked ? result.code === 'operationFailed' ? '× 插件操作没有完成' : '× 插件操作未完成'
|
|
3197
|
+
: completedTitle;
|
|
2906
3198
|
description = portableOperation
|
|
2907
3199
|
? blocked
|
|
2908
3200
|
? result.code === 'operationReviewExpired' || result.code === 'reviewTicketExpired'
|
|
@@ -3326,7 +3618,7 @@ export function ConsoleAppV4(props) {
|
|
|
3326
3618
|
return;
|
|
3327
3619
|
}
|
|
3328
3620
|
if (key.backspace || key.delete)
|
|
3329
|
-
setPortableAgentInput(
|
|
3621
|
+
setPortableAgentInput(removeLastGrapheme);
|
|
3330
3622
|
else if (input && !key.ctrl && !key.meta && input >= ' ')
|
|
3331
3623
|
setPortableAgentInput((value) => value + input);
|
|
3332
3624
|
setInputError(undefined);
|
|
@@ -3413,7 +3705,7 @@ export function ConsoleAppV4(props) {
|
|
|
3413
3705
|
return;
|
|
3414
3706
|
}
|
|
3415
3707
|
if (key.backspace || key.delete)
|
|
3416
|
-
setSourceInput(
|
|
3708
|
+
setSourceInput(removeLastGrapheme);
|
|
3417
3709
|
else if (input && !key.ctrl && !key.meta && input >= ' ')
|
|
3418
3710
|
setSourceInput((value) => value + input);
|
|
3419
3711
|
setSourceInputError(undefined);
|
|
@@ -3455,19 +3747,44 @@ export function ConsoleAppV4(props) {
|
|
|
3455
3747
|
return;
|
|
3456
3748
|
}
|
|
3457
3749
|
if (key.backspace || key.delete)
|
|
3458
|
-
setInputValue(
|
|
3750
|
+
setInputValue(removeLastGrapheme);
|
|
3459
3751
|
else if (input && !key.ctrl && !key.meta && input >= ' ')
|
|
3460
3752
|
setInputValue((value) => value + input);
|
|
3461
3753
|
setInputError(undefined);
|
|
3462
3754
|
return;
|
|
3463
3755
|
}
|
|
3464
|
-
if (
|
|
3756
|
+
if (searchFocus && route.name === 'pluginList') {
|
|
3465
3757
|
if (key.escape) {
|
|
3466
|
-
|
|
3758
|
+
setSearchFocus(false);
|
|
3759
|
+
return;
|
|
3760
|
+
}
|
|
3761
|
+
if (key.return) {
|
|
3762
|
+
setSearchFocus(false);
|
|
3763
|
+
const row = pluginRows[focus];
|
|
3764
|
+
if (row)
|
|
3765
|
+
go(route.mode === 'browse'
|
|
3766
|
+
? { name: 'pluginPreview', pluginId: row.pluginId }
|
|
3767
|
+
: { name: 'pluginDetail', pluginId: row.pluginId });
|
|
3768
|
+
return;
|
|
3769
|
+
}
|
|
3770
|
+
if (key.upArrow || key.downArrow) {
|
|
3771
|
+
setSearchFocus(false);
|
|
3772
|
+
setFocus((value) => moveIndex(pluginRows.length, value, key.upArrow ? -1 : 1));
|
|
3773
|
+
return;
|
|
3774
|
+
}
|
|
3775
|
+
if (key.leftArrow || key.rightArrow) {
|
|
3776
|
+
setSearchFocus(false);
|
|
3777
|
+
const tabs = ['all', ...props.controller.listSources().map((source) => source.id)];
|
|
3778
|
+
const current = route.sourceId ?? 'all';
|
|
3779
|
+
const direction = key.leftArrow ? -1 : 1;
|
|
3780
|
+
const next = tabs[(tabs.indexOf(current) + direction + tabs.length) % tabs.length];
|
|
3781
|
+
props.controller.replace({ name: 'pluginList', mode: route.mode, ...(next !== 'all' ? { sourceId: next } : {}) }, { ...snapshot.router.current.context, query, installFilter, sourceTabId: next });
|
|
3782
|
+
setFocus(0);
|
|
3783
|
+
setScrollOffset(0);
|
|
3467
3784
|
return;
|
|
3468
3785
|
}
|
|
3469
3786
|
if (key.backspace || key.delete)
|
|
3470
|
-
setQuery(
|
|
3787
|
+
setQuery(removeLastGrapheme);
|
|
3471
3788
|
else if (input && !key.ctrl && !key.meta && input >= ' ')
|
|
3472
3789
|
setQuery((value) => value + input);
|
|
3473
3790
|
setFocus(0);
|
|
@@ -3492,7 +3809,7 @@ export function ConsoleAppV4(props) {
|
|
|
3492
3809
|
setShowTechnical((value) => !value);
|
|
3493
3810
|
}
|
|
3494
3811
|
else if ((key.escape || input.toLowerCase() === 'b')
|
|
3495
|
-
&& route.name === 'configFieldEditor') {
|
|
3812
|
+
&& (route.name === 'configFieldEditor' || route.name === 'configFieldAction')) {
|
|
3496
3813
|
back();
|
|
3497
3814
|
}
|
|
3498
3815
|
else if (key.escape || input.toLowerCase() === 'b') {
|
|
@@ -3505,7 +3822,7 @@ export function ConsoleAppV4(props) {
|
|
|
3505
3822
|
back();
|
|
3506
3823
|
}
|
|
3507
3824
|
else if (route.name === 'pluginList' && input === '/') {
|
|
3508
|
-
|
|
3825
|
+
setSearchFocus(true);
|
|
3509
3826
|
}
|
|
3510
3827
|
else if (route.name === 'pluginList' && route.mode === 'browse' && input.toLowerCase() === 'f') {
|
|
3511
3828
|
const selectedPluginId = pluginRows[focus]?.pluginId;
|
|
@@ -3543,12 +3860,15 @@ export function ConsoleAppV4(props) {
|
|
|
3543
3860
|
setScrollOffset(0);
|
|
3544
3861
|
}
|
|
3545
3862
|
else if (input.toLowerCase() === 'r' && route.name === 'sourceDetail') {
|
|
3863
|
+
go({ name: 'catalogRefresh', sourceId: route.sourceId });
|
|
3546
3864
|
void props.controller.refreshSource(route.sourceId);
|
|
3547
3865
|
}
|
|
3548
3866
|
else if (input.toLowerCase() === 'r' && route.name === 'sourceList') {
|
|
3549
3867
|
const source = props.controller.listSources()[focus];
|
|
3550
|
-
if (source)
|
|
3868
|
+
if (source) {
|
|
3869
|
+
go({ name: 'catalogRefresh', sourceId: source.id });
|
|
3551
3870
|
void props.controller.refreshSource(source.id);
|
|
3871
|
+
}
|
|
3552
3872
|
}
|
|
3553
3873
|
else if (route.name === 'pluginList' && (key.leftArrow || key.rightArrow || input === '[' || input === ']')) {
|
|
3554
3874
|
const tabs = ['all', ...props.controller.listSources().map((source) => source.id)];
|