@ggui-ai/ui-gen 0.7.0 → 0.9.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/dist/adapters/generation-dispatch.d.ts +10 -0
- package/dist/adapters/generation-dispatch.js +172 -1392
- package/dist/adapters/generation-dispatch.js.map +1 -1
- package/dist/advanced/index.d.ts +1 -1
- package/dist/advanced/index.js +191 -1403
- package/dist/advanced/index.js.map +1 -1
- package/dist/boilerplate.js +3 -2
- package/dist/boilerplate.js.map +1 -1
- package/dist/compose.js +5 -5
- package/dist/compose.js.map +1 -1
- package/dist/{create-ui-generator-GX7tvbyH.d.ts → create-ui-generator-B9kV4U9h.d.ts} +13 -0
- package/dist/evaluation/axis-checks/index.js +32 -1
- package/dist/evaluation/axis-checks/index.js.map +1 -1
- package/dist/evaluation/axis-checks/registry.js +32 -1
- package/dist/evaluation/axis-checks/registry.js.map +1 -1
- package/dist/evaluation/index.js +57 -12
- package/dist/evaluation/index.js.map +1 -1
- package/dist/fragments/index.js +5 -5
- package/dist/fragments/index.js.map +1 -1
- package/dist/harness/index.d.ts +4 -125
- package/dist/harness/index.js +34 -19
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/runtime.d.ts +9 -0
- package/dist/harness/runtime.js +3 -2
- package/dist/harness/runtime.js.map +1 -1
- package/dist/harness/types-public.js +8 -7
- package/dist/harness/types-public.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +191 -1403
- package/dist/index.js.map +1 -1
- package/dist/llm-router-1TyI0_TV.d.ts +156 -0
- package/dist/providers/index.d.ts +35 -93
- package/dist/providers/index.js +13 -8
- package/dist/providers/index.js.map +1 -1
- package/dist/validation/index.js +2 -2
- package/dist/validation/index.js.map +1 -1
- package/package.json +18 -18
- package/src/adapters/generation-dispatch.ts +19 -2
- package/src/boilerplate/system-prompt.ts +3 -2
- package/src/create-ui-generator.ts +44 -11
- package/src/evaluation/axis-checks/checks/state-merge.ts +1 -1
- package/src/evaluation/axis-checks/checks/universal.ts +39 -0
- package/src/evaluation/llm-evaluator.ts +13 -3
- package/src/evaluation/visual-evaluator.ts +5 -1
- package/src/fragments/realtime.ts +3 -3
- package/src/fragments/state.ts +2 -2
- package/src/harness/coding/init-session.ts +4 -1
- package/src/harness/coding/run-eval-round.ts +6 -0
- package/src/harness/llm-router.ts +59 -14
- package/src/harness/runtime.ts +8 -0
- package/src/providers/bedrock.ts +84 -22
- package/src/validation/ui-compiler.ts +2 -2
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { JsonObject } from '@ggui-ai/protocol';
|
|
2
|
+
import { LLMToolDef } from './llm.js';
|
|
3
|
+
|
|
4
|
+
interface AgentConfig {
|
|
5
|
+
provider: 'anthropic' | 'openai' | 'google' | 'openrouter';
|
|
6
|
+
model: string;
|
|
7
|
+
/**
|
|
8
|
+
* Sampling temperature. When defined it is threaded into the provider
|
|
9
|
+
* request; when undefined the provider default is used (unchanged
|
|
10
|
+
* behavior for all existing callers).
|
|
11
|
+
*/
|
|
12
|
+
temperature?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Explicit per-call credentials/routing, bypassing `process.env`
|
|
15
|
+
* entirely when supplied. Absent (default) preserves today's
|
|
16
|
+
* behavior — each agent falls back to reading its provider's env
|
|
17
|
+
* var(s) directly, so existing callers (including self-hosters who
|
|
18
|
+
* set env vars once at process start) are unaffected. Use this to
|
|
19
|
+
* run concurrent generations safely in one process: two simultaneous
|
|
20
|
+
* calls with different `routeOverride`s never race on shared
|
|
21
|
+
* `process.env` state.
|
|
22
|
+
*/
|
|
23
|
+
routeOverride?: {
|
|
24
|
+
readonly apiKey?: string;
|
|
25
|
+
/** Anthropic-only: force the Bedrock-IAM client instead of the direct API client. */
|
|
26
|
+
readonly useBedrock?: boolean;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
interface LLMResponse {
|
|
30
|
+
text: string;
|
|
31
|
+
inputTokens: number;
|
|
32
|
+
outputTokens: number;
|
|
33
|
+
}
|
|
34
|
+
interface LLMTool {
|
|
35
|
+
name: string;
|
|
36
|
+
description: string;
|
|
37
|
+
parameters: JsonObject;
|
|
38
|
+
handler: (args: JsonObject) => Promise<{
|
|
39
|
+
content: Array<{
|
|
40
|
+
text: string;
|
|
41
|
+
}>;
|
|
42
|
+
isError?: boolean;
|
|
43
|
+
}>;
|
|
44
|
+
}
|
|
45
|
+
interface LLMWithToolsResponse {
|
|
46
|
+
text: string;
|
|
47
|
+
inputTokens: number;
|
|
48
|
+
outputTokens: number;
|
|
49
|
+
turnsUsed: number;
|
|
50
|
+
}
|
|
51
|
+
interface LLMToolCall {
|
|
52
|
+
/** Provider-specific call ID (for sendToolResult) */
|
|
53
|
+
id?: string;
|
|
54
|
+
name: string;
|
|
55
|
+
input: JsonObject;
|
|
56
|
+
}
|
|
57
|
+
interface LLMToolCallResponse {
|
|
58
|
+
toolCalls: LLMToolCall[];
|
|
59
|
+
inputTokens: number;
|
|
60
|
+
outputTokens: number;
|
|
61
|
+
/**
|
|
62
|
+
* Tokens read from / written to the prompt cache, when the provider
|
|
63
|
+
* reports them. Optional because not every provider exposes
|
|
64
|
+
* prompt-cache accounting — absent means "unreported", never zero.
|
|
65
|
+
*/
|
|
66
|
+
cacheReadTokens?: number;
|
|
67
|
+
cacheCreationTokens?: number;
|
|
68
|
+
}
|
|
69
|
+
/** Result of executing a tool — passed to sendToolResult to close the API contract. */
|
|
70
|
+
interface LLMToolResult {
|
|
71
|
+
/** Tool call ID from the response (for providers that need it) */
|
|
72
|
+
callId?: string;
|
|
73
|
+
/** Tool name */
|
|
74
|
+
name: string;
|
|
75
|
+
/** Text result of executing the tool */
|
|
76
|
+
result: string;
|
|
77
|
+
/** Whether the tool execution failed */
|
|
78
|
+
isError?: boolean;
|
|
79
|
+
}
|
|
80
|
+
declare abstract class LLMAgent {
|
|
81
|
+
abstract readonly provider: AgentConfig['provider'];
|
|
82
|
+
private client;
|
|
83
|
+
protected lastSessionId: string | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Explicit per-call routing override — see `AgentConfig.routeOverride`.
|
|
86
|
+
* Absent when constructed via the bare `new XAgent()` form (every
|
|
87
|
+
* existing call site), so `createClient()`/`resolveModel()` fall
|
|
88
|
+
* back to `process.env` exactly as before.
|
|
89
|
+
*/
|
|
90
|
+
protected readonly routeOverride: AgentConfig['routeOverride'];
|
|
91
|
+
constructor(routeOverride?: AgentConfig['routeOverride']);
|
|
92
|
+
protected abstract resolveModel(model: string): string;
|
|
93
|
+
protected abstract createClient(): Promise<unknown>;
|
|
94
|
+
protected getClient<T>(): Promise<T>;
|
|
95
|
+
/** Text-only call — no tools */
|
|
96
|
+
abstract callText(model: string, systemPrompt: string, userPrompt: string, maxTokens?: number, temperature?: number): Promise<LLMResponse>;
|
|
97
|
+
/**
|
|
98
|
+
* Single-turn function calling — returns tool calls without executing them.
|
|
99
|
+
* Each provider uses its native function/tool calling:
|
|
100
|
+
* - Anthropic: tool_use blocks
|
|
101
|
+
* - OpenAI: function_call output items
|
|
102
|
+
* - Google: functionCall parts
|
|
103
|
+
* SDK handles JSON escaping — safe for code, diffs, and other content.
|
|
104
|
+
*/
|
|
105
|
+
abstract callTools(model: string, systemPrompt: string, userPrompt: string, tools: LLMToolDef[], toolChoice?: 'required' | 'auto',
|
|
106
|
+
/**
|
|
107
|
+
* Optional scoped fallback tools. If the primary tools fail with a
|
|
108
|
+
* transport-class error (e.g. `malformed_tool_call` on Gemini after
|
|
109
|
+
* retry exhaustion), the provider may retry once with these narrower
|
|
110
|
+
* tools before throwing. Universal signal — not provider-gated.
|
|
111
|
+
*/
|
|
112
|
+
scopedTools?: LLMToolDef[]): Promise<LLMToolCallResponse>;
|
|
113
|
+
/** Multi-turn agentic loop — executes tools internally */
|
|
114
|
+
abstract callWithTools(model: string, systemPrompt: string, userPrompt: string, tools: LLMTool[], maxTurns: number): Promise<LLMWithToolsResponse>;
|
|
115
|
+
/**
|
|
116
|
+
* Pre-warm cache for repeated callTools() calls with the same system prompt + tools.
|
|
117
|
+
* Override in providers that support server-side context caching (e.g., Google).
|
|
118
|
+
* No-op by default (Anthropic/OpenAI handle caching automatically per-request).
|
|
119
|
+
*/
|
|
120
|
+
warmCache(_model: string, _systemPrompt: string, _tools: LLMToolDef[], _toolChoice?: 'required' | 'auto'): Promise<void>;
|
|
121
|
+
/** Cleanup any cached resources. Call after generation completes. No-op by default. */
|
|
122
|
+
cleanup(): Promise<void>;
|
|
123
|
+
/** Reset session state between independent generation runs. */
|
|
124
|
+
resetSession(): void;
|
|
125
|
+
/**
|
|
126
|
+
* Send tool execution results back to the provider to close the API contract.
|
|
127
|
+
* Call this after executing tools from callTools() and before the next callTools().
|
|
128
|
+
*
|
|
129
|
+
* For providers with server-side state (Google, OpenAI), this sends the
|
|
130
|
+
* function results so the next callTools() can chain properly.
|
|
131
|
+
* For stateless providers (Anthropic), this is a no-op.
|
|
132
|
+
*
|
|
133
|
+
* Override in providers that need it.
|
|
134
|
+
*/
|
|
135
|
+
sendToolResult(_results: LLMToolResult[]): Promise<void>;
|
|
136
|
+
/**
|
|
137
|
+
* Execute an API call. No retry — if it fails, it fails.
|
|
138
|
+
* Logs the error with provider context and re-throws.
|
|
139
|
+
*/
|
|
140
|
+
protected apiCall<T>(fn: () => Promise<T>): Promise<T>;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Create a fresh agent instance for the given provider.
|
|
144
|
+
* Each call returns a new instance — no shared state between callers.
|
|
145
|
+
*
|
|
146
|
+
* Accepts either a bare provider string (every pre-existing call
|
|
147
|
+
* site — the agent falls back to reading its provider's env var(s)
|
|
148
|
+
* directly) or a full {@link AgentConfig}, whose `routeOverride`
|
|
149
|
+
* (when present) is threaded into the constructed agent so it never
|
|
150
|
+
* touches `process.env`.
|
|
151
|
+
*/
|
|
152
|
+
declare function createAgent(provider: AgentConfig['provider']): LLMAgent;
|
|
153
|
+
declare function createAgent(config: AgentConfig): LLMAgent;
|
|
154
|
+
declare function callLLM(config: AgentConfig, systemPrompt: string, userPrompt: string, maxTokens?: number): Promise<LLMResponse>;
|
|
155
|
+
|
|
156
|
+
export { type AgentConfig as A, type LLMResponse as L, createAgent as a, callLLM as c };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ProviderAdapter } from '../provider-adapter.js';
|
|
2
|
-
import { AnthropicBedrock } from '@anthropic-ai/bedrock-sdk';
|
|
3
2
|
import { LlmProvider } from '@ggui-ai/mcp-server-core';
|
|
4
3
|
import '@ggui-ai/protocol';
|
|
5
4
|
|
|
@@ -72,95 +71,36 @@ interface OpenRouterAdapterOptions {
|
|
|
72
71
|
declare function createOpenRouterAdapter(options?: OpenRouterAdapterOptions): ProviderAdapter;
|
|
73
72
|
|
|
74
73
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* chain (IRSA pod token / `~/.aws/credentials` / env vars) supplies
|
|
79
|
-
* SigV4 signatures automatically.
|
|
80
|
-
*
|
|
81
|
-
* ## Why this adapter exists
|
|
82
|
-
*
|
|
83
|
-
* Anyone running the generator on an AWS-credentialed host (EC2, ECS,
|
|
84
|
-
* Lambda, EKS) can target Bedrock without managing API keys: IAM is
|
|
85
|
-
* the auth boundary, AWS rotates host credentials automatically, and
|
|
86
|
-
* a misconfigured IAM role surfaces as a clear `AccessDeniedException`
|
|
87
|
-
* the SDK funnels through `mapError`. The alternative — parking a
|
|
88
|
-
* provider API key in a secrets store and lazily fetching it on first
|
|
89
|
-
* render — works but adds operational surface (a seed ceremony,
|
|
90
|
-
* key-rotation discipline, a misconfig mode where the secret is
|
|
91
|
-
* empty); Bedrock removes all of it.
|
|
92
|
-
*
|
|
93
|
-
* ## Wire shape
|
|
94
|
-
*
|
|
95
|
-
* The Bedrock SDK's `client.messages.create(...)` mirrors the direct
|
|
96
|
-
* Anthropic API surface 1:1 — same request body fields (`model`,
|
|
97
|
-
* `max_tokens`, `system`, `messages`), same response shape (`content[]`
|
|
98
|
-
* with `{type:'text', text}` blocks, `stop_reason`, `usage`). Both
|
|
99
|
-
* adapters therefore share ONE success-envelope parser —
|
|
100
|
-
* {@link parseAnthropicMessagesResponse} in `./anthropic-wire.ts`.
|
|
101
|
-
* Streaming is supported by the SDK
|
|
102
|
-
* (`client.messages.stream(...)` returns an async iterable) but this
|
|
103
|
-
* adapter uses the non-streaming `create(...)` call to match the
|
|
104
|
-
* single-completion {@link ProviderAdapter} contract; higher layers
|
|
105
|
-
* (`UiGenerator`) compose multi-turn loops above the seam.
|
|
106
|
-
*
|
|
107
|
-
* ## Auth — no API key in `ProviderRequest`
|
|
108
|
-
*
|
|
109
|
-
* The {@link ProviderAdapter} contract types `ProviderRequest.apiKey`
|
|
110
|
-
* as a required string because direct API providers need it on the
|
|
111
|
-
* wire. Bedrock doesn't — the SDK signs requests with AWS credentials
|
|
112
|
-
* resolved at process boot. Two compatible options were considered:
|
|
113
|
-
*
|
|
114
|
-
* 1. Add an `auth: 'apiKey' | 'iam'` discriminator to
|
|
115
|
-
* `ProviderAdapter` + thread it through every adapter.
|
|
116
|
-
* 2. Override `validateConfig` so this adapter accepts (and ignores)
|
|
117
|
-
* whatever the caller puts in `apiKey` — `'iam'` / sentinel /
|
|
118
|
-
* empty string all pass.
|
|
119
|
-
*
|
|
120
|
-
* Option 2 wins on cost: ZERO callers, contract, or tests change.
|
|
121
|
-
* Callers pass a sentinel (e.g. `'bedrock-iam'`) so the model-id
|
|
122
|
-
* check still gates on a non-empty value. Future work could add the
|
|
123
|
-
* discriminator if a third auth mode (e.g. cross-account assume-role)
|
|
124
|
-
* lands.
|
|
125
|
-
*
|
|
126
|
-
* ## Model IDs — pass-through
|
|
127
|
-
*
|
|
128
|
-
* Bedrock and the direct Anthropic API use OVERLAPPING but DISTINCT
|
|
129
|
-
* model id namespaces:
|
|
130
|
-
*
|
|
131
|
-
* - Direct API: `claude-haiku-4-5`, `claude-opus-4-7`, etc.
|
|
132
|
-
* - Bedrock foundation models: `anthropic.claude-sonnet-4-6`
|
|
133
|
-
* - Bedrock cross-region inference profiles: `us.anthropic.claude-haiku-4-5-20251001-v1:0`
|
|
134
|
-
*
|
|
135
|
-
* The adapter passes whatever `request.model` contains straight to
|
|
136
|
-
* Bedrock — translation lives in the caller (model picker / deployment
|
|
137
|
-
* config). Supply a Bedrock foundation-model or inference-profile id,
|
|
138
|
-
* not a direct-API model name.
|
|
139
|
-
*
|
|
140
|
-
* ## Failure mapping
|
|
141
|
-
*
|
|
142
|
-
* The bedrock-sdk throws `APIError` subclasses (`AuthenticationError`,
|
|
143
|
-
* `PermissionDeniedError`, `RateLimitError`, `InternalServerError`,
|
|
144
|
-
* etc.) that all carry a numeric `.status` property. We classify them
|
|
145
|
-
* by structural duck-typing (`typeof err.status === 'number'`) rather
|
|
146
|
-
* than `instanceof Anthropic.APIError` because pnpm hoisting often
|
|
147
|
-
* resolves multiple `@anthropic-ai/sdk` versions across the workspace
|
|
148
|
-
* — the bedrock-sdk's nested SDK and ui-gen's direct SDK can diverge,
|
|
149
|
-
* and `instanceof` then silently returns false for valid errors.
|
|
150
|
-
* Duck-typing on `.status` is robust to that drift and matches the
|
|
151
|
-
* SDK's documented API contract (every subclass exposes `.status`).
|
|
152
|
-
*
|
|
153
|
-
* Transport-shaped errors (`APIConnectionError`, `APIUserAbortError`)
|
|
154
|
-
* carry NO status — they fall through to {@link classifyFetchError}
|
|
155
|
-
* for the standard `network` / `aborted` mapping.
|
|
156
|
-
*
|
|
157
|
-
* AWS-specific failure modes (`AccessDeniedException` — wrong IAM
|
|
158
|
-
* grants; `ThrottlingException` — Bedrock rate limit;
|
|
159
|
-
* `ValidationException` — bad model id) all surface as `APIError`
|
|
160
|
-
* subclasses in the SDK, distinguished by `.status` (403 / 429 / 400
|
|
161
|
-
* respectively).
|
|
74
|
+
* Which Bedrock endpoint a model id resolves to. The namespaces are
|
|
75
|
+
* disjoint (see the docstring above), so the shape of the id fully
|
|
76
|
+
* determines the endpoint — no configuration knob needed.
|
|
162
77
|
*/
|
|
163
|
-
|
|
78
|
+
type BedrockEndpoint = 'runtime' | 'mantle';
|
|
79
|
+
/**
|
|
80
|
+
* Structural slice of the two SDK clients the adapter actually drives —
|
|
81
|
+
* the seam that lets tests inject a stub without standing up a real
|
|
82
|
+
* AWS client. Both `AnthropicBedrock` and `AnthropicBedrockMantle`
|
|
83
|
+
* satisfy it (the adapter's single-completion contract only ever calls
|
|
84
|
+
* non-streaming `messages.create`; the response is parsed from
|
|
85
|
+
* `unknown` by `parseAnthropicMessagesResponse`, so the SDK's
|
|
86
|
+
* version-volatile `Message` type is deliberately not part of the
|
|
87
|
+
* seam).
|
|
88
|
+
*/
|
|
89
|
+
interface BedrockMessagesClient {
|
|
90
|
+
readonly messages: {
|
|
91
|
+
create(body: {
|
|
92
|
+
model: string;
|
|
93
|
+
max_tokens: number;
|
|
94
|
+
system?: string;
|
|
95
|
+
messages: Array<{
|
|
96
|
+
role: 'user';
|
|
97
|
+
content: string;
|
|
98
|
+
}>;
|
|
99
|
+
}, options?: {
|
|
100
|
+
signal?: AbortSignal;
|
|
101
|
+
}): Promise<unknown>;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
164
104
|
/**
|
|
165
105
|
* Constructor options for the Bedrock adapter.
|
|
166
106
|
*
|
|
@@ -181,11 +121,13 @@ interface BedrockAdapterOptions {
|
|
|
181
121
|
readonly region?: string;
|
|
182
122
|
/**
|
|
183
123
|
* Optional client factory override — used by tests to inject a
|
|
184
|
-
* mock or stub
|
|
185
|
-
*
|
|
186
|
-
*
|
|
124
|
+
* mock or stub client without actually hitting AWS. Called with the
|
|
125
|
+
* endpoint the request's model id routed to (`'runtime'` →
|
|
126
|
+
* `AnthropicBedrock`, `'mantle'` → `AnthropicBedrockMantle`).
|
|
127
|
+
* Production callers leave this unset; the adapter constructs the
|
|
128
|
+
* real client lazily on first `complete(...)` call per endpoint.
|
|
187
129
|
*/
|
|
188
|
-
readonly clientFactory?: (region: string) =>
|
|
130
|
+
readonly clientFactory?: (region: string, endpoint: BedrockEndpoint) => BedrockMessagesClient;
|
|
189
131
|
}
|
|
190
132
|
/**
|
|
191
133
|
* Construct an AWS Bedrock provider adapter.
|
package/dist/providers/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AnthropicBedrock } from '@anthropic-ai/bedrock-sdk';
|
|
1
|
+
import { AnthropicBedrockMantle, AnthropicBedrock } from '@anthropic-ai/bedrock-sdk';
|
|
2
2
|
|
|
3
3
|
// src/provider-adapter.ts
|
|
4
4
|
function makeProviderError(args) {
|
|
@@ -609,14 +609,19 @@ function createOpenRouterAdapter(options = {}) {
|
|
|
609
609
|
}
|
|
610
610
|
var PROVIDER5 = "bedrock";
|
|
611
611
|
var DEFAULT_MAX_TOKENS2 = 4096;
|
|
612
|
+
function bedrockEndpointFor(model) {
|
|
613
|
+
return model.startsWith("anthropic.") ? "mantle" : "runtime";
|
|
614
|
+
}
|
|
612
615
|
function createBedrockAdapter(options = {}) {
|
|
613
616
|
const region = options.region ?? process.env["AWS_REGION"] ?? "us-east-1";
|
|
614
|
-
const clientFactory = options.clientFactory ?? ((r) => new AnthropicBedrock({ awsRegion: r }));
|
|
615
|
-
|
|
616
|
-
function getClient() {
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
617
|
+
const clientFactory = options.clientFactory ?? ((r, endpoint) => endpoint === "mantle" ? new AnthropicBedrockMantle({ awsRegion: r }) : new AnthropicBedrock({ awsRegion: r }));
|
|
618
|
+
const cachedClients = {};
|
|
619
|
+
function getClient(endpoint) {
|
|
620
|
+
const cached = cachedClients[endpoint];
|
|
621
|
+
if (cached) return cached;
|
|
622
|
+
const created = clientFactory(region, endpoint);
|
|
623
|
+
cachedClients[endpoint] = created;
|
|
624
|
+
return created;
|
|
620
625
|
}
|
|
621
626
|
function mapError(raw) {
|
|
622
627
|
if (raw && typeof raw === "object" && "status" in raw) {
|
|
@@ -667,7 +672,7 @@ function createBedrockAdapter(options = {}) {
|
|
|
667
672
|
error: classifyFetchError(null, PROVIDER5, request.signal)
|
|
668
673
|
};
|
|
669
674
|
}
|
|
670
|
-
const client = getClient();
|
|
675
|
+
const client = getClient(bedrockEndpointFor(request.route.model));
|
|
671
676
|
let raw;
|
|
672
677
|
try {
|
|
673
678
|
raw = await client.messages.create(
|