@narumitw/pi-sync 0.49.5 → 0.49.8
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/README.md +58 -28
- package/package.json +2 -2
- package/src/cancellable-operation.ts +8 -3
- package/src/config.ts +4 -0
- package/src/index.ts +1 -1
- package/src/manager-attention.ts +81 -0
- package/src/manager-result-dispatcher.ts +93 -0
- package/src/manager-state.ts +50 -3
- package/src/manager-ui.ts +70 -53
- package/src/remote-selection-ui.ts +541 -142
- package/src/remote-snapshot.ts +3 -2
- package/src/settings-management.ts +9 -2
- package/src/settings-ui.ts +21 -5
- package/src/setup-switch.ts +3 -2
- package/src/snapshot-paths.ts +13 -0
- package/src/snapshot-transaction.ts +1 -1
- package/src/snapshot.ts +2 -12
- package/src/sync-attention.ts +100 -0
- package/src/sync-decision.ts +5 -13
- package/src/sync-errors.ts +23 -0
- package/src/sync-extension.ts +765 -0
- package/src/sync-format.ts +3 -4
- package/src/sync-operations.ts +4 -2
- package/src/sync-policy.ts +63 -4
- package/src/sync-resolution-ui.ts +19 -4
- package/src/sync.ts +1 -512
package/src/manager-ui.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { type ActionMenuItem, defineMenu, runMenu } from "@narumitw/pi-tui-kit";
|
|
3
|
-
import {
|
|
4
|
-
type CancellableOperationResult,
|
|
5
|
-
type RunRoute,
|
|
6
|
-
runCancellableOperation,
|
|
7
|
-
} from "./cancellable-operation.js";
|
|
3
|
+
import { type RunRoute, runCancellableOperation } from "./cancellable-operation.js";
|
|
8
4
|
import { setSyncSetupCompletions } from "./command.js";
|
|
9
5
|
import {
|
|
10
6
|
configuredSyncSetupNames,
|
|
@@ -18,6 +14,12 @@ import {
|
|
|
18
14
|
} from "./config.js";
|
|
19
15
|
import { showAddGitTarget, showEditGitTarget, showGitSetup } from "./git-ui.js";
|
|
20
16
|
import { inspectLock, isStaleLock } from "./lock.js";
|
|
17
|
+
import {
|
|
18
|
+
attentionMainMenuItems,
|
|
19
|
+
blockedSyncMenuItem,
|
|
20
|
+
type SyncManagerAttentionOptions,
|
|
21
|
+
showManagerAttention,
|
|
22
|
+
} from "./manager-attention.js";
|
|
21
23
|
import {
|
|
22
24
|
errorMessage,
|
|
23
25
|
ownRecord,
|
|
@@ -25,6 +27,7 @@ import {
|
|
|
25
27
|
requiredInput,
|
|
26
28
|
safeTerminalText,
|
|
27
29
|
} from "./manager-helpers.js";
|
|
30
|
+
import { dispatchManagerResult } from "./manager-result-dispatcher.js";
|
|
28
31
|
import { backendStorageDescription, describeManagerState } from "./manager-state.js";
|
|
29
32
|
import { chooseS3Credentials } from "./s3-credentials-ui.js";
|
|
30
33
|
import {
|
|
@@ -37,7 +40,6 @@ import { showSyncSettings } from "./settings-ui.js";
|
|
|
37
40
|
import { useSyncSetup } from "./setup-switch.js";
|
|
38
41
|
import { showAddStorageConnection, showStorageConnections } from "./storage-connections-ui.js";
|
|
39
42
|
import { DEFAULT_SYNC_INCLUDE, syncIncludeSelection } from "./sync-policy.js";
|
|
40
|
-
import { showSyncResolution } from "./sync-resolution-ui.js";
|
|
41
43
|
import { showSyncSetups } from "./sync-setups-ui.js";
|
|
42
44
|
import type { AnySyncConfig } from "./types.js";
|
|
43
45
|
import { showAddWebDavTarget, showEditWebDavTarget, showWebDavSetup } from "./webdav-ui.js";
|
|
@@ -46,6 +48,7 @@ export async function showSyncManager(
|
|
|
46
48
|
ctx: ExtensionCommandContext,
|
|
47
49
|
runRoute: RunRoute,
|
|
48
50
|
sessionSignal?: AbortSignal,
|
|
51
|
+
options: SyncManagerAttentionOptions = {},
|
|
49
52
|
): Promise<void> {
|
|
50
53
|
if (!ctx.hasUI) {
|
|
51
54
|
await runRoute("help");
|
|
@@ -53,6 +56,7 @@ export async function showSyncManager(
|
|
|
53
56
|
}
|
|
54
57
|
type Screen = "main" | "more" | "recovery";
|
|
55
58
|
type Action =
|
|
59
|
+
| "review-attention"
|
|
56
60
|
| "sync"
|
|
57
61
|
| "switch"
|
|
58
62
|
| "diff"
|
|
@@ -78,7 +82,12 @@ export async function showSyncManager(
|
|
|
78
82
|
kind: "actions",
|
|
79
83
|
title: "Manage sync",
|
|
80
84
|
lines: state.manager.title.split("\n").slice(1),
|
|
81
|
-
items:
|
|
85
|
+
items: [
|
|
86
|
+
...attentionMainMenuItems(state.manager),
|
|
87
|
+
...state.manager.actions.map(
|
|
88
|
+
(label) => blockedSyncMenuItem(label, state.manager) ?? syncMainMenuItem(label),
|
|
89
|
+
),
|
|
90
|
+
],
|
|
82
91
|
hint: "close",
|
|
83
92
|
}),
|
|
84
93
|
more: () => ({
|
|
@@ -114,7 +123,28 @@ export async function showSyncManager(
|
|
|
114
123
|
}),
|
|
115
124
|
},
|
|
116
125
|
actions: {
|
|
126
|
+
"review-attention": async () => {
|
|
127
|
+
const attention = options.getAttention?.();
|
|
128
|
+
if (!attention) return { kind: "stay" };
|
|
129
|
+
const disposition = await showManagerAttention(
|
|
130
|
+
ctx,
|
|
131
|
+
attention,
|
|
132
|
+
runRoute,
|
|
133
|
+
sessionSignal,
|
|
134
|
+
() => options.onSelectionResolved?.(attention),
|
|
135
|
+
);
|
|
136
|
+
return { kind: disposition };
|
|
137
|
+
},
|
|
117
138
|
sync: async () => {
|
|
139
|
+
const pendingAttention = options.getAttention?.();
|
|
140
|
+
if (pendingAttention) {
|
|
141
|
+
const activeConfig = await loadConfig();
|
|
142
|
+
if (sessionSignal?.aborted) return { kind: "close" };
|
|
143
|
+
if (pendingAttention.decision.setupName === activeConfig.setupName) {
|
|
144
|
+
ctx.ui.notify("Review synced content before starting Sync now.", "warning");
|
|
145
|
+
return { kind: "stay" };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
118
148
|
const result = await runCancellableOperation(
|
|
119
149
|
ctx,
|
|
120
150
|
"Checking current sync setup…",
|
|
@@ -125,10 +155,14 @@ export async function showSyncManager(
|
|
|
125
155
|
signal: sessionSignal,
|
|
126
156
|
},
|
|
127
157
|
);
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
158
|
+
const disposition = await dispatchManagerResult(
|
|
159
|
+
ctx,
|
|
160
|
+
result,
|
|
161
|
+
"sync",
|
|
162
|
+
runRoute,
|
|
163
|
+
sessionSignal,
|
|
164
|
+
);
|
|
165
|
+
return disposition.kind === "close" ? { kind: "close" } : { kind: "stay" };
|
|
132
166
|
},
|
|
133
167
|
switch: async () => {
|
|
134
168
|
const result = await showSetupSwitcher(ctx, runRoute, undefined, sessionSignal);
|
|
@@ -162,12 +196,14 @@ export async function showSyncManager(
|
|
|
162
196
|
signal: sessionSignal,
|
|
163
197
|
},
|
|
164
198
|
);
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
199
|
+
const disposition = await dispatchManagerResult(
|
|
200
|
+
ctx,
|
|
201
|
+
result,
|
|
202
|
+
"pull",
|
|
203
|
+
runRoute,
|
|
204
|
+
sessionSignal,
|
|
205
|
+
);
|
|
206
|
+
return disposition.kind === "close" ? { kind: "close" } : { kind: "stay" };
|
|
171
207
|
},
|
|
172
208
|
push: async () => {
|
|
173
209
|
const result = await runCancellableOperation(
|
|
@@ -181,10 +217,14 @@ export async function showSyncManager(
|
|
|
181
217
|
signal: sessionSignal,
|
|
182
218
|
},
|
|
183
219
|
);
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
220
|
+
const disposition = await dispatchManagerResult(
|
|
221
|
+
ctx,
|
|
222
|
+
result,
|
|
223
|
+
"push",
|
|
224
|
+
runRoute,
|
|
225
|
+
sessionSignal,
|
|
226
|
+
);
|
|
227
|
+
return disposition.kind === "close" ? { kind: "close" } : { kind: "stay" };
|
|
188
228
|
},
|
|
189
229
|
setups: async () => {
|
|
190
230
|
const result = await showSyncSetupManager(ctx, runRoute, sessionSignal);
|
|
@@ -219,10 +259,14 @@ export async function showSyncManager(
|
|
|
219
259
|
});
|
|
220
260
|
await runMenu(ctx, menu, {
|
|
221
261
|
getState: async () => {
|
|
262
|
+
const pendingAttention = options.getAttention?.();
|
|
222
263
|
const [manager, lock] = await Promise.all([
|
|
223
|
-
describeManagerState(sessionSignal),
|
|
264
|
+
describeManagerState(sessionSignal, pendingAttention),
|
|
224
265
|
inspectLock(),
|
|
225
266
|
]);
|
|
267
|
+
if (pendingAttention && options.getAttention?.() === pendingAttention && !manager.attention) {
|
|
268
|
+
options.onSelectionResolved?.(pendingAttention);
|
|
269
|
+
}
|
|
226
270
|
return {
|
|
227
271
|
manager,
|
|
228
272
|
canRecover:
|
|
@@ -234,21 +278,6 @@ export async function showSyncManager(
|
|
|
234
278
|
});
|
|
235
279
|
}
|
|
236
280
|
|
|
237
|
-
async function resolveManagerDecision(
|
|
238
|
-
ctx: ExtensionCommandContext,
|
|
239
|
-
result: CancellableOperationResult,
|
|
240
|
-
runRoute: RunRoute,
|
|
241
|
-
signal?: AbortSignal,
|
|
242
|
-
) {
|
|
243
|
-
if (result.kind !== "decision-required") return undefined;
|
|
244
|
-
const resolution = await showSyncResolution(ctx, result.decision, runRoute, signal);
|
|
245
|
-
return resolution.kind === "resolved" ||
|
|
246
|
-
resolution.kind === "closed" ||
|
|
247
|
-
resolution.kind === "stale"
|
|
248
|
-
? "close"
|
|
249
|
-
: "stay";
|
|
250
|
-
}
|
|
251
|
-
|
|
252
281
|
function syncMainMenuItem(
|
|
253
282
|
label: string,
|
|
254
283
|
): ActionMenuItem<
|
|
@@ -553,23 +582,11 @@ async function showSetupSwitcher(
|
|
|
553
582
|
signal,
|
|
554
583
|
},
|
|
555
584
|
);
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
}
|
|
560
|
-
if (pullResult.kind === "decision-required") {
|
|
561
|
-
const resolution = await showSyncResolution(ctx, pullResult.decision, runRoute, signal);
|
|
562
|
-
if (
|
|
563
|
-
resolution.kind === "resolved" ||
|
|
564
|
-
resolution.kind === "closed" ||
|
|
565
|
-
resolution.kind === "stale"
|
|
566
|
-
) {
|
|
567
|
-
pullClosed = true;
|
|
568
|
-
}
|
|
569
|
-
return resolution.kind === "resolved" && resolution.direction === "pull"
|
|
570
|
-
? "applied"
|
|
571
|
-
: undefined;
|
|
585
|
+
const disposition = await dispatchManagerResult(ctx, pullResult, "pull", runRoute, signal);
|
|
586
|
+
if (pullResult.kind === "closed" || pullResult.kind.endsWith("required")) {
|
|
587
|
+
pullClosed = disposition.kind === "close";
|
|
572
588
|
}
|
|
589
|
+
if (disposition.appliedRoute === "pull") return "applied";
|
|
573
590
|
if (pullResult.kind === "completed") return pullResult.outcome;
|
|
574
591
|
return pullResult.kind === "cancelled" ? "cancelled" : undefined;
|
|
575
592
|
},
|