@darkhorseprojects/circuitry 0.2.14 → 0.2.16

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.
Files changed (2) hide show
  1. package/dist/index.js +243 -212
  2. package/package.json +1 -1
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((entry) => typeof entry !== "string" && entry.rule === "require-executable-inputs");
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,11 +169,14 @@ 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(standard, graph && typeof graph === "object" && !Array.isArray(graph) ? graph : undefined);
174
+ const resolvedStandard = createCircuitryValidationStandard(
175
+ standard,
176
+ graph && typeof graph === "object" && !Array.isArray(graph) ? graph : void 0
177
+ );
175
178
  const errors = [];
176
- const addError = (code, message, path2) => errors.push({ code, message, ...path2 ? { path: path2 } : {} });
179
+ const addError = (code, message, path3) => errors.push({ code, message, ...path3 ? { path: path3 } : {} });
177
180
  if (!graph || typeof graph !== "object" || Array.isArray(graph)) {
178
181
  addError("invalid_graph", "Circuitry graph must be an object");
179
182
  return { ok: false, errors, standard: resolvedStandard };
@@ -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("invalid_spec_version", `Expected circuitry: "${CIRCUITRY_SPEC_VERSION}"`, ["circuitry"]);
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,24 +251,21 @@ var validateCircuitryGraphWithStandard = (graph, standard = {}) => {
244
251
  }
245
252
  }
246
253
  }
247
- const visiting = new Set;
248
- const visited = new Set;
249
- const path = [];
254
+ const visiting = /* @__PURE__ */ new Set();
255
+ const visited = /* @__PURE__ */ new Set();
256
+ const path2 = [];
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
- cycleMessage = [...path.slice(path.indexOf(id)), id].join(" -> ");
261
+ cycleMessage = [...path2.slice(path2.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
- path.push(id);
262
- for (const next of adjacency.get(id) || [])
263
- visit(next);
264
- path.pop();
266
+ path2.push(id);
267
+ for (const next of adjacency.get(id) || []) visit(next);
268
+ path2.pop();
265
269
  visiting.delete(id);
266
270
  visited.add(id);
267
271
  };
@@ -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 !== undefined && value !== null && 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,47 +308,45 @@ 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
  }
315
315
  }
316
316
  continue;
317
317
  }
318
- const checkString = (target, subject, id, match, path2) => {
318
+ const checkString = (target, subject, id, match, path3) => {
319
319
  const value = getField(subject, match.field);
320
320
  const text = typeof value === "string" ? value : "";
321
321
  const includes = text.includes(match.value);
322
322
  if (rule.rule === "require-string" && !includes) {
323
- addError("missing_required_string", `${target} ${id} field ${match.field} must include string: ${match.value}`, path2);
323
+ addError("missing_required_string", `${target} ${id} field ${match.field} must include string: ${match.value}`, path3);
324
324
  }
325
325
  if (rule.rule === "reject-string" && includes) {
326
- addError("rejected_string", `${target} ${id} field ${match.field} must not include string: ${match.value}`, path2);
326
+ addError("rejected_string", `${target} ${id} field ${match.field} must not include string: ${match.value}`, path3);
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((error) => error.message);
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((input, index) => `Upstream ${index + 1} from ${input.nodeId}:
515
- ${input.output}`).join(`
516
-
517
- `) : "No upstream node outputs.";
518
- const contextSection = contextInputs.length ? contextInputs.map((input, index) => input.kind === "text" ? `Context ${index + 1} [text] from ${input.sourceId}:
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}` : ""}`).join(`
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
- `) : "- none"
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" ? undefined : agent.model) || (defaultModel === "inherit" ? undefined : defaultModel) || "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((sourceId) => executionGraph.nodes.has(sourceId)).length;
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(chunk.map(async (nodeId) => ({
685
- nodeId,
686
- result: await runOne(nodeId, outputs)
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(0, (remainingDependencies.get(outputNodeId) || 0) - 1);
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((input, index) => `Upstream ${index + 1} from ${input.nodeId}:
764
- ${input.output}`).join(`
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(await executeSimulationNode({
863
- node,
864
- fallbackCycle: false,
865
- inputPayload,
866
- contextInputs,
867
- executeNode,
868
- onNodeStart,
869
- onNodeComplete
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(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
- }));
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" && ("randomUUID" in crypto) ? crypto.randomUUID().replaceAll("-", "") : Math.random().toString(36).slice(2, 12);
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((item) => idMap.has(item.id) ? { ...item, id: idMap.get(item.id) } : item);
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,13 +1025,16 @@ var createUnsupportedRuntimeAdapter = (id) => ({
1020
1025
  throw new Error(`Circuitry runtime adapter is not configured: ${String(id)}`);
1021
1026
  }
1022
1027
  });
1028
+
1023
1029
  // src/tools.ts
1024
1030
  import { z } from "zod";
1025
1031
  var standardSchema = z.object({
1026
1032
  version: z.string().optional(),
1027
1033
  requireSpecVersion: z.boolean().optional(),
1028
1034
  executableKinds: z.array(z.string()).optional(),
1029
- rules: z.array(z.union([z.string(), z.object({ rule: z.string() }).passthrough()])).optional()
1035
+ rules: z.array(
1036
+ z.union([z.string(), z.object({ rule: z.string() }).passthrough()])
1037
+ ).optional()
1030
1038
  }).passthrough().optional();
1031
1039
  var createCircuitryReadGraphTool = (host) => ({
1032
1040
  name: "circuitry_read_graph",
@@ -1051,7 +1059,9 @@ var createCircuitryRunGraphTool = (host) => ({
1051
1059
  name: "circuitry_run_graph",
1052
1060
  description: "Run the current Circuitry graph. After running, call circuitry_read_graph to inspect updated per-node outputs and errors.",
1053
1061
  parameters: z.object({
1054
- source: z.enum(["current", "text"]).optional().describe("Whether to run the 'current' canvas/file or provided 'text'."),
1062
+ source: z.enum(["current", "text"]).optional().describe(
1063
+ "Whether to run the 'current' canvas/file or provided 'text'."
1064
+ ),
1055
1065
  text: z.string().optional().describe("YAML graph text if source is 'text'."),
1056
1066
  filename: z.string().optional().describe("Optional filename."),
1057
1067
  selectedNodeId: z.string().optional().describe("Optional specific node to run."),
@@ -1076,6 +1086,7 @@ var createCircuitryTools = (host) => [
1076
1086
  createCircuitryRunGraphTool(host),
1077
1087
  createCircuitryValidateGraphTool(host)
1078
1088
  ];
1089
+
1079
1090
  // src/node.ts
1080
1091
  import { access, readFile, writeFile } from "node:fs/promises";
1081
1092
  import fs from "node:fs";
@@ -1094,12 +1105,9 @@ var loadPiSDK = async () => {
1094
1105
  return await import("@earendil-works/pi-coding-agent");
1095
1106
  };
1096
1107
  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 "";
1108
+ if (!message || message.role !== "assistant") return "";
1109
+ if (typeof message.content === "string") return message.content;
1110
+ if (!Array.isArray(message.content)) return "";
1103
1111
  return message.content.filter((part) => part?.type === "text" && typeof part.text === "string").map((part) => part.text).join("");
1104
1112
  };
1105
1113
  var withTimeout = async (promise, timeoutMs) => {
@@ -1108,7 +1116,10 @@ var withTimeout = async (promise, timeoutMs) => {
1108
1116
  return await Promise.race([
1109
1117
  promise,
1110
1118
  new Promise((_, reject) => {
1111
- timeout = setTimeout(() => reject(new Error(`Pi SDK request timed out after ${timeoutMs}ms`)), timeoutMs);
1119
+ timeout = setTimeout(
1120
+ () => reject(new Error(`Pi SDK request timed out after ${timeoutMs}ms`)),
1121
+ timeoutMs
1122
+ );
1112
1123
  })
1113
1124
  ]);
1114
1125
  } finally {
@@ -1127,12 +1138,13 @@ var runNodeWithPiSDK = async ({
1127
1138
  sdk = await loadPiSDK();
1128
1139
  } catch (error) {
1129
1140
  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
- `));
1141
+ throw new Error(
1142
+ [
1143
+ "Circuitry could not load the Pi SDK package for execution.",
1144
+ "Ensure @earendil-works/pi-coding-agent is installed.",
1145
+ message
1146
+ ].join("\n")
1147
+ );
1136
1148
  }
1137
1149
  const { AuthStorage, ModelRegistry, SessionManager, createAgentSession } = sdk;
1138
1150
  const authStorage = AuthStorage.create();
@@ -1140,9 +1152,8 @@ var runNodeWithPiSDK = async ({
1140
1152
  const [provider, ...modelParts] = String(model || "").split("/");
1141
1153
  const modelId = modelParts.join("/");
1142
1154
  const available = await modelRegistry.getAvailable();
1143
- const selectedModel = (provider && modelId ? modelRegistry.find(provider, modelId) : undefined) || available.find((entry) => {
1144
- if (!modelId)
1145
- return false;
1155
+ const selectedModel = (provider && modelId ? modelRegistry.find(provider, modelId) : void 0) || available.find((entry) => {
1156
+ if (!modelId) return false;
1146
1157
  return `${entry.provider}/${entry.id}` === `${provider}/${modelId}` || entry.id === modelId;
1147
1158
  }) || available[0];
1148
1159
  if (!selectedModel) {
@@ -1171,7 +1182,7 @@ var runNodeWithPiSDK = async ({
1171
1182
  type: "image",
1172
1183
  source: { type: "base64", mediaType: image.mediaType, data: image.data }
1173
1184
  }));
1174
- await withTimeout(session.prompt(prompt, { images: promptImages }), 180000);
1185
+ await withTimeout(session.prompt(prompt, { images: promptImages }), 18e4);
1175
1186
  return { output: output.trim() };
1176
1187
  } finally {
1177
1188
  unsubscribe();
@@ -1179,10 +1190,12 @@ var runNodeWithPiSDK = async ({
1179
1190
  }
1180
1191
  };
1181
1192
  var defaultFilename = "graph.circuitry.yaml";
1182
-
1183
- class NodeCircuitryHost {
1193
+ var NodeCircuitryHost = class {
1184
1194
  resolveGraphFile(filename) {
1185
- return path.resolve(process.cwd(), filename || process.env.CIRCUITRY_GRAPH || defaultFilename);
1195
+ return path.resolve(
1196
+ process.cwd(),
1197
+ filename || process.env.CIRCUITRY_GRAPH || defaultFilename
1198
+ );
1186
1199
  }
1187
1200
  runFileFor(filename) {
1188
1201
  return `${filename}.run.json`;
@@ -1222,7 +1235,7 @@ class NodeCircuitryHost {
1222
1235
  async readGraph(input = {}) {
1223
1236
  const { graphFile, text, graph } = await this.readGraphFile(input.filename);
1224
1237
  const lastRunFile = this.runFileFor(graphFile);
1225
- const lastRun = await this.exists(lastRunFile) ? JSON.parse(await readFile(lastRunFile, "utf8")) : undefined;
1238
+ const lastRun = await this.exists(lastRunFile) ? JSON.parse(await readFile(lastRunFile, "utf8")) : void 0;
1226
1239
  return { filename: graphFile, graph, text, lastRun };
1227
1240
  }
1228
1241
  async validateGraph(input) {
@@ -1241,7 +1254,11 @@ class NodeCircuitryHost {
1241
1254
  }
1242
1255
  async writeGraph(input) {
1243
1256
  const graphFile = this.resolveGraphFile(input.filename);
1244
- const parsed = input.graph ? { graph: input.graph } : this.parseGraphForValidation(input.text, input.filename || graphFile, input.standard);
1257
+ const parsed = input.graph ? { graph: input.graph } : this.parseGraphForValidation(
1258
+ input.text,
1259
+ input.filename || graphFile,
1260
+ input.standard
1261
+ );
1245
1262
  if (!parsed.graph)
1246
1263
  throw new Error(`Invalid Circuitry graph:
1247
1264
  ${parsed.error?.message}`);
@@ -1250,10 +1267,15 @@ ${parsed.error?.message}`);
1250
1267
  standard: input.standard
1251
1268
  });
1252
1269
  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");
1270
+ throw new Error(
1271
+ `Invalid Circuitry graph:
1272
+ ${validation.errors.map((e) => e.message).join("\n")}`
1273
+ );
1274
+ await writeFile(
1275
+ graphFile,
1276
+ stringifyCircuitryText(parsed.graph, graphFile),
1277
+ "utf8"
1278
+ );
1257
1279
  return {
1258
1280
  filename: graphFile,
1259
1281
  graph: parsed.graph,
@@ -1263,7 +1285,11 @@ ${validation.errors.map((e) => e.message).join(`
1263
1285
  async runGraph(input = {}) {
1264
1286
  const source = input.source || (input.text ? "text" : "current");
1265
1287
  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 };
1288
+ const parsed = source === "text" ? this.parseGraphForValidation(
1289
+ input.text,
1290
+ input.filename || graphFile,
1291
+ input.standard
1292
+ ) : { graph: (await this.readGraphFile(input.filename)).graph };
1267
1293
  if (!parsed.graph)
1268
1294
  throw new Error(`Invalid Circuitry graph:
1269
1295
  ${parsed.error?.message}`);
@@ -1272,61 +1298,66 @@ ${parsed.error?.message}`);
1272
1298
  standard: input.standard
1273
1299
  });
1274
1300
  if (validation.errors.length)
1275
- throw new Error(`Invalid Circuitry graph:
1276
- ${validation.errors.map((e) => e.message).join(`
1277
- `)}`);
1301
+ throw new Error(
1302
+ `Invalid Circuitry graph:
1303
+ ${validation.errors.map((e) => e.message).join("\n")}`
1304
+ );
1278
1305
  const runItems = await runCircuitryGraphExecution({
1279
1306
  graph: parsed.graph,
1280
1307
  selectedNodeId: input.selectedNodeId,
1281
1308
  executeNode: (req) => runNodeWithPiSDK(req)
1282
1309
  });
1283
- const result = { completedAt: new Date().toISOString(), runItems };
1310
+ const result = { completedAt: (/* @__PURE__ */ new Date()).toISOString(), runItems };
1284
1311
  if (source !== "text")
1285
- await writeFile(this.runFileFor(graphFile), JSON.stringify(result, null, 2), "utf8");
1312
+ await writeFile(
1313
+ this.runFileFor(graphFile),
1314
+ JSON.stringify(result, null, 2),
1315
+ "utf8"
1316
+ );
1286
1317
  return result;
1287
1318
  }
1288
- }
1319
+ };
1289
1320
  export {
1290
- validateCircuitryGraphWithStandard,
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,
1321
+ BUNDLE_MIME,
1330
1322
  CIRCUITRY_AGENT_PRESET_DIRS,
1331
- BUNDLE_MIME
1323
+ CIRCUITRY_NODE_CUSTOM_TYPE,
1324
+ CIRCUITRY_NODE_KIND,
1325
+ CIRCUITRY_SPEC_VERSION,
1326
+ CIRCUITRY_SPEC_VERSION_LEGACY,
1327
+ DEFAULT_CIRCUITRY_VALIDATION_RULES,
1328
+ DEFAULT_CIRCUITRY_VALIDATION_STANDARD,
1329
+ DEFAULT_MAX_PARALLEL_RUNS,
1330
+ NodeCircuitryHost,
1331
+ applyAgentPresets,
1332
+ buildCircuitryExecutionGraph,
1333
+ buildSimulationGraph,
1334
+ createBundleFromSelection,
1335
+ createCircuitryReadGraphTool,
1336
+ createCircuitryRunGraphTool,
1337
+ createCircuitryTools,
1338
+ createCircuitryValidateGraphTool,
1339
+ createCircuitryValidationStandard,
1340
+ createCircuitryWriteGraphTool,
1341
+ createDefaultNodeData,
1342
+ createUnsupportedRuntimeAdapter,
1343
+ hasCircuitryNodeData,
1344
+ importBundleElements,
1345
+ isNodeElement,
1346
+ isUriInput,
1347
+ normalizeCircuitryGraph,
1348
+ parseAgentPresetMarkdown,
1349
+ parseBundleText,
1350
+ parseCircuitryJson,
1351
+ parseCircuitryText,
1352
+ parseCircuitryYaml,
1353
+ runCircuitryGraphExecution,
1354
+ runDependencySimulation,
1355
+ runGraphExecution,
1356
+ runNodeWithPiSDK,
1357
+ standardSchema,
1358
+ stringifyCircuitryJson,
1359
+ stringifyCircuitryText,
1360
+ stringifyCircuitryYaml,
1361
+ validateCircuitryGraph,
1362
+ validateCircuitryGraphWithStandard
1332
1363
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@darkhorseprojects/circuitry",
3
- "version": "0.2.14",
3
+ "version": "0.2.16",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",