oui-spec 0.5.0 → 0.6.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 (45) hide show
  1. package/README.md +18 -8
  2. package/dist/{chunk-XUX4XVP3.cjs → chunk-5UUJ3F7C.cjs} +49 -22
  3. package/dist/chunk-5UUJ3F7C.cjs.map +1 -0
  4. package/dist/{chunk-27CBVTA4.cjs → chunk-AFNWLRKV.cjs} +82 -18
  5. package/dist/chunk-AFNWLRKV.cjs.map +1 -0
  6. package/dist/{chunk-BNGJJM3T.js → chunk-B2EFZMGY.js} +40 -3
  7. package/dist/chunk-B2EFZMGY.js.map +1 -0
  8. package/dist/{chunk-2AISUNMW.cjs → chunk-LDECTDPU.cjs} +40 -2
  9. package/dist/chunk-LDECTDPU.cjs.map +1 -0
  10. package/dist/{chunk-UKKITNZK.js → chunk-R3SGP2UY.js} +49 -22
  11. package/dist/chunk-R3SGP2UY.js.map +1 -0
  12. package/dist/{chunk-6ZIKO7MG.js → chunk-VQETSIY5.js} +77 -13
  13. package/dist/chunk-VQETSIY5.js.map +1 -0
  14. package/dist/core/index.cjs +7 -7
  15. package/dist/core/index.d.cts +5 -5
  16. package/dist/core/index.d.ts +5 -5
  17. package/dist/core/index.js +3 -3
  18. package/dist/index.cjs +19 -15
  19. package/dist/index.d.cts +4 -3
  20. package/dist/index.d.ts +4 -3
  21. package/dist/index.js +3 -3
  22. package/dist/react/index.d.cts +3 -3
  23. package/dist/react/index.d.ts +3 -3
  24. package/dist/spec/index.cjs +13 -9
  25. package/dist/spec/index.d.cts +21 -360
  26. package/dist/spec/index.d.ts +21 -360
  27. package/dist/spec/index.js +1 -1
  28. package/dist/{surface-runtime-CS0rByFQ.d.ts → surface-runtime-CSZ9UtBO.d.cts} +10 -2
  29. package/dist/{surface-runtime-lqXn221P.d.cts → surface-runtime-D5nINY4b.d.ts} +10 -2
  30. package/dist/transport/index.cjs +2 -2
  31. package/dist/transport/index.d.cts +3 -3
  32. package/dist/transport/index.d.ts +3 -3
  33. package/dist/transport/index.js +1 -1
  34. package/dist/types-CmJb1BQ8.d.cts +403 -0
  35. package/dist/types-CmJb1BQ8.d.ts +403 -0
  36. package/dist/{websocket-YfWILdZ4.d.cts → websocket-Ce3tDSsJ.d.ts} +26 -7
  37. package/dist/{websocket-c5tIUWY5.d.ts → websocket-Ds2Rh_jL.d.cts} +26 -7
  38. package/package.json +1 -1
  39. package/spec/OUI-SPEC-v0.1.md +63 -7
  40. package/dist/chunk-27CBVTA4.cjs.map +0 -1
  41. package/dist/chunk-2AISUNMW.cjs.map +0 -1
  42. package/dist/chunk-6ZIKO7MG.js.map +0 -1
  43. package/dist/chunk-BNGJJM3T.js.map +0 -1
  44. package/dist/chunk-UKKITNZK.js.map +0 -1
  45. package/dist/chunk-XUX4XVP3.cjs.map +0 -1
package/README.md CHANGED
@@ -53,17 +53,26 @@ flowchart TD
53
53
  Every action request carries a `requestId`, and the client answers it exactly
54
54
  once with an `OUIActionResult` (spec §7.3):
55
55
 
56
- | Event | Direction | Carries |
57
- | -------------------- | ---------------- | ---------------------------------------------------------------------------------------------------- |
58
- | `{ns}:dispatch` | runtime → client | `OUIActionRequest` — `requestId`, `surfaceId`, `actionId`, `params` |
59
- | `{ns}:action:result` | client → runtime | `OUIActionResult` — success or error, and the client's surfaces and observations once the UI settled |
60
- | `{ns}:observation` | client → runtime | state updates as they happen |
56
+ | Event | Direction | Carries |
57
+ | -------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
58
+ | `{ns}:dispatch` | runtime → client | `OUIActionRequest` — `requestId`, `surfaceId`, `actionId`, `params` |
59
+ | `{ns}:action:result` | client → runtime | `OUIActionResult` — success or error, the client's observations once the UI settled, its surfaces' hash, and its surfaces when they changed |
60
+ | `{ns}:observation` | client → runtime | state updates as they happen |
61
61
 
62
62
  The result includes what the client can do **after** the action. An action can
63
63
  change that: navigating unmounts one page's surfaces and mounts another's. An
64
64
  agent that only knew the capability set from before the action would be acting
65
65
  on the page it just left.
66
66
 
67
+ Surfaces are heavy (every action's schema), so a result repeats them only when
68
+ the agent runtime does not hold them: the runtime sends the `surfacesHash` it
69
+ holds as the request's `knownSurfaces`, and the result carries `surfaces` only
70
+ when the client's hash differs. A result the receiver refuses (too large,
71
+ invalid) is acknowledged as refused, and the client sends it again trimmed,
72
+ with `delivery` saying what was left out and why: the agent always learns the
73
+ action's outcome. A request is acknowledged on receipt when the sender asks,
74
+ and a repeat of a request whose answer is on its way gets no second copy.
75
+
67
76
  An async action (`async: true`) is acknowledged at once with `interim: true`,
68
77
  and answered a second time, under the same `requestId`, when its polling
69
78
  finishes. Progress in between is published as observations.
@@ -164,8 +173,8 @@ function CounterPage() {
164
173
  }
165
174
  ```
166
175
 
167
- `runtime.snapshot()` returns `{ surfaces, observations }` for everything
168
- mounted. An agent runtime that keeps no registry of its own can take it with
176
+ `runtime.snapshot()` returns `{ surfaces, observations, surfacesHash }` for
177
+ everything mounted. An agent runtime that keeps no registry of its own can take it with
169
178
  each request (for example, with each chat turn); set `announce: false` and the
170
179
  runtime sends nothing but results over the socket.
171
180
 
@@ -247,7 +256,7 @@ sequenceDiagram
247
256
  WS->>Browser: oui:dispatch
248
257
  Note over Browser: Handler runs once (de-duplicated by requestId)
249
258
  Note over Browser: Waits until the UI settles
250
- Browser->>WS: oui:action:result { requestId, success, data, surfaces, observations }
259
+ Browser->>WS: oui:action:result { requestId, success, data, observations, surfacesHash, surfaces if changed }
251
260
  WS->>Agent: result for requestId
252
261
  ```
253
262
 
@@ -726,6 +735,7 @@ They even share JSON Schema for parameter validation — a deliberate design cho
726
735
  - [x] `createOUI()` — gated instantiation; integration requirements enforced at compile time
727
736
  - [x] `createSurfaceRuntime()` — client-side record of mounted surfaces; every request answered with a result and the snapshot after it
728
737
  - [x] Approvals — `transaction` and destructive actions run only on a grant from the user's own confirmation, bound to the exact params (0.5.0)
738
+ - [x] Results carry surfaces only when they changed (`knownSurfaces` / `surfacesHash`), and a refused result is sent again trimmed, saying why (0.6.0)
729
739
  - [ ] `oui-spec/devtools` — Surface inspector / debugger
730
740
  - [ ] `oui-spec/vue` — Vue bindings
731
741
  - [ ] `oui-spec/validator` — Runtime schema validation
@@ -24,7 +24,8 @@ function createWebSocketTransport(socket, config) {
24
24
  if (shouldBuffer) {
25
25
  while (buffer.length > 0) {
26
26
  const msg = buffer.shift();
27
- socket.emit(msg.event, msg.data);
27
+ if (msg.ack) socket.emit(msg.event, msg.data, msg.ack);
28
+ else socket.emit(msg.event, msg.data);
28
29
  }
29
30
  }
30
31
  connectionHandlers.forEach((h) => h(true));
@@ -33,11 +34,12 @@ function createWebSocketTransport(socket, config) {
33
34
  connected = false;
34
35
  connectionHandlers.forEach((h) => h(false));
35
36
  });
36
- function emit(event, data) {
37
+ function emit(event, data, ack) {
37
38
  if (connected) {
38
- socket.emit(event, data);
39
+ if (ack) socket.emit(event, data, ack);
40
+ else socket.emit(event, data);
39
41
  } else if (shouldBuffer && buffer.length < maxBuffer) {
40
- buffer.push({ event, data });
42
+ buffer.push({ event, data, ...ack ? { ack } : {} });
41
43
  }
42
44
  }
43
45
  return {
@@ -48,33 +50,50 @@ function createWebSocketTransport(socket, config) {
48
50
  onAction(handler) {
49
51
  return listen(
50
52
  `${ns}:dispatch`,
51
- (data) => {
53
+ (data, ack) => {
54
+ const receipt = typeof ack === "function" ? (a) => ack(a) : void 0;
52
55
  if (!data || typeof data.requestId !== "string" || !data.requestId || typeof data.surfaceId !== "string" || typeof data.actionId !== "string") {
53
56
  console.warn(
54
57
  "[OUI] Dropped a dispatch without requestId/surfaceId/actionId",
55
58
  data
56
59
  );
60
+ receipt?.({
61
+ ok: false,
62
+ reason: "a request needs requestId, surfaceId and actionId"
63
+ });
57
64
  return;
58
65
  }
59
- handler({
60
- requestId: data.requestId,
61
- surfaceId: data.surfaceId,
62
- actionId: data.actionId,
63
- params: data.params ?? {},
64
- timestamp: data.timestamp ?? Date.now(),
65
- ...isApproval(data.approval) ? {
66
- approval: {
67
- approvalId: data.approval.approvalId,
68
- argsHash: data.approval.argsHash
69
- }
70
- } : {}
71
- });
66
+ handler(
67
+ {
68
+ requestId: data.requestId,
69
+ surfaceId: data.surfaceId,
70
+ actionId: data.actionId,
71
+ params: data.params ?? {},
72
+ timestamp: data.timestamp ?? Date.now(),
73
+ ...isApproval(data.approval) ? {
74
+ approval: {
75
+ approvalId: data.approval.approvalId,
76
+ argsHash: data.approval.argsHash
77
+ }
78
+ } : {},
79
+ // The surfaces the agent runtime holds, so the answer need not repeat them (§7.3.4).
80
+ ...typeof data.knownSurfaces === "string" && data.knownSurfaces ? { knownSurfaces: data.knownSurfaces } : {}
81
+ },
82
+ receipt
83
+ );
72
84
  }
73
85
  );
74
86
  },
75
87
  // ─── Result ─────────────────────────────────────────────────
76
- sendResult(result) {
77
- emit(`${ns}:action:result`, result);
88
+ sendResult(result, onAcknowledged) {
89
+ emit(
90
+ `${ns}:action:result`,
91
+ result,
92
+ onAcknowledged ? (response) => {
93
+ const ack = acknowledgmentOf(response);
94
+ if (ack) onAcknowledged(ack);
95
+ } : void 0
96
+ );
78
97
  },
79
98
  onResult(handler) {
80
99
  return listen(
@@ -159,7 +178,15 @@ function isApproval(value) {
159
178
  const a = value;
160
179
  return !!a && typeof a.approvalId === "string" && !!a.approvalId && typeof a.argsHash === "string";
161
180
  }
181
+ function acknowledgmentOf(response) {
182
+ const r = response;
183
+ if (!r || typeof r !== "object") return null;
184
+ if (r.ok === true) return { ok: true };
185
+ if (r.ok !== false) return null;
186
+ const why = typeof r.error === "string" ? r.error : typeof r.reason === "string" ? r.reason : "";
187
+ return { ok: false, reason: why || "refused" };
188
+ }
162
189
 
163
190
  exports.createWebSocketTransport = createWebSocketTransport;
164
- //# sourceMappingURL=chunk-XUX4XVP3.cjs.map
165
- //# sourceMappingURL=chunk-XUX4XVP3.cjs.map
191
+ //# sourceMappingURL=chunk-5UUJ3F7C.cjs.map
192
+ //# sourceMappingURL=chunk-5UUJ3F7C.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/transport/websocket.ts"],"names":[],"mappings":"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","file":"chunk-5UUJ3F7C.cjs","sourcesContent":["import type {\n OUIAcknowledgment,\n OUITransport,\n OUITransportConfig,\n OUIActionHandler,\n OUIObservationHandler,\n OUIResultHandler,\n} from \"./types.js\";\nimport type {\n OUISurface,\n OUIObservationUpdate,\n OUIActionRequest,\n OUIActionResult,\n OUIActionApproval,\n} from \"../spec/index.js\";\n\n/**\n * WebSocket transport using Socket.IO.\n * Maps OUI protocol events to socket events with a configurable namespace prefix.\n *\n * Events:\n * {ns}:dispatch — action request (runtime → client)\n * {ns}:action:result — action result (client → runtime)\n * {ns}:observation — observation (client → runtime)\n * {ns}:surface:register — registration (client → runtime)\n * {ns}:surface:deregister — deregistration (client → runtime)\n */\nexport function createWebSocketTransport(\n socket: SocketLike,\n config?: OUITransportConfig,\n): OUITransport {\n const ns = config?.namespace ?? \"oui\";\n const buffer: Array<{ event: string; data: unknown; ack?: Ack }> = [];\n const maxBuffer = config?.maxBufferSize ?? 100;\n const shouldBuffer = config?.bufferWhileDisconnected ?? true;\n\n let connected = socket.connected ?? false;\n const connectionHandlers: Array<(c: boolean) => void> = [];\n\n // Every listener this transport attaches, so dispose() can remove exactly\n // these and nothing the integrator attached to the same socket.\n const attached: Array<{ event: string; handler: (...args: any[]) => void }> =\n [];\n function listen(\n event: string,\n handler: (...args: any[]) => void,\n ): () => void {\n socket.on(event, handler);\n const entry = { event, handler };\n attached.push(entry);\n return () => {\n socket.off(event, handler);\n const i = attached.indexOf(entry);\n if (i >= 0) attached.splice(i, 1);\n };\n }\n\n listen(\"connect\", () => {\n connected = true;\n // Flush before announcing: anything queued while offline was sent earlier\n // than whatever a connection handler is about to send.\n if (shouldBuffer) {\n while (buffer.length > 0) {\n const msg = buffer.shift()!;\n if (msg.ack) socket.emit(msg.event, msg.data, msg.ack);\n else socket.emit(msg.event, msg.data);\n }\n }\n connectionHandlers.forEach((h) => h(true));\n });\n\n listen(\"disconnect\", () => {\n connected = false;\n connectionHandlers.forEach((h) => h(false));\n });\n\n function emit(event: string, data: unknown, ack?: Ack) {\n if (connected) {\n if (ack) socket.emit(event, data, ack);\n else socket.emit(event, data);\n } else if (shouldBuffer && buffer.length < maxBuffer) {\n buffer.push({ event, data, ...(ack ? { ack } : {}) });\n }\n }\n\n return {\n // ─── Dispatch ───────────────────────────────────────────────\n dispatch(request: OUIActionRequest) {\n emit(`${ns}:dispatch`, request);\n },\n\n onAction(handler: OUIActionHandler) {\n return listen(\n `${ns}:dispatch`,\n (data: Partial<OUIActionRequest> | undefined, ack?: unknown) => {\n // The sender's receipt, when it asked for one (§7.3.7).\n const receipt =\n typeof ack === \"function\"\n ? (a: OUIAcknowledgment) => (ack as (r: unknown) => void)(a)\n : undefined;\n // A request without a requestId cannot be answered, and answering is\n // the contract. Refuse it loudly rather than run an action whose\n // result has nowhere to go.\n if (\n !data ||\n typeof data.requestId !== \"string\" ||\n !data.requestId ||\n typeof data.surfaceId !== \"string\" ||\n typeof data.actionId !== \"string\"\n ) {\n console.warn(\n \"[OUI] Dropped a dispatch without requestId/surfaceId/actionId\",\n data,\n );\n receipt?.({\n ok: false,\n reason: \"a request needs requestId, surfaceId and actionId\",\n });\n return;\n }\n handler(\n {\n requestId: data.requestId,\n surfaceId: data.surfaceId,\n actionId: data.actionId,\n params: data.params ?? {},\n timestamp: data.timestamp ?? Date.now(),\n ...(isApproval(data.approval)\n ? {\n approval: {\n approvalId: data.approval.approvalId,\n argsHash: data.approval.argsHash,\n },\n }\n : {}),\n // The surfaces the agent runtime holds, so the answer need not repeat them (§7.3.4).\n ...(typeof data.knownSurfaces === \"string\" && data.knownSurfaces\n ? { knownSurfaces: data.knownSurfaces }\n : {}),\n },\n receipt,\n );\n },\n );\n },\n\n // ─── Result ─────────────────────────────────────────────────\n sendResult(\n result: OUIActionResult,\n onAcknowledged?: (ack: OUIAcknowledgment) => void,\n ) {\n // Acknowledged, so a refusal is heard rather than silent (§7.3.6).\n emit(\n `${ns}:action:result`,\n result,\n onAcknowledged\n ? (response: unknown) => {\n const ack = acknowledgmentOf(response);\n if (ack) onAcknowledged(ack);\n }\n : undefined,\n );\n },\n\n onResult(handler: OUIResultHandler) {\n return listen(`${ns}:action:result`, (data: OUIActionResult) =>\n handler(data),\n );\n },\n\n // ─── Observation Channel ────────────────────────────────────\n pushObservation(update: OUIObservationUpdate) {\n emit(`${ns}:observation`, update);\n },\n\n onObservation(handler: OUIObservationHandler) {\n return listen(`${ns}:observation`, (data: OUIObservationUpdate) =>\n handler(data),\n );\n },\n\n // ─── Surface Lifecycle ──────────────────────────────────────\n registerSurface(surface: OUISurface) {\n emit(`${ns}:surface:register`, { surface, timestamp: Date.now() });\n },\n\n deregisterSurface(surfaceId: string) {\n emit(`${ns}:surface:deregister`, { surfaceId, timestamp: Date.now() });\n },\n\n onSurfaceRegister(handler: (surface: OUISurface) => void) {\n return listen(`${ns}:surface:register`, (data: { surface: OUISurface }) =>\n handler(data.surface),\n );\n },\n\n onSurfaceDeregister(handler: (surfaceId: string) => void) {\n return listen(`${ns}:surface:deregister`, (data: { surfaceId: string }) =>\n handler(data.surfaceId),\n );\n },\n\n // ─── Connection ─────────────────────────────────────────────\n get connected() {\n return connected;\n },\n\n async connect() {\n if (connected) return;\n return new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(\n new Error(\n `OUI transport connect timeout (${config?.connectTimeoutMs ?? 10000}ms)`,\n ),\n );\n }, config?.connectTimeoutMs ?? 10000);\n\n socket.once(\"connect\", () => {\n clearTimeout(timeout);\n resolve();\n });\n\n if (typeof socket.connect === \"function\") {\n socket.connect();\n }\n });\n },\n\n disconnect() {\n if (typeof socket.disconnect === \"function\") {\n socket.disconnect();\n }\n },\n\n onConnectionChange(handler: (c: boolean) => void) {\n connectionHandlers.push(handler);\n return () => {\n const idx = connectionHandlers.indexOf(handler);\n if (idx >= 0) connectionHandlers.splice(idx, 1);\n };\n },\n\n dispose() {\n for (const { event, handler } of attached.splice(0)) {\n socket.off(event, handler);\n }\n connectionHandlers.length = 0;\n buffer.length = 0;\n },\n };\n}\n\n/**\n * Minimal socket interface — compatible with Socket.IO client or server socket.\n * Only the methods OUI actually uses.\n */\nexport interface SocketLike {\n readonly connected?: boolean;\n /** An optional last argument is the receiver's acknowledgment callback, as Socket.IO takes it. */\n emit(event: string, ...args: any[]): void;\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler: (...args: any[]) => void): void;\n once(event: string, handler: (...args: any[]) => void): void;\n connect?(): void;\n disconnect?(): void;\n}\n\n/** An approval as the wire carries it; anything else is dropped, so the runtime treats the request as unapproved. */\nfunction isApproval(value: unknown): value is OUIActionApproval {\n const a = value as Partial<OUIActionApproval> | null | undefined;\n return (\n !!a &&\n typeof a.approvalId === \"string\" &&\n !!a.approvalId &&\n typeof a.argsHash === \"string\"\n );\n}\n\n/** The receiver's acknowledgment callback. */\ntype Ack = (response: unknown) => void;\n\n/**\n * A receiver's acknowledgment: `{ ok: true }`, or `{ ok: false, error }` /\n * `{ ok: false, reason }` as a refusal; null for anything else.\n */\nfunction acknowledgmentOf(response: unknown): OUIAcknowledgment | null {\n const r = response as\n { ok?: unknown; error?: unknown; reason?: unknown } | null | undefined;\n if (!r || typeof r !== \"object\") return null;\n if (r.ok === true) return { ok: true };\n if (r.ok !== false) return null;\n const why =\n typeof r.error === \"string\"\n ? r.error\n : typeof r.reason === \"string\"\n ? r.reason\n : \"\";\n return { ok: false, reason: why || \"refused\" };\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk2AISUNMW_cjs = require('./chunk-2AISUNMW.cjs');
4
- var chunkXUX4XVP3_cjs = require('./chunk-XUX4XVP3.cjs');
3
+ var chunkLDECTDPU_cjs = require('./chunk-LDECTDPU.cjs');
4
+ var chunk5UUJ3F7C_cjs = require('./chunk-5UUJ3F7C.cjs');
5
5
 
6
6
  // src/core/brand.ts
7
7
  function brand(value) {
@@ -130,7 +130,7 @@ function createOUI(config) {
130
130
  seen.add(surface.id);
131
131
  }
132
132
  const transport = brand(
133
- chunkXUX4XVP3_cjs.createWebSocketTransport(socket, transportConfig)
133
+ chunk5UUJ3F7C_cjs.createWebSocketTransport(socket, transportConfig)
134
134
  );
135
135
  const byId = new Map(surfaces.map((s) => [s.id, s]));
136
136
  return {
@@ -158,12 +158,14 @@ function createOUI(config) {
158
158
  var DEFAULT_QUIET_MS = 250;
159
159
  var DEFAULT_SETTLE_TIMEOUT_MS = 5e3;
160
160
  var DEFAULT_DEDUPE_WINDOW = 500;
161
+ var DEFAULT_REANSWER_AFTER_MS = 8e3;
161
162
  var SETTLE_TICK_MS = 50;
162
163
  function createSurfaceRuntime(options = {}) {
163
164
  const announce = options.announce ?? true;
164
165
  const quietMs = options.settle?.quietMs ?? DEFAULT_QUIET_MS;
165
166
  const settleTimeoutMs = options.settle?.timeoutMs ?? DEFAULT_SETTLE_TIMEOUT_MS;
166
167
  const dedupeWindow = options.dedupeWindow ?? DEFAULT_DEDUPE_WINDOW;
168
+ const reanswerAfterMs = options.reanswerAfterMs ?? DEFAULT_REANSWER_AFTER_MS;
167
169
  let nextKey = 1;
168
170
  const entries = [];
169
171
  const observations = /* @__PURE__ */ new Map();
@@ -188,6 +190,8 @@ function createSurfaceRuntime(options = {}) {
188
190
  function acknowledged(requestId) {
189
191
  return ackFor(requestId).promise;
190
192
  }
193
+ const delivery = /* @__PURE__ */ new Map();
194
+ const answeredHash = /* @__PURE__ */ new Map();
191
195
  let lastChangeAt = Date.now();
192
196
  const grants = /* @__PURE__ */ new Map();
193
197
  async function approvalRefusal(request) {
@@ -196,7 +200,7 @@ function createSurfaceRuntime(options = {}) {
196
200
  return "it needs the user's approval, and the request carries none";
197
201
  let hash;
198
202
  try {
199
- hash = await chunk2AISUNMW_cjs.argsHash(request.params ?? {});
203
+ hash = await chunkLDECTDPU_cjs.argsHash(request.params ?? {});
200
204
  } catch (err) {
201
205
  return `its params cannot be checked against an approval: ${err instanceof Error ? err.message : String(err)}`;
202
206
  }
@@ -301,17 +305,20 @@ function createSurfaceRuntime(options = {}) {
301
305
  const finish = async (success, data, error) => {
302
306
  await acknowledged(requestId);
303
307
  const snap = snapshot();
304
- transport?.sendResult({
308
+ const known = answeredHash.get(requestId);
309
+ answer({
305
310
  requestId,
306
311
  success,
307
312
  ...data !== void 0 ? { data: toJsonSafe(data) } : {},
308
313
  ...error ? { error } : {},
309
314
  interim: false,
310
315
  timestamp: Date.now(),
311
- surfaces: snap.surfaces,
312
- observations: snap.observations
316
+ ...snap.surfacesHash !== known ? { surfaces: snap.surfaces } : {},
317
+ observations: snap.observations,
318
+ surfacesHash: snap.surfacesHash
313
319
  });
314
320
  acks.delete(requestId);
321
+ answeredHash.delete(requestId);
315
322
  };
316
323
  const observationId = `${surfaceId}:${actionId}:status`;
317
324
  const pollerKey = `${surfaceId}\0${actionId}`;
@@ -443,7 +450,7 @@ function createSurfaceRuntime(options = {}) {
443
450
  const declared = entry.surface.actions.find(
444
451
  (a) => a.id === request.actionId
445
452
  );
446
- const refusal = declared && chunk2AISUNMW_cjs.requiresApproval(declared.effect, declared.confirm) ? await approvalRefusal(request) : null;
453
+ const refusal = declared && chunkLDECTDPU_cjs.requiresApproval(declared.effect, declared.confirm) ? await approvalRefusal(request) : null;
447
454
  result = refusal ? {
448
455
  success: false,
449
456
  error: {
@@ -473,6 +480,7 @@ function createSurfaceRuntime(options = {}) {
473
480
  }
474
481
  const settled = await waitUntilSettled(startedAt);
475
482
  const snap = snapshot();
483
+ if (interim) answeredHash.set(request.requestId, snap.surfacesHash);
476
484
  return {
477
485
  requestId: request.requestId,
478
486
  success: result.success,
@@ -481,11 +489,39 @@ function createSurfaceRuntime(options = {}) {
481
489
  ...interim ? { interim: true } : {},
482
490
  durationMs: Date.now() - startedAt,
483
491
  timestamp: Date.now(),
484
- surfaces: snap.surfaces,
492
+ // Only what the agent runtime does not already hold (§7.3.4).
493
+ ...snap.surfacesHash !== request.knownSurfaces ? { surfaces: snap.surfaces } : {},
485
494
  observations: snap.observations,
495
+ surfacesHash: snap.surfacesHash,
486
496
  settled
487
497
  };
488
498
  }
499
+ function answer(result, onReceived) {
500
+ const steps = [
501
+ ["surfaces", "observations"],
502
+ ["surfaces", "observations", "data"]
503
+ ];
504
+ const send = (frame, step) => {
505
+ transport?.sendResult(frame, (ack) => {
506
+ if (ack.ok) {
507
+ onReceived?.();
508
+ return;
509
+ }
510
+ const omitted = steps[step];
511
+ if (!omitted) {
512
+ console.warn(
513
+ `[OUI] The answer to ${result.requestId} was refused even trimmed: ${ack.reason}`
514
+ );
515
+ return;
516
+ }
517
+ console.warn(
518
+ `[OUI] The answer to ${result.requestId} was refused (${ack.reason}); sending it without ${omitted.join(", ")}`
519
+ );
520
+ send(trimmed(result, ack.reason, omitted), step + 1);
521
+ });
522
+ };
523
+ send(result, 0);
524
+ }
489
525
  function execute(request) {
490
526
  const seen = results.get(request.requestId);
491
527
  if (seen) return seen;
@@ -494,6 +530,7 @@ function createSurfaceRuntime(options = {}) {
494
530
  while (results.size > dedupeWindow) {
495
531
  const oldest = results.keys().next().value;
496
532
  results.delete(oldest);
533
+ delivery.delete(oldest);
497
534
  }
498
535
  return pending;
499
536
  }
@@ -506,7 +543,11 @@ function createSurfaceRuntime(options = {}) {
506
543
  if (values && values.size > 0)
507
544
  obs[e.surface.id] = Object.fromEntries(values);
508
545
  }
509
- return { surfaces, observations: obs };
546
+ return {
547
+ surfaces,
548
+ observations: obs,
549
+ surfacesHash: chunkLDECTDPU_cjs.surfacesHash(surfaces)
550
+ };
510
551
  }
511
552
  function attach(next) {
512
553
  if (next === socket) return;
@@ -516,21 +557,36 @@ function createSurfaceRuntime(options = {}) {
516
557
  transport = null;
517
558
  socket = next;
518
559
  if (!next) return;
519
- const t = chunkXUX4XVP3_cjs.createWebSocketTransport(next, options.transport);
560
+ const t = chunk5UUJ3F7C_cjs.createWebSocketTransport(next, options.transport);
520
561
  transport = t;
521
562
  detachTransport.push(
522
- t.onAction((request) => {
563
+ t.onAction((request, receipt) => {
523
564
  if (options.accept && !options.accept(request)) {
524
565
  console.warn(
525
566
  `[OUI] Refused a request the client does not accept: ${request.surfaceId}.${request.actionId} (${request.requestId})`
526
567
  );
568
+ receipt?.({
569
+ ok: false,
570
+ reason: "this client does not accept requests now"
571
+ });
527
572
  return;
528
573
  }
574
+ receipt?.({ ok: true });
575
+ const id = request.requestId;
576
+ const prior = delivery.get(id);
577
+ if (prior && prior.state !== "sent") return;
578
+ if (prior && Date.now() - prior.at < reanswerAfterMs) return;
579
+ if (!prior) delivery.set(id, { state: "running", at: Date.now() });
529
580
  void execute(request).then((result) => {
530
- transport?.sendResult(result);
531
- const ack = ackFor(request.requestId);
581
+ if (results.has(id))
582
+ delivery.set(id, { state: "sent", at: Date.now() });
583
+ answer(result, () => {
584
+ if (results.has(id))
585
+ delivery.set(id, { state: "received", at: Date.now() });
586
+ });
587
+ const ack = ackFor(id);
532
588
  ack.resolve();
533
- if (!result.interim) acks.delete(request.requestId);
589
+ if (!result.interim) acks.delete(id);
534
590
  });
535
591
  })
536
592
  );
@@ -594,7 +650,7 @@ function createSurfaceRuntime(options = {}) {
594
650
  };
595
651
  },
596
652
  grantApproval(grant) {
597
- if (!grant || typeof grant.approvalId !== "string" || !grant.approvalId || typeof grant.argsHash !== "string" || !chunk2AISUNMW_cjs.ARGS_HASH_PATTERN.test(grant.argsHash) || !Number.isFinite(grant.expiresAt)) {
653
+ if (!grant || typeof grant.approvalId !== "string" || !grant.approvalId || typeof grant.argsHash !== "string" || !chunkLDECTDPU_cjs.ARGS_HASH_PATTERN.test(grant.argsHash) || !Number.isFinite(grant.expiresAt)) {
598
654
  throw new Error(
599
655
  "[OUI] grantApproval needs an approvalId, an args hash and an expiry"
600
656
  );
@@ -620,10 +676,18 @@ function createSurfaceRuntime(options = {}) {
620
676
  holds.clear();
621
677
  listeners.clear();
622
678
  acks.clear();
679
+ answeredHash.clear();
680
+ delivery.clear();
623
681
  grants.clear();
624
682
  }
625
683
  };
626
684
  }
685
+ function trimmed(result, reason, omitted) {
686
+ const out = { ...result };
687
+ for (const field of omitted) delete out[field];
688
+ out.delivery = { trimmed: true, reason, omitted: [...omitted] };
689
+ return out;
690
+ }
627
691
  function sleep(ms) {
628
692
  return new Promise((resolve) => setTimeout(resolve, ms));
629
693
  }
@@ -639,5 +703,5 @@ function toJsonSafe(value) {
639
703
  exports.createOUI = createOUI;
640
704
  exports.createSurfaceRuntime = createSurfaceRuntime;
641
705
  exports.defineSurface = defineSurface;
642
- //# sourceMappingURL=chunk-27CBVTA4.cjs.map
643
- //# sourceMappingURL=chunk-27CBVTA4.cjs.map
706
+ //# sourceMappingURL=chunk-AFNWLRKV.cjs.map
707
+ //# sourceMappingURL=chunk-AFNWLRKV.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/brand.ts","../src/core/define-surface.ts","../src/core/create-oui.ts","../src/core/surface-runtime.ts"],"names":["createWebSocketTransport","argsHash","requiresApproval","surfacesHash","ARGS_HASH_PATTERN"],"mappings":"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","file":"chunk-AFNWLRKV.cjs","sourcesContent":["/**\n * Nominal branding for values OUI must construct itself.\n *\n * Structural typing means any object with the right shape satisfies an\n * interface. That is how Closure Studio ended up hand-rolling OUI's transport:\n * `SocketLike` was importable, `OUITransport` was a plain interface, so an\n * integrator could satisfy every type without ever calling OUI. The result was\n * a second implementation of the wire — hardcoded namespace, re-declared\n * payload types on the server, and a dead `action:result` mapping alongside the\n * observation channel that already carried results.\n *\n * A unique symbol cannot be produced outside this module. Branding the types\n * OUI owns turns \"you should use our constructor\" into \"you cannot compile\n * without it\".\n */\n\ndeclare const OUI_BRAND: unique symbol;\n\n/** Marks a value as constructed by OUI itself. */\nexport interface OUIBranded<TKind extends string> {\n readonly [OUI_BRAND]: TKind;\n}\n\n/**\n * Attach the brand at runtime. The property does not exist at runtime — the\n * symbol is declare-only — so this is a type-level assertion with no cost.\n */\nexport function brand<TKind extends string, T>(\n value: T,\n): T & OUIBranded<TKind> {\n return value as T & OUIBranded<TKind>;\n}\n","import type {\n OUISurface,\n OUIAction,\n OUIObservation,\n OUIActivation,\n OUIActionPolling,\n JSONSchema,\n OUIEffectKind,\n} from \"../spec/index.js\";\nimport { brand, type OUIBranded } from \"./brand.js\";\n\n/**\n * Configuration for defining an OUI surface with handlers.\n * This is the \"integration file\" an app provides — it declares both\n * the schema (what the agent sees) and the implementation (what executes).\n */\nexport interface SurfaceDefinition<TContext = unknown> {\n id: string;\n name: string;\n description: string;\n version?: string;\n activation?: OUIActivation;\n actions: ActionDefinition<TContext>[];\n observations?: ObservationDefinition[];\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Polling config with an optional resolve handler.\n * The spec's OUIActionPolling is the manifest shape (no functions).\n * The core extends it with the resolve implementation for the runtime.\n */\nexport interface ActionPollingConfig<\n TContext = unknown,\n> extends OUIActionPolling {\n /**\n * Called on each poll interval. Receives the dispatch result from the handler\n * plus the current context. Return { done: true, data } to stop polling,\n * or { done: false, data } to continue.\n */\n resolve?: (\n dispatchResult: unknown,\n context: TContext,\n ) => Promise<{ done: boolean; data: unknown }>;\n}\n\n/**\n * An action definition includes both the schema (for the agent) and\n * the handler (for execution). This is the single source of truth —\n * no separate YAML, no separate listener, no drift possible.\n */\nexport interface ActionDefinition<TContext = unknown> {\n id: string;\n description: string;\n /** Its name as a person reads it, for a confirmation the user approves. */\n title?: string;\n /** What using it does; a `transaction` runs only on the user's approval of the exact request. */\n effect?: OUIEffectKind;\n input: JSONSchema;\n output?: JSONSchema;\n /** Destructive: it runs only on the user's approval of the exact request, unless it only reads. */\n confirm?: boolean;\n async?: boolean;\n\n /**\n * Polling/subscription config for async actions.\n * After the handler returns, the OUI runtime starts polling or subscribing\n * and pushes observation updates until the operation completes.\n * Extends the spec's OUIActionPolling with an optional resolve handler.\n */\n polling?: ActionPollingConfig<TContext>;\n\n usage?: string;\n preconditions?: string;\n estimatedDuration?: string;\n tags?: string[];\n\n /**\n * The handler that executes when the agent invokes this action.\n * Receives typed params and a context object (app-specific state/utilities).\n * Returns a result that the agent sees as the tool output.\n */\n handler: (\n params: Record<string, unknown>,\n context: TContext,\n ) => Promise<ActionHandlerResult>;\n}\n\nexport interface ActionHandlerResult {\n success: boolean;\n data?: unknown;\n error?: { code: string; message: string; details?: unknown };\n /** For async actions: metadata passed to the polling resolver */\n dispatchMeta?: Record<string, unknown>;\n}\n\nexport interface ObservationDefinition {\n id: string;\n description: string;\n schema: JSONSchema;\n /** Function that returns the current observation value */\n getValue?: () => unknown;\n}\n\n/**\n * Define an OUI surface — the single entry point for integrating\n * an application feature with the OUI protocol.\n *\n * This function validates the definition and returns a typed surface\n * object that can be registered with an agent runtime or transport layer.\n *\n * @example\n * ```typescript\n * const mySurface = defineSurface({\n * id: 'my-feature',\n * name: 'My Feature',\n * description: 'Does something cool',\n * actions: [\n * {\n * id: 'do_thing',\n * description: 'Does the thing',\n * input: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] },\n * handler: async (params) => {\n * const result = await doTheThing(params.name);\n * return { success: true, data: result };\n * },\n * },\n * ],\n * });\n * ```\n */\nexport function defineSurface<\n TContext = unknown,\n const TId extends string = string,\n>(\n definition: SurfaceDefinition<TContext> & { id: TId },\n): DefinedSurface<TContext> & { id: TId } {\n // Validate: no duplicate action IDs\n const actionIds = new Set<string>();\n for (const action of definition.actions) {\n if (actionIds.has(action.id)) {\n throw new Error(\n `[OUI] Duplicate action ID \"${action.id}\" in surface \"${definition.id}\"`,\n );\n }\n actionIds.add(action.id);\n }\n\n // Validate: no duplicate observation IDs\n if (definition.observations) {\n const obsIds = new Set<string>();\n for (const obs of definition.observations) {\n if (obsIds.has(obs.id)) {\n throw new Error(\n `[OUI] Duplicate observation ID \"${obs.id}\" in surface \"${definition.id}\"`,\n );\n }\n obsIds.add(obs.id);\n }\n }\n\n return brand<\"surface\", unknown>({\n ...definition,\n\n /** Extract the manifest (schema only, no handlers) for transmission to the agent runtime */\n toManifest(): OUISurface {\n return {\n id: definition.id,\n name: definition.name,\n description: definition.description,\n version: definition.version,\n activation: definition.activation,\n actions: definition.actions.map(actionToManifest),\n observations: definition.observations?.map(obsToManifest),\n metadata: definition.metadata,\n };\n },\n\n /** Execute an action by ID with the given params and context */\n async executeAction(\n actionId: string,\n params: Record<string, unknown>,\n context: TContext,\n ): Promise<ActionHandlerResult> {\n const action = definition.actions.find((a) => a.id === actionId);\n if (!action) {\n return {\n success: false,\n error: {\n code: \"ACTION_NOT_FOUND\",\n message: `Action \"${actionId}\" not found on surface \"${definition.id}\"`,\n },\n };\n }\n try {\n return await action.handler(params, context);\n } catch (err) {\n return {\n success: false,\n error: {\n code: \"ACTION_EXECUTION_ERROR\",\n message: err instanceof Error ? err.message : String(err),\n },\n };\n }\n },\n\n /** Get all action IDs */\n getActionIds(): string[] {\n return definition.actions.map((a) => a.id);\n },\n\n /** Get the polling config for an action (if async) */\n getPollingConfig(actionId: string): OUIActionPolling | undefined {\n const action = definition.actions.find((a) => a.id === actionId);\n return action?.polling;\n },\n }) as DefinedSurface<TContext> & { id: TId };\n}\n\n/** A fully defined surface with both manifest extraction and execution capabilities */\n/**\n * Branded so it can only come from `defineSurface`.\n *\n * Without the brand a plain object literal satisfies this interface\n * structurally, which is how an integrator can assemble a surface that never\n * ran defineSurface's duplicate-id checks and never produced a real manifest.\n */\nexport interface DefinedSurface<TContext = unknown>\n extends SurfaceDefinition<TContext>, OUIBranded<\"surface\"> {\n toManifest(): OUISurface;\n executeAction(\n actionId: string,\n params: Record<string, unknown>,\n context: TContext,\n ): Promise<ActionHandlerResult>;\n getActionIds(): string[];\n /** Get the polling config for an action (if async) */\n getPollingConfig(actionId: string): OUIActionPolling | undefined;\n}\n\n// ─── Internal helpers ────────────────────────────────────────────────────────\n\nfunction actionToManifest<T>(action: ActionDefinition<T>): OUIAction {\n return {\n id: action.id,\n description: action.description,\n ...(action.title !== undefined ? { title: action.title } : {}),\n ...(action.effect !== undefined ? { effect: action.effect } : {}),\n input: action.input,\n output: action.output,\n confirm: action.confirm,\n async: action.async,\n polling: action.polling,\n usage: action.usage,\n preconditions: action.preconditions,\n estimatedDuration: action.estimatedDuration,\n tags: action.tags,\n };\n}\n\nfunction obsToManifest(obs: ObservationDefinition): OUIObservation {\n return {\n id: obs.id,\n description: obs.description,\n schema: obs.schema,\n };\n}\n","/**\n * createOUI — a fixed set of surfaces announced over one socket.\n *\n * For a client whose surfaces come and go (a React app, where a page's\n * surfaces mount with the page), use `createSurfaceRuntime` instead: it keeps\n * the client's own record of what is mounted and answers every request.\n *\n * WHY THIS EXISTS\n *\n * OUI shipped a correct protocol and a correct transport, and its first\n * integrator used neither. studio-ui imported only the `SocketLike` TYPE from\n * oui-spec and rebuilt the wire by hand: a literal map of protocol types to\n * socket names, `oui:` hardcoded so the configurable namespace was unreachable,\n * payload interfaces re-declared on the server, and an `action:result` channel\n * mapped but never sent — duplicating the observation channel that already\n * carries results.\n *\n * Nothing was wrong with the spec. Nothing enforced it. Structural typing meant\n * every hand-rolled piece type-checked, and both ends agreed only by the\n * coincidence of matching string literals. Rename one and the other keeps\n * compiling and silently stops receiving.\n *\n * So the requirements are gated here:\n *\n * OUI owns the wire. The integrator provides a socket; it cannot provide a\n * transport, because `OUITransport` values are branded and only this module\n * brands them.\n *\n * OUI owns the result path. Every dispatch carries a requestId and is\n * answered on OUI's result channel. An integrator cannot add a parallel\n * channel because it cannot construct a transport to add one to.\n *\n * The integrator owns content. Surfaces, action schemas, observation schemas\n * and handlers all arrive through `defineSurface`, whose output is branded —\n * so a plain object shaped like a surface will not compile.\n *\n * Violations fail at compile time with a message naming the offending id.\n */\nimport type { OUITransport, OUITransportConfig } from \"../transport/types.js\";\nimport type { SocketLike } from \"../transport/websocket.js\";\nimport { createWebSocketTransport } from \"../transport/websocket.js\";\nimport type { DefinedSurface } from \"./define-surface.js\";\nimport { brand, type OUIBranded } from \"./brand.js\";\nimport type { OUIConfigError, ValidateSurfaceIds } from \"./validate.js\";\nimport type { OUISurface } from \"../spec/index.js\";\n\n/** A transport OUI constructed. Integrators cannot produce one. */\nexport type OwnedTransport = OUITransport & OUIBranded<\"transport\">;\n\n/** Surface ids as literal types, for the duplicate check. */\ntype SurfaceIds<T extends readonly DefinedSurface<never>[]> = {\n [K in keyof T]: T[K][\"id\"];\n};\n\nexport interface OUIConfig<TSurfaces extends readonly DefinedSurface<never>[]> {\n /**\n * The socket OUI will speak over. The integrator owns the connection —\n * auth, reconnection, lifecycle — and OUI owns what travels on it.\n */\n socket: SocketLike;\n\n /**\n * Surfaces produced by `defineSurface`. A plain object with the same shape\n * will not compile: DefinedSurface is branded.\n */\n surfaces: TSurfaces;\n\n /**\n * Wire configuration. `namespace` defaults to 'oui' and is the supported way\n * to change the event prefix — hardcoding it at the call site is what made\n * this option unreachable in the first integration.\n */\n transport?: Omit<OUITransportConfig, \"namespace\"> & { namespace?: string };\n}\n\n/** A live OUI instance. */\nexport interface OUIInstance {\n /** The transport OUI owns. Exposed for wiring, not for reimplementation. */\n readonly transport: OwnedTransport;\n\n /** Manifests for every registered surface, as the agent sees them. */\n readonly manifests: readonly OUISurface[];\n\n /** Register every surface and connect. */\n start(): Promise<void>;\n\n /**\n * Deregister every surface and detach OUI from the socket. The socket stays\n * connected: the integrator owns it, and other code may share it.\n */\n stop(): void;\n\n /** Look up a registered surface by id. */\n getSurface(id: string): DefinedSurface<never> | undefined;\n}\n\n/**\n * Instantiate OUI.\n *\n * `const` on the type parameter captures surface ids as literal types, which is\n * what allows duplicate detection to name the offending id rather than failing\n * with an unassignable-to-never error.\n */\nexport function createOUI<\n const TSurfaces extends readonly DefinedSurface<never>[],\n>(\n config: OUIConfig<TSurfaces> & ValidateSurfaceIds<SurfaceIds<TSurfaces>>,\n): OUIInstance {\n const {\n socket,\n surfaces,\n transport: transportConfig,\n } = config as OUIConfig<TSurfaces>;\n\n // Defensive, not decorative: the compile-time checks only bind when a caller\n // passes literals. A surface list assembled at runtime, or JS with no types\n // at all, reaches here unchecked.\n if (!socket) {\n throw new Error(\n \"[OUI] createOUI requires a socket. OUI owns the wire; the integrator owns the connection.\",\n );\n }\n if (!Array.isArray(surfaces) || surfaces.length === 0) {\n throw new Error(\"[OUI] createOUI requires at least one surface.\");\n }\n\n const seen = new Set<string>();\n for (const surface of surfaces) {\n if (seen.has(surface.id)) {\n throw new Error(\n `[OUI] Duplicate surface id \"${surface.id}\". Registration is keyed by id, so the second would replace the first.`,\n );\n }\n seen.add(surface.id);\n }\n\n const transport = brand<\"transport\", OUITransport>(\n createWebSocketTransport(socket, transportConfig),\n );\n\n const byId = new Map(surfaces.map((s) => [s.id, s] as const));\n\n return {\n transport,\n manifests: surfaces.map((s) => s.toManifest()),\n\n async start() {\n await transport.connect();\n for (const surface of surfaces) {\n transport.registerSurface(surface.toManifest());\n }\n },\n\n stop() {\n for (const surface of surfaces) {\n transport.deregisterSurface(surface.id);\n }\n transport.dispose();\n },\n\n getSurface(id) {\n return byId.get(id);\n },\n };\n}\n\n/** Re-exported so integrators can name the error type in tests. */\nexport type { OUIConfigError };\n","/**\n * The client-side surface runtime.\n *\n * Holds the surfaces a client has mounted, answers every action request with a\n * result, and produces the snapshot an agent runtime works from.\n *\n * WHY THIS EXISTS\n *\n * The first integration kept no client-side record of what was mounted. Each\n * surface hook registered itself with a server-side registry and listened for\n * dispatches on its own. Three things followed:\n *\n * - The registry was the only record of what the client could do, and it lost\n * entries: a dead socket's cleanup removed a live tab's registration, and the\n * browser never registered again. The agent then had no UI tools at all.\n * - Nothing answered a dispatch. The agent was told an action succeeded before\n * the client had run it, and never saw the page an action led to.\n * - Every hook listened independently, through two paths, so one dispatch ran\n * twice and nothing de-duplicated it.\n *\n * Here the client is the record. `snapshot()` is what the client can do right\n * now, and every request is run once, waited on until the UI settles, and\n * answered with its result and the snapshot after it.\n */\nimport type {\n OUIActionRequest,\n OUIActionResult,\n OUIApprovalGrant,\n OUIResultDelivery,\n OUISurface,\n OUISurfaceSnapshot,\n OUIObservationSnapshot,\n} from \"../spec/index.js\";\nimport {\n ARGS_HASH_PATTERN,\n argsHash,\n requiresApproval,\n} from \"../spec/approval.js\";\nimport { surfacesHash } from \"../spec/surfaces-hash.js\";\nimport type { OUITransport, OUITransportConfig } from \"../transport/types.js\";\nimport {\n createWebSocketTransport,\n type SocketLike,\n} from \"../transport/websocket.js\";\nimport type {\n ActionHandlerResult,\n ActionPollingConfig,\n DefinedSurface,\n} from \"./define-surface.js\";\n\n// ─── Options ─────────────────────────────────────────────────────────────────\n\nexport interface SettleOptions {\n /**\n * The UI counts as settled once nothing has mounted, unmounted or changed an\n * observation for this long, and no hold is open. Default 250 ms.\n */\n quietMs?: number;\n /** Give up waiting after this long and answer with `settled: false`. Default 5000 ms. */\n timeoutMs?: number;\n}\n\nexport interface SurfaceRuntimeOptions {\n /** The socket to answer requests on. Can be set or replaced later with `attach`. */\n socket?: SocketLike | null;\n\n /** Wire configuration for the transport the runtime builds on the socket. */\n transport?: OUITransportConfig;\n\n /**\n * Also announce registrations and observations over the transport, for agent\n * runtimes that keep a server-side registry. Default true.\n *\n * An agent runtime that takes the client's snapshot instead (sent with each\n * turn, and returned on every result) has no use for them: set false.\n */\n announce?: boolean;\n\n settle?: SettleOptions;\n\n /** How many answered request ids to remember, for de-duplication. Default 500. */\n dedupeWindow?: number;\n\n /**\n * Decides whether a request that arrived on the socket may run at all. A\n * refused request is neither run nor answered, and is logged.\n *\n * The server should be the only sender of action requests, but a client can\n * also check that a request is one it expects: for example, only while its\n * agent has a turn in progress. Requests passed to `execute` directly are\n * not checked; they come from the application itself.\n */\n accept?: (request: OUIActionRequest) => boolean;\n\n /**\n * A request sent again while its answer is on the way is not answered again\n * (§7.3.7): every copy of a large answer queues on the one socket, ahead of\n * the next request's answer. Only once the answer has gone this long without\n * the receiver acknowledging it — lost, or a receiver that does not\n * acknowledge — is a repeat answered again. Default 8000 ms.\n */\n reanswerAfterMs?: number;\n}\n\n// ─── Public types ────────────────────────────────────────────────────────────\n\nexport interface MountedSurface {\n readonly surfaceId: string;\n /** Record an observation value. A no-op once unmounted. */\n pushObservation(observationId: string, value: unknown): void;\n /** Remove this mount. Other mounts of the same surface id are unaffected. */\n unmount(): void;\n}\n\nexport interface SurfaceRuntime {\n /**\n * Mount a surface. `getContext` is read when an action runs, so handlers see\n * the latest state rather than the state at mount time.\n *\n * Mounting the same surface id twice is allowed (React StrictMode does it on\n * every mount); the most recent mount serves its actions.\n */\n mount<TContext>(\n surface: DefinedSurface<TContext>,\n getContext: () => TContext,\n ): MountedSurface;\n\n /** Answer requests arriving on this socket (null detaches). */\n attach(socket: SocketLike | null): void;\n\n /** What the client can do right now. */\n snapshot(): OUISurfaceSnapshot;\n\n /**\n * Run a request once and resolve with its result. A request id seen before\n * resolves with the first result instead of running again.\n */\n execute(request: OUIActionRequest): Promise<OUIActionResult>;\n\n /**\n * Keep the UI unsettled until the returned function is called. For work an\n * action starts that mounting and unmounting cannot show, such as a route's\n * code still loading or a page fetching the data it will display.\n */\n hold(): () => void;\n\n /**\n * Record that the user approved one request, here, through their own\n * confirmation (the agent runtime's approval store answered it to this tab).\n * An action that needs approval — a `transaction`, or a destructive write —\n * runs only on a request whose `approval` matches an unused, unexpired grant\n * for exactly its params. Each grant admits one request.\n */\n grantApproval(grant: OUIApprovalGrant): void;\n\n /** Called whenever the snapshot changes. */\n subscribe(listener: () => void): () => void;\n\n /** Stop polling, detach from the socket and forget every mount. */\n dispose(): void;\n}\n\n// ─── Implementation ──────────────────────────────────────────────────────────\n\ninterface Entry {\n key: number;\n surface: DefinedSurface<unknown>;\n getContext: () => unknown;\n}\n\nconst DEFAULT_QUIET_MS = 250;\nconst DEFAULT_SETTLE_TIMEOUT_MS = 5000;\nconst DEFAULT_DEDUPE_WINDOW = 500;\nconst DEFAULT_REANSWER_AFTER_MS = 8000;\nconst SETTLE_TICK_MS = 50;\n\nexport function createSurfaceRuntime(\n options: SurfaceRuntimeOptions = {},\n): SurfaceRuntime {\n const announce = options.announce ?? true;\n const quietMs = options.settle?.quietMs ?? DEFAULT_QUIET_MS;\n const settleTimeoutMs =\n options.settle?.timeoutMs ?? DEFAULT_SETTLE_TIMEOUT_MS;\n const dedupeWindow = options.dedupeWindow ?? DEFAULT_DEDUPE_WINDOW;\n const reanswerAfterMs = options.reanswerAfterMs ?? DEFAULT_REANSWER_AFTER_MS;\n\n let nextKey = 1;\n const entries: Entry[] = [];\n const observations = new Map<string, Map<string, unknown>>();\n const serializedObservations = new Map<string, string>();\n const holds = new Set<number>();\n let nextHold = 1;\n const results = new Map<string, Promise<OUIActionResult>>();\n const pollers = new Map<string, ReturnType<typeof setInterval>>();\n // How each running poll answers its request if it has to stop early.\n const abandon = new Map<\n string,\n (error: { code: string; message: string }) => void\n >();\n const listeners = new Set<() => void>();\n // Resolves once a request's first result has been handed to the transport.\n const acks = new Map<\n string,\n { promise: Promise<void>; resolve: () => void }\n >();\n function ackFor(requestId: string) {\n let ack = acks.get(requestId);\n if (!ack) {\n let resolve!: () => void;\n const promise = new Promise<void>((r) => (resolve = r));\n ack = { promise, resolve };\n acks.set(requestId, ack);\n }\n return ack;\n }\n function acknowledged(requestId: string): Promise<void> {\n return ackFor(requestId).promise;\n }\n // How each request's first answer is getting to the agent runtime: still\n // being worked out, sent (when), or acknowledged as received. A repeat of the\n // request is answered again only when the answer may have been lost (§7.3.7).\n const delivery = new Map<\n string,\n { state: \"running\" | \"sent\" | \"received\"; at: number }\n >();\n // The surfaces hash each request's first answer reported: an async action's\n // final answer repeats its surfaces only if they changed since then, since\n // the agent runtime waited for that first answer before waiting for this one.\n const answeredHash = new Map<string, string>();\n let lastChangeAt = Date.now();\n // Approvals the user gave in this tab, by approval id, until used or expired.\n const grants = new Map<string, OUIApprovalGrant>();\n\n /**\n * Why a request for an action that needs approval may not run, or null when\n * it may — in which case its grant is used up.\n */\n async function approvalRefusal(\n request: OUIActionRequest,\n ): Promise<string | null> {\n const approval = request.approval;\n if (!approval)\n return \"it needs the user's approval, and the request carries none\";\n let hash: string;\n try {\n hash = await argsHash(request.params ?? {});\n } catch (err) {\n return `its params cannot be checked against an approval: ${err instanceof Error ? err.message : String(err)}`;\n }\n // Checked and used up with no await in between, so one grant admits one request.\n const grant = grants.get(approval.approvalId);\n if (!grant) return \"this tab holds no unused approval for it\";\n if (Date.now() >= grant.expiresAt) {\n grants.delete(approval.approvalId);\n return \"its approval has expired\";\n }\n if (approval.argsHash !== grant.argsHash || hash !== grant.argsHash) {\n return \"its params are not the ones the user approved\";\n }\n grants.delete(approval.approvalId);\n return null;\n }\n\n let socket: SocketLike | null = null;\n let transport: OUITransport | null = null;\n let detachTransport: Array<() => void> = [];\n\n /**\n * `settles: false` for changes that are not the UI reacting to an action,\n * such as an async job's progress: those notify listeners but do not keep\n * an action's result waiting.\n */\n function changed(settles = true) {\n if (settles) lastChangeAt = Date.now();\n for (const l of [...listeners]) l();\n }\n\n function activeFor(surfaceId: string): Entry | undefined {\n for (let i = entries.length - 1; i >= 0; i--) {\n if (entries[i].surface.id === surfaceId) return entries[i];\n }\n return undefined;\n }\n\n /** Active entries, one per surface id, in the order each id was first mounted. */\n function activeEntries(): Entry[] {\n const seen = new Set<string>();\n const out: Entry[] = [];\n for (const e of entries) {\n if (seen.has(e.surface.id)) continue;\n seen.add(e.surface.id);\n out.push(activeFor(e.surface.id)!);\n }\n return out;\n }\n\n function announceSurface(entry: Entry) {\n if (!announce || !transport) return;\n transport.registerSurface(entry.surface.toManifest());\n const obs = observations.get(entry.surface.id);\n if (obs) {\n for (const [observationId, value] of obs) {\n transport.pushObservation({\n surfaceId: entry.surface.id,\n observationId,\n value,\n timestamp: Date.now(),\n });\n }\n }\n }\n\n function announceAll() {\n for (const e of activeEntries()) announceSurface(e);\n }\n\n function setObservation(\n surfaceId: string,\n observationId: string,\n value: unknown,\n settles = true,\n ) {\n const key = `${surfaceId}\\u0000${observationId}`;\n let serialized: string;\n try {\n serialized = JSON.stringify(value) ?? \"undefined\";\n } catch {\n serialized = String(value);\n }\n if (serializedObservations.get(key) === serialized) return;\n serializedObservations.set(key, serialized);\n\n let obs = observations.get(surfaceId);\n if (!obs) {\n obs = new Map();\n observations.set(surfaceId, obs);\n }\n obs.set(observationId, toJsonSafe(value));\n\n if (announce && transport) {\n transport.pushObservation({\n surfaceId,\n observationId,\n value,\n timestamp: Date.now(),\n });\n }\n changed(settles);\n }\n\n function forgetSurface(surfaceId: string) {\n observations.delete(surfaceId);\n for (const key of [...serializedObservations.keys()]) {\n if (key.startsWith(`${surfaceId}\\u0000`))\n serializedObservations.delete(key);\n }\n for (const [key, timer] of pollers) {\n if (key.startsWith(`${surfaceId}\\u0000`)) {\n clearInterval(timer);\n pollers.delete(key);\n // The request still gets its final answer: a poll that stops\n // without one leaves the agent waiting forever.\n abandon.get(key)?.({\n code: \"SURFACE_NOT_MOUNTED\",\n message:\n `Surface \"${surfaceId}\" left the page before its action finished, ` +\n \"so it is no longer being followed. Check what the page shows \" +\n \"before trying again.\",\n });\n abandon.delete(key);\n }\n }\n }\n\n // ─── Polling (async actions) ──────────────────────────────────────────────\n\n /**\n * Polls an async action to completion, publishing progress as an observation\n * and, when it ends, the request's final result (OUI spec §7.3: an async\n * action is acknowledged, then answered once more when it finishes).\n */\n function startPolling(\n requestId: string,\n surfaceId: string,\n actionId: string,\n polling: ActionPollingConfig<unknown>,\n dispatchResult: unknown,\n ) {\n const finish = async (\n success: boolean,\n data: unknown,\n error?: { code: string; message: string },\n ) => {\n // The acknowledgment goes first: a job can finish before the UI settles.\n await acknowledged(requestId);\n const snap = snapshot();\n const known = answeredHash.get(requestId);\n answer({\n requestId,\n success,\n ...(data !== undefined ? { data: toJsonSafe(data) } : {}),\n ...(error ? { error } : {}),\n interim: false,\n timestamp: Date.now(),\n ...(snap.surfacesHash !== known ? { surfaces: snap.surfaces } : {}),\n observations: snap.observations,\n surfacesHash: snap.surfacesHash,\n });\n acks.delete(requestId);\n answeredHash.delete(requestId);\n };\n\n // The observation id is the one surfaces have always published under.\n const observationId = `${surfaceId}:${actionId}:status`;\n const pollerKey = `${surfaceId}\\u0000${actionId}`;\n\n if (polling.subscribe) {\n setObservation(\n surfaceId,\n observationId,\n { status: \"dispatched\", dispatchResult, interim: true },\n false,\n );\n return;\n }\n if (!polling.resolve) {\n setObservation(\n surfaceId,\n observationId,\n { status: \"dispatched\", dispatchResult, interim: false },\n false,\n );\n return;\n }\n\n const existing = pollers.get(pollerKey);\n if (existing) {\n clearInterval(existing);\n pollers.delete(pollerKey);\n abandon.get(pollerKey)?.({\n code: \"SUPERSEDED\",\n message:\n `\"${actionId}\" was started again before this run finished, ` +\n \"so only the newer run is being followed.\",\n });\n abandon.delete(pollerKey);\n }\n\n setObservation(\n surfaceId,\n observationId,\n { status: \"polling\", dispatchResult, interim: true },\n false,\n );\n\n const maxAttempts = polling.maxAttempts ?? Infinity;\n const maxDuration = polling.maxDurationMs ?? Infinity;\n const startedAt = Date.now();\n let attempts = 0;\n\n const timer = setInterval(async () => {\n attempts++;\n if (attempts > maxAttempts || Date.now() - startedAt > maxDuration) {\n clearInterval(timer);\n pollers.delete(pollerKey);\n abandon.delete(pollerKey);\n setObservation(\n surfaceId,\n observationId,\n { status: \"timeout\", dispatchResult, interim: false },\n false,\n );\n void finish(false, undefined, {\n code: \"TIMEOUT\",\n message: `\"${actionId}\" did not finish within its polling limits.`,\n });\n return;\n }\n const entry = activeFor(surfaceId);\n if (!entry) {\n // forgetSurface normally gets here first; answer anyway.\n clearInterval(timer);\n pollers.delete(pollerKey);\n const gone = abandon.get(pollerKey);\n abandon.delete(pollerKey);\n gone?.({\n code: \"SURFACE_NOT_MOUNTED\",\n message:\n `Surface \"${surfaceId}\" left the page before \"${actionId}\" ` +\n \"finished, so it is no longer being followed. Check what the \" +\n \"page shows before trying again.\",\n });\n return;\n }\n // The surface may have remounted without this action (a control that is\n // disabled while its job runs, say). The job is still running, so keep\n // following it with the polling it started with.\n const action = entry.surface.actions.find((a) => a.id === actionId);\n const resolve = action?.polling?.resolve ?? polling.resolve;\n if (!resolve) return;\n try {\n const r = await resolve(dispatchResult, entry.getContext());\n setObservation(\n surfaceId,\n observationId,\n {\n ...(r.data as Record<string, unknown>),\n interim: !r.done,\n },\n false,\n );\n if (r.done) {\n clearInterval(timer);\n pollers.delete(pollerKey);\n abandon.delete(pollerKey);\n void finish(true, r.data);\n }\n } catch (err) {\n // A transient failure is reported, not fatal: keep polling.\n setObservation(\n surfaceId,\n observationId,\n { status: \"poll_error\", error: String(err), interim: true },\n false,\n );\n }\n }, polling.intervalMs);\n\n pollers.set(pollerKey, timer);\n abandon.set(pollerKey, (error) => void finish(false, undefined, error));\n }\n\n // ─── Settling ─────────────────────────────────────────────────────────────\n\n async function waitUntilSettled(since: number): Promise<boolean> {\n const deadline = since + settleTimeoutMs;\n for (;;) {\n const now = Date.now();\n const quietFor = now - Math.max(since, lastChangeAt);\n if (holds.size === 0 && quietFor >= quietMs) return true;\n if (now >= deadline) return false;\n await sleep(Math.min(SETTLE_TICK_MS, deadline - now));\n }\n }\n\n // ─── Execution ────────────────────────────────────────────────────────────\n\n async function run(request: OUIActionRequest): Promise<OUIActionResult> {\n const startedAt = Date.now();\n const entry = activeFor(request.surfaceId);\n\n let result: ActionHandlerResult;\n let interim = false;\n if (!entry) {\n const mounted = activeEntries().map((e) => e.surface.id);\n result = {\n success: false,\n error: {\n code: \"SURFACE_NOT_MOUNTED\",\n message:\n `Surface \"${request.surfaceId}\" is not on screen. ` +\n `Mounted surfaces: ${mounted.length ? mounted.join(\", \") : \"none\"}.`,\n },\n };\n } else {\n const declared = entry.surface.actions.find(\n (a) => a.id === request.actionId,\n );\n const refusal =\n declared && requiresApproval(declared.effect, declared.confirm)\n ? await approvalRefusal(request)\n : null;\n // executeAction turns a thrown handler into ACTION_EXECUTION_ERROR.\n result = refusal\n ? {\n success: false,\n error: {\n code: \"APPROVAL_REQUIRED\",\n message: `\"${request.actionId}\" was not run: ${refusal}.`,\n },\n }\n : await entry.surface.executeAction(\n request.actionId,\n request.params ?? {},\n entry.getContext(),\n );\n if (result.success) {\n const action = entry.surface.actions.find(\n (a) => a.id === request.actionId,\n );\n if (action?.polling) {\n interim = true;\n startPolling(\n request.requestId,\n entry.surface.id,\n action.id,\n action.polling,\n result.data ?? result.dispatchMeta,\n );\n }\n }\n }\n\n const settled = await waitUntilSettled(startedAt);\n const snap = snapshot();\n if (interim) answeredHash.set(request.requestId, snap.surfacesHash!);\n\n return {\n requestId: request.requestId,\n success: result.success,\n ...(result.data !== undefined ? { data: toJsonSafe(result.data) } : {}),\n ...(result.error\n ? { error: toJsonSafe(result.error) as OUIActionResult[\"error\"] }\n : {}),\n ...(interim ? { interim: true } : {}),\n durationMs: Date.now() - startedAt,\n timestamp: Date.now(),\n // Only what the agent runtime does not already hold (§7.3.4).\n ...(snap.surfacesHash !== request.knownSurfaces\n ? { surfaces: snap.surfaces }\n : {}),\n observations: snap.observations,\n surfacesHash: snap.surfacesHash,\n settled,\n };\n }\n\n // ─── Answering ────────────────────────────────────────────────────────────\n\n /**\n * Send an answer, and if the receiving side refuses it, send it again\n * trimmed, saying why (§7.3.6): first without the page's surfaces and\n * observations, then without the action's data too. An answer that is\n * refused and not sent again leaves the agent waiting until its deadline,\n * then reporting an action that ran as one that did not answer.\n */\n function answer(result: OUIActionResult, onReceived?: () => void) {\n const steps: Array<OUIResultDelivery[\"omitted\"]> = [\n [\"surfaces\", \"observations\"],\n [\"surfaces\", \"observations\", \"data\"],\n ];\n const send = (frame: OUIActionResult, step: number) => {\n transport?.sendResult(frame, (ack) => {\n if (ack.ok) {\n onReceived?.();\n return;\n }\n const omitted = steps[step];\n if (!omitted) {\n console.warn(\n `[OUI] The answer to ${result.requestId} was refused even trimmed: ${ack.reason}`,\n );\n return;\n }\n console.warn(\n `[OUI] The answer to ${result.requestId} was refused (${ack.reason}); sending it without ${omitted.join(\", \")}`,\n );\n send(trimmed(result, ack.reason, omitted), step + 1);\n });\n };\n send(result, 0);\n }\n\n function execute(request: OUIActionRequest): Promise<OUIActionResult> {\n const seen = results.get(request.requestId);\n if (seen) return seen;\n\n const pending = run(request);\n results.set(request.requestId, pending);\n while (results.size > dedupeWindow) {\n const oldest = results.keys().next().value as string;\n results.delete(oldest);\n delivery.delete(oldest);\n }\n return pending;\n }\n\n // ─── Snapshot ─────────────────────────────────────────────────────────────\n\n function snapshot(): OUISurfaceSnapshot {\n const surfaces: OUISurface[] = [];\n const obs: OUIObservationSnapshot = {};\n for (const e of activeEntries()) {\n surfaces.push(e.surface.toManifest());\n const values = observations.get(e.surface.id);\n if (values && values.size > 0)\n obs[e.surface.id] = Object.fromEntries(values);\n }\n return {\n surfaces,\n observations: obs,\n surfacesHash: surfacesHash(surfaces),\n };\n }\n\n // ─── Transport ────────────────────────────────────────────────────────────\n\n function attach(next: SocketLike | null) {\n if (next === socket) return;\n for (const off of detachTransport) off();\n detachTransport = [];\n transport?.dispose();\n transport = null;\n socket = next;\n if (!next) return;\n\n const t = createWebSocketTransport(next, options.transport);\n transport = t;\n\n detachTransport.push(\n t.onAction((request, receipt) => {\n if (options.accept && !options.accept(request)) {\n console.warn(\n `[OUI] Refused a request the client does not accept: ${request.surfaceId}.${request.actionId} (${request.requestId})`,\n );\n receipt?.({\n ok: false,\n reason: \"this client does not accept requests now\",\n });\n return;\n }\n // Received: the sender need not send it again (§7.3.7).\n receipt?.({ ok: true });\n const id = request.requestId;\n const prior = delivery.get(id);\n // A repeat while the answer is being worked out, or is on its way, or\n // has arrived, gets no second copy: copies of a large answer queue on\n // the one socket ahead of the next request's answer.\n if (prior && prior.state !== \"sent\") return;\n if (prior && Date.now() - prior.at < reanswerAfterMs) return;\n if (!prior) delivery.set(id, { state: \"running\", at: Date.now() });\n void execute(request).then((result) => {\n // Answer on whichever transport is live when the result is ready: a\n // reconnect in between keeps the same socket, so this still reaches\n // the runtime that asked.\n if (results.has(id))\n delivery.set(id, { state: \"sent\", at: Date.now() });\n answer(result, () => {\n if (results.has(id))\n delivery.set(id, { state: \"received\", at: Date.now() });\n });\n const ack = ackFor(id);\n ack.resolve();\n // Keep the gate only while a final result may still follow.\n if (!result.interim) acks.delete(id);\n });\n }),\n );\n\n if (announce) {\n // A server-side registry forgets a socket's surfaces when it drops, so\n // every (re)connection announces them again.\n detachTransport.push(\n t.onConnectionChange((connected) => {\n if (connected) announceAll();\n }),\n );\n if (t.connected) announceAll();\n }\n }\n\n if (options.socket) attach(options.socket);\n\n // ─── Mounting ─────────────────────────────────────────────────────────────\n\n function mount<TContext>(\n surface: DefinedSurface<TContext>,\n getContext: () => TContext,\n ): MountedSurface {\n const entry: Entry = {\n key: nextKey++,\n surface: surface as unknown as DefinedSurface<unknown>,\n getContext: getContext as () => unknown,\n };\n entries.push(entry);\n announceSurface(entry);\n changed();\n\n let mounted = true;\n return {\n surfaceId: surface.id,\n pushObservation(observationId, value) {\n // Only the mount serving the surface speaks for it.\n if (!mounted || activeFor(surface.id) !== entry) return;\n setObservation(surface.id, observationId, value);\n },\n unmount() {\n if (!mounted) return;\n mounted = false;\n const i = entries.indexOf(entry);\n if (i >= 0) entries.splice(i, 1);\n const replacement = activeFor(surface.id);\n if (replacement) {\n announceSurface(replacement);\n } else {\n forgetSurface(surface.id);\n if (announce && transport) transport.deregisterSurface(surface.id);\n }\n changed();\n },\n };\n }\n\n return {\n mount,\n attach,\n snapshot,\n execute,\n hold() {\n const id = nextHold++;\n holds.add(id);\n changed();\n let released = false;\n return () => {\n if (released) return;\n released = true;\n holds.delete(id);\n changed();\n };\n },\n grantApproval(grant) {\n if (\n !grant ||\n typeof grant.approvalId !== \"string\" ||\n !grant.approvalId ||\n typeof grant.argsHash !== \"string\" ||\n !ARGS_HASH_PATTERN.test(grant.argsHash) ||\n !Number.isFinite(grant.expiresAt)\n ) {\n throw new Error(\n \"[OUI] grantApproval needs an approvalId, an args hash and an expiry\",\n );\n }\n const now = Date.now();\n for (const [id, g] of grants) if (now >= g.expiresAt) grants.delete(id);\n grants.set(grant.approvalId, { ...grant });\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n dispose() {\n for (const timer of pollers.values()) clearInterval(timer);\n pollers.clear();\n abandon.clear();\n attach(null);\n entries.length = 0;\n observations.clear();\n serializedObservations.clear();\n holds.clear();\n listeners.clear();\n acks.clear();\n answeredHash.clear();\n delivery.clear();\n grants.clear();\n },\n };\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\n/** `result` without the fields `omitted` names, saying so and why (§7.3.6). */\nfunction trimmed(\n result: OUIActionResult,\n reason: string,\n omitted: OUIResultDelivery[\"omitted\"],\n): OUIActionResult {\n const out: OUIActionResult = { ...result };\n for (const field of omitted) delete out[field];\n out.delivery = { trimmed: true, reason, omitted: [...omitted] };\n return out;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Results and observations cross a wire as JSON. A handler returning something\n * that is not (a DOM node, a class instance with cycles) must not take the\n * result down with it.\n */\nfunction toJsonSafe(value: unknown): unknown {\n if (value === undefined) return undefined;\n try {\n return JSON.parse(JSON.stringify(value));\n } catch {\n return String(value);\n }\n}\n"]}