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,291 @@
1
+ /**
2
+ * lib/runtime/native/interrupts.ts — approvals on the native loop: the
3
+ * answer to an `adk_request_confirmation` call runs or refuses the pinned
4
+ * call before the next model step (WS2-7a, ADR 0028, ADR 0077).
5
+ *
6
+ * WHY this file exists:
7
+ * A tool that requires approval does not run when called. The loop
8
+ * (agentLoop.ts) stores ADK's `adk_request_confirmation` call in place of
9
+ * the response, pinning the original call and its arguments, and the run
10
+ * ends paused. The person's answer arrives as the next user message: a
11
+ * function response to that call carrying `{ confirmed }`. On the ADK
12
+ * runtime, LlmAgent's request-confirmation processor reads it before every
13
+ * model step and runs the pinned call with the confirmation. This file is
14
+ * that processor, case for case, so an approval opened on either runtime
15
+ * resumes on the other and both store the same events.
16
+ *
17
+ * BEFORE EACH STEP, AS ADK'S PROCESSOR RUNS IT:
18
+ * 1. The answers: the function responses named `adk_request_confirmation`
19
+ * in the latest user event (events on another branch left out), each
20
+ * read as `{ confirmed, hint, payload }`, or as JSON under `response`.
21
+ * None: nothing happens, and the step goes on as usual.
22
+ * 2. The gates they answer: every `adk_request_confirmation` call whose id
23
+ * an answer names. A request authored by the user is refused
24
+ * (`untrusted_request`); one authored by another agent is skipped; one
25
+ * whose pinned call has no id or name is refused (`malformed_request`);
26
+ * one this agent has already answered the pinned call after is skipped,
27
+ * so a later step never runs the call again.
28
+ * 3. The binding. The pinned call must be one this agent made, by id
29
+ * (`unknown_original_call`); its tool must be the agent's
30
+ * (`unregistered_tool`); the name and the arguments must equal the
31
+ * call's as the model made it (`tool_name_mismatch`,
32
+ * `arguments_mismatch`); and the tool must require approval, or have
33
+ * asked for it (`confirmation_not_required`). A refusal throws ADK's
34
+ * IntentMismatchError text and nothing runs.
35
+ * 4. The bound calls run through the loop's own call path with the
36
+ * confirmation in their context: an approved call runs its tool, a
37
+ * refused one answers ADK's refusal. Their response is stored as its
38
+ * own event before the step builds its request, so the model reads it.
39
+ *
40
+ * Not here: a plain-text "yes" as an answer (ADK's plainTextToolConfirmation,
41
+ * which no surface turns on), and answers delivered by a remote peer (ADK's
42
+ * remoteDelivered, which no surface sets).
43
+ *
44
+ * QUESTIONS (ask_user, WS2-7b, ADR 0079) need no processor here. ADK runs its
45
+ * request-input processor (REQUEST_INPUT_LLM_REQUEST_PROCESSOR) next, before
46
+ * compaction, but it only re-runs a node tool (a workflow run as a tool) that
47
+ * paused on an `adk_request_input` call; for an agent that lists no node tool
48
+ * it returns before doing anything, and no native agent lists one (native
49
+ * refuses workflows). An `ask_user` call is an ordinary long-running call:
50
+ * the turn runner stores the person's next message as its function response
51
+ * (lib/runtime/questions.ts questionAnswerPart), and the step reads the call
52
+ * and the answer side by side from the history (history.ts), as ADK's
53
+ * content processor does. When workflows run natively (WS4), the node-tool
54
+ * resume is ported beside approvedCalls, in the same place in the order.
55
+ *
56
+ * CREDENTIALS (OAuth consent, WS6-3b, ADR 0085) run first, as ADK runs its
57
+ * auth preprocessor (AUTH_PREPROCESSOR) before request-confirmation.
58
+ * grantedCalls is that preprocessor, check for check, with one difference
59
+ * in what the answer carries:
60
+ * 1. The answers: the function responses named `adk_request_credential`
61
+ * in the last event with content, which must be the user's. None:
62
+ * nothing happens.
63
+ * 2. The requests they answer: `adk_request_credential` calls this agent
64
+ * made, by id. An answer naming no such request is ignored, as ADK
65
+ * ignores it.
66
+ * 3. The binding. ADK's answer carries the authorization response (a code
67
+ * or the redirect URL), which ADK exchanges in-process with the client
68
+ * secret its request event stored. Here the server's callback route has
69
+ * already exchanged the code and stored the grant
70
+ * (lib/tools/oauthConsent.ts), so the answer carries no credential:
71
+ * `{ credentialKey, granted: true }`, bound to the request by its
72
+ * credentialKey. An answer that does not bind is ignored.
73
+ * 4. The paused calls the bound requests name (`function_call_id`, ADK's
74
+ * toolset requests aside) run again, from the latest event that made
75
+ * them, through the loop's own call path. The tool now reads its grant
76
+ * through ctx.accessToken. The response is stored before the step
77
+ * builds its request. A later step finds the agent's own events last,
78
+ * so the call runs once.
79
+ *
80
+ * ADK stays out of this file: an ADK tool an agent still lists is asked
81
+ * whether it gates through its own checkRequireConfirmation, by shape.
82
+ */
83
+ import { isDeepStrictEqual } from 'node:util';
84
+ import { nativeToolOf } from '../../models/schemaNormalize.js';
85
+ import { instructionToolOf, isTool, toolOf } from '../../tools/tool.js';
86
+ import { getFunctionCalls, getFunctionResponses } from '../events.js';
87
+ import { REQUEST_CONFIRMATION_CALL, REQUEST_CREDENTIAL_CALL, isSegmentPrefix } from './history.js';
88
+ import { isToolset } from './request.js';
89
+ /** A confirmation that does not bind to its pinned call: ADK's IntentMismatchError, by name and text. */
90
+ export class IntentMismatchError extends Error {
91
+ reason;
92
+ functionCallId;
93
+ constructor(reason, functionCallId) {
94
+ super(`Tool confirmation rejected${functionCallId ? ` for function call '${functionCallId}'` : ''}: ${reason}.`);
95
+ this.name = 'IntentMismatchError';
96
+ this.reason = reason;
97
+ if (functionCallId !== undefined)
98
+ this.functionCallId = functionCallId;
99
+ }
100
+ }
101
+ const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
102
+ /** ADK's parseToolConfirmation: `{ confirmed, hint, payload }`, or the same as JSON under `response`. */
103
+ function parseConfirmation(response) {
104
+ const keys = Object.keys(response);
105
+ const fields = (keys.length === 1 && keys[0] === 'response' ? JSON.parse(String(response.response)) : response);
106
+ return { hint: typeof fields.hint === 'string' ? fields.hint : '', confirmed: fields.confirmed === true, payload: fields.payload };
107
+ }
108
+ /** Step 1: the answers in the latest user event, by the request id each names. */
109
+ function answersIn(events) {
110
+ const answers = new Map();
111
+ let latest;
112
+ for (let i = events.length - 1; i >= 0 && !latest; i--)
113
+ if (events[i]?.author === 'user')
114
+ latest = events[i];
115
+ if (!latest)
116
+ return answers;
117
+ for (const r of getFunctionResponses(latest)) {
118
+ if (r.name !== REQUEST_CONFIRMATION_CALL || !r.id || !r.response)
119
+ continue;
120
+ answers.set(r.id, parseConfirmation(r.response));
121
+ }
122
+ return answers;
123
+ }
124
+ /** The agent's callable tools by name, toolsets expanded, as ADK's canonicalTools lists them. */
125
+ async function toolsOf(agent, scope) {
126
+ const state = scope.session.state;
127
+ const toolsetContext = {
128
+ agentName: agent.name,
129
+ invocationId: scope.invocationId,
130
+ state: { get: (key) => state[key], has: (key) => Object.hasOwn(state, key) },
131
+ };
132
+ const tools = new Map();
133
+ for (const union of agent.tools ?? []) {
134
+ const expanded = isToolset(union) ? await union.getTools(toolsetContext) : [union];
135
+ for (const listed of expanded) {
136
+ if (nativeToolOf(listed) || instructionToolOf(listed))
137
+ continue;
138
+ const name = listed?.name;
139
+ if (typeof name === 'string')
140
+ tools.set(name, toolOf(listed) ?? listed);
141
+ }
142
+ }
143
+ return tools;
144
+ }
145
+ /** Whether `tool` gates the call: an own Tool's requiresApproval, an ADK tool's checkRequireConfirmation. */
146
+ async function gates(tool, args, context) {
147
+ if (isTool(tool))
148
+ return tool.requiresApproval === true;
149
+ const check = tool.checkRequireConfirmation;
150
+ return typeof check === 'function' ? (await check.call(tool, args, context)) === true : false;
151
+ }
152
+ /**
153
+ * The pinned calls the latest user message approves or refuses, bound to
154
+ * the calls this agent made; undefined when it answers no open request.
155
+ * Throws IntentMismatchError when an answer does not bind (nothing runs).
156
+ * `contextFor` makes the context a tool's gate check reads.
157
+ */
158
+ export async function approvedCalls(agent, scope, contextFor) {
159
+ const all = scope.session.events;
160
+ const events = scope.branch ? all.filter((e) => !e.branch || isSegmentPrefix(scope.branch, e.branch)) : all;
161
+ if (events.length === 0)
162
+ return undefined;
163
+ const answers = answersIn(events);
164
+ if (answers.size === 0)
165
+ return undefined;
166
+ // Step 2: the gates the answers name.
167
+ const candidates = [];
168
+ for (const [index, event] of events.entries()) {
169
+ for (const call of getFunctionCalls(event)) {
170
+ const confirmation = call.id ? answers.get(call.id) : undefined;
171
+ if (!confirmation || call.name !== REQUEST_CONFIRMATION_CALL)
172
+ continue;
173
+ if (event.author !== agent.name) {
174
+ if (event.author === 'user')
175
+ throw new IntentMismatchError('untrusted_request', call.id);
176
+ continue;
177
+ }
178
+ const pinned = isRecord(call.args) ? call.args.originalFunctionCall : undefined;
179
+ if (!isRecord(pinned))
180
+ continue;
181
+ if (!pinned.id || !pinned.name)
182
+ throw new IntentMismatchError('malformed_request', call.id);
183
+ const pinnedCall = pinned;
184
+ const answeredAfter = events
185
+ .slice(index + 1)
186
+ .some((e) => e.author === agent.name && getFunctionResponses(e).some((r) => r.id === pinnedCall.id));
187
+ if (!answeredAfter)
188
+ candidates.push({ pinned: pinnedCall, confirmation });
189
+ }
190
+ }
191
+ if (candidates.length === 0)
192
+ return undefined;
193
+ // Step 3: each pinned call bound to the call the agent made, by id, name and arguments.
194
+ const tools = await toolsOf(agent, scope);
195
+ const made = new Map();
196
+ const requested = new Set();
197
+ for (const event of events) {
198
+ if (event.author !== agent.name)
199
+ continue;
200
+ for (const call of getFunctionCalls(event))
201
+ if (call.id && call.name !== REQUEST_CONFIRMATION_CALL)
202
+ made.set(call.id, call);
203
+ for (const id of Object.keys(event.actions?.requestedToolConfirmations ?? {}))
204
+ requested.add(id);
205
+ }
206
+ const bound = new Map();
207
+ for (const { pinned, confirmation } of candidates) {
208
+ const id = pinned.id;
209
+ const original = made.get(id);
210
+ if (!original)
211
+ throw new IntentMismatchError('unknown_original_call', id);
212
+ const tool = tools.get(pinned.name);
213
+ if (!tool)
214
+ throw new IntentMismatchError('unregistered_tool', id);
215
+ if (original.name !== pinned.name)
216
+ throw new IntentMismatchError('tool_name_mismatch', id);
217
+ if (!isDeepStrictEqual(original.args ?? {}, pinned.args ?? {}))
218
+ throw new IntentMismatchError('arguments_mismatch', id);
219
+ if (!(await gates(tool, original.args ?? {}, contextFor(id))) && !requested.has(id))
220
+ throw new IntentMismatchError('confirmation_not_required', id);
221
+ bound.set(id, { call: pinned, confirmation });
222
+ }
223
+ return {
224
+ calls: [...bound.values()].map((b) => b.call),
225
+ confirmations: new Map([...bound].map(([id, b]) => [id, b.confirmation])),
226
+ tools,
227
+ };
228
+ }
229
+ // ── Credentials (ADK's auth preprocessor) ────────────────────────────────────
230
+ /** ADK's prefix for a toolset's own credential request, which resumes no call. */
231
+ const TOOLSET_AUTH_CREDENTIAL_ID_PREFIX = '_adk_toolset_auth_';
232
+ /** Whether an answer binds to the request it names: granted, for the provider the request named. */
233
+ function bindsGrant(config, response) {
234
+ if (!isRecord(response) || response.granted !== true)
235
+ return false;
236
+ return typeof config.credentialKey === 'string' && config.credentialKey !== '' && response.credentialKey === config.credentialKey;
237
+ }
238
+ /**
239
+ * The paused calls the latest user message resumes by answering this
240
+ * agent's credential requests; undefined when it answers none (ADK's
241
+ * AuthPreprocessor, the exchange left to the callback route).
242
+ */
243
+ export async function grantedCalls(agent, scope) {
244
+ const events = scope.session.events;
245
+ if (events.length === 0)
246
+ return undefined;
247
+ let last;
248
+ for (let i = events.length - 1; i >= 0 && !last; i--)
249
+ if (events[i]?.content !== undefined)
250
+ last = events[i];
251
+ if (!last || last.author !== 'user')
252
+ return undefined;
253
+ const answers = new Map();
254
+ for (const r of getFunctionResponses(last))
255
+ if (r.name === REQUEST_CREDENTIAL_CALL && r.id)
256
+ answers.set(r.id, r.response);
257
+ if (answers.size === 0)
258
+ return undefined;
259
+ // The requests this agent made, by id.
260
+ const requests = new Map();
261
+ for (const event of events) {
262
+ if (event.author !== agent.name)
263
+ continue;
264
+ for (const call of getFunctionCalls(event)) {
265
+ if (!call.id || !answers.has(call.id) || call.name !== REQUEST_CREDENTIAL_CALL || !isRecord(call.args))
266
+ continue;
267
+ const config = call.args.auth_config ?? call.args.authConfig;
268
+ if (isRecord(config))
269
+ requests.set(call.id, { config, args: call.args });
270
+ }
271
+ }
272
+ const resume = new Set();
273
+ for (const [id, response] of answers) {
274
+ const request = requests.get(id);
275
+ if (!request || !bindsGrant(request.config, response))
276
+ continue;
277
+ const callId = request.args.function_call_id ?? request.args.functionCallId;
278
+ if (typeof callId === 'string' && callId && !callId.startsWith(TOOLSET_AUTH_CREDENTIAL_ID_PREFIX))
279
+ resume.add(callId);
280
+ }
281
+ if (resume.size === 0)
282
+ return undefined;
283
+ // As ADK: the latest event before the answer that made any of the calls, those calls only.
284
+ for (let i = events.length - 2; i >= 0; i--) {
285
+ const calls = getFunctionCalls(events[i]);
286
+ if (!calls.some((c) => c.id && resume.has(c.id)))
287
+ continue;
288
+ return { calls: calls.filter((c) => c.id && resume.has(c.id)), tools: await toolsOf(agent, scope) };
289
+ }
290
+ return undefined;
291
+ }
@@ -0,0 +1,215 @@
1
+ /**
2
+ * lib/runtime/native/request.ts — one model request of the native loop,
3
+ * built from an agent and its session (ADR 0045, ADR 0066).
4
+ *
5
+ * WHY this file exists:
6
+ * The native runtime calls a ModelAdapter (lib/models/contract.ts) with a
7
+ * ModelRequest it builds itself, with no LlmRequest in between. A session
8
+ * moves between the runtimes and an agent must behave the same on either,
9
+ * so the request is the one the ADK runtime hands the same adapter for
10
+ * the same agent and session: what ADK's LlmAgent request processors and
11
+ * tools build, read through the shim's mapping (llmRequestToModelRequest,
12
+ * lib/models/genaiMapping.ts). tests/nativeStep.test.ts asserts that on
13
+ * whole syndicates.
14
+ *
15
+ * THE REQUEST, in the order ADK builds it:
16
+ * 1. The agent's generateContentConfig, and its output schema when it has
17
+ * no tools (or the model takes a schema beside tools: Gemini 2 and
18
+ * later on Vertex AI).
19
+ * 2. The system prompt, each piece joined to the last by a blank line:
20
+ * - the identity lines ("You are an agent. Your internal name is …"),
21
+ * unless the agent may transfer to no one (an output schema rules
22
+ * transfer out);
23
+ * - the root agent's globalInstruction, then the agent's instruction,
24
+ * each with `{state_key}` placeholders filled from session state,
25
+ * and, in a workflow node's run, `{input.field}` and
26
+ * `<input.field from Node>` filled from its workflow scope;
27
+ * - with an output schema beside tools on a model that cannot take
28
+ * both, the line asking for set_model_response;
29
+ * - then, at each tool's place in the agent's list, the text its
30
+ * `instruction(ctx)` writes: few-shot examples, preload_memory, an
31
+ * own Tool's note (ADR 0059, ADR 0062). The skills index is part of
32
+ * the instruction itself (lib/compile.ts appends it).
33
+ * A Tool's `contents` hook then adds to the history, after it is
34
+ * projected (load_skill_resource's binary file, ADR 0083).
35
+ * 3. The history: the session's events projected by includeContents
36
+ * (lib/runtime/native/history.ts), with Gemini code execution's parts
37
+ * as text when the agent runs code.
38
+ * 4. The tools, in the agent's order, a toolset expanded to its tools:
39
+ * each client-side tool's declaration (contractToolDeclaration), at
40
+ * most one per name, the later one winning; each server-side tool
41
+ * where the ADK runtime sends it (web_search everywhere, url_context
42
+ * and google_search on Gemini, x_search and collections_search on
43
+ * xAI); `code_execution` first among Gemini's own tools; and the
44
+ * set_model_response tool when (2) asked for it, then the caller's
45
+ * `extraTools` (self-correction's reflection tool, as ADK's plugin adds
46
+ * it to the toolsDict last). In `mode: task`, finish_task takes
47
+ * set_model_response's place and the output schema is never the
48
+ * response schema (lib/runtime/native/taskMode.ts).
49
+ * 5. Tool choice, the output schema or JSON mode, reasoning and sampling,
50
+ * read from the config by the mapping's own readers.
51
+ *
52
+ * WHAT IT DOES NOT DO (later tickets): resume an approval or an input
53
+ * request (ADK's confirmation and input processors run tools before the
54
+ * request; WS2-7), add transfer_to_agent
55
+ * (compiled syndicates never set subAgents; they delegate through subagent tools, delegate.ts),
56
+ * artifacts in an
57
+ * instruction (no runtime has an artifact service), and an ADK tool's own
58
+ * processLlmRequest side effects beyond its declaration (an own Tool says
59
+ * what it writes through `instruction`).
60
+ *
61
+ * ADK STAYS OUT OF THIS FILE'S OWN LOGIC: it reads tools by marker and by
62
+ * the own-tool symbols (lib/tools/tool.ts), and only lib/models/
63
+ * genaiMapping.ts, which stored history needs anyway (ADR 0048 item 8),
64
+ * names @google/*. An ADK tool or toolset an agent still carries (an
65
+ * AgentTool, an MCP or OpenAPI tool) is read through its declaration and
66
+ * `getTools`, by shape, as is the engine's own skills toolset.
67
+ */
68
+ import type { ModelRequest } from '../../models/contract.ts';
69
+ import type { MemoryService } from '../memoryService.ts';
70
+ import type { TurnContent, TurnEvent } from '../events.ts';
71
+ import type { Session } from '../sessions.ts';
72
+ import type { Tool } from '../../tools/tool.ts';
73
+ import type { ContextConfig } from './compaction.ts';
74
+ /**
75
+ * One agent as the native loop runs it: the fields of a compiled agent that
76
+ * shape its model requests, in the YAML's own spelling. lib/compile.ts
77
+ * builds the same fields into ADK's LlmAgent, and lib/compileNative.ts
78
+ * builds this from the same AgentSpec (ADR 0073).
79
+ */
80
+ export interface NativeAgent {
81
+ name: string;
82
+ description?: string;
83
+ /** The model id, as the YAML names it. */
84
+ model: string;
85
+ /**
86
+ * The agent's instruction. A string has `{key}` placeholders filled from
87
+ * session state (`{key?}` is optional); a function's result is used as it is.
88
+ */
89
+ instruction?: string | ((ctx: InstructionContext) => string | Promise<string>);
90
+ /** Prepended to every request of the run's root agent (ADK's global instruction). */
91
+ globalInstruction?: string | ((ctx: InstructionContext) => string | Promise<string>);
92
+ /**
93
+ * In the agent's order: own Tools and defineTool contracts, InstructionTools,
94
+ * NativeToolMarkers, and during the dual period the ADK tools and toolsets
95
+ * an agent may still list (their own-tool symbols are read first).
96
+ */
97
+ tools?: readonly unknown[];
98
+ /** The answer's schema, as the YAML spells it (lowercase or Gemini's dialect). */
99
+ outputSchema?: Record<string, unknown>;
100
+ /** As lib/compile.ts builds it: the YAML's config with `reasoning:` mapped in (withReasoning). */
101
+ generateContentConfig?: Record<string, unknown>;
102
+ includeContents?: 'default' | 'none';
103
+ disallowTransferToParent?: boolean;
104
+ disallowTransferToPeers?: boolean;
105
+ /** `code_execution: gemini`: Gemini runs the code it writes. */
106
+ codeExecution?: 'gemini';
107
+ /** `mode: task` (workflow nodes): finish_task is declared after the agent's tools and the output schema is its parameters (lib/runtime/native/taskMode.ts). */
108
+ mode?: 'task';
109
+ /** The session-state key the agent's final answer is saved under (the loop writes it, lib/runtime/native/agentLoop.ts). */
110
+ outputKey?: string;
111
+ /** `fallback_model:`: answers a provider-side failure of the agent's model (ADR 0044). The loop calls it as its own leaf adapter. */
112
+ fallbackModel?: string;
113
+ /** `context:` (ADR 0033): compact the history into a summary past a token threshold. The loop runs it before each step (compaction.ts). */
114
+ context?: ContextConfig;
115
+ }
116
+ /** What an instruction function reads. */
117
+ export interface InstructionContext {
118
+ readonly agentName: string;
119
+ readonly invocationId: string;
120
+ readonly state: Readonly<Record<string, unknown>>;
121
+ readonly userContent?: TurnContent;
122
+ }
123
+ /** Where the request is made: the run, its session, and who it is for. */
124
+ export interface RequestContext {
125
+ /** The session as it stands: the run's user event already appended. */
126
+ session: Session;
127
+ invocationId: string;
128
+ /** The message that started the run (the examples block reads it). */
129
+ userContent?: TurnContent;
130
+ /** The run's branch; undefined at the root. */
131
+ branch?: string;
132
+ isolationScope?: string;
133
+ /** The run's root agent, whose globalInstruction applies. Default: the agent itself. */
134
+ root?: Pick<NativeAgent, 'globalInstruction'>;
135
+ /** The run's memory, already namespaced: preload_memory and load_memory read it. */
136
+ memory?: Pick<MemoryService, 'search'>;
137
+ /** Stream text and thinking as partial responses. Default false. */
138
+ stream?: boolean;
139
+ /**
140
+ * State laid over the session's for this request: the run's `temp:` keys,
141
+ * which no store keeps (lib/runtime/native/tempState.ts).
142
+ */
143
+ stateOverlay?: Readonly<Record<string, unknown>>;
144
+ /** Aborts the call in flight: the turn's signal. */
145
+ signal?: AbortSignal;
146
+ /**
147
+ * Tools declared after the agent's own, as a plugin's beforeModelCallback
148
+ * adds them to ADK's toolsDict last: self-correction's reflection tool
149
+ * (lib/runtime/native/selfCorrection.ts).
150
+ */
151
+ extraTools?: readonly unknown[];
152
+ /**
153
+ * A workflow agent node's run: the node's input and the outputs stored so
154
+ * far, which fill the instruction's workflow placeholders as ADK's
155
+ * workflowInstructionScope does (lib/workflow/agentNode.ts).
156
+ */
157
+ workflowScope?: WorkflowInstructionScope;
158
+ }
159
+ /** A request, and the client-side tools it declares by name (what the loop runs and checks for long-running calls). */
160
+ export interface BuiltRequest {
161
+ request: ModelRequest;
162
+ /** By declared name, in the request's order: the own Tool when there is one, else the object listed. */
163
+ tools: Map<string, unknown>;
164
+ }
165
+ /** The tool ADK adds when an agent has an output schema and tools a model cannot take together. */
166
+ export declare const SET_MODEL_RESPONSE = "set_model_response";
167
+ /** set_model_response as an own Tool: its answer is the arguments, as JSON text, and it ends the step. */
168
+ export declare function setModelResponseTool(outputSchema: Record<string, unknown>): Tool;
169
+ /** Whether the model takes an output schema beside tools in one request (ADK: Vertex AI, Gemini 2 and later). */
170
+ export declare function outputSchemaWithTools(model: string): boolean;
171
+ /**
172
+ * What ADK's runLlmAgentAsNode puts in a node agent's invocation context
173
+ * (`withWorkflowInstructionScope`): the node's input, and the output each
174
+ * node of the invocation stored so far, by node name, the last one winning.
175
+ * Its instruction then fills `{<any>.<field>}` from the input and
176
+ * `<<any>.<field> from <Node>>` from that node's output.
177
+ */
178
+ export interface WorkflowInstructionScope {
179
+ readonly input: unknown;
180
+ readonly outputsByNode: Readonly<Record<string, unknown>>;
181
+ }
182
+ /**
183
+ * ADK's collectPredecessorOutputs: the output every event of the invocation
184
+ * carries, keyed by the last segment of its node path without the run
185
+ * suffix (`Graph.Fan.Agent@2` is `Agent`), the later event winning.
186
+ */
187
+ export declare function predecessorOutputs(events: readonly TurnEvent[], invocationId: string): Record<string, unknown>;
188
+ /**
189
+ * `template` with each `{key}` naming a state key replaced by the value in
190
+ * `state` (a string as it is, anything else as JSON). `{key?}` is optional
191
+ * and becomes empty when the key is absent; a required key that is absent
192
+ * fails, as on the ADK runtime. A placeholder that names no state key
193
+ * (`{ "a": 1 }` in an example) stays as it is. `{artifact.x}` fails: no
194
+ * runtime of this engine has an artifact service. Own keys only: a key such
195
+ * as `constructor` is absent unless the state holds it.
196
+ *
197
+ * With a workflow `scope` (a workflow agent node's run), ADK 2.2's two
198
+ * workflow placeholders are filled too, as its injectSessionState fills
199
+ * them: `{x.field}` (any identifier before the dot) from the node's input
200
+ * when it is an object holding `field`, `''` when optional and absent, else
201
+ * left as written (the key's first spelling); and `<x.field from Node>`
202
+ * from that node's stored object output, else left as written.
203
+ */
204
+ export declare function injectSessionState(template: string, state: Readonly<Record<string, unknown>>, scope?: WorkflowInstructionScope): string;
205
+ /** A toolset (the skills harness, an MCP toolset): something that yields tools, and is not one. */
206
+ export declare function isToolset(value: unknown): value is {
207
+ getTools(ctx?: unknown): Promise<unknown[]>;
208
+ };
209
+ /**
210
+ * The ModelRequest the native loop sends for `agent` now, with the
211
+ * client-side tools it declares. Throws where the ADK runtime throws
212
+ * building the same request: a required state key that is absent, a
213
+ * Gemini-only tool on another model, a config field LlmAgent refuses.
214
+ */
215
+ export declare function buildModelRequest(agent: NativeAgent, ctx: RequestContext): Promise<BuiltRequest>;