@multiplayer-app/agent 0.1.20 → 0.1.22

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 (298) 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/build-log.d.ts +14 -0
  29. package/dist/app/build-log.d.ts.map +1 -0
  30. package/dist/app/build-log.js +173 -0
  31. package/dist/app/build-log.js.map +1 -0
  32. package/dist/app/build-log.test.d.ts +2 -0
  33. package/dist/app/build-log.test.d.ts.map +1 -0
  34. package/dist/app/build-log.test.js +255 -0
  35. package/dist/app/build-log.test.js.map +1 -0
  36. package/dist/app/config.d.ts +196 -0
  37. package/dist/app/config.d.ts.map +1 -0
  38. package/dist/app/config.js +362 -0
  39. package/dist/app/config.js.map +1 -0
  40. package/dist/app/config.test.d.ts +2 -0
  41. package/dist/app/config.test.d.ts.map +1 -0
  42. package/dist/app/config.test.js +224 -0
  43. package/dist/app/config.test.js.map +1 -0
  44. package/dist/app/detect.d.ts +68 -0
  45. package/dist/app/detect.d.ts.map +1 -0
  46. package/dist/app/detect.js +449 -0
  47. package/dist/app/detect.js.map +1 -0
  48. package/dist/app/detect.test.d.ts +2 -0
  49. package/dist/app/detect.test.d.ts.map +1 -0
  50. package/dist/app/detect.test.js +267 -0
  51. package/dist/app/detect.test.js.map +1 -0
  52. package/dist/app/env.d.ts +5 -0
  53. package/dist/app/env.d.ts.map +1 -0
  54. package/dist/app/env.js +22 -0
  55. package/dist/app/env.js.map +1 -0
  56. package/dist/app/functions-cli.d.ts +3 -0
  57. package/dist/app/functions-cli.d.ts.map +1 -0
  58. package/dist/app/functions-cli.js +27 -0
  59. package/dist/app/functions-cli.js.map +1 -0
  60. package/dist/app/functions-host.d.ts +15 -0
  61. package/dist/app/functions-host.d.ts.map +1 -0
  62. package/dist/app/functions-host.js +276 -0
  63. package/dist/app/functions-host.js.map +1 -0
  64. package/dist/app/functions-host.test.d.ts +2 -0
  65. package/dist/app/functions-host.test.d.ts.map +1 -0
  66. package/dist/app/functions-host.test.js +117 -0
  67. package/dist/app/functions-host.test.js.map +1 -0
  68. package/dist/app/functions-routes.d.ts +23 -0
  69. package/dist/app/functions-routes.d.ts.map +1 -0
  70. package/dist/app/functions-routes.js +85 -0
  71. package/dist/app/functions-routes.js.map +1 -0
  72. package/dist/app/functions-routes.test.d.ts +2 -0
  73. package/dist/app/functions-routes.test.d.ts.map +1 -0
  74. package/dist/app/functions-routes.test.js +40 -0
  75. package/dist/app/functions-routes.test.js.map +1 -0
  76. package/dist/app/manifest.d.ts +17 -0
  77. package/dist/app/manifest.d.ts.map +1 -0
  78. package/dist/app/manifest.js +64 -0
  79. package/dist/app/manifest.js.map +1 -0
  80. package/dist/app/manifest.test.d.ts +2 -0
  81. package/dist/app/manifest.test.d.ts.map +1 -0
  82. package/dist/app/manifest.test.js +173 -0
  83. package/dist/app/manifest.test.js.map +1 -0
  84. package/dist/app/release-artifacts.d.ts +43 -0
  85. package/dist/app/release-artifacts.d.ts.map +1 -0
  86. package/dist/app/release-artifacts.js +239 -0
  87. package/dist/app/release-artifacts.js.map +1 -0
  88. package/dist/app/release-artifacts.test.d.ts +2 -0
  89. package/dist/app/release-artifacts.test.d.ts.map +1 -0
  90. package/dist/app/release-artifacts.test.js +326 -0
  91. package/dist/app/release-artifacts.test.js.map +1 -0
  92. package/dist/app/route-pattern.d.ts +23 -0
  93. package/dist/app/route-pattern.d.ts.map +1 -0
  94. package/dist/app/route-pattern.js +339 -0
  95. package/dist/app/route-pattern.js.map +1 -0
  96. package/dist/app/route-pattern.test.d.ts +2 -0
  97. package/dist/app/route-pattern.test.d.ts.map +1 -0
  98. package/dist/app/route-pattern.test.js +187 -0
  99. package/dist/app/route-pattern.test.js.map +1 -0
  100. package/dist/app/rules.d.ts +61 -0
  101. package/dist/app/rules.d.ts.map +1 -0
  102. package/dist/app/rules.js +90 -0
  103. package/dist/app/rules.js.map +1 -0
  104. package/dist/app/rules.test.d.ts +2 -0
  105. package/dist/app/rules.test.d.ts.map +1 -0
  106. package/dist/app/rules.test.js +69 -0
  107. package/dist/app/rules.test.js.map +1 -0
  108. package/dist/app/runner.d.ts +109 -0
  109. package/dist/app/runner.d.ts.map +1 -0
  110. package/dist/app/runner.js +429 -0
  111. package/dist/app/runner.js.map +1 -0
  112. package/dist/app/site.d.ts +73 -0
  113. package/dist/app/site.d.ts.map +1 -0
  114. package/dist/app/site.js +161 -0
  115. package/dist/app/site.js.map +1 -0
  116. package/dist/app/site.test.d.ts +2 -0
  117. package/dist/app/site.test.d.ts.map +1 -0
  118. package/dist/app/site.test.js +291 -0
  119. package/dist/app/site.test.js.map +1 -0
  120. package/dist/app/static-server.d.ts +20 -0
  121. package/dist/app/static-server.d.ts.map +1 -0
  122. package/dist/app/static-server.js +145 -0
  123. package/dist/app/static-server.js.map +1 -0
  124. package/dist/persistence/conversation-store.d.ts +21 -0
  125. package/dist/persistence/conversation-store.d.ts.map +1 -0
  126. package/dist/persistence/conversation-store.js +59 -0
  127. package/dist/persistence/conversation-store.js.map +1 -0
  128. package/dist/persistence/conversation-store.test.d.ts +2 -0
  129. package/dist/persistence/conversation-store.test.d.ts.map +1 -0
  130. package/dist/persistence/conversation-store.test.js +98 -0
  131. package/dist/persistence/conversation-store.test.js.map +1 -0
  132. package/dist/persistence/git-sync.d.ts +14 -1
  133. package/dist/persistence/git-sync.d.ts.map +1 -1
  134. package/dist/persistence/git-sync.js +73 -17
  135. package/dist/persistence/git-sync.js.map +1 -1
  136. package/dist/persistence/git-sync.test.js +155 -6
  137. package/dist/persistence/git-sync.test.js.map +1 -1
  138. package/dist/persistence/snapshot-sync.d.ts +19 -2
  139. package/dist/persistence/snapshot-sync.d.ts.map +1 -1
  140. package/dist/persistence/snapshot-sync.js +194 -83
  141. package/dist/persistence/snapshot-sync.js.map +1 -1
  142. package/dist/persistence/snapshot-sync.test.js +145 -27
  143. package/dist/persistence/snapshot-sync.test.js.map +1 -1
  144. package/dist/persistence/workspace.d.ts +3 -0
  145. package/dist/persistence/workspace.d.ts.map +1 -1
  146. package/dist/persistence/workspace.js +1 -0
  147. package/dist/persistence/workspace.js.map +1 -1
  148. package/dist/research/extract-texts.d.ts.map +1 -1
  149. package/dist/research/extract-texts.js +6 -13
  150. package/dist/research/extract-texts.js.map +1 -1
  151. package/dist/research/filingramp/attachment-tools.d.ts.map +1 -1
  152. package/dist/research/filingramp/attachment-tools.js +7 -4
  153. package/dist/research/filingramp/attachment-tools.js.map +1 -1
  154. package/dist/research/filingramp/shared.d.ts.map +1 -1
  155. package/dist/research/filingramp/shared.js +5 -5
  156. package/dist/research/filingramp/shared.js.map +1 -1
  157. package/dist/runtime/app-mode.d.ts +10 -0
  158. package/dist/runtime/app-mode.d.ts.map +1 -0
  159. package/dist/runtime/app-mode.js +172 -0
  160. package/dist/runtime/app-mode.js.map +1 -0
  161. package/dist/runtime/app-mode.test.d.ts +2 -0
  162. package/dist/runtime/app-mode.test.d.ts.map +1 -0
  163. package/dist/runtime/app-mode.test.js +130 -0
  164. package/dist/runtime/app-mode.test.js.map +1 -0
  165. package/dist/runtime/app-rehearsal.d.ts +2 -0
  166. package/dist/runtime/app-rehearsal.d.ts.map +1 -0
  167. package/dist/runtime/app-rehearsal.js +56 -0
  168. package/dist/runtime/app-rehearsal.js.map +1 -0
  169. package/dist/runtime/build-mode.d.ts +18 -0
  170. package/dist/runtime/build-mode.d.ts.map +1 -0
  171. package/dist/runtime/build-mode.js +108 -0
  172. package/dist/runtime/build-mode.js.map +1 -0
  173. package/dist/runtime/build-mode.test.d.ts +2 -0
  174. package/dist/runtime/build-mode.test.d.ts.map +1 -0
  175. package/dist/runtime/build-mode.test.js +159 -0
  176. package/dist/runtime/build-mode.test.js.map +1 -0
  177. package/dist/runtime/cli.js +7 -2
  178. package/dist/runtime/cli.js.map +1 -1
  179. package/dist/runtime/config.d.ts +4 -0
  180. package/dist/runtime/config.d.ts.map +1 -1
  181. package/dist/runtime/config.js +13 -2
  182. package/dist/runtime/config.js.map +1 -1
  183. package/dist/runtime/guest-server.d.ts +3 -0
  184. package/dist/runtime/guest-server.d.ts.map +1 -0
  185. package/dist/runtime/{lambda-microvm.js → guest-server.js} +49 -18
  186. package/dist/runtime/guest-server.js.map +1 -0
  187. package/dist/runtime/image-hooks.d.ts +5 -0
  188. package/dist/runtime/image-hooks.d.ts.map +1 -0
  189. package/dist/runtime/image-hooks.js +68 -0
  190. package/dist/runtime/image-hooks.js.map +1 -0
  191. package/dist/runtime/image-hooks.test.d.ts +2 -0
  192. package/dist/runtime/image-hooks.test.d.ts.map +1 -0
  193. package/dist/runtime/image-hooks.test.js +74 -0
  194. package/dist/runtime/image-hooks.test.js.map +1 -0
  195. package/dist/runtime/index.d.ts +8 -3
  196. package/dist/runtime/index.d.ts.map +1 -1
  197. package/dist/runtime/index.js +53 -35
  198. package/dist/runtime/index.js.map +1 -1
  199. package/dist/runtime/listening-ports.d.ts +13 -0
  200. package/dist/runtime/listening-ports.d.ts.map +1 -0
  201. package/dist/runtime/listening-ports.js +78 -0
  202. package/dist/runtime/listening-ports.js.map +1 -0
  203. package/dist/runtime/listening-ports.test.d.ts +2 -0
  204. package/dist/runtime/listening-ports.test.d.ts.map +1 -0
  205. package/dist/runtime/listening-ports.test.js +39 -0
  206. package/dist/runtime/listening-ports.test.js.map +1 -0
  207. package/dist/runtime/preview-proxy.d.ts +56 -0
  208. package/dist/runtime/preview-proxy.d.ts.map +1 -0
  209. package/dist/runtime/preview-proxy.js +302 -0
  210. package/dist/runtime/preview-proxy.js.map +1 -0
  211. package/dist/runtime/preview-proxy.test.d.ts +2 -0
  212. package/dist/runtime/preview-proxy.test.d.ts.map +1 -0
  213. package/dist/runtime/preview-proxy.test.js +122 -0
  214. package/dist/runtime/preview-proxy.test.js.map +1 -0
  215. package/dist/runtime/session-mode.d.ts +3 -0
  216. package/dist/runtime/session-mode.d.ts.map +1 -0
  217. package/dist/runtime/session-mode.js +60 -0
  218. package/dist/runtime/session-mode.js.map +1 -0
  219. package/dist/runtime/workload.d.ts +44 -0
  220. package/dist/runtime/workload.d.ts.map +1 -0
  221. package/dist/runtime/workload.js +222 -0
  222. package/dist/runtime/workload.js.map +1 -0
  223. package/dist/runtime/workload.test.d.ts +2 -0
  224. package/dist/runtime/workload.test.d.ts.map +1 -0
  225. package/dist/runtime/workload.test.js +235 -0
  226. package/dist/runtime/workload.test.js.map +1 -0
  227. package/dist/session/conversation.d.ts +3 -2
  228. package/dist/session/conversation.d.ts.map +1 -1
  229. package/dist/session/conversation.js +11 -7
  230. package/dist/session/conversation.js.map +1 -1
  231. package/dist/session/conversation.test.js +2 -3
  232. package/dist/session/conversation.test.js.map +1 -1
  233. package/dist/session/runtime.d.ts +16 -3
  234. package/dist/session/runtime.d.ts.map +1 -1
  235. package/dist/session/runtime.js +80 -13
  236. package/dist/session/runtime.js.map +1 -1
  237. package/dist/session/runtime.test.js +18 -7
  238. package/dist/session/runtime.test.js.map +1 -1
  239. package/dist/session/tools.d.ts.map +1 -1
  240. package/dist/session/tools.js +3 -3
  241. package/dist/session/tools.js.map +1 -1
  242. package/dist/task/loop.d.ts.map +1 -1
  243. package/dist/task/loop.js +6 -4
  244. package/dist/task/loop.js.map +1 -1
  245. package/dist/tools/exec-tools.d.ts +12 -0
  246. package/dist/tools/exec-tools.d.ts.map +1 -1
  247. package/dist/tools/exec-tools.js +46 -3
  248. package/dist/tools/exec-tools.js.map +1 -1
  249. package/dist/tools/exec-tools.test.d.ts +2 -0
  250. package/dist/tools/exec-tools.test.d.ts.map +1 -0
  251. package/dist/tools/exec-tools.test.js +48 -0
  252. package/dist/tools/exec-tools.test.js.map +1 -0
  253. package/dist/tools/fs-tools.d.ts.map +1 -1
  254. package/dist/tools/fs-tools.js +5 -5
  255. package/dist/tools/fs-tools.js.map +1 -1
  256. package/dist/transport/link.d.ts.map +1 -1
  257. package/dist/transport/link.js +16 -5
  258. package/dist/transport/link.js.map +1 -1
  259. package/dist/transport/link.test.js +24 -0
  260. package/dist/transport/link.test.js.map +1 -1
  261. package/dist/transport/protocol.d.ts +215 -3
  262. package/dist/transport/protocol.d.ts.map +1 -1
  263. package/dist/transport/protocol.js +163 -7
  264. package/dist/transport/protocol.js.map +1 -1
  265. package/dist/transport/protocol.test.js +41 -0
  266. package/dist/transport/protocol.test.js.map +1 -1
  267. package/dist/workspace-sync/eligibility.d.ts +14 -0
  268. package/dist/workspace-sync/eligibility.d.ts.map +1 -0
  269. package/dist/workspace-sync/eligibility.js +53 -0
  270. package/dist/workspace-sync/eligibility.js.map +1 -0
  271. package/dist/workspace-sync/merge.d.ts +15 -0
  272. package/dist/workspace-sync/merge.d.ts.map +1 -0
  273. package/dist/workspace-sync/merge.js +66 -0
  274. package/dist/workspace-sync/merge.js.map +1 -0
  275. package/dist/workspace-sync/merge.test.d.ts +2 -0
  276. package/dist/workspace-sync/merge.test.d.ts.map +1 -0
  277. package/dist/workspace-sync/merge.test.js +28 -0
  278. package/dist/workspace-sync/merge.test.js.map +1 -0
  279. package/dist/workspace-sync/workspace-sync.d.ts +48 -0
  280. package/dist/workspace-sync/workspace-sync.d.ts.map +1 -0
  281. package/dist/workspace-sync/workspace-sync.js +308 -0
  282. package/dist/workspace-sync/workspace-sync.js.map +1 -0
  283. package/dist/workspace-sync/workspace-sync.test.d.ts +2 -0
  284. package/dist/workspace-sync/workspace-sync.test.d.ts.map +1 -0
  285. package/dist/workspace-sync/workspace-sync.test.js +111 -0
  286. package/dist/workspace-sync/workspace-sync.test.js.map +1 -0
  287. package/dist/workspace-sync/write-drafts.d.ts +24 -0
  288. package/dist/workspace-sync/write-drafts.d.ts.map +1 -0
  289. package/dist/workspace-sync/write-drafts.js +87 -0
  290. package/dist/workspace-sync/write-drafts.js.map +1 -0
  291. package/dist/workspace-sync/write-drafts.test.d.ts +2 -0
  292. package/dist/workspace-sync/write-drafts.test.d.ts.map +1 -0
  293. package/dist/workspace-sync/write-drafts.test.js +36 -0
  294. package/dist/workspace-sync/write-drafts.test.js.map +1 -0
  295. package/package.json +12 -2
  296. package/dist/runtime/lambda-microvm.d.ts +0 -3
  297. package/dist/runtime/lambda-microvm.d.ts.map +0 -1
  298. package/dist/runtime/lambda-microvm.js.map +0 -1
@@ -0,0 +1,308 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WorkspaceSync = void 0;
7
+ // Workspace live sync, the guest's half: every text file in the workspace is mirrored into the
8
+ // session as it changes, however it changed (the agent's tools, a shell command, an SSH user), and
9
+ // people's edits to the session's copy come back into the file. The platform holds the session's
10
+ // copy as a collaborative document (services/api/src/services/sessions/workspace-sync.service.ts)
11
+ // and applies each change as a character diff, so open editors update in place.
12
+ //
13
+ // Each file has a version both sides agreed on, named by its workspaceFileHash. A change is sent
14
+ // with the hash it was built on; the platform applies it when its copy is still that version,
15
+ // and otherwise sends its copy back (file_state), which is merged here, where the agreed text is
16
+ // known, and sent again. The platform keeps no file text of its own, only the agreed hash.
17
+ const fs_1 = require("fs");
18
+ const path_1 = __importDefault(require("path"));
19
+ const workload_1 = require("../runtime/workload");
20
+ const protocol_1 = require("../transport/protocol");
21
+ const eligibility_1 = require("./eligibility");
22
+ const merge_1 = require("./merge");
23
+ // A save is often several writes (truncate, write, rename): wait for the last one.
24
+ const CHANGE_DEBOUNCE_MS = 120;
25
+ // Watch events can be missed (a directory filled before its watcher started, an overflowing
26
+ // inotify queue): a full rescan now and then catches up.
27
+ const RESCAN_INTERVAL_MS = 30000;
28
+ const MAX_UNCONFIRMED_VERSIONS = 8;
29
+ function remember(sent, hash, content) {
30
+ sent.delete(hash);
31
+ sent.set(hash, content);
32
+ while (sent.size > MAX_UNCONFIRMED_VERSIONS)
33
+ sent.delete(sent.keys().next().value);
34
+ }
35
+ class WorkspaceSync {
36
+ constructor(dir, send) {
37
+ this.dir = dir;
38
+ this.send = send;
39
+ this.files = new Map();
40
+ this.timers = new Map();
41
+ this.watchers = new Map();
42
+ this.queues = new Map();
43
+ this.stopped = false;
44
+ }
45
+ /** Mirrors every file there is now, then follows changes until stop(). */
46
+ async start() {
47
+ await this.rescan();
48
+ this.rescanTimer = setInterval(() => {
49
+ this.rescan().catch((error) => console.error('[sync] rescan failed:', error));
50
+ }, RESCAN_INTERVAL_MS);
51
+ this.rescanTimer.unref();
52
+ }
53
+ stop() {
54
+ this.stopped = true;
55
+ if (this.rescanTimer)
56
+ clearInterval(this.rescanTimer);
57
+ for (const timer of this.timers.values())
58
+ clearTimeout(timer);
59
+ this.timers.clear();
60
+ for (const watcher of this.watchers.values())
61
+ watcher.close();
62
+ this.watchers.clear();
63
+ }
64
+ /** Whether the session has confirmed exactly this version of `file`, so storage already holds it. */
65
+ isConfirmed(file, content) {
66
+ var _a;
67
+ const confirmed = (_a = this.files.get((0, eligibility_1.normalizeSyncPath)(file))) === null || _a === void 0 ? void 0 : _a.confirmed;
68
+ return confirmed !== undefined && confirmed === content.toString('utf8');
69
+ }
70
+ /** Sends what the model has written so far of a file it is still writing (see WriteDraftTracker). */
71
+ draft(file, content) {
72
+ const relative = (0, eligibility_1.normalizeSyncPath)(file);
73
+ if (this.stopped || !(0, eligibility_1.isSyncablePath)(relative) || !this.resolve(relative))
74
+ return;
75
+ if (Buffer.byteLength(content, 'utf8') > eligibility_1.MAX_SYNCED_FILE_BYTES)
76
+ return;
77
+ this.send({ type: 'file_draft', path: relative, content });
78
+ }
79
+ /** Ends drafts: the session's copy becomes whatever is on disk now (or goes, if nothing is). */
80
+ async settle(files) {
81
+ await Promise.all(files.map((file) => {
82
+ const relative = (0, eligibility_1.normalizeSyncPath)(file);
83
+ return this.enqueue(relative, () => this.syncPath(relative, { final: true }));
84
+ }));
85
+ }
86
+ /** Mirrors these files now, without waiting for their watch events (publish_results). */
87
+ async flush(files) {
88
+ await Promise.all(files.map((file) => {
89
+ const relative = (0, eligibility_1.normalizeSyncPath)(file);
90
+ return this.enqueue(relative, () => this.syncPath(relative));
91
+ }));
92
+ }
93
+ /** file_state: people changed the session's copy (content), or it took the guest's version (none). */
94
+ applyState(command) {
95
+ const relative = (0, eligibility_1.normalizeSyncPath)(command.path);
96
+ return this.enqueue(relative, async () => {
97
+ const state = this.files.get(relative);
98
+ const { content } = command;
99
+ if (content === undefined) {
100
+ const text = state === null || state === void 0 ? void 0 : state.sent.get(command.hash);
101
+ if (state && text !== undefined) {
102
+ state.confirmed = text;
103
+ state.sent.delete(command.hash);
104
+ }
105
+ return;
106
+ }
107
+ if (!(0, eligibility_1.isSyncablePath)(relative))
108
+ return;
109
+ const read = await this.read(relative);
110
+ if (read.kind === 'unsyncable' || read.kind === 'unchanged')
111
+ return;
112
+ const disk = read.kind === 'text' ? read.content : undefined;
113
+ // Without an agreed version (a restart, a file new to the guest), the platform already decided
114
+ // its copy is the newer one.
115
+ const base = state === null || state === void 0 ? void 0 : state.confirmed;
116
+ const merged = disk === undefined || base === undefined || disk === base ? content : (0, merge_1.merge3)(base, disk, content);
117
+ if (merged !== disk)
118
+ await this.write(relative, merged);
119
+ const hash = (0, protocol_1.workspaceFileHash)(content);
120
+ this.files.set(relative, { confirmed: content, reported: hash, sent: new Map() });
121
+ // A merge kept a change of the guest's own: that goes up as a change built on the session's copy.
122
+ if (merged === content)
123
+ this.send({ type: 'file_synced', path: relative, hash });
124
+ else
125
+ await this.syncPath(relative);
126
+ });
127
+ }
128
+ /** file_delete: someone deleted the session's copy. */
129
+ applyDelete(file) {
130
+ const relative = (0, eligibility_1.normalizeSyncPath)(file);
131
+ return this.enqueue(relative, async () => {
132
+ this.files.delete(relative);
133
+ const target = (0, eligibility_1.isSyncablePath)(relative) ? this.resolve(relative) : undefined;
134
+ if (target)
135
+ await (0, workload_1.removeWorkloadFile)(target);
136
+ });
137
+ }
138
+ async rescan() {
139
+ const seen = new Set();
140
+ await this.scan('', seen);
141
+ // A file gone without a watch event (its directory removed at once, say).
142
+ for (const relative of this.files.keys())
143
+ if (!seen.has(relative))
144
+ this.schedule(relative);
145
+ }
146
+ async scan(relativeDir, seen) {
147
+ if (this.stopped || !(0, eligibility_1.isWatchedDirectory)(relativeDir))
148
+ return;
149
+ this.watchDirectory(relativeDir);
150
+ let entries;
151
+ try {
152
+ entries = await fs_1.promises.readdir(path_1.default.join(this.dir, relativeDir), { withFileTypes: true });
153
+ }
154
+ catch (_a) {
155
+ return;
156
+ }
157
+ for (const entry of entries) {
158
+ const relative = (0, eligibility_1.normalizeSyncPath)(path_1.default.posix.join(relativeDir, entry.name));
159
+ if (entry.isDirectory()) {
160
+ await this.scan(relative, seen);
161
+ }
162
+ else if (entry.isFile() && (0, eligibility_1.isSyncablePath)(relative)) {
163
+ seen === null || seen === void 0 ? void 0 : seen.add(relative);
164
+ this.schedule(relative);
165
+ }
166
+ }
167
+ }
168
+ /** One watcher per directory, not one recursive watch: excluded trees (node_modules) are never watched. */
169
+ watchDirectory(relativeDir) {
170
+ if (this.stopped || this.watchers.has(relativeDir))
171
+ return;
172
+ try {
173
+ const watcher = (0, fs_1.watch)(path_1.default.join(this.dir, relativeDir), (_event, name) => {
174
+ if (name)
175
+ this.onWatchEvent((0, eligibility_1.normalizeSyncPath)(path_1.default.posix.join(relativeDir, name.toString())));
176
+ });
177
+ watcher.on('error', () => this.unwatch(relativeDir));
178
+ watcher.unref();
179
+ this.watchers.set(relativeDir, watcher);
180
+ }
181
+ catch (_a) {
182
+ // Removed before it could be watched; its parent's event covers it.
183
+ }
184
+ }
185
+ unwatch(relativeDir) {
186
+ for (const [dir, watcher] of this.watchers) {
187
+ if (dir === relativeDir || dir.startsWith(`${relativeDir}/`)) {
188
+ watcher.close();
189
+ this.watchers.delete(dir);
190
+ }
191
+ }
192
+ }
193
+ onWatchEvent(relative) {
194
+ const target = this.resolve(relative);
195
+ if (!target || this.stopped)
196
+ return;
197
+ fs_1.promises.lstat(target).then((stat) => {
198
+ if (stat.isDirectory()) {
199
+ if (!this.watchers.has(relative))
200
+ void this.scan(relative);
201
+ }
202
+ else if (stat.isFile()) {
203
+ this.schedule(relative);
204
+ }
205
+ }, () => {
206
+ // Gone: a file, or a directory and every file in it.
207
+ this.unwatch(relative);
208
+ for (const tracked of [...this.files.keys()]) {
209
+ if (tracked === relative || tracked.startsWith(`${relative}/`))
210
+ this.schedule(tracked);
211
+ }
212
+ });
213
+ }
214
+ schedule(relative) {
215
+ if (this.stopped || !(0, eligibility_1.isSyncablePath)(relative))
216
+ return;
217
+ clearTimeout(this.timers.get(relative));
218
+ this.timers.set(relative, setTimeout(() => {
219
+ this.timers.delete(relative);
220
+ this.enqueue(relative, () => this.syncPath(relative)).catch((error) => {
221
+ console.error(`[sync] ${relative}:`, error instanceof Error ? error.message : error);
222
+ });
223
+ }, CHANGE_DEBOUNCE_MS));
224
+ }
225
+ /** One operation at a time per file, in the order they were asked for. */
226
+ enqueue(relative, work) {
227
+ var _a;
228
+ const next = ((_a = this.queues.get(relative)) !== null && _a !== void 0 ? _a : Promise.resolve()).then(work, work);
229
+ const settled = next.catch(() => undefined);
230
+ this.queues.set(relative, settled);
231
+ void settled.then(() => {
232
+ if (this.queues.get(relative) === settled)
233
+ this.queues.delete(relative);
234
+ });
235
+ return next;
236
+ }
237
+ /** Sends the file's current state, if it is new to the session. `final` sends it regardless (ends a draft). */
238
+ async syncPath(relative, options = {}) {
239
+ if (this.stopped)
240
+ return;
241
+ const state = this.files.get(relative);
242
+ const read = await this.read(relative, options.final ? undefined : state === null || state === void 0 ? void 0 : state.statKey);
243
+ if (read.kind === 'unsyncable' || read.kind === 'unchanged')
244
+ return;
245
+ if (read.kind === 'missing') {
246
+ if (state || options.final) {
247
+ this.files.delete(relative);
248
+ this.send({ type: 'file_deleted', path: relative });
249
+ }
250
+ return;
251
+ }
252
+ const hash = (0, protocol_1.workspaceFileHash)(read.content);
253
+ if (state)
254
+ state.statKey = read.statKey;
255
+ if (hash === (state === null || state === void 0 ? void 0 : state.reported) && !options.final)
256
+ return;
257
+ if (!state && this.files.size >= eligibility_1.MAX_SYNCED_FILES)
258
+ return;
259
+ const next = state !== null && state !== void 0 ? state : { sent: new Map(), statKey: read.statKey };
260
+ const base = next.reported;
261
+ next.reported = hash;
262
+ remember(next.sent, hash, read.content);
263
+ this.files.set(relative, next);
264
+ this.send({
265
+ type: 'file_changed',
266
+ path: relative,
267
+ content: read.content,
268
+ ...(base ? { base } : {}),
269
+ ...(options.final ? { final: true } : {}),
270
+ });
271
+ }
272
+ /** The file's text; `unchanged` when its size and modification time still match `statKey`. */
273
+ async read(relative, statKey) {
274
+ const target = this.resolve(relative);
275
+ if (!target)
276
+ return { kind: 'unsyncable' };
277
+ try {
278
+ const stat = await fs_1.promises.lstat(target);
279
+ if (stat.isSymbolicLink())
280
+ return { kind: 'unsyncable' };
281
+ if (!stat.isFile())
282
+ return { kind: 'missing' };
283
+ const key = `${stat.size}:${stat.mtimeMs}`;
284
+ if (key === statKey)
285
+ return { kind: 'unchanged' };
286
+ const content = (0, eligibility_1.syncableText)(await (0, workload_1.readInside)(this.dir, target));
287
+ return content === undefined ? { kind: 'unsyncable' } : { kind: 'text', content, statKey: key };
288
+ }
289
+ catch (error) {
290
+ const code = error.code;
291
+ return code === 'ENOENT' || code === 'ENOTDIR' ? { kind: 'missing' } : { kind: 'unsyncable' };
292
+ }
293
+ }
294
+ async write(relative, content) {
295
+ const target = this.resolve(relative);
296
+ if (!target)
297
+ return;
298
+ await (0, workload_1.writeWorkloadFile)(target, content);
299
+ }
300
+ /** The absolute path of a workspace file, or undefined when it would escape the workspace. */
301
+ resolve(relative) {
302
+ const root = path_1.default.resolve(this.dir);
303
+ const target = path_1.default.resolve(root, relative);
304
+ return target !== root && (0, workload_1.isInsideDir)(root, target) ? target : undefined;
305
+ }
306
+ }
307
+ exports.WorkspaceSync = WorkspaceSync;
308
+ //# sourceMappingURL=workspace-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-sync.js","sourceRoot":"","sources":["../../src/workspace-sync/workspace-sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=workspace-sync.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-sync.test.d.ts","sourceRoot":"","sources":["../../src/workspace-sync/workspace-sync.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const strict_1 = __importDefault(require("node:assert/strict"));
7
+ const node_fs_1 = require("node:fs");
8
+ const node_os_1 = __importDefault(require("node:os"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const node_test_1 = require("node:test");
11
+ const protocol_1 = require("../transport/protocol");
12
+ const workspace_sync_1 = require("./workspace-sync");
13
+ let dir;
14
+ let sync;
15
+ let events;
16
+ function until(find, timeoutMs = 3000) {
17
+ const deadline = Date.now() + timeoutMs;
18
+ return new Promise((resolve, reject) => {
19
+ const poll = () => {
20
+ const found = find();
21
+ if (found !== undefined)
22
+ return resolve(found);
23
+ if (Date.now() > deadline)
24
+ return reject(new Error(`timed out; events: ${JSON.stringify(events)}`));
25
+ setTimeout(poll, 10);
26
+ };
27
+ poll();
28
+ });
29
+ }
30
+ const changed = (file, after = 0) => () => events.slice(after).find((event) => event.type === 'file_changed' && event.path === file);
31
+ (0, node_test_1.beforeEach)(async () => {
32
+ dir = await node_fs_1.promises.mkdtemp(node_path_1.default.join(node_os_1.default.tmpdir(), 'workspace-sync-'));
33
+ events = [];
34
+ await node_fs_1.promises.mkdir(node_path_1.default.join(dir, 'src'));
35
+ await node_fs_1.promises.mkdir(node_path_1.default.join(dir, 'node_modules/pkg'), { recursive: true });
36
+ await node_fs_1.promises.writeFile(node_path_1.default.join(dir, 'src/app.js'), 'one\n');
37
+ await node_fs_1.promises.writeFile(node_path_1.default.join(dir, 'node_modules/pkg/index.js'), 'ignored\n');
38
+ await node_fs_1.promises.writeFile(node_path_1.default.join(dir, 'logo.png'), Buffer.from([0x89, 0x50, 0x00, 0x01]));
39
+ sync = new workspace_sync_1.WorkspaceSync(dir, (event) => events.push(event));
40
+ await sync.start();
41
+ });
42
+ (0, node_test_1.afterEach)(async () => {
43
+ sync.stop();
44
+ await node_fs_1.promises.rm(dir, { recursive: true, force: true });
45
+ });
46
+ (0, node_test_1.it)('mirrors the workspace\'s text files, without dependencies or binaries, then each change built on the last', async () => {
47
+ const first = await until(changed('src/app.js'));
48
+ strict_1.default.equal(first.content, 'one\n');
49
+ strict_1.default.equal(first.base, undefined, 'nothing agreed yet');
50
+ strict_1.default.equal(events.some((event) => 'path' in event && /node_modules|logo/.test(String(event.path))), false);
51
+ const before = events.length;
52
+ await node_fs_1.promises.writeFile(node_path_1.default.join(dir, 'src/app.js'), 'two\n');
53
+ const second = await until(changed('src/app.js', before));
54
+ strict_1.default.equal(second.content, 'two\n');
55
+ strict_1.default.equal(second.base, (0, protocol_1.workspaceFileHash)('one\n'));
56
+ await node_fs_1.promises.mkdir(node_path_1.default.join(dir, 'docs'));
57
+ await node_fs_1.promises.writeFile(node_path_1.default.join(dir, 'docs/new.md'), '# New\n');
58
+ strict_1.default.equal((await until(changed('docs/new.md'))).content, '# New\n');
59
+ await node_fs_1.promises.rm(node_path_1.default.join(dir, 'docs'), { recursive: true });
60
+ await until(() => events.find((event) => event.type === 'file_deleted' && event.path === 'docs/new.md'));
61
+ });
62
+ (0, node_test_1.it)('merges people\'s edits with a change of its own the session has not seen yet', async () => {
63
+ await until(changed('src/app.js'));
64
+ const base = 'a\nb\nc\n';
65
+ await sync.applyState({ path: 'src/app.js', hash: (0, protocol_1.workspaceFileHash)(base), content: base });
66
+ strict_1.default.equal(await node_fs_1.promises.readFile(node_path_1.default.join(dir, 'src/app.js'), 'utf8'), base);
67
+ strict_1.default.ok(events.some((event) => event.type === 'file_synced' && event.hash === (0, protocol_1.workspaceFileHash)(base)));
68
+ // The agent edits line a; meanwhile someone edits line c in the session.
69
+ await node_fs_1.promises.writeFile(node_path_1.default.join(dir, 'src/app.js'), 'A\nb\nc\n');
70
+ const before = events.length;
71
+ await sync.applyState({ path: 'src/app.js', hash: (0, protocol_1.workspaceFileHash)('a\nb\nC\n'), content: 'a\nb\nC\n' });
72
+ strict_1.default.equal(await node_fs_1.promises.readFile(node_path_1.default.join(dir, 'src/app.js'), 'utf8'), 'A\nb\nC\n');
73
+ const merged = await until(changed('src/app.js', before));
74
+ strict_1.default.equal(merged.content, 'A\nb\nC\n');
75
+ strict_1.default.equal(merged.base, (0, protocol_1.workspaceFileHash)('a\nb\nC\n'), 'built on the session\'s copy');
76
+ });
77
+ (0, node_test_1.it)('settles a draft to the disk, and to a deletion when the write never happened', async () => {
78
+ await until(changed('src/app.js'));
79
+ sync.draft('src/app.js', 'partial');
80
+ sync.draft('../outside.txt', 'never');
81
+ await sync.settle(['src/app.js', 'src/never-written.js']);
82
+ const final = events.find((event) => event.type === 'file_changed' && event.final);
83
+ strict_1.default.equal(final && 'content' in final ? final.content : undefined, 'one\n');
84
+ strict_1.default.ok(events.some((event) => event.type === 'file_deleted' && event.path === 'src/never-written.js'));
85
+ strict_1.default.equal(events.some((event) => event.type === 'file_draft' && event.path.includes('outside')), false);
86
+ });
87
+ (0, node_test_1.it)('deletes the file when someone deletes it in the session', async () => {
88
+ await until(changed('src/app.js'));
89
+ await sync.applyDelete('src/app.js');
90
+ await strict_1.default.rejects(node_fs_1.promises.stat(node_path_1.default.join(dir, 'src/app.js')));
91
+ });
92
+ (0, node_test_1.it)('mirrors the app manifest, and nothing else of the agent\'s .builder state', async () => {
93
+ await until(changed('src/app.js'));
94
+ await node_fs_1.promises.mkdir(node_path_1.default.join(dir, '.builder/logs'), { recursive: true });
95
+ await node_fs_1.promises.writeFile(node_path_1.default.join(dir, '.builder/conversation.json'), '{"messages":[]}');
96
+ await node_fs_1.promises.writeFile(node_path_1.default.join(dir, '.builder/logs/app.log'), 'started\n');
97
+ await node_fs_1.promises.writeFile(node_path_1.default.join(dir, '.builder/builder.json'), '{\n "framework": null\n}\n');
98
+ const manifest = await until(changed('.builder/builder.json'));
99
+ strict_1.default.equal(manifest.content, '{\n "framework": null\n}\n');
100
+ await new Promise((resolve) => setTimeout(resolve, 200));
101
+ strict_1.default.equal(events.some((event) => 'path' in event && /conversation|app\.log/.test(String(event.path))), false);
102
+ });
103
+ (0, node_test_1.it)('says which version of a file the session has confirmed', async () => {
104
+ const first = await until(changed('src/app.js'));
105
+ strict_1.default.equal(sync.isConfirmed('src/app.js', Buffer.from('one\n')), false, 'sent, not confirmed yet');
106
+ await sync.applyState({ path: 'src/app.js', hash: (0, protocol_1.workspaceFileHash)(first.content) });
107
+ strict_1.default.equal(sync.isConfirmed('src/app.js', Buffer.from('one\n')), true);
108
+ strict_1.default.equal(sync.isConfirmed('src/app.js', Buffer.from('two\n')), false);
109
+ strict_1.default.equal(sync.isConfirmed('src/other.js', Buffer.from('one\n')), false);
110
+ });
111
+ //# sourceMappingURL=workspace-sync.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-sync.test.js","sourceRoot":"","sources":["../../src/workspace-sync/workspace-sync.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export interface DraftSink {
2
+ draft(path: string, content: string): void;
3
+ /** The call ended: each drafted file becomes what is on disk now. */
4
+ settle(paths: string[]): Promise<void>;
5
+ }
6
+ /** The files a partial write_files input already names in full, with their text so far. */
7
+ export declare function draftableFiles(input: string): Promise<Array<{
8
+ path: string;
9
+ content: string;
10
+ }>>;
11
+ export declare class WriteDraftTracker {
12
+ private readonly sink;
13
+ private readonly calls;
14
+ constructor(sink: DraftSink);
15
+ start(toolCallId: string, toolName: string): void;
16
+ delta(toolCallId: string, delta: string): void;
17
+ /** The whole input arrived: send the complete drafts now, before the call runs. */
18
+ end(toolCallId: string): Promise<void>;
19
+ settle(toolCallId: string): Promise<void>;
20
+ /** The turn ended: calls cut off before they ran leave no draft behind. */
21
+ settleAll(): Promise<void>;
22
+ private flush;
23
+ }
24
+ //# sourceMappingURL=write-drafts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-drafts.d.ts","sourceRoot":"","sources":["../../src/workspace-sync/write-drafts.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1C,qEAAqE;IACrE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACvC;AAUD,2FAA2F;AAC3F,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAWrG;AAED,qBAAa,iBAAiB;IAGhB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;gBAE1B,IAAI,EAAE,SAAS;IAE5C,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAIjD,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAY9C,mFAAmF;IAC7E,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQtC,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS/C,2EAA2E;IACrE,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;YAIlB,KAAK;CAapB"}
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WriteDraftTracker = void 0;
4
+ exports.draftableFiles = draftableFiles;
5
+ // Streams the files a write_files call is writing while the model is still generating them, so
6
+ // people watch the text appear instead of waiting for the call to finish. Drafts are shown, never
7
+ // saved: once the call ends — written, failed or cut off — the session's copy settles to the disk.
8
+ const ai_1 = require("ai");
9
+ const DRAFT_INTERVAL_MS = 250;
10
+ const DRAFTED_TOOL = 'write_files';
11
+ /** The files a partial write_files input already names in full, with their text so far. */
12
+ async function draftableFiles(input) {
13
+ const { value } = await (0, ai_1.parsePartialJson)(input);
14
+ const files = value === null || value === void 0 ? void 0 : value.files;
15
+ if (!Array.isArray(files))
16
+ return [];
17
+ return files.flatMap((file) => {
18
+ const { path, content, encoding } = (file !== null && file !== void 0 ? file : {});
19
+ if (typeof path !== 'string' || typeof content !== 'string' || encoding === 'base64')
20
+ return [];
21
+ // A path still being generated parses as its prefix ("src/ma"): only one whose closing quote
22
+ // has arrived is the real path.
23
+ return input.includes(JSON.stringify(path)) ? [{ path, content }] : [];
24
+ });
25
+ }
26
+ class WriteDraftTracker {
27
+ constructor(sink) {
28
+ this.sink = sink;
29
+ this.calls = new Map();
30
+ }
31
+ start(toolCallId, toolName) {
32
+ if (toolName === DRAFTED_TOOL)
33
+ this.calls.set(toolCallId, { input: '', sent: new Map() });
34
+ }
35
+ delta(toolCallId, delta) {
36
+ const call = this.calls.get(toolCallId);
37
+ if (!call)
38
+ return;
39
+ call.input += delta;
40
+ if (!call.timer) {
41
+ call.timer = setTimeout(() => {
42
+ call.timer = undefined;
43
+ void this.flush(call);
44
+ }, DRAFT_INTERVAL_MS);
45
+ }
46
+ }
47
+ /** The whole input arrived: send the complete drafts now, before the call runs. */
48
+ async end(toolCallId) {
49
+ const call = this.calls.get(toolCallId);
50
+ if (!call)
51
+ return;
52
+ clearTimeout(call.timer);
53
+ call.timer = undefined;
54
+ await this.flush(call);
55
+ }
56
+ async settle(toolCallId) {
57
+ const call = this.calls.get(toolCallId);
58
+ if (!call)
59
+ return;
60
+ this.calls.delete(toolCallId);
61
+ clearTimeout(call.timer);
62
+ await call.parsing;
63
+ if (call.sent.size)
64
+ await this.sink.settle([...call.sent.keys()]);
65
+ }
66
+ /** The turn ended: calls cut off before they ran leave no draft behind. */
67
+ async settleAll() {
68
+ await Promise.all([...this.calls.keys()].map((toolCallId) => this.settle(toolCallId)));
69
+ }
70
+ async flush(call) {
71
+ // One parse at a time; the next flush picks up whatever arrived meanwhile.
72
+ await call.parsing;
73
+ const parsing = (async () => {
74
+ var _a;
75
+ for (const file of await draftableFiles(call.input).catch(() => [])) {
76
+ if (((_a = call.sent.get(file.path)) !== null && _a !== void 0 ? _a : -1) >= file.content.length)
77
+ continue;
78
+ call.sent.set(file.path, file.content.length);
79
+ this.sink.draft(file.path, file.content);
80
+ }
81
+ })();
82
+ call.parsing = parsing;
83
+ await parsing;
84
+ }
85
+ }
86
+ exports.WriteDraftTracker = WriteDraftTracker;
87
+ //# sourceMappingURL=write-drafts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-drafts.js","sourceRoot":"","sources":["../../src/workspace-sync/write-drafts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=write-drafts.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-drafts.test.d.ts","sourceRoot":"","sources":["../../src/workspace-sync/write-drafts.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const strict_1 = __importDefault(require("node:assert/strict"));
7
+ const node_test_1 = require("node:test");
8
+ const write_drafts_1 = require("./write-drafts");
9
+ (0, node_test_1.it)('drafts only files whose path is complete, with the text so far', async () => {
10
+ strict_1.default.deepEqual(await (0, write_drafts_1.draftableFiles)('{"files":[{"path":"src/ma'), []);
11
+ strict_1.default.deepEqual(await (0, write_drafts_1.draftableFiles)('{"files":[{"path":"src/main.js","content":"const a = 1;\\nconst'), [
12
+ { path: 'src/main.js', content: 'const a = 1;\nconst' },
13
+ ]);
14
+ strict_1.default.deepEqual(await (0, write_drafts_1.draftableFiles)('{"files":[{"path":"logo.png","encoding":"base64","content":"iVBOR'), []);
15
+ });
16
+ (0, node_test_1.it)('streams a write_files call\'s files and settles them when it ends', async () => {
17
+ const drafts = [];
18
+ const settled = [];
19
+ const tracker = new write_drafts_1.WriteDraftTracker({
20
+ draft: (path, content) => drafts.push([path, content]),
21
+ settle: async (paths) => {
22
+ settled.push(paths);
23
+ },
24
+ });
25
+ tracker.start('call-1', 'write_files');
26
+ tracker.start('call-2', 'run_command');
27
+ tracker.delta('call-1', '{"files":[{"path":"a.md","content":"# Ti');
28
+ tracker.delta('call-2', '{"command":"ls"}');
29
+ tracker.delta('call-1', 'tle\\n"}]}');
30
+ await tracker.end('call-1');
31
+ strict_1.default.deepEqual(drafts[drafts.length - 1], ['a.md', '# Title\n']);
32
+ await tracker.settle('call-1');
33
+ await tracker.settleAll();
34
+ strict_1.default.deepEqual(settled, [['a.md']]);
35
+ });
36
+ //# sourceMappingURL=write-drafts.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-drafts.test.js","sourceRoot":"","sources":["../../src/workspace-sync/write-drafts.test.ts"],"names":[],"mappings":";;;;;AAAA,gEAAuC;AACvC,yCAA8B;AAC9B,iDAAkE;AAElE,IAAA,cAAE,EAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;IAC9E,gBAAM,CAAC,SAAS,CAAC,MAAM,IAAA,6BAAc,EAAC,2BAA2B,CAAC,EAAE,EAAE,CAAC,CAAA;IACvE,gBAAM,CAAC,SAAS,CAAC,MAAM,IAAA,6BAAc,EAAC,iEAAiE,CAAC,EAAE;QACxG,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,qBAAqB,EAAE;KACxD,CAAC,CAAA;IACF,gBAAM,CAAC,SAAS,CAAC,MAAM,IAAA,6BAAc,EAAC,mEAAmE,CAAC,EAAE,EAAE,CAAC,CAAA;AACjH,CAAC,CAAC,CAAA;AAEF,IAAA,cAAE,EAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;IACjF,MAAM,MAAM,GAA4B,EAAE,CAAA;IAC1C,MAAM,OAAO,GAAe,EAAE,CAAA;IAC9B,MAAM,OAAO,GAAG,IAAI,gCAAiB,CAAC;QACpC,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YACtB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACrB,CAAC;KACF,CAAC,CAAA;IACF,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;IACtC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;IACtC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,0CAA0C,CAAC,CAAA;IACnE,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAA;IAC3C,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAA;IACrC,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAC3B,gBAAM,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAA;IAClE,MAAM,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC9B,MAAM,OAAO,CAAC,SAAS,EAAE,CAAA;IACzB,gBAAM,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;AACvC,CAAC,CAAC,CAAA"}