agent-contracts 0.6.1 → 0.7.1

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/cli.js CHANGED
@@ -11927,7 +11927,7 @@ var require_getJsonPathForPosition = __commonJS({
11927
11927
  return;
11928
11928
  return path;
11929
11929
  };
11930
- function* walk(node) {
11930
+ function* walk2(node) {
11931
11931
  switch (node.kind) {
11932
11932
  case types_1.Kind.MAP:
11933
11933
  if (node.mappings.length !== 0) {
@@ -11988,7 +11988,7 @@ var require_getJsonPathForPosition = __commonJS({
11988
11988
  return node;
11989
11989
  }
11990
11990
  function findClosestScalar(container, offset, line, lineMap) {
11991
- for (const node of walk(container)) {
11991
+ for (const node of walk2(container)) {
11992
11992
  if (node.startPosition <= offset && offset <= node.endPosition) {
11993
11993
  return node.kind === types_1.Kind.SCALAR ? node : findClosestScalar(node, offset, line, lineMap);
11994
11994
  }
@@ -58342,6 +58342,7 @@ var RenderTargetSchema = z.object({
58342
58342
  );
58343
58343
  var AgentContractsConfigSchema = z.object({
58344
58344
  dsl: z.string(),
58345
+ vars: z.record(z.string(), z.string()).optional(),
58345
58346
  renders: z.array(RenderTargetSchema).min(1)
58346
58347
  });
58347
58348
 
@@ -58410,6 +58411,7 @@ ${issues}`,
58410
58411
  const config = result.data;
58411
58412
  return {
58412
58413
  dsl: resolve(configDir, config.dsl),
58414
+ vars: config.vars,
58413
58415
  renders: config.renders.map((r3) => ({
58414
58416
  ...r3,
58415
58417
  template: resolve(configDir, r3.template),
@@ -58980,6 +58982,50 @@ async function resolve4(projectDirOrFile) {
58980
58982
  };
58981
58983
  }
58982
58984
 
58985
+ // src/resolver/substitute-vars.ts
58986
+ var VAR_PATTERN = /\$\{vars\.([a-zA-Z0-9_-]+)\}/g;
58987
+ var VarsSubstitutionError = class extends Error {
58988
+ constructor(varName, sourceValue, definedVars) {
58989
+ const defined = definedVars.length > 0 ? definedVars.join(", ") : "(none)";
58990
+ super(
58991
+ `Undefined variable "${varName}" in value "${sourceValue}"
58992
+ Defined vars: ${defined}`
58993
+ );
58994
+ this.varName = varName;
58995
+ this.sourceValue = sourceValue;
58996
+ this.definedVars = definedVars;
58997
+ this.name = "VarsSubstitutionError";
58998
+ }
58999
+ varName;
59000
+ sourceValue;
59001
+ definedVars;
59002
+ };
59003
+ function substituteString(value, vars) {
59004
+ return value.replace(VAR_PATTERN, (match, varName) => {
59005
+ if (!(varName in vars)) {
59006
+ throw new VarsSubstitutionError(varName, value, Object.keys(vars));
59007
+ }
59008
+ return vars[varName];
59009
+ });
59010
+ }
59011
+ function walk(data, vars) {
59012
+ if (typeof data === "string") return substituteString(data, vars);
59013
+ if (Array.isArray(data)) return data.map((item) => walk(item, vars));
59014
+ if (data !== null && typeof data === "object") {
59015
+ const result = {};
59016
+ for (const [key, value] of Object.entries(
59017
+ data
59018
+ )) {
59019
+ result[key] = walk(value, vars);
59020
+ }
59021
+ return result;
59022
+ }
59023
+ return data;
59024
+ }
59025
+ function substituteVars(data, vars) {
59026
+ return walk(data, vars);
59027
+ }
59028
+
58983
59029
  // src/cli/commands/resolve.ts
58984
59030
  import { stringify } from "yaml";
58985
59031
  var DIR_DEFAULT = "agent-contracts.yaml";
@@ -58988,10 +59034,11 @@ var resolveCommand = new Command("resolve").description("Resolve DSL (load + mer
58988
59034
  const config = await loadConfig(opts.config);
58989
59035
  const dslPath = resolveDslPath(dir, DIR_DEFAULT, config);
58990
59036
  const result = await resolve4(dslPath);
59037
+ const data = config?.vars ? substituteVars(result.data, config.vars) : result.data;
58991
59038
  if (opts.format === "json") {
58992
- process.stdout.write(JSON.stringify(result.data, null, 2) + "\n");
59039
+ process.stdout.write(JSON.stringify(data, null, 2) + "\n");
58993
59040
  } else {
58994
- process.stdout.write(stringify(result.data));
59041
+ process.stdout.write(stringify(data));
58995
59042
  }
58996
59043
  } catch (err) {
58997
59044
  const msg = err instanceof Error ? err.message : String(err);
@@ -59108,6 +59155,7 @@ var ExecutionStepSchema = z7.object({
59108
59155
  abort_on_failure: z7.boolean().optional(),
59109
59156
  uses_tool: z7.string().optional(),
59110
59157
  produces_artifact: z7.string().optional(),
59158
+ reads_artifact: z7.string().optional(),
59111
59159
  depends_on: z7.array(z7.string()).optional(),
59112
59160
  skip_condition: z7.string().optional(),
59113
59161
  wait_for_approval: z7.boolean().optional()
@@ -59178,6 +59226,7 @@ var WorkflowStepSchema = z10.discriminatedUnion("type", [
59178
59226
  WorkflowDecisionStepSchema
59179
59227
  ]);
59180
59228
  var WorkflowSchema = z10.object({
59229
+ description: z10.string().optional(),
59181
59230
  entry_conditions: z10.array(z10.string()).default([]),
59182
59231
  trigger: z10.string().optional(),
59183
59232
  steps: z10.array(WorkflowStepSchema)
@@ -59512,7 +59561,8 @@ var validateCommand = new Command2("validate").description("Validate DSL against
59512
59561
  const config = await loadConfig(opts.config);
59513
59562
  const dslPath = resolveDslPath(dir, DIR_DEFAULT2, config);
59514
59563
  const resolved = await resolve4(dslPath);
59515
- const schemaResult = validateSchema(resolved.data);
59564
+ const data = config?.vars ? substituteVars(resolved.data, config.vars) : resolved.data;
59565
+ const schemaResult = validateSchema(data);
59516
59566
  if (!schemaResult.success) {
59517
59567
  const output = formatDiagnostics(schemaResult.diagnostics, opts);
59518
59568
  if (output) process.stderr.write(output + "\n");
@@ -59757,6 +59807,16 @@ var taskAgentBindingRule = {
59757
59807
  });
59758
59808
  }
59759
59809
  }
59810
+ if (step.reads_artifact) {
59811
+ if (!targetAgent.can_read_artifacts.includes(step.reads_artifact)) {
59812
+ diagnostics.push({
59813
+ ruleId: "task-agent-binding",
59814
+ severity: "error",
59815
+ path: `tasks.${taskId}.execution_steps`,
59816
+ message: `Task "${taskId}" step reads_artifact "${step.reads_artifact}" not in target agent "${task.target_agent}" can_read_artifacts`
59817
+ });
59818
+ }
59819
+ }
59760
59820
  }
59761
59821
  }
59762
59822
  return diagnostics;
@@ -60376,7 +60436,8 @@ var lintCommand = new Command3("lint").description("Run semantic lint rules on r
60376
60436
  const config = await loadConfig(opts.config);
60377
60437
  const dslPath = resolveDslPath(dir, DIR_DEFAULT3, config);
60378
60438
  const resolved = await resolve4(dslPath);
60379
- const schemaResult = validateSchema(resolved.data);
60439
+ const data = config?.vars ? substituteVars(resolved.data, config.vars) : resolved.data;
60440
+ const schemaResult = validateSchema(data);
60380
60441
  if (!schemaResult.success) {
60381
60442
  const output = formatDiagnostics(schemaResult.diagnostics, {
60382
60443
  format: opts.format,
@@ -60434,12 +60495,76 @@ function buildTaskContext(dsl, taskId) {
60434
60495
  function buildArtifactContext(dsl, artifactId) {
60435
60496
  const artifactDef = dsl.artifacts[artifactId];
60436
60497
  const artifact = { ...artifactDef, id: artifactId };
60437
- return { artifact, dsl };
60498
+ const relatedTools = {};
60499
+ for (const [id, tool] of Object.entries(dsl.tools)) {
60500
+ if (tool.input_artifacts.includes(artifactId) || tool.output_artifacts.includes(artifactId)) {
60501
+ relatedTools[id] = tool;
60502
+ }
60503
+ }
60504
+ const relatedValidations = {};
60505
+ for (const [id, val] of Object.entries(dsl.validations)) {
60506
+ if (val.target_artifact === artifactId) {
60507
+ relatedValidations[id] = val;
60508
+ }
60509
+ }
60510
+ const pickAgents = (ids) => {
60511
+ const result = {};
60512
+ for (const id of ids) {
60513
+ if (dsl.agents[id]) result[id] = dsl.agents[id];
60514
+ }
60515
+ return result;
60516
+ };
60517
+ const producerAgents = pickAgents(artifactDef.producers);
60518
+ const consumerAgents = pickAgents(artifactDef.consumers);
60519
+ const editorAgents = pickAgents(artifactDef.editors);
60520
+ const createdInWorkflows = [];
60521
+ for (const [_taskId, task] of Object.entries(dsl.tasks)) {
60522
+ if (createdInWorkflows.includes(task.workflow)) continue;
60523
+ const targetAgent = dsl.agents[task.target_agent];
60524
+ if (targetAgent?.can_write_artifacts.includes(artifactId)) {
60525
+ createdInWorkflows.push(task.workflow);
60526
+ continue;
60527
+ }
60528
+ const steps = task.execution_steps ?? [];
60529
+ for (const step of steps) {
60530
+ if (step["produces_artifact"] === artifactId) {
60531
+ createdInWorkflows.push(task.workflow);
60532
+ break;
60533
+ }
60534
+ }
60535
+ }
60536
+ return {
60537
+ artifact,
60538
+ relatedTools,
60539
+ relatedValidations,
60540
+ producerAgents,
60541
+ consumerAgents,
60542
+ editorAgents,
60543
+ createdInWorkflows,
60544
+ dsl
60545
+ };
60438
60546
  }
60439
60547
  function buildToolContext(dsl, toolId) {
60440
60548
  const toolDef = dsl.tools[toolId];
60441
60549
  const tool = { ...toolDef, id: toolId };
60442
- return { tool, dsl };
60550
+ const invokableAgents = {};
60551
+ for (const agentId of toolDef.invokable_by) {
60552
+ if (dsl.agents[agentId]) invokableAgents[agentId] = dsl.agents[agentId];
60553
+ }
60554
+ const pickArtifacts = (ids) => {
60555
+ const result = {};
60556
+ for (const id of ids) {
60557
+ if (dsl.artifacts[id]) result[id] = dsl.artifacts[id];
60558
+ }
60559
+ return result;
60560
+ };
60561
+ return {
60562
+ tool,
60563
+ invokableAgents,
60564
+ inputArtifactDetails: pickArtifacts(toolDef.input_artifacts),
60565
+ outputArtifactDetails: pickArtifacts(toolDef.output_artifacts),
60566
+ dsl
60567
+ };
60443
60568
  }
60444
60569
  function buildValidationContext(dsl, validationId) {
60445
60570
  const validationDef = dsl.validations[validationId];
@@ -60457,7 +60582,85 @@ function buildHandoffTypeContext(dsl, handoffTypeId) {
60457
60582
  function buildWorkflowContext(dsl, workflowId) {
60458
60583
  const wfDef = dsl.workflow[workflowId];
60459
60584
  const workflow = { ...wfDef, id: workflowId };
60460
- return { workflow, dsl };
60585
+ const relatedTasks = Object.entries(dsl.tasks).filter(([, t3]) => t3.workflow === workflowId).map(([id, t3]) => ({ ...t3, id }));
60586
+ const agentIds = /* @__PURE__ */ new Set();
60587
+ for (const task of relatedTasks) {
60588
+ agentIds.add(task.target_agent);
60589
+ for (const fromAgent of task.allowed_from_agents) {
60590
+ agentIds.add(fromAgent);
60591
+ }
60592
+ }
60593
+ for (const step of wfDef.steps) {
60594
+ if (step.type === "handoff" && step.from_agent) {
60595
+ agentIds.add(step.from_agent);
60596
+ }
60597
+ if (step.type === "validation") {
60598
+ const val = dsl.validations[step.validation];
60599
+ if (val?.executor_type === "agent" && val.executor) {
60600
+ agentIds.add(val.executor);
60601
+ }
60602
+ }
60603
+ }
60604
+ const relatedAgents = {};
60605
+ for (const id of agentIds) {
60606
+ if (dsl.agents[id]) relatedAgents[id] = dsl.agents[id];
60607
+ }
60608
+ const toolIds = /* @__PURE__ */ new Set();
60609
+ for (const id of agentIds) {
60610
+ const agent = dsl.agents[id];
60611
+ if (agent) {
60612
+ for (const toolId of agent.can_execute_tools) {
60613
+ toolIds.add(toolId);
60614
+ }
60615
+ }
60616
+ }
60617
+ for (const task of relatedTasks) {
60618
+ for (const step of task.execution_steps ?? []) {
60619
+ if (step.uses_tool) toolIds.add(step.uses_tool);
60620
+ }
60621
+ }
60622
+ const relatedTools = {};
60623
+ for (const id of toolIds) {
60624
+ if (dsl.tools[id]) relatedTools[id] = dsl.tools[id];
60625
+ }
60626
+ const artifactIds = /* @__PURE__ */ new Set();
60627
+ for (const task of relatedTasks) {
60628
+ for (const artId of task.input_artifacts) artifactIds.add(artId);
60629
+ for (const step of task.execution_steps ?? []) {
60630
+ if (step.produces_artifact) artifactIds.add(step.produces_artifact);
60631
+ if (step.reads_artifact) artifactIds.add(step.reads_artifact);
60632
+ }
60633
+ }
60634
+ for (const id of agentIds) {
60635
+ const agent = dsl.agents[id];
60636
+ if (agent) {
60637
+ for (const artId of agent.can_read_artifacts) artifactIds.add(artId);
60638
+ for (const artId of agent.can_write_artifacts) artifactIds.add(artId);
60639
+ }
60640
+ }
60641
+ const relatedArtifacts = {};
60642
+ for (const id of artifactIds) {
60643
+ if (dsl.artifacts[id]) relatedArtifacts[id] = dsl.artifacts[id];
60644
+ }
60645
+ const validationIds = /* @__PURE__ */ new Set();
60646
+ for (const step of wfDef.steps) {
60647
+ if (step.type === "validation") {
60648
+ validationIds.add(step.validation);
60649
+ }
60650
+ }
60651
+ const relatedValidations = {};
60652
+ for (const id of validationIds) {
60653
+ if (dsl.validations[id]) relatedValidations[id] = dsl.validations[id];
60654
+ }
60655
+ return {
60656
+ workflow,
60657
+ relatedAgents,
60658
+ relatedTasks,
60659
+ relatedTools,
60660
+ relatedArtifacts,
60661
+ relatedValidations,
60662
+ dsl
60663
+ };
60461
60664
  }
60462
60665
  function buildPolicyContext(dsl, policyId) {
60463
60666
  const policyDef = dsl.policies[policyId];
@@ -60570,6 +60773,248 @@ function buildPerAgentContext(dsl, agent) {
60570
60773
  };
60571
60774
  }
60572
60775
 
60776
+ // src/renderer/sequence-diagram.ts
60777
+ function hashToColor(s2, saturation, lightness) {
60778
+ let hash = 0;
60779
+ for (const ch of s2) hash = (hash << 5) - hash + ch.charCodeAt(0) | 0;
60780
+ const h2 = (hash % 360 + 360) % 360;
60781
+ const c2 = (1 - Math.abs(2 * lightness - 1)) * saturation;
60782
+ const x3 = c2 * (1 - Math.abs(h2 / 60 % 2 - 1));
60783
+ const m2 = lightness - c2 / 2;
60784
+ let r3 = 0, g2 = 0, b3 = 0;
60785
+ if (h2 < 60) {
60786
+ r3 = c2;
60787
+ g2 = x3;
60788
+ } else if (h2 < 120) {
60789
+ r3 = x3;
60790
+ g2 = c2;
60791
+ } else if (h2 < 180) {
60792
+ g2 = c2;
60793
+ b3 = x3;
60794
+ } else if (h2 < 240) {
60795
+ g2 = x3;
60796
+ b3 = c2;
60797
+ } else if (h2 < 300) {
60798
+ r3 = x3;
60799
+ b3 = c2;
60800
+ } else {
60801
+ r3 = c2;
60802
+ b3 = x3;
60803
+ }
60804
+ return `rgb(${Math.round((r3 + m2) * 255)},${Math.round((g2 + m2) * 255)},${Math.round((b3 + m2) * 255)})`;
60805
+ }
60806
+ function sanitizeAlias(id) {
60807
+ return id.replace(/[^a-zA-Z0-9_]/g, "_");
60808
+ }
60809
+ function agentAlias(id, agent) {
60810
+ const words = agent.role_name.split(/\s+/);
60811
+ if (words.length === 1) return sanitizeAlias(words[0].slice(0, 4));
60812
+ return sanitizeAlias(words.map((w2) => w2[0]).join(""));
60813
+ }
60814
+ function collectReferencedIds(workflow, dsl, relatedTasks) {
60815
+ const agents = /* @__PURE__ */ new Set();
60816
+ const tools = /* @__PURE__ */ new Set();
60817
+ const artifacts = /* @__PURE__ */ new Set();
60818
+ const taskMap = /* @__PURE__ */ new Map();
60819
+ for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
60820
+ for (const step of workflow.steps) {
60821
+ if (step.type === "handoff") {
60822
+ if (step.from_agent) agents.add(step.from_agent);
60823
+ if (step.task) {
60824
+ const task = taskMap.get(step.task);
60825
+ if (task) {
60826
+ agents.add(task.target_agent);
60827
+ for (const es of task.execution_steps ?? []) {
60828
+ collectExecutionStepIds(es, tools, artifacts);
60829
+ }
60830
+ }
60831
+ }
60832
+ } else if (step.type === "validation") {
60833
+ const val = dsl.validations[step.validation];
60834
+ if (val) {
60835
+ if (val.executor_type === "agent") agents.add(val.executor);
60836
+ else tools.add(val.executor);
60837
+ artifacts.add(val.target_artifact);
60838
+ }
60839
+ } else if (step.type === "decision") {
60840
+ }
60841
+ }
60842
+ return { agents, tools, artifacts };
60843
+ }
60844
+ function collectExecutionStepIds(es, tools, artifacts) {
60845
+ if (es.uses_tool) tools.add(es.uses_tool);
60846
+ if (es.produces_artifact) artifacts.add(es.produces_artifact);
60847
+ if (es.reads_artifact) artifacts.add(es.reads_artifact);
60848
+ }
60849
+ function buildParticipants(ids, dsl) {
60850
+ const participants = [];
60851
+ const usedAliases = /* @__PURE__ */ new Set();
60852
+ function uniqueAlias(preferred) {
60853
+ let alias = preferred;
60854
+ let i3 = 2;
60855
+ while (usedAliases.has(alias)) {
60856
+ alias = `${preferred}${i3}`;
60857
+ i3++;
60858
+ }
60859
+ usedAliases.add(alias);
60860
+ return alias;
60861
+ }
60862
+ for (const id of ids.agents) {
60863
+ const agent = dsl.agents[id];
60864
+ if (!agent) continue;
60865
+ const alias = uniqueAlias(agentAlias(id, agent));
60866
+ participants.push({ id, alias, label: agent.role_name, group: "agents" });
60867
+ }
60868
+ for (const id of ids.tools) {
60869
+ const tool = dsl.tools[id];
60870
+ if (!tool) continue;
60871
+ const alias = uniqueAlias(sanitizeAlias(id));
60872
+ participants.push({ id, alias, label: id, group: "toolchain" });
60873
+ }
60874
+ for (const id of ids.artifacts) {
60875
+ const art = dsl.artifacts[id];
60876
+ if (!art) continue;
60877
+ const alias = uniqueAlias(sanitizeAlias(id));
60878
+ participants.push({ id, alias, label: id, group: "artifacts" });
60879
+ }
60880
+ return participants;
60881
+ }
60882
+ function participantAlias(participants, id) {
60883
+ const p2 = participants.find((pp) => pp.id === id);
60884
+ return p2 ? p2.alias : sanitizeAlias(id);
60885
+ }
60886
+ function emitParticipants(participants, lines, indent) {
60887
+ const groups = {
60888
+ agents: [],
60889
+ toolchain: [],
60890
+ artifacts: []
60891
+ };
60892
+ for (const p2 of participants) groups[p2.group].push(p2);
60893
+ const groupConfig = [
60894
+ { key: "agents", label: "Agents", color: "rgb(200,220,255)" },
60895
+ { key: "toolchain", label: "Toolchain", color: "rgb(220,255,220)" },
60896
+ { key: "artifacts", label: "Artifacts", color: "rgb(255,230,210)" }
60897
+ ];
60898
+ for (const { key, label, color } of groupConfig) {
60899
+ const members = groups[key];
60900
+ if (members.length === 0) continue;
60901
+ lines.push(`${indent}box ${color} ${label}`);
60902
+ for (const p2 of members) {
60903
+ if (p2.alias === p2.label) {
60904
+ lines.push(`${indent}participant ${p2.alias}`);
60905
+ } else {
60906
+ lines.push(`${indent}participant ${p2.alias} as ${p2.label}`);
60907
+ }
60908
+ }
60909
+ lines.push(`${indent}end`);
60910
+ }
60911
+ }
60912
+ function emitHandoffStep(step, participants, dsl, relatedTasks, lines, indent) {
60913
+ const taskMap = /* @__PURE__ */ new Map();
60914
+ for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
60915
+ if (!step.task) {
60916
+ if (step.from_agent) {
60917
+ const fromAlias2 = participantAlias(participants, step.from_agent);
60918
+ lines.push(`${indent}${fromAlias2}->>${fromAlias2}: ${step.handoff_kind}`);
60919
+ }
60920
+ return;
60921
+ }
60922
+ const task = taskMap.get(step.task);
60923
+ if (!task) return;
60924
+ const fromAlias = step.from_agent ? participantAlias(participants, step.from_agent) : null;
60925
+ const targetAlias = participantAlias(participants, task.target_agent);
60926
+ if (fromAlias) {
60927
+ lines.push(`${indent}${fromAlias}->>${targetAlias}: delegate ${step.task}`);
60928
+ }
60929
+ for (const es of task.execution_steps ?? []) {
60930
+ emitExecutionStep(es, targetAlias, participants, lines, indent);
60931
+ }
60932
+ if (fromAlias) {
60933
+ lines.push(`${indent}${targetAlias}-->>${fromAlias}: ${task.result_handoff}`);
60934
+ }
60935
+ }
60936
+ function emitExecutionStep(es, agentAlias2, participants, lines, indent) {
60937
+ if (es.reads_artifact) {
60938
+ const artAlias = participantAlias(participants, es.reads_artifact);
60939
+ lines.push(`${indent}${agentAlias2}->>${artAlias}: [R] ${es.action}`);
60940
+ }
60941
+ if (es.produces_artifact) {
60942
+ const artAlias = participantAlias(participants, es.produces_artifact);
60943
+ lines.push(`${indent}${agentAlias2}->>${artAlias}: [W] ${es.action}`);
60944
+ }
60945
+ if (es.uses_tool) {
60946
+ const toolAlias = participantAlias(participants, es.uses_tool);
60947
+ lines.push(`${indent}${agentAlias2}->>${toolAlias}: ${es.action}`);
60948
+ }
60949
+ if (!es.reads_artifact && !es.produces_artifact && !es.uses_tool) {
60950
+ lines.push(`${indent}${agentAlias2}->>${agentAlias2}: ${es.action}`);
60951
+ }
60952
+ }
60953
+ function emitValidationStep(step, participants, dsl, lastFromAgent, lines, indent) {
60954
+ const val = dsl.validations[step.validation];
60955
+ if (!val) return;
60956
+ const executorAlias = participantAlias(participants, val.executor);
60957
+ const artifactAlias = participantAlias(participants, val.target_artifact);
60958
+ const fromAlias = lastFromAgent ? participantAlias(participants, lastFromAgent) : null;
60959
+ if (fromAlias && fromAlias !== executorAlias) {
60960
+ lines.push(`${indent}${fromAlias}->>${executorAlias}: ${step.validation}`);
60961
+ }
60962
+ lines.push(`${indent}${executorAlias}->>${artifactAlias}: [R] ${val.target_artifact}`);
60963
+ if (fromAlias && fromAlias !== executorAlias) {
60964
+ lines.push(`${indent}${executorAlias}-->>${fromAlias}: results`);
60965
+ }
60966
+ }
60967
+ function emitDecisionStep(step, participants, lastFromAgent, lines, indent) {
60968
+ const branches = Object.entries(step.branches);
60969
+ if (branches.length === 0) return;
60970
+ const agentAlias2 = lastFromAgent ? participantAlias(participants, lastFromAgent) : null;
60971
+ for (let i3 = 0; i3 < branches.length; i3++) {
60972
+ const [key, values] = branches[i3];
60973
+ if (i3 === 0) {
60974
+ lines.push(`${indent}alt ${key}`);
60975
+ } else {
60976
+ lines.push(`${indent}else ${key}`);
60977
+ }
60978
+ if (agentAlias2) {
60979
+ lines.push(`${indent} Note over ${agentAlias2}: ${values.join(", ")}`);
60980
+ } else {
60981
+ lines.push(`${indent} Note right of ${participantAlias(participants, [.../* @__PURE__ */ new Set()].join(""))}: ${values.join(", ")}`);
60982
+ }
60983
+ }
60984
+ lines.push(`${indent}end`);
60985
+ }
60986
+ function generateSequenceDiagram(workflow, relatedTasks, dsl) {
60987
+ const ids = collectReferencedIds(workflow, dsl, relatedTasks);
60988
+ const participants = buildParticipants(ids, dsl);
60989
+ const lines = [];
60990
+ const indent = " ";
60991
+ lines.push("sequenceDiagram");
60992
+ emitParticipants(participants, lines, indent);
60993
+ lines.push("");
60994
+ lines.push(`${indent}rect ${hashToColor(workflow.id, 0.15, 0.95)}`);
60995
+ const firstP = participants[0];
60996
+ const lastP = participants[participants.length - 1];
60997
+ if (firstP && lastP) {
60998
+ const noteLabel = workflow.description ? `${workflow.id} \u2014 ${workflow.description}` : workflow.id;
60999
+ lines.push(`${indent}Note over ${firstP.alias},${lastP.alias}: ${noteLabel}`);
61000
+ }
61001
+ let lastFromAgent;
61002
+ for (const step of workflow.steps) {
61003
+ lines.push("");
61004
+ if (step.type === "handoff") {
61005
+ if (step.from_agent) lastFromAgent = step.from_agent;
61006
+ emitHandoffStep(step, participants, dsl, relatedTasks, lines, indent);
61007
+ } else if (step.type === "validation") {
61008
+ emitValidationStep(step, participants, dsl, lastFromAgent, lines, indent);
61009
+ } else if (step.type === "decision") {
61010
+ emitDecisionStep(step, participants, lastFromAgent, lines, indent);
61011
+ }
61012
+ }
61013
+ lines.push("");
61014
+ lines.push(`${indent}end`);
61015
+ return lines.join("\n");
61016
+ }
61017
+
60573
61018
  // src/renderer/renderer.ts
60574
61019
  Handlebars.registerHelper("eq", (a3, b3) => a3 === b3);
60575
61020
  Handlebars.registerHelper("notEmpty", (obj) => {
@@ -60665,6 +61110,82 @@ function toYamlLines(obj, indent) {
60665
61110
  Handlebars.registerHelper("yamlBlock", (obj) => {
60666
61111
  return toYamlLines(obj, 0).join("\n");
60667
61112
  });
61113
+ Handlebars.registerHelper(
61114
+ "join",
61115
+ (arr, separator) => {
61116
+ if (!Array.isArray(arr)) return "";
61117
+ const sep = typeof separator === "string" ? separator : ", ";
61118
+ return arr.join(sep);
61119
+ }
61120
+ );
61121
+ Handlebars.registerHelper("contains", (arr, value) => {
61122
+ if (!Array.isArray(arr)) return false;
61123
+ return arr.includes(value);
61124
+ });
61125
+ Handlebars.registerHelper(
61126
+ "groupBy",
61127
+ (arr, key) => {
61128
+ if (!Array.isArray(arr)) return {};
61129
+ const result = {};
61130
+ for (const item of arr) {
61131
+ const k2 = String(
61132
+ item?.[key] ?? "undefined"
61133
+ );
61134
+ (result[k2] ??= []).push(item);
61135
+ }
61136
+ return result;
61137
+ }
61138
+ );
61139
+ Handlebars.registerHelper(
61140
+ "keys",
61141
+ (obj) => {
61142
+ if (!obj || typeof obj !== "object") return [];
61143
+ return Object.keys(obj);
61144
+ }
61145
+ );
61146
+ Handlebars.registerHelper(
61147
+ "values",
61148
+ (obj) => {
61149
+ if (!obj || typeof obj !== "object") return [];
61150
+ return Object.values(obj);
61151
+ }
61152
+ );
61153
+ Handlebars.registerHelper(
61154
+ "filterByField",
61155
+ (arr, field, value) => {
61156
+ if (!Array.isArray(arr)) return [];
61157
+ return arr.filter(
61158
+ (item) => item?.[field] === value
61159
+ );
61160
+ }
61161
+ );
61162
+ Handlebars.registerHelper("not", (value) => !value);
61163
+ Handlebars.registerHelper("or", (...args) => {
61164
+ const _options = args.pop();
61165
+ return args.some((a3) => !!a3);
61166
+ });
61167
+ Handlebars.registerHelper("and", (...args) => {
61168
+ const _options = args.pop();
61169
+ return args.every((a3) => !!a3);
61170
+ });
61171
+ Handlebars.registerHelper("gt", (a3, b3) => a3 > b3);
61172
+ Handlebars.registerHelper("gte", (a3, b3) => a3 >= b3);
61173
+ Handlebars.registerHelper("lt", (a3, b3) => a3 < b3);
61174
+ Handlebars.registerHelper("size", (obj) => {
61175
+ if (Array.isArray(obj)) return obj.length;
61176
+ if (obj && typeof obj === "object") return Object.keys(obj).length;
61177
+ return 0;
61178
+ });
61179
+ Handlebars.registerHelper(
61180
+ "sequenceDiagram",
61181
+ function() {
61182
+ const workflow = this["workflow"];
61183
+ const relatedTasks = this["relatedTasks"];
61184
+ const dsl = this["dsl"];
61185
+ if (!workflow || !dsl) return "";
61186
+ return generateSequenceDiagram(workflow, relatedTasks ?? [], dsl);
61187
+ }
61188
+ );
60668
61189
  function getDslSection(dsl, context) {
60669
61190
  const sectionMap = {
60670
61191
  agent: dsl.agents,
@@ -60787,7 +61308,8 @@ var renderCommand = new Command4("render").description("Render resolved DSL with
60787
61308
  process.exit(1);
60788
61309
  }
60789
61310
  const resolved = await resolve4(config.dsl);
60790
- const schemaResult = validateSchema(resolved.data);
61311
+ const data = config.vars ? substituteVars(resolved.data, config.vars) : resolved.data;
61312
+ const schemaResult = validateSchema(data);
60791
61313
  if (!schemaResult.success) {
60792
61314
  process.stderr.write(
60793
61315
  "Schema validation failed. Run 'agent-contracts validate' for details.\n"
@@ -60852,7 +61374,8 @@ var checkCommand = new Command5("check").description("Run full pipeline: resolve
60852
61374
  process.exit(1);
60853
61375
  }
60854
61376
  const resolved = await resolve4(config.dsl);
60855
- const schemaResult = validateSchema(resolved.data);
61377
+ const data = config.vars ? substituteVars(resolved.data, config.vars) : resolved.data;
61378
+ const schemaResult = validateSchema(data);
60856
61379
  if (!schemaResult.success) {
60857
61380
  const output = formatDiagnostics(schemaResult.diagnostics, {
60858
61381
  format: opts.format,