melchizedek-agents 1.0.0 → 1.0.2
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/CHANGELOG.md +53 -0
- package/DOCUMENTATION.md +11 -9
- package/config/agents/examples/critic.yaml +12 -7
- package/config/agents/examples/image_production.yaml +2 -2
- package/config/agents/examples/librarian.yaml +1 -1
- package/config/agents/examples/pipeline.yaml +1 -1
- package/config/agents/examples/research.yaml +3 -2
- package/config/agents/examples/scribe.yaml +5 -4
- package/config/agents/examples/weather.yaml +2 -1
- package/config/agents/syndicateSchema.yaml +18 -15
- package/dist/lib/dispatch.d.ts +4 -4
- package/dist/lib/dispatch.js +4 -4
- package/dist/lib/syndicateSchema.js +6 -6
- package/package.json +2 -2
- package/skills/briefs/melchizedek-author.md +1 -1
- package/skills/melchizedek-author/SKILL.md +1 -1
- package/skills/melchizedek-author/assets/minimal.yaml +1 -1
- package/dist/lib/adkPeer.d.ts +0 -63
- package/dist/lib/adkPeer.js +0 -240
- package/dist/lib/compileAdk.d.ts +0 -32
- package/dist/lib/compileAdk.js +0 -142
- package/dist/lib/models/adkGeminiAdapter.d.ts +0 -90
- package/dist/lib/models/adkGeminiAdapter.js +0 -369
- package/dist/lib/models/adkShim.d.ts +0 -111
- package/dist/lib/models/adkShim.js +0 -136
- package/dist/lib/models/claudeLlm.d.ts +0 -79
- package/dist/lib/models/claudeLlm.js +0 -87
- package/dist/lib/models/fallback.d.ts +0 -48
- package/dist/lib/models/fallback.js +0 -116
- package/dist/lib/models/gatewayLlm.d.ts +0 -36
- package/dist/lib/models/gatewayLlm.js +0 -44
- package/dist/lib/models/gptLlm.d.ts +0 -99
- package/dist/lib/models/gptLlm.js +0 -129
- package/dist/lib/models/grokLlm.d.ts +0 -50
- package/dist/lib/models/grokLlm.js +0 -56
- package/dist/lib/models/kimiLlm.d.ts +0 -31
- package/dist/lib/models/kimiLlm.js +0 -35
- package/dist/lib/models/ollamaLlm.d.ts +0 -37
- package/dist/lib/models/ollamaLlm.js +0 -42
- package/dist/lib/models/openAiCompatibleLlm.d.ts +0 -96
- package/dist/lib/models/openAiCompatibleLlm.js +0 -156
- package/dist/lib/models/tracedGemini.d.ts +0 -41
- package/dist/lib/models/tracedGemini.js +0 -98
- package/dist/lib/runtime/adkMemoryBridge.d.ts +0 -46
- package/dist/lib/runtime/adkMemoryBridge.js +0 -68
- package/dist/lib/runtime/adkSessionBridge.d.ts +0 -78
- package/dist/lib/runtime/adkSessionBridge.js +0 -176
- package/dist/lib/tools/adkTool.d.ts +0 -81
- package/dist/lib/tools/adkTool.js +0 -268
- package/dist/lib/tools/collectionsSearchTool.d.ts +0 -56
- package/dist/lib/tools/collectionsSearchTool.js +0 -71
- package/dist/lib/tools/urlContextTool.d.ts +0 -32
- package/dist/lib/tools/urlContextTool.js +0 -43
- package/dist/lib/tools/webSearchTool.d.ts +0 -51
- package/dist/lib/tools/webSearchTool.js +0 -82
- package/dist/lib/tools/xSearchTool.d.ts +0 -59
- package/dist/lib/tools/xSearchTool.js +0 -74
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/models/claudeLlm.ts — Anthropic Claude for the ADK LLMRegistry: the
|
|
3
|
-
* Claude adapter on the engine's contract (lib/models/claudeAdapter.ts)
|
|
4
|
-
* behind the ADK shim (lib/models/adkShim.ts).
|
|
5
|
-
*
|
|
6
|
-
* WHY this file exists:
|
|
7
|
-
* ADK's TypeScript line ships only Gemini models, but it takes any BaseLlm
|
|
8
|
-
* subclass registered with LLMRegistry, keyed by model-name patterns, so
|
|
9
|
-
* once registered every LlmAgent with model: "claude-*" routes here. The
|
|
10
|
-
* translation to the Messages API lives in ClaudeAdapter, which reads a
|
|
11
|
-
* ModelRequest and yields ModelResponses (ADR 0048). This class is the
|
|
12
|
-
* shim around it: the shim maps ADK's LlmRequest in and each response
|
|
13
|
-
* back, charges the turn and opens the llm.request span (ADR 0053).
|
|
14
|
-
*
|
|
15
|
-
* HOW TO ENABLE:
|
|
16
|
-
* 1. Install the Anthropic SDK:
|
|
17
|
-
* npm install @anthropic-ai/sdk
|
|
18
|
-
* 2. Add your API key to .env:
|
|
19
|
-
* ANTHROPIC_API_KEY=sk-ant-...
|
|
20
|
-
* 3. registerAvailableProviders() (lib/models/registry.ts) registers this
|
|
21
|
-
* class automatically when the key is set.
|
|
22
|
-
* 4. Set model: "claude-sonnet-4-6" (or any claude-* id) in your YAML.
|
|
23
|
-
*
|
|
24
|
-
* WHAT THIS CLASS ADDS TO THE SHIM: the agent's older reasoning spelling.
|
|
25
|
-
* The compiler writes `reasoning:` as generateContentConfig.thinkingConfig
|
|
26
|
-
* and reasoningEffort (ADR 0047), and an agent may set those directly. The
|
|
27
|
-
* contract's `reasoning` cannot say all of what ADR 0049 reads from them
|
|
28
|
-
* (the effort words `xhigh` and `max`, `minimal` as `low`, the budget rows
|
|
29
|
-
* reading the budget alone), so this class hands the adapter that reading
|
|
30
|
-
* as `claudeReasoning` (ADR 0055). Everything else is the shim's mapping.
|
|
31
|
-
*
|
|
32
|
-
* What the adapter does (thinking by model generation, signed blocks
|
|
33
|
-
* replayed within the tool loop, structured output, images, web search) is
|
|
34
|
-
* described in its header and in wiki/models/claude-adapter.md.
|
|
35
|
-
*/
|
|
36
|
-
import type { LlmRequest } from '@google/adk';
|
|
37
|
-
import { AdkShim } from './adkShim.ts';
|
|
38
|
-
import type { ClaudeModelRequest } from './claudeAdapter.ts';
|
|
39
|
-
import type { ProviderEndpoint } from './endpoints.ts';
|
|
40
|
-
import type { ModelRequestOptions } from './genaiMapping.ts';
|
|
41
|
-
export { THINKING_STATE_KIND } from './claudeAdapter.ts';
|
|
42
|
-
/**
|
|
43
|
-
* The tool definitions ClaudeLlm sends for an LlmRequest's toolsDict, before
|
|
44
|
-
* the platform is known: client tools with lowercase schemas, and the
|
|
45
|
-
* web_search sentinel as Anthropic's native server tool (AnthropicTool, from
|
|
46
|
-
* anthropicTools in lib/models/claudeAdapter.ts).
|
|
47
|
-
*/
|
|
48
|
-
export declare function buildAnthropicTools(llmRequest: LlmRequest): any[];
|
|
49
|
-
export declare class ClaudeLlm extends AdkShim {
|
|
50
|
-
/**
|
|
51
|
-
* Regex patterns that map model name strings to this provider.
|
|
52
|
-
* Any model: "claude-*" in a YAML config will route here after registration.
|
|
53
|
-
*/
|
|
54
|
-
static readonly supportedModels: Array<string | RegExp>;
|
|
55
|
-
/**
|
|
56
|
-
* `apiKey`: a caller's own key, which wins over the endpoint's and
|
|
57
|
-
* ANTHROPIC_API_KEY. `endpoint` (ADR 0023): where the request goes —
|
|
58
|
-
* Anthropic's API (or a proxy at its base URL), Bedrock, or Vertex AI.
|
|
59
|
-
* Default: the environment's (`ANTHROPIC_PLATFORM`).
|
|
60
|
-
*/
|
|
61
|
-
constructor({ model, apiKey, endpoint }: {
|
|
62
|
-
model: string;
|
|
63
|
-
apiKey?: string;
|
|
64
|
-
endpoint?: ProviderEndpoint;
|
|
65
|
-
});
|
|
66
|
-
/** The shim's ModelRequest, with the agent's older reasoning spelling read as ADR 0049 reads it (ADR 0055). */
|
|
67
|
-
protected toModelRequest(llmRequest: LlmRequest, options: ModelRequestOptions): ClaudeModelRequest;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Registers ClaudeLlm with the ADK LLMRegistry.
|
|
71
|
-
*
|
|
72
|
-
* WHY a separate function instead of auto-registering at import time:
|
|
73
|
-
* Auto-registration at module load would cause every consumer of this file
|
|
74
|
-
* to unconditionally register Claude, even if ANTHROPIC_API_KEY is absent.
|
|
75
|
-
* By making registration explicit, registerAvailableProviders() can
|
|
76
|
-
* conditionally call this only when the key is present, and log a clear
|
|
77
|
-
* message about which provider is active.
|
|
78
|
-
*/
|
|
79
|
-
export declare function registerClaudeLlm(): void;
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/models/claudeLlm.ts — Anthropic Claude for the ADK LLMRegistry: the
|
|
3
|
-
* Claude adapter on the engine's contract (lib/models/claudeAdapter.ts)
|
|
4
|
-
* behind the ADK shim (lib/models/adkShim.ts).
|
|
5
|
-
*
|
|
6
|
-
* WHY this file exists:
|
|
7
|
-
* ADK's TypeScript line ships only Gemini models, but it takes any BaseLlm
|
|
8
|
-
* subclass registered with LLMRegistry, keyed by model-name patterns, so
|
|
9
|
-
* once registered every LlmAgent with model: "claude-*" routes here. The
|
|
10
|
-
* translation to the Messages API lives in ClaudeAdapter, which reads a
|
|
11
|
-
* ModelRequest and yields ModelResponses (ADR 0048). This class is the
|
|
12
|
-
* shim around it: the shim maps ADK's LlmRequest in and each response
|
|
13
|
-
* back, charges the turn and opens the llm.request span (ADR 0053).
|
|
14
|
-
*
|
|
15
|
-
* HOW TO ENABLE:
|
|
16
|
-
* 1. Install the Anthropic SDK:
|
|
17
|
-
* npm install @anthropic-ai/sdk
|
|
18
|
-
* 2. Add your API key to .env:
|
|
19
|
-
* ANTHROPIC_API_KEY=sk-ant-...
|
|
20
|
-
* 3. registerAvailableProviders() (lib/models/registry.ts) registers this
|
|
21
|
-
* class automatically when the key is set.
|
|
22
|
-
* 4. Set model: "claude-sonnet-4-6" (or any claude-* id) in your YAML.
|
|
23
|
-
*
|
|
24
|
-
* WHAT THIS CLASS ADDS TO THE SHIM: the agent's older reasoning spelling.
|
|
25
|
-
* The compiler writes `reasoning:` as generateContentConfig.thinkingConfig
|
|
26
|
-
* and reasoningEffort (ADR 0047), and an agent may set those directly. The
|
|
27
|
-
* contract's `reasoning` cannot say all of what ADR 0049 reads from them
|
|
28
|
-
* (the effort words `xhigh` and `max`, `minimal` as `low`, the budget rows
|
|
29
|
-
* reading the budget alone), so this class hands the adapter that reading
|
|
30
|
-
* as `claudeReasoning` (ADR 0055). Everything else is the shim's mapping.
|
|
31
|
-
*
|
|
32
|
-
* What the adapter does (thinking by model generation, signed blocks
|
|
33
|
-
* replayed within the tool loop, structured output, images, web search) is
|
|
34
|
-
* described in its header and in wiki/models/claude-adapter.md.
|
|
35
|
-
*/
|
|
36
|
-
import { requireAdk } from '../adkPeer.js';
|
|
37
|
-
import { AdkShim } from './adkShim.js';
|
|
38
|
-
import { ClaudeAdapter, anthropicTools } from './claudeAdapter.js';
|
|
39
|
-
import { claudeReasoningFromConfig } from './claudeModels.js';
|
|
40
|
-
import { llmRequestToModelRequest } from './genaiMapping.js';
|
|
41
|
-
export { THINKING_STATE_KIND } from './claudeAdapter.js';
|
|
42
|
-
/**
|
|
43
|
-
* The tool definitions ClaudeLlm sends for an LlmRequest's toolsDict, before
|
|
44
|
-
* the platform is known: client tools with lowercase schemas, and the
|
|
45
|
-
* web_search sentinel as Anthropic's native server tool (AnthropicTool, from
|
|
46
|
-
* anthropicTools in lib/models/claudeAdapter.ts).
|
|
47
|
-
*/
|
|
48
|
-
export function buildAnthropicTools(llmRequest) {
|
|
49
|
-
return anthropicTools(llmRequestToModelRequest(llmRequest));
|
|
50
|
-
}
|
|
51
|
-
export class ClaudeLlm extends AdkShim {
|
|
52
|
-
/**
|
|
53
|
-
* Regex patterns that map model name strings to this provider.
|
|
54
|
-
* Any model: "claude-*" in a YAML config will route here after registration.
|
|
55
|
-
*/
|
|
56
|
-
static supportedModels = [/^claude-.+/];
|
|
57
|
-
/**
|
|
58
|
-
* `apiKey`: a caller's own key, which wins over the endpoint's and
|
|
59
|
-
* ANTHROPIC_API_KEY. `endpoint` (ADR 0023): where the request goes —
|
|
60
|
-
* Anthropic's API (or a proxy at its base URL), Bedrock, or Vertex AI.
|
|
61
|
-
* Default: the environment's (`ANTHROPIC_PLATFORM`).
|
|
62
|
-
*/
|
|
63
|
-
constructor({ model, apiKey, endpoint }) {
|
|
64
|
-
super(new ClaudeAdapter({ model, apiKey, endpoint }), { model });
|
|
65
|
-
}
|
|
66
|
-
/** The shim's ModelRequest, with the agent's older reasoning spelling read as ADR 0049 reads it (ADR 0055). */
|
|
67
|
-
toModelRequest(llmRequest, options) {
|
|
68
|
-
return {
|
|
69
|
-
...super.toModelRequest(llmRequest, options),
|
|
70
|
-
claudeReasoning: claudeReasoningFromConfig((llmRequest.config ?? {})),
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
// ── Registration helper ───────────────────────────────────────────────────────
|
|
75
|
-
/**
|
|
76
|
-
* Registers ClaudeLlm with the ADK LLMRegistry.
|
|
77
|
-
*
|
|
78
|
-
* WHY a separate function instead of auto-registering at import time:
|
|
79
|
-
* Auto-registration at module load would cause every consumer of this file
|
|
80
|
-
* to unconditionally register Claude, even if ANTHROPIC_API_KEY is absent.
|
|
81
|
-
* By making registration explicit, registerAvailableProviders() can
|
|
82
|
-
* conditionally call this only when the key is present, and log a clear
|
|
83
|
-
* message about which provider is active.
|
|
84
|
-
*/
|
|
85
|
-
export function registerClaudeLlm() {
|
|
86
|
-
requireAdk("Registering a model class with ADK's LLMRegistry").LLMRegistry.register(ClaudeLlm);
|
|
87
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/models/fallback.ts — a fallback model and a per-provider circuit
|
|
3
|
-
* breaker for an agent that declares `fallback_model:` (ADR 0044).
|
|
4
|
-
*
|
|
5
|
-
* WHY: lib/models/retry.ts makes one call survive a blip. It does nothing for
|
|
6
|
-
* an outage: every turn on a provider that is down spends its retries and
|
|
7
|
-
* fails. An agent that names a fallback model now answers from it instead,
|
|
8
|
-
* and a provider that keeps failing is skipped for a cooldown rather than
|
|
9
|
-
* tried on every turn.
|
|
10
|
-
*
|
|
11
|
-
* TWO WAYS A PRIMARY FAILS: Gemini throws; the other adapters yield an
|
|
12
|
-
* error response (`errorCode`) whose customMetadata['error.retryable'] carries
|
|
13
|
-
* retry.ts's verdict (lib/models/errorResponse.ts). Both are read here by
|
|
14
|
-
* the same rules.
|
|
15
|
-
*
|
|
16
|
-
* THE RULES:
|
|
17
|
-
* - Only provider-side failures count: what retry.ts classifies retryable
|
|
18
|
-
* (408/409/425/429/5xx, connection resets) once the adapter's own retries
|
|
19
|
-
* are spent. A 4xx is the request's fault and is thrown, or its error
|
|
20
|
-
* response passed on, as it is; a canceled turn is never counted or
|
|
21
|
-
* redirected.
|
|
22
|
-
* - The fallback runs only if the primary produced nothing yet: a stream
|
|
23
|
-
* that failed midway is thrown, or its error passed on, never replayed
|
|
24
|
-
* on another model. A redirected error response is never yielded.
|
|
25
|
-
* - Only a call that yielded content and no error counts as a success.
|
|
26
|
-
* - The breaker is per provider, shared by every agent in the process:
|
|
27
|
-
* MODEL_BREAKER_THRESHOLD consecutive failures (default 5; 0 disables)
|
|
28
|
-
* open it for MODEL_BREAKER_COOLDOWN_MS (default 30 s). While open, a
|
|
29
|
-
* wrapped agent goes straight to its fallback; after the cooldown calls
|
|
30
|
-
* go through again, the next failure reopens it at once, and a success
|
|
31
|
-
* closes it. Its state is lib/models/circuitBreaker.ts, which the
|
|
32
|
-
* contract-level wrapper (lib/models/fallbackAdapter.ts) shares.
|
|
33
|
-
*/
|
|
34
|
-
import { BaseLlm } from '../adkPeer.ts';
|
|
35
|
-
import type { BaseLlmConnection, LlmRequest, LlmResponse } from '@google/adk';
|
|
36
|
-
export { circuitOpen, resetCircuits } from './circuitBreaker.ts';
|
|
37
|
-
/** A provider-side failure: worth counting against the provider and worth a fallback. A cancellation never is. */
|
|
38
|
-
export declare function isProviderFailure(err: unknown): boolean;
|
|
39
|
-
export declare class FallbackLlm extends BaseLlm {
|
|
40
|
-
readonly primary: BaseLlm;
|
|
41
|
-
readonly fallback: BaseLlm;
|
|
42
|
-
private readonly log;
|
|
43
|
-
private readonly primaryProvider;
|
|
44
|
-
constructor(primary: BaseLlm, fallback: BaseLlm, log?: (m: string) => void);
|
|
45
|
-
generateContentAsync(llmRequest: LlmRequest, stream?: boolean, abortSignal?: AbortSignal): AsyncGenerator<LlmResponse, void>;
|
|
46
|
-
private onFallback;
|
|
47
|
-
connect(llmRequest: LlmRequest): Promise<BaseLlmConnection>;
|
|
48
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/models/fallback.ts — a fallback model and a per-provider circuit
|
|
3
|
-
* breaker for an agent that declares `fallback_model:` (ADR 0044).
|
|
4
|
-
*
|
|
5
|
-
* WHY: lib/models/retry.ts makes one call survive a blip. It does nothing for
|
|
6
|
-
* an outage: every turn on a provider that is down spends its retries and
|
|
7
|
-
* fails. An agent that names a fallback model now answers from it instead,
|
|
8
|
-
* and a provider that keeps failing is skipped for a cooldown rather than
|
|
9
|
-
* tried on every turn.
|
|
10
|
-
*
|
|
11
|
-
* TWO WAYS A PRIMARY FAILS: Gemini throws; the other adapters yield an
|
|
12
|
-
* error response (`errorCode`) whose customMetadata['error.retryable'] carries
|
|
13
|
-
* retry.ts's verdict (lib/models/errorResponse.ts). Both are read here by
|
|
14
|
-
* the same rules.
|
|
15
|
-
*
|
|
16
|
-
* THE RULES:
|
|
17
|
-
* - Only provider-side failures count: what retry.ts classifies retryable
|
|
18
|
-
* (408/409/425/429/5xx, connection resets) once the adapter's own retries
|
|
19
|
-
* are spent. A 4xx is the request's fault and is thrown, or its error
|
|
20
|
-
* response passed on, as it is; a canceled turn is never counted or
|
|
21
|
-
* redirected.
|
|
22
|
-
* - The fallback runs only if the primary produced nothing yet: a stream
|
|
23
|
-
* that failed midway is thrown, or its error passed on, never replayed
|
|
24
|
-
* on another model. A redirected error response is never yielded.
|
|
25
|
-
* - Only a call that yielded content and no error counts as a success.
|
|
26
|
-
* - The breaker is per provider, shared by every agent in the process:
|
|
27
|
-
* MODEL_BREAKER_THRESHOLD consecutive failures (default 5; 0 disables)
|
|
28
|
-
* open it for MODEL_BREAKER_COOLDOWN_MS (default 30 s). While open, a
|
|
29
|
-
* wrapped agent goes straight to its fallback; after the cooldown calls
|
|
30
|
-
* go through again, the next failure reopens it at once, and a success
|
|
31
|
-
* closes it. Its state is lib/models/circuitBreaker.ts, which the
|
|
32
|
-
* contract-level wrapper (lib/models/fallbackAdapter.ts) shares.
|
|
33
|
-
*/
|
|
34
|
-
import { BaseLlm } from '../adkPeer.js';
|
|
35
|
-
import { errorDecision, errorText, isRetryableErrorResponse } from './errorResponse.js';
|
|
36
|
-
import { providerForModel } from './providerMap.js';
|
|
37
|
-
import { circuitOpen, recordFailure, recordSuccess } from './circuitBreaker.js';
|
|
38
|
-
import { currentTurnSignal } from '../runtime/turnControl.js';
|
|
39
|
-
// The breaker's state lives in lib/models/circuitBreaker.ts, shared with the
|
|
40
|
-
// contract-level FallbackAdapter. Re-exported so existing imports keep working.
|
|
41
|
-
export { circuitOpen, resetCircuits } from './circuitBreaker.js';
|
|
42
|
-
/** A provider-side failure: worth counting against the provider and worth a fallback. A cancellation never is. */
|
|
43
|
-
export function isProviderFailure(err) {
|
|
44
|
-
return errorDecision(err).retryable;
|
|
45
|
-
}
|
|
46
|
-
/** A response that carries something the model produced. */
|
|
47
|
-
function hasContent(response) {
|
|
48
|
-
return (response.content?.parts?.length ?? 0) > 0;
|
|
49
|
-
}
|
|
50
|
-
/** The turn was canceled: by the signal ADK passes, or the turn's own. */
|
|
51
|
-
function canceled(abortSignal) {
|
|
52
|
-
return !!abortSignal?.aborted || !!currentTurnSignal()?.aborted;
|
|
53
|
-
}
|
|
54
|
-
export class FallbackLlm extends BaseLlm {
|
|
55
|
-
primary;
|
|
56
|
-
fallback;
|
|
57
|
-
log;
|
|
58
|
-
primaryProvider;
|
|
59
|
-
constructor(primary, fallback, log = (m) => console.warn(m)) {
|
|
60
|
-
super({ model: primary.model });
|
|
61
|
-
this.primary = primary;
|
|
62
|
-
this.fallback = fallback;
|
|
63
|
-
this.log = log;
|
|
64
|
-
this.primaryProvider = providerForModel(primary.model);
|
|
65
|
-
}
|
|
66
|
-
async *generateContentAsync(llmRequest, stream, abortSignal) {
|
|
67
|
-
if (circuitOpen(this.primaryProvider)) {
|
|
68
|
-
yield* this.onFallback(llmRequest, stream, abortSignal, `${this.primaryProvider} circuit is open`);
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
let yielded = false;
|
|
72
|
-
let answered = false;
|
|
73
|
-
let errored = false;
|
|
74
|
-
let redirect;
|
|
75
|
-
try {
|
|
76
|
-
for await (const r of this.primary.generateContentAsync(llmRequest, stream, abortSignal)) {
|
|
77
|
-
if (r.errorCode) {
|
|
78
|
-
errored = true;
|
|
79
|
-
if (!canceled(abortSignal) && isRetryableErrorResponse(r)) {
|
|
80
|
-
recordFailure(this.primaryProvider);
|
|
81
|
-
if (!yielded && !hasContent(r)) {
|
|
82
|
-
// Leaving the loop closes the primary's call before the fallback's opens.
|
|
83
|
-
redirect = `${this.primary.model} failed (${r.errorCode}: ${String(r.errorMessage ?? '').slice(0, 120)})`;
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
else if (hasContent(r)) {
|
|
89
|
-
answered = true;
|
|
90
|
-
}
|
|
91
|
-
yielded = true;
|
|
92
|
-
yield r;
|
|
93
|
-
}
|
|
94
|
-
if (answered && !errored)
|
|
95
|
-
recordSuccess(this.primaryProvider);
|
|
96
|
-
}
|
|
97
|
-
catch (err) {
|
|
98
|
-
if (canceled(abortSignal) || !isProviderFailure(err))
|
|
99
|
-
throw err;
|
|
100
|
-
recordFailure(this.primaryProvider);
|
|
101
|
-
if (yielded)
|
|
102
|
-
throw err;
|
|
103
|
-
redirect = `${this.primary.model} failed (${errorText(err).slice(0, 120)})`;
|
|
104
|
-
}
|
|
105
|
-
if (redirect)
|
|
106
|
-
yield* this.onFallback(llmRequest, stream, abortSignal, redirect);
|
|
107
|
-
}
|
|
108
|
-
async *onFallback(llmRequest, stream, abortSignal, why) {
|
|
109
|
-
this.log(`[models] ${why}; answering from ${this.fallback.model}.`);
|
|
110
|
-
const request = { ...llmRequest, model: this.fallback.model };
|
|
111
|
-
yield* this.fallback.generateContentAsync(request, stream, abortSignal);
|
|
112
|
-
}
|
|
113
|
-
connect(llmRequest) {
|
|
114
|
-
return this.primary.connect(llmRequest);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/models/gatewayLlm.ts — the one-key fallback, as an ADK BaseLlm.
|
|
3
|
-
*
|
|
4
|
-
* WHY this file exists:
|
|
5
|
-
* The transport's work is GatewayAdapter (lib/models/gatewayAdapter.ts),
|
|
6
|
-
* on the engine's own model contract: any cloud model id through a hosted
|
|
7
|
-
* gateway's chat-completions endpoint when the provider's direct key is
|
|
8
|
-
* absent (lib/models/gateway.ts owns that decision), attributed to the
|
|
9
|
-
* upstream provider, with every native tool dropped and reported. ADK
|
|
10
|
-
* still runs every turn, so this class runs the adapter under ADK: it is
|
|
11
|
-
* the chat-completions shim (lib/models/openAiCompatibleLlm.ts, ADR 0057).
|
|
12
|
-
* The constructor is what it was before the adapter moved onto the
|
|
13
|
-
* contract, so lib/models/registry.ts and every caller are unchanged.
|
|
14
|
-
*
|
|
15
|
-
* Registration: LLMRegistry keys on regex OBJECTS, so a gateway class must
|
|
16
|
-
* carry the SAME supportedModels instances as the direct adapter it stands
|
|
17
|
-
* in for (see gatewayClassFor below, and its use in registry.ts).
|
|
18
|
-
*/
|
|
19
|
-
import { OpenAiCompatibleLlm } from './openAiCompatibleLlm.ts';
|
|
20
|
-
export declare class GatewayLlm extends OpenAiCompatibleLlm {
|
|
21
|
-
/** Never registered directly — see gatewayClassFor(). */
|
|
22
|
-
static readonly supportedModels: Array<string | RegExp>;
|
|
23
|
-
/** The gateway (MODEL_GATEWAY and its key) is read from the environment when constructed. */
|
|
24
|
-
constructor({ model }: {
|
|
25
|
-
model: string;
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* A GatewayLlm subclass that answers for the given model patterns. Pass the
|
|
30
|
-
* direct adapter's OWN `supportedModels` array so the registry entry
|
|
31
|
-
* REPLACES that adapter's (the dict is keyed by regex object) rather than
|
|
32
|
-
* adding a second, shadowed match.
|
|
33
|
-
*/
|
|
34
|
-
export declare function gatewayClassFor(patterns: Array<string | RegExp>): typeof GatewayLlm;
|
|
35
|
-
/** Registers a gateway stand-in for the given patterns. */
|
|
36
|
-
export declare function registerGatewayLlm(patterns: Array<string | RegExp>): void;
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/models/gatewayLlm.ts — the one-key fallback, as an ADK BaseLlm.
|
|
3
|
-
*
|
|
4
|
-
* WHY this file exists:
|
|
5
|
-
* The transport's work is GatewayAdapter (lib/models/gatewayAdapter.ts),
|
|
6
|
-
* on the engine's own model contract: any cloud model id through a hosted
|
|
7
|
-
* gateway's chat-completions endpoint when the provider's direct key is
|
|
8
|
-
* absent (lib/models/gateway.ts owns that decision), attributed to the
|
|
9
|
-
* upstream provider, with every native tool dropped and reported. ADK
|
|
10
|
-
* still runs every turn, so this class runs the adapter under ADK: it is
|
|
11
|
-
* the chat-completions shim (lib/models/openAiCompatibleLlm.ts, ADR 0057).
|
|
12
|
-
* The constructor is what it was before the adapter moved onto the
|
|
13
|
-
* contract, so lib/models/registry.ts and every caller are unchanged.
|
|
14
|
-
*
|
|
15
|
-
* Registration: LLMRegistry keys on regex OBJECTS, so a gateway class must
|
|
16
|
-
* carry the SAME supportedModels instances as the direct adapter it stands
|
|
17
|
-
* in for (see gatewayClassFor below, and its use in registry.ts).
|
|
18
|
-
*/
|
|
19
|
-
import { requireAdk } from '../adkPeer.js';
|
|
20
|
-
import { GatewayAdapter } from './gatewayAdapter.js';
|
|
21
|
-
import { OpenAiCompatibleLlm } from './openAiCompatibleLlm.js';
|
|
22
|
-
export class GatewayLlm extends OpenAiCompatibleLlm {
|
|
23
|
-
/** Never registered directly — see gatewayClassFor(). */
|
|
24
|
-
static supportedModels = [];
|
|
25
|
-
/** The gateway (MODEL_GATEWAY and its key) is read from the environment when constructed. */
|
|
26
|
-
constructor({ model }) {
|
|
27
|
-
super(new GatewayAdapter({ model }), { model });
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* A GatewayLlm subclass that answers for the given model patterns. Pass the
|
|
32
|
-
* direct adapter's OWN `supportedModels` array so the registry entry
|
|
33
|
-
* REPLACES that adapter's (the dict is keyed by regex object) rather than
|
|
34
|
-
* adding a second, shadowed match.
|
|
35
|
-
*/
|
|
36
|
-
export function gatewayClassFor(patterns) {
|
|
37
|
-
return class GatewayLlmFor extends GatewayLlm {
|
|
38
|
-
static supportedModels = patterns;
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
/** Registers a gateway stand-in for the given patterns. */
|
|
42
|
-
export function registerGatewayLlm(patterns) {
|
|
43
|
-
requireAdk("Registering a model class with ADK's LLMRegistry").LLMRegistry.register(gatewayClassFor(patterns));
|
|
44
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/models/gptLlm.ts — OpenAI GPT for ADK's LLMRegistry: the ADK shim
|
|
3
|
-
* (lib/models/adkShim.ts) around GptAdapter (lib/models/gptAdapter.ts).
|
|
4
|
-
*
|
|
5
|
-
* WHY this file exists:
|
|
6
|
-
* Model optionality: any agent YAML with model: "gpt-*" (or an o-series id
|
|
7
|
-
* like "o4-mini") routes here after registration. The Responses API
|
|
8
|
-
* translation lives in GptAdapter, on the engine's own model contract
|
|
9
|
-
* (ADR 0048), so the native runtime can call it without ADK. GptLlm is
|
|
10
|
-
* what ADK registers and calls: the shim maps ADK's LlmRequest to a
|
|
11
|
-
* ModelRequest, charges the turn and opens the llm.request span once
|
|
12
|
-
* (ADR 0053), and maps each ModelResponse back. GrokLlm subclasses it.
|
|
13
|
-
*
|
|
14
|
-
* HOW TO ENABLE:
|
|
15
|
-
* 1. Install the SDK (already in package.json): npm install
|
|
16
|
-
* 2. Add your API key to .env: OPENAI_API_KEY=sk-...
|
|
17
|
-
* 3. Set model: "gpt-5-mini" (or any gpt-* / o-series id) in your YAML.
|
|
18
|
-
* registerAvailableProviders() registers this adapter when the key is set.
|
|
19
|
-
*
|
|
20
|
-
* WHAT IT KEEPS FROM THE ADK PATH (ADR 0056), beyond the shim's mapping:
|
|
21
|
-
* - Usage in the Responses meaning: `candidatesTokenCount` is
|
|
22
|
-
* `output_tokens`, reasoning included, so llm.tokens.output, the turn's
|
|
23
|
-
* token charge and the ledger count what they always counted for GPT and
|
|
24
|
-
* Grok. (The shim's mapping writes Gemini's meaning, reasoning excluded.)
|
|
25
|
-
* - The server-side tool calls (web_search, x_search…) as
|
|
26
|
-
* customMetadata['responses.server_tool_calls'] and the vendor's counters
|
|
27
|
-
* as ['responses.server_tool_usage'], which the root span turns into
|
|
28
|
-
* ToolCall events so adk_turns.tool_calls counts a searched answer.
|
|
29
|
-
* - groundingMetadata from the adapter's grounding, so the A2A server
|
|
30
|
-
* lists the answer's web sources, as it does for Gemini (owner's
|
|
31
|
-
* decision, 2026-10-08).
|
|
32
|
-
*
|
|
33
|
-
* The LlmRequest builders below (buildResponsesInput, buildResponsesTools)
|
|
34
|
-
* are the adapter's own, run on the LlmRequest mapped to the contract.
|
|
35
|
-
*/
|
|
36
|
-
import type { LlmRequest, LlmResponse } from '@google/adk';
|
|
37
|
-
import { AdkShim } from './adkShim.ts';
|
|
38
|
-
import type { ModelResponse } from './contract.ts';
|
|
39
|
-
import type { ProviderEndpoint } from './endpoints.ts';
|
|
40
|
-
import { GptAdapter } from './gptAdapter.ts';
|
|
41
|
-
import type { GptAdapterOptions, ReasoningReplay } from './gptAdapter.ts';
|
|
42
|
-
export { REASONING_STATE_KIND, extractServerToolCalls, serverToolUsage, streamEventDelta, } from './gptAdapter.ts';
|
|
43
|
-
export type { ServerToolCall } from './gptAdapter.ts';
|
|
44
|
-
/**
|
|
45
|
-
* ADK Contents → Responses API `input` items + `instructions` string: the
|
|
46
|
-
* LlmRequest mapped to the contract (lib/models/genaiMapping.ts), then
|
|
47
|
-
* GptAdapter's responsesInput. With `replay`, that provider's reasoning items
|
|
48
|
-
* for that model are sent back before their part's item, within the current
|
|
49
|
-
* turn's tool loop only (ADR 0050).
|
|
50
|
-
*/
|
|
51
|
-
export declare function buildResponsesInput(llmRequest: LlmRequest, replay?: ReasoningReplay): {
|
|
52
|
-
instructions: string | undefined;
|
|
53
|
-
input: any[];
|
|
54
|
-
};
|
|
55
|
-
/**
|
|
56
|
-
* ADK toolsDict (+ the native-tool sentinels) → Responses API tool
|
|
57
|
-
* definitions: the function tools, then the vendor's native tools, the
|
|
58
|
-
* request's model choosing the vendor (xAI's filters ride only on grok ids).
|
|
59
|
-
*/
|
|
60
|
-
export declare function buildResponsesTools(llmRequest: LlmRequest): any[];
|
|
61
|
-
/** GptLlm's constructor options: the adapter's (ADR 0023 for `endpoint`). */
|
|
62
|
-
export type GptLlmOptions = GptAdapterOptions;
|
|
63
|
-
export declare class GptLlm extends AdkShim {
|
|
64
|
-
/** gpt-* and o-series ids route here after registration. */
|
|
65
|
-
static readonly supportedModels: Array<string | RegExp>;
|
|
66
|
-
readonly adapter: GptAdapter;
|
|
67
|
-
/** The adapter a class builds for its options: GptAdapter here, GrokAdapter in GrokLlm. */
|
|
68
|
-
protected static createAdapter(options: GptLlmOptions): GptAdapter;
|
|
69
|
-
/**
|
|
70
|
-
* `endpoint` (ADR 0023): OpenAI's API (or a proxy at its base URL) or Azure
|
|
71
|
-
* OpenAI. Default: the environment's (`OPENAI_PLATFORM`).
|
|
72
|
-
*/
|
|
73
|
-
constructor(options: {
|
|
74
|
-
model: string;
|
|
75
|
-
apiKey?: string;
|
|
76
|
-
endpoint?: ProviderEndpoint;
|
|
77
|
-
});
|
|
78
|
-
/**
|
|
79
|
-
* The shim's mapping, with the Responses usage meaning and the server-side
|
|
80
|
-
* tool record the ADK path has always carried, and the grounding the
|
|
81
|
-
* mapping writes (see the header, ADR 0056).
|
|
82
|
-
*/
|
|
83
|
-
protected toLlmResponse(response: ModelResponse): LlmResponse;
|
|
84
|
-
/** The `reasoning` field this model sends for an LlmRequest's config (ADR 0047), as the adapter maps it. */
|
|
85
|
-
protected reasoningParam(llmRequest?: LlmRequest): Record<string, unknown> | undefined;
|
|
86
|
-
/**
|
|
87
|
-
* A Responses reply (non-delta) as the LlmResponses ADK sees: the reasoning
|
|
88
|
-
* summaries as one thought partial (unless `skipThoughts`), then the final,
|
|
89
|
-
* through the adapter's finalOf and this class's mapping.
|
|
90
|
-
*/
|
|
91
|
-
protected mapFinalResponse(response: any, opts?: {
|
|
92
|
-
skipThoughts?: boolean;
|
|
93
|
-
}): Generator<LlmResponse>;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Registers GptLlm with the ADK LLMRegistry. Called by
|
|
97
|
-
* registerAvailableProviders() when OPENAI_API_KEY is present.
|
|
98
|
-
*/
|
|
99
|
-
export declare function registerGptLlm(): void;
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* lib/models/gptLlm.ts — OpenAI GPT for ADK's LLMRegistry: the ADK shim
|
|
3
|
-
* (lib/models/adkShim.ts) around GptAdapter (lib/models/gptAdapter.ts).
|
|
4
|
-
*
|
|
5
|
-
* WHY this file exists:
|
|
6
|
-
* Model optionality: any agent YAML with model: "gpt-*" (or an o-series id
|
|
7
|
-
* like "o4-mini") routes here after registration. The Responses API
|
|
8
|
-
* translation lives in GptAdapter, on the engine's own model contract
|
|
9
|
-
* (ADR 0048), so the native runtime can call it without ADK. GptLlm is
|
|
10
|
-
* what ADK registers and calls: the shim maps ADK's LlmRequest to a
|
|
11
|
-
* ModelRequest, charges the turn and opens the llm.request span once
|
|
12
|
-
* (ADR 0053), and maps each ModelResponse back. GrokLlm subclasses it.
|
|
13
|
-
*
|
|
14
|
-
* HOW TO ENABLE:
|
|
15
|
-
* 1. Install the SDK (already in package.json): npm install
|
|
16
|
-
* 2. Add your API key to .env: OPENAI_API_KEY=sk-...
|
|
17
|
-
* 3. Set model: "gpt-5-mini" (or any gpt-* / o-series id) in your YAML.
|
|
18
|
-
* registerAvailableProviders() registers this adapter when the key is set.
|
|
19
|
-
*
|
|
20
|
-
* WHAT IT KEEPS FROM THE ADK PATH (ADR 0056), beyond the shim's mapping:
|
|
21
|
-
* - Usage in the Responses meaning: `candidatesTokenCount` is
|
|
22
|
-
* `output_tokens`, reasoning included, so llm.tokens.output, the turn's
|
|
23
|
-
* token charge and the ledger count what they always counted for GPT and
|
|
24
|
-
* Grok. (The shim's mapping writes Gemini's meaning, reasoning excluded.)
|
|
25
|
-
* - The server-side tool calls (web_search, x_search…) as
|
|
26
|
-
* customMetadata['responses.server_tool_calls'] and the vendor's counters
|
|
27
|
-
* as ['responses.server_tool_usage'], which the root span turns into
|
|
28
|
-
* ToolCall events so adk_turns.tool_calls counts a searched answer.
|
|
29
|
-
* - groundingMetadata from the adapter's grounding, so the A2A server
|
|
30
|
-
* lists the answer's web sources, as it does for Gemini (owner's
|
|
31
|
-
* decision, 2026-10-08).
|
|
32
|
-
*
|
|
33
|
-
* The LlmRequest builders below (buildResponsesInput, buildResponsesTools)
|
|
34
|
-
* are the adapter's own, run on the LlmRequest mapped to the contract.
|
|
35
|
-
*/
|
|
36
|
-
import { requireAdk } from '../adkPeer.js';
|
|
37
|
-
import { AdkShim } from './adkShim.js';
|
|
38
|
-
import { llmRequestToModelRequest, reasoningOf } from './genaiMapping.js';
|
|
39
|
-
import { GptAdapter, responsesFunctionTools, responsesInput, responsesServerTools } from './gptAdapter.js';
|
|
40
|
-
import { GrokAdapter } from './grokAdapter.js';
|
|
41
|
-
import { providerForModel } from './providerMap.js';
|
|
42
|
-
export { REASONING_STATE_KIND, extractServerToolCalls, serverToolUsage, streamEventDelta, } from './gptAdapter.js';
|
|
43
|
-
// ── The LlmRequest builders (the adapter's, on the mapped request) ───────────
|
|
44
|
-
/** The ModelRequest an LlmRequest maps to, for the request's own model id. */
|
|
45
|
-
function toModelRequest(llmRequest) {
|
|
46
|
-
return llmRequestToModelRequest(llmRequest, { model: llmRequest.model || 'unknown' });
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* ADK Contents → Responses API `input` items + `instructions` string: the
|
|
50
|
-
* LlmRequest mapped to the contract (lib/models/genaiMapping.ts), then
|
|
51
|
-
* GptAdapter's responsesInput. With `replay`, that provider's reasoning items
|
|
52
|
-
* for that model are sent back before their part's item, within the current
|
|
53
|
-
* turn's tool loop only (ADR 0050).
|
|
54
|
-
*/
|
|
55
|
-
export function buildResponsesInput(llmRequest, replay) {
|
|
56
|
-
const { instructions, input } = responsesInput(toModelRequest(llmRequest), replay);
|
|
57
|
-
return { instructions, input };
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* ADK toolsDict (+ the native-tool sentinels) → Responses API tool
|
|
61
|
-
* definitions: the function tools, then the vendor's native tools, the
|
|
62
|
-
* request's model choosing the vendor (xAI's filters ride only on grok ids).
|
|
63
|
-
*/
|
|
64
|
-
export function buildResponsesTools(llmRequest) {
|
|
65
|
-
const request = toModelRequest(llmRequest);
|
|
66
|
-
const adapter = providerForModel(request.model) === 'xai' ? new GrokAdapter({ model: request.model }) : new GptAdapter({ model: request.model });
|
|
67
|
-
return [...responsesFunctionTools(request), ...adapter.nativeToolPlan(request).tools];
|
|
68
|
-
}
|
|
69
|
-
export class GptLlm extends AdkShim {
|
|
70
|
-
/** gpt-* and o-series ids route here after registration. */
|
|
71
|
-
static supportedModels = [/^gpt-.+/, /^o[0-9].*/];
|
|
72
|
-
/** The adapter a class builds for its options: GptAdapter here, GrokAdapter in GrokLlm. */
|
|
73
|
-
static createAdapter(options) {
|
|
74
|
-
return new GptAdapter(options);
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* `endpoint` (ADR 0023): OpenAI's API (or a proxy at its base URL) or Azure
|
|
78
|
-
* OpenAI. Default: the environment's (`OPENAI_PLATFORM`).
|
|
79
|
-
*/
|
|
80
|
-
constructor(options) {
|
|
81
|
-
super(new.target.createAdapter(options), { model: options.model });
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* The shim's mapping, with the Responses usage meaning and the server-side
|
|
85
|
-
* tool record the ADK path has always carried, and the grounding the
|
|
86
|
-
* mapping writes (see the header, ADR 0056).
|
|
87
|
-
*/
|
|
88
|
-
toLlmResponse(response) {
|
|
89
|
-
const mapped = super.toLlmResponse(response);
|
|
90
|
-
if (response.partial)
|
|
91
|
-
return mapped;
|
|
92
|
-
const out = { ...mapped };
|
|
93
|
-
if (response.usage && out.usageMetadata) {
|
|
94
|
-
out.usageMetadata = { ...out.usageMetadata, candidatesTokenCount: response.usage.outputTokens };
|
|
95
|
-
}
|
|
96
|
-
const tools = responsesServerTools(response);
|
|
97
|
-
if (tools) {
|
|
98
|
-
out.customMetadata = {
|
|
99
|
-
...out.customMetadata,
|
|
100
|
-
...(tools.calls.length > 0 ? { 'responses.server_tool_calls': tools.calls } : {}),
|
|
101
|
-
...(Object.keys(tools.usage).length > 0 ? { 'responses.server_tool_usage': tools.usage } : {}),
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
return out;
|
|
105
|
-
}
|
|
106
|
-
/** The `reasoning` field this model sends for an LlmRequest's config (ADR 0047), as the adapter maps it. */
|
|
107
|
-
reasoningParam(llmRequest) {
|
|
108
|
-
return this.adapter.reasoningParam(reasoningOf(llmRequest?.config));
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* A Responses reply (non-delta) as the LlmResponses ADK sees: the reasoning
|
|
112
|
-
* summaries as one thought partial (unless `skipThoughts`), then the final,
|
|
113
|
-
* through the adapter's finalOf and this class's mapping.
|
|
114
|
-
*/
|
|
115
|
-
*mapFinalResponse(response, opts = {}) {
|
|
116
|
-
const { thinking, final } = this.adapter.finalOf(response, this.model, opts);
|
|
117
|
-
if (thinking)
|
|
118
|
-
yield this.toLlmResponse(thinking);
|
|
119
|
-
yield this.toLlmResponse(final);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
// ── Registration helper ───────────────────────────────────────────────────────
|
|
123
|
-
/**
|
|
124
|
-
* Registers GptLlm with the ADK LLMRegistry. Called by
|
|
125
|
-
* registerAvailableProviders() when OPENAI_API_KEY is present.
|
|
126
|
-
*/
|
|
127
|
-
export function registerGptLlm() {
|
|
128
|
-
requireAdk("Registering a model class with ADK's LLMRegistry").LLMRegistry.register(GptLlm);
|
|
129
|
-
}
|