R1 and R3 block: a late broker reply shifts later replies on the host IPC channel, and a dangling workspace symlink passes the gate. R2 (close waits on an open launch.sock client) should be fixed in the same round. Probes, mutants and suite outputs alongside. Comment 26995 on #1523, queue rev 247. Co-Authored-By: Claude Opus 5.5 <[email protected]>
46 lines
2.9 KiB
JavaScript
46 lines
2.9 KiB
JavaScript
// A mock Messages API on 127.0.0.1: logs each request body to LOG and
|
|
// streams back one short text answer. No real model is reached.
|
|
import { createServer } from "node:http";
|
|
import { appendFileSync } from "node:fs";
|
|
const LOG = process.argv[2];
|
|
// TOOL_USE: optional JSON {name, input}; the first streamed answer calls it.
|
|
let toolUse = process.env.TOOL_USE ? JSON.parse(process.env.TOOL_USE) : null;
|
|
const sse = (res, ev, data) => res.write(`event: ${ev}\ndata: ${JSON.stringify(data)}\n\n`);
|
|
const server = createServer((req, res) => {
|
|
let body = "";
|
|
req.on("data", (b) => (body += b));
|
|
req.on("end", () => {
|
|
appendFileSync(LOG, `${JSON.stringify({ method: req.method, url: req.url, body })}\n`);
|
|
if (req.method !== "POST" || !req.url.startsWith("/v1/messages") || req.url.includes("count_tokens")) {
|
|
res.writeHead(200, { "content-type": "application/json" });
|
|
return res.end(req.url.includes("count_tokens") ? '{"input_tokens":1}' : "{}");
|
|
}
|
|
let stream = false;
|
|
try { stream = JSON.parse(body).stream === true; } catch {}
|
|
const msg = { id: "msg_mock", type: "message", role: "assistant", model: "claude-sonnet-5-5", content: [], stop_reason: null, stop_sequence: null, usage: { input_tokens: 1, output_tokens: 1 } };
|
|
if (!stream) {
|
|
res.writeHead(200, { "content-type": "application/json" });
|
|
return res.end(JSON.stringify({ ...msg, content: [{ type: "text", text: "mock answer" }], stop_reason: "end_turn" }));
|
|
}
|
|
res.writeHead(200, { "content-type": "text/event-stream" });
|
|
sse(res, "message_start", { type: "message_start", message: msg });
|
|
if (toolUse) {
|
|
const t = toolUse;
|
|
toolUse = null;
|
|
sse(res, "content_block_start", { type: "content_block_start", index: 0, content_block: { type: "tool_use", id: "toolu_mock1", name: t.name, input: {} } });
|
|
sse(res, "content_block_delta", { type: "content_block_delta", index: 0, delta: { type: "input_json_delta", partial_json: JSON.stringify(t.input) } });
|
|
sse(res, "content_block_stop", { type: "content_block_stop", index: 0 });
|
|
sse(res, "message_delta", { type: "message_delta", delta: { stop_reason: "tool_use", stop_sequence: null }, usage: { output_tokens: 2 } });
|
|
sse(res, "message_stop", { type: "message_stop" });
|
|
return res.end();
|
|
}
|
|
sse(res, "content_block_start", { type: "content_block_start", index: 0, content_block: { type: "text", text: "" } });
|
|
sse(res, "content_block_delta", { type: "content_block_delta", index: 0, delta: { type: "text_delta", text: "mock answer" } });
|
|
sse(res, "content_block_stop", { type: "content_block_stop", index: 0 });
|
|
sse(res, "message_delta", { type: "message_delta", delta: { stop_reason: "end_turn", stop_sequence: null }, usage: { output_tokens: 2 } });
|
|
sse(res, "message_stop", { type: "message_stop" });
|
|
res.end();
|
|
});
|
|
});
|
|
server.listen(0, "127.0.0.1", () => console.log(server.address().port));
|