@ggui-ai/iframe-runtime 0.25.0 → 0.26.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 (40) hide show
  1. package/README.md +2 -2
  2. package/dist/channels/data.d.ts +8 -0
  3. package/dist/channels/data.js +2 -0
  4. package/dist/credential-controller.d.ts +71 -0
  5. package/dist/credential-controller.js +135 -0
  6. package/dist/iframe-runtime.js +97 -94
  7. package/dist/iframe-runtime.meta.json +1 -1
  8. package/dist/index.d.ts +2 -2
  9. package/dist/ladders.d.ts +77 -0
  10. package/dist/ladders.js +383 -0
  11. package/dist/meta-parse.js +38 -8
  12. package/dist/observability.d.ts +22 -1
  13. package/dist/react-renderer.d.ts +20 -0
  14. package/dist/react-renderer.js +22 -0
  15. package/dist/registry-subscribe.d.ts +37 -1
  16. package/dist/registry-subscribe.js +34 -8
  17. package/dist/render-failure-report.d.ts +15 -0
  18. package/dist/render-failure-report.js +61 -0
  19. package/dist/render-item.d.ts +3 -0
  20. package/dist/render-item.js +2 -0
  21. package/dist/runtime-telemetry.d.ts +28 -18
  22. package/dist/runtime-telemetry.js +68 -29
  23. package/dist/runtime.d.ts +114 -35
  24. package/dist/runtime.js +556 -309
  25. package/dist/stream-seq.d.ts +56 -0
  26. package/dist/stream-seq.js +46 -0
  27. package/dist/system-cards/ProtocolProbeCard.d.ts +16 -0
  28. package/dist/system-cards/ProtocolProbeCard.js +17 -14
  29. package/dist/tool-result-error.d.ts +6 -0
  30. package/dist/tool-result-error.js +32 -0
  31. package/dist/types.d.ts +49 -1
  32. package/dist/view-origin.d.ts +29 -0
  33. package/dist/view-origin.js +33 -0
  34. package/dist/view-proof-signer.d.ts +31 -0
  35. package/dist/view-proof-signer.js +99 -0
  36. package/dist/view-root.d.ts +51 -0
  37. package/dist/view-root.js +56 -0
  38. package/dist/wire-config.d.ts +13 -0
  39. package/dist/wire-config.js +39 -1
  40. package/package.json +8 -7
@@ -9,6 +9,12 @@ import { postObservabilityToParent } from './observability.js';
9
9
  // ruling; ggui#599 cycle-2 caught the stale reference here) — and the
10
10
  // hoist stands on its own merits. Re-exported for internal modules.
11
11
  export { StreamBus };
12
+ /**
13
+ * The most `action-refused` events one render posts (ggui#1536). A tap is a
14
+ * person; a card that re-dispatches in a loop is code, and the host needs to
15
+ * know it happened, not every time. The last one says it is the last.
16
+ */
17
+ const REFUSED_EVENTS_PER_RENDER = 10;
12
18
  /**
13
19
  * Build the per-render `WireConfig` for the iframe runtime.
14
20
  * Bootstraps the renderer's outbound emission + inbound subscription
@@ -67,8 +73,35 @@ export function buildRootWireConfig(opts) {
67
73
  namedUnenforceableFor = currentRender.id;
68
74
  postObservabilityToParent({ kind: 'one-shot-unenforceable', renderId: currentRender.id, actionName });
69
75
  };
76
+ // ggui#1536 — a dispatch the outbound contract check refuses sent nothing
77
+ // and said so only on this iframe's console. Name it where the runtime names
78
+ // its other degradations: the `action-refused` event to the embedding host,
79
+ // carrying field paths and schema keywords only, because a violation's
80
+ // `received` and `message` can carry the visitor's input. Then the renderer
81
+ // tells the visitor.
82
+ let refusedFor = null;
83
+ let refusedPosted = 0;
84
+ const nameRefused = ({ actionName, violations }) => {
85
+ const renderId = opts.getCurrentGguiSession()?.id ?? opts.sessionId;
86
+ if (refusedFor !== renderId) {
87
+ refusedFor = renderId;
88
+ refusedPosted = 0;
89
+ }
90
+ if (refusedPosted < REFUSED_EVENTS_PER_RENDER) {
91
+ refusedPosted += 1;
92
+ postObservabilityToParent({
93
+ kind: 'action-refused',
94
+ renderId,
95
+ actionName,
96
+ violations: violations.map((v) => ({ field: v.field, ...(v.keyword !== undefined ? { keyword: v.keyword } : {}) })),
97
+ ...(refusedPosted === REFUSED_EVENTS_PER_RENDER ? { capped: true } : {}),
98
+ });
99
+ }
100
+ opts.onDispatchRefused?.(actionName);
101
+ };
70
102
  return buildWireConfig({
71
103
  app: { appId: opts.appId, appName: opts.appId },
104
+ onDispatchRefused: nameRefused,
72
105
  // `isConnected` here is the static config field; `useRender()`
73
106
  // reads the LIVE value from wire's document connection store,
74
107
  // which the runtime writes at the relay latch's edges (ggui#670).
@@ -103,7 +136,12 @@ export function buildRootWireConfig(opts) {
103
136
  return undefined;
104
137
  }
105
138
  const record = currentRender.spentOneShots;
106
- return record !== undefined && record.epoch === (currentRender.epoch ?? 0) ? record.actions : undefined;
139
+ const persisted = record !== undefined && record.epoch === (currentRender.epoch ?? 0) ? record.actions : undefined;
140
+ // ggui#1424 — plus the names the server refused as already spent.
141
+ const refused = opts.refusedSpentOneShots?.();
142
+ if (refused === undefined || refused.length === 0)
143
+ return persisted;
144
+ return persisted === undefined ? refused : [...persisted, ...refused];
107
145
  },
108
146
  // The iframe's precompiled-validator variant — the dispatch never
109
147
  // trips the iframe's no-`unsafe-eval` CSP.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ggui-ai/iframe-runtime",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "description": "The iframe-local ggui runtime: a self-contained ESM bundle that boots inside an MCP Apps host iframe, runs the protocol-version handshake, opens the live-channel WebSocket, and mounts the rendered UI. Bundles React, ReactDOM, and the ggui design system so generated component code has a single seam to read from.",
5
5
  "keywords": [
6
6
  "ggui",
@@ -37,16 +37,17 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "@modelcontextprotocol/ext-apps": "^1.7.2",
40
+ "@noble/hashes": "^1.6.0",
40
41
  "qrcode-generator": "^2.0.4",
41
42
  "react": "^19.0.0",
42
43
  "react-dom": "^19.0.0",
43
44
  "zod": "^4.3.6",
44
- "@ggui-ai/gadgets": "0.25.0",
45
- "@ggui-ai/design": "0.25.0",
46
- "@ggui-ai/live-channel": "0.25.0",
47
- "@ggui-ai/preview-a2ui": "0.25.0",
48
- "@ggui-ai/protocol": "0.25.0",
49
- "@ggui-ai/wire": "0.25.0"
45
+ "@ggui-ai/design": "0.26.0",
46
+ "@ggui-ai/gadgets": "0.26.0",
47
+ "@ggui-ai/preview-a2ui": "0.26.0",
48
+ "@ggui-ai/live-channel": "0.26.0",
49
+ "@ggui-ai/protocol": "0.26.0",
50
+ "@ggui-ai/wire": "0.26.0"
50
51
  },
51
52
  "peerDependencies": {
52
53
  "@modelcontextprotocol/sdk": "^1.27.0"