@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.
Files changed (209) hide show
  1. package/README.md +49 -16
  2. package/dist/chunks/chunk-2B2ELUF5.ts +29 -0
  3. package/dist/chunks/chunk-2B2ELUF5.ts.map +7 -0
  4. package/dist/chunks/chunk-6LP3MCR2.ts +115 -0
  5. package/dist/chunks/chunk-6LP3MCR2.ts.map +7 -0
  6. package/dist/chunks/chunk-6UHKGALE.ts +134 -0
  7. package/dist/chunks/chunk-6UHKGALE.ts.map +7 -0
  8. package/dist/chunks/{chunk-JF6MZCT4.ts → chunk-AUSDLD6F.ts} +4 -4
  9. package/dist/chunks/chunk-AUSDLD6F.ts.map +7 -0
  10. package/dist/chunks/{chunk-X7SQ2EQM.ts → chunk-AXXS2BPA.ts} +9 -9
  11. package/dist/chunks/chunk-AXXS2BPA.ts.map +7 -0
  12. package/dist/chunks/{chunk-5T442OP3.ts → chunk-C7XY5NF5.ts} +210 -373
  13. package/dist/chunks/chunk-C7XY5NF5.ts.map +7 -0
  14. package/dist/chunks/{chunk-4U6AFLJB.ts → chunk-CHH26D4F.ts} +3 -2
  15. package/dist/chunks/chunk-CHH26D4F.ts.map +7 -0
  16. package/dist/chunks/chunk-CPEHGXJV.ts +50 -0
  17. package/dist/chunks/chunk-CPEHGXJV.ts.map +7 -0
  18. package/dist/chunks/{chunk-5MQ76BK5.ts → chunk-D5X27LCA.ts} +2 -2
  19. package/dist/chunks/chunk-D5X27LCA.ts.map +7 -0
  20. package/dist/chunks/{chunk-WSOBYHIZ.ts → chunk-GWMHAQG4.ts} +4 -4
  21. package/dist/chunks/chunk-GWMHAQG4.ts.map +7 -0
  22. package/dist/chunks/{chunk-5LZALPCD.ts → chunk-HUDQATCL.ts} +25 -25
  23. package/dist/chunks/chunk-HUDQATCL.ts.map +7 -0
  24. package/dist/chunks/{chunk-YQ6UW7IF.ts → chunk-JAAKLL6M.ts} +2 -2
  25. package/dist/chunks/chunk-JAAKLL6M.ts.map +7 -0
  26. package/dist/chunks/chunk-JSYMGJQQ.ts +51 -0
  27. package/dist/chunks/chunk-JSYMGJQQ.ts.map +7 -0
  28. package/dist/chunks/chunk-L7TBO32M.ts +25 -0
  29. package/dist/chunks/chunk-L7TBO32M.ts.map +7 -0
  30. package/dist/chunks/{chunk-DFXBKHGN.ts → chunk-LCRI3ABW.ts} +21 -8
  31. package/dist/chunks/chunk-LCRI3ABW.ts.map +7 -0
  32. package/dist/chunks/chunk-LTBWGSBV.ts +12 -0
  33. package/dist/chunks/chunk-LTBWGSBV.ts.map +7 -0
  34. package/dist/chunks/chunk-NJFUIVYL.ts +17 -0
  35. package/dist/chunks/chunk-NJFUIVYL.ts.map +7 -0
  36. package/dist/chunks/{chunk-HVUSHMVL.ts → chunk-OEX4ABY6.ts} +39 -37
  37. package/dist/chunks/chunk-OEX4ABY6.ts.map +7 -0
  38. package/dist/chunks/chunk-OUHGBFYF.ts +1255 -0
  39. package/dist/chunks/chunk-OUHGBFYF.ts.map +7 -0
  40. package/dist/chunks/{chunk-HGV24P4T.ts → chunk-Q2TUM5X6.ts} +3 -3
  41. package/dist/chunks/chunk-Q2TUM5X6.ts.map +7 -0
  42. package/dist/chunks/{chunk-GLQLN5GV.ts → chunk-SL64RLXR.ts} +8 -6
  43. package/dist/chunks/chunk-SL64RLXR.ts.map +7 -0
  44. package/dist/chunks/chunk-T3HH3UEJ.ts +96 -0
  45. package/dist/chunks/chunk-T3HH3UEJ.ts.map +7 -0
  46. package/dist/chunks/chunk-TEN2ZBJV.ts +101 -0
  47. package/dist/chunks/chunk-TEN2ZBJV.ts.map +7 -0
  48. package/dist/chunks/chunk-THMF4BVL.ts +18 -0
  49. package/dist/chunks/chunk-THMF4BVL.ts.map +7 -0
  50. package/dist/chunks/{chunk-44LPGQTI.ts → chunk-X5OM6GXT.ts} +9 -7
  51. package/dist/chunks/chunk-X5OM6GXT.ts.map +7 -0
  52. package/dist/chunks/chunk-XBX4HBLG.ts +57 -0
  53. package/dist/chunks/chunk-XBX4HBLG.ts.map +7 -0
  54. package/dist/chunks/{chunk-ARN2672F.ts → chunk-YKJHPTGO.ts} +23 -55
  55. package/dist/chunks/chunk-YKJHPTGO.ts.map +7 -0
  56. package/dist/chunks/chunk-Z4DQF6L3.ts +12 -0
  57. package/dist/chunks/chunk-Z4DQF6L3.ts.map +7 -0
  58. package/dist/chunks/{chunk-F5QL2GPY.ts → chunk-ZI5MXMEX.ts} +5 -99
  59. package/dist/chunks/chunk-ZI5MXMEX.ts.map +7 -0
  60. package/dist/chunks/{file-selection-RKEHALNQ.ts → file-selection-FTTKAOYX.ts} +10 -7
  61. package/dist/chunks/file-selection-FTTKAOYX.ts.map +7 -0
  62. package/dist/chunks/{git-backend-E3UOUUOM.ts → git-backend-OQW46G2X.ts} +42 -17
  63. package/dist/chunks/git-backend-OQW46G2X.ts.map +7 -0
  64. package/dist/chunks/manager-result-dispatcher-U23ODD32.ts +22 -0
  65. package/dist/chunks/manager-ui-ABATHC36.ts +1680 -0
  66. package/dist/chunks/manager-ui-ABATHC36.ts.map +7 -0
  67. package/dist/chunks/remote-selection-ui-ZE3TY67S.ts +21 -0
  68. package/dist/chunks/{s3-backend-552LXHE4.ts → s3-backend-3P33LQHU.ts} +96 -18
  69. package/dist/chunks/s3-backend-3P33LQHU.ts.map +7 -0
  70. package/dist/chunks/{setup-switch-5YDG5YGJ.ts → setup-switch-IS2PEZ3J.ts} +9 -9
  71. package/dist/chunks/setup-wizard-VB3VDOV5.ts +89 -0
  72. package/dist/chunks/setup-wizard-VB3VDOV5.ts.map +7 -0
  73. package/dist/chunks/{snapshot-2RYBUDRA.ts → snapshot-HKEWCVK6.ts} +7 -6
  74. package/dist/chunks/sync-inspection-FEP4L5TR.ts +20 -0
  75. package/dist/chunks/{sync-operations-3LLIHWZO.ts → sync-operations-ONJ27QRL.ts} +374 -294
  76. package/dist/chunks/sync-operations-ONJ27QRL.ts.map +7 -0
  77. package/dist/chunks/{sync-state-SRN6YRBK.ts → sync-state-Q2FTXTW6.ts} +6 -6
  78. package/dist/chunks/sync-state-Q2FTXTW6.ts.map +7 -0
  79. package/dist/chunks/{webdav-backend-ZD5RHRIU.ts → webdav-backend-ECIKD7SO.ts} +26 -13
  80. package/dist/chunks/webdav-backend-ECIKD7SO.ts.map +7 -0
  81. package/dist/index.ts +477 -342
  82. package/dist/index.ts.map +4 -4
  83. package/docs/settings.md +30 -6
  84. package/package.json +1 -1
  85. package/src/{backend-factory.ts → backends/backend-factory.ts} +4 -4
  86. package/src/backends/backend-identity.ts +40 -0
  87. package/src/backends/backend-types.ts +81 -0
  88. package/src/{git-backend.ts → backends/git/git-backend.ts} +43 -19
  89. package/src/{git-config.ts → backends/git/git-config.ts} +1 -0
  90. package/src/{git-storage.ts → backends/git/git-storage.ts} +2 -2
  91. package/src/{s3-backend.ts → backends/s3/s3-backend.ts} +45 -9
  92. package/src/{s3-client.ts → backends/s3/s3-client.ts} +56 -8
  93. package/src/{sync-backend.ts → backends/sync-backend.ts} +1 -1
  94. package/src/{webdav-backend.ts → backends/webdav/webdav-backend.ts} +22 -10
  95. package/src/{webdav-client.ts → backends/webdav/webdav-client.ts} +1 -1
  96. package/src/{webdav-config.ts → backends/webdav/webdav-config.ts} +1 -0
  97. package/src/commands/command-execution.ts +330 -0
  98. package/src/commands/command-handler.ts +201 -0
  99. package/src/commands/command-types.ts +18 -0
  100. package/src/{command.ts → commands/command.ts} +2 -1
  101. package/src/commands/setup-completions.ts +6 -0
  102. package/src/settings/config.ts +238 -0
  103. package/src/{settings-management.ts → settings/settings-management.ts} +39 -14
  104. package/src/settings/settings-store.ts +109 -0
  105. package/src/settings/settings-types.ts +128 -0
  106. package/src/settings/settings-validation.ts +443 -0
  107. package/src/snapshot/session-paths.ts +84 -0
  108. package/src/{snapshot-apply.ts → snapshot/snapshot-apply.ts} +3 -3
  109. package/src/{snapshot-codec.ts → snapshot/snapshot-codec.ts} +2 -2
  110. package/src/{snapshot-transaction.ts → snapshot/snapshot-transaction.ts} +5 -4
  111. package/src/snapshot/snapshot-types.ts +38 -0
  112. package/src/{snapshot.ts → snapshot/snapshot.ts} +39 -20
  113. package/src/state/json-file.ts +20 -0
  114. package/src/{lock.ts → state/lock.ts} +3 -2
  115. package/src/{operation-availability.ts → state/operation-availability.ts} +2 -2
  116. package/src/state/state-types.ts +20 -0
  117. package/src/state/sync-state-store.ts +62 -0
  118. package/src/sync/automatic-sync.ts +103 -0
  119. package/src/{remote-snapshot.ts → sync/remote-snapshot.ts} +27 -4
  120. package/src/{setup-switch.ts → sync/setup-switch.ts} +6 -7
  121. package/src/sync/signals.ts +10 -0
  122. package/src/sync/startup-check.ts +128 -0
  123. package/src/{sync-decision.ts → sync/sync-decision.ts} +6 -3
  124. package/src/sync/sync-error-guidance.ts +53 -0
  125. package/src/sync/sync-inspection.ts +51 -0
  126. package/src/sync/sync-loaders.ts +54 -0
  127. package/src/{sync-operations.ts → sync/sync-mutations.ts} +34 -325
  128. package/src/sync/sync-operations.ts +12 -0
  129. package/src/{sync-policy.ts → sync/sync-policy.ts} +2 -2
  130. package/src/sync/sync-queries.ts +235 -0
  131. package/src/{sync-state.ts → sync/sync-state.ts} +5 -4
  132. package/src/sync-extension.ts +64 -708
  133. package/src/sync.ts +8 -8
  134. package/src/types.ts +47 -286
  135. package/src/ui/automatic-sync-summary.ts +6 -0
  136. package/src/{cancellable-operation.ts → ui/cancellable-operation.ts} +4 -4
  137. package/src/{file-selection.ts → ui/file-selection.ts} +5 -3
  138. package/src/{manager-attention.ts → ui/manager-attention.ts} +5 -1
  139. package/src/{manager-recovery.ts → ui/manager-recovery.ts} +6 -2
  140. package/src/{manager-state.ts → ui/manager-state.ts} +35 -14
  141. package/src/ui/manager-ui.ts +386 -0
  142. package/src/{remote-selection-ui.ts → ui/remote-selection-ui.ts} +21 -13
  143. package/src/{secret-input.ts → ui/secret-input.ts} +22 -4
  144. package/src/{settings-ui.ts → ui/settings-ui.ts} +17 -13
  145. package/src/ui/setup/git-ui.ts +293 -0
  146. package/src/{s3-credentials-ui.ts → ui/setup/s3-credentials-ui.ts} +13 -21
  147. package/src/ui/setup/s3-ui.ts +217 -0
  148. package/src/ui/setup/setup-actions.ts +127 -0
  149. package/src/ui/setup/setup-location-ui.ts +167 -0
  150. package/src/ui/setup/setup-name-ui.ts +34 -0
  151. package/src/ui/setup/setup-prompts.ts +92 -0
  152. package/src/ui/setup/setup-review.ts +70 -0
  153. package/src/ui/setup/setup-switcher.ts +181 -0
  154. package/src/ui/setup/setup-wizard.ts +39 -0
  155. package/src/ui/setup/text-input.ts +78 -0
  156. package/src/ui/setup/webdav-ui.ts +330 -0
  157. package/src/{storage-connections-ui.ts → ui/storage-connections-ui.ts} +99 -69
  158. package/src/{sync-attention.ts → ui/sync-attention.ts} +75 -6
  159. package/src/{sync-format.ts → ui/sync-format.ts} +7 -13
  160. package/src/{sync-resolution-ui.ts → ui/sync-resolution-ui.ts} +4 -3
  161. package/src/{sync-setups-ui.ts → ui/sync-setups-ui.ts} +23 -10
  162. package/src/ui/terminal-text.ts +4 -0
  163. package/dist/chunks/chunk-44LPGQTI.ts.map +0 -7
  164. package/dist/chunks/chunk-4U6AFLJB.ts.map +0 -7
  165. package/dist/chunks/chunk-5LZALPCD.ts.map +0 -7
  166. package/dist/chunks/chunk-5MQ76BK5.ts.map +0 -7
  167. package/dist/chunks/chunk-5T442OP3.ts.map +0 -7
  168. package/dist/chunks/chunk-ARN2672F.ts.map +0 -7
  169. package/dist/chunks/chunk-C7LXZ3UH.ts +0 -167
  170. package/dist/chunks/chunk-C7LXZ3UH.ts.map +0 -7
  171. package/dist/chunks/chunk-DFXBKHGN.ts.map +0 -7
  172. package/dist/chunks/chunk-E4COSV32.ts +0 -82
  173. package/dist/chunks/chunk-E4COSV32.ts.map +0 -7
  174. package/dist/chunks/chunk-F5QL2GPY.ts.map +0 -7
  175. package/dist/chunks/chunk-GLQLN5GV.ts.map +0 -7
  176. package/dist/chunks/chunk-HGV24P4T.ts.map +0 -7
  177. package/dist/chunks/chunk-HVUSHMVL.ts.map +0 -7
  178. package/dist/chunks/chunk-JF6MZCT4.ts.map +0 -7
  179. package/dist/chunks/chunk-WSOBYHIZ.ts.map +0 -7
  180. package/dist/chunks/chunk-X7SQ2EQM.ts.map +0 -7
  181. package/dist/chunks/chunk-YQ6UW7IF.ts.map +0 -7
  182. package/dist/chunks/file-selection-RKEHALNQ.ts.map +0 -7
  183. package/dist/chunks/git-backend-E3UOUUOM.ts.map +0 -7
  184. package/dist/chunks/manager-result-dispatcher-LWPYJAD5.ts +0 -18
  185. package/dist/chunks/manager-ui-NF4RUHBY.ts +0 -2785
  186. package/dist/chunks/manager-ui-NF4RUHBY.ts.map +0 -7
  187. package/dist/chunks/remote-selection-ui-NUF5P4ZJ.ts +0 -17
  188. package/dist/chunks/s3-backend-552LXHE4.ts.map +0 -7
  189. package/dist/chunks/sync-operations-3LLIHWZO.ts.map +0 -7
  190. package/dist/chunks/webdav-backend-ZD5RHRIU.ts.map +0 -7
  191. package/src/config.ts +0 -923
  192. package/src/git-ui.ts +0 -307
  193. package/src/manager-helpers.ts +0 -64
  194. package/src/manager-ui.ts +0 -997
  195. package/src/webdav-ui.ts +0 -421
  196. /package/dist/chunks/{manager-result-dispatcher-LWPYJAD5.ts.map → manager-result-dispatcher-U23ODD32.ts.map} +0 -0
  197. /package/dist/chunks/{remote-selection-ui-NUF5P4ZJ.ts.map → remote-selection-ui-ZE3TY67S.ts.map} +0 -0
  198. /package/dist/chunks/{setup-switch-5YDG5YGJ.ts.map → setup-switch-IS2PEZ3J.ts.map} +0 -0
  199. /package/dist/chunks/{snapshot-2RYBUDRA.ts.map → snapshot-HKEWCVK6.ts.map} +0 -0
  200. /package/dist/chunks/{sync-state-SRN6YRBK.ts.map → sync-inspection-FEP4L5TR.ts.map} +0 -0
  201. /package/src/{git-runner.ts → backends/git/git-runner.ts} +0 -0
  202. /package/src/{config-errors.ts → settings/config-errors.ts} +0 -0
  203. /package/src/{config-file.ts → settings/config-file.ts} +0 -0
  204. /package/src/{snapshot-paths.ts → snapshot/snapshot-paths.ts} +0 -0
  205. /package/src/{lock-policy.ts → state/lock-policy.ts} +0 -0
  206. /package/src/{lockfile-fs.ts → state/lockfile-fs.ts} +0 -0
  207. /package/src/{state-directory.ts → state/state-directory.ts} +0 -0
  208. /package/src/{sync-errors.ts → sync/sync-errors.ts} +0 -0
  209. /package/src/{manager-result-dispatcher.ts → ui/manager-result-dispatcher.ts} +0 -0
@@ -0,0 +1,51 @@
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
+ stateDir
5
+ } from "./chunk-ZI5MXMEX.ts";
6
+ import {
7
+ backendIdentityCoordinates
8
+ } from "./chunk-6LP3MCR2.ts";
9
+ import {
10
+ readJsonIfExists,
11
+ writeJson
12
+ } from "./chunk-T3HH3UEJ.ts";
13
+
14
+ // src/state/sync-state-store.ts
15
+ import { createHash } from "node:crypto";
16
+ import fs from "node:fs/promises";
17
+ import path from "node:path";
18
+ var STATE_VERSION = 2;
19
+ function syncStateFingerprint(state) {
20
+ return createHash("sha256").update(JSON.stringify(state)).digest("hex");
21
+ }
22
+ async function readStateForConfig(config) {
23
+ return await readJsonIfExists(statePathForConfig(config)) ?? {
24
+ version: STATE_VERSION,
25
+ profile: config.snapshotIdentity,
26
+ lastFileHashes: {}
27
+ };
28
+ }
29
+ async function writeStateForConfig(config, state) {
30
+ await writeJson(statePathForConfig(config), state);
31
+ }
32
+ function statePathForConfig(config) {
33
+ const identity = backendIdentityCoordinates(config);
34
+ const hash = createHash("sha256").update(identity).digest("hex").slice(0, 16);
35
+ return path.join(stateDir(), "setups", `${config.backend.type}-${hash}.state.json`);
36
+ }
37
+ function lockPath() {
38
+ return path.join(stateDir(), "lock");
39
+ }
40
+ async function ensureStateDir() {
41
+ await fs.mkdir(stateDir(), { recursive: true });
42
+ }
43
+
44
+ export {
45
+ syncStateFingerprint,
46
+ readStateForConfig,
47
+ writeStateForConfig,
48
+ lockPath,
49
+ ensureStateDir
50
+ };
51
+ //# sourceMappingURL=chunk-JSYMGJQQ.ts.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/state/sync-state-store.ts"],
4
+ "sourcesContent": ["import { createHash } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { backendIdentityCoordinates } from \"../backends/backend-identity.js\";\nimport { safeName } from \"../paths.js\";\nimport type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport { readJsonIfExists, writeJson } from \"./json-file.js\";\nimport { stateDir } from \"./state-directory.js\";\nimport type { SyncState } from \"./state-types.js\";\n\nconst STATE_VERSION = 2;\n\n/** Bounded observation token; do not retain the full baseline in passive UI state. */\nexport function syncStateFingerprint(state: SyncState) {\n\treturn createHash(\"sha256\").update(JSON.stringify(state)).digest(\"hex\");\n}\n\nexport async function readState(profile: string): Promise<SyncState> {\n\treturn (\n\t\t(await readJsonIfExists<SyncState>(statePath(profile))) ?? {\n\t\t\tversion: STATE_VERSION,\n\t\t\tprofile,\n\t\t\tlastFileHashes: {},\n\t\t}\n\t);\n}\n\nexport async function writeState(profile: string, state: SyncState) {\n\tawait writeJson(statePath(profile), state);\n}\n\nexport async function readStateForConfig(config: AnySyncConfig): Promise<SyncState> {\n\treturn (\n\t\t(await readJsonIfExists<SyncState>(statePathForConfig(config))) ?? {\n\t\t\tversion: STATE_VERSION,\n\t\t\tprofile: config.snapshotIdentity,\n\t\t\tlastFileHashes: {},\n\t\t}\n\t);\n}\n\nexport async function writeStateForConfig(config: AnySyncConfig, state: SyncState) {\n\tawait writeJson(statePathForConfig(config), state);\n}\n\nexport function statePathForConfig(config: AnySyncConfig) {\n\tconst identity = backendIdentityCoordinates(config);\n\tconst hash = createHash(\"sha256\").update(identity).digest(\"hex\").slice(0, 16);\n\treturn path.join(stateDir(), \"setups\", `${config.backend.type}-${hash}.state.json`);\n}\n\nfunction statePath(profile: string) {\n\treturn path.join(stateDir(), `${safeName(profile)}.state.json`);\n}\n\nexport function lockPath() {\n\treturn path.join(stateDir(), \"lock\");\n}\n\nexport async function ensureStateDir() {\n\tawait fs.mkdir(stateDir(), { recursive: true });\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;AAAA,SAAS,kBAAkB;AAC3B,OAAO,QAAQ;AACf,OAAO,UAAU;AAQjB,IAAM,gBAAgB;AAGf,SAAS,qBAAqB,OAAkB;AACtD,SAAO,WAAW,QAAQ,EAAE,OAAO,KAAK,UAAU,KAAK,CAAC,EAAE,OAAO,KAAK;AACvE;AAgBA,eAAsB,mBAAmB,QAA2C;AACnF,SACE,MAAM,iBAA4B,mBAAmB,MAAM,CAAC,KAAM;AAAA,IAClE,SAAS;AAAA,IACT,SAAS,OAAO;AAAA,IAChB,gBAAgB,CAAC;AAAA,EAClB;AAEF;AAEA,eAAsB,oBAAoB,QAAuB,OAAkB;AAClF,QAAM,UAAU,mBAAmB,MAAM,GAAG,KAAK;AAClD;AAEO,SAAS,mBAAmB,QAAuB;AACzD,QAAM,WAAW,2BAA2B,MAAM;AAClD,QAAM,OAAO,WAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AAC5E,SAAO,KAAK,KAAK,SAAS,GAAG,UAAU,GAAG,OAAO,QAAQ,IAAI,IAAI,IAAI,aAAa;AACnF;AAMO,SAAS,WAAW;AAC1B,SAAO,KAAK,KAAK,SAAS,GAAG,MAAM;AACpC;AAEA,eAAsB,iBAAiB;AACtC,QAAM,GAAG,MAAM,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;AAC/C;",
6
+ "names": []
7
+ }
@@ -0,0 +1,25 @@
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/backends/backend-factory.ts
5
+ var createSyncBackend = async (config) => {
6
+ switch (config.backend.type) {
7
+ case "s3": {
8
+ const { S3SyncBackend } = await import("./s3-backend-3P33LQHU.ts");
9
+ return new S3SyncBackend(config.backend);
10
+ }
11
+ case "webdav": {
12
+ const { WebDavSyncBackend } = await import("./webdav-backend-ECIKD7SO.ts");
13
+ return new WebDavSyncBackend(config.backend);
14
+ }
15
+ case "git": {
16
+ const { GitSyncBackend } = await import("./git-backend-OQW46G2X.ts");
17
+ return new GitSyncBackend(config.backend);
18
+ }
19
+ }
20
+ };
21
+
22
+ export {
23
+ createSyncBackend
24
+ };
25
+ //# sourceMappingURL=chunk-L7TBO32M.ts.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/backends/backend-factory.ts"],
4
+ "sourcesContent": ["import type { AnySyncConfig } from \"../settings/settings-types.js\";\nimport type { SyncBackend } from \"./sync-backend.js\";\n\nexport type SyncBackendFactory = {\n\tbivarianceHack(config: AnySyncConfig): SyncBackend | Promise<SyncBackend>;\n}[\"bivarianceHack\"];\n\nexport const createSyncBackend: SyncBackendFactory = async (config) => {\n\tswitch (config.backend.type) {\n\t\tcase \"s3\": {\n\t\t\tconst { S3SyncBackend } = await import(\"./s3/s3-backend.js\");\n\t\t\treturn new S3SyncBackend(config.backend);\n\t\t}\n\t\tcase \"webdav\": {\n\t\t\tconst { WebDavSyncBackend } = await import(\"./webdav/webdav-backend.js\");\n\t\t\treturn new WebDavSyncBackend(config.backend);\n\t\t}\n\t\tcase \"git\": {\n\t\t\tconst { GitSyncBackend } = await import(\"./git/git-backend.js\");\n\t\t\treturn new GitSyncBackend(config.backend);\n\t\t}\n\t}\n};\n"],
5
+ "mappings": ";;;;AAOO,IAAM,oBAAwC,OAAO,WAAW;AACtE,UAAQ,OAAO,QAAQ,MAAM;AAAA,IAC5B,KAAK,MAAM;AACV,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,0BAAoB;AAC3D,aAAO,IAAI,cAAc,OAAO,OAAO;AAAA,IACxC;AAAA,IACA,KAAK,UAAU;AACd,YAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,8BAA4B;AACvE,aAAO,IAAI,kBAAkB,OAAO,OAAO;AAAA,IAC5C;AAAA,IACA,KAAK,OAAO;AACX,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,2BAAsB;AAC9D,aAAO,IAAI,eAAe,OAAO,OAAO;AAAA,IACzC;AAAA,EACD;AACD;",
6
+ "names": []
7
+ }
@@ -6,12 +6,13 @@ import {
6
6
  syncSetupStorageReview,
7
7
  updateLocalConfig,
8
8
  validateConfigName
9
- } from "./chunk-5T442OP3.ts";
9
+ } from "./chunk-C7XY5NF5.ts";
10
10
  import {
11
11
  normalizeSyncInclude
12
- } from "./chunk-YQ6UW7IF.ts";
12
+ } from "./chunk-JAAKLL6M.ts";
13
13
 
14
- // src/settings-management.ts
14
+ // src/settings/settings-management.ts
15
+ import { isDeepStrictEqual } from "node:util";
15
16
  var SyncSetupReviewChangedError = class extends Error {
16
17
  constructor(message) {
17
18
  super(message);
@@ -34,13 +35,12 @@ async function saveNewV3Settings(input, signal) {
34
35
  }
35
36
  }
36
37
  };
37
- await updateLocalConfig((current) => {
38
+ return updateLocalConfig((current) => {
38
39
  if (Object.keys(current.storageConnections).length || Object.keys(current.syncSetups).length) {
39
40
  throw new Error(`Settings already exist: ${localConfigPath()}`);
40
41
  }
41
- return settings;
42
+ return { ...current, ...settings };
42
43
  }, signal);
43
- return settings;
44
44
  }
45
45
  async function addStorageConnection(name, connection, signal) {
46
46
  validateConfigName(name, "storage connection");
@@ -74,7 +74,7 @@ async function updateStorageConnection(name, update, expectedSetups, signal) {
74
74
  return { ...settings, storageConnections: nextConnections };
75
75
  }, signal);
76
76
  }
77
- async function addSyncSetup(name, setup, signal) {
77
+ async function addSyncSetup(name, setup, signal, expectedConnection) {
78
78
  validateConfigName(name, "sync setup");
79
79
  await updateSettings((settings) => {
80
80
  if (Object.hasOwn(settings.syncSetups, name))
@@ -82,6 +82,11 @@ async function addSyncSetup(name, setup, signal) {
82
82
  if (!Object.hasOwn(settings.storageConnections, setup.storage.connection)) {
83
83
  throw new Error(`Storage connection not found: ${setup.storage.connection}`);
84
84
  }
85
+ if (expectedConnection && !isDeepStrictEqual(settings.storageConnections[setup.storage.connection], expectedConnection)) {
86
+ throw new SyncSetupReviewChangedError(
87
+ "Storage connection changed while the setup review was open; reopen it."
88
+ );
89
+ }
85
90
  const nextSetups = { ...settings.syncSetups, [name]: structuredClone(setup) };
86
91
  assertUniqueLocations(nextSetups, settings.storageConnections);
87
92
  return {
@@ -113,6 +118,14 @@ async function updateSyncSetup(name, update, options = {}) {
113
118
  );
114
119
  }
115
120
  }
121
+ if (options.expectedConnection && !isDeepStrictEqual(
122
+ settings.storageConnections[setup.storage.connection],
123
+ options.expectedConnection
124
+ )) {
125
+ throw new SyncSetupReviewChangedError(
126
+ "Storage connection changed while the setup review was open; reopen it."
127
+ );
128
+ }
116
129
  const nextSetup = update(structuredClone(setup));
117
130
  if (!Object.hasOwn(settings.storageConnections, nextSetup.storage.connection)) {
118
131
  throw new Error(`Storage connection not found: ${nextSetup.storage.connection}`);
@@ -193,4 +206,4 @@ export {
193
206
  removeSyncSetup,
194
207
  removeStorageConnection
195
208
  };
196
- //# sourceMappingURL=chunk-DFXBKHGN.ts.map
209
+ //# sourceMappingURL=chunk-LCRI3ABW.ts.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/settings/settings-management.ts"],
4
+ "sourcesContent": ["import { isDeepStrictEqual } from \"node:util\";\nimport { normalizeSyncInclude } from \"../sync/sync-policy.js\";\nimport { type SyncSetupStorageReview, syncSetupStorageReview } from \"./config.js\";\nimport { localConfigPath } from \"./config-file.js\";\nimport { updateLocalConfig } from \"./settings-store.js\";\nimport type {\n\tPiSyncSettingsV3,\n\tStorageConnectionSettings,\n\tSyncSetupSettings,\n} from \"./settings-types.js\";\nimport { effectiveSyncSetupRemoteIdentity, validateConfigName } from \"./settings-validation.js\";\n\nexport class SyncSetupReviewChangedError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"SyncSetupReviewChangedError\";\n\t}\n}\n\nexport async function saveNewV3Settings(\n\tinput: {\n\t\tsetupName: string;\n\t\tconnectionName: string;\n\t\tconnection: StorageConnectionSettings;\n\t\tsetup: SyncSetupSettings;\n\t},\n\tsignal?: AbortSignal,\n) {\n\tvalidateConfigName(input.setupName, \"sync setup\");\n\tvalidateConfigName(input.connectionName, \"storage connection\");\n\tconst settings: PiSyncSettingsV3 = {\n\t\tversion: 3,\n\t\tactiveSyncSetup: input.setupName,\n\t\tonSwitch: \"ask-before-pull\",\n\t\tskipSecretScan: false,\n\t\tstorageConnections: { [input.connectionName]: structuredClone(input.connection) },\n\t\tsyncSetups: {\n\t\t\t[input.setupName]: {\n\t\t\t\t...structuredClone(input.setup),\n\t\t\t\tstorage: { ...input.setup.storage, connection: input.connectionName },\n\t\t\t},\n\t\t},\n\t};\n\treturn updateLocalConfig((current) => {\n\t\tif (Object.keys(current.storageConnections).length || Object.keys(current.syncSetups).length) {\n\t\t\tthrow new Error(`Settings already exist: ${localConfigPath()}`);\n\t\t}\n\t\treturn { ...current, ...settings };\n\t}, signal);\n}\n\nexport async function addStorageConnection(\n\tname: string,\n\tconnection: StorageConnectionSettings,\n\tsignal?: AbortSignal,\n) {\n\tvalidateConfigName(name, \"storage connection\");\n\tawait updateSettings((settings) => {\n\t\tif (Object.hasOwn(settings.storageConnections, name)) {\n\t\t\tthrow new Error(`Storage connection already exists: ${name}`);\n\t\t}\n\t\treturn {\n\t\t\t...settings,\n\t\t\tstorageConnections: {\n\t\t\t\t...settings.storageConnections,\n\t\t\t\t[name]: structuredClone(connection),\n\t\t\t},\n\t\t};\n\t}, signal);\n}\n\nexport async function updateStorageConnection(\n\tname: string,\n\tupdate: (connection: StorageConnectionSettings) => StorageConnectionSettings,\n\texpectedSetups?: readonly string[],\n\tsignal?: AbortSignal,\n) {\n\tvalidateConfigName(name, \"storage connection\");\n\tawait updateSettings((settings) => {\n\t\tconst connection = settings.storageConnections[name];\n\t\tif (!connection) throw new Error(`Storage connection not found: ${name}`);\n\t\tconst currentSetups = referencingSetupNames(settings.syncSetups, name);\n\t\tif (expectedSetups && !sameNames(currentSetups, expectedSetups)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Storage connection \u201C${name}\u201D usage changed while it was open; reopen it and review the affected sync setups.`,\n\t\t\t);\n\t\t}\n\t\tconst nextConnection = update(structuredClone(connection));\n\t\tconst nextConnections = { ...settings.storageConnections, [name]: nextConnection };\n\t\tassertUniqueLocations(settings.syncSetups, nextConnections);\n\t\treturn { ...settings, storageConnections: nextConnections };\n\t}, signal);\n}\n\nexport async function addSyncSetup(\n\tname: string,\n\tsetup: SyncSetupSettings,\n\tsignal?: AbortSignal,\n\texpectedConnection?: StorageConnectionSettings,\n) {\n\tvalidateConfigName(name, \"sync setup\");\n\tawait updateSettings((settings) => {\n\t\tif (Object.hasOwn(settings.syncSetups, name))\n\t\t\tthrow new Error(`Sync setup already exists: ${name}`);\n\t\tif (!Object.hasOwn(settings.storageConnections, setup.storage.connection)) {\n\t\t\tthrow new Error(`Storage connection not found: ${setup.storage.connection}`);\n\t\t}\n\t\tif (\n\t\t\texpectedConnection &&\n\t\t\t!isDeepStrictEqual(settings.storageConnections[setup.storage.connection], expectedConnection)\n\t\t) {\n\t\t\tthrow new SyncSetupReviewChangedError(\n\t\t\t\t\"Storage connection changed while the setup review was open; reopen it.\",\n\t\t\t);\n\t\t}\n\t\tconst nextSetups = { ...settings.syncSetups, [name]: structuredClone(setup) };\n\t\tassertUniqueLocations(nextSetups, settings.storageConnections);\n\t\treturn {\n\t\t\t...settings,\n\t\t\tsyncSetups: nextSetups,\n\t\t\t...(settings.activeSyncSetup ? {} : { activeSyncSetup: name }),\n\t\t};\n\t}, signal);\n}\n\nexport async function updateSyncSetup(\n\tname: string,\n\tupdate: (setup: SyncSetupSettings) => SyncSetupSettings,\n\toptions: {\n\t\texpectedStorage?: SyncSetupStorageReview;\n\t\texpectedInclude?: readonly string[];\n\t\texpectedConnection?: StorageConnectionSettings;\n\t\tsignal?: AbortSignal;\n\t} = {},\n) {\n\tvalidateConfigName(name, \"sync setup\");\n\tawait updateSettings((settings) => {\n\t\tconst setup = settings.syncSetups[name];\n\t\tif (!setup) throw new Error(`Sync setup not found: ${name}`);\n\t\tif (\n\t\t\toptions.expectedInclude &&\n\t\t\t!sameNames(normalizeSyncInclude(setup.sync.include), options.expectedInclude)\n\t\t) {\n\t\t\tthrow new SyncSetupReviewChangedError(\n\t\t\t\t`Sync setup \u201C${name}\u201D included content changed while it was open; reopen it and review the current selection.`,\n\t\t\t);\n\t\t}\n\t\tif (options.expectedStorage) {\n\t\t\tconst connectionName = setup.storage.connection;\n\t\t\tconst connection = settings.storageConnections[connectionName];\n\t\t\tif (\n\t\t\t\t!connection ||\n\t\t\t\t!sameStorageReview(\n\t\t\t\t\tsyncSetupStorageReview(name, setup, connectionName, connection),\n\t\t\t\t\toptions.expectedStorage,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthrow new SyncSetupReviewChangedError(\n\t\t\t\t\t`Sync setup \u201C${name}\u201D storage changed while it was open; reopen it and review the current storage location.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (\n\t\t\toptions.expectedConnection &&\n\t\t\t!isDeepStrictEqual(\n\t\t\t\tsettings.storageConnections[setup.storage.connection],\n\t\t\t\toptions.expectedConnection,\n\t\t\t)\n\t\t) {\n\t\t\tthrow new SyncSetupReviewChangedError(\n\t\t\t\t\"Storage connection changed while the setup review was open; reopen it.\",\n\t\t\t);\n\t\t}\n\t\tconst nextSetup = update(structuredClone(setup));\n\t\tif (!Object.hasOwn(settings.storageConnections, nextSetup.storage.connection)) {\n\t\t\tthrow new Error(`Storage connection not found: ${nextSetup.storage.connection}`);\n\t\t}\n\t\tconst nextSetups = { ...settings.syncSetups, [name]: nextSetup };\n\t\tassertUniqueLocations(nextSetups, settings.storageConnections);\n\t\treturn { ...settings, syncSetups: nextSetups };\n\t}, options.signal);\n}\n\nexport async function removeSyncSetup(name: string, signal?: AbortSignal) {\n\tvalidateConfigName(name, \"sync setup\");\n\tawait updateSettings((settings) => {\n\t\tif (!Object.hasOwn(settings.syncSetups, name)) throw new Error(`Sync setup not found: ${name}`);\n\t\tconst isCurrent = settings.activeSyncSetup === name;\n\t\tif (isCurrent && Object.keys(settings.syncSetups).length > 1) {\n\t\t\tthrow new Error(\"Switch to another sync setup before removing the current setup.\");\n\t\t}\n\t\tconst syncSetups = { ...settings.syncSetups };\n\t\tdelete syncSetups[name];\n\t\tconst next = { ...settings, syncSetups };\n\t\tif (isCurrent) delete next.activeSyncSetup;\n\t\treturn next;\n\t}, signal);\n}\n\nexport async function removeStorageConnection(name: string, signal?: AbortSignal) {\n\tvalidateConfigName(name, \"storage connection\");\n\tawait updateSettings((settings) => {\n\t\tconst referenced = referencingSetupNames(settings.syncSetups, name)[0];\n\t\tif (referenced) {\n\t\t\tthrow new Error(`Storage connection \u201C${name}\u201D is used by sync setup \u201C${referenced}\u201D.`);\n\t\t}\n\t\tif (!Object.hasOwn(settings.storageConnections, name)) {\n\t\t\tthrow new Error(`Storage connection not found: ${name}`);\n\t\t}\n\t\tconst storageConnections = { ...settings.storageConnections };\n\t\tdelete storageConnections[name];\n\t\treturn { ...settings, storageConnections };\n\t}, signal);\n}\n\nasync function updateSettings(\n\tupdate: (settings: PiSyncSettingsV3) => PiSyncSettingsV3,\n\tsignal?: AbortSignal,\n) {\n\treturn updateLocalConfig((settings) => {\n\t\tif (settings.version !== 3) {\n\t\t\tthrow new Error(\"Storage connections and sync setups require version 3 pi-sync settings.\");\n\t\t}\n\t\treturn update(settings);\n\t}, signal);\n}\n\nfunction referencingSetupNames(setups: Record<string, SyncSetupSettings>, connection: string) {\n\treturn Object.entries(setups)\n\t\t.filter(([, setup]) => setup.storage.connection === connection)\n\t\t.map(([name]) => name)\n\t\t.sort((left, right) => left.localeCompare(right));\n}\n\nfunction assertUniqueLocations(\n\tsetups: Record<string, SyncSetupSettings>,\n\tconnections: Record<string, StorageConnectionSettings>,\n) {\n\tconst identities = new Map<string, string>();\n\tfor (const [name, setup] of Object.entries(setups)) {\n\t\tconst connection = connections[setup.storage.connection];\n\t\tif (!connection) throw new Error(`Storage connection not found: ${setup.storage.connection}`);\n\t\tconst identity = effectiveSyncSetupRemoteIdentity(setup, connection);\n\t\tconst previous = identities.get(identity);\n\t\tif (previous) {\n\t\t\tthrow new Error(`Sync setup \u201C${name}\u201D duplicates the storage location of \u201C${previous}\u201D.`);\n\t\t}\n\t\tidentities.set(identity, name);\n\t}\n}\n\nfunction sameNames(left: readonly string[], right: readonly string[]) {\n\treturn left.length === right.length && left.every((name, index) => name === right[index]);\n}\n\nfunction sameStorageReview(left: SyncSetupStorageReview, right: SyncSetupStorageReview) {\n\treturn (\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);\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/terminal-text.ts
5
+ function safeTerminalText(value) {
6
+ return value.replace(/[\u0000-\u001f\u007f-\u009f]/gu, "?");
7
+ }
8
+
9
+ export {
10
+ safeTerminalText
11
+ };
12
+ //# sourceMappingURL=chunk-LTBWGSBV.ts.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/ui/terminal-text.ts"],
4
+ "sourcesContent": ["export function safeTerminalText(value: string) {\n\t// biome-ignore lint/suspicious/noControlCharactersInRegex: Escape untrusted terminal controls.\n\treturn value.replace(/[\\u0000-\\u001f\\u007f-\\u009f]/gu, \"?\");\n}\n"],
5
+ "mappings": ";;;;AAAO,SAAS,iBAAiB,OAAe;AAE/C,SAAO,MAAM,QAAQ,kCAAkC,GAAG;AAC3D;",
6
+ "names": []
7
+ }
@@ -0,0 +1,17 @@
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/sync/signals.ts
5
+ function throwIfAborted(signal) {
6
+ if (!signal?.aborted) return;
7
+ throw signal.reason instanceof Error ? signal.reason : new DOMException("The operation was aborted", "AbortError");
8
+ }
9
+ function combineSignals(primary, secondary) {
10
+ return secondary ? AbortSignal.any([primary, secondary]) : primary;
11
+ }
12
+
13
+ export {
14
+ throwIfAborted,
15
+ combineSignals
16
+ };
17
+ //# sourceMappingURL=chunk-NJFUIVYL.ts.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/sync/signals.ts"],
4
+ "sourcesContent": ["export function 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\nexport function combineSignals(primary: AbortSignal, secondary?: AbortSignal) {\n\treturn secondary ? AbortSignal.any([primary, secondary]) : primary;\n}\n"],
5
+ "mappings": ";;;;AAAO,SAAS,eAAe,QAAsB;AACpD,MAAI,CAAC,QAAQ,QAAS;AACtB,QAAM,OAAO,kBAAkB,QAC5B,OAAO,SACP,IAAI,aAAa,6BAA6B,YAAY;AAC9D;AAEO,SAAS,eAAe,SAAsB,WAAyB;AAC7E,SAAO,YAAY,YAAY,IAAI,CAAC,SAAS,SAAS,CAAC,IAAI;AAC5D;",
6
+ "names": []
7
+ }
@@ -1,9 +1,12 @@
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
+ import {
4
+ sessionStorageRoot
5
+ } from "./chunk-THMF4BVL.ts";
3
6
  import {
4
7
  agentDir,
5
8
  configuredSessionDir
6
- } from "./chunk-5T442OP3.ts";
9
+ } from "./chunk-T3HH3UEJ.ts";
7
10
  import {
8
11
  DEFAULT_SYNC_INCLUDE,
9
12
  canonicalSnapshotPathForConfig,
@@ -20,26 +23,13 @@ import {
20
23
  snapshotSelectionInclude,
21
24
  syncIncludeSelection,
22
25
  toPosix
23
- } from "./chunk-YQ6UW7IF.ts";
26
+ } from "./chunk-JAAKLL6M.ts";
24
27
 
25
- // src/snapshot.ts
28
+ // src/snapshot/snapshot.ts
26
29
  import { createHash, randomUUID } from "node:crypto";
27
30
  import fs from "node:fs/promises";
28
31
  import os from "node:os";
29
- import path2 from "node:path";
30
-
31
- // src/snapshot-paths.ts
32
32
  import path from "node:path";
33
- function expandHome(value) {
34
- if (value === "~") return process.env.HOME ?? value;
35
- if (value.startsWith("~/")) return path.join(process.env.HOME ?? "~", value.slice(2));
36
- return value;
37
- }
38
- function sessionStorageRoot(root, configuredSessionDir2) {
39
- return configuredSessionDir2 ? path.resolve(expandHome(configuredSessionDir2)) : path.resolve(root, "sessions");
40
- }
41
-
42
- // src/snapshot.ts
43
33
  var VERSION = 1;
44
34
  var TOP_LEVEL_FILES = DEFAULT_SYNC_INCLUDE.filter(
45
35
  (name) => name.includes(".")
@@ -64,7 +54,7 @@ function sha256(value) {
64
54
  function isSafeSnapshotPath(relativePath) {
65
55
  if (relativePath.includes("\\")) return false;
66
56
  const normalized = toPosix(relativePath);
67
- return Boolean(normalized) && normalized !== "." && normalized !== ".." && !normalized.startsWith("../") && !path2.posix.isAbsolute(normalized) && path2.posix.normalize(normalized) === normalized && !isDeniedPath(normalized);
57
+ return Boolean(normalized) && normalized !== "." && normalized !== ".." && !normalized.startsWith("../") && !path.posix.isAbsolute(normalized) && path.posix.normalize(normalized) === normalized && !isDeniedPath(normalized);
68
58
  }
69
59
  function snapshotsMatch(left, right) {
70
60
  const leftHashes = new Map(left.files.map((file) => [file.path, file.sha256]));
@@ -83,12 +73,13 @@ function regenerateSnapshotIdentity(snapshot) {
83
73
  };
84
74
  }
85
75
  async function createSnapshot(profile, options = {}) {
76
+ options.signal?.throwIfAborted();
86
77
  const include = effectiveInclude(options);
87
78
  const syncSessions = include.includes("sessions");
88
- const files = await collectFiles(agentDir(), {
89
- include,
90
- sessionDir: options.sessionDir ?? await configuredSessionDir()
91
- });
79
+ const sessionDir = options.sessionDir ?? await configuredSessionDir();
80
+ options.signal?.throwIfAborted();
81
+ const files = await collectFiles(agentDir(), { include, sessionDir, signal: options.signal });
82
+ options.signal?.throwIfAborted();
92
83
  return {
93
84
  version: VERSION,
94
85
  id: snapshotId(),
@@ -109,67 +100,79 @@ function effectiveInclude(options) {
109
100
  ];
110
101
  }
111
102
  async function collectFiles(root, options = {}) {
103
+ const signal = options.signal;
104
+ signal?.throwIfAborted();
112
105
  const results = [];
113
106
  const entries = await fs.readdir(root, { withFileTypes: true });
107
+ signal?.throwIfAborted();
114
108
  const selection = syncIncludeSelection(effectiveInclude(options));
115
109
  const selectedFiles = new Set(selection.builtIns);
116
110
  for (const entry of entries) {
117
111
  if (entry.isDirectory() && TOP_LEVEL_DIRS.has(entry.name) && selectedFiles.has(entry.name)) {
118
- await collectDirectory(results, root, entry.name);
112
+ await collectDirectory(results, root, entry.name, { signal });
119
113
  }
120
114
  }
121
115
  for (const fileName of TOP_LEVEL_FILES) {
122
116
  if (!selectedFiles.has(fileName)) continue;
123
117
  const entry = selectTopLevelFileEntry(entries, fileName);
124
- if (entry) await addFile(results, root, entry.name, fileName);
118
+ if (entry) await addFile(results, root, entry.name, fileName, signal);
125
119
  }
126
120
  for (const relativePath of selection.custom) {
127
- await collectIncludedPath(results, root, relativePath);
121
+ await collectIncludedPath(results, root, relativePath, signal);
128
122
  }
129
123
  if (selection.sessions) {
130
124
  try {
131
125
  await collectDirectory(results, sessionStorageRoot(root, options.sessionDir), "", {
132
126
  sessionsOnly: true,
133
- virtualPrefix: "sessions"
127
+ virtualPrefix: "sessions",
128
+ signal
134
129
  });
135
130
  } catch (error) {
136
131
  if (error.code !== "ENOENT") throw error;
137
132
  }
138
133
  }
134
+ signal?.throwIfAborted();
139
135
  return results.sort((left, right) => left.path.localeCompare(right.path));
140
136
  }
141
- async function collectIncludedPath(results, root, relativePath) {
137
+ async function collectIncludedPath(results, root, relativePath, signal) {
138
+ signal?.throwIfAborted();
142
139
  const absolutePath = safeJoin(root, relativePath);
143
140
  try {
144
141
  const stat = await fs.lstat(absolutePath);
145
- if (stat.isFile()) await addFile(results, root, relativePath);
146
- else if (stat.isDirectory()) await collectDirectory(results, root, relativePath);
142
+ signal?.throwIfAborted();
143
+ if (stat.isFile()) await addFile(results, root, relativePath, relativePath, signal);
144
+ else if (stat.isDirectory()) await collectDirectory(results, root, relativePath, { signal });
147
145
  } catch (error) {
148
146
  if (error.code !== "ENOENT") throw error;
149
147
  if (!relativePath.includes("/")) {
150
148
  const entries = await fs.readdir(root, { withFileTypes: true });
149
+ signal?.throwIfAborted();
151
150
  const entry = selectTopLevelFileEntry(entries, relativePath);
152
- if (entry) await addFile(results, root, entry.name, relativePath);
151
+ if (entry) await addFile(results, root, entry.name, relativePath, signal);
153
152
  }
154
153
  }
155
154
  }
156
155
  async function collectDirectory(results, root, relativeDirectory, options = {}) {
157
- const absoluteDirectory = path2.join(root, relativeDirectory);
156
+ options.signal?.throwIfAborted();
157
+ const absoluteDirectory = path.join(root, relativeDirectory);
158
158
  for (const entry of await fs.readdir(absoluteDirectory, { withFileTypes: true })) {
159
+ options.signal?.throwIfAborted();
159
160
  const relativePath = relativeDirectory ? posixJoin(relativeDirectory, entry.name) : entry.name;
160
161
  const snapshotPath = options.virtualPrefix ? posixJoin(options.virtualPrefix, relativePath) : relativePath;
161
162
  if (isDeniedPath(snapshotPath)) continue;
162
163
  if (entry.isDirectory()) {
163
164
  await collectDirectory(results, root, relativePath, options);
164
165
  } else if (entry.isFile() && (!options.sessionsOnly || isSessionFilePath(snapshotPath))) {
165
- await addFile(results, root, relativePath, snapshotPath);
166
+ await addFile(results, root, relativePath, snapshotPath, options.signal);
166
167
  }
167
168
  }
168
169
  }
169
- async function addFile(results, root, relativePath, snapshotPath = relativePath) {
170
+ async function addFile(results, root, relativePath, snapshotPath = relativePath, signal) {
171
+ signal?.throwIfAborted();
170
172
  if (!isSafeSnapshotPath(snapshotPath)) return;
171
173
  const absolutePath = safeJoin(root, relativePath);
172
- const content = await fs.readFile(absolutePath);
174
+ const content = await fs.readFile(absolutePath, { signal });
175
+ signal?.throwIfAborted();
173
176
  results.push({
174
177
  path: snapshotPath,
175
178
  contentBase64: content.toString("base64"),
@@ -185,9 +188,9 @@ function isSessionFilePath(relativePath) {
185
188
  }
186
189
  function sessionSnapshotPathFromAbsolute(sessionFile, configuredSessionDir2) {
187
190
  const relativePath = toPosix(
188
- path2.relative(sessionStorageRoot(agentDir(), configuredSessionDir2), sessionFile)
191
+ path.relative(sessionStorageRoot(agentDir(), configuredSessionDir2), sessionFile)
189
192
  );
190
- if (!relativePath || relativePath.startsWith("../") || path2.posix.isAbsolute(relativePath)) {
193
+ if (!relativePath || relativePath.startsWith("../") || path.posix.isAbsolute(relativePath)) {
191
194
  return void 0;
192
195
  }
193
196
  const snapshotPath = posixJoin("sessions", relativePath);
@@ -338,7 +341,6 @@ function sameOptionalInclude(left, right) {
338
341
  }
339
342
 
340
343
  export {
341
- sessionStorageRoot,
342
344
  regenerateSnapshotIdentity,
343
345
  createSnapshot,
344
346
  collectFiles,
@@ -353,4 +355,4 @@ export {
353
355
  mergeRemotePreservedFiles,
354
356
  mergeRemoteSessionFiles
355
357
  };
356
- //# sourceMappingURL=chunk-HVUSHMVL.ts.map
358
+ //# sourceMappingURL=chunk-OEX4ABY6.ts.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/snapshot/snapshot.ts"],
4
+ "sourcesContent": ["import { createHash, randomUUID } from \"node:crypto\";\nimport type { Dirent } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { isDeniedPath, posixJoin, safeJoin, toPosix } from \"../paths.js\";\nimport { agentDir, configuredSessionDir } from \"./session-paths.js\";\nimport { sessionStorageRoot } from \"./snapshot-paths.js\";\n\nexport { isDeniedPath } from \"../paths.js\";\nexport { sessionStorageRoot } from \"./snapshot-paths.js\";\n\nimport {\n\tcanonicalSnapshotPathForConfig,\n\tcustomIncludePathsByLower,\n\tDEFAULT_SYNC_INCLUDE,\n\tincludeFromSelectionConfig,\n\tisConfiguredSnapshotPath,\n\tisPreservableUnmanagedSnapshotPath,\n\tnormalizeExtraFiles,\n\tnormalizeSyncFiles,\n\ttype SyncSelectionConfig,\n\tselectionForSnapshot,\n\tsnapshotSelectionInclude,\n\tsyncIncludeSelection,\n} from \"../sync/sync-policy.js\";\nimport type { Snapshot, SnapshotFile, SnapshotOptions } from \"./snapshot-types.js\";\n\nexport { canonicalSnapshotPathForConfig, isConfiguredSnapshotPath } from \"../sync/sync-policy.js\";\n\nconst VERSION = 1;\nconst TOP_LEVEL_FILES: readonly string[] = DEFAULT_SYNC_INCLUDE.filter((name) =>\n\tname.includes(\".\"),\n);\nconst TOP_LEVEL_DIRS = new Set<string>(DEFAULT_SYNC_INCLUDE.filter((name) => !name.includes(\".\")));\nconst SECRET_PATTERNS = [\n\t/AWS_SECRET_ACCESS_KEY\\s*[=:]\\s*['\"]?[A-Za-z0-9/+]{35,}/i,\n\t/(ANTHROPIC|OPENAI|GEMINI|GOOGLE|FIRECRAWL|GITHUB|CLOUDFLARE|R2|S3)_[A-Z0-9_]*(KEY|TOKEN|SECRET)\\s*[=:]\\s*['\"]?[^\\s'\"]{12,}/i,\n\t/sk-ant-[A-Za-z0-9_-]{20,}/,\n\t/sk-[A-Za-z0-9]{20,}/,\n\t/gh[pousr]_[A-Za-z0-9_]{20,}/,\n];\n\nfunction selectTopLevelFileEntry(entries: Dirent[], fileName: string) {\n\tconst exact = entries.find((entry) => entry.isFile() && entry.name === fileName);\n\tif (exact) return exact;\n\tconst lower = fileName.toLowerCase();\n\treturn entries\n\t\t.filter((entry) => entry.isFile() && entry.name.toLowerCase() === lower)\n\t\t.sort((left, right) => left.name.localeCompare(right.name))[0];\n}\n\nfunction sha256(value: Buffer) {\n\treturn createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nfunction isSafeSnapshotPath(relativePath: string) {\n\tif (relativePath.includes(\"\\\\\")) return false;\n\tconst normalized = toPosix(relativePath);\n\treturn (\n\t\tBoolean(normalized) &&\n\t\tnormalized !== \".\" &&\n\t\tnormalized !== \"..\" &&\n\t\t!normalized.startsWith(\"../\") &&\n\t\t!path.posix.isAbsolute(normalized) &&\n\t\tpath.posix.normalize(normalized) === normalized &&\n\t\t!isDeniedPath(normalized)\n\t);\n}\n\nfunction snapshotsMatch(left: Snapshot, right: Snapshot) {\n\tconst leftHashes = new Map(left.files.map((file) => [file.path, file.sha256]));\n\tconst rightHashes = new Map(right.files.map((file) => [file.path, file.sha256]));\n\treturn (\n\t\tleft.syncSessions === right.syncSessions &&\n\t\tsameOptionalInclude(snapshotSelectionInclude(left), snapshotSelectionInclude(right)) &&\n\t\tleftHashes.size === rightHashes.size &&\n\t\t[...leftHashes].every(([filePath, hash]) => rightHashes.get(filePath) === hash)\n\t);\n}\n\nfunction snapshotId() {\n\treturn `${new Date().toISOString().replace(/[:.]/g, \"-\")}-${randomUUID().slice(0, 8)}`;\n}\n\nexport function regenerateSnapshotIdentity(snapshot: Snapshot): Snapshot {\n\treturn {\n\t\t...snapshot,\n\t\tid: snapshotId(),\n\t\tcreatedAt: new Date().toISOString(),\n\t\tmachine: os.hostname(),\n\t};\n}\n\nexport async function createSnapshot(\n\tprofile: string,\n\toptions: SnapshotOptions = {},\n): Promise<Snapshot> {\n\toptions.signal?.throwIfAborted();\n\tconst include = effectiveInclude(options);\n\tconst syncSessions = include.includes(\"sessions\");\n\tconst sessionDir = options.sessionDir ?? (await configuredSessionDir());\n\toptions.signal?.throwIfAborted();\n\tconst files = await collectFiles(agentDir(), { include, sessionDir, signal: options.signal });\n\toptions.signal?.throwIfAborted();\n\treturn {\n\t\tversion: VERSION,\n\t\tid: snapshotId(),\n\t\tcreatedAt: new Date().toISOString(),\n\t\tmachine: os.hostname(),\n\t\tprofile,\n\t\tsyncSessions,\n\t\tselection: selectionForSnapshot(include),\n\t\tfiles,\n\t};\n}\n\nfunction effectiveInclude(options: SnapshotOptions) {\n\tif (options.include) return options.include;\n\treturn [\n\t\t...normalizeSyncFiles(options.syncFiles),\n\t\t...normalizeExtraFiles(options.extraFiles),\n\t\t...(options.syncSessions ? [\"sessions\"] : []),\n\t];\n}\n\nexport async function collectFiles(\n\troot: string,\n\toptions: SnapshotOptions = {},\n): Promise<SnapshotFile[]> {\n\tconst signal = options.signal;\n\tsignal?.throwIfAborted();\n\tconst results: SnapshotFile[] = [];\n\tconst entries = await fs.readdir(root, { withFileTypes: true });\n\tsignal?.throwIfAborted();\n\tconst selection = syncIncludeSelection(effectiveInclude(options));\n\tconst selectedFiles = new Set<string>(selection.builtIns);\n\tfor (const entry of entries) {\n\t\tif (entry.isDirectory() && TOP_LEVEL_DIRS.has(entry.name) && selectedFiles.has(entry.name)) {\n\t\t\tawait collectDirectory(results, root, entry.name, { signal });\n\t\t}\n\t}\n\tfor (const fileName of TOP_LEVEL_FILES) {\n\t\tif (!selectedFiles.has(fileName)) continue;\n\t\tconst entry = selectTopLevelFileEntry(entries, fileName);\n\t\tif (entry) await addFile(results, root, entry.name, fileName, signal);\n\t}\n\tfor (const relativePath of selection.custom) {\n\t\tawait collectIncludedPath(results, root, relativePath, signal);\n\t}\n\tif (selection.sessions) {\n\t\ttry {\n\t\t\tawait collectDirectory(results, sessionStorageRoot(root, options.sessionDir), \"\", {\n\t\t\t\tsessionsOnly: true,\n\t\t\t\tvirtualPrefix: \"sessions\",\n\t\t\t\tsignal,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n\t\t}\n\t}\n\tsignal?.throwIfAborted();\n\treturn results.sort((left, right) => left.path.localeCompare(right.path));\n}\n\nasync function collectIncludedPath(\n\tresults: SnapshotFile[],\n\troot: string,\n\trelativePath: string,\n\tsignal?: AbortSignal,\n) {\n\tsignal?.throwIfAborted();\n\tconst absolutePath = safeJoin(root, relativePath);\n\ttry {\n\t\tconst stat = await fs.lstat(absolutePath);\n\t\tsignal?.throwIfAborted();\n\t\tif (stat.isFile()) await addFile(results, root, relativePath, relativePath, signal);\n\t\telse if (stat.isDirectory()) await collectDirectory(results, root, relativePath, { signal });\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n\t\tif (!relativePath.includes(\"/\")) {\n\t\t\tconst entries = await fs.readdir(root, { withFileTypes: true });\n\t\t\tsignal?.throwIfAborted();\n\t\t\tconst entry = selectTopLevelFileEntry(entries, relativePath);\n\t\t\tif (entry) await addFile(results, root, entry.name, relativePath, signal);\n\t\t}\n\t}\n}\n\nasync function collectDirectory(\n\tresults: SnapshotFile[],\n\troot: string,\n\trelativeDirectory: string,\n\toptions: { sessionsOnly?: boolean; virtualPrefix?: string; signal?: AbortSignal } = {},\n) {\n\toptions.signal?.throwIfAborted();\n\tconst absoluteDirectory = path.join(root, relativeDirectory);\n\tfor (const entry of await fs.readdir(absoluteDirectory, { withFileTypes: true })) {\n\t\toptions.signal?.throwIfAborted();\n\t\tconst relativePath = relativeDirectory ? posixJoin(relativeDirectory, entry.name) : entry.name;\n\t\tconst snapshotPath = options.virtualPrefix\n\t\t\t? posixJoin(options.virtualPrefix, relativePath)\n\t\t\t: relativePath;\n\t\tif (isDeniedPath(snapshotPath)) continue;\n\t\tif (entry.isDirectory()) {\n\t\t\tawait collectDirectory(results, root, relativePath, options);\n\t\t} else if (entry.isFile() && (!options.sessionsOnly || isSessionFilePath(snapshotPath))) {\n\t\t\tawait addFile(results, root, relativePath, snapshotPath, options.signal);\n\t\t}\n\t}\n}\n\nasync function addFile(\n\tresults: SnapshotFile[],\n\troot: string,\n\trelativePath: string,\n\tsnapshotPath = relativePath,\n\tsignal?: AbortSignal,\n) {\n\tsignal?.throwIfAborted();\n\tif (!isSafeSnapshotPath(snapshotPath)) return;\n\tconst absolutePath = safeJoin(root, relativePath);\n\tconst content = await fs.readFile(absolutePath, { signal });\n\tsignal?.throwIfAborted();\n\tresults.push({\n\t\tpath: snapshotPath,\n\t\tcontentBase64: content.toString(\"base64\"),\n\t\tsha256: sha256(content),\n\t});\n}\n\nexport function isSessionPath(relativePath: string) {\n\treturn toPosix(relativePath).startsWith(\"sessions/\");\n}\n\nexport function isSessionFilePath(relativePath: string) {\n\tconst normalized = toPosix(relativePath);\n\treturn isSessionPath(normalized) && normalized.endsWith(\".jsonl\");\n}\n\nexport function sessionSnapshotPathFromAbsolute(\n\tsessionFile: string,\n\tconfiguredSessionDir?: string,\n) {\n\tconst relativePath = toPosix(\n\t\tpath.relative(sessionStorageRoot(agentDir(), configuredSessionDir), sessionFile),\n\t);\n\tif (!relativePath || relativePath.startsWith(\"../\") || path.posix.isAbsolute(relativePath)) {\n\t\treturn undefined;\n\t}\n\tconst snapshotPath = posixJoin(\"sessions\", relativePath);\n\treturn isSessionFilePath(snapshotPath) ? snapshotPath : undefined;\n}\n\nexport function snapshotTarget(root: string, relativePath: string, configuredSessionDir?: string) {\n\tif (isSessionPath(relativePath)) {\n\t\treturn safeJoin(\n\t\t\tsessionStorageRoot(root, configuredSessionDir),\n\t\t\trelativePath.slice(\"sessions/\".length),\n\t\t);\n\t}\n\treturn safeJoin(root, relativePath);\n}\n\nexport function snapshotIncludesSessions(snapshot: Snapshot) {\n\treturn (\n\t\tsnapshot.syncSessions === true ||\n\t\tsnapshotSelectionInclude(snapshot)?.includes(\"sessions\") === true ||\n\t\tsnapshot.files.some((file) => isSessionPath(file.path))\n\t);\n}\n\nexport function filterSnapshotForConfigPolicy(\n\tsnapshot: Snapshot,\n\tconfig: SyncSelectionConfig,\n\toptions: { regenerateId?: boolean } = {},\n) {\n\tconst include = includeFromSelectionConfig(config);\n\tconst includePaths = customIncludePathsByLower(include);\n\tconst filtered = {\n\t\t...snapshot,\n\t\tsyncSessions: include.includes(\"sessions\") ? snapshot.syncSessions : false,\n\t\tselection: selectionForSnapshot(include),\n\t\tfiles: canonicalizeSnapshotFilesForConfig(snapshot.files, config, includePaths),\n\t};\n\tif (!options.regenerateId || snapshotsMatch(snapshot, filtered)) return filtered;\n\treturn {\n\t\t...filtered,\n\t\tid: snapshotId(),\n\t\tcreatedAt: new Date().toISOString(),\n\t\tmachine: os.hostname(),\n\t};\n}\n\nfunction canonicalizeSnapshotFilesForConfig(\n\tfiles: SnapshotFile[],\n\tconfig: SyncSelectionConfig,\n\tincludePaths: Map<string, string>,\n) {\n\tconst configuredFiles: SnapshotFile[] = [];\n\tconst extraCandidates = new Map<\n\t\tstring,\n\t\t{ exact: boolean; file: SnapshotFile; originalPath: string }\n\t>();\n\tfor (const file of files) {\n\t\tconst normalized = toPosix(file.path);\n\t\tif (!isSafeSnapshotPath(file.path) || !isConfiguredSnapshotPath(normalized, config)) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (normalized.includes(\"/\")) {\n\t\t\tconfiguredFiles.push(normalized === file.path ? file : { ...file, path: normalized });\n\t\t\tcontinue;\n\t\t}\n\t\tconst topLevelPath = canonicalSnapshotPathForConfig(normalized, includePaths);\n\t\tconst candidate = {\n\t\t\texact: normalized === topLevelPath,\n\t\t\tfile: { ...file, path: topLevelPath },\n\t\t\toriginalPath: normalized,\n\t\t};\n\t\tconst current = extraCandidates.get(topLevelPath.toLowerCase());\n\t\tif (!current || isPreferredExtraCandidate(candidate, current)) {\n\t\t\textraCandidates.set(topLevelPath.toLowerCase(), candidate);\n\t\t}\n\t}\n\treturn [\n\t\t...configuredFiles,\n\t\t...[...extraCandidates.values()].map((candidate) => candidate.file),\n\t].sort((left, right) => left.path.localeCompare(right.path));\n}\n\nfunction isPreferredExtraCandidate(\n\tleft: { exact: boolean; originalPath: string },\n\tright: { exact: boolean; originalPath: string },\n) {\n\tif (left.exact !== right.exact) return left.exact;\n\treturn left.originalPath.localeCompare(right.originalPath) < 0;\n}\n\nexport function snapshotWithoutSessions(snapshot: Snapshot) {\n\tconst files = snapshot.files.filter((file) => !isSessionPath(file.path));\n\tconst include = snapshotSelectionInclude(snapshot)?.filter((item) => item !== \"sessions\");\n\tif (\n\t\tfiles.length === snapshot.files.length &&\n\t\tsnapshot.syncSessions !== true &&\n\t\tinclude?.length === snapshot.selection?.include.length\n\t) {\n\t\treturn snapshot;\n\t}\n\treturn {\n\t\t...snapshot,\n\t\tid: snapshotId(),\n\t\tcreatedAt: new Date().toISOString(),\n\t\tmachine: os.hostname(),\n\t\tsyncSessions: false,\n\t\t...(include ? { selection: selectionForSnapshot(include) } : {}),\n\t\tfiles,\n\t};\n}\n\nexport function scanSnapshot(snapshot: Snapshot) {\n\tconst findings: string[] = [];\n\tfor (const file of snapshot.files) {\n\t\tconst content = Buffer.from(file.contentBase64, \"base64\");\n\t\tif (content.includes(0)) continue;\n\t\tconst text = content.toString(\"utf8\");\n\t\tfor (const pattern of SECRET_PATTERNS) {\n\t\t\tif (pattern.test(text)) {\n\t\t\t\tfindings.push(file.path);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn findings;\n}\n\nexport function mergeRemotePreservedFiles(\n\tlocal: Snapshot,\n\tremote: Snapshot,\n\tconfig: SyncSelectionConfig,\n) {\n\tconst localPathNames = new Set(local.files.map((file) => file.path.toLowerCase()));\n\tconst preservedPathNames = new Set<string>();\n\tconst preserved = remote.files.filter((file) => {\n\t\tconst normalized = toPosix(file.path);\n\t\tconst lower = normalized.toLowerCase();\n\t\tif (\n\t\t\tlocalPathNames.has(lower) ||\n\t\t\tpreservedPathNames.has(lower) ||\n\t\t\t!isSafeSnapshotPath(file.path) ||\n\t\t\tisConfiguredSnapshotPath(normalized, config) ||\n\t\t\t!isPreservableUnmanagedSnapshotPath(normalized)\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\tpreservedPathNames.add(lower);\n\t\treturn true;\n\t});\n\tif (preserved.length === 0) return local;\n\treturn {\n\t\t...local,\n\t\tid: snapshotId(),\n\t\tcreatedAt: new Date().toISOString(),\n\t\tmachine: os.hostname(),\n\t\tsyncSessions: snapshotIncludesSessions(local) || snapshotIncludesSessions(remote),\n\t\tfiles: [...local.files, ...preserved].sort((left, right) =>\n\t\t\tleft.path.localeCompare(right.path),\n\t\t),\n\t};\n}\n\nexport function mergeRemoteSessionFiles(local: Snapshot, remote: Snapshot) {\n\tconst remoteSessions = remote.files.filter((file) => {\n\t\tconst normalized = toPosix(file.path);\n\t\treturn isSessionFilePath(normalized) && isSafeSnapshotPath(file.path);\n\t});\n\tif (remoteSessions.length === 0 && !snapshotIncludesSessions(remote)) return local;\n\tconst localInclude = snapshotSelectionInclude(local);\n\treturn {\n\t\t...local,\n\t\tid: snapshotId(),\n\t\tcreatedAt: new Date().toISOString(),\n\t\tmachine: os.hostname(),\n\t\tsyncSessions: true,\n\t\t...(localInclude\n\t\t\t? {\n\t\t\t\t\tselection: selectionForSnapshot(\n\t\t\t\t\t\tlocalInclude.includes(\"sessions\") ? localInclude : [...localInclude, \"sessions\"],\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t: {}),\n\t\tfiles: [...local.files.filter((file) => !isSessionPath(file.path)), ...remoteSessions].sort(\n\t\t\t(left, right) => left.path.localeCompare(right.path),\n\t\t),\n\t};\n}\n\nfunction sameOptionalInclude(left: string[] | undefined, right: string[] | undefined) {\n\tif (!left || !right) return left === right;\n\treturn left.length === right.length && left.every((item, index) => item === right[index]);\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,YAAY,kBAAkB;AAEvC,OAAO,QAAQ;AACf,OAAO,QAAQ;AACf,OAAO,UAAU;AA0BjB,IAAM,UAAU;AAChB,IAAM,kBAAqC,qBAAqB;AAAA,EAAO,CAAC,SACvE,KAAK,SAAS,GAAG;AAClB;AACA,IAAM,iBAAiB,IAAI,IAAY,qBAAqB,OAAO,CAAC,SAAS,CAAC,KAAK,SAAS,GAAG,CAAC,CAAC;AACjG,IAAM,kBAAkB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEA,SAAS,wBAAwB,SAAmB,UAAkB;AACrE,QAAM,QAAQ,QAAQ,KAAK,CAAC,UAAU,MAAM,OAAO,KAAK,MAAM,SAAS,QAAQ;AAC/E,MAAI,MAAO,QAAO;AAClB,QAAM,QAAQ,SAAS,YAAY;AACnC,SAAO,QACL,OAAO,CAAC,UAAU,MAAM,OAAO,KAAK,MAAM,KAAK,YAAY,MAAM,KAAK,EACtE,KAAK,CAAC,MAAM,UAAU,KAAK,KAAK,cAAc,MAAM,IAAI,CAAC,EAAE,CAAC;AAC/D;AAEA,SAAS,OAAO,OAAe;AAC9B,SAAO,WAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK;AACvD;AAEA,SAAS,mBAAmB,cAAsB;AACjD,MAAI,aAAa,SAAS,IAAI,EAAG,QAAO;AACxC,QAAM,aAAa,QAAQ,YAAY;AACvC,SACC,QAAQ,UAAU,KAClB,eAAe,OACf,eAAe,QACf,CAAC,WAAW,WAAW,KAAK,KAC5B,CAAC,KAAK,MAAM,WAAW,UAAU,KACjC,KAAK,MAAM,UAAU,UAAU,MAAM,cACrC,CAAC,aAAa,UAAU;AAE1B;AAEA,SAAS,eAAe,MAAgB,OAAiB;AACxD,QAAM,aAAa,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,MAAM,KAAK,MAAM,CAAC,CAAC;AAC7E,QAAM,cAAc,IAAI,IAAI,MAAM,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,MAAM,KAAK,MAAM,CAAC,CAAC;AAC/E,SACC,KAAK,iBAAiB,MAAM,gBAC5B,oBAAoB,yBAAyB,IAAI,GAAG,yBAAyB,KAAK,CAAC,KACnF,WAAW,SAAS,YAAY,QAChC,CAAC,GAAG,UAAU,EAAE,MAAM,CAAC,CAAC,UAAU,IAAI,MAAM,YAAY,IAAI,QAAQ,MAAM,IAAI;AAEhF;AAEA,SAAS,aAAa;AACrB,SAAO,IAAG,oBAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG,CAAC,IAAI,WAAW,EAAE,MAAM,GAAG,CAAC,CAAC;AACrF;AAEO,SAAS,2BAA2B,UAA8B;AACxE,SAAO;AAAA,IACN,GAAG;AAAA,IACH,IAAI,WAAW;AAAA,IACf,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,SAAS,GAAG,SAAS;AAAA,EACtB;AACD;AAEA,eAAsB,eACrB,SACA,UAA2B,CAAC,GACR;AACpB,UAAQ,QAAQ,eAAe;AAC/B,QAAM,UAAU,iBAAiB,OAAO;AACxC,QAAM,eAAe,QAAQ,SAAS,UAAU;AAChD,QAAM,aAAa,QAAQ,cAAe,MAAM,qBAAqB;AACrE,UAAQ,QAAQ,eAAe;AAC/B,QAAM,QAAQ,MAAM,aAAa,SAAS,GAAG,EAAE,SAAS,YAAY,QAAQ,QAAQ,OAAO,CAAC;AAC5F,UAAQ,QAAQ,eAAe;AAC/B,SAAO;AAAA,IACN,SAAS;AAAA,IACT,IAAI,WAAW;AAAA,IACf,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,SAAS,GAAG,SAAS;AAAA,IACrB;AAAA,IACA;AAAA,IACA,WAAW,qBAAqB,OAAO;AAAA,IACvC;AAAA,EACD;AACD;AAEA,SAAS,iBAAiB,SAA0B;AACnD,MAAI,QAAQ,QAAS,QAAO,QAAQ;AACpC,SAAO;AAAA,IACN,GAAG,mBAAmB,QAAQ,SAAS;AAAA,IACvC,GAAG,oBAAoB,QAAQ,UAAU;AAAA,IACzC,GAAI,QAAQ,eAAe,CAAC,UAAU,IAAI,CAAC;AAAA,EAC5C;AACD;AAEA,eAAsB,aACrB,MACA,UAA2B,CAAC,GACF;AAC1B,QAAM,SAAS,QAAQ;AACvB,UAAQ,eAAe;AACvB,QAAM,UAA0B,CAAC;AACjC,QAAM,UAAU,MAAM,GAAG,QAAQ,MAAM,EAAE,eAAe,KAAK,CAAC;AAC9D,UAAQ,eAAe;AACvB,QAAM,YAAY,qBAAqB,iBAAiB,OAAO,CAAC;AAChE,QAAM,gBAAgB,IAAI,IAAY,UAAU,QAAQ;AACxD,aAAW,SAAS,SAAS;AAC5B,QAAI,MAAM,YAAY,KAAK,eAAe,IAAI,MAAM,IAAI,KAAK,cAAc,IAAI,MAAM,IAAI,GAAG;AAC3F,YAAM,iBAAiB,SAAS,MAAM,MAAM,MAAM,EAAE,OAAO,CAAC;AAAA,IAC7D;AAAA,EACD;AACA,aAAW,YAAY,iBAAiB;AACvC,QAAI,CAAC,cAAc,IAAI,QAAQ,EAAG;AAClC,UAAM,QAAQ,wBAAwB,SAAS,QAAQ;AACvD,QAAI,MAAO,OAAM,QAAQ,SAAS,MAAM,MAAM,MAAM,UAAU,MAAM;AAAA,EACrE;AACA,aAAW,gBAAgB,UAAU,QAAQ;AAC5C,UAAM,oBAAoB,SAAS,MAAM,cAAc,MAAM;AAAA,EAC9D;AACA,MAAI,UAAU,UAAU;AACvB,QAAI;AACH,YAAM,iBAAiB,SAAS,mBAAmB,MAAM,QAAQ,UAAU,GAAG,IAAI;AAAA,QACjF,cAAc;AAAA,QACd,eAAe;AAAA,QACf;AAAA,MACD,CAAC;AAAA,IACF,SAAS,OAAO;AACf,UAAK,MAAgC,SAAS,SAAU,OAAM;AAAA,IAC/D;AAAA,EACD;AACA,UAAQ,eAAe;AACvB,SAAO,QAAQ,KAAK,CAAC,MAAM,UAAU,KAAK,KAAK,cAAc,MAAM,IAAI,CAAC;AACzE;AAEA,eAAe,oBACd,SACA,MACA,cACA,QACC;AACD,UAAQ,eAAe;AACvB,QAAM,eAAe,SAAS,MAAM,YAAY;AAChD,MAAI;AACH,UAAM,OAAO,MAAM,GAAG,MAAM,YAAY;AACxC,YAAQ,eAAe;AACvB,QAAI,KAAK,OAAO,EAAG,OAAM,QAAQ,SAAS,MAAM,cAAc,cAAc,MAAM;AAAA,aACzE,KAAK,YAAY,EAAG,OAAM,iBAAiB,SAAS,MAAM,cAAc,EAAE,OAAO,CAAC;AAAA,EAC5F,SAAS,OAAO;AACf,QAAK,MAAgC,SAAS,SAAU,OAAM;AAC9D,QAAI,CAAC,aAAa,SAAS,GAAG,GAAG;AAChC,YAAM,UAAU,MAAM,GAAG,QAAQ,MAAM,EAAE,eAAe,KAAK,CAAC;AAC9D,cAAQ,eAAe;AACvB,YAAM,QAAQ,wBAAwB,SAAS,YAAY;AAC3D,UAAI,MAAO,OAAM,QAAQ,SAAS,MAAM,MAAM,MAAM,cAAc,MAAM;AAAA,IACzE;AAAA,EACD;AACD;AAEA,eAAe,iBACd,SACA,MACA,mBACA,UAAoF,CAAC,GACpF;AACD,UAAQ,QAAQ,eAAe;AAC/B,QAAM,oBAAoB,KAAK,KAAK,MAAM,iBAAiB;AAC3D,aAAW,SAAS,MAAM,GAAG,QAAQ,mBAAmB,EAAE,eAAe,KAAK,CAAC,GAAG;AACjF,YAAQ,QAAQ,eAAe;AAC/B,UAAM,eAAe,oBAAoB,UAAU,mBAAmB,MAAM,IAAI,IAAI,MAAM;AAC1F,UAAM,eAAe,QAAQ,gBAC1B,UAAU,QAAQ,eAAe,YAAY,IAC7C;AACH,QAAI,aAAa,YAAY,EAAG;AAChC,QAAI,MAAM,YAAY,GAAG;AACxB,YAAM,iBAAiB,SAAS,MAAM,cAAc,OAAO;AAAA,IAC5D,WAAW,MAAM,OAAO,MAAM,CAAC,QAAQ,gBAAgB,kBAAkB,YAAY,IAAI;AACxF,YAAM,QAAQ,SAAS,MAAM,cAAc,cAAc,QAAQ,MAAM;AAAA,IACxE;AAAA,EACD;AACD;AAEA,eAAe,QACd,SACA,MACA,cACA,eAAe,cACf,QACC;AACD,UAAQ,eAAe;AACvB,MAAI,CAAC,mBAAmB,YAAY,EAAG;AACvC,QAAM,eAAe,SAAS,MAAM,YAAY;AAChD,QAAM,UAAU,MAAM,GAAG,SAAS,cAAc,EAAE,OAAO,CAAC;AAC1D,UAAQ,eAAe;AACvB,UAAQ,KAAK;AAAA,IACZ,MAAM;AAAA,IACN,eAAe,QAAQ,SAAS,QAAQ;AAAA,IACxC,QAAQ,OAAO,OAAO;AAAA,EACvB,CAAC;AACF;AAEO,SAAS,cAAc,cAAsB;AACnD,SAAO,QAAQ,YAAY,EAAE,WAAW,WAAW;AACpD;AAEO,SAAS,kBAAkB,cAAsB;AACvD,QAAM,aAAa,QAAQ,YAAY;AACvC,SAAO,cAAc,UAAU,KAAK,WAAW,SAAS,QAAQ;AACjE;AAEO,SAAS,gCACf,aACAA,uBACC;AACD,QAAM,eAAe;AAAA,IACpB,KAAK,SAAS,mBAAmB,SAAS,GAAGA,qBAAoB,GAAG,WAAW;AAAA,EAChF;AACA,MAAI,CAAC,gBAAgB,aAAa,WAAW,KAAK,KAAK,KAAK,MAAM,WAAW,YAAY,GAAG;AAC3F,WAAO;AAAA,EACR;AACA,QAAM,eAAe,UAAU,YAAY,YAAY;AACvD,SAAO,kBAAkB,YAAY,IAAI,eAAe;AACzD;AAEO,SAAS,eAAe,MAAc,cAAsBA,uBAA+B;AACjG,MAAI,cAAc,YAAY,GAAG;AAChC,WAAO;AAAA,MACN,mBAAmB,MAAMA,qBAAoB;AAAA,MAC7C,aAAa,MAAM,YAAY,MAAM;AAAA,IACtC;AAAA,EACD;AACA,SAAO,SAAS,MAAM,YAAY;AACnC;AAEO,SAAS,yBAAyB,UAAoB;AAC5D,SACC,SAAS,iBAAiB,QAC1B,yBAAyB,QAAQ,GAAG,SAAS,UAAU,MAAM,QAC7D,SAAS,MAAM,KAAK,CAAC,SAAS,cAAc,KAAK,IAAI,CAAC;AAExD;AAEO,SAAS,8BACf,UACA,QACA,UAAsC,CAAC,GACtC;AACD,QAAM,UAAU,2BAA2B,MAAM;AACjD,QAAM,eAAe,0BAA0B,OAAO;AACtD,QAAM,WAAW;AAAA,IAChB,GAAG;AAAA,IACH,cAAc,QAAQ,SAAS,UAAU,IAAI,SAAS,eAAe;AAAA,IACrE,WAAW,qBAAqB,OAAO;AAAA,IACvC,OAAO,mCAAmC,SAAS,OAAO,QAAQ,YAAY;AAAA,EAC/E;AACA,MAAI,CAAC,QAAQ,gBAAgB,eAAe,UAAU,QAAQ,EAAG,QAAO;AACxE,SAAO;AAAA,IACN,GAAG;AAAA,IACH,IAAI,WAAW;AAAA,IACf,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,SAAS,GAAG,SAAS;AAAA,EACtB;AACD;AAEA,SAAS,mCACR,OACA,QACA,cACC;AACD,QAAM,kBAAkC,CAAC;AACzC,QAAM,kBAAkB,oBAAI,IAG1B;AACF,aAAW,QAAQ,OAAO;AACzB,UAAM,aAAa,QAAQ,KAAK,IAAI;AACpC,QAAI,CAAC,mBAAmB,KAAK,IAAI,KAAK,CAAC,yBAAyB,YAAY,MAAM,GAAG;AACpF;AAAA,IACD;AACA,QAAI,WAAW,SAAS,GAAG,GAAG;AAC7B,sBAAgB,KAAK,eAAe,KAAK,OAAO,OAAO,EAAE,GAAG,MAAM,MAAM,WAAW,CAAC;AACpF;AAAA,IACD;AACA,UAAM,eAAe,+BAA+B,YAAY,YAAY;AAC5E,UAAM,YAAY;AAAA,MACjB,OAAO,eAAe;AAAA,MACtB,MAAM,EAAE,GAAG,MAAM,MAAM,aAAa;AAAA,MACpC,cAAc;AAAA,IACf;AACA,UAAM,UAAU,gBAAgB,IAAI,aAAa,YAAY,CAAC;AAC9D,QAAI,CAAC,WAAW,0BAA0B,WAAW,OAAO,GAAG;AAC9D,sBAAgB,IAAI,aAAa,YAAY,GAAG,SAAS;AAAA,IAC1D;AAAA,EACD;AACA,SAAO;AAAA,IACN,GAAG;AAAA,IACH,GAAG,CAAC,GAAG,gBAAgB,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,UAAU,IAAI;AAAA,EACnE,EAAE,KAAK,CAAC,MAAM,UAAU,KAAK,KAAK,cAAc,MAAM,IAAI,CAAC;AAC5D;AAEA,SAAS,0BACR,MACA,OACC;AACD,MAAI,KAAK,UAAU,MAAM,MAAO,QAAO,KAAK;AAC5C,SAAO,KAAK,aAAa,cAAc,MAAM,YAAY,IAAI;AAC9D;AAEO,SAAS,wBAAwB,UAAoB;AAC3D,QAAM,QAAQ,SAAS,MAAM,OAAO,CAAC,SAAS,CAAC,cAAc,KAAK,IAAI,CAAC;AACvE,QAAM,UAAU,yBAAyB,QAAQ,GAAG,OAAO,CAAC,SAAS,SAAS,UAAU;AACxF,MACC,MAAM,WAAW,SAAS,MAAM,UAChC,SAAS,iBAAiB,QAC1B,SAAS,WAAW,SAAS,WAAW,QAAQ,QAC/C;AACD,WAAO;AAAA,EACR;AACA,SAAO;AAAA,IACN,GAAG;AAAA,IACH,IAAI,WAAW;AAAA,IACf,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,SAAS,GAAG,SAAS;AAAA,IACrB,cAAc;AAAA,IACd,GAAI,UAAU,EAAE,WAAW,qBAAqB,OAAO,EAAE,IAAI,CAAC;AAAA,IAC9D;AAAA,EACD;AACD;AAEO,SAAS,aAAa,UAAoB;AAChD,QAAM,WAAqB,CAAC;AAC5B,aAAW,QAAQ,SAAS,OAAO;AAClC,UAAM,UAAU,OAAO,KAAK,KAAK,eAAe,QAAQ;AACxD,QAAI,QAAQ,SAAS,CAAC,EAAG;AACzB,UAAM,OAAO,QAAQ,SAAS,MAAM;AACpC,eAAW,WAAW,iBAAiB;AACtC,UAAI,QAAQ,KAAK,IAAI,GAAG;AACvB,iBAAS,KAAK,KAAK,IAAI;AACvB;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACA,SAAO;AACR;AAEO,SAAS,0BACf,OACA,QACA,QACC;AACD,QAAM,iBAAiB,IAAI,IAAI,MAAM,MAAM,IAAI,CAAC,SAAS,KAAK,KAAK,YAAY,CAAC,CAAC;AACjF,QAAM,qBAAqB,oBAAI,IAAY;AAC3C,QAAM,YAAY,OAAO,MAAM,OAAO,CAAC,SAAS;AAC/C,UAAM,aAAa,QAAQ,KAAK,IAAI;AACpC,UAAM,QAAQ,WAAW,YAAY;AACrC,QACC,eAAe,IAAI,KAAK,KACxB,mBAAmB,IAAI,KAAK,KAC5B,CAAC,mBAAmB,KAAK,IAAI,KAC7B,yBAAyB,YAAY,MAAM,KAC3C,CAAC,mCAAmC,UAAU,GAC7C;AACD,aAAO;AAAA,IACR;AACA,uBAAmB,IAAI,KAAK;AAC5B,WAAO;AAAA,EACR,CAAC;AACD,MAAI,UAAU,WAAW,EAAG,QAAO;AACnC,SAAO;AAAA,IACN,GAAG;AAAA,IACH,IAAI,WAAW;AAAA,IACf,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,SAAS,GAAG,SAAS;AAAA,IACrB,cAAc,yBAAyB,KAAK,KAAK,yBAAyB,MAAM;AAAA,IAChF,OAAO,CAAC,GAAG,MAAM,OAAO,GAAG,SAAS,EAAE;AAAA,MAAK,CAAC,MAAM,UACjD,KAAK,KAAK,cAAc,MAAM,IAAI;AAAA,IACnC;AAAA,EACD;AACD;AAEO,SAAS,wBAAwB,OAAiB,QAAkB;AAC1E,QAAM,iBAAiB,OAAO,MAAM,OAAO,CAAC,SAAS;AACpD,UAAM,aAAa,QAAQ,KAAK,IAAI;AACpC,WAAO,kBAAkB,UAAU,KAAK,mBAAmB,KAAK,IAAI;AAAA,EACrE,CAAC;AACD,MAAI,eAAe,WAAW,KAAK,CAAC,yBAAyB,MAAM,EAAG,QAAO;AAC7E,QAAM,eAAe,yBAAyB,KAAK;AACnD,SAAO;AAAA,IACN,GAAG;AAAA,IACH,IAAI,WAAW;AAAA,IACf,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,SAAS,GAAG,SAAS;AAAA,IACrB,cAAc;AAAA,IACd,GAAI,eACD;AAAA,MACA,WAAW;AAAA,QACV,aAAa,SAAS,UAAU,IAAI,eAAe,CAAC,GAAG,cAAc,UAAU;AAAA,MAChF;AAAA,IACD,IACC,CAAC;AAAA,IACJ,OAAO,CAAC,GAAG,MAAM,MAAM,OAAO,CAAC,SAAS,CAAC,cAAc,KAAK,IAAI,CAAC,GAAG,GAAG,cAAc,EAAE;AAAA,MACtF,CAAC,MAAM,UAAU,KAAK,KAAK,cAAc,MAAM,IAAI;AAAA,IACpD;AAAA,EACD;AACD;AAEA,SAAS,oBAAoB,MAA4B,OAA6B;AACrF,MAAI,CAAC,QAAQ,CAAC,MAAO,QAAO,SAAS;AACrC,SAAO,KAAK,WAAW,MAAM,UAAU,KAAK,MAAM,CAAC,MAAM,UAAU,SAAS,MAAM,KAAK,CAAC;AACzF;",
6
+ "names": ["configuredSessionDir"]
7
+ }