Files
tutti/apps/desktop/scripts/smoke-claude-sdk-sidecar.mjs
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

143 lines
3.8 KiB
JavaScript

#!/usr/bin/env node
import { spawn } from "node:child_process";
import { createInterface } from "node:readline";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const defaultBundleDir = join(__dirname, "..", "build", "claude-sdk-sidecar");
const DEFAULT_TIMEOUT_MS = 15_000;
export async function smokeClaudeSDKSidecar({
bundleDir = defaultBundleDir,
nodeExecutable = process.execPath,
timeoutMs = DEFAULT_TIMEOUT_MS
} = {}) {
const entry = join(bundleDir, "src", "main.ts");
const child = spawn(nodeExecutable, ["--experimental-strip-types", entry], {
cwd: bundleDir,
env: {
...process.env,
TUTTI_CLAUDE_SDK_SIDECAR_TEST_DRIVER: "1"
},
stdio: ["pipe", "pipe", "pipe"]
});
const exitPromise = new Promise((resolveExit, rejectExit) => {
child.once("error", rejectExit);
child.once("exit", resolveExit);
});
void exitPromise.catch(() => {});
const lines = createInterface({ input: child.stdout });
const iterator = lines[Symbol.asyncIterator]();
let stderr = "";
child.stderr.setEncoding("utf8");
child.stderr.on("data", (chunk) => {
stderr = `${stderr}${chunk}`.slice(-8_000);
});
const send = (request) => {
child.stdin.write(`${JSON.stringify({ version: 10, ...request })}\n`);
};
const waitForEvent = async (predicate, label) => {
while (true) {
const next = await withTimeout(
iterator.next(),
timeoutMs,
`timed out waiting for ${label}`
);
if (next.done) {
throw new Error(`sidecar exited before ${label}`);
}
const event = JSON.parse(next.value);
if (event.type === "error") {
throw new Error(`sidecar protocol error: ${JSON.stringify(event)}`);
}
if (predicate(event)) {
return event;
}
}
};
try {
send({
id: "smoke-start",
type: "start",
payload: {
agentSessionId: "smoke-agent-session",
providerSessionId: "smoke-provider-session",
cwd: bundleDir,
env: {},
settings: {}
}
});
await waitForEvent(
(event) => event.type === "session_started",
"session_started"
);
send({
id: "smoke-exec",
type: "exec",
payload: {
agentSessionId: "smoke-agent-session",
turnId: "smoke-turn",
prompt: "sidecar startup smoke"
}
});
await waitForEvent(
(event) =>
event.type === "turn_completed" &&
event.payload?.turnId === "smoke-turn",
"turn_completed"
);
send({
id: "smoke-close",
type: "close",
payload: { agentSessionId: "smoke-agent-session" }
});
await waitForEvent(
(event) => event.type === "ok" && event.id === "smoke-close",
"close acknowledgement"
);
child.stdin.end();
const exitCode = await withTimeout(
exitPromise,
timeoutMs,
"timed out waiting for sidecar exit"
);
if (exitCode !== 0) {
throw new Error(`sidecar exited with code ${String(exitCode)}`);
}
} catch (error) {
child.kill();
const detail = stderr.trim() ? `\nstderr:\n${stderr.trim()}` : "";
throw new Error(
`${error instanceof Error ? error.message : error}${detail}`
);
} finally {
lines.close();
}
}
function withTimeout(promise, timeoutMs, message) {
let timer;
return Promise.race([
promise,
new Promise((_, reject) => {
timer = setTimeout(() => reject(new Error(message)), timeoutMs);
})
]).finally(() => clearTimeout(timer));
}
if (
process.argv[1] &&
fileURLToPath(import.meta.url) === resolve(process.argv[1])
) {
const bundleDir = process.argv[2]
? resolve(process.argv[2])
: defaultBundleDir;
await smokeClaudeSDKSidecar({ bundleDir });
process.stderr.write(`[smoke-claude-sdk-sidecar] OK: ${bundleDir}\n`);
}