@pipelex/mthds-ui 0.27.0 → 0.29.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 +19 -5
- package/dist/{chunk-VCO4GZDZ.js → chunk-3I3ZPYMW.js} +13 -1
- package/dist/chunk-3I3ZPYMW.js.map +1 -0
- package/dist/{chunk-XBHDA3PQ.js → chunk-Y46574OW.js} +2 -2
- package/dist/{chunk-K3BWHQVX.js → chunk-ZTXSDTVF.js} +81 -34
- package/dist/chunk-ZTXSDTVF.js.map +1 -0
- package/dist/form/react/RunPanel.css +1 -3
- package/dist/form/react/index.d.ts +5 -5
- package/dist/form/react/index.js +2 -2
- package/dist/form/react/index.js.map +1 -1
- package/dist/graph/index.d.ts +24 -9
- package/dist/graph/index.js +11 -3
- package/dist/graph/react/graph-core.css +12 -0
- package/dist/graph/react/index.d.ts +113 -45
- package/dist/graph/react/index.js +333 -283
- package/dist/graph/react/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +11 -3
- package/dist/standalone/graph-standalone.html +420 -114
- package/dist/standalone/graph-viewer.css +13 -1
- package/dist/standalone/graph-viewer.js +406 -112
- package/dist/static-graph/index.d.ts +32 -9
- package/dist/static-graph/index.js +709 -88
- package/dist/static-graph/index.js.map +1 -1
- package/dist/{types-DgqW3Jg4.d.ts → types-BaFWy56P.d.ts} +106 -13
- package/package.json +2 -2
- package/dist/chunk-K3BWHQVX.js.map +0 -1
- package/dist/chunk-VCO4GZDZ.js.map +0 -1
- /package/dist/{chunk-XBHDA3PQ.js.map → chunk-Y46574OW.js.map} +0 -0
|
@@ -3,9 +3,11 @@ import {
|
|
|
3
3
|
parsePipeRef
|
|
4
4
|
} from "../chunk-2N65P32H.js";
|
|
5
5
|
import {
|
|
6
|
+
BINDING_STEP_TYPE,
|
|
6
7
|
KNOWN_PIPE_TYPES,
|
|
8
|
+
isBindingStepSpec,
|
|
7
9
|
isPluralMultiplicity
|
|
8
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-3I3ZPYMW.js";
|
|
9
11
|
import {
|
|
10
12
|
__spreadProps,
|
|
11
13
|
__spreadValues
|
|
@@ -33,28 +35,117 @@ function boolOrNull(value) {
|
|
|
33
35
|
|
|
34
36
|
// src/static-graph/conceptRefs.ts
|
|
35
37
|
var NATIVE_DOMAIN = "native";
|
|
36
|
-
var
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
38
|
+
var field = (type) => ({
|
|
39
|
+
type,
|
|
40
|
+
conceptRef: null,
|
|
41
|
+
itemType: null,
|
|
42
|
+
itemConceptRef: null
|
|
43
|
+
});
|
|
44
|
+
var conceptField = (conceptRef) => ({
|
|
45
|
+
type: "concept",
|
|
46
|
+
conceptRef,
|
|
47
|
+
itemType: null,
|
|
48
|
+
itemConceptRef: null
|
|
49
|
+
});
|
|
50
|
+
var conceptListField = (itemConceptRef) => ({
|
|
51
|
+
type: "list",
|
|
52
|
+
conceptRef: null,
|
|
53
|
+
itemType: "concept",
|
|
54
|
+
itemConceptRef
|
|
55
|
+
});
|
|
56
|
+
var NATIVE_CONCEPTS = {
|
|
57
|
+
Dynamic: { description: "A dynamic concept", fields: null },
|
|
58
|
+
Text: { description: "A text", fields: { text: field("text") } },
|
|
59
|
+
Markdown: {
|
|
60
|
+
description: "A text written in Markdown",
|
|
61
|
+
refines: "native.Text",
|
|
62
|
+
fields: { text: field("text") }
|
|
63
|
+
},
|
|
64
|
+
Image: {
|
|
65
|
+
description: "An image",
|
|
66
|
+
fields: {
|
|
67
|
+
url: field("text"),
|
|
68
|
+
public_url: field("text"),
|
|
69
|
+
source_prompt: field("text"),
|
|
70
|
+
source_negative_prompt: field("text"),
|
|
71
|
+
caption: field("text"),
|
|
72
|
+
mime_type: field("text"),
|
|
73
|
+
width: field("integer"),
|
|
74
|
+
height: field("integer"),
|
|
75
|
+
filename: field("text")
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
Document: {
|
|
79
|
+
description: "A document",
|
|
80
|
+
fields: {
|
|
81
|
+
url: field("text"),
|
|
82
|
+
public_url: field("text"),
|
|
83
|
+
mime_type: field("text"),
|
|
84
|
+
filename: field("text"),
|
|
85
|
+
title: field("text"),
|
|
86
|
+
snippet: field("text")
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
Html: {
|
|
90
|
+
description: "HTML content",
|
|
91
|
+
fields: { inner_html: field("text"), css_class: field("text") }
|
|
92
|
+
},
|
|
93
|
+
TextAndImages: {
|
|
94
|
+
description: "A text and an image",
|
|
95
|
+
fields: {
|
|
96
|
+
text: conceptField("native.Text"),
|
|
97
|
+
images: conceptListField("native.Image"),
|
|
98
|
+
raw_html: field("text")
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
Number: { description: "A number", fields: { number: field("number") } },
|
|
102
|
+
YesNo: {
|
|
103
|
+
description: "The answer to a yes/no question",
|
|
104
|
+
fields: { yes_no: field("boolean"), probability: field("number") }
|
|
105
|
+
},
|
|
106
|
+
Choice: {
|
|
107
|
+
description: "One option picked out of a declared set",
|
|
108
|
+
fields: { choice: field("text"), confidence: field("number"), probabilities: field("dict") }
|
|
109
|
+
},
|
|
110
|
+
Rating: {
|
|
111
|
+
description: "A position on an ordered scale of described levels",
|
|
112
|
+
fields: {
|
|
113
|
+
level: field("integer"),
|
|
114
|
+
confidence: field("number"),
|
|
115
|
+
probabilities: field("dict"),
|
|
116
|
+
position: field("number")
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
Date: {
|
|
120
|
+
description: "A calendar date, optionally with a time of day \u2014 as precise as its source states.",
|
|
121
|
+
fields: { date: field("date"), time: field("time") }
|
|
122
|
+
},
|
|
123
|
+
Time: {
|
|
124
|
+
description: "A time of day, optionally with a UTC offset \u2014 as precise as its source states.",
|
|
125
|
+
fields: { time: field("time") }
|
|
126
|
+
},
|
|
127
|
+
Page: {
|
|
128
|
+
description: "The content of a page of a document, comprising text and linked images and an optional page view image",
|
|
129
|
+
fields: {
|
|
130
|
+
text_and_images: conceptField("native.TextAndImages"),
|
|
131
|
+
page_view: conceptField("native.Image")
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
JSON: { description: "A JSON object", fields: { json_obj: field("dict") } },
|
|
135
|
+
SearchResult: {
|
|
136
|
+
description: "A search result with answer and sources",
|
|
137
|
+
fields: { answer: field("text"), sources: conceptListField("native.Document") }
|
|
138
|
+
},
|
|
139
|
+
Anything: { description: "Anything", fields: null },
|
|
140
|
+
Composite: { description: "A named composition of contents", fields: null }
|
|
52
141
|
};
|
|
53
|
-
var NATIVE_CONCEPT_CODES = new Set(
|
|
54
|
-
Object.keys(NATIVE_CONCEPT_DESCRIPTIONS)
|
|
55
|
-
);
|
|
142
|
+
var NATIVE_CONCEPT_CODES = new Set(Object.keys(NATIVE_CONCEPTS));
|
|
56
143
|
function isNativeConceptCode(code) {
|
|
57
|
-
return Object.hasOwn(
|
|
144
|
+
return Object.hasOwn(NATIVE_CONCEPTS, code);
|
|
145
|
+
}
|
|
146
|
+
function nativeConceptFields(code) {
|
|
147
|
+
const definition = NATIVE_CONCEPTS[code];
|
|
148
|
+
return definition.fields;
|
|
58
149
|
}
|
|
59
150
|
var CONCEPT_REF_RE = /^(?:([A-Za-z0-9_][A-Za-z0-9_.]*)\.)?([A-Za-z0-9_]+)(?:\[(\d*)\])?([?!])?$/;
|
|
60
151
|
function presenceFromSymbol(symbol) {
|
|
@@ -76,40 +167,50 @@ function parseConceptRef(raw) {
|
|
|
76
167
|
}
|
|
77
168
|
var INPUT_SLOT_KEYS = /* @__PURE__ */ new Set(["concept", "hints"]);
|
|
78
169
|
var CONCEPT_CODE_RE = /^[A-Z][A-Za-z0-9]*$/;
|
|
79
|
-
function
|
|
80
|
-
|
|
81
|
-
return
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
170
|
+
function isConceptCodeRef(raw) {
|
|
171
|
+
const parts = parseConceptRef(raw);
|
|
172
|
+
return parts !== null && CONCEPT_CODE_RE.test(parts.code);
|
|
173
|
+
}
|
|
174
|
+
function unquotedDottedInputNames(name, raw) {
|
|
175
|
+
if (!isPlainObject(raw) || raw.concept !== void 0) return null;
|
|
176
|
+
const keys = Object.keys(raw);
|
|
177
|
+
if (keys.length === 0) return null;
|
|
178
|
+
const dottedNames = [];
|
|
179
|
+
for (const key of keys) {
|
|
180
|
+
const value = raw[key];
|
|
181
|
+
const dottedName = `${name}.${key}`;
|
|
182
|
+
if (isConceptCodeRef(value) || isPlainObject(value) && isConceptCodeRef(value.concept)) {
|
|
183
|
+
dottedNames.push(dottedName);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
const nested = unquotedDottedInputNames(dottedName, value);
|
|
187
|
+
if (nested === null) return null;
|
|
188
|
+
dottedNames.push(...nested);
|
|
189
|
+
}
|
|
190
|
+
return dottedNames;
|
|
85
191
|
}
|
|
86
192
|
function parseInputSlot(raw) {
|
|
87
193
|
if (!isPlainObject(raw)) {
|
|
88
|
-
return {
|
|
89
|
-
ref: parseConceptRef(raw),
|
|
90
|
-
missingConcept: false,
|
|
91
|
-
unknownKeys: [],
|
|
92
|
-
dottedName: false
|
|
93
|
-
};
|
|
194
|
+
return { ref: parseConceptRef(raw), missingConcept: false, unknownKeys: [] };
|
|
94
195
|
}
|
|
95
|
-
const unknownKeys = Object.keys(raw).filter((key) => !INPUT_SLOT_KEYS.has(key));
|
|
96
196
|
return {
|
|
97
197
|
ref: parseConceptRef(raw.concept),
|
|
98
198
|
missingConcept: raw.concept === void 0,
|
|
99
|
-
unknownKeys
|
|
100
|
-
dottedName: looksLikeUnquotedDottedName(raw, unknownKeys)
|
|
199
|
+
unknownKeys: Object.keys(raw).filter((key) => !INPUT_SLOT_KEYS.has(key))
|
|
101
200
|
};
|
|
102
201
|
}
|
|
103
202
|
function qualifiedStructureClassName(domain, code) {
|
|
104
203
|
return `${domain.replaceAll(".", "\xB7")}__${code}`;
|
|
105
204
|
}
|
|
106
205
|
function nativeConceptInfo(code) {
|
|
206
|
+
var _a;
|
|
207
|
+
const definition = NATIVE_CONCEPTS[code];
|
|
107
208
|
return {
|
|
108
209
|
code,
|
|
109
210
|
domain_code: NATIVE_DOMAIN,
|
|
110
|
-
description:
|
|
211
|
+
description: definition.description,
|
|
111
212
|
structure_class_name: `${code}Content`,
|
|
112
|
-
refines: null
|
|
213
|
+
refines: (_a = definition.refines) != null ? _a : null
|
|
113
214
|
};
|
|
114
215
|
}
|
|
115
216
|
function stubConceptInfo(code, domain) {
|
|
@@ -146,12 +247,11 @@ function resolveStuffSpec(raw, currentDomain, localConcepts) {
|
|
|
146
247
|
return parts === null ? null : stuffSpecFromParts(parts, currentDomain, localConcepts);
|
|
147
248
|
}
|
|
148
249
|
function resolveInputSlot(raw, currentDomain, localConcepts) {
|
|
149
|
-
const { ref, missingConcept, unknownKeys
|
|
250
|
+
const { ref, missingConcept, unknownKeys } = parseInputSlot(raw);
|
|
150
251
|
return {
|
|
151
252
|
spec: ref === null ? null : stuffSpecFromParts(ref, currentDomain, localConcepts),
|
|
152
253
|
missingConcept,
|
|
153
|
-
unknownKeys
|
|
154
|
-
dottedName
|
|
254
|
+
unknownKeys
|
|
155
255
|
};
|
|
156
256
|
}
|
|
157
257
|
|
|
@@ -174,6 +274,25 @@ function stringArrayOrNull(value) {
|
|
|
174
274
|
if (!Array.isArray(value)) return null;
|
|
175
275
|
return value.filter((item) => typeof item === "string");
|
|
176
276
|
}
|
|
277
|
+
var PLAIN_NAME_RE = /^[a-z][a-z0-9_]*$/;
|
|
278
|
+
function bindingStepFor(dottedPath) {
|
|
279
|
+
const plainName = dottedPath.slice(dottedPath.lastIndexOf(".") + 1);
|
|
280
|
+
return `{ from = "${dottedPath}", result = "${plainName}" }`;
|
|
281
|
+
}
|
|
282
|
+
function dottedInputNameRemedy(dottedName) {
|
|
283
|
+
const root = dottedName.slice(0, dottedName.indexOf("."));
|
|
284
|
+
return `an input names one whole value, so its name cannot reach into a field with a dot; declare "${root}" with its whole concept and read the field through it, or have the calling sequence bind the field to a plain name with a binding step (${bindingStepFor(dottedName)}) and declare that name`;
|
|
285
|
+
}
|
|
286
|
+
function invalidInputNameReason(name) {
|
|
287
|
+
const segments = name.split(".");
|
|
288
|
+
if (segments.length > 1 && segments.every((segment) => PLAIN_NAME_RE.test(segment))) {
|
|
289
|
+
return `is not a plain input name: ${dottedInputNameRemedy(name)}`;
|
|
290
|
+
}
|
|
291
|
+
return "is not a plain input name, which is a lowercase letter followed by lowercase letters, digits and underscores";
|
|
292
|
+
}
|
|
293
|
+
function tomlKey(key) {
|
|
294
|
+
return /^[A-Za-z0-9_-]+$/.test(key) ? key : JSON.stringify(key);
|
|
295
|
+
}
|
|
177
296
|
function normalizeInputs(raw, pipeCode, ctx) {
|
|
178
297
|
const inputs = authoredRecord();
|
|
179
298
|
if (raw === void 0 || raw === null) return inputs;
|
|
@@ -187,26 +306,33 @@ function normalizeInputs(raw, pipeCode, ctx) {
|
|
|
187
306
|
return inputs;
|
|
188
307
|
}
|
|
189
308
|
for (const [name, slot] of Object.entries(raw)) {
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
ctx.domain,
|
|
193
|
-
ctx.concepts
|
|
194
|
-
);
|
|
195
|
-
if (dottedName) {
|
|
309
|
+
const path = `pipe.${pipeCode}.inputs.${tomlKey(name)}`;
|
|
310
|
+
if (!PLAIN_NAME_RE.test(name)) {
|
|
196
311
|
ctx.diagnostics.push({
|
|
197
312
|
severity: "warning",
|
|
198
|
-
code: "invalid-
|
|
199
|
-
message: `pipe "${pipeCode}": input "${name}"
|
|
200
|
-
path
|
|
313
|
+
code: "invalid-input-name",
|
|
314
|
+
message: `pipe "${pipeCode}": input "${name}" ${invalidInputNameReason(name)} \u2014 skipped`,
|
|
315
|
+
path
|
|
201
316
|
});
|
|
202
317
|
continue;
|
|
203
318
|
}
|
|
319
|
+
const dottedNames = unquotedDottedInputNames(name, slot);
|
|
320
|
+
if (dottedNames !== null) {
|
|
321
|
+
ctx.diagnostics.push({
|
|
322
|
+
severity: "warning",
|
|
323
|
+
code: "invalid-input-name",
|
|
324
|
+
message: `pipe "${pipeCode}": input "${name}" is a table with no "concept", which is how TOML reads the unquoted dotted input ${dottedNames.length === 1 ? "name" : "names"} ${dottedNames.map((dotted) => `"${dotted}"`).join(", ")}; ${dottedInputNameRemedy(dottedNames[0])} \u2014 skipped`,
|
|
325
|
+
path
|
|
326
|
+
});
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
const { spec, missingConcept, unknownKeys } = resolveInputSlot(slot, ctx.domain, ctx.concepts);
|
|
204
330
|
if (unknownKeys.length > 0) {
|
|
205
331
|
ctx.diagnostics.push({
|
|
206
332
|
severity: "warning",
|
|
207
333
|
code: "unknown-input-slot-key",
|
|
208
334
|
message: `pipe "${pipeCode}": input "${name}" declares ${unknownKeys.map((key) => `"${key}"`).join(", ")}, which the input slot form does not define \u2014 ignored here, and the runtime refuses the bundle`,
|
|
209
|
-
path
|
|
335
|
+
path
|
|
210
336
|
});
|
|
211
337
|
}
|
|
212
338
|
if (spec === null) {
|
|
@@ -214,7 +340,7 @@ function normalizeInputs(raw, pipeCode, ctx) {
|
|
|
214
340
|
severity: "warning",
|
|
215
341
|
code: "invalid-concept-ref",
|
|
216
342
|
message: missingConcept ? `pipe "${pipeCode}": input "${name}" is a slot table with no "concept" \u2014 the key is required \u2014 skipped` : `pipe "${pipeCode}": input "${name}" has an uninterpretable concept ref \u2014 skipped`,
|
|
217
|
-
path
|
|
343
|
+
path
|
|
218
344
|
});
|
|
219
345
|
continue;
|
|
220
346
|
}
|
|
@@ -235,7 +361,7 @@ function normalizeOutput(raw, pipeCode, ctx) {
|
|
|
235
361
|
}
|
|
236
362
|
function normalizeSubPipe(raw, pipeCode, path, ctx) {
|
|
237
363
|
var _a;
|
|
238
|
-
if (
|
|
364
|
+
if (strOrNull(raw.pipe) === null) {
|
|
239
365
|
ctx.diagnostics.push({
|
|
240
366
|
severity: "warning",
|
|
241
367
|
code: "invalid-sub-pipe",
|
|
@@ -266,21 +392,168 @@ function normalizeSubPipe(raw, pipeCode, path, ctx) {
|
|
|
266
392
|
batch_params: batchParams
|
|
267
393
|
};
|
|
268
394
|
}
|
|
269
|
-
|
|
395
|
+
var BINDING_PATH_RE = /^[A-Za-z][A-Za-z0-9_]*(?:\.[A-Za-z][A-Za-z0-9_]*)*$/;
|
|
396
|
+
var BINDING_STEP_KEYS = /* @__PURE__ */ new Set(["from", "result"]);
|
|
397
|
+
var PRIVATE_BINDING_NAME_PREFIX = "_bound_";
|
|
398
|
+
function normalizeBindingStep(raw, pipeCode, path, ctx) {
|
|
399
|
+
const skip = (why) => {
|
|
400
|
+
ctx.diagnostics.push({
|
|
401
|
+
severity: "warning",
|
|
402
|
+
code: "invalid-binding-step",
|
|
403
|
+
message: `pipe "${pipeCode}": binding step ${why} \u2014 skipped`,
|
|
404
|
+
path
|
|
405
|
+
});
|
|
406
|
+
return null;
|
|
407
|
+
};
|
|
408
|
+
if (raw.pipe !== void 0) return skip(`carries both "from" and "pipe"`);
|
|
409
|
+
const fromPath = strOrNull(raw.from);
|
|
410
|
+
if (fromPath === null || !BINDING_PATH_RE.test(fromPath)) {
|
|
411
|
+
return skip(`has a "from" that is not a path of identifiers separated by dots`);
|
|
412
|
+
}
|
|
413
|
+
const result = strOrNull(raw.result);
|
|
414
|
+
if (result === null) return skip(`binds "${fromPath}" under no "result"`);
|
|
415
|
+
if (!PLAIN_NAME_RE.test(result)) {
|
|
416
|
+
return skip(
|
|
417
|
+
result.startsWith(PRIVATE_BINDING_NAME_PREFIX) ? `binds "${fromPath}" under "${result}", which takes the prefix "${PRIVATE_BINDING_NAME_PREFIX}" the runtime reserves for its own names` : `binds "${fromPath}" under "${result}", which is not a plain name (lowercase letters, digits and underscores, starting with a letter)`
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
const extraKeys = Object.keys(raw).filter((key) => !BINDING_STEP_KEYS.has(key));
|
|
421
|
+
if (extraKeys.length > 0) {
|
|
422
|
+
ctx.diagnostics.push({
|
|
423
|
+
severity: "warning",
|
|
424
|
+
code: "invalid-binding-step",
|
|
425
|
+
message: `pipe "${pipeCode}": binding step of "${fromPath}" carries ${extraKeys.map((key) => `"${key}"`).join(", ")}, which a binding step does not take \u2014 ignored`,
|
|
426
|
+
path
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
return { from_path: fromPath, output_name: result, is_dotted_batch_over: false };
|
|
430
|
+
}
|
|
431
|
+
function namesInSequence(inputNames, rawSteps) {
|
|
432
|
+
const names = new Set(inputNames);
|
|
433
|
+
for (const step of rawSteps) {
|
|
434
|
+
if (!isPlainObject(step)) continue;
|
|
435
|
+
if (step.from !== void 0) {
|
|
436
|
+
const fromPath = strOrNull(step.from);
|
|
437
|
+
if (fromPath !== null) names.add(fromPath.split(".")[0]);
|
|
438
|
+
const result = strOrNull(step.result);
|
|
439
|
+
if (result !== null) names.add(result);
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
for (const name of [strOrNull(step.result), strOrNull(step.batch_as)]) {
|
|
443
|
+
if (name !== null) names.add(name);
|
|
444
|
+
}
|
|
445
|
+
const batchOver = strOrNull(step.batch_over);
|
|
446
|
+
if (batchOver !== null) names.add(batchOver.split(".")[0]);
|
|
447
|
+
}
|
|
448
|
+
return names;
|
|
449
|
+
}
|
|
450
|
+
function makePrivateBindingName(path, takenNames) {
|
|
451
|
+
const baseName = `${PRIVATE_BINDING_NAME_PREFIX}${path.replaceAll(".", "_")}`;
|
|
452
|
+
let name = baseName;
|
|
453
|
+
for (let suffix = 2; takenNames.has(name); suffix++) name = `${baseName}_${suffix}`;
|
|
454
|
+
return name;
|
|
455
|
+
}
|
|
456
|
+
function normalizeSequenceSteps(raw, pipeCode, inputNames, ctx) {
|
|
457
|
+
if (!Array.isArray(raw)) {
|
|
458
|
+
if (raw !== void 0) {
|
|
459
|
+
ctx.diagnostics.push({
|
|
460
|
+
severity: "warning",
|
|
461
|
+
code: "invalid-pipe-entry",
|
|
462
|
+
message: `pipe "${pipeCode}": steps is not an array \u2014 treated as empty`,
|
|
463
|
+
path: `pipe.${pipeCode}.steps`
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
return [];
|
|
467
|
+
}
|
|
468
|
+
const takenNames = namesInSequence(inputNames, raw);
|
|
469
|
+
const steps = [];
|
|
470
|
+
raw.forEach((entry, index) => {
|
|
471
|
+
var _a;
|
|
472
|
+
const path = `pipe.${pipeCode}.steps[${index}]`;
|
|
473
|
+
if (isPlainObject(entry) && entry.from !== void 0) {
|
|
474
|
+
const binding = normalizeBindingStep(entry, pipeCode, path, ctx);
|
|
475
|
+
if (binding !== null) steps.push(binding);
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
if (!isPlainObject(entry)) {
|
|
479
|
+
ctx.diagnostics.push({
|
|
480
|
+
severity: "warning",
|
|
481
|
+
code: "invalid-sub-pipe",
|
|
482
|
+
message: `pipe "${pipeCode}": sub-pipe entry without a "pipe" ref \u2014 skipped`,
|
|
483
|
+
path
|
|
484
|
+
});
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
const step = normalizeSubPipe(entry, pipeCode, path, ctx);
|
|
488
|
+
if (step === null) return;
|
|
489
|
+
const listName = (_a = step.batch_params) == null ? void 0 : _a.input_list_stuff_name;
|
|
490
|
+
if (step.batch_params != null && listName !== void 0 && listName.includes(".")) {
|
|
491
|
+
if (!BINDING_PATH_RE.test(listName)) {
|
|
492
|
+
ctx.diagnostics.push({
|
|
493
|
+
severity: "warning",
|
|
494
|
+
code: "invalid-binding-step",
|
|
495
|
+
message: `pipe "${pipeCode}": dotted batch_over "${listName}" is not a path of identifiers separated by dots \u2014 batching over it as a name`,
|
|
496
|
+
path
|
|
497
|
+
});
|
|
498
|
+
} else {
|
|
499
|
+
const privateName = makePrivateBindingName(listName, takenNames);
|
|
500
|
+
takenNames.add(privateName);
|
|
501
|
+
steps.push({ from_path: listName, output_name: privateName, is_dotted_batch_over: true });
|
|
502
|
+
step.batch_params = __spreadProps(__spreadValues({}, step.batch_params), { input_list_stuff_name: privateName });
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
steps.push(step);
|
|
506
|
+
});
|
|
507
|
+
return steps;
|
|
508
|
+
}
|
|
509
|
+
function normalizeBranchList(raw, pipeCode, ctx) {
|
|
270
510
|
if (!Array.isArray(raw)) {
|
|
271
511
|
if (raw !== void 0) {
|
|
272
512
|
ctx.diagnostics.push({
|
|
273
513
|
severity: "warning",
|
|
274
514
|
code: "invalid-pipe-entry",
|
|
275
|
-
message: `pipe "${pipeCode}":
|
|
276
|
-
path: `pipe.${pipeCode}
|
|
515
|
+
message: `pipe "${pipeCode}": branches is not an array \u2014 treated as empty`,
|
|
516
|
+
path: `pipe.${pipeCode}.branches`
|
|
277
517
|
});
|
|
278
518
|
}
|
|
279
519
|
return [];
|
|
280
520
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
521
|
+
const branches = [];
|
|
522
|
+
raw.forEach((entry, index) => {
|
|
523
|
+
var _a;
|
|
524
|
+
const path = `pipe.${pipeCode}.branches[${index}]`;
|
|
525
|
+
if (!isPlainObject(entry)) {
|
|
526
|
+
ctx.diagnostics.push({
|
|
527
|
+
severity: "warning",
|
|
528
|
+
code: "invalid-sub-pipe",
|
|
529
|
+
message: `pipe "${pipeCode}": sub-pipe entry without a "pipe" ref \u2014 skipped`,
|
|
530
|
+
path
|
|
531
|
+
});
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
if (entry.from !== void 0) {
|
|
535
|
+
ctx.diagnostics.push({
|
|
536
|
+
severity: "warning",
|
|
537
|
+
code: "invalid-binding-step",
|
|
538
|
+
message: `pipe "${pipeCode}": a parallel branch cannot be a binding step \u2014 bind in a sequence step before the parallel \u2014 skipped`,
|
|
539
|
+
path
|
|
540
|
+
});
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
const branch = normalizeSubPipe(entry, pipeCode, path, ctx);
|
|
544
|
+
if (branch === null) return;
|
|
545
|
+
if ((_a = branch.batch_params) == null ? void 0 : _a.input_list_stuff_name.includes(".")) {
|
|
546
|
+
ctx.diagnostics.push({
|
|
547
|
+
severity: "warning",
|
|
548
|
+
code: "invalid-binding-step",
|
|
549
|
+
message: `pipe "${pipeCode}": a parallel branch cannot batch over the dotted path "${branch.batch_params.input_list_stuff_name}" \u2014 bind it in a sequence step before the parallel \u2014 skipped`,
|
|
550
|
+
path
|
|
551
|
+
});
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
branches.push(branch);
|
|
555
|
+
});
|
|
556
|
+
return branches;
|
|
284
557
|
}
|
|
285
558
|
function normalizeConstructField(value) {
|
|
286
559
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || Array.isArray(value)) {
|
|
@@ -306,11 +579,36 @@ function normalizeConstruct(raw) {
|
|
|
306
579
|
if (!isPlainObject(raw)) return null;
|
|
307
580
|
const fields = {};
|
|
308
581
|
for (const [name, value] of Object.entries(raw)) {
|
|
309
|
-
const
|
|
310
|
-
if (
|
|
582
|
+
const field2 = normalizeConstructField(value);
|
|
583
|
+
if (field2 !== null) fields[name] = field2;
|
|
311
584
|
}
|
|
312
585
|
return Object.keys(fields).length > 0 ? { fields } : null;
|
|
313
586
|
}
|
|
587
|
+
function normalizeJudgmentQuestion(raw) {
|
|
588
|
+
var _a, _b;
|
|
589
|
+
const instructions = (_b = (_a = strOrNull(raw.question)) != null ? _a : strOrNull(raw.prompt)) != null ? _b : "";
|
|
590
|
+
if (isPlainObject(raw.options)) {
|
|
591
|
+
const options = {};
|
|
592
|
+
for (const [key, description] of Object.entries(raw.options)) {
|
|
593
|
+
options[key] = typeof description === "string" ? description : null;
|
|
594
|
+
}
|
|
595
|
+
return { kind: "choice", instructions, options };
|
|
596
|
+
}
|
|
597
|
+
if (Array.isArray(raw.levels)) {
|
|
598
|
+
return {
|
|
599
|
+
kind: "rating",
|
|
600
|
+
instructions,
|
|
601
|
+
levels: raw.levels.filter((level) => typeof level === "string")
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
const criteria = isPlainObject(raw.criteria) ? raw.criteria : {};
|
|
605
|
+
return {
|
|
606
|
+
kind: "yes_no",
|
|
607
|
+
instructions,
|
|
608
|
+
yes_criterion: strOrNull(criteria.yes),
|
|
609
|
+
no_criterion: strOrNull(criteria.no)
|
|
610
|
+
};
|
|
611
|
+
}
|
|
314
612
|
var SIGNATURE_ONLY_KEYS = /* @__PURE__ */ new Set([
|
|
315
613
|
"description",
|
|
316
614
|
"inputs",
|
|
@@ -343,7 +641,7 @@ function resolvePipeTypeTag(code, raw, ctx) {
|
|
|
343
641
|
return null;
|
|
344
642
|
}
|
|
345
643
|
function normalizePipe(code, raw, ctx) {
|
|
346
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
644
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
|
|
347
645
|
const typeValue = resolvePipeTypeTag(code, raw, ctx);
|
|
348
646
|
if (typeValue === null) return null;
|
|
349
647
|
const type = typeValue;
|
|
@@ -359,13 +657,18 @@ function normalizePipe(code, raw, ctx) {
|
|
|
359
657
|
return __spreadProps(__spreadValues({}, base), {
|
|
360
658
|
type,
|
|
361
659
|
pipe_category: "PipeController",
|
|
362
|
-
sequential_sub_pipes:
|
|
660
|
+
sequential_sub_pipes: normalizeSequenceSteps(
|
|
661
|
+
raw.steps,
|
|
662
|
+
code,
|
|
663
|
+
Object.keys(base.inputs),
|
|
664
|
+
ctx
|
|
665
|
+
)
|
|
363
666
|
});
|
|
364
667
|
case "PipeParallel":
|
|
365
668
|
return __spreadProps(__spreadValues({}, base), {
|
|
366
669
|
type,
|
|
367
670
|
pipe_category: "PipeController",
|
|
368
|
-
parallel_sub_pipes:
|
|
671
|
+
parallel_sub_pipes: normalizeBranchList(raw.branches, code, ctx),
|
|
369
672
|
add_each_output: raw.add_each_output === true,
|
|
370
673
|
combined_output: strOrNull(raw.combined_output)
|
|
371
674
|
});
|
|
@@ -527,6 +830,24 @@ function normalizePipe(code, raw, ctx) {
|
|
|
527
830
|
}
|
|
528
831
|
case "PipeFunc":
|
|
529
832
|
return __spreadProps(__spreadValues({}, base), { type, pipe_category: "PipeOperator" });
|
|
833
|
+
case "PipeJudge":
|
|
834
|
+
return __spreadProps(__spreadValues({}, base), {
|
|
835
|
+
type,
|
|
836
|
+
pipe_category: "PipeOperator",
|
|
837
|
+
judgment_choice: isPlainObject(raw.model) ? raw.model : strOrNull(raw.model),
|
|
838
|
+
judgment_question: normalizeJudgmentQuestion(raw),
|
|
839
|
+
threshold: typeof raw.threshold === "number" ? raw.threshold : null
|
|
840
|
+
});
|
|
841
|
+
case "PipeDocGen":
|
|
842
|
+
return __spreadProps(__spreadValues({}, base), {
|
|
843
|
+
type,
|
|
844
|
+
pipe_category: "PipeOperator",
|
|
845
|
+
doc_gen_format: (_m = strOrNull(raw.format)) != null ? _m : "",
|
|
846
|
+
doc_gen_choice: isPlainObject(raw.model) ? raw.model : strOrNull(raw.model),
|
|
847
|
+
template: strOrNull(raw.template),
|
|
848
|
+
template_file: strOrNull(raw.template_file),
|
|
849
|
+
filename: strOrNull(raw.filename)
|
|
850
|
+
});
|
|
530
851
|
case "PipeSignature": {
|
|
531
852
|
const signatureFor = strOrNull(raw.signature_for);
|
|
532
853
|
return __spreadProps(__spreadValues({}, base), {
|
|
@@ -580,6 +901,7 @@ function deriveJsonSchema(structure, title, description) {
|
|
|
580
901
|
for (const [name, spec] of Object.entries(structure)) {
|
|
581
902
|
if (typeof spec === "string") {
|
|
582
903
|
properties[name] = { type: "string", description: spec };
|
|
904
|
+
required.push(name);
|
|
583
905
|
continue;
|
|
584
906
|
}
|
|
585
907
|
if (!isPlainObject(spec)) continue;
|
|
@@ -611,10 +933,28 @@ function qualifyRefines(raw, domain, declaredCodes, conceptCode, diagnostics) {
|
|
|
611
933
|
}
|
|
612
934
|
return `${domain}.${parts.code}`;
|
|
613
935
|
}
|
|
936
|
+
function parseStructureFields(structure) {
|
|
937
|
+
const fields = authoredRecord();
|
|
938
|
+
for (const [name, spec] of Object.entries(structure)) {
|
|
939
|
+
if (typeof spec === "string") {
|
|
940
|
+
fields[name] = { type: "text", conceptRef: null, itemType: null, itemConceptRef: null };
|
|
941
|
+
continue;
|
|
942
|
+
}
|
|
943
|
+
if (!isPlainObject(spec)) continue;
|
|
944
|
+
fields[name] = {
|
|
945
|
+
type: strOrNull(spec.type),
|
|
946
|
+
conceptRef: strOrNull(spec.concept_ref),
|
|
947
|
+
itemType: strOrNull(spec.item_type),
|
|
948
|
+
itemConceptRef: strOrNull(spec.item_concept_ref)
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
return fields;
|
|
952
|
+
}
|
|
614
953
|
function parseConcepts(raw, domain, diagnostics) {
|
|
615
954
|
var _a, _b;
|
|
616
955
|
const concepts = authoredRecord();
|
|
617
|
-
|
|
956
|
+
const structures = authoredRecord();
|
|
957
|
+
if (raw === void 0) return { concepts, structures };
|
|
618
958
|
if (!isPlainObject(raw)) {
|
|
619
959
|
diagnostics.push({
|
|
620
960
|
severity: "warning",
|
|
@@ -622,7 +962,7 @@ function parseConcepts(raw, domain, diagnostics) {
|
|
|
622
962
|
message: "concept section is not a table \u2014 ignored",
|
|
623
963
|
path: "concept"
|
|
624
964
|
});
|
|
625
|
-
return concepts;
|
|
965
|
+
return { concepts, structures };
|
|
626
966
|
}
|
|
627
967
|
const declaredCodes = new Set(Object.keys(raw));
|
|
628
968
|
for (const [code, entry] of Object.entries(raw)) {
|
|
@@ -655,8 +995,13 @@ function parseConcepts(raw, domain, diagnostics) {
|
|
|
655
995
|
refines: qualifyRefines(entry.refines, domain, declaredCodes, code, diagnostics),
|
|
656
996
|
json_schema: deriveJsonSchema(entry.structure, structureClassName, description)
|
|
657
997
|
};
|
|
998
|
+
if (isPlainObject(entry.structure)) {
|
|
999
|
+
structures[code] = parseStructureFields(entry.structure);
|
|
1000
|
+
} else if (typeof entry.structure === "string") {
|
|
1001
|
+
structures[code] = entry.structure;
|
|
1002
|
+
}
|
|
658
1003
|
}
|
|
659
|
-
return concepts;
|
|
1004
|
+
return { concepts, structures };
|
|
660
1005
|
}
|
|
661
1006
|
function emptyBundle() {
|
|
662
1007
|
return {
|
|
@@ -665,6 +1010,7 @@ function emptyBundle() {
|
|
|
665
1010
|
main_pipe: null,
|
|
666
1011
|
system_prompt: null,
|
|
667
1012
|
concepts: authoredRecord(),
|
|
1013
|
+
structures: authoredRecord(),
|
|
668
1014
|
pipes: authoredRecord()
|
|
669
1015
|
};
|
|
670
1016
|
}
|
|
@@ -696,7 +1042,9 @@ function parseMthdsBundle(tomlText) {
|
|
|
696
1042
|
});
|
|
697
1043
|
}
|
|
698
1044
|
const domain = (_a = bundle.domain) != null ? _a : UNKNOWN_DOMAIN;
|
|
699
|
-
|
|
1045
|
+
const { concepts, structures } = parseConcepts(root.concept, domain, diagnostics);
|
|
1046
|
+
bundle.concepts = concepts;
|
|
1047
|
+
bundle.structures = structures;
|
|
700
1048
|
const pipeTable = root.pipe;
|
|
701
1049
|
if (pipeTable !== void 0) {
|
|
702
1050
|
if (!isPlainObject(pipeTable)) {
|
|
@@ -754,6 +1102,7 @@ function mergeBundles(bundles) {
|
|
|
754
1102
|
const namespace = (_b = domains[domain]) != null ? _b : domains[domain] = {
|
|
755
1103
|
domain,
|
|
756
1104
|
concepts: authoredRecord(),
|
|
1105
|
+
structures: authoredRecord(),
|
|
757
1106
|
pipes: authoredRecord()
|
|
758
1107
|
};
|
|
759
1108
|
if (mainDomain === null && bundle.domain !== null) mainDomain = bundle.domain;
|
|
@@ -774,6 +1123,9 @@ function mergeBundles(bundles) {
|
|
|
774
1123
|
continue;
|
|
775
1124
|
}
|
|
776
1125
|
namespace.concepts[code] = concept;
|
|
1126
|
+
if (Object.hasOwn(bundle.structures, code)) {
|
|
1127
|
+
namespace.structures[code] = bundle.structures[code];
|
|
1128
|
+
}
|
|
777
1129
|
}
|
|
778
1130
|
for (const [code, pipe] of Object.entries(bundle.pipes)) {
|
|
779
1131
|
const existing = namespace.pipes[code];
|
|
@@ -816,6 +1168,197 @@ function mergeBundles(bundles) {
|
|
|
816
1168
|
return { domains, mainDomain, mainPipe, description, diagnostics };
|
|
817
1169
|
}
|
|
818
1170
|
|
|
1171
|
+
// src/static-graph/bindingWalk.ts
|
|
1172
|
+
var SINGLE_FIELD_NATIVE_REASON = "holds its value in a single field";
|
|
1173
|
+
var DESCRIBED_ONLY_REASON = "is declared with neither a structure nor refines";
|
|
1174
|
+
function splitRef(ref) {
|
|
1175
|
+
const dot = ref.lastIndexOf(".");
|
|
1176
|
+
return { domain: ref.slice(0, dot), code: ref.slice(dot + 1) };
|
|
1177
|
+
}
|
|
1178
|
+
function qualifyFieldRef(ref, domain) {
|
|
1179
|
+
if (ref.includes("->")) return ref;
|
|
1180
|
+
if (ref.startsWith(`${NATIVE_DOMAIN}.`)) return ref;
|
|
1181
|
+
if (!ref.includes("."))
|
|
1182
|
+
return isNativeConceptCode(ref) ? `${NATIVE_DOMAIN}.${ref}` : `${domain}.${ref}`;
|
|
1183
|
+
return ref;
|
|
1184
|
+
}
|
|
1185
|
+
function resolveWalkable(set, ref, visited = /* @__PURE__ */ new Set()) {
|
|
1186
|
+
if (ref.includes("->")) {
|
|
1187
|
+
return {
|
|
1188
|
+
shape: "no-structure",
|
|
1189
|
+
ref,
|
|
1190
|
+
reason: "belongs to a dependency, which a method's own bundles do not show"
|
|
1191
|
+
};
|
|
1192
|
+
}
|
|
1193
|
+
const { domain, code } = splitRef(ref);
|
|
1194
|
+
if (domain === NATIVE_DOMAIN) {
|
|
1195
|
+
if (!isNativeConceptCode(code)) {
|
|
1196
|
+
return { shape: "no-structure", ref, reason: "is not a native concept" };
|
|
1197
|
+
}
|
|
1198
|
+
const fields = nativeConceptFields(code);
|
|
1199
|
+
if (fields === null) {
|
|
1200
|
+
return { shape: "no-structure", ref, reason: "is structureless by definition" };
|
|
1201
|
+
}
|
|
1202
|
+
if (Object.keys(fields).length === 1) {
|
|
1203
|
+
return { shape: "value", ref, reason: SINGLE_FIELD_NATIVE_REASON };
|
|
1204
|
+
}
|
|
1205
|
+
return { shape: "structure", ref, fields };
|
|
1206
|
+
}
|
|
1207
|
+
if (visited.has(ref))
|
|
1208
|
+
return { shape: "no-structure", ref, reason: "refines itself through a cycle" };
|
|
1209
|
+
const namespace = set.domains[domain];
|
|
1210
|
+
const concept = namespace !== void 0 && Object.hasOwn(namespace.concepts, code) ? namespace.concepts[code] : void 0;
|
|
1211
|
+
if (namespace === void 0 || concept === void 0) {
|
|
1212
|
+
return { shape: "no-structure", ref, reason: "is not declared in this method" };
|
|
1213
|
+
}
|
|
1214
|
+
const structure = Object.hasOwn(namespace.structures, code) ? namespace.structures[code] : void 0;
|
|
1215
|
+
if (typeof structure === "string") {
|
|
1216
|
+
return {
|
|
1217
|
+
shape: "no-structure",
|
|
1218
|
+
ref,
|
|
1219
|
+
reason: "has a Python class for a structure, which a bundle does not show"
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
if (structure !== void 0) {
|
|
1223
|
+
const fields = /* @__PURE__ */ Object.create(null);
|
|
1224
|
+
for (const [name, declared] of Object.entries(structure)) {
|
|
1225
|
+
fields[name] = __spreadProps(__spreadValues({}, declared), {
|
|
1226
|
+
conceptRef: declared.conceptRef === null ? null : qualifyFieldRef(declared.conceptRef, domain),
|
|
1227
|
+
itemConceptRef: declared.itemConceptRef === null ? null : qualifyFieldRef(declared.itemConceptRef, domain)
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
return { shape: "structure", ref, fields };
|
|
1231
|
+
}
|
|
1232
|
+
if (concept.refines != null) {
|
|
1233
|
+
const refined = resolveWalkable(set, concept.refines, /* @__PURE__ */ new Set([...visited, ref]));
|
|
1234
|
+
if (refined.shape === "structure") return { shape: "structure", ref, fields: refined.fields };
|
|
1235
|
+
const reason = `refines '${refined.ref}', which ${refined.reason}`;
|
|
1236
|
+
return refined.shape === "value" ? { shape: "value", ref, reason } : { shape: "no-structure", ref, reason };
|
|
1237
|
+
}
|
|
1238
|
+
return { shape: "no-structure", ref, reason: DESCRIBED_ONLY_REASON };
|
|
1239
|
+
}
|
|
1240
|
+
var SCALAR_NATIVE = {
|
|
1241
|
+
text: "Text",
|
|
1242
|
+
number: "Number",
|
|
1243
|
+
integer: "Number",
|
|
1244
|
+
boolean: "YesNo",
|
|
1245
|
+
date: "Date",
|
|
1246
|
+
datetime: "Date",
|
|
1247
|
+
time: "Time",
|
|
1248
|
+
dict: "JSON"
|
|
1249
|
+
};
|
|
1250
|
+
function fieldStep(declared) {
|
|
1251
|
+
var _a;
|
|
1252
|
+
const type = (_a = declared.type) != null ? _a : "text";
|
|
1253
|
+
if (type === "concept") return { kind: "concept", ref: declared.conceptRef, crossesList: false };
|
|
1254
|
+
if (type === "list") {
|
|
1255
|
+
const itemType = declared.itemType;
|
|
1256
|
+
if (itemType === null) {
|
|
1257
|
+
return { kind: "underivable", crossesList: true, reason: "the list declares no item_type" };
|
|
1258
|
+
}
|
|
1259
|
+
if (itemType === "concept") {
|
|
1260
|
+
return { kind: "concept", ref: declared.itemConceptRef, crossesList: true };
|
|
1261
|
+
}
|
|
1262
|
+
const nativeCode2 = Object.hasOwn(SCALAR_NATIVE, itemType) ? SCALAR_NATIVE[itemType] : null;
|
|
1263
|
+
if (nativeCode2 === null) {
|
|
1264
|
+
return {
|
|
1265
|
+
kind: "underivable",
|
|
1266
|
+
crossesList: true,
|
|
1267
|
+
reason: `the list's item_type '${itemType}' derives no concept`
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
return { kind: "leaf", nativeCode: nativeCode2, crossesList: true, description: `a list of ${itemType}` };
|
|
1271
|
+
}
|
|
1272
|
+
const nativeCode = Object.hasOwn(SCALAR_NATIVE, type) ? SCALAR_NATIVE[type] : null;
|
|
1273
|
+
if (nativeCode === null) {
|
|
1274
|
+
return {
|
|
1275
|
+
kind: "underivable",
|
|
1276
|
+
crossesList: false,
|
|
1277
|
+
reason: `its type '${type}' derives no concept`
|
|
1278
|
+
};
|
|
1279
|
+
}
|
|
1280
|
+
return { kind: "leaf", nativeCode, crossesList: false, description: `a ${type} field` };
|
|
1281
|
+
}
|
|
1282
|
+
function conceptInfoForRef(set, ref) {
|
|
1283
|
+
var _a, _b;
|
|
1284
|
+
const { domain, code } = splitRef(ref);
|
|
1285
|
+
return resolveConceptInfo(
|
|
1286
|
+
{ domain, code, multiplicity: null, presence: "plain" },
|
|
1287
|
+
domain,
|
|
1288
|
+
(_b = (_a = set.domains[domain]) == null ? void 0 : _a.concepts) != null ? _b : {}
|
|
1289
|
+
);
|
|
1290
|
+
}
|
|
1291
|
+
function conceptRefOf(concept) {
|
|
1292
|
+
return `${concept.domain_code}.${concept.code}`;
|
|
1293
|
+
}
|
|
1294
|
+
function deriveBinding(set, path, root) {
|
|
1295
|
+
const segments = path.split(".").slice(1);
|
|
1296
|
+
if (segments.length === 0) {
|
|
1297
|
+
return { kind: "derived", concept: root.concept, multiplicity: root.multiplicity };
|
|
1298
|
+
}
|
|
1299
|
+
let crossesAnyList = isPluralMultiplicity(root.multiplicity);
|
|
1300
|
+
let reachedPath = path.split(".")[0];
|
|
1301
|
+
let current = resolveWalkable(set, conceptRefOf(root.concept));
|
|
1302
|
+
let leafDescription = null;
|
|
1303
|
+
let derivedRef = conceptRefOf(root.concept);
|
|
1304
|
+
const fail = (reason) => ({
|
|
1305
|
+
kind: "unresolved",
|
|
1306
|
+
reason: `cannot bind '${path}': ${reason}`
|
|
1307
|
+
});
|
|
1308
|
+
for (const [index, segment] of segments.entries()) {
|
|
1309
|
+
if (leafDescription !== null) {
|
|
1310
|
+
return fail(
|
|
1311
|
+
`'${reachedPath}' is ${leafDescription}, a leaf holding a plain value, so the segment '${segment}' cannot follow it`
|
|
1312
|
+
);
|
|
1313
|
+
}
|
|
1314
|
+
if (current === null) {
|
|
1315
|
+
return fail(
|
|
1316
|
+
`nothing is known of '${reachedPath}', so the segment '${segment}' cannot be walked`
|
|
1317
|
+
);
|
|
1318
|
+
}
|
|
1319
|
+
if (current.shape === "value") {
|
|
1320
|
+
return fail(
|
|
1321
|
+
`'${reachedPath}' holds a '${current.ref}', which ${current.reason}, so it is a leaf and the segment '${segment}' cannot follow it`
|
|
1322
|
+
);
|
|
1323
|
+
}
|
|
1324
|
+
if (current.shape === "no-structure") {
|
|
1325
|
+
return fail(
|
|
1326
|
+
`'${reachedPath}' holds a '${current.ref}', which ${current.reason}, so the segment '${segment}' has no structure to walk`
|
|
1327
|
+
);
|
|
1328
|
+
}
|
|
1329
|
+
const declared = Object.hasOwn(current.fields, segment) ? current.fields[segment] : void 0;
|
|
1330
|
+
if (declared === void 0) {
|
|
1331
|
+
const names = Object.keys(current.fields);
|
|
1332
|
+
return fail(
|
|
1333
|
+
`'${reachedPath}' holds a '${current.ref}', which has no field '${segment}'` + (names.length > 0 ? ` (its fields are ${names.map((name) => `'${name}'`).join(", ")})` : "")
|
|
1334
|
+
);
|
|
1335
|
+
}
|
|
1336
|
+
reachedPath = `${reachedPath}.${segment}`;
|
|
1337
|
+
const isLast = index === segments.length - 1;
|
|
1338
|
+
const step = fieldStep(declared);
|
|
1339
|
+
if (step.crossesList) crossesAnyList = true;
|
|
1340
|
+
switch (step.kind) {
|
|
1341
|
+
case "underivable":
|
|
1342
|
+
return fail(`'${reachedPath}' derives no concept, since ${step.reason}`);
|
|
1343
|
+
case "concept":
|
|
1344
|
+
if (step.ref === null) return fail(`the concept field '${reachedPath}' names no concept`);
|
|
1345
|
+
derivedRef = step.ref;
|
|
1346
|
+
current = isLast ? null : resolveWalkable(set, step.ref);
|
|
1347
|
+
break;
|
|
1348
|
+
case "leaf":
|
|
1349
|
+
derivedRef = `${NATIVE_DOMAIN}.${step.nativeCode}`;
|
|
1350
|
+
leafDescription = step.description;
|
|
1351
|
+
current = null;
|
|
1352
|
+
break;
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
return {
|
|
1356
|
+
kind: "derived",
|
|
1357
|
+
concept: conceptInfoForRef(set, derivedRef),
|
|
1358
|
+
multiplicity: crossesAnyList ? true : null
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
|
|
819
1362
|
// src/static-graph/buildStaticGraphSpec.ts
|
|
820
1363
|
function buildStaticGraphSpec(set, options = {}) {
|
|
821
1364
|
var _a;
|
|
@@ -893,7 +1436,9 @@ function referencedPipeCodes(namespace) {
|
|
|
893
1436
|
for (const pipe of Object.values(namespace.pipes)) {
|
|
894
1437
|
switch (pipe.type) {
|
|
895
1438
|
case "PipeSequence":
|
|
896
|
-
for (const
|
|
1439
|
+
for (const step of pipe.sequential_sub_pipes) {
|
|
1440
|
+
if (!isBindingStepSpec(step)) add(step.pipe_code);
|
|
1441
|
+
}
|
|
897
1442
|
break;
|
|
898
1443
|
case "PipeParallel":
|
|
899
1444
|
for (const sub of pipe.parallel_sub_pipes) add(sub.pipe_code);
|
|
@@ -1017,23 +1562,13 @@ function formatBatchMultiplicity(multiplicity) {
|
|
|
1017
1562
|
if (multiplicity === true) return "xmany";
|
|
1018
1563
|
return "x?";
|
|
1019
1564
|
}
|
|
1020
|
-
function lookupScope(scope, name) {
|
|
1021
|
-
let candidate = name;
|
|
1022
|
-
for (; ; ) {
|
|
1023
|
-
const found = scope.get(candidate);
|
|
1024
|
-
if (found !== void 0) return found;
|
|
1025
|
-
const dot = candidate.lastIndexOf(".");
|
|
1026
|
-
if (dot <= 0) return void 0;
|
|
1027
|
-
candidate = candidate.slice(0, dot);
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
1565
|
function conceptKey(concept) {
|
|
1031
1566
|
return `${concept.domain_code}.${concept.code}`;
|
|
1032
1567
|
}
|
|
1033
1568
|
function bindInputs(ctx, blueprint, scope) {
|
|
1034
1569
|
const ioInputs = [];
|
|
1035
1570
|
for (const [name, spec] of Object.entries(blueprint.inputs)) {
|
|
1036
|
-
let bound =
|
|
1571
|
+
let bound = scope.get(name);
|
|
1037
1572
|
if (bound === void 0) {
|
|
1038
1573
|
bound = mintStuff(ctx, `input:${name}`, name, spec.concept, spec.multiplicity);
|
|
1039
1574
|
scope.set(name, bound);
|
|
@@ -1179,11 +1714,18 @@ function emitOpaqueLeaf(ctx, ref, currentDomain, nodeId, parentId, inv) {
|
|
|
1179
1714
|
function finishSequence(ctx, node, blueprint, nodeId, scope, inv) {
|
|
1180
1715
|
let lastOutput = null;
|
|
1181
1716
|
blueprint.sequential_sub_pipes.forEach((sub, index) => {
|
|
1717
|
+
const stepId = `${nodeId}/step_${index + 1}`;
|
|
1718
|
+
if (isBindingStepSpec(sub)) {
|
|
1719
|
+
const bound = walkBindingStep(ctx, sub, blueprint, stepId, nodeId, scope);
|
|
1720
|
+
scope.set(sub.output_name, bound);
|
|
1721
|
+
lastOutput = bound;
|
|
1722
|
+
return;
|
|
1723
|
+
}
|
|
1182
1724
|
const result = walkSubPipe(
|
|
1183
1725
|
ctx,
|
|
1184
1726
|
sub,
|
|
1185
1727
|
blueprint.domain_code,
|
|
1186
|
-
|
|
1728
|
+
stepId,
|
|
1187
1729
|
nodeId,
|
|
1188
1730
|
scope,
|
|
1189
1731
|
inv.outputMultiplicity
|
|
@@ -1198,6 +1740,54 @@ function finishSequence(ctx, node, blueprint, nodeId, scope, inv) {
|
|
|
1198
1740
|
node.io.outputs = lastOutput === null ? [] : [ioItem(lastOutput, inv.resultName)];
|
|
1199
1741
|
return { nodeId, output: lastOutput, eachOutputs: [] };
|
|
1200
1742
|
}
|
|
1743
|
+
function walkBindingStep(ctx, step, sequence, nodeId, parentId, scope) {
|
|
1744
|
+
const rootName = step.from_path.split(".")[0];
|
|
1745
|
+
let root = scope.get(rootName);
|
|
1746
|
+
if (root === void 0) {
|
|
1747
|
+
root = mintStuff(ctx, `input:${rootName}`, rootName, nativeConceptInfo("Anything"), null);
|
|
1748
|
+
scope.set(rootName, root);
|
|
1749
|
+
}
|
|
1750
|
+
const node = emitNode(ctx, {
|
|
1751
|
+
id: nodeId,
|
|
1752
|
+
kind: "binding",
|
|
1753
|
+
pipeCode: step.from_path,
|
|
1754
|
+
pipeType: BINDING_STEP_TYPE,
|
|
1755
|
+
description: `Binds '${step.from_path}' to '${step.output_name}'`,
|
|
1756
|
+
domainCode: sequence.domain_code,
|
|
1757
|
+
ioInputs: [ioItem(root, rootName)],
|
|
1758
|
+
parentId,
|
|
1759
|
+
inv: { resultName: step.output_name, outputMultiplicity: null }
|
|
1760
|
+
});
|
|
1761
|
+
node.execution_data = { from: step.from_path, result: step.output_name };
|
|
1762
|
+
const derivation = deriveBinding(ctx.set, step.from_path, {
|
|
1763
|
+
concept: root.concept,
|
|
1764
|
+
multiplicity: root.multiplicity
|
|
1765
|
+
});
|
|
1766
|
+
let concept;
|
|
1767
|
+
let multiplicity;
|
|
1768
|
+
if (derivation.kind === "derived") {
|
|
1769
|
+
({ concept, multiplicity } = derivation);
|
|
1770
|
+
} else {
|
|
1771
|
+
ctx.diagnostics.push({
|
|
1772
|
+
severity: "warning",
|
|
1773
|
+
code: "binding-path-unresolved",
|
|
1774
|
+
message: `pipe "${sequence.code}": ${derivation.reason} \u2014 bound as native.Anything`,
|
|
1775
|
+
path: nodeId,
|
|
1776
|
+
domain_code: sequence.domain_code
|
|
1777
|
+
});
|
|
1778
|
+
concept = nativeConceptInfo("Anything");
|
|
1779
|
+
multiplicity = isPluralMultiplicity(root.multiplicity) ? true : null;
|
|
1780
|
+
}
|
|
1781
|
+
const output = mintStuff(
|
|
1782
|
+
ctx,
|
|
1783
|
+
`${nodeId}:${step.output_name}`,
|
|
1784
|
+
step.output_name,
|
|
1785
|
+
concept,
|
|
1786
|
+
multiplicity
|
|
1787
|
+
);
|
|
1788
|
+
node.io.outputs = [ioItem(output)];
|
|
1789
|
+
return output;
|
|
1790
|
+
}
|
|
1201
1791
|
function finishParallel(ctx, node, blueprint, nodeId, scope, inv) {
|
|
1202
1792
|
var _a, _b;
|
|
1203
1793
|
const branchResults = [];
|
|
@@ -1240,13 +1830,13 @@ function finishParallel(ctx, node, blueprint, nodeId, scope, inv) {
|
|
|
1240
1830
|
return { nodeId, output: combined, eachOutputs };
|
|
1241
1831
|
}
|
|
1242
1832
|
function finishCondition(ctx, node, blueprint, nodeId, scope, inv) {
|
|
1243
|
-
var _a, _b
|
|
1833
|
+
var _a, _b;
|
|
1244
1834
|
const conditionScope = new Map(scope);
|
|
1245
1835
|
if (blueprint.add_alias_from_expression_to != null) {
|
|
1246
1836
|
const alias = blueprint.add_alias_from_expression_to;
|
|
1247
1837
|
conditionScope.set(
|
|
1248
1838
|
alias,
|
|
1249
|
-
mintStuff(ctx, `${nodeId}:${alias}`, alias, nativeConceptInfo("Dynamic"), null)
|
|
1839
|
+
mintStuff(ctx, `${nodeId}:alias:${alias}`, alias, nativeConceptInfo("Dynamic"), null)
|
|
1250
1840
|
);
|
|
1251
1841
|
}
|
|
1252
1842
|
const targets = [];
|
|
@@ -1289,16 +1879,47 @@ function finishCondition(ctx, node, blueprint, nodeId, scope, inv) {
|
|
|
1289
1879
|
);
|
|
1290
1880
|
if (result !== null) results.push({ entry, result });
|
|
1291
1881
|
}
|
|
1292
|
-
const
|
|
1293
|
-
|
|
1294
|
-
|
|
1882
|
+
const outputs = results.flatMap(({ result }) => result.output === null ? [] : [result.output]);
|
|
1883
|
+
const representative = (_b = (_a = results.find(({ entry, result }) => entry.viaDefault && result.output !== null)) == null ? void 0 : _a.result.output) != null ? _b : outputs[0];
|
|
1884
|
+
if (representative === void 0) {
|
|
1885
|
+
node.io.outputs = [];
|
|
1886
|
+
return { nodeId, output: null, eachOutputs: [] };
|
|
1887
|
+
}
|
|
1888
|
+
const outcomesAgree = outputs.every(
|
|
1889
|
+
(output) => conceptKey(output.concept) === conceptKey(representative.concept) && output.multiplicity === representative.multiplicity
|
|
1890
|
+
);
|
|
1891
|
+
const declaredMultiplicity = typeof inv.outputMultiplicity === "number" || inv.outputMultiplicity === true ? inv.outputMultiplicity : blueprint.output.multiplicity;
|
|
1892
|
+
const shared = mintStuff(
|
|
1893
|
+
ctx,
|
|
1894
|
+
`${nodeId}:${representative.name}`,
|
|
1895
|
+
representative.name,
|
|
1896
|
+
outcomesAgree ? representative.concept : blueprint.output.concept,
|
|
1897
|
+
outcomesAgree ? representative.multiplicity : declaredMultiplicity
|
|
1898
|
+
);
|
|
1899
|
+
for (const output of outputs) {
|
|
1900
|
+
if (output.digest.startsWith(`${nodeId}/`)) renameStuff(ctx, output.digest, shared);
|
|
1901
|
+
}
|
|
1902
|
+
node.io.outputs = [ioItem(shared, inv.resultName)];
|
|
1903
|
+
return { nodeId, output: shared, eachOutputs: [] };
|
|
1904
|
+
}
|
|
1905
|
+
function renameStuff(ctx, from, to) {
|
|
1906
|
+
for (const node of ctx.nodes) {
|
|
1907
|
+
for (const item of [...node.io.inputs, ...node.io.outputs]) {
|
|
1908
|
+
if (item.digest === from) item.digest = to.digest;
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
for (const edge of ctx.edges) {
|
|
1912
|
+
if (edge.source_stuff_digest === from) edge.source_stuff_digest = to.digest;
|
|
1913
|
+
if (edge.target_stuff_digest === from) edge.target_stuff_digest = to.digest;
|
|
1914
|
+
}
|
|
1915
|
+
ctx.stuffByDigest.delete(from);
|
|
1295
1916
|
}
|
|
1296
1917
|
function finishBatch(ctx, node, blueprint, nodeId, scope, inv) {
|
|
1297
1918
|
var _a, _b, _c;
|
|
1298
1919
|
const params = blueprint.batch_params;
|
|
1299
1920
|
let listStuff = null;
|
|
1300
1921
|
if (params.input_list_stuff_name !== "") {
|
|
1301
|
-
const bound =
|
|
1922
|
+
const bound = scope.get(params.input_list_stuff_name);
|
|
1302
1923
|
if (bound !== void 0) {
|
|
1303
1924
|
listStuff = bound;
|
|
1304
1925
|
} else {
|
|
@@ -1368,7 +1989,7 @@ function walkInlineBatch(ctx, sub, domain, nodeId, parentId, scope) {
|
|
|
1368
1989
|
const branchTail = refTail.slice(refTail.lastIndexOf(".") + 1);
|
|
1369
1990
|
const branchResolution = resolvePipeRef(ctx.set, sub.pipe_code, domain);
|
|
1370
1991
|
const branchBlueprint = branchResolution.kind === "resolved" ? branchResolution.blueprint : null;
|
|
1371
|
-
const listBinding =
|
|
1992
|
+
const listBinding = scope.get(params.input_list_stuff_name);
|
|
1372
1993
|
const listConcept = (_c = (_b = listBinding == null ? void 0 : listBinding.concept) != null ? _b : (_a = branchBlueprint == null ? void 0 : branchBlueprint.inputs[params.input_item_stuff_name]) == null ? void 0 : _a.concept) != null ? _c : nativeConceptInfo("Anything");
|
|
1373
1994
|
const outputSpec = (_d = branchBlueprint == null ? void 0 : branchBlueprint.output) != null ? _d : {
|
|
1374
1995
|
concept: nativeConceptInfo("Anything"),
|