@narumitw/pi-sync 0.53.0 → 0.54.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 +6 -4
- package/dist/chunks/{chunk-I5IG4WV4.ts → chunk-5ZWQ33XL.ts} +39 -19
- package/dist/chunks/{chunk-I5IG4WV4.ts.map → chunk-5ZWQ33XL.ts.map} +2 -2
- package/dist/chunks/{chunk-QTCGWQP3.ts → chunk-QDPED3XJ.ts} +67 -8
- package/dist/chunks/{chunk-QTCGWQP3.ts.map → chunk-QDPED3XJ.ts.map} +3 -3
- package/dist/chunks/{chunk-FHNISD7A.ts → chunk-SDZCTCYQ.ts} +4 -4
- package/dist/chunks/{chunk-NGIJQSRE.ts → chunk-VHXBCEVF.ts} +2 -2
- package/dist/chunks/{chunk-BX3K7YW7.ts → chunk-WFKUKVCP.ts} +2 -2
- package/dist/chunks/{chunk-UETBKTDI.ts → chunk-YDVQYUHE.ts} +1 -1
- package/dist/chunks/{chunk-UETBKTDI.ts.map → chunk-YDVQYUHE.ts.map} +2 -2
- package/dist/chunks/{conflict-review-NK5CM6UA.ts → conflict-review-JANNPKKS.ts} +4 -4
- package/dist/chunks/{git-backend-HLGKUQJT.ts → git-backend-FD7AVSK6.ts} +2 -2
- package/dist/chunks/{manager-result-dispatcher-35TM3ZR3.ts → manager-result-dispatcher-6MQKFCWB.ts} +4 -4
- package/dist/chunks/{manager-ui-6AYMNXUP.ts → manager-ui-IURS4WXY.ts} +675 -610
- package/dist/chunks/manager-ui-IURS4WXY.ts.map +7 -0
- package/dist/chunks/{remote-selection-ui-BB5SX6P5.ts → remote-selection-ui-6LJJ4IMQ.ts} +3 -3
- package/dist/chunks/{s3-backend-O2AS3TH6.ts → s3-backend-AQGV6LFT.ts} +18 -4
- package/dist/chunks/s3-backend-AQGV6LFT.ts.map +7 -0
- package/dist/chunks/{sync-inspection-RLIHUYDV.ts → sync-inspection-K45QVLHB.ts} +3 -3
- package/dist/chunks/{sync-operations-RBUOUJWL.ts → sync-operations-OWTE3ZL2.ts} +18 -12
- package/dist/chunks/{sync-operations-RBUOUJWL.ts.map → sync-operations-OWTE3ZL2.ts.map} +2 -2
- package/dist/chunks/{webdav-backend-ETQGSI6I.ts → webdav-backend-TBILVEQK.ts} +2 -2
- package/dist/index.ts +33 -8
- package/dist/index.ts.map +3 -3
- package/docs/settings.md +11 -3
- package/package.json +4 -4
- package/src/backends/s3/s3-backend.ts +22 -1
- package/src/backends/s3/s3-client.ts +3 -1
- package/src/backends/sync-backend.ts +2 -0
- package/src/commands/command-execution.ts +3 -0
- package/src/commands/command-handler.ts +8 -1
- package/src/sync/merge-transfer-error.ts +72 -0
- package/src/sync/merged-sync.ts +8 -5
- package/src/sync/sync-mutations.ts +9 -7
- package/src/sync/sync-queries.ts +1 -0
- package/src/ui/cancellable-operation.ts +47 -17
- package/src/ui/manager-attention.ts +3 -5
- package/src/ui/manager-state.ts +32 -15
- package/src/ui/manager-ui.ts +59 -87
- package/src/ui/operation-dialogs.ts +29 -0
- package/src/ui/settings-ui.ts +140 -46
- package/src/ui/setup/setup-actions.ts +2 -2
- package/dist/chunks/manager-ui-6AYMNXUP.ts.map +0 -7
- package/dist/chunks/s3-backend-O2AS3TH6.ts.map +0 -7
- /package/dist/chunks/{chunk-FHNISD7A.ts.map → chunk-SDZCTCYQ.ts.map} +0 -0
- /package/dist/chunks/{chunk-NGIJQSRE.ts.map → chunk-VHXBCEVF.ts.map} +0 -0
- /package/dist/chunks/{chunk-BX3K7YW7.ts.map → chunk-WFKUKVCP.ts.map} +0 -0
- /package/dist/chunks/{conflict-review-NK5CM6UA.ts.map → conflict-review-JANNPKKS.ts.map} +0 -0
- /package/dist/chunks/{git-backend-HLGKUQJT.ts.map → git-backend-FD7AVSK6.ts.map} +0 -0
- /package/dist/chunks/{manager-result-dispatcher-35TM3ZR3.ts.map → manager-result-dispatcher-6MQKFCWB.ts.map} +0 -0
- /package/dist/chunks/{remote-selection-ui-BB5SX6P5.ts.map → remote-selection-ui-6LJJ4IMQ.ts.map} +0 -0
- /package/dist/chunks/{sync-inspection-RLIHUYDV.ts.map → sync-inspection-K45QVLHB.ts.map} +0 -0
- /package/dist/chunks/{webdav-backend-ETQGSI6I.ts.map → webdav-backend-TBILVEQK.ts.map} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
|
|
3
3
|
import {
|
|
4
4
|
inspectSync
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-WFKUKVCP.ts";
|
|
6
6
|
import {
|
|
7
7
|
applySnapshot,
|
|
8
8
|
countPreservedRemoteFiles,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
formatSnapshotOnlyDiff,
|
|
15
15
|
mergeSync,
|
|
16
16
|
publicationCapabilityDescription
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-QDPED3XJ.ts";
|
|
18
18
|
import {
|
|
19
19
|
readMergeJournal,
|
|
20
20
|
requireNoMergeJournal,
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
} from "./chunk-V6VZ5TLG.ts";
|
|
42
42
|
import {
|
|
43
43
|
createSyncBackend
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-SDZCTCYQ.ts";
|
|
45
45
|
import "./chunk-ANWNQIR7.ts";
|
|
46
46
|
import {
|
|
47
47
|
backupLocal,
|
|
@@ -79,7 +79,7 @@ import "./chunk-2JZFHNLM.ts";
|
|
|
79
79
|
import "./chunk-T2SJD3N7.ts";
|
|
80
80
|
import {
|
|
81
81
|
expectedRemoteHead
|
|
82
|
-
} from "./chunk-
|
|
82
|
+
} from "./chunk-YDVQYUHE.ts";
|
|
83
83
|
import "./chunk-ZX2Q6THB.ts";
|
|
84
84
|
import {
|
|
85
85
|
errorMessage
|
|
@@ -570,12 +570,17 @@ async function rollback(ctx, options, factory = createSyncBackend, expectedSelec
|
|
|
570
570
|
if (!await confirmFieldMigration(ctx, config, state, currentRemote, true, options.signal)) return;
|
|
571
571
|
validateMutation();
|
|
572
572
|
const physical = overlayLocalFields(remote, local, config.localFields);
|
|
573
|
-
if (!options.yes
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
573
|
+
if (!options.yes) {
|
|
574
|
+
const confirmed = await ctx.ui.confirm(
|
|
575
|
+
snapshotIncludesSessions(remote) ? "Rollback pi settings and sessions?" : "Rollback pi settings?",
|
|
576
|
+
formatRollbackSummary(config, backend.destination, local, physical, target, protectedSessionPaths(ctx).size),
|
|
577
|
+
{ signal: options.signal }
|
|
578
|
+
);
|
|
579
|
+
validateMutation();
|
|
580
|
+
if (!confirmed) {
|
|
581
|
+
ctx.ui.notify("Rollback cancelled.", "info");
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
579
584
|
}
|
|
580
585
|
validateMutation();
|
|
581
586
|
const currentLocal = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));
|
|
@@ -842,7 +847,8 @@ async function history(ctx, options, factory = createSyncBackend) {
|
|
|
842
847
|
`History for sync setup \u201C${safeTerminalText(config.setupName)}\u201D
|
|
843
848
|
|
|
844
849
|
Choose a snapshot to preview rollback.`,
|
|
845
|
-
[...labels, "Back"]
|
|
850
|
+
[...labels, "Back"],
|
|
851
|
+
{ signal: options.signal }
|
|
846
852
|
);
|
|
847
853
|
if (!selected || selected === "Back") return;
|
|
848
854
|
throwIfAborted(options.signal);
|
|
@@ -876,4 +882,4 @@ export {
|
|
|
876
882
|
status,
|
|
877
883
|
syncBoth
|
|
878
884
|
};
|
|
879
|
-
//# sourceMappingURL=sync-operations-
|
|
885
|
+
//# sourceMappingURL=sync-operations-OWTE3ZL2.ts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/sync/field-migration.ts", "../../src/sync/sync-mutations.ts", "../../src/sync/sync-queries.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport type { Snapshot } from \"../snapshot/snapshot-types.js\";\nimport type { SyncState } from \"../state/state-types.js\";\nimport { safeTerminalText } from \"../ui/terminal-text.js\";\nimport { sameLocalFields } from \"./local-fields.js\";\nimport { captureMutationOwner } from \"./sync-local.js\";\n\nexport async function confirmFieldMigration(\n ctx: ExtensionContext,\n config: AnySyncConfig,\n state: SyncState,\n remote: Snapshot | undefined,\n force: boolean,\n signal?: AbortSignal,\n) {\n if (remote?.localFields !== undefined && config.localFields === undefined)\n throw new Error(\n \"Portable snapshots require settings version 4 and explicit localFields rules on this machine; older policy must not replace local-only values.\",\n );\n const changed =\n (Boolean(state.lastAppliedSnapshot) && !sameLocalFields(state.localFields, config.localFields)) ||\n (remote !== undefined && !sameLocalFields(remote.localFields, config.localFields));\n if (!changed) return true;\n if (!force)\n throw new Error(\n \"Local-field policy changed; review an explicit push --force or pull --force migration. Old remote history is not erased.\",\n );\n const validate = captureMutationOwner(ctx, signal);\n if (!ctx.hasUI) throw new Error(\"Local-field migration requires observable TUI/RPC confirmation.\");\n validate();\n const confirmed = await ctx.ui.confirm(\n \"Migrate portable settings policy?\",\n `New machine-local fields: ${(config.localFields ?? []).map(safeTerminalText).join(\", \") || \"none\"}. Additions remove fields from future snapshots, not old history. Removals make local-only values portable again and a pull may replace them. The selected direction is authoritative; inspect /sync diff first. This confirmation is required even with --yes.`,\n { signal },\n );\n validate();\n return confirmed;\n}\n", "import type { ExtensionCommandContext, ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { createSyncBackend, type SyncBackendFactory } from \"../backends/backend-factory.js\";\nimport {\n expectedRemoteHead,\n type PublishSnapshotResult,\n type RemoteHead,\n type SyncBackend,\n} from \"../backends/sync-backend.js\";\nimport type { CommandOptions } from \"../commands/command-types.js\";\nimport { loadConfig, syncCheckConfigFingerprint } from \"../settings/config.js\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport { sessionDirForApply, snapshotOptionsForContext } from \"../snapshot/session-paths.js\";\nimport {\n createSnapshot,\n filterSnapshotForConfigPolicy,\n mergeRemotePreservedFiles,\n regenerateSnapshotIdentity,\n scanSnapshot,\n snapshotIncludesSessions,\n snapshotWithoutSessions,\n} from \"../snapshot/snapshot.js\";\nimport { applySnapshot } from \"../snapshot/snapshot-apply.js\";\nimport type { Snapshot } from \"../snapshot/snapshot-types.js\";\nimport { pruneMergeBaselines } from \"../state/merge-baseline-store.js\";\nimport type { SyncState } from \"../state/state-types.js\";\nimport { readStateForConfig, writeStateForConfig } from \"../state/sync-state-store.js\";\nimport {\n countPreservedRemoteFiles,\n formatPullSummary,\n formatPushSummary,\n formatRollbackSummary,\n} from \"../ui/sync-format.js\";\nimport { setSyncStatus } from \"../ui/sync-status.js\";\nimport { confirmFieldMigration } from \"./field-migration.js\";\nimport { overlayLocalFields, portableSnapshot, sameLocalFields, validatePortableSnapshot } from \"./local-fields.js\";\nimport { readMergeJournal, requireNoMergeJournal, retireMergeJournal } from \"./merge-journal.js\";\nimport { mergeSync } from \"./merged-sync.js\";\nimport { readRemoteSnapshot, readSnapshotForHead, requireCompatibleRemoteSelection } from \"./remote-snapshot.js\";\nimport { throwIfAborted } from \"./signals.js\";\nimport { createSyncDecision } from \"./sync-decision.js\";\nimport { errorMessage } from \"./sync-errors.js\";\n\nimport { backupLocal, captureMutationOwner, protectedSessionPaths } from \"./sync-local.js\";\nimport { inspectRemoteSelection } from \"./sync-policy.js\";\nimport {\n canPullRemoteSessionsOnFirstSync,\n canPullRemoteSettingsOnFirstSync,\n fileHashMap,\n hasLocalChanges,\n hasRemoteChanges,\n remoteChangedSinceState,\n sameHashes,\n shouldRefreshSyncedState,\n snapshotHashesMatchState,\n snapshotsMatch,\n syncPolicyChanged,\n} from \"./sync-state.js\";\n\nconst VERSION = 1;\nconst POST_LOCAL_COMMIT_TIMEOUT_MS = 30_000;\n\n/** Whole-direction acceptance must never forget withheld state without an explicit recovery choice. */\nfunction requireResolvedDirectionalProgress(state: SyncState, options: CommandOptions, allowForce = true) {\n if (state.unresolved?.length && (options.auto || !options.force || !allowForce))\n throw new Error(\n \"Unresolved partial conflicts remain. Review /sync conflicts or explicitly choose push --force or pull --force; automatic transfer and rollback cannot accept unresolved groups.\",\n );\n}\n\nexport class PublicationStatePersistenceError extends Error {\n readonly head: RemoteHead;\n readonly backupPath?: string;\n\n constructor(head: RemoteHead, cause: unknown, backupPath?: string) {\n super(\n `Remote publication ${head.snapshotId} is active, but local sync state could not be saved${backupPath ? `; local backup: ${backupPath}` : \"\"}: ${errorMessage(cause)}`,\n { cause },\n );\n this.name = \"PublicationStatePersistenceError\";\n this.head = head;\n this.backupPath = backupPath;\n }\n}\n\nexport class RollbackPublicationError extends Error {\n readonly backupPath: string;\n\n constructor(backupPath: string, cause: unknown) {\n super(`Rollback applied locally with backup ${backupPath}, but remote publication failed: ${errorMessage(cause)}`, {\n cause,\n });\n this.name = \"RollbackPublicationError\";\n this.backupPath = backupPath;\n }\n}\n\ninterface PushInput {\n config: AnySyncConfig;\n state: SyncState;\n local: Snapshot;\n backend?: SyncBackend;\n}\n\nexport async function push(\n ctx: ExtensionCommandContext | ExtensionContext,\n options: CommandOptions,\n input?: PushInput,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const validateMutation = captureMutationOwner(ctx, options.signal);\n const validateCommittedOwner = captureMutationOwner(ctx);\n const config = input?.config ?? (await loadConfig(options.setup));\n throwIfAborted(options.signal);\n await requireNoMergeJournal(config, options);\n const state = input?.state ?? (await readStateForConfig(config));\n validateMutation();\n requireResolvedDirectionalProgress(state, options);\n setSyncStatus(ctx, `pushing ${config.setupName}`);\n const backend = input?.backend ?? (await factory(config));\n throwIfAborted(options.signal);\n const localRaw =\n input?.local ?? (await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config)));\n const local = portableSnapshot(localRaw, config.localFields);\n throwIfAborted(options.signal);\n\n let head = await backend.readHead(options.signal);\n let remoteForUpload = await readRemoteSnapshotForUpload(backend, config, head, state, options.signal);\n if (\n !options.force &&\n !remoteForUpload &&\n head?.selection &&\n inspectRemoteSelection(config.include, { selection: head.selection, files: [] }).kind === \"different\"\n ) {\n remoteForUpload = await readSnapshotForHead(backend, head, options.signal);\n }\n if (remoteForUpload && !options.force) {\n requireCompatibleRemoteSelection(config, remoteForUpload);\n }\n if (\n remoteChangedSinceState(head, state, config, (left, right) => backend.sameRevision(left, right)) &&\n !options.force\n ) {\n const remoteForConflict = remoteForUpload ? filterSnapshotForConfigPolicy(remoteForUpload, config) : undefined;\n if (!remoteForConflict || !snapshotHashesMatchState(remoteForConflict, state, config)) {\n throw createSyncDecision({\n kind: head ? \"remote-or-policy-changed\" : \"remote-empty\",\n config,\n state,\n local,\n remote: remoteForConflict,\n localChanged: hasLocalChanges(local, state, config),\n remoteChanged: true,\n directMessage: \"Remote or sync policy changed since last sync. Run /sync pull first or /sync push --force.\",\n });\n }\n }\n\n if (!remoteForUpload && head && config.localFields !== undefined)\n remoteForUpload = await readSnapshotForHead(backend, head, options.signal);\n if (!(await confirmFieldMigration(ctx, config, state, remoteForUpload, options.force, options.signal))) {\n setSyncStatus(ctx, undefined);\n return \"cancelled\" as const;\n }\n const configIdentity = syncCheckConfigFingerprint(config);\n let upload = await snapshotForUpload(backend, config, local, head, remoteForUpload, options.signal);\n if (!config.skipSecretScan) {\n const secrets = scanSnapshot(local);\n if (secrets.length > 0) {\n throw new Error(`Refusing to push possible secrets:\\n${secrets.map((s) => `- ${s}`).join(\"\\n\")}`);\n }\n }\n\n if (!(await confirmPush(ctx, options, config, backend, local, upload, head, remoteForUpload))) {\n return \"cancelled\" as const;\n }\n\n if (options.force) {\n const refreshedHead = await backend.readHead(options.signal);\n if (!sameRemoteHead(backend, head, refreshedHead)) {\n head = refreshedHead;\n remoteForUpload = head ? await readSnapshotForHead(backend, head, options.signal) : undefined;\n validateMutation();\n if (!(await confirmFieldMigration(ctx, config, state, remoteForUpload, options.force, options.signal))) {\n setSyncStatus(ctx, undefined);\n return \"cancelled\" as const;\n }\n validateMutation();\n upload = await snapshotForUpload(backend, config, local, head, remoteForUpload, options.signal);\n if (\n !(await confirmPush(\n ctx,\n options,\n config,\n backend,\n local,\n upload,\n head,\n remoteForUpload,\n \"Remote changed during review. Push the refreshed plan?\",\n ))\n ) {\n return \"cancelled\" as const;\n }\n }\n }\n\n validateMutation();\n if (configIdentity !== syncCheckConfigFingerprint(await loadConfig(options.setup)))\n throw new Error(\"Settings changed during push review.\");\n validateMutation();\n if (config.localFields !== undefined || (await readMergeJournal(config))) {\n const current = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n if (!sameHashes(fileHashMap(current), fileHashMap(localRaw)))\n throw new Error(\"Local content changed during recovery review; retry from current bytes.\");\n }\n requireResolvedDirectionalProgress(await readStateForConfig(config), options);\n validateMutation();\n const result = await backend.publishSnapshot(upload, expectedRemoteHead(head), {\n signal: options.signal,\n onCommit: options.onCommit,\n });\n try {\n await writeStateForConfig(\n config,\n {\n version: VERSION,\n profile: config.snapshotIdentity,\n lastAppliedSnapshot: result.head.snapshotId,\n lastRemoteRevision: result.head.revision,\n lastFileHashes: fileHashMap(local),\n include: [...config.include],\n ...(config.localFields !== undefined ? { localFields: config.localFields } : {}),\n },\n local,\n validateCommittedOwner,\n );\n } catch (error) {\n throw new PublicationStatePersistenceError(result.head, error);\n }\n await retireMergeJournal(config);\n await pruneMergeBaselines(config, await readStateForConfig(config), validateCommittedOwner);\n validateCommittedOwner();\n if (options.signal?.aborted) return;\n setSyncStatus(ctx, undefined);\n if (!options.silent) {\n ctx.ui.notify(\n [\n `Pushed ${upload.files.length} files from sync setup \u201C${config.setupName}\u201D as ${result.head.snapshotId}.`,\n ...result.warnings,\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n result.warnings.length > 0 ? \"warning\" : \"info\",\n );\n }\n return \"applied\" as const;\n}\n\nexport async function pull(\n ctx: ExtensionCommandContext | ExtensionContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const validateMutation = captureMutationOwner(ctx, options.signal);\n const validateCommittedOwner = captureMutationOwner(ctx);\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n await requireNoMergeJournal(config, options);\n setSyncStatus(ctx, `pulling ${config.setupName}`);\n const backend = await factory(config);\n const state = await readStateForConfig(config);\n validateMutation();\n requireResolvedDirectionalProgress(state, options);\n const local = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n throwIfAborted(options.signal);\n const { head, snapshot: remote } = await readRemoteSnapshot(backend, config, options.signal);\n throwIfAborted(options.signal);\n const localChanged = hasLocalChanges(local, state, config);\n if (!remote) {\n throw createSyncDecision({\n kind: \"remote-empty\",\n config,\n state,\n local,\n localChanged,\n remoteChanged: false,\n directMessage: \"Remote is empty. Run /sync push from a configured machine first.\",\n });\n }\n\n if (!sameLocalFields(config.localFields, remote.localFields)) {\n setSyncStatus(ctx, undefined);\n throw new Error(\n \"Pull requires the configured local-field policy to match the remote. To change the remote policy, review push --force from the authoritative machine first, then pull using matching rules; old history is not erased.\",\n );\n }\n if (!(await confirmFieldMigration(ctx, config, state, remote, options.force, options.signal))) {\n setSyncStatus(ctx, undefined);\n return \"cancelled\" as const;\n }\n const configIdentity = syncCheckConfigFingerprint(config);\n const logical = portableSnapshot(remote, config.localFields);\n const physical = overlayLocalFields(logical, local, config.localFields);\n const remoteChanged = hasRemoteChanges(remote, state, config, protectedSessionPaths(ctx));\n if (localChanged && remoteChanged && state.lastAppliedSnapshot && !options.force) {\n throw createSyncDecision({\n kind: \"both-changed\",\n config,\n state,\n local,\n remote,\n localChanged,\n remoteChanged,\n directMessage:\n \"Both local and remote changed since last sync. Run /sync diff, then choose /sync pull --force or /sync push --force.\",\n });\n }\n\n if (\n !options.yes &&\n !(await ctx.ui.confirm(\n snapshotIncludesSessions(remote) ? \"Pull pi settings and sessions?\" : \"Pull pi settings?\",\n formatPullSummary(config, backend.destination, local, physical, protectedSessionPaths(ctx).size),\n ))\n ) {\n setSyncStatus(ctx, undefined);\n ctx.ui.notify(\"Pull cancelled.\", \"info\");\n return \"cancelled\" as const;\n }\n\n throwIfAborted(options.signal);\n const recoveringMerge = Boolean(await readMergeJournal(config));\n const requireFreshRecovery = async () => {\n validateMutation();\n const currentHead = await backend.readHead(options.signal);\n validateMutation();\n const current = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n validateMutation();\n if (!sameHashes(fileHashMap(current), fileHashMap(local)) || !sameRemoteHead(backend, head, currentHead)) {\n throw new Error(\"Local or remote content changed during recovery review; retry from a fresh diff.\");\n }\n };\n if (recoveringMerge) await requireFreshRecovery();\n if (configIdentity !== syncCheckConfigFingerprint(await loadConfig(options.setup)))\n throw new Error(\"Settings changed during pull review.\");\n validateMutation();\n const refreshed = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n if (!sameHashes(fileHashMap(local), fileHashMap(refreshed)))\n throw new Error(\"Local bytes changed during pull review.\");\n if (!sameRemoteHead(backend, head, await backend.readHead(options.signal)))\n throw new Error(\"Remote changed during pull review.\");\n validateMutation();\n const backup = await backupLocal(config.snapshotIdentity, snapshotOptionsForContext(ctx, config), options.signal);\n const applySessionDir = await sessionDirForApply(ctx, physical);\n if (recoveringMerge) await requireFreshRecovery();\n requireResolvedDirectionalProgress(await readStateForConfig(config), options);\n validateMutation();\n options.onCommit?.();\n const lastFileHashes = await applySnapshot(physical, protectedSessionPaths(ctx), {\n include: config.include,\n sessionDir: applySessionDir,\n signal: options.signal,\n validateMutation,\n expectedFileHashes: config.localFields?.length\n ? { \"settings.json\": fileHashMap(local)[\"settings.json\"] ?? null }\n : undefined,\n });\n // Local installation is complete; user cancellation must not leave the baseline stale.\n validateCommittedOwner();\n await writeStateForConfig(\n config,\n {\n version: VERSION,\n profile: config.snapshotIdentity,\n lastAppliedSnapshot: remote.id,\n lastRemoteRevision: head?.revision,\n lastFileHashes: config.localFields?.length\n ? { ...lastFileHashes, \"settings.json\": fileHashMap(logical)[\"settings.json\"] }\n : lastFileHashes,\n include: [...config.include],\n ...(config.localFields !== undefined ? { localFields: config.localFields } : {}),\n },\n logical,\n validateCommittedOwner,\n );\n await retireMergeJournal(config);\n await pruneMergeBaselines(config, await readStateForConfig(config), validateCommittedOwner);\n validateCommittedOwner();\n if (options.signal?.aborted) return \"applied\" as const;\n setSyncStatus(ctx, undefined);\n if (!options.silent) {\n ctx.ui.notify(`Pulled ${remote.files.length} files from ${remote.id}. Backup: ${backup}`, \"info\");\n } else if (options.auto && config.include.includes(\"sessions\") && snapshotIncludesSessions(remote)) {\n ctx.ui.notify(\n \"Pulled Pi sessions after startup selected the current session. Restart Pi or resume a pulled session to use newly synced conversations.\",\n \"warning\",\n );\n }\n if (options.reload) await maybeReload(ctx, options.signal, validateMutation);\n return \"applied\" as const;\n}\n\nexport async function syncBoth(\n ctx: ExtensionCommandContext | ExtensionContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const validateMutation = captureMutationOwner(ctx, options.signal);\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n if (config.include.length > 0 && options.auto && config.automaticTransfer) return mergeSync(ctx, options, factory);\n if (!options.auto && config.include.length > 0 && (await readMergeJournal(config)))\n return mergeSync(ctx, options, factory);\n const state = await readStateForConfig(config);\n throwIfAborted(options.signal);\n if (!options.auto && config.include.length > 0 && state.lastAppliedSnapshot) return mergeSync(ctx, options, factory);\n const backend = await factory(config);\n const local = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n throwIfAborted(options.signal);\n if (config.include.length === 0) {\n if (!options.silent) {\n ctx.ui.notify(\n `Sync setup \u201C${config.setupName}\u201D includes no files. Choose included content in /sync Settings before syncing.`,\n \"warning\",\n );\n }\n return;\n }\n const { head, snapshot: remote } = await readRemoteSnapshot(backend, config, options.signal);\n throwIfAborted(options.signal);\n const localChanged = hasLocalChanges(local, state, config);\n const remoteChanged = remote ? hasRemoteChanges(remote, state, config, protectedSessionPaths(ctx)) : false;\n const firstSync = !state.lastAppliedSnapshot;\n if (options.auto) throw new Error(\"Automatic transfer is not authorized by the current settings.\");\n\n const portableLocal = portableSnapshot(local, config.localFields);\n const acceptMatchingState = async (snapshot: Snapshot) => {\n requireCompatibleRemoteSelection(config, snapshot);\n const accepted = portableSnapshot(snapshot, config.localFields);\n if (state.lastAppliedSnapshot && !sameLocalFields(state.localFields, config.localFields))\n throw new Error(\"Local-field rules changed; review and confirm a directional migration first.\");\n await writeStateForConfig(\n config,\n {\n version: VERSION,\n profile: config.snapshotIdentity,\n lastAppliedSnapshot: snapshot.id,\n lastRemoteRevision: head?.revision,\n lastFileHashes: fileHashMap(accepted),\n include: [...config.include],\n ...(config.localFields !== undefined ? { localFields: config.localFields } : {}),\n },\n accepted,\n validateMutation,\n );\n await pruneMergeBaselines(config, await readStateForConfig(config), validateMutation);\n validateMutation();\n };\n if (firstSync && remote && remote.files.length > 0 && local.files.length > 0) {\n requireCompatibleRemoteSelection(config, remote);\n const portableRemote = portableSnapshot(remote, config.localFields);\n if (!canPullRemoteSettingsOnFirstSync(portableLocal, portableRemote)) {\n throw createSyncDecision({\n kind: \"first-sync-settings-diverged\",\n config,\n state,\n local,\n remote,\n localChanged: true,\n remoteChanged: true,\n directMessage:\n \"Remote settings exist and this machine has different local Pi settings. Run /sync diff, then manually choose /sync pull or /sync push.\",\n });\n }\n if (!sameHashes(fileHashMap(portableLocal), fileHashMap(portableRemote))) {\n if (!canPullRemoteSessionsOnFirstSync(portableLocal, portableRemote)) {\n throw createSyncDecision({\n kind: \"first-sync-sessions-diverged\",\n config,\n state,\n local,\n remote,\n localChanged: true,\n remoteChanged: true,\n directMessage:\n \"Remote settings match, but local and remote Pi sessions differ. Run /sync diff, then manually choose /sync pull or /sync push.\",\n });\n }\n await pull(ctx, options, factory);\n return;\n }\n await acceptMatchingState(remote);\n if (!options.silent) ctx.ui.notify(\"pi-sync state initialized; local settings already match remote.\", \"info\");\n return;\n }\n if (\n localChanged &&\n remoteChanged &&\n remote &&\n snapshotsMatch(portableLocal, portableSnapshot(remote, remote.localFields))\n ) {\n requireCompatibleRemoteSelection(config, remote);\n await acceptMatchingState(remote);\n if (!options.silent) ctx.ui.notify(\"pi-sync is already up to date.\", \"info\");\n return;\n }\n if (localChanged && remoteChanged && state.lastAppliedSnapshot) {\n throw createSyncDecision({\n kind: \"both-changed\",\n config,\n state,\n local,\n remote,\n localChanged,\n remoteChanged,\n directMessage: \"Both local and remote changed. Run /sync diff and resolve with push --force or pull --force.\",\n });\n }\n if (remoteChanged) {\n await pull(ctx, options, factory);\n return;\n }\n if (localChanged || !remote) {\n await push(ctx, options, undefined, factory);\n return;\n }\n if (shouldRefreshSyncedState(remote, head, state, config, (left, right) => backend.sameRevision(left, right))) {\n await acceptMatchingState(remote);\n }\n if (!options.silent) ctx.ui.notify(\"pi-sync is already up to date.\", \"info\");\n}\n\nexport async function rollback(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n expectedSelection?: { backendIdentity: string; setup?: string },\n) {\n const validateMutation = captureMutationOwner(ctx, options.signal);\n const validateCommittedOwner = captureMutationOwner(ctx);\n const target = options.args[0];\n if (!target) throw new Error(\"Usage: /sync rollback <snapshot-id> [--yes]\");\n\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n const backend = await factory(config);\n if (\n expectedSelection &&\n (backend.identity !== expectedSelection.backendIdentity || config.setupName !== expectedSelection.setup)\n ) {\n throw new Error(\"Sync setup or storage location changed while history was open; reopen history and retry.\");\n }\n // --force is only a rollback compatibility flag, not a reviewed merge-recovery direction.\n await requireNoMergeJournal(config);\n const state = await readStateForConfig(config);\n validateMutation();\n requireResolvedDirectionalProgress(state, options, false);\n const decoded = await backend.readSnapshot(target, options.signal);\n validatePortableSnapshot(decoded);\n if (!sameLocalFields(decoded.localFields, config.localFields))\n throw new Error(\n \"Rollback requires the historical snapshot local-field policy to match the configured rules. Review push --force from current local bytes to migrate policy first; choose matching history afterward.\",\n );\n const selected = filterSnapshotForConfigPolicy(\n config.include.includes(\"sessions\") ? decoded : snapshotWithoutSessions(decoded),\n config,\n );\n const remote = portableSnapshot(regenerateSnapshotIdentity(selected), config.localFields);\n const local = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n const expectedHead = await backend.readHead(options.signal);\n const currentRemote = expectedHead ? await readSnapshotForHead(backend, expectedHead, options.signal) : undefined;\n validateMutation();\n if (!(await confirmFieldMigration(ctx, config, state, currentRemote, true, options.signal))) return;\n validateMutation();\n const physical = overlayLocalFields(remote, local, config.localFields);\n\n if (\n !options.yes &&\n !(await ctx.ui.confirm(\n snapshotIncludesSessions(remote) ? \"Rollback pi settings and sessions?\" : \"Rollback pi settings?\",\n formatRollbackSummary(config, backend.destination, local, physical, target, protectedSessionPaths(ctx).size),\n ))\n ) {\n ctx.ui.notify(\"Rollback cancelled.\", \"info\");\n return;\n }\n\n validateMutation();\n const currentLocal = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n if (!sameHashes(fileHashMap(currentLocal), fileHashMap(local)))\n throw new Error(\"Local bytes changed during rollback review.\");\n if (syncCheckConfigFingerprint(config) !== syncCheckConfigFingerprint(await loadConfig(options.setup)))\n throw new Error(\"Settings changed during rollback review.\");\n if (!sameRemoteHead(backend, expectedHead, await backend.readHead(options.signal)))\n throw new Error(\"Remote changed during rollback review.\");\n validateMutation();\n throwIfAborted(options.signal);\n const backup = await backupLocal(config.snapshotIdentity, snapshotOptionsForContext(ctx, config), options.signal);\n const applySessionDir = await sessionDirForApply(ctx, remote);\n requireResolvedDirectionalProgress(await readStateForConfig(config), options, false);\n validateMutation();\n options.onCommit?.();\n const lastFileHashes = await applySnapshot(physical, protectedSessionPaths(ctx), {\n include: config.include,\n sessionDir: applySessionDir,\n signal: options.signal,\n validateMutation,\n expectedFileHashes: config.localFields?.length\n ? { \"settings.json\": fileHashMap(local)[\"settings.json\"] ?? null }\n : undefined,\n });\n // The local transaction is retired; finish publication despite caller cancellation.\n validateCommittedOwner();\n let result: PublishSnapshotResult;\n try {\n const completionSignal = AbortSignal.timeout(POST_LOCAL_COMMIT_TIMEOUT_MS);\n const upload = await snapshotForUpload(backend, config, remote, expectedHead, currentRemote, completionSignal);\n validateCommittedOwner();\n result = await backend.publishSnapshot(upload, expectedRemoteHead(expectedHead), {\n signal: completionSignal,\n });\n } catch (error) {\n throw new RollbackPublicationError(backup, error);\n }\n try {\n await writeStateForConfig(\n config,\n {\n version: VERSION,\n profile: config.snapshotIdentity,\n lastAppliedSnapshot: result.head.snapshotId,\n lastRemoteRevision: result.head.revision,\n lastFileHashes: config.localFields?.length\n ? { ...lastFileHashes, \"settings.json\": fileHashMap(remote)[\"settings.json\"] }\n : lastFileHashes,\n include: [...config.include],\n ...(config.localFields !== undefined ? { localFields: config.localFields } : {}),\n },\n remote,\n validateCommittedOwner,\n );\n } catch (error) {\n throw new PublicationStatePersistenceError(result.head, error, backup);\n }\n await retireMergeJournal(config);\n await pruneMergeBaselines(config, await readStateForConfig(config), validateCommittedOwner);\n validateCommittedOwner();\n if (options.signal?.aborted) return;\n ctx.ui.notify(\n [\n `Rolled back sync setup \u201C${config.setupName}\u201D to ${target}; latest: ${result.head.snapshotId}. Backup: ${backup}`,\n ...result.warnings,\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n result.warnings.length > 0 ? \"warning\" : \"info\",\n );\n await maybeReload(ctx, options.signal, validateMutation);\n}\n\nasync function maybeReload(\n ctx: ExtensionCommandContext | ExtensionContext,\n signal?: AbortSignal,\n validateMutation = captureMutationOwner(ctx, signal),\n) {\n if (signal?.aborted || !(\"reload\" in ctx)) return;\n validateMutation();\n if (\n ctx.hasUI &&\n (await ctx.ui.confirm(\n \"Reload Pi resources now?\",\n \"This reloads extensions, skills, prompts, themes, and context files.\",\n ))\n ) {\n if (signal?.aborted) return;\n validateMutation();\n await ctx.reload();\n }\n}\n\nasync function readRemoteSnapshotForUpload(\n backend: SyncBackend,\n config: AnySyncConfig,\n head: RemoteHead | undefined,\n state: SyncState,\n signal?: AbortSignal,\n) {\n if (\n !head ||\n (head.snapshotId === state.lastAppliedSnapshot &&\n !syncPolicyChanged(state, config) &&\n (!state.lastRemoteRevision || backend.sameRevision(head.revision, state.lastRemoteRevision)))\n ) {\n return undefined;\n }\n return readSnapshotForHead(backend, head, signal);\n}\n\nasync function snapshotForUpload(\n backend: SyncBackend,\n config: AnySyncConfig,\n local: Snapshot,\n head: RemoteHead | undefined,\n remote?: Snapshot,\n signal?: AbortSignal,\n) {\n if (!head) return local;\n const snapshot = remote ?? (await readSnapshotForHead(backend, head, signal));\n return mergeRemotePreservedFiles(local, snapshot, config);\n}\n\nasync function confirmPush(\n ctx: ExtensionCommandContext | ExtensionContext,\n options: CommandOptions,\n config: AnySyncConfig,\n backend: SyncBackend,\n local: Snapshot,\n upload: Snapshot,\n head: RemoteHead | undefined,\n remote: Snapshot | undefined,\n title = snapshotIncludesSessions(upload) ? \"Push pi settings and sessions?\" : \"Push pi settings?\",\n) {\n throwIfAborted(options.signal);\n if (options.yes) return true;\n const confirmed = await ctx.ui.confirm(\n title,\n formatPushSummary(config, backend.destination, upload, head, countPreservedRemoteFiles(local, upload), remote),\n );\n throwIfAborted(options.signal);\n if (confirmed) return true;\n setSyncStatus(ctx, undefined);\n ctx.ui.notify(\"Push cancelled.\", \"info\");\n return false;\n}\n\nfunction sameRemoteHead(backend: SyncBackend, left: RemoteHead | undefined, right: RemoteHead | undefined) {\n if (!left || !right) return left === right;\n return backend.sameRevision(left.revision, right.revision);\n}\n\nexport { backupLocal } from \"./sync-local.js\";\n", "import type { ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport { createSyncBackend, type SyncBackendFactory } from \"../backends/backend-factory.js\";\nimport type { SyncBackend } from \"../backends/sync-backend.js\";\nimport type { CommandOptions } from \"../commands/command-types.js\";\nimport { loadConfig, syncSessionsWarnings } from \"../settings/config.js\";\nimport { snapshotOptionsForContext } from \"../snapshot/session-paths.js\";\nimport { createSnapshot, scanSnapshot } from \"../snapshot/snapshot.js\";\nimport type { SnapshotOptions } from \"../snapshot/snapshot-types.js\";\nimport { inspectLock, isLockGuardHeld, isStaleLock, withLock } from \"../state/lock.js\";\nimport { formatDiff, formatSnapshotOnlyDiff, publicationCapabilityDescription } from \"../ui/sync-format.js\";\nimport { setSyncStatus } from \"../ui/sync-status.js\";\nimport { safeTerminalText } from \"../ui/terminal-text.js\";\nimport { portableSnapshot } from \"./local-fields.js\";\nimport { formatRemoteSelectionStatus, readRemoteSnapshot } from \"./remote-snapshot.js\";\nimport { throwIfAborted } from \"./signals.js\";\nimport { errorMessage } from \"./sync-errors.js\";\nimport { inspectSync } from \"./sync-inspection.js\";\nimport { rollback } from \"./sync-mutations.js\";\n\nconst DEFAULT_PROFILE = \"default\";\n\nexport async function status(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n setSyncStatus(ctx, `checking ${config.setupName}`);\n const { head, selectionState, localChanged, remoteChanged, localFiles, destination, capability } = await inspectSync(\n config,\n snapshotOptionsForContext(ctx, config),\n options.signal,\n factory,\n );\n throwIfAborted(options.signal);\n\n const remoteText = head ? `remote: ${head.snapshotId} from ${head.machine} at ${head.createdAt}` : \"remote: empty\";\n const warnings = syncSessionsWarnings(config);\n setSyncStatus(ctx, undefined);\n ctx.ui.notify(\n [\n `sync setup: ${config.setupName}`,\n `storage connection: ${config.connectionName}`,\n `storage location: ${safeTerminalText(destination)}`,\n `publication safety: ${publicationCapabilityDescription(capability)}`,\n `included content: ${config.include.join(\", \") || \"none\"}`,\n `sessions: ${config.include.includes(\"sessions\") ? \"included\" : \"excluded\"}`,\n remoteText,\n formatRemoteSelectionStatus(selectionState),\n `local files: ${localFiles}`,\n `local changed since last sync: ${localChanged ? \"yes\" : \"no\"}`,\n `remote changed since last sync: ${remoteChanged ? \"yes\" : \"no\"}`,\n ...warnings,\n ].join(\"\\n\"),\n localChanged || remoteChanged || selectionState?.kind === \"different\" || warnings.length > 0 ? \"warning\" : \"info\",\n );\n}\n\nexport async function diff(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n setSyncStatus(ctx, `checking ${config.setupName}`);\n const backend = await factory(config);\n const local = portableSnapshot(\n await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config)),\n config.localFields,\n );\n throwIfAborted(options.signal);\n const { snapshot: remote, selectionState } = await readRemoteSnapshot(backend, config, options.signal, {\n allowSelectionDifference: true,\n });\n throwIfAborted(options.signal);\n setSyncStatus(ctx, undefined);\n\n const warnings = syncSessionsWarnings(config);\n const header = [\n `sync setup: ${config.setupName}`,\n `storage connection: ${config.connectionName}`,\n `storage location: ${safeTerminalText(backend.destination)}`,\n `included content: ${config.include.join(\", \") || \"none\"}`,\n `sessions: ${config.include.includes(\"sessions\") ? \"included\" : \"excluded\"}`,\n formatRemoteSelectionStatus(selectionState),\n ...warnings,\n ].join(\"\\n\");\n const level = warnings.length > 0 || selectionState?.kind === \"different\" ? \"warning\" : \"info\";\n if (!remote) {\n ctx.ui.notify(`${header}\\n\\n${formatSnapshotOnlyDiff(\"Remote is empty. Local push would upload\", local)}`, level);\n return;\n }\n\n ctx.ui.notify(`${header}\\n\\n${formatDiff(local, portableSnapshot(remote, remote.localFields))}`, level);\n}\n\nexport async function doctor(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const messages: string[] = [];\n let level: \"info\" | \"warning\" = \"info\";\n let snapshotOptions: SnapshotOptions = {};\n let profile = DEFAULT_PROFILE;\n let backend: SyncBackend | undefined;\n let backendSummary: string[] = [];\n\n try {\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n backend = await factory(config);\n profile = config.snapshotIdentity;\n snapshotOptions = snapshotOptionsForContext(ctx, config);\n messages.push(\n `config: ok (sync setup ${config.setupName})`,\n `included content: ${config.include.join(\", \") || \"none\"}`,\n `sessions: ${config.include.includes(\"sessions\") ? \"included\" : \"excluded\"}`,\n );\n backendSummary = [\n `storage location: ${safeTerminalText(backend.destination)}`,\n `publication safety: ${publicationCapabilityDescription(backend.capability)}`,\n ];\n const warnings = syncSessionsWarnings(config);\n if (warnings.length > 0) {\n level = \"warning\";\n messages.push(...warnings);\n }\n } catch (error) {\n throwIfAborted(options.signal);\n level = \"warning\";\n messages.push(`config: ${errorMessage(error)}`);\n }\n\n const local = await createSnapshot(profile, snapshotOptions);\n throwIfAborted(options.signal);\n const secrets = scanSnapshot(local);\n if (secrets.length > 0) {\n level = \"warning\";\n messages.push(\"secret scan: possible secrets found:\");\n messages.push(...secrets.map((secret) => `- ${secret}`));\n } else {\n messages.push(`secret scan: ok (${local.files.length} files checked)`);\n }\n\n const lock = await inspectLock();\n throwIfAborted(options.signal);\n if (lock.status === \"valid\" && isStaleLock(lock.lock)) {\n level = \"warning\";\n messages.push(`lock: stale (pid ${lock.lock.pid}); run /sync unlock --stale after verifying no sync is running`);\n } else if (lock.status === \"valid\") {\n messages.push(`lock: held by pid ${lock.lock.pid} since ${lock.lock.startedAt}`);\n } else if (lock.status === \"unreadable\") {\n level = \"warning\";\n messages.push(\"lock: unreadable; use /sync unlock --stale only after verifying no sync is running\");\n } else if (await isLockGuardHeld()) {\n throwIfAborted(options.signal);\n level = \"warning\";\n messages.push(\"lock: guard active while metadata is missing or still being initialized\");\n } else {\n messages.push(\"lock: free\");\n }\n\n if (backend) {\n messages.push(...backendSummary);\n const diagnostics = await backend.diagnose(options.signal);\n throwIfAborted(options.signal);\n for (const diagnostic of diagnostics) {\n messages.push(diagnostic.message);\n if (diagnostic.level !== \"info\") level = \"warning\";\n }\n }\n ctx.ui.notify(messages.join(\"\\n\"), level);\n}\n\nexport async function history(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n const backend = await factory(config);\n const snapshots = (await backend.listHistory(options.signal)).slice(-20).reverse();\n throwIfAborted(options.signal);\n if (snapshots.length === 0) {\n ctx.ui.notify(\"No remote pi-sync history found.\", \"info\");\n return;\n }\n\n const currentSnapshot = snapshots[0]?.snapshotId;\n if (ctx.mode === \"tui\") {\n const labels = snapshots.map(\n (item, index) =>\n `${index + 1}. ${item.createdAt} \u00B7 ${safeTerminalText(item.machine)} \u00B7 ${item.snapshotId}${item.snapshotId === currentSnapshot ? \" (current)\" : \"\"}${item.syncSessions ? \" \u00B7 sessions\" : \"\"}`,\n );\n const selected = await ctx.ui.select(\n `History for sync setup \u201C${safeTerminalText(config.setupName)}\u201D\\n\\nChoose a snapshot to preview rollback.`,\n [...labels, \"Back\"],\n );\n if (!selected || selected === \"Back\") return;\n throwIfAborted(options.signal);\n const index = labels.indexOf(selected);\n const snapshot = snapshots[index];\n if (!snapshot) return;\n await withLock(\"rollback\", () =>\n rollback(ctx, { ...options, args: [snapshot.snapshotRef], yes: false }, factory, {\n backendIdentity: backend.identity,\n setup: config.setupName,\n }),\n );\n return;\n }\n ctx.ui.notify(\n snapshots.map((item) => `${item.snapshotRef} ${item.createdAt} ${safeTerminalText(item.machine)}`).join(\"\\n\"),\n \"info\",\n );\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport type { Snapshot } from \"../snapshot/snapshot-types.js\";\nimport type { SyncState } from \"../state/state-types.js\";\nimport { safeTerminalText } from \"../ui/terminal-text.js\";\nimport { sameLocalFields } from \"./local-fields.js\";\nimport { captureMutationOwner } from \"./sync-local.js\";\n\nexport async function confirmFieldMigration(\n ctx: ExtensionContext,\n config: AnySyncConfig,\n state: SyncState,\n remote: Snapshot | undefined,\n force: boolean,\n signal?: AbortSignal,\n) {\n if (remote?.localFields !== undefined && config.localFields === undefined)\n throw new Error(\n \"Portable snapshots require settings version 4 and explicit localFields rules on this machine; older policy must not replace local-only values.\",\n );\n const changed =\n (Boolean(state.lastAppliedSnapshot) && !sameLocalFields(state.localFields, config.localFields)) ||\n (remote !== undefined && !sameLocalFields(remote.localFields, config.localFields));\n if (!changed) return true;\n if (!force)\n throw new Error(\n \"Local-field policy changed; review an explicit push --force or pull --force migration. Old remote history is not erased.\",\n );\n const validate = captureMutationOwner(ctx, signal);\n if (!ctx.hasUI) throw new Error(\"Local-field migration requires observable TUI/RPC confirmation.\");\n validate();\n const confirmed = await ctx.ui.confirm(\n \"Migrate portable settings policy?\",\n `New machine-local fields: ${(config.localFields ?? []).map(safeTerminalText).join(\", \") || \"none\"}. Additions remove fields from future snapshots, not old history. Removals make local-only values portable again and a pull may replace them. The selected direction is authoritative; inspect /sync diff first. This confirmation is required even with --yes.`,\n { signal },\n );\n validate();\n return confirmed;\n}\n", "import type { ExtensionCommandContext, ExtensionContext } from \"@earendil-works/pi-coding-agent\";\nimport { createSyncBackend, type SyncBackendFactory } from \"../backends/backend-factory.js\";\nimport {\n expectedRemoteHead,\n type PublishSnapshotResult,\n type RemoteHead,\n type SyncBackend,\n} from \"../backends/sync-backend.js\";\nimport type { CommandOptions } from \"../commands/command-types.js\";\nimport { loadConfig, syncCheckConfigFingerprint } from \"../settings/config.js\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport { sessionDirForApply, snapshotOptionsForContext } from \"../snapshot/session-paths.js\";\nimport {\n createSnapshot,\n filterSnapshotForConfigPolicy,\n mergeRemotePreservedFiles,\n regenerateSnapshotIdentity,\n scanSnapshot,\n snapshotIncludesSessions,\n snapshotWithoutSessions,\n} from \"../snapshot/snapshot.js\";\nimport { applySnapshot } from \"../snapshot/snapshot-apply.js\";\nimport type { Snapshot } from \"../snapshot/snapshot-types.js\";\nimport { pruneMergeBaselines } from \"../state/merge-baseline-store.js\";\nimport type { SyncState } from \"../state/state-types.js\";\nimport { readStateForConfig, writeStateForConfig } from \"../state/sync-state-store.js\";\nimport {\n countPreservedRemoteFiles,\n formatPullSummary,\n formatPushSummary,\n formatRollbackSummary,\n} from \"../ui/sync-format.js\";\nimport { setSyncStatus } from \"../ui/sync-status.js\";\nimport { confirmFieldMigration } from \"./field-migration.js\";\nimport { overlayLocalFields, portableSnapshot, sameLocalFields, validatePortableSnapshot } from \"./local-fields.js\";\nimport { readMergeJournal, requireNoMergeJournal, retireMergeJournal } from \"./merge-journal.js\";\nimport { mergeSync } from \"./merged-sync.js\";\nimport { readRemoteSnapshot, readSnapshotForHead, requireCompatibleRemoteSelection } from \"./remote-snapshot.js\";\nimport { throwIfAborted } from \"./signals.js\";\nimport { createSyncDecision } from \"./sync-decision.js\";\nimport { errorMessage } from \"./sync-errors.js\";\n\nimport { backupLocal, captureMutationOwner, protectedSessionPaths } from \"./sync-local.js\";\nimport { inspectRemoteSelection } from \"./sync-policy.js\";\nimport {\n canPullRemoteSessionsOnFirstSync,\n canPullRemoteSettingsOnFirstSync,\n fileHashMap,\n hasLocalChanges,\n hasRemoteChanges,\n remoteChangedSinceState,\n sameHashes,\n shouldRefreshSyncedState,\n snapshotHashesMatchState,\n snapshotsMatch,\n syncPolicyChanged,\n} from \"./sync-state.js\";\n\nconst VERSION = 1;\nconst POST_LOCAL_COMMIT_TIMEOUT_MS = 30_000;\n\n/** Whole-direction acceptance must never forget withheld state without an explicit recovery choice. */\nfunction requireResolvedDirectionalProgress(state: SyncState, options: CommandOptions, allowForce = true) {\n if (state.unresolved?.length && (options.auto || !options.force || !allowForce))\n throw new Error(\n \"Unresolved partial conflicts remain. Review /sync conflicts or explicitly choose push --force or pull --force; automatic transfer and rollback cannot accept unresolved groups.\",\n );\n}\n\nexport class PublicationStatePersistenceError extends Error {\n readonly head: RemoteHead;\n readonly backupPath?: string;\n\n constructor(head: RemoteHead, cause: unknown, backupPath?: string) {\n super(\n `Remote publication ${head.snapshotId} is active, but local sync state could not be saved${backupPath ? `; local backup: ${backupPath}` : \"\"}: ${errorMessage(cause)}`,\n { cause },\n );\n this.name = \"PublicationStatePersistenceError\";\n this.head = head;\n this.backupPath = backupPath;\n }\n}\n\nexport class RollbackPublicationError extends Error {\n readonly backupPath: string;\n\n constructor(backupPath: string, cause: unknown) {\n super(`Rollback applied locally with backup ${backupPath}, but remote publication failed: ${errorMessage(cause)}`, {\n cause,\n });\n this.name = \"RollbackPublicationError\";\n this.backupPath = backupPath;\n }\n}\n\ninterface PushInput {\n config: AnySyncConfig;\n state: SyncState;\n local: Snapshot;\n backend?: SyncBackend;\n}\n\nexport async function push(\n ctx: ExtensionCommandContext | ExtensionContext,\n options: CommandOptions,\n input?: PushInput,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const validateMutation = captureMutationOwner(ctx, options.signal);\n const validateCommittedOwner = captureMutationOwner(ctx);\n const config = input?.config ?? (await loadConfig(options.setup));\n throwIfAborted(options.signal);\n await requireNoMergeJournal(config, options);\n const state = input?.state ?? (await readStateForConfig(config));\n validateMutation();\n requireResolvedDirectionalProgress(state, options);\n setSyncStatus(ctx, `pushing ${config.setupName}`);\n const backend = input?.backend ?? (await factory(config));\n throwIfAborted(options.signal);\n const localRaw =\n input?.local ?? (await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config)));\n const local = portableSnapshot(localRaw, config.localFields);\n throwIfAborted(options.signal);\n\n let head = await backend.readHead(options.signal);\n let remoteForUpload = await readRemoteSnapshotForUpload(backend, config, head, state, options.signal);\n if (\n !options.force &&\n !remoteForUpload &&\n head?.selection &&\n inspectRemoteSelection(config.include, { selection: head.selection, files: [] }).kind === \"different\"\n ) {\n remoteForUpload = await readSnapshotForHead(backend, head, options.signal);\n }\n if (remoteForUpload && !options.force) {\n requireCompatibleRemoteSelection(config, remoteForUpload);\n }\n if (\n remoteChangedSinceState(head, state, config, (left, right) => backend.sameRevision(left, right)) &&\n !options.force\n ) {\n const remoteForConflict = remoteForUpload ? filterSnapshotForConfigPolicy(remoteForUpload, config) : undefined;\n if (!remoteForConflict || !snapshotHashesMatchState(remoteForConflict, state, config)) {\n throw createSyncDecision({\n kind: head ? \"remote-or-policy-changed\" : \"remote-empty\",\n config,\n state,\n local,\n remote: remoteForConflict,\n localChanged: hasLocalChanges(local, state, config),\n remoteChanged: true,\n directMessage: \"Remote or sync policy changed since last sync. Run /sync pull first or /sync push --force.\",\n });\n }\n }\n\n if (!remoteForUpload && head && config.localFields !== undefined)\n remoteForUpload = await readSnapshotForHead(backend, head, options.signal);\n if (!(await confirmFieldMigration(ctx, config, state, remoteForUpload, options.force, options.signal))) {\n setSyncStatus(ctx, undefined);\n return \"cancelled\" as const;\n }\n const configIdentity = syncCheckConfigFingerprint(config);\n let upload = await snapshotForUpload(backend, config, local, head, remoteForUpload, options.signal);\n if (!config.skipSecretScan) {\n const secrets = scanSnapshot(local);\n if (secrets.length > 0) {\n throw new Error(`Refusing to push possible secrets:\\n${secrets.map((s) => `- ${s}`).join(\"\\n\")}`);\n }\n }\n\n if (!(await confirmPush(ctx, options, config, backend, local, upload, head, remoteForUpload))) {\n return \"cancelled\" as const;\n }\n\n if (options.force) {\n const refreshedHead = await backend.readHead(options.signal);\n if (!sameRemoteHead(backend, head, refreshedHead)) {\n head = refreshedHead;\n remoteForUpload = head ? await readSnapshotForHead(backend, head, options.signal) : undefined;\n validateMutation();\n if (!(await confirmFieldMigration(ctx, config, state, remoteForUpload, options.force, options.signal))) {\n setSyncStatus(ctx, undefined);\n return \"cancelled\" as const;\n }\n validateMutation();\n upload = await snapshotForUpload(backend, config, local, head, remoteForUpload, options.signal);\n if (\n !(await confirmPush(\n ctx,\n options,\n config,\n backend,\n local,\n upload,\n head,\n remoteForUpload,\n \"Remote changed during review. Push the refreshed plan?\",\n ))\n ) {\n return \"cancelled\" as const;\n }\n }\n }\n\n validateMutation();\n if (configIdentity !== syncCheckConfigFingerprint(await loadConfig(options.setup)))\n throw new Error(\"Settings changed during push review.\");\n validateMutation();\n if (config.localFields !== undefined || (await readMergeJournal(config))) {\n const current = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n if (!sameHashes(fileHashMap(current), fileHashMap(localRaw)))\n throw new Error(\"Local content changed during recovery review; retry from current bytes.\");\n }\n requireResolvedDirectionalProgress(await readStateForConfig(config), options);\n validateMutation();\n const result = await backend.publishSnapshot(upload, expectedRemoteHead(head), {\n signal: options.signal,\n onCommit: options.onCommit,\n });\n try {\n await writeStateForConfig(\n config,\n {\n version: VERSION,\n profile: config.snapshotIdentity,\n lastAppliedSnapshot: result.head.snapshotId,\n lastRemoteRevision: result.head.revision,\n lastFileHashes: fileHashMap(local),\n include: [...config.include],\n ...(config.localFields !== undefined ? { localFields: config.localFields } : {}),\n },\n local,\n validateCommittedOwner,\n );\n } catch (error) {\n throw new PublicationStatePersistenceError(result.head, error);\n }\n await retireMergeJournal(config);\n await pruneMergeBaselines(config, await readStateForConfig(config), validateCommittedOwner);\n validateCommittedOwner();\n if (options.signal?.aborted) return;\n setSyncStatus(ctx, undefined);\n if (!options.silent) {\n ctx.ui.notify(\n [\n `Pushed ${upload.files.length} files from sync setup \u201C${config.setupName}\u201D as ${result.head.snapshotId}.`,\n ...result.warnings,\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n result.warnings.length > 0 ? \"warning\" : \"info\",\n );\n }\n return \"applied\" as const;\n}\n\nexport async function pull(\n ctx: ExtensionCommandContext | ExtensionContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const validateMutation = captureMutationOwner(ctx, options.signal);\n const validateCommittedOwner = captureMutationOwner(ctx);\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n await requireNoMergeJournal(config, options);\n setSyncStatus(ctx, `pulling ${config.setupName}`);\n const backend = await factory(config);\n const state = await readStateForConfig(config);\n validateMutation();\n requireResolvedDirectionalProgress(state, options);\n const local = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n throwIfAborted(options.signal);\n const { head, snapshot: remote } = await readRemoteSnapshot(backend, config, options.signal);\n throwIfAborted(options.signal);\n const localChanged = hasLocalChanges(local, state, config);\n if (!remote) {\n throw createSyncDecision({\n kind: \"remote-empty\",\n config,\n state,\n local,\n localChanged,\n remoteChanged: false,\n directMessage: \"Remote is empty. Run /sync push from a configured machine first.\",\n });\n }\n\n if (!sameLocalFields(config.localFields, remote.localFields)) {\n setSyncStatus(ctx, undefined);\n throw new Error(\n \"Pull requires the configured local-field policy to match the remote. To change the remote policy, review push --force from the authoritative machine first, then pull using matching rules; old history is not erased.\",\n );\n }\n if (!(await confirmFieldMigration(ctx, config, state, remote, options.force, options.signal))) {\n setSyncStatus(ctx, undefined);\n return \"cancelled\" as const;\n }\n const configIdentity = syncCheckConfigFingerprint(config);\n const logical = portableSnapshot(remote, config.localFields);\n const physical = overlayLocalFields(logical, local, config.localFields);\n const remoteChanged = hasRemoteChanges(remote, state, config, protectedSessionPaths(ctx));\n if (localChanged && remoteChanged && state.lastAppliedSnapshot && !options.force) {\n throw createSyncDecision({\n kind: \"both-changed\",\n config,\n state,\n local,\n remote,\n localChanged,\n remoteChanged,\n directMessage:\n \"Both local and remote changed since last sync. Run /sync diff, then choose /sync pull --force or /sync push --force.\",\n });\n }\n\n if (\n !options.yes &&\n !(await ctx.ui.confirm(\n snapshotIncludesSessions(remote) ? \"Pull pi settings and sessions?\" : \"Pull pi settings?\",\n formatPullSummary(config, backend.destination, local, physical, protectedSessionPaths(ctx).size),\n ))\n ) {\n setSyncStatus(ctx, undefined);\n ctx.ui.notify(\"Pull cancelled.\", \"info\");\n return \"cancelled\" as const;\n }\n\n throwIfAborted(options.signal);\n const recoveringMerge = Boolean(await readMergeJournal(config));\n const requireFreshRecovery = async () => {\n validateMutation();\n const currentHead = await backend.readHead(options.signal);\n validateMutation();\n const current = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n validateMutation();\n if (!sameHashes(fileHashMap(current), fileHashMap(local)) || !sameRemoteHead(backend, head, currentHead)) {\n throw new Error(\"Local or remote content changed during recovery review; retry from a fresh diff.\");\n }\n };\n if (recoveringMerge) await requireFreshRecovery();\n if (configIdentity !== syncCheckConfigFingerprint(await loadConfig(options.setup)))\n throw new Error(\"Settings changed during pull review.\");\n validateMutation();\n const refreshed = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n if (!sameHashes(fileHashMap(local), fileHashMap(refreshed)))\n throw new Error(\"Local bytes changed during pull review.\");\n if (!sameRemoteHead(backend, head, await backend.readHead(options.signal)))\n throw new Error(\"Remote changed during pull review.\");\n validateMutation();\n const backup = await backupLocal(config.snapshotIdentity, snapshotOptionsForContext(ctx, config), options.signal);\n const applySessionDir = await sessionDirForApply(ctx, physical);\n if (recoveringMerge) await requireFreshRecovery();\n requireResolvedDirectionalProgress(await readStateForConfig(config), options);\n validateMutation();\n options.onCommit?.();\n const lastFileHashes = await applySnapshot(physical, protectedSessionPaths(ctx), {\n include: config.include,\n sessionDir: applySessionDir,\n signal: options.signal,\n validateMutation,\n expectedFileHashes: config.localFields?.length\n ? { \"settings.json\": fileHashMap(local)[\"settings.json\"] ?? null }\n : undefined,\n });\n // Local installation is complete; user cancellation must not leave the baseline stale.\n validateCommittedOwner();\n await writeStateForConfig(\n config,\n {\n version: VERSION,\n profile: config.snapshotIdentity,\n lastAppliedSnapshot: remote.id,\n lastRemoteRevision: head?.revision,\n lastFileHashes: config.localFields?.length\n ? { ...lastFileHashes, \"settings.json\": fileHashMap(logical)[\"settings.json\"] }\n : lastFileHashes,\n include: [...config.include],\n ...(config.localFields !== undefined ? { localFields: config.localFields } : {}),\n },\n logical,\n validateCommittedOwner,\n );\n await retireMergeJournal(config);\n await pruneMergeBaselines(config, await readStateForConfig(config), validateCommittedOwner);\n validateCommittedOwner();\n if (options.signal?.aborted) return \"applied\" as const;\n setSyncStatus(ctx, undefined);\n if (!options.silent) {\n ctx.ui.notify(`Pulled ${remote.files.length} files from ${remote.id}. Backup: ${backup}`, \"info\");\n } else if (options.auto && config.include.includes(\"sessions\") && snapshotIncludesSessions(remote)) {\n ctx.ui.notify(\n \"Pulled Pi sessions after startup selected the current session. Restart Pi or resume a pulled session to use newly synced conversations.\",\n \"warning\",\n );\n }\n if (options.reload) await maybeReload(ctx, options.signal, validateMutation);\n return \"applied\" as const;\n}\n\nexport async function syncBoth(\n ctx: ExtensionCommandContext | ExtensionContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const validateMutation = captureMutationOwner(ctx, options.signal);\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n if (config.include.length > 0 && options.auto && config.automaticTransfer) return mergeSync(ctx, options, factory);\n if (!options.auto && config.include.length > 0 && (await readMergeJournal(config)))\n return mergeSync(ctx, options, factory);\n const state = await readStateForConfig(config);\n throwIfAborted(options.signal);\n if (!options.auto && config.include.length > 0 && state.lastAppliedSnapshot) return mergeSync(ctx, options, factory);\n const backend = await factory(config);\n const local = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n throwIfAborted(options.signal);\n if (config.include.length === 0) {\n if (!options.silent) {\n ctx.ui.notify(\n `Sync setup \u201C${config.setupName}\u201D includes no files. Choose included content in /sync Settings before syncing.`,\n \"warning\",\n );\n }\n return;\n }\n const { head, snapshot: remote } = await readRemoteSnapshot(backend, config, options.signal);\n throwIfAborted(options.signal);\n const localChanged = hasLocalChanges(local, state, config);\n const remoteChanged = remote ? hasRemoteChanges(remote, state, config, protectedSessionPaths(ctx)) : false;\n const firstSync = !state.lastAppliedSnapshot;\n if (options.auto) throw new Error(\"Automatic transfer is not authorized by the current settings.\");\n\n const portableLocal = portableSnapshot(local, config.localFields);\n const acceptMatchingState = async (snapshot: Snapshot) => {\n requireCompatibleRemoteSelection(config, snapshot);\n const accepted = portableSnapshot(snapshot, config.localFields);\n if (state.lastAppliedSnapshot && !sameLocalFields(state.localFields, config.localFields))\n throw new Error(\"Local-field rules changed; review and confirm a directional migration first.\");\n await writeStateForConfig(\n config,\n {\n version: VERSION,\n profile: config.snapshotIdentity,\n lastAppliedSnapshot: snapshot.id,\n lastRemoteRevision: head?.revision,\n lastFileHashes: fileHashMap(accepted),\n include: [...config.include],\n ...(config.localFields !== undefined ? { localFields: config.localFields } : {}),\n },\n accepted,\n validateMutation,\n );\n await pruneMergeBaselines(config, await readStateForConfig(config), validateMutation);\n validateMutation();\n };\n if (firstSync && remote && remote.files.length > 0 && local.files.length > 0) {\n requireCompatibleRemoteSelection(config, remote);\n const portableRemote = portableSnapshot(remote, config.localFields);\n if (!canPullRemoteSettingsOnFirstSync(portableLocal, portableRemote)) {\n throw createSyncDecision({\n kind: \"first-sync-settings-diverged\",\n config,\n state,\n local,\n remote,\n localChanged: true,\n remoteChanged: true,\n directMessage:\n \"Remote settings exist and this machine has different local Pi settings. Run /sync diff, then manually choose /sync pull or /sync push.\",\n });\n }\n if (!sameHashes(fileHashMap(portableLocal), fileHashMap(portableRemote))) {\n if (!canPullRemoteSessionsOnFirstSync(portableLocal, portableRemote)) {\n throw createSyncDecision({\n kind: \"first-sync-sessions-diverged\",\n config,\n state,\n local,\n remote,\n localChanged: true,\n remoteChanged: true,\n directMessage:\n \"Remote settings match, but local and remote Pi sessions differ. Run /sync diff, then manually choose /sync pull or /sync push.\",\n });\n }\n await pull(ctx, options, factory);\n return;\n }\n await acceptMatchingState(remote);\n if (!options.silent) ctx.ui.notify(\"pi-sync state initialized; local settings already match remote.\", \"info\");\n return;\n }\n if (\n localChanged &&\n remoteChanged &&\n remote &&\n snapshotsMatch(portableLocal, portableSnapshot(remote, remote.localFields))\n ) {\n requireCompatibleRemoteSelection(config, remote);\n await acceptMatchingState(remote);\n if (!options.silent) ctx.ui.notify(\"pi-sync is already up to date.\", \"info\");\n return;\n }\n if (localChanged && remoteChanged && state.lastAppliedSnapshot) {\n throw createSyncDecision({\n kind: \"both-changed\",\n config,\n state,\n local,\n remote,\n localChanged,\n remoteChanged,\n directMessage: \"Both local and remote changed. Run /sync diff and resolve with push --force or pull --force.\",\n });\n }\n if (remoteChanged) {\n await pull(ctx, options, factory);\n return;\n }\n if (localChanged || !remote) {\n await push(ctx, options, undefined, factory);\n return;\n }\n if (shouldRefreshSyncedState(remote, head, state, config, (left, right) => backend.sameRevision(left, right))) {\n await acceptMatchingState(remote);\n }\n if (!options.silent) ctx.ui.notify(\"pi-sync is already up to date.\", \"info\");\n}\n\nexport async function rollback(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n expectedSelection?: { backendIdentity: string; setup?: string },\n) {\n const validateMutation = captureMutationOwner(ctx, options.signal);\n const validateCommittedOwner = captureMutationOwner(ctx);\n const target = options.args[0];\n if (!target) throw new Error(\"Usage: /sync rollback <snapshot-id> [--yes]\");\n\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n const backend = await factory(config);\n if (\n expectedSelection &&\n (backend.identity !== expectedSelection.backendIdentity || config.setupName !== expectedSelection.setup)\n ) {\n throw new Error(\"Sync setup or storage location changed while history was open; reopen history and retry.\");\n }\n // --force is only a rollback compatibility flag, not a reviewed merge-recovery direction.\n await requireNoMergeJournal(config);\n const state = await readStateForConfig(config);\n validateMutation();\n requireResolvedDirectionalProgress(state, options, false);\n const decoded = await backend.readSnapshot(target, options.signal);\n validatePortableSnapshot(decoded);\n if (!sameLocalFields(decoded.localFields, config.localFields))\n throw new Error(\n \"Rollback requires the historical snapshot local-field policy to match the configured rules. Review push --force from current local bytes to migrate policy first; choose matching history afterward.\",\n );\n const selected = filterSnapshotForConfigPolicy(\n config.include.includes(\"sessions\") ? decoded : snapshotWithoutSessions(decoded),\n config,\n );\n const remote = portableSnapshot(regenerateSnapshotIdentity(selected), config.localFields);\n const local = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n const expectedHead = await backend.readHead(options.signal);\n const currentRemote = expectedHead ? await readSnapshotForHead(backend, expectedHead, options.signal) : undefined;\n validateMutation();\n if (!(await confirmFieldMigration(ctx, config, state, currentRemote, true, options.signal))) return;\n validateMutation();\n const physical = overlayLocalFields(remote, local, config.localFields);\n\n if (!options.yes) {\n const confirmed = await ctx.ui.confirm(\n snapshotIncludesSessions(remote) ? \"Rollback pi settings and sessions?\" : \"Rollback pi settings?\",\n formatRollbackSummary(config, backend.destination, local, physical, target, protectedSessionPaths(ctx).size),\n { signal: options.signal },\n );\n validateMutation();\n if (!confirmed) {\n ctx.ui.notify(\"Rollback cancelled.\", \"info\");\n return;\n }\n }\n\n validateMutation();\n const currentLocal = await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config));\n if (!sameHashes(fileHashMap(currentLocal), fileHashMap(local)))\n throw new Error(\"Local bytes changed during rollback review.\");\n if (syncCheckConfigFingerprint(config) !== syncCheckConfigFingerprint(await loadConfig(options.setup)))\n throw new Error(\"Settings changed during rollback review.\");\n if (!sameRemoteHead(backend, expectedHead, await backend.readHead(options.signal)))\n throw new Error(\"Remote changed during rollback review.\");\n validateMutation();\n throwIfAborted(options.signal);\n const backup = await backupLocal(config.snapshotIdentity, snapshotOptionsForContext(ctx, config), options.signal);\n const applySessionDir = await sessionDirForApply(ctx, remote);\n requireResolvedDirectionalProgress(await readStateForConfig(config), options, false);\n validateMutation();\n options.onCommit?.();\n const lastFileHashes = await applySnapshot(physical, protectedSessionPaths(ctx), {\n include: config.include,\n sessionDir: applySessionDir,\n signal: options.signal,\n validateMutation,\n expectedFileHashes: config.localFields?.length\n ? { \"settings.json\": fileHashMap(local)[\"settings.json\"] ?? null }\n : undefined,\n });\n // The local transaction is retired; finish publication despite caller cancellation.\n validateCommittedOwner();\n let result: PublishSnapshotResult;\n try {\n const completionSignal = AbortSignal.timeout(POST_LOCAL_COMMIT_TIMEOUT_MS);\n const upload = await snapshotForUpload(backend, config, remote, expectedHead, currentRemote, completionSignal);\n validateCommittedOwner();\n result = await backend.publishSnapshot(upload, expectedRemoteHead(expectedHead), {\n signal: completionSignal,\n });\n } catch (error) {\n throw new RollbackPublicationError(backup, error);\n }\n try {\n await writeStateForConfig(\n config,\n {\n version: VERSION,\n profile: config.snapshotIdentity,\n lastAppliedSnapshot: result.head.snapshotId,\n lastRemoteRevision: result.head.revision,\n lastFileHashes: config.localFields?.length\n ? { ...lastFileHashes, \"settings.json\": fileHashMap(remote)[\"settings.json\"] }\n : lastFileHashes,\n include: [...config.include],\n ...(config.localFields !== undefined ? { localFields: config.localFields } : {}),\n },\n remote,\n validateCommittedOwner,\n );\n } catch (error) {\n throw new PublicationStatePersistenceError(result.head, error, backup);\n }\n await retireMergeJournal(config);\n await pruneMergeBaselines(config, await readStateForConfig(config), validateCommittedOwner);\n validateCommittedOwner();\n if (options.signal?.aborted) return;\n ctx.ui.notify(\n [\n `Rolled back sync setup \u201C${config.setupName}\u201D to ${target}; latest: ${result.head.snapshotId}. Backup: ${backup}`,\n ...result.warnings,\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n result.warnings.length > 0 ? \"warning\" : \"info\",\n );\n await maybeReload(ctx, options.signal, validateMutation);\n}\n\nasync function maybeReload(\n ctx: ExtensionCommandContext | ExtensionContext,\n signal?: AbortSignal,\n validateMutation = captureMutationOwner(ctx, signal),\n) {\n if (signal?.aborted || !(\"reload\" in ctx)) return;\n validateMutation();\n if (\n ctx.hasUI &&\n (await ctx.ui.confirm(\n \"Reload Pi resources now?\",\n \"This reloads extensions, skills, prompts, themes, and context files.\",\n ))\n ) {\n if (signal?.aborted) return;\n validateMutation();\n await ctx.reload();\n }\n}\n\nasync function readRemoteSnapshotForUpload(\n backend: SyncBackend,\n config: AnySyncConfig,\n head: RemoteHead | undefined,\n state: SyncState,\n signal?: AbortSignal,\n) {\n if (\n !head ||\n (head.snapshotId === state.lastAppliedSnapshot &&\n !syncPolicyChanged(state, config) &&\n (!state.lastRemoteRevision || backend.sameRevision(head.revision, state.lastRemoteRevision)))\n ) {\n return undefined;\n }\n return readSnapshotForHead(backend, head, signal);\n}\n\nasync function snapshotForUpload(\n backend: SyncBackend,\n config: AnySyncConfig,\n local: Snapshot,\n head: RemoteHead | undefined,\n remote?: Snapshot,\n signal?: AbortSignal,\n) {\n if (!head) return local;\n const snapshot = remote ?? (await readSnapshotForHead(backend, head, signal));\n return mergeRemotePreservedFiles(local, snapshot, config);\n}\n\nasync function confirmPush(\n ctx: ExtensionCommandContext | ExtensionContext,\n options: CommandOptions,\n config: AnySyncConfig,\n backend: SyncBackend,\n local: Snapshot,\n upload: Snapshot,\n head: RemoteHead | undefined,\n remote: Snapshot | undefined,\n title = snapshotIncludesSessions(upload) ? \"Push pi settings and sessions?\" : \"Push pi settings?\",\n) {\n throwIfAborted(options.signal);\n if (options.yes) return true;\n const confirmed = await ctx.ui.confirm(\n title,\n formatPushSummary(config, backend.destination, upload, head, countPreservedRemoteFiles(local, upload), remote),\n );\n throwIfAborted(options.signal);\n if (confirmed) return true;\n setSyncStatus(ctx, undefined);\n ctx.ui.notify(\"Push cancelled.\", \"info\");\n return false;\n}\n\nfunction sameRemoteHead(backend: SyncBackend, left: RemoteHead | undefined, right: RemoteHead | undefined) {\n if (!left || !right) return left === right;\n return backend.sameRevision(left.revision, right.revision);\n}\n\nexport { backupLocal } from \"./sync-local.js\";\n", "import type { ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport { createSyncBackend, type SyncBackendFactory } from \"../backends/backend-factory.js\";\nimport type { SyncBackend } from \"../backends/sync-backend.js\";\nimport type { CommandOptions } from \"../commands/command-types.js\";\nimport { loadConfig, syncSessionsWarnings } from \"../settings/config.js\";\nimport { snapshotOptionsForContext } from \"../snapshot/session-paths.js\";\nimport { createSnapshot, scanSnapshot } from \"../snapshot/snapshot.js\";\nimport type { SnapshotOptions } from \"../snapshot/snapshot-types.js\";\nimport { inspectLock, isLockGuardHeld, isStaleLock, withLock } from \"../state/lock.js\";\nimport { formatDiff, formatSnapshotOnlyDiff, publicationCapabilityDescription } from \"../ui/sync-format.js\";\nimport { setSyncStatus } from \"../ui/sync-status.js\";\nimport { safeTerminalText } from \"../ui/terminal-text.js\";\nimport { portableSnapshot } from \"./local-fields.js\";\nimport { formatRemoteSelectionStatus, readRemoteSnapshot } from \"./remote-snapshot.js\";\nimport { throwIfAborted } from \"./signals.js\";\nimport { errorMessage } from \"./sync-errors.js\";\nimport { inspectSync } from \"./sync-inspection.js\";\nimport { rollback } from \"./sync-mutations.js\";\n\nconst DEFAULT_PROFILE = \"default\";\n\nexport async function status(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n setSyncStatus(ctx, `checking ${config.setupName}`);\n const { head, selectionState, localChanged, remoteChanged, localFiles, destination, capability } = await inspectSync(\n config,\n snapshotOptionsForContext(ctx, config),\n options.signal,\n factory,\n );\n throwIfAborted(options.signal);\n\n const remoteText = head ? `remote: ${head.snapshotId} from ${head.machine} at ${head.createdAt}` : \"remote: empty\";\n const warnings = syncSessionsWarnings(config);\n setSyncStatus(ctx, undefined);\n ctx.ui.notify(\n [\n `sync setup: ${config.setupName}`,\n `storage connection: ${config.connectionName}`,\n `storage location: ${safeTerminalText(destination)}`,\n `publication safety: ${publicationCapabilityDescription(capability)}`,\n `included content: ${config.include.join(\", \") || \"none\"}`,\n `sessions: ${config.include.includes(\"sessions\") ? \"included\" : \"excluded\"}`,\n remoteText,\n formatRemoteSelectionStatus(selectionState),\n `local files: ${localFiles}`,\n `local changed since last sync: ${localChanged ? \"yes\" : \"no\"}`,\n `remote changed since last sync: ${remoteChanged ? \"yes\" : \"no\"}`,\n ...warnings,\n ].join(\"\\n\"),\n localChanged || remoteChanged || selectionState?.kind === \"different\" || warnings.length > 0 ? \"warning\" : \"info\",\n );\n}\n\nexport async function diff(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n setSyncStatus(ctx, `checking ${config.setupName}`);\n const backend = await factory(config);\n const local = portableSnapshot(\n await createSnapshot(config.snapshotIdentity, snapshotOptionsForContext(ctx, config)),\n config.localFields,\n );\n throwIfAborted(options.signal);\n const { snapshot: remote, selectionState } = await readRemoteSnapshot(backend, config, options.signal, {\n allowSelectionDifference: true,\n });\n throwIfAborted(options.signal);\n setSyncStatus(ctx, undefined);\n\n const warnings = syncSessionsWarnings(config);\n const header = [\n `sync setup: ${config.setupName}`,\n `storage connection: ${config.connectionName}`,\n `storage location: ${safeTerminalText(backend.destination)}`,\n `included content: ${config.include.join(\", \") || \"none\"}`,\n `sessions: ${config.include.includes(\"sessions\") ? \"included\" : \"excluded\"}`,\n formatRemoteSelectionStatus(selectionState),\n ...warnings,\n ].join(\"\\n\");\n const level = warnings.length > 0 || selectionState?.kind === \"different\" ? \"warning\" : \"info\";\n if (!remote) {\n ctx.ui.notify(`${header}\\n\\n${formatSnapshotOnlyDiff(\"Remote is empty. Local push would upload\", local)}`, level);\n return;\n }\n\n ctx.ui.notify(`${header}\\n\\n${formatDiff(local, portableSnapshot(remote, remote.localFields))}`, level);\n}\n\nexport async function doctor(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const messages: string[] = [];\n let level: \"info\" | \"warning\" = \"info\";\n let snapshotOptions: SnapshotOptions = {};\n let profile = DEFAULT_PROFILE;\n let backend: SyncBackend | undefined;\n let backendSummary: string[] = [];\n\n try {\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n backend = await factory(config);\n profile = config.snapshotIdentity;\n snapshotOptions = snapshotOptionsForContext(ctx, config);\n messages.push(\n `config: ok (sync setup ${config.setupName})`,\n `included content: ${config.include.join(\", \") || \"none\"}`,\n `sessions: ${config.include.includes(\"sessions\") ? \"included\" : \"excluded\"}`,\n );\n backendSummary = [\n `storage location: ${safeTerminalText(backend.destination)}`,\n `publication safety: ${publicationCapabilityDescription(backend.capability)}`,\n ];\n const warnings = syncSessionsWarnings(config);\n if (warnings.length > 0) {\n level = \"warning\";\n messages.push(...warnings);\n }\n } catch (error) {\n throwIfAborted(options.signal);\n level = \"warning\";\n messages.push(`config: ${errorMessage(error)}`);\n }\n\n const local = await createSnapshot(profile, snapshotOptions);\n throwIfAborted(options.signal);\n const secrets = scanSnapshot(local);\n if (secrets.length > 0) {\n level = \"warning\";\n messages.push(\"secret scan: possible secrets found:\");\n messages.push(...secrets.map((secret) => `- ${secret}`));\n } else {\n messages.push(`secret scan: ok (${local.files.length} files checked)`);\n }\n\n const lock = await inspectLock();\n throwIfAborted(options.signal);\n if (lock.status === \"valid\" && isStaleLock(lock.lock)) {\n level = \"warning\";\n messages.push(`lock: stale (pid ${lock.lock.pid}); run /sync unlock --stale after verifying no sync is running`);\n } else if (lock.status === \"valid\") {\n messages.push(`lock: held by pid ${lock.lock.pid} since ${lock.lock.startedAt}`);\n } else if (lock.status === \"unreadable\") {\n level = \"warning\";\n messages.push(\"lock: unreadable; use /sync unlock --stale only after verifying no sync is running\");\n } else if (await isLockGuardHeld()) {\n throwIfAborted(options.signal);\n level = \"warning\";\n messages.push(\"lock: guard active while metadata is missing or still being initialized\");\n } else {\n messages.push(\"lock: free\");\n }\n\n if (backend) {\n messages.push(...backendSummary);\n const diagnostics = await backend.diagnose(options.signal);\n throwIfAborted(options.signal);\n for (const diagnostic of diagnostics) {\n messages.push(diagnostic.message);\n if (diagnostic.level !== \"info\") level = \"warning\";\n }\n }\n ctx.ui.notify(messages.join(\"\\n\"), level);\n}\n\nexport async function history(\n ctx: ExtensionCommandContext,\n options: CommandOptions,\n factory: SyncBackendFactory = createSyncBackend,\n) {\n const config = await loadConfig(options.setup);\n throwIfAborted(options.signal);\n const backend = await factory(config);\n const snapshots = (await backend.listHistory(options.signal)).slice(-20).reverse();\n throwIfAborted(options.signal);\n if (snapshots.length === 0) {\n ctx.ui.notify(\"No remote pi-sync history found.\", \"info\");\n return;\n }\n\n const currentSnapshot = snapshots[0]?.snapshotId;\n if (ctx.mode === \"tui\") {\n const labels = snapshots.map(\n (item, index) =>\n `${index + 1}. ${item.createdAt} \u00B7 ${safeTerminalText(item.machine)} \u00B7 ${item.snapshotId}${item.snapshotId === currentSnapshot ? \" (current)\" : \"\"}${item.syncSessions ? \" \u00B7 sessions\" : \"\"}`,\n );\n const selected = await ctx.ui.select(\n `History for sync setup \u201C${safeTerminalText(config.setupName)}\u201D\\n\\nChoose a snapshot to preview rollback.`,\n [...labels, \"Back\"],\n { signal: options.signal },\n );\n if (!selected || selected === \"Back\") return;\n throwIfAborted(options.signal);\n const index = labels.indexOf(selected);\n const snapshot = snapshots[index];\n if (!snapshot) return;\n await withLock(\"rollback\", () =>\n rollback(ctx, { ...options, args: [snapshot.snapshotRef], yes: false }, factory, {\n backendIdentity: backend.identity,\n setup: config.setupName,\n }),\n );\n return;\n }\n ctx.ui.notify(\n snapshots.map((item) => `${item.snapshotRef} ${item.createdAt} ${safeTerminalText(item.machine)}`).join(\"\\n\"),\n \"info\",\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["index"]
|
|
7
7
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import {
|
|
4
4
|
SyncBackendConflictError,
|
|
5
5
|
SyncBackendPublicationOutcomeUnknownError
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-YDVQYUHE.ts";
|
|
7
7
|
import {
|
|
8
8
|
decodeSnapshot,
|
|
9
9
|
encodeSnapshot
|
|
@@ -854,4 +854,4 @@ export {
|
|
|
854
854
|
snapshotsPath,
|
|
855
855
|
webDavBackendIdentity
|
|
856
856
|
};
|
|
857
|
-
//# sourceMappingURL=webdav-backend-
|
|
857
|
+
//# sourceMappingURL=webdav-backend-TBILVEQK.ts.map
|
package/dist/index.ts
CHANGED
|
@@ -82,6 +82,29 @@ import {
|
|
|
82
82
|
import "./chunks/chunk-ZW5ZLGBI.ts";
|
|
83
83
|
import "./chunks/chunk-HUZ5CR4W.ts";
|
|
84
84
|
|
|
85
|
+
// src/ui/operation-dialogs.ts
|
|
86
|
+
function trackOperationDialogs(ctx, onDialog) {
|
|
87
|
+
if (!onDialog) return ctx;
|
|
88
|
+
const runDialog = async (task) => {
|
|
89
|
+
onDialog(true);
|
|
90
|
+
try {
|
|
91
|
+
return await task();
|
|
92
|
+
} finally {
|
|
93
|
+
onDialog(false);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const ui = {
|
|
97
|
+
...ctx.ui,
|
|
98
|
+
select: (...args) => runDialog(() => ctx.ui.select(...args)),
|
|
99
|
+
confirm: (...args) => runDialog(() => ctx.ui.confirm(...args))
|
|
100
|
+
};
|
|
101
|
+
return new Proxy(ctx, {
|
|
102
|
+
get(target, key, receiver) {
|
|
103
|
+
return key === "ui" ? ui : Reflect.get(target, key, receiver);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
85
108
|
// src/commands/command-execution.ts
|
|
86
109
|
async function executeRecoveryCommand(rawArgs, ctx, signal, loaders, onCommit, setup) {
|
|
87
110
|
try {
|
|
@@ -121,7 +144,8 @@ async function executeRecoveryCommand(rawArgs, ctx, signal, loaders, onCommit, s
|
|
|
121
144
|
return { kind: "failed" };
|
|
122
145
|
}
|
|
123
146
|
}
|
|
124
|
-
async function executeCommand(rawArgs, ctx, signal, loaders, onCommit, setup) {
|
|
147
|
+
async function executeCommand(rawArgs, ctx, signal, loaders, onCommit, setup, onDialog) {
|
|
148
|
+
ctx = trackOperationDialogs(ctx, onDialog);
|
|
125
149
|
try {
|
|
126
150
|
const command = await resolveSyncCommand(rawArgs, ctx);
|
|
127
151
|
if (signal?.aborted || !command) return { kind: "completed" };
|
|
@@ -176,7 +200,7 @@ async function executeCommand(rawArgs, ctx, signal, loaders, onCommit, setup) {
|
|
|
176
200
|
return { kind: "completed" };
|
|
177
201
|
}
|
|
178
202
|
case "conflicts": {
|
|
179
|
-
const { showConflicts } = await import("./chunks/conflict-review-
|
|
203
|
+
const { showConflicts } = await import("./chunks/conflict-review-JANNPKKS.ts");
|
|
180
204
|
throwIfAborted(options.signal);
|
|
181
205
|
await withLock("sync", () => showConflicts(ctx, options));
|
|
182
206
|
return { kind: "completed" };
|
|
@@ -366,17 +390,18 @@ function displayWebDavUrl(value, username) {
|
|
|
366
390
|
async function handleCommand(rawArgs, ctx, sessionSignal, loaders, attention) {
|
|
367
391
|
await reconcileObservation(attention, sessionSignal);
|
|
368
392
|
if (sessionSignal.aborted) return;
|
|
369
|
-
const run = (route, signal, onCommit, target) => executeCommand(
|
|
393
|
+
const run = (route, signal, onCommit, target, onDialog) => executeCommand(
|
|
370
394
|
route,
|
|
371
395
|
ctx,
|
|
372
396
|
combineSignals(sessionSignal, signal),
|
|
373
397
|
loaders,
|
|
374
398
|
observationCommitCallback(attention, sessionSignal, onCommit),
|
|
375
|
-
target
|
|
399
|
+
target,
|
|
400
|
+
onDialog
|
|
376
401
|
);
|
|
377
402
|
if (!rawArgs.trim()) {
|
|
378
403
|
try {
|
|
379
|
-
const { showSyncManager } = await import("./chunks/manager-ui-
|
|
404
|
+
const { showSyncManager } = await import("./chunks/manager-ui-IURS4WXY.ts");
|
|
380
405
|
if (sessionSignal.aborted) return;
|
|
381
406
|
await showSyncManager(ctx, run, sessionSignal, {
|
|
382
407
|
getAttention: () => attention.current(),
|
|
@@ -476,7 +501,7 @@ function directSelectionOrigin(rawArgs) {
|
|
|
476
501
|
async function resolveSelectionAttention(ctx, attention, signal, loaders, options = {}) {
|
|
477
502
|
const current = attention.current();
|
|
478
503
|
if (!current || signal.aborted) return;
|
|
479
|
-
const { dispatchManagerResult } = await import("./chunks/manager-result-dispatcher-
|
|
504
|
+
const { dispatchManagerResult } = await import("./chunks/manager-result-dispatcher-6MQKFCWB.ts");
|
|
480
505
|
if (signal.aborted || attention.current() !== current) return;
|
|
481
506
|
await dispatchManagerResult(
|
|
482
507
|
ctx,
|
|
@@ -755,11 +780,11 @@ function createStartupCheck(loaders, attention, timeoutMs = 3e4) {
|
|
|
755
780
|
// src/sync/sync-loaders.ts
|
|
756
781
|
function createSyncLoaders(dependencies) {
|
|
757
782
|
const loaders = {
|
|
758
|
-
inspection: cachedModuleLoader(dependencies.loadSyncInspection ?? (() => import("./chunks/sync-inspection-
|
|
783
|
+
inspection: cachedModuleLoader(dependencies.loadSyncInspection ?? (() => import("./chunks/sync-inspection-K45QVLHB.ts"))),
|
|
759
784
|
setupSwitch: cachedModuleLoader(dependencies.loadSetupSwitch ?? (() => import("./chunks/setup-switch-KTUWL6DE.ts"))),
|
|
760
785
|
snapshot: cachedModuleLoader(dependencies.loadSnapshot ?? (() => import("./chunks/snapshot-THS5EY2L.ts"))),
|
|
761
786
|
syncState: cachedModuleLoader(dependencies.loadSyncState ?? (() => import("./chunks/sync-state-CFL4RRRB.ts"))),
|
|
762
|
-
operations: cachedModuleLoader(dependencies.loadSyncOperations ?? (() => import("./chunks/sync-operations-
|
|
787
|
+
operations: cachedModuleLoader(dependencies.loadSyncOperations ?? (() => import("./chunks/sync-operations-OWTE3ZL2.ts")))
|
|
763
788
|
};
|
|
764
789
|
return loaders;
|
|
765
790
|
}
|