@statelyai/sdk 0.7.1 → 0.8.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/README.md CHANGED
@@ -1,651 +1,24 @@
1
1
  # @statelyai/sdk
2
2
 
3
- <!-- package.json#name and #description top-level summary -->
3
+ Shared SDK modules for Stately clients, sync helpers, graph conversion, and code generation.
4
4
 
5
- Embed the [Stately editor](https://stately.ai), inspect running actor systems over WebSockets, talk to the Stately Studio API, and convert between Studio graph data and code. Fully typed.
5
+ The Stately CLI now lives in:
6
6
 
7
- ## Install
7
+ - `statelyai`
8
8
 
9
- <!-- install command derived from package.json#name -->
9
+ If you want the command-line workflow, use:
10
10
 
11
11
  ```bash
12
- npm install @statelyai/sdk
12
+ npx statelyai --help
13
13
  ```
14
14
 
15
- ## What It Includes
15
+ This package is the programmatic dependency used by that CLI.
16
16
 
17
- <!-- top-level runtime exports from src/index.ts and CLI bin from package.json#bin -->
17
+ The broader in-progress package documentation draft is kept in:
18
18
 
19
- - `createStatelyEmbed()` for browser embeds backed by `postMessage`
20
- - `createStatelyInspector()` for inspecting live actor systems over WebSockets
21
- - `createStatelyClient()` for Stately Studio API access
22
- - graph conversion and codegen helpers such as `fromStudioMachine()`, `toStudioMachine()`, `graphToMachineConfig()`, and `graphToXStateTS()`
23
- - sync helpers under `@statelyai/sdk/sync` and a `statelyai` CLI binary
19
+ - [README-next.md](./README-next.md)
24
20
 
25
- ## Authentication
21
+ Published schemas:
26
22
 
27
- The embed supports three common deployment models:
28
-
29
- - Hosted Stately: pass an API key to `createStatelyEmbed()`
30
- - Self-hosted deployments: configure auth in the editor server and omit `apiKey` when no token is required
31
-
32
- ### Hosted Stately
33
-
34
- An API key is required. To get one:
35
-
36
- 1. Go to your [Stately settings](https://stately.ai/settings)
37
- 2. Select the **API Key** tab
38
- 3. Click **Create API Key** (Project or Account scope)
39
- 4. Copy and store it securely
40
-
41
- See the [Studio API docs](https://stately.ai/docs/studio-api) for more details.
42
-
43
- Pass the key to the SDK:
44
-
45
- ```ts
46
- const embed = createStatelyEmbed({
47
- baseUrl: 'https://stately.ai',
48
- apiKey: 'your-api-key',
49
- });
50
- ```
51
-
52
- ### Self-hosting
53
-
54
- When self-hosting the editor, authentication is enforced by the editor server, not by this npm package.
55
-
56
- The common environment variables are:
57
-
58
- | Variable | Purpose |
59
- | --------------------------- | ----------------------------------------------------------------------- |
60
- | `AUTH_PROVIDER` | Auth strategy used by the editor host |
61
- | `EDITOR_SYNC_AUTH_REQUIRED` | Set to `false` to disable API-key checks for editor-sync endpoints only |
62
- | `STATELY_API_KEY` | Server-side API key for Stately data fetching |
63
- | `STATELY_API_URL` | Stately API base URL override |
64
- | `NEXT_PUBLIC_BASE_URL` | Public-facing editor URL |
65
-
66
- For a fully self-contained deployment with no auth, omit `apiKey` in the SDK and configure the host/editor to allow unauthenticated access:
67
-
68
- ```ts
69
- const embed = createStatelyEmbed({
70
- baseUrl: 'https://your-editor.example.com',
71
- });
72
- ```
73
-
74
- ## Quick Start
75
-
76
- ### Third-party embed (with API key)
77
-
78
- ```ts
79
- import { createStatelyEmbed } from '@statelyai/sdk';
80
-
81
- const embed = createStatelyEmbed({
82
- baseUrl: 'https://stately.ai',
83
- apiKey: 'your-api-key',
84
- });
85
-
86
- embed.mount(document.getElementById('editor')!);
87
-
88
- embed.init({
89
- machine: myMachineConfig,
90
- format: 'xstate',
91
- mode: 'editing',
92
- theme: 'dark',
93
- });
94
- ```
95
-
96
- ### Comments
97
-
98
- Comments are optional and integrator-configured. Pass a `comments` object to `embed.init()` when you want Liveblocks-backed commenting enabled.
99
-
100
- ```ts
101
- embed.init({
102
- machine: machineConfig,
103
- mode: 'editing',
104
- comments: {
105
- roomId: 'machine:checkout',
106
- publicApiKey: 'pk_live_...',
107
- userId: currentUserId ?? null,
108
- },
109
- });
110
- ```
111
-
112
- You can also use a custom auth endpoint instead of a public key:
113
-
114
- ```ts
115
- embed.init({
116
- machine: machineConfig,
117
- comments: {
118
- roomId: 'machine:checkout',
119
- authEndpoint: '/api/liveblocks-auth',
120
- userId: currentUserId ?? null,
121
- },
122
- });
123
- ```
124
-
125
- `roomId` is required when comments are enabled. `userId` is optional and only used for comment identity metadata.
126
-
127
- ## Module Layout
128
-
129
- <!-- subpath imports derived from package.json#exports -->
130
-
131
- The SDK ships root exports for the most common entry points and helpers:
132
-
133
- ```ts
134
- import {
135
- createStatelyApiClient,
136
- createStatelyApiUrl,
137
- createStatelyClient,
138
- createStatelyEmbed,
139
- createStatelyInspector,
140
- createS3AssetUploadAdapter,
141
- createSupabaseAssetUploadAdapter,
142
- fromStudioMachine,
143
- graphToMachineConfig,
144
- graphToXStateTS,
145
- toStudioMachine,
146
- } from '@statelyai/sdk';
147
- ```
148
-
149
- It also supports narrower subpath imports:
150
-
151
- ```ts
152
- import { createStatelyClient } from '@statelyai/sdk/studio';
153
- import { createStatelyInspector } from '@statelyai/sdk/inspect';
154
- import { createStatelyEmbed } from '@statelyai/sdk/embed';
155
- import {
156
- createStatelyApiClient,
157
- createStatelyApiUrl,
158
- } from '@statelyai/sdk/api';
159
- import { fromStudioMachine, toStudioMachine } from '@statelyai/sdk/graph';
160
- import { planSync, pullSync, pushSync } from '@statelyai/sdk/sync';
161
- import {
162
- createS3AssetUploadAdapter,
163
- createSupabaseAssetUploadAdapter,
164
- } from '@statelyai/sdk/assetStorage';
165
- import type { GraphPatch } from '@statelyai/sdk/patchTypes';
166
- ```
167
-
168
- The root package also exports `getStatelyPragma()`, `findStatelyPragmaAttachments()`, and `upsertStatelyPragma()` for working with canonical source annotations such as `// @statelyai id=machine-123`.
169
-
170
- ## Studio API Client
171
-
172
- ```ts
173
- import { createStatelyClient } from '@statelyai/sdk';
174
-
175
- const studio = createStatelyClient({
176
- apiKey: process.env.STATELY_API_KEY,
177
- });
178
-
179
- const createdProject = await studio.projects.create({
180
- name: 'My project',
181
- visibility: 'Private',
182
- });
183
- const project = await studio.projects.get('project-id');
184
- const projects = await studio.projects.list();
185
- const createdMachine = await studio.machines.create({
186
- projectVersionId: createdProject.projectVersionId!,
187
- definition: digraphDefinition,
188
- xstateVersion: 5,
189
- });
190
- const machine = await studio.machines.get('machine-id', { version: '42' });
191
- const extracted = await studio.code.extractMachines(sourceCode);
192
- ```
193
-
194
- `studio.projects.list(...)`, `studio.projects.create(...)`, and `studio.machines.create(...)` use the documented Studio REST API. `studio.projects.ensure(...)` is a client-side helper that uses the documented list/create endpoints to reuse an existing connected project when the repo metadata matches.
195
-
196
- <!-- public methods of StudioClient from src/studio.ts -->
197
-
198
- Available client methods:
199
-
200
- | Method | Description |
201
- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------ |
202
- | `studio.auth.verify(apiKey?)` | Verify an API key against the registry API |
203
- | `studio.projects.list()` | List accessible projects, including connected repo metadata when present |
204
- | `studio.projects.create({ name, visibility, description?, keywords? })` | Create a new project through the published REST API |
205
- | `studio.projects.ensure({ name, visibility, repo?, ... })` | Reuse an existing connected project or create one through the REST API |
206
- | `studio.projects.get(projectId)` | Fetch a project and its machines |
207
- | `studio.machines.create({ projectVersionId, ... })` | Create a machine through the published REST API |
208
- | `studio.machines.createMany({ projectVersionId, ... })` | Compatibility wrapper around `create()` that returns a one-item array |
209
- | `studio.machines.update({ id, ... })` | Update a machine through the published REST API |
210
- | `studio.machines.get(machineId, { version? })` | Fetch a machine, optionally pinned to a version |
211
- | `studio.code.extractMachines(code, { apiKey? })` | Extract machine configs from source text |
212
-
213
- ## Sync Helpers
214
-
215
- `pushSync()` complements `planSync()` and `pullSync()` for local-to-Studio flows. It resolves a local source file, ensures there is a target project, updates the linked remote machine when `// @statelyai id=...` is present, otherwise creates one, and writes the pragma back into XState source files when needed.
216
-
217
- For project-scoped discovery flows, `statelyai.json` defines which local files should be scanned. The CLI `statelyai push` command uses that config to find local XState sources, creates remote Studio machines for unlabeled ones, updates already-linked ones, and writes returned `// @statelyai id=...` pragmas back into source.
218
-
219
- ```ts
220
- import { pushSync } from '@statelyai/sdk/sync';
221
-
222
- const result = await pushSync({
223
- source: './src/machines/toggle.ts',
224
- apiKey: process.env.STATELY_API_KEY,
225
- project: {
226
- visibility: 'Private',
227
- repo: {
228
- url: 'https://github.com/statelyai/viz',
229
- owner: 'statelyai',
230
- repo: 'viz',
231
- branch: 'main',
232
- treeSha: 'abc123',
233
- },
234
- },
235
- });
236
- ```
237
-
238
- Projects can also check in a `statelyai.json` file to describe which local sources belong to a Studio project. The published schema lives at `@statelyai/sdk/statelyai.schema.json` and the canonical schema id is `https://stately.ai/schemas/statelyai.json`. The strict XState JSON export schema is published at `@statelyai/sdk/xstate-json.schema.json`.
239
-
240
- ```json
241
- {
242
- "$schema": "https://stately.ai/schemas/statelyai.json",
243
- "version": "1.0.0",
244
- "projectId": "project_123",
245
- "studioUrl": "https://stately.ai",
246
- "defaultXStateVersion": 5,
247
- "sources": []
248
- }
249
- ```
250
-
251
- ## Inspector
252
-
253
- <!-- public API of createStatelyInspector from src/inspect.ts -->
254
-
255
- `createStatelyInspector()` streams actor-system state to the Stately inspector over WebSockets. It supports both automatic XState actor adoption and manual actor registration.
256
-
257
- ```ts
258
- import { createActor } from 'xstate';
259
- import { createStatelyInspector } from '@statelyai/sdk';
260
-
261
- const actor = createActor(machine);
262
- const inspector = createStatelyInspector({
263
- actor,
264
- url: 'ws://localhost:4242',
265
- autoOpen: true,
266
- });
267
-
268
- actor.start();
269
- ```
270
-
271
- Key options:
272
-
273
- | Option | Description |
274
- | -------------------------------------- | ---------------------------------------------------------------- |
275
- | `actor` | Root actor to adopt and inspect automatically |
276
- | `url` | Devtools relay URL. Defaults to `ws://localhost:4242` |
277
- | `autoOpen` | Whether to ask the relay to open the inspector UI |
278
- | `sessionId` | Override the relay session id |
279
- | `name` | Display name shown to the inspector |
280
- | `serializeSnapshot` | Customize snapshot serialization before sending it over the wire |
281
- | `extractMachineConfig` | Customize how machine config is derived from an actor |
282
- | `selectedActorId` | Focus a specific actor first |
283
- | `panels`, `theme`, `readOnly`, `depth` | Initial inspector UI options |
284
- | `transport` | Inject an existing transport instead of opening a new WebSocket |
285
-
286
- Key methods:
287
-
288
- - `inspector.export(format, options?)`
289
- - `inspector.actor(id, options?)`
290
- - `inspector.snapshot(actorId, snapshot, event?)`
291
- - `inspector.event(actorId, event, { source? })`
292
- - `inspector.stop(actorId)`
293
- - `inspector.destroy()`
294
-
295
- ## Embed API
296
-
297
- ### `createStatelyEmbed(options)`
298
-
299
- Creates an embed instance.
300
-
301
- <!-- public options of StatelyEmbedOptions from src/embed.ts -->
302
-
303
- | Option | Type | Description |
304
- | ---------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
305
- | `baseUrl` | `string` | **Required.** Base URL of the Stately app |
306
- | `apiKey` | `string` | API key for hosted Stately deployments |
307
- | `origin` | `string` | Optional strict target origin for `postMessage`; defaults to permissive wildcard messaging for local/self-hosted testing |
308
- | `assets` | `AssetConfig` | Asset upload configuration |
309
- | `onReady` | `() => void` | Called when the embed is ready |
310
- | `onLoaded` | `(graph) => void` | Called when a machine is loaded |
311
- | `onChange` | `(graph, machineConfig) => void` | Called on every change |
312
- | `onSave` | `(graph, machineConfig) => void` | Called on save |
313
- | `onError` | `({ code, message }) => void` | Called when the embed reports an error |
314
-
315
- ### Embed methods
316
-
317
- #### `embed.mount(container)` / `embed.attach(iframe)`
318
-
319
- `mount()` creates an iframe inside a container element. `attach()` connects to an existing iframe.
320
-
321
- ```ts
322
- const iframe = embed.mount(document.getElementById('editor')!);
323
-
324
- embed.attach(document.querySelector('iframe')!);
325
- ```
326
-
327
- #### `embed.init(options)`
328
-
329
- Initialize the embed with a machine and display options.
330
-
331
- ```ts
332
- embed.init({
333
- machine: machineConfig,
334
- format: 'xstate',
335
- mode: 'editing',
336
- theme: 'dark',
337
- readOnly: false,
338
- depth: 3,
339
- panels: {
340
- leftPanels: ['code'],
341
- rightPanels: ['events'],
342
- activePanels: ['code'],
343
- },
344
- unsavedIndicator: {
345
- enabled: true,
346
- mode: 'structural',
347
- },
348
- comments: {
349
- roomId: 'machine:checkout',
350
- publicApiKey: 'pk_live_...',
351
- },
352
- });
353
- ```
354
-
355
- `comments` accepts:
356
-
357
- | Field | Type | Description |
358
- | -------------- | ---------------- | ------------------------------------------- |
359
- | `roomId` | `string` | **Required.** Liveblocks room identifier |
360
- | `publicApiKey` | `string` | Liveblocks public key |
361
- | `authEndpoint` | `string` | Custom Liveblocks auth endpoint |
362
- | `baseUrl` | `string` | Custom Liveblocks base URL for self-hosting |
363
- | `userId` | `string \| null` | Optional user identity metadata |
364
-
365
- `unsavedIndicator` accepts:
366
-
367
- | Field | Type | Description |
368
- | --------- | ----------------------- | ---------------------------------------------- |
369
- | `enabled` | `boolean` | Show the persistent "Save to apply" pill |
370
- | `mode` | `'structural' \| 'all'` | Track only structural graph edits or all edits |
371
-
372
- #### `embed.updateMachine(machine, format?)`
373
-
374
- Update the displayed machine.
375
-
376
- #### `embed.setMode(mode)` / `embed.setTheme(theme)`
377
-
378
- Change the embed mode or theme at runtime.
379
-
380
- #### `embed.setSettings(settings)`
381
-
382
- Update editor settings at runtime. Settings are merged with the existing editor settings.
383
-
384
- ```ts
385
- embed.setSettings({
386
- appearance: { colorMode: 'light' },
387
- canvas: { showGrid: false },
388
- });
389
- ```
390
-
391
- Available core settings:
392
-
393
- <!-- core setting paths from ../../src/settings.ts -->
394
-
395
- | Path | Type | Default |
396
- | ---------------------------- | ------------------------------- | --------- |
397
- | `appearance.colorMode` | `'light' \| 'dark' \| 'system'` | `'dark'` |
398
- | `canvas.showGrid` | `boolean` | `true` |
399
- | `canvas.viewMode` | `'graph' \| 'list'` | `'graph'` |
400
- | `canvas.enableSnapLines` | `boolean` | `true` |
401
- | `canvas.dimUnselected` | `boolean` | `true` |
402
- | `validation.showValidations` | `boolean` | `true` |
403
- | `layout.autolayout` | `boolean` | `false` |
404
- | `developer.devMode` | `boolean` | `false` |
405
-
406
- #### `embed.export(format, options?)`
407
-
408
- Export the current machine. Returns a promise.
409
-
410
- ```ts
411
- const xstateCode = await embed.export('xstate', { version: 5 });
412
- const digraph = await embed.export('digraph');
413
- const redux = await embed.export('redux');
414
- const aslYaml = await embed.export('asl-yaml');
415
- ```
416
-
417
- <!-- supported export formats from ExportFormatMap in src/protocol.ts -->
418
-
419
- Supported formats: `xstate`, `xstate-json`, `xgraph`, `digraph`, `mermaid`, `redux`, `zustand`, `asl-json`, `asl-yaml`, `scxml`
420
-
421
- #### `embed.on(event, handler)` / `embed.off(event, handler)`
422
-
423
- <!-- keys of EmbedEventMap in src/protocol.ts -->
424
-
425
- Event names are `ready`, `loaded`, `change`, `save`, `error`, and `snapshot`.
426
-
427
- `createStatelyEmbed()` emits `ready`, `loaded`, `change`, `save`, and `error` for browser embeds:
428
-
429
- ```ts
430
- embed.on('change', ({ graph, machineConfig, patches }) => {
431
- console.log('Machine changed', graph, machineConfig, patches);
432
- });
433
-
434
- embed.on('save', ({ validations }) => {
435
- console.log('Save validations', validations);
436
- });
437
- ```
438
-
439
- #### `embed.toast(message, type?)`
440
-
441
- Show a toast notification in the embed. Type: `'success' | 'error' | 'info' | 'warning'`
442
-
443
- #### `embed.destroy()`
444
-
445
- Tear down the embed. Removes listeners, rejects pending promises, and removes the iframe if it was created via `mount()`.
446
-
447
- ### Asset uploads
448
-
449
- By default, dropped files are stored as base64 data URLs. To upload assets to your own storage, pass an `assets` config:
450
-
451
- ```ts
452
- const embed = createStatelyEmbed({
453
- baseUrl: 'https://stately.ai',
454
- assets: {
455
- onUploadRequest: async (file, { stateNodeId }) => {
456
- return { url: await uploadToStorage(file, stateNodeId) };
457
- },
458
- accept: ['image/*'],
459
- maxFileSize: 5 * 1024 * 1024,
460
- },
461
- });
462
- ```
463
-
464
- For reusable integrations, pass an upload adapter instead of wiring the callback inline:
465
-
466
- ```ts
467
- import { createStatelyEmbed, createS3AssetUploadAdapter } from '@statelyai/sdk';
468
-
469
- const adapter = createS3AssetUploadAdapter({
470
- bucket: 'assets',
471
- publicBaseUrl: 'https://cdn.example.com/assets',
472
- async getUploadTarget({ key, contentType }) {
473
- const response = await fetch('/api/assets/presign', {
474
- method: 'POST',
475
- headers: { 'Content-Type': 'application/json' },
476
- body: JSON.stringify({ key, contentType }),
477
- });
478
- return response.json();
479
- },
480
- });
481
-
482
- const embed = createStatelyEmbed({
483
- baseUrl: 'https://stately.ai',
484
- assets: { adapter },
485
- });
486
- ```
487
-
488
- Supabase storage can use the same adapter contract:
489
-
490
- ```ts
491
- import {
492
- createStatelyEmbed,
493
- createSupabaseAssetUploadAdapter,
494
- } from '@statelyai/sdk';
495
-
496
- const adapter = createSupabaseAssetUploadAdapter({
497
- client: supabaseClient,
498
- bucket: 'assets',
499
- projectVersionId,
500
- });
501
-
502
- const embed = createStatelyEmbed({
503
- baseUrl: 'https://stately.ai',
504
- assets: { adapter },
505
- });
506
- ```
507
-
508
- | Option | Type | Description |
509
- | ----------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------- |
510
- | `onUploadRequest` | `(file: File, context: { stateNodeId: string }) => Promise<UploadResult>` | Called when the editor needs to upload a file |
511
- | `adapter` | `AssetUploadAdapter` | Provider-specific uploader, such as the S3 or Supabase adapter |
512
- | `accept` | `string[]` | Accepted MIME types. Supports wildcards like `image/*` |
513
- | `maxFileSize` | `number` | Max file size in bytes. Defaults to `10_485_760` |
514
-
515
- `UploadResult`:
516
-
517
- ```ts
518
- interface UploadResult {
519
- url: string;
520
- name?: string;
521
- metadata?: Record<string, unknown>;
522
- }
523
- ```
524
-
525
- If `onUploadRequest` throws or rejects, the editor shows an error toast. If no `assets` config is provided, files are stored inline and no upload request is sent.
526
-
527
- ## Graph And Codegen Helpers
528
-
529
- <!-- root helper exports from src/index.ts -->
530
-
531
- Use the conversion helpers to move between Studio digraph data, generic Stately graphs, machine config objects, and XState TypeScript source.
532
-
533
- ```ts
534
- import {
535
- fromStudioMachine,
536
- graphToMachineConfig,
537
- graphToXStateTS,
538
- toStudioMachine,
539
- } from '@statelyai/sdk';
540
-
541
- const graph = fromStudioMachine(studioMachine);
542
- const machineConfig = graphToMachineConfig(graph, {
543
- showDescriptions: true,
544
- showMeta: true,
545
- });
546
- const source = graphToXStateTS(graph, {
547
- exportStyle: 'named',
548
- });
549
- const digraph = toStudioMachine(graph);
550
- ```
551
-
552
- Other exported helpers:
553
-
554
- - `studioMachineConverter` for reusable format conversion
555
- - `createStatelyApiUrl()` and `createStatelyApiClient()` for building and
556
- calling self-hosted Viz API routes from a shared API base URL
557
- - `serializeJS()`, `raw()`, and `RawCode` for emitting JavaScript source
558
- - `jsonSchemaToTSType()`, `contextSchemaToTSType()`, and `eventsSchemaToTSType()` for generating inline TypeScript types from JSON Schema
559
- - `GraphPatch` and `ActionLocation` types from `@statelyai/sdk/patchTypes`
560
-
561
- ## Sync Helpers And CLI
562
-
563
- <!-- sync helpers from src/sync.ts and CLI commands from src/cli.ts#COMMANDS -->
564
-
565
- The sync helpers compare or materialize machines across local files, Stately machine IDs, and Stately URLs.
566
-
567
- Programmatic usage:
568
-
569
- ```ts
570
- import { planSync, pullSync } from '@statelyai/sdk/sync';
571
-
572
- const plan = await planSync({
573
- source: './checkout.machine.ts',
574
- target: 'machine-id',
575
- apiKey: process.env.STATELY_API_KEY,
576
- });
577
-
578
- if (plan.summary.hasChanges) {
579
- console.log(plan.summary);
580
- }
581
-
582
- await pullSync({
583
- source: 'machine-id',
584
- target: './checkout.machine.ts',
585
- apiKey: process.env.STATELY_API_KEY,
586
- });
587
- ```
588
-
589
- Supported locators:
590
-
591
- - local files
592
- - Stately machine IDs
593
- - full Stately machine URLs
594
-
595
- Installing the package also exposes a `statelyai` binary:
596
-
597
- ```bash
598
- npx statelyai open ./checkout.machine.ts
599
-
600
- statelyai init
601
- statelyai init --scan
602
- statelyai login
603
- statelyai auth status
604
- statelyai plan ./checkout.machine.ts machine-id
605
- statelyai diff ./checkout.machine.ts machine-id --fail-on-changes
606
- statelyai push
607
- statelyai push ./checkout.machine.ts
608
- statelyai pull machine-id ./checkout.machine.ts
609
- statelyai pull ./checkout.machine.ts
610
- statelyai open ./checkout.machine.ts
611
- ```
612
-
613
- For one-off use, `npx statelyai ...` installs the small `statelyai` CLI package, which delegates to this SDK CLI.
614
-
615
- Available commands:
616
-
617
- | Command | Description |
618
- | ---------------------------------- | --------------------------------------------------------------------------- |
619
- | `statelyai init` | Create or reuse a Studio project for the current directory and write `statelyai.json` with an empty `sources` array |
620
- | `statelyai login` | Store an API key for future CLI use |
621
- | `statelyai logout` | Remove a stored API key |
622
- | `statelyai auth status` | Show whether the CLI would use an environment variable or stored credential |
623
- | `statelyai plan <source> <target>` | Print a semantic sync summary |
624
- | `statelyai diff <source> <target>` | Diff two locators and optionally fail on changes |
625
- | `statelyai push [file]` | Discover local machine sources, create remote Studio machines for unlabeled files, update linked ones, and persist returned ids |
626
- | `statelyai pull <source> <target>` | Materialize a source into a local target file |
627
- | `statelyai pull <linked-file>` | Refresh a linked local file from the `@statelyai id=...` pragma |
628
- | `statelyai open <file>` | Open a local file in a browser-backed visual editor session |
629
-
630
- Common flags:
631
-
632
- - `--api-key` for remote machine resolution or editor servers that require auth
633
- - `--base-url` for self-hosted or non-default Stately deployments
634
- - `--fail-on-changes` to return a nonzero exit code when a diff is detected
635
-
636
- The CLI resolves credentials in this order: `--api-key`, then `STATELY_API_KEY`/`NEXT_PUBLIC_STATELY_API_KEY`, then the key stored by `statelyai login`. `login` stores the key in the OS credential store when available, with a private file fallback.
637
-
638
- `statelyai init --scan` walks local code files, detects machine-bearing files from their contents, and suggests `sources` globs to save into `statelyai.json`. Without `--scan`, `init` leaves `sources` empty so you can opt in explicitly before running `statelyai push`.
639
-
640
- `statelyai open` also supports `--api-key`, `--editor-url`, `--host`, `--port`, `--no-open`, and `--debug`. It watches the local file on disk and sends source snapshots to `/api/editor-sync/*` endpoints, which return the text replacements to apply locally. When the source file contains `// @statelyai id=...` and an API key is available, the editor session also reuses the referenced remote machine layout while continuing to treat the local source as the semantic source of truth. Pass `--api-key`, set `STATELY_API_KEY`, or run `statelyai login` when the editor server requires auth. Self-hosted servers can disable editor-sync API-key checks with `EDITOR_SYNC_AUTH_REQUIRED=false`. The private source reconciliation engine is not bundled into the published CLI.
641
-
642
- ## Transport Helpers
643
-
644
- <!-- transport helpers exported from src/index.ts -->
645
-
646
- For advanced integrations, the root package also exports:
647
-
648
- - `createPostMessageTransport()` for iframe-based clients
649
- - `createWebSocketTransport()` for relay-based integrations
650
-
651
- These power the embed and inspector internals, but they are also available when you need lower-level control over the `@statelyai.*` protocol.
23
+ - `@statelyai/sdk/statelyai.schema.json`
24
+ - `@statelyai/sdk/xstate-json.schema.json`
@@ -1,4 +1,4 @@
1
- import { m as UploadResult } from "./protocol-s9zwsiCW.mjs";
1
+ import { UploadResult } from "./protocol.mjs";
2
2
 
3
3
  //#region src/assetStorage.d.ts
4
4
  interface AssetUploadContext {
package/dist/embed.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as EmbedMode, c as ExportFormatMap, d as MachineSourceLocations, f as ProjectEmbedMachine, i as EmbedEventName, l as InitOptions, m as UploadResult, n as EmbedEventHandler, o as ExportCallOptions, r as EmbedEventMap, s as ExportFormat, t as CommentsConfig, u as MachineInitOptions } from "./protocol-s9zwsiCW.mjs";
1
+ import { CommentsConfig, EmbedEventHandler, EmbedEventMap, EmbedEventName, EmbedMode, ExportCallOptions, ExportFormat, ExportFormatMap, InitOptions, MachineInitOptions, MachineSourceLocations, ProjectEmbedMachine, UploadResult } from "./protocol.mjs";
2
2
  import { AssetUploadAdapter } from "./assetStorage.mjs";
3
3
 
4
4
  //#region src/embed.d.ts
package/dist/embed.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as toInitMessage, i as createPendingExportManager, r as createEventRegistry, t as createPostMessageTransport } from "./transport-C8UTS3Fa.mjs";
1
+ import { a as toInitMessage, i as createPendingExportManager, r as createEventRegistry, t as createPostMessageTransport } from "./transport-CVZGF0w9.mjs";
2
2
 
3
3
  //#region src/embed.ts
4
4
  function buildEmbedUrl(options) {