@ggui-ai/protocol 0.15.0 → 0.16.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.
Files changed (75) hide show
  1. package/dist/errors/domain-error.d.ts +70 -0
  2. package/dist/errors/domain-error.d.ts.map +1 -0
  3. package/dist/errors/domain-error.js +118 -0
  4. package/dist/gadgets/stdlib-gadgets.d.ts +1 -1
  5. package/dist/gadgets/stdlib-gadgets.js +1 -1
  6. package/dist/index.d.ts +3 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +4 -2
  9. package/dist/integrations/mcp-apps.d.ts +33 -7
  10. package/dist/integrations/mcp-apps.d.ts.map +1 -1
  11. package/dist/integrations/mcp-apps.js +13 -13
  12. package/dist/integrations/overlay-hash.d.ts +19 -0
  13. package/dist/integrations/overlay-hash.d.ts.map +1 -0
  14. package/dist/integrations/overlay-hash.js +29 -0
  15. package/dist/integrations/theme-binding.d.ts +14 -12
  16. package/dist/integrations/theme-binding.d.ts.map +1 -1
  17. package/dist/integrations/theme-binding.js +10 -6
  18. package/dist/registry/blueprint-key.d.ts.map +1 -1
  19. package/dist/registry/blueprint-key.js +4 -3
  20. package/dist/schemas/app-theme.d.ts +46 -10
  21. package/dist/schemas/app-theme.d.ts.map +1 -1
  22. package/dist/schemas/app-theme.js +108 -40
  23. package/dist/schemas/blueprint.d.ts +2 -1
  24. package/dist/schemas/blueprint.d.ts.map +1 -1
  25. package/dist/schemas/blueprint.js +15 -3
  26. package/dist/schemas/data-contract.d.ts +1 -1
  27. package/dist/schemas/data-contract.js +1 -1
  28. package/dist/schemas/handshake-suggestion.d.ts.map +1 -1
  29. package/dist/schemas/handshake-suggestion.js +8 -1
  30. package/dist/schemas/mcp.d.ts +48 -22
  31. package/dist/schemas/mcp.d.ts.map +1 -1
  32. package/dist/schemas/mcp.js +44 -15
  33. package/dist/schemas/ops-blueprint.d.ts +4 -4
  34. package/dist/schemas/ops-blueprint.d.ts.map +1 -1
  35. package/dist/schemas/ops-blueprint.js +13 -8
  36. package/dist/schemas/render-input-envelope.js +1 -1
  37. package/dist/types/blueprint-source.d.ts +27 -7
  38. package/dist/types/blueprint-source.d.ts.map +1 -1
  39. package/dist/types/blueprint-source.js +19 -3
  40. package/dist/types/blueprint.d.ts +2 -2
  41. package/dist/types/blueprint.d.ts.map +1 -1
  42. package/dist/types/data-contract.d.ts +3 -3
  43. package/dist/types/domain-error-codes.d.ts +167 -0
  44. package/dist/types/domain-error-codes.d.ts.map +1 -0
  45. package/dist/types/domain-error-codes.js +170 -0
  46. package/dist/types/handshake-suggestion.d.ts +2 -2
  47. package/dist/types/live-channel.d.ts +1 -1
  48. package/dist/types/llm-route.d.ts +59 -2
  49. package/dist/types/llm-route.d.ts.map +1 -1
  50. package/dist/types/llm-route.js +62 -16
  51. package/dist/types/llm.d.ts +22 -2
  52. package/dist/types/llm.d.ts.map +1 -1
  53. package/dist/types/llm.js +29 -2
  54. package/dist/types/mcp.d.ts +31 -39
  55. package/dist/types/mcp.d.ts.map +1 -1
  56. package/dist/types/mcp.js +22 -10
  57. package/dist/types/refusal-codes.d.ts +31 -93
  58. package/dist/types/refusal-codes.d.ts.map +1 -1
  59. package/dist/types/refusal-codes.js +41 -96
  60. package/dist/types/render.d.ts +3 -3
  61. package/dist/types/render.d.ts.map +1 -1
  62. package/dist/validation/contract-validator.d.ts +8 -2
  63. package/dist/validation/contract-validator.d.ts.map +1 -1
  64. package/dist/validation/contract-validator.js +12 -4
  65. package/dist/validation/lint-contract.d.ts +2 -2
  66. package/dist/validation/lint-contract.d.ts.map +1 -1
  67. package/dist/validation/lint-contract.js +6 -4
  68. package/dist/validation/schema-subset.d.ts +3 -3
  69. package/dist/version.d.ts +357 -6
  70. package/dist/version.d.ts.map +1 -1
  71. package/dist/version.js +356 -5
  72. package/package.json +1 -1
  73. package/dist/envelope-adapters.d.ts +0 -12
  74. package/dist/envelope-adapters.d.ts.map +0 -1
  75. package/dist/envelope-adapters.js +0 -30
@@ -7,7 +7,7 @@
7
7
  * Two consumption patterns, both anchored here:
8
8
  *
9
9
  * - **Wired raw shapes** (`*InputShape`): handlers in
10
- * `@ggui-ai/mcp-server-handlers` (and the hosted pod's discover
10
+ * `@ggui-ai/mcp-server-handlers` (and a hosted deployment's discover
11
11
  * tool) import the SHAPE directly as their `inputSchema` and
12
12
  * validate with `z.object(shape)` — unknown keys are STRIPPED.
13
13
  * The shape is the one authored copy of the validation rules AND
@@ -48,14 +48,14 @@ export const consumeInputShape = {
48
48
  sessionId: z
49
49
  .string()
50
50
  .min(1)
51
- .describe('Globally-unique sessionId to consume events from. Cross-tenant access surfaces uniformly as session_not_found.'),
51
+ .describe('Globally-unique sessionId to consume events from. Cross-app access surfaces uniformly as session_not_found.'),
52
52
  timeout: z
53
53
  .number()
54
54
  .int()
55
55
  .min(0)
56
56
  .max(25)
57
57
  .optional()
58
- .describe('Inline long-poll seconds, integer in [0, 25]. 0 = immediate. Values outside the bound reject INVALID_PARAMS. Returns on first event OR timeout; re-call on empty to keep waiting — longer waits are your loop, not a bigger timeout.'),
58
+ .describe('Inline long-poll seconds, integer in [0, 25]. 0 = immediate. Values outside the bound reject INVALID_PARAMS. Returns on first event OR timeout; on empty you may re-call once, then end your turn — a later gesture arrives as a new user message carrying its own consume directive.'),
59
59
  };
60
60
  export const consumeInputSchema = z.object(consumeInputShape);
61
61
  /**
@@ -220,7 +220,7 @@ export const handshakeInputSchema = z.object({
220
220
  * `'declined'` cover every legal outcome.
221
221
  */
222
222
  export const handshakeOutputSchema = z.object({
223
- handshakeId: z.string().describe('Stable id — pass to ggui_render / ggui_update'),
223
+ handshakeId: z.string().describe('Stable id — pass to ggui_render'),
224
224
  action: z.enum(['create', 'reuse', 'update', 'replace', 'declined']),
225
225
  /**
226
226
  * The handshake suggestion — see `handshakeSuggestionSchema`. The
@@ -330,7 +330,7 @@ export const renderInputShape = {
330
330
  .string()
331
331
  .min(1)
332
332
  .optional()
333
- .describe('Model route in either wire form — canonical `anthropic:claude-haiku-4-5-20251001` or LiteLLM `anthropic/claude-haiku-4-5` (aliases resolve in both); generator-specific prefixes (e.g. `bedrock/...`) route to that transport. A value that parses in neither form fails the handler input parse at `infra.model`, before any pre-generation gate; `model_not_in_tier` is only ever a well-formed route with no rate row on the effective tier.'),
333
+ .describe('Model route in either wire form — canonical `anthropic:claude-haiku-4-5-20251001` or LiteLLM `anthropic/claude-haiku-4-5` (aliases resolve in both); generator-specific prefixes (e.g. `bedrock/...`) route to that transport. A value that parses in neither form fails the handler input parse at `infra.model`, before any pre-generation gate; `model_not_allowed` is only ever a well-formed route with no rate row on the effective tier.'),
334
334
  })
335
335
  .strict()
336
336
  .optional(),
@@ -516,13 +516,23 @@ export const renderRefusalSchema = z.object({
516
516
  * from {@link MCP_ENDPOINT_REFUSAL_CODES} — today exactly
517
517
  * `app_deprovisioned`, the one refusal with a tenant-side fix and
518
518
  * therefore the one that MUST be legible where a deleted app and a bad
519
- * credential would otherwise look alike.
519
+ * credential would otherwise look alike. `appId` (ggui#870) is the app
520
+ * the refused endpoint serves, as DATA — equal to the path's `{appId}`
521
+ * — so a tenant's repair loop keys on it and never parses prose; it is
522
+ * the ggui id the bound caller already holds, never the tenant's own
523
+ * `ownerRef`. The typed refusal answers a correctly bound federated
524
+ * identity only (identity first): an anonymous request is refused by the
525
+ * auth adapter before this arm, and learns nothing about the app.
520
526
  */
521
527
  export const transportRefusalSchema = z.strictObject({
522
528
  code: z
523
529
  .enum(MCP_ENDPOINT_REFUSAL_CODES)
524
530
  .describe("Registered refusal state on the per-app endpoint. Look the code up in the protocol's refusal registry for its retry class and which party can act."),
525
531
  ...refusalProjectionFields,
532
+ appId: z
533
+ .string()
534
+ .min(1)
535
+ .describe('The app id the refused endpoint serves — equals the {appId} of the endpoint path. Structured here so a repair loop keys on it instead of parsing the message.'),
526
536
  });
527
537
  /**
528
538
  * The JSON-RPC error object a per-app MCP endpoint answers with when it
@@ -532,7 +542,7 @@ export const transportRefusalSchema = z.strictObject({
532
542
  * proxy 403) and `message` `App not found`, plus `data.refusal`, which
533
543
  * makes it legible. `data` is strict: it carries the refusal and nothing
534
544
  * else. An authorization failure that is not a registry state answers
535
- * HTTP 403 with `-32001` (`UNAUTHORIZED`) and NO `data` — the three
545
+ * HTTP 403 with `-32007` (`UNAUTHORIZED`) and NO `data` — the three
536
546
  * untyped arms stay indistinguishable among themselves by contract:
537
547
  * naming any of them would say which is true. A first-party server
538
548
  * never chooses `-32000`: it is the SDK client's `ConnectionClosed`, so
@@ -851,7 +861,7 @@ export const renderOutputSchema = z.object({
851
861
  * wise). Use when most props stay the same and the agent only
852
862
  * needs to send a small delta — common after a single domain-tool
853
863
  * mutation. RFC 7396 chosen because it has a published spec and
854
- * wide library support (GitHub API, Kubernetes strategic-merge).
864
+ * wide library support (GitHub API's merge semantics, strategic-merge-patch).
855
865
  *
856
866
  * Anti-patterns (the discriminated union rejects these structurally,
857
867
  * but they're a common author mistake when copy-pasting):
@@ -864,7 +874,7 @@ export const renderOutputSchema = z.object({
864
874
  * partial patches that would break required fields, type-mismatch
865
875
  * values, etc. all reject pre-persist.
866
876
  *
867
- * `sessionId` is globally unique; the server tenancy-checks via
877
+ * `sessionId` is globally unique; the server checks the app scope via
868
878
  * `ctx.appId`.
869
879
  */
870
880
  export const updateInputSchema = z.discriminatedUnion('kind', [
@@ -1138,15 +1148,15 @@ export const gguiSessionEventSchema = z.object({
1138
1148
  * OPTIONAL here (the bridge rung owns its cursor and seeds from 0; the
1139
1149
  * route requires it because a bare browser GET has no cursor owner),
1140
1150
  * and `limit` is clamped to {@link RUNTIME_PULL_MAX_LIMIT} instead of
1141
- * rejecting above it. Tenancy violations and unknown sessionIds
1151
+ * rejecting above it. Cross-app access and unknown sessionIds
1142
1152
  * surface uniformly as the `session_not_found` error — existence of
1143
- * other tenants' renders is never leaked.
1153
+ * other apps' renders is never leaked.
1144
1154
  */
1145
1155
  export const runtimePullInputShape = {
1146
1156
  sessionId: z
1147
1157
  .string()
1148
1158
  .min(1)
1149
- .describe('Active render id — sourced from `_meta["ai.ggui/render"].sessionId` on the iframe boot envelope. Unknown and cross-tenant ids surface uniformly as session_not_found.'),
1159
+ .describe('Active render id — sourced from `_meta["ai.ggui/render"].sessionId` on the iframe boot envelope. Unknown and cross-app ids surface uniformly as session_not_found.'),
1150
1160
  sinceSequence: z
1151
1161
  .number()
1152
1162
  .int()
@@ -1332,9 +1342,9 @@ export const gguiSessionStatusSchema = z.enum(['active', 'expired']);
1332
1342
  /**
1333
1343
  * One drained row of `ggui_consume` — a user action that reached the
1334
1344
  * pipe (ggui#817 part C2). Closed on the wire: an unknown key is
1335
- * stripped at the transport, a missing key refuses the row at the seam
1336
- * (`parsePendingEnvelope`), so a malformed pipe entry never ships to an
1337
- * agent typed as a good one.
1345
+ * stripped at the transport, a missing key refuses the row at the store
1346
+ * boundary (`pendingEventSchema`, ggui#839), so a malformed pipe entry
1347
+ * never ships to an agent typed as a good one.
1338
1348
  */
1339
1349
  export const consumeEventEntrySchema = z.object({
1340
1350
  type: z.literal('action'),
@@ -1345,6 +1355,25 @@ export const consumeEventEntrySchema = z.object({
1345
1355
  actionId: z.string(),
1346
1356
  firedAt: z.string(),
1347
1357
  });
1358
+ /**
1359
+ * One stored row of the consume pipe — what a producer appends and
1360
+ * `consumeAndClear` drains, the same shape on every store (ggui#839; a
1361
+ * store-boundary contract, never wire — `ggui_consume` returns the
1362
+ * entries, never the wrapper). `id` is the drain_ack key and the
1363
+ * idempotency key per `(sessionId, id)`; `envelope` is the
1364
+ * {@link consumeEventEntrySchema} entry, always the object (every writer
1365
+ * passes one; a store that serializes the row serializes the whole row);
1366
+ * `createdAt` is when the row was appended — a string, never `.datetime()`:
1367
+ * the relay copies the client's `firedAt`, which the ingress accepts as a
1368
+ * diagnostic. `PendingEventConsumer` adapters validate every row through
1369
+ * this schema on append and, when rows come back from a serialization, on
1370
+ * drain — a malformed row never reaches an agent typed as a good entry.
1371
+ */
1372
+ export const pendingEventSchema = z.object({
1373
+ id: z.string().min(1),
1374
+ envelope: consumeEventEntrySchema,
1375
+ createdAt: z.string(),
1376
+ });
1348
1377
  /**
1349
1378
  * `ggui_consume`'s output — the drained rows, the session's state, and the
1350
1379
  * client's observations when the host sent any (ggui#817 part C2). The
@@ -7,7 +7,7 @@
7
7
  * persisting the result. Optionally pins as the operator default
8
8
  * for its `(appId, contractHash)` group.
9
9
  * - `ggui_ops_list_blueprints` — enumerate blueprint metadata
10
- * (no code body) under tenancy + optional filters. Sorted by
10
+ * (no code body) under the caller's app scope + optional filters. Sorted by
11
11
  * `createdAt desc`.
12
12
  * - `ggui_ops_update_blueprint` — toggle the operator-default flag
13
13
  * and/or patch variance tags. Immutable fields (contractHash,
@@ -19,7 +19,7 @@
19
19
  * The schemas live in `@ggui-ai/protocol` (not the handler package)
20
20
  * for the same reason all wire-shape schemas do: the protocol package
21
21
  * is the source of truth for every MCP wire surface, and consumers
22
- * (cloud pod handlers, console UI, fixture authors) can import from
22
+ * (a hosted deployment's handlers, console UI, fixture authors) can import from
23
23
  * one place. Handler package wraps these into `SharedHandler`
24
24
  * factories.
25
25
  */
@@ -69,11 +69,11 @@ export declare const opsGenerateBlueprintOutputSchema: z.ZodObject<{
69
69
  * - Seeding pre-vetted blueprints at deploy time (fixture corpus,
70
70
  * migration imports).
71
71
  * - Round-tripping export+reimport — operator exports a blueprint
72
- * from one tenant and re-registers it in another.
72
+ * from one app (or one deployment) and re-registers it in another.
73
73
  * - Reapplying a fixed version of a blueprint after live edits
74
74
  * (manual recovery from a bad generate run).
75
75
  *
76
- * Same tenancy + variance + default-pin semantics as
76
+ * Same app-scoping + variance + default-pin semantics as
77
77
  * `*_generate_*`; the only difference is the LLM/generator dispatch
78
78
  * is replaced with a verbatim accept of the operator's
79
79
  * `componentCode` string.
@@ -1 +1 @@
1
- {"version":3,"file":"ops-blueprint.d.ts","sourceRoot":"","sources":["../../src/schemas/ops-blueprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAYxB;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,+BAA+B;;;;;;;;;kBAgDjC,CAAC;AAEZ;;;;GAIG;AACH,eAAO,MAAM,gCAAgC;;;;;kBAqBlC,CAAC;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,+BAA+B;;;;;;;;;kBA+CjC,CAAC;AAEZ;;;;GAIG;AACH,eAAO,MAAM,gCAAgC;;;;kBAalC,CAAC;AAEZ;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,4BAA4B;;;;;;kBAoC9B,CAAC;AAEZ,eAAO,MAAM,6BAA6B;;kBAI/B,CAAC;AAEZ;;;;;;;;GAQG;AACH,eAAO,MAAM,6BAA6B;;;;;kBAsB/B,CAAC;AAEZ,eAAO,MAAM,8BAA8B;;;kBAKhC,CAAC;AAEZ;;;;GAIG;AACH,eAAO,MAAM,6BAA6B;;;kBAW/B,CAAC;AAEZ,eAAO,MAAM,8BAA8B;;kBAIhC,CAAC;AAEZ;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAC7C,OAAO,+BAA+B,CACvC,CAAC;AACF,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAC9C,OAAO,gCAAgC,CACxC,CAAC;AACF,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAC7C,OAAO,+BAA+B,CACvC,CAAC;AACF,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAC9C,OAAO,gCAAgC,CACxC,CAAC;AACF,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAC1C,OAAO,4BAA4B,CACpC,CAAC;AACF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AACF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AACF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAC5C,OAAO,8BAA8B,CACtC,CAAC;AACF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AACF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAC5C,OAAO,8BAA8B,CACtC,CAAC"}
1
+ {"version":3,"file":"ops-blueprint.d.ts","sourceRoot":"","sources":["../../src/schemas/ops-blueprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,+BAA+B;;;;;;;;;kBAkDjC,CAAC;AAEZ;;;;GAIG;AACH,eAAO,MAAM,gCAAgC;;;;;kBAqBlC,CAAC;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,+BAA+B;;;;;;;;;kBA+CjC,CAAC;AAEZ;;;;GAIG;AACH,eAAO,MAAM,gCAAgC;;;;kBAalC,CAAC;AAEZ;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,4BAA4B;;;;;;kBAsC9B,CAAC;AAEZ,eAAO,MAAM,6BAA6B;;kBAI/B,CAAC;AAEZ;;;;;;;;GAQG;AACH,eAAO,MAAM,6BAA6B;;;;;kBAsB/B,CAAC;AAEZ,eAAO,MAAM,8BAA8B;;;kBAKhC,CAAC;AAEZ;;;;GAIG;AACH,eAAO,MAAM,6BAA6B;;;kBAW/B,CAAC;AAEZ,eAAO,MAAM,8BAA8B;;kBAIhC,CAAC;AAEZ;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAC7C,OAAO,+BAA+B,CACvC,CAAC;AACF,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAC9C,OAAO,gCAAgC,CACxC,CAAC;AACF,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAC7C,OAAO,+BAA+B,CACvC,CAAC;AACF,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAC9C,OAAO,gCAAgC,CACxC,CAAC;AACF,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAC1C,OAAO,4BAA4B,CACpC,CAAC;AACF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AACF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AACF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAC5C,OAAO,8BAA8B,CACtC,CAAC;AACF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AACF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAC5C,OAAO,8BAA8B,CACtC,CAAC"}
@@ -7,7 +7,7 @@
7
7
  * persisting the result. Optionally pins as the operator default
8
8
  * for its `(appId, contractHash)` group.
9
9
  * - `ggui_ops_list_blueprints` — enumerate blueprint metadata
10
- * (no code body) under tenancy + optional filters. Sorted by
10
+ * (no code body) under the caller's app scope + optional filters. Sorted by
11
11
  * `createdAt desc`.
12
12
  * - `ggui_ops_update_blueprint` — toggle the operator-default flag
13
13
  * and/or patch variance tags. Immutable fields (contractHash,
@@ -19,11 +19,12 @@
19
19
  * The schemas live in `@ggui-ai/protocol` (not the handler package)
20
20
  * for the same reason all wire-shape schemas do: the protocol package
21
21
  * is the source of truth for every MCP wire surface, and consumers
22
- * (cloud pod handlers, console UI, fixture authors) can import from
22
+ * (a hosted deployment's handlers, console UI, fixture authors) can import from
23
23
  * one place. Handler package wraps these into `SharedHandler`
24
24
  * factories.
25
25
  */
26
26
  import { z } from 'zod';
27
+ import { GENERATOR_ID_PATTERN } from '../types/blueprint-source.js';
27
28
  import { dataContractSchema, jsonValueSchema, } from './data-contract.js';
28
29
  import { blueprintSchema, blueprintVarianceSchema, llmBlueprintSourceSchema, userBlueprintSourceSchema, } from './blueprint.js';
29
30
  /**
@@ -51,9 +52,11 @@ export const opsGenerateBlueprintInputSchema = z
51
52
  contract: dataContractSchema,
52
53
  generator: z
53
54
  .string()
54
- .min(1)
55
+ .regex(GENERATOR_ID_PATTERN, {
56
+ error: 'generator is an identity `ui-gen-<tier>` — one tier token, no model segment (ggui#924)',
57
+ })
55
58
  .optional()
56
- .describe('Generator slug (e.g. `ui-gen-default-haiku-4-5`). When omitted, dispatches through `GeneratorRegistry.defaultGenerator()`.'),
59
+ .describe('Generator identity (e.g. `ui-gen-default`; the model is chosen by the deployment and reported on `source.model`). When omitted, dispatches through `GeneratorRegistry.defaultGenerator()`.'),
57
60
  persona: z
58
61
  .string()
59
62
  .optional()
@@ -106,11 +109,11 @@ export const opsGenerateBlueprintOutputSchema = z
106
109
  * - Seeding pre-vetted blueprints at deploy time (fixture corpus,
107
110
  * migration imports).
108
111
  * - Round-tripping export+reimport — operator exports a blueprint
109
- * from one tenant and re-registers it in another.
112
+ * from one app (or one deployment) and re-registers it in another.
110
113
  * - Reapplying a fixed version of a blueprint after live edits
111
114
  * (manual recovery from a bad generate run).
112
115
  *
113
- * Same tenancy + variance + default-pin semantics as
116
+ * Same app-scoping + variance + default-pin semantics as
114
117
  * `*_generate_*`; the only difference is the LLM/generator dispatch
115
118
  * is replaced with a verbatim accept of the operator's
116
119
  * `componentCode` string.
@@ -206,9 +209,11 @@ export const opsListBlueprintsInputSchema = z
206
209
  .describe('Filter to a single `(appId, contractHash)` group. Combine with `generator` / `persona` to narrow within the group.'),
207
210
  generator: z
208
211
  .string()
209
- .min(1)
212
+ .regex(GENERATOR_ID_PATTERN, {
213
+ error: 'generator is an identity `ui-gen-<tier>` — one tier token, no model segment (ggui#924)',
214
+ })
210
215
  .optional()
211
- .describe('Filter to engine-generated blueprints (`source.kind === "llm"`) whose `source.generator` equals this slug. `user`-sourced rows never match (they carry no engine provenance).'),
216
+ .describe('Filter to engine-generated blueprints (`source.kind === "llm"`) whose `source.generator` equals this identity (`ui-gen-<tier>`, e.g. `ui-gen-advanced`). `user`-sourced rows never match (they carry no engine provenance).'),
212
217
  persona: z
213
218
  .string()
214
219
  .optional()
@@ -7,7 +7,7 @@ import { renderInputShape } from './mcp.js';
7
7
  * either wire form (canonical `provider:model` or LiteLLM `provider/model`;
8
8
  * aliases resolve in both). The render handler parses this BEFORE its
9
9
  * pre-generation gate, so a malformed route is a contract error at zod path
10
- * `infra.model` — never a policy refusal (`model_not_in_tier` is reserved
10
+ * `infra.model` — never a policy refusal (`model_not_allowed` is reserved
11
11
  * for a well-formed route with no rate row on the effective tier).
12
12
  *
13
13
  * Kept OUT of the registered shape on purpose: `@ggui-ai/iframe-runtime`
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * - `llm` — engine-generated. `generator` is the slug of the
13
13
  * {@link UiGenerator} that produced the component code; `model` is
14
- * the LLM model id the engine called. Both REQUIRED: every
14
+ * the route the engine called, as a `ModelRef`. Both REQUIRED: every
15
15
  * generation mint site has them in scope, and an engine-generated
16
16
  * artifact without them is not a real state.
17
17
  * - `user` — developer-registered / hand-authored. Covers
@@ -30,21 +30,41 @@
30
30
  * cache (invalidation = regeneration, never data loss), so unlabeled
31
31
  * rows are dropped at the trust boundary, never coerced.
32
32
  */
33
+ import { type ModelRef } from "./llm-route.js";
33
34
  /** Closed list of `BlueprintSource` discriminants. */
34
35
  export declare const BLUEPRINT_SOURCE_KINDS: readonly ["llm", "user", "curated"];
35
36
  /** Discriminant of {@link BlueprintSource}. */
36
37
  export type BlueprintSourceKind = (typeof BLUEPRINT_SOURCE_KINDS)[number];
38
+ /**
39
+ * The de-modeled generator identity (ggui#924): `ui-gen-` + ONE tier token
40
+ * — `ui-gen-default`, `ui-gen-advanced`, or an operator-defined tier. No
41
+ * model segment: the model is its own field, so a model retirement never
42
+ * renames an identity or re-keys a stored record. The template admits any
43
+ * `ui-gen-*` at the type level; {@link isGeneratorId} is the grammar.
44
+ */
45
+ export declare const GENERATOR_ID_PATTERN: RegExp;
46
+ /** A generator identity — see {@link GENERATOR_ID_PATTERN}. */
47
+ export type GeneratorId = `ui-gen-${string}`;
48
+ /** Whether `value` is a generator identity: one tier token, no model segment. */
49
+ export declare function isGeneratorId(value: string): value is GeneratorId;
37
50
  /** Engine-generated — full engine provenance is mandatory. */
38
51
  export interface LlmBlueprintSource {
39
52
  readonly kind: "llm";
40
53
  /**
41
- * Slug of the generator that produced the component code (e.g.
42
- * `'ui-gen-default-haiku-4-5'`). The server's `GeneratorRegistry` is
43
- * the authority for which slugs exist on a given deployment.
54
+ * The generator identity that produced the component code (e.g.
55
+ * `'ui-gen-default'`), de-modeled — see {@link GENERATOR_ID_PATTERN}.
56
+ * The server's `GeneratorRegistry` is the authority for which
57
+ * identities exist on a given deployment.
58
+ */
59
+ readonly generator: GeneratorId;
60
+ /**
61
+ * The route the generator's LLM call used, rendered in the registry's
62
+ * spelling (`<prefix>/<model>`; {@link ModelRef}, composed only by
63
+ * `modelRefOfRoute`). Registry ids (`'anthropic/claude-haiku-4-5'`) are
64
+ * the subset the registry lists; a self-hoster's bedrock or OpenRouter
65
+ * route is a ref too. One spelling per route: a dated wire id is refused.
44
66
  */
45
- readonly generator: string;
46
- /** Model id of the LLM call the generator made. */
47
- readonly model: string;
67
+ readonly model: ModelRef;
48
68
  }
49
69
  /** Developer-registered / hand-authored — no engine provenance exists. */
50
70
  export interface UserBlueprintSource {
@@ -1 +1 @@
1
- {"version":3,"file":"blueprint-source.d.ts","sourceRoot":"","sources":["../../src/types/blueprint-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAIH,sDAAsD;AACtD,eAAO,MAAM,sBAAsB,qCAAsC,CAAC;AAE1E,+CAA+C;AAC/C,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E,8DAA8D;AAC9D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,0EAA0E;AAC1E,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;CAC1B;AAED,MAAM,MAAM,eAAe,GACvB,kBAAkB,GAClB,mBAAmB,GACnB,sBAAsB,CAAC;AAE3B;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAoB3E;AAED,uDAAuD;AACvD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAE1E;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,0BAA0B;;;;CAI7B,CAAC;AAEX;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,qEAAqE;AACrE,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,eAAe,GACtB,mBAAmB,CAQrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE;IACzC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC,GAAG,eAAe,GAAG,IAAI,CAMzB"}
1
+ {"version":3,"file":"blueprint-source.d.ts","sourceRoot":"","sources":["../../src/types/blueprint-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAExD,sDAAsD;AACtD,eAAO,MAAM,sBAAsB,qCAAsC,CAAC;AAE1E,+CAA+C;AAC/C,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,QAAuB,CAAC;AAEzD,+DAA+D;AAC/D,MAAM,MAAM,WAAW,GAAG,UAAU,MAAM,EAAE,CAAC;AAE7C,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,WAAW,CAEjE;AAED,8DAA8D;AAC9D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC;IAChC;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B;AAED,0EAA0E;AAC1E,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,0EAA0E;AAC1E,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;CAC1B;AAED,MAAM,MAAM,eAAe,GACvB,kBAAkB,GAClB,mBAAmB,GACnB,sBAAsB,CAAC;AAE3B;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAuB3E;AAED,uDAAuD;AACvD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAE1E;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,0BAA0B;;;;CAI7B,CAAC;AAEX;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,qEAAqE;AACrE,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,eAAe,GACtB,mBAAmB,CAQrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE;IACzC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC,GAAG,eAAe,GAAG,IAAI,CAMzB"}
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * - `llm` — engine-generated. `generator` is the slug of the
13
13
  * {@link UiGenerator} that produced the component code; `model` is
14
- * the LLM model id the engine called. Both REQUIRED: every
14
+ * the route the engine called, as a `ModelRef`. Both REQUIRED: every
15
15
  * generation mint site has them in scope, and an engine-generated
16
16
  * artifact without them is not a real state.
17
17
  * - `user` — developer-registered / hand-authored. Covers
@@ -31,8 +31,21 @@
31
31
  * rows are dropped at the trust boundary, never coerced.
32
32
  */
33
33
  import { isRecord } from "../validation/is-record.js";
34
+ import { isModelRef } from "./llm-route.js";
34
35
  /** Closed list of `BlueprintSource` discriminants. */
35
36
  export const BLUEPRINT_SOURCE_KINDS = ["llm", "user", "curated"];
37
+ /**
38
+ * The de-modeled generator identity (ggui#924): `ui-gen-` + ONE tier token
39
+ * — `ui-gen-default`, `ui-gen-advanced`, or an operator-defined tier. No
40
+ * model segment: the model is its own field, so a model retirement never
41
+ * renames an identity or re-keys a stored record. The template admits any
42
+ * `ui-gen-*` at the type level; {@link isGeneratorId} is the grammar.
43
+ */
44
+ export const GENERATOR_ID_PATTERN = /^ui-gen-[a-z0-9]+$/;
45
+ /** Whether `value` is a generator identity: one tier token, no model segment. */
46
+ export function isGeneratorId(value) {
47
+ return GENERATOR_ID_PATTERN.test(value);
48
+ }
36
49
  /**
37
50
  * Validating narrower for trust boundaries (DB row → union, JSON
38
51
  * artifact → union). Returns a CANONICAL rebuild of the union value —
@@ -50,9 +63,12 @@ export function parseBlueprintSource(value) {
50
63
  case "llm": {
51
64
  const generator = v["generator"];
52
65
  const model = v["model"];
53
- if (typeof generator !== "string" || generator.length === 0)
66
+ // ggui#924: a modeled identity (`ui-gen-default-haiku-4-5`) or a
67
+ // non-route model (a bare `claude-…`, a dated API name) is not a
68
+ // provenance — null.
69
+ if (typeof generator !== "string" || !isGeneratorId(generator))
54
70
  return null;
55
- if (typeof model !== "string" || model.length === 0)
71
+ if (typeof model !== "string" || !isModelRef(model))
56
72
  return null;
57
73
  return { kind: "llm", generator, model };
58
74
  }
@@ -18,7 +18,7 @@
18
18
  * advanced-generator iterative-loop output routinely exceeds
19
19
  * them). The in-memory adapter skips the body store (in-process
20
20
  * `Map<codeHash, string>`).
21
- * - **Tenancy.** Scoped per `(appId, contractHash)`. Different apps'
21
+ * - **App scope.** Scoped per `(appId, contractHash)`. Different apps'
22
22
  * contract may coincidentally hash the same; their blueprints
23
23
  * must never cross-pollinate. Rows are keyed by `blueprintId`;
24
24
  * lookups go through an indexed `(appId, contractHash)` query.
@@ -127,7 +127,7 @@ export interface Blueprint {
127
127
  * key.
128
128
  */
129
129
  readonly contractHash: string;
130
- /** Tenancy scope. Composite secondary key with `contractHash`. */
130
+ /** App scope. Composite secondary key with `contractHash`. */
131
131
  readonly appId: string;
132
132
  /**
133
133
  * S3 URL (`s3://<bucket>/<key>`) of the generated code body when
@@ -1 +1 @@
1
- {"version":3,"file":"blueprint.d.ts","sourceRoot":"","sources":["../../src/types/blueprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEnE;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,sBAAsB;IACrC;;qDAEiD;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;0CACsC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;yCACqC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;yCACqC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,wBAAwB;IACvC;8CAC0C;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACnD;yCACqC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,mEAAmE;IACnE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;;;;;;;;;OASG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC;;;;;;;;;OASG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,IAAI,CAAC;IAClC,qDAAqD;IACrD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,UAAU,CAAC;IACzC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAChD"}
1
+ {"version":3,"file":"blueprint.d.ts","sourceRoot":"","sources":["../../src/types/blueprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEnE;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,sBAAsB;IACrC;;qDAEiD;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;0CACsC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;yCACqC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;yCACqC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,wBAAwB;IACvC;8CAC0C;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACnD;yCACqC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,mEAAmE;IACnE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;;;;;;;;;OASG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC;;;;;;;;;OASG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,IAAI,CAAC;IAClC,qDAAqD;IACrD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,UAAU,CAAC;IACzC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAChD"}
@@ -188,7 +188,7 @@ export interface StreamChannelEntry {
188
188
  * `CTR_SCHEMA_INCOMPAT` linter additionally checks that the feed
189
189
  * tool's declared return schema is a subset of this schema — see
190
190
  * the docstring on {@link ActionEntry.schema} for the schema-subset
191
- * algorithm and the `SCHEMA_MISMATCH_ERROR` failure surface.
191
+ * algorithm and the `schema_mismatch_error` failure surface.
192
192
  */
193
193
  schema: JsonSchema;
194
194
  /** Example payload (used for documentation and smoke testing). Typed as {@link JsonValue}. */
@@ -276,7 +276,7 @@ export interface ActionEntry {
276
276
  * advisory — the agent owns the actual tool call on its next turn
277
277
  * and is responsible for shaping the payload as the tool expects.
278
278
  * For tools registered on THIS server, the F4 schema-compat checker
279
- * surfaces a `SCHEMA_MISMATCH_ERROR` at render-time / blueprint-
279
+ * surfaces a `schema_mismatch_error` at render-time / blueprint-
280
280
  * registration-time so authors get fail-loud feedback.
281
281
  *
282
282
  * The canonical algorithm lives in
@@ -610,7 +610,7 @@ export interface GadgetDescriptor {
610
610
  package: string;
611
611
  /**
612
612
  * ggui-hosted bundle URL — the preferred distribution path. Same
613
- * origin as the iframe in single-tenant OSS deployments (served
613
+ * origin as the iframe in single-deployment installs (served
614
614
  * from `/_ggui/libs/<libId>/bundle.js`) and the ggui marketplace
615
615
  * CDN in cloud deployments. CSP `script-src` allowlists only the
616
616
  * ggui origin — no per-plugin third-party origins.
@@ -0,0 +1,167 @@
1
+ /**
2
+ * The Plane-2 registry — the ONLY list of domain-error slugs (ggui#880).
3
+ *
4
+ * SPEC §7.9 Plane 2: a recoverable, contract-level failure the caller can
5
+ * fix — a missing session or handshake, props that do not satisfy the
6
+ * contract, an undeclared channel. The MCP SDK ships a thrown handler error
7
+ * to the agent as `{content: [{type: 'text', text: error.message}],
8
+ * isError: true}` and nothing else, so the slug travels as the LEADING
9
+ * token of that text — `<code>: <detail>` — composed by the `DomainError`
10
+ * base in `../errors/domain-error` from a code in this registry. A reader
11
+ * branches on `text.startsWith(code + ': ')` for a registered code and on
12
+ * nothing else.
13
+ *
14
+ * Same posture as the refusal registry in `./refusal-codes`: `code === key`
15
+ * is forced at the definer, the code type is derived from the keys, and
16
+ * the two registries are disjoint (pinned) — one code names one plane.
17
+ */
18
+ /**
19
+ * How a caller recovers from a Plane-2 failure.
20
+ *
21
+ * - `retry-same-id` — fix the input and retry on the SAME handshakeId /
22
+ * sessionId; nothing was consumed.
23
+ * - `re-mint` — the id itself is gone (unknown, consumed, expired,
24
+ * another app's); mint a fresh one (`ggui_handshake`, then `ggui_render`).
25
+ * - `later` — a dependency the server fetches was unavailable; time
26
+ * restores it, the input was fine.
27
+ */
28
+ export declare const DOMAIN_ERROR_RECOVERIES: readonly ["retry-same-id", "re-mint", "later"];
29
+ /** One member of {@link DOMAIN_ERROR_RECOVERIES}. */
30
+ export type DomainErrorRecovery = (typeof DOMAIN_ERROR_RECOVERIES)[number];
31
+ /**
32
+ * A data-plane `tools/call` name a Plane-2 slug may be emitted on. The
33
+ * template admits any `ggui_*` name at the type level; the registry's own
34
+ * suite narrows every row's `tools` to the data-plane set (no `ggui_ops_*`,
35
+ * no `ggui_protocol_*`).
36
+ */
37
+ export type DataPlaneToolName = `ggui_${string}`;
38
+ /**
39
+ * The registry with its per-key literal types kept (ggui#889):
40
+ * `DOMAIN_ERROR_ROWS.session_not_found.code` is `'session_not_found'`,
41
+ * its `recovery` is `'re-mint'`. {@link DOMAIN_ERROR_REGISTRY} is the
42
+ * same object read through the normalized row type.
43
+ */
44
+ export declare const DOMAIN_ERROR_ROWS: {
45
+ readonly session_not_found: {
46
+ readonly code: "session_not_found";
47
+ readonly tools: readonly ["ggui_consume", "ggui_get_session", "ggui_get_render_source", "ggui_update", "ggui_amend", "ggui_emit", "ggui_runtime_pull"];
48
+ readonly recovery: "re-mint";
49
+ readonly emitter: "the session lookup on every session-scoped tool";
50
+ readonly description: "The sessionId names no session this caller can reach — never minted, expired, closed, or owned by another app (cross-app access surfaces uniformly). Re-handshake and re-render to mint a fresh one.";
51
+ };
52
+ readonly handshake_not_found: {
53
+ readonly code: "handshake_not_found";
54
+ readonly tools: readonly ["ggui_render"];
55
+ readonly recovery: "re-mint";
56
+ readonly emitter: "the handshake-record lookup at ggui_render";
57
+ readonly description: "The handshakeId is unknown, already consumed by a render, or expired. Call ggui_handshake again for a fresh id, then render with the new pair.";
58
+ };
59
+ readonly contract_violation: {
60
+ readonly code: "contract_violation";
61
+ readonly tools: readonly ["ggui_render", "ggui_update", "ggui_amend", "ggui_emit"];
62
+ readonly recovery: "retry-same-id";
63
+ readonly emitter: "the props / payload validator against the contract";
64
+ readonly description: "Props or a payload do not satisfy the contract's spec — a missing required prop included. Fix the values and retry with the same id; nothing was consumed.";
65
+ };
66
+ readonly schema_mismatch_error: {
67
+ readonly code: "schema_mismatch_error";
68
+ readonly tools: readonly ["ggui_render"];
69
+ readonly recovery: "retry-same-id";
70
+ readonly emitter: "the schema-compatibility check between the contract and the registered tool shapes";
71
+ readonly description: "An actionSpec or streamSpec schema is not a subset of the named tool's registered shape. Adjust the contract or the tool, then retry with the same handshakeId.";
72
+ };
73
+ readonly contract_validation_failed: {
74
+ readonly code: "contract_validation_failed";
75
+ readonly tools: readonly ["ggui_render"];
76
+ readonly recovery: "retry-same-id";
77
+ readonly emitter: "the contract lint gate (shape, retired fields, schema metadata, cross-references, schema compatibility)";
78
+ readonly description: "The contract failed the lint gate; the detail names the category and the finding. Fix the contract and retry with the same handshakeId.";
79
+ };
80
+ readonly override_contract_invalid: {
81
+ readonly code: "override_contract_invalid";
82
+ readonly tools: readonly ["ggui_render"];
83
+ readonly recovery: "retry-same-id";
84
+ readonly emitter: "the override gate at ggui_render";
85
+ readonly description: "override.contract failed validation — an override commits the caller to a conforming contract. Drop the override and render the suggestion, or fix the draft.";
86
+ };
87
+ readonly channel_not_declared: {
88
+ readonly code: "channel_not_declared";
89
+ readonly tools: readonly ["ggui_emit"];
90
+ readonly recovery: "retry-same-id";
91
+ readonly emitter: "ggui_emit's channel check against the contract's streamSpec";
92
+ readonly description: "The channel is not declared by the session's contract. Emit on a declared channel; the detail lists them.";
93
+ };
94
+ readonly invalid_complete: {
95
+ readonly code: "invalid_complete";
96
+ readonly tools: readonly ["ggui_emit"];
97
+ readonly recovery: "retry-same-id";
98
+ readonly emitter: "ggui_emit's completion check";
99
+ readonly description: "A completion was signalled for a channel that cannot complete in its current state. Emit on the channel first, or omit the completion.";
100
+ };
101
+ readonly gadget_not_registered: {
102
+ readonly code: "gadget_not_registered";
103
+ readonly tools: readonly ["ggui_render"];
104
+ readonly recovery: "retry-same-id";
105
+ readonly emitter: "the gadget gate at ggui_render";
106
+ readonly description: "A clientCapabilities.gadgets reference names an export the app's gadget registry does not carry. Drop the reference or fix the name; the detail suggests the nearest match.";
107
+ };
108
+ readonly gadget_package_mismatch: {
109
+ readonly code: "gadget_package_mismatch";
110
+ readonly tools: readonly ["ggui_render"];
111
+ readonly recovery: "retry-same-id";
112
+ readonly emitter: "the gadget gate at ggui_render";
113
+ readonly description: "A gadget export is registered, but only under a different package than the contract requested. Request the registered package; the detail names it.";
114
+ };
115
+ readonly gadget_public_env_missing: {
116
+ readonly code: "gadget_public_env_missing";
117
+ readonly tools: readonly ["ggui_render"];
118
+ readonly recovery: "retry-same-id";
119
+ readonly emitter: "the gadget gate at ggui_render";
120
+ readonly description: "A registered wrapper requires a public-env key the app has not set. Set the key on the app's public env, then retry.";
121
+ };
122
+ readonly duplicate_gadget_hook: {
123
+ readonly code: "duplicate_gadget_hook";
124
+ readonly tools: readonly ["ggui_render"];
125
+ readonly recovery: "retry-same-id";
126
+ readonly emitter: "the gadget gate at ggui_render";
127
+ readonly description: "Two gadget packages export the same name; the generated import would collide. Reference one of them.";
128
+ };
129
+ readonly gadget_types_fetch_failed: {
130
+ readonly code: "gadget_types_fetch_failed";
131
+ readonly tools: readonly ["ggui_render"];
132
+ readonly recovery: "later";
133
+ readonly emitter: "the gadget type fetch before cold generation";
134
+ readonly description: "Fetching a gadget package's types failed; the input was fine. Retry after a short delay.";
135
+ };
136
+ readonly gadget_catalog_integrity: {
137
+ readonly code: "gadget_catalog_integrity";
138
+ readonly tools: readonly ["ggui_render"];
139
+ readonly recovery: "retry-same-id";
140
+ readonly emitter: "the app's gadget catalog resolver at ggui_render";
141
+ readonly description: "The app's gadget catalog is inconsistent with its registrations. Repair the catalog, then retry with the same handshakeId.";
142
+ };
143
+ readonly blueprint_rejected: {
144
+ readonly code: "blueprint_rejected";
145
+ readonly tools: readonly ["ggui_render"];
146
+ readonly recovery: "retry-same-id";
147
+ readonly emitter: "the blueprint registry on registration";
148
+ readonly description: "The blueprint was rejected by the registry's error-level findings; the detail lists them. Fix the contract and retry with the same handshakeId.";
149
+ };
150
+ };
151
+ /** A domain-error code = a registry key. Derived; never a second list. */
152
+ export type DomainErrorCode = keyof typeof DOMAIN_ERROR_ROWS;
153
+ /** A registry row, as consumers read it. */
154
+ export interface DomainErrorRow {
155
+ readonly code: DomainErrorCode;
156
+ readonly tools: readonly DataPlaneToolName[];
157
+ readonly recovery: DomainErrorRecovery;
158
+ readonly emitter: string;
159
+ readonly description: string;
160
+ }
161
+ /** The registry consumers read. */
162
+ export declare const DOMAIN_ERROR_REGISTRY: Readonly<Record<DomainErrorCode, DomainErrorRow>>;
163
+ /** Whether `value` is a registered domain-error code. */
164
+ export declare function isDomainErrorCode(value: string): value is DomainErrorCode;
165
+ /** Every registered code, in registry order. */
166
+ export declare const DOMAIN_ERROR_CODES: readonly DomainErrorCode[];
167
+ //# sourceMappingURL=domain-error-codes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-error-codes.d.ts","sourceRoot":"","sources":["../../src/types/domain-error-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,gDAAiD,CAAC;AAEtF,qDAAqD;AACrD,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3E;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,MAAM,EAAE,CAAC;AAyBjD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsI5B,CAAC;AAEH,0EAA0E;AAC1E,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,iBAAiB,CAAC;AAE7D,4CAA4C;AAC5C,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC7C,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,mCAAmC;AACnC,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,cAAc,CAAC,CACjE,CAAC;AAEpB,yDAAyD;AACzD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,eAAe,CAEzE;AAED,gDAAgD;AAChD,eAAO,MAAM,kBAAkB,EAAE,SAAS,eAAe,EACC,CAAC"}