@ggui-ai/ui-gen 0.8.0 → 0.10.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 +18 -1
- package/dist/adapters/generation-dispatch.js +819 -1577
- package/dist/adapters/generation-dispatch.js.map +1 -1
- package/dist/adapters/index.js +28 -11
- package/dist/adapters/index.js.map +1 -1
- package/dist/advanced/index.d.ts +5 -3
- package/dist/advanced/index.js +838 -1579
- package/dist/advanced/index.js.map +1 -1
- package/dist/blueprint-validator.js +109 -3
- package/dist/blueprint-validator.js.map +1 -1
- package/dist/boilerplate.js +17 -4
- package/dist/boilerplate.js.map +1 -1
- package/dist/check/index.d.ts +1 -1
- package/dist/check/index.js +11 -1
- package/dist/check/index.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-CF0EL0Li.d.ts} +26 -1
- package/dist/{dispatch-Deo9qzrG.d.ts → dispatch-D75M-OfZ.d.ts} +1 -1
- package/dist/evaluation/axis-checks/index.d.ts +3 -3
- package/dist/evaluation/axis-checks/index.js +133 -1
- package/dist/evaluation/axis-checks/index.js.map +1 -1
- package/dist/evaluation/axis-checks/registry.d.ts +1 -1
- package/dist/evaluation/axis-checks/registry.js +133 -1
- package/dist/evaluation/axis-checks/registry.js.map +1 -1
- package/dist/evaluation/index.d.ts +46 -3
- package/dist/evaluation/index.js +410 -24
- 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/check/runtime-render/index.d.ts +2 -2
- package/dist/harness/check/runtime-render/index.js +110 -3
- package/dist/harness/check/runtime-render/index.js.map +1 -1
- package/dist/harness/index.d.ts +5 -126
- package/dist/harness/index.js +292 -32
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/llm-trace-sink.d.ts +1 -1
- package/dist/harness/llm-trace-sink.js.map +1 -1
- package/dist/harness/prompts.js +17 -3
- package/dist/harness/prompts.js.map +1 -1
- package/dist/harness/result-types.d.ts +1 -1
- package/dist/harness/runtime.d.ts +17 -1
- package/dist/harness/runtime.js +23 -8
- package/dist/harness/runtime.js.map +1 -1
- package/dist/harness/types-public.d.ts +1 -1
- package/dist/harness/types-public.js +22 -9
- package/dist/harness/types-public.js.map +1 -1
- package/dist/harness/validator-trace-sink.d.ts +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +838 -1579
- package/dist/index.js.map +1 -1
- package/dist/llm-router-BEVtbAb9.d.ts +213 -0
- package/dist/patch.d.ts +1 -1
- package/dist/provider-adapter.d.ts +16 -6
- package/dist/provider-adapter.js.map +1 -1
- package/dist/providers/index.d.ts +54 -99
- package/dist/providers/index.js +13 -8
- package/dist/providers/index.js.map +1 -1
- package/dist/{render-check-CNZjHD5g.d.ts → render-check-BNYGVDJd.d.ts} +1 -1
- package/dist/{types-public-C36k1q6s.d.ts → types-public-DIpjC-OA.d.ts} +1 -1
- package/dist/validation/index.js +2 -2
- package/dist/validation/index.js.map +1 -1
- package/dist/workflows.d.ts +1 -1
- package/package.json +18 -18
- package/src/adapters/generation-dispatch.ts +28 -2
- package/src/adapters/openrouter/client.ts +2 -2
- package/src/adapters/openrouter/types.ts +10 -0
- package/src/boilerplate/generate.ts +10 -2
- package/src/boilerplate/json-schema-ts.ts +22 -2
- package/src/boilerplate/system-prompt.ts +4 -2
- package/src/compile.ts +1 -1
- package/src/contract-context.ts +10 -2
- package/src/create-ui-generator.ts +58 -11
- package/src/design-system-docs.ts +6 -4
- package/src/evaluation/axis-checks/checks/state-merge.ts +1 -1
- package/src/evaluation/axis-checks/checks/state-ui-affordance.ts +162 -0
- package/src/evaluation/axis-checks/checks/universal.ts +39 -0
- package/src/evaluation/axis-checks/registry.ts +2 -0
- package/src/evaluation/index.ts +11 -0
- package/src/evaluation/llm-evaluator.ts +26 -3
- package/src/evaluation/visual-evaluator.ts +49 -66
- package/src/fragments/realtime.ts +3 -3
- package/src/fragments/state.ts +2 -2
- package/src/harness/check/runtime-render/adapter.ts +18 -0
- package/src/harness/check/runtime-render/index.ts +8 -0
- package/src/harness/check/runtime-render/prepare-mockup.ts +14 -0
- package/src/harness/check/runtime-render/production-act-shim.ts +158 -0
- package/src/harness/check/runtime-render/render-check.ts +72 -1
- package/src/harness/coding/init-session.ts +4 -1
- package/src/harness/coding/run-eval-round.ts +67 -5
- package/src/harness/index.ts +1 -1
- package/src/harness/llm-router.ts +451 -27
- package/src/harness/llm-trace-sink.ts +2 -1
- package/src/harness/runtime.ts +15 -0
- package/src/index.ts +5 -5
- package/src/provider-adapter.ts +16 -6
- package/src/providers/bedrock.ts +89 -26
- package/src/providers/index.ts +16 -4
- package/src/tools/render-check.ts +19 -7
- package/src/validation/ui-compiler.ts +2 -2
package/src/provider-adapter.ts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Provider adapter contract — the narrow surface every concrete LLM
|
|
3
|
-
* provider client (Anthropic, Google, OpenAI, OpenRouter)
|
|
4
|
-
*
|
|
3
|
+
* provider client (Anthropic, Google, OpenAI, OpenRouter, Bedrock)
|
|
4
|
+
* implements.
|
|
5
|
+
*
|
|
6
|
+
* **Real role:** a provider-agnostic one-shot LLM caller for
|
|
7
|
+
* lightweight callers that need a single `complete()` round-trip — NOT
|
|
8
|
+
* a generation harness. The primary consumer is the negotiator's LLM
|
|
9
|
+
* seam (`@ggui-ai/mcp-server`'s `llm-backed-negotiator.ts`, via
|
|
10
|
+
* {@link selectAdapter} from `./providers/index.js`); other lightweight
|
|
11
|
+
* one-shot callers use it the same way. It is explicitly NOT part of
|
|
12
|
+
* the generation dispatch path: `createUiGenerator()` accepts no
|
|
13
|
+
* adapter option, and generation-call 429 retry/backoff lives entirely
|
|
14
|
+
* in `harness/llm-router.ts`'s `apiCall()` — a separate retry story for
|
|
15
|
+
* a separate call shape (an agentic SDK loop, not a single completion).
|
|
5
16
|
*
|
|
6
17
|
* The contract is deliberately defined independently of concrete
|
|
7
18
|
* adapters so:
|
|
@@ -9,10 +20,9 @@
|
|
|
9
20
|
* - Adapter implementations can be written against a stable surface —
|
|
10
21
|
* every concrete adapter MUST pass
|
|
11
22
|
* {@link providerAdapterContract} or it isn't a `ProviderAdapter`.
|
|
12
|
-
* - Downstream callers
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* UX.
|
|
23
|
+
* - Downstream one-shot callers build against ONE structured failure
|
|
24
|
+
* shape ({@link ProviderError}) instead of inventing per-provider
|
|
25
|
+
* error UX.
|
|
16
26
|
* - The negotiator + cache layers can branch on
|
|
17
27
|
* `error.kind === 'rate-limited'` etc. without parsing strings.
|
|
18
28
|
*
|
package/src/providers/bedrock.ts
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*
|
|
8
8
|
* ## Why this adapter exists
|
|
9
9
|
*
|
|
10
|
-
* Anyone running
|
|
11
|
-
* Lambda, EKS) can target Bedrock without managing API keys: IAM is
|
|
10
|
+
* Anyone running a one-shot LLM caller on an AWS-credentialed host
|
|
11
|
+
* (EC2, ECS, Lambda, EKS) can target Bedrock without managing API keys: IAM is
|
|
12
12
|
* the auth boundary, AWS rotates host credentials automatically, and
|
|
13
13
|
* a misconfigured IAM role surfaces as a clear `AccessDeniedException`
|
|
14
14
|
* the SDK funnels through `mapError`. The alternative — parking a
|
|
@@ -50,19 +50,29 @@
|
|
|
50
50
|
* discriminator if a third auth mode (e.g. cross-account assume-role)
|
|
51
51
|
* lands.
|
|
52
52
|
*
|
|
53
|
-
* ## Model IDs — pass-through
|
|
53
|
+
* ## Model IDs — pass-through, endpoint chosen by ID shape
|
|
54
54
|
*
|
|
55
|
-
* Bedrock
|
|
56
|
-
* model
|
|
55
|
+
* Bedrock serves Anthropic models through TWO endpoints with DISJOINT
|
|
56
|
+
* model-id namespaces (live-probed against us-east-1, 2026-08-13):
|
|
57
57
|
*
|
|
58
|
-
* -
|
|
59
|
-
*
|
|
60
|
-
*
|
|
58
|
+
* - **bedrock-runtime** (`AnthropicBedrock`): serves ONLY
|
|
59
|
+
* cross-region inference-profile ids —
|
|
60
|
+
* `us.anthropic.claude-haiku-4-5-20251001-v1:0` etc. Bare
|
|
61
|
+
* `anthropic.*` foundation ids are rejected with 400
|
|
62
|
+
* "on-demand throughput isn't supported".
|
|
63
|
+
* - **Messages-API endpoint / Mantle** (`AnthropicBedrockMantle`):
|
|
64
|
+
* serves ONLY region-less `anthropic.*` ids —
|
|
65
|
+
* `anthropic.claude-opus-5`, `anthropic.claude-haiku-4-5`. The
|
|
66
|
+
* Claude 5 family and Opus 4.8 exist ONLY here. Profile ids are
|
|
67
|
+
* rejected with 404. Requires the account to have enabled Claude
|
|
68
|
+
* in Amazon Bedrock (otherwise every id 403s "not available for
|
|
69
|
+
* this account").
|
|
61
70
|
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
71
|
+
* Because the namespaces never overlap, the adapter routes each
|
|
72
|
+
* request by shape: ids starting `anthropic.` go to Mantle, region-
|
|
73
|
+
* prefixed ids (`us.` / `eu.` / `apac.` / `global.`) go to
|
|
74
|
+
* bedrock-runtime. The id itself passes through untranslated —
|
|
75
|
+
* supply a Bedrock id, not a direct-API model name.
|
|
66
76
|
*
|
|
67
77
|
* ## Failure mapping
|
|
68
78
|
*
|
|
@@ -87,7 +97,7 @@
|
|
|
87
97
|
* subclasses in the SDK, distinguished by `.status` (403 / 429 / 400
|
|
88
98
|
* respectively).
|
|
89
99
|
*/
|
|
90
|
-
import { AnthropicBedrock } from '@anthropic-ai/bedrock-sdk';
|
|
100
|
+
import { AnthropicBedrock, AnthropicBedrockMantle } from '@anthropic-ai/bedrock-sdk';
|
|
91
101
|
import type { LlmProvider } from '@ggui-ai/mcp-server-core';
|
|
92
102
|
import {
|
|
93
103
|
makeProviderError,
|
|
@@ -110,6 +120,47 @@ import { classifyFetchError } from './http.js';
|
|
|
110
120
|
const PROVIDER: LlmProvider = 'bedrock';
|
|
111
121
|
const DEFAULT_MAX_TOKENS = 4096;
|
|
112
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Which Bedrock endpoint a model id resolves to. The namespaces are
|
|
125
|
+
* disjoint (see the docstring above), so the shape of the id fully
|
|
126
|
+
* determines the endpoint — no configuration knob needed.
|
|
127
|
+
*/
|
|
128
|
+
export type BedrockEndpoint = 'runtime' | 'mantle';
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Structural slice of the two SDK clients the adapter actually drives —
|
|
132
|
+
* the seam that lets tests inject a stub without standing up a real
|
|
133
|
+
* AWS client. Both `AnthropicBedrock` and `AnthropicBedrockMantle`
|
|
134
|
+
* satisfy it (the adapter's single-completion contract only ever calls
|
|
135
|
+
* non-streaming `messages.create`; the response is parsed from
|
|
136
|
+
* `unknown` by `parseAnthropicMessagesResponse`, so the SDK's
|
|
137
|
+
* version-volatile `Message` type is deliberately not part of the
|
|
138
|
+
* seam).
|
|
139
|
+
*/
|
|
140
|
+
export interface BedrockMessagesClient {
|
|
141
|
+
readonly messages: {
|
|
142
|
+
create(
|
|
143
|
+
body: {
|
|
144
|
+
model: string;
|
|
145
|
+
max_tokens: number;
|
|
146
|
+
system?: string;
|
|
147
|
+
messages: Array<{ role: 'user'; content: string }>;
|
|
148
|
+
},
|
|
149
|
+
options?: { signal?: AbortSignal },
|
|
150
|
+
): Promise<unknown>;
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Route a Bedrock model id to its serving endpoint. Region-less
|
|
156
|
+
* `anthropic.*` ids exist only on the Messages-API (Mantle) endpoint;
|
|
157
|
+
* everything else (region-prefixed inference profiles, ARNs) belongs
|
|
158
|
+
* to bedrock-runtime.
|
|
159
|
+
*/
|
|
160
|
+
export function bedrockEndpointFor(model: string): BedrockEndpoint {
|
|
161
|
+
return model.startsWith('anthropic.') ? 'mantle' : 'runtime';
|
|
162
|
+
}
|
|
163
|
+
|
|
113
164
|
/**
|
|
114
165
|
* Constructor options for the Bedrock adapter.
|
|
115
166
|
*
|
|
@@ -130,11 +181,16 @@ export interface BedrockAdapterOptions {
|
|
|
130
181
|
readonly region?: string;
|
|
131
182
|
/**
|
|
132
183
|
* Optional client factory override — used by tests to inject a
|
|
133
|
-
* mock or stub
|
|
134
|
-
*
|
|
135
|
-
*
|
|
184
|
+
* mock or stub client without actually hitting AWS. Called with the
|
|
185
|
+
* endpoint the request's model id routed to (`'runtime'` →
|
|
186
|
+
* `AnthropicBedrock`, `'mantle'` → `AnthropicBedrockMantle`).
|
|
187
|
+
* Production callers leave this unset; the adapter constructs the
|
|
188
|
+
* real client lazily on first `complete(...)` call per endpoint.
|
|
136
189
|
*/
|
|
137
|
-
readonly clientFactory?: (
|
|
190
|
+
readonly clientFactory?: (
|
|
191
|
+
region: string,
|
|
192
|
+
endpoint: BedrockEndpoint,
|
|
193
|
+
) => BedrockMessagesClient;
|
|
138
194
|
}
|
|
139
195
|
|
|
140
196
|
/**
|
|
@@ -142,21 +198,28 @@ export interface BedrockAdapterOptions {
|
|
|
142
198
|
*
|
|
143
199
|
* No API key — IAM is the auth boundary. The returned `ProviderAdapter`
|
|
144
200
|
* satisfies the same contract as `createAnthropicAdapter`, so it
|
|
145
|
-
* slots into
|
|
146
|
-
* the per-provider model-id namespace
|
|
201
|
+
* slots into any one-shot `ProviderAdapter` caller (e.g. `selectAdapter`)
|
|
202
|
+
* interchangeably (modulo the per-provider model-id namespace
|
|
203
|
+
* differences).
|
|
147
204
|
*/
|
|
148
205
|
export function createBedrockAdapter(
|
|
149
206
|
options: BedrockAdapterOptions = {},
|
|
150
207
|
): ProviderAdapter {
|
|
151
208
|
const region = options.region ?? process.env['AWS_REGION'] ?? 'us-east-1';
|
|
152
209
|
const clientFactory =
|
|
153
|
-
options.clientFactory ??
|
|
210
|
+
options.clientFactory ??
|
|
211
|
+
((r: string, endpoint: BedrockEndpoint): BedrockMessagesClient =>
|
|
212
|
+
endpoint === 'mantle'
|
|
213
|
+
? new AnthropicBedrockMantle({ awsRegion: r })
|
|
214
|
+
: new AnthropicBedrock({ awsRegion: r }));
|
|
154
215
|
|
|
155
|
-
|
|
156
|
-
function getClient():
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
216
|
+
const cachedClients: Partial<Record<BedrockEndpoint, BedrockMessagesClient>> = {};
|
|
217
|
+
function getClient(endpoint: BedrockEndpoint): BedrockMessagesClient {
|
|
218
|
+
const cached = cachedClients[endpoint];
|
|
219
|
+
if (cached) return cached;
|
|
220
|
+
const created = clientFactory(region, endpoint);
|
|
221
|
+
cachedClients[endpoint] = created;
|
|
222
|
+
return created;
|
|
160
223
|
}
|
|
161
224
|
|
|
162
225
|
function mapError(raw: unknown): ProviderError {
|
|
@@ -218,7 +281,7 @@ export function createBedrockAdapter(
|
|
|
218
281
|
};
|
|
219
282
|
}
|
|
220
283
|
|
|
221
|
-
const client = getClient();
|
|
284
|
+
const client = getClient(bedrockEndpointFor(request.route.model));
|
|
222
285
|
// The SDK's `Message` return type drifts between
|
|
223
286
|
// `@anthropic-ai/sdk` versions (pnpm hoists multiple copies in
|
|
224
287
|
// this workspace today). We type the captured value as
|
package/src/providers/index.ts
CHANGED
|
@@ -5,6 +5,15 @@
|
|
|
5
5
|
* providers ggui supports today: Anthropic (direct API), Google,
|
|
6
6
|
* OpenAI, OpenRouter, and AWS Bedrock (Anthropic models via IAM).
|
|
7
7
|
*
|
|
8
|
+
* **Real role:** a provider-agnostic one-shot LLM caller for
|
|
9
|
+
* lightweight callers that need a single `complete()` round-trip — NOT
|
|
10
|
+
* the generation dispatch path. `createUiGenerator()` accepts no
|
|
11
|
+
* adapter option; generation-call retry/backoff lives entirely in
|
|
12
|
+
* `harness/llm-router.ts`'s `apiCall()`. The primary consumer is the
|
|
13
|
+
* negotiator's LLM seam (`@ggui-ai/mcp-server`'s
|
|
14
|
+
* `llm-backed-negotiator.ts`, via {@link selectAdapter}); other
|
|
15
|
+
* lightweight one-shot callers use it the same way.
|
|
16
|
+
*
|
|
8
17
|
* Every adapter satisfies the structural
|
|
9
18
|
* {@link import('../provider-adapter.js').ProviderAdapter} contract.
|
|
10
19
|
* The four direct-API adapters compose
|
|
@@ -15,15 +24,18 @@
|
|
|
15
24
|
* because rolling our own AWS SigV4 signer for one provider isn't a
|
|
16
25
|
* reasonable trade.
|
|
17
26
|
*
|
|
18
|
-
* Typical usage
|
|
27
|
+
* Typical usage — a one-shot completion:
|
|
19
28
|
*
|
|
20
29
|
* ```ts
|
|
21
30
|
* import { createAnthropicAdapter } from '@ggui-ai/ui-gen/providers';
|
|
22
|
-
* import { createUiGenerator } from '@ggui-ai/ui-gen';
|
|
23
31
|
*
|
|
24
32
|
* const adapter = createAnthropicAdapter();
|
|
25
|
-
* const
|
|
26
|
-
*
|
|
33
|
+
* const result = await adapter.complete({
|
|
34
|
+
* apiKey,
|
|
35
|
+
* route: { provider: 'anthropic', model: 'claude-haiku-4-5-20251001' },
|
|
36
|
+
* systemPrompt,
|
|
37
|
+
* userPrompt,
|
|
38
|
+
* });
|
|
27
39
|
* ```
|
|
28
40
|
*
|
|
29
41
|
* Bedrock pool path (no API key — IAM at process boot):
|
|
@@ -28,7 +28,12 @@ import { existsSync } from 'node:fs';
|
|
|
28
28
|
import { createRequire } from 'node:module';
|
|
29
29
|
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
30
30
|
import { runSandboxed } from '@ggui-ai/sandbox';
|
|
31
|
-
import type {
|
|
31
|
+
import type {
|
|
32
|
+
JsonObject,
|
|
33
|
+
JsonSchema,
|
|
34
|
+
JsonValue,
|
|
35
|
+
PropsSpec,
|
|
36
|
+
} from '@ggui-ai/protocol';
|
|
32
37
|
|
|
33
38
|
/**
|
|
34
39
|
* Generate sample props from a PropsSpec contract.
|
|
@@ -58,21 +63,28 @@ export function generateSampleProps(spec: PropsSpec): JsonObject {
|
|
|
58
63
|
return props;
|
|
59
64
|
}
|
|
60
65
|
|
|
61
|
-
function synthesizeFromSchema(schema:
|
|
62
|
-
|
|
66
|
+
function synthesizeFromSchema(schema: JsonSchema): JsonValue | undefined {
|
|
67
|
+
// Draft-07 type arrays (`['string','null']`) synthesize from the
|
|
68
|
+
// first non-null member — the canonical nullability form the
|
|
69
|
+
// enforced-props-schema emission produces.
|
|
70
|
+
const declared = Array.isArray(schema.type)
|
|
71
|
+
? schema.type.find((t) => t !== 'null')
|
|
72
|
+
: schema.type;
|
|
73
|
+
switch (declared) {
|
|
63
74
|
case 'string': return 'sample';
|
|
64
|
-
case 'number':
|
|
75
|
+
case 'number':
|
|
76
|
+
case 'integer': return 0;
|
|
65
77
|
case 'boolean': return false;
|
|
78
|
+
case 'null': return null;
|
|
66
79
|
case 'array': {
|
|
67
|
-
|
|
68
|
-
if (itemSchema) return [synthesizeFromSchema(itemSchema) ?? null];
|
|
80
|
+
if (schema.items) return [synthesizeFromSchema(schema.items) ?? null];
|
|
69
81
|
return [];
|
|
70
82
|
}
|
|
71
83
|
case 'object': {
|
|
72
84
|
const obj: JsonObject = {};
|
|
73
85
|
if (schema.properties) {
|
|
74
86
|
for (const [k, v] of Object.entries(schema.properties)) {
|
|
75
|
-
obj[k] = synthesizeFromSchema(v
|
|
87
|
+
obj[k] = synthesizeFromSchema(v);
|
|
76
88
|
}
|
|
77
89
|
}
|
|
78
90
|
return obj;
|
|
@@ -64,8 +64,8 @@ const SANDBOX_EXTERNALS = [
|
|
|
64
64
|
'@ggui-ai/design/*',
|
|
65
65
|
'@ggui-ai/wire',
|
|
66
66
|
'@ggui-ai/wire/*',
|
|
67
|
-
'@ggui-ai/react',
|
|
68
|
-
'@ggui-ai/react/*',
|
|
67
|
+
'@ggui-ai/mcp-apps-react',
|
|
68
|
+
'@ggui-ai/mcp-apps-react/*',
|
|
69
69
|
];
|
|
70
70
|
|
|
71
71
|
/** Max compiled bundle size (2MB). Prevents accidentally bundling huge deps. */
|