oui-spec 0.2.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.
Files changed (63) hide show
  1. package/README.md +94 -122
  2. package/dist/{chunk-CVUUSPF4.js → chunk-BMCL2K74.js} +2 -2
  3. package/dist/chunk-BMCL2K74.js.map +1 -0
  4. package/dist/{chunk-MTMEW6MM.cjs → chunk-DCVVTP3V.cjs} +72 -23
  5. package/dist/chunk-DCVVTP3V.cjs.map +1 -0
  6. package/dist/chunk-F3SKRAGU.cjs +98 -0
  7. package/dist/chunk-F3SKRAGU.cjs.map +1 -0
  8. package/dist/{chunk-YDMGV72W.js → chunk-F3WKIRAU.js} +72 -23
  9. package/dist/chunk-F3WKIRAU.js.map +1 -0
  10. package/dist/chunk-IIZ6HL2L.js +89 -0
  11. package/dist/chunk-IIZ6HL2L.js.map +1 -0
  12. package/dist/chunk-KNWGQRXL.cjs +567 -0
  13. package/dist/chunk-KNWGQRXL.cjs.map +1 -0
  14. package/dist/chunk-NYCJZQSP.js +92 -0
  15. package/dist/chunk-NYCJZQSP.js.map +1 -0
  16. package/dist/chunk-ROGKEMLL.cjs +91 -0
  17. package/dist/chunk-ROGKEMLL.cjs.map +1 -0
  18. package/dist/chunk-TRNVXAB5.js +563 -0
  19. package/dist/chunk-TRNVXAB5.js.map +1 -0
  20. package/dist/{chunk-3DCIL4FV.cjs → chunk-ZKM4XWAB.cjs} +2 -2
  21. package/dist/chunk-ZKM4XWAB.cjs.map +1 -0
  22. package/dist/core/index.cjs +10 -6
  23. package/dist/core/index.d.cts +15 -8
  24. package/dist/core/index.d.ts +15 -8
  25. package/dist/core/index.js +3 -3
  26. package/dist/index.cjs +28 -12
  27. package/dist/index.d.cts +5 -4
  28. package/dist/index.d.ts +5 -4
  29. package/dist/index.js +5 -5
  30. package/dist/react/index.cjs +15 -3
  31. package/dist/react/index.d.cts +33 -50
  32. package/dist/react/index.d.ts +33 -50
  33. package/dist/react/index.js +1 -1
  34. package/dist/spec/index.cjs +2 -2
  35. package/dist/spec/index.d.cts +35 -7
  36. package/dist/spec/index.d.ts +35 -7
  37. package/dist/spec/index.js +1 -1
  38. package/dist/{define-surface-D6XPtoqu.d.cts → surface-runtime--2lZGB7Z.d.cts} +92 -2
  39. package/dist/{define-surface-DXBop-uB.d.ts → surface-runtime-Dj_nhd7r.d.ts} +92 -2
  40. package/dist/transport/index.cjs +4 -4
  41. package/dist/transport/index.d.cts +2 -2
  42. package/dist/transport/index.d.ts +2 -2
  43. package/dist/transport/index.js +2 -2
  44. package/dist/{websocket-CrI0yRNo.d.cts → websocket-YfWILdZ4.d.cts} +36 -18
  45. package/dist/{websocket-CiWvkaz_.d.ts → websocket-c5tIUWY5.d.ts} +36 -18
  46. package/package.json +5 -1
  47. package/spec/OUI-SPEC-v0.1.md +229 -155
  48. package/dist/chunk-2ON5IEXB.cjs +0 -167
  49. package/dist/chunk-2ON5IEXB.cjs.map +0 -1
  50. package/dist/chunk-3DCIL4FV.cjs.map +0 -1
  51. package/dist/chunk-5TQ6AVQH.cjs +0 -108
  52. package/dist/chunk-5TQ6AVQH.cjs.map +0 -1
  53. package/dist/chunk-CVUUSPF4.js.map +0 -1
  54. package/dist/chunk-HK7OXB2W.cjs +0 -157
  55. package/dist/chunk-HK7OXB2W.cjs.map +0 -1
  56. package/dist/chunk-ILUTAHUJ.js +0 -154
  57. package/dist/chunk-ILUTAHUJ.js.map +0 -1
  58. package/dist/chunk-MTMEW6MM.cjs.map +0 -1
  59. package/dist/chunk-O6EI77LD.js +0 -106
  60. package/dist/chunk-O6EI77LD.js.map +0 -1
  61. package/dist/chunk-UIGRLZOX.js +0 -164
  62. package/dist/chunk-UIGRLZOX.js.map +0 -1
  63. package/dist/chunk-YDMGV72W.js.map +0 -1
@@ -0,0 +1,92 @@
1
+ import { createContext, createElement, useContext, useRef, useEffect, useCallback, useMemo } from 'react';
2
+
3
+ // src/react/use-surface.ts
4
+ var SurfaceRuntimeContext = createContext(null);
5
+ function SurfaceRuntimeProvider({
6
+ runtime,
7
+ children
8
+ }) {
9
+ return createElement(
10
+ SurfaceRuntimeContext.Provider,
11
+ { value: runtime },
12
+ children
13
+ );
14
+ }
15
+ function useSurfaceRuntime() {
16
+ const runtime = useContext(SurfaceRuntimeContext);
17
+ if (!runtime) {
18
+ throw new Error(
19
+ "[OUI] useSurface needs a SurfaceRuntimeProvider above it. Create one runtime per client with createSurfaceRuntime() and provide it at the root."
20
+ );
21
+ }
22
+ return runtime;
23
+ }
24
+ var localRequestSeq = 0;
25
+ function useSurface(options) {
26
+ const { surface, context, active = true } = options;
27
+ const runtime = useSurfaceRuntime();
28
+ const contextRef = useRef(context);
29
+ contextRef.current = context;
30
+ const mountedRef = useRef(null);
31
+ const pendingRef = useRef(/* @__PURE__ */ new Map());
32
+ useEffect(() => {
33
+ if (!active) return;
34
+ const mounted = runtime.mount(surface, () => contextRef.current);
35
+ mountedRef.current = mounted;
36
+ for (const [observationId, value] of pendingRef.current) {
37
+ mounted.pushObservation(observationId, value);
38
+ }
39
+ pendingRef.current.clear();
40
+ return () => {
41
+ mounted.unmount();
42
+ if (mountedRef.current === mounted) mountedRef.current = null;
43
+ };
44
+ }, [runtime, surface, active]);
45
+ const pushObservation = useCallback(
46
+ (observationId, value) => {
47
+ const mounted = mountedRef.current;
48
+ if (mounted) mounted.pushObservation(observationId, value);
49
+ else pendingRef.current.set(observationId, value);
50
+ },
51
+ []
52
+ );
53
+ const execute = useCallback(
54
+ (actionId, params = {}) => runtime.execute({
55
+ requestId: `local_${Date.now()}_${++localRequestSeq}`,
56
+ surfaceId: surface.id,
57
+ actionId,
58
+ params,
59
+ timestamp: Date.now()
60
+ }),
61
+ [runtime, surface.id]
62
+ );
63
+ return useMemo(
64
+ () => ({ surfaceId: surface.id, pushObservation, execute }),
65
+ [surface.id, pushObservation, execute]
66
+ );
67
+ }
68
+ function useObservation(surface, observationId, value) {
69
+ const { pushObservation } = surface;
70
+ let serialized;
71
+ try {
72
+ serialized = JSON.stringify(value) ?? "undefined";
73
+ } catch {
74
+ serialized = String(value);
75
+ }
76
+ const valueRef = useRef(value);
77
+ valueRef.current = value;
78
+ useEffect(() => {
79
+ pushObservation(observationId, valueRef.current);
80
+ }, [pushObservation, observationId, serialized]);
81
+ }
82
+ function useSurfaceHold(busy) {
83
+ const runtime = useSurfaceRuntime();
84
+ useEffect(() => {
85
+ if (!busy) return;
86
+ return runtime.hold();
87
+ }, [runtime, busy]);
88
+ }
89
+
90
+ export { SurfaceRuntimeProvider, useObservation, useSurface, useSurfaceHold, useSurfaceRuntime };
91
+ //# sourceMappingURL=chunk-NYCJZQSP.js.map
92
+ //# sourceMappingURL=chunk-NYCJZQSP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/use-surface.ts"],"names":[],"mappings":"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","file":"chunk-NYCJZQSP.js","sourcesContent":["import {\n createContext,\n createElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n type ReactNode,\n} from \"react\";\nimport type {\n DefinedSurface,\n SurfaceRuntime,\n MountedSurface,\n} from \"../core/index.js\";\nimport type { OUIActionResult } from \"../spec/index.js\";\n\n// ─── Runtime context ─────────────────────────────────────────────────────────\n\nconst SurfaceRuntimeContext = createContext<SurfaceRuntime | null>(null);\n\nexport interface SurfaceRuntimeProviderProps {\n runtime: SurfaceRuntime;\n children?: ReactNode;\n}\n\n/** Makes one surface runtime available to every `useSurface` below it. */\nexport function SurfaceRuntimeProvider({\n runtime,\n children,\n}: SurfaceRuntimeProviderProps) {\n return createElement(\n SurfaceRuntimeContext.Provider,\n { value: runtime },\n children,\n );\n}\n\n/** The surface runtime from the nearest `SurfaceRuntimeProvider`. */\nexport function useSurfaceRuntime(): SurfaceRuntime {\n const runtime = useContext(SurfaceRuntimeContext);\n if (!runtime) {\n throw new Error(\n \"[OUI] useSurface needs a SurfaceRuntimeProvider above it. Create one runtime per client with \" +\n \"createSurfaceRuntime() and provide it at the root.\",\n );\n }\n return runtime;\n}\n\n// ─── useSurface ──────────────────────────────────────────────────────────────\n\nexport interface UseSurfaceOptions<TContext> {\n /** The defined surface (from defineSurface()) */\n surface: DefinedSurface<TContext>;\n\n /** Passed to action handlers. Read when an action runs, so it is always current. */\n context: TContext;\n\n /** Mount the surface only while true. Default true. */\n active?: boolean;\n}\n\nexport interface UseSurfaceResult {\n surfaceId: string;\n /** Record an observation value on this surface. Unchanged values are ignored. */\n pushObservation(observationId: string, value: unknown): void;\n /** Run one of this surface's actions locally, exactly as a dispatched request would. */\n execute(\n actionId: string,\n params?: Record<string, unknown>,\n ): Promise<OUIActionResult>;\n}\n\nlet localRequestSeq = 0;\n\n/**\n * Mount a surface into the client's surface runtime for as long as the\n * component is mounted (and `active`). The runtime answers dispatched requests\n * for it, so the component needs no listener of its own.\n */\nexport function useSurface<TContext>(\n options: UseSurfaceOptions<TContext>,\n): UseSurfaceResult {\n const { surface, context, active = true } = options;\n const runtime = useSurfaceRuntime();\n\n const contextRef = useRef(context);\n contextRef.current = context;\n\n const mountedRef = useRef<MountedSurface | null>(null);\n // Observations pushed before the mount effect ran (effects declared earlier\n // in the same component run first) are kept and delivered on mount rather\n // than lost.\n const pendingRef = useRef(new Map<string, unknown>());\n\n useEffect(() => {\n if (!active) return;\n const mounted = runtime.mount(surface, () => contextRef.current);\n mountedRef.current = mounted;\n for (const [observationId, value] of pendingRef.current) {\n mounted.pushObservation(observationId, value);\n }\n pendingRef.current.clear();\n return () => {\n mounted.unmount();\n if (mountedRef.current === mounted) mountedRef.current = null;\n };\n }, [runtime, surface, active]);\n\n const pushObservation = useCallback(\n (observationId: string, value: unknown) => {\n const mounted = mountedRef.current;\n if (mounted) mounted.pushObservation(observationId, value);\n else pendingRef.current.set(observationId, value);\n },\n [],\n );\n\n const execute = useCallback(\n (actionId: string, params: Record<string, unknown> = {}) =>\n runtime.execute({\n requestId: `local_${Date.now()}_${++localRequestSeq}`,\n surfaceId: surface.id,\n actionId,\n params,\n timestamp: Date.now(),\n }),\n [runtime, surface.id],\n );\n\n return useMemo(\n () => ({ surfaceId: surface.id, pushObservation, execute }),\n [surface.id, pushObservation, execute],\n );\n}\n\n// ─── useObservation ──────────────────────────────────────────────────────────\n\n/** Keep an observation on a mounted surface equal to `value`. */\nexport function useObservation(\n surface: Pick<UseSurfaceResult, \"pushObservation\">,\n observationId: string,\n value: unknown,\n): void {\n const { pushObservation } = surface;\n let serialized: string;\n try {\n serialized = JSON.stringify(value) ?? \"undefined\";\n } catch {\n serialized = String(value);\n }\n const valueRef = useRef(value);\n valueRef.current = value;\n\n useEffect(() => {\n pushObservation(observationId, valueRef.current);\n }, [pushObservation, observationId, serialized]);\n}\n\n// ─── useSurfaceHold ──────────────────────────────────────────────────────────\n\n/**\n * Keep the UI unsettled while `busy` is true: an action's result waits for it.\n * For work mounting cannot show, such as a route's code or a page's data still\n * loading.\n */\nexport function useSurfaceHold(busy: boolean): void {\n const runtime = useSurfaceRuntime();\n useEffect(() => {\n if (!busy) return;\n return runtime.hold();\n }, [runtime, busy]);\n}\n"]}
@@ -0,0 +1,91 @@
1
+ 'use strict';
2
+
3
+ // src/transport/direct.ts
4
+ function createDirectTransportPair() {
5
+ const actionHandlers = [];
6
+ const resultHandlers = [];
7
+ const observationHandlers = [];
8
+ const surfaceRegisterHandlers = [];
9
+ const surfaceDeregisterHandlers = [];
10
+ function subscribe(list, handler) {
11
+ list.push(handler);
12
+ return () => {
13
+ const i = list.indexOf(handler);
14
+ if (i >= 0) list.splice(i, 1);
15
+ };
16
+ }
17
+ const noop = () => {
18
+ };
19
+ const unsubscribed = () => noop;
20
+ const server = {
21
+ dispatch(request) {
22
+ actionHandlers.forEach((h) => h(request));
23
+ },
24
+ onAction: unsubscribed,
25
+ // Server doesn't receive dispatches
26
+ sendResult: noop,
27
+ // Server doesn't answer requests
28
+ onResult(handler) {
29
+ return subscribe(resultHandlers, handler);
30
+ },
31
+ pushObservation: noop,
32
+ // Server doesn't push observations
33
+ onObservation(handler) {
34
+ return subscribe(observationHandlers, handler);
35
+ },
36
+ registerSurface: noop,
37
+ deregisterSurface: noop,
38
+ onSurfaceRegister(handler) {
39
+ return subscribe(surfaceRegisterHandlers, handler);
40
+ },
41
+ onSurfaceDeregister(handler) {
42
+ return subscribe(surfaceDeregisterHandlers, handler);
43
+ },
44
+ get connected() {
45
+ return true;
46
+ },
47
+ async connect() {
48
+ },
49
+ disconnect: noop,
50
+ onConnectionChange: unsubscribed,
51
+ dispose: noop
52
+ };
53
+ const client = {
54
+ dispatch: noop,
55
+ // Client doesn't dispatch
56
+ onAction(handler) {
57
+ return subscribe(actionHandlers, handler);
58
+ },
59
+ sendResult(result) {
60
+ resultHandlers.forEach((h) => h(result));
61
+ },
62
+ onResult: unsubscribed,
63
+ // Client doesn't receive results
64
+ pushObservation(update) {
65
+ observationHandlers.forEach((h) => h(update));
66
+ },
67
+ onObservation: unsubscribed,
68
+ // Client doesn't receive observations
69
+ registerSurface(surface) {
70
+ surfaceRegisterHandlers.forEach((h) => h(surface));
71
+ },
72
+ deregisterSurface(surfaceId) {
73
+ surfaceDeregisterHandlers.forEach((h) => h(surfaceId));
74
+ },
75
+ onSurfaceRegister: unsubscribed,
76
+ onSurfaceDeregister: unsubscribed,
77
+ get connected() {
78
+ return true;
79
+ },
80
+ async connect() {
81
+ },
82
+ disconnect: noop,
83
+ onConnectionChange: unsubscribed,
84
+ dispose: noop
85
+ };
86
+ return { server, client };
87
+ }
88
+
89
+ exports.createDirectTransportPair = createDirectTransportPair;
90
+ //# sourceMappingURL=chunk-ROGKEMLL.cjs.map
91
+ //# sourceMappingURL=chunk-ROGKEMLL.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/transport/direct.ts"],"names":[],"mappings":"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","file":"chunk-ROGKEMLL.cjs","sourcesContent":["import type {\n OUITransport,\n OUIActionHandler,\n OUIObservationHandler,\n OUIResultHandler,\n} 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(): {\n server: OUITransport;\n client: OUITransport;\n} {\n const actionHandlers: OUIActionHandler[] = [];\n const resultHandlers: OUIResultHandler[] = [];\n const observationHandlers: OUIObservationHandler[] = [];\n const surfaceRegisterHandlers: Array<(s: OUISurface) => void> = [];\n const surfaceDeregisterHandlers: Array<(id: string) => void> = [];\n\n function subscribe<T>(list: T[], handler: T): () => void {\n list.push(handler);\n return () => {\n const i = list.indexOf(handler);\n if (i >= 0) list.splice(i, 1);\n };\n }\n\n const noop = () => {};\n const unsubscribed = () => noop;\n\n const server: OUITransport = {\n dispatch(request) {\n // Server dispatches → client receives\n actionHandlers.forEach((h) => h(request));\n },\n onAction: unsubscribed, // Server doesn't receive dispatches\n sendResult: noop, // Server doesn't answer requests\n onResult(handler) {\n return subscribe(resultHandlers, handler);\n },\n pushObservation: noop, // Server doesn't push observations\n onObservation(handler) {\n return subscribe(observationHandlers, handler);\n },\n registerSurface: noop,\n deregisterSurface: noop,\n onSurfaceRegister(handler) {\n return subscribe(surfaceRegisterHandlers, handler);\n },\n onSurfaceDeregister(handler) {\n return subscribe(surfaceDeregisterHandlers, handler);\n },\n get connected() {\n return true;\n },\n async connect() {},\n disconnect: noop,\n onConnectionChange: unsubscribed,\n dispose: noop,\n };\n\n const client: OUITransport = {\n dispatch: noop, // Client doesn't dispatch\n onAction(handler) {\n return subscribe(actionHandlers, handler);\n },\n sendResult(result) {\n // Client answers → server receives\n resultHandlers.forEach((h) => h(result));\n },\n onResult: unsubscribed, // Client doesn't receive results\n pushObservation(update: OUIObservationUpdate) {\n // Client pushes → server receives\n observationHandlers.forEach((h) => h(update));\n },\n onObservation: unsubscribed, // 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: unsubscribed,\n onSurfaceDeregister: unsubscribed,\n get connected() {\n return true;\n },\n async connect() {},\n disconnect: noop,\n onConnectionChange: unsubscribed,\n dispose: noop,\n };\n\n return { server, client };\n}\n"]}