oui-spec 0.1.0 → 0.3.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.
- package/README.md +161 -104
- package/dist/{chunk-CVUUSPF4.js → chunk-BMCL2K74.js} +2 -2
- package/dist/chunk-BMCL2K74.js.map +1 -0
- package/dist/chunk-DCVVTP3V.cjs +155 -0
- package/dist/chunk-DCVVTP3V.cjs.map +1 -0
- package/dist/chunk-F3SKRAGU.cjs +98 -0
- package/dist/chunk-F3SKRAGU.cjs.map +1 -0
- package/dist/chunk-F3WKIRAU.js +153 -0
- package/dist/chunk-F3WKIRAU.js.map +1 -0
- package/dist/chunk-IIZ6HL2L.js +89 -0
- package/dist/chunk-IIZ6HL2L.js.map +1 -0
- package/dist/chunk-KNWGQRXL.cjs +567 -0
- package/dist/chunk-KNWGQRXL.cjs.map +1 -0
- package/dist/chunk-NYCJZQSP.js +92 -0
- package/dist/chunk-NYCJZQSP.js.map +1 -0
- package/dist/chunk-ROGKEMLL.cjs +91 -0
- package/dist/chunk-ROGKEMLL.cjs.map +1 -0
- package/dist/chunk-TRNVXAB5.js +563 -0
- package/dist/chunk-TRNVXAB5.js.map +1 -0
- package/dist/{chunk-3DCIL4FV.cjs → chunk-ZKM4XWAB.cjs} +2 -2
- package/dist/chunk-ZKM4XWAB.cjs.map +1 -0
- package/dist/core/index.cjs +13 -4
- package/dist/core/index.d.cts +123 -102
- package/dist/core/index.d.ts +123 -102
- package/dist/core/index.js +3 -2
- package/dist/index.cjs +31 -10
- package/dist/index.d.cts +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +5 -4
- package/dist/react/index.cjs +15 -3
- package/dist/react/index.d.cts +33 -50
- package/dist/react/index.d.ts +33 -50
- package/dist/react/index.js +1 -1
- package/dist/spec/index.cjs +2 -2
- package/dist/spec/index.d.cts +35 -7
- package/dist/spec/index.d.ts +35 -7
- package/dist/spec/index.js +1 -1
- package/dist/surface-runtime--2lZGB7Z.d.cts +241 -0
- package/dist/surface-runtime-Dj_nhd7r.d.ts +241 -0
- package/dist/transport/index.cjs +4 -3
- package/dist/transport/index.d.cts +4 -77
- package/dist/transport/index.d.ts +4 -77
- package/dist/transport/index.js +2 -1
- package/dist/websocket-YfWILdZ4.d.cts +96 -0
- package/dist/websocket-c5tIUWY5.d.ts +96 -0
- package/package.json +8 -3
- package/spec/OUI-SPEC-v0.1.md +229 -155
- package/dist/chunk-2ON5IEXB.cjs +0 -167
- package/dist/chunk-2ON5IEXB.cjs.map +0 -1
- package/dist/chunk-3DCIL4FV.cjs.map +0 -1
- package/dist/chunk-7EXSMPGR.js +0 -207
- package/dist/chunk-7EXSMPGR.js.map +0 -1
- package/dist/chunk-CVUUSPF4.js.map +0 -1
- package/dist/chunk-JO5LGOB6.js +0 -88
- package/dist/chunk-JO5LGOB6.js.map +0 -1
- package/dist/chunk-LEXIU2MH.cjs +0 -90
- package/dist/chunk-LEXIU2MH.cjs.map +0 -1
- package/dist/chunk-UIGRLZOX.js +0 -164
- package/dist/chunk-UIGRLZOX.js.map +0 -1
- package/dist/chunk-WZXUKJ7E.cjs +0 -210
- package/dist/chunk-WZXUKJ7E.cjs.map +0 -1
package/dist/chunk-LEXIU2MH.cjs
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// src/core/define-surface.ts
|
|
4
|
-
function defineSurface(definition) {
|
|
5
|
-
const actionIds = /* @__PURE__ */ new Set();
|
|
6
|
-
for (const action of definition.actions) {
|
|
7
|
-
if (actionIds.has(action.id)) {
|
|
8
|
-
throw new Error(`[OUI] Duplicate action ID "${action.id}" in surface "${definition.id}"`);
|
|
9
|
-
}
|
|
10
|
-
actionIds.add(action.id);
|
|
11
|
-
}
|
|
12
|
-
if (definition.observations) {
|
|
13
|
-
const obsIds = /* @__PURE__ */ new Set();
|
|
14
|
-
for (const obs of definition.observations) {
|
|
15
|
-
if (obsIds.has(obs.id)) {
|
|
16
|
-
throw new Error(`[OUI] Duplicate observation ID "${obs.id}" in surface "${definition.id}"`);
|
|
17
|
-
}
|
|
18
|
-
obsIds.add(obs.id);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return {
|
|
22
|
-
...definition,
|
|
23
|
-
/** Extract the manifest (schema only, no handlers) for transmission to the agent runtime */
|
|
24
|
-
toManifest() {
|
|
25
|
-
return {
|
|
26
|
-
id: definition.id,
|
|
27
|
-
name: definition.name,
|
|
28
|
-
description: definition.description,
|
|
29
|
-
version: definition.version,
|
|
30
|
-
activation: definition.activation,
|
|
31
|
-
actions: definition.actions.map(actionToManifest),
|
|
32
|
-
observations: definition.observations?.map(obsToManifest),
|
|
33
|
-
metadata: definition.metadata
|
|
34
|
-
};
|
|
35
|
-
},
|
|
36
|
-
/** Execute an action by ID with the given params and context */
|
|
37
|
-
async executeAction(actionId, params, context) {
|
|
38
|
-
const action = definition.actions.find((a) => a.id === actionId);
|
|
39
|
-
if (!action) {
|
|
40
|
-
return { success: false, error: { code: "ACTION_NOT_FOUND", message: `Action "${actionId}" not found on surface "${definition.id}"` } };
|
|
41
|
-
}
|
|
42
|
-
try {
|
|
43
|
-
return await action.handler(params, context);
|
|
44
|
-
} catch (err) {
|
|
45
|
-
return {
|
|
46
|
-
success: false,
|
|
47
|
-
error: {
|
|
48
|
-
code: "ACTION_EXECUTION_ERROR",
|
|
49
|
-
message: err instanceof Error ? err.message : String(err)
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
/** Get all action IDs */
|
|
55
|
-
getActionIds() {
|
|
56
|
-
return definition.actions.map((a) => a.id);
|
|
57
|
-
},
|
|
58
|
-
/** Get the polling config for an action (if async) */
|
|
59
|
-
getPollingConfig(actionId) {
|
|
60
|
-
const action = definition.actions.find((a) => a.id === actionId);
|
|
61
|
-
return action?.polling;
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
function actionToManifest(action) {
|
|
66
|
-
return {
|
|
67
|
-
id: action.id,
|
|
68
|
-
description: action.description,
|
|
69
|
-
input: action.input,
|
|
70
|
-
output: action.output,
|
|
71
|
-
confirm: action.confirm,
|
|
72
|
-
async: action.async,
|
|
73
|
-
polling: action.polling,
|
|
74
|
-
usage: action.usage,
|
|
75
|
-
preconditions: action.preconditions,
|
|
76
|
-
estimatedDuration: action.estimatedDuration,
|
|
77
|
-
tags: action.tags
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
function obsToManifest(obs) {
|
|
81
|
-
return {
|
|
82
|
-
id: obs.id,
|
|
83
|
-
description: obs.description,
|
|
84
|
-
schema: obs.schema
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
exports.defineSurface = defineSurface;
|
|
89
|
-
//# sourceMappingURL=chunk-LEXIU2MH.cjs.map
|
|
90
|
-
//# sourceMappingURL=chunk-LEXIU2MH.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/define-surface.ts"],"names":[],"mappings":"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","file":"chunk-LEXIU2MH.cjs","sourcesContent":["import type { OUISurface, OUIAction, OUIObservation, OUIActivation, OUIActionPolling, JSONSchema } from '../spec/index.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<TContext = unknown> 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?: (dispatchResult: unknown, context: TContext) => 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 input: JSONSchema;\n output?: JSONSchema;\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: (params: Record<string, unknown>, context: TContext) => 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<TContext = unknown>(\n definition: SurfaceDefinition<TContext>,\n): DefinedSurface<TContext> {\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(`[OUI] Duplicate action ID \"${action.id}\" in surface \"${definition.id}\"`);\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(`[OUI] Duplicate observation ID \"${obs.id}\" in surface \"${definition.id}\"`);\n }\n obsIds.add(obs.id);\n }\n }\n\n return {\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(actionId: string, params: Record<string, unknown>, context: TContext): Promise<ActionHandlerResult> {\n const action = definition.actions.find(a => a.id === actionId);\n if (!action) {\n return { success: false, error: { code: 'ACTION_NOT_FOUND', message: `Action \"${actionId}\" not found on surface \"${definition.id}\"` } };\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 };\n}\n\n/** A fully defined surface with both manifest extraction and execution capabilities */\nexport interface DefinedSurface<TContext = unknown> extends SurfaceDefinition<TContext> {\n toManifest(): OUISurface;\n executeAction(actionId: string, params: Record<string, unknown>, context: TContext): 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 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"]}
|
package/dist/chunk-UIGRLZOX.js
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import { useRef, useCallback, useEffect, useMemo } from 'react';
|
|
2
|
-
|
|
3
|
-
// src/react/use-surface.ts
|
|
4
|
-
function useSurface(options) {
|
|
5
|
-
const { surface, context, send, active = true } = options;
|
|
6
|
-
const contextRef = useRef(context);
|
|
7
|
-
contextRef.current = context;
|
|
8
|
-
const surfaceRef = useRef(surface);
|
|
9
|
-
surfaceRef.current = surface;
|
|
10
|
-
const sendRef = useRef(send);
|
|
11
|
-
sendRef.current = send;
|
|
12
|
-
const activePollers = useRef(/* @__PURE__ */ new Map());
|
|
13
|
-
const pushObservation = useCallback((observationId, value) => {
|
|
14
|
-
const update = {
|
|
15
|
-
surfaceId: surfaceRef.current.id,
|
|
16
|
-
observationId,
|
|
17
|
-
value,
|
|
18
|
-
timestamp: Date.now()
|
|
19
|
-
};
|
|
20
|
-
sendRef.current({ type: "observation:update", payload: update });
|
|
21
|
-
}, []);
|
|
22
|
-
const startPolling = useCallback((actionId, pollingConfig, dispatchResult) => {
|
|
23
|
-
const observationId = `${surfaceRef.current.id}:${actionId}:status`;
|
|
24
|
-
let attempts = 0;
|
|
25
|
-
const maxAttempts = pollingConfig.maxAttempts ?? Infinity;
|
|
26
|
-
const startTime = Date.now();
|
|
27
|
-
const maxDuration = pollingConfig.maxDurationMs ?? Infinity;
|
|
28
|
-
if (pollingConfig.subscribe) {
|
|
29
|
-
pushObservation(observationId, { status: "dispatched", dispatchResult, interim: true });
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
if (!pollingConfig.resolve) {
|
|
33
|
-
pushObservation(observationId, { status: "dispatched", dispatchResult, interim: false });
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
pushObservation(observationId, { status: "polling", dispatchResult, interim: true });
|
|
37
|
-
const timer = setInterval(async () => {
|
|
38
|
-
attempts++;
|
|
39
|
-
const elapsed = Date.now() - startTime;
|
|
40
|
-
if (attempts > maxAttempts || elapsed > maxDuration) {
|
|
41
|
-
clearInterval(timer);
|
|
42
|
-
activePollers.current.delete(actionId);
|
|
43
|
-
pushObservation(observationId, { status: "timeout", dispatchResult, interim: false });
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
try {
|
|
47
|
-
const action = surfaceRef.current.actions.find((a) => a.id === actionId);
|
|
48
|
-
if (action?.polling?.resolve) {
|
|
49
|
-
const result = await action.polling.resolve(dispatchResult, contextRef.current);
|
|
50
|
-
pushObservation(observationId, { ...result.data, interim: !result.done });
|
|
51
|
-
if (result.done) {
|
|
52
|
-
clearInterval(timer);
|
|
53
|
-
activePollers.current.delete(actionId);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
} catch (err) {
|
|
57
|
-
pushObservation(observationId, { status: "poll_error", error: String(err), interim: true });
|
|
58
|
-
}
|
|
59
|
-
}, pollingConfig.intervalMs);
|
|
60
|
-
activePollers.current.set(actionId, timer);
|
|
61
|
-
}, [pushObservation]);
|
|
62
|
-
const clearAllPollers = useCallback(() => {
|
|
63
|
-
for (const [, timer] of activePollers.current) {
|
|
64
|
-
clearInterval(timer);
|
|
65
|
-
}
|
|
66
|
-
activePollers.current.clear();
|
|
67
|
-
}, []);
|
|
68
|
-
useEffect(() => {
|
|
69
|
-
if (!active) {
|
|
70
|
-
send({
|
|
71
|
-
type: "surface:deregister",
|
|
72
|
-
payload: { surfaceId: surface.id, timestamp: Date.now() }
|
|
73
|
-
});
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
send({
|
|
77
|
-
type: "surface:register",
|
|
78
|
-
payload: {
|
|
79
|
-
surface: surface.toManifest(),
|
|
80
|
-
timestamp: Date.now()
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
return () => {
|
|
84
|
-
clearAllPollers();
|
|
85
|
-
send({
|
|
86
|
-
type: "surface:deregister",
|
|
87
|
-
payload: { surfaceId: surface.id, timestamp: Date.now() }
|
|
88
|
-
});
|
|
89
|
-
};
|
|
90
|
-
}, [surface.id, active, send, clearAllPollers]);
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
return () => {
|
|
93
|
-
clearAllPollers();
|
|
94
|
-
};
|
|
95
|
-
}, [clearAllPollers]);
|
|
96
|
-
const handleActionRequest = useCallback(async (request) => {
|
|
97
|
-
if (request.surfaceId !== surfaceRef.current.id) return;
|
|
98
|
-
const { actionId, params } = request;
|
|
99
|
-
const observationId = `${surfaceRef.current.id}:${actionId}:status`;
|
|
100
|
-
let result;
|
|
101
|
-
try {
|
|
102
|
-
result = await surfaceRef.current.executeAction(actionId, params, contextRef.current);
|
|
103
|
-
} catch (err) {
|
|
104
|
-
pushObservation(observationId, {
|
|
105
|
-
status: "error",
|
|
106
|
-
error: err instanceof Error ? err.message : String(err),
|
|
107
|
-
interim: false
|
|
108
|
-
});
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
pushObservation(observationId, {
|
|
112
|
-
status: result.success ? "dispatched" : "error",
|
|
113
|
-
data: result.data,
|
|
114
|
-
error: result.error,
|
|
115
|
-
interim: !!result.success
|
|
116
|
-
});
|
|
117
|
-
if (result.success) {
|
|
118
|
-
const action = surfaceRef.current.actions.find((a) => a.id === actionId);
|
|
119
|
-
if (action?.polling) {
|
|
120
|
-
startPolling(actionId, action.polling, result.data ?? result.dispatchMeta);
|
|
121
|
-
} else {
|
|
122
|
-
pushObservation(observationId, {
|
|
123
|
-
status: "complete",
|
|
124
|
-
data: result.data,
|
|
125
|
-
interim: false
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}, [pushObservation, startPolling]);
|
|
130
|
-
return useMemo(() => ({
|
|
131
|
-
handleActionRequest,
|
|
132
|
-
surfaceId: surface.id,
|
|
133
|
-
manifest: surface.toManifest(),
|
|
134
|
-
/** Manually stop polling for a specific action */
|
|
135
|
-
stopPolling: (actionId) => {
|
|
136
|
-
const timer = activePollers.current.get(actionId);
|
|
137
|
-
if (timer) {
|
|
138
|
-
clearInterval(timer);
|
|
139
|
-
activePollers.current.delete(actionId);
|
|
140
|
-
}
|
|
141
|
-
},
|
|
142
|
-
/** Stop all active pollers */
|
|
143
|
-
stopAllPolling: clearAllPollers
|
|
144
|
-
}), [handleActionRequest, surface, clearAllPollers]);
|
|
145
|
-
}
|
|
146
|
-
function useObservation(surfaceId, observationId, value, send) {
|
|
147
|
-
const prevValueRef = useRef("");
|
|
148
|
-
useEffect(() => {
|
|
149
|
-
const serialized = JSON.stringify(value);
|
|
150
|
-
if (serialized === prevValueRef.current) return;
|
|
151
|
-
prevValueRef.current = serialized;
|
|
152
|
-
const update = {
|
|
153
|
-
surfaceId,
|
|
154
|
-
observationId,
|
|
155
|
-
value,
|
|
156
|
-
timestamp: Date.now()
|
|
157
|
-
};
|
|
158
|
-
send({ type: "observation:update", payload: update });
|
|
159
|
-
}, [surfaceId, observationId, value, send]);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export { useObservation, useSurface };
|
|
163
|
-
//# sourceMappingURL=chunk-UIGRLZOX.js.map
|
|
164
|
-
//# sourceMappingURL=chunk-UIGRLZOX.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react/use-surface.ts"],"names":[],"mappings":"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","file":"chunk-UIGRLZOX.js","sourcesContent":["import { useEffect, useRef, useCallback, useMemo } from 'react';\nimport type { DefinedSurface, ActionHandlerResult, ActionPollingConfig } from '../core/index.js';\nimport type { OUIActionRequest, OUIObservationUpdate } from '../spec/index.js';\n\n/**\n * Configuration for the useSurface hook.\n */\nexport interface UseSurfaceOptions<TContext> {\n /** The defined surface (from defineSurface()) */\n surface: DefinedSurface<TContext>;\n\n /** The context passed to action handlers (app state, utilities, etc.) */\n context: TContext;\n\n /** Transport send function — how to send protocol events to the agent runtime */\n send: (event: { type: string; payload: unknown }) => void;\n\n /** Whether the surface is currently active (respects activation conditions) */\n active?: boolean;\n}\n\n/**\n * useSurface — registers an OUI surface with the agent runtime and handles\n * incoming action requests by executing them locally and pushing observation\n * updates. Actions are dispatched one-way (no request/response correlation).\n *\n * After an action handler executes, if the action has a polling config, the\n * hook starts a polling loop that pushes observation updates until the\n * operation completes or times out.\n *\n * @example\n * ```tsx\n * function DataVizPage() {\n * const { state, updateState, goToStep } = useDataVizWizard();\n *\n * useSurface({\n * surface: datavizSurface,\n * context: { state, updateState, goToStep },\n * send: agentTransport.send,\n * active: true,\n * });\n *\n * return <DataVizWizard />;\n * }\n * ```\n */\nexport function useSurface<TContext>(options: UseSurfaceOptions<TContext>) {\n const { surface, context, send, active = true } = options;\n const contextRef = useRef(context);\n contextRef.current = context;\n\n const surfaceRef = useRef(surface);\n surfaceRef.current = surface;\n\n const sendRef = useRef(send);\n sendRef.current = send;\n\n // Track active polling intervals for cleanup\n const activePollers = useRef<Map<string, ReturnType<typeof setInterval>>>(new Map());\n\n // Push an observation update to the agent runtime\n const pushObservation = useCallback((observationId: string, value: unknown) => {\n const update: OUIObservationUpdate = {\n surfaceId: surfaceRef.current.id,\n observationId,\n value,\n timestamp: Date.now(),\n };\n sendRef.current({ type: 'observation:update', payload: update });\n }, []);\n\n // Start the polling runtime for an async action\n const startPolling = useCallback((\n actionId: string,\n pollingConfig: ActionPollingConfig<TContext>,\n dispatchResult: unknown,\n ) => {\n const observationId = `${surfaceRef.current.id}:${actionId}:status`;\n let attempts = 0;\n const maxAttempts = pollingConfig.maxAttempts ?? Infinity;\n const startTime = Date.now();\n const maxDuration = pollingConfig.maxDurationMs ?? Infinity;\n\n // Subscribe mode — transport layer handles events, just push initial state\n if (pollingConfig.subscribe) {\n pushObservation(observationId, { status: 'dispatched', dispatchResult, interim: true });\n return;\n }\n\n // Polling mode — requires a resolve function\n if (!pollingConfig.resolve) {\n pushObservation(observationId, { status: 'dispatched', dispatchResult, interim: false });\n return;\n }\n\n // Push initial dispatched state\n pushObservation(observationId, { status: 'polling', dispatchResult, interim: true });\n\n const timer = setInterval(async () => {\n attempts++;\n const elapsed = Date.now() - startTime;\n\n if (attempts > maxAttempts || elapsed > maxDuration) {\n clearInterval(timer);\n activePollers.current.delete(actionId);\n pushObservation(observationId, { status: 'timeout', dispatchResult, interim: false });\n return;\n }\n\n try {\n const action = surfaceRef.current.actions.find(a => a.id === actionId);\n if (action?.polling?.resolve) {\n const result = await action.polling.resolve(dispatchResult, contextRef.current);\n pushObservation(observationId, { ...result.data as Record<string, unknown>, interim: !result.done });\n if (result.done) {\n clearInterval(timer);\n activePollers.current.delete(actionId);\n }\n }\n } catch (err) {\n // Don't stop polling on transient errors — push error state and continue\n pushObservation(observationId, { status: 'poll_error', error: String(err), interim: true });\n }\n }, pollingConfig.intervalMs);\n\n activePollers.current.set(actionId, timer);\n }, [pushObservation]);\n\n // Clear all active pollers\n const clearAllPollers = useCallback(() => {\n for (const [, timer] of activePollers.current) {\n clearInterval(timer);\n }\n activePollers.current.clear();\n }, []);\n\n // Register surface when it becomes active\n useEffect(() => {\n if (!active) {\n send({\n type: 'surface:deregister',\n payload: { surfaceId: surface.id, timestamp: Date.now() },\n });\n return;\n }\n\n send({\n type: 'surface:register',\n payload: {\n surface: surface.toManifest(),\n timestamp: Date.now(),\n },\n });\n\n return () => {\n // Clean up all active pollers on deregister\n clearAllPollers();\n send({\n type: 'surface:deregister',\n payload: { surfaceId: surface.id, timestamp: Date.now() },\n });\n };\n }, [surface.id, active, send, clearAllPollers]);\n\n // Clean up pollers on unmount (safety net)\n useEffect(() => {\n return () => {\n clearAllPollers();\n };\n }, [clearAllPollers]);\n\n // Handler for incoming action requests — fully async, no response correlation\n const handleActionRequest = useCallback(async (request: OUIActionRequest) => {\n if (request.surfaceId !== surfaceRef.current.id) return;\n\n const { actionId, params } = request;\n const observationId = `${surfaceRef.current.id}:${actionId}:status`;\n\n // Execute the handler locally\n let result: ActionHandlerResult;\n try {\n result = await surfaceRef.current.executeAction(actionId, params, contextRef.current);\n } catch (err) {\n // Execution failed — push error observation\n pushObservation(observationId, {\n status: 'error',\n error: err instanceof Error ? err.message : String(err),\n interim: false,\n });\n return;\n }\n\n // Push observation with dispatch result immediately\n pushObservation(observationId, {\n status: result.success ? 'dispatched' : 'error',\n data: result.data,\n error: result.error,\n interim: !!result.success,\n });\n\n // If action has polling config and dispatch succeeded, start polling runtime\n if (result.success) {\n const action = surfaceRef.current.actions.find(a => a.id === actionId);\n if (action?.polling) {\n startPolling(actionId, action.polling, result.data ?? result.dispatchMeta);\n } else {\n // Non-async action — mark as complete (not interim)\n pushObservation(observationId, {\n status: 'complete',\n data: result.data,\n interim: false,\n });\n }\n }\n }, [pushObservation, startPolling]);\n\n // Expose the handler for the transport layer to call\n return useMemo(() => ({\n handleActionRequest,\n surfaceId: surface.id,\n manifest: surface.toManifest(),\n /** Manually stop polling for a specific action */\n stopPolling: (actionId: string) => {\n const timer = activePollers.current.get(actionId);\n if (timer) {\n clearInterval(timer);\n activePollers.current.delete(actionId);\n }\n },\n /** Stop all active pollers */\n stopAllPolling: clearAllPollers,\n }), [handleActionRequest, surface, clearAllPollers]);\n}\n\n/**\n * Helper to push an observation update to the agent runtime.\n */\nexport function useObservation(\n surfaceId: string,\n observationId: string,\n value: unknown,\n send: (event: { type: string; payload: unknown }) => void,\n) {\n const prevValueRef = useRef<string>('');\n\n useEffect(() => {\n const serialized = JSON.stringify(value);\n if (serialized === prevValueRef.current) return;\n prevValueRef.current = serialized;\n\n const update: OUIObservationUpdate = {\n surfaceId,\n observationId,\n value,\n timestamp: Date.now(),\n };\n\n send({ type: 'observation:update', payload: update });\n }, [surfaceId, observationId, value, send]);\n}\n"]}
|
package/dist/chunk-WZXUKJ7E.cjs
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// src/transport/websocket.ts
|
|
4
|
-
function createWebSocketTransport(socket, config) {
|
|
5
|
-
const ns = config?.namespace ?? "oui";
|
|
6
|
-
const buffer = [];
|
|
7
|
-
const maxBuffer = config?.maxBufferSize ?? 100;
|
|
8
|
-
const shouldBuffer = config?.bufferWhileDisconnected ?? true;
|
|
9
|
-
let connected = socket.connected ?? false;
|
|
10
|
-
const connectionHandlers = [];
|
|
11
|
-
socket.on("connect", () => {
|
|
12
|
-
connected = true;
|
|
13
|
-
connectionHandlers.forEach((h) => h(true));
|
|
14
|
-
if (shouldBuffer) {
|
|
15
|
-
while (buffer.length > 0) {
|
|
16
|
-
const msg = buffer.shift();
|
|
17
|
-
socket.emit(msg.event, msg.data);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
socket.on("disconnect", () => {
|
|
22
|
-
connected = false;
|
|
23
|
-
connectionHandlers.forEach((h) => h(false));
|
|
24
|
-
});
|
|
25
|
-
function emit(event, data) {
|
|
26
|
-
if (connected) {
|
|
27
|
-
socket.emit(event, data);
|
|
28
|
-
} else if (shouldBuffer && buffer.length < maxBuffer) {
|
|
29
|
-
buffer.push({ event, data });
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return {
|
|
33
|
-
// ─── Dispatch Channel ───────────────────────────────────────
|
|
34
|
-
dispatch(surfaceId, actionId, params) {
|
|
35
|
-
emit(`${ns}:dispatch`, { surfaceId, actionId, params, timestamp: Date.now() });
|
|
36
|
-
},
|
|
37
|
-
onAction(handler) {
|
|
38
|
-
const listener = (data) => {
|
|
39
|
-
handler(data.surfaceId, data.actionId, data.params);
|
|
40
|
-
};
|
|
41
|
-
socket.on(`${ns}:dispatch`, listener);
|
|
42
|
-
return () => socket.off(`${ns}:dispatch`, listener);
|
|
43
|
-
},
|
|
44
|
-
// ─── Observation Channel ────────────────────────────────────
|
|
45
|
-
pushObservation(update) {
|
|
46
|
-
emit(`${ns}:observation`, update);
|
|
47
|
-
},
|
|
48
|
-
onObservation(handler) {
|
|
49
|
-
const listener = (data) => handler(data);
|
|
50
|
-
socket.on(`${ns}:observation`, listener);
|
|
51
|
-
return () => socket.off(`${ns}:observation`, listener);
|
|
52
|
-
},
|
|
53
|
-
// ─── Surface Lifecycle ──────────────────────────────────────
|
|
54
|
-
registerSurface(surface) {
|
|
55
|
-
emit(`${ns}:surface:register`, { surface, timestamp: Date.now() });
|
|
56
|
-
},
|
|
57
|
-
deregisterSurface(surfaceId) {
|
|
58
|
-
emit(`${ns}:surface:deregister`, { surfaceId, timestamp: Date.now() });
|
|
59
|
-
},
|
|
60
|
-
onSurfaceRegister(handler) {
|
|
61
|
-
const listener = (data) => handler(data.surface);
|
|
62
|
-
socket.on(`${ns}:surface:register`, listener);
|
|
63
|
-
return () => socket.off(`${ns}:surface:register`, listener);
|
|
64
|
-
},
|
|
65
|
-
onSurfaceDeregister(handler) {
|
|
66
|
-
const listener = (data) => handler(data.surfaceId);
|
|
67
|
-
socket.on(`${ns}:surface:deregister`, listener);
|
|
68
|
-
return () => socket.off(`${ns}:surface:deregister`, listener);
|
|
69
|
-
},
|
|
70
|
-
// ─── Connection ─────────────────────────────────────────────
|
|
71
|
-
get connected() {
|
|
72
|
-
return connected;
|
|
73
|
-
},
|
|
74
|
-
async connect() {
|
|
75
|
-
if (connected) return;
|
|
76
|
-
return new Promise((resolve, reject) => {
|
|
77
|
-
const timeout = setTimeout(() => {
|
|
78
|
-
reject(new Error(`OUI transport connect timeout (${config?.connectTimeoutMs ?? 1e4}ms)`));
|
|
79
|
-
}, config?.connectTimeoutMs ?? 1e4);
|
|
80
|
-
socket.once("connect", () => {
|
|
81
|
-
clearTimeout(timeout);
|
|
82
|
-
resolve();
|
|
83
|
-
});
|
|
84
|
-
if (typeof socket.connect === "function") {
|
|
85
|
-
socket.connect();
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
},
|
|
89
|
-
disconnect() {
|
|
90
|
-
if (typeof socket.disconnect === "function") {
|
|
91
|
-
socket.disconnect();
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
onConnectionChange(handler) {
|
|
95
|
-
connectionHandlers.push(handler);
|
|
96
|
-
return () => {
|
|
97
|
-
const idx = connectionHandlers.indexOf(handler);
|
|
98
|
-
if (idx >= 0) connectionHandlers.splice(idx, 1);
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// src/transport/direct.ts
|
|
105
|
-
function createDirectTransportPair() {
|
|
106
|
-
const actionHandlers = [];
|
|
107
|
-
const observationHandlers = [];
|
|
108
|
-
const surfaceRegisterHandlers = [];
|
|
109
|
-
const surfaceDeregisterHandlers = [];
|
|
110
|
-
const server = {
|
|
111
|
-
dispatch(surfaceId, actionId, params) {
|
|
112
|
-
actionHandlers.forEach((h) => h(surfaceId, actionId, params));
|
|
113
|
-
},
|
|
114
|
-
onAction() {
|
|
115
|
-
return () => {
|
|
116
|
-
};
|
|
117
|
-
},
|
|
118
|
-
// Server doesn't receive dispatches
|
|
119
|
-
pushObservation() {
|
|
120
|
-
},
|
|
121
|
-
// Server doesn't push observations
|
|
122
|
-
onObservation(handler) {
|
|
123
|
-
observationHandlers.push(handler);
|
|
124
|
-
return () => {
|
|
125
|
-
const i = observationHandlers.indexOf(handler);
|
|
126
|
-
if (i >= 0) observationHandlers.splice(i, 1);
|
|
127
|
-
};
|
|
128
|
-
},
|
|
129
|
-
registerSurface() {
|
|
130
|
-
},
|
|
131
|
-
deregisterSurface() {
|
|
132
|
-
},
|
|
133
|
-
onSurfaceRegister(handler) {
|
|
134
|
-
surfaceRegisterHandlers.push(handler);
|
|
135
|
-
return () => {
|
|
136
|
-
const i = surfaceRegisterHandlers.indexOf(handler);
|
|
137
|
-
if (i >= 0) surfaceRegisterHandlers.splice(i, 1);
|
|
138
|
-
};
|
|
139
|
-
},
|
|
140
|
-
onSurfaceDeregister(handler) {
|
|
141
|
-
surfaceDeregisterHandlers.push(handler);
|
|
142
|
-
return () => {
|
|
143
|
-
const i = surfaceDeregisterHandlers.indexOf(handler);
|
|
144
|
-
if (i >= 0) surfaceDeregisterHandlers.splice(i, 1);
|
|
145
|
-
};
|
|
146
|
-
},
|
|
147
|
-
get connected() {
|
|
148
|
-
return true;
|
|
149
|
-
},
|
|
150
|
-
async connect() {
|
|
151
|
-
},
|
|
152
|
-
disconnect() {
|
|
153
|
-
},
|
|
154
|
-
onConnectionChange() {
|
|
155
|
-
return () => {
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
const client = {
|
|
160
|
-
dispatch() {
|
|
161
|
-
},
|
|
162
|
-
// Client doesn't dispatch
|
|
163
|
-
onAction(handler) {
|
|
164
|
-
actionHandlers.push(handler);
|
|
165
|
-
return () => {
|
|
166
|
-
const i = actionHandlers.indexOf(handler);
|
|
167
|
-
if (i >= 0) actionHandlers.splice(i, 1);
|
|
168
|
-
};
|
|
169
|
-
},
|
|
170
|
-
pushObservation(update) {
|
|
171
|
-
observationHandlers.forEach((h) => h(update));
|
|
172
|
-
},
|
|
173
|
-
onObservation() {
|
|
174
|
-
return () => {
|
|
175
|
-
};
|
|
176
|
-
},
|
|
177
|
-
// Client doesn't receive observations
|
|
178
|
-
registerSurface(surface) {
|
|
179
|
-
surfaceRegisterHandlers.forEach((h) => h(surface));
|
|
180
|
-
},
|
|
181
|
-
deregisterSurface(surfaceId) {
|
|
182
|
-
surfaceDeregisterHandlers.forEach((h) => h(surfaceId));
|
|
183
|
-
},
|
|
184
|
-
onSurfaceRegister() {
|
|
185
|
-
return () => {
|
|
186
|
-
};
|
|
187
|
-
},
|
|
188
|
-
onSurfaceDeregister() {
|
|
189
|
-
return () => {
|
|
190
|
-
};
|
|
191
|
-
},
|
|
192
|
-
get connected() {
|
|
193
|
-
return true;
|
|
194
|
-
},
|
|
195
|
-
async connect() {
|
|
196
|
-
},
|
|
197
|
-
disconnect() {
|
|
198
|
-
},
|
|
199
|
-
onConnectionChange() {
|
|
200
|
-
return () => {
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
};
|
|
204
|
-
return { server, client };
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
exports.createDirectTransportPair = createDirectTransportPair;
|
|
208
|
-
exports.createWebSocketTransport = createWebSocketTransport;
|
|
209
|
-
//# sourceMappingURL=chunk-WZXUKJ7E.cjs.map
|
|
210
|
-
//# sourceMappingURL=chunk-WZXUKJ7E.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/transport/websocket.ts","../src/transport/direct.ts"],"names":[],"mappings":"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","file":"chunk-WZXUKJ7E.cjs","sourcesContent":["import type { OUITransport, OUITransportConfig, OUIActionHandler, OUIObservationHandler } from './types.js';\nimport type { OUISurface, OUIObservationUpdate } 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 emitted:\n * {ns}:dispatch — action dispatch (server → client)\n * {ns}:observation — observation update (client → server)\n * {ns}:surface:register — surface registration (client → server)\n * {ns}:surface:deregister — surface deregistration (client → server)\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 }> = [];\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 // Track connection state\n socket.on('connect', () => {\n connected = true;\n connectionHandlers.forEach(h => h(true));\n // Flush buffer\n if (shouldBuffer) {\n while (buffer.length > 0) {\n const msg = buffer.shift()!;\n socket.emit(msg.event, msg.data);\n }\n }\n });\n\n socket.on('disconnect', () => {\n connected = false;\n connectionHandlers.forEach(h => h(false));\n });\n\n function emit(event: string, data: unknown) {\n if (connected) {\n socket.emit(event, data);\n } else if (shouldBuffer && buffer.length < maxBuffer) {\n buffer.push({ event, data });\n }\n }\n\n return {\n // ─── Dispatch Channel ───────────────────────────────────────\n dispatch(surfaceId, actionId, params) {\n emit(`${ns}:dispatch`, { surfaceId, actionId, params, timestamp: Date.now() });\n },\n\n onAction(handler: OUIActionHandler) {\n const listener = (data: { surfaceId: string; actionId: string; params: Record<string, unknown> }) => {\n handler(data.surfaceId, data.actionId, data.params);\n };\n socket.on(`${ns}:dispatch`, listener);\n return () => socket.off(`${ns}:dispatch`, listener);\n },\n\n // ─── Observation Channel ────────────────────────────────────\n pushObservation(update: OUIObservationUpdate) {\n emit(`${ns}:observation`, update);\n },\n\n onObservation(handler: OUIObservationHandler) {\n const listener = (data: OUIObservationUpdate) => handler(data);\n socket.on(`${ns}:observation`, listener);\n return () => socket.off(`${ns}:observation`, listener);\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 const listener = (data: { surface: OUISurface }) => handler(data.surface);\n socket.on(`${ns}:surface:register`, listener);\n return () => socket.off(`${ns}:surface:register`, listener);\n },\n\n onSurfaceDeregister(handler: (surfaceId: string) => void) {\n const listener = (data: { surfaceId: string }) => handler(data.surfaceId);\n socket.on(`${ns}:surface:deregister`, listener);\n return () => socket.off(`${ns}:surface:deregister`, listener);\n },\n\n // ─── Connection ─────────────────────────────────────────────\n get connected() { return connected; },\n\n async connect() {\n if (connected) return;\n return new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(`OUI transport connect timeout (${config?.connectTimeoutMs ?? 10000}ms)`));\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}\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 emit(event: string, data: unknown): 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","import type { OUITransport, OUIActionHandler, OUIObservationHandler } from './types.js';\nimport type { OUISurface, OUIObservationUpdate } from '../spec/index.js';\n\n/**\n * Direct transport — for same-process communication.\n * Used for API surfaces (where the agent runtime and surface are in the same Lambda)\n * and for testing (where you want synchronous, in-memory communication).\n *\n * Creates a paired (server, client) transport where messages sent on one\n * side are immediately received on the other.\n */\nexport function createDirectTransportPair(): { server: OUITransport; client: OUITransport } {\n const actionHandlers: OUIActionHandler[] = [];\n const observationHandlers: OUIObservationHandler[] = [];\n const surfaceRegisterHandlers: Array<(s: OUISurface) => void> = [];\n const surfaceDeregisterHandlers: Array<(id: string) => void> = [];\n\n const server: OUITransport = {\n dispatch(surfaceId, actionId, params) {\n // Server dispatches → client receives\n actionHandlers.forEach(h => h(surfaceId, actionId, params));\n },\n onAction() { return () => {}; }, // Server doesn't receive dispatches\n pushObservation() {}, // Server doesn't push observations\n onObservation(handler) {\n observationHandlers.push(handler);\n return () => { const i = observationHandlers.indexOf(handler); if (i >= 0) observationHandlers.splice(i, 1); };\n },\n registerSurface() {},\n deregisterSurface() {},\n onSurfaceRegister(handler) {\n surfaceRegisterHandlers.push(handler);\n return () => { const i = surfaceRegisterHandlers.indexOf(handler); if (i >= 0) surfaceRegisterHandlers.splice(i, 1); };\n },\n onSurfaceDeregister(handler) {\n surfaceDeregisterHandlers.push(handler);\n return () => { const i = surfaceDeregisterHandlers.indexOf(handler); if (i >= 0) surfaceDeregisterHandlers.splice(i, 1); };\n },\n get connected() { return true; },\n async connect() {},\n disconnect() {},\n onConnectionChange() { return () => {}; },\n };\n\n const client: OUITransport = {\n dispatch() {}, // Client doesn't dispatch\n onAction(handler) {\n actionHandlers.push(handler);\n return () => { const i = actionHandlers.indexOf(handler); if (i >= 0) actionHandlers.splice(i, 1); };\n },\n pushObservation(update: OUIObservationUpdate) {\n // Client pushes → server receives\n observationHandlers.forEach(h => h(update));\n },\n onObservation() { return () => {}; }, // Client doesn't receive observations\n registerSurface(surface) {\n surfaceRegisterHandlers.forEach(h => h(surface));\n },\n deregisterSurface(surfaceId) {\n surfaceDeregisterHandlers.forEach(h => h(surfaceId));\n },\n onSurfaceRegister() { return () => {}; },\n onSurfaceDeregister() { return () => {}; },\n get connected() { return true; },\n async connect() {},\n disconnect() {},\n onConnectionChange() { return () => {}; },\n };\n\n return { server, client };\n}\n"]}
|