import assert from "node:assert/strict"; import { chmod, mkdtemp, mkdir, writeFile } from "node:fs/promises"; import os from "node:os"; import path from "node:path"; const TEST_AGENT_USERNAME = "server-test-agent"; const TEST_AGENT_PASSWORD = "server-test-agent-password"; const testAuthByPort = new Map(); export function durableBlockedRuntime({ blocker, blockedLayer, queryResult, gates }) { return { adapter: "postgres", durable: false, durableRequested: true, durableCapable: false, ready: false, status: "blocked", blocker, reason: `test durable runtime blocker ${blocker}`, liveRuntimeEvidence: false, fixtureEvidence: false, connection: { queryAttempted: true, queryResult, endpointRedacted: true, valueRedacted: true, errorCode: "TEST_BLOCKER" }, schema: { checked: gates.schema !== "not_checked", ready: gates.schema === "ready", missingTables: gates.schema === "blocked" ? ["gateway_sessions"] : [], missingColumns: gates.schema === "blocked" ? ["gateway_sessions.gateway_session_json"] : [] }, migration: { checked: gates.migration !== "not_checked", ready: gates.migration === "ready", missing: gates.migration !== "ready" }, gates: Object.fromEntries(Object.entries(gates).map(([name, status]) => [ name, { checked: status !== "not_checked", ready: status === "ready", status, blocker: status === "blocked" ? blocker : null } ])), durabilityContract: { ready: false, status: "blocked", requiredEvidence: "runtime_adapter_schema_migration_read_query", dbLiveEvidenceIsDurabilityEvidence: false, liveRuntimeEvidence: false, adapterQueryRequired: true, blockedLayer, blocker, secretMaterialRead: false }, safety: { secretMaterialRead: false, valuesRedacted: true, endpointRedacted: true }, counts: {} }; } export function durableReadyRuntime() { return { adapter: "postgres", durable: true, durableRequested: true, durableCapable: true, ready: true, status: "ready", blocker: null, reason: "test durable runtime ready", liveRuntimeEvidence: true, fixtureEvidence: false, connection: { queryAttempted: true, queryResult: "durable_readiness_ready", endpointRedacted: true, valueRedacted: true }, schema: { checked: true, ready: true, missingTables: [], missingColumns: [] }, migration: { checked: true, ready: true, missing: false }, gates: Object.fromEntries(["ssl", "auth", "schema", "migration", "durability"].map((name) => [ name, { checked: true, ready: true, status: "ready", blocker: null } ])), durabilityContract: { ready: true, status: "ready", requiredEvidence: "runtime_adapter_schema_migration_read_query", dbLiveEvidenceIsDurabilityEvidence: false, liveRuntimeEvidence: true, adapterQueryRequired: true, blockedLayer: null, blocker: null, secretMaterialRead: false }, safety: { secretMaterialRead: false, valuesRedacted: true, endpointRedacted: true }, counts: {} }; } export function layerStatus(gateStatus) { if (gateStatus === "ready") return "pass"; if (gateStatus === "blocked") return "blocked"; return "not_proven"; } export function layerForBlockedCase(blockedLayer) { if (blockedLayer === "durability_query") return "durability"; return blockedLayer; } export async function m3ReadinessRequestJson(url, request = {}) { const parsed = new URL(url); const body = request.body ?? {}; if (url.startsWith("http://gateway-1") && parsed.pathname === "/status") { return { ok: true, status: 200, body: m3GatewayStatus({ gatewayId: "gwsimu_1", gatewaySessionId: "gws_gwsimu_1", boxId: "boxsimu_1", resourceId: "res_boxsimu_1" }) }; } if (url.startsWith("http://gateway-1") && parsed.pathname === "/invoke") { return { ok: true, status: 200, body: { accepted: true, operationId: "op_m3_status_do1", traceId: "trc_m3_status_do1", boxId: "boxsimu_1", resourceId: "res_boxsimu_1", port: "DO1", value: false, state: { port: "DO1", direction: "output", value: false, source: "gateway-simu", updatedAt: "2026-05-23T00:00:00.000Z" }, auditId: "aud_m3_status_do1", evidenceId: "evd_m3_status_do1" } }; } if (url.startsWith("http://gateway-2") && parsed.pathname === "/status") { return { ok: true, status: 200, body: m3GatewayStatus({ gatewayId: "gwsimu_2", gatewaySessionId: "gws_gwsimu_2", boxId: "boxsimu_2", resourceId: "res_boxsimu_2" }) }; } if (url.startsWith("http://gateway-2") && parsed.pathname === "/invoke") { const value = request.body?.operationId?.includes("do_write") || request.body?.operationId?.includes("do-write") ? true : false; return { ok: true, status: 200, body: { accepted: true, operationId: "op_m3_status_di1", traceId: "trc_m3_status_di1", boxId: "boxsimu_2", resourceId: "res_boxsimu_2", port: "DI1", value, state: { port: "DI1", direction: "input", value, source: "patch-panel", sourceResourceId: "res_boxsimu_1", sourcePort: "DO1", propagatedBy: "hwlab-patch-panel", updatedAt: "2026-05-23T00:00:00.000Z" }, auditId: "aud_m3_status_di1", evidenceId: "evd_m3_status_di1" } }; } if (url.startsWith("http://patch-panel") && parsed.pathname === "/status") { return { ok: true, status: 200, body: { serviceId: "hwlab-patch-panel", state: "active", activeConnections: [ { fromResourceId: "res_boxsimu_1", fromPort: "DO1", toResourceId: "res_boxsimu_2", toPort: "DI1" } ] } }; } if (url.startsWith("http://patch-panel") && parsed.pathname === "/wiring") { return { ok: true, status: 200, body: { wiringConfigId: "wir_m3_do1_di1", status: "active", connections: [ { from: { resourceId: "res_boxsimu_1", port: "DO1" }, to: { resourceId: "res_boxsimu_2", port: "DI1" }, mode: "exclusive" } ] } }; } if (url.startsWith("http://patch-panel") && parsed.pathname === "/sync/tick") { return { ok: true, status: 200, body: { accepted: true, propagatedBy: "hwlab-patch-panel", routeCount: 1, deliveryCount: 1, routes: [ { accepted: true, deliveryCount: 1, deliveries: [ { resourceId: "res_boxsimu_2", port: "DI1", value: body.signals?.[0]?.value ?? false, sourceResourceId: "res_boxsimu_1", sourcePort: "DO1", deliveryStatus: "applied" } ] } ] } }; } throw new Error(`unexpected M3 readiness request ${url}`); } export function m3GatewayStatus({ gatewayId, gatewaySessionId, boxId, resourceId }) { return { serviceId: "hwlab-gateway-simu", gatewayId, gatewaySessionId, session: { gatewayId, gatewaySessionId }, registry: { gatewayId, gatewaySessionId, boxes: [ { boxId, resourceId, state: "registered" } ] } }; } export function codexStdioReadyFixture({ workspace, codexHome }) { return { kind: "codex-app-server-stdio-runner", provider: "codex-stdio", backend: "hwlab-cloud-api/codex-app-server-stdio", status: "feasible", ready: true, startupReady: true, canStartLongLivedCodexStdio: true, command: path.join(process.cwd(), "node_modules", ".bin", "codex"), binaryOnPath: true, binary: { present: true, executable: true, nativeDependencyPresent: true, versionDetected: true }, workspace, workspaceState: { exists: true, readable: true, writable: true, writeRequired: true }, codexHome, codexHomeState: { exists: true, readable: true, writable: true, writeRequired: true }, sandbox: "workspace-write", enabled: true, supervisor: { configured: true, mode: "repo-owned-node-supervisor" }, tokenBoundary: { present: true, secretMaterialRead: false, valuesRedacted: true }, egress: { configured: true, directPublicOpenAi: false, valueRedacted: true }, protocol: { status: "wired", wired: true, requiredTools: ["codex", "codex-reply"], toolsObserved: ["codex", "codex-reply"], missingTools: [], command: "codex app-server --listen stdio://" }, commandProbe: { status: "ready", ready: true, probe: "workspace.pwd", traceId: "trc_codex_stdio_command_probe", toolCalls: [{ name: "pwd", status: "completed", cwd: workspace, command: "pwd", exitCode: 0, stdoutSummary: "workspace path matched", outputTruncated: false }], secretMaterialRead: false, valuesRedacted: true }, stdioProtocol: { status: "wired", wired: true, requiredTools: ["codex", "codex-reply"], toolsObserved: ["codex", "codex-reply"], missingTools: [], command: "codex app-server --listen stdio://" }, sessionLifecycle: { status: "present", present: true, create: true, reuse: true, cancel: true, reap: true, traceCapture: true, idleTimeoutMs: 1800000 }, lifecycleSupervisor: { status: "present", present: true, create: true, reuse: true, cancel: true, reap: true, traceCapture: true, idleTimeoutMs: 1800000 }, runtimeContract: { status: "ready", ready: true, binary: { status: "present", present: true, executable: true, nativeDependencyPresent: true, versionDetected: true }, stdioProtocol: { status: "wired", wired: true, requiredTools: ["codex", "codex-reply"], toolsObserved: ["codex", "codex-reply"], missingTools: [] }, commandProbe: { status: "ready", ready: true, probe: "workspace.pwd", traceId: "trc_codex_stdio_command_probe", toolCalls: [{ name: "pwd", status: "completed", cwd: workspace, command: "pwd", exitCode: 0, stdoutSummary: "workspace path matched", outputTruncated: false }], secretMaterialRead: false, valuesRedacted: true }, lifecycleSupervisor: { status: "present", present: true, create: true, reuse: true, cancel: true, reap: true, traceCapture: true, idleTimeoutMs: 1800000 }, workspaceMount: { path: workspace, status: "ready", mounted: true, readable: true, writable: true, sandbox: "workspace-write" }, codexHome: { path: codexHome, status: "ready", exists: true, readable: true, writable: true }, cancelReapTraceReadiness: { status: "ready", cancel: true, reap: true, traceCapture: true, idleTimeout: true } }, blockers: [], blockerCodes: [], safety: { secretMaterialRead: false, valuesRedacted: true } }; } export function codexStdioChatFixture({ workspace, codexHome, params }) { const traceId = params.traceId; const session = { sessionId: "ses_server_stdio_pwd", conversationId: params.conversationId, status: "idle", workspace, sandbox: "workspace-write", runnerKind: "codex-app-server-stdio-runner", sessionMode: "codex-app-server-stdio-long-lived", capabilityLevel: "long-lived-codex-stdio-session", implementationType: "repo-owned-codex-app-server-stdio-session", createdAt: "2026-05-23T00:00:00.000Z", updatedAt: "2026-05-23T00:00:00.000Z", idleTimeoutMs: 1800000, expiresAt: "2026-05-23T00:30:00.000Z", lastTraceId: traceId, turn: 1, threadId: "thread_server_stdio_pwd", reused: false, durable: true, longLivedSession: true, codexStdio: true, writeCapable: true, secretMaterialStored: false, valuesRedacted: true }; const feasibility = codexStdioReadyFixture({ workspace, codexHome }); return { provider: "codex-stdio", model: "gpt-test", backend: "hwlab-cloud-api/codex-app-server-stdio", content: `stdio pwd\n${workspace}`, workspace, sandbox: "workspace-write", session, sessionMode: "codex-app-server-stdio-long-lived", sessionReuse: { conversationId: params.conversationId, sessionId: session.sessionId, threadId: session.threadId, mapped: true, reused: false, turn: 1, previousTurns: 0, workspace, status: "idle", idleTimeoutMs: 1800000 }, implementationType: "repo-owned-codex-app-server-stdio-session", runnerLimitations: ["secret-values-redacted"], codexStdioFeasibility: feasibility, longLivedSessionGate: { status: "pass", pass: true, provider: "codex-stdio", runnerKind: "codex-app-server-stdio-runner", sessionMode: "codex-app-server-stdio-long-lived", implementationType: "repo-owned-codex-app-server-stdio-session", blockers: [] }, toolCalls: [{ id: "tool_server_stdio_pwd", type: "workspace-read", name: "pwd", status: "completed", cwd: workspace, command: "pwd", exitCode: 0, stdout: workspace, stderrSummary: "", outputTruncated: false, traceId }], skills: { status: "not_requested", items: [], count: 0, blockers: [] }, runner: { kind: "codex-app-server-stdio-runner", provider: "codex-stdio", backend: "hwlab-cloud-api/codex-app-server-stdio", workspace, sandbox: "workspace-write", session: "codex-app-server-stdio-long-lived", sessionMode: "codex-app-server-stdio-long-lived", sessionId: session.sessionId, implementationType: "repo-owned-codex-app-server-stdio-session", codexStdio: true, longLivedSession: true, durableSession: true, writeCapable: true, readOnly: false, capabilityLevel: "long-lived-codex-stdio-session" }, runnerTrace: { traceId, runnerKind: "codex-app-server-stdio-runner", workspace, sandbox: "workspace-write", sessionMode: "codex-app-server-stdio-long-lived", sessionId: session.sessionId, sessionStatus: "idle", turn: 1, implementationType: "repo-owned-codex-app-server-stdio-session", events: ["stdio:acquire", "session:created", "stdio:ready", "tool:pwd:completed"], outputTruncated: false, valuesPrinted: false }, capabilityLevel: "long-lived-codex-stdio-session", providerTrace: { transport: "stdio", protocol: "codex-app-server-jsonrpc-stdio", command: "codex app-server --listen stdio://", toolName: "codex", threadId: "thread_server_stdio_pwd", valuesPrinted: false } }; } export function delay(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } export async function postAgent(port, body) { const nextBody = { ...body }; let auth = testAuthByPort.get(port) ?? null; const manual = nextBody.sessionId ? null : await createManualAgentSession(port, { conversationId: nextBody.conversationId, projectId: nextBody.projectId, providerProfile: nextBody.providerProfile }); auth = auth ?? manual; if (manual) { nextBody.conversationId = manual.conversationId; nextBody.sessionId = manual.sessionId; } const response = await fetch(`http://127.0.0.1:${port}/v1/agent/chat`, { method: "POST", headers: { "content-type": "application/json", ...(auth?.cookie ? { cookie: auth.cookie } : {}), ...(nextBody.traceId ? { "x-trace-id": nextBody.traceId } : {}) }, body: JSON.stringify(nextBody) }); assert.equal(response.status, 200); return response.json(); } export async function createManualAgentSession(port, input = {}) { const auth = await ensureTestAgentAuth(port); const response = await fetch(`http://127.0.0.1:${port}/v1/agent/sessions`, { method: "POST", headers: { "content-type": "application/json", cookie: auth.cookie }, body: JSON.stringify({ conversationId: input.conversationId, sessionId: input.sessionId, projectId: input.projectId, providerProfile: input.providerProfile, updatedByClient: "server-agent-chat-test" }) }); const body = await response.json(); assert.equal(response.status, 201); assert.equal(body.ok, true); assert.equal(body.session.usable, true); return { cookie: auth.cookie, headers: { "content-type": "application/json", cookie: auth.cookie }, session: body.session, sessionId: body.session.sessionId, conversationId: body.session.conversationId }; } export async function ensureTestAgentAuth(port) { const cached = testAuthByPort.get(port); if (cached?.cookie) return cached; const setup = await fetch(`http://127.0.0.1:${port}/v1/setup/first-admin`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ username: TEST_AGENT_USERNAME, displayName: "Server Test Agent", password: TEST_AGENT_PASSWORD }) }); let cookie = sessionCookieFromResponse(setup); if (!cookie) { const login = await fetch(`http://127.0.0.1:${port}/auth/login`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ username: TEST_AGENT_USERNAME, password: TEST_AGENT_PASSWORD }) }); cookie = sessionCookieFromResponse(login); assert.equal(login.status, 200); } else { assert.equal(setup.status, 201); } assert.ok(cookie); const auth = { cookie }; testAuthByPort.set(port, auth); return auth; } function sessionCookieFromResponse(response) { const value = response.headers.get("set-cookie") ?? ""; return value.split(";")[0] || ""; } export async function pollAgentResult(port, traceId) { let last = null; for (let attempt = 0; attempt < 20; attempt += 1) { const response = await fetch(`http://127.0.0.1:${port}/v1/agent/chat/result/${encodeURIComponent(traceId)}`); last = { status: response.status, body: await response.json() }; if (response.status === 200) return last.body; await delay(10); } throw new Error(`Code Agent result did not complete: ${JSON.stringify(last)}`); } export async function createFakeCodexCommand() { const root = await mkdtemp(path.join(os.tmpdir(), "hwlab-fake-codex-")); const packageRoot = path.join(root, "node_modules", "@openai", "codex"); const command = path.join(packageRoot, "bin", "codex.js"); const native = path.join(root, "node_modules", "@openai", "codex-linux-x64", "vendor", "x86_64-unknown-linux-musl", "codex", "codex"); await mkdir(path.dirname(command), { recursive: true }); await mkdir(path.dirname(native), { recursive: true }); await writeFile(path.join(packageRoot, "package.json"), JSON.stringify({ name: "@openai/codex", version: "0.128.0" }), "utf8"); await writeFile(command, "#!/usr/bin/env node\nconsole.log('codex 0.128.0');\n", "utf8"); await writeFile(native, "#!/bin/sh\nexit 0\n", "utf8"); await chmod(command, 0o755); await chmod(native, 0o755); return { root, command }; } export async function prepareFakeCodexHome(codexHome) { await mkdir(codexHome, { recursive: true }); await writeFile(path.join(codexHome, "config.toml"), "model = \"gpt-test\"\n", "utf8"); await writeFile(path.join(codexHome, "auth.json"), "{\"auth\":\"redacted-test-placeholder\"}\n", "utf8"); return codexHome; } export function createFakeAppServerClient({ text = "真实 Codex stdio 回复", delayMs = 0 } = {}) { let notificationHandler = null; return { async initialize() { return { initialized: true }; }, setNotificationHandler(handler) { notificationHandler = typeof handler === "function" ? handler : null; }, async startThread() { notificationHandler?.({ method: "thread/started", params: { thread: { id: "thread_server_test_stdio" } } }); return { threadId: "thread_server_test_stdio" }; }, async resumeThread(args) { notificationHandler?.({ method: "thread/started", params: { thread: { id: args.threadId } } }); return { threadId: args.threadId }; }, async startTurn() { const turnId = "turn_server_test_stdio"; notificationHandler?.({ method: "turn/started", params: { turn: { id: turnId } } }); if (delayMs > 0) await delay(delayMs); notificationHandler?.({ method: "item/agentMessage/delta", params: { itemId: "item_server_test_stdio", delta: text } }); notificationHandler?.({ method: "item/completed", params: { item: { id: "item_server_test_stdio", type: "agentMessage", text } } }); notificationHandler?.({ method: "turn/completed", params: { turn: { id: turnId, status: "completed" } } }); return { turnId }; }, close() {} }; } export async function postAgentRaw(port, body, headers = {}) { const response = await fetch(`http://127.0.0.1:${port}/v1/agent/chat`, { method: "POST", headers: { "content-type": "application/json", ...headers }, body }); return { status: response.status, body: await response.json() }; } export function createGreenM3StatusRuntimeStore({ blocker = null } = {}) { return { async readiness() { return { adapter: "postgres", durable: true, durableRequested: true, durableCapable: true, ready: true, status: "ready", blocker, reason: "Postgres durable runtime adapter completed live schema, migration, and read readiness queries", liveRuntimeEvidence: true, fixtureEvidence: false }; }, async queryAuditEvents() { return { events: [ { auditId: "aud_m3_di_read_d5afd84b-3a9d-475f-894f-dff8ea5f49ff_succeeded", traceId: "trc_hotfix_307_verify_1779527747043_read_false", actorType: "user", actorId: "usr_m3_operator", action: "m3.io.di.read", targetType: "hardware_operation", targetId: "op_m3_di_read_75fc664f-e94f-41e8-816e-aff9fdb3666f", projectId: "prj_mvp_topology", gatewaySessionId: "gws_gwsimu_2", operationId: "op_m3_di_read_75fc664f-e94f-41e8-816e-aff9fdb3666f", serviceId: "hwlab-cloud-api", outcome: "succeeded", metadata: { route: "res_boxsimu_1:DO1->hwlab-patch-panel->res_boxsimu_2:DI1" }, environment: "dev", occurredAt: "2026-05-23T00:00:00.000Z" } ], count: 1 }; }, async queryEvidenceRecords() { return { records: [ { evidenceId: "evd_m3_di_read_75fc664f-e94f-41e8-816e-aff9fdb3666f_succeeded", projectId: "prj_mvp_topology", operationId: "op_m3_di_read_75fc664f-e94f-41e8-816e-aff9fdb3666f", kind: "trace", uri: "memory://hwlab-cloud-api/op_m3_di_read_75fc664f-e94f-41e8-816e-aff9fdb3666f/m3-io-control.json", sha256: "0".repeat(64), serviceId: "hwlab-cloud-api", environment: "dev", metadata: { traceId: "trc_hotfix_307_verify_1779527747043_read_false", route: "res_boxsimu_1:DO1->hwlab-patch-panel->res_boxsimu_2:DI1" }, createdAt: "2026-05-23T00:00:00.000Z" } ], count: 1 }; } }; }