@statelyai/sdk 0.12.2 → 0.13.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 +17 -2
- package/dist/auth.d.mts +1 -1
- package/dist/embed.mjs +2 -1
- package/dist/{graph-Dq5ycdSq.d.mts → graph-R0sbxnZ7.d.mts} +1 -1
- package/dist/graph.d.mts +1 -1
- package/dist/index.d.mts +7 -6
- package/dist/index.mjs +6 -4
- package/dist/{inspect-BmZUcnZB.d.mts → inspect-BMHheAvx.d.mts} +85 -4
- package/dist/inspect-D9GyHTTW.mjs +469 -0
- package/dist/inspect.d.mts +3 -3
- package/dist/inspect.mjs +2 -305
- package/dist/patchTypes.d.mts +1 -1
- package/dist/protocol.d.mts +38 -6
- package/dist/protocol.mjs +3 -1
- package/dist/relay.d.mts +43 -0
- package/dist/relay.mjs +153 -0
- package/dist/studio.d.mts +1 -1
- package/dist/sync.d.mts +1 -1
- package/dist/sync.mjs +1 -1
- package/dist/{transport-D0nlFaLn.mjs → transport-D2Ud05yg.mjs} +179 -2
- package/package.json +7 -2
- /package/dist/{auth-DO1-eQcU.d.mts → auth-DmPZiERd.d.mts} +0 -0
- /package/dist/{dist-C-AdA8Iw.mjs → dist-CHGcvOdQ.mjs} +0 -0
- /package/dist/{index-BRW2DecD.d.mts → index-DVjNSTuQ.d.mts} +0 -0
package/dist/inspect.mjs
CHANGED
|
@@ -1,306 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as createStatelyInspector, t as createInspector } from "./inspect-D9GyHTTW.mjs";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
const defaultSerializeSnapshot = (snapshot) => ({
|
|
5
|
-
value: snapshot?.value,
|
|
6
|
-
status: snapshot?.status
|
|
7
|
-
});
|
|
8
|
-
const defaultExtractMachineConfig = (actor) => actor?.logic?.config ?? null;
|
|
9
|
-
let nextManualId = 0;
|
|
10
|
-
function generateSessionId() {
|
|
11
|
-
return `manual-${Date.now()}-${nextManualId++}`;
|
|
12
|
-
}
|
|
13
|
-
function createStatelyInspector(options = {}) {
|
|
14
|
-
const { url = "ws://localhost:4242", autoOpen = true, name, serializeSnapshot = defaultSerializeSnapshot, extractMachineConfig = defaultExtractMachineConfig, selectedActorId, panels, theme, readOnly, depth, capabilities, transport: injectedTransport } = options;
|
|
15
|
-
const sessionId = options.sessionId ?? generateSessionId();
|
|
16
|
-
const displayName = name ?? "system:manual";
|
|
17
|
-
let destroyed = false;
|
|
18
|
-
let initSent = false;
|
|
19
|
-
const pendingMessages = [];
|
|
20
|
-
const events = createEventRegistry();
|
|
21
|
-
const localListeners = {};
|
|
22
|
-
const transport = injectedTransport ?? createWebSocketTransport({
|
|
23
|
-
url,
|
|
24
|
-
role: "client",
|
|
25
|
-
sessionId,
|
|
26
|
-
metadata: { name: displayName }
|
|
27
|
-
});
|
|
28
|
-
const ownsTransport = !injectedTransport;
|
|
29
|
-
const exportManager = createPendingExportManager((message) => send(message));
|
|
30
|
-
function send(msg) {
|
|
31
|
-
if (!transport.ready) {
|
|
32
|
-
pendingMessages.push(msg);
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
transport.send(msg);
|
|
36
|
-
}
|
|
37
|
-
transport.onReady(() => {
|
|
38
|
-
pendingMessages.length = 0;
|
|
39
|
-
initSent = false;
|
|
40
|
-
sendInit();
|
|
41
|
-
if (autoOpen) transport.send({
|
|
42
|
-
type: "@statelyai.requestOpen",
|
|
43
|
-
sessionId
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
transport.onMessage((msg) => {
|
|
47
|
-
if (destroyed) return;
|
|
48
|
-
switch (msg.type) {
|
|
49
|
-
case "@statelyai.retrieved":
|
|
50
|
-
exportManager.resolve(msg.requestId, msg.data);
|
|
51
|
-
break;
|
|
52
|
-
case "@statelyai.error":
|
|
53
|
-
exportManager.reject(new Error(msg.message), msg.requestId);
|
|
54
|
-
emitLocal("error", {
|
|
55
|
-
code: msg.code,
|
|
56
|
-
message: msg.message
|
|
57
|
-
});
|
|
58
|
-
events.emit("error", {
|
|
59
|
-
code: msg.code,
|
|
60
|
-
message: msg.message
|
|
61
|
-
});
|
|
62
|
-
break;
|
|
63
|
-
default: break;
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
function emitLocal(event, data) {
|
|
67
|
-
const set = localListeners[event];
|
|
68
|
-
if (!set) return;
|
|
69
|
-
for (const handler of set) handler(data);
|
|
70
|
-
}
|
|
71
|
-
const actors = /* @__PURE__ */ new Map();
|
|
72
|
-
/** Tracks which actors we've already emitted local 'register' events for. */
|
|
73
|
-
const locallyRegistered = /* @__PURE__ */ new Set();
|
|
74
|
-
/**
|
|
75
|
-
* Maps target actorId → source actorId for the most recent `@xstate.event`.
|
|
76
|
-
* Read + cleared by `handleSnapshot` so the source info propagates into the
|
|
77
|
-
* `actorSnapshot` message. xstate emits `@xstate.event` immediately before
|
|
78
|
-
* `@xstate.snapshot` for the same actor.
|
|
79
|
-
*/
|
|
80
|
-
const pendingEventSource = /* @__PURE__ */ new Map();
|
|
81
|
-
function emitRegisterOnce(entry) {
|
|
82
|
-
if (locallyRegistered.has(entry.actorId)) return;
|
|
83
|
-
locallyRegistered.add(entry.actorId);
|
|
84
|
-
emitLocal("register", entry);
|
|
85
|
-
}
|
|
86
|
-
function snapshotValue(actorRef) {
|
|
87
|
-
try {
|
|
88
|
-
return serializeSnapshot(actorRef.getSnapshot());
|
|
89
|
-
} catch {
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
function toEntry(actorRef, rootActorId) {
|
|
94
|
-
return {
|
|
95
|
-
actorId: actorRef.sessionId,
|
|
96
|
-
parentActorId: actorRef._parent?.sessionId ?? null,
|
|
97
|
-
rootId: rootActorId,
|
|
98
|
-
id: actorRef.id,
|
|
99
|
-
systemId: actorRef.systemId,
|
|
100
|
-
snapshot: snapshotValue(actorRef),
|
|
101
|
-
machineConfig: extractMachineConfig(actorRef)
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
function toSystemEntry(entry) {
|
|
105
|
-
return {
|
|
106
|
-
actorId: entry.actorId,
|
|
107
|
-
parentActorId: entry.parentActorId,
|
|
108
|
-
id: entry.id,
|
|
109
|
-
machine: entry.machineConfig,
|
|
110
|
-
snapshot: entry.snapshot ?? void 0
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Walk the actor tree and populate the local `actors` map. Idempotent —
|
|
115
|
-
* existing entries stay in place but have their snapshot refreshed.
|
|
116
|
-
*/
|
|
117
|
-
function backfillActorTree(actorRef, rootActorId) {
|
|
118
|
-
const existing = actors.get(actorRef.sessionId);
|
|
119
|
-
const entry = existing ?? toEntry(actorRef, rootActorId);
|
|
120
|
-
if (existing) existing.snapshot = snapshotValue(actorRef);
|
|
121
|
-
else actors.set(entry.actorId, entry);
|
|
122
|
-
emitRegisterOnce(entry);
|
|
123
|
-
const children = actorRef.getSnapshot()?.children ?? {};
|
|
124
|
-
for (const child of Object.values(children)) if (child) backfillActorTree(child, rootActorId);
|
|
125
|
-
}
|
|
126
|
-
const inspectedRoots = /* @__PURE__ */ new Map();
|
|
127
|
-
function sendInit() {
|
|
128
|
-
for (const [rootActorId, { actor }] of inspectedRoots) backfillActorTree(actor, rootActorId);
|
|
129
|
-
send({
|
|
130
|
-
type: "@statelyai.system.init",
|
|
131
|
-
mode: "inspecting",
|
|
132
|
-
actors: Array.from(actors.values()).map(toSystemEntry),
|
|
133
|
-
selectedActorId: selectedActorId ?? inspectedRoots.keys().next().value ?? sessionId,
|
|
134
|
-
...theme && { theme },
|
|
135
|
-
...readOnly !== void 0 && { readOnly },
|
|
136
|
-
...depth !== void 0 && { depth },
|
|
137
|
-
...capabilities !== void 0 && { capabilities },
|
|
138
|
-
...panels?.leftPanels && { leftPanels: panels.leftPanels },
|
|
139
|
-
...panels?.rightPanels && { rightPanels: panels.rightPanels },
|
|
140
|
-
...panels?.activePanels && { activePanels: panels.activePanels }
|
|
141
|
-
});
|
|
142
|
-
initSent = true;
|
|
143
|
-
}
|
|
144
|
-
function handleActor(actorRef, rootActorId) {
|
|
145
|
-
if (actors.has(actorRef.sessionId)) return;
|
|
146
|
-
const entry = toEntry(actorRef, rootActorId);
|
|
147
|
-
actors.set(entry.actorId, entry);
|
|
148
|
-
if (!initSent) return;
|
|
149
|
-
send({
|
|
150
|
-
type: "@statelyai.system.actorRegistered",
|
|
151
|
-
actorId: entry.actorId,
|
|
152
|
-
parentActorId: entry.parentActorId,
|
|
153
|
-
id: entry.id,
|
|
154
|
-
machine: entry.machineConfig,
|
|
155
|
-
snapshot: entry.snapshot ?? void 0
|
|
156
|
-
});
|
|
157
|
-
emitRegisterOnce(entry);
|
|
158
|
-
}
|
|
159
|
-
function handleSnapshot(actorRef, snapshot, triggeringEvent, rootActorId) {
|
|
160
|
-
if (!actors.has(actorRef.sessionId)) handleActor(actorRef, rootActorId);
|
|
161
|
-
const entry = actors.get(actorRef.sessionId);
|
|
162
|
-
if (!entry) return;
|
|
163
|
-
const serialized = serializeSnapshot(snapshot);
|
|
164
|
-
entry.snapshot = serialized;
|
|
165
|
-
const sourceActorId = pendingEventSource.get(entry.actorId) ?? null;
|
|
166
|
-
pendingEventSource.delete(entry.actorId);
|
|
167
|
-
if (initSent) send({
|
|
168
|
-
type: "@statelyai.system.actorSnapshot",
|
|
169
|
-
actorId: entry.actorId,
|
|
170
|
-
snapshot: serialized,
|
|
171
|
-
event: triggeringEvent ?? null,
|
|
172
|
-
...sourceActorId ? { sourceActorId } : {}
|
|
173
|
-
});
|
|
174
|
-
emitLocal("snapshot", entry);
|
|
175
|
-
const status = snapshot?.status;
|
|
176
|
-
if (status === "done" || status === "stopped" || status === "error") {
|
|
177
|
-
actors.delete(entry.actorId);
|
|
178
|
-
pendingEventSource.delete(entry.actorId);
|
|
179
|
-
if (initSent) send({
|
|
180
|
-
type: "@statelyai.system.actorStopped",
|
|
181
|
-
actorId: entry.actorId
|
|
182
|
-
});
|
|
183
|
-
emitLocal("stopped", { actorId: entry.actorId });
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
function inspectActor(actor) {
|
|
187
|
-
const root = actor;
|
|
188
|
-
const rootActorId = root.sessionId;
|
|
189
|
-
const existing = inspectedRoots.get(rootActorId);
|
|
190
|
-
if (existing) return existing.subscription;
|
|
191
|
-
const subscription = root.system.inspect((inspectionEvent) => {
|
|
192
|
-
if (destroyed) return;
|
|
193
|
-
switch (inspectionEvent.type) {
|
|
194
|
-
case "@xstate.actor":
|
|
195
|
-
handleActor(inspectionEvent.actorRef, rootActorId);
|
|
196
|
-
break;
|
|
197
|
-
case "@xstate.event":
|
|
198
|
-
if (inspectionEvent.sourceRef) pendingEventSource.set(inspectionEvent.actorRef.sessionId, inspectionEvent.sourceRef.sessionId);
|
|
199
|
-
break;
|
|
200
|
-
case "@xstate.snapshot":
|
|
201
|
-
handleSnapshot(inspectionEvent.actorRef, inspectionEvent.snapshot, inspectionEvent.event, rootActorId);
|
|
202
|
-
break;
|
|
203
|
-
default: break;
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
inspectedRoots.set(rootActorId, {
|
|
207
|
-
actor: root,
|
|
208
|
-
subscription
|
|
209
|
-
});
|
|
210
|
-
backfillActorTree(root, rootActorId);
|
|
211
|
-
if (initSent) sendInit();
|
|
212
|
-
return { unsubscribe() {
|
|
213
|
-
subscription.unsubscribe();
|
|
214
|
-
inspectedRoots.delete(rootActorId);
|
|
215
|
-
} };
|
|
216
|
-
}
|
|
217
|
-
function manualRegister(id, opts) {
|
|
218
|
-
if (actors.has(id)) return;
|
|
219
|
-
const entry = {
|
|
220
|
-
actorId: id,
|
|
221
|
-
parentActorId: opts?.parent ?? null,
|
|
222
|
-
rootId: sessionId,
|
|
223
|
-
id,
|
|
224
|
-
systemId: opts?.systemId,
|
|
225
|
-
snapshot: opts?.snapshot ?? null,
|
|
226
|
-
machineConfig: opts?.machine ?? null
|
|
227
|
-
};
|
|
228
|
-
actors.set(id, entry);
|
|
229
|
-
if (initSent) send({
|
|
230
|
-
type: "@statelyai.system.actorRegistered",
|
|
231
|
-
actorId: id,
|
|
232
|
-
parentActorId: entry.parentActorId,
|
|
233
|
-
id,
|
|
234
|
-
machine: entry.machineConfig,
|
|
235
|
-
snapshot: entry.snapshot ?? void 0
|
|
236
|
-
});
|
|
237
|
-
emitRegisterOnce(entry);
|
|
238
|
-
}
|
|
239
|
-
function manualSnapshot(actorId, snapshot, event, sourceActorId) {
|
|
240
|
-
if (!actors.has(actorId)) manualRegister(actorId);
|
|
241
|
-
const entry = actors.get(actorId);
|
|
242
|
-
entry.snapshot = snapshot;
|
|
243
|
-
if (initSent) send({
|
|
244
|
-
type: "@statelyai.system.actorSnapshot",
|
|
245
|
-
actorId,
|
|
246
|
-
snapshot,
|
|
247
|
-
event: event ?? null,
|
|
248
|
-
...sourceActorId ? { sourceActorId } : {}
|
|
249
|
-
});
|
|
250
|
-
emitLocal("snapshot", entry);
|
|
251
|
-
}
|
|
252
|
-
function manualEvent(actorId, event, eventOpts) {
|
|
253
|
-
const eventObj = typeof event === "string" ? { type: event } : { ...event };
|
|
254
|
-
manualSnapshot(actorId, actors.get(actorId)?.snapshot ?? null, eventObj, eventOpts?.source ?? null);
|
|
255
|
-
}
|
|
256
|
-
function manualStop(actorId) {
|
|
257
|
-
if (!actors.has(actorId)) return;
|
|
258
|
-
actors.delete(actorId);
|
|
259
|
-
if (initSent) send({
|
|
260
|
-
type: "@statelyai.system.actorStopped",
|
|
261
|
-
actorId
|
|
262
|
-
});
|
|
263
|
-
emitLocal("stopped", { actorId });
|
|
264
|
-
}
|
|
265
|
-
return {
|
|
266
|
-
actors,
|
|
267
|
-
get sessionId() {
|
|
268
|
-
return sessionId;
|
|
269
|
-
},
|
|
270
|
-
inspect: inspectActor,
|
|
271
|
-
on(event, handler) {
|
|
272
|
-
if (!localListeners[event]) localListeners[event] = /* @__PURE__ */ new Set();
|
|
273
|
-
localListeners[event].add(handler);
|
|
274
|
-
return () => {
|
|
275
|
-
localListeners[event].delete(handler);
|
|
276
|
-
};
|
|
277
|
-
},
|
|
278
|
-
off(event, handler) {
|
|
279
|
-
localListeners[event]?.delete(handler);
|
|
280
|
-
},
|
|
281
|
-
export(format, callOptions) {
|
|
282
|
-
return exportManager.start(format, callOptions, "Inspector is destroyed", () => destroyed);
|
|
283
|
-
},
|
|
284
|
-
actor: manualRegister,
|
|
285
|
-
snapshot: manualSnapshot,
|
|
286
|
-
event: manualEvent,
|
|
287
|
-
stop: manualStop,
|
|
288
|
-
destroy() {
|
|
289
|
-
if (destroyed) return;
|
|
290
|
-
destroyed = true;
|
|
291
|
-
try {
|
|
292
|
-
for (const { subscription } of inspectedRoots.values()) subscription.unsubscribe();
|
|
293
|
-
} catch {}
|
|
294
|
-
if (ownsTransport) transport.destroy();
|
|
295
|
-
exportManager.clear("Inspector destroyed");
|
|
296
|
-
events.clear();
|
|
297
|
-
actors.clear();
|
|
298
|
-
inspectedRoots.clear();
|
|
299
|
-
pendingMessages.length = 0;
|
|
300
|
-
for (const set of Object.values(localListeners)) set?.clear();
|
|
301
|
-
}
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
//#endregion
|
|
306
|
-
export { createStatelyInspector };
|
|
3
|
+
export { createInspector, createStatelyInspector };
|
package/dist/patchTypes.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as EditorStateType, n as CanvasColor, o as GraphPatch, s as ImplementationSourceType, t as ActionLocation } from "./index-
|
|
1
|
+
import { a as EditorStateType, n as CanvasColor, o as GraphPatch, s as ImplementationSourceType, t as ActionLocation } from "./index-DVjNSTuQ.mjs";
|
|
2
2
|
export { type ActionLocation, type CanvasColor, type EditorStateType, type GraphPatch, type ImplementationSourceType };
|
package/dist/protocol.d.mts
CHANGED
|
@@ -29,6 +29,7 @@ interface EditorCapabilities {
|
|
|
29
29
|
panels?: string[];
|
|
30
30
|
commands?: string[];
|
|
31
31
|
}
|
|
32
|
+
type ReadOnlyReason = "free-plan" | "access-unverified";
|
|
32
33
|
type CapabilityDeniedCapability = "edit" | "export" | "ai" | "simulate" | "inspect" | "navigateHierarchy" | "panel" | "mode";
|
|
33
34
|
interface CapabilityDeniedEvent {
|
|
34
35
|
capability: CapabilityDeniedCapability;
|
|
@@ -178,6 +179,7 @@ interface MachineInitOptions {
|
|
|
178
179
|
mode?: EmbedMode;
|
|
179
180
|
theme?: "light" | "dark";
|
|
180
181
|
readOnly?: boolean;
|
|
182
|
+
readOnlyReason?: ReadOnlyReason;
|
|
181
183
|
depth?: number;
|
|
182
184
|
capabilities?: EditorCapabilities;
|
|
183
185
|
panels?: {
|
|
@@ -233,6 +235,7 @@ interface InitMessage {
|
|
|
233
235
|
mode?: EmbedMode;
|
|
234
236
|
theme?: "light" | "dark";
|
|
235
237
|
readOnly?: boolean;
|
|
238
|
+
readOnlyReason?: ReadOnlyReason;
|
|
236
239
|
depth?: number;
|
|
237
240
|
capabilities?: EditorCapabilities;
|
|
238
241
|
leftPanels?: string[];
|
|
@@ -335,8 +338,29 @@ interface ActorSystemEntry {
|
|
|
335
338
|
/** Optional current snapshot (`{value, status, ...}`). */
|
|
336
339
|
snapshot?: unknown;
|
|
337
340
|
}
|
|
341
|
+
/** JSON-safe record of an action executed during an inspected transition. */
|
|
342
|
+
interface InspectionAction {
|
|
343
|
+
type: string;
|
|
344
|
+
params?: unknown;
|
|
345
|
+
}
|
|
346
|
+
/** JSON-safe identity of a state transition taken during a macrostep. */
|
|
347
|
+
interface InspectionTakenTransition {
|
|
348
|
+
sourceStateId: string | null;
|
|
349
|
+
targetStateIds: string[];
|
|
350
|
+
eventType?: string;
|
|
351
|
+
reenter?: boolean;
|
|
352
|
+
}
|
|
353
|
+
/** JSON-safe record of an event sent or scheduled during a transition. */
|
|
354
|
+
interface InspectionSentEvent {
|
|
355
|
+
targetActorId?: string;
|
|
356
|
+
targetId: string;
|
|
357
|
+
event: unknown;
|
|
358
|
+
delay?: number;
|
|
359
|
+
id?: string;
|
|
360
|
+
}
|
|
338
361
|
interface SystemInitMessage {
|
|
339
362
|
type: "@statelyai.system.init";
|
|
363
|
+
protocolVersion?: number;
|
|
340
364
|
/** All known actors at the moment the system is first streamed. */
|
|
341
365
|
actors: ActorSystemEntry[];
|
|
342
366
|
/** Actor id the viz should focus first. Defaults to the root. */
|
|
@@ -364,10 +388,18 @@ interface SystemActorRegisteredMessage {
|
|
|
364
388
|
interface SystemActorSnapshotMessage {
|
|
365
389
|
type: "@statelyai.system.actorSnapshot";
|
|
366
390
|
actorId: string;
|
|
391
|
+
/** Snapshot before the event was processed. */
|
|
392
|
+
previousSnapshot?: unknown | null;
|
|
367
393
|
snapshot: unknown;
|
|
368
394
|
event?: unknown | null;
|
|
369
395
|
/** The actorId of the actor that sent the triggering event, if known. */
|
|
370
396
|
sourceActorId?: string | null;
|
|
397
|
+
/** Actions executed while processing the event. */
|
|
398
|
+
actions?: InspectionAction[];
|
|
399
|
+
/** State transitions taken across every microstep. */
|
|
400
|
+
transitions?: InspectionTakenTransition[];
|
|
401
|
+
/** Events sent or scheduled while processing the event. */
|
|
402
|
+
sent?: InspectionSentEvent[];
|
|
371
403
|
}
|
|
372
404
|
/** An actor reached a final state / was stopped. */
|
|
373
405
|
interface SystemActorStoppedMessage {
|
|
@@ -465,6 +497,7 @@ type ClientMessage = InitMessage | SetApiKeyMessage | ProjectInitMessage | Proje
|
|
|
465
497
|
type VizMessage = ReadyMessage | LoadedMessage | ChangeMessage | SaveMessage | ProjectMachineSelectedMessage | RetrievedMessage | ErrorMessage | CapabilityDeniedMessage | UploadRequestMessage;
|
|
466
498
|
interface RegisterMessage {
|
|
467
499
|
type: "@statelyai.register";
|
|
500
|
+
protocolVersion?: number;
|
|
468
501
|
role: "client" | "viz";
|
|
469
502
|
sessionId: string;
|
|
470
503
|
metadata?: {
|
|
@@ -474,10 +507,7 @@ interface RegisterMessage {
|
|
|
474
507
|
}
|
|
475
508
|
interface RegisteredMessage {
|
|
476
509
|
type: "@statelyai.registered";
|
|
477
|
-
|
|
478
|
-
}
|
|
479
|
-
interface RequestOpenMessage {
|
|
480
|
-
type: "@statelyai.requestOpen";
|
|
510
|
+
protocolVersion?: number;
|
|
481
511
|
sessionId: string;
|
|
482
512
|
}
|
|
483
513
|
/**
|
|
@@ -505,9 +535,11 @@ interface SessionAddedMessage {
|
|
|
505
535
|
sessionId: string;
|
|
506
536
|
}
|
|
507
537
|
/** All session-management messages for the WS relay. */
|
|
508
|
-
type SessionMessage = RegisterMessage | RegisteredMessage |
|
|
538
|
+
type SessionMessage = RegisterMessage | RegisteredMessage | AddSessionMessage | SessionAddedMessage;
|
|
509
539
|
/** Any valid protocol message. */
|
|
510
540
|
type ProtocolMessage = ClientMessage | VizMessage | SessionMessage;
|
|
511
541
|
declare const PREFIX = "@statelyai.";
|
|
542
|
+
/** Current WebSocket inspection protocol version. */
|
|
543
|
+
declare const INSPECTION_PROTOCOL_VERSION = 1;
|
|
512
544
|
//#endregion
|
|
513
|
-
export { ActorSystemEntry, AddSessionMessage, CapabilityDeniedCapability, CapabilityDeniedEvent, CapabilityDeniedMessage, ChangeMessage, ClientMessage, CommentsConfig, EditorCapabilities, EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ErrorMessage, ExportCallOptions, ExportFormat, ExportFormatMap, InitMessage, InitOptions, InspectSnapshotMessage, LoadedMessage, MachineInitOptions, MachineSourceLocations, PREFIX, ProjectEmbedMachine, ProjectInitMessage, ProjectInitOptions, ProjectMachineSelectedMessage, ProjectSelectMachineMessage, ProjectUpdateMessage, ProtocolMessage, ReadyMessage, RegisterMessage, RegisteredMessage,
|
|
545
|
+
export { ActorSystemEntry, AddSessionMessage, CapabilityDeniedCapability, CapabilityDeniedEvent, CapabilityDeniedMessage, ChangeMessage, ClientMessage, CommentsConfig, EditorCapabilities, EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ErrorMessage, ExportCallOptions, ExportFormat, ExportFormatMap, INSPECTION_PROTOCOL_VERSION, InitMessage, InitOptions, InspectSnapshotMessage, InspectionAction, InspectionSentEvent, InspectionTakenTransition, LoadedMessage, MachineInitOptions, MachineSourceLocations, PREFIX, ProjectEmbedMachine, ProjectInitMessage, ProjectInitOptions, ProjectMachineSelectedMessage, ProjectSelectMachineMessage, ProjectUpdateMessage, ProtocolMessage, ReadOnlyReason, ReadyMessage, RegisterMessage, RegisteredMessage, RetrieveMessage, RetrievedMessage, SaveMessage, SessionAddedMessage, SessionMessage, SetApiKeyMessage, SetModeMessage, SetSettingsMessage, SetThemeMessage, SourceLocation, SourceRange, StateSourceLocation, SystemActorRegisteredMessage, SystemActorSnapshotMessage, SystemActorStoppedMessage, SystemInitMessage, ToastMessage, UpdateMessage, UploadCapabilitiesMessage, UploadFileInfo, UploadRequestMessage, UploadResponseMessage, UploadResult, ValidationIssue, VizMessage };
|
package/dist/protocol.mjs
CHANGED
package/dist/relay.d.mts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ProtocolMessage } from "./protocol.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/relay.d.ts
|
|
4
|
+
type InspectionRelayRole = 'client' | 'viz';
|
|
5
|
+
interface InspectionRelayPeer {
|
|
6
|
+
id: string;
|
|
7
|
+
role: InspectionRelayRole;
|
|
8
|
+
primarySessionId: string;
|
|
9
|
+
sessionIds: string[];
|
|
10
|
+
}
|
|
11
|
+
interface InspectionRelaySnapshot {
|
|
12
|
+
sessions: Record<string, ProtocolMessage[]>;
|
|
13
|
+
}
|
|
14
|
+
type InspectionRelayEffect = {
|
|
15
|
+
type: 'send';
|
|
16
|
+
peerId: string;
|
|
17
|
+
message: ProtocolMessage;
|
|
18
|
+
};
|
|
19
|
+
interface InspectionRelay {
|
|
20
|
+
/** Restore a live peer after process/DO hibernation. */
|
|
21
|
+
connect(peer: InspectionRelayPeer): void;
|
|
22
|
+
disconnect(peerId: string): void;
|
|
23
|
+
clear(): void;
|
|
24
|
+
peer(peerId: string): InspectionRelayPeer | undefined;
|
|
25
|
+
receive(peerId: string, raw: unknown): InspectionRelayEffect[];
|
|
26
|
+
snapshot(): InspectionRelaySnapshot;
|
|
27
|
+
}
|
|
28
|
+
interface CreateInspectionRelayOptions {
|
|
29
|
+
snapshot?: InspectionRelaySnapshot;
|
|
30
|
+
maxReplayMessages?: number;
|
|
31
|
+
/** Maximum sessions retained for late-join replay. Default 100. */
|
|
32
|
+
maxReplaySessions?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Runtime-neutral WebSocket inspection room.
|
|
36
|
+
*
|
|
37
|
+
* It owns protocol registration, routing, multiplexed session membership, and
|
|
38
|
+
* bounded late-join replay. Node and Durable Object adapters only translate
|
|
39
|
+
* `send` effects to their native WebSocket APIs and persist `snapshot()`.
|
|
40
|
+
*/
|
|
41
|
+
declare function createInspectionRelay(options?: CreateInspectionRelayOptions): InspectionRelay;
|
|
42
|
+
//#endregion
|
|
43
|
+
export { CreateInspectionRelayOptions, InspectionRelay, InspectionRelayEffect, InspectionRelayPeer, InspectionRelayRole, InspectionRelaySnapshot, createInspectionRelay };
|
package/dist/relay.mjs
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { INSPECTION_PROTOCOL_VERSION, PREFIX } from "./protocol.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/relay.ts
|
|
4
|
+
function parseMessage(raw) {
|
|
5
|
+
if (raw instanceof ArrayBuffer) raw = new TextDecoder().decode(raw);
|
|
6
|
+
if (typeof raw === "string") try {
|
|
7
|
+
raw = JSON.parse(raw);
|
|
8
|
+
} catch {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
12
|
+
const message = raw;
|
|
13
|
+
return typeof message.type === "string" && message.type.startsWith(PREFIX) ? message : null;
|
|
14
|
+
}
|
|
15
|
+
function errorMessage(code, message) {
|
|
16
|
+
return {
|
|
17
|
+
type: "@statelyai.error",
|
|
18
|
+
code,
|
|
19
|
+
message
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function compactReplay(replay, message, max) {
|
|
23
|
+
const record = message;
|
|
24
|
+
const type = record.type;
|
|
25
|
+
if (type === "@statelyai.system.init") for (let index = replay.length - 1; index >= 0; index--) {
|
|
26
|
+
const replayType = replay[index].type;
|
|
27
|
+
if (replayType === "@statelyai.system.init" || replayType.startsWith("@statelyai.system.actor")) replay.splice(index, 1);
|
|
28
|
+
}
|
|
29
|
+
else if (type === "@statelyai.init") {
|
|
30
|
+
const index = replay.findIndex((entry) => entry.type === "@statelyai.init");
|
|
31
|
+
if (index >= 0) replay.splice(index, 1);
|
|
32
|
+
} else if (type === "@statelyai.system.actorSnapshot" || type === "@statelyai.inspectSnapshot") {
|
|
33
|
+
const actorId = record.actorId;
|
|
34
|
+
const index = replay.findIndex((entry) => {
|
|
35
|
+
const candidate = entry;
|
|
36
|
+
return candidate.type === type && candidate.actorId === actorId;
|
|
37
|
+
});
|
|
38
|
+
if (index >= 0) replay.splice(index, 1);
|
|
39
|
+
}
|
|
40
|
+
replay.push(message);
|
|
41
|
+
if (replay.length > max) replay.splice(0, replay.length - max);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Runtime-neutral WebSocket inspection room.
|
|
45
|
+
*
|
|
46
|
+
* It owns protocol registration, routing, multiplexed session membership, and
|
|
47
|
+
* bounded late-join replay. Node and Durable Object adapters only translate
|
|
48
|
+
* `send` effects to their native WebSocket APIs and persist `snapshot()`.
|
|
49
|
+
*/
|
|
50
|
+
function createInspectionRelay(options = {}) {
|
|
51
|
+
const maxReplayMessages = options.maxReplayMessages ?? 200;
|
|
52
|
+
const maxReplaySessions = Math.max(1, options.maxReplaySessions ?? 100);
|
|
53
|
+
const peers = /* @__PURE__ */ new Map();
|
|
54
|
+
const sessions = new Map(Object.entries(options.snapshot?.sessions ?? {}).slice(-maxReplaySessions).map(([id, replay]) => [id, [...replay]]));
|
|
55
|
+
const send = (peerId, message) => ({
|
|
56
|
+
type: "send",
|
|
57
|
+
peerId,
|
|
58
|
+
message
|
|
59
|
+
});
|
|
60
|
+
function replayTo(peerId, sessionId) {
|
|
61
|
+
return (sessions.get(sessionId) ?? []).map((message) => send(peerId, message));
|
|
62
|
+
}
|
|
63
|
+
function oppositePeers(sender, sessionId) {
|
|
64
|
+
return Array.from(peers.values()).filter((peer) => peer.id !== sender.id && peer.role !== sender.role && peer.sessionIds.includes(sessionId));
|
|
65
|
+
}
|
|
66
|
+
function retainReplay(sessionId, replay) {
|
|
67
|
+
sessions.delete(sessionId);
|
|
68
|
+
sessions.set(sessionId, replay);
|
|
69
|
+
while (sessions.size > maxReplaySessions) {
|
|
70
|
+
const oldestSessionId = sessions.keys().next().value;
|
|
71
|
+
if (oldestSessionId === void 0) break;
|
|
72
|
+
sessions.delete(oldestSessionId);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
connect(peer) {
|
|
77
|
+
peers.set(peer.id, {
|
|
78
|
+
...peer,
|
|
79
|
+
sessionIds: Array.from(new Set([peer.primarySessionId, ...peer.sessionIds]))
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
disconnect(peerId) {
|
|
83
|
+
peers.delete(peerId);
|
|
84
|
+
},
|
|
85
|
+
clear() {
|
|
86
|
+
peers.clear();
|
|
87
|
+
sessions.clear();
|
|
88
|
+
},
|
|
89
|
+
peer(peerId) {
|
|
90
|
+
const peer = peers.get(peerId);
|
|
91
|
+
return peer ? {
|
|
92
|
+
...peer,
|
|
93
|
+
sessionIds: [...peer.sessionIds]
|
|
94
|
+
} : void 0;
|
|
95
|
+
},
|
|
96
|
+
receive(peerId, raw) {
|
|
97
|
+
const message = parseMessage(raw);
|
|
98
|
+
if (!message) return [];
|
|
99
|
+
if (message.type === "@statelyai.register") {
|
|
100
|
+
const role = message.role;
|
|
101
|
+
const sessionId = message.sessionId;
|
|
102
|
+
const protocolVersion = message.protocolVersion;
|
|
103
|
+
if (role !== "client" && role !== "viz" || typeof sessionId !== "string" || sessionId.length === 0) return [send(peerId, errorMessage("invalid_registration", "Invalid relay registration"))];
|
|
104
|
+
if (typeof protocolVersion === "number" && protocolVersion > INSPECTION_PROTOCOL_VERSION) return [send(peerId, errorMessage("unsupported_protocol", `Protocol ${protocolVersion} is not supported`))];
|
|
105
|
+
const peer = {
|
|
106
|
+
id: peerId,
|
|
107
|
+
role,
|
|
108
|
+
primarySessionId: sessionId,
|
|
109
|
+
sessionIds: [sessionId]
|
|
110
|
+
};
|
|
111
|
+
peers.set(peerId, peer);
|
|
112
|
+
const effects = [send(peerId, {
|
|
113
|
+
type: "@statelyai.registered",
|
|
114
|
+
protocolVersion: INSPECTION_PROTOCOL_VERSION,
|
|
115
|
+
sessionId
|
|
116
|
+
})];
|
|
117
|
+
if (role === "viz") effects.push(...replayTo(peerId, sessionId));
|
|
118
|
+
return effects;
|
|
119
|
+
}
|
|
120
|
+
const sender = peers.get(peerId);
|
|
121
|
+
if (!sender) return [send(peerId, errorMessage("not_registered", "Register before sending messages"))];
|
|
122
|
+
if (message.type === "@statelyai.addSession") {
|
|
123
|
+
const sessionId = message.sessionId;
|
|
124
|
+
if (typeof sessionId !== "string" || sessionId.length === 0) return [send(peerId, errorMessage("invalid_session", "Invalid session id"))];
|
|
125
|
+
if (!sender.sessionIds.includes(sessionId)) sender.sessionIds.push(sessionId);
|
|
126
|
+
const effects = [send(peerId, {
|
|
127
|
+
type: "@statelyai.sessionAdded",
|
|
128
|
+
sessionId
|
|
129
|
+
})];
|
|
130
|
+
if (sender.role === "viz") effects.push(...replayTo(peerId, sessionId));
|
|
131
|
+
return effects;
|
|
132
|
+
}
|
|
133
|
+
const sessionId = (typeof message.sessionId === "string" ? message.sessionId : void 0) ?? sender.primarySessionId;
|
|
134
|
+
if (!sender.sessionIds.includes(sessionId)) return [send(peerId, errorMessage("unknown_session", "Peer is not registered for session"))];
|
|
135
|
+
const stamped = {
|
|
136
|
+
...message,
|
|
137
|
+
sessionId
|
|
138
|
+
};
|
|
139
|
+
if (sender.role === "client") {
|
|
140
|
+
const replay = sessions.get(sessionId) ?? [];
|
|
141
|
+
compactReplay(replay, stamped, maxReplayMessages);
|
|
142
|
+
retainReplay(sessionId, replay);
|
|
143
|
+
}
|
|
144
|
+
return oppositePeers(sender, sessionId).map((peer) => send(peer.id, stamped));
|
|
145
|
+
},
|
|
146
|
+
snapshot() {
|
|
147
|
+
return { sessions: Object.fromEntries(Array.from(sessions, ([sessionId, replay]) => [sessionId, [...replay]])) };
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
//#endregion
|
|
153
|
+
export { createInspectionRelay };
|
package/dist/studio.d.mts
CHANGED
package/dist/sync.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as DigraphConfig, i as StatelyGraph } from "./graph-
|
|
1
|
+
import { b as DigraphConfig, i as StatelyGraph } from "./graph-R0sbxnZ7.mjs";
|
|
2
2
|
import { CreateProjectInput, ProjectData, StudioClient, StudioMachineRecord, XStateVersion } from "./studio.mjs";
|
|
3
3
|
import { GraphDiff } from "@statelyai/graph";
|
|
4
4
|
|
package/dist/sync.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createStatelyClient } from "./studio.mjs";
|
|
2
|
-
import { d as xstateSourceToConfig, f as findStatelyPragmaAttachments, i as detectXStateSourceProfile, m as upsertStatelyPragma, p as getStatelyPragma, s as graphToXStateTS, t as INLINE_EXPRESSION_DIRECTIVE_FIELDS, u as serializeJS } from "./dist-
|
|
2
|
+
import { d as xstateSourceToConfig, f as findStatelyPragmaAttachments, i as detectXStateSourceProfile, m as upsertStatelyPragma, p as getStatelyPragma, s as graphToXStateTS, t as INLINE_EXPRESSION_DIRECTIVE_FIELDS, u as serializeJS } from "./dist-CHGcvOdQ.mjs";
|
|
3
3
|
import { fromStudioMachine, toStudioMachine } from "./graph.mjs";
|
|
4
4
|
import * as ts$1 from "typescript";
|
|
5
5
|
import ts from "typescript";
|