@xopcai/xopc 0.0.95 → 0.0.96

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 (428) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  3. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  4. package/dist/extensions/telegram/src/plugin.js +1 -1
  5. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  6. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  7. package/dist/extensions/telegram/xopc.extension.json +1 -1
  8. package/dist/extensions/weixin/src/api/api.js +2 -2
  9. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  10. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  11. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  12. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  13. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  14. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  15. package/dist/extensions/weixin/src/plugin.js +1 -1
  16. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  17. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  18. package/dist/gateway/static/root/assets/{agents-CKe2LMnz.js → agents-DmIuSaOE.js} +2 -2
  19. package/dist/gateway/static/root/assets/{apps-page-Mi9mMIZ1.js → apps-page-DFcHBxLw.js} +1 -1
  20. package/dist/gateway/static/root/assets/{channels-settings-BrdyC101.js → channels-settings-DDUf55C5.js} +1 -1
  21. package/dist/gateway/static/root/assets/{channels-status-swr-D55Bu0nn.js → channels-status-swr-BxF-_nzD.js} +1 -1
  22. package/dist/gateway/static/root/assets/{cron-api-CPpx2l-E.js → cron-api-DylQtnb_.js} +1 -1
  23. package/dist/gateway/static/root/assets/{cron-page-Bx2jB0YN.js → cron-page-BO0d9Pf-.js} +1 -1
  24. package/dist/gateway/static/root/assets/{dist-D_AiG_Kg.js → dist-BskF0qDS.js} +1 -1
  25. package/dist/gateway/static/root/assets/{extension-debug-page-6ieHsxRE.js → extension-debug-page-BcZdTdjJ.js} +1 -1
  26. package/dist/gateway/static/root/assets/{extension-page-B8nywHRO.js → extension-page-D2iuDa1D.js} +1 -1
  27. package/dist/gateway/static/root/assets/{extension-settings-page-DrskdEIV.js → extension-settings-page-BKpQCgLc.js} +1 -1
  28. package/dist/gateway/static/root/assets/{fetch-B0aeeY0q.js → fetch-CtNDpjij.js} +1 -1
  29. package/dist/gateway/static/root/assets/{field-primitives--9ooY8Xl.js → field-primitives-2PekrGZF.js} +1 -1
  30. package/dist/gateway/static/root/assets/{heartbeat-config-api-DUZ_W1w-.js → heartbeat-config-api-D3D7SW8A.js} +1 -1
  31. package/dist/gateway/static/root/assets/index-BvEhL9RQ.css +1 -0
  32. package/dist/gateway/static/root/assets/{index-Dj9FuxCm.js → index-Db9fd_X4.js} +74 -74
  33. package/dist/gateway/static/root/assets/{logs-page-CaXqhpKf.js → logs-page-B3I1a26m.js} +1 -1
  34. package/dist/gateway/static/root/assets/{note-detail-page-DYzym2B0.js → note-detail-page-BOizhtJ8.js} +54 -53
  35. package/dist/gateway/static/root/assets/{note-detail-page-B91pLkEI.css → note-detail-page-D4ZIVQbk.css} +1 -1
  36. package/dist/gateway/static/root/assets/{note-time-B-vSi2dR.js → note-time-CjUGtqKr.js} +1 -1
  37. package/dist/gateway/static/root/assets/{notes-page-BkhWdGiT.js → notes-page-BB8-I0Of.js} +1 -1
  38. package/dist/gateway/static/root/assets/{sessions-page-53YFokoe.js → sessions-page-BcH-1K9i.js} +1 -1
  39. package/dist/gateway/static/root/assets/{settings-advanced-gate-BaZmaklx.js → settings-advanced-gate-Czn8nnjN.js} +1 -1
  40. package/dist/gateway/static/root/assets/{settings-form-section-DIJPKpTR.js → settings-form-section-ZZWDwgVe.js} +1 -1
  41. package/dist/gateway/static/root/assets/{settings-page-Dvb230FF.js → settings-page-BX8c_zrN.js} +1 -1
  42. package/dist/gateway/static/root/assets/{share-preview-page-CRyjTAG6.js → share-preview-page-Ch3_6Qah.js} +1 -1
  43. package/dist/gateway/static/root/assets/{skills-page-C5ZJbfAe.js → skills-page-WO0bbJ54.js} +1 -1
  44. package/dist/gateway/static/root/assets/{theme-store-Cg_SuBw0.js → theme-store-XxRFRZDX.js} +1 -1
  45. package/dist/gateway/static/root/assets/url-6zpynn1R.js +3 -0
  46. package/dist/gateway/static/root/assets/{utils-lMYoWhqo.js → utils-uTYKh54l.js} +1 -1
  47. package/dist/gateway/static/root/assets/{voice-api-key-field-Dda2pcUU.js → voice-api-key-field-BIAYHRs-.js} +1 -1
  48. package/dist/gateway/static/root/assets/{workflow-page.utils-KIladUrU.js → workflow-page.utils-BbWhqD36.js} +1 -1
  49. package/dist/gateway/static/root/assets/{workflows-page-BTis4Z7Y.js → workflows-page-D4RIF7E1.js} +1 -1
  50. package/dist/gateway/static/root/index.html +5 -5
  51. package/dist/package.js +1 -1
  52. package/dist/src/agent/agent-manager.js +15 -9
  53. package/dist/src/agent/agent-manager.js.map +1 -1
  54. package/dist/src/agent/agent-scope.d.ts +0 -1
  55. package/dist/src/agent/agent-scope.js +2 -5
  56. package/dist/src/agent/agent-scope.js.map +1 -1
  57. package/dist/src/agent/bootstrap/bootstrap-cache.d.ts +3 -0
  58. package/dist/src/agent/bootstrap/bootstrap-cache.js +13 -3
  59. package/dist/src/agent/bootstrap/bootstrap-cache.js.map +1 -1
  60. package/dist/src/agent/bootstrap/bootstrap-files.d.ts +6 -0
  61. package/dist/src/agent/bootstrap/bootstrap-files.js +35 -12
  62. package/dist/src/agent/bootstrap/bootstrap-files.js.map +1 -1
  63. package/dist/src/agent/bootstrap/load-bootstrap-files.d.ts +5 -2
  64. package/dist/src/agent/bootstrap/load-bootstrap-files.js +12 -3
  65. package/dist/src/agent/bootstrap/load-bootstrap-files.js.map +1 -1
  66. package/dist/src/agent/context/workspace-seed.js +8 -4
  67. package/dist/src/agent/context/workspace-seed.js.map +1 -1
  68. package/dist/src/agent/context/workspace-state.d.ts +52 -0
  69. package/dist/src/agent/context/workspace-state.js +101 -0
  70. package/dist/src/agent/context/workspace-state.js.map +1 -0
  71. package/dist/src/agent/embedded/index.d.ts +2 -2
  72. package/dist/src/agent/embedded/index.js +3 -3
  73. package/dist/src/agent/embedded/run-turn.js +0 -3
  74. package/dist/src/agent/embedded/run-turn.js.map +1 -1
  75. package/dist/src/agent/embedded/session-manager-init.d.ts +0 -17
  76. package/dist/src/agent/embedded/session-manager-init.js +1 -36
  77. package/dist/src/agent/embedded/session-manager-init.js.map +1 -1
  78. package/dist/src/agent/embedded/session-runner.d.ts +3 -12
  79. package/dist/src/agent/embedded/session-runner.js +12 -26
  80. package/dist/src/agent/embedded/session-runner.js.map +1 -1
  81. package/dist/src/agent/embedded/session-tool-result-guard.js +2 -4
  82. package/dist/src/agent/embedded/session-tool-result-guard.js.map +1 -1
  83. package/dist/src/agent/embedded/sqlite-hydrating-session-manager.d.ts +10 -0
  84. package/dist/src/agent/embedded/sqlite-hydrating-session-manager.js +34 -0
  85. package/dist/src/agent/embedded/sqlite-hydrating-session-manager.js.map +1 -0
  86. package/dist/src/agent/goals/goal-run-store.js +4 -4
  87. package/dist/src/agent/goals/persistent-goal-service.js +8 -15
  88. package/dist/src/agent/goals/persistent-goal-service.js.map +1 -1
  89. package/dist/src/agent/goals/post-turn.js +2 -2
  90. package/dist/src/agent/image/load-image-media.js +2 -2
  91. package/dist/src/agent/ipc/bus.js +1 -1
  92. package/dist/src/agent/ipc/inbox.js +2 -2
  93. package/dist/src/agent/ipc/socket.js +1 -1
  94. package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
  95. package/dist/src/agent/mcp/bundle-mcp-runtime.js +2 -2
  96. package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
  97. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  98. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  99. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  100. package/dist/src/agent/memory/dreaming/events.js +1 -1
  101. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  102. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  103. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  104. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  105. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  106. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  107. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  108. package/dist/src/agent/models/manager.js +1 -1
  109. package/dist/src/agent/prompt/memory/index.d.ts +1 -0
  110. package/dist/src/agent/prompt/memory/index.js +34 -80
  111. package/dist/src/agent/prompt/memory/index.js.map +1 -1
  112. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  113. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  114. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  115. package/dist/src/agent/sandbox/path-policy.js +2 -2
  116. package/dist/src/agent/service/build-direct-message-content.js +1 -1
  117. package/dist/src/agent/service/process-direct-one-shot.js +8 -17
  118. package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
  119. package/dist/src/agent/service/process-direct-streaming.js +14 -23
  120. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  121. package/dist/src/agent/service.js +7 -11
  122. package/dist/src/agent/service.js.map +1 -1
  123. package/dist/src/agent/session/session-inspector.js +1 -1
  124. package/dist/src/agent/skills/config.js +1 -1
  125. package/dist/src/agent/skills/hub-hash.js +2 -2
  126. package/dist/src/agent/skills/hub-lock.js +1 -1
  127. package/dist/src/agent/skills/hub-pull.js +3 -3
  128. package/dist/src/agent/skills/index.js +1 -1
  129. package/dist/src/agent/skills/managed-store.js +1 -1
  130. package/dist/src/agent/skills/scanner.js +1 -1
  131. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  132. package/dist/src/agent/skills/skill-manager.js +1 -1
  133. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  134. package/dist/src/agent/tools/factory.js +1 -1
  135. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  136. package/dist/src/agent/tools/index.d.ts +0 -1
  137. package/dist/src/agent/tools/index.js +1 -2
  138. package/dist/src/agent/tools/send-media.js +1 -1
  139. package/dist/src/agent/tools/session-search-tool.d.ts +0 -1
  140. package/dist/src/agent/tools/session-search-tool.js +11 -6
  141. package/dist/src/agent/tools/session-search-tool.js.map +1 -1
  142. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  143. package/dist/src/agent/tools/workflow-tool.js +1 -1
  144. package/dist/src/agent/tools/write.js +1 -1
  145. package/dist/src/agent/workflow/catalog.js +1 -1
  146. package/dist/src/auth/credentials.js +3 -3
  147. package/dist/src/auth/profiles/store.js +1 -1
  148. package/dist/src/auth/sync-provider-auth.js +1 -1
  149. package/dist/src/browser/cache-dir-policy.js +1 -1
  150. package/dist/src/browser/cdp-local-launcher.js +2 -2
  151. package/dist/src/browser/providers/browser-ext-install.js +4 -4
  152. package/dist/src/browser/providers/cloakbrowser.js +4 -4
  153. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  154. package/dist/src/browser/stealth.js +1 -1
  155. package/dist/src/channels/attachments/inbound-persist.js +1 -1
  156. package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
  157. package/dist/src/channels/outbound/persist-store.js +1 -1
  158. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  159. package/dist/src/channels/pairing/pairing-store.js +2 -2
  160. package/dist/src/chat-commands/agent-edit.js +2 -2
  161. package/dist/src/chat-commands/builtins/config.js +2 -2
  162. package/dist/src/chat-commands/context.js +1 -1
  163. package/dist/src/cli/commands/config.js +1 -1
  164. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  165. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  166. package/dist/src/cli/commands/doctor/checks/session-integrity.js +32 -95
  167. package/dist/src/cli/commands/doctor/checks/session-integrity.js.map +1 -1
  168. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  169. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  170. package/dist/src/cli/commands/extension-dev.js +1 -1
  171. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  172. package/dist/src/cli/commands/extension-pack.js +1 -1
  173. package/dist/src/cli/commands/gateway/logs.js +1 -1
  174. package/dist/src/cli/commands/image.js +1 -1
  175. package/dist/src/cli/commands/init.js +5 -7
  176. package/dist/src/cli/commands/init.js.map +1 -1
  177. package/dist/src/cli/commands/onboard.js +1 -1
  178. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  179. package/dist/src/commands/agents.config.js +1 -1
  180. package/dist/src/config/agent-profile.js +1 -1
  181. package/dist/src/config/gateway-bind.js +1 -1
  182. package/dist/src/config/index.js +7 -8
  183. package/dist/src/config/index.js.map +1 -1
  184. package/dist/src/config/loader.js +2 -2
  185. package/dist/src/config/models-json.js +2 -2
  186. package/dist/src/config/paths-state.d.ts +3 -0
  187. package/dist/src/config/paths-state.js +7 -3
  188. package/dist/src/config/paths-state.js.map +1 -1
  189. package/dist/src/config/paths.d.ts +5 -35
  190. package/dist/src/config/paths.js +6 -50
  191. package/dist/src/config/paths.js.map +1 -1
  192. package/dist/src/config/profile.js +2 -2
  193. package/dist/src/config/schema.d.ts +15 -0
  194. package/dist/src/config/schema.js +11 -0
  195. package/dist/src/config/schema.js.map +1 -1
  196. package/dist/src/config/workspace-path.js +1 -1
  197. package/dist/src/cron/execution-types.d.ts +42 -0
  198. package/dist/src/cron/executor.js +2 -2
  199. package/dist/src/cron/persistence.js +1 -1
  200. package/dist/src/cron/run-log-store.d.ts +4 -8
  201. package/dist/src/cron/run-log-store.js +26 -78
  202. package/dist/src/cron/run-log-store.js.map +1 -1
  203. package/dist/src/cron/service.d.ts +3 -3
  204. package/dist/src/cron/service.js +2 -2
  205. package/dist/src/cron/service.js.map +1 -1
  206. package/dist/src/cron/types.d.ts +1 -42
  207. package/dist/src/daemon/constants.js +1 -1
  208. package/dist/src/daemon/install-plan.js +2 -2
  209. package/dist/src/daemon/launchd.js +2 -2
  210. package/dist/src/daemon/schtasks.js +2 -2
  211. package/dist/src/daemon/systemd.js +2 -2
  212. package/dist/src/extensions/bundle-mcp.js +1 -1
  213. package/dist/src/extensions/discover-extensions.js +1 -1
  214. package/dist/src/extensions/health.js +1 -1
  215. package/dist/src/extensions/loader.js +1 -1
  216. package/dist/src/extensions/lockfile.js +2 -2
  217. package/dist/src/extensions/update.js +1 -1
  218. package/dist/src/gateway/agents-admin.js +8 -3
  219. package/dist/src/gateway/agents-admin.js.map +1 -1
  220. package/dist/src/gateway/file-path-classifier.d.ts +0 -1
  221. package/dist/src/gateway/file-path-classifier.js +2 -8
  222. package/dist/src/gateway/file-path-classifier.js.map +1 -1
  223. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  224. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  225. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  226. package/dist/src/gateway/hono/oauth.js +1 -1
  227. package/dist/src/gateway/hono/routes/agents.js +1 -1
  228. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  229. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  230. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  231. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  232. package/dist/src/gateway/hono/routes/models.js +1 -1
  233. package/dist/src/gateway/hono/routes/shares.js +1 -1
  234. package/dist/src/gateway/hono/routes/workspace.js +2 -2
  235. package/dist/src/gateway/lock.js +3 -3
  236. package/dist/src/gateway/ports.js +1 -1
  237. package/dist/src/gateway/service/agent-runner.js +2 -2
  238. package/dist/src/gateway/service/marketplace-service.js +2 -2
  239. package/dist/src/gateway/service.js +5 -1
  240. package/dist/src/gateway/service.js.map +1 -1
  241. package/dist/src/gateway/session-reset-service.d.ts +1 -1
  242. package/dist/src/gateway/session-reset-service.js +1 -1
  243. package/dist/src/gateway/session-reset-service.js.map +1 -1
  244. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  245. package/dist/src/infra/brew.js +1 -1
  246. package/dist/src/infra/node-sqlite.d.ts +1 -0
  247. package/dist/src/infra/node-sqlite.js +17 -0
  248. package/dist/src/infra/node-sqlite.js.map +1 -0
  249. package/dist/src/infra/package-json.js +1 -1
  250. package/dist/src/infra/package-update-steps.js +1 -1
  251. package/dist/src/infra/path-env.js +2 -2
  252. package/dist/src/infra/restart.js +2 -2
  253. package/dist/src/infra/sqlite-errors.d.ts +1 -0
  254. package/dist/src/infra/sqlite-errors.js +77 -0
  255. package/dist/src/infra/sqlite-errors.js.map +1 -0
  256. package/dist/src/infra/stable-node-path.js +1 -1
  257. package/dist/src/infra/unhandled-rejections.d.ts +1 -0
  258. package/dist/src/infra/unhandled-rejections.js +25 -0
  259. package/dist/src/infra/unhandled-rejections.js.map +1 -0
  260. package/dist/src/infra/update-check.js +1 -1
  261. package/dist/src/infra/update-global.js +1 -1
  262. package/dist/src/infra/update-lock.js +3 -3
  263. package/dist/src/infra/update-runner.js +1 -1
  264. package/dist/src/infra/update-startup.js +2 -2
  265. package/dist/src/infra/warning-filter.d.ts +7 -0
  266. package/dist/src/infra/warning-filter.js +59 -0
  267. package/dist/src/infra/warning-filter.js.map +1 -0
  268. package/dist/src/infra/write-file-atomic.js +2 -2
  269. package/dist/src/notes/store.d.ts +3 -9
  270. package/dist/src/notes/store.js +22 -196
  271. package/dist/src/notes/store.js.map +1 -1
  272. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  273. package/dist/src/providers/index.js +2 -2
  274. package/dist/src/providers/model-registry.js +1 -1
  275. package/dist/src/session/config-store.d.ts +6 -75
  276. package/dist/src/session/config-store.js +38 -144
  277. package/dist/src/session/config-store.js.map +1 -1
  278. package/dist/src/session/config-types.d.ts +15 -0
  279. package/dist/src/session/config-types.js +1 -0
  280. package/dist/src/session/index.d.ts +1 -3
  281. package/dist/src/session/index.js +3 -5
  282. package/dist/src/session/init-session-turn.d.ts +0 -6
  283. package/dist/src/session/init-session-turn.js +18 -18
  284. package/dist/src/session/init-session-turn.js.map +1 -1
  285. package/dist/src/session/lifecycle-timestamps.d.ts +5 -2
  286. package/dist/src/session/lifecycle-timestamps.js.map +1 -1
  287. package/dist/src/session/{parity/load-jsonl-entries.js → load-jsonl-entries.js} +1 -1
  288. package/dist/src/session/load-jsonl-entries.js.map +1 -0
  289. package/dist/src/session/manager.d.ts +5 -3
  290. package/dist/src/session/manager.js +1 -5
  291. package/dist/src/session/manager.js.map +1 -1
  292. package/dist/src/session/resolve-session.d.ts +3 -6
  293. package/dist/src/session/resolve-session.js +26 -31
  294. package/dist/src/session/resolve-session.js.map +1 -1
  295. package/dist/src/session/session-context-for-llm.js +5 -1
  296. package/dist/src/session/session-context-for-llm.js.map +1 -1
  297. package/dist/src/session/session-id.js +12 -0
  298. package/dist/src/session/session-id.js.map +1 -0
  299. package/dist/src/session/session-title.js +2 -2
  300. package/dist/src/session/session-workspace.d.ts +1 -1
  301. package/dist/src/session/session-workspace.js.map +1 -1
  302. package/dist/src/session/store.d.ts +14 -63
  303. package/dist/src/session/store.js +172 -847
  304. package/dist/src/session/store.js.map +1 -1
  305. package/dist/src/session/stored-rows-to-file-entries.d.ts +11 -0
  306. package/dist/src/session/stored-rows-to-file-entries.js +95 -0
  307. package/dist/src/session/stored-rows-to-file-entries.js.map +1 -0
  308. package/dist/src/session/transcript-events.d.ts +1 -2
  309. package/dist/src/session/transcript-events.js +5 -12
  310. package/dist/src/session/transcript-events.js.map +1 -1
  311. package/dist/src/session/transcript-format.d.ts +1 -1
  312. package/dist/src/session/transcript-format.js.map +1 -1
  313. package/dist/src/session/transcript-stats.d.ts +1 -0
  314. package/dist/src/session/transcript-stats.js +10 -0
  315. package/dist/src/session/transcript-stats.js.map +1 -0
  316. package/dist/src/share/share-auto.js +2 -2
  317. package/dist/src/share/share-store.js +3 -3
  318. package/dist/src/share/share-thumbnail.js +2 -2
  319. package/dist/src/share/share-zip.js +1 -1
  320. package/dist/src/share/site-share-store.js +3 -3
  321. package/dist/src/share/site-static-serve.js +1 -1
  322. package/dist/src/storage/sqlite/config-repository.d.ts +6 -0
  323. package/dist/src/storage/sqlite/config-repository.js +56 -0
  324. package/dist/src/storage/sqlite/config-repository.js.map +1 -0
  325. package/dist/src/storage/sqlite/connection.d.ts +38 -0
  326. package/dist/src/storage/sqlite/connection.js +258 -0
  327. package/dist/src/storage/sqlite/connection.js.map +1 -0
  328. package/dist/src/storage/sqlite/cron-run-repository.d.ts +5 -0
  329. package/dist/src/storage/sqlite/cron-run-repository.js +97 -0
  330. package/dist/src/storage/sqlite/cron-run-repository.js.map +1 -0
  331. package/dist/src/storage/sqlite/fts.d.ts +2 -0
  332. package/dist/src/storage/sqlite/fts.js +11 -0
  333. package/dist/src/storage/sqlite/fts.js.map +1 -0
  334. package/dist/src/storage/sqlite/index.d.ts +12 -0
  335. package/dist/src/storage/sqlite/index.js +13 -0
  336. package/dist/src/storage/sqlite/memory-index-repository.d.ts +18 -0
  337. package/dist/src/storage/sqlite/memory-index-repository.js +132 -0
  338. package/dist/src/storage/sqlite/memory-index-repository.js.map +1 -0
  339. package/dist/src/storage/sqlite/notes-repository.d.ts +11 -0
  340. package/dist/src/storage/sqlite/notes-repository.js +191 -0
  341. package/dist/src/storage/sqlite/notes-repository.js.map +1 -0
  342. package/dist/src/storage/sqlite/paths.d.ts +1 -0
  343. package/dist/src/storage/sqlite/paths.js +7 -0
  344. package/dist/src/storage/sqlite/paths.js.map +1 -0
  345. package/dist/src/storage/sqlite/row-mappers.d.ts +82 -0
  346. package/dist/src/storage/sqlite/row-mappers.js +164 -0
  347. package/dist/src/storage/sqlite/row-mappers.js.map +1 -0
  348. package/dist/src/storage/sqlite/schema.d.ts +5 -0
  349. package/dist/src/storage/sqlite/schema.js +43 -0
  350. package/dist/src/storage/sqlite/schema.js.map +1 -0
  351. package/dist/src/storage/sqlite/schema.sql +195 -0
  352. package/dist/src/storage/sqlite/session-metadata.d.ts +8 -0
  353. package/dist/src/storage/sqlite/session-metadata.js +83 -0
  354. package/dist/src/storage/sqlite/session-metadata.js.map +1 -0
  355. package/dist/src/storage/sqlite/session-repository.d.ts +29 -0
  356. package/dist/src/storage/sqlite/session-repository.js +268 -0
  357. package/dist/src/storage/sqlite/session-repository.js.map +1 -0
  358. package/dist/src/storage/sqlite/transaction.d.ts +11 -0
  359. package/dist/src/storage/sqlite/transaction.js +115 -0
  360. package/dist/src/storage/sqlite/transaction.js.map +1 -0
  361. package/dist/src/storage/sqlite/transcript-repository.d.ts +34 -0
  362. package/dist/src/storage/sqlite/transcript-repository.js +241 -0
  363. package/dist/src/storage/sqlite/transcript-repository.js.map +1 -0
  364. package/dist/src/tui/clipboard-image.js +3 -3
  365. package/dist/src/tui/theme-manager.js +1 -1
  366. package/dist/src/tui/tui-keybindings-file.js +1 -1
  367. package/dist/src/tui/tui-scoped-models.js +2 -2
  368. package/dist/src/tui/tui-settings.js +1 -1
  369. package/dist/src/tui/tui.js +3 -3
  370. package/dist/src/tunnel/frpc-binary.js +3 -3
  371. package/dist/src/tunnel/frpc-config.js +1 -1
  372. package/dist/src/tunnel/frpc-extract.js +1 -1
  373. package/dist/src/tunnel/tunnel-state.js +1 -1
  374. package/dist/src/utils/logger/audit.js +1 -1
  375. package/dist/src/utils/logger/log-store.js +1 -1
  376. package/dist/src/utils/logger/rotation.js +1 -1
  377. package/dist/src/voice/tts/audio.js +1 -1
  378. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  379. package/dist/src/workflows/service/workflow-session-bridge.js +41 -64
  380. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  381. package/dist/src/workflows/store/event-store.js +1 -1
  382. package/dist/src/workflows/store/run-store.js +1 -1
  383. package/package.json +2 -2
  384. package/dist/gateway/static/root/assets/index-Bj_l8QDp.css +0 -1
  385. package/dist/gateway/static/root/assets/url-BHHmdJYc.js +0 -3
  386. package/dist/src/agent/embedded/session-manager-cache.d.ts +0 -19
  387. package/dist/src/agent/embedded/session-manager-cache.js +0 -48
  388. package/dist/src/agent/embedded/session-manager-cache.js.map +0 -1
  389. package/dist/src/session/parity/artifacts.d.ts +0 -16
  390. package/dist/src/session/parity/artifacts.js +0 -80
  391. package/dist/src/session/parity/artifacts.js.map +0 -1
  392. package/dist/src/session/parity/jsonl-transcript-io.d.ts +0 -54
  393. package/dist/src/session/parity/jsonl-transcript-io.js +0 -236
  394. package/dist/src/session/parity/jsonl-transcript-io.js.map +0 -1
  395. package/dist/src/session/parity/load-jsonl-entries.js.map +0 -1
  396. package/dist/src/session/parity/session-id.js +0 -18
  397. package/dist/src/session/parity/session-id.js.map +0 -1
  398. package/dist/src/session/parity/sessions-json-cache.d.ts +0 -14
  399. package/dist/src/session/parity/sessions-json-cache.js +0 -98
  400. package/dist/src/session/parity/sessions-json-cache.js.map +0 -1
  401. package/dist/src/session/parity/sessions-json-file-read.d.ts +0 -6
  402. package/dist/src/session/parity/sessions-json-file-read.js +0 -19
  403. package/dist/src/session/parity/sessions-json-file-read.js.map +0 -1
  404. package/dist/src/session/parity/sessions-json-file.d.ts +0 -11
  405. package/dist/src/session/parity/sessions-json-file.js +0 -52
  406. package/dist/src/session/parity/sessions-json-file.js.map +0 -1
  407. package/dist/src/session/parity/sessions-json-patch.d.ts +0 -14
  408. package/dist/src/session/parity/sessions-json-patch.js +0 -40
  409. package/dist/src/session/parity/sessions-json-patch.js.map +0 -1
  410. package/dist/src/session/parity/transcript-file-lock.d.ts +0 -22
  411. package/dist/src/session/parity/transcript-file-lock.js +0 -142
  412. package/dist/src/session/parity/transcript-file-lock.js.map +0 -1
  413. package/dist/src/session/parity/transcript-pagination.d.ts +0 -29
  414. package/dist/src/session/parity/transcript-pagination.js +0 -132
  415. package/dist/src/session/parity/transcript-pagination.js.map +0 -1
  416. package/dist/src/session/parity/transcript-paths.d.ts +0 -13
  417. package/dist/src/session/parity/transcript-paths.js +0 -64
  418. package/dist/src/session/parity/transcript-paths.js.map +0 -1
  419. package/dist/src/session/parity/xopc-session-disk-entry.d.ts +0 -22
  420. package/dist/src/session/search-index-cache.d.ts +0 -6
  421. package/dist/src/session/search-index-cache.js +0 -44
  422. package/dist/src/session/search-index-cache.js.map +0 -1
  423. package/dist/src/session/search-index.d.ts +0 -20
  424. package/dist/src/session/search-index.js +0 -124
  425. package/dist/src/session/search-index.js.map +0 -1
  426. /package/dist/src/{session/parity/xopc-session-disk-entry.js → cron/execution-types.js} +0 -0
  427. /package/dist/src/session/{parity/load-jsonl-entries.d.ts → load-jsonl-entries.d.ts} +0 -0
  428. /package/dist/src/session/{parity/session-id.d.ts → session-id.d.ts} +0 -0
@@ -0,0 +1,132 @@
1
+ import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
2
+ import { escapeFts5Query } from "./fts.js";
3
+ import { createHash } from "node:crypto";
4
+ import { existsSync, readFileSync, statSync } from "node:fs";
5
+ import { join, relative } from "node:path";
6
+ //#region src/storage/sqlite/memory-index-repository.ts
7
+ const CURATED_MEMORY_FILENAMES = new Set(["MEMORY.md", "USER.md"]);
8
+ const MEMORY_SYNC_CACHE_TTL_MS = 3e4;
9
+ const memorySyncCache = /* @__PURE__ */ new Map();
10
+ function resolveAgentIdFromMemoriesDir(memoriesDir) {
11
+ if (!memoriesDir) return "main";
12
+ return memoriesDir.replace(/\\/g, "/").match(/\/agents\/([^/]+)\/memories\/?$/)?.[1] ?? "main";
13
+ }
14
+ function getDailyMemoryPath(baseDir, date) {
15
+ const d = date || /* @__PURE__ */ new Date();
16
+ return join(baseDir, "memory", `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}.md`);
17
+ }
18
+ function getCuratedMemoryPaths(memoriesDir) {
19
+ if (!memoriesDir) return [];
20
+ return [join(memoriesDir, "MEMORY.md"), join(memoriesDir, "USER.md")].filter((p) => existsSync(p));
21
+ }
22
+ function collectMemoryPaths(baseDir, memoriesDir) {
23
+ const paths = [];
24
+ paths.push(...getCuratedMemoryPaths(memoriesDir));
25
+ const longTermPath = join(baseDir, "MEMORY.md");
26
+ if (existsSync(longTermPath)) paths.push(longTermPath);
27
+ if (existsSync(join(baseDir, "memory"))) {
28
+ const today = /* @__PURE__ */ new Date();
29
+ for (let i = 0; i < 30; i++) {
30
+ const date = new Date(today);
31
+ date.setDate(date.getDate() - i);
32
+ const path = getDailyMemoryPath(baseDir, date);
33
+ if (existsSync(path)) paths.push(path);
34
+ }
35
+ }
36
+ return paths;
37
+ }
38
+ function displayPath(baseDir, memoriesDir, absPath) {
39
+ const normalized = absPath.replace(/\\/g, "/");
40
+ if (memoriesDir) {
41
+ const memoriesRoot = memoriesDir.replace(/\\/g, "/");
42
+ if (normalized.startsWith(memoriesRoot)) {
43
+ const filename = normalized.slice(memoriesRoot.length).replace(/^\//, "");
44
+ if (CURATED_MEMORY_FILENAMES.has(filename)) return filename;
45
+ }
46
+ }
47
+ return relative(baseDir, absPath).replace(/\\/g, "/");
48
+ }
49
+ function contentHash(content) {
50
+ return createHash("sha256").update(content).digest("hex");
51
+ }
52
+ function bm25ToScore(rank) {
53
+ return 1 / (1 + Math.max(0, -rank));
54
+ }
55
+ function indexFile(db, agentId, baseDir, memoriesDir, absPath) {
56
+ const content = readFileSync(absPath, "utf-8");
57
+ const mtimeMs = statSync(absPath).mtimeMs;
58
+ const hash = contentHash(content);
59
+ const relPath = displayPath(baseDir, memoriesDir, absPath);
60
+ const fileId = `${agentId}:${relPath}`;
61
+ const existing = db.prepare(`SELECT content_hash, mtime_ms FROM memory_files WHERE file_id = ?`).get(fileId);
62
+ if (existing && existing.content_hash === hash && existing.mtime_ms === mtimeMs) return;
63
+ db.prepare(`DELETE FROM memory_fts WHERE chunk_id IN (SELECT chunk_id FROM memory_chunks WHERE file_id = ?)`).run(fileId);
64
+ db.prepare(`DELETE FROM memory_chunks WHERE file_id = ?`).run(fileId);
65
+ db.prepare(`DELETE FROM memory_files WHERE file_id = ?`).run(fileId);
66
+ db.prepare(`INSERT INTO memory_files (file_id, agent_id, path, mtime_ms, content_hash)
67
+ VALUES (?, ?, ?, ?, ?)`).run(fileId, agentId, relPath, mtimeMs, hash);
68
+ const lines = content.split("\n");
69
+ const insertChunk = db.prepare(`INSERT INTO memory_chunks (chunk_id, file_id, start_line, end_line, content)
70
+ VALUES (?, ?, ?, ?, ?)`);
71
+ const insertFts = db.prepare(`INSERT INTO memory_fts (content, chunk_id, agent_id, path, start_line, end_line)
72
+ VALUES (?, ?, ?, ?, ?, ?)`);
73
+ for (let i = 0; i < lines.length; i++) {
74
+ const line = lines[i];
75
+ if (!line.trim()) continue;
76
+ const lineNo = i + 1;
77
+ const chunkId = `${fileId}:${lineNo}`;
78
+ insertChunk.run(chunkId, fileId, lineNo, lineNo, line);
79
+ insertFts.run(line, chunkId, agentId, relPath, lineNo, lineNo);
80
+ }
81
+ }
82
+ function syncMemoryIndex(params) {
83
+ const cacheKey = `${params.agentId}:${params.workspaceDir}:${params.memoriesDir ?? ""}`;
84
+ const now = Date.now();
85
+ const cached = memorySyncCache.get(cacheKey);
86
+ if (cached && now - cached.timestamp < MEMORY_SYNC_CACHE_TTL_MS) return;
87
+ const paths = collectMemoryPaths(params.workspaceDir, params.memoriesDir);
88
+ memorySyncCache.set(cacheKey, {
89
+ timestamp: now,
90
+ paths
91
+ });
92
+ runSqliteWriteTransaction((db) => {
93
+ const seen = /* @__PURE__ */ new Set();
94
+ for (const absPath of paths) {
95
+ seen.add(`${params.agentId}:${displayPath(params.workspaceDir, params.memoriesDir, absPath)}`);
96
+ indexFile(db, params.agentId, params.workspaceDir, params.memoriesDir, absPath);
97
+ }
98
+ const stale = db.prepare(`SELECT file_id FROM memory_files WHERE agent_id = ?`).all(params.agentId);
99
+ for (const row of stale) if (!seen.has(row.file_id)) {
100
+ db.prepare(`DELETE FROM memory_fts WHERE chunk_id IN (SELECT chunk_id FROM memory_chunks WHERE file_id = ?)`).run(row.file_id);
101
+ db.prepare(`DELETE FROM memory_chunks WHERE file_id = ?`).run(row.file_id);
102
+ db.prepare(`DELETE FROM memory_files WHERE file_id = ?`).run(row.file_id);
103
+ }
104
+ });
105
+ }
106
+ function searchMemoryIndex(params) {
107
+ const { agentId, query, maxResults = 5, minScore = .3 } = params;
108
+ const ftsQuery = escapeFts5Query(query);
109
+ if (!ftsQuery) return [];
110
+ const rows = getSqliteDatabase().prepare(`SELECT chunk_id, path, start_line, end_line, content, bm25(memory_fts) AS rank
111
+ FROM memory_fts
112
+ WHERE memory_fts MATCH ? AND agent_id = ?
113
+ ORDER BY rank
114
+ LIMIT ?`).all(ftsQuery, agentId, maxResults * 3);
115
+ const results = [];
116
+ for (const row of rows) {
117
+ const score = bm25ToScore(row.rank);
118
+ if (score < minScore) continue;
119
+ results.push({
120
+ path: row.path,
121
+ lines: row.content,
122
+ score,
123
+ lineNumbers: [row.start_line]
124
+ });
125
+ }
126
+ results.sort((a, b) => b.score - a.score);
127
+ return results.slice(0, maxResults);
128
+ }
129
+ //#endregion
130
+ export { resolveAgentIdFromMemoriesDir, searchMemoryIndex, syncMemoryIndex };
131
+
132
+ //# sourceMappingURL=memory-index-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-index-repository.js","names":[],"sources":["../../../../src/storage/sqlite/memory-index-repository.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\nimport { escapeFts5Query } from './fts.js';\nimport { getSqliteDatabase, runSqliteWriteTransaction } from './transaction.js';\n\nexport type MemorySearchHit = {\n path: string;\n lines: string;\n score: number;\n lineNumbers: number[];\n};\n\nconst CURATED_MEMORY_FILENAMES = new Set(['MEMORY.md', 'USER.md']);\nconst MEMORY_SYNC_CACHE_TTL_MS = 30_000;\n\ntype MemorySyncCache = {\n timestamp: number;\n paths: string[];\n};\n\nconst memorySyncCache = new Map<string, MemorySyncCache>();\n\nexport function resolveAgentIdFromMemoriesDir(memoriesDir: string | undefined): string {\n if (!memoriesDir) return 'main';\n const normalized = memoriesDir.replace(/\\\\/g, '/');\n const match = normalized.match(/\\/agents\\/([^/]+)\\/memories\\/?$/);\n return match?.[1] ?? 'main';\n}\n\nfunction getDailyMemoryPath(baseDir: string, date?: Date): string {\n const d = date || new Date();\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return join(baseDir, 'memory', `${year}-${month}-${day}.md`);\n}\n\nfunction getCuratedMemoryPaths(memoriesDir: string | undefined): string[] {\n if (!memoriesDir) return [];\n return [join(memoriesDir, 'MEMORY.md'), join(memoriesDir, 'USER.md')].filter((p) => existsSync(p));\n}\n\nfunction collectMemoryPaths(baseDir: string, memoriesDir?: string): string[] {\n const paths: string[] = [];\n paths.push(...getCuratedMemoryPaths(memoriesDir));\n\n const longTermPath = join(baseDir, 'MEMORY.md');\n if (existsSync(longTermPath)) {\n paths.push(longTermPath);\n }\n\n const memoryDir = join(baseDir, 'memory');\n if (existsSync(memoryDir)) {\n const today = new Date();\n for (let i = 0; i < 30; i++) {\n const date = new Date(today);\n date.setDate(date.getDate() - i);\n const path = getDailyMemoryPath(baseDir, date);\n if (existsSync(path)) {\n paths.push(path);\n }\n }\n }\n\n return paths;\n}\n\nfunction displayPath(baseDir: string, memoriesDir: string | undefined, absPath: string): string {\n const normalized = absPath.replace(/\\\\/g, '/');\n if (memoriesDir) {\n const memoriesRoot = memoriesDir.replace(/\\\\/g, '/');\n if (normalized.startsWith(memoriesRoot)) {\n const filename = normalized.slice(memoriesRoot.length).replace(/^\\//, '');\n if (CURATED_MEMORY_FILENAMES.has(filename)) {\n return filename;\n }\n }\n }\n return relative(baseDir, absPath).replace(/\\\\/g, '/');\n}\n\nfunction contentHash(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\nfunction bm25ToScore(rank: number): number {\n return 1 / (1 + Math.max(0, -rank));\n}\n\nfunction indexFile(\n db: ReturnType<typeof getSqliteDatabase>,\n agentId: string,\n baseDir: string,\n memoriesDir: string | undefined,\n absPath: string,\n): void {\n const content = readFileSync(absPath, 'utf-8');\n const mtimeMs = statSync(absPath).mtimeMs;\n const hash = contentHash(content);\n const relPath = displayPath(baseDir, memoriesDir, absPath);\n const fileId = `${agentId}:${relPath}`;\n\n const existing = db\n .prepare(`SELECT content_hash, mtime_ms FROM memory_files WHERE file_id = ?`)\n .get(fileId) as { content_hash: string; mtime_ms: number } | undefined;\n if (existing && existing.content_hash === hash && existing.mtime_ms === mtimeMs) {\n return;\n }\n\n db.prepare(`DELETE FROM memory_fts WHERE chunk_id IN (SELECT chunk_id FROM memory_chunks WHERE file_id = ?)`).run(\n fileId,\n );\n db.prepare(`DELETE FROM memory_chunks WHERE file_id = ?`).run(fileId);\n db.prepare(`DELETE FROM memory_files WHERE file_id = ?`).run(fileId);\n\n db.prepare(\n `INSERT INTO memory_files (file_id, agent_id, path, mtime_ms, content_hash)\n VALUES (?, ?, ?, ?, ?)`,\n ).run(fileId, agentId, relPath, mtimeMs, hash);\n\n const lines = content.split('\\n');\n const insertChunk = db.prepare(\n `INSERT INTO memory_chunks (chunk_id, file_id, start_line, end_line, content)\n VALUES (?, ?, ?, ?, ?)`,\n );\n const insertFts = db.prepare(\n `INSERT INTO memory_fts (content, chunk_id, agent_id, path, start_line, end_line)\n VALUES (?, ?, ?, ?, ?, ?)`,\n );\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (!line.trim()) continue;\n const lineNo = i + 1;\n const chunkId = `${fileId}:${lineNo}`;\n insertChunk.run(chunkId, fileId, lineNo, lineNo, line);\n insertFts.run(line, chunkId, agentId, relPath, lineNo, lineNo);\n }\n}\n\nexport function syncMemoryIndex(params: {\n agentId: string;\n workspaceDir: string;\n memoriesDir?: string;\n}): void {\n const cacheKey = `${params.agentId}:${params.workspaceDir}:${params.memoriesDir ?? ''}`;\n const now = Date.now();\n const cached = memorySyncCache.get(cacheKey);\n if (cached && now - cached.timestamp < MEMORY_SYNC_CACHE_TTL_MS) {\n return;\n }\n\n const paths = collectMemoryPaths(params.workspaceDir, params.memoriesDir);\n memorySyncCache.set(cacheKey, { timestamp: now, paths });\n runSqliteWriteTransaction((db) => {\n const seen = new Set<string>();\n for (const absPath of paths) {\n seen.add(`${params.agentId}:${displayPath(params.workspaceDir, params.memoriesDir, absPath)}`);\n indexFile(db, params.agentId, params.workspaceDir, params.memoriesDir, absPath);\n }\n\n const stale = db\n .prepare(`SELECT file_id FROM memory_files WHERE agent_id = ?`)\n .all(params.agentId) as Array<{ file_id: string }>;\n for (const row of stale) {\n if (!seen.has(row.file_id)) {\n db.prepare(\n `DELETE FROM memory_fts WHERE chunk_id IN (SELECT chunk_id FROM memory_chunks WHERE file_id = ?)`,\n ).run(row.file_id);\n db.prepare(`DELETE FROM memory_chunks WHERE file_id = ?`).run(row.file_id);\n db.prepare(`DELETE FROM memory_files WHERE file_id = ?`).run(row.file_id);\n }\n }\n });\n}\n\nexport function searchMemoryIndex(params: {\n agentId: string;\n query: string;\n maxResults?: number;\n minScore?: number;\n}): MemorySearchHit[] {\n const { agentId, query, maxResults = 5, minScore = 0.3 } = params;\n const ftsQuery = escapeFts5Query(query);\n if (!ftsQuery) {\n return [];\n }\n\n const db = getSqliteDatabase();\n const rows = db\n .prepare(\n `SELECT chunk_id, path, start_line, end_line, content, bm25(memory_fts) AS rank\n FROM memory_fts\n WHERE memory_fts MATCH ? AND agent_id = ?\n ORDER BY rank\n LIMIT ?`,\n )\n .all(ftsQuery, agentId, maxResults * 3) as Array<{\n chunk_id: string;\n path: string;\n start_line: number;\n end_line: number;\n content: string;\n rank: number;\n }>;\n\n const results: MemorySearchHit[] = [];\n for (const row of rows) {\n const score = bm25ToScore(row.rank);\n if (score < minScore) continue;\n results.push({\n path: row.path,\n lines: row.content,\n score,\n lineNumbers: [row.start_line],\n });\n }\n\n results.sort((a, b) => b.score - a.score);\n return results.slice(0, maxResults);\n}\n"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Note, NoteIndexEntry, NotesListQuery } from '../../notes/types.js';
2
+ export declare function upsertNoteRecord(note: Note): void;
3
+ export declare function getNoteRecord(noteId: string): Note | null;
4
+ export declare function deleteNoteRecord(noteId: string): boolean;
5
+ export declare function listNoteRecords(query?: NotesListQuery): {
6
+ items: NoteIndexEntry[];
7
+ total: number;
8
+ limit: number;
9
+ offset: number;
10
+ hasMore: boolean;
11
+ };
@@ -0,0 +1,191 @@
1
+ import { getSqliteDatabase, runSqliteWriteTransaction } from "./transaction.js";
2
+ import { escapeFts5Query } from "./fts.js";
3
+ import { buildNoteIndexMeta, extractAttachmentFileNames, notePlainText } from "../../notes/note-index-meta.js";
4
+ //#region src/storage/sqlite/notes-repository.ts
5
+ function parseTags(json) {
6
+ try {
7
+ const parsed = JSON.parse(json);
8
+ return Array.isArray(parsed) ? parsed.filter((t) => typeof t === "string") : [];
9
+ } catch {
10
+ return [];
11
+ }
12
+ }
13
+ function parseAttachmentNames(json) {
14
+ if (!json) return void 0;
15
+ try {
16
+ const parsed = JSON.parse(json);
17
+ return Array.isArray(parsed) ? parsed.filter((n) => typeof n === "string") : void 0;
18
+ } catch {
19
+ return;
20
+ }
21
+ }
22
+ function rowToIndexEntry(row) {
23
+ return {
24
+ id: row.note_id,
25
+ title: row.title ?? void 0,
26
+ kind: row.kind,
27
+ status: row.status,
28
+ createdAt: row.created_at,
29
+ updatedAt: row.updated_at,
30
+ pinned: row.pinned ? true : void 0,
31
+ tags: parseTags(row.tags_json),
32
+ snippet: row.snippet ?? void 0,
33
+ coverAttachmentId: row.cover_attachment_id ?? void 0,
34
+ voiceAttachmentId: row.voice_attachment_id ?? void 0,
35
+ voiceDurationSec: row.voice_duration_sec ?? void 0,
36
+ attachmentNames: parseAttachmentNames(row.attachment_names_json),
37
+ groupId: row.group_id ?? void 0,
38
+ lastOpenedAt: row.last_opened_at ?? void 0,
39
+ taskDone: row.task_done != null ? Boolean(row.task_done) : void 0,
40
+ taskDueAt: row.task_due_at ?? void 0
41
+ };
42
+ }
43
+ function noteSearchContent(note) {
44
+ const plain = notePlainText(note);
45
+ const attachmentText = note.attachments?.map((a) => a.transcript).filter(Boolean).join(" ") ?? "";
46
+ const attachmentNames = extractAttachmentFileNames(note)?.join(" ") ?? "";
47
+ return [
48
+ note.title,
49
+ plain,
50
+ attachmentText,
51
+ attachmentNames,
52
+ ...note.tags ?? []
53
+ ].filter(Boolean).join("\n");
54
+ }
55
+ function noteToRow(note) {
56
+ const meta = buildNoteIndexMeta(note);
57
+ return {
58
+ note_id: note.id,
59
+ title: note.title ?? null,
60
+ kind: note.kind,
61
+ status: note.status,
62
+ payload_json: JSON.stringify(note),
63
+ created_at: note.createdAt,
64
+ updated_at: note.updatedAt,
65
+ pinned: note.pinned ? 1 : 0,
66
+ tags_json: JSON.stringify(note.tags ?? []),
67
+ snippet: meta.snippet ?? null,
68
+ cover_attachment_id: meta.coverAttachmentId ?? null,
69
+ voice_attachment_id: meta.voiceAttachmentId ?? null,
70
+ voice_duration_sec: meta.voiceDurationSec ?? null,
71
+ attachment_names_json: meta.attachmentNames ? JSON.stringify(meta.attachmentNames) : null,
72
+ group_id: note.groupId ?? null,
73
+ last_opened_at: note.lastOpenedAt ?? null,
74
+ task_done: note.taskMeta?.done != null ? note.taskMeta.done ? 1 : 0 : null,
75
+ task_due_at: note.taskMeta?.dueAt ?? null
76
+ };
77
+ }
78
+ function upsertNoteFts(db, note) {
79
+ db.prepare(`DELETE FROM notes_fts WHERE note_id = ?`).run(note.id);
80
+ const content = noteSearchContent(note);
81
+ if (!content.trim()) return;
82
+ db.prepare(`INSERT INTO notes_fts (content, note_id) VALUES (?, ?)`).run(content, note.id);
83
+ }
84
+ function upsertNoteRecord(note) {
85
+ const row = noteToRow(note);
86
+ runSqliteWriteTransaction((db) => {
87
+ db.prepare(`INSERT INTO notes (
88
+ note_id, title, kind, status, payload_json, created_at, updated_at,
89
+ pinned, tags_json, snippet, cover_attachment_id, voice_attachment_id,
90
+ voice_duration_sec, attachment_names_json, group_id, last_opened_at,
91
+ task_done, task_due_at
92
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
93
+ ON CONFLICT(note_id) DO UPDATE SET
94
+ title = excluded.title,
95
+ kind = excluded.kind,
96
+ status = excluded.status,
97
+ payload_json = excluded.payload_json,
98
+ updated_at = excluded.updated_at,
99
+ pinned = excluded.pinned,
100
+ tags_json = excluded.tags_json,
101
+ snippet = excluded.snippet,
102
+ cover_attachment_id = excluded.cover_attachment_id,
103
+ voice_attachment_id = excluded.voice_attachment_id,
104
+ voice_duration_sec = excluded.voice_duration_sec,
105
+ attachment_names_json = excluded.attachment_names_json,
106
+ group_id = excluded.group_id,
107
+ last_opened_at = excluded.last_opened_at,
108
+ task_done = excluded.task_done,
109
+ task_due_at = excluded.task_due_at`).run(row.note_id, row.title, row.kind, row.status, row.payload_json, row.created_at, row.updated_at, row.pinned, row.tags_json, row.snippet, row.cover_attachment_id, row.voice_attachment_id, row.voice_duration_sec, row.attachment_names_json, row.group_id, row.last_opened_at, row.task_done, row.task_due_at);
110
+ upsertNoteFts(db, note);
111
+ });
112
+ }
113
+ function getNoteRecord(noteId) {
114
+ const row = getSqliteDatabase().prepare(`SELECT payload_json FROM notes WHERE note_id = ?`).get(noteId);
115
+ if (!row?.payload_json) return null;
116
+ try {
117
+ return JSON.parse(row.payload_json);
118
+ } catch {
119
+ return null;
120
+ }
121
+ }
122
+ function deleteNoteRecord(noteId) {
123
+ return runSqliteWriteTransaction((db) => {
124
+ if (!db.prepare(`SELECT note_id FROM notes WHERE note_id = ?`).get(noteId)) return false;
125
+ db.prepare(`DELETE FROM notes_fts WHERE note_id = ?`).run(noteId);
126
+ db.prepare(`DELETE FROM notes WHERE note_id = ?`).run(noteId);
127
+ return true;
128
+ });
129
+ }
130
+ function listNoteRecords(query = {}) {
131
+ const db = getSqliteDatabase();
132
+ const conditions = [];
133
+ const params = [];
134
+ if (query.status) {
135
+ conditions.push(`status = ?`);
136
+ params.push(query.status);
137
+ } else {
138
+ conditions.push(`status != ?`);
139
+ params.push("trashed");
140
+ }
141
+ if (query.kind) {
142
+ conditions.push(`kind = ?`);
143
+ params.push(query.kind);
144
+ }
145
+ if (query.pinned !== void 0) {
146
+ conditions.push(`pinned = ?`);
147
+ params.push(query.pinned ? 1 : 0);
148
+ }
149
+ if (query.groupId !== void 0) if (query.groupId === "ungrouped") conditions.push(`(group_id IS NULL OR group_id = '')`);
150
+ else {
151
+ conditions.push(`group_id = ?`);
152
+ params.push(query.groupId);
153
+ }
154
+ if (query.pendingTasksOnly) conditions.push(`kind = 'task' AND (task_done IS NULL OR task_done = 0)`);
155
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
156
+ let entries = db.prepare(`SELECT note_id, title, kind, status, payload_json, created_at, updated_at,
157
+ pinned, tags_json, snippet, cover_attachment_id, voice_attachment_id,
158
+ voice_duration_sec, attachment_names_json, group_id, last_opened_at,
159
+ task_done, task_due_at
160
+ FROM notes ${where}`).all(...params).map(rowToIndexEntry);
161
+ if (query.tag) entries = entries.filter((entry) => entry.tags?.includes(query.tag));
162
+ if (query.search) {
163
+ const ftsQuery = escapeFts5Query(query.search);
164
+ const ftsIds = /* @__PURE__ */ new Set();
165
+ if (ftsQuery) {
166
+ const ftsRows = db.prepare(`SELECT note_id FROM notes_fts WHERE notes_fts MATCH ? ORDER BY rank`).all(ftsQuery);
167
+ for (const row of ftsRows) ftsIds.add(row.note_id);
168
+ }
169
+ entries = entries.filter((entry) => ftsIds.has(entry.id));
170
+ }
171
+ const sortField = query.sortBy || "createdAt";
172
+ const sortDir = query.sortOrder === "asc" ? 1 : -1;
173
+ entries = [...entries].sort((a, b) => {
174
+ return ((a[sortField] ?? 0) - (b[sortField] ?? 0)) * sortDir;
175
+ });
176
+ const total = entries.length;
177
+ const offset = query.offset || 0;
178
+ const limit = Math.min(query.limit || 50, 200);
179
+ const items = entries.slice(offset, offset + limit);
180
+ return {
181
+ items,
182
+ total,
183
+ limit,
184
+ offset,
185
+ hasMore: offset + items.length < total
186
+ };
187
+ }
188
+ //#endregion
189
+ export { deleteNoteRecord, getNoteRecord, listNoteRecords, upsertNoteRecord };
190
+
191
+ //# sourceMappingURL=notes-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notes-repository.js","names":[],"sources":["../../../../src/storage/sqlite/notes-repository.ts"],"sourcesContent":["import type { Note, NoteIndexEntry, NotesListQuery } from '../../notes/types.js';\nimport { buildNoteIndexMeta, extractAttachmentFileNames, notePlainText } from '../../notes/note-index-meta.js';\nimport { escapeFts5Query } from './fts.js';\nimport { getSqliteDatabase, runSqliteWriteTransaction } from './transaction.js';\n\ntype NoteRow = {\n note_id: string;\n title: string | null;\n kind: string;\n status: string;\n payload_json: string;\n created_at: number;\n updated_at: number;\n pinned: number;\n tags_json: string;\n snippet: string | null;\n cover_attachment_id: string | null;\n voice_attachment_id: string | null;\n voice_duration_sec: number | null;\n attachment_names_json: string | null;\n group_id: string | null;\n last_opened_at: number | null;\n task_done: number | null;\n task_due_at: number | null;\n};\n\nfunction parseTags(json: string): string[] {\n try {\n const parsed = JSON.parse(json) as unknown;\n return Array.isArray(parsed) ? parsed.filter((t): t is string => typeof t === 'string') : [];\n } catch {\n return [];\n }\n}\n\nfunction parseAttachmentNames(json: string | null): string[] | undefined {\n if (!json) return undefined;\n try {\n const parsed = JSON.parse(json) as unknown;\n return Array.isArray(parsed) ? parsed.filter((n): n is string => typeof n === 'string') : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction rowToIndexEntry(row: NoteRow): NoteIndexEntry {\n return {\n id: row.note_id,\n title: row.title ?? undefined,\n kind: row.kind as NoteIndexEntry['kind'],\n status: row.status as NoteIndexEntry['status'],\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n pinned: row.pinned ? true : undefined,\n tags: parseTags(row.tags_json),\n snippet: row.snippet ?? undefined,\n coverAttachmentId: row.cover_attachment_id ?? undefined,\n voiceAttachmentId: row.voice_attachment_id ?? undefined,\n voiceDurationSec: row.voice_duration_sec ?? undefined,\n attachmentNames: parseAttachmentNames(row.attachment_names_json),\n groupId: row.group_id ?? undefined,\n lastOpenedAt: row.last_opened_at ?? undefined,\n taskDone: row.task_done != null ? Boolean(row.task_done) : undefined,\n taskDueAt: row.task_due_at ?? undefined,\n };\n}\n\nfunction noteSearchContent(note: Note): string {\n const plain = notePlainText(note);\n const attachmentText = note.attachments?.map((a) => a.transcript).filter(Boolean).join(' ') ?? '';\n const attachmentNames = extractAttachmentFileNames(note)?.join(' ') ?? '';\n return [note.title, plain, attachmentText, attachmentNames, ...(note.tags ?? [])].filter(Boolean).join('\\n');\n}\n\nfunction noteToRow(note: Note): Omit<NoteRow, 'payload_json'> & { payload_json: string } {\n const meta = buildNoteIndexMeta(note);\n return {\n note_id: note.id,\n title: note.title ?? null,\n kind: note.kind,\n status: note.status,\n payload_json: JSON.stringify(note),\n created_at: note.createdAt,\n updated_at: note.updatedAt,\n pinned: note.pinned ? 1 : 0,\n tags_json: JSON.stringify(note.tags ?? []),\n snippet: meta.snippet ?? null,\n cover_attachment_id: meta.coverAttachmentId ?? null,\n voice_attachment_id: meta.voiceAttachmentId ?? null,\n voice_duration_sec: meta.voiceDurationSec ?? null,\n attachment_names_json: meta.attachmentNames ? JSON.stringify(meta.attachmentNames) : null,\n group_id: note.groupId ?? null,\n last_opened_at: note.lastOpenedAt ?? null,\n task_done: note.taskMeta?.done != null ? (note.taskMeta.done ? 1 : 0) : null,\n task_due_at: note.taskMeta?.dueAt ?? null,\n };\n}\n\nfunction upsertNoteFts(db: ReturnType<typeof getSqliteDatabase>, note: Note): void {\n db.prepare(`DELETE FROM notes_fts WHERE note_id = ?`).run(note.id);\n const content = noteSearchContent(note);\n if (!content.trim()) {\n return;\n }\n db.prepare(`INSERT INTO notes_fts (content, note_id) VALUES (?, ?)`).run(content, note.id);\n}\n\nexport function upsertNoteRecord(note: Note): void {\n const row = noteToRow(note);\n runSqliteWriteTransaction((db) => {\n db.prepare(\n `INSERT INTO notes (\n note_id, title, kind, status, payload_json, created_at, updated_at,\n pinned, tags_json, snippet, cover_attachment_id, voice_attachment_id,\n voice_duration_sec, attachment_names_json, group_id, last_opened_at,\n task_done, task_due_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(note_id) DO UPDATE SET\n title = excluded.title,\n kind = excluded.kind,\n status = excluded.status,\n payload_json = excluded.payload_json,\n updated_at = excluded.updated_at,\n pinned = excluded.pinned,\n tags_json = excluded.tags_json,\n snippet = excluded.snippet,\n cover_attachment_id = excluded.cover_attachment_id,\n voice_attachment_id = excluded.voice_attachment_id,\n voice_duration_sec = excluded.voice_duration_sec,\n attachment_names_json = excluded.attachment_names_json,\n group_id = excluded.group_id,\n last_opened_at = excluded.last_opened_at,\n task_done = excluded.task_done,\n task_due_at = excluded.task_due_at`,\n ).run(\n row.note_id,\n row.title,\n row.kind,\n row.status,\n row.payload_json,\n row.created_at,\n row.updated_at,\n row.pinned,\n row.tags_json,\n row.snippet,\n row.cover_attachment_id,\n row.voice_attachment_id,\n row.voice_duration_sec,\n row.attachment_names_json,\n row.group_id,\n row.last_opened_at,\n row.task_done,\n row.task_due_at,\n );\n upsertNoteFts(db, note);\n });\n}\n\nexport function getNoteRecord(noteId: string): Note | null {\n const db = getSqliteDatabase();\n const row = db.prepare(`SELECT payload_json FROM notes WHERE note_id = ?`).get(noteId) as\n | { payload_json: string }\n | undefined;\n if (!row?.payload_json) {\n return null;\n }\n try {\n return JSON.parse(row.payload_json) as Note;\n } catch {\n return null;\n }\n}\n\nexport function deleteNoteRecord(noteId: string): boolean {\n return runSqliteWriteTransaction((db) => {\n const existing = db.prepare(`SELECT note_id FROM notes WHERE note_id = ?`).get(noteId);\n if (!existing) {\n return false;\n }\n db.prepare(`DELETE FROM notes_fts WHERE note_id = ?`).run(noteId);\n db.prepare(`DELETE FROM notes WHERE note_id = ?`).run(noteId);\n return true;\n });\n}\n\nexport function listNoteRecords(\n query: NotesListQuery = {},\n): { items: NoteIndexEntry[]; total: number; limit: number; offset: number; hasMore: boolean } {\n const db = getSqliteDatabase();\n const conditions: string[] = [];\n const params: Array<string | number> = [];\n\n if (query.status) {\n conditions.push(`status = ?`);\n params.push(query.status);\n } else {\n conditions.push(`status != ?`);\n params.push('trashed');\n }\n if (query.kind) {\n conditions.push(`kind = ?`);\n params.push(query.kind);\n }\n if (query.pinned !== undefined) {\n conditions.push(`pinned = ?`);\n params.push(query.pinned ? 1 : 0);\n }\n if (query.groupId !== undefined) {\n if (query.groupId === 'ungrouped') {\n conditions.push(`(group_id IS NULL OR group_id = '')`);\n } else {\n conditions.push(`group_id = ?`);\n params.push(query.groupId);\n }\n }\n if (query.pendingTasksOnly) {\n conditions.push(`kind = 'task' AND (task_done IS NULL OR task_done = 0)`);\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const rows = db\n .prepare(\n `SELECT note_id, title, kind, status, payload_json, created_at, updated_at,\n pinned, tags_json, snippet, cover_attachment_id, voice_attachment_id,\n voice_duration_sec, attachment_names_json, group_id, last_opened_at,\n task_done, task_due_at\n FROM notes ${where}`,\n )\n .all(...params) as NoteRow[];\n\n let entries = rows.map(rowToIndexEntry);\n\n if (query.tag) {\n entries = entries.filter((entry) => entry.tags?.includes(query.tag!));\n }\n\n if (query.search) {\n const ftsQuery = escapeFts5Query(query.search);\n const ftsIds = new Set<string>();\n if (ftsQuery) {\n const ftsRows = db\n .prepare(\n `SELECT note_id FROM notes_fts WHERE notes_fts MATCH ? ORDER BY rank`,\n )\n .all(ftsQuery) as Array<{ note_id: string }>;\n for (const row of ftsRows) {\n ftsIds.add(row.note_id);\n }\n }\n entries = entries.filter((entry) => ftsIds.has(entry.id));\n }\n\n const sortField = query.sortBy || 'createdAt';\n const sortDir = query.sortOrder === 'asc' ? 1 : -1;\n entries = [...entries].sort((a, b) => {\n const aVal = (a[sortField] as number | undefined) ?? 0;\n const bVal = (b[sortField] as number | undefined) ?? 0;\n return (aVal - bVal) * sortDir;\n });\n\n const total = entries.length;\n const offset = query.offset || 0;\n const limit = Math.min(query.limit || 50, 200);\n const items = entries.slice(offset, offset + limit);\n const hasMore = offset + items.length < total;\n\n return { items, total, limit, offset, hasMore };\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { resolveXopcDatabasePath, XOPC_DB_FILENAME } from '../../config/paths-state.js';
@@ -0,0 +1,7 @@
1
+ import { XOPC_DB_FILENAME, init_paths_state, resolveXopcDatabasePath } from "../../config/paths-state.js";
2
+ //#region src/storage/sqlite/paths.ts
3
+ init_paths_state();
4
+ //#endregion
5
+ export { XOPC_DB_FILENAME, resolveXopcDatabasePath };
6
+
7
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","names":[],"sources":["../../../../src/storage/sqlite/paths.ts"],"sourcesContent":["export { resolveXopcDatabasePath, XOPC_DB_FILENAME } from '../../config/paths-state.js';\n"],"mappings":";;kBAAwF"}
@@ -0,0 +1,82 @@
1
+ import type { AgentMessage } from '@earendil-works/pi-agent-core';
2
+ import type { SessionAgentConfig } from '../../session/config-types.js';
3
+ import { type TranscriptStoredRow } from '../../session/session-context-for-llm.js';
4
+ import { type GlobalSessionStats, type SessionMetadata } from '../../session/types.js';
5
+ export type SessionRow = {
6
+ session_key: string;
7
+ agent_id: string;
8
+ current_transcript_id: string;
9
+ status: string;
10
+ name: string | null;
11
+ tags_json: string;
12
+ created_at: number;
13
+ updated_at: number;
14
+ last_accessed_at: number;
15
+ session_started_at: number | null;
16
+ last_interaction_at: number | null;
17
+ source_channel: string;
18
+ source_chat_id: string;
19
+ session_type: string | null;
20
+ routing_json: string | null;
21
+ custom_data_json: string | null;
22
+ abort_cutoff_timestamp: number | null;
23
+ message_count: number;
24
+ estimated_tokens: number;
25
+ compacted_count: number;
26
+ thinking_level: string | null;
27
+ verbose_level: string | null;
28
+ };
29
+ export type TranscriptEntryRow = {
30
+ entry_id: string;
31
+ transcript_id: string;
32
+ seq: number;
33
+ entry_kind: string;
34
+ role: string | null;
35
+ payload_json: string;
36
+ created_at: number;
37
+ };
38
+ export type SessionConfigRow = {
39
+ session_key: string;
40
+ thinking_level: string | null;
41
+ reasoning_level: string | null;
42
+ verbose_level: string | null;
43
+ elevated_mode: string | null;
44
+ model_override: string | null;
45
+ provider_override: string | null;
46
+ working_directory_override: string | null;
47
+ updated_at: number;
48
+ };
49
+ export declare function sessionRowToMetadata(sessionKey: string, row: SessionRow): SessionMetadata;
50
+ export declare function metadataToSessionInsert(sessionKey: string, transcriptId: string, metadata: SessionMetadata, thinkingLevel?: string | null, verboseLevel?: string | null): {
51
+ sessionKey: string;
52
+ agentId: string;
53
+ transcriptId: string;
54
+ status: string;
55
+ name: string | null;
56
+ tagsJson: string;
57
+ createdAt: number;
58
+ updatedAt: number;
59
+ lastAccessedAt: number;
60
+ sessionStartedAt: number | null;
61
+ lastInteractionAt: number | null;
62
+ sourceChannel: string;
63
+ sourceChatId: string;
64
+ sessionType: string | null;
65
+ routingJson: string | null;
66
+ customDataJson: string | null;
67
+ abortCutoffTimestamp: number | null;
68
+ messageCount: number;
69
+ estimatedTokens: number;
70
+ compactedCount: number;
71
+ thinkingLevel: string | null;
72
+ verboseLevel: string | null;
73
+ };
74
+ export declare function sessionConfigRowToConfig(row: SessionConfigRow): SessionAgentConfig;
75
+ export declare function transcriptEntryRowToStoredRow(row: TranscriptEntryRow): TranscriptStoredRow;
76
+ export declare function classifyStoredRow(row: TranscriptStoredRow): {
77
+ entryKind: 'message' | 'context' | 'compaction';
78
+ role: string | null;
79
+ };
80
+ export declare function extractFtsContent(row: TranscriptStoredRow): string;
81
+ export declare function estimateTokensFromMessages(messages: AgentMessage[]): number;
82
+ export declare function buildGlobalSessionStats(sessions: SessionMetadata[]): GlobalSessionStats;
@@ -0,0 +1,164 @@
1
+ import "../../session/types.js";
2
+ import { buildDefaultSessionMetadata, parseSessionKeySource, resolveAgentIdFromSessionKey } from "./session-metadata.js";
3
+ import { isTranscriptContextEntry } from "../../session/session-context-for-llm.js";
4
+ //#region src/storage/sqlite/row-mappers.ts
5
+ function parseJson(raw) {
6
+ if (!raw?.trim()) return;
7
+ try {
8
+ return JSON.parse(raw);
9
+ } catch {
10
+ return;
11
+ }
12
+ }
13
+ function isoFromMs(ms) {
14
+ if (ms == null || !Number.isFinite(ms)) return;
15
+ return new Date(ms).toISOString();
16
+ }
17
+ function sessionRowToMetadata(sessionKey, row) {
18
+ const defaults = buildDefaultSessionMetadata(sessionKey);
19
+ const { channel: keySource, chatId: keyChatId } = parseSessionKeySource(sessionKey);
20
+ const routing = parseJson(row.routing_json) ?? defaults.routing;
21
+ const customData = parseJson(row.custom_data_json) ?? defaults.customData;
22
+ const tags = parseJson(row.tags_json) ?? [];
23
+ const createdAt = isoFromMs(row.created_at) ?? defaults.createdAt;
24
+ const updatedAt = isoFromMs(row.updated_at) ?? defaults.updatedAt;
25
+ const lastAccessedAt = isoFromMs(row.last_accessed_at) ?? defaults.lastAccessedAt;
26
+ const diskSc = row.source_channel?.trim() ?? "";
27
+ const diskChat = row.source_chat_id?.trim() ?? "";
28
+ return {
29
+ ...defaults,
30
+ key: sessionKey,
31
+ status: row.status,
32
+ name: row.name ?? void 0,
33
+ tags,
34
+ createdAt,
35
+ updatedAt,
36
+ lastAccessedAt,
37
+ sessionStartedAt: isoFromMs(row.session_started_at),
38
+ lastInteractionAt: isoFromMs(row.last_interaction_at),
39
+ sourceChannel: diskSc || keySource,
40
+ sourceChatId: diskChat || keyChatId,
41
+ sessionType: row.session_type ?? defaults.sessionType,
42
+ routing,
43
+ customData,
44
+ abortCutoffTimestamp: row.abort_cutoff_timestamp ?? void 0,
45
+ messageCount: row.message_count,
46
+ estimatedTokens: row.estimated_tokens,
47
+ compactedCount: row.compacted_count,
48
+ transcriptId: row.current_transcript_id,
49
+ stats: {
50
+ messageCount: row.message_count,
51
+ tokenCount: row.estimated_tokens,
52
+ lastTurnAt: row.last_interaction_at ?? void 0
53
+ }
54
+ };
55
+ }
56
+ function metadataToSessionInsert(sessionKey, transcriptId, metadata, thinkingLevel, verboseLevel) {
57
+ const now = Date.now();
58
+ return {
59
+ sessionKey,
60
+ agentId: resolveAgentIdFromSessionKey(sessionKey),
61
+ transcriptId,
62
+ status: metadata.status,
63
+ name: metadata.name ?? null,
64
+ tagsJson: JSON.stringify(metadata.tags ?? []),
65
+ createdAt: Date.parse(metadata.createdAt) || now,
66
+ updatedAt: Date.parse(metadata.updatedAt) || now,
67
+ lastAccessedAt: Date.parse(metadata.lastAccessedAt) || now,
68
+ sessionStartedAt: metadata.sessionStartedAt ? Date.parse(metadata.sessionStartedAt) : now,
69
+ lastInteractionAt: metadata.lastInteractionAt ? Date.parse(metadata.lastInteractionAt) : null,
70
+ sourceChannel: metadata.sourceChannel,
71
+ sourceChatId: metadata.sourceChatId,
72
+ sessionType: metadata.sessionType ?? null,
73
+ routingJson: metadata.routing ? JSON.stringify(metadata.routing) : null,
74
+ customDataJson: metadata.customData ? JSON.stringify(metadata.customData) : null,
75
+ abortCutoffTimestamp: metadata.abortCutoffTimestamp ?? null,
76
+ messageCount: metadata.messageCount,
77
+ estimatedTokens: metadata.estimatedTokens,
78
+ compactedCount: metadata.compactedCount,
79
+ thinkingLevel: thinkingLevel ?? null,
80
+ verboseLevel: verboseLevel ?? null
81
+ };
82
+ }
83
+ function sessionConfigRowToConfig(row) {
84
+ return {
85
+ ...row.thinking_level ? { thinkingLevel: row.thinking_level } : {},
86
+ ...row.reasoning_level ? { reasoningLevel: row.reasoning_level } : {},
87
+ ...row.verbose_level ? { verboseLevel: row.verbose_level } : {},
88
+ ...row.elevated_mode ? { elevatedMode: row.elevated_mode } : {},
89
+ ...row.model_override ? { modelOverride: row.model_override } : {},
90
+ ...row.provider_override ? { providerOverride: row.provider_override } : {},
91
+ ...row.working_directory_override ? { workingDirectoryOverride: row.working_directory_override } : {},
92
+ updatedAt: row.updated_at
93
+ };
94
+ }
95
+ function transcriptEntryRowToStoredRow(row) {
96
+ return JSON.parse(row.payload_json);
97
+ }
98
+ function classifyStoredRow(row) {
99
+ if (isTranscriptContextEntry(row)) return {
100
+ entryKind: "context",
101
+ role: null
102
+ };
103
+ const record = row;
104
+ if (record.type === "compaction" || row.kind === "compaction") return {
105
+ entryKind: "compaction",
106
+ role: null
107
+ };
108
+ return {
109
+ entryKind: "message",
110
+ role: record.role ?? null
111
+ };
112
+ }
113
+ function extractFtsContent(row) {
114
+ if (isTranscriptContextEntry(row)) {
115
+ const ctx = row;
116
+ return [ctx.text, ctx.id].filter(Boolean).join(" ");
117
+ }
118
+ return extractTextFromMessageContent(row.content);
119
+ }
120
+ function extractTextFromMessageContent(content) {
121
+ if (typeof content === "string") return content;
122
+ if (!Array.isArray(content)) return "";
123
+ const parts = [];
124
+ for (const block of content) {
125
+ if (!block || typeof block !== "object") continue;
126
+ if (block.type === "text" && typeof block.text === "string") parts.push(block.text);
127
+ }
128
+ return parts.join("\n");
129
+ }
130
+ function estimateTokensFromMessages(messages) {
131
+ let total = 0;
132
+ for (const msg of messages) {
133
+ const content = msg.content;
134
+ const text = extractTextFromMessageContent(content);
135
+ total += Math.ceil(text.length / 4);
136
+ }
137
+ return total;
138
+ }
139
+ function buildGlobalSessionStats(sessions) {
140
+ const byChannel = {};
141
+ for (const session of sessions) byChannel[session.sourceChannel] = (byChannel[session.sourceChannel] || 0) + 1;
142
+ let oldestSession;
143
+ let newestSession;
144
+ if (sessions.length > 0) {
145
+ const sorted = [...sessions].sort((a, b) => a.createdAt.localeCompare(b.createdAt));
146
+ oldestSession = sorted[0].createdAt;
147
+ newestSession = sorted[sorted.length - 1].createdAt;
148
+ }
149
+ return {
150
+ totalSessions: sessions.length,
151
+ activeSessions: sessions.filter((s) => s.status === "active" || s.status === "idle").length,
152
+ archivedSessions: sessions.filter((s) => s.status === "archived").length,
153
+ pinnedSessions: sessions.filter((s) => s.status === "pinned").length,
154
+ totalMessages: sessions.reduce((sum, s) => sum + s.messageCount, 0),
155
+ totalTokens: sessions.reduce((sum, s) => sum + s.estimatedTokens, 0),
156
+ oldestSession,
157
+ newestSession,
158
+ byChannel
159
+ };
160
+ }
161
+ //#endregion
162
+ export { buildGlobalSessionStats, classifyStoredRow, estimateTokensFromMessages, extractFtsContent, metadataToSessionInsert, sessionConfigRowToConfig, sessionRowToMetadata, transcriptEntryRowToStoredRow };
163
+
164
+ //# sourceMappingURL=row-mappers.js.map