diff --git a/packages/spark/src/coding-tools.ts b/packages/spark/src/coding-tools.ts index 662866a..9696411 100644 --- a/packages/spark/src/coding-tools.ts +++ b/packages/spark/src/coding-tools.ts @@ -1,6 +1,8 @@ export { buildClaudeCommandForTest, + buildClaudeSmokeCommandForTest, buildCodexCommandForTest, + buildCodexSmokeCommandForTest, codingToolLabel, discoverCodingTools, parseClaudeEventForTest, diff --git a/packages/spark/src/coding-tools/claude.ts b/packages/spark/src/coding-tools/claude.ts index da03286..b13bca7 100644 --- a/packages/spark/src/coding-tools/claude.ts +++ b/packages/spark/src/coding-tools/claude.ts @@ -23,6 +23,10 @@ export const claudeAdapter: Adapter = { command: commandPath, args: [ "-p", + "--model", + "haiku", + "--effort", + "low", "--verbose", "--output-format", "stream-json", diff --git a/packages/spark/src/coding-tools/codex.ts b/packages/spark/src/coding-tools/codex.ts index d2992e9..e509684 100644 --- a/packages/spark/src/coding-tools/codex.ts +++ b/packages/spark/src/coding-tools/codex.ts @@ -14,7 +14,14 @@ import { stringField, } from "./utils"; -const CODEX_MODEL_ARGS = [ +const CODEX_SMOKE_MODEL_ARGS = [ + "--model", + "gpt-5.4-mini", + "-c", + 'model_reasoning_effort="low"', +] as const; + +const CODEX_RUN_MODEL_ARGS = [ "--model", "gpt-5.5", "-c", @@ -33,7 +40,7 @@ export const codexAdapter: Adapter = { "--json", "--ephemeral", "--skip-git-repo-check", - ...CODEX_MODEL_ARGS, + ...CODEX_SMOKE_MODEL_ARGS, "-s", "read-only", "-C", @@ -50,7 +57,7 @@ export const codexAdapter: Adapter = { "--json", "--ephemeral", "--skip-git-repo-check", - ...CODEX_MODEL_ARGS, + ...CODEX_RUN_MODEL_ARGS, "-s", "danger-full-access", "--dangerously-bypass-approvals-and-sandbox", diff --git a/packages/spark/src/coding-tools/index.ts b/packages/spark/src/coding-tools/index.ts index ffc73f2..2ddaa16 100644 --- a/packages/spark/src/coding-tools/index.ts +++ b/packages/spark/src/coding-tools/index.ts @@ -100,6 +100,14 @@ export function buildClaudeCommandForTest(args: { return adapterFor("claude").runCommand(args); } +export function buildClaudeSmokeCommandForTest(args: { + readonly commandPath: string; + readonly cwd: string; + readonly prompt: string; +}): CommandSpec { + return adapterFor("claude").smokeCommand(args); +} + export function buildCodexCommandForTest(args: { readonly commandPath: string; readonly cwd: string; @@ -109,6 +117,14 @@ export function buildCodexCommandForTest(args: { return adapterFor("codex").runCommand(args); } +export function buildCodexSmokeCommandForTest(args: { + readonly commandPath: string; + readonly cwd: string; + readonly prompt: string; +}): CommandSpec { + return adapterFor("codex").smokeCommand(args); +} + export function parseClaudeEventForTest( value: unknown, cwd: string, diff --git a/packages/spark/test/coding-tools.test.ts b/packages/spark/test/coding-tools.test.ts index 87af9e3..30e1ded 100644 --- a/packages/spark/test/coding-tools.test.ts +++ b/packages/spark/test/coding-tools.test.ts @@ -2,7 +2,9 @@ import { describe, expect, it } from "vitest"; import { buildClaudeCommandForTest, + buildClaudeSmokeCommandForTest, buildCodexCommandForTest, + buildCodexSmokeCommandForTest, parseClaudeEventForTest, parseClaudeEventsForTest, parseClaudeStatusForTest, @@ -115,6 +117,25 @@ describe("coding tool command construction", () => { expect(spec.stdin).toBe("prompt"); }); + it("builds low-cost Claude Code smoke command", () => { + const spec = buildClaudeSmokeCommandForTest({ + commandPath: "/bin/claude", + cwd: CWD, + prompt: "prompt", + }); + + expect(spec.command).toBe("/bin/claude"); + expect(spec.args).toContain("--model"); + expect(spec.args).toContain("haiku"); + expect(spec.args).toContain("--effort"); + expect(spec.args).toContain("low"); + expect(spec.args).toContain("--tools"); + expect(spec.args).toContain(""); + expect(spec.args).not.toContain("bypassPermissions"); + expect(spec.args).not.toContain("--dangerously-skip-permissions"); + expect(spec.stdin).toBe("prompt"); + }); + it("builds autonomous Codex command", () => { const spec = buildCodexCommandForTest({ commandPath: "/bin/codex", @@ -134,6 +155,27 @@ describe("coding tool command construction", () => { expect(spec.args.at(-1)).toBe("-"); expect(spec.stdin).toBe("prompt"); }); + + it("builds low-cost Codex smoke command", () => { + const spec = buildCodexSmokeCommandForTest({ + commandPath: "/bin/codex", + cwd: CWD, + prompt: "prompt", + }); + + expect(spec.command).toBe("/bin/codex"); + expect(spec.args).toContain("--json"); + expect(spec.args).toContain("--model"); + expect(spec.args).toContain("gpt-5.4-mini"); + expect(spec.args).toContain('model_reasoning_effort="low"'); + expect(spec.args).toContain("read-only"); + expect(spec.args).not.toContain("danger-full-access"); + expect(spec.args).not.toContain( + "--dangerously-bypass-approvals-and-sandbox", + ); + expect(spec.args.at(-1)).toBe("-"); + expect(spec.stdin).toBe("prompt"); + }); }); describe("coding tool event normalization", () => {