statelyai 0.12.8 → 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.
@@ -2,6 +2,7 @@ import { Args, Command, Flags, flush, handle, run } from "@oclif/core";
2
2
  import fsPromises from "node:fs/promises";
3
3
  import * as path$1 from "node:path";
4
4
  import path from "node:path";
5
+ import { changeSet, createFileStore, createLoop, parseModelGraph, proposalOutline, verdictLines, verify } from "@statelyai/mcp/loop";
5
6
  import { z, z as z$1 } from "zod";
6
7
  import { execFile, execFileSync, spawn } from "node:child_process";
7
8
  import { promisify } from "node:util";
@@ -26,6 +27,167 @@ import { StudioApiError, buildAuthorizeUrl, createPkcePair, createStatelyClient
26
27
  //#region \0rolldown/runtime.js
27
28
  var __commonJSMin$1 = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
28
29
 
30
+ //#endregion
31
+ //#region src/loopCommands.ts
32
+ /** An XGraph file, or a `.statelyai` head or version file (its `graph`). */
33
+ async function readGraphFile(file) {
34
+ const value = JSON.parse(await fsPromises.readFile(file, "utf8"));
35
+ return parseModelGraph(Array.isArray(value.nodes) ? value : value.graph);
36
+ }
37
+ /** `statelyai changes`: change lines and the proposed flow outline, base -> proposed. */
38
+ async function changesReport(baseFile, proposedFile, json = false) {
39
+ const [base, proposed] = await Promise.all([readGraphFile(baseFile), readGraphFile(proposedFile)]);
40
+ const { comparison, changes } = await changeSet(base, proposed);
41
+ if (json) return {
42
+ text: JSON.stringify({
43
+ changes,
44
+ comparison
45
+ }, null, 2),
46
+ exitCode: 0
47
+ };
48
+ return {
49
+ text: [
50
+ ...changes.length ? changes.map((line) => `- ${line}`) : ["No behavior changes."],
51
+ "",
52
+ proposalOutline({
53
+ name: path.basename(proposedFile),
54
+ proposed,
55
+ comparison,
56
+ changes
57
+ })
58
+ ].join("\n"),
59
+ exitCode: 0
60
+ };
61
+ }
62
+ /** `statelyai verify <proposal> <regenerated>`: behavior verdict; 1 on drift, 2 when unavailable. */
63
+ async function verifyReport(proposalFile, regeneratedFile, json = false) {
64
+ const [proposal, regenerated] = await Promise.all([readGraphFile(proposalFile), readGraphFile(regeneratedFile)]);
65
+ const verdict = await verify(path.basename(proposalFile), proposal, regenerated);
66
+ return {
67
+ text: json ? JSON.stringify(verdict, null, 2) : verdictLines(verdict).join("\n"),
68
+ exitCode: verdict.status === "matches" ? 0 : verdict.status === "drifted" ? 1 : 2
69
+ };
70
+ }
71
+ const localLoop = (root) => createLoop({ store: createFileStore(root) });
72
+ /** `statelyai brief`: the Apply brief for a pending proposal in `.statelyai/`. */
73
+ async function briefReport(root, machineId, versionId, json = false) {
74
+ const loop = localLoop(root);
75
+ const brief = await loop.brief(machineId, versionId);
76
+ if (json) return {
77
+ text: JSON.stringify(brief, null, 2),
78
+ exitCode: 0
79
+ };
80
+ const proposal = await loop.getProposal(machineId, versionId);
81
+ return {
82
+ text: [
83
+ proposalOutline({
84
+ name: `${brief.name} (${machineId}, ${versionId}, from ${brief.origin === "prompt" ? "a prompt" : "the editor"})`,
85
+ proposed: proposal.proposed,
86
+ comparison: proposal.comparison,
87
+ changes: proposal.changes,
88
+ evidence: proposal.evidence
89
+ }),
90
+ "",
91
+ brief.text
92
+ ].join("\n"),
93
+ exitCode: 0
94
+ };
95
+ }
96
+ /** `statelyai pending`: proposals in `.statelyai/` whose baseline is still the head. */
97
+ async function pendingReport(root, json = false) {
98
+ const { proposals } = await localLoop(root).listPendingProposals({});
99
+ if (json) return {
100
+ text: JSON.stringify({ proposals }, null, 2),
101
+ exitCode: 0
102
+ };
103
+ if (!proposals.length) return {
104
+ text: "No pending proposals in .statelyai/.",
105
+ exitCode: 0
106
+ };
107
+ return {
108
+ text: proposals.flatMap((proposal) => [
109
+ `- ${JSON.stringify(proposal.name)} for ${JSON.stringify(proposal.machineName)} (from ${proposal.origin === "prompt" ? "a prompt" : "the editor"})`,
110
+ ` statelyai brief ${proposal.machineId} --proposal ${proposal.versionId}`,
111
+ ...proposal.changes.map((line) => ` - ${line}`)
112
+ ]).join("\n"),
113
+ exitCode: 0
114
+ };
115
+ }
116
+ const jsonFlag = Flags.boolean({
117
+ description: "Print machine-readable JSON",
118
+ default: false
119
+ });
120
+ const rootFlag = Flags.string({ description: "Repository root containing .statelyai/ (defaults to the current directory)" });
121
+ var ReportCommand = class extends Command {
122
+ static enableJsonFlag = false;
123
+ async print(report) {
124
+ let result;
125
+ try {
126
+ result = await report;
127
+ } catch (error) {
128
+ this.error(error instanceof Error ? error.message : String(error), { exit: 2 });
129
+ }
130
+ this.log(result.text);
131
+ if (result.exitCode) this.exit(result.exitCode);
132
+ }
133
+ };
134
+ var ChangesCommand = class ChangesCommand extends ReportCommand {
135
+ static summary = "Print the behavior changes between two machine graphs.";
136
+ static description = "Compares XGraph JSON files (or .statelyai head and version files) offline, then prints change lines and an outline of the proposed flow.";
137
+ static args = {
138
+ base: Args.string({
139
+ required: true,
140
+ description: "Base XGraph JSON file"
141
+ }),
142
+ proposed: Args.string({
143
+ required: true,
144
+ description: "Proposed XGraph JSON file"
145
+ })
146
+ };
147
+ static flags = {
148
+ help: Flags.help({ char: "h" }),
149
+ json: jsonFlag
150
+ };
151
+ async run() {
152
+ const { args, flags } = await this.parse(ChangesCommand);
153
+ await this.print(changesReport(args.base, args.proposed, flags.json));
154
+ }
155
+ };
156
+ var BriefCommand = class BriefCommand extends ReportCommand {
157
+ static summary = "Print the implementation brief for a pending local proposal.";
158
+ static description = "Reads .statelyai/ and prints the proposal outline and the Apply message an agent implements. Fails when the model changed since the proposal.";
159
+ static args = { machine: Args.string({
160
+ required: true,
161
+ description: "Machine id (its .statelyai/machines file name)"
162
+ }) };
163
+ static flags = {
164
+ help: Flags.help({ char: "h" }),
165
+ proposal: Flags.string({
166
+ required: true,
167
+ description: "Proposal version id, for example v0002"
168
+ }),
169
+ root: rootFlag,
170
+ json: jsonFlag
171
+ };
172
+ async run() {
173
+ const { args, flags } = await this.parse(BriefCommand);
174
+ await this.print(briefReport(flags.root ?? process.cwd(), args.machine, flags.proposal, flags.json));
175
+ }
176
+ };
177
+ var PendingCommand = class PendingCommand extends ReportCommand {
178
+ static summary = "List pending proposals in .statelyai/.";
179
+ static description = "Lists proposals whose baseline still matches the machine head, newest first.";
180
+ static flags = {
181
+ help: Flags.help({ char: "h" }),
182
+ root: rootFlag,
183
+ json: jsonFlag
184
+ };
185
+ async run() {
186
+ const { flags } = await this.parse(PendingCommand);
187
+ await this.print(pendingReport(flags.root ?? process.cwd(), flags.json));
188
+ }
189
+ };
190
+
29
191
  //#endregion
30
192
  //#region ../api-contract/dist/verification.mjs
31
193
  const count = z.number().int().nonnegative();
@@ -679,7 +841,11 @@ async function verifyProject(options = {}) {
679
841
  var VerifyCommand = class VerifyCommand extends Command {
680
842
  static enableJsonFlag = false;
681
843
  static summary = "Validate a verification report, print its verdict, and export JSON or JUnit.";
682
- static description = "Saved-report processing works offline. Live execution requires a configured verification adapter.";
844
+ static description = "Saved-report processing works offline. Live execution requires a configured verification adapter. With two graph files, compares a proposal with its regeneration instead (exit 1 on drift).";
845
+ static args = {
846
+ proposal: Args.string({ description: "Proposal XGraph JSON file (or .statelyai version file) to compare" }),
847
+ regenerated: Args.string({ description: "Regenerated XGraph JSON file (or .statelyai head file)" })
848
+ };
683
849
  static flags = {
684
850
  model: Flags.string({ description: "Model file or registry machine ID (live execution)" }),
685
851
  bindings: Flags.string({ description: "Bindings file (live execution)" }),
@@ -698,7 +864,19 @@ var VerifyCommand = class VerifyCommand extends Command {
698
864
  })
699
865
  };
700
866
  async run() {
701
- const { flags } = await this.parse(VerifyCommand);
867
+ const { args, flags } = await this.parse(VerifyCommand);
868
+ if (args.proposal || args.regenerated) {
869
+ if (!args.proposal || !args.regenerated) this.error("Pass both the proposal and the regenerated graph files.", { exit: 2 });
870
+ let report;
871
+ try {
872
+ report = await verifyReport(args.proposal, args.regenerated);
873
+ } catch (error) {
874
+ this.error(error instanceof Error ? error.message : String(error), { exit: 2 });
875
+ }
876
+ this.log(report.text);
877
+ if (report.exitCode) this.exit(report.exitCode);
878
+ return;
879
+ }
702
880
  let result;
703
881
  try {
704
882
  result = await verifyProject({
@@ -928,258 +1106,594 @@ function offsetAt(lineStarts, line, character) {
928
1106
  }
929
1107
 
930
1108
  //#endregion
931
- //#region ../../node_modules/.pnpm/xstate@5.32.1/node_modules/xstate/dist/xstate-dev.esm.js
932
- function getGlobal() {
933
- if (typeof globalThis !== "undefined") return globalThis;
934
- if (typeof self !== "undefined") return self;
935
- if (typeof window !== "undefined") return window;
936
- if (typeof global !== "undefined") return global;
937
- }
938
- function getDevTools() {
939
- const w = getGlobal();
940
- if (w.__xstate__) return w.__xstate__;
941
- }
942
- const devToolsAdapter = (service) => {
943
- if (typeof window === "undefined") return;
944
- const devTools = getDevTools();
945
- if (devTools) devTools.register(service);
946
- };
947
-
948
- //#endregion
949
- //#region ../../node_modules/.pnpm/xstate@5.32.1/node_modules/xstate/dist/raise-e974d1c9.esm.js
950
- var Mailbox = class {
951
- constructor(_process) {
952
- this._process = _process;
953
- this._active = false;
954
- this._current = null;
955
- this._last = null;
956
- }
957
- start() {
958
- this._active = true;
959
- this.flush();
960
- }
961
- clear() {
962
- if (this._current) {
963
- this._current.next = null;
964
- this._last = this._current;
965
- }
966
- }
967
- enqueue(event) {
968
- const enqueued = {
969
- value: event,
970
- next: null
971
- };
972
- if (this._current) {
973
- this._last.next = enqueued;
974
- this._last = enqueued;
975
- return;
976
- }
977
- this._current = enqueued;
978
- this._last = enqueued;
979
- if (this._active) this.flush();
980
- }
981
- flush() {
982
- while (this._current) {
983
- const consumed = this._current;
984
- this._process(consumed.value);
985
- this._current = consumed.next;
986
- }
987
- this._last = null;
988
- }
989
- };
990
- const STATE_DELIMITER = ".";
991
- const TARGETLESS_KEY = "";
992
- const NULL_EVENT = "";
993
- const STATE_IDENTIFIER = "#";
994
- const WILDCARD = "*";
995
- const XSTATE_INIT = "xstate.init";
996
- const XSTATE_STOP = "xstate.stop";
1109
+ //#region ../graph-tools/dist/semanticGraphDiffModel-1Yw70u6x.mjs
997
1110
  /**
998
- * Returns an event that represents an implicit event that is sent after the
999
- * specified `delay`.
1111
+ * Convert a resolved {@link GraphNode} back into a {@link NodeConfig}.
1000
1112
  *
1001
- * @param delayRef The delay in milliseconds
1002
- * @param id The state node ID where this event is handled
1113
+ * Faithful and complete: round-tripping through `createGraphNode` yields a
1114
+ * deep-equal node. Optional fields are only included when present; ports are
1115
+ * deep-copied so the config does not share port objects with the source node.
1003
1116
  */
1004
- function createAfterEvent(delayRef, id) {
1005
- return { type: `xstate.after.${delayRef}.${id}` };
1117
+ function toNodeConfig(node) {
1118
+ const config = { id: node.id };
1119
+ if (node.parentId != null) config.parentId = node.parentId;
1120
+ if (node.initialNodeId != null) config.initialNodeId = node.initialNodeId;
1121
+ if (node.label != null) config.label = node.label;
1122
+ if (node.data != null) config.data = node.data;
1123
+ if (node.ports !== void 0) config.ports = node.ports.map((p) => ({ ...p }));
1124
+ if (node.x !== void 0) config.x = node.x;
1125
+ if (node.y !== void 0) config.y = node.y;
1126
+ if (node.width !== void 0) config.width = node.width;
1127
+ if (node.height !== void 0) config.height = node.height;
1128
+ if (node.shape !== void 0) config.shape = node.shape;
1129
+ if (node.color !== void 0) config.color = node.color;
1130
+ if (node.style !== void 0) config.style = node.style;
1131
+ return config;
1006
1132
  }
1007
1133
  /**
1008
- * Returns an event that represents that a final state node has been reached in
1009
- * the parent state node.
1134
+ * Convert a resolved {@link GraphEdge} back into an {@link EdgeConfig}.
1010
1135
  *
1011
- * @param id The final state node's parent state node `id`
1012
- * @param output The data to pass into the event
1136
+ * Faithful and complete: round-tripping through `createGraphEdge` yields a
1137
+ * deep-equal edge. Optional fields are only included when present.
1013
1138
  */
1014
- function createDoneStateEvent(id, output) {
1015
- return {
1016
- type: `xstate.done.state.${id}`,
1017
- output
1139
+ function toEdgeConfig(edge) {
1140
+ const config = {
1141
+ id: edge.id,
1142
+ sourceId: edge.sourceId,
1143
+ targetId: edge.targetId
1018
1144
  };
1145
+ if (edge.label != null) config.label = edge.label;
1146
+ if (edge.data != null) config.data = edge.data;
1147
+ if (edge.weight !== void 0) config.weight = edge.weight;
1148
+ if (edge.mode !== void 0) config.mode = edge.mode;
1149
+ if (edge.sourcePort !== void 0) config.sourcePort = edge.sourcePort;
1150
+ if (edge.targetPort !== void 0) config.targetPort = edge.targetPort;
1151
+ if (edge.points !== void 0) config.points = edge.points.map((p) => ({ ...p }));
1152
+ if (edge.routing !== void 0) config.routing = edge.routing;
1153
+ if (edge.x !== void 0) config.x = edge.x;
1154
+ if (edge.y !== void 0) config.y = edge.y;
1155
+ if (edge.width !== void 0) config.width = edge.width;
1156
+ if (edge.height !== void 0) config.height = edge.height;
1157
+ if (edge.color !== void 0) config.color = edge.color;
1158
+ if (edge.style !== void 0) config.style = edge.style;
1159
+ return config;
1160
+ }
1161
+ const LAYOUT_KEYS$1 = {
1162
+ node: [
1163
+ "x",
1164
+ "y",
1165
+ "width",
1166
+ "height",
1167
+ "style",
1168
+ "color",
1169
+ "shape"
1170
+ ],
1171
+ edge: [
1172
+ "x",
1173
+ "y",
1174
+ "width",
1175
+ "height",
1176
+ "points",
1177
+ "routing",
1178
+ "style",
1179
+ "color"
1180
+ ]
1181
+ };
1182
+ new Set(LAYOUT_KEYS$1.node), new Set(LAYOUT_KEYS$1.edge);
1183
+ /** Shallow-compare two values, returning true if they differ. */
1184
+ function differs(a, b) {
1185
+ if (a === b) return false;
1186
+ if (a == null || b == null) return a !== b;
1187
+ if (typeof a === "object" && typeof b === "object") return JSON.stringify(a) !== JSON.stringify(b);
1188
+ return true;
1019
1189
  }
1190
+ const NODE_COMPARE_KEYS = [
1191
+ "parentId",
1192
+ "initialNodeId",
1193
+ "label",
1194
+ "data",
1195
+ "ports",
1196
+ "x",
1197
+ "y",
1198
+ "width",
1199
+ "height",
1200
+ "shape",
1201
+ "color",
1202
+ "style"
1203
+ ];
1204
+ const EDGE_COMPARE_KEYS = [
1205
+ "sourceId",
1206
+ "targetId",
1207
+ "label",
1208
+ "data",
1209
+ "weight",
1210
+ "mode",
1211
+ "sourcePort",
1212
+ "targetPort",
1213
+ "points",
1214
+ "routing",
1215
+ "x",
1216
+ "y",
1217
+ "width",
1218
+ "height",
1219
+ "color",
1220
+ "style"
1221
+ ];
1020
1222
  /**
1021
- * Returns an event that represents that an invoked service has terminated.
1223
+ * Compute a structured diff from graph `a` to graph `b` by matching IDs.
1022
1224
  *
1023
- * An invoked service is terminated when it has reached a top-level final state
1024
- * node, but not when it is canceled.
1225
+ * @example
1226
+ * ```ts
1227
+ * import { createGraph, getDiff } from '@statelyai/graph';
1025
1228
  *
1026
- * @param invokeId The invoked service ID
1027
- * @param output The data to pass into the event
1028
- */
1029
- function createDoneActorEvent(invokeId, output) {
1030
- return {
1031
- type: `xstate.done.actor.${invokeId}`,
1032
- output,
1033
- actorId: invokeId
1034
- };
1035
- }
1036
- function createErrorActorEvent(id, error) {
1037
- return {
1038
- type: `xstate.error.actor.${id}`,
1039
- error,
1040
- actorId: id
1041
- };
1042
- }
1043
- function createInitEvent(input) {
1044
- return {
1045
- type: XSTATE_INIT,
1046
- input
1047
- };
1048
- }
1049
- /**
1050
- * This function makes sure that unhandled errors are thrown in a separate
1051
- * macrotask. It allows those errors to be detected by global error handlers and
1052
- * reported to bug tracking services without interrupting our own stack of
1053
- * execution.
1229
+ * const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
1230
+ * const b = createGraph({ nodes: [{ id: 'n1', label: 'hello' }, { id: 'n2' }], edges: [] });
1054
1231
  *
1055
- * @param err Error to be thrown
1232
+ * const diff = getDiff(a, b);
1233
+ * // diff.nodes.added → [{ id: 'n2' }]
1234
+ * // diff.nodes.updated → [{ id: 'n1', old: { label: '' }, new: { label: 'hello' } }]
1235
+ * ```
1056
1236
  */
1057
- function reportUnhandledError(err) {
1058
- setTimeout(() => {
1059
- throw err;
1060
- });
1061
- }
1062
- const symbolObservable = typeof Symbol === "function" && Symbol.observable || "@@observable";
1063
- function matchesState(parentStateId, childStateId) {
1064
- const parentStateValue = toStateValue(parentStateId);
1065
- const childStateValue = toStateValue(childStateId);
1066
- if (typeof childStateValue === "string") {
1067
- if (typeof parentStateValue === "string") return childStateValue === parentStateValue;
1068
- return false;
1237
+ function getDiff(a, b) {
1238
+ const aNodeMap = new Map(a.nodes.map((n) => [n.id, n]));
1239
+ const bNodeMap = new Map(b.nodes.map((n) => [n.id, n]));
1240
+ const aEdgeMap = new Map(a.edges.map((e) => [e.id, e]));
1241
+ const bEdgeMap = new Map(b.edges.map((e) => [e.id, e]));
1242
+ const diff = {
1243
+ nodes: {
1244
+ added: [],
1245
+ removed: [],
1246
+ updated: []
1247
+ },
1248
+ edges: {
1249
+ added: [],
1250
+ removed: [],
1251
+ updated: []
1252
+ }
1253
+ };
1254
+ for (const [id, nodeB] of bNodeMap) {
1255
+ const nodeA = aNodeMap.get(id);
1256
+ if (!nodeA) diff.nodes.added.push(toNodeConfig(nodeB));
1257
+ else {
1258
+ const oldPartial = {};
1259
+ const newPartial = {};
1260
+ for (const key of NODE_COMPARE_KEYS) {
1261
+ const oldValue = nodeA[key] ?? null;
1262
+ const newValue = nodeB[key] ?? null;
1263
+ if (differs(oldValue, newValue)) {
1264
+ oldPartial[key] = oldValue;
1265
+ newPartial[key] = newValue;
1266
+ }
1267
+ }
1268
+ if (Object.keys(oldPartial).length > 0) diff.nodes.updated.push({
1269
+ id,
1270
+ old: oldPartial,
1271
+ new: newPartial
1272
+ });
1273
+ }
1069
1274
  }
1070
- if (typeof parentStateValue === "string") return parentStateValue in childStateValue;
1071
- return Object.keys(parentStateValue).every((key) => {
1072
- if (!(key in childStateValue)) return false;
1073
- return matchesState(parentStateValue[key], childStateValue[key]);
1074
- });
1075
- }
1076
- function toStatePath(stateId) {
1077
- if (isArray(stateId)) return stateId;
1078
- const result = [];
1079
- let segment = "";
1080
- for (let i = 0; i < stateId.length; i++) {
1081
- switch (stateId.charCodeAt(i)) {
1082
- case 92:
1083
- segment += stateId[i + 1];
1084
- i++;
1085
- continue;
1086
- case 46:
1087
- result.push(segment);
1088
- segment = "";
1089
- continue;
1275
+ for (const [id, nodeA] of aNodeMap) if (!bNodeMap.has(id)) diff.nodes.removed.push(toNodeConfig(nodeA));
1276
+ for (const [id, edgeB] of bEdgeMap) {
1277
+ const edgeA = aEdgeMap.get(id);
1278
+ if (!edgeA) diff.edges.added.push(toEdgeConfig(edgeB));
1279
+ else {
1280
+ const oldPartial = {};
1281
+ const newPartial = {};
1282
+ for (const key of EDGE_COMPARE_KEYS) {
1283
+ const oldValue = edgeA[key] ?? null;
1284
+ const newValue = edgeB[key] ?? null;
1285
+ if (differs(oldValue, newValue)) {
1286
+ oldPartial[key] = oldValue;
1287
+ newPartial[key] = newValue;
1288
+ }
1289
+ }
1290
+ if (Object.keys(oldPartial).length > 0) diff.edges.updated.push({
1291
+ id,
1292
+ old: oldPartial,
1293
+ new: newPartial
1294
+ });
1090
1295
  }
1091
- segment += stateId[i];
1092
1296
  }
1093
- result.push(segment);
1094
- return result;
1297
+ for (const [id, edgeA] of aEdgeMap) if (!bEdgeMap.has(id)) diff.edges.removed.push(toEdgeConfig(edgeA));
1298
+ return diff;
1095
1299
  }
1096
- function toStateValue(stateValue) {
1097
- if (isMachineSnapshot(stateValue)) return stateValue.value;
1098
- if (typeof stateValue !== "string") return stateValue;
1099
- return pathToStateValue(toStatePath(stateValue));
1300
+ /**
1301
+ * Check if a diff has zero changes.
1302
+ *
1303
+ * @example
1304
+ * ```ts
1305
+ * import { createGraph, getDiff, isEmptyDiff } from '@statelyai/graph';
1306
+ *
1307
+ * const g = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
1308
+ * const diff = getDiff(g, g);
1309
+ * isEmptyDiff(diff); // true
1310
+ * ```
1311
+ */
1312
+ function isEmptyDiff$1(diff) {
1313
+ return diff.nodes.added.length === 0 && diff.nodes.removed.length === 0 && diff.nodes.updated.length === 0 && diff.edges.added.length === 0 && diff.edges.removed.length === 0 && diff.edges.updated.length === 0;
1100
1314
  }
1101
- function pathToStateValue(statePath) {
1102
- if (statePath.length === 1) return statePath[0];
1103
- const value = {};
1104
- let marker = value;
1105
- for (let i = 0; i < statePath.length - 1; i++) if (i === statePath.length - 2) marker[statePath[i]] = statePath[i + 1];
1106
- else {
1107
- const previous = marker;
1108
- marker = {};
1109
- previous[statePath[i]] = marker;
1110
- }
1111
- return value;
1315
+ function summarizeGraphDiff(diff) {
1316
+ return {
1317
+ hasChanges: !isEmptyDiff$1(diff),
1318
+ nodeChanges: diff.nodes.added.length + diff.nodes.removed.length + diff.nodes.updated.length,
1319
+ edgeChanges: diff.edges.added.length + diff.edges.removed.length + diff.edges.updated.length
1320
+ };
1112
1321
  }
1113
- function mapValues(collection, iteratee) {
1114
- const result = {};
1115
- const collectionKeys = Object.keys(collection);
1116
- for (let i = 0; i < collectionKeys.length; i++) {
1117
- const key = collectionKeys[i];
1118
- result[key] = iteratee(collection[key], key, collection, i);
1322
+ function nodeDepth$1(graph, node) {
1323
+ let depth = 0;
1324
+ let parentId = node.parentId;
1325
+ while (parentId) {
1326
+ depth++;
1327
+ parentId = graph.nodes.find((candidate) => candidate.id === parentId)?.parentId;
1119
1328
  }
1120
- return result;
1121
- }
1122
- function toArrayStrict(value) {
1123
- if (isArray(value)) return value;
1124
- return [value];
1125
- }
1126
- function toArray$1(value) {
1127
- if (value === void 0) return [];
1128
- return toArrayStrict(value);
1129
- }
1130
- function resolveOutput(mapper, context, event, self) {
1131
- if (typeof mapper === "function") return mapper({
1132
- context,
1133
- event,
1134
- self
1135
- });
1136
- return mapper;
1137
- }
1138
- function isArray(value) {
1139
- return Array.isArray(value);
1140
- }
1141
- function isErrorActorEvent(event) {
1142
- return event.type.startsWith("xstate.error.actor");
1329
+ return depth;
1143
1330
  }
1144
- function toTransitionConfigArray(configLike) {
1145
- return toArrayStrict(configLike).map((transitionLike) => {
1146
- if (typeof transitionLike === "undefined" || typeof transitionLike === "string") return { target: transitionLike };
1147
- return transitionLike;
1148
- });
1331
+ function nodeKey(node) {
1332
+ return node.data?.key || node.id;
1149
1333
  }
1150
- function normalizeTarget(target) {
1151
- if (target === void 0 || target === TARGETLESS_KEY) return;
1152
- return toArray$1(target);
1334
+ function edgeSignature(edge) {
1335
+ return [
1336
+ edge.sourceId,
1337
+ edge.data?.eventType,
1338
+ edge.targetId,
1339
+ edge.data?.guard?.type ?? ""
1340
+ ].join("->");
1153
1341
  }
1154
- function toObserver(nextHandler, errorHandler, completionHandler) {
1155
- const isObserver = typeof nextHandler === "object";
1156
- const self = isObserver ? nextHandler : void 0;
1157
- return {
1158
- next: (isObserver ? nextHandler.next : nextHandler)?.bind(self),
1159
- error: (isObserver ? nextHandler.error : errorHandler)?.bind(self),
1160
- complete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self)
1161
- };
1342
+ function getStableNodeId(node, parentStableId, siblingIndex, preferredIds) {
1343
+ const preferredId = preferredIds?.get(node.id);
1344
+ if (preferredId !== void 0) return preferredId;
1345
+ if (node.parentId === null) return "root";
1346
+ const key = nodeKey(node);
1347
+ const suffix = siblingIndex === 0 ? key : `${key}_${siblingIndex + 1}`;
1348
+ return parentStableId ? `${parentStableId}.${suffix}` : suffix;
1162
1349
  }
1163
- function createInvokeId(stateNodeId, index) {
1164
- return `${index}.${stateNodeId}`;
1350
+ function getStableEdgeId(edge, siblingIndex, preferredIds) {
1351
+ const preferredId = preferredIds?.get(edge.id);
1352
+ if (preferredId !== void 0) return preferredId;
1353
+ const suffix = siblingIndex === 0 ? "" : `.${siblingIndex + 1}`;
1354
+ return edgeSignature(edge).concat(suffix);
1165
1355
  }
1166
- function resolveReferencedActor(machine, src) {
1167
- const match = src.match(/^xstate\.invoke\.(\d+)\.(.*)/);
1168
- if (!match) return machine.implementations.actors[src];
1169
- const [, indexStr, nodeId] = match;
1170
- const invokeConfig = machine.getStateNodeById(nodeId).config.invoke;
1171
- return (Array.isArray(invokeConfig) ? invokeConfig[indexStr] : invokeConfig).src;
1356
+ function removePresentationFields(entity, kind) {
1357
+ const mutableEntity = entity;
1358
+ for (const key of LAYOUT_KEYS$1[kind]) delete mutableEntity[key];
1359
+ const data = mutableEntity.data;
1360
+ if (data && typeof data === "object" && !Array.isArray(data)) delete data.color;
1172
1361
  }
1173
1362
  /**
1174
- * Checks if an event type matches an event descriptor, supporting wildcards.
1175
- * Event descriptors can be:
1176
- *
1177
- * - Exact matches: "event.type"
1178
- * - Wildcard: "*"
1179
- * - Partial matches: "event.*"
1363
+ * Rewrites entity ids to structural ("semantic") ids so two graphs that model
1364
+ * the same machine compare equal regardless of how their ids were minted.
1180
1365
  *
1181
- * @param eventType - The actual event type string
1182
- * @param descriptor - The event descriptor to match against
1366
+ * Invariant: node and edge array order is preserved exactly. Callers
1367
+ * (`alignCompareIds` in the editor's /v1/diff route) rely on
1368
+ * `normalized.nodes[i]` describing `graph.nodes[i]` to translate a semantic id
1369
+ * back to the caller's original id. Never sort, filter, or reorder the arrays
1370
+ * on the returned graph; sorting for traversal must be done on a copy, as the
1371
+ * depth ordering below does.
1372
+ *
1373
+ * Presentation-only fields defined by `LAYOUT_KEYS`, plus entity data colors,
1374
+ * are removed. When preferred ids are supplied, matching raw ids retain the
1375
+ * base graph's semantic identity so a stable-id rename is reported as an
1376
+ * update.
1377
+ *
1378
+ * Entity `data` is treated as optional throughout: sparse graphs (a node with
1379
+ * `data: {}`, an edge with `data: null`) normalize instead of throwing.
1380
+ */
1381
+ function normalizeGraphForSemanticDiff(graph, preferredIds) {
1382
+ const normalized = structuredClone(graph);
1383
+ const nodeIdMap = /* @__PURE__ */ new Map();
1384
+ const siblingKeys = /* @__PURE__ */ new Map();
1385
+ const reservedNodeIds = new Set(preferredIds?.nodes.values());
1386
+ const claimedNodeIds = /* @__PURE__ */ new Set();
1387
+ const nodesByDepth = [...normalized.nodes].sort((a, b) => nodeDepth$1(normalized, a) - nodeDepth$1(normalized, b));
1388
+ for (const node of nodesByDepth) {
1389
+ const parentStableId = node.parentId ? nodeIdMap.get(node.parentId) ?? node.parentId : null;
1390
+ const key = `${parentStableId ?? ""}:${nodeKey(node)}`;
1391
+ const siblingIndex = siblingKeys.get(key) ?? 0;
1392
+ siblingKeys.set(key, siblingIndex + 1);
1393
+ const proposedId = getStableNodeId(node, parentStableId, siblingIndex, preferredIds?.nodes);
1394
+ let stableId = proposedId;
1395
+ let collisionIndex = 2;
1396
+ while (!preferredIds?.nodes.has(node.id) && (reservedNodeIds.has(stableId) || claimedNodeIds.has(stableId))) stableId = `${proposedId}:unmatched:${collisionIndex++}`;
1397
+ claimedNodeIds.add(stableId);
1398
+ nodeIdMap.set(node.id, stableId);
1399
+ }
1400
+ for (const node of normalized.nodes) {
1401
+ removePresentationFields(node, "node");
1402
+ node.id = nodeIdMap.get(node.id) ?? node.id;
1403
+ if (node.parentId) node.parentId = nodeIdMap.get(node.parentId) ?? node.parentId;
1404
+ if (node.initialNodeId) node.initialNodeId = nodeIdMap.get(node.initialNodeId) ?? node.initialNodeId;
1405
+ if (node.data?.initialId) node.data.initialId = nodeIdMap.get(node.data.initialId) ?? node.data.initialId;
1406
+ }
1407
+ const edgeSiblingKeys = /* @__PURE__ */ new Map();
1408
+ const reservedEdgeIds = new Set(preferredIds?.edges.values());
1409
+ const claimedEdgeIds = /* @__PURE__ */ new Set();
1410
+ for (const edge of normalized.edges) {
1411
+ removePresentationFields(edge, "edge");
1412
+ edge.sourceId = nodeIdMap.get(edge.sourceId) ?? edge.sourceId;
1413
+ edge.targetId = nodeIdMap.get(edge.targetId) ?? edge.targetId;
1414
+ const key = edgeSignature(edge);
1415
+ const siblingIndex = edgeSiblingKeys.get(key) ?? 0;
1416
+ edgeSiblingKeys.set(key, siblingIndex + 1);
1417
+ const proposedId = getStableEdgeId(edge, siblingIndex, preferredIds?.edges);
1418
+ let stableId = proposedId;
1419
+ let collisionIndex = 2;
1420
+ while (!preferredIds?.edges.has(edge.id) && (reservedEdgeIds.has(stableId) || claimedEdgeIds.has(stableId))) stableId = `${proposedId}:unmatched:${collisionIndex++}`;
1421
+ claimedEdgeIds.add(stableId);
1422
+ edge.id = stableId;
1423
+ }
1424
+ if (normalized.initialNodeId) normalized.initialNodeId = nodeIdMap.get(normalized.initialNodeId) ?? normalized.initialNodeId;
1425
+ return normalized;
1426
+ }
1427
+ function diffGraphsSemantically(baseGraph, compareGraph) {
1428
+ const base = normalizeGraphForSemanticDiff(baseGraph);
1429
+ const compareNodeIds = new Set(compareGraph.nodes.map((node) => node.id));
1430
+ const compareEdgeIds = new Set(compareGraph.edges.map((edge) => edge.id));
1431
+ const compare = normalizeGraphForSemanticDiff(compareGraph, {
1432
+ nodes: new Map(baseGraph.nodes.map((node, index) => [node.id, base.nodes[index].id]).filter(([id]) => compareNodeIds.has(id))),
1433
+ edges: new Map(baseGraph.edges.map((edge, index) => [edge.id, base.edges[index].id]).filter(([id]) => compareEdgeIds.has(id)))
1434
+ });
1435
+ const diff = getDiff(base, compare);
1436
+ return {
1437
+ base,
1438
+ compare,
1439
+ diff,
1440
+ summary: summarizeGraphDiff(diff)
1441
+ };
1442
+ }
1443
+
1444
+ //#endregion
1445
+ //#region ../../node_modules/.pnpm/xstate@5.32.1/node_modules/xstate/dist/xstate-dev.esm.js
1446
+ function getGlobal() {
1447
+ if (typeof globalThis !== "undefined") return globalThis;
1448
+ if (typeof self !== "undefined") return self;
1449
+ if (typeof window !== "undefined") return window;
1450
+ if (typeof global !== "undefined") return global;
1451
+ }
1452
+ function getDevTools() {
1453
+ const w = getGlobal();
1454
+ if (w.__xstate__) return w.__xstate__;
1455
+ }
1456
+ const devToolsAdapter = (service) => {
1457
+ if (typeof window === "undefined") return;
1458
+ const devTools = getDevTools();
1459
+ if (devTools) devTools.register(service);
1460
+ };
1461
+
1462
+ //#endregion
1463
+ //#region ../../node_modules/.pnpm/xstate@5.32.1/node_modules/xstate/dist/raise-e974d1c9.esm.js
1464
+ var Mailbox = class {
1465
+ constructor(_process) {
1466
+ this._process = _process;
1467
+ this._active = false;
1468
+ this._current = null;
1469
+ this._last = null;
1470
+ }
1471
+ start() {
1472
+ this._active = true;
1473
+ this.flush();
1474
+ }
1475
+ clear() {
1476
+ if (this._current) {
1477
+ this._current.next = null;
1478
+ this._last = this._current;
1479
+ }
1480
+ }
1481
+ enqueue(event) {
1482
+ const enqueued = {
1483
+ value: event,
1484
+ next: null
1485
+ };
1486
+ if (this._current) {
1487
+ this._last.next = enqueued;
1488
+ this._last = enqueued;
1489
+ return;
1490
+ }
1491
+ this._current = enqueued;
1492
+ this._last = enqueued;
1493
+ if (this._active) this.flush();
1494
+ }
1495
+ flush() {
1496
+ while (this._current) {
1497
+ const consumed = this._current;
1498
+ this._process(consumed.value);
1499
+ this._current = consumed.next;
1500
+ }
1501
+ this._last = null;
1502
+ }
1503
+ };
1504
+ const STATE_DELIMITER = ".";
1505
+ const TARGETLESS_KEY = "";
1506
+ const NULL_EVENT = "";
1507
+ const STATE_IDENTIFIER = "#";
1508
+ const WILDCARD = "*";
1509
+ const XSTATE_INIT = "xstate.init";
1510
+ const XSTATE_STOP = "xstate.stop";
1511
+ /**
1512
+ * Returns an event that represents an implicit event that is sent after the
1513
+ * specified `delay`.
1514
+ *
1515
+ * @param delayRef The delay in milliseconds
1516
+ * @param id The state node ID where this event is handled
1517
+ */
1518
+ function createAfterEvent(delayRef, id) {
1519
+ return { type: `xstate.after.${delayRef}.${id}` };
1520
+ }
1521
+ /**
1522
+ * Returns an event that represents that a final state node has been reached in
1523
+ * the parent state node.
1524
+ *
1525
+ * @param id The final state node's parent state node `id`
1526
+ * @param output The data to pass into the event
1527
+ */
1528
+ function createDoneStateEvent(id, output) {
1529
+ return {
1530
+ type: `xstate.done.state.${id}`,
1531
+ output
1532
+ };
1533
+ }
1534
+ /**
1535
+ * Returns an event that represents that an invoked service has terminated.
1536
+ *
1537
+ * An invoked service is terminated when it has reached a top-level final state
1538
+ * node, but not when it is canceled.
1539
+ *
1540
+ * @param invokeId The invoked service ID
1541
+ * @param output The data to pass into the event
1542
+ */
1543
+ function createDoneActorEvent(invokeId, output) {
1544
+ return {
1545
+ type: `xstate.done.actor.${invokeId}`,
1546
+ output,
1547
+ actorId: invokeId
1548
+ };
1549
+ }
1550
+ function createErrorActorEvent(id, error) {
1551
+ return {
1552
+ type: `xstate.error.actor.${id}`,
1553
+ error,
1554
+ actorId: id
1555
+ };
1556
+ }
1557
+ function createInitEvent(input) {
1558
+ return {
1559
+ type: XSTATE_INIT,
1560
+ input
1561
+ };
1562
+ }
1563
+ /**
1564
+ * This function makes sure that unhandled errors are thrown in a separate
1565
+ * macrotask. It allows those errors to be detected by global error handlers and
1566
+ * reported to bug tracking services without interrupting our own stack of
1567
+ * execution.
1568
+ *
1569
+ * @param err Error to be thrown
1570
+ */
1571
+ function reportUnhandledError(err) {
1572
+ setTimeout(() => {
1573
+ throw err;
1574
+ });
1575
+ }
1576
+ const symbolObservable = typeof Symbol === "function" && Symbol.observable || "@@observable";
1577
+ function matchesState(parentStateId, childStateId) {
1578
+ const parentStateValue = toStateValue(parentStateId);
1579
+ const childStateValue = toStateValue(childStateId);
1580
+ if (typeof childStateValue === "string") {
1581
+ if (typeof parentStateValue === "string") return childStateValue === parentStateValue;
1582
+ return false;
1583
+ }
1584
+ if (typeof parentStateValue === "string") return parentStateValue in childStateValue;
1585
+ return Object.keys(parentStateValue).every((key) => {
1586
+ if (!(key in childStateValue)) return false;
1587
+ return matchesState(parentStateValue[key], childStateValue[key]);
1588
+ });
1589
+ }
1590
+ function toStatePath(stateId) {
1591
+ if (isArray(stateId)) return stateId;
1592
+ const result = [];
1593
+ let segment = "";
1594
+ for (let i = 0; i < stateId.length; i++) {
1595
+ switch (stateId.charCodeAt(i)) {
1596
+ case 92:
1597
+ segment += stateId[i + 1];
1598
+ i++;
1599
+ continue;
1600
+ case 46:
1601
+ result.push(segment);
1602
+ segment = "";
1603
+ continue;
1604
+ }
1605
+ segment += stateId[i];
1606
+ }
1607
+ result.push(segment);
1608
+ return result;
1609
+ }
1610
+ function toStateValue(stateValue) {
1611
+ if (isMachineSnapshot(stateValue)) return stateValue.value;
1612
+ if (typeof stateValue !== "string") return stateValue;
1613
+ return pathToStateValue(toStatePath(stateValue));
1614
+ }
1615
+ function pathToStateValue(statePath) {
1616
+ if (statePath.length === 1) return statePath[0];
1617
+ const value = {};
1618
+ let marker = value;
1619
+ for (let i = 0; i < statePath.length - 1; i++) if (i === statePath.length - 2) marker[statePath[i]] = statePath[i + 1];
1620
+ else {
1621
+ const previous = marker;
1622
+ marker = {};
1623
+ previous[statePath[i]] = marker;
1624
+ }
1625
+ return value;
1626
+ }
1627
+ function mapValues(collection, iteratee) {
1628
+ const result = {};
1629
+ const collectionKeys = Object.keys(collection);
1630
+ for (let i = 0; i < collectionKeys.length; i++) {
1631
+ const key = collectionKeys[i];
1632
+ result[key] = iteratee(collection[key], key, collection, i);
1633
+ }
1634
+ return result;
1635
+ }
1636
+ function toArrayStrict(value) {
1637
+ if (isArray(value)) return value;
1638
+ return [value];
1639
+ }
1640
+ function toArray$1(value) {
1641
+ if (value === void 0) return [];
1642
+ return toArrayStrict(value);
1643
+ }
1644
+ function resolveOutput(mapper, context, event, self) {
1645
+ if (typeof mapper === "function") return mapper({
1646
+ context,
1647
+ event,
1648
+ self
1649
+ });
1650
+ return mapper;
1651
+ }
1652
+ function isArray(value) {
1653
+ return Array.isArray(value);
1654
+ }
1655
+ function isErrorActorEvent(event) {
1656
+ return event.type.startsWith("xstate.error.actor");
1657
+ }
1658
+ function toTransitionConfigArray(configLike) {
1659
+ return toArrayStrict(configLike).map((transitionLike) => {
1660
+ if (typeof transitionLike === "undefined" || typeof transitionLike === "string") return { target: transitionLike };
1661
+ return transitionLike;
1662
+ });
1663
+ }
1664
+ function normalizeTarget(target) {
1665
+ if (target === void 0 || target === TARGETLESS_KEY) return;
1666
+ return toArray$1(target);
1667
+ }
1668
+ function toObserver(nextHandler, errorHandler, completionHandler) {
1669
+ const isObserver = typeof nextHandler === "object";
1670
+ const self = isObserver ? nextHandler : void 0;
1671
+ return {
1672
+ next: (isObserver ? nextHandler.next : nextHandler)?.bind(self),
1673
+ error: (isObserver ? nextHandler.error : errorHandler)?.bind(self),
1674
+ complete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self)
1675
+ };
1676
+ }
1677
+ function createInvokeId(stateNodeId, index) {
1678
+ return `${index}.${stateNodeId}`;
1679
+ }
1680
+ function resolveReferencedActor(machine, src) {
1681
+ const match = src.match(/^xstate\.invoke\.(\d+)\.(.*)/);
1682
+ if (!match) return machine.implementations.actors[src];
1683
+ const [, indexStr, nodeId] = match;
1684
+ const invokeConfig = machine.getStateNodeById(nodeId).config.invoke;
1685
+ return (Array.isArray(invokeConfig) ? invokeConfig[indexStr] : invokeConfig).src;
1686
+ }
1687
+ /**
1688
+ * Checks if an event type matches an event descriptor, supporting wildcards.
1689
+ * Event descriptors can be:
1690
+ *
1691
+ * - Exact matches: "event.type"
1692
+ * - Wildcard: "*"
1693
+ * - Partial matches: "event.*"
1694
+ *
1695
+ * @param eventType - The actual event type string
1696
+ * @param descriptor - The event descriptor to match against
1183
1697
  * @returns True if the event type matches the descriptor
1184
1698
  */
1185
1699
  function matchesEventDescriptor(eventType, descriptor) {
@@ -5538,666 +6052,333 @@ var require_dumper = /* @__PURE__ */ __commonJSMin(((exports, module) => {
5538
6052
  if (shouldTrackWidth) {
5539
6053
  hasFoldableLine = hasFoldableLine || i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ";
5540
6054
  previousLineBreak = i;
5541
- }
5542
- } else if (!isPrintable(char)) return STYLE_DOUBLE;
5543
- plain = plain && isPlainSafe(char, prevChar, inblock);
5544
- prevChar = char;
5545
- }
5546
- hasFoldableLine = hasFoldableLine || shouldTrackWidth && i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ";
5547
- }
5548
- if (!hasLineBreak && !hasFoldableLine) {
5549
- if (plain && !forceQuotes && !testAmbiguousType(string)) return STYLE_PLAIN;
5550
- return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
5551
- }
5552
- if (indentPerLevel > 9 && needIndentIndicator(string)) return STYLE_DOUBLE;
5553
- if (!forceQuotes) return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
5554
- return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
5555
- }
5556
- function writeScalar(state, string, level, iskey, inblock) {
5557
- state.dump = function() {
5558
- if (string.length === 0) return state.quotingType === QUOTING_TYPE_DOUBLE ? "\"\"" : "''";
5559
- if (!state.noCompatMode) {
5560
- if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) return state.quotingType === QUOTING_TYPE_DOUBLE ? "\"" + string + "\"" : "'" + string + "'";
5561
- }
5562
- const indent = state.indent * Math.max(1, level);
5563
- const lineWidth = state.lineWidth === -1 ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);
5564
- const singleLineOnly = iskey || state.flowLevel > -1 && level >= state.flowLevel;
5565
- function testAmbiguity(string) {
5566
- return testImplicitResolving(state, string);
5567
- }
5568
- switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth, testAmbiguity, state.quotingType, state.forceQuotes && !iskey, inblock)) {
5569
- case STYLE_PLAIN: return string;
5570
- case STYLE_SINGLE: return "'" + string.replace(/'/g, "''") + "'";
5571
- case STYLE_LITERAL: return "|" + blockHeader(string, state.indent) + dropEndingNewline(indentString(string, indent));
5572
- case STYLE_FOLDED: return ">" + blockHeader(string, state.indent) + dropEndingNewline(indentString(foldString(string, lineWidth), indent));
5573
- case STYLE_DOUBLE: return "\"" + escapeString(string, lineWidth) + "\"";
5574
- default: throw new YAMLException("impossible error: invalid scalar style");
5575
- }
5576
- }();
5577
- }
5578
- function blockHeader(string, indentPerLevel) {
5579
- const indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : "";
5580
- const clip = string[string.length - 1] === "\n";
5581
- return indentIndicator + (clip && (string[string.length - 2] === "\n" || string === "\n") ? "+" : clip ? "" : "-") + "\n";
5582
- }
5583
- function dropEndingNewline(string) {
5584
- return string[string.length - 1] === "\n" ? string.slice(0, -1) : string;
5585
- }
5586
- function foldString(string, width) {
5587
- const lineRe = /(\n+)([^\n]*)/g;
5588
- let result = function() {
5589
- let nextLF = string.indexOf("\n");
5590
- nextLF = nextLF !== -1 ? nextLF : string.length;
5591
- lineRe.lastIndex = nextLF;
5592
- return foldLine(string.slice(0, nextLF), width);
5593
- }();
5594
- let prevMoreIndented = string[0] === "\n" || string[0] === " ";
5595
- let moreIndented;
5596
- let match;
5597
- while (match = lineRe.exec(string)) {
5598
- const prefix = match[1];
5599
- const line = match[2];
5600
- moreIndented = line[0] === " ";
5601
- result += prefix + (!prevMoreIndented && !moreIndented && line !== "" ? "\n" : "") + foldLine(line, width);
5602
- prevMoreIndented = moreIndented;
5603
- }
5604
- return result;
5605
- }
5606
- function foldLine(line, width) {
5607
- if (line === "" || line[0] === " ") return line;
5608
- const breakRe = / [^ ]/g;
5609
- let match;
5610
- let start = 0;
5611
- let end;
5612
- let curr = 0;
5613
- let next = 0;
5614
- let result = "";
5615
- while (match = breakRe.exec(line)) {
5616
- next = match.index;
5617
- if (next - start > width) {
5618
- end = curr > start ? curr : next;
5619
- result += "\n" + line.slice(start, end);
5620
- start = end + 1;
5621
- }
5622
- curr = next;
5623
- }
5624
- result += "\n";
5625
- if (line.length - start > width && curr > start) result += line.slice(start, curr) + "\n" + line.slice(curr + 1);
5626
- else result += line.slice(start);
5627
- return result.slice(1);
5628
- }
5629
- function escapeString(string) {
5630
- let result = "";
5631
- let char = 0;
5632
- for (let i = 0; i < string.length; char >= 65536 ? i += 2 : i++) {
5633
- char = codePointAt(string, i);
5634
- const escapeSeq = ESCAPE_SEQUENCES[char];
5635
- if (!escapeSeq && isPrintable(char)) {
5636
- result += string[i];
5637
- if (char >= 65536) result += string[i + 1];
5638
- } else result += escapeSeq || encodeHex(char);
5639
- }
5640
- return result;
5641
- }
5642
- function writeFlowSequence(state, level, object) {
5643
- let _result = "";
5644
- const _tag = state.tag;
5645
- for (let index = 0, length = object.length; index < length; index += 1) {
5646
- let value = object[index];
5647
- if (state.replacer) value = state.replacer.call(object, String(index), value);
5648
- if (writeNode(state, level, value, false, false) || typeof value === "undefined" && writeNode(state, level, null, false, false)) {
5649
- if (_result !== "") _result += "," + (!state.condenseFlow ? " " : "");
5650
- _result += state.dump;
5651
- }
5652
- }
5653
- state.tag = _tag;
5654
- state.dump = "[" + _result + "]";
5655
- }
5656
- function writeBlockSequence(state, level, object, compact) {
5657
- let _result = "";
5658
- const _tag = state.tag;
5659
- for (let index = 0, length = object.length; index < length; index += 1) {
5660
- let value = object[index];
5661
- if (state.replacer) value = state.replacer.call(object, String(index), value);
5662
- if (writeNode(state, level + 1, value, true, true, false, true) || typeof value === "undefined" && writeNode(state, level + 1, null, true, true, false, true)) {
5663
- if (!compact || _result !== "") _result += generateNextLine(state, level);
5664
- if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) _result += "-";
5665
- else _result += "- ";
5666
- _result += state.dump;
5667
- }
5668
- }
5669
- state.tag = _tag;
5670
- state.dump = _result || "[]";
5671
- }
5672
- function writeFlowMapping(state, level, object) {
5673
- let _result = "";
5674
- const _tag = state.tag;
5675
- const objectKeyList = Object.keys(object);
5676
- for (let index = 0, length = objectKeyList.length; index < length; index += 1) {
5677
- let pairBuffer = "";
5678
- if (_result !== "") pairBuffer += ", ";
5679
- if (state.condenseFlow) pairBuffer += "\"";
5680
- const objectKey = objectKeyList[index];
5681
- let objectValue = object[objectKey];
5682
- if (state.replacer) objectValue = state.replacer.call(object, objectKey, objectValue);
5683
- if (!writeNode(state, level, objectKey, false, false)) continue;
5684
- if (state.dump.length > 1024) pairBuffer += "? ";
5685
- pairBuffer += state.dump + (state.condenseFlow ? "\"" : "") + ":" + (state.condenseFlow ? "" : " ");
5686
- if (!writeNode(state, level, objectValue, false, false)) continue;
5687
- pairBuffer += state.dump;
5688
- _result += pairBuffer;
5689
- }
5690
- state.tag = _tag;
5691
- state.dump = "{" + _result + "}";
5692
- }
5693
- function writeBlockMapping(state, level, object, compact) {
5694
- let _result = "";
5695
- const _tag = state.tag;
5696
- const objectKeyList = Object.keys(object);
5697
- if (state.sortKeys === true) objectKeyList.sort();
5698
- else if (typeof state.sortKeys === "function") objectKeyList.sort(state.sortKeys);
5699
- else if (state.sortKeys) throw new YAMLException("sortKeys must be a boolean or a function");
5700
- for (let index = 0, length = objectKeyList.length; index < length; index += 1) {
5701
- let pairBuffer = "";
5702
- if (!compact || _result !== "") pairBuffer += generateNextLine(state, level);
5703
- const objectKey = objectKeyList[index];
5704
- let objectValue = object[objectKey];
5705
- if (state.replacer) objectValue = state.replacer.call(object, objectKey, objectValue);
5706
- if (!writeNode(state, level + 1, objectKey, true, true, true)) continue;
5707
- const explicitPair = state.tag !== null && state.tag !== "?" || state.dump && state.dump.length > 1024;
5708
- if (explicitPair) if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) pairBuffer += "?";
5709
- else pairBuffer += "? ";
5710
- pairBuffer += state.dump;
5711
- if (explicitPair) pairBuffer += generateNextLine(state, level);
5712
- if (!writeNode(state, level + 1, objectValue, true, explicitPair)) continue;
5713
- if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) pairBuffer += ":";
5714
- else pairBuffer += ": ";
5715
- pairBuffer += state.dump;
5716
- _result += pairBuffer;
5717
- }
5718
- state.tag = _tag;
5719
- state.dump = _result || "{}";
5720
- }
5721
- function detectType(state, object, explicit) {
5722
- const typeList = explicit ? state.explicitTypes : state.implicitTypes;
5723
- for (let index = 0, length = typeList.length; index < length; index += 1) {
5724
- const type = typeList[index];
5725
- if ((type.instanceOf || type.predicate) && (!type.instanceOf || typeof object === "object" && object instanceof type.instanceOf) && (!type.predicate || type.predicate(object))) {
5726
- if (explicit) if (type.multi && type.representName) state.tag = type.representName(object);
5727
- else state.tag = type.tag;
5728
- else state.tag = "?";
5729
- if (type.represent) {
5730
- const style = state.styleMap[type.tag] || type.defaultStyle;
5731
- let _result;
5732
- if (_toString.call(type.represent) === "[object Function]") _result = type.represent(object, style);
5733
- else if (_hasOwnProperty.call(type.represent, style)) _result = type.represent[style](object, style);
5734
- else throw new YAMLException("!<" + type.tag + "> tag resolver accepts not \"" + style + "\" style");
5735
- state.dump = _result;
5736
- }
5737
- return true;
5738
- }
5739
- }
5740
- return false;
5741
- }
5742
- function writeNode(state, level, object, block, compact, iskey, isblockseq) {
5743
- state.tag = null;
5744
- state.dump = object;
5745
- if (!detectType(state, object, false)) detectType(state, object, true);
5746
- const type = _toString.call(state.dump);
5747
- const inblock = block;
5748
- if (block) block = state.flowLevel < 0 || state.flowLevel > level;
5749
- const objectOrArray = type === "[object Object]" || type === "[object Array]";
5750
- let duplicateIndex;
5751
- let duplicate;
5752
- if (objectOrArray) {
5753
- duplicateIndex = state.duplicates.indexOf(object);
5754
- duplicate = duplicateIndex !== -1;
5755
- }
5756
- if (state.tag !== null && state.tag !== "?" || duplicate || state.indent !== 2 && level > 0) compact = false;
5757
- if (duplicate && state.usedDuplicates[duplicateIndex]) state.dump = "*ref_" + duplicateIndex;
5758
- else {
5759
- if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) state.usedDuplicates[duplicateIndex] = true;
5760
- if (type === "[object Object]") if (block && Object.keys(state.dump).length !== 0) {
5761
- writeBlockMapping(state, level, state.dump, compact);
5762
- if (duplicate) state.dump = "&ref_" + duplicateIndex + state.dump;
5763
- } else {
5764
- writeFlowMapping(state, level, state.dump);
5765
- if (duplicate) state.dump = "&ref_" + duplicateIndex + " " + state.dump;
5766
- }
5767
- else if (type === "[object Array]") if (block && state.dump.length !== 0) {
5768
- if (state.noArrayIndent && !isblockseq && level > 0) writeBlockSequence(state, level - 1, state.dump, compact);
5769
- else writeBlockSequence(state, level, state.dump, compact);
5770
- if (duplicate) state.dump = "&ref_" + duplicateIndex + state.dump;
5771
- } else {
5772
- writeFlowSequence(state, level, state.dump);
5773
- if (duplicate) state.dump = "&ref_" + duplicateIndex + " " + state.dump;
5774
- }
5775
- else if (type === "[object String]") {
5776
- if (state.tag !== "?") writeScalar(state, state.dump, level, iskey, inblock);
5777
- } else if (type === "[object Undefined]") return false;
5778
- else {
5779
- if (state.skipInvalid) return false;
5780
- throw new YAMLException("unacceptable kind of an object to dump " + type);
5781
- }
5782
- if (state.tag !== null && state.tag !== "?") {
5783
- let tagStr = encodeURI(state.tag[0] === "!" ? state.tag.slice(1) : state.tag).replace(/!/g, "%21");
5784
- if (state.tag[0] === "!") tagStr = "!" + tagStr;
5785
- else if (tagStr.slice(0, 18) === "tag:yaml.org,2002:") tagStr = "!!" + tagStr.slice(18);
5786
- else tagStr = "!<" + tagStr + ">";
5787
- state.dump = tagStr + " " + state.dump;
6055
+ }
6056
+ } else if (!isPrintable(char)) return STYLE_DOUBLE;
6057
+ plain = plain && isPlainSafe(char, prevChar, inblock);
6058
+ prevChar = char;
5788
6059
  }
6060
+ hasFoldableLine = hasFoldableLine || shouldTrackWidth && i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ";
5789
6061
  }
5790
- return true;
5791
- }
5792
- function getDuplicateReferences(object, state) {
5793
- const objects = [];
5794
- const duplicatesIndexes = [];
5795
- inspectNode(object, objects, duplicatesIndexes);
5796
- const length = duplicatesIndexes.length;
5797
- for (let index = 0; index < length; index += 1) state.duplicates.push(objects[duplicatesIndexes[index]]);
5798
- state.usedDuplicates = new Array(length);
6062
+ if (!hasLineBreak && !hasFoldableLine) {
6063
+ if (plain && !forceQuotes && !testAmbiguousType(string)) return STYLE_PLAIN;
6064
+ return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
6065
+ }
6066
+ if (indentPerLevel > 9 && needIndentIndicator(string)) return STYLE_DOUBLE;
6067
+ if (!forceQuotes) return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
6068
+ return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
5799
6069
  }
5800
- function inspectNode(object, objects, duplicatesIndexes) {
5801
- if (object !== null && typeof object === "object") {
5802
- const index = objects.indexOf(object);
5803
- if (index !== -1) {
5804
- if (duplicatesIndexes.indexOf(index) === -1) duplicatesIndexes.push(index);
5805
- } else {
5806
- objects.push(object);
5807
- if (Array.isArray(object)) for (let i = 0, length = object.length; i < length; i += 1) inspectNode(object[i], objects, duplicatesIndexes);
5808
- else {
5809
- const objectKeyList = Object.keys(object);
5810
- for (let i = 0, length = objectKeyList.length; i < length; i += 1) inspectNode(object[objectKeyList[i]], objects, duplicatesIndexes);
5811
- }
6070
+ function writeScalar(state, string, level, iskey, inblock) {
6071
+ state.dump = function() {
6072
+ if (string.length === 0) return state.quotingType === QUOTING_TYPE_DOUBLE ? "\"\"" : "''";
6073
+ if (!state.noCompatMode) {
6074
+ if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) return state.quotingType === QUOTING_TYPE_DOUBLE ? "\"" + string + "\"" : "'" + string + "'";
5812
6075
  }
5813
- }
6076
+ const indent = state.indent * Math.max(1, level);
6077
+ const lineWidth = state.lineWidth === -1 ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);
6078
+ const singleLineOnly = iskey || state.flowLevel > -1 && level >= state.flowLevel;
6079
+ function testAmbiguity(string) {
6080
+ return testImplicitResolving(state, string);
6081
+ }
6082
+ switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth, testAmbiguity, state.quotingType, state.forceQuotes && !iskey, inblock)) {
6083
+ case STYLE_PLAIN: return string;
6084
+ case STYLE_SINGLE: return "'" + string.replace(/'/g, "''") + "'";
6085
+ case STYLE_LITERAL: return "|" + blockHeader(string, state.indent) + dropEndingNewline(indentString(string, indent));
6086
+ case STYLE_FOLDED: return ">" + blockHeader(string, state.indent) + dropEndingNewline(indentString(foldString(string, lineWidth), indent));
6087
+ case STYLE_DOUBLE: return "\"" + escapeString(string, lineWidth) + "\"";
6088
+ default: throw new YAMLException("impossible error: invalid scalar style");
6089
+ }
6090
+ }();
5814
6091
  }
5815
- function dump(input, options) {
5816
- options = options || {};
5817
- const state = new State(options);
5818
- if (!state.noRefs) getDuplicateReferences(input, state);
5819
- let value = input;
5820
- if (state.replacer) value = state.replacer.call({ "": value }, "", value);
5821
- if (writeNode(state, 0, value, true, true)) return state.dump + "\n";
5822
- return "";
6092
+ function blockHeader(string, indentPerLevel) {
6093
+ const indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : "";
6094
+ const clip = string[string.length - 1] === "\n";
6095
+ return indentIndicator + (clip && (string[string.length - 2] === "\n" || string === "\n") ? "+" : clip ? "" : "-") + "\n";
5823
6096
  }
5824
- module.exports.dump = dump;
5825
- }));
5826
- var import_js_yaml = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
5827
- var loader = require_loader();
5828
- var dumper = require_dumper();
5829
- function renamed(from, to) {
5830
- return function() {
5831
- throw new Error("Function yaml." + from + " is removed in js-yaml 4. Use yaml." + to + " instead, which is now safe by default.");
5832
- };
6097
+ function dropEndingNewline(string) {
6098
+ return string[string.length - 1] === "\n" ? string.slice(0, -1) : string;
5833
6099
  }
5834
- module.exports.Type = require_type();
5835
- module.exports.Schema = require_schema();
5836
- module.exports.FAILSAFE_SCHEMA = require_failsafe();
5837
- module.exports.JSON_SCHEMA = require_json();
5838
- module.exports.CORE_SCHEMA = require_core();
5839
- module.exports.DEFAULT_SCHEMA = require_default();
5840
- module.exports.load = loader.load;
5841
- module.exports.loadAll = loader.loadAll;
5842
- module.exports.dump = dumper.dump;
5843
- module.exports.YAMLException = require_exception();
5844
- module.exports.types = {
5845
- binary: require_binary(),
5846
- float: require_float(),
5847
- map: require_map(),
5848
- null: require_null(),
5849
- pairs: require_pairs(),
5850
- set: require_set(),
5851
- timestamp: require_timestamp(),
5852
- bool: require_bool(),
5853
- int: require_int(),
5854
- merge: require_merge(),
5855
- omap: require_omap(),
5856
- seq: require_seq(),
5857
- str: require_str()
5858
- };
5859
- module.exports.safeLoad = renamed("safeLoad", "load");
5860
- module.exports.safeLoadAll = renamed("safeLoadAll", "loadAll");
5861
- module.exports.safeDump = renamed("safeDump", "dump");
5862
- })))(), 1);
5863
- var { Type, Schema, FAILSAFE_SCHEMA, JSON_SCHEMA, CORE_SCHEMA, DEFAULT_SCHEMA, load, loadAll, dump, YAMLException, types, safeLoad, safeLoadAll, safeDump } = import_js_yaml.default;
5864
- var index_vite_proxy_tmp_default = import_js_yaml.default;
5865
-
5866
- //#endregion
5867
- //#region ../graph-tools/dist/index.mjs
5868
- /**
5869
- * Convert a resolved {@link GraphNode} back into a {@link NodeConfig}.
5870
- *
5871
- * Faithful and complete: round-tripping through `createGraphNode` yields a
5872
- * deep-equal node. Optional fields are only included when present; ports are
5873
- * deep-copied so the config does not share port objects with the source node.
5874
- */
5875
- function toNodeConfig(node) {
5876
- const config = { id: node.id };
5877
- if (node.parentId != null) config.parentId = node.parentId;
5878
- if (node.initialNodeId != null) config.initialNodeId = node.initialNodeId;
5879
- if (node.label != null) config.label = node.label;
5880
- if (node.data != null) config.data = node.data;
5881
- if (node.ports !== void 0) config.ports = node.ports.map((p) => ({ ...p }));
5882
- if (node.x !== void 0) config.x = node.x;
5883
- if (node.y !== void 0) config.y = node.y;
5884
- if (node.width !== void 0) config.width = node.width;
5885
- if (node.height !== void 0) config.height = node.height;
5886
- if (node.shape !== void 0) config.shape = node.shape;
5887
- if (node.color !== void 0) config.color = node.color;
5888
- if (node.style !== void 0) config.style = node.style;
5889
- return config;
5890
- }
5891
- /**
5892
- * Convert a resolved {@link GraphEdge} back into an {@link EdgeConfig}.
5893
- *
5894
- * Faithful and complete: round-tripping through `createGraphEdge` yields a
5895
- * deep-equal edge. Optional fields are only included when present.
5896
- */
5897
- function toEdgeConfig(edge) {
5898
- const config = {
5899
- id: edge.id,
5900
- sourceId: edge.sourceId,
5901
- targetId: edge.targetId
5902
- };
5903
- if (edge.label != null) config.label = edge.label;
5904
- if (edge.data != null) config.data = edge.data;
5905
- if (edge.weight !== void 0) config.weight = edge.weight;
5906
- if (edge.mode !== void 0) config.mode = edge.mode;
5907
- if (edge.sourcePort !== void 0) config.sourcePort = edge.sourcePort;
5908
- if (edge.targetPort !== void 0) config.targetPort = edge.targetPort;
5909
- if (edge.points !== void 0) config.points = edge.points.map((p) => ({ ...p }));
5910
- if (edge.routing !== void 0) config.routing = edge.routing;
5911
- if (edge.x !== void 0) config.x = edge.x;
5912
- if (edge.y !== void 0) config.y = edge.y;
5913
- if (edge.width !== void 0) config.width = edge.width;
5914
- if (edge.height !== void 0) config.height = edge.height;
5915
- if (edge.color !== void 0) config.color = edge.color;
5916
- if (edge.style !== void 0) config.style = edge.style;
5917
- return config;
5918
- }
5919
- const LAYOUT_KEYS$1 = {
5920
- node: [
5921
- "x",
5922
- "y",
5923
- "width",
5924
- "height",
5925
- "style",
5926
- "color",
5927
- "shape"
5928
- ],
5929
- edge: [
5930
- "x",
5931
- "y",
5932
- "width",
5933
- "height",
5934
- "points",
5935
- "routing",
5936
- "style",
5937
- "color"
5938
- ]
5939
- };
5940
- new Set(LAYOUT_KEYS$1.node), new Set(LAYOUT_KEYS$1.edge);
5941
- /** Shallow-compare two values, returning true if they differ. */
5942
- function differs(a, b) {
5943
- if (a === b) return false;
5944
- if (a == null || b == null) return a !== b;
5945
- if (typeof a === "object" && typeof b === "object") return JSON.stringify(a) !== JSON.stringify(b);
5946
- return true;
5947
- }
5948
- const NODE_COMPARE_KEYS = [
5949
- "parentId",
5950
- "initialNodeId",
5951
- "label",
5952
- "data",
5953
- "ports",
5954
- "x",
5955
- "y",
5956
- "width",
5957
- "height",
5958
- "shape",
5959
- "color",
5960
- "style"
5961
- ];
5962
- const EDGE_COMPARE_KEYS = [
5963
- "sourceId",
5964
- "targetId",
5965
- "label",
5966
- "data",
5967
- "weight",
5968
- "mode",
5969
- "sourcePort",
5970
- "targetPort",
5971
- "points",
5972
- "routing",
5973
- "x",
5974
- "y",
5975
- "width",
5976
- "height",
5977
- "color",
5978
- "style"
5979
- ];
5980
- /**
5981
- * Compute a structured diff from graph `a` to graph `b` by matching IDs.
5982
- *
5983
- * @example
5984
- * ```ts
5985
- * import { createGraph, getDiff } from '@statelyai/graph';
5986
- *
5987
- * const a = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
5988
- * const b = createGraph({ nodes: [{ id: 'n1', label: 'hello' }, { id: 'n2' }], edges: [] });
5989
- *
5990
- * const diff = getDiff(a, b);
5991
- * // diff.nodes.added → [{ id: 'n2' }]
5992
- * // diff.nodes.updated → [{ id: 'n1', old: { label: '' }, new: { label: 'hello' } }]
5993
- * ```
5994
- */
5995
- function getDiff(a, b) {
5996
- const aNodeMap = new Map(a.nodes.map((n) => [n.id, n]));
5997
- const bNodeMap = new Map(b.nodes.map((n) => [n.id, n]));
5998
- const aEdgeMap = new Map(a.edges.map((e) => [e.id, e]));
5999
- const bEdgeMap = new Map(b.edges.map((e) => [e.id, e]));
6000
- const diff = {
6001
- nodes: {
6002
- added: [],
6003
- removed: [],
6004
- updated: []
6005
- },
6006
- edges: {
6007
- added: [],
6008
- removed: [],
6009
- updated: []
6100
+ function foldString(string, width) {
6101
+ const lineRe = /(\n+)([^\n]*)/g;
6102
+ let result = function() {
6103
+ let nextLF = string.indexOf("\n");
6104
+ nextLF = nextLF !== -1 ? nextLF : string.length;
6105
+ lineRe.lastIndex = nextLF;
6106
+ return foldLine(string.slice(0, nextLF), width);
6107
+ }();
6108
+ let prevMoreIndented = string[0] === "\n" || string[0] === " ";
6109
+ let moreIndented;
6110
+ let match;
6111
+ while (match = lineRe.exec(string)) {
6112
+ const prefix = match[1];
6113
+ const line = match[2];
6114
+ moreIndented = line[0] === " ";
6115
+ result += prefix + (!prevMoreIndented && !moreIndented && line !== "" ? "\n" : "") + foldLine(line, width);
6116
+ prevMoreIndented = moreIndented;
6010
6117
  }
6011
- };
6012
- for (const [id, nodeB] of bNodeMap) {
6013
- const nodeA = aNodeMap.get(id);
6014
- if (!nodeA) diff.nodes.added.push(toNodeConfig(nodeB));
6015
- else {
6016
- const oldPartial = {};
6017
- const newPartial = {};
6018
- for (const key of NODE_COMPARE_KEYS) {
6019
- const oldValue = nodeA[key] ?? null;
6020
- const newValue = nodeB[key] ?? null;
6021
- if (differs(oldValue, newValue)) {
6022
- oldPartial[key] = oldValue;
6023
- newPartial[key] = newValue;
6024
- }
6118
+ return result;
6119
+ }
6120
+ function foldLine(line, width) {
6121
+ if (line === "" || line[0] === " ") return line;
6122
+ const breakRe = / [^ ]/g;
6123
+ let match;
6124
+ let start = 0;
6125
+ let end;
6126
+ let curr = 0;
6127
+ let next = 0;
6128
+ let result = "";
6129
+ while (match = breakRe.exec(line)) {
6130
+ next = match.index;
6131
+ if (next - start > width) {
6132
+ end = curr > start ? curr : next;
6133
+ result += "\n" + line.slice(start, end);
6134
+ start = end + 1;
6025
6135
  }
6026
- if (Object.keys(oldPartial).length > 0) diff.nodes.updated.push({
6027
- id,
6028
- old: oldPartial,
6029
- new: newPartial
6030
- });
6136
+ curr = next;
6031
6137
  }
6138
+ result += "\n";
6139
+ if (line.length - start > width && curr > start) result += line.slice(start, curr) + "\n" + line.slice(curr + 1);
6140
+ else result += line.slice(start);
6141
+ return result.slice(1);
6032
6142
  }
6033
- for (const [id, nodeA] of aNodeMap) if (!bNodeMap.has(id)) diff.nodes.removed.push(toNodeConfig(nodeA));
6034
- for (const [id, edgeB] of bEdgeMap) {
6035
- const edgeA = aEdgeMap.get(id);
6036
- if (!edgeA) diff.edges.added.push(toEdgeConfig(edgeB));
6037
- else {
6038
- const oldPartial = {};
6039
- const newPartial = {};
6040
- for (const key of EDGE_COMPARE_KEYS) {
6041
- const oldValue = edgeA[key] ?? null;
6042
- const newValue = edgeB[key] ?? null;
6043
- if (differs(oldValue, newValue)) {
6044
- oldPartial[key] = oldValue;
6045
- newPartial[key] = newValue;
6143
+ function escapeString(string) {
6144
+ let result = "";
6145
+ let char = 0;
6146
+ for (let i = 0; i < string.length; char >= 65536 ? i += 2 : i++) {
6147
+ char = codePointAt(string, i);
6148
+ const escapeSeq = ESCAPE_SEQUENCES[char];
6149
+ if (!escapeSeq && isPrintable(char)) {
6150
+ result += string[i];
6151
+ if (char >= 65536) result += string[i + 1];
6152
+ } else result += escapeSeq || encodeHex(char);
6153
+ }
6154
+ return result;
6155
+ }
6156
+ function writeFlowSequence(state, level, object) {
6157
+ let _result = "";
6158
+ const _tag = state.tag;
6159
+ for (let index = 0, length = object.length; index < length; index += 1) {
6160
+ let value = object[index];
6161
+ if (state.replacer) value = state.replacer.call(object, String(index), value);
6162
+ if (writeNode(state, level, value, false, false) || typeof value === "undefined" && writeNode(state, level, null, false, false)) {
6163
+ if (_result !== "") _result += "," + (!state.condenseFlow ? " " : "");
6164
+ _result += state.dump;
6165
+ }
6166
+ }
6167
+ state.tag = _tag;
6168
+ state.dump = "[" + _result + "]";
6169
+ }
6170
+ function writeBlockSequence(state, level, object, compact) {
6171
+ let _result = "";
6172
+ const _tag = state.tag;
6173
+ for (let index = 0, length = object.length; index < length; index += 1) {
6174
+ let value = object[index];
6175
+ if (state.replacer) value = state.replacer.call(object, String(index), value);
6176
+ if (writeNode(state, level + 1, value, true, true, false, true) || typeof value === "undefined" && writeNode(state, level + 1, null, true, true, false, true)) {
6177
+ if (!compact || _result !== "") _result += generateNextLine(state, level);
6178
+ if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) _result += "-";
6179
+ else _result += "- ";
6180
+ _result += state.dump;
6181
+ }
6182
+ }
6183
+ state.tag = _tag;
6184
+ state.dump = _result || "[]";
6185
+ }
6186
+ function writeFlowMapping(state, level, object) {
6187
+ let _result = "";
6188
+ const _tag = state.tag;
6189
+ const objectKeyList = Object.keys(object);
6190
+ for (let index = 0, length = objectKeyList.length; index < length; index += 1) {
6191
+ let pairBuffer = "";
6192
+ if (_result !== "") pairBuffer += ", ";
6193
+ if (state.condenseFlow) pairBuffer += "\"";
6194
+ const objectKey = objectKeyList[index];
6195
+ let objectValue = object[objectKey];
6196
+ if (state.replacer) objectValue = state.replacer.call(object, objectKey, objectValue);
6197
+ if (!writeNode(state, level, objectKey, false, false)) continue;
6198
+ if (state.dump.length > 1024) pairBuffer += "? ";
6199
+ pairBuffer += state.dump + (state.condenseFlow ? "\"" : "") + ":" + (state.condenseFlow ? "" : " ");
6200
+ if (!writeNode(state, level, objectValue, false, false)) continue;
6201
+ pairBuffer += state.dump;
6202
+ _result += pairBuffer;
6203
+ }
6204
+ state.tag = _tag;
6205
+ state.dump = "{" + _result + "}";
6206
+ }
6207
+ function writeBlockMapping(state, level, object, compact) {
6208
+ let _result = "";
6209
+ const _tag = state.tag;
6210
+ const objectKeyList = Object.keys(object);
6211
+ if (state.sortKeys === true) objectKeyList.sort();
6212
+ else if (typeof state.sortKeys === "function") objectKeyList.sort(state.sortKeys);
6213
+ else if (state.sortKeys) throw new YAMLException("sortKeys must be a boolean or a function");
6214
+ for (let index = 0, length = objectKeyList.length; index < length; index += 1) {
6215
+ let pairBuffer = "";
6216
+ if (!compact || _result !== "") pairBuffer += generateNextLine(state, level);
6217
+ const objectKey = objectKeyList[index];
6218
+ let objectValue = object[objectKey];
6219
+ if (state.replacer) objectValue = state.replacer.call(object, objectKey, objectValue);
6220
+ if (!writeNode(state, level + 1, objectKey, true, true, true)) continue;
6221
+ const explicitPair = state.tag !== null && state.tag !== "?" || state.dump && state.dump.length > 1024;
6222
+ if (explicitPair) if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) pairBuffer += "?";
6223
+ else pairBuffer += "? ";
6224
+ pairBuffer += state.dump;
6225
+ if (explicitPair) pairBuffer += generateNextLine(state, level);
6226
+ if (!writeNode(state, level + 1, objectValue, true, explicitPair)) continue;
6227
+ if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) pairBuffer += ":";
6228
+ else pairBuffer += ": ";
6229
+ pairBuffer += state.dump;
6230
+ _result += pairBuffer;
6231
+ }
6232
+ state.tag = _tag;
6233
+ state.dump = _result || "{}";
6234
+ }
6235
+ function detectType(state, object, explicit) {
6236
+ const typeList = explicit ? state.explicitTypes : state.implicitTypes;
6237
+ for (let index = 0, length = typeList.length; index < length; index += 1) {
6238
+ const type = typeList[index];
6239
+ if ((type.instanceOf || type.predicate) && (!type.instanceOf || typeof object === "object" && object instanceof type.instanceOf) && (!type.predicate || type.predicate(object))) {
6240
+ if (explicit) if (type.multi && type.representName) state.tag = type.representName(object);
6241
+ else state.tag = type.tag;
6242
+ else state.tag = "?";
6243
+ if (type.represent) {
6244
+ const style = state.styleMap[type.tag] || type.defaultStyle;
6245
+ let _result;
6246
+ if (_toString.call(type.represent) === "[object Function]") _result = type.represent(object, style);
6247
+ else if (_hasOwnProperty.call(type.represent, style)) _result = type.represent[style](object, style);
6248
+ else throw new YAMLException("!<" + type.tag + "> tag resolver accepts not \"" + style + "\" style");
6249
+ state.dump = _result;
6046
6250
  }
6251
+ return true;
6047
6252
  }
6048
- if (Object.keys(oldPartial).length > 0) diff.edges.updated.push({
6049
- id,
6050
- old: oldPartial,
6051
- new: newPartial
6052
- });
6053
6253
  }
6254
+ return false;
6054
6255
  }
6055
- for (const [id, edgeA] of aEdgeMap) if (!bEdgeMap.has(id)) diff.edges.removed.push(toEdgeConfig(edgeA));
6056
- return diff;
6057
- }
6058
- /**
6059
- * Check if a diff has zero changes.
6060
- *
6061
- * @example
6062
- * ```ts
6063
- * import { createGraph, getDiff, isEmptyDiff } from '@statelyai/graph';
6064
- *
6065
- * const g = createGraph({ nodes: [{ id: 'n1' }], edges: [] });
6066
- * const diff = getDiff(g, g);
6067
- * isEmptyDiff(diff); // true
6068
- * ```
6069
- */
6070
- function isEmptyDiff$1(diff) {
6071
- return diff.nodes.added.length === 0 && diff.nodes.removed.length === 0 && diff.nodes.updated.length === 0 && diff.edges.added.length === 0 && diff.edges.removed.length === 0 && diff.edges.updated.length === 0;
6072
- }
6073
- function summarizeGraphDiff(diff) {
6074
- return {
6075
- hasChanges: !isEmptyDiff$1(diff),
6076
- nodeChanges: diff.nodes.added.length + diff.nodes.removed.length + diff.nodes.updated.length,
6077
- edgeChanges: diff.edges.added.length + diff.edges.removed.length + diff.edges.updated.length
6078
- };
6079
- }
6080
- function nodeDepth$1(graph, node) {
6081
- let depth = 0;
6082
- let parentId = node.parentId;
6083
- while (parentId) {
6084
- depth++;
6085
- parentId = graph.nodes.find((candidate) => candidate.id === parentId)?.parentId;
6256
+ function writeNode(state, level, object, block, compact, iskey, isblockseq) {
6257
+ state.tag = null;
6258
+ state.dump = object;
6259
+ if (!detectType(state, object, false)) detectType(state, object, true);
6260
+ const type = _toString.call(state.dump);
6261
+ const inblock = block;
6262
+ if (block) block = state.flowLevel < 0 || state.flowLevel > level;
6263
+ const objectOrArray = type === "[object Object]" || type === "[object Array]";
6264
+ let duplicateIndex;
6265
+ let duplicate;
6266
+ if (objectOrArray) {
6267
+ duplicateIndex = state.duplicates.indexOf(object);
6268
+ duplicate = duplicateIndex !== -1;
6269
+ }
6270
+ if (state.tag !== null && state.tag !== "?" || duplicate || state.indent !== 2 && level > 0) compact = false;
6271
+ if (duplicate && state.usedDuplicates[duplicateIndex]) state.dump = "*ref_" + duplicateIndex;
6272
+ else {
6273
+ if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) state.usedDuplicates[duplicateIndex] = true;
6274
+ if (type === "[object Object]") if (block && Object.keys(state.dump).length !== 0) {
6275
+ writeBlockMapping(state, level, state.dump, compact);
6276
+ if (duplicate) state.dump = "&ref_" + duplicateIndex + state.dump;
6277
+ } else {
6278
+ writeFlowMapping(state, level, state.dump);
6279
+ if (duplicate) state.dump = "&ref_" + duplicateIndex + " " + state.dump;
6280
+ }
6281
+ else if (type === "[object Array]") if (block && state.dump.length !== 0) {
6282
+ if (state.noArrayIndent && !isblockseq && level > 0) writeBlockSequence(state, level - 1, state.dump, compact);
6283
+ else writeBlockSequence(state, level, state.dump, compact);
6284
+ if (duplicate) state.dump = "&ref_" + duplicateIndex + state.dump;
6285
+ } else {
6286
+ writeFlowSequence(state, level, state.dump);
6287
+ if (duplicate) state.dump = "&ref_" + duplicateIndex + " " + state.dump;
6288
+ }
6289
+ else if (type === "[object String]") {
6290
+ if (state.tag !== "?") writeScalar(state, state.dump, level, iskey, inblock);
6291
+ } else if (type === "[object Undefined]") return false;
6292
+ else {
6293
+ if (state.skipInvalid) return false;
6294
+ throw new YAMLException("unacceptable kind of an object to dump " + type);
6295
+ }
6296
+ if (state.tag !== null && state.tag !== "?") {
6297
+ let tagStr = encodeURI(state.tag[0] === "!" ? state.tag.slice(1) : state.tag).replace(/!/g, "%21");
6298
+ if (state.tag[0] === "!") tagStr = "!" + tagStr;
6299
+ else if (tagStr.slice(0, 18) === "tag:yaml.org,2002:") tagStr = "!!" + tagStr.slice(18);
6300
+ else tagStr = "!<" + tagStr + ">";
6301
+ state.dump = tagStr + " " + state.dump;
6302
+ }
6303
+ }
6304
+ return true;
6086
6305
  }
6087
- return depth;
6088
- }
6089
- function nodeKey(node) {
6090
- return node.data?.key || node.id;
6091
- }
6092
- function edgeSignature(edge) {
6093
- return [
6094
- edge.sourceId,
6095
- edge.data?.eventType,
6096
- edge.targetId,
6097
- edge.data?.guard?.type ?? ""
6098
- ].join("->");
6099
- }
6100
- function getStableNodeId(node, parentStableId, siblingIndex, preferredIds) {
6101
- const preferredId = preferredIds?.get(node.id);
6102
- if (preferredId !== void 0) return preferredId;
6103
- if (node.parentId === null) return "root";
6104
- const key = nodeKey(node);
6105
- const suffix = siblingIndex === 0 ? key : `${key}_${siblingIndex + 1}`;
6106
- return parentStableId ? `${parentStableId}.${suffix}` : suffix;
6107
- }
6108
- function getStableEdgeId(edge, siblingIndex, preferredIds) {
6109
- const preferredId = preferredIds?.get(edge.id);
6110
- if (preferredId !== void 0) return preferredId;
6111
- const suffix = siblingIndex === 0 ? "" : `.${siblingIndex + 1}`;
6112
- return edgeSignature(edge).concat(suffix);
6113
- }
6114
- function removePresentationFields(entity, kind) {
6115
- const mutableEntity = entity;
6116
- for (const key of LAYOUT_KEYS$1[kind]) delete mutableEntity[key];
6117
- const data = mutableEntity.data;
6118
- if (data && typeof data === "object" && !Array.isArray(data)) delete data.color;
6119
- }
6120
- /**
6121
- * Rewrites entity ids to structural ("semantic") ids so two graphs that model
6122
- * the same machine compare equal regardless of how their ids were minted.
6123
- *
6124
- * Invariant: node and edge array order is preserved exactly. Callers
6125
- * (`alignCompareIds` in the editor's /v1/diff route) rely on
6126
- * `normalized.nodes[i]` describing `graph.nodes[i]` to translate a semantic id
6127
- * back to the caller's original id. Never sort, filter, or reorder the arrays
6128
- * on the returned graph; sorting for traversal must be done on a copy, as the
6129
- * depth ordering below does.
6130
- *
6131
- * Presentation-only fields defined by `LAYOUT_KEYS`, plus entity data colors,
6132
- * are removed. When preferred ids are supplied, matching raw ids retain the
6133
- * base graph's semantic identity so a stable-id rename is reported as an
6134
- * update.
6135
- *
6136
- * Entity `data` is treated as optional throughout: sparse graphs (a node with
6137
- * `data: {}`, an edge with `data: null`) normalize instead of throwing.
6138
- */
6139
- function normalizeGraphForSemanticDiff(graph, preferredIds) {
6140
- const normalized = structuredClone(graph);
6141
- const nodeIdMap = /* @__PURE__ */ new Map();
6142
- const siblingKeys = /* @__PURE__ */ new Map();
6143
- const reservedNodeIds = new Set(preferredIds?.nodes.values());
6144
- const claimedNodeIds = /* @__PURE__ */ new Set();
6145
- const nodesByDepth = [...normalized.nodes].sort((a, b) => nodeDepth$1(normalized, a) - nodeDepth$1(normalized, b));
6146
- for (const node of nodesByDepth) {
6147
- const parentStableId = node.parentId ? nodeIdMap.get(node.parentId) ?? node.parentId : null;
6148
- const key = `${parentStableId ?? ""}:${nodeKey(node)}`;
6149
- const siblingIndex = siblingKeys.get(key) ?? 0;
6150
- siblingKeys.set(key, siblingIndex + 1);
6151
- const proposedId = getStableNodeId(node, parentStableId, siblingIndex, preferredIds?.nodes);
6152
- let stableId = proposedId;
6153
- let collisionIndex = 2;
6154
- while (!preferredIds?.nodes.has(node.id) && (reservedNodeIds.has(stableId) || claimedNodeIds.has(stableId))) stableId = `${proposedId}:unmatched:${collisionIndex++}`;
6155
- claimedNodeIds.add(stableId);
6156
- nodeIdMap.set(node.id, stableId);
6306
+ function getDuplicateReferences(object, state) {
6307
+ const objects = [];
6308
+ const duplicatesIndexes = [];
6309
+ inspectNode(object, objects, duplicatesIndexes);
6310
+ const length = duplicatesIndexes.length;
6311
+ for (let index = 0; index < length; index += 1) state.duplicates.push(objects[duplicatesIndexes[index]]);
6312
+ state.usedDuplicates = new Array(length);
6157
6313
  }
6158
- for (const node of normalized.nodes) {
6159
- removePresentationFields(node, "node");
6160
- node.id = nodeIdMap.get(node.id) ?? node.id;
6161
- if (node.parentId) node.parentId = nodeIdMap.get(node.parentId) ?? node.parentId;
6162
- if (node.initialNodeId) node.initialNodeId = nodeIdMap.get(node.initialNodeId) ?? node.initialNodeId;
6163
- if (node.data?.initialId) node.data.initialId = nodeIdMap.get(node.data.initialId) ?? node.data.initialId;
6314
+ function inspectNode(object, objects, duplicatesIndexes) {
6315
+ if (object !== null && typeof object === "object") {
6316
+ const index = objects.indexOf(object);
6317
+ if (index !== -1) {
6318
+ if (duplicatesIndexes.indexOf(index) === -1) duplicatesIndexes.push(index);
6319
+ } else {
6320
+ objects.push(object);
6321
+ if (Array.isArray(object)) for (let i = 0, length = object.length; i < length; i += 1) inspectNode(object[i], objects, duplicatesIndexes);
6322
+ else {
6323
+ const objectKeyList = Object.keys(object);
6324
+ for (let i = 0, length = objectKeyList.length; i < length; i += 1) inspectNode(object[objectKeyList[i]], objects, duplicatesIndexes);
6325
+ }
6326
+ }
6327
+ }
6164
6328
  }
6165
- const edgeSiblingKeys = /* @__PURE__ */ new Map();
6166
- const reservedEdgeIds = new Set(preferredIds?.edges.values());
6167
- const claimedEdgeIds = /* @__PURE__ */ new Set();
6168
- for (const edge of normalized.edges) {
6169
- removePresentationFields(edge, "edge");
6170
- edge.sourceId = nodeIdMap.get(edge.sourceId) ?? edge.sourceId;
6171
- edge.targetId = nodeIdMap.get(edge.targetId) ?? edge.targetId;
6172
- const key = edgeSignature(edge);
6173
- const siblingIndex = edgeSiblingKeys.get(key) ?? 0;
6174
- edgeSiblingKeys.set(key, siblingIndex + 1);
6175
- const proposedId = getStableEdgeId(edge, siblingIndex, preferredIds?.edges);
6176
- let stableId = proposedId;
6177
- let collisionIndex = 2;
6178
- while (!preferredIds?.edges.has(edge.id) && (reservedEdgeIds.has(stableId) || claimedEdgeIds.has(stableId))) stableId = `${proposedId}:unmatched:${collisionIndex++}`;
6179
- claimedEdgeIds.add(stableId);
6180
- edge.id = stableId;
6329
+ function dump(input, options) {
6330
+ options = options || {};
6331
+ const state = new State(options);
6332
+ if (!state.noRefs) getDuplicateReferences(input, state);
6333
+ let value = input;
6334
+ if (state.replacer) value = state.replacer.call({ "": value }, "", value);
6335
+ if (writeNode(state, 0, value, true, true)) return state.dump + "\n";
6336
+ return "";
6181
6337
  }
6182
- if (normalized.initialNodeId) normalized.initialNodeId = nodeIdMap.get(normalized.initialNodeId) ?? normalized.initialNodeId;
6183
- return normalized;
6184
- }
6185
- function diffGraphsSemantically(baseGraph, compareGraph) {
6186
- const base = normalizeGraphForSemanticDiff(baseGraph);
6187
- const compareNodeIds = new Set(compareGraph.nodes.map((node) => node.id));
6188
- const compareEdgeIds = new Set(compareGraph.edges.map((edge) => edge.id));
6189
- const compare = normalizeGraphForSemanticDiff(compareGraph, {
6190
- nodes: new Map(baseGraph.nodes.map((node, index) => [node.id, base.nodes[index].id]).filter(([id]) => compareNodeIds.has(id))),
6191
- edges: new Map(baseGraph.edges.map((edge, index) => [edge.id, base.edges[index].id]).filter(([id]) => compareEdgeIds.has(id)))
6192
- });
6193
- const diff = getDiff(base, compare);
6194
- return {
6195
- base,
6196
- compare,
6197
- diff,
6198
- summary: summarizeGraphDiff(diff)
6338
+ module.exports.dump = dump;
6339
+ }));
6340
+ var import_js_yaml = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
6341
+ var loader = require_loader();
6342
+ var dumper = require_dumper();
6343
+ function renamed(from, to) {
6344
+ return function() {
6345
+ throw new Error("Function yaml." + from + " is removed in js-yaml 4. Use yaml." + to + " instead, which is now safe by default.");
6346
+ };
6347
+ }
6348
+ module.exports.Type = require_type();
6349
+ module.exports.Schema = require_schema();
6350
+ module.exports.FAILSAFE_SCHEMA = require_failsafe();
6351
+ module.exports.JSON_SCHEMA = require_json();
6352
+ module.exports.CORE_SCHEMA = require_core();
6353
+ module.exports.DEFAULT_SCHEMA = require_default();
6354
+ module.exports.load = loader.load;
6355
+ module.exports.loadAll = loader.loadAll;
6356
+ module.exports.dump = dumper.dump;
6357
+ module.exports.YAMLException = require_exception();
6358
+ module.exports.types = {
6359
+ binary: require_binary(),
6360
+ float: require_float(),
6361
+ map: require_map(),
6362
+ null: require_null(),
6363
+ pairs: require_pairs(),
6364
+ set: require_set(),
6365
+ timestamp: require_timestamp(),
6366
+ bool: require_bool(),
6367
+ int: require_int(),
6368
+ merge: require_merge(),
6369
+ omap: require_omap(),
6370
+ seq: require_seq(),
6371
+ str: require_str()
6199
6372
  };
6200
- }
6373
+ module.exports.safeLoad = renamed("safeLoad", "load");
6374
+ module.exports.safeLoadAll = renamed("safeLoadAll", "loadAll");
6375
+ module.exports.safeDump = renamed("safeDump", "dump");
6376
+ })))(), 1);
6377
+ var { Type, Schema, FAILSAFE_SCHEMA, JSON_SCHEMA, CORE_SCHEMA, DEFAULT_SCHEMA, load, loadAll, dump, YAMLException, types, safeLoad, safeLoadAll, safeDump } = import_js_yaml.default;
6378
+ var index_vite_proxy_tmp_default = import_js_yaml.default;
6379
+
6380
+ //#endregion
6381
+ //#region ../graph-tools/dist/index.mjs
6201
6382
  /** A patch changes machine semantics rather than presentation metadata. */
6202
6383
  function isStructuralPatch(patch) {
6203
6384
  if (patch.op === "createImplementation" && !patch.implementation.code) return false;
@@ -13344,7 +13525,7 @@ function modify(text, path, value, options) {
13344
13525
  }
13345
13526
 
13346
13527
  //#endregion
13347
- //#region ../editor-sync/dist/adapters-Dt77BFUa.mjs
13528
+ //#region ../editor-sync/dist/adapters-9XXzVfbF.mjs
13348
13529
  const sourceFileUris = /* @__PURE__ */ new WeakMap();
13349
13530
  function collectXStateSourceLocations(sourceText, document, options = {}) {
13350
13531
  const sourceFile = ts$1.createSourceFile(document.fileName, sourceText, ts$1.ScriptTarget.Latest, true, getScriptKind$2$1(document.fileName));
@@ -13359,10 +13540,13 @@ function collectXStateSourceLocations(sourceText, document, options = {}) {
13359
13540
  const states = [];
13360
13541
  const statesObjectLocations = [];
13361
13542
  collectStateLocations(root, [], states, statesObjectLocations, bindings, staticValues, root);
13362
- const packageProfile = detectXStatePackageProfile(options.resolver?.resolvePackageJson?.({
13543
+ const packageProfile = detectXStatePackageProfile(machineFactoryPackage(sourceFile, {
13363
13544
  fileName: document.fileName,
13364
13545
  uri
13365
- }, "xstate"));
13546
+ }, options.machineIndex, options.resolver) === "xstate" ? options.resolver?.resolvePackageJson?.({
13547
+ fileName: document.fileName,
13548
+ uri
13549
+ }, "xstate") : void 0);
13366
13550
  const rootProfile = detectXStateSourceProfile(sourceText);
13367
13551
  const referencedStateSymbols = new Set([...states, ...statesObjectLocations].map((state) => state.symbol).filter((symbol) => typeof symbol === "string"));
13368
13552
  const resolvedTransitionFunctions = collectResolvedTransitionFunctions(root, bindings);
@@ -13390,6 +13574,104 @@ function collectXStateSourceLocations(sourceText, document, options = {}) {
13390
13574
  }])
13391
13575
  };
13392
13576
  }
13577
+ /** Only the package providing this machine's factory can establish its version. */
13578
+ function machineFactoryPackage(sourceFile, document, machineIndex = 0, resolver) {
13579
+ const modules = /* @__PURE__ */ new Map();
13580
+ const rootModule = {
13581
+ file: sourceFile,
13582
+ document
13583
+ };
13584
+ modules.set(document.uri, rootModule);
13585
+ const visited = /* @__PURE__ */ new Set();
13586
+ function imported(module, specifier, name) {
13587
+ if (!specifier.startsWith(".")) return specifier;
13588
+ const snapshot = resolver?.resolveImport(module.document, specifier);
13589
+ if (!snapshot || !name) return void 0;
13590
+ let target = modules.get(snapshot.uri);
13591
+ if (!target) {
13592
+ target = {
13593
+ file: ts$1.createSourceFile(snapshot.fileName, snapshot.text, ts$1.ScriptTarget.Latest, true, getScriptKind$2$1(snapshot.fileName)),
13594
+ document: snapshot
13595
+ };
13596
+ modules.set(snapshot.uri, target);
13597
+ }
13598
+ return exported(target, name);
13599
+ }
13600
+ function exported(module, name) {
13601
+ const key = `${module.document.uri}\0export\0${name}`;
13602
+ if (visited.has(key)) return void 0;
13603
+ visited.add(key);
13604
+ try {
13605
+ for (const statement of module.file.statements) {
13606
+ if (!ts$1.isExportDeclaration(statement) || !statement.exportClause || !ts$1.isNamedExports(statement.exportClause)) continue;
13607
+ const element = statement.exportClause.elements.find((element) => element.name.text === name);
13608
+ if (!element) continue;
13609
+ const localName = element.propertyName?.text ?? element.name.text;
13610
+ return statement.moduleSpecifier && ts$1.isStringLiteral(statement.moduleSpecifier) ? imported(module, statement.moduleSpecifier.text, localName) : symbol(module, localName);
13611
+ }
13612
+ for (const statement of module.file.statements) if (ts$1.isVariableStatement(statement) && statement.modifiers?.some((modifier) => modifier.kind === ts$1.SyntaxKind.ExportKeyword)) {
13613
+ if (statement.declarationList.declarations.some((declaration) => ts$1.isIdentifier(declaration.name) && declaration.name.text === name)) return symbol(module, name);
13614
+ }
13615
+ for (const statement of module.file.statements) {
13616
+ if (!ts$1.isExportDeclaration(statement) || statement.exportClause || !statement.moduleSpecifier || !ts$1.isStringLiteral(statement.moduleSpecifier)) continue;
13617
+ const result = imported(module, statement.moduleSpecifier.text, name);
13618
+ if (result) return result;
13619
+ }
13620
+ return;
13621
+ } finally {
13622
+ visited.delete(key);
13623
+ }
13624
+ }
13625
+ function symbol(module, name, member) {
13626
+ const key = `${module.document.uri}\0symbol\0${name}\0${member ?? ""}`;
13627
+ if (visited.has(key)) return void 0;
13628
+ visited.add(key);
13629
+ try {
13630
+ for (const statement of module.file.statements) {
13631
+ if (ts$1.isImportDeclaration(statement) && ts$1.isStringLiteral(statement.moduleSpecifier)) {
13632
+ const bindings = statement.importClause?.namedBindings;
13633
+ if (bindings && ts$1.isNamedImports(bindings)) {
13634
+ const element = bindings.elements.find((element) => element.name.text === name);
13635
+ if (element) return imported(module, statement.moduleSpecifier.text, element.propertyName?.text ?? element.name.text);
13636
+ } else if (bindings && ts$1.isNamespaceImport(bindings) && bindings.name.text === name) return imported(module, statement.moduleSpecifier.text, member);
13637
+ }
13638
+ if (!ts$1.isVariableStatement(statement)) continue;
13639
+ for (const declaration of statement.declarationList.declarations) {
13640
+ if (!declaration.initializer) continue;
13641
+ if (ts$1.isIdentifier(declaration.name) && declaration.name.text === name) return resolve(module, declaration.initializer, member);
13642
+ if (ts$1.isObjectBindingPattern(declaration.name)) {
13643
+ const element = declaration.name.elements.find((element) => !element.dotDotDotToken && ts$1.isIdentifier(element.name) && element.name.text === name);
13644
+ if (element) return resolve(module, declaration.initializer, element.propertyName ? element.propertyName.getText(module.file).replace(/^['"]|['"]$/g, "") : name);
13645
+ }
13646
+ }
13647
+ }
13648
+ return;
13649
+ } finally {
13650
+ visited.delete(key);
13651
+ }
13652
+ }
13653
+ function resolve(module, node, member) {
13654
+ if (ts$1.isIdentifier(node)) return symbol(module, node.text, member);
13655
+ if (ts$1.isCallExpression(node)) {
13656
+ if (ts$1.isIdentifier(node.expression) && node.expression.text === "require" && node.arguments.length === 1 && ts$1.isStringLiteral(node.arguments[0])) return imported(module, node.arguments[0].text, member);
13657
+ return resolve(module, node.expression);
13658
+ }
13659
+ if (ts$1.isPropertyAccessExpression(node)) return resolve(module, node.expression, node.name.text);
13660
+ if (ts$1.isParenthesizedExpression(node) || ts$1.isAsExpression(node) || ts$1.isSatisfiesExpression(node) || ts$1.isNonNullExpression(node)) return resolve(module, node.expression, member);
13661
+ }
13662
+ let factory;
13663
+ let index = 0;
13664
+ const visit = (node) => {
13665
+ if (factory) return;
13666
+ if (ts$1.isCallExpression(node) && isCreateMachineExpression$1$1(node.expression)) {
13667
+ if (index++ === machineIndex) factory = node;
13668
+ return;
13669
+ }
13670
+ ts$1.forEachChild(node, visit);
13671
+ };
13672
+ visit(sourceFile);
13673
+ return factory ? resolve(rootModule, factory) : void 0;
13674
+ }
13393
13675
  function detectXStatePackageProfile(packageJson) {
13394
13676
  if (!packageJson) return void 0;
13395
13677
  let manifest;
@@ -14121,7 +14403,14 @@ function parseSourceToMachine(text, document, options = {}) {
14121
14403
  ].filter(removeOverlappingRanges).sort(compareSourceRangesDescending));
14122
14404
  if (sourceLocations.profile === "xstate-v6-alpha" || options.machineIndex !== void 0) {
14123
14405
  const importedTransitionSources = collectImportedXStateTransitionSources(text, document, options);
14124
- const parseText = importedTransitionSources.length ? `${hydratedText}\n${importedTransitionSources.join("\n")}` : hydratedText;
14406
+ const transitionDeclarations = ts$1.createSourceFile(document.fileName, importedTransitionSources.join("\n"), ts$1.ScriptTarget.Latest, true, ts$1.ScriptKind.TSX);
14407
+ const transitionSymbols = /* @__PURE__ */ new Set();
14408
+ for (const statement of transitionDeclarations.statements) if (ts$1.isFunctionDeclaration(statement) && statement.name) transitionSymbols.add(statement.name.text);
14409
+ else if (ts$1.isVariableStatement(statement)) {
14410
+ for (const declaration of statement.declarationList.declarations) if (ts$1.isIdentifier(declaration.name)) transitionSymbols.add(declaration.name.text);
14411
+ }
14412
+ const moduleText = applySourceRangeReplacements(hydratedText, collectHydratedImportReplacements(hydratedText, document, transitionSymbols).sort(compareSourceRangesDescending));
14413
+ const parseText = importedTransitionSources.length ? `${moduleText}\n${importedTransitionSources.join("\n")}` : moduleText;
14125
14414
  const selectedMachineIndex = options.machineIndex ?? 0;
14126
14415
  const config = extractXStateMachineConfigEntries(parseText, { profile: sourceLocations.profile }).find((entry) => entry.machineIndex === selectedMachineIndex)?.config;
14127
14416
  if (!config) throw new Error(`No machine at index ${selectedMachineIndex} was found in ${document.fileName}.`);
@@ -14139,17 +14428,38 @@ function parseSourceToMachine(text, document, options = {}) {
14139
14428
  setupImplementations[category] = Object.fromEntries(Object.entries(value).map(([name, body]) => [name, typeof body === "string" ? raw(body) : body]));
14140
14429
  delete machineConfig[category];
14141
14430
  }
14142
- if (Object.keys(setupImplementations).length) return `import { setup } from "xstate";
14143
-
14144
- export const machine = setup(${serializeJS(setupImplementations, 0)}).createMachine(${serializeJS(machineConfig, 0)});
14145
- `;
14146
- return `import { createMachine } from "xstate";
14147
-
14148
- export const machine = createMachine(${serializeJS(machineConfig, 0)});
14149
- `;
14431
+ const factory = Object.keys(setupImplementations).length ? "setup" : "createMachine";
14432
+ return selectMachineInModule(parseText, selectedMachineIndex, factory, factory === "setup" ? `setup(${serializeJS(setupImplementations, 0)}).createMachine(${serializeJS(machineConfig, 0)})` : `createMachine(${serializeJS(machineConfig, 0)})`);
14150
14433
  }
14151
14434
  return hydratedText;
14152
14435
  }
14436
+ function selectMachineInModule(source, machineIndex, factory, expression) {
14437
+ const file = ts$1.createSourceFile("machine.ts", source, ts$1.ScriptTarget.Latest, true, ts$1.ScriptKind.TSX);
14438
+ const replacements = [];
14439
+ let index = 0;
14440
+ let factoryAlias = "__stately_sync_factory";
14441
+ while (source.includes(factoryAlias)) factoryAlias += "_";
14442
+ const visit = (node) => {
14443
+ if (ts$1.isCallExpression(node) && isCreateMachineExpression$1$1(node.expression)) {
14444
+ if (index++ === machineIndex) replacements.push({
14445
+ start: node.getStart(file),
14446
+ end: node.getEnd(),
14447
+ text: `(() => { const ${factory} = ${factoryAlias}; return ${expression}; })()`
14448
+ });
14449
+ else replacements.push({
14450
+ start: node.expression.getStart(file),
14451
+ end: node.expression.getEnd(),
14452
+ text: `(${node.expression.getText(file)})`
14453
+ });
14454
+ return;
14455
+ }
14456
+ ts$1.forEachChild(node, visit);
14457
+ };
14458
+ visit(file);
14459
+ let result = source;
14460
+ for (const replacement of replacements.sort((a, b) => b.start - a.start)) result = result.slice(0, replacement.start) + replacement.text + result.slice(replacement.end);
14461
+ return `import { ${factory} as ${factoryAlias} } from 'xstate';\n${result}`;
14462
+ }
14153
14463
  function readHydratedStatesObject(uri, range, states, resolver) {
14154
14464
  if (!resolver) return null;
14155
14465
  const document = resolver.read(uri);
@@ -14188,11 +14498,13 @@ function collectHydratedImportReplacements(text, document, hydratedSymbols) {
14188
14498
  if (!statement.moduleSpecifier.text.startsWith(".")) continue;
14189
14499
  const namedBindings = statement.importClause?.namedBindings;
14190
14500
  if (!namedBindings || !ts$1.isNamedImports(namedBindings)) continue;
14191
- const importedNames = namedBindings.elements.map((element) => element.name.text);
14192
- if (importedNames.length === 0 || !importedNames.every((name) => hydratedSymbols.has(name))) continue;
14501
+ const remaining = namedBindings.elements.filter((element) => !hydratedSymbols.has(element.name.text));
14502
+ if (remaining.length === namedBindings.elements.length) continue;
14503
+ const clause = statement.importClause;
14504
+ const replacement = remaining.length || clause.name ? ts$1.createPrinter().printNode(ts$1.EmitHint.Unspecified, ts$1.factory.updateImportDeclaration(statement, statement.modifiers, ts$1.factory.updateImportClause(clause, clause.isTypeOnly, clause.name, remaining.length ? ts$1.factory.updateNamedImports(namedBindings, remaining) : void 0), statement.moduleSpecifier, statement.attributes), sourceFile) + "\n" : "";
14193
14505
  replacements.push({
14194
14506
  range: toSourceRange(sourceFile, statement, { includeTrailingNewline: true }),
14195
- newText: ""
14507
+ newText: replacement
14196
14508
  });
14197
14509
  }
14198
14510
  return replacements;
@@ -18434,7 +18746,7 @@ function diagnosticKey$1(diagnostic) {
18434
18746
  }
18435
18747
 
18436
18748
  //#endregion
18437
- //#region ../editor-sync/dist/localBackend-DH1qEsOz.mjs
18749
+ //#region ../editor-sync/dist/localBackend-CAt5onqr.mjs
18438
18750
  var LocalEditorSyncBackend = class {
18439
18751
  constructor(access) {
18440
18752
  this.access = access;
@@ -18882,7 +19194,7 @@ async function updateMachineDefinition(client, machineId, localGraph) {
18882
19194
  }
18883
19195
 
18884
19196
  //#endregion
18885
- //#region ../editor-sync/dist/presentationMetadata-YX6iRP4T.mjs
19197
+ //#region ../editor-sync/dist/presentationMetadata-CIXaHmqN.mjs
18886
19198
  function createStudioPresentationMetadataStore(client, machineId) {
18887
19199
  const load = async () => {
18888
19200
  return {
@@ -19248,6 +19560,54 @@ function isPresentationOverlay(value) {
19248
19560
  function clone(value) {
19249
19561
  return value === void 0 ? value : structuredClone(value);
19250
19562
  }
19563
+ /**
19564
+ * Apply only what an automatic layout computed to the last persisted graph:
19565
+ * the completed layout status of each newly laid-out region and the positions
19566
+ * of entities inside those regions. Colors, notes, assets, display choices and
19567
+ * manual moves the user has not saved stay as they were persisted.
19568
+ */
19569
+ function mergeAutomaticLayout(persisted, laidOut) {
19570
+ if (!isGraph(persisted) || !isGraph(laidOut)) return persisted;
19571
+ const result = clone(persisted);
19572
+ const laidOutNodes = new Map(laidOut.nodes.map((node) => [node.id, node]));
19573
+ const regions = /* @__PURE__ */ new Set();
19574
+ if (laidOut.layout?.status === "complete" && result.layout?.status !== "complete") {
19575
+ regions.add(null);
19576
+ result.layout = {
19577
+ ...result.layout,
19578
+ ...clone(laidOut.layout)
19579
+ };
19580
+ }
19581
+ for (const node of result.nodes) if (laidOutNodes.get(node.id)?.data?.layout?.status === "complete" && node.data?.layout?.status !== "complete") {
19582
+ regions.add(node.id);
19583
+ node.data = {
19584
+ ...node.data,
19585
+ layout: {
19586
+ ...node.data?.layout,
19587
+ status: "complete"
19588
+ }
19589
+ };
19590
+ }
19591
+ if (regions.size === 0) return result;
19592
+ const parentOf = new Map(result.nodes.map((node) => [node.id, node.parentId ?? null]));
19593
+ const inRegion = (nodeId) => typeof nodeId === "string" && parentOf.has(nodeId) && regions.has(parentOf.get(nodeId));
19594
+ const copyPosition = (target, source) => {
19595
+ if (!source) return;
19596
+ for (const field of [
19597
+ "position",
19598
+ "x",
19599
+ "y"
19600
+ ]) if (source[field] !== void 0) target[field] = clone(source[field]);
19601
+ };
19602
+ for (const node of result.nodes) if (inRegion(node.id)) copyPosition(node, laidOutNodes.get(node.id));
19603
+ const laidOutEdges = new Map(laidOut.edges.map((edge) => [edge.id, edge]));
19604
+ for (const edge of result.edges) if (inRegion(edge.sourceId) || inRegion(edge.targetId)) copyPosition(edge, laidOutEdges.get(edge.id));
19605
+ if (Array.isArray(result.annotations) && Array.isArray(laidOut.annotations)) {
19606
+ const laidOutAnnotations = new Map(laidOut.annotations.map((item) => [item.id, item]));
19607
+ for (const annotation of result.annotations) if (regions.has(annotation.parentId ?? null)) copyPosition(annotation, laidOutAnnotations.get(annotation.id));
19608
+ }
19609
+ return result;
19610
+ }
19251
19611
 
19252
19612
  //#endregion
19253
19613
  //#region ../../node_modules/.pnpm/@asteasolutions+zod-to-openapi@8.5.0_zod@4.4.3/node_modules/@asteasolutions/zod-to-openapi/dist/index.cjs
@@ -19681,7 +20041,7 @@ const editorSyncApplyResponseSchema = z$1.object({ replacements: z$1.array(edito
19681
20041
  const editorSyncAccessResponseSchema = z$1.object({ access: editorSyncAccessSchema });
19682
20042
 
19683
20043
  //#endregion
19684
- //#region ../editor-sync/dist/host-BX7mLyHj.mjs
20044
+ //#region ../editor-sync/dist/host-DCVLN7MS.mjs
19685
20045
  let diagnosticSequence = 0;
19686
20046
  function presentationsEqual(first, second) {
19687
20047
  return JSON.stringify(createPresentationSnapshot(first)) === JSON.stringify(createPresentationSnapshot(second));
@@ -19858,6 +20218,7 @@ var EditorHostSession = class {
19858
20218
  this.currentGraph = message.graph;
19859
20219
  if (message.source === "external") this.lastPersistedGraph = message.sourceBaselineGraph ?? message.graph;
19860
20220
  this.currentSourceLocations = mergeSourceLocations(this.currentSourceLocations, message.sourceLocations);
20221
+ if (message.source === "layout") await this.persistAutomaticLayout(message.graph, message.serialized);
19861
20222
  break;
19862
20223
  case "@statelyai.save":
19863
20224
  try {
@@ -20088,6 +20449,27 @@ var EditorHostSession = class {
20088
20449
  return graph;
20089
20450
  }
20090
20451
  }
20452
+ /**
20453
+ * Store automatic layout positions as presentation metadata so the next
20454
+ * session skips automatic layout. Unsaved colors, notes or moves are never
20455
+ * committed this way: such a graph waits for the user's save. Source files are never written, and a graph with unsaved structural edits
20456
+ * waits for the user's save instead.
20457
+ */
20458
+ async persistAutomaticLayout(graph, serialized) {
20459
+ const persisted = this.lastPersistedGraph;
20460
+ if (!this.options.presentation || this.access?.readOnly || persisted === void 0) return;
20461
+ try {
20462
+ const change = graphChangeToPatchesResult(persisted, graph);
20463
+ if (change.unsupportedChanges.length > 0 || change.patches.some(isStructuralPatch)) return;
20464
+ } catch {
20465
+ return;
20466
+ }
20467
+ if (!presentationsEqual(mergeAutomaticLayout(persisted, graph), graph)) return;
20468
+ try {
20469
+ await this.options.presentation.persist(graph, { serialized: serialized?.digraph !== void 0 ? serialized : await this.getSerializedPayload(serialized) });
20470
+ this.lastPersistedGraph = graph;
20471
+ } catch {}
20472
+ }
20091
20473
  async persistPresentation(graph, serialized) {
20092
20474
  if (!this.options.presentation) return;
20093
20475
  try {
@@ -20648,7 +21030,7 @@ function sourceLocationUris(sourceLocations) {
20648
21030
 
20649
21031
  //#endregion
20650
21032
  //#region src/version.ts
20651
- const CLI_VERSION = "0.12.8";
21033
+ const CLI_VERSION = "0.13.0";
20652
21034
 
20653
21035
  //#endregion
20654
21036
  //#region src/cliHost.ts
@@ -21749,7 +22131,7 @@ function getScriptKind$1(fileName) {
21749
22131
  }
21750
22132
 
21751
22133
  //#endregion
21752
- //#region ../../node_modules/.pnpm/@statelyai+graph@2.1.0_@statelyai+layout@0.4.2_cytoscape@3.34.0_d3-force@3.0.0_d3-hiera_48d6687797f6ba8a844c48e50eec3ae1/node_modules/@statelyai/graph/dist/index.mjs
22134
+ //#region ../../node_modules/.pnpm/@statelyai+graph@2.1.0_@statelyai+layout@0.4.3_cytoscape@3.34.0_d3-force@3.0.0_d3-hiera_2afdfa88fae2fa10712f99651d0f58d6/node_modules/@statelyai/graph/dist/index.mjs
21753
22135
  const LAYOUT_KEYS = {
21754
22136
  node: [
21755
22137
  "x",
@@ -24130,7 +24512,10 @@ const COMMANDS = {
24130
24512
  init: InitCommand,
24131
24513
  login: LoginCommand,
24132
24514
  logout: LogoutCommand,
24133
- whoami: WhoamiCommand
24515
+ whoami: WhoamiCommand,
24516
+ changes: ChangesCommand,
24517
+ brief: BriefCommand,
24518
+ pending: PendingCommand
24134
24519
  };
24135
24520
  async function run$1(argv = process.argv.slice(2), entryUrl = import.meta.url) {
24136
24521
  const normalizedArgv = argv.length === 1 && argv[0] === "-h" ? ["--help"] : argv;
@@ -24154,4 +24539,4 @@ function isDirectExecution() {
24154
24539
  if (isDirectExecution()) run$1();
24155
24540
 
24156
24541
  //#endregion
24157
- export { run$1 as C, verifyProject as D, resolveVerificationRequest as E, formatVerificationJUnit as O, resolveProjectStatus as S, scanProjectSources as T, isFileGitDirty as _, discoverMachinesInSource as a, resolveCredentialStatus as b, formatDiscoveredMachines as c, formatProjectStatus as d, formatStoredCredentialSource as f, initProject as g, inferInitProjectName as h, discoverLinkedPullTargets as i, createStatelyProjectConfig as k, formatMissingNewMachineDirMessage as l, getEnvCredential as m, buildOAuthLoginStart as n, discoverOAuthLogin as o, getEnvApiKey as p, classifyPushCandidates as r, discoverRemoteProjectMachineTargets as s, COMMANDS as t, formatPlanSummary as u, resolveApiKey as v, scanProjectMachines as w, resolveOpenRootDir as x, resolveConfiguredPullTargets as y };
24542
+ export { briefReport as A, run$1 as C, verifyProject as D, resolveVerificationRequest as E, pendingReport as M, readGraphFile as N, formatVerificationJUnit as O, verifyReport as P, resolveProjectStatus as S, scanProjectSources as T, isFileGitDirty as _, discoverMachinesInSource as a, resolveCredentialStatus as b, formatDiscoveredMachines as c, formatProjectStatus as d, formatStoredCredentialSource as f, initProject as g, inferInitProjectName as h, discoverLinkedPullTargets as i, changesReport as j, createStatelyProjectConfig as k, formatMissingNewMachineDirMessage as l, getEnvCredential as m, buildOAuthLoginStart as n, discoverOAuthLogin as o, getEnvApiKey as p, classifyPushCandidates as r, discoverRemoteProjectMachineTargets as s, COMMANDS as t, formatPlanSummary as u, resolveApiKey as v, scanProjectMachines as w, resolveOpenRootDir as x, resolveConfiguredPullTargets as y };