melchizedek-agents 0.18.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.
- package/.env.example +12 -0
- package/CHANGELOG.md +1001 -0
- package/DOCUMENTATION.md +252 -65
- package/QUICKSTART.md +9 -6
- package/README.md +42 -4
- package/config/agents/examples/harness.yaml +3 -1
- package/config/agents/examples/model_zoo.yaml +10 -9
- package/config/agents/syndicateSchema.yaml +53 -16
- package/config/agents/templates/account_memory.yaml +2 -6
- package/config/agents/templates/case_desk.yaml +3 -9
- package/config/agents/templates/draft_review.yaml +3 -9
- package/config/agents/templates/intake_extractor.yaml +1 -3
- package/config/agents/templates/research_brief.yaml +3 -9
- package/config/agents/templates/research_desk.yaml +3 -9
- package/config/agents/templates/review_panel.yaml +4 -12
- package/config/agents/templates/support_triage.yaml +4 -12
- package/config/agents/templates/systems_operator.yaml +2 -6
- package/db/hardening.sql +7 -1
- package/db/migrations/0013_tool_credentials.sql +260 -0
- package/dist/lib/a2a/app.d.ts +70 -6
- package/dist/lib/a2a/app.js +107 -2
- package/dist/lib/a2a/executor.d.ts +20 -3
- package/dist/lib/a2a/executor.js +66 -7
- package/dist/lib/a2a/remoteAgent.d.ts +24 -9
- package/dist/lib/a2a/remoteAgent.js +31 -14
- package/dist/lib/adkPeer.d.ts +63 -0
- package/dist/lib/adkPeer.js +240 -0
- package/dist/lib/compile.d.ts +159 -30
- package/dist/lib/compile.js +215 -134
- package/dist/lib/compileAdk.d.ts +32 -0
- package/dist/lib/compileAdk.js +142 -0
- package/dist/lib/compileNative.d.ts +111 -0
- package/dist/lib/compileNative.js +278 -0
- package/dist/lib/config.d.ts +6 -5
- package/dist/lib/config.js +6 -5
- package/dist/lib/doctor.d.ts +28 -1
- package/dist/lib/doctor.js +64 -2
- package/dist/lib/index.d.ts +6 -1
- package/dist/lib/index.js +7 -1
- package/dist/lib/loadSyndicate.d.ts +18 -0
- package/dist/lib/memory/erase.d.ts +5 -3
- package/dist/lib/memory/erase.js +5 -2
- package/dist/lib/memory/namespace.d.ts +8 -1
- package/dist/lib/memory/namespace.js +12 -6
- package/dist/lib/memory/providers.js +2 -1
- package/dist/lib/memory/supabaseMemoryService.d.ts +37 -3
- package/dist/lib/memory/supabaseMemoryService.js +42 -2
- package/dist/lib/model.d.ts +47 -0
- package/dist/lib/model.js +37 -0
- package/dist/lib/models/adapterResolver.d.ts +115 -0
- package/dist/lib/models/adapterResolver.js +137 -0
- package/dist/lib/models/adkGeminiAdapter.d.ts +90 -0
- package/dist/lib/models/adkGeminiAdapter.js +369 -0
- package/dist/lib/models/adkShim.d.ts +111 -0
- package/dist/lib/models/adkShim.js +136 -0
- package/dist/lib/models/capabilities.d.ts +3 -0
- package/dist/lib/models/capabilities.js +33 -23
- package/dist/lib/models/chatCompletionsAdapter.d.ts +279 -0
- package/dist/lib/models/chatCompletionsAdapter.js +854 -0
- package/dist/lib/models/circuitBreaker.d.ts +42 -0
- package/dist/lib/models/circuitBreaker.js +70 -0
- package/dist/lib/models/claudeAdapter.d.ts +103 -0
- package/dist/lib/models/claudeAdapter.js +669 -0
- package/dist/lib/models/claudeLlm.d.ts +39 -62
- package/dist/lib/models/claudeLlm.js +45 -350
- package/dist/lib/models/claudeModels.d.ts +127 -0
- package/dist/lib/models/claudeModels.js +237 -0
- package/dist/lib/models/contract.d.ts +395 -0
- package/dist/lib/models/contract.js +39 -0
- package/dist/lib/models/endpoints.js +2 -1
- package/dist/lib/models/errorResponse.d.ts +50 -0
- package/dist/lib/models/errorResponse.js +48 -0
- package/dist/lib/models/fallback.d.ts +18 -11
- package/dist/lib/models/fallback.js +54 -43
- package/dist/lib/models/fallbackAdapter.d.ts +55 -0
- package/dist/lib/models/fallbackAdapter.js +62 -0
- package/dist/lib/models/gateway.js +2 -1
- package/dist/lib/models/gatewayAdapter.d.ts +51 -0
- package/dist/lib/models/gatewayAdapter.js +81 -0
- package/dist/lib/models/gatewayLlm.d.ts +12 -33
- package/dist/lib/models/gatewayLlm.js +16 -77
- package/dist/lib/models/geminiAdapter.d.ts +125 -0
- package/dist/lib/models/geminiAdapter.js +854 -0
- package/dist/lib/models/geminiState.d.ts +46 -0
- package/dist/lib/models/geminiState.js +51 -0
- package/dist/lib/models/genaiMapping.d.ts +283 -0
- package/dist/lib/models/genaiMapping.js +965 -0
- package/dist/lib/models/gptAdapter.d.ts +240 -0
- package/dist/lib/models/gptAdapter.js +804 -0
- package/dist/lib/models/gptLlm.d.ts +63 -123
- package/dist/lib/models/gptLlm.js +89 -603
- package/dist/lib/models/grokAdapter.d.ts +86 -0
- package/dist/lib/models/grokAdapter.js +142 -0
- package/dist/lib/models/grokLlm.d.ts +22 -45
- package/dist/lib/models/grokLlm.js +24 -69
- package/dist/lib/models/kimiAdapter.d.ts +157 -0
- package/dist/lib/models/kimiAdapter.js +203 -0
- package/dist/lib/models/kimiLlm.d.ts +15 -107
- package/dist/lib/models/kimiLlm.js +19 -155
- package/dist/lib/models/ollamaAdapter.d.ts +125 -0
- package/dist/lib/models/ollamaAdapter.js +155 -0
- package/dist/lib/models/ollamaLlm.d.ts +11 -107
- package/dist/lib/models/ollamaLlm.js +15 -153
- package/dist/lib/models/openAiCompatibleLlm.d.ts +73 -216
- package/dist/lib/models/openAiCompatibleLlm.js +109 -671
- package/dist/lib/models/providerState.d.ts +63 -0
- package/dist/lib/models/providerState.js +61 -0
- package/dist/lib/models/reasoning.d.ts +26 -0
- package/dist/lib/models/reasoning.js +59 -0
- package/dist/lib/models/registry.d.ts +62 -35
- package/dist/lib/models/registry.js +100 -124
- package/dist/lib/models/retry.d.ts +2 -1
- package/dist/lib/models/retry.js +3 -2
- package/dist/lib/models/schemaNormalize.d.ts +98 -0
- package/dist/lib/models/schemaNormalize.js +321 -1
- package/dist/lib/models/tracedGemini.d.ts +41 -0
- package/dist/lib/models/tracedGemini.js +98 -0
- package/dist/lib/models/urls.d.ts +11 -0
- package/dist/lib/models/urls.js +16 -0
- package/dist/lib/net/redirects.d.ts +21 -2
- package/dist/lib/net/redirects.js +11 -34
- package/dist/lib/observability/audit.d.ts +5 -1
- package/dist/lib/observability/lineage.d.ts +14 -0
- package/dist/lib/observability/lineage.js +33 -0
- package/dist/lib/observability/supabaseSpanExporter.d.ts +10 -4
- package/dist/lib/observability/supabaseSpanExporter.js +17 -9
- package/dist/lib/observability/tracer.d.ts +26 -8
- package/dist/lib/observability/tracer.js +43 -18
- package/dist/lib/runtime/adkMemoryBridge.d.ts +46 -0
- package/dist/lib/runtime/adkMemoryBridge.js +68 -0
- package/dist/lib/runtime/adkSessionBridge.d.ts +78 -0
- package/dist/lib/runtime/adkSessionBridge.js +176 -0
- package/dist/lib/runtime/approvals.d.ts +5 -0
- package/dist/lib/runtime/approvals.js +39 -8
- package/dist/lib/runtime/credentials.d.ts +61 -0
- package/dist/lib/runtime/credentials.js +67 -0
- package/dist/lib/runtime/events.d.ts +229 -0
- package/dist/lib/runtime/events.js +274 -0
- package/dist/lib/runtime/logging.d.ts +32 -0
- package/dist/lib/runtime/logging.js +55 -0
- package/dist/lib/runtime/memoryService.d.ts +72 -0
- package/dist/lib/runtime/memoryService.js +25 -0
- package/dist/lib/runtime/native/agentLoop.d.ts +209 -0
- package/dist/lib/runtime/native/agentLoop.js +705 -0
- package/dist/lib/runtime/native/compaction.d.ts +103 -0
- package/dist/lib/runtime/native/compaction.js +191 -0
- package/dist/lib/runtime/native/delegate.d.ts +151 -0
- package/dist/lib/runtime/native/delegate.js +256 -0
- package/dist/lib/runtime/native/history.d.ts +83 -0
- package/dist/lib/runtime/native/history.js +312 -0
- package/dist/lib/runtime/native/interrupts.d.ts +129 -0
- package/dist/lib/runtime/native/interrupts.js +310 -0
- package/dist/lib/runtime/native/request.d.ts +215 -0
- package/dist/lib/runtime/native/request.js +585 -0
- package/dist/lib/runtime/native/selfCorrection.d.ts +164 -0
- package/dist/lib/runtime/native/selfCorrection.js +327 -0
- package/dist/lib/runtime/native/step.d.ts +156 -0
- package/dist/lib/runtime/native/step.js +263 -0
- package/dist/lib/runtime/native/taskMode.d.ts +64 -0
- package/dist/lib/runtime/native/taskMode.js +126 -0
- package/dist/lib/runtime/native/telemetry.d.ts +75 -0
- package/dist/lib/runtime/native/telemetry.js +299 -0
- package/dist/lib/runtime/native/tempState.d.ts +31 -0
- package/dist/lib/runtime/native/tempState.js +56 -0
- package/dist/lib/runtime/nativeTurn.d.ts +86 -0
- package/dist/lib/runtime/nativeTurn.js +107 -0
- package/dist/lib/runtime/questions.d.ts +29 -7
- package/dist/lib/runtime/questions.js +47 -32
- package/dist/lib/runtime/runtimeFlag.d.ts +38 -0
- package/dist/lib/runtime/runtimeFlag.js +58 -0
- package/dist/lib/runtime/sessions.d.ts +166 -0
- package/dist/lib/runtime/sessions.js +201 -0
- package/dist/lib/runtime/syndicateTurn.d.ts +46 -5
- package/dist/lib/runtime/syndicateTurn.js +233 -36
- package/dist/lib/runtime/valueDepth.d.ts +23 -0
- package/dist/lib/runtime/valueDepth.js +41 -0
- package/dist/lib/session/supabaseSessionService.d.ts +65 -18
- package/dist/lib/session/supabaseSessionService.js +148 -105
- package/dist/lib/session/transcript.d.ts +69 -23
- package/dist/lib/session/transcript.js +105 -29
- package/dist/lib/skills.js +33 -7
- package/dist/lib/storage/postgres/credentialStore.d.ts +20 -0
- package/dist/lib/storage/postgres/credentialStore.js +82 -0
- package/dist/lib/storage/postgres/index.d.ts +12 -0
- package/dist/lib/storage/postgres/index.js +6 -1
- package/dist/lib/storage/postgres/sessionService.d.ts +44 -16
- package/dist/lib/storage/postgres/sessionService.js +128 -66
- package/dist/lib/syndicateSchema.d.ts +49 -0
- package/dist/lib/syndicateSchema.js +99 -9
- package/dist/lib/toolRegistry.d.ts +26 -2
- package/dist/lib/toolRegistry.js +73 -17
- package/dist/lib/tools/adkTool.d.ts +81 -0
- package/dist/lib/tools/adkTool.js +268 -0
- package/dist/lib/tools/auth.d.ts +118 -0
- package/dist/lib/tools/auth.js +89 -0
- package/dist/lib/tools/collectionsSearchTool.d.ts +8 -7
- package/dist/lib/tools/collectionsSearchTool.js +12 -27
- package/dist/lib/tools/credentialCipher.d.ts +58 -0
- package/dist/lib/tools/credentialCipher.js +116 -0
- package/dist/lib/tools/credentialStore.d.ts +77 -0
- package/dist/lib/tools/credentialStore.js +246 -0
- package/dist/lib/tools/examples.d.ts +43 -0
- package/dist/lib/tools/examples.js +62 -0
- package/dist/lib/tools/generateImageTool.d.ts +15 -6
- package/dist/lib/tools/generateImageTool.js +19 -29
- package/dist/lib/tools/inspectImageTool.d.ts +9 -6
- package/dist/lib/tools/inspectImageTool.js +13 -17
- package/dist/lib/tools/mcpToolFactory.d.ts +42 -1
- package/dist/lib/tools/mcpToolFactory.js +46 -47
- package/dist/lib/tools/memoryTools.d.ts +61 -0
- package/dist/lib/tools/memoryTools.js +119 -0
- package/dist/lib/tools/nativeTools.d.ts +38 -0
- package/dist/lib/tools/nativeTools.js +43 -0
- package/dist/lib/tools/oauthConsent.d.ts +181 -0
- package/dist/lib/tools/oauthConsent.js +330 -0
- package/dist/lib/tools/openapi/call.d.ts +108 -0
- package/dist/lib/tools/openapi/call.js +295 -0
- package/dist/lib/tools/openapi/parse.d.ts +147 -0
- package/dist/lib/tools/openapi/parse.js +570 -0
- package/dist/lib/tools/openapiTools.d.ts +25 -17
- package/dist/lib/tools/openapiTools.js +124 -121
- package/dist/lib/tools/scienceTools.d.ts +14 -14
- package/dist/lib/tools/skillToolset.d.ts +58 -87
- package/dist/lib/tools/skillToolset.js +61 -142
- package/dist/lib/tools/skills/env.d.ts +58 -0
- package/dist/lib/tools/skills/env.js +165 -0
- package/dist/lib/tools/skills/executor.d.ts +114 -0
- package/dist/lib/tools/skills/executor.js +331 -0
- package/dist/lib/tools/skills/frontmatter.d.ts +79 -0
- package/dist/lib/tools/skills/frontmatter.js +215 -0
- package/dist/lib/tools/skills/loader.d.ts +91 -0
- package/dist/lib/tools/skills/loader.js +257 -0
- package/dist/lib/tools/skills/tools.d.ts +187 -0
- package/dist/lib/tools/skills/tools.js +386 -0
- package/dist/lib/tools/taskTools.d.ts +15 -15
- package/dist/lib/tools/tool.d.ts +354 -0
- package/dist/lib/tools/tool.js +304 -0
- package/dist/lib/tools/toolContract.d.ts +89 -33
- package/dist/lib/tools/toolContract.js +104 -82
- package/dist/lib/tools/urlContextTool.d.ts +4 -1
- package/dist/lib/tools/urlContextTool.js +6 -2
- package/dist/lib/tools/webExtractTool.d.ts +3 -3
- package/dist/lib/tools/webExtractTool.js +2 -1
- package/dist/lib/tools/webSearchTool.d.ts +7 -10
- package/dist/lib/tools/webSearchTool.js +15 -60
- package/dist/lib/tools/wikiTools.d.ts +19 -19
- package/dist/lib/tools/wikiTools.js +13 -9
- package/dist/lib/tools/xApiSearchTool.d.ts +3 -3
- package/dist/lib/tools/xApiSearchTool.js +2 -1
- package/dist/lib/tools/xSearchTool.d.ts +8 -10
- package/dist/lib/tools/xSearchTool.js +12 -63
- package/dist/lib/tools/xaiSearchParams.d.ts +41 -0
- package/dist/lib/tools/xaiSearchParams.js +126 -0
- package/dist/lib/wiki/agentRun.d.ts +12 -0
- package/dist/lib/wiki/agentRun.js +74 -35
- package/dist/lib/wiki/entities.d.ts +12 -0
- package/dist/lib/wiki/entities.js +45 -3
- package/dist/lib/workflow/agentNode.d.ts +153 -0
- package/dist/lib/workflow/agentNode.js +365 -0
- package/dist/lib/workflow/graph.d.ts +178 -0
- package/dist/lib/workflow/graph.js +468 -0
- package/dist/lib/workflow/nodeEvents.d.ts +50 -0
- package/dist/lib/workflow/nodeEvents.js +101 -0
- package/dist/lib/workflow/pause.d.ts +122 -0
- package/dist/lib/workflow/pause.js +180 -0
- package/dist/lib/workflow/resume.d.ts +166 -0
- package/dist/lib/workflow/resume.js +441 -0
- package/dist/lib/workflow/route.d.ts +58 -0
- package/dist/lib/workflow/route.js +69 -0
- package/dist/lib/workflow/scheduler.d.ts +418 -0
- package/dist/lib/workflow/scheduler.js +756 -0
- package/dist/lib/workflow/toolNode.d.ts +127 -0
- package/dist/lib/workflow/toolNode.js +236 -0
- package/dist/lib/workflow/turn.d.ts +118 -0
- package/dist/lib/workflow/turn.js +216 -0
- package/dist/lib/workflow.d.ts +33 -11
- package/dist/lib/workflow.js +49 -27
- package/dist/lib/workflowConfig.d.ts +7 -2
- package/dist/lib/workflowConfig.js +7 -12
- package/dist/scripts/a2a_server.js +4 -3
- package/dist/scripts/assistant_worker.d.ts +2 -1
- package/dist/scripts/assistant_worker.js +9 -4
- package/dist/scripts/doctor.d.ts +3 -1
- package/dist/scripts/doctor.js +4 -2
- package/dist/scripts/syndicate_chat.js +19 -10
- package/package.json +9 -3
- package/skills/briefs/melchizedek-author.md +3 -2
- package/skills/briefs/melchizedek-models.md +13 -9
- package/skills/briefs/melchizedek.md +3 -3
- package/skills/melchizedek/SKILL.md +2 -1
- package/skills/melchizedek-author/SKILL.md +2 -1
- package/skills/melchizedek-author/assets/minimal.yaml +2 -0
- package/skills/melchizedek-models/SKILL.md +23 -6
package/dist/lib/compile.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* lib/compile.ts — the one YAML →
|
|
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,31 @@
|
|
|
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 {
|
|
40
|
+
import { BaseLlm, FunctionTool } from './adkPeer.js';
|
|
31
41
|
import { relative } from 'node:path';
|
|
42
|
+
import { compileAdk } from './compileAdk.js';
|
|
32
43
|
import { isDispatchSyndicate } from './dispatch.js';
|
|
44
|
+
import { isWorkflowSyndicate, nodeKind } from './workflowConfig.js';
|
|
33
45
|
import { loadSyndicate, nestedLoader } from './loadSyndicate.js';
|
|
46
|
+
import { REASONING_OLDER_SPELLING } from './syndicateSchema.js';
|
|
47
|
+
import { reasoningConfig } from './models/reasoning.js';
|
|
34
48
|
import { resolveTools as resolveNamedTools } from './toolRegistry.js';
|
|
35
49
|
import { createMcpTools } from './tools/mcpToolFactory.js';
|
|
50
|
+
import { toAdkInstructionTool, toAdkToolset } from './tools/adkTool.js';
|
|
51
|
+
import { examplesInstructionTool } from './tools/examples.js';
|
|
36
52
|
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
53
|
import { buildSkillHarness } from './tools/skillToolset.js';
|
|
41
|
-
import { buildOpenApiTools,
|
|
54
|
+
import { buildOpenApiTools, namesTool, openApiOperationId } from './tools/openapiTools.js';
|
|
42
55
|
/** generateContentConfig as every entrypoint has always sent it to ADK. */
|
|
43
56
|
function withServerSideToolInvocations(generateContentConfig) {
|
|
44
57
|
const cfg = (generateContentConfig ?? {});
|
|
@@ -50,59 +63,31 @@ function withServerSideToolInvocations(generateContentConfig) {
|
|
|
50
63
|
},
|
|
51
64
|
};
|
|
52
65
|
}
|
|
66
|
+
// ── Reasoning (ADR 0047) ─────────────────────────────────────────────────────
|
|
67
|
+
// REASONING_BUDGETS and reasoningConfig live in lib/models/reasoning.ts, so a
|
|
68
|
+
// model adapter can map `reasoning:` without importing the compiler (and ADK).
|
|
69
|
+
export { REASONING_BUDGETS, reasoningConfig } from './models/reasoning.js';
|
|
53
70
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
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.
|
|
61
|
-
*/
|
|
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).
|
|
71
|
+
* An agent's generateContentConfig with its `reasoning:` key mapped in for
|
|
72
|
+
* the model it runs on. Unchanged (the same object) when the agent sets no
|
|
73
|
+
* `reasoning`. The loader refuses `reasoning` next to the older spelling;
|
|
74
|
+
* this refuses it too, for a config built in code.
|
|
85
75
|
*/
|
|
86
|
-
function
|
|
87
|
-
const
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
];
|
|
76
|
+
export function withReasoning(agent, model) {
|
|
77
|
+
const cfg = agent.generateContentConfig;
|
|
78
|
+
if (agent.reasoning === undefined)
|
|
79
|
+
return cfg;
|
|
80
|
+
const clash = REASONING_OLDER_SPELLING.filter((k) => cfg?.[k] !== undefined);
|
|
81
|
+
if (clash.length) {
|
|
82
|
+
throw new Error(`${agent.name ?? 'agent'}: reasoning cannot be combined with ${clash.map((k) => `generateContentConfig.${k}`).join(' or ')}; reasoning replaces it (ADR 0047)`);
|
|
103
83
|
}
|
|
104
|
-
return
|
|
84
|
+
return { ...cfg, ...reasoningConfig(model ?? '', agent.reasoning) };
|
|
105
85
|
}
|
|
86
|
+
/** The model id an agent runs on, from its YAML or its resolved adapter. */
|
|
87
|
+
function modelIdOf(yamlModel, resolved) {
|
|
88
|
+
return yamlModel ?? (typeof resolved === 'string' ? resolved : resolved instanceof BaseLlm ? resolved.model : undefined);
|
|
89
|
+
}
|
|
90
|
+
export { DEFAULT_KEEP_RECENT_EVENTS } from './runtime/native/compaction.js';
|
|
106
91
|
/**
|
|
107
92
|
* Says, once per compiled agent, what its resolved path cannot honour — a
|
|
108
93
|
* dropped server-side tool, a gateway stand-in, or no route at all. Quiet
|
|
@@ -131,9 +116,13 @@ export function requireApprovalOn(tool) {
|
|
|
131
116
|
return gated;
|
|
132
117
|
}
|
|
133
118
|
/**
|
|
134
|
-
* A copy of an
|
|
135
|
-
*
|
|
136
|
-
*
|
|
119
|
+
* A copy of an ADK BaseTool that runs only after a person approves the
|
|
120
|
+
* call: the same confirmation interrupt FunctionTool's own gate raises, so
|
|
121
|
+
* the turn pauses and resumes exactly as ADR 0028 says. The engine no
|
|
122
|
+
* longer uses it: an OpenAPI operation is a FunctionTool over an own Tool
|
|
123
|
+
* (ADR 0067) and takes requireApprovalOn like every registry tool.
|
|
124
|
+
* @deprecated Gate a FunctionTool with requireApprovalOn, or an own Tool
|
|
125
|
+
* with requireApproval (lib/tools/tool.ts).
|
|
137
126
|
*/
|
|
138
127
|
export function requireApprovalOnBaseTool(tool) {
|
|
139
128
|
const gated = Object.create(tool);
|
|
@@ -157,17 +146,16 @@ function gateTools(tools, names, agentName) {
|
|
|
157
146
|
return tools;
|
|
158
147
|
const wanted = new Set(names);
|
|
159
148
|
const out = tools.map((t) => {
|
|
160
|
-
const
|
|
161
|
-
const name = tool?.name;
|
|
149
|
+
const name = t?.name;
|
|
162
150
|
if (!name)
|
|
163
151
|
return t;
|
|
164
152
|
// An OpenAPI operation may be named as the YAML named it (its operationId).
|
|
165
|
-
const
|
|
153
|
+
const operationId = openApiOperationId(t);
|
|
154
|
+
const match = [...wanted].find((w) => w === name || (operationId !== undefined && namesTool(w, { name, operation: { operationId } })));
|
|
166
155
|
if (!match)
|
|
167
156
|
return t;
|
|
168
157
|
wanted.delete(match);
|
|
169
|
-
|
|
170
|
-
return requireApprovalOnBaseTool(t);
|
|
158
|
+
// An OpenAPI operation is a FunctionTool over an own Tool (ADR 0067): one gate for both.
|
|
171
159
|
if (!(t instanceof FunctionTool)) {
|
|
172
160
|
throw new Error(`${agentName}: '${name}' cannot require approval — only function tools from the registry and OpenAPI operations can be gated (ADR 0028).`);
|
|
173
161
|
}
|
|
@@ -185,27 +173,14 @@ export function declaresApprovals(config) {
|
|
|
185
173
|
return agentGates(config.orchestrator) || (config.subagents ?? []).some((s) => agentGates(s));
|
|
186
174
|
}
|
|
187
175
|
/**
|
|
188
|
-
*
|
|
189
|
-
*
|
|
176
|
+
* An agent's `examples:` as the ADK tool for their InstructionTool
|
|
177
|
+
* (lib/tools/examples.ts): never called by the model, it adds the exchanges
|
|
178
|
+
* to every request's instruction as few-shot examples, in the words ADK's
|
|
179
|
+
* ExampleTool used.
|
|
190
180
|
*/
|
|
191
181
|
export function examplesTool(examples) {
|
|
192
|
-
|
|
193
|
-
|
|
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)));
|
|
182
|
+
const tool = examplesInstructionTool(examples);
|
|
183
|
+
return tool ? [toAdkInstructionTool(tool)] : [];
|
|
209
184
|
}
|
|
210
185
|
async function resolveAgentTools(toolNames, mcpServerUrl, opts, openapi, examples, mcpAllowed) {
|
|
211
186
|
const tools = [...resolveNamedTools(toolNames, opts.onUnknownTool), ...examplesTool(examples)];
|
|
@@ -258,94 +233,200 @@ async function withSkills(instruction, tools, skills, agentName, opts) {
|
|
|
258
233
|
opts.log?.(`skills · ${agentName}: ${count} skill${count === 1 ? '' : 's'} from ${skills.dir}${skills.scripts === 'local' ? ' · scripts run after approval' : ''}`);
|
|
259
234
|
for (const problem of harness.problems)
|
|
260
235
|
opts.log?.(`⚠ skills · ${skills.dir}: not loaded — ${problem}`);
|
|
261
|
-
|
|
236
|
+
// The ADK face of the engine's own toolset; compileNative reads the toolset back (toolsetOf).
|
|
237
|
+
return { instruction: `${instruction.trimEnd()}\n\n${harness.instruction}`, tools: [...tools, toAdkToolset(harness.toolset)] };
|
|
262
238
|
}
|
|
263
239
|
/** True when a turn running this agent directly may pause for a person (ADR 0028). */
|
|
264
240
|
export function agentGates(agent) {
|
|
265
241
|
return !!agent?.require_approval?.length || agent?.skills?.scripts === 'local';
|
|
266
242
|
}
|
|
243
|
+
function specOf(yaml, name, description, instruction, tools, opts) {
|
|
244
|
+
const resolvedModel = (opts.resolveModel ?? ((m) => m))(yaml.model);
|
|
245
|
+
const modelId = modelIdOf(yaml.model, resolvedModel);
|
|
246
|
+
const spec = {
|
|
247
|
+
name,
|
|
248
|
+
instruction,
|
|
249
|
+
tools,
|
|
250
|
+
resolvedModel,
|
|
251
|
+
generateContentConfig: withServerSideToolInvocations(withReasoning(yaml, modelId)),
|
|
252
|
+
};
|
|
253
|
+
if (description !== undefined)
|
|
254
|
+
spec.description = description;
|
|
255
|
+
if (yaml.model !== undefined)
|
|
256
|
+
spec.model = yaml.model;
|
|
257
|
+
if (modelId !== undefined)
|
|
258
|
+
spec.modelId = modelId;
|
|
259
|
+
if (yaml.fallback_model)
|
|
260
|
+
spec.fallbackModel = yaml.fallback_model;
|
|
261
|
+
if (yaml.outputSchema)
|
|
262
|
+
spec.outputSchema = yaml.outputSchema;
|
|
263
|
+
if (yaml.includeContents !== undefined)
|
|
264
|
+
spec.includeContents = yaml.includeContents;
|
|
265
|
+
if (yaml.outputKey !== undefined)
|
|
266
|
+
spec.outputKey = yaml.outputKey;
|
|
267
|
+
if (yaml.globalInstruction !== undefined)
|
|
268
|
+
spec.globalInstruction = yaml.globalInstruction;
|
|
269
|
+
if (yaml.disallowTransferToParent !== undefined)
|
|
270
|
+
spec.disallowTransferToParent = yaml.disallowTransferToParent;
|
|
271
|
+
if (yaml.disallowTransferToPeers !== undefined)
|
|
272
|
+
spec.disallowTransferToPeers = yaml.disallowTransferToPeers;
|
|
273
|
+
if (yaml.code_execution)
|
|
274
|
+
spec.codeExecution = yaml.code_execution;
|
|
275
|
+
if (yaml.context)
|
|
276
|
+
spec.context = yaml.context;
|
|
277
|
+
if (yaml.mode)
|
|
278
|
+
spec.mode = yaml.mode;
|
|
279
|
+
return spec;
|
|
280
|
+
}
|
|
281
|
+
const asTools = (tools) => tools.map((tool) => ({ kind: 'tool', tool }));
|
|
282
|
+
/**
|
|
283
|
+
* A nested `yaml_reference:` syndicate, loaded. A nested syndicate runs
|
|
284
|
+
* inside a tool call (or as a route whose own subagents do): a pause there
|
|
285
|
+
* cannot reach the caller (ADR 0028), so one that declares approval gates is
|
|
286
|
+
* refused.
|
|
287
|
+
*/
|
|
288
|
+
/** Where the yaml_reference chain a compile is inside is kept: an own symbol on the options, so a spread copy keeps it. */
|
|
289
|
+
const NESTING = Symbol('melchizedek.compile.nesting');
|
|
290
|
+
/** The deepest a yaml_reference chain may go: well past any syndicate the engine ships, short of the stack. */
|
|
291
|
+
const MAX_NESTING_DEPTH = 16;
|
|
267
292
|
/**
|
|
268
|
-
*
|
|
269
|
-
*
|
|
293
|
+
* The options a nested `ref` compiles with: `opts` and the chain of
|
|
294
|
+
* references above it. A reference already on the chain (a syndicate that
|
|
295
|
+
* reaches itself) or a chain past MAX_NESTING_DEPTH is refused by name (WS5-5,
|
|
296
|
+
* ADR 0101): the compile would otherwise recurse until the stack gave out,
|
|
297
|
+
* which took the process with it.
|
|
298
|
+
*/
|
|
299
|
+
function nestedOptions(ref, opts) {
|
|
300
|
+
const chain = (opts[NESTING] ?? []);
|
|
301
|
+
if (chain.includes(ref))
|
|
302
|
+
throw new Error(`${ref}: a nested syndicate reaches itself (${[...chain, ref].join(' → ')}); a yaml_reference chain must end.`);
|
|
303
|
+
if (chain.length >= MAX_NESTING_DEPTH)
|
|
304
|
+
throw new Error(`${ref}: nested syndicates go deeper than ${MAX_NESTING_DEPTH} levels (${[...chain, ref].join(' → ')}).`);
|
|
305
|
+
return { ...opts, [NESTING]: [...chain, ref] };
|
|
306
|
+
}
|
|
307
|
+
function loadNestedSyndicate(ref, opts) {
|
|
308
|
+
opts.log?.(`Loading nested syndicate: ${ref}`);
|
|
309
|
+
const nested = (opts.loadNested ?? loadSyndicate)(ref);
|
|
310
|
+
if (declaresApprovals(nested)) {
|
|
311
|
+
throw new Error(`${ref}: approval gates (require_approval) are not supported inside a nested syndicate.`);
|
|
312
|
+
}
|
|
313
|
+
return nested;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* The spec of a workflow syndicate: every agent through compileSubagentSpec
|
|
317
|
+
* (the orchestrator first, as a node like any other), and the registry's
|
|
318
|
+
* lookup for its tool nodes. `name` and `description` name a nested one
|
|
319
|
+
* after its subagent entry (ADR 0098); `ref` is the file it came from.
|
|
320
|
+
*
|
|
321
|
+
* A nested workflow runs inside its caller's tool call, so a pause inside it
|
|
322
|
+
* could not reach the caller (ADR 0028, as for any nested syndicate): an
|
|
323
|
+
* `ask_user` node is refused by name here, on both runtimes.
|
|
324
|
+
*/
|
|
325
|
+
export async function compileWorkflowSpec(config, opts = {}, name, description, ref) {
|
|
326
|
+
if (!isWorkflowSyndicate(config))
|
|
327
|
+
throw new Error(`${config.syndicate_name}: no workflow block`);
|
|
328
|
+
if (name) {
|
|
329
|
+
const asking = Object.entries(config.workflow.nodes ?? {}).find(([, node]) => nodeKind(node) === 'ask_user');
|
|
330
|
+
if (asking) {
|
|
331
|
+
throw new Error(`${ref ?? config.syndicate_name}: the ask_user node '${asking[0]}' pauses for a person, which a workflow nested as a subagent (${name}) cannot carry to its caller; run the workflow as its own syndicate, or remove the node.`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
const workflowName = name || config.syndicate_name;
|
|
335
|
+
const agents = [];
|
|
336
|
+
for (const yaml of [{ description: '', ...config.orchestrator }, ...(config.subagents ?? [])]) {
|
|
337
|
+
agents.push({ yaml, spec: await compileSubagentSpec(yaml, opts) });
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
name: workflowName,
|
|
341
|
+
description: description ?? '',
|
|
342
|
+
config: { ...config, syndicate_name: workflowName },
|
|
343
|
+
agents,
|
|
344
|
+
resolveTool: (tool) => resolveNamedTools([tool], opts.onUnknownTool)[0],
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* The spec of ONE agent from a subagent entry. A `yaml_reference` entry is
|
|
349
|
+
* the nested syndicate's whole graph under this entry's name and
|
|
270
350
|
* description, so the parent sees one tool (or one route) either way.
|
|
271
351
|
*/
|
|
272
|
-
export async function
|
|
352
|
+
export async function compileSubagentSpec(subCfg, opts = {}) {
|
|
273
353
|
if (subCfg.a2a_agent_url) {
|
|
274
354
|
// A remote agent has its own model and prompt on its own server; there
|
|
275
355
|
// is no local agent to build. It is reached as a delegation tool
|
|
276
|
-
// (
|
|
356
|
+
// (compileSpec) or a dispatch route (lib/runtime/syndicateTurn.ts).
|
|
277
357
|
throw new Error(`'${subCfg.name}' is a remote A2A agent (a2a_agent_url) and has no local agent to compile.`);
|
|
278
358
|
}
|
|
279
359
|
if (subCfg.yaml_reference) {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
if (declaresApprovals(nested)) {
|
|
283
|
-
// A nested syndicate runs inside a tool call (or as a route whose
|
|
284
|
-
// own subagents do): a pause there cannot reach the caller (ADR 0028).
|
|
285
|
-
throw new Error(`${subCfg.yaml_reference}: approval gates (require_approval) are not supported inside a nested syndicate.`);
|
|
286
|
-
}
|
|
287
|
-
return compileGraph(nested, opts, subCfg.name, subCfg.description);
|
|
360
|
+
const nestedOpts = nestedOptions(subCfg.yaml_reference, opts);
|
|
361
|
+
return compileSpec(loadNestedSyndicate(subCfg.yaml_reference, nestedOpts), nestedOpts, subCfg.name, subCfg.description);
|
|
288
362
|
}
|
|
289
363
|
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
364
|
const { instruction, tools } = await withSkills(subCfg.instruction ?? '', gated, subCfg.skills, subCfg.name, opts);
|
|
291
|
-
const resolveModel = opts.resolveModel ?? ((m) => m);
|
|
292
365
|
logCapabilities(opts, subCfg.name, subCfg.model, subCfg.tools);
|
|
293
|
-
return
|
|
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
|
-
});
|
|
366
|
+
return specOf(subCfg, subCfg.name, subCfg.description, instruction, asTools(tools), opts);
|
|
305
367
|
}
|
|
306
368
|
/**
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
* outputSchema + AgentTool on one agent — see
|
|
310
|
-
* and the caller dispatches to
|
|
369
|
+
* The spec of a syndicate's orchestrator. In DELEGATE mode its subagents
|
|
370
|
+
* come first among its tools, as delegations; in PLAN-DISPATCH mode it gets
|
|
371
|
+
* none (ADK refuses outputSchema + AgentTool on one agent — see
|
|
372
|
+
* config/agents/critic.yaml), and the caller dispatches to a route's own
|
|
373
|
+
* spec itself.
|
|
311
374
|
*/
|
|
312
|
-
export async function
|
|
375
|
+
export async function compileSpec(config, opts = {}, overrideName, overrideDescription) {
|
|
313
376
|
// A registry definition carries its nested syndicates (ADR 0018 item 6).
|
|
314
377
|
if (config.bundled_references && !opts.loadNested)
|
|
315
378
|
opts = { ...opts, loadNested: nestedLoader(config) };
|
|
316
379
|
// A graph has no orchestrator-with-tools shape to build: its agents are
|
|
317
|
-
// nodes (lib/workflow.ts).
|
|
318
|
-
//
|
|
380
|
+
// nodes (lib/workflow.ts). A delegated yaml_reference to one runs the whole
|
|
381
|
+
// graph as the tool (nestedWorkflowSpec, ADR 0098); as a dispatch route or
|
|
382
|
+
// a workflow node it is still its orchestrator alone.
|
|
319
383
|
if (config.workflow && !overrideName) {
|
|
320
384
|
throw new Error(`${config.syndicate_name}: a workflow syndicate is compiled with compileWorkflow (lib/workflow.ts), not compileGraph`);
|
|
321
385
|
}
|
|
322
386
|
if (config.workflow)
|
|
323
|
-
opts.log?.(`${config.syndicate_name}:
|
|
324
|
-
const
|
|
387
|
+
opts.log?.(`${config.syndicate_name}: a dispatch route or a workflow node, so only its orchestrator runs (a delegated subagent runs the whole graph)`);
|
|
388
|
+
const delegated = isDispatchSyndicate(config)
|
|
325
389
|
? []
|
|
326
390
|
: await Promise.all((config.subagents ?? []).map(async (subCfg) => {
|
|
327
391
|
if (subCfg.a2a_agent_url) {
|
|
328
392
|
opts.log?.(`Remote A2A agent: ${subCfg.name} → ${subCfg.a2a_agent_url}`);
|
|
329
|
-
return
|
|
393
|
+
return { kind: 'remote', name: subCfg.name, description: subCfg.description, url: subCfg.a2a_agent_url };
|
|
330
394
|
}
|
|
331
|
-
|
|
395
|
+
if (subCfg.yaml_reference) {
|
|
396
|
+
const nestedOpts = nestedOptions(subCfg.yaml_reference, opts);
|
|
397
|
+
const nested = loadNestedSyndicate(subCfg.yaml_reference, nestedOpts);
|
|
398
|
+
if (isWorkflowSyndicate(nested))
|
|
399
|
+
return { kind: 'workflow', workflow: await compileWorkflowSpec(nested, nestedOpts, subCfg.name, subCfg.description, subCfg.yaml_reference) };
|
|
400
|
+
return { kind: 'agent', agent: await compileSpec(nested, nestedOpts, subCfg.name, subCfg.description) };
|
|
401
|
+
}
|
|
402
|
+
return { kind: 'agent', agent: await compileSubagentSpec(subCfg, opts) };
|
|
332
403
|
}));
|
|
404
|
+
const name = overrideName || config.orchestrator.name;
|
|
333
405
|
// Orchestrator tools are registry names only — no entrypoint has ever
|
|
334
406
|
// attached an MCP server to an orchestrator, and this compiler preserves
|
|
335
407
|
// that exactly rather than widening the contract in passing.
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
const
|
|
339
|
-
logCapabilities(opts,
|
|
340
|
-
return
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
408
|
+
const own = gateTools(await resolveAgentTools(config.orchestrator.tools, undefined, opts, config.orchestrator.openapi, config.orchestrator.examples), config.orchestrator.require_approval, name);
|
|
409
|
+
// The skills toolset goes last, after the delegations and the agent's own tools.
|
|
410
|
+
const { instruction, tools } = await withSkills(config.orchestrator.instruction, own, config.orchestrator.skills, name, opts);
|
|
411
|
+
logCapabilities(opts, name, config.orchestrator.model, config.orchestrator.tools);
|
|
412
|
+
return specOf(config.orchestrator, name, overrideDescription || config.orchestrator.description, instruction, [...delegated, ...asTools(tools)], opts);
|
|
413
|
+
}
|
|
414
|
+
// ── The ADK runtime's agents (lib/compileAdk.ts) ─────────────────────────────
|
|
415
|
+
/**
|
|
416
|
+
* Builds ONE runnable ADK agent from a subagent entry: its spec, as
|
|
417
|
+
* lib/compileAdk.ts builds it. A workflow node's settings
|
|
418
|
+
* (CompileOptions.nodeConfig) apply to a local agent, not to a nested
|
|
419
|
+
* syndicate's orchestrator.
|
|
420
|
+
*/
|
|
421
|
+
export async function compileSubagent(subCfg, opts = {}) {
|
|
422
|
+
const spec = await compileSubagentSpec(subCfg, opts);
|
|
423
|
+
return compileAdk(spec, opts, subCfg.yaml_reference ? {} : (opts.nodeConfig?.(subCfg.name) ?? {}));
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Compiles a syndicate's orchestrator for the ADK runtime. In DELEGATE mode
|
|
427
|
+
* its subagents are attached as AgentTools; in PLAN-DISPATCH mode it gets
|
|
428
|
+
* none, and the caller dispatches to `compileSubagent(route)` itself.
|
|
429
|
+
*/
|
|
430
|
+
export async function compileGraph(config, opts = {}, overrideName, overrideDescription) {
|
|
431
|
+
return compileAdk(await compileSpec(config, opts, overrideName, overrideDescription), opts);
|
|
351
432
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
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 nested workflow's whole Workflow too; a remote one as its
|
|
12
|
+
* A2A tool), Gemini's code executor, the
|
|
13
|
+
* context compactor, task mode and a workflow node's settings. Every field
|
|
14
|
+
* reaches LlmAgent as compileGraph and compileSubagent always passed it, so
|
|
15
|
+
* the ADK runtime runs the agent it ran before the split.
|
|
16
|
+
* lib/compileNative.ts builds the native loop's agent from the same spec.
|
|
17
|
+
*
|
|
18
|
+
* Imports from lib/compile.ts are types only. A nested workflow's Workflow
|
|
19
|
+
* comes from lib/workflow.ts (assembleWorkflow, ADR 0098), which imports
|
|
20
|
+
* lib/compile.ts; every use of either is inside a function, so the modules
|
|
21
|
+
* load in any order.
|
|
22
|
+
*/
|
|
23
|
+
import type { LlmAgent } from '@google/adk';
|
|
24
|
+
import type { AgentSpec, CompileOptions } from './compile.ts';
|
|
25
|
+
import { DEFAULT_KEEP_RECENT_EVENTS } from './runtime/native/compaction.ts';
|
|
26
|
+
/** Events kept verbatim after a compaction summary when `context:` names none: the native compactor's default. */
|
|
27
|
+
export { DEFAULT_KEEP_RECENT_EVENTS };
|
|
28
|
+
/**
|
|
29
|
+
* The LlmAgent for `spec`. `extra` is spread last: a workflow node's
|
|
30
|
+
* settings (CompileOptions.nodeConfig), which compileSubagent passes.
|
|
31
|
+
*/
|
|
32
|
+
export declare function compileAdk(spec: AgentSpec, opts?: CompileOptions, extra?: Record<string, unknown>): LlmAgent;
|
|
@@ -0,0 +1,142 @@
|
|
|
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 nested workflow's whole Workflow too; a remote one as its
|
|
12
|
+
* A2A tool), Gemini's code executor, the
|
|
13
|
+
* context compactor, task mode and a workflow node's settings. Every field
|
|
14
|
+
* reaches LlmAgent as compileGraph and compileSubagent always passed it, so
|
|
15
|
+
* the ADK runtime runs the agent it ran before the split.
|
|
16
|
+
* lib/compileNative.ts builds the native loop's agent from the same spec.
|
|
17
|
+
*
|
|
18
|
+
* Imports from lib/compile.ts are types only. A nested workflow's Workflow
|
|
19
|
+
* comes from lib/workflow.ts (assembleWorkflow, ADR 0098), which imports
|
|
20
|
+
* lib/compile.ts; every use of either is inside a function, so the modules
|
|
21
|
+
* load in any order.
|
|
22
|
+
*/
|
|
23
|
+
import { BaseLlm, adk, requireAdk } from './adkPeer.js';
|
|
24
|
+
import { remoteAgentTool } from './a2a/remoteAgent.js';
|
|
25
|
+
import { assembleWorkflow } from './workflow.js';
|
|
26
|
+
import { FallbackLlm } from './models/fallback.js';
|
|
27
|
+
import { resolveModel as resolveRegistryModel } from './models/registry.js';
|
|
28
|
+
import { onLogLevel } from './runtime/logging.js';
|
|
29
|
+
import { DEFAULT_KEEP_RECENT_EVENTS } from './runtime/native/compaction.js';
|
|
30
|
+
/**
|
|
31
|
+
* ADK's logger follows the engine's level (lib/runtime/logging.ts, ADR
|
|
32
|
+
* 0080), so a surface sets one level and never names ADK to quiet it.
|
|
33
|
+
*/
|
|
34
|
+
if (adk) {
|
|
35
|
+
const { LogLevel: Level, setLogLevel } = adk;
|
|
36
|
+
const levels = { debug: Level.DEBUG, info: Level.INFO, warn: Level.WARN, error: Level.ERROR };
|
|
37
|
+
onLogLevel((level) => setLogLevel(levels[level]));
|
|
38
|
+
}
|
|
39
|
+
/** What compileAdk builds needs @google/adk; without it, this names the package (ADR 0102). */
|
|
40
|
+
const FEATURE = 'Compiling an agent for the ADK runtime (MELCHIZEDEK_RUNTIME=adk, compileGraph, compileSubagent)';
|
|
41
|
+
/** Events kept verbatim after a compaction summary when `context:` names none: the native compactor's default. */
|
|
42
|
+
export { DEFAULT_KEEP_RECENT_EVENTS };
|
|
43
|
+
/**
|
|
44
|
+
* The LlmAgent fields a YAML agent may set beyond model, instruction, tools
|
|
45
|
+
* and schemas. The schema reference (config/agents/syndicateSchema.yaml)
|
|
46
|
+
* documents each as mapping 1:1 to its ADK counterpart. Only fields the YAML
|
|
47
|
+
* sets are passed, so ADK's defaults stay in force otherwise.
|
|
48
|
+
*/
|
|
49
|
+
function passthroughFields(spec) {
|
|
50
|
+
const out = {};
|
|
51
|
+
if (spec.includeContents !== undefined)
|
|
52
|
+
out.includeContents = spec.includeContents;
|
|
53
|
+
if (spec.outputKey !== undefined)
|
|
54
|
+
out.outputKey = spec.outputKey;
|
|
55
|
+
if (spec.globalInstruction !== undefined)
|
|
56
|
+
out.globalInstruction = spec.globalInstruction;
|
|
57
|
+
if (spec.disallowTransferToParent !== undefined)
|
|
58
|
+
out.disallowTransferToParent = spec.disallowTransferToParent;
|
|
59
|
+
if (spec.disallowTransferToPeers !== undefined)
|
|
60
|
+
out.disallowTransferToPeers = spec.disallowTransferToPeers;
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The LlmAgent fields the engine builds from YAML rather than passing
|
|
65
|
+
* through (ADR 0033): `code_execution: gemini` (Gemini's server-side
|
|
66
|
+
* sandbox runs the model's Python; nothing runs on this host), `context:`
|
|
67
|
+
* (ADK's token-based compactor with an LLM summarizer, so a long
|
|
68
|
+
* conversation is summarized instead of overflowing the window), and
|
|
69
|
+
* `mode: task` (the agent works until it calls finish_task; on a workflow
|
|
70
|
+
* node, its arguments become the node's output).
|
|
71
|
+
*/
|
|
72
|
+
function executionFields(cfg, opts) {
|
|
73
|
+
const { BuiltInCodeExecutor, LLMRegistry, LlmSummarizer, TokenBasedContextCompactor } = requireAdk(FEATURE);
|
|
74
|
+
const out = {};
|
|
75
|
+
if (cfg.codeExecution === 'gemini')
|
|
76
|
+
out.codeExecutor = new BuiltInCodeExecutor();
|
|
77
|
+
if (cfg.mode)
|
|
78
|
+
out.mode = cfg.mode;
|
|
79
|
+
if (cfg.context) {
|
|
80
|
+
const resolve = opts.resolveModel ?? ((m) => m);
|
|
81
|
+
const summaryModel = resolve(cfg.context.summary_model ?? cfg.model);
|
|
82
|
+
const llm = typeof summaryModel === 'string' || !summaryModel ? LLMRegistry.newLlm(String(summaryModel ?? cfg.model)) : summaryModel;
|
|
83
|
+
out.contextCompactors = [
|
|
84
|
+
new TokenBasedContextCompactor({
|
|
85
|
+
tokenThreshold: cfg.context.compact_after_tokens,
|
|
86
|
+
eventRetentionSize: cfg.context.keep_recent_events ?? DEFAULT_KEEP_RECENT_EVENTS,
|
|
87
|
+
summarizer: new LlmSummarizer({ llm }),
|
|
88
|
+
}),
|
|
89
|
+
];
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* An agent with `fallback_model:` gets its model wrapped (lib/models/fallback.ts):
|
|
95
|
+
* the fallback answers a provider-side failure, and a provider that keeps
|
|
96
|
+
* failing is skipped for a cooldown. A model id string is resolved to its
|
|
97
|
+
* adapter first, so the wrapper always holds two adapters.
|
|
98
|
+
*/
|
|
99
|
+
function withFallback(primary, fallbackId, opts) {
|
|
100
|
+
if (!fallbackId)
|
|
101
|
+
return primary;
|
|
102
|
+
const resolve = opts.resolveModel ?? ((m) => m);
|
|
103
|
+
const asLlm = (m) => (m instanceof BaseLlm ? m : resolveRegistryModel(String(m)));
|
|
104
|
+
return new FallbackLlm(asLlm(primary), asLlm(resolve(fallbackId)), opts.log ?? ((m) => console.warn(m)));
|
|
105
|
+
}
|
|
106
|
+
/** The spec's tools as LlmAgent takes them: a delegated subagent (a nested workflow's Workflow included) as an AgentTool, a remote one as its A2A tool. */
|
|
107
|
+
function adkTools(spec, opts) {
|
|
108
|
+
const { AgentTool } = requireAdk(FEATURE);
|
|
109
|
+
return spec.tools.map((entry) => {
|
|
110
|
+
switch (entry.kind) {
|
|
111
|
+
case 'tool':
|
|
112
|
+
return entry.tool;
|
|
113
|
+
case 'agent':
|
|
114
|
+
return new AgentTool({ agent: compileAdk(entry.agent, opts) });
|
|
115
|
+
case 'remote':
|
|
116
|
+
return remoteAgentTool({ name: entry.name, description: entry.description, url: entry.url });
|
|
117
|
+
case 'workflow':
|
|
118
|
+
// ADK's AgentTool runs any node its Runner takes, a Workflow included: the whole graph, its last event's text the answer (ADR 0098).
|
|
119
|
+
return new AgentTool({ agent: assembleWorkflow(entry.workflow, opts).workflow });
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The LlmAgent for `spec`. `extra` is spread last: a workflow node's
|
|
125
|
+
* settings (CompileOptions.nodeConfig), which compileSubagent passes.
|
|
126
|
+
*/
|
|
127
|
+
export function compileAdk(spec, opts = {}, extra = {}) {
|
|
128
|
+
const { LlmAgent } = requireAdk(FEATURE);
|
|
129
|
+
const tools = adkTools(spec, opts);
|
|
130
|
+
return new LlmAgent({
|
|
131
|
+
name: spec.name,
|
|
132
|
+
description: spec.description,
|
|
133
|
+
model: withFallback(spec.resolvedModel, spec.fallbackModel, opts),
|
|
134
|
+
instruction: spec.instruction,
|
|
135
|
+
tools: tools.length > 0 ? tools : undefined,
|
|
136
|
+
outputSchema: spec.outputSchema,
|
|
137
|
+
generateContentConfig: spec.generateContentConfig,
|
|
138
|
+
...passthroughFields(spec),
|
|
139
|
+
...executionFields(spec, opts),
|
|
140
|
+
...extra,
|
|
141
|
+
});
|
|
142
|
+
}
|