@darkhorseprojects/circuitry 0.2.14 → 0.2.15
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/index.d.ts +0 -3
- package/dist/index.js +166 -435
- package/package.json +1 -1
- package/dist/host.d.ts +0 -40
- package/dist/node.d.ts +0 -48
- package/dist/tools.d.ts +0 -547
package/dist/index.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
-
|
|
4
1
|
// src/types.ts
|
|
5
2
|
var CIRCUITRY_NODE_CUSTOM_TYPE = "circuitry-node-person";
|
|
6
3
|
var CIRCUITRY_NODE_KIND = "circuitry-node";
|
|
@@ -28,6 +25,7 @@ var hasCircuitryNodeData = (element) => {
|
|
|
28
25
|
var isNodeElement = (element) => {
|
|
29
26
|
return hasCircuitryNodeData(element);
|
|
30
27
|
};
|
|
28
|
+
|
|
31
29
|
// src/graph.ts
|
|
32
30
|
var CIRCUITRY_SPEC_VERSION = "0.2";
|
|
33
31
|
var CIRCUITRY_SPEC_VERSION_LEGACY = "0.1";
|
|
@@ -44,7 +42,9 @@ var DEFAULT_CIRCUITRY_VALIDATION_STANDARD = {
|
|
|
44
42
|
executableKinds: ["agent", "tool", "output"]
|
|
45
43
|
};
|
|
46
44
|
var executableKindsFromRules = (rules = []) => {
|
|
47
|
-
const executableRule = rules.find(
|
|
45
|
+
const executableRule = rules.find(
|
|
46
|
+
(entry) => typeof entry !== "string" && entry.rule === "require-executable-inputs"
|
|
47
|
+
);
|
|
48
48
|
return executableRule?.executableKinds;
|
|
49
49
|
};
|
|
50
50
|
var createCircuitryValidationStandard = (standard = {}, graph) => {
|
|
@@ -169,9 +169,12 @@ var normalizeCircuitryGraph = (graph) => {
|
|
|
169
169
|
nodes
|
|
170
170
|
};
|
|
171
171
|
};
|
|
172
|
-
var VALID_SPEC_VERSIONS = new Set([CIRCUITRY_SPEC_VERSION]);
|
|
172
|
+
var VALID_SPEC_VERSIONS = /* @__PURE__ */ new Set([CIRCUITRY_SPEC_VERSION]);
|
|
173
173
|
var validateCircuitryGraphWithStandard = (graph, standard = {}) => {
|
|
174
|
-
const resolvedStandard = createCircuitryValidationStandard(
|
|
174
|
+
const resolvedStandard = createCircuitryValidationStandard(
|
|
175
|
+
standard,
|
|
176
|
+
graph && typeof graph === "object" && !Array.isArray(graph) ? graph : void 0
|
|
177
|
+
);
|
|
175
178
|
const errors = [];
|
|
176
179
|
const addError = (code, message, path2) => errors.push({ code, message, ...path2 ? { path: path2 } : {} });
|
|
177
180
|
if (!graph || typeof graph !== "object" || Array.isArray(graph)) {
|
|
@@ -182,7 +185,11 @@ var validateCircuitryGraphWithStandard = (graph, standard = {}) => {
|
|
|
182
185
|
const rules = resolvedStandard.rules;
|
|
183
186
|
const hasRule = (name) => rules.some((entry) => (typeof entry === "string" ? entry : entry.rule) === name);
|
|
184
187
|
if (resolvedStandard.requireSpecVersion && !VALID_SPEC_VERSIONS.has(String(graphObject.circuitry))) {
|
|
185
|
-
addError(
|
|
188
|
+
addError(
|
|
189
|
+
"invalid_spec_version",
|
|
190
|
+
`Expected circuitry: "${CIRCUITRY_SPEC_VERSION}"`,
|
|
191
|
+
["circuitry"]
|
|
192
|
+
);
|
|
186
193
|
}
|
|
187
194
|
if (graphObject.circuitry === CIRCUITRY_SPEC_VERSION && graphObject.resources && Object.keys(graphObject.resources).length > 0) {
|
|
188
195
|
if (graphObject.agents && Object.keys(graphObject.agents).length > 0) {
|
|
@@ -196,7 +203,7 @@ var validateCircuitryGraphWithStandard = (graph, standard = {}) => {
|
|
|
196
203
|
}
|
|
197
204
|
}
|
|
198
205
|
const normalized = normalizeCircuitryGraph(graphObject);
|
|
199
|
-
const ids = new Set;
|
|
206
|
+
const ids = /* @__PURE__ */ new Set();
|
|
200
207
|
for (const [index, node] of (normalized.nodes || []).entries()) {
|
|
201
208
|
if (!node.id) {
|
|
202
209
|
addError("missing_node_id", "Node is missing id", ["nodes", index, "id"]);
|
|
@@ -210,8 +217,8 @@ var validateCircuitryGraphWithStandard = (graph, standard = {}) => {
|
|
|
210
217
|
addError("missing_node_kind", `Node ${node.id} is missing kind`, ["nodes", index, "kind"]);
|
|
211
218
|
}
|
|
212
219
|
}
|
|
213
|
-
const adjacency = new Map;
|
|
214
|
-
const incomingCount = new Map;
|
|
220
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
221
|
+
const incomingCount = /* @__PURE__ */ new Map();
|
|
215
222
|
for (const id of ids) {
|
|
216
223
|
adjacency.set(id, []);
|
|
217
224
|
incomingCount.set(id, 0);
|
|
@@ -244,23 +251,20 @@ var validateCircuitryGraphWithStandard = (graph, standard = {}) => {
|
|
|
244
251
|
}
|
|
245
252
|
}
|
|
246
253
|
}
|
|
247
|
-
const visiting = new Set;
|
|
248
|
-
const visited = new Set;
|
|
254
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
255
|
+
const visited = /* @__PURE__ */ new Set();
|
|
249
256
|
const path = [];
|
|
250
257
|
let cycleMessage = "";
|
|
251
258
|
const visit = (id) => {
|
|
252
|
-
if (cycleMessage)
|
|
253
|
-
return;
|
|
259
|
+
if (cycleMessage) return;
|
|
254
260
|
if (visiting.has(id)) {
|
|
255
261
|
cycleMessage = [...path.slice(path.indexOf(id)), id].join(" -> ");
|
|
256
262
|
return;
|
|
257
263
|
}
|
|
258
|
-
if (visited.has(id))
|
|
259
|
-
return;
|
|
264
|
+
if (visited.has(id)) return;
|
|
260
265
|
visiting.add(id);
|
|
261
266
|
path.push(id);
|
|
262
|
-
for (const next of adjacency.get(id) || [])
|
|
263
|
-
visit(next);
|
|
267
|
+
for (const next of adjacency.get(id) || []) visit(next);
|
|
264
268
|
path.pop();
|
|
265
269
|
visiting.delete(id);
|
|
266
270
|
visited.add(id);
|
|
@@ -275,17 +279,15 @@ var validateCircuitryGraphWithStandard = (graph, standard = {}) => {
|
|
|
275
279
|
}
|
|
276
280
|
}
|
|
277
281
|
const additionalRules = rules.filter((rule) => {
|
|
278
|
-
if (typeof rule === "string")
|
|
279
|
-
return false;
|
|
282
|
+
if (typeof rule === "string") return false;
|
|
280
283
|
return rule.rule === "require-graph-field" || rule.rule === "require-node-field" || rule.rule === "require-edge-field" || rule.rule === "require-string" || rule.rule === "reject-string";
|
|
281
284
|
});
|
|
282
285
|
const fieldPath = (field) => field.split(".").filter(Boolean);
|
|
283
286
|
const getField = (value, field) => fieldPath(field).reduce((current, key) => {
|
|
284
|
-
if (!current || typeof current !== "object")
|
|
285
|
-
return;
|
|
287
|
+
if (!current || typeof current !== "object") return void 0;
|
|
286
288
|
return current[key];
|
|
287
289
|
}, value);
|
|
288
|
-
const isPresent = (value) => value !==
|
|
290
|
+
const isPresent = (value) => value !== void 0 && value !== null && value !== "";
|
|
289
291
|
for (const rule of additionalRules) {
|
|
290
292
|
if (rule.rule === "require-graph-field") {
|
|
291
293
|
if (!isPresent(getField(normalized, rule.field))) {
|
|
@@ -296,8 +298,7 @@ var validateCircuitryGraphWithStandard = (graph, standard = {}) => {
|
|
|
296
298
|
if (rule.rule === "require-node-field") {
|
|
297
299
|
const nodeKinds = new Set(rule.nodeKinds || []);
|
|
298
300
|
for (const [index, node] of (normalized.nodes || []).entries()) {
|
|
299
|
-
if (nodeKinds.size > 0 && !nodeKinds.has(node.kind))
|
|
300
|
-
continue;
|
|
301
|
+
if (nodeKinds.size > 0 && !nodeKinds.has(node.kind)) continue;
|
|
301
302
|
if (!isPresent(getField(node, rule.field))) {
|
|
302
303
|
addError("missing_required_node_field", `Node ${node.id || "<missing id>"} is missing required field: ${rule.field}`, ["nodes", index, ...fieldPath(rule.field)]);
|
|
303
304
|
}
|
|
@@ -307,8 +308,7 @@ var validateCircuitryGraphWithStandard = (graph, standard = {}) => {
|
|
|
307
308
|
if (rule.rule === "require-edge-field") {
|
|
308
309
|
const edgeKinds = new Set(rule.edgeKinds || []);
|
|
309
310
|
for (const [index, edge] of (normalized.edges || []).entries()) {
|
|
310
|
-
if (edgeKinds.size > 0 && (!edge.kind || !edgeKinds.has(edge.kind)))
|
|
311
|
-
continue;
|
|
311
|
+
if (edgeKinds.size > 0 && (!edge.kind || !edgeKinds.has(edge.kind))) continue;
|
|
312
312
|
if (!isPresent(getField(edge, rule.field))) {
|
|
313
313
|
addError("missing_required_edge_field", `Edge ${edge.id || index} is missing required field: ${rule.field}`, ["edges", index, ...fieldPath(rule.field)]);
|
|
314
314
|
}
|
|
@@ -326,28 +326,27 @@ var validateCircuitryGraphWithStandard = (graph, standard = {}) => {
|
|
|
326
326
|
addError("rejected_string", `${target} ${id} field ${match.field} must not include string: ${match.value}`, path2);
|
|
327
327
|
}
|
|
328
328
|
};
|
|
329
|
-
for (const match of rule.graph || [])
|
|
330
|
-
checkString("graph", normalized, "<root>", match, fieldPath(match.field));
|
|
329
|
+
for (const match of rule.graph || []) checkString("graph", normalized, "<root>", match, fieldPath(match.field));
|
|
331
330
|
for (const match of rule.nodes || []) {
|
|
332
331
|
const nodeKinds = new Set(match.nodeKinds || []);
|
|
333
332
|
for (const [index, node] of (normalized.nodes || []).entries()) {
|
|
334
|
-
if (nodeKinds.size > 0 && !nodeKinds.has(node.kind))
|
|
335
|
-
continue;
|
|
333
|
+
if (nodeKinds.size > 0 && !nodeKinds.has(node.kind)) continue;
|
|
336
334
|
checkString("node", node, node.id || "<missing id>", match, ["nodes", index, ...fieldPath(match.field)]);
|
|
337
335
|
}
|
|
338
336
|
}
|
|
339
337
|
for (const match of rule.edges || []) {
|
|
340
338
|
const edgeKinds = new Set(match.edgeKinds || []);
|
|
341
339
|
for (const [index, edge] of (normalized.edges || []).entries()) {
|
|
342
|
-
if (edgeKinds.size > 0 && (!edge.kind || !edgeKinds.has(edge.kind)))
|
|
343
|
-
continue;
|
|
340
|
+
if (edgeKinds.size > 0 && (!edge.kind || !edgeKinds.has(edge.kind))) continue;
|
|
344
341
|
checkString("edge", edge, edge.id || String(index), match, ["edges", index, ...fieldPath(match.field)]);
|
|
345
342
|
}
|
|
346
343
|
}
|
|
347
344
|
}
|
|
348
345
|
return { ok: errors.length === 0, errors, standard: resolvedStandard };
|
|
349
346
|
};
|
|
350
|
-
var validateCircuitryGraph = (graph, standard = {}) => validateCircuitryGraphWithStandard(graph, standard).errors.map(
|
|
347
|
+
var validateCircuitryGraph = (graph, standard = {}) => validateCircuitryGraphWithStandard(graph, standard).errors.map(
|
|
348
|
+
(error) => error.message
|
|
349
|
+
);
|
|
351
350
|
var parseCircuitryJson = (text, standard = {}, options = {}) => {
|
|
352
351
|
let graph;
|
|
353
352
|
try {
|
|
@@ -361,8 +360,7 @@ ${message}`);
|
|
|
361
360
|
const errors = validateCircuitryGraph(graph, standard);
|
|
362
361
|
if (errors.length) {
|
|
363
362
|
throw new Error(`Invalid Circuitry graph:
|
|
364
|
-
${errors.join(`
|
|
365
|
-
`)}`);
|
|
363
|
+
${errors.join("\n")}`);
|
|
366
364
|
}
|
|
367
365
|
}
|
|
368
366
|
return normalizeCircuitryGraph(graph);
|
|
@@ -374,6 +372,7 @@ var stringifyCircuitryJson = (graph) => {
|
|
|
374
372
|
var isUriInput = (input) => {
|
|
375
373
|
return Boolean(input.uri || ["file", "url", "uri", "image", "mcp"].includes(input.type));
|
|
376
374
|
};
|
|
375
|
+
|
|
377
376
|
// src/yaml.ts
|
|
378
377
|
import YAML from "yaml";
|
|
379
378
|
var parseCircuitryYaml = (text, standard = {}, options = {}) => {
|
|
@@ -392,8 +391,7 @@ ${message}`);
|
|
|
392
391
|
const errors = validateCircuitryGraph(graph, standard);
|
|
393
392
|
if (errors.length) {
|
|
394
393
|
throw new Error(`Invalid Circuitry graph:
|
|
395
|
-
${errors.join(`
|
|
396
|
-
`)}`);
|
|
394
|
+
${errors.join("\n")}`);
|
|
397
395
|
}
|
|
398
396
|
}
|
|
399
397
|
return normalizeCircuitryGraph(graph);
|
|
@@ -407,6 +405,7 @@ var parseCircuitryText = (text, filename = "graph.circuitry.yaml", standard = {}
|
|
|
407
405
|
var stringifyCircuitryText = (graph, filename = "graph.circuitry.yaml") => {
|
|
408
406
|
return filename.endsWith(".json") ? stringifyCircuitryJson(graph) : stringifyCircuitryYaml(graph);
|
|
409
407
|
};
|
|
408
|
+
|
|
410
409
|
// src/presets.ts
|
|
411
410
|
var CIRCUITRY_AGENT_PRESET_DIRS = [
|
|
412
411
|
".agents/agents",
|
|
@@ -423,8 +422,7 @@ var parseAgentPresetMarkdown = (text, fallbackName) => {
|
|
|
423
422
|
};
|
|
424
423
|
}
|
|
425
424
|
const metadata = {};
|
|
426
|
-
for (const line of frontmatter[1].split(
|
|
427
|
-
`)) {
|
|
425
|
+
for (const line of frontmatter[1].split("\n")) {
|
|
428
426
|
const match = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(line.trim());
|
|
429
427
|
if (match) {
|
|
430
428
|
metadata[match[1]] = match[2].replace(/^['\"]|['\"]$/g, "");
|
|
@@ -462,12 +460,13 @@ var applyAgentPresets = (graph, presets) => {
|
|
|
462
460
|
});
|
|
463
461
|
return { ...graph, nodes };
|
|
464
462
|
};
|
|
463
|
+
|
|
465
464
|
// src/scheduler.ts
|
|
466
465
|
var buildCircuitryExecutionGraph = (graph) => {
|
|
467
466
|
const normalized = normalizeCircuitryGraph(graph);
|
|
468
|
-
const nodes = new Map;
|
|
469
|
-
const inputSets = new Map;
|
|
470
|
-
const outputSets = new Map;
|
|
467
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
468
|
+
const inputSets = /* @__PURE__ */ new Map();
|
|
469
|
+
const outputSets = /* @__PURE__ */ new Map();
|
|
471
470
|
for (const node of normalized.nodes || []) {
|
|
472
471
|
if (node.kind !== "agent" && node.kind !== "tool" && node.kind !== "output" && node.kind !== "input") {
|
|
473
472
|
continue;
|
|
@@ -477,10 +476,11 @@ var buildCircuitryExecutionGraph = (graph) => {
|
|
|
477
476
|
node,
|
|
478
477
|
inputNodeIds: [],
|
|
479
478
|
outputNodeIds: [],
|
|
479
|
+
// Input nodes are already "done" with their value as output
|
|
480
480
|
...node.kind === "input" ? { output: node.input?.value || "", completed: true } : {}
|
|
481
481
|
});
|
|
482
|
-
inputSets.set(node.id, new Set);
|
|
483
|
-
outputSets.set(node.id, new Set);
|
|
482
|
+
inputSets.set(node.id, /* @__PURE__ */ new Set());
|
|
483
|
+
outputSets.set(node.id, /* @__PURE__ */ new Set());
|
|
484
484
|
}
|
|
485
485
|
for (const edge of normalized.edges || []) {
|
|
486
486
|
if (!nodes.has(edge.to)) {
|
|
@@ -511,27 +511,24 @@ var describeEdge = (edge, direction) => {
|
|
|
511
511
|
};
|
|
512
512
|
var composeCircuitryPrompt = (graph, node, inputs, contextInputs) => {
|
|
513
513
|
const agent = node.agent || {};
|
|
514
|
-
const upstreamSection = inputs.length ? inputs.map(
|
|
515
|
-
${input.
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
const contextSection = contextInputs.length ? contextInputs.map(
|
|
514
|
+
const upstreamSection = inputs.length ? inputs.map(
|
|
515
|
+
(input, index) => `Upstream ${index + 1} from ${input.nodeId}:
|
|
516
|
+
${input.output}`
|
|
517
|
+
).join("\n\n") : "No upstream node outputs.";
|
|
518
|
+
const contextSection = contextInputs.length ? contextInputs.map(
|
|
519
|
+
(input, index) => input.kind === "text" ? `Context ${index + 1} [text] from ${input.sourceId}:
|
|
519
520
|
${input.text || ""}` : `Context ${index + 1} [${input.kind}] from ${input.sourceId}${input.text ? `:
|
|
520
|
-
${input.text}` : ""}`
|
|
521
|
-
|
|
522
|
-
`) : "No connected external context.";
|
|
521
|
+
${input.text}` : ""}`
|
|
522
|
+
).join("\n\n") : "No connected external context.";
|
|
523
523
|
const incomingEdges = (graph.edges || []).filter((edge) => edge.to === node.id);
|
|
524
524
|
const outgoingEdges = (graph.edges || []).filter((edge) => edge.from === node.id);
|
|
525
525
|
const wiringSection = [
|
|
526
526
|
"Canvas Wiring:",
|
|
527
527
|
"Incoming edges:",
|
|
528
|
-
incomingEdges.length ? incomingEdges.map((edge) => describeEdge(edge, "incoming")).join(
|
|
529
|
-
`) : "- none",
|
|
528
|
+
incomingEdges.length ? incomingEdges.map((edge) => describeEdge(edge, "incoming")).join("\n") : "- none",
|
|
530
529
|
"Outgoing edges:",
|
|
531
|
-
outgoingEdges.length ? outgoingEdges.map((edge) => describeEdge(edge, "outgoing")).join(
|
|
532
|
-
|
|
533
|
-
].join(`
|
|
534
|
-
`);
|
|
530
|
+
outgoingEdges.length ? outgoingEdges.map((edge) => describeEdge(edge, "outgoing")).join("\n") : "- none"
|
|
531
|
+
].join("\n");
|
|
535
532
|
return [
|
|
536
533
|
`Node label: ${node.label}`,
|
|
537
534
|
agent.identity ? `Identity: ${agent.identity}` : "",
|
|
@@ -546,9 +543,7 @@ ${agent.instructions}` : "",
|
|
|
546
543
|
${upstreamSection}`,
|
|
547
544
|
`Connected Context Inputs:
|
|
548
545
|
${contextSection}`
|
|
549
|
-
].filter(Boolean).join(
|
|
550
|
-
|
|
551
|
-
`);
|
|
546
|
+
].filter(Boolean).join("\n\n");
|
|
552
547
|
};
|
|
553
548
|
var collectImages = (contextInputs) => contextInputs.filter((item) => item.kind === "image" && item.image).map((item) => item.image);
|
|
554
549
|
var executeCircuitryNode = async ({
|
|
@@ -564,9 +559,7 @@ var executeCircuitryNode = async ({
|
|
|
564
559
|
}) => {
|
|
565
560
|
onNodeStart?.(item.id, fallbackCycle);
|
|
566
561
|
if (item.node.kind === "output") {
|
|
567
|
-
const output = inputPayload.map((input) => input.output).join(
|
|
568
|
-
|
|
569
|
-
`);
|
|
562
|
+
const output = inputPayload.map((input) => input.output).join("\n\n");
|
|
570
563
|
onNodeComplete?.(item.id, { output });
|
|
571
564
|
return {
|
|
572
565
|
nodeId: item.id,
|
|
@@ -579,7 +572,7 @@ var executeCircuitryNode = async ({
|
|
|
579
572
|
try {
|
|
580
573
|
const result = await executeNode({
|
|
581
574
|
nodeId: item.id,
|
|
582
|
-
model: (agent.model === "inherit" ?
|
|
575
|
+
model: (agent.model === "inherit" ? void 0 : agent.model) || (defaultModel === "inherit" ? void 0 : defaultModel) || "inherit",
|
|
583
576
|
tools: agent.tools || [],
|
|
584
577
|
thinkingLevel: agent.thinkingLevel || "off",
|
|
585
578
|
personality: agent.personality || "",
|
|
@@ -650,14 +643,14 @@ var runCircuitryGraphExecution = async ({
|
|
|
650
643
|
if (!executionGraph.nodes.has(selectedNodeId)) {
|
|
651
644
|
return runs;
|
|
652
645
|
}
|
|
653
|
-
runs.push(await runOne(selectedNodeId, new Map));
|
|
646
|
+
runs.push(await runOne(selectedNodeId, /* @__PURE__ */ new Map()));
|
|
654
647
|
return runs;
|
|
655
648
|
}
|
|
656
|
-
const completed = new Set;
|
|
657
|
-
const queued = new Set;
|
|
658
|
-
const outputs = new Map;
|
|
649
|
+
const completed = /* @__PURE__ */ new Set();
|
|
650
|
+
const queued = /* @__PURE__ */ new Set();
|
|
651
|
+
const outputs = /* @__PURE__ */ new Map();
|
|
659
652
|
const nodeIds = [...executionGraph.nodes.keys()];
|
|
660
|
-
const remainingDependencies = new Map;
|
|
653
|
+
const remainingDependencies = /* @__PURE__ */ new Map();
|
|
661
654
|
const ready = [];
|
|
662
655
|
for (const nodeId of nodeIds) {
|
|
663
656
|
const node = executionGraph.nodes.get(nodeId);
|
|
@@ -668,7 +661,9 @@ var runCircuitryGraphExecution = async ({
|
|
|
668
661
|
}
|
|
669
662
|
continue;
|
|
670
663
|
}
|
|
671
|
-
const count = node.inputNodeIds.filter(
|
|
664
|
+
const count = node.inputNodeIds.filter(
|
|
665
|
+
(sourceId) => executionGraph.nodes.has(sourceId)
|
|
666
|
+
).length;
|
|
672
667
|
remainingDependencies.set(nodeId, count);
|
|
673
668
|
if (count === 0) {
|
|
674
669
|
ready.push(nodeId);
|
|
@@ -681,10 +676,12 @@ var runCircuitryGraphExecution = async ({
|
|
|
681
676
|
throw new Error(`Circuitry execution stalled; unresolved dependencies: ${blocked.join(", ")}`);
|
|
682
677
|
}
|
|
683
678
|
const chunk = ready.splice(0, parallelism);
|
|
684
|
-
const chunkResults = await Promise.all(
|
|
685
|
-
nodeId
|
|
686
|
-
|
|
687
|
-
|
|
679
|
+
const chunkResults = await Promise.all(
|
|
680
|
+
chunk.map(async (nodeId) => ({
|
|
681
|
+
nodeId,
|
|
682
|
+
result: await runOne(nodeId, outputs)
|
|
683
|
+
}))
|
|
684
|
+
);
|
|
688
685
|
for (const { nodeId, result } of chunkResults) {
|
|
689
686
|
outputs.set(nodeId, result.output);
|
|
690
687
|
completed.add(nodeId);
|
|
@@ -693,7 +690,10 @@ var runCircuitryGraphExecution = async ({
|
|
|
693
690
|
if (completed.has(outputNodeId) || queued.has(outputNodeId)) {
|
|
694
691
|
continue;
|
|
695
692
|
}
|
|
696
|
-
const nextCount = Math.max(
|
|
693
|
+
const nextCount = Math.max(
|
|
694
|
+
0,
|
|
695
|
+
(remainingDependencies.get(outputNodeId) || 0) - 1
|
|
696
|
+
);
|
|
697
697
|
remainingDependencies.set(outputNodeId, nextCount);
|
|
698
698
|
if (nextCount === 0) {
|
|
699
699
|
ready.push(outputNodeId);
|
|
@@ -704,6 +704,7 @@ var runCircuitryGraphExecution = async ({
|
|
|
704
704
|
}
|
|
705
705
|
return runs;
|
|
706
706
|
};
|
|
707
|
+
|
|
707
708
|
// src/simulation.ts
|
|
708
709
|
var DEFAULT_MAX_PARALLEL_RUNS = 4;
|
|
709
710
|
var pushUnique = (array, value) => {
|
|
@@ -712,7 +713,7 @@ var pushUnique = (array, value) => {
|
|
|
712
713
|
}
|
|
713
714
|
};
|
|
714
715
|
var buildSimulationGraph = (elements) => {
|
|
715
|
-
const nodes = new Map;
|
|
716
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
716
717
|
for (const element of elements) {
|
|
717
718
|
if (!hasCircuitryNodeData(element)) {
|
|
718
719
|
continue;
|
|
@@ -760,13 +761,11 @@ ${input.text || ""}`;
|
|
|
760
761
|
${input.text}` : ""}`;
|
|
761
762
|
};
|
|
762
763
|
var composePrompt = (node, inputs, contextInputs) => {
|
|
763
|
-
const upstreamSection = inputs.length === 0 ? "No upstream node outputs." : inputs.map(
|
|
764
|
-
${input.
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
const contextSection = contextInputs.length === 0 ? "No connected external context." : contextInputs.map(formatContextInput).join(
|
|
768
|
-
|
|
769
|
-
`);
|
|
764
|
+
const upstreamSection = inputs.length === 0 ? "No upstream node outputs." : inputs.map(
|
|
765
|
+
(input, index) => `Upstream ${index + 1} from ${input.nodeId}:
|
|
766
|
+
${input.output}`
|
|
767
|
+
).join("\n\n");
|
|
768
|
+
const contextSection = contextInputs.length === 0 ? "No connected external context." : contextInputs.map(formatContextInput).join("\n\n");
|
|
770
769
|
return [
|
|
771
770
|
`Node label: ${node.data.label}`,
|
|
772
771
|
node.data.context ? `Context:
|
|
@@ -779,9 +778,7 @@ ${node.data.instructions}` : "",
|
|
|
779
778
|
${upstreamSection}`,
|
|
780
779
|
`Connected Context Inputs:
|
|
781
780
|
${contextSection}`
|
|
782
|
-
].filter(Boolean).join(
|
|
783
|
-
|
|
784
|
-
`);
|
|
781
|
+
].filter(Boolean).join("\n\n");
|
|
785
782
|
};
|
|
786
783
|
var collectImages2 = (contextInputs) => {
|
|
787
784
|
return contextInputs.filter((item) => item.kind === "image" && item.image).map((item) => item.image);
|
|
@@ -859,19 +856,21 @@ var runGraphExecution = async ({
|
|
|
859
856
|
incomingSourceIds: node.incomingSourceIds,
|
|
860
857
|
elements
|
|
861
858
|
}) || [];
|
|
862
|
-
runs.push(
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
859
|
+
runs.push(
|
|
860
|
+
await executeSimulationNode({
|
|
861
|
+
node,
|
|
862
|
+
fallbackCycle: false,
|
|
863
|
+
inputPayload,
|
|
864
|
+
contextInputs,
|
|
865
|
+
executeNode,
|
|
866
|
+
onNodeStart,
|
|
867
|
+
onNodeComplete
|
|
868
|
+
})
|
|
869
|
+
);
|
|
871
870
|
return runs;
|
|
872
871
|
}
|
|
873
|
-
const completed = new Set;
|
|
874
|
-
const outputs = new Map;
|
|
872
|
+
const completed = /* @__PURE__ */ new Set();
|
|
873
|
+
const outputs = /* @__PURE__ */ new Map();
|
|
875
874
|
const nodeIds = [...graph.nodes.keys()];
|
|
876
875
|
while (completed.size < nodeIds.length) {
|
|
877
876
|
const pending = nodeIds.filter((id) => !completed.has(id));
|
|
@@ -884,31 +883,33 @@ var runGraphExecution = async ({
|
|
|
884
883
|
}
|
|
885
884
|
const fallbackCycle = false;
|
|
886
885
|
const currentBatch = ready;
|
|
887
|
-
for (let index = 0;index < currentBatch.length; index += parallelism) {
|
|
886
|
+
for (let index = 0; index < currentBatch.length; index += parallelism) {
|
|
888
887
|
const chunk = currentBatch.slice(index, index + parallelism);
|
|
889
|
-
const chunkResults = await Promise.all(
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
888
|
+
const chunkResults = await Promise.all(
|
|
889
|
+
chunk.map(async (nodeId) => {
|
|
890
|
+
const node = graph.nodes.get(nodeId);
|
|
891
|
+
const inputPayload = node.inputNodeIds.filter((sourceId) => outputs.has(sourceId)).map((sourceId) => ({
|
|
892
|
+
nodeId: sourceId,
|
|
893
|
+
output: outputs.get(sourceId)
|
|
894
|
+
}));
|
|
895
|
+
const contextInputs = await resolveContextInputs?.({
|
|
896
|
+
nodeId,
|
|
897
|
+
inputNodeIds: new Set(node.inputNodeIds),
|
|
898
|
+
incomingSourceIds: node.incomingSourceIds,
|
|
899
|
+
elements
|
|
900
|
+
}) || [];
|
|
901
|
+
const result = await executeSimulationNode({
|
|
902
|
+
node,
|
|
903
|
+
fallbackCycle,
|
|
904
|
+
inputPayload,
|
|
905
|
+
contextInputs,
|
|
906
|
+
executeNode,
|
|
907
|
+
onNodeStart,
|
|
908
|
+
onNodeComplete
|
|
909
|
+
});
|
|
910
|
+
return { nodeId, result };
|
|
911
|
+
})
|
|
912
|
+
);
|
|
912
913
|
for (const { nodeId, result } of chunkResults) {
|
|
913
914
|
outputs.set(nodeId, result.output);
|
|
914
915
|
completed.add(nodeId);
|
|
@@ -934,6 +935,7 @@ var runDependencySimulation = async ({
|
|
|
934
935
|
maxParallelRuns
|
|
935
936
|
});
|
|
936
937
|
};
|
|
938
|
+
|
|
937
939
|
// src/bundle.ts
|
|
938
940
|
var BUNDLE_MIME = "application/vnd.circuitry.bundle+json";
|
|
939
941
|
var deepClone = (value) => JSON.parse(JSON.stringify(value));
|
|
@@ -952,11 +954,11 @@ var createBundleFromSelection = (elements, selectedIds) => {
|
|
|
952
954
|
const target = arrow.endBinding?.elementId;
|
|
953
955
|
return !!source && !!target && selectedSet.has(source) && selectedSet.has(target);
|
|
954
956
|
});
|
|
955
|
-
const dedup = new Map;
|
|
957
|
+
const dedup = /* @__PURE__ */ new Map();
|
|
956
958
|
[...selected, ...relationships].forEach((el) => dedup.set(el.id, deepClone(el)));
|
|
957
959
|
return {
|
|
958
960
|
version: 1,
|
|
959
|
-
createdAt: new Date().toISOString(),
|
|
961
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
960
962
|
elements: [...dedup.values()]
|
|
961
963
|
};
|
|
962
964
|
};
|
|
@@ -967,11 +969,11 @@ var parseBundleText = (text) => {
|
|
|
967
969
|
}
|
|
968
970
|
return parsed;
|
|
969
971
|
};
|
|
970
|
-
var randomId = () => typeof crypto !== "undefined" &&
|
|
972
|
+
var randomId = () => typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID().replaceAll("-", "") : Math.random().toString(36).slice(2, 12);
|
|
971
973
|
var importBundleElements = (bundle, opts) => {
|
|
972
974
|
const offsetX = opts?.offsetX ?? 24;
|
|
973
975
|
const offsetY = opts?.offsetY ?? 24;
|
|
974
|
-
const idMap = new Map;
|
|
976
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
975
977
|
for (const element of bundle.elements) {
|
|
976
978
|
idMap.set(element.id, randomId());
|
|
977
979
|
}
|
|
@@ -989,7 +991,9 @@ var importBundleElements = (bundle, opts) => {
|
|
|
989
991
|
cloned.frameId = idMap.get(cloned.frameId);
|
|
990
992
|
}
|
|
991
993
|
if (cloned.boundElements?.length) {
|
|
992
|
-
cloned.boundElements = cloned.boundElements.map(
|
|
994
|
+
cloned.boundElements = cloned.boundElements.map(
|
|
995
|
+
(item) => idMap.has(item.id) ? { ...item, id: idMap.get(item.id) } : item
|
|
996
|
+
);
|
|
993
997
|
}
|
|
994
998
|
if (cloned.containerId && idMap.has(cloned.containerId)) {
|
|
995
999
|
cloned.containerId = idMap.get(cloned.containerId);
|
|
@@ -1012,6 +1016,7 @@ var importBundleElements = (bundle, opts) => {
|
|
|
1012
1016
|
return cloned;
|
|
1013
1017
|
});
|
|
1014
1018
|
};
|
|
1019
|
+
|
|
1015
1020
|
// src/runtime.ts
|
|
1016
1021
|
var createUnsupportedRuntimeAdapter = (id) => ({
|
|
1017
1022
|
id,
|
|
@@ -1020,313 +1025,39 @@ var createUnsupportedRuntimeAdapter = (id) => ({
|
|
|
1020
1025
|
throw new Error(`Circuitry runtime adapter is not configured: ${String(id)}`);
|
|
1021
1026
|
}
|
|
1022
1027
|
});
|
|
1023
|
-
// src/tools.ts
|
|
1024
|
-
import { z } from "zod";
|
|
1025
|
-
var standardSchema = z.object({
|
|
1026
|
-
version: z.string().optional(),
|
|
1027
|
-
requireSpecVersion: z.boolean().optional(),
|
|
1028
|
-
executableKinds: z.array(z.string()).optional(),
|
|
1029
|
-
rules: z.array(z.union([z.string(), z.object({ rule: z.string() }).passthrough()])).optional()
|
|
1030
|
-
}).passthrough().optional();
|
|
1031
|
-
var createCircuitryReadGraphTool = (host) => ({
|
|
1032
|
-
name: "circuitry_read_graph",
|
|
1033
|
-
description: "Read the current Circuitry graph. In the App this reads the canvas and includes latest node run outputs.",
|
|
1034
|
-
parameters: z.object({
|
|
1035
|
-
filename: z.string().optional().describe("Optional filename when in standalone mode.")
|
|
1036
|
-
}),
|
|
1037
|
-
execute: (input) => host.readGraph(input)
|
|
1038
|
-
});
|
|
1039
|
-
var createCircuitryWriteGraphTool = (host) => ({
|
|
1040
|
-
name: "circuitry_write_graph",
|
|
1041
|
-
description: "Replace a Circuitry graph. In the App this applies the graph to the canvas; standalone writes a file.",
|
|
1042
|
-
parameters: z.object({
|
|
1043
|
-
text: z.string().optional().describe("YAML graph text."),
|
|
1044
|
-
filename: z.string().optional().describe("Optional filename."),
|
|
1045
|
-
graph: z.any().optional().describe("Parsed graph object."),
|
|
1046
|
-
standard: standardSchema
|
|
1047
|
-
}),
|
|
1048
|
-
execute: (input) => host.writeGraph(input)
|
|
1049
|
-
});
|
|
1050
|
-
var createCircuitryRunGraphTool = (host) => ({
|
|
1051
|
-
name: "circuitry_run_graph",
|
|
1052
|
-
description: "Run the current Circuitry graph. After running, call circuitry_read_graph to inspect updated per-node outputs and errors.",
|
|
1053
|
-
parameters: z.object({
|
|
1054
|
-
source: z.enum(["current", "text"]).optional().describe("Whether to run the 'current' canvas/file or provided 'text'."),
|
|
1055
|
-
text: z.string().optional().describe("YAML graph text if source is 'text'."),
|
|
1056
|
-
filename: z.string().optional().describe("Optional filename."),
|
|
1057
|
-
selectedNodeId: z.string().optional().describe("Optional specific node to run."),
|
|
1058
|
-
standard: standardSchema,
|
|
1059
|
-
hostModel: z.string().optional().describe("Optional model to use when a node is set to 'inherit'.")
|
|
1060
|
-
}),
|
|
1061
|
-
execute: (input) => host.runGraph(input)
|
|
1062
|
-
});
|
|
1063
|
-
var createCircuitryValidateGraphTool = (host) => ({
|
|
1064
|
-
name: "circuitry_validate_graph",
|
|
1065
|
-
description: "Validate Circuitry YAML or JSON graph text. Returns structured validation issues.",
|
|
1066
|
-
parameters: z.object({
|
|
1067
|
-
text: z.string().describe("YAML or JSON graph text to validate."),
|
|
1068
|
-
filename: z.string().optional().describe("Optional filename context."),
|
|
1069
|
-
standard: standardSchema
|
|
1070
|
-
}),
|
|
1071
|
-
execute: (input) => host.validateGraph(input)
|
|
1072
|
-
});
|
|
1073
|
-
var createCircuitryTools = (host) => [
|
|
1074
|
-
createCircuitryReadGraphTool(host),
|
|
1075
|
-
createCircuitryWriteGraphTool(host),
|
|
1076
|
-
createCircuitryRunGraphTool(host),
|
|
1077
|
-
createCircuitryValidateGraphTool(host)
|
|
1078
|
-
];
|
|
1079
|
-
// src/node.ts
|
|
1080
|
-
import { access, readFile, writeFile } from "node:fs/promises";
|
|
1081
|
-
import fs from "node:fs";
|
|
1082
|
-
import path from "node:path";
|
|
1083
|
-
import os from "node:os";
|
|
1084
|
-
var loadPiSDK = async () => {
|
|
1085
|
-
const possiblePaths = [
|
|
1086
|
-
path.join(process.cwd(), "node_modules/@earendil-works/pi-coding-agent/dist/index.js"),
|
|
1087
|
-
path.join(os.homedir(), ".npm-global/lib/node_modules/@earendil-works/pi-coding-agent/dist/index.js")
|
|
1088
|
-
];
|
|
1089
|
-
for (const modulePath of possiblePaths) {
|
|
1090
|
-
if (fs.existsSync(modulePath)) {
|
|
1091
|
-
return await import(modulePath);
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
return await import("@earendil-works/pi-coding-agent");
|
|
1095
|
-
};
|
|
1096
|
-
var extractAssistantText = (message) => {
|
|
1097
|
-
if (!message || message.role !== "assistant")
|
|
1098
|
-
return "";
|
|
1099
|
-
if (typeof message.content === "string")
|
|
1100
|
-
return message.content;
|
|
1101
|
-
if (!Array.isArray(message.content))
|
|
1102
|
-
return "";
|
|
1103
|
-
return message.content.filter((part) => part?.type === "text" && typeof part.text === "string").map((part) => part.text).join("");
|
|
1104
|
-
};
|
|
1105
|
-
var withTimeout = async (promise, timeoutMs) => {
|
|
1106
|
-
let timeout;
|
|
1107
|
-
try {
|
|
1108
|
-
return await Promise.race([
|
|
1109
|
-
promise,
|
|
1110
|
-
new Promise((_, reject) => {
|
|
1111
|
-
timeout = setTimeout(() => reject(new Error(`Pi SDK request timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
1112
|
-
})
|
|
1113
|
-
]);
|
|
1114
|
-
} finally {
|
|
1115
|
-
clearTimeout(timeout);
|
|
1116
|
-
}
|
|
1117
|
-
};
|
|
1118
|
-
var runNodeWithPiSDK = async ({
|
|
1119
|
-
model,
|
|
1120
|
-
prompt,
|
|
1121
|
-
images = [],
|
|
1122
|
-
tools = [],
|
|
1123
|
-
thinkingLevel = "off"
|
|
1124
|
-
}) => {
|
|
1125
|
-
let sdk;
|
|
1126
|
-
try {
|
|
1127
|
-
sdk = await loadPiSDK();
|
|
1128
|
-
} catch (error) {
|
|
1129
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1130
|
-
throw new Error([
|
|
1131
|
-
"Circuitry could not load the Pi SDK package for execution.",
|
|
1132
|
-
"Ensure @earendil-works/pi-coding-agent is installed.",
|
|
1133
|
-
message
|
|
1134
|
-
].join(`
|
|
1135
|
-
`));
|
|
1136
|
-
}
|
|
1137
|
-
const { AuthStorage, ModelRegistry, SessionManager, createAgentSession } = sdk;
|
|
1138
|
-
const authStorage = AuthStorage.create();
|
|
1139
|
-
const modelRegistry = ModelRegistry.create(authStorage);
|
|
1140
|
-
const [provider, ...modelParts] = String(model || "").split("/");
|
|
1141
|
-
const modelId = modelParts.join("/");
|
|
1142
|
-
const available = await modelRegistry.getAvailable();
|
|
1143
|
-
const selectedModel = (provider && modelId ? modelRegistry.find(provider, modelId) : undefined) || available.find((entry) => {
|
|
1144
|
-
if (!modelId)
|
|
1145
|
-
return false;
|
|
1146
|
-
return `${entry.provider}/${entry.id}` === `${provider}/${modelId}` || entry.id === modelId;
|
|
1147
|
-
}) || available[0];
|
|
1148
|
-
if (!selectedModel) {
|
|
1149
|
-
throw new Error("No Pi SDK models are available. Configure ~/.pi/agent/auth.json");
|
|
1150
|
-
}
|
|
1151
|
-
const { session } = await createAgentSession({
|
|
1152
|
-
model: selectedModel,
|
|
1153
|
-
thinkingLevel,
|
|
1154
|
-
sessionManager: SessionManager.inMemory(),
|
|
1155
|
-
authStorage,
|
|
1156
|
-
modelRegistry
|
|
1157
|
-
});
|
|
1158
|
-
session.setActiveToolsByName(Array.isArray(tools) ? tools.map((tool) => String(tool)) : []);
|
|
1159
|
-
let output = "";
|
|
1160
|
-
const unsubscribe = session.subscribe((event) => {
|
|
1161
|
-
if ((event.type === "message_update" || event.type === "message_end") && event.message?.role === "assistant") {
|
|
1162
|
-
output = extractAssistantText(event.message);
|
|
1163
|
-
}
|
|
1164
|
-
if (event.type === "agent_end" && Array.isArray(event.messages)) {
|
|
1165
|
-
const assistantMessage = [...event.messages].reverse().find((message) => message.role === "assistant");
|
|
1166
|
-
output = extractAssistantText(assistantMessage);
|
|
1167
|
-
}
|
|
1168
|
-
});
|
|
1169
|
-
try {
|
|
1170
|
-
const promptImages = images.filter((image) => image?.mediaType && image?.data).map((image) => ({
|
|
1171
|
-
type: "image",
|
|
1172
|
-
source: { type: "base64", mediaType: image.mediaType, data: image.data }
|
|
1173
|
-
}));
|
|
1174
|
-
await withTimeout(session.prompt(prompt, { images: promptImages }), 180000);
|
|
1175
|
-
return { output: output.trim() };
|
|
1176
|
-
} finally {
|
|
1177
|
-
unsubscribe();
|
|
1178
|
-
session.dispose();
|
|
1179
|
-
}
|
|
1180
|
-
};
|
|
1181
|
-
var defaultFilename = "graph.circuitry.yaml";
|
|
1182
|
-
|
|
1183
|
-
class NodeCircuitryHost {
|
|
1184
|
-
resolveGraphFile(filename) {
|
|
1185
|
-
return path.resolve(process.cwd(), filename || process.env.CIRCUITRY_GRAPH || defaultFilename);
|
|
1186
|
-
}
|
|
1187
|
-
runFileFor(filename) {
|
|
1188
|
-
return `${filename}.run.json`;
|
|
1189
|
-
}
|
|
1190
|
-
async exists(filename) {
|
|
1191
|
-
try {
|
|
1192
|
-
await access(filename);
|
|
1193
|
-
return true;
|
|
1194
|
-
} catch {
|
|
1195
|
-
return false;
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
parseIssue(error, filename) {
|
|
1199
|
-
return {
|
|
1200
|
-
code: "parse_error",
|
|
1201
|
-
message: error instanceof Error ? error.message : String(error),
|
|
1202
|
-
path: [filename]
|
|
1203
|
-
};
|
|
1204
|
-
}
|
|
1205
|
-
parseGraphForValidation(text, filename, standard) {
|
|
1206
|
-
try {
|
|
1207
|
-
return {
|
|
1208
|
-
graph: parseCircuitryText(text || "", filename, standard, {
|
|
1209
|
-
validate: false
|
|
1210
|
-
})
|
|
1211
|
-
};
|
|
1212
|
-
} catch (error) {
|
|
1213
|
-
return { error: this.parseIssue(error, filename) };
|
|
1214
|
-
}
|
|
1215
|
-
}
|
|
1216
|
-
async readGraphFile(filename) {
|
|
1217
|
-
const graphFile = this.resolveGraphFile(filename);
|
|
1218
|
-
const text = await readFile(graphFile, "utf8");
|
|
1219
|
-
const graph = parseCircuitryText(text, graphFile);
|
|
1220
|
-
return { graphFile, text, graph };
|
|
1221
|
-
}
|
|
1222
|
-
async readGraph(input = {}) {
|
|
1223
|
-
const { graphFile, text, graph } = await this.readGraphFile(input.filename);
|
|
1224
|
-
const lastRunFile = this.runFileFor(graphFile);
|
|
1225
|
-
const lastRun = await this.exists(lastRunFile) ? JSON.parse(await readFile(lastRunFile, "utf8")) : undefined;
|
|
1226
|
-
return { filename: graphFile, graph, text, lastRun };
|
|
1227
|
-
}
|
|
1228
|
-
async validateGraph(input) {
|
|
1229
|
-
if (input.graph)
|
|
1230
|
-
return validateCircuitryGraphWithStandard(input.graph, input.standard);
|
|
1231
|
-
const filename = input.filename || defaultFilename;
|
|
1232
|
-
const parsed = this.parseGraphForValidation(input.text, filename, input.standard);
|
|
1233
|
-
if (parsed.error) {
|
|
1234
|
-
return {
|
|
1235
|
-
ok: false,
|
|
1236
|
-
errors: [parsed.error],
|
|
1237
|
-
standard: validateCircuitryGraphWithStandard({}, input.standard).standard
|
|
1238
|
-
};
|
|
1239
|
-
}
|
|
1240
|
-
return validateCircuitryGraphWithStandard(parsed.graph, input.standard);
|
|
1241
|
-
}
|
|
1242
|
-
async writeGraph(input) {
|
|
1243
|
-
const graphFile = this.resolveGraphFile(input.filename);
|
|
1244
|
-
const parsed = input.graph ? { graph: input.graph } : this.parseGraphForValidation(input.text, input.filename || graphFile, input.standard);
|
|
1245
|
-
if (!parsed.graph)
|
|
1246
|
-
throw new Error(`Invalid Circuitry graph:
|
|
1247
|
-
${parsed.error?.message}`);
|
|
1248
|
-
const validation = await this.validateGraph({
|
|
1249
|
-
graph: parsed.graph,
|
|
1250
|
-
standard: input.standard
|
|
1251
|
-
});
|
|
1252
|
-
if (validation.errors.length)
|
|
1253
|
-
throw new Error(`Invalid Circuitry graph:
|
|
1254
|
-
${validation.errors.map((e) => e.message).join(`
|
|
1255
|
-
`)}`);
|
|
1256
|
-
await writeFile(graphFile, stringifyCircuitryText(parsed.graph, graphFile), "utf8");
|
|
1257
|
-
return {
|
|
1258
|
-
filename: graphFile,
|
|
1259
|
-
graph: parsed.graph,
|
|
1260
|
-
mode: "replace"
|
|
1261
|
-
};
|
|
1262
|
-
}
|
|
1263
|
-
async runGraph(input = {}) {
|
|
1264
|
-
const source = input.source || (input.text ? "text" : "current");
|
|
1265
|
-
const graphFile = this.resolveGraphFile(input.filename);
|
|
1266
|
-
const parsed = source === "text" ? this.parseGraphForValidation(input.text, input.filename || graphFile, input.standard) : { graph: (await this.readGraphFile(input.filename)).graph };
|
|
1267
|
-
if (!parsed.graph)
|
|
1268
|
-
throw new Error(`Invalid Circuitry graph:
|
|
1269
|
-
${parsed.error?.message}`);
|
|
1270
|
-
const validation = await this.validateGraph({
|
|
1271
|
-
graph: parsed.graph,
|
|
1272
|
-
standard: input.standard
|
|
1273
|
-
});
|
|
1274
|
-
if (validation.errors.length)
|
|
1275
|
-
throw new Error(`Invalid Circuitry graph:
|
|
1276
|
-
${validation.errors.map((e) => e.message).join(`
|
|
1277
|
-
`)}`);
|
|
1278
|
-
const runItems = await runCircuitryGraphExecution({
|
|
1279
|
-
graph: parsed.graph,
|
|
1280
|
-
selectedNodeId: input.selectedNodeId,
|
|
1281
|
-
executeNode: (req) => runNodeWithPiSDK(req)
|
|
1282
|
-
});
|
|
1283
|
-
const result = { completedAt: new Date().toISOString(), runItems };
|
|
1284
|
-
if (source !== "text")
|
|
1285
|
-
await writeFile(this.runFileFor(graphFile), JSON.stringify(result, null, 2), "utf8");
|
|
1286
|
-
return result;
|
|
1287
|
-
}
|
|
1288
|
-
}
|
|
1289
1028
|
export {
|
|
1290
|
-
|
|
1291
|
-
validateCircuitryGraph,
|
|
1292
|
-
stringifyCircuitryYaml,
|
|
1293
|
-
stringifyCircuitryText,
|
|
1294
|
-
stringifyCircuitryJson,
|
|
1295
|
-
standardSchema,
|
|
1296
|
-
runNodeWithPiSDK,
|
|
1297
|
-
runGraphExecution,
|
|
1298
|
-
runDependencySimulation,
|
|
1299
|
-
runCircuitryGraphExecution,
|
|
1300
|
-
parseCircuitryYaml,
|
|
1301
|
-
parseCircuitryText,
|
|
1302
|
-
parseCircuitryJson,
|
|
1303
|
-
parseBundleText,
|
|
1304
|
-
parseAgentPresetMarkdown,
|
|
1305
|
-
normalizeCircuitryGraph,
|
|
1306
|
-
isUriInput,
|
|
1307
|
-
isNodeElement,
|
|
1308
|
-
importBundleElements,
|
|
1309
|
-
hasCircuitryNodeData,
|
|
1310
|
-
createUnsupportedRuntimeAdapter,
|
|
1311
|
-
createDefaultNodeData,
|
|
1312
|
-
createCircuitryWriteGraphTool,
|
|
1313
|
-
createCircuitryValidationStandard,
|
|
1314
|
-
createCircuitryValidateGraphTool,
|
|
1315
|
-
createCircuitryTools,
|
|
1316
|
-
createCircuitryRunGraphTool,
|
|
1317
|
-
createCircuitryReadGraphTool,
|
|
1318
|
-
createBundleFromSelection,
|
|
1319
|
-
buildSimulationGraph,
|
|
1320
|
-
buildCircuitryExecutionGraph,
|
|
1321
|
-
applyAgentPresets,
|
|
1322
|
-
NodeCircuitryHost,
|
|
1323
|
-
DEFAULT_MAX_PARALLEL_RUNS,
|
|
1324
|
-
DEFAULT_CIRCUITRY_VALIDATION_STANDARD,
|
|
1325
|
-
DEFAULT_CIRCUITRY_VALIDATION_RULES,
|
|
1326
|
-
CIRCUITRY_SPEC_VERSION_LEGACY,
|
|
1327
|
-
CIRCUITRY_SPEC_VERSION,
|
|
1328
|
-
CIRCUITRY_NODE_KIND,
|
|
1329
|
-
CIRCUITRY_NODE_CUSTOM_TYPE,
|
|
1029
|
+
BUNDLE_MIME,
|
|
1330
1030
|
CIRCUITRY_AGENT_PRESET_DIRS,
|
|
1331
|
-
|
|
1031
|
+
CIRCUITRY_NODE_CUSTOM_TYPE,
|
|
1032
|
+
CIRCUITRY_NODE_KIND,
|
|
1033
|
+
CIRCUITRY_SPEC_VERSION,
|
|
1034
|
+
CIRCUITRY_SPEC_VERSION_LEGACY,
|
|
1035
|
+
DEFAULT_CIRCUITRY_VALIDATION_RULES,
|
|
1036
|
+
DEFAULT_CIRCUITRY_VALIDATION_STANDARD,
|
|
1037
|
+
DEFAULT_MAX_PARALLEL_RUNS,
|
|
1038
|
+
applyAgentPresets,
|
|
1039
|
+
buildCircuitryExecutionGraph,
|
|
1040
|
+
buildSimulationGraph,
|
|
1041
|
+
createBundleFromSelection,
|
|
1042
|
+
createCircuitryValidationStandard,
|
|
1043
|
+
createDefaultNodeData,
|
|
1044
|
+
createUnsupportedRuntimeAdapter,
|
|
1045
|
+
hasCircuitryNodeData,
|
|
1046
|
+
importBundleElements,
|
|
1047
|
+
isNodeElement,
|
|
1048
|
+
isUriInput,
|
|
1049
|
+
normalizeCircuitryGraph,
|
|
1050
|
+
parseAgentPresetMarkdown,
|
|
1051
|
+
parseBundleText,
|
|
1052
|
+
parseCircuitryJson,
|
|
1053
|
+
parseCircuitryText,
|
|
1054
|
+
parseCircuitryYaml,
|
|
1055
|
+
runCircuitryGraphExecution,
|
|
1056
|
+
runDependencySimulation,
|
|
1057
|
+
runGraphExecution,
|
|
1058
|
+
stringifyCircuitryJson,
|
|
1059
|
+
stringifyCircuitryText,
|
|
1060
|
+
stringifyCircuitryYaml,
|
|
1061
|
+
validateCircuitryGraph,
|
|
1062
|
+
validateCircuitryGraphWithStandard
|
|
1332
1063
|
};
|