@sweny-ai/core 0.1.161 → 0.1.163
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/dist/browser.d.ts +3 -1
- package/dist/browser.js +2 -0
- package/dist/cli/main.d.ts +1 -0
- package/dist/cli/main.js +7 -2
- package/dist/cli/run-history.d.ts +6 -0
- package/dist/cli/run-history.js +10 -1
- package/dist/cli/run-output.d.ts +11 -1
- package/dist/cli/run-output.js +19 -2
- package/dist/decider.d.ts +144 -0
- package/dist/decider.js +260 -0
- package/dist/executor.d.ts +7 -0
- package/dist/executor.js +115 -11
- package/dist/index.d.ts +5 -1
- package/dist/index.js +4 -0
- package/dist/mermaid.js +4 -2
- package/dist/schema.d.ts +243 -38
- package/dist/schema.js +136 -3
- package/dist/studio.d.ts +2 -2
- package/dist/types.d.ts +24 -2
- package/dist/when.d.ts +114 -0
- package/dist/when.js +581 -0
- package/dist/workflows/browser.js +1 -1
- package/dist/workflows/triage.yml +15 -4
- package/package.json +1 -1
package/dist/schema.js
CHANGED
|
@@ -10,6 +10,9 @@ import { z } from "zod";
|
|
|
10
10
|
import { AUTHOR_ASSOCIATIONS, CONTEXT_MODES, EVALUATOR_KINDS, EVAL_POLICIES, MCP_TRANSPORTS, NODE_ACCESS, NODE_ON_FAIL, REQUIRES_ON_FAIL, SAFE_OUTPUT_APPLIERS, SAFE_OUTPUT_EXPIRES_PATTERN, SAFE_OUTPUT_MAX_CEILING, SAFE_OUTPUT_STATES, SAFE_OUTPUT_TYPES, SKILL_CATEGORIES, SKILL_ID_MAX_LENGTH, SKILL_ID_PATTERN, TOOL_ACCESS, TOOL_CLASSES, WORKFLOW_TYPES, } from "./types.js";
|
|
11
11
|
import { sourceZ } from "./sources.js";
|
|
12
12
|
import { workflowInputsZ, WORKFLOW_INPUT_TYPES } from "./inputs.js";
|
|
13
|
+
import { checkExpression, isWhenExpression, WHEN_EXPR_MAX_LENGTH } from "./when.js";
|
|
14
|
+
// Studio and other schema-only consumers label edges without importing the root entry.
|
|
15
|
+
export { isWhenExpression, whenLabel } from "./when.js";
|
|
13
16
|
export { sourceZ };
|
|
14
17
|
export { workflowInputsZ };
|
|
15
18
|
// ─── Zod Schemas ─────────────────────────────────────────────────
|
|
@@ -275,6 +278,27 @@ export const budgetZ = z
|
|
|
275
278
|
.refine((b) => b.tokens !== undefined || b.cost_usd !== undefined, {
|
|
276
279
|
message: "budget must declare at least one of tokens, cost_usd",
|
|
277
280
|
});
|
|
281
|
+
/**
|
|
282
|
+
* Decision model for route choices (#357). `shadow` needs a provider; the
|
|
283
|
+
* state only ever goes to that `base_url`, there is no fallback. The key is
|
|
284
|
+
* named by env var, never inlined.
|
|
285
|
+
*/
|
|
286
|
+
export const deciderZ = z
|
|
287
|
+
.object({
|
|
288
|
+
mode: z.enum(["off", "shadow"]),
|
|
289
|
+
provider: z
|
|
290
|
+
.object({
|
|
291
|
+
base_url: z.string().url(),
|
|
292
|
+
model: z.string().min(1),
|
|
293
|
+
api_key_env: z.string().min(1).optional(),
|
|
294
|
+
})
|
|
295
|
+
.strict()
|
|
296
|
+
.optional(),
|
|
297
|
+
})
|
|
298
|
+
.strict()
|
|
299
|
+
.refine((d) => d.mode === "off" || d.provider !== undefined, {
|
|
300
|
+
message: "decider.provider is required when mode is shadow",
|
|
301
|
+
});
|
|
278
302
|
/** One typed write intent a node may emit (#365). */
|
|
279
303
|
export const safeOutputDeclarationZ = z
|
|
280
304
|
.object({
|
|
@@ -330,7 +354,9 @@ export const edgeZ = z
|
|
|
330
354
|
.object({
|
|
331
355
|
from: z.string().min(1),
|
|
332
356
|
to: z.string().min(1),
|
|
333
|
-
|
|
357
|
+
// Natural language (the harness picks the edge) or `{ expr }`, a
|
|
358
|
+
// deterministic expression sweny evaluates itself (#461). One or the other.
|
|
359
|
+
when: z.union([z.string(), z.object({ expr: z.string().min(1).max(WHEN_EXPR_MAX_LENGTH) }).strict()]).optional(),
|
|
334
360
|
max_iterations: z.number().int().min(1).max(EDGE_MAX_ITERATIONS_CEILING).optional(),
|
|
335
361
|
})
|
|
336
362
|
.strict();
|
|
@@ -372,6 +398,7 @@ export const workflowZ = z.object({
|
|
|
372
398
|
model: z.string().min(1).optional(),
|
|
373
399
|
judge_budget: z.number().int().min(0).optional(),
|
|
374
400
|
budget: budgetZ.optional(),
|
|
401
|
+
decider: deciderZ.optional(),
|
|
375
402
|
context_mode: z.enum(CONTEXT_MODES).optional(),
|
|
376
403
|
inputs: workflowInputsZ.optional(),
|
|
377
404
|
permissions: nodePermissionsZ.optional(),
|
|
@@ -507,6 +534,68 @@ export function validateWorkflow(workflow, knownSkills) {
|
|
|
507
534
|
});
|
|
508
535
|
}
|
|
509
536
|
}
|
|
537
|
+
// Deterministic `when` expressions (#461). Every path must name a declared
|
|
538
|
+
// output field of the edge's source node or one of its ancestors, so a typo
|
|
539
|
+
// is a load error rather than a branch that never fires. A node routes on
|
|
540
|
+
// expressions or on natural language, never both: a mixed node would hand
|
|
541
|
+
// the expression edges to the model and lose the determinism the author
|
|
542
|
+
// asked for.
|
|
543
|
+
const ancestorsCache = new Map();
|
|
544
|
+
const inAll = new Map();
|
|
545
|
+
for (const [from, tos] of outAll)
|
|
546
|
+
for (const to of tos)
|
|
547
|
+
push(inAll, to, from);
|
|
548
|
+
const ancestorsOf = (id) => {
|
|
549
|
+
let seen = ancestorsCache.get(id);
|
|
550
|
+
if (seen)
|
|
551
|
+
return seen;
|
|
552
|
+
seen = new Set([id]);
|
|
553
|
+
const queue = [id];
|
|
554
|
+
for (let i = 0; i < queue.length; i++) {
|
|
555
|
+
for (const from of inAll.get(queue[i]) ?? []) {
|
|
556
|
+
if (!seen.has(from)) {
|
|
557
|
+
seen.add(from);
|
|
558
|
+
queue.push(from);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
ancestorsCache.set(id, seen);
|
|
563
|
+
return seen;
|
|
564
|
+
};
|
|
565
|
+
const outputs = Object.fromEntries(Object.entries(workflow.nodes).map(([id, n]) => [id, n.output]));
|
|
566
|
+
const conditionKinds = new Map();
|
|
567
|
+
for (const edge of workflow.edges) {
|
|
568
|
+
if (!nodeIds.has(edge.from) || !edge.when)
|
|
569
|
+
continue;
|
|
570
|
+
const kinds = conditionKinds.get(edge.from) ?? { expr: 0, nl: 0 };
|
|
571
|
+
conditionKinds.set(edge.from, kinds);
|
|
572
|
+
if (!isWhenExpression(edge.when)) {
|
|
573
|
+
kinds.nl++;
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
kinds.expr++;
|
|
577
|
+
const problems = checkExpression(edge.when.expr, {
|
|
578
|
+
from: edge.from,
|
|
579
|
+
ancestors: ancestorsOf(edge.from),
|
|
580
|
+
outputs,
|
|
581
|
+
});
|
|
582
|
+
for (const problem of problems) {
|
|
583
|
+
errors.push({
|
|
584
|
+
code: "INVALID_WHEN_EXPRESSION",
|
|
585
|
+
message: `Edge "${edge.from}" -> "${edge.to}": ${problem}`,
|
|
586
|
+
nodeId: edge.from,
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
for (const [from, kinds] of conditionKinds) {
|
|
591
|
+
if (kinds.expr > 0 && kinds.nl > 0) {
|
|
592
|
+
errors.push({
|
|
593
|
+
code: "MIXED_EDGE_CONDITIONS",
|
|
594
|
+
message: `Node "${from}" mixes expression and natural-language 'when' conditions on its out-edges; use one kind per node (an unconditional default edge is fine with either)`,
|
|
595
|
+
nodeId: from,
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
}
|
|
510
599
|
// Reachability: BFS from entry. Skipped only when the entry is missing
|
|
511
600
|
// (every node would be reported, which is noise). All other diagnostics
|
|
512
601
|
// accumulate so one pass reports every structural problem.
|
|
@@ -894,6 +983,31 @@ export const workflowJsonSchema = {
|
|
|
894
983
|
cost_usd: { type: "number", exclusiveMinimum: 0, description: "Max reported cost in USD." },
|
|
895
984
|
},
|
|
896
985
|
},
|
|
986
|
+
Decider: {
|
|
987
|
+
type: "object",
|
|
988
|
+
required: ["mode"],
|
|
989
|
+
additionalProperties: false,
|
|
990
|
+
description: "Decision model for route choices. 'shadow' asks it alongside the agent and logs whether they agree; the route is always the agent's. The workflow state goes only to provider.base_url, with no fallback.",
|
|
991
|
+
properties: {
|
|
992
|
+
mode: { type: "string", enum: ["off", "shadow"] },
|
|
993
|
+
provider: {
|
|
994
|
+
type: "object",
|
|
995
|
+
required: ["base_url", "model"],
|
|
996
|
+
additionalProperties: false,
|
|
997
|
+
properties: {
|
|
998
|
+
base_url: {
|
|
999
|
+
type: "string",
|
|
1000
|
+
format: "uri",
|
|
1001
|
+
description: "Server root serving POST /v1/systemone (Ollama or TypeSafe Jev).",
|
|
1002
|
+
},
|
|
1003
|
+
model: { type: "string", minLength: 1 },
|
|
1004
|
+
api_key_env: { type: "string", minLength: 1, description: "Env var holding the bearer key." },
|
|
1005
|
+
},
|
|
1006
|
+
},
|
|
1007
|
+
},
|
|
1008
|
+
if: { properties: { mode: { const: "shadow" } } },
|
|
1009
|
+
then: { required: ["provider"] },
|
|
1010
|
+
},
|
|
897
1011
|
SafeOutput: {
|
|
898
1012
|
type: "object",
|
|
899
1013
|
required: ["type"],
|
|
@@ -1043,6 +1157,10 @@ export const workflowJsonSchema = {
|
|
|
1043
1157
|
$ref: "#/$defs/Budget",
|
|
1044
1158
|
description: "Spend ceiling for the whole run and for every node. A node's own budget may only narrow it. The CLI's --max-tokens and --max-cost tighten it further.",
|
|
1045
1159
|
},
|
|
1160
|
+
decider: {
|
|
1161
|
+
$ref: "#/$defs/Decider",
|
|
1162
|
+
description: "Decision model for route choices (shadow mode only). Default: off.",
|
|
1163
|
+
},
|
|
1046
1164
|
context_mode: {
|
|
1047
1165
|
type: "string",
|
|
1048
1166
|
enum: [...CONTEXT_MODES],
|
|
@@ -1299,8 +1417,23 @@ export const workflowJsonSchema = {
|
|
|
1299
1417
|
from: { type: "string", minLength: 1 },
|
|
1300
1418
|
to: { type: "string", minLength: 1 },
|
|
1301
1419
|
when: {
|
|
1302
|
-
|
|
1303
|
-
|
|
1420
|
+
description: "Condition for taking this edge. A string is natural language, evaluated at runtime by the workflow's harness. An object { expr } is a deterministic expression over prior nodes' declared output fields, evaluated by sweny with no model call.",
|
|
1421
|
+
oneOf: [
|
|
1422
|
+
{ type: "string" },
|
|
1423
|
+
{
|
|
1424
|
+
type: "object",
|
|
1425
|
+
required: ["expr"],
|
|
1426
|
+
additionalProperties: false,
|
|
1427
|
+
properties: {
|
|
1428
|
+
expr: {
|
|
1429
|
+
type: "string",
|
|
1430
|
+
minLength: 1,
|
|
1431
|
+
maxLength: WHEN_EXPR_MAX_LENGTH,
|
|
1432
|
+
description: "Boolean expression: == != < <= > >= in, && || !, exists, string/number/boolean/null literals, and node.field paths to declared output fields.",
|
|
1433
|
+
},
|
|
1434
|
+
},
|
|
1435
|
+
},
|
|
1436
|
+
],
|
|
1304
1437
|
},
|
|
1305
1438
|
max_iterations: {
|
|
1306
1439
|
type: "integer",
|
package/dist/studio.d.ts
CHANGED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
* directly to node highlights. node:enter → glow blue,
|
|
39
39
|
* tool:call → show tool name, node:exit → green/red.
|
|
40
40
|
*/
|
|
41
|
-
import type { Workflow, Node, ExecutionEvent, NodeResult, Skill } from "./types.js";
|
|
41
|
+
import type { Workflow, Node, Edge, ExecutionEvent, NodeResult, Skill } from "./types.js";
|
|
42
42
|
export interface FlowNode {
|
|
43
43
|
id: string;
|
|
44
44
|
type: "skillNode";
|
|
@@ -74,7 +74,7 @@ export interface FlowEdge {
|
|
|
74
74
|
/** Array index of this edge in workflow.edges — used for stable lookups. */
|
|
75
75
|
edgeIndex: number;
|
|
76
76
|
data: {
|
|
77
|
-
when?:
|
|
77
|
+
when?: Edge["when"];
|
|
78
78
|
max_iterations?: number;
|
|
79
79
|
isConditional: boolean;
|
|
80
80
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { WORKFLOW_INPUT_TYPES } from "./inputs.js";
|
|
|
4
4
|
import type { Source as _Source, ResolvedSource as _ResolvedSource } from "./sources.js";
|
|
5
5
|
import type { ToolClass } from "./harness/types.js";
|
|
6
6
|
import type { Budget, BudgetOverrun } from "./budget.js";
|
|
7
|
+
import type { DeciderConfig, DeciderRecord } from "./decider.js";
|
|
7
8
|
export type JSONSchema = Record<string, unknown>;
|
|
8
9
|
/** Context passed to tool handlers at execution time */
|
|
9
10
|
export interface ToolContext {
|
|
@@ -489,12 +490,26 @@ export interface NodeToolFilter {
|
|
|
489
490
|
/** Skill tool names removed from the node (applied after `allow`). */
|
|
490
491
|
deny?: string[];
|
|
491
492
|
}
|
|
493
|
+
/**
|
|
494
|
+
* A deterministic edge condition (#461): a boolean expression over prior
|
|
495
|
+
* nodes' declared output fields, evaluated by sweny with no model call.
|
|
496
|
+
* Grammar and semantics: `when.ts`.
|
|
497
|
+
*/
|
|
498
|
+
export interface WhenExpression {
|
|
499
|
+
expr: string;
|
|
500
|
+
}
|
|
501
|
+
/** An edge condition: natural language (model-evaluated) or a `{ expr }` expression. */
|
|
502
|
+
export type EdgeWhen = string | WhenExpression;
|
|
492
503
|
/** An edge connecting two nodes */
|
|
493
504
|
export interface Edge {
|
|
494
505
|
from: string;
|
|
495
506
|
to: string;
|
|
496
|
-
/**
|
|
497
|
-
|
|
507
|
+
/**
|
|
508
|
+
* Condition for taking this edge. A string is natural language, evaluated at
|
|
509
|
+
* runtime by the workflow's harness. `{ expr }` is a deterministic expression
|
|
510
|
+
* evaluated by sweny with no model call.
|
|
511
|
+
*/
|
|
512
|
+
when?: EdgeWhen;
|
|
498
513
|
/** Max times this edge can be followed (enables retry loops). Default: unlimited. */
|
|
499
514
|
max_iterations?: number;
|
|
500
515
|
}
|
|
@@ -537,6 +552,11 @@ export interface Workflow {
|
|
|
537
552
|
* `budget` may only narrow it. The CLI's `--max-tokens` / `--max-cost` tighten it.
|
|
538
553
|
*/
|
|
539
554
|
budget?: Budget;
|
|
555
|
+
/**
|
|
556
|
+
* Decision model for route choices (#357). `shadow` asks it alongside the
|
|
557
|
+
* agent and logs agreement; the route is always the agent's. Default: off.
|
|
558
|
+
*/
|
|
559
|
+
decider?: DeciderConfig;
|
|
540
560
|
/**
|
|
541
561
|
* What prior results a node's prompt receives (#337). `bounded` (default):
|
|
542
562
|
* only nodes it can depend on (graph ancestors, nodes named by `requires`
|
|
@@ -751,6 +771,8 @@ export interface ExecutionTrace {
|
|
|
751
771
|
edges: TraceEdge[];
|
|
752
772
|
/** Resolved sources keyed by field path (e.g. "nodes.gather.instruction") */
|
|
753
773
|
sources: Record<string, _ResolvedSource>;
|
|
774
|
+
/** Shadow-mode decider records, one per route decision (#357). Metadata only. Absent when the decider is off. */
|
|
775
|
+
decisions?: DeciderRecord[];
|
|
754
776
|
}
|
|
755
777
|
/** Result of execute() — final node results + full execution trace */
|
|
756
778
|
export interface ExecutionResult {
|
package/dist/when.d.ts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic `when` expressions (#461).
|
|
3
|
+
*
|
|
4
|
+
* An edge's `when` is either natural language (a model picks the edge at
|
|
5
|
+
* runtime) or `{ expr: "..." }`, a small boolean expression over prior nodes'
|
|
6
|
+
* declared output fields that sweny evaluates itself, with no model call.
|
|
7
|
+
*
|
|
8
|
+
* Grammar (precedence low to high):
|
|
9
|
+
*
|
|
10
|
+
* expr := or
|
|
11
|
+
* or := and ( "||" and )*
|
|
12
|
+
* and := unary ( "&&" unary )*
|
|
13
|
+
* unary := "!" unary | comparison
|
|
14
|
+
* comparison := operand ( ( "==" | "!=" | "<" | "<=" | ">" | ">=" | "in" ) operand )?
|
|
15
|
+
* operand := literal | list | path | "exists" path | "(" expr ")"
|
|
16
|
+
* list := "[" ( literal ( "," literal )* )? "]"
|
|
17
|
+
* literal := number | 'string' | "string" | true | false | null
|
|
18
|
+
* path := ident ( "." ident )+ (node id, then field, then nested fields)
|
|
19
|
+
*
|
|
20
|
+
* Semantics are strict and total. There is no coercion and no truthiness:
|
|
21
|
+
* `&&`, `||`, `!` and the expression itself need booleans; `<` and friends
|
|
22
|
+
* need two numbers or two strings; `in` needs a list on the right. A missing
|
|
23
|
+
* field (undefined, or a node that did not run or did not succeed) or a type
|
|
24
|
+
* mismatch makes the WHOLE expression false and is reported, so a negation
|
|
25
|
+
* can never turn a missing field into a silent true. `exists path` is the
|
|
26
|
+
* one explicit presence test: true when the value is present and not null,
|
|
27
|
+
* never a warning. `&&` and `||` short-circuit, so `exists a.x && a.x > 0`
|
|
28
|
+
* is safe.
|
|
29
|
+
*
|
|
30
|
+
* Pure module: no I/O, no eval, no Function, browser-safe. Strings in the
|
|
31
|
+
* routed data are compared as data only; nothing in them is ever parsed.
|
|
32
|
+
*/
|
|
33
|
+
import type { EdgeWhen, JSONSchema, WhenExpression } from "./types.js";
|
|
34
|
+
/** Longest expression source accepted. Routing conditions are short. */
|
|
35
|
+
export declare const WHEN_EXPR_MAX_LENGTH = 2000;
|
|
36
|
+
/** True when an edge `when` is the structured `{ expr }` form. */
|
|
37
|
+
export declare function isWhenExpression(when: unknown): when is WhenExpression;
|
|
38
|
+
/** Human-readable label for a `when`: the NL text or the expression source. */
|
|
39
|
+
export declare function whenLabel(when: EdgeWhen | undefined): string | undefined;
|
|
40
|
+
export type Literal = string | number | boolean | null;
|
|
41
|
+
export type ExprNode = {
|
|
42
|
+
kind: "literal";
|
|
43
|
+
value: Literal;
|
|
44
|
+
} | {
|
|
45
|
+
kind: "list";
|
|
46
|
+
items: Literal[];
|
|
47
|
+
} | {
|
|
48
|
+
kind: "path";
|
|
49
|
+
segments: string[];
|
|
50
|
+
} | {
|
|
51
|
+
kind: "exists";
|
|
52
|
+
path: {
|
|
53
|
+
kind: "path";
|
|
54
|
+
segments: string[];
|
|
55
|
+
};
|
|
56
|
+
} | {
|
|
57
|
+
kind: "not";
|
|
58
|
+
operand: ExprNode;
|
|
59
|
+
} | {
|
|
60
|
+
kind: "and" | "or";
|
|
61
|
+
left: ExprNode;
|
|
62
|
+
right: ExprNode;
|
|
63
|
+
} | {
|
|
64
|
+
kind: "cmp";
|
|
65
|
+
op: CmpOp;
|
|
66
|
+
left: ExprNode;
|
|
67
|
+
right: ExprNode;
|
|
68
|
+
};
|
|
69
|
+
export type CmpOp = "==" | "!=" | "<" | "<=" | ">" | ">=" | "in";
|
|
70
|
+
export declare class ExpressionSyntaxError extends Error {
|
|
71
|
+
readonly position: number;
|
|
72
|
+
constructor(message: string, position: number);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Parse an expression source into an AST. Throws `ExpressionSyntaxError` on
|
|
76
|
+
* any syntax problem, including an empty source, an over-long source, or
|
|
77
|
+
* nesting deeper than the cap.
|
|
78
|
+
*/
|
|
79
|
+
export declare function parseExpression(src: string): ExprNode;
|
|
80
|
+
/**
|
|
81
|
+
* Per-node data an expression may read, keyed by node id. A node that did not
|
|
82
|
+
* run or did not succeed is absent, so every path into it reads as missing.
|
|
83
|
+
*/
|
|
84
|
+
export type ExpressionScope = Record<string, Record<string, unknown> | undefined>;
|
|
85
|
+
export interface ExpressionResult {
|
|
86
|
+
/** The edge is taken only when this is true. */
|
|
87
|
+
value: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Why the expression was forced false: a missing field or a type mismatch.
|
|
90
|
+
* Absent when it evaluated normally (to true or false).
|
|
91
|
+
*/
|
|
92
|
+
problem?: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Evaluate a parsed expression against node outputs. Never throws: a missing
|
|
96
|
+
* field or a type mismatch yields `{ value: false, problem }`.
|
|
97
|
+
*/
|
|
98
|
+
export declare function evaluateExpression(ast: ExprNode, scope: ExpressionScope): ExpressionResult;
|
|
99
|
+
/**
|
|
100
|
+
* Check an expression against the workflow it routes. Returns one message per
|
|
101
|
+
* problem, empty when the expression is valid:
|
|
102
|
+
* - the source must parse;
|
|
103
|
+
* - every path's node must be the edge's source or one of its ancestors;
|
|
104
|
+
* - that node must declare `output.properties`, and the field (and any
|
|
105
|
+
* nested field) must be declared there;
|
|
106
|
+
* - a literal compared with a declared field must fit its declared type,
|
|
107
|
+
* and a string literal compared with an enum field must be in the enum;
|
|
108
|
+
* - a field used where a boolean is needed must be declared boolean.
|
|
109
|
+
*/
|
|
110
|
+
export declare function checkExpression(src: string, ctx: {
|
|
111
|
+
from: string;
|
|
112
|
+
ancestors: Set<string>;
|
|
113
|
+
outputs: Record<string, JSONSchema | undefined>;
|
|
114
|
+
}): string[];
|