import { spawn } from "node:child_process";
import { setTimeout as delay } from "node:timers/promises";
import { createAuthenticatedTestClient } from "./lib/authenticated-test-client.mjs";
const apiPort = process.env.API_PORT ?? "8798";
const apiBaseUrl = `http://127.0.0.1:${apiPort}`;
const metadataDbPath = process.env.METADATA_DB_PATH ?? `storage/metadata/copilotkit-smoke-${Date.now()}.sqlite`;
const child = spawn("npm", ["--workspace", "@datafoundry/api", "run", "dev"], {
env: {
...process.env,
API_HOST: "127.0.0.1",
API_PORT: apiPort,
METADATA_DB_PATH: metadataDbPath,
AUTH_SESSION_SECRET: process.env.AUTH_SESSION_SECRET ?? "copilotkit-smoke-session-secret-32b!",
AUTH_PUBLIC_BASE_URL: process.env.AUTH_PUBLIC_BASE_URL ?? "http://127.0.0.1:3000",
AUTH_EMAIL_DELIVERY: process.env.AUTH_EMAIL_DELIVERY ?? "test",
AUTH_REGISTRATION_MODE: process.env.AUTH_REGISTRATION_MODE ?? "open"
},
stdio: ["ignore", "pipe", "pipe"]
});
let output = "";
child.stdout.on("data", (chunk) => {
output += chunk.toString();
});
child.stderr.on("data", (chunk) => {
output += chunk.toString();
});
try {
await waitForHealth(apiBaseUrl);
const client = createAuthenticatedTestClient({ baseUrl: apiBaseUrl });
await client.registerAndLogin({ displayName: "CopilotKit Smoke" });
const optionsResponse = await client.fetch("/api/copilotkit", {
method: "OPTIONS",
headers: {
Origin: "http://127.0.0.1:3000",
"Access-Control-Request-Method": "POST"
}
});
if (optionsResponse.status !== 204) {
throw new Error(`Unexpected CopilotKit OPTIONS status: ${optionsResponse.status}`);
}
const postResponse = await client.fetch("/api/copilotkit", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({})
});
const body = await postResponse.json();
const validMissingProviderResponse =
postResponse.status === 503 && body?.error?.code === "PROVIDER_CONFIG_MISSING";
const validRuntimeValidationResponse = postResponse.status === 400 && body?.message === "Missing method field";
if (!validMissingProviderResponse && !validRuntimeValidationResponse) {
throw new Error(`Unexpected CopilotKit validation response: ${postResponse.status} ${JSON.stringify(body)}`);
}
console.log("CopilotKit smoke OK: /api/copilotkit CORS and runtime validation are reachable");
} finally {
child.kill("SIGTERM");
}
async function waitForHealth(baseUrl) {
const startedAt = Date.now();
while (Date.now() - startedAt < 15000) {
try {
const response = await fetch(`${baseUrl}/healthz`);
if (response.ok) {
return;
}
} catch {
}
await delay(300);
}
throw new Error(`API did not become healthy. Output:\n${output}`);
}