@statelyai/sdk 0.29.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -1
- package/dist/assetStorage.d.mts +1 -1
- package/dist/auth.d.mts +1 -1
- package/dist/{statelyPragma-Cg1KzBZr.mjs → dist-BQEaIgBI.mjs} +172 -139
- package/dist/{editor-sync-types-DB1N6QUK.d.mts → editor-sync-types-CPpzTSnT.d.mts} +4 -0
- package/dist/{editorHostSession-vSt07IJV.d.mts → editorHostSession-BHr3WBHT.d.mts} +105 -6
- package/dist/{editorHostSession-DNpXPNAc.mjs → editorHostSession-Dm5i4mg_.mjs} +380 -20
- package/dist/editorHostSession.d.mts +2 -2
- package/dist/editorHostSession.mjs +3 -2
- package/dist/embed.d.mts +3 -4
- package/dist/embed.mjs +6 -2
- package/dist/{graph-5X1Ilppq.d.mts → graph-CehpcL7P.d.mts} +1 -1
- package/dist/graph.d.mts +1 -1
- package/dist/{index-DNDfA-YC.d.mts → index-ZlKF1x_z.d.mts} +81 -2
- package/dist/index.d.mts +8 -9
- package/dist/index.mjs +7 -6
- package/dist/{inspect-DYFQzEsh.mjs → inspect-BD6fDWzd.mjs} +1 -1
- package/dist/{inspect-D61HS-t7.d.mts → inspect-BgYRNJF9.d.mts} +1 -2
- package/dist/inspect.d.mts +2 -2
- package/dist/inspect.mjs +2 -2
- package/dist/patchTypes.d.mts +1 -1
- package/dist/protocol-DOt1Vz-5.d.mts +842 -0
- package/dist/protocol.d.mts +2 -819
- package/dist/relay.d.mts +1 -1
- package/dist/statelyPragma-D46lczJR.mjs +102 -0
- package/dist/{studio-QQRLjF5V.d.mts → studio-GZ6E_xns.d.mts} +34 -11
- package/dist/{studio-DpCW5V4a.mjs → studio-rSI54Ese.mjs} +149 -7
- package/dist/studio.d.mts +1 -1
- package/dist/studio.mjs +1 -1
- package/dist/sync.d.mts +2 -2
- package/dist/sync.mjs +74 -26
- package/dist/{version-BJPr6idb.mjs → version-DbnY8nLV.mjs} +4 -3
- package/package.json +3 -3
- package/schemas/statelyai.schema.json +6 -0
- package/dist/embedPanel-Bpbq4sfJ.d.mts +0 -13
- /package/dist/{auth-BPyCCHYo.d.mts → auth-Dg7prjeL.d.mts} +0 -0
package/README.md
CHANGED
|
@@ -62,6 +62,8 @@ and validator implementations remain in the host and are called asynchronously.
|
|
|
62
62
|
RPC methods and payloads are validated before host code runs, and malformed
|
|
63
63
|
graphs returned by custom importers are rejected.
|
|
64
64
|
Use `defaultProfile` and `defaultFormat` to choose the initial custom pair.
|
|
65
|
+
Profile namespaced-data adaptation and migration hooks are in-process React
|
|
66
|
+
editor extensions and are intentionally omitted from iframe manifests.
|
|
65
67
|
|
|
66
68
|
The Get started launchpad is host-configurable. Pass serializable `examples` to
|
|
67
69
|
`embed.init()` (or the project equivalent) to show the Examples section; omit
|
|
@@ -303,7 +305,10 @@ relay. An explicit `url` wins over `STATELY_INSPECT_URL`, which wins over the
|
|
|
303
305
|
hosted default. See `@statelyai/sdk/protocol` for the versioned message and
|
|
304
306
|
`?r=` query contract. SDK producer registration also reports its SDK version
|
|
305
307
|
and coarse browser, Node, or unknown runtime; it never adds inspection payloads
|
|
306
|
-
to registration metadata.
|
|
308
|
+
to registration metadata. Protocol mismatches and registration errors reject
|
|
309
|
+
`ready` and close the connection without retrying. Browser transports use
|
|
310
|
+
application close code `4002`, with a fixed reason that stays within the
|
|
311
|
+
WebSocket UTF-8 length limit.
|
|
307
312
|
|
|
308
313
|
### CLI and sync
|
|
309
314
|
|
|
@@ -322,8 +327,12 @@ npx statelyai push
|
|
|
322
327
|
npx statelyai pull
|
|
323
328
|
npx statelyai diff ./checkout.machine.ts machine-id
|
|
324
329
|
npx statelyai open ./checkout.machine.ts
|
|
330
|
+
npx statelyai open
|
|
325
331
|
```
|
|
326
332
|
|
|
333
|
+
`open <file>` shows every machine in that file in one collapsed workspace;
|
|
334
|
+
`open` discovers machines across the current worktree.
|
|
335
|
+
|
|
327
336
|
`statelyai diff` ignores entity IDs and presentation-only layout or color
|
|
328
337
|
fields, so `--fail-on-changes` can gate CI on machine semantics.
|
|
329
338
|
|
package/dist/assetStorage.d.mts
CHANGED
package/dist/auth.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as getCredentialToken, n as StatelyCredential, r as createAuthorizationHeader, t as StatelyAuthMode } from "./auth-
|
|
1
|
+
import { i as getCredentialToken, n as StatelyCredential, r as createAuthorizationHeader, t as StatelyAuthMode } from "./auth-Dg7prjeL.mjs";
|
|
2
2
|
export { StatelyAuthMode, StatelyCredential, createAuthorizationHeader, getCredentialToken };
|
|
@@ -3167,6 +3167,10 @@ function graphChangeToPatchesResult(prevGraph, nextGraph) {
|
|
|
3167
3167
|
op: "deleteTransition",
|
|
3168
3168
|
transitionId: edge.id
|
|
3169
3169
|
});
|
|
3170
|
+
if (prevGraph.data.profile !== nextGraph.data.profile) patches.push({
|
|
3171
|
+
op: "setProfile",
|
|
3172
|
+
profile: nextGraph.data.profile ?? "xstate-v5"
|
|
3173
|
+
});
|
|
3170
3174
|
if (!isEqual(prevGraph.data.context, nextGraph.data.context)) patches.push({
|
|
3171
3175
|
op: "setContext",
|
|
3172
3176
|
context: nextGraph.data.context ?? null
|
|
@@ -3273,6 +3277,30 @@ function alignCompareGraphIds(base, compare, semanticBase, semanticCompare) {
|
|
|
3273
3277
|
}
|
|
3274
3278
|
return aligned;
|
|
3275
3279
|
}
|
|
3280
|
+
const XSTATE_V5_PROFILE = "@statelyai/xstate@5.30.0";
|
|
3281
|
+
const XSTATE_V6_PROFILE = "@statelyai/xstate@6.0.0-alpha.51";
|
|
3282
|
+
const LEGACY_MACHINE_PROFILES = ["xstate-v5", "xstate-v6-alpha"];
|
|
3283
|
+
function normalizeMachineProfile(profile) {
|
|
3284
|
+
return profile === "xstate-v5" ? XSTATE_V5_PROFILE : profile === "xstate-v6-alpha" ? XSTATE_V6_PROFILE : profile;
|
|
3285
|
+
}
|
|
3286
|
+
function isXStateV6Profile(profile) {
|
|
3287
|
+
return (profile === "xstate-v5" || profile === "xstate-v6-alpha" ? normalizeMachineProfile(profile) : profile ?? XSTATE_V5_PROFILE).startsWith("@statelyai/xstate@6.");
|
|
3288
|
+
}
|
|
3289
|
+
const EXACT_SEMVER$1 = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
3290
|
+
function parseProfileSpecifier(specifier) {
|
|
3291
|
+
const separator = specifier.lastIndexOf("@");
|
|
3292
|
+
const name = specifier.slice(0, separator);
|
|
3293
|
+
const version = specifier.slice(separator + 1);
|
|
3294
|
+
if (separator <= 0 || !/^@[^/]+\/[^@/]+$/.test(name) || !version) throw new Error(`Invalid profile specifier: ${specifier}`);
|
|
3295
|
+
return {
|
|
3296
|
+
name,
|
|
3297
|
+
version,
|
|
3298
|
+
kind: EXACT_SEMVER$1.test(version) ? "exact" : "range"
|
|
3299
|
+
};
|
|
3300
|
+
}
|
|
3301
|
+
function normalizeProfileRef(profile) {
|
|
3302
|
+
return profile === "xstate-v5" || profile === "xstate-v6-alpha" ? normalizeMachineProfile(profile) : profile;
|
|
3303
|
+
}
|
|
3276
3304
|
function isAutoGeneratedId(id) {
|
|
3277
3305
|
return !!id && id.startsWith("$auto-");
|
|
3278
3306
|
}
|
|
@@ -3388,15 +3416,6 @@ function stripExportDefault(code) {
|
|
|
3388
3416
|
if (trimmed.startsWith("export default ")) return trimmed.slice(15).replace(/;$/, "");
|
|
3389
3417
|
return trimmed;
|
|
3390
3418
|
}
|
|
3391
|
-
const XSTATE_V5_PROFILE = "@statelyai/xstate@5.30.0";
|
|
3392
|
-
const XSTATE_V6_PROFILE = "@statelyai/xstate@6.0.0-alpha.51";
|
|
3393
|
-
const LEGACY_MACHINE_PROFILES = ["xstate-v5", "xstate-v6-alpha"];
|
|
3394
|
-
function normalizeMachineProfile(profile) {
|
|
3395
|
-
return profile === "xstate-v5" ? XSTATE_V5_PROFILE : profile === "xstate-v6-alpha" ? XSTATE_V6_PROFILE : profile;
|
|
3396
|
-
}
|
|
3397
|
-
function isXStateV6Profile(profile) {
|
|
3398
|
-
return (profile === "xstate-v5" || profile === "xstate-v6-alpha" ? normalizeMachineProfile(profile) : profile ?? XSTATE_V5_PROFILE).startsWith("@statelyai/xstate@6.");
|
|
3399
|
-
}
|
|
3400
3419
|
/**
|
|
3401
3420
|
* Graph-native transition references. Transitions point at invoke/action/state
|
|
3402
3421
|
* blocks by graph id (`@statelyai.*`); the literal `xstate.*` event is produced
|
|
@@ -3990,25 +4009,79 @@ const INLINE_EXPRESSION_DIRECTIVE_FIELDS = [
|
|
|
3990
4009
|
"initialInput",
|
|
3991
4010
|
"route"
|
|
3992
4011
|
];
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
const
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4012
|
+
function analyzeXStateV5Compatibility(graph) {
|
|
4013
|
+
const issues = [];
|
|
4014
|
+
const graphPaths = [
|
|
4015
|
+
["data.version", graph.data.version],
|
|
4016
|
+
["data.options", graph.data.options],
|
|
4017
|
+
["data.schemas.input", graph.data.schemas?.input],
|
|
4018
|
+
["data.schemas.output", graph.data.schemas?.output]
|
|
4019
|
+
].filter(([, value]) => value != null);
|
|
4020
|
+
if (graphPaths.length) issues.push({
|
|
4021
|
+
level: "warning",
|
|
4022
|
+
message: "XState v6 machine fields are retained but read-only in XState v5.",
|
|
4023
|
+
readOnlyPaths: graphPaths.map(([path]) => path)
|
|
4024
|
+
});
|
|
4025
|
+
for (const node of graph.nodes) {
|
|
4026
|
+
const paths = [
|
|
4027
|
+
["data.initialInput", node.data.initialInput],
|
|
4028
|
+
["data.timeout", node.data.timeout],
|
|
4029
|
+
["data.route", node.data.route],
|
|
4030
|
+
["data.schemas", node.data.schemas]
|
|
4031
|
+
].filter(([, value]) => value != null);
|
|
4032
|
+
if (paths.length) issues.push({
|
|
4033
|
+
level: "warning",
|
|
4034
|
+
message: `XState v6 fields on ${node.data.key ?? node.id} are retained but read-only in XState v5.`,
|
|
4035
|
+
nodeIds: [node.id],
|
|
4036
|
+
readOnlyPaths: paths.map(([path]) => `nodes.${node.id}.${path}`)
|
|
4037
|
+
});
|
|
4038
|
+
}
|
|
4039
|
+
for (const edge of graph.edges) {
|
|
4040
|
+
const paths = [["data.matches", edge.data.matches], ["data.input", edge.data.input]].filter(([, value]) => value != null);
|
|
4041
|
+
if (paths.length) issues.push({
|
|
4042
|
+
level: "warning",
|
|
4043
|
+
message: "XState v6 transition fields are retained but read-only in XState v5.",
|
|
4044
|
+
edgeIds: [edge.id],
|
|
4045
|
+
readOnlyPaths: paths.map(([path]) => `edges.${edge.id}.${path}`)
|
|
4046
|
+
});
|
|
4047
|
+
}
|
|
4048
|
+
return issues;
|
|
4049
|
+
}
|
|
4050
|
+
const XSTATE_V5_PROJECTION = {
|
|
4051
|
+
readOnlyPaths: [
|
|
4052
|
+
"data.version",
|
|
4053
|
+
"data.options",
|
|
4054
|
+
"data.schemas.input",
|
|
4055
|
+
"data.schemas.output",
|
|
4056
|
+
"nodes.*.data.initialInput",
|
|
4057
|
+
"nodes.*.data.timeout",
|
|
4058
|
+
"nodes.*.data.route",
|
|
4059
|
+
"nodes.*.data.schemas",
|
|
4060
|
+
"edges.*.data.matches",
|
|
4061
|
+
"edges.*.data.input"
|
|
4062
|
+
],
|
|
4063
|
+
analyzeCompatibility: analyzeXStateV5Compatibility
|
|
4064
|
+
};
|
|
4065
|
+
const XSTATE_V6_PROJECTION = {};
|
|
4066
|
+
/**
|
|
4067
|
+
* Derive LangGraph authoring kinds into its namespace. Canonical fields and
|
|
4068
|
+
* graph topology are never returned, so the adapter cannot rewrite them.
|
|
4069
|
+
*/
|
|
4070
|
+
const LANGGRAPH_PROJECTION = { adapt: (graph) => ({ data: {
|
|
4071
|
+
nodes: Object.fromEntries(graph.nodes.map((node) => [node.id, { kind: node.data.type === "final" ? "end" : node.data.kind === "agent" || node.data.kind === "task" || node.data.kind === "entrypoint" ? node.data.kind : "node" }])),
|
|
4072
|
+
edges: Object.fromEntries(graph.edges.map((edge) => {
|
|
4073
|
+
const source = graph.nodes.find((node) => node.id === edge.sourceId);
|
|
4074
|
+
return [edge.id, { kind: edge.data.kind === "call" ? "call" : edge.data.kind === "conditional" || edge.data.guard != null || source?.data.type === "choice" ? "conditional" : "edge" }];
|
|
4075
|
+
}))
|
|
4076
|
+
} }) };
|
|
4008
4077
|
/** Stately's semantic projection of the LangGraph 1.x APIs across runtimes. */
|
|
4009
4078
|
const LANGGRAPH_PROFILE = "@statelyai/langgraph@1.0.0";
|
|
4010
4079
|
const LANGGRAPH_PROFILE_MANIFEST = {
|
|
4011
4080
|
profile: LANGGRAPH_PROFILE,
|
|
4081
|
+
namespace: "@statelyai.langgraph",
|
|
4082
|
+
lineage: "@statelyai/langgraph",
|
|
4083
|
+
projection: LANGGRAPH_PROJECTION,
|
|
4084
|
+
selectable: false,
|
|
4012
4085
|
name: "LangGraph",
|
|
4013
4086
|
description: "LangGraph 1.x graph semantics for Python and JavaScript/TypeScript source.",
|
|
4014
4087
|
restrictFormatsToListed: true,
|
|
@@ -4189,6 +4262,9 @@ const XSTATE_AUTHORING = {
|
|
|
4189
4262
|
};
|
|
4190
4263
|
const XSTATE_PROFILE_MANIFESTS = [{
|
|
4191
4264
|
profile: XSTATE_V5_PROFILE,
|
|
4265
|
+
namespace: "@statelyai.xstate",
|
|
4266
|
+
lineage: "@statelyai/xstate",
|
|
4267
|
+
projection: XSTATE_V5_PROJECTION,
|
|
4192
4268
|
name: "XState v5",
|
|
4193
4269
|
formats: [...XSTATE_FORMATS],
|
|
4194
4270
|
authoring: XSTATE_AUTHORING,
|
|
@@ -4199,7 +4275,10 @@ const XSTATE_PROFILE_MANIFESTS = [{
|
|
|
4199
4275
|
}
|
|
4200
4276
|
}, {
|
|
4201
4277
|
profile: XSTATE_V6_PROFILE,
|
|
4202
|
-
|
|
4278
|
+
namespace: "@statelyai.xstate",
|
|
4279
|
+
lineage: "@statelyai/xstate",
|
|
4280
|
+
projection: XSTATE_V6_PROJECTION,
|
|
4281
|
+
name: "XState v6 alpha",
|
|
4203
4282
|
formats: [...XSTATE_FORMATS],
|
|
4204
4283
|
authoring: XSTATE_AUTHORING,
|
|
4205
4284
|
operations: {
|
|
@@ -5325,16 +5404,58 @@ function hasV6Syntax(source) {
|
|
|
5325
5404
|
if (!binding) return false;
|
|
5326
5405
|
return containsFunction(binding, new Set([...seenBindings, node.text]));
|
|
5327
5406
|
}
|
|
5328
|
-
if (ts.isObjectLiteralExpression(node)) return node.properties.some((property) => {
|
|
5329
|
-
if (ts.isPropertyAssignment(property)) return containsFunction(property.initializer, seenBindings);
|
|
5330
|
-
if (ts.isShorthandPropertyAssignment(property)) return containsFunction(property.name, seenBindings);
|
|
5331
|
-
if (ts.isSpreadAssignment(property)) return containsFunction(property.expression, seenBindings);
|
|
5332
|
-
return false;
|
|
5333
|
-
});
|
|
5334
5407
|
if (ts.isArrayLiteralExpression(node)) return node.elements.some((element) => ts.isExpression(element) && containsFunction(element, seenBindings));
|
|
5335
5408
|
if (ts.isCallExpression(node)) return ts.isIdentifier(node.expression) && containsFunction(node.expression, seenBindings) || node.arguments.some((argument) => ts.isExpression(argument) && containsFunction(argument, seenBindings));
|
|
5336
5409
|
return false;
|
|
5337
5410
|
}
|
|
5411
|
+
function containsEnqueueAction(expression, seen = /* @__PURE__ */ new Set()) {
|
|
5412
|
+
if (seen.has(expression)) return false;
|
|
5413
|
+
seen.add(expression);
|
|
5414
|
+
const node = ts.isFunctionDeclaration(expression) ? expression : unwrapExpression(expression);
|
|
5415
|
+
if (ts.isIdentifier(node)) {
|
|
5416
|
+
const binding = bindings.get(node.text);
|
|
5417
|
+
return binding ? containsEnqueueAction(binding, seen) : false;
|
|
5418
|
+
}
|
|
5419
|
+
if (ts.isArrayLiteralExpression(node)) return node.elements.some((element) => ts.isSpreadElement(element) ? containsEnqueueAction(element.expression, seen) : ts.isExpression(element) && containsEnqueueAction(element, seen));
|
|
5420
|
+
if (!isFunctionBinding(node)) return false;
|
|
5421
|
+
const enqueue = node.parameters[1]?.name;
|
|
5422
|
+
if (!enqueue || !ts.isIdentifier(enqueue) || !node.body) return false;
|
|
5423
|
+
const enqueueName = enqueue.text;
|
|
5424
|
+
let callsEnqueue = false;
|
|
5425
|
+
function visit(node) {
|
|
5426
|
+
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) return;
|
|
5427
|
+
if (ts.isCallExpression(node)) {
|
|
5428
|
+
const callee = node.expression;
|
|
5429
|
+
const receiver = ts.isPropertyAccessExpression(callee) ? callee.expression : callee;
|
|
5430
|
+
if (ts.isIdentifier(receiver) && receiver.text === enqueueName) callsEnqueue = true;
|
|
5431
|
+
}
|
|
5432
|
+
ts.forEachChild(node, visit);
|
|
5433
|
+
}
|
|
5434
|
+
visit(node.body);
|
|
5435
|
+
return callsEnqueue;
|
|
5436
|
+
}
|
|
5437
|
+
function containsFunctionTransitionMap(expression, seen = /* @__PURE__ */ new Set()) {
|
|
5438
|
+
if (seen.has(expression) || ts.isFunctionDeclaration(expression)) return false;
|
|
5439
|
+
seen.add(expression);
|
|
5440
|
+
const node = unwrapExpression(expression);
|
|
5441
|
+
if (ts.isIdentifier(node)) {
|
|
5442
|
+
const binding = bindings.get(node.text);
|
|
5443
|
+
return binding ? containsFunctionTransitionMap(binding, seen) : false;
|
|
5444
|
+
}
|
|
5445
|
+
if (ts.isArrayLiteralExpression(node)) return node.elements.some((element) => ts.isExpression(element) && containsFunctionTransitionMap(element, seen));
|
|
5446
|
+
if (!ts.isObjectLiteralExpression(node)) return containsFunction(node);
|
|
5447
|
+
return node.properties.some((property) => {
|
|
5448
|
+
if (ts.isMethodDeclaration(property)) return true;
|
|
5449
|
+
if (ts.isPropertyAssignment(property)) {
|
|
5450
|
+
const key = propName(property.name);
|
|
5451
|
+
if (key === "guard" || key === "cond" || key === "actions") return false;
|
|
5452
|
+
return containsFunctionTransitionMap(property.initializer, seen);
|
|
5453
|
+
}
|
|
5454
|
+
if (ts.isShorthandPropertyAssignment(property)) return containsFunction(property.name);
|
|
5455
|
+
if (ts.isSpreadAssignment(property)) return containsFunctionTransitionMap(property.expression, seen);
|
|
5456
|
+
return false;
|
|
5457
|
+
});
|
|
5458
|
+
}
|
|
5338
5459
|
function visitSyntax(node) {
|
|
5339
5460
|
if (found) return;
|
|
5340
5461
|
if (ts.isIdentifier(node)) {
|
|
@@ -5351,7 +5472,24 @@ function hasV6Syntax(source) {
|
|
|
5351
5472
|
found = true;
|
|
5352
5473
|
return;
|
|
5353
5474
|
}
|
|
5354
|
-
if (
|
|
5475
|
+
if ([
|
|
5476
|
+
"entry",
|
|
5477
|
+
"exit",
|
|
5478
|
+
"actions"
|
|
5479
|
+
].includes(key) && containsEnqueueAction(node.initializer)) {
|
|
5480
|
+
found = true;
|
|
5481
|
+
return;
|
|
5482
|
+
}
|
|
5483
|
+
if ((key === "on" || key === "after") && containsFunctionTransitionMap(node.initializer)) {
|
|
5484
|
+
found = true;
|
|
5485
|
+
return;
|
|
5486
|
+
}
|
|
5487
|
+
if ([
|
|
5488
|
+
"always",
|
|
5489
|
+
"onDone",
|
|
5490
|
+
"onError",
|
|
5491
|
+
"onSnapshot"
|
|
5492
|
+
].includes(key) && containsFunction(node.initializer)) {
|
|
5355
5493
|
found = true;
|
|
5356
5494
|
return;
|
|
5357
5495
|
}
|
|
@@ -5378,11 +5516,6 @@ function hasV6Syntax(source) {
|
|
|
5378
5516
|
function detectXStateSourceProfile(source) {
|
|
5379
5517
|
return hasV6Syntax(source) ? "xstate-v6-alpha" : "xstate-v5";
|
|
5380
5518
|
}
|
|
5381
|
-
function xstateSourceToConfig(source, options = {}) {
|
|
5382
|
-
const [config] = extractXStateMachineConfigs(source, options);
|
|
5383
|
-
if (!config) throw new Error("No createMachine(...), createFSM(...), or setup factory call found.");
|
|
5384
|
-
return config;
|
|
5385
|
-
}
|
|
5386
5519
|
/**
|
|
5387
5520
|
* Extract every XState machine config from source without executing code.
|
|
5388
5521
|
* XState 5/6 syntax is inferred structurally unless a profile is supplied.
|
|
@@ -5498,9 +5631,6 @@ function extractXStateMachineConfigEntries(source, options = {}) {
|
|
|
5498
5631
|
visit(file);
|
|
5499
5632
|
return found;
|
|
5500
5633
|
}
|
|
5501
|
-
function extractXStateMachineConfigs(source, options = {}) {
|
|
5502
|
-
return extractXStateMachineConfigEntries(source, options).map(({ config }) => config);
|
|
5503
|
-
}
|
|
5504
5634
|
function jsonSchemaToTSType(schema) {
|
|
5505
5635
|
if (!schema) return "unknown";
|
|
5506
5636
|
if (schema.enum) return schema.enum.map((v) => typeof v === "string" ? `'${v}'` : String(v)).join(" | ");
|
|
@@ -7525,6 +7655,7 @@ const validationIssueCodeSchema = _enum([
|
|
|
7525
7655
|
"missing_delay_implementation",
|
|
7526
7656
|
"invalid_final_transition",
|
|
7527
7657
|
"invalid_history_transition",
|
|
7658
|
+
"invalid_choice_event",
|
|
7528
7659
|
"parallel_region_transition",
|
|
7529
7660
|
"duplicate_source_name",
|
|
7530
7661
|
"undefined_action",
|
|
@@ -7622,102 +7753,4 @@ const simulateMachineStepInputSchema = machineInputSchema.extend({
|
|
|
7622
7753
|
});
|
|
7623
7754
|
|
|
7624
7755
|
//#endregion
|
|
7625
|
-
|
|
7626
|
-
function findStatelyPragmaAttachments(sourceText, fileName = "machine.ts") {
|
|
7627
|
-
const sourceFile = ts.createSourceFile(fileName, sourceText, ts.ScriptTarget.Latest, true, getScriptKind(fileName));
|
|
7628
|
-
const attachments = [];
|
|
7629
|
-
const visit = (node) => {
|
|
7630
|
-
if (ts.isCallExpression(node) && isCreateMachineExpression(node.expression)) {
|
|
7631
|
-
const attachNode = findAttachNode(node);
|
|
7632
|
-
if (attachNode) attachments.push({
|
|
7633
|
-
machineStart: getMachineExpressionStart(node.expression, sourceFile),
|
|
7634
|
-
attachStart: attachNode.getStart(sourceFile),
|
|
7635
|
-
pragma: findAttachedStatelyPragma(sourceText, attachNode)
|
|
7636
|
-
});
|
|
7637
|
-
}
|
|
7638
|
-
ts.forEachChild(node, visit);
|
|
7639
|
-
};
|
|
7640
|
-
visit(sourceFile);
|
|
7641
|
-
return attachments;
|
|
7642
|
-
}
|
|
7643
|
-
function getStatelyPragma(sourceText, fileName = "machine.ts", machineIndex = 0) {
|
|
7644
|
-
return findStatelyPragmaAttachments(sourceText, fileName)[machineIndex]?.pragma;
|
|
7645
|
-
}
|
|
7646
|
-
function upsertStatelyPragma(sourceText, id, options = {}) {
|
|
7647
|
-
const attachment = findStatelyPragmaAttachments(sourceText, options.fileName ?? "machine.ts")[options.machineIndex ?? 0];
|
|
7648
|
-
if (!attachment) return sourceText;
|
|
7649
|
-
const lineEnding = options.lineEnding ?? detectLineEnding(sourceText);
|
|
7650
|
-
const canonicalComment = `// @statelyai id=${id}`;
|
|
7651
|
-
if (attachment.pragma) return sourceText.slice(0, attachment.pragma.start) + canonicalComment + sourceText.slice(attachment.pragma.end);
|
|
7652
|
-
const insertText = `${getIndentationAtOffset(sourceText, attachment.attachStart)}${canonicalComment}${lineEnding}`;
|
|
7653
|
-
return sourceText.slice(0, attachment.attachStart) + insertText + sourceText.slice(attachment.attachStart);
|
|
7654
|
-
}
|
|
7655
|
-
function findAttachedStatelyPragma(sourceText, node) {
|
|
7656
|
-
const comments = ts.getLeadingCommentRanges(sourceText, node.getFullStart()) ?? [];
|
|
7657
|
-
for (let index = comments.length - 1; index >= 0; index -= 1) {
|
|
7658
|
-
const comment = comments[index];
|
|
7659
|
-
const parsed = parseStatelyPragma(sourceText, comment.pos, comment.end);
|
|
7660
|
-
if (parsed) return parsed;
|
|
7661
|
-
}
|
|
7662
|
-
}
|
|
7663
|
-
function parseStatelyPragma(sourceText, start, end) {
|
|
7664
|
-
const match = normalizeCommentContent(sourceText.slice(start, end)).match(/^@statelyai(?:\s+(.*))?$/s);
|
|
7665
|
-
if (!match) return;
|
|
7666
|
-
const fields = parseFields(match[1] ?? "");
|
|
7667
|
-
return {
|
|
7668
|
-
tag: "@statelyai",
|
|
7669
|
-
id: fields.id,
|
|
7670
|
-
fields,
|
|
7671
|
-
start,
|
|
7672
|
-
end
|
|
7673
|
-
};
|
|
7674
|
-
}
|
|
7675
|
-
function normalizeCommentContent(rawComment) {
|
|
7676
|
-
if (rawComment.startsWith("//")) return rawComment.slice(2).trim();
|
|
7677
|
-
if (rawComment.startsWith("/*")) return rawComment.slice(2, rawComment.endsWith("*/") ? -2 : void 0).split(/\r?\n/).map((line) => line.replace(/^\s*\*\s?/, "")).join(" ").trim();
|
|
7678
|
-
return rawComment.trim();
|
|
7679
|
-
}
|
|
7680
|
-
function parseFields(input) {
|
|
7681
|
-
const fields = {};
|
|
7682
|
-
for (const token of input.split(/\s+/)) {
|
|
7683
|
-
if (!token) continue;
|
|
7684
|
-
const equalsIndex = token.indexOf("=");
|
|
7685
|
-
if (equalsIndex <= 0) continue;
|
|
7686
|
-
const key = token.slice(0, equalsIndex);
|
|
7687
|
-
const value = token.slice(equalsIndex + 1);
|
|
7688
|
-
if (!key || !value) continue;
|
|
7689
|
-
fields[key] = value;
|
|
7690
|
-
}
|
|
7691
|
-
return fields;
|
|
7692
|
-
}
|
|
7693
|
-
function findAttachNode(node) {
|
|
7694
|
-
let current = node;
|
|
7695
|
-
while (current?.parent) {
|
|
7696
|
-
if (ts.isVariableStatement(current.parent) || ts.isExpressionStatement(current.parent) || ts.isExportAssignment(current.parent)) return current.parent;
|
|
7697
|
-
current = current.parent;
|
|
7698
|
-
}
|
|
7699
|
-
return current;
|
|
7700
|
-
}
|
|
7701
|
-
function isCreateMachineExpression(expression) {
|
|
7702
|
-
return ts.isIdentifier(expression) && expression.text === "createMachine" || ts.isPropertyAccessExpression(expression) && expression.name.text === "createMachine";
|
|
7703
|
-
}
|
|
7704
|
-
function getMachineExpressionStart(expression, sourceFile) {
|
|
7705
|
-
if (ts.isPropertyAccessExpression(expression)) return expression.name.getStart(sourceFile);
|
|
7706
|
-
return expression.getStart(sourceFile);
|
|
7707
|
-
}
|
|
7708
|
-
function getIndentationAtOffset(sourceText, offset) {
|
|
7709
|
-
const lineStart = sourceText.lastIndexOf("\n", Math.max(0, offset - 1)) + 1;
|
|
7710
|
-
return sourceText.slice(lineStart, offset).match(/^[ \t]*/)?.[0] ?? "";
|
|
7711
|
-
}
|
|
7712
|
-
function detectLineEnding(sourceText) {
|
|
7713
|
-
return sourceText.includes("\r\n") ? "\r\n" : "\n";
|
|
7714
|
-
}
|
|
7715
|
-
function getScriptKind(fileName) {
|
|
7716
|
-
if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
7717
|
-
if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
7718
|
-
if (fileName.endsWith(".js")) return ts.ScriptKind.JS;
|
|
7719
|
-
return ts.ScriptKind.TS;
|
|
7720
|
-
}
|
|
7721
|
-
|
|
7722
|
-
//#endregion
|
|
7723
|
-
export { jsonSchemaToTSType as _, RawCode as a, serializeJS as b, detectXStateSourceProfile as c, getXStateFSMCompatibilityIssues as d, graphChangeToPatchesResult as f, graphToXStateV4TS as g, graphToXStateTS as h, INLINE_EXPRESSION_DIRECTIVE_FIELDS as i, diffGraphsSemantically as l, graphToXStateFSM as m, getStatelyPragma as n, alignCompareGraphIds as o, graphToMachineConfig as p, upsertStatelyPragma as r, contextSchemaToTSType as s, findStatelyPragmaAttachments as t, eventsSchemaToTSType as u, normalizeMachineProfile as v, xstateSourceToConfig as x, raw as y };
|
|
7756
|
+
export { raw as _, detectXStateSourceProfile as a, extractXStateMachineConfigEntries as c, graphToMachineConfig as d, graphToXStateFSM as f, normalizeMachineProfile as g, jsonSchemaToTSType as h, contextSchemaToTSType as i, getXStateFSMCompatibilityIssues as l, graphToXStateV4TS as m, RawCode as n, diffGraphsSemantically as o, graphToXStateTS as p, alignCompareGraphIds as r, eventsSchemaToTSType as s, INLINE_EXPRESSION_DIRECTIVE_FIELDS as t, graphChangeToPatchesResult as u, serializeJS as v };
|
|
@@ -65,6 +65,8 @@ interface EditorSyncDocumentContext {
|
|
|
65
65
|
rootFileName: string;
|
|
66
66
|
rootDir: string;
|
|
67
67
|
documents: EditorSyncSourceDocument[];
|
|
68
|
+
/** Zero-based machine occurrence within the root source document. */
|
|
69
|
+
machineIndex?: number;
|
|
68
70
|
}
|
|
69
71
|
type EditorSyncParseRequest = EditorSyncDocumentContext;
|
|
70
72
|
interface EditorSyncParseResponse {
|
|
@@ -81,7 +83,9 @@ interface EditorSyncApplyRequest extends EditorSyncDocumentContext {
|
|
|
81
83
|
sourceLocations?: MachineSourceLocations;
|
|
82
84
|
serialized?: Record<string, string>;
|
|
83
85
|
preserveStatelyMetadata?: boolean;
|
|
86
|
+
sourceUpdateStrategy?: SourceUpdateStrategy;
|
|
84
87
|
}
|
|
88
|
+
type SourceUpdateStrategy = 'preserve' | 'rewrite';
|
|
85
89
|
interface EditorSyncTextReplacement {
|
|
86
90
|
uri?: string;
|
|
87
91
|
range: EditorSyncSourceRange;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as EditorSyncParseRequest, d as EditorSyncTextReplacement, f as MachineSourceLocations, i as EditorSyncApplyResponse, n as EditorSyncAccess, o as EditorSyncParseResponse, r as EditorSyncApplyRequest, s as EditorSyncSourceDocument, t as EditorCapabilities } from "./editor-sync-types-
|
|
1
|
+
import { Y as ProjectEmbedMachine, Zt as EmbedPanelConfig, ot as ProjectWorkspaceConfig } from "./protocol-DOt1Vz-5.mjs";
|
|
2
|
+
import { a as EditorSyncParseRequest, d as EditorSyncTextReplacement, f as MachineSourceLocations, i as EditorSyncApplyResponse, n as EditorSyncAccess, o as EditorSyncParseResponse, r as EditorSyncApplyRequest, s as EditorSyncSourceDocument, t as EditorCapabilities } from "./editor-sync-types-CPpzTSnT.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/editorHostProtocol.d.ts
|
|
5
5
|
declare const EDITOR_PROTOCOL_VERSION = 1;
|
|
@@ -24,11 +24,13 @@ type EditorHostInboundMessage = {
|
|
|
24
24
|
} | {
|
|
25
25
|
type: '@statelyai.loaded';
|
|
26
26
|
graph: unknown;
|
|
27
|
+
machineId?: string;
|
|
27
28
|
sourceLocations?: MachineSourceLocations;
|
|
28
29
|
} | {
|
|
29
30
|
type: '@statelyai.change';
|
|
30
31
|
graph: unknown;
|
|
31
32
|
machineConfig: unknown;
|
|
33
|
+
machineId?: string;
|
|
32
34
|
patches?: unknown[];
|
|
33
35
|
sourceLocations?: MachineSourceLocations;
|
|
34
36
|
} | {
|
|
@@ -36,19 +38,24 @@ type EditorHostInboundMessage = {
|
|
|
36
38
|
requestId?: string;
|
|
37
39
|
graph: unknown;
|
|
38
40
|
machineConfig: unknown;
|
|
41
|
+
machineId?: string;
|
|
39
42
|
patches?: unknown[];
|
|
40
43
|
validations?: EditorHostValidationIssue[];
|
|
41
44
|
sourceLocations?: MachineSourceLocations;
|
|
45
|
+
sourceUpdateStrategy?: 'preserve' | 'rewrite';
|
|
42
46
|
} | {
|
|
43
47
|
type: '@statelyai.refresh';
|
|
48
|
+
machineId?: string;
|
|
44
49
|
} | {
|
|
45
50
|
type: '@statelyai.retrieved';
|
|
46
51
|
requestId: string;
|
|
47
52
|
data: unknown;
|
|
53
|
+
machineId?: string;
|
|
48
54
|
} | {
|
|
49
55
|
type: '@statelyai.error';
|
|
50
56
|
code: string;
|
|
51
57
|
message: string;
|
|
58
|
+
machineId?: string;
|
|
52
59
|
requestId?: string;
|
|
53
60
|
diagnostic?: EditorHostDiagnostic;
|
|
54
61
|
} | {
|
|
@@ -58,6 +65,18 @@ type EditorHostInboundMessage = {
|
|
|
58
65
|
type: '@statelyai.clipboardWrite';
|
|
59
66
|
requestId: string;
|
|
60
67
|
text: string;
|
|
68
|
+
} | {
|
|
69
|
+
type: '@statelyai.project.machineSelected';
|
|
70
|
+
machineId: string;
|
|
71
|
+
} | {
|
|
72
|
+
type: '@statelyai.project.workspaceAction';
|
|
73
|
+
actionId: string;
|
|
74
|
+
projectId?: string;
|
|
75
|
+
machineId?: string;
|
|
76
|
+
data?: unknown;
|
|
77
|
+
} | {
|
|
78
|
+
type: '@statelyai.project.workspaceOpenChanged';
|
|
79
|
+
open: boolean;
|
|
61
80
|
};
|
|
62
81
|
interface EditorHostInitOptions {
|
|
63
82
|
settings?: Record<string, unknown>;
|
|
@@ -92,6 +111,32 @@ type EditorHostOutboundMessage = {
|
|
|
92
111
|
enabled?: boolean;
|
|
93
112
|
mode?: 'structural' | 'all';
|
|
94
113
|
};
|
|
114
|
+
} | {
|
|
115
|
+
type: '@statelyai.project.init';
|
|
116
|
+
machines: ProjectEmbedMachine[];
|
|
117
|
+
currentMachineId?: string;
|
|
118
|
+
mode?: 'editing' | 'viewing';
|
|
119
|
+
theme?: 'light' | 'dark';
|
|
120
|
+
readOnly?: boolean;
|
|
121
|
+
readOnlyReason?: 'free-plan' | 'access-unverified';
|
|
122
|
+
capabilities?: EditorCapabilities;
|
|
123
|
+
projectWorkspace?: ProjectWorkspaceConfig;
|
|
124
|
+
projectWorkspaceOpen?: boolean;
|
|
125
|
+
settings?: Record<string, unknown>;
|
|
126
|
+
panels?: EmbedPanelConfig[];
|
|
127
|
+
unsavedIndicator?: {
|
|
128
|
+
enabled?: boolean;
|
|
129
|
+
mode?: 'structural' | 'all';
|
|
130
|
+
};
|
|
131
|
+
} | {
|
|
132
|
+
type: '@statelyai.project.update';
|
|
133
|
+
machines: ProjectEmbedMachine[];
|
|
134
|
+
currentMachineId?: string;
|
|
135
|
+
projectWorkspace?: ProjectWorkspaceConfig;
|
|
136
|
+
projectWorkspaceOpen?: boolean;
|
|
137
|
+
} | {
|
|
138
|
+
type: '@statelyai.project.selectMachine';
|
|
139
|
+
machineId: string;
|
|
95
140
|
} | {
|
|
96
141
|
type: '@statelyai.setApiKey';
|
|
97
142
|
apiKey: string;
|
|
@@ -106,23 +151,28 @@ type EditorHostOutboundMessage = {
|
|
|
106
151
|
type: '@statelyai.update';
|
|
107
152
|
machine: unknown;
|
|
108
153
|
format?: string;
|
|
154
|
+
machineId?: string;
|
|
109
155
|
sourceLocations?: MachineSourceLocations;
|
|
110
156
|
} | {
|
|
111
157
|
type: '@statelyai.saved';
|
|
112
158
|
requestId?: string;
|
|
113
159
|
graph: unknown;
|
|
160
|
+
machineId?: string;
|
|
114
161
|
} | {
|
|
115
162
|
type: '@statelyai.retrieve';
|
|
116
163
|
requestId: string;
|
|
117
164
|
format: EditorHostExportFormat;
|
|
165
|
+
machineId?: string;
|
|
118
166
|
} | {
|
|
119
167
|
type: '@statelyai.toast';
|
|
120
168
|
message: string;
|
|
121
169
|
toastType?: 'success' | 'error' | 'info' | 'warning';
|
|
170
|
+
machineId?: string;
|
|
122
171
|
} | {
|
|
123
172
|
type: '@statelyai.error';
|
|
124
173
|
code: string;
|
|
125
174
|
message: string;
|
|
175
|
+
machineId?: string;
|
|
126
176
|
requestId?: string;
|
|
127
177
|
diagnostic?: EditorHostDiagnostic;
|
|
128
178
|
} | {
|
|
@@ -156,6 +206,8 @@ interface EditorSourceHost {
|
|
|
156
206
|
rootUri: string;
|
|
157
207
|
rootFileName: string;
|
|
158
208
|
rootDir: string;
|
|
209
|
+
/** Zero-based machine occurrence within the root source document. */
|
|
210
|
+
machineIndex?: number;
|
|
159
211
|
collectDocuments(extraUris?: readonly string[]): Promise<EditorSyncSourceDocument[]>;
|
|
160
212
|
applyReplacements(replacements: EditorSyncTextReplacement[], rootUri: string): Promise<string[]>;
|
|
161
213
|
saveDocuments?(uris: string[]): Promise<void>;
|
|
@@ -168,6 +220,7 @@ interface EditorSourceHost {
|
|
|
168
220
|
getPreserveStatelyMetadata?(uri: string): boolean;
|
|
169
221
|
}
|
|
170
222
|
interface EditorHostSessionOptions {
|
|
223
|
+
sourceUpdateStrategy?: 'preserve' | 'rewrite';
|
|
171
224
|
source: EditorSourceHost;
|
|
172
225
|
sync: EditorSyncBackend;
|
|
173
226
|
send(message: EditorHostOutboundMessage): void;
|
|
@@ -183,8 +236,16 @@ interface EditorHostSessionOptions {
|
|
|
183
236
|
version: string;
|
|
184
237
|
};
|
|
185
238
|
}
|
|
239
|
+
type SaveReminderState = {
|
|
240
|
+
shown: boolean;
|
|
241
|
+
};
|
|
242
|
+
type SelfEditState = {
|
|
243
|
+
count: number;
|
|
244
|
+
};
|
|
186
245
|
declare class EditorHostSession {
|
|
187
246
|
private options;
|
|
247
|
+
private saveReminderState;
|
|
248
|
+
private selfEditState;
|
|
188
249
|
private editorProtocolState;
|
|
189
250
|
private currentGraph;
|
|
190
251
|
private lastPersistedGraph;
|
|
@@ -192,13 +253,11 @@ declare class EditorHostSession {
|
|
|
192
253
|
private currentSourceLocations;
|
|
193
254
|
private access;
|
|
194
255
|
private watchedSourceUris;
|
|
195
|
-
private selfEditCount;
|
|
196
|
-
private saveReminderShown;
|
|
197
256
|
private watcher;
|
|
198
257
|
private changeWatcher;
|
|
199
258
|
private retrieveRequestCount;
|
|
200
259
|
private pendingRetrievals;
|
|
201
|
-
constructor(options: EditorHostSessionOptions);
|
|
260
|
+
constructor(options: EditorHostSessionOptions, saveReminderState?: SaveReminderState, selfEditState?: SelfEditState);
|
|
202
261
|
dispose(): void;
|
|
203
262
|
notifySavedDocument(uri?: string): Promise<void>;
|
|
204
263
|
receive(message: EditorHostInboundMessage): Promise<void>;
|
|
@@ -211,5 +270,45 @@ declare class EditorHostSession {
|
|
|
211
270
|
private requestSerialized;
|
|
212
271
|
private resolveRetrieved;
|
|
213
272
|
}
|
|
273
|
+
interface EditorHostWorkspaceMachine {
|
|
274
|
+
id: string;
|
|
275
|
+
name?: string;
|
|
276
|
+
sourceReference?: string;
|
|
277
|
+
source: EditorSourceHost;
|
|
278
|
+
}
|
|
279
|
+
type EditorHostWorkspaceSessionOptions = Omit<EditorHostSessionOptions, 'source' | 'send'> & {
|
|
280
|
+
machines: EditorHostWorkspaceMachine[];
|
|
281
|
+
send(message: EditorHostOutboundMessage): void;
|
|
282
|
+
currentMachineId?: string;
|
|
283
|
+
workspaceName?: string;
|
|
284
|
+
projectWorkspaceOpen?: boolean;
|
|
285
|
+
};
|
|
286
|
+
/**
|
|
287
|
+
* Runs one source-sync session per discovered machine while presenting the
|
|
288
|
+
* editor's project/workspace protocol as a single surface.
|
|
289
|
+
*/
|
|
290
|
+
declare class EditorHostWorkspaceSession {
|
|
291
|
+
private options;
|
|
292
|
+
private children;
|
|
293
|
+
private machineDefinitions;
|
|
294
|
+
private initialMessages;
|
|
295
|
+
private selectedMachineId;
|
|
296
|
+
private sentHandshake;
|
|
297
|
+
private sentApiKey;
|
|
298
|
+
private initialized;
|
|
299
|
+
private projectWorkspaceOpen;
|
|
300
|
+
private retrieveRequestCount;
|
|
301
|
+
private pendingRetrievals;
|
|
302
|
+
private saveReminderStates;
|
|
303
|
+
private selfEditStates;
|
|
304
|
+
constructor(options: EditorHostWorkspaceSessionOptions);
|
|
305
|
+
receive(message: EditorHostInboundMessage): Promise<void>;
|
|
306
|
+
selectMachine(machineId: string): void;
|
|
307
|
+
dispose(): void;
|
|
308
|
+
private handleChildMessage;
|
|
309
|
+
private flushProjectInit;
|
|
310
|
+
private getProjectMachines;
|
|
311
|
+
private getProjectWorkspace;
|
|
312
|
+
}
|
|
214
313
|
//#endregion
|
|
215
|
-
export {
|
|
314
|
+
export { EditorHostOutboundMessage as _, EditorHostWorkspaceSessionOptions as a, EditorSyncError as c, fetchEditorSyncAccess as d, EDITOR_PROTOCOL_VERSION as f, EditorHostInitOptions as g, EditorHostInboundMessage as h, EditorHostWorkspaceSession as i, RemoteEditorSyncBackendOptions as l, EditorHostExportFormat as m, EditorHostSessionOptions as n, EditorSourceHost as o, EditorHostDiagnostic as p, EditorHostWorkspaceMachine as r, EditorSyncBackend as s, EditorHostSession as t, createRemoteEditorSyncBackend as u, EditorHostValidationIssue as v };
|