@lesliechan721/aw 0.1.0-beta.18 → 0.1.0-beta.19
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/operation-planner.d.ts +3 -3
- package/dist/src/commands/status-v6.d.ts +81 -31
- package/dist/src/commands/status-v6.js +494 -183
- package/dist/src/commands/status-v6.js.map +1 -1
- package/dist/src/commands/wizard.d.ts +2 -2
- package/dist/src/index.js +2 -2
- package/dist/src/tui/catalog-sources/projection.d.ts +2 -2
- package/dist/src/tui/catalog-sources/screens.js +17 -10
- package/dist/src/tui/catalog-sources/screens.js.map +1 -1
- package/dist/src/tui/console-app-v4.js +1291 -435
- package/dist/src/tui/console-app-v4.js.map +1 -1
- package/dist/src/tui/controller-runtime.d.ts +3 -3
- package/dist/src/tui/controller-runtime.js +85 -27
- package/dist/src/tui/controller-runtime.js.map +1 -1
- package/dist/src/tui/controller.d.ts +17 -7
- package/dist/src/tui/controller.js +265 -24
- package/dist/src/tui/controller.js.map +1 -1
- package/dist/src/tui/dependency-graph.d.ts +3 -0
- package/dist/src/tui/dependency-graph.js +37 -1
- package/dist/src/tui/dependency-graph.js.map +1 -1
- package/dist/src/tui/diagnostic-projection.d.ts +1 -0
- package/dist/src/tui/diagnostic-projection.js +51 -4
- package/dist/src/tui/diagnostic-projection.js.map +1 -1
- package/dist/src/tui/model.d.ts +22 -12
- package/dist/src/tui/model.js +251 -86
- package/dist/src/tui/model.js.map +1 -1
- package/dist/src/tui/operation-history.d.ts +1 -0
- package/dist/src/tui/operation-history.js +5 -0
- package/dist/src/tui/operation-history.js.map +1 -1
- package/dist/src/tui/operation-review-planner.js +67 -2
- package/dist/src/tui/operation-review-planner.js.map +1 -1
- package/dist/src/tui/plugin-write-task.d.ts +2 -0
- package/dist/src/tui/plugin-write-task.js.map +1 -1
- package/dist/src/tui/router.d.ts +6 -0
- package/dist/src/tui/router.js +56 -12
- package/dist/src/tui/router.js.map +1 -1
- package/dist/src/tui/screen-registry.d.ts +7 -0
- package/dist/src/utils/plugin-config-write.js +3 -3
- package/dist/src/utils/plugin-config-write.js.map +1 -1
- package/dist/src/utils/target-eligibility.d.ts +2 -2
- package/dist/src/utils/target-eligibility.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CliExecutionContext } from '../commands/runtime.js';
|
|
2
|
-
import { type StatusTargetRevision, type
|
|
2
|
+
import { type StatusTargetRevision, type StatusScopedTarget, type StatusV8Target } from '../commands/status-v6.js';
|
|
3
3
|
import { type CatalogSourceMutationProgress } from '../commands/catalog-source.js';
|
|
4
4
|
import type { RebuildProgressFeed } from '../output/rebuild-progress.js';
|
|
5
5
|
import { inventoryCatalogSourceReferences } from '../utils/catalog-source-references.js';
|
|
@@ -13,8 +13,8 @@ export interface TuiControllerRuntimeTestHooks {
|
|
|
13
13
|
afterCatalogGenerationCandidateResolved?: () => Promise<void>;
|
|
14
14
|
}
|
|
15
15
|
export declare function setTuiControllerRuntimeTestHooksForTests(hooks: TuiControllerRuntimeTestHooks | undefined): void;
|
|
16
|
-
export declare function statusTargetFingerprint(targets:
|
|
17
|
-
export declare function configAffectedStatusTargets(targets:
|
|
16
|
+
export declare function statusTargetFingerprint(targets: StatusScopedTarget[], revisions?: StatusTargetRevision[]): string;
|
|
17
|
+
export declare function configAffectedStatusTargets(targets: StatusV8Target[], pluginId: string, configScope: 'user' | 'project'): StatusScopedTarget[];
|
|
18
18
|
export declare function createTuiControllerDependencies(context: CliExecutionContext, progressFeed?: RebuildProgressFeed, options?: {
|
|
19
19
|
now?: () => number;
|
|
20
20
|
inventoryCatalogSourceReferences?: typeof inventoryCatalogSourceReferences;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import crypto from 'node:crypto';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { flattenStatusTargets, statusCommandV8, statusTargetActivation, statusTargetIntent, statusTargetOwnershipState, } from '../commands/status-v6.js';
|
|
4
4
|
import { addCatalogSourceCommand, listCatalogSources, preflightCatalogSourceMutation, removeCatalogSourceCommand, setPrimaryCatalogSourceCommand, updateCatalogSourceCommand, } from '../commands/catalog-source.js';
|
|
5
5
|
import { cleanupWriteCommand, failedWriteCommandResult, installWriteCommand, mergeWriteCommandResults, reinstallWriteCommand, syncWriteCommand, taskWriteCommand, uninstallWriteCommand, } from '../commands/write-commands.js';
|
|
6
6
|
import { resolveSyncIntentSelection } from '../commands/sync-command.js';
|
|
@@ -19,6 +19,7 @@ import { inventoryCatalogSourceReferences } from '../utils/catalog-source-refere
|
|
|
19
19
|
import { operationEvidenceMatches, operationEvidenceFingerprint, TuiConfigInvalidStoreError, TuiController, TuiOperationBlockedError, } from './controller.js';
|
|
20
20
|
import { buildConfigGroups, buildConfigPage, buildTuiViewModel, projectPlatformPlacement, } from './model.js';
|
|
21
21
|
import { buildPluginWriteTaskCandidates, buildPluginWriteTaskDraft, evaluatePluginWriteTaskRestoreVersion, pluginWriteTaskTargetKey, } from './plugin-write-task.js';
|
|
22
|
+
import { projectExecutionDiagnostics, projectThrownOperationDiagnostic } from './diagnostic-projection.js';
|
|
22
23
|
import { createCatalogManagementService, } from './catalog-management.js';
|
|
23
24
|
import { projectCatalogSourceLocation } from '../utils/catalog-source-presentation.js';
|
|
24
25
|
import { calculateCatalogSourceConfigFingerprint, calculateCatalogSourceIdentity, } from '../utils/catalog-source-identity.js';
|
|
@@ -91,8 +92,13 @@ export function statusTargetFingerprint(targets, revisions = []) {
|
|
|
91
92
|
scope: target.scope,
|
|
92
93
|
state: target.state,
|
|
93
94
|
errors: target.reasons.map((error) => error.code).sort(),
|
|
95
|
+
sharedReasons: [...(target.sharedReasons ?? [])]
|
|
96
|
+
.sort((left, right) => `${left.code}\0${left.message}`.localeCompare(`${right.code}\0${right.message}`, 'en')),
|
|
94
97
|
components: target.components.map((component) => [component.key, component.state])
|
|
95
98
|
.sort(([left], [right]) => left.localeCompare(right, 'en')),
|
|
99
|
+
sharedComponents: (target.sharedComponents ?? [])
|
|
100
|
+
.map((component) => [component.key, component.state, component.metadata])
|
|
101
|
+
.sort(([left], [right]) => left.localeCompare(right, 'en')),
|
|
96
102
|
})).sort((left, right) => [left.pluginId, left.platform, left.scope].join('\0')
|
|
97
103
|
.localeCompare([right.pluginId, right.platform, right.scope].join('\0'), 'en')),
|
|
98
104
|
revisions: revisions.map((entry) => ({
|
|
@@ -106,7 +112,7 @@ export function statusTargetFingerprint(targets, revisions = []) {
|
|
|
106
112
|
}
|
|
107
113
|
export function configAffectedStatusTargets(targets, pluginId, configScope) {
|
|
108
114
|
const affected = new Map();
|
|
109
|
-
for (const target of targets) {
|
|
115
|
+
for (const target of flattenStatusTargets(targets)) {
|
|
110
116
|
const intent = statusTargetIntent(target);
|
|
111
117
|
if (target.pluginId !== pluginId || !intent.enabled)
|
|
112
118
|
continue;
|
|
@@ -146,8 +152,8 @@ function configIntentRequestsApply(intent) {
|
|
|
146
152
|
return Object.keys(intent.updates ?? {}).length > 0
|
|
147
153
|
|| (intent.removeKeys?.length ?? 0) > 0;
|
|
148
154
|
}
|
|
149
|
-
function operationReviewStale(message) {
|
|
150
|
-
return new TuiOperationBlockedError('operationReviewStale', `operationReviewStale: ${message}
|
|
155
|
+
function operationReviewStale(message, diagnostics) {
|
|
156
|
+
return new TuiOperationBlockedError('operationReviewStale', `operationReviewStale: ${message}`, diagnostics);
|
|
151
157
|
}
|
|
152
158
|
function sourceEvidenceForPlugin(source, pluginName) {
|
|
153
159
|
const entry = source.manifest.entries.find((candidate) => candidate.name === pluginName);
|
|
@@ -364,7 +370,7 @@ async function loadDependencyOverviews(options) {
|
|
|
364
370
|
}
|
|
365
371
|
}
|
|
366
372
|
const targetsByPlugin = new Map();
|
|
367
|
-
for (const target of options.status.payload.targets) {
|
|
373
|
+
for (const target of flattenStatusTargets(options.status.payload.targets)) {
|
|
368
374
|
targetsByPlugin.set(target.pluginId, [...(targetsByPlugin.get(target.pluginId) ?? []), target]);
|
|
369
375
|
}
|
|
370
376
|
const unsupportedPluginIds = new Set(options.status.pluginSummaries
|
|
@@ -647,7 +653,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
647
653
|
if (catalogOperationContext)
|
|
648
654
|
sessionCatalogOperationContext = catalogOperationContext;
|
|
649
655
|
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
650
|
-
const result = await
|
|
656
|
+
const result = await statusCommandV8({
|
|
651
657
|
cwd: context.cwd,
|
|
652
658
|
env: context.env,
|
|
653
659
|
nativeCliRunner: context.nativeCliRunner,
|
|
@@ -1208,16 +1214,39 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1208
1214
|
...(signal ? { signal } : {}),
|
|
1209
1215
|
});
|
|
1210
1216
|
}
|
|
1211
|
-
catch {
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
+
catch (error) {
|
|
1218
|
+
if (error instanceof Error && error.name === 'AbortError')
|
|
1219
|
+
throw error;
|
|
1220
|
+
blockedTargets.push(...requestedTargets.map((target, index) => {
|
|
1221
|
+
const diagnostic = error instanceof CatalogGenerationError ? {
|
|
1222
|
+
id: `task-source:${sourceId}:${index}`,
|
|
1223
|
+
code: error.code,
|
|
1224
|
+
stage: 'source',
|
|
1225
|
+
sourceId,
|
|
1226
|
+
safeMessage: 'The Catalog source could not be prepared safely.',
|
|
1227
|
+
target: { pluginId: target.pluginId, platform: target.platform, scope: target.scope },
|
|
1228
|
+
causes: [],
|
|
1229
|
+
detailLines: [],
|
|
1230
|
+
} : projectThrownOperationDiagnostic({
|
|
1231
|
+
error,
|
|
1232
|
+
id: `task-source:${sourceId}:${index}`,
|
|
1233
|
+
stage: 'source',
|
|
1234
|
+
fallbackCode: 'catalogSourceResolutionFailed',
|
|
1235
|
+
sourceId,
|
|
1236
|
+
target,
|
|
1237
|
+
});
|
|
1238
|
+
return {
|
|
1239
|
+
target,
|
|
1240
|
+
reason: 'targetUnavailable',
|
|
1241
|
+
issueIds: [],
|
|
1242
|
+
errorCodes: [diagnostic.code],
|
|
1243
|
+
diagnostics: [diagnostic],
|
|
1244
|
+
};
|
|
1245
|
+
}));
|
|
1217
1246
|
continue;
|
|
1218
1247
|
}
|
|
1219
1248
|
operationContexts.set(sourceId, catalogOperation);
|
|
1220
|
-
const status = await
|
|
1249
|
+
const status = await statusCommandV8({
|
|
1221
1250
|
plugins: [...new Set(requestedTargets.map((target) => target.pluginId))],
|
|
1222
1251
|
cwd: context.cwd,
|
|
1223
1252
|
env: context.env,
|
|
@@ -1227,7 +1256,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1227
1256
|
catalogOperationContext: catalogOperation,
|
|
1228
1257
|
inventoryCatalogSourceReferences: operationInventory,
|
|
1229
1258
|
});
|
|
1230
|
-
observedTargets.push(...status.payload.targets);
|
|
1259
|
+
observedTargets.push(...flattenStatusTargets(status.payload.targets));
|
|
1231
1260
|
observedRevisions.push(...status.targetRevisions);
|
|
1232
1261
|
const model = buildTuiViewModel({
|
|
1233
1262
|
status: status.payload,
|
|
@@ -1240,7 +1269,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1240
1269
|
const expected = target.expectedUpdate;
|
|
1241
1270
|
const revision = status.targetRevisions.find((entry) => entry.pluginId === target.pluginId && entry.platform === target.platform
|
|
1242
1271
|
&& entry.scope === target.scope);
|
|
1243
|
-
const live = status.payload.targets.find((entry) => {
|
|
1272
|
+
const live = flattenStatusTargets(status.payload.targets).find((entry) => {
|
|
1244
1273
|
if (entry.pluginId !== target.pluginId || entry.platform !== target.platform)
|
|
1245
1274
|
return false;
|
|
1246
1275
|
const desired = statusTargetIntent(entry);
|
|
@@ -1325,12 +1354,41 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1325
1354
|
} : {}),
|
|
1326
1355
|
});
|
|
1327
1356
|
if (!preview.operationPlan) {
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1357
|
+
const projected = projectExecutionDiagnostics(preview, `task-preview:${sourceId}`, [], 'pluginWrite');
|
|
1358
|
+
const sourceDiagnostics = projected.diagnostics.filter((diagnostic) => !diagnostic.target)
|
|
1359
|
+
.map((diagnostic) => ({ ...diagnostic, sourceId, target: undefined }));
|
|
1360
|
+
blockedTargets.push(...draft.executableTargets.map((target, targetIndex) => {
|
|
1361
|
+
const matchingDiagnostics = projected.diagnostics.filter((diagnostic) => diagnostic.target?.pluginId === target.pluginId
|
|
1362
|
+
&& diagnostic.target.platform === target.platform
|
|
1363
|
+
&& diagnostic.target.scope === target.scope);
|
|
1364
|
+
const preparedDiagnostics = [
|
|
1365
|
+
...matchingDiagnostics,
|
|
1366
|
+
...(targetIndex === 0 ? sourceDiagnostics : []),
|
|
1367
|
+
];
|
|
1368
|
+
const targetDiagnostics = preparedDiagnostics.length > 0
|
|
1369
|
+
? preparedDiagnostics
|
|
1370
|
+
: [projectThrownOperationDiagnostic({
|
|
1371
|
+
error: undefined,
|
|
1372
|
+
id: `task-preview:${sourceId}:${targetIndex}`,
|
|
1373
|
+
stage: 'dependencyPlan',
|
|
1374
|
+
fallbackCode: 'taskOperationPlanMissing',
|
|
1375
|
+
sourceId,
|
|
1376
|
+
target,
|
|
1377
|
+
})];
|
|
1378
|
+
const diagnostics = targetDiagnostics.map((diagnostic, diagnosticIndex) => ({
|
|
1379
|
+
...structuredClone(diagnostic),
|
|
1380
|
+
id: `task-preview:${sourceId}:${targetIndex}:${diagnosticIndex}`,
|
|
1381
|
+
sourceId,
|
|
1382
|
+
}));
|
|
1383
|
+
return {
|
|
1384
|
+
target,
|
|
1385
|
+
reason: 'targetUnavailable',
|
|
1386
|
+
issueIds: draft.causes.filter((cause) => cause.consumers.some((consumer) => pluginWriteTaskTargetKey(consumer) === pluginWriteTaskTargetKey(target)))
|
|
1387
|
+
.map((cause) => cause.issueId),
|
|
1388
|
+
errorCodes: [...new Set(diagnostics.map((diagnostic) => diagnostic.code))],
|
|
1389
|
+
diagnostics,
|
|
1390
|
+
};
|
|
1391
|
+
}));
|
|
1334
1392
|
draft.executableTargets = [];
|
|
1335
1393
|
draft.causes = [];
|
|
1336
1394
|
break;
|
|
@@ -1520,10 +1578,10 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1520
1578
|
])).values()].sort((left, right) => pluginWriteTaskTargetKey(left.target)
|
|
1521
1579
|
.localeCompare(pluginWriteTaskTargetKey(right.target), 'en'));
|
|
1522
1580
|
if (executableTargets.length === 0) {
|
|
1523
|
-
throw new TuiOperationBlockedError('taskNoExecutableTargets', '任务没有可安全执行的目标。');
|
|
1581
|
+
throw new TuiOperationBlockedError('taskNoExecutableTargets', '任务没有可安全执行的目标。', canonicalBlocked.flatMap((target) => target.diagnostics ?? []));
|
|
1524
1582
|
}
|
|
1525
1583
|
if (intent.executionPolicy === 'all' && canonicalBlocked.length > 0) {
|
|
1526
|
-
throw new TuiOperationBlockedError('taskHasBlockedTargets', '部分目标需要先处理。请调整选择。');
|
|
1584
|
+
throw new TuiOperationBlockedError('taskHasBlockedTargets', '部分目标需要先处理。请调整选择。', canonicalBlocked.flatMap((target) => target.diagnostics ?? []));
|
|
1527
1585
|
}
|
|
1528
1586
|
await preparation?.reporter.emit('evidence');
|
|
1529
1587
|
const evidence = {
|
|
@@ -1662,7 +1720,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1662
1720
|
return [];
|
|
1663
1721
|
const platform = group.platform;
|
|
1664
1722
|
return group.requestedPluginIds.map((pluginId) => {
|
|
1665
|
-
const live = sessionStatusResult?.payload.targets.find((target) => target.pluginId === pluginId && target.platform === platform
|
|
1723
|
+
const live = flattenStatusTargets(sessionStatusResult?.payload.targets ?? []).find((target) => target.pluginId === pluginId && target.platform === platform
|
|
1666
1724
|
&& (target.scope === group.scope || statusTargetIntent(target).scopes.includes(group.scope)
|
|
1667
1725
|
|| platform === 'codex' && statusTargetActivation(target)?.[group.scope] === true));
|
|
1668
1726
|
const revision = sessionStatusResult?.targetRevisions?.find((target) => target.pluginId === pluginId && target.platform === platform
|
|
@@ -1915,7 +1973,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
1915
1973
|
await preparation?.reporter.emit('status');
|
|
1916
1974
|
const statusCatalogOperation = catalogOperation
|
|
1917
1975
|
?? (!freshCatalog ? sessionCatalogOperationContext : undefined);
|
|
1918
|
-
const status = await
|
|
1976
|
+
const status = await statusCommandV8({
|
|
1919
1977
|
plugins: [...new Set([intent.pluginId,
|
|
1920
1978
|
...(intent.kind === 'pluginWrite' && intent.originIssue?.consumerPluginId
|
|
1921
1979
|
? [intent.originIssue.consumerPluginId] : [])])],
|
|
@@ -2118,7 +2176,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
2118
2176
|
signal?.throwIfAborted();
|
|
2119
2177
|
const evidenceTargets = intent.kind === 'configSave'
|
|
2120
2178
|
? configVisibleTargets
|
|
2121
|
-
: status.payload.targets;
|
|
2179
|
+
: flattenStatusTargets(status.payload.targets);
|
|
2122
2180
|
const evidenceRevisions = intent.kind === 'configSave'
|
|
2123
2181
|
? (status.targetRevisions ?? []).filter((revision) => evidenceTargets.some((target) => target.platform === revision.platform
|
|
2124
2182
|
&& target.scope === revision.scope
|
|
@@ -2849,7 +2907,7 @@ export function createTuiControllerDependencies(context, progressFeed, options =
|
|
|
2849
2907
|
const code = error instanceof TuiOperationBlockedError ? error.code : undefined;
|
|
2850
2908
|
if (intent.kind === 'pluginWriteTask'
|
|
2851
2909
|
&& (code === 'taskHasBlockedTargets' || code === 'taskNoExecutableTargets')) {
|
|
2852
|
-
throw operationReviewStale('确认后任务可执行目标发生变化。');
|
|
2910
|
+
throw operationReviewStale('确认后任务可执行目标发生变化。', error instanceof TuiOperationBlockedError ? error.diagnostics : undefined);
|
|
2853
2911
|
}
|
|
2854
2912
|
throw error;
|
|
2855
2913
|
}
|