@lesliechan721/aw 0.1.0-beta.20 → 0.1.0-beta.22
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/src/commands/status-v6.js +49 -32
- package/dist/src/commands/status-v6.js.map +1 -1
- package/dist/src/tui/components.d.ts +1 -0
- package/dist/src/tui/components.js +3 -1
- package/dist/src/tui/components.js.map +1 -1
- package/dist/src/tui/console-app-v4.d.ts +1 -1
- package/dist/src/tui/console-app-v4.js +756 -1127
- package/dist/src/tui/console-app-v4.js.map +1 -1
- package/dist/src/tui/controller-runtime.js +65 -42
- package/dist/src/tui/controller-runtime.js.map +1 -1
- package/dist/src/tui/controller.d.ts +4 -30
- package/dist/src/tui/controller.js +7 -219
- package/dist/src/tui/controller.js.map +1 -1
- package/dist/src/tui/dependency-graph.d.ts +3 -3
- package/dist/src/tui/dependency-graph.js +15 -14
- package/dist/src/tui/dependency-graph.js.map +1 -1
- package/dist/src/tui/glossary.d.ts +1 -1
- package/dist/src/tui/glossary.js +1 -1
- package/dist/src/tui/glossary.js.map +1 -1
- package/dist/src/tui/model.d.ts +2 -0
- package/dist/src/tui/model.js +67 -30
- package/dist/src/tui/model.js.map +1 -1
- package/dist/src/tui/operation-review-planner.js +8 -195
- package/dist/src/tui/operation-review-planner.js.map +1 -1
- package/dist/src/tui/plugin-write-task.js +4 -0
- package/dist/src/tui/plugin-write-task.js.map +1 -1
- package/dist/src/tui/router.d.ts +4 -16
- package/dist/src/tui/router.js.map +1 -1
- package/dist/src/tui/screen-registry.d.ts +10 -57
- package/dist/src/tui/screen-registry.js +1 -15
- package/dist/src/tui/screen-registry.js.map +1 -1
- package/package.json +3 -3
- package/dist/src/tui/catalog-management-screens.d.ts +0 -45
- package/dist/src/tui/catalog-management-screens.js +0 -25
- package/dist/src/tui/catalog-management-screens.js.map +0 -1
- package/dist/src/tui/catalog-management.d.ts +0 -240
- package/dist/src/tui/catalog-management.js +0 -856
- package/dist/src/tui/catalog-management.js.map +0 -1
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type CatalogDevManagementViewModel, type CatalogManagementIntent, type CatalogManagementReviewEvidence, type CatalogManagementService, type CatalogPublicationManagementViewModel, type CatalogStoreManagementViewModel, type CatalogValidationViewModel, type CatalogWorkspaceManagementViewModel } from './catalog-management.js';
|
|
2
1
|
import type { CatalogActivationMode, CatalogSource, CatalogGenerationActiveV1, CatalogGenerationCandidateEvidence, CatalogGenerationSyncResult, CatalogSourceImpact, DependencyScopeOverride, PlatformName, Scope } from '../types.js';
|
|
3
2
|
import type { PortableReview } from '../portable/commands.js';
|
|
4
3
|
import type { CatalogSourceUpdate } from '../utils/catalog-sources.js';
|
|
@@ -18,9 +17,9 @@ import type { CatalogSourceFreshnessViewModel } from './catalog-freshness.js';
|
|
|
18
17
|
import type { CatalogSessionReusableCandidate } from './catalog-sources/types.js';
|
|
19
18
|
import { type PluginWriteTaskBlockedTarget, type PluginWriteTaskCandidate, type PluginWriteTaskCause, type PluginWriteTaskGoal, type PluginWriteTaskIntent, type PluginWriteTaskTarget } from './plugin-write-task.js';
|
|
20
19
|
export type { PluginWriteTaskBlockReason, PluginWriteTaskCandidate, PluginWriteTaskExpectedUpdate, PluginWriteTaskGoal, PluginWriteTaskIntent, PluginWriteTaskMethod, PluginWriteTaskTarget, } from './plugin-write-task.js';
|
|
21
|
-
type CatalogActivationBlockReason = 'configDraft' | 'sourceDraft' | 'batchDraft' | '
|
|
20
|
+
type CatalogActivationBlockReason = 'configDraft' | 'sourceDraft' | 'batchDraft' | 'portableDraft' | 'activeReview' | 'reviewPreparation' | 'writeProgress';
|
|
22
21
|
export interface ExternalDraftState {
|
|
23
|
-
kind: 'configDraft' | 'sourceDraft' | 'batchDraft'
|
|
22
|
+
kind: 'configDraft' | 'sourceDraft' | 'batchDraft';
|
|
24
23
|
owner: string;
|
|
25
24
|
flowId?: string;
|
|
26
25
|
revision: number;
|
|
@@ -219,7 +218,7 @@ export type OperationIntent = {
|
|
|
219
218
|
setPrimaryAfterActivation?: boolean;
|
|
220
219
|
} | {
|
|
221
220
|
kind: 'catalogSourcesRecovery';
|
|
222
|
-
}
|
|
221
|
+
};
|
|
223
222
|
export interface OperationEvidence {
|
|
224
223
|
catalog: {
|
|
225
224
|
configDigest: string;
|
|
@@ -311,7 +310,6 @@ export interface OperationEvidence {
|
|
|
311
310
|
}>['sourceMutation'];
|
|
312
311
|
setPrimaryAfterActivation?: boolean;
|
|
313
312
|
};
|
|
314
|
-
catalogManagement?: CatalogManagementReviewEvidence;
|
|
315
313
|
portable?: PortableReview;
|
|
316
314
|
}
|
|
317
315
|
export interface OperationReviewChange {
|
|
@@ -387,6 +385,7 @@ export interface ReviewPreparationSnapshot {
|
|
|
387
385
|
currentStage?: ReviewPreparationStageId;
|
|
388
386
|
code?: 'reviewPreparationFailed';
|
|
389
387
|
message?: string;
|
|
388
|
+
operationRecordId?: string;
|
|
390
389
|
}
|
|
391
390
|
export type OperationExecuteResult = {
|
|
392
391
|
state: 'succeeded';
|
|
@@ -455,24 +454,6 @@ export interface OperationResultSummary {
|
|
|
455
454
|
catalogAction?: Extract<OperationIntent, {
|
|
456
455
|
kind: 'catalogGeneration';
|
|
457
456
|
}>['action'];
|
|
458
|
-
catalogManagement?: {
|
|
459
|
-
action: CatalogManagementIntent['action'];
|
|
460
|
-
state: 'succeeded' | 'partial';
|
|
461
|
-
catalogVersion?: string;
|
|
462
|
-
planDigest?: string;
|
|
463
|
-
store?: {
|
|
464
|
-
deletedEntries: number;
|
|
465
|
-
deletedBytes: number;
|
|
466
|
-
retainedEntries: number;
|
|
467
|
-
};
|
|
468
|
-
publication?: {
|
|
469
|
-
catalogVersion: string;
|
|
470
|
-
planDigest: string;
|
|
471
|
-
state: 'prepared' | 'uncertain' | 'published';
|
|
472
|
-
remote: string;
|
|
473
|
-
branch: string;
|
|
474
|
-
};
|
|
475
|
-
};
|
|
476
457
|
catalogGeneration?: Pick<CatalogGenerationSyncResult, 'activeChanged' | 'outcome'> & {
|
|
477
458
|
catalogVersion: string;
|
|
478
459
|
};
|
|
@@ -603,7 +584,6 @@ export interface SourceReferenceSummaryViewModel {
|
|
|
603
584
|
}>;
|
|
604
585
|
}
|
|
605
586
|
export interface TuiControllerDependencies {
|
|
606
|
-
catalogManagement?: CatalogManagementService;
|
|
607
587
|
beginCatalogSession?: (options?: {
|
|
608
588
|
reuseValidatedGenerations?: boolean;
|
|
609
589
|
}) => void;
|
|
@@ -821,12 +801,6 @@ export declare class TuiController {
|
|
|
821
801
|
getConfigPage(pluginId: string, layer: {
|
|
822
802
|
scope: Scope | 'effective';
|
|
823
803
|
}, signal?: AbortSignal): Promise<ConfigPageViewModel>;
|
|
824
|
-
selectCatalogWorkspace(workspaceRoot?: string): Promise<CatalogWorkspaceManagementViewModel>;
|
|
825
|
-
getCatalogWorkspaceManagement(): Promise<CatalogWorkspaceManagementViewModel>;
|
|
826
|
-
validateCatalogWorkspace(): Promise<CatalogValidationViewModel>;
|
|
827
|
-
getCatalogDevManagement(): Promise<CatalogDevManagementViewModel>;
|
|
828
|
-
getCatalogStoreManagement(): Promise<CatalogStoreManagementViewModel>;
|
|
829
|
-
getCatalogPublicationManagement(): Promise<CatalogPublicationManagementViewModel>;
|
|
830
804
|
previewConfigSaveImpact(intent: Extract<OperationIntent, {
|
|
831
805
|
kind: 'configSave';
|
|
832
806
|
}>, signal?: AbortSignal): Promise<NonNullable<OperationEvidence['config']>>;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import crypto from 'node:crypto';
|
|
2
|
-
import { CatalogManagementError, } from './catalog-management.js';
|
|
3
2
|
import { CatalogGenerationError } from '../utils/catalog-generation-error.js';
|
|
4
3
|
import { readSafeOperationError } from '../utils/safe-operation-diagnostic.js';
|
|
5
4
|
import { flattenStatusTargets, statusTargetActivation, statusTargetIntent, statusTargetOwnershipState, statusTargetSharedNative, } from '../commands/status-v6.js';
|
|
@@ -139,13 +138,6 @@ function normalizeOperationIntent(intent) {
|
|
|
139
138
|
if (intent.kind === 'pluginWriteTask') {
|
|
140
139
|
return { ...intent, targets: canonicalPluginWriteTaskTargets(intent.targets) };
|
|
141
140
|
}
|
|
142
|
-
if (intent.kind === 'catalogManagement' && intent.action === 'storePrune') {
|
|
143
|
-
const items = [...new Map(intent.items.map((item) => [
|
|
144
|
-
`${item.category}\0${item.storeKey}`,
|
|
145
|
-
item,
|
|
146
|
-
])).values()].sort((left, right) => `${left.category}\0${left.storeKey}`.localeCompare(`${right.category}\0${right.storeKey}`, 'en'));
|
|
147
|
-
return { ...intent, items };
|
|
148
|
-
}
|
|
149
141
|
if (intent.kind !== 'pluginWriteBatch')
|
|
150
142
|
return intent;
|
|
151
143
|
if (intent.selection.kind === 'targets') {
|
|
@@ -360,12 +352,6 @@ export function pluginWriteTaskFailedRequestedTargets(execution) {
|
|
|
360
352
|
}));
|
|
361
353
|
}
|
|
362
354
|
function collectOperationSensitiveValues(intent) {
|
|
363
|
-
if (intent.kind === 'catalogManagement') {
|
|
364
|
-
return [
|
|
365
|
-
...('ownerUrl' in intent && intent.ownerUrl ? [intent.ownerUrl] : []),
|
|
366
|
-
...('remoteUrl' in intent && intent.remoteUrl ? [intent.remoteUrl] : []),
|
|
367
|
-
];
|
|
368
|
-
}
|
|
369
355
|
if (intent.kind !== 'configSave')
|
|
370
356
|
return [];
|
|
371
357
|
const sensitiveKeys = new Set([...(intent.sensitiveKeys ?? []), ...(intent.privateKeys ?? [])]);
|
|
@@ -413,22 +399,6 @@ function cloneFrozen(value) {
|
|
|
413
399
|
return deepFreeze(structuredClone(value));
|
|
414
400
|
}
|
|
415
401
|
export function operationEvidenceFingerprint(evidence) {
|
|
416
|
-
if (evidence.catalogManagement) {
|
|
417
|
-
const management = evidence.catalogManagement;
|
|
418
|
-
return crypto.createHash('sha256')
|
|
419
|
-
.update(JSON.stringify(stableValue(management.action === 'storePrune'
|
|
420
|
-
? {
|
|
421
|
-
action: management.action,
|
|
422
|
-
workspaceBinding: management.workspaceBinding,
|
|
423
|
-
authorizedStoreItems: management.authorizedStoreItems,
|
|
424
|
-
}
|
|
425
|
-
: {
|
|
426
|
-
action: management.action,
|
|
427
|
-
workspaceBinding: management.workspaceBinding,
|
|
428
|
-
evidenceDigest: management.evidenceDigest,
|
|
429
|
-
})))
|
|
430
|
-
.digest('hex');
|
|
431
|
-
}
|
|
432
402
|
if ('taskPlan' in evidence) {
|
|
433
403
|
const task = evidence.taskPlan;
|
|
434
404
|
return crypto.createHash('sha256')
|
|
@@ -566,8 +536,6 @@ function issueCode(error) {
|
|
|
566
536
|
return safeDiagnosticCode(safeOperationError.code, 'operationBlocked');
|
|
567
537
|
if (error instanceof TuiOperationBlockedError)
|
|
568
538
|
return error.code;
|
|
569
|
-
if (error instanceof CatalogManagementError)
|
|
570
|
-
return error.code;
|
|
571
539
|
if (error instanceof CatalogGenerationError)
|
|
572
540
|
return error.code;
|
|
573
541
|
if (error instanceof Error && error.name === 'CatalogSourcesConfigConflictError') {
|
|
@@ -1095,12 +1063,6 @@ export class TuiController {
|
|
|
1095
1063
|
}
|
|
1096
1064
|
#ensureOperationFlow(intent) {
|
|
1097
1065
|
const active = this.#router.activeFlow();
|
|
1098
|
-
if (intent.kind === 'catalogManagement') {
|
|
1099
|
-
if (active?.kind === 'catalogManagement')
|
|
1100
|
-
return;
|
|
1101
|
-
this.#router.beginFlow('catalogManagement', this.#router.snapshot.current.route);
|
|
1102
|
-
return;
|
|
1103
|
-
}
|
|
1104
1066
|
if (intent.kind === 'pluginWriteTask') {
|
|
1105
1067
|
if (active?.kind === 'pluginWriteTask')
|
|
1106
1068
|
return;
|
|
@@ -1193,17 +1155,6 @@ export class TuiController {
|
|
|
1193
1155
|
}
|
|
1194
1156
|
return this.#normalizeRoute({ name: 'sourceDetail', sourceId: intent.sourceId });
|
|
1195
1157
|
}
|
|
1196
|
-
if (intent.kind === 'catalogManagement') {
|
|
1197
|
-
if (intent.action === 'devActivate' || intent.action === 'devDeactivate') {
|
|
1198
|
-
return { name: 'catalogDev', step: 'overview' };
|
|
1199
|
-
}
|
|
1200
|
-
if (intent.action === 'storePrune')
|
|
1201
|
-
return { name: 'catalogStore' };
|
|
1202
|
-
if (intent.action === 'publishPlan' || intent.action === 'publishApply') {
|
|
1203
|
-
return { name: 'catalogPublish', step: 'overview' };
|
|
1204
|
-
}
|
|
1205
|
-
return { name: 'catalogWorkspace', view: 'overview' };
|
|
1206
|
-
}
|
|
1207
1158
|
return { name: 'sourceList' };
|
|
1208
1159
|
}
|
|
1209
1160
|
#showResult(result, intent) {
|
|
@@ -2011,8 +1962,10 @@ export class TuiController {
|
|
|
2011
1962
|
}
|
|
2012
1963
|
listPlugins(options) {
|
|
2013
1964
|
const query = options.query?.trim().toLocaleLowerCase('en');
|
|
1965
|
+
const catalogPluginIds = new Set(this.#status?.pluginSummaries.map((plugin) => plugin.pluginId));
|
|
2014
1966
|
return cloneFrozen((this.#viewModel?.plugins ?? []).filter((plugin) => (!options.sourceId || plugin.sourceId === options.sourceId)
|
|
2015
|
-
&& (options.mode === 'browse'
|
|
1967
|
+
&& (options.mode === 'browse' ? catalogPluginIds.has(plugin.pluginId)
|
|
1968
|
+
: hasInstalledPlacement(plugin) || plugin.savedConfigScopes.length > 0)
|
|
2016
1969
|
&& (options.installFilter !== 'uninstalled' || !hasInstalledPlacement(plugin))
|
|
2017
1970
|
&& (options.installFilter !== 'updateAvailable' || plugin.update?.state === 'available')
|
|
2018
1971
|
&& (!query || `${plugin.displayName}\n${plugin.description}\n${plugin.sourceId}`.toLocaleLowerCase('en').includes(query))));
|
|
@@ -2243,7 +2196,7 @@ export class TuiController {
|
|
|
2243
2196
|
return this.#catalogSourcesSession.fullValidate(sourceId);
|
|
2244
2197
|
}
|
|
2245
2198
|
setExternalDraftState(states = []) {
|
|
2246
|
-
const priority = { sourceDraft: 0, batchDraft: 1,
|
|
2199
|
+
const priority = { sourceDraft: 0, batchDraft: 1, configDraft: 2 };
|
|
2247
2200
|
this.#externalDrafts = structuredClone(states).sort((left, right) => priority[left.kind] - priority[right.kind] || left.owner.localeCompare(right.owner, 'en'));
|
|
2248
2201
|
this.#publish();
|
|
2249
2202
|
}
|
|
@@ -2411,48 +2364,6 @@ export class TuiController {
|
|
|
2411
2364
|
: this.#abort.signal;
|
|
2412
2365
|
return cloneFrozen(await this.#trackRead(this.dependencies.getConfigPage(pluginId, structuredClone(layer), combined)));
|
|
2413
2366
|
}
|
|
2414
|
-
async selectCatalogWorkspace(workspaceRoot) {
|
|
2415
|
-
this.#assertAcceptingActions();
|
|
2416
|
-
if (!this.dependencies.catalogManagement) {
|
|
2417
|
-
throw new TuiOperationBlockedError('catalogManagementUnavailable', 'Catalog management is unavailable.');
|
|
2418
|
-
}
|
|
2419
|
-
return cloneFrozen(await this.#trackRead(this.dependencies.catalogManagement.selectWorkspace(workspaceRoot)));
|
|
2420
|
-
}
|
|
2421
|
-
async getCatalogWorkspaceManagement() {
|
|
2422
|
-
this.#assertAcceptingActions();
|
|
2423
|
-
if (!this.dependencies.catalogManagement) {
|
|
2424
|
-
throw new TuiOperationBlockedError('catalogManagementUnavailable', 'Catalog management is unavailable.');
|
|
2425
|
-
}
|
|
2426
|
-
return cloneFrozen(await this.#trackRead(this.dependencies.catalogManagement.getWorkspace()));
|
|
2427
|
-
}
|
|
2428
|
-
async validateCatalogWorkspace() {
|
|
2429
|
-
this.#assertAcceptingActions();
|
|
2430
|
-
if (!this.dependencies.catalogManagement) {
|
|
2431
|
-
throw new TuiOperationBlockedError('catalogManagementUnavailable', 'Catalog management is unavailable.');
|
|
2432
|
-
}
|
|
2433
|
-
return cloneFrozen(await this.#trackRead(this.dependencies.catalogManagement.validateWorkspace()));
|
|
2434
|
-
}
|
|
2435
|
-
async getCatalogDevManagement() {
|
|
2436
|
-
this.#assertAcceptingActions();
|
|
2437
|
-
if (!this.dependencies.catalogManagement) {
|
|
2438
|
-
throw new TuiOperationBlockedError('catalogManagementUnavailable', 'Catalog management is unavailable.');
|
|
2439
|
-
}
|
|
2440
|
-
return cloneFrozen(await this.#trackRead(this.dependencies.catalogManagement.getDev()));
|
|
2441
|
-
}
|
|
2442
|
-
async getCatalogStoreManagement() {
|
|
2443
|
-
this.#assertAcceptingActions();
|
|
2444
|
-
if (!this.dependencies.catalogManagement) {
|
|
2445
|
-
throw new TuiOperationBlockedError('catalogManagementUnavailable', 'Catalog management is unavailable.');
|
|
2446
|
-
}
|
|
2447
|
-
return cloneFrozen(await this.#trackRead(this.dependencies.catalogManagement.getStore()));
|
|
2448
|
-
}
|
|
2449
|
-
async getCatalogPublicationManagement() {
|
|
2450
|
-
this.#assertAcceptingActions();
|
|
2451
|
-
if (!this.dependencies.catalogManagement) {
|
|
2452
|
-
throw new TuiOperationBlockedError('catalogManagementUnavailable', 'Catalog management is unavailable.');
|
|
2453
|
-
}
|
|
2454
|
-
return cloneFrozen(await this.#trackRead(this.dependencies.catalogManagement.getPublication()));
|
|
2455
|
-
}
|
|
2456
2367
|
async previewConfigSaveImpact(intent, signal) {
|
|
2457
2368
|
this.#assertAcceptingActions();
|
|
2458
2369
|
const normalized = normalizeOperationIntent(intent);
|
|
@@ -2492,6 +2403,8 @@ export class TuiController {
|
|
|
2492
2403
|
catch (error) {
|
|
2493
2404
|
const code = issueCode(error);
|
|
2494
2405
|
await this.#logOperationError(error, code, intent);
|
|
2406
|
+
if (error instanceof TuiOperationBlockedError && error.diagnostics?.length)
|
|
2407
|
+
throw error;
|
|
2495
2408
|
throw new TuiOperationBlockedError(code, code === 'catalogGenerationUnavailable'
|
|
2496
2409
|
? '本次加载时 Catalog 来源不可用。请刷新来源并重新加载后重试。'
|
|
2497
2410
|
: '操作未建立。请检查当前设置后重试。');
|
|
@@ -2564,23 +2477,6 @@ export class TuiController {
|
|
|
2564
2477
|
return this.startReviewPreparation(structuredClone(intent), preparation.returnRoute);
|
|
2565
2478
|
}
|
|
2566
2479
|
#validateReviewIntent(intent) {
|
|
2567
|
-
if (intent.kind === 'catalogManagement') {
|
|
2568
|
-
if (intent.action === 'storePrune' && intent.items.length === 0) {
|
|
2569
|
-
throw new TuiOperationBlockedError('catalogStoreSelectionInvalid', 'Select at least one reclaimable Catalog store item.');
|
|
2570
|
-
}
|
|
2571
|
-
if (intent.action === 'workspaceVersion'
|
|
2572
|
-
&& (intent.version === undefined) === (intent.bump === undefined)) {
|
|
2573
|
-
throw new TuiOperationBlockedError('catalogVersionSelectionInvalid', 'Select exactly one Catalog version or bump level.');
|
|
2574
|
-
}
|
|
2575
|
-
if ((intent.action === 'publishPlan' || intent.action === 'publishApply')
|
|
2576
|
-
&& intent.remote !== undefined && intent.remoteUrl !== undefined) {
|
|
2577
|
-
throw new TuiOperationBlockedError('catalogPublicationTargetInvalid', 'Select a Git remote name or one direct remote URL.');
|
|
2578
|
-
}
|
|
2579
|
-
if (intent.action === 'publishApply'
|
|
2580
|
-
&& !/^sha256:[0-9a-f]{64}$/u.test(intent.expectedPlanDigest)) {
|
|
2581
|
-
throw new TuiOperationBlockedError('catalogPublicationPlanInvalid', 'Select an exact prepared Catalog publication plan.');
|
|
2582
|
-
}
|
|
2583
|
-
}
|
|
2584
2480
|
if (intent.kind === 'pluginWriteTask') {
|
|
2585
2481
|
if (intent.targets.length === 0
|
|
2586
2482
|
|| JSON.stringify(intent.targets) !== JSON.stringify(canonicalPluginWriteTaskTargets(intent.targets))) {
|
|
@@ -2615,8 +2511,6 @@ export class TuiController {
|
|
|
2615
2511
|
}
|
|
2616
2512
|
}
|
|
2617
2513
|
#reviewPreparationLabel(intent) {
|
|
2618
|
-
if (intent.kind === 'catalogManagement')
|
|
2619
|
-
return 'Catalog 管理';
|
|
2620
2514
|
if (intent.kind === 'catalogSourcesRecovery')
|
|
2621
2515
|
return 'Catalog 来源配置';
|
|
2622
2516
|
if (intent.kind === 'pluginWriteTask')
|
|
@@ -2714,6 +2608,7 @@ export class TuiController {
|
|
|
2714
2608
|
? '本次加载时 Catalog 来源不可用。请刷新来源并重新加载后重试。'
|
|
2715
2609
|
: '无法准备确认信息。请返回检查选择,或重试。';
|
|
2716
2610
|
const preparationRecordId = `${this.#sessionEpoch}:${active.snapshot.id}`;
|
|
2611
|
+
active.snapshot.operationRecordId = preparationRecordId;
|
|
2717
2612
|
const carriedDiagnostics = error instanceof TuiOperationBlockedError
|
|
2718
2613
|
? error.diagnostics : undefined;
|
|
2719
2614
|
if (carriedDiagnostics?.length) {
|
|
@@ -3042,63 +2937,6 @@ export class TuiController {
|
|
|
3042
2937
|
...executionProjection,
|
|
3043
2938
|
sensitiveValues: collectOperationSensitiveValues(ticket.intent),
|
|
3044
2939
|
});
|
|
3045
|
-
if (ticket.intent.kind === 'catalogManagement') {
|
|
3046
|
-
if (ticket.intent.action === 'devActivate' || ticket.intent.action === 'devDeactivate') {
|
|
3047
|
-
this.dependencies.beginCatalogSession?.();
|
|
3048
|
-
generation = ++this.#generation;
|
|
3049
|
-
try {
|
|
3050
|
-
const refreshed = await this.dependencies.loadStatus(this.#abort.signal);
|
|
3051
|
-
if (!this.#operationIsCurrent(generation)) {
|
|
3052
|
-
return this.#detachedBlocked(operationId, ticket.intent);
|
|
3053
|
-
}
|
|
3054
|
-
this.#applyStatus(refreshed);
|
|
3055
|
-
}
|
|
3056
|
-
catch (reloadError) {
|
|
3057
|
-
if (!this.#operationIsCurrent(generation)) {
|
|
3058
|
-
return this.#detachedBlocked(operationId, ticket.intent);
|
|
3059
|
-
}
|
|
3060
|
-
await this.#logErrorSafe(reloadError, 'tuiStateReloadFailed', {
|
|
3061
|
-
privateConfigOperation: true,
|
|
3062
|
-
});
|
|
3063
|
-
this.#status = undefined;
|
|
3064
|
-
this.#viewModel = undefined;
|
|
3065
|
-
this.#phase = 'error';
|
|
3066
|
-
this.#loadError = {
|
|
3067
|
-
code: 'tuiStateReloadFailed',
|
|
3068
|
-
message: 'Catalog 来源已变更,但插件状态刷新失败。请重新加载后再继续操作。',
|
|
3069
|
-
};
|
|
3070
|
-
return this.#setBlocked(operationId, 'tuiStateReloadFailed', {
|
|
3071
|
-
intent: ticket.intent,
|
|
3072
|
-
navigation: 'result',
|
|
3073
|
-
returnRoute: ticket.returnRoute,
|
|
3074
|
-
writeMayHaveCompleted: true,
|
|
3075
|
-
});
|
|
3076
|
-
}
|
|
3077
|
-
}
|
|
3078
|
-
const baseSummary = operationResultSummary(ticket.intent, execution);
|
|
3079
|
-
const summary = {
|
|
3080
|
-
...baseSummary,
|
|
3081
|
-
elapsedMs: Math.max(0, (this.dependencies.now?.() ?? Date.now()) - startedAtMs),
|
|
3082
|
-
messages: [...this.#progress.messages, ...(baseSummary.messages ?? [])].slice(-8)
|
|
3083
|
-
.map((message) => sanitizeDiagnosticText(message, [], collectOperationSensitiveValues(ticket.intent))),
|
|
3084
|
-
};
|
|
3085
|
-
const projection = this.#operationDiagnostics.get(operationId);
|
|
3086
|
-
if (projection)
|
|
3087
|
-
projection.effects.finalVerification = 'completed';
|
|
3088
|
-
this.#progress = { ...this.#progress, elapsedMs: summary.elapsedMs };
|
|
3089
|
-
const result = {
|
|
3090
|
-
state: summary.code === 'operationPartial' ? 'partial' : 'succeeded',
|
|
3091
|
-
operationId,
|
|
3092
|
-
summary,
|
|
3093
|
-
operationKind: ticket.intent.kind,
|
|
3094
|
-
returnRoute: structuredClone(this.#normalizeRoute(ticket.returnRoute)),
|
|
3095
|
-
};
|
|
3096
|
-
this.#result = result;
|
|
3097
|
-
this.#activeReview = undefined;
|
|
3098
|
-
this.#showResult(result, ticket.intent);
|
|
3099
|
-
this.#publish();
|
|
3100
|
-
return cloneFrozen(result);
|
|
3101
|
-
}
|
|
3102
2940
|
if (ticket.intent.kind === 'sourceMutation' && ticket.intent.action === 'update') {
|
|
3103
2941
|
const confirmedAutoCheck = catalogSourceAutoCheckOnlyValue(ticket.intent.update);
|
|
3104
2942
|
if (confirmedAutoCheck !== undefined) {
|
|
@@ -3375,14 +3213,6 @@ export class TuiController {
|
|
|
3375
3213
|
if (code === 'operationReviewStale' || code === 'catalogGenerationReviewStale') {
|
|
3376
3214
|
return this.#rebuildStaleReview(ticket, operationId, undefined, generation);
|
|
3377
3215
|
}
|
|
3378
|
-
if (ticket.intent.kind === 'catalogManagement') {
|
|
3379
|
-
return this.#setBlocked(operationId, code, {
|
|
3380
|
-
intent: ticket.intent,
|
|
3381
|
-
navigation: 'result',
|
|
3382
|
-
returnRoute: ticket.returnRoute,
|
|
3383
|
-
writeMayHaveCompleted: true,
|
|
3384
|
-
});
|
|
3385
|
-
}
|
|
3386
3216
|
generation = ++this.#generation;
|
|
3387
3217
|
let finalVerification = 'completed';
|
|
3388
3218
|
try {
|
|
@@ -3486,32 +3316,6 @@ export class TuiController {
|
|
|
3486
3316
|
});
|
|
3487
3317
|
}
|
|
3488
3318
|
async #rebuildStaleReview(ticket, operationId, currentEvidence, generation = this.#generation) {
|
|
3489
|
-
if (ticket.intent.kind === 'catalogManagement') {
|
|
3490
|
-
let evidence = currentEvidence;
|
|
3491
|
-
try {
|
|
3492
|
-
evidence ??= await this.dependencies.captureEvidence(structuredClone(ticket.intent), this.#abort.signal);
|
|
3493
|
-
}
|
|
3494
|
-
catch (error) {
|
|
3495
|
-
const code = issueCode(error);
|
|
3496
|
-
this.#appendThrownProjection(operationId, error, code, 'reviewPreparation', ticket.intent);
|
|
3497
|
-
await this.#logOperationError(error, code, ticket.intent);
|
|
3498
|
-
return this.#setBlocked(operationId, code, {
|
|
3499
|
-
intent: ticket.intent,
|
|
3500
|
-
returnRoute: ticket.returnRoute,
|
|
3501
|
-
});
|
|
3502
|
-
}
|
|
3503
|
-
const review = this.#storeOperationReview(ticket.intent, evidence, 'replace', ticket.returnRoute);
|
|
3504
|
-
const result = {
|
|
3505
|
-
state: 'stale',
|
|
3506
|
-
operationId,
|
|
3507
|
-
review,
|
|
3508
|
-
...this.#operationIdentity(ticket.intent),
|
|
3509
|
-
};
|
|
3510
|
-
this.#recordStaleAttempt(operationId, ticket.intent);
|
|
3511
|
-
this.#result = result;
|
|
3512
|
-
this.#publish();
|
|
3513
|
-
return cloneFrozen(result);
|
|
3514
|
-
}
|
|
3515
3319
|
this.dependencies.beginCatalogSession?.();
|
|
3516
3320
|
generation = ++this.#generation;
|
|
3517
3321
|
try {
|
|
@@ -3667,22 +3471,6 @@ export class TuiController {
|
|
|
3667
3471
|
}
|
|
3668
3472
|
}
|
|
3669
3473
|
function operationResultSummaryUnsafe(intent, execution) {
|
|
3670
|
-
if (intent.kind === 'catalogManagement') {
|
|
3671
|
-
const result = execution;
|
|
3672
|
-
return {
|
|
3673
|
-
code: result.state === 'partial' ? 'operationPartial' : 'operationSucceeded',
|
|
3674
|
-
message: result.message,
|
|
3675
|
-
messages: result.messages,
|
|
3676
|
-
catalogManagement: {
|
|
3677
|
-
action: result.action,
|
|
3678
|
-
state: result.state,
|
|
3679
|
-
...(result.catalogVersion ? { catalogVersion: result.catalogVersion } : {}),
|
|
3680
|
-
...(result.planDigest ? { planDigest: result.planDigest } : {}),
|
|
3681
|
-
...(result.store ? { store: structuredClone(result.store) } : {}),
|
|
3682
|
-
...(result.publication ? { publication: structuredClone(result.publication) } : {}),
|
|
3683
|
-
},
|
|
3684
|
-
};
|
|
3685
|
-
}
|
|
3686
3474
|
if (intent.kind === 'catalogSourcesRecovery') {
|
|
3687
3475
|
const result = execution;
|
|
3688
3476
|
return {
|