@botbotgo/agent-harness 0.0.474 → 0.0.476

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/README.md +3 -1234
  2. package/README.zh.md +3 -1191
  3. package/dist/acp.js +1 -1
  4. package/dist/api.js +1 -404
  5. package/dist/benchmark/checkpoint-resume-cost-benchmark.js +1 -55
  6. package/dist/benchmark/deepagent-local-model-benchmark.js +2 -35
  7. package/dist/benchmark/upstream-runtime-ab-benchmark.js +1 -179
  8. package/dist/cli/chat-interactive.js +25 -244
  9. package/dist/cli/chat-rendering.js +6 -100
  10. package/dist/cli/chat-stream.js +23 -512
  11. package/dist/cli/chat-ui.js +21 -199
  12. package/dist/cli/chat-workspace.js +2 -210
  13. package/dist/cli/main.js +21 -428
  14. package/dist/cli/managed-service-commands.js +9 -63
  15. package/dist/cli/managed-service.js +2 -137
  16. package/dist/cli/options-init-chat.js +1 -108
  17. package/dist/cli/options-runtime.js +1 -158
  18. package/dist/cli/options-serve.js +1 -282
  19. package/dist/cli/options.js +2 -19
  20. package/dist/cli/process-guards.js +1 -139
  21. package/dist/cli/request-tree.js +7 -296
  22. package/dist/cli/runtime-commands.js +12 -258
  23. package/dist/cli/runtime-output.js +16 -155
  24. package/dist/cli/server-commands.js +16 -270
  25. package/dist/cli/workspace.js +1 -67
  26. package/dist/cli.js +1 -7
  27. package/dist/client/acp.js +1 -1
  28. package/dist/client/in-process.js +1 -67
  29. package/dist/client/index.js +1 -2
  30. package/dist/client/types.js +0 -1
  31. package/dist/client.js +1 -1
  32. package/dist/contracts/core.js +1 -1
  33. package/dist/contracts/runtime-evaluation.js +0 -1
  34. package/dist/contracts/runtime-memory.js +0 -1
  35. package/dist/contracts/runtime-observability.js +0 -1
  36. package/dist/contracts/runtime-requests.js +0 -1
  37. package/dist/contracts/runtime-scheduling.js +0 -1
  38. package/dist/contracts/runtime.js +1 -27
  39. package/dist/contracts/types.js +1 -3
  40. package/dist/contracts/workspace.js +0 -1
  41. package/dist/flow/build-flow-graph.js +1 -50
  42. package/dist/flow/export-mermaid.js +2 -464
  43. package/dist/flow/export-sequence-mermaid.js +2 -325
  44. package/dist/flow/flow-graph-normalization.js +1 -214
  45. package/dist/flow/flow-graph-runtime.js +1 -107
  46. package/dist/flow/flow-graph-upstream.js +1 -494
  47. package/dist/flow/index.js +1 -3
  48. package/dist/flow/types.js +0 -1
  49. package/dist/index.js +1 -5
  50. package/dist/init-project.js +1 -1
  51. package/dist/knowledge/config.js +1 -32
  52. package/dist/knowledge/contracts.js +0 -1
  53. package/dist/knowledge/index.js +1 -2
  54. package/dist/knowledge/module.js +12 -909
  55. package/dist/knowledge/procedural/config.js +1 -125
  56. package/dist/knowledge/procedural/index.js +1 -2
  57. package/dist/knowledge/procedural/manager.js +9 -345
  58. package/dist/mcp.js +1 -2
  59. package/dist/package-version.d.ts +2 -2
  60. package/dist/package-version.js +1 -2
  61. package/dist/persistence/file-store.js +3 -758
  62. package/dist/persistence/sqlite-request-context-store.js +5 -54
  63. package/dist/persistence/sqlite-request-queue-store.js +10 -108
  64. package/dist/persistence/sqlite-runtime.js +1 -86
  65. package/dist/persistence/sqlite-store.js +62 -810
  66. package/dist/persistence/types.js +0 -1
  67. package/dist/projections/presentation.js +37 -206
  68. package/dist/projections/request-events.js +2 -502
  69. package/dist/projections/upstream-events.js +1 -201
  70. package/dist/protocol/a2a/http-discovery.js +1 -178
  71. package/dist/protocol/a2a/http-rpc.js +6 -622
  72. package/dist/protocol/a2a/http.js +1 -138
  73. package/dist/protocol/a2a/task-state.js +3 -317
  74. package/dist/protocol/acp/client.js +8 -294
  75. package/dist/protocol/acp/harness-client.js +1 -218
  76. package/dist/protocol/acp/http.js +5 -130
  77. package/dist/protocol/acp/server.js +1 -310
  78. package/dist/protocol/acp/stdio.js +2 -69
  79. package/dist/protocol/ag-ui/http.js +3 -378
  80. package/dist/protocol/mcp/server.js +1 -428
  81. package/dist/resource/backend/workspace-scoped-backend.js +1 -319
  82. package/dist/resource/isolation.js +1 -237
  83. package/dist/resource/mcp/tool-support.js +3 -296
  84. package/dist/resource/mcp-tool-support.js +1 -2
  85. package/dist/resource/providers/resource-provider.js +1 -215
  86. package/dist/resource/resource-impl.js +1 -3
  87. package/dist/resource/resource-types.js +0 -1
  88. package/dist/resource/resource.js +1 -1
  89. package/dist/resource/sources.js +1 -247
  90. package/dist/resource/tools/function-tool-resolver.js +2 -272
  91. package/dist/runtime/adapter/compat/deepagent-compat.js +1 -29
  92. package/dist/runtime/adapter/compat/openai-compatible.js +1 -55
  93. package/dist/runtime/adapter/direct-builtin-utility.js +2 -90
  94. package/dist/runtime/adapter/flow/execution-context.js +1 -71
  95. package/dist/runtime/adapter/flow/invocation-flow.js +8 -411
  96. package/dist/runtime/adapter/flow/invoke-runtime.js +1 -20
  97. package/dist/runtime/adapter/flow/stream-runtime.js +11 -1395
  98. package/dist/runtime/adapter/invocation-result.js +2 -473
  99. package/dist/runtime/adapter/local-tool-invocation.js +6 -638
  100. package/dist/runtime/adapter/middleware/context-hygiene.js +1 -83
  101. package/dist/runtime/adapter/middleware-assembly.js +5 -477
  102. package/dist/runtime/adapter/model/invocation-request.js +3 -183
  103. package/dist/runtime/adapter/model/message-assembly.js +1 -28
  104. package/dist/runtime/adapter/model/model-providers.js +23 -1089
  105. package/dist/runtime/adapter/model/prompted-json-tool-call-capture.js +1 -40
  106. package/dist/runtime/adapter/model/prompted-json-tool-policy.js +1 -22
  107. package/dist/runtime/adapter/resilience.js +1 -104
  108. package/dist/runtime/adapter/runtime-adapter-support.js +3 -141
  109. package/dist/runtime/adapter/runtime-shell.js +5 -166
  110. package/dist/runtime/adapter/stream-event-projection.js +2 -622
  111. package/dist/runtime/adapter/stream-text-consumption.js +1 -18
  112. package/dist/runtime/adapter/terminal-status.js +2 -67
  113. package/dist/runtime/adapter/tool/builtin-middleware-tools.js +6 -627
  114. package/dist/runtime/adapter/tool/declared-middleware.js +1 -154
  115. package/dist/runtime/adapter/tool/interrupt-policy.js +1 -34
  116. package/dist/runtime/adapter/tool/provider-tool.js +1 -25
  117. package/dist/runtime/adapter/tool/resolved-tool.js +1 -225
  118. package/dist/runtime/adapter/tool/tool-arguments.js +3 -486
  119. package/dist/runtime/adapter/tool/tool-hitl.js +1 -346
  120. package/dist/runtime/adapter/tool/tool-name-mapping.js +1 -128
  121. package/dist/runtime/adapter/tool/tool-output-artifacts.js +2 -88
  122. package/dist/runtime/adapter/tool/tool-replay.js +1 -37
  123. package/dist/runtime/adapter/tool-resolution.js +1 -86
  124. package/dist/runtime/adapter/upstream-configurable-keys.js +1 -2
  125. package/dist/runtime/agent-runtime-adapter.js +60 -2338
  126. package/dist/runtime/agent-runtime-assembly.js +7 -249
  127. package/dist/runtime/env/runtime-env.js +1 -62
  128. package/dist/runtime/harness/background-runtime.js +1 -8
  129. package/dist/runtime/harness/bindings.js +1 -58
  130. package/dist/runtime/harness/events/event-bus.js +1 -16
  131. package/dist/runtime/harness/events/event-sink.js +1 -61
  132. package/dist/runtime/harness/events/events.js +1 -80
  133. package/dist/runtime/harness/events/listener-runtime.js +1 -13
  134. package/dist/runtime/harness/events/runtime-event-operations.js +1 -9
  135. package/dist/runtime/harness/events/streaming.js +1 -100
  136. package/dist/runtime/harness/events/timeline.js +1 -52
  137. package/dist/runtime/harness/public-shapes.js +1 -186
  138. package/dist/runtime/harness/run/artifact-paths.js +1 -15
  139. package/dist/runtime/harness/run/governance.js +1 -295
  140. package/dist/runtime/harness/run/helpers.js +1 -71
  141. package/dist/runtime/harness/run/inspection.js +1 -409
  142. package/dist/runtime/harness/run/operator-overview.js +1 -80
  143. package/dist/runtime/harness/run/queue-diagnostics.js +1 -15
  144. package/dist/runtime/harness/run/recovery.js +1 -162
  145. package/dist/runtime/harness/run/resources.js +1 -60
  146. package/dist/runtime/harness/run/resume.js +1 -56
  147. package/dist/runtime/harness/run/routing.js +1 -48
  148. package/dist/runtime/harness/run/run-lifecycle.js +1 -66
  149. package/dist/runtime/harness/run/run-operations.js +1 -217
  150. package/dist/runtime/harness/run/run-queue.js +1 -43
  151. package/dist/runtime/harness/run/run-slot-acquisition.js +1 -157
  152. package/dist/runtime/harness/run/session-records.js +1 -97
  153. package/dist/runtime/harness/run/start-run.js +1 -120
  154. package/dist/runtime/harness/run/startup-runtime.js +1 -69
  155. package/dist/runtime/harness/run/stream-run.js +8 -1418
  156. package/dist/runtime/harness/run/surface-semantics.js +1 -79
  157. package/dist/runtime/harness/runtime-defaults.js +1 -39
  158. package/dist/runtime/harness/system/boundary-analysis.js +1 -234
  159. package/dist/runtime/harness/system/health-monitor.js +1 -258
  160. package/dist/runtime/harness/system/inventory.js +1 -129
  161. package/dist/runtime/harness/system/mem0-ingestion-sync.js +5 -345
  162. package/dist/runtime/harness/system/policy-engine.js +1 -175
  163. package/dist/runtime/harness/system/runtime-memory-candidates.js +4 -110
  164. package/dist/runtime/harness/system/runtime-memory-consolidation.js +1 -51
  165. package/dist/runtime/harness/system/runtime-memory-manager.js +10 -693
  166. package/dist/runtime/harness/system/runtime-memory-policy.js +1 -155
  167. package/dist/runtime/harness/system/runtime-memory-records.js +11 -577
  168. package/dist/runtime/harness/system/runtime-memory-sync.js +5 -206
  169. package/dist/runtime/harness/system/session-memory-sync.js +3 -113
  170. package/dist/runtime/harness/system/skill-requirements.js +1 -112
  171. package/dist/runtime/harness/system/store.js +9 -365
  172. package/dist/runtime/harness/tool-gateway/index.js +1 -2
  173. package/dist/runtime/harness/tool-gateway/policy.js +1 -45
  174. package/dist/runtime/harness/tool-gateway/validation.js +1 -176
  175. package/dist/runtime/harness/tool-schema.js +1 -3
  176. package/dist/runtime/harness.js +3 -1490
  177. package/dist/runtime/index.js +1 -3
  178. package/dist/runtime/layout/runtime-layout.js +1 -31
  179. package/dist/runtime/maintenance/checkpoint-maintenance.js +2 -178
  180. package/dist/runtime/maintenance/file-checkpoint-saver.js +1 -106
  181. package/dist/runtime/maintenance/runtime-record-maintenance.js +2 -169
  182. package/dist/runtime/maintenance/sqlite-checkpoint-saver.js +4 -289
  183. package/dist/runtime/parsing/output-content.js +10 -550
  184. package/dist/runtime/parsing/output-parsing.js +1 -4
  185. package/dist/runtime/parsing/output-recovery.js +3 -213
  186. package/dist/runtime/parsing/output-tool-args.js +7 -663
  187. package/dist/runtime/parsing/stream-event-parsing.js +3 -362
  188. package/dist/runtime/prompts/runtime-prompts.js +4 -73
  189. package/dist/runtime/scheduling/system-schedule-manager.js +11 -532
  190. package/dist/runtime/skills/skill-metadata.js +1 -197
  191. package/dist/runtime/startup-tracing.js +2 -37
  192. package/dist/runtime/support/compiled-binding.js +1 -290
  193. package/dist/runtime/support/embedding-models.js +1 -118
  194. package/dist/runtime/support/harness-support.js +5 -137
  195. package/dist/runtime/support/llamaindex.js +1 -108
  196. package/dist/runtime/support/runtime-adapter-options.js +1 -29
  197. package/dist/runtime/support/runtime-factories.js +1 -51
  198. package/dist/runtime/support/vector-stores.js +9 -270
  199. package/dist/scaffold/init-project.js +54 -233
  200. package/dist/tooling/extensions.js +1 -311
  201. package/dist/tooling/module-loader.js +1 -55
  202. package/dist/tools.js +1 -176
  203. package/dist/utils/agent-display.js +1 -18
  204. package/dist/utils/bundled-text.js +4 -39
  205. package/dist/utils/compiled-binding.js +1 -33
  206. package/dist/utils/fs.js +2 -45
  207. package/dist/utils/id.js +1 -9
  208. package/dist/utils/message-content.js +1 -30
  209. package/dist/utils/object.js +1 -6
  210. package/dist/workspace/agent-binding-compiler.js +3 -613
  211. package/dist/workspace/compile.js +1 -472
  212. package/dist/workspace/framework-contract-validation.js +2 -322
  213. package/dist/workspace/index.js +1 -1
  214. package/dist/workspace/object-loader-paths.js +1 -71
  215. package/dist/workspace/object-loader-readers.js +1 -187
  216. package/dist/workspace/object-loader.js +1 -754
  217. package/dist/workspace/resource-compilers.js +1 -374
  218. package/dist/workspace/support/agent-capabilities.js +1 -37
  219. package/dist/workspace/support/agent-execution-config.js +1 -44
  220. package/dist/workspace/support/discovery.js +1 -147
  221. package/dist/workspace/support/source-collectors.js +1 -30
  222. package/dist/workspace/support/source-protocols.js +2 -192
  223. package/dist/workspace/support/workspace-ref-utils.js +1 -362
  224. package/dist/workspace/tool-hydration.js +1 -280
  225. package/dist/workspace/validate.js +1 -99
  226. package/dist/workspace/yaml-object-reader.js +1 -285
  227. package/package.json +7 -3
@@ -1,909 +1,12 @@
1
- import { createPersistentId } from "../utils/id.js";
2
- import { findMemoryRecordById, getMemoryRecord, listMemoryRecordsForScopes, persistStructuredMemoryRecords, removeMemoryRecord, updateMemoryRecord, } from "../runtime/harness/system/runtime-memory-records.js";
3
- import { consolidateStructuredMemoryScope } from "../runtime/harness/system/runtime-memory-consolidation.js";
4
- import { renderMemoryCandidatesMarkdown } from "../runtime/harness/system/runtime-memory-candidates.js";
5
- import { shouldRecallDurableMemory, normalizeLangMemMemoryKind, shouldStoreMemoryCandidate, isNonDurableTranscriptWorkflowMemory, } from "../runtime/harness/system/runtime-memory-policy.js";
6
- const ALL_SCOPES = ["session", "agent", "workspace", "user", "project"];
7
- const TITLE_BY_SCOPE = {
8
- session: "Session Structured Memory",
9
- agent: "Agent Structured Memory",
10
- workspace: "Workspace Structured Memory",
11
- user: "User Structured Memory",
12
- project: "Project Structured Memory",
13
- };
14
- function normalizeRuntimeContext(context) {
15
- if (typeof context.agentId !== "string" || context.agentId.trim().length === 0) {
16
- throw new Error("knowledge operations require agentId in runtime context.");
17
- }
18
- return {
19
- ...context,
20
- agentId: context.agentId,
21
- userId: context.userId ?? "default",
22
- projectId: context.projectId ?? context.workspaceId,
23
- };
24
- }
25
- function summarizeMemoryContent(content) {
26
- return (content.trim().split("\n")[0] || content.trim()).slice(0, 240);
27
- }
28
- function normalizeMemoryScope(scope) {
29
- if (scope === "agent" || scope === "workspace" || scope === "user" || scope === "project") {
30
- return scope;
31
- }
32
- return "session";
33
- }
34
- function extractCandidateScopeOptions(candidate) {
35
- if (candidate.scope) {
36
- return [normalizeMemoryScope(candidate.scope)];
37
- }
38
- const provenance = typeof candidate.provenance === "object" && candidate.provenance !== null && !Array.isArray(candidate.provenance)
39
- ? candidate.provenance
40
- : undefined;
41
- const scopeOptions = Array.isArray(provenance?.scopeOptions)
42
- ? provenance.scopeOptions.filter((item) => item === "session" || item === "agent" || item === "workspace" || item === "user" || item === "project")
43
- : [];
44
- return scopeOptions.length > 0 ? Array.from(new Set(scopeOptions)) : ["session"];
45
- }
46
- function resolveRecallScopes(input, context) {
47
- if (Array.isArray(input.scopes) && input.scopes.length > 0) {
48
- return Array.from(new Set(input.scopes));
49
- }
50
- const scopes = new Set(["session", "agent", "workspace"]);
51
- if (context.userId) {
52
- scopes.add("user");
53
- }
54
- if (context.projectId) {
55
- scopes.add("project");
56
- }
57
- return Array.from(scopes);
58
- }
59
- function matchesMemoryFilters(record, filters) {
60
- const sessionId = String(record.provenance.sessionId ?? "");
61
- if (filters.sessionId && sessionId !== filters.sessionId) {
62
- return false;
63
- }
64
- if (filters.agentId && record.provenance.agentId !== filters.agentId) {
65
- return false;
66
- }
67
- if (filters.workspaceId && record.provenance.workspaceId !== filters.workspaceId) {
68
- return false;
69
- }
70
- if (filters.userId && record.provenance.userId !== filters.userId) {
71
- return false;
72
- }
73
- if (filters.projectId && record.provenance.projectId !== filters.projectId) {
74
- return false;
75
- }
76
- return true;
77
- }
78
- function matchesRecallScope(record, filters) {
79
- if (record.scope === "session") {
80
- return typeof filters.sessionId === "string"
81
- && String(record.provenance.sessionId ?? "") === filters.sessionId;
82
- }
83
- if (record.scope === "agent") {
84
- return String(record.provenance.agentId ?? "") === filters.agentId;
85
- }
86
- if (record.scope === "workspace") {
87
- return String(record.provenance.workspaceId ?? filters.workspaceId) === filters.workspaceId;
88
- }
89
- if (record.scope === "user") {
90
- return String(record.provenance.userId ?? "default") === filters.userId;
91
- }
92
- return String(record.provenance.projectId ?? filters.workspaceId) === filters.projectId;
93
- }
94
- function getMemoryScopeBoost(scope) {
95
- if (scope === "session") {
96
- return 4;
97
- }
98
- if (scope === "agent") {
99
- return 2;
100
- }
101
- if (scope === "workspace") {
102
- return 1;
103
- }
104
- return 0;
105
- }
106
- function memoryFreshnessBoost(value) {
107
- return Math.max(0, 1 - ((Date.now() - Date.parse(value)) / (1000 * 60 * 60 * 24 * 365)));
108
- }
109
- function scoreStructuredRecord(record) {
110
- return (getMemoryScopeBoost(record.scope) +
111
- memoryFreshnessBoost(record.lastConfirmedAt) +
112
- record.confidence);
113
- }
114
- function characterGramSet(value) {
115
- const normalized = normalizeCompareText(value).replace(/\s+/g, "");
116
- const grams = new Set();
117
- if (normalized.length < 2) {
118
- if (normalized.length > 0) {
119
- grams.add(normalized);
120
- }
121
- return grams;
122
- }
123
- for (let index = 0; index < normalized.length - 1; index += 1) {
124
- grams.add(normalized.slice(index, index + 2));
125
- }
126
- return grams;
127
- }
128
- function characterGramSimilarity(left, right) {
129
- const leftGrams = characterGramSet(left);
130
- const rightGrams = characterGramSet(right);
131
- if (leftGrams.size === 0 || rightGrams.size === 0) {
132
- return 0;
133
- }
134
- let intersection = 0;
135
- for (const gram of leftGrams) {
136
- if (rightGrams.has(gram)) {
137
- intersection += 1;
138
- }
139
- }
140
- const union = new Set([...leftGrams, ...rightGrams]).size;
141
- return union === 0 ? 0 : intersection / union;
142
- }
143
- function textSimilarity(left, right) {
144
- return Math.max(jaccardTextSimilarity(left, right), characterGramSimilarity(left, right));
145
- }
146
- function scoreStructuredRecordForQuery(record, query) {
147
- let score = scoreStructuredRecord(record);
148
- score += textSimilarity(record.summary, query) * 5;
149
- score += textSimilarity(record.content, query) * 4;
150
- if (record.knowledgeIdentity) {
151
- score += textSimilarity(record.knowledgeIdentity, query) * 2;
152
- }
153
- if (record.operationalRule) {
154
- score += textSimilarity(record.operationalRule.trigger, query) * 3;
155
- score += textSimilarity(record.operationalRule.target, query) * 2;
156
- if (record.operationalRule.effect === "invalidate" || record.knowledgeOperation === "delete") {
157
- score += 0.5;
158
- }
159
- }
160
- return score;
161
- }
162
- function normalizeMemoryDedupKey(record) {
163
- return `${record.scope}::${record.summary.toLowerCase().replace(/\s+/g, " ").trim()}::${record.content.toLowerCase().replace(/\s+/g, " ").trim()}`;
164
- }
165
- function normalizeCompareText(value) {
166
- return value.toLowerCase().replace(/\s+/g, " ").trim();
167
- }
168
- function tokenizeText(value) {
169
- return new Set(value
170
- .toLowerCase()
171
- .split(/[^a-z0-9_]+/i)
172
- .map((token) => token.trim())
173
- .filter((token) => token.length > 2));
174
- }
175
- function jaccardTextSimilarity(left, right) {
176
- const leftTokens = tokenizeText(left);
177
- const rightTokens = tokenizeText(right);
178
- if (leftTokens.size === 0 || rightTokens.size === 0) {
179
- return 0;
180
- }
181
- let intersection = 0;
182
- for (const token of leftTokens) {
183
- if (rightTokens.has(token)) {
184
- intersection += 1;
185
- }
186
- }
187
- const union = new Set([...leftTokens, ...rightTokens]).size;
188
- return union === 0 ? 0 : intersection / union;
189
- }
190
- function containsDeletionSignal(value) {
191
- const normalized = normalizeCompareText(value);
192
- if (!normalized) {
193
- return false;
194
- }
195
- return [
196
- "delete",
197
- "deleted",
198
- "remove",
199
- "removed",
200
- "revoked",
201
- "forbidden",
202
- "not allowed",
203
- "no longer",
204
- "unavailable",
205
- "disabled",
206
- "deprecated",
207
- "取消",
208
- "撤销",
209
- "删除",
210
- "已删除",
211
- "删掉",
212
- "移除",
213
- "不再",
214
- "不可用",
215
- "不能",
216
- "无法",
217
- "禁用",
218
- "废弃",
219
- ].some((signal) => normalized.includes(signal));
220
- }
221
- function extractSalientLiterals(value) {
222
- const results = new Set();
223
- const normalized = value.trim();
224
- if (!normalized) {
225
- return results;
226
- }
227
- for (const match of normalized.matchAll(/[`'"]([^`'"]{1,64})[`'"]/g)) {
228
- const literal = match[1]?.trim().toLowerCase();
229
- if (literal && literal.length >= 2) {
230
- results.add(literal);
231
- }
232
- }
233
- for (const match of normalized.matchAll(/\b[a-z][a-z0-9._/-]{1,63}\b/gi)) {
234
- const token = match[0]?.trim().toLowerCase();
235
- if (token && !["system", "startup", "command", "memory", "instruction", "user", "deleted"].includes(token)) {
236
- results.add(token);
237
- }
238
- }
239
- return results;
240
- }
241
- function sharesSalientLiteral(left, right) {
242
- const leftLiterals = extractSalientLiterals(left);
243
- const rightLiterals = extractSalientLiterals(right);
244
- if (leftLiterals.size === 0 || rightLiterals.size === 0) {
245
- return false;
246
- }
247
- for (const literal of leftLiterals) {
248
- if (rightLiterals.has(literal)) {
249
- return true;
250
- }
251
- }
252
- return false;
253
- }
254
- function mergeScoredRecords(...groups) {
255
- const merged = new Map();
256
- for (const group of groups) {
257
- for (const item of group) {
258
- const existing = merged.get(item.record.id);
259
- if (!existing || item.score > existing.score) {
260
- merged.set(item.record.id, item);
261
- }
262
- }
263
- }
264
- return Array.from(merged.values())
265
- .sort((left, right) => right.score - left.score || right.record.lastConfirmedAt.localeCompare(left.record.lastConfirmedAt))
266
- .map((item) => item.record);
267
- }
268
- function selectRelevantExistingRecords(candidates, existingRecords) {
269
- const scored = new Map();
270
- for (const candidate of candidates) {
271
- const candidateScopes = new Set(extractCandidateScopeOptions(candidate));
272
- const content = normalizeCompareText(candidate.content);
273
- const summary = normalizeCompareText(candidate.summary ?? summarizeMemoryContent(candidate.content));
274
- const sourceRef = typeof candidate.sourceRef === "string" ? candidate.sourceRef.trim() : "";
275
- const candidateText = `${candidate.summary ?? ""}\n${candidate.content}`;
276
- const deletionSignal = containsDeletionSignal(candidateText);
277
- for (const record of existingRecords) {
278
- if (!candidateScopes.has(record.scope)) {
279
- continue;
280
- }
281
- let score = 0;
282
- let deterministicMatch = false;
283
- if (sourceRef && record.sourceRefs.includes(sourceRef)) {
284
- score += 10;
285
- deterministicMatch = true;
286
- }
287
- if (normalizeCompareText(record.content) === content) {
288
- score += 9;
289
- deterministicMatch = true;
290
- }
291
- if (normalizeCompareText(record.summary) === summary) {
292
- score += 8;
293
- deterministicMatch = true;
294
- }
295
- const similarityScore = textSimilarity(record.summary, candidate.summary ?? candidate.content) * 4
296
- + textSimilarity(record.content, candidate.content) * 3;
297
- score += similarityScore;
298
- if (deletionSignal) {
299
- const ruleTarget = record.operationalRule?.target?.trim().toLowerCase();
300
- if (ruleTarget && candidateText.toLowerCase().includes(ruleTarget)) {
301
- score += 12;
302
- deterministicMatch = true;
303
- }
304
- if (sharesSalientLiteral(candidateText, `${record.summary}\n${record.content}`)) {
305
- score += 8;
306
- deterministicMatch = true;
307
- }
308
- }
309
- if (!deterministicMatch && similarityScore < 1) {
310
- continue;
311
- }
312
- if (score <= 0) {
313
- continue;
314
- }
315
- const existing = scored.get(record.id);
316
- if (!existing || score > existing.score) {
317
- scored.set(record.id, { record, score });
318
- }
319
- }
320
- }
321
- return Array.from(scored.values())
322
- .sort((left, right) => right.score - left.score || right.record.lastConfirmedAt.localeCompare(left.record.lastConfirmedAt))
323
- .map((item) => item.record);
324
- }
325
- async function selectVectorRelevantExistingRecords(input) {
326
- const vectorStore = await input.resolveVectorStore();
327
- if (!vectorStore) {
328
- return [];
329
- }
330
- const existingById = new Map(input.existingRecords.map((record) => [record.id, record]));
331
- const scored = new Map();
332
- try {
333
- for (const candidate of input.candidates) {
334
- const candidateScopes = new Set(extractCandidateScopeOptions(candidate));
335
- const query = [candidate.summary?.trim(), candidate.content.trim()].filter((value) => !!value && value.length > 0).join("\n");
336
- if (!query) {
337
- continue;
338
- }
339
- const hits = await vectorStore.similaritySearch(query, 8);
340
- for (const hit of hits) {
341
- const metadata = typeof hit.metadata === "object" && hit.metadata !== null && !Array.isArray(hit.metadata)
342
- ? hit.metadata
343
- : {};
344
- const recordId = typeof metadata.recordId === "string" ? metadata.recordId : undefined;
345
- if (!recordId) {
346
- continue;
347
- }
348
- const record = existingById.get(recordId);
349
- if (!record || record.status !== "active" || !candidateScopes.has(record.scope)) {
350
- continue;
351
- }
352
- const score = (typeof hit.score === "number" ? hit.score : 0) + scoreStructuredRecordForQuery(record, query);
353
- const existing = scored.get(record.id);
354
- if (!existing || score > existing.score) {
355
- scored.set(record.id, { record, score });
356
- }
357
- }
358
- }
359
- }
360
- catch {
361
- return [];
362
- }
363
- return Array.from(scored.values())
364
- .sort((left, right) => right.score - left.score || right.record.lastConfirmedAt.localeCompare(left.record.lastConfirmedAt));
365
- }
366
- function sortPromptRecallRecords(items) {
367
- return [...items].sort((left, right) => left.record.observedAt.localeCompare(right.record.observedAt)
368
- || left.record.createdAt.localeCompare(right.record.createdAt)
369
- || left.record.id.localeCompare(right.record.id));
370
- }
371
- function inferMem0MemoryKind(hit) {
372
- const candidates = [
373
- ...hit.categories,
374
- typeof hit.metadata.kind === "string" ? hit.metadata.kind : undefined,
375
- typeof hit.metadata.memoryType === "string" ? hit.metadata.memoryType : undefined,
376
- ].filter((value) => typeof value === "string" && value.trim().length > 0);
377
- for (const candidate of candidates) {
378
- const kind = normalizeLangMemMemoryKind(candidate);
379
- if (kind === "semantic" || kind === "episodic" || kind === "procedural") {
380
- return kind;
381
- }
382
- }
383
- return "semantic";
384
- }
385
- function inferMem0MemoryScope(hit, filters) {
386
- const metadataScope = typeof hit.metadata.scope === "string" ? hit.metadata.scope : undefined;
387
- if (metadataScope === "session" || metadataScope === "agent" || metadataScope === "workspace" || metadataScope === "user" || metadataScope === "project") {
388
- return metadataScope;
389
- }
390
- if (typeof hit.metadata.sessionId === "string" && filters.sessionId && hit.metadata.sessionId === filters.sessionId) {
391
- return "session";
392
- }
393
- if (hit.agentId === filters.agentId || hit.metadata.agentId === filters.agentId) {
394
- return "agent";
395
- }
396
- return "workspace";
397
- }
398
- function createMem0MemoryRecord(hit, filters) {
399
- const scope = inferMem0MemoryScope(hit, filters);
400
- const kind = inferMem0MemoryKind(hit);
401
- const summary = hit.memory.split("\n")[0]?.trim() || hit.memory;
402
- return {
403
- id: `mem0:${hit.id}`,
404
- canonicalKey: `mem0:${hit.id}`,
405
- kind,
406
- scope,
407
- content: hit.memory,
408
- summary: summary.slice(0, 240),
409
- status: "active",
410
- confidence: Math.max(0, Math.min(1, hit.score || 0.5)),
411
- createdAt: hit.createdAt,
412
- observedAt: hit.createdAt,
413
- lastConfirmedAt: hit.updatedAt,
414
- sourceType: "mem0-search",
415
- sourceRefs: [`mem0:${hit.id}`],
416
- tags: hit.categories,
417
- provenance: {
418
- source: "mem0",
419
- sessionId: typeof hit.metadata.sessionId === "string" ? hit.metadata.sessionId : filters.sessionId,
420
- requestId: typeof hit.metadata.requestId === "string" ? hit.metadata.requestId : undefined,
421
- agentId: hit.agentId ?? (typeof hit.metadata.agentId === "string" ? hit.metadata.agentId : filters.agentId),
422
- workspaceId: filters.workspaceId,
423
- userId: filters.userId,
424
- projectId: filters.projectId,
425
- ...hit.metadata,
426
- },
427
- revision: 1,
428
- supersedes: [],
429
- conflictsWith: [],
430
- };
431
- }
432
- export class DefaultKnowledgeModule {
433
- deps;
434
- constructor(deps) {
435
- this.deps = deps;
436
- }
437
- async memorize(input, context) {
438
- if (!Array.isArray(input.records)) {
439
- throw new Error("memorize requires input.records to be an array.");
440
- }
441
- const normalizedContext = normalizeRuntimeContext(context);
442
- const candidates = input.records
443
- .filter((record) => typeof record === "object" && record !== null)
444
- .filter((record) => record.noStore !== true);
445
- if (candidates.length === 0) {
446
- return { records: [], decisions: [] };
447
- }
448
- if (candidates.some((record) => typeof record.content !== "string" || record.content.trim().length === 0)) {
449
- throw new Error("memorize requires every record to include non-empty content.");
450
- }
451
- if (candidates.some((record) => (record.scope ?? "session") === "session") && !normalizedContext.sessionId) {
452
- throw new Error("memorize requires sessionId when storing session-scoped memory.");
453
- }
454
- const recordedAt = normalizedContext.recordedAt ?? new Date().toISOString();
455
- const requestId = normalizedContext.requestId ?? createPersistentId(new Date(recordedAt));
456
- const sessionId = normalizedContext.sessionId ?? `memory-api-${requestId}`;
457
- return this.memorizeCandidates(candidates.map((record) => ({ ...record, content: record.content.trim() })), {
458
- ...normalizedContext,
459
- requestId,
460
- sessionId,
461
- recordedAt,
462
- }, {
463
- storeCandidateLog: input.storeCandidateLog !== false,
464
- forceStore: input.forceStore === true,
465
- });
466
- }
467
- async recall(input, context) {
468
- if (typeof input.query !== "string" || input.query.trim().length === 0) {
469
- throw new Error("recall requires a non-empty query.");
470
- }
471
- const normalizedContext = normalizeRuntimeContext(context);
472
- const scopes = resolveRecallScopes(input, normalizedContext);
473
- const topK = typeof input.topK === "number" && Number.isInteger(input.topK) && input.topK > 0
474
- ? input.topK
475
- : (this.deps.policy?.retrieval.defaultTopK ?? 5);
476
- const kinds = input.kinds?.length ? new Set(input.kinds) : null;
477
- const items = (await this.rankRecallCandidates({
478
- query: input.query.trim(),
479
- scopes,
480
- kinds,
481
- topK,
482
- includeStale: input.includeStale === true,
483
- context: normalizedContext,
484
- }))
485
- .slice(0, topK)
486
- .map(({ record }) => record);
487
- return { items };
488
- }
489
- async buildPromptRecall(input, context) {
490
- if (!shouldRecallDurableMemory(input.query)) {
491
- return { items: [] };
492
- }
493
- const normalizedContext = normalizeRuntimeContext(context);
494
- const ranked = (await this.rankRecallCandidates({
495
- query: input.query,
496
- scopes: input.scopes ?? ALL_SCOPES,
497
- kinds: input.kinds?.length ? new Set(input.kinds) : null,
498
- topK: input.topK ?? this.deps.policy?.retrieval.maxPromptMemories ?? 8,
499
- includeStale: input.includeStale === true,
500
- context: normalizedContext,
501
- }))
502
- .filter(({ record }) => !isNonDurableTranscriptWorkflowMemory(record))
503
- .map((item) => {
504
- const scopeBoost = item.record.scope === "session"
505
- ? 4
506
- : item.record.scope === "agent"
507
- ? 3
508
- : item.record.scope === "user"
509
- ? 2
510
- : 1;
511
- return {
512
- record: item.record,
513
- scope: item.record.scope,
514
- content: [
515
- `# Durable ${item.record.scope[0].toUpperCase()}${item.record.scope.slice(1)} Memory`,
516
- "",
517
- `- summary: ${item.record.summary}`,
518
- `- kind: ${item.record.kind}`,
519
- `- scope: ${item.record.scope}`,
520
- `- confidence: ${item.record.confidence.toFixed(2)}`,
521
- ...(item.record.knowledgeIdentity
522
- ? [
523
- `- knowledge_identity: ${item.record.knowledgeIdentity}`,
524
- `- knowledge_operation: ${item.record.knowledgeOperation ?? "create"}`,
525
- ]
526
- : []),
527
- "",
528
- item.record.content,
529
- ].join("\n"),
530
- score: scopeBoost +
531
- memoryFreshnessBoost(item.record.lastConfirmedAt) +
532
- item.record.confidence,
533
- };
534
- })
535
- .sort((left, right) => right.score - left.score);
536
- if (ranked.length === 0) {
537
- return { items: [] };
538
- }
539
- const maxPromptMemories = this.deps.policy?.retrieval.maxPromptMemories ?? 8;
540
- const selected = ranked.slice(0, maxPromptMemories);
541
- if (selected.length === 0) {
542
- return { items: [] };
543
- }
544
- const orderedSelected = sortPromptRecallRecords(selected);
545
- return {
546
- items: orderedSelected.map((entry) => entry.record),
547
- context: orderedSelected.map((entry) => entry.content).join("\n\n"),
548
- };
549
- }
550
- async buildPromptContext(input, context) {
551
- const promptRecall = await this.buildPromptRecall(input, context);
552
- return promptRecall.context;
553
- }
554
- async list(input = {}, context) {
555
- const normalizedContext = { ...context };
556
- const scopes = Array.isArray(input.scopes) && input.scopes.length > 0
557
- ? Array.from(new Set(input.scopes))
558
- : ALL_SCOPES;
559
- const kinds = input.kinds?.length ? new Set(input.kinds) : null;
560
- const statuses = input.status?.length ? new Set(input.status) : new Set(["active"]);
561
- const limit = typeof input.limit === "number" && Number.isInteger(input.limit) && input.limit > 0
562
- ? input.limit
563
- : Number.POSITIVE_INFINITY;
564
- const items = (await listMemoryRecordsForScopes(this.deps.store, scopes))
565
- .filter((record) => statuses.has(record.status))
566
- .filter((record) => !kinds || kinds.has(record.kind))
567
- .filter((record) => matchesMemoryFilters(record, {
568
- sessionId: normalizedContext.sessionId,
569
- agentId: normalizedContext.agentId,
570
- workspaceId: normalizedContext.workspaceId,
571
- userId: normalizedContext.userId,
572
- projectId: normalizedContext.projectId,
573
- }))
574
- .sort((left, right) => right.lastConfirmedAt.localeCompare(left.lastConfirmedAt))
575
- .slice(0, limit);
576
- return { items };
577
- }
578
- async update(input, context) {
579
- if (typeof input.memoryId !== "string" || input.memoryId.trim().length === 0) {
580
- throw new Error("updateMemory requires a non-empty memoryId.");
581
- }
582
- const existing = await findMemoryRecordById(this.deps.store, input.memoryId.trim());
583
- if (!existing) {
584
- throw new Error(`Memory record not found: ${input.memoryId}`);
585
- }
586
- const updatedAt = new Date().toISOString();
587
- const nextContent = typeof input.content === "string" ? input.content.trim() : existing.content;
588
- if (nextContent.length === 0) {
589
- throw new Error("updateMemory requires content to remain non-empty.");
590
- }
591
- const next = {
592
- ...existing,
593
- content: nextContent,
594
- summary: typeof input.summary === "string"
595
- ? input.summary.trim() || summarizeMemoryContent(nextContent)
596
- : (typeof input.content === "string" ? summarizeMemoryContent(nextContent) : existing.summary),
597
- status: input.status ?? existing.status,
598
- confidence: typeof input.confidence === "number" ? Math.max(0, Math.min(1, input.confidence)) : existing.confidence,
599
- expiresAt: input.expiresAt === undefined ? existing.expiresAt : (input.expiresAt ?? undefined),
600
- sourceType: typeof input.sourceType === "string" && input.sourceType.trim().length > 0 ? input.sourceType.trim() : existing.sourceType,
601
- sourceRefs: Array.isArray(input.sourceRefs)
602
- ? Array.from(new Set(input.sourceRefs.map((item) => item.trim()).filter((item) => item.length > 0)))
603
- : existing.sourceRefs,
604
- tags: Array.isArray(input.tags)
605
- ? Array.from(new Set(input.tags.map((item) => item.trim()).filter((item) => item.length > 0)))
606
- : existing.tags,
607
- knowledgeIdentity: typeof input.knowledgeIdentity === "string" && input.knowledgeIdentity.trim().length > 0
608
- ? input.knowledgeIdentity.trim()
609
- : existing.knowledgeIdentity,
610
- knowledgeOperation: input.knowledgeOperation === "create" || input.knowledgeOperation === "update" || input.knowledgeOperation === "delete"
611
- ? input.knowledgeOperation
612
- : existing.knowledgeOperation,
613
- observedAt: typeof input.observedAt === "string" && input.observedAt.trim().length > 0 ? input.observedAt : existing.observedAt,
614
- lastConfirmedAt: typeof input.lastConfirmedAt === "string" && input.lastConfirmedAt.trim().length > 0
615
- ? input.lastConfirmedAt
616
- : updatedAt,
617
- provenance: input.provenance ? { ...existing.provenance, ...input.provenance } : existing.provenance,
618
- revision: existing.revision + 1,
619
- };
620
- await updateMemoryRecord(this.deps.store, next, updatedAt);
621
- await this.rebuildVectorIndex();
622
- await this.refreshStructuredMemoryScope(next, context);
623
- return next;
624
- }
625
- async remove(input, context) {
626
- if (typeof input.memoryId !== "string" || input.memoryId.trim().length === 0) {
627
- throw new Error("removeMemory requires a non-empty memoryId.");
628
- }
629
- const existing = await findMemoryRecordById(this.deps.store, input.memoryId.trim());
630
- if (!existing) {
631
- throw new Error(`Memory record not found: ${input.memoryId}`);
632
- }
633
- await removeMemoryRecord(this.deps.store, existing.scope, existing.id);
634
- await this.rebuildVectorIndex();
635
- await this.refreshStructuredMemoryScope(existing, context);
636
- return existing;
637
- }
638
- async memorizeCandidates(candidates, context, options) {
639
- const normalizedContext = normalizeRuntimeContext(context);
640
- const validCandidates = candidates
641
- .filter((candidate) => candidate.noStore !== true)
642
- .filter((candidate) => typeof candidate.content === "string" && candidate.content.trim().length > 0)
643
- .map((candidate) => ({ ...candidate, content: candidate.content.trim() }));
644
- if (validCandidates.length === 0) {
645
- return { records: [], decisions: [] };
646
- }
647
- const relevantScopes = Array.from(new Set(validCandidates.flatMap((candidate) => extractCandidateScopeOptions(candidate))));
648
- const existingRecords = await listMemoryRecordsForScopes(this.deps.store, relevantScopes);
649
- const vectorRelatedExistingRecords = await selectVectorRelevantExistingRecords({
650
- candidates: validCandidates,
651
- existingRecords,
652
- resolveVectorStore: this.deps.resolveVectorStore,
653
- });
654
- const deterministicRelatedExistingRecords = selectRelevantExistingRecords(validCandidates, existingRecords)
655
- .map((record) => ({
656
- record,
657
- score: scoreStructuredRecord(record),
658
- }));
659
- const relatedExistingRecords = mergeScoredRecords(vectorRelatedExistingRecords, deterministicRelatedExistingRecords);
660
- const transformedCandidates = this.deps.transformCandidates
661
- ? await this.deps.transformCandidates({ candidates: validCandidates, context: normalizedContext, existingRecords: relatedExistingRecords })
662
- : validCandidates;
663
- const storedCandidates = options.forceStore === true
664
- ? transformedCandidates
665
- : transformedCandidates.filter((candidate) => shouldStoreMemoryCandidate(this.deps.policy, candidate));
666
- if (storedCandidates.length === 0) {
667
- return { records: [], decisions: [] };
668
- }
669
- if (options.storeCandidateLog) {
670
- await this.deps.store.put(["memories", "candidates", normalizedContext.sessionId ?? `memory-api-${normalizedContext.requestId ?? "unknown"}`], `${normalizedContext.requestId}.json`, {
671
- requestId: normalizedContext.requestId,
672
- sessionId: normalizedContext.sessionId,
673
- storedAt: normalizedContext.recordedAt,
674
- candidates: storedCandidates,
675
- });
676
- }
677
- const persisted = await persistStructuredMemoryRecords({
678
- store: this.deps.store,
679
- candidates: storedCandidates,
680
- sessionId: normalizedContext.sessionId ?? `memory-api-${normalizedContext.requestId ?? "unknown"}`,
681
- requestId: normalizedContext.requestId ?? createPersistentId(new Date(normalizedContext.recordedAt ?? new Date().toISOString())),
682
- agentId: normalizedContext.agentId,
683
- workspaceId: normalizedContext.workspaceId,
684
- userId: normalizedContext.userId ?? "default",
685
- projectId: normalizedContext.projectId ?? normalizedContext.workspaceId,
686
- recordedAt: normalizedContext.recordedAt ?? new Date().toISOString(),
687
- });
688
- await this.rebuildVectorIndex();
689
- await this.refreshAfterWrite(storedCandidates, normalizedContext);
690
- return persisted;
691
- }
692
- async refreshAfterWrite(candidates, context) {
693
- const buckets = {
694
- session: candidates.filter((candidate) => (candidate.scope ?? "session") === "session"),
695
- agent: candidates.filter((candidate) => (candidate.scope ?? "session") === "agent"),
696
- workspace: candidates.filter((candidate) => (candidate.scope ?? "session") === "workspace"),
697
- user: candidates.filter((candidate) => (candidate.scope ?? "session") === "user"),
698
- project: candidates.filter((candidate) => (candidate.scope ?? "session") === "project"),
699
- };
700
- const writes = [];
701
- for (const scope of ALL_SCOPES) {
702
- if (buckets[scope].length === 0) {
703
- continue;
704
- }
705
- const maxEntries = scope === "session" ? 12 : 20;
706
- writes.push(this.appendMemoryDigest(this.deps.resolveNamespace(scope, context), "tool-memory.md", buckets[scope], maxEntries, TITLE_BY_SCOPE[scope].replace("Structured", "Tool")));
707
- writes.push(consolidateStructuredMemoryScope({
708
- store: this.deps.store,
709
- namespace: this.deps.resolveNamespace(scope, context),
710
- title: TITLE_BY_SCOPE[scope],
711
- scope,
712
- maxEntries,
713
- config: this.deps.maintenanceConfig ?? undefined,
714
- }));
715
- }
716
- await Promise.all(writes);
717
- }
718
- async appendMemoryDigest(namespace, key, candidates, maxEntries, title) {
719
- const existing = await this.deps.store.get(namespace, key);
720
- const existingItems = Array.isArray(existing?.value?.items)
721
- ? ((existing?.value).items ?? [])
722
- : [];
723
- const merged = [...existingItems];
724
- for (const candidate of candidates) {
725
- if (merged.some((entry) => entry.content === candidate.content && (entry.scope ?? "session") === (candidate.scope ?? "session"))) {
726
- continue;
727
- }
728
- merged.push(candidate);
729
- }
730
- const recent = merged.slice(-maxEntries);
731
- const taxonomyGroups = new Map();
732
- for (const candidate of recent) {
733
- const kind = normalizeLangMemMemoryKind(candidate.kind);
734
- const current = taxonomyGroups.get(kind) ?? [];
735
- current.push({ ...candidate, kind });
736
- taxonomyGroups.set(kind, current);
737
- }
738
- await this.deps.store.put(namespace, key, {
739
- content: `${renderMemoryCandidatesMarkdown(title, recent)}\n`,
740
- items: recent,
741
- });
742
- await Promise.all(Array.from(taxonomyGroups.entries()).map(async ([kind, items]) => {
743
- await this.deps.store.put(namespace, `${kind}.md`, {
744
- content: `${renderMemoryCandidatesMarkdown(`${title} (${kind})`, items)}\n`,
745
- items,
746
- });
747
- }));
748
- }
749
- async refreshStructuredMemoryScope(record, context) {
750
- const provenance = record.provenance;
751
- const namespaceContext = {
752
- sessionId: provenance.sessionId,
753
- agentId: provenance.agentId ?? context.agentId,
754
- workspaceId: provenance.workspaceId ?? context.workspaceId,
755
- userId: provenance.userId ?? context.userId,
756
- projectId: provenance.projectId ?? context.projectId,
757
- };
758
- const maxEntries = record.scope === "session" ? 12 : 20;
759
- await consolidateStructuredMemoryScope({
760
- store: this.deps.store,
761
- namespace: this.deps.resolveNamespace(record.scope, normalizeRuntimeContext(namespaceContext)),
762
- title: TITLE_BY_SCOPE[record.scope],
763
- scope: record.scope,
764
- maxEntries,
765
- config: this.deps.maintenanceConfig ?? undefined,
766
- });
767
- }
768
- async rebuildVectorIndex() {
769
- const vectorStore = await this.deps.resolveVectorStore();
770
- if (!vectorStore) {
771
- return;
772
- }
773
- const records = (await listMemoryRecordsForScopes(this.deps.store, ALL_SCOPES))
774
- .filter((record) => record.status === "active");
775
- try {
776
- await vectorStore.delete({ deleteAll: true });
777
- if (records.length === 0) {
778
- return;
779
- }
780
- await vectorStore.addDocuments(records.map((record) => ({
781
- pageContent: `${record.summary}\n${record.content}`,
782
- metadata: {
783
- recordId: record.id,
784
- scope: record.scope,
785
- kind: record.kind,
786
- status: record.status,
787
- sessionId: record.provenance.sessionId,
788
- agentId: record.provenance.agentId,
789
- workspaceId: record.provenance.workspaceId,
790
- userId: record.provenance.userId,
791
- projectId: record.provenance.projectId,
792
- confidence: record.confidence,
793
- lastConfirmedAt: record.lastConfirmedAt,
794
- },
795
- })));
796
- }
797
- catch {
798
- // Fail open: vector indexing must not break durable memory writes.
799
- }
800
- }
801
- async rankRecallCandidates(input) {
802
- const structuredRecords = await listMemoryRecordsForScopes(this.deps.store, input.scopes);
803
- const ranked = structuredRecords
804
- .filter((record) => matchesRecallScope(record, {
805
- sessionId: input.context.sessionId,
806
- agentId: input.context.agentId,
807
- workspaceId: input.context.workspaceId,
808
- userId: input.context.userId ?? "default",
809
- projectId: input.context.projectId ?? input.context.workspaceId,
810
- }))
811
- .filter((record) => (input.includeStale ? record.status === "active" || record.status === "stale" : record.status === "active"))
812
- .filter((record) => (input.kinds ? input.kinds.has(record.kind) : true))
813
- .map((record) => ({
814
- record,
815
- score: scoreStructuredRecordForQuery(record, input.query),
816
- }));
817
- const deduped = new Map();
818
- for (const item of ranked) {
819
- deduped.set(normalizeMemoryDedupKey(item.record), item);
820
- }
821
- const vectorStore = await this.deps.resolveVectorStore();
822
- if (vectorStore) {
823
- try {
824
- const vectorHits = await vectorStore.similaritySearch(input.query, Math.max(input.topK, this.deps.policy?.retrieval.maxPromptMemories ?? input.topK));
825
- for (const hit of vectorHits) {
826
- const metadata = typeof hit.metadata === "object" && hit.metadata && !Array.isArray(hit.metadata)
827
- ? hit.metadata
828
- : {};
829
- const recordId = typeof metadata.recordId === "string" ? metadata.recordId : undefined;
830
- const scope = metadata.scope;
831
- if (!recordId || (scope !== "session" && scope !== "agent" && scope !== "workspace" && scope !== "user" && scope !== "project")) {
832
- continue;
833
- }
834
- const canonical = await getMemoryRecord(this.deps.store, scope, recordId);
835
- if (!canonical) {
836
- continue;
837
- }
838
- if (!matchesRecallScope(canonical, {
839
- sessionId: input.context.sessionId,
840
- agentId: input.context.agentId,
841
- workspaceId: input.context.workspaceId,
842
- userId: input.context.userId ?? "default",
843
- projectId: input.context.projectId ?? input.context.workspaceId,
844
- })) {
845
- continue;
846
- }
847
- if (input.includeStale ? canonical.status !== "active" && canonical.status !== "stale" : canonical.status !== "active") {
848
- continue;
849
- }
850
- if (input.kinds && !input.kinds.has(canonical.kind)) {
851
- continue;
852
- }
853
- const key = normalizeMemoryDedupKey(canonical);
854
- const score = scoreStructuredRecordForQuery(canonical, input.query) + (typeof hit.score === "number" ? hit.score : 0);
855
- const existing = deduped.get(key);
856
- if (!existing || score > existing.score) {
857
- deduped.set(key, { record: canonical, score });
858
- }
859
- }
860
- }
861
- catch {
862
- // Fail open to lexical/runtime ranking.
863
- }
864
- }
865
- const supportsMem0Scope = input.scopes.some((scope) => scope === "session" || scope === "agent" || scope === "workspace");
866
- const mem0SemanticRecall = this.deps.getMem0SemanticRecall?.() ?? null;
867
- if (!mem0SemanticRecall || !supportsMem0Scope) {
868
- return Array.from(deduped.values()).sort((left, right) => right.score - left.score);
869
- }
870
- try {
871
- const hits = await mem0SemanticRecall.search({
872
- query: input.query,
873
- topK: Math.max(input.topK, this.deps.policy?.retrieval.maxPromptMemories ?? input.topK),
874
- agentId: input.context.agentId,
875
- sessionId: input.context.sessionId,
876
- });
877
- for (const hit of hits) {
878
- const record = createMem0MemoryRecord(hit, {
879
- sessionId: input.context.sessionId,
880
- agentId: input.context.agentId,
881
- workspaceId: input.context.workspaceId,
882
- userId: input.context.userId ?? "default",
883
- projectId: input.context.projectId ?? input.context.workspaceId,
884
- });
885
- if (!input.scopes.includes(record.scope)) {
886
- continue;
887
- }
888
- if (input.kinds && !input.kinds.has(record.kind)) {
889
- continue;
890
- }
891
- const key = normalizeMemoryDedupKey(record);
892
- if (deduped.has(key)) {
893
- continue;
894
- }
895
- deduped.set(key, {
896
- record,
897
- score: scoreStructuredRecordForQuery(record, input.query) + Math.max(0, Math.min(1, hit.score)) * 4,
898
- });
899
- }
900
- return Array.from(deduped.values()).sort((left, right) => right.score - left.score);
901
- }
902
- catch {
903
- return Array.from(deduped.values()).sort((left, right) => right.score - left.score);
904
- }
905
- }
906
- }
907
- export function createKnowledgeModule(dependencies) {
908
- return new DefaultKnowledgeModule(dependencies);
909
- }
1
+ import{createPersistentId as R}from"../utils/id.js";import{findMemoryRecordById as j,getMemoryRecord as D,listMemoryRecordsForScopes as h,persistStructuredMemoryRecords as P,removeMemoryRecord as V,updateMemoryRecord as N}from"../runtime/harness/system/runtime-memory-records.js";import{consolidateStructuredMemoryScope as b}from"../runtime/harness/system/runtime-memory-consolidation.js";import{renderMemoryCandidatesMarkdown as z}from"../runtime/harness/system/runtime-memory-candidates.js";import{shouldRecallDurableMemory as _,normalizeLangMemMemoryKind as q,shouldStoreMemoryCandidate as B,isNonDurableTranscriptWorkflowMemory as F}from"../runtime/harness/system/runtime-memory-policy.js";const k=["session","agent","workspace","user","project"],v={session:"Session Structured Memory",agent:"Agent Structured Memory",workspace:"Workspace Structured Memory",user:"User Structured Memory",project:"Project Structured Memory"};function w(t){if(typeof t.agentId!="string"||t.agentId.trim().length===0)throw new Error("knowledge operations require agentId in runtime context.");return{...t,agentId:t.agentId,userId:t.userId??"default",projectId:t.projectId??t.workspaceId}}function A(t){return(t.trim().split(`
2
+ `)[0]||t.trim()).slice(0,240)}function G(t){return t==="agent"||t==="workspace"||t==="user"||t==="project"?t:"session"}function x(t){if(t.scope)return[G(t.scope)];const e=typeof t.provenance=="object"&&t.provenance!==null&&!Array.isArray(t.provenance)?t.provenance:void 0,o=Array.isArray(e?.scopeOptions)?e.scopeOptions.filter(r=>r==="session"||r==="agent"||r==="workspace"||r==="user"||r==="project"):[];return o.length>0?Array.from(new Set(o)):["session"]}function W(t,e){if(Array.isArray(t.scopes)&&t.scopes.length>0)return Array.from(new Set(t.scopes));const o=new Set(["session","agent","workspace"]);return e.userId&&o.add("user"),e.projectId&&o.add("project"),Array.from(o)}function U(t,e){const o=String(t.provenance.sessionId??"");return!(e.sessionId&&o!==e.sessionId||e.agentId&&t.provenance.agentId!==e.agentId||e.workspaceId&&t.provenance.workspaceId!==e.workspaceId||e.userId&&t.provenance.userId!==e.userId||e.projectId&&t.provenance.projectId!==e.projectId)}function $(t,e){return t.scope==="session"?typeof e.sessionId=="string"&&String(t.provenance.sessionId??"")===e.sessionId:t.scope==="agent"?String(t.provenance.agentId??"")===e.agentId:t.scope==="workspace"?String(t.provenance.workspaceId??e.workspaceId)===e.workspaceId:t.scope==="user"?String(t.provenance.userId??"default")===e.userId:String(t.provenance.projectId??e.workspaceId)===e.projectId}function Y(t){return t==="session"?4:t==="agent"?2:t==="workspace"?1:0}function T(t){return Math.max(0,1-(Date.now()-Date.parse(t))/(1e3*60*60*24*365))}function E(t){return Y(t.scope)+T(t.lastConfirmedAt)+t.confidence}function K(t){const e=I(t).replace(/\s+/g,""),o=new Set;if(e.length<2)return e.length>0&&o.add(e),o;for(let r=0;r<e.length-1;r+=1)o.add(e.slice(r,r+2));return o}function H(t,e){const o=K(t),r=K(e);if(o.size===0||r.size===0)return 0;let n=0;for(const m of o)r.has(m)&&(n+=1);const a=new Set([...o,...r]).size;return a===0?0:n/a}function y(t,e){return Math.max(Q(t,e),H(t,e))}function S(t,e){let o=E(t);return o+=y(t.summary,e)*5,o+=y(t.content,e)*4,t.knowledgeIdentity&&(o+=y(t.knowledgeIdentity,e)*2),t.operationalRule&&(o+=y(t.operationalRule.trigger,e)*3,o+=y(t.operationalRule.target,e)*2,(t.operationalRule.effect==="invalidate"||t.knowledgeOperation==="delete")&&(o+=.5)),o}function M(t){return`${t.scope}::${t.summary.toLowerCase().replace(/\s+/g," ").trim()}::${t.content.toLowerCase().replace(/\s+/g," ").trim()}`}function I(t){return t.toLowerCase().replace(/\s+/g," ").trim()}function L(t){return new Set(t.toLowerCase().split(/[^a-z0-9_]+/i).map(e=>e.trim()).filter(e=>e.length>2))}function Q(t,e){const o=L(t),r=L(e);if(o.size===0||r.size===0)return 0;let n=0;for(const m of o)r.has(m)&&(n+=1);const a=new Set([...o,...r]).size;return a===0?0:n/a}function J(t){const e=I(t);return e?["delete","deleted","remove","removed","revoked","forbidden","not allowed","no longer","unavailable","disabled","deprecated","\u53D6\u6D88","\u64A4\u9500","\u5220\u9664","\u5DF2\u5220\u9664","\u5220\u6389","\u79FB\u9664","\u4E0D\u518D","\u4E0D\u53EF\u7528","\u4E0D\u80FD","\u65E0\u6CD5","\u7981\u7528","\u5E9F\u5F03"].some(o=>e.includes(o)):!1}function O(t){const e=new Set,o=t.trim();if(!o)return e;for(const r of o.matchAll(/[`'"]([^`'"]{1,64})[`'"]/g)){const n=r[1]?.trim().toLowerCase();n&&n.length>=2&&e.add(n)}for(const r of o.matchAll(/\b[a-z][a-z0-9._/-]{1,63}\b/gi)){const n=r[0]?.trim().toLowerCase();n&&!["system","startup","command","memory","instruction","user","deleted"].includes(n)&&e.add(n)}return e}function X(t,e){const o=O(t),r=O(e);if(o.size===0||r.size===0)return!1;for(const n of o)if(r.has(n))return!0;return!1}function Z(...t){const e=new Map;for(const o of t)for(const r of o){const n=e.get(r.record.id);(!n||r.score>n.score)&&e.set(r.record.id,r)}return Array.from(e.values()).sort((o,r)=>r.score-o.score||r.record.lastConfirmedAt.localeCompare(o.record.lastConfirmedAt)).map(o=>o.record)}function ee(t,e){const o=new Map;for(const r of t){const n=new Set(x(r)),a=I(r.content),m=I(r.summary??A(r.content)),f=typeof r.sourceRef=="string"?r.sourceRef.trim():"",s=`${r.summary??""}
3
+ ${r.content}`,c=J(s);for(const d of e){if(!n.has(d.scope))continue;let i=0,l=!1;f&&d.sourceRefs.includes(f)&&(i+=10,l=!0),I(d.content)===a&&(i+=9,l=!0),I(d.summary)===m&&(i+=8,l=!0);const p=y(d.summary,r.summary??r.content)*4+y(d.content,r.content)*3;if(i+=p,c){const g=d.operationalRule?.target?.trim().toLowerCase();g&&s.toLowerCase().includes(g)&&(i+=12,l=!0),X(s,`${d.summary}
4
+ ${d.content}`)&&(i+=8,l=!0)}if(!l&&p<1||i<=0)continue;const u=o.get(d.id);(!u||i>u.score)&&o.set(d.id,{record:d,score:i})}}return Array.from(o.values()).sort((r,n)=>n.score-r.score||n.record.lastConfirmedAt.localeCompare(r.record.lastConfirmedAt)).map(r=>r.record)}async function te(t){const e=await t.resolveVectorStore();if(!e)return[];const o=new Map(t.existingRecords.map(n=>[n.id,n])),r=new Map;try{for(const n of t.candidates){const a=new Set(x(n)),m=[n.summary?.trim(),n.content.trim()].filter(s=>!!s&&s.length>0).join(`
5
+ `);if(!m)continue;const f=await e.similaritySearch(m,8);for(const s of f){const c=typeof s.metadata=="object"&&s.metadata!==null&&!Array.isArray(s.metadata)?s.metadata:{},d=typeof c.recordId=="string"?c.recordId:void 0;if(!d)continue;const i=o.get(d);if(!i||i.status!=="active"||!a.has(i.scope))continue;const l=(typeof s.score=="number"?s.score:0)+S(i,m),p=r.get(i.id);(!p||l>p.score)&&r.set(i.id,{record:i,score:l})}}}catch{return[]}return Array.from(r.values()).sort((n,a)=>a.score-n.score||a.record.lastConfirmedAt.localeCompare(n.record.lastConfirmedAt))}function re(t){return[...t].sort((e,o)=>e.record.observedAt.localeCompare(o.record.observedAt)||e.record.createdAt.localeCompare(o.record.createdAt)||e.record.id.localeCompare(o.record.id))}function oe(t){const e=[...t.categories,typeof t.metadata.kind=="string"?t.metadata.kind:void 0,typeof t.metadata.memoryType=="string"?t.metadata.memoryType:void 0].filter(o=>typeof o=="string"&&o.trim().length>0);for(const o of e){const r=q(o);if(r==="semantic"||r==="episodic"||r==="procedural")return r}return"semantic"}function se(t,e){const o=typeof t.metadata.scope=="string"?t.metadata.scope:void 0;return o==="session"||o==="agent"||o==="workspace"||o==="user"||o==="project"?o:typeof t.metadata.sessionId=="string"&&e.sessionId&&t.metadata.sessionId===e.sessionId?"session":t.agentId===e.agentId||t.metadata.agentId===e.agentId?"agent":"workspace"}function ne(t,e){const o=se(t,e),r=oe(t),n=t.memory.split(`
6
+ `)[0]?.trim()||t.memory;return{id:`mem0:${t.id}`,canonicalKey:`mem0:${t.id}`,kind:r,scope:o,content:t.memory,summary:n.slice(0,240),status:"active",confidence:Math.max(0,Math.min(1,t.score||.5)),createdAt:t.createdAt,observedAt:t.createdAt,lastConfirmedAt:t.updatedAt,sourceType:"mem0-search",sourceRefs:[`mem0:${t.id}`],tags:t.categories,provenance:{source:"mem0",sessionId:typeof t.metadata.sessionId=="string"?t.metadata.sessionId:e.sessionId,requestId:typeof t.metadata.requestId=="string"?t.metadata.requestId:void 0,agentId:t.agentId??(typeof t.metadata.agentId=="string"?t.metadata.agentId:e.agentId),workspaceId:e.workspaceId,userId:e.userId,projectId:e.projectId,...t.metadata},revision:1,supersedes:[],conflictsWith:[]}}class ae{deps;constructor(e){this.deps=e}async memorize(e,o){if(!Array.isArray(e.records))throw new Error("memorize requires input.records to be an array.");const r=w(o),n=e.records.filter(s=>typeof s=="object"&&s!==null).filter(s=>s.noStore!==!0);if(n.length===0)return{records:[],decisions:[]};if(n.some(s=>typeof s.content!="string"||s.content.trim().length===0))throw new Error("memorize requires every record to include non-empty content.");if(n.some(s=>(s.scope??"session")==="session")&&!r.sessionId)throw new Error("memorize requires sessionId when storing session-scoped memory.");const a=r.recordedAt??new Date().toISOString(),m=r.requestId??R(new Date(a)),f=r.sessionId??`memory-api-${m}`;return this.memorizeCandidates(n.map(s=>({...s,content:s.content.trim()})),{...r,requestId:m,sessionId:f,recordedAt:a},{storeCandidateLog:e.storeCandidateLog!==!1,forceStore:e.forceStore===!0})}async recall(e,o){if(typeof e.query!="string"||e.query.trim().length===0)throw new Error("recall requires a non-empty query.");const r=w(o),n=W(e,r),a=typeof e.topK=="number"&&Number.isInteger(e.topK)&&e.topK>0?e.topK:this.deps.policy?.retrieval.defaultTopK??5,m=e.kinds?.length?new Set(e.kinds):null;return{items:(await this.rankRecallCandidates({query:e.query.trim(),scopes:n,kinds:m,topK:a,includeStale:e.includeStale===!0,context:r})).slice(0,a).map(({record:s})=>s)}}async buildPromptRecall(e,o){if(!_(e.query))return{items:[]};const r=w(o),n=(await this.rankRecallCandidates({query:e.query,scopes:e.scopes??k,kinds:e.kinds?.length?new Set(e.kinds):null,topK:e.topK??this.deps.policy?.retrieval.maxPromptMemories??8,includeStale:e.includeStale===!0,context:r})).filter(({record:s})=>!F(s)).map(s=>{const c=s.record.scope==="session"?4:s.record.scope==="agent"?3:s.record.scope==="user"?2:1;return{record:s.record,scope:s.record.scope,content:[`# Durable ${s.record.scope[0].toUpperCase()}${s.record.scope.slice(1)} Memory`,"",`- summary: ${s.record.summary}`,`- kind: ${s.record.kind}`,`- scope: ${s.record.scope}`,`- confidence: ${s.record.confidence.toFixed(2)}`,...s.record.knowledgeIdentity?[`- knowledge_identity: ${s.record.knowledgeIdentity}`,`- knowledge_operation: ${s.record.knowledgeOperation??"create"}`]:[],"",s.record.content].join(`
7
+ `),score:c+T(s.record.lastConfirmedAt)+s.record.confidence}}).sort((s,c)=>c.score-s.score);if(n.length===0)return{items:[]};const a=this.deps.policy?.retrieval.maxPromptMemories??8,m=n.slice(0,a);if(m.length===0)return{items:[]};const f=re(m);return{items:f.map(s=>s.record),context:f.map(s=>s.content).join(`
8
+
9
+ `)}}async buildPromptContext(e,o){return(await this.buildPromptRecall(e,o)).context}async list(e={},o){const r={...o},n=Array.isArray(e.scopes)&&e.scopes.length>0?Array.from(new Set(e.scopes)):k,a=e.kinds?.length?new Set(e.kinds):null,m=e.status?.length?new Set(e.status):new Set(["active"]),f=typeof e.limit=="number"&&Number.isInteger(e.limit)&&e.limit>0?e.limit:Number.POSITIVE_INFINITY;return{items:(await h(this.deps.store,n)).filter(c=>m.has(c.status)).filter(c=>!a||a.has(c.kind)).filter(c=>U(c,{sessionId:r.sessionId,agentId:r.agentId,workspaceId:r.workspaceId,userId:r.userId,projectId:r.projectId})).sort((c,d)=>d.lastConfirmedAt.localeCompare(c.lastConfirmedAt)).slice(0,f)}}async update(e,o){if(typeof e.memoryId!="string"||e.memoryId.trim().length===0)throw new Error("updateMemory requires a non-empty memoryId.");const r=await j(this.deps.store,e.memoryId.trim());if(!r)throw new Error(`Memory record not found: ${e.memoryId}`);const n=new Date().toISOString(),a=typeof e.content=="string"?e.content.trim():r.content;if(a.length===0)throw new Error("updateMemory requires content to remain non-empty.");const m={...r,content:a,summary:typeof e.summary=="string"?e.summary.trim()||A(a):typeof e.content=="string"?A(a):r.summary,status:e.status??r.status,confidence:typeof e.confidence=="number"?Math.max(0,Math.min(1,e.confidence)):r.confidence,expiresAt:e.expiresAt===void 0?r.expiresAt:e.expiresAt??void 0,sourceType:typeof e.sourceType=="string"&&e.sourceType.trim().length>0?e.sourceType.trim():r.sourceType,sourceRefs:Array.isArray(e.sourceRefs)?Array.from(new Set(e.sourceRefs.map(f=>f.trim()).filter(f=>f.length>0))):r.sourceRefs,tags:Array.isArray(e.tags)?Array.from(new Set(e.tags.map(f=>f.trim()).filter(f=>f.length>0))):r.tags,knowledgeIdentity:typeof e.knowledgeIdentity=="string"&&e.knowledgeIdentity.trim().length>0?e.knowledgeIdentity.trim():r.knowledgeIdentity,knowledgeOperation:e.knowledgeOperation==="create"||e.knowledgeOperation==="update"||e.knowledgeOperation==="delete"?e.knowledgeOperation:r.knowledgeOperation,observedAt:typeof e.observedAt=="string"&&e.observedAt.trim().length>0?e.observedAt:r.observedAt,lastConfirmedAt:typeof e.lastConfirmedAt=="string"&&e.lastConfirmedAt.trim().length>0?e.lastConfirmedAt:n,provenance:e.provenance?{...r.provenance,...e.provenance}:r.provenance,revision:r.revision+1};return await N(this.deps.store,m,n),await this.rebuildVectorIndex(),await this.refreshStructuredMemoryScope(m,o),m}async remove(e,o){if(typeof e.memoryId!="string"||e.memoryId.trim().length===0)throw new Error("removeMemory requires a non-empty memoryId.");const r=await j(this.deps.store,e.memoryId.trim());if(!r)throw new Error(`Memory record not found: ${e.memoryId}`);return await V(this.deps.store,r.scope,r.id),await this.rebuildVectorIndex(),await this.refreshStructuredMemoryScope(r,o),r}async memorizeCandidates(e,o,r){const n=w(o),a=e.filter(u=>u.noStore!==!0).filter(u=>typeof u.content=="string"&&u.content.trim().length>0).map(u=>({...u,content:u.content.trim()}));if(a.length===0)return{records:[],decisions:[]};const m=Array.from(new Set(a.flatMap(u=>x(u)))),f=await h(this.deps.store,m),s=await te({candidates:a,existingRecords:f,resolveVectorStore:this.deps.resolveVectorStore}),c=ee(a,f).map(u=>({record:u,score:E(u)})),d=Z(s,c),i=this.deps.transformCandidates?await this.deps.transformCandidates({candidates:a,context:n,existingRecords:d}):a,l=r.forceStore===!0?i:i.filter(u=>B(this.deps.policy,u));if(l.length===0)return{records:[],decisions:[]};r.storeCandidateLog&&await this.deps.store.put(["memories","candidates",n.sessionId??`memory-api-${n.requestId??"unknown"}`],`${n.requestId}.json`,{requestId:n.requestId,sessionId:n.sessionId,storedAt:n.recordedAt,candidates:l});const p=await P({store:this.deps.store,candidates:l,sessionId:n.sessionId??`memory-api-${n.requestId??"unknown"}`,requestId:n.requestId??R(new Date(n.recordedAt??new Date().toISOString())),agentId:n.agentId,workspaceId:n.workspaceId,userId:n.userId??"default",projectId:n.projectId??n.workspaceId,recordedAt:n.recordedAt??new Date().toISOString()});return await this.rebuildVectorIndex(),await this.refreshAfterWrite(l,n),p}async refreshAfterWrite(e,o){const r={session:e.filter(a=>(a.scope??"session")==="session"),agent:e.filter(a=>(a.scope??"session")==="agent"),workspace:e.filter(a=>(a.scope??"session")==="workspace"),user:e.filter(a=>(a.scope??"session")==="user"),project:e.filter(a=>(a.scope??"session")==="project")},n=[];for(const a of k){if(r[a].length===0)continue;const m=a==="session"?12:20;n.push(this.appendMemoryDigest(this.deps.resolveNamespace(a,o),"tool-memory.md",r[a],m,v[a].replace("Structured","Tool"))),n.push(b({store:this.deps.store,namespace:this.deps.resolveNamespace(a,o),title:v[a],scope:a,maxEntries:m,config:this.deps.maintenanceConfig??void 0}))}await Promise.all(n)}async appendMemoryDigest(e,o,r,n,a){const m=await this.deps.store.get(e,o),s=[...Array.isArray(m?.value?.items)?(m?.value).items??[]:[]];for(const i of r)s.some(l=>l.content===i.content&&(l.scope??"session")===(i.scope??"session"))||s.push(i);const c=s.slice(-n),d=new Map;for(const i of c){const l=q(i.kind),p=d.get(l)??[];p.push({...i,kind:l}),d.set(l,p)}await this.deps.store.put(e,o,{content:`${z(a,c)}
10
+ `,items:c}),await Promise.all(Array.from(d.entries()).map(async([i,l])=>{await this.deps.store.put(e,`${i}.md`,{content:`${z(`${a} (${i})`,l)}
11
+ `,items:l})}))}async refreshStructuredMemoryScope(e,o){const r=e.provenance,n={sessionId:r.sessionId,agentId:r.agentId??o.agentId,workspaceId:r.workspaceId??o.workspaceId,userId:r.userId??o.userId,projectId:r.projectId??o.projectId},a=e.scope==="session"?12:20;await b({store:this.deps.store,namespace:this.deps.resolveNamespace(e.scope,w(n)),title:v[e.scope],scope:e.scope,maxEntries:a,config:this.deps.maintenanceConfig??void 0})}async rebuildVectorIndex(){const e=await this.deps.resolveVectorStore();if(!e)return;const o=(await h(this.deps.store,k)).filter(r=>r.status==="active");try{if(await e.delete({deleteAll:!0}),o.length===0)return;await e.addDocuments(o.map(r=>({pageContent:`${r.summary}
12
+ ${r.content}`,metadata:{recordId:r.id,scope:r.scope,kind:r.kind,status:r.status,sessionId:r.provenance.sessionId,agentId:r.provenance.agentId,workspaceId:r.provenance.workspaceId,userId:r.provenance.userId,projectId:r.provenance.projectId,confidence:r.confidence,lastConfirmedAt:r.lastConfirmedAt}})))}catch{}}async rankRecallCandidates(e){const r=(await h(this.deps.store,e.scopes)).filter(s=>$(s,{sessionId:e.context.sessionId,agentId:e.context.agentId,workspaceId:e.context.workspaceId,userId:e.context.userId??"default",projectId:e.context.projectId??e.context.workspaceId})).filter(s=>e.includeStale?s.status==="active"||s.status==="stale":s.status==="active").filter(s=>e.kinds?e.kinds.has(s.kind):!0).map(s=>({record:s,score:S(s,e.query)})),n=new Map;for(const s of r)n.set(M(s.record),s);const a=await this.deps.resolveVectorStore();if(a)try{const s=await a.similaritySearch(e.query,Math.max(e.topK,this.deps.policy?.retrieval.maxPromptMemories??e.topK));for(const c of s){const d=typeof c.metadata=="object"&&c.metadata&&!Array.isArray(c.metadata)?c.metadata:{},i=typeof d.recordId=="string"?d.recordId:void 0,l=d.scope;if(!i||l!=="session"&&l!=="agent"&&l!=="workspace"&&l!=="user"&&l!=="project")continue;const p=await D(this.deps.store,l,i);if(!p||!$(p,{sessionId:e.context.sessionId,agentId:e.context.agentId,workspaceId:e.context.workspaceId,userId:e.context.userId??"default",projectId:e.context.projectId??e.context.workspaceId})||(e.includeStale?p.status!=="active"&&p.status!=="stale":p.status!=="active")||e.kinds&&!e.kinds.has(p.kind))continue;const u=M(p),g=S(p,e.query)+(typeof c.score=="number"?c.score:0),C=n.get(u);(!C||g>C.score)&&n.set(u,{record:p,score:g})}}catch{}const m=e.scopes.some(s=>s==="session"||s==="agent"||s==="workspace"),f=this.deps.getMem0SemanticRecall?.()??null;if(!f||!m)return Array.from(n.values()).sort((s,c)=>c.score-s.score);try{const s=await f.search({query:e.query,topK:Math.max(e.topK,this.deps.policy?.retrieval.maxPromptMemories??e.topK),agentId:e.context.agentId,sessionId:e.context.sessionId});for(const c of s){const d=ne(c,{sessionId:e.context.sessionId,agentId:e.context.agentId,workspaceId:e.context.workspaceId,userId:e.context.userId??"default",projectId:e.context.projectId??e.context.workspaceId});if(!e.scopes.includes(d.scope)||e.kinds&&!e.kinds.has(d.kind))continue;const i=M(d);n.has(i)||n.set(i,{record:d,score:S(d,e.query)+Math.max(0,Math.min(1,c.score))*4})}return Array.from(n.values()).sort((c,d)=>d.score-c.score)}catch{return Array.from(n.values()).sort((s,c)=>c.score-s.score)}}}function fe(t){return new ae(t)}export{ae as DefaultKnowledgeModule,fe as createKnowledgeModule};