melchizedek-agents 0.20.0 → 1.0.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 (207) hide show
  1. package/.env.example +4 -5
  2. package/AGENT_SETUP.md +3 -3
  3. package/CHANGELOG.md +240 -0
  4. package/DOCUMENTATION.md +142 -150
  5. package/QUICKSTART.md +12 -11
  6. package/README.md +11 -11
  7. package/config/agents/examples/image_production.yaml +2 -2
  8. package/config/agents/syndicateSchema.yaml +52 -26
  9. package/dist/lib/a2a/app.d.ts +17 -12
  10. package/dist/lib/a2a/app.js +16 -6
  11. package/dist/lib/a2a/executor.d.ts +10 -14
  12. package/dist/lib/a2a/executor.js +10 -18
  13. package/dist/lib/a2a/remoteAgent.d.ts +5 -12
  14. package/dist/lib/a2a/remoteAgent.js +5 -12
  15. package/dist/lib/compile.d.ts +76 -86
  16. package/dist/lib/compile.js +100 -116
  17. package/dist/lib/compileNative.d.ts +44 -56
  18. package/dist/lib/compileNative.js +91 -89
  19. package/dist/lib/config.d.ts +6 -6
  20. package/dist/lib/config.js +6 -6
  21. package/dist/lib/doctor.d.ts +8 -14
  22. package/dist/lib/doctor.js +10 -46
  23. package/dist/lib/index.d.ts +12 -9
  24. package/dist/lib/index.js +10 -11
  25. package/dist/lib/loadSyndicate.d.ts +3 -3
  26. package/dist/lib/loadSyndicate.js +2 -2
  27. package/dist/lib/memory/erase.d.ts +1 -1
  28. package/dist/lib/memory/erase.js +1 -1
  29. package/dist/lib/memory/namespace.d.ts +12 -14
  30. package/dist/lib/memory/namespace.js +13 -14
  31. package/dist/lib/memory/providers.d.ts +4 -5
  32. package/dist/lib/memory/providers.js +12 -6
  33. package/dist/lib/memory/supabaseMemoryService.d.ts +9 -30
  34. package/dist/lib/memory/supabaseMemoryService.js +8 -30
  35. package/dist/lib/model.d.ts +6 -12
  36. package/dist/lib/model.js +6 -12
  37. package/dist/lib/models/adapterResolver.d.ts +21 -40
  38. package/dist/lib/models/adapterResolver.js +32 -40
  39. package/dist/lib/models/chatCompletionsAdapter.d.ts +12 -33
  40. package/dist/lib/models/chatCompletionsAdapter.js +13 -18
  41. package/dist/lib/models/circuitBreaker.d.ts +5 -5
  42. package/dist/lib/models/circuitBreaker.js +5 -5
  43. package/dist/lib/models/claudeAdapter.d.ts +9 -26
  44. package/dist/lib/models/claudeAdapter.js +11 -15
  45. package/dist/lib/models/claudeModels.d.ts +4 -4
  46. package/dist/lib/models/claudeModels.js +4 -4
  47. package/dist/lib/models/contract.d.ts +11 -11
  48. package/dist/lib/models/contract.js +6 -6
  49. package/dist/lib/models/errorResponse.d.ts +13 -20
  50. package/dist/lib/models/errorResponse.js +0 -12
  51. package/dist/lib/models/fallbackAdapter.d.ts +7 -8
  52. package/dist/lib/models/gatewayAdapter.d.ts +1 -1
  53. package/dist/lib/models/gatewayAdapter.js +1 -1
  54. package/dist/lib/models/geminiAdapter.d.ts +5 -6
  55. package/dist/lib/models/geminiAdapter.js +9 -10
  56. package/dist/lib/models/geminiState.d.ts +8 -8
  57. package/dist/lib/models/geminiState.js +8 -8
  58. package/dist/lib/models/genaiMapping.d.ts +82 -36
  59. package/dist/lib/models/genaiMapping.js +41 -41
  60. package/dist/lib/models/gptAdapter.d.ts +11 -11
  61. package/dist/lib/models/gptAdapter.js +13 -13
  62. package/dist/lib/models/kimiAdapter.d.ts +6 -7
  63. package/dist/lib/models/kimiAdapter.js +6 -9
  64. package/dist/lib/models/ollamaAdapter.d.ts +3 -3
  65. package/dist/lib/models/ollamaAdapter.js +3 -3
  66. package/dist/lib/models/providerMap.d.ts +6 -5
  67. package/dist/lib/models/providerMap.js +6 -5
  68. package/dist/lib/models/providerState.d.ts +3 -2
  69. package/dist/lib/models/providerState.js +3 -2
  70. package/dist/lib/models/reasoning.d.ts +1 -1
  71. package/dist/lib/models/registry.d.ts +26 -73
  72. package/dist/lib/models/registry.js +31 -144
  73. package/dist/lib/models/retry.d.ts +2 -2
  74. package/dist/lib/models/retry.js +2 -2
  75. package/dist/lib/models/schemaNormalize.d.ts +25 -55
  76. package/dist/lib/models/schemaNormalize.js +30 -100
  77. package/dist/lib/observability/lineage.d.ts +3 -3
  78. package/dist/lib/observability/lineage.js +10 -10
  79. package/dist/lib/observability/supabaseSpanExporter.js +1 -1
  80. package/dist/lib/observability/tracer.d.ts +25 -23
  81. package/dist/lib/observability/tracer.js +26 -63
  82. package/dist/lib/persistence/supabaseProvider.d.ts +4 -3
  83. package/dist/lib/runtime/approvals.d.ts +1 -1
  84. package/dist/lib/runtime/credentials.d.ts +1 -1
  85. package/dist/lib/runtime/events.d.ts +3 -4
  86. package/dist/lib/runtime/events.js +3 -4
  87. package/dist/lib/runtime/logging.d.ts +3 -8
  88. package/dist/lib/runtime/logging.js +3 -8
  89. package/dist/lib/runtime/memoryService.d.ts +4 -6
  90. package/dist/lib/runtime/memoryService.js +3 -5
  91. package/dist/lib/runtime/native/agentLoop.d.ts +18 -16
  92. package/dist/lib/runtime/native/agentLoop.js +38 -26
  93. package/dist/lib/runtime/native/compaction.d.ts +10 -11
  94. package/dist/lib/runtime/native/compaction.js +10 -11
  95. package/dist/lib/runtime/native/delegate.d.ts +13 -14
  96. package/dist/lib/runtime/native/delegate.js +11 -18
  97. package/dist/lib/runtime/native/history.d.ts +5 -6
  98. package/dist/lib/runtime/native/history.js +5 -6
  99. package/dist/lib/runtime/native/interrupts.d.ts +6 -6
  100. package/dist/lib/runtime/native/interrupts.js +6 -6
  101. package/dist/lib/runtime/native/request.d.ts +24 -24
  102. package/dist/lib/runtime/native/request.js +35 -24
  103. package/dist/lib/runtime/native/selfCorrection.d.ts +32 -32
  104. package/dist/lib/runtime/native/selfCorrection.js +34 -34
  105. package/dist/lib/runtime/native/step.d.ts +23 -23
  106. package/dist/lib/runtime/native/step.js +49 -27
  107. package/dist/lib/runtime/native/taskMode.d.ts +8 -8
  108. package/dist/lib/runtime/native/taskMode.js +8 -8
  109. package/dist/lib/runtime/native/telemetry.d.ts +11 -11
  110. package/dist/lib/runtime/native/telemetry.js +11 -11
  111. package/dist/lib/runtime/native/tempState.d.ts +4 -4
  112. package/dist/lib/runtime/native/tempState.js +4 -4
  113. package/dist/lib/runtime/nativeTurn.d.ts +29 -32
  114. package/dist/lib/runtime/nativeTurn.js +30 -41
  115. package/dist/lib/runtime/questions.d.ts +8 -9
  116. package/dist/lib/runtime/questions.js +1 -2
  117. package/dist/lib/runtime/runtimeFlag.d.ts +28 -14
  118. package/dist/lib/runtime/runtimeFlag.js +38 -16
  119. package/dist/lib/runtime/sessions.d.ts +10 -12
  120. package/dist/lib/runtime/sessions.js +10 -12
  121. package/dist/lib/runtime/syndicateTurn.d.ts +44 -45
  122. package/dist/lib/runtime/syndicateTurn.js +163 -158
  123. package/dist/lib/runtime/turnControl.d.ts +8 -8
  124. package/dist/lib/runtime/turnControl.js +8 -8
  125. package/dist/lib/session/supabaseSessionService.d.ts +7 -21
  126. package/dist/lib/session/supabaseSessionService.js +7 -43
  127. package/dist/lib/session/transcript.d.ts +16 -26
  128. package/dist/lib/session/transcript.js +17 -57
  129. package/dist/lib/storage/postgres/sessionService.d.ts +6 -20
  130. package/dist/lib/storage/postgres/sessionService.js +6 -39
  131. package/dist/lib/syndicateSchema.js +7 -6
  132. package/dist/lib/toolRegistry.d.ts +9 -14
  133. package/dist/lib/toolRegistry.js +36 -33
  134. package/dist/lib/tools/auth.d.ts +1 -1
  135. package/dist/lib/tools/auth.js +1 -1
  136. package/dist/lib/tools/examples.d.ts +2 -4
  137. package/dist/lib/tools/examples.js +2 -4
  138. package/dist/lib/tools/generateImageTool.d.ts +3 -3
  139. package/dist/lib/tools/generateImageTool.js +4 -5
  140. package/dist/lib/tools/inspectImageTool.d.ts +2 -2
  141. package/dist/lib/tools/inspectImageTool.js +3 -4
  142. package/dist/lib/tools/mcpToolFactory.d.ts +4 -24
  143. package/dist/lib/tools/mcpToolFactory.js +19 -9
  144. package/dist/lib/tools/memoryTools.d.ts +5 -6
  145. package/dist/lib/tools/memoryTools.js +5 -6
  146. package/dist/lib/tools/nativeTools.d.ts +9 -14
  147. package/dist/lib/tools/nativeTools.js +9 -14
  148. package/dist/lib/tools/openapiTools.d.ts +5 -7
  149. package/dist/lib/tools/openapiTools.js +6 -13
  150. package/dist/lib/tools/scienceTools.d.ts +3 -3
  151. package/dist/lib/tools/scienceTools.js +8 -10
  152. package/dist/lib/tools/skillToolset.d.ts +1 -2
  153. package/dist/lib/tools/skillToolset.js +1 -2
  154. package/dist/lib/tools/skills/executor.d.ts +1 -1
  155. package/dist/lib/tools/skills/executor.js +1 -1
  156. package/dist/lib/tools/skills/frontmatter.d.ts +2 -2
  157. package/dist/lib/tools/skills/frontmatter.js +2 -2
  158. package/dist/lib/tools/skills/tools.d.ts +8 -10
  159. package/dist/lib/tools/skills/tools.js +9 -11
  160. package/dist/lib/tools/tool.d.ts +24 -40
  161. package/dist/lib/tools/tool.js +24 -56
  162. package/dist/lib/tools/toolContract.d.ts +8 -13
  163. package/dist/lib/tools/toolContract.js +6 -17
  164. package/dist/lib/tools/webExtractTool.d.ts +2 -2
  165. package/dist/lib/tools/webExtractTool.js +3 -4
  166. package/dist/lib/tools/wikiTools.d.ts +2 -2
  167. package/dist/lib/tools/wikiTools.js +5 -6
  168. package/dist/lib/tools/xApiSearchTool.d.ts +2 -2
  169. package/dist/lib/tools/xApiSearchTool.js +3 -4
  170. package/dist/lib/tools/xaiSearchParams.d.ts +2 -5
  171. package/dist/lib/tools/xaiSearchParams.js +2 -5
  172. package/dist/lib/wiki/agentRun.d.ts +10 -11
  173. package/dist/lib/wiki/agentRun.js +24 -42
  174. package/dist/lib/workflow/agentNode.d.ts +10 -1
  175. package/dist/lib/workflow/agentNode.js +5 -3
  176. package/dist/lib/workflow/graph.d.ts +8 -9
  177. package/dist/lib/workflow/graph.js +12 -12
  178. package/dist/lib/workflow/nodeEvents.d.ts +5 -5
  179. package/dist/lib/workflow/nodeEvents.js +5 -5
  180. package/dist/lib/workflow/pause.d.ts +5 -4
  181. package/dist/lib/workflow/pause.js +5 -4
  182. package/dist/lib/workflow/resume.d.ts +4 -4
  183. package/dist/lib/workflow/resume.js +4 -4
  184. package/dist/lib/workflow/route.d.ts +7 -7
  185. package/dist/lib/workflow/route.js +8 -8
  186. package/dist/lib/workflow/scheduler.d.ts +44 -2
  187. package/dist/lib/workflow/scheduler.js +60 -6
  188. package/dist/lib/workflow/toolNode.d.ts +18 -29
  189. package/dist/lib/workflow/toolNode.js +29 -35
  190. package/dist/lib/workflow/turn.d.ts +29 -20
  191. package/dist/lib/workflow/turn.js +111 -24
  192. package/dist/lib/workflow.d.ts +34 -60
  193. package/dist/lib/workflow.js +34 -168
  194. package/dist/lib/workflowConfig.d.ts +2 -10
  195. package/dist/lib/workflowConfig.js +2 -31
  196. package/dist/scripts/a2a_server.js +1 -2
  197. package/dist/scripts/assistant_worker.d.ts +2 -2
  198. package/dist/scripts/assistant_worker.js +8 -7
  199. package/dist/scripts/doctor.d.ts +2 -2
  200. package/dist/scripts/doctor.js +2 -2
  201. package/dist/scripts/syndicate_chat.js +14 -24
  202. package/package.json +3 -9
  203. package/skills/briefs/_shared.md +2 -2
  204. package/skills/briefs/melchizedek-author.md +2 -2
  205. package/skills/briefs/melchizedek-models.md +6 -6
  206. package/skills/melchizedek-author/SKILL.md +2 -2
  207. package/skills/melchizedek-models/SKILL.md +5 -5
@@ -2,28 +2,27 @@
2
2
  * lib/workflow/turn.ts — one turn of a workflow syndicate on the native
3
3
  * runtime: the message stored, the graph walked by the engine's scheduler,
4
4
  * and every event the walk stores yielded in the order it was stored, the
5
- * node inputs aside, as ADK's Runner yields them (ADR 0095).
5
+ * node inputs aside, as ADK's Runner yielded them (ADR 0095).
6
6
  *
7
7
  * WHY this file exists:
8
- * runSyndicateTurn (lib/runtime/syndicateTurn.ts) runs a workflow on ADK
9
- * by handing ADK's Workflow to its Runner and draining the events the
10
- * Runner yields (drainAgentStream). On the native runtime it hands this
11
- * generator to the same drain, under the same root span, so the progress
12
- * lines, onProgress calls, node errors, the paused input and the ledger
13
- * rows come out of one reader on both runtimes. Everything a node does is
8
+ * runSyndicateTurn (lib/runtime/syndicateTurn.ts) hands this generator to
9
+ * the turn's reader (drainAgentStream), under the turn's root span, as it
10
+ * once handed ADK's Runner stream, so the progress lines, onProgress
11
+ * calls, node errors, the paused input and the ledger rows come out of
12
+ * the one reader every turn uses. Everything a node does is
14
13
  * the WS4 modules': the scheduler (scheduler.ts), agent nodes on the
15
14
  * native loop (agentNode.ts), tool nodes (toolNode.ts), ask_user nodes and
16
15
  * the workflow's pause record (pause.ts), and the resume rebuilt from the
17
16
  * session (resume.ts). This file wires them for one turn, as ADK's Runner
18
- * and Workflow wire theirs:
17
+ * and Workflow wired theirs:
19
18
  *
20
19
  * 1. THE MESSAGE. Stored as the user's event under a new `e-` invocation
21
- * id, before the walk, as the Runner stores it (runNativeAgent does the
20
+ * id, before the walk, as the Runner stored it (runNativeAgent does the
22
21
  * same for one agent). A turn whose signal aborted first stores nothing.
23
22
  * 2. THE START. workflowResume rebuilds every node's prior runs and the
24
- * answers from the session, as ADK's rehydration does on every message:
23
+ * answers from the session, as ADK's rehydration did on every message:
25
24
  * with nothing paused every node runs fresh. The walk's input is the
26
- * message's text, not its content, as ADK hands its root workflow, and
25
+ * message's text, not its content, as ADK handed its root workflow, and
27
26
  * that text is what the workflow's pause record keeps. A pause only ADK
28
27
  * can resume (UnsupportedWorkflowResumeError) fails the turn; it never
29
28
  * walks afresh and asks the person again.
@@ -32,18 +31,18 @@
32
31
  * turn's signal. Every event a runner stores goes through the agent
33
32
  * node runtime's one queue, in walk order: node inputs, the agents'
34
33
  * events, tool and ask_user events, route steps, joins and maps, and
35
- * the node-error event ADK writes for a node that gave up
34
+ * the node-error event ADK wrote for a node that gave up
36
35
  * (nodeErrorEvent, on the scheduler's `workflow` node_error). A node's
37
- * input turn is stored and not yielded, as ADK's Runner never yields
36
+ * input turn is stored and not yielded, as ADK's Runner never yielded
38
37
  * it; a node agent's partial (streamed) event is yielded and not
39
- * stored, as the Runner yields it.
38
+ * stored, as the Runner yielded it.
40
39
  * 4. THE END. A paused walk stores the workflow's own record
41
40
  * (workflowPauseEvent) after every node's event. A walk the turn
42
41
  * stopped (InvocationAbortedError, or any failure once the signal
43
- * fired) ends quietly, as ADK's Runner ends an aborted run: the turn
42
+ * fired) ends quietly, as ADK's Runner ended an aborted run: the turn
44
43
  * runner reads the stop reason from its control. A node that gave up
45
44
  * rethrows its error once every event is stored and yielded, as ADK's
46
- * Runner throws it.
45
+ * Runner threw it.
47
46
  * 5. THE SPANS. `workflow.invoke <name>` around the walk, `node.execute
48
47
  * <name>` around each node run (the scheduler's traceNode hook), and
49
48
  * `tool.execute <name>` around a tool node's call
@@ -53,24 +52,104 @@
53
52
  *
54
53
  * WHAT IT REFUSES before any model call: refuseUnrunnableNodes throws, for
55
54
  * a tool node, ADK's compile-time refusals (an unregistered tool, a
56
- * long-running one). A pause raised inside an agent node is refused by
55
+ * long-running one), and an ADK tool (anything with runAsync), which 1.0.0
56
+ * no longer runs. A pause raised inside an agent node is refused by
57
57
  * runAgentNode by name.
58
58
  *
59
59
  * It imports nothing from ADK: the caller passes the tool lookup (the
60
- * registry builds ADK's tools) and the store as the engine's interface.
60
+ * registry's own Tools) and the store as the engine's interface.
61
61
  * The message, the answers and every stored event are data the walk
62
62
  * carries, never instructions this module acts on.
63
63
  */
64
64
  import { randomUUID } from 'node:crypto';
65
65
  import { createTurnEvent } from '../runtime/events.js';
66
66
  import { traceNodeExecution, traceToolNodeCall, traceWorkflowInvocation } from '../runtime/native/telemetry.js';
67
- import { agentNodeRuntime } from './agentNode.js';
67
+ import { TEMP_STATE_PREFIX } from '../runtime/sessions.js';
68
+ import { NodeStoppedError, agentNodeRuntime, nodeInputContent } from './agentNode.js';
68
69
  import { askUserNodeRunner, workflowPauseEvent } from './pause.js';
69
70
  import { workflowResume } from './resume.js';
70
71
  import { InvocationAbortedError, nodeErrorEvent, runWorkflowGraph } from './scheduler.js';
71
- import { resolveToolNode, toolNodeRunner } from './toolNode.js';
72
+ import { enrichNodeEvent, resolveToolNode, toolNodeRunner } from './toolNode.js';
73
+ /** ADK's AgentTool answer: the last event's non-thought text parts, joined by a newline. */
74
+ function lastText(event) {
75
+ return (event?.content?.parts ?? [])
76
+ .filter((p) => !p.thought)
77
+ .map((p) => p.text)
78
+ .filter((t) => t)
79
+ .join('\n');
80
+ }
81
+ /**
82
+ * Runs `workflow` as the node `run` names (ADR 0106), as a delegated nested
83
+ * workflow runs (ADR 0098): the whole graph walked on the child session
84
+ * under the node's name (created from the caller's state the first time,
85
+ * `temp:` keys dropped, and kept), the node's input as its message, its last
86
+ * yielded event's text the node's output. The caller stores one event for
87
+ * the node, carrying that output and the walk's state writes, so a resumed
88
+ * walk completes the node from it. A walk that ends paused is refused by
89
+ * name: a pause cannot reach the caller's walk yet (WS6-2).
90
+ */
91
+ async function runWorkflowNode(name, workflow, run, params, parent) {
92
+ const { sessions, userId, sessionId } = params;
93
+ const key = { appName: name, userId, sessionId };
94
+ const state = Object.fromEntries(Object.entries(parent.session.state ?? {}).filter(([k]) => !k.startsWith(TEMP_STATE_PREFIX)));
95
+ if (!(await sessions.get(key)))
96
+ await sessions.create({ ...key, state });
97
+ const input = run.input === undefined || run.input === null ? parent.userContent : nodeInputContent(run.input);
98
+ const walk = runNativeWorkflow({
99
+ graph: workflow.graph,
100
+ agents: workflow.agents,
101
+ resolveTool: workflow.resolveTool,
102
+ ...(workflow.workflows ? { workflows: workflow.workflows } : {}),
103
+ sessions,
104
+ appName: name,
105
+ userId,
106
+ sessionId,
107
+ userParts: input.parts ?? [],
108
+ adapterFor: params.adapterFor,
109
+ signal: run.signal,
110
+ stream: false,
111
+ ...(params.memory ? { memory: params.memory } : {}),
112
+ ...(params.log ? { log: params.log } : {}),
113
+ ...(params.selfCorrection ? { selfCorrection: params.selfCorrection } : {}),
114
+ ...(params.credentials ? { credentials: params.credentials } : {}),
115
+ });
116
+ let last;
117
+ const stateDelta = {};
118
+ let end;
119
+ for (;;) {
120
+ const next = await walk.next();
121
+ if (next.done) {
122
+ end = next.value;
123
+ break;
124
+ }
125
+ if (next.value.partial)
126
+ continue;
127
+ for (const [k, v] of Object.entries(next.value.actions?.stateDelta ?? {}))
128
+ if (!k.startsWith(TEMP_STATE_PREFIX))
129
+ stateDelta[k] = v;
130
+ last = next.value;
131
+ }
132
+ if (!end || end.stopped)
133
+ throw new NodeStoppedError(name, undefined);
134
+ const paused = end.run?.interruptIds ?? [];
135
+ if (paused.length > 0) {
136
+ throw new Error(`Node '${name}': the workflow it runs paused on ${paused.join(', ')}; a pause inside a workflow run as a node cannot reach the walk yet.`);
137
+ }
138
+ const output = lastText(last);
139
+ const event = createTurnEvent({
140
+ author: name,
141
+ invocationId: parent.invocationId,
142
+ content: { role: 'model', parts: [{ text: output }] },
143
+ ...(Object.keys(stateDelta).length ? { actions: { stateDelta } } : {}),
144
+ });
145
+ event.output = output;
146
+ event.nodeInfo = { messageAsOutput: true };
147
+ enrichNodeEvent(event, run, { invocationId: parent.invocationId });
148
+ parent.store(event);
149
+ return { output };
150
+ }
72
151
  /**
73
- * Throws, before any model call, what ADK's compileWorkflow throws for a
152
+ * Throws, before any model call, what ADK's workflow compile threw for a
74
153
  * tool node: an unregistered tool, or a long-running one (ADR 0091).
75
154
  */
76
155
  export function refuseUnrunnableNodes(graph, resolveTool) {
@@ -83,7 +162,7 @@ const isAborted = (error) => error instanceof InvocationAbortedError || error?.n
83
162
  * Runs one turn of the workflow: stores the message, walks the graph (a
84
163
  * resume when the session holds a paused walk), and yields every event the
85
164
  * walk stores, in the order stored, but the node inputs (ADK's Runner
86
- * yields none of them). Returns how the walk ended, or
165
+ * yielded none of them). Returns how the walk ended, or
87
166
  * undefined when the signal fired before the message was stored. Throws
88
167
  * the error a node gave up with (after its events), ADK's message for a
89
168
  * reply that answers nothing, and UnsupportedWorkflowResumeError.
@@ -129,11 +208,19 @@ export async function* runNativeWorkflow(params) {
129
208
  queue.push(event);
130
209
  wake?.();
131
210
  },
132
- // A node agent's streamed text, yielded as ADK's Runner yields its partial events.
211
+ // A node agent's streamed text, yielded as ADK's Runner yielded its partial events.
133
212
  onPartial: (event) => {
134
213
  queue.push(event);
135
214
  wake?.();
136
215
  },
216
+ ...(params.workflows?.size
217
+ ? {
218
+ workflowNodes: {
219
+ has: (name) => params.workflows.has(name),
220
+ run: (name, run) => runWorkflowNode(name, params.workflows.get(name), run, params, { session, invocationId, userContent, store }),
221
+ },
222
+ }
223
+ : {}),
137
224
  });
138
225
  // Every event handed over is queued a microtask later (agentNodeRuntime.store); `stored` waits for all of them.
139
226
  const handed = new Set();
@@ -192,7 +279,7 @@ export async function* runNativeWorkflow(params) {
192
279
  }).then((run) => {
193
280
  end = { run };
194
281
  }, (error) => {
195
- // ADK's Runner ends an aborted run without an error; the turn's control holds why.
282
+ // An aborted run ends without an error, as ADK's Runner ended one; the turn's control holds why.
196
283
  if (isAborted(error) || signal?.aborted)
197
284
  end = { stopped: true };
198
285
  else
@@ -18,77 +18,51 @@
18
18
  * Confirm: { ask_user: "Publish? yes, or say what to change." }
19
19
  * Planner: { route_key: "kind", retry: { max_attempts: 2 } }
20
20
  *
21
- * ADK 2.2 runs it (`Workflow`, `FunctionNode`, `JoinNode`, `ParallelWorker`,
22
- * `ToolNode`, `RequestInput`): per-node retries and timeouts, fan-out and
23
- * fan-in, a pause that waits for a person and resumes on the next message,
24
- * and resumption from the session's own events. Every agent is already a
25
- * node (`LlmAgent extends BaseNode`): a node agent receives the previous
26
- * node's output as its user turn and, unless its YAML sets
27
- * `includeContents`, sees nothing else of the conversation.
21
+ * The engine's scheduler walks it (lib/workflow/, ADR 0095): per-node
22
+ * retries and timeouts, fan-out and fan-in, a pause that waits for a person
23
+ * and resumes on the next message, and resumption from the session's own
24
+ * events, which are the JSON ADK's Workflow stored before 1.0.0. A node
25
+ * agent receives the previous node's output as its user turn and, unless
26
+ * its YAML sets `includeContents`, sees nothing else of the conversation.
28
27
  *
29
- * ── What the engine adds to ADK ───────────────────────────────────────────
30
- * ROUTING. ADK's TypeScript port never derives a route from an agent's
31
- * output, so a routing map in YAML gets a hidden step after the agent
28
+ * ROUTING. A routing map in YAML gets a hidden step after the agent
32
29
  * (`<Agent>__route`) that reads the route from the output — the
33
30
  * `route_key` property of a JSON output, else the trimmed text — and
34
31
  * re-emits the output with it. A `default` key catches what no key
35
32
  * matched.
36
- * THE PAUSE. `ask_user` is a node that raises ADK's `RequestInput`. The
37
- * turn ends `input-required` carrying the question (`result.input`); the
38
- * next message on the conversation is the answer and becomes that node's
39
- * output. The A2A server publishes the question; the chat prints it.
33
+ * THE PAUSE. `ask_user` is a node that asks the person (`adk_request_input`).
34
+ * The turn ends `input-required` carrying the question (`result.input`);
35
+ * the next message on the conversation is the answer and becomes that
36
+ * node's output. The A2A server publishes the question; the chat prints it.
40
37
  * NAMES. Nodes are addressed by their YAML names everywhere (edges, events,
41
- * the wiki), including a `map` node, which ADK would otherwise name after
42
- * the agent it wraps.
38
+ * the wiki), including a `map` node.
43
39
  *
44
40
  * ── As a subagent (ADR 0098) ─────────────────────────────────────────────
45
- * A delegated `yaml_reference` to a workflow syndicate is the whole graph:
46
- * `assembleWorkflow` builds its Workflow under the subagent entry's name
47
- * and description, and lib/compileAdk.ts wraps it in ADK's AgentTool, whose
48
- * answer is the graph's last event's text. A nested workflow with an
41
+ * A delegated `yaml_reference` to a workflow syndicate is the whole graph,
42
+ * walked under the subagent entry's name and description on a child
43
+ * session (lib/compileNative.ts workflowSubagentOf); its answer is the
44
+ * graph's last event's text. A nested workflow with an
49
45
  * `ask_user` node is refused by name (lib/compile.ts compileWorkflowSpec): a
50
- * pause inside a tool call cannot reach the caller (ADR 0028). As a dispatch
51
- * route or a workflow node, a workflow syndicate is still its orchestrator
52
- * alone.
46
+ * pause inside a tool call cannot reach the caller (ADR 0028).
53
47
  *
54
- * ── Approval gates (ADR 0098) ────────────────────────────────────────────
55
- * A tool in a node agent's `require_approval` pauses the node on ADK's
56
- * `adk_request_confirmation`, and the walk with it. Only the native walk
57
- * resumes it (lib/workflow/agentNode.ts): ADK's runLlmAgentAsNode reruns the
58
- * node from its input and never runs the pinned call, so runSyndicateTurn
59
- * refuses a gated workflow on ADK. The schema refuses a gate on an agent a
60
- * map runs (an item cannot pause the walk).
48
+ * ── As a dispatch route or a workflow node (ADR 0106) ────────────────────
49
+ * A `yaml_reference` to a workflow syndicate runs its whole graph there too,
50
+ * on the child session filed under the entry's name, as a subagent does. A
51
+ * route's answer is what the graph would answer as its own syndicate
52
+ * (lib/runtime/syndicateTurn.ts); a node's is the nested walk's
53
+ * (lib/workflow/turn.ts). A map over one is refused (lib/compile.ts).
54
+ *
55
+ * ── Approval gates (ADR 0098, ADR 0106) ──────────────────────────────────
56
+ * A tool in a node agent's `require_approval`, and a skill script
57
+ * (`skills.scripts: local`, run_skill_script), pause the node on
58
+ * `adk_request_confirmation`, and the walk with it; the answer resumes the
59
+ * pinned call (lib/workflow/agentNode.ts). The schema refuses
60
+ * a gate or skill scripts on an agent a map runs (an item cannot pause the
61
+ * walk). A script runs with ADR 0086's minimal environment, as anywhere.
61
62
  *
62
63
  * ── Not in this version ───────────────────────────────────────────────────
63
- * Skill scripts (`skills.scripts: local`, an approval pause) and remote
64
- * `a2a_agent_url` subagents are refused inside a workflow by the schema; a
65
- * remote agent is reachable only as a tool. Both are open for a later
66
- * record.
64
+ * Remote `a2a_agent_url` subagents are refused inside a workflow by the
65
+ * schema; a remote agent is reachable only as a tool. It is open for a
66
+ * later record.
67
67
  */
68
- import type { BaseNode, LlmAgent, Workflow } from '@google/adk';
69
- import type { CompileOptions, WorkflowSpec } from './compile.ts';
70
- import type { SyndicateYamlConfig } from './loadSyndicate.ts';
71
68
  export * from './workflowConfig.ts';
72
- export interface CompiledWorkflow {
73
- workflow: Workflow;
74
- /** Every agent node by YAML name, compiled. */
75
- agents: Map<string, LlmAgent>;
76
- /** Every node by YAML name, hidden route steps excluded. */
77
- nodes: Map<string, BaseNode>;
78
- }
79
- /**
80
- * Compile a workflow syndicate: every agent through `compileSubagentSpec` (its
81
- * tools, skills and MCP server as in any mode), the declared nodes, the
82
- * hidden route steps, and the edge chains, into one ADK `Workflow` named
83
- * after the syndicate. Throws on a name the schema let through, a tool that
84
- * is not registered, or a graph ADK rejects (unreachable node, cycle).
85
- */
86
- export declare function compileWorkflow(config: SyndicateYamlConfig, opts?: CompileOptions, transformAgent?: (agent: LlmAgent) => LlmAgent): Promise<CompiledWorkflow>;
87
- /**
88
- * ADK's Workflow from a compiled workflow spec, synchronously: each agent
89
- * built by compileAdk with its node modifiers (retry, timeout) at
90
- * construction, then the declared nodes, route steps and edges. A nested
91
- * workflow (ADR 0098) is this Workflow under its subagent entry's name and
92
- * description, which lib/compileAdk.ts wraps in ADK's AgentTool.
93
- */
94
- export declare function assembleWorkflow(spec: WorkflowSpec, opts?: CompileOptions, transformAgent?: (agent: LlmAgent) => LlmAgent): CompiledWorkflow;
@@ -18,185 +18,51 @@
18
18
  * Confirm: { ask_user: "Publish? yes, or say what to change." }
19
19
  * Planner: { route_key: "kind", retry: { max_attempts: 2 } }
20
20
  *
21
- * ADK 2.2 runs it (`Workflow`, `FunctionNode`, `JoinNode`, `ParallelWorker`,
22
- * `ToolNode`, `RequestInput`): per-node retries and timeouts, fan-out and
23
- * fan-in, a pause that waits for a person and resumes on the next message,
24
- * and resumption from the session's own events. Every agent is already a
25
- * node (`LlmAgent extends BaseNode`): a node agent receives the previous
26
- * node's output as its user turn and, unless its YAML sets
27
- * `includeContents`, sees nothing else of the conversation.
21
+ * The engine's scheduler walks it (lib/workflow/, ADR 0095): per-node
22
+ * retries and timeouts, fan-out and fan-in, a pause that waits for a person
23
+ * and resumes on the next message, and resumption from the session's own
24
+ * events, which are the JSON ADK's Workflow stored before 1.0.0. A node
25
+ * agent receives the previous node's output as its user turn and, unless
26
+ * its YAML sets `includeContents`, sees nothing else of the conversation.
28
27
  *
29
- * ── What the engine adds to ADK ───────────────────────────────────────────
30
- * ROUTING. ADK's TypeScript port never derives a route from an agent's
31
- * output, so a routing map in YAML gets a hidden step after the agent
28
+ * ROUTING. A routing map in YAML gets a hidden step after the agent
32
29
  * (`<Agent>__route`) that reads the route from the output — the
33
30
  * `route_key` property of a JSON output, else the trimmed text — and
34
31
  * re-emits the output with it. A `default` key catches what no key
35
32
  * matched.
36
- * THE PAUSE. `ask_user` is a node that raises ADK's `RequestInput`. The
37
- * turn ends `input-required` carrying the question (`result.input`); the
38
- * next message on the conversation is the answer and becomes that node's
39
- * output. The A2A server publishes the question; the chat prints it.
33
+ * THE PAUSE. `ask_user` is a node that asks the person (`adk_request_input`).
34
+ * The turn ends `input-required` carrying the question (`result.input`);
35
+ * the next message on the conversation is the answer and becomes that
36
+ * node's output. The A2A server publishes the question; the chat prints it.
40
37
  * NAMES. Nodes are addressed by their YAML names everywhere (edges, events,
41
- * the wiki), including a `map` node, which ADK would otherwise name after
42
- * the agent it wraps.
38
+ * the wiki), including a `map` node.
43
39
  *
44
40
  * ── As a subagent (ADR 0098) ─────────────────────────────────────────────
45
- * A delegated `yaml_reference` to a workflow syndicate is the whole graph:
46
- * `assembleWorkflow` builds its Workflow under the subagent entry's name
47
- * and description, and lib/compileAdk.ts wraps it in ADK's AgentTool, whose
48
- * answer is the graph's last event's text. A nested workflow with an
41
+ * A delegated `yaml_reference` to a workflow syndicate is the whole graph,
42
+ * walked under the subagent entry's name and description on a child
43
+ * session (lib/compileNative.ts workflowSubagentOf); its answer is the
44
+ * graph's last event's text. A nested workflow with an
49
45
  * `ask_user` node is refused by name (lib/compile.ts compileWorkflowSpec): a
50
- * pause inside a tool call cannot reach the caller (ADR 0028). As a dispatch
51
- * route or a workflow node, a workflow syndicate is still its orchestrator
52
- * alone.
46
+ * pause inside a tool call cannot reach the caller (ADR 0028).
53
47
  *
54
- * ── Approval gates (ADR 0098) ────────────────────────────────────────────
55
- * A tool in a node agent's `require_approval` pauses the node on ADK's
56
- * `adk_request_confirmation`, and the walk with it. Only the native walk
57
- * resumes it (lib/workflow/agentNode.ts): ADK's runLlmAgentAsNode reruns the
58
- * node from its input and never runs the pinned call, so runSyndicateTurn
59
- * refuses a gated workflow on ADK. The schema refuses a gate on an agent a
60
- * map runs (an item cannot pause the walk).
48
+ * ── As a dispatch route or a workflow node (ADR 0106) ────────────────────
49
+ * A `yaml_reference` to a workflow syndicate runs its whole graph there too,
50
+ * on the child session filed under the entry's name, as a subagent does. A
51
+ * route's answer is what the graph would answer as its own syndicate
52
+ * (lib/runtime/syndicateTurn.ts); a node's is the nested walk's
53
+ * (lib/workflow/turn.ts). A map over one is refused (lib/compile.ts).
54
+ *
55
+ * ── Approval gates (ADR 0098, ADR 0106) ──────────────────────────────────
56
+ * A tool in a node agent's `require_approval`, and a skill script
57
+ * (`skills.scripts: local`, run_skill_script), pause the node on
58
+ * `adk_request_confirmation`, and the walk with it; the answer resumes the
59
+ * pinned call (lib/workflow/agentNode.ts). The schema refuses
60
+ * a gate or skill scripts on an agent a map runs (an item cannot pause the
61
+ * walk). A script runs with ADR 0086's minimal environment, as anywhere.
61
62
  *
62
63
  * ── Not in this version ───────────────────────────────────────────────────
63
- * Skill scripts (`skills.scripts: local`, an approval pause) and remote
64
- * `a2a_agent_url` subagents are refused inside a workflow by the schema; a
65
- * remote agent is reachable only as a tool. Both are open for a later
66
- * record.
64
+ * Remote `a2a_agent_url` subagents are refused inside a workflow by the
65
+ * schema; a remote agent is reachable only as a tool. It is open for a
66
+ * later record.
67
67
  */
68
- import { requireAdk } from './adkPeer.js';
69
- import { compileWorkflowSpec } from './compile.js';
70
- import { compileAdk } from './compileAdk.js';
71
- import { DEFAULT_ROUTE_KEY, ROUTE_STEP_SUFFIX, START_NAME, isWorkflowSyndicate, nodeKind, nodeSettings, routeOf } from './workflowConfig.js';
72
68
  export * from './workflowConfig.js';
73
- /**
74
- * Compile a workflow syndicate: every agent through `compileSubagentSpec` (its
75
- * tools, skills and MCP server as in any mode), the declared nodes, the
76
- * hidden route steps, and the edge chains, into one ADK `Workflow` named
77
- * after the syndicate. Throws on a name the schema let through, a tool that
78
- * is not registered, or a graph ADK rejects (unreachable node, cycle).
79
- */
80
- export async function compileWorkflow(config, opts = {}, transformAgent = (a) => a) {
81
- if (!isWorkflowSyndicate(config))
82
- throw new Error(`${config.syndicate_name}: no workflow block`);
83
- return assembleWorkflow(await compileWorkflowSpec(config, opts), opts, transformAgent);
84
- }
85
- /**
86
- * ADK's Workflow from a compiled workflow spec, synchronously: each agent
87
- * built by compileAdk with its node modifiers (retry, timeout) at
88
- * construction, then the declared nodes, route steps and edges. A nested
89
- * workflow (ADR 0098) is this Workflow under its subagent entry's name and
90
- * description, which lib/compileAdk.ts wraps in ADK's AgentTool.
91
- */
92
- export function assembleWorkflow(spec, opts = {}, transformAgent = (a) => a) {
93
- const config = spec.config;
94
- if (!isWorkflowSyndicate(config))
95
- throw new Error(`${config.syndicate_name}: no workflow block`);
96
- // ADK's Workflow is the adk runtime's; the native walk (lib/workflow/turn.ts) needs none of this (ADR 0102).
97
- const { DEFAULT_ROUTE, FunctionNode, JoinNode, ParallelWorker, RequestInput, ToolNode, Workflow, createEvent } = requireAdk("ADK's Workflow (a workflow syndicate on the adk runtime, compileWorkflow)");
98
- const wf = config.workflow;
99
- const nodeYaml = wf.nodes ?? {};
100
- // Agents, with their node modifiers (retry, timeout) at construction; not on a nested syndicate's orchestrator.
101
- const agents = new Map();
102
- for (const { yaml, spec: agentSpec } of spec.agents) {
103
- const settings = yaml.yaml_reference ? {} : nodeSettings(nodeYaml[yaml.name]);
104
- agents.set(yaml.name, transformAgent(compileAdk(agentSpec, opts, settings)));
105
- }
106
- // Declared nodes.
107
- const nodes = new Map(agents);
108
- for (const [name, entry] of Object.entries(nodeYaml)) {
109
- const kind = nodeKind(entry);
110
- if (!kind)
111
- continue; // modifiers on an agent
112
- const settings = nodeSettings(entry);
113
- if (kind === 'ask_user') {
114
- const message = entry.ask_user ?? '';
115
- const schema = entry.schema;
116
- // The node runs again on resume (rerunOnResume): ADK then hands it the
117
- // same input and the answers resolved so far, so its output can carry
118
- // BOTH the reply and what the person was asked about. A node fast-
119
- // forwarded by ADK would output the bare reply, and the next agent
120
- // would never see the draft it is meant to act on.
121
- nodes.set(name, new FunctionNode(name, (ctx, input) => {
122
- const replies = Object.values(ctx.resumeInputs);
123
- if (replies.length > 0)
124
- return { reply: replies[replies.length - 1], input };
125
- return new RequestInput({ message, payload: input, ...(schema ? { responseSchema: schema } : {}) });
126
- }, { ...settings, rerunOnResume: true }));
127
- }
128
- else if (kind === 'join') {
129
- nodes.set(name, new JoinNode({ name, ...settings }));
130
- }
131
- else if (kind === 'map') {
132
- const inner = agents.get(entry.map);
133
- if (!inner)
134
- throw new Error(`workflow node '${name}': map names '${entry.map}', which is not an agent of this syndicate`);
135
- const worker = new ParallelWorker(inner, entry.max_parallel !== undefined ? { maxParallelWorkers: entry.max_parallel } : {});
136
- // ADK names a worker after the agent it wraps; the YAML name is what
137
- // the edges, the events and the docs use.
138
- Object.defineProperty(worker, 'name', { value: name, enumerable: true });
139
- nodes.set(name, worker);
140
- }
141
- else if (kind === 'tool') {
142
- const tool = spec.resolveTool(entry.tool);
143
- if (!tool)
144
- throw new Error(`workflow node '${name}': tool '${entry.tool}' is not registered`);
145
- nodes.set(name, new ToolNode(tool, { name, ...settings }));
146
- }
147
- }
148
- const nodeOf = (name) => {
149
- const node = nodes.get(name);
150
- if (!node)
151
- throw new Error(`workflow: '${name}' is not an agent or a declared node of this syndicate`);
152
- return node;
153
- };
154
- const routeSteps = new Map();
155
- const routeStepAfter = (name) => {
156
- let step = routeSteps.get(name);
157
- if (step)
158
- return step;
159
- const routeKey = nodeYaml[name]?.route_key ?? 'route';
160
- const stepName = `${name}${ROUTE_STEP_SUFFIX}`;
161
- step = new FunctionNode(stepName, (ctx, input) => createEvent({
162
- author: stepName,
163
- invocationId: ctx.invocationId,
164
- branch: ctx.branch,
165
- output: input,
166
- route: routeOf(input, routeKey),
167
- }));
168
- routeSteps.set(name, step);
169
- return step;
170
- };
171
- const edges = wf.edges.map((chain) => {
172
- const out = [];
173
- chain.forEach((element, i) => {
174
- if (typeof element === 'string') {
175
- out.push(element === START_NAME ? 'START' : nodeOf(element));
176
- }
177
- else if (Array.isArray(element)) {
178
- out.push(element.map(nodeOf));
179
- }
180
- else {
181
- const previous = chain[i - 1];
182
- if (typeof previous !== 'string' || previous === START_NAME) {
183
- throw new Error(`workflow: a routing map must follow the name of the node whose output it routes`);
184
- }
185
- out.push(routeStepAfter(previous));
186
- const map = {};
187
- for (const [key, target] of Object.entries(element)) {
188
- map[key === DEFAULT_ROUTE_KEY ? DEFAULT_ROUTE : key] = Array.isArray(target) ? target.map(nodeOf) : nodeOf(target);
189
- }
190
- out.push(map);
191
- }
192
- });
193
- return out;
194
- });
195
- const workflow = new Workflow({
196
- name: spec.name,
197
- ...(spec.description ? { description: spec.description } : {}),
198
- edges,
199
- ...(wf.max_concurrency !== undefined ? { maxConcurrency: wf.max_concurrency } : {}),
200
- });
201
- return { workflow, agents, nodes };
202
- }
@@ -4,7 +4,6 @@
4
4
  * the compiler (lib/workflow.ts) and the turn runner share. No imports
5
5
  * beyond types, so the schema can read it without pulling the compiler in.
6
6
  */
7
- import type { RetryConfig as AdkRetryConfig } from '@google/adk';
8
7
  /** `START` in an edge chain: the graph's entry. Not a node. */
9
8
  export declare const START_NAME = "START";
10
9
  /** The routing-map key that catches an unmatched route. */
@@ -63,18 +62,11 @@ export declare const NODE_KINDS: readonly ['ask_user', 'join', 'map', 'tool'];
63
62
  export declare function nodeKind(node: WorkflowNodeYaml | undefined): (typeof NODE_KINDS)[number] | undefined;
64
63
  /** Every name an edge element references (`START` excluded). */
65
64
  export declare function elementNames(element: EdgeElement): string[];
66
- /** ADK's retry config from the YAML spelling. */
67
- export declare function toRetryConfig(retry: RetryYaml | undefined): AdkRetryConfig | undefined;
68
- /** The BaseNode fields a node entry's modifiers map to. */
69
- export declare function nodeSettings(node: WorkflowNodeYaml | undefined): {
70
- retryConfig?: AdkRetryConfig;
71
- timeout?: number;
72
- };
73
65
  /**
74
66
  * The route an output names: the `routeKey` property of an object (a parsed
75
67
  * JSON output), else the trimmed text. Never undefined, so an edge with a
76
- * `default` key always has something to fall back from. One function for
77
- * both runtimes; it lives in lib/workflow/route.ts.
68
+ * `default` key always has something to fall back from. It lives in
69
+ * lib/workflow/route.ts.
78
70
  */
79
71
  export { routeOf } from './workflow/route.ts';
80
72
  /** A pause raised by an `ask_user` node, read from the run's events (`adk_request_input`). */
@@ -29,40 +29,11 @@ export function elementNames(element) {
29
29
  return element;
30
30
  return Object.values(element).flatMap((v) => (Array.isArray(v) ? v : [v]));
31
31
  }
32
- /** ADK's retry config from the YAML spelling. */
33
- export function toRetryConfig(retry) {
34
- if (!retry)
35
- return undefined;
36
- const out = {};
37
- if (retry.max_attempts !== undefined)
38
- out.maxAttempts = retry.max_attempts;
39
- if (retry.initial_delay !== undefined)
40
- out.initialDelay = retry.initial_delay;
41
- if (retry.max_delay !== undefined)
42
- out.maxDelay = retry.max_delay;
43
- if (retry.backoff_factor !== undefined)
44
- out.backoffFactor = retry.backoff_factor;
45
- if (retry.jitter !== undefined)
46
- out.jitter = retry.jitter;
47
- if (retry.exceptions !== undefined)
48
- out.exceptions = [...retry.exceptions];
49
- return out;
50
- }
51
- /** The BaseNode fields a node entry's modifiers map to. */
52
- export function nodeSettings(node) {
53
- const out = {};
54
- const retry = toRetryConfig(node?.retry);
55
- if (retry)
56
- out.retryConfig = retry;
57
- if (node?.timeout !== undefined)
58
- out.timeout = node.timeout;
59
- return out;
60
- }
61
32
  /**
62
33
  * The route an output names: the `routeKey` property of an object (a parsed
63
34
  * JSON output), else the trimmed text. Never undefined, so an edge with a
64
- * `default` key always has something to fall back from. One function for
65
- * both runtimes; it lives in lib/workflow/route.ts.
35
+ * `default` key always has something to fall back from. It lives in
36
+ * lib/workflow/route.ts.
66
37
  */
67
38
  export { routeOf } from './workflow/route.js';
68
39
  /** ADK's function-call name for a workflow input request. */
@@ -138,8 +138,7 @@ export async function startServer(syndicateName = 'syndicate.yaml', extensions =
138
138
  // the root span carries the full user message and answer.
139
139
  if (process.env.OTEL_CONSOLE_SPANS === undefined)
140
140
  process.env.OTEL_CONSOLE_SPANS = 'false';
141
- // The engine's level, which ADK's logger follows: ADK's INFO/DEBUG logs
142
- // carry raw event JSON, so keep them quiet.
141
+ // The engine's level: INFO/DEBUG lines carry raw event JSON, so keep them quiet.
143
142
  setLogLevel('warn');
144
143
  const publicUrl = process.env.PUBLIC_URL?.trim() || undefined;
145
144
  const port = envInt('PORT', 4000);