@cydm/happy-elves 0.1.0-beta.31 → 0.1.0-beta.310

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 (342) hide show
  1. package/apps/cli/dist/commands/app.js +10 -0
  2. package/apps/cli/dist/commands/daemon.js +92 -4
  3. package/apps/cli/dist/commands/gateway.d.ts +2 -0
  4. package/apps/cli/dist/commands/gateway.js +429 -0
  5. package/apps/cli/dist/commands/lib/args.js +49 -0
  6. package/apps/cli/dist/commands/lib/bootstrap-daemon.d.ts +2 -2
  7. package/apps/cli/dist/commands/lib/bootstrap-daemon.js +2 -2
  8. package/apps/cli/dist/commands/lib/doctor.d.ts +11 -0
  9. package/apps/cli/dist/commands/lib/doctor.js +276 -11
  10. package/apps/cli/dist/commands/lib/gateway-store.d.ts +38 -0
  11. package/apps/cli/dist/commands/lib/gateway-store.js +33 -0
  12. package/apps/cli/dist/commands/lib/index.d.ts +4 -2
  13. package/apps/cli/dist/commands/lib/index.js +2 -0
  14. package/apps/cli/dist/commands/lib/json.d.ts +2 -2
  15. package/apps/cli/dist/commands/lib/json.js +5 -2
  16. package/apps/cli/dist/commands/lib/local-daemon.d.ts +1 -0
  17. package/apps/cli/dist/commands/lib/local-daemon.js +14 -0
  18. package/apps/cli/dist/commands/lib/paths.d.ts +2 -0
  19. package/apps/cli/dist/commands/lib/paths.js +2 -0
  20. package/apps/cli/dist/commands/lib/relay-db-audit.d.ts +37 -0
  21. package/apps/cli/dist/commands/lib/relay-db-audit.js +300 -0
  22. package/apps/cli/dist/commands/lib/relay-http.d.ts +1 -1
  23. package/apps/cli/dist/commands/lib/scope.d.ts +1 -1
  24. package/apps/cli/dist/commands/lib/session-output.d.ts +15 -1
  25. package/apps/cli/dist/commands/lib/session-output.js +214 -6
  26. package/apps/cli/dist/commands/lib/session-view.d.ts +2 -2
  27. package/apps/cli/dist/commands/lib/status.js +5 -1
  28. package/apps/cli/dist/commands/lib/types.d.ts +4 -2
  29. package/apps/cli/dist/commands/lib/usage.js +123 -10
  30. package/apps/cli/dist/commands/lib/workspace.d.ts +2 -2
  31. package/apps/cli/dist/commands/lib/workspace.js +63 -10
  32. package/apps/cli/dist/commands/machine.js +50 -9
  33. package/apps/cli/dist/commands/memory.d.ts +2 -0
  34. package/apps/cli/dist/commands/memory.js +179 -0
  35. package/apps/cli/dist/commands/relay.js +29 -2
  36. package/apps/cli/dist/commands/release.d.ts +2 -0
  37. package/apps/cli/dist/commands/release.js +197 -0
  38. package/apps/cli/dist/commands/remote.js +10 -2
  39. package/apps/cli/dist/commands/schedule.d.ts +2 -0
  40. package/apps/cli/dist/commands/schedule.js +273 -0
  41. package/apps/cli/dist/commands/session.js +517 -5
  42. package/apps/cli/dist/commands/turn.js +225 -9
  43. package/apps/cli/dist/commands/workspace.d.ts +2 -0
  44. package/apps/cli/dist/commands/workspace.js +68 -0
  45. package/apps/cli/package.json +6 -0
  46. package/apps/daemon/dist/gateway/adapters.d.ts +38 -0
  47. package/apps/daemon/dist/gateway/adapters.js +2 -0
  48. package/apps/daemon/dist/gateway/feishu.d.ts +65 -0
  49. package/apps/daemon/dist/gateway/feishu.js +493 -0
  50. package/apps/daemon/dist/gateway/format.d.ts +2 -0
  51. package/apps/daemon/dist/gateway/format.js +19 -0
  52. package/apps/daemon/dist/gateway/handler.d.ts +7 -0
  53. package/apps/daemon/dist/gateway/handler.js +151 -0
  54. package/apps/daemon/dist/gateway/runtime.d.ts +33 -0
  55. package/apps/daemon/dist/gateway/runtime.js +850 -0
  56. package/apps/daemon/dist/gateway/store.d.ts +92 -0
  57. package/apps/daemon/dist/gateway/store.js +268 -0
  58. package/apps/daemon/dist/memory/handler.d.ts +7 -0
  59. package/apps/daemon/dist/memory/handler.js +105 -0
  60. package/apps/daemon/dist/memory/manager.d.ts +44 -0
  61. package/apps/daemon/dist/memory/manager.js +359 -0
  62. package/apps/daemon/dist/paths.d.ts +3 -0
  63. package/apps/daemon/dist/paths.js +3 -0
  64. package/apps/daemon/dist/relay/admission.d.ts +30 -0
  65. package/apps/daemon/dist/relay/admission.js +31 -0
  66. package/apps/daemon/dist/relay/connection.js +37 -1
  67. package/apps/daemon/dist/relay/devtools.d.ts +1 -1
  68. package/apps/daemon/dist/relay/register.js +2 -0
  69. package/apps/daemon/dist/relay/send.d.ts +2 -2
  70. package/apps/daemon/dist/relay/send.js +2 -0
  71. package/apps/daemon/dist/relay-http.d.ts +1 -1
  72. package/apps/daemon/dist/runtime/external-provider.d.ts +1 -1
  73. package/apps/daemon/dist/runtime/external-provider.js +187 -17
  74. package/apps/daemon/dist/runtime.d.ts +1 -2
  75. package/apps/daemon/dist/runtime.js +0 -3
  76. package/apps/daemon/dist/schedule/handler.d.ts +9 -0
  77. package/apps/daemon/dist/schedule/handler.js +148 -0
  78. package/apps/daemon/dist/schedule/runner.d.ts +21 -0
  79. package/apps/daemon/dist/schedule/runner.js +547 -0
  80. package/apps/daemon/dist/schedule/store.d.ts +9 -0
  81. package/apps/daemon/dist/schedule/store.js +143 -0
  82. package/apps/daemon/dist/session/create-session.d.ts +1 -1
  83. package/apps/daemon/dist/session/directory.d.ts +1 -1
  84. package/apps/daemon/dist/session/events.d.ts +15 -2
  85. package/apps/daemon/dist/session/events.js +76 -24
  86. package/apps/daemon/dist/session/file-preview.d.ts +1 -1
  87. package/apps/daemon/dist/session/lifecycle.d.ts +26 -3
  88. package/apps/daemon/dist/session/lifecycle.js +161 -22
  89. package/apps/daemon/dist/session/metadata.d.ts +2 -2
  90. package/apps/daemon/dist/session/metadata.js +42 -1
  91. package/apps/daemon/dist/session/primitives.d.ts +1 -1
  92. package/apps/daemon/dist/session/primitives.js +37 -6
  93. package/apps/daemon/dist/session/prompt.d.ts +28 -1
  94. package/apps/daemon/dist/session/prompt.js +340 -5
  95. package/apps/daemon/dist/session/reconcile.d.ts +3 -0
  96. package/apps/daemon/dist/session/reconcile.js +235 -0
  97. package/apps/daemon/dist/session/runtime-handle.d.ts +1 -1
  98. package/apps/daemon/dist/start.js +5 -1
  99. package/apps/daemon/dist/state.d.ts +2 -2
  100. package/apps/daemon/dist/turn-coordinator.d.ts +1 -0
  101. package/apps/daemon/dist/turn-coordinator.js +4 -0
  102. package/apps/daemon/dist/types.d.ts +16 -1
  103. package/apps/daemon/package.json +3 -25
  104. package/apps/relay/dist/connections.d.ts +2 -0
  105. package/apps/relay/dist/controller-handlers.d.ts +42 -2
  106. package/apps/relay/dist/controller-handlers.js +349 -37
  107. package/apps/relay/dist/db.js +296 -2
  108. package/apps/relay/dist/errors.d.ts +2 -1
  109. package/apps/relay/dist/errors.js +3 -1
  110. package/apps/relay/dist/http-routes.js +659 -33
  111. package/apps/relay/dist/http-schemas.d.ts +156 -0
  112. package/apps/relay/dist/http-schemas.js +85 -0
  113. package/apps/relay/dist/index.js +31 -1
  114. package/apps/relay/dist/machine-handlers.d.ts +15 -7
  115. package/apps/relay/dist/machine-handlers.js +567 -27
  116. package/apps/relay/dist/projections.d.ts +1 -1
  117. package/apps/relay/dist/projections.js +13 -0
  118. package/apps/relay/dist/relay-context.d.ts +41 -3
  119. package/apps/relay/dist/relay-context.js +244 -19
  120. package/apps/relay/dist/repositories.d.ts +2 -2
  121. package/apps/relay/dist/repositories.js +28 -1
  122. package/apps/relay/dist/runtime-bindings.d.ts +25 -0
  123. package/apps/relay/dist/runtime-bindings.js +49 -0
  124. package/apps/relay/dist/scope.d.ts +1 -1
  125. package/apps/relay/dist/types.d.ts +71 -1
  126. package/apps/relay/dist/websocket.js +2 -0
  127. package/package.json +5 -11
  128. package/packages/agent-sdk/dist/index.d.ts +80 -0
  129. package/packages/agent-sdk/dist/index.js +16 -0
  130. package/packages/client/dist/account.d.ts +35 -2
  131. package/packages/client/dist/account.js +98 -1
  132. package/packages/client/dist/client.d.ts +59 -6
  133. package/packages/client/dist/client.js +312 -58
  134. package/packages/client/dist/index.d.ts +1 -1
  135. package/packages/client/dist/parsers.d.ts +28 -2
  136. package/packages/client/dist/parsers.js +167 -0
  137. package/packages/client/dist/transport.d.ts +21 -1
  138. package/packages/client/dist/transport.js +69 -6
  139. package/packages/client/dist/types.d.ts +177 -1
  140. package/packages/client/dist/validation.d.ts +1 -1
  141. package/packages/runtime/dist/index.d.ts +66 -0
  142. package/packages/runtime-acpx/dist/index.d.ts +1 -1
  143. package/packages/runtime-acpx/dist/index.js +8 -0
  144. package/packages/runtime-cli/dist/claude-history.d.ts +1 -2
  145. package/packages/runtime-cli/dist/claude-history.js +0 -3
  146. package/packages/runtime-cli/dist/claude-session-store.d.ts +0 -1
  147. package/packages/runtime-cli/dist/claude-session-store.js +1 -1
  148. package/packages/runtime-cli/dist/claude-turn.d.ts +2 -1
  149. package/packages/runtime-cli/dist/claude-turn.js +29 -9
  150. package/packages/runtime-cli/dist/codex-app-server.d.ts +8 -3
  151. package/packages/runtime-cli/dist/codex-app-server.js +122 -25
  152. package/packages/runtime-cli/dist/codex-history.d.ts +1 -2
  153. package/packages/runtime-cli/dist/codex-history.js +11 -5
  154. package/packages/runtime-cli/dist/codex-protocol.d.ts +2 -2
  155. package/packages/runtime-cli/dist/codex-protocol.js +4 -4
  156. package/packages/runtime-cli/dist/history-merge.d.ts +1 -1
  157. package/packages/runtime-cli/dist/index.d.ts +1 -1
  158. package/packages/runtime-cli/dist/index.js +108 -2
  159. package/packages/runtime-cli/dist/permissions.d.ts +1 -1
  160. package/packages/runtime-cli/dist/session-store.d.ts +2 -1
  161. package/packages/runtime-cli/dist/session-store.js +9 -8
  162. package/packages/shared/dist/index.d.ts +2 -0
  163. package/packages/shared/dist/index.js +2 -0
  164. package/packages/shared/dist/protocol-schemas.d.ts +1077 -0
  165. package/packages/shared/dist/protocol-schemas.js +273 -0
  166. package/packages/shared/dist/protocol-types.d.ts +371 -3
  167. package/packages/shared/dist/protocol.d.ts +181 -2
  168. package/packages/shared/dist/protocol.js +197 -1
  169. package/packages/shared/dist/session-tags.d.ts +12 -0
  170. package/packages/shared/dist/session-tags.js +50 -0
  171. package/apps/cli/dist/commands/account.js.map +0 -1
  172. package/apps/cli/dist/commands/app.js.map +0 -1
  173. package/apps/cli/dist/commands/collect.js.map +0 -1
  174. package/apps/cli/dist/commands/command.js.map +0 -1
  175. package/apps/cli/dist/commands/config.js.map +0 -1
  176. package/apps/cli/dist/commands/daemon.js.map +0 -1
  177. package/apps/cli/dist/commands/lib/args.js.map +0 -1
  178. package/apps/cli/dist/commands/lib/audit.js.map +0 -1
  179. package/apps/cli/dist/commands/lib/bootstrap-config.js.map +0 -1
  180. package/apps/cli/dist/commands/lib/bootstrap-daemon.js.map +0 -1
  181. package/apps/cli/dist/commands/lib/bootstrap-output.js.map +0 -1
  182. package/apps/cli/dist/commands/lib/bootstrap.js.map +0 -1
  183. package/apps/cli/dist/commands/lib/config.js.map +0 -1
  184. package/apps/cli/dist/commands/lib/doctor.js.map +0 -1
  185. package/apps/cli/dist/commands/lib/exit.js.map +0 -1
  186. package/apps/cli/dist/commands/lib/index.js.map +0 -1
  187. package/apps/cli/dist/commands/lib/json.js.map +0 -1
  188. package/apps/cli/dist/commands/lib/local-daemon.js.map +0 -1
  189. package/apps/cli/dist/commands/lib/loop-store.js.map +0 -1
  190. package/apps/cli/dist/commands/lib/paths.js.map +0 -1
  191. package/apps/cli/dist/commands/lib/relay-http.js.map +0 -1
  192. package/apps/cli/dist/commands/lib/scope.js.map +0 -1
  193. package/apps/cli/dist/commands/lib/session-output.js.map +0 -1
  194. package/apps/cli/dist/commands/lib/session-view.js.map +0 -1
  195. package/apps/cli/dist/commands/lib/status.js.map +0 -1
  196. package/apps/cli/dist/commands/lib/types.js.map +0 -1
  197. package/apps/cli/dist/commands/lib/usage.js.map +0 -1
  198. package/apps/cli/dist/commands/lib/workspace.js.map +0 -1
  199. package/apps/cli/dist/commands/loop.js.map +0 -1
  200. package/apps/cli/dist/commands/machine.js.map +0 -1
  201. package/apps/cli/dist/commands/relay.js.map +0 -1
  202. package/apps/cli/dist/commands/remote.js.map +0 -1
  203. package/apps/cli/dist/commands/session.js.map +0 -1
  204. package/apps/cli/dist/commands/token.js.map +0 -1
  205. package/apps/cli/dist/commands/turn.js.map +0 -1
  206. package/apps/cli/dist/errors.js.map +0 -1
  207. package/apps/cli/dist/index.js.map +0 -1
  208. package/apps/daemon/dist/app.js.map +0 -1
  209. package/apps/daemon/dist/args.js.map +0 -1
  210. package/apps/daemon/dist/audit.js.map +0 -1
  211. package/apps/daemon/dist/cli.js.map +0 -1
  212. package/apps/daemon/dist/config.js.map +0 -1
  213. package/apps/daemon/dist/errors.js.map +0 -1
  214. package/apps/daemon/dist/loop/runner.js.map +0 -1
  215. package/apps/daemon/dist/loop/store.js.map +0 -1
  216. package/apps/daemon/dist/pair.js.map +0 -1
  217. package/apps/daemon/dist/paths.js.map +0 -1
  218. package/apps/daemon/dist/process.js.map +0 -1
  219. package/apps/daemon/dist/relay/connection.js.map +0 -1
  220. package/apps/daemon/dist/relay/devtools.js.map +0 -1
  221. package/apps/daemon/dist/relay/register.js.map +0 -1
  222. package/apps/daemon/dist/relay/send.js.map +0 -1
  223. package/apps/daemon/dist/relay-http.js.map +0 -1
  224. package/apps/daemon/dist/runtime/external-provider.js.map +0 -1
  225. package/apps/daemon/dist/runtime.js.map +0 -1
  226. package/apps/daemon/dist/session/create-session.js.map +0 -1
  227. package/apps/daemon/dist/session/directory.js.map +0 -1
  228. package/apps/daemon/dist/session/events.js.map +0 -1
  229. package/apps/daemon/dist/session/file-preview.js.map +0 -1
  230. package/apps/daemon/dist/session/lifecycle.js.map +0 -1
  231. package/apps/daemon/dist/session/metadata.js.map +0 -1
  232. package/apps/daemon/dist/session/primitives.js.map +0 -1
  233. package/apps/daemon/dist/session/prompt.js.map +0 -1
  234. package/apps/daemon/dist/session/runtime-handle.js.map +0 -1
  235. package/apps/daemon/dist/start.js.map +0 -1
  236. package/apps/daemon/dist/state.js.map +0 -1
  237. package/apps/daemon/dist/turn-coordinator.js.map +0 -1
  238. package/apps/daemon/dist/types.js.map +0 -1
  239. package/apps/daemon/dist/utils.js.map +0 -1
  240. package/apps/relay/dist/auth.js.map +0 -1
  241. package/apps/relay/dist/connections.js.map +0 -1
  242. package/apps/relay/dist/controller-handlers.js.map +0 -1
  243. package/apps/relay/dist/db.js.map +0 -1
  244. package/apps/relay/dist/errors.js.map +0 -1
  245. package/apps/relay/dist/http-routes.js.map +0 -1
  246. package/apps/relay/dist/http-schemas.js.map +0 -1
  247. package/apps/relay/dist/index.js.map +0 -1
  248. package/apps/relay/dist/machine-handlers.js.map +0 -1
  249. package/apps/relay/dist/projections.js.map +0 -1
  250. package/apps/relay/dist/relay-context.js.map +0 -1
  251. package/apps/relay/dist/repositories.js.map +0 -1
  252. package/apps/relay/dist/retention.js.map +0 -1
  253. package/apps/relay/dist/scope.js.map +0 -1
  254. package/apps/relay/dist/security.js.map +0 -1
  255. package/apps/relay/dist/types.js.map +0 -1
  256. package/apps/relay/dist/websocket.js.map +0 -1
  257. package/apps/relay/package.json +0 -29
  258. package/packages/agent-sdk/dist/index.d.ts.map +0 -1
  259. package/packages/agent-sdk/dist/index.js.map +0 -1
  260. package/packages/agent-sdk/package.json +0 -20
  261. package/packages/client/dist/account.d.ts.map +0 -1
  262. package/packages/client/dist/account.js.map +0 -1
  263. package/packages/client/dist/client.d.ts.map +0 -1
  264. package/packages/client/dist/client.js.map +0 -1
  265. package/packages/client/dist/errors.d.ts.map +0 -1
  266. package/packages/client/dist/errors.js.map +0 -1
  267. package/packages/client/dist/http.d.ts.map +0 -1
  268. package/packages/client/dist/http.js.map +0 -1
  269. package/packages/client/dist/index.d.ts.map +0 -1
  270. package/packages/client/dist/index.js.map +0 -1
  271. package/packages/client/dist/parsers.d.ts.map +0 -1
  272. package/packages/client/dist/parsers.js.map +0 -1
  273. package/packages/client/dist/transport.d.ts.map +0 -1
  274. package/packages/client/dist/transport.js.map +0 -1
  275. package/packages/client/dist/types.d.ts.map +0 -1
  276. package/packages/client/dist/types.js.map +0 -1
  277. package/packages/client/dist/validation.d.ts.map +0 -1
  278. package/packages/client/dist/validation.js.map +0 -1
  279. package/packages/client/package.json +0 -22
  280. package/packages/pie-provider/dist/index.d.ts.map +0 -1
  281. package/packages/pie-provider/dist/index.js.map +0 -1
  282. package/packages/pie-provider/package.json +0 -26
  283. package/packages/runtime/dist/index.d.ts.map +0 -1
  284. package/packages/runtime/dist/index.js.map +0 -1
  285. package/packages/runtime/package.json +0 -19
  286. package/packages/runtime-acpx/dist/index.d.ts.map +0 -1
  287. package/packages/runtime-acpx/dist/index.js.map +0 -1
  288. package/packages/runtime-acpx/package.json +0 -23
  289. package/packages/runtime-cli/dist/async-queue.d.ts.map +0 -1
  290. package/packages/runtime-cli/dist/async-queue.js.map +0 -1
  291. package/packages/runtime-cli/dist/claude-history.d.ts.map +0 -1
  292. package/packages/runtime-cli/dist/claude-history.js.map +0 -1
  293. package/packages/runtime-cli/dist/claude-json.d.ts.map +0 -1
  294. package/packages/runtime-cli/dist/claude-json.js.map +0 -1
  295. package/packages/runtime-cli/dist/claude-rename.d.ts.map +0 -1
  296. package/packages/runtime-cli/dist/claude-rename.js.map +0 -1
  297. package/packages/runtime-cli/dist/claude-session-store.d.ts.map +0 -1
  298. package/packages/runtime-cli/dist/claude-session-store.js.map +0 -1
  299. package/packages/runtime-cli/dist/claude-turn.d.ts.map +0 -1
  300. package/packages/runtime-cli/dist/claude-turn.js.map +0 -1
  301. package/packages/runtime-cli/dist/codex-app-server.d.ts.map +0 -1
  302. package/packages/runtime-cli/dist/codex-app-server.js.map +0 -1
  303. package/packages/runtime-cli/dist/codex-approvals.d.ts.map +0 -1
  304. package/packages/runtime-cli/dist/codex-approvals.js.map +0 -1
  305. package/packages/runtime-cli/dist/codex-history.d.ts.map +0 -1
  306. package/packages/runtime-cli/dist/codex-history.js.map +0 -1
  307. package/packages/runtime-cli/dist/codex-json-rpc.d.ts.map +0 -1
  308. package/packages/runtime-cli/dist/codex-json-rpc.js.map +0 -1
  309. package/packages/runtime-cli/dist/codex-lifecycle.d.ts.map +0 -1
  310. package/packages/runtime-cli/dist/codex-lifecycle.js.map +0 -1
  311. package/packages/runtime-cli/dist/codex-protocol.d.ts.map +0 -1
  312. package/packages/runtime-cli/dist/codex-protocol.js.map +0 -1
  313. package/packages/runtime-cli/dist/command-resolver.d.ts.map +0 -1
  314. package/packages/runtime-cli/dist/command-resolver.js.map +0 -1
  315. package/packages/runtime-cli/dist/history-merge.d.ts.map +0 -1
  316. package/packages/runtime-cli/dist/history-merge.js.map +0 -1
  317. package/packages/runtime-cli/dist/index.d.ts.map +0 -1
  318. package/packages/runtime-cli/dist/index.js.map +0 -1
  319. package/packages/runtime-cli/dist/permissions.d.ts.map +0 -1
  320. package/packages/runtime-cli/dist/permissions.js.map +0 -1
  321. package/packages/runtime-cli/dist/session-store.d.ts.map +0 -1
  322. package/packages/runtime-cli/dist/session-store.js.map +0 -1
  323. package/packages/runtime-cli/package.json +0 -22
  324. package/packages/shared/dist/args.d.ts.map +0 -1
  325. package/packages/shared/dist/args.js.map +0 -1
  326. package/packages/shared/dist/crypto.d.ts.map +0 -1
  327. package/packages/shared/dist/crypto.js.map +0 -1
  328. package/packages/shared/dist/ids.d.ts.map +0 -1
  329. package/packages/shared/dist/ids.js.map +0 -1
  330. package/packages/shared/dist/index.d.ts.map +0 -1
  331. package/packages/shared/dist/index.js.map +0 -1
  332. package/packages/shared/dist/protocol-schemas.d.ts.map +0 -1
  333. package/packages/shared/dist/protocol-schemas.js.map +0 -1
  334. package/packages/shared/dist/protocol-types.d.ts.map +0 -1
  335. package/packages/shared/dist/protocol-types.js.map +0 -1
  336. package/packages/shared/dist/protocol.d.ts.map +0 -1
  337. package/packages/shared/dist/protocol.js.map +0 -1
  338. package/packages/shared/dist/session-name.d.ts.map +0 -1
  339. package/packages/shared/dist/session-name.js.map +0 -1
  340. package/packages/shared/dist/session-state.d.ts.map +0 -1
  341. package/packages/shared/dist/session-state.js.map +0 -1
  342. package/packages/shared/package.json +0 -24
@@ -1,5 +1,8 @@
1
+ import { normalizeRuntimeSessionIds, upsertSessionRuntimeBindings } from "./runtime-bindings.js";
2
+ const REWRITE_HEAD_BASIS_SEQ = 0;
3
+ const REWRITE_HEAD_BASIS_PREFIX = "rewrite:";
1
4
  export function handleMachineMessage(context, connection, message) {
2
- const { broadcastAck, broadcastControllers, broadcastError, clearCommandPending, db, insertEvent, aliasedRuntimeEventHasRequestEvents, machineMessageProcessed, markMachineMessageProcessed, now, recordTurnAlias, rememberCommandResponse, sendMachineMessageAck, sessionSnapshot, setSessionStatus, updateMachineLastSeen, } = context;
5
+ const { broadcastAck, broadcastControllers, broadcastError, clearCommandPending, db, finishSessionClaim, insertEvent, machineMessageProcessed, markMachineMessageProcessed, now, recordTurnAlias, rememberCommandResponse, sendMachineMessageAck, sessionSnapshot, setSessionStatus, updateMachineLastSeen, } = context;
3
6
  const messageId = machineMessageId(message);
4
7
  if (messageId && machineMessageProcessed(connection.accountId, connection.machineId, messageId)) {
5
8
  sendMachineMessageAck(connection, messageId);
@@ -28,10 +31,12 @@ export function handleMachineMessage(context, connection, message) {
28
31
  name = COALESCE(?, name),
29
32
  encrypted_metadata = COALESCE(?, encrypted_metadata),
30
33
  updated_at = ?
31
- WHERE id = ? AND account_id = ? AND machine_id = ?`).run(message.name ?? null, message.encryptedMetadata ? JSON.stringify(message.encryptedMetadata) : null, ts, message.sessionId, connection.accountId, connection.machineId);
34
+ WHERE id = ? AND account_id = ? AND machine_id = ? AND status != 'closed'`).run(message.name ?? null, message.encryptedMetadata ? JSON.stringify(message.encryptedMetadata) : null, ts, message.sessionId, connection.accountId, connection.machineId);
32
35
  const row = db.prepare("SELECT * FROM sessions WHERE id = ?").get(message.sessionId);
33
- if (row)
36
+ if (row && row.status !== "closed") {
37
+ recordRuntimeBindingsFromMachineMessage(db, connection, row, message, ts);
34
38
  broadcastControllers(connection.accountId, { type: "server:session", session: sessionSnapshot(row) });
39
+ }
35
40
  broadcastAck(connection.accountId, {
36
41
  type: "server:ack",
37
42
  requestId: message.requestId,
@@ -48,10 +53,12 @@ export function handleMachineMessage(context, connection, message) {
48
53
  name = COALESCE(?, name),
49
54
  encrypted_metadata = COALESCE(?, encrypted_metadata),
50
55
  updated_at = ?
51
- WHERE id = ? AND account_id = ? AND machine_id = ?`).run(message.name ?? null, message.encryptedMetadata ? JSON.stringify(message.encryptedMetadata) : null, ts, message.sessionId, connection.accountId, connection.machineId);
56
+ WHERE id = ? AND account_id = ? AND machine_id = ? AND status != 'closed'`).run(message.name ?? null, message.encryptedMetadata ? JSON.stringify(message.encryptedMetadata) : null, ts, message.sessionId, connection.accountId, connection.machineId);
52
57
  const row = db.prepare("SELECT * FROM sessions WHERE id = ?").get(message.sessionId);
53
- if (row)
58
+ if (row && row.status !== "closed") {
59
+ recordRuntimeBindingsFromMachineMessage(db, connection, row, message, ts);
54
60
  broadcastControllers(connection.accountId, { type: "server:session", session: sessionSnapshot(row) });
61
+ }
55
62
  broadcastAck(connection.accountId, { type: "server:ack", requestId: message.requestId, ok: true });
56
63
  acknowledgeMachineMessage();
57
64
  return;
@@ -117,15 +124,150 @@ export function handleMachineMessage(context, connection, message) {
117
124
  broadcastControllers(connection.accountId, response);
118
125
  return;
119
126
  }
127
+ if (message.type === "machine:gatewayResult") {
128
+ const response = {
129
+ type: "server:gatewayResult",
130
+ requestId: message.requestId,
131
+ machineId: connection.machineId,
132
+ result: message.result,
133
+ };
134
+ rememberCommandResponse(connection.accountId, message.requestId, response);
135
+ clearCommandPending(connection.accountId, message.requestId);
136
+ broadcastControllers(connection.accountId, response);
137
+ return;
138
+ }
139
+ if (message.type === "machine:scheduleResult") {
140
+ const response = {
141
+ type: "server:scheduleResult",
142
+ requestId: message.requestId,
143
+ machineId: connection.machineId,
144
+ result: message.result,
145
+ };
146
+ rememberCommandResponse(connection.accountId, message.requestId, response);
147
+ clearCommandPending(connection.accountId, message.requestId);
148
+ broadcastControllers(connection.accountId, response);
149
+ return;
150
+ }
151
+ if (message.type === "machine:memoryResult") {
152
+ const response = {
153
+ type: "server:memoryResult",
154
+ requestId: message.requestId,
155
+ machineId: connection.machineId,
156
+ result: message.result,
157
+ };
158
+ rememberCommandResponse(connection.accountId, message.requestId, response);
159
+ clearCommandPending(connection.accountId, message.requestId);
160
+ broadcastControllers(connection.accountId, response);
161
+ return;
162
+ }
163
+ if (message.type === "machine:optionResponded") {
164
+ clearCommandPending(connection.accountId, message.requestId);
165
+ broadcastAck(connection.accountId, {
166
+ type: "server:ack",
167
+ requestId: message.requestId,
168
+ ok: true,
169
+ sessionId: message.sessionId,
170
+ turnId: message.turnId,
171
+ });
172
+ acknowledgeMachineMessage();
173
+ return;
174
+ }
175
+ if (message.type === "machine:turnReconciled") {
176
+ const response = {
177
+ type: "server:turnReconciled",
178
+ requestId: message.requestId,
179
+ machineId: connection.machineId,
180
+ result: message.result,
181
+ };
182
+ const ts = now();
183
+ if (message.result.status === "active") {
184
+ db.prepare(`UPDATE sessions
185
+ SET status = 'running', updated_at = ?
186
+ WHERE id = ? AND account_id = ? AND machine_id = ? AND status NOT IN ('closed', 'cancelled', 'failed', 'completed')`).run(ts, message.result.sessionId, connection.accountId, connection.machineId);
187
+ const row = db.prepare("SELECT * FROM sessions WHERE id = ?").get(message.result.sessionId);
188
+ if (row)
189
+ broadcastControllers(connection.accountId, { type: "server:session", session: sessionSnapshot(row) });
190
+ }
191
+ if (message.result.status === "terminal" && message.result.terminalStatus) {
192
+ const activeClaim = activePromptClaim(db, connection.accountId, message.result.sessionId, connection.machineId);
193
+ const terminalMatchesActiveClaim = Boolean(activeClaim) &&
194
+ (!message.result.requestId || message.result.requestId === activeClaim?.request_id) &&
195
+ (!message.result.turnId || message.result.turnId === activeClaim?.turn_id);
196
+ const shouldProjectTerminal = !activeClaim || terminalMatchesActiveClaim;
197
+ if (message.result.turnId || message.result.lastTurnId || message.result.currentHead || message.result.providerTurnId) {
198
+ recordTurnAlias({
199
+ accountId: connection.accountId,
200
+ sessionId: message.result.sessionId,
201
+ machineId: connection.machineId,
202
+ requestTurnId: message.result.turnId ?? message.result.lastTurnId ?? message.result.currentHead ?? message.result.providerTurnId ?? "",
203
+ runtimeTurnId: message.result.lastTurnId ?? message.result.currentHead ?? message.result.providerTurnId,
204
+ requestId: message.result.requestId,
205
+ });
206
+ }
207
+ if (shouldProjectTerminal) {
208
+ db.prepare(`UPDATE sessions
209
+ SET status = ?,
210
+ current_head = COALESCE(?, current_head),
211
+ last_turn_id = COALESCE(?, last_turn_id),
212
+ updated_at = ?
213
+ WHERE id = ? AND account_id = ? AND machine_id = ? AND status != 'closed'`).run(message.result.terminalStatus, message.result.currentHead ?? null, message.result.lastTurnId ?? message.result.turnId ?? null, ts, message.result.sessionId, connection.accountId, connection.machineId);
214
+ }
215
+ finishSessionClaim({
216
+ accountId: connection.accountId,
217
+ sessionId: message.result.sessionId,
218
+ requestId: message.result.requestId,
219
+ turnId: message.result.turnId,
220
+ terminalStatus: message.result.terminalStatus,
221
+ ...(message.result.error ? { errorCode: "TURN_ERROR" } : {}),
222
+ finishedAt: ts,
223
+ });
224
+ if (shouldProjectTerminal) {
225
+ const row = db.prepare("SELECT * FROM sessions WHERE id = ?").get(message.result.sessionId);
226
+ if (row && row.status !== "closed")
227
+ broadcastControllers(connection.accountId, { type: "server:session", session: sessionSnapshot(row) });
228
+ }
229
+ }
230
+ if (message.result.status === "unknown" || message.result.status === "not_found" || message.result.status === "uninspectable") {
231
+ const claim = activePromptClaim(db, connection.accountId, message.result.sessionId, connection.machineId);
232
+ const turnId = message.result.turnId ?? claim?.turn_id;
233
+ const requestId = message.result.requestId ?? claim?.request_id;
234
+ const claimMatches = Boolean(claim) &&
235
+ (!message.result.requestId || message.result.requestId === claim?.request_id) &&
236
+ (!message.result.turnId || message.result.turnId === claim?.turn_id);
237
+ if (claimMatches && turnId) {
238
+ finishSessionClaim({
239
+ accountId: connection.accountId,
240
+ sessionId: message.result.sessionId,
241
+ requestId,
242
+ turnId,
243
+ terminalStatus: "unknown",
244
+ errorCode: message.result.status === "not_found" ? "EXECUTION_NOT_FOUND" : "EXECUTION_UNKNOWN",
245
+ finishedAt: ts,
246
+ });
247
+ const row = db.prepare("SELECT * FROM sessions WHERE id = ?").get(message.result.sessionId);
248
+ if (row && row.status !== "closed")
249
+ broadcastControllers(connection.accountId, { type: "server:session", session: sessionSnapshot(row) });
250
+ }
251
+ }
252
+ rememberCommandResponse(connection.accountId, message.requestId, response);
253
+ clearCommandPending(connection.accountId, message.requestId);
254
+ broadcastControllers(connection.accountId, response);
255
+ acknowledgeMachineMessage();
256
+ return;
257
+ }
120
258
  if (message.type === "machine:sessionRewound") {
121
259
  const ts = now();
122
260
  const update = db.prepare(`UPDATE sessions
123
261
  SET status = 'ready',
124
262
  current_head = ?,
125
263
  last_turn_id = COALESCE(?, last_turn_id),
264
+ head_basis_event_id = NULL,
265
+ head_basis_message_id = ?,
266
+ head_basis_logical_time = ?,
267
+ head_basis_turn_seq = ?,
126
268
  encrypted_metadata = COALESCE(?, encrypted_metadata),
127
269
  updated_at = ?
128
- WHERE id = ? AND account_id = ? AND machine_id = ?`).run(message.currentHead, message.lastTurnId ?? null, message.encryptedMetadata ? JSON.stringify(message.encryptedMetadata) : null, ts, message.sessionId, connection.accountId, connection.machineId);
270
+ WHERE id = ? AND account_id = ? AND machine_id = ?`).run(message.currentHead, message.lastTurnId ?? null, `rewrite:${message.requestId}`, ts, REWRITE_HEAD_BASIS_SEQ, message.encryptedMetadata ? JSON.stringify(message.encryptedMetadata) : null, ts, message.sessionId, connection.accountId, connection.machineId);
129
271
  if (update.changes === 0) {
130
272
  broadcastError(connection.accountId, {
131
273
  type: "server:error",
@@ -136,6 +278,7 @@ export function handleMachineMessage(context, connection, message) {
136
278
  acknowledgeMachineMessage();
137
279
  return;
138
280
  }
281
+ clearPendingSessionHeadAdvances(db, connection.accountId, message.sessionId, connection.machineId);
139
282
  const row = db.prepare("SELECT * FROM sessions WHERE id = ?").get(message.sessionId);
140
283
  if (row)
141
284
  broadcastControllers(connection.accountId, { type: "server:session", session: sessionSnapshot(row) });
@@ -180,7 +323,7 @@ export function handleMachineMessage(context, connection, message) {
180
323
  db.prepare(`INSERT INTO sessions
181
324
  (id, account_id, machine_id, agent, cwd, name, status, encrypted_metadata,
182
325
  current_head, last_turn_id, source_session_id, source_checkpoint_id, created_at, updated_at)
183
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(message.sessionId, connection.accountId, connection.machineId, source.agent, source.cwd, message.name ?? source.name, "ready", message.encryptedMetadata ? JSON.stringify(message.encryptedMetadata) : source.encrypted_metadata, message.sourceCheckpointId, source.last_turn_id, message.sourceSessionId, message.sourceCheckpointId, ts, ts);
326
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(message.sessionId, connection.accountId, connection.machineId, source.agent, source.cwd, message.name ?? source.name, message.transcriptPending === true ? "running" : "ready", message.encryptedMetadata ? JSON.stringify(message.encryptedMetadata) : source.encrypted_metadata, message.sourceCheckpointId, source.last_turn_id, message.sourceSessionId, message.sourceCheckpointId, ts, ts);
184
327
  }
185
328
  const row = db.prepare("SELECT * FROM sessions WHERE id = ?").get(message.sessionId);
186
329
  if (row)
@@ -220,6 +363,12 @@ export function handleMachineMessage(context, connection, message) {
220
363
  }
221
364
  if (message.type === "machine:sessionClosed") {
222
365
  const session = setSessionStatus(message.sessionId, "closed");
366
+ finishSessionClaim({
367
+ accountId: connection.accountId,
368
+ sessionId: message.sessionId,
369
+ terminalStatus: "cancelled",
370
+ errorCode: "SESSION_CLOSED",
371
+ });
223
372
  if (session)
224
373
  broadcastControllers(connection.accountId, { type: "server:session", session });
225
374
  broadcastAck(connection.accountId, { type: "server:ack", requestId: message.requestId, ok: true });
@@ -234,6 +383,34 @@ export function handleMachineMessage(context, connection, message) {
234
383
  acknowledgeMachineMessage();
235
384
  return;
236
385
  }
386
+ if (sessionRow.status === "closed") {
387
+ acknowledgeMachineMessage();
388
+ return;
389
+ }
390
+ const replacementBasis = message.basis;
391
+ const replacementBasisEvent = replacementBasis
392
+ ? message.events.find((event) => event.messageId === replacementBasis.eventMessageId &&
393
+ event.turnId === replacementBasis.turnId &&
394
+ event.seq === replacementBasis.turnSeq)
395
+ : undefined;
396
+ if (replacementBasis && !replacementBasisEvent) {
397
+ broadcastError(connection.accountId, {
398
+ type: "server:error",
399
+ code: "SESSION_REPLACEMENT_BASIS_MISSING",
400
+ message: "Transcript replacement basis event is not present in the replacement window",
401
+ });
402
+ acknowledgeMachineMessage();
403
+ return;
404
+ }
405
+ const currentOrder = sessionHeadBasisOrder(db, sessionRow);
406
+ const replacementOrder = replacementBasis ? headAdvanceBasisOrder(replacementBasis) : undefined;
407
+ const shouldApplyReplacement = message.replacementKind === "command" ||
408
+ !currentOrder ||
409
+ (replacementOrder !== undefined && compareHeadBasisOrder(replacementOrder, currentOrder) >= 0);
410
+ if (!shouldApplyReplacement) {
411
+ acknowledgeMachineMessage();
412
+ return;
413
+ }
237
414
  const ts = now();
238
415
  const inserted = [];
239
416
  db.exec("BEGIN");
@@ -242,6 +419,7 @@ export function handleMachineMessage(context, connection, message) {
242
419
  WHERE account_id = ? AND session_id = ? AND machine_id = ?`).run(connection.accountId, message.sessionId, connection.machineId);
243
420
  db.prepare(`DELETE FROM session_turn_aliases
244
421
  WHERE account_id = ? AND session_id = ? AND machine_id = ?`).run(connection.accountId, message.sessionId, connection.machineId);
422
+ clearPendingSessionHeadAdvances(db, connection.accountId, message.sessionId, connection.machineId);
245
423
  for (const event of message.events) {
246
424
  const result = db
247
425
  .prepare(`INSERT INTO session_events
@@ -261,21 +439,42 @@ export function handleMachineMessage(context, connection, message) {
261
439
  payload: event.payload,
262
440
  });
263
441
  }
442
+ const insertedBasisEvent = replacementBasis
443
+ ? inserted.find((event) => event.messageId === replacementBasis.eventMessageId &&
444
+ event.turnId === replacementBasis.turnId &&
445
+ event.turnSeq === replacementBasis.turnSeq)
446
+ : undefined;
264
447
  const lastEvent = inserted.at(-1);
448
+ const headBasisEvent = insertedBasisEvent ?? lastEvent;
449
+ const headBasisOrder = headBasisEvent ? logicalEventOrderFromParts({
450
+ id: headBasisEvent.id,
451
+ createdAt: headBasisEvent.createdAt,
452
+ messageId: headBasisEvent.messageId,
453
+ occurredAt: headBasisEvent.occurredAt,
454
+ seq: headBasisEvent.seq,
455
+ turnSeq: headBasisEvent.turnSeq,
456
+ }) : undefined;
265
457
  db.prepare(`UPDATE sessions
266
458
  SET status = COALESCE(?, status),
267
459
  current_head = COALESCE(?, ?),
268
460
  last_turn_id = COALESCE(?, ?),
461
+ head_basis_event_id = ?,
462
+ head_basis_message_id = ?,
463
+ head_basis_logical_time = ?,
464
+ head_basis_turn_seq = ?,
269
465
  encrypted_metadata = COALESCE(?, encrypted_metadata),
270
466
  updated_at = ?
271
- WHERE id = ? AND account_id = ? AND machine_id = ?`).run(message.status ?? null, message.currentHead ?? null, lastEvent ? `event:${lastEvent.id}` : sessionRow.current_head, message.lastTurnId ?? null, lastEvent?.turnId ?? sessionRow.last_turn_id, message.encryptedMetadata ? JSON.stringify(message.encryptedMetadata) : null, ts, message.sessionId, connection.accountId, connection.machineId);
467
+ WHERE id = ? AND account_id = ? AND machine_id = ?`).run(message.status ?? null, message.currentHead ?? null, lastEvent ? `event:${lastEvent.id}` : sessionRow.current_head, message.lastTurnId ?? null, lastEvent?.turnId ?? sessionRow.last_turn_id, headBasisEvent?.id ?? null, headBasisEvent?.messageId ?? null, headBasisOrder?.time ?? null, headBasisOrder?.seq ?? null, message.encryptedMetadata ? JSON.stringify(message.encryptedMetadata) : null, ts, message.sessionId, connection.accountId, connection.machineId);
272
468
  db.exec("COMMIT");
273
469
  }
274
470
  catch (error) {
275
471
  db.exec("ROLLBACK");
276
472
  throw error;
277
473
  }
278
- const row = db.prepare("SELECT * FROM sessions WHERE id = ?").get(message.sessionId);
474
+ const pendingSessionRow = inserted.length > 0
475
+ ? applyPendingSessionHeadAdvances(db, connection.accountId, message.sessionId, connection.machineId, now())
476
+ : undefined;
477
+ const row = pendingSessionRow ?? db.prepare("SELECT * FROM sessions WHERE id = ?").get(message.sessionId);
279
478
  if (row) {
280
479
  const session = sessionSnapshot(row);
281
480
  broadcastControllers(connection.accountId, {
@@ -298,6 +497,10 @@ export function handleMachineMessage(context, connection, message) {
298
497
  acknowledgeMachineMessage();
299
498
  return;
300
499
  }
500
+ if (sessionRow.status === "closed") {
501
+ acknowledgeMachineMessage();
502
+ return;
503
+ }
301
504
  const ts = now();
302
505
  const inserted = [];
303
506
  db.exec("BEGIN");
@@ -339,7 +542,8 @@ export function handleMachineMessage(context, connection, message) {
339
542
  db.exec("ROLLBACK");
340
543
  throw error;
341
544
  }
342
- const row = db.prepare("SELECT * FROM sessions WHERE id = ?").get(message.sessionId);
545
+ const pendingSessionRow = applyPendingSessionHeadAdvances(db, connection.accountId, message.sessionId, connection.machineId, now());
546
+ const row = pendingSessionRow ?? db.prepare("SELECT * FROM sessions WHERE id = ?").get(message.sessionId);
343
547
  if (row) {
344
548
  const session = sessionSnapshot(row);
345
549
  broadcastControllers(connection.accountId, {
@@ -354,32 +558,79 @@ export function handleMachineMessage(context, connection, message) {
354
558
  acknowledgeMachineMessage();
355
559
  return;
356
560
  }
357
- if (message.type === "machine:event") {
358
- const sessionRow = db
359
- .prepare("SELECT * FROM sessions WHERE id = ? AND account_id = ? AND machine_id = ?")
360
- .get(message.sessionId, connection.accountId, connection.machineId);
361
- if (!sessionRow)
362
- return;
363
- if (aliasedRuntimeEventHasRequestEvents({
561
+ if (message.type === "machine:sessionHeadAdvanced") {
562
+ const ts = now();
563
+ const input = {
364
564
  accountId: connection.accountId,
365
565
  sessionId: message.sessionId,
366
566
  machineId: connection.machineId,
367
- runtimeTurnId: message.turnId,
368
- })) {
567
+ messageId,
568
+ currentHead: message.currentHead,
569
+ lastTurnId: message.lastTurnId,
570
+ basis: message.basis,
571
+ status: message.status,
572
+ ...(message.encryptedMetadata ? { encryptedMetadata: message.encryptedMetadata } : {}),
573
+ };
574
+ const result = applySessionHeadAdvance(db, input, ts);
575
+ if (result.status === "session-not-found") {
576
+ broadcastError(connection.accountId, {
577
+ type: "server:error",
578
+ code: "SESSION_NOT_FOUND",
579
+ message: "Session not found for head advance",
580
+ });
581
+ acknowledgeMachineMessage();
582
+ return;
583
+ }
584
+ if (result.status === "missing") {
585
+ storePendingSessionHeadAdvance(db, input, ts);
586
+ broadcastError(connection.accountId, {
587
+ type: "server:error",
588
+ code: "SESSION_HEAD_BASIS_MISSING",
589
+ message: "Head advance basis event is not available yet; update will be applied when the event arrives",
590
+ });
591
+ acknowledgeMachineMessage();
592
+ return;
593
+ }
594
+ if (result.status === "mismatch") {
595
+ broadcastError(connection.accountId, {
596
+ type: "server:error",
597
+ code: "SESSION_HEAD_BASIS_MISMATCH",
598
+ message: "Head advance basis does not match the stored event",
599
+ });
369
600
  acknowledgeMachineMessage();
370
601
  return;
371
602
  }
603
+ const row = result.session ?? db.prepare("SELECT * FROM sessions WHERE id = ?").get(message.sessionId);
604
+ if (row && row.status !== "closed")
605
+ broadcastControllers(connection.accountId, { type: "server:session", session: sessionSnapshot(row) });
606
+ acknowledgeMachineMessage();
607
+ return;
608
+ }
609
+ if (message.type === "machine:event") {
610
+ const sessionRow = db
611
+ .prepare("SELECT * FROM sessions WHERE id = ? AND account_id = ? AND machine_id = ?")
612
+ .get(message.sessionId, connection.accountId, connection.machineId);
613
+ if (!sessionRow)
614
+ return;
615
+ const closed = sessionRow.status === "closed";
372
616
  const event = insertEvent({
373
617
  accountId: connection.accountId,
374
618
  sessionId: message.sessionId,
375
619
  machineId: connection.machineId,
620
+ source: "machine",
376
621
  messageId: message.messageId,
377
622
  turnId: message.turnId,
378
623
  turnSeq: message.seq,
379
624
  occurredAt: message.occurredAt,
380
625
  payload: message.payload,
626
+ updateSession: !closed,
381
627
  });
382
- broadcastControllers(connection.accountId, { type: "server:event", event });
628
+ const pendingSessionRow = applyPendingSessionHeadAdvances(db, connection.accountId, message.sessionId, connection.machineId, now());
629
+ if (!closed) {
630
+ broadcastControllers(connection.accountId, { type: "server:event", event });
631
+ if (pendingSessionRow && pendingSessionRow.status !== "closed")
632
+ broadcastControllers(connection.accountId, { type: "server:session", session: sessionSnapshot(pendingSessionRow) });
633
+ }
383
634
  acknowledgeMachineMessage();
384
635
  return;
385
636
  }
@@ -395,29 +646,115 @@ export function handleMachineMessage(context, connection, message) {
395
646
  runtimeTurnId: message.lastTurnId ?? message.currentHead,
396
647
  });
397
648
  }
649
+ const runtimeTurnId = message.lastTurnId ?? message.currentHead ?? message.turnId;
650
+ const runtimeBasisEvent = runtimeTurnId
651
+ ? latestEventForTurn(db, connection.accountId, message.sessionId, connection.machineId, runtimeTurnId)
652
+ : undefined;
653
+ const requestBasisEvent = runtimeTurnId !== message.turnId
654
+ ? latestEventForTurn(db, connection.accountId, message.sessionId, connection.machineId, message.turnId)
655
+ : undefined;
656
+ const basisEvent = runtimeBasisEvent ?? requestBasisEvent;
657
+ const basisOrder = basisEvent ? logicalEventOrder(basisEvent) : undefined;
658
+ const requestOrder = requestBasisEvent ? logicalEventOrder(requestBasisEvent) : undefined;
659
+ const sessionRow = db
660
+ .prepare("SELECT * FROM sessions WHERE id = ? AND account_id = ? AND machine_id = ?")
661
+ .get(message.sessionId, connection.accountId, connection.machineId);
662
+ if (!sessionRow) {
663
+ acknowledgeMachineMessage();
664
+ return;
665
+ }
666
+ if (sessionRow.status === "closed") {
667
+ finishSessionClaim({
668
+ accountId: connection.accountId,
669
+ sessionId: message.sessionId,
670
+ turnId: message.turnId,
671
+ terminalStatus: status,
672
+ ...(message.error ? { errorCode: "TURN_ERROR" } : {}),
673
+ finishedAt: ts,
674
+ });
675
+ acknowledgeMachineMessage();
676
+ return;
677
+ }
678
+ const activeClaim = activePromptClaim(db, connection.accountId, message.sessionId, connection.machineId);
679
+ const turnDoneMatchesActiveClaim = !activeClaim || activeClaim.turn_id === message.turnId;
680
+ const currentOrder = sessionHeadBasisOrder(db, sessionRow);
681
+ const basisComparison = basisOrder ? compareHeadBasisOrder(basisOrder, currentOrder) : null;
682
+ const isRuntimeAliasForCurrentRequest = Boolean(runtimeBasisEvent && runtimeTurnId !== message.turnId && (sessionRow.last_turn_id === message.turnId || requestBasisEvent));
683
+ const isInitialTerminal = !sessionRow.last_turn_id && !currentOrder;
684
+ const isTerminalForCurrentTurn = isRuntimeAliasForCurrentRequest ||
685
+ sessionRow.last_turn_id === message.turnId ||
686
+ isInitialTerminal ||
687
+ (sessionRow.status === "running" && !sessionRow.last_turn_id);
688
+ const aliasCompletesCurrentRequest = isRuntimeAliasForCurrentRequest &&
689
+ requestOrder !== undefined &&
690
+ compareHeadBasisOrder(requestOrder, currentOrder) >= 0;
691
+ const shouldApplyTurnDone = turnDoneMatchesActiveClaim &&
692
+ isTerminalForCurrentTurn &&
693
+ (aliasCompletesCurrentRequest || (basisComparison !== null ? basisComparison >= 0 : !currentOrder));
694
+ const shouldApplyHead = shouldApplyTurnDone;
398
695
  db.prepare(`UPDATE sessions
399
696
  SET status = ?,
400
697
  current_head = COALESCE(?, current_head),
401
698
  last_turn_id = COALESCE(?, last_turn_id),
699
+ head_basis_event_id = COALESCE(?, head_basis_event_id),
700
+ head_basis_message_id = COALESCE(?, head_basis_message_id),
701
+ head_basis_logical_time = COALESCE(?, head_basis_logical_time),
702
+ head_basis_turn_seq = COALESCE(?, head_basis_turn_seq),
402
703
  encrypted_metadata = COALESCE(?, encrypted_metadata),
403
704
  updated_at = ?
404
- WHERE id = ? AND account_id = ? AND machine_id = ?`).run(status, message.currentHead ?? null, message.lastTurnId ?? message.turnId, message.encryptedMetadata ? JSON.stringify(message.encryptedMetadata) : null, ts, message.sessionId, connection.accountId, connection.machineId);
705
+ WHERE id = ? AND account_id = ? AND machine_id = ?`).run(shouldApplyTurnDone ? status : sessionRow.status, shouldApplyHead ? message.currentHead ?? null : null, shouldApplyHead ? message.lastTurnId ?? message.turnId : null, shouldApplyHead ? basisEvent?.id ?? null : null, shouldApplyHead ? basisEvent?.message_id ?? null : null, shouldApplyHead ? basisOrder?.time ?? null : null, shouldApplyHead ? basisOrder?.seq ?? null : null, shouldApplyTurnDone && message.encryptedMetadata ? JSON.stringify(message.encryptedMetadata) : null, ts, message.sessionId, connection.accountId, connection.machineId);
405
706
  const row = db.prepare("SELECT * FROM sessions WHERE id = ?").get(message.sessionId);
406
707
  const session = row ? sessionSnapshot(row) : undefined;
407
- if (session)
708
+ if (session && session.status !== "closed")
408
709
  broadcastControllers(connection.accountId, { type: "server:session", session });
409
- if (message.error) {
710
+ if (shouldApplyTurnDone && message.error) {
410
711
  broadcastControllers(connection.accountId, { type: "server:error", message: message.error });
411
712
  }
713
+ if (shouldApplyTurnDone) {
714
+ finishSessionClaim({
715
+ accountId: connection.accountId,
716
+ sessionId: message.sessionId,
717
+ turnId: message.turnId,
718
+ terminalStatus: status,
719
+ ...(message.error ? { errorCode: "TURN_ERROR" } : {}),
720
+ finishedAt: ts,
721
+ });
722
+ }
412
723
  acknowledgeMachineMessage();
413
724
  return;
414
725
  }
415
726
  if (message.type === "machine:error") {
416
727
  const nonFatalSessionErrors = new Set(["CAPABILITY_UNAVAILABLE", "SESSION_BUSY", "SESSION_NAME_INVALID", "SESSION_RENAME_UNSUPPORTED", "SESSION_RENAME_FAILED"]);
417
- if (message.sessionId && !nonFatalSessionErrors.has(message.code ?? "")) {
418
- const session = setSessionStatus(message.sessionId, "failed");
419
- if (session)
420
- broadcastControllers(connection.accountId, { type: "server:session", session });
728
+ if (message.sessionId) {
729
+ if (!nonFatalSessionErrors.has(message.code ?? "")) {
730
+ const row = db
731
+ .prepare("SELECT status FROM sessions WHERE id = ? AND account_id = ? AND machine_id = ?")
732
+ .get(message.sessionId, connection.accountId, connection.machineId);
733
+ if (row?.status === "new" || row?.status === "running") {
734
+ const session = setSessionStatus(message.sessionId, "failed");
735
+ if (session)
736
+ broadcastControllers(connection.accountId, { type: "server:session", session });
737
+ }
738
+ }
739
+ else {
740
+ const row = db
741
+ .prepare("SELECT status FROM sessions WHERE id = ? AND account_id = ? AND machine_id = ?")
742
+ .get(message.sessionId, connection.accountId, connection.machineId);
743
+ if (row?.status === "running" && message.code !== "SESSION_BUSY") {
744
+ const session = setSessionStatus(message.sessionId, "ready");
745
+ if (session)
746
+ broadcastControllers(connection.accountId, { type: "server:session", session });
747
+ }
748
+ }
749
+ }
750
+ if (message.sessionId && message.requestId && message.code !== "SESSION_BUSY") {
751
+ finishSessionClaim({
752
+ accountId: connection.accountId,
753
+ sessionId: message.sessionId,
754
+ requestId: message.requestId,
755
+ terminalStatus: "error",
756
+ errorCode: message.code,
757
+ });
421
758
  }
422
759
  broadcastError(connection.accountId, {
423
760
  type: "server:error",
@@ -432,4 +769,207 @@ export function handleMachineMessage(context, connection, message) {
432
769
  function machineMessageId(message) {
433
770
  return "messageId" in message && typeof message.messageId === "string" ? message.messageId : undefined;
434
771
  }
772
+ function storePendingSessionHeadAdvance(db, input, ts) {
773
+ db.prepare(`INSERT INTO pending_session_head_advances
774
+ (account_id, session_id, machine_id, message_id, current_head, last_turn_id,
775
+ basis_turn_id, basis_event_message_id, basis_turn_seq, basis_occurred_at,
776
+ encrypted_metadata, created_at, updated_at)
777
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
778
+ ON CONFLICT(account_id, machine_id, message_id) WHERE message_id IS NOT NULL
779
+ DO UPDATE SET
780
+ current_head = excluded.current_head,
781
+ last_turn_id = excluded.last_turn_id,
782
+ basis_turn_id = excluded.basis_turn_id,
783
+ basis_event_message_id = excluded.basis_event_message_id,
784
+ basis_turn_seq = excluded.basis_turn_seq,
785
+ basis_occurred_at = excluded.basis_occurred_at,
786
+ encrypted_metadata = excluded.encrypted_metadata,
787
+ updated_at = excluded.updated_at`).run(input.accountId, input.sessionId, input.machineId, input.messageId ?? null, input.currentHead, input.lastTurnId, input.basis.turnId, input.basis.eventMessageId, input.basis.turnSeq, input.basis.occurredAt ?? null, input.encryptedMetadata ? JSON.stringify(input.encryptedMetadata) : null, ts, ts);
788
+ }
789
+ function clearPendingSessionHeadAdvances(db, accountId, sessionId, machineId) {
790
+ db.prepare(`DELETE FROM pending_session_head_advances
791
+ WHERE account_id = ? AND session_id = ? AND machine_id = ?`).run(accountId, sessionId, machineId);
792
+ }
793
+ function applyPendingSessionHeadAdvances(db, accountId, sessionId, machineId, ts) {
794
+ const pending = db
795
+ .prepare(`SELECT * FROM pending_session_head_advances
796
+ WHERE account_id = ? AND session_id = ? AND machine_id = ?
797
+ ORDER BY created_at, id`)
798
+ .all(accountId, sessionId, machineId);
799
+ let latestSession;
800
+ for (const row of pending) {
801
+ const result = applySessionHeadAdvance(db, pendingRowToHeadAdvanceInput(row), ts);
802
+ if (result.status === "missing")
803
+ continue;
804
+ db.prepare("DELETE FROM pending_session_head_advances WHERE id = ?").run(row.id);
805
+ latestSession = result.session ?? latestSession;
806
+ }
807
+ return latestSession;
808
+ }
809
+ function pendingRowToHeadAdvanceInput(row) {
810
+ return {
811
+ accountId: row.account_id,
812
+ sessionId: row.session_id,
813
+ machineId: row.machine_id,
814
+ messageId: row.message_id ?? undefined,
815
+ currentHead: row.current_head,
816
+ lastTurnId: row.last_turn_id,
817
+ basis: {
818
+ turnId: row.basis_turn_id,
819
+ eventMessageId: row.basis_event_message_id,
820
+ turnSeq: row.basis_turn_seq,
821
+ ...(row.basis_occurred_at !== null ? { occurredAt: row.basis_occurred_at } : {}),
822
+ },
823
+ status: "completed",
824
+ ...(row.encrypted_metadata ? { encryptedMetadata: JSON.parse(row.encrypted_metadata) } : {}),
825
+ };
826
+ }
827
+ function applySessionHeadAdvance(db, input, ts) {
828
+ const sessionRow = db
829
+ .prepare("SELECT * FROM sessions WHERE id = ? AND account_id = ? AND machine_id = ?")
830
+ .get(input.sessionId, input.accountId, input.machineId);
831
+ if (!sessionRow)
832
+ return { status: "session-not-found" };
833
+ if (sessionRow.status === "closed")
834
+ return { status: "noop", session: sessionRow };
835
+ const basisEvent = resolveHeadAdvanceBasisEvent(db, input.accountId, input.sessionId, input.machineId, input.basis);
836
+ if (!basisEvent)
837
+ return { status: "missing", session: sessionRow };
838
+ if (basisEvent.turn_id !== input.basis.turnId || basisEvent.turn_seq !== input.basis.turnSeq) {
839
+ return { status: "mismatch", session: sessionRow };
840
+ }
841
+ const nextOrder = logicalEventOrder(basisEvent);
842
+ const currentOrder = sessionHeadBasisOrder(db, sessionRow);
843
+ const rewriteFenced = typeof sessionRow.head_basis_message_id === "string" &&
844
+ sessionRow.head_basis_message_id.startsWith(REWRITE_HEAD_BASIS_PREFIX);
845
+ const comparison = compareHeadBasisOrder(nextOrder, currentOrder);
846
+ const currentHeadIsBasisEvent = sessionRow.current_head === `event:${basisEvent.id}`;
847
+ const currentHeadAlreadySettled = currentHeadIsBasisEvent ||
848
+ sessionRow.current_head === input.currentHead ||
849
+ sessionRow.last_turn_id === input.lastTurnId;
850
+ const shouldAdvance = !rewriteFenced && (comparison > 0 || (comparison === 0 && currentHeadIsBasisEvent));
851
+ const shouldSettleStatus = !rewriteFenced &&
852
+ input.status !== undefined &&
853
+ sessionRow.status === "running" &&
854
+ comparison === 0 &&
855
+ currentHeadAlreadySettled;
856
+ const shouldRefreshMetadata = !rewriteFenced &&
857
+ input.encryptedMetadata !== undefined &&
858
+ currentHeadAlreadySettled;
859
+ if (!shouldAdvance && !shouldSettleStatus && !shouldRefreshMetadata)
860
+ return { status: "noop", session: sessionRow };
861
+ db.prepare(`UPDATE sessions
862
+ SET status = COALESCE(?, status),
863
+ current_head = COALESCE(?, current_head),
864
+ last_turn_id = COALESCE(?, last_turn_id),
865
+ head_basis_event_id = COALESCE(?, head_basis_event_id),
866
+ head_basis_message_id = COALESCE(?, head_basis_message_id),
867
+ head_basis_logical_time = COALESCE(?, head_basis_logical_time),
868
+ head_basis_turn_seq = COALESCE(?, head_basis_turn_seq),
869
+ encrypted_metadata = COALESCE(?, encrypted_metadata),
870
+ updated_at = ?
871
+ WHERE id = ? AND account_id = ? AND machine_id = ?`).run(input.status && sessionRow.status === "running" ? input.status : null, shouldAdvance ? input.currentHead : null, shouldAdvance ? input.lastTurnId : null, shouldAdvance ? basisEvent.id : null, shouldAdvance ? basisEvent.message_id : null, shouldAdvance ? nextOrder.time : null, shouldAdvance ? nextOrder.seq : null, input.encryptedMetadata ? JSON.stringify(input.encryptedMetadata) : null, ts, input.sessionId, input.accountId, input.machineId);
872
+ const session = db.prepare("SELECT * FROM sessions WHERE id = ?").get(input.sessionId);
873
+ return { status: "applied", session };
874
+ }
875
+ function compareHeadBasisOrder(nextOrder, currentOrder) {
876
+ if (!currentOrder)
877
+ return 1;
878
+ if (nextOrder.time !== currentOrder.time)
879
+ return nextOrder.time > currentOrder.time ? 1 : -1;
880
+ if (nextOrder.seq !== currentOrder.seq)
881
+ return nextOrder.seq > currentOrder.seq ? 1 : -1;
882
+ if (nextOrder.id !== currentOrder.id)
883
+ return nextOrder.id > currentOrder.id ? 1 : -1;
884
+ return 0;
885
+ }
886
+ function sessionHeadBasisOrder(db, session) {
887
+ if (session.head_basis_logical_time !== null &&
888
+ session.head_basis_turn_seq !== null) {
889
+ return {
890
+ time: session.head_basis_logical_time,
891
+ seq: session.head_basis_turn_seq,
892
+ id: session.head_basis_event_id ?? 0,
893
+ };
894
+ }
895
+ const eventId = session.current_head ? /^event:(\d+)$/.exec(session.current_head)?.[1] : undefined;
896
+ if (!eventId)
897
+ return undefined;
898
+ const event = db
899
+ .prepare("SELECT * FROM session_events WHERE account_id = ? AND session_id = ? AND machine_id = ? AND id = ?")
900
+ .get(session.account_id, session.id, session.machine_id, Number(eventId));
901
+ return event ? logicalEventOrder(event) : undefined;
902
+ }
903
+ function headAdvanceBasisOrder(basis) {
904
+ return {
905
+ time: basis.occurredAt ?? 0,
906
+ seq: basis.turnSeq,
907
+ id: Number.MAX_SAFE_INTEGER,
908
+ };
909
+ }
910
+ function resolveHeadAdvanceBasisEvent(db, accountId, sessionId, machineId, basis) {
911
+ const exact = db
912
+ .prepare(`SELECT * FROM session_events
913
+ WHERE account_id = ? AND session_id = ? AND machine_id = ? AND message_id = ?`)
914
+ .get(accountId, sessionId, machineId, basis.eventMessageId);
915
+ if (exact)
916
+ return exact;
917
+ return db
918
+ .prepare(`SELECT * FROM session_events
919
+ WHERE account_id = ? AND session_id = ? AND machine_id = ? AND turn_id = ? AND turn_seq = ?
920
+ ORDER BY id DESC
921
+ LIMIT 1`)
922
+ .get(accountId, sessionId, machineId, basis.turnId, basis.turnSeq);
923
+ }
924
+ function logicalEventOrder(event) {
925
+ return logicalEventOrderFromParts({
926
+ id: event.id,
927
+ createdAt: event.created_at,
928
+ messageId: event.message_id ?? undefined,
929
+ occurredAt: event.occurred_at ?? undefined,
930
+ seq: event.seq,
931
+ turnSeq: event.turn_seq ?? undefined,
932
+ });
933
+ }
934
+ function logicalEventOrderFromParts(input) {
935
+ if (input.occurredAt !== undefined) {
936
+ return { time: input.occurredAt, seq: input.turnSeq ?? input.seq ?? input.id, id: input.id };
937
+ }
938
+ if (typeof input.messageId === "string" && input.messageId.startsWith("hist_") && input.turnSeq !== undefined) {
939
+ return { time: 0, seq: input.turnSeq, id: input.id };
940
+ }
941
+ return { time: input.createdAt, seq: input.turnSeq ?? input.seq ?? input.id, id: input.id };
942
+ }
943
+ function latestEventForTurn(db, accountId, sessionId, machineId, turnId) {
944
+ return db
945
+ .prepare(`SELECT * FROM session_events
946
+ WHERE account_id = ? AND session_id = ? AND machine_id = ? AND turn_id = ?
947
+ ORDER BY id DESC
948
+ LIMIT 1`)
949
+ .get(accountId, sessionId, machineId, turnId);
950
+ }
951
+ function activePromptClaim(db, accountId, sessionId, machineId) {
952
+ return db
953
+ .prepare(`SELECT request_id, turn_id
954
+ FROM relay_session_claims
955
+ WHERE account_id = ? AND session_id = ? AND machine_id = ? AND command_type = 'prompt' AND state = 'active'`)
956
+ .get(accountId, sessionId, machineId);
957
+ }
958
+ function recordRuntimeBindingsFromMachineMessage(db, connection, row, message, ts) {
959
+ const runtimeSessionIds = normalizeRuntimeSessionIds([
960
+ message.runtimeSessionId,
961
+ ...(message.runtimeSessionIds ?? []),
962
+ ]);
963
+ if (runtimeSessionIds.length === 0)
964
+ return;
965
+ upsertSessionRuntimeBindings(db, {
966
+ accountId: connection.accountId,
967
+ machineId: connection.machineId,
968
+ agent: row.agent,
969
+ sessionId: row.id,
970
+ runtimeSessionIds,
971
+ status: "active",
972
+ ts,
973
+ });
974
+ }
435
975
  //# sourceMappingURL=machine-handlers.js.map