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
9 changes: 3 additions & 6 deletions apps/ade-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,15 +291,12 @@ ade prs comments pr-id --text
ade run defs --text
ade run start web --lane lane-id
ade shell start --lane lane-id -- npm test
ade shell start-cli codex --lane lane-id --permission-mode edit --message "fix failing tests"
ade shell start-cli claude --lane lane-id --model anthropic/claude-opus-4-8 --reasoning-effort ultracode --prompt "fix failing tests"
ade shell start-cli --provider claude --lane lane-id --permission-mode default
ade new chat --mode chat --lane lane-id --provider codex --model openai/gpt-5.5 --reasoning-effort xhigh --no-fast --permissions full-auto --prompt "fix failing tests"
ade new chat --mode cli --lane lane-id --provider codex --model openai/gpt-5.5 --reasoning-effort xhigh --no-fast --permissions full-auto --prompt "fix failing tests"
ade new chat --mode chat --lane auto --lane-name fix-checkout-flow --prompt "fix failing tests"
ade chat list --lane lane-id --include-automation --no-archived --text
ade chat create --lane lane-id --provider codex --model openai/gpt-5.5 --reasoning-effort xhigh --no-fast --permissions full-auto
ade chat create --lane lane-id --provider claude --model anthropic/claude-opus-4-8 --prompt "fix failing tests"
ade chat create --lane lane-id --provider codex --model openai/gpt-5.5 --permissions full-auto --print-config --json
ade chat read session-id --limit 20 --text
ade agent spawn --lane lane-id --provider codex --model openai/gpt-5.5 --permissions full-auto --prompt "fix failing tests"
ade code
ade code --embedded
ade tests run --lane lane-id --suite unit --wait
Expand Down
3 changes: 2 additions & 1 deletion apps/ade-cli/src/adeRpcServer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1636,6 +1636,7 @@ describe("adeRpcServer", () => {
initialInput: "fix failing tests",
modelId: "openai/gpt-5.5",
reasoningEffort: "xhigh",
fastMode: false,
cols: 90,
rows: 24,
});
Expand All @@ -1656,7 +1657,7 @@ describe("adeRpcServer", () => {
}),
);
const createCall = fixture.runtime.ptyService.create.mock.calls.at(-1)?.[0];
expect(createCall?.args).toEqual(expect.arrayContaining(["--model", "gpt-5.5", "-c", "model_reasoning_effort=\"xhigh\""]));
expect(createCall?.args).toEqual(expect.arrayContaining(["--model", "gpt-5.5", "-c", "model_reasoning_effort=\"xhigh\"", "-c", "service_tier=\"default\""]));
expect(createCall?.args).not.toContain(expect.stringContaining("fix failing tests"));
expect(createCall?.initialInput).toContain("fix failing tests");
expect(createCall?.initialInputDelayMs).toBe(750);
Expand Down
8 changes: 8 additions & 0 deletions apps/ade-cli/src/adeRpcServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ const TOOL_SPECS: ToolSpec[] = [
model: { type: "string" },
modelId: { type: "string" },
reasoningEffort: { type: "string" },
fastMode: { type: "boolean" },
codexFastMode: { type: "boolean", deprecated: true },
cwd: { type: "string" },
chatSessionId: { type: "string" },
tracked: { type: "boolean", default: true }
Expand Down Expand Up @@ -1663,6 +1665,10 @@ function asBoolean(value: unknown, fallback = false): boolean {
return typeof value === "boolean" ? value : fallback;
}

function asOptionalBoolean(value: unknown): boolean | undefined {
return typeof value === "boolean" ? value : undefined;
}

function asPositiveInteger(value: unknown): number | null {
let parsed = NaN;
if (typeof value === "number") parsed = value;
Expand Down Expand Up @@ -3473,6 +3479,7 @@ async function runTool(args: {
const initialInput = asOptionalTrimmedString(toolArgs.initialInput)?.slice(0, 20_000) ?? null;
const model = asOptionalTrimmedString(toolArgs.model) ?? asOptionalTrimmedString(toolArgs.modelId);
const reasoningEffort = asOptionalTrimmedString(toolArgs.reasoningEffort);
const fastMode = asOptionalBoolean(toolArgs.fastMode) ?? asOptionalBoolean(toolArgs.codexFastMode);
const initialInputMeta = deriveTrackedCliInitialInputSessionMeta({
provider,
title: asOptionalTrimmedString(toolArgs.title),
Expand All @@ -3498,6 +3505,7 @@ async function runTool(args: {
sessionId: preassignedSessionId,
model,
reasoningEffort,
fastMode,
initialPrompt: initialInput,
laneWorktreePath,
});
Expand Down
184 changes: 183 additions & 1 deletion apps/ade-cli/src/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,161 @@ describe("ADE CLI", () => {
});
});

it("builds new chat mode with auto-created lane and kickoff prompt", () => {
const plan = buildCliPlan([
"new",
"chat",
"--mode",
"chat",
"--lane",
"auto",
"--lane-name",
"fix-login",
"--base",
"origin/main",
"--provider",
"codex",
"--model",
"openai/gpt-5.5",
"--reasoning-effort",
"xhigh",
"--permissions",
"full-auto",
"--no-fast",
"--prompt",
"Fix login",
"--arg",
"openInUi=true",
]);

const executePlan = expectExecutePlan(plan);
expect(executePlan.steps).toHaveLength(3);
expect(executePlan.steps[0]?.params).toEqual({
name: "create_lane",
arguments: {
name: "fix-login",
baseBranch: "origin/main",
},
});

const createParams = (executePlan.steps[1]?.params as (v: Record<string, unknown>) => Record<string, unknown>)({
lane: { id: "lane-new" },
});
expect(createParams).toMatchObject({
name: "run_ade_action",
arguments: {
domain: "chat",
action: "createSession",
args: {
laneId: "lane-new",
provider: "codex",
model: "openai/gpt-5.5",
modelId: "openai/gpt-5.5",
reasoningEffort: "xhigh",
permissionMode: "full-auto",
fastMode: false,
codexFastMode: false,
openInUi: true,
},
},
});

const sendParams = (executePlan.steps[2]?.params as (v: Record<string, unknown>) => Record<string, unknown>)({
session: { domain: "chat", action: "createSession", result: { sessionId: "chat-new" } },
});
expect(sendParams).toMatchObject({
name: "run_ade_action",
arguments: {
domain: "chat",
action: "sendMessage",
args: {
sessionId: "chat-new",
text: "Fix login",
},
},
});
});

it("builds new chat CLI mode with the same launch controls", () => {
const plan = buildCliPlan([
"new",
"chat",
"--mode",
"cli",
"--lane",
"lane-1",
"--provider",
"Codex",
"--model",
"openai/gpt-5.5",
"--reasoning-effort",
"xhigh",
"--permissions",
"full-auto",
"--no-fast",
"--prompt",
"Fix the tests",
]);

const executePlan = expectExecutePlan(plan);
expect(executePlan.label).toBe("new chat cli");
expect(executePlan.steps).toHaveLength(1);
const launchParams = (executePlan.steps[0]?.params as (v: Record<string, unknown>) => Record<string, unknown>)({});
expect(launchParams).toMatchObject({
name: "start_cli_session",
arguments: {
laneId: "lane-1",
provider: "codex",
model: "openai/gpt-5.5",
modelId: "openai/gpt-5.5",
reasoningEffort: "xhigh",
permissionMode: "full-auto",
fastMode: false,
codexFastMode: false,
initialInput: "Fix the tests",
cols: 120,
rows: 36,
tracked: true,
},
});
});

it("rejects unknown providers for new chat before launching", () => {
expect(() =>
buildCliPlan([
"new",
"chat",
"--lane",
"lane-1",
"--provider",
"mystery",
]),
).toThrow(/Provider must be claude, codex, cursor, droid, opencode, or shell/);
});

it("does not treat new --mode values as subcommands", () => {
const plan = buildCliPlan([
"new",
"--mode",
"cli",
"--lane",
"lane-1",
"--prompt",
"Fix the tests",
]);

const executePlan = expectExecutePlan(plan);
const launchParams = (executePlan.steps[0]?.params as (v: Record<string, unknown>) => Record<string, unknown>)({});
expect(launchParams).toMatchObject({
name: "start_cli_session",
arguments: {
laneId: "lane-1",
provider: "codex",
initialInput: "Fix the tests",
},
});
});

it("prints chat create config without launching a session", () => {
const plan = buildCliPlan([
"chat",
Expand Down Expand Up @@ -1592,6 +1747,30 @@ describe("ADE CLI", () => {
kickoff: { ok: true, accepted: true, sessionId: "chat-new" },
});

const newChatWithLaneAndKickoff = summarizeExecution({
plan: { kind: "execute", label: "new chat", steps: [] },
connection: chatConnection,
values: {
lane: { id: "lane-new", name: "fix-login" },
session: {
domain: "chat",
action: "createSession",
result: { sessionId: "chat-new" },
},
result: {
domain: "chat",
action: "sendMessage",
result: { ok: true, accepted: true, sessionId: "chat-new" },
},
},
} as any);
expect(newChatWithLaneAndKickoff).toEqual({
ok: true,
lane: { id: "lane-new", name: "fix-login" },
session: { sessionId: "chat-new" },
kickoff: { ok: true, accepted: true, sessionId: "chat-new" },
});

const chatRead = summarizeExecution({
plan: { kind: "execute", label: "chat read", steps: [] },
connection: chatConnection,
Expand Down Expand Up @@ -2667,13 +2846,14 @@ describe("ADE CLI", () => {
expect(chatCreateHelp.text).toContain("--reasoning-effort");
expect(chatCreateHelp.text).toContain("ultracode");
expect(chatCreateHelp.text).toContain("--prompt <text>");
expect(chatCreateHelp.text).toContain("ade shell start-cli claude");
expect(chatCreateHelp.text).toContain("ade new chat --mode cli");
expect(chatCreateHelp.text).toContain("codexSandbox=danger-full-access");

const chatHelp = buildCliPlan(["help", "chat"]);
expect(chatHelp.kind).toBe("help");
if (chatHelp.kind !== "help") return;
expect(chatHelp.text).toContain("ade chat read <session>");
expect(chatHelp.text).toContain("ade new chat --mode cli");

const agentSpawnHelp = buildCliPlan(["agent", "spawn", "--help"]);
expect(agentSpawnHelp.kind).toBe("help");
Expand Down Expand Up @@ -3539,6 +3719,7 @@ describe("ADE CLI", () => {
"gpt-5.4",
"--reasoning",
"high",
"--no-fast",
"--message",
"fix the tests",
]);
Expand All @@ -3551,6 +3732,7 @@ describe("ADE CLI", () => {
provider: "codex",
model: "gpt-5.4",
reasoningEffort: "high",
fastMode: false,
initialInput: "fix the tests",
}),
});
Expand Down
Loading
Loading