agent-contracts 0.7.1 → 0.8.0
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/README.md +22 -4
- package/dist/cli.js +428 -31
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +81 -1
- package/dist/index.js +429 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -58424,13 +58424,21 @@ var TaskSchema = z6.object({
|
|
|
58424
58424
|
|
|
58425
58425
|
// src/schema/tool.ts
|
|
58426
58426
|
import { z as z7 } from "zod";
|
|
58427
|
+
var CommandSchema = z7.object({
|
|
58428
|
+
command: z7.string(),
|
|
58429
|
+
category: z7.string(),
|
|
58430
|
+
reads: z7.array(z7.string()).default([]),
|
|
58431
|
+
writes: z7.array(z7.string()).default([]),
|
|
58432
|
+
purpose: z7.string().optional()
|
|
58433
|
+
});
|
|
58427
58434
|
var ToolSchema = z7.object({
|
|
58428
58435
|
kind: z7.string(),
|
|
58429
58436
|
description: z7.string().optional(),
|
|
58430
58437
|
input_artifacts: z7.array(z7.string()).default([]),
|
|
58431
58438
|
output_artifacts: z7.array(z7.string()).default([]),
|
|
58432
58439
|
invokable_by: z7.array(z7.string()),
|
|
58433
|
-
side_effects: z7.array(z7.string()).default([])
|
|
58440
|
+
side_effects: z7.array(z7.string()).default([]),
|
|
58441
|
+
commands: z7.array(CommandSchema).default([])
|
|
58434
58442
|
}).passthrough();
|
|
58435
58443
|
|
|
58436
58444
|
// src/schema/validation.ts
|
|
@@ -58446,23 +58454,38 @@ var ValidationSchema = z8.object({
|
|
|
58446
58454
|
|
|
58447
58455
|
// src/schema/workflow.ts
|
|
58448
58456
|
import { z as z9 } from "zod";
|
|
58457
|
+
var RetrySchema = z9.object({
|
|
58458
|
+
condition: z9.string(),
|
|
58459
|
+
fix_task: z9.string(),
|
|
58460
|
+
revalidate_task: z9.string().optional()
|
|
58461
|
+
});
|
|
58462
|
+
var ExternalParticipantSchema = z9.object({
|
|
58463
|
+
id: z9.string(),
|
|
58464
|
+
kind: z9.enum(["actor", "participant"]),
|
|
58465
|
+
label: z9.string(),
|
|
58466
|
+
description: z9.string().optional()
|
|
58467
|
+
});
|
|
58449
58468
|
var WorkflowHandoffStepSchema = z9.object({
|
|
58450
58469
|
type: z9.literal("handoff"),
|
|
58451
58470
|
description: z9.string().optional(),
|
|
58452
58471
|
handoff_kind: z9.string(),
|
|
58453
58472
|
task: z9.string().optional(),
|
|
58454
|
-
from_agent: z9.string().optional()
|
|
58473
|
+
from_agent: z9.string().optional(),
|
|
58474
|
+
group: z9.string().optional(),
|
|
58475
|
+
retry: RetrySchema.optional()
|
|
58455
58476
|
}).passthrough();
|
|
58456
58477
|
var WorkflowValidationStepSchema = z9.object({
|
|
58457
58478
|
type: z9.literal("validation"),
|
|
58458
58479
|
description: z9.string().optional(),
|
|
58459
|
-
validation: z9.string()
|
|
58480
|
+
validation: z9.string(),
|
|
58481
|
+
group: z9.string().optional()
|
|
58460
58482
|
}).passthrough();
|
|
58461
58483
|
var WorkflowDecisionStepSchema = z9.object({
|
|
58462
58484
|
type: z9.literal("decision"),
|
|
58463
58485
|
description: z9.string().optional(),
|
|
58464
58486
|
on: z9.string(),
|
|
58465
|
-
branches: z9.record(z9.string(), z9.array(z9.string()))
|
|
58487
|
+
branches: z9.record(z9.string(), z9.array(z9.string())),
|
|
58488
|
+
group: z9.string().optional()
|
|
58466
58489
|
}).passthrough();
|
|
58467
58490
|
var WorkflowStepSchema = z9.discriminatedUnion("type", [
|
|
58468
58491
|
WorkflowHandoffStepSchema,
|
|
@@ -58473,7 +58496,8 @@ var WorkflowSchema = z9.object({
|
|
|
58473
58496
|
description: z9.string().optional(),
|
|
58474
58497
|
entry_conditions: z9.array(z9.string()).default([]),
|
|
58475
58498
|
trigger: z9.string().optional(),
|
|
58476
|
-
steps: z9.array(WorkflowStepSchema)
|
|
58499
|
+
steps: z9.array(WorkflowStepSchema),
|
|
58500
|
+
external_participants: z9.array(ExternalParticipantSchema).default([])
|
|
58477
58501
|
}).passthrough();
|
|
58478
58502
|
|
|
58479
58503
|
// src/schema/dsl.ts
|
|
@@ -59594,12 +59618,100 @@ var mergeIntegrityRule = {
|
|
|
59594
59618
|
}
|
|
59595
59619
|
};
|
|
59596
59620
|
|
|
59621
|
+
// src/linter/rules/artifact-ownership.ts
|
|
59622
|
+
var artifactOwnershipRule = {
|
|
59623
|
+
id: "artifact-ownership",
|
|
59624
|
+
description: "Ensure execution_step produces/reads operations are consistent with artifact producers/editors/consumers",
|
|
59625
|
+
run(dsl) {
|
|
59626
|
+
const diagnostics = [];
|
|
59627
|
+
for (const [taskId, task] of Object.entries(dsl.tasks)) {
|
|
59628
|
+
if (!task.execution_steps) continue;
|
|
59629
|
+
const agentId = task.target_agent;
|
|
59630
|
+
for (const step of task.execution_steps) {
|
|
59631
|
+
if (step.produces_artifact) {
|
|
59632
|
+
const artifact = dsl.artifacts[step.produces_artifact];
|
|
59633
|
+
if (artifact) {
|
|
59634
|
+
const canWrite = artifact.producers.includes(agentId) || artifact.editors.includes(agentId);
|
|
59635
|
+
if (!canWrite) {
|
|
59636
|
+
diagnostics.push({
|
|
59637
|
+
ruleId: "artifact-ownership",
|
|
59638
|
+
severity: "warning",
|
|
59639
|
+
path: `tasks.${taskId}.execution_steps`,
|
|
59640
|
+
message: `Agent "${agentId}" produces artifact "${step.produces_artifact}" but is not listed in its producers or editors`
|
|
59641
|
+
});
|
|
59642
|
+
}
|
|
59643
|
+
}
|
|
59644
|
+
}
|
|
59645
|
+
if (step.reads_artifact) {
|
|
59646
|
+
const artifact = dsl.artifacts[step.reads_artifact];
|
|
59647
|
+
if (artifact) {
|
|
59648
|
+
const canRead = artifact.consumers.includes(agentId) || artifact.producers.includes(agentId) || artifact.editors.includes(agentId);
|
|
59649
|
+
if (!canRead) {
|
|
59650
|
+
diagnostics.push({
|
|
59651
|
+
ruleId: "artifact-ownership",
|
|
59652
|
+
severity: "warning",
|
|
59653
|
+
path: `tasks.${taskId}.execution_steps`,
|
|
59654
|
+
message: `Agent "${agentId}" reads artifact "${step.reads_artifact}" but is not listed in its producers, editors, or consumers`
|
|
59655
|
+
});
|
|
59656
|
+
}
|
|
59657
|
+
}
|
|
59658
|
+
}
|
|
59659
|
+
}
|
|
59660
|
+
}
|
|
59661
|
+
return diagnostics;
|
|
59662
|
+
}
|
|
59663
|
+
};
|
|
59664
|
+
|
|
59665
|
+
// src/linter/rules/tool-commands.ts
|
|
59666
|
+
var toolCommandsRule = {
|
|
59667
|
+
id: "tool-commands",
|
|
59668
|
+
description: "Validate tool commands: reads/writes reference existing artifacts; writes align with output_artifacts",
|
|
59669
|
+
run(dsl) {
|
|
59670
|
+
const diagnostics = [];
|
|
59671
|
+
for (const [toolId, tool] of Object.entries(dsl.tools)) {
|
|
59672
|
+
for (const cmd of tool.commands) {
|
|
59673
|
+
for (const ref of cmd.reads) {
|
|
59674
|
+
if (!dsl.artifacts[ref]) {
|
|
59675
|
+
diagnostics.push({
|
|
59676
|
+
ruleId: "tool-commands",
|
|
59677
|
+
severity: "error",
|
|
59678
|
+
path: `tools.${toolId}.commands`,
|
|
59679
|
+
message: `Command "${cmd.command}" reads artifact "${ref}" which does not exist`
|
|
59680
|
+
});
|
|
59681
|
+
}
|
|
59682
|
+
}
|
|
59683
|
+
for (const ref of cmd.writes) {
|
|
59684
|
+
if (!dsl.artifacts[ref]) {
|
|
59685
|
+
diagnostics.push({
|
|
59686
|
+
ruleId: "tool-commands",
|
|
59687
|
+
severity: "error",
|
|
59688
|
+
path: `tools.${toolId}.commands`,
|
|
59689
|
+
message: `Command "${cmd.command}" writes artifact "${ref}" which does not exist`
|
|
59690
|
+
});
|
|
59691
|
+
}
|
|
59692
|
+
if (dsl.artifacts[ref] && !tool.output_artifacts.includes(ref)) {
|
|
59693
|
+
diagnostics.push({
|
|
59694
|
+
ruleId: "tool-commands",
|
|
59695
|
+
severity: "warning",
|
|
59696
|
+
path: `tools.${toolId}.commands`,
|
|
59697
|
+
message: `Command "${cmd.command}" writes artifact "${ref}" but tool's output_artifacts does not include it`
|
|
59698
|
+
});
|
|
59699
|
+
}
|
|
59700
|
+
}
|
|
59701
|
+
}
|
|
59702
|
+
}
|
|
59703
|
+
return diagnostics;
|
|
59704
|
+
}
|
|
59705
|
+
};
|
|
59706
|
+
|
|
59597
59707
|
// src/linter/linter.ts
|
|
59598
59708
|
var builtinRules = [
|
|
59599
59709
|
validationCoverageRule,
|
|
59600
59710
|
toolExecutionRule,
|
|
59601
59711
|
taskAgentBindingRule,
|
|
59602
|
-
mergeIntegrityRule
|
|
59712
|
+
mergeIntegrityRule,
|
|
59713
|
+
artifactOwnershipRule,
|
|
59714
|
+
toolCommandsRule
|
|
59603
59715
|
];
|
|
59604
59716
|
function lint(dsl, rules = builtinRules) {
|
|
59605
59717
|
const diagnostics = [];
|
|
@@ -60526,40 +60638,63 @@ function agentAlias(id, agent) {
|
|
|
60526
60638
|
}
|
|
60527
60639
|
function collectReferencedIds(workflow, dsl, relatedTasks) {
|
|
60528
60640
|
const agents = /* @__PURE__ */ new Set();
|
|
60641
|
+
const auditAgents = /* @__PURE__ */ new Set();
|
|
60529
60642
|
const tools = /* @__PURE__ */ new Set();
|
|
60530
60643
|
const artifacts = /* @__PURE__ */ new Set();
|
|
60531
60644
|
const taskMap = /* @__PURE__ */ new Map();
|
|
60532
60645
|
for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
|
|
60533
60646
|
for (const step of workflow.steps) {
|
|
60534
60647
|
if (step.type === "handoff") {
|
|
60535
|
-
if (step.from_agent)
|
|
60648
|
+
if (step.from_agent) addAgent(step.from_agent);
|
|
60536
60649
|
if (step.task) {
|
|
60537
60650
|
const task = taskMap.get(step.task);
|
|
60538
60651
|
if (task) {
|
|
60539
|
-
|
|
60652
|
+
addAgent(task.target_agent);
|
|
60540
60653
|
for (const es of task.execution_steps ?? []) {
|
|
60541
60654
|
collectExecutionStepIds(es, tools, artifacts);
|
|
60542
60655
|
}
|
|
60543
60656
|
}
|
|
60544
60657
|
}
|
|
60658
|
+
if (step.retry) {
|
|
60659
|
+
const fixTask = taskMap.get(step.retry.fix_task);
|
|
60660
|
+
if (fixTask) {
|
|
60661
|
+
addAgent(fixTask.target_agent);
|
|
60662
|
+
for (const es of fixTask.execution_steps ?? []) {
|
|
60663
|
+
collectExecutionStepIds(es, tools, artifacts);
|
|
60664
|
+
}
|
|
60665
|
+
}
|
|
60666
|
+
if (step.retry.revalidate_task) {
|
|
60667
|
+
const revalTask = taskMap.get(step.retry.revalidate_task);
|
|
60668
|
+
if (revalTask) {
|
|
60669
|
+
addAgent(revalTask.target_agent);
|
|
60670
|
+
}
|
|
60671
|
+
}
|
|
60672
|
+
}
|
|
60545
60673
|
} else if (step.type === "validation") {
|
|
60546
60674
|
const val = dsl.validations[step.validation];
|
|
60547
60675
|
if (val) {
|
|
60548
|
-
if (val.executor_type === "agent")
|
|
60676
|
+
if (val.executor_type === "agent") addAgent(val.executor);
|
|
60549
60677
|
else tools.add(val.executor);
|
|
60550
60678
|
artifacts.add(val.target_artifact);
|
|
60551
60679
|
}
|
|
60552
|
-
} else if (step.type === "decision") {
|
|
60553
60680
|
}
|
|
60554
60681
|
}
|
|
60555
|
-
|
|
60682
|
+
function addAgent(agentId) {
|
|
60683
|
+
const agent = dsl.agents[agentId];
|
|
60684
|
+
if (agent?.mode === "read-only") {
|
|
60685
|
+
auditAgents.add(agentId);
|
|
60686
|
+
} else {
|
|
60687
|
+
agents.add(agentId);
|
|
60688
|
+
}
|
|
60689
|
+
}
|
|
60690
|
+
return { agents, auditAgents, tools, artifacts };
|
|
60556
60691
|
}
|
|
60557
60692
|
function collectExecutionStepIds(es, tools, artifacts) {
|
|
60558
60693
|
if (es.uses_tool) tools.add(es.uses_tool);
|
|
60559
60694
|
if (es.produces_artifact) artifacts.add(es.produces_artifact);
|
|
60560
60695
|
if (es.reads_artifact) artifacts.add(es.reads_artifact);
|
|
60561
60696
|
}
|
|
60562
|
-
function buildParticipants(ids, dsl) {
|
|
60697
|
+
function buildParticipants(ids, externals, dsl) {
|
|
60563
60698
|
const participants = [];
|
|
60564
60699
|
const usedAliases = /* @__PURE__ */ new Set();
|
|
60565
60700
|
function uniqueAlias(preferred) {
|
|
@@ -60572,12 +60707,22 @@ function buildParticipants(ids, dsl) {
|
|
|
60572
60707
|
usedAliases.add(alias);
|
|
60573
60708
|
return alias;
|
|
60574
60709
|
}
|
|
60710
|
+
for (const ep of externals) {
|
|
60711
|
+
const alias = uniqueAlias(sanitizeAlias(ep.id));
|
|
60712
|
+
participants.push({ id: ep.id, alias, label: ep.label, group: "external" });
|
|
60713
|
+
}
|
|
60575
60714
|
for (const id of ids.agents) {
|
|
60576
60715
|
const agent = dsl.agents[id];
|
|
60577
60716
|
if (!agent) continue;
|
|
60578
60717
|
const alias = uniqueAlias(agentAlias(id, agent));
|
|
60579
60718
|
participants.push({ id, alias, label: agent.role_name, group: "agents" });
|
|
60580
60719
|
}
|
|
60720
|
+
for (const id of ids.auditAgents) {
|
|
60721
|
+
const agent = dsl.agents[id];
|
|
60722
|
+
if (!agent) continue;
|
|
60723
|
+
const alias = uniqueAlias(agentAlias(id, agent));
|
|
60724
|
+
participants.push({ id, alias, label: agent.role_name, group: "audit" });
|
|
60725
|
+
}
|
|
60581
60726
|
for (const id of ids.tools) {
|
|
60582
60727
|
const tool = dsl.tools[id];
|
|
60583
60728
|
if (!tool) continue;
|
|
@@ -60596,15 +60741,33 @@ function participantAlias(participants, id) {
|
|
|
60596
60741
|
const p2 = participants.find((pp) => pp.id === id);
|
|
60597
60742
|
return p2 ? p2.alias : sanitizeAlias(id);
|
|
60598
60743
|
}
|
|
60599
|
-
function emitParticipants(participants, lines, indent) {
|
|
60744
|
+
function emitParticipants(participants, externals, lines, indent) {
|
|
60600
60745
|
const groups = {
|
|
60746
|
+
external: [],
|
|
60601
60747
|
agents: [],
|
|
60748
|
+
audit: [],
|
|
60602
60749
|
toolchain: [],
|
|
60603
60750
|
artifacts: []
|
|
60604
60751
|
};
|
|
60605
60752
|
for (const p2 of participants) groups[p2.group].push(p2);
|
|
60753
|
+
const externalMap = /* @__PURE__ */ new Map();
|
|
60754
|
+
for (const ep of externals) externalMap.set(ep.id, ep);
|
|
60755
|
+
if (groups.external.length > 0) {
|
|
60756
|
+
lines.push(`${indent}box rgb(255,245,230) External`);
|
|
60757
|
+
for (const p2 of groups.external) {
|
|
60758
|
+
const ep = externalMap.get(p2.id);
|
|
60759
|
+
const keyword = ep?.kind === "actor" ? "actor" : "participant";
|
|
60760
|
+
if (p2.alias === p2.label) {
|
|
60761
|
+
lines.push(`${indent}${keyword} ${p2.alias}`);
|
|
60762
|
+
} else {
|
|
60763
|
+
lines.push(`${indent}${keyword} ${p2.alias} as ${p2.label}`);
|
|
60764
|
+
}
|
|
60765
|
+
}
|
|
60766
|
+
lines.push(`${indent}end`);
|
|
60767
|
+
}
|
|
60606
60768
|
const groupConfig = [
|
|
60607
60769
|
{ key: "agents", label: "Agents", color: "rgb(200,220,255)" },
|
|
60770
|
+
{ key: "audit", label: "Audit", color: "rgb(255,220,220)" },
|
|
60608
60771
|
{ key: "toolchain", label: "Toolchain", color: "rgb(220,255,220)" },
|
|
60609
60772
|
{ key: "artifacts", label: "Artifacts", color: "rgb(255,230,210)" }
|
|
60610
60773
|
];
|
|
@@ -60680,7 +60843,7 @@ function emitValidationStep(step, participants, dsl, lastFromAgent, lines, inden
|
|
|
60680
60843
|
function emitDecisionStep(step, participants, lastFromAgent, lines, indent) {
|
|
60681
60844
|
const branches = Object.entries(step.branches);
|
|
60682
60845
|
if (branches.length === 0) return;
|
|
60683
|
-
const
|
|
60846
|
+
const agentAl = lastFromAgent ? participantAlias(participants, lastFromAgent) : null;
|
|
60684
60847
|
for (let i3 = 0; i3 < branches.length; i3++) {
|
|
60685
60848
|
const [key, values] = branches[i3];
|
|
60686
60849
|
if (i3 === 0) {
|
|
@@ -60688,21 +60851,78 @@ function emitDecisionStep(step, participants, lastFromAgent, lines, indent) {
|
|
|
60688
60851
|
} else {
|
|
60689
60852
|
lines.push(`${indent}else ${key}`);
|
|
60690
60853
|
}
|
|
60691
|
-
if (
|
|
60692
|
-
lines.push(`${indent} Note over ${
|
|
60693
|
-
} else {
|
|
60694
|
-
lines.push(`${indent} Note right of ${participantAlias(participants, [.../* @__PURE__ */ new Set()].join(""))}: ${values.join(", ")}`);
|
|
60854
|
+
if (agentAl) {
|
|
60855
|
+
lines.push(`${indent} Note over ${agentAl}: ${values.join(", ")}`);
|
|
60695
60856
|
}
|
|
60696
60857
|
}
|
|
60697
60858
|
lines.push(`${indent}end`);
|
|
60698
60859
|
}
|
|
60860
|
+
function emitRetryBlock(step, participants, dsl, relatedTasks, lines, indent) {
|
|
60861
|
+
const retry = step.retry;
|
|
60862
|
+
if (!retry) return;
|
|
60863
|
+
const taskMap = /* @__PURE__ */ new Map();
|
|
60864
|
+
for (const t3 of relatedTasks) taskMap.set(t3.id, t3);
|
|
60865
|
+
lines.push(`${indent}opt ${retry.condition}`);
|
|
60866
|
+
const innerIndent = indent + " ";
|
|
60867
|
+
const fixTask = taskMap.get(retry.fix_task);
|
|
60868
|
+
if (fixTask) {
|
|
60869
|
+
const fromAlias = step.from_agent ? participantAlias(participants, step.from_agent) : null;
|
|
60870
|
+
const targetAlias = participantAlias(participants, fixTask.target_agent);
|
|
60871
|
+
if (fromAlias) {
|
|
60872
|
+
lines.push(`${innerIndent}${fromAlias}->>${targetAlias}: fix ${retry.fix_task}`);
|
|
60873
|
+
}
|
|
60874
|
+
for (const es of fixTask.execution_steps ?? []) {
|
|
60875
|
+
emitExecutionStep(es, targetAlias, participants, lines, innerIndent);
|
|
60876
|
+
}
|
|
60877
|
+
if (fromAlias) {
|
|
60878
|
+
lines.push(`${innerIndent}${targetAlias}-->>${fromAlias}: ${fixTask.result_handoff}`);
|
|
60879
|
+
}
|
|
60880
|
+
}
|
|
60881
|
+
if (retry.revalidate_task) {
|
|
60882
|
+
const revalTask = taskMap.get(retry.revalidate_task);
|
|
60883
|
+
if (revalTask) {
|
|
60884
|
+
const fromAlias = step.from_agent ? participantAlias(participants, step.from_agent) : null;
|
|
60885
|
+
const revalAlias = participantAlias(participants, revalTask.target_agent);
|
|
60886
|
+
if (fromAlias) {
|
|
60887
|
+
lines.push(`${innerIndent}${fromAlias}->>${revalAlias}: revalidate ${retry.revalidate_task}`);
|
|
60888
|
+
lines.push(`${innerIndent}${revalAlias}-->>${fromAlias}: ${revalTask.result_handoff}`);
|
|
60889
|
+
}
|
|
60890
|
+
}
|
|
60891
|
+
}
|
|
60892
|
+
lines.push(`${indent}end`);
|
|
60893
|
+
}
|
|
60894
|
+
function groupSteps(steps) {
|
|
60895
|
+
const result = [];
|
|
60896
|
+
let currentGroup = null;
|
|
60897
|
+
for (let i3 = 0; i3 < steps.length; i3++) {
|
|
60898
|
+
const step = steps[i3];
|
|
60899
|
+
const group = "group" in step ? step.group : void 0;
|
|
60900
|
+
if (group) {
|
|
60901
|
+
if (currentGroup && currentGroup.group === group) {
|
|
60902
|
+
currentGroup.steps.push({ step, index: i3 });
|
|
60903
|
+
} else {
|
|
60904
|
+
if (currentGroup) result.push(currentGroup);
|
|
60905
|
+
currentGroup = { group, steps: [{ step, index: i3 }] };
|
|
60906
|
+
}
|
|
60907
|
+
} else {
|
|
60908
|
+
if (currentGroup) {
|
|
60909
|
+
result.push(currentGroup);
|
|
60910
|
+
currentGroup = null;
|
|
60911
|
+
}
|
|
60912
|
+
result.push({ group: null, steps: [{ step, index: i3 }] });
|
|
60913
|
+
}
|
|
60914
|
+
}
|
|
60915
|
+
if (currentGroup) result.push(currentGroup);
|
|
60916
|
+
return result;
|
|
60917
|
+
}
|
|
60699
60918
|
function generateSequenceDiagram(workflow, relatedTasks, dsl) {
|
|
60700
60919
|
const ids = collectReferencedIds(workflow, dsl, relatedTasks);
|
|
60701
|
-
const
|
|
60920
|
+
const externals = workflow.external_participants ?? [];
|
|
60921
|
+
const participants = buildParticipants(ids, externals, dsl);
|
|
60702
60922
|
const lines = [];
|
|
60703
60923
|
const indent = " ";
|
|
60704
60924
|
lines.push("sequenceDiagram");
|
|
60705
|
-
emitParticipants(participants, lines, indent);
|
|
60925
|
+
emitParticipants(participants, externals, lines, indent);
|
|
60706
60926
|
lines.push("");
|
|
60707
60927
|
lines.push(`${indent}rect ${hashToColor(workflow.id, 0.15, 0.95)}`);
|
|
60708
60928
|
const firstP = participants[0];
|
|
@@ -60711,22 +60931,174 @@ function generateSequenceDiagram(workflow, relatedTasks, dsl) {
|
|
|
60711
60931
|
const noteLabel = workflow.description ? `${workflow.id} \u2014 ${workflow.description}` : workflow.id;
|
|
60712
60932
|
lines.push(`${indent}Note over ${firstP.alias},${lastP.alias}: ${noteLabel}`);
|
|
60713
60933
|
}
|
|
60934
|
+
if (workflow.trigger && externals.some((ep) => ep.kind === "actor")) {
|
|
60935
|
+
const actor = externals.find((ep) => ep.kind === "actor");
|
|
60936
|
+
const actorAlias = participantAlias(participants, actor.id);
|
|
60937
|
+
const firstAgent = participants.find((p2) => p2.group === "agents" || p2.group === "audit");
|
|
60938
|
+
if (firstAgent) {
|
|
60939
|
+
lines.push(`${indent}${actorAlias}->>${firstAgent.alias}: ${workflow.trigger}`);
|
|
60940
|
+
}
|
|
60941
|
+
}
|
|
60714
60942
|
let lastFromAgent;
|
|
60715
|
-
|
|
60716
|
-
|
|
60717
|
-
if (
|
|
60718
|
-
|
|
60719
|
-
|
|
60720
|
-
|
|
60721
|
-
|
|
60722
|
-
|
|
60723
|
-
|
|
60943
|
+
const grouped = groupSteps(workflow.steps);
|
|
60944
|
+
for (const g2 of grouped) {
|
|
60945
|
+
if (g2.group && g2.steps.length > 1) {
|
|
60946
|
+
lines.push("");
|
|
60947
|
+
lines.push(`${indent}par ${g2.group}`);
|
|
60948
|
+
const parIndent = indent + " ";
|
|
60949
|
+
for (let i3 = 0; i3 < g2.steps.length; i3++) {
|
|
60950
|
+
const { step } = g2.steps[i3];
|
|
60951
|
+
if (i3 > 0) lines.push(`${indent}and`);
|
|
60952
|
+
emitStep(step, participants, dsl, relatedTasks, lines, parIndent, lastFromAgent, (a3) => {
|
|
60953
|
+
lastFromAgent = a3;
|
|
60954
|
+
});
|
|
60955
|
+
}
|
|
60956
|
+
lines.push(`${indent}end`);
|
|
60957
|
+
} else {
|
|
60958
|
+
for (const { step } of g2.steps) {
|
|
60959
|
+
lines.push("");
|
|
60960
|
+
emitStep(step, participants, dsl, relatedTasks, lines, indent, lastFromAgent, (a3) => {
|
|
60961
|
+
lastFromAgent = a3;
|
|
60962
|
+
});
|
|
60963
|
+
}
|
|
60724
60964
|
}
|
|
60725
60965
|
}
|
|
60726
60966
|
lines.push("");
|
|
60727
60967
|
lines.push(`${indent}end`);
|
|
60728
60968
|
return lines.join("\n");
|
|
60729
60969
|
}
|
|
60970
|
+
function emitStep(step, participants, dsl, relatedTasks, lines, indent, lastFromAgent, setLastFromAgent) {
|
|
60971
|
+
if (step.type === "handoff") {
|
|
60972
|
+
if (step.from_agent) setLastFromAgent(step.from_agent);
|
|
60973
|
+
emitHandoffStep(step, participants, dsl, relatedTasks, lines, indent);
|
|
60974
|
+
if (step.retry) {
|
|
60975
|
+
emitRetryBlock(step, participants, dsl, relatedTasks, lines, indent);
|
|
60976
|
+
}
|
|
60977
|
+
} else if (step.type === "validation") {
|
|
60978
|
+
emitValidationStep(step, participants, dsl, lastFromAgent, lines, indent);
|
|
60979
|
+
} else if (step.type === "decision") {
|
|
60980
|
+
emitDecisionStep(step, participants, lastFromAgent, lines, indent);
|
|
60981
|
+
}
|
|
60982
|
+
}
|
|
60983
|
+
|
|
60984
|
+
// src/renderer/overview-flowchart.ts
|
|
60985
|
+
function collectPhaseOps(dsl, wfId) {
|
|
60986
|
+
const ctx = buildWorkflowContext(dsl, wfId);
|
|
60987
|
+
const wf = dsl.workflow[wfId];
|
|
60988
|
+
const agentOps = /* @__PURE__ */ new Map();
|
|
60989
|
+
const artifactOps = /* @__PURE__ */ new Map();
|
|
60990
|
+
const toolOps = /* @__PURE__ */ new Map();
|
|
60991
|
+
function addOp(map, id, op) {
|
|
60992
|
+
if (!map.has(id)) map.set(id, /* @__PURE__ */ new Set());
|
|
60993
|
+
map.get(id).add(op);
|
|
60994
|
+
}
|
|
60995
|
+
const taskMap = new Map(ctx.relatedTasks.map((t3) => [t3.id, t3]));
|
|
60996
|
+
for (const step of wf.steps) {
|
|
60997
|
+
if (step.type === "handoff") {
|
|
60998
|
+
if (step.from_agent) addOp(agentOps, step.from_agent, "delegate");
|
|
60999
|
+
if (step.task) {
|
|
61000
|
+
const task = taskMap.get(step.task);
|
|
61001
|
+
if (task) {
|
|
61002
|
+
addOp(agentOps, task.target_agent, "execute");
|
|
61003
|
+
for (const es of task.execution_steps ?? []) {
|
|
61004
|
+
if (es.reads_artifact) addOp(artifactOps, es.reads_artifact, "R");
|
|
61005
|
+
if (es.produces_artifact) addOp(artifactOps, es.produces_artifact, "W");
|
|
61006
|
+
if (es.uses_tool) {
|
|
61007
|
+
const tool = dsl.tools[es.uses_tool];
|
|
61008
|
+
if (tool) {
|
|
61009
|
+
const cats = tool.commands.map((c2) => c2.category).filter((v2, i3, a3) => a3.indexOf(v2) === i3);
|
|
61010
|
+
for (const cat of cats) addOp(toolOps, es.uses_tool, cat);
|
|
61011
|
+
if (cats.length === 0) addOp(toolOps, es.uses_tool, "\u2713");
|
|
61012
|
+
} else {
|
|
61013
|
+
addOp(toolOps, es.uses_tool, "\u2713");
|
|
61014
|
+
}
|
|
61015
|
+
}
|
|
61016
|
+
}
|
|
61017
|
+
}
|
|
61018
|
+
}
|
|
61019
|
+
} else if (step.type === "validation") {
|
|
61020
|
+
const val = dsl.validations[step.validation];
|
|
61021
|
+
if (val) {
|
|
61022
|
+
if (val.executor_type === "agent") {
|
|
61023
|
+
addOp(agentOps, val.executor, "validate");
|
|
61024
|
+
} else {
|
|
61025
|
+
addOp(toolOps, val.executor, "verification");
|
|
61026
|
+
}
|
|
61027
|
+
addOp(artifactOps, val.target_artifact, "V");
|
|
61028
|
+
}
|
|
61029
|
+
}
|
|
61030
|
+
}
|
|
61031
|
+
return { agentOps, artifactOps, toolOps };
|
|
61032
|
+
}
|
|
61033
|
+
function formatOps(ops) {
|
|
61034
|
+
if (!ops || ops.size === 0) return "\u2014";
|
|
61035
|
+
return [...ops].join(", ");
|
|
61036
|
+
}
|
|
61037
|
+
function buildTable(header, rows) {
|
|
61038
|
+
const lines = [];
|
|
61039
|
+
lines.push("| " + header.join(" | ") + " |");
|
|
61040
|
+
lines.push("|" + header.map(() => "---").join("|") + "|");
|
|
61041
|
+
for (const row of rows) {
|
|
61042
|
+
lines.push("| " + row.join(" | ") + " |");
|
|
61043
|
+
}
|
|
61044
|
+
return lines.join("\n");
|
|
61045
|
+
}
|
|
61046
|
+
function generateOverviewFlowchart(dsl) {
|
|
61047
|
+
const workflowOrder = dsl.system.default_workflow_order ?? Object.keys(dsl.workflow);
|
|
61048
|
+
const phases = workflowOrder.filter((id) => dsl.workflow[id]);
|
|
61049
|
+
const phaseData = /* @__PURE__ */ new Map();
|
|
61050
|
+
for (const wfId of phases) {
|
|
61051
|
+
phaseData.set(wfId, collectPhaseOps(dsl, wfId));
|
|
61052
|
+
}
|
|
61053
|
+
const allAgentIds = /* @__PURE__ */ new Set();
|
|
61054
|
+
const allArtifactIds = /* @__PURE__ */ new Set();
|
|
61055
|
+
const allToolIds = /* @__PURE__ */ new Set();
|
|
61056
|
+
for (const ops of phaseData.values()) {
|
|
61057
|
+
for (const id of ops.agentOps.keys()) allAgentIds.add(id);
|
|
61058
|
+
for (const id of ops.artifactOps.keys()) allArtifactIds.add(id);
|
|
61059
|
+
for (const id of ops.toolOps.keys()) allToolIds.add(id);
|
|
61060
|
+
}
|
|
61061
|
+
const sections = [];
|
|
61062
|
+
if (allAgentIds.size > 0) {
|
|
61063
|
+
const header = ["Agent", ...phases];
|
|
61064
|
+
const rows = [];
|
|
61065
|
+
for (const agentId of allAgentIds) {
|
|
61066
|
+
const agent = dsl.agents[agentId];
|
|
61067
|
+
const label = agent ? agent.role_name : agentId;
|
|
61068
|
+
const row = [label];
|
|
61069
|
+
for (const wfId of phases) {
|
|
61070
|
+
row.push(formatOps(phaseData.get(wfId).agentOps.get(agentId)));
|
|
61071
|
+
}
|
|
61072
|
+
rows.push(row);
|
|
61073
|
+
}
|
|
61074
|
+
sections.push("#### Agent \xD7 Phase\n\n" + buildTable(header, rows));
|
|
61075
|
+
}
|
|
61076
|
+
if (allArtifactIds.size > 0) {
|
|
61077
|
+
const header = ["Artifact", ...phases];
|
|
61078
|
+
const rows = [];
|
|
61079
|
+
for (const artId of allArtifactIds) {
|
|
61080
|
+
const row = [artId];
|
|
61081
|
+
for (const wfId of phases) {
|
|
61082
|
+
row.push(formatOps(phaseData.get(wfId).artifactOps.get(artId)));
|
|
61083
|
+
}
|
|
61084
|
+
rows.push(row);
|
|
61085
|
+
}
|
|
61086
|
+
sections.push("#### Artifact \xD7 Phase\n\n" + buildTable(header, rows));
|
|
61087
|
+
}
|
|
61088
|
+
if (allToolIds.size > 0) {
|
|
61089
|
+
const header = ["Tool", ...phases];
|
|
61090
|
+
const rows = [];
|
|
61091
|
+
for (const toolId of allToolIds) {
|
|
61092
|
+
const row = [toolId];
|
|
61093
|
+
for (const wfId of phases) {
|
|
61094
|
+
row.push(formatOps(phaseData.get(wfId).toolOps.get(toolId)));
|
|
61095
|
+
}
|
|
61096
|
+
rows.push(row);
|
|
61097
|
+
}
|
|
61098
|
+
sections.push("#### Tool \xD7 Phase\n\n" + buildTable(header, rows));
|
|
61099
|
+
}
|
|
61100
|
+
return sections.join("\n\n");
|
|
61101
|
+
}
|
|
60730
61102
|
|
|
60731
61103
|
// src/renderer/renderer.ts
|
|
60732
61104
|
Handlebars.registerHelper("eq", (a3, b3) => a3 === b3);
|
|
@@ -60891,14 +61263,39 @@ Handlebars.registerHelper("size", (obj) => {
|
|
|
60891
61263
|
});
|
|
60892
61264
|
Handlebars.registerHelper(
|
|
60893
61265
|
"sequenceDiagram",
|
|
60894
|
-
function() {
|
|
61266
|
+
function(...args) {
|
|
61267
|
+
const opts = args[args.length - 1];
|
|
61268
|
+
const positionalArgs = args.slice(0, -1);
|
|
61269
|
+
if (typeof positionalArgs[0] === "string" && positionalArgs[1]) {
|
|
61270
|
+
const workflowId = positionalArgs[0];
|
|
61271
|
+
const dsl2 = positionalArgs[1];
|
|
61272
|
+
if (!dsl2.workflow[workflowId]) return "";
|
|
61273
|
+
const ctx = buildWorkflowContext(dsl2, workflowId);
|
|
61274
|
+
return generateSequenceDiagram(
|
|
61275
|
+
ctx.workflow,
|
|
61276
|
+
ctx.relatedTasks,
|
|
61277
|
+
dsl2
|
|
61278
|
+
);
|
|
61279
|
+
}
|
|
60895
61280
|
const workflow = this["workflow"];
|
|
60896
61281
|
const relatedTasks = this["relatedTasks"];
|
|
60897
|
-
const dsl = this["dsl"];
|
|
61282
|
+
const dsl = opts?.hash?.["dsl"] ?? this["dsl"];
|
|
60898
61283
|
if (!workflow || !dsl) return "";
|
|
60899
61284
|
return generateSequenceDiagram(workflow, relatedTasks ?? [], dsl);
|
|
60900
61285
|
}
|
|
60901
61286
|
);
|
|
61287
|
+
Handlebars.registerHelper(
|
|
61288
|
+
"overviewFlowchart",
|
|
61289
|
+
function(...args) {
|
|
61290
|
+
const positionalArgs = args.slice(0, -1);
|
|
61291
|
+
if (positionalArgs[0] && typeof positionalArgs[0] === "object") {
|
|
61292
|
+
return generateOverviewFlowchart(positionalArgs[0]);
|
|
61293
|
+
}
|
|
61294
|
+
const dsl = this["dsl"];
|
|
61295
|
+
if (!dsl) return "";
|
|
61296
|
+
return generateOverviewFlowchart(dsl);
|
|
61297
|
+
}
|
|
61298
|
+
);
|
|
60902
61299
|
function getDslSection(dsl, context) {
|
|
60903
61300
|
const sectionMap = {
|
|
60904
61301
|
agent: dsl.agents,
|
|
@@ -61140,6 +61537,7 @@ export {
|
|
|
61140
61537
|
ArtifactSchema,
|
|
61141
61538
|
BaseResolveError,
|
|
61142
61539
|
CONTEXT_TYPES,
|
|
61540
|
+
CommandSchema,
|
|
61143
61541
|
ConfigLoadError,
|
|
61144
61542
|
ContextTypeSchema,
|
|
61145
61543
|
DslLoadError,
|