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/README.md +168 -2
- package/dist/cli.js +534 -11
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +23 -0
- package/dist/index.js +477 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -11927,7 +11927,7 @@ var require_getJsonPathForPosition = __commonJS({
|
|
|
11927
11927
|
return;
|
|
11928
11928
|
return path;
|
|
11929
11929
|
};
|
|
11930
|
-
function*
|
|
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
|
|
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(
|
|
59039
|
+
process.stdout.write(JSON.stringify(data, null, 2) + "\n");
|
|
58993
59040
|
} else {
|
|
58994
|
-
process.stdout.write(stringify(
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|