fix: support Claude stream-json verbose mode
This commit is contained in:
@@ -154,7 +154,7 @@ describe("ClaudeAdapter", () => {
|
||||
beforeEach(() => { tmpDir = makeTmpDir(); });
|
||||
afterEach(() => { cleanupDir(tmpDir); });
|
||||
|
||||
it("start includes --session-id and -p flags", async () => {
|
||||
it("start includes --session-id, -p, --verbose, and --output-format flags", async () => {
|
||||
const argsFile = path.join(tmpDir, "args.txt");
|
||||
const fakeBin = writeFakeCli(tmpDir, {
|
||||
argsFile,
|
||||
@@ -170,10 +170,17 @@ describe("ClaudeAdapter", () => {
|
||||
config: { binary: fakeBin },
|
||||
});
|
||||
|
||||
const capturedArgs = fs.existsSync(argsFile) ? fs.readFileSync(argsFile, "utf8") : "";
|
||||
const capturedArgs = fs.existsSync(argsFile)
|
||||
? fs.readFileSync(argsFile, "utf8").split("\0").filter(Boolean)
|
||||
: [];
|
||||
expect(capturedArgs).toContain("-p");
|
||||
expect(capturedArgs).toContain("--output-format");
|
||||
expect(capturedArgs).toContain("--session-id");
|
||||
expect(capturedArgs).toContain("--verbose");
|
||||
const outputFormatIdx = capturedArgs.indexOf("--output-format");
|
||||
expect(outputFormatIdx).toBeGreaterThanOrEqual(0);
|
||||
expect(capturedArgs[outputFormatIdx + 1]).toBe("stream-json");
|
||||
const sessionIdIdx = capturedArgs.indexOf("--session-id");
|
||||
expect(sessionIdIdx).toBeGreaterThanOrEqual(0);
|
||||
expect(capturedArgs[sessionIdIdx + 1]).toMatch(/^[0-9a-f-]{36}$/i);
|
||||
expect(result.sessionHandle?.kind).toBe("claude");
|
||||
});
|
||||
|
||||
@@ -192,9 +199,17 @@ describe("ClaudeAdapter", () => {
|
||||
config: { binary: fakeBin },
|
||||
});
|
||||
|
||||
const capturedArgs = fs.existsSync(argsFile) ? fs.readFileSync(argsFile, "utf8") : "";
|
||||
expect(capturedArgs).toContain("--resume");
|
||||
expect(capturedArgs).toContain("captured-session-id");
|
||||
const capturedArgs = fs.existsSync(argsFile)
|
||||
? fs.readFileSync(argsFile, "utf8").split("\0").filter(Boolean)
|
||||
: [];
|
||||
expect(capturedArgs).toContain("-p");
|
||||
expect(capturedArgs).toContain("--verbose");
|
||||
const outputFormatIdx = capturedArgs.indexOf("--output-format");
|
||||
expect(outputFormatIdx).toBeGreaterThanOrEqual(0);
|
||||
expect(capturedArgs[outputFormatIdx + 1]).toBe("stream-json");
|
||||
const resumeIdx = capturedArgs.indexOf("--resume");
|
||||
expect(resumeIdx).toBeGreaterThanOrEqual(0);
|
||||
expect(capturedArgs[resumeIdx + 1]).toBe("captured-session-id");
|
||||
expect(result.sessionHandle?.kind).toBe("claude");
|
||||
});
|
||||
|
||||
@@ -338,10 +353,15 @@ printf '%s\\0' "$@" >> "${argsFile}"
|
||||
config: { binary: trackingBin },
|
||||
});
|
||||
|
||||
// 1) --output-format stream-json was passed
|
||||
const capturedArgs = fs.existsSync(argsFile) ? fs.readFileSync(argsFile, "utf8") : "";
|
||||
expect(capturedArgs).toContain("--output-format");
|
||||
expect(capturedArgs).toContain("stream-json");
|
||||
// 1) --output-format stream-json, -p, --verbose were passed
|
||||
const capturedArgs = fs.existsSync(argsFile)
|
||||
? fs.readFileSync(argsFile, "utf8").split("\0").filter(Boolean)
|
||||
: [];
|
||||
expect(capturedArgs).toContain("-p");
|
||||
expect(capturedArgs).toContain("--verbose");
|
||||
const outputFormatIdx = capturedArgs.indexOf("--output-format");
|
||||
expect(outputFormatIdx).toBeGreaterThanOrEqual(0);
|
||||
expect(capturedArgs[outputFormatIdx + 1]).toBe("stream-json");
|
||||
|
||||
// 2) Exact session preservation
|
||||
if (result.sessionHandle?.kind === "claude") {
|
||||
@@ -384,11 +404,17 @@ printf '%s\\0' "$@" >> "${argsFile}"
|
||||
expect(sidecar!.phase).toBe("failed");
|
||||
});
|
||||
|
||||
it("resume: preserves session ID from the handle", async () => {
|
||||
it("resume: preserves session ID from the handle and passes expected args", async () => {
|
||||
const argsFile = path.join(tmpDir, "args.txt");
|
||||
const fakeBin = makeFakeClaude([
|
||||
'{"type":"system","subtype":"init","session_id":"resumed-session-999"}',
|
||||
'{"type":"result","result":"completed"}',
|
||||
]);
|
||||
const trackingBin = path.join(tmpDir, "tracking-claude.sh");
|
||||
fs.writeFileSync(trackingBin, `#!/bin/bash
|
||||
printf '%s\\0' "$@" >> "${argsFile}"
|
||||
"${fakeBin}" "$@"
|
||||
`, { mode: 0o755 });
|
||||
|
||||
const adapter = createExecutorAdapter("claude");
|
||||
const logFilePath = path.join(tmpDir, "claude-resume.log");
|
||||
@@ -400,9 +426,21 @@ printf '%s\\0' "$@" >> "${argsFile}"
|
||||
runDir: tmpDir,
|
||||
cycleIndex: 2,
|
||||
logFilePath,
|
||||
config: { binary: fakeBin },
|
||||
config: { binary: trackingBin },
|
||||
});
|
||||
|
||||
const capturedArgs = fs.existsSync(argsFile)
|
||||
? fs.readFileSync(argsFile, "utf8").split("\0").filter(Boolean)
|
||||
: [];
|
||||
expect(capturedArgs).toContain("-p");
|
||||
expect(capturedArgs).toContain("--verbose");
|
||||
const outputFormatIdx = capturedArgs.indexOf("--output-format");
|
||||
expect(outputFormatIdx).toBeGreaterThanOrEqual(0);
|
||||
expect(capturedArgs[outputFormatIdx + 1]).toBe("stream-json");
|
||||
const resumeIdx = capturedArgs.indexOf("--resume");
|
||||
expect(resumeIdx).toBeGreaterThanOrEqual(0);
|
||||
expect(capturedArgs[resumeIdx + 1]).toBe("resumed-session-999");
|
||||
|
||||
if (result.sessionHandle?.kind === "claude") {
|
||||
expect(result.sessionHandle.sessionId).toBe("resumed-session-999");
|
||||
}
|
||||
|
||||
@@ -631,6 +631,7 @@ class ClaudeAdapter implements ExecutorAdapter {
|
||||
|
||||
const args: string[] = [
|
||||
"-p",
|
||||
"--verbose",
|
||||
"--safe-mode",
|
||||
"--permission-mode", "bypassPermissions",
|
||||
"--output-format", "stream-json",
|
||||
@@ -703,6 +704,7 @@ class ClaudeAdapter implements ExecutorAdapter {
|
||||
|
||||
const args: string[] = [
|
||||
"-p",
|
||||
"--verbose",
|
||||
"--safe-mode",
|
||||
"--permission-mode", "bypassPermissions",
|
||||
"--output-format", "stream-json",
|
||||
|
||||
Reference in New Issue
Block a user