@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,258 @@
1
+ import { ContentAnnotation } from "./annotations.js";
2
+ import { ContextLocalePack, PartialContextLocalePack } from "./locale-packs/types.js";
3
+ import { AutoRecallStrategy, AutoRecallTriggerResult } from "./auto-recall.js";
4
+ import { ContextTokenCounter } from "./token-counter.js";
5
+ import { CompactionConfig, CompactionResult, CompactionSource, CompactionSummarizer } from "./compaction/types.js";
6
+ import { PrivacyDecisionReason } from "./privacy-filter.js";
7
+ import { MemoryBaseMode, SkillMetadataCard } from "./templates/composer.js";
8
+ import { AllocationResult } from "./token-budget.js";
9
+ import { Memory } from "../facade.js";
10
+ import { LocalProviderTrust, Message, MessageContent, Sensitivity, SessionScope, TokenCounter } from "@graphorin/core";
11
+
12
+ //#region src/context-engine/engine.d.ts
13
+
14
+ /**
15
+ * Per-layer cap configuration. Mirrors the documented
16
+ * `ContextEngineConfig.layers.*` fields.
17
+ *
18
+ * @stable
19
+ */
20
+ interface LayerConfig {
21
+ readonly enabled?: boolean;
22
+ readonly cap?: number;
23
+ }
24
+ /**
25
+ * Auto-recall config knob. `false` disables; `{ topK }` enables
26
+ * the heuristic with a bounded top-K.
27
+ *
28
+ * @stable
29
+ */
30
+ type AutoRecallConfig = false | {
31
+ readonly topK?: number;
32
+ /**
33
+ * Minimum fused score a hit must reach to be injected. **Default `0`**
34
+ * (CE-4) — `topK` already bounds the volume. The scale is
35
+ * reranker-dependent: the default RRF reranker fuses the FTS + vector
36
+ * candidate lists as `1/(60 + rank)` per list, so scores top out near
37
+ * `2/(60 + 1) ≈ 0.033` — any positive default would silently drop every
38
+ * hit. Set this only when calibrating against a known reranker's scale.
39
+ */
40
+ readonly threshold?: number;
41
+ readonly strategy?: AutoRecallStrategy;
42
+ };
43
+ /**
44
+ * Privacy block of the engine config.
45
+ *
46
+ * @stable
47
+ */
48
+ interface PrivacyConfig {
49
+ readonly cloudUploadConsent?: boolean;
50
+ readonly defaultSensitivity?: Sensitivity;
51
+ readonly providerAcceptsSensitivity?: ReadonlyArray<Sensitivity>;
52
+ readonly providerTrust?: LocalProviderTrust;
53
+ }
54
+ /**
55
+ * Configuration accepted by {@link createContextEngine}.
56
+ *
57
+ * @stable
58
+ */
59
+ interface ContextEngineConfig {
60
+ /**
61
+ * Layer 1 base-template mode. `'full'` (default) ships the
62
+ * verbose ~250-350 token narrative aimed at general LLMs;
63
+ * `'minimal'` opts top-tier models into the ~80-120 token
64
+ * compact form.
65
+ */
66
+ readonly memoryBaseMode?: MemoryBaseMode;
67
+ /** Default `'en'`. Pluggable via `defineContextLocalePack`. */
68
+ readonly locale?: string | ContextLocalePack | PartialContextLocalePack;
69
+ /** Per-layer enable / cap overrides. */
70
+ readonly layers?: {
71
+ readonly identity?: LayerConfig;
72
+ readonly memoryMetadata?: LayerConfig;
73
+ readonly activeRules?: LayerConfig;
74
+ readonly activeSkills?: LayerConfig;
75
+ readonly workingBlocks?: LayerConfig;
76
+ readonly autoRecall?: LayerConfig & {
77
+ readonly topK?: number;
78
+ readonly threshold?: number;
79
+ };
80
+ };
81
+ /** Auto-recall trigger configuration. Default `false`. */
82
+ readonly factsAutoRecall?: AutoRecallConfig;
83
+ /** Privacy-filter configuration. */
84
+ readonly privacy?: PrivacyConfig;
85
+ /** Hard token budget. Default `Number.POSITIVE_INFINITY` (no global cap). */
86
+ readonly maxContextTokens?: number;
87
+ /** Tokens reserved for the model's response. Default `4096`. */
88
+ readonly reservedForResponse?: number;
89
+ /** Tokens reserved for the compaction summarizer call. Default `8192`. */
90
+ readonly reservedForCompaction?: number;
91
+ /** Pluggable token counter. Default heuristic (chars/4). */
92
+ readonly tokenCounter?: TokenCounter | ContextTokenCounter;
93
+ /** Auto-compaction configuration (RB-46). */
94
+ readonly compaction?: false | CompactionConfig;
95
+ /** Active provider's context window; required when compaction is enabled. */
96
+ readonly providerContextWindow?: number;
97
+ /** Default summarizer adapter the auto-trigger uses. */
98
+ readonly summarizer?: CompactionSummarizer;
99
+ /** Wall clock for tests + deterministic compaction. */
100
+ readonly now?: () => number;
101
+ }
102
+ /**
103
+ * Per-call runtime context handed to {@link ContextEngine.assemble}.
104
+ *
105
+ * @stable
106
+ */
107
+ interface AssembleInput {
108
+ readonly scope: SessionScope;
109
+ readonly agentId: string;
110
+ readonly sessionId: string;
111
+ readonly runId: string;
112
+ readonly agentInstructions?: string;
113
+ readonly skills?: ReadonlyArray<SkillMetadataCard>;
114
+ readonly proceduralActivation?: {
115
+ readonly topic?: string;
116
+ readonly tags?: ReadonlyArray<string>;
117
+ };
118
+ readonly lastUserMessage?: string;
119
+ readonly autoRecallStrategyOverride?: AutoRecallStrategy;
120
+ /**
121
+ * Optional inbound-trust annotations carried by upstream
122
+ * messages (`session_messages` rows tagged by Phase 12 / Phase
123
+ * 07 / Phase 09). When at least one part has `inboundTrust !==
124
+ * 'trusted' && inboundTrust !== 'n/a'`, the per-step preamble
125
+ * fires (see RB-43 / DEC-159).
126
+ */
127
+ readonly upstreamAnnotations?: ReadonlyArray<ContentAnnotation>;
128
+ }
129
+ /**
130
+ * Single annotated `MessageContent` part assembled by the engine.
131
+ *
132
+ * @stable
133
+ */
134
+ interface AnnotatedPart {
135
+ readonly content: MessageContent;
136
+ readonly annotation: ContentAnnotation;
137
+ }
138
+ /**
139
+ * Output of {@link ContextEngine.assemble}.
140
+ *
141
+ * @stable
142
+ */
143
+ interface AssembledPrompt {
144
+ /** Single system message ready for `provider.stream(...)`. */
145
+ readonly systemMessage: {
146
+ readonly role: 'system';
147
+ readonly content: string;
148
+ };
149
+ /**
150
+ * Per-part annotations, in the same order as the assembled
151
+ * system content. Span-only — never serialized to the wire payload.
152
+ */
153
+ readonly annotations: ReadonlyArray<AnnotatedPart>;
154
+ /**
155
+ * Per-layer allocation snapshot. Surfaced for tests + diagnostics.
156
+ */
157
+ readonly layerAllocation: AllocationResult;
158
+ /** Whether the per-step inbound preamble fragment fired this assembly. */
159
+ readonly inboundPreambleFired: boolean;
160
+ /** Privacy-filter counters surfaced to the metadata block. */
161
+ readonly privacyCounters: Readonly<Record<PrivacyDecisionReason, number>>;
162
+ /** Resolved locale id (`'en'` for the default; custom otherwise). */
163
+ readonly localeId: string;
164
+ /** Resolved memory base mode. */
165
+ readonly memoryBaseMode: MemoryBaseMode;
166
+ /** Whether auto-recall was triggered this assembly. */
167
+ readonly autoRecall: AutoRecallTriggerResult;
168
+ }
169
+ /**
170
+ * Public surface of the {@link ContextEngine} instance returned by
171
+ * {@link createContextEngine}.
172
+ *
173
+ * @stable
174
+ */
175
+ interface ContextEngine {
176
+ /** Assemble the layered system prompt for a single step. */
177
+ assemble(memory: Memory, input: AssembleInput): Promise<AssembledPrompt>;
178
+ /**
179
+ * Trigger evaluation primitive used by Phase 12 (agent runtime)
180
+ * at the top of every step. Returns `true` when the in-flight
181
+ * buffer's token count crosses the per-provider trigger
182
+ * threshold. Pass `precomputedTokens` to amortize the count
183
+ * via the per-message cache surfaced by
184
+ * `SessionMemoryStoreExt.totalCachedTokens(scope)` (DEC-131) —
185
+ * the production hot path is an O(1) comparison when the cache
186
+ * is warm.
187
+ */
188
+ shouldCompact(messages: ReadonlyArray<Message>, options?: {
189
+ readonly precomputedTokens?: number;
190
+ }): Promise<boolean>;
191
+ /**
192
+ * Run a compaction call. Phase 12 calls this when the trigger
193
+ * fires (`source: 'auto-trigger'`) or the operator invokes
194
+ * `agent.compact(...)` (`source: 'manual'`).
195
+ */
196
+ compactNow(input: {
197
+ readonly scope: SessionScope;
198
+ readonly runId: string;
199
+ readonly sessionId: string;
200
+ readonly agentId: string;
201
+ readonly source: CompactionSource;
202
+ readonly messages: ReadonlyArray<Message>;
203
+ readonly memory: Memory;
204
+ readonly summarizer?: CompactionSummarizer;
205
+ /** Per-call override of the strategy's preserve-recent count (CE-3). */
206
+ readonly preserveRecentTurns?: number;
207
+ /** Topic/tags narrowing for the procedural-rules re-anchor hook (CE-6). */
208
+ readonly procedural?: {
209
+ readonly topic?: string;
210
+ readonly tags?: ReadonlyArray<string>;
211
+ };
212
+ readonly signal?: AbortSignal;
213
+ }): Promise<{
214
+ readonly result: CompactionResult;
215
+ readonly extraContent: ReadonlyArray<MessageContent>;
216
+ readonly hookFailures: ReadonlyArray<{
217
+ readonly hookName: string;
218
+ readonly reason: string;
219
+ }>;
220
+ }>;
221
+ /** Resolved configuration snapshot. */
222
+ config(): ResolvedContextEngineConfig;
223
+ }
224
+ /**
225
+ * Resolved configuration snapshot returned by
226
+ * {@link ContextEngine.config}.
227
+ *
228
+ * @stable
229
+ */
230
+ interface ResolvedContextEngineConfig {
231
+ readonly memoryBaseMode: MemoryBaseMode;
232
+ readonly localeId: string;
233
+ readonly maxContextTokens: number;
234
+ readonly reservedForResponse: number;
235
+ readonly reservedForCompaction: number;
236
+ readonly compactionEnabled: boolean;
237
+ /**
238
+ * Whether compaction can actually fire (CE-12): `compactionEnabled` **and** a
239
+ * `providerContextWindow` was supplied. `compactionEnabled: true` with
240
+ * `compactionEffective: false` is the honest signal that compaction is
241
+ * configured-on but a no-op for want of a context window.
242
+ */
243
+ readonly compactionEffective: boolean;
244
+ readonly compactionThresholdTokens: number;
245
+ readonly providerContextWindow: number | null;
246
+ readonly providerTrust: LocalProviderTrust;
247
+ readonly cloudUploadConsent: boolean;
248
+ readonly defaultSensitivity: Sensitivity;
249
+ }
250
+ /**
251
+ * Build a ContextEngine instance from the supplied configuration.
252
+ *
253
+ * @stable
254
+ */
255
+ declare function createContextEngine(config?: ContextEngineConfig): ContextEngine;
256
+ //#endregion
257
+ export { AnnotatedPart, AssembleInput, AssembledPrompt, AutoRecallConfig, ContextEngine, ContextEngineConfig, LayerConfig, PrivacyConfig, ResolvedContextEngineConfig, createContextEngine };
258
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","names":[],"sources":["../../src/context-engine/engine.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;AAwLA;AACkB,UA3FD,WAAA,CA2FC;EAKgB,SAAA,OAAA,CAAA,EAAA,OAAA;EAAd,SAAA,GAAA,CAAA,EAAA,MAAA;;;;;;AAsBpB;AAUA;AAOsC,KA5H1B,gBAAA,GA4H0B,KAAA,GAAA;EAAd,SAAA,IAAA,CAAA,EAAA,MAAA;EAII;;;;;;;AAmB5B;EAEmB,SAAA,SAAA,CAAA,EAAA,MAAA;EAAe,SAAA,QAAA,CAAA,EAxIR,kBAwIQ;CAAwB;;;;;;AAyBrC,UAzJJ,aAAA,CAyJI;EACgB,SAAA,kBAAA,CAAA,EAAA,OAAA;EAAd,SAAA,kBAAA,CAAA,EAxJS,WAwJT;EACF,SAAA,0BAAA,CAAA,EAxJmB,aAwJnB,CAxJiC,WAwJjC,CAAA;EACK,SAAA,aAAA,CAAA,EAxJC,kBAwJD;;;;;;;AAMpB,UAtJW,mBAAA,CAsJX;EAMM;;AASZ;;;;EAkB0C,SAAA,cAAA,CAAA,EAhLd,cAgLc;EAgE1B;6BA9Oa,oBAAoB;;;wBAGzB;8BACM;2BACH;4BACC;6BACC;0BACH;;;;;;6BAGG;;qBAER;;;;;;;;0BAQK,eAAe;;gCAET;;;;wBAIR;;;;;;;;;UAUP,aAAA;kBACC;;;;;oBAKE,cAAc;;;oBAGd;;;wCAGoB;;;;;;;;iCAQP,cAAc;;;;;;;UAQ9B,aAAA;oBACG;uBACG;;;;;;;UAQN,eAAA;;;;;;;;;;wBAOO,cAAc;;;;4BAIV;;;;4BAIA,SAAS,OAAO;;;;2BAIjB;;uBAEJ;;;;;;;;UASN,aAAA;;mBAEE,eAAe,gBAAgB,QAAQ;;;;;;;;;;;0BAY5C,cAAc;;MAEvB;;;;;;;oBAOe;;;;qBAIC;uBACE,cAAc;qBAChB;0BACK;;;;;;sBAI2C;;sBAC/C;MAChB;qBACe;2BACM,cAAc;2BACd;;;;;;YAGf;;;;;;;;UASK,2BAAA;2BACU;;;;;;;;;;;;;;;0BAeD;;+BAEK;;;;;;;iBAgEf,mBAAA,UAA4B,sBAA2B"}
@@ -0,0 +1,424 @@
1
+ import { annotate, shouldFireInboundPreamble } from "./annotations.js";
2
+ import { defaultLocaleHeuristicStrategy } from "./auto-recall.js";
3
+ import { HEURISTIC_TOKEN_COUNTER, adaptTokenCounter, countMessageTokens } from "./token-counter.js";
4
+ import { DEFAULT_PRESERVE_RECENT_TURNS, executeCompaction } from "./compaction/compactor.js";
5
+ import { reanchorPersonaBlock } from "./compaction/hooks/reanchor-persona-block.js";
6
+ import { reanchorPinnedFacts } from "./compaction/hooks/reanchor-pinned-facts.js";
7
+ import { reanchorProjectRules } from "./compaction/hooks/reanchor-project-rules.js";
8
+ import { resolveAutoCompactionDefault, resolveTriggerThreshold } from "./compaction/thresholds.js";
9
+ import "./compaction/index.js";
10
+ import { enLocalePack } from "./locale-packs/en.js";
11
+ import "./locale-packs/index.js";
12
+ import { resolveLocalePack } from "./locale-packs/resolver.js";
13
+ import { renderMetadataBlock } from "./metadata.js";
14
+ import { decide } from "./privacy-filter.js";
15
+ import { composeInboundPreamble, composeLayer1, composeLayer2, composeLayer4Skills } from "./templates/composer.js";
16
+ import { allocate } from "./token-budget.js";
17
+
18
+ //#region src/context-engine/engine.ts
19
+ const DEFAULT_LAYER_CAPS = {
20
+ identity: void 0,
21
+ memoryMetadata: void 0,
22
+ activeRules: void 0,
23
+ activeSkills: void 0,
24
+ workingBlocks: void 0,
25
+ autoRecall: void 0
26
+ };
27
+ let compactionIneffectiveWarned = false;
28
+ let heuristicCounterWarned = false;
29
+ /** Emit the "compaction enabled but ineffective" warning at most once (CE-12). */
30
+ function warnCompactionIneffective(message) {
31
+ if (compactionIneffectiveWarned) return;
32
+ compactionIneffectiveWarned = true;
33
+ process.stderr.write(`[graphorin/memory] ${message}\n`);
34
+ }
35
+ /**
36
+ * Emission order for the assembled layers — deliberately **distinct from the
37
+ * truncation priority ladder** (CE-9). Allocation still trims by
38
+ * `DEFAULT_LAYER_PRIORITY` (lowest priority first), but layers are *emitted* in
39
+ * this order so the volatile blocks that change every turn (`memoryMetadata`'s
40
+ * counts, `autoRecall`'s injected facts) sit **after** the stable Layer 1-4
41
+ * prefix (identity / rules / blocks / skills). That keeps the provider's — and a
42
+ * local llama.cpp / vLLM server's — KV-cache breakpoint real: the prefix stays
43
+ * byte-identical across turns even as the message count and recalled facts move.
44
+ */
45
+ const LAYER_EMIT_ORDER = Object.freeze({
46
+ identity: 0,
47
+ activeRules: 1,
48
+ workingBlocks: 2,
49
+ activeSkills: 3,
50
+ memoryMetadata: 4,
51
+ autoRecall: 5
52
+ });
53
+ /**
54
+ * Build a ContextEngine instance from the supplied configuration.
55
+ *
56
+ * @stable
57
+ */
58
+ function createContextEngine(config = {}) {
59
+ const memoryBaseMode = config.memoryBaseMode ?? "full";
60
+ const localeInput = config.locale;
61
+ const localePack = resolvePackInput(localeInput);
62
+ const localeId = localePack.id;
63
+ const layerCfg = config.layers ?? {};
64
+ const layersEnabled = {
65
+ identity: layerCfg.identity?.enabled ?? true,
66
+ memoryMetadata: layerCfg.memoryMetadata?.enabled ?? true,
67
+ activeRules: layerCfg.activeRules?.enabled ?? true,
68
+ activeSkills: layerCfg.activeSkills?.enabled ?? true,
69
+ workingBlocks: layerCfg.workingBlocks?.enabled ?? true,
70
+ autoRecall: layerCfg.autoRecall?.enabled ?? true
71
+ };
72
+ const layerCaps = {
73
+ identity: layerCfg.identity?.cap ?? DEFAULT_LAYER_CAPS.identity,
74
+ memoryMetadata: layerCfg.memoryMetadata?.cap ?? DEFAULT_LAYER_CAPS.memoryMetadata,
75
+ activeRules: layerCfg.activeRules?.cap ?? DEFAULT_LAYER_CAPS.activeRules,
76
+ activeSkills: layerCfg.activeSkills?.cap ?? DEFAULT_LAYER_CAPS.activeSkills,
77
+ workingBlocks: layerCfg.workingBlocks?.cap ?? DEFAULT_LAYER_CAPS.workingBlocks,
78
+ autoRecall: layerCfg.autoRecall?.cap ?? DEFAULT_LAYER_CAPS.autoRecall
79
+ };
80
+ const factsAutoRecall = config.factsAutoRecall ?? false;
81
+ const reservedForResponse = config.reservedForResponse ?? 4096;
82
+ const reservedForCompaction = config.reservedForCompaction ?? 8192;
83
+ const maxContextTokens = config.maxContextTokens ?? Number.POSITIVE_INFINITY;
84
+ const tokenCounter = config.tokenCounter ? "count" in config.tokenCounter ? adaptTokenCounter(config.tokenCounter) : config.tokenCounter : HEURISTIC_TOKEN_COUNTER;
85
+ if (config.tokenCounter === void 0 && typeof config.providerContextWindow === "number" && !heuristicCounterWarned) {
86
+ heuristicCounterWarned = true;
87
+ process.stderr.write("[graphorin/memory] context-engine token counts use the built-in heuristic (chars/4 + dense-script). For production budgeting against a real provider window, pass `contextEngine.tokenCounter` (e.g. the provider package JsTiktokenCounter).\n");
88
+ }
89
+ const privacy = config.privacy ?? {};
90
+ const defaultSensitivity = privacy.defaultSensitivity ?? "internal";
91
+ const providerTrust = privacy.providerTrust ?? "public-tls";
92
+ const cloudUploadConsent = privacy.cloudUploadConsent ?? false;
93
+ const heuristicStrategy = defaultLocaleHeuristicStrategy(localePack);
94
+ const compactionInput = config.compaction;
95
+ const compactionAutoDefault = resolveAutoCompactionDefault(providerTrust);
96
+ const compactionEnabled = compactionInput === false ? false : compactionInput === void 0 ? compactionAutoDefault === "enabled" : compactionInput.trigger !== "never";
97
+ const providerContextWindow = config.providerContextWindow ?? null;
98
+ const triggerSpec = compactionInput === false || compactionInput === void 0 ? void 0 : compactionInput.trigger;
99
+ const compactionThresholdTokens = compactionEnabled && providerContextWindow !== null ? resolveTriggerThreshold({
100
+ contextWindow: providerContextWindow,
101
+ ...triggerSpec !== void 0 ? { trigger: triggerSpec } : {},
102
+ reservedForResponse,
103
+ reservedForCompaction
104
+ }) : Number.POSITIVE_INFINITY;
105
+ const compactionEffective = compactionEnabled && providerContextWindow !== null;
106
+ if (compactionEnabled && providerContextWindow === null) {
107
+ const message = "context-engine compaction is enabled but `providerContextWindow` is not set, so the trigger threshold is Infinity and compaction will never fire. Pass `providerContextWindow` (your model's context window, in tokens) — auto-detection from the provider is not implemented.";
108
+ if (compactionInput !== void 0 && compactionInput !== false) throw new Error(`[graphorin/memory] ${message}`);
109
+ warnCompactionIneffective(message);
110
+ }
111
+ const compactionStrategy = compactionInput === false || compactionInput === void 0 || compactionInput.strategy === void 0 ? {
112
+ kind: "summarize-old-preserve-recent",
113
+ preserveRecentTurns: 6,
114
+ templateName: "summary-9-section"
115
+ } : compactionInput.strategy;
116
+ const compactionMinReclaimTokens = triggerSpec !== void 0 && triggerSpec !== "never" ? Math.max(0, triggerSpec.minReclaimTokens ?? 0) : 0;
117
+ const reclaimPreserveTurns = compactionStrategy.kind === "summarize-old-preserve-recent" ? compactionStrategy.preserveRecentTurns ?? DEFAULT_PRESERVE_RECENT_TURNS : compactionStrategy.kind === "clear-old-tool-results" && typeof compactionStrategy.summarizeFallback === "object" ? compactionStrategy.summarizeFallback.preserveRecentTurns ?? DEFAULT_PRESERVE_RECENT_TURNS : DEFAULT_PRESERVE_RECENT_TURNS;
118
+ const compactionHooks = resolveDefaultHooks(compactionInput === false || compactionInput === void 0 ? void 0 : compactionInput.postCompactionHooks);
119
+ const summarizer = config.summarizer;
120
+ const now = config.now ?? Date.now;
121
+ const resolvedConfig = Object.freeze({
122
+ memoryBaseMode,
123
+ localeId,
124
+ maxContextTokens,
125
+ reservedForResponse,
126
+ reservedForCompaction,
127
+ compactionEnabled,
128
+ compactionEffective,
129
+ compactionThresholdTokens,
130
+ providerContextWindow,
131
+ providerTrust,
132
+ cloudUploadConsent,
133
+ defaultSensitivity
134
+ });
135
+ async function assemble(memory, input) {
136
+ const layer1Text = layersEnabled.identity ? composeLayer1(localePack, memoryBaseMode) : "";
137
+ const layer2Text = composeLayer2(input.agentInstructions);
138
+ const blocks = await memory.working.list(input.scope);
139
+ const blocksKept = [];
140
+ const privacyCounters = {
141
+ allowed: 0,
142
+ "no-cloud-upload-consent": 0,
143
+ "provider-rejects-internal": 0,
144
+ "provider-rejects-secret": 0
145
+ };
146
+ for (const block of blocks) {
147
+ const decision = decide(block.sensitivity, {
148
+ ...privacy.providerAcceptsSensitivity !== void 0 ? { providerAcceptsSensitivity: privacy.providerAcceptsSensitivity } : {},
149
+ providerTrust,
150
+ cloudUploadConsent,
151
+ defaultSensitivity
152
+ });
153
+ privacyCounters[decision.reason] += 1;
154
+ if (decision.decision === "pass") blocksKept.push(block);
155
+ }
156
+ const layer3Text = layersEnabled.workingBlocks ? renderWorkingBlocks(blocksKept) : "";
157
+ const rules = await memory.procedural.activate(input.scope, input.proceduralActivation ?? {});
158
+ const rulesKept = [];
159
+ for (const rule of rules) {
160
+ const decision = decide(rule.sensitivity, {
161
+ ...privacy.providerAcceptsSensitivity !== void 0 ? { providerAcceptsSensitivity: privacy.providerAcceptsSensitivity } : {},
162
+ providerTrust,
163
+ cloudUploadConsent,
164
+ defaultSensitivity
165
+ });
166
+ privacyCounters[decision.reason] += 1;
167
+ if (decision.decision === "pass") rulesKept.push(rule);
168
+ }
169
+ const layer4RulesText = layersEnabled.activeRules ? renderProceduralRules(rulesKept) : "";
170
+ const layer4SkillsText = layersEnabled.activeSkills ? composeLayer4Skills(input.skills ?? []) : "";
171
+ const meta = await memory.metadata(input.scope);
172
+ const layer5Text = layersEnabled.memoryMetadata ? renderMetadataBlock(enrichMetadataTags(meta, localeId, memory.embedderId())) : "";
173
+ let autoRecall = { factsTriggered: false };
174
+ let layer6Text = "";
175
+ if (factsAutoRecall !== false && layersEnabled.autoRecall) {
176
+ autoRecall = (input.autoRecallStrategyOverride ?? factsAutoRecall.strategy ?? heuristicStrategy)({
177
+ locale: localeId,
178
+ lastUserMessage: input.lastUserMessage ?? ""
179
+ });
180
+ if (autoRecall.factsTriggered) {
181
+ const topK = factsAutoRecall.topK ?? layerCfg.autoRecall?.topK ?? 5;
182
+ const threshold = factsAutoRecall.threshold ?? layerCfg.autoRecall?.threshold ?? 0;
183
+ const hits = await memory.semantic.search(input.scope, input.lastUserMessage ?? "", { topK }).catch(() => []);
184
+ const facts = [];
185
+ for (const hit of hits) {
186
+ if (hit.score < threshold) continue;
187
+ const decision = decide(hit.record.sensitivity, {
188
+ ...privacy.providerAcceptsSensitivity !== void 0 ? { providerAcceptsSensitivity: privacy.providerAcceptsSensitivity } : {},
189
+ providerTrust,
190
+ cloudUploadConsent,
191
+ defaultSensitivity
192
+ });
193
+ privacyCounters[decision.reason] += 1;
194
+ if (decision.decision === "pass") facts.push(hit.record);
195
+ }
196
+ layer6Text = renderAutoRecalledFacts(facts);
197
+ }
198
+ }
199
+ const allocation = await allocate([
200
+ buildCandidate("identity", layer1Text.length > 0 && layer2Text.length > 0 ? `${layer1Text}\n\n${layer2Text}` : layer1Text + layer2Text, layerCaps.identity),
201
+ buildCandidate("memoryMetadata", layer5Text, layerCaps.memoryMetadata),
202
+ buildCandidate("activeRules", layer4RulesText, layerCaps.activeRules),
203
+ buildCandidate("workingBlocks", layer3Text, layerCaps.workingBlocks),
204
+ buildCandidate("activeSkills", layer4SkillsText, layerCaps.activeSkills),
205
+ buildCandidate("autoRecall", layer6Text, layerCaps.autoRecall)
206
+ ].filter((c) => c.text.length > 0), maxContextTokens, tokenCounter);
207
+ const preambleFired = shouldFireInboundPreamble(input.upstreamAnnotations ?? []);
208
+ const preambleText = preambleFired ? composeInboundPreamble(localePack) : "";
209
+ const assembledLayers = allocation.layers.filter((l) => l.text.length > 0).sort((a, b) => LAYER_EMIT_ORDER[a.id] - LAYER_EMIT_ORDER[b.id]);
210
+ const finalParts = assembledLayers.map((l) => l.text);
211
+ if (preambleText.length > 0) finalParts.push(preambleText);
212
+ const systemContent = finalParts.join("\n\n");
213
+ const annotations = assembledLayers.map((layer) => ({
214
+ content: {
215
+ type: "text",
216
+ text: layer.text
217
+ },
218
+ annotation: annotationForLayer(layer)
219
+ }));
220
+ if (preambleText.length > 0) annotations.push({
221
+ content: {
222
+ type: "text",
223
+ text: preambleText
224
+ },
225
+ annotation: annotate("system:framework", "n/a")
226
+ });
227
+ return Object.freeze({
228
+ systemMessage: Object.freeze({
229
+ role: "system",
230
+ content: systemContent
231
+ }),
232
+ annotations: Object.freeze(annotations),
233
+ layerAllocation: allocation,
234
+ inboundPreambleFired: preambleFired,
235
+ privacyCounters: Object.freeze(privacyCounters),
236
+ localeId,
237
+ memoryBaseMode,
238
+ autoRecall
239
+ });
240
+ }
241
+ let lastCompactionAfterTokens = null;
242
+ const REARM_GROWTH_TOKENS = 256;
243
+ async function shouldCompact(messages, options = {}) {
244
+ if (!compactionEnabled) return false;
245
+ if (compactionThresholdTokens === Number.POSITIVE_INFINITY) return false;
246
+ const total = options.precomputedTokens ?? await countMessageTokens(messages, tokenCounter);
247
+ if (total < compactionThresholdTokens) return false;
248
+ if (lastCompactionAfterTokens !== null && total <= lastCompactionAfterTokens + REARM_GROWTH_TOKENS) return false;
249
+ if (compactionMinReclaimTokens > 0) {
250
+ const olderCount = Math.max(0, messages.length - reclaimPreserveTurns);
251
+ if (olderCount === 0) return false;
252
+ if (await countMessageTokens(messages.slice(0, olderCount), tokenCounter) < compactionMinReclaimTokens) return false;
253
+ }
254
+ return true;
255
+ }
256
+ async function compactNow(callInput) {
257
+ const activeSummarizer = callInput.summarizer ?? summarizer;
258
+ if (activeSummarizer === void 0) throw new TypeError("[graphorin/memory] ContextEngine.compactNow: no summarizer configured. Pass `summarizer` to createContextEngine({...}) or to compactNow({...}).");
259
+ const result = await executeCompaction({
260
+ messages: callInput.messages,
261
+ source: callInput.source,
262
+ strategy: callInput.preserveRecentTurns !== void 0 && compactionStrategy.kind === "summarize-old-preserve-recent" ? {
263
+ ...compactionStrategy,
264
+ preserveRecentTurns: callInput.preserveRecentTurns
265
+ } : compactionStrategy,
266
+ localePack,
267
+ summarizer: activeSummarizer,
268
+ tokenCounter,
269
+ thresholdTokens: compactionThresholdTokens,
270
+ runId: callInput.runId,
271
+ sessionId: callInput.sessionId,
272
+ agentId: callInput.agentId,
273
+ scope: callInput.scope,
274
+ providerTrust,
275
+ now,
276
+ ...callInput.signal !== void 0 ? { signal: callInput.signal } : {}
277
+ });
278
+ const ctx = {
279
+ result,
280
+ scope: callInput.scope,
281
+ runId: callInput.runId,
282
+ sessionId: callInput.sessionId,
283
+ agentId: callInput.agentId,
284
+ source: callInput.source
285
+ };
286
+ const hookFailures = [];
287
+ const extraContent = [];
288
+ let hooksFired = 0;
289
+ for (const hook of compactionHooks) try {
290
+ const parts = await hook.resolveContent({
291
+ memory: callInput.memory,
292
+ scope: callInput.scope,
293
+ ...callInput.procedural !== void 0 ? { procedural: callInput.procedural } : {}
294
+ }, ctx);
295
+ extraContent.push(...parts);
296
+ hooksFired += 1;
297
+ } catch (err) {
298
+ hookFailures.push({
299
+ hookName: hook.id,
300
+ reason: err instanceof Error ? err.name : "UnknownError"
301
+ });
302
+ }
303
+ const enrichedResult = Object.freeze({
304
+ ...result,
305
+ hooksFiredCount: hooksFired
306
+ });
307
+ lastCompactionAfterTokens = enrichedResult.afterTokens;
308
+ if (compactionThresholdTokens !== Number.POSITIVE_INFINITY && enrichedResult.afterTokens >= compactionThresholdTokens) process.stderr.write(`[graphorin/memory] compaction finished at ${enrichedResult.afterTokens} tokens — still at/above the ${compactionThresholdTokens}-token trigger (oversized preserved turns?). The immediate re-trigger is suppressed until the buffer grows.\n`);
309
+ return Object.freeze({
310
+ result: enrichedResult,
311
+ extraContent: Object.freeze(extraContent),
312
+ hookFailures: Object.freeze(hookFailures)
313
+ });
314
+ }
315
+ return Object.freeze({
316
+ assemble,
317
+ shouldCompact,
318
+ compactNow,
319
+ config() {
320
+ return resolvedConfig;
321
+ }
322
+ });
323
+ }
324
+ function buildCandidate(id, text, cap) {
325
+ if (cap !== void 0) return {
326
+ id,
327
+ text,
328
+ cap
329
+ };
330
+ return {
331
+ id,
332
+ text
333
+ };
334
+ }
335
+ function annotationForLayer(layer) {
336
+ switch (layer.id) {
337
+ case "identity": return annotate("system:framework", "n/a");
338
+ case "memoryMetadata":
339
+ case "activeRules":
340
+ case "workingBlocks":
341
+ case "activeSkills":
342
+ case "autoRecall": return annotate("memory:tier-filtered", "n/a");
343
+ default: return annotate("system:framework", "n/a");
344
+ }
345
+ }
346
+ function renderWorkingBlocks(blocks) {
347
+ if (blocks.length === 0) return "";
348
+ const lines = ["<memory_blocks>"];
349
+ for (const block of blocks) {
350
+ const description = block.description !== void 0 ? ` description="${escapeXmlAttr(block.description)}"` : "";
351
+ lines.push(` <block label="${escapeXmlAttr(block.label)}"${description}>`);
352
+ lines.push(` ${escapeXmlText(block.value)}`);
353
+ lines.push(" </block>");
354
+ }
355
+ lines.push("</memory_blocks>");
356
+ return lines.join("\n");
357
+ }
358
+ function renderProceduralRules(rules) {
359
+ if (rules.length === 0) return "";
360
+ const lines = ["<memory_rules>"];
361
+ for (const rule of rules) lines.push(` <rule priority="${rule.priority}">${escapeXmlText(rule.text)}</rule>`);
362
+ lines.push("</memory_rules>");
363
+ return lines.join("\n");
364
+ }
365
+ function renderAutoRecalledFacts(facts) {
366
+ if (facts.length === 0) return "";
367
+ const lines = ["<auto_recalled_facts>"];
368
+ for (const fact of facts) {
369
+ const tagsAttr = fact.tags !== void 0 ? ` tags="${escapeXmlAttr((fact.tags ?? []).join(","))}"` : "";
370
+ lines.push(` <fact id="${escapeXmlAttr(fact.id)}"${tagsAttr}>${escapeXmlText(fact.text)}</fact>`);
371
+ }
372
+ lines.push("</auto_recalled_facts>");
373
+ return lines.join("\n");
374
+ }
375
+ function escapeXmlAttr(value) {
376
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
377
+ }
378
+ function escapeXmlText(value) {
379
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
380
+ }
381
+ function resolvePackInput(input) {
382
+ if (input === void 0) return enLocalePack;
383
+ if (typeof input === "string") {
384
+ if (input === enLocalePack.id) return enLocalePack;
385
+ return resolveLocalePack({ id: input });
386
+ }
387
+ return resolveLocalePack(input);
388
+ }
389
+ function resolveDefaultHooks(input) {
390
+ if (input === void 0) return Object.freeze([
391
+ reanchorProjectRules(),
392
+ reanchorPersonaBlock(),
393
+ reanchorPinnedFacts({ pinnedFactIds: [] })
394
+ ]);
395
+ return Object.freeze(input.map((hook, idx) => {
396
+ if (typeof hook === "function") return {
397
+ id: `customHook_${idx}`,
398
+ async resolveContent(_deps, ctx) {
399
+ if (ctx === void 0) throw new TypeError("[graphorin/memory] post-compaction hooks require the compaction context — call through ContextEngine.compactNow(...).");
400
+ return await hook(ctx);
401
+ }
402
+ };
403
+ return hook;
404
+ }));
405
+ }
406
+ /**
407
+ * Augment a {@link MemoryMetadata} snapshot with the active locale +
408
+ * embedder tags so the rendered metadata block carries the
409
+ * additional context the model uses for reasoning. Pure: the
410
+ * original `meta` reference is not mutated.
411
+ */
412
+ function enrichMetadataTags(meta, localeId, embedderId) {
413
+ const baseTags = meta.tags !== void 0 ? [...meta.tags] : [];
414
+ if (!baseTags.some((tag) => tag.startsWith("locale:"))) baseTags.push(`locale:${localeId}`);
415
+ if (embedderId !== null && !baseTags.some((tag) => tag.startsWith("embedder:"))) baseTags.push(`embedder:${embedderId}`);
416
+ return {
417
+ ...meta,
418
+ tags: Object.freeze(baseTags)
419
+ };
420
+ }
421
+
422
+ //#endregion
423
+ export { createContextEngine };
424
+ //# sourceMappingURL=engine.js.map