@graychennpm/codebridge 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (434) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE +21 -0
  3. package/README.md +217 -2
  4. package/README.zh-CN.md +222 -0
  5. package/apps/web/public/brand/agent-logo-carbon.svg +1 -0
  6. package/apps/web/public/brand/agent-logo.svg +1 -0
  7. package/docs/zh-CN/npm-release.md +77 -0
  8. package/node_modules/@codebridge/agent-registry/dist/index.d.ts +32 -0
  9. package/node_modules/@codebridge/agent-registry/dist/index.js +177 -0
  10. package/node_modules/@codebridge/agent-registry/dist/setup.d.ts +9 -0
  11. package/node_modules/@codebridge/agent-registry/dist/setup.js +115 -0
  12. package/node_modules/@codebridge/agent-registry/package.json +17 -0
  13. package/node_modules/@codebridge/backends/dist/acp/acp-active-session.d.ts +12 -0
  14. package/node_modules/@codebridge/backends/dist/acp/acp-active-session.js +57 -0
  15. package/node_modules/@codebridge/backends/dist/acp/acp-claude-activity.d.ts +9 -0
  16. package/node_modules/@codebridge/backends/dist/acp/acp-claude-activity.js +49 -0
  17. package/node_modules/@codebridge/backends/dist/acp/acp-config-options.d.ts +46 -0
  18. package/node_modules/@codebridge/backends/dist/acp/acp-config-options.js +220 -0
  19. package/node_modules/@codebridge/backends/dist/acp/acp-doctor.d.ts +3 -0
  20. package/node_modules/@codebridge/backends/dist/acp/acp-doctor.js +18 -0
  21. package/node_modules/@codebridge/backends/dist/acp/acp-event-mapper.d.ts +5 -0
  22. package/node_modules/@codebridge/backends/dist/acp/acp-event-mapper.js +136 -0
  23. package/node_modules/@codebridge/backends/dist/acp/acp-kill.d.ts +10 -0
  24. package/node_modules/@codebridge/backends/dist/acp/acp-kill.js +24 -0
  25. package/node_modules/@codebridge/backends/dist/acp/acp-race.d.ts +6 -0
  26. package/node_modules/@codebridge/backends/dist/acp/acp-race.js +29 -0
  27. package/node_modules/@codebridge/backends/dist/acp/acp-session-list.d.ts +32 -0
  28. package/node_modules/@codebridge/backends/dist/acp/acp-session-list.js +218 -0
  29. package/node_modules/@codebridge/backends/dist/acp/acp-session-pool.d.ts +85 -0
  30. package/node_modules/@codebridge/backends/dist/acp/acp-session-pool.js +165 -0
  31. package/node_modules/@codebridge/backends/dist/acp/acp-session-runner.d.ts +78 -0
  32. package/node_modules/@codebridge/backends/dist/acp/acp-session-runner.js +550 -0
  33. package/node_modules/@codebridge/backends/dist/acp/acp-spawn-profiles.d.ts +9 -0
  34. package/node_modules/@codebridge/backends/dist/acp/acp-spawn-profiles.js +28 -0
  35. package/node_modules/@codebridge/backends/dist/acp/headless-client.d.ts +19 -0
  36. package/node_modules/@codebridge/backends/dist/acp/headless-client.js +47 -0
  37. package/node_modules/@codebridge/backends/dist/acp/index.d.ts +9 -0
  38. package/node_modules/@codebridge/backends/dist/acp/index.js +9 -0
  39. package/node_modules/@codebridge/backends/dist/agent-setup.d.ts +60 -0
  40. package/node_modules/@codebridge/backends/dist/agent-setup.js +504 -0
  41. package/node_modules/@codebridge/backends/dist/attachment-prompt.d.ts +8 -0
  42. package/node_modules/@codebridge/backends/dist/attachment-prompt.js +28 -0
  43. package/node_modules/@codebridge/backends/dist/auth-error-hints.d.ts +8 -0
  44. package/node_modules/@codebridge/backends/dist/auth-error-hints.js +33 -0
  45. package/node_modules/@codebridge/backends/dist/codex-skill-commands.d.ts +3 -0
  46. package/node_modules/@codebridge/backends/dist/codex-skill-commands.js +88 -0
  47. package/node_modules/@codebridge/backends/dist/index.d.ts +18 -0
  48. package/node_modules/@codebridge/backends/dist/index.js +34 -0
  49. package/node_modules/@codebridge/backends/dist/pi-providers.d.ts +45 -0
  50. package/node_modules/@codebridge/backends/dist/pi-providers.js +148 -0
  51. package/node_modules/@codebridge/backends/dist/pi-session-runner.d.ts +85 -0
  52. package/node_modules/@codebridge/backends/dist/pi-session-runner.js +460 -0
  53. package/node_modules/@codebridge/backends/dist/provider-connection.d.ts +17 -0
  54. package/node_modules/@codebridge/backends/dist/provider-connection.js +99 -0
  55. package/node_modules/@codebridge/backends/dist/session-discovery.d.ts +23 -0
  56. package/node_modules/@codebridge/backends/dist/session-discovery.js +340 -0
  57. package/node_modules/@codebridge/backends/dist/skill-control-plane.d.ts +147 -0
  58. package/node_modules/@codebridge/backends/dist/skill-control-plane.js +832 -0
  59. package/node_modules/@codebridge/backends/package.json +22 -0
  60. package/node_modules/@codebridge/bridge/dist/alert-notification-rules.d.ts +14 -0
  61. package/node_modules/@codebridge/bridge/dist/alert-notification-rules.js +37 -0
  62. package/node_modules/@codebridge/bridge/dist/channel-config.d.ts +4 -0
  63. package/node_modules/@codebridge/bridge/dist/channel-config.js +9 -0
  64. package/node_modules/@codebridge/bridge/dist/channel-ingress.d.ts +5 -0
  65. package/node_modules/@codebridge/bridge/dist/channel-ingress.js +403 -0
  66. package/node_modules/@codebridge/bridge/dist/cli.d.ts +3 -0
  67. package/node_modules/@codebridge/bridge/dist/cli.js +581 -0
  68. package/node_modules/@codebridge/bridge/dist/deployment.d.ts +46 -0
  69. package/node_modules/@codebridge/bridge/dist/deployment.js +174 -0
  70. package/node_modules/@codebridge/bridge/dist/event-loop-lag.d.ts +19 -0
  71. package/node_modules/@codebridge/bridge/dist/event-loop-lag.js +33 -0
  72. package/node_modules/@codebridge/bridge/dist/feishu-alert-monitor.d.ts +70 -0
  73. package/node_modules/@codebridge/bridge/dist/feishu-alert-monitor.js +591 -0
  74. package/node_modules/@codebridge/bridge/dist/init-wizard.d.ts +52 -0
  75. package/node_modules/@codebridge/bridge/dist/init-wizard.js +571 -0
  76. package/node_modules/@codebridge/bridge/dist/mcp-api.d.ts +4 -0
  77. package/node_modules/@codebridge/bridge/dist/mcp-api.js +100 -0
  78. package/node_modules/@codebridge/bridge/dist/outbound-api.d.ts +31 -0
  79. package/node_modules/@codebridge/bridge/dist/outbound-api.js +184 -0
  80. package/node_modules/@codebridge/bridge/dist/outbound-publishers.d.ts +54 -0
  81. package/node_modules/@codebridge/bridge/dist/outbound-publishers.js +213 -0
  82. package/node_modules/@codebridge/bridge/dist/project-api.d.ts +4 -0
  83. package/node_modules/@codebridge/bridge/dist/project-api.js +161 -0
  84. package/node_modules/@codebridge/bridge/dist/secrets-command.d.ts +13 -0
  85. package/node_modules/@codebridge/bridge/dist/secrets-command.js +34 -0
  86. package/node_modules/@codebridge/bridge/dist/session-api.d.ts +26 -0
  87. package/node_modules/@codebridge/bridge/dist/session-api.js +1378 -0
  88. package/node_modules/@codebridge/bridge/dist/session-history-import.d.ts +24 -0
  89. package/node_modules/@codebridge/bridge/dist/session-history-import.js +82 -0
  90. package/node_modules/@codebridge/bridge/dist/session-runtime-api.d.ts +19 -0
  91. package/node_modules/@codebridge/bridge/dist/session-runtime-api.js +453 -0
  92. package/node_modules/@codebridge/bridge/dist/session-runtime-migration.d.ts +21 -0
  93. package/node_modules/@codebridge/bridge/dist/session-runtime-migration.js +43 -0
  94. package/node_modules/@codebridge/bridge/dist/session-runtime-types.d.ts +85 -0
  95. package/node_modules/@codebridge/bridge/dist/session-runtime-types.js +98 -0
  96. package/node_modules/@codebridge/bridge/dist/skill-api.d.ts +28 -0
  97. package/node_modules/@codebridge/bridge/dist/skill-api.js +129 -0
  98. package/node_modules/@codebridge/bridge/dist/startup-surfaces.d.ts +15 -0
  99. package/node_modules/@codebridge/bridge/dist/startup-surfaces.js +13 -0
  100. package/node_modules/@codebridge/bridge/dist/web-frontend.d.ts +8 -0
  101. package/node_modules/@codebridge/bridge/dist/web-frontend.js +76 -0
  102. package/node_modules/@codebridge/bridge/dist/work-item-api.d.ts +6 -0
  103. package/node_modules/@codebridge/bridge/dist/work-item-api.js +414 -0
  104. package/node_modules/@codebridge/bridge/package.json +28 -0
  105. package/node_modules/@codebridge/channel-feishu/dist/alert-reactions.d.ts +6 -0
  106. package/node_modules/@codebridge/channel-feishu/dist/alert-reactions.js +58 -0
  107. package/node_modules/@codebridge/channel-feishu/dist/alert-types.d.ts +35 -0
  108. package/node_modules/@codebridge/channel-feishu/dist/alert-types.js +2 -0
  109. package/node_modules/@codebridge/channel-feishu/dist/bridge.d.ts +130 -0
  110. package/node_modules/@codebridge/channel-feishu/dist/bridge.js +1231 -0
  111. package/node_modules/@codebridge/channel-feishu/dist/cardkit-writer.d.ts +48 -0
  112. package/node_modules/@codebridge/channel-feishu/dist/cardkit-writer.js +153 -0
  113. package/node_modules/@codebridge/channel-feishu/dist/chain-topics.d.ts +20 -0
  114. package/node_modules/@codebridge/channel-feishu/dist/chain-topics.js +35 -0
  115. package/node_modules/@codebridge/channel-feishu/dist/coalescing-card-writer.d.ts +12 -0
  116. package/node_modules/@codebridge/channel-feishu/dist/coalescing-card-writer.js +53 -0
  117. package/node_modules/@codebridge/channel-feishu/dist/delivery-reconciler.d.ts +19 -0
  118. package/node_modules/@codebridge/channel-feishu/dist/delivery-reconciler.js +53 -0
  119. package/node_modules/@codebridge/channel-feishu/dist/durable-markdown-card.d.ts +19 -0
  120. package/node_modules/@codebridge/channel-feishu/dist/durable-markdown-card.js +77 -0
  121. package/node_modules/@codebridge/channel-feishu/dist/feishu-extra-events.d.ts +27 -0
  122. package/node_modules/@codebridge/channel-feishu/dist/feishu-extra-events.js +24 -0
  123. package/node_modules/@codebridge/channel-feishu/dist/feishu-http.d.ts +4 -0
  124. package/node_modules/@codebridge/channel-feishu/dist/feishu-http.js +25 -0
  125. package/node_modules/@codebridge/channel-feishu/dist/feishu-inbound-context.d.ts +13 -0
  126. package/node_modules/@codebridge/channel-feishu/dist/feishu-inbound-context.js +45 -0
  127. package/node_modules/@codebridge/channel-feishu/dist/feishu-inbound-media.d.ts +22 -0
  128. package/node_modules/@codebridge/channel-feishu/dist/feishu-inbound-media.js +273 -0
  129. package/node_modules/@codebridge/channel-feishu/dist/feishu-mention-gate.d.ts +13 -0
  130. package/node_modules/@codebridge/channel-feishu/dist/feishu-mention-gate.js +22 -0
  131. package/node_modules/@codebridge/channel-feishu/dist/feishu-outbound-file.d.ts +12 -0
  132. package/node_modules/@codebridge/channel-feishu/dist/feishu-outbound-file.js +38 -0
  133. package/node_modules/@codebridge/channel-feishu/dist/feishu-quoted-message.d.ts +30 -0
  134. package/node_modules/@codebridge/channel-feishu/dist/feishu-quoted-message.js +183 -0
  135. package/node_modules/@codebridge/channel-feishu/dist/index.d.ts +7 -0
  136. package/node_modules/@codebridge/channel-feishu/dist/index.js +3 -0
  137. package/node_modules/@codebridge/channel-feishu/dist/redacting-logger.d.ts +17 -0
  138. package/node_modules/@codebridge/channel-feishu/dist/redacting-logger.js +41 -0
  139. package/node_modules/@codebridge/channel-feishu/dist/run-status.d.ts +39 -0
  140. package/node_modules/@codebridge/channel-feishu/dist/run-status.js +166 -0
  141. package/node_modules/@codebridge/channel-feishu/dist/session-watcher.d.ts +98 -0
  142. package/node_modules/@codebridge/channel-feishu/dist/session-watcher.js +655 -0
  143. package/node_modules/@codebridge/channel-feishu/package.json +19 -0
  144. package/node_modules/@codebridge/channel-telegram/dist/coalescing-message-writer.d.ts +14 -0
  145. package/node_modules/@codebridge/channel-telegram/dist/coalescing-message-writer.js +56 -0
  146. package/node_modules/@codebridge/channel-telegram/dist/index.d.ts +3 -0
  147. package/node_modules/@codebridge/channel-telegram/dist/index.js +3 -0
  148. package/node_modules/@codebridge/channel-telegram/dist/telegram-api.d.ts +62 -0
  149. package/node_modules/@codebridge/channel-telegram/dist/telegram-api.js +72 -0
  150. package/node_modules/@codebridge/channel-telegram/dist/telegram-bridge.d.ts +64 -0
  151. package/node_modules/@codebridge/channel-telegram/dist/telegram-bridge.js +469 -0
  152. package/node_modules/@codebridge/channel-telegram/dist/telegram-session-watcher.d.ts +41 -0
  153. package/node_modules/@codebridge/channel-telegram/dist/telegram-session-watcher.js +184 -0
  154. package/node_modules/@codebridge/channel-telegram/package.json +18 -0
  155. package/node_modules/@codebridge/core/dist/config-schema.d.ts +1195 -0
  156. package/node_modules/@codebridge/core/dist/config-schema.js +293 -0
  157. package/node_modules/@codebridge/core/dist/config-store.d.ts +48 -0
  158. package/node_modules/@codebridge/core/dist/config-store.js +207 -0
  159. package/node_modules/@codebridge/core/dist/index.d.ts +11 -0
  160. package/node_modules/@codebridge/core/dist/index.js +10 -0
  161. package/node_modules/@codebridge/core/dist/json-file-store.d.ts +16 -0
  162. package/node_modules/@codebridge/core/dist/json-file-store.js +46 -0
  163. package/node_modules/@codebridge/core/dist/mcp-types.d.ts +7 -0
  164. package/node_modules/@codebridge/core/dist/mcp-types.js +2 -0
  165. package/node_modules/@codebridge/core/dist/mentions.d.ts +36 -0
  166. package/node_modules/@codebridge/core/dist/mentions.js +138 -0
  167. package/node_modules/@codebridge/core/dist/secret-migration.d.ts +14 -0
  168. package/node_modules/@codebridge/core/dist/secret-migration.js +55 -0
  169. package/node_modules/@codebridge/core/dist/secret-refs.d.ts +34 -0
  170. package/node_modules/@codebridge/core/dist/secret-refs.js +142 -0
  171. package/node_modules/@codebridge/core/dist/session-event-wire.d.ts +17 -0
  172. package/node_modules/@codebridge/core/dist/session-event-wire.js +28 -0
  173. package/node_modules/@codebridge/core/dist/types.d.ts +363 -0
  174. package/node_modules/@codebridge/core/dist/types.js +22 -0
  175. package/node_modules/@codebridge/core/dist/workspace-key.d.ts +11 -0
  176. package/node_modules/@codebridge/core/dist/workspace-key.js +25 -0
  177. package/node_modules/@codebridge/core/package.json +22 -0
  178. package/node_modules/@codebridge/mcp-runtime/dist/.tsbuildinfo +1 -0
  179. package/node_modules/@codebridge/mcp-runtime/dist/index.d.ts +92 -0
  180. package/node_modules/@codebridge/mcp-runtime/dist/index.js +377 -0
  181. package/node_modules/@codebridge/mcp-runtime/package.json +19 -0
  182. package/node_modules/@codebridge/policy/dist/capability-runtime.d.ts +123 -0
  183. package/node_modules/@codebridge/policy/dist/capability-runtime.js +195 -0
  184. package/node_modules/@codebridge/policy/dist/demo-capabilities.d.ts +4 -0
  185. package/node_modules/@codebridge/policy/dist/demo-capabilities.js +134 -0
  186. package/node_modules/@codebridge/policy/dist/equity-capabilities.d.ts +8 -0
  187. package/node_modules/@codebridge/policy/dist/equity-capabilities.js +35 -0
  188. package/node_modules/@codebridge/policy/dist/index.d.ts +107 -0
  189. package/node_modules/@codebridge/policy/dist/index.js +317 -0
  190. package/node_modules/@codebridge/policy/package.json +17 -0
  191. package/node_modules/@codebridge/project-catalog/dist/index.d.ts +145 -0
  192. package/node_modules/@codebridge/project-catalog/dist/index.js +699 -0
  193. package/node_modules/@codebridge/project-catalog/package.json +18 -0
  194. package/node_modules/@codebridge/router/dist/channel-stream-projector.d.ts +19 -0
  195. package/node_modules/@codebridge/router/dist/channel-stream-projector.js +68 -0
  196. package/node_modules/@codebridge/router/dist/command-help.d.ts +14 -0
  197. package/node_modules/@codebridge/router/dist/command-help.js +151 -0
  198. package/node_modules/@codebridge/router/dist/feishu-stream-presenter.d.ts +18 -0
  199. package/node_modules/@codebridge/router/dist/feishu-stream-presenter.js +193 -0
  200. package/node_modules/@codebridge/router/dist/index.d.ts +9 -0
  201. package/node_modules/@codebridge/router/dist/index.js +9 -0
  202. package/node_modules/@codebridge/router/dist/model-effort.d.ts +5 -0
  203. package/node_modules/@codebridge/router/dist/model-effort.js +33 -0
  204. package/node_modules/@codebridge/router/dist/orchestrator.d.ts +56 -0
  205. package/node_modules/@codebridge/router/dist/orchestrator.js +290 -0
  206. package/node_modules/@codebridge/router/dist/session-list-format.d.ts +19 -0
  207. package/node_modules/@codebridge/router/dist/session-list-format.js +97 -0
  208. package/node_modules/@codebridge/router/dist/session-rotation.d.ts +9 -0
  209. package/node_modules/@codebridge/router/dist/session-rotation.js +31 -0
  210. package/node_modules/@codebridge/router/dist/session-router.d.ts +59 -0
  211. package/node_modules/@codebridge/router/dist/session-router.js +182 -0
  212. package/node_modules/@codebridge/router/dist/slash-commands.d.ts +78 -0
  213. package/node_modules/@codebridge/router/dist/slash-commands.js +874 -0
  214. package/node_modules/@codebridge/router/package.json +18 -0
  215. package/node_modules/@codebridge/run-executor/dist/agent-event-aggregator.d.ts +18 -0
  216. package/node_modules/@codebridge/run-executor/dist/agent-event-aggregator.js +88 -0
  217. package/node_modules/@codebridge/run-executor/dist/index.d.ts +55 -0
  218. package/node_modules/@codebridge/run-executor/dist/index.js +754 -0
  219. package/node_modules/@codebridge/run-executor/dist/run-heartbeat.d.ts +14 -0
  220. package/node_modules/@codebridge/run-executor/dist/run-heartbeat.js +24 -0
  221. package/node_modules/@codebridge/run-executor/package.json +20 -0
  222. package/node_modules/@codebridge/runner-client/dist/index.d.ts +142 -0
  223. package/node_modules/@codebridge/runner-client/dist/index.js +439 -0
  224. package/node_modules/@codebridge/runner-client/package.json +18 -0
  225. package/node_modules/@codebridge/runner-host/dist/cli.d.ts +3 -0
  226. package/node_modules/@codebridge/runner-host/dist/cli.js +58 -0
  227. package/node_modules/@codebridge/runner-host/dist/codex-session-ownership.d.ts +13 -0
  228. package/node_modules/@codebridge/runner-host/dist/codex-session-ownership.js +79 -0
  229. package/node_modules/@codebridge/runner-host/dist/deployment-mcp-server.d.ts +10 -0
  230. package/node_modules/@codebridge/runner-host/dist/deployment-mcp-server.js +54 -0
  231. package/node_modules/@codebridge/runner-host/dist/fcb-script.d.ts +3 -0
  232. package/node_modules/@codebridge/runner-host/dist/fcb-script.js +99 -0
  233. package/node_modules/@codebridge/runner-host/dist/index.d.ts +3 -0
  234. package/node_modules/@codebridge/runner-host/dist/index.js +2 -0
  235. package/node_modules/@codebridge/runner-host/dist/materialize-attachments.d.ts +4 -0
  236. package/node_modules/@codebridge/runner-host/dist/materialize-attachments.js +62 -0
  237. package/node_modules/@codebridge/runner-host/dist/server.d.ts +150 -0
  238. package/node_modules/@codebridge/runner-host/dist/server.js +1295 -0
  239. package/node_modules/@codebridge/runner-host/dist/session-lease.d.ts +12 -0
  240. package/node_modules/@codebridge/runner-host/dist/session-lease.js +146 -0
  241. package/node_modules/@codebridge/runner-host/package.json +26 -0
  242. package/node_modules/@codebridge/session-catalog/dist/index.d.ts +124 -0
  243. package/node_modules/@codebridge/session-catalog/dist/index.js +411 -0
  244. package/node_modules/@codebridge/session-catalog/package.json +17 -0
  245. package/node_modules/@codebridge/session-coordinator/dist/coordinator.d.ts +111 -0
  246. package/node_modules/@codebridge/session-coordinator/dist/coordinator.js +364 -0
  247. package/node_modules/@codebridge/session-coordinator/dist/index.d.ts +5 -0
  248. package/node_modules/@codebridge/session-coordinator/dist/index.js +5 -0
  249. package/node_modules/@codebridge/session-coordinator/dist/lease.d.ts +14 -0
  250. package/node_modules/@codebridge/session-coordinator/dist/lease.js +26 -0
  251. package/node_modules/@codebridge/session-coordinator/dist/queued-claim.d.ts +20 -0
  252. package/node_modules/@codebridge/session-coordinator/dist/queued-claim.js +45 -0
  253. package/node_modules/@codebridge/session-coordinator/dist/recovery.d.ts +31 -0
  254. package/node_modules/@codebridge/session-coordinator/dist/recovery.js +114 -0
  255. package/node_modules/@codebridge/session-coordinator/package.json +17 -0
  256. package/node_modules/@codebridge/web/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  257. package/node_modules/@codebridge/web/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  258. package/node_modules/@codebridge/web/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  259. package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  260. package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  261. package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  262. package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  263. package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  264. package/node_modules/@codebridge/web/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  265. package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  266. package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  267. package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  268. package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  269. package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  270. package/node_modules/@codebridge/web/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  271. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  272. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  273. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  274. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  275. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  276. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  277. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  278. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  279. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  280. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  281. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  282. package/node_modules/@codebridge/web/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  283. package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  284. package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  285. package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  286. package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  287. package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  288. package/node_modules/@codebridge/web/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  289. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  290. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  291. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  292. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  293. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  294. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  295. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  296. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  297. package/node_modules/@codebridge/web/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  298. package/node_modules/@codebridge/web/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  299. package/node_modules/@codebridge/web/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  300. package/node_modules/@codebridge/web/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  301. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  302. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  303. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  304. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  305. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  306. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  307. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  308. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  309. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  310. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  311. package/node_modules/@codebridge/web/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  312. package/node_modules/@codebridge/web/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  313. package/node_modules/@codebridge/web/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  314. package/node_modules/@codebridge/web/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  315. package/node_modules/@codebridge/web/dist/assets/abnfDiagram-N423BO3Z-C-JdFv0U.js +1 -0
  316. package/node_modules/@codebridge/web/dist/assets/arc-DsNROjzU.js +1 -0
  317. package/node_modules/@codebridge/web/dist/assets/architecture-TIHT7OUA-ZEBHG2JZ.js +1 -0
  318. package/node_modules/@codebridge/web/dist/assets/architectureDiagram-T3A2C74G-OsrxcwPM.js +36 -0
  319. package/node_modules/@codebridge/web/dist/assets/array-BifhSqXX.js +1 -0
  320. package/node_modules/@codebridge/web/dist/assets/blockDiagram-VBNYF7ZC-DRgfNeNW.js +132 -0
  321. package/node_modules/@codebridge/web/dist/assets/c4Diagram-5PPSVZJV-BtOGKTh8.js +10 -0
  322. package/node_modules/@codebridge/web/dist/assets/channel-MhXyjxUS.js +1 -0
  323. package/node_modules/@codebridge/web/dist/assets/chunk-2GRJ4B5K-Dy1gJ7sY.js +1 -0
  324. package/node_modules/@codebridge/web/dist/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  325. package/node_modules/@codebridge/web/dist/assets/chunk-4I5QYGJK-1pOLR_SG.js +1 -0
  326. package/node_modules/@codebridge/web/dist/assets/chunk-5RXB4S5H-CP43rgsO.js +231 -0
  327. package/node_modules/@codebridge/web/dist/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  328. package/node_modules/@codebridge/web/dist/assets/chunk-6Q2QTUOP-Bi3Xrp6W.js +88 -0
  329. package/node_modules/@codebridge/web/dist/assets/chunk-7BUUIJ7U-Bb538aSH.js +1 -0
  330. package/node_modules/@codebridge/web/dist/assets/chunk-7Z6QIM7H-CILAW2Nk.js +10 -0
  331. package/node_modules/@codebridge/web/dist/assets/chunk-GF5L2VYU-CAp09yhq.js +206 -0
  332. package/node_modules/@codebridge/web/dist/assets/chunk-I66GZJ75-B_rJXmNu.js +128 -0
  333. package/node_modules/@codebridge/web/dist/assets/chunk-JQJVKLGR-OVeOJFCx.js +156 -0
  334. package/node_modules/@codebridge/web/dist/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  335. package/node_modules/@codebridge/web/dist/assets/chunk-KBJHAD2P-uaupp0k5.js +1 -0
  336. package/node_modules/@codebridge/web/dist/assets/chunk-KEIR6QF5-BICK3FdT.js +161 -0
  337. package/node_modules/@codebridge/web/dist/assets/chunk-NSK5VX7P-fIHF5wwn.js +2 -0
  338. package/node_modules/@codebridge/web/dist/assets/chunk-QR6OTTB3-DxkJuF2b.js +62 -0
  339. package/node_modules/@codebridge/web/dist/assets/chunk-RYQCIY6F-CC5j3u-X.js +1 -0
  340. package/node_modules/@codebridge/web/dist/assets/chunk-UBXNYLIW-DB35O-6R.js +1 -0
  341. package/node_modules/@codebridge/web/dist/assets/chunk-W5SLKNZC-bkRBsbq-.js +1 -0
  342. package/node_modules/@codebridge/web/dist/assets/chunk-WRU74C26-DwvEoD-1.js +70 -0
  343. package/node_modules/@codebridge/web/dist/assets/chunk-XXDRQBXY-DRyYA-HY.js +1 -0
  344. package/node_modules/@codebridge/web/dist/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  345. package/node_modules/@codebridge/web/dist/assets/classDiagram-JCYQIIEL-B8r7z8ii.js +1 -0
  346. package/node_modules/@codebridge/web/dist/assets/classDiagram-v2-OCEON4UE-B8r7z8ii.js +1 -0
  347. package/node_modules/@codebridge/web/dist/assets/cose-bilkent-JH36ORCC-CLkwlrX7.js +1 -0
  348. package/node_modules/@codebridge/web/dist/assets/cynefin-VYW2F7L2-C3_Llw02.js +1 -0
  349. package/node_modules/@codebridge/web/dist/assets/cynefinDiagram-MW4NZA55-D5v7UnJy.js +62 -0
  350. package/node_modules/@codebridge/web/dist/assets/cytoscape.esm-B-NFISlW.js +321 -0
  351. package/node_modules/@codebridge/web/dist/assets/dagre-Buvkdvvj.js +1 -0
  352. package/node_modules/@codebridge/web/dist/assets/dagre-VZM6K2ZE-Cr0IibwW.js +4 -0
  353. package/node_modules/@codebridge/web/dist/assets/defaultLocale-BFoDCU3G.js +1 -0
  354. package/node_modules/@codebridge/web/dist/assets/diagram-7IWD3JNH-CpQXDIzA.js +30 -0
  355. package/node_modules/@codebridge/web/dist/assets/diagram-B4RE2ZJO-VaOkH0Ya.js +3 -0
  356. package/node_modules/@codebridge/web/dist/assets/diagram-LBJQPF4R-D0iXyNks.js +24 -0
  357. package/node_modules/@codebridge/web/dist/assets/diagram-Q27KOJAE-CtqYk01P.js +24 -0
  358. package/node_modules/@codebridge/web/dist/assets/diagram-UB23O5K3-CFnd3H1_.js +41 -0
  359. package/node_modules/@codebridge/web/dist/assets/dist-D2L7nRdk.js +1 -0
  360. package/node_modules/@codebridge/web/dist/assets/ebnfDiagram-BXEA7PRR-B0GIbJYt.js +1 -0
  361. package/node_modules/@codebridge/web/dist/assets/erDiagram-JOGREHBK-BApaLGVA.js +85 -0
  362. package/node_modules/@codebridge/web/dist/assets/eventmodeling-45OFAUF4-DqGGjcld.js +1 -0
  363. package/node_modules/@codebridge/web/dist/assets/flowDiagram-UKHOOZJN-I_qlizLH.js +1 -0
  364. package/node_modules/@codebridge/web/dist/assets/ganttDiagram-PKOTCBZU-B-QZ-J82.js +292 -0
  365. package/node_modules/@codebridge/web/dist/assets/gitGraph-TEB2WS4Q-DK2SJ2Ne.js +1 -0
  366. package/node_modules/@codebridge/web/dist/assets/gitGraphDiagram-DS77QQ5N-B6Z-pu0D.js +106 -0
  367. package/node_modules/@codebridge/web/dist/assets/graphlib-DS17s2tU.js +1 -0
  368. package/node_modules/@codebridge/web/dist/assets/index-8BzpyygS.js +559 -0
  369. package/node_modules/@codebridge/web/dist/assets/index-Bzaz89LE.css +1 -0
  370. package/node_modules/@codebridge/web/dist/assets/info-DKCQHKI2-CGWxt_Py.js +1 -0
  371. package/node_modules/@codebridge/web/dist/assets/infoDiagram-6WML65LV-77XjrPZs.js +2 -0
  372. package/node_modules/@codebridge/web/dist/assets/init-C-OQMol4.js +1 -0
  373. package/node_modules/@codebridge/web/dist/assets/ishikawaDiagram-WSZJBQD7-P1bZAz2x.js +70 -0
  374. package/node_modules/@codebridge/web/dist/assets/journeyDiagram-NVQOT4AX-C4rwMcBY.js +139 -0
  375. package/node_modules/@codebridge/web/dist/assets/kanban-definition-27J2QSJJ-mtw4a9bc.js +89 -0
  376. package/node_modules/@codebridge/web/dist/assets/line-DP4RkYqm.js +1 -0
  377. package/node_modules/@codebridge/web/dist/assets/linear-DMg3PPio.js +1 -0
  378. package/node_modules/@codebridge/web/dist/assets/map-BaFkSB1l.js +1 -0
  379. package/node_modules/@codebridge/web/dist/assets/mermaid-parser.core-HY84kHw1.js +7 -0
  380. package/node_modules/@codebridge/web/dist/assets/mermaid.core-DdgCdsnM.js +42 -0
  381. package/node_modules/@codebridge/web/dist/assets/mindmap-definition-FAOFIHXS-Cw1EnbhZ.js +96 -0
  382. package/node_modules/@codebridge/web/dist/assets/ordinal-BDEzSJ7C.js +1 -0
  383. package/node_modules/@codebridge/web/dist/assets/packet-7NZHBO7P-CEbrbJH3.js +1 -0
  384. package/node_modules/@codebridge/web/dist/assets/path-fybaL0A-.js +1 -0
  385. package/node_modules/@codebridge/web/dist/assets/pegDiagram-VL7TDLO6-CEc1Gedb.js +1 -0
  386. package/node_modules/@codebridge/web/dist/assets/pie-RZYD4A2V-DPXVs-IW.js +1 -0
  387. package/node_modules/@codebridge/web/dist/assets/pieDiagram-7S7Q4E2Y-hoQeGMFH.js +39 -0
  388. package/node_modules/@codebridge/web/dist/assets/quadrantDiagram-CIZ2JOQS-C-Nmxx0f.js +7 -0
  389. package/node_modules/@codebridge/web/dist/assets/radar-I7S5WNFK-BVd3X3Pd.js +1 -0
  390. package/node_modules/@codebridge/web/dist/assets/railroad-3IZDKUUU-CxLxzr_v.js +1 -0
  391. package/node_modules/@codebridge/web/dist/assets/railroad-abnf-AHOZXSZD-MA1zPI84.js +1 -0
  392. package/node_modules/@codebridge/web/dist/assets/railroad-ebnf-EBAXGLYW-Bqug_umD.js +1 -0
  393. package/node_modules/@codebridge/web/dist/assets/railroad-peg-LSFZ7HO6-DRcRFwpq.js +1 -0
  394. package/node_modules/@codebridge/web/dist/assets/railroadDiagram-AXF67PYL-B007ZkL9.js +1 -0
  395. package/node_modules/@codebridge/web/dist/assets/requirementDiagram-LRYGKXZP-LrTCcEi5.js +84 -0
  396. package/node_modules/@codebridge/web/dist/assets/rough.esm-Dy-Kn_BL.js +1 -0
  397. package/node_modules/@codebridge/web/dist/assets/sankeyDiagram-W5VNT64P-Ch4mzHck.js +40 -0
  398. package/node_modules/@codebridge/web/dist/assets/sequenceDiagram-SI44F4Z6-CHg4OzLX.js +162 -0
  399. package/node_modules/@codebridge/web/dist/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +1 -0
  400. package/node_modules/@codebridge/web/dist/assets/src-BrO6_odD.js +1 -0
  401. package/node_modules/@codebridge/web/dist/assets/stateDiagram-OKZ733FA-7cVkr5nR.js +1 -0
  402. package/node_modules/@codebridge/web/dist/assets/stateDiagram-v2-UEYNNEHI-CTy_mAXb.js +1 -0
  403. package/node_modules/@codebridge/web/dist/assets/swimlanes-SLNWSIFB-BwSVF5qy.js +2 -0
  404. package/node_modules/@codebridge/web/dist/assets/swimlanesDiagram-ULZ7WXOC-BBQnfZ1j.js +8 -0
  405. package/node_modules/@codebridge/web/dist/assets/timeline-definition-Z64GVDOM-BaHEkVDV.js +120 -0
  406. package/node_modules/@codebridge/web/dist/assets/treeView-QDETBFTQ-CF0kLN62.js +1 -0
  407. package/node_modules/@codebridge/web/dist/assets/treemap-6X3UGDF4-BB8A8uux.js +1 -0
  408. package/node_modules/@codebridge/web/dist/assets/vennDiagram-T6HMQDX7-BFK12Iro.js +34 -0
  409. package/node_modules/@codebridge/web/dist/assets/wardley-OPB4EBWU-C_3y61zk.js +1 -0
  410. package/node_modules/@codebridge/web/dist/assets/wardleyDiagram-T6FBY63Y-W2oGu4WK.js +78 -0
  411. package/node_modules/@codebridge/web/dist/assets/xychartDiagram-ELKLHX3M-BiVRnbvz.js +7 -0
  412. package/node_modules/@codebridge/web/dist/brand/agent-logo-carbon.svg +1 -0
  413. package/node_modules/@codebridge/web/dist/brand/agent-logo.svg +1 -0
  414. package/node_modules/@codebridge/web/dist/brand/agnet-logo-carbon.svg +1 -0
  415. package/node_modules/@codebridge/web/dist/brand/agnet-logo.svg +1 -0
  416. package/node_modules/@codebridge/web/dist/brand/agnet-mark-carbon.svg +1 -0
  417. package/node_modules/@codebridge/web/dist/brand/agnet-mark.svg +1 -0
  418. package/node_modules/@codebridge/web/dist/fonts/CommitMono-400-Regular.otf +0 -0
  419. package/node_modules/@codebridge/web/dist/fonts/CommitMono-700-Regular.otf +0 -0
  420. package/node_modules/@codebridge/web/dist/fonts/CommitMono-OFL.txt +21 -0
  421. package/node_modules/@codebridge/web/dist/fonts/DepartureMono-OFL.txt +21 -0
  422. package/node_modules/@codebridge/web/dist/fonts/DepartureMono-Regular.woff2 +0 -0
  423. package/node_modules/@codebridge/web/dist/index.html +25 -0
  424. package/node_modules/@codebridge/web/package.json +7 -0
  425. package/node_modules/@codebridge/work-items/dist/index.d.ts +371 -0
  426. package/node_modules/@codebridge/work-items/dist/index.js +1784 -0
  427. package/node_modules/@codebridge/work-items/dist/session-projector.d.ts +4 -0
  428. package/node_modules/@codebridge/work-items/dist/session-projector.js +506 -0
  429. package/node_modules/@codebridge/work-items/dist/session-runtime.d.ts +274 -0
  430. package/node_modules/@codebridge/work-items/dist/session-runtime.js +1103 -0
  431. package/node_modules/@codebridge/work-items/dist/session-schema.d.ts +9 -0
  432. package/node_modules/@codebridge/work-items/dist/session-schema.js +292 -0
  433. package/node_modules/@codebridge/work-items/package.json +20 -0
  434. package/package.json +75 -4
@@ -0,0 +1,1784 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { createHash, randomUUID } from "node:crypto";
4
+ import { createRequire } from "node:module";
5
+ import { initializeSessionRuntimeSchema } from "./session-schema.js";
6
+ import { projectSessionEvent } from "./session-projector.js";
7
+ import { appendSessionEventInTransaction, createSqliteSessionRuntimeTransaction, importProviderHistory, parseSessionTurnMessage, resolveRunExecutionKind, } from "./session-runtime.js";
8
+ const { DatabaseSync } = createRequire(import.meta.url)("node:sqlite");
9
+ const STATUS_BY_EVENT = {
10
+ PLAN_PROPOSED: "planned",
11
+ APPROVAL_REQUESTED: "awaiting_approval",
12
+ RUN_CANCELLED: "cancelled",
13
+ STEP_STARTED: "executing",
14
+ VERIFICATION_COMPLETED: "verifying",
15
+ STEP_FAILED: "failed",
16
+ WORK_ITEM_COMPLETED: "completed",
17
+ };
18
+ export class SqliteEventStore {
19
+ database;
20
+ transactionDepth = 0;
21
+ constructor(databasePath) {
22
+ if (databasePath !== ":memory:") {
23
+ fs.mkdirSync(path.dirname(databasePath), { recursive: true });
24
+ }
25
+ this.database = new DatabaseSync(databasePath);
26
+ this.database.exec("PRAGMA busy_timeout = 5000;");
27
+ if (databasePath !== ":memory:") {
28
+ this.database.exec("PRAGMA journal_mode = WAL;");
29
+ }
30
+ this.database.exec(`
31
+ PRAGMA foreign_keys = ON;
32
+
33
+ CREATE TABLE IF NOT EXISTS work_items (
34
+ id TEXT PRIMARY KEY,
35
+ schema_version INTEGER NOT NULL,
36
+ title TEXT NOT NULL,
37
+ status TEXT NOT NULL,
38
+ mode TEXT NOT NULL,
39
+ conversation_id TEXT NOT NULL,
40
+ agent_id TEXT,
41
+ workflow_id TEXT,
42
+ workflow_revision TEXT,
43
+ workspace_scope TEXT NOT NULL,
44
+ identifiers TEXT NOT NULL,
45
+ context_revision INTEGER NOT NULL,
46
+ risk_level TEXT NOT NULL,
47
+ created_at TEXT NOT NULL,
48
+ updated_at TEXT NOT NULL
49
+ );
50
+
51
+ CREATE TABLE IF NOT EXISTS domain_events (
52
+ event_id TEXT PRIMARY KEY,
53
+ schema_version INTEGER NOT NULL,
54
+ sequence INTEGER NOT NULL,
55
+ work_item_id TEXT NOT NULL,
56
+ run_id TEXT,
57
+ execution_kind TEXT CHECK (execution_kind IN ('agent', 'flow') OR execution_kind IS NULL),
58
+ type TEXT NOT NULL,
59
+ occurred_at TEXT NOT NULL,
60
+ actor TEXT NOT NULL,
61
+ target TEXT,
62
+ input_hash TEXT,
63
+ result_ref TEXT,
64
+ payload TEXT NOT NULL,
65
+ FOREIGN KEY (work_item_id) REFERENCES work_items(id),
66
+ UNIQUE (work_item_id, sequence)
67
+ );
68
+
69
+ CREATE INDEX IF NOT EXISTS domain_events_work_item_sequence
70
+ ON domain_events (work_item_id, sequence);
71
+
72
+ CREATE INDEX IF NOT EXISTS domain_events_target_sequence
73
+ ON domain_events (target, sequence);
74
+
75
+ CREATE TABLE IF NOT EXISTS runs (
76
+ id TEXT PRIMARY KEY,
77
+ schema_version INTEGER NOT NULL,
78
+ work_item_id TEXT NOT NULL,
79
+ mode TEXT NOT NULL,
80
+ status TEXT NOT NULL,
81
+ execution_kind TEXT NOT NULL DEFAULT 'agent'
82
+ CHECK (execution_kind IN ('agent', 'flow')),
83
+ agent_id TEXT,
84
+ plan_id TEXT,
85
+ workflow_revision TEXT,
86
+ created_at TEXT NOT NULL,
87
+ updated_at TEXT NOT NULL,
88
+ FOREIGN KEY (work_item_id) REFERENCES work_items(id)
89
+ );
90
+
91
+ CREATE INDEX IF NOT EXISTS runs_work_item_created
92
+ ON runs (work_item_id, created_at);
93
+
94
+ CREATE TABLE IF NOT EXISTS message_attachments (
95
+ id TEXT PRIMARY KEY,
96
+ schema_version INTEGER NOT NULL,
97
+ work_item_id TEXT NOT NULL,
98
+ name TEXT NOT NULL,
99
+ mime_type TEXT NOT NULL,
100
+ data_base64 TEXT NOT NULL,
101
+ byte_size INTEGER NOT NULL,
102
+ content_hash TEXT NOT NULL,
103
+ created_at TEXT NOT NULL,
104
+ FOREIGN KEY (work_item_id) REFERENCES work_items(id) ON DELETE CASCADE
105
+ );
106
+ CREATE INDEX IF NOT EXISTS message_attachments_work_item_created
107
+ ON message_attachments (work_item_id, created_at);
108
+
109
+ CREATE TABLE IF NOT EXISTS plans (
110
+ plan_id TEXT PRIMARY KEY,
111
+ schema_version INTEGER NOT NULL,
112
+ source TEXT NOT NULL,
113
+ workflow_id TEXT NOT NULL,
114
+ definition_revision TEXT,
115
+ session_id TEXT,
116
+ run_id TEXT UNIQUE,
117
+ steps TEXT NOT NULL,
118
+ created_at TEXT NOT NULL
119
+ );
120
+
121
+ CREATE TABLE IF NOT EXISTS idempotency_responses (
122
+ namespace TEXT NOT NULL,
123
+ idempotency_key TEXT NOT NULL,
124
+ response TEXT NOT NULL,
125
+ created_at TEXT NOT NULL,
126
+ PRIMARY KEY (namespace, idempotency_key)
127
+ );
128
+
129
+ CREATE TABLE IF NOT EXISTS artifacts (
130
+ id TEXT PRIMARY KEY,
131
+ work_item_id TEXT NOT NULL,
132
+ run_id TEXT NOT NULL,
133
+ step_id TEXT,
134
+ kind TEXT NOT NULL,
135
+ name TEXT NOT NULL,
136
+ mime_type TEXT NOT NULL,
137
+ content TEXT NOT NULL,
138
+ content_hash TEXT NOT NULL,
139
+ metadata TEXT NOT NULL,
140
+ created_at TEXT NOT NULL,
141
+ FOREIGN KEY (work_item_id) REFERENCES work_items(id),
142
+ FOREIGN KEY (run_id) REFERENCES runs(id)
143
+ );
144
+ CREATE INDEX IF NOT EXISTS artifacts_run_created ON artifacts (run_id, created_at);
145
+
146
+ CREATE TABLE IF NOT EXISTS verifications (
147
+ id TEXT PRIMARY KEY,
148
+ work_item_id TEXT NOT NULL,
149
+ run_id TEXT NOT NULL,
150
+ step_id TEXT,
151
+ validator TEXT NOT NULL,
152
+ status TEXT NOT NULL,
153
+ summary TEXT NOT NULL,
154
+ artifact_ids TEXT NOT NULL,
155
+ created_at TEXT NOT NULL,
156
+ FOREIGN KEY (work_item_id) REFERENCES work_items(id),
157
+ FOREIGN KEY (run_id) REFERENCES runs(id)
158
+ );
159
+ CREATE INDEX IF NOT EXISTS verifications_run_created ON verifications (run_id, created_at);
160
+ `);
161
+ for (const statement of [
162
+ "ALTER TABLE runs ADD COLUMN workflow_revision TEXT",
163
+ "ALTER TABLE plans ADD COLUMN plan_ir_hash TEXT",
164
+ "ALTER TABLE runs ADD COLUMN plan_ir_hash TEXT",
165
+ ]) {
166
+ try {
167
+ this.database.exec(statement);
168
+ }
169
+ catch { /* Existing databases already contain the column. */ }
170
+ }
171
+ initializeSessionRuntimeSchema(this.database);
172
+ }
173
+ createWorkItem(input) {
174
+ const now = new Date().toISOString();
175
+ const workItem = {
176
+ schemaVersion: 1,
177
+ id: input.id ?? createId("wi"),
178
+ title: input.title,
179
+ status: "created",
180
+ mode: input.mode,
181
+ conversationId: input.conversationId,
182
+ sessionId: input.sessionId ?? null,
183
+ agentId: input.agentId ?? null,
184
+ workflowId: input.workflowId ?? null,
185
+ workflowRevision: input.workflowRevision ?? null,
186
+ workspaceScope: [...(input.workspaceScope ?? [])],
187
+ identifiers: { ...(input.identifiers ?? {}) },
188
+ contextRevision: input.contextRevision ?? 1,
189
+ riskLevel: input.riskLevel,
190
+ createdAt: now,
191
+ updatedAt: now,
192
+ };
193
+ this.withTransaction(() => {
194
+ this.database
195
+ .prepare(`INSERT INTO work_items (
196
+ id, schema_version, title, status, mode, conversation_id,
197
+ session_id, agent_id, workflow_id, workflow_revision, workspace_scope,
198
+ identifiers, context_revision, risk_level, created_at, updated_at
199
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
200
+ .run(workItem.id, workItem.schemaVersion, workItem.title, workItem.status, workItem.mode, workItem.conversationId, workItem.sessionId, workItem.agentId, workItem.workflowId, workItem.workflowRevision, JSON.stringify(workItem.workspaceScope), JSON.stringify(workItem.identifiers), workItem.contextRevision, workItem.riskLevel, workItem.createdAt, workItem.updatedAt);
201
+ if (workItem.sessionId) {
202
+ this.database
203
+ .prepare(`INSERT INTO session_runtime (
204
+ session_id, active_run_id, queue_state, queue_pause_reason,
205
+ last_event_sequence, version, updated_at
206
+ ) VALUES (?, NULL, 'ready', NULL, 0, 1, ?)`)
207
+ .run(workItem.sessionId, workItem.createdAt);
208
+ }
209
+ this.appendEventInTransaction({
210
+ workItemId: workItem.id,
211
+ type: "WORK_ITEM_CREATED",
212
+ actor: "system",
213
+ });
214
+ });
215
+ return workItem;
216
+ }
217
+ getWorkItem(workItemId) {
218
+ const row = this.database
219
+ .prepare("SELECT * FROM work_items WHERE id = ?")
220
+ .get(workItemId);
221
+ return row ? toWorkItem(row) : undefined;
222
+ }
223
+ getWorkItemBySessionId(sessionId) {
224
+ const row = this.database
225
+ .prepare("SELECT * FROM work_items WHERE session_id = ?")
226
+ .get(sessionId);
227
+ return row ? toWorkItem(row) : undefined;
228
+ }
229
+ getSessionRuntime(sessionId) {
230
+ const row = this.database
231
+ .prepare("SELECT * FROM session_runtime WHERE session_id = ?")
232
+ .get(sessionId);
233
+ return row ? toSessionRuntime(row) : undefined;
234
+ }
235
+ /**
236
+ * First and latest ACP usage_update persisted for a session (context tokens in use / model window).
237
+ * INDEXED BY: without ANALYZE stats SQLite picks the (target, sequence) index and scans every
238
+ * session's usage rows; this keeps the lookup inside one work item.
239
+ */
240
+ getContextUsage(sessionId) {
241
+ const workItemId = this.getWorkItemBySessionId(sessionId)?.id;
242
+ if (!workItemId)
243
+ return undefined;
244
+ const read = (order) => {
245
+ const row = this.database
246
+ .prepare(`SELECT payload FROM domain_events INDEXED BY domain_events_work_item_sequence
247
+ WHERE work_item_id = ? AND target = 'usage_update'
248
+ ORDER BY sequence ${order} LIMIT 1`)
249
+ .get(workItemId);
250
+ const event = row?.payload
251
+ ? JSON.parse(row.payload).event
252
+ : undefined;
253
+ return typeof event?.used === "number" && typeof event.size === "number"
254
+ ? { used: event.used, size: event.size }
255
+ : undefined;
256
+ };
257
+ const latest = read("DESC");
258
+ const first = latest && read("ASC");
259
+ return latest && first ? { first, latest } : undefined;
260
+ }
261
+ getTurn(turnId) {
262
+ const row = this.database
263
+ .prepare("SELECT * FROM session_turns WHERE turn_id = ?")
264
+ .get(turnId);
265
+ return row ? toSessionTurn(row) : undefined;
266
+ }
267
+ listQueuedTurns(sessionId, options) {
268
+ const afterPosition = Math.max(0, Math.floor(options.afterPosition ?? 0));
269
+ const limit = Math.max(1, Math.min(100, Math.floor(options.limit)));
270
+ const rows = this.database
271
+ .prepare(`SELECT * FROM session_turns
272
+ WHERE session_id = ? AND status = 'queued' AND queue_position > ?
273
+ ORDER BY queue_position ASC
274
+ LIMIT ?`)
275
+ .all(sessionId, afterPosition, limit + 1);
276
+ const totalRow = this.database
277
+ .prepare(`SELECT COUNT(*) AS total FROM session_turns
278
+ WHERE session_id = ? AND status = 'queued'`)
279
+ .get(sessionId);
280
+ const hasMore = rows.length > limit;
281
+ const turns = rows.slice(0, limit).map(toSessionTurn);
282
+ return {
283
+ turns,
284
+ total: Number(totalRow?.total ?? 0),
285
+ nextCursor: hasMore
286
+ ? turns.at(-1)?.queuePosition ?? null
287
+ : null,
288
+ };
289
+ }
290
+ listTimelineTurns(sessionId, options) {
291
+ const limit = Math.max(1, Math.min(50, Math.floor(options.limit)));
292
+ const before = Number.isFinite(options.before)
293
+ ? Math.max(1, Math.floor(options.before))
294
+ : Number.MAX_SAFE_INTEGER;
295
+ const contentBudget = Math.max(1, Math.min(1_048_576, Math.floor(options.contentBudgetBytes ?? 1_048_576)));
296
+ const rows = this.database
297
+ .prepare(`SELECT * FROM session_timeline_turns
298
+ WHERE session_id = ? AND timeline_index < ?
299
+ ORDER BY timeline_index DESC
300
+ LIMIT ?`)
301
+ .all(sessionId, before, limit + 1);
302
+ const hasEarlier = rows.length > limit;
303
+ const selectedRows = rows.slice(0, limit).reverse();
304
+ const truncatedBlockIds = [];
305
+ let usedBytes = 0;
306
+ const turns = selectedRows.map((turnRow) => {
307
+ const blockRows = this.database
308
+ .prepare(`SELECT * FROM session_timeline_blocks
309
+ WHERE turn_id = ?
310
+ ORDER BY block_index ASC`)
311
+ .all(String(turnRow.turn_id));
312
+ const blocks = blockRows.map((blockRow) => {
313
+ const segmentRows = this.database
314
+ .prepare(`SELECT * FROM session_output_segments
315
+ WHERE block_id = ?
316
+ ORDER BY segment_index ASC
317
+ LIMIT 101`)
318
+ .all(String(blockRow.block_id));
319
+ const segments = [];
320
+ for (const segmentRow of segmentRows.slice(0, 100)) {
321
+ const byteLength = Number(segmentRow.byte_length);
322
+ if (usedBytes + byteLength > contentBudget)
323
+ break;
324
+ segments.push(toTimelineSegment(segmentRow));
325
+ usedBytes += byteLength;
326
+ }
327
+ const hasMore = segments.length < segmentRows.length;
328
+ if (hasMore)
329
+ truncatedBlockIds.push(String(blockRow.block_id));
330
+ return {
331
+ ...toTimelineBlock(blockRow),
332
+ segments,
333
+ nextSegmentCursor: hasMore
334
+ ? segments.at(-1)?.segmentIndex ?? -1
335
+ : null,
336
+ };
337
+ });
338
+ return {
339
+ ...toTimelineTurn(turnRow),
340
+ blocks,
341
+ };
342
+ });
343
+ return {
344
+ turns,
345
+ previousCursor: hasEarlier
346
+ ? turns[0]?.timelineIndex ?? null
347
+ : null,
348
+ truncatedBlockIds,
349
+ };
350
+ }
351
+ listTimelineSegments(blockId, options) {
352
+ const after = Number.isFinite(options.after)
353
+ ? Math.floor(options.after)
354
+ : -1;
355
+ const limit = Math.max(1, Math.min(100, Math.floor(options.limit)));
356
+ const rows = this.database
357
+ .prepare(`SELECT * FROM session_output_segments
358
+ WHERE block_id = ? AND segment_index > ?
359
+ ORDER BY segment_index ASC
360
+ LIMIT ?`)
361
+ .all(blockId, after, limit + 1);
362
+ const hasMore = rows.length > limit;
363
+ const segments = rows.slice(0, limit).map(toTimelineSegment);
364
+ return {
365
+ segments,
366
+ nextCursor: hasMore
367
+ ? segments.at(-1)?.segmentIndex ?? null
368
+ : null,
369
+ };
370
+ }
371
+ listSessionCommands(sessionId) {
372
+ const rows = this.database
373
+ .prepare(`SELECT name, description, input_json
374
+ FROM session_commands
375
+ WHERE session_id = ?
376
+ ORDER BY name ASC`)
377
+ .all(sessionId);
378
+ return rows.map((row) => {
379
+ const input = row.input_json === null || row.input_json === undefined
380
+ ? undefined
381
+ : JSON.parse(String(row.input_json));
382
+ return {
383
+ name: String(row.name),
384
+ description: String(row.description),
385
+ ...(input ? { input } : {}),
386
+ };
387
+ });
388
+ }
389
+ countAllChanges() {
390
+ const row = this.database
391
+ .prepare("SELECT total_changes() AS value")
392
+ .get();
393
+ return Number(row?.value ?? 0);
394
+ }
395
+ getProviderHistoryImport(sessionId, providerSessionId) {
396
+ const row = this.database
397
+ .prepare(`SELECT provider_digest, imported_position, imported_at
398
+ FROM provider_history_imports
399
+ WHERE session_id = ? AND provider_session_id = ?`)
400
+ .get(sessionId, providerSessionId);
401
+ return row
402
+ ? {
403
+ providerDigest: String(row.provider_digest),
404
+ importedPosition: Number(row.imported_position),
405
+ importedAt: String(row.imported_at),
406
+ }
407
+ : undefined;
408
+ }
409
+ importProviderHistory(input) {
410
+ return this.withSessionTransaction((tx) => importProviderHistory(tx, input));
411
+ }
412
+ withSessionTransaction(operation) {
413
+ return this.withTransaction(() => {
414
+ const { transaction, deactivate } = createSqliteSessionRuntimeTransaction(this.database);
415
+ try {
416
+ return operation(transaction);
417
+ }
418
+ finally {
419
+ deactivate();
420
+ }
421
+ });
422
+ }
423
+ withTransaction(operation) {
424
+ if (this.transactionDepth > 0) {
425
+ throw new Error("nested transaction is not supported");
426
+ }
427
+ this.database.exec("BEGIN IMMEDIATE;");
428
+ this.transactionDepth = 1;
429
+ try {
430
+ const result = operation();
431
+ this.database.exec("COMMIT;");
432
+ return result;
433
+ }
434
+ catch (error) {
435
+ this.database.exec("ROLLBACK;");
436
+ throw error;
437
+ }
438
+ finally {
439
+ this.transactionDepth = 0;
440
+ }
441
+ }
442
+ previewSessionRuntimeMigration(bindings) {
443
+ const conflicts = [];
444
+ for (const binding of bindings) {
445
+ const activeRuns = this.database
446
+ .prepare(`SELECT id
447
+ FROM runs
448
+ WHERE work_item_id = ?
449
+ AND status IN ('queued', 'running', 'waiting')
450
+ ORDER BY created_at ASC, id ASC`)
451
+ .all(binding.workItemId);
452
+ const activeRunIds = activeRuns.map((row) => String(row.id));
453
+ if (activeRunIds.length > 1) {
454
+ conflicts.push({
455
+ sessionId: binding.sessionId,
456
+ activeRunIds,
457
+ });
458
+ }
459
+ }
460
+ return { conflicts };
461
+ }
462
+ bindWorkItemToSession(sessionId, workItemId) {
463
+ this.withTransaction(() => {
464
+ const workItem = this.database
465
+ .prepare("SELECT session_id FROM work_items WHERE id = ?")
466
+ .get(workItemId);
467
+ if (!workItem) {
468
+ throw new Error(`WorkItem not found: ${workItemId}`);
469
+ }
470
+ const existingBinding = this.database
471
+ .prepare("SELECT id FROM work_items WHERE session_id = ? AND id != ? LIMIT 1")
472
+ .get(sessionId, workItemId);
473
+ if (existingBinding) {
474
+ throw new Error(`Session already bound to another WorkItem: ${sessionId}`);
475
+ }
476
+ if (workItem.session_id !== null
477
+ && workItem.session_id !== undefined
478
+ && String(workItem.session_id) !== sessionId) {
479
+ throw new Error(`WorkItem already bound to another Session: ${workItemId}`);
480
+ }
481
+ const now = new Date().toISOString();
482
+ this.database
483
+ .prepare("UPDATE work_items SET session_id = ?, updated_at = ? WHERE id = ?")
484
+ .run(sessionId, now, workItemId);
485
+ this.database
486
+ .prepare(`INSERT INTO session_runtime (
487
+ session_id, active_run_id, queue_state, queue_pause_reason,
488
+ last_event_sequence, version, updated_at
489
+ ) VALUES (?, NULL, 'ready', NULL, 0, 1, ?)
490
+ ON CONFLICT(session_id) DO NOTHING`)
491
+ .run(sessionId, now);
492
+ });
493
+ }
494
+ backfillRunTurns(sessionId, workItemId) {
495
+ return this.withTransaction(() => {
496
+ const runs = this.database
497
+ .prepare(`SELECT *
498
+ FROM runs
499
+ WHERE work_item_id = ?
500
+ ORDER BY created_at ASC, id ASC`)
501
+ .all(workItemId);
502
+ if (runs.length === 0) {
503
+ const events = this.database
504
+ .prepare(`SELECT *
505
+ FROM domain_events
506
+ WHERE work_item_id = ?
507
+ AND type IN ('MESSAGE_RECEIVED', 'AGENT_EVENT')
508
+ ORDER BY sequence ASC`)
509
+ .all(workItemId);
510
+ let activeGroup = false;
511
+ let syntheticCount = 0;
512
+ for (const row of events) {
513
+ const event = toDomainEvent(row);
514
+ if (event.type !== "MESSAGE_RECEIVED" && activeGroup)
515
+ continue;
516
+ const seed = event.type === "MESSAGE_RECEIVED"
517
+ ? `message:${event.sequence}`
518
+ : `agent:${event.sequence}`;
519
+ const turnId = createMigrationId("turn", sessionId, seed);
520
+ const runId = createMigrationId("run", sessionId, seed);
521
+ const message = event.type === "MESSAGE_RECEIVED"
522
+ ? legacyTurnMessageFromEvent(event)
523
+ : emptyLegacyTurnMessage();
524
+ const run = createLegacySyntheticRun({
525
+ runId,
526
+ turnId,
527
+ workItemId,
528
+ sessionId,
529
+ occurredAt: event.occurredAt,
530
+ });
531
+ upsertLegacyRunTurn(this.database, {
532
+ sessionId,
533
+ workItemId,
534
+ runId,
535
+ turnId,
536
+ queuePosition: syntheticCount + 1,
537
+ message,
538
+ createdAt: event.occurredAt,
539
+ }, run, event.occurredAt);
540
+ syntheticCount += 1;
541
+ activeGroup = true;
542
+ }
543
+ return syntheticCount;
544
+ }
545
+ const messageRows = this.database
546
+ .prepare(`SELECT *
547
+ FROM domain_events
548
+ WHERE work_item_id = ? AND type = 'MESSAGE_RECEIVED'
549
+ ORDER BY sequence ASC`)
550
+ .all(workItemId);
551
+ const explicitMessagesByRunId = new Map();
552
+ const unscopedMessages = [];
553
+ for (const row of messageRows) {
554
+ const message = toDomainEvent(row);
555
+ if (message.runId) {
556
+ explicitMessagesByRunId.set(message.runId, message);
557
+ }
558
+ else {
559
+ unscopedMessages.push(message);
560
+ }
561
+ }
562
+ let unscopedIndex = 0;
563
+ let boundCount = 0;
564
+ for (const [index, row] of runs.entries()) {
565
+ const run = toRun(row);
566
+ const turnEvent = this.database
567
+ .prepare(`SELECT *
568
+ FROM domain_events
569
+ WHERE work_item_id = ? AND run_id = ? AND type = 'TURN_DISPATCHED'
570
+ ORDER BY sequence ASC
571
+ LIMIT 1`)
572
+ .get(workItemId, run.id);
573
+ const messageEvent = explicitMessagesByRunId.get(run.id)
574
+ ?? unscopedMessages.at(unscopedIndex++)
575
+ ?? undefined;
576
+ const turnId = turnEvent
577
+ ? legacyTurnIdFromEvent(sessionId, turnEvent, run.id)
578
+ : run.turnId
579
+ ?? (messageEvent
580
+ ? createMigrationId("turn", sessionId, `message:${messageEvent.sequence}`)
581
+ : createMigrationId("turn", sessionId, `run:${run.id}`));
582
+ const queuePosition = index + 1;
583
+ const message = messageEvent
584
+ ? legacyTurnMessageFromEvent(messageEvent)
585
+ : emptyLegacyTurnMessage();
586
+ upsertLegacyRunTurn(this.database, {
587
+ sessionId,
588
+ workItemId,
589
+ runId: run.id,
590
+ turnId,
591
+ queuePosition,
592
+ message,
593
+ createdAt: messageEvent?.occurredAt === undefined
594
+ ? run.createdAt
595
+ : String(messageEvent.occurredAt),
596
+ }, run, turnEvent ? String(turnEvent.occurred_at) : undefined);
597
+ boundCount += 1;
598
+ }
599
+ return boundCount;
600
+ });
601
+ }
602
+ ensureRuntimeFromRuns(sessionId) {
603
+ return this.withTransaction(() => {
604
+ const current = this.getSessionRuntime(sessionId);
605
+ const runs = this.database
606
+ .prepare(`SELECT *
607
+ FROM runs
608
+ WHERE session_id = ? OR work_item_id IN (
609
+ SELECT id FROM work_items WHERE session_id = ?
610
+ )
611
+ ORDER BY created_at ASC, id ASC`)
612
+ .all(sessionId, sessionId);
613
+ const activeRuns = runs
614
+ .map(toRun)
615
+ .filter((run) => isActiveRunStatus(run.status));
616
+ if (activeRuns.length > 1) {
617
+ const error = new Error("session_runtime_migration_conflict");
618
+ error.conflicts = [{
619
+ sessionId,
620
+ activeRunIds: activeRuns.map((run) => run.id),
621
+ }];
622
+ throw error;
623
+ }
624
+ const latestRun = runs.length > 0
625
+ ? toRun(runs.at(-1))
626
+ : undefined;
627
+ const next = activeRuns[0]
628
+ ? {
629
+ activeRunId: activeRuns[0].id,
630
+ queueState: "ready",
631
+ queuePauseReason: null,
632
+ }
633
+ : latestRun && (latestRun.status === "failed"
634
+ || latestRun.status === "cancelled"
635
+ || latestRun.status === "interrupted")
636
+ ? {
637
+ activeRunId: null,
638
+ queueState: "paused",
639
+ queuePauseReason: latestRun.status,
640
+ }
641
+ : {
642
+ activeRunId: current?.activeRunId ?? null,
643
+ queueState: current?.queueState ?? "ready",
644
+ queuePauseReason: current?.queuePauseReason ?? null,
645
+ };
646
+ const now = new Date().toISOString();
647
+ if (current) {
648
+ this.database
649
+ .prepare(`UPDATE session_runtime
650
+ SET active_run_id = ?, queue_state = ?, queue_pause_reason = ?,
651
+ updated_at = ?
652
+ WHERE session_id = ?`)
653
+ .run(next.activeRunId, next.queueState, next.queuePauseReason, now, sessionId);
654
+ }
655
+ else {
656
+ this.database
657
+ .prepare(`INSERT INTO session_runtime (
658
+ session_id, active_run_id, queue_state, queue_pause_reason,
659
+ last_event_sequence, version, updated_at
660
+ ) VALUES (?, ?, ?, ?, 0, 1, ?)`)
661
+ .run(sessionId, next.activeRunId, next.queueState, next.queuePauseReason, now);
662
+ }
663
+ return this.getSessionRuntime(sessionId);
664
+ });
665
+ }
666
+ getProjectionCursor(sessionId) {
667
+ const row = this.database
668
+ .prepare("SELECT last_projected_sequence FROM session_projection_cursors WHERE session_id = ?")
669
+ .get(sessionId);
670
+ return row ? Number(row.last_projected_sequence) : 0;
671
+ }
672
+ backfillSessionProjection(sessionId, workItemId, batchSize) {
673
+ return this.withTransaction(() => {
674
+ const cursor = this.getProjectionCursor(sessionId);
675
+ const boundedBatchSize = Math.max(1, Math.min(1_000, Math.floor(batchSize)));
676
+ const projectionBindings = this.database
677
+ .prepare(`SELECT st.turn_id, st.dispatched_run_id
678
+ FROM session_turns st
679
+ WHERE st.session_id = ?
680
+ AND NOT EXISTS (
681
+ SELECT 1
682
+ FROM domain_events de
683
+ WHERE de.run_id = st.dispatched_run_id
684
+ AND de.type = 'MESSAGE_RECEIVED'
685
+ )
686
+ ORDER BY queue_position ASC, turn_id ASC`)
687
+ .all(sessionId);
688
+ const priorUnscopedMessages = this.database
689
+ .prepare(`SELECT COUNT(*) AS count
690
+ FROM domain_events
691
+ WHERE work_item_id = ? AND type = 'MESSAGE_RECEIVED'
692
+ AND run_id IS NULL AND sequence <= ?`)
693
+ .get(workItemId, cursor);
694
+ const bindings = projectionBindings.map((row) => ({
695
+ turnId: String(row.turn_id),
696
+ runId: String(row.dispatched_run_id),
697
+ }));
698
+ const bindingIndex = Number(priorUnscopedMessages?.count ?? 0);
699
+ const bindingState = {
700
+ index: bindingIndex,
701
+ bindings,
702
+ };
703
+ const priorUnscopedMessageRow = bindingIndex > 0
704
+ ? this.database
705
+ .prepare(`SELECT *
706
+ FROM domain_events
707
+ WHERE work_item_id = ? AND type = 'MESSAGE_RECEIVED'
708
+ AND run_id IS NULL AND sequence <= ?
709
+ ORDER BY sequence DESC
710
+ LIMIT 1`)
711
+ .get(workItemId, cursor)
712
+ : undefined;
713
+ const rows = this.database
714
+ .prepare(`SELECT *
715
+ FROM domain_events
716
+ WHERE work_item_id = ? AND sequence > ?
717
+ ORDER BY sequence ASC
718
+ LIMIT ?`)
719
+ .all(workItemId, cursor, boundedBatchSize);
720
+ if (!rows.length) {
721
+ return 0;
722
+ }
723
+ const priorBinding = bindingIndex > 0
724
+ ? bindings.at(bindingIndex - 1)
725
+ : undefined;
726
+ const priorMessage = priorUnscopedMessageRow
727
+ ? toDomainEvent(priorUnscopedMessageRow)
728
+ : undefined;
729
+ let currentSynthetic = priorBinding
730
+ ? {
731
+ ...priorBinding,
732
+ queuePosition: bindingIndex,
733
+ }
734
+ : priorMessage
735
+ ? {
736
+ runId: createMigrationId("run", sessionId, `message:${priorMessage.sequence}`),
737
+ turnId: createMigrationId("turn", sessionId, `message:${priorMessage.sequence}`),
738
+ queuePosition: bindingIndex,
739
+ }
740
+ : null;
741
+ let projected = 0;
742
+ for (const row of rows) {
743
+ const event = toDomainEvent(row);
744
+ const projectedEvent = normalizeLegacyProjectionEvent(this.database, sessionId, event, currentSynthetic, bindingState);
745
+ currentSynthetic = projectedEvent.syntheticGroup ?? currentSynthetic;
746
+ projectSessionEvent(this.database, sessionId, projectedEvent.event);
747
+ projected += 1;
748
+ }
749
+ return projected;
750
+ });
751
+ }
752
+ listWorkItems() {
753
+ const rows = this.database
754
+ .prepare("SELECT * FROM work_items ORDER BY updated_at DESC, rowid ASC")
755
+ .all();
756
+ return rows.map(toWorkItem);
757
+ }
758
+ appendEvent(input) {
759
+ if (!this.getWorkItem(input.workItemId)) {
760
+ throw new Error(`WorkItem not found: ${input.workItemId}`);
761
+ }
762
+ return this.withTransaction(() => {
763
+ const event = this.appendEventInTransaction(input);
764
+ return event;
765
+ });
766
+ }
767
+ appendLeasedRunEvent(owner, input) {
768
+ return this.withTransaction(() => {
769
+ const lease = this.database
770
+ .prepare(`SELECT 1 FROM runs
771
+ WHERE id = ? AND session_id = ? AND status = 'running'
772
+ AND lease_owner = ? AND lease_expires_at >= ?`)
773
+ .get(input.runId, input.sessionId, owner, new Date().toISOString());
774
+ if (!lease)
775
+ throw new Error("run_lease_lost");
776
+ const event = appendSessionEventInTransaction(this.database, input);
777
+ return event;
778
+ });
779
+ }
780
+ appendEventOnce(input) {
781
+ if (!this.getWorkItem(input.workItemId)) {
782
+ throw new Error(`WorkItem not found: ${input.workItemId}`);
783
+ }
784
+ return this.withTransaction(() => {
785
+ const existing = this.database
786
+ .prepare("SELECT * FROM domain_events WHERE work_item_id = ? AND input_hash = ? LIMIT 1")
787
+ .get(input.workItemId, input.inputHash);
788
+ const event = existing ? toDomainEvent(existing) : this.appendEventInTransaction(input);
789
+ return event;
790
+ });
791
+ }
792
+ listEvents(workItemId, afterSequence = 0) {
793
+ const rows = this.database
794
+ .prepare(`SELECT * FROM domain_events
795
+ WHERE work_item_id = ? AND sequence > ?
796
+ ORDER BY sequence ASC`)
797
+ .all(workItemId, afterSequence);
798
+ return rows.map(toDomainEvent);
799
+ }
800
+ listEventsByTarget(target) {
801
+ const rows = this.database
802
+ .prepare(`SELECT * FROM domain_events
803
+ WHERE target = ?
804
+ ORDER BY sequence ASC`)
805
+ .all(target);
806
+ return rows.map(toDomainEvent);
807
+ }
808
+ listEventsPage(workItemId, afterSequence, limit) {
809
+ const boundedLimit = Math.max(1, Math.min(501, Math.floor(limit)));
810
+ const rows = this.database
811
+ .prepare(`SELECT * FROM domain_events
812
+ WHERE work_item_id = ? AND sequence > ?
813
+ ORDER BY sequence ASC
814
+ LIMIT ?`)
815
+ .all(workItemId, afterSequence, boundedLimit);
816
+ return rows.map(toDomainEvent);
817
+ }
818
+ listRecentEvents(workItemId, limit) {
819
+ const boundedLimit = Math.max(1, Math.min(10_000, Math.floor(limit)));
820
+ const rows = this.database
821
+ .prepare(`SELECT * FROM domain_events
822
+ WHERE work_item_id = ?
823
+ ORDER BY sequence DESC
824
+ LIMIT ?`)
825
+ .all(workItemId, boundedLimit);
826
+ return rows.reverse().map(toDomainEvent);
827
+ }
828
+ listEventInputHashes(workItemId) {
829
+ const rows = this.database
830
+ .prepare(`SELECT input_hash FROM domain_events
831
+ WHERE work_item_id = ? AND input_hash IS NOT NULL`)
832
+ .all(workItemId);
833
+ return new Set(rows.map((row) => String(row.input_hash)));
834
+ }
835
+ sequenceForEventId(workItemId, eventId) {
836
+ const row = this.database
837
+ .prepare("SELECT sequence FROM domain_events WHERE work_item_id = ? AND event_id = ?")
838
+ .get(workItemId, eventId);
839
+ return row?.sequence ? Number(row.sequence) : 0;
840
+ }
841
+ savePlan(input) {
842
+ const plan = {
843
+ schemaVersion: 1,
844
+ planId: input.planId,
845
+ source: input.source,
846
+ workflowId: input.workflowId,
847
+ definitionRevision: input.definitionRevision,
848
+ planIrHash: input.planIrHash ?? null,
849
+ sessionId: input.sessionId ?? null,
850
+ runId: input.runId ?? null,
851
+ steps: input.steps.map(clonePlanStep),
852
+ createdAt: new Date().toISOString(),
853
+ };
854
+ this.database
855
+ .prepare(`INSERT INTO plans (
856
+ plan_id, schema_version, source, workflow_id, definition_revision,
857
+ plan_ir_hash, session_id, run_id, steps, created_at
858
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
859
+ ON CONFLICT(plan_id) DO UPDATE SET
860
+ source = excluded.source,
861
+ workflow_id = excluded.workflow_id,
862
+ definition_revision = excluded.definition_revision,
863
+ plan_ir_hash = excluded.plan_ir_hash,
864
+ session_id = excluded.session_id,
865
+ run_id = excluded.run_id,
866
+ steps = excluded.steps`)
867
+ .run(plan.planId, plan.schemaVersion, plan.source, plan.workflowId, plan.definitionRevision, plan.planIrHash, plan.sessionId, plan.runId, JSON.stringify(plan.steps), plan.createdAt);
868
+ return this.getPlan(plan.planId);
869
+ }
870
+ getPlan(planId) {
871
+ const row = this.database.prepare("SELECT * FROM plans WHERE plan_id = ?").get(planId);
872
+ return row ? toPlan(row) : undefined;
873
+ }
874
+ getPlanForRun(runId) {
875
+ const row = this.database.prepare("SELECT * FROM plans WHERE run_id = ?").get(runId);
876
+ return row ? toPlan(row) : undefined;
877
+ }
878
+ createRun(input) {
879
+ const workItem = this.getWorkItem(input.workItemId);
880
+ if (!workItem) {
881
+ throw new Error(`WorkItem not found: ${input.workItemId}`);
882
+ }
883
+ const plan = input.planId ? this.getPlan(input.planId) : undefined;
884
+ if (input.planId && !plan) {
885
+ throw new Error(`Plan not found: ${input.planId}`);
886
+ }
887
+ if (plan?.runId && input.id && plan.runId !== input.id) {
888
+ throw new Error(`Plan ${plan.planId} is bound to another Run`);
889
+ }
890
+ const now = new Date().toISOString();
891
+ const run = {
892
+ schemaVersion: 1,
893
+ id: input.id ?? createId("run"),
894
+ workItemId: input.workItemId,
895
+ sessionId: input.sessionId ?? workItem.sessionId,
896
+ turnId: input.turnId ?? null,
897
+ mode: input.mode,
898
+ status: "queued",
899
+ executionKind: input.executionKind,
900
+ agentId: input.agentId ?? workItem.agentId,
901
+ planId: input.planId ?? null,
902
+ planIrHash: input.planIrHash ?? plan?.planIrHash ?? null,
903
+ workflowRevision: input.workflowRevision ?? plan?.definitionRevision ?? workItem.workflowRevision,
904
+ terminalReason: null,
905
+ replaySafety: "safe",
906
+ leaseOwner: null,
907
+ leaseExpiresAt: null,
908
+ cancelRequestedAt: null,
909
+ cancelDeadlineAt: null,
910
+ providerSessionId: input.providerSessionId ?? null,
911
+ createdAt: now,
912
+ updatedAt: now,
913
+ };
914
+ this.withTransaction(() => {
915
+ this.database
916
+ .prepare(`INSERT INTO runs (
917
+ id, schema_version, work_item_id, session_id, turn_id, mode, status,
918
+ execution_kind, agent_id, plan_id, plan_ir_hash, workflow_revision, terminal_reason,
919
+ replay_safety, lease_owner, lease_expires_at, cancel_requested_at,
920
+ cancel_deadline_at, provider_session_id, created_at, updated_at
921
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
922
+ .run(run.id, run.schemaVersion, run.workItemId, run.sessionId, run.turnId, run.mode, run.status, run.executionKind, run.agentId, run.planId, run.planIrHash, run.workflowRevision, run.terminalReason, run.replaySafety, run.leaseOwner, run.leaseExpiresAt, run.cancelRequestedAt, run.cancelDeadlineAt, run.providerSessionId ?? null, run.createdAt, run.updatedAt);
923
+ this.appendEventInTransaction({
924
+ workItemId: run.workItemId,
925
+ runId: run.id,
926
+ type: "RUN_CREATED",
927
+ actor: "system",
928
+ target: run.id,
929
+ payload: {
930
+ mode: run.mode,
931
+ agent_id: run.agentId,
932
+ plan_id: run.planId,
933
+ workflow_revision: run.workflowRevision,
934
+ execution_kind: run.executionKind,
935
+ },
936
+ });
937
+ if (plan) {
938
+ this.appendEventInTransaction({
939
+ workItemId: run.workItemId,
940
+ runId: run.id,
941
+ type: "PLAN_VALIDATED",
942
+ actor: "system",
943
+ target: plan.planId,
944
+ payload: {
945
+ workflow_id: plan.workflowId,
946
+ definition_revision: plan.definitionRevision,
947
+ source: plan.source,
948
+ step_count: plan.steps.length,
949
+ },
950
+ });
951
+ }
952
+ });
953
+ return run;
954
+ }
955
+ getRun(runId) {
956
+ const row = this.database.prepare("SELECT * FROM runs WHERE id = ?").get(runId);
957
+ return row ? toRun(row) : undefined;
958
+ }
959
+ listRuns(workItemId) {
960
+ const rows = this.database
961
+ .prepare("SELECT * FROM runs WHERE work_item_id = ? ORDER BY created_at ASC")
962
+ .all(workItemId);
963
+ return rows.map(toRun);
964
+ }
965
+ listRunsByStatus(statuses) {
966
+ if (!statuses.length)
967
+ return [];
968
+ const placeholders = statuses.map(() => "?").join(", ");
969
+ const rows = this.database
970
+ .prepare(`SELECT * FROM runs WHERE status IN (${placeholders}) ORDER BY created_at ASC`)
971
+ .all(...statuses);
972
+ return rows.map(toRun);
973
+ }
974
+ updateRunStatus(runId, status) {
975
+ const now = new Date().toISOString();
976
+ const result = this.database
977
+ .prepare("UPDATE runs SET status = ?, updated_at = ? WHERE id = ?")
978
+ .run(status, now, runId);
979
+ if (Number(result.changes) !== 1)
980
+ throw new Error(`Run not found: ${runId}`);
981
+ return this.getRun(runId);
982
+ }
983
+ updateRunControl(runId, patch) {
984
+ const current = this.getRun(runId);
985
+ if (!current)
986
+ throw new Error(`Run not found: ${runId}`);
987
+ const next = {
988
+ ...current,
989
+ ...patch,
990
+ updatedAt: new Date().toISOString(),
991
+ };
992
+ this.database
993
+ .prepare(`UPDATE runs
994
+ SET status = ?, terminal_reason = ?, replay_safety = ?,
995
+ lease_owner = ?, lease_expires_at = ?, cancel_requested_at = ?,
996
+ cancel_deadline_at = ?, updated_at = ?
997
+ WHERE id = ?`)
998
+ .run(next.status, next.terminalReason, next.replaySafety, next.leaseOwner, next.leaseExpiresAt, next.cancelRequestedAt, next.cancelDeadlineAt, next.updatedAt, runId);
999
+ return this.getRun(runId);
1000
+ }
1001
+ claimRun(runId, owner, now, expiresAt) {
1002
+ return this.withSessionTransaction((tx) => tx.claimRun(runId, owner, now, expiresAt));
1003
+ }
1004
+ renewRunLease(runId, owner, now, expiresAt) {
1005
+ return this.withSessionTransaction((tx) => tx.renewRunLease(runId, owner, now, expiresAt));
1006
+ }
1007
+ reclaimRunLease(runId, owner, expiresAt) {
1008
+ return this.withSessionTransaction((tx) => tx.reclaimRunLease(runId, owner, expiresAt));
1009
+ }
1010
+ updateLeasedRunReplaySafety(runId, owner, replaySafety) {
1011
+ const now = new Date().toISOString();
1012
+ const result = this.database
1013
+ .prepare(`UPDATE runs
1014
+ SET replay_safety = ?, updated_at = ?
1015
+ WHERE id = ? AND status = 'running' AND lease_owner = ?
1016
+ AND lease_expires_at >= ?`)
1017
+ .run(replaySafety, now, runId, owner, now);
1018
+ if (Number(result.changes) !== 1) {
1019
+ throw new Error("run_lease_lost");
1020
+ }
1021
+ return this.getRun(runId);
1022
+ }
1023
+ listExpiredRunningRuns(now, limit) {
1024
+ return createSqliteSessionRuntimeTransaction(this.database)
1025
+ .transaction.listExpiredRunningRuns(now, limit);
1026
+ }
1027
+ listCancellationDeadlineRuns(now, limit) {
1028
+ return createSqliteSessionRuntimeTransaction(this.database)
1029
+ .transaction.listCancellationDeadlineRuns(now, limit);
1030
+ }
1031
+ listDeliveries(channel, surfaceMessageId) {
1032
+ return createSqliteSessionRuntimeTransaction(this.database)
1033
+ .transaction.listDeliveries(channel, surfaceMessageId);
1034
+ }
1035
+ claimProviderSession(input) {
1036
+ return this.withSessionTransaction((tx) => tx.claimProviderSession(input));
1037
+ }
1038
+ renewProviderSession(input) {
1039
+ return this.withSessionTransaction((tx) => tx.renewProviderSession(input));
1040
+ }
1041
+ releaseProviderSession(input) {
1042
+ return this.withSessionTransaction((tx) => tx.releaseProviderSession(input));
1043
+ }
1044
+ findLiveProviderLease(agentId, providerSessionId, now) {
1045
+ return createSqliteSessionRuntimeTransaction(this.database)
1046
+ .transaction.findLiveProviderLease(agentId, providerSessionId, now);
1047
+ }
1048
+ setSessionProviderSessionId(sessionId, providerSessionId) {
1049
+ this.withSessionTransaction((tx) => tx.setSessionProviderSessionId(sessionId, providerSessionId));
1050
+ }
1051
+ startRunAttempt(runId) {
1052
+ if (!this.getRun(runId))
1053
+ throw new Error(`Run not found: ${runId}`);
1054
+ return this.withTransaction(() => {
1055
+ const row = this.database
1056
+ .prepare(`SELECT COALESCE(MAX(attempt_number), 0) + 1 AS next_attempt
1057
+ FROM run_attempts WHERE run_id = ?`)
1058
+ .get(runId);
1059
+ const attemptId = `attempt_${randomUUID().replaceAll("-", "")}`;
1060
+ this.database
1061
+ .prepare(`INSERT INTO run_attempts (
1062
+ attempt_id, run_id, attempt_number, started_at, ended_at,
1063
+ provider_error, side_effect_boundary
1064
+ ) VALUES (?, ?, ?, ?, NULL, NULL, 'safe')`)
1065
+ .run(attemptId, runId, Number(row?.next_attempt ?? 1), new Date().toISOString());
1066
+ const attempt = this.database
1067
+ .prepare("SELECT * FROM run_attempts WHERE attempt_id = ?")
1068
+ .get(attemptId);
1069
+ return toRunAttempt(attempt);
1070
+ });
1071
+ }
1072
+ finishRunAttempt(attemptId, input) {
1073
+ const result = this.database
1074
+ .prepare(`UPDATE run_attempts
1075
+ SET ended_at = ?, provider_error = ?,
1076
+ side_effect_boundary = ?
1077
+ WHERE attempt_id = ? AND ended_at IS NULL`)
1078
+ .run(new Date().toISOString(), input.providerError, input.sideEffectBoundary, attemptId);
1079
+ if (Number(result.changes) !== 1) {
1080
+ throw new Error(`Open Run attempt not found: ${attemptId}`);
1081
+ }
1082
+ const row = this.database
1083
+ .prepare("SELECT * FROM run_attempts WHERE attempt_id = ?")
1084
+ .get(attemptId);
1085
+ return toRunAttempt(row);
1086
+ }
1087
+ listRunAttempts(runId) {
1088
+ const rows = this.database
1089
+ .prepare(`SELECT * FROM run_attempts
1090
+ WHERE run_id = ? ORDER BY attempt_number ASC`)
1091
+ .all(runId);
1092
+ return rows.map(toRunAttempt);
1093
+ }
1094
+ findTerminalEventForRun(runId) {
1095
+ const row = this.database
1096
+ .prepare(`SELECT * FROM domain_events
1097
+ WHERE run_id = ?
1098
+ AND type IN (
1099
+ 'RUN_SUCCEEDED', 'RUN_FAILED',
1100
+ 'RUN_CANCELLED', 'RUN_INTERRUPTED'
1101
+ )
1102
+ ORDER BY sequence DESC
1103
+ LIMIT 1`)
1104
+ .get(runId);
1105
+ return row ? toDomainEvent(row) : undefined;
1106
+ }
1107
+ requeueRun(runId) {
1108
+ return this.updateRunStatus(runId, "queued");
1109
+ }
1110
+ putIdempotencyResponse(namespace, key, response, createdAt) {
1111
+ this.database
1112
+ .prepare(`INSERT OR IGNORE INTO idempotency_responses
1113
+ (namespace, idempotency_key, response, created_at) VALUES (?, ?, ?, ?)`)
1114
+ .run(namespace, key, JSON.stringify(response), createdAt ?? new Date().toISOString());
1115
+ }
1116
+ getIdempotencyRecord(namespace, key) {
1117
+ const row = this.database
1118
+ .prepare("SELECT response, created_at FROM idempotency_responses WHERE namespace = ? AND idempotency_key = ?")
1119
+ .get(namespace, key);
1120
+ if (!row?.response)
1121
+ return undefined;
1122
+ return { response: JSON.parse(row.response), createdAt: row.created_at ?? "" };
1123
+ }
1124
+ getIdempotencyResponse(namespace, key) {
1125
+ return this.getIdempotencyRecord(namespace, key)?.response;
1126
+ }
1127
+ deleteIdempotencyResponse(namespace, key) {
1128
+ this.database
1129
+ .prepare("DELETE FROM idempotency_responses WHERE namespace = ? AND idempotency_key = ?")
1130
+ .run(namespace, key);
1131
+ }
1132
+ createMessageAttachment(input) {
1133
+ if (!this.getWorkItem(input.workItemId))
1134
+ throw new Error(`WorkItem not found: ${input.workItemId}`);
1135
+ if (!/^[A-Za-z0-9+/]*={0,2}$/.test(input.dataBase64) || input.dataBase64.length % 4 === 1) {
1136
+ throw new Error("attachment data must be valid base64");
1137
+ }
1138
+ const bytes = Buffer.from(input.dataBase64, "base64");
1139
+ if (bytes.length === 0)
1140
+ throw new Error("attachment data cannot be empty");
1141
+ if (bytes.length > 10_000_000)
1142
+ throw new Error("attachment content exceeds 10 MB");
1143
+ const record = {
1144
+ schemaVersion: 1,
1145
+ id: input.id ?? createId("attachment"),
1146
+ workItemId: input.workItemId,
1147
+ name: path.basename(input.name || "attachment"),
1148
+ mimeType: input.mimeType || "application/octet-stream",
1149
+ dataBase64: input.dataBase64,
1150
+ byteSize: bytes.length,
1151
+ contentHash: `sha256:${createHash("sha256").update(bytes).digest("hex")}`,
1152
+ createdAt: new Date().toISOString(),
1153
+ };
1154
+ this.database
1155
+ .prepare(`INSERT INTO message_attachments (
1156
+ id, schema_version, work_item_id, name, mime_type, data_base64,
1157
+ byte_size, content_hash, created_at
1158
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1159
+ .run(record.id, record.schemaVersion, record.workItemId, record.name, record.mimeType, record.dataBase64, record.byteSize, record.contentHash, record.createdAt);
1160
+ return record;
1161
+ }
1162
+ getMessageAttachment(id) {
1163
+ const row = this.database.prepare("SELECT * FROM message_attachments WHERE id = ?").get(id);
1164
+ return row ? toMessageAttachment(row) : undefined;
1165
+ }
1166
+ listMessageAttachments(workItemId, ids) {
1167
+ const rows = this.database
1168
+ .prepare("SELECT * FROM message_attachments WHERE work_item_id = ? ORDER BY created_at ASC")
1169
+ .all(workItemId);
1170
+ const attachments = rows.map(toMessageAttachment);
1171
+ if (!ids)
1172
+ return attachments;
1173
+ const byId = new Map(attachments.map((attachment) => [attachment.id, attachment]));
1174
+ return ids.flatMap((id) => {
1175
+ const attachment = byId.get(id);
1176
+ return attachment ? [attachment] : [];
1177
+ });
1178
+ }
1179
+ createArtifact(input) {
1180
+ if (!this.getWorkItem(input.workItemId))
1181
+ throw new Error(`WorkItem not found: ${input.workItemId}`);
1182
+ if (!this.getRun(input.runId))
1183
+ throw new Error(`Run not found: ${input.runId}`);
1184
+ if (input.content.length > 10_000_000)
1185
+ throw new Error("artifact content exceeds 10 MB");
1186
+ const record = {
1187
+ id: input.id ?? createId("artifact"),
1188
+ workItemId: input.workItemId,
1189
+ runId: input.runId,
1190
+ stepId: input.stepId ?? null,
1191
+ kind: input.kind ?? "output",
1192
+ name: input.name,
1193
+ mimeType: input.mimeType ?? "text/plain",
1194
+ content: input.content,
1195
+ contentHash: `sha256:${createHash("sha256").update(input.content).digest("hex")}`,
1196
+ metadata: { ...(input.metadata ?? {}) },
1197
+ createdAt: new Date().toISOString(),
1198
+ };
1199
+ this.database
1200
+ .prepare(`INSERT INTO artifacts (
1201
+ id, work_item_id, run_id, step_id, kind, name, mime_type, content,
1202
+ content_hash, metadata, created_at
1203
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1204
+ .run(record.id, record.workItemId, record.runId, record.stepId, record.kind, record.name, record.mimeType, record.content, record.contentHash, JSON.stringify(record.metadata), record.createdAt);
1205
+ this.appendEvent({
1206
+ workItemId: record.workItemId,
1207
+ runId: record.runId,
1208
+ type: "ARTIFACT_CREATED",
1209
+ actor: input.actor ?? "adapter",
1210
+ target: record.id,
1211
+ resultRef: `artifact://${record.id}`,
1212
+ payload: {
1213
+ artifact_id: record.id,
1214
+ step_id: record.stepId,
1215
+ kind: record.kind,
1216
+ name: record.name,
1217
+ mime_type: record.mimeType,
1218
+ content_hash: record.contentHash,
1219
+ },
1220
+ });
1221
+ return record;
1222
+ }
1223
+ getArtifact(id) {
1224
+ const row = this.database.prepare("SELECT * FROM artifacts WHERE id = ?").get(id);
1225
+ return row ? toArtifact(row) : undefined;
1226
+ }
1227
+ listArtifacts(runId) {
1228
+ return this.database.prepare("SELECT * FROM artifacts WHERE run_id = ? ORDER BY created_at ASC").all(runId).map(toArtifact);
1229
+ }
1230
+ recordVerification(input) {
1231
+ if (!this.getWorkItem(input.workItemId))
1232
+ throw new Error(`WorkItem not found: ${input.workItemId}`);
1233
+ if (!this.getRun(input.runId))
1234
+ throw new Error(`Run not found: ${input.runId}`);
1235
+ const record = {
1236
+ id: input.id ?? createId("verification"),
1237
+ workItemId: input.workItemId,
1238
+ runId: input.runId,
1239
+ stepId: input.stepId ?? null,
1240
+ validator: input.validator,
1241
+ status: input.status,
1242
+ summary: input.summary,
1243
+ artifactIds: [...(input.artifactIds ?? [])],
1244
+ createdAt: new Date().toISOString(),
1245
+ };
1246
+ this.database
1247
+ .prepare(`INSERT INTO verifications (
1248
+ id, work_item_id, run_id, step_id, validator, status, summary,
1249
+ artifact_ids, created_at
1250
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1251
+ .run(record.id, record.workItemId, record.runId, record.stepId, record.validator, record.status, record.summary, JSON.stringify(record.artifactIds), record.createdAt);
1252
+ this.appendEvent({
1253
+ workItemId: record.workItemId,
1254
+ runId: record.runId,
1255
+ type: "VERIFICATION_COMPLETED",
1256
+ actor: "adapter",
1257
+ target: record.stepId ?? record.runId,
1258
+ resultRef: record.artifactIds[0] ? `artifact://${record.artifactIds[0]}` : null,
1259
+ payload: {
1260
+ verification_id: record.id,
1261
+ step_id: record.stepId,
1262
+ validator: record.validator,
1263
+ status: record.status,
1264
+ summary: record.summary,
1265
+ artifact_ids: record.artifactIds,
1266
+ },
1267
+ });
1268
+ return record;
1269
+ }
1270
+ listVerifications(runId) {
1271
+ return this.database.prepare("SELECT * FROM verifications WHERE run_id = ? ORDER BY created_at ASC").all(runId).map(toVerification);
1272
+ }
1273
+ close() {
1274
+ if (this.database.isOpen)
1275
+ this.database.close();
1276
+ }
1277
+ appendEventInTransaction(input) {
1278
+ const workItem = this.database
1279
+ .prepare("SELECT session_id FROM work_items WHERE id = ?")
1280
+ .get(input.workItemId);
1281
+ if (workItem?.session_id) {
1282
+ return appendSessionEventInTransaction(this.database, {
1283
+ ...input,
1284
+ sessionId: String(workItem.session_id),
1285
+ });
1286
+ }
1287
+ const sequenceRow = this.database
1288
+ .prepare("SELECT COALESCE(MAX(sequence), 0) + 1 AS next_sequence FROM domain_events WHERE work_item_id = ?")
1289
+ .get(input.workItemId);
1290
+ const sequence = Number(sequenceRow?.next_sequence ?? 1);
1291
+ const event = {
1292
+ schemaVersion: 1,
1293
+ eventId: createId("evt"),
1294
+ sequence,
1295
+ workItemId: input.workItemId,
1296
+ runId: input.runId ?? null,
1297
+ executionKind: resolveRunExecutionKind(this.database, input.runId ?? null),
1298
+ type: input.type,
1299
+ occurredAt: new Date().toISOString(),
1300
+ actor: input.actor,
1301
+ target: input.target ?? null,
1302
+ inputHash: input.inputHash ?? null,
1303
+ resultRef: input.resultRef ?? null,
1304
+ payload: { ...(input.payload ?? {}) },
1305
+ };
1306
+ this.database
1307
+ .prepare(`INSERT INTO domain_events (
1308
+ event_id, schema_version, sequence, work_item_id, run_id, execution_kind, type,
1309
+ occurred_at, actor, target, input_hash, result_ref, payload
1310
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1311
+ .run(event.eventId, event.schemaVersion, event.sequence, event.workItemId, event.runId, event.executionKind, event.type, event.occurredAt, event.actor, event.target, event.inputHash, event.resultRef, JSON.stringify(event.payload));
1312
+ this.database
1313
+ .prepare(`UPDATE session_runtime
1314
+ SET last_event_sequence = ?, updated_at = ?
1315
+ WHERE session_id = (
1316
+ SELECT session_id FROM work_items WHERE id = ?
1317
+ )`)
1318
+ .run(event.sequence, event.occurredAt, event.workItemId);
1319
+ const nextStatus = STATUS_BY_EVENT[event.type];
1320
+ if (nextStatus) {
1321
+ this.database
1322
+ .prepare("UPDATE work_items SET status = ?, updated_at = ? WHERE id = ?")
1323
+ .run(nextStatus, event.occurredAt, event.workItemId);
1324
+ }
1325
+ return event;
1326
+ }
1327
+ }
1328
+ function createId(prefix) {
1329
+ return `${prefix}_${randomUUID().replaceAll("-", "")}`;
1330
+ }
1331
+ function createMigrationId(prefix, sessionId, seed) {
1332
+ return `${prefix}_mig_${createHash("sha256")
1333
+ .update(`${sessionId}\0${seed}`)
1334
+ .digest("hex")
1335
+ .slice(0, 24)}`;
1336
+ }
1337
+ function createLegacySyntheticRun(input) {
1338
+ return {
1339
+ schemaVersion: 1,
1340
+ id: input.runId,
1341
+ workItemId: input.workItemId,
1342
+ sessionId: input.sessionId,
1343
+ turnId: input.turnId,
1344
+ mode: "auto",
1345
+ status: "succeeded",
1346
+ executionKind: "agent",
1347
+ agentId: null,
1348
+ planId: null,
1349
+ planIrHash: null,
1350
+ workflowRevision: null,
1351
+ terminalReason: "legacy_history_import",
1352
+ replaySafety: "safe",
1353
+ leaseOwner: null,
1354
+ leaseExpiresAt: null,
1355
+ cancelRequestedAt: null,
1356
+ cancelDeadlineAt: null,
1357
+ createdAt: input.occurredAt,
1358
+ updatedAt: input.occurredAt,
1359
+ };
1360
+ }
1361
+ function isActiveRunStatus(status) {
1362
+ return status === "queued" || status === "running" || status === "waiting";
1363
+ }
1364
+ function legacyTurnMessageFromEvent(event) {
1365
+ const payload = event.payload;
1366
+ return {
1367
+ text: typeof payload.message === "string" ? payload.message : "",
1368
+ attachmentIds: Array.isArray(payload.attachment_ids)
1369
+ ? payload.attachment_ids.map((value) => String(value))
1370
+ : [],
1371
+ executionKind: "agent",
1372
+ model: null,
1373
+ effort: null,
1374
+ permissionMode: null,
1375
+ plan: null,
1376
+ };
1377
+ }
1378
+ function emptyLegacyTurnMessage() {
1379
+ return {
1380
+ text: "",
1381
+ attachmentIds: [],
1382
+ executionKind: "agent",
1383
+ model: null,
1384
+ effort: null,
1385
+ permissionMode: null,
1386
+ plan: null,
1387
+ };
1388
+ }
1389
+ function legacyTurnIdFromEvent(sessionId, event, runId) {
1390
+ const target = event.target === null || event.target === undefined
1391
+ ? null
1392
+ : String(event.target);
1393
+ if (target)
1394
+ return target;
1395
+ return createMigrationId("turn", sessionId, `run:${runId}`);
1396
+ }
1397
+ function nextLegacyQueuePosition(database, sessionId) {
1398
+ const row = database
1399
+ .prepare(`SELECT COALESCE(MAX(queue_position), 0) + 1 AS next_position
1400
+ FROM session_turns
1401
+ WHERE session_id = ?`)
1402
+ .get(sessionId);
1403
+ return Number(row?.next_position ?? 1);
1404
+ }
1405
+ function ensureSyntheticTimelineTurn(database, sessionId, turnId, runId, startedSequence, occurredAt) {
1406
+ const existing = database
1407
+ .prepare(`SELECT 1 FROM session_timeline_turns
1408
+ WHERE turn_id = ? OR run_id = ?`)
1409
+ .get(turnId, runId);
1410
+ if (existing)
1411
+ return;
1412
+ const row = database
1413
+ .prepare(`SELECT COALESCE(MAX(timeline_index), 0) + 1 AS next_index
1414
+ FROM session_timeline_turns
1415
+ WHERE session_id = ?`)
1416
+ .get(sessionId);
1417
+ database
1418
+ .prepare(`INSERT INTO session_timeline_turns (
1419
+ session_id, timeline_index, turn_id, run_id, started_sequence,
1420
+ ended_sequence, status, updated_at
1421
+ ) VALUES (?, ?, ?, ?, ?, NULL, 'dispatched', ?)`)
1422
+ .run(sessionId, Number(row?.next_index ?? 1), turnId, runId, startedSequence, occurredAt);
1423
+ }
1424
+ function upsertLegacyRunTurn(database, input, run, dispatchOccurredAt) {
1425
+ database
1426
+ .prepare(`INSERT INTO runs (
1427
+ id, schema_version, work_item_id, session_id, turn_id, mode, status,
1428
+ execution_kind, agent_id, plan_id, plan_ir_hash, workflow_revision, terminal_reason,
1429
+ replay_safety, lease_owner, lease_expires_at, cancel_requested_at,
1430
+ cancel_deadline_at, created_at, updated_at
1431
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1432
+ ON CONFLICT(id) DO UPDATE SET
1433
+ work_item_id = excluded.work_item_id,
1434
+ session_id = excluded.session_id,
1435
+ turn_id = excluded.turn_id`)
1436
+ .run(input.runId, run.schemaVersion, input.workItemId, input.sessionId, input.turnId, run.mode, run.status, run.executionKind, run.agentId, run.planId, run.planIrHash, run.workflowRevision, run.terminalReason, run.replaySafety, run.leaseOwner, run.leaseExpiresAt, run.cancelRequestedAt, run.cancelDeadlineAt, run.createdAt, run.updatedAt);
1437
+ upsertSessionTurnBinding(database, {
1438
+ turnId: input.turnId,
1439
+ sessionId: input.sessionId,
1440
+ queuePosition: input.queuePosition,
1441
+ message: input.message,
1442
+ dispatchedRunId: input.runId,
1443
+ createdAt: input.createdAt,
1444
+ dispatchedAt: dispatchOccurredAt ?? input.createdAt,
1445
+ });
1446
+ }
1447
+ function upsertSessionTurnBinding(database, input) {
1448
+ const existingTurn = database
1449
+ .prepare(`SELECT turn_id, queue_position
1450
+ FROM session_turns
1451
+ WHERE turn_id = ? OR dispatched_run_id = ? OR (
1452
+ session_id = ? AND queue_position = ?
1453
+ )
1454
+ ORDER BY
1455
+ CASE
1456
+ WHEN turn_id = ? THEN 0
1457
+ WHEN dispatched_run_id = ? THEN 1
1458
+ ELSE 2
1459
+ END,
1460
+ queue_position ASC
1461
+ LIMIT 1`)
1462
+ .get(input.turnId, input.dispatchedRunId, input.sessionId, input.queuePosition, input.turnId, input.dispatchedRunId);
1463
+ if (existingTurn?.turn_id) {
1464
+ database
1465
+ .prepare(`UPDATE session_turns
1466
+ SET session_id = ?, status = 'dispatched',
1467
+ message_json = ?, dispatched_run_id = ?, created_at = ?,
1468
+ dispatched_at = ?, cancelled_at = NULL
1469
+ WHERE turn_id = ?`)
1470
+ .run(input.sessionId, JSON.stringify(input.message), input.dispatchedRunId, input.createdAt, input.dispatchedAt, String(existingTurn.turn_id));
1471
+ return;
1472
+ }
1473
+ database
1474
+ .prepare(`INSERT INTO session_turns (
1475
+ turn_id, session_id, queue_position, status, message_json, version,
1476
+ dispatched_run_id, created_at, dispatched_at, cancelled_at
1477
+ ) VALUES (?, ?, ?, 'dispatched', ?, 2, ?, ?, ?, NULL)`)
1478
+ .run(input.turnId, input.sessionId, input.queuePosition, JSON.stringify(input.message), input.dispatchedRunId, input.createdAt, input.dispatchedAt);
1479
+ }
1480
+ function normalizeLegacyProjectionEvent(database, sessionId, event, currentSynthetic, bindingState) {
1481
+ if (event.runId) {
1482
+ if (event.type === "MESSAGE_RECEIVED"
1483
+ || event.type === "AGENT_EVENT"
1484
+ || event.type === "APPROVAL_REQUESTED") {
1485
+ ensureSyntheticProjectionTurnForRun(database, sessionId, event);
1486
+ }
1487
+ return { event, syntheticGroup: currentSynthetic };
1488
+ }
1489
+ let syntheticGroup = currentSynthetic;
1490
+ if (event.type !== "MESSAGE_RECEIVED" && event.type !== "AGENT_EVENT") {
1491
+ return { event, syntheticGroup };
1492
+ }
1493
+ if (event.type === "MESSAGE_RECEIVED" || !syntheticGroup) {
1494
+ const binding = bindingState && bindingState.index < bindingState.bindings.length
1495
+ ? bindingState.bindings[bindingState.index++]
1496
+ : undefined;
1497
+ if (binding) {
1498
+ syntheticGroup = {
1499
+ runId: binding.runId,
1500
+ turnId: binding.turnId,
1501
+ queuePosition: bindingState ? bindingState.index : nextLegacyQueuePosition(database, sessionId),
1502
+ };
1503
+ ensureSyntheticTimelineTurn(database, sessionId, binding.turnId, binding.runId, event.sequence, event.occurredAt);
1504
+ }
1505
+ else {
1506
+ const seed = event.type === "MESSAGE_RECEIVED"
1507
+ ? `message:${event.sequence}`
1508
+ : `agent:${event.sequence}`;
1509
+ syntheticGroup = {
1510
+ runId: createMigrationId("run", sessionId, seed),
1511
+ turnId: createMigrationId("turn", sessionId, seed),
1512
+ queuePosition: nextLegacyQueuePosition(database, sessionId),
1513
+ };
1514
+ ensureSyntheticTimelineTurn(database, sessionId, syntheticGroup.turnId, syntheticGroup.runId, event.sequence, event.occurredAt);
1515
+ }
1516
+ }
1517
+ else {
1518
+ ensureSyntheticTimelineTurn(database, sessionId, syntheticGroup.turnId, syntheticGroup.runId, event.sequence, event.occurredAt);
1519
+ }
1520
+ if (!syntheticGroup) {
1521
+ throw new Error("legacy synthetic projection group missing");
1522
+ }
1523
+ return {
1524
+ event: {
1525
+ ...event,
1526
+ runId: syntheticGroup.runId,
1527
+ target: event.target ?? syntheticGroup.turnId,
1528
+ },
1529
+ syntheticGroup,
1530
+ };
1531
+ }
1532
+ function ensureSyntheticProjectionTurnForRun(database, sessionId, event) {
1533
+ const run = database
1534
+ .prepare("SELECT * FROM runs WHERE id = ?")
1535
+ .get(event.runId);
1536
+ if (!run)
1537
+ return;
1538
+ const turnId = run.turn_id === null || run.turn_id === undefined
1539
+ ? legacyTurnIdFromEvent(sessionId, event, event.runId)
1540
+ : String(run.turn_id);
1541
+ ensureSyntheticTimelineTurn(database, sessionId, turnId, event.runId, event.sequence, event.occurredAt);
1542
+ }
1543
+ function toWorkItem(row) {
1544
+ return {
1545
+ schemaVersion: Number(row.schema_version),
1546
+ id: String(row.id),
1547
+ title: String(row.title),
1548
+ status: String(row.status),
1549
+ mode: String(row.mode),
1550
+ conversationId: String(row.conversation_id),
1551
+ sessionId: row.session_id === null || row.session_id === undefined
1552
+ ? null
1553
+ : String(row.session_id),
1554
+ agentId: row.agent_id === null ? null : String(row.agent_id),
1555
+ workflowId: row.workflow_id === null ? null : String(row.workflow_id),
1556
+ workflowRevision: row.workflow_revision === null ? null : String(row.workflow_revision),
1557
+ workspaceScope: JSON.parse(String(row.workspace_scope)),
1558
+ identifiers: JSON.parse(String(row.identifiers)),
1559
+ contextRevision: Number(row.context_revision),
1560
+ riskLevel: String(row.risk_level),
1561
+ createdAt: String(row.created_at),
1562
+ updatedAt: String(row.updated_at),
1563
+ };
1564
+ }
1565
+ function toDomainEvent(row) {
1566
+ const runId = row.run_id === null ? null : String(row.run_id);
1567
+ return {
1568
+ schemaVersion: Number(row.schema_version),
1569
+ eventId: String(row.event_id),
1570
+ sequence: Number(row.sequence),
1571
+ workItemId: String(row.work_item_id),
1572
+ runId,
1573
+ executionKind: executionKindValue(row.execution_kind, runId),
1574
+ type: String(row.type),
1575
+ occurredAt: String(row.occurred_at),
1576
+ actor: String(row.actor),
1577
+ target: row.target === null ? null : String(row.target),
1578
+ inputHash: row.input_hash === null ? null : String(row.input_hash),
1579
+ resultRef: row.result_ref === null ? null : String(row.result_ref),
1580
+ payload: JSON.parse(String(row.payload)),
1581
+ };
1582
+ }
1583
+ function toRun(row) {
1584
+ return {
1585
+ schemaVersion: Number(row.schema_version),
1586
+ id: String(row.id),
1587
+ workItemId: String(row.work_item_id),
1588
+ sessionId: row.session_id === null || row.session_id === undefined
1589
+ ? null
1590
+ : String(row.session_id),
1591
+ turnId: row.turn_id === null || row.turn_id === undefined
1592
+ ? null
1593
+ : String(row.turn_id),
1594
+ mode: String(row.mode),
1595
+ status: String(row.status),
1596
+ executionKind: executionKindValue(row.execution_kind, String(row.id)),
1597
+ agentId: row.agent_id === null ? null : String(row.agent_id),
1598
+ planId: row.plan_id === null ? null : String(row.plan_id),
1599
+ planIrHash: row.plan_ir_hash === null || row.plan_ir_hash === undefined ? null : String(row.plan_ir_hash),
1600
+ workflowRevision: row.workflow_revision === null || row.workflow_revision === undefined
1601
+ ? null
1602
+ : String(row.workflow_revision),
1603
+ terminalReason: row.terminal_reason === null || row.terminal_reason === undefined
1604
+ ? null
1605
+ : String(row.terminal_reason),
1606
+ replaySafety: String(row.replay_safety ?? "safe"),
1607
+ leaseOwner: row.lease_owner === null || row.lease_owner === undefined
1608
+ ? null
1609
+ : String(row.lease_owner),
1610
+ leaseExpiresAt: row.lease_expires_at === null || row.lease_expires_at === undefined
1611
+ ? null
1612
+ : String(row.lease_expires_at),
1613
+ cancelRequestedAt: row.cancel_requested_at === null || row.cancel_requested_at === undefined
1614
+ ? null
1615
+ : String(row.cancel_requested_at),
1616
+ cancelDeadlineAt: row.cancel_deadline_at === null || row.cancel_deadline_at === undefined
1617
+ ? null
1618
+ : String(row.cancel_deadline_at),
1619
+ providerSessionId: row.provider_session_id === null || row.provider_session_id === undefined
1620
+ ? null
1621
+ : String(row.provider_session_id),
1622
+ createdAt: String(row.created_at),
1623
+ updatedAt: String(row.updated_at),
1624
+ };
1625
+ }
1626
+ function executionKindValue(value, runId) {
1627
+ if (runId === null) {
1628
+ if (value === null || value === undefined)
1629
+ return null;
1630
+ throw new Error("Runless event cannot have an execution kind");
1631
+ }
1632
+ if (value === "agent" || value === "flow")
1633
+ return value;
1634
+ throw new Error(`Invalid Run execution kind: ${runId}`);
1635
+ }
1636
+ function toSessionRuntime(row) {
1637
+ return {
1638
+ sessionId: String(row.session_id),
1639
+ activeRunId: row.active_run_id === null || row.active_run_id === undefined
1640
+ ? null
1641
+ : String(row.active_run_id),
1642
+ queueState: String(row.queue_state),
1643
+ queuePauseReason: row.queue_pause_reason === null || row.queue_pause_reason === undefined
1644
+ ? null
1645
+ : String(row.queue_pause_reason),
1646
+ lastEventSequence: Number(row.last_event_sequence),
1647
+ version: Number(row.version),
1648
+ updatedAt: String(row.updated_at),
1649
+ };
1650
+ }
1651
+ function toSessionTurn(row) {
1652
+ return {
1653
+ turnId: String(row.turn_id),
1654
+ sessionId: String(row.session_id),
1655
+ queuePosition: Number(row.queue_position),
1656
+ status: String(row.status),
1657
+ message: parseSessionTurnMessage(String(row.message_json)),
1658
+ version: Number(row.version),
1659
+ dispatchedRunId: row.dispatched_run_id === null || row.dispatched_run_id === undefined
1660
+ ? null
1661
+ : String(row.dispatched_run_id),
1662
+ createdAt: String(row.created_at),
1663
+ dispatchedAt: row.dispatched_at === null || row.dispatched_at === undefined
1664
+ ? null
1665
+ : String(row.dispatched_at),
1666
+ cancelledAt: row.cancelled_at === null || row.cancelled_at === undefined
1667
+ ? null
1668
+ : String(row.cancelled_at),
1669
+ };
1670
+ }
1671
+ function toRunAttempt(row) {
1672
+ return {
1673
+ attemptId: String(row.attempt_id),
1674
+ runId: String(row.run_id),
1675
+ attemptNumber: Number(row.attempt_number),
1676
+ startedAt: String(row.started_at),
1677
+ endedAt: row.ended_at === null
1678
+ ? null
1679
+ : String(row.ended_at),
1680
+ providerError: row.provider_error === null
1681
+ ? null
1682
+ : String(row.provider_error),
1683
+ sideEffectBoundary: String(row.side_effect_boundary),
1684
+ };
1685
+ }
1686
+ function toTimelineSegment(row) {
1687
+ return {
1688
+ segmentId: String(row.segment_id),
1689
+ blockId: String(row.block_id),
1690
+ segmentIndex: Number(row.segment_index),
1691
+ content: String(row.content),
1692
+ byteLength: Number(row.byte_length),
1693
+ sealed: Number(row.sealed) === 1,
1694
+ };
1695
+ }
1696
+ function toTimelineBlock(row) {
1697
+ return {
1698
+ blockId: String(row.block_id),
1699
+ sessionId: String(row.session_id),
1700
+ turnId: String(row.turn_id),
1701
+ runId: String(row.run_id),
1702
+ blockIndex: Number(row.block_index),
1703
+ kind: String(row.kind),
1704
+ status: String(row.status),
1705
+ metadata: JSON.parse(String(row.metadata_json ?? "{}")),
1706
+ };
1707
+ }
1708
+ function toTimelineTurn(row) {
1709
+ return {
1710
+ sessionId: String(row.session_id),
1711
+ timelineIndex: Number(row.timeline_index),
1712
+ turnId: String(row.turn_id),
1713
+ runId: String(row.run_id),
1714
+ startedSequence: Number(row.started_sequence),
1715
+ endedSequence: row.ended_sequence === null || row.ended_sequence === undefined
1716
+ ? null
1717
+ : Number(row.ended_sequence),
1718
+ status: String(row.status),
1719
+ };
1720
+ }
1721
+ function toPlan(row) {
1722
+ return {
1723
+ schemaVersion: Number(row.schema_version),
1724
+ planId: String(row.plan_id),
1725
+ source: String(row.source),
1726
+ workflowId: String(row.workflow_id),
1727
+ definitionRevision: row.definition_revision === null ? null : String(row.definition_revision),
1728
+ planIrHash: row.plan_ir_hash === null || row.plan_ir_hash === undefined ? null : String(row.plan_ir_hash),
1729
+ sessionId: row.session_id === null ? null : String(row.session_id),
1730
+ runId: row.run_id === null ? null : String(row.run_id),
1731
+ steps: JSON.parse(String(row.steps)).map(clonePlanStep),
1732
+ createdAt: String(row.created_at),
1733
+ };
1734
+ }
1735
+ function toArtifact(row) {
1736
+ return {
1737
+ id: String(row.id),
1738
+ workItemId: String(row.work_item_id),
1739
+ runId: String(row.run_id),
1740
+ stepId: row.step_id === null ? null : String(row.step_id),
1741
+ kind: String(row.kind),
1742
+ name: String(row.name),
1743
+ mimeType: String(row.mime_type),
1744
+ content: String(row.content),
1745
+ contentHash: String(row.content_hash),
1746
+ metadata: JSON.parse(String(row.metadata)),
1747
+ createdAt: String(row.created_at),
1748
+ };
1749
+ }
1750
+ function toMessageAttachment(row) {
1751
+ return {
1752
+ schemaVersion: Number(row.schema_version),
1753
+ id: String(row.id),
1754
+ workItemId: String(row.work_item_id),
1755
+ name: String(row.name),
1756
+ mimeType: String(row.mime_type),
1757
+ dataBase64: String(row.data_base64),
1758
+ byteSize: Number(row.byte_size),
1759
+ contentHash: String(row.content_hash),
1760
+ createdAt: String(row.created_at),
1761
+ };
1762
+ }
1763
+ function toVerification(row) {
1764
+ return {
1765
+ id: String(row.id),
1766
+ workItemId: String(row.work_item_id),
1767
+ runId: String(row.run_id),
1768
+ stepId: row.step_id === null ? null : String(row.step_id),
1769
+ validator: String(row.validator),
1770
+ status: String(row.status),
1771
+ summary: String(row.summary),
1772
+ artifactIds: JSON.parse(String(row.artifact_ids)),
1773
+ createdAt: String(row.created_at),
1774
+ };
1775
+ }
1776
+ function clonePlanStep(step) {
1777
+ return {
1778
+ ...step,
1779
+ dependsOn: [...step.dependsOn],
1780
+ branches: step.branches.map((branch) => ({ ...branch })),
1781
+ retry: step.retry ? { ...step.retry } : null,
1782
+ };
1783
+ }
1784
+ //# sourceMappingURL=index.js.map