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/index.d.ts CHANGED
@@ -168,6 +168,7 @@ declare const DslSchema: z.ZodObject<{
168
168
  abort_on_failure: z.ZodOptional<z.ZodBoolean>;
169
169
  uses_tool: z.ZodOptional<z.ZodString>;
170
170
  produces_artifact: z.ZodOptional<z.ZodString>;
171
+ reads_artifact: z.ZodOptional<z.ZodString>;
171
172
  depends_on: z.ZodOptional<z.ZodArray<z.ZodString>>;
172
173
  skip_condition: z.ZodOptional<z.ZodString>;
173
174
  wait_for_approval: z.ZodOptional<z.ZodBoolean>;
@@ -238,6 +239,7 @@ declare const DslSchema: z.ZodObject<{
238
239
  example: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
239
240
  }, z.core.$loose>>>;
240
241
  workflow: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
242
+ description: z.ZodOptional<z.ZodString>;
241
243
  entry_conditions: z.ZodDefault<z.ZodArray<z.ZodString>>;
242
244
  trigger: z.ZodOptional<z.ZodString>;
243
245
  steps: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -348,6 +350,7 @@ declare const ExecutionStepSchema: z.ZodObject<{
348
350
  abort_on_failure: z.ZodOptional<z.ZodBoolean>;
349
351
  uses_tool: z.ZodOptional<z.ZodString>;
350
352
  produces_artifact: z.ZodOptional<z.ZodString>;
353
+ reads_artifact: z.ZodOptional<z.ZodString>;
351
354
  depends_on: z.ZodOptional<z.ZodArray<z.ZodString>>;
352
355
  skip_condition: z.ZodOptional<z.ZodString>;
353
356
  wait_for_approval: z.ZodOptional<z.ZodBoolean>;
@@ -372,6 +375,7 @@ declare const TaskSchema: z.ZodObject<{
372
375
  abort_on_failure: z.ZodOptional<z.ZodBoolean>;
373
376
  uses_tool: z.ZodOptional<z.ZodString>;
374
377
  produces_artifact: z.ZodOptional<z.ZodString>;
378
+ reads_artifact: z.ZodOptional<z.ZodString>;
375
379
  depends_on: z.ZodOptional<z.ZodArray<z.ZodString>>;
376
380
  skip_condition: z.ZodOptional<z.ZodString>;
377
381
  wait_for_approval: z.ZodOptional<z.ZodBoolean>;
@@ -448,6 +452,7 @@ declare const WorkflowStepSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
448
452
  }, z.core.$loose>], "type">;
449
453
  type WorkflowStep = z.infer<typeof WorkflowStepSchema>;
450
454
  declare const WorkflowSchema: z.ZodObject<{
455
+ description: z.ZodOptional<z.ZodString>;
451
456
  entry_conditions: z.ZodDefault<z.ZodArray<z.ZodString>>;
452
457
  trigger: z.ZodOptional<z.ZodString>;
453
458
  steps: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -571,6 +576,7 @@ declare const RenderTargetSchema: z.ZodObject<{
571
576
  type RenderTarget = z.infer<typeof RenderTargetSchema>;
572
577
  declare const AgentContractsConfigSchema: z.ZodObject<{
573
578
  dsl: z.ZodString;
579
+ vars: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
574
580
  renders: z.ZodArray<z.ZodObject<{
575
581
  template: z.ZodString;
576
582
  context: z.ZodEnum<{
@@ -599,6 +605,7 @@ interface ResolvedRenderTarget {
599
605
  }
600
606
  interface ResolvedConfig {
601
607
  dsl: string;
608
+ vars?: Record<string, string>;
602
609
  renders: ResolvedRenderTarget[];
603
610
  configDir: string;
604
611
  }
@@ -640,6 +647,12 @@ interface PerArtifactContext {
640
647
  artifact: Artifact & {
641
648
  id: string;
642
649
  };
650
+ relatedTools: Dsl["tools"];
651
+ relatedValidations: Dsl["validations"];
652
+ producerAgents: Dsl["agents"];
653
+ consumerAgents: Dsl["agents"];
654
+ editorAgents: Dsl["agents"];
655
+ createdInWorkflows: string[];
643
656
  dsl: Dsl;
644
657
  [key: string]: unknown;
645
658
  }
@@ -647,6 +660,9 @@ interface PerToolContext {
647
660
  tool: Tool & {
648
661
  id: string;
649
662
  };
663
+ invokableAgents: Dsl["agents"];
664
+ inputArtifactDetails: Dsl["artifacts"];
665
+ outputArtifactDetails: Dsl["artifacts"];
650
666
  dsl: Dsl;
651
667
  [key: string]: unknown;
652
668
  }
@@ -671,6 +687,13 @@ interface PerWorkflowContext {
671
687
  workflow: Workflow & {
672
688
  id: string;
673
689
  };
690
+ relatedAgents: Dsl["agents"];
691
+ relatedTasks: Array<(Task & Record<string, unknown>) & {
692
+ id: string;
693
+ }>;
694
+ relatedTools: Dsl["tools"];
695
+ relatedArtifacts: Dsl["artifacts"];
696
+ relatedValidations: Dsl["validations"];
674
697
  dsl: Dsl;
675
698
  [key: string]: unknown;
676
699
  }
package/dist/index.js CHANGED
@@ -58399,6 +58399,7 @@ var ExecutionStepSchema = z6.object({
58399
58399
  abort_on_failure: z6.boolean().optional(),
58400
58400
  uses_tool: z6.string().optional(),
58401
58401
  produces_artifact: z6.string().optional(),
58402
+ reads_artifact: z6.string().optional(),
58402
58403
  depends_on: z6.array(z6.string()).optional(),
58403
58404
  skip_condition: z6.string().optional(),
58404
58405
  wait_for_approval: z6.boolean().optional()
@@ -58469,6 +58470,7 @@ var WorkflowStepSchema = z9.discriminatedUnion("type", [
58469
58470
  WorkflowDecisionStepSchema
58470
58471
  ]);
58471
58472
  var WorkflowSchema = z9.object({
58473
+ description: z9.string().optional(),
58472
58474
  entry_conditions: z9.array(z9.string()).default([]),
58473
58475
  trigger: z9.string().optional(),
58474
58476
  steps: z9.array(WorkflowStepSchema)
@@ -59553,6 +59555,16 @@ var taskAgentBindingRule = {
59553
59555
  });
59554
59556
  }
59555
59557
  }
59558
+ if (step.reads_artifact) {
59559
+ if (!targetAgent.can_read_artifacts.includes(step.reads_artifact)) {
59560
+ diagnostics.push({
59561
+ ruleId: "task-agent-binding",
59562
+ severity: "error",
59563
+ path: `tasks.${taskId}.execution_steps`,
59564
+ message: `Task "${taskId}" step reads_artifact "${step.reads_artifact}" not in target agent "${task.target_agent}" can_read_artifacts`
59565
+ });
59566
+ }
59567
+ }
59556
59568
  }
59557
59569
  }
59558
59570
  return diagnostics;
@@ -60196,12 +60208,76 @@ function buildTaskContext(dsl, taskId) {
60196
60208
  function buildArtifactContext(dsl, artifactId) {
60197
60209
  const artifactDef = dsl.artifacts[artifactId];
60198
60210
  const artifact = { ...artifactDef, id: artifactId };
60199
- return { artifact, dsl };
60211
+ const relatedTools = {};
60212
+ for (const [id, tool] of Object.entries(dsl.tools)) {
60213
+ if (tool.input_artifacts.includes(artifactId) || tool.output_artifacts.includes(artifactId)) {
60214
+ relatedTools[id] = tool;
60215
+ }
60216
+ }
60217
+ const relatedValidations = {};
60218
+ for (const [id, val] of Object.entries(dsl.validations)) {
60219
+ if (val.target_artifact === artifactId) {
60220
+ relatedValidations[id] = val;
60221
+ }
60222
+ }
60223
+ const pickAgents = (ids) => {
60224
+ const result = {};
60225
+ for (const id of ids) {
60226
+ if (dsl.agents[id]) result[id] = dsl.agents[id];
60227
+ }
60228
+ return result;
60229
+ };
60230
+ const producerAgents = pickAgents(artifactDef.producers);
60231
+ const consumerAgents = pickAgents(artifactDef.consumers);
60232
+ const editorAgents = pickAgents(artifactDef.editors);
60233
+ const createdInWorkflows = [];
60234
+ for (const [_taskId, task] of Object.entries(dsl.tasks)) {
60235
+ if (createdInWorkflows.includes(task.workflow)) continue;
60236
+ const targetAgent = dsl.agents[task.target_agent];
60237
+ if (targetAgent?.can_write_artifacts.includes(artifactId)) {
60238
+ createdInWorkflows.push(task.workflow);
60239
+ continue;
60240
+ }
60241
+ const steps = task.execution_steps ?? [];
60242
+ for (const step of steps) {
60243
+ if (step["produces_artifact"] === artifactId) {
60244
+ createdInWorkflows.push(task.workflow);
60245
+ break;
60246
+ }
60247
+ }
60248
+ }
60249
+ return {
60250
+ artifact,
60251
+ relatedTools,
60252
+ relatedValidations,
60253
+ producerAgents,
60254
+ consumerAgents,
60255
+ editorAgents,
60256
+ createdInWorkflows,
60257
+ dsl
60258
+ };
60200
60259
  }
60201
60260
  function buildToolContext(dsl, toolId) {
60202
60261
  const toolDef = dsl.tools[toolId];
60203
60262
  const tool = { ...toolDef, id: toolId };
60204
- return { tool, dsl };
60263
+ const invokableAgents = {};
60264
+ for (const agentId of toolDef.invokable_by) {
60265
+ if (dsl.agents[agentId]) invokableAgents[agentId] = dsl.agents[agentId];
60266
+ }
60267
+ const pickArtifacts = (ids) => {
60268
+ const result = {};
60269
+ for (const id of ids) {
60270
+ if (dsl.artifacts[id]) result[id] = dsl.artifacts[id];
60271
+ }
60272
+ return result;
60273
+ };
60274
+ return {
60275
+ tool,
60276
+ invokableAgents,
60277
+ inputArtifactDetails: pickArtifacts(toolDef.input_artifacts),
60278
+ outputArtifactDetails: pickArtifacts(toolDef.output_artifacts),
60279
+ dsl
60280
+ };
60205
60281
  }
60206
60282
  function buildValidationContext(dsl, validationId) {
60207
60283
  const validationDef = dsl.validations[validationId];
@@ -60219,7 +60295,85 @@ function buildHandoffTypeContext(dsl, handoffTypeId) {
60219
60295
  function buildWorkflowContext(dsl, workflowId) {
60220
60296
  const wfDef = dsl.workflow[workflowId];
60221
60297
  const workflow = { ...wfDef, id: workflowId };
60222
- return { workflow, dsl };
60298
+ const relatedTasks = Object.entries(dsl.tasks).filter(([, t3]) => t3.workflow === workflowId).map(([id, t3]) => ({ ...t3, id }));
60299
+ const agentIds = /* @__PURE__ */ new Set();
60300
+ for (const task of relatedTasks) {
60301
+ agentIds.add(task.target_agent);
60302
+ for (const fromAgent of task.allowed_from_agents) {
60303
+ agentIds.add(fromAgent);
60304
+ }
60305
+ }
60306
+ for (const step of wfDef.steps) {
60307
+ if (step.type === "handoff" && step.from_agent) {
60308
+ agentIds.add(step.from_agent);
60309
+ }
60310
+ if (step.type === "validation") {
60311
+ const val = dsl.validations[step.validation];
60312
+ if (val?.executor_type === "agent" && val.executor) {
60313
+ agentIds.add(val.executor);
60314
+ }
60315
+ }
60316
+ }
60317
+ const relatedAgents = {};
60318
+ for (const id of agentIds) {
60319
+ if (dsl.agents[id]) relatedAgents[id] = dsl.agents[id];
60320
+ }
60321
+ const toolIds = /* @__PURE__ */ new Set();
60322
+ for (const id of agentIds) {
60323
+ const agent = dsl.agents[id];
60324
+ if (agent) {
60325
+ for (const toolId of agent.can_execute_tools) {
60326
+ toolIds.add(toolId);
60327
+ }
60328
+ }
60329
+ }
60330
+ for (const task of relatedTasks) {
60331
+ for (const step of task.execution_steps ?? []) {
60332
+ if (step.uses_tool) toolIds.add(step.uses_tool);
60333
+ }
60334
+ }
60335
+ const relatedTools = {};
60336
+ for (const id of toolIds) {
60337
+ if (dsl.tools[id]) relatedTools[id] = dsl.tools[id];
60338
+ }
60339
+ const artifactIds = /* @__PURE__ */ new Set();
60340
+ for (const task of relatedTasks) {
60341
+ for (const artId of task.input_artifacts) artifactIds.add(artId);
60342
+ for (const step of task.execution_steps ?? []) {
60343
+ if (step.produces_artifact) artifactIds.add(step.produces_artifact);
60344
+ if (step.reads_artifact) artifactIds.add(step.reads_artifact);
60345
+ }
60346
+ }
60347
+ for (const id of agentIds) {
60348
+ const agent = dsl.agents[id];
60349
+ if (agent) {
60350
+ for (const artId of agent.can_read_artifacts) artifactIds.add(artId);
60351
+ for (const artId of agent.can_write_artifacts) artifactIds.add(artId);
60352
+ }
60353
+ }
60354
+ const relatedArtifacts = {};
60355
+ for (const id of artifactIds) {
60356
+ if (dsl.artifacts[id]) relatedArtifacts[id] = dsl.artifacts[id];
60357
+ }
60358
+ const validationIds = /* @__PURE__ */ new Set();
60359
+ for (const step of wfDef.steps) {
60360
+ if (step.type === "validation") {
60361
+ validationIds.add(step.validation);
60362
+ }
60363
+ }
60364
+ const relatedValidations = {};
60365
+ for (const id of validationIds) {
60366
+ if (dsl.validations[id]) relatedValidations[id] = dsl.validations[id];
60367
+ }
60368
+ return {
60369
+ workflow,
60370
+ relatedAgents,
60371
+ relatedTasks,
60372
+ relatedTools,
60373
+ relatedArtifacts,
60374
+ relatedValidations,
60375
+ dsl
60376
+ };
60223
60377
  }
60224
60378
  function buildPolicyContext(dsl, policyId) {
60225
60379
  const policyDef = dsl.policies[policyId];
@@ -60332,6 +60486,248 @@ function buildPerAgentContext(dsl, agent) {
60332
60486
  };
60333
60487
  }
60334
60488
 
60489
+ // src/renderer/sequence-diagram.ts
60490
+ function hashToColor(s2, saturation, lightness) {
60491
+ let hash = 0;
60492
+ for (const ch of s2) hash = (hash << 5) - hash + ch.charCodeAt(0) | 0;
60493
+ const h2 = (hash % 360 + 360) % 360;
60494
+ const c2 = (1 - Math.abs(2 * lightness - 1)) * saturation;
60495
+ const x3 = c2 * (1 - Math.abs(h2 / 60 % 2 - 1));
60496
+ const m2 = lightness - c2 / 2;
60497
+ let r3 = 0, g2 = 0, b3 = 0;
60498
+ if (h2 < 60) {
60499
+ r3 = c2;
60500
+ g2 = x3;
60501
+ } else if (h2 < 120) {
60502
+ r3 = x3;
60503
+ g2 = c2;
60504
+ } else if (h2 < 180) {
60505
+ g2 = c2;
60506
+ b3 = x3;
60507
+ } else if (h2 < 240) {
60508
+ g2 = x3;
60509
+ b3 = c2;
60510
+ } else if (h2 < 300) {
60511
+ r3 = x3;
60512
+ b3 = c2;
60513
+ } else {
60514
+ r3 = c2;
60515
+ b3 = x3;
60516
+ }
60517
+ return `rgb(${Math.round((r3 + m2) * 255)},${Math.round((g2 + m2) * 255)},${Math.round((b3 + m2) * 255)})`;
60518
+ }
60519
+ function sanitizeAlias(id) {
60520
+ return id.replace(/[^a-zA-Z0-9_]/g, "_");
60521
+ }
60522
+ function agentAlias(id, agent) {
60523
+ const words = agent.role_name.split(/\s+/);
60524
+ if (words.length === 1) return sanitizeAlias(words[0].slice(0, 4));
60525
+ return sanitizeAlias(words.map((w2) => w2[0]).join(""));
60526
+ }
60527
+ function collectReferencedIds(workflow, dsl, relatedTasks) {
60528
+ const agents = /* @__PURE__ */ new Set();
60529
+ const tools = /* @__PURE__ */ new Set();
60530
+ const artifacts = /* @__PURE__ */ new Set();
60531
+ const taskMap = /* @__PURE__ */ new Map();
60532
+ for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
60533
+ for (const step of workflow.steps) {
60534
+ if (step.type === "handoff") {
60535
+ if (step.from_agent) agents.add(step.from_agent);
60536
+ if (step.task) {
60537
+ const task = taskMap.get(step.task);
60538
+ if (task) {
60539
+ agents.add(task.target_agent);
60540
+ for (const es of task.execution_steps ?? []) {
60541
+ collectExecutionStepIds(es, tools, artifacts);
60542
+ }
60543
+ }
60544
+ }
60545
+ } else if (step.type === "validation") {
60546
+ const val = dsl.validations[step.validation];
60547
+ if (val) {
60548
+ if (val.executor_type === "agent") agents.add(val.executor);
60549
+ else tools.add(val.executor);
60550
+ artifacts.add(val.target_artifact);
60551
+ }
60552
+ } else if (step.type === "decision") {
60553
+ }
60554
+ }
60555
+ return { agents, tools, artifacts };
60556
+ }
60557
+ function collectExecutionStepIds(es, tools, artifacts) {
60558
+ if (es.uses_tool) tools.add(es.uses_tool);
60559
+ if (es.produces_artifact) artifacts.add(es.produces_artifact);
60560
+ if (es.reads_artifact) artifacts.add(es.reads_artifact);
60561
+ }
60562
+ function buildParticipants(ids, dsl) {
60563
+ const participants = [];
60564
+ const usedAliases = /* @__PURE__ */ new Set();
60565
+ function uniqueAlias(preferred) {
60566
+ let alias = preferred;
60567
+ let i3 = 2;
60568
+ while (usedAliases.has(alias)) {
60569
+ alias = `${preferred}${i3}`;
60570
+ i3++;
60571
+ }
60572
+ usedAliases.add(alias);
60573
+ return alias;
60574
+ }
60575
+ for (const id of ids.agents) {
60576
+ const agent = dsl.agents[id];
60577
+ if (!agent) continue;
60578
+ const alias = uniqueAlias(agentAlias(id, agent));
60579
+ participants.push({ id, alias, label: agent.role_name, group: "agents" });
60580
+ }
60581
+ for (const id of ids.tools) {
60582
+ const tool = dsl.tools[id];
60583
+ if (!tool) continue;
60584
+ const alias = uniqueAlias(sanitizeAlias(id));
60585
+ participants.push({ id, alias, label: id, group: "toolchain" });
60586
+ }
60587
+ for (const id of ids.artifacts) {
60588
+ const art = dsl.artifacts[id];
60589
+ if (!art) continue;
60590
+ const alias = uniqueAlias(sanitizeAlias(id));
60591
+ participants.push({ id, alias, label: id, group: "artifacts" });
60592
+ }
60593
+ return participants;
60594
+ }
60595
+ function participantAlias(participants, id) {
60596
+ const p2 = participants.find((pp) => pp.id === id);
60597
+ return p2 ? p2.alias : sanitizeAlias(id);
60598
+ }
60599
+ function emitParticipants(participants, lines, indent) {
60600
+ const groups = {
60601
+ agents: [],
60602
+ toolchain: [],
60603
+ artifacts: []
60604
+ };
60605
+ for (const p2 of participants) groups[p2.group].push(p2);
60606
+ const groupConfig = [
60607
+ { key: "agents", label: "Agents", color: "rgb(200,220,255)" },
60608
+ { key: "toolchain", label: "Toolchain", color: "rgb(220,255,220)" },
60609
+ { key: "artifacts", label: "Artifacts", color: "rgb(255,230,210)" }
60610
+ ];
60611
+ for (const { key, label, color } of groupConfig) {
60612
+ const members = groups[key];
60613
+ if (members.length === 0) continue;
60614
+ lines.push(`${indent}box ${color} ${label}`);
60615
+ for (const p2 of members) {
60616
+ if (p2.alias === p2.label) {
60617
+ lines.push(`${indent}participant ${p2.alias}`);
60618
+ } else {
60619
+ lines.push(`${indent}participant ${p2.alias} as ${p2.label}`);
60620
+ }
60621
+ }
60622
+ lines.push(`${indent}end`);
60623
+ }
60624
+ }
60625
+ function emitHandoffStep(step, participants, dsl, relatedTasks, lines, indent) {
60626
+ const taskMap = /* @__PURE__ */ new Map();
60627
+ for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
60628
+ if (!step.task) {
60629
+ if (step.from_agent) {
60630
+ const fromAlias2 = participantAlias(participants, step.from_agent);
60631
+ lines.push(`${indent}${fromAlias2}->>${fromAlias2}: ${step.handoff_kind}`);
60632
+ }
60633
+ return;
60634
+ }
60635
+ const task = taskMap.get(step.task);
60636
+ if (!task) return;
60637
+ const fromAlias = step.from_agent ? participantAlias(participants, step.from_agent) : null;
60638
+ const targetAlias = participantAlias(participants, task.target_agent);
60639
+ if (fromAlias) {
60640
+ lines.push(`${indent}${fromAlias}->>${targetAlias}: delegate ${step.task}`);
60641
+ }
60642
+ for (const es of task.execution_steps ?? []) {
60643
+ emitExecutionStep(es, targetAlias, participants, lines, indent);
60644
+ }
60645
+ if (fromAlias) {
60646
+ lines.push(`${indent}${targetAlias}-->>${fromAlias}: ${task.result_handoff}`);
60647
+ }
60648
+ }
60649
+ function emitExecutionStep(es, agentAlias2, participants, lines, indent) {
60650
+ if (es.reads_artifact) {
60651
+ const artAlias = participantAlias(participants, es.reads_artifact);
60652
+ lines.push(`${indent}${agentAlias2}->>${artAlias}: [R] ${es.action}`);
60653
+ }
60654
+ if (es.produces_artifact) {
60655
+ const artAlias = participantAlias(participants, es.produces_artifact);
60656
+ lines.push(`${indent}${agentAlias2}->>${artAlias}: [W] ${es.action}`);
60657
+ }
60658
+ if (es.uses_tool) {
60659
+ const toolAlias = participantAlias(participants, es.uses_tool);
60660
+ lines.push(`${indent}${agentAlias2}->>${toolAlias}: ${es.action}`);
60661
+ }
60662
+ if (!es.reads_artifact && !es.produces_artifact && !es.uses_tool) {
60663
+ lines.push(`${indent}${agentAlias2}->>${agentAlias2}: ${es.action}`);
60664
+ }
60665
+ }
60666
+ function emitValidationStep(step, participants, dsl, lastFromAgent, lines, indent) {
60667
+ const val = dsl.validations[step.validation];
60668
+ if (!val) return;
60669
+ const executorAlias = participantAlias(participants, val.executor);
60670
+ const artifactAlias = participantAlias(participants, val.target_artifact);
60671
+ const fromAlias = lastFromAgent ? participantAlias(participants, lastFromAgent) : null;
60672
+ if (fromAlias && fromAlias !== executorAlias) {
60673
+ lines.push(`${indent}${fromAlias}->>${executorAlias}: ${step.validation}`);
60674
+ }
60675
+ lines.push(`${indent}${executorAlias}->>${artifactAlias}: [R] ${val.target_artifact}`);
60676
+ if (fromAlias && fromAlias !== executorAlias) {
60677
+ lines.push(`${indent}${executorAlias}-->>${fromAlias}: results`);
60678
+ }
60679
+ }
60680
+ function emitDecisionStep(step, participants, lastFromAgent, lines, indent) {
60681
+ const branches = Object.entries(step.branches);
60682
+ if (branches.length === 0) return;
60683
+ const agentAlias2 = lastFromAgent ? participantAlias(participants, lastFromAgent) : null;
60684
+ for (let i3 = 0; i3 < branches.length; i3++) {
60685
+ const [key, values] = branches[i3];
60686
+ if (i3 === 0) {
60687
+ lines.push(`${indent}alt ${key}`);
60688
+ } else {
60689
+ lines.push(`${indent}else ${key}`);
60690
+ }
60691
+ if (agentAlias2) {
60692
+ lines.push(`${indent} Note over ${agentAlias2}: ${values.join(", ")}`);
60693
+ } else {
60694
+ lines.push(`${indent} Note right of ${participantAlias(participants, [.../* @__PURE__ */ new Set()].join(""))}: ${values.join(", ")}`);
60695
+ }
60696
+ }
60697
+ lines.push(`${indent}end`);
60698
+ }
60699
+ function generateSequenceDiagram(workflow, relatedTasks, dsl) {
60700
+ const ids = collectReferencedIds(workflow, dsl, relatedTasks);
60701
+ const participants = buildParticipants(ids, dsl);
60702
+ const lines = [];
60703
+ const indent = " ";
60704
+ lines.push("sequenceDiagram");
60705
+ emitParticipants(participants, lines, indent);
60706
+ lines.push("");
60707
+ lines.push(`${indent}rect ${hashToColor(workflow.id, 0.15, 0.95)}`);
60708
+ const firstP = participants[0];
60709
+ const lastP = participants[participants.length - 1];
60710
+ if (firstP && lastP) {
60711
+ const noteLabel = workflow.description ? `${workflow.id} \u2014 ${workflow.description}` : workflow.id;
60712
+ lines.push(`${indent}Note over ${firstP.alias},${lastP.alias}: ${noteLabel}`);
60713
+ }
60714
+ let lastFromAgent;
60715
+ for (const step of workflow.steps) {
60716
+ lines.push("");
60717
+ if (step.type === "handoff") {
60718
+ if (step.from_agent) lastFromAgent = step.from_agent;
60719
+ emitHandoffStep(step, participants, dsl, relatedTasks, lines, indent);
60720
+ } else if (step.type === "validation") {
60721
+ emitValidationStep(step, participants, dsl, lastFromAgent, lines, indent);
60722
+ } else if (step.type === "decision") {
60723
+ emitDecisionStep(step, participants, lastFromAgent, lines, indent);
60724
+ }
60725
+ }
60726
+ lines.push("");
60727
+ lines.push(`${indent}end`);
60728
+ return lines.join("\n");
60729
+ }
60730
+
60335
60731
  // src/renderer/renderer.ts
60336
60732
  Handlebars.registerHelper("eq", (a3, b3) => a3 === b3);
60337
60733
  Handlebars.registerHelper("notEmpty", (obj) => {
@@ -60427,6 +60823,82 @@ function toYamlLines(obj, indent) {
60427
60823
  Handlebars.registerHelper("yamlBlock", (obj) => {
60428
60824
  return toYamlLines(obj, 0).join("\n");
60429
60825
  });
60826
+ Handlebars.registerHelper(
60827
+ "join",
60828
+ (arr, separator) => {
60829
+ if (!Array.isArray(arr)) return "";
60830
+ const sep = typeof separator === "string" ? separator : ", ";
60831
+ return arr.join(sep);
60832
+ }
60833
+ );
60834
+ Handlebars.registerHelper("contains", (arr, value) => {
60835
+ if (!Array.isArray(arr)) return false;
60836
+ return arr.includes(value);
60837
+ });
60838
+ Handlebars.registerHelper(
60839
+ "groupBy",
60840
+ (arr, key) => {
60841
+ if (!Array.isArray(arr)) return {};
60842
+ const result = {};
60843
+ for (const item of arr) {
60844
+ const k2 = String(
60845
+ item?.[key] ?? "undefined"
60846
+ );
60847
+ (result[k2] ??= []).push(item);
60848
+ }
60849
+ return result;
60850
+ }
60851
+ );
60852
+ Handlebars.registerHelper(
60853
+ "keys",
60854
+ (obj) => {
60855
+ if (!obj || typeof obj !== "object") return [];
60856
+ return Object.keys(obj);
60857
+ }
60858
+ );
60859
+ Handlebars.registerHelper(
60860
+ "values",
60861
+ (obj) => {
60862
+ if (!obj || typeof obj !== "object") return [];
60863
+ return Object.values(obj);
60864
+ }
60865
+ );
60866
+ Handlebars.registerHelper(
60867
+ "filterByField",
60868
+ (arr, field, value) => {
60869
+ if (!Array.isArray(arr)) return [];
60870
+ return arr.filter(
60871
+ (item) => item?.[field] === value
60872
+ );
60873
+ }
60874
+ );
60875
+ Handlebars.registerHelper("not", (value) => !value);
60876
+ Handlebars.registerHelper("or", (...args) => {
60877
+ const _options = args.pop();
60878
+ return args.some((a3) => !!a3);
60879
+ });
60880
+ Handlebars.registerHelper("and", (...args) => {
60881
+ const _options = args.pop();
60882
+ return args.every((a3) => !!a3);
60883
+ });
60884
+ Handlebars.registerHelper("gt", (a3, b3) => a3 > b3);
60885
+ Handlebars.registerHelper("gte", (a3, b3) => a3 >= b3);
60886
+ Handlebars.registerHelper("lt", (a3, b3) => a3 < b3);
60887
+ Handlebars.registerHelper("size", (obj) => {
60888
+ if (Array.isArray(obj)) return obj.length;
60889
+ if (obj && typeof obj === "object") return Object.keys(obj).length;
60890
+ return 0;
60891
+ });
60892
+ Handlebars.registerHelper(
60893
+ "sequenceDiagram",
60894
+ function() {
60895
+ const workflow = this["workflow"];
60896
+ const relatedTasks = this["relatedTasks"];
60897
+ const dsl = this["dsl"];
60898
+ if (!workflow || !dsl) return "";
60899
+ return generateSequenceDiagram(workflow, relatedTasks ?? [], dsl);
60900
+ }
60901
+ );
60430
60902
  function getDslSection(dsl, context) {
60431
60903
  const sectionMap = {
60432
60904
  agent: dsl.agents,
@@ -60574,6 +61046,7 @@ var RenderTargetSchema = z14.object({
60574
61046
  );
60575
61047
  var AgentContractsConfigSchema = z14.object({
60576
61048
  dsl: z14.string(),
61049
+ vars: z14.record(z14.string(), z14.string()).optional(),
60577
61050
  renders: z14.array(RenderTargetSchema).min(1)
60578
61051
  });
60579
61052
 
@@ -60642,6 +61115,7 @@ ${issues}`,
60642
61115
  const config = result.data;
60643
61116
  return {
60644
61117
  dsl: resolve4(configDir, config.dsl),
61118
+ vars: config.vars,
60645
61119
  renders: config.renders.map((r3) => ({
60646
61120
  ...r3,
60647
61121
  template: resolve4(configDir, r3.template),