@statelyai/sdk 0.15.0 → 0.16.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.
@@ -1,12 +1,17 @@
1
1
  import { EditorCapabilities, EmbedEventMap, ExportCallOptions, ExportFormat, ExportFormatMap, InspectionAction, InspectionSentEvent, InspectionTakenTransition, ProtocolMessage } from "./protocol.mjs";
2
2
 
3
3
  //#region src/transport.d.ts
4
+ interface TransportFailure {
5
+ code: string;
6
+ message: string;
7
+ }
4
8
  interface Transport {
5
9
  send(msg: ProtocolMessage): void;
6
10
  onMessage(handler: (msg: ProtocolMessage) => void): () => void;
7
11
  destroy(): void;
8
12
  readonly ready: boolean;
9
13
  onReady(handler: () => void): () => void;
14
+ onError?(handler: (failure: TransportFailure) => void): () => void;
10
15
  }
11
16
  interface PostMessageTransportOptions {
12
17
  iframe: HTMLIFrameElement;
@@ -17,51 +22,18 @@ interface PostMessageTransportOptions {
17
22
  declare function createPostMessageTransport(options: PostMessageTransportOptions): Transport;
18
23
  interface WebSocketTransportOptions {
19
24
  url: string;
20
- role: 'client' | 'viz';
21
- sessionId: string;
25
+ role: 'producer' | 'viewer';
26
+ producerId?: string;
22
27
  metadata?: {
23
28
  name?: string;
24
29
  machineId?: string;
25
30
  };
26
31
  /** Reconnect on disconnect. Default true. */
27
32
  reconnect?: boolean;
28
- /** Max reconnect attempts. Default 10. */
33
+ /** Max reconnect attempts after the first connection. Default 10. */
29
34
  maxReconnectAttempts?: number;
30
35
  }
31
36
  declare function createWebSocketTransport(options: WebSocketTransportOptions): Transport;
32
- interface MultiplexedWebSocketConnectionOptions {
33
- url: string;
34
- role: 'client' | 'viz';
35
- /** First (primary) session to register on connect. */
36
- sessionId: string;
37
- /** Metadata for the primary session. */
38
- metadata?: {
39
- name?: string;
40
- machineId?: string;
41
- };
42
- reconnect?: boolean;
43
- maxReconnectAttempts?: number;
44
- }
45
- interface MultiplexedChannelOptions {
46
- /** Session id this channel targets. */
47
- sessionId: string;
48
- /** Optional metadata for this session. */
49
- metadata?: {
50
- name?: string;
51
- machineId?: string;
52
- };
53
- }
54
- interface MultiplexedWebSocketConnection {
55
- /** Open a channel for a sessionId. Re-opening an existing session returns the same channel. */
56
- openChannel(options: MultiplexedChannelOptions): Transport;
57
- /** Close the connection and all its channels. */
58
- destroy(): void;
59
- /** Whether the underlying WebSocket is connected + the primary session is registered. */
60
- readonly ready: boolean;
61
- /** Primary session id (first registered). */
62
- readonly primarySessionId: string;
63
- }
64
- declare function createMultiplexedWebSocketConnection(options: MultiplexedWebSocketConnectionOptions): MultiplexedWebSocketConnection;
65
37
  //#endregion
66
38
  //#region src/inspect.d.ts
67
39
  interface MinimalActorRef {
@@ -93,14 +65,14 @@ interface InspectorInspectionEvent {
93
65
  readonly actorRef: unknown;
94
66
  }
95
67
  interface AdoptedActor {
96
- /** `actor.sessionId` from xstate. Unique across the system. */
68
+ /** Globally unique `actor.sessionId` from xstate. */
69
+ sessionId: string;
70
+ /** System-local `actor.id`. */
97
71
  actorId: string;
98
72
  /** Parent actor's sessionId, or `null` for the root. */
99
- parentActorId: string | null;
100
- /** Root actor's sessionId (equal to `actorId` for the root). */
101
- rootId: string;
102
- /** `actor.id` — a human-facing local name. */
103
- id: string;
73
+ parentSessionId: string | null;
74
+ /** Root actor's sessionId. */
75
+ rootSessionId: string;
104
76
  /** `actor.systemId`, if registered under one. */
105
77
  systemId: string | undefined;
106
78
  /** Latest serialized snapshot streamed for this actor. */
@@ -112,8 +84,8 @@ interface AdoptedActor {
112
84
  }
113
85
  /** One observed snapshot, independent of the XState inspection version. */
114
86
  interface InspectedSnapshot {
115
- actorId: string;
116
- sourceActorId: string | null;
87
+ sessionId: string;
88
+ sourceSessionId: string | null;
117
89
  /** Previously observed snapshot, which may not be the immediate predecessor. */
118
90
  previousSnapshot: unknown | null;
119
91
  snapshot: unknown;
@@ -127,8 +99,8 @@ interface InspectedSnapshot {
127
99
  type InspectedTransition = InspectedSnapshot;
128
100
  /** One observed event, independent of whether processing produced a snapshot. */
129
101
  interface InspectedEvent {
130
- actorId: string;
131
- sourceActorId: string | null;
102
+ sessionId: string;
103
+ sourceSessionId: string | null;
132
104
  event: unknown;
133
105
  }
134
106
  interface InspectorEvents {
@@ -136,7 +108,7 @@ interface InspectorEvents {
136
108
  event: InspectedEvent;
137
109
  snapshot: InspectedSnapshot;
138
110
  stop: {
139
- actorId: string;
111
+ sessionId: string;
140
112
  };
141
113
  /** @deprecated Use `actor`. */
142
114
  register: AdoptedActor;
@@ -144,7 +116,7 @@ interface InspectorEvents {
144
116
  transition: InspectedSnapshot;
145
117
  /** @deprecated Use `stop`. */
146
118
  stopped: {
147
- actorId: string;
119
+ sessionId: string;
148
120
  };
149
121
  error: EmbedEventMap['error'];
150
122
  }
@@ -161,15 +133,27 @@ interface ManualActorOptions {
161
133
  systemId?: string;
162
134
  }
163
135
  interface CreateInspectorOptions {
164
- /** WebSocket URL of the devtools server. Default: `'ws://localhost:4242'`. */
136
+ /**
137
+ * WebSocket relay base URL. Defaults to `STATELY_INSPECT_URL`, then
138
+ * `wss://sky.stately.ai`. Passing this option always wins.
139
+ */
165
140
  url?: string;
141
+ /** Unguessable inspection room capability. Defaults to a random UUID. */
142
+ roomId?: string;
143
+ /** Stable identity for this producer connection. Defaults to a random UUID. */
144
+ producerId?: string;
145
+ /**
146
+ * Inspector UI base URL when hosted separately from the WebSocket relay. The
147
+ * inspector adds `ws` and `r` query parameters. When omitted, the URL
148
+ * is derived from the relay URL by replacing `ws` with `http`.
149
+ */
150
+ inspectorBaseUrl?: string;
166
151
  /** Auto-open browser to visualizer. Default: `true`. */
167
152
  autoOpen?: boolean;
168
153
  /**
169
- * Relay session capability. Defaults to a cryptographically random UUID.
170
- * This is the `?session=<id>` value the visualizer connects with. Custom
171
- * values used with a hosted relay must be unguessable.
154
+ * Legacy name for the unguessable room capability.
172
155
  */
156
+ /** @deprecated Use {@link roomId}. */
173
157
  sessionId?: string;
174
158
  /** Display name for this system in the visualizer. */
175
159
  name?: string;
@@ -184,7 +168,9 @@ interface CreateInspectorOptions {
184
168
  * `actor.logic.config`. Return `null` for non-machine actors.
185
169
  */
186
170
  extractMachineConfig?: (actor: any, source?: unknown) => unknown;
187
- /** Selected actor id to focus on first. Defaults to the first inspected root. */
171
+ /** Selected actor session id to focus on first. */
172
+ selectedSessionId?: string;
173
+ /** @deprecated Use {@link selectedSessionId}. */
188
174
  selectedActorId?: string;
189
175
  /** Panel layout forwarded into the system init message. */
190
176
  panels?: {
@@ -197,17 +183,26 @@ interface CreateInspectorOptions {
197
183
  depth?: number;
198
184
  capabilities?: EditorCapabilities;
199
185
  /**
200
- * Advanced: inject a pre-built transport (e.g. a channel from a
201
- * multiplexed connection). When provided, `url`/`name` are ignored and the
202
- * inspector shares that transport instead of opening its own WebSocket.
186
+ * Advanced: inject a pre-built transport. When provided, `url`/`name` are
187
+ * ignored and no WebSocket or browser URL is created.
203
188
  */
204
189
  transport?: Transport;
205
190
  }
206
191
  interface Inspector {
207
- /** Snapshot of currently-adopted actors keyed by `actorId`. */
192
+ /** Snapshot of currently-adopted actors keyed by global `sessionId`. */
208
193
  readonly actors: ReadonlyMap<string, AdoptedActor>;
209
- /** The relay sessionId this inspector registered under. */
194
+ /** Unguessable inspection room capability. */
195
+ readonly roomId: string;
196
+ /** Complete WebSocket URL for this room. */
197
+ readonly relayUrl: string | null;
198
+ /** Identity stamped onto this producer's protocol messages. */
199
+ readonly producerId: string;
200
+ /** @deprecated Use {@link roomId}. */
210
201
  readonly sessionId: string;
202
+ /** URL that opens the inspector UI for this live session. */
203
+ readonly inspectorUrl: string | null;
204
+ /** Resolves after the first relay registration and initial-state flush. */
205
+ readonly ready: Promise<void>;
211
206
  /**
212
207
  * XState `inspect` option callback. Pass directly to `createActor` or another
213
208
  * host that creates actors internally.
@@ -251,4 +246,4 @@ declare function createInspector(options?: CreateInspectorOptions): Inspector;
251
246
  /** @deprecated Use {@link createInspector}. */
252
247
  declare const createStatelyInspector: typeof createInspector;
253
248
  //#endregion
254
- export { createPostMessageTransport as _, InspectedTransition as a, InspectorInspectionEvent as c, createStatelyInspector as d, MultiplexedChannelOptions as f, createMultiplexedWebSocketConnection as g, Transport as h, InspectedSnapshot as i, ManualActorOptions as l, MultiplexedWebSocketConnectionOptions as m, CreateInspectorOptions as n, Inspector as o, MultiplexedWebSocketConnection as p, InspectedEvent as r, InspectorEvents as s, AdoptedActor as t, createInspector as u, createWebSocketTransport as v };
249
+ export { InspectedTransition as a, InspectorInspectionEvent as c, createStatelyInspector as d, Transport as f, createWebSocketTransport as h, InspectedSnapshot as i, ManualActorOptions as l, createPostMessageTransport as m, CreateInspectorOptions as n, Inspector as o, TransportFailure as p, InspectedEvent as r, InspectorEvents as s, AdoptedActor as t, createInspector as u };
@@ -1,3 +1,3 @@
1
1
  import { EditorCapabilities, EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ExportCallOptions, ExportFormat, ExportFormatMap, InspectionAction, InspectionSentEvent, InspectionTakenTransition } from "./protocol.mjs";
2
- import { a as InspectedTransition, c as InspectorInspectionEvent, d as createStatelyInspector, h as Transport, i as InspectedSnapshot, l as ManualActorOptions, n as CreateInspectorOptions, o as Inspector, r as InspectedEvent, s as InspectorEvents, t as AdoptedActor, u as createInspector } from "./inspect-DenVP7IE.mjs";
2
+ import { a as InspectedTransition, c as InspectorInspectionEvent, d as createStatelyInspector, f as Transport, i as InspectedSnapshot, l as ManualActorOptions, n as CreateInspectorOptions, o as Inspector, r as InspectedEvent, s as InspectorEvents, t as AdoptedActor, u as createInspector } from "./inspect-CduY_2Fa.mjs";
3
3
  export { AdoptedActor, CreateInspectorOptions, EditorCapabilities, EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ExportCallOptions, ExportFormat, ExportFormatMap, InspectedEvent, InspectedSnapshot, InspectedTransition, InspectionAction, InspectionSentEvent, InspectionTakenTransition, Inspector, InspectorEvents, InspectorInspectionEvent, ManualActorOptions, Transport, createInspector, createStatelyInspector };
package/dist/inspect.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { n as createStatelyInspector, t as createInspector } from "./inspect-DWDTNMEc.mjs";
1
+ import { n as createStatelyInspector, t as createInspector } from "./inspect-BwVdM4R8.mjs";
2
2
 
3
3
  export { createInspector, createStatelyInspector };
@@ -0,0 +1,22 @@
1
+ //#region src/node-relay.d.ts
2
+ interface NodeInspectionRelayOptions {
3
+ host?: string;
4
+ port?: number;
5
+ logger?: Pick<Console, 'info'>;
6
+ }
7
+ /** Local/self-hosted Node adapter for the room inspection relay. */
8
+ declare class NodeInspectionRelayServer {
9
+ private readonly options;
10
+ private server;
11
+ private webSocketServer;
12
+ private readonly rooms;
13
+ private readonly connections;
14
+ private readonly sockets;
15
+ constructor(options?: NodeInspectionRelayOptions);
16
+ get url(): string;
17
+ start(): Promise<void>;
18
+ stop(): Promise<void>;
19
+ }
20
+ declare function createNodeInspectionRelay(options?: NodeInspectionRelayOptions): NodeInspectionRelayServer;
21
+ //#endregion
22
+ export { NodeInspectionRelayOptions, NodeInspectionRelayServer, createNodeInspectionRelay };
@@ -0,0 +1,84 @@
1
+ import { getInspectionRoomId } from "./protocol.mjs";
2
+ import { createInspectionRelay } from "./relay.mjs";
3
+ import { createServer } from "node:http";
4
+ import { randomUUID } from "node:crypto";
5
+ import { WebSocket, WebSocketServer } from "ws";
6
+
7
+ //#region src/node-relay.ts
8
+ /** Local/self-hosted Node adapter for the room inspection relay. */
9
+ var NodeInspectionRelayServer = class {
10
+ server = null;
11
+ webSocketServer = null;
12
+ rooms = /* @__PURE__ */ new Map();
13
+ connections = /* @__PURE__ */ new Map();
14
+ sockets = /* @__PURE__ */ new Map();
15
+ constructor(options = {}) {
16
+ this.options = options;
17
+ }
18
+ get url() {
19
+ if (!this.server) throw new Error("Inspection relay is not running.");
20
+ const address = this.server.address();
21
+ if (!address || typeof address === "string") throw new Error("Inspection relay address is unavailable.");
22
+ return `ws://${this.options.host ?? "127.0.0.1"}:${address.port}`;
23
+ }
24
+ async start() {
25
+ if (this.server) return;
26
+ this.server = createServer();
27
+ this.webSocketServer = new WebSocketServer({ server: this.server });
28
+ this.webSocketServer.on("connection", (socket, request) => {
29
+ const roomId = getInspectionRoomId(new URL(request.url ?? "/", this.url));
30
+ if (!roomId) {
31
+ socket.close(1008, "Missing ?r=<roomId>");
32
+ return;
33
+ }
34
+ const relay = this.rooms.get(roomId) ?? createInspectionRelay();
35
+ this.rooms.set(roomId, relay);
36
+ const peerId = randomUUID();
37
+ this.connections.set(socket, {
38
+ peerId,
39
+ relay
40
+ });
41
+ this.sockets.set(peerId, socket);
42
+ socket.on("message", (raw) => {
43
+ for (const effect of relay.receive(peerId, raw.toString())) {
44
+ const target = this.sockets.get(effect.peerId);
45
+ if (target?.readyState === WebSocket.OPEN) target.send(JSON.stringify(effect.message));
46
+ }
47
+ });
48
+ socket.on("close", () => {
49
+ relay.disconnect(peerId);
50
+ this.connections.delete(socket);
51
+ this.sockets.delete(peerId);
52
+ });
53
+ });
54
+ await new Promise((resolve, reject) => {
55
+ this.server.once("error", reject);
56
+ this.server.listen(this.options.port ?? 4242, this.options.host ?? "127.0.0.1", () => {
57
+ this.server.off("error", reject);
58
+ resolve();
59
+ });
60
+ });
61
+ this.options.logger?.info(`Inspection relay listening on ${this.url}`);
62
+ }
63
+ async stop() {
64
+ for (const socket of this.connections.keys()) socket.close();
65
+ this.connections.clear();
66
+ this.sockets.clear();
67
+ for (const relay of this.rooms.values()) relay.clear();
68
+ this.rooms.clear();
69
+ if (this.webSocketServer) {
70
+ await new Promise((resolve) => this.webSocketServer.close(() => resolve()));
71
+ this.webSocketServer = null;
72
+ }
73
+ if (this.server) {
74
+ await new Promise((resolve, reject) => this.server.close((error) => error ? reject(error) : resolve()));
75
+ this.server = null;
76
+ }
77
+ }
78
+ };
79
+ function createNodeInspectionRelay(options) {
80
+ return new NodeInspectionRelayServer(options);
81
+ }
82
+
83
+ //#endregion
84
+ export { NodeInspectionRelayServer, createNodeInspectionRelay };