@graphorin/memory 0.5.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 (287) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +21 -0
  3. package/README.md +401 -0
  4. package/dist/conflict/index.d.ts +3 -0
  5. package/dist/conflict/index.js +7 -0
  6. package/dist/conflict/locale-packs/en.js +262 -0
  7. package/dist/conflict/locale-packs/en.js.map +1 -0
  8. package/dist/conflict/locale-packs/index.js +4 -0
  9. package/dist/conflict/locale-packs/types.d.ts +103 -0
  10. package/dist/conflict/locale-packs/types.d.ts.map +1 -0
  11. package/dist/conflict/locale-packs/types.js +55 -0
  12. package/dist/conflict/locale-packs/types.js.map +1 -0
  13. package/dist/conflict/pipeline.d.ts +35 -0
  14. package/dist/conflict/pipeline.d.ts.map +1 -0
  15. package/dist/conflict/pipeline.js +257 -0
  16. package/dist/conflict/pipeline.js.map +1 -0
  17. package/dist/conflict/stages/helpers.js +66 -0
  18. package/dist/conflict/stages/helpers.js.map +1 -0
  19. package/dist/conflict/stages/stage1-exact-dedup.js +21 -0
  20. package/dist/conflict/stages/stage1-exact-dedup.js.map +1 -0
  21. package/dist/conflict/stages/stage2-embedding-three-zone.js +37 -0
  22. package/dist/conflict/stages/stage2-embedding-three-zone.js.map +1 -0
  23. package/dist/conflict/stages/stage3-heuristic-regex.js +45 -0
  24. package/dist/conflict/stages/stage3-heuristic-regex.js.map +1 -0
  25. package/dist/conflict/stages/stage4-subject-predicate.js +31 -0
  26. package/dist/conflict/stages/stage4-subject-predicate.js.map +1 -0
  27. package/dist/conflict/stages/stage5-defer-to-deep.js +22 -0
  28. package/dist/conflict/stages/stage5-defer-to-deep.js.map +1 -0
  29. package/dist/conflict/types.d.ts +222 -0
  30. package/dist/conflict/types.d.ts.map +1 -0
  31. package/dist/conflict/types.js +50 -0
  32. package/dist/conflict/types.js.map +1 -0
  33. package/dist/consolidator/budget.d.ts +1 -0
  34. package/dist/consolidator/budget.js +214 -0
  35. package/dist/consolidator/budget.js.map +1 -0
  36. package/dist/consolidator/decay.d.ts +35 -0
  37. package/dist/consolidator/decay.d.ts.map +1 -0
  38. package/dist/consolidator/decay.js +91 -0
  39. package/dist/consolidator/decay.js.map +1 -0
  40. package/dist/consolidator/dlq.js +58 -0
  41. package/dist/consolidator/dlq.js.map +1 -0
  42. package/dist/consolidator/errors.d.ts +54 -0
  43. package/dist/consolidator/errors.d.ts.map +1 -0
  44. package/dist/consolidator/errors.js +67 -0
  45. package/dist/consolidator/errors.js.map +1 -0
  46. package/dist/consolidator/idempotency.d.ts +1 -0
  47. package/dist/consolidator/idempotency.js +22 -0
  48. package/dist/consolidator/idempotency.js.map +1 -0
  49. package/dist/consolidator/index.d.ts +34 -0
  50. package/dist/consolidator/index.d.ts.map +1 -0
  51. package/dist/consolidator/index.js +163 -0
  52. package/dist/consolidator/index.js.map +1 -0
  53. package/dist/consolidator/lock.d.ts +2 -0
  54. package/dist/consolidator/lock.js +89 -0
  55. package/dist/consolidator/lock.js.map +1 -0
  56. package/dist/consolidator/noise-filter.d.ts +2 -0
  57. package/dist/consolidator/noise-filter.js +173 -0
  58. package/dist/consolidator/noise-filter.js.map +1 -0
  59. package/dist/consolidator/phases/deep.d.ts +4 -0
  60. package/dist/consolidator/phases/deep.js +198 -0
  61. package/dist/consolidator/phases/deep.js.map +1 -0
  62. package/dist/consolidator/phases/induce.d.ts +154 -0
  63. package/dist/consolidator/phases/induce.d.ts.map +1 -0
  64. package/dist/consolidator/phases/induce.js +253 -0
  65. package/dist/consolidator/phases/induce.js.map +1 -0
  66. package/dist/consolidator/phases/light.d.ts +4 -0
  67. package/dist/consolidator/phases/light.js +99 -0
  68. package/dist/consolidator/phases/light.js.map +1 -0
  69. package/dist/consolidator/phases/reflect.js +287 -0
  70. package/dist/consolidator/phases/reflect.js.map +1 -0
  71. package/dist/consolidator/phases/standard.d.ts +8 -0
  72. package/dist/consolidator/phases/standard.js +499 -0
  73. package/dist/consolidator/phases/standard.js.map +1 -0
  74. package/dist/consolidator/reconcile.js +192 -0
  75. package/dist/consolidator/reconcile.js.map +1 -0
  76. package/dist/consolidator/runtime.d.ts +62 -0
  77. package/dist/consolidator/runtime.d.ts.map +1 -0
  78. package/dist/consolidator/runtime.js +580 -0
  79. package/dist/consolidator/runtime.js.map +1 -0
  80. package/dist/consolidator/scheduler.d.ts +111 -0
  81. package/dist/consolidator/scheduler.d.ts.map +1 -0
  82. package/dist/consolidator/scheduler.js +71 -0
  83. package/dist/consolidator/scheduler.js.map +1 -0
  84. package/dist/consolidator/triggers.d.ts +40 -0
  85. package/dist/consolidator/triggers.d.ts.map +1 -0
  86. package/dist/consolidator/triggers.js +94 -0
  87. package/dist/consolidator/triggers.js.map +1 -0
  88. package/dist/consolidator/types.d.ts +397 -0
  89. package/dist/consolidator/types.d.ts.map +1 -0
  90. package/dist/consolidator/types.js +117 -0
  91. package/dist/consolidator/types.js.map +1 -0
  92. package/dist/context-engine/annotations.d.ts +118 -0
  93. package/dist/context-engine/annotations.d.ts.map +1 -0
  94. package/dist/context-engine/annotations.js +102 -0
  95. package/dist/context-engine/annotations.js.map +1 -0
  96. package/dist/context-engine/auto-recall.d.ts +52 -0
  97. package/dist/context-engine/auto-recall.d.ts.map +1 -0
  98. package/dist/context-engine/auto-recall.js +41 -0
  99. package/dist/context-engine/auto-recall.js.map +1 -0
  100. package/dist/context-engine/compaction/clear-tool-results.d.ts +55 -0
  101. package/dist/context-engine/compaction/clear-tool-results.d.ts.map +1 -0
  102. package/dist/context-engine/compaction/clear-tool-results.js +97 -0
  103. package/dist/context-engine/compaction/clear-tool-results.js.map +1 -0
  104. package/dist/context-engine/compaction/compactor.d.ts +52 -0
  105. package/dist/context-engine/compaction/compactor.d.ts.map +1 -0
  106. package/dist/context-engine/compaction/compactor.js +196 -0
  107. package/dist/context-engine/compaction/compactor.js.map +1 -0
  108. package/dist/context-engine/compaction/hooks/reanchor-persona-block.d.ts +15 -0
  109. package/dist/context-engine/compaction/hooks/reanchor-persona-block.d.ts.map +1 -0
  110. package/dist/context-engine/compaction/hooks/reanchor-persona-block.js +27 -0
  111. package/dist/context-engine/compaction/hooks/reanchor-persona-block.js.map +1 -0
  112. package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.d.ts +18 -0
  113. package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.d.ts.map +1 -0
  114. package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.js +47 -0
  115. package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.js.map +1 -0
  116. package/dist/context-engine/compaction/hooks/reanchor-project-rules.d.ts +15 -0
  117. package/dist/context-engine/compaction/hooks/reanchor-project-rules.d.ts.map +1 -0
  118. package/dist/context-engine/compaction/hooks/reanchor-project-rules.js +32 -0
  119. package/dist/context-engine/compaction/hooks/reanchor-project-rules.js.map +1 -0
  120. package/dist/context-engine/compaction/hooks/types.d.ts +42 -0
  121. package/dist/context-engine/compaction/hooks/types.d.ts.map +1 -0
  122. package/dist/context-engine/compaction/index.d.ts +9 -0
  123. package/dist/context-engine/compaction/index.js +9 -0
  124. package/dist/context-engine/compaction/templates/summary-9-section.d.ts +84 -0
  125. package/dist/context-engine/compaction/templates/summary-9-section.d.ts.map +1 -0
  126. package/dist/context-engine/compaction/templates/summary-9-section.js +84 -0
  127. package/dist/context-engine/compaction/templates/summary-9-section.js.map +1 -0
  128. package/dist/context-engine/compaction/thresholds.d.ts +68 -0
  129. package/dist/context-engine/compaction/thresholds.d.ts.map +1 -0
  130. package/dist/context-engine/compaction/thresholds.js +63 -0
  131. package/dist/context-engine/compaction/thresholds.js.map +1 -0
  132. package/dist/context-engine/compaction/types.d.ts +202 -0
  133. package/dist/context-engine/compaction/types.d.ts.map +1 -0
  134. package/dist/context-engine/engine.d.ts +258 -0
  135. package/dist/context-engine/engine.d.ts.map +1 -0
  136. package/dist/context-engine/engine.js +424 -0
  137. package/dist/context-engine/engine.js.map +1 -0
  138. package/dist/context-engine/index.d.ts +68 -0
  139. package/dist/context-engine/index.d.ts.map +1 -0
  140. package/dist/context-engine/index.js +24 -0
  141. package/dist/context-engine/locale-packs/en.d.ts +14 -0
  142. package/dist/context-engine/locale-packs/en.d.ts.map +1 -0
  143. package/dist/context-engine/locale-packs/en.js +87 -0
  144. package/dist/context-engine/locale-packs/en.js.map +1 -0
  145. package/dist/context-engine/locale-packs/index.js +4 -0
  146. package/dist/context-engine/locale-packs/resolver.d.ts +41 -0
  147. package/dist/context-engine/locale-packs/resolver.d.ts.map +1 -0
  148. package/dist/context-engine/locale-packs/resolver.js +119 -0
  149. package/dist/context-engine/locale-packs/resolver.js.map +1 -0
  150. package/dist/context-engine/locale-packs/types.d.ts +119 -0
  151. package/dist/context-engine/locale-packs/types.d.ts.map +1 -0
  152. package/dist/context-engine/locale-packs/types.js +24 -0
  153. package/dist/context-engine/locale-packs/types.js.map +1 -0
  154. package/dist/context-engine/metadata.d.ts +40 -0
  155. package/dist/context-engine/metadata.d.ts.map +1 -0
  156. package/dist/context-engine/metadata.js +66 -0
  157. package/dist/context-engine/metadata.js.map +1 -0
  158. package/dist/context-engine/preambles/inbound-en.d.ts +20 -0
  159. package/dist/context-engine/preambles/inbound-en.d.ts.map +1 -0
  160. package/dist/context-engine/preambles/inbound-en.js +23 -0
  161. package/dist/context-engine/preambles/inbound-en.js.map +1 -0
  162. package/dist/context-engine/privacy-filter.d.ts +108 -0
  163. package/dist/context-engine/privacy-filter.d.ts.map +1 -0
  164. package/dist/context-engine/privacy-filter.js +113 -0
  165. package/dist/context-engine/privacy-filter.js.map +1 -0
  166. package/dist/context-engine/templates/base-en.d.ts +19 -0
  167. package/dist/context-engine/templates/base-en.d.ts.map +1 -0
  168. package/dist/context-engine/templates/base-en.js +22 -0
  169. package/dist/context-engine/templates/base-en.js.map +1 -0
  170. package/dist/context-engine/templates/composer.d.ts +55 -0
  171. package/dist/context-engine/templates/composer.d.ts.map +1 -0
  172. package/dist/context-engine/templates/composer.js +51 -0
  173. package/dist/context-engine/templates/composer.js.map +1 -0
  174. package/dist/context-engine/token-budget.d.ts +99 -0
  175. package/dist/context-engine/token-budget.d.ts.map +1 -0
  176. package/dist/context-engine/token-budget.js +211 -0
  177. package/dist/context-engine/token-budget.js.map +1 -0
  178. package/dist/context-engine/token-counter.d.ts +54 -0
  179. package/dist/context-engine/token-counter.d.ts.map +1 -0
  180. package/dist/context-engine/token-counter.js +81 -0
  181. package/dist/context-engine/token-counter.js.map +1 -0
  182. package/dist/errors/index.d.ts +171 -0
  183. package/dist/errors/index.d.ts.map +1 -0
  184. package/dist/errors/index.js +206 -0
  185. package/dist/errors/index.js.map +1 -0
  186. package/dist/facade.d.ts +278 -0
  187. package/dist/facade.d.ts.map +1 -0
  188. package/dist/facade.js +265 -0
  189. package/dist/facade.js.map +1 -0
  190. package/dist/graph/entity-resolver.d.ts +135 -0
  191. package/dist/graph/entity-resolver.d.ts.map +1 -0
  192. package/dist/graph/entity-resolver.js +202 -0
  193. package/dist/graph/entity-resolver.js.map +1 -0
  194. package/dist/graph/index.d.ts +1 -0
  195. package/dist/index.d.ts +103 -0
  196. package/dist/index.d.ts.map +1 -0
  197. package/dist/index.js +95 -0
  198. package/dist/index.js.map +1 -0
  199. package/dist/internal/contextualize.d.ts +14 -0
  200. package/dist/internal/contextualize.d.ts.map +1 -0
  201. package/dist/internal/contextualize.js +110 -0
  202. package/dist/internal/contextualize.js.map +1 -0
  203. package/dist/internal/embedder-binding.js +50 -0
  204. package/dist/internal/embedder-binding.js.map +1 -0
  205. package/dist/internal/id.js +24 -0
  206. package/dist/internal/id.js.map +1 -0
  207. package/dist/internal/injection-heuristics.js +64 -0
  208. package/dist/internal/injection-heuristics.js.map +1 -0
  209. package/dist/internal/spans.js +35 -0
  210. package/dist/internal/spans.js.map +1 -0
  211. package/dist/internal/storage-adapter.d.ts +742 -0
  212. package/dist/internal/storage-adapter.d.ts.map +1 -0
  213. package/dist/migration/embedder-migration.d.ts +124 -0
  214. package/dist/migration/embedder-migration.d.ts.map +1 -0
  215. package/dist/migration/embedder-migration.js +109 -0
  216. package/dist/migration/embedder-migration.js.map +1 -0
  217. package/dist/migration/index.d.ts +2 -0
  218. package/dist/migration/index.js +3 -0
  219. package/dist/search/explain.d.ts +74 -0
  220. package/dist/search/explain.d.ts.map +1 -0
  221. package/dist/search/explain.js +50 -0
  222. package/dist/search/explain.js.map +1 -0
  223. package/dist/search/index.d.ts +6 -0
  224. package/dist/search/index.js +6 -0
  225. package/dist/search/iterative.d.ts +223 -0
  226. package/dist/search/iterative.d.ts.map +1 -0
  227. package/dist/search/iterative.js +330 -0
  228. package/dist/search/iterative.js.map +1 -0
  229. package/dist/search/query-transform.d.ts +112 -0
  230. package/dist/search/query-transform.d.ts.map +1 -0
  231. package/dist/search/query-transform.js +184 -0
  232. package/dist/search/query-transform.js.map +1 -0
  233. package/dist/search/rrf.d.ts +95 -0
  234. package/dist/search/rrf.d.ts.map +1 -0
  235. package/dist/search/rrf.js +166 -0
  236. package/dist/search/rrf.js.map +1 -0
  237. package/dist/search/types.d.ts +50 -0
  238. package/dist/search/types.d.ts.map +1 -0
  239. package/dist/tiers/episodic-memory.d.ts +142 -0
  240. package/dist/tiers/episodic-memory.d.ts.map +1 -0
  241. package/dist/tiers/episodic-memory.js +254 -0
  242. package/dist/tiers/episodic-memory.js.map +1 -0
  243. package/dist/tiers/index.d.ts +8 -0
  244. package/dist/tiers/index.js +9 -0
  245. package/dist/tiers/insight-memory.d.ts +71 -0
  246. package/dist/tiers/insight-memory.d.ts.map +1 -0
  247. package/dist/tiers/insight-memory.js +133 -0
  248. package/dist/tiers/insight-memory.js.map +1 -0
  249. package/dist/tiers/procedural-memory.d.ts +147 -0
  250. package/dist/tiers/procedural-memory.d.ts.map +1 -0
  251. package/dist/tiers/procedural-memory.js +267 -0
  252. package/dist/tiers/procedural-memory.js.map +1 -0
  253. package/dist/tiers/semantic-memory.d.ts +461 -0
  254. package/dist/tiers/semantic-memory.d.ts.map +1 -0
  255. package/dist/tiers/semantic-memory.js +631 -0
  256. package/dist/tiers/semantic-memory.js.map +1 -0
  257. package/dist/tiers/session-memory.d.ts +117 -0
  258. package/dist/tiers/session-memory.d.ts.map +1 -0
  259. package/dist/tiers/session-memory.js +163 -0
  260. package/dist/tiers/session-memory.js.map +1 -0
  261. package/dist/tiers/shared-memory.d.ts +29 -0
  262. package/dist/tiers/shared-memory.d.ts.map +1 -0
  263. package/dist/tiers/shared-memory.js +58 -0
  264. package/dist/tiers/shared-memory.js.map +1 -0
  265. package/dist/tiers/working-memory.d.ts +129 -0
  266. package/dist/tiers/working-memory.d.ts.map +1 -0
  267. package/dist/tiers/working-memory.js +229 -0
  268. package/dist/tiers/working-memory.js.map +1 -0
  269. package/dist/tools/block-tools.d.ts +98 -0
  270. package/dist/tools/block-tools.d.ts.map +1 -0
  271. package/dist/tools/block-tools.js +114 -0
  272. package/dist/tools/block-tools.js.map +1 -0
  273. package/dist/tools/fact-tools.d.ts +294 -0
  274. package/dist/tools/fact-tools.d.ts.map +1 -0
  275. package/dist/tools/fact-tools.js +293 -0
  276. package/dist/tools/fact-tools.js.map +1 -0
  277. package/dist/tools/index.d.ts +35 -0
  278. package/dist/tools/index.d.ts.map +1 -0
  279. package/dist/tools/index.js +36 -0
  280. package/dist/tools/index.js.map +1 -0
  281. package/dist/tools/recall-tools.d.ts +209 -0
  282. package/dist/tools/recall-tools.d.ts.map +1 -0
  283. package/dist/tools/recall-tools.js +170 -0
  284. package/dist/tools/recall-tools.js.map +1 -0
  285. package/dist/tools/types.d.ts +40 -0
  286. package/dist/tools/types.d.ts.map +1 -0
  287. package/package.json +119 -0
@@ -0,0 +1,50 @@
1
+ import { MemoryHit, MemoryRecord } from "@graphorin/core";
2
+
3
+ //#region src/search/types.d.ts
4
+
5
+ /**
6
+ * Pluggable reranker contract. Concrete implementations live in
7
+ * `@graphorin/memory/search` (the built-in `RRFReranker`) and the
8
+ * Phase 16 optional packages (`@graphorin/reranker-transformersjs`,
9
+ * `@graphorin/reranker-llm`).
10
+ *
11
+ * The reranker accepts one or more parallel ranked lists (vector +
12
+ * FTS5 + optional entity boost) and produces a single fused ranking.
13
+ * Implementations MUST be pure (no I/O outside `signal`-aware
14
+ * dependencies) so the agent runtime can call them mid-stream without
15
+ * deadlocking the main loop.
16
+ *
17
+ * @stable
18
+ */
19
+ interface ReRanker {
20
+ /** Stable lowercase identifier surfaced on every span. */
21
+ readonly id: string;
22
+ /**
23
+ * Rerank one or more parallel ranked lists and return the fused
24
+ * top-K (default `topK = 10`). Each input list must already be
25
+ * sorted by `score` descending.
26
+ */
27
+ rerank<TRecord extends MemoryRecord>(query: string, lists: ReadonlyArray<ReadonlyArray<MemoryHit<TRecord>>>, options?: ReRankOptions): Promise<ReadonlyArray<MemoryHit<TRecord>>>;
28
+ }
29
+ /**
30
+ * Per-call reranker options. `topK` defaults to `10`; `signal` is
31
+ * propagated to any async work the reranker performs.
32
+ *
33
+ * @stable
34
+ */
35
+ interface ReRankOptions {
36
+ readonly topK?: number;
37
+ readonly signal?: AbortSignal;
38
+ /**
39
+ * Stable per-list labels for the explanation signals (MRET-13) —
40
+ * `rrf.<label>` instead of the ephemeral `rrf.list_<index>`. Callers
41
+ * that fan lists out conditionally (multi-query, HyDE, graph) pass
42
+ * retriever-kind labels so X-3 consumers can identify which leg a
43
+ * contribution came from across calls. Missing entries fall back to
44
+ * the positional key.
45
+ */
46
+ readonly labels?: ReadonlyArray<string>;
47
+ }
48
+ //#endregion
49
+ export { ReRankOptions, ReRanker };
50
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../src/search/types.ts"],"sourcesContent":[],"mappings":";;;;;;AAgBA;;;;;;;;;;;;AAqBiB,UArBA,QAAA,CAqBa;;;;;;;;yBAbL,oCAEd,cAAc,cAAc,UAAU,sBACnC,gBACT,QAAQ,cAAc,UAAU;;;;;;;;UASpB,aAAA;;oBAEG;;;;;;;;;oBASA"}
@@ -0,0 +1,142 @@
1
+ import { MemoryStoreAdapter } from "../internal/storage-adapter.js";
2
+ import { EmbedderProvider, Episode, MemoryHit, MemoryProvenance, MemoryStatus, Sensitivity, SessionScope, Tracer } from "@graphorin/core";
3
+
4
+ //#region src/tiers/episodic-memory.d.ts
5
+
6
+ /**
7
+ * Author-time episode payload. The framework derives `id`,
8
+ * `kind: 'episodic'`, `userId`, `createdAt`, `updatedAt`, and the
9
+ * `embedder_id` from the surrounding `EpisodicMemory.record(...)`
10
+ * call.
11
+ *
12
+ * @stable
13
+ */
14
+ interface EpisodeInput {
15
+ readonly summary: string;
16
+ readonly startedAt: string;
17
+ readonly endedAt: string;
18
+ /** Optional importance score in `[0, 1]`. */
19
+ readonly importance?: number;
20
+ readonly sensitivity?: Sensitivity;
21
+ readonly tags?: ReadonlyArray<string>;
22
+ /**
23
+ * Trust-provenance tag (P1-4). Episodes auto-formed by the
24
+ * consolidator pass `'extraction'` so they land quarantined; omit
25
+ * (defaults to first-party `active`) for user-authored episodes.
26
+ */
27
+ readonly provenance?: MemoryProvenance;
28
+ /**
29
+ * Retrieval-trust state (P1-4). Defaults to `active`; the
30
+ * consolidator records auto-formed episodes as `'quarantined'` so
31
+ * they are excluded from action-driving recall until validated.
32
+ */
33
+ readonly status?: MemoryStatus;
34
+ }
35
+ /**
36
+ * Triple-signal episode retrieval weights. Defaults match DEC-105:
37
+ * `recency 0.3`, `relevance 0.5`, `importance 0.2`. Implementations
38
+ * normalize the weighted sum back to `[0, 1]`.
39
+ *
40
+ * @stable
41
+ */
42
+ interface EpisodeRetrievalWeights {
43
+ readonly recency: number;
44
+ readonly relevance: number;
45
+ readonly importance: number;
46
+ }
47
+ /**
48
+ * Per-call options accepted by {@link EpisodicMemory.search}.
49
+ *
50
+ * @stable
51
+ */
52
+ interface EpisodeSearchOptions {
53
+ readonly topK?: number;
54
+ readonly signal?: AbortSignal;
55
+ readonly weights?: EpisodeRetrievalWeights;
56
+ readonly dateRange?: {
57
+ readonly from?: string;
58
+ readonly to?: string;
59
+ };
60
+ /**
61
+ * Point-in-time ("as of") read. When set, only episodes that had
62
+ * started by this instant (`started_at <= asOf`) are returned.
63
+ * ISO-8601. Absent ⇒ current behaviour is unchanged. P0-2.
64
+ *
65
+ * @stable
66
+ */
67
+ readonly asOf?: string;
68
+ /**
69
+ * Include quarantined episodes in the result set (P1-4). Defaults to
70
+ * `false`: action-driving recall never returns quarantined rows. Set
71
+ * `true` only for the validation / inspector path — never for
72
+ * auto-recall fed back into the model. Auto-formed episodes (P1-2)
73
+ * land quarantined, so this is how an operator surfaces them for
74
+ * review.
75
+ *
76
+ * @stable
77
+ */
78
+ readonly includeQuarantined?: boolean;
79
+ }
80
+ /**
81
+ * `EpisodicMemory` — record + retrieve summarized stretches of past
82
+ * activity. Stored embeddings power triple-signal retrieval (recency
83
+ * × relevance × importance).
84
+ *
85
+ * @stable
86
+ */
87
+ declare class EpisodicMemory {
88
+ #private;
89
+ constructor(args: {
90
+ store: MemoryStoreAdapter;
91
+ tracer: Tracer;
92
+ embedder: EmbedderProvider | null;
93
+ embedderIdProvider: () => string | null;
94
+ });
95
+ /** Persist an episode + its embedding (when an embedder is configured). */
96
+ record(scope: SessionScope, input: EpisodeInput): Promise<Episode>;
97
+ /** Lookup a single episode by id. */
98
+ get(id: string): Promise<Episode | null>;
99
+ /**
100
+ * Triple-signal episode retrieval (`recency × relevance ×
101
+ * importance`). The vector signal is computed on demand when an
102
+ * embedder is configured AND the storage adapter exposes
103
+ * `searchVector`; otherwise the FTS5 BM25 score is fed into the
104
+ * relevance term as a normalized fallback.
105
+ */
106
+ search(scope: SessionScope, query: string, opts?: EpisodeSearchOptions): Promise<ReadonlyArray<MemoryHit<Episode>>>;
107
+ /**
108
+ * Soft-archive an episode. Storage adapters that implement
109
+ * `EpisodicMemoryStoreExt.archive(...)` mark the row archived in
110
+ * place. Adapters that do not expose the extension surface a
111
+ * friendly `TypeError` so the operator can opt the storage layer
112
+ * in (or call `episodic.put(...)` with the archived state set
113
+ * manually).
114
+ */
115
+ archive(scope: SessionScope, episodeId: string, reason?: string): Promise<void>;
116
+ /**
117
+ * Most-recent episodes by end time (newest first), with no embedding / FTS
118
+ * query (MCON-1). Requires `EpisodicMemoryStoreExt.listRecent` — the default
119
+ * `@graphorin/store-sqlite` adapter implements it. Optionally includes
120
+ * quarantined episodes (the importance source for the reflection gate).
121
+ */
122
+ listRecent(scope: SessionScope, limit: number, opts?: {
123
+ includeQuarantined?: boolean;
124
+ }): Promise<ReadonlyArray<Episode>>;
125
+ /** List the most recent episodes (no embedding required). */
126
+ recent(scope: SessionScope, opts?: {
127
+ topK?: number;
128
+ }): Promise<ReadonlyArray<Episode>>;
129
+ /**
130
+ * Promote a quarantined episode into default recall (MCON-2). Mirrors
131
+ * {@link SemanticMemory.validate}: re-derives the injection verdict from the
132
+ * stored summary and **refuses** promotion of an injection-flagged episode
133
+ * (`QuarantinePromotionRefusedError`) unless an operator passes
134
+ * `{ force: true }` from a trusted, non-agent context.
135
+ */
136
+ validate(scope: SessionScope, episodeId: string, reason?: string, options?: {
137
+ readonly force?: boolean;
138
+ }): Promise<void>;
139
+ }
140
+ //#endregion
141
+ export { EpisodeInput, EpisodeRetrievalWeights, EpisodeSearchOptions, EpisodicMemory };
142
+ //# sourceMappingURL=episodic-memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"episodic-memory.d.ts","names":[],"sources":["../../src/tiers/episodic-memory.ts"],"sourcesContent":[],"mappings":";;;;;;;AAwBA;;;;;;AA6BiB,UA7BA,YAAA,CA6BuB;EAiBvB,SAAA,OAAA,EAAA,MAAoB;EAiCxB,SAAA,SAAc,EAAA,MAAA;EAOhB,SAAA,OAAA,EAAA,MAAA;EACC;EACE,SAAA,UAAA,CAAA,EAAA,MAAA;EAUQ,SAAA,WAAA,CAAA,EA5FG,WA4FH;EAAqB,SAAA,IAAA,CAAA,EA3FzB,aA2FyB,CAAA,MAAA,CAAA;EAAuB;;;;;EA+DxD,SAAA,UAAA,CAAA,EApJc,gBAoJd;EAC2B;;;;;EA8DqC,SAAA,MAAA,CAAA,EA7MtD,YA6MsD;;;;;;;;;AAwD/D,UA3PM,uBAAA,CA2PN;EAIN,SAAA,OAAA,EAAA,MAAA;EAAO,SAAA,SAAA,EAAA,MAAA;;;;;;;;UA9OK,oBAAA;;oBAEG;qBACC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA8BR,cAAA;;;WAOF;YACC;cACE;;;;gBAUQ,qBAAqB,eAAe,QAAQ;;mBAiDzC,QAAQ;;;;;;;;gBAYtB,oCAED,uBACL,QAAQ,cAAc,UAAU;;;;;;;;;iBA8Dd,mDAAmD;;;;;;;oBAyB/D;;MAGN,QAAQ,cAAc;;gBAgBL;;MAA6C,QAAQ,cAAc;;;;;;;;kBAY9E;;MAIN"}
@@ -0,0 +1,254 @@
1
+ import { withMemorySpan } from "../internal/spans.js";
2
+ import { QuarantinePromotionRefusedError } from "../errors/index.js";
3
+ import { newMemoryId } from "../internal/id.js";
4
+ import { detectMemoryInjection } from "../internal/injection-heuristics.js";
5
+
6
+ //#region src/tiers/episodic-memory.ts
7
+ const DEFAULT_WEIGHTS = Object.freeze({
8
+ recency: .3,
9
+ relevance: .5,
10
+ importance: .2
11
+ });
12
+ /**
13
+ * `EpisodicMemory` — record + retrieve summarized stretches of past
14
+ * activity. Stored embeddings power triple-signal retrieval (recency
15
+ * × relevance × importance).
16
+ *
17
+ * @stable
18
+ */
19
+ var EpisodicMemory = class {
20
+ #store;
21
+ #tracer;
22
+ #embedder;
23
+ #embedderIdProvider;
24
+ constructor(args) {
25
+ this.#store = args.store;
26
+ this.#tracer = args.tracer;
27
+ this.#embedder = args.embedder;
28
+ this.#embedderIdProvider = args.embedderIdProvider;
29
+ }
30
+ /** Persist an episode + its embedding (when an embedder is configured). */
31
+ async record(scope, input) {
32
+ return withMemorySpan(this.#tracer, "memory.write.episodic", scope, {}, async (span) => {
33
+ const now = (/* @__PURE__ */ new Date()).toISOString();
34
+ const episode = {
35
+ id: newMemoryId("ep"),
36
+ kind: "episodic",
37
+ userId: scope.userId,
38
+ ...scope.sessionId !== void 0 ? { sessionId: scope.sessionId } : {},
39
+ ...scope.agentId !== void 0 ? { agentId: scope.agentId } : {},
40
+ sensitivity: input.sensitivity ?? "internal",
41
+ summary: input.summary,
42
+ startedAt: input.startedAt,
43
+ endedAt: input.endedAt,
44
+ ...input.importance !== void 0 ? { importance: input.importance } : {},
45
+ ...input.tags !== void 0 ? { tags: Object.freeze([...input.tags]) } : {},
46
+ ...input.provenance !== void 0 ? { provenance: input.provenance } : {},
47
+ ...input.status !== void 0 ? { status: input.status } : {},
48
+ createdAt: now,
49
+ updatedAt: now
50
+ };
51
+ const embedderId = this.#embedderIdProvider();
52
+ if (this.#embedder !== null && embedderId !== null && typeof this.#store.episodic.putWithEmbedding === "function") {
53
+ const [vector] = await this.#embedder.embed([input.summary], { taskType: "passage" });
54
+ if (vector !== void 0) await this.#store.episodic.putWithEmbedding(episode, { embedding: {
55
+ embedderId,
56
+ vector
57
+ } });
58
+ else await this.#store.episodic.put(episode);
59
+ } else await this.#store.episodic.put(episode);
60
+ span.setAttributes({
61
+ "memory.episodic.summary_length": input.summary.length,
62
+ ...input.importance !== void 0 ? { "memory.episodic.importance": input.importance } : {}
63
+ });
64
+ return episode;
65
+ });
66
+ }
67
+ /** Lookup a single episode by id. */
68
+ async get(id) {
69
+ return this.#store.episodic.get(id);
70
+ }
71
+ /**
72
+ * Triple-signal episode retrieval (`recency × relevance ×
73
+ * importance`). The vector signal is computed on demand when an
74
+ * embedder is configured AND the storage adapter exposes
75
+ * `searchVector`; otherwise the FTS5 BM25 score is fed into the
76
+ * relevance term as a normalized fallback.
77
+ */
78
+ async search(scope, query, opts = {}) {
79
+ return withMemorySpan(this.#tracer, "memory.search.episodic", scope, { "memory.search.query_length": query.length }, async (span) => {
80
+ const topK = opts.topK ?? 10;
81
+ const weights = opts.weights ?? DEFAULT_WEIGHTS;
82
+ const ftsHits = await this.#store.episodic.search(scope, {
83
+ query,
84
+ topK: topK * 2,
85
+ ...opts.asOf !== void 0 ? { asOf: opts.asOf } : {},
86
+ ...opts.dateRange !== void 0 ? { dateRange: opts.dateRange } : {},
87
+ ...opts.signal !== void 0 ? { signal: opts.signal } : {},
88
+ ...opts.includeQuarantined !== void 0 ? { includeQuarantined: opts.includeQuarantined } : {}
89
+ });
90
+ const vectorHits = await this.#tryVectorSearch(scope, query, topK * 2, opts.asOf, opts.includeQuarantined);
91
+ const from = opts.dateRange?.from !== void 0 ? Date.parse(opts.dateRange.from) : null;
92
+ const to = opts.dateRange?.to !== void 0 ? Date.parse(opts.dateRange.to) : null;
93
+ const finalHits = mergeRecency(ftsHits, from !== null || to !== null ? vectorHits.filter((h) => {
94
+ if (from !== null && Date.parse(h.record.endedAt) < from) return false;
95
+ if (to !== null && Date.parse(h.record.startedAt) > to) return false;
96
+ return true;
97
+ }) : vectorHits, weights).slice(0, topK);
98
+ span.setAttributes({
99
+ "memory.search.episodic.fts_count": ftsHits.length,
100
+ "memory.search.episodic.vector_count": vectorHits.length,
101
+ "memory.search.episodic.final_count": finalHits.length,
102
+ ...opts.asOf !== void 0 ? { "memory.search.episodic.as_of": opts.asOf } : {}
103
+ });
104
+ return finalHits;
105
+ });
106
+ }
107
+ /**
108
+ * Soft-archive an episode. Storage adapters that implement
109
+ * `EpisodicMemoryStoreExt.archive(...)` mark the row archived in
110
+ * place. Adapters that do not expose the extension surface a
111
+ * friendly `TypeError` so the operator can opt the storage layer
112
+ * in (or call `episodic.put(...)` with the archived state set
113
+ * manually).
114
+ */
115
+ async archive(scope, episodeId, reason) {
116
+ await withMemorySpan(this.#tracer, "memory.write.episodic", scope, {
117
+ "memory.episodic.action": "archive",
118
+ "memory.episodic.episode_id": episodeId
119
+ }, async () => {
120
+ if (typeof this.#store.episodic.archive !== "function") throw new TypeError("[graphorin/memory] EpisodicMemory.archive(...) requires a storage adapter that implements `episodic.archive(id)`. The default `@graphorin/store-sqlite` adapter implements it; custom adapters can opt in via EpisodicMemoryStoreExt.");
121
+ await this.#store.episodic.archive(episodeId, reason);
122
+ });
123
+ }
124
+ /**
125
+ * Most-recent episodes by end time (newest first), with no embedding / FTS
126
+ * query (MCON-1). Requires `EpisodicMemoryStoreExt.listRecent` — the default
127
+ * `@graphorin/store-sqlite` adapter implements it. Optionally includes
128
+ * quarantined episodes (the importance source for the reflection gate).
129
+ */
130
+ async listRecent(scope, limit, opts = {}) {
131
+ return withMemorySpan(this.#tracer, "memory.read.episodic", scope, {}, async (span) => {
132
+ const store = this.#store.episodic;
133
+ if (typeof store.listRecent !== "function") throw new Error("[graphorin/memory] EpisodicMemory.listRecent requires EpisodicMemoryStoreExt.listRecent. The default `@graphorin/store-sqlite` adapter implements it; custom adapters can opt in.");
134
+ const out = await store.listRecent(scope, limit, opts);
135
+ span.setAttributes({ "memory.read.episodic.count": out.length });
136
+ return out;
137
+ });
138
+ }
139
+ /** List the most recent episodes (no embedding required). */
140
+ async recent(scope, opts = {}) {
141
+ return this.listRecent(scope, opts.topK ?? 10, {});
142
+ }
143
+ /**
144
+ * Promote a quarantined episode into default recall (MCON-2). Mirrors
145
+ * {@link SemanticMemory.validate}: re-derives the injection verdict from the
146
+ * stored summary and **refuses** promotion of an injection-flagged episode
147
+ * (`QuarantinePromotionRefusedError`) unless an operator passes
148
+ * `{ force: true }` from a trusted, non-agent context.
149
+ */
150
+ async validate(scope, episodeId, reason, options) {
151
+ await withMemorySpan(this.#tracer, "memory.write.episodic", scope, {
152
+ "memory.episodic.action": "validate",
153
+ "memory.episodic.episode_id": episodeId
154
+ }, async (span) => {
155
+ const store = this.#store.episodic;
156
+ if (typeof store.setStatus !== "function") throw new TypeError("[graphorin/memory] EpisodicMemory.validate(...) requires a storage adapter that implements `episodic.setStatus(id, status)`. The default `@graphorin/store-sqlite` adapter implements it; custom adapters can opt in via EpisodicMemoryStoreExt.");
157
+ const force = options?.force === true;
158
+ const existing = await store.get(episodeId);
159
+ if (existing !== null && !force) {
160
+ const injection = detectMemoryInjection(existing.summary);
161
+ if (injection.flagged) {
162
+ span.setAttributes({ "memory.episodic.validate.refused": true });
163
+ throw new QuarantinePromotionRefusedError(episodeId, injection.markers);
164
+ }
165
+ }
166
+ span.setAttributes({ "memory.episodic.validate.forced": force });
167
+ await store.setStatus(episodeId, "active", reason);
168
+ });
169
+ }
170
+ async #tryVectorSearch(scope, query, topK, asOf, includeQuarantined) {
171
+ const embedderId = this.#embedderIdProvider();
172
+ if (this.#embedder === null || embedderId === null || typeof this.#store.episodic.searchVector !== "function") return [];
173
+ const [vector] = await this.#embedder.embed([query], { taskType: "query" });
174
+ if (vector === void 0) return [];
175
+ return this.#store.episodic.searchVector(scope, vector, embedderId, topK, asOf, includeQuarantined);
176
+ }
177
+ };
178
+ function mergeRecency(ftsHits, vectorHits, weights) {
179
+ const now = Date.now();
180
+ const aggregates = /* @__PURE__ */ new Map();
181
+ for (const hit of ftsHits) {
182
+ const id = hit.record.id;
183
+ const recency = computeRecency(now, hit.record);
184
+ const importance = hit.record.importance ?? 0;
185
+ const relevance = normalizeRelevance(hit.score);
186
+ const score = weights.recency * recency + weights.relevance * relevance + weights.importance * importance;
187
+ aggregates.set(id, {
188
+ record: hit.record,
189
+ relevance,
190
+ recency,
191
+ importance,
192
+ score,
193
+ signals: {
194
+ fts: relevance,
195
+ recency,
196
+ importance
197
+ }
198
+ });
199
+ }
200
+ for (const hit of vectorHits) {
201
+ const id = hit.record.id;
202
+ const cosine = clamp01(hit.score);
203
+ const existing = aggregates.get(id);
204
+ if (existing === void 0) {
205
+ const recency = computeRecency(now, hit.record);
206
+ const importance = hit.record.importance ?? 0;
207
+ const score = weights.recency * recency + weights.relevance * cosine + weights.importance * importance;
208
+ aggregates.set(id, {
209
+ record: hit.record,
210
+ relevance: cosine,
211
+ recency,
212
+ importance,
213
+ score,
214
+ signals: {
215
+ vector: cosine,
216
+ recency,
217
+ importance
218
+ }
219
+ });
220
+ } else {
221
+ const blended = Math.max(existing.relevance, cosine);
222
+ existing.relevance = blended;
223
+ existing.score = weights.recency * existing.recency + weights.relevance * blended + weights.importance * existing.importance;
224
+ existing.signals.vector = cosine;
225
+ existing.signals["rrf-blend"] = blended;
226
+ }
227
+ }
228
+ const out = Array.from(aggregates.values()).map((a) => ({
229
+ record: a.record,
230
+ score: a.score,
231
+ signals: Object.freeze({ ...a.signals })
232
+ }));
233
+ out.sort((a, b) => b.score - a.score);
234
+ return out;
235
+ }
236
+ function computeRecency(now, episode) {
237
+ const ended = Date.parse(episode.endedAt);
238
+ if (!Number.isFinite(ended)) return 0;
239
+ const elapsedDays = Math.max(0, (now - ended) / (1440 * 60 * 1e3));
240
+ return Math.exp(-elapsedDays / 30);
241
+ }
242
+ function normalizeRelevance(score) {
243
+ return clamp01(Math.max(0, score) / (Math.max(0, score) + 1));
244
+ }
245
+ function clamp01(value) {
246
+ if (Number.isNaN(value)) return 0;
247
+ if (value < 0) return 0;
248
+ if (value > 1) return 1;
249
+ return value;
250
+ }
251
+
252
+ //#endregion
253
+ export { EpisodicMemory };
254
+ //# sourceMappingURL=episodic-memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"episodic-memory.js","names":["DEFAULT_WEIGHTS: EpisodeRetrievalWeights","#store","#tracer","#embedder","#embedderIdProvider","episode: Episode","#tryVectorSearch"],"sources":["../../src/tiers/episodic-memory.ts"],"sourcesContent":["import type {\n EmbedderProvider,\n Episode,\n MemoryHit,\n MemoryProvenance,\n MemoryStatus,\n Sensitivity,\n SessionScope,\n Tracer,\n} from '@graphorin/core';\nimport { QuarantinePromotionRefusedError } from '../errors/index.js';\nimport { newMemoryId } from '../internal/id.js';\nimport { detectMemoryInjection } from '../internal/injection-heuristics.js';\nimport { withMemorySpan } from '../internal/spans.js';\nimport type { MemoryStoreAdapter } from '../internal/storage-adapter.js';\n\n/**\n * Author-time episode payload. The framework derives `id`,\n * `kind: 'episodic'`, `userId`, `createdAt`, `updatedAt`, and the\n * `embedder_id` from the surrounding `EpisodicMemory.record(...)`\n * call.\n *\n * @stable\n */\nexport interface EpisodeInput {\n readonly summary: string;\n readonly startedAt: string;\n readonly endedAt: string;\n /** Optional importance score in `[0, 1]`. */\n readonly importance?: number;\n readonly sensitivity?: Sensitivity;\n readonly tags?: ReadonlyArray<string>;\n /**\n * Trust-provenance tag (P1-4). Episodes auto-formed by the\n * consolidator pass `'extraction'` so they land quarantined; omit\n * (defaults to first-party `active`) for user-authored episodes.\n */\n readonly provenance?: MemoryProvenance;\n /**\n * Retrieval-trust state (P1-4). Defaults to `active`; the\n * consolidator records auto-formed episodes as `'quarantined'` so\n * they are excluded from action-driving recall until validated.\n */\n readonly status?: MemoryStatus;\n}\n\n/**\n * Triple-signal episode retrieval weights. Defaults match DEC-105:\n * `recency 0.3`, `relevance 0.5`, `importance 0.2`. Implementations\n * normalize the weighted sum back to `[0, 1]`.\n *\n * @stable\n */\nexport interface EpisodeRetrievalWeights {\n readonly recency: number;\n readonly relevance: number;\n readonly importance: number;\n}\n\nconst DEFAULT_WEIGHTS: EpisodeRetrievalWeights = Object.freeze({\n recency: 0.3,\n relevance: 0.5,\n importance: 0.2,\n});\n\n/**\n * Per-call options accepted by {@link EpisodicMemory.search}.\n *\n * @stable\n */\nexport interface EpisodeSearchOptions {\n readonly topK?: number;\n readonly signal?: AbortSignal;\n readonly weights?: EpisodeRetrievalWeights;\n readonly dateRange?: { readonly from?: string; readonly to?: string };\n /**\n * Point-in-time (\"as of\") read. When set, only episodes that had\n * started by this instant (`started_at <= asOf`) are returned.\n * ISO-8601. Absent ⇒ current behaviour is unchanged. P0-2.\n *\n * @stable\n */\n readonly asOf?: string;\n /**\n * Include quarantined episodes in the result set (P1-4). Defaults to\n * `false`: action-driving recall never returns quarantined rows. Set\n * `true` only for the validation / inspector path — never for\n * auto-recall fed back into the model. Auto-formed episodes (P1-2)\n * land quarantined, so this is how an operator surfaces them for\n * review.\n *\n * @stable\n */\n readonly includeQuarantined?: boolean;\n}\n\n/**\n * `EpisodicMemory` — record + retrieve summarized stretches of past\n * activity. Stored embeddings power triple-signal retrieval (recency\n * × relevance × importance).\n *\n * @stable\n */\nexport class EpisodicMemory {\n readonly #store: MemoryStoreAdapter;\n readonly #tracer: Tracer;\n readonly #embedder: EmbedderProvider | null;\n readonly #embedderIdProvider: () => string | null;\n\n constructor(args: {\n store: MemoryStoreAdapter;\n tracer: Tracer;\n embedder: EmbedderProvider | null;\n embedderIdProvider: () => string | null;\n }) {\n this.#store = args.store;\n this.#tracer = args.tracer;\n this.#embedder = args.embedder;\n this.#embedderIdProvider = args.embedderIdProvider;\n }\n\n /** Persist an episode + its embedding (when an embedder is configured). */\n async record(scope: SessionScope, input: EpisodeInput): Promise<Episode> {\n return withMemorySpan(this.#tracer, 'memory.write.episodic', scope, {}, async (span) => {\n const now = new Date().toISOString();\n const episode: Episode = {\n id: newMemoryId('ep'),\n kind: 'episodic',\n userId: scope.userId,\n ...(scope.sessionId !== undefined ? { sessionId: scope.sessionId } : {}),\n ...(scope.agentId !== undefined ? { agentId: scope.agentId } : {}),\n sensitivity: input.sensitivity ?? 'internal',\n summary: input.summary,\n startedAt: input.startedAt,\n endedAt: input.endedAt,\n ...(input.importance !== undefined ? { importance: input.importance } : {}),\n ...(input.tags !== undefined ? { tags: Object.freeze([...input.tags]) } : {}),\n ...(input.provenance !== undefined ? { provenance: input.provenance } : {}),\n ...(input.status !== undefined ? { status: input.status } : {}),\n createdAt: now,\n updatedAt: now,\n };\n const embedderId = this.#embedderIdProvider();\n if (\n this.#embedder !== null &&\n embedderId !== null &&\n typeof this.#store.episodic.putWithEmbedding === 'function'\n ) {\n // PS-10: a stored episode summary is the `passage` role for E5.\n const [vector] = await this.#embedder.embed([input.summary], { taskType: 'passage' });\n if (vector !== undefined) {\n await this.#store.episodic.putWithEmbedding(episode, {\n embedding: { embedderId, vector },\n });\n } else {\n await this.#store.episodic.put(episode);\n }\n } else {\n await this.#store.episodic.put(episode);\n }\n span.setAttributes({\n 'memory.episodic.summary_length': input.summary.length,\n ...(input.importance !== undefined\n ? { 'memory.episodic.importance': input.importance }\n : {}),\n });\n return episode;\n });\n }\n\n /** Lookup a single episode by id. */\n async get(id: string): Promise<Episode | null> {\n return this.#store.episodic.get(id);\n }\n\n /**\n * Triple-signal episode retrieval (`recency × relevance ×\n * importance`). The vector signal is computed on demand when an\n * embedder is configured AND the storage adapter exposes\n * `searchVector`; otherwise the FTS5 BM25 score is fed into the\n * relevance term as a normalized fallback.\n */\n async search(\n scope: SessionScope,\n query: string,\n opts: EpisodeSearchOptions = {},\n ): Promise<ReadonlyArray<MemoryHit<Episode>>> {\n return withMemorySpan(\n this.#tracer,\n 'memory.search.episodic',\n scope,\n { 'memory.search.query_length': query.length },\n async (span) => {\n const topK = opts.topK ?? 10;\n const weights = opts.weights ?? DEFAULT_WEIGHTS;\n const ftsHits = await this.#store.episodic.search(scope, {\n query,\n topK: topK * 2,\n ...(opts.asOf !== undefined ? { asOf: opts.asOf } : {}),\n // MRET-4: forward the date filter — it was accepted by the\n // recall_episodes tool and silently dropped right here.\n ...(opts.dateRange !== undefined ? { dateRange: opts.dateRange } : {}),\n ...(opts.signal !== undefined ? { signal: opts.signal } : {}),\n ...(opts.includeQuarantined !== undefined\n ? { includeQuarantined: opts.includeQuarantined }\n : {}),\n });\n const vectorHits = await this.#tryVectorSearch(\n scope,\n query,\n topK * 2,\n opts.asOf,\n opts.includeQuarantined,\n );\n // MRET-4: the vector leg's store signature is positional (no\n // dateRange parameter) — apply the same overlap semantics to its\n // hits so both legs agree before the merge.\n const from = opts.dateRange?.from !== undefined ? Date.parse(opts.dateRange.from) : null;\n const to = opts.dateRange?.to !== undefined ? Date.parse(opts.dateRange.to) : null;\n const rangedVectorHits =\n from !== null || to !== null\n ? vectorHits.filter((h) => {\n if (from !== null && Date.parse(h.record.endedAt) < from) return false;\n if (to !== null && Date.parse(h.record.startedAt) > to) return false;\n return true;\n })\n : vectorHits;\n const merged = mergeRecency(ftsHits, rangedVectorHits, weights);\n const finalHits = merged.slice(0, topK);\n span.setAttributes({\n 'memory.search.episodic.fts_count': ftsHits.length,\n 'memory.search.episodic.vector_count': vectorHits.length,\n 'memory.search.episodic.final_count': finalHits.length,\n ...(opts.asOf !== undefined ? { 'memory.search.episodic.as_of': opts.asOf } : {}),\n });\n return finalHits;\n },\n );\n }\n\n /**\n * Soft-archive an episode. Storage adapters that implement\n * `EpisodicMemoryStoreExt.archive(...)` mark the row archived in\n * place. Adapters that do not expose the extension surface a\n * friendly `TypeError` so the operator can opt the storage layer\n * in (or call `episodic.put(...)` with the archived state set\n * manually).\n */\n async archive(scope: SessionScope, episodeId: string, reason?: string): Promise<void> {\n await withMemorySpan(\n this.#tracer,\n 'memory.write.episodic',\n scope,\n { 'memory.episodic.action': 'archive', 'memory.episodic.episode_id': episodeId },\n async () => {\n if (typeof this.#store.episodic.archive !== 'function') {\n throw new TypeError(\n '[graphorin/memory] EpisodicMemory.archive(...) requires a storage adapter that implements `episodic.archive(id)`. ' +\n 'The default `@graphorin/store-sqlite` adapter implements it; custom adapters can opt in via EpisodicMemoryStoreExt.',\n );\n }\n await this.#store.episodic.archive(episodeId, reason);\n },\n );\n }\n\n /**\n * Most-recent episodes by end time (newest first), with no embedding / FTS\n * query (MCON-1). Requires `EpisodicMemoryStoreExt.listRecent` — the default\n * `@graphorin/store-sqlite` adapter implements it. Optionally includes\n * quarantined episodes (the importance source for the reflection gate).\n */\n async listRecent(\n scope: SessionScope,\n limit: number,\n opts: { includeQuarantined?: boolean } = {},\n ): Promise<ReadonlyArray<Episode>> {\n return withMemorySpan(this.#tracer, 'memory.read.episodic', scope, {}, async (span) => {\n const store = this.#store.episodic;\n if (typeof store.listRecent !== 'function') {\n throw new Error(\n '[graphorin/memory] EpisodicMemory.listRecent requires EpisodicMemoryStoreExt.listRecent. ' +\n 'The default `@graphorin/store-sqlite` adapter implements it; custom adapters can opt in.',\n );\n }\n const out = await store.listRecent(scope, limit, opts);\n span.setAttributes({ 'memory.read.episodic.count': out.length });\n return out;\n });\n }\n\n /** List the most recent episodes (no embedding required). */\n async recent(scope: SessionScope, opts: { topK?: number } = {}): Promise<ReadonlyArray<Episode>> {\n return this.listRecent(scope, opts.topK ?? 10, {});\n }\n\n /**\n * Promote a quarantined episode into default recall (MCON-2). Mirrors\n * {@link SemanticMemory.validate}: re-derives the injection verdict from the\n * stored summary and **refuses** promotion of an injection-flagged episode\n * (`QuarantinePromotionRefusedError`) unless an operator passes\n * `{ force: true }` from a trusted, non-agent context.\n */\n async validate(\n scope: SessionScope,\n episodeId: string,\n reason?: string,\n options?: { readonly force?: boolean },\n ): Promise<void> {\n await withMemorySpan(\n this.#tracer,\n 'memory.write.episodic',\n scope,\n { 'memory.episodic.action': 'validate', 'memory.episodic.episode_id': episodeId },\n async (span) => {\n const store = this.#store.episodic;\n if (typeof store.setStatus !== 'function') {\n throw new TypeError(\n '[graphorin/memory] EpisodicMemory.validate(...) requires a storage adapter that implements `episodic.setStatus(id, status)`. ' +\n 'The default `@graphorin/store-sqlite` adapter implements it; custom adapters can opt in via EpisodicMemoryStoreExt.',\n );\n }\n const force = options?.force === true;\n const existing = await store.get(episodeId);\n if (existing !== null && !force) {\n const injection = detectMemoryInjection(existing.summary);\n if (injection.flagged) {\n span.setAttributes({ 'memory.episodic.validate.refused': true });\n throw new QuarantinePromotionRefusedError(episodeId, injection.markers);\n }\n }\n span.setAttributes({ 'memory.episodic.validate.forced': force });\n await store.setStatus(episodeId, 'active', reason);\n },\n );\n }\n\n async #tryVectorSearch(\n scope: SessionScope,\n query: string,\n topK: number,\n asOf?: string,\n includeQuarantined?: boolean,\n ): Promise<ReadonlyArray<MemoryHit<Episode>>> {\n const embedderId = this.#embedderIdProvider();\n if (\n this.#embedder === null ||\n embedderId === null ||\n typeof this.#store.episodic.searchVector !== 'function'\n ) {\n return [];\n }\n // PS-10: a search query is the `query` role for E5.\n const [vector] = await this.#embedder.embed([query], { taskType: 'query' });\n if (vector === undefined) return [];\n return this.#store.episodic.searchVector(\n scope,\n vector,\n embedderId,\n topK,\n asOf,\n includeQuarantined,\n );\n }\n}\n\nfunction mergeRecency(\n ftsHits: ReadonlyArray<MemoryHit<Episode>>,\n vectorHits: ReadonlyArray<MemoryHit<Episode>>,\n weights: EpisodeRetrievalWeights,\n): ReadonlyArray<MemoryHit<Episode>> {\n const now = Date.now();\n const aggregates = new Map<\n string,\n {\n record: Episode;\n relevance: number;\n recency: number;\n importance: number;\n score: number;\n signals: Record<string, number>;\n }\n >();\n for (const hit of ftsHits) {\n const id = hit.record.id;\n const recency = computeRecency(now, hit.record);\n const importance = hit.record.importance ?? 0;\n const relevance = normalizeRelevance(hit.score);\n const score =\n weights.recency * recency + weights.relevance * relevance + weights.importance * importance;\n aggregates.set(id, {\n record: hit.record,\n relevance,\n recency,\n importance,\n score,\n signals: { fts: relevance, recency, importance },\n });\n }\n for (const hit of vectorHits) {\n const id = hit.record.id;\n const cosine = clamp01(hit.score);\n const existing = aggregates.get(id);\n if (existing === undefined) {\n const recency = computeRecency(now, hit.record);\n const importance = hit.record.importance ?? 0;\n const score =\n weights.recency * recency + weights.relevance * cosine + weights.importance * importance;\n aggregates.set(id, {\n record: hit.record,\n relevance: cosine,\n recency,\n importance,\n score,\n signals: { vector: cosine, recency, importance },\n });\n } else {\n const blended = Math.max(existing.relevance, cosine);\n existing.relevance = blended;\n existing.score =\n weights.recency * existing.recency +\n weights.relevance * blended +\n weights.importance * existing.importance;\n existing.signals.vector = cosine;\n existing.signals['rrf-blend'] = blended;\n }\n }\n const out = Array.from(aggregates.values()).map((a) => ({\n record: a.record,\n score: a.score,\n signals: Object.freeze({ ...a.signals }),\n }));\n out.sort((a, b) => b.score - a.score);\n return out;\n}\n\nfunction computeRecency(now: number, episode: Episode): number {\n const ended = Date.parse(episode.endedAt);\n if (!Number.isFinite(ended)) return 0;\n const elapsedDays = Math.max(0, (now - ended) / (24 * 60 * 60 * 1000));\n return Math.exp(-elapsedDays / 30);\n}\n\nfunction normalizeRelevance(score: number): number {\n // MRET-5/MST-7: the store returns `score = -bm25(...)` — POSITIVE for\n // every FTS match (SQLite bm25 is always negative), so the old\n // `1 / (1 + max(0, -score))` collapsed every lexical hit to exactly\n // 1.0 and the DEC-105 triple-signal ranking degraded to\n // recency + importance. Saturating ratio: 0 at no signal, → 1 as the\n // match strengthens, graduated in between (k = 1 half-point).\n return clamp01(Math.max(0, score) / (Math.max(0, score) + 1));\n}\n\nfunction clamp01(value: number): number {\n if (Number.isNaN(value)) return 0;\n if (value < 0) return 0;\n if (value > 1) return 1;\n return value;\n}\n"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { EpisodeInput, EpisodeRetrievalWeights, EpisodeSearchOptions, EpisodicMemory } from "./episodic-memory.js";
2
+ import { FactInput, FactRememberOptions, FactSearchOptions, FusionStrategy, FusionWeights, IterativeRecallResult, IterativeSearchOptions, RememberOutcome, SemanticMemory } from "./semantic-memory.js";
3
+ import { InsightListOptions, InsightMemory, InsightSearchOptions, capInsightsBelowFacts } from "./insight-memory.js";
4
+ import { InduceOptions, ProceduralMemory, RuleActivationContext, RuleInput } from "./procedural-memory.js";
5
+ import { SessionCompactionPolicy, SessionCompactionResult, SessionMemory } from "./session-memory.js";
6
+ import { SharedMemory } from "./shared-memory.js";
7
+ import { BlockDefinition, BlockSpec, WorkingMemory, defineBlock } from "./working-memory.js";
8
+ export { type BlockDefinition, type BlockSpec, type EpisodeInput, type EpisodeRetrievalWeights, type EpisodeSearchOptions, EpisodicMemory, type FactInput, type FactRememberOptions, type FactSearchOptions, type FusionStrategy, type FusionWeights, type InduceOptions, type InsightListOptions, InsightMemory, type InsightSearchOptions, type IterativeRecallResult, type IterativeSearchOptions, ProceduralMemory, type RememberOutcome, type RuleActivationContext, type RuleInput, SemanticMemory, type SessionCompactionPolicy, type SessionCompactionResult, SessionMemory, SharedMemory, WorkingMemory, capInsightsBelowFacts, defineBlock };
@@ -0,0 +1,9 @@
1
+ import { EpisodicMemory } from "./episodic-memory.js";
2
+ import { InsightMemory, capInsightsBelowFacts } from "./insight-memory.js";
3
+ import { ProceduralMemory } from "./procedural-memory.js";
4
+ import { SemanticMemory } from "./semantic-memory.js";
5
+ import { SessionMemory } from "./session-memory.js";
6
+ import { SharedMemory } from "./shared-memory.js";
7
+ import { WorkingMemory, defineBlock } from "./working-memory.js";
8
+
9
+ export { EpisodicMemory, InsightMemory, ProceduralMemory, SemanticMemory, SessionMemory, SharedMemory, WorkingMemory, capInsightsBelowFacts, defineBlock };
@@ -0,0 +1,71 @@
1
+ import { MemoryStoreAdapter } from "../internal/storage-adapter.js";
2
+ import { Fact, Insight, MemoryHit, SessionScope, Tracer } from "@graphorin/core";
3
+
4
+ //#region src/tiers/insight-memory.d.ts
5
+
6
+ /** Per-call options accepted by {@link InsightMemory.search}. */
7
+ interface InsightSearchOptions {
8
+ readonly topK?: number;
9
+ /**
10
+ * Include quarantined insights (P1-4). Defaults to `false`. Since
11
+ * reflection-synthesized insights *always* land quarantined, set this
12
+ * `true` to surface them for the validation / inspector path — never
13
+ * for auto-recall fed back into the model.
14
+ */
15
+ readonly includeQuarantined?: boolean;
16
+ readonly signal?: AbortSignal;
17
+ }
18
+ /** Per-call options accepted by {@link InsightMemory.list}. */
19
+ interface InsightListOptions {
20
+ readonly limit?: number;
21
+ /** Include quarantined insights (validation / inspector path). */
22
+ readonly includeQuarantined?: boolean;
23
+ }
24
+ /**
25
+ * `InsightMemory` — list / search reflection insights. A no-op (returns
26
+ * empty) when the storage adapter does not expose the optional
27
+ * `insights` surface.
28
+ *
29
+ * @stable
30
+ */
31
+ declare class InsightMemory {
32
+ #private;
33
+ constructor(args: {
34
+ store: MemoryStoreAdapter;
35
+ tracer: Tracer;
36
+ });
37
+ /** FTS keyword search over insight text. */
38
+ search(scope: SessionScope, query: string, opts?: InsightSearchOptions): Promise<ReadonlyArray<MemoryHit<Insight>>>;
39
+ /** Most-recent insights for the scope (newest first). */
40
+ list(scope: SessionScope, opts?: InsightListOptions): Promise<ReadonlyArray<Insight>>;
41
+ /** Lookup a single insight by id. */
42
+ get(id: string): Promise<Insight | null>;
43
+ /**
44
+ * Promote a quarantined insight out of quarantine (MCON-2). Mirrors
45
+ * {@link SemanticMemory.validate}: re-derives the injection verdict from the
46
+ * stored text and **refuses** promotion of an injection-flagged insight
47
+ * unless an operator passes `{ force: true }` from a trusted context.
48
+ */
49
+ validate(scope: SessionScope, insightId: string, reason?: string, options?: {
50
+ readonly force?: boolean;
51
+ }): Promise<void>;
52
+ }
53
+ /**
54
+ * Enforce the P1-1 rank ceiling: an insight may never outrank a primary
55
+ * fact **it cites**. For each insight hit, if any fact it cites is
56
+ * present in `factHits`, its score is lowered to strictly below that
57
+ * cited fact's score — so concatenating the two lists and sorting by
58
+ * score descending can never place the insight above the evidence it
59
+ * was synthesized from. Insights whose cited facts are absent from
60
+ * `factHits` are returned unchanged; this is a relative, not a global,
61
+ * cap (per the execution plan: "never outrank the primary facts they
62
+ * cite").
63
+ *
64
+ * Pure + deterministic — does not mutate its inputs.
65
+ *
66
+ * @stable
67
+ */
68
+ declare function capInsightsBelowFacts(factHits: ReadonlyArray<MemoryHit<Fact>>, insightHits: ReadonlyArray<MemoryHit<Insight>>): ReadonlyArray<MemoryHit<Insight>>;
69
+ //#endregion
70
+ export { InsightListOptions, InsightMemory, InsightSearchOptions, capInsightsBelowFacts };
71
+ //# sourceMappingURL=insight-memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insight-memory.d.ts","names":[],"sources":["../../src/tiers/insight-memory.ts"],"sourcesContent":[],"mappings":";;;;;;AAkGwF,UA5EvE,oBAAA,CA4EuE;EAAd,SAAA,IAAA,CAAA,EAAA,MAAA;EAAR;;;;;;EAoFlD,SAAA,kBAAqB,CAAA,EAAA,OAAA;EACD,SAAA,MAAA,CAAA,EAxJhB,WAwJgB;;;AACG,UArJtB,kBAAA,CAqJsB;EAAV,SAAA,KAAA,CAAA,EAAA,MAAA;EAAd;EACY,SAAA,kBAAA,CAAA,EAAA,OAAA;;;;;;;;;cAzId,aAAA;;;WAIgB;YAA4B;;;gBAO9C,oCAED,uBACL,QAAQ,cAAc,UAAU;;cAoCjB,qBAAoB,qBAA0B,QAAQ,cAAc;;mBAmB/D,QAAQ;;;;;;;kBAatB;;MAIN;;;;;;;;;;;;;;;;;iBAgDW,qBAAA,WACJ,cAAc,UAAU,qBACrB,cAAc,UAAU,YACpC,cAAc,UAAU"}