Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/testcases.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,13 @@ Run explicitly with `bun run test:e2e` (not included in `bun test`).
- CLI invoked via `Bun.spawn` running `bun run src/index.ts <command> --yes`
- On test failure, state file is kept and a manual cleanup message is displayed

### CLI Prompt Handling

| # | Case | Input | Expected |
|---|------|-------|----------|
| C-1 | Apply confirmation accepts affirmative answers | `y`, `yes`, mixed case, surrounding whitespace | Apply continues |
| C-2 | Apply confirmation defaults to no | empty input, `n`, `no` | Apply is cancelled |

### E2E-1: Full Lifecycle

Precondition: agup.yaml with environment + skill + agent placed in temp directory
Expand Down
16 changes: 15 additions & 1 deletion packages/cli/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test";
import { parseCliArgs } from "./index.ts";
import { parseCliArgs, parseConfirmationAnswer } from "./index.ts";

describe("parseCliArgs", () => {
test("parses global options before the command", () => {
Expand Down Expand Up @@ -78,3 +78,17 @@ describe("parseCliArgs", () => {
);
});
});

describe("parseConfirmationAnswer", () => {
test("accepts y and yes in a case-insensitive way", () => {
expect(parseConfirmationAnswer("y")).toBe(true);
expect(parseConfirmationAnswer("YES")).toBe(true);
expect(parseConfirmationAnswer(" yes ")).toBe(true);
});

test("rejects empty and non-affirmative answers", () => {
expect(parseConfirmationAnswer("")).toBe(false);
expect(parseConfirmationAnswer("n")).toBe(false);
expect(parseConfirmationAnswer("no")).toBe(false);
});
});
21 changes: 16 additions & 5 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as fs from "node:fs/promises";
import * as path from "node:path";
import { createInterface } from "node:readline/promises";
import { fileURLToPath } from "node:url";
import {
parseYaml,
Expand Down Expand Up @@ -304,13 +305,23 @@ function operationDetail(op: Operation): string {
}
}

export function parseConfirmationAnswer(answer: string): boolean {
const normalized = answer.trim().toLowerCase();
return normalized === "y" || normalized === "yes";
}

async function confirm(message: string): Promise<boolean> {
process.stdout.write(`${message} [y/N] `);
for await (const line of console) {
const answer = (line as string).trim().toLowerCase();
return answer === "y" || answer === "yes";
const rl = createInterface({
input: process.stdin,
output: process.stdout,
});

try {
const answer = await rl.question(`${message} [y/N] `);
return parseConfirmationAnswer(answer);
} finally {
rl.close();
}
return false;
}

async function createApiClient(): Promise<ApiClient> {
Expand Down
Loading