@statelyai/sdk 0.13.4 → 0.14.1

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/LICENSE CHANGED
@@ -1,10 +1,21 @@
1
- Copyright (c) 2025 Stately Software, Inc.
1
+ MIT License
2
2
 
3
- All rights reserved.
3
+ Copyright (c) 2026 Stately Software, Inc.
4
4
 
5
- This repository and the Stately Viz software are proprietary to Stately
6
- Software, Inc. No rights are granted to use, copy, modify, distribute, host, or
7
- sublicense this software except under a separate written agreement with Stately
8
- Software, Inc.
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
9
11
 
10
- For licensing inquiries, contact team@stately.ai.
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -115,21 +115,28 @@ Stream live actor-system state to the Stately inspector over WebSockets, with su
115
115
  import { createActor } from 'xstate';
116
116
  import { createInspector } from '@statelyai/sdk';
117
117
 
118
- const actor = createActor(machine);
119
118
  const inspector = createInspector({
120
119
  url: 'ws://localhost:4242',
121
120
  });
121
+ const { inspect } = inspector;
122
122
 
123
- inspector.inspect(actor);
123
+ const actor = createActor(machine, { inspect });
124
124
  actor.start();
125
125
  ```
126
126
 
127
- XState v5 and v6 inspection events normalize to actor, transition, and stop
128
- events before crossing the WebSocket protocol.
127
+ If you already have the actor reference, `inspector.attach(actor)` subscribes to
128
+ its system and backfills actors that are already running.
129
+
130
+ Stopped actors remain in `inspector.actors` and in reconnect checkpoints, so
131
+ completed request-scoped runs stay available for inspection.
132
+
133
+ XState v5 and v6 inspection events normalize to independent actor, event,
134
+ snapshot, and stop observations before crossing the WebSocket protocol.
129
135
  In Node, the inspector opens in the default browser automatically. The SDK
130
- generates a cryptographically random session capability; hosted inspectors send
131
- signed-out users through OAuth and return them to that same live session. The
132
- Node process does not need a Stately API key.
136
+ generates a cryptographically random session capability; hosted inspectors open
137
+ without requiring login. The session capability controls access to the live
138
+ session. AI-backed features remain separately authenticated. The Node process
139
+ does not need a Stately API key.
133
140
 
134
141
  ### CLI and sync
135
142
 
@@ -8713,6 +8713,7 @@ const validationIssueCodeSchema = _enum([
8713
8713
  "empty_parallel",
8714
8714
  "single_child_compound",
8715
8715
  "noop_transient_state",
8716
+ "sole_default_choice",
8716
8717
  "on_done_unreachable",
8717
8718
  "duplicate_transition",
8718
8719
  "invalid_delay",
package/dist/index.d.mts CHANGED
@@ -5,7 +5,7 @@ import { i as getCredentialToken, n as StatelyCredential, r as createAuthorizati
5
5
  import { AssetConfig, StatelyEmbed, StatelyEmbedOptions, createStatelyEmbed } from "./embed.mjs";
6
6
  import { _ as serializeJS, c as MachineConfigOptions, d as contextSchemaToTSType, f as eventsSchemaToTSType, g as raw, h as jsonSchemaToTSType, i as CodeGenGraph, l as RawCode, m as graphToXStateTS, o as GraphPatch, p as graphToMachineConfig, t as ActionLocation, u as XStateTSOptions } from "./index-DVjNSTuQ.mjs";
7
7
  import { C as EventTypeData, S as DigraphNodeConfig, _ as studioMachineConverter, a as StatelyGraphData, b as DigraphConfig, c as StatelyInvoke, d as StudioAction, f as StudioEdge, g as fromStudioMachine, h as StudioNode, i as StatelyGraph, l as StatelyNodeData, m as StudioMachine, o as StatelyGuard, r as StatelyEdgeData, t as StatelyAction, v as toStudioMachine, w as StateNodeJSONData, x as DigraphEdgeConfig, y as DigraphAction } from "./graph-R0sbxnZ7.mjs";
8
- import { a as InspectorEvents, c as createStatelyInspector, d as MultiplexedWebSocketConnectionOptions, f as Transport, h as createWebSocketTransport, i as Inspector, l as MultiplexedChannelOptions, m as createPostMessageTransport, n as CreateInspectorOptions, o as ManualActorOptions, p as createMultiplexedWebSocketConnection, r as InspectedTransition, s as createInspector, t as AdoptedActor, u as MultiplexedWebSocketConnection } from "./inspect-COqtklcn.mjs";
8
+ import { _ as createPostMessageTransport, a as InspectedTransition, c as InspectorInspectionEvent, d as createStatelyInspector, f as MultiplexedChannelOptions, g as createMultiplexedWebSocketConnection, h as Transport, i as InspectedSnapshot, l as ManualActorOptions, m as MultiplexedWebSocketConnectionOptions, n as CreateInspectorOptions, o as Inspector, p as MultiplexedWebSocketConnection, r as InspectedEvent, s as InspectorEvents, t as AdoptedActor, u as createInspector, v as createWebSocketTransport } from "./inspect-DQ_7I7eH.mjs";
9
9
  import { ConnectedRepo, CreateMachineFromDefinitionInput, CreateMachineFromTemplateInput, CreateMachineInput, CreateMachineTemplate, CreateProjectInput, EnsureProjectInput, ExtractMachinesResponse, ExtractedMachine, GetMachineOptions, ProjectData, ProjectMachine, ProjectVisibility, RepoType, StudioApiError, StudioClient, StudioClientOptions, StudioMachineRecord, UpdateMachineInput, VerifyApiKeyResponse, XStateVersion, createStatelyClient } from "./studio.mjs";
10
10
  import { OAuthAuthorizationServerMetadata, OAuthClientRegistrationResponse, OAuthProtectedResourceMetadata, OAuthTokenResponse, PkcePair, buildAuthorizeUrl, createPkcePair, discoverAuthorizationServer, discoverProtectedResource, exchangeCodeForToken, refreshToken, registerOAuthClient } from "./oauth.mjs";
11
11
  import { PlanSyncOptions, PullSyncResult, PushLocalMachineLinksResult, PushSyncOptions, PushSyncProjectOptions, PushSyncResult, ResolvedSyncInput, SyncInputFormat, SyncPlan, SyncPlanSummary } from "./sync.mjs";
@@ -32,4 +32,4 @@ declare function findStatelyPragmaAttachments(sourceText: string, fileName?: str
32
32
  declare function getStatelyPragma(sourceText: string, fileName?: string, machineIndex?: number): StatelyPragma | undefined;
33
33
  declare function upsertStatelyPragma(sourceText: string, id: string, options?: UpsertStatelyPragmaOptions): string;
34
34
  //#endregion
35
- export { type ActionLocation, type AdoptedActor, type AssetConfig, type AssetUploadAdapter, type AssetUploadContext, type AssetUploadRequest, type CapabilityDeniedCapability, type CapabilityDeniedEvent, type CodeGenGraph, type CommentsConfig, type ConnectedRepo, type CreateInspectionRelayOptions, type CreateInspectorOptions, type CreateMachineFromDefinitionInput, type CreateMachineFromTemplateInput, type CreateMachineInput, type CreateMachineTemplate, type CreateProjectInput, type CreateS3AssetUploadAdapterOptions, type CreateSupabaseAssetUploadAdapterOptions, type DigraphAction, type DigraphConfig, type DigraphEdgeConfig, type DigraphNodeConfig, type EditorCapabilities, type EmbedEventHandler, type EmbedEventMap, type EmbedEventName, type EmbedMode, type EnsureProjectInput, type EventTypeData, type ExportCallOptions, type ExportFormat, type ExportFormatMap, type ExtractMachinesResponse, type ExtractedMachine, type GetMachineOptions, type GraphPatch, INSPECTION_PROTOCOL_VERSION, type InitOptions, type InspectedTransition, type InspectionAction, type InspectionRelay, type InspectionRelayEffect, type InspectionRelayPeer, type InspectionRelayRole, type InspectionRelaySnapshot, type InspectionSentEvent, type InspectionTakenTransition, type Inspector, type InspectorEvents, type MachineConfigOptions, type ManualActorOptions, type MultiplexedChannelOptions, type MultiplexedWebSocketConnection, type MultiplexedWebSocketConnectionOptions, type OAuthAuthorizationServerMetadata, type OAuthClientRegistrationResponse, type OAuthProtectedResourceMetadata, type OAuthTokenResponse, type PkcePair, type PlanSyncOptions, type ProjectData, type ProjectEmbedMachine, type ProjectMachine, type ProjectVisibility, type PullSyncResult, type PushLocalMachineLinksResult, type PushSyncOptions, type PushSyncProjectOptions, type PushSyncResult, RawCode, type RepoType, type ResolvedSyncInput, type S3UploadTarget, type StateNodeJSONData, type StatelyAction, type StatelyApiClientOptions, StatelyApiError, type StatelyApiUrlOptions, type StatelyAuthMode, type StatelyCredential, type StatelyEdgeData, type StatelyEmbed, type StatelyEmbedOptions, type StatelyGraph, type StatelyGraphData, type StatelyGuard, type StatelyInvoke, type StatelyNodeData, type StatelyPragma, type StatelyPragmaAttachment, type StudioAction, StudioApiError, type StudioClient, type StudioClientOptions, type StudioEdge, type StudioMachine, type StudioMachineRecord, type StudioNode, type SupabaseStorageClient, type SyncInputFormat, type SyncPlan, type SyncPlanSummary, type Transport, type UpdateMachineInput, type UploadResult, type UpsertStatelyPragmaOptions, type VerifyApiKeyResponse, type XStateTSOptions, type XStateVersion, buildAuthorizeUrl, contextSchemaToTSType, createAuthorizationHeader, createInspectionRelay, createInspector, createMultiplexedWebSocketConnection, createPkcePair, createPostMessageTransport, createS3AssetUploadAdapter, createStatelyApiClient, createStatelyApiUrl, createStatelyClient, createStatelyEmbed, createStatelyInspector, createSupabaseAssetUploadAdapter, createWebSocketTransport, discoverAuthorizationServer, discoverProtectedResource, eventsSchemaToTSType, exchangeCodeForToken, findStatelyPragmaAttachments, fromStudioMachine, getCredentialToken, getStatelyPragma, graphToMachineConfig, graphToXStateTS, jsonSchemaToTSType, raw, refreshToken, registerOAuthClient, serializeJS, studioMachineConverter, toStudioMachine, upsertStatelyPragma };
35
+ export { type ActionLocation, type AdoptedActor, type AssetConfig, type AssetUploadAdapter, type AssetUploadContext, type AssetUploadRequest, type CapabilityDeniedCapability, type CapabilityDeniedEvent, type CodeGenGraph, type CommentsConfig, type ConnectedRepo, type CreateInspectionRelayOptions, type CreateInspectorOptions, type CreateMachineFromDefinitionInput, type CreateMachineFromTemplateInput, type CreateMachineInput, type CreateMachineTemplate, type CreateProjectInput, type CreateS3AssetUploadAdapterOptions, type CreateSupabaseAssetUploadAdapterOptions, type DigraphAction, type DigraphConfig, type DigraphEdgeConfig, type DigraphNodeConfig, type EditorCapabilities, type EmbedEventHandler, type EmbedEventMap, type EmbedEventName, type EmbedMode, type EnsureProjectInput, type EventTypeData, type ExportCallOptions, type ExportFormat, type ExportFormatMap, type ExtractMachinesResponse, type ExtractedMachine, type GetMachineOptions, type GraphPatch, INSPECTION_PROTOCOL_VERSION, type InitOptions, type InspectedEvent, type InspectedSnapshot, type InspectedTransition, type InspectionAction, type InspectionRelay, type InspectionRelayEffect, type InspectionRelayPeer, type InspectionRelayRole, type InspectionRelaySnapshot, type InspectionSentEvent, type InspectionTakenTransition, type Inspector, type InspectorEvents, type InspectorInspectionEvent, type MachineConfigOptions, type ManualActorOptions, type MultiplexedChannelOptions, type MultiplexedWebSocketConnection, type MultiplexedWebSocketConnectionOptions, type OAuthAuthorizationServerMetadata, type OAuthClientRegistrationResponse, type OAuthProtectedResourceMetadata, type OAuthTokenResponse, type PkcePair, type PlanSyncOptions, type ProjectData, type ProjectEmbedMachine, type ProjectMachine, type ProjectVisibility, type PullSyncResult, type PushLocalMachineLinksResult, type PushSyncOptions, type PushSyncProjectOptions, type PushSyncResult, RawCode, type RepoType, type ResolvedSyncInput, type S3UploadTarget, type StateNodeJSONData, type StatelyAction, type StatelyApiClientOptions, StatelyApiError, type StatelyApiUrlOptions, type StatelyAuthMode, type StatelyCredential, type StatelyEdgeData, type StatelyEmbed, type StatelyEmbedOptions, type StatelyGraph, type StatelyGraphData, type StatelyGuard, type StatelyInvoke, type StatelyNodeData, type StatelyPragma, type StatelyPragmaAttachment, type StudioAction, StudioApiError, type StudioClient, type StudioClientOptions, type StudioEdge, type StudioMachine, type StudioMachineRecord, type StudioNode, type SupabaseStorageClient, type SyncInputFormat, type SyncPlan, type SyncPlanSummary, type Transport, type UpdateMachineInput, type UploadResult, type UpsertStatelyPragmaOptions, type VerifyApiKeyResponse, type XStateTSOptions, type XStateVersion, buildAuthorizeUrl, contextSchemaToTSType, createAuthorizationHeader, createInspectionRelay, createInspector, createMultiplexedWebSocketConnection, createPkcePair, createPostMessageTransport, createS3AssetUploadAdapter, createStatelyApiClient, createStatelyApiUrl, createStatelyClient, createStatelyEmbed, createStatelyInspector, createSupabaseAssetUploadAdapter, createWebSocketTransport, discoverAuthorizationServer, discoverProtectedResource, eventsSchemaToTSType, exchangeCodeForToken, findStatelyPragmaAttachments, fromStudioMachine, getCredentialToken, getStatelyPragma, graphToMachineConfig, graphToXStateTS, jsonSchemaToTSType, raw, refreshToken, registerOAuthClient, serializeJS, studioMachineConverter, toStudioMachine, upsertStatelyPragma };
package/dist/index.mjs CHANGED
@@ -2,12 +2,12 @@ import { n as createPostMessageTransport, r as createWebSocketTransport, t as cr
2
2
  import { INSPECTION_PROTOCOL_VERSION } from "./protocol.mjs";
3
3
  import { createStatelyEmbed } from "./embed.mjs";
4
4
  import { createS3AssetUploadAdapter, createSupabaseAssetUploadAdapter } from "./assetStorage.mjs";
5
- import { n as createStatelyInspector, t as createInspector } from "./inspect-pcNCbL7j.mjs";
5
+ import { n as createStatelyInspector, t as createInspector } from "./inspect-BcKTFJI1.mjs";
6
6
  import { createAuthorizationHeader, getCredentialToken } from "./auth.mjs";
7
7
  import { StudioApiError, createStatelyClient } from "./studio.mjs";
8
8
  import { buildAuthorizeUrl, createPkcePair, discoverAuthorizationServer, discoverProtectedResource, exchangeCodeForToken, refreshToken, registerOAuthClient } from "./oauth.mjs";
9
9
  import { StatelyApiError, createStatelyApiClient, createStatelyApiUrl } from "./api.mjs";
10
- import { a as eventsSchemaToTSType, c as jsonSchemaToTSType, f as findStatelyPragmaAttachments, l as raw, m as upsertStatelyPragma, n as RawCode, o as graphToMachineConfig, p as getStatelyPragma, r as contextSchemaToTSType, s as graphToXStateTS, u as serializeJS } from "./dist-CHGcvOdQ.mjs";
10
+ import { a as eventsSchemaToTSType, c as jsonSchemaToTSType, f as findStatelyPragmaAttachments, l as raw, m as upsertStatelyPragma, n as RawCode, o as graphToMachineConfig, p as getStatelyPragma, r as contextSchemaToTSType, s as graphToXStateTS, u as serializeJS } from "./dist-C8jVuuHf.mjs";
11
11
  import { fromStudioMachine, studioMachineConverter, toStudioMachine } from "./graph.mjs";
12
12
  import { createInspectionRelay } from "./relay.mjs";
13
13
 
@@ -33,6 +33,10 @@ const defaultSerializeSnapshot = (snapshot) => ({
33
33
  status: snapshot?.status
34
34
  });
35
35
  const defaultExtractMachineConfig = (actor, source) => actor?.logic?.config ?? source?.config ?? null;
36
+ function isStoppedSnapshot(snapshot) {
37
+ const status = snapshot?.status;
38
+ return status === "done" || status === "stopped" || status === "error";
39
+ }
36
40
  function generateSessionId() {
37
41
  if (!globalThis.crypto?.randomUUID) throw new Error("createInspector() requires crypto.randomUUID() to generate a secure session capability. Pass sessionId explicitly in older runtimes.");
38
42
  return globalThis.crypto.randomUUID();
@@ -143,6 +147,13 @@ function createInspector(options = {}) {
143
147
  return null;
144
148
  }
145
149
  }
150
+ function stoppedValue(actorRef, snapshot) {
151
+ try {
152
+ return isStoppedSnapshot(snapshot ?? actorRef.getSnapshot());
153
+ } catch {
154
+ return false;
155
+ }
156
+ }
146
157
  function toEntry(actorRef, rootActorId, details) {
147
158
  return {
148
159
  actorId: actorRef.sessionId,
@@ -151,6 +162,7 @@ function createInspector(options = {}) {
151
162
  id: details?.id ?? actorRef.id ?? actorRef.sessionId,
152
163
  systemId: actorRef.systemId,
153
164
  snapshot: details?.snapshot ? serializeSnapshot(details.snapshot) : snapshotValue(actorRef),
165
+ stopped: stoppedValue(actorRef, details?.snapshot),
154
166
  machineConfig: extractMachineConfig(actorRef, details?.source ?? actorRef.src)
155
167
  };
156
168
  }
@@ -160,7 +172,8 @@ function createInspector(options = {}) {
160
172
  parentActorId: entry.parentActorId,
161
173
  id: entry.id,
162
174
  machine: entry.machineConfig,
163
- snapshot: entry.snapshot ?? void 0
175
+ snapshot: entry.snapshot ?? void 0,
176
+ ...entry.stopped && { stopped: true }
164
177
  };
165
178
  }
166
179
  /**
@@ -170,13 +183,17 @@ function createInspector(options = {}) {
170
183
  function backfillActorTree(actorRef, rootActorId) {
171
184
  const existing = actors.get(actorRef.sessionId);
172
185
  const entry = existing ?? toEntry(actorRef, rootActorId);
173
- if (existing) existing.snapshot = snapshotValue(actorRef);
174
- else actors.set(entry.actorId, entry);
186
+ if (existing) {
187
+ const snapshot = actorRef.getSnapshot();
188
+ existing.snapshot = serializeSnapshot(snapshot);
189
+ existing.stopped ||= isStoppedSnapshot(snapshot);
190
+ } else actors.set(entry.actorId, entry);
175
191
  emitRegisterOnce(entry);
176
192
  const children = actorRef.getSnapshot()?.children ?? {};
177
193
  for (const child of Object.values(children)) if (child) backfillActorTree(child, rootActorId);
178
194
  }
179
195
  const inspectedRoots = /* @__PURE__ */ new Map();
196
+ const observedRootIds = /* @__PURE__ */ new Set();
180
197
  function sendInit() {
181
198
  for (const [rootActorId, { actor }] of inspectedRoots) backfillActorTree(actor, rootActorId);
182
199
  send({
@@ -184,7 +201,7 @@ function createInspector(options = {}) {
184
201
  protocolVersion: INSPECTION_PROTOCOL_VERSION,
185
202
  mode: "inspecting",
186
203
  actors: Array.from(actors.values()).map(toSystemEntry),
187
- selectedActorId: selectedActorId ?? inspectedRoots.keys().next().value ?? sessionId,
204
+ selectedActorId: selectedActorId ?? observedRootIds.values().next().value ?? sessionId,
188
205
  ...theme && { theme },
189
206
  ...readOnly !== void 0 && { readOnly },
190
207
  ...depth !== void 0 && { depth },
@@ -246,6 +263,20 @@ function createInspector(options = {}) {
246
263
  sent: []
247
264
  };
248
265
  }
266
+ function handleEvent(actorId, event, sourceActorId) {
267
+ const inspectedEvent = {
268
+ actorId,
269
+ sourceActorId,
270
+ event
271
+ };
272
+ if (initSent) send({
273
+ type: "@statelyai.system.actorEvent",
274
+ actorId,
275
+ event,
276
+ sourceActorId
277
+ });
278
+ emitLocal("event", inspectedEvent);
279
+ }
249
280
  function getPendingTransition(actorRef, event) {
250
281
  const existing = pendingTransitions.get(actorRef.sessionId);
251
282
  if (existing) return existing;
@@ -258,7 +289,7 @@ function createInspector(options = {}) {
258
289
  const entry = actors.get(actorRef.sessionId);
259
290
  if (!entry) return;
260
291
  const serialized = serializeSnapshot(snapshot);
261
- const inspectedTransition = {
292
+ const inspectedSnapshot = {
262
293
  actorId: entry.actorId,
263
294
  sourceActorId: transition.sourceActorId,
264
295
  previousSnapshot: transition.previousSnapshot,
@@ -268,24 +299,25 @@ function createInspector(options = {}) {
268
299
  transitions: transition.transitions,
269
300
  sent: transition.sent
270
301
  };
302
+ const wasStopped = entry.stopped;
271
303
  entry.snapshot = serialized;
304
+ const stopped = isStoppedSnapshot(snapshot);
305
+ entry.stopped ||= stopped;
272
306
  pendingTransitions.delete(entry.actorId);
273
307
  if (initSent) send({
274
308
  type: "@statelyai.system.actorSnapshot",
275
309
  actorId: entry.actorId,
276
- previousSnapshot: inspectedTransition.previousSnapshot,
277
- snapshot: inspectedTransition.snapshot,
278
- event: inspectedTransition.event,
279
- sourceActorId: inspectedTransition.sourceActorId,
280
- actions: inspectedTransition.actions,
281
- transitions: inspectedTransition.transitions,
282
- sent: inspectedTransition.sent
310
+ previousSnapshot: inspectedSnapshot.previousSnapshot,
311
+ snapshot: inspectedSnapshot.snapshot,
312
+ event: inspectedSnapshot.event,
313
+ sourceActorId: inspectedSnapshot.sourceActorId,
314
+ actions: inspectedSnapshot.actions,
315
+ transitions: inspectedSnapshot.transitions,
316
+ sent: inspectedSnapshot.sent
283
317
  });
284
- emitLocal("transition", inspectedTransition);
285
- emitLocal("snapshot", entry);
286
- const status = snapshot?.status;
287
- if (status === "done" || status === "stopped" || status === "error") {
288
- actors.delete(entry.actorId);
318
+ emitLocal("snapshot", inspectedSnapshot);
319
+ emitLocal("transition", inspectedSnapshot);
320
+ if (stopped && !wasStopped) {
289
321
  pendingTransitions.delete(entry.actorId);
290
322
  if (initSent) send({
291
323
  type: "@statelyai.system.actorStopped",
@@ -296,50 +328,59 @@ function createInspector(options = {}) {
296
328
  emitLocal("stopped", stopped);
297
329
  }
298
330
  }
299
- function inspectActor(actor) {
331
+ function handleInspectionEvent(inspectionEvent) {
332
+ if (destroyed) return;
333
+ const event = inspectionEvent;
334
+ const rootActorId = event.rootId;
335
+ const isNewRoot = !observedRootIds.has(rootActorId);
336
+ observedRootIds.add(rootActorId);
337
+ switch (event.type) {
338
+ case "@xstate.actor":
339
+ handleActor(event.actorRef, rootActorId, {
340
+ parentRef: event.parentRef,
341
+ id: event.id,
342
+ source: event.src,
343
+ snapshot: event.snapshot
344
+ });
345
+ break;
346
+ case "@xstate.event":
347
+ if (!actors.has(event.actorRef.sessionId)) handleActor(event.actorRef, rootActorId);
348
+ handleEvent(event.actorRef.sessionId, event.event, event.sourceRef?.sessionId ?? null);
349
+ pendingTransitions.set(event.actorRef.sessionId, createPendingTransition(event.actorRef, event.event, event.sourceRef));
350
+ break;
351
+ case "@xstate.action":
352
+ getPendingTransition(event.actorRef).actions.push(normalizeAction(event.action));
353
+ break;
354
+ case "@xstate.microstep":
355
+ getPendingTransition(event.actorRef, event.event).transitions.push(...(event._transitions ?? []).map(normalizeTakenTransition));
356
+ break;
357
+ case "@xstate.snapshot": {
358
+ const pending = getPendingTransition(event.actorRef, event.event);
359
+ handleTransition(event.actorRef, event.snapshot, event.event, rootActorId, pending);
360
+ break;
361
+ }
362
+ case "@xstate.transition":
363
+ if (!event.actions || !event.microsteps || !event.sent) break;
364
+ handleTransition(event.actorRef, event.snapshot, event.event, rootActorId, {
365
+ previousSnapshot: actors.get(event.actorRef.sessionId)?.snapshot ?? null,
366
+ event: event.event,
367
+ sourceActorId: event.sourceRef?.sessionId ?? null,
368
+ actions: event.actions.map(normalizeAction),
369
+ transitions: event.microsteps.map(normalizeTakenTransition),
370
+ sent: event.sent.map(normalizeSentEvent)
371
+ });
372
+ break;
373
+ default: break;
374
+ }
375
+ if (isNewRoot && initSent) sendInit();
376
+ }
377
+ function attachActor(actor) {
300
378
  const root = actor;
301
379
  const rootActorId = root.sessionId;
302
380
  const existing = inspectedRoots.get(rootActorId);
303
381
  if (existing) return existing.subscription;
304
- const subscription = root.system.inspect((inspectionEvent) => {
305
- if (destroyed) return;
306
- switch (inspectionEvent.type) {
307
- case "@xstate.actor":
308
- handleActor(inspectionEvent.actorRef, rootActorId, {
309
- parentRef: inspectionEvent.parentRef,
310
- id: inspectionEvent.id,
311
- source: inspectionEvent.src,
312
- snapshot: inspectionEvent.snapshot
313
- });
314
- break;
315
- case "@xstate.event":
316
- pendingTransitions.set(inspectionEvent.actorRef.sessionId, createPendingTransition(inspectionEvent.actorRef, inspectionEvent.event, inspectionEvent.sourceRef));
317
- break;
318
- case "@xstate.action":
319
- getPendingTransition(inspectionEvent.actorRef).actions.push(normalizeAction(inspectionEvent.action));
320
- break;
321
- case "@xstate.microstep":
322
- getPendingTransition(inspectionEvent.actorRef, inspectionEvent.event).transitions.push(...(inspectionEvent._transitions ?? []).map(normalizeTakenTransition));
323
- break;
324
- case "@xstate.snapshot": {
325
- const pending = getPendingTransition(inspectionEvent.actorRef, inspectionEvent.event);
326
- handleTransition(inspectionEvent.actorRef, inspectionEvent.snapshot, inspectionEvent.event, rootActorId, pending);
327
- break;
328
- }
329
- case "@xstate.transition":
330
- if (!inspectionEvent.actions || !inspectionEvent.microsteps || !inspectionEvent.sent) break;
331
- handleTransition(inspectionEvent.actorRef, inspectionEvent.snapshot, inspectionEvent.event, rootActorId, {
332
- previousSnapshot: actors.get(inspectionEvent.actorRef.sessionId)?.snapshot ?? null,
333
- event: inspectionEvent.event,
334
- sourceActorId: inspectionEvent.sourceRef?.sessionId ?? null,
335
- actions: inspectionEvent.actions.map(normalizeAction),
336
- transitions: inspectionEvent.microsteps.map(normalizeTakenTransition),
337
- sent: inspectionEvent.sent.map(normalizeSentEvent)
338
- });
339
- break;
340
- default: break;
341
- }
342
- });
382
+ observedRootIds.add(rootActorId);
383
+ const subscription = root.system.inspect(handleInspectionEvent);
343
384
  inspectedRoots.set(rootActorId, {
344
385
  actor: root,
345
386
  subscription
@@ -360,6 +401,7 @@ function createInspector(options = {}) {
360
401
  id,
361
402
  systemId: opts?.systemId,
362
403
  snapshot: opts?.snapshot ?? null,
404
+ stopped: false,
363
405
  machineConfig: opts?.machine ?? null
364
406
  };
365
407
  actors.set(id, entry);
@@ -373,13 +415,13 @@ function createInspector(options = {}) {
373
415
  });
374
416
  emitRegisterOnce(entry);
375
417
  }
376
- function manualSnapshot(actorId, snapshot, event, sourceActorId) {
418
+ function manualSnapshot(actorId, snapshot, event) {
377
419
  if (!actors.has(actorId)) manualRegister(actorId);
378
420
  const entry = actors.get(actorId);
379
421
  const previousSnapshot = entry.snapshot;
380
- const transition = {
422
+ const inspectedSnapshot = {
381
423
  actorId,
382
- sourceActorId: sourceActorId ?? null,
424
+ sourceActorId: null,
383
425
  previousSnapshot,
384
426
  snapshot,
385
427
  event: event ?? null,
@@ -394,21 +436,23 @@ function createInspector(options = {}) {
394
436
  previousSnapshot,
395
437
  snapshot,
396
438
  event: event ?? null,
397
- sourceActorId: sourceActorId ?? null,
439
+ sourceActorId: null,
398
440
  actions: [],
399
441
  transitions: [],
400
442
  sent: []
401
443
  });
402
- emitLocal("transition", transition);
403
- emitLocal("snapshot", entry);
444
+ emitLocal("snapshot", inspectedSnapshot);
445
+ emitLocal("transition", inspectedSnapshot);
404
446
  }
405
447
  function manualEvent(actorId, event, eventOpts) {
406
448
  const eventObj = typeof event === "string" ? { type: event } : { ...event };
407
- manualSnapshot(actorId, actors.get(actorId)?.snapshot ?? null, eventObj, eventOpts?.source ?? null);
449
+ if (!actors.has(actorId)) manualRegister(actorId);
450
+ handleEvent(actorId, eventObj, eventOpts?.source ?? null);
408
451
  }
409
452
  function manualStop(actorId) {
410
- if (!actors.has(actorId)) return;
411
- actors.delete(actorId);
453
+ const entry = actors.get(actorId);
454
+ if (!entry || entry.stopped) return;
455
+ entry.stopped = true;
412
456
  if (initSent) send({
413
457
  type: "@statelyai.system.actorStopped",
414
458
  actorId
@@ -427,7 +471,8 @@ function createInspector(options = {}) {
427
471
  get sessionId() {
428
472
  return sessionId;
429
473
  },
430
- inspect: inspectActor,
474
+ inspect: handleInspectionEvent,
475
+ attach: attachActor,
431
476
  on(event, handler) {
432
477
  if (!localListeners[event]) localListeners[event] = /* @__PURE__ */ new Set();
433
478
  localListeners[event].add(handler);
@@ -456,6 +501,7 @@ function createInspector(options = {}) {
456
501
  events.clear();
457
502
  actors.clear();
458
503
  inspectedRoots.clear();
504
+ observedRootIds.clear();
459
505
  pendingTransitions.clear();
460
506
  pendingMessages.length = 0;
461
507
  for (const set of Object.values(localListeners)) set?.clear();
@@ -75,7 +75,7 @@ interface MinimalActorRef {
75
75
  src?: unknown;
76
76
  getSnapshot(): MinimalSnapshot;
77
77
  system: {
78
- inspect: (observer: (event: InspectionEvent) => void) => {
78
+ inspect: (observer: (event: InspectorInspectionEvent) => void) => {
79
79
  unsubscribe: () => void;
80
80
  };
81
81
  };
@@ -86,63 +86,12 @@ interface MinimalSnapshot {
86
86
  context?: unknown;
87
87
  children?: Record<string, MinimalActorRef>;
88
88
  }
89
- type InspectionEvent = {
90
- type: '@xstate.actor';
91
- actorRef: MinimalActorRef;
92
- rootId: string;
93
- parentRef?: MinimalActorRef;
94
- id?: string;
95
- src?: unknown;
96
- snapshot?: MinimalSnapshot;
97
- } | {
98
- type: '@xstate.snapshot';
99
- actorRef: MinimalActorRef;
100
- rootId: string;
101
- snapshot: MinimalSnapshot;
102
- event: unknown;
103
- } | {
104
- type: '@xstate.event';
105
- actorRef: MinimalActorRef;
106
- rootId: string;
107
- sourceRef?: MinimalActorRef;
108
- event: unknown;
109
- } | {
110
- type: '@xstate.transition';
111
- actorRef: MinimalActorRef;
112
- rootId: string;
113
- snapshot: MinimalSnapshot;
114
- event: unknown;
115
- sourceRef?: MinimalActorRef;
116
- targetRef?: MinimalActorRef;
117
- eventType?: string;
118
- microsteps?: unknown[];
119
- actions?: Array<{
120
- type: string;
121
- params: unknown;
122
- }>;
123
- sent?: Array<{
124
- targetRef?: MinimalActorRef;
125
- targetId: string;
126
- event: unknown;
127
- delay?: number;
128
- id?: string;
129
- }>;
130
- } | {
131
- type: '@xstate.microstep';
132
- actorRef: MinimalActorRef;
133
- rootId: string;
134
- snapshot: MinimalSnapshot;
135
- event: unknown;
136
- _transitions?: unknown[];
137
- } | {
138
- type: '@xstate.action';
139
- actorRef: MinimalActorRef;
140
- rootId: string;
141
- action: {
142
- type: string;
143
- params: unknown;
144
- };
145
- };
89
+ /** Cross-version event envelope accepted by {@link Inspector.inspect}. */
90
+ interface InspectorInspectionEvent {
91
+ readonly type: string;
92
+ readonly rootId: string;
93
+ readonly actorRef: unknown;
94
+ }
146
95
  interface AdoptedActor {
147
96
  /** `actor.sessionId` from xstate. Unique across the system. */
148
97
  actorId: string;
@@ -156,30 +105,43 @@ interface AdoptedActor {
156
105
  systemId: string | undefined;
157
106
  /** Latest serialized snapshot streamed for this actor. */
158
107
  snapshot: unknown | null;
108
+ /** Whether the actor has stopped. Stopped actors remain inspectable. */
109
+ stopped: boolean;
159
110
  /** Machine config sent to the visualizer, or `null` for non-machine actors. */
160
111
  machineConfig: unknown;
161
112
  }
162
- /** One normalized transition, independent of the XState inspection version. */
163
- interface InspectedTransition {
113
+ /** One observed snapshot, independent of the XState inspection version. */
114
+ interface InspectedSnapshot {
164
115
  actorId: string;
165
116
  sourceActorId: string | null;
117
+ /** Previously observed snapshot, which may not be the immediate predecessor. */
166
118
  previousSnapshot: unknown | null;
167
119
  snapshot: unknown;
120
+ /** Event known to have caused this snapshot, if observed. */
168
121
  event: unknown | null;
169
122
  actions: InspectionAction[];
170
123
  transitions: InspectionTakenTransition[];
171
124
  sent: InspectionSentEvent[];
172
125
  }
126
+ /** @deprecated Use {@link InspectedSnapshot}. */
127
+ type InspectedTransition = InspectedSnapshot;
128
+ /** One observed event, independent of whether processing produced a snapshot. */
129
+ interface InspectedEvent {
130
+ actorId: string;
131
+ sourceActorId: string | null;
132
+ event: unknown;
133
+ }
173
134
  interface InspectorEvents {
174
135
  actor: AdoptedActor;
175
- transition: InspectedTransition;
136
+ event: InspectedEvent;
137
+ snapshot: InspectedSnapshot;
176
138
  stop: {
177
139
  actorId: string;
178
140
  };
179
141
  /** @deprecated Use `actor`. */
180
142
  register: AdoptedActor;
181
- /** @deprecated Use `transition`. */
182
- snapshot: AdoptedActor;
143
+ /** @deprecated Use `snapshot`. */
144
+ transition: InspectedSnapshot;
183
145
  /** @deprecated Use `stop`. */
184
146
  stopped: {
185
147
  actorId: string;
@@ -246,8 +208,13 @@ interface Inspector {
246
208
  readonly actors: ReadonlyMap<string, AdoptedActor>;
247
209
  /** The relay sessionId this inspector registered under. */
248
210
  readonly sessionId: string;
249
- /** Adopt an xstate actor system. Existing actors are backfilled immediately. */
250
- inspect(actor: any): {
211
+ /**
212
+ * XState `inspect` option callback. Pass directly to `createActor` or another
213
+ * host that creates actors internally.
214
+ */
215
+ readonly inspect: (event: InspectorInspectionEvent) => void;
216
+ /** Attach an existing xstate actor system and backfill its current actors. */
217
+ attach(actor: any): {
251
218
  unsubscribe(): void;
252
219
  };
253
220
  /** Subscribe to lifecycle / error events. Returns an unsubscribe function. */
@@ -261,13 +228,13 @@ interface Inspector {
261
228
  */
262
229
  actor(id: string, options?: ManualActorOptions): void;
263
230
  /**
264
- * Push a snapshot update for an actor. The actor is auto-registered if
265
- * it hasn't been `.actor()`'d yet.
231
+ * Push a snapshot update for an actor, optionally with the event known to
232
+ * have caused it. The actor is auto-registered if needed.
266
233
  */
267
234
  snapshot(actorId: string, snapshot: unknown, event?: unknown): void;
268
235
  /**
269
- * Log an event targeting an actor. Sends a snapshot message with the
270
- * actor's current snapshot + the new event so it appears in the event log.
236
+ * Log an event targeting an actor immediately, independently of any later
237
+ * snapshot. The actor is auto-registered if needed.
271
238
  */
272
239
  event(actorId: string, event: string | {
273
240
  type: string;
@@ -275,7 +242,7 @@ interface Inspector {
275
242
  }, options?: {
276
243
  source?: string;
277
244
  }): void;
278
- /** Mark an actor as stopped and remove it from the tree. */
245
+ /** Mark an actor as stopped while retaining it in the tree. */
279
246
  stop(actorId: string): void;
280
247
  /** Tear down the WebSocket + xstate subscription. */
281
248
  destroy(): void;
@@ -284,4 +251,4 @@ declare function createInspector(options?: CreateInspectorOptions): Inspector;
284
251
  /** @deprecated Use {@link createInspector}. */
285
252
  declare const createStatelyInspector: typeof createInspector;
286
253
  //#endregion
287
- export { InspectorEvents as a, createStatelyInspector as c, MultiplexedWebSocketConnectionOptions as d, Transport as f, createWebSocketTransport as h, Inspector as i, MultiplexedChannelOptions as l, createPostMessageTransport as m, CreateInspectorOptions as n, ManualActorOptions as o, createMultiplexedWebSocketConnection as p, InspectedTransition as r, createInspector as s, AdoptedActor as t, MultiplexedWebSocketConnection as u };
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 };
@@ -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 InspectorEvents, c as createStatelyInspector, f as Transport, i as Inspector, n as CreateInspectorOptions, o as ManualActorOptions, r as InspectedTransition, s as createInspector, t as AdoptedActor } from "./inspect-COqtklcn.mjs";
3
- export { AdoptedActor, CreateInspectorOptions, EditorCapabilities, EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ExportCallOptions, ExportFormat, ExportFormatMap, InspectedTransition, InspectionAction, InspectionSentEvent, InspectionTakenTransition, Inspector, InspectorEvents, ManualActorOptions, Transport, createInspector, createStatelyInspector };
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-DQ_7I7eH.mjs";
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-pcNCbL7j.mjs";
1
+ import { n as createStatelyInspector, t as createInspector } from "./inspect-BcKTFJI1.mjs";
2
2
 
3
3
  export { createInspector, createStatelyInspector };