@darkhorseprojects/circuitry 0.2.7 → 0.2.13

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