@narumitw/pi-sync 0.57.10 → 0.57.12
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/CHANGELOG.md +14 -0
- package/README.md +32 -22
- package/dist/chunks/{agent-candidate-EYB35AGL.ts → agent-candidate-U2NU3GUX.ts} +11 -11
- package/dist/chunks/{agent-plan-KO43GTOR.ts → agent-plan-3YXDIJXO.ts} +25 -22
- package/dist/chunks/agent-plan-3YXDIJXO.ts.map +7 -0
- package/dist/chunks/{agent-refusal-retry-C2HQROTP.ts → agent-refusal-retry-476YGNU5.ts} +10 -10
- package/dist/chunks/{agent-runner-WMSCKSCB.ts → agent-runner-FCRV2Z75.ts} +11 -10
- package/dist/chunks/agent-runner-FCRV2Z75.ts.map +7 -0
- package/dist/chunks/{agent-store-UT52DS7B.ts → agent-store-7GINKTS7.ts} +8 -8
- package/dist/chunks/{agent-store-UT52DS7B.ts.map → agent-store-7GINKTS7.ts.map} +2 -2
- package/dist/chunks/{agent-sync-VM3TXWA3.ts → agent-sync-P6AWQXGK.ts} +6 -6
- package/dist/chunks/{chunk-JXWTEJS5.ts → chunk-45COPAK7.ts} +10 -3
- package/dist/chunks/chunk-45COPAK7.ts.map +7 -0
- package/dist/chunks/{chunk-DOJRPBQU.ts → chunk-5TSCBBPP.ts} +4 -4
- package/dist/chunks/{chunk-CDQGSZL3.ts → chunk-6LD5KX55.ts} +6 -6
- package/dist/chunks/{chunk-MDUORMCK.ts → chunk-6O3EDBRL.ts} +2 -2
- package/dist/chunks/{chunk-AAPAHANE.ts → chunk-7A35ZAVO.ts} +320 -219
- package/dist/chunks/chunk-7A35ZAVO.ts.map +7 -0
- package/dist/chunks/{chunk-STVQQ5KG.ts → chunk-7ZIYU5QS.ts} +6 -6
- package/dist/chunks/{chunk-AO6EDUA6.ts → chunk-AKMV47YC.ts} +3 -3
- package/dist/chunks/{chunk-66GAUVDL.ts → chunk-BEST45H2.ts} +6 -6
- package/dist/chunks/{chunk-DO55XUNU.ts → chunk-CBLTWXAU.ts} +15 -5
- package/dist/chunks/chunk-CBLTWXAU.ts.map +7 -0
- package/dist/chunks/{chunk-IMMMZUFC.ts → chunk-CQD2TJHE.ts} +7 -7
- package/dist/chunks/{chunk-IMMMZUFC.ts.map → chunk-CQD2TJHE.ts.map} +2 -2
- package/dist/chunks/{chunk-73MDIVYJ.ts → chunk-DN4IA7MR.ts} +6 -6
- package/dist/chunks/{chunk-PHANBTVM.ts → chunk-ESKOPQVB.ts} +4 -4
- package/dist/chunks/{chunk-YZ5BQNRZ.ts → chunk-FHE2DCA2.ts} +2 -2
- package/dist/chunks/{chunk-YZ5BQNRZ.ts.map → chunk-FHE2DCA2.ts.map} +2 -2
- package/dist/chunks/{chunk-MRIPZGPR.ts → chunk-FLHCOJCD.ts} +3 -3
- package/dist/chunks/{chunk-5WJQ6XOW.ts → chunk-GNYGNHFF.ts} +2 -2
- package/dist/chunks/{chunk-DFJGTVPX.ts → chunk-KYTT7KV4.ts} +2 -2
- package/dist/chunks/{chunk-UGSSZWQ6.ts → chunk-MKSMJPVA.ts} +2 -2
- package/dist/chunks/{chunk-2VSN3MFX.ts → chunk-MMQIEDZ6.ts} +33 -27
- package/dist/chunks/chunk-MMQIEDZ6.ts.map +7 -0
- package/dist/chunks/{chunk-RAMHGOX2.ts → chunk-OJARL2TG.ts} +4 -4
- package/dist/chunks/{chunk-BJXSCGQK.ts → chunk-OKPPZA4D.ts} +148 -89
- package/dist/chunks/chunk-OKPPZA4D.ts.map +7 -0
- package/dist/chunks/{chunk-RX3WGWVL.ts → chunk-OVBAW7KV.ts} +177 -130
- package/dist/chunks/chunk-OVBAW7KV.ts.map +7 -0
- package/dist/chunks/{chunk-U77DWNRH.ts → chunk-Q23JJW7E.ts} +3 -3
- package/dist/chunks/{chunk-NLWS55B6.ts → chunk-QPC5HT3A.ts} +2 -2
- package/dist/chunks/{chunk-NLWS55B6.ts.map → chunk-QPC5HT3A.ts.map} +1 -1
- package/dist/chunks/{chunk-4RLATUP4.ts → chunk-S5OCYVPS.ts} +7 -7
- package/dist/chunks/{chunk-4RLATUP4.ts.map → chunk-S5OCYVPS.ts.map} +2 -2
- package/dist/chunks/{chunk-QWV3XKNJ.ts → chunk-TIMWN2RH.ts} +5 -5
- package/dist/chunks/{chunk-Z5O2TLNF.ts → chunk-TZC7GDJE.ts} +7 -7
- package/dist/chunks/{chunk-UCD7TQDT.ts → chunk-U6GXGY5G.ts} +5 -5
- package/dist/chunks/{chunk-PWA3YN5Z.ts → chunk-XEODG2PE.ts} +3 -3
- package/dist/chunks/{chunk-TO2GMX3K.ts → chunk-XJHQPB3E.ts} +2 -2
- package/dist/chunks/{chunk-JY2RVOUL.ts → chunk-Y4UVXOLQ.ts} +5 -5
- package/dist/chunks/{chunk-ODF2M4RF.ts → chunk-ZC3IHFNM.ts} +8 -8
- package/dist/chunks/{chunk-ODF2M4RF.ts.map → chunk-ZC3IHFNM.ts.map} +2 -2
- package/dist/chunks/{chunk-M5IV3KL2.ts → chunk-ZDDBZH72.ts} +3 -3
- package/dist/chunks/{command-handler-FO6F2APH.ts → command-handler-VKLZBRLO.ts} +26 -21
- package/dist/chunks/command-handler-VKLZBRLO.ts.map +7 -0
- package/dist/chunks/{config-B37W7FXW.ts → config-HYG7G5EM.ts} +6 -4
- package/dist/chunks/{conflict-artifacts-6XGSSU5S.ts → conflict-artifacts-J6WSDCWP.ts} +12 -12
- package/dist/chunks/{conflict-review-BQSHSJB3.ts → conflict-review-GXA6Y7KY.ts} +23 -23
- package/dist/chunks/{continuous-record-4DQ2EAZS.ts → continuous-record-EPHGR2DU.ts} +6 -6
- package/dist/chunks/{continuous-sync-ZT3UEQLK.ts → continuous-sync-TTOSJCQU.ts} +18 -18
- package/dist/chunks/{file-selection-FBLKM25V.ts → file-selection-IELTXSGZ.ts} +6 -7
- package/dist/chunks/{file-selection-FBLKM25V.ts.map → file-selection-IELTXSGZ.ts.map} +1 -1
- package/dist/chunks/{git-backend-7PCWECRN.ts → git-backend-KHD36W27.ts} +6 -7
- package/dist/chunks/{git-backend-7PCWECRN.ts.map → git-backend-KHD36W27.ts.map} +1 -1
- package/dist/chunks/{local-fields-B6JWLPAE.ts → local-fields-JEKAPZKD.ts} +6 -7
- package/dist/chunks/manager-result-dispatcher-6W52NM7F.ts +32 -0
- package/dist/chunks/{manager-ui-DGRTG76I.ts → manager-ui-INVMAFEN.ts} +245 -224
- package/dist/chunks/manager-ui-INVMAFEN.ts.map +7 -0
- package/dist/chunks/{merge-baseline-store-HL3VLMAM.ts → merge-baseline-store-65GKUMXI.ts} +6 -6
- package/dist/chunks/{remote-selection-ui-OHMIQ32X.ts → remote-selection-ui-TD4C4W3J.ts} +16 -12
- package/dist/chunks/{s3-backend-CJXBEWWU.ts → s3-backend-L24UZ6IK.ts} +12 -10
- package/dist/chunks/s3-backend-L24UZ6IK.ts.map +7 -0
- package/dist/chunks/{setup-switch-66GWMBNH.ts → setup-switch-KLGESLQX.ts} +6 -6
- package/dist/chunks/{setup-wizard-OHZXJVQZ.ts → setup-wizard-ZQAK35BP.ts} +7 -7
- package/dist/chunks/{snapshot-VRHNAUUH.ts → snapshot-RGNDYT6A.ts} +5 -6
- package/dist/chunks/{snapshot-transaction-EUGA4VX6.ts → snapshot-transaction-26BQO36S.ts} +8 -8
- package/dist/chunks/{sync-inspection-4WFQEJOE.ts → sync-inspection-MOMLGUTD.ts} +11 -11
- package/dist/chunks/{sync-operations-X4AOXMBT.ts → sync-operations-TMGQHBF5.ts} +26 -26
- package/dist/chunks/{sync-operations-X4AOXMBT.ts.map → sync-operations-TMGQHBF5.ts.map} +2 -2
- package/dist/chunks/{sync-state-SWLSMK4G.ts → sync-state-7L4NT7W2.ts} +7 -8
- package/dist/chunks/{webdav-backend-2Q5ZEBST.ts → webdav-backend-3ZCACILP.ts} +7 -8
- package/dist/chunks/{webdav-backend-2Q5ZEBST.ts.map → webdav-backend-3ZCACILP.ts.map} +1 -1
- package/dist/index.ts +20 -20
- package/docs/agent-continuous-hardening.md +5 -5
- package/docs/agent-mode-verification.md +3 -3
- package/docs/agent-quality-verification.md +3 -3
- package/docs/continuous-sync-verification.md +2 -2
- package/docs/settings.md +9 -5
- package/docs/tui-contract.md +20 -3
- package/package.json +3 -3
- package/skills/configure-pi-sync/SKILL.md +3 -1
- package/skills/configure-pi-sync/references/configuration.md +56 -38
- package/src/backends/s3/s3-client.ts +8 -1
- package/src/commands/command-execution.ts +11 -6
- package/src/commands/command.ts +1 -1
- package/src/paths.ts +6 -1
- package/src/settings/config-file.ts +205 -118
- package/src/settings/config.ts +1 -1
- package/src/settings/settings-management.ts +15 -1
- package/src/settings/settings-store.ts +0 -14
- package/src/settings/settings-types.ts +1 -1
- package/src/snapshot/session-paths.ts +15 -2
- package/src/snapshot/snapshot-mutation-queues.ts +142 -0
- package/src/snapshot/snapshot-transaction.ts +122 -125
- package/src/sync/agent-candidate.ts +3 -3
- package/src/sync/agent-plan.ts +11 -8
- package/src/sync/agent-runner.ts +10 -9
- package/src/sync/agent-store.ts +1 -1
- package/src/sync/agent-sync.ts +2 -2
- package/src/sync/continuous-record.ts +1 -1
- package/src/sync/merge-apply.ts +6 -0
- package/src/sync/merged-sync.ts +4 -4
- package/src/sync/sync-mutations.ts +1 -1
- package/src/ui/agent-mode-setting.ts +6 -6
- package/src/ui/cancellable-operation.ts +36 -13
- package/src/ui/manager-state.ts +4 -2
- package/src/ui/manager-ui.ts +76 -24
- package/src/ui/remote-selection-ui.ts +131 -82
- package/src/ui/settings-ui.ts +21 -56
- package/src/ui/setup/setup-switcher.ts +2 -2
- package/src/ui/sync-setups-ui.ts +2 -2
- package/dist/chunks/agent-plan-KO43GTOR.ts.map +0 -7
- package/dist/chunks/agent-runner-WMSCKSCB.ts.map +0 -7
- package/dist/chunks/chunk-2VSN3MFX.ts.map +0 -7
- package/dist/chunks/chunk-AAPAHANE.ts.map +0 -7
- package/dist/chunks/chunk-BJXSCGQK.ts.map +0 -7
- package/dist/chunks/chunk-DO55XUNU.ts.map +0 -7
- package/dist/chunks/chunk-JXWTEJS5.ts.map +0 -7
- package/dist/chunks/chunk-RX3WGWVL.ts.map +0 -7
- package/dist/chunks/command-handler-FO6F2APH.ts.map +0 -7
- package/dist/chunks/manager-result-dispatcher-NODX3KKH.ts +0 -28
- package/dist/chunks/manager-ui-DGRTG76I.ts.map +0 -7
- package/dist/chunks/s3-backend-CJXBEWWU.ts.map +0 -7
- /package/dist/chunks/{agent-candidate-EYB35AGL.ts.map → agent-candidate-U2NU3GUX.ts.map} +0 -0
- /package/dist/chunks/{agent-refusal-retry-C2HQROTP.ts.map → agent-refusal-retry-476YGNU5.ts.map} +0 -0
- /package/dist/chunks/{agent-sync-VM3TXWA3.ts.map → agent-sync-P6AWQXGK.ts.map} +0 -0
- /package/dist/chunks/{chunk-DOJRPBQU.ts.map → chunk-5TSCBBPP.ts.map} +0 -0
- /package/dist/chunks/{chunk-CDQGSZL3.ts.map → chunk-6LD5KX55.ts.map} +0 -0
- /package/dist/chunks/{chunk-MDUORMCK.ts.map → chunk-6O3EDBRL.ts.map} +0 -0
- /package/dist/chunks/{chunk-STVQQ5KG.ts.map → chunk-7ZIYU5QS.ts.map} +0 -0
- /package/dist/chunks/{chunk-AO6EDUA6.ts.map → chunk-AKMV47YC.ts.map} +0 -0
- /package/dist/chunks/{chunk-66GAUVDL.ts.map → chunk-BEST45H2.ts.map} +0 -0
- /package/dist/chunks/{chunk-73MDIVYJ.ts.map → chunk-DN4IA7MR.ts.map} +0 -0
- /package/dist/chunks/{chunk-PHANBTVM.ts.map → chunk-ESKOPQVB.ts.map} +0 -0
- /package/dist/chunks/{chunk-MRIPZGPR.ts.map → chunk-FLHCOJCD.ts.map} +0 -0
- /package/dist/chunks/{chunk-5WJQ6XOW.ts.map → chunk-GNYGNHFF.ts.map} +0 -0
- /package/dist/chunks/{chunk-DFJGTVPX.ts.map → chunk-KYTT7KV4.ts.map} +0 -0
- /package/dist/chunks/{chunk-UGSSZWQ6.ts.map → chunk-MKSMJPVA.ts.map} +0 -0
- /package/dist/chunks/{chunk-RAMHGOX2.ts.map → chunk-OJARL2TG.ts.map} +0 -0
- /package/dist/chunks/{chunk-U77DWNRH.ts.map → chunk-Q23JJW7E.ts.map} +0 -0
- /package/dist/chunks/{chunk-QWV3XKNJ.ts.map → chunk-TIMWN2RH.ts.map} +0 -0
- /package/dist/chunks/{chunk-Z5O2TLNF.ts.map → chunk-TZC7GDJE.ts.map} +0 -0
- /package/dist/chunks/{chunk-UCD7TQDT.ts.map → chunk-U6GXGY5G.ts.map} +0 -0
- /package/dist/chunks/{chunk-PWA3YN5Z.ts.map → chunk-XEODG2PE.ts.map} +0 -0
- /package/dist/chunks/{chunk-TO2GMX3K.ts.map → chunk-XJHQPB3E.ts.map} +0 -0
- /package/dist/chunks/{chunk-JY2RVOUL.ts.map → chunk-Y4UVXOLQ.ts.map} +0 -0
- /package/dist/chunks/{chunk-M5IV3KL2.ts.map → chunk-ZDDBZH72.ts.map} +0 -0
- /package/dist/chunks/{config-B37W7FXW.ts.map → config-HYG7G5EM.ts.map} +0 -0
- /package/dist/chunks/{conflict-artifacts-6XGSSU5S.ts.map → conflict-artifacts-J6WSDCWP.ts.map} +0 -0
- /package/dist/chunks/{conflict-review-BQSHSJB3.ts.map → conflict-review-GXA6Y7KY.ts.map} +0 -0
- /package/dist/chunks/{continuous-record-4DQ2EAZS.ts.map → continuous-record-EPHGR2DU.ts.map} +0 -0
- /package/dist/chunks/{continuous-sync-ZT3UEQLK.ts.map → continuous-sync-TTOSJCQU.ts.map} +0 -0
- /package/dist/chunks/{local-fields-B6JWLPAE.ts.map → local-fields-JEKAPZKD.ts.map} +0 -0
- /package/dist/chunks/{manager-result-dispatcher-NODX3KKH.ts.map → manager-result-dispatcher-6W52NM7F.ts.map} +0 -0
- /package/dist/chunks/{merge-baseline-store-HL3VLMAM.ts.map → merge-baseline-store-65GKUMXI.ts.map} +0 -0
- /package/dist/chunks/{remote-selection-ui-OHMIQ32X.ts.map → remote-selection-ui-TD4C4W3J.ts.map} +0 -0
- /package/dist/chunks/{setup-switch-66GWMBNH.ts.map → setup-switch-KLGESLQX.ts.map} +0 -0
- /package/dist/chunks/{setup-wizard-OHZXJVQZ.ts.map → setup-wizard-ZQAK35BP.ts.map} +0 -0
- /package/dist/chunks/{snapshot-VRHNAUUH.ts.map → snapshot-RGNDYT6A.ts.map} +0 -0
- /package/dist/chunks/{snapshot-transaction-EUGA4VX6.ts.map → snapshot-transaction-26BQO36S.ts.map} +0 -0
- /package/dist/chunks/{sync-inspection-4WFQEJOE.ts.map → sync-inspection-MOMLGUTD.ts.map} +0 -0
- /package/dist/chunks/{sync-state-SWLSMK4G.ts.map → sync-state-7L4NT7W2.ts.map} +0 -0
|
@@ -2,14 +2,17 @@
|
|
|
2
2
|
// @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
|
|
3
3
|
import {
|
|
4
4
|
readSnapshotForHead
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-TIMWN2RH.ts";
|
|
6
6
|
import {
|
|
7
7
|
createSyncBackend
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-OJARL2TG.ts";
|
|
9
9
|
import {
|
|
10
10
|
SyncSetupReviewChangedError,
|
|
11
11
|
updateSyncSetup
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-45COPAK7.ts";
|
|
13
|
+
import {
|
|
14
|
+
captureMutationOwner
|
|
15
|
+
} from "./chunk-GNYGNHFF.ts";
|
|
13
16
|
import {
|
|
14
17
|
safeTerminalText
|
|
15
18
|
} from "./chunk-AMJRUXFT.ts";
|
|
@@ -21,9 +24,9 @@ import {
|
|
|
21
24
|
} from "./chunk-7D5SF7P3.ts";
|
|
22
25
|
import {
|
|
23
26
|
loadConfig,
|
|
24
|
-
|
|
27
|
+
syncCheckConfigFingerprint,
|
|
25
28
|
syncConfigReviewFingerprint
|
|
26
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-OVBAW7KV.ts";
|
|
27
30
|
import {
|
|
28
31
|
throwIfAborted
|
|
29
32
|
} from "./chunk-PWMWOJP4.ts";
|
|
@@ -31,7 +34,7 @@ import {
|
|
|
31
34
|
compareSyncInclude,
|
|
32
35
|
inspectRemoteSelection,
|
|
33
36
|
sameSyncInclude
|
|
34
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-KYTT7KV4.ts";
|
|
35
38
|
|
|
36
39
|
// src/ui/remote-selection-ui.ts
|
|
37
40
|
import { defineMenu, runMenu } from "@narumitw/pi-tui-kit";
|
|
@@ -41,21 +44,29 @@ import { BorderedLoader } from "@earendil-works/pi-coding-agent";
|
|
|
41
44
|
import { isKeyRelease, Key, matchesKey, truncateToWidth } from "@earendil-works/pi-tui";
|
|
42
45
|
import { formatInteractionHints, runCustomInteraction } from "@narumitw/pi-tui-kit";
|
|
43
46
|
async function runCancellableOperation(ctx, message, route, runRoute, options = {}) {
|
|
47
|
+
const result = await runCancellableTask(
|
|
48
|
+
ctx,
|
|
49
|
+
message,
|
|
50
|
+
(signal, onCommit, onDialog) => runRoute(route, signal, onCommit, options.target, onDialog),
|
|
51
|
+
options
|
|
52
|
+
);
|
|
53
|
+
return result.kind === "completed" ? result.value ?? { kind: "failed" } : result;
|
|
54
|
+
}
|
|
55
|
+
async function runCancellableTask(ctx, message, task, options = {}) {
|
|
44
56
|
const {
|
|
45
57
|
commitAware = false,
|
|
46
58
|
cancelAcrossDialogs = false,
|
|
47
59
|
cancelledMessage = "Check cancelled; no settings or files were changed.",
|
|
48
|
-
|
|
49
|
-
|
|
60
|
+
signal,
|
|
61
|
+
isCurrent = () => true
|
|
50
62
|
} = options;
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
}
|
|
63
|
+
if (signal?.aborted || !isCurrent()) return { kind: "closed" };
|
|
64
|
+
if (ctx.mode !== "tui") return { kind: "completed", value: await task(signal) };
|
|
54
65
|
let commitStarted = false;
|
|
55
|
-
let
|
|
66
|
+
let taskResult;
|
|
56
67
|
const interaction = await runCustomInteraction(ctx, {
|
|
57
68
|
signal,
|
|
58
|
-
isCurrent: () => !signal?.aborted,
|
|
69
|
+
isCurrent: () => !signal?.aborted && isCurrent(),
|
|
59
70
|
create: ({ tui, theme, keybindings, signal: interactionSignal, complete }) => {
|
|
60
71
|
const loader = new BorderedLoader(tui, theme, message, { cancellable: false });
|
|
61
72
|
const cancelHint = formatInteractionHints(keybindings, [
|
|
@@ -78,13 +89,11 @@ async function runCancellableOperation(ctx, message, route, runRoute, options =
|
|
|
78
89
|
if (activeDialogs > 0 && !matchesKey(data, Key.ctrl("c"))) return;
|
|
79
90
|
return cancel(data) ? { consume: true } : void 0;
|
|
80
91
|
}) : void 0;
|
|
81
|
-
let
|
|
92
|
+
let pendingTask;
|
|
82
93
|
try {
|
|
83
|
-
|
|
84
|
-
route,
|
|
94
|
+
pendingTask = task(
|
|
85
95
|
interactionSignal,
|
|
86
96
|
commitAware ? () => commitStarted = true : void 0,
|
|
87
|
-
target,
|
|
88
97
|
cancelAcrossDialogs ? (active) => {
|
|
89
98
|
activeDialogs += active ? 1 : -1;
|
|
90
99
|
} : void 0
|
|
@@ -94,9 +103,9 @@ async function runCancellableOperation(ctx, message, route, runRoute, options =
|
|
|
94
103
|
loader.dispose();
|
|
95
104
|
throw error;
|
|
96
105
|
}
|
|
97
|
-
const operation =
|
|
106
|
+
const operation = pendingTask.then(
|
|
98
107
|
(result) => {
|
|
99
|
-
|
|
108
|
+
taskResult = result;
|
|
100
109
|
complete({});
|
|
101
110
|
},
|
|
102
111
|
(error) => complete({ error })
|
|
@@ -130,7 +139,7 @@ async function runCancellableOperation(ctx, message, route, runRoute, options =
|
|
|
130
139
|
return { kind: "cancelled" };
|
|
131
140
|
}
|
|
132
141
|
if (interaction.value.error) throw interaction.value.error;
|
|
133
|
-
return
|
|
142
|
+
return { kind: "completed", value: taskResult };
|
|
134
143
|
}
|
|
135
144
|
function hasControlCharacter(value) {
|
|
136
145
|
return /[\u0000-\u001f\u007f-\u009f]/u.test(value);
|
|
@@ -138,11 +147,23 @@ function hasControlCharacter(value) {
|
|
|
138
147
|
|
|
139
148
|
// src/ui/remote-selection-ui.ts
|
|
140
149
|
async function showRemoteSelectionReview(ctx, setupName, signal, factory = createSyncBackend, options = {}) {
|
|
150
|
+
const validateOwner = captureMutationOwner(ctx, signal);
|
|
151
|
+
const isCurrent = () => isReviewOwnerCurrent(validateOwner);
|
|
141
152
|
try {
|
|
153
|
+
validateOwner();
|
|
142
154
|
let decision = options.decision;
|
|
143
155
|
if (!decision) {
|
|
144
|
-
const
|
|
145
|
-
|
|
156
|
+
const inspection = await runCancellableTask(
|
|
157
|
+
ctx,
|
|
158
|
+
"Checking remote content list\u2026",
|
|
159
|
+
(workSignal) => inspectConfiguredRemoteSelection(ctx, setupName, workSignal, factory, validateOwner),
|
|
160
|
+
{ signal, isCurrent, cancelledMessage: null }
|
|
161
|
+
);
|
|
162
|
+
if (!isCurrent()) return { kind: "stale" };
|
|
163
|
+
if (inspection.kind !== "completed") return { kind: inspection.kind === "cancelled" ? "back" : "closed" };
|
|
164
|
+
validateOwner();
|
|
165
|
+
const inspected = inspection.value;
|
|
166
|
+
if (!inspected) return { kind: "stale" };
|
|
146
167
|
if (inspected.kind === "empty" || inspected.state.kind !== "different") {
|
|
147
168
|
options.onSelectionResolved?.();
|
|
148
169
|
}
|
|
@@ -178,14 +199,24 @@ async function showRemoteSelectionReview(ctx, setupName, signal, factory = creat
|
|
|
178
199
|
options.runRoute,
|
|
179
200
|
signal,
|
|
180
201
|
factory,
|
|
181
|
-
options
|
|
202
|
+
options,
|
|
203
|
+
validateOwner
|
|
182
204
|
);
|
|
183
205
|
if (result.kind !== "refresh") return result;
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
206
|
+
const refresh = await runCancellableTask(
|
|
207
|
+
ctx,
|
|
208
|
+
"Refreshing remote content list\u2026",
|
|
209
|
+
(workSignal) => runWithOptionalStateAccess(
|
|
210
|
+
options,
|
|
211
|
+
() => inspectConfiguredRemoteSelection(ctx, currentDecision.setupName, workSignal, factory, validateOwner)
|
|
212
|
+
),
|
|
213
|
+
{ signal, isCurrent, cancelledMessage: null }
|
|
187
214
|
);
|
|
188
|
-
if (!
|
|
215
|
+
if (!isCurrent()) return { kind: "stale" };
|
|
216
|
+
if (refresh.kind !== "completed") return { kind: refresh.kind === "cancelled" ? "back" : "closed" };
|
|
217
|
+
validateOwner();
|
|
218
|
+
const refreshed = refresh.value;
|
|
219
|
+
if (!refreshed) return { kind: "stale" };
|
|
189
220
|
if (refreshed.kind === "empty") {
|
|
190
221
|
options.onSelectionResolved?.();
|
|
191
222
|
ctx.ui.notify("Remote storage no longer has a snapshot or synced-content list.", "warning");
|
|
@@ -202,16 +233,17 @@ async function showRemoteSelectionReview(ctx, setupName, signal, factory = creat
|
|
|
202
233
|
currentDecision = decisionFromState(refreshed.config, refreshed.state);
|
|
203
234
|
}
|
|
204
235
|
} catch (error) {
|
|
205
|
-
if (
|
|
236
|
+
if (!isCurrent()) return { kind: "stale" };
|
|
206
237
|
ctx.ui.notify(`Could not review synced content: ${errorMessage(error)}`, "error");
|
|
207
238
|
return { kind: "back" };
|
|
208
239
|
} finally {
|
|
209
|
-
setSyncStatus(ctx, void 0);
|
|
240
|
+
if (isCurrent()) setSyncStatus(ctx, void 0);
|
|
210
241
|
}
|
|
211
242
|
}
|
|
212
|
-
async function showSelectionDifference(ctx, initialDecision, origin, runRoute, sessionSignal, factory, options) {
|
|
243
|
+
async function showSelectionDifference(ctx, initialDecision, origin, runRoute, sessionSignal, factory, options, validateOwner) {
|
|
244
|
+
const isCurrent = () => isReviewOwnerCurrent(validateOwner);
|
|
213
245
|
let flowState = { decision: initialDecision, saved: false };
|
|
214
|
-
let
|
|
246
|
+
let continuationFingerprint;
|
|
215
247
|
let nextResult;
|
|
216
248
|
let refreshRequested = false;
|
|
217
249
|
const route = origin === "settings" ? "sync" : origin;
|
|
@@ -279,41 +311,58 @@ async function showSelectionDifference(ctx, initialDecision, origin, runRoute, s
|
|
|
279
311
|
adopt: async ({ state, signal: actionSignal }) => {
|
|
280
312
|
const signal = combineSignals(sessionSignal, actionSignal);
|
|
281
313
|
try {
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
314
|
+
const adoption = await runCancellableTask(
|
|
315
|
+
ctx,
|
|
316
|
+
"Checking and saving remote content list\u2026",
|
|
317
|
+
async (workSignal, _onCommit, onDialog) => {
|
|
318
|
+
const ownedSignal = workSignal ?? signal;
|
|
319
|
+
const currentConfig = await loadConfig(state.decision.setupName);
|
|
320
|
+
ownedSignal.throwIfAborted();
|
|
321
|
+
validateOwner();
|
|
322
|
+
assertLocalSelectionCurrent(currentConfig, state.decision);
|
|
323
|
+
if (!currentConfig.include.includes("sessions") && state.decision.remoteInclude.includes("sessions")) {
|
|
324
|
+
onDialog?.(true);
|
|
325
|
+
let acknowledged;
|
|
326
|
+
try {
|
|
327
|
+
acknowledged = await ctx.ui.confirm(
|
|
328
|
+
"Use a content list that includes session conversations?",
|
|
329
|
+
"Session JSONL may contain prompts, tool output, file paths, images, and secrets. This saves the list only; it does not pull files.",
|
|
330
|
+
{ signal: ownedSignal }
|
|
331
|
+
);
|
|
332
|
+
} finally {
|
|
333
|
+
onDialog?.(false);
|
|
334
|
+
}
|
|
335
|
+
ownedSignal.throwIfAborted();
|
|
336
|
+
validateOwner();
|
|
337
|
+
if (!acknowledged) return void 0;
|
|
338
|
+
}
|
|
339
|
+
return runWithOptionalStateAccess(options, async () => {
|
|
340
|
+
const loaded = await loadAdoptionReview(state.decision, ownedSignal, factory, validateOwner);
|
|
341
|
+
ownedSignal.throwIfAborted();
|
|
342
|
+
validateOwner();
|
|
343
|
+
await revalidateAndAdopt(loaded, state.decision, ownedSignal, validateOwner);
|
|
344
|
+
return loaded;
|
|
345
|
+
});
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
signal,
|
|
349
|
+
isCurrent,
|
|
350
|
+
cancelAcrossDialogs: true,
|
|
351
|
+
cancelledMessage: "Remote content-list adoption cancelled."
|
|
352
|
+
}
|
|
353
|
+
);
|
|
354
|
+
if (signal.aborted || adoption.kind === "closed") return { kind: "close" };
|
|
355
|
+
if (adoption.kind === "cancelled" || !adoption.value) return { kind: "stay" };
|
|
356
|
+
validateOwner();
|
|
301
357
|
options.onSelectionResolved?.();
|
|
302
|
-
|
|
303
|
-
...
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
automatic: review.config.automatic,
|
|
307
|
-
automaticTransfer: review.config.automaticTransfer,
|
|
308
|
-
agentMode: review.config.agentMode,
|
|
309
|
-
continuous: review.config.continuous,
|
|
310
|
-
onSwitch: review.config.onSwitch,
|
|
311
|
-
showStatus: review.config.showStatus
|
|
312
|
-
};
|
|
358
|
+
continuationFingerprint = syncCheckConfigFingerprint({
|
|
359
|
+
...adoption.value.config,
|
|
360
|
+
include: [...state.decision.remoteInclude]
|
|
361
|
+
});
|
|
313
362
|
flowState = { decision: state.decision, saved: true };
|
|
314
363
|
return { kind: "to", screen: "saved" };
|
|
315
364
|
} catch (error) {
|
|
316
|
-
if (signal.aborted) return { kind: "close" };
|
|
365
|
+
if (signal.aborted || !isCurrent()) return { kind: "close" };
|
|
317
366
|
if (isStaleReviewError(error)) {
|
|
318
367
|
ctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, "warning");
|
|
319
368
|
refreshRequested = true;
|
|
@@ -332,6 +381,7 @@ async function showSelectionDifference(ctx, initialDecision, origin, runRoute, s
|
|
|
332
381
|
try {
|
|
333
382
|
const latest = await loadConfig(state.decision.setupName);
|
|
334
383
|
if (signal.aborted) return { kind: "close" };
|
|
384
|
+
validateOwner();
|
|
335
385
|
assertLocalSelectionCurrent(latest, state.decision);
|
|
336
386
|
const result = await runCancellableOperation(
|
|
337
387
|
ctx,
|
|
@@ -347,7 +397,7 @@ async function showSelectionDifference(ctx, initialDecision, origin, runRoute, s
|
|
|
347
397
|
);
|
|
348
398
|
return handleNestedRouteResult(result, "push");
|
|
349
399
|
} catch (error) {
|
|
350
|
-
if (signal.aborted) return { kind: "close" };
|
|
400
|
+
if (signal.aborted || !isCurrent()) return { kind: "close" };
|
|
351
401
|
if (isStaleReviewError(error)) {
|
|
352
402
|
ctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, "warning");
|
|
353
403
|
refreshRequested = true;
|
|
@@ -358,12 +408,13 @@ async function showSelectionDifference(ctx, initialDecision, origin, runRoute, s
|
|
|
358
408
|
}
|
|
359
409
|
},
|
|
360
410
|
continue: async ({ state, signal: actionSignal }) => {
|
|
361
|
-
if (!runRoute || !
|
|
411
|
+
if (!runRoute || !continuationFingerprint) return { kind: "stay" };
|
|
362
412
|
const signal = combineSignals(sessionSignal, actionSignal);
|
|
363
413
|
try {
|
|
364
|
-
const latest = await
|
|
414
|
+
const latest = await loadConfig(state.decision.setupName);
|
|
365
415
|
if (signal.aborted) return { kind: "close" };
|
|
366
|
-
|
|
416
|
+
validateOwner();
|
|
417
|
+
if (syncCheckConfigFingerprint(latest) !== continuationFingerprint) {
|
|
367
418
|
throw new StaleRemoteSelectionReviewError(
|
|
368
419
|
`Sync setup \u201C${safeTerminalText(state.decision.setupName)}\u201D changed after the remote content list was saved.`
|
|
369
420
|
);
|
|
@@ -376,7 +427,7 @@ async function showSelectionDifference(ctx, initialDecision, origin, runRoute, s
|
|
|
376
427
|
});
|
|
377
428
|
return handleNestedRouteResult(result, route);
|
|
378
429
|
} catch (error) {
|
|
379
|
-
if (signal.aborted) return { kind: "close" };
|
|
430
|
+
if (signal.aborted || !isCurrent()) return { kind: "close" };
|
|
380
431
|
ctx.ui.notify(`Could not continue: ${errorMessage(error)}`, "error");
|
|
381
432
|
return { kind: "stay" };
|
|
382
433
|
}
|
|
@@ -405,10 +456,10 @@ async function showSelectionDifference(ctx, initialDecision, origin, runRoute, s
|
|
|
405
456
|
const menuResult = await runMenu(ctx, menu, {
|
|
406
457
|
getState: () => flowState,
|
|
407
458
|
signal: sessionSignal,
|
|
408
|
-
isCurrent
|
|
459
|
+
isCurrent,
|
|
409
460
|
onError: (_menuCtx, error) => ctx.ui.notify(errorMessage(error), "error")
|
|
410
461
|
});
|
|
411
|
-
if (
|
|
462
|
+
if (!isCurrent() || menuResult.kind === "stale") return { kind: "stale" };
|
|
412
463
|
if (refreshRequested) return { kind: "refresh" };
|
|
413
464
|
if (nextResult) return nextResult;
|
|
414
465
|
if (menuResult.kind === "closed") {
|
|
@@ -416,68 +467,71 @@ async function showSelectionDifference(ctx, initialDecision, origin, runRoute, s
|
|
|
416
467
|
}
|
|
417
468
|
return { kind: "closed" };
|
|
418
469
|
}
|
|
419
|
-
async function loadAdoptionReview(decision, signal, factory) {
|
|
470
|
+
async function loadAdoptionReview(decision, signal, factory, validateOwner) {
|
|
420
471
|
const config = await loadConfig(decision.setupName);
|
|
421
472
|
throwIfAborted(signal);
|
|
473
|
+
validateOwner();
|
|
422
474
|
assertLocalSelectionCurrent(config, decision);
|
|
423
|
-
const partial = await loadPartialConfig(decision.setupName);
|
|
424
|
-
throwIfAborted(signal);
|
|
425
|
-
if (!sameSyncInclude(partial.include, decision.localInclude)) {
|
|
426
|
-
throw new StaleRemoteSelectionReviewError(
|
|
427
|
-
`Sync setup \u201C${safeTerminalText(decision.setupName)}\u201D changed while the comparison was open.`
|
|
428
|
-
);
|
|
429
|
-
}
|
|
430
475
|
const backend = await factory(config);
|
|
431
476
|
throwIfAborted(signal);
|
|
477
|
+
validateOwner();
|
|
432
478
|
const reviewedHead = await backend.readHead(signal);
|
|
433
479
|
throwIfAborted(signal);
|
|
480
|
+
validateOwner();
|
|
434
481
|
if (!reviewedHead) {
|
|
435
482
|
throw new StaleRemoteSelectionReviewError("Remote storage changed while the comparison was open.");
|
|
436
483
|
}
|
|
437
484
|
const snapshot = await readSnapshotForHead(backend, reviewedHead, signal);
|
|
438
485
|
throwIfAborted(signal);
|
|
486
|
+
validateOwner();
|
|
439
487
|
const state = inspectRemoteSelection(config.include, snapshot);
|
|
440
488
|
if (state.kind !== "different" || !sameSyncInclude(state.include, decision.remoteInclude)) {
|
|
441
489
|
throw new StaleRemoteSelectionReviewError("Remote synced content changed while the comparison was open.");
|
|
442
490
|
}
|
|
443
|
-
return { config,
|
|
491
|
+
return { config, backend, reviewedHead };
|
|
444
492
|
}
|
|
445
|
-
async function revalidateAndAdopt(review, decision, signal) {
|
|
493
|
+
async function revalidateAndAdopt(review, decision, signal, validateOwner) {
|
|
446
494
|
const currentHead = await review.backend.readHead(signal);
|
|
447
495
|
throwIfAborted(signal);
|
|
496
|
+
validateOwner();
|
|
448
497
|
if (!currentHead || !review.backend.sameRevision(review.reviewedHead.revision, currentHead.revision)) {
|
|
449
498
|
throw new StaleRemoteSelectionReviewError("Remote storage changed while the comparison was open.");
|
|
450
499
|
}
|
|
451
500
|
const currentSnapshot = await readSnapshotForHead(review.backend, currentHead, signal);
|
|
452
501
|
throwIfAborted(signal);
|
|
502
|
+
validateOwner();
|
|
453
503
|
const currentState = inspectRemoteSelection(review.config.include, currentSnapshot);
|
|
454
504
|
if (currentState.kind !== "different" || !sameSyncInclude(currentState.include, decision.remoteInclude)) {
|
|
455
505
|
throw new StaleRemoteSelectionReviewError("Remote synced content changed while the comparison was open.");
|
|
456
506
|
}
|
|
457
507
|
await updateSyncSetup(
|
|
458
508
|
decision.setupName,
|
|
459
|
-
(setup) =>
|
|
460
|
-
|
|
461
|
-
sync: { ...setup.sync, include: [...decision.remoteInclude] }
|
|
462
|
-
}
|
|
509
|
+
(setup) => {
|
|
510
|
+
validateOwner();
|
|
511
|
+
return { ...setup, sync: { ...setup.sync, include: [...decision.remoteInclude] } };
|
|
512
|
+
},
|
|
463
513
|
{
|
|
464
|
-
|
|
514
|
+
expectedConfigFingerprint: syncCheckConfigFingerprint(review.config),
|
|
465
515
|
expectedInclude: decision.localInclude,
|
|
466
516
|
signal
|
|
467
517
|
}
|
|
468
518
|
);
|
|
469
519
|
}
|
|
470
|
-
async function inspectConfiguredRemoteSelection(ctx, setupName, signal, factory) {
|
|
520
|
+
async function inspectConfiguredRemoteSelection(ctx, setupName, signal, factory, validateOwner) {
|
|
471
521
|
const config = await loadConfig(setupName);
|
|
472
522
|
if (signal?.aborted) return void 0;
|
|
523
|
+
validateOwner();
|
|
473
524
|
setSyncStatus(ctx, `checking synced content for ${safeTerminalText(config.setupName)}`);
|
|
474
525
|
const backend = await factory(config);
|
|
475
526
|
if (signal?.aborted) return void 0;
|
|
527
|
+
validateOwner();
|
|
476
528
|
const head = await backend.readHead(signal);
|
|
477
529
|
if (signal?.aborted) return void 0;
|
|
530
|
+
validateOwner();
|
|
478
531
|
if (!head) return { kind: "empty", config };
|
|
479
532
|
const snapshot = await readSnapshotForHead(backend, head, signal);
|
|
480
533
|
if (signal?.aborted) return void 0;
|
|
534
|
+
validateOwner();
|
|
481
535
|
return {
|
|
482
536
|
kind: "selection",
|
|
483
537
|
config,
|
|
@@ -584,9 +638,6 @@ function assertLocalSelectionCurrent(config, decision) {
|
|
|
584
638
|
`Sync setup \u201C${safeTerminalText(config.setupName)}\u201D changed while the comparison was open.`
|
|
585
639
|
);
|
|
586
640
|
}
|
|
587
|
-
function sameContinuationReview(left, right) {
|
|
588
|
-
return left.setupName === right.setupName && left.connectionName === right.connectionName && left.storageKind === right.storageKind && left.storagePath === right.storagePath && left.bucket === right.bucket && left.branch === right.branch && Boolean(left.agentMode) === Boolean(right.agentMode) && Boolean(left.continuous) === Boolean(right.continuous) && sameSyncInclude(left.include, right.include);
|
|
589
|
-
}
|
|
590
641
|
function continueLabel(origin) {
|
|
591
642
|
if (origin === "pull") return "Continue Pull now\u2026";
|
|
592
643
|
if (origin === "push") return "Continue Push now\u2026";
|
|
@@ -617,6 +668,14 @@ function isStaleReviewError(error) {
|
|
|
617
668
|
function runWithOptionalStateAccess(options, task) {
|
|
618
669
|
return options.withStateAccess ? options.withStateAccess(task) : task();
|
|
619
670
|
}
|
|
671
|
+
function isReviewOwnerCurrent(validateOwner) {
|
|
672
|
+
try {
|
|
673
|
+
validateOwner();
|
|
674
|
+
return true;
|
|
675
|
+
} catch {
|
|
676
|
+
return false;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
620
679
|
function combineSignals(sessionSignal, actionSignal) {
|
|
621
680
|
return sessionSignal ? AbortSignal.any([sessionSignal, actionSignal]) : actionSignal;
|
|
622
681
|
}
|
|
@@ -625,4 +684,4 @@ export {
|
|
|
625
684
|
runCancellableOperation,
|
|
626
685
|
showRemoteSelectionReview
|
|
627
686
|
};
|
|
628
|
-
//# sourceMappingURL=chunk-
|
|
687
|
+
//# sourceMappingURL=chunk-OKPPZA4D.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/ui/remote-selection-ui.ts", "../../src/ui/cancellable-operation.ts"],
|
|
4
|
+
"sourcesContent": ["import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { defineMenu, runMenu } from \"@narumitw/pi-tui-kit\";\nimport { createSyncBackend, type SyncBackendFactory } from \"../backends/backend-factory.js\";\nimport type { RemoteHead, SyncBackend } from \"../backends/sync-backend.js\";\nimport { loadConfig, syncCheckConfigFingerprint, syncConfigReviewFingerprint } from \"../settings/config.js\";\nimport { SyncSetupReviewChangedError, updateSyncSetup } from \"../settings/settings-management.js\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport { readSnapshotForHead } from \"../sync/remote-snapshot.js\";\nimport { throwIfAborted } from \"../sync/signals.js\";\nimport { errorMessage } from \"../sync/sync-errors.js\";\nimport { captureMutationOwner } from \"../sync/sync-local.js\";\nimport {\n compareSyncInclude,\n inspectRemoteSelection,\n type RemoteSelectionDecision,\n type RemoteSelectionState,\n sameSyncInclude,\n} from \"../sync/sync-policy.js\";\nimport {\n type RunRoute,\n type RunRouteResult,\n runCancellableOperation,\n runCancellableTask,\n} from \"./cancellable-operation.js\";\nimport { setSyncStatus } from \"./sync-status.js\";\nimport { safeTerminalText } from \"./terminal-text.js\";\n\nexport type RemoteSelectionOrigin = \"settings\" | \"sync\" | \"pull\" | \"push\";\n\nexport interface RemoteSelectionReviewOptions {\n decision?: RemoteSelectionDecision;\n origin?: RemoteSelectionOrigin;\n runRoute?: RunRoute;\n cancelLabel?: string;\n /** The explicit mismatch is resolved or superseded; this does not imply file equality. */\n onSelectionResolved?: () => void;\n withStateAccess?: <T>(task: () => Promise<T>) => Promise<T>;\n}\n\nexport type RemoteSelectionReviewResult =\n | { kind: \"back\" }\n | { kind: \"closed\" }\n | { kind: \"done\" }\n | { kind: \"stale\" }\n | { kind: \"route-result\"; result: RunRouteResult; route: \"sync\" | \"pull\" | \"push\" };\n\nexport async function showRemoteSelectionReview(\n ctx: ExtensionContext,\n setupName?: string,\n signal?: AbortSignal,\n factory: SyncBackendFactory = createSyncBackend,\n options: RemoteSelectionReviewOptions = {},\n): Promise<RemoteSelectionReviewResult> {\n const validateOwner = captureMutationOwner(ctx, signal);\n const isCurrent = () => isReviewOwnerCurrent(validateOwner);\n try {\n validateOwner();\n let decision = options.decision;\n if (!decision) {\n const inspection = await runCancellableTask(\n ctx,\n \"Checking remote content list\u2026\",\n (workSignal) => inspectConfiguredRemoteSelection(ctx, setupName, workSignal, factory, validateOwner),\n { signal, isCurrent, cancelledMessage: null },\n );\n if (!isCurrent()) return { kind: \"stale\" };\n if (inspection.kind !== \"completed\") return { kind: inspection.kind === \"cancelled\" ? \"back\" : \"closed\" };\n validateOwner();\n const inspected = inspection.value;\n if (!inspected) return { kind: \"stale\" };\n // A successful fresh read can supersede an old explicit mismatch without\n // changing local settings. This is not user cancellation or proof of file equality.\n if (inspected.kind === \"empty\" || inspected.state.kind !== \"different\") {\n options.onSelectionResolved?.();\n }\n if (inspected.kind === \"empty\") {\n ctx.ui.notify(\"Remote storage has no snapshot or synced-content list yet.\", \"info\");\n return { kind: \"back\" };\n }\n if (inspected.state.kind === \"same\") {\n ctx.ui.notify(\"Remote synced content already matches this sync setup.\", \"info\");\n return { kind: \"back\" };\n }\n if (inspected.state.kind === \"legacy\") {\n if (ctx.mode !== \"tui\") {\n ctx.ui.notify(formatLegacySummary(inspected.config, inspected.state.discovered), \"info\");\n return { kind: \"back\" };\n }\n await showLegacyDiscovery(ctx, inspected.config, inspected.state.discovered, signal);\n return signal?.aborted ? { kind: \"stale\" } : { kind: \"back\" };\n }\n decision = decisionFromState(inspected.config, inspected.state);\n }\n\n if (ctx.mode !== \"tui\") {\n ctx.ui.notify(formatRemoteSelectionSummary(decision), \"warning\");\n return { kind: \"back\" };\n }\n\n let currentDecision = decision;\n for (;;) {\n if (signal?.aborted) return { kind: \"stale\" };\n const result = await showSelectionDifference(\n ctx,\n currentDecision,\n options.origin ?? \"settings\",\n options.runRoute,\n signal,\n factory,\n options,\n validateOwner,\n );\n if (result.kind !== \"refresh\") return result;\n const refresh = await runCancellableTask(\n ctx,\n \"Refreshing remote content list\u2026\",\n (workSignal) =>\n runWithOptionalStateAccess(options, () =>\n inspectConfiguredRemoteSelection(ctx, currentDecision.setupName, workSignal, factory, validateOwner),\n ),\n { signal, isCurrent, cancelledMessage: null },\n );\n if (!isCurrent()) return { kind: \"stale\" };\n if (refresh.kind !== \"completed\") return { kind: refresh.kind === \"cancelled\" ? \"back\" : \"closed\" };\n validateOwner();\n const refreshed = refresh.value;\n if (!refreshed) return { kind: \"stale\" };\n if (refreshed.kind === \"empty\") {\n options.onSelectionResolved?.();\n ctx.ui.notify(\"Remote storage no longer has a snapshot or synced-content list.\", \"warning\");\n return { kind: \"back\" };\n }\n if (refreshed.state.kind !== \"different\") {\n ctx.ui.notify(\n refreshed.state.kind === \"same\"\n ? \"Remote synced content now matches this sync setup.\"\n : \"The refreshed legacy snapshot has no authoritative synced-content list.\",\n \"info\",\n );\n options.onSelectionResolved?.();\n return { kind: \"done\" };\n }\n currentDecision = decisionFromState(refreshed.config, refreshed.state);\n }\n } catch (error) {\n if (!isCurrent()) return { kind: \"stale\" };\n ctx.ui.notify(`Could not review synced content: ${errorMessage(error)}`, \"error\");\n return { kind: \"back\" };\n } finally {\n if (isCurrent()) setSyncStatus(ctx, undefined);\n }\n}\n\ntype DifferenceFlowResult = RemoteSelectionReviewResult | { kind: \"refresh\" };\n\nasync function showSelectionDifference(\n ctx: ExtensionContext,\n initialDecision: RemoteSelectionDecision,\n origin: RemoteSelectionOrigin,\n runRoute: RunRoute | undefined,\n sessionSignal: AbortSignal | undefined,\n factory: SyncBackendFactory,\n options: Pick<RemoteSelectionReviewOptions, \"cancelLabel\" | \"onSelectionResolved\" | \"withStateAccess\">,\n validateOwner: () => void,\n): Promise<DifferenceFlowResult> {\n type Screen = \"choice\" | \"review\" | \"saved\";\n type Action = \"adopt\" | \"keep\" | \"cancel\" | \"continue\" | \"done\";\n interface FlowState {\n decision: RemoteSelectionDecision;\n saved: boolean;\n }\n const isCurrent = () => isReviewOwnerCurrent(validateOwner);\n let flowState: FlowState = { decision: initialDecision, saved: false };\n let continuationFingerprint: string | undefined;\n let nextResult: RemoteSelectionReviewResult | undefined;\n let refreshRequested = false;\n const route = origin === \"settings\" ? \"sync\" : origin;\n const menu = defineMenu<FlowState, Screen, Action, ExtensionContext>({\n start: \"choice\",\n screens: {\n choice: ({ state }) => ({\n kind: \"actions\",\n title: \"Synced content differs\",\n lines: selectionSummaryLines(state.decision),\n items: [\n {\n id: \"review\",\n label: \"Review all paths (recommended)\",\n description: \"Compare exact remote-only, device-only, and ordered lists.\",\n to: \"review\",\n },\n {\n id: \"adopt\",\n label: \"Use remote content list\",\n description: \"Save the reviewed list on this device without pulling files.\",\n action: \"adopt\",\n },\n {\n id: \"keep\",\n label: \"Keep this device's content list and update remote\u2026\",\n description: \"Open the existing exact force-push preview without skipping confirmation.\",\n action: \"keep\",\n },\n { id: \"cancel\", label: options.cancelLabel ?? \"Cancel\", action: \"cancel\" },\n ],\n hint: \"back\",\n }),\n review: ({ state }) => ({\n kind: \"review\",\n title: `Review synced content \u00B7 ${safeTerminalText(state.decision.setupName)}`,\n content: formatSelectionDifference(state.decision),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n hint: \"back\",\n }),\n saved: ({ state }) => ({\n kind: \"actions\",\n title: \"Remote content list saved\",\n lines: [\n `Sync setup: ${safeTerminalText(state.decision.setupName)}`,\n \"Only the included-content setting was saved.\",\n \"No files were pulled and sync state was not changed.\",\n ],\n items: [\n ...(runRoute\n ? [\n {\n id: \"continue\",\n label: continueLabel(origin),\n description: \"Start a fresh check and exact preview for this sync setup.\",\n action: \"continue\" as const,\n },\n ]\n : []),\n { id: \"done\", label: \"Done\", action: \"done\" },\n ],\n hint: \"close\",\n }),\n },\n actions: {\n adopt: async ({ state, signal: actionSignal }) => {\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const adoption = await runCancellableTask(\n ctx,\n \"Checking and saving remote content list\u2026\",\n async (workSignal, _onCommit, onDialog) => {\n const ownedSignal = workSignal ?? signal;\n const currentConfig = await loadConfig(state.decision.setupName);\n ownedSignal.throwIfAborted();\n validateOwner();\n assertLocalSelectionCurrent(currentConfig, state.decision);\n if (!currentConfig.include.includes(\"sessions\") && state.decision.remoteInclude.includes(\"sessions\")) {\n onDialog?.(true);\n let acknowledged: boolean;\n try {\n acknowledged = await ctx.ui.confirm(\n \"Use a content list that includes session conversations?\",\n \"Session JSONL may contain prompts, tool output, file paths, images, and secrets. This saves the list only; it does not pull files.\",\n { signal: ownedSignal },\n );\n } finally {\n onDialog?.(false);\n }\n ownedSignal.throwIfAborted();\n validateOwner();\n if (!acknowledged) return undefined;\n }\n return runWithOptionalStateAccess(options, async () => {\n const loaded = await loadAdoptionReview(state.decision, ownedSignal, factory, validateOwner);\n ownedSignal.throwIfAborted();\n validateOwner();\n await revalidateAndAdopt(loaded, state.decision, ownedSignal, validateOwner);\n return loaded;\n });\n },\n {\n signal,\n isCurrent,\n cancelAcrossDialogs: true,\n cancelledMessage: \"Remote content-list adoption cancelled.\",\n },\n );\n if (signal.aborted || adoption.kind === \"closed\") return { kind: \"close\" as const };\n if (adoption.kind === \"cancelled\" || !adoption.value) return { kind: \"stay\" as const };\n validateOwner();\n options.onSelectionResolved?.();\n continuationFingerprint = syncCheckConfigFingerprint({\n ...adoption.value.config,\n include: [...state.decision.remoteInclude],\n });\n flowState = { decision: state.decision, saved: true };\n return { kind: \"to\" as const, screen: \"saved\" as const };\n } catch (error) {\n if (signal.aborted || !isCurrent()) return { kind: \"close\" as const };\n if (isStaleReviewError(error)) {\n ctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, \"warning\");\n refreshRequested = true;\n return { kind: \"close\" as const };\n }\n ctx.ui.notify(`Could not save the remote content list: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n keep: async ({ state, signal: actionSignal }) => {\n if (!runRoute) {\n ctx.ui.notify(\"The reviewed update-remote route is unavailable.\", \"error\");\n return { kind: \"stay\" as const };\n }\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const latest = await loadConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n validateOwner();\n assertLocalSelectionCurrent(latest, state.decision);\n const result = await runCancellableOperation(\n ctx,\n \"Preparing this device's push preview\u2026\",\n \"push --force\",\n runRoute,\n {\n commitAware: true,\n cancelledMessage: \"Push preparation cancelled; no remote files were changed.\",\n target: state.decision.setupName,\n signal,\n },\n );\n return handleNestedRouteResult(result, \"push\");\n } catch (error) {\n if (signal.aborted || !isCurrent()) return { kind: \"close\" as const };\n if (isStaleReviewError(error)) {\n ctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, \"warning\");\n refreshRequested = true;\n return { kind: \"close\" as const };\n }\n ctx.ui.notify(`Could not prepare the remote update: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n continue: async ({ state, signal: actionSignal }) => {\n if (!runRoute || !continuationFingerprint) return { kind: \"stay\" as const };\n const signal = combineSignals(sessionSignal, actionSignal);\n try {\n const latest = await loadConfig(state.decision.setupName);\n if (signal.aborted) return { kind: \"close\" as const };\n validateOwner();\n if (syncCheckConfigFingerprint(latest) !== continuationFingerprint) {\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(state.decision.setupName)}\u201D changed after the remote content list was saved.`,\n );\n }\n const result = await runCancellableOperation(ctx, continueBusyLabel(origin), route, runRoute, {\n commitAware: true,\n cancelledMessage: continuationCancelledMessage(route),\n target: state.decision.setupName,\n signal,\n });\n return handleNestedRouteResult(result, route);\n } catch (error) {\n if (signal.aborted || !isCurrent()) return { kind: \"close\" as const };\n ctx.ui.notify(`Could not continue: ${errorMessage(error)}`, \"error\");\n return { kind: \"stay\" as const };\n }\n },\n cancel: async () => ({ kind: \"back\" }),\n done: async () => {\n nextResult = { kind: \"done\" };\n return { kind: \"close\" };\n },\n },\n });\n\n function handleNestedRouteResult(\n result: Awaited<ReturnType<typeof runCancellableOperation>>,\n nestedRoute: \"sync\" | \"pull\" | \"push\",\n ) {\n if (result.kind === \"completed\" && result.outcome === \"applied\") {\n options.onSelectionResolved?.();\n }\n if (result.kind === \"closed\") {\n nextResult = { kind: \"closed\" };\n return { kind: \"close\" as const };\n }\n if (\n result.kind === \"cancelled\" ||\n (result.kind === \"completed\" && result.outcome === \"cancelled\") ||\n result.kind === \"failed\"\n ) {\n return { kind: \"stay\" as const };\n }\n nextResult = { kind: \"route-result\", result, route: nestedRoute };\n return { kind: \"close\" as const };\n }\n\n const menuResult = await runMenu(ctx, menu, {\n getState: () => flowState,\n signal: sessionSignal,\n isCurrent,\n onError: (_menuCtx, error) => ctx.ui.notify(errorMessage(error), \"error\"),\n });\n if (!isCurrent() || menuResult.kind === \"stale\") return { kind: \"stale\" };\n if (refreshRequested) return { kind: \"refresh\" };\n if (nextResult) return nextResult;\n if (menuResult.kind === \"closed\") {\n return menuResult.reason === \"back\" ? { kind: \"back\" } : { kind: \"closed\" };\n }\n return { kind: \"closed\" };\n}\n\ninterface AdoptionReview {\n config: AnySyncConfig;\n backend: SyncBackend;\n reviewedHead: RemoteHead;\n}\n\nasync function loadAdoptionReview(\n decision: RemoteSelectionDecision,\n signal: AbortSignal,\n factory: SyncBackendFactory,\n validateOwner: () => void,\n): Promise<AdoptionReview> {\n const config = await loadConfig(decision.setupName);\n throwIfAborted(signal);\n validateOwner();\n assertLocalSelectionCurrent(config, decision);\n const backend = await factory(config);\n throwIfAborted(signal);\n validateOwner();\n const reviewedHead = await backend.readHead(signal);\n throwIfAborted(signal);\n validateOwner();\n if (!reviewedHead) {\n throw new StaleRemoteSelectionReviewError(\"Remote storage changed while the comparison was open.\");\n }\n const snapshot = await readSnapshotForHead(backend, reviewedHead, signal);\n throwIfAborted(signal);\n validateOwner();\n const state = inspectRemoteSelection(config.include, snapshot);\n if (state.kind !== \"different\" || !sameSyncInclude(state.include, decision.remoteInclude)) {\n throw new StaleRemoteSelectionReviewError(\"Remote synced content changed while the comparison was open.\");\n }\n return { config, backend, reviewedHead };\n}\n\nasync function revalidateAndAdopt(\n review: AdoptionReview,\n decision: RemoteSelectionDecision,\n signal: AbortSignal,\n validateOwner: () => void,\n) {\n const currentHead = await review.backend.readHead(signal);\n throwIfAborted(signal);\n validateOwner();\n if (!currentHead || !review.backend.sameRevision(review.reviewedHead.revision, currentHead.revision)) {\n throw new StaleRemoteSelectionReviewError(\"Remote storage changed while the comparison was open.\");\n }\n const currentSnapshot = await readSnapshotForHead(review.backend, currentHead, signal);\n throwIfAborted(signal);\n validateOwner();\n const currentState = inspectRemoteSelection(review.config.include, currentSnapshot);\n if (currentState.kind !== \"different\" || !sameSyncInclude(currentState.include, decision.remoteInclude)) {\n throw new StaleRemoteSelectionReviewError(\"Remote synced content changed while the comparison was open.\");\n }\n await updateSyncSetup(\n decision.setupName,\n (setup) => {\n validateOwner();\n return { ...setup, sync: { ...setup.sync, include: [...decision.remoteInclude] } };\n },\n {\n expectedConfigFingerprint: syncCheckConfigFingerprint(review.config),\n expectedInclude: decision.localInclude,\n signal,\n },\n );\n}\n\nasync function inspectConfiguredRemoteSelection(\n ctx: ExtensionContext,\n setupName: string | undefined,\n signal: AbortSignal | undefined,\n factory: SyncBackendFactory,\n validateOwner: () => void,\n): Promise<\n | { kind: \"empty\"; config: AnySyncConfig }\n | { kind: \"selection\"; config: AnySyncConfig; state: RemoteSelectionState }\n | undefined\n> {\n const config = await loadConfig(setupName);\n if (signal?.aborted) return undefined;\n validateOwner();\n setSyncStatus(ctx, `checking synced content for ${safeTerminalText(config.setupName)}`);\n const backend = await factory(config);\n if (signal?.aborted) return undefined;\n validateOwner();\n const head = await backend.readHead(signal);\n if (signal?.aborted) return undefined;\n validateOwner();\n if (!head) return { kind: \"empty\", config };\n const snapshot = await readSnapshotForHead(backend, head, signal);\n if (signal?.aborted) return undefined;\n validateOwner();\n return {\n kind: \"selection\",\n config,\n state: inspectRemoteSelection(config.include, snapshot),\n };\n}\n\nasync function showLegacyDiscovery(\n ctx: ExtensionContext,\n config: AnySyncConfig,\n discovered: string[],\n signal?: AbortSignal,\n) {\n const menu = defineMenu<undefined, \"choice\" | \"review\", \"back\", ExtensionContext>({\n start: \"choice\",\n screens: {\n choice: () => ({\n kind: \"actions\",\n title: `Compare synced content \u00B7 ${safeTerminalText(config.setupName)}`,\n lines: [\n \"This legacy snapshot has no portable synced-content list.\",\n \"Discovered paths are partial and read-only; preserved files may not have been selected.\",\n ],\n items: [\n { id: \"review\", label: \"Review discovered paths\", to: \"review\" },\n { id: \"back\", label: \"Back\", action: \"back\" },\n ],\n hint: \"close\",\n }),\n review: () => ({\n kind: \"review\",\n title: \"Partial discovery from legacy snapshot\",\n content: [\n \"Partial discovery only \u2014 not an authoritative selection.\",\n \"\",\n ...(discovered.length > 0\n ? discovered.map((item) => `Discovered: ${safeTerminalText(item)}`)\n : [\"No safe paths were discovered.\"]),\n \"\",\n \"Use Add custom path\u2026 in the local Included Content editor if needed.\",\n ].join(\"\\n\"),\n format: { kind: \"text\" },\n viewportSize: \"adaptive\",\n hint: \"back\",\n }),\n },\n actions: { back: async () => ({ kind: \"close\" }) },\n });\n await runMenu(ctx, menu, {\n getState: () => undefined,\n signal,\n isCurrent: () => !signal?.aborted,\n });\n}\n\nfunction selectionSummaryLines(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n `Sync setup: ${safeTerminalText(decision.setupName)}`,\n \"Nothing changed. Review both lists before choosing what happens next.\",\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\"Only the ordering differs; membership is the same.\"]\n : [`Remote-only paths: ${comparison.remoteOnly.length} \u00B7 Device-only paths: ${comparison.localOnly.length}`]),\n ];\n}\n\nfunction formatSelectionDifference(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\"Only ordering differs; both lists contain the same paths.\", \"\"]\n : []),\n \"Remote-only paths:\",\n ...(comparison.remoteOnly.length > 0\n ? comparison.remoteOnly.map((item) => `+ ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Device-only paths:\",\n ...(comparison.localOnly.length > 0\n ? comparison.localOnly.map((item) => `- ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Remote ordered list:\",\n ...(decision.remoteInclude.length > 0\n ? decision.remoteInclude.map((item, index) => `${index + 1}. ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"This device's ordered list:\",\n ...(decision.localInclude.length > 0\n ? decision.localInclude.map((item, index) => `${index + 1}. ${safeTerminalText(item)}`)\n : [\"(none)\"]),\n \"\",\n \"Using the remote list saves settings only and does not pull files.\",\n ].join(\"\\n\");\n}\n\nfunction formatRemoteSelectionSummary(decision: RemoteSelectionDecision) {\n const comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n return [\n `Synced content for \u201C${safeTerminalText(decision.setupName)}\u201D differs from this device.`,\n `Remote-only: ${safeList(comparison.remoteOnly)}`,\n `Device-only: ${safeList(comparison.localOnly)}`,\n ...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n ? [\n \"Only ordering differs.\",\n `Remote order: ${safeList(decision.remoteInclude)}`,\n `Device order: ${safeList(decision.localInclude)}`,\n ]\n : []),\n \"Run /sync in TUI to choose a content list; RPC review is read-only.\",\n ].join(\"\\n\");\n}\n\nfunction formatLegacySummary(config: AnySyncConfig, discovered: readonly string[]) {\n return `Remote snapshot for \u201C${safeTerminalText(config.setupName)}\u201D has no portable synced-content list; ${discovered.length} safe path${discovered.length === 1 ? \" was\" : \"s were\"} discovered, but the result is partial and read-only.`;\n}\n\nfunction decisionFromState(\n config: AnySyncConfig,\n state: Extract<RemoteSelectionState, { kind: \"different\" }>,\n): RemoteSelectionDecision {\n return {\n setupName: config.setupName,\n configIdentity: syncConfigReviewFingerprint(config),\n localInclude: [...config.include],\n remoteInclude: [...state.include],\n };\n}\n\nfunction assertLocalSelectionCurrent(config: AnySyncConfig, decision: RemoteSelectionDecision) {\n if (\n syncConfigReviewFingerprint(config) === decision.configIdentity &&\n sameSyncInclude(config.include, decision.localInclude)\n ) {\n return;\n }\n throw new StaleRemoteSelectionReviewError(\n `Sync setup \u201C${safeTerminalText(config.setupName)}\u201D changed while the comparison was open.`,\n );\n}\n\nfunction continueLabel(origin: RemoteSelectionOrigin) {\n if (origin === \"pull\") return \"Continue Pull now\u2026\";\n if (origin === \"push\") return \"Continue Push now\u2026\";\n return \"Continue Sync now\u2026\";\n}\n\nfunction continueBusyLabel(origin: RemoteSelectionOrigin) {\n if (origin === \"pull\") return \"Checking remote changes\u2026\";\n if (origin === \"push\") return \"Preparing push preview\u2026\";\n return \"Checking current sync setup\u2026\";\n}\n\nfunction continuationCancelledMessage(route: \"sync\" | \"pull\" | \"push\") {\n if (route === \"pull\") return \"Pull check cancelled; no local files were changed.\";\n if (route === \"push\") return \"Push preparation cancelled; no remote files were changed.\";\n return \"Sync check cancelled; no settings or files were changed.\";\n}\n\nfunction safeList(values: readonly string[]) {\n return values.length > 0 ? values.map(safeTerminalText).join(\", \") : \"none\";\n}\n\nclass StaleRemoteSelectionReviewError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"StaleRemoteSelectionReviewError\";\n }\n}\n\nfunction isStaleReviewError(error: unknown) {\n return error instanceof StaleRemoteSelectionReviewError || error instanceof SyncSetupReviewChangedError;\n}\n\nfunction runWithOptionalStateAccess<T>(\n options: Pick<RemoteSelectionReviewOptions, \"withStateAccess\">,\n task: () => Promise<T>,\n) {\n return options.withStateAccess ? options.withStateAccess(task) : task();\n}\n\nfunction isReviewOwnerCurrent(validateOwner: () => void) {\n try {\n validateOwner();\n return true;\n } catch {\n return false;\n }\n}\n\nfunction combineSignals(sessionSignal: AbortSignal | undefined, actionSignal: AbortSignal) {\n return sessionSignal ? AbortSignal.any([sessionSignal, actionSignal]) : actionSignal;\n}\n", "import { BorderedLoader, type ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { isKeyRelease, Key, matchesKey, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { formatInteractionHints, runCustomInteraction } from \"@narumitw/pi-tui-kit\";\nimport type { SetupPullOutcome } from \"../sync/setup-switch.js\";\nimport type { SyncDecision } from \"../sync/sync-decision.js\";\nimport type { RemoteSelectionDecision } from \"../sync/sync-policy.js\";\n\nexport type RunRouteResult =\n | { kind: \"completed\"; outcome?: SetupPullOutcome }\n | { kind: \"decision-required\"; decision: SyncDecision }\n | { kind: \"remote-selection-required\"; decision: RemoteSelectionDecision }\n | { kind: \"failed\" };\n\nexport type RunRoute = (\n route: string,\n signal?: AbortSignal,\n onCommit?: () => void,\n target?: string,\n onDialog?: (active: boolean) => void,\n retryRefusal?: boolean,\n) => Promise<RunRouteResult | undefined>;\n\nexport type CancellableOperationResult = RunRouteResult | { kind: \"closed\" } | { kind: \"cancelled\" };\n\ninterface CancellableOperationOptions {\n commitAware?: boolean;\n cancelAcrossDialogs?: boolean;\n cancelledMessage?: string | null;\n target?: string;\n signal?: AbortSignal;\n isCurrent?: () => boolean;\n}\n\nexport async function runCancellableOperation(\n ctx: ExtensionContext,\n message: string,\n route: string,\n runRoute: RunRoute,\n options: CancellableOperationOptions = {},\n): Promise<CancellableOperationResult> {\n const result = await runCancellableTask(\n ctx,\n message,\n (signal, onCommit, onDialog) => runRoute(route, signal, onCommit, options.target, onDialog),\n options,\n );\n return result.kind === \"completed\" ? (result.value ?? { kind: \"failed\" }) : result;\n}\n\nexport type CancellableTaskResult<Value> =\n | { kind: \"completed\"; value: Value }\n | { kind: \"closed\" }\n | { kind: \"cancelled\" };\n\n/** Keep non-route work under the same cancellation and drain owner as transfers. */\nexport async function runCancellableTask<Value>(\n ctx: ExtensionContext,\n message: string,\n task: (\n signal: AbortSignal | undefined,\n onCommit?: () => void,\n onDialog?: (active: boolean) => void,\n ) => Promise<Value>,\n options: Omit<CancellableOperationOptions, \"target\"> = {},\n): Promise<CancellableTaskResult<Value>> {\n const {\n commitAware = false,\n cancelAcrossDialogs = false,\n cancelledMessage = \"Check cancelled; no settings or files were changed.\",\n signal,\n isCurrent = () => true,\n } = options;\n if (signal?.aborted || !isCurrent()) return { kind: \"closed\" };\n if (ctx.mode !== \"tui\") return { kind: \"completed\", value: await task(signal) };\n let commitStarted = false;\n let taskResult!: Value;\n const interaction = await runCustomInteraction<{ cancelled?: boolean; error?: unknown }, ExtensionContext>(ctx, {\n signal,\n isCurrent: () => !signal?.aborted && isCurrent(),\n create: ({ tui, theme, keybindings, signal: interactionSignal, complete }) => {\n const loader = new BorderedLoader(tui, theme, message, { cancellable: false });\n const cancelHint = formatInteractionHints(keybindings, [\n {\n keys: [...keybindings.getKeys(\"tui.select.cancel\").filter((key) => !hasControlCharacter(key)), \"ctrl+c\"],\n label: \"cancel\",\n },\n ]);\n const cancel = (data: string) => {\n // Raw terminal listeners run before Pi filters Kitty key releases.\n if (isKeyRelease(data)) return false;\n if (!matchesKey(data, Key.ctrl(\"c\")) && !keybindings.matches(data, \"tui.select.cancel\")) return false;\n if (commitStarted) {\n ctx.ui.notify(\"Applying or publishing has started and cannot be cancelled safely.\", \"warning\");\n } else complete({ cancelled: true });\n return true;\n };\n // Pi dialogs replace this loader and restore the normal editor. Defer\n // ordinary keys while they are open; retain raw cancellation afterward.\n // Ctrl+C remains the root flow's hard-cancel path regardless of focus.\n let activeDialogs = 0;\n const unsubscribe = cancelAcrossDialogs\n ? ctx.ui.onTerminalInput((data) => {\n if (isKeyRelease(data)) return;\n if (activeDialogs > 0 && !matchesKey(data, Key.ctrl(\"c\"))) return;\n return cancel(data) ? { consume: true } : undefined;\n })\n : undefined;\n let pendingTask: Promise<Value>;\n try {\n pendingTask = task(\n interactionSignal,\n commitAware ? () => (commitStarted = true) : undefined,\n cancelAcrossDialogs\n ? (active) => {\n activeDialogs += active ? 1 : -1;\n }\n : undefined,\n );\n } catch (error) {\n unsubscribe?.();\n loader.dispose();\n throw error;\n }\n const operation = pendingTask.then(\n (result) => {\n taskResult = result;\n complete({});\n },\n (error: unknown) => complete({ error }),\n );\n return {\n render(width: number) {\n if (width <= 0) return [];\n const safeWidth = Math.max(1, width);\n const lines = loader.render(safeWidth);\n const bottomBorder = lines.at(-1);\n return [\n ...lines.slice(0, -1),\n truncateToWidth(theme.fg(\"dim\", cancelHint), safeWidth, \"\"),\n ...(bottomBorder === undefined ? [] : [bottomBorder]),\n ];\n },\n invalidate: () => loader.invalidate(),\n handleInput: cancel,\n dispose() {\n unsubscribe?.();\n loader.dispose();\n },\n waitForPending: () => operation,\n };\n },\n });\n if (interaction.kind === \"error\") throw interaction.error;\n if (interaction.kind !== \"completed\") return { kind: \"closed\" };\n if (interaction.value.cancelled) {\n if (cancelledMessage) ctx.ui.notify(cancelledMessage, \"info\");\n return { kind: \"cancelled\" };\n }\n if (interaction.value.error) throw interaction.value.error;\n return { kind: \"completed\", value: taskResult };\n}\n\nfunction hasControlCharacter(value: string) {\n // biome-ignore lint/suspicious/noControlCharactersInRegex: Unsafe key labels must be omitted.\n return /[\\u0000-\\u001f\\u007f-\\u009f]/u.test(value);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|