melchizedek-agents 0.19.0 → 0.20.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 (106) hide show
  1. package/CHANGELOG.md +252 -76
  2. package/DOCUMENTATION.md +44 -15
  3. package/QUICKSTART.md +9 -6
  4. package/README.md +6 -9
  5. package/config/agents/syndicateSchema.yaml +3 -0
  6. package/dist/lib/adkPeer.d.ts +63 -0
  7. package/dist/lib/adkPeer.js +240 -0
  8. package/dist/lib/compile.d.ts +40 -2
  9. package/dist/lib/compile.js +80 -12
  10. package/dist/lib/compileAdk.d.ts +7 -4
  11. package/dist/lib/compileAdk.js +22 -12
  12. package/dist/lib/compileNative.d.ts +28 -2
  13. package/dist/lib/compileNative.js +60 -4
  14. package/dist/lib/doctor.d.ts +28 -1
  15. package/dist/lib/doctor.js +63 -2
  16. package/dist/lib/index.d.ts +4 -0
  17. package/dist/lib/index.js +5 -0
  18. package/dist/lib/models/adapterResolver.d.ts +13 -11
  19. package/dist/lib/models/adapterResolver.js +11 -10
  20. package/dist/lib/models/adkGeminiAdapter.js +2 -0
  21. package/dist/lib/models/adkShim.d.ts +1 -1
  22. package/dist/lib/models/adkShim.js +1 -1
  23. package/dist/lib/models/capabilities.js +13 -10
  24. package/dist/lib/models/claudeLlm.js +2 -2
  25. package/dist/lib/models/fallback.d.ts +1 -1
  26. package/dist/lib/models/fallback.js +1 -1
  27. package/dist/lib/models/gatewayLlm.js +2 -2
  28. package/dist/lib/models/geminiAdapter.d.ts +6 -4
  29. package/dist/lib/models/geminiAdapter.js +28 -5
  30. package/dist/lib/models/geminiState.d.ts +21 -0
  31. package/dist/lib/models/geminiState.js +26 -0
  32. package/dist/lib/models/genaiMapping.d.ts +24 -4
  33. package/dist/lib/models/genaiMapping.js +109 -6
  34. package/dist/lib/models/gptLlm.js +2 -2
  35. package/dist/lib/models/grokLlm.js +2 -2
  36. package/dist/lib/models/kimiLlm.js +2 -2
  37. package/dist/lib/models/ollamaLlm.js +2 -2
  38. package/dist/lib/models/registry.d.ts +5 -1
  39. package/dist/lib/models/registry.js +17 -12
  40. package/dist/lib/models/tracedGemini.d.ts +1 -1
  41. package/dist/lib/models/tracedGemini.js +1 -1
  42. package/dist/lib/runtime/adkSessionBridge.d.ts +1 -1
  43. package/dist/lib/runtime/adkSessionBridge.js +1 -1
  44. package/dist/lib/runtime/approvals.d.ts +5 -0
  45. package/dist/lib/runtime/approvals.js +39 -8
  46. package/dist/lib/runtime/credentials.d.ts +3 -1
  47. package/dist/lib/runtime/credentials.js +6 -1
  48. package/dist/lib/runtime/native/agentLoop.d.ts +7 -1
  49. package/dist/lib/runtime/native/agentLoop.js +31 -13
  50. package/dist/lib/runtime/native/delegate.d.ts +53 -0
  51. package/dist/lib/runtime/native/delegate.js +91 -8
  52. package/dist/lib/runtime/native/interrupts.d.ts +6 -3
  53. package/dist/lib/runtime/native/interrupts.js +23 -4
  54. package/dist/lib/runtime/native/request.d.ts +1 -1
  55. package/dist/lib/runtime/native/request.js +1 -1
  56. package/dist/lib/runtime/native/selfCorrection.d.ts +64 -6
  57. package/dist/lib/runtime/native/selfCorrection.js +82 -8
  58. package/dist/lib/runtime/native/step.d.ts +14 -6
  59. package/dist/lib/runtime/native/step.js +34 -10
  60. package/dist/lib/runtime/runtimeFlag.d.ts +13 -5
  61. package/dist/lib/runtime/runtimeFlag.js +14 -6
  62. package/dist/lib/runtime/syndicateTurn.d.ts +15 -10
  63. package/dist/lib/runtime/syndicateTurn.js +59 -32
  64. package/dist/lib/runtime/valueDepth.d.ts +23 -0
  65. package/dist/lib/runtime/valueDepth.js +41 -0
  66. package/dist/lib/session/supabaseSessionService.d.ts +1 -1
  67. package/dist/lib/session/supabaseSessionService.js +1 -1
  68. package/dist/lib/session/transcript.d.ts +1 -1
  69. package/dist/lib/session/transcript.js +5 -3
  70. package/dist/lib/storage/postgres/sessionService.d.ts +1 -1
  71. package/dist/lib/storage/postgres/sessionService.js +1 -1
  72. package/dist/lib/syndicateSchema.d.ts +2 -0
  73. package/dist/lib/syndicateSchema.js +27 -6
  74. package/dist/lib/toolRegistry.d.ts +12 -1
  75. package/dist/lib/toolRegistry.js +42 -2
  76. package/dist/lib/tools/adkTool.d.ts +1 -1
  77. package/dist/lib/tools/adkTool.js +1 -1
  78. package/dist/lib/tools/collectionsSearchTool.d.ts +1 -1
  79. package/dist/lib/tools/collectionsSearchTool.js +1 -1
  80. package/dist/lib/tools/generateImageTool.d.ts +1 -1
  81. package/dist/lib/tools/inspectImageTool.d.ts +1 -1
  82. package/dist/lib/tools/urlContextTool.d.ts +1 -1
  83. package/dist/lib/tools/urlContextTool.js +1 -1
  84. package/dist/lib/tools/webExtractTool.d.ts +1 -1
  85. package/dist/lib/tools/webSearchTool.d.ts +1 -1
  86. package/dist/lib/tools/webSearchTool.js +1 -1
  87. package/dist/lib/tools/xApiSearchTool.d.ts +1 -1
  88. package/dist/lib/tools/xSearchTool.d.ts +1 -1
  89. package/dist/lib/tools/xSearchTool.js +1 -1
  90. package/dist/lib/wiki/agentRun.d.ts +1 -1
  91. package/dist/lib/wiki/agentRun.js +2 -1
  92. package/dist/lib/workflow/agentNode.d.ts +21 -4
  93. package/dist/lib/workflow/agentNode.js +96 -5
  94. package/dist/lib/workflow/graph.d.ts +5 -4
  95. package/dist/lib/workflow/graph.js +14 -4
  96. package/dist/lib/workflow/resume.d.ts +10 -9
  97. package/dist/lib/workflow/resume.js +13 -12
  98. package/dist/lib/workflow/scheduler.d.ts +10 -7
  99. package/dist/lib/workflow/scheduler.js +15 -2
  100. package/dist/lib/workflow.d.ts +33 -11
  101. package/dist/lib/workflow.js +49 -27
  102. package/dist/lib/workflowConfig.d.ts +4 -0
  103. package/dist/lib/workflowConfig.js +4 -0
  104. package/dist/scripts/doctor.d.ts +3 -1
  105. package/dist/scripts/doctor.js +4 -2
  106. package/package.json +6 -3
@@ -16,7 +16,8 @@
16
16
  * runs by shape during the dual period (ADR 0071). A delegated subagent
17
17
  * becomes a subagentTool holding its own NativeAgent, which the loop runs as
18
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
19
+ * syndicate as its orchestrator's agent, a nested workflow syndicate as a
20
+ * workflowSubagentTool whose call walks the whole graph (ADR 0098); a remote A2A subagent is the own
20
21
  * Tool the ADK runtime's FunctionTool wraps (lib/a2a/remoteAgent.ts).
21
22
  *
22
23
  * EVERY AGENT KEY COMPILES for the native loop: `context:` is handed to
@@ -41,10 +42,13 @@
41
42
  import { remoteAgentOwnTool } from './a2a/remoteAgent.js';
42
43
  import { compileSpec, compileSubagentSpec } from './compile.js';
43
44
  import { providerForModel, resolveAdapter } from './models/registry.js';
44
- import { subagentTool } from './runtime/native/delegate.js';
45
+ import { subagentTool, workflowSubagentTool } from './runtime/native/delegate.js';
46
+ import { servedThroughShim } from './runtime/native/selfCorrection.js';
45
47
  import { unsupportedOnNative } from './runtime/runtimeFlag.js';
46
48
  export { UnsupportedOnRuntimeError, unsupportedOnNative } from './runtime/runtimeFlag.js';
47
49
  import { instructionToolOf, toolOf, toolsetOf } from './tools/tool.js';
50
+ import { buildWorkflowGraph } from './workflow/graph.js';
51
+ import { refuseUnrunnableNodes, runNativeWorkflow } from './workflow/turn.js';
48
52
  /** A resolved tool as the loop holds it: the own Tool, InstructionTool or Toolset behind it, else the object itself. */
49
53
  function nativeTool(tool) {
50
54
  return toolOf(tool) ?? instructionToolOf(tool) ?? toolsetOf(tool) ?? tool;
@@ -85,6 +89,8 @@ export function compileNative(spec) {
85
89
  for (const entry of spec.tools) {
86
90
  if (entry.kind === 'agent')
87
91
  tools.push(subagentTool(compileNative(entry.agent)));
92
+ else if (entry.kind === 'workflow')
93
+ tools.push(workflowSubagentTool(workflowSubagentOf(compileNativeWorkflow(entry.workflow))));
88
94
  else if (entry.kind === 'remote')
89
95
  tools.push(remoteAgentOwnTool({ name: entry.name, description: entry.description, url: entry.url }));
90
96
  else
@@ -145,6 +151,50 @@ export function wireModelOf(spec) {
145
151
  export async function compileNativeGraph(config, opts = {}) {
146
152
  return compileNative(await compileSpec(config, opts));
147
153
  }
154
+ /**
155
+ * A workflow spec for the native walk: the graph, every agent compiled for
156
+ * native from the same specs ADK's assembleWorkflow builds its agents from,
157
+ * and the registry's lookup for tool nodes. A tool node ADK's compile
158
+ * refuses (an unregistered or long-running tool) is refused here, before
159
+ * any model call, with ADK's message.
160
+ */
161
+ export function compileNativeWorkflow(spec) {
162
+ const graph = buildWorkflowGraph(spec.config);
163
+ const agents = new Map();
164
+ for (const { yaml, spec: agentSpec } of spec.agents)
165
+ agents.set(yaml.name, compileNative(agentSpec));
166
+ refuseUnrunnableNodes(graph, spec.resolveTool);
167
+ return { name: spec.name, description: spec.description, graph, agents, resolveTool: spec.resolveTool };
168
+ }
169
+ /**
170
+ * A nested workflow as the delegated subagent the native loop calls (ADR
171
+ * 0098): one call walks the whole graph with runNativeWorkflow on the child
172
+ * session lib/runtime/native/delegate.ts opened, as ADK's AgentTool runs a
173
+ * Workflow on its own Runner.
174
+ */
175
+ export function workflowSubagentOf(workflow) {
176
+ return {
177
+ name: workflow.name,
178
+ ...(workflow.description ? { description: workflow.description } : {}),
179
+ walk: (run) => runNativeWorkflow({
180
+ graph: workflow.graph,
181
+ agents: workflow.agents,
182
+ resolveTool: workflow.resolveTool,
183
+ sessions: run.sessions,
184
+ appName: run.appName,
185
+ userId: run.userId,
186
+ sessionId: run.sessionId,
187
+ userParts: run.userParts,
188
+ adapterFor: run.adapterFor,
189
+ selfCorrection: run.selfCorrection,
190
+ stream: false,
191
+ ...(run.signal ? { signal: run.signal } : {}),
192
+ ...(run.memory ? { memory: run.memory } : {}),
193
+ ...(run.log ? { log: run.log } : {}),
194
+ ...(run.credentials ? { credentials: run.credentials } : {}),
195
+ }),
196
+ };
197
+ }
148
198
  /** One subagent entry (a dispatch route) for the native loop: compileSubagentSpec, then compileNative. */
149
199
  export async function compileNativeSubagent(subCfg, opts = {}) {
150
200
  return compileNative(await compileSubagentSpec(subCfg, opts));
@@ -167,8 +217,9 @@ function adapterOf(resolved, model) {
167
217
  if (!resolved || typeof resolved !== 'object')
168
218
  return resolveAdapter(model);
169
219
  const held = resolved;
220
+ // On ADK a shim declares the toolsDict, the reflection tool included, whatever its adapter (ADR 0097).
170
221
  if (isModelAdapter(held.adapter))
171
- return held.adapter;
222
+ return servedThroughShim(held.adapter);
172
223
  // On Vertex AI the client authenticates with the platform's credentials, never a key (ADR 0023).
173
224
  if (typeof held.apiKey === 'string' && held.apiKey && held.vertexai !== true) {
174
225
  return resolveAdapter(model, { apiKey: held.apiKey, keyProvider: providerForModel(model) });
@@ -203,9 +254,14 @@ export function nativeAdapterFor(opts = {}, spec) {
203
254
  refuseModelClass(resolved, id, s.name ?? 'the native runtime');
204
255
  known.set(id, resolved);
205
256
  }
206
- for (const entry of s.tools ?? [])
257
+ for (const entry of s.tools ?? []) {
207
258
  if (entry.kind === 'agent')
208
259
  learn(entry.agent);
260
+ // A nested workflow's agents run under the caller's lookup (ADR 0098).
261
+ else if (entry.kind === 'workflow')
262
+ for (const node of entry.workflow.agents)
263
+ learn(node.spec);
264
+ }
209
265
  };
210
266
  // A workflow's agents share one lookup: every node's spec is learned.
211
267
  for (const s of spec === undefined ? [] : Array.isArray(spec) ? spec : [spec])
@@ -18,11 +18,15 @@
18
18
  * The routing and capability judgments are not re-implemented here: they
19
19
  * come from lib/models/gateway.ts and lib/models/capabilities.ts, the same
20
20
  * modules the registry and the A2A server use, so the report cannot
21
- * disagree with what a run would do.
21
+ * disagree with what a run would do. The runtime line comes from
22
+ * lib/runtime/runtimeFlag.ts, which a turn reads (ADR 0102); whether
23
+ * @google/adk is installed is a module resolution, so the doctor never
24
+ * loads ADK to answer it.
22
25
  */
23
26
  import type { Platform } from './models/endpoints.ts';
24
27
  import type { CapabilityGap, CapabilityReport } from './models/capabilities.ts';
25
28
  import type { ProviderId } from './models/providerMap.ts';
29
+ import type { RuntimeName, RuntimeSource } from './runtime/runtimeFlag.ts';
26
30
  /**
27
31
  * What a file costs to run: `keyless` (all Ollama), a single provider's id
28
32
  * when every agent shares one (`gemini`, `anthropic`, `openai`, `xai` — one
@@ -81,8 +85,25 @@ export interface Unlock {
81
85
  /** Syndicates this one variable would move from blocked to ready. */
82
86
  syndicates: string[];
83
87
  }
88
+ /** The runtime a turn would run on here, where that came from, and the optional ADK peer (ADR 0102). */
89
+ export interface DoctorRuntime {
90
+ /** The runtime in use; undefined when MELCHIZEDEK_RUNTIME holds a value no turn accepts (`problem` says so). */
91
+ runtime?: RuntimeName;
92
+ /** Where it came from: MELCHIZEDEK_RUNTIME, or the default (a turn's own option is the caller's, not the environment's). */
93
+ source?: RuntimeSource;
94
+ /** @google/adk: whether it resolves from here, its version, and whether the runtime in use needs it. */
95
+ adk: {
96
+ installed: boolean;
97
+ version?: string;
98
+ needed: boolean;
99
+ };
100
+ /** Why no turn would run as configured, if none would. */
101
+ problem?: string;
102
+ }
84
103
  export interface DoctorResult {
85
104
  agentsDir: string;
105
+ /** The runtime in use and whether @google/adk is installed. */
106
+ runtime: DoctorRuntime;
86
107
  syndicates: DoctorSyndicate[];
87
108
  unlocks: Unlock[];
88
109
  gateway: {
@@ -110,6 +131,12 @@ export interface DoctorEndpoint {
110
131
  /** Cloud platforms are tested against mocks only (ADR 0023). */
111
132
  liveVerified: boolean;
112
133
  }
134
+ /**
135
+ * The runtime a turn would run on under this environment (lib/runtime/
136
+ * runtimeFlag.ts), where that came from, and whether @google/adk resolves.
137
+ * `adk` without the package is a problem: every turn would fail.
138
+ */
139
+ export declare function runtimeReport(env?: NodeJS.ProcessEnv, adkResolvable?: (module: string) => boolean): DoctorRuntime;
113
140
  /** One row per provider that is not on its vendor's public API with an env key. */
114
141
  export declare function endpointRows(): DoctorEndpoint[];
115
142
  export declare const CONSOLE_URLS: Record<ProviderId, string>;
@@ -18,7 +18,10 @@
18
18
  * The routing and capability judgments are not re-implemented here: they
19
19
  * come from lib/models/gateway.ts and lib/models/capabilities.ts, the same
20
20
  * modules the registry and the A2A server use, so the report cannot
21
- * disagree with what a run would do.
21
+ * disagree with what a run would do. The runtime line comes from
22
+ * lib/runtime/runtimeFlag.ts, which a turn reads (ADR 0102); whether
23
+ * @google/adk is installed is a module resolution, so the doctor never
24
+ * loads ADK to answer it.
22
25
  */
23
26
  import fs from 'node:fs';
24
27
  import path from 'node:path';
@@ -30,6 +33,7 @@ import { CAPABILITY_LABELS, capabilityGaps, describeCapabilities } from './model
30
33
  import { credentialSource, endpointFromEnv, endpointLabel, endpointProblems, PLATFORM_SDK, PLATFORMS_FOR } from './models/endpoints.js';
31
34
  import { GATEWAY_ENV, GATEWAY_KEY_ENV, GATEWAYS, gatewayConfig, gatewayProblem, gatewayUsable, } from './models/gateway.js';
32
35
  import { PROVIDERS } from './models/providerMap.js';
36
+ import { describeRuntime } from './runtime/runtimeFlag.js';
33
37
  function resolvable(module) {
34
38
  try {
35
39
  createRequire(import.meta.url).resolve(module);
@@ -39,6 +43,52 @@ function resolvable(module) {
39
43
  return false;
40
44
  }
41
45
  }
46
+ /** The installed version of a package that resolves from here, read from its package.json (its exports map may hide it). */
47
+ function installedVersion(module) {
48
+ try {
49
+ let dir = path.dirname(createRequire(import.meta.url).resolve(module));
50
+ for (let i = 0; i < 8; i++) {
51
+ const file = path.join(dir, 'package.json');
52
+ if (fs.existsSync(file)) {
53
+ const pkg = JSON.parse(fs.readFileSync(file, 'utf8'));
54
+ if (pkg.name === module)
55
+ return pkg.version;
56
+ }
57
+ const up = path.dirname(dir);
58
+ if (up === dir)
59
+ break;
60
+ dir = up;
61
+ }
62
+ }
63
+ catch {
64
+ // Not resolvable, or unreadable: no version to report.
65
+ }
66
+ return undefined;
67
+ }
68
+ /** The ADK peer, as an install command names it. */
69
+ const ADK_PEER = '@google/adk';
70
+ /**
71
+ * The runtime a turn would run on under this environment (lib/runtime/
72
+ * runtimeFlag.ts), where that came from, and whether @google/adk resolves.
73
+ * `adk` without the package is a problem: every turn would fail.
74
+ */
75
+ export function runtimeReport(env = process.env, adkResolvable = resolvable) {
76
+ const installed = adkResolvable(ADK_PEER);
77
+ const adk = { installed, ...(installed && installedVersion(ADK_PEER) ? { version: installedVersion(ADK_PEER) } : {}) };
78
+ let chosen;
79
+ try {
80
+ chosen = describeRuntime(undefined, env);
81
+ }
82
+ catch (err) {
83
+ return { adk: { ...adk, needed: false }, problem: err instanceof Error ? err.message : String(err) };
84
+ }
85
+ const needed = chosen.runtime === 'adk';
86
+ return {
87
+ ...chosen,
88
+ adk: { ...adk, needed },
89
+ ...(needed && !installed ? { problem: `MELCHIZEDEK_RUNTIME=adk needs ${ADK_PEER}, which is not installed: npm install ${ADK_PEER}@~2.2.0, or unset MELCHIZEDEK_RUNTIME to run on native` } : {}),
90
+ };
91
+ }
42
92
  /** One row per provider that is not on its vendor's public API with an env key. */
43
93
  export function endpointRows() {
44
94
  const rows = [];
@@ -381,7 +431,7 @@ export function runDoctor(options = {}) {
381
431
  for (const s of syndicates)
382
432
  counts[s.verdict.state]++;
383
433
  flagMemoryNamespaces(syndicates);
384
- return { agentsDir, syndicates, unlocks, gateway, endpoints: endpointRows(), counts };
434
+ return { agentsDir, runtime: runtimeReport(), syndicates, unlocks, gateway, endpoints: endpointRows(), counts };
385
435
  }
386
436
  // ── Rendering ────────────────────────────────────────────────────────────────
387
437
  const ANSI = {
@@ -417,6 +467,17 @@ export function renderDoctor(result, opts = {}) {
417
467
  : `${c.green}${text}${c.reset}`;
418
468
  lines.push(`${c.bold}melchizedek doctor${c.reset} ${c.dim}· ${result.agentsDir}${c.reset}`);
419
469
  lines.push('');
470
+ // The runtime a turn would run on, where that came from, and the ADK peer (ADR 0102).
471
+ if (result.runtime) {
472
+ const rt = result.runtime;
473
+ const adk = rt.adk.installed
474
+ ? `${ADK_PEER} ${rt.adk.version ?? ''}`.trimEnd() + ' installed'
475
+ : `${ADK_PEER} not installed${rt.adk.needed ? '' : ' (needed only for MELCHIZEDEK_RUNTIME=adk)'}`;
476
+ const source = rt.source === 'default' ? 'the default' : rt.source;
477
+ lines.push(rt.problem
478
+ ? `runtime ${c.red}✗${c.reset} ${rt.runtime ? `${rt.runtime} ${c.dim}(${source})${c.reset} · ` : ''}${c.red}${rt.problem}${c.reset}`
479
+ : `runtime ${c.green}✓${c.reset} ${rt.runtime} ${c.dim}(${source})${c.reset} · ${c.dim}${adk}${c.reset}`);
480
+ }
420
481
  // Provider line: what is funded, and how. Each provider is probed with an
421
482
  // id of its own prefix, so the line names ITS key (a fallthrough once put
422
483
  // xAI's key beside Moonshot).
@@ -14,6 +14,10 @@
14
14
  export { loadSyndicate, loadSyndicateFromRegistry, parseCliBindings, validateRegistryConfig, } from './loadSyndicate.ts';
15
15
  export type { AgentYamlConfig, LoadSyndicateOptions, SubagentYamlConfig, SyndicateYamlConfig, VariableMap, } from './loadSyndicate.ts';
16
16
  export { runSyndicateTurn, ingestTurnMemory } from './runtime/syndicateTurn.ts';
17
+ export { DEFAULT_RUNTIME, describeRuntime, AdkNotInstalledError, adkInstalled } from './runtime/syndicateTurn.ts';
18
+ export type { RuntimeName, RuntimeSource } from './runtime/syndicateTurn.ts';
19
+ export { InProcessSessionService } from './runtime/sessions.ts';
20
+ export { asAdkSessionService, asSessionService } from './runtime/adkSessionBridge.ts';
17
21
  export { approvalResponsePart, pendingApproval, APPROVAL_REQUEST } from './runtime/approvals.ts';
18
22
  export type { PendingApproval } from './runtime/approvals.ts';
19
23
  export type { DrainedRun, MessagePart, TurnUsage, RouteDecision, SyndicateTurnOptions, SyndicateTurnResult, TraceOptions, TurnEvents, TurnStage, } from './runtime/syndicateTurn.ts';
package/dist/lib/index.js CHANGED
@@ -15,6 +15,11 @@
15
15
  export { loadSyndicate, loadSyndicateFromRegistry, parseCliBindings, validateRegistryConfig, } from './loadSyndicate.js';
16
16
  // ── Run it ──────────────────────────────────────────────────────────────────
17
17
  export { runSyndicateTurn, ingestTurnMemory } from './runtime/syndicateTurn.js';
18
+ // The runtime in use (native by default since 0.20.0) and the optional ADK peer (ADR 0102).
19
+ export { DEFAULT_RUNTIME, describeRuntime, AdkNotInstalledError, adkInstalled } from './runtime/syndicateTurn.js';
20
+ // An in-process session store that needs no ADK; runSyndicateTurn takes it through asAdkSessionService.
21
+ export { InProcessSessionService } from './runtime/sessions.js';
22
+ export { asAdkSessionService, asSessionService } from './runtime/adkSessionBridge.js';
18
23
  export { approvalResponsePart, pendingApproval, APPROVAL_REQUEST } from './runtime/approvals.js';
19
24
  export { compileGraph, compileSubagent } from './compile.js';
20
25
  export { compileWorkflow, isWorkflowSyndicate, describeInput } from './workflow.js';
@@ -11,12 +11,13 @@
11
11
  * and the contract adapter table live here; registry.ts imports them for
12
12
  * resolveModel and for its own resolveAdapter.
13
13
  *
14
- * GEMINI (ADR 0068): `adapterResolver(adkGemini)` takes the factory for the
15
- * temporary AdkGeminiAdapter from its caller. registry.ts passes one, so its
16
- * resolveAdapter keeps ADR 0060's default (`adk` until gate G3). The resolver
17
- * exported here has none: a Gemini id gets the engine's GeminiAdapter unless
18
- * `adk` is asked for, by the option or by GEMINI_ADAPTER=adk, which throws
19
- * and names the entry that has it.
14
+ * GEMINI (ADR 0068, ADR 0100): a Gemini id gets the engine's GeminiAdapter
15
+ * unless `adk` is asked for, by the option or by GEMINI_ADAPTER=adk.
16
+ * `adapterResolver(adkGemini)` takes the factory for the temporary
17
+ * AdkGeminiAdapter from its caller: registry.ts passes one, so `adk` works
18
+ * there for one release (with @google/adk installed). The resolver exported
19
+ * here has none, so asking it for `adk` throws and names the entry that has
20
+ * it.
20
21
  */
21
22
  import type { ModelAdapter } from './contract.ts';
22
23
  import type { ProviderEndpoint } from './endpoints.ts';
@@ -75,8 +76,9 @@ export interface ResolveAdapterOptions {
75
76
  endpoint?: Partial<ProviderEndpoint>;
76
77
  /**
77
78
  * Which Gemini adapter a Gemini id gets. Default: GEMINI_ADAPTER, else
78
- * `adk` through `melchizedek-agents/models/registry` and `engine` through
79
- * `melchizedek-agents/model`, which has no `adk`.
79
+ * `engine` (since 0.20.0, ADR 0100). `adk` is available for one release
80
+ * through `melchizedek-agents/models/registry` with @google/adk installed;
81
+ * `melchizedek-agents/model` has no `adk`.
80
82
  */
81
83
  gemini?: GeminiAdapterChoice;
82
84
  }
@@ -89,9 +91,9 @@ export interface AdapterResolver {
89
91
  resolveAdapterWithFallback(modelId: string, fallbackId: string | undefined, options?: ResolveAdapterOptions, fallbackOptions?: FallbackAdapterOptions): ModelAdapter;
90
92
  }
91
93
  /**
92
- * A resolver over the one prefix table. With `adkGemini`, a Gemini id gets
93
- * AdkGeminiAdapter unless `engine` is asked for (ADR 0060). Without it, a
94
- * Gemini id gets GeminiAdapter, and asking for `adk` throws (ADR 0068).
94
+ * A resolver over the one prefix table. A Gemini id gets GeminiAdapter
95
+ * unless `adk` is asked for (ADR 0100). With `adkGemini`, `adk` gets
96
+ * AdkGeminiAdapter (ADR 0060); without it, asking for `adk` throws (ADR 0068).
95
97
  */
96
98
  export declare function adapterResolver(adkGemini?: AdkGeminiFactory): AdapterResolver;
97
99
  /**
@@ -11,12 +11,13 @@
11
11
  * and the contract adapter table live here; registry.ts imports them for
12
12
  * resolveModel and for its own resolveAdapter.
13
13
  *
14
- * GEMINI (ADR 0068): `adapterResolver(adkGemini)` takes the factory for the
15
- * temporary AdkGeminiAdapter from its caller. registry.ts passes one, so its
16
- * resolveAdapter keeps ADR 0060's default (`adk` until gate G3). The resolver
17
- * exported here has none: a Gemini id gets the engine's GeminiAdapter unless
18
- * `adk` is asked for, by the option or by GEMINI_ADAPTER=adk, which throws
19
- * and names the entry that has it.
14
+ * GEMINI (ADR 0068, ADR 0100): a Gemini id gets the engine's GeminiAdapter
15
+ * unless `adk` is asked for, by the option or by GEMINI_ADAPTER=adk.
16
+ * `adapterResolver(adkGemini)` takes the factory for the temporary
17
+ * AdkGeminiAdapter from its caller: registry.ts passes one, so `adk` works
18
+ * there for one release (with @google/adk installed). The resolver exported
19
+ * here has none, so asking it for `adk` throws and names the entry that has
20
+ * it.
20
21
  */
21
22
  import { ClaudeAdapter } from './claudeAdapter.js';
22
23
  import { mergeEndpoint } from './endpoints.js';
@@ -78,9 +79,9 @@ const CONTRACT_ADAPTER = {
78
79
  moonshot: (r) => new KimiAdapter({ model: r.model, apiKey: r.apiKey, baseUrl: r.endpoint?.baseURL }),
79
80
  };
80
81
  /**
81
- * A resolver over the one prefix table. With `adkGemini`, a Gemini id gets
82
- * AdkGeminiAdapter unless `engine` is asked for (ADR 0060). Without it, a
83
- * Gemini id gets GeminiAdapter, and asking for `adk` throws (ADR 0068).
82
+ * A resolver over the one prefix table. A Gemini id gets GeminiAdapter
83
+ * unless `adk` is asked for (ADR 0100). With `adkGemini`, `adk` gets
84
+ * AdkGeminiAdapter (ADR 0060); without it, asking for `adk` throws (ADR 0068).
84
85
  */
85
86
  export function adapterResolver(adkGemini) {
86
87
  const geminiFor = (r, choice) => {
@@ -99,7 +100,7 @@ export function adapterResolver(adkGemini) {
99
100
  if (route.transport === 'gateway')
100
101
  return new GatewayAdapter({ model: modelId });
101
102
  if (route.provider === 'gemini') {
102
- return geminiFor(route, options.gemini ?? geminiAdapterSetting() ?? (adkGemini ? 'adk' : 'engine'));
103
+ return geminiFor(route, options.gemini ?? geminiAdapterSetting() ?? 'engine');
103
104
  }
104
105
  return CONTRACT_ADAPTER[route.provider](route);
105
106
  }
@@ -71,6 +71,7 @@ import { errorText } from './errorResponse.js';
71
71
  import { GEMINI_PROVIDER } from './geminiState.js';
72
72
  import { llmResponseToModelResponse, modelRequestToLlmRequest, nativeToolsWithoutGeminiTool } from './genaiMapping.js';
73
73
  import { TracedGemini } from './tracedGemini.js';
74
+ import { requireAdk } from '../adkPeer.js';
74
75
  import { classifyError, errorStatus } from './retry.js';
75
76
  import { setLlmSpanAttribute } from '../observability/tracer.js';
76
77
  /** The prefix of a call id ADK (or the engine after it) made: such an id never goes on the wire. */
@@ -85,6 +86,7 @@ export class AdkGeminiAdapter {
85
86
  #connection;
86
87
  #warned = new Set();
87
88
  constructor(options) {
89
+ requireAdk('GEMINI_ADAPTER=adk (AdkGeminiAdapter, which runs ADK\'s Gemini)');
88
90
  this.model = options.model;
89
91
  this.#apiKey = nonEmpty(options.apiKey);
90
92
  this.#endpoint = options.endpoint;
@@ -51,7 +51,7 @@
51
51
  * is charged and traced on its own, as today. A FallbackAdapter behind one
52
52
  * shim would make a redirected call one span and one charge.
53
53
  */
54
- import { BaseLlm } from '@google/adk';
54
+ import { BaseLlm } from '../adkPeer.ts';
55
55
  import type { BaseLlmConnection, BaseLlmType, LlmRequest, LlmResponse } from '@google/adk';
56
56
  import type { ModelAdapter, ModelRequest, ModelResponse } from './contract.ts';
57
57
  import type { ModelRequestOptions } from './genaiMapping.ts';
@@ -51,7 +51,7 @@
51
51
  * is charged and traced on its own, as today. A FallbackAdapter behind one
52
52
  * shim would make a redirected call one span and one charge.
53
53
  */
54
- import { BaseLlm } from '@google/adk';
54
+ import { BaseLlm } from '../adkPeer.js';
55
55
  import { llmRequestToModelRequest, modelResponseToLlmResponse } from './genaiMapping.js';
56
56
  import { traceLlmGeneration } from '../observability/tracer.js';
57
57
  import { currentTurnSignal } from '../runtime/turnControl.js';
@@ -108,8 +108,11 @@ export function capabilitySummary(agentName, r) {
108
108
  //
109
109
  // `evidence: 'test'` cells are asserted against the real outgoing request body
110
110
  // in tests/capabilityMatrix.test.ts, so changing an adapter without changing
111
- // its row fails a test. `evidence: 'adk'` cells are ADK's own Gemini adapter,
112
- // which this repo does not build requests for.
111
+ // its row fails a test. Every cell is `test`. The Gemini row is the engine's
112
+ // own GeminiAdapter (lib/models/geminiAdapter.ts), asserted on the real
113
+ // @google/genai client over a stubbed fetch (gate G3, ADR 0100). `'adk'`
114
+ // (a cell taken on trust from ADK's own Gemini) stays in the type because the
115
+ // type is published (`melchizedek-agents/models/*`); no cell uses it.
113
116
  export const CAPABILITIES = [
114
117
  'delegation',
115
118
  'memory_tools',
@@ -132,18 +135,18 @@ const ok = (evidence = 'test', note) => note ? { support: 'supported', note, evi
132
135
  const degraded = (note) => ({ support: 'degraded', note, evidence: 'test' });
133
136
  const unsupported = (note) => ({ support: 'unsupported', note, evidence: 'test' });
134
137
  const nativeSearch = (row) => SERVER_SIDE_TOOLS.web_search.includes(row)
135
- ? ok(row === 'gemini' ? 'adk' : 'test')
138
+ ? ok()
136
139
  : unsupported('no native search on this path; the web_search sentinel is dropped (use web_extract)');
137
140
  const responsesReasoningNote = (ids) => `encrypted reasoning items are replayed verbatim within the turn's tool loop, with store: false (ADR 0050); ${ids}`;
138
141
  const CHAT_THINKING_NOTE = "reasoning: is the lever, sent as reasoning_effort in the model's word, a thinking budget as the level that covers it (ADR 0047); the reasoning is not carried between tool steps, so the model re-reasons each step";
139
142
  export const CAPABILITY_MATRIX = {
140
143
  gemini: {
141
- delegation: ok('adk'),
142
- memory_tools: ok('adk'),
143
- structured_output: ok('adk'),
144
- thinking_with_tools: ok('adk'),
145
- streaming: ok('adk'),
146
- vision: ok('adk'),
144
+ delegation: ok(),
145
+ memory_tools: ok(),
146
+ structured_output: ok(),
147
+ thinking_with_tools: ok(),
148
+ streaming: ok(),
149
+ vision: ok(),
147
150
  native_search: nativeSearch('gemini'),
148
151
  },
149
152
  anthropic: {
@@ -286,7 +289,7 @@ export function renderCapabilityMatrix() {
286
289
  lines.push(`| ${CAPABILITY_LABELS[cap]} | ${cells.join(' | ')} |`);
287
290
  }
288
291
  lines.push('');
289
- lines.push('✓ supported · ◐ degraded · ✗ unsupported. Gemini cells are ADK\'s own adapter; every other cell is asserted against the request the adapter sends.');
292
+ lines.push('✓ supported · ◐ degraded · ✗ unsupported. Every cell is asserted against the request the adapter sends; the Gemini column is the engine\'s own Gemini adapter.');
290
293
  lines.push('');
291
294
  notes.forEach((n, i) => lines.push(`${i + 1}. ${n}`));
292
295
  lines.push('');
@@ -33,7 +33,7 @@
33
33
  * replayed within the tool loop, structured output, images, web search) is
34
34
  * described in its header and in wiki/models/claude-adapter.md.
35
35
  */
36
- import { LLMRegistry } from '@google/adk';
36
+ import { requireAdk } from '../adkPeer.js';
37
37
  import { AdkShim } from './adkShim.js';
38
38
  import { ClaudeAdapter, anthropicTools } from './claudeAdapter.js';
39
39
  import { claudeReasoningFromConfig } from './claudeModels.js';
@@ -83,5 +83,5 @@ export class ClaudeLlm extends AdkShim {
83
83
  * message about which provider is active.
84
84
  */
85
85
  export function registerClaudeLlm() {
86
- LLMRegistry.register(ClaudeLlm);
86
+ requireAdk("Registering a model class with ADK's LLMRegistry").LLMRegistry.register(ClaudeLlm);
87
87
  }
@@ -31,7 +31,7 @@
31
31
  * closes it. Its state is lib/models/circuitBreaker.ts, which the
32
32
  * contract-level wrapper (lib/models/fallbackAdapter.ts) shares.
33
33
  */
34
- import { BaseLlm } from '@google/adk';
34
+ import { BaseLlm } from '../adkPeer.ts';
35
35
  import type { BaseLlmConnection, LlmRequest, LlmResponse } from '@google/adk';
36
36
  export { circuitOpen, resetCircuits } from './circuitBreaker.ts';
37
37
  /** A provider-side failure: worth counting against the provider and worth a fallback. A cancellation never is. */
@@ -31,7 +31,7 @@
31
31
  * closes it. Its state is lib/models/circuitBreaker.ts, which the
32
32
  * contract-level wrapper (lib/models/fallbackAdapter.ts) shares.
33
33
  */
34
- import { BaseLlm } from '@google/adk';
34
+ import { BaseLlm } from '../adkPeer.js';
35
35
  import { errorDecision, errorText, isRetryableErrorResponse } from './errorResponse.js';
36
36
  import { providerForModel } from './providerMap.js';
37
37
  import { circuitOpen, recordFailure, recordSuccess } from './circuitBreaker.js';
@@ -16,7 +16,7 @@
16
16
  * carry the SAME supportedModels instances as the direct adapter it stands
17
17
  * in for (see gatewayClassFor below, and its use in registry.ts).
18
18
  */
19
- import { LLMRegistry } from '@google/adk';
19
+ import { requireAdk } from '../adkPeer.js';
20
20
  import { GatewayAdapter } from './gatewayAdapter.js';
21
21
  import { OpenAiCompatibleLlm } from './openAiCompatibleLlm.js';
22
22
  export class GatewayLlm extends OpenAiCompatibleLlm {
@@ -40,5 +40,5 @@ export function gatewayClassFor(patterns) {
40
40
  }
41
41
  /** Registers a gateway stand-in for the given patterns. */
42
42
  export function registerGatewayLlm(patterns) {
43
- LLMRegistry.register(gatewayClassFor(patterns));
43
+ requireAdk("Registering a model class with ADK's LLMRegistry").LLMRegistry.register(gatewayClassFor(patterns));
44
44
  }
@@ -49,7 +49,7 @@
49
49
  import type { GenerateContentParameters, GenerateContentResponse, GoogleGenAIOptions, Part as WirePart } from '@google/genai';
50
50
  import type { ModelAdapter, ModelRequest, ModelResponse } from './contract.ts';
51
51
  import type { ProviderEndpoint } from './endpoints.ts';
52
- import { GEMINI_PROVIDER, THOUGHT_SIGNATURE_KIND } from './geminiState.ts';
52
+ import { CARRIED_PARTS_KIND, GEMINI_PROVIDER, PLACEHOLDER_THOUGHT_SIGNATURE, THOUGHT_SIGNATURE_KIND } from './geminiState.ts';
53
53
  /**
54
54
  * The provider id this adapter reports and writes its state under, and the
55
55
  * providerState kind for a Gemini thought signature (ADR 0046). Defined once
@@ -64,9 +64,11 @@ export declare const ENGINE_CALL_ID_PREFIX = "adk-";
64
64
  /**
65
65
  * The providerState kind for Gemini parts the contract has no type for
66
66
  * (code execution and server-side tool invocations), carried whole on the
67
- * next output part (ADR 0065). The payload is a `CarriedParts`.
67
+ * next output part (ADR 0065). The payload is a `CarriedParts`. Defined in
68
+ * lib/models/geminiState.ts, so the genai mapping writes them back out as
69
+ * the parts they were when an event is stored (ADR 0100).
68
70
  */
69
- export declare const CARRIED_PARTS_KIND = "carried_parts";
71
+ export { CARRIED_PARTS_KIND };
70
72
  /** The payload of a `carried_parts` state. */
71
73
  export interface CarriedParts {
72
74
  /** The genai parts that came before the output part, as Gemini sent them. */
@@ -82,7 +84,7 @@ export interface CarriedParts {
82
84
  * (default PLACEHOLDER_SIGNATURES_BY_DEFAULT, off) until the G3 live run
83
85
  * confirms it (ADR 0065).
84
86
  */
85
- export declare const PLACEHOLDER_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
87
+ export { PLACEHOLDER_THOUGHT_SIGNATURE };
86
88
  /** Off: no placeholder signature is sent unless the adapter is built to send it. */
87
89
  export declare const PLACEHOLDER_SIGNATURES_BY_DEFAULT = false;
88
90
  /** The part of the @google/genai client this adapter calls. `GoogleGenAI` satisfies it. */
@@ -48,7 +48,7 @@
48
48
  */
49
49
  import { FunctionCallingConfigMode, GoogleGenAI } from '@google/genai';
50
50
  import { endpointFromEnv, endpointProblems, platformModel } from './endpoints.js';
51
- import { GEMINI_PROVIDER, MINTED_CALL_ID_PREFIX, THOUGHT_SIGNATURE_KIND } from './geminiState.js';
51
+ import { CARRIED_PARTS_KIND, GEMINI_PROVIDER, GENAI_PART_KIND, MINTED_CALL_ID_PREFIX, PLACEHOLDER_THOUGHT_SIGNATURE, THOUGHT_SIGNATURE_KIND, isCarriedWirePart, } from './geminiState.js';
52
52
  import { currentTurnStart, providerStateOf } from './providerState.js';
53
53
  import { classifyError, errorStatus, retryUntilFirstYield } from './retry.js';
54
54
  import { reasoningConfig } from './reasoning.js';
@@ -67,9 +67,11 @@ export const ENGINE_CALL_ID_PREFIX = 'adk-';
67
67
  /**
68
68
  * The providerState kind for Gemini parts the contract has no type for
69
69
  * (code execution and server-side tool invocations), carried whole on the
70
- * next output part (ADR 0065). The payload is a `CarriedParts`.
70
+ * next output part (ADR 0065). The payload is a `CarriedParts`. Defined in
71
+ * lib/models/geminiState.ts, so the genai mapping writes them back out as
72
+ * the parts they were when an event is stored (ADR 0100).
71
73
  */
72
- export const CARRIED_PARTS_KIND = 'carried_parts';
74
+ export { CARRIED_PARTS_KIND };
73
75
  /**
74
76
  * The thought signature Gemini documents for a function call that has no
75
77
  * real one: a call another provider or model made earlier in the current
@@ -78,7 +80,7 @@ export const CARRIED_PARTS_KIND = 'carried_parts';
78
80
  * (default PLACEHOLDER_SIGNATURES_BY_DEFAULT, off) until the G3 live run
79
81
  * confirms it (ADR 0065).
80
82
  */
81
- export const PLACEHOLDER_THOUGHT_SIGNATURE = 'skip_thought_signature_validator';
83
+ export { PLACEHOLDER_THOUGHT_SIGNATURE };
82
84
  /** Off: no placeholder signature is sent unless the adapter is built to send it. */
83
85
  export const PLACEHOLDER_SIGNATURES_BY_DEFAULT = false;
84
86
  const defaultClientFactory = (options) => new GoogleGenAI(options);
@@ -330,6 +332,18 @@ function assistantToWire(message, replay, model) {
330
332
  carried = signature ?? carried;
331
333
  continue;
332
334
  }
335
+ // A carried part read back from a stored event (the mapping's genai_part):
336
+ // itself, verbatim, within its turn; outside it, nothing (ADR 0065, ADR 0100).
337
+ const stored = storedCarriedPart(part);
338
+ if (stored) {
339
+ if (!replay)
340
+ continue;
341
+ if (carried && !stored.thoughtSignature)
342
+ stored.thoughtSignature = carried;
343
+ carried = undefined;
344
+ out.push(stored);
345
+ continue;
346
+ }
333
347
  const before = replay ? carriedPartsOf(part, model) : [];
334
348
  if (before.length && carried) {
335
349
  if (!before[0].thoughtSignature)
@@ -381,6 +395,15 @@ function carriedPartsOf(part, model) {
381
395
  return own && typeof thoughtSignature === 'string' && thoughtSignature ? { ...rest, thoughtSignature } : { ...rest };
382
396
  });
383
397
  }
398
+ /**
399
+ * A copy of the code execution or server-side invocation part a stored
400
+ * event held, as the genai mapping reads it back (`genai_part` state on its
401
+ * text projection), or undefined for any other part.
402
+ */
403
+ function storedCarriedPart(part) {
404
+ const payload = providerStateOf(part, GEMINI_PROVIDER, GENAI_PART_KIND)?.payload;
405
+ return isPlainObject(payload) && isCarriedWirePart(payload) ? { ...payload } : undefined;
406
+ }
384
407
  /**
385
408
  * Gemini 3 rejects a current-turn step whose first function call has no
386
409
  * signature (a call another provider or model made). With placeholder
@@ -456,7 +479,7 @@ function finishReasonOf(reason) {
456
479
  * turn: code execution, and a server-side tool invocation.
457
480
  */
458
481
  function isCarried(part) {
459
- return part.executableCode !== undefined || part.codeExecutionResult !== undefined || part.toolCall !== undefined || part.toolResponse !== undefined;
482
+ return isCarriedWirePart(part);
460
483
  }
461
484
  /**
462
485
  * Folds Gemini's responses (one, or a stream's chunks) into the contract's