@tekmidian/pai 0.54.1 → 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. package/dist/{aibroker-client-CNfIBrl5.mjs → aibroker-client-B8Wtasez.mjs} +1 -1
  2. package/dist/{aibroker-client-DzkTpVjx.mjs → aibroker-client-BK1h--W_.mjs} +3 -3
  3. package/dist/{aibroker-client-DzkTpVjx.mjs.map → aibroker-client-BK1h--W_.mjs.map} +1 -1
  4. package/dist/{indexer-backend-CdvCJCkD.mjs → async-CLvuY7b-.mjs} +7 -7
  5. package/dist/async-CLvuY7b-.mjs.map +1 -0
  6. package/dist/auto-route-CF8WNaoy.mjs +100 -0
  7. package/dist/auto-route-CF8WNaoy.mjs.map +1 -0
  8. package/dist/{chain-CZKlI0hq.mjs → chain-DogidBji.mjs} +4 -4
  9. package/dist/{chain-CZKlI0hq.mjs.map → chain-DogidBji.mjs.map} +1 -1
  10. package/dist/cli/index.mjs +22 -23
  11. package/dist/cli/index.mjs.map +1 -1
  12. package/dist/cli/program.d.mts.map +1 -1
  13. package/dist/cli/program.mjs +22 -23
  14. package/dist/{clusters-Cw_P6lO-.mjs → clusters-Ci1mseh2.mjs} +4 -36
  15. package/dist/clusters-Ci1mseh2.mjs.map +1 -0
  16. package/dist/{config-B3EPzRjf.mjs → config-B93YS8tP.mjs} +3 -3
  17. package/dist/{config-B3EPzRjf.mjs.map → config-B93YS8tP.mjs.map} +1 -1
  18. package/dist/{config-Bn9jpblO.mjs → config-D1omG_UU.mjs} +3 -3
  19. package/dist/{config-Bn9jpblO.mjs.map → config-D1omG_UU.mjs.map} +1 -1
  20. package/dist/{config-RjeVGJ7K.mjs → config-DCYWFaEi.mjs} +1 -1
  21. package/dist/{context-handover-cache-CXyH6QsC.mjs → context-handover-cache-k2kWbE6G.mjs} +82 -99
  22. package/dist/context-handover-cache-k2kWbE6G.mjs.map +1 -0
  23. package/dist/daemon/index.mjs +18 -24
  24. package/dist/daemon/index.mjs.map +1 -1
  25. package/dist/daemon-B7Y8GQnt.mjs +19 -0
  26. package/dist/{daemon-aJTxzg20.mjs → daemon-Cgrdvdo6.mjs} +97 -466
  27. package/dist/daemon-Cgrdvdo6.mjs.map +1 -0
  28. package/dist/daemon-mcp/index.mjs +10 -10
  29. package/dist/daemon-mcp/index.mjs.map +1 -1
  30. package/dist/{detector-DWXkeTlk.mjs → detector-3g7XuU1r.mjs} +5 -12
  31. package/dist/detector-3g7XuU1r.mjs.map +1 -0
  32. package/dist/detector-DgDn56j-.mjs +3 -0
  33. package/dist/{embeddings-ClqKtLZ8.mjs → embeddings-BNv3TQC5.mjs} +1 -1
  34. package/dist/{embeddings-DvRKcQyt.mjs → embeddings-DfrYNIng.mjs} +1 -1
  35. package/dist/{embeddings-DvRKcQyt.mjs.map → embeddings-DfrYNIng.mjs.map} +1 -1
  36. package/dist/factory-C9wGUe30.mjs +3 -0
  37. package/dist/factory-DiuntvwG.mjs +250 -0
  38. package/dist/factory-DiuntvwG.mjs.map +1 -0
  39. package/dist/{fallback-CCFIpPha.mjs → fallback-DS6AEJsU.mjs} +190 -132
  40. package/dist/fallback-DS6AEJsU.mjs.map +1 -0
  41. package/dist/federation-db-CJDw_Pwq.mjs +3 -0
  42. package/dist/{db-DJ8rk0VM.mjs → federation-db-w8e-sKjp.mjs} +5 -5
  43. package/dist/federation-db-w8e-sKjp.mjs.map +1 -0
  44. package/dist/{helpers-crDEr6S2.mjs → helpers-D9WkIf9R.mjs} +1 -1
  45. package/dist/{helpers-crDEr6S2.mjs.map → helpers-D9WkIf9R.mjs.map} +1 -1
  46. package/dist/hooks/capture-all-events.mjs.map +1 -1
  47. package/dist/hooks/capture-session-summary.mjs.map +1 -1
  48. package/dist/hooks/capture-tool-output.mjs.map +1 -1
  49. package/dist/hooks/context-compression-hook.mjs.map +1 -1
  50. package/dist/hooks/load-core-context.mjs +5 -0
  51. package/dist/hooks/load-core-context.mjs.map +2 -2
  52. package/dist/hooks/load-project-context.mjs.map +1 -1
  53. package/dist/hooks/post-compact-inject.mjs.map +1 -1
  54. package/dist/hooks/route-agents-to-worker.mjs.map +1 -1
  55. package/dist/hooks/route-edits-to-worker.mjs +1 -1
  56. package/dist/hooks/route-edits-to-worker.mjs.map +2 -2
  57. package/dist/hooks/security-validator.mjs +8367 -19
  58. package/dist/hooks/security-validator.mjs.map +4 -4
  59. package/dist/hooks/stop-hook.mjs.map +2 -2
  60. package/dist/hooks/whisper-rules.mjs.map +2 -2
  61. package/dist/hooks/worker-proxy.mjs.map +1 -1
  62. package/dist/hooks/worker-status-line.mjs.map +2 -2
  63. package/dist/hooks/worker-supervision.mjs.map +1 -1
  64. package/dist/index.d.mts +327 -100
  65. package/dist/index.d.mts.map +1 -1
  66. package/dist/index.mjs +7 -11
  67. package/dist/indexer-backend-Cc-_NK3q.mjs +1 -0
  68. package/dist/indexer-backend-DcDtin1O.mjs +5 -0
  69. package/dist/{ipc-client-C6NryMMb.mjs → ipc-client-Dasm515c.mjs} +2 -2
  70. package/dist/{ipc-client-C6NryMMb.mjs.map → ipc-client-Dasm515c.mjs.map} +1 -1
  71. package/dist/kg-entity-Cj8Q6YmU.mjs +29 -0
  72. package/dist/kg-entity-Cj8Q6YmU.mjs.map +1 -0
  73. package/dist/{latent-ideas-BfL4nCQ3.mjs → latent-ideas-BRy6HNwg.mjs} +4 -4
  74. package/dist/{latent-ideas-BfL4nCQ3.mjs.map → latent-ideas-BRy6HNwg.mjs.map} +1 -1
  75. package/dist/{link-boost-C5PaNdzm.mjs → link-boost-BptbAPuv.mjs} +1 -1
  76. package/dist/{link-boost-C5PaNdzm.mjs.map → link-boost-BptbAPuv.mjs.map} +1 -1
  77. package/dist/{main-resolver-Bt1f6jJc.mjs → main-resolver-Dx-pxic1.mjs} +56 -31
  78. package/dist/main-resolver-Dx-pxic1.mjs.map +1 -0
  79. package/dist/main-resolver-uDtK9p6e.mjs +7 -0
  80. package/dist/merge-BncjJTfb.mjs +3 -0
  81. package/dist/merge-xoyfZQ4W.mjs +6 -0
  82. package/dist/merge-xoyfZQ4W.mjs.map +1 -0
  83. package/dist/{migrate-CfERwXhY.mjs → migrate-BD7D8EEh.mjs} +21 -54
  84. package/dist/migrate-BD7D8EEh.mjs.map +1 -0
  85. package/dist/{neighborhood-CETR_P4y.mjs → neighborhood-D8uscnGy.mjs} +4 -25
  86. package/dist/neighborhood-D8uscnGy.mjs.map +1 -0
  87. package/dist/{note-context-DCcRWBoN.mjs → note-context-CgffaUMh.mjs} +3 -23
  88. package/dist/note-context-CgffaUMh.mjs.map +1 -0
  89. package/dist/{pai-home-ChAOupZc.mjs → pai-home-CeOIYltV.mjs} +2 -2
  90. package/dist/pai-home-CeOIYltV.mjs.map +1 -0
  91. package/dist/{pai-marker-B20KqhA8.mjs → pai-marker-D1MMswkz.mjs} +1 -1
  92. package/dist/{pai-marker-B20KqhA8.mjs.map → pai-marker-D1MMswkz.mjs.map} +1 -1
  93. package/dist/{planner-D3keWys5.mjs → planner-C2wWnZrZ.mjs} +7 -7
  94. package/dist/{planner-D3keWys5.mjs.map → planner-C2wWnZrZ.mjs.map} +1 -1
  95. package/dist/{postgres-CUSXWgTG.mjs → postgres-nvU5pShF.mjs} +863 -4
  96. package/dist/postgres-nvU5pShF.mjs.map +1 -0
  97. package/dist/{program-B3eRMhff.mjs → program-Cb-9J5Ie.mjs} +2260 -1399
  98. package/dist/program-Cb-9J5Ie.mjs.map +1 -0
  99. package/dist/query-feedback-COYCnvHQ.mjs +3 -0
  100. package/dist/{query-feedback-CTs_jx6i.mjs → query-feedback-xz5axTj3.mjs} +3 -3
  101. package/dist/query-feedback-xz5axTj3.mjs.map +1 -0
  102. package/dist/{db-Ddns80yf.mjs → registry-db-Bkpbp7Gf.mjs} +5 -5
  103. package/dist/registry-db-Bkpbp7Gf.mjs.map +1 -0
  104. package/dist/registry-db-DwXpf7yF.mjs +3 -0
  105. package/dist/registry-postgres-B07-hmn8.mjs +795 -0
  106. package/dist/registry-postgres-B07-hmn8.mjs.map +1 -0
  107. package/dist/registry-sqlite-CkGND_tm.mjs +593 -0
  108. package/dist/registry-sqlite-CkGND_tm.mjs.map +1 -0
  109. package/dist/{reranker-B5qUTamW.mjs → reranker-BS5gqGeF.mjs} +1 -1
  110. package/dist/{reranker-HHmhZk6v.mjs → reranker-CRVawoEh.mjs} +1 -1
  111. package/dist/{reranker-HHmhZk6v.mjs.map → reranker-CRVawoEh.mjs.map} +1 -1
  112. package/dist/router-BXOf_e9e.mjs +3 -0
  113. package/dist/{router-DBAZfE7X.mjs → router-BdxdsAvs.mjs} +2 -2
  114. package/dist/{router-DBAZfE7X.mjs.map → router-BdxdsAvs.mjs.map} +1 -1
  115. package/dist/{run-DLG25bzt.mjs → run-DkTrZejF.mjs} +234 -49
  116. package/dist/run-DkTrZejF.mjs.map +1 -0
  117. package/dist/{runtime-paths-B0P1TvUr.mjs → runtime-paths-BRwDeBEg.mjs} +1 -1
  118. package/dist/{runtime-paths-B0P1TvUr.mjs.map → runtime-paths-BRwDeBEg.mjs.map} +1 -1
  119. package/dist/search-BQHL5wDr.mjs +3 -0
  120. package/dist/search-BaTbyWjK.mjs +107 -0
  121. package/dist/search-BaTbyWjK.mjs.map +1 -0
  122. package/dist/{server-CGiHdaUp.mjs → server-CGuZFOeR.mjs} +4 -4
  123. package/dist/{server-CGiHdaUp.mjs.map → server-CGuZFOeR.mjs.map} +1 -1
  124. package/dist/{session-keepalive-DklS8VmU.mjs → session-keepalive-C5_69Av6.mjs} +7 -7
  125. package/dist/{session-keepalive-DklS8VmU.mjs.map → session-keepalive-C5_69Av6.mjs.map} +1 -1
  126. package/dist/skills/Plan/SKILL.md +1 -1
  127. package/dist/{sources-KBGEA_E6.mjs → sources-BBe3AZ-W.mjs} +8 -27
  128. package/dist/sources-BBe3AZ-W.mjs.map +1 -0
  129. package/dist/sqlite-D9p5a4qe.mjs +935 -0
  130. package/dist/sqlite-D9p5a4qe.mjs.map +1 -0
  131. package/dist/state-CwlGAKgF.mjs +3 -0
  132. package/dist/{state-DwrsOoMi.mjs → state-n13uPK5B.mjs} +6 -5
  133. package/dist/state-n13uPK5B.mjs.map +1 -0
  134. package/dist/{stop-words-BaMEGVeY.mjs → stop-words-ClCwO8mZ.mjs} +1 -1
  135. package/dist/{stop-words-BaMEGVeY.mjs.map → stop-words-ClCwO8mZ.mjs.map} +1 -1
  136. package/dist/{themes-BVoAnLZj.mjs → themes-B2v7RNnA.mjs} +3 -3
  137. package/dist/{themes-BVoAnLZj.mjs.map → themes-B2v7RNnA.mjs.map} +1 -1
  138. package/dist/{tools-BEqiJt_j.mjs → tools-Diro2s8J.mjs} +157 -398
  139. package/dist/tools-Diro2s8J.mjs.map +1 -0
  140. package/dist/{tools-BwsOTmjh.mjs → tools-KgL1rkPD.mjs} +4 -4
  141. package/dist/{trace-Cy8quQTm.mjs → trace-BRflVyBi.mjs} +1 -1
  142. package/dist/{trace-Cy8quQTm.mjs.map → trace-BRflVyBi.mjs.map} +1 -1
  143. package/dist/{utils-BD8g8oSf.mjs → utils-BrX9FLeK.mjs} +1 -1
  144. package/dist/{utils-CJymHkYm.mjs → utils-C9HsYDpO.mjs} +1 -1
  145. package/dist/{utils-CJymHkYm.mjs.map → utils-C9HsYDpO.mjs.map} +1 -1
  146. package/dist/{vault-indexer-C5i-OAyr.mjs → vault-indexer-DHYBpRZ5.mjs} +2 -2
  147. package/dist/{vault-indexer-C5i-OAyr.mjs.map → vault-indexer-DHYBpRZ5.mjs.map} +1 -1
  148. package/dist/{wakeup-Yk5lQ0jb.mjs → wakeup-D0uvqLsE.mjs} +95 -4
  149. package/dist/wakeup-D0uvqLsE.mjs.map +1 -0
  150. package/dist/work-queue-worker-DEbWsrDQ.mjs +11 -0
  151. package/dist/{work-queue-worker-utPp4hUv.mjs → work-queue-worker-DufMOtrL.mjs} +9 -9
  152. package/dist/work-queue-worker-DufMOtrL.mjs.map +1 -0
  153. package/dist/{zettelkasten-DezbXghl.mjs → zettelkasten-BPxSOalU.mjs} +4 -4
  154. package/dist/{zettelkasten-DezbXghl.mjs.map → zettelkasten-BPxSOalU.mjs.map} +1 -1
  155. package/docker/init.sql +5 -1
  156. package/docs/commands/README.md +5 -0
  157. package/docs/commands/audit.md +1 -1
  158. package/docs/commands/backup.md +1 -1
  159. package/docs/commands/clear-names.md +1 -1
  160. package/docs/commands/config.md +4 -4
  161. package/docs/commands/daemon.md +1 -1
  162. package/docs/commands/db.md +15 -1
  163. package/docs/commands/end.md +1 -1
  164. package/docs/commands/help.md +1 -1
  165. package/docs/commands/hooks-db.md +47 -0
  166. package/docs/commands/identity.md +1 -1
  167. package/docs/commands/kg.md +1 -1
  168. package/docs/commands/launch.md +1 -1
  169. package/docs/commands/mcp.md +1 -1
  170. package/docs/commands/memory.md +1 -1
  171. package/docs/commands/notify.md +1 -1
  172. package/docs/commands/observation.md +1 -1
  173. package/docs/commands/obsidian.md +1 -1
  174. package/docs/commands/pause.md +1 -1
  175. package/docs/commands/project.md +1 -1
  176. package/docs/commands/projects.md +1 -1
  177. package/docs/commands/registry.md +1 -1
  178. package/docs/commands/restore.md +1 -1
  179. package/docs/commands/session.md +2 -2
  180. package/docs/commands/sessions.md +1 -1
  181. package/docs/commands/setup.md +1 -1
  182. package/docs/commands/shell-init.md +1 -1
  183. package/docs/commands/skill.md +1 -1
  184. package/docs/commands/task.md +1 -1
  185. package/docs/commands/topic.md +1 -1
  186. package/docs/commands/update.md +1 -1
  187. package/docs/commands/worker.md +1 -1
  188. package/docs/commands/zettel.md +1 -1
  189. package/docs/design/postgres-only.md +438 -0
  190. package/docs/design/registry-method-map.md +174 -0
  191. package/package.json +1 -1
  192. package/src/hooks/pre-compact.sh +2 -40
  193. package/src/hooks/session-hooks-db.test.ts +93 -0
  194. package/src/hooks/session-stop.sh +2 -26
  195. package/src/hooks/ts/lib/edit-gate.test.ts +9 -0
  196. package/src/hooks/ts/lib/edit-gate.ts +5 -2
  197. package/src/hooks/ts/lib/plutil-guard.test.ts +54 -0
  198. package/src/hooks/ts/lib/plutil-guard.ts +43 -0
  199. package/src/hooks/ts/lib/worker-git-guard.test.ts +134 -0
  200. package/src/hooks/ts/lib/worker-git-guard.ts +103 -0
  201. package/src/hooks/ts/pre-tool-use/security-validator.test.ts +68 -0
  202. package/src/hooks/ts/pre-tool-use/security-validator.ts +69 -21
  203. package/src/hooks/ts/session-start/load-core-context.ts +13 -0
  204. package/src/hooks/ts/session-start/session-start-worker-guard.test.ts +13 -0
  205. package/dist/auto-route-CcD0OWWB.mjs +0 -86
  206. package/dist/auto-route-CcD0OWWB.mjs.map +0 -1
  207. package/dist/clusters-Cw_P6lO-.mjs.map +0 -1
  208. package/dist/context-handover-cache-CXyH6QsC.mjs.map +0 -1
  209. package/dist/daemon-CknQ6YGZ.mjs +0 -25
  210. package/dist/daemon-aJTxzg20.mjs.map +0 -1
  211. package/dist/db-BOBfewFH.mjs +0 -3
  212. package/dist/db-DJ8rk0VM.mjs.map +0 -1
  213. package/dist/db-DbY2O8QO.mjs +0 -3
  214. package/dist/db-Ddns80yf.mjs.map +0 -1
  215. package/dist/detect-Bf2z-oKB.mjs +0 -86
  216. package/dist/detect-Bf2z-oKB.mjs.map +0 -1
  217. package/dist/detector-CkwkXuGh.mjs +0 -5
  218. package/dist/detector-DWXkeTlk.mjs.map +0 -1
  219. package/dist/factory-Ba8j9K7q.mjs +0 -3
  220. package/dist/factory-Bt7TWQje.mjs +0 -150
  221. package/dist/factory-Bt7TWQje.mjs.map +0 -1
  222. package/dist/fallback-CCFIpPha.mjs.map +0 -1
  223. package/dist/indexer-backend-CdvCJCkD.mjs.map +0 -1
  224. package/dist/kg-entity-BSW7ra8i.mjs +0 -176
  225. package/dist/kg-entity-BSW7ra8i.mjs.map +0 -1
  226. package/dist/main-resolver-Bt1f6jJc.mjs.map +0 -1
  227. package/dist/main-resolver-DYHhw5Ig.mjs +0 -7
  228. package/dist/migrate-CfERwXhY.mjs.map +0 -1
  229. package/dist/neighborhood-CETR_P4y.mjs.map +0 -1
  230. package/dist/note-context-DCcRWBoN.mjs.map +0 -1
  231. package/dist/pai-home-ChAOupZc.mjs.map +0 -1
  232. package/dist/postgres-CUSXWgTG.mjs.map +0 -1
  233. package/dist/program-B3eRMhff.mjs.map +0 -1
  234. package/dist/query-feedback-Bm6XvCmg.mjs +0 -3
  235. package/dist/query-feedback-CTs_jx6i.mjs.map +0 -1
  236. package/dist/router-CremHKTI.mjs +0 -3
  237. package/dist/run-DLG25bzt.mjs.map +0 -1
  238. package/dist/search-B69cQwDB.mjs +0 -303
  239. package/dist/search-B69cQwDB.mjs.map +0 -1
  240. package/dist/search-fb-5ovj4.mjs +0 -4
  241. package/dist/sources-KBGEA_E6.mjs.map +0 -1
  242. package/dist/sqlite-By6r2YhZ.mjs +0 -271
  243. package/dist/sqlite-By6r2YhZ.mjs.map +0 -1
  244. package/dist/state-Ca0ltLgI.mjs +0 -3
  245. package/dist/state-DwrsOoMi.mjs.map +0 -1
  246. package/dist/sync-Btcb6xA4.mjs +0 -310
  247. package/dist/sync-Btcb6xA4.mjs.map +0 -1
  248. package/dist/tools-BEqiJt_j.mjs.map +0 -1
  249. package/dist/wakeup-Yk5lQ0jb.mjs.map +0 -1
  250. package/dist/work-queue-worker-DsdJx-jn.mjs +0 -14
  251. package/dist/work-queue-worker-utPp4hUv.mjs.map +0 -1
@@ -1,20 +1,16 @@
1
- import { n as openRegistry } from "./db-Ddns80yf.mjs";
2
- import { r as openFederation } from "./db-DJ8rk0VM.mjs";
3
- import { d as sha256 } from "./helpers-crDEr6S2.mjs";
4
- import { n as indexAll } from "./sync-Btcb6xA4.mjs";
5
- import { t as configureEmbeddingModel } from "./embeddings-DvRKcQyt.mjs";
6
- import { a as enqueue, c as loadQueue, o as getStats } from "./context-handover-cache-CXyH6QsC.mjs";
7
- import { S as DEFAULT_NOTIFICATION_CONFIG, d as readMainConfigRaw, f as writeMainConfigRaw } from "./config-Bn9jpblO.mjs";
8
- import { C as readWorkersSection } from "./config-B3EPzRjf.mjs";
9
- import { F as loadStatuses, L as nowStamp, M as isChatPane, P as loadStatus, T as appendLedger, g as itermForClaudeSession, k as alive, n as runWorker } from "./run-DLG25bzt.mjs";
10
- import { n as runSessionKeepaliveTick } from "./session-keepalive-DklS8VmU.mjs";
11
- import { n as getBackendOutage, t as createStorageBackend } from "./factory-Bt7TWQje.mjs";
12
- import { _ as ledgerPath, b as workersLogDir, g as eventsPath } from "./server-CGiHdaUp.mjs";
13
- import { A as vaultIndexInProgress, C as setShutdownRequested, D as shutdownRequested, E as setVaultIndexInProgress, O as startTime, S as setRegistryDb, T as setStorageBackend, _ as setIndexSchedulerTimer, a as indexInProgress, b as setLastVaultIndexTime, c as lastIndexTime, d as registryDb, f as setCacheKeepaliveTimer, g as setIndexInProgress, h as setEmbedSchedulerTimer, i as embedSchedulerTimer, k as storageBackend, l as lastVaultIndexTime, m as setEmbedInProgress, n as daemonConfig, o as indexSchedulerTimer, p as setDaemonConfig, r as embedInProgress, s as lastEmbedTime, t as cacheKeepaliveTimer, u as notificationConfig, v as setLastEmbedTime, w as setStartTime, x as setNotificationConfig, y as setLastIndexTime } from "./state-DwrsOoMi.mjs";
14
- import { t as routeNotification } from "./router-DBAZfE7X.mjs";
15
- import { C as toolProjectInfo, D as toolMemoryGet, O as toolMemorySearch, S as toolProjectHealth, T as toolProjectTodo, a as toolMemoryWakeup, b as toolSessionRoute, i as toolMemoryTaxonomy, n as toolMemoryFeedback, t as toolMemoryKgSearch, v as toolRegistrySearch, w as toolProjectList, x as toolProjectDetect, y as toolSessionList } from "./tools-BEqiJt_j.mjs";
16
- import { t as detectTopicShift } from "./detector-DWXkeTlk.mjs";
17
- import { i as stopWorker, n as notifyNewWork, r as startWorker } from "./work-queue-worker-utPp4hUv.mjs";
1
+ import { n as createRegistryBackend, o as getBackendOutage, r as createStorageBackend } from "./factory-DiuntvwG.mjs";
2
+ import { a as enqueue, c as loadQueue, o as getStats } from "./context-handover-cache-k2kWbE6G.mjs";
3
+ import { S as DEFAULT_NOTIFICATION_CONFIG, d as readMainConfigRaw, f as writeMainConfigRaw } from "./config-D1omG_UU.mjs";
4
+ import { C as readWorkersSection } from "./config-B93YS8tP.mjs";
5
+ import { F as loadStatus, I as loadStatuses, N as isChatPane, R as nowStamp, T as appendLedger, g as itermForClaudeSession, k as alive, n as runWorker } from "./run-DkTrZejF.mjs";
6
+ import { _ as ledgerPath, b as workersLogDir, g as eventsPath } from "./server-CGuZFOeR.mjs";
7
+ import { A as vaultIndexInProgress, C as setShutdownRequested, D as shutdownRequested, E as setVaultIndexInProgress, O as startTime, S as setRegistryBackend, T as setStorageBackend, _ as setIndexSchedulerTimer, a as indexInProgress, b as setLastVaultIndexTime, c as lastIndexTime, d as registryBackend, f as setCacheKeepaliveTimer, g as setIndexInProgress, h as setEmbedSchedulerTimer, i as embedSchedulerTimer, k as storageBackend, l as lastVaultIndexTime, m as setEmbedInProgress, n as daemonConfig, o as indexSchedulerTimer, p as setDaemonConfig, r as embedInProgress, s as lastEmbedTime, t as cacheKeepaliveTimer, u as notificationConfig, v as setLastEmbedTime, w as setStartTime, x as setNotificationConfig, y as setLastIndexTime } from "./state-n13uPK5B.mjs";
8
+ import { n as runSessionKeepaliveTick } from "./session-keepalive-C5_69Av6.mjs";
9
+ import { t as configureEmbeddingModel } from "./embeddings-DfrYNIng.mjs";
10
+ import { t as routeNotification } from "./router-BdxdsAvs.mjs";
11
+ import { C as toolProjectInfo, D as toolMemoryGet, O as toolMemorySearch, S as toolProjectHealth, T as toolProjectTodo, a as toolMemoryWakeup, b as toolSessionRoute, i as toolMemoryTaxonomy, n as toolMemoryFeedback, t as toolMemoryKgSearch, v as toolRegistrySearch, w as toolProjectList, x as toolProjectDetect, y as toolSessionList } from "./tools-Diro2s8J.mjs";
12
+ import { t as detectTopicShift } from "./detector-3g7XuU1r.mjs";
13
+ import { i as stopWorker, n as notifyNewWork, r as startWorker } from "./work-queue-worker-DufMOtrL.mjs";
18
14
  import { appendFileSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
19
15
  import { setPriority } from "node:os";
20
16
  import { dirname, join } from "node:path";
@@ -442,7 +438,7 @@ const aibrokerPush = async (logDir, target, ev) => {
442
438
  const iterm = target.iterm ?? (target.claudeSession ? itermForClaudeSession(logDir, target.claudeSession) : null);
443
439
  if (!iterm) return false;
444
440
  try {
445
- const { sendToSession } = await import("./aibroker-client-CNfIBrl5.mjs");
441
+ const { sendToSession } = await import("./aibroker-client-B8Wtasez.mjs");
446
442
  const r = await sendToSession(iterm, ev.text);
447
443
  return r.ok || r.timedOut === true;
448
444
  } catch {
@@ -524,297 +520,6 @@ async function runSupervisionTick(logDir, opts = {}) {
524
520
  };
525
521
  }
526
522
 
527
- //#endregion
528
- //#region src/observations/store.ts
529
- /**
530
- * store.ts — PostgreSQL persistence for PAI observations.
531
- *
532
- * All functions accept a pg.Pool and are safe to call concurrently.
533
- * Schema is initialized lazily via ensureObservationTables().
534
- *
535
- * Content-hash deduplication: observations with the same hash
536
- * created within a 30-second window are silently dropped to prevent
537
- * duplicate entries from rapid repeated tool calls.
538
- */
539
- let _tablesEnsured = false;
540
- /**
541
- * Inlined schema DDL — avoids runtime file reads that break in bundled code
542
- * (the bundler puts this in a shared chunk whose __dirname differs from src/).
543
- */
544
- const SCHEMA_SQL = `
545
- CREATE TABLE IF NOT EXISTS pai_observations (
546
- id SERIAL PRIMARY KEY,
547
- session_id TEXT NOT NULL,
548
- project_id INTEGER,
549
- project_slug TEXT,
550
- type TEXT NOT NULL CHECK (type IN ('decision', 'bugfix', 'feature', 'refactor', 'discovery', 'change')),
551
- title TEXT NOT NULL,
552
- narrative TEXT,
553
- tool_name TEXT,
554
- tool_input_summary TEXT,
555
- files_read JSONB DEFAULT '[]'::jsonb,
556
- files_modified JSONB DEFAULT '[]'::jsonb,
557
- concepts JSONB DEFAULT '[]'::jsonb,
558
- content_hash TEXT,
559
- created_at TIMESTAMPTZ DEFAULT NOW()
560
- );
561
-
562
- CREATE INDEX IF NOT EXISTS idx_obs_project ON pai_observations(project_id);
563
- CREATE INDEX IF NOT EXISTS idx_obs_session ON pai_observations(session_id);
564
- CREATE INDEX IF NOT EXISTS idx_obs_type ON pai_observations(type);
565
- CREATE INDEX IF NOT EXISTS idx_obs_created ON pai_observations(created_at DESC);
566
- CREATE INDEX IF NOT EXISTS idx_obs_hash ON pai_observations(content_hash);
567
-
568
- CREATE TABLE IF NOT EXISTS pai_session_summaries (
569
- id SERIAL PRIMARY KEY,
570
- session_id TEXT NOT NULL UNIQUE,
571
- project_id INTEGER,
572
- project_slug TEXT,
573
- request TEXT,
574
- investigated TEXT,
575
- learned TEXT,
576
- completed TEXT,
577
- next_steps TEXT,
578
- observation_count INTEGER DEFAULT 0,
579
- created_at TIMESTAMPTZ DEFAULT NOW()
580
- );
581
-
582
- CREATE INDEX IF NOT EXISTS idx_ss_project ON pai_session_summaries(project_id);
583
- CREATE INDEX IF NOT EXISTS idx_ss_session ON pai_session_summaries(session_id);
584
- `;
585
- /**
586
- * Run schema DDL idempotently against the given pool.
587
- * Uses a module-level flag so subsequent calls are no-ops within the same
588
- * process lifetime (the SQL itself uses IF NOT EXISTS so it is safe to re-run).
589
- */
590
- async function ensureObservationTables(pool) {
591
- if (_tablesEnsured) return;
592
- await pool.query(SCHEMA_SQL);
593
- _tablesEnsured = true;
594
- }
595
- /**
596
- * Compute a 16-character hex content hash for deduplication.
597
- * Hash = SHA256(session_id + tool_name + title).slice(0, 16)
598
- */
599
- function computeContentHash(sessionId, toolName, title) {
600
- return sha256(sessionId + "\0" + toolName + "\0" + title).slice(0, 16);
601
- }
602
- /**
603
- * Insert an observation, skipping duplicates within a 30-second window.
604
- * Returns the inserted row's id, or null if the insert was suppressed.
605
- */
606
- async function storeObservation(pool, obs) {
607
- await ensureObservationTables(pool);
608
- const hash = computeContentHash(obs.session_id, obs.tool_name, obs.title);
609
- const dupCheck = await pool.query(`SELECT id FROM pai_observations
610
- WHERE content_hash = $1
611
- AND session_id = $2
612
- AND created_at >= NOW() - INTERVAL '30 seconds'
613
- LIMIT 1`, [hash, obs.session_id]);
614
- if (dupCheck.rowCount && dupCheck.rowCount > 0) return null;
615
- return (await pool.query(`INSERT INTO pai_observations
616
- (session_id, project_id, project_slug, type, title, narrative,
617
- tool_name, tool_input_summary, files_read, files_modified, concepts, content_hash)
618
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::jsonb, $10::jsonb, $11::jsonb, $12)
619
- RETURNING id`, [
620
- obs.session_id,
621
- obs.project_id ?? null,
622
- obs.project_slug ?? null,
623
- obs.type,
624
- obs.title,
625
- obs.narrative ?? null,
626
- obs.tool_name,
627
- obs.tool_input_summary ?? null,
628
- JSON.stringify(obs.files_read),
629
- JSON.stringify(obs.files_modified),
630
- JSON.stringify(obs.concepts),
631
- hash
632
- ])).rows[0]?.id ?? null;
633
- }
634
- /**
635
- * Attribute an observation to the active project covering `cwd`, then store
636
- * it. One shared sequence for every daemon-side writer (IPC handler, cache
637
- * keepalive) so the lookup query exists exactly once.
638
- */
639
- async function storeObservationWithProject(db, pool, obs) {
640
- let project_id = null;
641
- let project_slug = null;
642
- if (obs.cwd) {
643
- const row = db.prepare("SELECT id, slug FROM projects WHERE status = 'active' AND ? LIKE root_path || '%' ORDER BY length(root_path) DESC LIMIT 1").get(obs.cwd);
644
- if (row) {
645
- project_id = row.id;
646
- project_slug = row.slug;
647
- }
648
- }
649
- return storeObservation(pool, {
650
- ...obs,
651
- project_id,
652
- project_slug
653
- });
654
- }
655
- /**
656
- * Filtered query for observations with optional projectId, sessionId, type,
657
- * limit, and offset. Returns results ordered by created_at DESC.
658
- */
659
- async function queryObservations(pool, opts = {}) {
660
- await ensureObservationTables(pool);
661
- const conditions = [];
662
- const params = [];
663
- let idx = 1;
664
- if (opts.projectId !== void 0) {
665
- conditions.push(`project_id = $${idx++}`);
666
- params.push(opts.projectId);
667
- }
668
- if (opts.sessionId !== void 0) {
669
- conditions.push(`session_id = $${idx++}`);
670
- params.push(opts.sessionId);
671
- }
672
- if (opts.type !== void 0) {
673
- conditions.push(`type = $${idx++}`);
674
- params.push(opts.type);
675
- }
676
- const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
677
- const limit = opts.limit ?? 50;
678
- const offset = opts.offset ?? 0;
679
- params.push(limit, offset);
680
- return (await pool.query(`SELECT id, session_id, project_id, project_slug, type, title, narrative,
681
- tool_name, tool_input_summary,
682
- files_read, files_modified, concepts,
683
- content_hash, created_at
684
- FROM pai_observations
685
- ${where}
686
- ORDER BY created_at DESC
687
- LIMIT $${idx++} OFFSET $${idx}`, params)).rows;
688
- }
689
- /**
690
- * Most recent observations for a project, ordered by created_at DESC.
691
- */
692
- async function queryRecentObservations(pool, projectId, limit) {
693
- await ensureObservationTables(pool);
694
- return (await pool.query(`SELECT id, session_id, project_id, project_slug, type, title, narrative,
695
- tool_name, tool_input_summary,
696
- files_read, files_modified, concepts,
697
- content_hash, created_at
698
- FROM pai_observations
699
- WHERE project_id = $1
700
- ORDER BY created_at DESC
701
- LIMIT $2`, [projectId, limit])).rows;
702
- }
703
- /**
704
- * Upsert a session summary. Uses ON CONFLICT on session_id so calling this
705
- * multiple times with updated content is safe.
706
- */
707
- async function storeSessionSummary(pool, summary) {
708
- await ensureObservationTables(pool);
709
- await pool.query(`INSERT INTO pai_session_summaries
710
- (session_id, project_id, project_slug, request, investigated,
711
- learned, completed, next_steps, observation_count)
712
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
713
- ON CONFLICT (session_id) DO UPDATE SET
714
- project_id = EXCLUDED.project_id,
715
- project_slug = EXCLUDED.project_slug,
716
- request = EXCLUDED.request,
717
- investigated = EXCLUDED.investigated,
718
- learned = EXCLUDED.learned,
719
- completed = EXCLUDED.completed,
720
- next_steps = EXCLUDED.next_steps,
721
- observation_count = EXCLUDED.observation_count`, [
722
- summary.session_id,
723
- summary.project_id ?? null,
724
- summary.project_slug ?? null,
725
- summary.request ?? null,
726
- summary.investigated ?? null,
727
- summary.learned ?? null,
728
- summary.completed ?? null,
729
- summary.next_steps ?? null,
730
- summary.observation_count ?? 0
731
- ]);
732
- }
733
- const SKILL_TELEMETRY_SCHEMA_SQL = `
734
- CREATE TABLE IF NOT EXISTS pai_skill_telemetry (
735
- id SERIAL PRIMARY KEY,
736
- scope TEXT NOT NULL DEFAULT 'default',
737
- skill_name TEXT NOT NULL,
738
- source TEXT NOT NULL DEFAULT 'local',
739
- status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('trial','active','archived')),
740
- trigger_count INTEGER NOT NULL DEFAULT 0,
741
- accept_count INTEGER NOT NULL DEFAULT 0,
742
- first_triggered TIMESTAMPTZ DEFAULT NOW(),
743
- last_triggered TIMESTAMPTZ DEFAULT NOW(),
744
- context_projects JSONB DEFAULT '[]'::jsonb,
745
- hash TEXT,
746
- audit_status TEXT,
747
- last_audited TIMESTAMPTZ,
748
- UNIQUE(scope, skill_name, source)
749
- );
750
-
751
- CREATE INDEX IF NOT EXISTS idx_skilltel_scope ON pai_skill_telemetry(scope);
752
- CREATE INDEX IF NOT EXISTS idx_skilltel_status ON pai_skill_telemetry(scope, status);
753
- CREATE INDEX IF NOT EXISTS idx_skilltel_last ON pai_skill_telemetry(last_triggered DESC);
754
- `;
755
- let _skillTelemetryEnsured = false;
756
- async function ensureSkillTelemetryTable(pool) {
757
- if (_skillTelemetryEnsured) return;
758
- await pool.query(SKILL_TELEMETRY_SCHEMA_SQL);
759
- _skillTelemetryEnsured = true;
760
- }
761
- /**
762
- * Record a single skill invocation. Upserts on (scope, skill_name, source):
763
- * increments trigger_count, refreshes last_triggered, and dedup-merges the
764
- * project slug into context_projects.
765
- */
766
- async function recordSkillInvocation(pool, input) {
767
- await ensureSkillTelemetryTable(pool);
768
- const scope = input.scope ?? "default";
769
- const source = input.source ?? "local";
770
- const proj = input.project_slug ?? null;
771
- const initialProjects = JSON.stringify(proj ? [proj] : []);
772
- await pool.query(`INSERT INTO pai_skill_telemetry
773
- (scope, skill_name, source, trigger_count, context_projects)
774
- VALUES ($1, $2, $3, 1, $4::jsonb)
775
- ON CONFLICT (scope, skill_name, source) DO UPDATE SET
776
- trigger_count = pai_skill_telemetry.trigger_count + 1,
777
- last_triggered = NOW(),
778
- context_projects = CASE
779
- WHEN $5::text IS NULL THEN pai_skill_telemetry.context_projects
780
- WHEN pai_skill_telemetry.context_projects @> to_jsonb($5::text)
781
- THEN pai_skill_telemetry.context_projects
782
- ELSE pai_skill_telemetry.context_projects || to_jsonb($5::text)
783
- END`, [
784
- scope,
785
- input.skill_name,
786
- source,
787
- initialProjects,
788
- proj
789
- ]);
790
- }
791
- /**
792
- * List skill telemetry rows, most-triggered first.
793
- */
794
- async function querySkillTelemetry(pool, opts = {}) {
795
- await ensureSkillTelemetryTable(pool);
796
- const conditions = [];
797
- const params = [];
798
- let idx = 1;
799
- conditions.push(`scope = $${idx++}`);
800
- params.push(opts.scope ?? "default");
801
- if (opts.status !== void 0) {
802
- conditions.push(`status = $${idx++}`);
803
- params.push(opts.status);
804
- }
805
- const where = `WHERE ${conditions.join(" AND ")}`;
806
- const limit = opts.limit ?? 100;
807
- params.push(limit);
808
- return (await pool.query(`SELECT id, scope, skill_name, source, status,
809
- trigger_count, accept_count,
810
- first_triggered, last_triggered,
811
- context_projects, hash, audit_status, last_audited
812
- FROM pai_skill_telemetry
813
- ${where}
814
- ORDER BY trigger_count DESC, last_triggered DESC
815
- LIMIT $${idx}`, params)).rows;
816
- }
817
-
818
523
  //#endregion
819
524
  //#region src/daemon/daemon/scheduler.ts
820
525
  /**
@@ -841,21 +546,10 @@ async function runIndex() {
841
546
  const t0 = Date.now();
842
547
  try {
843
548
  process.stderr.write("[pai-daemon] Starting scheduled index run...\n");
844
- if (storageBackend.backendType === "sqlite") {
845
- const { SQLiteBackend } = await import("./sqlite-By6r2YhZ.mjs");
846
- if (storageBackend instanceof SQLiteBackend) {
847
- const { projects, result } = await indexAll(storageBackend.getRawDb(), registryDb);
848
- const elapsed = Date.now() - t0;
849
- setLastIndexTime(Date.now());
850
- process.stderr.write(`[pai-daemon] Index complete: ${projects} projects, ${result.filesProcessed} files, ${result.chunksCreated} chunks (${elapsed}ms)\n`);
851
- }
852
- } else {
853
- const { indexAllWithBackend } = await import("./indexer-backend-CdvCJCkD.mjs");
854
- const { projects, result } = await indexAllWithBackend(storageBackend, registryDb);
855
- const elapsed = Date.now() - t0;
856
- setLastIndexTime(Date.now());
857
- process.stderr.write(`[pai-daemon] Index complete (postgres): ${projects} projects, ${result.filesProcessed} files, ${result.chunksCreated} chunks (${elapsed}ms)\n`);
858
- }
549
+ const { projects, result } = await storageBackend.indexAll(registryBackend);
550
+ const elapsed = Date.now() - t0;
551
+ setLastIndexTime(Date.now());
552
+ process.stderr.write(`[pai-daemon] Index complete: ${projects} projects, ${result.filesProcessed} files, ${result.chunksCreated} chunks (${elapsed}ms)\n`);
859
553
  } catch (e) {
860
554
  const msg = e instanceof Error ? e.message : String(e);
861
555
  process.stderr.write(`[pai-daemon] Index error: ${msg}\n`);
@@ -877,11 +571,11 @@ async function runVaultIndex() {
877
571
  process.stderr.write("[pai-daemon] Index/embed in progress, deferring vault index.\n");
878
572
  return;
879
573
  }
880
- const { lastVaultIndexTime } = await import("./state-Ca0ltLgI.mjs");
574
+ const { lastVaultIndexTime } = await import("./state-CwlGAKgF.mjs");
881
575
  if (lastVaultIndexTime > 0 && Date.now() - lastVaultIndexTime < VAULT_INDEX_MIN_INTERVAL_MS) return;
882
576
  let vaultProjectId = daemonConfig.vaultProjectId;
883
577
  if (!vaultProjectId) {
884
- const row = registryDb.prepare("SELECT id FROM projects WHERE root_path = ?").get(daemonConfig.vaultPath);
578
+ const row = await registryBackend.getProjectByRootPath(daemonConfig.vaultPath);
885
579
  vaultProjectId = row?.id ?? 999;
886
580
  if (!row) process.stderr.write("[pai-daemon] Vault not in project registry — using synthetic project ID 999.\n");
887
581
  }
@@ -889,7 +583,7 @@ async function runVaultIndex() {
889
583
  const t0 = Date.now();
890
584
  process.stderr.write("[pai-daemon] Starting vault index run...\n");
891
585
  try {
892
- const { indexVault } = await import("./vault-indexer-C5i-OAyr.mjs");
586
+ const { indexVault } = await import("./vault-indexer-DHYBpRZ5.mjs");
893
587
  const r = await indexVault(storageBackend, vaultProjectId, daemonConfig.vaultPath);
894
588
  const elapsed = Date.now() - t0;
895
589
  setLastVaultIndexTime(Date.now());
@@ -950,38 +644,21 @@ async function runEmbed() {
950
644
  process.stderr.write("[pai-daemon] Index in progress, deferring embed pass.\n");
951
645
  return;
952
646
  }
953
- if (storageBackend.backendType !== "postgres") return;
647
+ if (!storageBackend.supportsPostgresFeatures) return;
954
648
  setEmbedInProgress(true);
955
649
  const t0 = Date.now();
956
650
  try {
957
651
  process.stderr.write("[pai-daemon] Starting scheduled embed pass...\n");
958
652
  const projectNames = /* @__PURE__ */ new Map();
959
653
  try {
960
- const rows = registryDb.prepare("SELECT id, slug FROM projects WHERE status = 'active'").all();
654
+ const rows = await registryBackend.listProjects({ status: "active" });
961
655
  for (const r of rows) projectNames.set(r.id, r.slug);
962
656
  } catch {}
963
- const { embedChunksWithBackend } = await import("./indexer-backend-CdvCJCkD.mjs");
657
+ const { embedChunksWithBackend } = await import("./indexer-backend-DcDtin1O.mjs");
964
658
  const count = await embedChunksWithBackend(storageBackend, () => shutdownRequested, projectNames, { maxMillis: 24e4 });
965
- let vaultEmbedCount = 0;
966
- if (daemonConfig.vaultPath) try {
967
- const { SQLiteBackend } = await import("./sqlite-By6r2YhZ.mjs");
968
- const { openFederation } = await import("./db-BOBfewFH.mjs");
969
- const federationDb = openFederation();
970
- const vaultSqliteBackend = new SQLiteBackend(federationDb);
971
- const vaultProjectNames = new Map(projectNames);
972
- if (!vaultProjectNames.has(999)) vaultProjectNames.set(999, "obsidian-vault");
973
- vaultEmbedCount = await embedChunksWithBackend(vaultSqliteBackend, () => shutdownRequested, vaultProjectNames, { maxMillis: 45e3 });
974
- try {
975
- federationDb.close();
976
- } catch {}
977
- if (vaultEmbedCount > 0) process.stderr.write(`[pai-daemon] Vault embed pass complete: ${vaultEmbedCount} vault chunks embedded\n`);
978
- } catch (ve) {
979
- const vmsg = ve instanceof Error ? ve.message : String(ve);
980
- process.stderr.write(`[pai-daemon] Vault embed error: ${vmsg}\n`);
981
- }
982
659
  const elapsed = Date.now() - t0;
983
660
  setLastEmbedTime(Date.now());
984
- process.stderr.write(`[pai-daemon] Embed pass complete: ${count} postgres chunks + ${vaultEmbedCount} vault chunks embedded (${elapsed}ms)\n`);
661
+ process.stderr.write(`[pai-daemon] Embed pass complete: ${count} chunks embedded (${elapsed}ms)\n`);
985
662
  } catch (e) {
986
663
  const msg = e instanceof Error ? e.message : String(e);
987
664
  process.stderr.write(`[pai-daemon] Embed error: ${msg}\n`);
@@ -1024,12 +701,12 @@ const REGISTRY_SCAN_STARTUP_DELAY_MS = 1e4;
1024
701
  function startRegistryScanScheduler() {
1025
702
  process.stderr.write("[pai-daemon] Registry scan scheduler: every 30min (first in 10s)\n");
1026
703
  setTimeout(() => {
1027
- import("./work-queue-worker-DsdJx-jn.mjs").then(({ enqueueRegistryScan }) => enqueueRegistryScan()).catch((e) => {
704
+ import("./work-queue-worker-DEbWsrDQ.mjs").then(({ enqueueRegistryScan }) => enqueueRegistryScan()).catch((e) => {
1028
705
  process.stderr.write(`[pai-daemon] Startup registry scan error: ${e}\n`);
1029
706
  });
1030
707
  }, REGISTRY_SCAN_STARTUP_DELAY_MS);
1031
708
  const timer = setInterval(() => {
1032
- import("./work-queue-worker-DsdJx-jn.mjs").then(({ enqueueRegistryScan }) => enqueueRegistryScan()).catch((e) => {
709
+ import("./work-queue-worker-DEbWsrDQ.mjs").then(({ enqueueRegistryScan }) => enqueueRegistryScan()).catch((e) => {
1033
710
  process.stderr.write(`[pai-daemon] Scheduled registry scan error: ${e}\n`);
1034
711
  });
1035
712
  }, REGISTRY_SCAN_INTERVAL_MS);
@@ -1098,22 +775,20 @@ function startCacheKeepalive(opts = {}) {
1098
775
  return;
1099
776
  }
1100
777
  let notedNoPostgres = false;
1101
- const sqliteNote = () => {
1102
- const pool = storageBackend?.getPool?.();
1103
- if (pool) return pool;
778
+ const supportsObservations = () => {
779
+ if (storageBackend?.supportsPostgresFeatures) return true;
1104
780
  if (!notedNoPostgres) {
1105
781
  notedNoPostgres = true;
1106
782
  process.stderr.write("[pai-daemon] Cache keepalive: observation rows need Postgres — ledger line only\n");
1107
783
  }
1108
- return null;
784
+ return false;
1109
785
  };
1110
786
  const beat = async () => {
1111
787
  const m = await (opts.beat ?? runKeepaliveBeat)();
1112
788
  if (!m) return;
1113
- const pool = sqliteNote();
1114
- if (!pool) return;
789
+ if (!supportsObservations()) return;
1115
790
  try {
1116
- await storeObservationWithProject(registryDb, pool, {
791
+ await storageBackend.storeObservationWithProject(registryBackend, {
1117
792
  session_id: m.id,
1118
793
  type: "change",
1119
794
  title: `cache keepalive ${m.ok ? "ok" : "failed"} (cache_read=${m.cache_read_input_tokens}, api_ms=${m.duration_api_ms})`,
@@ -1181,19 +856,19 @@ function startSessionKeepalive() {
1181
856
  async function dispatchTool(method, params) {
1182
857
  const p = params;
1183
858
  switch (method) {
1184
- case "memory_search": return toolMemorySearch(registryDb, storageBackend, p);
1185
- case "memory_get": return toolMemoryGet(registryDb, p);
1186
- case "project_info": return toolProjectInfo(registryDb, p);
1187
- case "project_list": return toolProjectList(registryDb, p);
1188
- case "session_list": return toolSessionList(registryDb, p);
1189
- case "registry_search": return toolRegistrySearch(registryDb, p);
1190
- case "project_detect": return toolProjectDetect(registryDb, p);
1191
- case "project_health": return toolProjectHealth(registryDb, p);
1192
- case "project_todo": return toolProjectTodo(registryDb, p);
1193
- case "memory_wakeup": return toolMemoryWakeup(registryDb, p);
1194
- case "memory_taxonomy": return toolMemoryTaxonomy(registryDb, storageBackend, p);
1195
- case "topic_check": return detectTopicShift(registryDb, storageBackend, p);
1196
- case "session_auto_route": return toolSessionRoute(registryDb, storageBackend, p);
859
+ case "memory_search": return toolMemorySearch(registryBackend, storageBackend, p);
860
+ case "memory_get": return toolMemoryGet(registryBackend, p);
861
+ case "project_info": return toolProjectInfo(registryBackend, p);
862
+ case "project_list": return toolProjectList(registryBackend, p);
863
+ case "session_list": return toolSessionList(registryBackend, p);
864
+ case "registry_search": return toolRegistrySearch(registryBackend, p);
865
+ case "project_detect": return toolProjectDetect(p);
866
+ case "project_health": return toolProjectHealth(registryBackend, p);
867
+ case "project_todo": return toolProjectTodo(registryBackend, p);
868
+ case "memory_wakeup": return toolMemoryWakeup(registryBackend, p);
869
+ case "memory_taxonomy": return toolMemoryTaxonomy(registryBackend, storageBackend, p);
870
+ case "topic_check": return detectTopicShift(registryBackend, storageBackend, p);
871
+ case "session_auto_route": return toolSessionRoute(registryBackend, storageBackend, p);
1197
872
  case "zettel_explore":
1198
873
  case "zettel_health":
1199
874
  case "zettel_surprise":
@@ -1202,7 +877,7 @@ async function dispatchTool(method, params) {
1202
877
  case "zettel_themes":
1203
878
  case "zettel_god_notes":
1204
879
  case "zettel_communities": {
1205
- const { toolZettelExplore, toolZettelHealth, toolZettelSurprise, toolZettelSuggest, toolZettelConverse, toolZettelThemes, toolZettelGodNotes, toolZettelCommunities } = await import("./tools-BwsOTmjh.mjs");
880
+ const { toolZettelExplore, toolZettelHealth, toolZettelSurprise, toolZettelSuggest, toolZettelConverse, toolZettelThemes, toolZettelGodNotes, toolZettelCommunities } = await import("./tools-KgL1rkPD.mjs");
1206
881
  switch (method) {
1207
882
  case "zettel_explore": return toolZettelExplore(storageBackend, p);
1208
883
  case "zettel_health": return toolZettelHealth(storageBackend, p);
@@ -1216,27 +891,27 @@ async function dispatchTool(method, params) {
1216
891
  break;
1217
892
  }
1218
893
  case "graph_clusters": {
1219
- const { handleGraphClusters } = await import("./clusters-Cw_P6lO-.mjs");
1220
- return handleGraphClusters(storageBackend.getPool?.() ?? null, storageBackend, p);
894
+ const { handleGraphClusters } = await import("./clusters-Ci1mseh2.mjs");
895
+ return handleGraphClusters(storageBackend, p);
1221
896
  }
1222
897
  case "graph_neighborhood": {
1223
- const { handleGraphNeighborhood } = await import("./neighborhood-CETR_P4y.mjs");
1224
- return handleGraphNeighborhood(storageBackend.getPool?.() ?? null, storageBackend, p);
898
+ const { handleGraphNeighborhood } = await import("./neighborhood-D8uscnGy.mjs");
899
+ return handleGraphNeighborhood(storageBackend, p);
1225
900
  }
1226
901
  case "graph_note_context": {
1227
- const { handleGraphNoteContext } = await import("./note-context-DCcRWBoN.mjs");
1228
- return handleGraphNoteContext(storageBackend.getPool?.() ?? null, storageBackend, p);
902
+ const { handleGraphNoteContext } = await import("./note-context-CgffaUMh.mjs");
903
+ return handleGraphNoteContext(storageBackend, p);
1229
904
  }
1230
905
  case "graph_trace": {
1231
- const { handleGraphTrace } = await import("./trace-Cy8quQTm.mjs");
906
+ const { handleGraphTrace } = await import("./trace-BRflVyBi.mjs");
1232
907
  return handleGraphTrace(storageBackend, p);
1233
908
  }
1234
909
  case "graph_latent_ideas": {
1235
- const { handleGraphLatentIdeas } = await import("./latent-ideas-BfL4nCQ3.mjs");
910
+ const { handleGraphLatentIdeas } = await import("./latent-ideas-BRy6HNwg.mjs");
1236
911
  return handleGraphLatentIdeas(storageBackend, p);
1237
912
  }
1238
913
  case "idea_materialize": {
1239
- const { handleIdeaMaterialize } = await import("./latent-ideas-BfL4nCQ3.mjs");
914
+ const { handleIdeaMaterialize } = await import("./latent-ideas-BRy6HNwg.mjs");
1240
915
  if (!daemonConfig.vaultPath) throw new Error("idea_materialize requires vaultPath to be configured in the daemon config");
1241
916
  return handleIdeaMaterialize(p, daemonConfig.vaultPath);
1242
917
  }
@@ -1244,42 +919,24 @@ async function dispatchTool(method, params) {
1244
919
  case "kg_query":
1245
920
  case "kg_invalidate":
1246
921
  case "kg_contradictions": {
1247
- const { toolKgAdd, toolKgQuery, toolKgInvalidate, toolKgContradictions } = await import("./tools-BwsOTmjh.mjs");
1248
- const pgPool = storageBackend.getPool?.() ?? null;
1249
- if (!pgPool) throw new Error(`${method} requires a Postgres storage backend`);
922
+ const { toolKgAdd, toolKgQuery, toolKgInvalidate, toolKgContradictions } = await import("./tools-KgL1rkPD.mjs");
923
+ if (!storageBackend.supportsPostgresFeatures) throw new Error(`${method} requires a Postgres storage backend`);
1250
924
  switch (method) {
1251
- case "kg_add": return toolKgAdd(pgPool, p);
1252
- case "kg_query": return toolKgQuery(pgPool, p);
1253
- case "kg_invalidate": return toolKgInvalidate(pgPool, p);
1254
- case "kg_contradictions": return toolKgContradictions(pgPool, p);
925
+ case "kg_add": return toolKgAdd(storageBackend, p);
926
+ case "kg_query": return toolKgQuery(storageBackend, p);
927
+ case "kg_invalidate": return toolKgInvalidate(storageBackend, p);
928
+ case "kg_contradictions": return toolKgContradictions(storageBackend, p);
1255
929
  }
1256
930
  break;
1257
931
  }
1258
932
  case "memory_tunnels": {
1259
- const { toolMemoryTunnels } = await import("./tools-BwsOTmjh.mjs");
1260
- return toolMemoryTunnels(registryDb, storageBackend, p);
1261
- }
1262
- case "memory_feedback": {
1263
- const federationDb = openFederation();
1264
- try {
1265
- return await toolMemoryFeedback(federationDb, p);
1266
- } finally {
1267
- federationDb.close();
1268
- }
1269
- }
1270
- case "memory_kg_search": {
1271
- const federationDb = openFederation();
1272
- const pgPool = storageBackend.getPool?.() ?? null;
1273
- if (!pgPool) {
1274
- federationDb.close();
1275
- throw new Error("memory_kg_search requires a Postgres storage backend for KG triple expansion");
1276
- }
1277
- try {
1278
- return await toolMemoryKgSearch(federationDb, pgPool, p);
1279
- } finally {
1280
- federationDb.close();
1281
- }
933
+ const { toolMemoryTunnels } = await import("./tools-KgL1rkPD.mjs");
934
+ return toolMemoryTunnels(registryBackend, storageBackend, p);
1282
935
  }
936
+ case "memory_feedback": return await toolMemoryFeedback(storageBackend, p);
937
+ case "memory_kg_search":
938
+ if (!storageBackend.supportsPostgresFeatures) throw new Error("memory_kg_search requires a Postgres storage backend for KG triple expansion");
939
+ return await toolMemoryKgSearch(storageBackend, p);
1283
940
  default: throw new Error(`Unknown method: ${method}`);
1284
941
  }
1285
942
  }
@@ -1301,7 +958,7 @@ async function handleRequest(request, socket) {
1301
958
  try {
1302
959
  if (!storageBackend) return null;
1303
960
  const fedStats = await storageBackend.getStats();
1304
- const projects = registryDb.prepare("SELECT COUNT(*) AS n FROM projects").get().n;
961
+ const projects = await registryBackend.countProjects();
1305
962
  return {
1306
963
  files: fedStats.files,
1307
964
  chunks: fedStats.chunks,
@@ -1428,8 +1085,7 @@ async function handleRequest(request, socket) {
1428
1085
  return;
1429
1086
  }
1430
1087
  if (method === "observation_store") {
1431
- const pool = storageBackend.getPool?.();
1432
- if (!pool) {
1088
+ if (!storageBackend?.supportsPostgresFeatures) {
1433
1089
  sendResponse(socket, {
1434
1090
  id,
1435
1091
  ok: false,
@@ -1445,7 +1101,7 @@ async function handleRequest(request, socket) {
1445
1101
  ok: true,
1446
1102
  result: {
1447
1103
  ok: true,
1448
- id: await storeObservationWithProject(registryDb, pool, {
1104
+ id: await storageBackend.storeObservationWithProject(registryBackend, {
1449
1105
  session_id: p.session_id,
1450
1106
  type: p.type,
1451
1107
  title: p.title,
@@ -1470,8 +1126,7 @@ async function handleRequest(request, socket) {
1470
1126
  return;
1471
1127
  }
1472
1128
  if (method === "skill_telemetry_record") {
1473
- const pool = storageBackend.getPool?.();
1474
- if (!pool) {
1129
+ if (!storageBackend?.supportsPostgresFeatures) {
1475
1130
  sendResponse(socket, {
1476
1131
  id,
1477
1132
  ok: false,
@@ -1484,10 +1139,10 @@ async function handleRequest(request, socket) {
1484
1139
  const p = params;
1485
1140
  let project_slug = null;
1486
1141
  if (p.cwd) {
1487
- const row = registryDb.prepare("SELECT slug FROM projects WHERE status = 'active' AND ? LIKE root_path || '%' ORDER BY length(root_path) DESC LIMIT 1").get(p.cwd);
1142
+ const row = await registryBackend.findProjectByCwdPrefix(p.cwd);
1488
1143
  if (row) project_slug = row.slug;
1489
1144
  }
1490
- await recordSkillInvocation(pool, {
1145
+ await storageBackend.recordSkillInvocation({
1491
1146
  skill_name: p.skill_name,
1492
1147
  source: p.source,
1493
1148
  scope: p.scope,
@@ -1509,8 +1164,7 @@ async function handleRequest(request, socket) {
1509
1164
  return;
1510
1165
  }
1511
1166
  if (method === "skill_telemetry_query") {
1512
- const pool = storageBackend.getPool?.();
1513
- if (!pool) {
1167
+ if (!storageBackend?.supportsPostgresFeatures) {
1514
1168
  sendResponse(socket, {
1515
1169
  id,
1516
1170
  ok: false,
@@ -1524,7 +1178,7 @@ async function handleRequest(request, socket) {
1524
1178
  sendResponse(socket, {
1525
1179
  id,
1526
1180
  ok: true,
1527
- result: await querySkillTelemetry(pool, {
1181
+ result: await storageBackend.querySkillTelemetry({
1528
1182
  scope: p.scope,
1529
1183
  status: p.status,
1530
1184
  limit: p.limit
@@ -1541,8 +1195,7 @@ async function handleRequest(request, socket) {
1541
1195
  return;
1542
1196
  }
1543
1197
  if (method === "observation_query") {
1544
- const pool = storageBackend.getPool?.();
1545
- if (!pool) {
1198
+ if (!storageBackend?.supportsPostgresFeatures) {
1546
1199
  sendResponse(socket, {
1547
1200
  id,
1548
1201
  ok: false,
@@ -1556,7 +1209,7 @@ async function handleRequest(request, socket) {
1556
1209
  sendResponse(socket, {
1557
1210
  id,
1558
1211
  ok: true,
1559
- result: await queryObservations(pool, {
1212
+ result: await storageBackend.queryObservations({
1560
1213
  projectId: p.project_id,
1561
1214
  sessionId: p.session_id,
1562
1215
  type: p.type,
@@ -1575,8 +1228,7 @@ async function handleRequest(request, socket) {
1575
1228
  return;
1576
1229
  }
1577
1230
  if (method === "observation_recent") {
1578
- const pool = storageBackend.getPool?.();
1579
- if (!pool) {
1231
+ if (!storageBackend?.supportsPostgresFeatures) {
1580
1232
  sendResponse(socket, {
1581
1233
  id,
1582
1234
  ok: false,
@@ -1591,15 +1243,15 @@ async function handleRequest(request, socket) {
1591
1243
  let resolvedProjectId = p.project_id;
1592
1244
  let resolvedProjectSlug;
1593
1245
  if (resolvedProjectId === void 0 && p.cwd) {
1594
- const row = registryDb.prepare("SELECT id, slug FROM projects WHERE status = 'active' AND ? LIKE root_path || '%' ORDER BY length(root_path) DESC LIMIT 1").get(p.cwd);
1246
+ const row = await registryBackend.findProjectByCwdPrefix(p.cwd);
1595
1247
  if (row) {
1596
1248
  resolvedProjectId = row.id;
1597
1249
  resolvedProjectSlug = row.slug;
1598
1250
  }
1599
1251
  }
1600
1252
  let rows;
1601
- if (resolvedProjectId !== void 0) rows = await queryRecentObservations(pool, resolvedProjectId, limit);
1602
- else rows = await queryObservations(pool, { limit });
1253
+ if (resolvedProjectId !== void 0) rows = await storageBackend.queryRecentObservations(resolvedProjectId, limit);
1254
+ else rows = await storageBackend.queryObservations({ limit });
1603
1255
  sendResponse(socket, {
1604
1256
  id,
1605
1257
  ok: true,
@@ -1619,8 +1271,7 @@ async function handleRequest(request, socket) {
1619
1271
  return;
1620
1272
  }
1621
1273
  if (method === "observation_list") {
1622
- const pool = storageBackend.getPool?.();
1623
- if (!pool) {
1274
+ if (!storageBackend?.supportsPostgresFeatures) {
1624
1275
  sendResponse(socket, {
1625
1276
  id,
1626
1277
  ok: false,
@@ -1632,11 +1283,11 @@ async function handleRequest(request, socket) {
1632
1283
  try {
1633
1284
  const p = params;
1634
1285
  let projectId;
1635
- if (p.project_slug) projectId = registryDb.prepare("SELECT id FROM projects WHERE slug = ?").get(p.project_slug)?.id;
1286
+ if (p.project_slug) projectId = (await registryBackend.getProjectBySlug(p.project_slug))?.id;
1636
1287
  sendResponse(socket, {
1637
1288
  id,
1638
1289
  ok: true,
1639
- result: await queryObservations(pool, {
1290
+ result: await storageBackend.queryObservations({
1640
1291
  projectId,
1641
1292
  sessionId: p.session_id,
1642
1293
  type: p.type,
@@ -1655,8 +1306,7 @@ async function handleRequest(request, socket) {
1655
1306
  return;
1656
1307
  }
1657
1308
  if (method === "observation_stats") {
1658
- const pool = storageBackend.getPool?.();
1659
- if (!pool) {
1309
+ if (!storageBackend?.supportsPostgresFeatures) {
1660
1310
  sendResponse(socket, {
1661
1311
  id,
1662
1312
  ok: false,
@@ -1666,28 +1316,10 @@ async function handleRequest(request, socket) {
1666
1316
  return;
1667
1317
  }
1668
1318
  try {
1669
- await ensureObservationTables(pool);
1670
- const [totalRes, byTypeRes, byProjectRes, recentRes] = await Promise.all([
1671
- pool.query("SELECT COUNT(*) as count FROM pai_observations"),
1672
- pool.query("SELECT type, COUNT(*) as count FROM pai_observations GROUP BY type ORDER BY count DESC"),
1673
- pool.query("SELECT project_slug, COUNT(*) as count FROM pai_observations GROUP BY project_slug ORDER BY count DESC LIMIT 15"),
1674
- pool.query("SELECT created_at FROM pai_observations ORDER BY created_at DESC LIMIT 1")
1675
- ]);
1676
1319
  sendResponse(socket, {
1677
1320
  id,
1678
1321
  ok: true,
1679
- result: {
1680
- total: parseInt(totalRes.rows[0]?.count ?? "0", 10),
1681
- by_type: byTypeRes.rows.map((r) => ({
1682
- type: r.type,
1683
- count: parseInt(r.count, 10)
1684
- })),
1685
- by_project: byProjectRes.rows.map((r) => ({
1686
- project_slug: r.project_slug,
1687
- count: parseInt(r.count, 10)
1688
- })),
1689
- most_recent: recentRes.rows[0]?.created_at ?? null
1690
- }
1322
+ result: await storageBackend.getObservationStats()
1691
1323
  });
1692
1324
  } catch (e) {
1693
1325
  sendResponse(socket, {
@@ -1700,8 +1332,7 @@ async function handleRequest(request, socket) {
1700
1332
  return;
1701
1333
  }
1702
1334
  if (method === "session_summary_store") {
1703
- const pool = storageBackend.getPool?.();
1704
- if (!pool) {
1335
+ if (!storageBackend?.supportsPostgresFeatures) {
1705
1336
  sendResponse(socket, {
1706
1337
  id,
1707
1338
  ok: false,
@@ -1715,13 +1346,13 @@ async function handleRequest(request, socket) {
1715
1346
  let resolvedProjectId = p.project_id ?? null;
1716
1347
  let resolvedProjectSlug = p.project_slug ?? null;
1717
1348
  if (resolvedProjectId === null && p.cwd) {
1718
- const row = registryDb.prepare("SELECT id, slug FROM projects WHERE status = 'active' AND ? LIKE root_path || '%' ORDER BY length(root_path) DESC LIMIT 1").get(p.cwd);
1349
+ const row = await registryBackend.findProjectByCwdPrefix(p.cwd);
1719
1350
  if (row) {
1720
1351
  resolvedProjectId = row.id;
1721
1352
  resolvedProjectSlug = row.slug;
1722
1353
  }
1723
1354
  }
1724
- await storeSessionSummary(pool, {
1355
+ await storageBackend.storeSessionSummary({
1725
1356
  session_id: p.session_id,
1726
1357
  project_id: resolvedProjectId,
1727
1358
  project_slug: resolvedProjectSlug,
@@ -1896,20 +1527,20 @@ async function serve(config) {
1896
1527
  process.stderr.write("[pai-daemon] Starting daemon...\n");
1897
1528
  process.stderr.write(`[pai-daemon] Socket: ${config.socketPath}\n`);
1898
1529
  process.stderr.write(`[pai-daemon] Storage backend: ${config.storageBackend}\n`);
1899
- const { notificationConfig } = await import("./state-Ca0ltLgI.mjs");
1530
+ const { notificationConfig } = await import("./state-CwlGAKgF.mjs");
1900
1531
  process.stderr.write(`[pai-daemon] Notification mode: ${notificationConfig.mode}\n`);
1901
1532
  try {
1902
1533
  setPriority(process.pid, 10);
1903
1534
  } catch {}
1904
1535
  configureEmbeddingModel(config.embeddingModel);
1905
- try {
1906
- setRegistryDb(openRegistry());
1907
- process.stderr.write("[pai-daemon] Registry database opened.\n");
1908
- } catch (e) {
1536
+ createRegistryBackend(config, { waitForPostgres: true }).then((backend) => {
1537
+ setRegistryBackend(backend);
1538
+ process.stderr.write(`[pai-daemon] Registry backend: ${backend.backendType}\n`);
1539
+ }).catch((e) => {
1909
1540
  const msg = e instanceof Error ? e.message : String(e);
1910
1541
  process.stderr.write(`[pai-daemon] Fatal: Could not open registry: ${msg}\n`);
1911
1542
  process.exit(1);
1912
- }
1543
+ });
1913
1544
  const server = await startIpcServer(config.socketPath);
1914
1545
  startRegistryScanScheduler();
1915
1546
  startWorkerSupervisor();
@@ -1919,7 +1550,7 @@ async function serve(config) {
1919
1550
  setStorageBackend(backend);
1920
1551
  process.stderr.write(`[pai-daemon] Federation backend: ${backend.backendType}\n`);
1921
1552
  startIndexScheduler();
1922
- if (backend.backendType === "postgres") startEmbedScheduler();
1553
+ if (backend.supportsPostgresFeatures) startEmbedScheduler();
1923
1554
  else process.stderr.write("[pai-daemon] Embed scheduler: disabled (SQLite backend)\n");
1924
1555
  loadQueue();
1925
1556
  startWorker();
@@ -1964,4 +1595,4 @@ async function serve(config) {
1964
1595
 
1965
1596
  //#endregion
1966
1597
  export { serve as t };
1967
- //# sourceMappingURL=daemon-aJTxzg20.mjs.map
1598
+ //# sourceMappingURL=daemon-Cgrdvdo6.mjs.map