import * as readline from "node:readline"; const rl = readline.createInterface({ input: process.stdin, crlfDelay: Infinity }); const mode = process.env.AGENTRUN_FAKE_CODEX_MODE ?? "success"; let threadCounter = 0; let turnCounter = 0; let observedThreadModel = false; for await (const line of rl) { const trimmed = String(line).trim(); if (trimmed.length === 0) continue; const message = JSON.parse(trimmed) as { id?: number; method?: string; params?: Record }; if (message.method === "initialize") { if (mode === "invalid-json") { process.stdout.write('{"token":"test-token-material"\n'); process.exit(0); } respond(message.id, { serverInfo: { name: "fake-codex-app-server", version: "self-test" } }); continue; } if (message.method === "thread/start") { observedThreadModel = Object.hasOwn(message.params ?? {}, "model"); if (mode === "reject-unexpected-model" && observedThreadModel) { respond(message.id, null, { code: -32000, message: "thread/start unexpectedly included model" }); continue; } if (mode === "require-explicit-model" && message.params?.model !== "gpt-5.5") { respond(message.id, null, { code: -32000, message: "thread/start did not include expected model" }); continue; } threadCounter += 1; const thread = { id: `thread_selftest_${threadCounter}` }; notify("thread/started", { thread }); respond(message.id, { thread }); continue; } if (message.method === "thread/resume") { observedThreadModel = Object.hasOwn(message.params ?? {}, "model"); if (mode === "reject-unexpected-model" && observedThreadModel) { respond(message.id, null, { code: -32000, message: "thread/resume unexpectedly included model" }); continue; } if (mode === "require-explicit-model" && message.params?.model !== "gpt-5.5") { respond(message.id, null, { code: -32000, message: "thread/resume did not include expected model" }); continue; } const thread = { id: String(message.params?.threadId ?? "thread_selftest_resumed") }; notify("thread/started", { thread }); respond(message.id, { thread }); continue; } if (message.method === "turn/start") { if (mode === "reject-unexpected-model" && (observedThreadModel || Object.hasOwn(message.params ?? {}, "model"))) { respond(message.id, null, { code: -32000, message: "turn/start unexpectedly included model" }); continue; } if (mode === "require-explicit-model" && message.params?.model !== "gpt-5.5") { respond(message.id, null, { code: -32000, message: "turn/start did not include expected model" }); continue; } if (mode === "missing-turn-result") { respond(message.id, {}); continue; } if (mode === "provider-503-rpc-error") { respond(message.id, null, { code: -32000, message: "responseStreamDisconnected: HTTP 503 Service Unavailable from provider" }); continue; } if (mode === "provider-401-rpc-error") { respond(message.id, null, { code: -32000, message: "HTTP 401 Unauthorized: invalid api key" }); continue; } if (mode === "missing-terminal") { turnCounter += 1; const turn = { id: `turn_selftest_${turnCounter}`, status: "running" }; notify("turn/started", { turn }); respond(message.id, { turn }); continue; } if (mode === "provider-503-terminal") { turnCounter += 1; const turn = { id: `turn_selftest_${turnCounter}`, status: "failed", error: { message: "HTTP 503 Service Unavailable" } }; notify("turn/started", { turn: { id: turn.id, status: "running" } }); notify("turn/completed", { turn }); respond(message.id, { turn }); continue; } if (mode === "provider-429-terminal") { turnCounter += 1; const turn = { id: `turn_selftest_${turnCounter}`, status: "failed", error: { message: "HTTP 429 Too Many Requests: rate limit exceeded" } }; notify("turn/started", { turn: { id: turn.id, status: "running" } }); notify("turn/completed", { turn }); respond(message.id, { turn }); continue; } if (mode === "provider-503-retry-event") { turnCounter += 1; const turn = { id: `turn_selftest_${turnCounter}`, status: "failed", error: { message: "unexpected status 503 Service Unavailable: Service temporarily unavailable", codexErrorInfo: { responseStreamDisconnected: { httpStatusCode: 503 } }, }, }; notify("turn/started", { turn: { id: turn.id, status: "running" } }); notify("error", { willRetry: true, error: { message: "Reconnecting... 1/5", codexErrorInfo: { responseStreamDisconnected: { httpStatusCode: 503 } }, additionalDetails: "unexpected status 503 Service Unavailable: Service temporarily unavailable, url: https://hyueapi.com/responses", }, }); notify("turn/completed", { turn }); respond(message.id, { turn }); continue; } if (mode === "multi-agent-message-final") { turnCounter += 1; const turn = { id: `turn_selftest_${turnCounter}`, status: "completed" }; notify("turn/started", { turn }); notify("item/agentMessage/delta", { itemId: "msg_progress", delta: "I am checking the workspace. " }); notify("item/completed", { item: { id: "msg_progress", type: "agentMessage", text: "I am checking the workspace." } }); notify("item/agentMessage/delta", { itemId: "msg_final", delta: "Final answer only." }); notify("item/completed", { item: { id: "msg_final", type: "agentMessage", text: "Final answer only." } }); notify("turn/completed", { turn }); respond(message.id, { turn }); continue; } turnCounter += 1; const turn = { id: `turn_selftest_${turnCounter}`, status: "completed" }; notify("turn/started", { turn }); notify("item/agentMessage/delta", { itemId: "msg_selftest", delta: "fake codex stdio reply" }); notify("item/commandExecution/outputDelta", { itemId: "cmd_selftest", delta: "Authorization: Bearer test-token\n" }); notify("turn/completed", { turn }); respond(message.id, { turn }); continue; } respond(message.id, null, { code: -32601, message: `unsupported fake method ${message.method ?? "unknown"}` }); } function respond(id: number | undefined, result: unknown, error?: unknown): void { if (id === undefined) return; process.stdout.write(`${JSON.stringify(error ? { id, error } : { id, result })}\n`); } function notify(method: string, params: unknown): void { process.stdout.write(`${JSON.stringify({ method, params })}\n`); }