@renxqoo/renx-code 0.0.9 → 0.0.10

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 (286) hide show
  1. package/README.md +14 -0
  2. package/bin/renx.cjs +79 -42
  3. package/bin/renx.exe +0 -0
  4. package/package.json +10 -28
  5. package/src/App.tsx +0 -297
  6. package/src/agent/runtime/event-format.ts +0 -258
  7. package/src/agent/runtime/model-types.ts +0 -13
  8. package/src/agent/runtime/runtime.context-usage.test.ts +0 -192
  9. package/src/agent/runtime/runtime.error-handling.test.ts +0 -235
  10. package/src/agent/runtime/runtime.simple.test.ts +0 -16
  11. package/src/agent/runtime/runtime.test.ts +0 -296
  12. package/src/agent/runtime/runtime.ts +0 -875
  13. package/src/agent/runtime/runtime.usage-forwarding.test.ts +0 -228
  14. package/src/agent/runtime/source-modules.test.ts +0 -38
  15. package/src/agent/runtime/source-modules.ts +0 -370
  16. package/src/agent/runtime/tool-call-buffer.test.ts +0 -65
  17. package/src/agent/runtime/tool-call-buffer.ts +0 -60
  18. package/src/agent/runtime/tool-confirmation.test.ts +0 -56
  19. package/src/agent/runtime/tool-confirmation.ts +0 -15
  20. package/src/agent/runtime/types.ts +0 -99
  21. package/src/commands/slash-commands.test.ts +0 -216
  22. package/src/commands/slash-commands.ts +0 -64
  23. package/src/components/chat/assistant-reply.test.tsx +0 -47
  24. package/src/components/chat/assistant-reply.tsx +0 -136
  25. package/src/components/chat/assistant-segment.test.ts +0 -99
  26. package/src/components/chat/assistant-segment.tsx +0 -125
  27. package/src/components/chat/assistant-tool-group.tsx +0 -900
  28. package/src/components/chat/code-block.test.tsx +0 -206
  29. package/src/components/chat/code-block.tsx +0 -313
  30. package/src/components/chat/prompt-card.tsx +0 -81
  31. package/src/components/chat/segment-groups.test.ts +0 -52
  32. package/src/components/chat/segment-groups.ts +0 -106
  33. package/src/components/chat/turn-item.tsx +0 -39
  34. package/src/components/conversation-panel.tsx +0 -43
  35. package/src/components/file-mention-menu.tsx +0 -77
  36. package/src/components/file-picker-dialog.tsx +0 -206
  37. package/src/components/footer-hints.tsx +0 -75
  38. package/src/components/model-picker-dialog.tsx +0 -248
  39. package/src/components/prompt.tsx +0 -233
  40. package/src/components/slash-command-menu.tsx +0 -65
  41. package/src/components/tool-confirm-dialog-content.test.ts +0 -103
  42. package/src/components/tool-confirm-dialog-content.ts +0 -186
  43. package/src/components/tool-confirm-dialog.tsx +0 -187
  44. package/src/components/tool-display-config.ts +0 -119
  45. package/src/context-usage-regressions.test.ts +0 -26
  46. package/src/files/attachment-capabilities.test.ts +0 -30
  47. package/src/files/attachment-capabilities.ts +0 -50
  48. package/src/files/attachment-content.ts +0 -153
  49. package/src/files/file-mention-query.test.ts +0 -34
  50. package/src/files/file-mention-query.ts +0 -32
  51. package/src/files/prompt-display.ts +0 -13
  52. package/src/files/types.ts +0 -5
  53. package/src/files/workspace-files.ts +0 -61
  54. package/src/hooks/agent-event-handlers.test.ts +0 -207
  55. package/src/hooks/agent-event-handlers.ts +0 -196
  56. package/src/hooks/chat-local-replies.fixed.test.ts +0 -119
  57. package/src/hooks/chat-local-replies.test.ts +0 -153
  58. package/src/hooks/chat-local-replies.ts +0 -63
  59. package/src/hooks/turn-updater.test.ts +0 -70
  60. package/src/hooks/turn-updater.ts +0 -166
  61. package/src/hooks/use-agent-chat.context.test.ts +0 -10
  62. package/src/hooks/use-agent-chat.status.test.ts +0 -14
  63. package/src/hooks/use-agent-chat.test.ts +0 -80
  64. package/src/hooks/use-agent-chat.ts +0 -621
  65. package/src/hooks/use-file-mention-menu.ts +0 -196
  66. package/src/hooks/use-file-picker.ts +0 -185
  67. package/src/hooks/use-model-picker.ts +0 -196
  68. package/src/hooks/use-slash-command-menu.ts +0 -154
  69. package/src/index.tsx +0 -55
  70. package/src/runtime/clipboard.test.ts +0 -43
  71. package/src/runtime/clipboard.ts +0 -89
  72. package/src/runtime/exit.test.ts +0 -177
  73. package/src/runtime/exit.ts +0 -98
  74. package/src/runtime/runtime-support.test.ts +0 -31
  75. package/src/runtime/terminal-theme.test.ts +0 -55
  76. package/src/runtime/terminal-theme.ts +0 -196
  77. package/src/types/chat.ts +0 -32
  78. package/src/types/message-content.ts +0 -48
  79. package/src/ui/open-code-theme.ts +0 -176
  80. package/src/ui/opencode-markdown.ts +0 -211
  81. package/src/ui/theme.simple.test.ts +0 -52
  82. package/src/ui/theme.test.ts +0 -151
  83. package/src/ui/theme.ts +0 -152
  84. package/src/utils/time.test.ts +0 -144
  85. package/src/utils/time.ts +0 -7
  86. package/tsconfig.json +0 -30
  87. package/vendor/agent-root/src/agent/ENTERPRISE_ACCEPTANCE_CHECKLIST.md +0 -95
  88. package/vendor/agent-root/src/agent/ENTERPRISE_REALTIME.html +0 -1345
  89. package/vendor/agent-root/src/agent/ENTERPRISE_REALTIME.md +0 -1353
  90. package/vendor/agent-root/src/agent/ERROR_CONTRACT.md +0 -60
  91. package/vendor/agent-root/src/agent/TEST_COVERAGE_ANALYSIS.md +0 -278
  92. package/vendor/agent-root/src/agent/__test__/error-contract.test.ts +0 -72
  93. package/vendor/agent-root/src/agent/__test__/types.test.ts +0 -137
  94. package/vendor/agent-root/src/agent/agent/__test__/abort-runtime.test.ts +0 -83
  95. package/vendor/agent-root/src/agent/agent/__test__/callback-safety.test.ts +0 -34
  96. package/vendor/agent-root/src/agent/agent/__test__/compaction.test.ts +0 -323
  97. package/vendor/agent-root/src/agent/agent/__test__/concurrency.test.ts +0 -290
  98. package/vendor/agent-root/src/agent/agent/__test__/error-normalizer.test.ts +0 -377
  99. package/vendor/agent-root/src/agent/agent/__test__/error.test.ts +0 -212
  100. package/vendor/agent-root/src/agent/agent/__test__/fault-injection.test.ts +0 -295
  101. package/vendor/agent-root/src/agent/agent/__test__/index.test.ts +0 -3607
  102. package/vendor/agent-root/src/agent/agent/__test__/logger.test.ts +0 -35
  103. package/vendor/agent-root/src/agent/agent/__test__/message-utils.test.ts +0 -517
  104. package/vendor/agent-root/src/agent/agent/__test__/telemetry.test.ts +0 -97
  105. package/vendor/agent-root/src/agent/agent/__test__/timeout-budget.test.ts +0 -479
  106. package/vendor/agent-root/src/agent/agent/__test__/tool-call-merge.test.ts +0 -80
  107. package/vendor/agent-root/src/agent/agent/__test__/tool-execution-ledger.test.ts +0 -76
  108. package/vendor/agent-root/src/agent/agent/__test__/write-buffer.test.ts +0 -173
  109. package/vendor/agent-root/src/agent/agent/__test__/write-file-session.test.ts +0 -109
  110. package/vendor/agent-root/src/agent/agent/abort-runtime.ts +0 -71
  111. package/vendor/agent-root/src/agent/agent/callback-safety.ts +0 -33
  112. package/vendor/agent-root/src/agent/agent/compaction.ts +0 -291
  113. package/vendor/agent-root/src/agent/agent/concurrency.ts +0 -103
  114. package/vendor/agent-root/src/agent/agent/error-normalizer.ts +0 -190
  115. package/vendor/agent-root/src/agent/agent/error.ts +0 -198
  116. package/vendor/agent-root/src/agent/agent/index.ts +0 -1772
  117. package/vendor/agent-root/src/agent/agent/logger.ts +0 -65
  118. package/vendor/agent-root/src/agent/agent/message-utils.ts +0 -101
  119. package/vendor/agent-root/src/agent/agent/stream-events.ts +0 -61
  120. package/vendor/agent-root/src/agent/agent/telemetry.ts +0 -123
  121. package/vendor/agent-root/src/agent/agent/timeout-budget.ts +0 -227
  122. package/vendor/agent-root/src/agent/agent/tool-call-merge.ts +0 -111
  123. package/vendor/agent-root/src/agent/agent/tool-execution-ledger.ts +0 -164
  124. package/vendor/agent-root/src/agent/agent/write-buffer.ts +0 -188
  125. package/vendor/agent-root/src/agent/agent/write-file-session.ts +0 -238
  126. package/vendor/agent-root/src/agent/app/__test__/agent-app-service.test.ts +0 -1053
  127. package/vendor/agent-root/src/agent/app/__test__/minimal-agent-application.test.ts +0 -158
  128. package/vendor/agent-root/src/agent/app/__test__/sqlite-agent-app-store.test.ts +0 -437
  129. package/vendor/agent-root/src/agent/app/agent-app-service.ts +0 -748
  130. package/vendor/agent-root/src/agent/app/contracts.ts +0 -109
  131. package/vendor/agent-root/src/agent/app/index.ts +0 -5
  132. package/vendor/agent-root/src/agent/app/minimal-agent-application.ts +0 -151
  133. package/vendor/agent-root/src/agent/app/ports.ts +0 -72
  134. package/vendor/agent-root/src/agent/app/sqlite-agent-app-store.ts +0 -1182
  135. package/vendor/agent-root/src/agent/app/sqlite-client.ts +0 -177
  136. package/vendor/agent-root/src/agent/docs/cli-app-layer/00-README.md +0 -36
  137. package/vendor/agent-root/src/agent/docs/cli-app-layer/01-scope-and-goals.md +0 -33
  138. package/vendor/agent-root/src/agent/docs/cli-app-layer/02-architecture-overview.md +0 -40
  139. package/vendor/agent-root/src/agent/docs/cli-app-layer/03-domain-model-and-contracts.md +0 -91
  140. package/vendor/agent-root/src/agent/docs/cli-app-layer/04-ports-and-interfaces.md +0 -116
  141. package/vendor/agent-root/src/agent/docs/cli-app-layer/05-run-orchestration-and-state-machine.md +0 -52
  142. package/vendor/agent-root/src/agent/docs/cli-app-layer/06-cli-commands-and-ux.md +0 -53
  143. package/vendor/agent-root/src/agent/docs/cli-app-layer/07-storage-design-local.md +0 -52
  144. package/vendor/agent-root/src/agent/docs/cli-app-layer/08-error-and-observability.md +0 -40
  145. package/vendor/agent-root/src/agent/docs/cli-app-layer/09-security-and-policy-boundary.md +0 -19
  146. package/vendor/agent-root/src/agent/docs/cli-app-layer/10-test-plan-and-acceptance.md +0 -28
  147. package/vendor/agent-root/src/agent/docs/cli-app-layer/11-implementation-phases.md +0 -26
  148. package/vendor/agent-root/src/agent/docs/cli-app-layer/12-open-questions-and-risks.md +0 -30
  149. package/vendor/agent-root/src/agent/docs/cli-app-layer/13-sqlite-schema-fields-and-rationale.md +0 -567
  150. package/vendor/agent-root/src/agent/docs/cli-app-layer/14-project-flow-mermaid.md +0 -583
  151. package/vendor/agent-root/src/agent/docs/cli-app-layer/15-openclaw-style-project-blueprint.md +0 -972
  152. package/vendor/agent-root/src/agent/error-contract.ts +0 -154
  153. package/vendor/agent-root/src/agent/prompts/system.ts +0 -246
  154. package/vendor/agent-root/src/agent/prompts/system1.ts +0 -208
  155. package/vendor/agent-root/src/agent/storage/__test__/file-history-store.test.ts +0 -98
  156. package/vendor/agent-root/src/agent/storage/file-history-store.ts +0 -313
  157. package/vendor/agent-root/src/agent/storage/file-storage-config.ts +0 -94
  158. package/vendor/agent-root/src/agent/storage/file-system.ts +0 -31
  159. package/vendor/agent-root/src/agent/storage/file-write-service.ts +0 -21
  160. package/vendor/agent-root/src/agent/tool/__test__/base-tool.test.ts +0 -413
  161. package/vendor/agent-root/src/agent/tool/__test__/bash-policy.test.ts +0 -356
  162. package/vendor/agent-root/src/agent/tool/__test__/bash.mocked-coverage.test.ts +0 -375
  163. package/vendor/agent-root/src/agent/tool/__test__/bash.test.ts +0 -372
  164. package/vendor/agent-root/src/agent/tool/__test__/error.test.ts +0 -108
  165. package/vendor/agent-root/src/agent/tool/__test__/file-edit-tool.test.ts +0 -258
  166. package/vendor/agent-root/src/agent/tool/__test__/file-history-tools.test.ts +0 -121
  167. package/vendor/agent-root/src/agent/tool/__test__/file-read-tool.test.ts +0 -210
  168. package/vendor/agent-root/src/agent/tool/__test__/glob.test.ts +0 -139
  169. package/vendor/agent-root/src/agent/tool/__test__/grep.mocked-coverage.test.ts +0 -456
  170. package/vendor/agent-root/src/agent/tool/__test__/grep.test.ts +0 -192
  171. package/vendor/agent-root/src/agent/tool/__test__/lsp.test.ts +0 -300
  172. package/vendor/agent-root/src/agent/tool/__test__/outside-workspace-confirmation.test.ts +0 -214
  173. package/vendor/agent-root/src/agent/tool/__test__/path-security.test.ts +0 -336
  174. package/vendor/agent-root/src/agent/tool/__test__/skill-loader.test.ts +0 -494
  175. package/vendor/agent-root/src/agent/tool/__test__/skill-parser.test.ts +0 -543
  176. package/vendor/agent-root/src/agent/tool/__test__/skill-tool.test.ts +0 -172
  177. package/vendor/agent-root/src/agent/tool/__test__/task-concurrency-and-version.test.ts +0 -116
  178. package/vendor/agent-root/src/agent/tool/__test__/task-create-get-list-update.test.ts +0 -267
  179. package/vendor/agent-root/src/agent/tool/__test__/task-create.test.ts +0 -519
  180. package/vendor/agent-root/src/agent/tool/__test__/task-errors.test.ts +0 -225
  181. package/vendor/agent-root/src/agent/tool/__test__/task-output-blocking.test.ts +0 -223
  182. package/vendor/agent-root/src/agent/tool/__test__/task-output.test.ts +0 -184
  183. package/vendor/agent-root/src/agent/tool/__test__/task-parent-abort.test.ts +0 -287
  184. package/vendor/agent-root/src/agent/tool/__test__/task-real-runner-adapter.test.ts +0 -190
  185. package/vendor/agent-root/src/agent/tool/__test__/task-run-lifecycle.test.ts +0 -352
  186. package/vendor/agent-root/src/agent/tool/__test__/task-store-runner-branches.test.ts +0 -395
  187. package/vendor/agent-root/src/agent/tool/__test__/task-store.test.ts +0 -391
  188. package/vendor/agent-root/src/agent/tool/__test__/task-subagent-config-integration.test.ts +0 -176
  189. package/vendor/agent-root/src/agent/tool/__test__/task-subagent-config.test.ts +0 -68
  190. package/vendor/agent-root/src/agent/tool/__test__/task-tools-core-edges.test.ts +0 -630
  191. package/vendor/agent-root/src/agent/tool/__test__/task-tools-runtime-edges.test.ts +0 -732
  192. package/vendor/agent-root/src/agent/tool/__test__/task-types.test.ts +0 -494
  193. package/vendor/agent-root/src/agent/tool/__test__/task-utils-branches.test.ts +0 -175
  194. package/vendor/agent-root/src/agent/tool/__test__/tool-manager.test.ts +0 -505
  195. package/vendor/agent-root/src/agent/tool/__test__/types.test.ts +0 -55
  196. package/vendor/agent-root/src/agent/tool/__test__/web-fetch.test.ts +0 -244
  197. package/vendor/agent-root/src/agent/tool/__test__/web-search.test.ts +0 -290
  198. package/vendor/agent-root/src/agent/tool/__test__/write-file.test.ts +0 -368
  199. package/vendor/agent-root/src/agent/tool/base-tool.ts +0 -345
  200. package/vendor/agent-root/src/agent/tool/bash-policy.ts +0 -636
  201. package/vendor/agent-root/src/agent/tool/bash.ts +0 -688
  202. package/vendor/agent-root/src/agent/tool/error.ts +0 -131
  203. package/vendor/agent-root/src/agent/tool/file-edit-tool.ts +0 -264
  204. package/vendor/agent-root/src/agent/tool/file-history-list.ts +0 -103
  205. package/vendor/agent-root/src/agent/tool/file-history-restore.ts +0 -149
  206. package/vendor/agent-root/src/agent/tool/file-read-tool.ts +0 -211
  207. package/vendor/agent-root/src/agent/tool/glob.ts +0 -171
  208. package/vendor/agent-root/src/agent/tool/grep.ts +0 -496
  209. package/vendor/agent-root/src/agent/tool/lsp.ts +0 -481
  210. package/vendor/agent-root/src/agent/tool/path-security.ts +0 -117
  211. package/vendor/agent-root/src/agent/tool/search/common.ts +0 -153
  212. package/vendor/agent-root/src/agent/tool/skill/index.ts +0 -13
  213. package/vendor/agent-root/src/agent/tool/skill/loader.ts +0 -229
  214. package/vendor/agent-root/src/agent/tool/skill/parser.ts +0 -124
  215. package/vendor/agent-root/src/agent/tool/skill/types.ts +0 -27
  216. package/vendor/agent-root/src/agent/tool/skill-tool.ts +0 -143
  217. package/vendor/agent-root/src/agent/tool/task-create.ts +0 -186
  218. package/vendor/agent-root/src/agent/tool/task-errors.ts +0 -42
  219. package/vendor/agent-root/src/agent/tool/task-get.ts +0 -116
  220. package/vendor/agent-root/src/agent/tool/task-graph.ts +0 -78
  221. package/vendor/agent-root/src/agent/tool/task-list.ts +0 -141
  222. package/vendor/agent-root/src/agent/tool/task-mock-runner-adapter.ts +0 -232
  223. package/vendor/agent-root/src/agent/tool/task-output.ts +0 -223
  224. package/vendor/agent-root/src/agent/tool/task-parent-abort.ts +0 -115
  225. package/vendor/agent-root/src/agent/tool/task-real-runner-adapter.ts +0 -336
  226. package/vendor/agent-root/src/agent/tool/task-runner-adapter.ts +0 -55
  227. package/vendor/agent-root/src/agent/tool/task-stop.ts +0 -187
  228. package/vendor/agent-root/src/agent/tool/task-store.ts +0 -217
  229. package/vendor/agent-root/src/agent/tool/task-subagent-config.ts +0 -149
  230. package/vendor/agent-root/src/agent/tool/task-types.ts +0 -264
  231. package/vendor/agent-root/src/agent/tool/task-update.ts +0 -315
  232. package/vendor/agent-root/src/agent/tool/task.ts +0 -209
  233. package/vendor/agent-root/src/agent/tool/tool-manager.ts +0 -361
  234. package/vendor/agent-root/src/agent/tool/tool-prompts.ts +0 -242
  235. package/vendor/agent-root/src/agent/tool/types.ts +0 -116
  236. package/vendor/agent-root/src/agent/tool/web-fetch.ts +0 -227
  237. package/vendor/agent-root/src/agent/tool/web-search.ts +0 -208
  238. package/vendor/agent-root/src/agent/tool/write-file.ts +0 -497
  239. package/vendor/agent-root/src/agent/types.ts +0 -232
  240. package/vendor/agent-root/src/agent/utils/__tests__/index.test.ts +0 -18
  241. package/vendor/agent-root/src/agent/utils/__tests__/message-utils.test.ts +0 -610
  242. package/vendor/agent-root/src/agent/utils/__tests__/message.test.ts +0 -223
  243. package/vendor/agent-root/src/agent/utils/__tests__/token.test.ts +0 -42
  244. package/vendor/agent-root/src/agent/utils/index.ts +0 -16
  245. package/vendor/agent-root/src/agent/utils/message.ts +0 -171
  246. package/vendor/agent-root/src/agent/utils/token.ts +0 -28
  247. package/vendor/agent-root/src/config/__tests__/load-config-to-env.test.ts +0 -238
  248. package/vendor/agent-root/src/config/__tests__/loader.test.ts +0 -361
  249. package/vendor/agent-root/src/config/__tests__/runtime.test.ts +0 -88
  250. package/vendor/agent-root/src/config/index.ts +0 -55
  251. package/vendor/agent-root/src/config/loader.ts +0 -494
  252. package/vendor/agent-root/src/config/paths.ts +0 -30
  253. package/vendor/agent-root/src/config/runtime.ts +0 -163
  254. package/vendor/agent-root/src/config/types.ts +0 -96
  255. package/vendor/agent-root/src/logger/index.ts +0 -57
  256. package/vendor/agent-root/src/logger/logger.ts +0 -819
  257. package/vendor/agent-root/src/logger/types.ts +0 -150
  258. package/vendor/agent-root/src/providers/__tests__/errors.test.ts +0 -441
  259. package/vendor/agent-root/src/providers/__tests__/index.test.ts +0 -16
  260. package/vendor/agent-root/src/providers/__tests__/openai-compatible.options.test.ts +0 -318
  261. package/vendor/agent-root/src/providers/__tests__/openai-compatible.test.ts +0 -600
  262. package/vendor/agent-root/src/providers/__tests__/registry.test.ts +0 -523
  263. package/vendor/agent-root/src/providers/__tests__/responses-adapter.test.ts +0 -298
  264. package/vendor/agent-root/src/providers/adapters/__tests__/anthropic.test.ts +0 -354
  265. package/vendor/agent-root/src/providers/adapters/__tests__/kimi.test.ts +0 -58
  266. package/vendor/agent-root/src/providers/adapters/__tests__/standard.test.ts +0 -261
  267. package/vendor/agent-root/src/providers/adapters/anthropic.ts +0 -572
  268. package/vendor/agent-root/src/providers/adapters/base.ts +0 -131
  269. package/vendor/agent-root/src/providers/adapters/kimi.ts +0 -48
  270. package/vendor/agent-root/src/providers/adapters/responses.ts +0 -732
  271. package/vendor/agent-root/src/providers/adapters/standard.ts +0 -120
  272. package/vendor/agent-root/src/providers/http/__tests__/client.timeout.test.ts +0 -313
  273. package/vendor/agent-root/src/providers/http/client.ts +0 -289
  274. package/vendor/agent-root/src/providers/http/stream-parser.ts +0 -109
  275. package/vendor/agent-root/src/providers/index.ts +0 -76
  276. package/vendor/agent-root/src/providers/kimi-headers.ts +0 -177
  277. package/vendor/agent-root/src/providers/openai-compatible.ts +0 -387
  278. package/vendor/agent-root/src/providers/registry/model-config.ts +0 -477
  279. package/vendor/agent-root/src/providers/registry/provider-factory.ts +0 -127
  280. package/vendor/agent-root/src/providers/registry.ts +0 -135
  281. package/vendor/agent-root/src/providers/types/api.ts +0 -284
  282. package/vendor/agent-root/src/providers/types/config.ts +0 -58
  283. package/vendor/agent-root/src/providers/types/errors.ts +0 -323
  284. package/vendor/agent-root/src/providers/types/index.ts +0 -72
  285. package/vendor/agent-root/src/providers/types/provider.ts +0 -45
  286. package/vendor/agent-root/src/providers/types/registry.ts +0 -68
@@ -1,1182 +0,0 @@
1
- import type { Message } from '../types';
2
- import type {
3
- CliEventEnvelope,
4
- CompactionDroppedMessageRecord,
5
- ListConversationEventsOptions,
6
- ListRunLogsOptions,
7
- ListRunsOptions,
8
- ListRunsResult,
9
- RunRecord,
10
- RunLogRecord,
11
- } from './contracts';
12
- import type {
13
- ContextProjectionStorePort,
14
- EventStorePort,
15
- ExecutionStorePort,
16
- MessageProjectionStorePort,
17
- RunLogStorePort,
18
- } from './ports';
19
- import { AgentAppSqliteClient } from './sqlite-client';
20
-
21
- interface RunRow {
22
- execution_id: string;
23
- run_id: string;
24
- conversation_id: string;
25
- status: RunRecord['status'];
26
- created_at_ms: number;
27
- updated_at_ms: number;
28
- step_index: number;
29
- started_at_ms: number | null;
30
- completed_at_ms: number | null;
31
- last_checkpoint_seq: number | null;
32
- terminal_reason: RunRecord['terminalReason'] | null;
33
- error_code: string | null;
34
- error_category: string | null;
35
- error_message: string | null;
36
- }
37
-
38
- interface EventRow {
39
- conversation_id: string;
40
- execution_id: string;
41
- seq: number;
42
- event_type: CliEventEnvelope['eventType'];
43
- payload_json: string;
44
- created_at_ms: number;
45
- }
46
-
47
- interface MessageRow {
48
- message_id: string;
49
- execution_id?: string;
50
- seq?: number;
51
- role: Message['role'];
52
- type: Message['type'];
53
- content_json: string;
54
- reasoning_content: string | null;
55
- tool_call_id: string | null;
56
- tool_calls_json: string | null;
57
- usage_json: string | null;
58
- metadata_json: string | null;
59
- created_at_ms: number;
60
- }
61
-
62
- interface CursorToken {
63
- updatedAt: number;
64
- executionId: string;
65
- }
66
-
67
- interface MessageEventPayload {
68
- message: Message;
69
- stepIndex?: number;
70
- }
71
-
72
- interface CompactionDroppedMessageRow {
73
- conversation_id: string;
74
- execution_id: string;
75
- step_index: number;
76
- removed_message_id: string;
77
- created_at_ms: number;
78
- }
79
-
80
- interface RunLogRow {
81
- id: number;
82
- execution_id: string;
83
- conversation_id: string;
84
- step_index: number | null;
85
- level: 'debug' | 'info' | 'warn' | 'error';
86
- code: string | null;
87
- source: string;
88
- message: string;
89
- error_json: string | null;
90
- context_json: string | null;
91
- data_json: string | null;
92
- created_at_ms: number;
93
- }
94
-
95
- const APP_MIGRATIONS = [
96
- {
97
- version: 1,
98
- sql: `
99
- CREATE TABLE IF NOT EXISTS agent_v4_schema_migrations (
100
- version INTEGER PRIMARY KEY,
101
- applied_at_ms INTEGER NOT NULL
102
- );
103
-
104
- CREATE TABLE IF NOT EXISTS runs (
105
- execution_id TEXT PRIMARY KEY,
106
- run_id TEXT NOT NULL,
107
- conversation_id TEXT NOT NULL,
108
- status TEXT NOT NULL,
109
- created_at_ms INTEGER NOT NULL,
110
- updated_at_ms INTEGER NOT NULL,
111
- step_index INTEGER NOT NULL DEFAULT 0,
112
- started_at_ms INTEGER,
113
- completed_at_ms INTEGER,
114
- last_checkpoint_seq INTEGER,
115
- terminal_reason TEXT,
116
- error_code TEXT,
117
- error_category TEXT,
118
- error_message TEXT
119
- );
120
- CREATE INDEX IF NOT EXISTS idx_runs_conversation_updated
121
- ON runs(conversation_id, updated_at_ms DESC, execution_id DESC);
122
-
123
- CREATE TABLE IF NOT EXISTS events (
124
- event_id INTEGER PRIMARY KEY AUTOINCREMENT,
125
- conversation_id TEXT NOT NULL,
126
- execution_id TEXT NOT NULL,
127
- seq INTEGER NOT NULL,
128
- event_type TEXT NOT NULL,
129
- payload_json TEXT NOT NULL,
130
- created_at_ms INTEGER NOT NULL,
131
- UNIQUE(conversation_id, seq)
132
- );
133
- CREATE INDEX IF NOT EXISTS idx_events_execution_seq
134
- ON events(execution_id, seq ASC);
135
- CREATE INDEX IF NOT EXISTS idx_events_conversation_seq
136
- ON events(conversation_id, seq ASC);
137
-
138
- CREATE TABLE IF NOT EXISTS messages (
139
- message_id TEXT PRIMARY KEY,
140
- conversation_id TEXT NOT NULL,
141
- execution_id TEXT NOT NULL,
142
- seq INTEGER NOT NULL,
143
- step_index INTEGER,
144
- role TEXT NOT NULL,
145
- type TEXT NOT NULL,
146
- content_json TEXT NOT NULL,
147
- reasoning_content TEXT,
148
- tool_call_id TEXT,
149
- tool_calls_json TEXT,
150
- usage_json TEXT,
151
- metadata_json TEXT,
152
- created_at_ms INTEGER NOT NULL
153
- );
154
- CREATE INDEX IF NOT EXISTS idx_messages_conversation_seq
155
- ON messages(conversation_id, seq ASC);
156
- CREATE INDEX IF NOT EXISTS idx_messages_execution_seq
157
- ON messages(execution_id, seq ASC);
158
- `,
159
- },
160
- {
161
- version: 2,
162
- sql: `
163
- CREATE TABLE IF NOT EXISTS context_messages (
164
- conversation_id TEXT NOT NULL,
165
- execution_id TEXT NOT NULL,
166
- message_id TEXT NOT NULL,
167
- seq INTEGER NOT NULL,
168
- step_index INTEGER,
169
- role TEXT NOT NULL,
170
- type TEXT NOT NULL,
171
- content_json TEXT NOT NULL,
172
- reasoning_content TEXT,
173
- tool_call_id TEXT,
174
- tool_calls_json TEXT,
175
- usage_json TEXT,
176
- metadata_json TEXT,
177
- created_at_ms INTEGER NOT NULL,
178
- PRIMARY KEY (conversation_id, message_id)
179
- );
180
- CREATE INDEX IF NOT EXISTS idx_context_messages_conversation_seq
181
- ON context_messages(conversation_id, seq ASC);
182
- CREATE INDEX IF NOT EXISTS idx_context_messages_execution_seq
183
- ON context_messages(execution_id, seq ASC);
184
-
185
- CREATE TABLE IF NOT EXISTS compaction_dropped_messages (
186
- id INTEGER PRIMARY KEY AUTOINCREMENT,
187
- conversation_id TEXT NOT NULL,
188
- execution_id TEXT NOT NULL,
189
- step_index INTEGER NOT NULL,
190
- removed_message_id TEXT NOT NULL,
191
- created_at_ms INTEGER NOT NULL,
192
- UNIQUE(execution_id, step_index, removed_message_id)
193
- );
194
- CREATE INDEX IF NOT EXISTS idx_compaction_dropped_execution_step
195
- ON compaction_dropped_messages(execution_id, step_index ASC, id ASC);
196
- CREATE INDEX IF NOT EXISTS idx_compaction_dropped_conversation
197
- ON compaction_dropped_messages(conversation_id, id ASC);
198
-
199
- INSERT OR IGNORE INTO context_messages (
200
- conversation_id,
201
- execution_id,
202
- message_id,
203
- seq,
204
- step_index,
205
- role,
206
- type,
207
- content_json,
208
- reasoning_content,
209
- tool_call_id,
210
- tool_calls_json,
211
- usage_json,
212
- metadata_json,
213
- created_at_ms
214
- )
215
- SELECT
216
- conversation_id,
217
- execution_id,
218
- message_id,
219
- seq,
220
- step_index,
221
- role,
222
- type,
223
- content_json,
224
- reasoning_content,
225
- tool_call_id,
226
- tool_calls_json,
227
- usage_json,
228
- metadata_json,
229
- created_at_ms
230
- FROM messages;
231
- `,
232
- },
233
- {
234
- version: 3,
235
- sql: `
236
- CREATE TABLE IF NOT EXISTS run_logs (
237
- id INTEGER PRIMARY KEY AUTOINCREMENT,
238
- execution_id TEXT NOT NULL,
239
- conversation_id TEXT NOT NULL,
240
- step_index INTEGER,
241
- level TEXT NOT NULL CHECK(level IN ('debug', 'info', 'warn', 'error')),
242
- code TEXT,
243
- source TEXT NOT NULL,
244
- message TEXT NOT NULL,
245
- error_json TEXT,
246
- context_json TEXT,
247
- data_json TEXT,
248
- created_at_ms INTEGER NOT NULL
249
- );
250
- CREATE INDEX IF NOT EXISTS idx_run_logs_execution_created
251
- ON run_logs(execution_id, created_at_ms ASC, id ASC);
252
- CREATE INDEX IF NOT EXISTS idx_run_logs_execution_level_created
253
- ON run_logs(execution_id, level, created_at_ms ASC, id ASC);
254
- `,
255
- },
256
- ];
257
-
258
- export class SqliteAgentAppStore
259
- implements
260
- ExecutionStorePort,
261
- EventStorePort,
262
- MessageProjectionStorePort,
263
- ContextProjectionStorePort,
264
- RunLogStorePort
265
- {
266
- private readonly client: AgentAppSqliteClient;
267
- private prepared = false;
268
- private preparePromise: Promise<void> | null = null;
269
- private mutationChain: Promise<void> = Promise.resolve();
270
-
271
- constructor(private readonly dbPath: string) {
272
- this.client = new AgentAppSqliteClient(dbPath);
273
- }
274
-
275
- async prepare(): Promise<void> {
276
- if (this.prepared) {
277
- return;
278
- }
279
- if (this.preparePromise) {
280
- await this.preparePromise;
281
- return;
282
- }
283
-
284
- this.preparePromise = (async () => {
285
- await this.client.prepare();
286
- await this.withMutationLock(async () => {
287
- await runAppMigrations(this.client);
288
- });
289
- this.prepared = true;
290
- })();
291
-
292
- try {
293
- await this.preparePromise;
294
- } finally {
295
- this.preparePromise = null;
296
- }
297
- }
298
-
299
- async close(): Promise<void> {
300
- await this.client.close();
301
- this.prepared = false;
302
- }
303
-
304
- getDatabasePath(): string {
305
- return this.dbPath;
306
- }
307
-
308
- async create(run: RunRecord): Promise<void> {
309
- await this.prepare();
310
- await this.withMutationLock(async () => {
311
- await this.client.run(
312
- `
313
- INSERT INTO runs (
314
- execution_id,
315
- run_id,
316
- conversation_id,
317
- status,
318
- created_at_ms,
319
- updated_at_ms,
320
- step_index,
321
- started_at_ms,
322
- completed_at_ms,
323
- last_checkpoint_seq,
324
- terminal_reason,
325
- error_code,
326
- error_category,
327
- error_message
328
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
329
- `,
330
- [
331
- run.executionId,
332
- run.runId,
333
- run.conversationId,
334
- run.status,
335
- run.createdAt,
336
- run.updatedAt,
337
- run.stepIndex,
338
- run.startedAt ?? null,
339
- run.completedAt ?? null,
340
- run.lastCheckpointSeq ?? null,
341
- run.terminalReason ?? null,
342
- run.errorCode ?? null,
343
- run.errorCategory ?? null,
344
- run.errorMessage ?? null,
345
- ]
346
- );
347
- });
348
- }
349
-
350
- async patch(executionId: string, patch: Partial<RunRecord>): Promise<void> {
351
- await this.prepare();
352
- const updates: string[] = [];
353
- const params: unknown[] = [];
354
-
355
- if (typeof patch.runId === 'string') {
356
- updates.push('run_id = ?');
357
- params.push(patch.runId);
358
- }
359
- if (typeof patch.conversationId === 'string') {
360
- updates.push('conversation_id = ?');
361
- params.push(patch.conversationId);
362
- }
363
- if (typeof patch.status === 'string') {
364
- updates.push('status = ?');
365
- params.push(patch.status);
366
- }
367
- if (typeof patch.stepIndex === 'number') {
368
- updates.push('step_index = ?');
369
- params.push(patch.stepIndex);
370
- }
371
- if ('startedAt' in patch) {
372
- updates.push('started_at_ms = ?');
373
- params.push(patch.startedAt ?? null);
374
- }
375
- if ('completedAt' in patch) {
376
- updates.push('completed_at_ms = ?');
377
- params.push(patch.completedAt ?? null);
378
- }
379
- if ('lastCheckpointSeq' in patch) {
380
- updates.push('last_checkpoint_seq = ?');
381
- params.push(patch.lastCheckpointSeq ?? null);
382
- }
383
- if ('terminalReason' in patch) {
384
- updates.push('terminal_reason = ?');
385
- params.push(patch.terminalReason ?? null);
386
- }
387
- if ('errorCode' in patch) {
388
- updates.push('error_code = ?');
389
- params.push(patch.errorCode ?? null);
390
- }
391
- if ('errorCategory' in patch) {
392
- updates.push('error_category = ?');
393
- params.push(patch.errorCategory ?? null);
394
- }
395
- if ('errorMessage' in patch) {
396
- updates.push('error_message = ?');
397
- params.push(patch.errorMessage ?? null);
398
- }
399
-
400
- updates.push('updated_at_ms = ?');
401
- params.push(typeof patch.updatedAt === 'number' ? patch.updatedAt : Date.now());
402
- params.push(executionId);
403
-
404
- await this.withMutationLock(async () => {
405
- await this.client.run(`UPDATE runs SET ${updates.join(', ')} WHERE execution_id = ?`, params);
406
- });
407
- }
408
-
409
- async get(executionId: string): Promise<RunRecord | null> {
410
- await this.prepare();
411
- const row = await this.client.get<RunRow>(
412
- `
413
- SELECT
414
- execution_id,
415
- run_id,
416
- conversation_id,
417
- status,
418
- created_at_ms,
419
- updated_at_ms,
420
- step_index,
421
- started_at_ms,
422
- completed_at_ms,
423
- last_checkpoint_seq,
424
- terminal_reason,
425
- error_code,
426
- error_category,
427
- error_message
428
- FROM runs
429
- WHERE execution_id = ?
430
- `,
431
- [executionId]
432
- );
433
-
434
- return row ? mapRunRow(row) : null;
435
- }
436
-
437
- async listByConversation(
438
- conversationId: string,
439
- opts: ListRunsOptions = {}
440
- ): Promise<ListRunsResult> {
441
- await this.prepare();
442
- const limit = clampLimit(opts.limit);
443
- const params: unknown[] = [conversationId];
444
- const filters: string[] = ['conversation_id = ?'];
445
-
446
- if (opts.statuses && opts.statuses.length > 0) {
447
- const placeholders = opts.statuses.map(() => '?').join(', ');
448
- filters.push(`status IN (${placeholders})`);
449
- params.push(...opts.statuses);
450
- }
451
-
452
- const cursor = decodeCursor(opts.cursor);
453
- if (cursor) {
454
- filters.push('(updated_at_ms < ? OR (updated_at_ms = ? AND execution_id < ?))');
455
- params.push(cursor.updatedAt, cursor.updatedAt, cursor.executionId);
456
- }
457
-
458
- params.push(limit + 1);
459
-
460
- const rows = await this.client.all<RunRow>(
461
- `
462
- SELECT
463
- execution_id,
464
- run_id,
465
- conversation_id,
466
- status,
467
- created_at_ms,
468
- updated_at_ms,
469
- step_index,
470
- started_at_ms,
471
- completed_at_ms,
472
- last_checkpoint_seq,
473
- terminal_reason,
474
- error_code,
475
- error_category,
476
- error_message
477
- FROM runs
478
- WHERE ${filters.join(' AND ')}
479
- ORDER BY updated_at_ms DESC, execution_id DESC
480
- LIMIT ?
481
- `,
482
- params
483
- );
484
-
485
- const hasNext = rows.length > limit;
486
- const selected = hasNext ? rows.slice(0, limit) : rows;
487
- const items = selected.map(mapRunRow);
488
- const tail = items[items.length - 1];
489
-
490
- return {
491
- items,
492
- nextCursor: hasNext && tail ? encodeCursor(tail.updatedAt, tail.executionId) : undefined,
493
- };
494
- }
495
-
496
- async appendAutoSeq(event: Omit<CliEventEnvelope, 'seq'>): Promise<CliEventEnvelope> {
497
- await this.prepare();
498
-
499
- return this.withMutationLock(async () => {
500
- return this.client.transaction(async () => {
501
- const row = await this.client.get<{ max_seq: number | null }>(
502
- 'SELECT MAX(seq) AS max_seq FROM events WHERE conversation_id = ?',
503
- [event.conversationId]
504
- );
505
- const seq = ((row?.max_seq ?? 0) as number) + 1;
506
- const payloadJson = JSON.stringify(event.data ?? null);
507
-
508
- await this.client.run(
509
- `
510
- INSERT INTO events (
511
- conversation_id,
512
- execution_id,
513
- seq,
514
- event_type,
515
- payload_json,
516
- created_at_ms
517
- ) VALUES (?, ?, ?, ?, ?, ?)
518
- `,
519
- [
520
- event.conversationId,
521
- event.executionId,
522
- seq,
523
- event.eventType,
524
- payloadJson,
525
- event.createdAt,
526
- ]
527
- );
528
-
529
- return {
530
- ...event,
531
- seq,
532
- };
533
- });
534
- });
535
- }
536
-
537
- async append(event: CliEventEnvelope): Promise<void> {
538
- await this.prepare();
539
- await this.withMutationLock(async () => {
540
- await this.client.run(
541
- `
542
- INSERT INTO events (
543
- conversation_id,
544
- execution_id,
545
- seq,
546
- event_type,
547
- payload_json,
548
- created_at_ms
549
- ) VALUES (?, ?, ?, ?, ?, ?)
550
- `,
551
- [
552
- event.conversationId,
553
- event.executionId,
554
- event.seq,
555
- event.eventType,
556
- JSON.stringify(event.data ?? null),
557
- event.createdAt,
558
- ]
559
- );
560
- });
561
- }
562
-
563
- async listByRun(executionId: string): Promise<CliEventEnvelope[]> {
564
- await this.prepare();
565
- const rows = await this.client.all<EventRow>(
566
- `
567
- SELECT
568
- conversation_id,
569
- execution_id,
570
- seq,
571
- event_type,
572
- payload_json,
573
- created_at_ms
574
- FROM events
575
- WHERE execution_id = ?
576
- ORDER BY seq ASC
577
- `,
578
- [executionId]
579
- );
580
- return rows.map(mapEventRow);
581
- }
582
-
583
- async listEventsByConversation(
584
- conversationId: string,
585
- opts: ListConversationEventsOptions = {}
586
- ): Promise<CliEventEnvelope[]> {
587
- await this.prepare();
588
- const filters = ['conversation_id = ?'];
589
- const params: unknown[] = [conversationId];
590
-
591
- if (typeof opts.fromSeq === 'number' && opts.fromSeq > 0) {
592
- filters.push('seq >= ?');
593
- params.push(opts.fromSeq);
594
- }
595
-
596
- if (typeof opts.limit === 'number' && opts.limit > 0) {
597
- params.push(opts.limit);
598
- const rows = await this.client.all<EventRow>(
599
- `
600
- SELECT
601
- conversation_id,
602
- execution_id,
603
- seq,
604
- event_type,
605
- payload_json,
606
- created_at_ms
607
- FROM events
608
- WHERE ${filters.join(' AND ')}
609
- ORDER BY seq ASC
610
- LIMIT ?
611
- `,
612
- params
613
- );
614
- return rows.map(mapEventRow);
615
- }
616
-
617
- const rows = await this.client.all<EventRow>(
618
- `
619
- SELECT
620
- conversation_id,
621
- execution_id,
622
- seq,
623
- event_type,
624
- payload_json,
625
- created_at_ms
626
- FROM events
627
- WHERE ${filters.join(' AND ')}
628
- ORDER BY seq ASC
629
- `,
630
- params
631
- );
632
- return rows.map(mapEventRow);
633
- }
634
-
635
- async upsertFromEvent(event: CliEventEnvelope): Promise<void> {
636
- await this.prepare();
637
- const payload = extractMessagePayload(event);
638
- if (!payload) {
639
- return;
640
- }
641
-
642
- const { message, stepIndex } = payload;
643
- await this.withMutationLock(async () => {
644
- await this.client.transaction(async () => {
645
- await upsertMessageIntoHistory(this.client, event, message, stepIndex);
646
- await upsertMessageIntoContext(this.client, event, message, stepIndex);
647
- });
648
- });
649
- }
650
-
651
- async list(conversationId: string): Promise<Message[]> {
652
- await this.prepare();
653
- const rows = await this.client.all<MessageRow>(
654
- `
655
- SELECT
656
- message_id,
657
- role,
658
- type,
659
- content_json,
660
- reasoning_content,
661
- tool_call_id,
662
- tool_calls_json,
663
- usage_json,
664
- metadata_json,
665
- created_at_ms
666
- FROM messages
667
- WHERE conversation_id = ?
668
- ORDER BY seq ASC
669
- `,
670
- [conversationId]
671
- );
672
-
673
- return rows.map((row) => mapMessageRow(row));
674
- }
675
-
676
- async listContext(conversationId: string): Promise<Message[]> {
677
- await this.prepare();
678
- const rows = await this.client.all<MessageRow>(
679
- `
680
- SELECT
681
- message_id,
682
- role,
683
- type,
684
- content_json,
685
- reasoning_content,
686
- tool_call_id,
687
- tool_calls_json,
688
- usage_json,
689
- metadata_json,
690
- created_at_ms
691
- FROM context_messages
692
- WHERE conversation_id = ?
693
- ORDER BY seq ASC
694
- `,
695
- [conversationId]
696
- );
697
-
698
- return rows.map((row) => mapMessageRow(row));
699
- }
700
-
701
- async applyCompaction(input: {
702
- conversationId: string;
703
- executionId: string;
704
- stepIndex: number;
705
- removedMessageIds: string[];
706
- createdAt: number;
707
- }): Promise<void> {
708
- await this.prepare();
709
- const deduplicated = Array.from(
710
- new Set(input.removedMessageIds.filter((messageId) => messageId.trim().length > 0))
711
- );
712
- if (deduplicated.length === 0) {
713
- return;
714
- }
715
-
716
- await this.withMutationLock(async () => {
717
- await this.client.transaction(async () => {
718
- for (const removedMessageId of deduplicated) {
719
- await this.client.run(
720
- `
721
- INSERT OR IGNORE INTO compaction_dropped_messages (
722
- conversation_id,
723
- execution_id,
724
- step_index,
725
- removed_message_id,
726
- created_at_ms
727
- ) VALUES (?, ?, ?, ?, ?)
728
- `,
729
- [
730
- input.conversationId,
731
- input.executionId,
732
- input.stepIndex,
733
- removedMessageId,
734
- input.createdAt,
735
- ]
736
- );
737
- }
738
-
739
- for (const idsChunk of chunkStrings(deduplicated, 200)) {
740
- const placeholders = idsChunk.map(() => '?').join(', ');
741
- await this.client.run(
742
- `
743
- DELETE FROM context_messages
744
- WHERE conversation_id = ?
745
- AND message_id IN (${placeholders})
746
- `,
747
- [input.conversationId, ...idsChunk]
748
- );
749
- }
750
- });
751
- });
752
- }
753
-
754
- async listDroppedMessages(
755
- executionId: string,
756
- opts: { stepIndex?: number; limit?: number } = {}
757
- ): Promise<CompactionDroppedMessageRecord[]> {
758
- await this.prepare();
759
- const filters = ['execution_id = ?'];
760
- const params: unknown[] = [executionId];
761
-
762
- if (typeof opts.stepIndex === 'number' && Number.isFinite(opts.stepIndex)) {
763
- filters.push('step_index = ?');
764
- params.push(Math.floor(opts.stepIndex));
765
- }
766
-
767
- const effectiveLimit =
768
- typeof opts.limit === 'number' && Number.isFinite(opts.limit) && opts.limit > 0
769
- ? Math.floor(opts.limit)
770
- : 1000;
771
- params.push(effectiveLimit);
772
-
773
- const rows = await this.client.all<CompactionDroppedMessageRow>(
774
- `
775
- SELECT
776
- conversation_id,
777
- execution_id,
778
- step_index,
779
- removed_message_id,
780
- created_at_ms
781
- FROM compaction_dropped_messages
782
- WHERE ${filters.join(' AND ')}
783
- ORDER BY step_index ASC, id ASC
784
- LIMIT ?
785
- `,
786
- params
787
- );
788
-
789
- return rows.map((row) => ({
790
- conversationId: row.conversation_id,
791
- executionId: row.execution_id,
792
- stepIndex: row.step_index,
793
- removedMessageId: row.removed_message_id,
794
- createdAt: row.created_at_ms,
795
- }));
796
- }
797
-
798
- async appendRunLog(record: RunLogRecord): Promise<void> {
799
- await this.prepare();
800
- await this.withMutationLock(async () => {
801
- await this.client.run(
802
- `
803
- INSERT INTO run_logs (
804
- execution_id,
805
- conversation_id,
806
- step_index,
807
- level,
808
- code,
809
- source,
810
- message,
811
- error_json,
812
- context_json,
813
- data_json,
814
- created_at_ms
815
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
816
- `,
817
- [
818
- record.executionId,
819
- record.conversationId,
820
- record.stepIndex ?? null,
821
- record.level,
822
- record.code ?? null,
823
- record.source,
824
- record.message,
825
- record.error ? JSON.stringify(record.error) : null,
826
- record.context ? JSON.stringify(record.context) : null,
827
- record.data !== undefined ? JSON.stringify(record.data) : null,
828
- record.createdAt,
829
- ]
830
- );
831
- });
832
- }
833
-
834
- async listRunLogs(executionId: string, opts: ListRunLogsOptions = {}): Promise<RunLogRecord[]> {
835
- await this.prepare();
836
- const filters = ['execution_id = ?'];
837
- const params: unknown[] = [executionId];
838
-
839
- if (opts.level) {
840
- filters.push('level = ?');
841
- params.push(opts.level);
842
- }
843
-
844
- params.push(clampLimit(opts.limit));
845
-
846
- const rows = await this.client.all<RunLogRow>(
847
- `
848
- SELECT
849
- id,
850
- execution_id,
851
- conversation_id,
852
- step_index,
853
- level,
854
- code,
855
- source,
856
- message,
857
- error_json,
858
- context_json,
859
- data_json,
860
- created_at_ms
861
- FROM run_logs
862
- WHERE ${filters.join(' AND ')}
863
- ORDER BY created_at_ms ASC, id ASC
864
- LIMIT ?
865
- `,
866
- params
867
- );
868
-
869
- return rows.map(mapRunLogRow);
870
- }
871
-
872
- private async withMutationLock<T>(operation: () => Promise<T>): Promise<T> {
873
- const previous = this.mutationChain;
874
- let release: () => void = () => undefined;
875
- this.mutationChain = new Promise<void>((resolve) => {
876
- release = resolve;
877
- });
878
- await previous;
879
- try {
880
- return await operation();
881
- } finally {
882
- release();
883
- }
884
- }
885
- }
886
-
887
- export function createSqliteAgentAppStore(dbPath: string): SqliteAgentAppStore {
888
- return new SqliteAgentAppStore(dbPath);
889
- }
890
-
891
- async function upsertMessageIntoHistory(
892
- client: AgentAppSqliteClient,
893
- event: CliEventEnvelope,
894
- message: Message,
895
- stepIndex?: number
896
- ): Promise<void> {
897
- const serialized = serializeMessage(event, message, stepIndex);
898
- await client.run(
899
- `
900
- INSERT INTO messages (
901
- message_id,
902
- conversation_id,
903
- execution_id,
904
- seq,
905
- step_index,
906
- role,
907
- type,
908
- content_json,
909
- reasoning_content,
910
- tool_call_id,
911
- tool_calls_json,
912
- usage_json,
913
- metadata_json,
914
- created_at_ms
915
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
916
- ON CONFLICT(message_id) DO UPDATE SET
917
- conversation_id = excluded.conversation_id,
918
- execution_id = excluded.execution_id,
919
- seq = excluded.seq,
920
- step_index = excluded.step_index,
921
- role = excluded.role,
922
- type = excluded.type,
923
- content_json = excluded.content_json,
924
- reasoning_content = excluded.reasoning_content,
925
- tool_call_id = excluded.tool_call_id,
926
- tool_calls_json = excluded.tool_calls_json,
927
- usage_json = excluded.usage_json,
928
- metadata_json = excluded.metadata_json,
929
- created_at_ms = excluded.created_at_ms
930
- `,
931
- serialized
932
- );
933
- }
934
-
935
- async function upsertMessageIntoContext(
936
- client: AgentAppSqliteClient,
937
- event: CliEventEnvelope,
938
- message: Message,
939
- stepIndex?: number
940
- ): Promise<void> {
941
- const serialized = serializeMessage(event, message, stepIndex);
942
- await client.run(
943
- `
944
- INSERT INTO context_messages (
945
- message_id,
946
- conversation_id,
947
- execution_id,
948
- seq,
949
- step_index,
950
- role,
951
- type,
952
- content_json,
953
- reasoning_content,
954
- tool_call_id,
955
- tool_calls_json,
956
- usage_json,
957
- metadata_json,
958
- created_at_ms
959
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
960
- ON CONFLICT(conversation_id, message_id) DO UPDATE SET
961
- execution_id = excluded.execution_id,
962
- seq = excluded.seq,
963
- step_index = excluded.step_index,
964
- role = excluded.role,
965
- type = excluded.type,
966
- content_json = excluded.content_json,
967
- reasoning_content = excluded.reasoning_content,
968
- tool_call_id = excluded.tool_call_id,
969
- tool_calls_json = excluded.tool_calls_json,
970
- usage_json = excluded.usage_json,
971
- metadata_json = excluded.metadata_json,
972
- created_at_ms = excluded.created_at_ms
973
- `,
974
- serialized
975
- );
976
- }
977
-
978
- function serializeMessage(
979
- event: CliEventEnvelope,
980
- message: Message,
981
- stepIndex?: number
982
- ): unknown[] {
983
- return [
984
- message.messageId,
985
- event.conversationId,
986
- event.executionId,
987
- event.seq,
988
- stepIndex ?? null,
989
- message.role,
990
- message.type,
991
- JSON.stringify(message.content ?? null),
992
- message.reasoning_content ?? null,
993
- message.tool_call_id ?? null,
994
- message.tool_calls ? JSON.stringify(message.tool_calls) : null,
995
- message.usage ? JSON.stringify(message.usage) : null,
996
- message.metadata ? JSON.stringify(message.metadata) : null,
997
- message.timestamp,
998
- ];
999
- }
1000
-
1001
- function mapMessageRow(row: MessageRow): Message {
1002
- return {
1003
- messageId: row.message_id,
1004
- role: row.role,
1005
- type: row.type,
1006
- content: parseJsonOrDefault(row.content_json, ''),
1007
- reasoning_content: row.reasoning_content ?? undefined,
1008
- tool_call_id: row.tool_call_id ?? undefined,
1009
- tool_calls: row.tool_calls_json
1010
- ? (parseJsonOrDefault(row.tool_calls_json, undefined) as Message['tool_calls'])
1011
- : undefined,
1012
- usage: row.usage_json
1013
- ? (parseJsonOrDefault(row.usage_json, undefined) as Message['usage'])
1014
- : undefined,
1015
- metadata: row.metadata_json
1016
- ? (parseJsonOrDefault(row.metadata_json, undefined) as Message['metadata'])
1017
- : undefined,
1018
- timestamp: row.created_at_ms,
1019
- };
1020
- }
1021
-
1022
- function chunkStrings(items: string[], chunkSize: number): string[][] {
1023
- const chunks: string[][] = [];
1024
- for (let index = 0; index < items.length; index += chunkSize) {
1025
- chunks.push(items.slice(index, index + chunkSize));
1026
- }
1027
- return chunks;
1028
- }
1029
-
1030
- function mapRunRow(row: RunRow): RunRecord {
1031
- return {
1032
- executionId: row.execution_id,
1033
- runId: row.run_id,
1034
- conversationId: row.conversation_id,
1035
- status: row.status,
1036
- createdAt: row.created_at_ms,
1037
- updatedAt: row.updated_at_ms,
1038
- stepIndex: row.step_index,
1039
- startedAt: row.started_at_ms ?? undefined,
1040
- completedAt: row.completed_at_ms ?? undefined,
1041
- lastCheckpointSeq: row.last_checkpoint_seq ?? undefined,
1042
- terminalReason: row.terminal_reason ?? undefined,
1043
- errorCode: row.error_code ?? undefined,
1044
- errorCategory: row.error_category ?? undefined,
1045
- errorMessage: row.error_message ?? undefined,
1046
- };
1047
- }
1048
-
1049
- function mapEventRow(row: EventRow): CliEventEnvelope {
1050
- return {
1051
- conversationId: row.conversation_id,
1052
- executionId: row.execution_id,
1053
- seq: row.seq,
1054
- eventType: row.event_type,
1055
- data: parseJsonOrDefault(row.payload_json, null),
1056
- createdAt: row.created_at_ms,
1057
- };
1058
- }
1059
-
1060
- function mapRunLogRow(row: RunLogRow): RunLogRecord {
1061
- return {
1062
- id: row.id,
1063
- executionId: row.execution_id,
1064
- conversationId: row.conversation_id,
1065
- stepIndex: row.step_index ?? undefined,
1066
- level: row.level,
1067
- code: row.code ?? undefined,
1068
- source: row.source,
1069
- message: row.message,
1070
- error: row.error_json
1071
- ? (parseJsonOrDefault(row.error_json, undefined) as RunLogRecord['error'])
1072
- : undefined,
1073
- context: row.context_json
1074
- ? (parseJsonOrDefault(row.context_json, undefined) as RunLogRecord['context'])
1075
- : undefined,
1076
- data: row.data_json ? parseJsonOrDefault(row.data_json, undefined) : undefined,
1077
- createdAt: row.created_at_ms,
1078
- };
1079
- }
1080
-
1081
- function clampLimit(limit?: number): number {
1082
- if (!Number.isFinite(limit)) {
1083
- return 20;
1084
- }
1085
- return Math.min(100, Math.max(1, Math.floor(Number(limit))));
1086
- }
1087
-
1088
- function encodeCursor(updatedAt: number, executionId: string): string {
1089
- return `${updatedAt}:${executionId}`;
1090
- }
1091
-
1092
- function decodeCursor(cursor?: string): CursorToken | null {
1093
- if (!cursor) {
1094
- return null;
1095
- }
1096
- const splitIndex = cursor.indexOf(':');
1097
- if (splitIndex <= 0 || splitIndex >= cursor.length - 1) {
1098
- return null;
1099
- }
1100
- const updatedAtRaw = cursor.slice(0, splitIndex);
1101
- const executionId = cursor.slice(splitIndex + 1);
1102
- const updatedAt = Number(updatedAtRaw);
1103
- if (!Number.isFinite(updatedAt) || executionId.length === 0) {
1104
- return null;
1105
- }
1106
- return {
1107
- updatedAt,
1108
- executionId,
1109
- };
1110
- }
1111
-
1112
- function parseJsonOrDefault<T>(raw: string, defaultValue: T): T {
1113
- try {
1114
- return JSON.parse(raw) as T;
1115
- } catch {
1116
- return defaultValue;
1117
- }
1118
- }
1119
-
1120
- function isRecord(value: unknown): value is Record<string, unknown> {
1121
- return typeof value === 'object' && value !== null;
1122
- }
1123
-
1124
- function isMessage(value: unknown): value is Message {
1125
- if (!isRecord(value)) {
1126
- return false;
1127
- }
1128
- return (
1129
- typeof value.messageId === 'string' &&
1130
- typeof value.role === 'string' &&
1131
- typeof value.type === 'string' &&
1132
- typeof value.timestamp === 'number' &&
1133
- 'content' in value
1134
- );
1135
- }
1136
-
1137
- function extractMessagePayload(event: CliEventEnvelope): MessageEventPayload | null {
1138
- if (event.eventType !== 'user_message' && event.eventType !== 'assistant_message') {
1139
- return null;
1140
- }
1141
-
1142
- if (isMessage(event.data)) {
1143
- return { message: event.data };
1144
- }
1145
-
1146
- if (!isRecord(event.data) || !isMessage(event.data.message)) {
1147
- return null;
1148
- }
1149
-
1150
- const stepIndex = event.data.stepIndex;
1151
- return {
1152
- message: event.data.message,
1153
- stepIndex: typeof stepIndex === 'number' ? stepIndex : undefined,
1154
- };
1155
- }
1156
-
1157
- async function runAppMigrations(client: AgentAppSqliteClient): Promise<void> {
1158
- await client.exec(`
1159
- CREATE TABLE IF NOT EXISTS agent_v4_schema_migrations (
1160
- version INTEGER PRIMARY KEY,
1161
- applied_at_ms INTEGER NOT NULL
1162
- );
1163
- `);
1164
-
1165
- const rows = await client.all<{ version: number }>(
1166
- 'SELECT version FROM agent_v4_schema_migrations ORDER BY version ASC'
1167
- );
1168
- const applied = new Set(rows.map((row) => row.version));
1169
-
1170
- for (const migration of APP_MIGRATIONS) {
1171
- if (applied.has(migration.version)) {
1172
- continue;
1173
- }
1174
- await client.transaction(async () => {
1175
- await client.exec(migration.sql);
1176
- await client.run(
1177
- 'INSERT INTO agent_v4_schema_migrations(version, applied_at_ms) VALUES(?, ?)',
1178
- [migration.version, Date.now()]
1179
- );
1180
- });
1181
- }
1182
- }