@multiplayer-app/agent 0.1.20 → 0.1.21

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 (290) hide show
  1. package/README.md +14 -7
  2. package/dist/agent/definition.test.js +8 -3
  3. package/dist/agent/definition.test.js.map +1 -1
  4. package/dist/agent/profiles/coding.d.ts +1 -1
  5. package/dist/agent/profiles/coding.d.ts.map +1 -1
  6. package/dist/agent/profiles/coding.js +21 -4
  7. package/dist/agent/profiles/coding.js.map +1 -1
  8. package/dist/agent/profiles/index.js +1 -1
  9. package/dist/agent/profiles/index.js.map +1 -1
  10. package/dist/agent/profiles/research.d.ts.map +1 -1
  11. package/dist/agent/profiles/research.js +2 -2
  12. package/dist/agent/profiles/research.js.map +1 -1
  13. package/dist/agent/turn-history.d.ts.map +1 -1
  14. package/dist/agent/turn-history.js +7 -1
  15. package/dist/agent/turn-history.js.map +1 -1
  16. package/dist/agent/turn-runner.d.ts +8 -0
  17. package/dist/agent/turn-runner.d.ts.map +1 -1
  18. package/dist/agent/turn-runner.js +35 -10
  19. package/dist/agent/turn-runner.js.map +1 -1
  20. package/dist/app/app-host.d.ts +57 -0
  21. package/dist/app/app-host.d.ts.map +1 -0
  22. package/dist/app/app-host.js +252 -0
  23. package/dist/app/app-host.js.map +1 -0
  24. package/dist/app/app-host.test.d.ts +2 -0
  25. package/dist/app/app-host.test.d.ts.map +1 -0
  26. package/dist/app/app-host.test.js +639 -0
  27. package/dist/app/app-host.test.js.map +1 -0
  28. package/dist/app/config.d.ts +196 -0
  29. package/dist/app/config.d.ts.map +1 -0
  30. package/dist/app/config.js +362 -0
  31. package/dist/app/config.js.map +1 -0
  32. package/dist/app/config.test.d.ts +2 -0
  33. package/dist/app/config.test.d.ts.map +1 -0
  34. package/dist/app/config.test.js +224 -0
  35. package/dist/app/config.test.js.map +1 -0
  36. package/dist/app/detect.d.ts +68 -0
  37. package/dist/app/detect.d.ts.map +1 -0
  38. package/dist/app/detect.js +449 -0
  39. package/dist/app/detect.js.map +1 -0
  40. package/dist/app/detect.test.d.ts +2 -0
  41. package/dist/app/detect.test.d.ts.map +1 -0
  42. package/dist/app/detect.test.js +267 -0
  43. package/dist/app/detect.test.js.map +1 -0
  44. package/dist/app/env.d.ts +5 -0
  45. package/dist/app/env.d.ts.map +1 -0
  46. package/dist/app/env.js +22 -0
  47. package/dist/app/env.js.map +1 -0
  48. package/dist/app/functions-cli.d.ts +3 -0
  49. package/dist/app/functions-cli.d.ts.map +1 -0
  50. package/dist/app/functions-cli.js +27 -0
  51. package/dist/app/functions-cli.js.map +1 -0
  52. package/dist/app/functions-host.d.ts +15 -0
  53. package/dist/app/functions-host.d.ts.map +1 -0
  54. package/dist/app/functions-host.js +276 -0
  55. package/dist/app/functions-host.js.map +1 -0
  56. package/dist/app/functions-host.test.d.ts +2 -0
  57. package/dist/app/functions-host.test.d.ts.map +1 -0
  58. package/dist/app/functions-host.test.js +117 -0
  59. package/dist/app/functions-host.test.js.map +1 -0
  60. package/dist/app/functions-routes.d.ts +23 -0
  61. package/dist/app/functions-routes.d.ts.map +1 -0
  62. package/dist/app/functions-routes.js +85 -0
  63. package/dist/app/functions-routes.js.map +1 -0
  64. package/dist/app/functions-routes.test.d.ts +2 -0
  65. package/dist/app/functions-routes.test.d.ts.map +1 -0
  66. package/dist/app/functions-routes.test.js +40 -0
  67. package/dist/app/functions-routes.test.js.map +1 -0
  68. package/dist/app/manifest.d.ts +17 -0
  69. package/dist/app/manifest.d.ts.map +1 -0
  70. package/dist/app/manifest.js +64 -0
  71. package/dist/app/manifest.js.map +1 -0
  72. package/dist/app/manifest.test.d.ts +2 -0
  73. package/dist/app/manifest.test.d.ts.map +1 -0
  74. package/dist/app/manifest.test.js +173 -0
  75. package/dist/app/manifest.test.js.map +1 -0
  76. package/dist/app/release-artifacts.d.ts +39 -0
  77. package/dist/app/release-artifacts.d.ts.map +1 -0
  78. package/dist/app/release-artifacts.js +229 -0
  79. package/dist/app/release-artifacts.js.map +1 -0
  80. package/dist/app/release-artifacts.test.d.ts +2 -0
  81. package/dist/app/release-artifacts.test.d.ts.map +1 -0
  82. package/dist/app/release-artifacts.test.js +295 -0
  83. package/dist/app/release-artifacts.test.js.map +1 -0
  84. package/dist/app/route-pattern.d.ts +23 -0
  85. package/dist/app/route-pattern.d.ts.map +1 -0
  86. package/dist/app/route-pattern.js +339 -0
  87. package/dist/app/route-pattern.js.map +1 -0
  88. package/dist/app/route-pattern.test.d.ts +2 -0
  89. package/dist/app/route-pattern.test.d.ts.map +1 -0
  90. package/dist/app/route-pattern.test.js +187 -0
  91. package/dist/app/route-pattern.test.js.map +1 -0
  92. package/dist/app/rules.d.ts +61 -0
  93. package/dist/app/rules.d.ts.map +1 -0
  94. package/dist/app/rules.js +90 -0
  95. package/dist/app/rules.js.map +1 -0
  96. package/dist/app/rules.test.d.ts +2 -0
  97. package/dist/app/rules.test.d.ts.map +1 -0
  98. package/dist/app/rules.test.js +69 -0
  99. package/dist/app/rules.test.js.map +1 -0
  100. package/dist/app/runner.d.ts +109 -0
  101. package/dist/app/runner.d.ts.map +1 -0
  102. package/dist/app/runner.js +429 -0
  103. package/dist/app/runner.js.map +1 -0
  104. package/dist/app/site.d.ts +73 -0
  105. package/dist/app/site.d.ts.map +1 -0
  106. package/dist/app/site.js +161 -0
  107. package/dist/app/site.js.map +1 -0
  108. package/dist/app/site.test.d.ts +2 -0
  109. package/dist/app/site.test.d.ts.map +1 -0
  110. package/dist/app/site.test.js +291 -0
  111. package/dist/app/site.test.js.map +1 -0
  112. package/dist/app/static-server.d.ts +20 -0
  113. package/dist/app/static-server.d.ts.map +1 -0
  114. package/dist/app/static-server.js +145 -0
  115. package/dist/app/static-server.js.map +1 -0
  116. package/dist/persistence/conversation-store.d.ts +21 -0
  117. package/dist/persistence/conversation-store.d.ts.map +1 -0
  118. package/dist/persistence/conversation-store.js +59 -0
  119. package/dist/persistence/conversation-store.js.map +1 -0
  120. package/dist/persistence/conversation-store.test.d.ts +2 -0
  121. package/dist/persistence/conversation-store.test.d.ts.map +1 -0
  122. package/dist/persistence/conversation-store.test.js +98 -0
  123. package/dist/persistence/conversation-store.test.js.map +1 -0
  124. package/dist/persistence/git-sync.d.ts +14 -1
  125. package/dist/persistence/git-sync.d.ts.map +1 -1
  126. package/dist/persistence/git-sync.js +73 -17
  127. package/dist/persistence/git-sync.js.map +1 -1
  128. package/dist/persistence/git-sync.test.js +155 -6
  129. package/dist/persistence/git-sync.test.js.map +1 -1
  130. package/dist/persistence/snapshot-sync.d.ts +19 -2
  131. package/dist/persistence/snapshot-sync.d.ts.map +1 -1
  132. package/dist/persistence/snapshot-sync.js +194 -83
  133. package/dist/persistence/snapshot-sync.js.map +1 -1
  134. package/dist/persistence/snapshot-sync.test.js +145 -27
  135. package/dist/persistence/snapshot-sync.test.js.map +1 -1
  136. package/dist/persistence/workspace.d.ts +3 -0
  137. package/dist/persistence/workspace.d.ts.map +1 -1
  138. package/dist/persistence/workspace.js +1 -0
  139. package/dist/persistence/workspace.js.map +1 -1
  140. package/dist/research/extract-texts.d.ts.map +1 -1
  141. package/dist/research/extract-texts.js +6 -13
  142. package/dist/research/extract-texts.js.map +1 -1
  143. package/dist/research/filingramp/attachment-tools.d.ts.map +1 -1
  144. package/dist/research/filingramp/attachment-tools.js +7 -4
  145. package/dist/research/filingramp/attachment-tools.js.map +1 -1
  146. package/dist/research/filingramp/shared.d.ts.map +1 -1
  147. package/dist/research/filingramp/shared.js +5 -5
  148. package/dist/research/filingramp/shared.js.map +1 -1
  149. package/dist/runtime/app-mode.d.ts +10 -0
  150. package/dist/runtime/app-mode.d.ts.map +1 -0
  151. package/dist/runtime/app-mode.js +172 -0
  152. package/dist/runtime/app-mode.js.map +1 -0
  153. package/dist/runtime/app-mode.test.d.ts +2 -0
  154. package/dist/runtime/app-mode.test.d.ts.map +1 -0
  155. package/dist/runtime/app-mode.test.js +130 -0
  156. package/dist/runtime/app-mode.test.js.map +1 -0
  157. package/dist/runtime/app-rehearsal.d.ts +2 -0
  158. package/dist/runtime/app-rehearsal.d.ts.map +1 -0
  159. package/dist/runtime/app-rehearsal.js +56 -0
  160. package/dist/runtime/app-rehearsal.js.map +1 -0
  161. package/dist/runtime/build-mode.d.ts +12 -0
  162. package/dist/runtime/build-mode.d.ts.map +1 -0
  163. package/dist/runtime/build-mode.js +116 -0
  164. package/dist/runtime/build-mode.js.map +1 -0
  165. package/dist/runtime/build-mode.test.d.ts +2 -0
  166. package/dist/runtime/build-mode.test.d.ts.map +1 -0
  167. package/dist/runtime/build-mode.test.js +121 -0
  168. package/dist/runtime/build-mode.test.js.map +1 -0
  169. package/dist/runtime/cli.js +7 -2
  170. package/dist/runtime/cli.js.map +1 -1
  171. package/dist/runtime/config.d.ts +4 -0
  172. package/dist/runtime/config.d.ts.map +1 -1
  173. package/dist/runtime/config.js +13 -2
  174. package/dist/runtime/config.js.map +1 -1
  175. package/dist/runtime/guest-server.d.ts +3 -0
  176. package/dist/runtime/guest-server.d.ts.map +1 -0
  177. package/dist/runtime/{lambda-microvm.js → guest-server.js} +49 -18
  178. package/dist/runtime/guest-server.js.map +1 -0
  179. package/dist/runtime/image-hooks.d.ts +5 -0
  180. package/dist/runtime/image-hooks.d.ts.map +1 -0
  181. package/dist/runtime/image-hooks.js +68 -0
  182. package/dist/runtime/image-hooks.js.map +1 -0
  183. package/dist/runtime/image-hooks.test.d.ts +2 -0
  184. package/dist/runtime/image-hooks.test.d.ts.map +1 -0
  185. package/dist/runtime/image-hooks.test.js +74 -0
  186. package/dist/runtime/image-hooks.test.js.map +1 -0
  187. package/dist/runtime/index.d.ts +8 -3
  188. package/dist/runtime/index.d.ts.map +1 -1
  189. package/dist/runtime/index.js +53 -35
  190. package/dist/runtime/index.js.map +1 -1
  191. package/dist/runtime/listening-ports.d.ts +13 -0
  192. package/dist/runtime/listening-ports.d.ts.map +1 -0
  193. package/dist/runtime/listening-ports.js +78 -0
  194. package/dist/runtime/listening-ports.js.map +1 -0
  195. package/dist/runtime/listening-ports.test.d.ts +2 -0
  196. package/dist/runtime/listening-ports.test.d.ts.map +1 -0
  197. package/dist/runtime/listening-ports.test.js +39 -0
  198. package/dist/runtime/listening-ports.test.js.map +1 -0
  199. package/dist/runtime/preview-proxy.d.ts +56 -0
  200. package/dist/runtime/preview-proxy.d.ts.map +1 -0
  201. package/dist/runtime/preview-proxy.js +302 -0
  202. package/dist/runtime/preview-proxy.js.map +1 -0
  203. package/dist/runtime/preview-proxy.test.d.ts +2 -0
  204. package/dist/runtime/preview-proxy.test.d.ts.map +1 -0
  205. package/dist/runtime/preview-proxy.test.js +122 -0
  206. package/dist/runtime/preview-proxy.test.js.map +1 -0
  207. package/dist/runtime/session-mode.d.ts +3 -0
  208. package/dist/runtime/session-mode.d.ts.map +1 -0
  209. package/dist/runtime/session-mode.js +60 -0
  210. package/dist/runtime/session-mode.js.map +1 -0
  211. package/dist/runtime/workload.d.ts +44 -0
  212. package/dist/runtime/workload.d.ts.map +1 -0
  213. package/dist/runtime/workload.js +222 -0
  214. package/dist/runtime/workload.js.map +1 -0
  215. package/dist/runtime/workload.test.d.ts +2 -0
  216. package/dist/runtime/workload.test.d.ts.map +1 -0
  217. package/dist/runtime/workload.test.js +235 -0
  218. package/dist/runtime/workload.test.js.map +1 -0
  219. package/dist/session/conversation.d.ts +3 -2
  220. package/dist/session/conversation.d.ts.map +1 -1
  221. package/dist/session/conversation.js +11 -7
  222. package/dist/session/conversation.js.map +1 -1
  223. package/dist/session/conversation.test.js +2 -3
  224. package/dist/session/conversation.test.js.map +1 -1
  225. package/dist/session/runtime.d.ts +16 -3
  226. package/dist/session/runtime.d.ts.map +1 -1
  227. package/dist/session/runtime.js +80 -13
  228. package/dist/session/runtime.js.map +1 -1
  229. package/dist/session/runtime.test.js +18 -7
  230. package/dist/session/runtime.test.js.map +1 -1
  231. package/dist/session/tools.d.ts.map +1 -1
  232. package/dist/session/tools.js +3 -3
  233. package/dist/session/tools.js.map +1 -1
  234. package/dist/task/loop.d.ts.map +1 -1
  235. package/dist/task/loop.js +6 -4
  236. package/dist/task/loop.js.map +1 -1
  237. package/dist/tools/exec-tools.d.ts +12 -0
  238. package/dist/tools/exec-tools.d.ts.map +1 -1
  239. package/dist/tools/exec-tools.js +46 -3
  240. package/dist/tools/exec-tools.js.map +1 -1
  241. package/dist/tools/exec-tools.test.d.ts +2 -0
  242. package/dist/tools/exec-tools.test.d.ts.map +1 -0
  243. package/dist/tools/exec-tools.test.js +48 -0
  244. package/dist/tools/exec-tools.test.js.map +1 -0
  245. package/dist/tools/fs-tools.d.ts.map +1 -1
  246. package/dist/tools/fs-tools.js +5 -5
  247. package/dist/tools/fs-tools.js.map +1 -1
  248. package/dist/transport/link.d.ts.map +1 -1
  249. package/dist/transport/link.js +16 -5
  250. package/dist/transport/link.js.map +1 -1
  251. package/dist/transport/link.test.js +24 -0
  252. package/dist/transport/link.test.js.map +1 -1
  253. package/dist/transport/protocol.d.ts +190 -3
  254. package/dist/transport/protocol.d.ts.map +1 -1
  255. package/dist/transport/protocol.js +147 -7
  256. package/dist/transport/protocol.js.map +1 -1
  257. package/dist/transport/protocol.test.js +41 -0
  258. package/dist/transport/protocol.test.js.map +1 -1
  259. package/dist/workspace-sync/eligibility.d.ts +14 -0
  260. package/dist/workspace-sync/eligibility.d.ts.map +1 -0
  261. package/dist/workspace-sync/eligibility.js +53 -0
  262. package/dist/workspace-sync/eligibility.js.map +1 -0
  263. package/dist/workspace-sync/merge.d.ts +15 -0
  264. package/dist/workspace-sync/merge.d.ts.map +1 -0
  265. package/dist/workspace-sync/merge.js +66 -0
  266. package/dist/workspace-sync/merge.js.map +1 -0
  267. package/dist/workspace-sync/merge.test.d.ts +2 -0
  268. package/dist/workspace-sync/merge.test.d.ts.map +1 -0
  269. package/dist/workspace-sync/merge.test.js +28 -0
  270. package/dist/workspace-sync/merge.test.js.map +1 -0
  271. package/dist/workspace-sync/workspace-sync.d.ts +48 -0
  272. package/dist/workspace-sync/workspace-sync.d.ts.map +1 -0
  273. package/dist/workspace-sync/workspace-sync.js +308 -0
  274. package/dist/workspace-sync/workspace-sync.js.map +1 -0
  275. package/dist/workspace-sync/workspace-sync.test.d.ts +2 -0
  276. package/dist/workspace-sync/workspace-sync.test.d.ts.map +1 -0
  277. package/dist/workspace-sync/workspace-sync.test.js +111 -0
  278. package/dist/workspace-sync/workspace-sync.test.js.map +1 -0
  279. package/dist/workspace-sync/write-drafts.d.ts +24 -0
  280. package/dist/workspace-sync/write-drafts.d.ts.map +1 -0
  281. package/dist/workspace-sync/write-drafts.js +87 -0
  282. package/dist/workspace-sync/write-drafts.js.map +1 -0
  283. package/dist/workspace-sync/write-drafts.test.d.ts +2 -0
  284. package/dist/workspace-sync/write-drafts.test.d.ts.map +1 -0
  285. package/dist/workspace-sync/write-drafts.test.js +36 -0
  286. package/dist/workspace-sync/write-drafts.test.js.map +1 -0
  287. package/package.json +12 -2
  288. package/dist/runtime/lambda-microvm.d.ts +0 -3
  289. package/dist/runtime/lambda-microvm.d.ts.map +0 -1
  290. package/dist/runtime/lambda-microvm.js.map +0 -1
@@ -3,48 +3,96 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.SessionStorageSync = exports.MAX_SESSION_SNAPSHOT_BYTES = void 0;
7
- // Standalone sessions persist snapshots to S3 through the authenticated storage service.
6
+ exports.SessionStorageSync = exports.MAX_SESSION_FILE_BYTES = void 0;
7
+ exports.fileRoute = fileRoute;
8
+ exports.inPool = inPool;
9
+ // A standalone session's workspace lives in the session's folder in storage, one object per file,
10
+ // reached through the authenticated storage service (never S3 directly). A checkpoint uploads only
11
+ // what changed. Text the session mirrors is already there (workspace live sync): it is uploaded too
12
+ // only while the session has not confirmed that version, so a lost connection never loses an edit.
8
13
  // No Git repository is created in the guest or in the session's bucket folder.
9
14
  const node_crypto_1 = require("node:crypto");
10
15
  const node_fs_1 = require("node:fs");
11
16
  const node_path_1 = __importDefault(require("node:path"));
12
- exports.MAX_SESSION_SNAPSHOT_BYTES = 64 * 1024 * 1024;
17
+ const workload_1 = require("../runtime/workload");
18
+ const protocol_1 = require("../transport/protocol");
19
+ const eligibility_1 = require("../workspace-sync/eligibility");
20
+ exports.MAX_SESSION_FILE_BYTES = 64 * 1024 * 1024;
13
21
  const MARKER = '.builder/session-storage.json';
14
22
  const TIMEOUT_MS = 60000;
23
+ const FILE_TIMEOUT_MS = 5 * 60000;
24
+ const CONCURRENCY = 8;
25
+ // The storage layer's own objects beside a session's files (lib/session-pages/artifact-storage-paths.ts in the api).
26
+ const STORAGE_SIDECAR = /\.latest\.state$|\.snapshot-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z$/;
15
27
  function validPath(value) {
16
28
  return typeof value === 'string' && !/[\\\x00-\x1f]/.test(value)
17
29
  && value !== MARKER && value.split('/').every((part) => !['', '.', '..', '.git'].includes(part));
18
30
  }
19
31
  function excluded(relative) {
20
- return relative === MARKER || relative === 'data/attachments' || relative.startsWith('data/attachments/')
32
+ return relative === MARKER || relative === protocol_1.SESSION_CONVERSATION_FILE || relative === 'data/attachments' || relative.startsWith('data/attachments/')
33
+ || relative === '.builder/logs' || relative.startsWith('.builder/logs/')
34
+ || relative === '.builder/releases' || relative.startsWith('.builder/releases/')
21
35
  || relative.split('/').some((part) => ['.git', 'node_modules', '.venv'].includes(part))
22
- || /\.sqlite(?:-journal)?$/.test(relative);
36
+ || /\.sqlite(?:-journal)?$/.test(relative) || STORAGE_SIDECAR.test(relative);
37
+ }
38
+ function sha256(data) {
39
+ return (0, node_crypto_1.createHash)('sha256').update(data).digest('hex');
40
+ }
41
+ function isMirrorable(relative, content) {
42
+ return (0, eligibility_1.isSyncablePath)(relative) && (0, eligibility_1.syncableText)(content) !== undefined;
43
+ }
44
+ function fileRoute(relative) {
45
+ return `/files/${relative.split('/').map(encodeURIComponent).join('/')}`;
46
+ }
47
+ /** Runs `work` over `items`, a few at a time; the first failure stops new work and is rethrown. */
48
+ async function inPool(items, work) {
49
+ let next = 0;
50
+ let failed = false;
51
+ const errors = [];
52
+ await Promise.all(Array.from({ length: Math.min(CONCURRENCY, items.length) }, async () => {
53
+ while (!failed && next < items.length) {
54
+ const item = items[next++];
55
+ try {
56
+ await work(item);
57
+ }
58
+ catch (error) {
59
+ failed = true;
60
+ errors.push(error);
61
+ }
62
+ }
63
+ }));
64
+ if (errors.length)
65
+ throw errors[0];
23
66
  }
24
67
  class SessionStorageSync {
25
68
  constructor(config) {
26
69
  this.config = config;
70
+ this.known = new Map();
27
71
  this.busy = Promise.resolve();
28
72
  }
29
73
  get dir() { return this.config.dir; }
74
+ /** Live sync's answer for mirrored text; without it every changed file is uploaded. */
75
+ setMirror(check) {
76
+ this.mirror = check;
77
+ }
30
78
  serialize(work) {
31
79
  const next = this.busy.then(work, work);
32
80
  this.busy = next.catch(() => undefined);
33
81
  return next;
34
82
  }
35
- async request(method, body) {
83
+ async request(method, route, body, timeoutMs = TIMEOUT_MS) {
36
84
  var _a;
37
- const response = await fetch(this.config.url, {
38
- method, body, redirect: 'error', signal: AbortSignal.timeout(TIMEOUT_MS),
39
- headers: { Authorization: `Bearer ${this.config.token}`, 'Content-Type': 'application/json' },
85
+ const response = await fetch(`${this.config.url}${route}`, {
86
+ method, body: body, redirect: 'error', signal: AbortSignal.timeout(timeoutMs),
87
+ headers: { Authorization: `Bearer ${this.config.token}`, 'Content-Type': 'application/octet-stream' },
40
88
  });
41
- if (!response.ok && !(method === 'GET' && response.status === 404)) {
89
+ if (!response.ok && !(method !== 'PUT' && response.status === 404)) {
42
90
  await ((_a = response.body) === null || _a === void 0 ? void 0 : _a.cancel());
43
91
  throw new Error(`Session storage ${method} failed (${response.status})`);
44
92
  }
45
93
  return response;
46
94
  }
47
- async writeFile(relative, data, executable = false) {
95
+ async writeFile(relative, data) {
48
96
  // Never follow a workspace symlink while restoring a file (including parent directories).
49
97
  let parent = this.dir;
50
98
  for (const part of relative.split('/').slice(0, -1)) {
@@ -59,99 +107,162 @@ class SessionStorageSync {
59
107
  const file = await node_fs_1.promises.open(node_path_1.default.join(this.dir, relative), node_fs_1.constants.O_WRONLY | node_fs_1.constants.O_CREAT | node_fs_1.constants.O_TRUNC | node_fs_1.constants.O_NOFOLLOW, 0o600);
60
108
  try {
61
109
  await file.writeFile(data);
62
- await file.chmod(executable ? 0o755 : 0o644);
110
+ await file.chmod(0o644);
63
111
  }
64
112
  finally {
65
113
  await file.close();
66
114
  }
67
115
  }
116
+ /** `atBoot`: restoring, before any workload exists and so still as the runtime. */
117
+ async saveMarker(atBoot = false) {
118
+ const marker = { url: this.config.url, files: Object.fromEntries(this.known) };
119
+ if (atBoot)
120
+ await this.writeFile(MARKER, JSON.stringify(marker));
121
+ else
122
+ await (0, workload_1.writeWorkloadFile)(node_path_1.default.join(this.dir, MARKER), JSON.stringify(marker));
123
+ }
124
+ async download(relative) {
125
+ var _a;
126
+ const response = await this.request('GET', fileRoute(relative), undefined, FILE_TIMEOUT_MS);
127
+ if (response.status === 404) {
128
+ // Deleted since it was listed.
129
+ await ((_a = response.body) === null || _a === void 0 ? void 0 : _a.cancel());
130
+ return;
131
+ }
132
+ const content = Buffer.from(await response.arrayBuffer());
133
+ await this.writeFile(relative, content);
134
+ const stat = await node_fs_1.promises.lstat(node_path_1.default.join(this.dir, relative));
135
+ this.known.set(relative, { hash: sha256(content), size: stat.size, mtimeMs: stat.mtimeMs, mirrored: isMirrorable(relative, content) });
136
+ }
137
+ async applyExecutables() {
138
+ const text = await node_fs_1.promises.readFile(node_path_1.default.join(this.dir, protocol_1.WORKSPACE_EXECUTABLES_FILE), 'utf8').catch(() => undefined);
139
+ if (text === undefined)
140
+ return;
141
+ const files = JSON.parse(text);
142
+ if (!Array.isArray(files))
143
+ throw new Error('Invalid session file list');
144
+ for (const relative of files) {
145
+ if (!validPath(relative))
146
+ throw new Error('Invalid session file list');
147
+ const handle = await node_fs_1.promises.open(node_path_1.default.join(this.dir, relative), node_fs_1.constants.O_RDONLY | node_fs_1.constants.O_NOFOLLOW).catch(() => undefined);
148
+ if (!handle)
149
+ continue;
150
+ try {
151
+ await handle.chmod(0o755);
152
+ }
153
+ finally {
154
+ await handle.close();
155
+ }
156
+ }
157
+ }
68
158
  restore() {
69
159
  return this.serialize(async () => {
70
160
  var _a;
71
161
  await node_fs_1.promises.mkdir(this.dir, { recursive: true });
72
162
  // A process restart on a retained disk must preserve uncheckpointed local edits/deletions.
73
- const marker = await node_fs_1.promises.readFile(node_path_1.default.join(this.dir, MARKER), 'utf8').catch((error) => {
163
+ const saved = await node_fs_1.promises.readFile(node_path_1.default.join(this.dir, MARKER), 'utf8').catch((error) => {
74
164
  if (error.code !== 'ENOENT')
75
165
  throw error;
76
166
  return undefined;
77
167
  });
78
- if (marker && JSON.parse(marker).url === this.config.url)
168
+ const marker = saved ? JSON.parse(saved) : undefined;
169
+ if (marker && marker.url === this.config.url) {
170
+ for (const [relative, file] of Object.entries(marker.files))
171
+ this.known.set(relative, file);
79
172
  return true;
80
- const response = await this.request('GET');
81
- const found = response.status !== 404;
82
- if (found) {
83
- const chunks = [];
84
- let size = 0;
85
- if (response.body)
86
- for await (const chunk of response.body) {
87
- size += chunk.byteLength;
88
- if (size > exports.MAX_SESSION_SNAPSHOT_BYTES)
89
- throw new Error('Session snapshot exceeds size limit');
90
- chunks.push(chunk);
91
- }
92
- const snapshot = JSON.parse(Buffer.concat(chunks).toString('utf8'));
93
- const seen = new Set();
94
- if (snapshot.version !== 1 || !Array.isArray(snapshot.files))
95
- throw new Error('Invalid session snapshot');
96
- // Validate the complete manifest before writing anything.
97
- for (const file of snapshot.files) {
98
- if (!file || !validPath(file.path) || seen.has(file.path) || typeof file.content !== 'string'
99
- || typeof file.executable !== 'boolean' || Buffer.from(file.content, 'base64').toString('base64') !== file.content) {
100
- throw new Error('Invalid session snapshot file');
101
- }
102
- seen.add(file.path);
103
- }
104
- for (const file of snapshot.files)
105
- await this.writeFile(file.path, Buffer.from(file.content, 'base64'), file.executable);
106
173
  }
107
- else
108
- await ((_a = response.body) === null || _a === void 0 ? void 0 : _a.cancel());
109
- await this.writeFile(MARKER, JSON.stringify({ url: this.config.url }));
110
- return found;
174
+ const listed = await this.request('GET', '/files');
175
+ const files = listed.status === 404 ? (await ((_a = listed.body) === null || _a === void 0 ? void 0 : _a.cancel()), []) : (await listed.json()).files;
176
+ const paths = files.map((file) => file.path);
177
+ if (!paths.every(validPath))
178
+ throw new Error('Invalid session file');
179
+ await inPool(paths.filter((relative) => !excluded(relative)), (relative) => this.download(relative));
180
+ await this.applyExecutables();
181
+ await this.saveMarker(true);
182
+ return paths.length > 0;
111
183
  });
112
184
  }
185
+ async walk(relative = '') {
186
+ const files = [];
187
+ const entries = await node_fs_1.promises.readdir(node_path_1.default.join(this.dir, relative), { withFileTypes: true });
188
+ entries.sort((a, b) => a.name.localeCompare(b.name));
189
+ for (const entry of entries) {
190
+ const name = relative ? `${relative}/${entry.name}` : entry.name;
191
+ if (excluded(name))
192
+ continue;
193
+ if (!validPath(name)) {
194
+ console.warn(`[storage] not saving a file with an unsupported name: ${JSON.stringify(name)}`);
195
+ }
196
+ else if (entry.isDirectory()) {
197
+ files.push(...(await this.walk(name)));
198
+ }
199
+ else if (entry.isFile()) {
200
+ const stat = await node_fs_1.promises.lstat(node_path_1.default.join(this.dir, name));
201
+ files.push({ path: name, size: stat.size, mtimeMs: stat.mtimeMs, executable: Boolean(stat.mode & 0o111) });
202
+ }
203
+ }
204
+ return files;
205
+ }
206
+ /** Brings the list of executables up to date; whether it changed. */
207
+ async recordExecutables(files) {
208
+ const text = `${JSON.stringify(files.filter((file) => file.executable).map((file) => file.path), null, 2)}\n`;
209
+ const current = await node_fs_1.promises.readFile(node_path_1.default.join(this.dir, protocol_1.WORKSPACE_EXECUTABLES_FILE), 'utf8').catch(() => undefined);
210
+ if (current === text)
211
+ return false;
212
+ await (0, workload_1.writeWorkloadFile)(node_path_1.default.join(this.dir, protocol_1.WORKSPACE_EXECUTABLES_FILE), text);
213
+ return true;
214
+ }
215
+ /** Saves `file` if it changed; whether it did. */
216
+ async save(file) {
217
+ var _a;
218
+ const known = this.known.get(file.path);
219
+ if (known && known.size === file.size && known.mtimeMs === file.mtimeMs)
220
+ return false;
221
+ if (file.size > exports.MAX_SESSION_FILE_BYTES) {
222
+ console.warn(`[storage] not saving ${file.path}: ${file.size} bytes is over the ${exports.MAX_SESSION_FILE_BYTES} byte limit`);
223
+ return false;
224
+ }
225
+ const handle = await (0, workload_1.openInside)(this.dir, node_path_1.default.join(this.dir, file.path), node_fs_1.constants.O_NOFOLLOW);
226
+ let content;
227
+ try {
228
+ content = await handle.readFile();
229
+ }
230
+ finally {
231
+ await handle.close();
232
+ }
233
+ const hash = sha256(content);
234
+ const mirrored = isMirrorable(file.path, content);
235
+ const changed = (known === null || known === void 0 ? void 0 : known.hash) !== hash;
236
+ if (changed && !(mirrored && ((_a = this.mirror) === null || _a === void 0 ? void 0 : _a.call(this, file.path, content)))) {
237
+ await this.request('PUT', fileRoute(file.path), new Uint8Array(content.buffer, content.byteOffset, content.byteLength), FILE_TIMEOUT_MS);
238
+ }
239
+ this.known.set(file.path, { hash, size: file.size, mtimeMs: file.mtimeMs, mirrored });
240
+ return changed;
241
+ }
113
242
  commit(_reason) {
114
243
  return this.serialize(async () => {
115
- var _a;
116
- const files = [];
117
- let size = 0;
118
- const walk = async (relative) => {
119
- const entries = await node_fs_1.promises.readdir(node_path_1.default.join(this.dir, relative), { withFileTypes: true });
120
- entries.sort((a, b) => a.name.localeCompare(b.name));
121
- for (const entry of entries) {
122
- const name = relative ? `${relative}/${entry.name}` : entry.name;
123
- if (excluded(name))
124
- continue;
125
- if (!validPath(name))
126
- throw new Error(`Unsupported snapshot path: ${name}`);
127
- if (entry.isDirectory())
128
- await walk(name);
129
- else if (entry.isFile()) {
130
- const handle = await node_fs_1.promises.open(node_path_1.default.join(this.dir, name), node_fs_1.constants.O_RDONLY | node_fs_1.constants.O_NOFOLLOW);
131
- try {
132
- const stat = await handle.stat();
133
- size += Math.ceil(stat.size / 3) * 4 + name.length + 100;
134
- if (size > exports.MAX_SESSION_SNAPSHOT_BYTES)
135
- throw new Error('Session snapshot exceeds size limit');
136
- files.push({ path: name, content: (await handle.readFile()).toString('base64'), executable: Boolean(stat.mode & 0o111) });
137
- }
138
- finally {
139
- await handle.close();
140
- }
141
- }
142
- }
143
- };
144
- await walk('');
145
- const body = JSON.stringify({ version: 1, files });
146
- if (Buffer.byteLength(body) > exports.MAX_SESSION_SNAPSHOT_BYTES)
147
- throw new Error('Session snapshot exceeds size limit');
148
- const hash = (0, node_crypto_1.createHash)('sha256').update(body).digest('hex');
149
- if (hash === this.lastHash)
244
+ await (0, workload_1.makeWorkloadDir)(node_path_1.default.join(this.dir, '.builder'));
245
+ let files = await this.walk();
246
+ if (await this.recordExecutables(files))
247
+ files = await this.walk();
248
+ let changed = false;
249
+ await inPool(files, async (file) => {
250
+ if (await this.save(file))
251
+ changed = true;
252
+ });
253
+ // Only what this guest knows was there: a file someone added meanwhile is never touched.
254
+ const present = new Set(files.map((file) => file.path));
255
+ await inPool([...this.known].filter(([relative]) => !present.has(relative)), async ([relative, file]) => {
256
+ // Live sync already told the session about a mirrored file.
257
+ if (!file.mirrored)
258
+ await this.request('DELETE', fileRoute(relative));
259
+ this.known.delete(relative);
260
+ changed = true;
261
+ });
262
+ await this.saveMarker();
263
+ if (!changed)
150
264
  return undefined;
151
- const response = await this.request('PUT', body);
152
- await ((_a = response.body) === null || _a === void 0 ? void 0 : _a.cancel());
153
- this.lastHash = hash; // A failed upload must be retried even when files have not changed.
154
- return hash;
265
+ return sha256([...this.known].sort(([a], [b]) => a.localeCompare(b)).map(([relative, file]) => `${relative}\0${file.hash}`).join('\n'));
155
266
  });
156
267
  }
157
268
  }
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot-sync.js","sourceRoot":"","sources":["../../src/persistence/snapshot-sync.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"snapshot-sync.js","sourceRoot":"","sources":["../../src/persistence/snapshot-sync.ts"],"names":[],"mappings":"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"}
@@ -10,34 +10,49 @@ const node_path_1 = __importDefault(require("node:path"));
10
10
  const node_test_1 = require("node:test");
11
11
  const snapshot_sync_1 = require("./snapshot-sync");
12
12
  const URL = 'https://git.test/workspaces/5c5ad0ca633de27c588a5bb1/6ad5fd18a798fd253b05d5d2';
13
- /** The git service's /workspaces endpoint: one stored snapshot, replaced on every PUT. */
13
+ const BINARY = Buffer.from([0x89, 0x50, 0x00, 0xff, 0x01]);
14
+ /** The git service's /workspaces routes over an in-memory session folder. */
14
15
  function storageService() {
15
- const service = { stored: undefined, puts: 0, gets: 0, failPuts: 0 };
16
+ const service = {
17
+ files: new Map(),
18
+ requests: [],
19
+ failPuts: 0,
20
+ };
16
21
  node_test_1.mock.method(globalThis, 'fetch', async (url, init) => {
17
- strict_1.default.equal(url, URL);
22
+ strict_1.default.ok(url.startsWith(URL));
18
23
  strict_1.default.equal(init.headers.Authorization, 'Bearer session-token');
19
- if (init.method === 'PUT') {
20
- service.puts += 1;
21
- if (service.failPuts > 0) {
22
- service.failPuts -= 1;
23
- return new Response(null, { status: 503 });
24
- }
25
- service.stored = String(init.body);
24
+ const route = url.slice(URL.length);
25
+ service.requests.push(`${init.method} ${route}`);
26
+ if (route === '/files')
27
+ return Response.json({ files: [...service.files].map(([file, data]) => ({ path: file, size: data.length })) });
28
+ const file = decodeURIComponent(route.slice('/files/'.length));
29
+ if (init.method === 'GET') {
30
+ const data = service.files.get(file);
31
+ return data ? new Response(new Uint8Array(data)) : new Response(null, { status: 404 });
32
+ }
33
+ if (init.method === 'DELETE') {
34
+ service.files.delete(file);
26
35
  return new Response(null, { status: 204 });
27
36
  }
28
- service.gets += 1;
29
- return service.stored ? new Response(service.stored) : new Response(null, { status: 404 });
37
+ if (service.failPuts > 0) {
38
+ service.failPuts -= 1;
39
+ return new Response(null, { status: 503 });
40
+ }
41
+ service.files.set(file, Buffer.from(init.body));
42
+ return new Response(null, { status: 204 });
30
43
  });
31
44
  return service;
32
45
  }
33
- (0, node_test_1.describe)('session workspace snapshots', () => {
46
+ (0, node_test_1.describe)('a session workspace kept as files in its folder', () => {
34
47
  let root;
35
48
  const sync = (vm) => new snapshot_sync_1.SessionStorageSync({ url: URL, token: 'session-token', dir: node_path_1.default.join(root, vm) });
36
49
  const write = async (vm, relative, content, mode = 0o644) => {
37
50
  const file = node_path_1.default.join(root, vm, relative);
38
51
  await node_fs_1.promises.mkdir(node_path_1.default.dirname(file), { recursive: true });
39
- await node_fs_1.promises.writeFile(file, content, { mode });
52
+ await node_fs_1.promises.writeFile(file, content);
53
+ await node_fs_1.promises.chmod(file, mode);
40
54
  };
55
+ const puts = (service) => service.requests.filter((request) => request.startsWith('PUT'));
41
56
  (0, node_test_1.beforeEach)(async () => {
42
57
  root = await node_fs_1.promises.mkdtemp(node_path_1.default.join(node_os_1.default.tmpdir(), 'session-storage-'));
43
58
  });
@@ -45,52 +60,155 @@ function storageService() {
45
60
  node_test_1.mock.restoreAll();
46
61
  await node_fs_1.promises.rm(root, { recursive: true, force: true });
47
62
  });
48
- (0, node_test_1.it)('restores the workspace on a new VM without Git or bulky local-only files', async () => {
63
+ (0, node_test_1.it)('stores real files, and a new VM gets them back byte for byte, executable bits included', async () => {
49
64
  const service = storageService();
50
65
  const original = sync('original-vm');
51
66
  strict_1.default.equal(await original.restore(), false);
52
67
  await write('original-vm', '.builder/conversation.json', '{"version":1}');
53
68
  await write('original-vm', 'research/findings.md', '# Three filings');
69
+ await write('original-vm', 'report.png', BINARY);
54
70
  await write('original-vm', 'bin/run.sh', 'echo hi', 0o755);
55
71
  await write('original-vm', '.git/config', '[core]');
56
72
  await write('original-vm', 'node_modules/pkg/index.js', 'x');
57
73
  await write('original-vm', 'data/attachments/filing.pdf', 'pdf');
74
+ await write('original-vm', '.builder/logs/app.log', 'log');
58
75
  strict_1.default.ok(await original.commit('checkpoint: turn'));
59
- const snapshot = JSON.parse(service.stored);
60
- strict_1.default.deepEqual(snapshot.files.map((file) => file.path).sort(), ['.builder/conversation.json', 'bin/run.sh', 'research/findings.md']);
76
+ strict_1.default.deepEqual([...service.files.keys()].sort(), [
77
+ '.builder/executables.json', 'bin/run.sh', 'report.png', 'research/findings.md',
78
+ ]);
79
+ strict_1.default.deepEqual(service.files.get('report.png'), BINARY, 'stored as itself, not encoded');
61
80
  const replacement = sync('replacement-vm');
62
81
  strict_1.default.equal(await replacement.restore(), true);
63
82
  strict_1.default.equal(await node_fs_1.promises.readFile(node_path_1.default.join(root, 'replacement-vm/research/findings.md'), 'utf8'), '# Three filings');
83
+ strict_1.default.deepEqual(await node_fs_1.promises.readFile(node_path_1.default.join(root, 'replacement-vm/report.png')), BINARY);
64
84
  strict_1.default.equal((await node_fs_1.promises.stat(node_path_1.default.join(root, 'replacement-vm/bin/run.sh'))).mode & 0o111, 0o111);
85
+ strict_1.default.equal((await node_fs_1.promises.stat(node_path_1.default.join(root, 'replacement-vm/report.png'))).mode & 0o111, 0);
65
86
  await strict_1.default.rejects(node_fs_1.promises.stat(node_path_1.default.join(root, 'replacement-vm/.git')));
66
87
  });
67
- (0, node_test_1.it)('keeps uncheckpointed local edits when the agent restarts on the same disk', async () => {
88
+ (0, node_test_1.it)('starts a session that only ever had stored files with those files', async () => {
89
+ const service = storageService();
90
+ service.files.set('index.html', Buffer.from('<h1>published</h1>'));
91
+ strict_1.default.equal(await sync('vm').restore(), true);
92
+ strict_1.default.equal(await node_fs_1.promises.readFile(node_path_1.default.join(root, 'vm/index.html'), 'utf8'), '<h1>published</h1>');
93
+ });
94
+ (0, node_test_1.it)('uploads only what changed', async () => {
95
+ var _a;
96
+ const service = storageService();
97
+ const vm = sync('vm');
98
+ await vm.restore();
99
+ await write('vm', 'a.txt', 'a');
100
+ await write('vm', 'b.txt', 'b');
101
+ strict_1.default.ok(await vm.commit('checkpoint'));
102
+ service.requests.length = 0;
103
+ strict_1.default.equal(await vm.commit('checkpoint'), undefined, 'nothing changed');
104
+ strict_1.default.deepEqual(puts(service), []);
105
+ await write('vm', 'b.txt', 'b2');
106
+ strict_1.default.ok(await vm.commit('checkpoint'));
107
+ strict_1.default.deepEqual(puts(service), ['PUT /files/b.txt']);
108
+ strict_1.default.equal((_a = service.files.get('b.txt')) === null || _a === void 0 ? void 0 : _a.toString(), 'b2');
109
+ });
110
+ (0, node_test_1.it)('does not re-upload a restored file, nor one touched without changing', async () => {
111
+ const service = storageService();
112
+ service.files.set('a.png', BINARY);
113
+ const vm = sync('vm');
114
+ await vm.restore();
115
+ service.requests.length = 0;
116
+ await vm.commit('checkpoint');
117
+ strict_1.default.deepEqual(puts(service), ['PUT /files/.builder/executables.json']);
118
+ service.requests.length = 0;
119
+ await node_fs_1.promises.utimes(node_path_1.default.join(root, 'vm/a.png'), new Date(), new Date(Date.now() + 5000));
120
+ strict_1.default.equal(await vm.commit('checkpoint'), undefined);
121
+ strict_1.default.deepEqual(puts(service), []);
122
+ });
123
+ (0, node_test_1.it)('leaves text the session has confirmed to live sync, and uploads what it has not', async () => {
124
+ var _a;
125
+ const service = storageService();
126
+ const vm = sync('vm');
127
+ await vm.restore();
128
+ const confirmed = new Set(['synced.md']);
129
+ vm.setMirror((file, content) => {
130
+ strict_1.default.equal(content.toString(), file === 'synced.md' ? 'done' : 'edit not acknowledged');
131
+ return confirmed.has(file);
132
+ });
133
+ await write('vm', 'synced.md', 'done');
134
+ await write('vm', 'unconfirmed.md', 'edit not acknowledged');
135
+ await write('vm', 'photo.png', BINARY);
136
+ await write('vm', 'dist/bundle.js', 'x');
137
+ await vm.commit('checkpoint');
138
+ strict_1.default.equal(service.files.has('synced.md'), false);
139
+ strict_1.default.equal((_a = service.files.get('unconfirmed.md')) === null || _a === void 0 ? void 0 : _a.toString(), 'edit not acknowledged', 'a lost connection never loses an edit');
140
+ strict_1.default.deepEqual(service.files.get('photo.png'), BINARY);
141
+ strict_1.default.equal(service.files.has('dist/bundle.js'), true, 'build output is not mirrored');
142
+ });
143
+ (0, node_test_1.it)('deletes only files it knows, never one someone added meanwhile', async () => {
144
+ const service = storageService();
145
+ service.files.set('old.png', BINARY);
146
+ const vm = sync('vm');
147
+ await vm.restore();
148
+ service.files.set('added-while-running.png', BINARY);
149
+ await node_fs_1.promises.rm(node_path_1.default.join(root, 'vm/old.png'));
150
+ strict_1.default.ok(await vm.commit('checkpoint'));
151
+ strict_1.default.equal(service.files.has('old.png'), false);
152
+ strict_1.default.equal(service.files.has('added-while-running.png'), true);
153
+ });
154
+ (0, node_test_1.it)('leaves a deleted mirrored file to live sync, which removes its document too', async () => {
155
+ const service = storageService();
156
+ service.files.set('notes.md', Buffer.from('text'));
157
+ const vm = sync('vm');
158
+ await vm.restore();
159
+ await node_fs_1.promises.rm(node_path_1.default.join(root, 'vm/notes.md'));
160
+ await vm.commit('checkpoint');
161
+ strict_1.default.equal(service.files.has('notes.md'), true);
162
+ strict_1.default.deepEqual(service.requests.filter((request) => request.startsWith('DELETE')), []);
163
+ });
164
+ (0, node_test_1.it)('remembers what it knows when the agent restarts on the same disk, keeping local edits', async () => {
68
165
  const service = storageService();
69
166
  const first = sync('vm');
70
167
  await first.restore();
168
+ await write('vm', 'photo.png', BINARY);
71
169
  await write('vm', 'notes.md', 'v1');
72
170
  await first.commit('checkpoint');
73
171
  await write('vm', 'notes.md', 'v2 (not checkpointed)');
74
- strict_1.default.equal(await sync('vm').restore(), true);
75
- strict_1.default.equal(service.gets, 1, 'the retained disk is not overwritten from storage');
172
+ service.requests.length = 0;
173
+ const second = sync('vm');
174
+ strict_1.default.equal(await second.restore(), true);
175
+ strict_1.default.deepEqual(service.requests, [], 'the retained disk is not overwritten from storage');
76
176
  strict_1.default.equal(await node_fs_1.promises.readFile(node_path_1.default.join(root, 'vm/notes.md'), 'utf8'), 'v2 (not checkpointed)');
177
+ await node_fs_1.promises.rm(node_path_1.default.join(root, 'vm/photo.png'));
178
+ await second.commit('checkpoint');
179
+ strict_1.default.equal(service.files.has('photo.png'), false);
77
180
  });
78
- (0, node_test_1.it)('skips unchanged snapshots but retries one whose upload failed', async () => {
181
+ (0, node_test_1.it)('retries an upload that failed', async () => {
182
+ var _a;
79
183
  const service = storageService();
80
184
  const vm = sync('vm');
81
185
  await vm.restore();
82
186
  await write('vm', 'notes.md', 'v1');
83
- service.failPuts = 1;
187
+ service.failPuts = 2;
84
188
  await strict_1.default.rejects(vm.commit('checkpoint'), /Session storage PUT failed \(503\)/);
85
189
  strict_1.default.ok(await vm.commit('checkpoint'));
190
+ strict_1.default.equal((_a = service.files.get('notes.md')) === null || _a === void 0 ? void 0 : _a.toString(), 'v1');
86
191
  strict_1.default.equal(await vm.commit('checkpoint'), undefined);
87
- strict_1.default.equal(service.puts, 2);
88
192
  });
89
- (0, node_test_1.it)('refuses a snapshot that would write outside the workspace, before writing anything', async () => {
193
+ (0, node_test_1.it)('skips a file over the limit instead of failing the whole checkpoint', async () => {
194
+ const service = storageService();
195
+ const warn = node_test_1.mock.method(console, 'warn', () => { });
196
+ const vm = sync('vm');
197
+ await vm.restore();
198
+ await write('vm', 'small.txt', 'ok');
199
+ const file = await node_fs_1.promises.open(node_path_1.default.join(root, 'vm/huge.bin'), 'w');
200
+ await file.truncate(64 * 1024 * 1024 + 1);
201
+ await file.close();
202
+ await vm.commit('checkpoint');
203
+ strict_1.default.equal(service.files.has('small.txt'), true);
204
+ strict_1.default.equal(service.files.has('huge.bin'), false);
205
+ strict_1.default.match(String(warn.mock.calls[0].arguments[0]), /huge\.bin/);
206
+ });
207
+ (0, node_test_1.it)('refuses paths that would write outside the workspace, before writing anything', async () => {
90
208
  const service = storageService();
91
- const file = (name) => ({ path: name, content: Buffer.from('x').toString('base64'), executable: false });
92
- service.stored = JSON.stringify({ version: 1, files: [file('ok.md'), file('../escape.md')] });
93
- await strict_1.default.rejects(sync('vm').restore(), /Invalid session snapshot file/);
209
+ service.files.set('ok.md', Buffer.from('x'));
210
+ service.files.set('../escape.md', Buffer.from('x'));
211
+ await strict_1.default.rejects(sync('vm').restore(), /Invalid session file/);
94
212
  await strict_1.default.rejects(node_fs_1.promises.stat(node_path_1.default.join(root, 'vm/ok.md')));
95
213
  await strict_1.default.rejects(node_fs_1.promises.stat(node_path_1.default.join(root, 'escape.md')));
96
214
  });