@xopcai/xopc 0.0.113 → 0.0.114

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 (327) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CBlklyNr.js → agent-avatar-dicebear-Fp-p7bP1.js} +1 -1
  4. package/dist/gateway/static/root/assets/agent-browser-settings-page-CWh7trjd.js +6 -0
  5. package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-kC8OuLoj.js +1 -0
  6. package/dist/gateway/static/root/assets/agents-DJWG26Si.js +71 -0
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-28E_WfMe.js → app-management-settings-panel-v24i25Oj.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-Do1z0XgJ.js → appearance-settings-ycbdJRuZ.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-0V3DXZ7J.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-BAFlsov_.js → archive-plugin-CJzSADJo.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-V3qGPC3x.js → attachment-load-BTAB4zGS.js} +1 -1
  12. package/dist/gateway/static/root/assets/{binary-plugins-DT8NvA6W.js → binary-plugins-DXR1-mct.js} +1 -1
  13. package/dist/gateway/static/root/assets/{block-editor-CdLMEcHd.js → block-editor-CzQri9h2.js} +44 -44
  14. package/dist/gateway/static/root/assets/channels-settings-CIKOkYdO.js +1 -0
  15. package/dist/gateway/static/root/assets/{config-api-Bf5mjpu7.js → config-api-DRqjEvAx.js} +1 -1
  16. package/dist/gateway/static/root/assets/connectors-settings-ClrDS5jH.js +2 -0
  17. package/dist/gateway/static/root/assets/{cron-api--pAB_rps.js → cron-api-BXaZXv1o.js} +1 -1
  18. package/dist/gateway/static/root/assets/cron-page-Chi_4u4P.js +3 -0
  19. package/dist/gateway/static/root/assets/dreaming-settings-B0_rs2tj.js +1 -0
  20. package/dist/gateway/static/root/assets/{extension-debug-page-BGhE7msg.js → extension-debug-page-DSkqMYo7.js} +1 -1
  21. package/dist/gateway/static/root/assets/{extension-page-CvpI45WG.js → extension-page-h2dGDbMN.js} +1 -1
  22. package/dist/gateway/static/root/assets/{extension-settings-page-DAmR5FUe.js → extension-settings-page-hN99RhOi.js} +1 -1
  23. package/dist/gateway/static/root/assets/{fetch-NZmjSXLl.js → fetch-D9QqUtzZ.js} +1 -1
  24. package/dist/gateway/static/root/assets/{format-interval-label-qhth3BMV.js → format-interval-label-D6E687rG.js} +1 -1
  25. package/dist/gateway/static/root/assets/{gateway-config-api-CaXBt-9R.js → gateway-config-api-CLt_SKTC.js} +1 -1
  26. package/dist/gateway/static/root/assets/{gateway-settings-DphpbLBc.js → gateway-settings-1PDi4lI0.js} +1 -1
  27. package/dist/gateway/static/root/assets/{gateway-startup-retry-Be1omjh3.js → gateway-startup-retry-N7Z_sz7p.js} +1 -1
  28. package/dist/gateway/static/root/assets/goal-detail-page-D_wwXL-t.js +1 -0
  29. package/dist/gateway/static/root/assets/goals-page-DZ2toZ8y.js +2 -0
  30. package/dist/gateway/static/root/assets/{goals-settings-ceEBjnfc.js → goals-settings-LFlwtIKE.js} +1 -1
  31. package/dist/gateway/static/root/assets/{heartbeat-config-api-BzO6G4fD.js → heartbeat-config-api-DGPadTw-.js} +1 -1
  32. package/dist/gateway/static/root/assets/{heartbeat-settings-DCST9-du.js → heartbeat-settings-BHHAs8ZX.js} +1 -1
  33. package/dist/gateway/static/root/assets/index-DefIdW9q.js +122 -0
  34. package/dist/gateway/static/root/assets/index-DzmWBkq-.css +1 -0
  35. package/dist/gateway/static/root/assets/{interval-presets-DJmshV8n.js → interval-presets-CEklPQ_r.js} +1 -1
  36. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-9AUUlQ5Q.js → keyboard-shortcuts-settings-Ce_aQ8Iv.js} +1 -1
  37. package/dist/gateway/static/root/assets/logs-page-j_D2QTuQ.js +2 -0
  38. package/dist/gateway/static/root/assets/{markdown-split-CYYELqAr.js → markdown-split-BMz3xPXO.js} +1 -1
  39. package/dist/gateway/static/root/assets/{media-plugins-BEcMR2M8.js → media-plugins-BalOSoz9.js} +1 -1
  40. package/dist/gateway/static/root/assets/messages-BN_WiUg0.js +3 -0
  41. package/dist/gateway/static/root/assets/models-hub-panel-CMH_TmZz.js +2 -0
  42. package/dist/gateway/static/root/assets/note-detail-page-O18BrQPq.js +2 -0
  43. package/dist/gateway/static/root/assets/{note-image-lightbox-DNAoPcmm.js → note-image-lightbox-C5D1Q5mY.js} +1 -1
  44. package/dist/gateway/static/root/assets/notes-page-B_ZYCmY9.js +1 -0
  45. package/dist/gateway/static/root/assets/{preview-open-alternatives-BPLz0AIv.js → preview-open-alternatives-CYFR5U9l.js} +1 -1
  46. package/dist/gateway/static/root/assets/remote-access-hub-CwKgWixY.js +1 -0
  47. package/dist/gateway/static/root/assets/{save-bar-controls-CrWwWRVK.js → save-bar-controls-BQ79Z5IP.js} +1 -1
  48. package/dist/gateway/static/root/assets/{schedule-field-CF2sadvN.js → schedule-field-Bgk6Emue.js} +1 -1
  49. package/dist/gateway/static/root/assets/{schema-form-Di5cKjYE.js → schema-form-DzS36TMa.js} +1 -1
  50. package/dist/gateway/static/root/assets/sessions-page-C4fcD-7B.js +1 -0
  51. package/dist/gateway/static/root/assets/settings-advanced-gate-Ad2OJ86w.js +1 -0
  52. package/dist/gateway/static/root/assets/{settings-collapsible-section-Chh282jW.js → settings-collapsible-section-CdjFnSAy.js} +1 -1
  53. package/dist/gateway/static/root/assets/{settings-form-section-Dq-83cQd.js → settings-form-section-DZLy_exu.js} +1 -1
  54. package/dist/gateway/static/root/assets/settings-page-D2BMY5wo.js +1 -0
  55. package/dist/gateway/static/root/assets/setup-status-panel-aWwxl_E1.js +1 -0
  56. package/dist/gateway/static/root/assets/{share-preview-page-0FXYnSUA.js → share-preview-page-_qRDr4g_.js} +1 -1
  57. package/dist/gateway/static/root/assets/shares-settings-DUE83uIf.js +1 -0
  58. package/dist/gateway/static/root/assets/skill-reload-api-mWKJcrog.js +1 -0
  59. package/dist/gateway/static/root/assets/skills-page-0Sx1Q58n.js +2 -0
  60. package/dist/gateway/static/root/assets/{system-settings-panel-W1pTcojB.js → system-settings-panel-hqaBF5aG.js} +1 -1
  61. package/dist/gateway/static/root/assets/{use-agent-defaults-form-BVRvkK7m.js → use-agent-defaults-form-zbVIQLOA.js} +1 -1
  62. package/dist/gateway/static/root/assets/{use-channel-catalog-CgJibfMM.js → use-channel-catalog-CbXq97rT.js} +1 -1
  63. package/dist/gateway/static/root/assets/{use-settings-tab-guard-Bw_qkRQE.js → use-settings-tab-guard-DwS3drWK.js} +1 -1
  64. package/dist/gateway/static/root/assets/voice-api-key-field-D6HR0hR2.js +1 -0
  65. package/dist/gateway/static/root/assets/{voice-player-store-C7lziaAx.js → voice-player-store-DSuOd9zy.js} +1 -1
  66. package/dist/gateway/static/root/assets/workflow-page.utils-C0Uq3xyq.js +1 -0
  67. package/dist/gateway/static/root/assets/workflows-page-DW0fmWhQ.js +18 -0
  68. package/dist/gateway/static/root/index.html +5 -5
  69. package/dist/package.js +1 -1
  70. package/dist/src/agent/agent-manager.d.ts +8 -0
  71. package/dist/src/agent/agent-manager.js +57 -22
  72. package/dist/src/agent/agent-manager.js.map +1 -1
  73. package/dist/src/agent/bootstrap/project-agents-context.d.ts +2 -0
  74. package/dist/src/agent/bootstrap/project-agents-context.js +32 -0
  75. package/dist/src/agent/bootstrap/project-agents-context.js.map +1 -0
  76. package/dist/src/agent/goals/persistent-goal-service.js +2 -4
  77. package/dist/src/agent/goals/persistent-goal-service.js.map +1 -1
  78. package/dist/src/agent/inbound/inbound-loop.js +5 -1
  79. package/dist/src/agent/inbound/inbound-loop.js.map +1 -1
  80. package/dist/src/agent/inbound/turn-dispatcher.d.ts +2 -2
  81. package/dist/src/agent/inbound/turn-dispatcher.js +2 -2
  82. package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
  83. package/dist/src/agent/mcp/bundle-mcp-materialize.d.ts +27 -0
  84. package/dist/src/agent/mcp/bundle-mcp-materialize.js +49 -1
  85. package/dist/src/agent/mcp/bundle-mcp-materialize.js.map +1 -1
  86. package/dist/src/agent/mcp/bundle-mcp-runtime.js +78 -3
  87. package/dist/src/agent/mcp/bundle-mcp-runtime.js.map +1 -1
  88. package/dist/src/agent/mcp/bundle-mcp-types.d.ts +19 -0
  89. package/dist/src/agent/service/btw-query.js +11 -3
  90. package/dist/src/agent/service/btw-query.js.map +1 -1
  91. package/dist/src/agent/service/parse-outbound-session-key.js +13 -8
  92. package/dist/src/agent/service/parse-outbound-session-key.js.map +1 -1
  93. package/dist/src/agent/service/process-direct-one-shot.d.ts +2 -2
  94. package/dist/src/agent/service/process-direct-one-shot.js +1 -1
  95. package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
  96. package/dist/src/agent/service/process-direct-streaming.d.ts +2 -2
  97. package/dist/src/agent/service/process-direct-streaming.js +1 -1
  98. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  99. package/dist/src/agent/service.d.ts +1 -1
  100. package/dist/src/agent/service.js +9 -5
  101. package/dist/src/agent/service.js.map +1 -1
  102. package/dist/src/agent/service.types.d.ts +5 -0
  103. package/dist/src/agent/skills/filesystem-watcher.js +4 -3
  104. package/dist/src/agent/skills/filesystem-watcher.js.map +1 -1
  105. package/dist/src/agent/skills/index.js +2 -1
  106. package/dist/src/agent/skills/index.js.map +1 -1
  107. package/dist/src/agent/skills/skill-manage-ops.js +2 -1
  108. package/dist/src/agent/skills/skill-manage-ops.js.map +1 -1
  109. package/dist/src/agent/skills/types.d.ts +1 -1
  110. package/dist/src/agent/skills/watcher.js +2 -5
  111. package/dist/src/agent/skills/watcher.js.map +1 -1
  112. package/dist/src/agent/skills/workspace-skills-dir.d.ts +1 -0
  113. package/dist/src/agent/skills/workspace-skills-dir.js +11 -0
  114. package/dist/src/agent/skills/workspace-skills-dir.js.map +1 -0
  115. package/dist/src/agent/tool-manuals/browser.d.ts +1 -1
  116. package/dist/src/agent/tool-manuals/browser.js +62 -3
  117. package/dist/src/agent/tool-manuals/browser.js.map +1 -1
  118. package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +4 -1
  119. package/dist/src/agent/tools/browser/tool/browser-use-tool.js +13 -4
  120. package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
  121. package/dist/src/agent/tools/browser/tool/schemas.d.ts +0 -2
  122. package/dist/src/agent/tools/browser/tool/schemas.js +1 -2
  123. package/dist/src/agent/tools/browser/tool/schemas.js.map +1 -1
  124. package/dist/src/agent/tools/factory.js +1 -10
  125. package/dist/src/agent/tools/factory.js.map +1 -1
  126. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  127. package/dist/src/agent/tools/skill-manage-tool.js.map +1 -1
  128. package/dist/src/agent/workflow/subagent-runner.js +18 -1
  129. package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
  130. package/dist/src/browser/actions/extension-registry-bridge.js +91 -7
  131. package/dist/src/browser/actions/extension-registry-bridge.js.map +1 -1
  132. package/dist/src/browser/actions/registry.js +383 -7
  133. package/dist/src/browser/actions/registry.js.map +1 -1
  134. package/dist/src/browser/actions/types.d.ts +11 -3
  135. package/dist/src/browser/index.js +2 -2
  136. package/dist/src/browser/pipeline/output.d.ts +18 -16
  137. package/dist/src/browser/pipeline/output.js +28 -20
  138. package/dist/src/browser/pipeline/output.js.map +1 -1
  139. package/dist/src/browser/pipeline/runner.d.ts +7 -14
  140. package/dist/src/browser/pipeline/runner.js +349 -102
  141. package/dist/src/browser/pipeline/runner.js.map +1 -1
  142. package/dist/src/browser/pipeline/schema.d.ts +1 -0
  143. package/dist/src/browser/pipeline/schema.js +35 -58
  144. package/dist/src/browser/pipeline/schema.js.map +1 -1
  145. package/dist/src/browser/pipeline/source.d.ts +2 -0
  146. package/dist/src/browser/pipeline/source.js +10 -1
  147. package/dist/src/browser/pipeline/source.js.map +1 -1
  148. package/dist/src/browser/pipeline/template.d.ts +10 -2
  149. package/dist/src/browser/pipeline/template.js +50 -8
  150. package/dist/src/browser/pipeline/template.js.map +1 -1
  151. package/dist/src/chat-commands/builtins/config.js +3 -5
  152. package/dist/src/chat-commands/builtins/config.js.map +1 -1
  153. package/dist/src/chat-commands/context.d.ts +5 -0
  154. package/dist/src/chat-commands/context.js +18 -9
  155. package/dist/src/chat-commands/context.js.map +1 -1
  156. package/dist/src/chat-commands/index.d.ts +1 -1
  157. package/dist/src/chat-commands/index.js +2 -2
  158. package/dist/src/chat-commands/index.js.map +1 -1
  159. package/dist/src/chat-commands/processor.js +22 -21
  160. package/dist/src/chat-commands/processor.js.map +1 -1
  161. package/dist/src/chat-commands/session-key.d.ts +3 -15
  162. package/dist/src/chat-commands/session-key.js +3 -49
  163. package/dist/src/chat-commands/session-key.js.map +1 -1
  164. package/dist/src/chat-commands/types.d.ts +4 -0
  165. package/dist/src/cli/commands/browser-cli-helpers.js +11 -5
  166. package/dist/src/cli/commands/browser-cli-helpers.js.map +1 -1
  167. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  168. package/dist/src/cli/commands/doctor/checks/session-integrity.js +8 -8
  169. package/dist/src/cli/commands/doctor/checks/session-integrity.js.map +1 -1
  170. package/dist/src/config/rules.js +5 -0
  171. package/dist/src/config/rules.js.map +1 -1
  172. package/dist/src/connectors/builtin-catalog.js +180 -1
  173. package/dist/src/connectors/builtin-catalog.js.map +1 -1
  174. package/dist/src/connectors/health.js +18 -9
  175. package/dist/src/connectors/health.js.map +1 -1
  176. package/dist/src/connectors/types.d.ts +19 -0
  177. package/dist/src/connectors/usage.js +12 -4
  178. package/dist/src/connectors/usage.js.map +1 -1
  179. package/dist/src/extensions/types/tui.d.ts +2 -0
  180. package/dist/src/gateway/heartbeat/service.js +13 -1
  181. package/dist/src/gateway/heartbeat/service.js.map +1 -1
  182. package/dist/src/gateway/hono/app.js +13 -4
  183. package/dist/src/gateway/hono/app.js.map +1 -1
  184. package/dist/src/gateway/hono/oauth-async.js +1 -1
  185. package/dist/src/gateway/hono/routes/agent-stream.js +6 -6
  186. package/dist/src/gateway/hono/routes/agent-stream.js.map +1 -1
  187. package/dist/src/gateway/hono/routes/config-patch/gateway.d.ts +1 -1
  188. package/dist/src/gateway/hono/routes/config-patch/gateway.js +6 -0
  189. package/dist/src/gateway/hono/routes/config-patch/gateway.js.map +1 -1
  190. package/dist/src/gateway/hono/routes/goals.js +16 -3
  191. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  192. package/dist/src/gateway/hono/routes/logs.js +1 -0
  193. package/dist/src/gateway/hono/routes/logs.js.map +1 -1
  194. package/dist/src/gateway/hono/routes/mcp.js +27 -8
  195. package/dist/src/gateway/hono/routes/mcp.js.map +1 -1
  196. package/dist/src/gateway/hono/routes/notes.js +14 -2
  197. package/dist/src/gateway/hono/routes/notes.js.map +1 -1
  198. package/dist/src/gateway/hono/routes/sessions.js +62 -4
  199. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  200. package/dist/src/gateway/hono/routes/workspace.js +3 -66
  201. package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
  202. package/dist/src/gateway/hono/sse.d.ts +2 -2
  203. package/dist/src/gateway/hono/sse.js +7 -15
  204. package/dist/src/gateway/hono/sse.js.map +1 -1
  205. package/dist/src/gateway/resolve-webchat-session-key.d.ts +2 -6
  206. package/dist/src/gateway/resolve-webchat-session-key.js +5 -31
  207. package/dist/src/gateway/resolve-webchat-session-key.js.map +1 -1
  208. package/dist/src/gateway/service/agent-runner.d.ts +2 -3
  209. package/dist/src/gateway/service/agent-runner.js +9 -22
  210. package/dist/src/gateway/service/agent-runner.js.map +1 -1
  211. package/dist/src/gateway/service/run-gateway-agent.js +9 -7
  212. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  213. package/dist/src/gateway/service/sessions-api.d.ts +9 -0
  214. package/dist/src/gateway/service/sessions-api.js +11 -0
  215. package/dist/src/gateway/service/sessions-api.js.map +1 -1
  216. package/dist/src/gateway/service.d.ts +1 -1
  217. package/dist/src/gateway/service.js +19 -5
  218. package/dist/src/gateway/service.js.map +1 -1
  219. package/dist/src/gateway/workspace-file-search.d.ts +9 -0
  220. package/dist/src/gateway/workspace-file-search.js +76 -0
  221. package/dist/src/gateway/workspace-file-search.js.map +1 -0
  222. package/dist/src/goals/goal-notifications.d.ts +2 -0
  223. package/dist/src/goals/goal-notifications.js +16 -11
  224. package/dist/src/goals/goal-notifications.js.map +1 -1
  225. package/dist/src/goals/goal-service.js +1 -6
  226. package/dist/src/goals/goal-service.js.map +1 -1
  227. package/dist/src/project-trust/trust-store.js +2 -0
  228. package/dist/src/project-trust/trust-store.js.map +1 -1
  229. package/dist/src/session/index.d.ts +1 -1
  230. package/dist/src/session/index.js +2 -2
  231. package/dist/src/session/init-session-turn.js +6 -9
  232. package/dist/src/session/init-session-turn.js.map +1 -1
  233. package/dist/src/session/manager.d.ts +5 -1
  234. package/dist/src/session/manager.js +5 -2
  235. package/dist/src/session/manager.js.map +1 -1
  236. package/dist/src/session/reset-type.d.ts +0 -2
  237. package/dist/src/session/reset-type.js +3 -9
  238. package/dist/src/session/reset-type.js.map +1 -1
  239. package/dist/src/session/resolve-session.js +9 -20
  240. package/dist/src/session/resolve-session.js.map +1 -1
  241. package/dist/src/session/store.d.ts +11 -3
  242. package/dist/src/session/store.js +29 -13
  243. package/dist/src/session/store.js.map +1 -1
  244. package/dist/src/session/types.d.ts +2 -4
  245. package/dist/src/session/types.js.map +1 -1
  246. package/dist/src/storage/sqlite/index.d.ts +2 -2
  247. package/dist/src/storage/sqlite/index.js +3 -3
  248. package/dist/src/storage/sqlite/migrations/010_session_id_identity.sql +30 -0
  249. package/dist/src/storage/sqlite/migrations/runner.d.ts +2 -2
  250. package/dist/src/storage/sqlite/migrations/runner.js +4 -4
  251. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  252. package/dist/src/storage/sqlite/migrations/runner.ts +2 -2
  253. package/dist/src/storage/sqlite/row-mappers.d.ts +4 -4
  254. package/dist/src/storage/sqlite/row-mappers.js +11 -14
  255. package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
  256. package/dist/src/storage/sqlite/schema.js +3 -3
  257. package/dist/src/storage/sqlite/schema.js.map +1 -1
  258. package/dist/src/storage/sqlite/schema.sql +37 -10
  259. package/dist/src/storage/sqlite/session-metadata.d.ts +2 -7
  260. package/dist/src/storage/sqlite/session-metadata.js +18 -72
  261. package/dist/src/storage/sqlite/session-metadata.js.map +1 -1
  262. package/dist/src/storage/sqlite/session-repository.d.ts +6 -5
  263. package/dist/src/storage/sqlite/session-repository.js +34 -40
  264. package/dist/src/storage/sqlite/session-repository.js.map +1 -1
  265. package/dist/src/storage/sqlite/transcript-repository.d.ts +2 -2
  266. package/dist/src/storage/sqlite/transcript-repository.js +52 -52
  267. package/dist/src/storage/sqlite/transcript-repository.js.map +1 -1
  268. package/dist/src/tui/backends/embedded-backend.d.ts +11 -4
  269. package/dist/src/tui/backends/embedded-backend.js +27 -1
  270. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  271. package/dist/src/tui/backends/gateway-sse-backend.d.ts +4 -1
  272. package/dist/src/tui/backends/gateway-sse-backend.js +21 -2
  273. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  274. package/dist/src/tui/extension-host/autocomplete.js +13 -10
  275. package/dist/src/tui/extension-host/autocomplete.js.map +1 -1
  276. package/dist/src/tui/extension-host/runtime.d.ts +7 -0
  277. package/dist/src/tui/extension-host/runtime.js +6 -4
  278. package/dist/src/tui/extension-host/runtime.js.map +1 -1
  279. package/dist/src/tui/tui-backend.d.ts +9 -0
  280. package/dist/src/tui/tui-commands.js +85 -6
  281. package/dist/src/tui/tui-commands.js.map +1 -1
  282. package/dist/src/tui/tui-file-autocomplete.d.ts +5 -0
  283. package/dist/src/tui/tui-file-autocomplete.js +26 -0
  284. package/dist/src/tui/tui-file-autocomplete.js.map +1 -0
  285. package/dist/src/tui/tui-picker-overlay.js +1 -1
  286. package/dist/src/tui/tui.js +29 -11
  287. package/dist/src/tui/tui.js.map +1 -1
  288. package/dist/src/utils/logger/context.d.ts +2 -2
  289. package/dist/src/utils/logger/context.js +2 -1
  290. package/dist/src/utils/logger/context.js.map +1 -1
  291. package/dist/src/utils/logger/log-store.js +1 -0
  292. package/dist/src/utils/logger/log-store.js.map +1 -1
  293. package/dist/src/utils/logger/pino-record.js +3 -0
  294. package/dist/src/utils/logger/pino-record.js.map +1 -1
  295. package/dist/src/utils/logger/types.d.ts +5 -0
  296. package/dist/src/utils/logger/types.js.map +1 -1
  297. package/dist/src/workflows/service/workflow-session-bridge.js +13 -1
  298. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  299. package/package.json +1 -1
  300. package/dist/gateway/static/root/assets/agent-browser-settings-page-rGbKc2Hh.js +0 -6
  301. package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-CtwVbjOA.js +0 -1
  302. package/dist/gateway/static/root/assets/agents-CCBmGcwc.js +0 -71
  303. package/dist/gateway/static/root/assets/apps-page-xwCsJS15.js +0 -1
  304. package/dist/gateway/static/root/assets/channels-settings-C044DcYk.js +0 -1
  305. package/dist/gateway/static/root/assets/connectors-settings-8VEWUOTj.js +0 -2
  306. package/dist/gateway/static/root/assets/cron-page-DqmNGNOy.js +0 -3
  307. package/dist/gateway/static/root/assets/dreaming-settings-6UZE1FSK.js +0 -1
  308. package/dist/gateway/static/root/assets/goal-detail-page-bv0VRDaf.js +0 -1
  309. package/dist/gateway/static/root/assets/goals-page-1Ywnt4Cb.js +0 -2
  310. package/dist/gateway/static/root/assets/index-Cxm6xsps.js +0 -122
  311. package/dist/gateway/static/root/assets/index-b_R4tKqt.css +0 -1
  312. package/dist/gateway/static/root/assets/logs-page-B_wrxhee.js +0 -2
  313. package/dist/gateway/static/root/assets/messages-CkT-lcgP.js +0 -3
  314. package/dist/gateway/static/root/assets/models-hub-panel-D0JDSbNu.js +0 -2
  315. package/dist/gateway/static/root/assets/note-detail-page-DpFV-EO6.js +0 -2
  316. package/dist/gateway/static/root/assets/notes-page-CdkjTch8.js +0 -1
  317. package/dist/gateway/static/root/assets/remote-access-hub-DSYVAi96.js +0 -1
  318. package/dist/gateway/static/root/assets/sessions-page-CenkcVjF.js +0 -1
  319. package/dist/gateway/static/root/assets/settings-advanced-gate-D9sva86V.js +0 -1
  320. package/dist/gateway/static/root/assets/settings-page-DL35U0x0.js +0 -1
  321. package/dist/gateway/static/root/assets/setup-status-panel-Ctwbp9Er.js +0 -1
  322. package/dist/gateway/static/root/assets/shares-settings-DIM3JNsr.js +0 -1
  323. package/dist/gateway/static/root/assets/skill-reload-api-DAlNaNzL.js +0 -1
  324. package/dist/gateway/static/root/assets/skills-page-CLrHVzAt.js +0 -2
  325. package/dist/gateway/static/root/assets/voice-api-key-field-vYAO71Gn.js +0 -1
  326. package/dist/gateway/static/root/assets/workflow-page.utils-sgHjOXOm.js +0 -1
  327. package/dist/gateway/static/root/assets/workflows-page-DYyOTmFx.js +0 -18
@@ -1,11 +1,12 @@
1
1
  import type { DatabaseSync } from 'node:sqlite';
2
2
  import type { SessionListQuery, SessionMetadata, PaginatedResult } from '../../session/types.js';
3
+ import { type SessionMetadataSeed } from './session-metadata.js';
3
4
  import { buildGlobalSessionStats } from './row-mappers.js';
4
- export declare function ensureSessionInTransaction(db: DatabaseSync, sessionKey: string, cwd: string): SessionMetadata;
5
- export declare function ensureSessionRecord(sessionKey: string, cwd: string): SessionMetadata;
6
- export declare function readCurrentTranscriptId(db: DatabaseSync, sessionKey: string): string | null;
5
+ export declare function ensureSessionInTransaction(db: DatabaseSync, sessionKey: string, cwd: string, seed?: SessionMetadataSeed): SessionMetadata;
6
+ export declare function ensureSessionRecord(sessionKey: string, cwd: string, seed?: SessionMetadataSeed): SessionMetadata;
7
+ export declare function readCurrentSessionId(db: DatabaseSync, sessionKey: string): string | null;
7
8
  export declare function getSessionMetadata(sessionKey: string): SessionMetadata | null;
8
- export declare function getCurrentTranscriptId(sessionKey: string): string | null;
9
+ export declare function getCurrentSessionId(sessionKey: string): string | null;
9
10
  export declare function listSessionMetadata(query?: SessionListQuery): PaginatedResult<SessionMetadata>;
10
11
  export declare function patchSessionMetadata(sessionKey: string, updates: Partial<SessionMetadata>): SessionMetadata;
11
12
  export declare function updateSessionStats(sessionKey: string, stats: {
@@ -24,6 +25,6 @@ export declare function getSessionPersistedLevels(sessionKey: string): {
24
25
  thinkingLevel: string | null;
25
26
  verboseLevel: string | null;
26
27
  } | null;
27
- export declare function findSessionKeyByTranscriptId(transcriptId: string): string | null;
28
+ export declare function findSessionKeyBySessionId(sessionId: string): string | null;
28
29
  export declare function getGlobalSessionStats(): ReturnType<typeof buildGlobalSessionStats>;
29
30
  export declare function resolveSessionAgentId(sessionKey: string): string;
@@ -1,12 +1,12 @@
1
1
  import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
2
- import { buildDefaultSessionMetadata, resolveAgentIdFromSessionKey } from "./session-metadata.js";
2
+ import { buildDefaultSessionMetadata } from "./session-metadata.js";
3
3
  import { buildGlobalSessionStats, metadataToSessionInsert, sessionRowToMetadata } from "./row-mappers.js";
4
4
  import { validateSessionId } from "../../session/session-id.js";
5
5
  import { escapeFts5Query } from "./fts.js";
6
6
  import { randomUUID } from "node:crypto";
7
7
  //#region src/storage/sqlite/session-repository.ts
8
8
  const SESSION_COLUMNS = `
9
- s.session_key, s.agent_id, s.current_transcript_id, s.status, s.name, s.tags_json,
9
+ s.session_key, s.agent_id, s.session_id, s.status, s.name, s.tags_json,
10
10
  s.created_at, s.updated_at, s.last_accessed_at, s.session_started_at, s.last_interaction_at,
11
11
  s.source_channel, s.source_chat_id, s.session_type, s.hidden_from_session_list,
12
12
  s.parent_session_key, s.workflow_run_id, s.workflow_definition_id, s.workflow_agent_id, s.workflow_agent_label,
@@ -18,16 +18,16 @@ const SESSION_COLUMNS = `
18
18
  `;
19
19
  const SESSION_FROM_JOIN = `
20
20
  FROM sessions s
21
- LEFT JOIN transcripts t ON t.transcript_id = s.current_transcript_id
21
+ LEFT JOIN transcripts t ON t.session_id = s.session_id
22
22
  `;
23
23
  const SELECT_SESSION = `SELECT ${SESSION_COLUMNS} ${SESSION_FROM_JOIN} WHERE s.session_key = ?`;
24
24
  function readSessionRow(db, sessionKey) {
25
25
  return db.prepare(SELECT_SESSION).get(sessionKey);
26
26
  }
27
- function insertSessionAndTranscript(db, sessionKey, transcriptId, cwd, metadata) {
28
- const row = metadataToSessionInsert(sessionKey, transcriptId, metadata);
27
+ function insertSessionAndTranscript(db, sessionKey, sessionId, cwd, metadata) {
28
+ const row = metadataToSessionInsert(sessionKey, sessionId, metadata);
29
29
  db.prepare(`INSERT INTO sessions (
30
- session_key, agent_id, current_transcript_id, status, name, tags_json,
30
+ session_key, agent_id, session_id, status, name, tags_json,
31
31
  created_at, updated_at, last_accessed_at, session_started_at, last_interaction_at,
32
32
  source_channel, source_chat_id, session_type, hidden_from_session_list,
33
33
  parent_session_key, workflow_run_id, workflow_definition_id, workflow_agent_id, workflow_agent_label,
@@ -43,35 +43,35 @@ function insertSessionAndTranscript(db, sessionKey, transcriptId, cwd, metadata)
43
43
  ?, ?,
44
44
  ?, ?, ?, ?, ?, ?,
45
45
  ?, ?
46
- )`).run(row.sessionKey, row.agentId, row.transcriptId, row.status, row.name, row.tagsJson, row.createdAt, row.updatedAt, row.lastAccessedAt, row.sessionStartedAt, row.lastInteractionAt, row.sourceChannel, row.sourceChatId, row.sessionType, row.hiddenFromSessionList, row.parentSessionKey, row.workflowRunId, row.workflowDefinitionId, row.workflowAgentId, row.workflowAgentLabel, row.routingJson, row.customDataJson, row.abortCutoffTimestamp, row.messageCount, row.estimatedTokens, row.compactedCount, row.lastFlushedAt, row.flushCount, row.thinkingLevel, row.verboseLevel);
46
+ )`).run(row.sessionKey, row.agentId, row.sessionId, row.status, row.name, row.tagsJson, row.createdAt, row.updatedAt, row.lastAccessedAt, row.sessionStartedAt, row.lastInteractionAt, row.sourceChannel, row.sourceChatId, row.sessionType, row.hiddenFromSessionList, row.parentSessionKey, row.workflowRunId, row.workflowDefinitionId, row.workflowAgentId, row.workflowAgentLabel, row.routingJson, row.customDataJson, row.abortCutoffTimestamp, row.messageCount, row.estimatedTokens, row.compactedCount, row.lastFlushedAt, row.flushCount, row.thinkingLevel, row.verboseLevel);
47
47
  const now = Date.now();
48
- db.prepare(`INSERT INTO transcripts (transcript_id, session_key, status, created_at, cwd)
49
- VALUES (?, ?, 'active', ?, ?)`).run(transcriptId, sessionKey, now, cwd);
48
+ db.prepare(`INSERT INTO transcripts (session_id, session_key, status, created_at, cwd)
49
+ VALUES (?, ?, 'active', ?, ?)`).run(sessionId, sessionKey, now, cwd);
50
50
  }
51
- function ensureSessionInTransaction(db, sessionKey, cwd) {
51
+ function ensureSessionInTransaction(db, sessionKey, cwd, seed) {
52
52
  const existing = readSessionRow(db, sessionKey);
53
53
  if (existing) return sessionRowToMetadata(sessionKey, existing);
54
- const transcriptId = validateSessionId(randomUUID());
55
- const metadata = buildDefaultSessionMetadata(sessionKey);
56
- metadata.transcriptId = transcriptId;
57
- insertSessionAndTranscript(db, sessionKey, transcriptId, cwd, metadata);
54
+ const sessionId = validateSessionId(randomUUID());
55
+ const metadata = buildDefaultSessionMetadata(sessionKey, seed);
56
+ metadata.sessionId = sessionId;
57
+ insertSessionAndTranscript(db, sessionKey, sessionId, cwd, metadata);
58
58
  const row = readSessionRow(db, sessionKey);
59
59
  if (!row) throw new Error(`Failed to create session: ${sessionKey}`);
60
60
  return sessionRowToMetadata(sessionKey, row);
61
61
  }
62
- function ensureSessionRecord(sessionKey, cwd) {
63
- return runSqliteWriteTransaction((db) => ensureSessionInTransaction(db, sessionKey, cwd));
62
+ function ensureSessionRecord(sessionKey, cwd, seed) {
63
+ return runSqliteWriteTransaction((db) => ensureSessionInTransaction(db, sessionKey, cwd, seed));
64
64
  }
65
- function readCurrentTranscriptId(db, sessionKey) {
66
- return db.prepare(`SELECT current_transcript_id FROM sessions WHERE session_key = ?`).get(sessionKey)?.current_transcript_id ?? null;
65
+ function readCurrentSessionId(db, sessionKey) {
66
+ return db.prepare(`SELECT session_id FROM sessions WHERE session_key = ?`).get(sessionKey)?.session_id ?? null;
67
67
  }
68
68
  function getSessionMetadata(sessionKey) {
69
69
  const row = readSessionRow(getSqliteDatabase(), sessionKey);
70
70
  if (!row) return null;
71
71
  return sessionRowToMetadata(sessionKey, row);
72
72
  }
73
- function getCurrentTranscriptId(sessionKey) {
74
- return readCurrentTranscriptId(getSqliteDatabase(), sessionKey);
73
+ function getCurrentSessionId(sessionKey) {
74
+ return readCurrentSessionId(getSqliteDatabase(), sessionKey);
75
75
  }
76
76
  function listSessionMetadata(query = {}) {
77
77
  const db = getSqliteDatabase();
@@ -104,13 +104,7 @@ function listSessionMetadata(query = {}) {
104
104
  offset: query.offset ?? 0,
105
105
  hasMore: false
106
106
  };
107
- const directMatch = `LOWER(s.source_channel) IN (${channels.map(() => "?").join(", ")})`;
108
- const keyPatterns = /* @__PURE__ */ new Set();
109
- for (const c of channels) if (c === "webchat" || c === "ui") keyPatterns.add(`s.session_key LIKE 'agent:%:webchat:%'`);
110
- else if (c === "gateway" || c === "webui") keyPatterns.add(`s.session_key LIKE 'agent:%:gateway:%'`);
111
- else keyPatterns.add(`s.session_key LIKE 'agent:%:${c.replace(/'/g, "''")}:%'`);
112
- const keyFallback = keyPatterns.size > 0 ? `(TRIM(COALESCE(s.source_channel, '')) = '' AND (${[...keyPatterns].join(" OR ")}))` : "";
113
- conditions.push(keyFallback ? `(${directMatch} OR ${keyFallback})` : directMatch);
107
+ conditions.push(`LOWER(s.source_channel) IN (${channels.map(() => "?").join(", ")})`);
114
108
  params.push(...channels);
115
109
  }
116
110
  if (query.tags?.length) for (const tag of query.tags) {
@@ -236,23 +230,23 @@ function resetSessionRecord(sessionKey, cwd) {
236
230
  return runSqliteWriteTransaction((db) => {
237
231
  const existing = readSessionRow(db, sessionKey);
238
232
  if (!existing) return null;
239
- const previousSessionId = existing.current_transcript_id;
233
+ const previousSessionId = existing.session_id;
240
234
  const now = Date.now();
241
235
  db.prepare(`UPDATE transcripts SET status = 'archived', archive_reason = 'reset', archived_at = ?
242
- WHERE transcript_id = ?`).run(now, previousSessionId);
243
- const newTranscriptId = validateSessionId(randomUUID());
244
- db.prepare(`INSERT INTO transcripts (transcript_id, session_key, status, created_at, cwd)
245
- VALUES (?, ?, 'active', ?, ?)`).run(newTranscriptId, sessionKey, now, cwd);
236
+ WHERE session_id = ?`).run(now, previousSessionId);
237
+ const newSessionId = validateSessionId(randomUUID());
238
+ db.prepare(`INSERT INTO transcripts (session_id, session_key, status, created_at, cwd)
239
+ VALUES (?, ?, 'active', ?, ?)`).run(newSessionId, sessionKey, now, cwd);
246
240
  db.prepare(`UPDATE sessions SET
247
- current_transcript_id = ?,
241
+ session_id = ?,
248
242
  updated_at = ?,
249
243
  session_started_at = ?,
250
244
  last_interaction_at = NULL,
251
245
  message_count = 0,
252
246
  estimated_tokens = 0
253
- WHERE session_key = ?`).run(newTranscriptId, now, now, sessionKey);
247
+ WHERE session_key = ?`).run(newSessionId, now, now, sessionKey);
254
248
  return {
255
- sessionId: newTranscriptId,
249
+ sessionId: newSessionId,
256
250
  previousSessionId
257
251
  };
258
252
  });
@@ -263,7 +257,7 @@ function deleteSessionRecord(sessionKey) {
263
257
  if (!existing) return false;
264
258
  const now = Date.now();
265
259
  db.prepare(`UPDATE transcripts SET status = 'archived', archive_reason = 'delete', archived_at = ?
266
- WHERE transcript_id = ?`).run(now, existing.current_transcript_id);
260
+ WHERE session_id = ?`).run(now, existing.session_id);
267
261
  db.prepare(`DELETE FROM sessions WHERE session_key = ?`).run(sessionKey);
268
262
  return true;
269
263
  });
@@ -281,8 +275,8 @@ function getSessionPersistedLevels(sessionKey) {
281
275
  verboseLevel: row.verbose_level
282
276
  };
283
277
  }
284
- function findSessionKeyByTranscriptId(transcriptId) {
285
- return getSqliteDatabase().prepare(`SELECT session_key FROM sessions WHERE current_transcript_id = ?`).get(transcriptId)?.session_key ?? null;
278
+ function findSessionKeyBySessionId(sessionId) {
279
+ return getSqliteDatabase().prepare(`SELECT session_key FROM sessions WHERE session_id = ?`).get(sessionId)?.session_key ?? null;
286
280
  }
287
281
  function getGlobalSessionStats() {
288
282
  return buildGlobalSessionStats(listSessionMetadata({
@@ -291,9 +285,9 @@ function getGlobalSessionStats() {
291
285
  }).items);
292
286
  }
293
287
  function resolveSessionAgentId(sessionKey) {
294
- return resolveAgentIdFromSessionKey(sessionKey);
288
+ return getSessionMetadata(sessionKey)?.routing?.agentId ?? "main";
295
289
  }
296
290
  //#endregion
297
- export { deleteSessionRecord, ensureSessionInTransaction, ensureSessionRecord, findSessionKeyByTranscriptId, getCurrentTranscriptId, getGlobalSessionStats, getSessionMetadata, getSessionPersistedLevels, incrementSessionStatsOnAppend, listSessionMetadata, listSessionsByAgent, patchSessionMetadata, readCurrentTranscriptId, resetSessionRecord, resolveSessionAgentId, updateSessionStats };
291
+ export { deleteSessionRecord, ensureSessionInTransaction, ensureSessionRecord, findSessionKeyBySessionId, getCurrentSessionId, getGlobalSessionStats, getSessionMetadata, getSessionPersistedLevels, incrementSessionStatsOnAppend, listSessionMetadata, listSessionsByAgent, patchSessionMetadata, readCurrentSessionId, resetSessionRecord, resolveSessionAgentId, updateSessionStats };
298
292
 
299
293
  //# sourceMappingURL=session-repository.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-repository.js","names":[],"sources":["../../../../src/storage/sqlite/session-repository.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport type { DatabaseSync } from 'node:sqlite';\n\nimport { validateSessionId } from '../../session/session-id.js';\nimport type { SessionListQuery, SessionMetadata, PaginatedResult } from '../../session/types.js';\nimport {\n buildDefaultSessionMetadata,\n resolveAgentIdFromSessionKey,\n} from './session-metadata.js';\nimport {\n buildGlobalSessionStats,\n metadataToSessionInsert,\n sessionRowToMetadata,\n type SessionRow,\n} from './row-mappers.js';\nimport { getSqliteDatabase, runSqliteWriteTransaction } from './transaction.js';\n\nconst SESSION_COLUMNS = `\n s.session_key, s.agent_id, s.current_transcript_id, s.status, s.name, s.tags_json,\n s.created_at, s.updated_at, s.last_accessed_at, s.session_started_at, s.last_interaction_at,\n s.source_channel, s.source_chat_id, s.session_type, s.hidden_from_session_list,\n s.parent_session_key, s.workflow_run_id, s.workflow_definition_id, s.workflow_agent_id, s.workflow_agent_label,\n s.routing_json, s.custom_data_json,\n s.abort_cutoff_timestamp, s.message_count, s.estimated_tokens, s.compacted_count,\n s.last_flushed_at, s.flush_count,\n s.thinking_level, s.verbose_level,\n t.cwd AS cwd\n`;\n\nimport { escapeFts5Query } from './fts.js';\n\nconst SESSION_FROM_JOIN = `\n FROM sessions s\n LEFT JOIN transcripts t ON t.transcript_id = s.current_transcript_id\n`;\n\nconst SELECT_SESSION = `SELECT ${SESSION_COLUMNS} ${SESSION_FROM_JOIN} WHERE s.session_key = ?`;\n\nfunction readSessionRow(db: DatabaseSync, sessionKey: string): SessionRow | undefined {\n return db.prepare(SELECT_SESSION).get(sessionKey) as SessionRow | undefined;\n}\n\nfunction insertSessionAndTranscript(\n db: DatabaseSync,\n sessionKey: string,\n transcriptId: string,\n cwd: string,\n metadata: SessionMetadata,\n): void {\n const row = metadataToSessionInsert(sessionKey, transcriptId, metadata);\n db.prepare(\n `INSERT INTO sessions (\n session_key, agent_id, current_transcript_id, status, name, tags_json,\n created_at, updated_at, last_accessed_at, session_started_at, last_interaction_at,\n source_channel, source_chat_id, session_type, hidden_from_session_list,\n parent_session_key, workflow_run_id, workflow_definition_id, workflow_agent_id, workflow_agent_label,\n routing_json, custom_data_json,\n abort_cutoff_timestamp, message_count, estimated_tokens, compacted_count,\n last_flushed_at, flush_count,\n thinking_level, verbose_level\n ) VALUES (\n ?, ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?,\n ?, ?, ?, ?,\n ?, ?, ?, ?, ?,\n ?, ?,\n ?, ?, ?, ?, ?, ?,\n ?, ?\n )`,\n ).run(\n row.sessionKey,\n row.agentId,\n row.transcriptId,\n row.status,\n row.name,\n row.tagsJson,\n row.createdAt,\n row.updatedAt,\n row.lastAccessedAt,\n row.sessionStartedAt,\n row.lastInteractionAt,\n row.sourceChannel,\n row.sourceChatId,\n row.sessionType,\n row.hiddenFromSessionList,\n row.parentSessionKey,\n row.workflowRunId,\n row.workflowDefinitionId,\n row.workflowAgentId,\n row.workflowAgentLabel,\n row.routingJson,\n row.customDataJson,\n row.abortCutoffTimestamp,\n row.messageCount,\n row.estimatedTokens,\n row.compactedCount,\n row.lastFlushedAt,\n row.flushCount,\n row.thinkingLevel,\n row.verboseLevel,\n );\n\n const now = Date.now();\n db.prepare(\n `INSERT INTO transcripts (transcript_id, session_key, status, created_at, cwd)\n VALUES (?, ?, 'active', ?, ?)`,\n ).run(transcriptId, sessionKey, now, cwd);\n}\n\nexport function ensureSessionInTransaction(\n db: DatabaseSync,\n sessionKey: string,\n cwd: string,\n): SessionMetadata {\n const existing = readSessionRow(db, sessionKey);\n if (existing) {\n return sessionRowToMetadata(sessionKey, existing);\n }\n\n const transcriptId = validateSessionId(randomUUID());\n const metadata = buildDefaultSessionMetadata(sessionKey);\n metadata.transcriptId = transcriptId;\n insertSessionAndTranscript(db, sessionKey, transcriptId, cwd, metadata);\n const row = readSessionRow(db, sessionKey);\n if (!row) {\n throw new Error(`Failed to create session: ${sessionKey}`);\n }\n return sessionRowToMetadata(sessionKey, row);\n}\n\nexport function ensureSessionRecord(sessionKey: string, cwd: string): SessionMetadata {\n return runSqliteWriteTransaction((db) => ensureSessionInTransaction(db, sessionKey, cwd));\n}\n\nexport function readCurrentTranscriptId(db: DatabaseSync, sessionKey: string): string | null {\n const row = db\n .prepare(`SELECT current_transcript_id FROM sessions WHERE session_key = ?`)\n .get(sessionKey) as { current_transcript_id?: string } | undefined;\n return row?.current_transcript_id ?? null;\n}\n\nexport function getSessionMetadata(sessionKey: string): SessionMetadata | null {\n const db = getSqliteDatabase();\n const row = readSessionRow(db, sessionKey);\n if (!row) {\n return null;\n }\n return sessionRowToMetadata(sessionKey, row);\n}\n\nexport function getCurrentTranscriptId(sessionKey: string): string | null {\n return readCurrentTranscriptId(getSqliteDatabase(), sessionKey);\n}\n\nexport function listSessionMetadata(query: SessionListQuery = {}): PaginatedResult<SessionMetadata> {\n const db = getSqliteDatabase();\n const conditions: string[] = [];\n const params: Array<string | number> = [];\n\n if (!query.includeHidden) {\n conditions.push(`s.hidden_from_session_list = 0`);\n }\n\n if (query.sessionTypes?.length) {\n conditions.push(`s.session_type IN (${query.sessionTypes.map(() => '?').join(', ')})`);\n params.push(...query.sessionTypes);\n } else if (!query.includeHidden) {\n conditions.push(`s.session_type = ?`);\n params.push('chat');\n }\n\n if (query.status) {\n const statuses = Array.isArray(query.status) ? query.status : [query.status];\n conditions.push(`s.status IN (${statuses.map(() => '?').join(', ')})`);\n params.push(...statuses);\n }\n\n if (query.channel) {\n const rawChannels = query.channel\n .split(',')\n .map((c) => c.trim().toLowerCase())\n .filter(Boolean);\n const channels = [\n ...new Set(\n rawChannels.flatMap((c) => {\n if (c === 'webchat') return ['webchat', 'ui'];\n if (c === 'gateway') return ['gateway', 'webui'];\n return [c];\n }),\n ),\n ];\n if (channels.length === 0) {\n return { items: [], total: 0, limit: query.limit ?? 50, offset: query.offset ?? 0, hasMore: false };\n }\n const directMatch = `LOWER(s.source_channel) IN (${channels.map(() => '?').join(', ')})`;\n const keyPatterns = new Set<string>();\n for (const c of channels) {\n if (c === 'webchat' || c === 'ui') {\n keyPatterns.add(`s.session_key LIKE 'agent:%:webchat:%'`);\n } else if (c === 'gateway' || c === 'webui') {\n keyPatterns.add(`s.session_key LIKE 'agent:%:gateway:%'`);\n } else {\n keyPatterns.add(`s.session_key LIKE 'agent:%:${c.replace(/'/g, \"''\")}:%'`);\n }\n }\n const keyFallback =\n keyPatterns.size > 0\n ? `(TRIM(COALESCE(s.source_channel, '')) = '' AND (${[...keyPatterns].join(' OR ')}))`\n : '';\n conditions.push(keyFallback ? `(${directMatch} OR ${keyFallback})` : directMatch);\n params.push(...channels);\n }\n\n if (query.tags?.length) {\n for (const tag of query.tags) {\n conditions.push(`s.tags_json LIKE ?`);\n params.push(`%\"${tag}\"%`);\n }\n }\n\n let searchKeys: string[] | null = null;\n if (query.search?.trim()) {\n const rawSearch = query.search.trim();\n const ftsQuery = escapeFts5Query(rawSearch);\n const ftsRows = db\n .prepare(\n `SELECT DISTINCT session_key FROM transcript_fts WHERE transcript_fts MATCH ? LIMIT 500`,\n )\n .all(ftsQuery) as Array<{ session_key: string }>;\n const ftsKeys = new Set(ftsRows.map((r) => r.session_key));\n const like = `%${rawSearch.toLowerCase()}%`;\n const metaRows = db\n .prepare(\n `SELECT session_key FROM sessions\n WHERE LOWER(session_key) LIKE ?\n OR LOWER(COALESCE(name, '')) LIKE ?\n OR LOWER(source_channel) LIKE ?\n OR LOWER(source_chat_id) LIKE ?\n OR LOWER(tags_json) LIKE ?`,\n )\n .all(like, like, like, like, like) as Array<{ session_key: string }>;\n searchKeys = [...new Set([...ftsKeys, ...metaRows.map((r) => r.session_key)])];\n if (searchKeys.length === 0) {\n return { items: [], total: 0, limit: query.limit ?? 50, offset: query.offset ?? 0, hasMore: false };\n }\n conditions.push(`s.session_key IN (${searchKeys.map(() => '?').join(', ')})`);\n params.push(...searchKeys);\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const sortColumn = sessionSortColumn(query.sortBy);\n const sortOrder = query.sortOrder === 'asc' ? 'ASC' : 'DESC';\n\n const countRow = db\n .prepare(`SELECT COUNT(*) AS total FROM sessions s ${where}`)\n .get(...params) as { total: number };\n const total = countRow.total;\n\n const limit = query.limit ?? 50;\n const offset = query.offset ?? 0;\n const rows = db\n .prepare(\n `SELECT ${SESSION_COLUMNS} ${SESSION_FROM_JOIN} ${where}\n ORDER BY ${sortColumn} ${sortOrder}\n LIMIT ? OFFSET ?`,\n )\n .all(...params, limit, offset) as SessionRow[];\n\n const items = rows.map((row) => sessionRowToMetadata(row.session_key, row));\n return { items, total, limit, offset, hasMore: offset + limit < total };\n}\n\nfunction sessionSortColumn(sortBy: SessionListQuery['sortBy']): string {\n switch (sortBy) {\n case 'createdAt':\n return 's.created_at';\n case 'messageCount':\n return 's.message_count';\n case 'lastAccessedAt':\n return 's.last_accessed_at';\n case 'updatedAt':\n default:\n return 's.updated_at';\n }\n}\n\nexport function patchSessionMetadata(\n sessionKey: string,\n updates: Partial<SessionMetadata>,\n): SessionMetadata {\n return runSqliteWriteTransaction((db) => {\n const existing = readSessionRow(db, sessionKey);\n if (!existing) {\n throw new Error(`Session not found: ${sessionKey}`);\n }\n\n const current = sessionRowToMetadata(sessionKey, existing);\n const merged = { ...current, ...updates, key: sessionKey };\n const now = Date.now();\n\n db.prepare(\n `UPDATE sessions SET\n status = ?,\n name = ?,\n tags_json = ?,\n updated_at = ?,\n last_accessed_at = ?,\n session_started_at = ?,\n last_interaction_at = ?,\n source_channel = ?,\n source_chat_id = ?,\n session_type = ?,\n hidden_from_session_list = ?,\n parent_session_key = ?,\n workflow_run_id = ?,\n workflow_definition_id = ?,\n workflow_agent_id = ?,\n workflow_agent_label = ?,\n routing_json = ?,\n custom_data_json = ?,\n abort_cutoff_timestamp = ?,\n message_count = ?,\n estimated_tokens = ?,\n compacted_count = ?,\n last_flushed_at = ?,\n flush_count = ?,\n thinking_level = ?,\n verbose_level = ?\n WHERE session_key = ?`,\n ).run(\n merged.status,\n merged.name ?? null,\n JSON.stringify(merged.tags ?? []),\n Date.parse(merged.updatedAt) || now,\n Date.parse(merged.lastAccessedAt) || now,\n merged.sessionStartedAt ? Date.parse(merged.sessionStartedAt) : existing.session_started_at,\n merged.lastInteractionAt ? Date.parse(merged.lastInteractionAt) : existing.last_interaction_at,\n merged.sourceChannel,\n merged.sourceChatId,\n merged.sessionType,\n merged.hiddenFromSessionList ? 1 : 0,\n merged.parentSessionKey ?? null,\n merged.workflowRunId ?? null,\n merged.workflowDefinitionId ?? null,\n merged.workflowAgentId ?? null,\n merged.workflowAgentLabel ?? null,\n merged.routing ? JSON.stringify(merged.routing) : null,\n merged.customData ? JSON.stringify(merged.customData) : null,\n merged.abortCutoffTimestamp ?? null,\n merged.messageCount,\n merged.estimatedTokens,\n merged.compactedCount,\n merged.lastFlushedAt ?? null,\n merged.flushCount ?? 0,\n existing.thinking_level,\n existing.verbose_level,\n sessionKey,\n );\n\n const row = readSessionRow(db, sessionKey);\n if (!row) {\n throw new Error(`Session not found after patch: ${sessionKey}`);\n }\n return sessionRowToMetadata(sessionKey, row);\n });\n}\n\nexport function updateSessionStats(\n sessionKey: string,\n stats: { messageCount: number; estimatedTokens: number; lastInteractionAt?: number },\n): void {\n runSqliteWriteTransaction((db) => {\n const now = stats.lastInteractionAt ?? Date.now();\n db.prepare(\n `UPDATE sessions SET\n message_count = ?,\n estimated_tokens = ?,\n updated_at = ?,\n last_accessed_at = ?,\n last_interaction_at = ?\n WHERE session_key = ?`,\n ).run(stats.messageCount, stats.estimatedTokens, now, now, now, sessionKey);\n });\n}\n\nexport function incrementSessionStatsOnAppend(sessionKey: string, tokenDelta = 0): void {\n runSqliteWriteTransaction((db) => {\n const now = Date.now();\n db.prepare(\n `UPDATE sessions SET\n message_count = message_count + 1,\n estimated_tokens = estimated_tokens + ?,\n updated_at = ?,\n last_accessed_at = ?,\n last_interaction_at = ?\n WHERE session_key = ?`,\n ).run(tokenDelta, now, now, now, sessionKey);\n });\n}\n\nexport function resetSessionRecord(\n sessionKey: string,\n cwd: string,\n): { sessionId: string; previousSessionId: string } | null {\n return runSqliteWriteTransaction((db) => {\n const existing = readSessionRow(db, sessionKey);\n if (!existing) {\n return null;\n }\n\n const previousSessionId = existing.current_transcript_id;\n const now = Date.now();\n db.prepare(\n `UPDATE transcripts SET status = 'archived', archive_reason = 'reset', archived_at = ?\n WHERE transcript_id = ?`,\n ).run(now, previousSessionId);\n\n const newTranscriptId = validateSessionId(randomUUID());\n db.prepare(\n `INSERT INTO transcripts (transcript_id, session_key, status, created_at, cwd)\n VALUES (?, ?, 'active', ?, ?)`,\n ).run(newTranscriptId, sessionKey, now, cwd);\n\n db.prepare(\n `UPDATE sessions SET\n current_transcript_id = ?,\n updated_at = ?,\n session_started_at = ?,\n last_interaction_at = NULL,\n message_count = 0,\n estimated_tokens = 0\n WHERE session_key = ?`,\n ).run(newTranscriptId, now, now, sessionKey);\n\n return { sessionId: newTranscriptId, previousSessionId };\n });\n}\n\nexport function deleteSessionRecord(sessionKey: string): boolean {\n return runSqliteWriteTransaction((db) => {\n const existing = readSessionRow(db, sessionKey);\n if (!existing) {\n return false;\n }\n\n const now = Date.now();\n db.prepare(\n `UPDATE transcripts SET status = 'archived', archive_reason = 'delete', archived_at = ?\n WHERE transcript_id = ?`,\n ).run(now, existing.current_transcript_id);\n\n db.prepare(`DELETE FROM sessions WHERE session_key = ?`).run(sessionKey);\n return true;\n });\n}\n\nexport function listSessionsByAgent(agentId: string): SessionMetadata[] {\n const db = getSqliteDatabase();\n const rows = db\n .prepare(\n `SELECT ${SESSION_COLUMNS} ${SESSION_FROM_JOIN}\n WHERE s.agent_id = ?\n ORDER BY s.updated_at DESC`,\n )\n .all(agentId.toLowerCase()) as SessionRow[];\n return rows.map((row) => sessionRowToMetadata(row.session_key, row));\n}\n\nexport function getSessionPersistedLevels(sessionKey: string): {\n thinkingLevel: string | null;\n verboseLevel: string | null;\n} | null {\n const db = getSqliteDatabase();\n const row = db\n .prepare(`SELECT thinking_level, verbose_level FROM sessions WHERE session_key = ?`)\n .get(sessionKey) as { thinking_level: string | null; verbose_level: string | null } | undefined;\n if (!row) {\n return null;\n }\n return { thinkingLevel: row.thinking_level, verboseLevel: row.verbose_level };\n}\n\nexport function findSessionKeyByTranscriptId(transcriptId: string): string | null {\n const db = getSqliteDatabase();\n const row = db\n .prepare(`SELECT session_key FROM sessions WHERE current_transcript_id = ?`)\n .get(transcriptId) as { session_key?: string } | undefined;\n return row?.session_key ?? null;\n}\n\nexport function getGlobalSessionStats(): ReturnType<typeof buildGlobalSessionStats> {\n const all = listSessionMetadata({ limit: 100_000, offset: 0 });\n return buildGlobalSessionStats(all.items);\n}\n\nexport function resolveSessionAgentId(sessionKey: string): string {\n return resolveAgentIdFromSessionKey(sessionKey);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"session-repository.js","names":[],"sources":["../../../../src/storage/sqlite/session-repository.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport type { DatabaseSync } from 'node:sqlite';\n\nimport { validateSessionId } from '../../session/session-id.js';\nimport type { SessionListQuery, SessionMetadata, PaginatedResult } from '../../session/types.js';\nimport { buildDefaultSessionMetadata, type SessionMetadataSeed } from './session-metadata.js';\nimport {\n buildGlobalSessionStats,\n metadataToSessionInsert,\n sessionRowToMetadata,\n type SessionRow,\n} from './row-mappers.js';\nimport { getSqliteDatabase, runSqliteWriteTransaction } from './transaction.js';\n\nconst SESSION_COLUMNS = `\n s.session_key, s.agent_id, s.session_id, s.status, s.name, s.tags_json,\n s.created_at, s.updated_at, s.last_accessed_at, s.session_started_at, s.last_interaction_at,\n s.source_channel, s.source_chat_id, s.session_type, s.hidden_from_session_list,\n s.parent_session_key, s.workflow_run_id, s.workflow_definition_id, s.workflow_agent_id, s.workflow_agent_label,\n s.routing_json, s.custom_data_json,\n s.abort_cutoff_timestamp, s.message_count, s.estimated_tokens, s.compacted_count,\n s.last_flushed_at, s.flush_count,\n s.thinking_level, s.verbose_level,\n t.cwd AS cwd\n`;\n\nimport { escapeFts5Query } from './fts.js';\n\nconst SESSION_FROM_JOIN = `\n FROM sessions s\n LEFT JOIN transcripts t ON t.session_id = s.session_id\n`;\n\nconst SELECT_SESSION = `SELECT ${SESSION_COLUMNS} ${SESSION_FROM_JOIN} WHERE s.session_key = ?`;\n\nfunction readSessionRow(db: DatabaseSync, sessionKey: string): SessionRow | undefined {\n return db.prepare(SELECT_SESSION).get(sessionKey) as SessionRow | undefined;\n}\n\nfunction insertSessionAndTranscript(\n db: DatabaseSync,\n sessionKey: string,\n sessionId: string,\n cwd: string,\n metadata: SessionMetadata,\n): void {\n const row = metadataToSessionInsert(sessionKey, sessionId, metadata);\n db.prepare(\n `INSERT INTO sessions (\n session_key, agent_id, session_id, status, name, tags_json,\n created_at, updated_at, last_accessed_at, session_started_at, last_interaction_at,\n source_channel, source_chat_id, session_type, hidden_from_session_list,\n parent_session_key, workflow_run_id, workflow_definition_id, workflow_agent_id, workflow_agent_label,\n routing_json, custom_data_json,\n abort_cutoff_timestamp, message_count, estimated_tokens, compacted_count,\n last_flushed_at, flush_count,\n thinking_level, verbose_level\n ) VALUES (\n ?, ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?,\n ?, ?, ?, ?,\n ?, ?, ?, ?, ?,\n ?, ?,\n ?, ?, ?, ?, ?, ?,\n ?, ?\n )`,\n ).run(\n row.sessionKey,\n row.agentId,\n row.sessionId,\n row.status,\n row.name,\n row.tagsJson,\n row.createdAt,\n row.updatedAt,\n row.lastAccessedAt,\n row.sessionStartedAt,\n row.lastInteractionAt,\n row.sourceChannel,\n row.sourceChatId,\n row.sessionType,\n row.hiddenFromSessionList,\n row.parentSessionKey,\n row.workflowRunId,\n row.workflowDefinitionId,\n row.workflowAgentId,\n row.workflowAgentLabel,\n row.routingJson,\n row.customDataJson,\n row.abortCutoffTimestamp,\n row.messageCount,\n row.estimatedTokens,\n row.compactedCount,\n row.lastFlushedAt,\n row.flushCount,\n row.thinkingLevel,\n row.verboseLevel,\n );\n\n const now = Date.now();\n db.prepare(\n `INSERT INTO transcripts (session_id, session_key, status, created_at, cwd)\n VALUES (?, ?, 'active', ?, ?)`,\n ).run(sessionId, sessionKey, now, cwd);\n}\n\nexport function ensureSessionInTransaction(\n db: DatabaseSync,\n sessionKey: string,\n cwd: string,\n seed?: SessionMetadataSeed,\n): SessionMetadata {\n const existing = readSessionRow(db, sessionKey);\n if (existing) {\n return sessionRowToMetadata(sessionKey, existing);\n }\n\n const sessionId = validateSessionId(randomUUID());\n const metadata = buildDefaultSessionMetadata(sessionKey, seed);\n metadata.sessionId = sessionId;\n insertSessionAndTranscript(db, sessionKey, sessionId, cwd, metadata);\n const row = readSessionRow(db, sessionKey);\n if (!row) {\n throw new Error(`Failed to create session: ${sessionKey}`);\n }\n return sessionRowToMetadata(sessionKey, row);\n}\n\nexport function ensureSessionRecord(\n sessionKey: string,\n cwd: string,\n seed?: SessionMetadataSeed,\n): SessionMetadata {\n return runSqliteWriteTransaction((db) => ensureSessionInTransaction(db, sessionKey, cwd, seed));\n}\n\nexport function readCurrentSessionId(db: DatabaseSync, sessionKey: string): string | null {\n const row = db\n .prepare(`SELECT session_id FROM sessions WHERE session_key = ?`)\n .get(sessionKey) as { session_id?: string } | undefined;\n return row?.session_id ?? null;\n}\n\nexport function getSessionMetadata(sessionKey: string): SessionMetadata | null {\n const db = getSqliteDatabase();\n const row = readSessionRow(db, sessionKey);\n if (!row) {\n return null;\n }\n return sessionRowToMetadata(sessionKey, row);\n}\n\nexport function getCurrentSessionId(sessionKey: string): string | null {\n return readCurrentSessionId(getSqliteDatabase(), sessionKey);\n}\n\nexport function listSessionMetadata(query: SessionListQuery = {}): PaginatedResult<SessionMetadata> {\n const db = getSqliteDatabase();\n const conditions: string[] = [];\n const params: Array<string | number> = [];\n\n if (!query.includeHidden) {\n conditions.push(`s.hidden_from_session_list = 0`);\n }\n\n if (query.sessionTypes?.length) {\n conditions.push(`s.session_type IN (${query.sessionTypes.map(() => '?').join(', ')})`);\n params.push(...query.sessionTypes);\n } else if (!query.includeHidden) {\n conditions.push(`s.session_type = ?`);\n params.push('chat');\n }\n\n if (query.status) {\n const statuses = Array.isArray(query.status) ? query.status : [query.status];\n conditions.push(`s.status IN (${statuses.map(() => '?').join(', ')})`);\n params.push(...statuses);\n }\n\n if (query.channel) {\n const rawChannels = query.channel\n .split(',')\n .map((c) => c.trim().toLowerCase())\n .filter(Boolean);\n const channels = [\n ...new Set(\n rawChannels.flatMap((c) => {\n if (c === 'webchat') return ['webchat', 'ui'];\n if (c === 'gateway') return ['gateway', 'webui'];\n return [c];\n }),\n ),\n ];\n if (channels.length === 0) {\n return { items: [], total: 0, limit: query.limit ?? 50, offset: query.offset ?? 0, hasMore: false };\n }\n conditions.push(`LOWER(s.source_channel) IN (${channels.map(() => '?').join(', ')})`);\n params.push(...channels);\n }\n\n if (query.tags?.length) {\n for (const tag of query.tags) {\n conditions.push(`s.tags_json LIKE ?`);\n params.push(`%\"${tag}\"%`);\n }\n }\n\n let searchKeys: string[] | null = null;\n if (query.search?.trim()) {\n const rawSearch = query.search.trim();\n const ftsQuery = escapeFts5Query(rawSearch);\n const ftsRows = db\n .prepare(\n `SELECT DISTINCT session_key FROM transcript_fts WHERE transcript_fts MATCH ? LIMIT 500`,\n )\n .all(ftsQuery) as Array<{ session_key: string }>;\n const ftsKeys = new Set(ftsRows.map((r) => r.session_key));\n const like = `%${rawSearch.toLowerCase()}%`;\n const metaRows = db\n .prepare(\n `SELECT session_key FROM sessions\n WHERE LOWER(session_key) LIKE ?\n OR LOWER(COALESCE(name, '')) LIKE ?\n OR LOWER(source_channel) LIKE ?\n OR LOWER(source_chat_id) LIKE ?\n OR LOWER(tags_json) LIKE ?`,\n )\n .all(like, like, like, like, like) as Array<{ session_key: string }>;\n searchKeys = [...new Set([...ftsKeys, ...metaRows.map((r) => r.session_key)])];\n if (searchKeys.length === 0) {\n return { items: [], total: 0, limit: query.limit ?? 50, offset: query.offset ?? 0, hasMore: false };\n }\n conditions.push(`s.session_key IN (${searchKeys.map(() => '?').join(', ')})`);\n params.push(...searchKeys);\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const sortColumn = sessionSortColumn(query.sortBy);\n const sortOrder = query.sortOrder === 'asc' ? 'ASC' : 'DESC';\n\n const countRow = db\n .prepare(`SELECT COUNT(*) AS total FROM sessions s ${where}`)\n .get(...params) as { total: number };\n const total = countRow.total;\n\n const limit = query.limit ?? 50;\n const offset = query.offset ?? 0;\n const rows = db\n .prepare(\n `SELECT ${SESSION_COLUMNS} ${SESSION_FROM_JOIN} ${where}\n ORDER BY ${sortColumn} ${sortOrder}\n LIMIT ? OFFSET ?`,\n )\n .all(...params, limit, offset) as SessionRow[];\n\n const items = rows.map((row) => sessionRowToMetadata(row.session_key, row));\n return { items, total, limit, offset, hasMore: offset + limit < total };\n}\n\nfunction sessionSortColumn(sortBy: SessionListQuery['sortBy']): string {\n switch (sortBy) {\n case 'createdAt':\n return 's.created_at';\n case 'messageCount':\n return 's.message_count';\n case 'lastAccessedAt':\n return 's.last_accessed_at';\n case 'updatedAt':\n default:\n return 's.updated_at';\n }\n}\n\nexport function patchSessionMetadata(\n sessionKey: string,\n updates: Partial<SessionMetadata>,\n): SessionMetadata {\n return runSqliteWriteTransaction((db) => {\n const existing = readSessionRow(db, sessionKey);\n if (!existing) {\n throw new Error(`Session not found: ${sessionKey}`);\n }\n\n const current = sessionRowToMetadata(sessionKey, existing);\n const merged = { ...current, ...updates, key: sessionKey };\n const now = Date.now();\n\n db.prepare(\n `UPDATE sessions SET\n status = ?,\n name = ?,\n tags_json = ?,\n updated_at = ?,\n last_accessed_at = ?,\n session_started_at = ?,\n last_interaction_at = ?,\n source_channel = ?,\n source_chat_id = ?,\n session_type = ?,\n hidden_from_session_list = ?,\n parent_session_key = ?,\n workflow_run_id = ?,\n workflow_definition_id = ?,\n workflow_agent_id = ?,\n workflow_agent_label = ?,\n routing_json = ?,\n custom_data_json = ?,\n abort_cutoff_timestamp = ?,\n message_count = ?,\n estimated_tokens = ?,\n compacted_count = ?,\n last_flushed_at = ?,\n flush_count = ?,\n thinking_level = ?,\n verbose_level = ?\n WHERE session_key = ?`,\n ).run(\n merged.status,\n merged.name ?? null,\n JSON.stringify(merged.tags ?? []),\n Date.parse(merged.updatedAt) || now,\n Date.parse(merged.lastAccessedAt) || now,\n merged.sessionStartedAt ? Date.parse(merged.sessionStartedAt) : existing.session_started_at,\n merged.lastInteractionAt ? Date.parse(merged.lastInteractionAt) : existing.last_interaction_at,\n merged.sourceChannel,\n merged.sourceChatId,\n merged.sessionType,\n merged.hiddenFromSessionList ? 1 : 0,\n merged.parentSessionKey ?? null,\n merged.workflowRunId ?? null,\n merged.workflowDefinitionId ?? null,\n merged.workflowAgentId ?? null,\n merged.workflowAgentLabel ?? null,\n merged.routing ? JSON.stringify(merged.routing) : null,\n merged.customData ? JSON.stringify(merged.customData) : null,\n merged.abortCutoffTimestamp ?? null,\n merged.messageCount,\n merged.estimatedTokens,\n merged.compactedCount,\n merged.lastFlushedAt ?? null,\n merged.flushCount ?? 0,\n existing.thinking_level,\n existing.verbose_level,\n sessionKey,\n );\n\n const row = readSessionRow(db, sessionKey);\n if (!row) {\n throw new Error(`Session not found after patch: ${sessionKey}`);\n }\n return sessionRowToMetadata(sessionKey, row);\n });\n}\n\nexport function updateSessionStats(\n sessionKey: string,\n stats: { messageCount: number; estimatedTokens: number; lastInteractionAt?: number },\n): void {\n runSqliteWriteTransaction((db) => {\n const now = stats.lastInteractionAt ?? Date.now();\n db.prepare(\n `UPDATE sessions SET\n message_count = ?,\n estimated_tokens = ?,\n updated_at = ?,\n last_accessed_at = ?,\n last_interaction_at = ?\n WHERE session_key = ?`,\n ).run(stats.messageCount, stats.estimatedTokens, now, now, now, sessionKey);\n });\n}\n\nexport function incrementSessionStatsOnAppend(sessionKey: string, tokenDelta = 0): void {\n runSqliteWriteTransaction((db) => {\n const now = Date.now();\n db.prepare(\n `UPDATE sessions SET\n message_count = message_count + 1,\n estimated_tokens = estimated_tokens + ?,\n updated_at = ?,\n last_accessed_at = ?,\n last_interaction_at = ?\n WHERE session_key = ?`,\n ).run(tokenDelta, now, now, now, sessionKey);\n });\n}\n\nexport function resetSessionRecord(\n sessionKey: string,\n cwd: string,\n): { sessionId: string; previousSessionId: string } | null {\n return runSqliteWriteTransaction((db) => {\n const existing = readSessionRow(db, sessionKey);\n if (!existing) {\n return null;\n }\n\n const previousSessionId = existing.session_id;\n const now = Date.now();\n db.prepare(\n `UPDATE transcripts SET status = 'archived', archive_reason = 'reset', archived_at = ?\n WHERE session_id = ?`,\n ).run(now, previousSessionId);\n\n const newSessionId = validateSessionId(randomUUID());\n db.prepare(\n `INSERT INTO transcripts (session_id, session_key, status, created_at, cwd)\n VALUES (?, ?, 'active', ?, ?)`,\n ).run(newSessionId, sessionKey, now, cwd);\n\n db.prepare(\n `UPDATE sessions SET\n session_id = ?,\n updated_at = ?,\n session_started_at = ?,\n last_interaction_at = NULL,\n message_count = 0,\n estimated_tokens = 0\n WHERE session_key = ?`,\n ).run(newSessionId, now, now, sessionKey);\n\n return { sessionId: newSessionId, previousSessionId };\n });\n}\n\nexport function deleteSessionRecord(sessionKey: string): boolean {\n return runSqliteWriteTransaction((db) => {\n const existing = readSessionRow(db, sessionKey);\n if (!existing) {\n return false;\n }\n\n const now = Date.now();\n db.prepare(\n `UPDATE transcripts SET status = 'archived', archive_reason = 'delete', archived_at = ?\n WHERE session_id = ?`,\n ).run(now, existing.session_id);\n\n db.prepare(`DELETE FROM sessions WHERE session_key = ?`).run(sessionKey);\n return true;\n });\n}\n\nexport function listSessionsByAgent(agentId: string): SessionMetadata[] {\n const db = getSqliteDatabase();\n const rows = db\n .prepare(\n `SELECT ${SESSION_COLUMNS} ${SESSION_FROM_JOIN}\n WHERE s.agent_id = ?\n ORDER BY s.updated_at DESC`,\n )\n .all(agentId.toLowerCase()) as SessionRow[];\n return rows.map((row) => sessionRowToMetadata(row.session_key, row));\n}\n\nexport function getSessionPersistedLevels(sessionKey: string): {\n thinkingLevel: string | null;\n verboseLevel: string | null;\n} | null {\n const db = getSqliteDatabase();\n const row = db\n .prepare(`SELECT thinking_level, verbose_level FROM sessions WHERE session_key = ?`)\n .get(sessionKey) as { thinking_level: string | null; verbose_level: string | null } | undefined;\n if (!row) {\n return null;\n }\n return { thinkingLevel: row.thinking_level, verboseLevel: row.verbose_level };\n}\n\nexport function findSessionKeyBySessionId(sessionId: string): string | null {\n const db = getSqliteDatabase();\n const row = db\n .prepare(`SELECT session_key FROM sessions WHERE session_id = ?`)\n .get(sessionId) as { session_key?: string } | undefined;\n return row?.session_key ?? null;\n}\n\nexport function getGlobalSessionStats(): ReturnType<typeof buildGlobalSessionStats> {\n const all = listSessionMetadata({ limit: 100_000, offset: 0 });\n return buildGlobalSessionStats(all.items);\n}\n\nexport function resolveSessionAgentId(sessionKey: string): string {\n return getSessionMetadata(sessionKey)?.routing?.agentId ?? 'main';\n}\n"],"mappings":"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"}
@@ -4,11 +4,11 @@ import type { TranscriptCompactionRecord } from '../../session/transcript-format
4
4
  import { type TranscriptStoredRow } from '../../session/session-context-for-llm.js';
5
5
  import { type TranscriptEntryRow } from './row-mappers.js';
6
6
  export declare function appendTranscriptEntry(sessionKey: string, row: TranscriptStoredRow, opts?: {
7
- transcriptId?: string;
7
+ sessionId?: string;
8
8
  tokenDelta?: number;
9
9
  }): TranscriptEntryRow;
10
10
  export declare function loadTranscriptRowsForSession(sessionKey: string): TranscriptStoredRow[];
11
- export declare function loadTranscriptRows(transcriptId: string): TranscriptStoredRow[];
11
+ export declare function loadTranscriptRows(sessionId: string): TranscriptStoredRow[];
12
12
  export declare function loadLlmMessagesForSession(sessionKey: string): AgentMessage[];
13
13
  export declare function replaceTranscriptRows(sessionKey: string, rows: TranscriptStoredRow[], opts?: {
14
14
  appendCompaction?: TranscriptCompactionRecord;
@@ -1,27 +1,27 @@
1
1
  import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
2
2
  import { buildSessionContextForLlm } from "../../session/session-context-for-llm.js";
3
3
  import { classifyStoredRow, estimateTokensFromMessages, extractFtsContent, transcriptEntryRowToStoredRow } from "./row-mappers.js";
4
- import { getCurrentTranscriptId, readCurrentTranscriptId } from "./session-repository.js";
4
+ import { getCurrentSessionId, readCurrentSessionId } from "./session-repository.js";
5
5
  import { randomUUID } from "node:crypto";
6
6
  //#region src/storage/sqlite/transcript-repository.ts
7
7
  const MAX_CHECKPOINTS_PER_TRANSCRIPT = 15;
8
- function nextSeq(db, transcriptId) {
9
- return (db.prepare(`SELECT COALESCE(MAX(seq), 0) AS max_seq FROM transcript_entries WHERE transcript_id = ?`).get(transcriptId).max_seq ?? 0) + 1;
8
+ function nextSeq(db, sessionId) {
9
+ return (db.prepare(`SELECT COALESCE(MAX(seq), 0) AS max_seq FROM transcript_entries WHERE session_id = ?`).get(sessionId).max_seq ?? 0) + 1;
10
10
  }
11
11
  function insertEntry(db, params) {
12
12
  const { entryKind, role } = classifyStoredRow(params.row);
13
13
  const entryId = params.entryId ?? randomUUID();
14
- const seq = nextSeq(db, params.transcriptId);
14
+ const seq = nextSeq(db, params.sessionId);
15
15
  const createdAt = params.createdAt ?? Date.now();
16
16
  const payloadJson = JSON.stringify(params.row);
17
- db.prepare(`INSERT INTO transcript_entries (entry_id, transcript_id, seq, entry_kind, role, payload_json, created_at)
18
- VALUES (?, ?, ?, ?, ?, ?, ?)`).run(entryId, params.transcriptId, seq, entryKind, role, payloadJson, createdAt);
17
+ db.prepare(`INSERT INTO transcript_entries (entry_id, session_id, seq, entry_kind, role, payload_json, created_at)
18
+ VALUES (?, ?, ?, ?, ?, ?, ?)`).run(entryId, params.sessionId, seq, entryKind, role, payloadJson, createdAt);
19
19
  const content = extractFtsContent(params.row);
20
- if (content.trim()) db.prepare(`INSERT INTO transcript_fts (content, session_key, transcript_id, entry_id)
21
- VALUES (?, ?, ?, ?)`).run(content, params.sessionKey, params.transcriptId, entryId);
20
+ if (content.trim()) db.prepare(`INSERT INTO transcript_fts (content, session_key, session_id, entry_id)
21
+ VALUES (?, ?, ?, ?)`).run(content, params.sessionKey, params.sessionId, entryId);
22
22
  return {
23
23
  entry_id: entryId,
24
- transcript_id: params.transcriptId,
24
+ session_id: params.sessionId,
25
25
  seq,
26
26
  entry_kind: entryKind,
27
27
  role,
@@ -31,10 +31,10 @@ function insertEntry(db, params) {
31
31
  }
32
32
  function appendTranscriptEntry(sessionKey, row, opts) {
33
33
  return runSqliteWriteTransaction((db) => {
34
- const transcriptId = opts?.transcriptId ?? readCurrentTranscriptId(db, sessionKey);
35
- if (!transcriptId) throw new Error(`Session not found: ${sessionKey}`);
34
+ const sessionId = opts?.sessionId ?? readCurrentSessionId(db, sessionKey);
35
+ if (!sessionId) throw new Error(`Session not found: ${sessionKey}`);
36
36
  const inserted = insertEntry(db, {
37
- transcriptId,
37
+ sessionId,
38
38
  sessionKey,
39
39
  row
40
40
  });
@@ -53,32 +53,32 @@ function appendTranscriptEntry(sessionKey, row, opts) {
53
53
  });
54
54
  }
55
55
  function loadTranscriptRowsForSession(sessionKey) {
56
- const transcriptId = getCurrentTranscriptId(sessionKey);
57
- if (!transcriptId) return [];
58
- return loadTranscriptRows(transcriptId);
56
+ const sessionId = getCurrentSessionId(sessionKey);
57
+ if (!sessionId) return [];
58
+ return loadTranscriptRows(sessionId);
59
59
  }
60
- function loadTranscriptRows(transcriptId) {
61
- return getSqliteDatabase().prepare(`SELECT entry_id, transcript_id, seq, entry_kind, role, payload_json, created_at
60
+ function loadTranscriptRows(sessionId) {
61
+ return getSqliteDatabase().prepare(`SELECT entry_id, session_id, seq, entry_kind, role, payload_json, created_at
62
62
  FROM transcript_entries
63
- WHERE transcript_id = ?
64
- ORDER BY seq ASC`).all(transcriptId).map(transcriptEntryRowToStoredRow);
63
+ WHERE session_id = ?
64
+ ORDER BY seq ASC`).all(sessionId).map(transcriptEntryRowToStoredRow);
65
65
  }
66
66
  function loadLlmMessagesForSession(sessionKey) {
67
67
  return buildSessionContextForLlm(loadTranscriptRowsForSession(sessionKey));
68
68
  }
69
69
  function replaceTranscriptRows(sessionKey, rows, opts) {
70
70
  runSqliteWriteTransaction((db) => {
71
- const transcriptId = readCurrentTranscriptId(db, sessionKey);
72
- if (!transcriptId) throw new Error(`Session not found: ${sessionKey}`);
73
- db.prepare(`DELETE FROM transcript_fts WHERE transcript_id = ?`).run(transcriptId);
74
- db.prepare(`DELETE FROM transcript_entries WHERE transcript_id = ?`).run(transcriptId);
71
+ const sessionId = readCurrentSessionId(db, sessionKey);
72
+ if (!sessionId) throw new Error(`Session not found: ${sessionKey}`);
73
+ db.prepare(`DELETE FROM transcript_fts WHERE session_id = ?`).run(sessionId);
74
+ db.prepare(`DELETE FROM transcript_entries WHERE session_id = ?`).run(sessionId);
75
75
  const toWrite = [...rows];
76
76
  if (opts?.appendCompaction) toWrite.push({
77
77
  type: "compaction",
78
78
  ...opts.appendCompaction
79
79
  });
80
80
  for (const row of toWrite) insertEntry(db, {
81
- transcriptId,
81
+ sessionId,
82
82
  sessionKey,
83
83
  row
84
84
  });
@@ -102,8 +102,8 @@ function loadCheckpointRows(sessionKey, checkpointId) {
102
102
  ORDER BY seq ASC`).all(checkpointId).map((entry) => JSON.parse(entry.payload_json));
103
103
  }
104
104
  function paginateTranscriptMessages(sessionKey, options = {}) {
105
- const transcriptId = getCurrentTranscriptId(sessionKey);
106
- if (!transcriptId) return {
105
+ const sessionId = getCurrentSessionId(sessionKey);
106
+ if (!sessionId) return {
107
107
  rows: [],
108
108
  messages: [],
109
109
  total: 0,
@@ -114,35 +114,35 @@ function paginateTranscriptMessages(sessionKey, options = {}) {
114
114
  const kinds = options.includeContext ? ["message", "context"] : ["message"];
115
115
  const kindPlaceholders = kinds.map(() => "?").join(", ");
116
116
  const total = db.prepare(`SELECT COUNT(*) AS total FROM transcript_entries
117
- WHERE transcript_id = ? AND entry_kind IN (${kindPlaceholders})`).get(transcriptId, ...kinds).total;
117
+ WHERE session_id = ? AND entry_kind IN (${kindPlaceholders})`).get(sessionId, ...kinds).total;
118
118
  const limit = Math.min(200, Math.max(1, Math.trunc(options.limit ?? 50)));
119
119
  const offset = Math.max(0, Math.trunc(options.offset ?? 0));
120
120
  let rows;
121
121
  if (options.beforeEndIndex !== void 0 && Number.isFinite(options.beforeEndIndex)) {
122
122
  const endExclusive = Math.min(total, Math.max(0, Math.trunc(options.beforeEndIndex)));
123
123
  const startInclusive = Math.max(0, endExclusive - limit);
124
- rows = db.prepare(`SELECT entry_id, transcript_id, seq, entry_kind, role, payload_json, created_at
124
+ rows = db.prepare(`SELECT entry_id, session_id, seq, entry_kind, role, payload_json, created_at
125
125
  FROM (
126
- SELECT entry_id, transcript_id, seq, entry_kind, role, payload_json, created_at,
126
+ SELECT entry_id, session_id, seq, entry_kind, role, payload_json, created_at,
127
127
  ROW_NUMBER() OVER (ORDER BY seq ASC) - 1 AS idx
128
128
  FROM transcript_entries
129
- WHERE transcript_id = ? AND entry_kind IN (${kindPlaceholders})
129
+ WHERE session_id = ? AND entry_kind IN (${kindPlaceholders})
130
130
  )
131
131
  WHERE idx >= ? AND idx < ?
132
- ORDER BY seq ASC`).all(transcriptId, ...kinds, startInclusive, endExclusive);
132
+ ORDER BY seq ASC`).all(sessionId, ...kinds, startInclusive, endExclusive);
133
133
  } else if (options.beforeSeq !== void 0 && Number.isFinite(options.beforeSeq)) {
134
- rows = db.prepare(`SELECT entry_id, transcript_id, seq, entry_kind, role, payload_json, created_at
134
+ rows = db.prepare(`SELECT entry_id, session_id, seq, entry_kind, role, payload_json, created_at
135
135
  FROM transcript_entries
136
- WHERE transcript_id = ? AND entry_kind IN (${kindPlaceholders}) AND seq < ?
136
+ WHERE session_id = ? AND entry_kind IN (${kindPlaceholders}) AND seq < ?
137
137
  ORDER BY seq DESC
138
- LIMIT ?`).all(transcriptId, ...kinds, options.beforeSeq, limit);
138
+ LIMIT ?`).all(sessionId, ...kinds, options.beforeSeq, limit);
139
139
  rows.reverse();
140
140
  } else {
141
- rows = db.prepare(`SELECT entry_id, transcript_id, seq, entry_kind, role, payload_json, created_at
141
+ rows = db.prepare(`SELECT entry_id, session_id, seq, entry_kind, role, payload_json, created_at
142
142
  FROM transcript_entries
143
- WHERE transcript_id = ? AND entry_kind IN (${kindPlaceholders})
143
+ WHERE session_id = ? AND entry_kind IN (${kindPlaceholders})
144
144
  ORDER BY seq DESC
145
- LIMIT ? OFFSET ?`).all(transcriptId, ...kinds, limit, offset);
145
+ LIMIT ? OFFSET ?`).all(sessionId, ...kinds, limit, offset);
146
146
  rows.reverse();
147
147
  }
148
148
  const storedRows = rows.map(transcriptEntryRowToStoredRow);
@@ -156,29 +156,29 @@ function paginateTranscriptMessages(sessionKey, options = {}) {
156
156
  }
157
157
  function captureCompactionCheckpoint(sessionKey) {
158
158
  return runSqliteWriteTransaction((db) => {
159
- const transcriptId = readCurrentTranscriptId(db, sessionKey);
160
- if (!transcriptId) return null;
161
- const entries = db.prepare(`SELECT entry_id, transcript_id, seq, entry_kind, role, payload_json, created_at
162
- FROM transcript_entries WHERE transcript_id = ? ORDER BY seq ASC`).all(transcriptId);
159
+ const sessionId = readCurrentSessionId(db, sessionKey);
160
+ if (!sessionId) return null;
161
+ const entries = db.prepare(`SELECT entry_id, session_id, seq, entry_kind, role, payload_json, created_at
162
+ FROM transcript_entries WHERE session_id = ? ORDER BY seq ASC`).all(sessionId);
163
163
  if (entries.length === 0) return null;
164
164
  const checkpointId = randomUUID();
165
165
  const now = Date.now();
166
166
  const messageCount = entries.filter((e) => e.entry_kind === "message").length;
167
167
  const sizeBytes = entries.reduce((sum, e) => sum + e.payload_json.length, 0);
168
168
  db.prepare(`INSERT INTO compaction_checkpoints
169
- (checkpoint_id, transcript_id, session_key, created_at, message_count, size_bytes)
170
- VALUES (?, ?, ?, ?, ?, ?)`).run(checkpointId, transcriptId, sessionKey, now, messageCount, sizeBytes);
169
+ (checkpoint_id, session_id, session_key, created_at, message_count, size_bytes)
170
+ VALUES (?, ?, ?, ?, ?, ?)`).run(checkpointId, sessionId, sessionKey, now, messageCount, sizeBytes);
171
171
  const insertCheckpointEntry = db.prepare(`INSERT INTO checkpoint_entries (checkpoint_id, seq, entry_kind, role, payload_json)
172
172
  VALUES (?, ?, ?, ?, ?)`);
173
173
  for (const entry of entries) insertCheckpointEntry.run(checkpointId, entry.seq, entry.entry_kind, entry.role, entry.payload_json);
174
- pruneCompactionCheckpoints(db, transcriptId);
174
+ pruneCompactionCheckpoints(db, sessionId);
175
175
  return checkpointId;
176
176
  });
177
177
  }
178
- function pruneCompactionCheckpoints(db, transcriptId) {
178
+ function pruneCompactionCheckpoints(db, sessionId) {
179
179
  const rows = db.prepare(`SELECT checkpoint_id FROM compaction_checkpoints
180
- WHERE transcript_id = ?
181
- ORDER BY created_at ASC`).all(transcriptId);
180
+ WHERE session_id = ?
181
+ ORDER BY created_at ASC`).all(sessionId);
182
182
  if (rows.length <= MAX_CHECKPOINTS_PER_TRANSCRIPT) return;
183
183
  const toDelete = rows.slice(0, rows.length - MAX_CHECKPOINTS_PER_TRANSCRIPT);
184
184
  const del = db.prepare(`DELETE FROM compaction_checkpoints WHERE checkpoint_id = ?`);
@@ -208,18 +208,18 @@ function getCompactionCheckpointDetail(sessionKey, checkpointId) {
208
208
  }
209
209
  function restoreCompactionCheckpoint(sessionKey, checkpointId) {
210
210
  runSqliteWriteTransaction((db) => {
211
- const transcriptId = readCurrentTranscriptId(db, sessionKey);
212
- if (!transcriptId) throw new Error(`Session not found: ${sessionKey}`);
211
+ const sessionId = readCurrentSessionId(db, sessionKey);
212
+ if (!sessionId) throw new Error(`Session not found: ${sessionKey}`);
213
213
  if (!db.prepare(`SELECT checkpoint_id FROM compaction_checkpoints
214
214
  WHERE session_key = ? AND checkpoint_id = ?`).get(sessionKey, checkpointId)) throw new Error(`Checkpoint not found: ${checkpointId}`);
215
215
  const entries = db.prepare(`SELECT seq, entry_kind, role, payload_json
216
216
  FROM checkpoint_entries
217
217
  WHERE checkpoint_id = ?
218
218
  ORDER BY seq ASC`).all(checkpointId);
219
- db.prepare(`DELETE FROM transcript_fts WHERE transcript_id = ?`).run(transcriptId);
220
- db.prepare(`DELETE FROM transcript_entries WHERE transcript_id = ?`).run(transcriptId);
219
+ db.prepare(`DELETE FROM transcript_fts WHERE session_id = ?`).run(sessionId);
220
+ db.prepare(`DELETE FROM transcript_entries WHERE session_id = ?`).run(sessionId);
221
221
  for (const entry of entries) insertEntry(db, {
222
- transcriptId,
222
+ sessionId,
223
223
  sessionKey,
224
224
  row: JSON.parse(entry.payload_json),
225
225
  createdAt: Date.now()