Files
pikasTech-HWLAB/web/hwlab-cloud-web/scripts/workbench-e2e-server.ts
T

2709 lines
157 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// SPEC: PJ2026-010401 Web工作台 draft-2026-06-18-r1; PJ2026-0104010803 唯一投影 draft-2026-06-19-p2-terminal-sealed-final-response; PJ2026-010403 API契约 draft-2026-06-18-r1.
// Responsibility: Same-origin fake Workbench API and static server for Playwright browser regression tests.
import { createReadStream, existsSync, readFileSync, statSync } from "node:fs";
import { readFile } from "node:fs/promises";
import { createServer, type IncomingMessage, type ServerResponse } from "node:http";
import { extname, join, resolve, sep } from "node:path";
import {
DEFAULT_WORKBENCH_EMPTY_SESSION_TTL_MS,
classifyWorkbenchEmptySessionGcCandidate
} from "../../../internal/cloud/workbench-empty-session-gc.ts";
type JsonRecord = Record<string, unknown>;
interface SessionRecord extends JsonRecord {
sessionId: string;
threadId?: string | null;
status?: string | null;
lastTraceId?: string | null;
messages?: JsonRecord[];
hidden?: boolean;
}
interface ScenarioState {
scenarioId: string;
providerProfile: string;
selectedSessionId: string;
sessions: SessionRecord[];
traces: Record<string, JsonRecord>;
requestLedger: JsonRecord[];
legacyRequestLedger: JsonRecord[];
chatRequests: JsonRecord[];
projectLinks: JsonRecord[];
projectFiles: JsonRecord[];
projectTasks: JsonRecord[];
projectRevision: number;
listOmitSelected: boolean;
sessionDelayMs: number;
sessionDetailDelayMs: number;
chatDelayMs: number;
terminalScript: boolean;
terminalFailureScript: boolean;
staleTraceId: string | null;
liveBackfillTraceId: string | null;
liveBackfillReadyAtMs: number | null;
}
interface FakePerformanceWindow {
id: string;
label: string;
seconds: number | null;
windowFrom: string | null;
windowTo: string;
generatedAt: string;
}
const cwd = process.cwd();
const args = new Map<string, string>();
for (let index = 2; index < process.argv.length; index += 1) {
const key = process.argv[index];
const value = process.argv[index + 1];
if (key?.startsWith("--")) {
args.set(key.slice(2), value && !value.startsWith("--") ? value : "true");
if (value && !value.startsWith("--")) index += 1;
}
}
const port = Number(args.get("port") ?? process.env.HWLAB_WORKBENCH_E2E_PORT ?? 4173);
const distDir = resolve(cwd, args.get("dist") ?? "dist");
const capturePath = resolve(cwd, "tests/workbench-e2e/fixtures/real-captures/d601-v03-redacted.json");
const capture = JSON.parse(await readFile(capturePath, "utf8")) as { scenario: { selectedSessionId: string; providerProfile: string; sessions: SessionRecord[]; traces: Record<string, JsonRecord> } };
const progressOnlyText = "PROGRESS_ONLY_SHOULD_NOT_RENDER_AS_FINAL";
const finalOnlyText = "FINAL_ONLY_SHOULD_RENDER";
const markdownFinalText = [
"已新增并实际运行:",
"",
"- Go`go test ./...` 保留两个空格",
"- Rust`cargo test --release`",
"",
"```sh",
"go test ./...",
"cargo test --release",
"```",
"",
"| benchmark | Go | Rust |",
"|---|---:|---:|",
"| fib | 1.2ms | 1.0ms |",
"",
"| runtime | status |",
"|---|---|",
"| local | pass |"
].join("\n");
const terminalAssistantFinalText = [
"全部六份数据到手!下面是完整的六语言终极性能对比:",
"",
"| language | runtime | status |",
"|---|---|---|",
"| Lua | LuaJIT | pass |",
"| Python | CPython | pass |",
"| Rust | native | pass |"
].join("\n");
const canonicalTraceFinalText = "messageProjection 的 sealed final response 才是主消息正文。";
const traceDetailConflictText = "TRACE_DETAIL_CONFLICT_SHOULD_NOT_REPLACE_MESSAGE";
const runtimeConfigScript = `<script>\nwindow.HWLAB_CLOUD_WEB_CONFIG = {\n ...(window.HWLAB_CLOUD_WEB_CONFIG ?? {}),\n displayTime: window.HWLAB_CLOUD_WEB_CONFIG?.displayTime ?? { timeZone: "Asia/Shanghai", locale: "zh-CN", label: "北京时间" },\n workbench: {\n ...(window.HWLAB_CLOUD_WEB_CONFIG?.workbench ?? {}),\n realtimeFeatures: window.HWLAB_CLOUD_WEB_CONFIG?.workbench?.realtimeFeatures ?? { liveKafkaSse: false, kafkaRefreshReplay: false, projectionRealtime: true },\n debugCapabilities: window.HWLAB_CLOUD_WEB_CONFIG?.workbench?.debugCapabilities ?? { isolatedKafka: false, rawHwlabEventWindow: { enabled: false, maxEntries: 1, maxRetainedBytes: 1 } },\n traceTimeline: window.HWLAB_CLOUD_WEB_CONFIG?.workbench?.traceTimeline ?? { autoExpandRunning: false, autoCollapseTerminal: false }\n }\n};\n</script>`;
let state = createScenarioState("baseline");
const sseClients = new Set<ServerResponse>();
const debugSseClients = new Set<ServerResponse>();
let debugFakeSseQueue = createDebugFakeSseQueue();
const server = createServer((request, response) => {
void handleRequest(request, response).catch((error) => {
if (response.headersSent) {
console.error("workbench-e2e-server stream error", error);
response.destroy();
return;
}
json(response, 500, { ok: false, status: 500, error: { code: "e2e_server_error", message: error instanceof Error ? error.message : String(error) } });
});
});
server.listen(port, "127.0.0.1", () => {
console.log(`workbench-e2e-server listening on http://127.0.0.1:${port}`);
});
async function handleRequest(request: IncomingMessage, response: ServerResponse): Promise<void> {
const method = request.method ?? "GET";
const url = new URL(request.url ?? "/", `http://${request.headers.host ?? `127.0.0.1:${port}`}`);
const path = url.pathname;
recordLedger(method, url);
refreshBackgroundProjection();
if (path === "/__e2e/health") return json(response, 200, { ok: true, scenarioId: state.scenarioId });
if (path === "/__e2e/state") return json(response, 200, stateSummary());
if (path === "/__e2e/reset" && method === "POST") {
const body = await readJson(request);
state = createScenarioState(String(body.scenarioId ?? "baseline"));
return json(response, 200, stateSummary());
}
if (path === "/__e2e/scroll-follow/append" && method === "POST") {
const body = await readJson(request);
return json(response, 200, appendScrollFollowEvents(positiveInteger(body.count, 1)));
}
if (path === "/__e2e/gc-empty-sessions" && method === "POST") {
const body = await readJson(request);
return json(response, 200, gcEmptySessions(body));
}
if (path === "/auth/session" || path === "/auth/bootstrap") {
const payload = authPayload();
return json(response, payload.authenticated === true ? 200 : 401, payload);
}
if (path === "/auth/login" && method === "POST") return authLoginResponse(response);
if (path === "/v1/workbench/events" && method === "GET") return sse(request, response, url);
if (path === "/v1/workbench/debug/fake-sse" || path.startsWith("/v1/workbench/debug/fake-sse/")) return debugFakeSse(request, response, url, method);
if (path === "/v1/workbench/launches" && method === "POST") return json(response, 201, await createWorkbenchLaunch(request));
if (path === "/v1/workbench/sessions" && method === "GET") {
await delay(state.sessionDelayMs);
return json(response, 200, workbenchSessionListPayload(url));
}
const turnMatch = path.match(/^\/v1\/workbench\/turns\/([^/]+)$/u);
if (turnMatch && method === "GET") {
const traceId = decodeURIComponent(turnMatch[1] ?? "");
if (state.scenarioId === "completed-replay-detail-404" && traceId === "trc_completed") return json(response, 404, { ok: false, status: 404, error: { code: "turn_replay_unavailable" } });
if (traceId === state.staleTraceId) return json(response, 502, { ok: false, status: 502, error: { code: "upstream_unavailable", message: "stale trace is unavailable" } });
return json(response, 200, workbenchTurnPayload(traceId));
}
const traceMatch = path.match(/^\/v1\/workbench\/traces\/([^/]+)\/events$/u);
if (traceMatch && method === "GET") {
const traceId = decodeURIComponent(traceMatch[1] ?? "");
if (state.scenarioId === "completed-replay-detail-404" && traceId === "trc_completed") return json(response, 404, { ok: false, status: 404, error: { code: "trace_replay_unavailable" } });
if (state.scenarioId === "trace-detail-read-timeout-diagnostic" && traceId === "trc_trace_detail_read_timeout") return errorDiagnosticResponse(response, 504, `/v1/workbench/traces/${traceId}/events`, "trace_detail_read_timeout", "Trace 更新超时,运行记录暂不可见。", { traceId: "33333333333333333333333333333333", requestId: "req_e2e_trace_detail_read_timeout", layer: "workbench-read-model", category: "trace-detail-read" });
if (state.scenarioId === "sealed-final-response-diagnostics" && traceId === "trc_sealed_final_diag") return errorDiagnosticResponse(response, 504, `/v1/workbench/traces/${traceId}/events`, "trace_detail_read_timeout", "Trace 更新超时,运行记录暂不可见。", { traceId: "55555555555555555555555555555555", requestId: "req_e2e_sealed_final_trace_timeout", layer: "workbench-read-model", category: "trace-detail-read" });
if (traceId === state.staleTraceId) return json(response, 502, { ok: false, status: 502, error: { code: "upstream_unavailable", message: "stale trace is unavailable" } });
return json(response, 200, workbenchTracePayload(traceId, url));
}
const sessionMessagesMatch = path.match(/^\/v1\/workbench\/sessions\/([^/]+)\/messages$/u);
if (sessionMessagesMatch && method === "GET") {
const sessionId = canonicalSessionId(decodeURIComponent(sessionMessagesMatch[1] ?? ""));
await delay(sessionDetailDelayMs(sessionId));
if (state.scenarioId === "created-session-read-failure" && sessionId === "ses_created_read_failure") return json(response, 503, { ok: false, status: 503, error: { code: "session_messages_unavailable" } });
const session = visibleSessionById(sessionId);
return session ? json(response, 200, workbenchSessionMessagesPayload(session, url)) : json(response, 404, { ok: false, status: 404, error: { code: "session_not_found" } });
}
const workbenchSessionMatch = path.match(/^\/v1\/workbench\/sessions\/([^/]+)$/u);
if (workbenchSessionMatch && method === "GET") {
const sessionId = canonicalSessionId(decodeURIComponent(workbenchSessionMatch[1] ?? ""));
await delay(sessionDetailDelayMs(sessionId));
if (state.scenarioId === "created-session-read-failure" && sessionId === "ses_created_read_failure") return json(response, 503, { ok: false, status: 503, error: { code: "session_detail_unavailable" } });
if (state.scenarioId === "session-switch-detail-404-isolated" && sessionId === "ses_stale_404") return json(response, 404, { ok: false, status: 404, error: { code: "session_not_found" } });
if (state.scenarioId === "completed-replay-detail-404" && sessionId === "ses_completed") return json(response, 404, { ok: false, status: 404, error: { code: "session_replay_unavailable" } });
const session = visibleSessionById(sessionId, { includeArchived: true });
return session ? json(response, 200, { ok: true, status: "found", session }) : json(response, 404, { ok: false, status: 404, error: { code: "session_not_found" } });
}
if (path === "/v1/agent/chat" && method === "POST") {
const body = await readJson(request);
state.chatRequests.push(redactRequestBody(body));
await delay(state.chatDelayMs);
if (state.scenarioId === "admission-unavailable") {
return json(response, 503, {
ok: false,
accepted: false,
status: "failed",
traceId: body.traceId,
error: { code: "admission_unavailable", layer: "admission", retryable: true, message: "admission_unavailable: durable turn was not persisted" },
blocker: { code: "admission_unavailable", layer: "admission", retryable: true, summary: "durable turn was not persisted" },
valuesRedacted: true
});
}
return json(response, 200, acceptChatTurn(body));
}
if (path === "/v1/agent/sessions" && method === "POST") {
const body = await readJson(request);
const session = createManualSession(body);
state.selectedSessionId = session.sessionId;
state.sessions.unshift(session);
return json(response, state.scenarioId === "create-while-route-loading" ? 201 : 200, { ok: true, status: "ok", session });
}
const agentSessionMatch = path.match(/^\/v1\/agent\/sessions\/([^/]+)$/u);
if (agentSessionMatch && method === "DELETE") {
const session = sessionById(decodeURIComponent(agentSessionMatch[1] ?? ""));
if (!session) return json(response, 404, { ok: false, status: 404, error: { code: "session_not_found" } });
session.status = "archived";
session.updatedAt = new Date().toISOString();
return json(response, 200, { ok: true, status: "archived", session, archivedCount: 1 });
}
if (agentSessionMatch && method === "GET") return json(response, 200, { session: sessionPayload(decodeURIComponent(agentSessionMatch[1] ?? "")) });
if (path === "/v1/provider-profiles") {
const items = [
{ profile: "codex-api", backendProfile: "codex-api", backendKind: "responses", configured: true, failureKind: null, valuesPrinted: false },
{ profile: "deepseek", backendProfile: "deepseek", backendKind: "responses", configured: true, failureKind: null, valuesPrinted: false }
];
return json(response, 200, {
ok: true,
contractVersion: "provider-profile-management-v1",
count: items.length,
items,
data: { items, count: items.length, valuesPrinted: false },
valuesPrinted: false
});
}
if (path === "/v1/dashboard/summary") return json(response, 200, dashboardSummaryPayload());
if (path === "/health/live" || path === "/health" || path === "/v1") return json(response, 200, { status: "ok", serviceId: "workbench-e2e", codeAgent: { ready: true, status: "ready" } });
if (path === "/v1/live-builds") return json(response, 200, { status: "ok", builds: [] });
if (path === "/v1/hwpod/specs") return json(response, 200, hwpodSpecsPayload());
if (path === "/v1/hwpod-node-ops") return json(response, 200, hwpodNodeOpsPayload());
if (path.startsWith("/v1/project-management")) return projectManagementPayload(request, response, url, method);
if (path === "/v1/web-performance" && method === "POST") {
const body = await readJson(request);
return json(response, 202, { accepted: true, recorded: Array.isArray(body.events) ? body.events.length : 0, valuesRedacted: true });
}
if (path === "/v1/web-performance/summary") {
if (state.scenarioId === "performance-summary-error") return errorDiagnosticResponse(response, 502, "/v1/web-performance/summary", "upstream_unavailable", "暂时无法连接上游。");
const matrixStatus = performanceSummaryErrorStatus(state.scenarioId);
if (matrixStatus !== null) return errorDiagnosticResponse(response, matrixStatus, "/v1/web-performance/summary", `e2e_http_${matrixStatus}`, `模拟 ${matrixStatus} 错误。`, { traceId: statusMatrixTraceId(matrixStatus), requestId: `req_e2e_api_status_${matrixStatus}`, category: matrixStatus >= 500 ? "server" : "client" });
if (state.scenarioId === "performance-network-error") {
response.destroy(new Error("e2e performance network reset"));
return;
}
if (state.scenarioId === "performance-empty") return json(response, 200, webPerformanceEmptyPayload(url));
if (state.scenarioId === "performance-stale-window") return json(response, 200, webPerformanceStaleWindowPayload(url));
return json(response, 200, webPerformanceSummaryPayload(url));
}
if (path.startsWith("/v1/") || path.startsWith("/auth/") || path.startsWith("/health")) return json(response, 500, { ok: false, status: 500, error: { code: "unmocked_request", path } });
return staticFile(response, path);
}
function dashboardSummaryPayload(): JsonRecord {
const observedAt = "2026-07-13T03:30:00.000Z";
return {
ok: true,
status: "partial",
contractVersion: "cloud-dashboard-summary-v1",
route: "/v1/dashboard/summary",
observedAt,
actor: { id: "usr_e2e_admin", displayName: "E2E Admin", role: "admin" },
sources: [
{ id: "work", label: "项目与任务", authority: "hwlab-project-management", state: "ready", observedAt, reason: null, href: "/projects" },
{ id: "hwpod", label: "HWPOD", authority: "cloud-api-hwpod-domain", state: "partial", observedAt, reason: "1 个节点离线", href: "/hwpods/devices" },
{ id: "billing", label: "额度与 Plan", authority: "hwlab-user-billing", state: "ready", observedAt, reason: null, href: "/usage" }
],
work: { state: "ready", authority: "hwlab-project-management", observedAt, projectCount: 1, projects: [{ projectId: "project_hwlab_v03", title: "HWLAB MDTODO", status: "active", href: "/projects/project_hwlab_v03" }], taskCounts: { open: 2, inProgress: 1, blocked: 1 }, continuations: [{ taskRef: "mdtodo:hwlab-v03-mdtodo:file_plan:R1.1", taskId: "R1.1", title: "展示 MDTODO 任务详情", status: "open", projectId: "project_hwlab_v03", sourceId: "hwlab-v03-mdtodo", fileRef: "file_plan", updatedAt: observedAt, href: "/projects/mdtodo/sources/hwlab-v03-mdtodo/files/file_plan/tasks/R1.1" }] },
hwpod: { state: "partial", authority: "cloud-api-hwpod-domain", observedAt, nodeCount: 2, onlineNodeCount: 1, offlineNodeCount: 1, deviceCount: 2, availableDeviceCount: 1, busyDeviceCount: 0, capabilityMismatchCount: 0, invalidSpecCount: 0 },
billing: { state: "ready", authority: "hwlab-user-billing", observedAt, plan: { id: "default", displayName: "Default", status: "active" }, credits: { balance: 100, reserved: 5, available: 95 }, entitlementCount: 2, activeReservationCount: 1 },
issues: [{ id: "hwpod-offline-nodes", domain: "hwpod", severity: "error", code: "hwpod_node_offline", title: "HWPOD Node 离线", summary: "1 个已声明 Node 当前未连接。", count: 1, action: { label: "查看 Node", href: "/hwpods/nodes?status=offline" } }],
valuesRedacted: true
};
}
function hwpodSpecsPayload(): JsonRecord {
return {
ok: true,
status: "completed",
count: 1,
availableCount: 0,
nodeOpsContractVersion: "hwpod-node-ops-v1",
specs: [
{
name: "d601-f103-v2",
hwpodId: "d601-f103-v2",
nodeId: "node-d601-f103-v2",
workspacePath: "F:\\Work\\D601-HWLAB",
source: { caseId: "d601-f103-v2-compile" },
availability: {
ok: false,
status: "blocked",
checkedAt: "2026-06-18T04:30:00.000Z",
results: [
{ opId: "op_01_workspace_ls", op: "workspace.ls", ok: false, status: "blocked", blocker: { code: "hwpod_node_unavailable", layer: "hwpod-node", retryable: true, summary: "no outbound WebSocket hwpod-node is connected" } }
]
}
}
]
};
}
function hwpodNodeOpsPayload(): JsonRecord {
return {
ok: true,
status: "ready",
contractVersion: "hwpod-node-ops-v1",
route: "/v1/hwpod-node-ops",
supportedOps: ["node.health", "workspace.ls", "debug.build", "debug.flash"],
websocket: { connectedCount: 0, pendingCount: 1, nodes: [] },
events: [
{ ts: "2026-06-18T04:30:00.000Z", status: "blocked", blocker: { code: "hwpod_node_unavailable", summary: "no outbound WebSocket hwpod-node is connected" } }
]
};
}
async function projectManagementPayload(request: IncomingMessage, response: ServerResponse, url: URL, method: string): Promise<void> {
const path = url.pathname;
const source = projectManagementSource();
const files = state.projectFiles;
const links = state.projectLinks;
const tasks = projectManagementTasks(links);
if (path === "/v1/project-management/mdtodo/sources" && method === "POST") {
const body = await readJson(request);
return json(response, 201, projectManagementEnvelope({ source: projectManagementSourceFromBody(body, source) }));
}
const sourceMutationMatch = path.match(/^\/v1\/project-management\/mdtodo\/sources\/([^/]+)$/u);
if (sourceMutationMatch && method === "PATCH") {
const body = await readJson(request);
const sourceId = decodeURIComponent(sourceMutationMatch[1] ?? String(source.sourceId));
return json(response, 200, projectManagementEnvelope({ source: projectManagementSourceFromBody(body, { ...source, sourceId }) }));
}
const sourceProbeMatch = path.match(/^\/v1\/project-management\/mdtodo\/sources\/([^/]+)\/probe$/u);
if (sourceProbeMatch && method === "POST") {
const sourceId = decodeURIComponent(sourceProbeMatch[1] ?? String(source.sourceId));
return json(response, 200, projectManagementEnvelope({ probe: { ok: true, status: "ok", sourceId, sourceKind: "hwpod-workspace", entries: files.length, valuesRedacted: true } }));
}
const sourceReindexMatch = path.match(/^\/v1\/project-management\/mdtodo\/sources\/([^/]+)\/reindex$/u);
if (sourceReindexMatch && method === "POST") {
const sourceId = decodeURIComponent(sourceReindexMatch[1] ?? String(source.sourceId));
return json(response, 200, projectManagementEnvelope({ projection: { sourceId, sourceKind: "hwpod-workspace", rootRef: "docs/MDTODO/", documentCount: files.length, taskCount: tasks.length, projectedAt: "2026-06-25T09:05:00.000Z", valuesRedacted: true } }));
}
if (path === "/v1/project-management/workbench-links" && method === "POST") {
const body = await readJson(request);
const link = projectManagementLinkFromBody(body);
state.projectLinks.unshift(link);
return json(response, 201, projectManagementEnvelope({ link }));
}
const taskMutationMatch = path.match(/^\/v1\/project-management\/mdtodo\/tasks\/(.+)$/u);
if (path === "/v1/project-management/mdtodo/tasks" && method === "POST") return projectManagementCreateTask(response, await readJson(request));
if (taskMutationMatch && method === "PATCH") return projectManagementUpdateTask(response, decodeURIComponent(taskMutationMatch[1] ?? ""), await readJson(request));
if (taskMutationMatch && method === "DELETE") return projectManagementDeleteTask(response, decodeURIComponent(taskMutationMatch[1] ?? ""), await readJson(request));
if (method !== "GET" && method !== "HEAD") return json(response, 405, { ok: false, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", error: { code: "method_not_allowed" }, valuesRedacted: true });
if (path === "/v1/project-management" || path === "/v1/project-management/navigation") {
return json(response, 200, projectManagementEnvelope({
navigation: {
id: "project-management",
label: "Project Management",
actor: { id: "usr_e2e_admin", role: "admin", authMethod: "web-session" },
items: [
{ id: "projects", label: "Projects", apiRoute: "/v1/project-management/projects" },
{ id: "mdtodo", label: "MDTODO", apiRoute: "/v1/project-management/mdtodo/tasks" }
],
capabilities: { mdtodoProjection: true, workbenchLaunch: true, workbenchLinks: true, sourceOfTruth: "markdown-files" }
},
projection: { sourceId: source.sourceId, documentCount: files.length, taskCount: tasks.length, projectedAt: "2026-06-25T09:00:00.000Z" }
}));
}
if (path === "/v1/project-management/projects") return json(response, 200, projectManagementEnvelope({ projects: [{ projectId: "project_hwlab_v03", name: "HWLAB MDTODO", sourceIds: [source.sourceId], sourceOfTruth: "markdown-files", status: "active" }] }));
if (path === "/v1/project-management/mdtodo/sources") return json(response, 200, projectManagementEnvelope({ sources: [source] }));
if (path === "/v1/project-management/mdtodo/files") return json(response, 200, projectManagementEnvelope({ files: files.filter((file) => !url.searchParams.get("sourceId") || file.sourceId === url.searchParams.get("sourceId")) }));
if (path === "/v1/project-management/mdtodo/launch-context") return projectManagementLaunchContext(response, url);
if (path === "/v1/project-management/mdtodo/task-detail") return projectManagementTaskDetail(response, url);
if (path === "/v1/project-management/mdtodo/report-preview") return projectManagementReportPreview(response, url);
if (path === "/v1/project-management/mdtodo/tasks") {
const search = String(url.searchParams.get("search") ?? "").toLowerCase();
const filtered = tasks.filter((task) => (!url.searchParams.get("taskRef") || task.taskRef === url.searchParams.get("taskRef"))
&& (!url.searchParams.get("sourceId") || task.sourceId === url.searchParams.get("sourceId"))
&& (!url.searchParams.get("fileRef") || task.fileRef === url.searchParams.get("fileRef"))
&& (!url.searchParams.get("projectId") || task.projectId === url.searchParams.get("projectId"))
&& (!url.searchParams.get("status") || task.status === url.searchParams.get("status"))
&& (!search || [task.taskId, task.title, task.taskRef].some((value) => String(value ?? "").toLowerCase().includes(search))));
const offset = positiveInteger(url.searchParams.get("offset"), 0);
const limit = positiveInteger(url.searchParams.get("limit"), 200);
const pageTasks = filtered.slice(offset, offset + limit);
return json(response, 200, projectManagementEnvelope({ tasks: pageTasks, page: { offset, limit, maxLimit: 500, total: filtered.length, hasMore: offset + pageTasks.length < filtered.length } }));
}
if (path === "/v1/project-management/workbench-links") return json(response, 200, projectManagementEnvelope({ links: links.filter((link) => !url.searchParams.get("taskRef") || link.taskRef === url.searchParams.get("taskRef")) }));
return json(response, 404, { ok: false, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", error: { code: "not_found" }, valuesRedacted: true });
}
function projectManagementEnvelope(payload: JsonRecord): JsonRecord {
return { ok: true, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", ...payload, valuesRedacted: true };
}
function projectManagementSource(): JsonRecord {
return { sourceId: "hwlab-v03-mdtodo", kind: "mdtodo-file-tree", sourceKind: "hwpod-workspace", displayName: "HWLAB v0.3 MDTODO", projectId: "project_hwlab_v03", status: "active", hwpodId: "constart-71freq-c", nodeId: "D518", workspaceRootRef: "F:\\Work\\ConStart", mdtodoRootRef: "docs/MDTODO/", maxFiles: 120, valuesRedacted: true };
}
function projectManagementSourceFromBody(body: JsonRecord, base: JsonRecord): JsonRecord {
return {
...base,
sourceId: String(body.sourceId ?? base.sourceId ?? "hwlab-v03-mdtodo"),
sourceKind: String(body.sourceKind ?? "hwpod-workspace"),
displayName: String(body.displayName ?? base.displayName ?? "HWLAB v0.3 MDTODO"),
projectId: String(body.projectId ?? base.projectId ?? "project_hwlab_v03"),
hwpodId: String(body.hwpodId ?? base.hwpodId ?? ""),
nodeId: String(body.nodeId ?? base.nodeId ?? ""),
workspaceRootRef: String(body.workspaceRootRef ?? base.workspaceRootRef ?? ""),
mdtodoRootRef: String(body.mdtodoRootRef ?? base.mdtodoRootRef ?? "docs/MDTODO/"),
maxFiles: positiveInteger(body.maxFiles, Number(base.maxFiles ?? 120)),
status: "active",
valuesRedacted: true
};
}
function projectManagementFiles(): JsonRecord[] {
return [
{ sourceId: "hwlab-v03-mdtodo", fileRef: "file_plan", projectId: "project_hwlab_v03", relativePath: "docs/MDTODO/hwlab-v03-mdtodo-web-sample.md", title: "项目管理任务", taskCount: 3, parseError: null, revision: 3, fingerprint: "sha256:e2e-plan", updatedAt: "2026-06-25T09:00:00.000Z" },
{ sourceId: "hwlab-v03-mdtodo", fileRef: "file_rollout", projectId: "project_hwlab_v03", relativePath: "docs/MDTODO/D601-v03-rollout.md", title: "D601 发布任务", taskCount: 1, parseError: null, revision: 1, fingerprint: "sha256:e2e-rollout", updatedAt: "2026-06-25T09:00:00.000Z" },
{ sourceId: "hwlab-v03-mdtodo", fileRef: "file_feedback", projectId: "project_hwlab_v03", relativePath: "docs/MDTODO/20260609_频率判断_用户反馈.md", title: "这是用户的反馈,你分析原因:", taskCount: 1, parseError: null, revision: 1, fingerprint: "sha256:e2e-feedback", updatedAt: "2026-06-26T13:00:00.000Z" }
];
}
function projectManagementTasks(links: JsonRecord[] = []): JsonRecord[] {
const linkCount = (taskRef: string) => links.filter((link) => link.taskRef === taskRef).length;
return state.projectTasks.map((task) => ({ ...task, linkCount: linkCount(String(task.taskRef ?? "")) }));
}
function projectManagementSeedTasks(links: JsonRecord[] = []): JsonRecord[] {
const linkCount = (taskRef: string) => links.filter((link) => link.taskRef === taskRef).length;
const r1 = "mdtodo:hwlab-v03-mdtodo:file_plan:R1";
const r11 = "mdtodo:hwlab-v03-mdtodo:file_plan:R1.1";
const r111 = "mdtodo:hwlab-v03-mdtodo:file_plan:R1.1.1";
const r2 = "mdtodo:hwlab-v03-mdtodo:file_rollout:R2";
const feedbackR1 = "mdtodo:hwlab-v03-mdtodo:file_feedback:R1";
return [
{ taskRef: r1, projectId: "project_hwlab_v03", sourceId: "hwlab-v03-mdtodo", fileRef: "file_plan", taskId: "R1", title: "实现项目根导航", status: "done", parentTaskRef: null, depth: 0, lineNumber: 4, ordinal: 1, linkCount: linkCount(r1), sourceFingerprint: "sha256:e2e-plan", bodyPreview: "Root notes", body: "Root notes\n\n参考报告 [R1.1](./20260110_LOG/R1.1_log_implementation.md)", updatedAt: "2026-06-25T09:00:00.000Z" },
{ taskRef: r11, projectId: "project_hwlab_v03", sourceId: "hwlab-v03-mdtodo", fileRef: "file_plan", taskId: "R1.1", title: "展示 MDTODO 任务详情", status: "open", parentTaskRef: r1, depth: 1, lineNumber: 8, ordinal: 2, linkCount: linkCount(r11), sourceFingerprint: "sha256:e2e-plan", bodyPreview: "Detail body", body: "Detail body", updatedAt: "2026-06-25T09:00:00.000Z" },
{ taskRef: r111, projectId: "project_hwlab_v03", sourceId: "hwlab-v03-mdtodo", fileRef: "file_plan", taskId: "R1.1.1", title: "Source 顶部控制", status: "in_progress", parentTaskRef: r11, depth: 2, lineNumber: 12, ordinal: 3, linkCount: linkCount(r111), sourceFingerprint: "sha256:e2e-plan", bodyPreview: "Toolbar body", body: "Toolbar body", updatedAt: "2026-06-25T09:00:00.000Z" },
{ taskRef: r2, projectId: "project_hwlab_v03", sourceId: "hwlab-v03-mdtodo", fileRef: "file_rollout", taskId: "R2", title: "D601 v03 页面验收", status: "blocked", parentTaskRef: null, depth: 0, lineNumber: 3, ordinal: 4, linkCount: linkCount(r2), sourceFingerprint: "sha256:e2e-rollout", bodyPreview: "Rollout body", body: "Rollout body", updatedAt: "2026-06-25T09:00:00.000Z" },
{ taskRef: feedbackR1, projectId: "project_hwlab_v03", sourceId: "hwlab-v03-mdtodo", fileRef: "file_feedback", taskId: "R1", title: "这是用户的反馈,你分析原因:", status: "open", parentTaskRef: null, depth: 0, lineNumber: 4, ordinal: 5, linkCount: linkCount(feedbackR1), sourceFingerprint: "sha256:e2e-feedback", bodyPreview: "我 reset sys_trip 后,返回 sys_trip=false,但万用表测量端子还是通的。", body: "我 reset sys_trip 后,返回的代码中 sys_trip 已经 false 了,但万用表测量端子还是通的。是因为 int_trip:true 吗?\n\n完成任务后将详细报告写入 [R1](details/20260609_频率判断_用户反馈/20260609_161845_Task_Report.md)。", updatedAt: "2026-06-26T13:00:00.000Z" }
];
}
function projectManagementTaskDetail(response: ServerResponse, url: URL): void {
const taskRef = url.searchParams.get("taskRef");
const task = state.projectTasks.find((item) => item.taskRef === taskRef);
if (!task) return json(response, 404, { ok: false, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", error: { code: "task_not_found" }, valuesRedacted: true });
const body = String(task.body ?? task.bodyPreview ?? "");
const links = projectManagementTaskLinks(task, body);
return json(response, 200, projectManagementEnvelope({
task: { ...task, bodyPreview: body.slice(0, 240), linkCount: links.length },
detail: {
taskRef: task.taskRef,
taskId: task.taskId,
rxxId: task.taskId,
projectId: task.projectId,
sourceId: task.sourceId,
fileRef: task.fileRef,
relativePath: projectFileForTask(task).relativePath,
title: task.title,
status: task.status,
body,
bodyPreview: body.slice(0, 240),
links,
valuesRedacted: false
},
file: projectFileForTask(task)
}));
}
function projectManagementReportPreview(response: ServerResponse, url: URL): void {
const taskRef = url.searchParams.get("taskRef");
const linkId = url.searchParams.get("linkId");
const task = state.projectTasks.find((item) => item.taskRef === taskRef);
if (!task) return json(response, 404, { ok: false, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", error: { code: "task_not_found" }, valuesRedacted: true });
const link = projectManagementTaskLinks(task, String(task.body ?? task.bodyPreview ?? "")).find((item) => item.linkId === linkId);
if (!link) return json(response, 404, { ok: false, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", error: { code: "report_link_not_found" }, valuesRedacted: true });
return json(response, 200, projectManagementEnvelope({
task,
link,
report: {
sourceId: task.sourceId,
relativePath: link.relativePath,
content: reportContentForLink(link),
fingerprint: "sha256:e2e-report",
revision: "sha256:e2e-report",
byteCount: 56,
render: "markdown",
linkId: link.linkId,
label: link.label,
href: link.href,
valuesRedacted: false
},
file: projectFileForTask(task)
}));
}
function projectManagementLaunchContext(response: ServerResponse, url: URL): void {
const taskRef = url.searchParams.get("taskRef");
const payload = projectManagementLaunchContextForTask(taskRef);
if (!payload) return json(response, 404, { ok: false, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", error: { code: "task_not_found" }, valuesRedacted: true });
return json(response, 200, projectManagementEnvelope(payload));
}
function projectManagementLaunchContextForTask(taskRef: string | null): JsonRecord | null {
const task = state.projectTasks.find((item) => item.taskRef === taskRef);
if (!task) return null;
const source = projectManagementSource();
const file = projectFileForTask(task);
const workspaceRootRef = String(source.workspaceRootRef ?? "");
const executionContext = {
sourceId: task.sourceId,
sourceKind: source.sourceKind,
projectId: task.projectId,
taskRef: task.taskRef,
fileRef: task.fileRef,
relativePath: file.relativePath,
taskId: task.taskId,
hwpodId: source.hwpodId,
nodeId: source.nodeId,
workspaceRootRef,
workspaceRootHash: "e2e-workspace-root-hash",
workspaceRootLabel: "ConStart",
mdtodoRootRef: source.mdtodoRootRef,
hwpodWorkspaceArgs: `--hwpod-id ${source.hwpodId} --workspace-path '${workspaceRootRef}'`,
contextFingerprint: `ctx_e2e_${String(task.taskId ?? "task").replace(/[^A-Za-z0-9]/gu, "_")}`,
capabilities: source.capabilities ?? {},
valuesRedacted: true
};
const launchContext = {
source: "project-management",
projectId: task.projectId,
taskRef: task.taskRef,
sourceId: task.sourceId,
sourceKind: source.sourceKind,
fileRef: task.fileRef,
relativePath: file.relativePath,
taskId: task.taskId,
title: task.title,
status: task.status,
hwpodId: executionContext.hwpodId,
nodeId: executionContext.nodeId,
mdtodoRootRef: executionContext.mdtodoRootRef,
hwpodWorkspaceArgs: executionContext.hwpodWorkspaceArgs,
workspaceRootHash: executionContext.workspaceRootHash,
workspaceRootLabel: executionContext.workspaceRootLabel,
contextFingerprint: executionContext.contextFingerprint,
executionContext,
route: "/projects/mdtodo",
valuesRedacted: true
};
return { task, source, executionContext, launchContext };
}
function projectManagementTaskLinks(task: JsonRecord, body: string): JsonRecord[] {
if (String(task.taskId) !== "R1") return [];
if (body.includes("20260609_161845_Task_Report.md")) {
return [{
linkId: "lnk_feedback_r1_report",
label: "R1",
href: "details/20260609_频率判断_用户反馈/20260609_161845_Task_Report.md",
kind: "markdown-report",
relativePath: "details/20260609_频率判断_用户反馈/20260609_161845_Task_Report.md",
ordinal: 1,
valuesRedacted: true
}];
}
if (!body.includes("R1.1_log_implementation.md")) return [];
return [{
linkId: "lnk_r11_report",
label: "R1.1",
href: "./20260110_LOG/R1.1_log_implementation.md",
kind: "markdown-report",
relativePath: "20260110_LOG/R1.1_log_implementation.md",
ordinal: 1,
valuesRedacted: true
}];
}
function reportContentForLink(link: JsonRecord): string {
if (String(link.relativePath ?? "").includes("20260609_161845_Task_Report.md")) {
return [
"# R1 用户反馈分析报告",
"",
"停机继电器仍然动作时,需要同时确认外部 sys_trip 和内部 int_trip 的输出投票。",
"",
"```json",
"{",
" \"result\": {",
" \"sys_reset\": true,",
" \"int_trip\": true,",
" \"sys_trip\": false,",
" \"sys_alarm\": false",
" },",
" \"id\": 222",
"}",
"```",
"",
"如果 `int_trip` 仍为 true,理论上停机继电器仍可能保持动作。"
].join("\n");
}
return "# R1.1 implementation report\n\nReport body from fake server.";
}
function projectManagementUpdateTask(response: ServerResponse, taskRef: string, body: JsonRecord): void {
const task = state.projectTasks.find((item) => item.taskRef === taskRef);
if (!task) return json(response, 404, { ok: false, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", error: { code: "task_not_found" }, valuesRedacted: true });
const file = projectFileForTask(task);
if (!projectManagementExpectedFingerprintOk(response, file, body)) return;
if (typeof body.title === "string" && body.title.trim()) task.title = body.title.trim();
if (typeof body.status === "string" && body.status.trim()) task.status = body.status.trim();
if (typeof body.body === "string") {
task.body = body.body;
task.bodyPreview = body.body.slice(0, 240);
}
task.updatedAt = new Date().toISOString();
touchProjectFile(String(task.fileRef));
return json(response, 200, projectManagementEnvelope({ task, file: projectFileForTask(task), changedTaskId: task.taskId, affectedTaskIds: [task.taskId] }));
}
function projectManagementCreateTask(response: ServerResponse, body: JsonRecord): void {
const parent = typeof body.parentTaskRef === "string" ? state.projectTasks.find((item) => item.taskRef === body.parentTaskRef) : null;
const after = typeof body.afterTaskRef === "string" ? state.projectTasks.find((item) => item.taskRef === body.afterTaskRef) : null;
const sourceId = String(parent?.sourceId ?? after?.sourceId ?? body.sourceId ?? "hwlab-v03-mdtodo");
const fileRef = String(parent?.fileRef ?? after?.fileRef ?? body.fileRef ?? "file_plan");
const file = state.projectFiles.find((item) => item.sourceId === sourceId && item.fileRef === fileRef);
if (!file) return json(response, 404, { ok: false, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", error: { code: "file_not_found" }, valuesRedacted: true });
if (!projectManagementExpectedFingerprintOk(response, file, body)) return;
const title = String(body.title ?? "").trim();
if (!title) return json(response, 400, { ok: false, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", error: { code: "title_required" }, valuesRedacted: true });
const taskId = parent ? nextProjectChildTaskId(fileRef, String(parent.taskId)) : after ? nextProjectSiblingTaskId(fileRef, String(after.taskId)) : nextProjectRootTaskId(fileRef);
const taskRef = `mdtodo:${sourceId}:${fileRef}:${taskId}`;
const parentTaskRef = parent?.taskRef ?? after?.parentTaskRef ?? null;
const task = { taskRef, projectId: "project_hwlab_v03", sourceId, fileRef, taskId, title, status: String(body.status ?? "open"), parentTaskRef, depth: taskId.split(".").length - 1, lineNumber: 20 + state.projectTasks.length, ordinal: state.projectTasks.length + 1, linkCount: 0, sourceFingerprint: file.fingerprint, body: typeof body.body === "string" ? body.body : "", bodyPreview: typeof body.body === "string" ? body.body.slice(0, 240) : "", updatedAt: new Date().toISOString() };
state.projectTasks.push(task);
touchProjectFile(fileRef);
return json(response, 201, projectManagementEnvelope({ task, file: projectFileForTask(task), changedTaskId: taskId, affectedTaskIds: [taskId] }));
}
function projectManagementDeleteTask(response: ServerResponse, taskRef: string, body: JsonRecord): void {
const task = state.projectTasks.find((item) => item.taskRef === taskRef);
if (!task) return json(response, 404, { ok: false, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", error: { code: "task_not_found" }, valuesRedacted: true });
const file = projectFileForTask(task);
if (!projectManagementExpectedFingerprintOk(response, file, body)) return;
const prefix = `${task.taskId}.`;
const affected = state.projectTasks.filter((item) => item.taskRef === taskRef || String(item.taskId).startsWith(prefix)).map((item) => String(item.taskId));
state.projectTasks = state.projectTasks.filter((item) => !(item.taskRef === taskRef || String(item.taskId).startsWith(prefix)));
touchProjectFile(String(task.fileRef));
return json(response, 200, projectManagementEnvelope({ task: null, file: projectFileForTask(task), changedTaskId: task.taskId, affectedTaskIds: affected }));
}
function projectManagementExpectedFingerprintOk(response: ServerResponse, file: JsonRecord, body: JsonRecord): boolean {
const expected = String(body.expectedFingerprint ?? body.revision ?? "");
if (!expected) {
json(response, 400, { ok: false, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", error: { code: "expected_fingerprint_required" }, valuesRedacted: true });
return false;
}
if (expected !== file.fingerprint) {
json(response, 409, { ok: false, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", error: { code: "revision_conflict" }, valuesRedacted: true });
return false;
}
return true;
}
function projectFileForTask(task: JsonRecord): JsonRecord {
const file = state.projectFiles.find((item) => item.sourceId === task.sourceId && item.fileRef === task.fileRef) ?? state.projectFiles[0];
if (!file) throw new Error("project management fake-server file fixture is missing");
return file;
}
function touchProjectFile(fileRef: string): void {
state.projectRevision += 1;
const file = state.projectFiles.find((item) => item.fileRef === fileRef);
if (!file) return;
file.revision = Number(file.revision ?? 1) + 1;
file.fingerprint = `sha256:e2e-${fileRef}-${state.projectRevision}`;
file.taskCount = state.projectTasks.filter((task) => task.fileRef === fileRef).length;
file.updatedAt = new Date().toISOString();
for (const task of state.projectTasks.filter((item) => item.fileRef === fileRef)) task.sourceFingerprint = file.fingerprint;
}
function nextProjectRootTaskId(fileRef: string): string {
const next = Math.max(0, ...state.projectTasks.filter((task) => task.fileRef === fileRef && !String(task.taskId).includes(".")).map((task) => Number(String(task.taskId).replace(/^R/u, "")) || 0)) + 1;
return `R${next}`;
}
function nextProjectChildTaskId(fileRef: string, parentTaskId: string): string {
const prefix = `${parentTaskId}.`;
const next = Math.max(0, ...state.projectTasks.filter((task) => task.fileRef === fileRef && String(task.taskId).startsWith(prefix)).map((task) => Number(String(task.taskId).slice(prefix.length).split(".")[0]) || 0)) + 1;
return `${parentTaskId}.${next}`;
}
function nextProjectSiblingTaskId(fileRef: string, afterTaskId: string): string {
const parent = afterTaskId.includes(".") ? afterTaskId.split(".").slice(0, -1).join(".") : "";
return parent ? nextProjectChildTaskId(fileRef, parent) : nextProjectRootTaskId(fileRef);
}
function projectManagementSeedLinks(): JsonRecord[] {
return [{ linkId: "lnk_project_task_root", projectId: "project_hwlab_v03", taskRef: "mdtodo:hwlab-v03-mdtodo:file_plan:R1", sessionId: "ses_project_seed", traceId: "trc_project_seed", role: "reference", updatedAt: "2026-06-25T09:00:00.000Z" }];
}
function projectManagementLinkFromBody(body: JsonRecord): JsonRecord {
const now = new Date().toISOString();
return {
linkId: String(body.linkId ?? `lnk_project_launch_${Date.now().toString(36)}`),
projectId: String(body.projectId ?? "project_hwlab_v03"),
taskRef: typeof body.taskRef === "string" ? body.taskRef : null,
sessionId: typeof body.sessionId === "string" ? body.sessionId : null,
traceId: typeof body.traceId === "string" ? body.traceId : null,
role: String(body.role ?? "launch"),
updatedAt: now,
link: body.link && typeof body.link === "object" ? body.link : { valuesRedacted: true }
};
}
async function createWorkbenchLaunch(request: IncomingMessage): Promise<JsonRecord> {
const body = await readJson(request);
const now = new Date().toISOString();
const sessionId = typeof body.sessionId === "string" && body.sessionId.trim() ? body.sessionId : `ses_project_launch_${Date.now().toString(36)}`;
const conversationId = typeof body.conversationId === "string" && body.conversationId.trim() ? body.conversationId : `cnv_project_launch_${Date.now().toString(36)}`;
const authoritative = projectManagementLaunchContextForTask(typeof body.taskRef === "string" ? body.taskRef : null)?.launchContext as JsonRecord | undefined;
const launchContext: JsonRecord = authoritative ?? (body.launchContext && typeof body.launchContext === "object" ? body.launchContext as JsonRecord : {} as JsonRecord);
const session: SessionRecord = {
sessionId,
conversationId,
status: "idle",
projectId: String(body.projectId ?? launchContext.projectId ?? "project_hwlab_v03"),
launchContext,
metadata: { launchContext },
startedAt: now,
updatedAt: now,
messageCount: 0,
firstUserMessagePreview: null,
messages: []
};
state.sessions.unshift(session);
const link = projectManagementLinkFromBody({
linkId: `lnk_project_launch_${sessionId.replace(/^ses_/u, "")}`,
projectId: session.projectId,
taskRef: body.taskRef,
sessionId,
traceId: null,
role: "launch",
link: { launchContext, workbenchUrl: `/workbench/sessions/${sessionId}`, valuesRedacted: true }
});
state.projectLinks.unshift(link);
return {
ok: true,
status: "created",
contractVersion: "workbench-launch-v1",
sessionId,
conversationId,
projectId: session.projectId,
taskRef: body.taskRef,
workbenchUrl: `/workbench/sessions/${sessionId}`,
linkId: link.linkId,
link,
launchContext,
valuesRedacted: true
};
}
function webPerformanceSummaryPayload(url: URL): JsonRecord {
const sampleWindow = fakePerformanceWindow(url.searchParams.get("window"));
const rows = [
performanceRow({ kind: "workbench-journey", metric: "session-switch-full-load", route: "/workbench/sessions/:sessionId", count: 21, p50: 0.18, p75: 0.31, p95: 1.12, tone: "warn", backend: "agentrun", transport: "sse", targetState: "completed", sourceFamily: "workbench" }, sampleWindow),
performanceRow({ kind: "workbench-event-phase", metric: "trace-event-projected", route: "/workbench", count: 28, p50: 0.08, p75: 0.14, p95: 0.42, tone: "ok", eventType: "tool_result", phase: "render", source: "rum", sourceFamily: "workbench" }, sampleWindow),
performanceRow({ kind: "workbench-backend-event", metric: "backend-event-visible", route: "/v1/workbench/events", count: 15, p50: 0.2, p75: 0.34, p95: 1.38, tone: "warn", eventType: "agentrun.stdout", backend: "agentrun", cache: "miss", sourceFamily: "backend" }, sampleWindow),
performanceRow({ kind: "web-vital", metric: "LCP", route: "/performance", count: 9, p50: 1.2, p75: 1.8, p95: 2.9, tone: "ok", sourceFamily: "web" }, sampleWindow),
performanceRow({ kind: "api", metric: "api_request", route: "/v1/web-performance/summary", method: "GET", statusClass: "2xx", outcome: "ok", count: 17, p50: 0.09, p75: 0.15, p95: 0.33, tone: "ok", sourceFamily: "web", backendEvidence: fakeBackendEvidence({ route: "/v1/web-performance/summary", count: 16, p95: 0.18, diagnostic: "backend_matched", diagnosticLabel: "后端样本已匹配" }) }, sampleWindow),
performanceRow({ kind: "api", metric: "api_request", route: "/v1/workbench/sessions", method: "GET", statusClass: "2xx", outcome: "ok", count: 3, p50: 2.5, p75: 5, p95: 10, tone: "warn", problem: "slow-api_request", sampleState: "low-sample", freshness: "low-sample", aggregationKind: "histogram", approximation: "bucketed", sourceFamily: "web", backendEvidence: fakeBackendEvidence({ route: "/v1/workbench/sessions", count: 4, p95: 0.24, diagnostic: "rum_slower_than_backend", diagnosticLabel: "RUM 慢于后端" }) }, sampleWindow),
performanceRow({ kind: "long-task", metric: "longtask", route: "/workbench", count: 3, p50: 0.08, p75: 0.11, p95: 0.2, tone: "warn", problem: "main-thread busy", sourceFamily: "web" }, sampleWindow)
];
const sampleCount = performanceSampleCount(rows);
const collectionHealth = performanceCollectionHealthPayload(rows, sampleWindow);
return {
ok: true,
status: "ready",
source: "fake-server",
observedAt: sampleWindow.generatedAt,
namespace: "hwlab-v03",
gitopsTarget: "D601/v03",
sampleWindow: performanceSampleWindowPayload(sampleWindow),
summary: performanceSummaryContract(sampleWindow, rows, { status: "ready", sampleCount, sampleSeries: 12, problemCount: rows.filter((row) => row.tone === "warn").length }),
backendEvidence: fakeBackendEvidenceSummary(rows, sampleWindow),
collectionHealth,
dashboard: webPerformanceDashboardPayload(rows, sampleWindow, collectionHealth),
rows,
problems: rows.filter((row) => row.tone === "warn"),
webVitals: rows.filter((row) => row.kind === "web-vital"),
apiRoutes: rows.filter((row) => row.kind === "api"),
longTasks: rows.filter((row) => row.kind === "long-task"),
workbenchJourneys: rows.filter((row) => row.kind === "workbench-journey"),
workbenchEventPhases: rows.filter((row) => row.kind === "workbench-event-phase"),
workbenchBackendEvents: rows.filter((row) => row.kind === "workbench-backend-event")
};
}
function fakeBackendEvidence(input: { route: string; count: number; p95: number; diagnostic: string; diagnosticLabel: string }): JsonRecord {
return {
status: "matched",
statusLabel: "已匹配后端",
diagnostic: input.diagnostic,
diagnosticLabel: input.diagnosticLabel,
detail: `fake-server backend evidence for ${input.route}`,
route: input.route,
method: "GET",
count: input.count,
p50: Math.max(0.02, input.p95 / 3),
p75: Math.max(0.04, input.p95 / 2),
p95: input.p95,
responseBytesP95: 4096,
lastObservedAt: "2026-06-18T04:29:59.000Z",
phases: [{ phase: "workbench_session_page_query", outcome: "ok", count: input.count, p95: Math.min(input.p95, 0.2) }]
};
}
function fakeBackendEvidenceSummary(rows: JsonRecord[], sampleWindow: FakePerformanceWindow): JsonRecord {
const evidenceRows = rows
.map((row) => row.backendEvidence)
.filter((evidence): evidence is JsonRecord => Boolean(evidence && typeof evidence === "object" && !Array.isArray(evidence)))
.map((evidence) => ({ route: evidence.route, method: evidence.method, statusClass: "2xx", outcome: "ok", count: evidence.count, average: evidence.p50, p50: evidence.p50, p75: evidence.p75, p95: evidence.p95, firstObservedAt: sampleWindow.windowFrom, lastObservedAt: evidence.lastObservedAt, responseBytes: { count: evidence.count, average: 2048, p50: 2048, p75: 3072, p95: evidence.responseBytesP95 }, phases: evidence.phases, valuesRedacted: true }));
return { schemaVersion: "hwlab-backend-performance-evidence-v1", source: "fake-server-backend-performance-store", observedAt: sampleWindow.generatedAt, sampleCount: evidenceRows.reduce((sum, row) => sum + Number(row.count ?? 0), 0), retainedSampleCount: evidenceRows.length, routeCount: evidenceRows.length, rows: evidenceRows, available: true, valuesRedacted: true };
}
function webPerformanceEmptyPayload(url: URL): JsonRecord {
const sampleWindow = fakePerformanceWindow(url.searchParams.get("window"));
const rows: JsonRecord[] = [];
const collectionHealth = performanceCollectionHealthPayload(rows, sampleWindow);
return {
ok: true,
status: "waiting",
source: "fake-server",
observedAt: sampleWindow.generatedAt,
namespace: "hwlab-v03",
gitopsTarget: "D601/v03",
sampleWindow: performanceSampleWindowPayload(sampleWindow),
summary: performanceSummaryContract(sampleWindow, rows, { status: "waiting", sampleCount: 0, sampleSeries: 0, problemCount: 0 }),
collectionHealth,
dashboard: webPerformanceDashboardPayload(rows, sampleWindow, collectionHealth),
rows,
problems: [],
webVitals: [],
apiRoutes: [],
longTasks: [],
workbenchJourneys: [],
workbenchEventPhases: [],
workbenchBackendEvents: []
};
}
function webPerformanceStaleWindowPayload(url: URL): JsonRecord {
const sampleWindow = fakePerformanceWindow(url.searchParams.get("window"));
const rows: JsonRecord[] = [];
const collectionHealth = {
schemaVersion: "hwlab-web-performance-collection-health-v1",
status: "waiting",
statusLabel: "等待数据",
reason: "no_samples_in_window",
reasonLabel: "当前窗口暂无样本",
sampleCount: 0,
retainedSampleCount: 37,
sampleSeries: 0,
lowSampleThreshold: 5,
firstSampleAt: null,
lastSampleAt: null,
lastRetainedSampleAt: "2026-06-18T03:20:00.000Z",
secondsSinceLastSample: 4200,
windowCoverageSeconds: null,
sourceFamilyCounts: [{ sourceFamily: "web", rowCount: 0, sampleCount: 37 }],
unknownAttribution: { workbenchRows: 0, rowsWithUnknown: 0, samplesWithUnknown: 0, backendUnknownRows: 0, transportUnknownRows: 0 },
diagnostics: [{ code: "no_samples_in_window", label: "当前窗口无样本", tone: "warn", detail: "保留样本存在,但当前窗口没有性能样本。" }]
};
return {
ok: true,
status: "waiting",
source: "fake-server",
observedAt: sampleWindow.generatedAt,
namespace: "hwlab-v03",
gitopsTarget: "D601/v03",
sampleWindow: performanceSampleWindowPayload(sampleWindow),
summary: performanceSummaryContract(sampleWindow, rows, { status: "waiting", sampleCount: 0, retainedSampleCount: 37, sampleSeries: 0, problemCount: 0 }),
backendEvidence: { schemaVersion: "hwlab-backend-performance-evidence-v1", source: "fake-server-backend-performance-store", observedAt: sampleWindow.generatedAt, sampleCount: 0, retainedSampleCount: 37, routeCount: 0, rows: [], available: true, valuesRedacted: true },
collectionHealth,
dashboard: webPerformanceDashboardPayload(rows, sampleWindow, collectionHealth),
rows,
problems: [],
webVitals: [],
apiRoutes: [],
longTasks: [],
workbenchJourneys: [],
workbenchEventPhases: [],
workbenchBackendEvents: []
};
}
function performanceRow(row: JsonRecord, sampleWindow: FakePerformanceWindow): JsonRecord {
const count = Number(row.count ?? 0);
const sampleState = count === 0 ? "empty" : count < 5 ? "low-sample" : "ok";
return {
method: "GET",
statusClass: "2xx",
outcome: "ok",
unit: "seconds",
sampleState,
sampleCount: count,
sourceFamily: "mixed",
freshness: sampleState === "ok" ? "fresh" : sampleState,
aggregationKind: "exact",
approximation: "exact",
windowFrom: sampleWindow.windowFrom,
windowTo: sampleWindow.windowTo,
generatedAt: sampleWindow.generatedAt,
...row
};
}
function webPerformanceDashboardPayload(rows: JsonRecord[], sampleWindow: FakePerformanceWindow, collectionHealth: JsonRecord = performanceCollectionHealthPayload(rows, sampleWindow)): JsonRecord {
const workbench = rows.filter((row) => String(row.kind).startsWith("workbench"));
const api = rows.filter((row) => row.kind === "api");
const vital = rows.filter((row) => row.kind === "web-vital");
const longTask = rows.filter((row) => row.kind === "long-task");
const sampleCount = performanceSampleCount(rows);
const problemCount = rows.filter((row) => row.tone === "warn").length;
return {
schemaVersion: "hwlab-web-performance-dashboard-v1",
generatedAt: sampleWindow.generatedAt,
sampleWindow: { ...performanceSampleWindowPayload(sampleWindow), buckets: [{ id: sampleWindow.id, label: sampleWindow.label, observedAt: sampleWindow.generatedAt, sampleCount }] },
freshness: { observedAt: sampleWindow.generatedAt, generatedAt: sampleWindow.generatedAt, windowFrom: sampleWindow.windowFrom, windowTo: sampleWindow.windowTo, sampleCount, source: "fake-server", sourceFamily: "mixed", namespace: "hwlab-v03", gitopsTarget: "D601/v03", status: collectionHealth.status, statusLabel: collectionHealth.statusLabel, reason: collectionHealth.reason, reasonLabel: collectionHealth.reasonLabel, lowSampleThreshold: 5, lastSampleAt: collectionHealth.lastSampleAt, lastRetainedSampleAt: collectionHealth.lastRetainedSampleAt, secondsSinceLastSample: collectionHealth.secondsSinceLastSample },
collectionHealth,
cards: [
{ id: "health", label: "采集状态", value: collectionHealth.statusLabel, unit: "状态", tone: sampleCount === 0 ? "source" : collectionHealth.status === "fresh" ? "ok" : "warn", detail: collectionHealth.reasonLabel },
{ id: "samples", label: "样本数", value: sampleCount, unit: "样本", tone: sampleCount === 0 ? "source" : "ok", detail: `${sampleWindow.label} · ${rows.length} 个序列` },
{ id: "workbench", label: "工作台序列", value: workbench.length, unit: "序列", tone: workbench.length > 0 ? "ok" : "source", detail: "hwlab-v03 / D601/v03" },
{ id: "problems", label: "问题行", value: problemCount, unit: "条", tone: problemCount > 0 ? "warn" : "ok", detail: "低样本阈值 5 个样本" }
],
trends: [
{ id: "workbench-experience", title: "工作台体感趋势", subtitle: "首屏、会话切换和提交首个可见结果的 P95", unit: "seconds", points: workbench.map(dashboardPoint) },
{ id: "api-timing", title: "同源 API 耗时", subtitle: "Cloud Web 同源 API 请求 P95", unit: "seconds", points: api.map(dashboardPoint) },
{ id: "web-vitals", title: "浏览器核心指标", subtitle: "浏览器体感当前窗口", unit: "mixed", points: vital.map(dashboardPoint) }
],
distributions: [
{ id: "status", title: "状态分布", subtitle: "按健康状态聚合当前窗口行数", unit: "count", buckets: [{ label: "正常", count: 4, tone: "ok" }, { label: "预警", count: 2, tone: "warn" }] },
{ id: "samples", title: "样本状态", subtitle: "正常、低样本和暂无数据分布", unit: "count", buckets: [{ label: "正常样本", count: 6, tone: "ok" }] }
],
topN: [
{ id: "top-api", title: "慢 API TopN", subtitle: "同源 API P95 最慢路由", unit: "seconds", rows: api.map(dashboardTopRow) },
{ id: "top-workbench", title: "工作台慢路径 TopN", subtitle: "工作台 journey 和事件可见延迟", unit: "seconds", rows: workbench.map(dashboardTopRow) },
{ id: "top-long-task", title: "长任务 TopN", subtitle: "主线程长任务当前窗口", unit: "seconds", rows: longTask.map(dashboardTopRow) }
]
};
}
function performanceCollectionHealthPayload(rows: JsonRecord[], sampleWindow: FakePerformanceWindow): JsonRecord {
const sampleCount = performanceSampleCount(rows);
const sourceFamilyCounts = performanceSourceFamilyCounts(rows);
const unknownAttribution = performanceUnknownAttribution(rows);
const diagnostics: JsonRecord[] = [];
let status = "fresh";
let reason = "window_has_samples";
let reasonLabel = "当前窗口采集正常";
if (sampleCount <= 0) {
status = "waiting";
reason = "no_samples_retained";
reasonLabel = "采集器尚未上报样本";
diagnostics.push({ code: reason, label: "暂无采集样本", tone: "source", detail: "fake-server 当前场景没有性能样本。" });
} else if (sampleCount < 5) {
status = "low-sample";
reason = "low_sample_window";
reasonLabel = "当前窗口低样本";
diagnostics.push({ code: reason, label: "低样本窗口", tone: "warn", detail: `当前窗口只有 ${sampleCount} 个样本,低于 5 个样本阈值。` });
}
const rowsWithUnknown = Number(unknownAttribution.rowsWithUnknown ?? 0);
if (rowsWithUnknown > 0) {
if (status === "fresh") {
status = "degraded";
reason = "unknown_attribution";
reasonLabel = "归因字段不完整";
}
diagnostics.push({ code: "unknown_attribution", label: "工作台归因不完整", tone: "warn", detail: `${rowsWithUnknown} 条工作台序列存在 backend transport unknown` });
}
if (sourceFamilyCounts.length > 1) diagnostics.push({ code: "mixed_source_family", label: "多来源样本", tone: "ok", detail: `当前窗口包含 ${sourceFamilyCounts.length} 类低基数来源。` });
if (!diagnostics.length) diagnostics.push({ code: "ok", label: "采集健康", tone: "ok", detail: "当前窗口有足够样本,且没有发现低样本、缺样或 unknown 归因问题。" });
return {
schemaVersion: "hwlab-web-performance-collection-health-v1",
status,
statusLabel: status === "fresh" ? "采集正常" : status === "low-sample" ? "低样本" : status === "degraded" ? "归因不完整" : "等待数据",
reason,
reasonLabel,
sampleCount,
retainedSampleCount: sampleCount,
sampleSeries: rows.length,
lowSampleThreshold: 5,
firstSampleAt: sampleCount > 0 ? sampleWindow.windowFrom : null,
lastSampleAt: sampleCount > 0 ? sampleWindow.generatedAt : null,
lastRetainedSampleAt: sampleCount > 0 ? sampleWindow.generatedAt : null,
secondsSinceLastSample: sampleCount > 0 ? 0 : null,
windowCoverageSeconds: sampleCount > 0 ? sampleWindow.seconds : null,
sourceFamilyCounts,
unknownAttribution,
diagnostics
};
}
function performanceSourceFamilyCounts(rows: JsonRecord[]): JsonRecord[] {
const counts = new Map<string, { sourceFamily: string; rowCount: number; sampleCount: number }>();
for (const row of rows) {
const sourceFamily = String(row.sourceFamily ?? "mixed");
const entry = counts.get(sourceFamily) ?? { sourceFamily, rowCount: 0, sampleCount: 0 };
entry.rowCount += 1;
entry.sampleCount += Math.max(0, Number(row.count) || 0);
counts.set(sourceFamily, entry);
}
return [...counts.values()].sort((left, right) => right.sampleCount - left.sampleCount || left.sourceFamily.localeCompare(right.sourceFamily));
}
function performanceUnknownAttribution(rows: JsonRecord[]): JsonRecord {
const workbenchRows = rows.filter((row) => String(row.kind ?? "").startsWith("workbench"));
const isUnknown = (value: unknown) => !String(value ?? "").trim() || String(value ?? "").trim().toLowerCase() === "unknown" || String(value ?? "").trim() === "-";
const rowsWithUnknown = workbenchRows.filter((row) => isUnknown(row.backend) || isUnknown(row.transport)).length;
return {
workbenchRows: workbenchRows.length,
rowsWithUnknown,
samplesWithUnknown: workbenchRows.reduce((sum, row) => sum + ((isUnknown(row.backend) || isUnknown(row.transport)) ? Math.max(0, Number(row.count) || 0) : 0), 0),
backendUnknownRows: workbenchRows.filter((row) => isUnknown(row.backend)).length,
transportUnknownRows: workbenchRows.filter((row) => isUnknown(row.transport)).length
};
}
function fakePerformanceWindow(value: string | null): FakePerformanceWindow {
const id = ["5m", "15m", "1h", "6h", "24h", "all"].includes(String(value)) ? String(value) : "15m";
const generatedAt = "2026-06-18T04:30:00.000Z";
const specs: Record<string, Omit<FakePerformanceWindow, "id" | "generatedAt" | "windowTo">> = {
"5m": { label: "最近 5 分钟", seconds: 300, windowFrom: "2026-06-18T04:25:00.000Z" },
"15m": { label: "最近 15 分钟", seconds: 900, windowFrom: "2026-06-18T04:15:00.000Z" },
"1h": { label: "最近 1 小时", seconds: 3600, windowFrom: "2026-06-18T03:30:00.000Z" },
"6h": { label: "最近 6 小时", seconds: 21600, windowFrom: "2026-06-17T22:30:00.000Z" },
"24h": { label: "最近 24 小时", seconds: 86400, windowFrom: "2026-06-17T04:30:00.000Z" },
all: { label: "全部累计", seconds: null, windowFrom: null }
};
const spec = specs[id] ?? { label: "最近 15 分钟", seconds: 900, windowFrom: "2026-06-18T04:15:00.000Z" };
return { id, generatedAt, windowTo: generatedAt, ...spec };
}
function performanceSampleWindowPayload(sampleWindow: FakePerformanceWindow): JsonRecord {
return { id: sampleWindow.id, label: sampleWindow.label, seconds: sampleWindow.seconds, windowFrom: sampleWindow.windowFrom, windowTo: sampleWindow.windowTo, generatedAt: sampleWindow.generatedAt, aggregationKind: "exact", approximation: "exact" };
}
function performanceSummaryContract(sampleWindow: FakePerformanceWindow, rows: JsonRecord[], summary: JsonRecord): JsonRecord {
return {
routeCount: rows.length,
durationSeries: rows.filter((row) => row.unit === "seconds").length,
lowSampleThreshold: 5,
workbenchJourneySeries: rows.filter((row) => row.kind === "workbench-journey").length,
workbenchEventPhaseSeries: rows.filter((row) => row.kind === "workbench-event-phase").length,
workbenchBackendEventVisibleSeries: rows.filter((row) => row.kind === "workbench-backend-event").length,
window: sampleWindow.id,
windowLabel: sampleWindow.label,
windowSeconds: sampleWindow.seconds,
windowFrom: sampleWindow.windowFrom,
windowTo: sampleWindow.windowTo,
generatedAt: sampleWindow.generatedAt,
aggregationKind: "exact",
approximation: "exact",
...summary
};
}
function performanceSampleCount(rows: JsonRecord[]): number {
return rows.reduce((total, row) => total + (Number(row.count) || 0), 0);
}
function dashboardPoint(row: JsonRecord): JsonRecord {
return { label: dashboardMetricLabel(row), detail: dashboardRouteLabel(row.route), value: row.p95, p50: row.p50, p75: row.p75, p95: row.p95, count: row.count, tone: row.tone, sampleState: row.sampleState };
}
function dashboardTopRow(row: JsonRecord): JsonRecord {
return { label: dashboardMetricLabel(row), detail: dashboardRouteLabel(row.route), value: row.p95, unit: row.unit ?? "seconds", count: row.count, tone: row.tone };
}
function dashboardRouteLabel(route: unknown): string {
const value = String(route ?? "").trim();
if (!value || value === "-") return "当前窗口";
return value
.replace(/:sessionId/gu, ":会话")
.replace(/:traceId/gu, ":轨迹")
.replace(/:runId/gu, ":运行")
.replace(/:threadId/gu, ":线程")
.replace(/:turnId/gu, ":轮次");
}
function dashboardMetricLabel(row: JsonRecord): string {
const metric = String(row.metric ?? "unknown");
const labels: Record<string, string> = {
"session-switch-full-load": "切换会话完整加载",
"trace-event-projected": "轨迹事件投影",
"backend-event-visible": "后端事件到可见",
LCP: "最大内容绘制",
fetchJson: "同源 API 请求",
longtask: "主线程长任务"
};
return labels[metric] ?? metric;
}
function createScenarioState(scenarioId: string): ScenarioState {
const base = structuredClone(capture.scenario);
const id = scenarioId || "baseline";
const sessions = base.sessions;
const traces = base.traces;
if (id === "cross-project-detail-boundary") sessions.push(hiddenBoundarySession());
if (id === "legacy-cnv-deeplink-canonical") {
sessions.unshift(legacyCanonicalSession());
traces.trc_40badc15523146c9 = legacyCanonicalTrace();
}
if (id === "submit-authority-race") {
sessions.unshift(submitSplitSession());
traces.trc_submit_split = submitSplitTrace();
}
if (id === "session-switch-delayed-detail-frame") {
markSessionText(sessions, "ses_running", "SESSION_A_ONLY", "SESSION_A_ONLY running source session");
markSessionText(sessions, "ses_completed", "SESSION_B_ONLY", "SESSION_B_ONLY completed target session");
}
if (id === "session-rail-many") {
for (let index = 0; index < 51; index += 1) sessions.push(manyRailSession(index));
}
if (id === "session-switch-detail-404-isolated") {
sessions.unshift(staleDetailSession());
sessions.push(emptySession());
}
if (id === "terminal-empty-trace") {
sessions.push(terminalEmptyTraceSession());
traces.trc_terminal_empty = terminalEmptyTrace();
}
if (id === "markdown-final-response") {
sessions.unshift(markdownFinalSession());
traces.trc_markdown_final = markdownFinalTrace();
}
if (id === "terminal-assistant-event-final-response") {
sessions.unshift(terminalAssistantFinalSession());
traces.trc_terminal_assistant_final = terminalAssistantFinalTrace();
}
if (id === "progress-only-final-response") markRunningProgressOnly(sessions, traces);
if (id === "terminal-completed-no-final-response") markRunningNoFinalResponse(sessions, traces);
if (id === "tool-completed-projection-running") markToolCompletedProjectionRunning(sessions, traces);
if (id === "terminal-canceled-late-timing") markTerminalCanceledLateTiming(sessions, traces);
if (id === "projection-degraded-diagnostics") {
sessions.unshift(projectionDegradedSession());
traces.trc_projection_degraded = projectionDegradedTrace();
}
if (id === "projection-sse-error") {
sessions.unshift(projectionSseErrorSession());
traces.trc_projection_sse_error = projectionSseErrorTrace();
}
if (id === "trace-detail-read-timeout-diagnostic") {
sessions.unshift(traceDetailReadTimeoutSession());
traces.trc_trace_detail_read_timeout = traceDetailReadTimeoutTrace();
}
if (id === "sealed-final-response-diagnostics") {
sessions.unshift(sealedFinalResponseDiagnosticSession());
traces.trc_sealed_final_diag = sealedFinalResponseDiagnosticTrace();
}
if (id === "trace-final-response-not-message-authority") {
sessions.unshift(traceFinalResponseConflictSession());
traces.trc_trace_final_conflict = traceFinalResponseConflictTrace();
}
if (id === "scroll-follow-long-trace") {
const session = scrollFollowSession();
sessions.unshift(session);
traces.trc_scroll_follow = scrollFollowTrace(90);
}
if (id === "projector-resume-from-checkpoint") {
const session = projectorResumeSession();
sessions.unshift(session);
traces.trc_f2456023233a485b = projectorResumeEarlyTrace();
}
if (id === "cross-session-late-events") {
sessions.unshift(crossSessionLateB(), crossSessionLateA());
traces.trc_late_A = crossSessionLateTraceA();
}
if (id === "deleted-session-deeplink") sessions.unshift(archivedDeletedSession());
if (id === "session-switch-empty-reload") sessions.push(emptySession());
if (id === "empty-session-gc") sessions.unshift(staleEmptyTtlSession(), freshEmptyTtlSession(), staleMessagedTtlSession());
const selectedSessionId = id === "scroll-follow-long-trace"
? "ses_scroll_follow"
: id === "deep-link" || id === "stale-nested-trace"
? "ses_failed"
: id === "legacy-cnv-deeplink-canonical"
? "ses_running"
: id === "session-switch-detail-404-isolated" || id === "completed-replay-detail-404" || id === "deleted-session-deeplink" || id === "terminal-turn-stale-session-active"
? "ses_completed"
: id === "terminal-empty-trace"
? "ses_terminal_empty"
: id === "markdown-final-response"
? "ses_markdown_final"
: id === "terminal-assistant-event-final-response"
? "ses_terminal_assistant_final"
: id === "progress-only-final-response" || id === "terminal-completed-no-final-response" || id === "tool-completed-projection-running" || id === "terminal-canceled-late-timing"
? "ses_running"
: id === "projector-resume-from-checkpoint"
? "ses_317f78e1-ed91-4b09-a72a-3668d5469f59"
: id === "projection-degraded-diagnostics"
? "ses_projection_degraded"
: id === "projection-sse-error"
? "ses_projection_sse_error"
: id === "trace-detail-read-timeout-diagnostic"
? "ses_trace_detail_read_timeout"
: id === "sealed-final-response-diagnostics"
? "ses_sealed_final_diag"
: id === "trace-final-response-not-message-authority"
? "ses_trace_final_conflict"
: id === "create-while-route-loading"
? "ses_running"
: base.selectedSessionId;
const staleTraceId = id === "stale-nested-trace" || id === "stale-submit-restore" ? "trc_stale_502" : null;
const projectLinks = projectManagementSeedLinks();
return {
scenarioId: id,
providerProfile: base.providerProfile,
selectedSessionId,
sessions,
traces,
requestLedger: [],
legacyRequestLedger: [],
chatRequests: [],
projectLinks,
projectFiles: projectManagementFiles(),
projectTasks: projectManagementSeedTasks(projectLinks),
projectRevision: 1,
listOmitSelected: id === "selected-missing-from-list",
sessionDelayMs: id === "loading" ? 2_500 : 0,
sessionDetailDelayMs: id === "legacy-cnv-deeplink-canonical" ? 1_500 : id === "session-switch-delayed-detail-frame" ? 900 : id === "submit-authority-race" ? 1_000 : 0,
chatDelayMs: id === "submit-authority-race" ? 1_000 : 0,
terminalScript: id === "event-replay" || id === "running-to-terminal" || id === "stale-submit-restore" || id === "progress-only-final-response" || id === "terminal-completed-no-final-response" || id === "terminal-canceled-late-timing",
terminalFailureScript: id === "stale-submit-restore",
staleTraceId,
liveBackfillTraceId: id === "projector-resume-from-checkpoint" ? "trc_f2456023233a485b" : null,
liveBackfillReadyAtMs: id === "projector-resume-from-checkpoint" ? Date.now() + 5_000 : null
};
}
function refreshBackgroundProjection(): void {
if (state.scenarioId !== "projector-resume-from-checkpoint") return;
if (!state.liveBackfillReadyAtMs || Date.now() < state.liveBackfillReadyAtMs) return;
const session = sessionById("ses_317f78e1-ed91-4b09-a72a-3668d5469f59");
if (session?.status === "completed") return;
commitProjectorResumeProjection();
}
function projectorResumeSession(): SessionRecord {
const now = new Date().toISOString();
const trace = projectorResumeEarlyTrace();
return {
sessionId: "ses_317f78e1-ed91-4b09-a72a-3668d5469f59",
threadId: "thr_projector_resume_1596",
status: "running",
lastTraceId: "trc_f2456023233a485b",
startedAt: now,
updatedAt: now,
messageCount: 2,
firstUserMessagePreview: "issue 1596 durable projector resume sample",
turnSummary: { traceId: "trc_f2456023233a485b", status: "running", running: true, terminal: false, ...projectorResumeProjection("projecting", 4) },
messages: [
{ id: "msg_projector_resume_user", messageId: "msg_projector_resume_user", role: "user", title: "用户", text: "issue 1596 durable projector resume sample", status: "sent", createdAt: now, sessionId: "ses_317f78e1-ed91-4b09-a72a-3668d5469f59", threadId: "thr_projector_resume_1596", traceId: "trc_f2456023233a485b", turnId: "turn_projector_resume_1596" },
{ id: "msg_projector_resume_agent", messageId: "msg_projector_resume_agent", role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId: "ses_317f78e1-ed91-4b09-a72a-3668d5469f59", threadId: "thr_projector_resume_1596", traceId: "trc_f2456023233a485b", turnId: "turn_projector_resume_1596", runnerTrace: trace, ...projectorResumeProjection("projecting", 4) }
]
};
}
function projectorResumeEarlyTrace(): JsonRecord {
const createdAt = new Date().toISOString();
const projection = projectorResumeProjection("projecting", 4);
const events = [
{ seq: 1, sourceSeq: 1, createdAt, label: "agentrun:request:accepted", type: "backend_status", status: "running", payload: { commandId: "cmd_d4d20aa2bb2c4d19a91143ce87d73704" } },
{ seq: 2, sourceSeq: 2, createdAt, label: "agentrun:run:created", type: "backend_status", status: "running", payload: { runId: "run_58ef1811071548539f881515912560d8", runStatus: "claimed" } },
{ seq: 3, sourceSeq: 3, createdAt, label: "agentrun:command:created", type: "backend_status", status: "running", payload: { commandId: "cmd_d4d20aa2bb2c4d19a91143ce87d73704", commandState: "running" } },
{ seq: 4, sourceSeq: 4, createdAt, label: "agentrun:runner-job:created", type: "backend_status", status: "running", payload: { commandId: "cmd_d4d20aa2bb2c4d19a91143ce87d73704", namespace: "agentrun-v01" } }
];
return { traceId: "trc_f2456023233a485b", status: "running", running: true, terminal: false, sessionId: "ses_317f78e1-ed91-4b09-a72a-3668d5469f59", threadId: "thr_projector_resume_1596", turnId: "turn_projector_resume_1596", events, eventCount: events.length, fullTraceLoaded: true, hasMore: false, ...projection };
}
function projectorResumeCompletedTrace(): JsonRecord {
const createdAt = new Date().toISOString();
const finalText = "fake projector resume completed from durable checkpoint.";
const projection = projectorResumeProjection("caught-up", 7);
const events = [
...(projectorResumeEarlyTrace().events as JsonRecord[]),
{ seq: 5, sourceSeq: 2748, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "completed", message: finalText, payload: { commandId: "cmd_d4d20aa2bb2c4d19a91143ce87d73704" } },
{ seq: 6, sourceSeq: 2749, createdAt, label: "item/commandExecution:completed", type: "commandExecution", status: "completed", stdout: "OK\n", payload: { commandId: "cmd_d4d20aa2bb2c4d19a91143ce87d73704", exitCode: 0 } },
{ seq: 7, sourceSeq: 2750, createdAt, label: "agentrun:backend:turn/completed", type: "backend_status", status: "completed", terminal: true, payload: { commandId: "cmd_d4d20aa2bb2c4d19a91143ce87d73704", terminalStatus: "completed" } }
];
return { traceId: "trc_f2456023233a485b", status: "completed", running: false, terminal: true, sessionId: "ses_317f78e1-ed91-4b09-a72a-3668d5469f59", threadId: "thr_projector_resume_1596", turnId: "turn_projector_resume_1596", events, eventCount: events.length, fullTraceLoaded: true, hasMore: false, finalResponse: { text: finalText, status: "completed" }, traceSummary: { source: "durable-projector-resume", terminalStatus: "completed", valuesPrinted: false }, ...projection };
}
function projectorResumeProjection(status: "projecting" | "caught-up", lastProjectedSeq: number): JsonRecord {
const caughtUp = status === "caught-up";
const projection = {
projectionStatus: status,
projectionHealth: status,
lastProjectedSeq,
sourceLatestSeq: 2750,
sourceRunId: "run_58ef1811071548539f881515912560d8",
sourceCommandId: "cmd_d4d20aa2bb2c4d19a91143ce87d73704",
staleMs: caughtUp ? 0 : 90_000,
blocker: caughtUp ? null : { code: "projector_resume_pending", layer: "workbench-projector", retryable: true, message: "后台投影恢复中,已从 checkpoint 记录 lastProjectedSeq=4。", valuesPrinted: false },
valuesRedacted: true
};
return { projection, ...projection };
}
function commitProjectorResumeProjection(): void {
const completed = projectorResumeCompletedTrace();
state.traces.trc_f2456023233a485b = completed;
const session = sessionById("ses_317f78e1-ed91-4b09-a72a-3668d5469f59");
if (!session) return;
session.status = "completed";
session.updatedAt = new Date().toISOString();
session.turnSummary = { traceId: "trc_f2456023233a485b", status: "completed", running: false, terminal: true, ...projectorResumeProjection("caught-up", 7) };
session.messages = (session.messages ?? []).map((message) => {
if (message.role !== "agent" || message.traceId !== "trc_f2456023233a485b") return message;
return { ...message, text: "fake projector resume completed from durable checkpoint.", status: "completed", runnerTrace: completed, ...projectorResumeProjection("caught-up", 7) };
});
const terminalEvent = (completed.events as JsonRecord[]).at(-1) ?? null;
if (terminalEvent) broadcastSse("workbench.trace.event", { type: "trace.event", sessionId: session.sessionId, threadId: session.threadId ?? null, traceId: "trc_f2456023233a485b", event: terminalEvent, snapshot: completed });
broadcastSse("workbench.turn.snapshot", { type: "turn.snapshot", sessionId: session.sessionId, threadId: session.threadId ?? null, traceId: "trc_f2456023233a485b", turn: turnPayload("trc_f2456023233a485b") });
}
function markSessionText(sessions: SessionRecord[], sessionId: string, userText: string, agentText: string): void {
const session = sessions.find((item) => item.sessionId === sessionId);
if (!session) return;
session.firstUserMessagePreview = userText;
session.messages = (session.messages ?? []).map((message) => {
if (message.role === "user") return { ...message, text: userText };
if (message.role === "agent") return { ...message, text: agentText };
return message;
});
}
function markRunningProgressOnly(sessions: SessionRecord[], traces: Record<string, JsonRecord>): void {
const createdAt = new Date().toISOString();
const progressEvent = { seq: 1, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "running", replyAuthority: false, final: false, message: progressOnlyText };
const trace = { traceId: "trc_running", status: "running", sessionId: "ses_running", threadId: "thr_running", turnId: "turn_running", events: [progressEvent], eventCount: 1, fullTraceLoaded: false, hasMore: false };
traces.trc_running = trace;
const session = sessions.find((item) => item.sessionId === "ses_running");
if (!session) return;
session.status = "running";
session.lastTraceId = "trc_running";
session.firstUserMessagePreview = "progress-only running turn";
session.messages = (session.messages ?? []).map((message) => {
if (message.role === "user") return { ...message, text: "progress-only running turn" };
if (message.role !== "agent" || message.traceId !== "trc_running") return message;
return { ...message, text: "", status: "running", runnerTrace: trace };
});
}
function markRunningNoFinalResponse(sessions: SessionRecord[], traces: Record<string, JsonRecord>): void {
const trace = noFinalRunningTrace();
traces.trc_running = trace;
const session = sessions.find((item) => item.sessionId === "ses_running");
if (!session) return;
session.status = "running";
session.lastTraceId = "trc_running";
session.firstUserMessagePreview = "completed turn without final response";
session.messages = (session.messages ?? []).map((message) => {
if (message.role === "user") return { ...message, text: "completed turn without final response" };
if (message.role !== "agent" || message.traceId !== "trc_running") return message;
return { ...message, text: "", status: "running", runnerTrace: trace };
});
}
function markTerminalCanceledLateTiming(sessions: SessionRecord[], traces: Record<string, JsonRecord>): void {
const trace = terminalCanceledLateTimingRunningTrace();
traces.trc_running = trace;
const session = sessions.find((item) => item.sessionId === "ses_running");
if (!session) return;
session.status = "running";
session.lastTraceId = "trc_running";
session.firstUserMessagePreview = "terminal canceled timing should stay sealed";
session.messages = (session.messages ?? []).map((message) => {
if (message.role === "user") return { ...message, text: "terminal canceled timing should stay sealed" };
if (message.role !== "agent" || message.traceId !== "trc_running") return message;
return { ...message, text: "", status: "running", timing: trace.timing, startedAt: trace.startedAt, lastEventAt: trace.lastEventAt, finishedAt: null, durationMs: null, runnerTrace: trace };
});
}
function terminalCanceledLateTimingRunningTrace(): JsonRecord {
const startedAt = "2026-06-17T09:39:00.000Z";
const lastEventAt = "2026-06-17T09:39:04.000Z";
const timing = { startedAt, lastEventAt, finishedAt: null, durationMs: null, valuesRedacted: true };
return {
traceId: "trc_running",
status: "running",
sessionId: "ses_running",
threadId: "thr_running",
turnId: "turn_running",
timing,
startedAt,
lastEventAt,
finishedAt: null,
durationMs: null,
events: [{ seq: 1, createdAt: lastEventAt, label: "agentrun:backend:turn/running", type: "backend_status", status: "running" }],
eventCount: 1,
fullTraceLoaded: false,
hasMore: false
};
}
function applyTerminalCanceledLateTiming(durationMs: number, finishedAt: string): JsonRecord | null {
const startedAt = "2026-06-17T09:39:00.000Z";
const timing = { startedAt, lastEventAt: finishedAt, finishedAt, durationMs, valuesRedacted: true };
const event = { seq: 2, createdAt: finishedAt, label: "agentrun:terminal:canceled", type: "backend_status", status: "canceled", terminal: true };
const trace = {
traceId: "trc_running",
status: "canceled",
sessionId: "ses_running",
threadId: "thr_running",
turnId: "turn_running",
timing,
startedAt,
lastEventAt: finishedAt,
finishedAt,
durationMs,
events: [event],
eventCount: 2,
fullTraceLoaded: true,
hasMore: false,
finalResponse: { text: "hwlab-user-cancel", status: "canceled" }
};
state.traces.trc_running = trace;
const session = sessionById("ses_running");
if (!session) return null;
session.status = "canceled";
session.updatedAt = finishedAt;
session.messages = (session.messages ?? []).map((message) => message.role === "agent" && message.traceId === "trc_running"
? { ...message, text: "hwlab-user-cancel", status: "canceled", timing, startedAt, lastEventAt: finishedAt, finishedAt, durationMs, runnerTrace: trace }
: message);
return trace;
}
function markToolCompletedProjectionRunning(sessions: SessionRecord[], traces: Record<string, JsonRecord>): void {
const trace = toolCompletedProjectionRunningTrace();
traces.trc_running = trace;
const session = sessions.find((item) => item.sessionId === "ses_running");
if (!session) return;
session.status = "running";
session.lastTraceId = "trc_running";
session.firstUserMessagePreview = "tool completed but turn still running";
session.messages = (session.messages ?? []).map((message) => {
if (message.role === "user") return { ...message, text: "tool completed but turn still running" };
if (message.role !== "agent" || message.traceId !== "trc_running") return message;
return { ...message, text: "", status: "running", runnerTrace: trace };
});
}
function toolCompletedProjectionRunningTrace(): JsonRecord {
const createdAt = new Date().toISOString();
const events = [
{ seq: 1, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "running", terminal: false, message: "正在安装 Python。" },
{ seq: 2, createdAt, label: "item/commandExecution:completed", type: "commandExecution", status: "completed", terminal: false, command: "ls -ld .", stdout: "OK\n" }
];
return {
traceId: "trc_running",
status: "completed",
turnStatus: "running",
projectionStatus: "projecting",
sessionId: "ses_running",
threadId: "thr_running",
turnId: "turn_running",
events,
eventCount: events.length,
fullTraceLoaded: true,
hasMore: false,
finalResponse: null,
assistantText: null
};
}
function projectionDiagnostic(input: { code: string; message: string; health?: string; category?: string; layer?: string; traceId: string; runId?: string; commandId?: string; staleMs?: number }): JsonRecord {
const diagnostic = {
contractVersion: "hwlab-error-diagnostic-v1",
traceId: input.traceId,
requestId: `req_e2e_${input.code}`,
route: "/v1/workbench/events",
layer: input.layer ?? "agentrun",
category: input.category ?? "upstream-timeout",
code: input.code,
httpStatus: 0,
source: "server",
observedAt: new Date().toISOString(),
retryable: true,
valuesPrinted: false
};
return {
projectionStatus: "projecting",
projectionHealth: input.health ?? "degraded",
lastProjectedSeq: 137,
sourceRunId: input.runId ?? "run_projection_diag",
sourceCommandId: input.commandId ?? "cmd_projection_diag",
staleMs: input.staleMs ?? 12_345,
blocker: {
code: input.code,
layer: input.layer ?? "agentrun",
category: input.category ?? "upstream-timeout",
message: input.message,
retryable: true,
timeoutMs: 2500,
runId: input.runId ?? "run_projection_diag",
commandId: input.commandId ?? "cmd_projection_diag",
traceId: diagnostic.traceId,
requestId: diagnostic.requestId,
route: diagnostic.route,
source: diagnostic.source,
httpStatus: diagnostic.httpStatus,
diagnostic,
valuesPrinted: false
},
diagnostic,
valuesRedacted: true
};
}
function projectionDegradedTrace(): JsonRecord {
const projection = projectionDiagnostic({ traceId: "trc_projection_degraded", code: "agentrun_result_timeout", message: "状态更新超时,最近投影 seq=137,AgentRun 结果暂不可见。" });
return { traceId: "trc_projection_degraded", status: "running", sessionId: "ses_projection_degraded", threadId: "thr_projection_degraded", turnId: "turn_projection_degraded", events: [], eventCount: 0, fullTraceLoaded: true, hasMore: false, projection, ...projection };
}
function projectionDegradedSession(): SessionRecord {
const now = new Date().toISOString();
const projection = projectionDiagnostic({ traceId: "trc_projection_degraded", code: "agentrun_result_timeout", message: "状态更新超时,最近投影 seq=137,AgentRun 结果暂不可见。" });
return {
sessionId: "ses_projection_degraded",
threadId: "thr_projection_degraded",
status: "running",
lastTraceId: "trc_projection_degraded",
updatedAt: now,
messageCount: 2,
firstUserMessagePreview: "projection degraded visibility",
turnSummary: { traceId: "trc_projection_degraded", status: "running", running: true, terminal: false, ...projection },
messages: [
{ id: "msg_projection_degraded_user", messageId: "msg_projection_degraded_user", role: "user", title: "用户", text: "projection degraded visibility", status: "sent", createdAt: now, sessionId: "ses_projection_degraded", threadId: "thr_projection_degraded", turnId: "turn_projection_degraded" },
{ id: "msg_projection_degraded_agent", messageId: "msg_projection_degraded_agent", role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId: "ses_projection_degraded", threadId: "thr_projection_degraded", traceId: "trc_projection_degraded", turnId: "turn_projection_degraded", projection, runnerTrace: projectionDegradedTrace() }
]
};
}
function projectionSseErrorTrace(): JsonRecord {
return { traceId: "trc_projection_sse_error", status: "running", sessionId: "ses_projection_sse_error", threadId: "thr_projection_sse_error", turnId: "turn_projection_sse_error", events: [], eventCount: 0, fullTraceLoaded: false, hasMore: false };
}
function projectionSseErrorSession(): SessionRecord {
const now = new Date().toISOString();
return {
sessionId: "ses_projection_sse_error",
threadId: "thr_projection_sse_error",
status: "running",
lastTraceId: "trc_projection_sse_error",
updatedAt: now,
messageCount: 2,
firstUserMessagePreview: "projection SSE error visibility",
messages: [
{ id: "msg_projection_sse_error_user", messageId: "msg_projection_sse_error_user", role: "user", title: "用户", text: "projection SSE error visibility", status: "sent", createdAt: now, sessionId: "ses_projection_sse_error", threadId: "thr_projection_sse_error", turnId: "turn_projection_sse_error" },
{ id: "msg_projection_sse_error_agent", messageId: "msg_projection_sse_error_agent", role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId: "ses_projection_sse_error", threadId: "thr_projection_sse_error", traceId: "trc_projection_sse_error", turnId: "turn_projection_sse_error", runnerTrace: projectionSseErrorTrace() }
]
};
}
function traceDetailReadTimeoutTrace(): JsonRecord {
return { traceId: "trc_trace_detail_read_timeout", status: "running", sessionId: "ses_trace_detail_read_timeout", threadId: "thr_trace_detail_read_timeout", turnId: "turn_trace_detail_read_timeout", events: [], eventCount: 0, fullTraceLoaded: false, hasMore: true };
}
function traceDetailReadTimeoutSession(): SessionRecord {
const now = new Date().toISOString();
return {
sessionId: "ses_trace_detail_read_timeout",
threadId: "thr_trace_detail_read_timeout",
status: "running",
lastTraceId: "trc_trace_detail_read_timeout",
updatedAt: now,
messageCount: 2,
firstUserMessagePreview: "trace detail read timeout visibility",
messages: [
{ id: "msg_trace_detail_read_timeout_user", messageId: "msg_trace_detail_read_timeout_user", role: "user", title: "用户", text: "trace detail read timeout visibility", status: "sent", createdAt: now, sessionId: "ses_trace_detail_read_timeout", threadId: "thr_trace_detail_read_timeout", turnId: "turn_trace_detail_read_timeout" },
{ id: "msg_trace_detail_read_timeout_agent", messageId: "msg_trace_detail_read_timeout_agent", role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId: "ses_trace_detail_read_timeout", threadId: "thr_trace_detail_read_timeout", traceId: "trc_trace_detail_read_timeout", turnId: "turn_trace_detail_read_timeout", runnerTrace: traceDetailReadTimeoutTrace() }
]
};
}
function sealedFinalResponseDiagnosticTrace(): JsonRecord {
const now = new Date().toISOString();
const finalText = "已完成的 sealed final response 不应被诊断覆盖。";
return {
traceId: "trc_sealed_final_diag",
status: "completed",
sessionId: "ses_sealed_final_diag",
threadId: "thr_sealed_final_diag",
turnId: "turn_sealed_final_diag",
events: [],
eventCount: 1,
fullTraceLoaded: false,
hasMore: true,
finalResponse: { text: finalText, status: "completed" },
terminalEvidence: { terminal: true, status: "completed" },
sealedAt: now
};
}
function sealedFinalResponseDiagnosticSession(): SessionRecord {
const now = new Date().toISOString();
const finalText = "已完成的 sealed final response 不应被诊断覆盖。";
const trace = sealedFinalResponseDiagnosticTrace();
return {
sessionId: "ses_sealed_final_diag",
threadId: "thr_sealed_final_diag",
status: "completed",
lastTraceId: "trc_sealed_final_diag",
updatedAt: now,
messageCount: 2,
firstUserMessagePreview: "sealed final response diagnostic separation",
turnSummary: { traceId: "trc_sealed_final_diag", status: "completed", running: false, terminal: true, sealedAt: now },
messages: [
{ id: "msg_sealed_final_user", messageId: "msg_sealed_final_user", role: "user", title: "用户", text: "sealed final response diagnostic separation", status: "sent", createdAt: now, sessionId: "ses_sealed_final_diag", threadId: "thr_sealed_final_diag", turnId: "turn_sealed_final_diag" },
{ id: "msg_sealed_final_agent", messageId: "msg_sealed_final_agent", role: "agent", title: "Code Agent", text: finalText, status: "completed", createdAt: now, updatedAt: now, sessionId: "ses_sealed_final_diag", threadId: "thr_sealed_final_diag", traceId: "trc_sealed_final_diag", turnId: "turn_sealed_final_diag", sealedAt: now, runnerTrace: trace, finalResponse: { text: finalText, status: "completed" } }
]
};
}
function traceFinalResponseConflictTrace(): JsonRecord {
const now = new Date().toISOString();
const event = { seq: 1, sourceSeq: 91, createdAt: now, label: "agentrun:assistant:message", type: "assistant_message", status: "completed", terminal: true, final: true, replyAuthority: true, message: traceDetailConflictText };
return {
traceId: "trc_trace_final_conflict",
status: "completed",
sessionId: "ses_trace_final_conflict",
threadId: "thr_trace_final_conflict",
turnId: "turn_trace_final_conflict",
events: [event],
eventCount: 1,
fullTraceLoaded: true,
hasMore: false,
finalResponse: { text: traceDetailConflictText, status: "completed" },
terminalEvidence: { terminal: true, status: "completed" },
sealedAt: now
};
}
function traceFinalResponseConflictSession(): SessionRecord {
const now = new Date().toISOString();
return {
sessionId: "ses_trace_final_conflict",
threadId: "thr_trace_final_conflict",
status: "completed",
lastTraceId: "trc_trace_final_conflict",
updatedAt: now,
messageCount: 2,
firstUserMessagePreview: "trace final response authority separation",
turnSummary: { traceId: "trc_trace_final_conflict", status: "completed", running: false, terminal: true, sealedAt: now },
messages: [
{ id: "msg_trace_final_conflict_user", messageId: "msg_trace_final_conflict_user", role: "user", title: "用户", text: "trace final response authority separation", status: "sent", createdAt: now, sessionId: "ses_trace_final_conflict", threadId: "thr_trace_final_conflict", turnId: "turn_trace_final_conflict" },
{ id: "msg_trace_final_conflict_agent", messageId: "msg_trace_final_conflict_agent", role: "agent", title: "Code Agent", text: canonicalTraceFinalText, status: "completed", createdAt: now, updatedAt: now, sessionId: "ses_trace_final_conflict", threadId: "thr_trace_final_conflict", traceId: "trc_trace_final_conflict", turnId: "turn_trace_final_conflict", sealedAt: now, finalResponse: { text: canonicalTraceFinalText, status: "completed" }, runnerTrace: { traceId: "trc_trace_final_conflict", status: "completed", sessionId: "ses_trace_final_conflict", threadId: "thr_trace_final_conflict", events: [], eventCount: 1, fullTraceLoaded: false, hasMore: true } }
]
};
}
function noFinalRunningTrace(): JsonRecord {
const createdAt = new Date().toISOString();
return {
traceId: "trc_running",
status: "running",
sessionId: "ses_running",
threadId: "thr_running",
turnId: "turn_running",
events: [{ seq: 1, createdAt, label: "agentrun:backend:turn/running", type: "backend_status", status: "running" }],
eventCount: 1,
fullTraceLoaded: false,
hasMore: false
};
}
function completedNoFinalTrace(): JsonRecord {
const createdAt = new Date().toISOString();
const events = [
{ seq: 1, createdAt, label: "agentrun:backend:turn/running", type: "backend_status", status: "running" },
{ seq: 2, createdAt, label: "agentrun:backend:turn/completed", type: "backend_status", status: "completed", terminal: true }
];
return { traceId: "trc_running", status: "completed", sessionId: "ses_running", threadId: "thr_running", turnId: "turn_running", events, eventCount: events.length, fullTraceLoaded: true, hasMore: false };
}
function scrollFollowSession(): SessionRecord {
const now = new Date().toISOString();
const trace = scrollFollowTrace(90);
const history = Array.from({ length: 18 }, (_, index) => {
const seq = index + 1;
return seq % 2 === 0
? { id: `msg_scroll_history_agent_${seq}`, messageId: `msg_scroll_history_agent_${seq}`, role: "agent", title: "Code Agent", text: `历史回复 ${seq}\n\n用于撑开主工作区滚动高度`, status: "completed", createdAt: now, sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", turnId: `turn_scroll_history_${seq}` }
: { id: `msg_scroll_history_user_${seq}`, messageId: `msg_scroll_history_user_${seq}`, role: "user", title: "用户", text: `历史问题 ${seq}:保持主工作区可滚动。`, status: "sent", createdAt: now, sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", turnId: `turn_scroll_history_${seq}` };
});
const messages = [
...history,
{ id: "msg_scroll_follow_user", messageId: "msg_scroll_follow_user", role: "user", title: "用户", text: "scroll follow long trace probe", status: "sent", createdAt: now, sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", traceId: "trc_scroll_follow", turnId: "turn_scroll_follow" },
{ id: "msg_scroll_follow_agent", messageId: "msg_scroll_follow_agent", role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", traceId: "trc_scroll_follow", turnId: "turn_scroll_follow", runnerTrace: trace }
];
return {
sessionId: "ses_scroll_follow",
threadId: "thr_scroll_follow",
status: "running",
lastTraceId: "trc_scroll_follow",
startedAt: now,
updatedAt: now,
messageCount: messages.length,
firstUserMessagePreview: "scroll follow long trace probe",
messages
};
}
function scrollFollowTrace(count: number): JsonRecord {
const events = Array.from({ length: count }, (_, index) => scrollFollowEvent(index + 1));
return { traceId: "trc_scroll_follow", status: "running", sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", turnId: "turn_scroll_follow", events, eventCount: events.length, fullTraceLoaded: true, hasMore: false };
}
function scrollFollowEvent(seq: number): JsonRecord {
const createdAt = new Date(Date.parse("2026-06-18T18:00:00.000Z") + seq * 1000).toISOString();
if (seq % 5 === 0) {
return { seq, sourceSeq: seq, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "running", message: `滚动跟随采样 assistant row ${seq}\n\n- markdown ${seq}\n- append 后不能闪到顶部` };
}
return {
seq,
sourceSeq: seq,
createdAt,
label: "item/commandExecution:running",
type: "commandExecution",
status: "running",
itemId: `scroll-follow-${seq}`,
command: `printf 'scroll follow row ${seq}\\n'`,
stdout: `scroll-follow stdout ${seq}\nline ${seq} keeps the row tall enough for scroll sampling\n`
};
}
function appendScrollFollowEvents(count: number): JsonRecord {
if (state.scenarioId !== "scroll-follow-long-trace") return { ok: false, status: 409, error: { code: "scenario_mismatch", scenarioId: state.scenarioId } };
const trace = state.traces.trc_scroll_follow ?? scrollFollowTrace(0);
const events = Array.isArray(trace.events) ? [...trace.events as JsonRecord[]] : [];
const appended: JsonRecord[] = [];
for (let index = 0; index < count; index += 1) {
const seq = Number(events.at(-1)?.seq ?? events.length) + 1;
const event = scrollFollowEvent(seq);
events.push(event);
appended.push(event);
}
const nextTrace = { ...trace, status: "running", events, eventCount: events.length, fullTraceLoaded: true, hasMore: false };
state.traces.trc_scroll_follow = nextTrace;
const session = sessionById("ses_scroll_follow");
if (session) {
session.status = "running";
session.updatedAt = new Date().toISOString();
session.messages = (session.messages ?? []).map((message) => message.role === "agent" && message.traceId === "trc_scroll_follow" ? { ...message, status: "running", runnerTrace: nextTrace } : message);
}
for (const event of appended) {
broadcastSse("workbench.trace.event", { type: "trace.event", sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", traceId: "trc_scroll_follow", event, snapshot: nextTrace });
}
broadcastSse("workbench.turn.snapshot", { type: "turn.snapshot", sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", traceId: "trc_scroll_follow", turn: turnPayload("trc_scroll_follow") });
return { ok: true, status: "appended", appended: appended.length, eventCount: events.length };
}
function createManualSession(body: JsonRecord): SessionRecord {
const now = new Date().toISOString();
const token = state.scenarioId === "server-authoritative-create"
? "server_created"
: state.scenarioId === "create-while-route-loading"
? "created_while_running"
: state.scenarioId === "created-session-read-failure"
? "created_read_failure"
: Date.now().toString(36);
const sessionId = typeof body.sessionId === "string" && body.sessionId.trim() ? body.sessionId : `ses_${token}`;
const threadId = typeof body.threadId === "string" && body.threadId.trim() ? body.threadId : null;
return { sessionId, threadId, status: "active", startedAt: now, updatedAt: now, messageCount: 0, firstUserMessagePreview: null, messages: [] };
}
function hiddenBoundarySession(): SessionRecord {
const now = new Date().toISOString();
return { sessionId: "ses_cross_project", threadId: "thr_cross_project", hidden: true, status: "completed", lastTraceId: "trc_cross_project", startedAt: now, updatedAt: now, messageCount: 2, firstUserMessagePreview: "边界外 session 不应泄露", messages: [] };
}
function terminalEmptyTraceSession(): SessionRecord {
const now = new Date().toISOString();
return {
sessionId: "ses_terminal_empty",
threadId: "thr_terminal_empty",
status: "completed",
lastTraceId: "trc_terminal_empty",
startedAt: now,
updatedAt: now,
messageCount: 2,
firstUserMessagePreview: "完成态空 Trace 文案验证",
messages: [
{ id: "msg_terminal_empty_user", role: "user", title: "用户", text: "完成态空 Trace 文案验证", status: "sent", createdAt: now, sessionId: "ses_terminal_empty", threadId: "thr_terminal_empty", turnId: "turn_terminal_empty" },
{ id: "msg_terminal_empty_agent", role: "agent", title: "Code Agent", text: "终态空 Trace 已完成。", status: "completed", createdAt: now, sessionId: "ses_terminal_empty", threadId: "thr_terminal_empty", traceId: "trc_terminal_empty", turnId: "turn_terminal_empty", runnerTrace: terminalEmptyTrace() }
]
};
}
function terminalEmptyTrace(): JsonRecord {
return { traceId: "trc_terminal_empty", status: "completed", sessionId: "ses_terminal_empty", threadId: "thr_terminal_empty", events: [], eventCount: 0, fullTraceLoaded: true, hasMore: false, finalResponse: { text: "终态空 Trace 已完成。" } };
}
function legacyCanonicalSession(): SessionRecord {
const now = new Date().toISOString();
return {
sessionId: "ses_c5e1330558c94d8e",
conversationId: "cnv_c5e1330558c94d8e",
threadId: "thr_c5e1330558c94d8e",
status: "completed",
lastTraceId: "trc_40badc15523146c9",
startedAt: now,
updatedAt: now,
messageCount: 2,
firstUserMessagePreview: "legacy cnv deep link canonical smoke",
messages: [
{ id: "msg_c5_user", role: "user", title: "用户", text: "legacy cnv deep link canonical smoke", status: "sent", createdAt: now, sessionId: "ses_c5e1330558c94d8e", threadId: "thr_c5e1330558c94d8e", traceId: "trc_40badc15523146c9" },
{ id: "msg_c5_agent", role: "agent", title: "Code Agent", text: "已完成:新增 Python benchmark 脚本。", status: "completed", createdAt: now, sessionId: "ses_c5e1330558c94d8e", threadId: "thr_c5e1330558c94d8e", traceId: "trc_40badc15523146c9", runnerTrace: legacyCanonicalTrace() }
]
};
}
function legacyCanonicalTrace(): JsonRecord {
return {
traceId: "trc_40badc15523146c9",
status: "completed",
sessionId: "ses_c5e1330558c94d8e",
threadId: "thr_c5e1330558c94d8e",
events: [{ seq: 1, label: "agentrun:assistant:message", type: "assistant_message", status: "completed", terminal: true, final: true, message: "已完成:新增 Python benchmark 脚本。" }],
eventCount: 1,
fullTraceLoaded: true,
hasMore: false,
finalResponse: { text: "已完成:新增 Python benchmark 脚本。", status: "completed" }
};
}
function markdownFinalSession(): SessionRecord {
const now = new Date().toISOString();
return {
sessionId: "ses_markdown_final",
conversationId: "cnv_markdown_final",
threadId: "thr_markdown_final",
status: "completed",
lastTraceId: "trc_markdown_final",
startedAt: now,
updatedAt: now,
messageCount: 2,
firstUserMessagePreview: "render markdown final response",
messages: [
{ id: "msg_markdown_user", messageId: "msg_markdown_user", role: "user", title: "用户", text: "render markdown final response", status: "sent", createdAt: now, sessionId: "ses_markdown_final", threadId: "thr_markdown_final", traceId: "trc_markdown_final", turnId: "trc_markdown_final" },
{ id: "msg_markdown_agent", messageId: "msg_markdown_agent", role: "agent", title: "Code Agent", text: markdownFinalText, parts: [{ type: "text", text: markdownFinalText }], status: "completed", createdAt: now, updatedAt: now, sessionId: "ses_markdown_final", threadId: "thr_markdown_final", traceId: "trc_markdown_final", turnId: "trc_markdown_final", runnerTrace: markdownFinalTrace() }
]
};
}
function markdownFinalTrace(): JsonRecord {
const createdAt = new Date().toISOString();
const event = { seq: 1, sourceSeq: 88, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "completed", terminal: true, final: true, replyAuthority: true, message: markdownFinalText };
return {
traceId: "trc_markdown_final",
status: "completed",
sessionId: "ses_markdown_final",
threadId: "thr_markdown_final",
events: [event],
eventCount: 1,
fullTraceLoaded: true,
hasMore: false,
finalResponse: { text: markdownFinalText, status: "completed" }
};
}
function terminalAssistantFinalSession(): SessionRecord {
const now = new Date().toISOString();
const trace = terminalAssistantFinalTrace();
return {
sessionId: "ses_terminal_assistant_final",
conversationId: "cnv_terminal_assistant_final",
threadId: "thr_terminal_assistant_final",
status: "completed",
lastTraceId: "trc_terminal_assistant_final",
startedAt: now,
updatedAt: now,
messageCount: 2,
firstUserMessagePreview: "再把lua加入对比测试",
messages: [
{ id: "msg_terminal_assistant_user", messageId: "msg_terminal_assistant_user", role: "user", title: "用户", text: "再把lua加入对比测试", status: "sent", createdAt: now, sessionId: "ses_terminal_assistant_final", threadId: "thr_terminal_assistant_final", traceId: "trc_terminal_assistant_final", turnId: "trc_terminal_assistant_final" },
{ id: "msg_terminal_assistant_agent", messageId: "msg_terminal_assistant_agent", role: "agent", title: "Code Agent", text: terminalAssistantFinalText, parts: [{ type: "text", text: terminalAssistantFinalText, status: "completed" }], status: "completed", createdAt: now, updatedAt: now, sessionId: "ses_terminal_assistant_final", threadId: "thr_terminal_assistant_final", traceId: "trc_terminal_assistant_final", turnId: "trc_terminal_assistant_final", runnerTrace: trace, finalResponse: { text: terminalAssistantFinalText, status: "completed" } }
]
};
}
function terminalAssistantFinalTrace(): JsonRecord {
const createdAt = new Date().toISOString();
const events = [
{ seq: 1, sourceSeq: 21, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "running", replyAuthority: false, final: false, terminal: false, message: "现在写 Lua 基准测试脚本。" },
{ seq: 2, sourceSeq: 28, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "completed", replyAuthority: true, final: true, terminal: true, message: terminalAssistantFinalText },
{ seq: 3, sourceSeq: 29, createdAt, label: "agentrun:terminal:completed", type: "result", status: "completed", terminal: true, message: "AgentRun command completed." }
];
return {
traceId: "trc_terminal_assistant_final",
status: "completed",
sessionId: "ses_terminal_assistant_final",
threadId: "thr_terminal_assistant_final",
events,
eventCount: events.length,
fullTraceLoaded: true,
hasMore: false,
assistantText: terminalAssistantFinalText,
finalResponse: { text: terminalAssistantFinalText, status: "completed" }
};
}
function manyRailSession(index: number): SessionRecord {
const id = String(index).padStart(2, "0");
const now = new Date(Date.now() - (index + 1) * 1000).toISOString();
return { sessionId: `ses_many_${id}`, threadId: `thr_many_${id}`, status: "completed", lastTraceId: `trc_many_${id}`, startedAt: now, updatedAt: now, messageCount: 0, firstUserMessagePreview: `历史 session ${id}`, messages: [] };
}
function staleDetailSession(): SessionRecord {
const now = new Date().toISOString();
return { sessionId: "ses_stale_404", threadId: "thr_stale_404", status: "active", startedAt: now, updatedAt: now, messageCount: 0, firstUserMessagePreview: "已失效的列表项", messages: [] };
}
function emptySession(): SessionRecord {
const now = new Date().toISOString();
return { sessionId: "ses_empty", threadId: "thr_empty", status: "active", startedAt: now, updatedAt: now, messageCount: 0, firstUserMessagePreview: "空白会话", messages: [] };
}
function staleEmptyTtlSession(): SessionRecord {
const at = "2026-06-18T16:00:00.000Z";
return { sessionId: "ses_empty_ttl", threadId: "thr_empty_ttl", status: "idle", startedAt: at, updatedAt: at, messageCount: 0, firstUserMessagePreview: null, messages: [] };
}
function freshEmptyTtlSession(): SessionRecord {
const at = "2026-06-18T16:15:30.000Z";
return { sessionId: "ses_empty_fresh", threadId: "thr_empty_fresh", status: "idle", startedAt: at, updatedAt: at, messageCount: 0, firstUserMessagePreview: null, messages: [] };
}
function staleMessagedTtlSession(): SessionRecord {
const at = "2026-06-18T15:50:00.000Z";
return {
sessionId: "ses_empty_ttl_has_message",
threadId: "thr_empty_ttl_has_message",
status: "completed",
startedAt: at,
updatedAt: at,
messageCount: 2,
firstUserMessagePreview: "超过 TTL 但已有消息,不能被 GC",
messages: [
{ id: "msg_empty_ttl_user", role: "user", title: "用户", text: "超过 TTL 但已有消息,不能被 GC", status: "sent", createdAt: at, sessionId: "ses_empty_ttl_has_message", threadId: "thr_empty_ttl_has_message" },
{ id: "msg_empty_ttl_agent", role: "agent", title: "Code Agent", text: "保留已有消息 session。", status: "completed", createdAt: at, sessionId: "ses_empty_ttl_has_message", threadId: "thr_empty_ttl_has_message" }
]
};
}
function archivedDeletedSession(): SessionRecord {
const now = new Date().toISOString();
return { sessionId: "ses_deleted", threadId: "thr_deleted", status: "archived", startedAt: now, updatedAt: now, messageCount: 0, firstUserMessagePreview: "已删除 session", messages: [] };
}
function submitSplitSession(): SessionRecord {
const now = new Date().toISOString();
return {
sessionId: "ses_submit_split",
threadId: "thr_submit_split",
status: "idle",
lastTraceId: "trc_submit_split",
startedAt: now,
updatedAt: now,
messageCount: 2,
firstUserMessagePreview: "workbench submit race probe redacted: 请只回复 OK。",
messages: [
{ id: "msg_submit_split_user", messageId: "msg_submit_split_user", role: "user", title: "用户", text: "", status: "sent", createdAt: now, sessionId: "ses_submit_split", threadId: "thr_submit_split", traceId: "trc_submit_split", turnId: "turn_submit_split" },
{ id: "msg_submit_split_agent", messageId: "msg_submit_split_agent", role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId: "ses_submit_split", threadId: "thr_submit_split", traceId: "trc_submit_split", turnId: "turn_submit_split", runnerTrace: { traceId: "trc_submit_split", status: "running", sessionId: "ses_submit_split", threadId: "thr_submit_split", events: [], eventCount: 0, fullTraceLoaded: false, hasMore: false } }
]
};
}
function submitSplitTrace(): JsonRecord {
return { traceId: "trc_submit_split", status: "running", sessionId: "ses_submit_split", threadId: "thr_submit_split", turnId: "turn_submit_split", events: [], eventCount: 0, fullTraceLoaded: false, hasMore: false };
}
function crossSessionLateA(): SessionRecord {
const now = new Date().toISOString();
return {
sessionId: "ses_late_A",
threadId: "thr_late_A",
status: "completed",
lastTraceId: "trc_late_A",
startedAt: now,
updatedAt: now,
messageCount: 2,
firstUserMessagePreview: "写一个python脚本测试性能",
messages: [
{ id: "msg_late_A_user", messageId: "msg_late_A_user", role: "user", title: "用户", text: "写一个python脚本测试性能", status: "sent", createdAt: now, sessionId: "ses_late_A", threadId: "thr_late_A", traceId: "trc_late_A", turnId: "turn_late_A" },
{ id: "msg_late_A_agent", messageId: "msg_late_A_agent", role: "agent", title: "Code Agent", text: "已写好 perf_test.py,脚本可用。", status: "completed", createdAt: now, sessionId: "ses_late_A", threadId: "thr_late_A", traceId: "trc_late_A", turnId: "turn_late_A", runnerTrace: crossSessionLateTraceA() }
]
};
}
function crossSessionLateB(): SessionRecord {
const now = new Date().toISOString();
return {
sessionId: "ses_late_B",
threadId: "thr_late_B",
status: "active",
lastTraceId: "trc_late_A",
startedAt: now,
updatedAt: now,
messageCount: 2,
firstUserMessagePreview: "B session waiting",
messages: [
{ id: "msg_late_B_user", messageId: "msg_late_B_user", role: "user", title: "用户", text: "B session waiting", status: "sent", createdAt: now, sessionId: "ses_late_B", threadId: "thr_late_B", traceId: "trc_late_A", turnId: "turn_late_B" },
{ id: "msg_late_B_agent", messageId: "msg_late_B_agent", role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId: "ses_late_B", threadId: "thr_late_B", traceId: "trc_late_A", turnId: "turn_late_B", runnerTrace: { traceId: "trc_late_A", status: "running", sessionId: "ses_late_B", threadId: "thr_late_B", events: [], eventCount: 0, fullTraceLoaded: false, hasMore: false } }
]
};
}
function crossSessionLateTraceA(): JsonRecord {
const now = new Date().toISOString();
const finalText = "已写好 perf_test.py,脚本可用。";
const event = { seq: 1, createdAt: now, label: "agentrun:assistant:message", type: "assistant_message", status: "completed", replyAuthority: true, final: true, message: finalText, terminal: true };
return { traceId: "trc_late_A", status: "completed", sessionId: "ses_late_A", threadId: "thr_late_A", turnId: "turn_late_A", events: [event], eventCount: 1, fullTraceLoaded: true, hasMore: false, finalResponse: { text: finalText, status: "completed" }, assistantText: finalText };
}
function sessionDetailDelayMs(sessionId: string): number {
if (state.scenarioId === "cross-session-late-events" && sessionId === "ses_late_A") return 900;
if (state.scenarioId === "create-while-route-loading" && (sessionId === "ses_running" || sessionId === "ses_created_while_running")) return 4_000;
return state.sessionDetailDelayMs;
}
function acceptChatTurn(body: JsonRecord): JsonRecord {
const sessionId = typeof body.sessionId === "string" && body.sessionId.trim() ? body.sessionId : state.selectedSessionId;
const session = sessionById(sessionId) ?? createManualSession({ sessionId });
if (!state.sessions.includes(session)) state.sessions.unshift(session);
const threadId = typeof body.threadId === "string" && body.threadId.trim() ? body.threadId : null;
const traceId = state.scenarioId === "live-rest-backfill-without-terminal-sse"
? "trc_live_backfill"
: typeof body.traceId === "string" && body.traceId.trim() ? body.traceId : `trc_${Date.now().toString(16)}`;
const message = typeof body.message === "string" ? body.message : "";
const now = new Date().toISOString();
session.status = "running";
session.lastTraceId = traceId;
session.updatedAt = now;
session.firstUserMessagePreview = session.firstUserMessagePreview ?? message;
session.messageCount = (session.messages?.length ?? 0) + 2;
session.messages = [
...(session.messages ?? []),
{ id: `msg_${traceId}_user`, role: "user", title: "用户", text: message, status: "sent", createdAt: now, sessionId, threadId, traceId },
{ id: `msg_${traceId}_agent`, role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId, threadId, traceId, runnerTrace: { traceId, status: "running", sessionId, threadId, events: [], eventCount: 0, fullTraceLoaded: false, hasMore: false } }
];
if (state.scenarioId === "live-rest-backfill-without-terminal-sse") {
state.liveBackfillTraceId = traceId;
state.liveBackfillReadyAtMs = Date.now() + 2_000;
state.traces[traceId] = liveBackfillEarlyTrace(sessionId, threadId, traceId);
scheduleLiveBackfillProjection(sessionId, threadId, traceId, state.liveBackfillReadyAtMs);
} else {
state.traces[traceId] = { traceId, status: "running", sessionId, threadId, events: [], eventCount: 0, fullTraceLoaded: false, hasMore: false };
}
return { status: "running", accepted: true, running: true, terminal: false, traceId, sessionId, threadId, turnId: traceId };
}
function liveBackfillEarlyTrace(sessionId: string, threadId: string | null, traceId: string): JsonRecord {
const createdAt = new Date().toISOString();
const agentRun = liveBackfillAgentRun("pending", null, 4);
return {
traceId,
status: "running",
running: true,
terminal: false,
sessionId,
threadId,
agentRun,
events: [
{ seq: 1, sourceSeq: 1, createdAt, label: "agentrun:request:accepted", type: "backend_status", status: "running", payload: { commandId: agentRun.commandId } },
{ seq: 2, sourceSeq: 2, createdAt, label: "agentrun:run:created", type: "backend_status", status: "running", payload: { runId: agentRun.runId, runStatus: agentRun.runStatus } },
{ seq: 3, sourceSeq: 3, createdAt, label: "agentrun:command:created", type: "backend_status", status: "running", payload: { commandId: agentRun.commandId, commandState: agentRun.commandState } },
{ seq: 4, sourceSeq: 4, createdAt, label: "agentrun:runner-job:created", type: "backend_status", status: "running", payload: { commandId: agentRun.commandId, jobName: agentRun.jobName, namespace: agentRun.namespace } }
],
eventCount: 4,
fullTraceLoaded: true,
hasMore: false,
traceSummary: { source: "agentrun-events", agentRun, valuesPrinted: false }
};
}
function liveBackfillCompletedTrace(sessionId: string, threadId: string | null, traceId: string): JsonRecord {
const createdAt = new Date().toISOString();
const finalText = "fake AgentRun completed after detail backfill without terminal SSE.";
const agentRun = liveBackfillAgentRun("completed", "completed", 23);
const events = [
...(liveBackfillEarlyTrace(sessionId, threadId, traceId).events as JsonRecord[]),
{ seq: 5, sourceSeq: 21, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "completed", message: finalText, payload: { commandId: agentRun.commandId } },
{ seq: 6, sourceSeq: 22, createdAt, label: "item/commandExecution:completed", type: "commandExecution", status: "completed", stdout: "OK\n", payload: { commandId: agentRun.commandId, exitCode: 0 } },
{ seq: 7, sourceSeq: 23, createdAt, label: "agentrun:backend:turn/completed", type: "backend_status", status: "completed", terminal: true, payload: { commandId: agentRun.commandId, phase: "command-terminal", terminalStatus: "completed" } }
];
return {
traceId,
status: "completed",
running: false,
terminal: true,
sessionId,
threadId,
agentRun,
events,
eventCount: events.length,
fullTraceLoaded: true,
hasMore: false,
finalResponse: { text: finalText, status: "completed" },
traceSummary: { source: "agentrun-command-result", terminalStatus: "completed", agentRun, valuesPrinted: false }
};
}
function liveBackfillAgentRun(commandState: string, terminalStatus: string | null, lastSeq: number): JsonRecord {
return {
adapter: "agentrun-v01",
runId: "run_live_backfill_issue1555",
commandId: "cmd_live_backfill_issue1555",
status: commandState,
runStatus: "claimed",
commandState,
terminalStatus,
runnerStatus: "running",
namespace: "agentrun-v02",
jobName: "agentrun-v01-runner-live-backfill-issue1555",
lastSeq,
valuesPrinted: false
};
}
function scheduleLiveBackfillProjection(sessionId: string, threadId: string | null, traceId: string, readyAtMs: number): void {
const scenarioId = state.scenarioId;
setTimeout(() => {
if (state.scenarioId !== scenarioId || state.liveBackfillTraceId !== traceId) return;
commitLiveBackfillProjection(sessionId, threadId, traceId);
}, Math.max(0, readyAtMs - Date.now()));
}
function commitLiveBackfillProjection(sessionId: string, threadId: string | null, traceId: string): void {
const completed = liveBackfillCompletedTrace(sessionId, threadId, traceId);
const finalText = typeof (completed.finalResponse as JsonRecord | undefined)?.text === "string" ? String((completed.finalResponse as JsonRecord).text) : "";
state.traces[traceId] = completed;
const session = sessionById(sessionId);
if (!session) return;
session.status = "completed";
session.updatedAt = new Date().toISOString();
session.messages = (session.messages ?? []).map((message) => {
if (message.role !== "agent" || message.traceId !== traceId) return message;
return { ...message, text: finalText, status: "completed", runnerTrace: completed };
});
}
function sessionSummary(session: SessionRecord): SessionRecord {
const { messages: _messages, hidden: _hidden, ...rest } = session;
const status = typeof rest.status === "string" ? rest.status : "unknown";
return { ...rest, status, running: isRunningStatus(status), terminal: isTerminalStatus(status) } as SessionRecord;
}
function isRunningStatus(status: string): boolean {
return ["active", "accepted", "pending", "running"].includes(status);
}
function isTerminalStatus(status: string): boolean {
return ["blocked", "canceled", "cancelled", "completed", "failed", "timeout"].includes(status);
}
function workbenchSessionListPayload(url: URL): JsonRecord {
if (url.searchParams.has("projectId") || url.searchParams.has("workspaceId")) return { ok: false, status: 400, error: { code: "workbench_authority_removed" } };
const includeRouteId = url.searchParams.get("includeSessionId") || "";
const includeSessionId = includeRouteId ? canonicalSessionId(includeRouteId) : "";
const limit = boundedPageLimit(url.searchParams.get("limit"));
const offset = cursorOffset(url.searchParams.get("cursor") || url.searchParams.get("after"));
const visible = state.sessions.filter((item) => !item.hidden && (item.status !== "archived" || item.sessionId === includeSessionId));
const authorityVisible = state.scenarioId === "create-while-route-loading" && includeSessionId === "ses_running"
? visible.filter((item) => item.sessionId !== "ses_created_while_running")
: visible;
const listed = state.listOmitSelected && includeSessionId ? authorityVisible.filter((item) => item.sessionId !== includeSessionId) : authorityVisible;
const page = listed.slice(offset, offset + limit);
const included = includeSessionId && !page.some((session) => session.sessionId === includeSessionId) ? listed.find((session) => session.sessionId === includeSessionId) ?? null : null;
const summaries = [...(included ? [included] : []), ...page].map((session) => sessionSummary(session));
const hasMore = offset + limit < listed.length;
return { ok: true, status: "succeeded", contractVersion: "workbench-sessions-v1", sessions: summaries, count: summaries.length, total: listed.length, cursor: offset > 0 ? cursorFromOffset(offset) : null, hasMore, nextCursor: hasMore ? cursorFromOffset(offset + limit) : null };
}
function boundedPageLimit(value: string | null): number {
const parsed = Number.parseInt(value ?? "", 10);
return Math.min(100, Math.max(1, Number.isInteger(parsed) && parsed > 0 ? parsed : 50));
}
function cursorOffset(value: string | null): number {
const text = typeof value === "string" ? value.trim() : "";
if (!text) return 0;
if (text.startsWith("idx:")) return Math.max(0, Number.parseInt(text.slice(4), 10) || 0);
return Math.max(0, Number.parseInt(text, 10) || 0);
}
function cursorFromOffset(offset: number): string {
return `idx:${Math.max(0, Math.trunc(offset))}`;
}
function workbenchSessionMessagesPayload(session: SessionRecord, url: URL): JsonRecord {
const messages = Array.isArray(session.messages) ? session.messages : [];
const requestedLimit = Number(url.searchParams.get("limit") ?? messages.length);
const limit = Math.max(1, Number.isFinite(requestedLimit) ? Math.trunc(requestedLimit) : messages.length || 100);
const page = messages.slice(0, limit);
return { ok: true, status: "succeeded", sessionId: session.sessionId, messages: page, count: page.length, total: messages.length, hasMore: messages.length > page.length };
}
function sessionById(id: string): SessionRecord | null {
return state.sessions.find((session) => session.sessionId === id) ?? null;
}
function canonicalSessionId(id: string): string {
const text = id.trim();
if (!text.startsWith("cnv_")) return text;
const conversation = state.sessions.find((session) => session.conversationId === text);
return conversation?.sessionId ?? `ses_${text.slice("cnv_".length)}`;
}
function visibleSessionById(id: string, options: { includeArchived?: boolean } = {}): SessionRecord | null {
const session = sessionById(id);
if (!session || session.hidden) return null;
if (session.status === "archived" && !options.includeArchived) return null;
return session;
}
function sessionPayload(sessionId: string): JsonRecord {
const session = sessionById(sessionId);
if (state.scenarioId === "terminal-turn-stale-session-active" && sessionId === "ses_completed") return { sessionId, status: "active", lastTraceId: "trc_completed", updatedAt: new Date().toISOString() };
return { sessionId, status: session?.status ?? "unknown", lastTraceId: session?.lastTraceId ?? null, updatedAt: new Date().toISOString() };
}
function turnPayload(traceId: string): JsonRecord {
if (state.scenarioId === "live-rest-backfill-without-terminal-sse" && traceId === state.liveBackfillTraceId) {
const session = state.sessions.find((item) => item.lastTraceId === traceId) ?? state.sessions[0];
const sessionId = session?.sessionId ?? state.selectedSessionId;
const threadId = typeof session?.threadId === "string" ? session.threadId : null;
return state.traces[traceId] ?? liveBackfillEarlyTrace(sessionId, threadId, traceId);
}
const trace = state.traces[traceId] ?? { traceId, status: "unknown", events: [] };
if (state.scenarioId === "tool-completed-projection-running" && traceId === "trc_running") return { ...trace, traceId, status: "running", running: true, terminal: false, projectionStatus: "projecting", trace: { status: trace.status, eventCount: trace.eventCount ?? 0 } };
if (state.scenarioId === "terminal-turn-stale-session-active" && traceId === "trc_completed") return { ...trace, traceId, status: "active", running: true, terminal: false, trace: { status: "completed", eventCount: trace.eventCount ?? 0 } };
const status = String(trace.status ?? "unknown");
return { ...trace, traceId, status, running: ["running", "pending", "accepted"].includes(status), terminal: ["completed", "failed", "blocked", "timeout", "canceled"].includes(status) };
}
function workbenchTurnPayload(traceId: string): JsonRecord {
const turn = turnPayload(traceId);
return { ok: true, status: "ok", contractVersion: "workbench-read-model-v1", turn, ...projectionEnvelope(turn) };
}
function tracePayload(traceId: string, url: URL): JsonRecord {
const turn = turnPayload(traceId);
const events = Array.isArray(turn.events) ? turn.events as JsonRecord[] : [];
const afterProjectedSeq = traceAfterProjectedSeq(url);
const requestedLimit = Number(url.searchParams.get("limit") ?? events.length);
const limit = Math.max(1, Number.isFinite(requestedLimit) ? Math.trunc(requestedLimit) : events.length || 100);
const indexedEvents = events.map((event, index) => {
const projectedSeq = nonNegativeInteger(event.projectedSeq ?? event.seq, index + 1);
return { event: { ...event, seq: projectedSeq, projectedSeq }, projectedSeq };
});
const filtered = afterProjectedSeq > 0 ? indexedEvents.filter((item) => item.projectedSeq > afterProjectedSeq) : indexedEvents;
const pageRecords = filtered.slice(0, limit);
const page = pageRecords.map((item) => item.event);
const firstProjectedSeq = pageRecords.length > 0 ? pageRecords[0]?.projectedSeq ?? null : null;
const lastProjectedSeq = pageRecords.length > 0 ? pageRecords.at(-1)?.projectedSeq ?? null : null;
const hasMore = filtered.length > page.length;
return { ...turn, events: page, eventCount: events.length, hasMore, fullTraceLoaded: !hasMore, nextProjectedSeq: page.length > 0 ? lastProjectedSeq : afterProjectedSeq, nextCursor: hasMore && lastProjectedSeq ? `projected:${lastProjectedSeq}` : null, range: { afterProjectedSeq, fromProjectedSeq: firstProjectedSeq, toProjectedSeq: lastProjectedSeq, limit, returned: page.length, total: events.length } };
}
function traceAfterProjectedSeq(url: URL): number {
const cursor = url.searchParams.get("cursor") ?? "";
if (cursor.startsWith("projected:")) return nonNegativeInteger(cursor.slice("projected:".length), 0);
return nonNegativeInteger(url.searchParams.get("afterProjectedSeq"), 0);
}
function workbenchTracePayload(traceId: string, url: URL): JsonRecord {
const payload = tracePayload(traceId, url);
if (state.scenarioId === "tool-completed-projection-running" && traceId === "trc_running") {
return { ok: true, status: "ok", contractVersion: "workbench-read-model-v1", traceId, sessionId: payload.sessionId ?? null, threadId: payload.threadId ?? null, traceStatus: "completed", timing: payload.timing, startedAt: payload.startedAt, lastEventAt: payload.lastEventAt, finishedAt: payload.finishedAt, durationMs: payload.durationMs, events: payload.events, eventCount: payload.eventCount, hasMore: payload.hasMore, nextProjectedSeq: payload.nextProjectedSeq, nextCursor: payload.nextCursor, range: payload.range, fullTraceLoaded: payload.fullTraceLoaded, projectionStatus: "projecting", terminalEvidence: null, finalResponse: null, traceSummary: payload.traceSummary, retention: payload.retention };
}
return { ok: true, status: "ok", contractVersion: "workbench-read-model-v1", traceId, sessionId: payload.sessionId ?? null, threadId: payload.threadId ?? null, traceStatus: payload.status, timing: payload.timing, startedAt: payload.startedAt, lastEventAt: payload.lastEventAt, finishedAt: payload.finishedAt, durationMs: payload.durationMs, events: payload.events, eventCount: payload.eventCount, hasMore: payload.hasMore, nextProjectedSeq: payload.nextProjectedSeq, nextCursor: payload.nextCursor, range: payload.range, fullTraceLoaded: payload.fullTraceLoaded, terminalEvidence: payload.terminalEvidence, finalResponse: payload.finalResponse, traceSummary: payload.traceSummary, retention: payload.retention, ...projectionEnvelope(payload) };
}
function projectionEnvelope(payload: JsonRecord): JsonRecord {
const projection = payload.projection && typeof payload.projection === "object" ? payload.projection as JsonRecord : null;
if (!projection) return {};
return {
projection,
projectionStatus: projection.projectionStatus,
projectionHealth: projection.projectionHealth,
lastProjectedSeq: projection.lastProjectedSeq,
sourceRunId: projection.sourceRunId,
sourceCommandId: projection.sourceCommandId,
staleMs: projection.staleMs,
blocker: projection.blocker
};
}
function sse(request: IncomingMessage, response: ServerResponse, url: URL): void {
response.writeHead(200, { "content-type": "text/event-stream; charset=utf-8", "cache-control": "no-cache", connection: "keep-alive" });
sseClients.add(response);
request.on("close", () => sseClients.delete(response));
writeSse(response, "workbench.connected", { type: "connected", sessionId: url.searchParams.get("sessionId") });
if (state.scenarioId === "projection-sse-error") {
const scenarioId = state.scenarioId;
setTimeout(() => {
if (state.scenarioId !== scenarioId) return;
const projection = projectionDiagnostic({ traceId: "trc_projection_sse_error", code: "workbench_sse_projection_error", message: "SSE 投影事件异常,实时状态暂不可见。", category: "realtime-error", layer: "workbench-sse", runId: "run_projection_sse_error", commandId: "cmd_projection_sse_error" });
writeSse(response, "workbench.error", { type: "error", sessionId: "ses_projection_sse_error", threadId: "thr_projection_sse_error", traceId: "trc_projection_sse_error", projection, ...projectionEnvelope({ projection }), error: projection.blocker });
}, 350);
}
if (state.scenarioId === "cross-session-late-events") {
const scenarioId = state.scenarioId;
setTimeout(() => {
if (state.scenarioId !== scenarioId) return;
const trace = crossSessionLateTraceA();
const event = (trace.events as JsonRecord[])[0];
writeSse(response, "workbench.trace.event", { type: "trace.event", sessionId: "ses_late_A", threadId: "thr_late_A", traceId: "trc_late_A", event, snapshot: trace });
writeSse(response, "workbench.turn.snapshot", { type: "turn.snapshot", sessionId: "ses_late_A", threadId: "thr_late_A", traceId: "trc_late_A", turn: trace });
}, 650);
return;
}
if (!state.terminalScript) return;
const scenarioId = state.scenarioId;
setTimeout(() => {
if (state.scenarioId !== scenarioId) return;
if (state.scenarioId === "terminal-canceled-late-timing") {
const trace = applyTerminalCanceledLateTiming(12_000, "2026-06-17T09:39:12.000Z");
const event = Array.isArray(trace?.events) ? trace.events.at(-1) as JsonRecord : null;
if (event) writeSse(response, "workbench.trace.event", { type: "trace.event", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", event, snapshot: trace });
const message = runningAgentMessageSnapshot();
if (message) writeSse(response, "workbench.message.snapshot", { type: "message.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", message });
writeSse(response, "workbench.turn.snapshot", { type: "turn.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", turn: turnPayload("trc_running") });
setTimeout(() => {
if (state.scenarioId !== scenarioId) return;
applyTerminalCanceledLateTiming(14_000, "2026-06-17T09:39:14.000Z");
const late = runningAgentMessageSnapshot();
if (late) writeSse(response, "workbench.message.snapshot", { type: "message.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", message: late });
writeSse(response, "workbench.turn.snapshot", { type: "turn.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", turn: turnPayload("trc_running") });
}, 650);
return;
}
if (state.scenarioId === "terminal-completed-no-final-response") {
const trace = completedNoFinalTrace();
const event = (trace.events as JsonRecord[]).at(-1) ?? { status: "completed", terminal: true };
writeSse(response, "workbench.trace.event", { type: "trace.event", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", event, snapshot: trace });
finishRunningNoFinalResponse(trace);
const message = runningAgentMessageSnapshot();
if (message) writeSse(response, "workbench.message.snapshot", { type: "message.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", message });
writeSse(response, "workbench.turn.snapshot", { type: "turn.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", turn: turnPayload("trc_running") });
return;
}
const terminalStatus = state.terminalFailureScript ? "failed" : "completed";
const terminalText = state.terminalFailureScript ? "恢复后失败:缺少受控依赖。" : state.scenarioId === "progress-only-final-response" ? finalOnlyText : "事件重放后完成。";
const event = { seq: 3, createdAt: new Date().toISOString(), label: "agentrun:assistant:message", type: "assistant_message", status: terminalStatus, replyAuthority: true, final: true, message: terminalText, terminal: true };
writeSse(response, "workbench.trace.event", { type: "trace.event", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", event, snapshot: { traceId: "trc_running", sessionId: "ses_running", threadId: "thr_running", status: terminalStatus, events: [event], eventCount: 3, fullTraceLoaded: true, finalResponse: { text: terminalText, status: terminalStatus } } });
finishRunningSession(terminalStatus, terminalText);
const message = runningAgentMessageSnapshot();
if (message) writeSse(response, "workbench.message.snapshot", { type: "message.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", message });
writeSse(response, "workbench.turn.snapshot", { type: "turn.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", turn: turnPayload("trc_running") });
}, state.scenarioId === "progress-only-final-response" ? 5_000 : state.scenarioId === "event-replay" ? 1_500 : 350);
}
async function debugFakeSse(request: IncomingMessage, response: ServerResponse, url: URL, method: string): Promise<void> {
const suffix = url.pathname.replace(/^\/v1\/workbench\/debug\/fake-sse/u, "");
if (suffix === "" || suffix === "/sequences") return json(response, 200, debugFakeSsePayload());
if (suffix === "/events") {
response.writeHead(200, { "content-type": "text/event-stream; charset=utf-8", "cache-control": "no-cache", connection: "keep-alive" });
debugSseClients.add(response);
request.on("close", () => debugSseClients.delete(response));
return writeSse(response, "workbench.connected", { type: "connected", queue: debugFakeSseQueueSummary() });
}
if (method !== "POST") return json(response, 405, { ok: false, error: { code: "method_not_allowed" } });
if (suffix === "/reset") {
debugFakeSseQueue = createDebugFakeSseQueue();
return json(response, 200, debugFakeSsePayload());
}
if (suffix === "/append") {
const body = await readJson(request);
const events = Array.isArray(body.events) ? body.events.filter((event): event is JsonRecord => Boolean(event && typeof event === "object" && !Array.isArray(event))) : [];
debugFakeSseQueue.events.push(...events.map((event, index) => debugRealtimeEvent(event, debugFakeSseQueue.events.length + index + 1)));
return json(response, 200, { ok: true, appended: events.length, queue: debugFakeSseQueueSummary() });
}
if (suffix === "/next") return json(response, 200, { ok: true, delivered: debugDeliverNext(), queue: debugFakeSseQueueSummary() });
if (suffix === "/run") {
let count = 0;
while (debugFakeSseQueue.cursor < debugFakeSseQueue.events.length) {
debugDeliverNext();
count += 1;
}
return json(response, 200, { ok: true, delivered: { ok: true, count }, queue: debugFakeSseQueueSummary() });
}
return json(response, 404, { ok: false, error: { code: "debug_fake_sse_route_not_found" } });
}
function debugDeliverNext(): JsonRecord {
const event = debugFakeSseQueue.events[debugFakeSseQueue.cursor] as JsonRecord | undefined;
if (!event) return { ok: false, reason: "queue-empty", deliveredTo: 0 };
debugFakeSseQueue.cursor += 1;
const eventName = debugEventName(event);
for (const client of Array.from(debugSseClients)) writeSse(client, eventName, event);
return { ok: true, eventName, eventType: event.type, traceId: event.traceId, deliveredTo: debugSseClients.size };
}
function debugFakeSsePayload(): JsonRecord {
return { ok: true, contractVersion: "workbench-debug-fake-sse-v1", sequences: [{ sequenceId: "trace-card-basic", label: "Trace card basic", eventCount: debugFakeSseQueue.events.length }], queue: debugFakeSseQueueSummary() };
}
function debugFakeSseQueueSummary(): JsonRecord {
return { queueId: "trace-card", sequenceId: "trace-card-basic", cursor: debugFakeSseQueue.cursor, eventCount: debugFakeSseQueue.events.length, remaining: Math.max(0, debugFakeSseQueue.events.length - debugFakeSseQueue.cursor), connectedClients: debugSseClients.size, updatedAt: new Date().toISOString() };
}
function createDebugFakeSseQueue(): { cursor: number; events: JsonRecord[] } {
const sessionId = "ses_debug_fake_sse";
const threadId = "thr_debug_fake_sse";
const traceId = "trc_debug_fake_sse";
const finalText = "Fake SSE Trace 卡片渲染完成。";
const events = [
{ traceId, projectedSeq: 1, createdAt: "2026-07-09T08:00:01.000Z", label: "assistant:message", type: "assistant_message", status: "running", message: "读取 Workbench 组件和 Trace 渲染上下文。", elapsedMs: 1000 },
{ traceId, projectedSeq: 2, createdAt: "2026-07-09T08:00:03.000Z", label: "agentrun:tool:completed", type: "tool_call", status: "completed", toolName: "commandExecution", itemId: "tool_debug_rg", command: "rg -n \"TraceTimeline|message-card\" web/hwlab-cloud-web/src", stdoutSummary: "TraceTimeline.vue\\nConversationPanel.vue\\nWorkbenchMessageCard.vue", exitCode: 0, elapsedMs: 3000 },
{ traceId, projectedSeq: 3, createdAt: "2026-07-09T08:00:05.000Z", label: "assistant:message", type: "assistant_message", status: "running", message: "Trace 卡片已收到 tool 事件,继续等待 terminal snapshot。", elapsedMs: 5000 },
{ traceId, projectedSeq: 4, createdAt: "2026-07-09T08:00:07.000Z", label: "assistant:completed", type: "assistant_message", status: "completed", message: finalText, final: true, terminal: true, replyAuthority: true, elapsedMs: 7000 },
{ traceId, projectedSeq: 5, createdAt: "2026-07-09T08:00:07.500Z", label: "turn:completed", type: "completion", status: "completed", terminal: true, elapsedMs: 7500 }
];
return {
cursor: 0,
events: [
debugRealtimeEvent({ type: "message.snapshot", sessionId, threadId, traceId, message: debugAgentMessage(sessionId, threadId, traceId, "running", []) }, 1),
...events.slice(0, 3).map((event, index) => debugRealtimeEvent({ type: "trace.event", sessionId, threadId, traceId, event, snapshot: debugTraceSnapshot(sessionId, threadId, traceId, "running", events.slice(0, index + 1)) }, index + 2)),
debugRealtimeEvent({ type: "trace.event", sessionId, threadId, traceId, event: events[3], snapshot: debugTraceSnapshot(sessionId, threadId, traceId, "completed", events.slice(0, 4)) }, 5),
debugRealtimeEvent({ type: "message.snapshot", sessionId, threadId, traceId, message: debugAgentMessage(sessionId, threadId, traceId, "completed", events) }, 6)
]
};
}
function debugRealtimeEvent(event: JsonRecord, version: number): JsonRecord {
const type = String(event.type ?? "trace.event");
const traceId = String(event.traceId ?? "trc_debug_fake_sse");
const message = event.message && typeof event.message === "object" ? event.message as JsonRecord : null;
return {
contractVersion: "workbench-events-v1",
realtimeAuthority: "workbench-realtime-authority-v2",
sessionId: event.sessionId ?? "ses_debug_fake_sse",
threadId: event.threadId ?? "thr_debug_fake_sse",
traceId,
...event,
type,
entity: event.entity ?? { family: type === "message.snapshot" ? "messages" : "traceEvents", id: type === "message.snapshot" ? message?.messageId ?? "msg_debug_agent" : `${traceId}:${version}`, version, projectionRevision: `debug-${version}`, authority: "workbench-realtime-authority-v2" },
cursor: event.cursor ?? { traceSeq: version, outboxSeq: version }
};
}
function debugAgentMessage(sessionId: string, threadId: string, traceId: string, status: string, events: JsonRecord[]): JsonRecord {
const finalText = "Fake SSE Trace 卡片渲染完成。";
return { id: "msg_debug_agent", messageId: "msg_debug_agent", role: "agent", title: "Code Agent", text: status === "completed" ? finalText : "", status, createdAt: "2026-07-09T08:00:00.000Z", updatedAt: "2026-07-09T08:00:07.000Z", sessionId, threadId, traceId, turnId: traceId, runnerTrace: debugTraceSnapshot(sessionId, threadId, traceId, status, events) };
}
function debugTraceSnapshot(sessionId: string, threadId: string, traceId: string, status: string, events: JsonRecord[]): JsonRecord {
const finalText = "Fake SSE Trace 卡片渲染完成。";
return { traceId, sessionId, threadId, status, events, eventCount: events.length, fullTraceLoaded: status === "completed", hasMore: false, startedAt: "2026-07-09T08:00:00.000Z", lastEventAt: events.at(-1)?.createdAt ?? "2026-07-09T08:00:00.000Z", finishedAt: status === "completed" ? "2026-07-09T08:00:07.000Z" : null, durationMs: status === "completed" ? 7000 : null, finalResponse: status === "completed" ? { text: finalText, status: "completed" } : undefined };
}
function debugEventName(event: JsonRecord): string {
if (event.type === "message.snapshot") return "workbench.message.snapshot";
if (event.type === "trace.snapshot") return "workbench.trace.snapshot";
if (event.type === "turn.snapshot") return "workbench.turn.snapshot";
return event.type === "error" ? "workbench.error" : "workbench.trace.event";
}
function broadcastSse(eventName: string, payload: JsonRecord): void {
for (const client of Array.from(sseClients)) writeSse(client, eventName, payload);
}
function writeSse(response: ServerResponse, eventName: string, payload: JsonRecord): void {
response.write(`event: ${eventName}\n`);
response.write(`data: ${JSON.stringify(payload)}\n\n`);
}
function finishRunningSession(status: "completed" | "failed", text: string): void {
const session = sessionById("ses_running");
if (!session) return;
session.status = status;
session.updatedAt = new Date().toISOString();
const trace = state.traces.trc_running ?? { traceId: "trc_running", status: "running", events: [] };
const finalEvent = { seq: 4, createdAt: new Date().toISOString(), label: `agentrun:terminal:${status}`, status, terminal: true };
const events = [...(Array.isArray(trace.events) ? trace.events as JsonRecord[] : []), finalEvent];
state.traces.trc_running = { ...trace, status, events, eventCount: events.length, fullTraceLoaded: true, hasMore: false, assistantText: text, finalResponse: { text, status } };
session.messages = (session.messages ?? []).map((message) => message.role === "agent" ? { ...message, text, status, runnerTrace: state.traces.trc_running } : message);
}
function finishRunningNoFinalResponse(trace: JsonRecord = completedNoFinalTrace()): void {
state.traces.trc_running = trace;
const session = sessionById("ses_running");
if (!session) return;
session.status = "completed";
session.updatedAt = new Date().toISOString();
session.messages = (session.messages ?? []).map((message) => message.role === "agent" ? { ...message, text: "", status: "completed", runnerTrace: trace } : message);
}
function runningAgentMessageSnapshot(): JsonRecord | null {
const session = sessionById("ses_running");
const message = session?.messages?.find((item) => item.role === "agent" && item.traceId === "trc_running");
return message ?? null;
}
function stateSummary(): JsonRecord {
return { scenarioId: state.scenarioId, selectedSessionId: state.selectedSessionId, requestLedger: state.requestLedger, legacyRequestLedger: state.legacyRequestLedger, chatRequests: state.chatRequests, staleTraceId: state.staleTraceId, sessions: state.sessions.map((item) => ({ sessionId: item.sessionId, threadId: item.threadId, status: item.status, lastTraceId: item.lastTraceId, hidden: item.hidden === true })) };
}
function gcEmptySessions(body: JsonRecord): JsonRecord {
const ttlMs = positiveInteger(body.ttlMs, DEFAULT_WORKBENCH_EMPTY_SESSION_TTL_MS);
const nowMs = Date.parse(typeof body.now === "string" ? body.now : "2026-06-18T16:20:30.000Z");
const archivedSessionIds: string[] = [];
const keptByReason: Record<string, number> = {};
for (const session of state.sessions) {
if (session.status === "archived") continue;
const decision = classifyWorkbenchEmptySessionGcCandidate(toBackendSessionRecord(session), { nowMs, ttlMs });
if (!decision.eligible) {
keptByReason[decision.reason] = (keptByReason[decision.reason] ?? 0) + 1;
continue;
}
session.status = "archived";
session.updatedAt = new Date(nowMs).toISOString();
archivedSessionIds.push(session.sessionId);
}
return { ok: true, status: "completed", ttlMs, archived: archivedSessionIds.length, archivedSessionIds, keptByReason, valuesRedacted: true };
}
function toBackendSessionRecord(session: SessionRecord): JsonRecord {
return {
id: session.sessionId,
status: session.status,
startedAt: session.startedAt,
updatedAt: session.updatedAt,
lastTraceId: session.lastTraceId,
session: {
createdAt: session.startedAt,
updatedAt: session.updatedAt,
messageCount: session.messageCount,
messages: session.messages ?? [],
lastTraceId: session.lastTraceId,
valuesRedacted: true,
secretMaterialStored: false
}
};
}
function recordLedger(method: string, url: URL): void {
if (!url.pathname.startsWith("/v1/")) return;
const entry = { method, path: url.pathname, query: Object.fromEntries(url.searchParams.entries()) };
state.requestLedger.push(entry);
if (isLegacyWorkbenchPath(url.pathname)) state.legacyRequestLedger.push(entry);
}
function isLegacyWorkbenchPath(path: string): boolean {
if (/^\/v1\/workbench\/(sessions(?:\/[^/]+(?:\/messages)?)?|events|turns\/[^/]+|traces\/[^/]+\/events)$/u.test(path)) return false;
if (path === "/v1/workbench/debug/fake-sse" || path.startsWith("/v1/workbench/debug/fake-sse/")) return false;
if (path === "/v1/agent/chat" || /^\/v1\/agent\/sessions(?:\/[^/]+(?:\/select)?)?$/u.test(path)) return false;
return path.startsWith("/v1/workbench/") || path.startsWith("/v1/agent/");
}
function authPayload(): JsonRecord {
const deniedCapabilities = { web: "forbidden", workbench: "forbidden", codeAgent: "forbidden", billing: "forbidden", apiKeys: "forbidden", admin: "forbidden" };
if (state.scenarioId === "auth-upstream-unavailable" || state.scenarioId === "auth-invalid-credentials") {
return { authenticated: false, mode: "server", authMethod: null, identityAuthority: null, sessionKind: null, actor: null, user: null, capabilities: deniedCapabilities, expiresAt: null, valuesRedacted: true, error: { code: "auth_required", message: "Authentication is required", status: 401 } };
}
const actor = { id: "usr_e2e_admin", username: "e2e-admin", role: "admin", status: "active" };
return { authenticated: true, mode: "server", authMethod: "web-session", identityAuthority: "hwlab-local", sessionKind: "browser", actor, user: actor, capabilities: { web: "available", workbench: "available", codeAgent: "available", billing: "unlinked", apiKeys: "available", admin: "available" }, access: { nav: { profileId: "e2e-admin", allowedIds: ["*"], valuesRedacted: true } }, expiresAt: null, valuesRedacted: true };
}
function authLoginResponse(response: ServerResponse): void {
if (state.scenarioId === "auth-upstream-unavailable") return json(response, 502, { ok: false, status: "failed", error: { code: "upstream_unavailable", message: "auth upstream unavailable", retryable: true, layer: "proxy" } });
if (state.scenarioId === "auth-invalid-credentials") return json(response, 401, { ok: false, status: "failed", error: { code: "invalid_credentials", message: "invalid credentials" } });
response.setHeader("Set-Cookie", "hwlab_session=authenticated; Path=/; HttpOnly; SameSite=Lax");
return json(response, 200, authPayload());
}
function performanceSummaryErrorStatus(scenarioId: string): number | null {
const match = /^performance-summary-error-(400|401|403|404|409|500)$/u.exec(scenarioId);
return match ? Number(match[1]) : null;
}
function statusMatrixTraceId(status: number): string {
return String(status).repeat(11).slice(0, 32);
}
function redactRequestBody(value: JsonRecord): JsonRecord {
const output: JsonRecord = {};
for (const [key, item] of Object.entries(value)) output[key] = /secret|token|key|password|authorization/iu.test(key) ? "<redacted>" : item;
return output;
}
async function readJson(request: IncomingMessage): Promise<JsonRecord> {
const chunks: Buffer[] = [];
for await (const chunk of request) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
if (chunks.length === 0) return {};
try {
const parsed = JSON.parse(Buffer.concat(chunks).toString("utf8"));
return parsed && typeof parsed === "object" ? parsed as JsonRecord : {};
} catch {
return {};
}
}
function errorDiagnosticResponse(response: ServerResponse, status: number, route: string, code: string, message: string, overrides: Partial<JsonRecord> = {}): void {
const diagnostic = {
contractVersion: "hwlab-error-diagnostic-v1",
traceId: String(overrides.traceId ?? "11111111111111111111111111111111"),
requestId: String(overrides.requestId ?? "req_e2e_api_error_diagnostic"),
route,
layer: String(overrides.layer ?? "api"),
category: String(overrides.category ?? "server"),
code,
httpStatus: status,
source: String(overrides.source ?? "server"),
observedAt: new Date().toISOString(),
valuesPrinted: false
};
json(response, status, { ok: false, status, error: { code, message, diagnostic } }, {
traceparent: `00-${diagnostic.traceId}-2222222222222222-01`,
"x-hwlab-otel-trace-id": diagnostic.traceId,
"x-request-id": diagnostic.requestId
});
}
function json(response: ServerResponse, status: number, body: unknown, headers: Record<string, string> = {}): void {
response.writeHead(status, { "content-type": "application/json; charset=utf-8", ...headers });
response.end(JSON.stringify(body));
}
function staticFile(response: ServerResponse, path: string): void {
const filePath = safeStaticPath(path);
const target = filePath && existsSync(filePath) && statSync(filePath).isFile() ? filePath : join(distDir, "index.html");
response.writeHead(200, { "content-type": contentType(target) });
if (extname(target) === ".html") {
response.end(injectRuntimeConfig(readFileSync(target, "utf8")));
return;
}
createReadStream(target).pipe(response);
}
function injectRuntimeConfig(html: string): string {
if (html.includes("HWLAB_CLOUD_WEB_CONFIG")) return html;
return html.replace("</head>", ` ${runtimeConfigScript}\n </head>`);
}
function safeStaticPath(path: string): string | null {
const normalized = resolve(distDir, `.${decodeURIComponent(path === "/" ? "/index.html" : path)}`);
return normalized === distDir || normalized.startsWith(`${distDir}${sep}`) ? normalized : null;
}
function contentType(filePath: string): string {
switch (extname(filePath)) {
case ".html": return "text/html; charset=utf-8";
case ".js": return "text/javascript; charset=utf-8";
case ".css": return "text/css; charset=utf-8";
case ".svg": return "image/svg+xml";
case ".ico": return "image/x-icon";
default: return "application/octet-stream";
}
}
function delay(ms: number): Promise<void> {
return ms > 0 ? new Promise((resolveDelay) => setTimeout(resolveDelay, ms)) : Promise.resolve();
}
function positiveInteger(value: unknown, fallback: number): number {
const parsed = Number.parseInt(String(value ?? ""), 10);
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
}
function nonNegativeInteger(value: unknown, fallback: number): number {
const parsed = Number.parseInt(String(value ?? ""), 10);
return Number.isInteger(parsed) && parsed >= 0 ? parsed : Math.max(0, Math.trunc(fallback));
}