Skip to content

Commit 4ceb8df

Browse files
authored
Merge pull request #3 from AgentWorkforce/fix/cli-version-and-dry-run-labels
fix(cli): dynamic --version + label deterministic steps in dry-run
2 parents eec57c1 + cc345c9 commit 4ceb8df

4 files changed

Lines changed: 65 additions & 2 deletions

File tree

memory/workspace/.relay/state.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"workspaceId":"rw_7ccfea89","remoteRoot":"/memory/workspace","localRoot":"/home/daytona/workspace/memory/workspace","mode":"poll","intervalMs":5000,"lastReconcileAt":"2026-06-05T17:42:35.095091918Z","lastSuccessfulReconcileAt":"2026-06-05T17:42:35.095091918Z","staleAfter":"2026-06-05T17:42:45.095091918Z","status":"ready","states":{"stale":false,"offline":false,"hasConflicts":false,"hasPendingWriteback":false},"pendingWriteback":0,"pendingConflicts":0,"deniedPaths":0,"counters":{"snapshotDeleteBlocked":95},"circuit":{"open":false,"openedAt":"0001-01-01T00:00:00Z","windowMs":60000,"cooldownMs":30000,"threshold":5,"nextRetry":"0001-01-01T00:00:00Z"}}

packages/cli/src/cli.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/usr/bin/env node
2+
import { createRequire } from 'node:module';
23
import path from 'node:path';
34
import { Command } from 'commander';
45
import {
@@ -45,12 +46,19 @@ async function runYamlWorkflow(
4546
return result;
4647
}
4748

49+
// Read the version from package.json at runtime so it stays in sync with the
50+
// version the publish workflow bumps. `../package.json` resolves to the package
51+
// root from both src/cli.ts (dev) and dist/cli.js (published). createRequire
52+
// avoids a static JSON import, which would fall outside tsconfig's rootDir.
53+
const require = createRequire(import.meta.url);
54+
const { version } = require('../package.json') as { version: string };
55+
4856
const program = new Command();
4957

5058
program
5159
.name('relayflows')
5260
.description('Run Agent Relay workflows from the command line')
53-
.version('0.1.0');
61+
.version(version);
5462

5563
program
5664
.command('run <file>')
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { describe, it, expect } from 'vitest';
2+
3+
import { formatDryRunReport } from '../dry-run-format.js';
4+
import type { DryRunReport } from '../types.js';
5+
6+
function makeReport(overrides: Partial<DryRunReport> = {}): DryRunReport {
7+
return {
8+
valid: true,
9+
errors: [],
10+
warnings: [],
11+
name: 'demo',
12+
pattern: 'dag',
13+
agents: [{ name: 'builder', cli: 'claude', stepCount: 1 }],
14+
waves: [
15+
{
16+
wave: 1,
17+
steps: [
18+
{ name: 'implement', agent: 'builder', dependsOn: [] },
19+
// Agent-less step => deterministic (shell/gate) step.
20+
{ name: 'test-gate', dependsOn: ['implement'] },
21+
],
22+
},
23+
],
24+
totalSteps: 2,
25+
estimatedWaves: 1,
26+
...overrides,
27+
};
28+
}
29+
30+
describe('formatDryRunReport', () => {
31+
it('labels agent-less steps as deterministic, not "undefined"', () => {
32+
const out = formatDryRunReport(makeReport());
33+
34+
expect(out).toContain('implement (builder)');
35+
expect(out).toContain('test-gate (deterministic)');
36+
// Regression guard: the literal "undefined" must never reach the plan.
37+
expect(out).not.toContain('(undefined)');
38+
});
39+
40+
it('still renders the agent name when a step has one', () => {
41+
const out = formatDryRunReport(
42+
makeReport({
43+
waves: [{ wave: 1, steps: [{ name: 'review', agent: 'reviewer', dependsOn: [] }] }],
44+
totalSteps: 1,
45+
})
46+
);
47+
48+
expect(out).toContain('review (reviewer)');
49+
expect(out).not.toContain('deterministic');
50+
});
51+
});

packages/core/src/dry-run-format.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ export function formatDryRunReport(report: DryRunReport): string {
5252
for (let i = 0; i < wave.steps.length; i++) {
5353
const step = wave.steps[i];
5454
const prefix = i === 0 ? ` Wave ${String(wave.wave).padStart(2)}:` : ' ';
55-
lines.push(`${prefix} ${step.name} (${step.agent})`);
55+
// Steps without an agent are deterministic (shell/gate) steps; label
56+
// them as such rather than printing the literal "undefined".
57+
const actor = step.agent ?? 'deterministic';
58+
lines.push(`${prefix} ${step.name} (${actor})`);
5659
}
5760
}
5861
lines.push('');

0 commit comments

Comments
 (0)