@graphorin/memory 0.6.0 → 0.7.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 (227) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +24 -7
  3. package/dist/conflict/index.js +0 -1
  4. package/dist/conflict/pipeline.js +0 -1
  5. package/dist/conflict/pipeline.js.map +1 -1
  6. package/dist/conflict/stages/stage3-heuristic-regex.js +0 -1
  7. package/dist/conflict/stages/stage3-heuristic-regex.js.map +1 -1
  8. package/dist/conflict/types.d.ts +1 -1
  9. package/dist/conflict/types.js.map +1 -1
  10. package/dist/consolidator/index.js +2 -0
  11. package/dist/consolidator/index.js.map +1 -1
  12. package/dist/consolidator/lock.js +7 -1
  13. package/dist/consolidator/lock.js.map +1 -1
  14. package/dist/consolidator/phases/deep.js +19 -12
  15. package/dist/consolidator/phases/deep.js.map +1 -1
  16. package/dist/consolidator/phases/induce.d.ts.map +1 -1
  17. package/dist/consolidator/phases/induce.js +2 -3
  18. package/dist/consolidator/phases/induce.js.map +1 -1
  19. package/dist/consolidator/phases/reflect.js +35 -8
  20. package/dist/consolidator/phases/reflect.js.map +1 -1
  21. package/dist/consolidator/phases/standard.js +199 -28
  22. package/dist/consolidator/phases/standard.js.map +1 -1
  23. package/dist/consolidator/reconcile.js +16 -15
  24. package/dist/consolidator/reconcile.js.map +1 -1
  25. package/dist/consolidator/runtime.d.ts.map +1 -1
  26. package/dist/consolidator/runtime.js +129 -47
  27. package/dist/consolidator/runtime.js.map +1 -1
  28. package/dist/consolidator/scheduler.d.ts +17 -3
  29. package/dist/consolidator/scheduler.d.ts.map +1 -1
  30. package/dist/consolidator/scheduler.js.map +1 -1
  31. package/dist/consolidator/types.d.ts +30 -1
  32. package/dist/consolidator/types.d.ts.map +1 -1
  33. package/dist/consolidator/types.js +10 -0
  34. package/dist/consolidator/types.js.map +1 -1
  35. package/dist/context-engine/compaction/clear-tool-results.d.ts +1 -1
  36. package/dist/context-engine/compaction/clear-tool-results.js +1 -1
  37. package/dist/context-engine/compaction/clear-tool-results.js.map +1 -1
  38. package/dist/context-engine/compaction/compactor.d.ts +1 -0
  39. package/dist/context-engine/compaction/compactor.d.ts.map +1 -1
  40. package/dist/context-engine/compaction/compactor.js +32 -8
  41. package/dist/context-engine/compaction/compactor.js.map +1 -1
  42. package/dist/context-engine/compaction/hooks/types.d.ts +1 -1
  43. package/dist/context-engine/compaction/index.d.ts +1 -0
  44. package/dist/context-engine/compaction/templates/marker.d.ts +33 -0
  45. package/dist/context-engine/compaction/templates/marker.d.ts.map +1 -0
  46. package/dist/context-engine/compaction/templates/marker.js +34 -0
  47. package/dist/context-engine/compaction/templates/marker.js.map +1 -0
  48. package/dist/context-engine/compaction/templates/summary-9-section.d.ts +1 -1
  49. package/dist/context-engine/compaction/templates/summary-9-section.d.ts.map +1 -1
  50. package/dist/context-engine/compaction/templates/summary-9-section.js +4 -3
  51. package/dist/context-engine/compaction/templates/summary-9-section.js.map +1 -1
  52. package/dist/context-engine/engine.d.ts +7 -176
  53. package/dist/context-engine/engine.d.ts.map +1 -1
  54. package/dist/context-engine/engine.js +0 -2
  55. package/dist/context-engine/engine.js.map +1 -1
  56. package/dist/context-engine/index.d.ts +8 -49
  57. package/dist/context-engine/io-types.d.ts +144 -0
  58. package/dist/context-engine/io-types.d.ts.map +1 -0
  59. package/dist/context-engine/locale-packs/types.d.ts +1 -1
  60. package/dist/context-engine/locale-packs/types.js.map +1 -1
  61. package/dist/context-engine/privacy-filter.d.ts +1 -2
  62. package/dist/context-engine/privacy-filter.d.ts.map +1 -1
  63. package/dist/context-engine/privacy-filter.js +1 -2
  64. package/dist/context-engine/privacy-filter.js.map +1 -1
  65. package/dist/errors/index.d.ts +2 -2
  66. package/dist/errors/index.js +2 -2
  67. package/dist/errors/index.js.map +1 -1
  68. package/dist/facade.d.ts +43 -52
  69. package/dist/facade.d.ts.map +1 -1
  70. package/dist/facade.js +5 -3
  71. package/dist/facade.js.map +1 -1
  72. package/dist/graph/entity-resolver.js +1 -1
  73. package/dist/graph/entity-resolver.js.map +1 -1
  74. package/dist/index.d.ts +17 -15
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +5 -7
  77. package/dist/index.js.map +1 -1
  78. package/dist/internal/envelope.js +57 -0
  79. package/dist/internal/envelope.js.map +1 -0
  80. package/dist/internal/injection-heuristics.js +0 -0
  81. package/dist/internal/injection-heuristics.js.map +1 -1
  82. package/dist/internal/llm-json.js +40 -0
  83. package/dist/internal/llm-json.js.map +1 -0
  84. package/dist/internal/storage-adapter.d.ts +23 -10
  85. package/dist/internal/storage-adapter.d.ts.map +1 -1
  86. package/dist/memory-interface.d.ts +131 -0
  87. package/dist/memory-interface.d.ts.map +1 -0
  88. package/dist/package.js +6 -0
  89. package/dist/package.js.map +1 -0
  90. package/dist/search/iterative.d.ts.map +1 -1
  91. package/dist/search/iterative.js +2 -3
  92. package/dist/search/iterative.js.map +1 -1
  93. package/dist/search/query-transform.d.ts.map +1 -1
  94. package/dist/search/query-transform.js +2 -3
  95. package/dist/search/query-transform.js.map +1 -1
  96. package/dist/tiers/episodic-memory.js +3 -3
  97. package/dist/tiers/episodic-memory.js.map +1 -1
  98. package/dist/tiers/index.d.ts +2 -2
  99. package/dist/tiers/insight-memory.js +1 -1
  100. package/dist/tiers/insight-memory.js.map +1 -1
  101. package/dist/tiers/procedural-memory.d.ts +1 -1
  102. package/dist/tiers/procedural-memory.js +2 -2
  103. package/dist/tiers/procedural-memory.js.map +1 -1
  104. package/dist/tiers/semantic-memory.d.ts +58 -4
  105. package/dist/tiers/semantic-memory.d.ts.map +1 -1
  106. package/dist/tiers/semantic-memory.js +103 -20
  107. package/dist/tiers/semantic-memory.js.map +1 -1
  108. package/dist/tools/block-tools.d.ts +19 -57
  109. package/dist/tools/block-tools.d.ts.map +1 -1
  110. package/dist/tools/block-tools.js.map +1 -1
  111. package/dist/tools/fact-tools.d.ts +53 -214
  112. package/dist/tools/fact-tools.d.ts.map +1 -1
  113. package/dist/tools/fact-tools.js +3 -2
  114. package/dist/tools/fact-tools.js.map +1 -1
  115. package/dist/tools/recall-tools.d.ts +34 -175
  116. package/dist/tools/recall-tools.d.ts.map +1 -1
  117. package/dist/tools/recall-tools.js +5 -4
  118. package/dist/tools/recall-tools.js.map +1 -1
  119. package/dist/tools/runbook-tools.d.ts +15 -58
  120. package/dist/tools/runbook-tools.d.ts.map +1 -1
  121. package/dist/tools/runbook-tools.js.map +1 -1
  122. package/dist/tools/types.d.ts +1 -1
  123. package/package.json +18 -17
  124. package/src/conflict/index.ts +29 -0
  125. package/src/conflict/locale-packs/en.ts +142 -0
  126. package/src/conflict/locale-packs/index.ts +17 -0
  127. package/src/conflict/locale-packs/types.ts +138 -0
  128. package/src/conflict/pipeline.ts +371 -0
  129. package/src/conflict/stages/helpers.ts +65 -0
  130. package/src/conflict/stages/stage1-exact-dedup.ts +40 -0
  131. package/src/conflict/stages/stage2-embedding-three-zone.ts +54 -0
  132. package/src/conflict/stages/stage3-heuristic-regex.ts +51 -0
  133. package/src/conflict/stages/stage4-subject-predicate.ts +46 -0
  134. package/src/conflict/stages/stage5-defer-to-deep.ts +34 -0
  135. package/src/conflict/types.ts +263 -0
  136. package/src/consolidator/budget.ts +312 -0
  137. package/src/consolidator/decay.ts +246 -0
  138. package/src/consolidator/dlq.ts +61 -0
  139. package/src/consolidator/errors.ts +87 -0
  140. package/src/consolidator/idempotency.ts +27 -0
  141. package/src/consolidator/index.ts +269 -0
  142. package/src/consolidator/lock.ts +141 -0
  143. package/src/consolidator/noise-filter.ts +235 -0
  144. package/src/consolidator/phases/deep.ts +308 -0
  145. package/src/consolidator/phases/induce.ts +423 -0
  146. package/src/consolidator/phases/learned-context.ts +233 -0
  147. package/src/consolidator/phases/light.ts +166 -0
  148. package/src/consolidator/phases/reflect.ts +504 -0
  149. package/src/consolidator/phases/standard.ts +1002 -0
  150. package/src/consolidator/reconcile.ts +273 -0
  151. package/src/consolidator/runtime.ts +1049 -0
  152. package/src/consolidator/scheduler.ts +182 -0
  153. package/src/consolidator/triggers.ts +134 -0
  154. package/src/consolidator/types.ts +622 -0
  155. package/src/context-engine/annotations.ts +161 -0
  156. package/src/context-engine/auto-recall.ts +92 -0
  157. package/src/context-engine/compaction/clear-tool-results.ts +232 -0
  158. package/src/context-engine/compaction/compactor.ts +403 -0
  159. package/src/context-engine/compaction/hooks/reanchor-persona-block.ts +55 -0
  160. package/src/context-engine/compaction/hooks/reanchor-pinned-facts.ts +66 -0
  161. package/src/context-engine/compaction/hooks/reanchor-project-rules.ts +57 -0
  162. package/src/context-engine/compaction/hooks/reanchor-recent-results.ts +116 -0
  163. package/src/context-engine/compaction/hooks/types.ts +68 -0
  164. package/src/context-engine/compaction/index.ts +60 -0
  165. package/src/context-engine/compaction/templates/marker.ts +33 -0
  166. package/src/context-engine/compaction/templates/summary-9-section.ts +223 -0
  167. package/src/context-engine/compaction/thresholds.ts +107 -0
  168. package/src/context-engine/compaction/types.ts +255 -0
  169. package/src/context-engine/engine.ts +970 -0
  170. package/src/context-engine/index.ts +118 -0
  171. package/src/context-engine/io-types.ts +162 -0
  172. package/src/context-engine/locale-packs/en.ts +107 -0
  173. package/src/context-engine/locale-packs/index.ts +19 -0
  174. package/src/context-engine/locale-packs/resolver.ts +197 -0
  175. package/src/context-engine/locale-packs/types.ts +177 -0
  176. package/src/context-engine/metadata.ts +114 -0
  177. package/src/context-engine/preambles/inbound-en.ts +19 -0
  178. package/src/context-engine/privacy-filter.ts +190 -0
  179. package/src/context-engine/templates/base-en.ts +19 -0
  180. package/src/context-engine/templates/composer.ts +91 -0
  181. package/src/context-engine/token-budget.ts +319 -0
  182. package/src/context-engine/token-counter.ts +157 -0
  183. package/src/errors/index.ts +273 -0
  184. package/src/facade.ts +750 -0
  185. package/src/graph/entity-resolver.ts +364 -0
  186. package/src/graph/index.ts +24 -0
  187. package/src/index.ts +259 -0
  188. package/src/internal/contextualize.ts +173 -0
  189. package/src/internal/embedder-binding.ts +53 -0
  190. package/src/internal/envelope.ts +70 -0
  191. package/src/internal/id.ts +23 -0
  192. package/src/internal/injection-heuristics.ts +0 -0
  193. package/src/internal/llm-json.ts +38 -0
  194. package/src/internal/spans.ts +35 -0
  195. package/src/internal/storage-adapter.ts +963 -0
  196. package/src/memory-interface.ts +158 -0
  197. package/src/migration/embedder-migration.ts +237 -0
  198. package/src/migration/index.ts +13 -0
  199. package/src/search/explain.ts +123 -0
  200. package/src/search/fit-weights.ts +109 -0
  201. package/src/search/graph-ppr.ts +38 -0
  202. package/src/search/index.ts +55 -0
  203. package/src/search/iterative.ts +658 -0
  204. package/src/search/query-transform.ts +285 -0
  205. package/src/search/rrf.ts +225 -0
  206. package/src/search/trust.ts +55 -0
  207. package/src/search/types.ts +50 -0
  208. package/src/tiers/episodic-memory.ts +463 -0
  209. package/src/tiers/index.ts +50 -0
  210. package/src/tiers/insight-memory.ts +208 -0
  211. package/src/tiers/procedural-memory.ts +482 -0
  212. package/src/tiers/semantic-memory.ts +1729 -0
  213. package/src/tiers/session-memory.ts +271 -0
  214. package/src/tiers/shared-memory.ts +62 -0
  215. package/src/tiers/working-memory.ts +368 -0
  216. package/src/tools/block-tools.ts +172 -0
  217. package/src/tools/fact-tools.ts +473 -0
  218. package/src/tools/index.ts +109 -0
  219. package/src/tools/recall-tools.ts +303 -0
  220. package/src/tools/runbook-tools.ts +107 -0
  221. package/src/tools/taint.ts +39 -0
  222. package/src/tools/types.ts +37 -0
  223. package/dist/conflict/locale-packs/index.js +0 -4
  224. package/dist/context-engine/compaction/index.js +0 -10
  225. package/dist/context-engine/index.d.ts.map +0 -1
  226. package/dist/context-engine/index.js +0 -25
  227. package/dist/context-engine/locale-packs/index.js +0 -4
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Eleven memory tools registered with `@graphorin/tools` by the
3
+ * `createMemory()` facade - plus an opt-in twelfth, `deep_recall` (P2-4),
4
+ * appended only when iterative retrieval is configured. Each factory
5
+ * takes a {@link MemoryToolDeps} bundle so consumers can scope the tool
6
+ * surface (per-tier ACL, scope resolver, etc.) without rebuilding the
7
+ * underlying memory facade.
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+
12
+ import type { Tool } from '@graphorin/core';
13
+ import {
14
+ createBlockAppendTool,
15
+ createBlockReplaceTool,
16
+ createBlockRethinkTool,
17
+ } from './block-tools.js';
18
+ import {
19
+ createFactForgetTool,
20
+ createFactHistoryTool,
21
+ createFactRememberTool,
22
+ createFactSearchTool,
23
+ createFactSupersedeTool,
24
+ createFactValidateTool,
25
+ } from './fact-tools.js';
26
+ import {
27
+ createConversationSearchTool,
28
+ createDeepRecallTool,
29
+ createRecallEpisodesTool,
30
+ } from './recall-tools.js';
31
+ import { createRunbookSearchTool } from './runbook-tools.js';
32
+ import type { MemoryToolDeps } from './types.js';
33
+
34
+ export {
35
+ createBlockAppendTool,
36
+ createBlockReplaceTool,
37
+ createBlockRethinkTool,
38
+ } from './block-tools.js';
39
+ export {
40
+ createFactForgetTool,
41
+ createFactHistoryTool,
42
+ createFactRememberTool,
43
+ createFactSearchTool,
44
+ createFactSupersedeTool,
45
+ createFactValidateTool,
46
+ } from './fact-tools.js';
47
+ export {
48
+ createConversationSearchTool,
49
+ createDeepRecallTool,
50
+ createRecallEpisodesTool,
51
+ } from './recall-tools.js';
52
+ export { createRunbookSearchTool } from './runbook-tools.js';
53
+ export type { MemoryToolDeps, ScopeResolver } from './types.js';
54
+
55
+ /**
56
+ * Options for {@link buildMemoryTools}.
57
+ *
58
+ * @stable
59
+ */
60
+ export interface BuildMemoryToolsOptions {
61
+ /**
62
+ * Append the gated `deep_recall` tool (P2-4) as a twelfth tool. The
63
+ * facade sets this only when `iterativeRetrieval` is configured, so the
64
+ * default tool surface stays at the canonical eleven. Default `false`.
65
+ */
66
+ readonly includeDeepRecall?: boolean;
67
+ /**
68
+ * Append the gated `runbook_search` tool (D3). The facade sets this
69
+ * only when `createMemory({ runbookSearch: true })` opts in, so the
70
+ * default tool surface is unchanged. Default `false`.
71
+ */
72
+ readonly includeRunbookSearch?: boolean;
73
+ }
74
+
75
+ /**
76
+ * Build the canonical eleven-memory-tool array. Order is stable -
77
+ * consumers can rely on the indices for snapshot tests. `fact_history`
78
+ * (P0-2) and `fact_validate` (P1-4) are appended last so the original
79
+ * nine indices are unchanged. With `{ includeDeepRecall: true }` the
80
+ * gated `deep_recall` tool (P2-4) is appended as a twelfth, after the
81
+ * stable eleven.
82
+ *
83
+ * @stable
84
+ */
85
+ export function buildMemoryTools(
86
+ deps: MemoryToolDeps,
87
+ options: BuildMemoryToolsOptions = {},
88
+ ): ReadonlyArray<Tool> {
89
+ const tools: Tool[] = [
90
+ createBlockAppendTool(deps) as Tool,
91
+ createBlockReplaceTool(deps) as Tool,
92
+ createBlockRethinkTool(deps) as Tool,
93
+ createFactRememberTool(deps) as Tool,
94
+ createFactSearchTool(deps) as Tool,
95
+ createFactSupersedeTool(deps) as Tool,
96
+ createFactForgetTool(deps) as Tool,
97
+ createRecallEpisodesTool(deps) as Tool,
98
+ createConversationSearchTool(deps) as Tool,
99
+ createFactHistoryTool(deps) as Tool,
100
+ createFactValidateTool(deps) as Tool,
101
+ ];
102
+ if (options.includeDeepRecall === true) {
103
+ tools.push(createDeepRecallTool(deps) as Tool);
104
+ }
105
+ if (options.includeRunbookSearch === true) {
106
+ tools.push(createRunbookSearchTool(deps) as Tool);
107
+ }
108
+ return Object.freeze(tools);
109
+ }
@@ -0,0 +1,303 @@
1
+ import type { Tool } from '@graphorin/core';
2
+ import { toolReturn } from '@graphorin/core';
3
+ import { tool } from '@graphorin/tools';
4
+ import { z } from 'zod';
5
+ import { recallTaint } from './taint.js';
6
+ import type { MemoryToolDeps } from './types.js';
7
+
8
+ const recallEpisodesInputSchema = z.object({
9
+ query: z.string().min(1).max(1024),
10
+ topK: z.number().int().positive().max(20).optional(),
11
+ dateRange: z
12
+ .object({
13
+ from: z.string().datetime().optional(),
14
+ to: z.string().datetime().optional(),
15
+ })
16
+ .optional(),
17
+ });
18
+ const recallEpisodesOutputSchema = z.object({
19
+ episodes: z.array(
20
+ z.object({
21
+ episodeId: z.string(),
22
+ summary: z.string(),
23
+ score: z.number(),
24
+ startedAt: z.string(),
25
+ endedAt: z.string(),
26
+ /** Trust-provenance tag (MST-10) - synthesized episodes say so. */
27
+ provenance: z.string().optional(),
28
+ }),
29
+ ),
30
+ });
31
+
32
+ /** W-013: explicit interfaces (see fact-tools.ts) - no zod generics in d.ts. */
33
+ export interface RecallEpisodesInput {
34
+ query: string;
35
+ topK?: number | undefined;
36
+ dateRange?: { from?: string | undefined; to?: string | undefined } | undefined;
37
+ }
38
+ export interface RecallEpisodeHit {
39
+ episodeId: string;
40
+ summary: string;
41
+ score: number;
42
+ startedAt: string;
43
+ endedAt: string;
44
+ provenance?: string | undefined;
45
+ }
46
+ export interface RecallEpisodesOutput {
47
+ episodes: RecallEpisodeHit[];
48
+ }
49
+
50
+ const conversationSearchInputSchema = z.object({
51
+ query: z.string().min(1).max(1024),
52
+ topK: z.number().int().positive().max(20).optional(),
53
+ });
54
+ const conversationSearchOutputSchema = z.object({
55
+ matches: z.array(
56
+ z.object({
57
+ messageId: z.string(),
58
+ score: z.number(),
59
+ }),
60
+ ),
61
+ });
62
+
63
+ export interface ConversationSearchInput {
64
+ query: string;
65
+ topK?: number | undefined;
66
+ }
67
+ export interface ConversationSearchOutput {
68
+ matches: Array<{ messageId: string; score: number }>;
69
+ }
70
+
71
+ const deepRecallSensitivityEnum = z.enum(['public', 'internal', 'secret']);
72
+ const deepRecallInputSchema = z.object({
73
+ query: z.string().min(1).max(1024),
74
+ topK: z.number().int().positive().max(50).optional(),
75
+ maxIterations: z.number().int().min(1).max(5).optional(),
76
+ asOf: z.string().datetime().optional(),
77
+ });
78
+ const deepRecallOutputSchema = z.object({
79
+ hits: z.array(
80
+ z.object({
81
+ factId: z.string(),
82
+ text: z.string(),
83
+ score: z.number(),
84
+ sensitivity: deepRecallSensitivityEnum,
85
+ /** Trust-provenance tag (MST-10) - synthesized facts say so. */
86
+ provenance: z.string().optional(),
87
+ /** Closed validity end (only surfaces on `asOf` reads). */
88
+ validTo: z.string().optional(),
89
+ /** Id of the fact that superseded this one, when any. */
90
+ supersededBy: z.string().optional(),
91
+ }),
92
+ ),
93
+ sufficient: z.boolean(),
94
+ abstained: z.boolean(),
95
+ /**
96
+ * Whether the grader actually judged sufficiency
97
+ * (memory-retrieval-02). When `false`, `sufficient: true` is a
98
+ * default, not a verdict.
99
+ */
100
+ graded: z.boolean(),
101
+ iterations: z.number().int(),
102
+ });
103
+
104
+ export interface DeepRecallInput {
105
+ query: string;
106
+ topK?: number | undefined;
107
+ maxIterations?: number | undefined;
108
+ asOf?: string | undefined;
109
+ }
110
+ export interface DeepRecallHit {
111
+ factId: string;
112
+ text: string;
113
+ score: number;
114
+ sensitivity: 'public' | 'internal' | 'secret';
115
+ provenance?: string | undefined;
116
+ validTo?: string | undefined;
117
+ supersededBy?: string | undefined;
118
+ }
119
+ export interface DeepRecallOutput {
120
+ hits: DeepRecallHit[];
121
+ sufficient: boolean;
122
+ abstained: boolean;
123
+ graded: boolean;
124
+ iterations: number;
125
+ }
126
+
127
+ // W-013 parity gate (compile-time only, erased from the build and the
128
+ // d.ts): each explicit interface must stay MUTUALLY assignable with its
129
+ // schema's inference - a drifted transcription fails `tsc` right here.
130
+ type W013Equals<A, B> = A extends B ? (B extends A ? true : false) : false;
131
+ type W013Assert<T extends true> = T;
132
+ type _W013Check1 = W013Assert<
133
+ W013Equals<RecallEpisodesInput, z.infer<typeof recallEpisodesInputSchema>>
134
+ >;
135
+ type _W013Check2 = W013Assert<
136
+ W013Equals<RecallEpisodesOutput, z.infer<typeof recallEpisodesOutputSchema>>
137
+ >;
138
+ type _W013Check3 = W013Assert<
139
+ W013Equals<ConversationSearchInput, z.infer<typeof conversationSearchInputSchema>>
140
+ >;
141
+ type _W013Check4 = W013Assert<
142
+ W013Equals<ConversationSearchOutput, z.infer<typeof conversationSearchOutputSchema>>
143
+ >;
144
+ type _W013Check5 = W013Assert<W013Equals<DeepRecallInput, z.infer<typeof deepRecallInputSchema>>>;
145
+ type _W013Check6 = W013Assert<W013Equals<DeepRecallOutput, z.infer<typeof deepRecallOutputSchema>>>;
146
+
147
+ /**
148
+ * `recall_episodes` - triple-signal episode retrieval (recency ×
149
+ * relevance × importance).
150
+ *
151
+ * @stable
152
+ */
153
+ export function createRecallEpisodesTool(
154
+ deps: MemoryToolDeps,
155
+ ): Tool<RecallEpisodesInput, RecallEpisodesOutput> {
156
+ return tool<RecallEpisodesInput, RecallEpisodesOutput>({
157
+ name: 'recall_episodes',
158
+ description:
159
+ "Recall summarized episodes (multi-message stretches of past activity) matching a natural-language query. Combines vector relevance, time-decay recency, and the per-episode importance score. Use for long-horizon recall ('the last time we discussed X').",
160
+ inputSchema: recallEpisodesInputSchema,
161
+ outputSchema: recallEpisodesOutputSchema,
162
+ sideEffectClass: 'read-only',
163
+ sandboxPolicy: 'none',
164
+ sensitivity: 'internal',
165
+ memoryGuardTier: 'pure',
166
+ tags: ['memory', 'episodic'],
167
+ async execute(input, ctx) {
168
+ const scope = await deps.resolveScope(ctx);
169
+ const dateRange =
170
+ input.dateRange !== undefined
171
+ ? {
172
+ ...(input.dateRange.from !== undefined ? { from: input.dateRange.from } : {}),
173
+ ...(input.dateRange.to !== undefined ? { to: input.dateRange.to } : {}),
174
+ }
175
+ : undefined;
176
+ const hits = await deps.episodic.search(scope, input.query, {
177
+ ...(input.topK !== undefined ? { topK: input.topK } : {}),
178
+ ...(dateRange !== undefined ? { dateRange } : {}),
179
+ signal: ctx.signal,
180
+ });
181
+ const output = {
182
+ episodes: hits.map((hit) => ({
183
+ episodeId: hit.record.id,
184
+ summary: hit.record.summary,
185
+ score: hit.score,
186
+ startedAt: hit.record.startedAt,
187
+ endedAt: hit.record.endedAt,
188
+ // MST-10: surface origin so a consumer can tell a synthesized
189
+ // (consolidator-extracted) episode from a first-party record -
190
+ // recalled text re-enters the model as trusted tool output.
191
+ ...(hit.record.provenance !== undefined ? { provenance: hit.record.provenance } : {}),
192
+ })),
193
+ };
194
+ // C6: recalled foreign-provenance / quarantined episodes re-arm the
195
+ // taint ledger (the cross-session poisoning leg).
196
+ const taint = recallTaint(hits.map((h) => h.record));
197
+ return taint === undefined ? output : toolReturn({ output, taint });
198
+ },
199
+ });
200
+ }
201
+
202
+ /**
203
+ * `conversation_search` - FTS5 search over the active session
204
+ * messages.
205
+ *
206
+ * @stable
207
+ */
208
+ export function createConversationSearchTool(
209
+ deps: MemoryToolDeps,
210
+ ): Tool<ConversationSearchInput, ConversationSearchOutput> {
211
+ return tool<ConversationSearchInput, ConversationSearchOutput>({
212
+ name: 'conversation_search',
213
+ description:
214
+ 'Search the active session message log by natural-language query. Returns up to `topK` matched messages with their stable id and BM25 score.',
215
+ inputSchema: conversationSearchInputSchema,
216
+ outputSchema: conversationSearchOutputSchema,
217
+ sideEffectClass: 'read-only',
218
+ sandboxPolicy: 'none',
219
+ sensitivity: 'internal',
220
+ memoryGuardTier: 'pure',
221
+ tags: ['memory', 'session'],
222
+ async execute(input, ctx) {
223
+ const scope = await deps.resolveScope(ctx);
224
+ const hits = await deps.session.search(scope, input.query, {
225
+ ...(input.topK !== undefined ? { topK: input.topK } : {}),
226
+ signal: ctx.signal,
227
+ });
228
+ return {
229
+ matches: hits.map((hit) => ({
230
+ messageId: hit.record.id,
231
+ score: hit.score,
232
+ })),
233
+ };
234
+ },
235
+ });
236
+ }
237
+
238
+ /**
239
+ * `deep_recall` - gated, multi-pass ("deep") recall over the user's
240
+ * factual memory for HARD questions (P2-4). A local difficulty gate keeps
241
+ * simple lookups single-shot; only queries judged hard trigger a
242
+ * grade-and-reformulate loop (bounded by `maxIterations`, hard-capped at
243
+ * 5), widening to one-hop graph expansion on reformulation passes. The
244
+ * output reports `abstained: true` when memory was insufficient even
245
+ * after reformulating - the agent should then say it lacks the
246
+ * information rather than guess. Registered only when the facade is
247
+ * created with `iterativeRetrieval`; otherwise it degrades to a single
248
+ * pass, so prefer the cheaper `fact_search` for ordinary lookups.
249
+ *
250
+ * @stable
251
+ */
252
+ export function createDeepRecallTool(
253
+ deps: MemoryToolDeps,
254
+ ): Tool<DeepRecallInput, DeepRecallOutput> {
255
+ return tool<DeepRecallInput, DeepRecallOutput>({
256
+ name: 'deep_recall',
257
+ description:
258
+ "Multi-pass ('deep') recall over the user's long-term factual memory for HARD multi-hop or temporal questions one search can't answer (e.g. 'who recommended the book the person I met in Tbilisi mentioned?'). A difficulty gate keeps simple lookups single-shot; hard questions trigger a bounded grade-and-reformulate loop. If `abstained` is true the memory was insufficient even after reformulating - tell the user you don't have enough stored to answer and DO NOT guess. Prefer the cheaper fact_search for ordinary lookups.",
259
+ inputSchema: deepRecallInputSchema,
260
+ outputSchema: deepRecallOutputSchema,
261
+ sideEffectClass: 'read-only',
262
+ sandboxPolicy: 'none',
263
+ sensitivity: 'internal',
264
+ memoryGuardTier: 'pure',
265
+ tags: ['memory', 'semantic'],
266
+ async execute(input, ctx) {
267
+ const scope = await deps.resolveScope(ctx);
268
+ const result = await deps.semantic.searchIterative(scope, input.query, {
269
+ ...(input.topK !== undefined ? { topK: input.topK } : {}),
270
+ ...(input.maxIterations !== undefined ? { maxIterations: input.maxIterations } : {}),
271
+ ...(input.asOf !== undefined ? { asOf: input.asOf } : {}),
272
+ // memory-retrieval-02: the model choosing deep_recall over
273
+ // fact_search IS the hardness signal - the local heuristic gate
274
+ // rejected the tool's own documented multi-hop examples
275
+ // (W_MULTI_HOP 0.4 < threshold 0.5) and is English-only. The
276
+ // cap + grader stop conditions still bound cost.
277
+ forceHard: true,
278
+ signal: ctx.signal,
279
+ });
280
+ const output = {
281
+ hits: result.hits.map((hit) => ({
282
+ factId: hit.record.id,
283
+ text: hit.record.text,
284
+ score: hit.score,
285
+ sensitivity: hit.record.sensitivity,
286
+ // MST-10: origin annotation, mirroring fact_search.
287
+ ...(hit.record.provenance !== undefined ? { provenance: hit.record.provenance } : {}),
288
+ ...(hit.record.validTo !== undefined ? { validTo: hit.record.validTo } : {}),
289
+ ...(hit.record.supersededBy !== undefined
290
+ ? { supersededBy: hit.record.supersededBy }
291
+ : {}),
292
+ })),
293
+ sufficient: result.sufficient,
294
+ abstained: result.abstained,
295
+ graded: result.graded,
296
+ iterations: result.iterations,
297
+ };
298
+ // C6: mirror fact_search - recalled poisoned content re-arms the ledger.
299
+ const taint = recallTaint(result.hits.map((h) => h.record));
300
+ return taint === undefined ? output : toolReturn({ output, taint });
301
+ },
302
+ });
303
+ }
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Runbook tool (D3) - gated content recall over procedural memory.
3
+ * `runbook_search` finds validated procedures whose text / steps match
4
+ * a task description and returns them **whole** (title line, numbered
5
+ * steps, variables, success criteria), so the model can follow a known
6
+ * workflow file-style instead of re-deriving it. Registered only when
7
+ * the facade opts in (`createMemory({ runbookSearch: true })`) - the
8
+ * default tool surface is unchanged.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+
13
+ import type { Tool } from '@graphorin/core';
14
+ import { tool } from '@graphorin/tools';
15
+ import { z } from 'zod';
16
+ import type { MemoryToolDeps } from './types.js';
17
+
18
+ const runbookSearchInputSchema = z.object({
19
+ query: z.string().min(1).max(512),
20
+ topK: z.number().int().min(1).max(20).optional(),
21
+ });
22
+ const runbookSearchOutputSchema = z.object({
23
+ procedures: z.array(
24
+ z.object({
25
+ id: z.string(),
26
+ text: z.string(),
27
+ steps: z.array(z.string()).optional(),
28
+ variables: z.array(z.string()).optional(),
29
+ successCriteria: z.array(z.string()).optional(),
30
+ priority: z.number(),
31
+ score: z.number(),
32
+ }),
33
+ ),
34
+ });
35
+
36
+ /** W-013: explicit interfaces (see fact-tools.ts) - no zod generics in d.ts. */
37
+ export interface RunbookSearchInput {
38
+ query: string;
39
+ topK?: number | undefined;
40
+ }
41
+ export interface RunbookProcedureHit {
42
+ id: string;
43
+ text: string;
44
+ steps?: string[] | undefined;
45
+ variables?: string[] | undefined;
46
+ successCriteria?: string[] | undefined;
47
+ priority: number;
48
+ score: number;
49
+ }
50
+ export interface RunbookSearchOutput {
51
+ procedures: RunbookProcedureHit[];
52
+ }
53
+
54
+ // W-013 parity gate (compile-time only, erased from the build and the
55
+ // d.ts): each explicit interface must stay MUTUALLY assignable with its
56
+ // schema's inference - a drifted transcription fails `tsc` right here.
57
+ type W013Equals<A, B> = A extends B ? (B extends A ? true : false) : false;
58
+ type W013Assert<T extends true> = T;
59
+ type _W013Check1 = W013Assert<
60
+ W013Equals<RunbookSearchInput, z.infer<typeof runbookSearchInputSchema>>
61
+ >;
62
+ type _W013Check2 = W013Assert<
63
+ W013Equals<RunbookSearchOutput, z.infer<typeof runbookSearchOutputSchema>>
64
+ >;
65
+
66
+ /**
67
+ * `runbook_search` - find validated procedures matching a task
68
+ * description. Quarantined (unvalidated induced) procedures never
69
+ * surface here: they must not drive actions until validated.
70
+ *
71
+ * @stable
72
+ */
73
+ export function createRunbookSearchTool(
74
+ deps: MemoryToolDeps,
75
+ ): Tool<RunbookSearchInput, RunbookSearchOutput> {
76
+ return tool<RunbookSearchInput, RunbookSearchOutput>({
77
+ name: 'runbook_search',
78
+ description:
79
+ 'Find a stored, validated procedure ("runbook") matching the task at hand - e.g. "deploy the docs site" or "rotate the API key". Returns whole procedures with their numbered steps, variables, and success criteria so you can follow a known-good workflow instead of improvising. Use BEFORE attempting a multi-step operational task the user may have done with you previously.',
80
+ inputSchema: runbookSearchInputSchema,
81
+ outputSchema: runbookSearchOutputSchema,
82
+ sideEffectClass: 'read-only',
83
+ sandboxPolicy: 'none',
84
+ sensitivity: 'internal',
85
+ memoryGuardTier: 'pure',
86
+ tags: ['memory', 'procedural'],
87
+ async execute(input, ctx) {
88
+ const scope = await deps.resolveScope(ctx);
89
+ const hits = await deps.procedural.search(scope, input.query, {
90
+ ...(input.topK !== undefined ? { topK: input.topK } : {}),
91
+ });
92
+ return {
93
+ procedures: hits.map((hit) => ({
94
+ id: hit.record.id,
95
+ text: hit.record.text,
96
+ ...(hit.record.steps !== undefined ? { steps: [...hit.record.steps] } : {}),
97
+ ...(hit.record.variables !== undefined ? { variables: [...hit.record.variables] } : {}),
98
+ ...(hit.record.successCriteria !== undefined
99
+ ? { successCriteria: [...hit.record.successCriteria] }
100
+ : {}),
101
+ priority: hit.record.priority,
102
+ score: hit.score,
103
+ })),
104
+ };
105
+ },
106
+ });
107
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * C6: taint override for memory-recall tool results. The recall tools are
3
+ * first-party (`sideEffectClass: 'read-only'`), so the data-flow ledger
4
+ * would derive their outputs as trusted - but the CONTENT they return can
5
+ * be quarantined or foreign-provenance memory written in an earlier
6
+ * session (the cross-session poisoning leg). This helper computes the
7
+ * `ToolReturn.taint` override that re-arms the ledger at recall: recalled
8
+ * poisoned content is recorded as untrusted spans, so the verbatim probe
9
+ * and the trifecta/derived gates see it exactly like fresh untrusted
10
+ * input.
11
+ *
12
+ * @packageDocumentation
13
+ */
14
+
15
+ import { isForeignProvenance } from '../search/trust.js';
16
+
17
+ /** Minimal record surface the helper inspects. */
18
+ export interface RecalledItemLike {
19
+ readonly provenance?: string | null;
20
+ readonly status?: string;
21
+ }
22
+
23
+ /**
24
+ * Compute the taint override for a recalled item set: untrusted when ANY
25
+ * item is quarantined or foreign-provenance; `undefined` when all items
26
+ * are first-party active (the common case - zero overhead, no override).
27
+ *
28
+ * @stable
29
+ */
30
+ export function recallTaint(
31
+ items: ReadonlyArray<RecalledItemLike>,
32
+ ): { readonly untrusted: true; readonly sourceKind: 'memory-recall' } | undefined {
33
+ for (const item of items) {
34
+ if (item.status === 'quarantined' || isForeignProvenance(item.provenance)) {
35
+ return { untrusted: true, sourceKind: 'memory-recall' };
36
+ }
37
+ }
38
+ return undefined;
39
+ }
@@ -0,0 +1,37 @@
1
+ import type { SessionScope } from '@graphorin/core';
2
+ import type { EpisodicMemory } from '../tiers/episodic-memory.js';
3
+ import type { ProceduralMemory } from '../tiers/procedural-memory.js';
4
+ import type { SemanticMemory } from '../tiers/semantic-memory.js';
5
+ import type { SessionMemory } from '../tiers/session-memory.js';
6
+ import type { SharedMemory } from '../tiers/shared-memory.js';
7
+ import type { WorkingMemory } from '../tiers/working-memory.js';
8
+
9
+ /**
10
+ * Resolver that produces the live {@link SessionScope} for the tool
11
+ * call from the surrounding agent run context. The agent runtime
12
+ * (Phase 12) supplies a closure that reads `RunContext` directly;
13
+ * standalone callers can pass a fixed scope.
14
+ *
15
+ * @stable
16
+ */
17
+ export type ScopeResolver = (
18
+ ctx: import('@graphorin/core').ToolExecutionContext<unknown>,
19
+ ) => SessionScope | Promise<SessionScope>;
20
+
21
+ /**
22
+ * Dependency bundle threaded into every memory tool. Exposed
23
+ * separately from the `Tool` surface so the executor can scope
24
+ * the dependencies per call without leaking the wider memory facade
25
+ * into the tool author surface.
26
+ *
27
+ * @stable
28
+ */
29
+ export interface MemoryToolDeps {
30
+ readonly working: WorkingMemory;
31
+ readonly session: SessionMemory;
32
+ readonly episodic: EpisodicMemory;
33
+ readonly semantic: SemanticMemory;
34
+ readonly procedural: ProceduralMemory;
35
+ readonly shared: SharedMemory;
36
+ readonly resolveScope: ScopeResolver;
37
+ }
@@ -1,4 +0,0 @@
1
- import { defineLocalePack, evaluateMarkers } from "./types.js";
2
- import { enLocalePack } from "./en.js";
3
-
4
- export { };
@@ -1,10 +0,0 @@
1
- import { CLEARED_TOOL_RESULT_MARKER, DEFAULT_KEEP_TOOL_USES, clearOldToolResults } from "./clear-tool-results.js";
2
- import { DEFAULT_SUMMARIZER_DUMP_CHAR_BUDGET, SUMMARY_TEMPLATE_NAME, SUMMARY_TEMPLATE_VERSION, buildSummarizerPrompt, renderFinalSummary } from "./templates/summary-9-section.js";
3
- import { DEFAULT_PRESERVE_RECENT_TURNS, executeCompaction } from "./compactor.js";
4
- import { reanchorPersonaBlock } from "./hooks/reanchor-persona-block.js";
5
- import { reanchorPinnedFacts } from "./hooks/reanchor-pinned-facts.js";
6
- import { reanchorProjectRules } from "./hooks/reanchor-project-rules.js";
7
- import { reanchorRecentResults } from "./hooks/reanchor-recent-results.js";
8
- import { DEFAULT_RESERVED_FOR_COMPACTION, DEFAULT_RESERVED_FOR_RESPONSE, DEFAULT_THRESHOLD_RATIO, resolveAutoCompactionDefault, resolveTriggerThreshold } from "./thresholds.js";
9
-
10
- export { };
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/context-engine/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoJA;;;;;;;;UA/BiB,mBAAA;;;;;;;;;;;;wBAYO;;;;;;;UAQP,cAAA;;;wCAGuB;;;;;;;KAQ5B,YAAA,GAAY,gBAAA,CAA6B,YAAA"}
@@ -1,25 +0,0 @@
1
- import { CONTENT_ORIGIN_ATTR, INBOUND_TRUST_ATTR, NON_INBOUND_ORIGINS, annotate, shouldFireInboundPreamble, toSpanAttributes } from "./annotations.js";
2
- import { defaultLocaleHeuristicStrategy, defineAutoRecallStrategy } from "./auto-recall.js";
3
- import { HEURISTIC_TOKEN_COUNTER, adaptTokenCounter, countMessageTokens, renderMessageText } from "./token-counter.js";
4
- import { CLEARED_TOOL_RESULT_MARKER, DEFAULT_KEEP_TOOL_USES, clearOldToolResults } from "./compaction/clear-tool-results.js";
5
- import { DEFAULT_SUMMARIZER_DUMP_CHAR_BUDGET, SUMMARY_TEMPLATE_NAME, SUMMARY_TEMPLATE_VERSION, buildSummarizerPrompt, renderFinalSummary } from "./compaction/templates/summary-9-section.js";
6
- import { DEFAULT_PRESERVE_RECENT_TURNS, executeCompaction } from "./compaction/compactor.js";
7
- import { reanchorPersonaBlock } from "./compaction/hooks/reanchor-persona-block.js";
8
- import { reanchorPinnedFacts } from "./compaction/hooks/reanchor-pinned-facts.js";
9
- import { reanchorProjectRules } from "./compaction/hooks/reanchor-project-rules.js";
10
- import { reanchorRecentResults } from "./compaction/hooks/reanchor-recent-results.js";
11
- import { DEFAULT_RESERVED_FOR_COMPACTION, DEFAULT_RESERVED_FOR_RESPONSE, DEFAULT_THRESHOLD_RATIO, resolveAutoCompactionDefault, resolveTriggerThreshold } from "./compaction/thresholds.js";
12
- import "./compaction/index.js";
13
- import { enLocalePack } from "./locale-packs/en.js";
14
- import { defineContextLocalePack } from "./locale-packs/types.js";
15
- import "./locale-packs/index.js";
16
- import { _getLocaleFallbackWarningsForTesting, _resetLocaleFallbackWarningsForTesting, resolveLocalePack } from "./locale-packs/resolver.js";
17
- import { gatherMemoryMetadata, renderMetadataBlock } from "./metadata.js";
18
- import { decide, effectiveAcceptsSensitivity, partition } from "./privacy-filter.js";
19
- import { composeInboundPreamble, composeLayer1, composeLayer2, composeLayer4Skills } from "./templates/composer.js";
20
- import { DEFAULT_LAYER_PRIORITY, allocate, truncateToTokens } from "./token-budget.js";
21
- import { createContextEngine } from "./engine.js";
22
- import { INBOUND_SANITIZATION_PREAMBLE_EN } from "./preambles/inbound-en.js";
23
- import { BASE_TEMPLATE_EN_FULL, BASE_TEMPLATE_EN_MINIMAL } from "./templates/base-en.js";
24
-
25
- export { };
@@ -1,4 +0,0 @@
1
- import { enLocalePack } from "./en.js";
2
- import { defineContextLocalePack } from "./types.js";
3
-
4
- export { };