merge S-303 into M3

This commit is contained in:
2026-05-19 22:04:19 -05:00
2 changed files with 193 additions and 2 deletions
+17 -2
View File
@@ -71,10 +71,25 @@ function printHelp(): void {
Usage: Usage:
ai-cli-dispatch list [--json|--text] ai-cli-dispatch list [--json|--text]
ai-cli-dispatch run --client <client> --prompt <prompt> [--json|--text] ai-cli-dispatch run --client <client> --prompt <prompt> [--sync] [--timeout <ms>] [--debug] [--json|--text]
ai-cli-dispatch dispatch <prompt> [--client <client>] [--json|--text] ai-cli-dispatch dispatch <prompt> [--client <client>] [--sync] [--timeout <ms>] [--debug] [--json|--text]
ai-cli-dispatch start --client <client> --prompt <prompt> [--timeout <ms>] [--debug] [--json|--text]
ai-cli-dispatch status <job-id> [--json|--text]
ai-cli-dispatch results <job-id> [--json|--text]
ai-cli-dispatch cancel <job-id> [--json|--text]
ai-cli-dispatch list-jobs [--status running|completed|failed] [--json|--text]
ai-cli-dispatch cleanup-jobs [--max-age <number>[h|m|s|d]] [--json|--text]
ai-cli-dispatch --help ai-cli-dispatch --help
Flags:
--sync Run synchronously and block until the client returns (default is async)
--timeout Timeout in milliseconds (or override via config)
--debug Emit diagnostic JSON to stderr
--max-age Maximum age for cleanup (default unit: hours)
--status Filter jobs by status (running, completed, failed)
--json Output JSON (default)
--text Output plain text
Clients: codex, claude, opencode`); Clients: codex, claude, opencode`);
} }
+176
View File
@@ -1428,4 +1428,180 @@ describe("main", () => {
out.restore(); out.restore();
} }
}); });
// S-303: help output and CLI integration smoke tests
it("--help output documents start subcommand", async () => {
const out = captureOutput();
try {
const code = await main(["node", "cli.ts", "--help"]);
assert.strictEqual(code, 0);
const help = out.logs.join("\n");
assert.ok(help.includes("start"), "help should mention start");
} finally {
out.restore();
}
});
it("--help output documents status subcommand", async () => {
const out = captureOutput();
try {
const code = await main(["node", "cli.ts", "--help"]);
assert.strictEqual(code, 0);
const help = out.logs.join("\n");
assert.ok(help.includes("status"), "help should mention status");
} finally {
out.restore();
}
});
it("--help output documents results subcommand", async () => {
const out = captureOutput();
try {
const code = await main(["node", "cli.ts", "--help"]);
assert.strictEqual(code, 0);
const help = out.logs.join("\n");
assert.ok(help.includes("results"), "help should mention results");
} finally {
out.restore();
}
});
it("--help output documents cancel subcommand", async () => {
const out = captureOutput();
try {
const code = await main(["node", "cli.ts", "--help"]);
assert.strictEqual(code, 0);
const help = out.logs.join("\n");
assert.ok(help.includes("cancel"), "help should mention cancel");
} finally {
out.restore();
}
});
it("--help output documents list-jobs subcommand", async () => {
const out = captureOutput();
try {
const code = await main(["node", "cli.ts", "--help"]);
assert.strictEqual(code, 0);
const help = out.logs.join("\n");
assert.ok(help.includes("list-jobs"), "help should mention list-jobs");
} finally {
out.restore();
}
});
it("--help output documents cleanup-jobs subcommand", async () => {
const out = captureOutput();
try {
const code = await main(["node", "cli.ts", "--help"]);
assert.strictEqual(code, 0);
const help = out.logs.join("\n");
assert.ok(help.includes("cleanup-jobs"), "help should mention cleanup-jobs");
} finally {
out.restore();
}
});
it("--help output documents --sync flag", async () => {
const out = captureOutput();
try {
const code = await main(["node", "cli.ts", "--help"]);
assert.strictEqual(code, 0);
const help = out.logs.join("\n");
assert.ok(help.includes("--sync"), "help should mention --sync");
} finally {
out.restore();
}
});
it("--help output documents --timeout flag", async () => {
const out = captureOutput();
try {
const code = await main(["node", "cli.ts", "--help"]);
assert.strictEqual(code, 0);
const help = out.logs.join("\n");
assert.ok(help.includes("--timeout"), "help should mention --timeout");
} finally {
out.restore();
}
});
it("--help output documents --debug flag", async () => {
const out = captureOutput();
try {
const code = await main(["node", "cli.ts", "--help"]);
assert.strictEqual(code, 0);
const help = out.logs.join("\n");
assert.ok(help.includes("--debug"), "help should mention --debug");
} finally {
out.restore();
}
});
it("--help output documents --max-age flag", async () => {
const out = captureOutput();
try {
const code = await main(["node", "cli.ts", "--help"]);
assert.strictEqual(code, 0);
const help = out.logs.join("\n");
assert.ok(help.includes("--max-age"), "help should mention --max-age");
} finally {
out.restore();
}
});
it("--help output documents --status flag for list-jobs", async () => {
const out = captureOutput();
try {
const code = await main(["node", "cli.ts", "--help"]);
assert.strictEqual(code, 0);
const help = out.logs.join("\n");
assert.ok(help.includes("--status"), "help should mention --status");
} finally {
out.restore();
}
});
it("start returns 1 for unknown client", async () => {
const out = captureOutput();
try {
const code = await main(
["node", "cli.ts", "start", "--client", "bogus", "--prompt", "hello"],
{
detectClients: () => mockClients,
}
);
assert.strictEqual(code, 1);
const parsed = JSON.parse(out.errors[0]);
assert.ok(parsed.error.includes("client"));
} finally {
out.restore();
}
});
it("start prints text output with --text", async () => {
const out = captureOutput();
try {
const code = await main(
["node", "cli.ts", "start", "--client", "codex", "--prompt", "hello", "--text"],
{
detectClients: () => mockClients,
startJob: async (client, prompt) => ({
id: "job-start-txt",
client,
prompt,
status: "running",
startedAt: new Date().toISOString(),
}),
}
);
assert.strictEqual(code, 0);
assert.ok(out.logs[0].includes("job-start-txt"));
assert.ok(out.logs[0].includes("codex"));
assert.ok(out.logs[0].includes("running"));
} finally {
out.restore();
}
});
}); });