@ggui-ai/protocol 0.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +46 -0
- package/dist/bridge/invoke-agent.d.ts +65 -0
- package/dist/bridge/invoke-agent.d.ts.map +1 -0
- package/dist/bridge/invoke-agent.js +113 -0
- package/dist/envelope-adapters.d.ts +24 -0
- package/dist/envelope-adapters.d.ts.map +1 -0
- package/dist/envelope-adapters.js +14 -0
- package/dist/envelopes/builders.d.ts +145 -0
- package/dist/envelopes/builders.d.ts.map +1 -0
- package/dist/envelopes/builders.js +113 -0
- package/dist/errors/unknown-permission-name.d.ts +12 -0
- package/dist/errors/unknown-permission-name.d.ts.map +1 -0
- package/dist/errors/unknown-permission-name.js +29 -0
- package/dist/errors/version-mismatch.d.ts +55 -0
- package/dist/errors/version-mismatch.d.ts.map +1 -0
- package/dist/errors/version-mismatch.js +52 -0
- package/dist/gadgets/resolve-contract-gadgets.d.ts +93 -0
- package/dist/gadgets/resolve-contract-gadgets.d.ts.map +1 -0
- package/dist/gadgets/resolve-contract-gadgets.js +119 -0
- package/dist/gadgets/stdlib-gadgets.d.ts +43 -0
- package/dist/gadgets/stdlib-gadgets.d.ts.map +1 -0
- package/dist/gadgets/stdlib-gadgets.js +161 -0
- package/dist/iframe-bridge.d.ts +63 -0
- package/dist/iframe-bridge.d.ts.map +1 -0
- package/dist/iframe-bridge.js +166 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +79 -0
- package/dist/integrations/mcp-apps.d.ts +1218 -0
- package/dist/integrations/mcp-apps.d.ts.map +1 -0
- package/dist/integrations/mcp-apps.js +427 -0
- package/dist/navigation/index.d.ts +3 -0
- package/dist/navigation/index.d.ts.map +1 -0
- package/dist/navigation/index.js +1 -0
- package/dist/navigation/stack-navigation.d.ts +55 -0
- package/dist/navigation/stack-navigation.d.ts.map +1 -0
- package/dist/navigation/stack-navigation.js +80 -0
- package/dist/recommended-prompts.d.ts +56 -0
- package/dist/recommended-prompts.d.ts.map +1 -0
- package/dist/recommended-prompts.js +55 -0
- package/dist/registry/blueprint-key.d.ts +9 -0
- package/dist/registry/blueprint-key.d.ts.map +1 -0
- package/dist/registry/blueprint-key.js +28 -0
- package/dist/registry/canonicalize-contract.d.ts +35 -0
- package/dist/registry/canonicalize-contract.d.ts.map +1 -0
- package/dist/registry/canonicalize-contract.js +166 -0
- package/dist/registry/summarize-contract.d.ts +46 -0
- package/dist/registry/summarize-contract.d.ts.map +1 -0
- package/dist/registry/summarize-contract.js +63 -0
- package/dist/schema-learning/derive-contract.d.ts +67 -0
- package/dist/schema-learning/derive-contract.d.ts.map +1 -0
- package/dist/schema-learning/derive-contract.js +117 -0
- package/dist/schema-learning/merge.d.ts +32 -0
- package/dist/schema-learning/merge.d.ts.map +1 -0
- package/dist/schema-learning/merge.js +146 -0
- package/dist/schemas/blueprint.d.ts +32 -0
- package/dist/schemas/blueprint.d.ts.map +1 -0
- package/dist/schemas/blueprint.js +92 -0
- package/dist/schemas/data-contract.d.ts +750 -0
- package/dist/schemas/data-contract.d.ts.map +1 -0
- package/dist/schemas/data-contract.js +663 -0
- package/dist/schemas/gadget-name-grammar.d.ts +29 -0
- package/dist/schemas/gadget-name-grammar.d.ts.map +1 -0
- package/dist/schemas/gadget-name-grammar.js +28 -0
- package/dist/schemas/handshake-suggestion.d.ts +46 -0
- package/dist/schemas/handshake-suggestion.d.ts.map +1 -0
- package/dist/schemas/handshake-suggestion.js +107 -0
- package/dist/schemas/invoke.d.ts +337 -0
- package/dist/schemas/invoke.d.ts.map +1 -0
- package/dist/schemas/invoke.js +169 -0
- package/dist/schemas/mcp.d.ts +301 -0
- package/dist/schemas/mcp.d.ts.map +1 -0
- package/dist/schemas/mcp.js +373 -0
- package/dist/schemas/ops-blueprint.d.ts +176 -0
- package/dist/schemas/ops-blueprint.d.ts.map +1 -0
- package/dist/schemas/ops-blueprint.js +259 -0
- package/dist/schemas/sync-check.d.ts +11 -0
- package/dist/schemas/sync-check.d.ts.map +1 -0
- package/dist/schemas/sync-check.js +60 -0
- package/dist/screen-blueprints/define.d.ts +22 -0
- package/dist/screen-blueprints/define.d.ts.map +1 -0
- package/dist/screen-blueprints/define.js +3 -0
- package/dist/screen-blueprints/index.d.ts +4 -0
- package/dist/screen-blueprints/index.d.ts.map +1 -0
- package/dist/screen-blueprints/index.js +3 -0
- package/dist/screen-blueprints/match.d.ts +35 -0
- package/dist/screen-blueprints/match.d.ts.map +1 -0
- package/dist/screen-blueprints/match.js +51 -0
- package/dist/screen-blueprints/types.d.ts +164 -0
- package/dist/screen-blueprints/types.d.ts.map +1 -0
- package/dist/screen-blueprints/types.js +1 -0
- package/dist/stream/stream-parser.d.ts +62 -0
- package/dist/stream/stream-parser.d.ts.map +1 -0
- package/dist/stream/stream-parser.js +199 -0
- package/dist/transport/websocket.d.ts +178 -0
- package/dist/transport/websocket.d.ts.map +1 -0
- package/dist/transport/websocket.js +1 -0
- package/dist/types/app-config.d.ts +61 -0
- package/dist/types/app-config.d.ts.map +1 -0
- package/dist/types/app-config.js +1 -0
- package/dist/types/auth.d.ts +61 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/auth.js +1 -0
- package/dist/types/blueprint.d.ts +206 -0
- package/dist/types/blueprint.d.ts.map +1 -0
- package/dist/types/blueprint.js +1 -0
- package/dist/types/canvas-lifecycle.d.ts +105 -0
- package/dist/types/canvas-lifecycle.d.ts.map +1 -0
- package/dist/types/canvas-lifecycle.js +38 -0
- package/dist/types/capabilities.d.ts +40 -0
- package/dist/types/capabilities.d.ts.map +1 -0
- package/dist/types/capabilities.js +19 -0
- package/dist/types/contract-inference.d.ts +401 -0
- package/dist/types/contract-inference.d.ts.map +1 -0
- package/dist/types/contract-inference.js +44 -0
- package/dist/types/credential.d.ts +41 -0
- package/dist/types/credential.d.ts.map +1 -0
- package/dist/types/credential.js +32 -0
- package/dist/types/data-bindings.d.ts +322 -0
- package/dist/types/data-bindings.d.ts.map +1 -0
- package/dist/types/data-bindings.js +29 -0
- package/dist/types/data-contract.d.ts +1296 -0
- package/dist/types/data-contract.d.ts.map +1 -0
- package/dist/types/data-contract.js +111 -0
- package/dist/types/events.d.ts +182 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +8 -0
- package/dist/types/feedback.d.ts +24 -0
- package/dist/types/feedback.d.ts.map +1 -0
- package/dist/types/feedback.js +7 -0
- package/dist/types/gadget.d.ts +121 -0
- package/dist/types/gadget.d.ts.map +1 -0
- package/dist/types/gadget.js +24 -0
- package/dist/types/handshake-suggestion.d.ts +264 -0
- package/dist/types/handshake-suggestion.d.ts.map +1 -0
- package/dist/types/handshake-suggestion.js +70 -0
- package/dist/types/host-context.d.ts +163 -0
- package/dist/types/host-context.d.ts.map +1 -0
- package/dist/types/host-context.js +142 -0
- package/dist/types/interface-context.d.ts +105 -0
- package/dist/types/interface-context.d.ts.map +1 -0
- package/dist/types/interface-context.js +115 -0
- package/dist/types/invoke.d.ts +28 -0
- package/dist/types/invoke.d.ts.map +1 -0
- package/dist/types/invoke.js +7 -0
- package/dist/types/live-channel.d.ts +613 -0
- package/dist/types/live-channel.d.ts.map +1 -0
- package/dist/types/live-channel.js +1 -0
- package/dist/types/llm.d.ts +61 -0
- package/dist/types/llm.d.ts.map +1 -0
- package/dist/types/llm.js +186 -0
- package/dist/types/mcp-proxy.d.ts +67 -0
- package/dist/types/mcp-proxy.d.ts.map +1 -0
- package/dist/types/mcp-proxy.js +46 -0
- package/dist/types/mcp.d.ts +637 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +30 -0
- package/dist/types/openrouter-models.d.ts +22 -0
- package/dist/types/openrouter-models.d.ts.map +1 -0
- package/dist/types/openrouter-models.js +4843 -0
- package/dist/types/region.d.ts +26 -0
- package/dist/types/region.d.ts.map +1 -0
- package/dist/types/region.js +36 -0
- package/dist/types/session.d.ts +419 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +1 -0
- package/dist/types/thread.d.ts +207 -0
- package/dist/types/thread.d.ts.map +1 -0
- package/dist/types/thread.js +57 -0
- package/dist/types/ui-generator.d.ts +100 -0
- package/dist/types/ui-generator.d.ts.map +1 -0
- package/dist/types/ui-generator.js +53 -0
- package/dist/validation/ajv-runtime.d.ts +140 -0
- package/dist/validation/ajv-runtime.d.ts.map +1 -0
- package/dist/validation/ajv-runtime.js +452 -0
- package/dist/validation/content-hash.d.ts +3 -0
- package/dist/validation/content-hash.d.ts.map +1 -0
- package/dist/validation/content-hash.js +21 -0
- package/dist/validation/contract-validator.d.ts +244 -0
- package/dist/validation/contract-validator.d.ts.map +1 -0
- package/dist/validation/contract-validator.js +711 -0
- package/dist/validation/cross-references.d.ts +105 -0
- package/dist/validation/cross-references.d.ts.map +1 -0
- package/dist/validation/cross-references.js +164 -0
- package/dist/validation/hygiene-rules.d.ts +250 -0
- package/dist/validation/hygiene-rules.d.ts.map +1 -0
- package/dist/validation/hygiene-rules.js +564 -0
- package/dist/validation/lint-contract.d.ts +130 -0
- package/dist/validation/lint-contract.d.ts.map +1 -0
- package/dist/validation/lint-contract.js +225 -0
- package/dist/validation/name-invariants.d.ts +117 -0
- package/dist/validation/name-invariants.d.ts.map +1 -0
- package/dist/validation/name-invariants.js +172 -0
- package/dist/validation/reserved-channels.d.ts +156 -0
- package/dist/validation/reserved-channels.d.ts.map +1 -0
- package/dist/validation/reserved-channels.js +356 -0
- package/dist/validation/resolve-stream-channel.d.ts +78 -0
- package/dist/validation/resolve-stream-channel.d.ts.map +1 -0
- package/dist/validation/resolve-stream-channel.js +64 -0
- package/dist/validation/sanitize-error.d.ts +46 -0
- package/dist/validation/sanitize-error.d.ts.map +1 -0
- package/dist/validation/sanitize-error.js +88 -0
- package/dist/validation/schema-compat-invariants.d.ts +140 -0
- package/dist/validation/schema-compat-invariants.d.ts.map +1 -0
- package/dist/validation/schema-compat-invariants.js +220 -0
- package/dist/validation/schema-meta-validation.d.ts +60 -0
- package/dist/validation/schema-meta-validation.d.ts.map +1 -0
- package/dist/validation/schema-meta-validation.js +131 -0
- package/dist/validation/schema-subset.d.ts +165 -0
- package/dist/validation/schema-subset.d.ts.map +1 -0
- package/dist/validation/schema-subset.js +295 -0
- package/dist/validation/ui-security.d.ts +54 -0
- package/dist/validation/ui-security.d.ts.map +1 -0
- package/dist/validation/ui-security.js +138 -0
- package/dist/validation/zod-to-json-schema.d.ts +63 -0
- package/dist/validation/zod-to-json-schema.d.ts.map +1 -0
- package/dist/validation/zod-to-json-schema.js +126 -0
- package/dist/version.d.ts +1458 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +1459 -0
- package/package.json +113 -0
|
@@ -0,0 +1,1296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A JSON object — the object branch of {@link JsonValue}.
|
|
3
|
+
* Allows `undefined` values because TypeScript optional properties (`?:`)
|
|
4
|
+
* produce `T | undefined`, and JSON objects can have missing keys.
|
|
5
|
+
*
|
|
6
|
+
* Used as the default generic parameter throughout the protocol where a
|
|
7
|
+
* JSON-serializable object shape is expected (e.g., props, payloads, context).
|
|
8
|
+
* Typed interfaces with optional properties satisfy `JsonObject` because
|
|
9
|
+
* missing keys are `undefined` at runtime, which `JSON.stringify` omits.
|
|
10
|
+
*/
|
|
11
|
+
export interface JsonObject {
|
|
12
|
+
[key: string]: JsonValue | undefined;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Recursive type for any JSON-serializable value.
|
|
16
|
+
* Use instead of `unknown` when the value MUST be JSON-safe
|
|
17
|
+
* (no functions, symbols, bigint, etc.).
|
|
18
|
+
*
|
|
19
|
+
* Used as the default for fields that carry arbitrary JSON data
|
|
20
|
+
* (e.g., error details, schema defaults, example values).
|
|
21
|
+
* Prefer `JsonObject` when the value is known to be an object,
|
|
22
|
+
* and `JsonValue` when it could be any JSON leaf or structure.
|
|
23
|
+
*/
|
|
24
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | JsonObject;
|
|
25
|
+
/**
|
|
26
|
+
* JSON Schema subset for defining data shapes in ggui contract.
|
|
27
|
+
* Covers the types that map cleanly to TypeScript: primitives, objects, arrays, enums.
|
|
28
|
+
*
|
|
29
|
+
* Extends {@link JsonObject} so it can be used anywhere a JSON-serializable
|
|
30
|
+
* object is expected (e.g., stored server-side, sent over WebSocket).
|
|
31
|
+
* Fields like `default`, `example`, and `const` are typed as {@link JsonValue}
|
|
32
|
+
* to accept any JSON-safe value.
|
|
33
|
+
*/
|
|
34
|
+
export interface JsonSchema extends JsonObject {
|
|
35
|
+
/** JSON Schema type. Optional when using `oneOf`/`anyOf` unions. */
|
|
36
|
+
type?: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'null';
|
|
37
|
+
description?: string;
|
|
38
|
+
/** Allowed values (enum constraint) */
|
|
39
|
+
enum?: JsonValue[];
|
|
40
|
+
/** Default value */
|
|
41
|
+
default?: JsonValue;
|
|
42
|
+
/** Example value (for documentation / sample rendering) */
|
|
43
|
+
example?: JsonValue;
|
|
44
|
+
/** For type: 'array' — schema of each array element */
|
|
45
|
+
items?: JsonSchema;
|
|
46
|
+
/** For type: 'object' — property definitions */
|
|
47
|
+
properties?: Record<string, JsonSchema>;
|
|
48
|
+
/** For type: 'object' — which properties are required */
|
|
49
|
+
required?: string[];
|
|
50
|
+
/** For type: 'object' — schema for additional properties beyond `properties` */
|
|
51
|
+
additionalProperties?: JsonSchema | boolean;
|
|
52
|
+
/** For type: 'string' — format hint (e.g., 'date', 'email', 'uri') */
|
|
53
|
+
format?: string;
|
|
54
|
+
/** For type: 'number' / 'integer' — minimum value */
|
|
55
|
+
minimum?: number;
|
|
56
|
+
/** For type: 'number' / 'integer' — maximum value */
|
|
57
|
+
maximum?: number;
|
|
58
|
+
/** Union: exactly one of these schemas */
|
|
59
|
+
oneOf?: JsonSchema[];
|
|
60
|
+
/** Union: any of these schemas */
|
|
61
|
+
anyOf?: JsonSchema[];
|
|
62
|
+
/** Constant literal value */
|
|
63
|
+
const?: JsonValue;
|
|
64
|
+
/** OpenAPI 3.0 nullable shorthand */
|
|
65
|
+
nullable?: boolean;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Per-prop metadata in a PropsSpec.
|
|
69
|
+
* The `default` and `example` fields are {@link JsonValue} to accept any JSON-safe value
|
|
70
|
+
* (string, number, boolean, null, array, or object).
|
|
71
|
+
*/
|
|
72
|
+
export interface PropEntry {
|
|
73
|
+
/** Human-readable description of this prop */
|
|
74
|
+
description?: string;
|
|
75
|
+
/** JSON Schema for this prop's type */
|
|
76
|
+
schema: JsonSchema;
|
|
77
|
+
/** Whether this prop is required (component must accept it) */
|
|
78
|
+
required?: boolean;
|
|
79
|
+
/** Default value if not provided. Typed as {@link JsonValue} (any JSON-safe value). */
|
|
80
|
+
default?: JsonValue;
|
|
81
|
+
/** Example value (used for preview rendering). Typed as {@link JsonValue}. */
|
|
82
|
+
example?: JsonValue;
|
|
83
|
+
/**
|
|
84
|
+
* Which MCP tool produces this prop's data, if any.
|
|
85
|
+
* Data-lineage metadata. When set, the agent must have this tool available
|
|
86
|
+
* (or `required: false` on this prop) for the contract to be satisfiable.
|
|
87
|
+
* When absent, the agent populates the prop by its own means (memory,
|
|
88
|
+
* reasoning, search, etc.). Blueprint matcher aggregates these for GSI
|
|
89
|
+
* queries on `byPrimaryDataTool`.
|
|
90
|
+
*/
|
|
91
|
+
sourceTool?: string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Props contract — defines the prop interface a generated component MUST implement.
|
|
95
|
+
*
|
|
96
|
+
* Shape: a wrapper `{description?, properties}` over the per-prop map.
|
|
97
|
+
*
|
|
98
|
+
* NOT flat like {@link ActionSpec} / {@link StreamSpec}, which dropped
|
|
99
|
+
* their `{description, actions}` / `{description, channels}` wrappers
|
|
100
|
+
* because their inner key name duplicated the parent
|
|
101
|
+
* (`actionSpec.actions.createTask`). `PropsSpec.properties` is different:
|
|
102
|
+
* `properties` is the JSON Schema field name for the per-property bag on
|
|
103
|
+
* an object schema, so the wrapper matches a convention an external
|
|
104
|
+
* implementer already knows from reading JsonSchema itself. Flattening
|
|
105
|
+
* would also cost the top-level `description`, which documents the
|
|
106
|
+
* props contract as a whole — a genuine load-bearing field, unlike the
|
|
107
|
+
* vestigial descriptions on actionSpec / streamSpec.
|
|
108
|
+
*
|
|
109
|
+
* Symmetry is with {@link JsonSchema.properties}, not with sibling specs.
|
|
110
|
+
* Implementers walking `DataContract` must special-case `props` vs
|
|
111
|
+
* `actionSpec` / `streamSpec`.
|
|
112
|
+
*/
|
|
113
|
+
export interface PropsSpec {
|
|
114
|
+
/** Human-readable description of the overall props contract */
|
|
115
|
+
description?: string;
|
|
116
|
+
/** Per-prop definitions keyed by prop name */
|
|
117
|
+
properties: Record<string, PropEntry>;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Per-channel state-folding mode. Tells subscribers whether each
|
|
121
|
+
* delivery on a channel is a new event to accumulate or a full
|
|
122
|
+
* replacement of the channel's current value.
|
|
123
|
+
*
|
|
124
|
+
* Default when omitted on a {@link StreamChannelEntry}:
|
|
125
|
+
* {@link DEFAULT_STREAM_CHANNEL_MODE} (`'append'`).
|
|
126
|
+
*
|
|
127
|
+
* Maps 1:1 to the outbound stream envelope's `mode` field in the
|
|
128
|
+
* three-channel-topology doctrine.
|
|
129
|
+
*/
|
|
130
|
+
export type StreamChannelMode = 'append' | 'replace';
|
|
131
|
+
/**
|
|
132
|
+
* Per-channel replay policy. Declares what a reconnecting subscriber
|
|
133
|
+
* sees before the live tail resumes.
|
|
134
|
+
*
|
|
135
|
+
* Default when omitted on a {@link StreamChannelEntry}:
|
|
136
|
+
* {@link DEFAULT_STREAM_REPLAY_POLICY} (`'none'`).
|
|
137
|
+
*
|
|
138
|
+
* This is a DECLARATION. Replay infrastructure (ring buffer,
|
|
139
|
+
* resumption tokens) lives in `@ggui-ai/mcp-server-core`. Consumers
|
|
140
|
+
* MUST NOT assume replay is implemented just because the spec declares
|
|
141
|
+
* `'latest'` or `'all'`; until the infra ships, the field is advisory.
|
|
142
|
+
*
|
|
143
|
+
* - `'latest'` — subscriber sees only the most recent payload for the
|
|
144
|
+
* channel (useful for state-broadcast channels).
|
|
145
|
+
* - `'all'` — subscriber sees the full buffered history (useful for
|
|
146
|
+
* event logs / append-only feeds).
|
|
147
|
+
* - `'none'` — no replay; subscriber only sees deliveries after
|
|
148
|
+
* attachment.
|
|
149
|
+
*/
|
|
150
|
+
export type StreamReplayPolicy = 'latest' | 'all' | 'none';
|
|
151
|
+
/** Locked default applied when {@link StreamChannelEntry.mode} is omitted. */
|
|
152
|
+
export declare const DEFAULT_STREAM_CHANNEL_MODE: StreamChannelMode;
|
|
153
|
+
/** Locked default applied when {@link StreamChannelEntry.replay} is omitted. */
|
|
154
|
+
export declare const DEFAULT_STREAM_REPLAY_POLICY: StreamReplayPolicy;
|
|
155
|
+
/** Locked default applied when {@link StreamChannelEntry.complete} is omitted. */
|
|
156
|
+
export declare const DEFAULT_STREAM_CHANNEL_COMPLETE = false;
|
|
157
|
+
/**
|
|
158
|
+
* Per-channel metadata in a {@link StreamSpec}. Declares one named
|
|
159
|
+
* channel's payload contract plus its runtime semantics.
|
|
160
|
+
*
|
|
161
|
+
* The payload `schema` is the authoritative contract — every live-channel
|
|
162
|
+
* enforcement point validates deliveries against it. The semantics
|
|
163
|
+
* fields (`mode` / `replay` / `complete`) are informational: consumers
|
|
164
|
+
* that care about them honor them at their own boundary. Default
|
|
165
|
+
* behavior when a field is omitted is documented per-field.
|
|
166
|
+
*/
|
|
167
|
+
export interface StreamChannelEntry {
|
|
168
|
+
/** Human-readable description of this channel */
|
|
169
|
+
description?: string;
|
|
170
|
+
/**
|
|
171
|
+
* JSON Schema for the channel payload. This is the authoritative
|
|
172
|
+
* shape guard for every delivery on this channel — live-channel
|
|
173
|
+
* enforcement points (hosted fan-out, OSS `/ws`, `@ggui-ai/react`
|
|
174
|
+
* data receipt, `@ggui-ai/react-native` data receipt) all validate
|
|
175
|
+
* deliveries against it.
|
|
176
|
+
*
|
|
177
|
+
* **Author invariant when paired with {@link StreamChannelEntry.tool}:**
|
|
178
|
+
* when a refresh tool is declared, the values the tool returns MUST
|
|
179
|
+
* be a superset of the values `schema` accepts — i.e., every
|
|
180
|
+
* possible tool return passes validation. Drift in the opposite
|
|
181
|
+
* direction (tool returns shapes the schema rejects) produces
|
|
182
|
+
* `_ggui:contract-error` envelopes with `code: 'SCHEMA_VIOLATION'`
|
|
183
|
+
* rather than silent data, but channel subscribers see fewer
|
|
184
|
+
* refreshes than expected, which looks like a broken tool to
|
|
185
|
+
* operators.
|
|
186
|
+
*
|
|
187
|
+
* **F4 schema compat checker.** The compat relation — every value
|
|
188
|
+
* the tool returns MUST be accepted by this channel schema — is
|
|
189
|
+
* encoded as `isSchemaSubset(channelSchema, toolReturnSchema)` and
|
|
190
|
+
* is checked at push-time (before the stack item commits) and at
|
|
191
|
+
* blueprint-registration time (when the blueprint pre-declares
|
|
192
|
+
* tool refs). Mismatches surface as `SCHEMA_MISMATCH_ERROR` on
|
|
193
|
+
* the reserved `_ggui:contract-error` channel rather than showing
|
|
194
|
+
* up as downstream `SCHEMA_VIOLATION` rejections on individual
|
|
195
|
+
* refreshes. Default policy is `'reject'`; see the docstring on
|
|
196
|
+
* {@link ActionEntry.schema} for the full policy flag contract.
|
|
197
|
+
*/
|
|
198
|
+
schema: JsonSchema;
|
|
199
|
+
/** Example payload (used for documentation and smoke testing). Typed as {@link JsonValue}. */
|
|
200
|
+
example?: JsonValue;
|
|
201
|
+
/**
|
|
202
|
+
* Client-side state-folding mode. See {@link StreamChannelMode}. When
|
|
203
|
+
* omitted, consumers SHOULD apply {@link DEFAULT_STREAM_CHANNEL_MODE}
|
|
204
|
+
* (`'append'`). Not a validator input — informational only.
|
|
205
|
+
*/
|
|
206
|
+
mode?: StreamChannelMode;
|
|
207
|
+
/**
|
|
208
|
+
* Server-side replay policy. See {@link StreamReplayPolicy}. When
|
|
209
|
+
* omitted, consumers SHOULD apply {@link DEFAULT_STREAM_REPLAY_POLICY}
|
|
210
|
+
* (`'none'`). Advisory until the `@ggui-ai/mcp-server-core`
|
|
211
|
+
* ring-buffer infrastructure ships.
|
|
212
|
+
*/
|
|
213
|
+
replay?: StreamReplayPolicy;
|
|
214
|
+
/**
|
|
215
|
+
* Declares whether this channel has a terminal completion marker.
|
|
216
|
+
* When omitted, consumers SHOULD treat the channel as open-ended
|
|
217
|
+
* (default: {@link DEFAULT_STREAM_CHANNEL_COMPLETE}, `false`).
|
|
218
|
+
*
|
|
219
|
+
* Envelope-level plumbing (the outbound envelope's terminal marker)
|
|
220
|
+
* is NOT wired by the current `StreamSpec` definition — declaring
|
|
221
|
+
* `complete: true` here is forward-compatible but consumers MUST NOT
|
|
222
|
+
* assume the envelope carries a completion field until the envelope
|
|
223
|
+
* work lands.
|
|
224
|
+
*/
|
|
225
|
+
complete?: boolean;
|
|
226
|
+
/**
|
|
227
|
+
* Optional MCP tool name this channel is refreshed from when a
|
|
228
|
+
* wired action fires. Consumed by the server-side wiredActionRouter
|
|
229
|
+
* (see `@ggui-ai/mcp-server` session-channel) as a declarative hint:
|
|
230
|
+
* after a wired action on this stack item succeeds, the router
|
|
231
|
+
* invokes the named tool and emits its return value on THIS channel.
|
|
232
|
+
*
|
|
233
|
+
* Name-scoping invariant:
|
|
234
|
+
*
|
|
235
|
+
* A bare tool name (`"tasks_list"`) MUST be unique across every
|
|
236
|
+
* mount registered on the server. `composeHandlersWithMounts` in
|
|
237
|
+
* `@ggui-ai/mcp-server` rejects collisions at boot and names both
|
|
238
|
+
* owners in the error — an operator with two mounts both exposing
|
|
239
|
+
* `list` is forced to rename one. No namespace syntax is accepted
|
|
240
|
+
* here: MCP protocol requires unique tool names on `tools/list` /
|
|
241
|
+
* `tools/call` regardless, so two mounts can't both expose the
|
|
242
|
+
* same name at the wire level. Authors adding a second mount to
|
|
243
|
+
* an existing `ggui.json` SHOULD re-check this invariant; a newly-
|
|
244
|
+
* registered duplicate will fail server boot with a message
|
|
245
|
+
* naming both mounts.
|
|
246
|
+
*
|
|
247
|
+
* Refresh semantics (locked):
|
|
248
|
+
*
|
|
249
|
+
* - The refresh tool SHOULD be idempotent-read-only. The router
|
|
250
|
+
* calls it after every wired action targeting this channel.
|
|
251
|
+
* - On failure, the router emits a `_ggui:contract-error` envelope
|
|
252
|
+
* (see {@link ContractErrorPayload}) and the channel's previous
|
|
253
|
+
* state is preserved — the router does NOT fall back to the
|
|
254
|
+
* wired action's own return value.
|
|
255
|
+
* - Authors who want write-then-read semantics SHOULD chain via a
|
|
256
|
+
* single action tool that returns the new state directly.
|
|
257
|
+
*
|
|
258
|
+
* Absent ⇒ no refresh fires; channel is written to by the agent (or
|
|
259
|
+
* by some other server-emitted source). Declarative hint only — it
|
|
260
|
+
* does NOT alter payload shape validation, which remains
|
|
261
|
+
* `schema`-driven.
|
|
262
|
+
*/
|
|
263
|
+
tool?: string;
|
|
264
|
+
/**
|
|
265
|
+
* Optional source declaration — when present, the channel is fed by
|
|
266
|
+
* a tool called periodically (poll) or subscribed-to (push) by the
|
|
267
|
+
* runtime. Replaces the retired top-level `broadcast` config.
|
|
268
|
+
*
|
|
269
|
+
* `tool` references an `agentCapabilities.tools[*]` key (structural
|
|
270
|
+
* cross-ref enforced by the protocol linter: `CTR_REF_STREAM_SOURCE`).
|
|
271
|
+
* `args` are passed on each call.
|
|
272
|
+
*
|
|
273
|
+
* Transport selection is NOT in the contract — it's runtime-negotiated
|
|
274
|
+
* by `@ggui-ai/wire` between WebSocket subscribe (when the server
|
|
275
|
+
* declares `serverCapabilities.streamWebSocket` AND the tool is in
|
|
276
|
+
* `streamWebSocketLocalTools`) and iframe polling fallback.
|
|
277
|
+
*/
|
|
278
|
+
source?: {
|
|
279
|
+
/** agentCapabilities.tools key whose tool feeds this channel. */
|
|
280
|
+
tool: string;
|
|
281
|
+
/** Arguments passed to the source tool on each call. */
|
|
282
|
+
args?: JsonObject;
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Stream contract — describes the typed channels the component consumes
|
|
287
|
+
* on the live session plane (the live channel in the three-channel doctrine).
|
|
288
|
+
*
|
|
289
|
+
* Shape: flat map keyed by channel name → entry.
|
|
290
|
+
* `DataContract.streamSpec[channelName]` IS the entry.
|
|
291
|
+
*
|
|
292
|
+
* See the design-lock block above for what each channel declares and
|
|
293
|
+
* what is explicitly NOT in scope for this shape.
|
|
294
|
+
*/
|
|
295
|
+
export type StreamSpec = Record<string, StreamChannelEntry>;
|
|
296
|
+
/**
|
|
297
|
+
* Per-action metadata in an ActionSpec. Actions are GESTURES — discrete
|
|
298
|
+
* client-originated events the agent reacts to on its next turn. There
|
|
299
|
+
* is one and only one routing target: the agent (no synchronous
|
|
300
|
+
* server-side dispatch). Authors who want a hint about which tool the
|
|
301
|
+
* agent SHOULD invoke next declare it via the optional `nextStep` field
|
|
302
|
+
* below.
|
|
303
|
+
*
|
|
304
|
+
* Actions without a `schema` have void payload (fire-and-forget).
|
|
305
|
+
* The `example` field is {@link JsonValue} to accept any JSON-safe sample.
|
|
306
|
+
*/
|
|
307
|
+
export interface ActionEntry {
|
|
308
|
+
/** Human-readable description of this action */
|
|
309
|
+
description?: string;
|
|
310
|
+
/** Label shown on the UI element */
|
|
311
|
+
label: string;
|
|
312
|
+
/**
|
|
313
|
+
* JSON Schema for the callback payload. Optional — actions without a
|
|
314
|
+
* `schema` have void payload (fire-and-forget).
|
|
315
|
+
*
|
|
316
|
+
* **Author invariant when paired with `nextStep`:** the values
|
|
317
|
+
* accepted by `ActionEntry.schema` SHOULD be a subset of the values
|
|
318
|
+
* accepted by the hinted tool's `inputSchema`. The validation is
|
|
319
|
+
* advisory — the agent owns the actual tool call on its next turn
|
|
320
|
+
* and is responsible for shaping the payload as the tool expects.
|
|
321
|
+
* For tools registered on THIS server, the F4 schema-compat checker
|
|
322
|
+
* surfaces a `SCHEMA_MISMATCH_ERROR` at push-time / blueprint-
|
|
323
|
+
* registration-time so authors get fail-loud feedback.
|
|
324
|
+
*
|
|
325
|
+
* The canonical algorithm lives in
|
|
326
|
+
* `@ggui-ai/protocol/validation/schema-subset`; zod → JsonSchema
|
|
327
|
+
* conversion uses `@ggui-ai/protocol/validation/zod-to-json-schema`.
|
|
328
|
+
* Default policy is `'reject'`; hosts MAY configure `'warn'` or
|
|
329
|
+
* `'off'` via `CreateGguiServerOptions.schemaCompatCheck`.
|
|
330
|
+
*
|
|
331
|
+
* P0 checker scope covers type match, required-set, property
|
|
332
|
+
* recursion, items recursion, and `additionalProperties`.
|
|
333
|
+
* Unsupported constructs (`oneOf` / `anyOf` / `enum` / `const` /
|
|
334
|
+
* `$ref` / `allOf`) are flagged honestly rather than silently
|
|
335
|
+
* passing — authors using them see a `'unsupported'` violation
|
|
336
|
+
* reason and the check falls back to operator discipline for
|
|
337
|
+
* those constructs. P1/P2 algorithm coverage is a follow-up.
|
|
338
|
+
*/
|
|
339
|
+
schema?: JsonSchema;
|
|
340
|
+
/** Example callback payload (used for documentation). Typed as {@link JsonValue}. */
|
|
341
|
+
example?: JsonValue;
|
|
342
|
+
/** Icon hint (emoji or icon name) */
|
|
343
|
+
icon?: string;
|
|
344
|
+
/** Whether to show confirmation before triggering */
|
|
345
|
+
confirm?: boolean;
|
|
346
|
+
/**
|
|
347
|
+
* OPTIONAL. Author-declared hint for the agent's next turn — the
|
|
348
|
+
* `agentCapabilities.tools[*]` key the agent INTENDS to call when
|
|
349
|
+
* this action fires. The value MUST resolve to a declared
|
|
350
|
+
* `agentCapabilities.tools` entry on the same contract (cross-ref
|
|
351
|
+
* invariant `CTR_REF_NEXT_STEP`, enforced by
|
|
352
|
+
* `@ggui-ai/protocol/validation/cross-references`).
|
|
353
|
+
*
|
|
354
|
+
* Hint, not binding. The runtime emits the action as an event; the
|
|
355
|
+
* agent decides whether to honor the intent on its next turn based
|
|
356
|
+
* on its broader context (other tools available, user history, etc.).
|
|
357
|
+
*
|
|
358
|
+
* When absent, the action is a pure event signal — the agent receives
|
|
359
|
+
* `{action: <name>, data: <payload>}` and decides what to do
|
|
360
|
+
* unconstrained by author intent.
|
|
361
|
+
*
|
|
362
|
+
* Implementations MUST forward `nextStep` as event metadata to the
|
|
363
|
+
* agent without rejection. If the named tool isn't in the agent's
|
|
364
|
+
* toolbox at dispatch time, the agent surfaces the gap on its next
|
|
365
|
+
* turn (typically as `TOOL_UNAVAILABLE`); the protocol does NOT
|
|
366
|
+
* fail at push.
|
|
367
|
+
*/
|
|
368
|
+
nextStep?: string;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Action contract — declarative callbacks the component must wire.
|
|
372
|
+
*
|
|
373
|
+
* Shape: flat map keyed by action name → entry.
|
|
374
|
+
* `DataContract.actionSpec[actionName]` IS the entry.
|
|
375
|
+
*/
|
|
376
|
+
export type ActionSpec = Record<string, ActionEntry>;
|
|
377
|
+
/**
|
|
378
|
+
* Input passed to a refresh tool when the wiredActionRouter fires it
|
|
379
|
+
* after a wired action succeeds. See {@link StreamChannelEntry.tool}
|
|
380
|
+
* for the broader refresh-semantics lock.
|
|
381
|
+
*
|
|
382
|
+
* **v1 constraint: always empty.** Refresh tools MUST be parameterless
|
|
383
|
+
* (filter-less, context-less). Authors who need filtered / contextual
|
|
384
|
+
* reads should chain the filter into a single action tool that returns
|
|
385
|
+
* the filtered state directly — the refresh path is deliberately a
|
|
386
|
+
* read-only re-fetch of the channel's canonical state.
|
|
387
|
+
*
|
|
388
|
+
* Typed as `Record<string, never>` (empty object with no properties)
|
|
389
|
+
* rather than an empty interface so the type stays structurally
|
|
390
|
+
* assignable to `Record<string, unknown>` call sites (e.g.,
|
|
391
|
+
* `WiredActionRouter.invoke`) without any cast.
|
|
392
|
+
*
|
|
393
|
+
* This type is named separately from `{}` so that:
|
|
394
|
+
*
|
|
395
|
+
* 1. Call sites are grep-able — producers and consumers that need to
|
|
396
|
+
* reason about the refresh-input contract can find each other.
|
|
397
|
+
* 2. v2 evolution (e.g., passing `{sessionId}` / `{actor}` context on
|
|
398
|
+
* refresh) has a single point to widen; today's `{}` literal
|
|
399
|
+
* wouldn't trip any compile error if the wire expectation
|
|
400
|
+
* changed.
|
|
401
|
+
* 3. Implementations of {@link WiredActionRouter} that want to treat
|
|
402
|
+
* refresh inputs specially (e.g., route through a different
|
|
403
|
+
* invoker) can pattern-match on the type.
|
|
404
|
+
*/
|
|
405
|
+
export type RefreshInput = Record<string, never>;
|
|
406
|
+
/**
|
|
407
|
+
* Frozen singleton instance of {@link RefreshInput}. Pass this to
|
|
408
|
+
* refresh-tool invocations instead of a fresh `{}` literal so that:
|
|
409
|
+
*
|
|
410
|
+
* - Every call site emits exactly the same reference (cheap identity
|
|
411
|
+
* checks in mocks / spies / test harnesses).
|
|
412
|
+
* - `Object.freeze` catches accidental mutation that would otherwise
|
|
413
|
+
* surface as cross-invocation interference in long-running servers.
|
|
414
|
+
*/
|
|
415
|
+
export declare const EMPTY_REFRESH_INPUT: RefreshInput;
|
|
416
|
+
/**
|
|
417
|
+
* Per-tool metadata in an {@link AgentCapabilitiesSpec}.
|
|
418
|
+
*
|
|
419
|
+
* Documents an MCP tool the contract references — by `actionSpec[*].nextStep`,
|
|
420
|
+
* by `streamSpec[*].source.tool`, or simply for the LLM-authoring catalog.
|
|
421
|
+
* The `example` field's `input`/`output` keys align with MCP's tool envelope
|
|
422
|
+
* naming so the contract reads identically to what the agent's MCP client sees.
|
|
423
|
+
*/
|
|
424
|
+
export interface AgentToolEntry {
|
|
425
|
+
/** Human-readable description of this tool. */
|
|
426
|
+
description?: string;
|
|
427
|
+
/**
|
|
428
|
+
* When / why / by-whom this tool is called. Free-form LLM-targeted
|
|
429
|
+
* prose — the "context-of-use" hint that bare `description` lacks.
|
|
430
|
+
* Read by the UI generator and the agent's reasoning loop alike.
|
|
431
|
+
*/
|
|
432
|
+
usage?: string;
|
|
433
|
+
/**
|
|
434
|
+
* JSON Schema for the tool's input. MCP-aligned name. Optional —
|
|
435
|
+
* may be hydrated from MCP registry at generation time for tools the
|
|
436
|
+
* server can introspect; opaque for tools on other MCP servers.
|
|
437
|
+
*/
|
|
438
|
+
inputSchema?: JsonSchema;
|
|
439
|
+
/**
|
|
440
|
+
* JSON Schema for the tool's output. MCP-aligned name. Optional —
|
|
441
|
+
* same hydration story as `inputSchema`.
|
|
442
|
+
*/
|
|
443
|
+
outputSchema?: JsonSchema;
|
|
444
|
+
/**
|
|
445
|
+
* Whether the contract is unsatisfiable if the agent's MCP toolbox
|
|
446
|
+
* lacks this tool. Advisory in v1: enforcement happens at dispatch
|
|
447
|
+
* time (the agent gets `TOOL_UNAVAILABLE` if the named tool isn't
|
|
448
|
+
* registered), not at push time. Future: agent reports its toolbox
|
|
449
|
+
* on handshake; server can validate `required: true` proactively.
|
|
450
|
+
*
|
|
451
|
+
* Default: `false`. UI/agent code MUST guard against absence (e.g.,
|
|
452
|
+
* conditional render, fallback reasoning).
|
|
453
|
+
*/
|
|
454
|
+
required?: boolean;
|
|
455
|
+
/**
|
|
456
|
+
* Example input/output pair for documentation and boilerplate
|
|
457
|
+
* generation. Keys `input` / `output` are MCP-aligned.
|
|
458
|
+
*/
|
|
459
|
+
example?: {
|
|
460
|
+
input: JsonValue;
|
|
461
|
+
output: JsonValue;
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Agent-capabilities catalog — declares the MCP tools the contract references.
|
|
466
|
+
*
|
|
467
|
+
* The agent's MCP toolbox is the source of truth at dispatch time; this
|
|
468
|
+
* catalog is the **contract author's documentation** of which tools the
|
|
469
|
+
* UI relies on. Cross-referenced from:
|
|
470
|
+
*
|
|
471
|
+
* - `actionSpec[*].nextStep` (agent's next-turn hint)
|
|
472
|
+
* - `streamSpec[*].source.tool` (channel data source)
|
|
473
|
+
*
|
|
474
|
+
* Shape mirrors {@link ClientCapabilitiesSpec} — both are capability
|
|
475
|
+
* catalogs grouped under a `*Capabilities` parent so the protocol's
|
|
476
|
+
* capability namespace reads symmetrically (agent-side tools vs.
|
|
477
|
+
* client-side gadgets).
|
|
478
|
+
*/
|
|
479
|
+
export interface AgentCapabilitiesSpec {
|
|
480
|
+
/** Per-tool definitions keyed by tool name. */
|
|
481
|
+
tools: Record<string, AgentToolEntry>;
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Per-export metadata shared by every {@link GadgetExport} kind —
|
|
485
|
+
* LLM-targeted teaching text plus the runtime gates an export needs.
|
|
486
|
+
*
|
|
487
|
+
* Required-ness lives in the schemas, not the type system: the
|
|
488
|
+
* registry-side `strictGadgetExportSchema` requires `description` /
|
|
489
|
+
* `usage` / `example`; the wire-permissive `gadgetExportSchema`
|
|
490
|
+
* leaves them optional.
|
|
491
|
+
*/
|
|
492
|
+
export interface GadgetExportBase {
|
|
493
|
+
/**
|
|
494
|
+
* Human-readable description of what this export does. REQUIRED on
|
|
495
|
+
* the registry side; optional on the contract side (push-time merge
|
|
496
|
+
* inherits the registry copy when absent).
|
|
497
|
+
*/
|
|
498
|
+
description?: string;
|
|
499
|
+
/**
|
|
500
|
+
* When / why / by-whom this export is used — the free-form
|
|
501
|
+
* "context-of-use" hint bare `description` lacks. Parallel to
|
|
502
|
+
* {@link AgentToolEntry.usage}.
|
|
503
|
+
*/
|
|
504
|
+
usage?: string;
|
|
505
|
+
/**
|
|
506
|
+
* Concrete usage example for boilerplate generation + prompt
|
|
507
|
+
* priming. Free-form `JsonValue` (typically an object describing
|
|
508
|
+
* the call / render shape + expected return).
|
|
509
|
+
*/
|
|
510
|
+
example?: JsonValue;
|
|
511
|
+
/**
|
|
512
|
+
* Anti-patterns + known gotchas surfaced in code-gen prompts so the
|
|
513
|
+
* LLM avoids the same traps every time.
|
|
514
|
+
*/
|
|
515
|
+
gotchas?: string;
|
|
516
|
+
/**
|
|
517
|
+
* Optional permission identifier this export gates on (Web
|
|
518
|
+
* Permissions API + MCP Apps enum — see `KNOWN_PERMISSION_NAMES`).
|
|
519
|
+
* The registry-side schema enum-checks it; the wire side never
|
|
520
|
+
* carries it.
|
|
521
|
+
*/
|
|
522
|
+
permission?: string;
|
|
523
|
+
/**
|
|
524
|
+
* Whether the UI MUST mount this export for the contract to be
|
|
525
|
+
* satisfiable. Default `false`. Advisory in v1 — enforced at
|
|
526
|
+
* boilerplate-generation time, not at runtime.
|
|
527
|
+
*/
|
|
528
|
+
required?: boolean;
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* A hook export — a `use`-prefixed React hook the generated component
|
|
532
|
+
* calls. Implementations MUST satisfy {@link GadgetHook}.
|
|
533
|
+
*/
|
|
534
|
+
export interface GadgetHookExport extends GadgetExportBase {
|
|
535
|
+
/**
|
|
536
|
+
* Hook name — `use`-prefixed camelCase (e.g. `'useLeafletMap'`,
|
|
537
|
+
* `'useGeolocation'`). Boilerplate emits `import { <hook> } from
|
|
538
|
+
* '<package>'` plus a call site against this value.
|
|
539
|
+
*/
|
|
540
|
+
hook: string;
|
|
541
|
+
/**
|
|
542
|
+
* Mutually exclusive with {@link GadgetComponentExport.component}.
|
|
543
|
+
* `component?: never` makes {@link GadgetExport} a type-EXCLUSIVE
|
|
544
|
+
* union — a both-fields object `{hook, component}` no longer
|
|
545
|
+
* type-checks, so field-presence kind discrimination is order-
|
|
546
|
+
* independent.
|
|
547
|
+
*/
|
|
548
|
+
component?: never;
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* A component export — a PascalCase React component the generated
|
|
552
|
+
* code renders as JSX (`<Chart … />`).
|
|
553
|
+
*/
|
|
554
|
+
export interface GadgetComponentExport extends GadgetExportBase {
|
|
555
|
+
/**
|
|
556
|
+
* Component name — PascalCase (e.g. `'Chart'`, `'MapView'`).
|
|
557
|
+
* Boilerplate emits `import { <component> } from '<package>'` plus
|
|
558
|
+
* a JSX render site against this value.
|
|
559
|
+
*/
|
|
560
|
+
component: string;
|
|
561
|
+
/**
|
|
562
|
+
* Mutually exclusive with {@link GadgetHookExport.hook}.
|
|
563
|
+
* `hook?: never` makes {@link GadgetExport} a type-EXCLUSIVE union —
|
|
564
|
+
* a both-fields object `{hook, component}` no longer type-checks, so
|
|
565
|
+
* field-presence kind discrimination is order-independent.
|
|
566
|
+
*/
|
|
567
|
+
hook?: never;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* One export of a gadget package — a hook or a component,
|
|
571
|
+
* distinguished by which identifier field is present (`hook` vs
|
|
572
|
+
* `component`). A gadget package ({@link GadgetDescriptor}) bundles
|
|
573
|
+
* one or more of these behind a single npm identity; a wire-side
|
|
574
|
+
* {@link GadgetExportUse} entry points at exactly one.
|
|
575
|
+
*/
|
|
576
|
+
export type GadgetExport = GadgetHookExport | GadgetComponentExport;
|
|
577
|
+
/**
|
|
578
|
+
* **Wire-side** per-export use entry — one value in a package's
|
|
579
|
+
* {@link GadgetPackageUse} map on
|
|
580
|
+
* `DataContract.clientCapabilities.gadgets`.
|
|
581
|
+
*
|
|
582
|
+
* The export NAME is the map key, not a field — and its grammar
|
|
583
|
+
* discriminates kind (a `use`-prefixed key is a hook, a PascalCase
|
|
584
|
+
* key is a component). The only wire-authored payload is optional
|
|
585
|
+
* intent-specific override prose.
|
|
586
|
+
*
|
|
587
|
+
* Design intent (S+ protocol bar): the wire carries IDENTITY ONLY —
|
|
588
|
+
* `(package, export name)`. It CANNOT carry `version`, transport
|
|
589
|
+
* fields (`bundleUrl`, `bundleSri`, `bundleHost`, `connect`,
|
|
590
|
+
* `requires`, `typesUrl`, …) or per-export registry metadata
|
|
591
|
+
* (`permission`, `example`, `gotchas`). All of that belongs to the
|
|
592
|
+
* registered {@link GadgetDescriptor} the ggui server resolves from
|
|
593
|
+
* the app's `App.gadgets` catalog at push time — `version` is the
|
|
594
|
+
* operator's deployment pin, not the agent's to author.
|
|
595
|
+
*/
|
|
596
|
+
export interface GadgetExportUse {
|
|
597
|
+
/**
|
|
598
|
+
* Intent-specific override of the registered export's description.
|
|
599
|
+
* When omitted, push-time resolution inherits the registered
|
|
600
|
+
* description verbatim; when present, the agent's prose wins.
|
|
601
|
+
*/
|
|
602
|
+
description?: string;
|
|
603
|
+
/**
|
|
604
|
+
* Intent-specific override of the registered usage hint. Same
|
|
605
|
+
* "agent wins" merge semantics as `description`.
|
|
606
|
+
*/
|
|
607
|
+
usage?: string;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* **Wire-side** per-package gadget use — the value type of
|
|
611
|
+
* {@link ClientCapabilitiesSpec.gadgets}, which is keyed by npm
|
|
612
|
+
* package name.
|
|
613
|
+
*
|
|
614
|
+
* A map of export name → {@link GadgetExportUse} — the exports of one
|
|
615
|
+
* package the UI uses, keyed by export name (≥1; a `use`-prefixed
|
|
616
|
+
* hook or a PascalCase component). The wire carries no package-level
|
|
617
|
+
* field — `version` and transport metadata are registry-side — so a
|
|
618
|
+
* package entry IS its export map, with no `exports` wrapper.
|
|
619
|
+
*/
|
|
620
|
+
export type GadgetPackageUse = Record<string, GadgetExportUse>;
|
|
621
|
+
/**
|
|
622
|
+
* Flattened view of one gadget export a contract uses — produced by
|
|
623
|
+
* `listContractGadgets` from the package-keyed
|
|
624
|
+
* {@link ClientCapabilitiesSpec.gadgets}.
|
|
625
|
+
*
|
|
626
|
+
* NOT a wire type: an internal convenience so the push gates, the
|
|
627
|
+
* descriptor resolver, and code-gen can iterate `(package, name)`
|
|
628
|
+
* pairs uniformly instead of re-walking the nested wire map.
|
|
629
|
+
*/
|
|
630
|
+
export interface GadgetUse {
|
|
631
|
+
/** npm package name — the `clientCapabilities.gadgets` map key. */
|
|
632
|
+
package: string;
|
|
633
|
+
/** Export name — `use`-prefixed hook or PascalCase component. */
|
|
634
|
+
name: string;
|
|
635
|
+
/** Intent-specific description override, when the contract set one. */
|
|
636
|
+
description?: string;
|
|
637
|
+
/** Intent-specific usage override, when the contract set one. */
|
|
638
|
+
usage?: string;
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Registered descriptor for a gadget **package** (registry side).
|
|
642
|
+
*
|
|
643
|
+
* A gadget package bundles one or more {@link GadgetExport}s — hooks
|
|
644
|
+
* and/or components — behind a single npm identity (`package` +
|
|
645
|
+
* `version`) and a single bundle. Transport metadata (`bundleUrl`,
|
|
646
|
+
* `bundleSri`, `bundleHost`, `styleUrl`, `connect`, `requires`,
|
|
647
|
+
* `typesUrl`, `typesSri`) is per-PACKAGE; teaching text + `permission`
|
|
648
|
+
* + the `required` flag are per-EXPORT (on each `exports[*]`).
|
|
649
|
+
*
|
|
650
|
+
* One shape used by:
|
|
651
|
+
*
|
|
652
|
+
* - **Registry side** (`App.gadgets` + wrapper SDK output) — every
|
|
653
|
+
* export's `description` / `usage` / `example` SHOULD be
|
|
654
|
+
* populated. `strictGadgetDescriptorSchema` enforces required
|
|
655
|
+
* teaching text + an enum-tight `permission` per export;
|
|
656
|
+
* `registeredGadgetDescriptorSchema` additionally requires
|
|
657
|
+
* `typesUrl` for non-stdlib packages.
|
|
658
|
+
* - **Resolved sidecar side** — at push time
|
|
659
|
+
* `filterDescriptorsToContract` snapshots the subset of
|
|
660
|
+
* `App.gadgets` the contract references onto
|
|
661
|
+
* `SessionStackEntry.gadgetDescriptors`. Wire-side authors NEVER
|
|
662
|
+
* see this shape; they author the package-keyed
|
|
663
|
+
* {@link ClientCapabilitiesSpec} map of {@link GadgetPackageUse}.
|
|
664
|
+
*
|
|
665
|
+
* Strictness lives in the schemas, not the type system.
|
|
666
|
+
*
|
|
667
|
+
* See {@link GadgetHook} for the runtime hook contract every hook
|
|
668
|
+
* export MUST satisfy.
|
|
669
|
+
*/
|
|
670
|
+
export interface GadgetDescriptor {
|
|
671
|
+
/**
|
|
672
|
+
* The exports this package provides — hooks and/or components. At
|
|
673
|
+
* least one (enforced by the schema). Each {@link GadgetExport}
|
|
674
|
+
* carries its own identifier (`hook` or `component`) + teaching text
|
|
675
|
+
* (`description` / `usage` / `example` / `gotchas`) + per-export
|
|
676
|
+
* `permission` / `required`.
|
|
677
|
+
*/
|
|
678
|
+
exports: GadgetExport[];
|
|
679
|
+
/**
|
|
680
|
+
* Exact semver pin (e.g., `'0.0.1'`, `'1.2.3-beta.1'`). REQUIRED.
|
|
681
|
+
* Registry-side ONLY — the wire carries no version; the operator's
|
|
682
|
+
* `App.gadgets` catalog is the sole version pin, resolved
|
|
683
|
+
* server-side at push time. `(package, version)` is the registry's
|
|
684
|
+
* frozen identity tuple. Bumping requires a new `bundleSri` /
|
|
685
|
+
* `typesSri` (registry-immutability invariant enforced by
|
|
686
|
+
* `lintGadgetCatalog`).
|
|
687
|
+
*
|
|
688
|
+
* No ranges (no `^`, `~`, `>=`).
|
|
689
|
+
*/
|
|
690
|
+
version: string;
|
|
691
|
+
/**
|
|
692
|
+
* Bare npm package name the wrapper is imported from (e.g.,
|
|
693
|
+
* `'@my-org/leaflet'`, `'@ggui-ai/gadgets'`). REQUIRED. The wire
|
|
694
|
+
* references this package by name — it is the key of the
|
|
695
|
+
* `clientCapabilities.gadgets` map; `(package, version)` is the
|
|
696
|
+
* registry's frozen identity tuple.
|
|
697
|
+
*
|
|
698
|
+
* Boilerplate emits `import { <hook> } from '<package>';` against
|
|
699
|
+
* this value. NOT a URL — registry hostnames live on `bundleUrl` /
|
|
700
|
+
* `typesUrl`. The gadget author bundles all underlying 3rd-party
|
|
701
|
+
* dependencies into the wrapper bundle.
|
|
702
|
+
*/
|
|
703
|
+
package: string;
|
|
704
|
+
/**
|
|
705
|
+
* ggui-hosted bundle URL — the preferred distribution path. Same
|
|
706
|
+
* origin as the iframe in single-tenant OSS deployments (served
|
|
707
|
+
* from `/_ggui/libs/<libId>/bundle.js`) and the ggui marketplace
|
|
708
|
+
* CDN in cloud deployments. CSP `script-src` allowlists only the
|
|
709
|
+
* ggui origin — no per-plugin third-party origins.
|
|
710
|
+
*
|
|
711
|
+
* When set, the boilerplate generator imports from this URL
|
|
712
|
+
* instead of `package`. Either `package` OR `bundleUrl` MUST be
|
|
713
|
+
* present.
|
|
714
|
+
*
|
|
715
|
+
* Escape hatch: authors who want CDN-distributed bundles can point
|
|
716
|
+
* `bundleUrl` at a 3rd-party URL (e.g., `'https://esm.sh/...'`)
|
|
717
|
+
* and accept that origin in the CSP allowlist. The preferred path
|
|
718
|
+
* is to publish to ggui's bundle host and stay same-origin.
|
|
719
|
+
*/
|
|
720
|
+
bundleUrl?: string;
|
|
721
|
+
/**
|
|
722
|
+
* Registry hostname (no scheme, no path) the server uses to resolve
|
|
723
|
+
* `bundleUrl` + `styleUrl` at push time:
|
|
724
|
+
*
|
|
725
|
+
* `https://<bundleHost>/bundles/<scope>/<name>/<version>/bundle.js`
|
|
726
|
+
* `https://<bundleHost>/bundles/<scope>/<name>/<version>/style.css`
|
|
727
|
+
*
|
|
728
|
+
* Resolution order (operator wins over author wins over spec default):
|
|
729
|
+
*
|
|
730
|
+
* 1. operator's `app.gadgets[*].bundleUrl` — explicit full URL,
|
|
731
|
+
* escape hatch that bypasses bundleHost resolution entirely.
|
|
732
|
+
* 2. operator's `app.gadgets[*].bundleHost` — hostname override
|
|
733
|
+
* for e2e / sandbox testing.
|
|
734
|
+
* 3. gadget author's `ggui.gadget.json#bundleHost` (default the
|
|
735
|
+
* author shipped).
|
|
736
|
+
* 4. spec default `registry.ggui.ai`.
|
|
737
|
+
*
|
|
738
|
+
* Resolution requires `package` (`@scope/name`) and `version` on the
|
|
739
|
+
* same entry — without them the server cannot assemble the path.
|
|
740
|
+
* The `strictGadgetDescriptorSchema` refinement enforces this trio.
|
|
741
|
+
*
|
|
742
|
+
* Hostname-only constraint: lowercase alphanumerics + dots/hyphens +
|
|
743
|
+
* optional `:port`. See {@link BUNDLE_HOST_RE}. Non-HTTPS or
|
|
744
|
+
* non-standard paths require the `bundleUrl` escape hatch instead.
|
|
745
|
+
*/
|
|
746
|
+
bundleHost?: string;
|
|
747
|
+
/**
|
|
748
|
+
* SHA-384 SRI hash of the bundle, formatted as `sha384-<base64>`.
|
|
749
|
+
* When present, iframe-runtime emits the bundle import as a
|
|
750
|
+
* `<script type="module" integrity="<bundleSri>" src="<bundleUrl>">`
|
|
751
|
+
* element so the browser refuses execution on hash mismatch — the
|
|
752
|
+
* defense against CDN compromise that turned a marketplace bundle
|
|
753
|
+
* into an attack surface.
|
|
754
|
+
*
|
|
755
|
+
* Authors do NOT set this manually — registry install writes it
|
|
756
|
+
* from the value the publish Lambda computed server-side over the
|
|
757
|
+
* immutable bundle bytes. Hand-authored ggui.json refs omit the
|
|
758
|
+
* field; the loader falls back to integrity-less dynamic `import()`
|
|
759
|
+
* (the same posture as in-tree wrappers).
|
|
760
|
+
*
|
|
761
|
+
* Only meaningful alongside `bundleUrl`. When `bundleSri` is set
|
|
762
|
+
* but `bundleUrl` is absent the field is ignored — `package`
|
|
763
|
+
* resolution doesn't flow through `<script>` injection.
|
|
764
|
+
*/
|
|
765
|
+
bundleSri?: string;
|
|
766
|
+
/**
|
|
767
|
+
* URL of an optional stylesheet the wrapper requires (e.g.,
|
|
768
|
+
* `leaflet.css`). Same origin posture as `bundleUrl` — preferred
|
|
769
|
+
* to be ggui-hosted and same-origin so CSP `style-src 'self'`
|
|
770
|
+
* covers it. Wrappers MAY inline CSS inside their `bind` function
|
|
771
|
+
* instead of declaring a styleUrl — when they do, this field is
|
|
772
|
+
* omitted.
|
|
773
|
+
*/
|
|
774
|
+
styleUrl?: string;
|
|
775
|
+
/**
|
|
776
|
+
* API-call origins the wrapper makes runtime fetches against (e.g.,
|
|
777
|
+
* `['https://api.stripe.com', 'https://api.doordash.com']`). The
|
|
778
|
+
* renderer's CSP derives the `connect-src` allowlist from these
|
|
779
|
+
* URLs' origins. UNAVOIDABLE — ggui can't proxy 3rd-party API
|
|
780
|
+
* calls without breaking observability and auth/licensing
|
|
781
|
+
* constraints.
|
|
782
|
+
*
|
|
783
|
+
* Wrappers around browser-native APIs (stdlib hooks) omit this —
|
|
784
|
+
* they have no remote fetches.
|
|
785
|
+
*/
|
|
786
|
+
connect?: readonly string[];
|
|
787
|
+
/**
|
|
788
|
+
* Names of public-env keys the wrapper requires at runtime (e.g.,
|
|
789
|
+
* `['GGUI_PUBLIC_APP_MAPBOX_TOKEN']`). The registration-time
|
|
790
|
+
* validator rejects wrappers whose `requires` are unsatisfied by
|
|
791
|
+
* the app's declared public-env keys.
|
|
792
|
+
*/
|
|
793
|
+
requires?: readonly string[];
|
|
794
|
+
/**
|
|
795
|
+
* HTTPS URL of the wrapper's TypeScript declaration
|
|
796
|
+
* file (`.d.ts`). The publish flow runs `tsc --declaration` (or
|
|
797
|
+
* `tsup --dts`) over the wrapper source and uploads the emitted
|
|
798
|
+
* `.d.ts` alongside the bundle; the registry stamps the URL here.
|
|
799
|
+
*
|
|
800
|
+
* The handler parallel-fetches every `typesUrl` at push time
|
|
801
|
+
* (`fetchGadgetTypes`), verifies the SHA-384 SRI against
|
|
802
|
+
* {@link typesSri}, and loads the `.d.ts` content into the code-gen
|
|
803
|
+
* sandbox's virtual file system at
|
|
804
|
+
* `node_modules/<package>/index.d.ts`. A generated direct import
|
|
805
|
+
* `import { useLeafletMap } from '<package>'` resolves through the
|
|
806
|
+
* loaded `.d.ts` with the wrapper's NAMED types (`LeafletMapOptions`,
|
|
807
|
+
* …) preserved, not collapsed to structural soup.
|
|
808
|
+
*
|
|
809
|
+
* REQUIRED for non-stdlib registrations — the
|
|
810
|
+
* `strictGadgetDescriptorSchema` refinement enforces it when
|
|
811
|
+
* `package !== '@ggui-ai/gadgets'`. Stdlib gadgets omit it: the
|
|
812
|
+
* sandbox already loads `@ggui-ai/gadgets`'s own types directly.
|
|
813
|
+
*
|
|
814
|
+
* The bare name `signature` is reserved for a future
|
|
815
|
+
* descriptor-level cryptographic field (Ed25519 / Sigstore) and
|
|
816
|
+
* MUST NOT be reused for type metadata.
|
|
817
|
+
*/
|
|
818
|
+
typesUrl?: string;
|
|
819
|
+
/**
|
|
820
|
+
* SHA-384 SRI of the `.d.ts` at {@link typesUrl},
|
|
821
|
+
* formatted `sha384-<base64>`. The handler verifies the fetched
|
|
822
|
+
* `.d.ts` bytes against this before loading them into the sandbox
|
|
823
|
+
* VFS — a CDN-compromise defense symmetric with {@link bundleSri}
|
|
824
|
+
* for the bundle.
|
|
825
|
+
*
|
|
826
|
+
* Registry-emitted (computed over the immutable `.d.ts` bytes at
|
|
827
|
+
* publish time). Only meaningful alongside `typesUrl`.
|
|
828
|
+
*/
|
|
829
|
+
typesSri?: string;
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* Gadgets catalog — declares browser-capability gadget hooks
|
|
833
|
+
* the UI uses. Pure declaration (no RPC contract). See
|
|
834
|
+
* {@link GadgetHook} for the runtime hook contract.
|
|
835
|
+
*
|
|
836
|
+
* Shape mirrors {@link AgentCapabilitiesSpec} — both are capability
|
|
837
|
+
* catalogs grouped under a `*Capabilities` parent so the protocol's
|
|
838
|
+
* capability namespace reads symmetrically (agent-side tools vs.
|
|
839
|
+
* client-side gadgets).
|
|
840
|
+
*
|
|
841
|
+
* Non-generic — the wire surface carries package-keyed
|
|
842
|
+
* {@link GadgetPackageUse} values. The post-resolution view (full
|
|
843
|
+
* descriptors for hygiene + transport metadata derivation) lives on
|
|
844
|
+
* `SessionStackEntry.gadgetDescriptors` as a sidecar, NOT as an
|
|
845
|
+
* enrichment overlay on this type.
|
|
846
|
+
*/
|
|
847
|
+
export interface ClientCapabilitiesSpec {
|
|
848
|
+
/** Per-package gadget use, keyed by npm package name. */
|
|
849
|
+
gadgets: Record<string, GadgetPackageUse>;
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Per-slot metadata in a {@link ContextSpec}. Declares one named
|
|
853
|
+
* slot's value contract plus its observation timing.
|
|
854
|
+
*
|
|
855
|
+
* The `schema` is the authoritative shape guard — every value the
|
|
856
|
+
* runtime observes through this slot's React Context Provider gets
|
|
857
|
+
* validated against the schema before posting to the LLM context.
|
|
858
|
+
* Type mismatches drop silently in production with a dev-only warning;
|
|
859
|
+
* mirrors `ActionEntry.schema`'s enforcement posture.
|
|
860
|
+
*
|
|
861
|
+
* `default` is for boilerplate-generation only — the LLM uses it as
|
|
862
|
+
* the initial value for its `useState(default)` call. The runtime
|
|
863
|
+
* doesn't seed context slots from defaults; the Provider's `value`
|
|
864
|
+
* is the authoritative source.
|
|
865
|
+
*/
|
|
866
|
+
export interface ContextEntry {
|
|
867
|
+
/** Human-readable description of this slot. Used by docs + LLM
|
|
868
|
+
* context to explain what the slot represents. */
|
|
869
|
+
description?: string;
|
|
870
|
+
/**
|
|
871
|
+
* JSON Schema for the slot value. Authoritative shape guard.
|
|
872
|
+
* Every Provider value the observer sees gets validated against
|
|
873
|
+
* this before being posted to the LLM context. Mismatches log
|
|
874
|
+
* a dev-only warning and drop silently in production.
|
|
875
|
+
*/
|
|
876
|
+
schema: JsonSchema;
|
|
877
|
+
/**
|
|
878
|
+
* Optional initial value the boilerplate uses when generating the
|
|
879
|
+
* component's `useState(default)` call. The runtime does NOT seed
|
|
880
|
+
* context slots from this — it's authoring scaffold only. Typed as
|
|
881
|
+
* {@link JsonValue} (any JSON-safe value).
|
|
882
|
+
*/
|
|
883
|
+
default?: JsonValue;
|
|
884
|
+
/**
|
|
885
|
+
* Debounce window in milliseconds for posting value changes to the
|
|
886
|
+
* LLM context. `0` posts immediately on every change. Omitted →
|
|
887
|
+
* runtime applies the locked default {@link DEFAULT_CONTEXT_DEBOUNCE_MS}
|
|
888
|
+
* (`300`).
|
|
889
|
+
*
|
|
890
|
+
* Use cases:
|
|
891
|
+
* - Text drafts (typing input): leave default 300ms — coalesces
|
|
892
|
+
* keystrokes
|
|
893
|
+
* - Step / tab switches: set `0` — immediate, no value to coalesce
|
|
894
|
+
* - High-frequency UI state (hover, scroll): set higher, e.g. `500`,
|
|
895
|
+
* to reduce LLM context churn
|
|
896
|
+
*/
|
|
897
|
+
debounceMs?: number;
|
|
898
|
+
/**
|
|
899
|
+
* Example value (for documentation + sample rendering). Typed as
|
|
900
|
+
* {@link JsonValue}.
|
|
901
|
+
*/
|
|
902
|
+
example?: JsonValue;
|
|
903
|
+
}
|
|
904
|
+
/** Locked default applied when {@link ContextEntry.debounceMs}
|
|
905
|
+
* is omitted. */
|
|
906
|
+
export declare const DEFAULT_CONTEXT_DEBOUNCE_MS = 300;
|
|
907
|
+
/**
|
|
908
|
+
* Context contract — declares typed slots the iframe surfaces to the
|
|
909
|
+
* agent's LLM context via React Context Providers. Together with
|
|
910
|
+
* {@link PropsSpec}, {@link StreamSpec}, and {@link ActionSpec},
|
|
911
|
+
* forms the four-spec bidirectional state-movement protocol:
|
|
912
|
+
*
|
|
913
|
+
* - {@link PropsSpec} — agent → client (one-shot via `ggui_update`)
|
|
914
|
+
* - {@link StreamSpec} — agent → client (live via live-channel)
|
|
915
|
+
* - {@link ActionSpec} — client → agent (user gesture/tool intent)
|
|
916
|
+
* - {@link ContextSpec} — client → agent (observable state, this)
|
|
917
|
+
*
|
|
918
|
+
* Shape: flat map keyed by slot name → entry. Slot keys MUST be
|
|
919
|
+
* camelCase JS identifiers (`/^[a-zA-Z_][a-zA-Z0-9_]*$/`); the
|
|
920
|
+
* boilerplate generates one PascalCase `Context` per slot at
|
|
921
|
+
* generation time.
|
|
922
|
+
*
|
|
923
|
+
* Direction: **client → agent only**. Servers MUST NOT push values
|
|
924
|
+
* back to context slots — agent-driven state changes use propsSpec or
|
|
925
|
+
* streamSpec instead.
|
|
926
|
+
*
|
|
927
|
+
* Persistence: ephemeral. The server does NOT persist context values
|
|
928
|
+
* across iframe reconnects. On WS reattach the iframe re-emits its
|
|
929
|
+
* current values.
|
|
930
|
+
*/
|
|
931
|
+
export type ContextSpec = Record<string, ContextEntry>;
|
|
932
|
+
/**
|
|
933
|
+
* Derive a JSON-safe default value for a {@link ContextEntry}.
|
|
934
|
+
*
|
|
935
|
+
* Resolution order:
|
|
936
|
+
* 1. `entry.default` (if author provided)
|
|
937
|
+
* 2. Schema-typed fallback:
|
|
938
|
+
* - `string` → `''`
|
|
939
|
+
* - `number` / `integer` → `0`
|
|
940
|
+
* - `boolean` → `false`
|
|
941
|
+
* - `array` → `[]`
|
|
942
|
+
* - `object` → `{}`
|
|
943
|
+
* - `null` → `null`
|
|
944
|
+
* 3. `undefined` (caller validates / rejects)
|
|
945
|
+
*
|
|
946
|
+
* Push-time validators MUST reject contextSpec entries that resolve
|
|
947
|
+
* to `undefined` here (e.g., schema is `oneOf` with no clear primitive
|
|
948
|
+
* type — author MUST provide an explicit `default` for such schemas).
|
|
949
|
+
*
|
|
950
|
+
* Consumed by the boilerplate generator's useState emission and by
|
|
951
|
+
* the push-time validator's default-derivability rule.
|
|
952
|
+
*
|
|
953
|
+
* @public
|
|
954
|
+
*/
|
|
955
|
+
export declare function deriveContextDefault(entry: ContextEntry): JsonValue | undefined;
|
|
956
|
+
/**
|
|
957
|
+
* Data contract that bind a generated component to its consumers.
|
|
958
|
+
*
|
|
959
|
+
* Seven parts:
|
|
960
|
+
* - **intent**: WHY this UI exists — concise purpose capturing user goal, data shown, and interaction pattern (NOT a contract field; threaded externally on `ggui_handshake({sessionId, intent})`)
|
|
961
|
+
* - **propsSpec**: WHAT data the UI renders initially (set on push, mutated via ggui_update) — agent → client one-shot
|
|
962
|
+
* - **streamSpec**: WHAT live data the UI accepts — flat map keyed by channel name (agent → client live)
|
|
963
|
+
* - **contextSpec**: WHAT observable client state the LLM sees — flat map keyed by slot name (client → agent live, last-write-wins state)
|
|
964
|
+
* - **actionSpec**: WHAT user interactions the UI emits — flat map keyed by action name (client → agent, discrete events that drive turns)
|
|
965
|
+
* - **agentCapabilities**: WHAT MCP tools the contract references — declarative catalog keyed by tool name
|
|
966
|
+
* - **clientCapabilities**: WHAT gadget exports the UI declares — declarative catalog keyed by npm package name
|
|
967
|
+
*
|
|
968
|
+
* The two inbound specs (actionSpec + contextSpec) split on the placement test:
|
|
969
|
+
* "does this thing need the agent's next-turn reasoning?" Yes → actionSpec, No → contextSpec.
|
|
970
|
+
* Actions drive turns; context observes state. There is no third category.
|
|
971
|
+
*
|
|
972
|
+
* Together, the four typed surfaces — `propsSpec` / `streamSpec` /
|
|
973
|
+
* `actionSpec` / `contextSpec` — form a complete bidirectional
|
|
974
|
+
* state-movement protocol:
|
|
975
|
+
*
|
|
976
|
+
* - agent → client one-shot = `propsSpec` (initial render, mutate via `ggui_update`)
|
|
977
|
+
* - agent → client live = `streamSpec` (live-channel emits via `ggui_emit`)
|
|
978
|
+
* - client → agent gesture = `actionSpec` (discrete event; agent reacts on next turn via `ggui_consume`)
|
|
979
|
+
* - client → agent observable = `contextSpec` (last-write-wins state snapshot read on consume)
|
|
980
|
+
*
|
|
981
|
+
* The intent is the semantic identity of the contract — same intent = same UI pattern.
|
|
982
|
+
* Used for RAG search (embedding) and included in the contract hash.
|
|
983
|
+
*
|
|
984
|
+
* Field-shape note: `actionSpec` / `streamSpec` / `contextSpec` are flat
|
|
985
|
+
* `Record<name, Entry>` maps. `propsSpec` is a wrapper
|
|
986
|
+
* `{description?, properties: Record<name, PropEntry>}`.
|
|
987
|
+
*
|
|
988
|
+
* Every entry under `propsSpec.properties` / `actionSpec` /
|
|
989
|
+
* `streamSpec` / `contextSpec` is a WRAPPER carrying a JSON Schema in
|
|
990
|
+
* its `schema:` field; the JSON Schema does NOT sit flat at the entry
|
|
991
|
+
* level. The cross-ref invariant pairs `actionSpec[*].nextStep` and
|
|
992
|
+
* `streamSpec[*].source.tool` against `agentCapabilities.tools[*]`.
|
|
993
|
+
*
|
|
994
|
+
* Worked example (todo-list contract):
|
|
995
|
+
*
|
|
996
|
+
* {
|
|
997
|
+
* propsSpec: {
|
|
998
|
+
* properties: {
|
|
999
|
+
* todos: {
|
|
1000
|
+
* schema: { type: 'array', items: { type: 'object',
|
|
1001
|
+
* properties: { id: {type:'string'}, text: {type:'string'},
|
|
1002
|
+
* completed: {type:'boolean'} },
|
|
1003
|
+
* required: ['id', 'text', 'completed'] } },
|
|
1004
|
+
* required: true,
|
|
1005
|
+
* },
|
|
1006
|
+
* },
|
|
1007
|
+
* },
|
|
1008
|
+
* actionSpec: {
|
|
1009
|
+
* toggleTodo: {
|
|
1010
|
+
* label: 'Toggle todo',
|
|
1011
|
+
* schema: { type: 'object', properties: { id: {type:'string'} },
|
|
1012
|
+
* required: ['id'] },
|
|
1013
|
+
* nextStep: 'todo_toggle', // ← hints the next tool to the agent
|
|
1014
|
+
* },
|
|
1015
|
+
* },
|
|
1016
|
+
* agentCapabilities: {
|
|
1017
|
+
* tools: {
|
|
1018
|
+
* todo_toggle: { description: 'Flip a todo done/undone',
|
|
1019
|
+
* inputSchema: { type: 'object', properties: { id: {type:'string'} },
|
|
1020
|
+
* required: ['id'] } },
|
|
1021
|
+
* },
|
|
1022
|
+
* },
|
|
1023
|
+
* }
|
|
1024
|
+
*/
|
|
1025
|
+
export interface DataContract {
|
|
1026
|
+
/**
|
|
1027
|
+
* `intent` is NOT a contract field. The canonical intent (RAG
|
|
1028
|
+
* embedding search, contract hash key, prompt rendering, cache
|
|
1029
|
+
* scope) comes from the outer pipeline (the flat `intent` field on
|
|
1030
|
+
* `ggui_handshake`, the operator prompt for harness benchmarks),
|
|
1031
|
+
* which is the single source of truth for "the purpose of this UI".
|
|
1032
|
+
* `hashContract` takes `(contract, intent)`;
|
|
1033
|
+
* `buildContractsContext` takes `(contract, intent)`.
|
|
1034
|
+
*
|
|
1035
|
+
* No `interaction` mode field — the four specs
|
|
1036
|
+
* (props/action/context/stream) describe the wire surface
|
|
1037
|
+
* exhaustively, so a categorical mode label would be redundant.
|
|
1038
|
+
*/
|
|
1039
|
+
/**
|
|
1040
|
+
* Props spec — declaration of the initial-render props shape. Values
|
|
1041
|
+
* arrive on the wire via `ggui_push.input.props` / `ggui_update.input.props`
|
|
1042
|
+
* (those wire fields stay named `props` — they carry values, not the
|
|
1043
|
+
* spec). Naming aligns with the other three typed surfaces
|
|
1044
|
+
* (`actionSpec` / `streamSpec` / `contextSpec`).
|
|
1045
|
+
*/
|
|
1046
|
+
propsSpec?: PropsSpec;
|
|
1047
|
+
/**
|
|
1048
|
+
* Action contract — discrete user gestures (clicks, submits) the
|
|
1049
|
+
* agent reacts to on its NEXT TURN via `ggui_consume`. Flat map keyed
|
|
1050
|
+
* by action name (e.g., `actionSpec.createTask`).
|
|
1051
|
+
*
|
|
1052
|
+
* Every action drives a turn — there is no synchronous server-side
|
|
1053
|
+
* dispatch in agent-mediated deployments. Each entry carries a
|
|
1054
|
+
* `label`, optional payload `schema`, and optional `nextStep` hint
|
|
1055
|
+
* naming the tool the agent SHOULD call next. When `nextStep` is
|
|
1056
|
+
* present it MUST resolve in `agentCapabilities.tools` (cross-ref
|
|
1057
|
+
* invariant); OMIT `nextStep` entirely when the agent should decide
|
|
1058
|
+
* freely from broader context (open-ended form submits).
|
|
1059
|
+
*
|
|
1060
|
+
* Placement rule (`actions-vs-context.md`): use `actionSpec` for
|
|
1061
|
+
* events that NEED next-turn reasoning; use {@link contextSpec} for
|
|
1062
|
+
* observable state the agent reads without reacting per-change.
|
|
1063
|
+
*/
|
|
1064
|
+
actionSpec?: ActionSpec;
|
|
1065
|
+
/**
|
|
1066
|
+
* Stream contract — live update payloads via ggui_emit. Flat map
|
|
1067
|
+
* keyed by channel name (e.g., `streamSpec.tasks`).
|
|
1068
|
+
*/
|
|
1069
|
+
streamSpec?: StreamSpec;
|
|
1070
|
+
/**
|
|
1071
|
+
* Context contract — observable client state the LLM context
|
|
1072
|
+
* consumes. Flat map keyed by slot name (e.g.,
|
|
1073
|
+
* `contextSpec.currentStep`). Client → agent only; runtime
|
|
1074
|
+
* observes Provider values and posts debounced
|
|
1075
|
+
* `ui/update-model-context` envelopes. See {@link ContextSpec}
|
|
1076
|
+
* for the full contract.
|
|
1077
|
+
*/
|
|
1078
|
+
contextSpec?: ContextSpec;
|
|
1079
|
+
/** Agent-capabilities catalog — MCP tools the contract references. */
|
|
1080
|
+
agentCapabilities?: AgentCapabilitiesSpec;
|
|
1081
|
+
/**
|
|
1082
|
+
* Client-capabilities catalog — declares browser-capability gadget
|
|
1083
|
+
* hooks the UI calls. Pure declaration: no RPC, no input/output
|
|
1084
|
+
* schemas. The agent observes gadget values only when the UI threads
|
|
1085
|
+
* them into a `contextSpec` slot or an `actionSpec` payload. See
|
|
1086
|
+
* {@link ClientCapabilitiesSpec} + {@link GadgetHook}.
|
|
1087
|
+
*
|
|
1088
|
+
* Wire-side only. Package-keyed — values are {@link GadgetPackageUse}
|
|
1089
|
+
* (per-package export-use maps keyed by export name). The
|
|
1090
|
+
* post-resolution descriptor view lives on
|
|
1091
|
+
* `SessionStackEntry.gadgetDescriptors` as a sidecar.
|
|
1092
|
+
*/
|
|
1093
|
+
clientCapabilities?: ClientCapabilitiesSpec;
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Canonical error codes emitted on the reserved
|
|
1097
|
+
* `_ggui:contract-error` channel when a declared
|
|
1098
|
+
* `streamSpec[name].source.tool` (continuous feed),
|
|
1099
|
+
* `streamSpec[name].tool` (refresh-after-action hint, agent-less
|
|
1100
|
+
* deployments only), or a session-level boot failure happens. Emitted
|
|
1101
|
+
* as the body of a stream envelope.
|
|
1102
|
+
*
|
|
1103
|
+
* v1 codes emitted by `@ggui-ai/mcp-server`'s session-channel router:
|
|
1104
|
+
*
|
|
1105
|
+
* - `TOOL_NOT_FOUND` — declared tool not registered on the wired
|
|
1106
|
+
* action router. Author wiring bug.
|
|
1107
|
+
* - `TOOL_THREW` — the tool handler threw (sync or async rejection).
|
|
1108
|
+
* Handler failure captured verbatim in `message`; original stack (if
|
|
1109
|
+
* any) lives on `causedBy`.
|
|
1110
|
+
* - `TOOL_TIMEOUT` — invocation exceeded the router's configured
|
|
1111
|
+
* timeout (default 30s). Handler may still complete in the
|
|
1112
|
+
* background; caller must treat as failure either way.
|
|
1113
|
+
* - `SCHEMA_VIOLATION` — the tool returned a shape that violates the
|
|
1114
|
+
* declared `streamSpec[name].schema`. Router rejected
|
|
1115
|
+
* BEFORE emitting on the channel, so subscribers do NOT see the
|
|
1116
|
+
* malformed payload.
|
|
1117
|
+
*
|
|
1118
|
+
* Extensibility — typed as `'TOOL_NOT_FOUND' | 'TOOL_THREW' |
|
|
1119
|
+
* 'TOOL_TIMEOUT' | 'SCHEMA_VIOLATION' | 'SCHEMA_MISMATCH_ERROR' |
|
|
1120
|
+
* (string & {})` rather than a closed union. Consumers MUST handle
|
|
1121
|
+
* unknown codes gracefully — render as raw string, not switch-case
|
|
1122
|
+
* without default. Future failure modes that may populate this field
|
|
1123
|
+
* include `'SANITIZER_FAILED'` (the `causedBy` sanitizer itself
|
|
1124
|
+
* threw), `'MCP_TRANSPORT_ERROR'` (the MCP transport rejected the
|
|
1125
|
+
* tool invocation before the handler ran), `'RATE_LIMIT_EXCEEDED'`
|
|
1126
|
+
* (the tool was refused by an upstream rate limiter), and
|
|
1127
|
+
* `'BOOTSTRAP_FAILED'` (C8 — initial contract bootstrap failed on
|
|
1128
|
+
* attach). Adding such codes does NOT bump the protocol version,
|
|
1129
|
+
* because the type was extensible from day one.
|
|
1130
|
+
*
|
|
1131
|
+
* `'SCHEMA_MISMATCH_ERROR'` — F4 schema compat checker. Emitted when
|
|
1132
|
+
* `actionSpec[name].schema` and its declared `tool`'s inputSchema
|
|
1133
|
+
* disagree, or when a `streamSpec[channel].schema` and its declared
|
|
1134
|
+
* `tool`'s return schema disagree. Fires at push-time (before the
|
|
1135
|
+
* stack item commits) and at blueprint-registration time. See
|
|
1136
|
+
* {@link ActionEntry.schema} and {@link StreamChannelEntry.schema}
|
|
1137
|
+
* for the author invariant, and `@ggui-ai/protocol/validation/
|
|
1138
|
+
* schema-subset` for the subset algorithm that produces the named
|
|
1139
|
+
* failure. Provides a named, actionable signal before a malformed
|
|
1140
|
+
* envelope reaches the agentic loop — instead of a silent `TOOL_THREW`
|
|
1141
|
+
* at runtime.
|
|
1142
|
+
*
|
|
1143
|
+
* `'SESSION_NOT_FOUND'` + `'AUTH_REJECTED'` — fire on post-WS-open
|
|
1144
|
+
* boot failures where the live channel is already alive (so the envelope-
|
|
1145
|
+
* emittable invariant is satisfied). The renderer bundle surfaces
|
|
1146
|
+
* them BOTH on the live-channel `_ggui:contract-error` envelope (with
|
|
1147
|
+
* `sourceAction.type === 'bootstrap-load'`) AND as a
|
|
1148
|
+
* `postMessage({type:'ggui:bootstrap-failed', reason, message})` to
|
|
1149
|
+
* the embedding host — the former for in-session observability, the
|
|
1150
|
+
* latter for host-level UX response. Pre-WS bootstrap failures
|
|
1151
|
+
* (`BUNDLE_FETCH_FAILED`, `CSP_VIOLATION`, `BOOTSTRAP_META_MISSING`)
|
|
1152
|
+
* are postMessage-only: they can't reach the live channel because the WS
|
|
1153
|
+
* doesn't exist yet, so they remain OUT of `ContractErrorCode`'s
|
|
1154
|
+
* named set to preserve the "live-channel-emittable" invariant. The
|
|
1155
|
+
* renderer's `BootstrapFailureReason` union (in `@ggui-ai/iframe-runtime`)
|
|
1156
|
+
* carries ALL bootstrap codes — `ContractErrorCode` is the strict
|
|
1157
|
+
* subset that's observable on the contract-error envelope.
|
|
1158
|
+
*/
|
|
1159
|
+
export type ContractErrorCode = 'TOOL_NOT_FOUND' | 'TOOL_THREW' | 'TOOL_TIMEOUT' | 'SCHEMA_VIOLATION' | 'SCHEMA_MISMATCH_ERROR' | 'SESSION_NOT_FOUND' | 'AUTH_REJECTED'
|
|
1160
|
+
/**
|
|
1161
|
+
* `'INVALID_ACTION_KIND'` — emitted when the
|
|
1162
|
+
* `ggui_runtime_submit_action` handler receives an envelope whose `kind`
|
|
1163
|
+
* discriminator OR per-kind payload shape is malformed. Source of
|
|
1164
|
+
* truth for the envelope contract is `SubmitActionEnvelope` /
|
|
1165
|
+
* `GguiSubmitActionInput` in `@ggui-ai/protocol/integrations/mcp-apps`.
|
|
1166
|
+
* Fail-soft at the client: the primary host effect (the `ui/message`
|
|
1167
|
+
* / `ui/open-link` / 3-message-bridge call alongside the audit) MUST
|
|
1168
|
+
* still succeed; this code surfaces only on the server-side
|
|
1169
|
+
* `_ggui:contract-error` channel for operator observability.
|
|
1170
|
+
*/
|
|
1171
|
+
| 'INVALID_ACTION_KIND'
|
|
1172
|
+
/**
|
|
1173
|
+
* `'PIPE_NOT_FOUND'` — surfaced when `ggui_runtime_submit_action`
|
|
1174
|
+
* receives a `kind:"dispatch"` envelope referencing a `stackItemId`
|
|
1175
|
+
* whose pending-events pipe is closed/missing (popped, session
|
|
1176
|
+
* closed, or never opened). The handler returns `{ok:false, code:
|
|
1177
|
+
* 'PIPE_NOT_FOUND'}` in structuredContent; the iframe-runtime
|
|
1178
|
+
* inspects the response (via the host's postMessage relay) and
|
|
1179
|
+
* falls through to the `ui/message` chat-shortcut postMessage so
|
|
1180
|
+
* the gesture still reaches the agent (via the next chat turn)
|
|
1181
|
+
* instead of vanishing silently.
|
|
1182
|
+
*/
|
|
1183
|
+
| 'PIPE_NOT_FOUND'
|
|
1184
|
+
/**
|
|
1185
|
+
* `'CONTEXT_TOO_LARGE'` — emitted when `ggui_runtime_sync_context`
|
|
1186
|
+
* receives a snapshot that exceeds the contextSpec size limits:
|
|
1187
|
+
* per-slot value > {@link CONTEXT_SLOT_VALUE_MAX_BYTES} (16 KB),
|
|
1188
|
+
* total snapshot > {@link CONTEXT_SNAPSHOT_MAX_BYTES} (64 KB), or
|
|
1189
|
+
* slot count > {@link CONTEXT_SNAPSHOT_MAX_SLOTS} (50). Reject
|
|
1190
|
+
* instead of truncate so authors notice and route the data through
|
|
1191
|
+
* the right surface (propsSpec / streamSpec / a tool call).
|
|
1192
|
+
*/
|
|
1193
|
+
| 'CONTEXT_TOO_LARGE' | (string & {});
|
|
1194
|
+
/**
|
|
1195
|
+
* Maximum byte size (UTF-8) of a single contextSpec slot's value
|
|
1196
|
+
* accepted by `ggui_runtime_sync_context`. Values larger than this
|
|
1197
|
+
* reject with `CONTEXT_TOO_LARGE`. contextSpec is observable state for
|
|
1198
|
+
* the agent — content storage belongs on propsSpec / streamSpec / a
|
|
1199
|
+
* tool call.
|
|
1200
|
+
*/
|
|
1201
|
+
export declare const CONTEXT_SLOT_VALUE_MAX_BYTES: number;
|
|
1202
|
+
/**
|
|
1203
|
+
* Maximum byte size (UTF-8) of the full contextSpec snapshot (sum of
|
|
1204
|
+
* all slot values) accepted by `ggui_runtime_sync_context`. Snapshots
|
|
1205
|
+
* larger than this reject with `CONTEXT_TOO_LARGE`.
|
|
1206
|
+
*/
|
|
1207
|
+
export declare const CONTEXT_SNAPSHOT_MAX_BYTES: number;
|
|
1208
|
+
/**
|
|
1209
|
+
* Maximum number of slots in a contextSpec snapshot. Snapshots with
|
|
1210
|
+
* more slots reject with `CONTEXT_TOO_LARGE`.
|
|
1211
|
+
*/
|
|
1212
|
+
export declare const CONTEXT_SNAPSHOT_MAX_SLOTS = 50;
|
|
1213
|
+
/**
|
|
1214
|
+
* The body of a stream envelope the server emits on the reserved
|
|
1215
|
+
* `_ggui:contract-error` channel when a wired-action or refresh-stream
|
|
1216
|
+
* invocation fails. Carries enough shape to surface the failure in
|
|
1217
|
+
* SessionInspector activity panels AND to correlate back to the
|
|
1218
|
+
* originating dispatch.
|
|
1219
|
+
*
|
|
1220
|
+
* Design notes:
|
|
1221
|
+
*
|
|
1222
|
+
* - This is a PLATFORM-EMITTED envelope. Agents MUST NOT author
|
|
1223
|
+
* deliveries on `_ggui:contract-error` — the reserved-channel
|
|
1224
|
+
* validator rejects them.
|
|
1225
|
+
* - The payload is a leaf-level contract: it does NOT wrap a
|
|
1226
|
+
* semantic payload for the author to interpret. Consumers render
|
|
1227
|
+
* it as an error activity row, NOT as a declared channel's data.
|
|
1228
|
+
* - The shape intentionally omits retry / recovery metadata. Retries
|
|
1229
|
+
* are an explicit non-goal of the v1 contract.
|
|
1230
|
+
*/
|
|
1231
|
+
export interface ContractErrorPayload {
|
|
1232
|
+
/** The tool that failed — wired-action tool OR refresh-stream tool. */
|
|
1233
|
+
readonly toolName: string;
|
|
1234
|
+
/** The originating action name when the error came from a wired
|
|
1235
|
+
* action. Absent when the failure occurred on a refresh-stream path
|
|
1236
|
+
* that fired after a successful wired action. */
|
|
1237
|
+
readonly actionName?: string;
|
|
1238
|
+
/** Provenance on the router side — whether this error came from the
|
|
1239
|
+
* wired-action invocation (directly in response to a dispatch) or
|
|
1240
|
+
* from the refresh-stream tool that followed a successful action.
|
|
1241
|
+
*
|
|
1242
|
+
* v1 values emitted by `@ggui-ai/mcp-server`'s session-channel
|
|
1243
|
+
* router:
|
|
1244
|
+
*
|
|
1245
|
+
* - `'wired-action'` — failure surfaced on the wired-action dispatch
|
|
1246
|
+
* path (the originating tool threw, was not found, or timed out).
|
|
1247
|
+
* - `'refresh-stream'` — failure surfaced on the refresh tool that
|
|
1248
|
+
* fires after a successful wired action (declared via
|
|
1249
|
+
* {@link StreamChannelEntry.tool}).
|
|
1250
|
+
*
|
|
1251
|
+
* Extensibility — typed as `(string & {}) | 'wired-action' |
|
|
1252
|
+
* 'refresh-stream'` rather than a closed union. Consumers MUST handle
|
|
1253
|
+
* unknown values gracefully (render as the raw string, not a hard
|
|
1254
|
+
* switch-case that throws). Future router sources that may populate
|
|
1255
|
+
* this field include `'bootstrap-refresh'` (initial attach-time
|
|
1256
|
+
* refresh before the first wired action), `'scheduled-refresh'` (a
|
|
1257
|
+
* timer-driven refresh independent of any action), and
|
|
1258
|
+
* `'session-restore'` (a refresh fired after a session-resume
|
|
1259
|
+
* hydration). Adding such values does NOT bump the protocol version,
|
|
1260
|
+
* because the type was extensible from day one. */
|
|
1261
|
+
readonly sourceAction?: {
|
|
1262
|
+
readonly type: 'wired-action' | 'refresh-stream' | (string & {});
|
|
1263
|
+
/** ISO 8601 timestamp when the originating dispatch hit the router. */
|
|
1264
|
+
readonly dispatchedAt: string;
|
|
1265
|
+
};
|
|
1266
|
+
readonly error: {
|
|
1267
|
+
readonly code: ContractErrorCode;
|
|
1268
|
+
/** Short, author-readable failure summary. Safe to log/display. */
|
|
1269
|
+
readonly message: string;
|
|
1270
|
+
/** Optional stringified original error (typically `error.stack`) for
|
|
1271
|
+
* debugging. Producers MUST pipe the raw string through
|
|
1272
|
+
* {@link sanitizeCausedBy} (or an operator-supplied stricter
|
|
1273
|
+
* sanitizer) before populating this field — the envelope rides
|
|
1274
|
+
* `_ggui:contract-error` which is `replay: 'all'`, so anything
|
|
1275
|
+
* landed here persists in the session ring buffer and surfaces in
|
|
1276
|
+
* operator tools (SessionInspector). The default sanitizer redacts
|
|
1277
|
+
* Bearer tokens, query-param secrets, and common env-var dumps, and
|
|
1278
|
+
* truncates at 2KB. `@ggui-ai/mcp-server`'s session-channel router
|
|
1279
|
+
* applies it by default; alternative producers MUST match that
|
|
1280
|
+
* posture. */
|
|
1281
|
+
readonly causedBy?: string;
|
|
1282
|
+
};
|
|
1283
|
+
/** ISO 8601 timestamp of the error envelope itself. */
|
|
1284
|
+
readonly timestamp: string;
|
|
1285
|
+
/**
|
|
1286
|
+
* Protocol schema version stamped by the producer. Pre-launch:
|
|
1287
|
+
* advisory — consumers MUST NOT reject on mismatch. At launch
|
|
1288
|
+
* cutover, policy tightens so operators can surface an
|
|
1289
|
+
* UPGRADE_REQUIRED state when the received major diverges from the
|
|
1290
|
+
* client's known major.
|
|
1291
|
+
*
|
|
1292
|
+
* See `PROTOCOL_SCHEMA_VERSION` for the current value.
|
|
1293
|
+
*/
|
|
1294
|
+
readonly schemaVersion?: string;
|
|
1295
|
+
}
|
|
1296
|
+
//# sourceMappingURL=data-contract.d.ts.map
|