agentfootprint 8.7.0 → 8.9.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 (245) hide show
  1. package/AGENTS.md +12 -4
  2. package/CLAUDE.md +7 -3
  3. package/ai-instructions/claude-code/SKILL.md +1 -1
  4. package/ai-instructions/setup.sh +0 -0
  5. package/bin/agentfootprint-lint-tools.mjs +0 -0
  6. package/dist/adapters/memory/sqliteVector.js +875 -0
  7. package/dist/adapters/memory/sqliteVector.js.map +1 -0
  8. package/dist/core/Agent.js +6 -0
  9. package/dist/core/Agent.js.map +1 -1
  10. package/dist/core/agent/buildAgentChart.js +12 -1
  11. package/dist/core/agent/buildAgentChart.js.map +1 -1
  12. package/dist/core/agent/buildDynamicAgentChart.js +12 -1
  13. package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
  14. package/dist/core/agent/memoryRecallInjections.js +100 -10
  15. package/dist/core/agent/memoryRecallInjections.js.map +1 -1
  16. package/dist/core/agent/stages/deliver.js.map +1 -1
  17. package/dist/core/slots/buildSystemPromptSlot.js +10 -0
  18. package/dist/core/slots/buildSystemPromptSlot.js.map +1 -1
  19. package/dist/core/slots/helpers.js +12 -10
  20. package/dist/core/slots/helpers.js.map +1 -1
  21. package/dist/embedders/index.js +11 -0
  22. package/dist/embedders/index.js.map +1 -1
  23. package/dist/esm/adapters/memory/sqliteVector.d.ts +251 -0
  24. package/dist/esm/adapters/memory/sqliteVector.js +869 -0
  25. package/dist/esm/adapters/memory/sqliteVector.js.map +1 -0
  26. package/dist/esm/core/Agent.js +6 -0
  27. package/dist/esm/core/Agent.js.map +1 -1
  28. package/dist/esm/core/agent/buildAgentChart.js +13 -2
  29. package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
  30. package/dist/esm/core/agent/buildDynamicAgentChart.js +13 -2
  31. package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
  32. package/dist/esm/core/agent/memoryRecallInjections.d.ts +13 -3
  33. package/dist/esm/core/agent/memoryRecallInjections.js +101 -11
  34. package/dist/esm/core/agent/memoryRecallInjections.js.map +1 -1
  35. package/dist/esm/core/agent/stages/deliver.d.ts +6 -3
  36. package/dist/esm/core/agent/stages/deliver.js.map +1 -1
  37. package/dist/esm/core/slots/buildSystemPromptSlot.js +10 -0
  38. package/dist/esm/core/slots/buildSystemPromptSlot.js.map +1 -1
  39. package/dist/esm/core/slots/helpers.d.ts +11 -2
  40. package/dist/esm/core/slots/helpers.js +11 -9
  41. package/dist/esm/core/slots/helpers.js.map +1 -1
  42. package/dist/esm/embedders/index.js +11 -0
  43. package/dist/esm/embedders/index.js.map +1 -1
  44. package/dist/esm/events/payloads.d.ts +63 -0
  45. package/dist/esm/events/registry.d.ts +3 -1
  46. package/dist/esm/events/registry.js +2 -0
  47. package/dist/esm/events/registry.js.map +1 -1
  48. package/dist/esm/hosting/sqliteSessions.d.ts +7 -13
  49. package/dist/esm/hosting/sqliteSessions.js +8 -25
  50. package/dist/esm/hosting/sqliteSessions.js.map +1 -1
  51. package/dist/esm/index.d.ts +2 -1
  52. package/dist/esm/index.js +6 -1
  53. package/dist/esm/index.js.map +1 -1
  54. package/dist/esm/lib/fnv1a.d.ts +16 -0
  55. package/dist/esm/lib/fnv1a.js +24 -0
  56. package/dist/esm/lib/fnv1a.js.map +1 -0
  57. package/dist/esm/lib/injection-engine/types.d.ts +17 -0
  58. package/dist/esm/lib/injection-engine/types.js.map +1 -1
  59. package/dist/esm/lib/rag/defineRAG.d.ts +126 -26
  60. package/dist/esm/lib/rag/defineRAG.js +112 -25
  61. package/dist/esm/lib/rag/defineRAG.js.map +1 -1
  62. package/dist/esm/lib/rag/index.d.ts +1 -1
  63. package/dist/esm/lib/rag/index.js +1 -1
  64. package/dist/esm/lib/rag/index.js.map +1 -1
  65. package/dist/esm/lib/rag/indexDocuments.d.ts +26 -4
  66. package/dist/esm/lib/rag/indexDocuments.js +12 -1
  67. package/dist/esm/lib/rag/indexDocuments.js.map +1 -1
  68. package/dist/esm/lib/sqliteUnavailable.d.ts +55 -0
  69. package/dist/esm/lib/sqliteUnavailable.js +61 -0
  70. package/dist/esm/lib/sqliteUnavailable.js.map +1 -0
  71. package/dist/esm/memory/define.js +38 -2
  72. package/dist/esm/memory/define.js.map +1 -1
  73. package/dist/esm/memory/define.types.d.ts +93 -1
  74. package/dist/esm/memory/define.types.js +18 -0
  75. package/dist/esm/memory/define.types.js.map +1 -1
  76. package/dist/esm/memory/embedding/embedMessages.js +16 -0
  77. package/dist/esm/memory/embedding/embedMessages.js.map +1 -1
  78. package/dist/esm/memory/embedding/emitEmbedding.d.ts +38 -0
  79. package/dist/esm/memory/embedding/emitEmbedding.js +15 -0
  80. package/dist/esm/memory/embedding/emitEmbedding.js.map +1 -0
  81. package/dist/esm/memory/embedding/loadRelevant.d.ts +49 -15
  82. package/dist/esm/memory/embedding/loadRelevant.js +150 -7
  83. package/dist/esm/memory/embedding/loadRelevant.js.map +1 -1
  84. package/dist/esm/memory/embedding/mockEmbedder.js +4 -0
  85. package/dist/esm/memory/embedding/mockEmbedder.js.map +1 -1
  86. package/dist/esm/memory/embedding/types.d.ts +24 -0
  87. package/dist/esm/memory/index.d.ts +2 -1
  88. package/dist/esm/memory/index.js +2 -1
  89. package/dist/esm/memory/index.js.map +1 -1
  90. package/dist/esm/memory/pipeline/semantic.d.ts +15 -0
  91. package/dist/esm/memory/pipeline/semantic.js +3 -1
  92. package/dist/esm/memory/pipeline/semantic.js.map +1 -1
  93. package/dist/esm/memory/retrieval/index.d.ts +10 -0
  94. package/dist/esm/memory/retrieval/index.js +3 -0
  95. package/dist/esm/memory/retrieval/index.js.map +1 -0
  96. package/dist/esm/memory/retrieval/provenance.d.ts +43 -0
  97. package/dist/esm/memory/retrieval/provenance.js +60 -0
  98. package/dist/esm/memory/retrieval/provenance.js.map +1 -0
  99. package/dist/esm/memory/retrieval/topK.d.ts +67 -0
  100. package/dist/esm/memory/retrieval/topK.js +53 -0
  101. package/dist/esm/memory/retrieval/topK.js.map +1 -0
  102. package/dist/esm/memory/retrieval/types.d.ts +189 -0
  103. package/dist/esm/memory/retrieval/types.js +2 -0
  104. package/dist/esm/memory/retrieval/types.js.map +1 -0
  105. package/dist/esm/memory/stages/formatDefault.d.ts +52 -26
  106. package/dist/esm/memory/stages/formatDefault.js +118 -28
  107. package/dist/esm/memory/stages/formatDefault.js.map +1 -1
  108. package/dist/esm/memory/stages/pickByBudget.js +53 -3
  109. package/dist/esm/memory/stages/pickByBudget.js.map +1 -1
  110. package/dist/esm/memory/stages/types.d.ts +15 -0
  111. package/dist/esm/memory/wire/mountMemoryPipeline.d.ts +25 -0
  112. package/dist/esm/memory/wire/mountMemoryPipeline.js +11 -2
  113. package/dist/esm/memory/wire/mountMemoryPipeline.js.map +1 -1
  114. package/dist/esm/memory-providers.d.ts +2 -0
  115. package/dist/esm/memory-providers.js +8 -0
  116. package/dist/esm/memory-providers.js.map +1 -1
  117. package/dist/esm/observe.d.ts +2 -0
  118. package/dist/esm/observe.js +2 -0
  119. package/dist/esm/observe.js.map +1 -1
  120. package/dist/esm/recorders/core/EmbeddingRecorder.d.ts +19 -0
  121. package/dist/esm/recorders/core/EmbeddingRecorder.js +24 -0
  122. package/dist/esm/recorders/core/EmbeddingRecorder.js.map +1 -0
  123. package/dist/events/registry.js +2 -0
  124. package/dist/events/registry.js.map +1 -1
  125. package/dist/hosting/sqliteSessions.js +10 -27
  126. package/dist/hosting/sqliteSessions.js.map +1 -1
  127. package/dist/index.js +8 -1
  128. package/dist/index.js.map +1 -1
  129. package/dist/lib/fnv1a.js +28 -0
  130. package/dist/lib/fnv1a.js.map +1 -0
  131. package/dist/lib/injection-engine/types.js.map +1 -1
  132. package/dist/lib/rag/defineRAG.js +113 -26
  133. package/dist/lib/rag/defineRAG.js.map +1 -1
  134. package/dist/lib/rag/index.js +2 -1
  135. package/dist/lib/rag/index.js.map +1 -1
  136. package/dist/lib/rag/indexDocuments.js +12 -1
  137. package/dist/lib/rag/indexDocuments.js.map +1 -1
  138. package/dist/lib/sqliteUnavailable.js +65 -0
  139. package/dist/lib/sqliteUnavailable.js.map +1 -0
  140. package/dist/memory/define.js +38 -2
  141. package/dist/memory/define.js.map +1 -1
  142. package/dist/memory/define.types.js +21 -1
  143. package/dist/memory/define.types.js.map +1 -1
  144. package/dist/memory/embedding/embedMessages.js +16 -0
  145. package/dist/memory/embedding/embedMessages.js.map +1 -1
  146. package/dist/memory/embedding/emitEmbedding.js +19 -0
  147. package/dist/memory/embedding/emitEmbedding.js.map +1 -0
  148. package/dist/memory/embedding/loadRelevant.js +152 -8
  149. package/dist/memory/embedding/loadRelevant.js.map +1 -1
  150. package/dist/memory/embedding/mockEmbedder.js +4 -0
  151. package/dist/memory/embedding/mockEmbedder.js.map +1 -1
  152. package/dist/memory/index.js +5 -1
  153. package/dist/memory/index.js.map +1 -1
  154. package/dist/memory/pipeline/semantic.js +2 -0
  155. package/dist/memory/pipeline/semantic.js.map +1 -1
  156. package/dist/memory/retrieval/index.js +9 -0
  157. package/dist/memory/retrieval/index.js.map +1 -0
  158. package/dist/memory/retrieval/provenance.js +65 -0
  159. package/dist/memory/retrieval/provenance.js.map +1 -0
  160. package/dist/memory/retrieval/topK.js +57 -0
  161. package/dist/memory/retrieval/topK.js.map +1 -0
  162. package/dist/memory/retrieval/types.js +3 -0
  163. package/dist/memory/retrieval/types.js.map +1 -0
  164. package/dist/memory/stages/formatDefault.js +118 -28
  165. package/dist/memory/stages/formatDefault.js.map +1 -1
  166. package/dist/memory/stages/pickByBudget.js +53 -3
  167. package/dist/memory/stages/pickByBudget.js.map +1 -1
  168. package/dist/memory/wire/mountMemoryPipeline.js +11 -2
  169. package/dist/memory/wire/mountMemoryPipeline.js.map +1 -1
  170. package/dist/memory-providers.js +13 -1
  171. package/dist/memory-providers.js.map +1 -1
  172. package/dist/observe.js +4 -1
  173. package/dist/observe.js.map +1 -1
  174. package/dist/recorders/core/EmbeddingRecorder.js +28 -0
  175. package/dist/recorders/core/EmbeddingRecorder.js.map +1 -0
  176. package/dist/types/adapters/memory/sqliteVector.d.ts +252 -0
  177. package/dist/types/adapters/memory/sqliteVector.d.ts.map +1 -0
  178. package/dist/types/core/Agent.d.ts.map +1 -1
  179. package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
  180. package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
  181. package/dist/types/core/agent/memoryRecallInjections.d.ts +13 -3
  182. package/dist/types/core/agent/memoryRecallInjections.d.ts.map +1 -1
  183. package/dist/types/core/agent/stages/deliver.d.ts +6 -3
  184. package/dist/types/core/agent/stages/deliver.d.ts.map +1 -1
  185. package/dist/types/core/slots/buildSystemPromptSlot.d.ts.map +1 -1
  186. package/dist/types/core/slots/helpers.d.ts +11 -2
  187. package/dist/types/core/slots/helpers.d.ts.map +1 -1
  188. package/dist/types/embedders/index.d.ts.map +1 -1
  189. package/dist/types/events/payloads.d.ts +63 -0
  190. package/dist/types/events/payloads.d.ts.map +1 -1
  191. package/dist/types/events/registry.d.ts +3 -1
  192. package/dist/types/events/registry.d.ts.map +1 -1
  193. package/dist/types/hosting/sqliteSessions.d.ts +7 -13
  194. package/dist/types/hosting/sqliteSessions.d.ts.map +1 -1
  195. package/dist/types/index.d.ts +2 -1
  196. package/dist/types/index.d.ts.map +1 -1
  197. package/dist/types/lib/fnv1a.d.ts +17 -0
  198. package/dist/types/lib/fnv1a.d.ts.map +1 -0
  199. package/dist/types/lib/injection-engine/types.d.ts +17 -0
  200. package/dist/types/lib/injection-engine/types.d.ts.map +1 -1
  201. package/dist/types/lib/rag/defineRAG.d.ts +126 -26
  202. package/dist/types/lib/rag/defineRAG.d.ts.map +1 -1
  203. package/dist/types/lib/rag/index.d.ts +1 -1
  204. package/dist/types/lib/rag/index.d.ts.map +1 -1
  205. package/dist/types/lib/rag/indexDocuments.d.ts +26 -4
  206. package/dist/types/lib/rag/indexDocuments.d.ts.map +1 -1
  207. package/dist/types/lib/sqliteUnavailable.d.ts +56 -0
  208. package/dist/types/lib/sqliteUnavailable.d.ts.map +1 -0
  209. package/dist/types/memory/define.d.ts.map +1 -1
  210. package/dist/types/memory/define.types.d.ts +93 -1
  211. package/dist/types/memory/define.types.d.ts.map +1 -1
  212. package/dist/types/memory/embedding/embedMessages.d.ts.map +1 -1
  213. package/dist/types/memory/embedding/emitEmbedding.d.ts +39 -0
  214. package/dist/types/memory/embedding/emitEmbedding.d.ts.map +1 -0
  215. package/dist/types/memory/embedding/loadRelevant.d.ts +49 -15
  216. package/dist/types/memory/embedding/loadRelevant.d.ts.map +1 -1
  217. package/dist/types/memory/embedding/mockEmbedder.d.ts.map +1 -1
  218. package/dist/types/memory/embedding/types.d.ts +24 -0
  219. package/dist/types/memory/embedding/types.d.ts.map +1 -1
  220. package/dist/types/memory/index.d.ts +2 -1
  221. package/dist/types/memory/index.d.ts.map +1 -1
  222. package/dist/types/memory/pipeline/semantic.d.ts +15 -0
  223. package/dist/types/memory/pipeline/semantic.d.ts.map +1 -1
  224. package/dist/types/memory/retrieval/index.d.ts +11 -0
  225. package/dist/types/memory/retrieval/index.d.ts.map +1 -0
  226. package/dist/types/memory/retrieval/provenance.d.ts +44 -0
  227. package/dist/types/memory/retrieval/provenance.d.ts.map +1 -0
  228. package/dist/types/memory/retrieval/topK.d.ts +68 -0
  229. package/dist/types/memory/retrieval/topK.d.ts.map +1 -0
  230. package/dist/types/memory/retrieval/types.d.ts +190 -0
  231. package/dist/types/memory/retrieval/types.d.ts.map +1 -0
  232. package/dist/types/memory/stages/formatDefault.d.ts +52 -26
  233. package/dist/types/memory/stages/formatDefault.d.ts.map +1 -1
  234. package/dist/types/memory/stages/pickByBudget.d.ts.map +1 -1
  235. package/dist/types/memory/stages/types.d.ts +15 -0
  236. package/dist/types/memory/stages/types.d.ts.map +1 -1
  237. package/dist/types/memory/wire/mountMemoryPipeline.d.ts +25 -0
  238. package/dist/types/memory/wire/mountMemoryPipeline.d.ts.map +1 -1
  239. package/dist/types/memory-providers.d.ts +2 -0
  240. package/dist/types/memory-providers.d.ts.map +1 -1
  241. package/dist/types/observe.d.ts +2 -0
  242. package/dist/types/observe.d.ts.map +1 -1
  243. package/dist/types/recorders/core/EmbeddingRecorder.d.ts +20 -0
  244. package/dist/types/recorders/core/EmbeddingRecorder.d.ts.map +1 -0
  245. package/package.json +1 -1
@@ -1,29 +1,54 @@
1
1
  /**
2
2
  * loadRelevant — read-side stage that embeds a query and fetches the
3
- * top-k most similar entries from a vector-capable `MemoryStore`.
3
+ * most similar entries from a vector-capable `MemoryStore`.
4
4
  *
5
- * Reads from scope: `identity`, `newMessages` (or custom queryFrom)
6
- * Writes to scope: `loaded` (MemoryEntry[], ordered best-first — to be
7
- * narrowed by `pickByBudget` downstream)
5
+ * Reads from scope: `identity`, `messages` (or `newMessages`, or custom queryFrom)
6
+ * Writes to scope: `loaded` (MemoryEntry[], ordered best-first — narrowed
7
+ * by `pickByBudget` downstream)
8
+ * `retrieved` (RetrievalEvidence — what was considered,
9
+ * what was admitted, and why about each one)
8
10
  *
9
11
  * Query derivation:
10
- * Default: the last user message in `newMessages`. That's the natural
11
- * "what is the user asking about?" signal. Override with `queryFrom`
12
- * for custom retrieval (e.g., compose user + assistant content,
13
- * pull a summary, etc.).
12
+ * Default: the last user message. That's the natural "what is the user
13
+ * asking about?" signal. Override with `queryFrom` for custom retrieval.
14
14
  *
15
15
  * Empty behavior:
16
- * No query text → no search → `loaded = []`. Downstream
17
- * `pickByBudget` picks nothing and the formatter emits nothing — safe.
16
+ * No query text → no search → `loaded = []`. Downstream `pickByBudget`
17
+ * picks nothing and the formatter emits nothing — safe, and now
18
+ * RECORDED: the evidence still lands, saying the query was empty.
18
19
  *
19
20
  * Feature detection:
20
- * Throws at stage build time if the store doesn't implement
21
- * `search()`. Fail-loud — a semantic pipeline configured against a
22
- * non-vector store is a config bug, not a runtime condition.
21
+ * Throws at stage build time if the store doesn't implement `search()`.
22
+ * Fail-loud — a semantic pipeline configured against a non-vector store
23
+ * is a config bug, not a runtime condition.
24
+ *
25
+ * ─── Why the threshold moved out of the store (8.8.0) ──────────────────
26
+ *
27
+ * Until 8.8.0 the quality floor was passed to `store.search({ minScore })`,
28
+ * so every candidate that failed it was filtered INSIDE the store and never
29
+ * came back. The consequence was not a small one: a retrieval that injected
30
+ * nothing left no trace of what it nearly injected, and "why did the agent
31
+ * not read that passage" had no answer anywhere in the recording.
32
+ *
33
+ * The floor is now applied here, over a pool of `k + rejectWindow`. **This
34
+ * does not change which entries are admitted, ever.** Proof: `search`
35
+ * returns score-descending, and the pool is at least `k`. Either
36
+ *
37
+ * (a) every entry in the pool clears the floor — then the admitted set is
38
+ * the first `k` of them, which is exactly what `{ minScore, k }` would
39
+ * have returned; or
40
+ * (b) some entry at position p fails the floor — then every entry after p
41
+ * fails it too, so the pool already contains EVERY entry in the
42
+ * namespace that clears the floor, and admitting all of them (capped
43
+ * at `k`) is again exactly what `{ minScore, k }` would have returned.
44
+ *
45
+ * `rejectWindow` therefore only controls how many near-misses we can SHOW.
46
+ * It cannot change what the model sees.
23
47
  */
24
48
  import type { TypedScope } from 'footprintjs';
25
49
  import type { MemoryStore } from '../store/index.js';
26
50
  import type { MemoryState } from '../stages/index.js';
51
+ import type { RetrievalStrategy } from '../retrieval/types.js';
27
52
  import type { Embedder } from './types.js';
28
53
  export interface LoadRelevantConfig {
29
54
  /** The vector-capable store. Must implement `search()`. */
@@ -43,9 +68,18 @@ export interface LoadRelevantConfig {
43
68
  /** Filter results by tier. */
44
69
  readonly tiers?: ReadonlyArray<'hot' | 'warm' | 'cold'>;
45
70
  /**
46
- * Extract the query text from scope. Default: the last user message
47
- * in `newMessages`. Override for custom retrieval signals.
71
+ * The rule that decides which candidates reach the prompt. Defaults to
72
+ * `topK({ k, threshold: minScore })` — i.e. `k` and `minScore` above are
73
+ * the shorthand, and this is the same rule spelled out. Pass a strategy
74
+ * to replace the rule entirely.
75
+ */
76
+ readonly retrieval?: RetrievalStrategy;
77
+ /**
78
+ * Extract the query text from scope. Default: the last user message.
79
+ * Override for custom retrieval signals.
48
80
  */
49
81
  readonly queryFrom?: (scope: TypedScope<MemoryState>) => string;
50
82
  }
51
83
  export declare function loadRelevant(config: LoadRelevantConfig): (scope: TypedScope<MemoryState>) => Promise<void>;
84
+ /** Test seam — the once-per-process warning is per PROCESS, which tests must be able to reset. */
85
+ export declare function __resetEmptyCorpusWarnings(): void;
@@ -1,3 +1,8 @@
1
+ import { identityNamespace } from '../identity/index.js';
2
+ import { fnv1a } from '../../lib/fnv1a.js';
3
+ import { chunkProvenance } from '../retrieval/provenance.js';
4
+ import { topK } from '../retrieval/topK.js';
5
+ import { emitEmbedding } from './emitEmbedding.js';
1
6
  /**
2
7
  * Default query extractor — last user message.
3
8
  *
@@ -19,6 +24,12 @@ function defaultQueryFrom(scope) {
19
24
  }
20
25
  return '';
21
26
  }
27
+ /** Emit through the scope's emit channel when there is one (there always is under an Agent). */
28
+ function emit(scope, type, payload) {
29
+ const emitter = scope.$emit;
30
+ if (typeof emitter === 'function')
31
+ emitter.call(scope, type, payload);
32
+ }
22
33
  export function loadRelevant(config) {
23
34
  const { store, embedder } = config;
24
35
  if (!store.search) {
@@ -26,31 +37,163 @@ export function loadRelevant(config) {
26
37
  'Use a vector-capable adapter (InMemoryStore, pgvector, Pinecone, ...).');
27
38
  }
28
39
  const queryFrom = config.queryFrom ?? defaultQueryFrom;
29
- const k = config.k ?? 20;
40
+ // The shorthand and the strategy are two spellings of one rule; the
41
+ // strategy wins when both are present, and `defineMemory` refuses the
42
+ // contradiction before it ever gets here.
43
+ const strategy = config.retrieval ??
44
+ topK({
45
+ k: config.k ?? 20,
46
+ threshold: config.minScore === undefined ? null : config.minScore,
47
+ // With no explicit strategy there is no explicit reject window
48
+ // either; 10 near-misses is enough to diagnose a threshold without
49
+ // making every retrieval read a large page.
50
+ });
51
+ const poolSize = strategy.k + strategy.rejectWindow;
30
52
  return async (scope) => {
31
53
  const identity = scope.identity;
54
+ const namespace = identityNamespace(identity);
32
55
  const text = queryFrom(scope).trim();
56
+ const baseEvidence = {
57
+ queryHash: fnv1a(text),
58
+ k: strategy.k,
59
+ ...(strategy.threshold !== undefined && { threshold: strategy.threshold }),
60
+ ...(config.embedderId !== undefined && { embedderId: config.embedderId }),
61
+ selectionOrder: 'recency',
62
+ namespace,
63
+ };
33
64
  if (text.length === 0) {
34
65
  scope.loaded = [];
66
+ const emptyQuery = {
67
+ ...baseEvidence,
68
+ consideredCount: 0,
69
+ admittedCount: 0,
70
+ rejectedCount: 0,
71
+ candidates: [],
72
+ candidatesComplete: true,
73
+ // The corpus was never asked, so it cannot be reported empty.
74
+ corpusEmpty: false,
75
+ };
76
+ scope.retrieved = emptyQuery;
35
77
  return;
36
78
  }
37
79
  const signal = scope.$getEnv?.()?.signal;
80
+ const embedStartedAt = Date.now();
38
81
  const queryVec = (await embedder.embed({
39
82
  text,
40
83
  ...(signal ? { signal } : {}),
41
84
  }));
85
+ // The QUERY-time half of the two-phase cost model (8.9.0): one embedding
86
+ // per retrieval, scaling with traffic rather than with corpus size. Paired
87
+ // with the `'document'` side in `embedMessages`, this is what makes the
88
+ // cost of a corpus a number you can read rather than one you estimate.
89
+ emitEmbedding(scope, {
90
+ model: config.embedderId ?? embedder.id ?? 'unknown',
91
+ provider: 'custom',
92
+ inputKind: 'query',
93
+ dimension: queryVec.length,
94
+ count: 1,
95
+ durationMs: Date.now() - embedStartedAt,
96
+ });
42
97
  // store.search optional on MemoryStore but required when an embedder
43
98
  // is configured (validated upstream by defineMemory).
44
99
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
45
- const results = await store.search(identity, queryVec, {
46
- k,
47
- ...(config.minScore !== undefined && { minScore: config.minScore }),
100
+ const results = (await store.search(identity, queryVec, {
101
+ k: poolSize,
102
+ // `minScore` is deliberately NOT forwarded — see the header proof.
48
103
  ...(config.tiers && { tiers: config.tiers }),
49
104
  ...(config.embedderId !== undefined && { embedderId: config.embedderId }),
105
+ text,
106
+ }));
107
+ // A store that ranks server-side may return entries without a usable
108
+ // score. We report that rather than printing a number we did not get.
109
+ const scoresUsable = results.every((r) => typeof r.score === 'number' && Number.isFinite(r.score));
110
+ const verdicts = scoresUsable
111
+ ? strategy.select(results.map((r) => ({ entry: r.entry, score: r.score })))
112
+ : // No comparable scores to rule on. The store already ranked, so we
113
+ // honour its order and take the first `k` — and say in the record
114
+ // that we could not see the candidates ourselves.
115
+ results.map((_, i) => ({ admitted: i < strategy.k }));
116
+ const admitted = [];
117
+ const candidates = [];
118
+ results.forEach((result, i) => {
119
+ // `verdicts` is built from `results` above, one per element.
120
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
121
+ const verdict = verdicts[i];
122
+ if (verdict.admitted)
123
+ admitted.push(result);
124
+ candidates.push({
125
+ id: result.entry.id,
126
+ score: result.score,
127
+ rank: i + 1,
128
+ admitted: verdict.admitted,
129
+ ...(verdict.reason !== undefined && { reason: verdict.reason }),
130
+ ...chunkProvenance(result.entry.value),
131
+ });
132
+ });
133
+ const evidence = {
134
+ ...baseEvidence,
135
+ ...(queryVec.length > 0 && { dimensions: queryVec.length }),
136
+ consideredCount: results.length,
137
+ admittedCount: admitted.length,
138
+ rejectedCount: results.length - admitted.length,
139
+ ...(scoresUsable
140
+ ? { candidates }
141
+ : {
142
+ candidatesOmittedReason: 'the store ranked this query server-side and returned no comparable scores',
143
+ }),
144
+ // The pool came back full, so there may be further below-threshold
145
+ // entries we never saw. This never weakens the ADMITTED set (see
146
+ // the header proof) — only the rejected list is a sample.
147
+ candidatesComplete: results.length < poolSize,
148
+ corpusEmpty: results.length === 0,
149
+ };
150
+ scope.loaded = admitted.map((r) => r.entry);
151
+ scope.retrieved = evidence;
152
+ // Telemetry rides the emit channel, never a commit payload. The
153
+ // memory bridge (`memoryRecorder`) is attached on every Agent run, so
154
+ // this reaches `agent.on('agentfootprint.memory.retrieved')` with no
155
+ // extra wiring. Which retriever fired is `meta.runtimeStageId`
156
+ // (`sf-memory-read-<id>/load-relevant#N`) — the house correlation model.
157
+ emit(scope, 'agentfootprint.memory.retrieved', {
158
+ queryHash: evidence.queryHash,
159
+ k: evidence.k,
160
+ ...(evidence.threshold !== undefined && { threshold: evidence.threshold }),
161
+ ...(evidence.embedderId !== undefined && { embedderId: evidence.embedderId }),
162
+ ...(evidence.dimensions !== undefined && { dimensions: evidence.dimensions }),
163
+ consideredCount: evidence.consideredCount,
164
+ admittedCount: evidence.admittedCount,
165
+ rejectedCount: evidence.rejectedCount,
166
+ ...(evidence.candidates !== undefined && { candidates: evidence.candidates }),
167
+ ...(evidence.candidatesOmittedReason !== undefined && {
168
+ candidatesOmittedReason: evidence.candidatesOmittedReason,
169
+ }),
170
+ candidatesComplete: evidence.candidatesComplete,
171
+ corpusEmpty: evidence.corpusEmpty,
172
+ namespace: evidence.namespace,
50
173
  });
51
- // Write loaded entries to scope in best-first order — downstream
52
- // pickByBudget further narrows by the token budget.
53
- scope.loaded = results.map((r) => r.entry);
174
+ // An empty namespace is almost never "the corpus has nothing to say".
175
+ // It is almost always "the corpus was indexed under a different
176
+ // identity than the one being queried" — the failure that used to be
177
+ // completely silent. Say it once per process, naming both sides.
178
+ if (evidence.corpusEmpty)
179
+ warnEmptyCorpus(namespace);
54
180
  };
55
181
  }
182
+ const warnedNamespaces = new Set();
183
+ function warnEmptyCorpus(namespace) {
184
+ if (warnedNamespaces.has(namespace))
185
+ return;
186
+ warnedNamespaces.add(namespace);
187
+ console.warn(`[agentfootprint] Semantic retrieval found NO entries at all in namespace '${namespace}'.\n` +
188
+ ` Nothing was injected, and the answer will come from the model alone.\n` +
189
+ ` The usual cause is that the corpus was indexed under a different identity than the one\n` +
190
+ ` being queried: indexDocuments() defaults to { conversationId: '_global' }, and a memory\n` +
191
+ ` reads under the identity passed to agent.run() unless the retriever declares its own\n` +
192
+ ` \`corpus\`. defineRAG() defaults \`corpus\` to { conversationId: '_global' } so the two\n` +
193
+ ` sides meet; pass \`corpus\` explicitly when you index per tenant.`);
194
+ }
195
+ /** Test seam — the once-per-process warning is per PROCESS, which tests must be able to reset. */
196
+ export function __resetEmptyCorpusWarnings() {
197
+ warnedNamespaces.clear();
198
+ }
56
199
  //# sourceMappingURL=loadRelevant.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"loadRelevant.js","sourceRoot":"","sources":["../../../../src/memory/embedding/loadRelevant.ts"],"names":[],"mappings":"AA2DA;;;;;;;GAOG;AACH,SAAS,gBAAgB,CAAC,KAA8B;IACtD,MAAM,QAAQ,GAAG,KAAqD,CAAC;IACvE,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC;IACzC,MAAM,MAAM,GACV,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAwB,CAAC;IAErF,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QAChC,IAAI,CAAC,CAAC,OAAO;YAAE,OAAO,CAAC,CAAC,OAAO,CAAC;IAClC,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAA0B;IACrD,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;IACnC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CACb,kEAAkE;YAChE,wEAAwE,CAC3E,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,gBAAgB,CAAC;IACvD,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAEzB,OAAO,KAAK,EAAE,KAA8B,EAAiB,EAAE;QAC7D,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAChC,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC;QACzC,MAAM,QAAQ,GAAG,CAAC,MAAM,QAAQ,CAAC,KAAK,CAAC;YACrC,IAAI;YACJ,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9B,CAAC,CAAa,CAAC;QAEhB,qEAAqE;QACrE,sDAAsD;QACtD,oEAAoE;QACpE,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,MAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE;YACtD,CAAC;YACD,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;YACnE,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;YAC5C,GAAG,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;SAC1E,CAAC,CAAC;QAEH,iEAAiE;QACjE,oDAAoD;QACpD,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAA0B,CAAC;IACtE,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"loadRelevant.js","sourceRoot":"","sources":["../../../../src/memory/embedding/loadRelevant.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,10 @@ export function mockEmbedder(options = {}) {
17
17
  }
18
18
  return {
19
19
  dimensions,
20
+ // Named like the others so a store can refuse the swap between a mock
21
+ // index and a real one — which is a swap worth refusing, since a corpus
22
+ // indexed by letter frequency and queried by meaning scores nothing.
23
+ id: 'mock',
20
24
  async embed({ text }) {
21
25
  return charFrequency(text, dimensions);
22
26
  },
@@ -1 +1 @@
1
- {"version":3,"file":"mockEmbedder.js","sourceRoot":"","sources":["../../../../src/memory/embedding/mockEmbedder.ts"],"names":[],"mappings":"AAeA,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAE9B,SAAS,aAAa,CAAC,IAAY,EAAE,IAAY;IAC/C,MAAM,GAAG,GAAG,IAAI,KAAK,CAAS,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAMD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,UAA+B,EAAE;IAC5D,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,kBAAkB,CAAC;IAC5D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,4DAA4D,UAAU,GAAG,CAAC,CAAC;IAC7F,CAAC;IAED,OAAO;QACL,UAAU;QACV,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,EAAa;YAC7B,OAAO,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACzC,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,EAAE,KAAK,EAAkB;YACxC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;QAC9D,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"mockEmbedder.js","sourceRoot":"","sources":["../../../../src/memory/embedding/mockEmbedder.ts"],"names":[],"mappings":"AAeA,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAE9B,SAAS,aAAa,CAAC,IAAY,EAAE,IAAY;IAC/C,MAAM,GAAG,GAAG,IAAI,KAAK,CAAS,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAMD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,UAA+B,EAAE;IAC5D,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,kBAAkB,CAAC;IAC5D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,4DAA4D,UAAU,GAAG,CAAC,CAAC;IAC7F,CAAC;IAED,OAAO;QACL,UAAU;QACV,sEAAsE;QACtE,wEAAwE;QACxE,qEAAqE;QACrE,EAAE,EAAE,MAAM;QACV,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,EAAa;YAC7B,OAAO,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACzC,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,EAAE,KAAK,EAAkB;YACxC,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;QAC9D,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -35,6 +35,30 @@ export interface EmbedBatchArgs {
35
35
  export interface Embedder {
36
36
  /** Vector length. Constant per embedder instance. */
37
37
  readonly dimensions: number;
38
+ /**
39
+ * Stable name of the embedding space this instance produces (8.9.0).
40
+ *
41
+ * Together with `dimensions` it forms the fingerprint a durable store
42
+ * records per vector — `'<id>@<dims>'` — and refuses on when it changes.
43
+ * Cosine similarity between two embedding spaces is not a weak signal; it
44
+ * is not a signal, and it comes back as a confident number in the same
45
+ * range as a real one. A store that can name the space can refuse the mix;
46
+ * one that cannot has to let it through.
47
+ *
48
+ * Optional, because an `Embedder` is a structural interface and every
49
+ * hand-written one predates this field. When it is absent the store falls
50
+ * back to comparing `dimensions` alone, which catches the arithmetically
51
+ * impossible case and not the merely wrong one.
52
+ *
53
+ * Every shipped embedder sets it, and it is what you pass as `embedderId`:
54
+ *
55
+ * ```ts
56
+ * const embedder = staticEmbedder();
57
+ * await indexDocuments(store, embedder, docs, { embedderId: embedder.id });
58
+ * defineRAG({ id: 'docs', store, embedder, embedderId: embedder.id });
59
+ * ```
60
+ */
61
+ readonly id?: string;
38
62
  /** Embed a single text into a vector of length `dimensions`. */
39
63
  embed(args: EmbedArgs): Promise<number[]>;
40
64
  /**
@@ -15,7 +15,8 @@ export * from './pipeline/index.js';
15
15
  export * from './stages/index.js';
16
16
  export * from './store/index.js';
17
17
  export * from './wire/index.js';
18
- export { MEMORY_TYPES, MEMORY_STRATEGIES, MEMORY_TIMING, SNAPSHOT_PROJECTIONS, MEMORY_INJECTION_KEY_PREFIX, isMemoryType, isMemoryStrategyKind, isMemoryTiming, isSnapshotProjection, memoryInjectionKey, isMemoryInjectionKey, type MemoryType, type MemoryStrategyKind, type MemoryTiming, type SnapshotProjection, type Strategy, type MemoryWindowStrategy, type BudgetStrategy, type SummarizeStrategy, type TopKStrategy, type ExtractStrategy, type DecayStrategy, type HybridStrategy, type MemoryDefinition, type DefineMemoryOptions, type DefineEpisodicOptions, type DefineSemanticOptions, type DefineNarrativeOptions, type DefineCausalOptions, type MemoryRedactionPolicy, } from './define.types.js';
18
+ export * from './retrieval/index.js';
19
+ export { MEMORY_TYPES, MEMORY_STRATEGIES, MEMORY_TIMING, SNAPSHOT_PROJECTIONS, MEMORY_INJECTION_KEY_PREFIX, RETRIEVAL_EVIDENCE_KEY_PREFIX, isMemoryType, isMemoryStrategyKind, isMemoryTiming, isSnapshotProjection, memoryInjectionKey, isMemoryInjectionKey, retrievalEvidenceKey, isRetrievalEvidenceKey, type MemoryType, type MemoryStrategyKind, type MemoryTiming, type SnapshotProjection, type Strategy, type MemoryWindowStrategy, type BudgetStrategy, type SummarizeStrategy, type TopKStrategy, type TopKShorthandStrategy, type TopKRetrievalStrategy, type MemoryFlavor, type ExtractStrategy, type DecayStrategy, type HybridStrategy, type MemoryDefinition, type DefineMemoryOptions, type DefineEpisodicOptions, type DefineSemanticOptions, type DefineNarrativeOptions, type DefineCausalOptions, type MemoryRedactionPolicy, } from './define.types.js';
19
20
  /**
20
21
  * @deprecated Since 7.27.1 — use `MemoryWindowStrategy`.
21
22
  *
@@ -15,7 +15,8 @@ export * from './pipeline/index.js';
15
15
  export * from './stages/index.js';
16
16
  export * from './store/index.js';
17
17
  export * from './wire/index.js';
18
+ export * from './retrieval/index.js';
18
19
  // Consumer-facing factory + const-objects for memory configuration.
19
- export { MEMORY_TYPES, MEMORY_STRATEGIES, MEMORY_TIMING, SNAPSHOT_PROJECTIONS, MEMORY_INJECTION_KEY_PREFIX, isMemoryType, isMemoryStrategyKind, isMemoryTiming, isSnapshotProjection, memoryInjectionKey, isMemoryInjectionKey, } from './define.types.js';
20
+ export { MEMORY_TYPES, MEMORY_STRATEGIES, MEMORY_TIMING, SNAPSHOT_PROJECTIONS, MEMORY_INJECTION_KEY_PREFIX, RETRIEVAL_EVIDENCE_KEY_PREFIX, isMemoryType, isMemoryStrategyKind, isMemoryTiming, isSnapshotProjection, memoryInjectionKey, isMemoryInjectionKey, retrievalEvidenceKey, isRetrievalEvidenceKey, } from './define.types.js';
20
21
  export { defineMemory } from './define.js';
21
22
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/memory/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAEhC,oEAAoE;AACpE,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,YAAY,EACZ,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,GAoBrB,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/memory/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AAErC,oEAAoE;AACpE,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,6BAA6B,EAC7B,YAAY,EACZ,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,GAuBvB,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
@@ -1,3 +1,5 @@
1
+ import { type MemoryFormatFlavor } from '../stages/formatDefault.js';
2
+ import type { RetrievalStrategy } from '../retrieval/types.js';
1
3
  import type { MemoryStore } from '../store/index.js';
2
4
  import type { MemoryPipeline } from './types.js';
3
5
  import type { Embedder } from '../embedding/types.js';
@@ -29,6 +31,19 @@ export interface SemanticPipelineConfig {
29
31
  /** Forwarded to `formatDefault`. */
30
32
  readonly formatHeader?: string;
31
33
  readonly formatFooter?: string;
34
+ /**
35
+ * The retrieval rule (8.8.0). Replaces `k` + `minScore` above; see
36
+ * {@link RetrievalStrategy}. When absent, `topK({ k, threshold: minScore })`
37
+ * is built from those two — the same rule, spelled the old way.
38
+ */
39
+ readonly retrieval?: RetrievalStrategy;
40
+ /**
41
+ * Which claim the injected block makes (8.8.0). `'rag'` renders each
42
+ * entry as a citable `<source>` with its document, page and score;
43
+ * `'memory'` (default) keeps the conversation-recall `<memory>` shape
44
+ * byte for byte.
45
+ */
46
+ readonly flavor?: MemoryFormatFlavor;
32
47
  }
33
48
  /**
34
49
  * Build the semantic read + write pipelines sharing a single store.
@@ -37,7 +37,7 @@
37
37
  */
38
38
  import { flowChart } from 'footprintjs';
39
39
  import { pickByBudget } from '../stages/pickByBudget.js';
40
- import { formatDefault } from '../stages/formatDefault.js';
40
+ import { formatDefault, } from '../stages/formatDefault.js';
41
41
  import { writeMessages } from '../stages/writeMessages.js';
42
42
  import { loadRelevant } from '../embedding/loadRelevant.js';
43
43
  import { embedMessages, } from '../embedding/embedMessages.js';
@@ -57,6 +57,7 @@ export function semanticPipeline(config) {
57
57
  ...(config.k !== undefined && { k: config.k }),
58
58
  ...(config.minScore !== undefined && { minScore: config.minScore }),
59
59
  ...(config.tiers && { tiers: config.tiers }),
60
+ ...(config.retrieval !== undefined && { retrieval: config.retrieval }),
60
61
  };
61
62
  const pickConfig = {
62
63
  ...(config.reserveTokens !== undefined && { reserveTokens: config.reserveTokens }),
@@ -66,6 +67,7 @@ export function semanticPipeline(config) {
66
67
  const formatConfig = {
67
68
  ...(config.formatHeader !== undefined && { header: config.formatHeader }),
68
69
  ...(config.formatFooter !== undefined && { footer: config.formatFooter }),
70
+ ...(config.flavor !== undefined && { flavor: config.flavor }),
69
71
  };
70
72
  const embedConfig = {
71
73
  embedder: config.embedder,
@@ -1 +1 @@
1
- {"version":3,"file":"semantic.js","sourceRoot":"","sources":["../../../../src/memory/pipeline/semantic.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"semantic.js","sourceRoot":"","sources":["../../../../src/memory/pipeline/semantic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * memory/retrieval — what a retrieval considered, and the seam that
3
+ * decides what it keeps.
4
+ *
5
+ * @see ./types.ts the record + the strategy interface
6
+ * @see ./topK.ts the strategy 8.7.0 had, now written down as one
7
+ */
8
+ export type { RetrievalEvidence, RetrievalRejectReason, RetrievalStrategy, RetrievalVerdict, RetrievedCandidate, ScoredCandidate, } from './types.js';
9
+ export { topK, type TopKOptions } from './topK.js';
10
+ export { chunkProvenance, chunkText, type ChunkProvenance } from './provenance.js';
@@ -0,0 +1,3 @@
1
+ export { topK } from './topK.js';
2
+ export { chunkProvenance, chunkText } from './provenance.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/memory/retrieval/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,IAAI,EAAoB,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAwB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * provenance — read a stored entry's coordinates back out of it.
3
+ *
4
+ * Pattern: pure projection.
5
+ * Role: memory/ layer. One place that knows which metadata keys mean
6
+ * "which document", "which page", "which section", so the
7
+ * retrieval record and the citation the model sees can never
8
+ * disagree about a chunk's origin.
9
+ * Emits: N/A.
10
+ *
11
+ * The keys are the ones `indexDocuments` already accepts on
12
+ * `RagDocument.metadata`, and the ones a document splitter will write.
13
+ * Nothing is invented: an entry that carries no metadata simply has no
14
+ * coordinates, and the record says so by omitting the fields rather than
15
+ * by guessing a filename from an id.
16
+ */
17
+ /** The document coordinates a chunk can carry. All optional — absence is honest. */
18
+ export interface ChunkProvenance {
19
+ /** Which document this text came from. Read from `docUri`, else `source`. */
20
+ readonly docUri?: string;
21
+ /** Which page, for paginated formats. */
22
+ readonly page?: number;
23
+ /** Which section heading the splitter cut under. */
24
+ readonly heading?: string;
25
+ }
26
+ /**
27
+ * Pull the coordinates out of a stored value.
28
+ *
29
+ * Accepts metadata at the value's `metadata` key (where `indexDocuments`
30
+ * puts it) or directly on the value, so a hand-built entry works too.
31
+ */
32
+ export declare function chunkProvenance(value: unknown): ChunkProvenance;
33
+ /**
34
+ * The text a stored value carries.
35
+ *
36
+ * Two shapes reach the formatter through the same pipeline: a chat
37
+ * `Message` (`{ role, content }`) from conversation memory, and a
38
+ * document (`{ id, content, metadata }`) from `indexDocuments`. Both
39
+ * keep their text on `content`, which is why one accessor serves both —
40
+ * but only the message shape has a meaningful `role`, which is why the
41
+ * corpus formatter does not print one.
42
+ */
43
+ export declare function chunkText(value: unknown): string;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * provenance — read a stored entry's coordinates back out of it.
3
+ *
4
+ * Pattern: pure projection.
5
+ * Role: memory/ layer. One place that knows which metadata keys mean
6
+ * "which document", "which page", "which section", so the
7
+ * retrieval record and the citation the model sees can never
8
+ * disagree about a chunk's origin.
9
+ * Emits: N/A.
10
+ *
11
+ * The keys are the ones `indexDocuments` already accepts on
12
+ * `RagDocument.metadata`, and the ones a document splitter will write.
13
+ * Nothing is invented: an entry that carries no metadata simply has no
14
+ * coordinates, and the record says so by omitting the fields rather than
15
+ * by guessing a filename from an id.
16
+ */
17
+ function asRecord(value) {
18
+ return typeof value === 'object' && value !== null
19
+ ? value
20
+ : undefined;
21
+ }
22
+ /**
23
+ * Pull the coordinates out of a stored value.
24
+ *
25
+ * Accepts metadata at the value's `metadata` key (where `indexDocuments`
26
+ * puts it) or directly on the value, so a hand-built entry works too.
27
+ */
28
+ export function chunkProvenance(value) {
29
+ const root = asRecord(value);
30
+ if (!root)
31
+ return {};
32
+ const meta = asRecord(root['metadata']) ?? root;
33
+ const rawDoc = meta['docUri'] ?? meta['source'];
34
+ const docUri = typeof rawDoc === 'string' && rawDoc.length > 0 ? rawDoc : undefined;
35
+ const rawPage = meta['page'];
36
+ const page = typeof rawPage === 'number' && Number.isFinite(rawPage) ? rawPage : undefined;
37
+ const rawHeading = meta['heading'];
38
+ const heading = typeof rawHeading === 'string' && rawHeading.length > 0 ? rawHeading : undefined;
39
+ return {
40
+ ...(docUri !== undefined && { docUri }),
41
+ ...(page !== undefined && { page }),
42
+ ...(heading !== undefined && { heading }),
43
+ };
44
+ }
45
+ /**
46
+ * The text a stored value carries.
47
+ *
48
+ * Two shapes reach the formatter through the same pipeline: a chat
49
+ * `Message` (`{ role, content }`) from conversation memory, and a
50
+ * document (`{ id, content, metadata }`) from `indexDocuments`. Both
51
+ * keep their text on `content`, which is why one accessor serves both —
52
+ * but only the message shape has a meaningful `role`, which is why the
53
+ * corpus formatter does not print one.
54
+ */
55
+ export function chunkText(value) {
56
+ const root = asRecord(value);
57
+ const content = root?.['content'];
58
+ return typeof content === 'string' ? content : '';
59
+ }
60
+ //# sourceMappingURL=provenance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provenance.js","sourceRoot":"","sources":["../../../../src/memory/retrieval/provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAYH,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAChD,CAAC,CAAE,KAAiC;QACpC,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,IAAI,CAAC;IAEhD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAEpF,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAE3F,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IAEjG,OAAO;QACL,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,CAAC;QACvC,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC;QACnC,GAAG,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,CAAC;KAC1C,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC7B,MAAM,OAAO,GAAG,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC;IAClC,OAAO,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AACpD,CAAC"}