agent-contracts 0.7.0 → 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<{
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;
@@ -60315,6 +60327,11 @@ function buildWorkflowContext(dsl, workflowId) {
60315
60327
  }
60316
60328
  }
60317
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
+ }
60318
60335
  const relatedTools = {};
60319
60336
  for (const id of toolIds) {
60320
60337
  if (dsl.tools[id]) relatedTools[id] = dsl.tools[id];
@@ -60322,6 +60339,10 @@ function buildWorkflowContext(dsl, workflowId) {
60322
60339
  const artifactIds = /* @__PURE__ */ new Set();
60323
60340
  for (const task of relatedTasks) {
60324
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
+ }
60325
60346
  }
60326
60347
  for (const id of agentIds) {
60327
60348
  const agent = dsl.agents[id];
@@ -60465,6 +60486,248 @@ function buildPerAgentContext(dsl, agent) {
60465
60486
  };
60466
60487
  }
60467
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
+
60468
60731
  // src/renderer/renderer.ts
60469
60732
  Handlebars.registerHelper("eq", (a3, b3) => a3 === b3);
60470
60733
  Handlebars.registerHelper("notEmpty", (obj) => {
@@ -60626,6 +60889,16 @@ Handlebars.registerHelper("size", (obj) => {
60626
60889
  if (obj && typeof obj === "object") return Object.keys(obj).length;
60627
60890
  return 0;
60628
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
+ );
60629
60902
  function getDslSection(dsl, context) {
60630
60903
  const sectionMap = {
60631
60904
  agent: dsl.agents,