@ggui-ai/cli 0.1.0-rc.1 → 0.2.0-alpha.1

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/README.md CHANGED
@@ -44,8 +44,8 @@ ggui serve --mcp-only # skip agent supervision
44
44
  **Scope today:**
45
45
 
46
46
  - ✅ Local server, viewer, cookie-authenticated WebSocket subscribe/ack all work end-to-end.
47
- - ✅ `ggui_push` mints shortCodes and lands on the same-origin viewer.
48
- - ✅ Component-code generation is wired on the OSS path via `createUiGenerator()` from `@ggui-ai/ui-gen` — the same harness the hosted runtime uses. `ggui_push` returns `codeReady: false` only when no BYOK credentials resolve (no `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / etc.); supply a key to get full generation locally.
47
+ - ✅ `ggui_render` mints shortCodes and lands on the same-origin viewer.
48
+ - ✅ Component-code generation is wired on the OSS path via `createUiGenerator()` from `@ggui-ai/ui-gen` — the same harness the hosted runtime uses. `ggui_render` returns `codeReady: false` only when no BYOK credentials resolve (no `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / etc.); supply a key to get full generation locally.
49
49
  - 🔒 Default auth is dev-mode (any bearer → `builder`). Swap in a real `AuthAdapter` via `createGguiServer({ auth })` before exposing beyond `127.0.0.1`.
50
50
 
51
51
  ### `ggui dev`
package/dist/cli.js CHANGED
@@ -14,16 +14,16 @@ import { discoverLocalUis, discoverMcpMounts, discoverPrimitives, GguiJsonLoadEr
14
14
  import { resolveAgentPlan } from './serve-fallback.js';
15
15
  import { buildAgentRuntime, describeTunnelSession, launchBrowser, openTunnel, parseDevFlags, resolveAgentCommand, resolveHubUrl, shouldAutoOpen, } from './dev-command.js';
16
16
  import { createNullTunnelProvider, discoverTunnelProvider, } from './tunnel-provider.js';
17
- import { ManifestBlueprintProvider, resolveStorageFromConfig, buildNoCredentialsStackItem, } from '@ggui-ai/mcp-server';
17
+ import { ManifestBlueprintProvider, resolveStorageFromConfig, buildNoCredentialsRender, } from '@ggui-ai/mcp-server';
18
18
  import { InMemoryBlueprintProvider } from '@ggui-ai/mcp-server-core/in-memory';
19
19
  import { createByokResolver } from './byok-resolver.js';
20
20
  import { isInstalledBlueprintPath } from './internal/artifact-install.js';
21
- import { describeGenerationBinding, probeGenerationBinding, } from './generation-probe.js';
21
+ import { DEFAULT_ROUTE_BY_PROVIDER, describeGenerationBinding, probeGenerationBinding, } from './generation-probe.js';
22
22
  import { buildMcpServerBackend, pickFreePort } from './mcp-backend.js';
23
23
  import { createThemeWriter } from './theme-writer.js';
24
24
  import { createThemeFileUploader } from './theme-file-uploader.js';
25
25
  import { getPersistentDir } from './paths.js';
26
- import { createPersistentSessionStore, createPersistentVectorStore, } from './persistent-stores.js';
26
+ import { createPersistentRenderStore, createPersistentVectorStore, } from './persistent-stores.js';
27
27
  import { parseServeFlags, runServe, SERVE_HELP, } from './serve-command.js';
28
28
  import { runLoginCommand } from './auth-login.js';
29
29
  import { runLogoutCommand } from './auth-logout.js';
@@ -211,7 +211,7 @@ async function runServeCommand(args) {
211
211
  // Resolve `ggui.json#storage` → concrete adapters BEFORE binding.
212
212
  // Absent storage block → empty bundle → server keeps in-memory
213
213
  // defaults. Sqlite paths resolve relative to the manifest directory
214
- // (not CWD) so `"path": "./ggui-sessions.sqlite"` lands next to
214
+ // (not CWD) so `"path": "./ggui-renders.sqlite"` lands next to
215
215
  // `ggui.json` regardless of where the operator invoked `ggui serve`
216
216
  // from. Failure to instantiate (e.g. better-sqlite3 peer dep
217
217
  // missing, permission denied) propagates to the exit-1 path below.
@@ -223,7 +223,7 @@ async function runServeCommand(args) {
223
223
  process.stderr.write(`ggui serve: storage: ${err instanceof Error ? err.message : String(err)}\n`);
224
224
  return 1;
225
225
  }
226
- // Persistent default for SessionStore + VectorStore — layered AFTER
226
+ // Persistent default for RenderStore + VectorStore — layered AFTER
227
227
  // the manifest resolver so explicit `ggui.json#storage` declarations
228
228
  // always win, and BEFORE the banner so `describeStorageStatus`
229
229
  // reflects the actual wired state. Without this layer, ggui-default
@@ -235,13 +235,13 @@ async function runServeCommand(args) {
235
235
  // `--ephemeral` skips the whole persistent layering. Operators who
236
236
  // pass the flag get pure in-memory defaults across the board (HMAC
237
237
  // secrets mint fresh per process). Without the flag, the
238
- // sqlite-backed VectorStore + SessionStore persist across restarts
238
+ // sqlite-backed VectorStore + RenderStore persist across restarts
239
239
  // — note this means the install-to-cache bridge can serve stale
240
240
  // install-provenance rows after a boot if the source TSX behind a
241
241
  // cached row has been edited or uninstalled in the meantime.
242
242
  if (!parsed.ephemeral) {
243
243
  const persistentDir = getPersistentDir(plan.projectRoot);
244
- const manifestDeclaresSessions = plan.manifest?.storage?.sessions !== undefined;
244
+ const manifestDeclaresRenders = plan.manifest?.storage?.renders !== undefined;
245
245
  const manifestDeclaresVectors = plan.manifest?.storage?.vectors !== undefined;
246
246
  // The persistent stores are SQLite-backed (`better-sqlite3`, an
247
247
  // optional native module). When it isn't installed — or the
@@ -251,14 +251,14 @@ async function runServeCommand(args) {
251
251
  // `better-sqlite3` later upgrades them to persistence. An
252
252
  // explicit `ggui.json#storage` declaration still hard-fails (it
253
253
  // resolved above) — the operator asked for it by name.
254
- if (!manifestDeclaresSessions && storage.sessionStore === undefined) {
254
+ if (!manifestDeclaresRenders && storage.renderStore === undefined) {
255
255
  try {
256
- const sessionStore = await createPersistentSessionStore(persistentDir);
257
- storage = { ...storage, sessionStore };
256
+ const renderStore = await createPersistentRenderStore(persistentDir);
257
+ storage = { ...storage, renderStore };
258
258
  }
259
259
  catch (err) {
260
- process.stderr.write(`ggui serve: persistent session store unavailable — using in-memory `
261
- + `(sessions reset on restart; install \`better-sqlite3\` for persistence). `
260
+ process.stderr.write(`ggui serve: persistent render store unavailable — using in-memory `
261
+ + `(renders reset on restart; install \`better-sqlite3\` for persistence). `
262
262
  + `[${err instanceof Error ? err.message : String(err)}]\n`);
263
263
  }
264
264
  }
@@ -423,10 +423,10 @@ async function runServeCommand(args) {
423
423
  mcpMounts = narrowMcpMounts(discovery.mounts);
424
424
  }
425
425
  // Resolve `--port 0` BEFORE composing the backend. `createGguiServer`
426
- // captures `mcpApps.renderBaseUrl` + `wsUrl` at construction time, so
427
- // we need a concrete port to emit URLs the agent can hand to a
428
- // browser. A tiny race window exists between close + bind; surface
429
- // the bind failure cleanly if it loses.
426
+ // captures `mcpApps.wsUrl` + `runtime.url` at construction time, so
427
+ // we need a concrete port to emit URLs the iframe can connect to.
428
+ // A tiny race window exists between close + bind; surface the bind
429
+ // failure cleanly if it loses.
430
430
  //
431
431
  // Resolved BEFORE the BYOK probe (vs. previous ordering) because
432
432
  // the no-credentials fallback card needs the absolute settings URL
@@ -447,15 +447,33 @@ async function runServeCommand(args) {
447
447
  // BYOK probe — boot scan + per-request resolver. The probe ALWAYS
448
448
  // returns a `GenerationBinding` now (post-H2): when no env / global
449
449
  // / user-scope key resolved at boot, the binding's `resolveLlm`
450
- // re-runs at every push with `userScope: ctx.appId` (per-user keys
450
+ // re-runs at every render with `userScope: ctx.appId` (per-user keys
451
451
  // stored in `~/.ggui/credentials.json` flip in there); when the
452
452
  // re-run also misses, the bound `onNoCredentials` hook produces
453
- // a Connect-Claude card stack item pointing at THIS server's
454
- // `/settings`. Story-path `ggui_push` therefore always lands a
455
- // real stack item — either a generated component (key found) or
453
+ // a Connect-Claude card render pointing at THIS server's
454
+ // `/settings`. Story-path `ggui_render` therefore always lands a
455
+ // real render — either a generated component (key found) or
456
456
  // the card (key missing).
457
457
  const baseUrlForCard = parsed.publicBaseUrl ?? `http://${parsed.host}:${effectivePort}`;
458
458
  const settingsUrl = `${baseUrlForCard}/settings`;
459
+ // No-credentials cards live for an hour from mint — long enough for
460
+ // the operator to follow the Connect-Claude link, paste a key, and
461
+ // re-prompt before the persisted render is GC'd.
462
+ const NO_CREDENTIALS_CARD_TTL_MS = 60 * 60 * 1000;
463
+ // Resolve the operator's explicit `generation.model` route, if any.
464
+ // The schema-side `parseAnyLlmRoute` transform yields a typed
465
+ // `LlmRoute` directly — no string parsing here. Bedrock is
466
+ // hosted-only on the OSS path (no IAM resolver chain wired); reject
467
+ // explicitly with a clear error rather than silently failing at
468
+ // dispatch time.
469
+ const configuredRoute = plan.manifest?.generation?.model;
470
+ if (configuredRoute?.provider === 'bedrock') {
471
+ process.stderr.write(`ggui serve: ggui.json#generation.model declared a bedrock route ` +
472
+ `("${configuredRoute.model}"), but the OSS BYOK resolver chain ` +
473
+ `does not cover AWS IAM. Bedrock is supported via the hosted ` +
474
+ `runtime only. Pick an anthropic/openai/google/openrouter route.\n`);
475
+ return 1;
476
+ }
459
477
  let generationBinding;
460
478
  try {
461
479
  // Use whatever blueprint provider the manifest resolved, or
@@ -465,12 +483,18 @@ async function runServeCommand(args) {
465
483
  generationBinding = await probeGenerationBinding({
466
484
  resolver: createByokResolver(),
467
485
  blueprints: blueprintsForGen,
468
- onNoCredentials: (_ctx, story) => buildNoCredentialsStackItem({
469
- stackItemId: story.stackItemId,
470
- intent: story.intent,
471
- nowIso: story.nowIso,
472
- settingsUrl,
473
- }),
486
+ ...(configuredRoute ? { configuredRoute } : {}),
487
+ onNoCredentials: (ctx, story) => {
488
+ const nowEpochMs = Date.parse(story.nowIso);
489
+ return buildNoCredentialsRender({
490
+ renderId: story.renderId,
491
+ appId: ctx.appId,
492
+ intent: story.intent,
493
+ nowEpochMs,
494
+ expiresAt: nowEpochMs + NO_CREDENTIALS_CARD_TTL_MS,
495
+ settingsUrl,
496
+ });
497
+ },
474
498
  });
475
499
  }
476
500
  catch (err) {
@@ -484,8 +508,35 @@ async function runServeCommand(args) {
484
508
  generationBinding = await probeGenerationBinding({
485
509
  resolver: createByokResolver(),
486
510
  blueprints: blueprintsForGen,
511
+ ...(configuredRoute ? { configuredRoute } : {}),
487
512
  });
488
513
  }
514
+ // Strict-fail: a key resolved at boot, but the operator never
515
+ // declared `generation.model` in their manifest. Silently picking
516
+ // the per-provider default was the surprise that produced #22 and
517
+ // #42 — the typed system removed the WIRE bug class, this check
518
+ // removes the OPERATOR bug class. (`--mcp-only` and no-manifest
519
+ // paths skip the check — they have no generation surface to pin.)
520
+ if (plan.manifest !== null &&
521
+ generationBinding.bootResolved &&
522
+ configuredRoute === undefined) {
523
+ process.stderr.write(`ggui serve: boot scan resolved a ${generationBinding.provider} key but ` +
524
+ `ggui.json#generation.model is unset. Pick the model explicitly:\n` +
525
+ `\n` +
526
+ ` {\n` +
527
+ ` "schema": "1",\n` +
528
+ ` "generation": {\n` +
529
+ ` "model": "${generationBinding.provider}:${DEFAULT_ROUTE_BY_PROVIDER[generationBinding.provider].model}"\n` +
530
+ ` }\n` +
531
+ ` }\n` +
532
+ `\n` +
533
+ `Accepted forms:\n` +
534
+ ` - canonical: "anthropic:claude-haiku-4-5-20251001"\n` +
535
+ ` - LiteLLM: "anthropic/claude-haiku-4-5"\n` +
536
+ `\n` +
537
+ `See docs/principles/model-string-convention.md.\n`);
538
+ return 1;
539
+ }
489
540
  process.stdout.write(`${describeGenerationBinding(generationBinding)}\n`);
490
541
  try {
491
542
  return await runServe({
@@ -612,8 +663,8 @@ async function runServeCommand(args) {
612
663
  Object.keys(plan.manifest.app.publicEnv).length > 0
613
664
  ? { publicEnv: plan.manifest.app.publicEnv }
614
665
  : {}),
615
- ...(plan.manifest?.app?.defaultMcpAppsMode !== undefined
616
- ? { defaultMcpAppsMode: plan.manifest.app.defaultMcpAppsMode }
666
+ ...(plan.manifest?.app?.defaultDisplayMode !== undefined
667
+ ? { defaultDisplayMode: plan.manifest.app.defaultDisplayMode }
617
668
  : {}),
618
669
  generation: generationBinding.generation,
619
670
  ...(mcpMounts.length > 0 ? { mcpMounts } : {}),
@@ -685,10 +736,10 @@ function describeStorageStatus(config, resolved) {
685
736
  if (!config)
686
737
  return [];
687
738
  const lines = [];
688
- if (config.sessions) {
689
- lines.push(resolved.sessionStore
690
- ? `storage: sessions → sqlite (${config.sessions.driver === 'sqlite' ? config.sessions.path : '—'})`
691
- : `storage: sessions → in-memory`);
739
+ if (config.renders) {
740
+ lines.push(resolved.renderStore
741
+ ? `storage: renders → sqlite (${config.renders.driver === 'sqlite' ? config.renders.path : '—'})`
742
+ : `storage: renders → in-memory`);
692
743
  }
693
744
  if (config.vectors) {
694
745
  lines.push(resolved.vectors
@@ -17,12 +17,12 @@
17
17
  * server restart. Multi-tenant `ggui serve` lives off this
18
18
  * seam: each authenticated user manages their OWN provider
19
19
  * key via `/settings`, the resolver picks it up on the next
20
- * `ggui_push`.
20
+ * `ggui_render`.
21
21
  * 3. **No-key default** — when the boot scan finds nothing, we
22
22
  * STILL return a binding (provider=`anthropic`, model=
23
23
  * `claude-haiku-4-5`). Generation stays wired; the
24
24
  * no-credentials path now produces a Connect-Claude card
25
- * stack item via {@link GenerationDeps.onNoCredentials}
25
+ * render via {@link GenerationDeps.onNoCredentials}
26
26
  * instead of the broken `codeReady:false` placeholder.
27
27
  * Caller-supplied `onNoCredentials` is threaded through
28
28
  * verbatim.
@@ -37,7 +37,7 @@
37
37
  * can add `GGUI_GENERATION_PROVIDER` / `ggui.json#generation.model`
38
38
  * without re-shaping this seam.
39
39
  */
40
- import type { BlueprintProvider, GenerationDeps, HandlerContext, LlmProvider, SessionStackEntry } from '@ggui-ai/mcp-server';
40
+ import type { BlueprintProvider, GenerationDeps, HandlerContext, LlmProvider, LlmRoute, Render } from '@ggui-ai/mcp-server';
41
41
  import type { ByokKeyResolution, ByokResolver } from './byok-resolver.js';
42
42
  /**
43
43
  * Locked default model per provider for the OSS first-run path.
@@ -53,7 +53,14 @@ import type { ByokKeyResolution, ByokResolver } from './byok-resolver.js';
53
53
  * binds Bedrock through its own `GenerationDeps` at the hosted
54
54
  * surface.
55
55
  */
56
- export declare const DEFAULT_MODEL_BY_PROVIDER: Readonly<Record<Exclude<LlmProvider, 'bedrock'>, string>>;
56
+ /**
57
+ * Locked default route per provider, as a typed {@link LlmRoute}.
58
+ * Model strings are bare wire-canonical IDs (registry KEY ==
59
+ * what the provider's API expects on the wire) — there is no
60
+ * transformation step downstream. `dispatchGeneration` sends
61
+ * `route.model` verbatim.
62
+ */
63
+ export declare const DEFAULT_ROUTE_BY_PROVIDER: Readonly<Record<Exclude<LlmProvider, 'bedrock'>, LlmRoute>>;
57
64
  /**
58
65
  * Priority order for BYOK provider probing. The first provider
59
66
  * whose credentials resolve wins. Anthropic first is deliberate —
@@ -66,6 +73,21 @@ export interface ProbeGenerationBindingOptions {
66
73
  readonly blueprints: BlueprintProvider;
67
74
  /** Override the probe order. Tests use this to pin the winner. */
68
75
  readonly providerOrder?: readonly Exclude<LlmProvider, 'bedrock'>[];
76
+ /**
77
+ * Explicit operator-declared route from `ggui.json#generation.model`.
78
+ * When set:
79
+ * - `configuredRoute.provider` becomes the boot-scan provider
80
+ * (overriding the priority chain).
81
+ * - `configuredRoute.model` is what flows to the dispatch path
82
+ * (overriding `DEFAULT_ROUTE_BY_PROVIDER[provider]`).
83
+ *
84
+ * Absent → fall back to today's behavior: walk the priority chain,
85
+ * use the per-provider default. The CLI hard-fails BEFORE reaching
86
+ * this function when a ggui.json exists, a key resolves, but
87
+ * `generation.model` is unset — so this seam only sees `undefined`
88
+ * for the `--mcp-only` / no-manifest paths.
89
+ */
90
+ readonly configuredRoute?: LlmRoute;
69
91
  /**
70
92
  * Optional no-credentials fallback hook threaded straight onto
71
93
  * {@link GenerationDeps.onNoCredentials}. The CLI builds this
@@ -76,9 +98,9 @@ export interface ProbeGenerationBindingOptions {
76
98
  */
77
99
  readonly onNoCredentials?: (ctx: HandlerContext, story: {
78
100
  readonly intent: string;
79
- readonly stackItemId: string;
101
+ readonly renderId: string;
80
102
  readonly nowIso: string;
81
- }) => SessionStackEntry | null | Promise<SessionStackEntry | null>;
103
+ }) => Render | null | Promise<Render | null>;
82
104
  }
83
105
  /**
84
106
  * Outcome of the boot probe. Always returned (no `null` shape) —
@@ -1 +1 @@
1
- {"version":3,"file":"generation-probe.d.ts","sourceRoot":"","sources":["../src/generation-probe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,WAAW,EAGX,iBAAiB,EAClB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EACV,iBAAiB,EACjB,YAAY,EACb,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAC9C,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,CAUhD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,EAC1B,CAAC;AAElD,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IACvC,kEAAkE;IAClE,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE,CAAC;IACpE;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,CACzB,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE;QACL,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACzB,KACE,iBAAiB,GAAG,IAAI,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACnE;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,SAAS,CAAC,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACjD,qEAAqE;IACrE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,6BAA6B,GAClC,OAAO,CAAC,iBAAiB,CAAC,CA0E5B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,iBAAiB,GACzB,MAAM,CAWR"}
1
+ {"version":3,"file":"generation-probe.d.ts","sourceRoot":"","sources":["../src/generation-probe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,KAAK,EACV,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,WAAW,EACX,QAAQ,EAGR,MAAM,EACP,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EACV,iBAAiB,EACjB,YAAY,EACb,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;GAaG;AACH;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAC9C,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE,QAAQ,CAAC,CAMlD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,EAC1B,CAAC;AAElD,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IACvC,kEAAkE;IAClE,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE,CAAC;IACpE;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,QAAQ,CAAC;IACpC;;;;;;;OAOG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,CACzB,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE;QACL,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACzB,KACE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC7C;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,SAAS,CAAC,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACjD,qEAAqE;IACrE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,6BAA6B,GAClC,OAAO,CAAC,iBAAiB,CAAC,CAwF5B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,iBAAiB,GACzB,MAAM,CAWR"}
@@ -13,15 +13,18 @@ import { createUiGenerator } from '@ggui-ai/ui-gen';
13
13
  * binds Bedrock through its own `GenerationDeps` at the hosted
14
14
  * surface.
15
15
  */
16
- export const DEFAULT_MODEL_BY_PROVIDER = {
17
- // Slash-prefixed `<provider>/<model>` form — `getProviderForModel`
18
- // expects it; bare names trip the "Unrecognized model format" warning
19
- // and silently default to anthropic. Pre-matrix the openai/google
20
- // defaults were also bare; this fixes them as part of the model bump.
21
- anthropic: 'anthropic/claude-haiku-4-5',
22
- openai: 'openai/gpt-5.5-2026-04-23',
23
- google: 'google/gemini-3.5-flash',
24
- openrouter: 'anthropic/claude-haiku-4.5',
16
+ /**
17
+ * Locked default route per provider, as a typed {@link LlmRoute}.
18
+ * Model strings are bare wire-canonical IDs (registry KEY ==
19
+ * what the provider's API expects on the wire) — there is no
20
+ * transformation step downstream. `dispatchGeneration` sends
21
+ * `route.model` verbatim.
22
+ */
23
+ export const DEFAULT_ROUTE_BY_PROVIDER = {
24
+ anthropic: { provider: 'anthropic', model: 'claude-haiku-4-5-20251001' },
25
+ openai: { provider: 'openai', model: 'gpt-5.5-2026-04-23' },
26
+ google: { provider: 'google', model: 'gemini-3.5-flash' },
27
+ openrouter: { provider: 'openrouter', model: 'anthropic/claude-haiku-4.5' },
25
28
  };
26
29
  /**
27
30
  * Priority order for BYOK provider probing. The first provider
@@ -42,26 +45,37 @@ export const PROVIDER_PROBE_ORDER = ['anthropic', 'openai', 'google', 'openroute
42
45
  */
43
46
  export async function probeGenerationBinding(opts) {
44
47
  const order = opts.providerOrder ?? PROVIDER_PROBE_ORDER;
45
- // Boot scan — surfaces the banner-line provider/source. If
46
- // multiple providers have boot-time keys, the first in priority
47
- // order wins (matches pre-H2 behavior).
48
+ // When the operator declared an explicit route, the boot scan only
49
+ // needs to resolve THAT provider's credential — the priority walk
50
+ // is bypassed. Otherwise fall back to the original behavior: walk
51
+ // the chain, first hit wins.
52
+ const configured = opts.configuredRoute;
48
53
  let bootHit = null;
49
- for (const provider of order) {
50
- const resolution = await opts.resolver.resolve(provider);
54
+ if (configured && configured.provider !== 'bedrock') {
55
+ const resolution = await opts.resolver.resolve(configured.provider);
51
56
  if (resolution) {
52
- bootHit = { ...resolution, provider };
53
- break;
57
+ bootHit = { ...resolution, provider: configured.provider };
58
+ }
59
+ }
60
+ else {
61
+ for (const provider of order) {
62
+ const resolution = await opts.resolver.resolve(provider);
63
+ if (resolution) {
64
+ bootHit = { ...resolution, provider };
65
+ break;
66
+ }
54
67
  }
55
68
  }
56
- // Default provider locks to anthropic on boot-miss — matches the
57
- // OSS "Claude first" posture. The Connect-Claude card flow steers
58
- // misses toward an Anthropic key (env/file/OAuth); nothing in the
59
- // contract prevents users from pasting an OpenAI/Google key
60
- // instead, but the boot-time provider for THIS server stays
61
- // anthropic until the operator restarts with a different boot
62
- // hit.
63
- const defaultProvider = bootHit?.provider ?? 'anthropic';
64
- const defaultModel = DEFAULT_MODEL_BY_PROVIDER[defaultProvider];
69
+ // Resolve the route the dispatch path will use:
70
+ // - explicit `configuredRoute` always wins, even on boot-miss
71
+ // - else use the boot-hit provider's default route
72
+ // - else default to anthropic / Haiku 4.5 (the OSS "Claude first"
73
+ // posture; matches Connect-Claude card flow)
74
+ const defaultProvider = configured && configured.provider !== 'bedrock'
75
+ ? configured.provider
76
+ : bootHit?.provider ?? 'anthropic';
77
+ const defaultRoute = configured ?? DEFAULT_ROUTE_BY_PROVIDER[defaultProvider];
78
+ const defaultModel = defaultRoute.model;
65
79
  // Full-harness wire-up: `createUiGenerator` runs the same
66
80
  // multi-turn coding agent + self-check loop the bench validates;
67
81
  // `dispatchGeneration` returns compiled JS on `componentCode`.
@@ -77,7 +91,10 @@ export async function probeGenerationBinding(opts) {
77
91
  if (!resolution)
78
92
  return null;
79
93
  return {
80
- selection: { provider: defaultProvider, model: defaultModel },
94
+ // Spread the typed route — TS knows `defaultRoute` is an
95
+ // `LlmRoute`, so the discriminator + model alignment is
96
+ // preserved when assigning to `LlmSelection`.
97
+ selection: { ...defaultRoute },
81
98
  providerKey: { provider: defaultProvider, key: resolution.key },
82
99
  };
83
100
  };
@@ -1,7 +1,7 @@
1
- import { type BlueprintProvider, type GadgetDescriptor, type McpAppsMode, type DiscoveredPrimitiveCatalog, type GenerationDeps, type LoadedTheme, type McpServerMount, type OperatorConfig, type ResolvedStorageStores, type ShortCodeIndex, type ThemeWriter } from '@ggui-ai/mcp-server';
2
- import type { UiRegistry } from '@ggui-ai/ui-registry';
3
- import type { UiManifest } from '@ggui-ai/project-config';
4
- import type { ServeBackend } from './serve-command.js';
1
+ import { type BlueprintProvider, type DiscoveredPrimitiveCatalog, type GadgetDescriptor, type GenerationDeps, type LoadedTheme, type McpServerMount, type McpUiDisplayMode, type OperatorConfig, type ResolvedStorageStores, type ShortCodeIndex, type ThemeWriter } from "@ggui-ai/mcp-server";
2
+ import type { UiManifest } from "@ggui-ai/project-config";
3
+ import type { UiRegistry } from "@ggui-ai/ui-registry";
4
+ import type { ServeBackend } from "./serve-command.js";
5
5
  export interface BuildMcpServerBackendOptions {
6
6
  /**
7
7
  * Pre-resolved storage from `ggui.json#storage`. Threaded straight
@@ -18,19 +18,18 @@ export interface BuildMcpServerBackendOptions {
18
18
  */
19
19
  readonly cliVersion: string;
20
20
  /**
21
- * Bind host used to compose the MCP Apps `renderBaseUrl` + `wsUrl`.
21
+ * Bind host used to compose the MCP Apps `wsUrl` and `runtime.url`.
22
22
  * Must be the same host the CLI then passes to `listen()`; otherwise
23
- * the shortCode URLs the agent receives will point somewhere the
24
- * browser can't reach.
23
+ * those URLs will point somewhere the iframe browser can't reach.
25
24
  */
26
25
  readonly host: string;
27
26
  /**
28
27
  * Bind port used to compose the MCP Apps URLs. MUST be a concrete
29
- * port (not `0`) — the agent-returned URL is captured at composition
30
- * time, so deferring to an OS-assigned port would leave `ggui_push`
31
- * emitting a broken link. Callers that started with `--port 0`
32
- * should pre-resolve a free port via {@link pickFreePort} before
33
- * constructing the backend.
28
+ * port (not `0`) — the iframe-facing URLs (`wsUrl`, `runtime.url`)
29
+ * are captured at composition time, so deferring to an OS-assigned
30
+ * port would leave them pointing at the wrong port. Callers that
31
+ * started with `--port 0` should pre-resolve a free port via
32
+ * {@link pickFreePort} before constructing the backend.
34
33
  */
35
34
  readonly port: number;
36
35
  /**
@@ -83,13 +82,13 @@ export interface BuildMcpServerBackendOptions {
83
82
  readonly themeWriter?: ThemeWriter;
84
83
  /**
85
84
  * Live theme getter — when set, supersedes the static `theme`
86
- * resolution for every `ggui_push` bootstrap envelope. The CLI
85
+ * resolution for every `ggui_render` bootstrap envelope. The CLI
87
86
  * pairs this with `onThemeConfigChange` so a console save
88
- * reaches the next push without a server restart.
87
+ * reaches the next render without a server restart.
89
88
  */
90
89
  readonly themeProvider?: () => {
91
90
  readonly id?: string;
92
- readonly mode?: 'light' | 'dark';
91
+ readonly mode?: "light" | "dark";
93
92
  } | undefined;
94
93
  /**
95
94
  * Optional change notifier — fires from
@@ -99,17 +98,17 @@ export interface BuildMcpServerBackendOptions {
99
98
  */
100
99
  readonly onThemeConfigChange?: (next: string | {
101
100
  preset: string;
102
- mode?: 'light' | 'dark';
101
+ mode?: "light" | "dark";
103
102
  overrides?: Record<string, string>;
104
103
  } | {
105
104
  file: string;
106
- mode?: 'light' | 'dark';
105
+ mode?: "light" | "dark";
107
106
  } | null) => void;
108
107
  /**
109
- * Generation wiring for `ggui_push`. When present, the OSS push
108
+ * Generation wiring for `ggui_render`. When present, the OSS render
110
109
  * handler invokes the bound `UiGenerator` on every story-path
111
- * call and appends real componentCode as a `StackItem`. Absent =
112
- * placeholder mode: push creates sessions + shortCodes but does
110
+ * call and commits real componentCode as a `Render`. Absent =
111
+ * placeholder mode: render mints renderIds + shortCodes but does
113
112
  * not produce componentCode.
114
113
  *
115
114
  * The CLI resolves this from the operator's BYOK state at boot via
@@ -171,7 +170,7 @@ export interface BuildMcpServerBackendOptions {
171
170
  * (every bearer authenticates as builder) but additionally:
172
171
  * - Wires a per-remote-IP `FixedWindowRateLimiter` over an
173
172
  * `InMemoryQuotaStore` (default 30 generations / 10 minutes per
174
- * IP). The limiter binds at `ggui_push` so end-user generations
173
+ * IP). The limiter binds at `ggui_render` so end-user generations
175
174
  * can't burn the operator's BYOK budget.
176
175
  * - The CLI banner displays "PUBLIC DEMO" copy with a cost-
177
176
  * attribution + rate-limit note (vs. "DEV ALLOW-ALL" warning).
@@ -197,11 +196,10 @@ export interface BuildMcpServerBackendOptions {
197
196
  readonly multiTenant?: boolean;
198
197
  /**
199
198
  * Public base URL that replaces `http://<host>:<port>` when
200
- * composing `mcpApps.renderBaseUrl`, `mcpApps.wsUrl`, and
201
- * `runtime.url`. Set this when the server is being reached
202
- * through a tunnel (cloudflare, ngrok, …) so URLs the agent
203
- * receives resolve from the MCP host's perspective rather than
204
- * `localhost`.
199
+ * composing `mcpApps.wsUrl` and `runtime.url`. Set this when the
200
+ * server is being reached through a tunnel (cloudflare, ngrok, …)
201
+ * so URLs the iframe receives resolve from the MCP host's
202
+ * perspective rather than `localhost`.
205
203
  *
206
204
  * Required shape: `http://…` or `https://…`, no trailing slash.
207
205
  * The `wsUrl` is derived by replacing the scheme with `ws`/`wss`.
@@ -244,13 +242,13 @@ export interface BuildMcpServerBackendOptions {
244
242
  * Surface = `--mcp-instructions <preset>` CLI flag or
245
243
  * `GGUI_MCP_INSTRUCTIONS` env var (CLI flag wins).
246
244
  */
247
- readonly mcpInstructions?: 'default' | 'aggressive' | 'always' | 'minimal' | 'off';
245
+ readonly mcpInstructions?: "default" | "aggressive" | "always" | "minimal" | "off";
248
246
  /**
249
247
  * Directory backing the cross-restart persistence bundle. When set,
250
- * `bootstrapSecret` + `renderSigning.secret` are read from / minted
251
- * into 0600-mode files there so the HMAC keys survive `ggui serve`
252
- * restart — claude.ai chat-history revisits keep their cached
253
- * `_meta.ggui.bootstrap.token` + `/r/<code>?sig=&exp=` URLs valid.
248
+ * `wsTokenSecret` is read from / minted into a 0600-mode file there
249
+ * so the HMAC key survives `ggui serve` restart — claude.ai
250
+ * chat-history revisits keep their cached
251
+ * `_meta["ai.ggui/render"].wsToken` valid across reboots.
254
252
  *
255
253
  * Absent / undefined = the legacy ephemeral behavior (every restart
256
254
  * mints fresh secrets; cached tokens fail HMAC verify). The CLI sets
@@ -313,23 +311,22 @@ export interface BuildMcpServerBackendOptions {
313
311
  * `ggui.json#app.publicEnv`. Each key MUST match
314
312
  * `^GGUI_PUBLIC_APP_[A-Z0-9_]+$`. The server projects only the keys
315
313
  * that some registered wrapper's `requires` references, onto
316
- * `_meta.ggui.bootstrap.publicEnv` and ultimately
314
+ * `_meta["ai.ggui/render"].publicEnv` and ultimately
317
315
  * `globalThis.__ggui__.publicEnv` for `getPublicEnv()` to read.
318
316
  *
319
317
  * Omitted ⇒ field absent on the App record (no values projected;
320
318
  * wrappers without `requires` still mount, wrappers with `requires`
321
- * fail at push-gate validation).
319
+ * fail at render-gate validation).
322
320
  */
323
321
  readonly publicEnv?: Readonly<Record<string, string>>;
324
322
  /**
325
- * Per-app MCP-Apps presentation mode from
326
- * `ggui.json#app.defaultMcpAppsMode`. `'canvas'` makes
327
- * `ggui_new_session` mint a session-scoped iframe
328
- * (`ui://ggui/session/<sessionId>`) and route subsequent pushes
329
- * through the session channel; `'inline'` (or omitted) preserves
330
- * the per-push-iframe legacy behavior.
323
+ * Per-app default display-mode hint from
324
+ * `ggui.json#app.defaultDisplayMode`. Stamped on every `ggui_render`
325
+ * via `_meta.ui.displayMode` so the host knows whether to present
326
+ * the iframe inline, fullscreen, or picture-in-picture. See
327
+ * `App.defaultDisplayMode` for the full semantics.
331
328
  */
332
- readonly defaultMcpAppsMode?: McpAppsMode;
329
+ readonly defaultDisplayMode?: McpUiDisplayMode;
333
330
  }
334
331
  /**
335
332
  * Pick a free localhost TCP port by letting the OS assign one on a
@@ -337,7 +334,7 @@ export interface BuildMcpServerBackendOptions {
337
334
  * chosen number. Exported so the CLI (`cli.ts::runServeCommand`) and
338
335
  * the integration tests can resolve `--port 0` to a concrete port
339
336
  * BEFORE constructing the backend — {@link buildMcpServerBackend}
340
- * captures the port in the composed `mcpApps.renderBaseUrl` / `wsUrl`
337
+ * captures the port in the composed `mcpApps.wsUrl` / `runtime.url`
341
338
  * at construction time, so the caller must know it up-front.
342
339
  *
343
340
  * Tiny race window: another process could claim the port between our
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-backend.d.ts","sourceRoot":"","sources":["../src/mcp-backend.ts"],"names":[],"mappings":"AA0CA,OAAO,EAUL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,0BAA0B,EAE/B,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,cAAc,EACnB,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAevD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAQ1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,4BAA4B;IAC3C;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,qBAAqB,CAAC;IACzC;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IAC/C;;;;;;;;;OASG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC;;;;;;;;OAQG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,0BAA0B,EAAE,CAAC;IACnE;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;IAC7B;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM;QAC7B,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;KAClC,GAAG,SAAS,CAAC;IACd;;;;;OAKG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAC7B,IAAI,EACA,MAAM,GACN;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAC/E;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;KAAE,GACzC,IAAI,KACL,IAAI,CAAC;IACV;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC;IAErC;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE;QAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;YAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;YACpB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;YAC9B,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;SAC/B,CAAC,CAAC;KACJ,CAAC;IAEF;;;;;;;;;OASG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAEnD;;;;;;;;;OASG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAE/B;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAE9B;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAE/B;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEhC;;;;;;;;;OASG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,CAAC,EACrB,SAAS,GACT,YAAY,GACZ,QAAQ,GACR,SAAS,GACT,KAAK,CAAC;IAEV;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEhC;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IAEzC;;;;;;;;OAQG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAE7B;;;;;;;;;OASG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE;QACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC;QACnC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;IAEF;;;;;;;;;OASG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAE/C;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAEtD;;;;;;;OAOG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,WAAW,CAAC;CAC3C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,IAAI,SAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBhE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,4BAA4B,GACjC,YAAY,CAimBd"}
1
+ {"version":3,"file":"mcp-backend.d.ts","sourceRoot":"","sources":["../src/mcp-backend.ts"],"names":[],"mappings":"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"}