melchizedek-agents 0.18.0 → 0.19.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 (281) hide show
  1. package/.env.example +12 -0
  2. package/CHANGELOG.md +825 -0
  3. package/DOCUMENTATION.md +217 -59
  4. package/README.md +42 -1
  5. package/config/agents/examples/harness.yaml +3 -1
  6. package/config/agents/examples/model_zoo.yaml +10 -9
  7. package/config/agents/syndicateSchema.yaml +50 -16
  8. package/config/agents/templates/account_memory.yaml +2 -6
  9. package/config/agents/templates/case_desk.yaml +3 -9
  10. package/config/agents/templates/draft_review.yaml +3 -9
  11. package/config/agents/templates/intake_extractor.yaml +1 -3
  12. package/config/agents/templates/research_brief.yaml +3 -9
  13. package/config/agents/templates/research_desk.yaml +3 -9
  14. package/config/agents/templates/review_panel.yaml +4 -12
  15. package/config/agents/templates/support_triage.yaml +4 -12
  16. package/config/agents/templates/systems_operator.yaml +2 -6
  17. package/db/hardening.sql +7 -1
  18. package/db/migrations/0013_tool_credentials.sql +260 -0
  19. package/dist/lib/a2a/app.d.ts +70 -6
  20. package/dist/lib/a2a/app.js +107 -2
  21. package/dist/lib/a2a/executor.d.ts +20 -3
  22. package/dist/lib/a2a/executor.js +66 -7
  23. package/dist/lib/a2a/remoteAgent.d.ts +24 -9
  24. package/dist/lib/a2a/remoteAgent.js +31 -14
  25. package/dist/lib/compile.d.ts +121 -30
  26. package/dist/lib/compile.js +137 -124
  27. package/dist/lib/compileAdk.d.ts +29 -0
  28. package/dist/lib/compileAdk.js +132 -0
  29. package/dist/lib/compileNative.d.ts +85 -0
  30. package/dist/lib/compileNative.js +222 -0
  31. package/dist/lib/config.d.ts +6 -5
  32. package/dist/lib/config.js +6 -5
  33. package/dist/lib/doctor.js +1 -0
  34. package/dist/lib/index.d.ts +2 -1
  35. package/dist/lib/index.js +2 -1
  36. package/dist/lib/loadSyndicate.d.ts +18 -0
  37. package/dist/lib/memory/erase.d.ts +5 -3
  38. package/dist/lib/memory/erase.js +5 -2
  39. package/dist/lib/memory/namespace.d.ts +8 -1
  40. package/dist/lib/memory/namespace.js +12 -6
  41. package/dist/lib/memory/providers.js +2 -1
  42. package/dist/lib/memory/supabaseMemoryService.d.ts +37 -3
  43. package/dist/lib/memory/supabaseMemoryService.js +42 -2
  44. package/dist/lib/model.d.ts +47 -0
  45. package/dist/lib/model.js +37 -0
  46. package/dist/lib/models/adapterResolver.d.ts +113 -0
  47. package/dist/lib/models/adapterResolver.js +136 -0
  48. package/dist/lib/models/adkGeminiAdapter.d.ts +90 -0
  49. package/dist/lib/models/adkGeminiAdapter.js +367 -0
  50. package/dist/lib/models/adkShim.d.ts +111 -0
  51. package/dist/lib/models/adkShim.js +136 -0
  52. package/dist/lib/models/capabilities.d.ts +3 -0
  53. package/dist/lib/models/capabilities.js +20 -13
  54. package/dist/lib/models/chatCompletionsAdapter.d.ts +279 -0
  55. package/dist/lib/models/chatCompletionsAdapter.js +854 -0
  56. package/dist/lib/models/circuitBreaker.d.ts +42 -0
  57. package/dist/lib/models/circuitBreaker.js +70 -0
  58. package/dist/lib/models/claudeAdapter.d.ts +103 -0
  59. package/dist/lib/models/claudeAdapter.js +669 -0
  60. package/dist/lib/models/claudeLlm.d.ts +39 -62
  61. package/dist/lib/models/claudeLlm.js +44 -349
  62. package/dist/lib/models/claudeModels.d.ts +127 -0
  63. package/dist/lib/models/claudeModels.js +237 -0
  64. package/dist/lib/models/contract.d.ts +395 -0
  65. package/dist/lib/models/contract.js +39 -0
  66. package/dist/lib/models/endpoints.js +2 -1
  67. package/dist/lib/models/errorResponse.d.ts +50 -0
  68. package/dist/lib/models/errorResponse.js +48 -0
  69. package/dist/lib/models/fallback.d.ts +17 -10
  70. package/dist/lib/models/fallback.js +53 -42
  71. package/dist/lib/models/fallbackAdapter.d.ts +55 -0
  72. package/dist/lib/models/fallbackAdapter.js +62 -0
  73. package/dist/lib/models/gateway.js +2 -1
  74. package/dist/lib/models/gatewayAdapter.d.ts +51 -0
  75. package/dist/lib/models/gatewayAdapter.js +81 -0
  76. package/dist/lib/models/gatewayLlm.d.ts +12 -33
  77. package/dist/lib/models/gatewayLlm.js +14 -75
  78. package/dist/lib/models/geminiAdapter.d.ts +123 -0
  79. package/dist/lib/models/geminiAdapter.js +831 -0
  80. package/dist/lib/models/geminiState.d.ts +25 -0
  81. package/dist/lib/models/geminiState.js +25 -0
  82. package/dist/lib/models/genaiMapping.d.ts +263 -0
  83. package/dist/lib/models/genaiMapping.js +862 -0
  84. package/dist/lib/models/gptAdapter.d.ts +240 -0
  85. package/dist/lib/models/gptAdapter.js +804 -0
  86. package/dist/lib/models/gptLlm.d.ts +63 -123
  87. package/dist/lib/models/gptLlm.js +88 -602
  88. package/dist/lib/models/grokAdapter.d.ts +86 -0
  89. package/dist/lib/models/grokAdapter.js +142 -0
  90. package/dist/lib/models/grokLlm.d.ts +22 -45
  91. package/dist/lib/models/grokLlm.js +22 -67
  92. package/dist/lib/models/kimiAdapter.d.ts +157 -0
  93. package/dist/lib/models/kimiAdapter.js +203 -0
  94. package/dist/lib/models/kimiLlm.d.ts +15 -107
  95. package/dist/lib/models/kimiLlm.js +17 -153
  96. package/dist/lib/models/ollamaAdapter.d.ts +125 -0
  97. package/dist/lib/models/ollamaAdapter.js +155 -0
  98. package/dist/lib/models/ollamaLlm.d.ts +11 -107
  99. package/dist/lib/models/ollamaLlm.js +13 -151
  100. package/dist/lib/models/openAiCompatibleLlm.d.ts +73 -216
  101. package/dist/lib/models/openAiCompatibleLlm.js +109 -671
  102. package/dist/lib/models/providerState.d.ts +63 -0
  103. package/dist/lib/models/providerState.js +61 -0
  104. package/dist/lib/models/reasoning.d.ts +26 -0
  105. package/dist/lib/models/reasoning.js +59 -0
  106. package/dist/lib/models/registry.d.ts +58 -35
  107. package/dist/lib/models/registry.js +89 -118
  108. package/dist/lib/models/retry.d.ts +2 -1
  109. package/dist/lib/models/retry.js +3 -2
  110. package/dist/lib/models/schemaNormalize.d.ts +98 -0
  111. package/dist/lib/models/schemaNormalize.js +321 -1
  112. package/dist/lib/models/tracedGemini.d.ts +41 -0
  113. package/dist/lib/models/tracedGemini.js +98 -0
  114. package/dist/lib/models/urls.d.ts +11 -0
  115. package/dist/lib/models/urls.js +16 -0
  116. package/dist/lib/net/redirects.d.ts +21 -2
  117. package/dist/lib/net/redirects.js +11 -34
  118. package/dist/lib/observability/audit.d.ts +5 -1
  119. package/dist/lib/observability/lineage.d.ts +14 -0
  120. package/dist/lib/observability/lineage.js +33 -0
  121. package/dist/lib/observability/supabaseSpanExporter.d.ts +10 -4
  122. package/dist/lib/observability/supabaseSpanExporter.js +17 -9
  123. package/dist/lib/observability/tracer.d.ts +26 -8
  124. package/dist/lib/observability/tracer.js +43 -18
  125. package/dist/lib/runtime/adkMemoryBridge.d.ts +46 -0
  126. package/dist/lib/runtime/adkMemoryBridge.js +68 -0
  127. package/dist/lib/runtime/adkSessionBridge.d.ts +78 -0
  128. package/dist/lib/runtime/adkSessionBridge.js +176 -0
  129. package/dist/lib/runtime/credentials.d.ts +59 -0
  130. package/dist/lib/runtime/credentials.js +62 -0
  131. package/dist/lib/runtime/events.d.ts +229 -0
  132. package/dist/lib/runtime/events.js +274 -0
  133. package/dist/lib/runtime/logging.d.ts +32 -0
  134. package/dist/lib/runtime/logging.js +55 -0
  135. package/dist/lib/runtime/memoryService.d.ts +72 -0
  136. package/dist/lib/runtime/memoryService.js +25 -0
  137. package/dist/lib/runtime/native/agentLoop.d.ts +203 -0
  138. package/dist/lib/runtime/native/agentLoop.js +687 -0
  139. package/dist/lib/runtime/native/compaction.d.ts +103 -0
  140. package/dist/lib/runtime/native/compaction.js +191 -0
  141. package/dist/lib/runtime/native/delegate.d.ts +98 -0
  142. package/dist/lib/runtime/native/delegate.js +173 -0
  143. package/dist/lib/runtime/native/history.d.ts +83 -0
  144. package/dist/lib/runtime/native/history.js +312 -0
  145. package/dist/lib/runtime/native/interrupts.d.ts +126 -0
  146. package/dist/lib/runtime/native/interrupts.js +291 -0
  147. package/dist/lib/runtime/native/request.d.ts +215 -0
  148. package/dist/lib/runtime/native/request.js +585 -0
  149. package/dist/lib/runtime/native/selfCorrection.d.ts +106 -0
  150. package/dist/lib/runtime/native/selfCorrection.js +253 -0
  151. package/dist/lib/runtime/native/step.d.ts +148 -0
  152. package/dist/lib/runtime/native/step.js +239 -0
  153. package/dist/lib/runtime/native/taskMode.d.ts +64 -0
  154. package/dist/lib/runtime/native/taskMode.js +126 -0
  155. package/dist/lib/runtime/native/telemetry.d.ts +75 -0
  156. package/dist/lib/runtime/native/telemetry.js +299 -0
  157. package/dist/lib/runtime/native/tempState.d.ts +31 -0
  158. package/dist/lib/runtime/native/tempState.js +56 -0
  159. package/dist/lib/runtime/nativeTurn.d.ts +86 -0
  160. package/dist/lib/runtime/nativeTurn.js +107 -0
  161. package/dist/lib/runtime/questions.d.ts +29 -7
  162. package/dist/lib/runtime/questions.js +47 -32
  163. package/dist/lib/runtime/runtimeFlag.d.ts +30 -0
  164. package/dist/lib/runtime/runtimeFlag.js +50 -0
  165. package/dist/lib/runtime/sessions.d.ts +166 -0
  166. package/dist/lib/runtime/sessions.js +201 -0
  167. package/dist/lib/runtime/syndicateTurn.d.ts +41 -5
  168. package/dist/lib/runtime/syndicateTurn.js +202 -32
  169. package/dist/lib/session/supabaseSessionService.d.ts +64 -17
  170. package/dist/lib/session/supabaseSessionService.js +148 -105
  171. package/dist/lib/session/transcript.d.ts +68 -22
  172. package/dist/lib/session/transcript.js +102 -28
  173. package/dist/lib/skills.js +33 -7
  174. package/dist/lib/storage/postgres/credentialStore.d.ts +20 -0
  175. package/dist/lib/storage/postgres/credentialStore.js +82 -0
  176. package/dist/lib/storage/postgres/index.d.ts +12 -0
  177. package/dist/lib/storage/postgres/index.js +6 -1
  178. package/dist/lib/storage/postgres/sessionService.d.ts +43 -15
  179. package/dist/lib/storage/postgres/sessionService.js +128 -66
  180. package/dist/lib/syndicateSchema.d.ts +47 -0
  181. package/dist/lib/syndicateSchema.js +72 -3
  182. package/dist/lib/toolRegistry.d.ts +15 -2
  183. package/dist/lib/toolRegistry.js +33 -17
  184. package/dist/lib/tools/adkTool.d.ts +81 -0
  185. package/dist/lib/tools/adkTool.js +268 -0
  186. package/dist/lib/tools/auth.d.ts +118 -0
  187. package/dist/lib/tools/auth.js +89 -0
  188. package/dist/lib/tools/collectionsSearchTool.d.ts +7 -6
  189. package/dist/lib/tools/collectionsSearchTool.js +11 -26
  190. package/dist/lib/tools/credentialCipher.d.ts +58 -0
  191. package/dist/lib/tools/credentialCipher.js +116 -0
  192. package/dist/lib/tools/credentialStore.d.ts +77 -0
  193. package/dist/lib/tools/credentialStore.js +246 -0
  194. package/dist/lib/tools/examples.d.ts +43 -0
  195. package/dist/lib/tools/examples.js +62 -0
  196. package/dist/lib/tools/generateImageTool.d.ts +15 -6
  197. package/dist/lib/tools/generateImageTool.js +19 -29
  198. package/dist/lib/tools/inspectImageTool.d.ts +9 -6
  199. package/dist/lib/tools/inspectImageTool.js +13 -17
  200. package/dist/lib/tools/mcpToolFactory.d.ts +42 -1
  201. package/dist/lib/tools/mcpToolFactory.js +46 -47
  202. package/dist/lib/tools/memoryTools.d.ts +61 -0
  203. package/dist/lib/tools/memoryTools.js +119 -0
  204. package/dist/lib/tools/nativeTools.d.ts +38 -0
  205. package/dist/lib/tools/nativeTools.js +43 -0
  206. package/dist/lib/tools/oauthConsent.d.ts +181 -0
  207. package/dist/lib/tools/oauthConsent.js +330 -0
  208. package/dist/lib/tools/openapi/call.d.ts +108 -0
  209. package/dist/lib/tools/openapi/call.js +295 -0
  210. package/dist/lib/tools/openapi/parse.d.ts +147 -0
  211. package/dist/lib/tools/openapi/parse.js +570 -0
  212. package/dist/lib/tools/openapiTools.d.ts +25 -17
  213. package/dist/lib/tools/openapiTools.js +124 -121
  214. package/dist/lib/tools/scienceTools.d.ts +14 -14
  215. package/dist/lib/tools/skillToolset.d.ts +58 -87
  216. package/dist/lib/tools/skillToolset.js +61 -142
  217. package/dist/lib/tools/skills/env.d.ts +58 -0
  218. package/dist/lib/tools/skills/env.js +165 -0
  219. package/dist/lib/tools/skills/executor.d.ts +114 -0
  220. package/dist/lib/tools/skills/executor.js +331 -0
  221. package/dist/lib/tools/skills/frontmatter.d.ts +79 -0
  222. package/dist/lib/tools/skills/frontmatter.js +215 -0
  223. package/dist/lib/tools/skills/loader.d.ts +91 -0
  224. package/dist/lib/tools/skills/loader.js +257 -0
  225. package/dist/lib/tools/skills/tools.d.ts +187 -0
  226. package/dist/lib/tools/skills/tools.js +386 -0
  227. package/dist/lib/tools/taskTools.d.ts +15 -15
  228. package/dist/lib/tools/tool.d.ts +354 -0
  229. package/dist/lib/tools/tool.js +304 -0
  230. package/dist/lib/tools/toolContract.d.ts +89 -33
  231. package/dist/lib/tools/toolContract.js +104 -82
  232. package/dist/lib/tools/urlContextTool.d.ts +3 -0
  233. package/dist/lib/tools/urlContextTool.js +5 -1
  234. package/dist/lib/tools/webExtractTool.d.ts +2 -2
  235. package/dist/lib/tools/webExtractTool.js +2 -1
  236. package/dist/lib/tools/webSearchTool.d.ts +6 -9
  237. package/dist/lib/tools/webSearchTool.js +14 -59
  238. package/dist/lib/tools/wikiTools.d.ts +19 -19
  239. package/dist/lib/tools/wikiTools.js +13 -9
  240. package/dist/lib/tools/xApiSearchTool.d.ts +2 -2
  241. package/dist/lib/tools/xApiSearchTool.js +2 -1
  242. package/dist/lib/tools/xSearchTool.d.ts +7 -9
  243. package/dist/lib/tools/xSearchTool.js +11 -62
  244. package/dist/lib/tools/xaiSearchParams.d.ts +41 -0
  245. package/dist/lib/tools/xaiSearchParams.js +126 -0
  246. package/dist/lib/wiki/agentRun.d.ts +12 -0
  247. package/dist/lib/wiki/agentRun.js +72 -34
  248. package/dist/lib/wiki/entities.d.ts +12 -0
  249. package/dist/lib/wiki/entities.js +45 -3
  250. package/dist/lib/workflow/agentNode.d.ts +136 -0
  251. package/dist/lib/workflow/agentNode.js +274 -0
  252. package/dist/lib/workflow/graph.d.ts +177 -0
  253. package/dist/lib/workflow/graph.js +458 -0
  254. package/dist/lib/workflow/nodeEvents.d.ts +50 -0
  255. package/dist/lib/workflow/nodeEvents.js +101 -0
  256. package/dist/lib/workflow/pause.d.ts +122 -0
  257. package/dist/lib/workflow/pause.js +180 -0
  258. package/dist/lib/workflow/resume.d.ts +165 -0
  259. package/dist/lib/workflow/resume.js +440 -0
  260. package/dist/lib/workflow/route.d.ts +58 -0
  261. package/dist/lib/workflow/route.js +69 -0
  262. package/dist/lib/workflow/scheduler.d.ts +415 -0
  263. package/dist/lib/workflow/scheduler.js +743 -0
  264. package/dist/lib/workflow/toolNode.d.ts +127 -0
  265. package/dist/lib/workflow/toolNode.js +236 -0
  266. package/dist/lib/workflow/turn.d.ts +118 -0
  267. package/dist/lib/workflow/turn.js +216 -0
  268. package/dist/lib/workflowConfig.d.ts +3 -2
  269. package/dist/lib/workflowConfig.js +3 -12
  270. package/dist/scripts/a2a_server.js +4 -3
  271. package/dist/scripts/assistant_worker.d.ts +2 -1
  272. package/dist/scripts/assistant_worker.js +9 -4
  273. package/dist/scripts/syndicate_chat.js +19 -10
  274. package/package.json +4 -1
  275. package/skills/briefs/melchizedek-author.md +3 -2
  276. package/skills/briefs/melchizedek-models.md +13 -9
  277. package/skills/briefs/melchizedek.md +3 -3
  278. package/skills/melchizedek/SKILL.md +2 -1
  279. package/skills/melchizedek-author/SKILL.md +2 -1
  280. package/skills/melchizedek-author/assets/minimal.yaml +2 -0
  281. package/skills/melchizedek-models/SKILL.md +23 -6
@@ -0,0 +1,222 @@
1
+ /**
2
+ * lib/compileNative.ts — an AgentSpec as the native runtime runs it: the
3
+ * NativeAgent the agent loop takes (ADR 0045, ADR 0073).
4
+ *
5
+ * WHY this file exists:
6
+ * lib/compile.ts turns a YAML agent into a runtime-neutral AgentSpec, and
7
+ * lib/compileAdk.ts builds ADK's LlmAgent from it. This file builds the
8
+ * native loop's agent from the same spec (lib/runtime/native/request.ts,
9
+ * NativeAgent), so both runtimes run the agent the YAML describes, with
10
+ * the same tools, instruction and config. tests/compile.test.ts compiles
11
+ * one spec both ways and requires the same first request.
12
+ *
13
+ * TOOLS: each resolved tool is handed to the loop as the own Tool or
14
+ * InstructionTool behind it (lib/tools/tool.ts), else as itself: an MCP
15
+ * tool, the skills toolset, a gated registry FunctionTool, which the loop
16
+ * runs by shape during the dual period (ADR 0071). A delegated subagent
17
+ * becomes a subagentTool holding its own NativeAgent, which the loop runs as
18
+ * a child loop (lib/runtime/native/delegate.ts, ADR 0074), a nested
19
+ * syndicate as its orchestrator's agent; a remote A2A subagent is the own
20
+ * Tool the ADK runtime's FunctionTool wraps (lib/a2a/remoteAgent.ts).
21
+ *
22
+ * EVERY AGENT KEY COMPILES for the native loop: `context:` is handed to
23
+ * the loop, which compacts as ADK does (lib/runtime/native/compaction.ts,
24
+ * WS2-9); `mode: task` and `code_execution: gemini` pass through, the
25
+ * request declaring finish_task (lib/runtime/native/taskMode.ts) and asking
26
+ * Gemini for its code-execution tool (lib/runtime/native/request.ts). What
27
+ * native does not run yet (workflows, resuming an approval or a
28
+ * question, a caller's agent transform) is refused by the turn runner
29
+ * (lib/runtime/nativeTurn.ts), which owns those choices.
30
+ *
31
+ * THE MODEL: the loop calls a model through its contract adapter. A
32
+ * resolver may return an id, a contract adapter, an ADK shim (which carries
33
+ * one) or ADK's Gemini (TracedGemini), whose key reaches the registry's
34
+ * Gemini adapter. Any other ADK model class has no adapter behind it, so
35
+ * compileNative and nativeAdapterFor refuse it with UnsupportedOnRuntimeError
36
+ * before any model call, naming adkShim as the way to run it on native,
37
+ * rather than run the registry's model for that id in its place (ADR 0088).
38
+ * ADK classes are told apart by ADK's own Symbol.for marks, so this file
39
+ * imports nothing from ADK.
40
+ */
41
+ import { remoteAgentOwnTool } from './a2a/remoteAgent.js';
42
+ import { compileSpec, compileSubagentSpec } from './compile.js';
43
+ import { providerForModel, resolveAdapter } from './models/registry.js';
44
+ import { subagentTool } from './runtime/native/delegate.js';
45
+ import { unsupportedOnNative } from './runtime/runtimeFlag.js';
46
+ export { UnsupportedOnRuntimeError, unsupportedOnNative } from './runtime/runtimeFlag.js';
47
+ import { instructionToolOf, toolOf, toolsetOf } from './tools/tool.js';
48
+ /** A resolved tool as the loop holds it: the own Tool, InstructionTool or Toolset behind it, else the object itself. */
49
+ function nativeTool(tool) {
50
+ return toolOf(tool) ?? instructionToolOf(tool) ?? toolsetOf(tool) ?? tool;
51
+ }
52
+ /** ADK's own marks on its model classes (BaseLlm, Gemini), registered with Symbol.for so they hold across copies of ADK. */
53
+ const ADK_BASE_MODEL = Symbol.for('google.adk.baseModel');
54
+ const ADK_GEMINI_MODEL = Symbol.for('google.adk.geminiModel');
55
+ const marked = (value, mark) => !!value && typeof value === 'object' && value[mark] === true;
56
+ /**
57
+ * The class name of an ADK model the native runtime cannot run, else
58
+ * undefined: an ADK BaseLlm that is neither ADK's Gemini (TracedGemini
59
+ * included) nor a shim carrying a contract adapter (lib/models/adkShim.ts).
60
+ */
61
+ export function unrunnableModelClass(resolved) {
62
+ if (!marked(resolved, ADK_BASE_MODEL) || marked(resolved, ADK_GEMINI_MODEL))
63
+ return undefined;
64
+ if (isModelAdapter(resolved.adapter))
65
+ return undefined;
66
+ const name = resolved.constructor?.name;
67
+ return typeof name === 'string' && name ? name : 'BaseLlm';
68
+ }
69
+ /** Throws UnsupportedOnRuntimeError when `resolved` is an ADK model class native cannot run (see the header). */
70
+ function refuseModelClass(resolved, modelId, where) {
71
+ const name = unrunnableModelClass(resolved);
72
+ if (!name)
73
+ return;
74
+ throw unsupportedOnNative(`the ADK model class ${name} that resolveModel returned${modelId ? ` for '${modelId}'` : ''}, which has no contract adapter behind it ` +
75
+ `(return the ModelAdapter itself, or adkShim(adapter) from melchizedek-agents/models/adkShim, to run it on native)`, where);
76
+ }
77
+ /**
78
+ * The NativeAgent for `spec`. Throws when no model id is known, and
79
+ * UnsupportedOnRuntimeError when the resolver returned an ADK model class
80
+ * the loop cannot call (see the header).
81
+ */
82
+ export function compileNative(spec) {
83
+ refuseModelClass(spec.resolvedModel, spec.model ?? spec.modelId, spec.name);
84
+ const tools = [];
85
+ for (const entry of spec.tools) {
86
+ if (entry.kind === 'agent')
87
+ tools.push(subagentTool(compileNative(entry.agent)));
88
+ else if (entry.kind === 'remote')
89
+ tools.push(remoteAgentOwnTool({ name: entry.name, description: entry.description, url: entry.url }));
90
+ else
91
+ tools.push(nativeTool(entry.tool));
92
+ }
93
+ const model = wireModelOf(spec);
94
+ if (!model)
95
+ throw new Error(`${spec.name}: no model id to run on (the YAML names none and the resolver returned none).`);
96
+ const agent = {
97
+ name: spec.name,
98
+ model,
99
+ instruction: spec.instruction,
100
+ tools,
101
+ generateContentConfig: spec.generateContentConfig,
102
+ };
103
+ if (spec.description)
104
+ agent.description = spec.description;
105
+ if (spec.globalInstruction !== undefined)
106
+ agent.globalInstruction = spec.globalInstruction;
107
+ if (spec.outputSchema)
108
+ agent.outputSchema = spec.outputSchema;
109
+ if (spec.includeContents !== undefined)
110
+ agent.includeContents = spec.includeContents;
111
+ if (spec.disallowTransferToParent !== undefined)
112
+ agent.disallowTransferToParent = spec.disallowTransferToParent;
113
+ if (spec.disallowTransferToPeers !== undefined)
114
+ agent.disallowTransferToPeers = spec.disallowTransferToPeers;
115
+ if (spec.codeExecution)
116
+ agent.codeExecution = spec.codeExecution;
117
+ if (spec.mode)
118
+ agent.mode = spec.mode;
119
+ if (spec.outputKey !== undefined)
120
+ agent.outputKey = spec.outputKey;
121
+ if (spec.fallbackModel)
122
+ agent.fallbackModel = spec.fallbackModel;
123
+ if (spec.context)
124
+ agent.context = spec.context;
125
+ return agent;
126
+ }
127
+ /**
128
+ * The model id a request is sent under, as ADK's LlmAgent sends it: the id
129
+ * of the model object the resolver returned (an ADK model or a contract
130
+ * adapter carries its own), else the id the resolver returned, else the
131
+ * spec's. A resolver may answer a YAML id with a model under another id (a
132
+ * gateway stand-in, a caller's alias); the adapter, the span and the
133
+ * circuit breaker then see that id on both runtimes.
134
+ */
135
+ export function wireModelOf(spec) {
136
+ const resolved = spec.resolvedModel;
137
+ if (typeof resolved === 'string' && resolved)
138
+ return resolved;
139
+ const own = resolved && typeof resolved === 'object' ? resolved.model : undefined;
140
+ if (typeof own === 'string' && own)
141
+ return own;
142
+ return spec.modelId;
143
+ }
144
+ /** A syndicate's orchestrator for the native loop: compileSpec, then compileNative. */
145
+ export async function compileNativeGraph(config, opts = {}) {
146
+ return compileNative(await compileSpec(config, opts));
147
+ }
148
+ /** One subagent entry (a dispatch route) for the native loop: compileSubagentSpec, then compileNative. */
149
+ export async function compileNativeSubagent(subCfg, opts = {}) {
150
+ return compileNative(await compileSubagentSpec(subCfg, opts));
151
+ }
152
+ function isModelAdapter(value) {
153
+ return !!value && typeof value === 'object' && typeof value.generate === 'function' && typeof value.model === 'string';
154
+ }
155
+ /**
156
+ * The contract adapter behind what a resolver returned: an ADK shim's own
157
+ * adapter; for an ADK class that is not a shim (TracedGemini, ADK's Gemini)
158
+ * the registry's adapter under the key the instance carries, so a caller's
159
+ * BYOK key still pays for the call; else the registry's for the id.
160
+ */
161
+ function adapterOf(resolved, model) {
162
+ if (isModelAdapter(resolved))
163
+ return resolved;
164
+ refuseModelClass(resolved, model, 'the native runtime');
165
+ if (typeof resolved === 'string')
166
+ return resolveAdapter(resolved || model);
167
+ if (!resolved || typeof resolved !== 'object')
168
+ return resolveAdapter(model);
169
+ const held = resolved;
170
+ if (isModelAdapter(held.adapter))
171
+ return held.adapter;
172
+ // On Vertex AI the client authenticates with the platform's credentials, never a key (ADR 0023).
173
+ if (typeof held.apiKey === 'string' && held.apiKey && held.vertexai !== true) {
174
+ return resolveAdapter(model, { apiKey: held.apiKey, keyProvider: providerForModel(model) });
175
+ }
176
+ return resolveAdapter(model);
177
+ }
178
+ /**
179
+ * The loop's `adapterFor` under the same model resolution the ADK runtime
180
+ * uses: the leaf adapter behind what CompileOptions.resolveModel returns
181
+ * (an ADK shim carries its contract adapter, so a caller's BYOK key on a
182
+ * shimmed provider reaches the call), else resolveAdapter for the id
183
+ * (lib/models/registry.ts). The spec's own resolution, and each delegated
184
+ * subagent's, is reused for the id its agent runs under (wireModelOf).
185
+ * Each agent's `fallback_model:` and compaction `summary_model` are
186
+ * resolved here, as compileAdk resolves them at compile time, so a model
187
+ * class native cannot run is refused before any model call; any other id
188
+ * is resolved when first asked for. Each is kept.
189
+ */
190
+ export function nativeAdapterFor(opts = {}, spec) {
191
+ const cache = new Map();
192
+ const known = new Map();
193
+ const learn = (s) => {
194
+ if (s.resolvedModel !== undefined) {
195
+ for (const id of [wireModelOf(s), s.modelId])
196
+ if (id && !known.has(id))
197
+ known.set(id, s.resolvedModel);
198
+ }
199
+ for (const id of [s.fallbackModel, s.context?.summary_model]) {
200
+ if (!id || known.has(id) || !opts.resolveModel)
201
+ continue;
202
+ const resolved = opts.resolveModel(id);
203
+ refuseModelClass(resolved, id, s.name ?? 'the native runtime');
204
+ known.set(id, resolved);
205
+ }
206
+ for (const entry of s.tools ?? [])
207
+ if (entry.kind === 'agent')
208
+ learn(entry.agent);
209
+ };
210
+ // A workflow's agents share one lookup: every node's spec is learned.
211
+ for (const s of spec === undefined ? [] : Array.isArray(spec) ? spec : [spec])
212
+ learn(s);
213
+ return (model) => {
214
+ const held = cache.get(model);
215
+ if (held)
216
+ return held;
217
+ const resolved = known.has(model) ? known.get(model) : opts.resolveModel ? opts.resolveModel(model) : model;
218
+ const adapter = adapterOf(resolved, model);
219
+ cache.set(model, adapter);
220
+ return adapter;
221
+ };
222
+ }
@@ -52,11 +52,12 @@ export declare const DEFAULT_GPT_MODEL = "gpt-5-mini";
52
52
  */
53
53
  export declare const DEFAULT_GROK_MODEL = "grok-4.7";
54
54
  /**
55
- * Reasoning effort sent with grok-4.5/4.7 requests: 'low' | 'medium' | 'high'
56
- * (xAI's own default is 'high'; 4.7 adds 'xhigh'). Pinned to MEDIUM — deeper
57
- * than low without high's latency and token cost. Source: docs.x.ai › Model
58
- * capabilities › Text › Reasoning › Effort levels. Older grok ids don't
59
- * accept the param and never receive it (lib/models/grokLlm.ts).
55
+ * Reasoning effort sent with grok-4.5, 4.6 and 4.7 requests that set no
56
+ * `reasoning:`: 'low' | 'medium' | 'high' (xAI's own default is 'high'; 4.7
57
+ * adds 'xhigh'). Pinned to MEDIUM — deeper than low without high's latency
58
+ * and token cost. Source: docs.x.ai › Model capabilities › Text › Reasoning ›
59
+ * Effort levels. Older grok ids don't accept the param and never receive it
60
+ * (lib/models/grokAdapter.ts).
60
61
  */
61
62
  export declare const DEFAULT_GROK_REASONING_EFFORT = "medium";
62
63
  /**
@@ -53,11 +53,12 @@ export const DEFAULT_GPT_MODEL = 'gpt-5-mini';
53
53
  */
54
54
  export const DEFAULT_GROK_MODEL = 'grok-4.7';
55
55
  /**
56
- * Reasoning effort sent with grok-4.5/4.7 requests: 'low' | 'medium' | 'high'
57
- * (xAI's own default is 'high'; 4.7 adds 'xhigh'). Pinned to MEDIUM — deeper
58
- * than low without high's latency and token cost. Source: docs.x.ai › Model
59
- * capabilities › Text › Reasoning › Effort levels. Older grok ids don't
60
- * accept the param and never receive it (lib/models/grokLlm.ts).
56
+ * Reasoning effort sent with grok-4.5, 4.6 and 4.7 requests that set no
57
+ * `reasoning:`: 'low' | 'medium' | 'high' (xAI's own default is 'high'; 4.7
58
+ * adds 'xhigh'). Pinned to MEDIUM — deeper than low without high's latency
59
+ * and token cost. Source: docs.x.ai › Model capabilities › Text › Reasoning ›
60
+ * Effort levels. Older grok ids don't accept the param and never receive it
61
+ * (lib/models/grokAdapter.ts).
61
62
  */
62
63
  export const DEFAULT_GROK_REASONING_EFFORT = 'medium';
63
64
  /**
@@ -155,6 +155,7 @@ function needsOf(agent, delegates = false) {
155
155
  tools: agent.tools ?? [],
156
156
  outputSchema: agent.outputSchema,
157
157
  generateContentConfig: agent.generateContentConfig,
158
+ reasoning: agent.reasoning,
158
159
  delegates,
159
160
  };
160
161
  }
@@ -37,7 +37,8 @@ export type { RemoteAnswer } from './a2a/remoteAgent.ts';
37
37
  export { resolveTools, registerTool, registeredToolNames } from './toolRegistry.ts';
38
38
  export { registerGuard, resolveGuards } from './guards/index.ts';
39
39
  export type { Guard, GuardResult } from './guards/index.ts';
40
- export { defineTool, toFunctionTool } from './tools/toolContract.ts';
40
+ export { defineTool } from './tools/toolContract.ts';
41
+ export { toFunctionTool } from './tools/adkTool.ts';
41
42
  export { modelExtractor, geminiEmbedder, openAiCompatibleEmbedder, memoryProvidersFromEnv, } from './memory/providers.ts';
42
43
  export type { Embedder, MemoryExtractor } from './memory/providers.ts';
43
44
  export { eraseScope } from './memory/erase.ts';
package/dist/lib/index.js CHANGED
@@ -28,7 +28,8 @@ export { RemoteA2AAgent, remoteAgentTool } from './a2a/remoteAgent.js';
28
28
  // ── Extend it ───────────────────────────────────────────────────────────────
29
29
  export { resolveTools, registerTool, registeredToolNames } from './toolRegistry.js';
30
30
  export { registerGuard, resolveGuards } from './guards/index.js';
31
- export { defineTool, toFunctionTool } from './tools/toolContract.js';
31
+ export { defineTool } from './tools/toolContract.js';
32
+ export { toFunctionTool } from './tools/adkTool.js';
32
33
  // ── Memory ──────────────────────────────────────────────────────────────────
33
34
  export { modelExtractor, geminiEmbedder, openAiCompatibleEmbedder, memoryProvidersFromEnv, } from './memory/providers.js';
34
35
  export { eraseScope } from './memory/erase.js';
@@ -6,6 +6,7 @@ import type { ContextConfig, ExampleConfig } from './compile.ts';
6
6
  export type { OpenApiConfig } from './tools/openapiTools.ts';
7
7
  export type { SkillsConfig } from './tools/skillToolset.ts';
8
8
  import type { WorkflowConfig } from './workflowConfig.ts';
9
+ import type { ReasoningSetting } from './models/contract.ts';
9
10
  export type { WorkflowConfig } from './workflowConfig.ts';
10
11
  export interface ThinkingConfig {
11
12
  /** Token budget for internal reasoning. 0 = off, -1 = dynamic. */
@@ -13,6 +14,14 @@ export interface ThinkingConfig {
13
14
  /** Stream the thinking trace in the response. */
14
15
  includeThoughts?: boolean;
15
16
  }
17
+ /**
18
+ * How hard an agent reasons, on any provider (ADR 0047): a level, or a token
19
+ * budget. The engine's model contract (lib/models/contract.ts) defines it.
20
+ * The compiler maps it to the field the agent's provider reads
21
+ * (lib/compile.ts reasoningConfig); `thinkingConfig` and `reasoningEffort`
22
+ * inside generateContentConfig are the older, provider-specific spelling.
23
+ */
24
+ export type { ReasoningLevel, ReasoningSetting } from './models/contract.ts';
16
25
  export interface SafetySetting {
17
26
  category: string;
18
27
  threshold: string;
@@ -35,7 +44,10 @@ export interface GenerateContentConfig {
35
44
  seed?: number;
36
45
  responseMimeType?: string;
37
46
  safetySettings?: SafetySetting[];
47
+ /** Older spelling of `reasoning` for Gemini and Claude (ADR 0047). */
38
48
  thinkingConfig?: ThinkingConfig;
49
+ /** Older spelling of `reasoning` for the chat-completions providers (ADR 0047). */
50
+ reasoningEffort?: string;
39
51
  }
40
52
  /**
41
53
  * Maps to LlmAgentConfig (+ BaseAgentConfig) from @google/adk.
@@ -82,6 +94,12 @@ export interface AgentYamlConfig {
82
94
  * Maps to LlmAgentConfig.generateContentConfig.
83
95
  */
84
96
  generateContentConfig?: GenerateContentConfig;
97
+ /**
98
+ * How hard the agent reasons: none | low | medium | high, or
99
+ * { budget_tokens }. Cannot be combined with generateContentConfig's
100
+ * thinkingConfig or reasoningEffort (ADR 0047).
101
+ */
102
+ reasoning?: ReasoningSetting;
85
103
  /**
86
104
  * Output schema for structured JSON responses.
87
105
  * Maps to LlmAgentConfig.outputSchema.
@@ -5,8 +5,10 @@
5
5
  * which deletes memory facts, sessions (with the per-subagent rows ADK writes
6
6
  * beside them), the ledger's turns, spans, payloads, verdicts and labels, the
7
7
  * scope's durable A2A tasks for those conversations, its memory ingestion
8
- * markers, and (without a namespace) its task tools' list and jobs
9
- * (migration 0010), in one transaction. Returns what each store lost.
8
+ * markers, (without a namespace) its task tools' list and jobs
9
+ * (migration 0010), and the third-party tokens held for its tools, every
10
+ * app's or the namespace's own (migration 0013), in one transaction.
11
+ * Returns what each store lost.
10
12
  *
11
13
  * With a namespace, ledger turns and A2A tasks are kept only when their
12
14
  * conversation is still live in another namespace (migration 0011): they do
@@ -17,7 +19,7 @@
17
19
  * worse than an error the caller can surface and retry.
18
20
  */
19
21
  import type { SupabaseClient } from '@supabase/supabase-js';
20
- export declare const ERASE_STORES: readonly ['memory_facts', 'sessions', 'turns', 'spans', 'payloads', 'verdicts', 'labels', 'tasks', 'memory_markers', 'task_tools'];
22
+ export declare const ERASE_STORES: readonly ['memory_facts', 'sessions', 'turns', 'spans', 'payloads', 'verdicts', 'labels', 'tasks', 'memory_markers', 'task_tools', 'credentials'];
21
23
  export type EraseStore = (typeof ERASE_STORES)[number];
22
24
  export type EraseCounts = Record<EraseStore, number>;
23
25
  export interface EraseOptions {
@@ -5,8 +5,10 @@
5
5
  * which deletes memory facts, sessions (with the per-subagent rows ADK writes
6
6
  * beside them), the ledger's turns, spans, payloads, verdicts and labels, the
7
7
  * scope's durable A2A tasks for those conversations, its memory ingestion
8
- * markers, and (without a namespace) its task tools' list and jobs
9
- * (migration 0010), in one transaction. Returns what each store lost.
8
+ * markers, (without a namespace) its task tools' list and jobs
9
+ * (migration 0010), and the third-party tokens held for its tools, every
10
+ * app's or the namespace's own (migration 0013), in one transaction.
11
+ * Returns what each store lost.
10
12
  *
11
13
  * With a namespace, ledger turns and A2A tasks are kept only when their
12
14
  * conversation is still live in another namespace (migration 0011): they do
@@ -27,6 +29,7 @@ export const ERASE_STORES = [
27
29
  'tasks',
28
30
  'memory_markers',
29
31
  'task_tools',
32
+ 'credentials',
30
33
  ];
31
34
  export async function eraseScope(client, scopeKey, options = {}) {
32
35
  if (!scopeKey?.trim())
@@ -9,10 +9,17 @@
9
9
  * nothing, and said so without error. Wrapping the service the runtime hands
10
10
  * to ADK pins every search and ingestion to one namespace, whatever app
11
11
  * name the caller carries.
12
+ *
13
+ * The pin covers both interfaces a service may implement: ADK's
14
+ * (`searchMemory`, `addSessionToMemory`) and the engine's MemoryService
15
+ * (`search`, `ingest`, lib/runtime/memoryService.ts, ADR 0059). Every other
16
+ * member, erase and retention included, passes through unchanged: they name
17
+ * their key or namespace themselves.
12
18
  */
13
19
  import type { BaseMemoryService } from '@google/adk';
20
+ import type { MemoryService } from '../runtime/memoryService.ts';
14
21
  /** A memory service whose every read and write uses `namespace` as the app name. */
15
- export declare function namespacedMemoryService<T extends BaseMemoryService>(base: T, namespace: string): T;
22
+ export declare function namespacedMemoryService<T extends BaseMemoryService | MemoryService>(base: T, namespace: string): T;
16
23
  /** The server-wide name memory falls back to when a syndicate declares none. */
17
24
  export declare const LEGACY_MEMORY_APP_NAME = "melchizedek-a2a";
18
25
  /**
@@ -9,23 +9,29 @@
9
9
  * nothing, and said so without error. Wrapping the service the runtime hands
10
10
  * to ADK pins every search and ingestion to one namespace, whatever app
11
11
  * name the caller carries.
12
+ *
13
+ * The pin covers both interfaces a service may implement: ADK's
14
+ * (`searchMemory`, `addSessionToMemory`) and the engine's MemoryService
15
+ * (`search`, `ingest`, lib/runtime/memoryService.ts, ADR 0059). Every other
16
+ * member, erase and retention included, passes through unchanged: they name
17
+ * their key or namespace themselves.
12
18
  */
13
19
  import { randomBytes } from 'node:crypto';
14
20
  import fs from 'node:fs';
15
21
  import path from 'node:path';
22
+ /** The four methods whose first argument carries the app name the pin replaces. */
23
+ const PINNED = new Set(['searchMemory', 'addSessionToMemory', 'search', 'ingest']);
16
24
  /** A memory service whose every read and write uses `namespace` as the app name. */
17
25
  export function namespacedMemoryService(base, namespace) {
18
26
  if (!namespace)
19
27
  throw new Error('namespacedMemoryService: namespace is required');
20
28
  return new Proxy(base, {
21
29
  get(target, prop, receiver) {
22
- if (prop === 'searchMemory') {
23
- return (request) => target.searchMemory({ ...request, appName: namespace });
24
- }
25
- if (prop === 'addSessionToMemory') {
26
- return (session, ...rest) => target.addSessionToMemory.call(target, { ...session, appName: namespace }, ...rest);
27
- }
28
30
  const value = Reflect.get(target, prop, receiver);
31
+ if (PINNED.has(prop) && typeof value === 'function') {
32
+ // A search request or a session: the same object with the namespace as its app name.
33
+ return (first, ...rest) => value.call(target, { ...first, appName: namespace }, ...rest);
34
+ }
29
35
  return typeof value === 'function' ? value.bind(target) : value;
30
36
  },
31
37
  });
@@ -35,6 +35,7 @@ import { EMBEDDING_DIMENSIONS, EMBEDDING_MODEL, MEMORY_EXTRACTION_MODEL } from '
35
35
  import { providerForModel } from '../models/providerMap.js';
36
36
  import { resolveModel } from '../models/registry.js';
37
37
  import { initializeTracing } from '../observability/tracer.js';
38
+ import { trimTrailingSlashes } from '../models/urls.js';
38
39
  /**
39
40
  * Extraction on any model id. The key passed here reaches only a model of
40
41
  * the matching provider (resolveModel's BYOK rule); other providers read
@@ -146,7 +147,7 @@ export function geminiEmbedder(opts) {
146
147
  export function openAiCompatibleEmbedder(opts) {
147
148
  const dimensions = opts.dimensions ?? EMBEDDING_DIMENSIONS;
148
149
  const provider = opts.provider ?? 'openai-compatible';
149
- const url = `${opts.baseUrl.replace(/\/+$/, '')}/embeddings`;
150
+ const url = `${trimTrailingSlashes(opts.baseUrl)}/embeddings`;
150
151
  return {
151
152
  provider,
152
153
  model: opts.model,
@@ -1,5 +1,21 @@
1
- import type { BaseMemoryService, SearchMemoryRequest, SearchMemoryResponse, Session } from '@google/adk';
1
+ /**
2
+ * lib/memory/supabaseMemoryService.ts — long-term memory over pgvector
3
+ * (ADR 0020), on the engine's own interface and on ADK's.
4
+ *
5
+ * The class implements the engine's MemoryService (lib/runtime/memoryService.ts:
6
+ * `ingest`, `search`, and the optional `deleteUserMemory`, `pruneExpired`
7
+ * and `verifyEmbeddingDimensions`, ADR 0052), which the native runtime and
8
+ * the engine's own memory tools (lib/tools/memoryTools.ts) call. It also
9
+ * implements ADK's BaseMemoryService, whose `addSessionToMemory` and
10
+ * `searchMemory` the ADK runtime's Runner, the turn runner's ingestion
11
+ * (ingestTurnMemory) and the A2A server call: each is one line that hands
12
+ * its arguments to `ingest` or `search`, so both runtimes reach the same
13
+ * logic and the same silos (ADR 0059).
14
+ */
15
+ import type { BaseMemoryService, SearchMemoryRequest, SearchMemoryResponse, Session as AdkSession } from '@google/adk';
2
16
  import type { SupabaseClient } from '@supabase/supabase-js';
17
+ import type { MemoryIngestOptions, MemorySearchRequest, MemorySearchResult, MemoryService } from '../runtime/memoryService.ts';
18
+ import type { Session } from '../runtime/sessions.ts';
3
19
  import type { MemoryStore } from './store.ts';
4
20
  import type { Embedder, MemoryExtractor } from './providers.ts';
5
21
  /**
@@ -51,7 +67,7 @@ export declare function isSemanticDuplicate(candidate: {
51
67
  status: string | null;
52
68
  similarity: number;
53
69
  }>, threshold?: number): boolean;
54
- export declare class SupabaseVectorMemoryService implements BaseMemoryService {
70
+ export declare class SupabaseVectorMemoryService implements MemoryService, BaseMemoryService {
55
71
  private extractor;
56
72
  private embedder;
57
73
  private store;
@@ -90,15 +106,26 @@ export declare class SupabaseVectorMemoryService implements BaseMemoryService {
90
106
  extractorFor?: (model: string) => MemoryExtractor;
91
107
  }, backend: SupabaseClient | MemoryStore);
92
108
  /**
109
+ * ADK's name for `ingest`, which the ADK runtime and the A2A server call.
110
+ *
93
111
  * @param extractionRules Optional domain rules appended to the shared
94
112
  * extraction prompt for THIS consumer only. The prompt is global (the
95
113
  * patient advocate uses the same one), so anything domain-specific —
96
114
  * "never store a market quote" — arrives here rather than being edited
97
115
  * into it. Declared as `memory_extraction_rules` on the served syndicate.
98
116
  */
99
- addSessionToMemory(session: Session, extractionRules?: string, options?: {
117
+ addSessionToMemory(session: AdkSession, extractionRules?: string, options?: {
100
118
  extractionModel?: string;
101
119
  }): Promise<void>;
120
+ /**
121
+ * Distils the session's events not yet ingested into facts filed under
122
+ * `<appName>/<userId>`. Throws when a step fails, leaving those events
123
+ * pending for the next ingestion (ADR 0020 item 6).
124
+ *
125
+ * @param options.extractionRules The syndicate's `memory_extraction_rules`.
126
+ * @param options.extractionModel The syndicate's `memory_extraction_model`.
127
+ */
128
+ ingest(session: Session, options?: MemoryIngestOptions): Promise<void>;
102
129
  /**
103
130
  * Right-to-erasure: permanently deletes every stored fact for a user key
104
131
  * (`{appName}/{userId}`). Returns the number of rows removed. Throws on
@@ -109,7 +136,14 @@ export declare class SupabaseVectorMemoryService implements BaseMemoryService {
109
136
  * `adk_sessions` and must be cleared separately if full erasure is needed.
110
137
  */
111
138
  deleteUserMemory(userKey: string): Promise<number>;
139
+ /**
140
+ * ADK's name for `search`, which ADK's Context.searchMemory calls. The
141
+ * entries are the same JSON as ADK's MemoryEntry; only genai's types name
142
+ * a few part fields as enums, hence the cast.
143
+ */
112
144
  searchMemory(request: SearchMemoryRequest): Promise<SearchMemoryResponse>;
145
+ /** The facts most relevant to the query, from the `<appName>/<userId>` silo only. */
146
+ search(request: MemorySearchRequest): Promise<MemorySearchResult>;
113
147
  /**
114
148
  * The extractor for a syndicate's `memory_extraction_model` (ADR 0020
115
149
  * item 4), or the deployment's. The server's Gemini key reaches only a
@@ -1,3 +1,17 @@
1
+ /**
2
+ * lib/memory/supabaseMemoryService.ts — long-term memory over pgvector
3
+ * (ADR 0020), on the engine's own interface and on ADK's.
4
+ *
5
+ * The class implements the engine's MemoryService (lib/runtime/memoryService.ts:
6
+ * `ingest`, `search`, and the optional `deleteUserMemory`, `pruneExpired`
7
+ * and `verifyEmbeddingDimensions`, ADR 0052), which the native runtime and
8
+ * the engine's own memory tools (lib/tools/memoryTools.ts) call. It also
9
+ * implements ADK's BaseMemoryService, whose `addSessionToMemory` and
10
+ * `searchMemory` the ADK runtime's Runner, the turn runner's ingestion
11
+ * (ingestTurnMemory) and the A2A server call: each is one line that hands
12
+ * its arguments to `ingest` or `search`, so both runtimes reach the same
13
+ * logic and the same silos (ADR 0059).
14
+ */
1
15
  import { memoryProvidersFromEnv, modelExtractor } from './providers.js';
2
16
  import { providerForModel } from '../models/providerMap.js';
3
17
  import { isSupabaseClient, supabaseMemoryStore } from './store.js';
@@ -13,7 +27,9 @@ import { isSupabaseClient, supabaseMemoryStore } from './store.js';
13
27
  */
14
28
  export function stripHarnessBlocks(text) {
15
29
  return text
16
- .replace(/\[System Context:[^\]]*\]\s*/g, '')
30
+ // `[^[\]]` stops at any bracket, so a run of unclosed markers is
31
+ // scanned once, not once per marker (CodeQL js/polynomial-redos).
32
+ .replace(/\[System Context:[^[\]]*\]\s*/g, '')
17
33
  // A data block a calling surface attaches: a bracketed label ending in
18
34
  // "Payload" or "Sheet" (e.g. `[Account Payload]`), then a fenced block.
19
35
  .replace(/\[[A-Za-z][A-Za-z ]{0,60}(?:Payload|Sheet)\]\s*```[\s\S]*?```\s*/g, '')
@@ -147,6 +163,8 @@ export class SupabaseVectorMemoryService {
147
163
  + `extraction ${this.extractor.model}, embeddings ${this.embedder.provider}/${this.embedder.model} (${this.embedder.dimensions}d)`);
148
164
  }
149
165
  /**
166
+ * ADK's name for `ingest`, which the ADK runtime and the A2A server call.
167
+ *
150
168
  * @param extractionRules Optional domain rules appended to the shared
151
169
  * extraction prompt for THIS consumer only. The prompt is global (the
152
170
  * patient advocate uses the same one), so anything domain-specific —
@@ -154,6 +172,18 @@ export class SupabaseVectorMemoryService {
154
172
  * into it. Declared as `memory_extraction_rules` on the served syndicate.
155
173
  */
156
174
  async addSessionToMemory(session, extractionRules, options = {}) {
175
+ return this.ingest(session, { extractionRules, extractionModel: options.extractionModel });
176
+ }
177
+ /**
178
+ * Distils the session's events not yet ingested into facts filed under
179
+ * `<appName>/<userId>`. Throws when a step fails, leaving those events
180
+ * pending for the next ingestion (ADR 0020 item 6).
181
+ *
182
+ * @param options.extractionRules The syndicate's `memory_extraction_rules`.
183
+ * @param options.extractionModel The syndicate's `memory_extraction_model`.
184
+ */
185
+ async ingest(session, options = {}) {
186
+ const { extractionRules } = options;
157
187
  const userKey = `${session.appName}/${session.userId}`;
158
188
  const watermarkKey = `${userKey}::${session.id}`;
159
189
  let alreadyIngested = this.ingestedEventCount.get(watermarkKey) ?? 0;
@@ -238,9 +268,19 @@ export class SupabaseVectorMemoryService {
238
268
  console.log(`[MemoryService] Deleted ${count} fact(s) for user key: ${userKey}`);
239
269
  return count;
240
270
  }
271
+ /**
272
+ * ADK's name for `search`, which ADK's Context.searchMemory calls. The
273
+ * entries are the same JSON as ADK's MemoryEntry; only genai's types name
274
+ * a few part fields as enums, hence the cast.
275
+ */
241
276
  async searchMemory(request) {
277
+ return (await this.search(request));
278
+ }
279
+ /** The facts most relevant to the query, from the `<appName>/<userId>` silo only. */
280
+ async search(request) {
242
281
  const query = stripHarnessBlocks(request.query) || request.query;
243
- console.log(`[MemoryService] Searching memory for: "${query}"`);
282
+ // The query is the user's own words: the log says only how long it is.
283
+ console.log(`[MemoryService] Searching memory (${query.length} chars)`);
244
284
  const userKey = `${request.appName}/${request.userId}`;
245
285
  return this.searchSupabase(userKey, query);
246
286
  }