@lesliechan721/aw 0.1.0-beta.33 → 0.1.0-beta.35
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/scripts/test-plugin-scripts.js +1 -1
- package/dist/src/commands/aw-capabilities.d.ts +1 -1
- package/dist/src/commands/aw-capabilities.js +1 -0
- package/dist/src/commands/aw-capabilities.js.map +1 -1
- package/dist/src/portable/materializer.js +19 -3
- package/dist/src/portable/materializer.js.map +1 -1
- package/dist/src/review/review-profile.js +19 -2
- package/dist/src/review/review-profile.js.map +1 -1
- package/dist/src/tui/components.d.ts +20 -0
- package/dist/src/tui/components.js +13 -1
- package/dist/src/tui/components.js.map +1 -1
- package/dist/src/tui/config-array-draft.d.ts +29 -0
- package/dist/src/tui/config-array-draft.js +48 -0
- package/dist/src/tui/config-array-draft.js.map +1 -0
- package/dist/src/tui/config-value-presentation.d.ts +1 -0
- package/dist/src/tui/config-value-presentation.js +17 -1
- package/dist/src/tui/config-value-presentation.js.map +1 -1
- package/dist/src/tui/console-app-v4.js +504 -288
- package/dist/src/tui/console-app-v4.js.map +1 -1
- package/dist/src/tui/controller-runtime.js +27 -2
- package/dist/src/tui/controller-runtime.js.map +1 -1
- package/dist/src/tui/controller.d.ts +15 -0
- package/dist/src/tui/controller.js +111 -4
- package/dist/src/tui/controller.js.map +1 -1
- package/dist/src/tui/model.d.ts +9 -0
- package/dist/src/tui/model.js +10 -2
- package/dist/src/tui/model.js.map +1 -1
- package/dist/src/tui/project-inventory.d.ts +68 -0
- package/dist/src/tui/project-inventory.js +203 -0
- package/dist/src/tui/project-inventory.js.map +1 -0
- package/dist/src/tui/router.d.ts +16 -3
- package/dist/src/tui/router.js.map +1 -1
- package/dist/src/tui/screen-registry.d.ts +7 -1
- package/dist/src/tui/screen-registry.js +1 -1
- package/dist/src/tui/screen-registry.js.map +1 -1
- package/dist/src/tui/theme.d.ts +12 -0
- package/dist/src/tui/theme.js +12 -0
- package/dist/src/tui/theme.js.map +1 -1
- package/dist/src/types.d.ts +2 -0
- package/dist/src/types.js.map +1 -1
- package/dist/src/utils/catalog-source-references.js +2 -2
- package/dist/src/utils/plugin-config-write.js +3 -1
- package/dist/src/utils/plugin-config-write.js.map +1 -1
- package/dist/src/utils/plugin-config.d.ts +5 -5
- package/dist/src/utils/plugin-config.js +47 -23
- package/dist/src/utils/plugin-config.js.map +1 -1
- package/package.json +3 -3
|
@@ -12,6 +12,7 @@ import type { RebuildProgressFeed, RebuildProgressSnapshot } from '../output/reb
|
|
|
12
12
|
import { type ConfigPageViewModel, type ConfigGroupViewModel, type InstallPlacementDraftViewModel, type PluginListItemViewModel, type PluginDependencyOverviewViewModel, type PortableSkillSelectionViewModel, type SourceHealthViewModel, type SourceDetailViewModel, type TuiViewModel, type UserIssueCategory, type UserIssueViewModel } from './model.js';
|
|
13
13
|
import type { PluginContentOverview } from './plugin-content.js';
|
|
14
14
|
import { OperationHistoryStore, type OperationDiagnosticDetail, type OperationEffectFacts, type OperationHistorySummary, type OperationReportPreview, type SafeOperationDiagnostic, type SaveOperationReportResult } from './operation-history.js';
|
|
15
|
+
import { type ProjectInventoryRoot, type ProjectInventoryViewModel } from './project-inventory.js';
|
|
15
16
|
import { type ConfigInvalidStoreEvidence, type PluginInstallFilter, type PortableBlockerCode, type TuiPageContext, type TuiRoute, type TuiRouterSnapshot } from './router.js';
|
|
16
17
|
import { type CatalogSourceGenerationViewModel } from './catalog-generation.js';
|
|
17
18
|
import type { CatalogSourceFreshnessViewModel } from './catalog-freshness.js';
|
|
@@ -136,6 +137,7 @@ export interface ConfigOperationChange {
|
|
|
136
137
|
}>;
|
|
137
138
|
}
|
|
138
139
|
export interface ConfigSaveBatchGroup {
|
|
140
|
+
editEvidence?: Record<string, import('./model.js').ConfigEditEvidence>;
|
|
139
141
|
scope: Scope;
|
|
140
142
|
updates?: Record<string, unknown>;
|
|
141
143
|
removeKeys?: string[];
|
|
@@ -382,6 +384,10 @@ export interface OperationReviewModel {
|
|
|
382
384
|
version?: string;
|
|
383
385
|
};
|
|
384
386
|
changes: OperationReviewChange[];
|
|
387
|
+
configImpact?: {
|
|
388
|
+
state: 'known' | 'unknown';
|
|
389
|
+
affectedTargetCount: number;
|
|
390
|
+
};
|
|
385
391
|
confirmationDetails?: string[];
|
|
386
392
|
technicalDetails?: string[];
|
|
387
393
|
equivalentCommand?: string;
|
|
@@ -778,6 +784,12 @@ export interface TuiControllerSnapshot {
|
|
|
778
784
|
operationRecordId?: string;
|
|
779
785
|
};
|
|
780
786
|
projectIntentReminder?: ProjectIntentReminder;
|
|
787
|
+
projectInventory?: ProjectInventoryViewModel;
|
|
788
|
+
projectInventoryRefresh: {
|
|
789
|
+
state: 'idle' | 'checking' | 'error';
|
|
790
|
+
checkedAtMs?: number;
|
|
791
|
+
errorCode?: string;
|
|
792
|
+
};
|
|
781
793
|
projectDeclarationAbsent?: boolean;
|
|
782
794
|
projectIntentIssue?: {
|
|
783
795
|
state: 'invalid' | 'unavailable';
|
|
@@ -833,6 +845,9 @@ export declare class TuiController {
|
|
|
833
845
|
discardDrafts?: boolean;
|
|
834
846
|
}): boolean;
|
|
835
847
|
load(): Promise<void>;
|
|
848
|
+
listProjectInventoryRoots(section?: 'declared' | 'extraInstalled'): ProjectInventoryRoot[];
|
|
849
|
+
getProjectInventoryRoot(pluginId: string): ProjectInventoryRoot | undefined;
|
|
850
|
+
refreshProjectInventory(): Promise<boolean>;
|
|
836
851
|
push(route: TuiRoute, context?: TuiPageContext): void;
|
|
837
852
|
hasPortableSkills(pluginId: string): boolean;
|
|
838
853
|
preparePortableInstall(pluginId: string, navigation?: 'push' | 'replace'): Promise<PortableSkillSelectionViewModel>;
|
|
@@ -5,11 +5,12 @@ import { flattenStatusTargets, statusTargetActivation, statusTargetExtensions, s
|
|
|
5
5
|
import { buildRebuildReceiptJson, requestedIntentAction } from '../output/command-receipt.js';
|
|
6
6
|
import { buildOperationResultModel } from '../commands/operation-planner.js';
|
|
7
7
|
import { buildOperationReviewProjection } from './operation-review-planner.js';
|
|
8
|
-
import { buildTuiViewModel, dependencyPlacementTargets,
|
|
8
|
+
import { buildTuiViewModel, dependencyPlacementTargets, } from './model.js';
|
|
9
9
|
import { safeDiagnosticCode, sanitizeDiagnosticText } from './diagnostics.js';
|
|
10
10
|
import { projectExecutionDiagnostics, projectThrownOperationDiagnostic } from './diagnostic-projection.js';
|
|
11
11
|
import { OperationHistoryStore, } from './operation-history.js';
|
|
12
12
|
import { targetHasArtifactCollision } from '../utils/target-eligibility.js';
|
|
13
|
+
import { buildProjectInventory, hasStatusInstallationEvidence, } from './project-inventory.js';
|
|
13
14
|
import { TuiRouter, } from './router.js';
|
|
14
15
|
import { normalizeTuiRoute } from './screen-registry.js';
|
|
15
16
|
import { CatalogSourcesSession } from './catalog-sources/session.js';
|
|
@@ -731,6 +732,9 @@ export class TuiController {
|
|
|
731
732
|
#portableResultRecheck;
|
|
732
733
|
#completionNotice;
|
|
733
734
|
#projectIntentReminder;
|
|
735
|
+
#projectInventory;
|
|
736
|
+
#projectInventoryRefresh = { state: 'idle' };
|
|
737
|
+
#projectInventoryRefreshToken = 0;
|
|
734
738
|
#loadError;
|
|
735
739
|
#portableDraft;
|
|
736
740
|
#recoverablePortableDraft;
|
|
@@ -850,6 +854,8 @@ export class TuiController {
|
|
|
850
854
|
...(this.#projectIntentReminder
|
|
851
855
|
? { projectIntentReminder: this.#projectIntentReminder }
|
|
852
856
|
: {}),
|
|
857
|
+
...(this.#projectInventory ? { projectInventory: this.#projectInventory } : {}),
|
|
858
|
+
projectInventoryRefresh: this.#projectInventoryRefresh,
|
|
853
859
|
...(this.#status?.projectIntent?.state === 'absent' ? { projectDeclarationAbsent: true } : {}),
|
|
854
860
|
...(this.#status?.projectIntent?.state === 'invalid'
|
|
855
861
|
|| this.#status?.projectIntent?.state === 'unavailable'
|
|
@@ -1197,13 +1203,25 @@ export class TuiController {
|
|
|
1197
1203
|
portablePluginIds: this.#status.portablePluginIds,
|
|
1198
1204
|
configStoreInventory: this.#status.configStoreInventory,
|
|
1199
1205
|
});
|
|
1206
|
+
this.#projectInventory = buildProjectInventory({
|
|
1207
|
+
projectRoot: this.#status.projectRoot,
|
|
1208
|
+
projectIntent: this.#status.projectIntent,
|
|
1209
|
+
status: this.#status.payload,
|
|
1210
|
+
pluginSummaries: this.#viewModel.plugins,
|
|
1211
|
+
targetRevisions: this.#status.targetRevisions,
|
|
1212
|
+
dependencyOverviews: this.#status.dependencyOverviews,
|
|
1213
|
+
actionableTargets: this.#projectIntentReminder?.actionableTargets,
|
|
1214
|
+
});
|
|
1200
1215
|
}
|
|
1201
1216
|
#normalizeRoute(route) {
|
|
1202
1217
|
return normalizeTuiRoute(route, this.#routeEntityState());
|
|
1203
1218
|
}
|
|
1204
1219
|
#routeEntityState() {
|
|
1205
1220
|
return {
|
|
1206
|
-
hasPlugin: (pluginId) => this.#viewModel?.plugins.some((plugin) => plugin.pluginId === pluginId)
|
|
1221
|
+
hasPlugin: (pluginId) => this.#viewModel?.plugins.some((plugin) => plugin.pluginId === pluginId)
|
|
1222
|
+
|| this.#projectInventory?.declaredRoots.some((root) => root.pluginId === pluginId)
|
|
1223
|
+
|| this.#projectInventory?.extraInstalledRoots.some((root) => root.pluginId === pluginId)
|
|
1224
|
+
|| false,
|
|
1207
1225
|
hasSource: (sourceId) => this.#viewModel?.sourceTabs.some((source) => source.id === sourceId) ?? false,
|
|
1208
1226
|
hasIssue: (issueId) => this.#viewModel?.issues.some((issue) => issue.issueId === issueId) ?? false,
|
|
1209
1227
|
hasHistoryRecord: (recordId) => this.#operationHistory.get(recordId) !== undefined,
|
|
@@ -1527,6 +1545,8 @@ export class TuiController {
|
|
|
1527
1545
|
this.#assertAcceptingActions();
|
|
1528
1546
|
this.dependencies.beginCatalogSession?.();
|
|
1529
1547
|
const generation = ++this.#generation;
|
|
1548
|
+
this.#projectInventoryRefreshToken += 1;
|
|
1549
|
+
this.#projectInventoryRefresh = { state: 'idle' };
|
|
1530
1550
|
this.#pluginContentEpoch += 1;
|
|
1531
1551
|
this.#pluginContent.clear();
|
|
1532
1552
|
this.#pluginContentInflight.clear();
|
|
@@ -1554,6 +1574,49 @@ export class TuiController {
|
|
|
1554
1574
|
this.#loadError = undefined;
|
|
1555
1575
|
this.#publish();
|
|
1556
1576
|
}
|
|
1577
|
+
listProjectInventoryRoots(section = 'declared') {
|
|
1578
|
+
return cloneFrozen(section === 'declared'
|
|
1579
|
+
? this.#projectInventory?.declaredRoots ?? []
|
|
1580
|
+
: this.#projectInventory?.extraInstalledRoots ?? []);
|
|
1581
|
+
}
|
|
1582
|
+
getProjectInventoryRoot(pluginId) {
|
|
1583
|
+
const root = [...(this.#projectInventory?.declaredRoots ?? []),
|
|
1584
|
+
...(this.#projectInventory?.extraInstalledRoots ?? [])]
|
|
1585
|
+
.find((entry) => entry.pluginId === pluginId);
|
|
1586
|
+
return root ? cloneFrozen(root) : undefined;
|
|
1587
|
+
}
|
|
1588
|
+
async refreshProjectInventory() {
|
|
1589
|
+
this.#assertAcceptingActions();
|
|
1590
|
+
if (!this.#status || this.#phase !== 'ready')
|
|
1591
|
+
return false;
|
|
1592
|
+
const token = ++this.#projectInventoryRefreshToken;
|
|
1593
|
+
const generation = this.#generation;
|
|
1594
|
+
this.#projectInventoryRefresh = { state: 'checking' };
|
|
1595
|
+
this.#publish();
|
|
1596
|
+
try {
|
|
1597
|
+
const status = await this.#trackRead(this.dependencies.loadStatus(this.#abort.signal));
|
|
1598
|
+
if (this.#disposed || generation !== this.#generation
|
|
1599
|
+
|| token !== this.#projectInventoryRefreshToken)
|
|
1600
|
+
return false;
|
|
1601
|
+
this.#applyStatus(status);
|
|
1602
|
+
this.#projectInventoryRefresh = {
|
|
1603
|
+
state: 'idle',
|
|
1604
|
+
checkedAtMs: this.#statusReadAtMs,
|
|
1605
|
+
};
|
|
1606
|
+
this.#publish();
|
|
1607
|
+
return true;
|
|
1608
|
+
}
|
|
1609
|
+
catch (error) {
|
|
1610
|
+
if (this.#disposed || generation !== this.#generation
|
|
1611
|
+
|| token !== this.#projectInventoryRefreshToken)
|
|
1612
|
+
return false;
|
|
1613
|
+
const code = issueCode(error);
|
|
1614
|
+
await this.#logErrorSafe(error, code);
|
|
1615
|
+
this.#projectInventoryRefresh = { state: 'error', errorCode: code };
|
|
1616
|
+
this.#publish();
|
|
1617
|
+
return false;
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1557
1620
|
push(route, context) {
|
|
1558
1621
|
if (this.#router.snapshot.current.route.name === 'result') {
|
|
1559
1622
|
this.#invalidatePortableResultRecheck();
|
|
@@ -2433,10 +2496,39 @@ export class TuiController {
|
|
|
2433
2496
|
}
|
|
2434
2497
|
listPlugins(options) {
|
|
2435
2498
|
const query = options.query?.trim().toLocaleLowerCase('en');
|
|
2499
|
+
const actualScopes = new Map();
|
|
2500
|
+
const statusTargets = flattenStatusTargets(this.#status?.payload.targets ?? []);
|
|
2501
|
+
const targetsByPlugin = new Map();
|
|
2502
|
+
for (const target of statusTargets) {
|
|
2503
|
+
targetsByPlugin.set(target.pluginId, [...(targetsByPlugin.get(target.pluginId) ?? []), target]);
|
|
2504
|
+
const owned = target.platform === 'claude'
|
|
2505
|
+
? ['present', 'partial'].includes(statusTargetOwnershipState(target))
|
|
2506
|
+
: target.components.some((component) => component.kind === 'ownership'
|
|
2507
|
+
&& component.key !== 'native'
|
|
2508
|
+
&& !component.key.startsWith('activation-')
|
|
2509
|
+
&& !component.key.startsWith('marketplace-')
|
|
2510
|
+
&& (component.state === 'present' || component.state === 'partial'));
|
|
2511
|
+
const activation = target.platform === 'codex' ? statusTargetActivation(target) : undefined;
|
|
2512
|
+
if (!owned && !(activation?.evidence === 'observed'
|
|
2513
|
+
&& activation[target.scope] === true)
|
|
2514
|
+
&& !hasStatusInstallationEvidence(target))
|
|
2515
|
+
continue;
|
|
2516
|
+
const scopes = actualScopes.get(target.pluginId) ?? new Set();
|
|
2517
|
+
scopes.add(target.scope);
|
|
2518
|
+
actualScopes.set(target.pluginId, scopes);
|
|
2519
|
+
}
|
|
2436
2520
|
return cloneFrozen((this.#viewModel?.plugins ?? []).filter((plugin) => (!options.sourceId || plugin.sourceId === options.sourceId)
|
|
2437
2521
|
&& (options.installFilter !== 'installed'
|
|
2438
|
-
||
|
|
2439
|
-
&& (options.installFilter !== 'uninstalled'
|
|
2522
|
+
|| (actualScopes.get(plugin.pluginId)?.size ?? 0) > 0)
|
|
2523
|
+
&& (options.installFilter !== 'uninstalled'
|
|
2524
|
+
|| plugin.aggregateStatus === 'available'
|
|
2525
|
+
&& (targetsByPlugin.get(plugin.pluginId)?.length ?? 0) > 0
|
|
2526
|
+
&& targetsByPlugin.get(plugin.pluginId).every((target) => target.state === 'absent')
|
|
2527
|
+
&& (actualScopes.get(plugin.pluginId)?.size ?? 0) === 0)
|
|
2528
|
+
&& (options.installFilter !== 'project'
|
|
2529
|
+
|| actualScopes.get(plugin.pluginId)?.has('project') === true)
|
|
2530
|
+
&& (options.installFilter !== 'user'
|
|
2531
|
+
|| actualScopes.get(plugin.pluginId)?.has('user') === true)
|
|
2440
2532
|
&& (options.installFilter !== 'updateAvailable' || plugin.update?.state === 'available')
|
|
2441
2533
|
&& (options.installFilter !== 'attention'
|
|
2442
2534
|
|| plugin.aggregateStatus === 'needsAttention' || plugin.aggregateStatus === 'unavailable'
|
|
@@ -3277,6 +3369,20 @@ export class TuiController {
|
|
|
3277
3369
|
assertPluginWriteTaskEvidence(intent, evidence);
|
|
3278
3370
|
if (this.#router.snapshot.current.route.name === 'result')
|
|
3279
3371
|
navigation = 'replace';
|
|
3372
|
+
const configEvidence = intent.kind === 'configSave'
|
|
3373
|
+
? evidence.config ? [evidence.config] : undefined
|
|
3374
|
+
: intent.kind === 'configSaveBatch'
|
|
3375
|
+
? evidence.configBatch?.groups.map((group) => group.config)
|
|
3376
|
+
: undefined;
|
|
3377
|
+
if ((intent.kind === 'configSave' || intent.kind === 'configSaveBatch')
|
|
3378
|
+
&& (!configEvidence || configEvidence.length !== (intent.kind === 'configSave' ? 1 : intent.groups.length))) {
|
|
3379
|
+
throw new TuiOperationBlockedError('configImpactUnavailable', '设置确认缺少完整的应用影响证据。');
|
|
3380
|
+
}
|
|
3381
|
+
const configImpact = configEvidence ? {
|
|
3382
|
+
state: configEvidence.some((group) => group.impactState !== 'known') ? 'unknown' : 'known',
|
|
3383
|
+
affectedTargetCount: new Set(configEvidence.flatMap((group) => group.affectedTargets
|
|
3384
|
+
.map((target) => `${target.platform}\0${target.scope}`))).size,
|
|
3385
|
+
} : undefined;
|
|
3280
3386
|
const projection = buildOperationReviewProjection({
|
|
3281
3387
|
intent,
|
|
3282
3388
|
evidence,
|
|
@@ -3349,6 +3455,7 @@ export class TuiController {
|
|
|
3349
3455
|
? { originIssue: intent.originIssue }
|
|
3350
3456
|
: {}),
|
|
3351
3457
|
...projection,
|
|
3458
|
+
...(configImpact ? { configImpact } : {}),
|
|
3352
3459
|
subject: {
|
|
3353
3460
|
name: 'pluginId' in intent
|
|
3354
3461
|
? this.#viewModel?.plugins.find((plugin) => plugin.pluginId === intent.pluginId)?.displayName
|