@ggui-ai/protocol 0.14.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.
- package/dist/envelopes/render-refusal.d.ts +49 -0
- package/dist/envelopes/render-refusal.d.ts.map +1 -0
- package/dist/envelopes/render-refusal.js +12 -0
- package/dist/errors/domain-error.d.ts +70 -0
- package/dist/errors/domain-error.d.ts.map +1 -0
- package/dist/errors/domain-error.js +118 -0
- package/dist/gadgets/resolve-app-gadgets.d.ts +1 -1
- package/dist/gadgets/stdlib-gadgets.d.ts +2 -2
- package/dist/gadgets/stdlib-gadgets.js +1 -1
- package/dist/index.d.ts +69 -63
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/integrations/mcp-apps.d.ts +35 -9
- package/dist/integrations/mcp-apps.d.ts.map +1 -1
- package/dist/integrations/mcp-apps.js +13 -13
- package/dist/integrations/overlay-hash.d.ts +19 -0
- package/dist/integrations/overlay-hash.d.ts.map +1 -0
- package/dist/integrations/overlay-hash.js +29 -0
- package/dist/integrations/theme-binding.d.ts +14 -12
- package/dist/integrations/theme-binding.d.ts.map +1 -1
- package/dist/integrations/theme-binding.js +10 -6
- package/dist/registry/blueprint-key.d.ts.map +1 -1
- package/dist/registry/blueprint-key.js +4 -3
- package/dist/schemas/app-theme.d.ts +46 -10
- package/dist/schemas/app-theme.d.ts.map +1 -1
- package/dist/schemas/app-theme.js +108 -40
- package/dist/schemas/blueprint.d.ts +4 -3
- package/dist/schemas/blueprint.d.ts.map +1 -1
- package/dist/schemas/blueprint.js +15 -3
- package/dist/schemas/data-contract.d.ts +11 -31
- package/dist/schemas/data-contract.d.ts.map +1 -1
- package/dist/schemas/data-contract.js +5 -28
- package/dist/schemas/handshake-suggestion.d.ts.map +1 -1
- package/dist/schemas/handshake-suggestion.js +8 -1
- package/dist/schemas/interface-context.d.ts +44 -0
- package/dist/schemas/interface-context.d.ts.map +1 -0
- package/dist/schemas/interface-context.js +22 -0
- package/dist/schemas/invoke.d.ts +3 -3
- package/dist/schemas/invoke.js +1 -1
- package/dist/schemas/mcp.d.ts +246 -111
- package/dist/schemas/mcp.d.ts.map +1 -1
- package/dist/schemas/mcp.js +149 -42
- package/dist/schemas/ops-blueprint.d.ts +4 -4
- package/dist/schemas/ops-blueprint.d.ts.map +1 -1
- package/dist/schemas/ops-blueprint.js +13 -8
- package/dist/schemas/public-env-key.d.ts +26 -0
- package/dist/schemas/public-env-key.d.ts.map +1 -0
- package/dist/schemas/public-env-key.js +25 -0
- package/dist/schemas/render-input-envelope.d.ts +2 -2
- package/dist/schemas/render-input-envelope.js +1 -1
- package/dist/schemas/runtime-telemetry-limits.d.ts +11 -0
- package/dist/schemas/runtime-telemetry-limits.d.ts.map +1 -0
- package/dist/schemas/runtime-telemetry-limits.js +10 -0
- package/dist/transport/websocket.d.ts +5 -5
- package/dist/types/auth.d.ts +1 -1
- package/dist/types/blueprint-source.d.ts +27 -7
- package/dist/types/blueprint-source.d.ts.map +1 -1
- package/dist/types/blueprint-source.js +19 -3
- package/dist/types/blueprint.d.ts +2 -2
- package/dist/types/blueprint.d.ts.map +1 -1
- package/dist/types/contract-inference.d.ts +1 -1
- package/dist/types/data-contract.d.ts +3 -3
- package/dist/types/domain-error-codes.d.ts +167 -0
- package/dist/types/domain-error-codes.d.ts.map +1 -0
- package/dist/types/domain-error-codes.js +170 -0
- package/dist/types/events.d.ts +1 -1
- package/dist/types/ggui-session-event.d.ts +2 -2
- package/dist/types/handshake-suggestion.d.ts +2 -2
- package/dist/types/host-context.d.ts +3 -3
- package/dist/types/interface-context.d.ts +1 -1
- package/dist/types/invoke.d.ts +1 -1
- package/dist/types/lifecycle.d.ts +1 -1
- package/dist/types/live-channel.d.ts +3 -3
- package/dist/types/llm-route.d.ts +59 -2
- package/dist/types/llm-route.d.ts.map +1 -1
- package/dist/types/llm-route.js +62 -16
- package/dist/types/llm.d.ts +22 -2
- package/dist/types/llm.d.ts.map +1 -1
- package/dist/types/llm.js +29 -2
- package/dist/types/mcp.d.ts +49 -100
- package/dist/types/mcp.d.ts.map +1 -1
- package/dist/types/mcp.js +28 -9
- package/dist/types/refusal-codes.d.ts +54 -95
- package/dist/types/refusal-codes.d.ts.map +1 -1
- package/dist/types/refusal-codes.js +67 -105
- package/dist/types/render.d.ts +12 -11
- package/dist/types/render.d.ts.map +1 -1
- package/dist/types/ui-generator.d.ts +1 -1
- package/dist/validation/ajv-runtime.d.ts +2 -2
- package/dist/validation/contract-validator.d.ts +14 -8
- package/dist/validation/contract-validator.d.ts.map +1 -1
- package/dist/validation/contract-validator.js +12 -4
- package/dist/validation/cross-references.d.ts +2 -2
- package/dist/validation/hygiene-rules.d.ts +1 -1
- package/dist/validation/lint-contract.d.ts +2 -2
- package/dist/validation/lint-contract.d.ts.map +1 -1
- package/dist/validation/lint-contract.js +6 -4
- package/dist/validation/name-invariants.d.ts +2 -2
- package/dist/validation/reserved-channels.d.ts +1 -1
- package/dist/validation/schema-compat-invariants.d.ts +2 -2
- package/dist/validation/schema-meta-validation.d.ts +1 -1
- package/dist/validation/schema-subset.d.ts +3 -3
- package/dist/version.d.ts +485 -12
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +484 -11
- package/dist/wire.d.ts +45 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +44 -0
- package/package.json +7 -1
- package/dist/envelope-adapters.d.ts +0 -25
- package/dist/envelope-adapters.d.ts.map +0 -1
- package/dist/envelope-adapters.js +0 -14
|
@@ -131,18 +131,7 @@ export function deriveContextName(slotKey) {
|
|
|
131
131
|
* @public
|
|
132
132
|
*/
|
|
133
133
|
export const MCP_APP_AI_GGUI_RENDER_META_KEY = 'ai.ggui/render';
|
|
134
|
-
|
|
135
|
-
* Read the `ai.ggui/render` slice off a parsed JSON-RPC `_meta` object.
|
|
136
|
-
*
|
|
137
|
-
* Structural validation only. Missing key returns `{ok: true, meta: undefined}`
|
|
138
|
-
* — not a failure. Required-fields gate (sessionId / appId / runtimeUrl)
|
|
139
|
-
* fires only when the key is present. Field-level optional-field
|
|
140
|
-
* defensive parsing (e.g. context-slot schema narrowing, expiresAt date
|
|
141
|
-
* parse) lives downstream in the iframe-runtime's `validateMeta`.
|
|
142
|
-
*
|
|
143
|
-
* @public
|
|
144
|
-
*/
|
|
145
|
-
export function parseMcpAppAiGguiRenderMeta(meta) {
|
|
134
|
+
export function parseMcpAppAiGguiRenderMeta(meta, options = {}) {
|
|
146
135
|
if (!isRecord(meta)) {
|
|
147
136
|
return { ok: true };
|
|
148
137
|
}
|
|
@@ -241,6 +230,9 @@ export function parseMcpAppAiGguiRenderMeta(meta) {
|
|
|
241
230
|
// slice (tolerant degrade, consistent with the other optional fields).
|
|
242
231
|
const themeParse = s.theme !== undefined ? appThemeSchema.safeParse(s.theme) : undefined;
|
|
243
232
|
const parsedTheme = themeParse?.success === true ? themeParse.data : undefined;
|
|
233
|
+
if (themeParse !== undefined && !themeParse.success) {
|
|
234
|
+
options.onInvalidTheme?.(themeParse.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`));
|
|
235
|
+
}
|
|
244
236
|
const slice = {
|
|
245
237
|
sessionId: s.sessionId,
|
|
246
238
|
appId: s.appId,
|
|
@@ -601,6 +593,14 @@ export function isGguiSubmitActionInput(value) {
|
|
|
601
593
|
return true;
|
|
602
594
|
}
|
|
603
595
|
}
|
|
596
|
+
/**
|
|
597
|
+
* Narrow a guarded envelope to its `dispatch` member. Sound because
|
|
598
|
+
* {@link isGguiSubmitActionInput}'s closed-set `switch` validates the
|
|
599
|
+
* `'dispatch'` payload before any extension kind can carry that literal.
|
|
600
|
+
*/
|
|
601
|
+
export function isGguiSubmitDispatchInput(env) {
|
|
602
|
+
return env.kind === 'dispatch';
|
|
603
|
+
}
|
|
604
604
|
/**
|
|
605
605
|
* Does this slice carry at least one MOUNT MODE discriminator?
|
|
606
606
|
* Mirrors the iframe-runtime's `validateMeta`: the runtime needs
|
|
@@ -686,7 +686,7 @@ export function toolResultGguiRender(result) {
|
|
|
686
686
|
*
|
|
687
687
|
* @public
|
|
688
688
|
*/
|
|
689
|
-
export const GGUI_RENDER_SHELL_SURFACE = 'var(--ggui-shell-background, var(--ggui-color-
|
|
689
|
+
export const GGUI_RENDER_SHELL_SURFACE = 'var(--ggui-shell-background, var(--ggui-color-ground, var(--ggui-shell-scheme-surface, #f9fafb)))';
|
|
690
690
|
/**
|
|
691
691
|
* Inline `<style>` block that gives the shell's pre-render placeholder
|
|
692
692
|
* a SCHEME-AWARE neutral ground (#662). Before the runtime injects
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Overlay attestation (ggui#987 §6.3): ONE canonical serialization and ONE
|
|
3
|
+
* hash for the per-app theme overlay, so every minter (a platform's
|
|
4
|
+
* projector, a console, a CLI) and every write door compute the same bytes.
|
|
5
|
+
*
|
|
6
|
+
* Canonical JSON: object keys sorted recursively, no whitespace, `undefined`
|
|
7
|
+
* members omitted, strings/numbers as JSON emits them. Hash: SHA-256 over the
|
|
8
|
+
* UTF-8 bytes, lowercase hex. Async because it uses Web Crypto
|
|
9
|
+
* (`globalThis.crypto.subtle`), available in every runtime the protocol
|
|
10
|
+
* targets.
|
|
11
|
+
*/
|
|
12
|
+
import type { AppTheme } from '../schemas/app-theme.js';
|
|
13
|
+
/** The attested part of an overlay — never `mode`, `name` or `frameless`. */
|
|
14
|
+
export type OverlayHashInput = Pick<AppTheme, 'overlays' | 'cssVariables' | 'keyframes'>;
|
|
15
|
+
/** The canonical JSON the hash is taken over — exported so tests and other minters can pin it. */
|
|
16
|
+
export declare function canonicalOverlayJson(input: OverlayHashInput): string;
|
|
17
|
+
/** `sha256(canonicalOverlayJson(input))` as lowercase hex — the value `AppTheme.overlayHash` carries. */
|
|
18
|
+
export declare function canonicalOverlayHash(input: OverlayHashInput): Promise<string>;
|
|
19
|
+
//# sourceMappingURL=overlay-hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlay-hash.d.ts","sourceRoot":"","sources":["../../src/integrations/overlay-hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,6EAA6E;AAC7E,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,QAAQ,EAAE,UAAU,GAAG,cAAc,GAAG,WAAW,CAAC,CAAC;AAczF,kGAAkG;AAClG,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAOpE;AAMD,yGAAyG;AACzG,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAGnF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
function canonicalize(v) {
|
|
2
|
+
if (v === undefined)
|
|
3
|
+
return 'null';
|
|
4
|
+
if (v === null || typeof v !== 'object')
|
|
5
|
+
return JSON.stringify(v);
|
|
6
|
+
if (Array.isArray(v))
|
|
7
|
+
return `[${v.map((x) => canonicalize(x)).join(',')}]`;
|
|
8
|
+
const keys = Object.keys(v)
|
|
9
|
+
.filter((k) => v[k] !== undefined)
|
|
10
|
+
.sort();
|
|
11
|
+
return `{${keys.map((k) => `${JSON.stringify(k)}:${canonicalize(v[k])}`).join(',')}}`;
|
|
12
|
+
}
|
|
13
|
+
/** The canonical JSON the hash is taken over — exported so tests and other minters can pin it. */
|
|
14
|
+
export function canonicalOverlayJson(input) {
|
|
15
|
+
const doc = {
|
|
16
|
+
overlays: input.overlays,
|
|
17
|
+
cssVariables: input.cssVariables,
|
|
18
|
+
keyframes: input.keyframes,
|
|
19
|
+
};
|
|
20
|
+
return canonicalize(doc);
|
|
21
|
+
}
|
|
22
|
+
function toHex(bytes) {
|
|
23
|
+
return Array.from(new Uint8Array(bytes), (b) => b.toString(16).padStart(2, '0')).join('');
|
|
24
|
+
}
|
|
25
|
+
/** `sha256(canonicalOverlayJson(input))` as lowercase hex — the value `AppTheme.overlayHash` carries. */
|
|
26
|
+
export async function canonicalOverlayHash(input) {
|
|
27
|
+
const bytes = new TextEncoder().encode(canonicalOverlayJson(input));
|
|
28
|
+
return toHex(await globalThis.crypto.subtle.digest('SHA-256', bytes));
|
|
29
|
+
}
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* ## The normative total order
|
|
8
8
|
*
|
|
9
9
|
* ```
|
|
10
|
-
* themeMode: consolePick > staticConfig > sessionSidecar
|
|
11
|
-
* themeId: consolePick > renderOverride > staticConfig
|
|
10
|
+
* themeMode: hostAnnounced > consolePick > staticConfig > sessionSidecar
|
|
11
|
+
* themeId: consolePick > renderOverride > staticConfig
|
|
12
12
|
* ```
|
|
13
13
|
*
|
|
14
14
|
* - `consolePick` — the live operator pick (console theme provider).
|
|
@@ -17,8 +17,12 @@
|
|
|
17
17
|
* - `sessionSidecar` — the per-app `App.theme` sidecar snapshotted at
|
|
18
18
|
* render-commit: its `mode` (for `themeMode`) / its `name` (for
|
|
19
19
|
* `themeId`, the registered-theme base-ladder binding).
|
|
20
|
-
* - `hostAnnounced` — the embedding host's `hostContext.theme`
|
|
21
|
-
*
|
|
20
|
+
* - `hostAnnounced` — the embedding host's `hostContext.theme` (mode
|
|
21
|
+
* only; hosts announce no theme id). HIGHEST rank since ggui#987 (D4):
|
|
22
|
+
* the embedding host owns runtime mode; every other layer is a default
|
|
23
|
+
* the host's announce overrides. A one-palette sidecar can no longer
|
|
24
|
+
* exist (`appThemeSchema` requires both projections), so following the
|
|
25
|
+
* host never paints the wrong palette.
|
|
22
26
|
*
|
|
23
27
|
* An unresolved fact is `undefined` — NEVER defaulted to `'light'`.
|
|
24
28
|
* Absence is load-bearing: it is the signal that lets the next layer
|
|
@@ -72,7 +76,7 @@ export interface ThemeModeEffectiveSources {
|
|
|
72
76
|
readonly stamped?: ThemeModeOpinion | undefined;
|
|
73
77
|
/** The slice theme OBJECT's own `mode` (the sidecar, read directly). */
|
|
74
78
|
readonly sessionSidecar?: ThemeModeOpinion | undefined;
|
|
75
|
-
/** The embedding host's `hostContext.theme` announce —
|
|
79
|
+
/** The embedding host's `hostContext.theme` announce — HIGHEST rank (ggui#987). */
|
|
76
80
|
readonly hostAnnounced?: ThemeModeOpinion | undefined;
|
|
77
81
|
}
|
|
78
82
|
/** Server projection of the `themeMode` total order → the stamped field. */
|
|
@@ -88,16 +92,14 @@ export interface ThemeIdStampSources {
|
|
|
88
92
|
/** Static `ggui.json#theme` deps. */
|
|
89
93
|
readonly staticConfig?: string | undefined;
|
|
90
94
|
}
|
|
91
|
-
/**
|
|
95
|
+
/**
|
|
96
|
+
* Client-visible `themeId` layers. Since ggui#987 (D2 = B, the registration
|
|
97
|
+
* tier is gone) the sidecar's `name` is a label and never a binding: the
|
|
98
|
+
* only client-visible layer is the stamp.
|
|
99
|
+
*/
|
|
92
100
|
export interface ThemeIdEffectiveSources {
|
|
93
101
|
/** The slice's stamped top-level `themeId`. */
|
|
94
102
|
readonly stamped?: string | undefined;
|
|
95
|
-
/**
|
|
96
|
-
* The slice theme OBJECT's `name` — the registered-theme base-ladder
|
|
97
|
-
* binding (ggui#589 ask 3): an unregistered name is harmless by
|
|
98
|
-
* construction (renderer falls back to the default ladder).
|
|
99
|
-
*/
|
|
100
|
-
readonly sidecarName?: string | undefined;
|
|
101
103
|
}
|
|
102
104
|
/** Server projection of the `themeId` total order → the stamped field. */
|
|
103
105
|
export declare function stampThemeId(s: ThemeIdStampSources): string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-binding.d.ts","sourceRoot":"","sources":["../../src/integrations/theme-binding.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"theme-binding.d.ts","sourceRoot":"","sources":["../../src/integrations/theme-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AAEH,4EAA4E;AAC5E,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,CAAC;AAEhD,6DAA6D;AAC7D,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,QAAQ,CAAC,WAAW,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACpD,qCAAqC;IACrC,QAAQ,CAAC,YAAY,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACrD,mEAAmE;IACnE,QAAQ,CAAC,cAAc,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;CACxD;AAED,6DAA6D;AAC7D,MAAM,WAAW,yBAAyB;IACxC,kFAAkF;IAClF,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAChD,wEAAwE;IACxE,QAAQ,CAAC,cAAc,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACvD,mFAAmF;IACnF,QAAQ,CAAC,aAAa,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;CACvD;AAED,4EAA4E;AAC5E,wBAAgB,cAAc,CAC5B,CAAC,EAAE,qBAAqB,GACvB,gBAAgB,GAAG,SAAS,CAE9B;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAChC,CAAC,EAAE,yBAAyB,GAC3B,gBAAgB,GAAG,SAAS,CAE9B;AAED,2DAA2D;AAC3D,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,kEAAkE;IAClE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7C,qCAAqC;IACrC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5C;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,CAAC,EAAE,mBAAmB,GAAG,MAAM,GAAG,SAAS,CAEvE;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,uBAAuB,GAAG,MAAM,GAAG,SAAS,CAE/E"}
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* ## The normative total order
|
|
8
8
|
*
|
|
9
9
|
* ```
|
|
10
|
-
* themeMode: consolePick > staticConfig > sessionSidecar
|
|
11
|
-
* themeId: consolePick > renderOverride > staticConfig
|
|
10
|
+
* themeMode: hostAnnounced > consolePick > staticConfig > sessionSidecar
|
|
11
|
+
* themeId: consolePick > renderOverride > staticConfig
|
|
12
12
|
* ```
|
|
13
13
|
*
|
|
14
14
|
* - `consolePick` — the live operator pick (console theme provider).
|
|
@@ -17,8 +17,12 @@
|
|
|
17
17
|
* - `sessionSidecar` — the per-app `App.theme` sidecar snapshotted at
|
|
18
18
|
* render-commit: its `mode` (for `themeMode`) / its `name` (for
|
|
19
19
|
* `themeId`, the registered-theme base-ladder binding).
|
|
20
|
-
* - `hostAnnounced` — the embedding host's `hostContext.theme`
|
|
21
|
-
*
|
|
20
|
+
* - `hostAnnounced` — the embedding host's `hostContext.theme` (mode
|
|
21
|
+
* only; hosts announce no theme id). HIGHEST rank since ggui#987 (D4):
|
|
22
|
+
* the embedding host owns runtime mode; every other layer is a default
|
|
23
|
+
* the host's announce overrides. A one-palette sidecar can no longer
|
|
24
|
+
* exist (`appThemeSchema` requires both projections), so following the
|
|
25
|
+
* host never paints the wrong palette.
|
|
22
26
|
*
|
|
23
27
|
* An unresolved fact is `undefined` — NEVER defaulted to `'light'`.
|
|
24
28
|
* Absence is load-bearing: it is the signal that lets the next layer
|
|
@@ -61,7 +65,7 @@ export function stampThemeMode(s) {
|
|
|
61
65
|
}
|
|
62
66
|
/** Client projection of the `themeMode` total order → the effective mode. */
|
|
63
67
|
export function effectiveThemeMode(s) {
|
|
64
|
-
return s.
|
|
68
|
+
return s.hostAnnounced ?? s.stamped ?? s.sessionSidecar;
|
|
65
69
|
}
|
|
66
70
|
/** Server projection of the `themeId` total order → the stamped field. */
|
|
67
71
|
export function stampThemeId(s) {
|
|
@@ -69,5 +73,5 @@ export function stampThemeId(s) {
|
|
|
69
73
|
}
|
|
70
74
|
/** Client projection of the `themeId` total order → the effective id. */
|
|
71
75
|
export function effectiveThemeId(s) {
|
|
72
|
-
return s.stamped
|
|
76
|
+
return s.stamped;
|
|
73
77
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blueprint-key.d.ts","sourceRoot":"","sources":["../../src/registry/blueprint-key.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"blueprint-key.d.ts","sourceRoot":"","sources":["../../src/registry/blueprint-key.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAG9D;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,YAAY,GAAG,SAAS,GAAG,MAAM,CAGvE;AAMD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,iCAAiC,EACjC,+BAA+B,EAC/B,KAAK,uBAAuB,EAC5B,KAAK,6BAA6B,GACnC,MAAM,yBAAyB,CAAC;AAIjC,cAAc,sBAAsB,CAAC"}
|
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
* 16-character sha256 prefix — matches the existing `blueprintHash`
|
|
11
11
|
* shape in `cache-trace-sink` and `generation-cache.ts`. Collision
|
|
12
12
|
* probability for 100s-of-thousands of distinct contract is ~10^-6
|
|
13
|
-
* (birthday-bound on 2^64), well below the budget for
|
|
14
|
-
*
|
|
15
|
-
* by appId so the bound
|
|
13
|
+
* (birthday-bound on 2^64), well below the budget for a single
|
|
14
|
+
* deployment's key space. A deployment that serves many apps scopes
|
|
15
|
+
* keys by `appId`, so the bound holds per app, never across the whole
|
|
16
|
+
* store.
|
|
16
17
|
*/
|
|
17
18
|
import { createHash } from 'node:crypto';
|
|
18
19
|
import { canonicalizeContracts } from './canonicalize-contract.js';
|
|
@@ -26,23 +26,59 @@ export declare const GGUI_CSS_VAR_KEY_RE: RegExp;
|
|
|
26
26
|
* bare regex on its own.
|
|
27
27
|
*/
|
|
28
28
|
export declare const CSS_VALUE_SAFE_RE: RegExp;
|
|
29
|
+
/**
|
|
30
|
+
* The grammar a per-mode `keyframes` string MUST satisfy (ggui#987 §3.4,
|
|
31
|
+
* follower D). The renderer injects the text verbatim into the card's
|
|
32
|
+
* `<style>` after the variables, so the text is bounded to what that slot
|
|
33
|
+
* is FOR: zero or more `@keyframes <ident> { <frame-selectors> { <declarations> } … }`
|
|
34
|
+
* blocks and nothing else — no other at-rule (`@import`, `@font-face`,
|
|
35
|
+
* `@media`, …), no `<` / `>`, braces balanced and nested exactly one level
|
|
36
|
+
* inside a block. Comments (`/* … *\/`) are stripped before the walk and are
|
|
37
|
+
* therefore allowed, as `cssVariableMap` values allow `url(`; the deny-list
|
|
38
|
+
* on values (`;{}<>@`) cannot apply verbatim here because `;`, `{`, `}` and
|
|
39
|
+
* the one `@` ARE the grammar. Same principal, same slot, one rule.
|
|
40
|
+
*/
|
|
41
|
+
export declare const KEYFRAMES_NAME_RE: RegExp;
|
|
42
|
+
export declare function isKeyframesText(text: string): boolean;
|
|
29
43
|
export declare const appThemeSchema: z.ZodObject<{
|
|
30
|
-
mode: z.ZodEnum<{
|
|
44
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
31
45
|
light: "light";
|
|
32
46
|
dark: "dark";
|
|
33
|
-
}
|
|
34
|
-
cssVariables: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
47
|
+
}>>;
|
|
35
48
|
name: z.ZodOptional<z.ZodString>;
|
|
36
|
-
|
|
37
|
-
|
|
49
|
+
overlayHash: z.ZodString;
|
|
50
|
+
overlays: z.ZodObject<{
|
|
38
51
|
light: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
39
52
|
dark: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
53
|
+
}, z.core.$strict>;
|
|
54
|
+
cssVariables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
55
|
+
keyframes: z.ZodOptional<z.ZodObject<{
|
|
56
|
+
light: z.ZodOptional<z.ZodString>;
|
|
57
|
+
dark: z.ZodOptional<z.ZodString>;
|
|
45
58
|
}, z.core.$strict>>;
|
|
59
|
+
frameless: z.ZodOptional<z.ZodBoolean>;
|
|
46
60
|
}, z.core.$strict>;
|
|
47
61
|
export type AppTheme = z.infer<typeof appThemeSchema>;
|
|
62
|
+
/**
|
|
63
|
+
* The ONE refusal body every write door returns for an overlay it will not
|
|
64
|
+
* store (ggui#987 §3.4): REST 422 `invalid_app_config`, the AppSync
|
|
65
|
+
* `errorInfo`, the MCP ops door's `{ ok: false }` structured content. A
|
|
66
|
+
* discriminated union by key — exactly one of the four.
|
|
67
|
+
*/
|
|
68
|
+
export declare const appThemeRefusalBodySchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
69
|
+
uncovered: z.ZodObject<{
|
|
70
|
+
light: z.ZodArray<z.ZodString>;
|
|
71
|
+
dark: z.ZodArray<z.ZodString>;
|
|
72
|
+
}, z.core.$strict>;
|
|
73
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
74
|
+
unknown: z.ZodObject<{
|
|
75
|
+
light: z.ZodArray<z.ZodString>;
|
|
76
|
+
dark: z.ZodArray<z.ZodString>;
|
|
77
|
+
}, z.core.$strict>;
|
|
78
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
79
|
+
overlayHash: z.ZodLiteral<"mismatch">;
|
|
80
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
81
|
+
refused: z.ZodLiteral<"v1 shape">;
|
|
82
|
+
}, z.core.$strict>]>;
|
|
83
|
+
export type AppThemeRefusalBody = z.infer<typeof appThemeRefusalBodySchema>;
|
|
48
84
|
//# sourceMappingURL=app-theme.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-theme.d.ts","sourceRoot":"","sources":["../../src/schemas/app-theme.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,QAA2B,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,QAAiB,CAAC;AAahD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"app-theme.d.ts","sourceRoot":"","sources":["../../src/schemas/app-theme.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,QAA2B,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,QAAiB,CAAC;AAahD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,QAA+B,CAAC;AAE9D,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAoCrD;AAQD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;kBAuChB,CAAC;AAEZ,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;oBAKpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
|
|
@@ -35,54 +35,122 @@ const cssValue = z
|
|
|
35
35
|
const cssVariableMap = z
|
|
36
36
|
.record(z.string().regex(GGUI_CSS_VAR_KEY_RE, 'css var key must be --ggui-*'), cssValue)
|
|
37
37
|
.refine((m) => Object.keys(m).length <= 200, 'too many css variables (max 200)');
|
|
38
|
+
/**
|
|
39
|
+
* The grammar a per-mode `keyframes` string MUST satisfy (ggui#987 §3.4,
|
|
40
|
+
* follower D). The renderer injects the text verbatim into the card's
|
|
41
|
+
* `<style>` after the variables, so the text is bounded to what that slot
|
|
42
|
+
* is FOR: zero or more `@keyframes <ident> { <frame-selectors> { <declarations> } … }`
|
|
43
|
+
* blocks and nothing else — no other at-rule (`@import`, `@font-face`,
|
|
44
|
+
* `@media`, …), no `<` / `>`, braces balanced and nested exactly one level
|
|
45
|
+
* inside a block. Comments (`/* … *\/`) are stripped before the walk and are
|
|
46
|
+
* therefore allowed, as `cssVariableMap` values allow `url(`; the deny-list
|
|
47
|
+
* on values (`;{}<>@`) cannot apply verbatim here because `;`, `{`, `}` and
|
|
48
|
+
* the one `@` ARE the grammar. Same principal, same slot, one rule.
|
|
49
|
+
*/
|
|
50
|
+
export const KEYFRAMES_NAME_RE = /^[A-Za-z_-][A-Za-z0-9_-]*$/;
|
|
51
|
+
export function isKeyframesText(text) {
|
|
52
|
+
const s = text.replace(/\/\*[\s\S]*?\*\//g, ' ');
|
|
53
|
+
if (/[<>]/.test(s))
|
|
54
|
+
return false;
|
|
55
|
+
let i = 0;
|
|
56
|
+
const n = s.length;
|
|
57
|
+
const skipWs = () => {
|
|
58
|
+
while (i < n && /\s/.test(s[i]))
|
|
59
|
+
i += 1;
|
|
60
|
+
};
|
|
61
|
+
for (;;) {
|
|
62
|
+
skipWs();
|
|
63
|
+
if (i >= n)
|
|
64
|
+
return true;
|
|
65
|
+
if (!s.startsWith('@keyframes', i))
|
|
66
|
+
return false;
|
|
67
|
+
i += '@keyframes'.length;
|
|
68
|
+
if (i >= n || !/\s/.test(s[i]))
|
|
69
|
+
return false;
|
|
70
|
+
skipWs();
|
|
71
|
+
const nameStart = i;
|
|
72
|
+
while (i < n && /[A-Za-z0-9_-]/.test(s[i]))
|
|
73
|
+
i += 1;
|
|
74
|
+
if (!KEYFRAMES_NAME_RE.test(s.slice(nameStart, i)))
|
|
75
|
+
return false;
|
|
76
|
+
skipWs();
|
|
77
|
+
if (s[i] !== '{')
|
|
78
|
+
return false;
|
|
79
|
+
i += 1;
|
|
80
|
+
// Inside the block: frame rules only — `selectors { declarations }` at depth 1, no `@`.
|
|
81
|
+
let depth = 1;
|
|
82
|
+
while (i < n && depth > 0) {
|
|
83
|
+
const ch = s[i];
|
|
84
|
+
if (ch === '@')
|
|
85
|
+
return false;
|
|
86
|
+
if (ch === '{') {
|
|
87
|
+
depth += 1;
|
|
88
|
+
if (depth > 2)
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
else if (ch === '}') {
|
|
92
|
+
depth -= 1;
|
|
93
|
+
}
|
|
94
|
+
i += 1;
|
|
95
|
+
}
|
|
96
|
+
if (depth !== 0)
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/** A per-mode keyframes string: `@keyframes` blocks only (see {@link isKeyframesText}), 8 KiB cap unchanged. */
|
|
101
|
+
const keyframesText = z
|
|
102
|
+
.string()
|
|
103
|
+
.max(8192)
|
|
104
|
+
.refine(isKeyframesText, 'keyframes must be `@keyframes <name> { … }` blocks and nothing else');
|
|
38
105
|
export const appThemeSchema = z
|
|
39
106
|
.object({
|
|
40
|
-
|
|
41
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Default appearance: the mode painted when NO embedding host announces
|
|
109
|
+
* one. Never a pin — the host owns runtime mode (ggui#987 D4; see
|
|
110
|
+
* `integrations/theme-binding.ts`). Absent ⇒ mode-neutral.
|
|
111
|
+
*/
|
|
112
|
+
mode: z.enum(['light', 'dark']).optional(),
|
|
113
|
+
/** A label the author's tooling reads back. Never resolved by a renderer. */
|
|
42
114
|
name: z.string().min(1).max(64).optional(),
|
|
43
115
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* delivery never depends on the iframe being able to fetch. The
|
|
48
|
-
* renderer injects the mode-selected set BELOW `cssVariables` (the
|
|
49
|
-
* per-app overlay) in the documented precedence. `documentHash` is
|
|
50
|
-
* the registration's identity: it joins painted ladders to
|
|
51
|
-
* registration records, and a receiver holding the hash may be
|
|
52
|
-
* served a future envelope without the variable sets.
|
|
116
|
+
* Delivery attestation: `canonicalOverlayHash({ overlays, cssVariables,
|
|
117
|
+
* keyframes })` (`integrations/overlay-hash.ts`). Every write door
|
|
118
|
+
* recomputes it and refuses a mismatch; read doors pass it through.
|
|
53
119
|
*/
|
|
54
|
-
|
|
120
|
+
overlayHash: z.string().regex(/^[0-9a-f]{64}$/, 'overlayHash must be sha256 lowercase hex'),
|
|
121
|
+
/**
|
|
122
|
+
* The projection, both modes — the derived `--ggui-*` sets a card
|
|
123
|
+
* injects for the effective mode (ggui#987 §2.4: produced by ONE
|
|
124
|
+
* function on every path). REQUIRED, both: an overlay that could not
|
|
125
|
+
* follow the host's mode is not accepted.
|
|
126
|
+
*/
|
|
127
|
+
overlays: z.object({ light: cssVariableMap, dark: cssVariableMap }).strict(),
|
|
128
|
+
/** Mode-agnostic per-app overrides, injected above both projections. */
|
|
129
|
+
cssVariables: cssVariableMap.optional(),
|
|
130
|
+
/** Per-mode `@keyframes` blocks, injected verbatim after the variables — bounded to that grammar by {@link isKeyframesText}. */
|
|
131
|
+
keyframes: z
|
|
55
132
|
.object({
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
.regex(/^[0-9a-f]{64}$/, 'documentHash must be sha256 lowercase hex'),
|
|
59
|
-
light: cssVariableMap,
|
|
60
|
-
dark: cssVariableMap,
|
|
61
|
-
/**
|
|
62
|
-
* Per-mode `@keyframes` blocks from the registration document
|
|
63
|
-
* (ggui#613 residual 2). A mode key is absent when its
|
|
64
|
-
* document declares no motion keyframes; the whole field is
|
|
65
|
-
* absent on pre-#613 registrations (additive optional — old
|
|
66
|
-
* bases stay valid). Injected verbatim after the variable
|
|
67
|
-
* ladder, same position the compiled path gives
|
|
68
|
-
* `theme.cssKeyframes`.
|
|
69
|
-
*/
|
|
70
|
-
keyframes: z
|
|
71
|
-
.object({
|
|
72
|
-
light: z.string().max(8192).optional(),
|
|
73
|
-
dark: z.string().max(8192).optional(),
|
|
74
|
-
})
|
|
75
|
-
.strict()
|
|
76
|
-
.optional(),
|
|
77
|
-
/**
|
|
78
|
-
* `$metadata.frameless` delivered (OR of both modes): the
|
|
79
|
-
* embedding host owns the card silhouette, so the renderer
|
|
80
|
-
* appends the root-children border-suppression rule — the
|
|
81
|
-
* SAME rule the compiled path emits.
|
|
82
|
-
*/
|
|
83
|
-
frameless: z.boolean().optional(),
|
|
133
|
+
light: keyframesText.optional(),
|
|
134
|
+
dark: keyframesText.optional(),
|
|
84
135
|
})
|
|
85
136
|
.strict()
|
|
86
137
|
.optional(),
|
|
138
|
+
/**
|
|
139
|
+
* The embedding host owns the card silhouette: the renderer appends the
|
|
140
|
+
* root-children border-suppression rule.
|
|
141
|
+
*/
|
|
142
|
+
frameless: z.boolean().optional(),
|
|
87
143
|
})
|
|
88
144
|
.strict();
|
|
145
|
+
/**
|
|
146
|
+
* The ONE refusal body every write door returns for an overlay it will not
|
|
147
|
+
* store (ggui#987 §3.4): REST 422 `invalid_app_config`, the AppSync
|
|
148
|
+
* `errorInfo`, the MCP ops door's `{ ok: false }` structured content. A
|
|
149
|
+
* discriminated union by key — exactly one of the four.
|
|
150
|
+
*/
|
|
151
|
+
export const appThemeRefusalBodySchema = z.union([
|
|
152
|
+
z.object({ uncovered: z.object({ light: z.array(z.string()), dark: z.array(z.string()) }).strict() }).strict(),
|
|
153
|
+
z.object({ unknown: z.object({ light: z.array(z.string()), dark: z.array(z.string()) }).strict() }).strict(),
|
|
154
|
+
z.object({ overlayHash: z.literal('mismatch') }).strict(),
|
|
155
|
+
z.object({ refused: z.literal('v1 shape') }).strict(),
|
|
156
|
+
]);
|
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
* here is `z.ZodType<Blueprint>` so any drift fails compile.
|
|
6
6
|
*/
|
|
7
7
|
import { z } from 'zod';
|
|
8
|
-
import type { AppBlueprintSearchConfig, Blueprint, BlueprintVariance } from '../types/blueprint';
|
|
9
|
-
import type { BlueprintSource, CuratedBlueprintSource, LlmBlueprintSource, UserBlueprintSource } from '../types/blueprint-source';
|
|
8
|
+
import type { AppBlueprintSearchConfig, Blueprint, BlueprintVariance } from '../types/blueprint.js';
|
|
9
|
+
import type { BlueprintSource, CuratedBlueprintSource, LlmBlueprintSource, UserBlueprintSource } from '../types/blueprint-source.js';
|
|
10
10
|
/**
|
|
11
11
|
* Zod mirror of {@link LlmBlueprintSource} — the engine-generated arm.
|
|
12
12
|
* Both provenance fields are REQUIRED: every generation mint site has
|
|
13
13
|
* them in scope, and an engine-generated artifact that cannot name its
|
|
14
|
-
* engine + model is not a real state.
|
|
14
|
+
* engine + model is not a real state. Since ggui#924 the identity is
|
|
15
|
+
* de-modeled (`ui-gen-<tier>`) and the model is the run's `ModelRef`.
|
|
15
16
|
*/
|
|
16
17
|
export declare const llmBlueprintSourceSchema: z.ZodType<LlmBlueprintSource>;
|
|
17
18
|
/** Zod mirror of {@link UserBlueprintSource} — no engine claim exists. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blueprint.d.ts","sourceRoot":"","sources":["../../src/schemas/blueprint.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EACV,wBAAwB,EACxB,SAAS,EACT,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,eAAe,EACf,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"blueprint.d.ts","sourceRoot":"","sources":["../../src/schemas/blueprint.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EACV,wBAAwB,EACxB,SAAS,EACT,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,eAAe,EACf,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,2BAA2B,CAAC;AAKnC;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAexD,CAAC;AAEZ,0EAA0E;AAC1E,eAAO,MAAM,yBAAyB,EAAE,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAExB,CAAC;AAE9C,oDAAoD;AACpD,eAAO,MAAM,4BAA4B,EAAE,CAAC,CAAC,OAAO,CAAC,sBAAsB,CAE3B,CAAC;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,CAI7B,CAAC;AAEjC;;;;;;;;;GASG;AACH,sFAAsF;AACtF,eAAO,MAAM,uBAAuB,4DAA6D,CAAC;AAElG,eAAO,MAAM,uBAAuB,EAAE,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAgCtB,CAAC;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAwBd,CAAC;AAmBpC;;;GAGG;AACH,eAAO,MAAM,8BAA8B,EAAE,CAAC,CAAC,OAAO,CAAC,wBAAwB,CAM7B,CAAC"}
|
|
@@ -5,18 +5,30 @@
|
|
|
5
5
|
* here is `z.ZodType<Blueprint>` so any drift fails compile.
|
|
6
6
|
*/
|
|
7
7
|
import { z } from 'zod';
|
|
8
|
+
import { isGeneratorId } from '../types/blueprint-source.js';
|
|
9
|
+
import { MODEL_REF_PREFIXES, isModelRef } from '../types/llm-route.js';
|
|
8
10
|
import { dataContractSchema, jsonValueSchema } from './data-contract.js';
|
|
9
11
|
/**
|
|
10
12
|
* Zod mirror of {@link LlmBlueprintSource} — the engine-generated arm.
|
|
11
13
|
* Both provenance fields are REQUIRED: every generation mint site has
|
|
12
14
|
* them in scope, and an engine-generated artifact that cannot name its
|
|
13
|
-
* engine + model is not a real state.
|
|
15
|
+
* engine + model is not a real state. Since ggui#924 the identity is
|
|
16
|
+
* de-modeled (`ui-gen-<tier>`) and the model is the run's `ModelRef`.
|
|
14
17
|
*/
|
|
15
18
|
export const llmBlueprintSourceSchema = z
|
|
16
19
|
.object({
|
|
17
20
|
kind: z.literal('llm'),
|
|
18
|
-
|
|
19
|
-
model
|
|
21
|
+
// ggui#924: the de-modeled identity and the run's `ModelRef` — a
|
|
22
|
+
// modeled id, a bare model name or a second spelling is refused here,
|
|
23
|
+
// naming the field. Template literals (not `z.custom`) so the fields
|
|
24
|
+
// keep their literal types AND render to JSON Schema as `pattern` —
|
|
25
|
+
// this schema is embedded in tool inputs that `tools/list` renders.
|
|
26
|
+
generator: z.templateLiteral(['ui-gen-', z.string()]).refine(isGeneratorId, {
|
|
27
|
+
error: 'generator is the de-modeled identity `ui-gen-<tier>` — one tier token, no model segment (e.g. `ui-gen-default`)',
|
|
28
|
+
}),
|
|
29
|
+
model: z.templateLiteral([z.enum(MODEL_REF_PREFIXES), '/', z.string()]).refine(isModelRef, {
|
|
30
|
+
error: 'model is the run route in the registry spelling `<prefix>/<model>` (e.g. `anthropic/claude-haiku-4-5`)',
|
|
31
|
+
}),
|
|
20
32
|
})
|
|
21
33
|
.strict();
|
|
22
34
|
/** Zod mirror of {@link UserBlueprintSource} — no engine claim exists. */
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Output-side seams that type-narrow contract on the wire —
|
|
8
8
|
* `renderOutputSchema.contract` and the various `decision` echoes — use
|
|
9
9
|
* `z.custom<DataContract>()` because they trust the shape (it
|
|
10
|
-
* originates from internal
|
|
10
|
+
* originates from internal server state).
|
|
11
11
|
*
|
|
12
12
|
* The input seam is different: agents author contract on
|
|
13
13
|
* `story.contract` and the handler MUST plumb them to the generator.
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
* just to accept the contract and pass it to the generator.
|
|
52
52
|
*/
|
|
53
53
|
import { z } from 'zod';
|
|
54
|
-
import type { DataContract, JsonValue, JsonSchema, JsonObject } from '../types/data-contract';
|
|
54
|
+
import type { DataContract, JsonValue, JsonSchema, JsonObject } from '../types/data-contract.js';
|
|
55
55
|
/**
|
|
56
56
|
* Recursive {@link JsonValue} — string | number | boolean | null |
|
|
57
57
|
* array | object. All fields on contract entries that carry default
|
|
@@ -211,26 +211,6 @@ export declare const agentCapabilitiesSpecSchema: z.ZodObject<{
|
|
|
211
211
|
}, z.core.$strict>>;
|
|
212
212
|
}, z.core.$strict>>;
|
|
213
213
|
}, z.core.$loose>;
|
|
214
|
-
/**
|
|
215
|
-
* `App.publicEnv` key regex.
|
|
216
|
-
*
|
|
217
|
-
* Each key in `App.publicEnv` MUST match this pattern. The prefix is
|
|
218
|
-
* the **security boundary** — operators can't accidentally stash
|
|
219
|
-
* sensitive credentials under arbitrary names, and downstream consumers
|
|
220
|
-
* (render gate, bootstrap projection, iframe shim) can rely on the
|
|
221
|
-
* naming convention to mean "public-by-design".
|
|
222
|
-
*
|
|
223
|
-
* Rule: `GGUI_PUBLIC_APP_` prefix, then uppercase letters / digits /
|
|
224
|
-
* underscores, at least one char after the prefix.
|
|
225
|
-
*
|
|
226
|
-
* `GGUI_PUBLIC_USER_*` keys are RESERVED for a future per-user
|
|
227
|
-
* channel. The current regex rejects them so App-side config can't
|
|
228
|
-
* pre-emptively use the namespace.
|
|
229
|
-
*
|
|
230
|
-
* Hoisted above `gadgetDescriptorSchema` so the wrapper's `requires`
|
|
231
|
-
* array can reference it at schema-construction time (TDZ-safe).
|
|
232
|
-
*/
|
|
233
|
-
export declare const PUBLIC_ENV_APP_KEY_RE: RegExp;
|
|
234
214
|
/**
|
|
235
215
|
* Single source of truth for the `requires[]` field shape on gadget
|
|
236
216
|
* descriptors. The wire-permissive `gadgetDescriptorSchema`, the
|
|
@@ -244,7 +224,7 @@ export declare const PUBLIC_ENV_APP_KEY_RE: RegExp;
|
|
|
244
224
|
* that declare a `requires` key must have a corresponding App-side
|
|
245
225
|
* publicEnv value at render time (gate: `assertPublicEnvSatisfied`).
|
|
246
226
|
*/
|
|
247
|
-
export declare const gadgetRequiresSchema: z.
|
|
227
|
+
export declare const gadgetRequiresSchema: z.ZodArray<z.ZodString>;
|
|
248
228
|
/**
|
|
249
229
|
* SRI hash format for gadget bundles. Registry install writes
|
|
250
230
|
* `bundleSri` in this shape; iframe-runtime emits it verbatim into
|
|
@@ -367,7 +347,7 @@ export declare function bundleHostScheme(host: string): 'http' | 'https';
|
|
|
367
347
|
* needs the grammars and which this module imports
|
|
368
348
|
* `KNOWN_PERMISSION_NAMES` from).
|
|
369
349
|
*/
|
|
370
|
-
export { HOOK_NAME_RE, COMPONENT_NAME_RE } from './gadget-name-grammar';
|
|
350
|
+
export { HOOK_NAME_RE, COMPONENT_NAME_RE } from './gadget-name-grammar.js';
|
|
371
351
|
/**
|
|
372
352
|
* Wire-permissive {@link GadgetExport} schema — a union of a
|
|
373
353
|
* hook-export shape (carries `hook`) and a component-export shape
|
|
@@ -475,8 +455,8 @@ export declare const gadgetDescriptorSchema: z.ZodObject<{
|
|
|
475
455
|
bundleHost: z.ZodOptional<z.ZodString>;
|
|
476
456
|
bundleSri: z.ZodOptional<z.ZodString>;
|
|
477
457
|
styleUrl: z.ZodOptional<z.ZodURL>;
|
|
478
|
-
connect: z.ZodOptional<z.
|
|
479
|
-
requires: z.ZodOptional<z.
|
|
458
|
+
connect: z.ZodOptional<z.ZodArray<z.ZodURL>>;
|
|
459
|
+
requires: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
480
460
|
typesUrl: z.ZodOptional<z.ZodURL>;
|
|
481
461
|
typesSri: z.ZodOptional<z.ZodString>;
|
|
482
462
|
}, z.core.$strict>;
|
|
@@ -550,8 +530,8 @@ export declare const strictGadgetDescriptorSchema: z.ZodObject<{
|
|
|
550
530
|
bundleHost: z.ZodOptional<z.ZodString>;
|
|
551
531
|
bundleSri: z.ZodOptional<z.ZodString>;
|
|
552
532
|
styleUrl: z.ZodOptional<z.ZodURL>;
|
|
553
|
-
connect: z.ZodOptional<z.
|
|
554
|
-
requires: z.ZodOptional<z.
|
|
533
|
+
connect: z.ZodOptional<z.ZodArray<z.ZodURL>>;
|
|
534
|
+
requires: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
555
535
|
typesUrl: z.ZodOptional<z.ZodURL>;
|
|
556
536
|
typesSri: z.ZodOptional<z.ZodString>;
|
|
557
537
|
}, z.core.$strict>;
|
|
@@ -640,8 +620,8 @@ export declare const registeredGadgetDescriptorSchema: z.ZodObject<{
|
|
|
640
620
|
bundleHost: z.ZodOptional<z.ZodString>;
|
|
641
621
|
bundleSri: z.ZodOptional<z.ZodString>;
|
|
642
622
|
styleUrl: z.ZodOptional<z.ZodURL>;
|
|
643
|
-
connect: z.ZodOptional<z.
|
|
644
|
-
requires: z.ZodOptional<z.
|
|
623
|
+
connect: z.ZodOptional<z.ZodArray<z.ZodURL>>;
|
|
624
|
+
requires: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
645
625
|
typesUrl: z.ZodOptional<z.ZodURL>;
|
|
646
626
|
typesSri: z.ZodOptional<z.ZodString>;
|
|
647
627
|
}, z.core.$strict>;
|
|
@@ -718,7 +698,7 @@ export declare const clientCapabilitiesSpecSchema: z.ZodObject<{
|
|
|
718
698
|
* - Defensive re-validation in the iframe-runtime slice-meta
|
|
719
699
|
* extractors (`parseMetaFromGlobal`, `parseMetaFromToolResult`).
|
|
720
700
|
*/
|
|
721
|
-
export declare const appPublicEnvSchema: z.
|
|
701
|
+
export declare const appPublicEnvSchema: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
722
702
|
/**
|
|
723
703
|
* {@link DataContract} — the unified four-spec contract surface
|
|
724
704
|
* agents author on `story.contract` and that the generator
|