@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.
Files changed (222) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +46 -0
  3. package/dist/bridge/invoke-agent.d.ts +65 -0
  4. package/dist/bridge/invoke-agent.d.ts.map +1 -0
  5. package/dist/bridge/invoke-agent.js +113 -0
  6. package/dist/envelope-adapters.d.ts +24 -0
  7. package/dist/envelope-adapters.d.ts.map +1 -0
  8. package/dist/envelope-adapters.js +14 -0
  9. package/dist/envelopes/builders.d.ts +145 -0
  10. package/dist/envelopes/builders.d.ts.map +1 -0
  11. package/dist/envelopes/builders.js +113 -0
  12. package/dist/errors/unknown-permission-name.d.ts +12 -0
  13. package/dist/errors/unknown-permission-name.d.ts.map +1 -0
  14. package/dist/errors/unknown-permission-name.js +29 -0
  15. package/dist/errors/version-mismatch.d.ts +55 -0
  16. package/dist/errors/version-mismatch.d.ts.map +1 -0
  17. package/dist/errors/version-mismatch.js +52 -0
  18. package/dist/gadgets/resolve-contract-gadgets.d.ts +93 -0
  19. package/dist/gadgets/resolve-contract-gadgets.d.ts.map +1 -0
  20. package/dist/gadgets/resolve-contract-gadgets.js +119 -0
  21. package/dist/gadgets/stdlib-gadgets.d.ts +43 -0
  22. package/dist/gadgets/stdlib-gadgets.d.ts.map +1 -0
  23. package/dist/gadgets/stdlib-gadgets.js +161 -0
  24. package/dist/iframe-bridge.d.ts +63 -0
  25. package/dist/iframe-bridge.d.ts.map +1 -0
  26. package/dist/iframe-bridge.js +166 -0
  27. package/dist/index.d.ts +62 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +79 -0
  30. package/dist/integrations/mcp-apps.d.ts +1218 -0
  31. package/dist/integrations/mcp-apps.d.ts.map +1 -0
  32. package/dist/integrations/mcp-apps.js +427 -0
  33. package/dist/navigation/index.d.ts +3 -0
  34. package/dist/navigation/index.d.ts.map +1 -0
  35. package/dist/navigation/index.js +1 -0
  36. package/dist/navigation/stack-navigation.d.ts +55 -0
  37. package/dist/navigation/stack-navigation.d.ts.map +1 -0
  38. package/dist/navigation/stack-navigation.js +80 -0
  39. package/dist/recommended-prompts.d.ts +56 -0
  40. package/dist/recommended-prompts.d.ts.map +1 -0
  41. package/dist/recommended-prompts.js +55 -0
  42. package/dist/registry/blueprint-key.d.ts +9 -0
  43. package/dist/registry/blueprint-key.d.ts.map +1 -0
  44. package/dist/registry/blueprint-key.js +28 -0
  45. package/dist/registry/canonicalize-contract.d.ts +35 -0
  46. package/dist/registry/canonicalize-contract.d.ts.map +1 -0
  47. package/dist/registry/canonicalize-contract.js +166 -0
  48. package/dist/registry/summarize-contract.d.ts +46 -0
  49. package/dist/registry/summarize-contract.d.ts.map +1 -0
  50. package/dist/registry/summarize-contract.js +63 -0
  51. package/dist/schema-learning/derive-contract.d.ts +67 -0
  52. package/dist/schema-learning/derive-contract.d.ts.map +1 -0
  53. package/dist/schema-learning/derive-contract.js +117 -0
  54. package/dist/schema-learning/merge.d.ts +32 -0
  55. package/dist/schema-learning/merge.d.ts.map +1 -0
  56. package/dist/schema-learning/merge.js +146 -0
  57. package/dist/schemas/blueprint.d.ts +32 -0
  58. package/dist/schemas/blueprint.d.ts.map +1 -0
  59. package/dist/schemas/blueprint.js +92 -0
  60. package/dist/schemas/data-contract.d.ts +750 -0
  61. package/dist/schemas/data-contract.d.ts.map +1 -0
  62. package/dist/schemas/data-contract.js +663 -0
  63. package/dist/schemas/gadget-name-grammar.d.ts +29 -0
  64. package/dist/schemas/gadget-name-grammar.d.ts.map +1 -0
  65. package/dist/schemas/gadget-name-grammar.js +28 -0
  66. package/dist/schemas/handshake-suggestion.d.ts +46 -0
  67. package/dist/schemas/handshake-suggestion.d.ts.map +1 -0
  68. package/dist/schemas/handshake-suggestion.js +107 -0
  69. package/dist/schemas/invoke.d.ts +337 -0
  70. package/dist/schemas/invoke.d.ts.map +1 -0
  71. package/dist/schemas/invoke.js +169 -0
  72. package/dist/schemas/mcp.d.ts +301 -0
  73. package/dist/schemas/mcp.d.ts.map +1 -0
  74. package/dist/schemas/mcp.js +373 -0
  75. package/dist/schemas/ops-blueprint.d.ts +176 -0
  76. package/dist/schemas/ops-blueprint.d.ts.map +1 -0
  77. package/dist/schemas/ops-blueprint.js +259 -0
  78. package/dist/schemas/sync-check.d.ts +11 -0
  79. package/dist/schemas/sync-check.d.ts.map +1 -0
  80. package/dist/schemas/sync-check.js +60 -0
  81. package/dist/screen-blueprints/define.d.ts +22 -0
  82. package/dist/screen-blueprints/define.d.ts.map +1 -0
  83. package/dist/screen-blueprints/define.js +3 -0
  84. package/dist/screen-blueprints/index.d.ts +4 -0
  85. package/dist/screen-blueprints/index.d.ts.map +1 -0
  86. package/dist/screen-blueprints/index.js +3 -0
  87. package/dist/screen-blueprints/match.d.ts +35 -0
  88. package/dist/screen-blueprints/match.d.ts.map +1 -0
  89. package/dist/screen-blueprints/match.js +51 -0
  90. package/dist/screen-blueprints/types.d.ts +164 -0
  91. package/dist/screen-blueprints/types.d.ts.map +1 -0
  92. package/dist/screen-blueprints/types.js +1 -0
  93. package/dist/stream/stream-parser.d.ts +62 -0
  94. package/dist/stream/stream-parser.d.ts.map +1 -0
  95. package/dist/stream/stream-parser.js +199 -0
  96. package/dist/transport/websocket.d.ts +178 -0
  97. package/dist/transport/websocket.d.ts.map +1 -0
  98. package/dist/transport/websocket.js +1 -0
  99. package/dist/types/app-config.d.ts +61 -0
  100. package/dist/types/app-config.d.ts.map +1 -0
  101. package/dist/types/app-config.js +1 -0
  102. package/dist/types/auth.d.ts +61 -0
  103. package/dist/types/auth.d.ts.map +1 -0
  104. package/dist/types/auth.js +1 -0
  105. package/dist/types/blueprint.d.ts +206 -0
  106. package/dist/types/blueprint.d.ts.map +1 -0
  107. package/dist/types/blueprint.js +1 -0
  108. package/dist/types/canvas-lifecycle.d.ts +105 -0
  109. package/dist/types/canvas-lifecycle.d.ts.map +1 -0
  110. package/dist/types/canvas-lifecycle.js +38 -0
  111. package/dist/types/capabilities.d.ts +40 -0
  112. package/dist/types/capabilities.d.ts.map +1 -0
  113. package/dist/types/capabilities.js +19 -0
  114. package/dist/types/contract-inference.d.ts +401 -0
  115. package/dist/types/contract-inference.d.ts.map +1 -0
  116. package/dist/types/contract-inference.js +44 -0
  117. package/dist/types/credential.d.ts +41 -0
  118. package/dist/types/credential.d.ts.map +1 -0
  119. package/dist/types/credential.js +32 -0
  120. package/dist/types/data-bindings.d.ts +322 -0
  121. package/dist/types/data-bindings.d.ts.map +1 -0
  122. package/dist/types/data-bindings.js +29 -0
  123. package/dist/types/data-contract.d.ts +1296 -0
  124. package/dist/types/data-contract.d.ts.map +1 -0
  125. package/dist/types/data-contract.js +111 -0
  126. package/dist/types/events.d.ts +182 -0
  127. package/dist/types/events.d.ts.map +1 -0
  128. package/dist/types/events.js +8 -0
  129. package/dist/types/feedback.d.ts +24 -0
  130. package/dist/types/feedback.d.ts.map +1 -0
  131. package/dist/types/feedback.js +7 -0
  132. package/dist/types/gadget.d.ts +121 -0
  133. package/dist/types/gadget.d.ts.map +1 -0
  134. package/dist/types/gadget.js +24 -0
  135. package/dist/types/handshake-suggestion.d.ts +264 -0
  136. package/dist/types/handshake-suggestion.d.ts.map +1 -0
  137. package/dist/types/handshake-suggestion.js +70 -0
  138. package/dist/types/host-context.d.ts +163 -0
  139. package/dist/types/host-context.d.ts.map +1 -0
  140. package/dist/types/host-context.js +142 -0
  141. package/dist/types/interface-context.d.ts +105 -0
  142. package/dist/types/interface-context.d.ts.map +1 -0
  143. package/dist/types/interface-context.js +115 -0
  144. package/dist/types/invoke.d.ts +28 -0
  145. package/dist/types/invoke.d.ts.map +1 -0
  146. package/dist/types/invoke.js +7 -0
  147. package/dist/types/live-channel.d.ts +613 -0
  148. package/dist/types/live-channel.d.ts.map +1 -0
  149. package/dist/types/live-channel.js +1 -0
  150. package/dist/types/llm.d.ts +61 -0
  151. package/dist/types/llm.d.ts.map +1 -0
  152. package/dist/types/llm.js +186 -0
  153. package/dist/types/mcp-proxy.d.ts +67 -0
  154. package/dist/types/mcp-proxy.d.ts.map +1 -0
  155. package/dist/types/mcp-proxy.js +46 -0
  156. package/dist/types/mcp.d.ts +637 -0
  157. package/dist/types/mcp.d.ts.map +1 -0
  158. package/dist/types/mcp.js +30 -0
  159. package/dist/types/openrouter-models.d.ts +22 -0
  160. package/dist/types/openrouter-models.d.ts.map +1 -0
  161. package/dist/types/openrouter-models.js +4843 -0
  162. package/dist/types/region.d.ts +26 -0
  163. package/dist/types/region.d.ts.map +1 -0
  164. package/dist/types/region.js +36 -0
  165. package/dist/types/session.d.ts +419 -0
  166. package/dist/types/session.d.ts.map +1 -0
  167. package/dist/types/session.js +1 -0
  168. package/dist/types/thread.d.ts +207 -0
  169. package/dist/types/thread.d.ts.map +1 -0
  170. package/dist/types/thread.js +57 -0
  171. package/dist/types/ui-generator.d.ts +100 -0
  172. package/dist/types/ui-generator.d.ts.map +1 -0
  173. package/dist/types/ui-generator.js +53 -0
  174. package/dist/validation/ajv-runtime.d.ts +140 -0
  175. package/dist/validation/ajv-runtime.d.ts.map +1 -0
  176. package/dist/validation/ajv-runtime.js +452 -0
  177. package/dist/validation/content-hash.d.ts +3 -0
  178. package/dist/validation/content-hash.d.ts.map +1 -0
  179. package/dist/validation/content-hash.js +21 -0
  180. package/dist/validation/contract-validator.d.ts +244 -0
  181. package/dist/validation/contract-validator.d.ts.map +1 -0
  182. package/dist/validation/contract-validator.js +711 -0
  183. package/dist/validation/cross-references.d.ts +105 -0
  184. package/dist/validation/cross-references.d.ts.map +1 -0
  185. package/dist/validation/cross-references.js +164 -0
  186. package/dist/validation/hygiene-rules.d.ts +250 -0
  187. package/dist/validation/hygiene-rules.d.ts.map +1 -0
  188. package/dist/validation/hygiene-rules.js +564 -0
  189. package/dist/validation/lint-contract.d.ts +130 -0
  190. package/dist/validation/lint-contract.d.ts.map +1 -0
  191. package/dist/validation/lint-contract.js +225 -0
  192. package/dist/validation/name-invariants.d.ts +117 -0
  193. package/dist/validation/name-invariants.d.ts.map +1 -0
  194. package/dist/validation/name-invariants.js +172 -0
  195. package/dist/validation/reserved-channels.d.ts +156 -0
  196. package/dist/validation/reserved-channels.d.ts.map +1 -0
  197. package/dist/validation/reserved-channels.js +356 -0
  198. package/dist/validation/resolve-stream-channel.d.ts +78 -0
  199. package/dist/validation/resolve-stream-channel.d.ts.map +1 -0
  200. package/dist/validation/resolve-stream-channel.js +64 -0
  201. package/dist/validation/sanitize-error.d.ts +46 -0
  202. package/dist/validation/sanitize-error.d.ts.map +1 -0
  203. package/dist/validation/sanitize-error.js +88 -0
  204. package/dist/validation/schema-compat-invariants.d.ts +140 -0
  205. package/dist/validation/schema-compat-invariants.d.ts.map +1 -0
  206. package/dist/validation/schema-compat-invariants.js +220 -0
  207. package/dist/validation/schema-meta-validation.d.ts +60 -0
  208. package/dist/validation/schema-meta-validation.d.ts.map +1 -0
  209. package/dist/validation/schema-meta-validation.js +131 -0
  210. package/dist/validation/schema-subset.d.ts +165 -0
  211. package/dist/validation/schema-subset.d.ts.map +1 -0
  212. package/dist/validation/schema-subset.js +295 -0
  213. package/dist/validation/ui-security.d.ts +54 -0
  214. package/dist/validation/ui-security.d.ts.map +1 -0
  215. package/dist/validation/ui-security.js +138 -0
  216. package/dist/validation/zod-to-json-schema.d.ts +63 -0
  217. package/dist/validation/zod-to-json-schema.d.ts.map +1 -0
  218. package/dist/validation/zod-to-json-schema.js +126 -0
  219. package/dist/version.d.ts +1458 -0
  220. package/dist/version.d.ts.map +1 -0
  221. package/dist/version.js +1459 -0
  222. 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