@lesliechan721/aw 0.1.0-beta.27 → 0.1.0-beta.28
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.d.ts +3 -0
- package/dist/src/commands/status-v6.js +37 -10
- package/dist/src/commands/status-v6.js.map +1 -1
- package/dist/src/portable/skills-cli.js +35 -4
- package/dist/src/portable/skills-cli.js.map +1 -1
- package/dist/src/tui/catalog-sources/screens.js +5 -5
- package/dist/src/tui/catalog-sources/screens.js.map +1 -1
- package/dist/src/tui/console-app-v4.js +469 -139
- package/dist/src/tui/console-app-v4.js.map +1 -1
- package/dist/src/tui/controller-runtime.js +16 -8
- package/dist/src/tui/controller-runtime.js.map +1 -1
- package/dist/src/tui/controller.d.ts +31 -0
- package/dist/src/tui/controller.js +119 -19
- package/dist/src/tui/controller.js.map +1 -1
- package/dist/src/utils/plugin-intent-state.d.ts +15 -0
- package/dist/src/utils/plugin-intent-state.js +34 -3
- package/dist/src/utils/plugin-intent-state.js.map +1 -1
- package/package.json +3 -3
|
@@ -436,6 +436,7 @@ export type OperationExecuteResult = {
|
|
|
436
436
|
}>['action'];
|
|
437
437
|
pluginId?: string;
|
|
438
438
|
originIssue?: IssueOrigin;
|
|
439
|
+
portableIntent?: PortableResultIntentMetadata;
|
|
439
440
|
returnRoute?: TuiRoute;
|
|
440
441
|
operationRecordId?: string;
|
|
441
442
|
diagnosticIds?: string[];
|
|
@@ -450,6 +451,7 @@ export type OperationExecuteResult = {
|
|
|
450
451
|
}>['action'];
|
|
451
452
|
pluginId?: string;
|
|
452
453
|
originIssue?: IssueOrigin;
|
|
454
|
+
portableIntent?: PortableResultIntentMetadata;
|
|
453
455
|
returnRoute?: TuiRoute;
|
|
454
456
|
operationRecordId?: string;
|
|
455
457
|
diagnosticIds?: string[];
|
|
@@ -463,6 +465,7 @@ export type OperationExecuteResult = {
|
|
|
463
465
|
}>['action'];
|
|
464
466
|
review: OperationReviewModel;
|
|
465
467
|
originIssue?: IssueOrigin;
|
|
468
|
+
portableIntent?: PortableResultIntentMetadata;
|
|
466
469
|
operationRecordId?: string;
|
|
467
470
|
diagnosticIds?: string[];
|
|
468
471
|
effects?: OperationEffectFacts;
|
|
@@ -478,6 +481,7 @@ export type OperationExecuteResult = {
|
|
|
478
481
|
pluginId?: string;
|
|
479
482
|
returnRoute?: TuiRoute;
|
|
480
483
|
originIssue?: IssueOrigin;
|
|
484
|
+
portableIntent?: PortableResultIntentMetadata;
|
|
481
485
|
writeMayHaveCompleted?: boolean;
|
|
482
486
|
verification?: 'issueStillPresent' | 'verificationFailed';
|
|
483
487
|
summary?: OperationResultSummary;
|
|
@@ -485,6 +489,10 @@ export type OperationExecuteResult = {
|
|
|
485
489
|
diagnosticIds?: string[];
|
|
486
490
|
effects?: OperationEffectFacts;
|
|
487
491
|
};
|
|
492
|
+
export interface PortableResultIntentMetadata {
|
|
493
|
+
scope: Scope;
|
|
494
|
+
agentMode: 'automatic' | 'explicit';
|
|
495
|
+
}
|
|
488
496
|
export interface OperationResultSummary {
|
|
489
497
|
code: 'operationSucceeded' | 'operationPartial' | 'operationFailed';
|
|
490
498
|
message: string;
|
|
@@ -536,6 +544,10 @@ export interface OperationResultSummary {
|
|
|
536
544
|
selectedSkills: string[];
|
|
537
545
|
agentMode: 'automatic' | 'explicit';
|
|
538
546
|
requestedAgents: string[];
|
|
547
|
+
attemptedTargets?: Array<{
|
|
548
|
+
skill: string;
|
|
549
|
+
agent?: string;
|
|
550
|
+
}>;
|
|
539
551
|
scope: Scope;
|
|
540
552
|
materializationDigest: string;
|
|
541
553
|
skillsCliVersion: string;
|
|
@@ -603,6 +615,20 @@ export interface PluginOperationProgressLine {
|
|
|
603
615
|
}
|
|
604
616
|
export interface TuiStatusLoadResult {
|
|
605
617
|
projectRoot?: string;
|
|
618
|
+
projectIntent?: {
|
|
619
|
+
state: 'ready';
|
|
620
|
+
roots: Array<{
|
|
621
|
+
pluginId: string;
|
|
622
|
+
platforms: PlatformName[];
|
|
623
|
+
}>;
|
|
624
|
+
} | {
|
|
625
|
+
state: 'absent';
|
|
626
|
+
} | {
|
|
627
|
+
state: 'invalid' | 'unavailable';
|
|
628
|
+
code: string;
|
|
629
|
+
message: string;
|
|
630
|
+
};
|
|
631
|
+
/** Compatibility input for older injected status fixtures. Production uses projectIntent. */
|
|
606
632
|
projectIntentRoots?: Array<{
|
|
607
633
|
pluginId: string;
|
|
608
634
|
platforms: PlatformName[];
|
|
@@ -742,6 +768,11 @@ export interface TuiControllerSnapshot {
|
|
|
742
768
|
operationRecordId?: string;
|
|
743
769
|
};
|
|
744
770
|
projectIntentReminder?: ProjectIntentReminder;
|
|
771
|
+
projectIntentIssue?: {
|
|
772
|
+
state: 'invalid' | 'unavailable';
|
|
773
|
+
code: string;
|
|
774
|
+
message: string;
|
|
775
|
+
};
|
|
745
776
|
}
|
|
746
777
|
export declare class TuiOperationBlockedError extends Error {
|
|
747
778
|
readonly code: string;
|
|
@@ -90,10 +90,13 @@ function projectReminderTargetKey(target) {
|
|
|
90
90
|
return [target.pluginId, target.platform, target.scope].join('\0');
|
|
91
91
|
}
|
|
92
92
|
export function projectCurrentIntentReminder(status) {
|
|
93
|
+
if (status.projectIntent && status.projectIntent.state !== 'ready')
|
|
94
|
+
return undefined;
|
|
93
95
|
const actionableTargets = [];
|
|
94
96
|
const blockedTargets = [];
|
|
95
97
|
const unconfirmedTargets = [];
|
|
96
|
-
const projectRoots = new Map((status.
|
|
98
|
+
const projectRoots = new Map((status.projectIntent?.state === 'ready'
|
|
99
|
+
? status.projectIntent.roots : status.projectIntentRoots ?? []).map((root) => [
|
|
97
100
|
root.pluginId,
|
|
98
101
|
new Set(root.platforms),
|
|
99
102
|
]));
|
|
@@ -724,6 +727,8 @@ export class TuiController {
|
|
|
724
727
|
#portableResultSkills;
|
|
725
728
|
#portableResultReceipt;
|
|
726
729
|
#portableResultIntent;
|
|
730
|
+
#portableResultLifecycle = 0;
|
|
731
|
+
#portableResultRecheck;
|
|
727
732
|
#completionNotice;
|
|
728
733
|
#projectIntentReminder;
|
|
729
734
|
#loadError;
|
|
@@ -839,6 +844,10 @@ export class TuiController {
|
|
|
839
844
|
...(this.#projectIntentReminder
|
|
840
845
|
? { projectIntentReminder: this.#projectIntentReminder }
|
|
841
846
|
: {}),
|
|
847
|
+
...(this.#status?.projectIntent?.state === 'invalid'
|
|
848
|
+
|| this.#status?.projectIntent?.state === 'unavailable'
|
|
849
|
+
? { projectIntentIssue: this.#status.projectIntent }
|
|
850
|
+
: {}),
|
|
842
851
|
});
|
|
843
852
|
}
|
|
844
853
|
subscribe(listener) {
|
|
@@ -921,6 +930,7 @@ export class TuiController {
|
|
|
921
930
|
}
|
|
922
931
|
beginRetirement() {
|
|
923
932
|
this.#retiring = true;
|
|
933
|
+
this.#invalidatePortableResultRecheck();
|
|
924
934
|
}
|
|
925
935
|
async waitForWrites() {
|
|
926
936
|
this.beginRetirement();
|
|
@@ -952,6 +962,7 @@ export class TuiController {
|
|
|
952
962
|
goHome(options = {}) {
|
|
953
963
|
if (this.hasSessionDraft && !options.discardDrafts)
|
|
954
964
|
return false;
|
|
965
|
+
this.#invalidatePortableResultRecheck();
|
|
955
966
|
this.#cancelReviewPreparation();
|
|
956
967
|
this.#cancelPortableRequest();
|
|
957
968
|
this.#cancelInstallPlacementRequest();
|
|
@@ -1330,6 +1341,7 @@ export class TuiController {
|
|
|
1330
1341
|
return { name: 'sourceList' };
|
|
1331
1342
|
}
|
|
1332
1343
|
#showResult(result, intent) {
|
|
1344
|
+
this.#invalidatePortableResultRecheck();
|
|
1333
1345
|
const terminal = { name: 'result', operationId: result.operationId };
|
|
1334
1346
|
const target = this.#stableResultRoute(intent, result);
|
|
1335
1347
|
this.#resultAnchor = structuredClone(target);
|
|
@@ -1521,6 +1533,9 @@ export class TuiController {
|
|
|
1521
1533
|
this.#publish();
|
|
1522
1534
|
}
|
|
1523
1535
|
push(route, context) {
|
|
1536
|
+
if (this.#router.snapshot.current.route.name === 'result') {
|
|
1537
|
+
this.#invalidatePortableResultRecheck();
|
|
1538
|
+
}
|
|
1524
1539
|
this.#cancelReviewPreparation();
|
|
1525
1540
|
this.#cancelPortableRequest();
|
|
1526
1541
|
this.#cancelInstallPlacementRequest();
|
|
@@ -1709,26 +1724,86 @@ export class TuiController {
|
|
|
1709
1724
|
|| !this.dependencies.recheckPortableInstall) {
|
|
1710
1725
|
throw new TuiOperationBlockedError('portableRecheckUnavailable', '当前结果不能执行只读复查。');
|
|
1711
1726
|
}
|
|
1712
|
-
const
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1727
|
+
const currentResult = this.#result;
|
|
1728
|
+
if (currentResult.state !== 'succeeded' && currentResult.state !== 'partial') {
|
|
1729
|
+
throw new TuiOperationBlockedError('portableRecheckUnavailable', '当前结果不能执行只读复查。');
|
|
1730
|
+
}
|
|
1731
|
+
const previous = structuredClone(currentResult);
|
|
1732
|
+
const originalReceipt = structuredClone(this.#portableResultReceipt);
|
|
1733
|
+
const originalIntent = structuredClone(this.#portableResultIntent);
|
|
1734
|
+
const lifecycle = this.#portableResultLifecycle;
|
|
1735
|
+
if (this.#portableResultRecheck?.lifecycle === lifecycle
|
|
1736
|
+
&& this.#portableResultRecheck.operationId === previous.operationId) {
|
|
1737
|
+
return await this.#portableResultRecheck.promise;
|
|
1738
|
+
}
|
|
1739
|
+
const abort = new AbortController();
|
|
1740
|
+
const signal = AbortSignal.any([this.#abort.signal, abort.signal]);
|
|
1741
|
+
const isCurrent = () => !this.#disposed
|
|
1742
|
+
&& !this.#retiring
|
|
1743
|
+
&& !signal.aborted
|
|
1744
|
+
&& lifecycle === this.#portableResultLifecycle
|
|
1745
|
+
&& this.#router.snapshot.current.route.name === 'result'
|
|
1746
|
+
&& this.#result?.operationId === previous.operationId
|
|
1747
|
+
&& this.#result.operationRecordId === previous.operationRecordId;
|
|
1748
|
+
const promise = (async () => {
|
|
1749
|
+
let checked;
|
|
1750
|
+
try {
|
|
1751
|
+
checked = await this.#trackRead(this.dependencies.recheckPortableInstall(structuredClone(originalReceipt), signal));
|
|
1752
|
+
}
|
|
1753
|
+
catch (error) {
|
|
1754
|
+
if (!isCurrent())
|
|
1755
|
+
return cloneFrozen(originalReceipt);
|
|
1756
|
+
throw error;
|
|
1757
|
+
}
|
|
1758
|
+
if (!isCurrent())
|
|
1759
|
+
return cloneFrozen(originalReceipt);
|
|
1760
|
+
this.#portableResultReceipt = structuredClone(checked);
|
|
1761
|
+
const summary = operationResultSummary(originalIntent, checked);
|
|
1762
|
+
const verificationState = summary.portable?.verificationUnknown
|
|
1763
|
+
? 'unknown' : 'completed';
|
|
1764
|
+
const effects = previous.effects
|
|
1765
|
+
? { ...previous.effects, finalVerification: verificationState }
|
|
1766
|
+
: undefined;
|
|
1767
|
+
const updatedSummary = {
|
|
1720
1768
|
...summary,
|
|
1721
|
-
|
|
1722
|
-
? previous.summary.elapsedMs :
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1769
|
+
...(previous.summary.elapsedMs !== undefined
|
|
1770
|
+
? { elapsedMs: previous.summary.elapsedMs } : {}),
|
|
1771
|
+
...(previous.summary.diagnosticIds
|
|
1772
|
+
? { diagnosticIds: structuredClone(previous.summary.diagnosticIds) } : {}),
|
|
1773
|
+
...(effects ? { effects } : {}),
|
|
1774
|
+
};
|
|
1775
|
+
const updated = checked.status === 'succeeded'
|
|
1776
|
+
? { ...previous, state: 'succeeded', summary: updatedSummary, ...(effects ? { effects } : {}) }
|
|
1777
|
+
: { ...previous, state: 'partial', summary: updatedSummary, ...(effects ? { effects } : {}) };
|
|
1778
|
+
this.#result = updated;
|
|
1779
|
+
if (updated.operationRecordId) {
|
|
1780
|
+
const record = this.#operationHistory.get(updated.operationRecordId);
|
|
1781
|
+
if (record) {
|
|
1782
|
+
record.summary = {
|
|
1783
|
+
...record.summary,
|
|
1784
|
+
state: updated.state,
|
|
1785
|
+
code: updated.summary.code,
|
|
1786
|
+
message: updated.summary.message,
|
|
1787
|
+
effects: effects ?? record.summary.effects,
|
|
1788
|
+
};
|
|
1789
|
+
this.#operationHistory.record(record);
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
this.#publish();
|
|
1793
|
+
return cloneFrozen(checked);
|
|
1794
|
+
})();
|
|
1795
|
+
this.#portableResultRecheck = {
|
|
1796
|
+
lifecycle,
|
|
1797
|
+
operationId: previous.operationId,
|
|
1798
|
+
abort,
|
|
1799
|
+
promise,
|
|
1729
1800
|
};
|
|
1730
|
-
|
|
1731
|
-
|
|
1801
|
+
void promise.finally(() => {
|
|
1802
|
+
if (this.#portableResultRecheck?.promise === promise) {
|
|
1803
|
+
this.#portableResultRecheck = undefined;
|
|
1804
|
+
}
|
|
1805
|
+
}).catch(() => undefined);
|
|
1806
|
+
return await promise;
|
|
1732
1807
|
}
|
|
1733
1808
|
startPortableRetryReviewPreparation() {
|
|
1734
1809
|
this.#assertAcceptingActions();
|
|
@@ -1763,6 +1838,9 @@ export class TuiController {
|
|
|
1763
1838
|
this.#publish();
|
|
1764
1839
|
}
|
|
1765
1840
|
replace(route, context) {
|
|
1841
|
+
if (this.#router.snapshot.current.route.name === 'result') {
|
|
1842
|
+
this.#invalidatePortableResultRecheck();
|
|
1843
|
+
}
|
|
1766
1844
|
this.#cancelReviewPreparation();
|
|
1767
1845
|
this.#cancelPortableRequest();
|
|
1768
1846
|
this.#cancelInstallPlacementRequest();
|
|
@@ -1882,6 +1960,8 @@ export class TuiController {
|
|
|
1882
1960
|
}
|
|
1883
1961
|
back() {
|
|
1884
1962
|
const route = this.#router.snapshot.current.route;
|
|
1963
|
+
if (route.name === 'result')
|
|
1964
|
+
this.#invalidatePortableResultRecheck();
|
|
1885
1965
|
const activeFlow = this.#router.activeFlow();
|
|
1886
1966
|
this.#cancelReviewPreparation();
|
|
1887
1967
|
this.#cancelPortableRequest();
|
|
@@ -1925,6 +2005,7 @@ export class TuiController {
|
|
|
1925
2005
|
leaveResult(target) {
|
|
1926
2006
|
if (this.#router.snapshot.current.route.name !== 'result')
|
|
1927
2007
|
return;
|
|
2008
|
+
this.#invalidatePortableResultRecheck();
|
|
1928
2009
|
if (target?.name === 'home') {
|
|
1929
2010
|
this.#router.resetToRoot();
|
|
1930
2011
|
this.#portableDraft = undefined;
|
|
@@ -1973,6 +2054,7 @@ export class TuiController {
|
|
|
1973
2054
|
if (this.#router.snapshot.current.route.name !== 'result' || !result
|
|
1974
2055
|
|| !('returnRoute' in result) || !result.returnRoute)
|
|
1975
2056
|
return;
|
|
2057
|
+
this.#invalidatePortableResultRecheck();
|
|
1976
2058
|
const returnRoute = this.#normalizeRoute(result.returnRoute);
|
|
1977
2059
|
this.#router.back();
|
|
1978
2060
|
const kind = result.operationKind === 'configSave' || result.operationKind === 'configSaveBatch'
|
|
@@ -2024,6 +2106,7 @@ export class TuiController {
|
|
|
2024
2106
|
}
|
|
2025
2107
|
}
|
|
2026
2108
|
resetPortableFlowToPreview(pluginId, target, preserveDraft = false) {
|
|
2109
|
+
this.#invalidatePortableResultRecheck();
|
|
2027
2110
|
this.#cancelPortableRequest();
|
|
2028
2111
|
if (preserveDraft && !this.#portableDraft) {
|
|
2029
2112
|
this.#portableDraft = this.#recoverablePortableDraft;
|
|
@@ -2055,6 +2138,11 @@ export class TuiController {
|
|
|
2055
2138
|
this.#portableRequestAbort = undefined;
|
|
2056
2139
|
this.#portablePending = undefined;
|
|
2057
2140
|
}
|
|
2141
|
+
#invalidatePortableResultRecheck() {
|
|
2142
|
+
this.#portableResultLifecycle += 1;
|
|
2143
|
+
this.#portableResultRecheck?.abort.abort();
|
|
2144
|
+
this.#portableResultRecheck = undefined;
|
|
2145
|
+
}
|
|
2058
2146
|
#runPortableRequest(key, action) {
|
|
2059
2147
|
if (this.#portablePending?.key === key) {
|
|
2060
2148
|
return this.#portablePending.promise;
|
|
@@ -2766,6 +2854,8 @@ export class TuiController {
|
|
|
2766
2854
|
this.#ensureOperationFlow(intent);
|
|
2767
2855
|
const inheritedReturnRoute = this.#reviewPreparation?.returnRoute;
|
|
2768
2856
|
const current = this.#router.snapshot.current.route;
|
|
2857
|
+
if (current.name === 'result')
|
|
2858
|
+
this.#invalidatePortableResultRecheck();
|
|
2769
2859
|
const navigation = current.name === 'result' || current.name === 'reviewPreparing'
|
|
2770
2860
|
? 'replace' : 'push';
|
|
2771
2861
|
const resolvedReturnRoute = returnRoute
|
|
@@ -3836,6 +3926,12 @@ export class TuiController {
|
|
|
3836
3926
|
operationKind: intent.kind,
|
|
3837
3927
|
...(intent.kind === 'sourceMutation' ? { sourceAction: intent.action } : {}),
|
|
3838
3928
|
...('pluginId' in intent ? { pluginId: intent.pluginId } : {}),
|
|
3929
|
+
...(intent.kind === 'portableInstall' ? {
|
|
3930
|
+
portableIntent: {
|
|
3931
|
+
scope: intent.scope,
|
|
3932
|
+
agentMode: intent.requestedAgents === undefined ? 'automatic' : 'explicit',
|
|
3933
|
+
},
|
|
3934
|
+
} : {}),
|
|
3839
3935
|
...(intent.kind === 'pluginWrite' && intent.originIssue
|
|
3840
3936
|
? { originIssue: intent.originIssue }
|
|
3841
3937
|
: {}),
|
|
@@ -3845,6 +3941,7 @@ export class TuiController {
|
|
|
3845
3941
|
if (this.#disposed)
|
|
3846
3942
|
return;
|
|
3847
3943
|
this.#disposed = true;
|
|
3944
|
+
this.#invalidatePortableResultRecheck();
|
|
3848
3945
|
this.#cancelReviewPreparation();
|
|
3849
3946
|
this.#cancelPortableRequest();
|
|
3850
3947
|
this.#cancelInstallPlacementRequest();
|
|
@@ -3938,6 +4035,9 @@ function operationResultSummaryUnsafe(intent, execution) {
|
|
|
3938
4035
|
selectedSkills: receipt.selectedSkills.map((skill) => skill.name),
|
|
3939
4036
|
agentMode: receipt.agentMode,
|
|
3940
4037
|
requestedAgents: receipt.requestedAgents,
|
|
4038
|
+
...(receipt.attemptedTargets
|
|
4039
|
+
? { attemptedTargets: structuredClone(receipt.attemptedTargets) }
|
|
4040
|
+
: {}),
|
|
3941
4041
|
scope: receipt.scope,
|
|
3942
4042
|
materializationDigest: receipt.materializationDigest,
|
|
3943
4043
|
skillsCliVersion: receipt.skillsCliVersion,
|