@ggui-ai/protocol 0.2.0-alpha.3 → 0.3.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/README.md +16 -16
  2. package/dist/envelope-adapters.d.ts +6 -5
  3. package/dist/envelope-adapters.d.ts.map +1 -1
  4. package/dist/envelope-adapters.js +3 -3
  5. package/dist/envelopes/builders.d.ts +6 -32
  6. package/dist/envelopes/builders.d.ts.map +1 -1
  7. package/dist/envelopes/builders.js +3 -25
  8. package/dist/errors/version-mismatch.d.ts +1 -1
  9. package/dist/errors/version-mismatch.js +1 -1
  10. package/dist/gadgets/resolve-app-gadgets.d.ts +10 -0
  11. package/dist/gadgets/resolve-app-gadgets.d.ts.map +1 -0
  12. package/dist/gadgets/resolve-app-gadgets.js +19 -0
  13. package/dist/gadgets/resolve-contract-gadgets.d.ts +6 -6
  14. package/dist/gadgets/resolve-contract-gadgets.js +5 -5
  15. package/dist/gadgets/stdlib-gadgets.d.ts +1 -1
  16. package/dist/gadgets/stdlib-gadgets.d.ts.map +1 -1
  17. package/dist/gadgets/stdlib-gadgets.js +43 -22
  18. package/dist/iframe-bridge.d.ts +4 -43
  19. package/dist/iframe-bridge.d.ts.map +1 -1
  20. package/dist/iframe-bridge.js +4 -141
  21. package/dist/index.d.ts +60 -62
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +66 -61
  24. package/dist/integrations/mcp-apps.d.ts +83 -38
  25. package/dist/integrations/mcp-apps.d.ts.map +1 -1
  26. package/dist/integrations/mcp-apps.js +98 -52
  27. package/dist/recommended-prompts.d.ts +1 -1
  28. package/dist/recommended-prompts.js +1 -1
  29. package/dist/registry/blueprint-key.d.ts +3 -0
  30. package/dist/registry/blueprint-key.d.ts.map +1 -1
  31. package/dist/registry/blueprint-key.js +9 -0
  32. package/dist/registry/blueprint-stamp.d.ts +12 -0
  33. package/dist/registry/blueprint-stamp.d.ts.map +1 -0
  34. package/dist/registry/blueprint-stamp.js +12 -0
  35. package/dist/registry/canonicalize-contract.d.ts +31 -2
  36. package/dist/registry/canonicalize-contract.d.ts.map +1 -1
  37. package/dist/registry/canonicalize-contract.js +125 -13
  38. package/dist/registry/portable-blueprint.d.ts +64 -0
  39. package/dist/registry/portable-blueprint.d.ts.map +1 -0
  40. package/dist/registry/portable-blueprint.js +103 -0
  41. package/dist/registry/summarize-contract.d.ts +7 -2
  42. package/dist/registry/summarize-contract.d.ts.map +1 -1
  43. package/dist/registry/summarize-contract.js +12 -3
  44. package/dist/registry/variant-key.d.ts +17 -0
  45. package/dist/registry/variant-key.d.ts.map +1 -0
  46. package/dist/registry/variant-key.js +22 -0
  47. package/dist/schema-learning/derive-contract.d.ts +2 -2
  48. package/dist/schema-learning/derive-contract.js +2 -2
  49. package/dist/schema-learning/merge.d.ts.map +1 -1
  50. package/dist/schema-learning/merge.js +3 -2
  51. package/dist/schemas/app-theme.d.ts +38 -0
  52. package/dist/schemas/app-theme.d.ts.map +1 -0
  53. package/dist/schemas/app-theme.js +43 -0
  54. package/dist/schemas/blueprint.d.ts +30 -11
  55. package/dist/schemas/blueprint.d.ts.map +1 -1
  56. package/dist/schemas/blueprint.js +62 -26
  57. package/dist/schemas/data-contract.d.ts +28 -30
  58. package/dist/schemas/data-contract.d.ts.map +1 -1
  59. package/dist/schemas/data-contract.js +26 -26
  60. package/dist/schemas/handshake-suggestion.d.ts +2 -4
  61. package/dist/schemas/handshake-suggestion.d.ts.map +1 -1
  62. package/dist/schemas/handshake-suggestion.js +5 -14
  63. package/dist/schemas/mcp.d.ts +240 -58
  64. package/dist/schemas/mcp.d.ts.map +1 -1
  65. package/dist/schemas/mcp.js +285 -93
  66. package/dist/schemas/ops-blueprint.d.ts +12 -12
  67. package/dist/schemas/ops-blueprint.d.ts.map +1 -1
  68. package/dist/schemas/ops-blueprint.js +14 -24
  69. package/dist/screen-blueprints/define.d.ts +2 -2
  70. package/dist/screen-blueprints/match.d.ts +12 -7
  71. package/dist/screen-blueprints/match.d.ts.map +1 -1
  72. package/dist/screen-blueprints/match.js +7 -5
  73. package/dist/screen-blueprints/types.d.ts +14 -18
  74. package/dist/screen-blueprints/types.d.ts.map +1 -1
  75. package/dist/transport/websocket.d.ts +5 -26
  76. package/dist/transport/websocket.d.ts.map +1 -1
  77. package/dist/types/app-config.d.ts +0 -1
  78. package/dist/types/app-config.d.ts.map +1 -1
  79. package/dist/types/auth.d.ts +1 -46
  80. package/dist/types/auth.d.ts.map +1 -1
  81. package/dist/types/blueprint-source.d.ts +123 -0
  82. package/dist/types/blueprint-source.d.ts.map +1 -0
  83. package/dist/types/blueprint-source.js +126 -0
  84. package/dist/types/blueprint.d.ts +25 -18
  85. package/dist/types/blueprint.d.ts.map +1 -1
  86. package/dist/types/contract-inference.d.ts +2 -43
  87. package/dist/types/contract-inference.d.ts.map +1 -1
  88. package/dist/types/data-contract.d.ts +59 -344
  89. package/dist/types/data-contract.d.ts.map +1 -1
  90. package/dist/types/data-contract.js +5 -12
  91. package/dist/types/events.d.ts +31 -69
  92. package/dist/types/events.d.ts.map +1 -1
  93. package/dist/types/{render-event.d.ts → ggui-session-event.d.ts} +15 -15
  94. package/dist/types/ggui-session-event.d.ts.map +1 -0
  95. package/dist/types/{render-event.js → ggui-session-event.js} +5 -5
  96. package/dist/types/handshake-suggestion.d.ts +60 -40
  97. package/dist/types/handshake-suggestion.d.ts.map +1 -1
  98. package/dist/types/host-context.d.ts +8 -8
  99. package/dist/types/host-context.d.ts.map +1 -1
  100. package/dist/types/host-context.js +5 -5
  101. package/dist/types/invoke.d.ts +1 -13
  102. package/dist/types/invoke.d.ts.map +1 -1
  103. package/dist/types/{canvas-lifecycle.d.ts → lifecycle.d.ts} +35 -37
  104. package/dist/types/lifecycle.d.ts.map +1 -0
  105. package/dist/types/{canvas-lifecycle.js → lifecycle.js} +12 -14
  106. package/dist/types/live-channel.d.ts +48 -104
  107. package/dist/types/live-channel.d.ts.map +1 -1
  108. package/dist/types/llm.d.ts +13 -24
  109. package/dist/types/llm.d.ts.map +1 -1
  110. package/dist/types/llm.js +23 -53
  111. package/dist/types/mcp.d.ts +55 -176
  112. package/dist/types/mcp.d.ts.map +1 -1
  113. package/dist/types/mcp.js +2 -2
  114. package/dist/types/oauth-user-id.d.ts +12 -0
  115. package/dist/types/oauth-user-id.d.ts.map +1 -0
  116. package/dist/types/oauth-user-id.js +10 -0
  117. package/dist/types/portable-blueprint.d.ts +53 -0
  118. package/dist/types/portable-blueprint.d.ts.map +1 -0
  119. package/dist/types/portable-blueprint.js +8 -0
  120. package/dist/types/{session.d.ts → render.d.ts} +51 -53
  121. package/dist/types/render.d.ts.map +1 -0
  122. package/dist/types/thread.d.ts.map +1 -1
  123. package/dist/types/thread.js +3 -3
  124. package/dist/types/ui-generator.d.ts +5 -46
  125. package/dist/types/ui-generator.d.ts.map +1 -1
  126. package/dist/types/ui-generator.js +1 -53
  127. package/dist/validation/ajv-runtime.d.ts +3 -3
  128. package/dist/validation/ajv-runtime.d.ts.map +1 -1
  129. package/dist/validation/ajv-runtime.js +6 -5
  130. package/dist/validation/contract-validator.d.ts +23 -22
  131. package/dist/validation/contract-validator.d.ts.map +1 -1
  132. package/dist/validation/contract-validator.js +28 -26
  133. package/dist/validation/cross-references.d.ts +3 -3
  134. package/dist/validation/cross-references.js +3 -3
  135. package/dist/validation/hygiene-rules.d.ts +13 -10
  136. package/dist/validation/hygiene-rules.d.ts.map +1 -1
  137. package/dist/validation/hygiene-rules.js +20 -14
  138. package/dist/validation/is-record.d.ts +17 -0
  139. package/dist/validation/is-record.d.ts.map +1 -0
  140. package/dist/validation/is-record.js +18 -0
  141. package/dist/validation/lint-contract.d.ts +9 -8
  142. package/dist/validation/lint-contract.d.ts.map +1 -1
  143. package/dist/validation/lint-contract.js +89 -26
  144. package/dist/validation/name-invariants.d.ts +4 -4
  145. package/dist/validation/name-invariants.js +4 -4
  146. package/dist/validation/reserved-channels.d.ts +43 -46
  147. package/dist/validation/reserved-channels.d.ts.map +1 -1
  148. package/dist/validation/reserved-channels.js +14 -177
  149. package/dist/validation/resolve-stream-channel.d.ts +3 -9
  150. package/dist/validation/resolve-stream-channel.d.ts.map +1 -1
  151. package/dist/validation/resolve-stream-channel.js +3 -4
  152. package/dist/validation/sanitize-error.d.ts +10 -9
  153. package/dist/validation/sanitize-error.d.ts.map +1 -1
  154. package/dist/validation/sanitize-error.js +19 -18
  155. package/dist/validation/schema-compat-invariants.d.ts +1 -1
  156. package/dist/validation/schema-compat-invariants.js +3 -3
  157. package/dist/validation/schema-meta-validation.d.ts +21 -8
  158. package/dist/validation/schema-meta-validation.d.ts.map +1 -1
  159. package/dist/validation/schema-meta-validation.js +28 -14
  160. package/dist/validation/schema-subset.d.ts +9 -8
  161. package/dist/validation/schema-subset.d.ts.map +1 -1
  162. package/dist/validation/ui-security.d.ts +0 -17
  163. package/dist/validation/ui-security.d.ts.map +1 -1
  164. package/dist/validation/ui-security.js +17 -22
  165. package/dist/validation/zod-to-json-schema.d.ts +1 -1
  166. package/dist/validation/zod-to-json-schema.d.ts.map +1 -1
  167. package/dist/validation/zod-to-json-schema.js +4 -3
  168. package/dist/version.d.ts +783 -9
  169. package/dist/version.d.ts.map +1 -1
  170. package/dist/version.js +782 -8
  171. package/package.json +2 -2
  172. package/dist/bridge/invoke-agent.d.ts +0 -65
  173. package/dist/bridge/invoke-agent.d.ts.map +0 -1
  174. package/dist/bridge/invoke-agent.js +0 -113
  175. package/dist/stream/stream-parser.d.ts +0 -62
  176. package/dist/stream/stream-parser.d.ts.map +0 -1
  177. package/dist/stream/stream-parser.js +0 -199
  178. package/dist/types/canvas-lifecycle.d.ts.map +0 -1
  179. package/dist/types/credential.d.ts +0 -41
  180. package/dist/types/credential.d.ts.map +0 -1
  181. package/dist/types/credential.js +0 -32
  182. package/dist/types/data-bindings.d.ts +0 -322
  183. package/dist/types/data-bindings.d.ts.map +0 -1
  184. package/dist/types/data-bindings.js +0 -29
  185. package/dist/types/feedback.d.ts +0 -22
  186. package/dist/types/feedback.d.ts.map +0 -1
  187. package/dist/types/feedback.js +0 -7
  188. package/dist/types/mcp-proxy.d.ts +0 -67
  189. package/dist/types/mcp-proxy.d.ts.map +0 -1
  190. package/dist/types/mcp-proxy.js +0 -46
  191. package/dist/types/openrouter-models.d.ts +0 -23
  192. package/dist/types/openrouter-models.d.ts.map +0 -1
  193. package/dist/types/openrouter-models.js +0 -4843
  194. package/dist/types/region.d.ts +0 -26
  195. package/dist/types/region.d.ts.map +0 -1
  196. package/dist/types/region.js +0 -36
  197. package/dist/types/render-event.d.ts.map +0 -1
  198. package/dist/types/session.d.ts.map +0 -1
  199. /package/dist/types/{session.js → render.js} +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ggui-ai/protocol
2
2
 
3
- TypeScript source of truth for the ggui protocol — the open wire format between agents and generated user interfaces. Ships the envelope types (`ActionEnvelope`, `StreamEnvelope`, `ContractErrorPayload`), the canonical error-code union, the WebSocket + MCP transport bindings, and the DTCG design-token contract.
3
+ TypeScript source of truth for the ggui protocol — the open wire format between agents and generated user interfaces. Ships the envelope types (`ActionEnvelope`, `StreamEnvelope`), the canonical error-frame codes, the WebSocket + MCP transport bindings, and the DTCG design-token contract.
4
4
 
5
5
  The full normative spec lives at [docs.ggui.ai](https://docs.ggui.ai). This package is what an implementer actually imports.
6
6
 
@@ -17,13 +17,13 @@ Here is what happens when a user clicks "Add" on a generated todo UI:
17
17
  1. **LLM wrote the hook** — `const addTodo = useAction('addTodo');` bound to the button's `onClick`.
18
18
  2. **User clicks** — React fires `onClick`, which calls `addTodo(data)`.
19
19
  3. **Hook dispatches** — `useAction` (from `@ggui-ai/wire`) sends an `ActionEnvelope` on the live channel.
20
- 4. **WS transport** — the server receives the envelope on the render's live-channel WebSocket.
21
- 5. **Router looks up the tool** — `wiredActionRouter` reads `actionSpec.addTodo.nextStep === 'todo.add'`.
22
- 6. **MCP tool invoked** — the router calls `todo.add` with the validated payload.
23
- 7. **Tool responds** — `todo.add` returns; the response travels back as a `StreamEnvelope` on the live channel.
24
- 8. **UI absorbs the update** — the component's `useStream` callback fires, state updates, no regeneration.
20
+ 4. **WS transport** — the server receives the envelope on the GguiSession's live-channel WebSocket.
21
+ 5. **Server persists a consume event** — the validated envelope is appended to the session's event ledger, stamped with an advisory `tool` hint derived server-side from `actionSpec.addTodo.nextStep === 'todo.add'`.
22
+ 6. **Agent consumes** — the agent drains the event via `ggui_consume` on its next turn and calls `todo.add` itself. Actions drive agent turns; no client-side tool dispatch.
23
+ 7. **Agent pushes the update** — the agent's update travels back to the UI on the live channel (`props_update`, or a `StreamEnvelope` on a declared stream channel).
24
+ 8. **UI absorbs the update** — props or the component's `useStream` callback update state, no regeneration.
25
25
 
26
- **No SDK glue.** Every step has a named, typed enforcement layer — schema-subset check at push time, `ContractErrorPayload` on `_ggui:contract-error` at runtime, `@ggui-ai/protocol-conformance` at CI time, TypeScript narrowing at author time. Nothing about this pipeline assumes a specific SDK: a third-party implementer honoring the envelope + channel contracts inherits all four enforcement tiers for free.
26
+ **No SDK glue.** Every step has a named, typed enforcement layer — schema-subset check at push time, `CONTRACT_VIOLATION` error frames on the live channel at runtime, `@ggui-ai/protocol-conformance` at CI time, TypeScript narrowing at author time. Nothing about this pipeline assumes a specific SDK: a third-party implementer honoring the envelope + channel contracts inherits all four enforcement tiers for free.
27
27
 
28
28
  ## Implementer guide
29
29
 
@@ -31,15 +31,15 @@ Building a third-party MCP host that renders ggui UIs, a non-React viewer, or an
31
31
 
32
32
  ## What this package exports
33
33
 
34
- | Surface | What it is |
35
- | ------------------------------------------- | ---------------------------------------------------------------- |
36
- | `@ggui-ai/protocol` | Root barrel — envelope types, `Render`, `StreamSpec`, actions |
37
- | `@ggui-ai/protocol/content-hash` | Deterministic hashing for cache keys |
38
- | `@ggui-ai/protocol/blueprint-key` | Server-only blueprint cache-key derivation (uses `node:crypto`) |
39
- | `@ggui-ai/protocol/transport/websocket` | Live-channel WS binding — subscribe / ack / resume types |
40
- | `@ggui-ai/protocol/integrations/mcp-apps` | MCP Apps host integration types — bootstrap + lifecycle protocol |
41
- | `@ggui-ai/protocol/version` | Protocol version constant + negotiation helpers |
42
- | `@ggui-ai/protocol/errors/version-mismatch` | Typed error for version-negotiation failures |
34
+ | Surface | What it is |
35
+ | ------------------------------------------- | ------------------------------------------------------------------ |
36
+ | `@ggui-ai/protocol` | Root barrel — envelope types, `GguiSession`, `StreamSpec`, actions |
37
+ | `@ggui-ai/protocol/content-hash` | Deterministic hashing for cache keys |
38
+ | `@ggui-ai/protocol/blueprint-key` | Server-only blueprint cache-key derivation (uses `node:crypto`) |
39
+ | `@ggui-ai/protocol/transport/websocket` | Live-channel WS binding — subscribe / ack / resume types |
40
+ | `@ggui-ai/protocol/integrations/mcp-apps` | MCP Apps host integration types — bootstrap + lifecycle protocol |
41
+ | `@ggui-ai/protocol/version` | Protocol version constant + negotiation helpers |
42
+ | `@ggui-ai/protocol/errors/version-mismatch` | Typed error for version-negotiation failures |
43
43
 
44
44
  ## License
45
45
 
@@ -7,15 +7,16 @@
7
7
  *
8
8
  * The only bounded adapter that lives here now is
9
9
  * {@link parsePendingEnvelope} — a shape-neutral reader for stored
10
- * `PendingEvent.envelope` values that may arrive as raw objects (direct
11
- * DDB writes) or as JSON strings (AppSync `a.json()` semantics).
10
+ * `PendingEvent.envelope` values that may arrive as raw objects or as
11
+ * JSON strings, depending on how the deployment's storage layer
12
+ * serializes rows.
12
13
  */
13
14
  import type { ConsumeEventEntry } from './types/mcp';
14
15
  /**
15
16
  * Parse a {@link PendingEvent.envelope} that may arrive as either a raw
16
- * object (direct DDB writes) or a JSON-stringified object (AppSync
17
- * `a.json()` semantics). Returns the parsed entry unchanged when
18
- * already an object.
17
+ * object or a JSON-stringified object, depending on how the
18
+ * deployment's storage layer serializes rows. Returns the parsed entry
19
+ * unchanged when already an object.
19
20
  *
20
21
  * Throws `SyntaxError` when a string input is malformed JSON. Does NOT
21
22
  * validate the entry shape — that's the caller's job.
@@ -1 +1 @@
1
- {"version":3,"file":"envelope-adapters.d.ts","sourceRoot":"","sources":["../src/envelope-adapters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,iBAAiB,GAAG,MAAM,GACjC,iBAAiB,CAGnB"}
1
+ {"version":3,"file":"envelope-adapters.d.ts","sourceRoot":"","sources":["../src/envelope-adapters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,iBAAiB,GAAG,MAAM,GACjC,iBAAiB,CAGnB"}
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Parse a {@link PendingEvent.envelope} that may arrive as either a raw
3
- * object (direct DDB writes) or a JSON-stringified object (AppSync
4
- * `a.json()` semantics). Returns the parsed entry unchanged when
5
- * already an object.
3
+ * object or a JSON-stringified object, depending on how the
4
+ * deployment's storage layer serializes rows. Returns the parsed entry
5
+ * unchanged when already an object.
6
6
  *
7
7
  * Throws `SyntaxError` when a string input is malformed JSON. Does NOT
8
8
  * validate the entry shape — that's the caller's job.
@@ -4,8 +4,8 @@
4
4
  *
5
5
  * **Why centralize.** The `schemaVersion` forward-compat stamp is
6
6
  * emitted from many producer sites (wire helper, React-SDK emit
7
- * paths, OSS in-memory stream buffer, session-channel contract-error
8
- * router, hosted server paths). Spreading stamp logic across N sites
7
+ * paths, OSS in-memory stream buffer, hosted server paths).
8
+ * Spreading stamp logic across N sites
9
9
  * causes drift — producers silently skip the stamp. These builders
10
10
  * remove the drift surface by giving every producer a single function
11
11
  * to call; the default stamp happens inside the builder.
@@ -46,10 +46,10 @@
46
46
  */
47
47
  import type { ActionEnvelope, EventType } from '../types/events.js';
48
48
  import type { ErrorPayload, StreamEnvelope } from '../types/live-channel.js';
49
- import type { ContractErrorCode, ContractErrorPayload, JsonValue, StreamChannelMode } from '../types/data-contract.js';
49
+ import type { JsonValue, StreamChannelMode } from '../types/data-contract.js';
50
50
  /** Input type for {@link makeActionEnvelope}. */
51
51
  export interface MakeActionEnvelopeInput<TPayload = JsonValue> {
52
- readonly renderId: string;
52
+ readonly sessionId: string;
53
53
  readonly type: EventType;
54
54
  readonly payload?: TPayload;
55
55
  readonly clientSeq?: number;
@@ -63,7 +63,7 @@ export interface MakeActionEnvelopeInput<TPayload = JsonValue> {
63
63
  }
64
64
  /** Input type for {@link makeStreamEnvelope}. */
65
65
  export interface MakeStreamEnvelopeInput {
66
- readonly renderId: string;
66
+ readonly sessionId: string;
67
67
  readonly channel: string;
68
68
  readonly mode: StreamChannelMode;
69
69
  readonly payload: JsonValue;
@@ -78,23 +78,6 @@ export interface MakeErrorPayloadInput {
78
78
  readonly message: string;
79
79
  readonly details?: JsonValue;
80
80
  }
81
- /** Input type for {@link makeContractErrorPayload}. */
82
- export interface MakeContractErrorPayloadInput {
83
- readonly toolName: string;
84
- readonly actionName?: string;
85
- readonly sourceAction?: {
86
- readonly type: 'wired-action' | 'refresh-stream' | (string & {});
87
- readonly dispatchedAt: string;
88
- };
89
- readonly error: {
90
- readonly code: ContractErrorCode;
91
- readonly message: string;
92
- readonly causedBy?: string;
93
- };
94
- readonly timestamp: string;
95
- /** See {@link MakeActionEnvelopeInput.schemaVersion}. */
96
- readonly schemaVersion?: string;
97
- }
98
81
  /**
99
82
  * Build an {@link ActionEnvelope} with `schemaVersion` stamped to
100
83
  * {@link PROTOCOL_SCHEMA_VERSION} unless the caller overrides.
@@ -119,7 +102,7 @@ export declare function makeStreamEnvelope(parts: MakeStreamEnvelopeInput): Stre
119
102
  * Does NOT stamp `schemaVersion` — `ErrorPayload` is the wire-level
120
103
  * error envelope (free-form `code: string`), not an envelope that
121
104
  * opts into the forward-compat stamp (see {@link ActionEnvelope} /
122
- * {@link StreamEnvelope} / {@link ContractErrorPayload}). Keeping
105
+ * {@link StreamEnvelope}). Keeping
123
106
  * `ErrorPayload` stamp-free preserves byte-equivalence with every
124
107
  * existing server-side error emission that pre-dates the central
125
108
  * builders.
@@ -131,13 +114,4 @@ export declare function makeStreamEnvelope(parts: MakeStreamEnvelopeInput): Stre
131
114
  * pre-builder `{code, message}` shape byte-for-byte.
132
115
  */
133
116
  export declare function makeErrorPayload(parts: MakeErrorPayloadInput): ErrorPayload;
134
- /**
135
- * Build a {@link ContractErrorPayload} with `schemaVersion` stamped
136
- * to {@link PROTOCOL_SCHEMA_VERSION} unless the caller overrides.
137
- *
138
- * Filters `undefined` optional fields so the emitted payload keeps
139
- * byte-equivalence with the pre-refactor session-channel router
140
- * code.
141
- */
142
- export declare function makeContractErrorPayload(parts: MakeContractErrorPayloadInput): ContractErrorPayload;
143
117
  //# sourceMappingURL=builders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../src/envelopes/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,KAAK,EACV,iBAAiB,EACjB,oBAAoB,EACpB,SAAS,EACT,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAGnC,iDAAiD;AACjD,MAAM,WAAW,uBAAuB,CAAC,QAAQ,GAAG,SAAS;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,iDAAiD;AACjD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,yDAAyD;IACzD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;CAC9B;AAED,uDAAuD;AACvD,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE;QACtB,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,gBAAgB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;QACjE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;KAC/B,CAAC;IACF,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;QACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,yDAAyD;IACzD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAmBD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,GAAG,SAAS,EACrD,KAAK,EAAE,uBAAuB,CAAC,QAAQ,CAAC,GACvC,cAAc,CAAC,QAAQ,CAAC,CAU1B;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,uBAAuB,GAC7B,cAAc,CAYhB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,YAAY,CAO3E;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,6BAA6B,GACnC,oBAAoB,CAatB"}
1
+ {"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../src/envelopes/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAG9E,iDAAiD;AACjD,MAAM,WAAW,uBAAuB,CAAC,QAAQ,GAAG,SAAS;IAC3D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,iDAAiD;AACjD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,yDAAyD;IACzD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;CAC9B;AAmBD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,GAAG,SAAS,EACrD,KAAK,EAAE,uBAAuB,CAAC,QAAQ,CAAC,GACvC,cAAc,CAAC,QAAQ,CAAC,CAU1B;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,uBAAuB,GAC7B,cAAc,CAYhB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,YAAY,CAO3E"}
@@ -23,7 +23,7 @@ function resolveSchemaVersion(parts) {
23
23
  */
24
24
  export function makeActionEnvelope(parts) {
25
25
  const envelope = {
26
- renderId: parts.renderId,
26
+ sessionId: parts.sessionId,
27
27
  type: parts.type,
28
28
  };
29
29
  if (parts.payload !== undefined)
@@ -45,7 +45,7 @@ export function makeActionEnvelope(parts) {
45
45
  */
46
46
  export function makeStreamEnvelope(parts) {
47
47
  const envelope = {
48
- renderId: parts.renderId,
48
+ sessionId: parts.sessionId,
49
49
  channel: parts.channel,
50
50
  mode: parts.mode,
51
51
  payload: parts.payload,
@@ -65,7 +65,7 @@ export function makeStreamEnvelope(parts) {
65
65
  * Does NOT stamp `schemaVersion` — `ErrorPayload` is the wire-level
66
66
  * error envelope (free-form `code: string`), not an envelope that
67
67
  * opts into the forward-compat stamp (see {@link ActionEnvelope} /
68
- * {@link StreamEnvelope} / {@link ContractErrorPayload}). Keeping
68
+ * {@link StreamEnvelope}). Keeping
69
69
  * `ErrorPayload` stamp-free preserves byte-equivalence with every
70
70
  * existing server-side error emission that pre-dates the central
71
71
  * builders.
@@ -85,25 +85,3 @@ export function makeErrorPayload(parts) {
85
85
  payload.details = parts.details;
86
86
  return payload;
87
87
  }
88
- /**
89
- * Build a {@link ContractErrorPayload} with `schemaVersion` stamped
90
- * to {@link PROTOCOL_SCHEMA_VERSION} unless the caller overrides.
91
- *
92
- * Filters `undefined` optional fields so the emitted payload keeps
93
- * byte-equivalence with the pre-refactor session-channel router
94
- * code.
95
- */
96
- export function makeContractErrorPayload(parts) {
97
- const stamp = resolveSchemaVersion(parts);
98
- const payload = {
99
- toolName: parts.toolName,
100
- error: parts.error,
101
- timestamp: parts.timestamp,
102
- ...(parts.actionName !== undefined ? { actionName: parts.actionName } : {}),
103
- ...(parts.sourceAction !== undefined
104
- ? { sourceAction: parts.sourceAction }
105
- : {}),
106
- ...(stamp !== undefined ? { schemaVersion: stamp } : {}),
107
- };
108
- return payload;
109
- }
@@ -13,7 +13,7 @@
13
13
  * - Client side: on ack receipt, `AckPayload.serverVersion` is
14
14
  * present AND NOT in `CLIENT_SUPPORTED_VERSIONS`. The client
15
15
  * instantiates this class and surfaces it to the caller via the
16
- * session's `onError` hook.
16
+ * render's `onError` hook.
17
17
  *
18
18
  * The class pins `.name === 'UpgradeRequiredError'` and `.code ===
19
19
  * UPGRADE_REQUIRED` so consumers can pattern-match without
@@ -13,7 +13,7 @@
13
13
  * - Client side: on ack receipt, `AckPayload.serverVersion` is
14
14
  * present AND NOT in `CLIENT_SUPPORTED_VERSIONS`. The client
15
15
  * instantiates this class and surfaces it to the caller via the
16
- * session's `onError` hook.
16
+ * render's `onError` hook.
17
17
  *
18
18
  * The class pins `.name === 'UpgradeRequiredError'` and `.code ===
19
19
  * UPGRADE_REQUIRED` so consumers can pattern-match without
@@ -0,0 +1,10 @@
1
+ import type { GadgetDescriptor } from '../types/data-contract';
2
+ /**
3
+ * Resolve an app's effective gadget set: the first-party stdlib package is the
4
+ * structural FLOOR, and `declared` (app-declared extensions) layers on top.
5
+ * Replaces the legacy fallback-when-absent resolution that dropped the stdlib
6
+ * package the moment an app declared any extension. `declared` wins on a
7
+ * `package` collision; absent/empty ⇒ exactly the stdlib set; idempotent.
8
+ */
9
+ export declare function resolveAppGadgets(declared?: readonly GadgetDescriptor[] | null): readonly GadgetDescriptor[];
10
+ //# sourceMappingURL=resolve-app-gadgets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-app-gadgets.d.ts","sourceRoot":"","sources":["../../src/gadgets/resolve-app-gadgets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAO/D;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,CAAC,EAAE,SAAS,gBAAgB,EAAE,GAAG,IAAI,GAC5C,SAAS,gBAAgB,EAAE,CAG7B"}
@@ -0,0 +1,19 @@
1
+ import { STDLIB_GADGETS } from './stdlib-gadgets.js';
2
+ function dedupeByPackage(list) {
3
+ const m = new Map();
4
+ for (const g of list)
5
+ m.set(g.package, g);
6
+ return [...m.values()];
7
+ }
8
+ /**
9
+ * Resolve an app's effective gadget set: the first-party stdlib package is the
10
+ * structural FLOOR, and `declared` (app-declared extensions) layers on top.
11
+ * Replaces the legacy fallback-when-absent resolution that dropped the stdlib
12
+ * package the moment an app declared any extension. `declared` wins on a
13
+ * `package` collision; absent/empty ⇒ exactly the stdlib set; idempotent.
14
+ */
15
+ export function resolveAppGadgets(declared) {
16
+ if (!declared || declared.length === 0)
17
+ return STDLIB_GADGETS;
18
+ return dedupeByPackage([...STDLIB_GADGETS, ...declared]);
19
+ }
@@ -6,7 +6,7 @@
6
6
  * It carries identity only — `(package, export name)` — never
7
7
  * `version` or transport metadata. The operator's `App.gadgets`
8
8
  * catalog owns those; `filterDescriptorsToContract` snapshots the
9
- * referenced subset onto `SessionStackEntry.gadgetDescriptors` as a
9
+ * referenced subset onto `ComponentGguiSession.gadgetDescriptors` as a
10
10
  * sidecar.
11
11
  */
12
12
  import type { DataContract, GadgetDescriptor, GadgetExport, GadgetUse } from '../types/data-contract.js';
@@ -34,7 +34,7 @@ export declare function gadgetExportName(x: GadgetExport): string;
34
34
  * Canonical string key for a gadget EXPORT's identity —
35
35
  * `(name, package)`. Every site that decides "does this wire ref
36
36
  * resolve to that registered export?" MUST key through this helper so
37
- * the resolver and the push-time gates (`assertGadgetsRegistered`,
37
+ * the resolver and the render-time gates (`assertGadgetsRegistered`,
38
38
  * `assertPublicEnvSatisfied`) agree byte-for-byte on what "the same
39
39
  * gadget export" means.
40
40
  *
@@ -59,7 +59,7 @@ export declare function gadgetIdentityKey(use: {
59
59
  /**
60
60
  * Flatten the package-keyed `contract.clientCapabilities.gadgets` into
61
61
  * a list of `(package, name)` use records — one per export the
62
- * contract references. The single accessor every consumer (push
62
+ * contract references. The single accessor every consumer (render
63
63
  * gates, descriptor resolver, code-gen) iterates, so the nested wire
64
64
  * shape is walked in exactly one place.
65
65
  *
@@ -76,12 +76,12 @@ export declare function listContractGadgets(contract: DataContract): readonly Ga
76
76
  * descriptor IS a package, and `App.gadgets` registers at most one
77
77
  * descriptor per package, so a package key resolves to exactly one
78
78
  * descriptor. The filtered list lands as a sidecar on
79
- * `SessionStackEntry.gadgetDescriptors`.
79
+ * `ComponentGguiSession.gadgetDescriptors`.
80
80
  *
81
81
  * Ordering: descriptors appear in the order their package key first
82
82
  * appears on `clientCapabilities.gadgets`. A package absent from
83
- * `appGadgets` is dropped — the push-time `assertGadgetsRegistered`
84
- * gate rejects the push with a precise registration-mismatch code
83
+ * `appGadgets` is dropped — the render-time `assertGadgetsRegistered`
84
+ * gate rejects the render with a precise registration-mismatch code
85
85
  * BEFORE this helper runs, so silent drop here is safe in the happy
86
86
  * path.
87
87
  *
@@ -28,7 +28,7 @@ export function gadgetExportName(x) {
28
28
  * Canonical string key for a gadget EXPORT's identity —
29
29
  * `(name, package)`. Every site that decides "does this wire ref
30
30
  * resolve to that registered export?" MUST key through this helper so
31
- * the resolver and the push-time gates (`assertGadgetsRegistered`,
31
+ * the resolver and the render-time gates (`assertGadgetsRegistered`,
32
32
  * `assertPublicEnvSatisfied`) agree byte-for-byte on what "the same
33
33
  * gadget export" means.
34
34
  *
@@ -52,7 +52,7 @@ export function gadgetIdentityKey(use) {
52
52
  /**
53
53
  * Flatten the package-keyed `contract.clientCapabilities.gadgets` into
54
54
  * a list of `(package, name)` use records — one per export the
55
- * contract references. The single accessor every consumer (push
55
+ * contract references. The single accessor every consumer (render
56
56
  * gates, descriptor resolver, code-gen) iterates, so the nested wire
57
57
  * shape is walked in exactly one place.
58
58
  *
@@ -87,12 +87,12 @@ export function listContractGadgets(contract) {
87
87
  * descriptor IS a package, and `App.gadgets` registers at most one
88
88
  * descriptor per package, so a package key resolves to exactly one
89
89
  * descriptor. The filtered list lands as a sidecar on
90
- * `SessionStackEntry.gadgetDescriptors`.
90
+ * `ComponentGguiSession.gadgetDescriptors`.
91
91
  *
92
92
  * Ordering: descriptors appear in the order their package key first
93
93
  * appears on `clientCapabilities.gadgets`. A package absent from
94
- * `appGadgets` is dropped — the push-time `assertGadgetsRegistered`
95
- * gate rejects the push with a precise registration-mismatch code
94
+ * `appGadgets` is dropped — the render-time `assertGadgetsRegistered`
95
+ * gate rejects the render with a precise registration-mismatch code
96
96
  * BEFORE this helper runs, so silent drop here is safe in the happy
97
97
  * path.
98
98
  *
@@ -12,7 +12,7 @@ export declare const STDLIB_GADGETS_PACKAGE = "@ggui-ai/gadgets";
12
12
  * in `@ggui-ai/gadgets` asserts the two stay in sync, so a release-time
13
13
  * bump to the runtime package without updating this constant fails CI.
14
14
  */
15
- export declare const STDLIB_GADGETS_VERSION = "0.1.0-rc.3";
15
+ export declare const STDLIB_GADGETS_VERSION = "0.3.0";
16
16
  /**
17
17
  * v1 catalog of stdlib gadget descriptors. Every entry's
18
18
  * `package` defaults to {@link STDLIB_GADGETS_PACKAGE}; the
@@ -1 +1 @@
1
- {"version":3,"file":"stdlib-gadgets.d.ts","sourceRoot":"","sources":["../../src/gadgets/stdlib-gadgets.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AAEzD;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,eAAe,CAAC;AAEnD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,QAAQ,CAAC,gBAAgB,CAAC,EA+F/D,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAUnD,CAAC"}
1
+ {"version":3,"file":"stdlib-gadgets.d.ts","sourceRoot":"","sources":["../../src/gadgets/stdlib-gadgets.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AAEzD;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,UAAU,CAAC;AAE9C;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,QAAQ,CAAC,gBAAgB,CAAC,EAkH/D,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAUnD,CAAC"}
@@ -21,9 +21,11 @@
21
21
  // **Parity guarantee:** `@ggui-ai/gadgets` ships a cross-
22
22
  // package contract test (`stdlib-parity.test.ts`) that imports both
23
23
  // this list and the actual hook exports, then asserts the hook names
24
- // match exactly. Drift fails the test on CI; the protocol package
25
- // cannot ship a stale descriptor list without the runtime side
26
- // catching it.
24
+ // match exactly AND that every `example` block sticks to the real
25
+ // `GadgetHook` contract (statuses from the `GadgetStatus` union,
26
+ // `start()`/`stop()` as the only invokable methods). Drift fails the
27
+ // test on CI; the protocol package cannot ship a stale descriptor
28
+ // list without the runtime side catching it.
27
29
  /**
28
30
  * The first-party `@ggui-ai/gadgets` package name. Used as
29
31
  * the default `package` for every entry in {@link STDLIB_GADGETS}
@@ -37,7 +39,7 @@ export const STDLIB_GADGETS_PACKAGE = '@ggui-ai/gadgets';
37
39
  * in `@ggui-ai/gadgets` asserts the two stay in sync, so a release-time
38
40
  * bump to the runtime package without updating this constant fails CI.
39
41
  */
40
- export const STDLIB_GADGETS_VERSION = '0.1.0-rc.3';
42
+ export const STDLIB_GADGETS_VERSION = '0.3.0';
41
43
  /**
42
44
  * v1 catalog of stdlib gadget descriptors. Every entry's
43
45
  * `package` defaults to {@link STDLIB_GADGETS_PACKAGE}; the
@@ -66,10 +68,15 @@ export const STDLIB_GADGETS = [
66
68
  description: 'Capture stills or live video from the device camera.',
67
69
  usage: 'Mount when the intent names photo capture, QR / barcode scanning, video recording, or anything that requires a camera feed. The hook returns a stream once `start()` resolves; thread the resulting blob or stream URL into a contextSpec slot or an actionSpec payload to surface it to the agent.',
68
70
  example: {
69
- call: 'const cam = useCamera();',
71
+ call: "const cam = useCamera({ facingMode: 'environment' }); // on button click: await cam.start()",
70
72
  returns: {
71
- status: 'ready',
72
- value: { stream: '<MediaStream>', kind: 'video' },
73
+ status: 'completed',
74
+ value: {
75
+ dataUrl: 'data:image/png;base64,…',
76
+ width: 640,
77
+ height: 480,
78
+ mimeType: 'image/png',
79
+ },
73
80
  },
74
81
  },
75
82
  },
@@ -79,8 +86,8 @@ export const STDLIB_GADGETS = [
79
86
  description: 'Read the system clipboard contents on user gesture.',
80
87
  usage: 'Mount when the intent involves importing copied content (paste-into-form, paste-image-to-upload, paste-link). The Permissions API requires a user gesture; gate `start()` behind a button click. Returned value lands in a contextSpec slot or an actionSpec payload.',
81
88
  example: {
82
- call: 'const paste = useClipboardPaste();',
83
- returns: { status: 'ready', value: 'pasted clipboard text' },
89
+ call: 'const paste = useClipboardPaste(); // on button click: await paste.start()',
90
+ returns: { status: 'completed', value: 'pasted clipboard text' },
84
91
  },
85
92
  },
86
93
  {
@@ -89,8 +96,8 @@ export const STDLIB_GADGETS = [
89
96
  description: 'Write to the system clipboard on user gesture.',
90
97
  usage: 'Mount when the intent includes copying generated text, share links, codes, or transcripts to the system clipboard. Fire an actionSpec event so the agent observes the act (it does not see the written value — that stays component-local).',
91
98
  example: {
92
- call: "const write = useClipboardWrite(); write.write('hello');",
93
- returns: { status: 'ready' },
99
+ call: "const write = useClipboardWrite({ text: 'hello' }); // on button click: await write.start()",
100
+ returns: { status: 'completed', value: 'hello' },
94
101
  },
95
102
  },
96
103
  {
@@ -98,10 +105,19 @@ export const STDLIB_GADGETS = [
98
105
  description: 'Open the native file picker and read selected files.',
99
106
  usage: 'Mount when the intent names file upload, attachment selection, or document import. No permission required. The hook returns the picked files plus metadata; thread file refs / data URLs into a contextSpec slot or actionSpec payload.',
100
107
  example: {
101
- call: 'const picker = useFilePicker({ accept: "image/*" });',
108
+ call: "const picker = useFilePicker({ accept: 'image/*' }); // on button click: await picker.start()",
102
109
  returns: {
103
- status: 'ready',
104
- value: [{ name: 'photo.png', type: 'image/png', size: 12345 }],
110
+ status: 'completed',
111
+ value: {
112
+ files: [
113
+ {
114
+ name: 'photo.png',
115
+ type: 'image/png',
116
+ size: 12345,
117
+ _file: '<File>',
118
+ },
119
+ ],
120
+ },
105
121
  },
106
122
  },
107
123
  },
@@ -111,10 +127,15 @@ export const STDLIB_GADGETS = [
111
127
  description: "Resolve the device's current geolocation.",
112
128
  usage: 'Mount when the intent names "current location", maps, nearby search, location-aware UI. Browser prompts the user on `start()`; the hook returns coordinates once granted. Thread the resolved coords into a contextSpec slot so the agent observes the latest fix.',
113
129
  example: {
114
- call: 'const geo = useGeolocation();',
130
+ call: 'const geo = useGeolocation(); // on button click: await geo.start()',
115
131
  returns: {
116
- status: 'ready',
117
- value: { latitude: 37.7749, longitude: -122.4194, accuracy: 20 },
132
+ status: 'completed',
133
+ value: {
134
+ latitude: 37.7749,
135
+ longitude: -122.4194,
136
+ accuracy: 20,
137
+ timestamp: 1718000000000,
138
+ },
118
139
  },
119
140
  },
120
141
  },
@@ -124,10 +145,10 @@ export const STDLIB_GADGETS = [
124
145
  description: 'Capture audio from the device microphone.',
125
146
  usage: 'Mount when the intent names voice memos, audio messages, dictation, voice-driven UI. Returns an audio stream / blob; thread it into an actionSpec payload at recording-stop, or into a contextSpec slot for live transcription pipelines.',
126
147
  example: {
127
- call: 'const mic = useMicrophone();',
148
+ call: 'const mic = useMicrophone(); // record on click: await mic.start(); end with mic.stop()',
128
149
  returns: {
129
- status: 'ready',
130
- value: { stream: '<MediaStream>', kind: 'audio' },
150
+ status: 'completed',
151
+ value: { blob: '<Blob>', durationMs: 4200, mimeType: 'audio/webm' },
131
152
  },
132
153
  },
133
154
  },
@@ -137,8 +158,8 @@ export const STDLIB_GADGETS = [
137
158
  description: 'Show system / browser notifications to the user.',
138
159
  usage: 'Mount when the intent involves alerting the user about something (reminders, completion of long tasks, incoming messages) and the UI may be in the background. Permission is prompted on first `start()`; the agent does NOT see notification dismissal directly — surface it via an actionSpec if needed.',
139
160
  example: {
140
- call: "const notify = useNotifications(); notify.show({ title: 'Done' });",
141
- returns: { status: 'ready', value: { granted: true } },
161
+ call: "const notify = useNotifications({ title: 'Done' }); // after the task completes: await notify.start()",
162
+ returns: { status: 'completed', value: { outcome: 'closed' } },
142
163
  },
143
164
  },
144
165
  ],
@@ -4,32 +4,16 @@
4
4
  * Events prefixed with `ggui-` are `postMessage` types (cross-origin iframe boundary).
5
5
  * Events prefixed with `ggui:` are `CustomEvent` names (same-origin, dispatched on `window`).
6
6
  *
7
- * The bridge has three directions:
8
- * 1. **Agent to Component** (inbound): data, streams, progress
9
- * 2. **Component to Agent** (outbound): user interactions (form submits, clicks)
10
- * 3. **Component to Host** (outbound): rendering lifecycle (resize, success, error)
7
+ * The bridge is one-directional: **Agent to Component** (inbound) data
8
+ * deliveries. Outbound user interaction does NOT travel over this bridge —
9
+ * generated components emit canonical `data:submit` ActionEnvelopes via the
10
+ * wire-config action hooks (`useAction`) over the live channel.
11
11
  */
12
12
  export declare const BRIDGE_EVENTS: {
13
13
  /** `postMessage` type for parent-to-iframe data delivery. The parent window posts this type; the iframe bridge script converts it to an `AGENT_DATA` CustomEvent. */
14
14
  readonly AGENT_DATA_POST: "ggui-agent-data";
15
15
  /** `CustomEvent` name dispatched on `window` when agent data arrives. Components listen for this to receive real-time data from the agent (chat messages, typing indicators, etc.). */
16
16
  readonly AGENT_DATA: "ggui:agent-data";
17
- /** `CustomEvent` name for streaming text chunks from the agent. Fired incrementally as the agent generates a response. */
18
- readonly AGENT_STREAM: "ggui:agent-stream";
19
- /** `CustomEvent` name for agent messages. Payload includes `type: 'thinking' | 'chat'`. Thinking messages show what the agent is doing; chat messages are final responses. */
20
- readonly AGENT_MSG: "ggui:agent-msg";
21
- /** `CustomEvent` name for UI generation log updates. Debug/devtools only — not displayed to end users. */
22
- readonly AGENT_LOGS: "ggui:logs";
23
- /** `postMessage` type for iframe-to-parent user interaction data. Carries form submissions and click events from generated components back to the host. */
24
- readonly USER_DATA_POST: "ggui-user-data";
25
- /** `CustomEvent` name dispatched on the parent window when user data arrives from the iframe. The host shell listens for this to forward events to the agent. */
26
- readonly USER_DATA: "ggui:user-data";
27
- /** `postMessage` type sent when a component's content size changes. Used by the host to auto-resize the iframe to fit content. */
28
- readonly RESIZE: "ggui-resize";
29
- /** `postMessage` type sent when a component renders successfully. The host uses this to hide loading indicators and show the component. */
30
- readonly RENDER_SUCCESS: "ggui-render-success";
31
- /** `postMessage` type sent when a component fails to render. The host uses this to show an error state instead of a blank iframe. */
32
- readonly RENDER_ERROR: "ggui-render-error";
33
17
  };
34
18
  /**
35
19
  * Srcdoc JS snippet: bridge agent data postMessages into CustomEvents inside iframe.
@@ -37,27 +21,4 @@ export declare const BRIDGE_EVENTS: {
37
21
  * events when the parent forwards data via postMessage.
38
22
  */
39
23
  export declare const SRCDOC_AGENT_DATA_BRIDGE = "\n window.addEventListener(\"message\", function(event) {\n if (event.data && event.data.type === \"ggui-agent-data\") {\n window.dispatchEvent(new CustomEvent(\"ggui:agent-data\", { detail: event.data.payload }));\n }\n });";
40
- /**
41
- * Srcdoc JS snippet: auto-report content height changes to parent.
42
- *
43
- * Uses a ResizeObserver on <html> to detect layout changes and posts
44
- * a `ggui-resize` message with the current scrollHeight. Also fires
45
- * an initial measurement on the next animation frame after injection.
46
- *
47
- * Inject this into any srcdoc or rendered page <script> so the parent
48
- * can auto-size the iframe to fit content without scrollbars.
49
- */
50
- export declare const SRCDOC_RESIZE_BRIDGE: string;
51
- /**
52
- * Srcdoc JS snippet: universal interaction bridge inside iframe.
53
- *
54
- * Three layers of automatic event capture (no props.onSubmit needed):
55
- * 1. Form submit intercept — captures <form> submissions with all field data
56
- * 2. Interactive element clicks — buttons, [role="button"], links, [data-action]
57
- * 3. Cursor-pointer fallback (approach C) — any styled-clickable div/span/card
58
- *
59
- * All layers skip if props.onSubmit already handled the event (__ggui_submitHandled).
60
- * Click handler uses bubble phase so component handlers run first.
61
- */
62
- export declare const SRCDOC_USER_DATA_BRIDGE = "\n // Dedup: props.onSubmit sets __ggui_submitHandled = true synchronously.\n // Both layers check this. We use a microtask to reset it so it stays\n // true for ALL handlers in the same event cycle (click + submit).\n function __ggui_wasHandled() {\n if (!window.__ggui_submitHandled) return false;\n // Reset via microtask \u2014 stays true for all sync handlers in this tick\n Promise.resolve().then(function() { window.__ggui_submitHandled = false; });\n return true;\n }\n\n // Layer 1: Form submit intercept (bubble phase \u2014 lets component onSubmit run first)\n // Handles: <form> submit via enter key or submit-button click.\n // Uses bubble phase so component's onSubmit (which may call props.onSubmit) fires first.\n document.addEventListener(\"submit\", function(e) {\n e.preventDefault();\n if (__ggui_wasHandled()) return;\n var form = e.target;\n var data = {};\n try { data = Object.fromEntries(new FormData(form)); } catch(_) {}\n parent.postMessage({ type: \"ggui-user-data\", data: data }, \"*\");\n });\n\n // Layers 2+3: Universal click handler (bubble phase \u2014 runs after component handlers)\n // Handles: buttons, [role=\"button\"], links, [data-action], cursor:pointer elements.\n // Does NOT handle submit-type elements inside forms (Layer 1 handles those).\n document.addEventListener(\"click\", function(e) {\n if (__ggui_wasHandled()) return;\n if (!e.target || !e.target.closest) return;\n\n // Layer 2: Find the closest standard interactive element\n var el = e.target.closest(\"button\")\n || e.target.closest(\"[role='button']\")\n || e.target.closest(\"a[href], a[data-action]\")\n || e.target.closest(\"[data-action]\")\n || e.target.closest(\"[data-ggui-action]\");\n\n // Layer 3 (approach C): Fallback \u2014 walk up DOM looking for cursor:pointer\n if (!el) {\n var target = e.target;\n var depth = 0;\n while (target && target !== document.documentElement && depth < 6) {\n if (target.nodeType === 1) {\n try {\n if (window.getComputedStyle(target).cursor === \"pointer\") {\n el = target;\n break;\n }\n } catch(_) {}\n }\n target = target.parentElement;\n depth++;\n }\n }\n if (!el) return;\n\n // Skip submit-type elements inside forms \u2014 Layer 1 handles those.\n // (click fires before submit, so we must yield to avoid double-fire)\n // <button> defaults to type=\"submit\", so el.type === \"submit\" catches both\n // <button> and <button type=\"submit\">. Only <button type=\"button\"> is excluded.\n if (el.closest(\"form\") && el.type === \"submit\") return;\n\n // Skip form control elements \u2014 these are data entry, not actions.\n // Checkboxes, radios, inputs, selects get captured via form submit (Layer 1).\n var tag = el.tagName;\n if (tag === \"INPUT\" || tag === \"TEXTAREA\" || tag === \"SELECT\" || tag === \"LABEL\") return;\n\n // For standalone interactive elements, post click event with label + data attributes\n var data = { action: \"click\" };\n var label = el.getAttribute(\"aria-label\")\n || el.getAttribute(\"data-label\")\n || el.innerText\n || el.textContent;\n if (label) data.label = label.trim().substring(0, 200);\n\n // Spread data-* attributes into payload (data-action, data-value, etc.)\n if (el.dataset) {\n for (var key in el.dataset) {\n if (el.dataset.hasOwnProperty(key)) data[key] = el.dataset[key];\n }\n }\n\n parent.postMessage({ type: \"ggui-user-data\", data: data }, \"*\");\n });";
63
24
  //# sourceMappingURL=iframe-bridge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"iframe-bridge.d.ts","sourceRoot":"","sources":["../src/iframe-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa;IAExB,qKAAqK;;IAErK,uLAAuL;;IAIvL,0HAA0H;;IAI1H,8KAA8K;;IAI9K,0GAA0G;;IAI1G,2JAA2J;;IAE3J,iKAAiK;;IAIjK,kIAAkI;;IAElI,2IAA2I;;IAE3I,qIAAqI;;CAE7H,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,kPAK/B,CAAC;AAEP;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,QAUzB,CAAC;AAET;;;;;;;;;;GAUG;AACH,eAAO,MAAM,uBAAuB,8lHAmF9B,CAAC"}
1
+ {"version":3,"file":"iframe-bridge.d.ts","sourceRoot":"","sources":["../src/iframe-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa;IAExB,qKAAqK;;IAErK,uLAAuL;;CAE/K,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,kPAK/B,CAAC"}