@ggui-ai/protocol 0.2.0-alpha.4 → 0.4.0-rc.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/README.md +16 -16
- package/dist/envelope-adapters.d.ts +6 -5
- package/dist/envelope-adapters.d.ts.map +1 -1
- package/dist/envelope-adapters.js +3 -3
- package/dist/envelopes/builders.d.ts +6 -32
- package/dist/envelopes/builders.d.ts.map +1 -1
- package/dist/envelopes/builders.js +3 -25
- package/dist/errors/version-mismatch.d.ts +1 -1
- package/dist/errors/version-mismatch.js +1 -1
- package/dist/gadgets/resolve-app-gadgets.d.ts +10 -0
- package/dist/gadgets/resolve-app-gadgets.d.ts.map +1 -0
- package/dist/gadgets/resolve-app-gadgets.js +19 -0
- package/dist/gadgets/resolve-contract-gadgets.d.ts +6 -6
- package/dist/gadgets/resolve-contract-gadgets.js +5 -5
- package/dist/gadgets/stdlib-gadgets.d.ts +1 -1
- package/dist/gadgets/stdlib-gadgets.d.ts.map +1 -1
- package/dist/gadgets/stdlib-gadgets.js +43 -22
- package/dist/iframe-bridge.d.ts +4 -43
- package/dist/iframe-bridge.d.ts.map +1 -1
- package/dist/iframe-bridge.js +4 -141
- package/dist/index.d.ts +60 -62
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +66 -61
- package/dist/integrations/mcp-apps.d.ts +83 -38
- package/dist/integrations/mcp-apps.d.ts.map +1 -1
- package/dist/integrations/mcp-apps.js +98 -52
- package/dist/recommended-prompts.d.ts +1 -1
- package/dist/recommended-prompts.js +1 -1
- package/dist/registry/blueprint-key.d.ts +3 -0
- package/dist/registry/blueprint-key.d.ts.map +1 -1
- package/dist/registry/blueprint-key.js +9 -0
- package/dist/registry/blueprint-stamp.d.ts +12 -0
- package/dist/registry/blueprint-stamp.d.ts.map +1 -0
- package/dist/registry/blueprint-stamp.js +12 -0
- package/dist/registry/canonicalize-contract.d.ts +31 -2
- package/dist/registry/canonicalize-contract.d.ts.map +1 -1
- package/dist/registry/canonicalize-contract.js +125 -13
- package/dist/registry/portable-blueprint.d.ts +71 -0
- package/dist/registry/portable-blueprint.d.ts.map +1 -0
- package/dist/registry/portable-blueprint.js +111 -0
- package/dist/registry/summarize-contract.d.ts +7 -2
- package/dist/registry/summarize-contract.d.ts.map +1 -1
- package/dist/registry/summarize-contract.js +12 -3
- package/dist/registry/variant-key.d.ts +17 -0
- package/dist/registry/variant-key.d.ts.map +1 -0
- package/dist/registry/variant-key.js +22 -0
- package/dist/schema-learning/derive-contract.d.ts +2 -2
- package/dist/schema-learning/derive-contract.js +2 -2
- package/dist/schema-learning/merge.d.ts.map +1 -1
- package/dist/schema-learning/merge.js +3 -2
- package/dist/schemas/app-theme.d.ts +38 -0
- package/dist/schemas/app-theme.d.ts.map +1 -0
- package/dist/schemas/app-theme.js +43 -0
- package/dist/schemas/blueprint.d.ts +30 -11
- package/dist/schemas/blueprint.d.ts.map +1 -1
- package/dist/schemas/blueprint.js +62 -26
- package/dist/schemas/data-contract.d.ts +28 -30
- package/dist/schemas/data-contract.d.ts.map +1 -1
- package/dist/schemas/data-contract.js +26 -26
- package/dist/schemas/handshake-suggestion.d.ts +2 -4
- package/dist/schemas/handshake-suggestion.d.ts.map +1 -1
- package/dist/schemas/handshake-suggestion.js +5 -14
- package/dist/schemas/mcp.d.ts +294 -59
- package/dist/schemas/mcp.d.ts.map +1 -1
- package/dist/schemas/mcp.js +350 -94
- package/dist/schemas/ops-blueprint.d.ts +12 -12
- package/dist/schemas/ops-blueprint.d.ts.map +1 -1
- package/dist/schemas/ops-blueprint.js +14 -24
- package/dist/screen-blueprints/define.d.ts +2 -2
- package/dist/screen-blueprints/match.d.ts +12 -7
- package/dist/screen-blueprints/match.d.ts.map +1 -1
- package/dist/screen-blueprints/match.js +7 -5
- package/dist/screen-blueprints/types.d.ts +14 -18
- package/dist/screen-blueprints/types.d.ts.map +1 -1
- package/dist/transport/websocket.d.ts +5 -26
- package/dist/transport/websocket.d.ts.map +1 -1
- package/dist/types/app-config.d.ts +0 -1
- package/dist/types/app-config.d.ts.map +1 -1
- package/dist/types/auth.d.ts +1 -46
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/blueprint-source.d.ts +123 -0
- package/dist/types/blueprint-source.d.ts.map +1 -0
- package/dist/types/blueprint-source.js +126 -0
- package/dist/types/blueprint.d.ts +25 -18
- package/dist/types/blueprint.d.ts.map +1 -1
- package/dist/types/contract-inference.d.ts +2 -43
- package/dist/types/contract-inference.d.ts.map +1 -1
- package/dist/types/data-contract.d.ts +59 -344
- package/dist/types/data-contract.d.ts.map +1 -1
- package/dist/types/data-contract.js +5 -12
- package/dist/types/events.d.ts +31 -69
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/{render-event.d.ts → ggui-session-event.d.ts} +15 -15
- package/dist/types/ggui-session-event.d.ts.map +1 -0
- package/dist/types/{render-event.js → ggui-session-event.js} +5 -5
- package/dist/types/handshake-suggestion.d.ts +49 -35
- package/dist/types/handshake-suggestion.d.ts.map +1 -1
- package/dist/types/host-context.d.ts +8 -8
- package/dist/types/host-context.d.ts.map +1 -1
- package/dist/types/host-context.js +5 -5
- package/dist/types/invoke.d.ts +1 -13
- package/dist/types/invoke.d.ts.map +1 -1
- package/dist/types/{canvas-lifecycle.d.ts → lifecycle.d.ts} +35 -37
- package/dist/types/lifecycle.d.ts.map +1 -0
- package/dist/types/{canvas-lifecycle.js → lifecycle.js} +12 -14
- package/dist/types/live-channel.d.ts +48 -104
- package/dist/types/live-channel.d.ts.map +1 -1
- package/dist/types/llm-route.d.ts +4 -4
- package/dist/types/llm-route.d.ts.map +1 -1
- package/dist/types/llm-route.js +24 -2
- package/dist/types/llm.d.ts +13 -24
- package/dist/types/llm.d.ts.map +1 -1
- package/dist/types/llm.js +23 -53
- package/dist/types/mcp.d.ts +74 -177
- package/dist/types/mcp.d.ts.map +1 -1
- package/dist/types/mcp.js +11 -4
- package/dist/types/oauth-user-id.d.ts +12 -0
- package/dist/types/oauth-user-id.d.ts.map +1 -0
- package/dist/types/oauth-user-id.js +10 -0
- package/dist/types/portable-blueprint.d.ts +61 -0
- package/dist/types/portable-blueprint.d.ts.map +1 -0
- package/dist/types/portable-blueprint.js +8 -0
- package/dist/types/{session.d.ts → render.d.ts} +51 -53
- package/dist/types/render.d.ts.map +1 -0
- package/dist/types/thread.d.ts.map +1 -1
- package/dist/types/thread.js +3 -3
- package/dist/types/ui-generator.d.ts +24 -47
- package/dist/types/ui-generator.d.ts.map +1 -1
- package/dist/types/ui-generator.js +1 -53
- package/dist/validation/ajv-runtime.d.ts +3 -3
- package/dist/validation/ajv-runtime.d.ts.map +1 -1
- package/dist/validation/ajv-runtime.js +6 -5
- package/dist/validation/contract-validator.d.ts +23 -22
- package/dist/validation/contract-validator.d.ts.map +1 -1
- package/dist/validation/contract-validator.js +28 -26
- package/dist/validation/cross-references.d.ts +3 -3
- package/dist/validation/cross-references.js +3 -3
- package/dist/validation/hygiene-rules.d.ts +9 -9
- package/dist/validation/hygiene-rules.js +13 -13
- package/dist/validation/is-record.d.ts +17 -0
- package/dist/validation/is-record.d.ts.map +1 -0
- package/dist/validation/is-record.js +18 -0
- package/dist/validation/lint-contract.d.ts +1 -1
- package/dist/validation/lint-contract.js +3 -3
- package/dist/validation/name-invariants.d.ts +4 -4
- package/dist/validation/name-invariants.js +4 -4
- package/dist/validation/reserved-channels.d.ts +43 -46
- package/dist/validation/reserved-channels.d.ts.map +1 -1
- package/dist/validation/reserved-channels.js +14 -177
- package/dist/validation/resolve-stream-channel.d.ts +3 -9
- package/dist/validation/resolve-stream-channel.d.ts.map +1 -1
- package/dist/validation/resolve-stream-channel.js +3 -4
- package/dist/validation/sanitize-error.d.ts +10 -9
- package/dist/validation/sanitize-error.d.ts.map +1 -1
- package/dist/validation/sanitize-error.js +19 -18
- package/dist/validation/schema-compat-invariants.d.ts +1 -1
- package/dist/validation/schema-compat-invariants.js +3 -3
- package/dist/validation/schema-meta-validation.d.ts +4 -4
- package/dist/validation/schema-meta-validation.d.ts.map +1 -1
- package/dist/validation/schema-meta-validation.js +7 -9
- package/dist/validation/schema-subset.d.ts +9 -8
- package/dist/validation/schema-subset.d.ts.map +1 -1
- package/dist/validation/ui-security.d.ts +0 -17
- package/dist/validation/ui-security.d.ts.map +1 -1
- package/dist/validation/ui-security.js +17 -22
- package/dist/validation/zod-to-json-schema.d.ts +1 -1
- package/dist/validation/zod-to-json-schema.d.ts.map +1 -1
- package/dist/validation/zod-to-json-schema.js +4 -3
- package/dist/version.d.ts +818 -9
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +817 -8
- package/package.json +3 -3
- package/dist/bridge/invoke-agent.d.ts +0 -65
- package/dist/bridge/invoke-agent.d.ts.map +0 -1
- package/dist/bridge/invoke-agent.js +0 -113
- package/dist/stream/stream-parser.d.ts +0 -62
- package/dist/stream/stream-parser.d.ts.map +0 -1
- package/dist/stream/stream-parser.js +0 -199
- package/dist/types/canvas-lifecycle.d.ts.map +0 -1
- package/dist/types/credential.d.ts +0 -41
- package/dist/types/credential.d.ts.map +0 -1
- package/dist/types/credential.js +0 -32
- package/dist/types/data-bindings.d.ts +0 -322
- package/dist/types/data-bindings.d.ts.map +0 -1
- package/dist/types/data-bindings.js +0 -29
- package/dist/types/feedback.d.ts +0 -22
- package/dist/types/feedback.d.ts.map +0 -1
- package/dist/types/feedback.js +0 -7
- package/dist/types/mcp-proxy.d.ts +0 -67
- package/dist/types/mcp-proxy.d.ts.map +0 -1
- package/dist/types/mcp-proxy.js +0 -46
- package/dist/types/openrouter-models.d.ts +0 -23
- package/dist/types/openrouter-models.d.ts.map +0 -1
- package/dist/types/openrouter-models.js +0 -4843
- package/dist/types/region.d.ts +0 -26
- package/dist/types/region.d.ts.map +0 -1
- package/dist/types/region.js +0 -36
- package/dist/types/render-event.d.ts.map +0 -1
- package/dist/types/session.d.ts.map +0 -1
- /package/dist/types/{session.js → render.js} +0 -0
package/dist/schemas/mcp.js
CHANGED
|
@@ -3,10 +3,30 @@
|
|
|
3
3
|
*
|
|
4
4
|
* These schemas define the validation rules for MCP tool inputs.
|
|
5
5
|
* TypeScript types in types/mcp.ts are derived from these via z.infer.
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
|
+
* Two consumption patterns, both anchored here:
|
|
8
|
+
*
|
|
9
|
+
* - **Wired raw shapes** (`*InputShape`): handlers in
|
|
10
|
+
* `@ggui-ai/mcp-server-handlers` (and the hosted pod's
|
|
11
|
+
* discover / request-credential tools) import the SHAPE directly as
|
|
12
|
+
* their `inputSchema` and validate with `z.object(shape)` — unknown
|
|
13
|
+
* keys are STRIPPED. The shape is the one authored copy of the
|
|
14
|
+
* validation rules AND the agent-facing `.describe()` strings that
|
|
15
|
+
* ship via `tools/list`.
|
|
16
|
+
*
|
|
17
|
+
* - **Lifecycle triad** (`ggui_handshake` / `ggui_update`): the
|
|
18
|
+
* handlers carry deliberate input divergences (handshake's
|
|
19
|
+
* blueprintDraft contract is loose ON PURPOSE so the negotiator can
|
|
20
|
+
* repair malformations; update's sessionId is optional for
|
|
21
|
+
* in-process dispatch), so they author their own raw shapes. The
|
|
22
|
+
* schemas here remain the canonical strict wire contract + the
|
|
23
|
+
* `z.infer` source for the published types. `ggui_render` is wired:
|
|
24
|
+
* its handler imports {@link renderInputShape}.
|
|
7
25
|
*/
|
|
8
26
|
import { z } from 'zod';
|
|
9
|
-
import { blueprintDraftSchema, handshakeSuggestionSchema,
|
|
27
|
+
import { blueprintDraftSchema, handshakeSuggestionSchema, } from './handshake-suggestion.js';
|
|
28
|
+
import { dataContractSchema } from './data-contract.js';
|
|
29
|
+
import { blueprintVarianceSchema } from './blueprint.js';
|
|
10
30
|
// ── Shared Sub-Schemas ──
|
|
11
31
|
export const viewportSchema = z.object({
|
|
12
32
|
width: z.number(),
|
|
@@ -23,52 +43,84 @@ export const interfaceContextSchema = z.object({
|
|
|
23
43
|
colorScheme: z.enum(['light', 'dark']).optional(),
|
|
24
44
|
reducedMotion: z.boolean().optional(),
|
|
25
45
|
}).passthrough();
|
|
26
|
-
// ──
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
.describe('Long-poll timeout in seconds (default short; max 25).'),
|
|
36
|
-
}).strict();
|
|
46
|
+
// ── Wired Tool Input Shapes ──
|
|
47
|
+
//
|
|
48
|
+
// Raw zod shapes for the non-lifecycle tools. The SHAPE is the canonical
|
|
49
|
+
// authored artifact: the live handlers register it as their `inputSchema`
|
|
50
|
+
// (the transport layer projects it onto `tools/list`) and validate with
|
|
51
|
+
// `z.object(shape)` — unknown keys are stripped at the wire boundary.
|
|
52
|
+
// The derived `z.object(...)` schema next to each shape is the same
|
|
53
|
+
// contract as a composed validator and the `z.infer` source for the
|
|
54
|
+
// published input types in `types/mcp.ts`.
|
|
37
55
|
/**
|
|
38
|
-
*
|
|
56
|
+
* `ggui_consume` input. The long-poll bound is SPEC §7.3: integer
|
|
57
|
+
* seconds in `[0, 25]` — the cap dodges infrastructure kill windows
|
|
58
|
+
* (API-gateway 30s HTTP limits, host MCP clients that abort long tool
|
|
59
|
+
* calls). Longer waits are the agent's loop, not a server knob.
|
|
60
|
+
*/
|
|
61
|
+
export const consumeInputShape = {
|
|
62
|
+
sessionId: z
|
|
63
|
+
.string()
|
|
64
|
+
.min(1)
|
|
65
|
+
.describe('Globally-unique sessionId to consume events from. Cross-tenant access surfaces uniformly as session_not_found.'),
|
|
66
|
+
timeout: z
|
|
67
|
+
.number()
|
|
68
|
+
.int()
|
|
69
|
+
.min(0)
|
|
70
|
+
.max(25)
|
|
71
|
+
.optional()
|
|
72
|
+
.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.'),
|
|
73
|
+
};
|
|
74
|
+
export const consumeInputSchema = z.object(consumeInputShape);
|
|
75
|
+
/**
|
|
76
|
+
* `ggui_emit` input — emit a stamped delivery on a declared
|
|
39
77
|
* `streamSpec[channel]`.
|
|
40
78
|
*/
|
|
41
|
-
export const
|
|
42
|
-
|
|
43
|
-
channel: z.string()
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
export const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
79
|
+
export const emitInputShape = {
|
|
80
|
+
sessionId: z.string().min(1),
|
|
81
|
+
channel: z.string().min(1),
|
|
82
|
+
payload: z.unknown(),
|
|
83
|
+
complete: z.boolean().optional(),
|
|
84
|
+
};
|
|
85
|
+
export const emitInputSchema = z.object(emitInputShape);
|
|
86
|
+
export const getSessionInputShape = {
|
|
87
|
+
sessionId: z
|
|
88
|
+
.string()
|
|
89
|
+
.min(1)
|
|
90
|
+
.describe('GguiSession opaque id (UUID) — returned by ggui_render.'),
|
|
91
|
+
};
|
|
92
|
+
export const getSessionInputSchema = z.object(getSessionInputShape);
|
|
93
|
+
/**
|
|
94
|
+
* `ggui_list_featured_blueprints` input — intentionally EMPTY. The
|
|
95
|
+
* pre-launch No-Backcompat scrub deleted the level/category/tags/limit
|
|
96
|
+
* filters (delete-until-wired); filters re-enter here when a real
|
|
97
|
+
* consumer passes them.
|
|
98
|
+
*/
|
|
99
|
+
export const listFeaturedBlueprintsInputShape = {};
|
|
100
|
+
export const listFeaturedBlueprintsInputSchema = z.object(listFeaturedBlueprintsInputShape);
|
|
101
|
+
export const searchBlueprintsInputShape = {
|
|
102
|
+
query: z
|
|
103
|
+
.string()
|
|
104
|
+
.min(1)
|
|
105
|
+
.describe("Natural-language description of the UI you're looking for"),
|
|
106
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
107
|
+
};
|
|
108
|
+
export const searchBlueprintsInputSchema = z.object(searchBlueprintsInputShape);
|
|
109
|
+
export const renderBlueprintInputShape = {
|
|
110
|
+
blueprintId: z
|
|
111
|
+
.string()
|
|
112
|
+
.min(1)
|
|
113
|
+
.describe("The stable blueprint id declared via ggui.ui.json#id. Must match an entry in this server's UI registry."),
|
|
114
|
+
};
|
|
115
|
+
export const renderBlueprintInputSchema = z.object(renderBlueprintInputShape);
|
|
116
|
+
export const discoverInputShape = {};
|
|
117
|
+
export const discoverInputSchema = z.object(discoverInputShape);
|
|
118
|
+
export const requestCredentialInputShape = {
|
|
119
|
+
serviceId: z.string().min(1),
|
|
120
|
+
reason: z.string().optional(),
|
|
121
|
+
sessionId: z.string().optional(),
|
|
122
|
+
};
|
|
123
|
+
export const requestCredentialInputSchema = z.object(requestCredentialInputShape);
|
|
72
124
|
// ── Post-Phase-B — canonical tool triad ──
|
|
73
125
|
//
|
|
74
126
|
// `ggui_handshake` → `ggui_render` → `ggui_update` / `ggui_consume`.
|
|
@@ -76,7 +128,7 @@ export const requestCredentialInputSchema = z.object({
|
|
|
76
128
|
// render server-side. Conversation grouping (sibling renders within one
|
|
77
129
|
// host chat) lives on the unchanged `_meta["ai.ggui/host-session"]`
|
|
78
130
|
// channel, captured ONCE at render creation, never threaded by the
|
|
79
|
-
// agent. The collapse of Session→
|
|
131
|
+
// agent. The collapse of Session→GguiSession means `sessionId` is the single
|
|
80
132
|
// identity the wire references everywhere.
|
|
81
133
|
//
|
|
82
134
|
/**
|
|
@@ -100,10 +152,10 @@ export const requestCredentialInputSchema = z.object({
|
|
|
100
152
|
* - The agent is the contract authority; synth amends only when
|
|
101
153
|
* validation fails.
|
|
102
154
|
* - Post-Phase-B the handshake input carries NO `sessionId`. The
|
|
103
|
-
* server mints `
|
|
155
|
+
* server mints `sessionId` on the paired `ggui_render`; host
|
|
104
156
|
* conversation grouping flows via the host-supplied
|
|
105
157
|
* `_meta["ai.ggui/host-session"]` envelope captured at render
|
|
106
|
-
* creation (see {@link
|
|
158
|
+
* creation (see {@link GguiSessionBase.hostSession}).
|
|
107
159
|
*/
|
|
108
160
|
export const handshakeInputSchema = z.object({
|
|
109
161
|
/**
|
|
@@ -138,18 +190,19 @@ export const handshakeInputSchema = z.object({
|
|
|
138
190
|
*
|
|
139
191
|
* The agent reads `suggestion.origin` to branch the paired render call:
|
|
140
192
|
*
|
|
141
|
-
* - `cache` → render `{
|
|
142
|
-
* - `agent` → render `{
|
|
143
|
-
* - `synth` → render `{
|
|
193
|
+
* - `cache` → render `{handshakeId, props}` (omit `override`) for cache delivery.
|
|
194
|
+
* - `agent` → render `{handshakeId, props}` (omit `override`) to gen against the draft.
|
|
195
|
+
* - `synth` → render `{handshakeId, props}` (omit `override`) to gen against the amended contract.
|
|
144
196
|
*
|
|
145
|
-
* Any origin → render `{
|
|
146
|
-
*
|
|
147
|
-
* `
|
|
197
|
+
* Any origin → render `{handshakeId, props, override: {contract?, variance?}}`
|
|
198
|
+
* to re-aim the suggestion — `override.contract` gens against a fresh
|
|
199
|
+
* contract; `override.variance` re-aims the variant axis.
|
|
148
200
|
*
|
|
149
|
-
* Wire-output is intentionally lean. The handler carries `
|
|
150
|
-
* `
|
|
151
|
-
*
|
|
152
|
-
*
|
|
201
|
+
* Wire-output is intentionally lean. The handler carries `target`,
|
|
202
|
+
* `alternatives`, `contractHash`, `serverCapabilities` on its internal
|
|
203
|
+
* `HandshakeOutput` TS shape for telemetry / post-classify tracing —
|
|
204
|
+
* zod strips them before structuredContent serialization. `reason` IS
|
|
205
|
+
* a wire field (optional, ≤280 chars — see below).
|
|
153
206
|
*
|
|
154
207
|
* `serverCapabilities` reaches the iframe via the `ai.ggui/render`
|
|
155
208
|
* slice meta (see `slice-meta-derivation.ts`), not via this response.
|
|
@@ -168,7 +221,7 @@ export const handshakeOutputSchema = z.object({
|
|
|
168
221
|
* conditional on the routing outcome.
|
|
169
222
|
*/
|
|
170
223
|
suggestion: handshakeSuggestionSchema
|
|
171
|
-
.describe('Server\'s suggestion — origin-routed (cache | agent | synth). Always carries a provisional `blueprintMeta` the agent reuses by
|
|
224
|
+
.describe('Server\'s suggestion — origin-routed (cache | agent | synth). Always carries a provisional `blueprintMeta` the agent reuses by rendering WITHOUT `override` (accept the proposal as-is).'),
|
|
172
225
|
/**
|
|
173
226
|
* Truncated human-readable rationale for the `action` value. Helps
|
|
174
227
|
* the agent and the operator narrate why the server chose to reuse a cached
|
|
@@ -191,28 +244,39 @@ export const handshakeOutputSchema = z.object({
|
|
|
191
244
|
* `ggui_render` — materialises a UI emission. Step 3 of the three-step
|
|
192
245
|
* handshake protocol.
|
|
193
246
|
*
|
|
194
|
-
* The agent commits
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
247
|
+
* The agent commits relative to the prior handshake's suggestion by
|
|
248
|
+
* PRESENCE of `override` (no discriminated union): omit `override` to
|
|
249
|
+
* ACCEPT the proposal as-is, or provide `override: {contract?, variance?}`
|
|
250
|
+
* to re-aim the contract and/or the variant axis (PATCH semantics).
|
|
198
251
|
*
|
|
199
252
|
* Locked decisions:
|
|
200
253
|
*
|
|
201
|
-
* - `
|
|
202
|
-
*
|
|
203
|
-
* - `
|
|
204
|
-
*
|
|
254
|
+
* - ACCEPT (omit `override`) reuses the agreed contract + the proposed
|
|
255
|
+
* variance, resolving the proposed `(contractKey, variantKey)`.
|
|
256
|
+
* - `override.contract` re-drafts the contract (STRICT — must already
|
|
257
|
+
* conform; the server does not repair it) and cold-gens against it.
|
|
258
|
+
* - `override.variance` re-aims the variant axis while keeping the
|
|
259
|
+
* agreed contract, re-resolving the effective
|
|
260
|
+
* `(contractKey, variantKey(newVariance))`.
|
|
261
|
+
* - `props` is REQUIRED (pass `{}` when the effective contract declares
|
|
262
|
+
* no propsSpec).
|
|
205
263
|
*
|
|
206
264
|
* There is no separate `ggui_commit` — render absorbs that responsibility.
|
|
207
265
|
*
|
|
208
266
|
* Post-Phase-B rename from `ggui_push` — the tool materialises a single
|
|
209
267
|
* render (no stack of N to push onto); the new name reflects what the
|
|
210
268
|
* tool does at the protocol surface.
|
|
269
|
+
*
|
|
270
|
+
* WIRED shape — `@ggui-ai/mcp-server-handlers`'s `ggui_render` registers
|
|
271
|
+
* {@link renderInputShape} as its `inputSchema` and validates with
|
|
272
|
+
* `z.object(shape)` (unknown top-level keys strip; `infra` / `override`
|
|
273
|
+
* sub-objects stay `.strict()` so typos inside them surface as clear zod
|
|
274
|
+
* paths).
|
|
211
275
|
*/
|
|
212
|
-
export const
|
|
276
|
+
export const renderInputShape = {
|
|
213
277
|
handshakeId: z
|
|
214
278
|
.string({
|
|
215
|
-
message: 'ggui_render: handshakeId is REQUIRED. Call ggui_handshake({intent, blueprintDraft}) first to negotiate — handshake returns a handshakeId + suggestion. Then render with {handshakeId,
|
|
279
|
+
message: 'ggui_render: handshakeId is REQUIRED. Call ggui_handshake({intent, blueprintDraft}) first to negotiate — handshake returns a handshakeId + suggestion. Then render with {handshakeId, props} (accept the suggestion as-is) or {handshakeId, props, override: {contract?, variance?}} (re-aim the contract and/or variance). Direct-render without a handshakeId is not supported.',
|
|
216
280
|
})
|
|
217
281
|
.min(1, 'ggui_render: handshakeId must be a non-empty string from a prior ggui_handshake call.'),
|
|
218
282
|
/**
|
|
@@ -220,27 +284,142 @@ export const renderInputSchema = z.object({
|
|
|
220
284
|
* effective contract's `propsSpec` — required-field checks + type
|
|
221
285
|
* checks per spec entry. Validation failures fail the render with a
|
|
222
286
|
* recoverable `ContractViolationError`.
|
|
287
|
+
*
|
|
288
|
+
* REQUIRED — pass `{}` when the effective contract declares no
|
|
289
|
+
* propsSpec (the field is required, the value may be empty).
|
|
223
290
|
*/
|
|
224
|
-
props: z.record(z.string(), z.unknown())
|
|
291
|
+
props: z.record(z.string(), z.unknown()),
|
|
225
292
|
/**
|
|
226
|
-
*
|
|
293
|
+
* Per-render theme override. When set, lands on the committed
|
|
294
|
+
* render and takes priority over `App.defaultThemeId` at
|
|
295
|
+
* bootstrap-projection time. Use sparingly — most renders should
|
|
296
|
+
* inherit the app default.
|
|
297
|
+
*/
|
|
298
|
+
themeId: z
|
|
299
|
+
.string()
|
|
300
|
+
.min(1)
|
|
301
|
+
.optional()
|
|
302
|
+
.describe('Per-render theme override. Wins over App.defaultThemeId for THIS render. Omit to inherit the app theme.'),
|
|
303
|
+
/**
|
|
304
|
+
* Typed `infra` envelope. Today carries one field (`model`); future
|
|
305
|
+
* expansion (temperature, max_tokens, provider hints) lands here
|
|
306
|
+
* additively. `model` MUST be a provider-prefixed id
|
|
307
|
+
* (`provider/model-name`); a bound generator may also accept
|
|
308
|
+
* generator-specific prefixes for alternate transports.
|
|
227
309
|
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
* 'synth'). Reuses the provisional `blueprintId`.
|
|
232
|
-
* - `{kind: 'override', blueprintDraft: {...}}` — mint a fresh
|
|
233
|
-
* `blueprintId` and gen against the agent's NEW draft. The
|
|
234
|
-
* provisional id from the handshake is discarded. Telemetry
|
|
235
|
-
* threads via `handshakeId`.
|
|
310
|
+
* Strict — extra keys at `infra.*` are not silently dropped, so a
|
|
311
|
+
* typo (`infra.modelId`) surfaces as a clear zod path instead of a
|
|
312
|
+
* silent default-model fallback.
|
|
236
313
|
*/
|
|
237
|
-
|
|
238
|
-
.
|
|
239
|
-
|
|
314
|
+
infra: z
|
|
315
|
+
.object({
|
|
316
|
+
model: z
|
|
317
|
+
.string()
|
|
318
|
+
.min(1)
|
|
319
|
+
.optional()
|
|
320
|
+
.describe('Provider-prefixed model id (e.g., `anthropic/claude-haiku-4-5`, `openai/gpt-5`). Generator-specific prefixes (e.g., `bedrock/...` for AWS Bedrock routing) supported when the bound generator handles them.'),
|
|
321
|
+
})
|
|
322
|
+
.strict()
|
|
323
|
+
.optional(),
|
|
324
|
+
/**
|
|
325
|
+
* Re-aim the handshake proposal (PATCH semantics). Omit to ACCEPT the
|
|
326
|
+
* proposal as-is; provide to re-draft the contract and/or re-aim the
|
|
327
|
+
* variant axis. At least one of `contract` / `variance` MUST be set —
|
|
328
|
+
* an empty `override: {}` is rejected.
|
|
329
|
+
*
|
|
330
|
+
* - `contract` — STRICT full re-draft of the contract. The server
|
|
331
|
+
* does NOT repair it; it must already conform.
|
|
332
|
+
* - `variance` — re-aim the variant axis (persona / aesthetic /
|
|
333
|
+
* context / seedPrompt) while keeping the agreed contract. A
|
|
334
|
+
* different variance resolves a distinct cached component.
|
|
335
|
+
*/
|
|
336
|
+
override: z
|
|
337
|
+
.object({
|
|
338
|
+
contract: dataContractSchema
|
|
339
|
+
.optional()
|
|
340
|
+
.describe('STRICT full re-draft of the contract — must already conform; the server will not repair it.'),
|
|
341
|
+
variance: blueprintVarianceSchema
|
|
342
|
+
.optional()
|
|
343
|
+
.describe('Re-aim the variant (persona/aesthetic/context/seedPrompt); keeps the agreed contract.'),
|
|
344
|
+
})
|
|
345
|
+
.strict()
|
|
346
|
+
.refine((o) => o.contract !== undefined || o.variance !== undefined, {
|
|
347
|
+
message: 'override must set contract and/or variance — omit override entirely to ACCEPT the handshake proposal as-is.',
|
|
348
|
+
})
|
|
349
|
+
.optional()
|
|
350
|
+
.describe('Omit to ACCEPT the proposal as-is. Provide to re-aim contract and/or variance (PATCH semantics).'),
|
|
351
|
+
};
|
|
352
|
+
export const renderInputSchema = z.object(renderInputShape);
|
|
240
353
|
/**
|
|
241
|
-
*
|
|
354
|
+
* Reuse outcome for a single `ggui_render` — surfaced on the wire so an
|
|
355
|
+
* agent or operator can tell whether a stored component was served or a
|
|
356
|
+
* new one was generated. Counts generation calls only; it carries no
|
|
357
|
+
* cost or tier semantics.
|
|
358
|
+
*/
|
|
359
|
+
export const renderCacheMarkerSchema = z.object({
|
|
360
|
+
hit: z
|
|
361
|
+
.boolean()
|
|
362
|
+
.describe('True when a stored component was served without generating new code.'),
|
|
363
|
+
similarity: z
|
|
364
|
+
.number()
|
|
365
|
+
.optional()
|
|
366
|
+
.describe('Cosine similarity of the matched component to the request (semantic match only).'),
|
|
367
|
+
cachedBlueprintId: z
|
|
368
|
+
.string()
|
|
369
|
+
.optional()
|
|
370
|
+
.describe('The stored component id that was matched. Equals top-level blueprintId on a hit.'),
|
|
371
|
+
llmCallsAvoided: z
|
|
372
|
+
.number()
|
|
373
|
+
.describe('Generation calls skipped by serving the stored component (0 on a fresh generation).'),
|
|
374
|
+
kind: z
|
|
375
|
+
.enum(['full-template', 'cold'])
|
|
376
|
+
.optional()
|
|
377
|
+
.describe('full-template = a whole stored component was served; cold = freshly generated.'),
|
|
378
|
+
reason: z
|
|
379
|
+
.string()
|
|
380
|
+
.optional()
|
|
381
|
+
.describe('Compact human-readable explanation of the cache outcome — why this render reused a stored component or generated cold. Diagnostic; default-available without the verbose env-gated trace.'),
|
|
382
|
+
});
|
|
383
|
+
/**
|
|
384
|
+
* Canonical failure codes for the in-result `ggui_render` failure
|
|
385
|
+
* envelope (SPEC §7.9 Plane 3). Closed enum — a failed render's
|
|
386
|
+
* `error.code` is always one of these four; finer-grained diagnostics
|
|
387
|
+
* ride on `error.message`.
|
|
388
|
+
*
|
|
389
|
+
* - `PRODUCTION_FAILED` — generation ran but did not produce a
|
|
390
|
+
* component (LLM/compile/commit failure).
|
|
391
|
+
* - `VALIDATION_ERROR` — a server-side precondition rejected the
|
|
392
|
+
* render before generation could run (misconfigured generation
|
|
393
|
+
* route, unusable stored config).
|
|
394
|
+
* - `NO_PLATFORM_KEY` — the server's managed provider-key
|
|
395
|
+
* configuration has no key for the resolved route.
|
|
396
|
+
* - `NO_CREDENTIALS` — no generation credentials are configured on
|
|
397
|
+
* the server at all.
|
|
398
|
+
*/
|
|
399
|
+
export const renderErrorCodeSchema = z.enum([
|
|
400
|
+
'PRODUCTION_FAILED',
|
|
401
|
+
'VALIDATION_ERROR',
|
|
402
|
+
'NO_PLATFORM_KEY',
|
|
403
|
+
'NO_CREDENTIALS',
|
|
404
|
+
]);
|
|
405
|
+
/**
|
|
406
|
+
* In-result failure marker for `ggui_render`. Present on the wire
|
|
407
|
+
* output iff the tool result is `isError: true` — the structuredContent
|
|
408
|
+
* stays schema-conformant on failures, and this field carries the
|
|
409
|
+
* canonical failure classification.
|
|
410
|
+
*/
|
|
411
|
+
export const renderErrorSchema = z.object({
|
|
412
|
+
code: renderErrorCodeSchema.describe('Canonical failure class. PRODUCTION_FAILED: generation did not produce a component. VALIDATION_ERROR: a server-side precondition rejected the render before generation. NO_PLATFORM_KEY: the server\'s managed provider-key configuration has no key for the resolved route. NO_CREDENTIALS: no generation credentials are configured on the server.'),
|
|
413
|
+
message: z
|
|
414
|
+
.string()
|
|
415
|
+
.describe('Human-readable failure detail — fold into the next attempt or surface to the operator.'),
|
|
416
|
+
});
|
|
417
|
+
/**
|
|
418
|
+
* Wire-output shape — `{sessionId, resourceUri?, action, contractHash,
|
|
419
|
+
* cache, error?, nextStep?}`. `contractHash` (data-contract identity)
|
|
420
|
+
* and `cache` (reuse outcome) are required wire fields on this schema.
|
|
242
421
|
* The handler carries `shortCode`, `codeReady`, `handshakeId`,
|
|
243
|
-
* `decision`, `contract`, `
|
|
422
|
+
* `decision`, `contract`, `codeUrl`, `codeHash`
|
|
244
423
|
* on its internal `RenderOutput` TS shape for telemetry / post-classify
|
|
245
424
|
* tracing — zod strips them before structuredContent serialization.
|
|
246
425
|
*
|
|
@@ -248,15 +427,21 @@ export const renderInputSchema = z.object({
|
|
|
248
427
|
* `expiresAt`) via the single `ai.ggui/render` slice meta, not via this
|
|
249
428
|
* response. There is no clickable `url` field — post-R5 the `/r/`
|
|
250
429
|
* shortCode route was deleted (every host either resolves the
|
|
251
|
-
* `_meta.ui.resourceUri` iframe or reads `{
|
|
430
|
+
* `_meta.ui.resourceUri` iframe or reads `{sessionId}` via
|
|
252
431
|
* `render-resource/...`). Leaving a dead URL on the wire had the model
|
|
253
432
|
* hallucinating links that resolve nowhere.
|
|
254
433
|
*
|
|
434
|
+
* Failure envelope (SPEC §7.1): a failed/rejected generation returns
|
|
435
|
+
* this same schema-conformant shape on an `isError: true` tool result —
|
|
436
|
+
* `error` present, `resourceUri` absent (nothing mountable), no
|
|
437
|
+
* `_meta` on the result. The error GguiSession is still committed, so
|
|
438
|
+
* `sessionId` remains a live handle into the session channel.
|
|
439
|
+
*
|
|
255
440
|
* Post-Phase-B the `'compose'` action enum value is gone — there is no
|
|
256
441
|
* stack of N renders to compose against.
|
|
257
442
|
*/
|
|
258
443
|
export const renderOutputSchema = z.object({
|
|
259
|
-
|
|
444
|
+
sessionId: z.string(),
|
|
260
445
|
/**
|
|
261
446
|
* Spec-canonical MCP-Apps entry-point — same `ui://ggui/render/{id}`
|
|
262
447
|
* URI surfaced on `_meta.ui.resourceUri`. Surfacing it on the LLM-
|
|
@@ -264,9 +449,35 @@ export const renderOutputSchema = z.object({
|
|
|
264
449
|
* tool_results (OpenAI Agents SDK, Google ADK) reach the mount URI;
|
|
265
450
|
* SDKs that preserve `_meta` see the same value on both fields.
|
|
266
451
|
* Mirrors the `resourceUri` field on `ggui_update`'s output.
|
|
452
|
+
*
|
|
453
|
+
* OPTIONAL — present iff the render is mountable. Absent on the
|
|
454
|
+
* failure envelope (`error` present): a failed render commits an
|
|
455
|
+
* error GguiSession but exposes no mount affordance.
|
|
267
456
|
*/
|
|
268
|
-
resourceUri: z
|
|
457
|
+
resourceUri: z
|
|
458
|
+
.string()
|
|
459
|
+
.optional()
|
|
460
|
+
.describe('MCP-Apps mount URI (ui://ggui/render/{id}). Present iff the render is mountable; absent on a failed render.'),
|
|
269
461
|
action: z.enum(['create', 'reuse', 'update', 'replace', 'declined']),
|
|
462
|
+
contractHash: z
|
|
463
|
+
.string()
|
|
464
|
+
.describe('Canonical hash of the rendered data contract (shape only — fields, types, specs). Same hash ⟺ same data flow.'),
|
|
465
|
+
blueprintId: z
|
|
466
|
+
.string()
|
|
467
|
+
.describe('Opaque id of the materialised component for this render. On the handshake-decided reuse paths (accept a cache-origin proposal, or a variance re-aim that resolves to an existing variant) it is the stored id — equal ids across renders mean the same stored component. override.contract always generates cold and mints a fresh id, even for an identical contract.'),
|
|
468
|
+
variantKey: z
|
|
469
|
+
.string()
|
|
470
|
+
.describe('Canonical hash of the design-time variance (persona, aesthetic, seed prompt, context). With contractHash it forms the reuse key: the same pair reuses one component; a different variant of the same contract gets its own.'),
|
|
471
|
+
cache: renderCacheMarkerSchema.describe('Reuse outcome for this render: whether a stored component was served, its similarity, the matched component id, and how many generation calls that avoided.'),
|
|
472
|
+
/**
|
|
473
|
+
* In-result failure marker — present iff the tool result is
|
|
474
|
+
* `isError: true`. The structuredContent stays schema-conformant on
|
|
475
|
+
* failures; this field carries the canonical `{code, message}`
|
|
476
|
+
* classification. Absent on every successful render.
|
|
477
|
+
*/
|
|
478
|
+
error: renderErrorSchema
|
|
479
|
+
.optional()
|
|
480
|
+
.describe('Present iff the tool result is isError — canonical {code, message} for a failed/rejected generation. Absent on success.'),
|
|
270
481
|
/**
|
|
271
482
|
* Wire-shape recovery hint for the next call. Emitted ONLY when the
|
|
272
483
|
* rendered contract has a non-empty `actionSpec` — i.e. the agent will
|
|
@@ -276,7 +487,7 @@ export const renderOutputSchema = z.object({
|
|
|
276
487
|
* Mirrors the chain at `handshake.nextStep` (→ render). Closes the loop
|
|
277
488
|
* with consume.
|
|
278
489
|
*
|
|
279
|
-
* `args.
|
|
490
|
+
* `args.sessionId` is the literal value the agent passes to
|
|
280
491
|
* `ggui_consume` — copy-paste shape.
|
|
281
492
|
*/
|
|
282
493
|
nextStep: z.object({
|
|
@@ -284,9 +495,9 @@ export const renderOutputSchema = z.object({
|
|
|
284
495
|
description: z.string(),
|
|
285
496
|
example: z.string(),
|
|
286
497
|
args: z.object({
|
|
287
|
-
|
|
498
|
+
sessionId: z.string(),
|
|
288
499
|
}),
|
|
289
|
-
}).optional().describe('Recovery hint — when the rendered contract has actions, points the agent at ggui_consume({
|
|
500
|
+
}).optional().describe('Recovery hint — when the rendered contract has actions, points the agent at ggui_consume({sessionId}) for the inbound action loop. Absent for pure-display renders.'),
|
|
290
501
|
});
|
|
291
502
|
/**
|
|
292
503
|
* `ggui_update` — refresh the rendered UI with new state.
|
|
@@ -316,18 +527,18 @@ export const renderOutputSchema = z.object({
|
|
|
316
527
|
* partial patches that would break required fields, type-mismatch
|
|
317
528
|
* values, etc. all reject pre-persist.
|
|
318
529
|
*
|
|
319
|
-
* `
|
|
530
|
+
* `sessionId` is globally unique; the server tenancy-checks via
|
|
320
531
|
* `ctx.appId`.
|
|
321
532
|
*/
|
|
322
533
|
export const updateInputSchema = z.discriminatedUnion('kind', [
|
|
323
534
|
z.object({
|
|
324
|
-
|
|
535
|
+
sessionId: z.string().describe('GguiSession opaque id (UUID) — returned by ggui_render.'),
|
|
325
536
|
kind: z.literal('replace'),
|
|
326
537
|
props: z.record(z.string(), z.unknown())
|
|
327
538
|
.describe('Full replacement props map. New map IS the new state.'),
|
|
328
539
|
}).strict(),
|
|
329
540
|
z.object({
|
|
330
|
-
|
|
541
|
+
sessionId: z.string().describe('GguiSession opaque id (UUID) — returned by ggui_render.'),
|
|
331
542
|
kind: z.literal('merge'),
|
|
332
543
|
patch: z.record(z.string(), z.unknown())
|
|
333
544
|
.describe('RFC 7396 JSON Merge Patch — null deletes a key; arrays fully replace.'),
|
|
@@ -345,6 +556,51 @@ export const updateInputSchema = z.discriminatedUnion('kind', [
|
|
|
345
556
|
* acknowledgement.
|
|
346
557
|
*/
|
|
347
558
|
export const updateOutputSchema = z.object({
|
|
348
|
-
|
|
559
|
+
sessionId: z.string(),
|
|
349
560
|
updated: z.boolean(),
|
|
561
|
+
/**
|
|
562
|
+
* Unchanged from the initial render — the same `ui://ggui/render/{id}`
|
|
563
|
+
* URI the mount stamped. Mirrored on the LLM-visible structuredContent
|
|
564
|
+
* so SDKs that strip `_meta` from tool_results can still reach the
|
|
565
|
+
* mount URI. Kept in sync with the update handler's wire shape —
|
|
566
|
+
* this export and the handler's inline schema must not drift.
|
|
567
|
+
*/
|
|
568
|
+
resourceUri: z.string(),
|
|
350
569
|
});
|
|
570
|
+
/**
|
|
571
|
+
* `ggui_runtime_declare_tool_catalog` — the host runtime declares its
|
|
572
|
+
* per-app canonical tool-identity catalog (one row per app).
|
|
573
|
+
*
|
|
574
|
+
* The map is `bare tool name → the canonical serverInfo` that the tool's
|
|
575
|
+
* MCP server announced in its `initialize` reply. ggui folds this into
|
|
576
|
+
* the handshake step (`canonicalizeToolIdentity`) so a reused blueprint's
|
|
577
|
+
* `agentCapabilities.tools[*].serverInfo` is rewritten to the canonical
|
|
578
|
+
* value regardless of whether the inbound contract authored a config-key
|
|
579
|
+
* name, fabricated one, or omitted it. That makes blueprint reuse
|
|
580
|
+
* identity-stable across runtimes.
|
|
581
|
+
*
|
|
582
|
+
* Keyed by the BARE tool name — the same key the canonicalization step
|
|
583
|
+
* matches on. `version` is OPTIONAL: it rides along as metadata; tool
|
|
584
|
+
* identity is `(name)` matched by bare name, never `(name, version)`.
|
|
585
|
+
*
|
|
586
|
+
* `appId` is NOT on the input — the handler reads it off `ctx.appId`
|
|
587
|
+
* resolved by the upstream auth adapter, so a declaration can only ever
|
|
588
|
+
* write its own app's row. The output echoes the resolved `appId` so the
|
|
589
|
+
* caller can confirm which app row it wrote.
|
|
590
|
+
*
|
|
591
|
+
* REPLACE semantics: each declaration overwrites the app's prior catalog
|
|
592
|
+
* wholesale (the host re-declares its full current toolset on connect).
|
|
593
|
+
*/
|
|
594
|
+
export const declareToolCatalogInputSchema = z
|
|
595
|
+
.object({
|
|
596
|
+
toolCatalog: z
|
|
597
|
+
.record(z.string(), z.object({ name: z.string(), version: z.string().optional() }).strict())
|
|
598
|
+
.describe("Per-app canonical tool identities: bare tool name -> its server's initialize-declared serverInfo. Host/library-supplied; not an agent action."),
|
|
599
|
+
})
|
|
600
|
+
.strict();
|
|
601
|
+
export const declareToolCatalogOutputSchema = z
|
|
602
|
+
.object({
|
|
603
|
+
saved: z.boolean(),
|
|
604
|
+
appId: z.string(),
|
|
605
|
+
})
|
|
606
|
+
.strict();
|