@narumitw/pi-sync 0.49.15 → 0.50.0
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 +49 -16
- package/dist/chunks/chunk-2B2ELUF5.ts +29 -0
- package/dist/chunks/chunk-2B2ELUF5.ts.map +7 -0
- package/dist/chunks/chunk-6LP3MCR2.ts +115 -0
- package/dist/chunks/chunk-6LP3MCR2.ts.map +7 -0
- package/dist/chunks/chunk-6UHKGALE.ts +134 -0
- package/dist/chunks/chunk-6UHKGALE.ts.map +7 -0
- package/dist/chunks/{chunk-JF6MZCT4.ts → chunk-AUSDLD6F.ts} +4 -4
- package/dist/chunks/chunk-AUSDLD6F.ts.map +7 -0
- package/dist/chunks/{chunk-X7SQ2EQM.ts → chunk-AXXS2BPA.ts} +9 -9
- package/dist/chunks/chunk-AXXS2BPA.ts.map +7 -0
- package/dist/chunks/{chunk-5T442OP3.ts → chunk-C7XY5NF5.ts} +210 -373
- package/dist/chunks/chunk-C7XY5NF5.ts.map +7 -0
- package/dist/chunks/{chunk-4U6AFLJB.ts → chunk-CHH26D4F.ts} +3 -2
- package/dist/chunks/chunk-CHH26D4F.ts.map +7 -0
- package/dist/chunks/chunk-CPEHGXJV.ts +50 -0
- package/dist/chunks/chunk-CPEHGXJV.ts.map +7 -0
- package/dist/chunks/{chunk-5MQ76BK5.ts → chunk-D5X27LCA.ts} +2 -2
- package/dist/chunks/chunk-D5X27LCA.ts.map +7 -0
- package/dist/chunks/{chunk-WSOBYHIZ.ts → chunk-GWMHAQG4.ts} +4 -4
- package/dist/chunks/chunk-GWMHAQG4.ts.map +7 -0
- package/dist/chunks/{chunk-5LZALPCD.ts → chunk-HUDQATCL.ts} +25 -25
- package/dist/chunks/chunk-HUDQATCL.ts.map +7 -0
- package/dist/chunks/{chunk-YQ6UW7IF.ts → chunk-JAAKLL6M.ts} +2 -2
- package/dist/chunks/chunk-JAAKLL6M.ts.map +7 -0
- package/dist/chunks/chunk-JSYMGJQQ.ts +51 -0
- package/dist/chunks/chunk-JSYMGJQQ.ts.map +7 -0
- package/dist/chunks/chunk-L7TBO32M.ts +25 -0
- package/dist/chunks/chunk-L7TBO32M.ts.map +7 -0
- package/dist/chunks/{chunk-DFXBKHGN.ts → chunk-LCRI3ABW.ts} +21 -8
- package/dist/chunks/chunk-LCRI3ABW.ts.map +7 -0
- package/dist/chunks/chunk-LTBWGSBV.ts +12 -0
- package/dist/chunks/chunk-LTBWGSBV.ts.map +7 -0
- package/dist/chunks/chunk-NJFUIVYL.ts +17 -0
- package/dist/chunks/chunk-NJFUIVYL.ts.map +7 -0
- package/dist/chunks/{chunk-HVUSHMVL.ts → chunk-OEX4ABY6.ts} +39 -37
- package/dist/chunks/chunk-OEX4ABY6.ts.map +7 -0
- package/dist/chunks/chunk-OUHGBFYF.ts +1255 -0
- package/dist/chunks/chunk-OUHGBFYF.ts.map +7 -0
- package/dist/chunks/{chunk-HGV24P4T.ts → chunk-Q2TUM5X6.ts} +3 -3
- package/dist/chunks/chunk-Q2TUM5X6.ts.map +7 -0
- package/dist/chunks/{chunk-GLQLN5GV.ts → chunk-SL64RLXR.ts} +8 -6
- package/dist/chunks/chunk-SL64RLXR.ts.map +7 -0
- package/dist/chunks/chunk-T3HH3UEJ.ts +96 -0
- package/dist/chunks/chunk-T3HH3UEJ.ts.map +7 -0
- package/dist/chunks/chunk-TEN2ZBJV.ts +101 -0
- package/dist/chunks/chunk-TEN2ZBJV.ts.map +7 -0
- package/dist/chunks/chunk-THMF4BVL.ts +18 -0
- package/dist/chunks/chunk-THMF4BVL.ts.map +7 -0
- package/dist/chunks/{chunk-44LPGQTI.ts → chunk-X5OM6GXT.ts} +9 -7
- package/dist/chunks/chunk-X5OM6GXT.ts.map +7 -0
- package/dist/chunks/chunk-XBX4HBLG.ts +57 -0
- package/dist/chunks/chunk-XBX4HBLG.ts.map +7 -0
- package/dist/chunks/{chunk-ARN2672F.ts → chunk-YKJHPTGO.ts} +23 -55
- package/dist/chunks/chunk-YKJHPTGO.ts.map +7 -0
- package/dist/chunks/chunk-Z4DQF6L3.ts +12 -0
- package/dist/chunks/chunk-Z4DQF6L3.ts.map +7 -0
- package/dist/chunks/{chunk-F5QL2GPY.ts → chunk-ZI5MXMEX.ts} +5 -99
- package/dist/chunks/chunk-ZI5MXMEX.ts.map +7 -0
- package/dist/chunks/{file-selection-RKEHALNQ.ts → file-selection-FTTKAOYX.ts} +10 -7
- package/dist/chunks/file-selection-FTTKAOYX.ts.map +7 -0
- package/dist/chunks/{git-backend-E3UOUUOM.ts → git-backend-OQW46G2X.ts} +42 -17
- package/dist/chunks/git-backend-OQW46G2X.ts.map +7 -0
- package/dist/chunks/manager-result-dispatcher-U23ODD32.ts +22 -0
- package/dist/chunks/manager-ui-ABATHC36.ts +1680 -0
- package/dist/chunks/manager-ui-ABATHC36.ts.map +7 -0
- package/dist/chunks/remote-selection-ui-ZE3TY67S.ts +21 -0
- package/dist/chunks/{s3-backend-552LXHE4.ts → s3-backend-3P33LQHU.ts} +96 -18
- package/dist/chunks/s3-backend-3P33LQHU.ts.map +7 -0
- package/dist/chunks/{setup-switch-5YDG5YGJ.ts → setup-switch-IS2PEZ3J.ts} +9 -9
- package/dist/chunks/setup-wizard-VB3VDOV5.ts +89 -0
- package/dist/chunks/setup-wizard-VB3VDOV5.ts.map +7 -0
- package/dist/chunks/{snapshot-2RYBUDRA.ts → snapshot-HKEWCVK6.ts} +7 -6
- package/dist/chunks/sync-inspection-FEP4L5TR.ts +20 -0
- package/dist/chunks/{sync-operations-3LLIHWZO.ts → sync-operations-ONJ27QRL.ts} +374 -294
- package/dist/chunks/sync-operations-ONJ27QRL.ts.map +7 -0
- package/dist/chunks/{sync-state-SRN6YRBK.ts → sync-state-Q2FTXTW6.ts} +6 -6
- package/dist/chunks/sync-state-Q2FTXTW6.ts.map +7 -0
- package/dist/chunks/{webdav-backend-ZD5RHRIU.ts → webdav-backend-ECIKD7SO.ts} +26 -13
- package/dist/chunks/webdav-backend-ECIKD7SO.ts.map +7 -0
- package/dist/index.ts +477 -342
- package/dist/index.ts.map +4 -4
- package/docs/settings.md +30 -6
- package/package.json +1 -1
- package/src/{backend-factory.ts → backends/backend-factory.ts} +4 -4
- package/src/backends/backend-identity.ts +40 -0
- package/src/backends/backend-types.ts +81 -0
- package/src/{git-backend.ts → backends/git/git-backend.ts} +43 -19
- package/src/{git-config.ts → backends/git/git-config.ts} +1 -0
- package/src/{git-storage.ts → backends/git/git-storage.ts} +2 -2
- package/src/{s3-backend.ts → backends/s3/s3-backend.ts} +45 -9
- package/src/{s3-client.ts → backends/s3/s3-client.ts} +56 -8
- package/src/{sync-backend.ts → backends/sync-backend.ts} +1 -1
- package/src/{webdav-backend.ts → backends/webdav/webdav-backend.ts} +22 -10
- package/src/{webdav-client.ts → backends/webdav/webdav-client.ts} +1 -1
- package/src/{webdav-config.ts → backends/webdav/webdav-config.ts} +1 -0
- package/src/commands/command-execution.ts +330 -0
- package/src/commands/command-handler.ts +201 -0
- package/src/commands/command-types.ts +18 -0
- package/src/{command.ts → commands/command.ts} +2 -1
- package/src/commands/setup-completions.ts +6 -0
- package/src/settings/config.ts +238 -0
- package/src/{settings-management.ts → settings/settings-management.ts} +39 -14
- package/src/settings/settings-store.ts +109 -0
- package/src/settings/settings-types.ts +128 -0
- package/src/settings/settings-validation.ts +443 -0
- package/src/snapshot/session-paths.ts +84 -0
- package/src/{snapshot-apply.ts → snapshot/snapshot-apply.ts} +3 -3
- package/src/{snapshot-codec.ts → snapshot/snapshot-codec.ts} +2 -2
- package/src/{snapshot-transaction.ts → snapshot/snapshot-transaction.ts} +5 -4
- package/src/snapshot/snapshot-types.ts +38 -0
- package/src/{snapshot.ts → snapshot/snapshot.ts} +39 -20
- package/src/state/json-file.ts +20 -0
- package/src/{lock.ts → state/lock.ts} +3 -2
- package/src/{operation-availability.ts → state/operation-availability.ts} +2 -2
- package/src/state/state-types.ts +20 -0
- package/src/state/sync-state-store.ts +62 -0
- package/src/sync/automatic-sync.ts +103 -0
- package/src/{remote-snapshot.ts → sync/remote-snapshot.ts} +27 -4
- package/src/{setup-switch.ts → sync/setup-switch.ts} +6 -7
- package/src/sync/signals.ts +10 -0
- package/src/sync/startup-check.ts +128 -0
- package/src/{sync-decision.ts → sync/sync-decision.ts} +6 -3
- package/src/sync/sync-error-guidance.ts +53 -0
- package/src/sync/sync-inspection.ts +51 -0
- package/src/sync/sync-loaders.ts +54 -0
- package/src/{sync-operations.ts → sync/sync-mutations.ts} +34 -325
- package/src/sync/sync-operations.ts +12 -0
- package/src/{sync-policy.ts → sync/sync-policy.ts} +2 -2
- package/src/sync/sync-queries.ts +235 -0
- package/src/{sync-state.ts → sync/sync-state.ts} +5 -4
- package/src/sync-extension.ts +64 -708
- package/src/sync.ts +8 -8
- package/src/types.ts +47 -286
- package/src/ui/automatic-sync-summary.ts +6 -0
- package/src/{cancellable-operation.ts → ui/cancellable-operation.ts} +4 -4
- package/src/{file-selection.ts → ui/file-selection.ts} +5 -3
- package/src/{manager-attention.ts → ui/manager-attention.ts} +5 -1
- package/src/{manager-recovery.ts → ui/manager-recovery.ts} +6 -2
- package/src/{manager-state.ts → ui/manager-state.ts} +35 -14
- package/src/ui/manager-ui.ts +386 -0
- package/src/{remote-selection-ui.ts → ui/remote-selection-ui.ts} +21 -13
- package/src/{secret-input.ts → ui/secret-input.ts} +22 -4
- package/src/{settings-ui.ts → ui/settings-ui.ts} +17 -13
- package/src/ui/setup/git-ui.ts +293 -0
- package/src/{s3-credentials-ui.ts → ui/setup/s3-credentials-ui.ts} +13 -21
- package/src/ui/setup/s3-ui.ts +217 -0
- package/src/ui/setup/setup-actions.ts +127 -0
- package/src/ui/setup/setup-location-ui.ts +167 -0
- package/src/ui/setup/setup-name-ui.ts +34 -0
- package/src/ui/setup/setup-prompts.ts +92 -0
- package/src/ui/setup/setup-review.ts +70 -0
- package/src/ui/setup/setup-switcher.ts +181 -0
- package/src/ui/setup/setup-wizard.ts +39 -0
- package/src/ui/setup/text-input.ts +78 -0
- package/src/ui/setup/webdav-ui.ts +330 -0
- package/src/{storage-connections-ui.ts → ui/storage-connections-ui.ts} +99 -69
- package/src/{sync-attention.ts → ui/sync-attention.ts} +75 -6
- package/src/{sync-format.ts → ui/sync-format.ts} +7 -13
- package/src/{sync-resolution-ui.ts → ui/sync-resolution-ui.ts} +4 -3
- package/src/{sync-setups-ui.ts → ui/sync-setups-ui.ts} +23 -10
- package/src/ui/terminal-text.ts +4 -0
- package/dist/chunks/chunk-44LPGQTI.ts.map +0 -7
- package/dist/chunks/chunk-4U6AFLJB.ts.map +0 -7
- package/dist/chunks/chunk-5LZALPCD.ts.map +0 -7
- package/dist/chunks/chunk-5MQ76BK5.ts.map +0 -7
- package/dist/chunks/chunk-5T442OP3.ts.map +0 -7
- package/dist/chunks/chunk-ARN2672F.ts.map +0 -7
- package/dist/chunks/chunk-C7LXZ3UH.ts +0 -167
- package/dist/chunks/chunk-C7LXZ3UH.ts.map +0 -7
- package/dist/chunks/chunk-DFXBKHGN.ts.map +0 -7
- package/dist/chunks/chunk-E4COSV32.ts +0 -82
- package/dist/chunks/chunk-E4COSV32.ts.map +0 -7
- package/dist/chunks/chunk-F5QL2GPY.ts.map +0 -7
- package/dist/chunks/chunk-GLQLN5GV.ts.map +0 -7
- package/dist/chunks/chunk-HGV24P4T.ts.map +0 -7
- package/dist/chunks/chunk-HVUSHMVL.ts.map +0 -7
- package/dist/chunks/chunk-JF6MZCT4.ts.map +0 -7
- package/dist/chunks/chunk-WSOBYHIZ.ts.map +0 -7
- package/dist/chunks/chunk-X7SQ2EQM.ts.map +0 -7
- package/dist/chunks/chunk-YQ6UW7IF.ts.map +0 -7
- package/dist/chunks/file-selection-RKEHALNQ.ts.map +0 -7
- package/dist/chunks/git-backend-E3UOUUOM.ts.map +0 -7
- package/dist/chunks/manager-result-dispatcher-LWPYJAD5.ts +0 -18
- package/dist/chunks/manager-ui-NF4RUHBY.ts +0 -2785
- package/dist/chunks/manager-ui-NF4RUHBY.ts.map +0 -7
- package/dist/chunks/remote-selection-ui-NUF5P4ZJ.ts +0 -17
- package/dist/chunks/s3-backend-552LXHE4.ts.map +0 -7
- package/dist/chunks/sync-operations-3LLIHWZO.ts.map +0 -7
- package/dist/chunks/webdav-backend-ZD5RHRIU.ts.map +0 -7
- package/src/config.ts +0 -923
- package/src/git-ui.ts +0 -307
- package/src/manager-helpers.ts +0 -64
- package/src/manager-ui.ts +0 -997
- package/src/webdav-ui.ts +0 -421
- /package/dist/chunks/{manager-result-dispatcher-LWPYJAD5.ts.map → manager-result-dispatcher-U23ODD32.ts.map} +0 -0
- /package/dist/chunks/{remote-selection-ui-NUF5P4ZJ.ts.map → remote-selection-ui-ZE3TY67S.ts.map} +0 -0
- /package/dist/chunks/{setup-switch-5YDG5YGJ.ts.map → setup-switch-IS2PEZ3J.ts.map} +0 -0
- /package/dist/chunks/{snapshot-2RYBUDRA.ts.map → snapshot-HKEWCVK6.ts.map} +0 -0
- /package/dist/chunks/{sync-state-SRN6YRBK.ts.map → sync-inspection-FEP4L5TR.ts.map} +0 -0
- /package/src/{git-runner.ts → backends/git/git-runner.ts} +0 -0
- /package/src/{config-errors.ts → settings/config-errors.ts} +0 -0
- /package/src/{config-file.ts → settings/config-file.ts} +0 -0
- /package/src/{snapshot-paths.ts → snapshot/snapshot-paths.ts} +0 -0
- /package/src/{lock-policy.ts → state/lock-policy.ts} +0 -0
- /package/src/{lockfile-fs.ts → state/lockfile-fs.ts} +0 -0
- /package/src/{state-directory.ts → state/state-directory.ts} +0 -0
- /package/src/{sync-errors.ts → sync/sync-errors.ts} +0 -0
- /package/src/{manager-result-dispatcher.ts → ui/manager-result-dispatcher.ts} +0 -0
|
@@ -3,17 +3,19 @@
|
|
|
3
3
|
import {
|
|
4
4
|
runCancellableOperation,
|
|
5
5
|
showRemoteSelectionReview
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-YKJHPTGO.ts";
|
|
7
7
|
import {
|
|
8
|
-
errorMessage,
|
|
9
8
|
safeTerminalText
|
|
10
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-LTBWGSBV.ts";
|
|
11
10
|
import {
|
|
12
11
|
loadConfig,
|
|
13
12
|
syncConfigReviewIdentity
|
|
14
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-C7XY5NF5.ts";
|
|
14
|
+
import {
|
|
15
|
+
errorMessage
|
|
16
|
+
} from "./chunk-2B2ELUF5.ts";
|
|
15
17
|
|
|
16
|
-
// src/sync-resolution-ui.ts
|
|
18
|
+
// src/ui/sync-resolution-ui.ts
|
|
17
19
|
import { defineMenu, runMenu } from "@narumitw/pi-tui-kit";
|
|
18
20
|
async function showSyncResolution(ctx, initialDecision, runRoute, sessionSignal) {
|
|
19
21
|
let currentDecision = initialDecision;
|
|
@@ -146,7 +148,7 @@ function pullLabel(decision) {
|
|
|
146
148
|
return decision.kind.startsWith("first-sync-") ? "Use remote as initial source\u2026" : "Use remote content and replace local\u2026";
|
|
147
149
|
}
|
|
148
150
|
|
|
149
|
-
// src/manager-result-dispatcher.ts
|
|
151
|
+
// src/ui/manager-result-dispatcher.ts
|
|
150
152
|
var MAX_DECISION_TRANSITIONS = 32;
|
|
151
153
|
async function dispatchManagerResult(ctx, initialResult, origin, runRoute, signal, options = {}) {
|
|
152
154
|
let result = initialResult;
|
|
@@ -210,4 +212,4 @@ async function dispatchManagerResult(ctx, initialResult, origin, runRoute, signa
|
|
|
210
212
|
export {
|
|
211
213
|
dispatchManagerResult
|
|
212
214
|
};
|
|
213
|
-
//# sourceMappingURL=chunk-
|
|
215
|
+
//# sourceMappingURL=chunk-X5OM6GXT.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/ui/sync-resolution-ui.ts", "../../src/ui/manager-result-dispatcher.ts"],
|
|
4
|
+
"sourcesContent": ["import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { defineMenu, runMenu } from \"@narumitw/pi-tui-kit\";\nimport { loadConfig, syncConfigReviewIdentity } from \"../settings/config.js\";\nimport type { SyncDecision, SyncResolutionDirection } from \"../sync/sync-decision.js\";\nimport { errorMessage } from \"../sync/sync-errors.js\";\nimport {\n\ttype RunRoute,\n\ttype RunRouteResult,\n\trunCancellableOperation,\n} from \"./cancellable-operation.js\";\nimport { safeTerminalText } from \"./terminal-text.js\";\n\nexport type SyncResolutionResult =\n\t| { kind: \"resolved\"; direction: SyncResolutionDirection }\n\t| {\n\t\t\tkind: \"route-result\";\n\t\t\tresult: RunRouteResult;\n\t\t\troute: SyncResolutionDirection;\n\t }\n\t| { kind: \"back\" }\n\t| { kind: \"closed\" }\n\t| { kind: \"stale\" };\n\nexport async function showSyncResolution(\n\tctx: ExtensionContext,\n\tinitialDecision: SyncDecision,\n\trunRoute: RunRoute,\n\tsessionSignal?: AbortSignal,\n): Promise<SyncResolutionResult> {\n\ttype Screen = \"resolve\" | \"review\";\n\ttype Action = \"push\" | \"pull\" | \"back\";\n\tlet currentDecision = initialDecision;\n\tlet resolvedDirection: SyncResolutionDirection | undefined;\n\tlet chainedResult: { result: RunRouteResult; route: SyncResolutionDirection } | undefined;\n\tconst menu = defineMenu<SyncDecision, Screen, Action, ExtensionContext>({\n\t\tstart: \"resolve\",\n\t\tscreens: {\n\t\t\tresolve: ({ state }) => ({\n\t\t\t\tkind: \"actions\",\n\t\t\t\ttitle: resolutionTitle(state),\n\t\t\t\tlines: resolutionLines(state),\n\t\t\t\titems: [\n\t\t\t\t\t{ id: \"review\", label: \"Review differences (recommended)\", to: \"review\" },\n\t\t\t\t\t...(state.directions.includes(\"push\")\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tid: \"push\",\n\t\t\t\t\t\t\t\t\tlabel: pushLabel(state),\n\t\t\t\t\t\t\t\t\tdescription: \"Review an exact push before replacing the remote version.\",\n\t\t\t\t\t\t\t\t\taction: \"push\" as const,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t: []),\n\t\t\t\t\t...(state.directions.includes(\"pull\")\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tid: \"pull\",\n\t\t\t\t\t\t\t\t\tlabel: pullLabel(state),\n\t\t\t\t\t\t\t\t\tdescription: \"Review exact local changes and create a backup before applying.\",\n\t\t\t\t\t\t\t\t\taction: \"pull\" as const,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t: []),\n\t\t\t\t\t{ id: \"back\", label: \"Back\", action: \"back\" },\n\t\t\t\t],\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t\treview: ({ state }) => ({\n\t\t\t\tkind: \"review\",\n\t\t\t\ttitle: `Review differences \u00B7 ${safeTerminalText(state.setupName)}`,\n\t\t\t\tcontent: state.review,\n\t\t\t\tformat: { kind: \"text\" },\n\t\t\t\tviewportSize: \"adaptive\",\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t},\n\t\tactions: {\n\t\t\tpush: ({ state, signal }) => resolveDirection(\"push\", state, signal),\n\t\t\tpull: ({ state, signal }) => resolveDirection(\"pull\", state, signal),\n\t\t\tback: async () => ({ kind: \"back\" }),\n\t\t},\n\t});\n\n\tasync function resolveDirection(\n\t\tdirection: SyncResolutionDirection,\n\t\tdecision: SyncDecision,\n\t\tactionSignal: AbortSignal,\n\t) {\n\t\tconst signal = sessionSignal ? AbortSignal.any([sessionSignal, actionSignal]) : actionSignal;\n\t\tconst config = await loadConfig(decision.setupName);\n\t\tif (signal.aborted) return { kind: \"close\" as const };\n\t\tif (syncConfigReviewIdentity(config) !== decision.configIdentity) {\n\t\t\tthrow new Error(\n\t\t\t\t`Sync setup \u201C${safeTerminalText(decision.setupName)}\u201D changed while conflict resolution was open; return to the sync manager and retry.`,\n\t\t\t);\n\t\t}\n\t\tconst result = await runCancellableOperation(\n\t\t\tctx,\n\t\t\tdirection === \"push\"\n\t\t\t\t? \"Preparing local-wins push preview\u2026\"\n\t\t\t\t: \"Preparing remote-wins pull preview\u2026\",\n\t\t\t`${direction} --force`,\n\t\t\trunRoute,\n\t\t\t{\n\t\t\t\tcommitAware: true,\n\t\t\t\tcancelledMessage:\n\t\t\t\t\tdirection === \"push\"\n\t\t\t\t\t\t? \"Push preparation cancelled; no remote files were changed.\"\n\t\t\t\t\t\t: \"Pull check cancelled; no local files were changed.\",\n\t\t\t\ttarget: decision.setupName,\n\t\t\t\tsignal,\n\t\t\t},\n\t\t);\n\t\tif (result.kind === \"decision-required\") {\n\t\t\tcurrentDecision = result.decision;\n\t\t\treturn { kind: \"stay\" as const };\n\t\t}\n\t\tif (result.kind === \"remote-selection-required\") {\n\t\t\tchainedResult = { result, route: direction };\n\t\t\treturn { kind: \"close\" as const };\n\t\t}\n\t\tif (result.kind === \"completed\") {\n\t\t\tif (result.outcome === \"cancelled\") return { kind: \"stay\" as const };\n\t\t\tresolvedDirection = direction;\n\t\t\treturn { kind: \"close\" as const };\n\t\t}\n\t\treturn result.kind === \"closed\" ? { kind: \"close\" as const } : { kind: \"stay\" as const };\n\t}\n\n\tconst result = await runMenu(ctx, menu, {\n\t\tgetState: () => currentDecision,\n\t\tsignal: sessionSignal,\n\t\tisCurrent: () => !sessionSignal?.aborted,\n\t\tonError: (_menuCtx, error) => ctx.ui.notify(errorMessage(error), \"error\"),\n\t});\n\tif (sessionSignal?.aborted || result.kind === \"stale\") return { kind: \"stale\" };\n\tif (chainedResult) return { kind: \"route-result\", ...chainedResult };\n\tif (resolvedDirection) return { kind: \"resolved\", direction: resolvedDirection };\n\tif (result.kind === \"closed\") {\n\t\treturn result.reason === \"back\" ? { kind: \"back\" } : { kind: \"closed\" };\n\t}\n\treturn { kind: \"closed\" };\n}\n\nfunction resolutionTitle(decision: SyncDecision) {\n\treturn decision.kind === \"remote-empty\" ? \"Remote is empty\" : \"Resolve sync conflict\";\n}\n\nfunction resolutionLines(decision: SyncDecision) {\n\treturn [\n\t\t`Sync setup: ${safeTerminalText(decision.setupName)}`,\n\t\t...causeSummary(decision),\n\t\t\"No files have been changed by this failed operation.\",\n\t];\n}\n\nfunction causeSummary(decision: SyncDecision) {\n\tif (decision.kind === \"first-sync-settings-diverged\") {\n\t\treturn [\"This machine and the remote have different Pi settings on first sync.\"];\n\t}\n\tif (decision.kind === \"first-sync-sessions-diverged\") {\n\t\treturn [\"Pi settings match, but local and remote sessions differ on first sync.\"];\n\t}\n\tif (decision.kind === \"remote-empty\") return [\"The remote storage location has no snapshot.\"];\n\treturn [\n\t\t...(decision.causes.localChanged ? [\"Local content changed since the last sync.\"] : []),\n\t\t...(decision.causes.remoteChanged ? [\"Remote content changed since the last sync.\"] : []),\n\t\t...(decision.causes.policyChanged ? [\"Included content changed since the last sync.\"] : []),\n\t];\n}\n\nfunction pushLabel(decision: SyncDecision) {\n\tif (decision.kind === \"remote-empty\") return \"Push local content\u2026\";\n\tif (decision.kind.startsWith(\"first-sync-\")) return \"Use local as initial source\u2026\";\n\treturn \"Keep local content and replace remote\u2026\";\n}\n\nfunction pullLabel(decision: SyncDecision) {\n\treturn decision.kind.startsWith(\"first-sync-\")\n\t\t? \"Use remote as initial source\u2026\"\n\t\t: \"Use remote content and replace local\u2026\";\n}\n", "import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport type {\n\tCancellableOperationResult,\n\tRunRoute,\n\tRunRouteResult,\n} from \"./cancellable-operation.js\";\nimport { type RemoteSelectionOrigin, showRemoteSelectionReview } from \"./remote-selection-ui.js\";\nimport { showSyncResolution } from \"./sync-resolution-ui.js\";\n\nconst MAX_DECISION_TRANSITIONS = 32;\n\nexport interface ManagerResultDisposition {\n\tkind: \"close\" | \"stay\";\n\tappliedRoute?: \"sync\" | \"pull\" | \"push\";\n}\n\nexport interface ManagerResultOptions {\n\tcancelLabel?: string;\n\tonSelectionResolved?: () => void;\n\twithStateAccess?: <T>(task: () => Promise<T>) => Promise<T>;\n}\n\nexport async function dispatchManagerResult(\n\tctx: ExtensionContext,\n\tinitialResult: CancellableOperationResult,\n\torigin: Exclude<RemoteSelectionOrigin, \"settings\">,\n\trunRoute: RunRoute,\n\tsignal?: AbortSignal,\n\toptions: ManagerResultOptions = {},\n): Promise<ManagerResultDisposition> {\n\tlet result: CancellableOperationResult | RunRouteResult = initialResult;\n\tlet currentRoute: \"sync\" | \"pull\" | \"push\" = origin;\n\tlet resolving = false;\n\n\tfor (let transition = 0; transition < MAX_DECISION_TRANSITIONS; transition += 1) {\n\t\tif (signal?.aborted) return { kind: \"close\" };\n\t\tif (result.kind === \"remote-selection-required\") {\n\t\t\tresolving = true;\n\t\t\tconst resolution = await showRemoteSelectionReview(\n\t\t\t\tctx,\n\t\t\t\tresult.decision.setupName,\n\t\t\t\tsignal,\n\t\t\t\tundefined,\n\t\t\t\t{\n\t\t\t\t\tdecision: result.decision,\n\t\t\t\t\torigin: currentRoute,\n\t\t\t\t\trunRoute,\n\t\t\t\t\tcancelLabel: options.cancelLabel,\n\t\t\t\t\tonSelectionResolved: options.onSelectionResolved,\n\t\t\t\t\twithStateAccess: options.withStateAccess,\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (resolution.kind === \"route-result\") {\n\t\t\t\tresult = resolution.result;\n\t\t\t\tcurrentRoute = resolution.route;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn resolution.kind === \"closed\" || resolution.kind === \"stale\"\n\t\t\t\t? { kind: \"close\" }\n\t\t\t\t: { kind: \"stay\" };\n\t\t}\n\t\tif (result.kind === \"decision-required\") {\n\t\t\tresolving = true;\n\t\t\tconst resolution = await showSyncResolution(ctx, result.decision, runRoute, signal);\n\t\t\tif (resolution.kind === \"route-result\") {\n\t\t\t\tresult = resolution.result;\n\t\t\t\tcurrentRoute = resolution.route;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (resolution.kind === \"resolved\") {\n\t\t\t\treturn { kind: \"close\", appliedRoute: resolution.direction };\n\t\t\t}\n\t\t\treturn resolution.kind === \"closed\" || resolution.kind === \"stale\"\n\t\t\t\t? { kind: \"close\" }\n\t\t\t\t: { kind: \"stay\" };\n\t\t}\n\t\tif (result.kind === \"closed\") return { kind: \"close\" };\n\t\tif (result.kind === \"completed\") {\n\t\t\tconst appliedRoute = result.outcome === \"applied\" ? currentRoute : undefined;\n\t\t\tif (resolving || (origin === \"pull\" && result.outcome === \"applied\")) {\n\t\t\t\treturn { kind: \"close\", ...(appliedRoute ? { appliedRoute } : {}) };\n\t\t\t}\n\t\t\treturn { kind: \"stay\", ...(appliedRoute ? { appliedRoute } : {}) };\n\t\t}\n\t\treturn { kind: \"stay\" };\n\t}\n\n\tctx.ui.notify(\n\t\t\"Sync resolution stopped after too many state changes. Start /sync again to review fresh state.\",\n\t\t\"warning\",\n\t);\n\treturn { kind: \"stay\" };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["result"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// @generated by scripts/build-runtime.mjs; do not edit.
|
|
2
|
+
// @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
|
|
3
|
+
import {
|
|
4
|
+
hasLocalChanges,
|
|
5
|
+
remoteChangedSinceState
|
|
6
|
+
} from "./chunk-AUSDLD6F.ts";
|
|
7
|
+
import {
|
|
8
|
+
throwIfAborted
|
|
9
|
+
} from "./chunk-NJFUIVYL.ts";
|
|
10
|
+
import {
|
|
11
|
+
readStateForConfig,
|
|
12
|
+
syncStateFingerprint
|
|
13
|
+
} from "./chunk-JSYMGJQQ.ts";
|
|
14
|
+
import {
|
|
15
|
+
createSyncBackend
|
|
16
|
+
} from "./chunk-L7TBO32M.ts";
|
|
17
|
+
import {
|
|
18
|
+
createSnapshot
|
|
19
|
+
} from "./chunk-OEX4ABY6.ts";
|
|
20
|
+
import {
|
|
21
|
+
inspectRemoteSelection
|
|
22
|
+
} from "./chunk-JAAKLL6M.ts";
|
|
23
|
+
|
|
24
|
+
// src/sync/sync-inspection.ts
|
|
25
|
+
async function inspectSync(config, options, signal, factory = createSyncBackend) {
|
|
26
|
+
throwIfAborted(signal);
|
|
27
|
+
const backend = await factory(config);
|
|
28
|
+
throwIfAborted(signal);
|
|
29
|
+
const local = await createSnapshot(config.snapshotIdentity, { ...options, signal });
|
|
30
|
+
throwIfAborted(signal);
|
|
31
|
+
const state = await readStateForConfig(config);
|
|
32
|
+
throwIfAborted(signal);
|
|
33
|
+
const head = await backend.readHead(signal);
|
|
34
|
+
throwIfAborted(signal);
|
|
35
|
+
return {
|
|
36
|
+
head,
|
|
37
|
+
selectionState: head ? inspectRemoteSelection(config.include, { selection: head.selection, files: [] }) : void 0,
|
|
38
|
+
localFiles: local.files.length,
|
|
39
|
+
localChanged: hasLocalChanges(local, state, config),
|
|
40
|
+
remoteChanged: remoteChangedSinceState(
|
|
41
|
+
head,
|
|
42
|
+
state,
|
|
43
|
+
config,
|
|
44
|
+
(left, right) => backend.sameRevision(left, right)
|
|
45
|
+
),
|
|
46
|
+
firstSync: !state.lastAppliedSnapshot,
|
|
47
|
+
emptyInclude: config.include.length === 0,
|
|
48
|
+
stateIdentity: syncStateFingerprint(state),
|
|
49
|
+
destination: backend.destination,
|
|
50
|
+
capability: backend.capability
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export {
|
|
55
|
+
inspectSync
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=chunk-XBX4HBLG.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/sync/sync-inspection.ts"],
|
|
4
|
+
"sourcesContent": ["import { createSyncBackend, type SyncBackendFactory } from \"../backends/backend-factory.js\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport { createSnapshot } from \"../snapshot/snapshot.js\";\nimport type { SnapshotOptions } from \"../snapshot/snapshot-types.js\";\nimport { readStateForConfig, syncStateFingerprint } from \"../state/sync-state-store.js\";\nimport { throwIfAborted } from \"./signals.js\";\nimport { inspectRemoteSelection } from \"./sync-policy.js\";\nimport { hasLocalChanges, remoteChangedSinceState } from \"./sync-state.js\";\n\n/** Advisory baseline-relative observation, never an authorization to transfer files. */\nexport async function inspectSync(\n\tconfig: AnySyncConfig,\n\toptions: SnapshotOptions,\n\tsignal?: AbortSignal,\n\tfactory: SyncBackendFactory = createSyncBackend,\n) {\n\tthrowIfAborted(signal);\n\tconst backend = await factory(config);\n\tthrowIfAborted(signal);\n\tconst local = await createSnapshot(config.snapshotIdentity, { ...options, signal });\n\tthrowIfAborted(signal);\n\tconst state = await readStateForConfig(config);\n\tthrowIfAborted(signal);\n\tconst head = await backend.readHead(signal);\n\tthrowIfAborted(signal);\n\treturn {\n\t\thead,\n\t\tselectionState: head\n\t\t\t? inspectRemoteSelection(config.include, { selection: head.selection, files: [] })\n\t\t\t: undefined,\n\t\tlocalFiles: local.files.length,\n\t\tlocalChanged: hasLocalChanges(local, state, config),\n\t\tremoteChanged: remoteChangedSinceState(head, state, config, (left, right) =>\n\t\t\tbackend.sameRevision(left, right),\n\t\t),\n\t\tfirstSync: !state.lastAppliedSnapshot,\n\t\temptyInclude: config.include.length === 0,\n\t\tstateIdentity: syncStateFingerprint(state),\n\t\tdestination: backend.destination,\n\t\tcapability: backend.capability,\n\t};\n}\n\nexport type SyncInspection = Awaited<ReturnType<typeof inspectSync>>;\n\nexport interface StartupObservation {\n\tsetupName: string;\n\tconfigIdentity: string;\n\tcheckedAt: string;\n\tinspection: SyncInspection;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAUA,eAAsB,YACrB,QACA,SACA,QACA,UAA8B,mBAC7B;AACD,iBAAe,MAAM;AACrB,QAAM,UAAU,MAAM,QAAQ,MAAM;AACpC,iBAAe,MAAM;AACrB,QAAM,QAAQ,MAAM,eAAe,OAAO,kBAAkB,EAAE,GAAG,SAAS,OAAO,CAAC;AAClF,iBAAe,MAAM;AACrB,QAAM,QAAQ,MAAM,mBAAmB,MAAM;AAC7C,iBAAe,MAAM;AACrB,QAAM,OAAO,MAAM,QAAQ,SAAS,MAAM;AAC1C,iBAAe,MAAM;AACrB,SAAO;AAAA,IACN;AAAA,IACA,gBAAgB,OACb,uBAAuB,OAAO,SAAS,EAAE,WAAW,KAAK,WAAW,OAAO,CAAC,EAAE,CAAC,IAC/E;AAAA,IACH,YAAY,MAAM,MAAM;AAAA,IACxB,cAAc,gBAAgB,OAAO,OAAO,MAAM;AAAA,IAClD,eAAe;AAAA,MAAwB;AAAA,MAAM;AAAA,MAAO;AAAA,MAAQ,CAAC,MAAM,UAClE,QAAQ,aAAa,MAAM,KAAK;AAAA,IACjC;AAAA,IACA,WAAW,CAAC,MAAM;AAAA,IAClB,cAAc,OAAO,QAAQ,WAAW;AAAA,IACxC,eAAe,qBAAqB,KAAK;AAAA,IACzC,aAAa,QAAQ;AAAA,IACrB,YAAY,QAAQ;AAAA,EACrB;AACD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,72 +1,41 @@
|
|
|
1
1
|
// @generated by scripts/build-runtime.mjs; do not edit.
|
|
2
2
|
// @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
|
|
3
3
|
import {
|
|
4
|
-
SyncSetupReviewChangedError,
|
|
5
|
-
updateSyncSetup
|
|
6
|
-
} from "./chunk-DFXBKHGN.ts";
|
|
7
|
-
import {
|
|
8
|
-
createSyncBackend,
|
|
9
4
|
readSnapshotForHead
|
|
10
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-HUDQATCL.ts";
|
|
6
|
+
import {
|
|
7
|
+
createSyncBackend
|
|
8
|
+
} from "./chunk-L7TBO32M.ts";
|
|
11
9
|
import {
|
|
12
|
-
errorMessage,
|
|
13
10
|
safeTerminalText
|
|
14
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-LTBWGSBV.ts";
|
|
12
|
+
import {
|
|
13
|
+
SyncSetupReviewChangedError,
|
|
14
|
+
updateSyncSetup
|
|
15
|
+
} from "./chunk-LCRI3ABW.ts";
|
|
15
16
|
import {
|
|
16
17
|
loadConfig,
|
|
17
18
|
loadPartialConfig,
|
|
18
19
|
syncConfigReviewFingerprint
|
|
19
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-C7XY5NF5.ts";
|
|
21
|
+
import {
|
|
22
|
+
errorMessage
|
|
23
|
+
} from "./chunk-2B2ELUF5.ts";
|
|
20
24
|
import {
|
|
21
25
|
compareSyncInclude,
|
|
22
26
|
inspectRemoteSelection,
|
|
23
27
|
sameSyncInclude
|
|
24
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-JAAKLL6M.ts";
|
|
25
29
|
|
|
26
|
-
// src/remote-selection-ui.ts
|
|
30
|
+
// src/ui/remote-selection-ui.ts
|
|
27
31
|
import { defineMenu, runMenu } from "@narumitw/pi-tui-kit";
|
|
28
32
|
|
|
29
|
-
// src/cancellable-operation.ts
|
|
33
|
+
// src/ui/cancellable-operation.ts
|
|
30
34
|
import {
|
|
31
35
|
BorderedLoader
|
|
32
36
|
} from "@earendil-works/pi-coding-agent";
|
|
33
37
|
import { Key, matchesKey, truncateToWidth } from "@earendil-works/pi-tui";
|
|
34
38
|
import { runCustomInteraction } from "@narumitw/pi-tui-kit";
|
|
35
|
-
|
|
36
|
-
// src/manager-helpers.ts
|
|
37
|
-
async function requiredExistingBucket(ctx, example, signal) {
|
|
38
|
-
const value = await ctx.ui.input("Existing bucket", `Example: ${example}`, { signal });
|
|
39
|
-
if (signal?.aborted) {
|
|
40
|
-
throw signal.reason instanceof Error ? signal.reason : new DOMException("The operation was aborted", "AbortError");
|
|
41
|
-
}
|
|
42
|
-
if (value === void 0) return void 0;
|
|
43
|
-
const normalized = value.trim();
|
|
44
|
-
if (!normalized) {
|
|
45
|
-
ctx.ui.notify("Enter the name of an existing R2/S3 bucket, or cancel setup.", "warning");
|
|
46
|
-
return void 0;
|
|
47
|
-
}
|
|
48
|
-
return normalized;
|
|
49
|
-
}
|
|
50
|
-
async function requiredInput(ctx, title, placeholder, signal) {
|
|
51
|
-
const value = await ctx.ui.input(title, placeholder, { signal });
|
|
52
|
-
if (signal?.aborted) {
|
|
53
|
-
throw signal.reason instanceof Error ? signal.reason : new DOMException("The operation was aborted", "AbortError");
|
|
54
|
-
}
|
|
55
|
-
if (value === void 0) return void 0;
|
|
56
|
-
const normalized = value.trim() || placeholder;
|
|
57
|
-
return normalized.includes("<") || normalized.includes(">") ? void 0 : normalized;
|
|
58
|
-
}
|
|
59
|
-
function ownRecord(value) {
|
|
60
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
61
|
-
}
|
|
62
|
-
function safeTerminalText2(value) {
|
|
63
|
-
return value.replace(/[\u0000-\u001f\u007f-\u009f]/gu, "?");
|
|
64
|
-
}
|
|
65
|
-
function errorMessage2(error) {
|
|
66
|
-
return error instanceof Error ? error.message : String(error);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// src/cancellable-operation.ts
|
|
70
39
|
async function runCancellableOperation(ctx, message, route, runRoute, options = {}) {
|
|
71
40
|
const {
|
|
72
41
|
commitAware = false,
|
|
@@ -140,12 +109,12 @@ function keybindingText(keybindings, binding, fallback) {
|
|
|
140
109
|
const keys = [.../* @__PURE__ */ new Set([...keybindings.getKeys(binding), "ctrl+c"])].map(String).map((key) => {
|
|
141
110
|
if (key === "return") return "enter";
|
|
142
111
|
if (key === "escape") return "esc";
|
|
143
|
-
return
|
|
112
|
+
return safeTerminalText(key);
|
|
144
113
|
}).filter(Boolean);
|
|
145
114
|
return keys.join("/") || fallback;
|
|
146
115
|
}
|
|
147
116
|
|
|
148
|
-
// src/remote-selection-ui.ts
|
|
117
|
+
// src/ui/remote-selection-ui.ts
|
|
149
118
|
var STATUS_KEY = "sync";
|
|
150
119
|
async function showRemoteSelectionReview(ctx, setupName, signal, factory = createSyncBackend, options = {}) {
|
|
151
120
|
try {
|
|
@@ -153,6 +122,9 @@ async function showRemoteSelectionReview(ctx, setupName, signal, factory = creat
|
|
|
153
122
|
if (!decision) {
|
|
154
123
|
const inspected = await inspectConfiguredRemoteSelection(ctx, setupName, signal, factory);
|
|
155
124
|
if (!inspected || signal?.aborted) return { kind: "stale" };
|
|
125
|
+
if (inspected.kind === "empty" || inspected.state.kind !== "different") {
|
|
126
|
+
options.onSelectionResolved?.();
|
|
127
|
+
}
|
|
156
128
|
if (inspected.kind === "empty") {
|
|
157
129
|
ctx.ui.notify("Remote storage has no snapshot or synced-content list yet.", "info");
|
|
158
130
|
return { kind: "back" };
|
|
@@ -194,6 +166,7 @@ async function showRemoteSelectionReview(ctx, setupName, signal, factory = creat
|
|
|
194
166
|
);
|
|
195
167
|
if (!refreshed || signal?.aborted) return { kind: "stale" };
|
|
196
168
|
if (refreshed.kind === "empty") {
|
|
169
|
+
options.onSelectionResolved?.();
|
|
197
170
|
ctx.ui.notify("Remote storage no longer has a snapshot or synced-content list.", "warning");
|
|
198
171
|
return { kind: "back" };
|
|
199
172
|
}
|
|
@@ -644,12 +617,7 @@ function throwIfAborted(signal) {
|
|
|
644
617
|
}
|
|
645
618
|
|
|
646
619
|
export {
|
|
647
|
-
requiredExistingBucket,
|
|
648
|
-
requiredInput,
|
|
649
|
-
ownRecord,
|
|
650
|
-
safeTerminalText2 as safeTerminalText,
|
|
651
|
-
errorMessage2 as errorMessage,
|
|
652
620
|
runCancellableOperation,
|
|
653
621
|
showRemoteSelectionReview
|
|
654
622
|
};
|
|
655
|
-
//# sourceMappingURL=chunk-
|
|
623
|
+
//# sourceMappingURL=chunk-YKJHPTGO.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 {\n\tloadConfig,\n\tloadPartialConfig,\n\ttype SyncSetupStorageReview,\n\tsyncConfigReviewFingerprint,\n} from \"../settings/config.js\";\nimport { SyncSetupReviewChangedError, updateSyncSetup } from \"../settings/settings-management.js\";\nimport type { AnySyncConfig, PartialConfig } from \"../settings/settings-types.js\";\nimport { readSnapshotForHead } from \"../sync/remote-snapshot.js\";\nimport { errorMessage } from \"../sync/sync-errors.js\";\nimport {\n\tcompareSyncInclude,\n\tinspectRemoteSelection,\n\ttype RemoteSelectionDecision,\n\ttype RemoteSelectionState,\n\tsameSyncInclude,\n} from \"../sync/sync-policy.js\";\nimport {\n\ttype RunRoute,\n\ttype RunRouteResult,\n\trunCancellableOperation,\n} from \"./cancellable-operation.js\";\nimport { safeTerminalText } from \"./terminal-text.js\";\n\nconst STATUS_KEY = \"sync\";\n\nexport type RemoteSelectionOrigin = \"settings\" | \"sync\" | \"pull\" | \"push\";\n\nexport interface RemoteSelectionReviewOptions {\n\tdecision?: RemoteSelectionDecision;\n\torigin?: RemoteSelectionOrigin;\n\trunRoute?: RunRoute;\n\tcancelLabel?: string;\n\t/** The explicit mismatch is resolved or superseded; this does not imply file equality. */\n\tonSelectionResolved?: () => void;\n\twithStateAccess?: <T>(task: () => Promise<T>) => Promise<T>;\n}\n\nexport type RemoteSelectionReviewResult =\n\t| { kind: \"back\" }\n\t| { kind: \"closed\" }\n\t| { kind: \"done\" }\n\t| { kind: \"stale\" }\n\t| { kind: \"route-result\"; result: RunRouteResult; route: \"sync\" | \"pull\" | \"push\" };\n\nexport async function showRemoteSelectionReview(\n\tctx: ExtensionContext,\n\tsetupName?: string,\n\tsignal?: AbortSignal,\n\tfactory: SyncBackendFactory = createSyncBackend,\n\toptions: RemoteSelectionReviewOptions = {},\n): Promise<RemoteSelectionReviewResult> {\n\ttry {\n\t\tlet decision = options.decision;\n\t\tif (!decision) {\n\t\t\tconst inspected = await inspectConfiguredRemoteSelection(ctx, setupName, signal, factory);\n\t\t\tif (!inspected || signal?.aborted) return { kind: \"stale\" };\n\t\t\t// A successful fresh read can supersede an old explicit mismatch without\n\t\t\t// changing local settings. This is not user cancellation or proof of file equality.\n\t\t\tif (inspected.kind === \"empty\" || inspected.state.kind !== \"different\") {\n\t\t\t\toptions.onSelectionResolved?.();\n\t\t\t}\n\t\t\tif (inspected.kind === \"empty\") {\n\t\t\t\tctx.ui.notify(\"Remote storage has no snapshot or synced-content list yet.\", \"info\");\n\t\t\t\treturn { kind: \"back\" };\n\t\t\t}\n\t\t\tif (inspected.state.kind === \"same\") {\n\t\t\t\tctx.ui.notify(\"Remote synced content already matches this sync setup.\", \"info\");\n\t\t\t\treturn { kind: \"back\" };\n\t\t\t}\n\t\t\tif (inspected.state.kind === \"legacy\") {\n\t\t\t\tif (ctx.mode !== \"tui\") {\n\t\t\t\t\tctx.ui.notify(formatLegacySummary(inspected.config, inspected.state.discovered), \"info\");\n\t\t\t\t\treturn { kind: \"back\" };\n\t\t\t\t}\n\t\t\t\tawait showLegacyDiscovery(ctx, inspected.config, inspected.state.discovered, signal);\n\t\t\t\treturn signal?.aborted ? { kind: \"stale\" } : { kind: \"back\" };\n\t\t\t}\n\t\t\tdecision = decisionFromState(inspected.config, inspected.state);\n\t\t}\n\n\t\tif (ctx.mode !== \"tui\") {\n\t\t\tctx.ui.notify(formatRemoteSelectionSummary(decision), \"warning\");\n\t\t\treturn { kind: \"back\" };\n\t\t}\n\n\t\tlet currentDecision = decision;\n\t\tfor (;;) {\n\t\t\tif (signal?.aborted) return { kind: \"stale\" };\n\t\t\tconst result = await showSelectionDifference(\n\t\t\t\tctx,\n\t\t\t\tcurrentDecision,\n\t\t\t\toptions.origin ?? \"settings\",\n\t\t\t\toptions.runRoute,\n\t\t\t\tsignal,\n\t\t\t\tfactory,\n\t\t\t\toptions,\n\t\t\t);\n\t\t\tif (result.kind !== \"refresh\") return result;\n\t\t\tconst refreshed = await runWithOptionalStateAccess(options, () =>\n\t\t\t\tinspectConfiguredRemoteSelection(ctx, currentDecision.setupName, signal, factory),\n\t\t\t);\n\t\t\tif (!refreshed || signal?.aborted) return { kind: \"stale\" };\n\t\t\tif (refreshed.kind === \"empty\") {\n\t\t\t\toptions.onSelectionResolved?.();\n\t\t\t\tctx.ui.notify(\"Remote storage no longer has a snapshot or synced-content list.\", \"warning\");\n\t\t\t\treturn { kind: \"back\" };\n\t\t\t}\n\t\t\tif (refreshed.state.kind !== \"different\") {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\trefreshed.state.kind === \"same\"\n\t\t\t\t\t\t? \"Remote synced content now matches this sync setup.\"\n\t\t\t\t\t\t: \"The refreshed legacy snapshot has no authoritative synced-content list.\",\n\t\t\t\t\t\"info\",\n\t\t\t\t);\n\t\t\t\toptions.onSelectionResolved?.();\n\t\t\t\treturn { kind: \"done\" };\n\t\t\t}\n\t\t\tcurrentDecision = decisionFromState(refreshed.config, refreshed.state);\n\t\t}\n\t} catch (error) {\n\t\tif (signal?.aborted) return { kind: \"stale\" };\n\t\tctx.ui.notify(`Could not review synced content: ${errorMessage(error)}`, \"error\");\n\t\treturn { kind: \"back\" };\n\t} finally {\n\t\tctx.ui.setStatus(STATUS_KEY, undefined);\n\t}\n}\n\ntype DifferenceFlowResult = RemoteSelectionReviewResult | { kind: \"refresh\" };\n\nasync function showSelectionDifference(\n\tctx: ExtensionContext,\n\tinitialDecision: RemoteSelectionDecision,\n\torigin: RemoteSelectionOrigin,\n\trunRoute: RunRoute | undefined,\n\tsessionSignal: AbortSignal | undefined,\n\tfactory: SyncBackendFactory,\n\toptions: Pick<\n\t\tRemoteSelectionReviewOptions,\n\t\t\"cancelLabel\" | \"onSelectionResolved\" | \"withStateAccess\"\n\t>,\n): Promise<DifferenceFlowResult> {\n\ttype Screen = \"choice\" | \"review\" | \"saved\";\n\ttype Action = \"adopt\" | \"keep\" | \"cancel\" | \"continue\" | \"done\";\n\tinterface FlowState {\n\t\tdecision: RemoteSelectionDecision;\n\t\tsaved: boolean;\n\t}\n\tlet flowState: FlowState = { decision: initialDecision, saved: false };\n\tlet continuationReview: PartialConfig | undefined;\n\tlet nextResult: RemoteSelectionReviewResult | undefined;\n\tlet refreshRequested = false;\n\tconst route = origin === \"settings\" ? \"sync\" : origin;\n\tconst menu = defineMenu<FlowState, Screen, Action, ExtensionContext>({\n\t\tstart: \"choice\",\n\t\tscreens: {\n\t\t\tchoice: ({ state }) => ({\n\t\t\t\tkind: \"actions\",\n\t\t\t\ttitle: \"Synced content differs\",\n\t\t\t\tlines: selectionSummaryLines(state.decision),\n\t\t\t\titems: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"review\",\n\t\t\t\t\t\tlabel: \"Review all paths (recommended)\",\n\t\t\t\t\t\tdescription: \"Compare exact remote-only, device-only, and ordered lists.\",\n\t\t\t\t\t\tto: \"review\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"adopt\",\n\t\t\t\t\t\tlabel: \"Use remote content list\",\n\t\t\t\t\t\tdescription: \"Save the reviewed list on this device without pulling files.\",\n\t\t\t\t\t\taction: \"adopt\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"keep\",\n\t\t\t\t\t\tlabel: \"Keep this device's content list and update remote\u2026\",\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"Open the existing exact force-push preview without skipping confirmation.\",\n\t\t\t\t\t\taction: \"keep\",\n\t\t\t\t\t},\n\t\t\t\t\t{ id: \"cancel\", label: options.cancelLabel ?? \"Cancel\", action: \"cancel\" },\n\t\t\t\t],\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t\treview: ({ state }) => ({\n\t\t\t\tkind: \"review\",\n\t\t\t\ttitle: `Review synced content \u00B7 ${safeTerminalText(state.decision.setupName)}`,\n\t\t\t\tcontent: formatSelectionDifference(state.decision),\n\t\t\t\tformat: { kind: \"text\" },\n\t\t\t\tviewportSize: \"adaptive\",\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t\tsaved: ({ state }) => ({\n\t\t\t\tkind: \"actions\",\n\t\t\t\ttitle: \"Remote content list saved\",\n\t\t\t\tlines: [\n\t\t\t\t\t`Sync setup: ${safeTerminalText(state.decision.setupName)}`,\n\t\t\t\t\t\"Only the included-content setting was saved.\",\n\t\t\t\t\t\"No files were pulled and sync state was not changed.\",\n\t\t\t\t],\n\t\t\t\titems: [\n\t\t\t\t\t...(runRoute\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tid: \"continue\",\n\t\t\t\t\t\t\t\t\tlabel: continueLabel(origin),\n\t\t\t\t\t\t\t\t\tdescription: \"Start a fresh check and exact preview for this sync setup.\",\n\t\t\t\t\t\t\t\t\taction: \"continue\" as const,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t: []),\n\t\t\t\t\t{ id: \"done\", label: \"Done\", action: \"done\" },\n\t\t\t\t],\n\t\t\t\thint: \"close\",\n\t\t\t}),\n\t\t},\n\t\tactions: {\n\t\t\tadopt: async ({ state, signal: actionSignal }) => {\n\t\t\t\tconst signal = combineSignals(sessionSignal, actionSignal);\n\t\t\t\ttry {\n\t\t\t\t\tconst currentConfig = await loadConfig(state.decision.setupName);\n\t\t\t\t\tif (signal.aborted) return { kind: \"close\" as const };\n\t\t\t\t\tassertLocalSelectionCurrent(currentConfig, state.decision);\n\t\t\t\t\tif (\n\t\t\t\t\t\t!currentConfig.include.includes(\"sessions\") &&\n\t\t\t\t\t\tstate.decision.remoteInclude.includes(\"sessions\")\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst acknowledged = await ctx.ui.confirm(\n\t\t\t\t\t\t\t\"Use a content list that includes session conversations?\",\n\t\t\t\t\t\t\t\"Session JSONL may contain prompts, tool output, file paths, images, and secrets. This saves the list only; it does not pull files.\",\n\t\t\t\t\t\t\t{ signal },\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (signal.aborted) return { kind: \"close\" as const };\n\t\t\t\t\t\tif (!acknowledged) return { kind: \"stay\" as const };\n\t\t\t\t\t}\n\t\t\t\t\tconst review = await runWithOptionalStateAccess(options, async () => {\n\t\t\t\t\t\tconst loaded = await loadAdoptionReview(state.decision, signal, factory);\n\t\t\t\t\t\tif (signal.aborted) throw signal.reason;\n\t\t\t\t\t\tawait revalidateAndAdopt(loaded, state.decision, signal);\n\t\t\t\t\t\treturn loaded;\n\t\t\t\t\t});\n\t\t\t\t\tif (signal.aborted) return { kind: \"close\" as const };\n\t\t\t\t\toptions.onSelectionResolved?.();\n\t\t\t\t\tcontinuationReview = {\n\t\t\t\t\t\t...review.storageReview,\n\t\t\t\t\t\tsetupName: state.decision.setupName,\n\t\t\t\t\t\tinclude: [...state.decision.remoteInclude],\n\t\t\t\t\t\tautomatic: review.config.automatic,\n\t\t\t\t\t\tonSwitch: review.config.onSwitch,\n\t\t\t\t\t};\n\t\t\t\t\tflowState = { decision: state.decision, saved: true };\n\t\t\t\t\treturn { kind: \"to\" as const, screen: \"saved\" as const };\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (signal.aborted) return { kind: \"close\" as const };\n\t\t\t\t\tif (isStaleReviewError(error)) {\n\t\t\t\t\t\tctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, \"warning\");\n\t\t\t\t\t\trefreshRequested = true;\n\t\t\t\t\t\treturn { kind: \"close\" as const };\n\t\t\t\t\t}\n\t\t\t\t\tctx.ui.notify(`Could not save the remote content list: ${errorMessage(error)}`, \"error\");\n\t\t\t\t\treturn { kind: \"stay\" as const };\n\t\t\t\t}\n\t\t\t},\n\t\t\tkeep: async ({ state, signal: actionSignal }) => {\n\t\t\t\tif (!runRoute) {\n\t\t\t\t\tctx.ui.notify(\"The reviewed update-remote route is unavailable.\", \"error\");\n\t\t\t\t\treturn { kind: \"stay\" as const };\n\t\t\t\t}\n\t\t\t\tconst signal = combineSignals(sessionSignal, actionSignal);\n\t\t\t\ttry {\n\t\t\t\t\tconst latest = await loadConfig(state.decision.setupName);\n\t\t\t\t\tif (signal.aborted) return { kind: \"close\" as const };\n\t\t\t\t\tassertLocalSelectionCurrent(latest, state.decision);\n\t\t\t\t\tconst result = await runCancellableOperation(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"Preparing this device's push preview\u2026\",\n\t\t\t\t\t\t\"push --force\",\n\t\t\t\t\t\trunRoute,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommitAware: true,\n\t\t\t\t\t\t\tcancelledMessage: \"Push preparation cancelled; no remote files were changed.\",\n\t\t\t\t\t\t\ttarget: state.decision.setupName,\n\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\treturn handleNestedRouteResult(result, \"push\");\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (signal.aborted) return { kind: \"close\" as const };\n\t\t\t\t\tif (isStaleReviewError(error)) {\n\t\t\t\t\t\tctx.ui.notify(`${errorMessage(error)} Refreshing the comparison.`, \"warning\");\n\t\t\t\t\t\trefreshRequested = true;\n\t\t\t\t\t\treturn { kind: \"close\" as const };\n\t\t\t\t\t}\n\t\t\t\t\tctx.ui.notify(`Could not prepare the remote update: ${errorMessage(error)}`, \"error\");\n\t\t\t\t\treturn { kind: \"stay\" as const };\n\t\t\t\t}\n\t\t\t},\n\t\t\tcontinue: async ({ state, signal: actionSignal }) => {\n\t\t\t\tif (!runRoute || !continuationReview) return { kind: \"stay\" as const };\n\t\t\t\tconst signal = combineSignals(sessionSignal, actionSignal);\n\t\t\t\ttry {\n\t\t\t\t\tconst latest = await loadPartialConfig(state.decision.setupName);\n\t\t\t\t\tif (signal.aborted) return { kind: \"close\" as const };\n\t\t\t\t\tif (!sameContinuationReview(latest, continuationReview)) {\n\t\t\t\t\t\tthrow new StaleRemoteSelectionReviewError(\n\t\t\t\t\t\t\t`Sync setup \u201C${safeTerminalText(state.decision.setupName)}\u201D changed after the remote content list was saved.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst result = await runCancellableOperation(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\tcontinueBusyLabel(origin),\n\t\t\t\t\t\troute,\n\t\t\t\t\t\trunRoute,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommitAware: true,\n\t\t\t\t\t\t\tcancelledMessage: continuationCancelledMessage(route),\n\t\t\t\t\t\t\ttarget: state.decision.setupName,\n\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\treturn handleNestedRouteResult(result, route);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (signal.aborted) return { kind: \"close\" as const };\n\t\t\t\t\tctx.ui.notify(`Could not continue: ${errorMessage(error)}`, \"error\");\n\t\t\t\t\treturn { kind: \"stay\" as const };\n\t\t\t\t}\n\t\t\t},\n\t\t\tcancel: async () => ({ kind: \"back\" }),\n\t\t\tdone: async () => {\n\t\t\t\tnextResult = { kind: \"done\" };\n\t\t\t\treturn { kind: \"close\" };\n\t\t\t},\n\t\t},\n\t});\n\n\tfunction handleNestedRouteResult(\n\t\tresult: Awaited<ReturnType<typeof runCancellableOperation>>,\n\t\tnestedRoute: \"sync\" | \"pull\" | \"push\",\n\t) {\n\t\tif (result.kind === \"completed\" && result.outcome === \"applied\") {\n\t\t\toptions.onSelectionResolved?.();\n\t\t}\n\t\tif (result.kind === \"closed\") {\n\t\t\tnextResult = { kind: \"closed\" };\n\t\t\treturn { kind: \"close\" as const };\n\t\t}\n\t\tif (\n\t\t\tresult.kind === \"cancelled\" ||\n\t\t\t(result.kind === \"completed\" && result.outcome === \"cancelled\") ||\n\t\t\tresult.kind === \"failed\"\n\t\t) {\n\t\t\treturn { kind: \"stay\" as const };\n\t\t}\n\t\tnextResult = { kind: \"route-result\", result, route: nestedRoute };\n\t\treturn { kind: \"close\" as const };\n\t}\n\n\tconst menuResult = await runMenu(ctx, menu, {\n\t\tgetState: () => flowState,\n\t\tsignal: sessionSignal,\n\t\tisCurrent: () => !sessionSignal?.aborted,\n\t\tonError: (_menuCtx, error) => ctx.ui.notify(errorMessage(error), \"error\"),\n\t});\n\tif (sessionSignal?.aborted || menuResult.kind === \"stale\") return { kind: \"stale\" };\n\tif (refreshRequested) return { kind: \"refresh\" };\n\tif (nextResult) return nextResult;\n\tif (menuResult.kind === \"closed\") {\n\t\treturn menuResult.reason === \"back\" ? { kind: \"back\" } : { kind: \"closed\" };\n\t}\n\treturn { kind: \"closed\" };\n}\n\ninterface AdoptionReview {\n\tconfig: AnySyncConfig;\n\tstorageReview: SyncSetupStorageReview;\n\tbackend: SyncBackend;\n\treviewedHead: RemoteHead;\n}\n\nasync function loadAdoptionReview(\n\tdecision: RemoteSelectionDecision,\n\tsignal: AbortSignal,\n\tfactory: SyncBackendFactory,\n): Promise<AdoptionReview> {\n\tconst config = await loadConfig(decision.setupName);\n\tthrowIfAborted(signal);\n\tassertLocalSelectionCurrent(config, decision);\n\tconst partial = await loadPartialConfig(decision.setupName);\n\tthrowIfAborted(signal);\n\tif (!sameSyncInclude(partial.include, decision.localInclude)) {\n\t\tthrow new StaleRemoteSelectionReviewError(\n\t\t\t`Sync setup \u201C${safeTerminalText(decision.setupName)}\u201D changed while the comparison was open.`,\n\t\t);\n\t}\n\tconst backend = await factory(config);\n\tthrowIfAborted(signal);\n\tconst reviewedHead = await backend.readHead(signal);\n\tthrowIfAborted(signal);\n\tif (!reviewedHead) {\n\t\tthrow new StaleRemoteSelectionReviewError(\n\t\t\t\"Remote storage changed while the comparison was open.\",\n\t\t);\n\t}\n\tconst snapshot = await readSnapshotForHead(backend, reviewedHead, signal);\n\tthrowIfAborted(signal);\n\tconst state = inspectRemoteSelection(config.include, snapshot);\n\tif (state.kind !== \"different\" || !sameSyncInclude(state.include, decision.remoteInclude)) {\n\t\tthrow new StaleRemoteSelectionReviewError(\n\t\t\t\"Remote synced content changed while the comparison was open.\",\n\t\t);\n\t}\n\treturn { config, storageReview: partial, backend, reviewedHead };\n}\n\nasync function revalidateAndAdopt(\n\treview: AdoptionReview,\n\tdecision: RemoteSelectionDecision,\n\tsignal: AbortSignal,\n) {\n\tconst currentHead = await review.backend.readHead(signal);\n\tthrowIfAborted(signal);\n\tif (\n\t\t!currentHead ||\n\t\t!review.backend.sameRevision(review.reviewedHead.revision, currentHead.revision)\n\t) {\n\t\tthrow new StaleRemoteSelectionReviewError(\n\t\t\t\"Remote storage changed while the comparison was open.\",\n\t\t);\n\t}\n\tconst currentSnapshot = await readSnapshotForHead(review.backend, currentHead, signal);\n\tthrowIfAborted(signal);\n\tconst currentState = inspectRemoteSelection(review.config.include, currentSnapshot);\n\tif (\n\t\tcurrentState.kind !== \"different\" ||\n\t\t!sameSyncInclude(currentState.include, decision.remoteInclude)\n\t) {\n\t\tthrow new StaleRemoteSelectionReviewError(\n\t\t\t\"Remote synced content changed while the comparison was open.\",\n\t\t);\n\t}\n\tawait updateSyncSetup(\n\t\tdecision.setupName,\n\t\t(setup) => ({\n\t\t\t...setup,\n\t\t\tsync: { ...setup.sync, include: [...decision.remoteInclude] },\n\t\t}),\n\t\t{\n\t\t\texpectedStorage: review.storageReview,\n\t\t\texpectedInclude: decision.localInclude,\n\t\t\tsignal,\n\t\t},\n\t);\n}\n\nasync function inspectConfiguredRemoteSelection(\n\tctx: ExtensionContext,\n\tsetupName: string | undefined,\n\tsignal: AbortSignal | undefined,\n\tfactory: SyncBackendFactory,\n): Promise<\n\t| { kind: \"empty\"; config: AnySyncConfig }\n\t| { kind: \"selection\"; config: AnySyncConfig; state: RemoteSelectionState }\n\t| undefined\n> {\n\tconst config = await loadConfig(setupName);\n\tif (signal?.aborted) return undefined;\n\tctx.ui.setStatus(STATUS_KEY, `checking synced content for ${safeTerminalText(config.setupName)}`);\n\tconst backend = await factory(config);\n\tif (signal?.aborted) return undefined;\n\tconst head = await backend.readHead(signal);\n\tif (signal?.aborted) return undefined;\n\tif (!head) return { kind: \"empty\", config };\n\tconst snapshot = await readSnapshotForHead(backend, head, signal);\n\tif (signal?.aborted) return undefined;\n\treturn {\n\t\tkind: \"selection\",\n\t\tconfig,\n\t\tstate: inspectRemoteSelection(config.include, snapshot),\n\t};\n}\n\nasync function showLegacyDiscovery(\n\tctx: ExtensionContext,\n\tconfig: AnySyncConfig,\n\tdiscovered: string[],\n\tsignal?: AbortSignal,\n) {\n\tconst menu = defineMenu<undefined, \"choice\" | \"review\", \"back\", ExtensionContext>({\n\t\tstart: \"choice\",\n\t\tscreens: {\n\t\t\tchoice: () => ({\n\t\t\t\tkind: \"actions\",\n\t\t\t\ttitle: `Compare synced content \u00B7 ${safeTerminalText(config.setupName)}`,\n\t\t\t\tlines: [\n\t\t\t\t\t\"This legacy snapshot has no portable synced-content list.\",\n\t\t\t\t\t\"Discovered paths are partial and read-only; preserved files may not have been selected.\",\n\t\t\t\t],\n\t\t\t\titems: [\n\t\t\t\t\t{ id: \"review\", label: \"Review discovered paths\", to: \"review\" },\n\t\t\t\t\t{ id: \"back\", label: \"Back\", action: \"back\" },\n\t\t\t\t],\n\t\t\t\thint: \"close\",\n\t\t\t}),\n\t\t\treview: () => ({\n\t\t\t\tkind: \"review\",\n\t\t\t\ttitle: \"Partial discovery from legacy snapshot\",\n\t\t\t\tcontent: [\n\t\t\t\t\t\"Partial discovery only \u2014 not an authoritative selection.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t...(discovered.length > 0\n\t\t\t\t\t\t? discovered.map((item) => `Discovered: ${safeTerminalText(item)}`)\n\t\t\t\t\t\t: [\"No safe paths were discovered.\"]),\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Use Add custom path\u2026 in the local Included Content editor if needed.\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\tformat: { kind: \"text\" },\n\t\t\t\tviewportSize: \"adaptive\",\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t},\n\t\tactions: { back: async () => ({ kind: \"close\" }) },\n\t});\n\tawait runMenu(ctx, menu, {\n\t\tgetState: () => undefined,\n\t\tsignal,\n\t\tisCurrent: () => !signal?.aborted,\n\t});\n}\n\nfunction selectionSummaryLines(decision: RemoteSelectionDecision) {\n\tconst comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n\treturn [\n\t\t`Sync setup: ${safeTerminalText(decision.setupName)}`,\n\t\t\"Nothing changed. Review both lists before choosing what happens next.\",\n\t\t...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n\t\t\t? [\"Only the ordering differs; membership is the same.\"]\n\t\t\t: [\n\t\t\t\t\t`Remote-only paths: ${comparison.remoteOnly.length} \u00B7 Device-only paths: ${comparison.localOnly.length}`,\n\t\t\t\t]),\n\t];\n}\n\nfunction formatSelectionDifference(decision: RemoteSelectionDecision) {\n\tconst comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n\treturn [\n\t\t...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n\t\t\t? [\"Only ordering differs; both lists contain the same paths.\", \"\"]\n\t\t\t: []),\n\t\t\"Remote-only paths:\",\n\t\t...(comparison.remoteOnly.length > 0\n\t\t\t? comparison.remoteOnly.map((item) => `+ ${safeTerminalText(item)}`)\n\t\t\t: [\"(none)\"]),\n\t\t\"\",\n\t\t\"Device-only paths:\",\n\t\t...(comparison.localOnly.length > 0\n\t\t\t? comparison.localOnly.map((item) => `- ${safeTerminalText(item)}`)\n\t\t\t: [\"(none)\"]),\n\t\t\"\",\n\t\t\"Remote ordered list:\",\n\t\t...(decision.remoteInclude.length > 0\n\t\t\t? decision.remoteInclude.map((item, index) => `${index + 1}. ${safeTerminalText(item)}`)\n\t\t\t: [\"(none)\"]),\n\t\t\"\",\n\t\t\"This device's ordered list:\",\n\t\t...(decision.localInclude.length > 0\n\t\t\t? decision.localInclude.map((item, index) => `${index + 1}. ${safeTerminalText(item)}`)\n\t\t\t: [\"(none)\"]),\n\t\t\"\",\n\t\t\"Using the remote list saves settings only and does not pull files.\",\n\t].join(\"\\n\");\n}\n\nfunction formatRemoteSelectionSummary(decision: RemoteSelectionDecision) {\n\tconst comparison = compareSyncInclude(decision.localInclude, decision.remoteInclude);\n\treturn [\n\t\t`Synced content for \u201C${safeTerminalText(decision.setupName)}\u201D differs from this device.`,\n\t\t`Remote-only: ${safeList(comparison.remoteOnly)}`,\n\t\t`Device-only: ${safeList(comparison.localOnly)}`,\n\t\t...(comparison.remoteOnly.length === 0 && comparison.localOnly.length === 0\n\t\t\t? [\n\t\t\t\t\t\"Only ordering differs.\",\n\t\t\t\t\t`Remote order: ${safeList(decision.remoteInclude)}`,\n\t\t\t\t\t`Device order: ${safeList(decision.localInclude)}`,\n\t\t\t\t]\n\t\t\t: []),\n\t\t\"Run /sync in TUI to choose a content list; RPC review is read-only.\",\n\t].join(\"\\n\");\n}\n\nfunction formatLegacySummary(config: AnySyncConfig, discovered: readonly string[]) {\n\treturn `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\tconfig: AnySyncConfig,\n\tstate: Extract<RemoteSelectionState, { kind: \"different\" }>,\n): RemoteSelectionDecision {\n\treturn {\n\t\tsetupName: config.setupName,\n\t\tconfigIdentity: syncConfigReviewFingerprint(config),\n\t\tlocalInclude: [...config.include],\n\t\tremoteInclude: [...state.include],\n\t};\n}\n\nfunction assertLocalSelectionCurrent(config: AnySyncConfig, decision: RemoteSelectionDecision) {\n\tif (\n\t\tsyncConfigReviewFingerprint(config) === decision.configIdentity &&\n\t\tsameSyncInclude(config.include, decision.localInclude)\n\t) {\n\t\treturn;\n\t}\n\tthrow new StaleRemoteSelectionReviewError(\n\t\t`Sync setup \u201C${safeTerminalText(config.setupName)}\u201D changed while the comparison was open.`,\n\t);\n}\n\nfunction sameContinuationReview(left: PartialConfig, right: PartialConfig) {\n\treturn (\n\t\tleft.setupName === right.setupName &&\n\t\tleft.connectionName === right.connectionName &&\n\t\tleft.storageKind === right.storageKind &&\n\t\tleft.storagePath === right.storagePath &&\n\t\tleft.bucket === right.bucket &&\n\t\tleft.branch === right.branch &&\n\t\tsameSyncInclude(left.include, right.include)\n\t);\n}\n\nfunction continueLabel(origin: RemoteSelectionOrigin) {\n\tif (origin === \"pull\") return \"Continue Pull now\u2026\";\n\tif (origin === \"push\") return \"Continue Push now\u2026\";\n\treturn \"Continue Sync now\u2026\";\n}\n\nfunction continueBusyLabel(origin: RemoteSelectionOrigin) {\n\tif (origin === \"pull\") return \"Checking remote changes\u2026\";\n\tif (origin === \"push\") return \"Preparing push preview\u2026\";\n\treturn \"Checking current sync setup\u2026\";\n}\n\nfunction continuationCancelledMessage(route: \"sync\" | \"pull\" | \"push\") {\n\tif (route === \"pull\") return \"Pull check cancelled; no local files were changed.\";\n\tif (route === \"push\") return \"Push preparation cancelled; no remote files were changed.\";\n\treturn \"Sync check cancelled; no settings or files were changed.\";\n}\n\nfunction safeList(values: readonly string[]) {\n\treturn values.length > 0 ? values.map(safeTerminalText).join(\", \") : \"none\";\n}\n\nclass StaleRemoteSelectionReviewError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"StaleRemoteSelectionReviewError\";\n\t}\n}\n\nfunction isStaleReviewError(error: unknown) {\n\treturn (\n\t\terror instanceof StaleRemoteSelectionReviewError || error instanceof SyncSetupReviewChangedError\n\t);\n}\n\nfunction runWithOptionalStateAccess<T>(\n\toptions: Pick<RemoteSelectionReviewOptions, \"withStateAccess\">,\n\ttask: () => Promise<T>,\n) {\n\treturn options.withStateAccess ? options.withStateAccess(task) : task();\n}\n\nfunction combineSignals(sessionSignal: AbortSignal | undefined, actionSignal: AbortSignal) {\n\treturn sessionSignal ? AbortSignal.any([sessionSignal, actionSignal]) : actionSignal;\n}\n\nfunction throwIfAborted(signal: AbortSignal) {\n\tif (!signal.aborted) return;\n\tthrow signal.reason instanceof Error\n\t\t? signal.reason\n\t\t: new DOMException(\"The operation was aborted\", \"AbortError\");\n}\n", "import {\n\tBorderedLoader,\n\ttype ExtensionContext,\n\ttype KeybindingsManager,\n} from \"@earendil-works/pi-coding-agent\";\nimport { Key, matchesKey, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { 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\";\nimport { safeTerminalText } from \"./terminal-text.js\";\n\nexport type RunRouteResult =\n\t| { kind: \"completed\"; outcome?: SetupPullOutcome }\n\t| { kind: \"decision-required\"; decision: SyncDecision }\n\t| { kind: \"remote-selection-required\"; decision: RemoteSelectionDecision }\n\t| { kind: \"failed\" };\n\nexport type RunRoute = (\n\troute: string,\n\tsignal?: AbortSignal,\n\tonCommit?: () => void,\n\ttarget?: string,\n) => Promise<RunRouteResult | undefined>;\n\nexport type CancellableOperationResult =\n\t| RunRouteResult\n\t| { kind: \"closed\" }\n\t| { kind: \"cancelled\" };\n\ninterface CancellableOperationOptions {\n\tcommitAware?: boolean;\n\tcancelledMessage?: string | null;\n\ttarget?: string;\n\tsignal?: AbortSignal;\n}\n\nexport async function runCancellableOperation(\n\tctx: ExtensionContext,\n\tmessage: string,\n\troute: string,\n\trunRoute: RunRoute,\n\toptions: CancellableOperationOptions = {},\n): Promise<CancellableOperationResult> {\n\tconst {\n\t\tcommitAware = false,\n\t\tcancelledMessage = \"Check cancelled; no settings or files were changed.\",\n\t\ttarget,\n\t\tsignal,\n\t} = options;\n\tif (ctx.mode !== \"tui\") {\n\t\treturn (await runRoute(route, signal, undefined, target)) ?? { kind: \"failed\" };\n\t}\n\tlet commitStarted = false;\n\tlet routeResult: RunRouteResult | undefined;\n\tconst interaction = await runCustomInteraction<\n\t\t{ cancelled?: boolean; error?: unknown },\n\t\tExtensionContext\n\t>(ctx, {\n\t\tsignal,\n\t\tisCurrent: () => !signal?.aborted,\n\t\tcreate: ({ tui, theme, keybindings, signal: interactionSignal, complete }) => {\n\t\t\tconst loader = new BorderedLoader(tui, theme, message, { cancellable: false });\n\t\t\tconst cancelHint = `${keybindingText(keybindings, \"tui.select.cancel\", \"esc\")} cancel`;\n\t\t\tconst operation = runRoute(\n\t\t\t\troute,\n\t\t\t\tinteractionSignal,\n\t\t\t\tcommitAware ? () => (commitStarted = true) : undefined,\n\t\t\t\ttarget,\n\t\t\t).then(\n\t\t\t\t(result) => {\n\t\t\t\t\trouteResult = result;\n\t\t\t\t\tcomplete({});\n\t\t\t\t},\n\t\t\t\t(error: unknown) => complete({ error }),\n\t\t\t);\n\t\t\treturn {\n\t\t\t\trender(width: number) {\n\t\t\t\t\tconst safeWidth = Math.max(1, width);\n\t\t\t\t\tconst lines = loader.render(safeWidth);\n\t\t\t\t\tconst bottomBorder = lines.at(-1);\n\t\t\t\t\treturn [\n\t\t\t\t\t\t...lines.slice(0, -1),\n\t\t\t\t\t\ttruncateToWidth(theme.fg(\"dim\", cancelHint), safeWidth, \"\"),\n\t\t\t\t\t\t...(bottomBorder === undefined ? [] : [bottomBorder]),\n\t\t\t\t\t];\n\t\t\t\t},\n\t\t\t\tinvalidate: () => loader.invalidate(),\n\t\t\t\thandleInput(data: string) {\n\t\t\t\t\tif (!matchesKey(data, Key.ctrl(\"c\")) && !keybindings.matches(data, \"tui.select.cancel\")) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (commitStarted) {\n\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t\"Applying or publishing has started and cannot be cancelled safely.\",\n\t\t\t\t\t\t\t\"warning\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcomplete({ cancelled: true });\n\t\t\t\t},\n\t\t\t\tdispose: () => loader.dispose(),\n\t\t\t\twaitForPending: () => operation,\n\t\t\t};\n\t\t},\n\t});\n\tif (interaction.kind === \"error\") throw interaction.error;\n\tif (interaction.kind !== \"completed\") return { kind: \"closed\" };\n\tif (interaction.value.cancelled) {\n\t\tif (cancelledMessage) ctx.ui.notify(cancelledMessage, \"info\");\n\t\treturn { kind: \"cancelled\" };\n\t}\n\tif (interaction.value.error) throw interaction.value.error;\n\treturn routeResult ?? { kind: \"failed\" };\n}\n\nfunction keybindingText(\n\tkeybindings: Pick<KeybindingsManager, \"getKeys\">,\n\tbinding: Parameters<KeybindingsManager[\"getKeys\"]>[0],\n\tfallback: string,\n) {\n\tconst keys = [...new Set([...keybindings.getKeys(binding), \"ctrl+c\"])]\n\t\t.map(String)\n\t\t.map((key) => {\n\t\t\tif (key === \"return\") return \"enter\";\n\t\t\tif (key === \"escape\") return \"esc\";\n\t\t\treturn safeTerminalText(key);\n\t\t})\n\t\t.filter(Boolean);\n\treturn keys.join(\"/\") || fallback;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// @generated by scripts/build-runtime.mjs; do not edit.
|
|
2
|
+
// @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
|
|
3
|
+
|
|
4
|
+
// src/ui/automatic-sync-summary.ts
|
|
5
|
+
function automaticSyncSummary(enabled) {
|
|
6
|
+
return enabled ? "On (startup check; shutdown pushes selected content if sessions included)" : "Off";
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
automaticSyncSummary
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=chunk-Z4DQF6L3.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/ui/automatic-sync-summary.ts"],
|
|
4
|
+
"sourcesContent": ["/** Keep the setting's automatic transfer scope visible in every setup summary. */\nexport function automaticSyncSummary(enabled: boolean) {\n\treturn enabled\n\t\t? \"On (startup check; shutdown pushes selected content if sessions included)\"\n\t\t: \"Off\";\n}\n"],
|
|
5
|
+
"mappings": ";;;;AACO,SAAS,qBAAqB,SAAkB;AACtD,SAAO,UACJ,8EACA;AACJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,107 +1,18 @@
|
|
|
1
1
|
// @generated by scripts/build-runtime.mjs; do not edit.
|
|
2
2
|
// @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
|
|
3
3
|
|
|
4
|
-
// src/
|
|
5
|
-
var DEFAULT_GIT_BRANCH = "pi-sync";
|
|
6
|
-
var DEFAULT_GIT_DIRECTORY = "pi-sync";
|
|
7
|
-
function normalizeGitRemote(value) {
|
|
8
|
-
const normalized = normalizeOptionalString(value);
|
|
9
|
-
if (!normalized) return void 0;
|
|
10
|
-
if (hasControlCharacter(normalized) || /\s/u.test(normalized) || normalized.startsWith("-") || normalized.includes("\\")) {
|
|
11
|
-
throw new Error("Invalid pi-sync Git remote.");
|
|
12
|
-
}
|
|
13
|
-
if (!normalized.includes("://") && /^(?:[A-Za-z0-9._-]+@)?(?:\[[0-9A-Fa-f:]+\]|[A-Za-z0-9.-]+):(?!-)[^:].+$/u.test(normalized)) {
|
|
14
|
-
return normalized;
|
|
15
|
-
}
|
|
16
|
-
if (/^[A-Za-z][A-Za-z0-9+.-]*:/u.test(normalized) && !normalized.includes("://")) {
|
|
17
|
-
throw new Error("Invalid pi-sync Git remote: unsupported transport or remote-helper syntax.");
|
|
18
|
-
}
|
|
19
|
-
let url;
|
|
20
|
-
try {
|
|
21
|
-
url = new URL(normalized);
|
|
22
|
-
} catch {
|
|
23
|
-
throw new Error("Invalid pi-sync Git remote: use an SSH or HTTPS remote.");
|
|
24
|
-
}
|
|
25
|
-
if (url.protocol !== "https:" && url.protocol !== "ssh:") {
|
|
26
|
-
throw new Error("Invalid pi-sync Git remote: only SSH and HTTPS are supported.");
|
|
27
|
-
}
|
|
28
|
-
if (url.password || url.protocol === "https:" && url.username) {
|
|
29
|
-
throw new Error("Invalid pi-sync Git remote: URL credentials or userinfo are not allowed.");
|
|
30
|
-
}
|
|
31
|
-
if (url.search || url.hash || !url.hostname || !url.pathname || url.pathname === "/") {
|
|
32
|
-
throw new Error("Invalid pi-sync Git remote.");
|
|
33
|
-
}
|
|
34
|
-
return url.toString();
|
|
35
|
-
}
|
|
36
|
-
function normalizeGitRemoteIdentity(value) {
|
|
37
|
-
const normalized = normalizeGitRemote(value);
|
|
38
|
-
if (!normalized) return "";
|
|
39
|
-
if (!normalized.includes("://")) {
|
|
40
|
-
const match = /^(?<user>[A-Za-z0-9._-]+@)?(?<host>\[[0-9A-Fa-f:]+\]|[A-Za-z0-9.-]+):(?<path>.+)$/u.exec(
|
|
41
|
-
normalized
|
|
42
|
-
);
|
|
43
|
-
if (!match?.groups) return normalized;
|
|
44
|
-
const userAndHost = `${match.groups.user ?? ""}${match.groups.host.toLowerCase()}`;
|
|
45
|
-
const remotePath = match.groups.path.replace(/\/+$/gu, "");
|
|
46
|
-
return remotePath.startsWith("/") ? `scp-absolute://${userAndHost}${remotePath}` : `ssh://${userAndHost}/${remotePath}`;
|
|
47
|
-
}
|
|
48
|
-
const url = new URL(normalized);
|
|
49
|
-
url.hostname = url.hostname.toLowerCase();
|
|
50
|
-
if (url.protocol === "ssh:" && url.port === "22") url.port = "";
|
|
51
|
-
url.pathname = url.pathname.replace(/\/+$/gu, "");
|
|
52
|
-
if (url.protocol === "ssh:") {
|
|
53
|
-
return `ssh://${url.username ? `${url.username}@` : ""}${url.host}${url.pathname}`;
|
|
54
|
-
}
|
|
55
|
-
return url.toString();
|
|
56
|
-
}
|
|
57
|
-
function normalizeGitBranch(value) {
|
|
58
|
-
const branch = normalizeOptionalString(value) ?? DEFAULT_GIT_BRANCH;
|
|
59
|
-
if (branch === "@" || branch.startsWith("-") || branch.startsWith("refs/") || branch.startsWith("/") || branch.endsWith("/") || branch.endsWith(".") || branch.includes("..") || branch.includes("@{") || branch.includes("\\") || hasControlCharacter(branch) || /[ ~^:?*[\]]/u.test(branch) || branch.split("/").some((segment) => !segment || segment.startsWith(".") || segment.endsWith(".lock"))) {
|
|
60
|
-
throw new Error("Invalid pi-sync Git branch.");
|
|
61
|
-
}
|
|
62
|
-
return branch;
|
|
63
|
-
}
|
|
64
|
-
function normalizeGitDirectory(value) {
|
|
65
|
-
const directory = trimSlashes(normalizeOptionalString(value) ?? DEFAULT_GIT_DIRECTORY);
|
|
66
|
-
if (!directory || directory.startsWith("-") || directory.includes("\\") || hasControlCharacter(directory) || directory.split("/").some((segment) => !segment || segment === "." || segment === ".." || segment === ".git")) {
|
|
67
|
-
throw new Error("Invalid pi-sync Git directory.");
|
|
68
|
-
}
|
|
69
|
-
return directory;
|
|
70
|
-
}
|
|
71
|
-
function validateGitNamespace(value) {
|
|
72
|
-
if (value.length > 256 || value === "." || value === ".." || value.includes("/") || value.includes("\\") || hasControlCharacter(value)) {
|
|
73
|
-
throw new Error("Invalid pi-sync Git namespace.");
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
function normalizeOptionalString(value) {
|
|
77
|
-
if (value !== void 0 && typeof value !== "string") {
|
|
78
|
-
throw new Error("Invalid pi-sync settings: expected a string.");
|
|
79
|
-
}
|
|
80
|
-
const normalized = value?.trim();
|
|
81
|
-
return normalized || void 0;
|
|
82
|
-
}
|
|
83
|
-
function trimSlashes(value) {
|
|
84
|
-
return value.replace(/^\/+|\/+$/gu, "");
|
|
85
|
-
}
|
|
86
|
-
function hasControlCharacter(value) {
|
|
87
|
-
return [...value].some((character) => {
|
|
88
|
-
const code = character.codePointAt(0) ?? 0;
|
|
89
|
-
return code < 32 || code >= 127 && code <= 159;
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// src/state-directory.ts
|
|
4
|
+
// src/state/state-directory.ts
|
|
94
5
|
import { lstatSync } from "node:fs";
|
|
95
6
|
import fs from "node:fs/promises";
|
|
96
7
|
import path from "node:path";
|
|
97
8
|
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
98
9
|
import lockfile from "proper-lockfile";
|
|
99
10
|
|
|
100
|
-
// src/lock-policy.ts
|
|
11
|
+
// src/state/lock-policy.ts
|
|
101
12
|
var LOCK_GUARD_STALE_MS = 3e4;
|
|
102
13
|
var LOCK_GUARD_UPDATE_MS = 1e4;
|
|
103
14
|
|
|
104
|
-
// src/lockfile-fs.ts
|
|
15
|
+
// src/state/lockfile-fs.ts
|
|
105
16
|
import {
|
|
106
17
|
mkdir,
|
|
107
18
|
mkdirSync,
|
|
@@ -127,7 +38,7 @@ var LOCKFILE_FS_ADAPTER = {
|
|
|
127
38
|
utimesSync
|
|
128
39
|
};
|
|
129
40
|
|
|
130
|
-
// src/state-directory.ts
|
|
41
|
+
// src/state/state-directory.ts
|
|
131
42
|
var CANONICAL_DIRECTORY_NAME = "pi-sync";
|
|
132
43
|
var LEGACY_DIRECTORY_NAME = ".pisync";
|
|
133
44
|
var MIGRATION_LOCK_NAME = ".pi-sync-state-migration.lock";
|
|
@@ -325,11 +236,6 @@ async function pathExists(filePath) {
|
|
|
325
236
|
}
|
|
326
237
|
|
|
327
238
|
export {
|
|
328
|
-
normalizeGitRemote,
|
|
329
|
-
normalizeGitRemoteIdentity,
|
|
330
|
-
normalizeGitBranch,
|
|
331
|
-
normalizeGitDirectory,
|
|
332
|
-
validateGitNamespace,
|
|
333
239
|
LOCK_GUARD_STALE_MS,
|
|
334
240
|
LOCK_GUARD_UPDATE_MS,
|
|
335
241
|
LOCKFILE_FS_ADAPTER,
|
|
@@ -338,4 +244,4 @@ export {
|
|
|
338
244
|
withStateDirectoryAccess,
|
|
339
245
|
migrateLegacyStateDirectory
|
|
340
246
|
};
|
|
341
|
-
//# sourceMappingURL=chunk-
|
|
247
|
+
//# sourceMappingURL=chunk-ZI5MXMEX.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/state/state-directory.ts", "../../src/state/lock-policy.ts", "../../src/state/lockfile-fs.ts"],
|
|
4
|
+
"sourcesContent": ["import { lstatSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { getAgentDir } from \"@earendil-works/pi-coding-agent\";\nimport lockfile from \"proper-lockfile\";\nimport { LOCK_GUARD_STALE_MS } from \"./lock-policy.js\";\nimport { LOCKFILE_FS_ADAPTER } from \"./lockfile-fs.js\";\n\nconst CANONICAL_DIRECTORY_NAME = \"pi-sync\";\nconst LEGACY_DIRECTORY_NAME = \".pisync\";\nconst MIGRATION_LOCK_NAME = \".pi-sync-state-migration.lock\";\nconst MIGRATION_LOCK_STALE_MS = 30_000;\nconst MIGRATION_LOCK_UPDATE_MS = 10_000;\n\nexport type StateDirectoryPreparation =\n\t| { status: \"ready\" }\n\t| { status: \"migrated\"; message: string }\n\t| { status: \"deferred\"; message: string };\n\ninterface StateDirectoryGuard {\n\trelease: () => Promise<void>;\n\tthrowIfCompromised: () => void;\n}\n\ninterface SharedStateDirectoryGuard {\n\tguard: Promise<StateDirectoryGuard>;\n\tusers: number;\n\tclosing?: Promise<void>;\n}\n\nconst sharedStateDirectoryGuards = new Map<string, SharedStateDirectoryGuard>();\n\nexport function stateDir() {\n\tconst roots = inspectStateRoots();\n\tif (roots.canonical) return canonicalStateDir();\n\tif (roots.legacy) return legacyStateDir();\n\treturn canonicalStateDir();\n}\n\nexport function legacyStateDir() {\n\treturn path.join(getAgentDir(), LEGACY_DIRECTORY_NAME);\n}\n\nexport function stateDirectoryMigrationNotice() {\n\tconst roots = inspectStateRoots();\n\tif (!roots.legacy) return undefined;\n\treturn \"Legacy pi-sync state is still stored in .pisync. Close other Pi sessions, then run /sync migrate-state to move it to pi-sync/.\";\n}\n\nexport async function withStateDirectoryAccess<T>(fn: () => Promise<T>): Promise<T> {\n\tconst roots = inspectStateRoots();\n\tif (!roots.legacy) return fn();\n\treturn runWithStateDirectoryGuard(await acquireSharedStateDirectoryGuard(), fn);\n}\n\nexport async function migrateLegacyStateDirectory(): Promise<StateDirectoryPreparation> {\n\tconst initial = inspectStateRoots();\n\tif (initial.canonical || !initial.legacy) return { status: \"ready\" };\n\n\tlet guard: StateDirectoryGuard;\n\ttry {\n\t\tguard = await acquireStateDirectoryGuard();\n\t} catch (error) {\n\t\tif (!isLockHeldError(error)) throw error;\n\t\treturn {\n\t\t\tstatus: \"deferred\",\n\t\t\tmessage:\n\t\t\t\t\"pi-sync state migration was deferred because another state user is active. Close other Pi sessions and retry.\",\n\t\t};\n\t}\n\treturn runWithStateDirectoryGuard(guard, async () => {\n\t\tconst roots = inspectStateRoots();\n\t\tif (roots.canonical || !roots.legacy) return { status: \"ready\" };\n\n\t\tconst legacyLock = path.join(legacyStateDir(), \"lock\");\n\t\tconst legacyGuardHeld = await lockfile.check(legacyLock, {\n\t\t\tfs: LOCKFILE_FS_ADAPTER,\n\t\t\tlockfilePath: `${legacyLock}.guard`,\n\t\t\trealpath: false,\n\t\t\tstale: LOCK_GUARD_STALE_MS,\n\t\t});\n\t\tif (legacyGuardHeld || (await pathExists(legacyLock))) {\n\t\t\treturn {\n\t\t\t\tstatus: \"deferred\",\n\t\t\t\tmessage:\n\t\t\t\t\t\"pi-sync state migration was deferred because the legacy directory is busy. Close other Pi sessions, clear any confirmed stale sync lock, and retry.\",\n\t\t\t};\n\t\t}\n\t\tguard.throwIfCompromised();\n\t\tawait fs.rename(legacyStateDir(), canonicalStateDir());\n\t\tguard.throwIfCompromised();\n\t\tinspectStateRoots();\n\t\treturn {\n\t\t\tstatus: \"migrated\",\n\t\t\tmessage: `Migrated pi-sync state from ${legacyStateDir()} to ${canonicalStateDir()}.`,\n\t\t};\n\t});\n}\n\nasync function acquireSharedStateDirectoryGuard(): Promise<StateDirectoryGuard> {\n\tconst key = migrationLockPath();\n\tfor (;;) {\n\t\tlet shared = sharedStateDirectoryGuards.get(key);\n\t\tif (shared?.closing) {\n\t\t\tawait shared.closing;\n\t\t\tcontinue;\n\t\t}\n\t\tif (!shared) {\n\t\t\tshared = { guard: acquireStateDirectoryGuard(), users: 0 };\n\t\t\tsharedStateDirectoryGuards.set(key, shared);\n\t\t}\n\t\tshared.users += 1;\n\t\tlet guard: StateDirectoryGuard;\n\t\ttry {\n\t\t\tguard = await shared.guard;\n\t\t} catch (error) {\n\t\t\tif (sharedStateDirectoryGuards.get(key) === shared) {\n\t\t\t\tsharedStateDirectoryGuards.delete(key);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tlet released = false;\n\t\treturn {\n\t\t\tthrowIfCompromised: guard.throwIfCompromised,\n\t\t\trelease: async () => {\n\t\t\t\tif (released) return;\n\t\t\t\treleased = true;\n\t\t\t\tshared.users -= 1;\n\t\t\t\tif (shared.users > 0) return;\n\t\t\t\tconst closing = guard.release();\n\t\t\t\tshared.closing = closing;\n\t\t\t\ttry {\n\t\t\t\t\tawait closing;\n\t\t\t\t} finally {\n\t\t\t\t\tif (sharedStateDirectoryGuards.get(key) === shared) {\n\t\t\t\t\t\tsharedStateDirectoryGuards.delete(key);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n}\n\nasync function acquireStateDirectoryGuard(): Promise<StateDirectoryGuard> {\n\tlet compromisedError: Error | undefined;\n\tconst release = await lockfile.lock(getAgentDir(), {\n\t\tfs: LOCKFILE_FS_ADAPTER,\n\t\tlockfilePath: migrationLockPath(),\n\t\trealpath: false,\n\t\tstale: MIGRATION_LOCK_STALE_MS,\n\t\tupdate: MIGRATION_LOCK_UPDATE_MS,\n\t\tretries: { retries: 20, minTimeout: 10, maxTimeout: 50 },\n\t\tonCompromised: (error) => {\n\t\t\tcompromisedError = error;\n\t\t},\n\t});\n\treturn {\n\t\trelease,\n\t\tthrowIfCompromised: () => {\n\t\t\tif (compromisedError) throw compromisedError;\n\t\t},\n\t};\n}\n\nasync function runWithStateDirectoryGuard<T>(guard: StateDirectoryGuard, fn: () => Promise<T>) {\n\tlet result: T | undefined;\n\tlet failed = false;\n\tlet failure: unknown;\n\ttry {\n\t\tguard.throwIfCompromised();\n\t\tresult = await fn();\n\t\tguard.throwIfCompromised();\n\t} catch (error) {\n\t\tfailed = true;\n\t\tfailure = error;\n\t}\n\ttry {\n\t\tawait guard.release();\n\t} catch (error) {\n\t\tif (!failed) {\n\t\t\tfailed = true;\n\t\t\tfailure = error;\n\t\t}\n\t}\n\tif (failed) throw failure;\n\treturn result as T;\n}\n\nfunction isLockHeldError(error: unknown) {\n\treturn (error as NodeJS.ErrnoException).code === \"ELOCKED\";\n}\n\nfunction canonicalStateDir() {\n\treturn path.join(getAgentDir(), CANONICAL_DIRECTORY_NAME);\n}\n\nfunction migrationLockPath() {\n\treturn path.join(getAgentDir(), MIGRATION_LOCK_NAME);\n}\n\nfunction inspectStateRoots() {\n\tconst canonical = isDirectoryRoot(canonicalStateDir(), \"canonical\");\n\tconst legacy = isDirectoryRoot(legacyStateDir(), \"legacy\");\n\tif (canonical && legacy) {\n\t\tthrow new Error(\n\t\t\t`Both legacy ${legacyStateDir()} and canonical ${canonicalStateDir()} pi-sync state directories exist. Close all Pi sessions and reconcile the directories manually; pi-sync will not merge or delete either directory.`,\n\t\t);\n\t}\n\treturn { canonical, legacy };\n}\n\nfunction isDirectoryRoot(directory: string, label: string) {\n\ttry {\n\t\tconst entry = lstatSync(directory);\n\t\tif (entry.isSymbolicLink()) {\n\t\t\tthrow new Error(\n\t\t\t\t`Refusing to use ${label} pi-sync state directory symbolic link: ${directory}`,\n\t\t\t);\n\t\t}\n\t\tif (!entry.isDirectory()) {\n\t\t\tthrow new Error(`${label} pi-sync state path is not a directory: ${directory}`);\n\t\t}\n\t\treturn true;\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n\t\tthrow error;\n\t}\n}\n\nasync function pathExists(filePath: string) {\n\ttry {\n\t\tawait fs.lstat(filePath);\n\t\treturn true;\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n\t\tthrow error;\n\t}\n}\n", "export const LOCK_GUARD_STALE_MS = 30_000;\nexport const LOCK_GUARD_UPDATE_MS = 10_000;\n", "import {\n\tmkdir,\n\tmkdirSync,\n\trealpath,\n\trealpathSync,\n\trmdir,\n\trmdirSync,\n\tstat,\n\tstatSync,\n\tutimes,\n\tutimesSync,\n} from \"node:fs\";\n\nexport const LOCKFILE_FS_ADAPTER = {\n\tmkdir,\n\tmkdirSync,\n\trealpath,\n\trealpathSync,\n\trmdir,\n\trmdirSync,\n\tstat,\n\tstatSync,\n\tutimes,\n\tutimesSync,\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -2,21 +2,24 @@
|
|
|
2
2
|
// @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
|
|
3
3
|
import {
|
|
4
4
|
updateSyncSetup
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-LCRI3ABW.ts";
|
|
6
6
|
import {
|
|
7
|
-
agentDir,
|
|
8
7
|
loadConfig,
|
|
9
8
|
localConfigPath
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-C7XY5NF5.ts";
|
|
10
|
+
import "./chunk-6LP3MCR2.ts";
|
|
11
|
+
import "./chunk-TEN2ZBJV.ts";
|
|
12
|
+
import {
|
|
13
|
+
agentDir
|
|
14
|
+
} from "./chunk-T3HH3UEJ.ts";
|
|
12
15
|
import {
|
|
13
16
|
BUILT_IN_SYNC_ROOTS,
|
|
14
17
|
isSafeCustomIncludePath,
|
|
15
18
|
normalizeSyncInclude,
|
|
16
19
|
syncIncludeSelection
|
|
17
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-JAAKLL6M.ts";
|
|
18
21
|
|
|
19
|
-
// src/file-selection.ts
|
|
22
|
+
// src/ui/file-selection.ts
|
|
20
23
|
import fs from "node:fs/promises";
|
|
21
24
|
import { defineMenu, runMenu } from "@narumitw/pi-tui-kit";
|
|
22
25
|
var BUILT_IN_PREFIX = "builtin:";
|
|
@@ -287,4 +290,4 @@ function safeTerminalText(value) {
|
|
|
287
290
|
export {
|
|
288
291
|
showFileSelection
|
|
289
292
|
};
|
|
290
|
-
//# sourceMappingURL=file-selection-
|
|
293
|
+
//# sourceMappingURL=file-selection-FTTKAOYX.ts.map
|