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
@@ -1,5 +1,6 @@
1
1
  /**
2
- * lib/compile.ts — the one YAML → ADK agent-graph compiler.
2
+ * lib/compile.ts — the one YAML → agent compiler: a runtime-neutral
3
+ * AgentSpec, and the ADK agent graph built from it.
3
4
  *
4
5
  * WHY this file exists:
5
6
  * The A2A server carried this logic as two closures inside its executor,
@@ -26,19 +27,30 @@
26
27
  * paths build subagents through the same function, so the agent a route
27
28
  * dispatches to is identical to the one DELEGATE would have wrapped.
28
29
  * Contract and rationale: lib/dispatch.ts.
30
+ *
31
+ * ── One spec, two runtimes (ADR 0073) ─────────────────────────────────────
32
+ * compileSpec and compileSubagentSpec do the work every runtime shares:
33
+ * resolve and gate the tools, append the skills index, resolve the model
34
+ * once, build the generateContentConfig. The result is an AgentSpec.
35
+ * lib/compileAdk.ts builds ADK's LlmAgent from it (compileGraph and
36
+ * compileSubagent are spec + compileAdk), and lib/compileNative.ts builds
37
+ * the native loop's NativeAgent (ADR 0045). runSyndicateTurn picks one by
38
+ * MELCHIZEDEK_RUNTIME or its `runtime` option.
29
39
  */
30
- import { AgentTool, BaseLlm, BuiltInCodeExecutor, ExampleTool, FunctionTool, LLMRegistry, LlmAgent, LlmSummarizer, TokenBasedContextCompactor } from '@google/adk';
40
+ import { BaseLlm, FunctionTool } from '@google/adk';
31
41
  import { relative } from 'node:path';
42
+ import { compileAdk } from './compileAdk.js';
32
43
  import { isDispatchSyndicate } from './dispatch.js';
33
44
  import { loadSyndicate, nestedLoader } from './loadSyndicate.js';
45
+ import { REASONING_OLDER_SPELLING } from './syndicateSchema.js';
46
+ import { reasoningConfig } from './models/reasoning.js';
34
47
  import { resolveTools as resolveNamedTools } from './toolRegistry.js';
35
48
  import { createMcpTools } from './tools/mcpToolFactory.js';
49
+ import { toAdkInstructionTool, toAdkToolset } from './tools/adkTool.js';
50
+ import { examplesInstructionTool } from './tools/examples.js';
36
51
  import { capabilitySummary, describeCapabilities } from './models/capabilities.js';
37
- import { FallbackLlm } from './models/fallback.js';
38
- import { resolveModel as resolveRegistryModel } from './models/registry.js';
39
- import { remoteAgentTool } from './a2a/remoteAgent.js';
40
52
  import { buildSkillHarness } from './tools/skillToolset.js';
41
- import { buildOpenApiTools, isOpenApiTool, namesTool } from './tools/openapiTools.js';
53
+ import { buildOpenApiTools, namesTool, openApiOperationId } from './tools/openapiTools.js';
42
54
  /** generateContentConfig as every entrypoint has always sent it to ADK. */
43
55
  function withServerSideToolInvocations(generateContentConfig) {
44
56
  const cfg = (generateContentConfig ?? {});
@@ -50,59 +62,31 @@ function withServerSideToolInvocations(generateContentConfig) {
50
62
  },
51
63
  };
52
64
  }
65
+ // ── Reasoning (ADR 0047) ─────────────────────────────────────────────────────
66
+ // REASONING_BUDGETS and reasoningConfig live in lib/models/reasoning.ts, so a
67
+ // model adapter can map `reasoning:` without importing the compiler (and ADK).
68
+ export { REASONING_BUDGETS, reasoningConfig } from './models/reasoning.js';
53
69
  /**
54
- * The LlmAgent fields a YAML agent may set beyond model, instruction, tools
55
- * and schemas. The schema reference (config/agents/syndicateSchema.yaml)
56
- * documents each as mapping 1:1 to its ADK counterpart; before this they
57
- * were parsed and silently dropped, so `includeContents: none` — which the
58
- * intake template relies on so that a document never sees an earlier one —
59
- * changed nothing. Only fields the YAML sets are passed, so ADK's defaults
60
- * stay in force otherwise.
70
+ * An agent's generateContentConfig with its `reasoning:` key mapped in for
71
+ * the model it runs on. Unchanged (the same object) when the agent sets no
72
+ * `reasoning`. The loader refuses `reasoning` next to the older spelling;
73
+ * this refuses it too, for a config built in code.
61
74
  */
62
- function passthroughFields(cfg) {
63
- const out = {};
64
- if (cfg.includeContents !== undefined)
65
- out.includeContents = cfg.includeContents;
66
- if (cfg.outputKey !== undefined)
67
- out.outputKey = cfg.outputKey;
68
- if (cfg.globalInstruction !== undefined)
69
- out.globalInstruction = cfg.globalInstruction;
70
- if (cfg.disallowTransferToParent !== undefined)
71
- out.disallowTransferToParent = cfg.disallowTransferToParent;
72
- if (cfg.disallowTransferToPeers !== undefined)
73
- out.disallowTransferToPeers = cfg.disallowTransferToPeers;
74
- return out;
75
- }
76
- export const DEFAULT_KEEP_RECENT_EVENTS = 6;
77
- /**
78
- * The LlmAgent fields the engine builds from YAML rather than passing
79
- * through (ADR 0033): `code_execution: gemini` (Gemini's server-side
80
- * sandbox runs the model's Python; nothing runs on this host), `context:`
81
- * (ADK's token-based compactor with an LLM summarizer, so a long
82
- * conversation is summarized instead of overflowing the window), and
83
- * `mode: task` (the agent works until it calls finish_task; on a workflow
84
- * node, its arguments become the node's output).
85
- */
86
- function executionFields(cfg, opts) {
87
- const out = {};
88
- if (cfg.code_execution === 'gemini')
89
- out.codeExecutor = new BuiltInCodeExecutor();
90
- if (cfg.mode)
91
- out.mode = cfg.mode;
92
- if (cfg.context) {
93
- const resolve = opts.resolveModel ?? ((m) => m);
94
- const summaryModel = resolve(cfg.context.summary_model ?? cfg.model);
95
- const llm = typeof summaryModel === 'string' || !summaryModel ? LLMRegistry.newLlm(String(summaryModel ?? cfg.model)) : summaryModel;
96
- out.contextCompactors = [
97
- new TokenBasedContextCompactor({
98
- tokenThreshold: cfg.context.compact_after_tokens,
99
- eventRetentionSize: cfg.context.keep_recent_events ?? DEFAULT_KEEP_RECENT_EVENTS,
100
- summarizer: new LlmSummarizer({ llm }),
101
- }),
102
- ];
75
+ export function withReasoning(agent, model) {
76
+ const cfg = agent.generateContentConfig;
77
+ if (agent.reasoning === undefined)
78
+ return cfg;
79
+ const clash = REASONING_OLDER_SPELLING.filter((k) => cfg?.[k] !== undefined);
80
+ if (clash.length) {
81
+ throw new Error(`${agent.name ?? 'agent'}: reasoning cannot be combined with ${clash.map((k) => `generateContentConfig.${k}`).join(' or ')}; reasoning replaces it (ADR 0047)`);
103
82
  }
104
- return out;
83
+ return { ...cfg, ...reasoningConfig(model ?? '', agent.reasoning) };
84
+ }
85
+ /** The model id an agent runs on, from its YAML or its resolved adapter. */
86
+ function modelIdOf(yamlModel, resolved) {
87
+ return yamlModel ?? (typeof resolved === 'string' ? resolved : resolved instanceof BaseLlm ? resolved.model : undefined);
105
88
  }
89
+ export { DEFAULT_KEEP_RECENT_EVENTS } from './runtime/native/compaction.js';
106
90
  /**
107
91
  * Says, once per compiled agent, what its resolved path cannot honour — a
108
92
  * dropped server-side tool, a gateway stand-in, or no route at all. Quiet
@@ -131,9 +115,13 @@ export function requireApprovalOn(tool) {
131
115
  return gated;
132
116
  }
133
117
  /**
134
- * A copy of an OpenAPI tool (lib/tools/openapiTools.ts) that runs only after
135
- * a person approves the call: the same confirmation interrupt FunctionTool's
136
- * own gate raises, so the turn pauses and resumes exactly as ADR 0028 says.
118
+ * A copy of an ADK BaseTool that runs only after a person approves the
119
+ * call: the same confirmation interrupt FunctionTool's own gate raises, so
120
+ * the turn pauses and resumes exactly as ADR 0028 says. The engine no
121
+ * longer uses it: an OpenAPI operation is a FunctionTool over an own Tool
122
+ * (ADR 0067) and takes requireApprovalOn like every registry tool.
123
+ * @deprecated Gate a FunctionTool with requireApprovalOn, or an own Tool
124
+ * with requireApproval (lib/tools/tool.ts).
137
125
  */
138
126
  export function requireApprovalOnBaseTool(tool) {
139
127
  const gated = Object.create(tool);
@@ -157,17 +145,16 @@ function gateTools(tools, names, agentName) {
157
145
  return tools;
158
146
  const wanted = new Set(names);
159
147
  const out = tools.map((t) => {
160
- const tool = t;
161
- const name = tool?.name;
148
+ const name = t?.name;
162
149
  if (!name)
163
150
  return t;
164
151
  // An OpenAPI operation may be named as the YAML named it (its operationId).
165
- const match = [...wanted].find((w) => w === name || (isOpenApiTool(t) && namesTool(w, { name, operation: tool.operation })));
152
+ const operationId = openApiOperationId(t);
153
+ const match = [...wanted].find((w) => w === name || (operationId !== undefined && namesTool(w, { name, operation: { operationId } })));
166
154
  if (!match)
167
155
  return t;
168
156
  wanted.delete(match);
169
- if (isOpenApiTool(t))
170
- return requireApprovalOnBaseTool(t);
157
+ // An OpenAPI operation is a FunctionTool over an own Tool (ADR 0067): one gate for both.
171
158
  if (!(t instanceof FunctionTool)) {
172
159
  throw new Error(`${agentName}: '${name}' cannot require approval — only function tools from the registry and OpenAPI operations can be gated (ADR 0028).`);
173
160
  }
@@ -185,27 +172,14 @@ export function declaresApprovals(config) {
185
172
  return agentGates(config.orchestrator) || (config.subagents ?? []).some((s) => agentGates(s));
186
173
  }
187
174
  /**
188
- * ADK's ExampleTool from YAML pairs: never called by the model, it adds the
189
- * exchanges to every request's instruction as few-shot examples.
175
+ * An agent's `examples:` as the ADK tool for their InstructionTool
176
+ * (lib/tools/examples.ts): never called by the model, it adds the exchanges
177
+ * to every request's instruction as few-shot examples, in the words ADK's
178
+ * ExampleTool used.
190
179
  */
191
180
  export function examplesTool(examples) {
192
- if (!examples?.length)
193
- return [];
194
- return [
195
- new ExampleTool(examples.map((e) => ({ input: { role: 'user', parts: [{ text: e.input }] }, output: [{ role: 'model', parts: [{ text: e.output }] }] }))),
196
- ];
197
- }
198
- /**
199
- * An agent with `fallback_model:` gets its model wrapped (lib/models/fallback.ts):
200
- * the fallback answers a provider-side failure, and a provider that keeps
201
- * failing is skipped for a cooldown. A model id string is resolved to its
202
- * adapter first, so the wrapper always holds two adapters.
203
- */
204
- function withFallback(primary, fallbackId, resolve, opts) {
205
- if (!fallbackId)
206
- return primary;
207
- const asLlm = (m) => (m instanceof BaseLlm ? m : resolveRegistryModel(String(m)));
208
- return new FallbackLlm(asLlm(primary), asLlm(resolve(fallbackId)), opts.log ?? ((m) => console.warn(m)));
181
+ const tool = examplesInstructionTool(examples);
182
+ return tool ? [toAdkInstructionTool(tool)] : [];
209
183
  }
210
184
  async function resolveAgentTools(toolNames, mcpServerUrl, opts, openapi, examples, mcpAllowed) {
211
185
  const tools = [...resolveNamedTools(toolNames, opts.onUnknownTool), ...examplesTool(examples)];
@@ -258,22 +232,62 @@ async function withSkills(instruction, tools, skills, agentName, opts) {
258
232
  opts.log?.(`skills · ${agentName}: ${count} skill${count === 1 ? '' : 's'} from ${skills.dir}${skills.scripts === 'local' ? ' · scripts run after approval' : ''}`);
259
233
  for (const problem of harness.problems)
260
234
  opts.log?.(`⚠ skills · ${skills.dir}: not loaded — ${problem}`);
261
- return { instruction: `${instruction.trimEnd()}\n\n${harness.instruction}`, tools: [...tools, harness.toolset] };
235
+ // The ADK face of the engine's own toolset; compileNative reads the toolset back (toolsetOf).
236
+ return { instruction: `${instruction.trimEnd()}\n\n${harness.instruction}`, tools: [...tools, toAdkToolset(harness.toolset)] };
262
237
  }
263
238
  /** True when a turn running this agent directly may pause for a person (ADR 0028). */
264
239
  export function agentGates(agent) {
265
240
  return !!agent?.require_approval?.length || agent?.skills?.scripts === 'local';
266
241
  }
242
+ function specOf(yaml, name, description, instruction, tools, opts) {
243
+ const resolvedModel = (opts.resolveModel ?? ((m) => m))(yaml.model);
244
+ const modelId = modelIdOf(yaml.model, resolvedModel);
245
+ const spec = {
246
+ name,
247
+ instruction,
248
+ tools,
249
+ resolvedModel,
250
+ generateContentConfig: withServerSideToolInvocations(withReasoning(yaml, modelId)),
251
+ };
252
+ if (description !== undefined)
253
+ spec.description = description;
254
+ if (yaml.model !== undefined)
255
+ spec.model = yaml.model;
256
+ if (modelId !== undefined)
257
+ spec.modelId = modelId;
258
+ if (yaml.fallback_model)
259
+ spec.fallbackModel = yaml.fallback_model;
260
+ if (yaml.outputSchema)
261
+ spec.outputSchema = yaml.outputSchema;
262
+ if (yaml.includeContents !== undefined)
263
+ spec.includeContents = yaml.includeContents;
264
+ if (yaml.outputKey !== undefined)
265
+ spec.outputKey = yaml.outputKey;
266
+ if (yaml.globalInstruction !== undefined)
267
+ spec.globalInstruction = yaml.globalInstruction;
268
+ if (yaml.disallowTransferToParent !== undefined)
269
+ spec.disallowTransferToParent = yaml.disallowTransferToParent;
270
+ if (yaml.disallowTransferToPeers !== undefined)
271
+ spec.disallowTransferToPeers = yaml.disallowTransferToPeers;
272
+ if (yaml.code_execution)
273
+ spec.codeExecution = yaml.code_execution;
274
+ if (yaml.context)
275
+ spec.context = yaml.context;
276
+ if (yaml.mode)
277
+ spec.mode = yaml.mode;
278
+ return spec;
279
+ }
280
+ const asTools = (tools) => tools.map((tool) => ({ kind: 'tool', tool }));
267
281
  /**
268
- * Builds ONE runnable agent from a subagent entry. A `yaml_reference` entry
269
- * compiles the nested syndicate's whole graph under this entry's name and
282
+ * The spec of ONE agent from a subagent entry. A `yaml_reference` entry is
283
+ * the nested syndicate's whole graph under this entry's name and
270
284
  * description, so the parent sees one tool (or one route) either way.
271
285
  */
272
- export async function compileSubagent(subCfg, opts = {}) {
286
+ export async function compileSubagentSpec(subCfg, opts = {}) {
273
287
  if (subCfg.a2a_agent_url) {
274
288
  // A remote agent has its own model and prompt on its own server; there
275
289
  // is no local agent to build. It is reached as a delegation tool
276
- // (compileGraph) or a dispatch route (lib/runtime/syndicateTurn.ts).
290
+ // (compileSpec) or a dispatch route (lib/runtime/syndicateTurn.ts).
277
291
  throw new Error(`'${subCfg.name}' is a remote A2A agent (a2a_agent_url) and has no local agent to compile.`);
278
292
  }
279
293
  if (subCfg.yaml_reference) {
@@ -284,32 +298,21 @@ export async function compileSubagent(subCfg, opts = {}) {
284
298
  // own subagents do): a pause there cannot reach the caller (ADR 0028).
285
299
  throw new Error(`${subCfg.yaml_reference}: approval gates (require_approval) are not supported inside a nested syndicate.`);
286
300
  }
287
- return compileGraph(nested, opts, subCfg.name, subCfg.description);
301
+ return compileSpec(nested, opts, subCfg.name, subCfg.description);
288
302
  }
289
303
  const gated = gateTools(await resolveAgentTools(subCfg.tools, subCfg.mcp_server_url, opts, subCfg.openapi, subCfg.examples, subCfg.mcp_tools), subCfg.require_approval, subCfg.name);
290
304
  const { instruction, tools } = await withSkills(subCfg.instruction ?? '', gated, subCfg.skills, subCfg.name, opts);
291
- const resolveModel = opts.resolveModel ?? ((m) => m);
292
305
  logCapabilities(opts, subCfg.name, subCfg.model, subCfg.tools);
293
- return new LlmAgent({
294
- name: subCfg.name,
295
- description: subCfg.description,
296
- model: withFallback(resolveModel(subCfg.model), subCfg.fallback_model, resolveModel, opts),
297
- instruction,
298
- tools: tools.length > 0 ? tools : undefined,
299
- outputSchema: subCfg.outputSchema,
300
- generateContentConfig: withServerSideToolInvocations(subCfg.generateContentConfig),
301
- ...passthroughFields(subCfg),
302
- ...executionFields(subCfg, opts),
303
- ...(opts.nodeConfig?.(subCfg.name) ?? {}),
304
- });
306
+ return specOf(subCfg, subCfg.name, subCfg.description, instruction, asTools(tools), opts);
305
307
  }
306
308
  /**
307
- * Compiles a syndicate's orchestrator. In DELEGATE mode its subagents are
308
- * attached as AgentTools; in PLAN-DISPATCH mode it gets none (ADK refuses
309
- * outputSchema + AgentTool on one agent — see config/agents/critic.yaml),
310
- * and the caller dispatches to `compileSubagent(route)` itself.
309
+ * The spec of a syndicate's orchestrator. In DELEGATE mode its subagents
310
+ * come first among its tools, as delegations; in PLAN-DISPATCH mode it gets
311
+ * none (ADK refuses outputSchema + AgentTool on one agent — see
312
+ * config/agents/critic.yaml), and the caller dispatches to a route's own
313
+ * spec itself.
311
314
  */
312
- export async function compileGraph(config, opts = {}, overrideName, overrideDescription) {
315
+ export async function compileSpec(config, opts = {}, overrideName, overrideDescription) {
313
316
  // A registry definition carries its nested syndicates (ADR 0018 item 6).
314
317
  if (config.bundled_references && !opts.loadNested)
315
318
  opts = { ...opts, loadNested: nestedLoader(config) };
@@ -321,31 +324,41 @@ export async function compileGraph(config, opts = {}, overrideName, overrideDesc
321
324
  }
322
325
  if (config.workflow)
323
326
  opts.log?.(`${config.syndicate_name}: nested as a subagent, so only its orchestrator runs (a Workflow cannot be a subagent yet)`);
324
- const compiledTools = isDispatchSyndicate(config)
327
+ const delegated = isDispatchSyndicate(config)
325
328
  ? []
326
329
  : await Promise.all((config.subagents ?? []).map(async (subCfg) => {
327
330
  if (subCfg.a2a_agent_url) {
328
331
  opts.log?.(`Remote A2A agent: ${subCfg.name} → ${subCfg.a2a_agent_url}`);
329
- return remoteAgentTool({ name: subCfg.name, description: subCfg.description, url: subCfg.a2a_agent_url });
332
+ return { kind: 'remote', name: subCfg.name, description: subCfg.description, url: subCfg.a2a_agent_url };
330
333
  }
331
- return new AgentTool({ agent: await compileSubagent(subCfg, opts) });
334
+ return { kind: 'agent', agent: await compileSubagentSpec(subCfg, opts) };
332
335
  }));
336
+ const name = overrideName || config.orchestrator.name;
333
337
  // Orchestrator tools are registry names only — no entrypoint has ever
334
338
  // attached an MCP server to an orchestrator, and this compiler preserves
335
339
  // that exactly rather than widening the contract in passing.
336
- compiledTools.push(...gateTools(await resolveAgentTools(config.orchestrator.tools, undefined, opts, config.orchestrator.openapi, config.orchestrator.examples), config.orchestrator.require_approval, overrideName || config.orchestrator.name));
337
- const { instruction, tools: orchestratorTools } = await withSkills(config.orchestrator.instruction, compiledTools, config.orchestrator.skills, overrideName || config.orchestrator.name, opts);
338
- const resolveModel = opts.resolveModel ?? ((m) => m);
339
- logCapabilities(opts, overrideName || config.orchestrator.name, config.orchestrator.model, config.orchestrator.tools);
340
- return new LlmAgent({
341
- name: overrideName || config.orchestrator.name,
342
- description: overrideDescription || config.orchestrator.description,
343
- model: withFallback(resolveModel(config.orchestrator.model), config.orchestrator.fallback_model, resolveModel, opts),
344
- instruction,
345
- tools: orchestratorTools.length > 0 ? orchestratorTools : undefined,
346
- outputSchema: config.orchestrator.outputSchema,
347
- generateContentConfig: withServerSideToolInvocations(config.orchestrator.generateContentConfig),
348
- ...passthroughFields(config.orchestrator),
349
- ...executionFields(config.orchestrator, opts),
350
- });
340
+ const own = gateTools(await resolveAgentTools(config.orchestrator.tools, undefined, opts, config.orchestrator.openapi, config.orchestrator.examples), config.orchestrator.require_approval, name);
341
+ // The skills toolset goes last, after the delegations and the agent's own tools.
342
+ const { instruction, tools } = await withSkills(config.orchestrator.instruction, own, config.orchestrator.skills, name, opts);
343
+ logCapabilities(opts, name, config.orchestrator.model, config.orchestrator.tools);
344
+ return specOf(config.orchestrator, name, overrideDescription || config.orchestrator.description, instruction, [...delegated, ...asTools(tools)], opts);
345
+ }
346
+ // ── The ADK runtime's agents (lib/compileAdk.ts) ─────────────────────────────
347
+ /**
348
+ * Builds ONE runnable ADK agent from a subagent entry: its spec, as
349
+ * lib/compileAdk.ts builds it. A workflow node's settings
350
+ * (CompileOptions.nodeConfig) apply to a local agent, not to a nested
351
+ * syndicate's orchestrator.
352
+ */
353
+ export async function compileSubagent(subCfg, opts = {}) {
354
+ const spec = await compileSubagentSpec(subCfg, opts);
355
+ return compileAdk(spec, opts, subCfg.yaml_reference ? {} : (opts.nodeConfig?.(subCfg.name) ?? {}));
356
+ }
357
+ /**
358
+ * Compiles a syndicate's orchestrator for the ADK runtime. In DELEGATE mode
359
+ * its subagents are attached as AgentTools; in PLAN-DISPATCH mode it gets
360
+ * none, and the caller dispatches to `compileSubagent(route)` itself.
361
+ */
362
+ export async function compileGraph(config, opts = {}, overrideName, overrideDescription) {
363
+ return compileAdk(await compileSpec(config, opts, overrideName, overrideDescription), opts);
351
364
  }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * lib/compileAdk.ts — an AgentSpec as the ADK runtime runs it: today's
3
+ * LlmAgent (ADR 0045, ADR 0073).
4
+ *
5
+ * WHY this file exists:
6
+ * lib/compile.ts turns a YAML agent into a runtime-neutral AgentSpec: its
7
+ * tools resolved and gated, its instruction with the skills index, its
8
+ * model resolved once and its generateContentConfig built for that model.
9
+ * This file adds what only ADK's LlmAgent takes: the model wrapped in a
10
+ * FallbackLlm for `fallback_model:`, each delegated subagent as an
11
+ * AgentTool (a remote one as its A2A tool), Gemini's code executor, the
12
+ * context compactor, task mode and a workflow node's settings. Every field
13
+ * reaches LlmAgent as compileGraph and compileSubagent always passed it, so
14
+ * the ADK runtime runs the agent it ran before the split.
15
+ * lib/compileNative.ts builds the native loop's agent from the same spec.
16
+ *
17
+ * Imports from lib/compile.ts are types only, so the two modules load in
18
+ * either order.
19
+ */
20
+ import { LlmAgent } from '@google/adk';
21
+ import type { AgentSpec, CompileOptions } from './compile.ts';
22
+ import { DEFAULT_KEEP_RECENT_EVENTS } from './runtime/native/compaction.ts';
23
+ /** Events kept verbatim after a compaction summary when `context:` names none: the native compactor's default. */
24
+ export { DEFAULT_KEEP_RECENT_EVENTS };
25
+ /**
26
+ * The LlmAgent for `spec`. `extra` is spread last: a workflow node's
27
+ * settings (CompileOptions.nodeConfig), which compileSubagent passes.
28
+ */
29
+ export declare function compileAdk(spec: AgentSpec, opts?: CompileOptions, extra?: Record<string, unknown>): LlmAgent;
@@ -0,0 +1,132 @@
1
+ /**
2
+ * lib/compileAdk.ts — an AgentSpec as the ADK runtime runs it: today's
3
+ * LlmAgent (ADR 0045, ADR 0073).
4
+ *
5
+ * WHY this file exists:
6
+ * lib/compile.ts turns a YAML agent into a runtime-neutral AgentSpec: its
7
+ * tools resolved and gated, its instruction with the skills index, its
8
+ * model resolved once and its generateContentConfig built for that model.
9
+ * This file adds what only ADK's LlmAgent takes: the model wrapped in a
10
+ * FallbackLlm for `fallback_model:`, each delegated subagent as an
11
+ * AgentTool (a remote one as its A2A tool), Gemini's code executor, the
12
+ * context compactor, task mode and a workflow node's settings. Every field
13
+ * reaches LlmAgent as compileGraph and compileSubagent always passed it, so
14
+ * the ADK runtime runs the agent it ran before the split.
15
+ * lib/compileNative.ts builds the native loop's agent from the same spec.
16
+ *
17
+ * Imports from lib/compile.ts are types only, so the two modules load in
18
+ * either order.
19
+ */
20
+ import { AgentTool, BaseLlm, BuiltInCodeExecutor, LLMRegistry, LlmAgent, LlmSummarizer, LogLevel, TokenBasedContextCompactor, setLogLevel as setAdkLogLevel } from '@google/adk';
21
+ import { remoteAgentTool } from './a2a/remoteAgent.js';
22
+ import { FallbackLlm } from './models/fallback.js';
23
+ import { resolveModel as resolveRegistryModel } from './models/registry.js';
24
+ import { onLogLevel } from './runtime/logging.js';
25
+ import { DEFAULT_KEEP_RECENT_EVENTS } from './runtime/native/compaction.js';
26
+ /**
27
+ * ADK's logger follows the engine's level (lib/runtime/logging.ts, ADR
28
+ * 0080), so a surface sets one level and never names ADK to quiet it.
29
+ */
30
+ const ADK_LOG_LEVELS = {
31
+ debug: LogLevel.DEBUG,
32
+ info: LogLevel.INFO,
33
+ warn: LogLevel.WARN,
34
+ error: LogLevel.ERROR,
35
+ };
36
+ onLogLevel((level) => setAdkLogLevel(ADK_LOG_LEVELS[level]));
37
+ /** Events kept verbatim after a compaction summary when `context:` names none: the native compactor's default. */
38
+ export { DEFAULT_KEEP_RECENT_EVENTS };
39
+ /**
40
+ * The LlmAgent fields a YAML agent may set beyond model, instruction, tools
41
+ * and schemas. The schema reference (config/agents/syndicateSchema.yaml)
42
+ * documents each as mapping 1:1 to its ADK counterpart. Only fields the YAML
43
+ * sets are passed, so ADK's defaults stay in force otherwise.
44
+ */
45
+ function passthroughFields(spec) {
46
+ const out = {};
47
+ if (spec.includeContents !== undefined)
48
+ out.includeContents = spec.includeContents;
49
+ if (spec.outputKey !== undefined)
50
+ out.outputKey = spec.outputKey;
51
+ if (spec.globalInstruction !== undefined)
52
+ out.globalInstruction = spec.globalInstruction;
53
+ if (spec.disallowTransferToParent !== undefined)
54
+ out.disallowTransferToParent = spec.disallowTransferToParent;
55
+ if (spec.disallowTransferToPeers !== undefined)
56
+ out.disallowTransferToPeers = spec.disallowTransferToPeers;
57
+ return out;
58
+ }
59
+ /**
60
+ * The LlmAgent fields the engine builds from YAML rather than passing
61
+ * through (ADR 0033): `code_execution: gemini` (Gemini's server-side
62
+ * sandbox runs the model's Python; nothing runs on this host), `context:`
63
+ * (ADK's token-based compactor with an LLM summarizer, so a long
64
+ * conversation is summarized instead of overflowing the window), and
65
+ * `mode: task` (the agent works until it calls finish_task; on a workflow
66
+ * node, its arguments become the node's output).
67
+ */
68
+ function executionFields(cfg, opts) {
69
+ const out = {};
70
+ if (cfg.codeExecution === 'gemini')
71
+ out.codeExecutor = new BuiltInCodeExecutor();
72
+ if (cfg.mode)
73
+ out.mode = cfg.mode;
74
+ if (cfg.context) {
75
+ const resolve = opts.resolveModel ?? ((m) => m);
76
+ const summaryModel = resolve(cfg.context.summary_model ?? cfg.model);
77
+ const llm = typeof summaryModel === 'string' || !summaryModel ? LLMRegistry.newLlm(String(summaryModel ?? cfg.model)) : summaryModel;
78
+ out.contextCompactors = [
79
+ new TokenBasedContextCompactor({
80
+ tokenThreshold: cfg.context.compact_after_tokens,
81
+ eventRetentionSize: cfg.context.keep_recent_events ?? DEFAULT_KEEP_RECENT_EVENTS,
82
+ summarizer: new LlmSummarizer({ llm }),
83
+ }),
84
+ ];
85
+ }
86
+ return out;
87
+ }
88
+ /**
89
+ * An agent with `fallback_model:` gets its model wrapped (lib/models/fallback.ts):
90
+ * the fallback answers a provider-side failure, and a provider that keeps
91
+ * failing is skipped for a cooldown. A model id string is resolved to its
92
+ * adapter first, so the wrapper always holds two adapters.
93
+ */
94
+ function withFallback(primary, fallbackId, opts) {
95
+ if (!fallbackId)
96
+ return primary;
97
+ const resolve = opts.resolveModel ?? ((m) => m);
98
+ const asLlm = (m) => (m instanceof BaseLlm ? m : resolveRegistryModel(String(m)));
99
+ return new FallbackLlm(asLlm(primary), asLlm(resolve(fallbackId)), opts.log ?? ((m) => console.warn(m)));
100
+ }
101
+ /** The spec's tools as LlmAgent takes them: a delegated subagent as an AgentTool, a remote one as its A2A tool. */
102
+ function adkTools(spec, opts) {
103
+ return spec.tools.map((entry) => {
104
+ switch (entry.kind) {
105
+ case 'tool':
106
+ return entry.tool;
107
+ case 'agent':
108
+ return new AgentTool({ agent: compileAdk(entry.agent, opts) });
109
+ case 'remote':
110
+ return remoteAgentTool({ name: entry.name, description: entry.description, url: entry.url });
111
+ }
112
+ });
113
+ }
114
+ /**
115
+ * The LlmAgent for `spec`. `extra` is spread last: a workflow node's
116
+ * settings (CompileOptions.nodeConfig), which compileSubagent passes.
117
+ */
118
+ export function compileAdk(spec, opts = {}, extra = {}) {
119
+ const tools = adkTools(spec, opts);
120
+ return new LlmAgent({
121
+ name: spec.name,
122
+ description: spec.description,
123
+ model: withFallback(spec.resolvedModel, spec.fallbackModel, opts),
124
+ instruction: spec.instruction,
125
+ tools: tools.length > 0 ? tools : undefined,
126
+ outputSchema: spec.outputSchema,
127
+ generateContentConfig: spec.generateContentConfig,
128
+ ...passthroughFields(spec),
129
+ ...executionFields(spec, opts),
130
+ ...extra,
131
+ });
132
+ }
@@ -0,0 +1,85 @@
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 type { AgentSpec, CompileOptions } from './compile.ts';
42
+ import type { SubagentYamlConfig, SyndicateYamlConfig } from './loadSyndicate.ts';
43
+ import type { ModelAdapter } from './models/contract.ts';
44
+ import type { NativeAgent } from './runtime/native/request.ts';
45
+ export { UnsupportedOnRuntimeError, unsupportedOnNative } from './runtime/runtimeFlag.ts';
46
+ /**
47
+ * The class name of an ADK model the native runtime cannot run, else
48
+ * undefined: an ADK BaseLlm that is neither ADK's Gemini (TracedGemini
49
+ * included) nor a shim carrying a contract adapter (lib/models/adkShim.ts).
50
+ */
51
+ export declare function unrunnableModelClass(resolved: unknown): string | undefined;
52
+ /**
53
+ * The NativeAgent for `spec`. Throws when no model id is known, and
54
+ * UnsupportedOnRuntimeError when the resolver returned an ADK model class
55
+ * the loop cannot call (see the header).
56
+ */
57
+ export declare function compileNative(spec: AgentSpec): NativeAgent;
58
+ /**
59
+ * The model id a request is sent under, as ADK's LlmAgent sends it: the id
60
+ * of the model object the resolver returned (an ADK model or a contract
61
+ * adapter carries its own), else the id the resolver returned, else the
62
+ * spec's. A resolver may answer a YAML id with a model under another id (a
63
+ * gateway stand-in, a caller's alias); the adapter, the span and the
64
+ * circuit breaker then see that id on both runtimes.
65
+ */
66
+ export declare function wireModelOf(spec: Pick<AgentSpec, 'modelId' | 'resolvedModel'>): string | undefined;
67
+ /** A syndicate's orchestrator for the native loop: compileSpec, then compileNative. */
68
+ export declare function compileNativeGraph(config: SyndicateYamlConfig, opts?: CompileOptions): Promise<NativeAgent>;
69
+ /** One subagent entry (a dispatch route) for the native loop: compileSubagentSpec, then compileNative. */
70
+ export declare function compileNativeSubagent(subCfg: SubagentYamlConfig, opts?: CompileOptions): Promise<NativeAgent>;
71
+ /** What nativeAdapterFor reads from a spec: its model resolution, the other ids it calls, and its delegated subagents. */
72
+ type NativeModelSpec = Pick<AgentSpec, 'modelId' | 'resolvedModel'> & Partial<Pick<AgentSpec, 'name' | 'fallbackModel' | 'context' | 'tools'>>;
73
+ /**
74
+ * The loop's `adapterFor` under the same model resolution the ADK runtime
75
+ * uses: the leaf adapter behind what CompileOptions.resolveModel returns
76
+ * (an ADK shim carries its contract adapter, so a caller's BYOK key on a
77
+ * shimmed provider reaches the call), else resolveAdapter for the id
78
+ * (lib/models/registry.ts). The spec's own resolution, and each delegated
79
+ * subagent's, is reused for the id its agent runs under (wireModelOf).
80
+ * Each agent's `fallback_model:` and compaction `summary_model` are
81
+ * resolved here, as compileAdk resolves them at compile time, so a model
82
+ * class native cannot run is refused before any model call; any other id
83
+ * is resolved when first asked for. Each is kept.
84
+ */
85
+ export declare function nativeAdapterFor(opts?: CompileOptions, spec?: NativeModelSpec | readonly NativeModelSpec[]): (model: string) => ModelAdapter;