@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,118 @@
1
+ //#region src/context-engine/annotations.d.ts
2
+ /**
3
+ * Cooperation contract between the {@link ContextEngine} and the
4
+ * outbound prompt-redaction middleware (D3, see ADR-045 / DEC-157)
5
+ * + the inbound tool-result sanitization middleware (D4, see
6
+ * RB-43 / DEC-159).
7
+ *
8
+ * Every {@link MessageContent} part assembled by the ContextEngine
9
+ * carries two **independent** annotations:
10
+ *
11
+ * - `graphorin.content.origin` — where the content came from. Used
12
+ * by D3 (`withRedaction`) under `scanScope: 'untrusted'` to
13
+ * decide whether to re-scan a part that already passed the D2
14
+ * sensitivity-tier filter.
15
+ * - `graphorin.content.inbound.trust` — what trust class the source
16
+ * carries. Used by D4 (`withInboundSanitization`) and by Phase 12
17
+ * (agent runtime) to gate the per-step preamble injection.
18
+ *
19
+ * Both annotations live as **span attributes only** (observability)
20
+ * — they are never serialized to the wire payload. The wire-stable
21
+ * `ProviderRequest` shape is unchanged by Phase 10d.
22
+ *
23
+ * @packageDocumentation
24
+ */
25
+ /**
26
+ * Span-attribute key for the origin axis.
27
+ *
28
+ * @stable
29
+ */
30
+ declare const CONTENT_ORIGIN_ATTR: "graphorin.content.origin";
31
+ /**
32
+ * Span-attribute key for the inbound-trust axis.
33
+ *
34
+ * @stable
35
+ */
36
+ declare const INBOUND_TRUST_ATTR: "graphorin.content.inbound.trust";
37
+ /**
38
+ * Origin discriminator for an assembled message-content part. The
39
+ * non-ContextEngine origins (`'user:input'`, `'tool:result'`,
40
+ * `'mcp:response'`, `'tool-call:args'`) are tagged by Phase 12
41
+ * (agent runtime) when the corresponding payload enters
42
+ * `session_messages`; the ContextEngine then propagates the tag
43
+ * through the assembled message list.
44
+ *
45
+ * @stable
46
+ */
47
+ type ContentOrigin = 'memory:tier-filtered' | 'system:framework' | 'agent:instructions' | 'skill:content' | 'user:input' | 'tool:result' | 'mcp:response' | 'tool-call:args';
48
+ /**
49
+ * Trust-class discriminator for an assembled message-content part.
50
+ * Sibling axis to {@link ContentOrigin}; the two are independent.
51
+ *
52
+ * - `'trusted'` — built-in framework tools + trusted-skill-bundled
53
+ * tools; D4 preamble does NOT fire on steps containing only
54
+ * these parts.
55
+ * - `'user-defined'` — tools registered via `tool({...})` from user
56
+ * application code; D4 preamble fires.
57
+ * - `'untrusted-skill'` — tools bundled by an untrusted skill; D4
58
+ * preamble fires; default policy is strip-and-wrap.
59
+ * - `'mcp'` — every `Tool` produced by `MCPClient.toTools(...)`; D4
60
+ * preamble fires; default policy is strip-and-wrap.
61
+ * - `'web-search'` — built-in `web_search` adapter; D4 preamble
62
+ * fires; default policy is strip-and-wrap.
63
+ * - `'n/a'` — non-tool-result parts for which the inbound-trust
64
+ * axis is meaningless (`'user:input'`, `'memory:tier-filtered'`,
65
+ * `'system:framework'`, `'agent:instructions'`,
66
+ * `'tool-call:args'`).
67
+ *
68
+ * @stable
69
+ */
70
+ type InboundTrust = 'trusted' | 'user-defined' | 'untrusted-skill' | 'mcp' | 'web-search' | 'n/a';
71
+ /**
72
+ * Origins for which the inbound-trust axis is meaningless and is
73
+ * always set to `'n/a'`. Surfaced as a frozen constant so consumers
74
+ * can introspect the contract without re-implementing the rule.
75
+ *
76
+ * @stable
77
+ */
78
+ declare const NON_INBOUND_ORIGINS: ReadonlySet<ContentOrigin>;
79
+ /**
80
+ * Single typed annotation for an assembled message-content part.
81
+ *
82
+ * @stable
83
+ */
84
+ interface ContentAnnotation {
85
+ readonly origin: ContentOrigin;
86
+ readonly inboundTrust: InboundTrust;
87
+ }
88
+ /**
89
+ * Build an annotation, enforcing the rule that
90
+ * non-tool-result origins always carry `inboundTrust: 'n/a'`. A
91
+ * caller that requests a non-`'n/a'` value for a non-inbound origin
92
+ * is silently corrected (defense-in-depth: the rule is enforced
93
+ * here so callers cannot accidentally violate it).
94
+ *
95
+ * @stable
96
+ */
97
+ declare function annotate(origin: ContentOrigin, inboundTrust: InboundTrust): ContentAnnotation;
98
+ /**
99
+ * Convert a {@link ContentAnnotation} to a span-attributes record
100
+ * suitable for `AISpan.setAttributes(...)`.
101
+ *
102
+ * @stable
103
+ */
104
+ declare function toSpanAttributes(annotation: ContentAnnotation): Readonly<Record<string, string>>;
105
+ /**
106
+ * Decide whether the per-step inbound-sanitization preamble (D4)
107
+ * should fire for an assembled message list. The preamble fires
108
+ * iff at least one part carries an inbound-trust value other than
109
+ * `'trusted'` and `'n/a'`. Trusted-only steps skip the preamble for
110
+ * cache-friendliness; preamble is emitted exactly once per step
111
+ * regardless of how many untrusted parts the step carries.
112
+ *
113
+ * @stable
114
+ */
115
+ declare function shouldFireInboundPreamble(annotations: ReadonlyArray<ContentAnnotation>): boolean;
116
+ //#endregion
117
+ export { CONTENT_ORIGIN_ATTR, ContentAnnotation, ContentOrigin, INBOUND_TRUST_ATTR, InboundTrust, NON_INBOUND_ORIGINS, annotate, shouldFireInboundPreamble, toSpanAttributes };
118
+ //# sourceMappingURL=annotations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotations.d.ts","names":[],"sources":["../../src/context-engine/annotations.ts"],"sourcesContent":[],"mappings":";;AA6BA;AAOA;AAYA;AAgCA;AAeA;AAeA;AAcA;;;;;AAaA;;;;;AAiBA;;;;;;;;;;;cA7Ha;;;;;;cAOA;;;;;;;;;;;KAYD,aAAA;;;;;;;;;;;;;;;;;;;;;;;KAgCA,YAAA;;;;;;;;cAeC,qBAAqB,YAAY;;;;;;UAe7B,iBAAA;mBACE;yBACM;;;;;;;;;;;iBAYT,QAAA,SAAiB,6BAA6B,eAAe;;;;;;;iBAa7D,gBAAA,aAA6B,oBAAoB,SAAS;;;;;;;;;;;iBAiB1D,yBAAA,cAAuC,cAAc"}
@@ -0,0 +1,102 @@
1
+ //#region src/context-engine/annotations.ts
2
+ /**
3
+ * Cooperation contract between the {@link ContextEngine} and the
4
+ * outbound prompt-redaction middleware (D3, see ADR-045 / DEC-157)
5
+ * + the inbound tool-result sanitization middleware (D4, see
6
+ * RB-43 / DEC-159).
7
+ *
8
+ * Every {@link MessageContent} part assembled by the ContextEngine
9
+ * carries two **independent** annotations:
10
+ *
11
+ * - `graphorin.content.origin` — where the content came from. Used
12
+ * by D3 (`withRedaction`) under `scanScope: 'untrusted'` to
13
+ * decide whether to re-scan a part that already passed the D2
14
+ * sensitivity-tier filter.
15
+ * - `graphorin.content.inbound.trust` — what trust class the source
16
+ * carries. Used by D4 (`withInboundSanitization`) and by Phase 12
17
+ * (agent runtime) to gate the per-step preamble injection.
18
+ *
19
+ * Both annotations live as **span attributes only** (observability)
20
+ * — they are never serialized to the wire payload. The wire-stable
21
+ * `ProviderRequest` shape is unchanged by Phase 10d.
22
+ *
23
+ * @packageDocumentation
24
+ */
25
+ /**
26
+ * Span-attribute key for the origin axis.
27
+ *
28
+ * @stable
29
+ */
30
+ const CONTENT_ORIGIN_ATTR = "graphorin.content.origin";
31
+ /**
32
+ * Span-attribute key for the inbound-trust axis.
33
+ *
34
+ * @stable
35
+ */
36
+ const INBOUND_TRUST_ATTR = "graphorin.content.inbound.trust";
37
+ /**
38
+ * Origins for which the inbound-trust axis is meaningless and is
39
+ * always set to `'n/a'`. Surfaced as a frozen constant so consumers
40
+ * can introspect the contract without re-implementing the rule.
41
+ *
42
+ * @stable
43
+ */
44
+ const NON_INBOUND_ORIGINS = Object.freeze(new Set([
45
+ "memory:tier-filtered",
46
+ "system:framework",
47
+ "agent:instructions",
48
+ "user:input",
49
+ "tool-call:args"
50
+ ]));
51
+ /**
52
+ * Build an annotation, enforcing the rule that
53
+ * non-tool-result origins always carry `inboundTrust: 'n/a'`. A
54
+ * caller that requests a non-`'n/a'` value for a non-inbound origin
55
+ * is silently corrected (defense-in-depth: the rule is enforced
56
+ * here so callers cannot accidentally violate it).
57
+ *
58
+ * @stable
59
+ */
60
+ function annotate(origin, inboundTrust) {
61
+ if (NON_INBOUND_ORIGINS.has(origin)) return Object.freeze({
62
+ origin,
63
+ inboundTrust: "n/a"
64
+ });
65
+ return Object.freeze({
66
+ origin,
67
+ inboundTrust
68
+ });
69
+ }
70
+ /**
71
+ * Convert a {@link ContentAnnotation} to a span-attributes record
72
+ * suitable for `AISpan.setAttributes(...)`.
73
+ *
74
+ * @stable
75
+ */
76
+ function toSpanAttributes(annotation) {
77
+ return Object.freeze({
78
+ [CONTENT_ORIGIN_ATTR]: annotation.origin,
79
+ [INBOUND_TRUST_ATTR]: annotation.inboundTrust
80
+ });
81
+ }
82
+ /**
83
+ * Decide whether the per-step inbound-sanitization preamble (D4)
84
+ * should fire for an assembled message list. The preamble fires
85
+ * iff at least one part carries an inbound-trust value other than
86
+ * `'trusted'` and `'n/a'`. Trusted-only steps skip the preamble for
87
+ * cache-friendliness; preamble is emitted exactly once per step
88
+ * regardless of how many untrusted parts the step carries.
89
+ *
90
+ * @stable
91
+ */
92
+ function shouldFireInboundPreamble(annotations) {
93
+ for (const annotation of annotations) {
94
+ const trust = annotation.inboundTrust;
95
+ if (trust !== "trusted" && trust !== "n/a") return true;
96
+ }
97
+ return false;
98
+ }
99
+
100
+ //#endregion
101
+ export { CONTENT_ORIGIN_ATTR, INBOUND_TRUST_ATTR, NON_INBOUND_ORIGINS, annotate, shouldFireInboundPreamble, toSpanAttributes };
102
+ //# sourceMappingURL=annotations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotations.js","names":["NON_INBOUND_ORIGINS: ReadonlySet<ContentOrigin>"],"sources":["../../src/context-engine/annotations.ts"],"sourcesContent":["/**\n * Cooperation contract between the {@link ContextEngine} and the\n * outbound prompt-redaction middleware (D3, see ADR-045 / DEC-157)\n * + the inbound tool-result sanitization middleware (D4, see\n * RB-43 / DEC-159).\n *\n * Every {@link MessageContent} part assembled by the ContextEngine\n * carries two **independent** annotations:\n *\n * - `graphorin.content.origin` — where the content came from. Used\n * by D3 (`withRedaction`) under `scanScope: 'untrusted'` to\n * decide whether to re-scan a part that already passed the D2\n * sensitivity-tier filter.\n * - `graphorin.content.inbound.trust` — what trust class the source\n * carries. Used by D4 (`withInboundSanitization`) and by Phase 12\n * (agent runtime) to gate the per-step preamble injection.\n *\n * Both annotations live as **span attributes only** (observability)\n * — they are never serialized to the wire payload. The wire-stable\n * `ProviderRequest` shape is unchanged by Phase 10d.\n *\n * @packageDocumentation\n */\n\n/**\n * Span-attribute key for the origin axis.\n *\n * @stable\n */\nexport const CONTENT_ORIGIN_ATTR = 'graphorin.content.origin' as const;\n\n/**\n * Span-attribute key for the inbound-trust axis.\n *\n * @stable\n */\nexport const INBOUND_TRUST_ATTR = 'graphorin.content.inbound.trust' as const;\n\n/**\n * Origin discriminator for an assembled message-content part. The\n * non-ContextEngine origins (`'user:input'`, `'tool:result'`,\n * `'mcp:response'`, `'tool-call:args'`) are tagged by Phase 12\n * (agent runtime) when the corresponding payload enters\n * `session_messages`; the ContextEngine then propagates the tag\n * through the assembled message list.\n *\n * @stable\n */\nexport type ContentOrigin =\n | 'memory:tier-filtered'\n | 'system:framework'\n | 'agent:instructions'\n | 'skill:content'\n | 'user:input'\n | 'tool:result'\n | 'mcp:response'\n | 'tool-call:args';\n\n/**\n * Trust-class discriminator for an assembled message-content part.\n * Sibling axis to {@link ContentOrigin}; the two are independent.\n *\n * - `'trusted'` — built-in framework tools + trusted-skill-bundled\n * tools; D4 preamble does NOT fire on steps containing only\n * these parts.\n * - `'user-defined'` — tools registered via `tool({...})` from user\n * application code; D4 preamble fires.\n * - `'untrusted-skill'` — tools bundled by an untrusted skill; D4\n * preamble fires; default policy is strip-and-wrap.\n * - `'mcp'` — every `Tool` produced by `MCPClient.toTools(...)`; D4\n * preamble fires; default policy is strip-and-wrap.\n * - `'web-search'` — built-in `web_search` adapter; D4 preamble\n * fires; default policy is strip-and-wrap.\n * - `'n/a'` — non-tool-result parts for which the inbound-trust\n * axis is meaningless (`'user:input'`, `'memory:tier-filtered'`,\n * `'system:framework'`, `'agent:instructions'`,\n * `'tool-call:args'`).\n *\n * @stable\n */\nexport type InboundTrust =\n | 'trusted'\n | 'user-defined'\n | 'untrusted-skill'\n | 'mcp'\n | 'web-search'\n | 'n/a';\n\n/**\n * Origins for which the inbound-trust axis is meaningless and is\n * always set to `'n/a'`. Surfaced as a frozen constant so consumers\n * can introspect the contract without re-implementing the rule.\n *\n * @stable\n */\nexport const NON_INBOUND_ORIGINS: ReadonlySet<ContentOrigin> = Object.freeze(\n new Set<ContentOrigin>([\n 'memory:tier-filtered',\n 'system:framework',\n 'agent:instructions',\n 'user:input',\n 'tool-call:args',\n ]),\n);\n\n/**\n * Single typed annotation for an assembled message-content part.\n *\n * @stable\n */\nexport interface ContentAnnotation {\n readonly origin: ContentOrigin;\n readonly inboundTrust: InboundTrust;\n}\n\n/**\n * Build an annotation, enforcing the rule that\n * non-tool-result origins always carry `inboundTrust: 'n/a'`. A\n * caller that requests a non-`'n/a'` value for a non-inbound origin\n * is silently corrected (defense-in-depth: the rule is enforced\n * here so callers cannot accidentally violate it).\n *\n * @stable\n */\nexport function annotate(origin: ContentOrigin, inboundTrust: InboundTrust): ContentAnnotation {\n if (NON_INBOUND_ORIGINS.has(origin)) {\n return Object.freeze({ origin, inboundTrust: 'n/a' });\n }\n return Object.freeze({ origin, inboundTrust });\n}\n\n/**\n * Convert a {@link ContentAnnotation} to a span-attributes record\n * suitable for `AISpan.setAttributes(...)`.\n *\n * @stable\n */\nexport function toSpanAttributes(annotation: ContentAnnotation): Readonly<Record<string, string>> {\n return Object.freeze({\n [CONTENT_ORIGIN_ATTR]: annotation.origin,\n [INBOUND_TRUST_ATTR]: annotation.inboundTrust,\n });\n}\n\n/**\n * Decide whether the per-step inbound-sanitization preamble (D4)\n * should fire for an assembled message list. The preamble fires\n * iff at least one part carries an inbound-trust value other than\n * `'trusted'` and `'n/a'`. Trusted-only steps skip the preamble for\n * cache-friendliness; preamble is emitted exactly once per step\n * regardless of how many untrusted parts the step carries.\n *\n * @stable\n */\nexport function shouldFireInboundPreamble(annotations: ReadonlyArray<ContentAnnotation>): boolean {\n for (const annotation of annotations) {\n const trust = annotation.inboundTrust;\n if (trust !== 'trusted' && trust !== 'n/a') return true;\n }\n return false;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAa,sBAAsB;;;;;;AAOnC,MAAa,qBAAqB;;;;;;;;AA2DlC,MAAaA,sBAAkD,OAAO,OACpE,IAAI,IAAmB;CACrB;CACA;CACA;CACA;CACA;CACD,CAAC,CACH;;;;;;;;;;AAqBD,SAAgB,SAAS,QAAuB,cAA+C;AAC7F,KAAI,oBAAoB,IAAI,OAAO,CACjC,QAAO,OAAO,OAAO;EAAE;EAAQ,cAAc;EAAO,CAAC;AAEvD,QAAO,OAAO,OAAO;EAAE;EAAQ;EAAc,CAAC;;;;;;;;AAShD,SAAgB,iBAAiB,YAAiE;AAChG,QAAO,OAAO,OAAO;GAClB,sBAAsB,WAAW;GACjC,qBAAqB,WAAW;EAClC,CAAC;;;;;;;;;;;;AAaJ,SAAgB,0BAA0B,aAAwD;AAChG,MAAK,MAAM,cAAc,aAAa;EACpC,MAAM,QAAQ,WAAW;AACzB,MAAI,UAAU,aAAa,UAAU,MAAO,QAAO;;AAErD,QAAO"}
@@ -0,0 +1,52 @@
1
+ import { ContextLocalePack } from "./locale-packs/types.js";
2
+
3
+ //#region src/context-engine/auto-recall.d.ts
4
+
5
+ /**
6
+ * Per-call scope passed to a custom strategy.
7
+ *
8
+ * @stable
9
+ */
10
+ interface AutoRecallStrategyContext {
11
+ readonly locale: string;
12
+ readonly lastUserMessage: string;
13
+ }
14
+ /**
15
+ * Outcome of a strategy invocation.
16
+ *
17
+ * @stable
18
+ */
19
+ interface AutoRecallTriggerResult {
20
+ readonly factsTriggered: boolean;
21
+ /** Optional reason surfaced in spans / metadata. */
22
+ readonly reason?: string;
23
+ }
24
+ /**
25
+ * Pluggable strategy signature.
26
+ *
27
+ * @stable
28
+ */
29
+ type AutoRecallStrategy = (ctx: AutoRecallStrategyContext) => AutoRecallTriggerResult;
30
+ /**
31
+ * Build a locale-driven heuristic strategy. The default for every
32
+ * configured locale.
33
+ *
34
+ * @stable
35
+ */
36
+ declare function defaultLocaleHeuristicStrategy(pack: ContextLocalePack): AutoRecallStrategy;
37
+ /**
38
+ * Builder for application-supplied custom strategies. Accepts a
39
+ * raw function and returns a tagged version so the engine can
40
+ * surface the strategy name on spans.
41
+ *
42
+ * @stable
43
+ */
44
+ declare function defineAutoRecallStrategy(opts: {
45
+ readonly id: string;
46
+ readonly evaluate: AutoRecallStrategy;
47
+ }): AutoRecallStrategy & {
48
+ readonly id: string;
49
+ };
50
+ //#endregion
51
+ export { AutoRecallStrategy, AutoRecallStrategyContext, AutoRecallTriggerResult, defaultLocaleHeuristicStrategy, defineAutoRecallStrategy };
52
+ //# sourceMappingURL=auto-recall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-recall.d.ts","names":[],"sources":["../../src/context-engine/auto-recall.ts"],"sourcesContent":[],"mappings":";;;;;;;;;UAqBiB,yBAAA;;;;;;;;;UAUA,uBAAA;;;;;;;;;;KAWL,kBAAA,SAA2B,8BAA8B;;;;;;;iBAQrD,8BAAA,OAAqC,oBAAoB;;;;;;;;iBAsBzD,wBAAA;;qBAEK;IACjB"}
@@ -0,0 +1,41 @@
1
+ //#region src/context-engine/auto-recall.ts
2
+ /**
3
+ * Build a locale-driven heuristic strategy. The default for every
4
+ * configured locale.
5
+ *
6
+ * @stable
7
+ */
8
+ function defaultLocaleHeuristicStrategy(pack) {
9
+ const factTriggers = pack.autoRecallTriggers.factTriggers;
10
+ return (ctx) => {
11
+ const text = ctx.lastUserMessage ?? "";
12
+ if (text.length === 0) return { factsTriggered: false };
13
+ const factsTriggered = factTriggers.some((re) => re.test(text));
14
+ if (factsTriggered) return {
15
+ factsTriggered,
16
+ reason: "locale-heuristic-trigger-matched"
17
+ };
18
+ return { factsTriggered: false };
19
+ };
20
+ }
21
+ /**
22
+ * Builder for application-supplied custom strategies. Accepts a
23
+ * raw function and returns a tagged version so the engine can
24
+ * surface the strategy name on spans.
25
+ *
26
+ * @stable
27
+ */
28
+ function defineAutoRecallStrategy(opts) {
29
+ if (typeof opts.id !== "string" || opts.id.length === 0) throw new TypeError("[graphorin/memory] defineAutoRecallStrategy: `id` must be a non-empty string.");
30
+ if (typeof opts.evaluate !== "function") throw new TypeError("[graphorin/memory] defineAutoRecallStrategy: `evaluate` must be a function.");
31
+ const wrapped = ((ctx) => opts.evaluate(ctx));
32
+ Object.defineProperty(wrapped, "id", {
33
+ value: opts.id,
34
+ enumerable: true
35
+ });
36
+ return wrapped;
37
+ }
38
+
39
+ //#endregion
40
+ export { defaultLocaleHeuristicStrategy, defineAutoRecallStrategy };
41
+ //# sourceMappingURL=auto-recall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-recall.js","names":[],"sources":["../../src/context-engine/auto-recall.ts"],"sourcesContent":["/**\n * Auto-recall heuristic — opt-in regex-based pre-call that injects\n * the top-K facts into Layer 6 when the last user message matches one\n * of the configured trigger phrases. (Episode auto-recall is not\n * implemented; episodes are reachable via the `recall_episodes` tool.)\n *\n * The framework ships English defaults; per-locale trigger\n * phrases extend the default via {@link defineContextLocalePack}.\n * Application code can also register a fully-custom strategy via\n * {@link defineAutoRecallStrategy}.\n *\n * @packageDocumentation\n */\n\nimport type { ContextLocalePack } from './locale-packs/index.js';\n\n/**\n * Per-call scope passed to a custom strategy.\n *\n * @stable\n */\nexport interface AutoRecallStrategyContext {\n readonly locale: string;\n readonly lastUserMessage: string;\n}\n\n/**\n * Outcome of a strategy invocation.\n *\n * @stable\n */\nexport interface AutoRecallTriggerResult {\n readonly factsTriggered: boolean;\n /** Optional reason surfaced in spans / metadata. */\n readonly reason?: string;\n}\n\n/**\n * Pluggable strategy signature.\n *\n * @stable\n */\nexport type AutoRecallStrategy = (ctx: AutoRecallStrategyContext) => AutoRecallTriggerResult;\n\n/**\n * Build a locale-driven heuristic strategy. The default for every\n * configured locale.\n *\n * @stable\n */\nexport function defaultLocaleHeuristicStrategy(pack: ContextLocalePack): AutoRecallStrategy {\n const factTriggers = pack.autoRecallTriggers.factTriggers;\n return (ctx) => {\n const text = ctx.lastUserMessage ?? '';\n if (text.length === 0) {\n return { factsTriggered: false };\n }\n const factsTriggered = factTriggers.some((re) => re.test(text));\n if (factsTriggered) {\n return { factsTriggered, reason: 'locale-heuristic-trigger-matched' };\n }\n return { factsTriggered: false };\n };\n}\n\n/**\n * Builder for application-supplied custom strategies. Accepts a\n * raw function and returns a tagged version so the engine can\n * surface the strategy name on spans.\n *\n * @stable\n */\nexport function defineAutoRecallStrategy(opts: {\n readonly id: string;\n readonly evaluate: AutoRecallStrategy;\n}): AutoRecallStrategy & { readonly id: string } {\n if (typeof opts.id !== 'string' || opts.id.length === 0) {\n throw new TypeError(\n '[graphorin/memory] defineAutoRecallStrategy: `id` must be a non-empty string.',\n );\n }\n if (typeof opts.evaluate !== 'function') {\n throw new TypeError(\n '[graphorin/memory] defineAutoRecallStrategy: `evaluate` must be a function.',\n );\n }\n const wrapped = ((ctx: AutoRecallStrategyContext) => opts.evaluate(ctx)) as AutoRecallStrategy & {\n readonly id: string;\n };\n Object.defineProperty(wrapped, 'id', { value: opts.id, enumerable: true });\n return wrapped;\n}\n"],"mappings":";;;;;;;AAkDA,SAAgB,+BAA+B,MAA6C;CAC1F,MAAM,eAAe,KAAK,mBAAmB;AAC7C,SAAQ,QAAQ;EACd,MAAM,OAAO,IAAI,mBAAmB;AACpC,MAAI,KAAK,WAAW,EAClB,QAAO,EAAE,gBAAgB,OAAO;EAElC,MAAM,iBAAiB,aAAa,MAAM,OAAO,GAAG,KAAK,KAAK,CAAC;AAC/D,MAAI,eACF,QAAO;GAAE;GAAgB,QAAQ;GAAoC;AAEvE,SAAO,EAAE,gBAAgB,OAAO;;;;;;;;;;AAWpC,SAAgB,yBAAyB,MAGQ;AAC/C,KAAI,OAAO,KAAK,OAAO,YAAY,KAAK,GAAG,WAAW,EACpD,OAAM,IAAI,UACR,gFACD;AAEH,KAAI,OAAO,KAAK,aAAa,WAC3B,OAAM,IAAI,UACR,8EACD;CAEH,MAAM,YAAY,QAAmC,KAAK,SAAS,IAAI;AAGvE,QAAO,eAAe,SAAS,MAAM;EAAE,OAAO,KAAK;EAAI,YAAY;EAAM,CAAC;AAC1E,QAAO"}
@@ -0,0 +1,55 @@
1
+ import { ContextTokenCounter } from "../token-counter.js";
2
+ import { Message } from "@graphorin/core";
3
+
4
+ //#region src/context-engine/compaction/clear-tool-results.d.ts
5
+
6
+ /** Placeholder prefix on a cleared tool result — makes clearing idempotent. */
7
+ declare const CLEARED_TOOL_RESULT_MARKER = "[cleared tool result";
8
+ /** Knobs for {@link clearOldToolResults} (mirrors the strategy variant). */
9
+ interface ClearToolResultsOptions {
10
+ /** Most-recent tool results kept verbatim (default {@link DEFAULT_KEEP_TOOL_USES}). */
11
+ readonly keepToolUses?: number;
12
+ /** Only clear if at least this many tokens are reclaimable; else leave untouched (default 0). */
13
+ readonly clearAtLeast?: number;
14
+ /** Tool names whose results are never cleared. */
15
+ readonly excludeTools?: ReadonlyArray<string>;
16
+ /** Placeholder builder; defaults to a one-line `[cleared tool result …]` marker. */
17
+ readonly placeholder?: (info: {
18
+ readonly toolCallId: string;
19
+ readonly toolName?: string;
20
+ readonly clearedTokens: number;
21
+ }) => string;
22
+ /**
23
+ * A6 / SOTA-2 — recoverable clearing. When provided, the original tool-result
24
+ * text of each cleared message is handed to this callback (wire it to a spill
25
+ * store / the `read_result` handle registry) and the placeholder references the
26
+ * returned handle id + preview, so the model can re-fetch the full result via
27
+ * `read_result` rather than losing it. Invoked only for clears that actually
28
+ * commit (after the `clearAtLeast` floor), so a rejected clearing never spills.
29
+ * Omitted ⇒ the bare `placeholder` (irrecoverable, byte-identical default).
30
+ */
31
+ readonly externalize?: (content: string, info: {
32
+ readonly toolCallId: string;
33
+ readonly toolName?: string;
34
+ readonly clearedTokens: number;
35
+ }) => Promise<{
36
+ readonly handleId: string;
37
+ readonly preview?: string;
38
+ }>;
39
+ }
40
+ /** Result of a clearing pass. `clearedIndices` empty ⇒ nothing changed. */
41
+ interface ClearToolResultsOutcome {
42
+ readonly messages: ReadonlyArray<Message>;
43
+ readonly clearedIndices: ReadonlyArray<number>;
44
+ readonly reclaimedTokens: number;
45
+ }
46
+ /**
47
+ * Replace the oldest clearable tool results with placeholders. Returns the new
48
+ * buffer (same length — content is replaced in place, never removed) plus the
49
+ * cleared indices and reclaimed token count. Idempotent: already-cleared
50
+ * placeholders are skipped on a second pass.
51
+ */
52
+ declare function clearOldToolResults(messages: ReadonlyArray<Message>, options: ClearToolResultsOptions, counter: ContextTokenCounter): Promise<ClearToolResultsOutcome>;
53
+ //#endregion
54
+ export { CLEARED_TOOL_RESULT_MARKER, ClearToolResultsOptions, ClearToolResultsOutcome, clearOldToolResults };
55
+ //# sourceMappingURL=clear-tool-results.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clear-tool-results.d.ts","names":[],"sources":["../../../src/context-engine/compaction/clear-tool-results.ts"],"sourcesContent":[],"mappings":";;;;;;AA8FW,cAzEE,0BAAA,GAyEF,sBAAA;;UAnEM,uBAAA;;;;;;0BAMS;;;;;;;;;;;;;;;;;;;;QAuBnB;;;;;;UAIU,uBAAA;qBACI,cAAc;2BACR;;;;;;;;;iBA6BL,mBAAA,WACV,cAAc,mBACf,kCACA,sBACR,QAAQ"}
@@ -0,0 +1,97 @@
1
+ import { countMessageTokens, renderMessageText } from "../token-counter.js";
2
+
3
+ //#region src/context-engine/compaction/clear-tool-results.ts
4
+ /** Placeholder prefix on a cleared tool result — makes clearing idempotent. */
5
+ const CLEARED_TOOL_RESULT_MARKER = "[cleared tool result";
6
+ /** Default count of most-recent tool results kept verbatim. */
7
+ const DEFAULT_KEEP_TOOL_USES = 3;
8
+ function defaultPlaceholder(info) {
9
+ return `${CLEARED_TOOL_RESULT_MARKER} · ${info.toolName ?? "tool"} · ${info.clearedTokens} tokens elided · re-run the tool if needed]`;
10
+ }
11
+ /** A6: a placeholder that points at the externalized handle (recoverable via read_result). */
12
+ function handlePlaceholder(info) {
13
+ const preview = info.preview !== void 0 && info.preview.length > 0 ? ` · ${info.preview}` : "";
14
+ return `${CLEARED_TOOL_RESULT_MARKER} · ${info.toolName ?? "tool"} · ${info.clearedTokens} tokens · full result via read_result handle: ${info.handleId}${preview}]`;
15
+ }
16
+ function isAlreadyCleared(content) {
17
+ return typeof content === "string" && content.startsWith(CLEARED_TOOL_RESULT_MARKER);
18
+ }
19
+ /**
20
+ * Replace the oldest clearable tool results with placeholders. Returns the new
21
+ * buffer (same length — content is replaced in place, never removed) plus the
22
+ * cleared indices and reclaimed token count. Idempotent: already-cleared
23
+ * placeholders are skipped on a second pass.
24
+ */
25
+ async function clearOldToolResults(messages, options, counter) {
26
+ const keep = options.keepToolUses ?? DEFAULT_KEEP_TOOL_USES;
27
+ const exclude = new Set(options.excludeTools ?? []);
28
+ const placeholder = options.placeholder ?? defaultPlaceholder;
29
+ const toolNameById = /* @__PURE__ */ new Map();
30
+ for (const m of messages) if (m.role === "assistant" && m.toolCalls) for (const tc of m.toolCalls) toolNameById.set(tc.toolCallId, tc.toolName);
31
+ const toolIdx = [];
32
+ for (let i = 0; i < messages.length; i++) {
33
+ const m = messages[i];
34
+ if (m?.role === "tool" && !isAlreadyCleared(m.content)) toolIdx.push(i);
35
+ }
36
+ const keptCutoff = toolIdx.length - Math.max(0, keep);
37
+ const replacements = /* @__PURE__ */ new Map();
38
+ const clearedTokensByIdx = /* @__PURE__ */ new Map();
39
+ let reclaimable = 0;
40
+ for (let j = 0; j < toolIdx.length && j < keptCutoff; j++) {
41
+ const idx = toolIdx[j];
42
+ if (idx === void 0) continue;
43
+ const tm = messages[idx];
44
+ const name = toolNameById.get(tm.toolCallId);
45
+ if (name !== void 0 && exclude.has(name)) continue;
46
+ const originalTokens = await countMessageTokens([tm], counter);
47
+ const replaced = {
48
+ role: "tool",
49
+ toolCallId: tm.toolCallId,
50
+ content: placeholder({
51
+ toolCallId: tm.toolCallId,
52
+ ...name !== void 0 ? { toolName: name } : {},
53
+ clearedTokens: originalTokens
54
+ })
55
+ };
56
+ const placeholderTokens = await countMessageTokens([replaced], counter);
57
+ reclaimable += Math.max(0, originalTokens - placeholderTokens);
58
+ replacements.set(idx, replaced);
59
+ clearedTokensByIdx.set(idx, originalTokens);
60
+ }
61
+ const clearAtLeast = options.clearAtLeast ?? 0;
62
+ if (replacements.size === 0 || reclaimable < clearAtLeast) return {
63
+ messages,
64
+ clearedIndices: [],
65
+ reclaimedTokens: 0
66
+ };
67
+ const externalize = options.externalize;
68
+ if (externalize !== void 0) for (const idx of replacements.keys()) {
69
+ const tm = messages[idx];
70
+ const name = toolNameById.get(tm.toolCallId);
71
+ const clearedTokens = clearedTokensByIdx.get(idx) ?? 0;
72
+ const handle = await externalize(typeof tm.content === "string" ? tm.content : renderMessageText(tm), {
73
+ toolCallId: tm.toolCallId,
74
+ ...name !== void 0 ? { toolName: name } : {},
75
+ clearedTokens
76
+ });
77
+ replacements.set(idx, {
78
+ role: "tool",
79
+ toolCallId: tm.toolCallId,
80
+ content: handlePlaceholder({
81
+ ...name !== void 0 ? { toolName: name } : {},
82
+ clearedTokens,
83
+ handleId: handle.handleId,
84
+ ...handle.preview !== void 0 ? { preview: handle.preview } : {}
85
+ })
86
+ });
87
+ }
88
+ return {
89
+ messages: messages.map((m, i) => replacements.get(i) ?? m),
90
+ clearedIndices: [...replacements.keys()],
91
+ reclaimedTokens: reclaimable
92
+ };
93
+ }
94
+
95
+ //#endregion
96
+ export { CLEARED_TOOL_RESULT_MARKER, DEFAULT_KEEP_TOOL_USES, clearOldToolResults };
97
+ //# sourceMappingURL=clear-tool-results.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clear-tool-results.js","names":["toolIdx: number[]","replaced: ToolMessage"],"sources":["../../../src/context-engine/compaction/clear-tool-results.ts"],"sourcesContent":["/**\n * SOTA-1: zero-LLM tool-result clearing — the cheapest pre-compaction tier.\n *\n * Mirrors Anthropic context editing (`clear_tool_uses_20250919`): when the\n * buffer crosses the compaction threshold, replace the oldest tool results with\n * a compact placeholder BEFORE paying for a summarizer LLM call. The most recent\n * `keepToolUses` results stay verbatim, `excludeTools` are never touched, and\n * clearing is skipped entirely when it would reclaim fewer than `clearAtLeast`\n * tokens (not worth the context churn). Pure + deterministic — no provider call.\n *\n * @packageDocumentation\n */\n\nimport type { Message, ToolMessage } from '@graphorin/core';\nimport {\n type ContextTokenCounter,\n countMessageTokens,\n renderMessageText,\n} from '../token-counter.js';\n\n/** Placeholder prefix on a cleared tool result — makes clearing idempotent. */\nexport const CLEARED_TOOL_RESULT_MARKER = '[cleared tool result';\n\n/** Default count of most-recent tool results kept verbatim. */\nexport const DEFAULT_KEEP_TOOL_USES = 3;\n\n/** Knobs for {@link clearOldToolResults} (mirrors the strategy variant). */\nexport interface ClearToolResultsOptions {\n /** Most-recent tool results kept verbatim (default {@link DEFAULT_KEEP_TOOL_USES}). */\n readonly keepToolUses?: number;\n /** Only clear if at least this many tokens are reclaimable; else leave untouched (default 0). */\n readonly clearAtLeast?: number;\n /** Tool names whose results are never cleared. */\n readonly excludeTools?: ReadonlyArray<string>;\n /** Placeholder builder; defaults to a one-line `[cleared tool result …]` marker. */\n readonly placeholder?: (info: {\n readonly toolCallId: string;\n readonly toolName?: string;\n readonly clearedTokens: number;\n }) => string;\n /**\n * A6 / SOTA-2 — recoverable clearing. When provided, the original tool-result\n * text of each cleared message is handed to this callback (wire it to a spill\n * store / the `read_result` handle registry) and the placeholder references the\n * returned handle id + preview, so the model can re-fetch the full result via\n * `read_result` rather than losing it. Invoked only for clears that actually\n * commit (after the `clearAtLeast` floor), so a rejected clearing never spills.\n * Omitted ⇒ the bare `placeholder` (irrecoverable, byte-identical default).\n */\n readonly externalize?: (\n content: string,\n info: {\n readonly toolCallId: string;\n readonly toolName?: string;\n readonly clearedTokens: number;\n },\n ) => Promise<{ readonly handleId: string; readonly preview?: string }>;\n}\n\n/** Result of a clearing pass. `clearedIndices` empty ⇒ nothing changed. */\nexport interface ClearToolResultsOutcome {\n readonly messages: ReadonlyArray<Message>;\n readonly clearedIndices: ReadonlyArray<number>;\n readonly reclaimedTokens: number;\n}\n\nfunction defaultPlaceholder(info: { toolName?: string; clearedTokens: number }): string {\n return `${CLEARED_TOOL_RESULT_MARKER} · ${info.toolName ?? 'tool'} · ${info.clearedTokens} tokens elided · re-run the tool if needed]`;\n}\n\n/** A6: a placeholder that points at the externalized handle (recoverable via read_result). */\nfunction handlePlaceholder(info: {\n toolName?: string;\n clearedTokens: number;\n handleId: string;\n preview?: string;\n}): string {\n const preview = info.preview !== undefined && info.preview.length > 0 ? ` · ${info.preview}` : '';\n return `${CLEARED_TOOL_RESULT_MARKER} · ${info.toolName ?? 'tool'} · ${info.clearedTokens} tokens · full result via read_result handle: ${info.handleId}${preview}]`;\n}\n\nfunction isAlreadyCleared(content: Message['content']): boolean {\n return typeof content === 'string' && content.startsWith(CLEARED_TOOL_RESULT_MARKER);\n}\n\n/**\n * Replace the oldest clearable tool results with placeholders. Returns the new\n * buffer (same length — content is replaced in place, never removed) plus the\n * cleared indices and reclaimed token count. Idempotent: already-cleared\n * placeholders are skipped on a second pass.\n */\nexport async function clearOldToolResults(\n messages: ReadonlyArray<Message>,\n options: ClearToolResultsOptions,\n counter: ContextTokenCounter,\n): Promise<ClearToolResultsOutcome> {\n const keep = options.keepToolUses ?? DEFAULT_KEEP_TOOL_USES;\n const exclude = new Set(options.excludeTools ?? []);\n const placeholder = options.placeholder ?? defaultPlaceholder;\n\n // toolCallId → toolName from every assistant tool-call in the buffer.\n const toolNameById = new Map<string, string>();\n for (const m of messages) {\n if (m.role === 'assistant' && m.toolCalls) {\n for (const tc of m.toolCalls) toolNameById.set(tc.toolCallId, tc.toolName);\n }\n }\n\n // Indices of all not-yet-cleared tool-result messages, oldest first.\n const toolIdx: number[] = [];\n for (let i = 0; i < messages.length; i++) {\n const m = messages[i];\n if (m?.role === 'tool' && !isAlreadyCleared(m.content)) toolIdx.push(i);\n }\n\n // Keep the most-recent `keep`; older ones are candidates unless excluded.\n const keptCutoff = toolIdx.length - Math.max(0, keep);\n const replacements = new Map<number, ToolMessage>();\n const clearedTokensByIdx = new Map<number, number>();\n let reclaimable = 0;\n for (let j = 0; j < toolIdx.length && j < keptCutoff; j++) {\n const idx = toolIdx[j];\n if (idx === undefined) continue;\n const tm = messages[idx] as ToolMessage;\n const name = toolNameById.get(tm.toolCallId);\n if (name !== undefined && exclude.has(name)) continue;\n const originalTokens = await countMessageTokens([tm], counter);\n const replaced: ToolMessage = {\n role: 'tool',\n toolCallId: tm.toolCallId,\n content: placeholder({\n toolCallId: tm.toolCallId,\n ...(name !== undefined ? { toolName: name } : {}),\n clearedTokens: originalTokens,\n }),\n };\n const placeholderTokens = await countMessageTokens([replaced], counter);\n reclaimable += Math.max(0, originalTokens - placeholderTokens);\n replacements.set(idx, replaced);\n clearedTokensByIdx.set(idx, originalTokens);\n }\n\n const clearAtLeast = options.clearAtLeast ?? 0;\n if (replacements.size === 0 || reclaimable < clearAtLeast) {\n return { messages, clearedIndices: [], reclaimedTokens: 0 };\n }\n\n // A6: only now that the clearing commits, externalize each cleared result to a\n // recoverable handle and rewrite its placeholder to reference it. Skipped\n // clears (above) never reach here, so the spill never fires for nothing.\n const externalize = options.externalize;\n if (externalize !== undefined) {\n for (const idx of replacements.keys()) {\n const tm = messages[idx] as ToolMessage;\n const name = toolNameById.get(tm.toolCallId);\n const clearedTokens = clearedTokensByIdx.get(idx) ?? 0;\n const content = typeof tm.content === 'string' ? tm.content : renderMessageText(tm);\n const handle = await externalize(content, {\n toolCallId: tm.toolCallId,\n ...(name !== undefined ? { toolName: name } : {}),\n clearedTokens,\n });\n replacements.set(idx, {\n role: 'tool',\n toolCallId: tm.toolCallId,\n content: handlePlaceholder({\n ...(name !== undefined ? { toolName: name } : {}),\n clearedTokens,\n handleId: handle.handleId,\n ...(handle.preview !== undefined ? { preview: handle.preview } : {}),\n }),\n });\n }\n }\n\n const out = messages.map((m, i) => replacements.get(i) ?? m);\n return {\n messages: out,\n clearedIndices: [...replacements.keys()],\n reclaimedTokens: reclaimable,\n };\n}\n"],"mappings":";;;;AAqBA,MAAa,6BAA6B;;AAG1C,MAAa,yBAAyB;AA0CtC,SAAS,mBAAmB,MAA4D;AACtF,QAAO,GAAG,2BAA2B,KAAK,KAAK,YAAY,OAAO,KAAK,KAAK,cAAc;;;AAI5F,SAAS,kBAAkB,MAKhB;CACT,MAAM,UAAU,KAAK,YAAY,UAAa,KAAK,QAAQ,SAAS,IAAI,MAAM,KAAK,YAAY;AAC/F,QAAO,GAAG,2BAA2B,KAAK,KAAK,YAAY,OAAO,KAAK,KAAK,cAAc,gDAAgD,KAAK,WAAW,QAAQ;;AAGpK,SAAS,iBAAiB,SAAsC;AAC9D,QAAO,OAAO,YAAY,YAAY,QAAQ,WAAW,2BAA2B;;;;;;;;AAStF,eAAsB,oBACpB,UACA,SACA,SACkC;CAClC,MAAM,OAAO,QAAQ,gBAAgB;CACrC,MAAM,UAAU,IAAI,IAAI,QAAQ,gBAAgB,EAAE,CAAC;CACnD,MAAM,cAAc,QAAQ,eAAe;CAG3C,MAAM,+BAAe,IAAI,KAAqB;AAC9C,MAAK,MAAM,KAAK,SACd,KAAI,EAAE,SAAS,eAAe,EAAE,UAC9B,MAAK,MAAM,MAAM,EAAE,UAAW,cAAa,IAAI,GAAG,YAAY,GAAG,SAAS;CAK9E,MAAMA,UAAoB,EAAE;AAC5B,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;EACxC,MAAM,IAAI,SAAS;AACnB,MAAI,GAAG,SAAS,UAAU,CAAC,iBAAiB,EAAE,QAAQ,CAAE,SAAQ,KAAK,EAAE;;CAIzE,MAAM,aAAa,QAAQ,SAAS,KAAK,IAAI,GAAG,KAAK;CACrD,MAAM,+BAAe,IAAI,KAA0B;CACnD,MAAM,qCAAqB,IAAI,KAAqB;CACpD,IAAI,cAAc;AAClB,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,UAAU,IAAI,YAAY,KAAK;EACzD,MAAM,MAAM,QAAQ;AACpB,MAAI,QAAQ,OAAW;EACvB,MAAM,KAAK,SAAS;EACpB,MAAM,OAAO,aAAa,IAAI,GAAG,WAAW;AAC5C,MAAI,SAAS,UAAa,QAAQ,IAAI,KAAK,CAAE;EAC7C,MAAM,iBAAiB,MAAM,mBAAmB,CAAC,GAAG,EAAE,QAAQ;EAC9D,MAAMC,WAAwB;GAC5B,MAAM;GACN,YAAY,GAAG;GACf,SAAS,YAAY;IACnB,YAAY,GAAG;IACf,GAAI,SAAS,SAAY,EAAE,UAAU,MAAM,GAAG,EAAE;IAChD,eAAe;IAChB,CAAC;GACH;EACD,MAAM,oBAAoB,MAAM,mBAAmB,CAAC,SAAS,EAAE,QAAQ;AACvE,iBAAe,KAAK,IAAI,GAAG,iBAAiB,kBAAkB;AAC9D,eAAa,IAAI,KAAK,SAAS;AAC/B,qBAAmB,IAAI,KAAK,eAAe;;CAG7C,MAAM,eAAe,QAAQ,gBAAgB;AAC7C,KAAI,aAAa,SAAS,KAAK,cAAc,aAC3C,QAAO;EAAE;EAAU,gBAAgB,EAAE;EAAE,iBAAiB;EAAG;CAM7D,MAAM,cAAc,QAAQ;AAC5B,KAAI,gBAAgB,OAClB,MAAK,MAAM,OAAO,aAAa,MAAM,EAAE;EACrC,MAAM,KAAK,SAAS;EACpB,MAAM,OAAO,aAAa,IAAI,GAAG,WAAW;EAC5C,MAAM,gBAAgB,mBAAmB,IAAI,IAAI,IAAI;EAErD,MAAM,SAAS,MAAM,YADL,OAAO,GAAG,YAAY,WAAW,GAAG,UAAU,kBAAkB,GAAG,EACzC;GACxC,YAAY,GAAG;GACf,GAAI,SAAS,SAAY,EAAE,UAAU,MAAM,GAAG,EAAE;GAChD;GACD,CAAC;AACF,eAAa,IAAI,KAAK;GACpB,MAAM;GACN,YAAY,GAAG;GACf,SAAS,kBAAkB;IACzB,GAAI,SAAS,SAAY,EAAE,UAAU,MAAM,GAAG,EAAE;IAChD;IACA,UAAU,OAAO;IACjB,GAAI,OAAO,YAAY,SAAY,EAAE,SAAS,OAAO,SAAS,GAAG,EAAE;IACpE,CAAC;GACH,CAAC;;AAKN,QAAO;EACL,UAFU,SAAS,KAAK,GAAG,MAAM,aAAa,IAAI,EAAE,IAAI,EAAE;EAG1D,gBAAgB,CAAC,GAAG,aAAa,MAAM,CAAC;EACxC,iBAAiB;EAClB"}
@@ -0,0 +1,52 @@
1
+ import { ContextLocalePack } from "../locale-packs/types.js";
2
+ import { ContextTokenCounter } from "../token-counter.js";
3
+ import { CompactionResult, CompactionSource, CompactionStrategy, CompactionSummarizer } from "./types.js";
4
+ import * as _graphorin_core2 from "@graphorin/core";
5
+ import { Message } from "@graphorin/core";
6
+
7
+ //#region src/context-engine/compaction/compactor.d.ts
8
+
9
+ /**
10
+ * Default count of recent turns preserved verbatim by the
11
+ * `summarize-old-preserve-recent` strategy.
12
+ *
13
+ * @stable
14
+ */
15
+ declare const DEFAULT_PRESERVE_RECENT_TURNS = 6;
16
+ /**
17
+ * Trim the in-flight buffer using the
18
+ * `summarize-old-preserve-recent` strategy. Returns the trimmed
19
+ * messages + summary metadata; the caller is responsible for
20
+ * appending the summary to the message buffer (Phase 12 owns the
21
+ * lifecycle; this module exposes the primitive).
22
+ *
23
+ * @stable
24
+ */
25
+ interface ExecuteCompactionInput {
26
+ readonly messages: ReadonlyArray<Message>;
27
+ readonly source: CompactionSource;
28
+ readonly strategy: CompactionStrategy;
29
+ readonly localePack: ContextLocalePack;
30
+ readonly summarizer: CompactionSummarizer;
31
+ readonly tokenCounter?: ContextTokenCounter;
32
+ readonly thresholdTokens: number;
33
+ readonly runId: string;
34
+ readonly sessionId: string;
35
+ readonly agentId: string;
36
+ readonly scope: _graphorin_core2.SessionScope;
37
+ readonly providerTrust?: _graphorin_core2.LocalProviderTrust;
38
+ readonly now?: () => number;
39
+ readonly signal?: AbortSignal;
40
+ }
41
+ /**
42
+ * Perform a compaction call. Returns the result envelope containing
43
+ * the produced summary, the dropped/preserved message slices, and
44
+ * the per-event metadata. Phase 12 / `agent.compact()` is the
45
+ * lifecycle owner; this function is the trim primitive.
46
+ *
47
+ * @stable
48
+ */
49
+ declare function executeCompaction(input: ExecuteCompactionInput): Promise<CompactionResult>;
50
+ //#endregion
51
+ export { DEFAULT_PRESERVE_RECENT_TURNS, ExecuteCompactionInput, executeCompaction };
52
+ //# sourceMappingURL=compactor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compactor.d.ts","names":[],"sources":["../../../src/context-engine/compaction/compactor.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;cAiDa,6BAAA;;;;;;;;;;UA0CI,sBAAA;qBACI,cAAc;mBAChB;qBACE;uBACE;uBACA;0BACG;;;;;kBAAmB,gBAAA,CAKD;2BAAY,gBAAA,CACH;;oBAEjC;;;;;;;;;;iBAWE,iBAAA,QAAyB,yBAAyB,QAAQ"}