@jungjaehoon/mama-core 2.4.0 → 4.0.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 (374) hide show
  1. package/README.md +76 -239
  2. package/db/migrations/030-case-first-memory-substrate.sql +13 -98
  3. package/db/migrations/034-add-connector-event-scope-columns.sql +9 -13
  4. package/db/migrations/039-add-connector-event-operator-ingest-seq.sql +9 -95
  5. package/db/migrations/062-refresh-connector-event-sequences.sql +9 -113
  6. package/db/migrations/063-refresh-legacy-connector-event-updates.sql +9 -32
  7. package/db/migrations/067-add-connector-event-source-entity-id.sql +9 -13
  8. package/db/migrations/068-tool-trace-diagnostics.sql +13 -0
  9. package/db/migrations/069-create-registry-nodes.sql +52 -0
  10. package/db/migrations/070-record-identity.sql +35 -0
  11. package/db/migrations/071-service-operation-origins.sql +187 -0
  12. package/db/migrations/072-observation-versions.sql +29 -0
  13. package/db/migrations/073-registry-corrections.sql +45 -0
  14. package/db/migrations/074-work-graph-ref-kinds.sql +39 -0
  15. package/db/migrations/075-agent-judgments.sql +58 -0
  16. package/db/migrations/076-scoped-checkpoint-bindings.sql +15 -0
  17. package/db/migrations/077-legacy-record-kind.sql +6 -0
  18. package/db/migrations/078-source-ingest-commands.sql +18 -0
  19. package/db/migrations/079-twin-edge-relations.sql +43 -0
  20. package/db/migrations/080-restore-duration-days.sql +7 -0
  21. package/db/migrations/081-mailbox.sql +61 -0
  22. package/db/migrations/082-commitments-row-id.sql +12 -0
  23. package/db/migrations/083-observation-is-the-evidence.sql +49 -0
  24. package/db/migrations/084-scope-kind-is-not-the-cores-to-list.sql +34 -0
  25. package/db/migrations/085-a-migration-has-a-source.sql +37 -0
  26. package/db/migrations/086-the-mailbox-is-generic.sql +110 -0
  27. package/db/migrations/087-mailbox-payload.sql +5 -0
  28. package/db/migrations/088-native-input-journal.sql +14 -0
  29. package/db/migrations/089-native-turn-receipt-lookup.sql +3 -0
  30. package/db/migrations/090-model-run-native-inputs.sql +29 -0
  31. package/db/migrations/091-native-turn-results.sql +11 -0
  32. package/db/migrations/092-restore-decision-fts.sql +34 -0
  33. package/db/migrations/093-native-turn-primary-kind.sql +14 -0
  34. package/db/migrations/094-commitment-run-provenance.sql +9 -0
  35. package/db/migrations/095-model-run-native-input-identity.sql +39 -0
  36. package/db/migrations/096-drop-connector-event-index-fts.sql +9 -0
  37. package/db/migrations/097-native-input-json-validity.sql +37 -0
  38. package/db/migrations/098-workflow-memory-kind.sql +105 -0
  39. package/dist/action-contracts.d.ts +212 -0
  40. package/dist/action-contracts.js +10 -0
  41. package/dist/api/catalog.d.ts +118 -0
  42. package/dist/api/catalog.js +1756 -0
  43. package/dist/api/dispatch.d.ts +76 -0
  44. package/dist/api/dispatch.js +372 -0
  45. package/dist/canonicalize.d.ts +2 -2
  46. package/dist/canonicalize.js +3 -3
  47. package/dist/client/client.d.ts +33 -0
  48. package/dist/client/client.js +123 -0
  49. package/dist/client/ipc.d.ts +81 -0
  50. package/dist/client/ipc.js +314 -0
  51. package/dist/db-adapter/base-adapter.d.ts +6 -66
  52. package/dist/db-adapter/base-adapter.js +6 -6
  53. package/dist/db-adapter/index.d.ts +5 -5
  54. package/dist/db-adapter/index.js +2 -5
  55. package/dist/db-adapter/node-sqlite-adapter.d.ts +87 -15
  56. package/dist/db-adapter/node-sqlite-adapter.js +2045 -568
  57. package/dist/db-manager.d.ts +53 -97
  58. package/dist/db-manager.js +121 -603
  59. package/dist/embedding/embedder.d.ts +132 -0
  60. package/dist/embedding/embedder.js +299 -0
  61. package/dist/identity/principal-repository.d.ts +2 -2
  62. package/dist/index.d.ts +43 -58
  63. package/dist/index.js +99 -145
  64. package/dist/{context-compile/channel-grant.d.ts → knowledge/access.d.ts} +12 -17
  65. package/dist/knowledge/access.js +663 -0
  66. package/dist/knowledge/case-errors.d.ts +31 -0
  67. package/dist/knowledge/case-errors.js +40 -0
  68. package/dist/{cases/search-rollup.d.ts → knowledge/case-search-rollup.d.ts} +5 -4
  69. package/dist/{cases/search-rollup.js → knowledge/case-search-rollup.js} +6 -8
  70. package/dist/{cases/store.d.ts → knowledge/case-store.d.ts} +3 -6
  71. package/dist/{cases/store.js → knowledge/case-store.js} +7 -42
  72. package/dist/{cases/timeline-range.d.ts → knowledge/case-timeline-range.d.ts} +3 -3
  73. package/dist/{cases/timeline-range.js → knowledge/case-timeline-range.js} +47 -25
  74. package/dist/{cases/types.d.ts → knowledge/case-types.d.ts} +8 -2
  75. package/dist/{cases/types.js → knowledge/case-types.js} +1 -1
  76. package/dist/knowledge/commitments.d.ts +188 -0
  77. package/dist/knowledge/commitments.js +370 -0
  78. package/dist/knowledge/decision-edges.d.ts +70 -0
  79. package/dist/knowledge/decision-edges.js +123 -0
  80. package/dist/{agent-graph/types.d.ts → knowledge/graph-query.d.ts} +80 -70
  81. package/dist/knowledge/graph-query.js +1585 -0
  82. package/dist/knowledge/identity.d.ts +16 -0
  83. package/dist/knowledge/identity.js +22 -0
  84. package/dist/knowledge/index.d.ts +47 -0
  85. package/dist/knowledge/index.js +90 -0
  86. package/dist/knowledge/judgments.d.ts +118 -0
  87. package/dist/knowledge/judgments.js +808 -0
  88. package/dist/knowledge/observations.d.ts +160 -0
  89. package/dist/knowledge/observations.js +449 -0
  90. package/dist/knowledge/question-type.d.ts +34 -0
  91. package/dist/knowledge/question-type.js +70 -0
  92. package/dist/{search → knowledge}/ranker-features.js +1 -1
  93. package/dist/{search → knowledge}/search-quality.d.ts +0 -1
  94. package/dist/knowledge/search.d.ts +38 -0
  95. package/dist/knowledge/search.js +91 -0
  96. package/dist/knowledge/source-ingest.d.ts +65 -0
  97. package/dist/knowledge/source-ingest.js +174 -0
  98. package/dist/{edges/types.d.ts → knowledge/twin-edge-types.d.ts} +31 -4
  99. package/dist/{edges/types.js → knowledge/twin-edge-types.js} +13 -2
  100. package/dist/knowledge/work-dates.d.ts +49 -0
  101. package/dist/knowledge/work-dates.js +120 -0
  102. package/dist/mama-api.d.ts +116 -778
  103. package/dist/mama-api.js +313 -2457
  104. package/dist/memory/api.d.ts +264 -24
  105. package/dist/memory/api.js +1633 -843
  106. package/dist/memory/bootstrap-builder.d.ts +2 -1
  107. package/dist/memory/bootstrap-builder.js +5 -5
  108. package/dist/memory/channel-summary-state-store.d.ts +3 -2
  109. package/dist/memory/channel-summary-state-store.js +53 -51
  110. package/dist/memory/channel-summary-store.d.ts +5 -3
  111. package/dist/memory/channel-summary-store.js +3 -8
  112. package/dist/memory/dashboard-read.d.ts +46 -0
  113. package/dist/memory/dashboard-read.js +94 -0
  114. package/dist/memory/event-store.d.ts +3 -3
  115. package/dist/memory/event-store.js +3 -10
  116. package/dist/memory/finding-store.d.ts +3 -2
  117. package/dist/memory/finding-store.js +2 -7
  118. package/dist/memory/graph-read.d.ts +52 -0
  119. package/dist/memory/graph-read.js +130 -0
  120. package/dist/memory/judgment-types.d.ts +394 -0
  121. package/dist/memory/judgment-types.js +16 -0
  122. package/dist/memory/provenance-audit.d.ts +5 -2
  123. package/dist/memory/provenance-audit.js +8 -14
  124. package/dist/memory/provenance-live.d.ts +141 -0
  125. package/dist/memory/provenance-live.js +409 -0
  126. package/dist/memory/provenance-query.d.ts +5 -4
  127. package/dist/memory/provenance-query.js +21 -29
  128. package/dist/memory/provenance-resolver.d.ts +191 -0
  129. package/dist/memory/provenance-resolver.js +155 -0
  130. package/dist/memory/provenance.d.ts +1 -11
  131. package/dist/memory/provenance.js +2 -33
  132. package/dist/memory/recall-sanitize.d.ts +55 -0
  133. package/dist/memory/recall-sanitize.js +144 -0
  134. package/dist/memory/secret-filter.d.ts +32 -0
  135. package/dist/memory/secret-filter.js +126 -0
  136. package/dist/memory/truth-store.d.ts +2 -1
  137. package/dist/memory/truth-store.js +1 -4
  138. package/dist/memory/types.d.ts +74 -24
  139. package/dist/memory/types.js +75 -5
  140. package/dist/memory/write-adapters.d.ts +98 -0
  141. package/dist/memory/write-adapters.js +242 -0
  142. package/dist/operations/owner-action-effects.d.ts +53 -0
  143. package/dist/operations/owner-action-effects.js +96 -0
  144. package/dist/provenance/source-ref.d.ts +1 -1
  145. package/dist/provenance/source-ref.js +0 -2
  146. package/dist/registry/corrections.d.ts +31 -0
  147. package/dist/registry/corrections.js +332 -0
  148. package/dist/registry/record-identity.d.ts +49 -0
  149. package/dist/registry/record-identity.js +133 -0
  150. package/dist/registry/store.d.ts +101 -0
  151. package/dist/registry/store.js +395 -0
  152. package/dist/registry/types.d.ts +28 -0
  153. package/dist/registry/types.js +5 -0
  154. package/dist/relevance-scorer.js +2 -2
  155. package/dist/runtime/agent-event-bus.d.ts +50 -0
  156. package/dist/runtime/agent-event-bus.js +101 -0
  157. package/dist/runtime/drivers/claude-cli-wrapper.d.ts +155 -0
  158. package/dist/runtime/drivers/claude-cli-wrapper.js +392 -0
  159. package/dist/runtime/drivers/cli-arg-redaction.d.ts +2 -0
  160. package/dist/runtime/drivers/cli-arg-redaction.js +18 -0
  161. package/dist/runtime/drivers/cli-secret-redaction.d.ts +17 -0
  162. package/dist/runtime/drivers/cli-secret-redaction.js +126 -0
  163. package/dist/runtime/drivers/codex-app-server-process.d.ts +277 -0
  164. package/dist/runtime/drivers/codex-app-server-process.js +2342 -0
  165. package/dist/runtime/drivers/codex-auxiliary-tools.d.ts +17 -0
  166. package/dist/runtime/drivers/codex-auxiliary-tools.js +267 -0
  167. package/dist/runtime/drivers/codex-home.d.ts +20 -0
  168. package/dist/runtime/drivers/codex-home.js +674 -0
  169. package/dist/runtime/drivers/codex-thread-registry.d.ts +63 -0
  170. package/dist/runtime/drivers/codex-thread-registry.js +433 -0
  171. package/dist/runtime/drivers/persistent-cli-adapter.d.ts +160 -0
  172. package/dist/runtime/drivers/persistent-cli-adapter.js +396 -0
  173. package/dist/runtime/drivers/persistent-cli-process.d.ts +424 -0
  174. package/dist/runtime/drivers/persistent-cli-process.js +1543 -0
  175. package/dist/runtime/drivers/types.d.ts +456 -0
  176. package/dist/runtime/drivers/types.js +110 -0
  177. package/dist/runtime/mailbox.d.ts +223 -0
  178. package/dist/runtime/mailbox.js +582 -0
  179. package/dist/runtime/model-run-store.d.ts +28 -0
  180. package/dist/{model-runs/store.js → runtime/model-run-store.js} +81 -41
  181. package/dist/runtime/model-run-types.d.ts +132 -0
  182. package/dist/{model-runs/types.js → runtime/model-run-types.js} +1 -1
  183. package/dist/runtime/native-effect-observer.d.ts +22 -0
  184. package/dist/runtime/native-effect-observer.js +103 -0
  185. package/dist/runtime/native-input-journal.d.ts +46 -0
  186. package/dist/runtime/native-input-journal.js +308 -0
  187. package/dist/runtime/native-prompt.d.ts +118 -0
  188. package/dist/runtime/native-prompt.js +496 -0
  189. package/dist/runtime/native-session.d.ts +10 -0
  190. package/dist/{agent-graph/index.js → runtime/native-session.js} +9 -6
  191. package/dist/runtime/native-tool-trace-observer.d.ts +5 -0
  192. package/dist/runtime/native-tool-trace-observer.js +65 -0
  193. package/dist/runtime/native-turn.d.ts +272 -0
  194. package/dist/runtime/native-turn.js +1041 -0
  195. package/dist/runtime/operations.d.ts +236 -0
  196. package/dist/runtime/operations.js +565 -0
  197. package/dist/runtime/post-tool-handler.d.ts +74 -0
  198. package/dist/runtime/post-tool-handler.js +137 -0
  199. package/dist/runtime/prompt-layers.d.ts +126 -0
  200. package/dist/runtime/prompt-layers.js +239 -0
  201. package/dist/runtime/runtime-process.d.ts +102 -0
  202. package/dist/runtime/runtime-process.js +206 -0
  203. package/dist/runtime/runtime.d.ts +278 -0
  204. package/dist/runtime/runtime.js +563 -0
  205. package/dist/runtime/session-pool.d.ts +176 -0
  206. package/dist/runtime/session-pool.js +369 -0
  207. package/dist/runtime/stimulus-payload.d.ts +5 -0
  208. package/dist/runtime/stimulus-payload.js +50 -0
  209. package/dist/runtime/subagent-bridge.d.ts +24 -0
  210. package/dist/{agent-graph/types.js → runtime/subagent-bridge.js} +1 -1
  211. package/dist/runtime/text-completion.d.ts +22 -0
  212. package/dist/{agent-situation/types.js → runtime/text-completion.js} +1 -1
  213. package/dist/runtime/token-estimator.d.ts +25 -0
  214. package/dist/runtime/token-estimator.js +75 -0
  215. package/dist/runtime/tool-trace-store.d.ts +22 -0
  216. package/dist/runtime/tool-trace-store.js +242 -0
  217. package/dist/runtime/trace-summary.d.ts +5 -0
  218. package/dist/runtime/trace-summary.js +74 -0
  219. package/dist/runtime/turn-text.d.ts +23 -0
  220. package/dist/runtime/turn-text.js +41 -0
  221. package/dist/storage/database.d.ts +67 -0
  222. package/dist/storage/database.js +158 -0
  223. package/package.json +20 -34
  224. package/dist/agent-graph/alias-write.d.ts +0 -3
  225. package/dist/agent-graph/alias-write.js +0 -234
  226. package/dist/agent-graph/entity-resolve.d.ts +0 -3
  227. package/dist/agent-graph/entity-resolve.js +0 -271
  228. package/dist/agent-graph/errors.d.ts +0 -4
  229. package/dist/agent-graph/errors.js +0 -11
  230. package/dist/agent-graph/graph-query.d.ts +0 -5
  231. package/dist/agent-graph/graph-query.js +0 -360
  232. package/dist/agent-graph/index.d.ts +0 -6
  233. package/dist/agent-situation/builder.d.ts +0 -8
  234. package/dist/agent-situation/builder.js +0 -239
  235. package/dist/agent-situation/cache-key.d.ts +0 -4
  236. package/dist/agent-situation/cache-key.js +0 -64
  237. package/dist/agent-situation/index.d.ts +0 -7
  238. package/dist/agent-situation/index.js +0 -28
  239. package/dist/agent-situation/packet-store.d.ts +0 -27
  240. package/dist/agent-situation/packet-store.js +0 -228
  241. package/dist/agent-situation/ranking-policy.d.ts +0 -18
  242. package/dist/agent-situation/ranking-policy.js +0 -75
  243. package/dist/agent-situation/source-readers.d.ts +0 -52
  244. package/dist/agent-situation/source-readers.js +0 -300
  245. package/dist/agent-situation/types.d.ts +0 -195
  246. package/dist/cases/wiki-page-index.d.ts +0 -37
  247. package/dist/cases/wiki-page-index.js +0 -201
  248. package/dist/config-loader.d.ts +0 -68
  249. package/dist/config-loader.js +0 -239
  250. package/dist/connectors/event-index.d.ts +0 -24
  251. package/dist/connectors/event-index.js +0 -245
  252. package/dist/connectors/raw-query.d.ts +0 -40
  253. package/dist/connectors/raw-query.js +0 -412
  254. package/dist/connectors/types.d.ts +0 -117
  255. package/dist/connectors/types.js +0 -3
  256. package/dist/context-compile/boundary-defaults.d.ts +0 -12
  257. package/dist/context-compile/boundary-defaults.js +0 -105
  258. package/dist/context-compile/channel-grant.js +0 -66
  259. package/dist/context-compile/compiler-policy.d.ts +0 -39
  260. package/dist/context-compile/compiler-policy.js +0 -147
  261. package/dist/context-compile/compiler.d.ts +0 -18
  262. package/dist/context-compile/compiler.js +0 -404
  263. package/dist/context-compile/index.d.ts +0 -10
  264. package/dist/context-compile/index.js +0 -26
  265. package/dist/context-compile/packet-store.d.ts +0 -8
  266. package/dist/context-compile/packet-store.js +0 -239
  267. package/dist/context-compile/ref.d.ts +0 -7
  268. package/dist/context-compile/ref.js +0 -102
  269. package/dist/context-compile/source-readers.d.ts +0 -70
  270. package/dist/context-compile/source-readers.js +0 -840
  271. package/dist/context-compile/types.d.ts +0 -155
  272. package/dist/context-compile/types.js +0 -11
  273. package/dist/context-compile/visibility.d.ts +0 -21
  274. package/dist/context-compile/visibility.js +0 -224
  275. package/dist/decision-tracker.d.ts +0 -206
  276. package/dist/decision-tracker.js +0 -481
  277. package/dist/edges/ref-validation.d.ts +0 -7
  278. package/dist/edges/ref-validation.js +0 -321
  279. package/dist/edges/store.d.ts +0 -8
  280. package/dist/edges/store.js +0 -129
  281. package/dist/embedding-client.d.ts +0 -28
  282. package/dist/embedding-client.js +0 -53
  283. package/dist/embedding-server/index.d.ts +0 -67
  284. package/dist/embedding-server/index.js +0 -405
  285. package/dist/embedding-server/mobile/auth.d.ts +0 -44
  286. package/dist/embedding-server/mobile/auth.js +0 -150
  287. package/dist/embedding-server/mobile/daemon.d.ts +0 -129
  288. package/dist/embedding-server/mobile/daemon.js +0 -313
  289. package/dist/embedding-server/mobile/output-parser.d.ts +0 -115
  290. package/dist/embedding-server/mobile/output-parser.js +0 -241
  291. package/dist/embedding-server/mobile/session-api.d.ts +0 -57
  292. package/dist/embedding-server/mobile/session-api.js +0 -261
  293. package/dist/embedding-server/mobile/session-manager.d.ts +0 -138
  294. package/dist/embedding-server/mobile/session-manager.js +0 -378
  295. package/dist/embedding-server/mobile/websocket-handler.d.ts +0 -137
  296. package/dist/embedding-server/mobile/websocket-handler.js +0 -486
  297. package/dist/embeddings.d.ts +0 -68
  298. package/dist/embeddings.js +0 -244
  299. package/dist/entities/audit-metrics.d.ts +0 -68
  300. package/dist/entities/audit-metrics.js +0 -124
  301. package/dist/entities/candidate-generator.d.ts +0 -8
  302. package/dist/entities/candidate-generator.js +0 -24
  303. package/dist/entities/entity-linked-decision-counts.d.ts +0 -2
  304. package/dist/entities/entity-linked-decision-counts.js +0 -29
  305. package/dist/entities/entity-list.d.ts +0 -22
  306. package/dist/entities/entity-list.js +0 -3
  307. package/dist/entities/entity-orphan-list.d.ts +0 -17
  308. package/dist/entities/entity-orphan-list.js +0 -3
  309. package/dist/entities/entity-search.d.ts +0 -20
  310. package/dist/entities/entity-search.js +0 -3
  311. package/dist/entities/errors.d.ts +0 -55
  312. package/dist/entities/errors.js +0 -100
  313. package/dist/entities/lineage-store.d.ts +0 -28
  314. package/dist/entities/lineage-store.js +0 -204
  315. package/dist/entities/normalization.d.ts +0 -14
  316. package/dist/entities/normalization.js +0 -63
  317. package/dist/entities/policy-store.d.ts +0 -8
  318. package/dist/entities/policy-store.js +0 -75
  319. package/dist/entities/policy-types.d.ts +0 -72
  320. package/dist/entities/policy-types.js +0 -59
  321. package/dist/entities/projection.d.ts +0 -8
  322. package/dist/entities/projection.js +0 -82
  323. package/dist/entities/provenance-query.d.ts +0 -32
  324. package/dist/entities/provenance-query.js +0 -3
  325. package/dist/entities/read-identity.d.ts +0 -31
  326. package/dist/entities/read-identity.js +0 -264
  327. package/dist/entities/recall-bridge.d.ts +0 -5
  328. package/dist/entities/recall-bridge.js +0 -171
  329. package/dist/entities/resolution-engine.d.ts +0 -8
  330. package/dist/entities/resolution-engine.js +0 -3
  331. package/dist/entities/rollback-preview.d.ts +0 -35
  332. package/dist/entities/rollback-preview.js +0 -3
  333. package/dist/entities/source-locator.d.ts +0 -3
  334. package/dist/entities/source-locator.js +0 -32
  335. package/dist/entities/store.d.ts +0 -69
  336. package/dist/entities/store.js +0 -544
  337. package/dist/entities/types.d.ts +0 -166
  338. package/dist/entities/types.js +0 -30
  339. package/dist/memory/extraction-prompt.d.ts +0 -4
  340. package/dist/memory/extraction-prompt.js +0 -89
  341. package/dist/memory/scope-backfill.d.ts +0 -14
  342. package/dist/memory/scope-backfill.js +0 -3
  343. package/dist/memory/scope-store.d.ts +0 -4
  344. package/dist/memory/scope-store.js +0 -9
  345. package/dist/memory-store.d.ts +0 -87
  346. package/dist/memory-store.js +0 -78
  347. package/dist/model-runs/store.d.ts +0 -13
  348. package/dist/model-runs/tool-trace-store.d.ts +0 -4
  349. package/dist/model-runs/tool-trace-store.js +0 -118
  350. package/dist/model-runs/types.d.ts +0 -72
  351. package/dist/notification-manager.d.ts +0 -7
  352. package/dist/notification-manager.js +0 -12
  353. package/dist/outcome-tracker.d.ts +0 -151
  354. package/dist/outcome-tracker.js +0 -271
  355. package/dist/query-intent.d.ts +0 -23
  356. package/dist/query-intent.js +0 -114
  357. package/dist/runtime/trusted-provenance.d.ts +0 -3
  358. package/dist/runtime/trusted-provenance.js +0 -6
  359. package/dist/search/question-type.d.ts +0 -5
  360. package/dist/search/question-type.js +0 -41
  361. package/dist/test-utils.d.ts +0 -80
  362. package/dist/test-utils.js +0 -218
  363. package/dist/tier-validator.d.ts +0 -43
  364. package/dist/tier-validator.js +0 -159
  365. package/dist/time-formatter.d.ts +0 -25
  366. package/dist/time-formatter.js +0 -93
  367. /package/dist/{search → knowledge}/feedback-store.d.ts +0 -0
  368. /package/dist/{search → knowledge}/feedback-store.js +0 -0
  369. /package/dist/{search → knowledge}/ranker-features.d.ts +0 -0
  370. /package/dist/{search → knowledge}/ranker-rescore.d.ts +0 -0
  371. /package/dist/{search → knowledge}/ranker-rescore.js +0 -0
  372. /package/dist/{search → knowledge}/ranker-trainer.d.ts +0 -0
  373. /package/dist/{search → knowledge}/ranker-trainer.js +0 -0
  374. /package/dist/{search → knowledge}/search-quality.js +0 -0
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Knowledge observations: immutable observation versions and the visibility
3
+ * rule that decides which of them a caller may read. A cited observation must
4
+ * satisfy the same rule as a row the reader would have returned.
5
+ *
6
+ * @module knowledge/observations
7
+ */
8
+ import type { DatabaseAdapter } from '../db-manager.js';
9
+ import type { MemoryScopeRef } from '../memory/types.js';
10
+ type ObservationAdapter = Pick<DatabaseAdapter, 'prepare'>;
11
+ type ObservationVisibilityAdapter = Pick<DatabaseAdapter, 'prepare'>;
12
+ export interface ObservationBodyLocation {
13
+ kind: 'raw';
14
+ connectorName: string;
15
+ revisionSourceId: string;
16
+ }
17
+ export interface ObservationVersionInput {
18
+ /**
19
+ * Where this came from -- a namespace, paired with `sourceId` inside it. It was
20
+ * `sourceConnector`; a deployment with no connectors still observes things.
21
+ */
22
+ source: string;
23
+ sourceId: string;
24
+ producerVersionId?: string | null;
25
+ body?: string;
26
+ bodyLocation?: ObservationBodyLocation;
27
+ author?: string | null;
28
+ sourceAt?: number | null;
29
+ observedAt: number;
30
+ contentHash: string;
31
+ metadata?: Record<string, unknown> | null;
32
+ /**
33
+ * What was observed, beyond its body. These lived only on the connector index,
34
+ * which is why a core read had to go there to answer what a memory rests on.
35
+ */
36
+ sourceType?: string | null;
37
+ sourceLocator?: string | null;
38
+ title?: string | null;
39
+ artifactLocator?: string | null;
40
+ artifactTitle?: string | null;
41
+ eventDate?: string | null;
42
+ sourceEntityId?: string | null;
43
+ /**
44
+ * Who may see it. Columns rather than a JSON blob because raw visibility is a
45
+ * WHERE clause as well as a predicate, and the two are pinned against each other.
46
+ */
47
+ channel?: string | null;
48
+ projectId?: string | null;
49
+ tenantId?: string | null;
50
+ memoryScopeKind?: string | null;
51
+ memoryScopeId?: string | null;
52
+ scope?: Record<string, unknown> | null;
53
+ }
54
+ export interface ObservationVersionRecord {
55
+ observationId: string;
56
+ source: string;
57
+ sourceId: string;
58
+ producerVersionId: string | null;
59
+ body: string | null;
60
+ bodyLocation: ObservationBodyLocation | null;
61
+ author: string | null;
62
+ sourceAt: number | null;
63
+ observedAt: number;
64
+ contentHash: string;
65
+ metadata: Record<string, unknown>;
66
+ sourceType: string | null;
67
+ sourceLocator: string | null;
68
+ title: string | null;
69
+ artifactLocator: string | null;
70
+ artifactTitle: string | null;
71
+ eventDate: string | null;
72
+ sourceEntityId: string | null;
73
+ channel: string | null;
74
+ projectId: string | null;
75
+ tenantId: string | null;
76
+ memoryScopeKind: string | null;
77
+ memoryScopeId: string | null;
78
+ scope: Record<string, unknown>;
79
+ }
80
+ export interface OwnerObservationSearchItem {
81
+ observationRef: string;
82
+ source: string;
83
+ sourceId: string;
84
+ author: string | null;
85
+ sourceAt: number | null;
86
+ observedAt: number;
87
+ contentPreview: string;
88
+ metadataPreview: string;
89
+ }
90
+ export interface ObservationBodyReader {
91
+ readVersion(input: ObservationBodyLocation & {
92
+ expectedContentHash: string;
93
+ }): {
94
+ status: 'available';
95
+ body: string;
96
+ contentHash: string;
97
+ } | {
98
+ status: 'version_unavailable';
99
+ reason: 'VERSION_NOT_FOUND' | 'HASH_MISMATCH';
100
+ };
101
+ }
102
+ export type ObservationReadResult = {
103
+ status: 'available';
104
+ observation: ObservationVersionRecord;
105
+ body: string;
106
+ } | {
107
+ status: 'version_unavailable';
108
+ observation: ObservationVersionRecord;
109
+ reason: 'BODY_READER_UNAVAILABLE' | 'VERSION_NOT_FOUND' | 'HASH_MISMATCH';
110
+ } | {
111
+ status: 'not_found';
112
+ };
113
+ export declare function observationVersionId(input: ObservationVersionInput): string;
114
+ export declare function appendObservationVersion(adapter: ObservationAdapter, input: ObservationVersionInput): ObservationVersionRecord;
115
+ /**
116
+ * The observation's source, without reading the rest of it.
117
+ *
118
+ * A caller deciding whether a row is an owner observation needs one column. It
119
+ * asks for one: mapping the whole record would parse a body and a metadata
120
+ * blob it does not use, and a row whose metadata is malformed would then fail
121
+ * loudly where the answer is simply "not yours" — the disclosure the visibility
122
+ * check exists to avoid.
123
+ */
124
+ export declare function getObservationVersionSource(adapter: ObservationAdapter, observationId: string): string | null;
125
+ export declare function getObservationVersion(adapter: ObservationAdapter, observationId: string): ObservationVersionRecord | null;
126
+ export declare function searchOwnerObservationVersions(adapter: ObservationAdapter, input: {
127
+ query: string;
128
+ principalId: string;
129
+ agentId: string;
130
+ connectors?: string[];
131
+ connectorChannels?: Readonly<Record<string, readonly string[]>>;
132
+ fromMs?: number;
133
+ toMs?: number;
134
+ cursor?: string;
135
+ limit?: number;
136
+ }): {
137
+ items: OwnerObservationSearchItem[];
138
+ nextCursor: string | null;
139
+ };
140
+ export declare function readObservationVersion(adapter: ObservationAdapter, observationId: string, reader?: ObservationBodyReader, options?: {
141
+ maxSourceMs?: number | null;
142
+ }): ObservationReadResult;
143
+ export interface ObservationVisibilityAuthority {
144
+ principalId?: string;
145
+ agentId?: string;
146
+ scopes?: readonly MemoryScopeRef[];
147
+ connectors?: readonly string[];
148
+ connectorWideRead?: readonly string[];
149
+ channels?: Readonly<Record<string, readonly string[]>>;
150
+ maxSourceMs?: number | null;
151
+ }
152
+ export interface ObservationVisibilityRow {
153
+ source: unknown;
154
+ scope_json: unknown;
155
+ source_at?: unknown;
156
+ }
157
+ export declare function isObservationVersionVisible(adapter: ObservationVisibilityAdapter, observationId: string, authority: ObservationVisibilityAuthority): boolean;
158
+ export declare function isObservationVisibilityRowVisible(row: ObservationVisibilityRow, authority: ObservationVisibilityAuthority): boolean;
159
+ export {};
160
+ //# sourceMappingURL=observations.d.ts.map
@@ -0,0 +1,449 @@
1
+ "use strict";
2
+ /**
3
+ * Knowledge observations: immutable observation versions and the visibility
4
+ * rule that decides which of them a caller may read. A cited observation must
5
+ * satisfy the same rule as a row the reader would have returned.
6
+ *
7
+ * @module knowledge/observations
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.observationVersionId = observationVersionId;
11
+ exports.appendObservationVersion = appendObservationVersion;
12
+ exports.getObservationVersionSource = getObservationVersionSource;
13
+ exports.getObservationVersion = getObservationVersion;
14
+ exports.searchOwnerObservationVersions = searchOwnerObservationVersions;
15
+ exports.readObservationVersion = readObservationVersion;
16
+ exports.isObservationVersionVisible = isObservationVersionVisible;
17
+ exports.isObservationVisibilityRowVisible = isObservationVisibilityRowVisible;
18
+ const node_crypto_1 = require("node:crypto");
19
+ const canonicalize_js_1 = require("../canonicalize.js");
20
+ function parseObject(value, field) {
21
+ if (typeof value !== 'string') {
22
+ throw new Error(`observation_versions.${field} must be JSON text`);
23
+ }
24
+ let parsed;
25
+ try {
26
+ parsed = JSON.parse(value);
27
+ }
28
+ catch (error) {
29
+ const message = error instanceof Error ? error.message : String(error);
30
+ throw new Error(`observation_versions.${field} is malformed JSON: ${message}`);
31
+ }
32
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
33
+ throw new Error(`observation_versions.${field} must contain a JSON object`);
34
+ }
35
+ return parsed;
36
+ }
37
+ function nullableString(value, field) {
38
+ if (value === null) {
39
+ return null;
40
+ }
41
+ if (typeof value !== 'string') {
42
+ throw new Error(`observation_versions.${field} must be text or null`);
43
+ }
44
+ return value;
45
+ }
46
+ function finiteNumber(value, field, nullable = false) {
47
+ if (nullable && value === null) {
48
+ return null;
49
+ }
50
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
51
+ throw new Error(`observation_versions.${field} must be a finite number${nullable ? ' or null' : ''}`);
52
+ }
53
+ return value;
54
+ }
55
+ function mapRow(row) {
56
+ if (typeof row.observation_id !== 'string' || row.observation_id.trim() === '') {
57
+ throw new Error('observation_versions.observation_id must be nonblank text');
58
+ }
59
+ if (typeof row.source !== 'string' || row.source.trim() === '') {
60
+ throw new Error('observation_versions.source must be nonblank text');
61
+ }
62
+ if (typeof row.source_id !== 'string' || row.source_id.trim() === '') {
63
+ throw new Error('observation_versions.source_id must be nonblank text');
64
+ }
65
+ if (typeof row.content_hash !== 'string' || row.content_hash.trim() === '') {
66
+ throw new Error('observation_versions.content_hash must be nonblank text');
67
+ }
68
+ const body = nullableString(row.body, 'body');
69
+ const bodyLocationJson = nullableString(row.body_location_json, 'body_location_json');
70
+ if ((body === null) === (bodyLocationJson === null)) {
71
+ throw new Error('observation_versions row requires exactly one body source');
72
+ }
73
+ const bodyLocation = bodyLocationJson
74
+ ? parseObject(bodyLocationJson, 'body_location_json')
75
+ : null;
76
+ if (bodyLocation &&
77
+ (bodyLocation.kind !== 'raw' ||
78
+ typeof bodyLocation.connectorName !== 'string' ||
79
+ typeof bodyLocation.revisionSourceId !== 'string' ||
80
+ bodyLocation.connectorName.trim() === '' ||
81
+ bodyLocation.revisionSourceId.trim() === '')) {
82
+ throw new Error('observation_versions.body_location_json has an invalid raw locator');
83
+ }
84
+ return {
85
+ observationId: row.observation_id,
86
+ source: row.source,
87
+ sourceId: row.source_id,
88
+ producerVersionId: nullableString(row.producer_version_id, 'producer_version_id'),
89
+ body,
90
+ bodyLocation: bodyLocation,
91
+ author: nullableString(row.author, 'author'),
92
+ sourceAt: finiteNumber(row.source_at, 'source_at', true),
93
+ observedAt: finiteNumber(row.observed_at, 'observed_at'),
94
+ contentHash: row.content_hash,
95
+ metadata: parseObject(row.metadata_json, 'metadata_json'),
96
+ sourceType: nullableString(row.source_type, 'source_type'),
97
+ sourceLocator: nullableString(row.source_locator, 'source_locator'),
98
+ title: nullableString(row.title, 'title'),
99
+ artifactLocator: nullableString(row.artifact_locator, 'artifact_locator'),
100
+ artifactTitle: nullableString(row.artifact_title, 'artifact_title'),
101
+ eventDate: nullableString(row.event_date, 'event_date'),
102
+ sourceEntityId: nullableString(row.source_entity_id, 'source_entity_id'),
103
+ channel: nullableString(row.channel, 'channel'),
104
+ projectId: nullableString(row.project_id, 'project_id'),
105
+ tenantId: nullableString(row.tenant_id, 'tenant_id'),
106
+ memoryScopeKind: nullableString(row.memory_scope_kind, 'memory_scope_kind'),
107
+ memoryScopeId: nullableString(row.memory_scope_id, 'memory_scope_id'),
108
+ scope: parseObject(row.scope_json, 'scope_json'),
109
+ };
110
+ }
111
+ function sameObservation(actual, input, scope) {
112
+ return (actual.source === input.source &&
113
+ actual.sourceId === input.sourceId &&
114
+ actual.producerVersionId === (input.producerVersionId ?? null) &&
115
+ actual.body === (input.body ?? null) &&
116
+ (0, canonicalize_js_1.canonicalizeJSON)(actual.bodyLocation) === (0, canonicalize_js_1.canonicalizeJSON)(input.bodyLocation ?? null) &&
117
+ actual.author === (input.author ?? null) &&
118
+ actual.sourceAt === (input.sourceAt ?? null) &&
119
+ actual.observedAt === Math.floor(input.observedAt) &&
120
+ actual.contentHash === input.contentHash &&
121
+ (0, canonicalize_js_1.canonicalizeJSON)(actual.metadata) === (0, canonicalize_js_1.canonicalizeJSON)(input.metadata ?? {}) &&
122
+ (0, canonicalize_js_1.canonicalizeJSON)(actual.scope) === (0, canonicalize_js_1.canonicalizeJSON)(scope));
123
+ }
124
+ function observationVersionId(input) {
125
+ const identity = (0, canonicalize_js_1.canonicalizeJSON)({
126
+ source: input.source,
127
+ sourceId: input.sourceId,
128
+ producerVersionId: input.producerVersionId ?? null,
129
+ ...(input.producerVersionId === null || input.producerVersionId === undefined
130
+ ? { contentHash: input.contentHash }
131
+ : {}),
132
+ });
133
+ return `obs_${(0, node_crypto_1.createHash)('sha256').update(identity).digest('hex').slice(0, 24)}`;
134
+ }
135
+ function appendObservationVersion(adapter, input) {
136
+ if ((input.body === undefined) === (input.bodyLocation === undefined)) {
137
+ throw new Error('Observation requires exactly one of body or bodyLocation.');
138
+ }
139
+ if (!Number.isFinite(input.observedAt)) {
140
+ throw new Error('Observation observedAt must be finite.');
141
+ }
142
+ for (const [field, value] of [
143
+ ['source', input.source],
144
+ ['sourceId', input.sourceId],
145
+ ['contentHash', input.contentHash],
146
+ ]) {
147
+ if (!value.trim()) {
148
+ throw new Error(`Observation ${field} must be nonblank.`);
149
+ }
150
+ }
151
+ // The scope bag and the scope columns are one fact in two shapes: the bag is what
152
+ // was stated, the columns are what a WHERE clause can reach. Deriving the columns
153
+ // here, once, is what keeps them from disagreeing -- a caller that fills only one
154
+ // of the two is how they drift apart.
155
+ const scope = input.scope ?? {};
156
+ const fromScope = (key, explicit) => {
157
+ if (explicit !== undefined) {
158
+ return explicit;
159
+ }
160
+ const value = scope[key];
161
+ return typeof value === 'string' && value !== '' ? value : null;
162
+ };
163
+ const channel = fromScope('channel', input.channel);
164
+ const projectId = fromScope('projectId', input.projectId);
165
+ const tenantId = fromScope('tenantId', input.tenantId);
166
+ const memoryScopeKind = fromScope('memoryScopeKind', input.memoryScopeKind);
167
+ const memoryScopeId = fromScope('memoryScopeId', input.memoryScopeId);
168
+ // And the other direction. A caller that named the scope as columns has said the
169
+ // same thing as one that named it in the bag, and the two readers -- a WHERE
170
+ // clause over the columns, a predicate over the bag -- must not disagree about it.
171
+ const scopeBag = { ...scope };
172
+ for (const [key, value] of [
173
+ ['channel', channel],
174
+ ['projectId', projectId],
175
+ ['tenantId', tenantId],
176
+ ['memoryScopeKind', memoryScopeKind],
177
+ ['memoryScopeId', memoryScopeId],
178
+ ]) {
179
+ if (value !== null && scopeBag[key] === undefined) {
180
+ scopeBag[key] = value;
181
+ }
182
+ }
183
+ const id = observationVersionId(input);
184
+ adapter
185
+ .prepare(`INSERT OR IGNORE INTO observation_versions (
186
+ observation_id, source, source_id, producer_version_id, body,
187
+ body_location_json, author, source_at, observed_at, content_hash, metadata_json, scope_json,
188
+ source_type, source_locator, title, artifact_locator, artifact_title, event_date,
189
+ source_entity_id, channel, project_id, tenant_id, memory_scope_kind, memory_scope_id
190
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
191
+ .run(id, input.source, input.sourceId, input.producerVersionId ?? null, input.body ?? null, input.bodyLocation ? (0, canonicalize_js_1.canonicalizeJSON)(input.bodyLocation) : null, input.author ?? null, input.sourceAt ?? null, Math.floor(input.observedAt), input.contentHash, (0, canonicalize_js_1.canonicalizeJSON)(input.metadata ?? {}), (0, canonicalize_js_1.canonicalizeJSON)(scopeBag), input.sourceType ?? null, input.sourceLocator ?? null, input.title ?? null, input.artifactLocator ?? null, input.artifactTitle ?? null, input.eventDate ?? null, input.sourceEntityId ?? null, channel, projectId, tenantId, memoryScopeKind, memoryScopeId);
192
+ const record = getObservationVersion(adapter, id);
193
+ if (!record) {
194
+ throw new Error(`Failed to persist observation ${id}`);
195
+ }
196
+ if (!sameObservation(record, input, scopeBag)) {
197
+ throw new Error(`Observation replay conflict for ${id}`);
198
+ }
199
+ return record;
200
+ }
201
+ /**
202
+ * The observation's source, without reading the rest of it.
203
+ *
204
+ * A caller deciding whether a row is an owner observation needs one column. It
205
+ * asks for one: mapping the whole record would parse a body and a metadata
206
+ * blob it does not use, and a row whose metadata is malformed would then fail
207
+ * loudly where the answer is simply "not yours" — the disclosure the visibility
208
+ * check exists to avoid.
209
+ */
210
+ function getObservationVersionSource(adapter, observationId) {
211
+ const row = adapter
212
+ .prepare('SELECT source FROM observation_versions WHERE observation_id = ? LIMIT 1')
213
+ .get(observationId);
214
+ if (!row) {
215
+ return null;
216
+ }
217
+ if (typeof row.source !== 'string' || row.source.trim() === '') {
218
+ throw new Error('observation_versions.source must be nonblank text');
219
+ }
220
+ return row.source;
221
+ }
222
+ function getObservationVersion(adapter, observationId) {
223
+ const row = adapter
224
+ .prepare('SELECT * FROM observation_versions WHERE observation_id = ? LIMIT 1')
225
+ .get(observationId);
226
+ return row ? mapRow(row) : null;
227
+ }
228
+ function searchOwnerObservationVersions(adapter, input) {
229
+ const query = input.query.trim();
230
+ const limit = Math.min(100, Math.max(1, Math.floor(input.limit ?? 25)));
231
+ const clauses = [
232
+ "(source LIKE 'owner-message:%' OR source LIKE 'owner-result:%')",
233
+ "json_extract(scope_json, '$.visibility') = 'owner'",
234
+ "json_extract(scope_json, '$.principalId') = ?",
235
+ "json_extract(scope_json, '$.agentId') = ?",
236
+ ];
237
+ const params = [input.principalId, input.agentId];
238
+ const connectors = [...new Set((input.connectors ?? []).map((value) => value.trim()))].filter(Boolean);
239
+ if (input.connectors !== undefined && connectors.length === 0) {
240
+ return { items: [], nextCursor: null };
241
+ }
242
+ if (connectors.length > 0) {
243
+ clauses.push(`source IN (${connectors.map(() => '?').join(', ')})`);
244
+ params.push(...connectors);
245
+ }
246
+ if (input.connectorChannels !== undefined) {
247
+ const pairs = Object.entries(input.connectorChannels)
248
+ .map(([connector, values]) => [
249
+ connector.trim(),
250
+ [...new Set(values.map((value) => value.trim()).filter(Boolean))],
251
+ ])
252
+ .filter(([connector, values]) => connector.length > 0 && values.length > 0);
253
+ if (pairs.length === 0) {
254
+ return { items: [], nextCursor: null };
255
+ }
256
+ clauses.push(`(${pairs
257
+ .map(([, values]) => `(source IN (?, ?) AND channel IN (${values.map(() => '?').join(', ')}))`)
258
+ .join(' OR ')})`);
259
+ for (const [connector, values] of pairs) {
260
+ params.push(`owner-message:${connector}`, `owner-result:${connector}`, ...values);
261
+ }
262
+ }
263
+ if (input.fromMs !== undefined) {
264
+ clauses.push('observed_at >= ?');
265
+ params.push(input.fromMs);
266
+ }
267
+ if (input.toMs !== undefined) {
268
+ clauses.push('observed_at <= ?');
269
+ params.push(input.toMs);
270
+ }
271
+ if (query) {
272
+ clauses.push('(instr(body, ?) > 0 OR instr(metadata_json, ?) > 0)');
273
+ params.push(query, query);
274
+ }
275
+ if (input.cursor) {
276
+ let cursor;
277
+ try {
278
+ cursor = JSON.parse(Buffer.from(input.cursor, 'base64url').toString('utf8'));
279
+ }
280
+ catch {
281
+ throw new Error('Invalid owner observation cursor.');
282
+ }
283
+ if (!cursor ||
284
+ typeof cursor !== 'object' ||
285
+ Array.isArray(cursor) ||
286
+ !Number.isFinite(cursor.observedAt) ||
287
+ typeof cursor.observationId !== 'string' ||
288
+ !cursor.observationId) {
289
+ throw new Error('Invalid owner observation cursor.');
290
+ }
291
+ clauses.push('(observed_at < ? OR (observed_at = ? AND observation_id > ?))');
292
+ params.push(cursor.observedAt, cursor.observedAt, cursor.observationId);
293
+ }
294
+ const rows = adapter
295
+ .prepare(`SELECT * FROM observation_versions
296
+ WHERE ${clauses.join(' AND ')}
297
+ ORDER BY observed_at DESC, observation_id ASC
298
+ LIMIT ?`)
299
+ .all(...params, limit + 1);
300
+ const pageRows = rows.slice(0, limit);
301
+ const last = rows.length > limit ? pageRows[pageRows.length - 1] : undefined;
302
+ return {
303
+ items: pageRows.map((row) => {
304
+ const record = mapRow(row);
305
+ const compact = (record.body ?? '').replace(/\s+/g, ' ').trim();
306
+ return {
307
+ observationRef: record.observationId,
308
+ source: record.source,
309
+ sourceId: record.sourceId,
310
+ author: record.author,
311
+ sourceAt: record.sourceAt,
312
+ observedAt: record.observedAt,
313
+ contentPreview: compact.length > 500 ? `${compact.slice(0, 497)}...` : compact,
314
+ metadataPreview: (0, canonicalize_js_1.canonicalizeJSON)(record.metadata).slice(0, 500),
315
+ };
316
+ }),
317
+ nextCursor: last
318
+ ? Buffer.from(JSON.stringify({
319
+ observedAt: Number(last.observed_at),
320
+ observationId: String(last.observation_id),
321
+ })).toString('base64url')
322
+ : null,
323
+ };
324
+ }
325
+ function readObservationVersion(adapter, observationId, reader, options) {
326
+ const observation = getObservationVersion(adapter, observationId);
327
+ if (!observation) {
328
+ return { status: 'not_found' };
329
+ }
330
+ const maxSourceMs = options?.maxSourceMs ?? null;
331
+ if (maxSourceMs !== null) {
332
+ if (!Number.isSafeInteger(maxSourceMs) || maxSourceMs < 0) {
333
+ throw new Error('Observation source ceiling must be a nonnegative epoch millisecond integer');
334
+ }
335
+ if (observation.sourceAt === null || observation.sourceAt > maxSourceMs) {
336
+ return { status: 'not_found' };
337
+ }
338
+ }
339
+ if (observation.body !== null) {
340
+ return { status: 'available', observation, body: observation.body };
341
+ }
342
+ if (!reader || !observation.bodyLocation) {
343
+ return { status: 'version_unavailable', observation, reason: 'BODY_READER_UNAVAILABLE' };
344
+ }
345
+ const result = reader.readVersion({
346
+ ...observation.bodyLocation,
347
+ expectedContentHash: observation.contentHash,
348
+ });
349
+ if (result.status === 'available') {
350
+ return result.contentHash === observation.contentHash
351
+ ? { status: 'available', observation, body: result.body }
352
+ : { status: 'version_unavailable', observation, reason: 'HASH_MISMATCH' };
353
+ }
354
+ return { status: 'version_unavailable', observation, reason: result.reason };
355
+ }
356
+ function parseScopeJson(value) {
357
+ if (typeof value !== 'string') {
358
+ throw new Error('observation_versions.scope_json must be JSON text');
359
+ }
360
+ let parsed;
361
+ try {
362
+ parsed = JSON.parse(value);
363
+ }
364
+ catch (error) {
365
+ const message = error instanceof Error ? error.message : String(error);
366
+ throw new Error(`observation_versions.scope_json is malformed JSON: ${message}`);
367
+ }
368
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
369
+ throw new Error('observation_versions.scope_json must contain a JSON object');
370
+ }
371
+ return parsed;
372
+ }
373
+ function matchesScope(scope, visible) {
374
+ if (visible.kind === 'project') {
375
+ return (scope.projectId === visible.id ||
376
+ (scope.memoryScopeKind === 'project' && scope.memoryScopeId === visible.id));
377
+ }
378
+ if (visible.kind === 'channel') {
379
+ return (scope.channel === visible.id ||
380
+ (scope.memoryScopeKind === 'channel' && scope.memoryScopeId === visible.id));
381
+ }
382
+ return scope.memoryScopeKind === visible.kind && scope.memoryScopeId === visible.id;
383
+ }
384
+ function isObservationVersionVisible(adapter, observationId, authority) {
385
+ const row = adapter
386
+ .prepare(`SELECT scope_json, source, source_at
387
+ FROM observation_versions WHERE observation_id = ?`)
388
+ .get(observationId);
389
+ if (!row) {
390
+ return false;
391
+ }
392
+ return isObservationVisibilityRowVisible(row, authority);
393
+ }
394
+ function isObservationVisibilityRowVisible(row, authority) {
395
+ const principalId = authority.principalId?.trim();
396
+ const agentId = authority.agentId?.trim();
397
+ if (!principalId || !agentId) {
398
+ return false;
399
+ }
400
+ const maxSourceMs = authority.maxSourceMs ?? null;
401
+ if (maxSourceMs !== null) {
402
+ if (!Number.isSafeInteger(maxSourceMs) || maxSourceMs < 0) {
403
+ throw new Error('Observation source ceiling must be a nonnegative epoch millisecond integer');
404
+ }
405
+ const sourceAt = typeof row.source_at === 'number' ? row.source_at : null;
406
+ if (sourceAt === null || sourceAt > maxSourceMs)
407
+ return false;
408
+ }
409
+ if (typeof row.source !== 'string' || !row.source.trim()) {
410
+ throw new Error('observation_versions.source must be nonblank text');
411
+ }
412
+ const ownerConnector = /^owner-(?:message|result):(.+)$/.exec(row.source)?.[1];
413
+ const connector = ownerConnector ?? row.source;
414
+ if (!authority.connectors?.includes(connector)) {
415
+ return false;
416
+ }
417
+ const scope = parseScopeJson(row.scope_json);
418
+ const connectorWideRead = authority.connectorWideRead?.includes(connector) === true;
419
+ if (authority.channels && !connectorWideRead) {
420
+ const visibleChannels = authority.channels[connector];
421
+ const channel = typeof scope.channel === 'string' ? scope.channel : null;
422
+ const normalizedChannel = channel?.startsWith(`${connector}:`)
423
+ ? channel.slice(connector.length + 1)
424
+ : channel;
425
+ if (!visibleChannels ||
426
+ channel === null ||
427
+ (!visibleChannels.includes(channel) &&
428
+ (normalizedChannel === null || !visibleChannels.includes(normalizedChannel)))) {
429
+ return false;
430
+ }
431
+ }
432
+ if (ownerConnector !== undefined || scope.visibility === 'owner') {
433
+ if (ownerConnector === undefined || scope.visibility !== 'owner') {
434
+ throw new Error('owner observation connector and scope visibility are inconsistent');
435
+ }
436
+ return scope.principalId === principalId && scope.agentId === agentId;
437
+ }
438
+ // A current connector/channel grant is the same read authority source.read
439
+ // applies. Imported originals can have no project or memory-scope tag; that
440
+ // absence does not revoke an explicitly granted source read in the graph.
441
+ if (connectorWideRead || authority.channels) {
442
+ return true;
443
+ }
444
+ if (!authority.scopes || authority.scopes.length === 0) {
445
+ return false;
446
+ }
447
+ return authority.scopes.some((visible) => matchesScope(scope, visible));
448
+ }
449
+ //# sourceMappingURL=observations.js.map
@@ -0,0 +1,34 @@
1
+ /**
2
+ * What a search query is asking for.
3
+ *
4
+ * The classifier is a mechanism: an ordered list of patterns, first match wins. The
5
+ * WORDS are not. Two of them named connectors that one deployment happens to run,
6
+ * which told every other product installing this core that asking about that
7
+ * connector is asking about an artifact, whether or not it has one.
8
+ *
9
+ * So the words are injectable. The default below carries only words that name no
10
+ * product: what a file is, what a date is, what asking "why" looks like. A caller
11
+ * with its own domain adds to it.
12
+ */
13
+ export type QuestionType = 'correction' | 'artifact' | 'timeline' | 'status' | 'decision_reason' | 'how_to' | 'unknown';
14
+ export declare const QUESTION_TYPES: readonly QuestionType[];
15
+ /** One question type and the pattern that names it. Order is the precedence. */
16
+ export interface QuestionPattern {
17
+ readonly type: Exclude<QuestionType, 'unknown'>;
18
+ readonly pattern: RegExp;
19
+ }
20
+ export type QuestionVocabulary = readonly QuestionPattern[];
21
+ export declare const DEFAULT_QUESTION_VOCABULARY: QuestionVocabulary;
22
+ /**
23
+ * Declare the words this deployment asks questions with. Call once, at boot.
24
+ *
25
+ * Replaces the default outright rather than merging: a caller that wants the general
26
+ * words plus its own spreads DEFAULT_QUESTION_VOCABULARY itself, and can see in one
27
+ * place what its classifier actually knows.
28
+ */
29
+ export declare function declareQuestionVocabulary(next: QuestionVocabulary): void;
30
+ /** Restore the default. For tests that declared their own. */
31
+ export declare function resetQuestionVocabulary(): void;
32
+ export declare function classifyQuestionType(query: string): QuestionType;
33
+ export declare function isQuestionType(value: string): value is QuestionType;
34
+ //# sourceMappingURL=question-type.d.ts.map