// SPEC: PJ2026-0104010803 Workbench唯一投影 draft-2026-06-18-p0-unique-projection; PJ2026-010403 API契约 draft-2026-06-18-r1; PJ2026-010205 HWLAB接入 draft-2026-06-17-r0; PJ2026-0102 Agent编排 draft-2026-06-17-r0; PJ2026-01060505 Workbench Performance draft-2026-06-17-p0. // Responsibility: Code Agent HTTP turn admission, lifecycle compatibility wrappers, and Workbench projection writer/finalizer integration. import { createHash, randomUUID } from "node:crypto"; import { M3_IO_CONTROL_ROUTE, M3_STATUS_ROUTE, describeM3StatusLive, handleM3IoControl } from "./m3-io-control.ts"; import { agentRunSessionEvidence, cancelAgentRunChatTurn, codeAgentAgentRunAdapterEnabled, initialAgentRunChatResult, loadPersistedAgentRunResult, refreshAgentRunTrace, steerAgentRunChatTurn, submitAgentRunChatTurn, syncAgentRunChatResult } from "./code-agent-agentrun-adapter.ts"; import { createCodeAgentErrorPayload, handleCodeAgentChat } from "./code-agent-chat.ts"; import { defaultCodeAgentTraceStore } from "./code-agent-trace-store.ts"; import { codeAgentSessionLifecycleSummary } from "./code-agent-session-lifecycle.ts"; import { scheduleWorkbenchProjectionFinalizer } from "./workbench-projection-finalizer.ts"; import { writeWorkbenchProjectionSession } from "./workbench-projection-writer.ts"; import { firstHeaderValue, getHeader, parsePositiveInteger, positiveInteger, readBody, safeConversationId, safeOpaqueId, safeSessionId, safeTraceId, sendJson, truthyFlag } from "./server-http-utils.ts"; const DEFAULT_CODE_AGENT_RESULT_TRACE_EVENT_LIMIT = 120; const DEFAULT_CODE_AGENT_TRACE_PAGE_LIMIT = 100; const MAX_CODE_AGENT_TRACE_PAGE_LIMIT = 100; const DEFAULT_CODE_AGENT_TURN_STATUS_REFRESH_TIMEOUT_MS = 2500; const DEFAULT_CODE_AGENT_PROJECT_ID = "prj_hwpod_workbench"; const DEFAULT_CODE_AGENT_PROVIDER_PROFILE = "deepseek"; const CODE_AGENT_TERMINAL_STATUSES = new Set(["completed", "failed", "blocked", "timeout", "cancelled", "canceled"]); const CODE_AGENT_PROVIDER_PROFILE_ALIASES = Object.freeze({ codex: "codex-api" }); const CODE_AGENT_PROVIDER_PROFILE_ID_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/u; const CODE_AGENT_PROVIDER_PROFILE_LABELS = Object.freeze({ "deepseek": "DeepSeek", "codex-api": "Codex API", "minimax-m3": "MiniMax-M3 via AgentRun", "runtime-default": "运行默认" }); const DEFAULT_CODE_AGENT_CODEX_API_MODEL = "gpt-5.5"; const DEFAULT_CODE_AGENT_CODEX_API_BASE_URL = "http://127.0.0.1:49280/responses"; const DEFAULT_CODE_AGENT_DEEPSEEK_MODEL = "deepseek-chat"; const DEFAULT_CODE_AGENT_MINIMAX_M3_MODEL = "MiniMax-M3"; export async function handleCodeAgentChatHttp(request, response, options) { const perf = options.backendPerformance; const body = perf ? await perf.measure("body_read", () => readBody(request, options.bodyLimitBytes)) : await readBody(request, options.bodyLimitBytes); let params = {}; try { params = body ? JSON.parse(body) : {}; } catch (error) { sendJson(response, 400, { ...createCodeAgentErrorPayload({ code: "parse_error", message: "Invalid JSON body", reason: error.message, traceId: getHeader(request, "x-trace-id") || "trc_unassigned", model: options.env?.HWLAB_CODE_AGENT_MODEL || options.env?.OPENAI_MODEL || process.env.HWLAB_CODE_AGENT_MODEL || process.env.OPENAI_MODEL || "unknown", layer: "api", retryable: true }) }); return; } if (!params || typeof params !== "object" || Array.isArray(params)) { sendJson(response, 400, { ...createCodeAgentErrorPayload({ code: "invalid_params", message: "Code Agent chat body must be a JSON object", traceId: getHeader(request, "x-trace-id") || "trc_unassigned", model: options.env?.HWLAB_CODE_AGENT_MODEL || options.env?.OPENAI_MODEL || process.env.HWLAB_CODE_AGENT_MODEL || process.env.OPENAI_MODEL || "unknown", layer: "api", retryable: true }) }); return; } const traceId = safeTraceId(getHeader(request, "x-trace-id") || params.traceId) || `trc_${randomUUID()}`; const lifecycle = codeAgentTurnLifecycleFields(traceId, params); const chatParams = { ...params, traceId, ...lifecycle, ownerUserId: options.actor?.id ?? params.ownerUserId, ownerRole: options.actor?.role ?? params.ownerRole }; const manualSession = perf ? await perf.measure("manual_session", () => prepareManualCodeAgentSession({ params: chatParams, options, traceId, response })) : await prepareManualCodeAgentSession({ params: chatParams, options, traceId, response }); if (manualSession?.blocked) return; const billingPreflight = perf ? await perf.measure("billing_preflight", () => preflightCodeAgentBilling({ params: chatParams, options, traceId, response })) : await preflightCodeAgentBilling({ params: chatParams, options, traceId, response }); if (billingPreflight?.blocked) return; const nativeSessionChatParams = stripSyntheticConversationContext({ ...chatParams, userBillingReservation: billingPreflight?.reservation ?? null }, traceId, options); if (codeAgentChatShortConnectionRequested(request, params, options)) { if (perf) perf.recordPhase({ phase: "short_connection_accept", durationMs: 0, outcome: "ok" }); submitCodeAgentChatTurn({ params: nativeSessionChatParams, options, traceId }); const traceUrl = `/v1/agent/traces/${encodeURIComponent(traceId)}`; const turnUrl = `/v1/agent/turns/${encodeURIComponent(traceId)}`; sendJson(response, 202, { accepted: true, status: "running", shortConnection: true, controlSemantics: "submit-and-poll", traceId, ...lifecycle, sessionId: safeSessionId(nativeSessionChatParams.sessionId) || null, traceUrl, resultUrl: `/v1/agent/chat/result/${encodeURIComponent(traceId)}`, turnUrl, streamUrl: `${traceUrl}/stream`, cancelUrl: "/v1/agent/chat/cancel", polling: { resultIntervalMs: parsePositiveInteger(options.env?.HWLAB_CODE_AGENT_RESULT_POLL_INTERVAL_MS, 1000), traceIntervalMs: parsePositiveInteger(options.env?.HWLAB_CODE_AGENT_TRACE_POLL_INTERVAL_MS, 1000) }, runnerTrace: (options.traceStore ?? defaultCodeAgentTraceStore).snapshot(traceId) }); return; } const payload = perf ? await perf.measure("code_agent_run", () => runCodeAgentChat(nativeSessionChatParams, options)) : await runCodeAgentChat(nativeSessionChatParams, options); await (perf ? perf.measure("billing_finalize", () => finalizeCodeAgentBillingUsage({ payload, params: nativeSessionChatParams, options })) : finalizeCodeAgentBillingUsage({ payload, params: nativeSessionChatParams, options })); await (perf ? perf.measure("session_owner_record", () => recordCodeAgentSessionOwner({ payload, params: nativeSessionChatParams, options, status: codeAgentOwnerStatusForResult(payload) })) : recordCodeAgentSessionOwner({ payload, params: nativeSessionChatParams, options, status: codeAgentOwnerStatusForResult(payload) })); const responsePayload = annotateOwner(payload, nativeSessionChatParams); sendJson(response, responsePayload.status === "failed" && responsePayload.error?.code === "invalid_params" ? 400 : 200, responsePayload); } export async function handleCodeAgentSessionsHttp(request, response, url, options) { const match = url.pathname.match(/^\/v1\/agent\/sessions(?:\/([^/]+)(?:\/(select))?)?$/u); const sessionId = safeSessionId(match?.[1] ? decodeURIComponent(match[1]) : ""); const action = match?.[2] ?? null; if (!match) { sendJson(response, 404, manualSessionErrorPayload({ code: "session_route_not_found", message: "Code Agent session route is not implemented." })); return; } if (request.method === "GET" && !sessionId) { await listManualCodeAgentSessions(request, response, url, options); return; } if (request.method === "POST" && !sessionId) { await createManualCodeAgentSession(request, response, options); return; } if (request.method === "GET" && sessionId && !action) { await getManualCodeAgentSession(response, options, sessionId); return; } if (request.method === "DELETE" && sessionId && !action) { await archiveManualCodeAgentSession(response, options, sessionId); return; } if (request.method === "POST" && sessionId && action === "select") { await selectManualCodeAgentSession(request, response, options, sessionId); return; } sendJson(response, 405, manualSessionErrorPayload({ code: "session_method_not_allowed", message: "Unsupported Code Agent session method." })); } async function listManualCodeAgentSessions(request, response, url, options) { const projectId = textValue(url.searchParams.get("projectId")) || DEFAULT_CODE_AGENT_PROJECT_ID; const limit = parsePositiveInteger(url.searchParams.get("limit"), 20); const sessions = await options.accessController?.store?.listAgentSessionsForUser?.({ ownerUserId: options.actor?.id, actorRole: options.actor?.role, ownerScoped: true, projectId, limit }) ?? []; sendJson(response, 200, { ok: true, status: "succeeded", contractVersion: "code-agent-manual-session-v1", projectId, sessions: sessions.map(publicManualAgentSession), count: sessions.length, valuesRedacted: true, secretMaterialStored: false }); } async function createManualCodeAgentSession(request, response, options) { const body = await readJsonObjectBody(request, options.bodyLimitBytes); if (!body.ok) { sendJson(response, 400, manualSessionErrorPayload({ code: body.code, message: body.message, reason: body.reason })); return; } const params = body.value; const projectId = textValue(params.projectId) || DEFAULT_CODE_AGENT_PROJECT_ID; const conversationId = safeConversationId(params.conversationId) || `cnv_${randomUUID()}`; const sessionId = safeSessionId(params.sessionId) || `ses_${randomUUID()}`; const providerProfile = normalizeCodeAgentProviderProfile(params.providerProfile ?? params.codeAgentProviderProfile); const now = new Date().toISOString(); const session = await options.accessController.recordAgentSessionOwner({ ownerUserId: options.actor?.id, ownerRole: options.actor?.role, sessionId, projectId, agentId: "hwlab-code-agent", status: "idle", conversationId, threadId: null, traceId: null, session: { source: "manual-session-create", providerProfile, sessionStatus: "idle", createdAt: now, valuesRedacted: true, secretMaterialStored: false } }); sendJson(response, 201, { ok: true, status: "created", contractVersion: "code-agent-manual-session-v1", session: publicManualAgentSession(session), nextCommands: manualSessionNextCommands(session), valuesRedacted: true, secretMaterialStored: false }); } async function getManualCodeAgentSession(response, options, sessionId) { const session = await getVisibleManualAgentSession(options, sessionId); if (!session) { sendJson(response, 404, manualSessionErrorPayload({ code: "session_not_found", message: "Code Agent session is not visible to the current actor.", sessionId })); return; } sendJson(response, 200, { ok: true, status: "found", contractVersion: "code-agent-manual-session-v1", session: publicManualAgentSession(session), valuesRedacted: true, secretMaterialStored: false }); } async function archiveManualCodeAgentSession(response, options, sessionId) { const session = await getVisibleManualAgentSession(options, sessionId); if (!session) { sendJson(response, 404, manualSessionErrorPayload({ code: "session_not_found", message: "Code Agent session is not visible to the current actor.", sessionId })); return; } const result = await options.accessController?.store?.archiveAgentConversation?.({ ownerUserId: options.actor?.id, actorRole: options.actor?.role, ownerScoped: true, sessionId, conversationId: session.conversationId, projectId: session.projectId }) ?? { count: 0 }; sendJson(response, 200, { ok: true, status: "archived", contractVersion: "code-agent-manual-session-v1", archivedCount: result.count ?? 0, session: publicManualAgentSession({ ...session, status: "archived", endedAt: session.endedAt ?? new Date().toISOString(), updatedAt: new Date().toISOString() }), valuesRedacted: true, secretMaterialStored: false }); } async function selectManualCodeAgentSession(request, response, options, sessionId) { const body = await readJsonObjectBody(request, options.bodyLimitBytes); if (!body.ok) { sendJson(response, 400, manualSessionErrorPayload({ code: body.code, message: body.message, reason: body.reason, sessionId })); return; } const session = await getVisibleManualAgentSession(options, sessionId); if (!session) { sendJson(response, 404, manualSessionErrorPayload({ code: "session_not_found", message: "Code Agent session is not visible to the current actor.", sessionId })); return; } if (!manualSessionUsable(session.status)) { sendJson(response, 409, manualSessionErrorPayload({ code: "session_not_usable", message: `Code Agent session ${sessionId} is ${session.status}; create a new session before continuing.`, sessionId, session })); return; } sendJson(response, 200, { ok: true, status: "selected", contractVersion: "code-agent-manual-session-v1", session: publicManualAgentSession(session), nextCommands: manualSessionNextCommands(session), valuesRedacted: true, secretMaterialStored: false }); } async function prepareManualCodeAgentSession({ params, options, traceId, response }) { if (!options.actor?.id) { sendJson(response, 401, manualSessionErrorPayload({ code: "auth_required", message: "Authentication is required before using an explicit HWLAB Code Agent session.", traceId, retryable: true })); return { blocked: true }; } const sessionId = safeSessionId(params.sessionId); if (!sessionId) { sendJson(response, 409, manualSessionErrorPayload({ code: "session_required", message: "Code Agent session is explicit in HWLAB v0.2; create/select a session before sending a turn.", traceId, retryable: true, nextCommands: ["hwlab-cli client agent session create --provider-profile PROFILE", "hwlab-cli client agent send --session-id --message TEXT"] })); return { blocked: true }; } const session = await getVisibleManualAgentSession(options, sessionId); if (!session) { sendJson(response, 404, manualSessionErrorPayload({ code: "session_not_found", message: "Code Agent session is not visible to the current actor.", traceId, sessionId })); return { blocked: true }; } if (!manualSessionUsable(session.status)) { sendJson(response, 409, manualSessionErrorPayload({ code: "session_not_usable", message: `Code Agent session ${sessionId} is ${session.status}; create a new session before continuing.`, traceId, sessionId, session })); return { blocked: true }; } const requestedProjectId = textValue(params.projectId); const sessionProjectId = textValue(session.projectId); if (requestedProjectId && sessionProjectId && requestedProjectId !== sessionProjectId) { sendJson(response, 409, manualSessionErrorPayload({ code: "session_project_mismatch", message: `sessionId ${sessionId} belongs to ${sessionProjectId}; requested ${requestedProjectId}.`, traceId, sessionId, session })); return { blocked: true }; } const storedConversationId = safeConversationId(session.conversationId); const requestedConversationId = safeConversationId(params.conversationId); if (requestedConversationId && storedConversationId && requestedConversationId !== storedConversationId) { sendJson(response, 409, manualSessionErrorPayload({ code: "session_conversation_mismatch", message: `sessionId ${sessionId} is bound to ${storedConversationId}; requested ${requestedConversationId}.`, traceId, sessionId, session })); return { blocked: true }; } const conversationId = requestedConversationId || storedConversationId; if (!conversationId) { sendJson(response, 409, manualSessionErrorPayload({ code: "session_conversation_required", message: "Code Agent session has no bound conversationId; create a new session before continuing.", traceId, sessionId, session })); return { blocked: true }; } params.conversationId = conversationId; params.sessionId = sessionId; params.projectId = requestedProjectId || sessionProjectId || DEFAULT_CODE_AGENT_PROJECT_ID; params.threadId = safeOpaqueId(params.threadId) || safeOpaqueId(session.threadId) || undefined; return { session }; } async function getVisibleManualAgentSession(options, sessionId) { if (!safeSessionId(sessionId) || !options.actor?.id || !options.accessController?.getAgentSession) return null; const session = await options.accessController.getAgentSession(sessionId); if (!session) return null; if (session.ownerUserId === options.actor.id) return session; return null; } function publicManualAgentSession(session) { if (!session || typeof session !== "object") return null; return { sessionId: session.id, agentId: session.agentId ?? "hwlab-code-agent", status: session.status ?? null, usable: manualSessionUsable(session.status), threadId: safeOpaqueId(session.threadId) || null, lastTraceId: safeTraceId(session.lastTraceId) || null, providerProfile: textValue(session.session?.providerProfile) || null, createdAt: session.startedAt ?? null, updatedAt: session.updatedAt ?? null, valuesRedacted: true, secretMaterialStored: false }; } function manualSessionUsable(status) { const value = String(status ?? "").trim().toLowerCase().replace(/_/gu, "-"); return !["blocked", "expired", "stale", "thread-resume-failed"].includes(value); } function manualSessionErrorPayload({ code, message, reason = null, traceId = null, sessionId = null, session = null, retryable = true, nextCommands = undefined } = {}) { return { ok: false, accepted: false, status: "blocked", traceId: safeTraceId(traceId) || null, sessionId: safeSessionId(sessionId) || safeSessionId(session?.id) || null, session: session ? publicManualAgentSession(session) : null, error: { code, layer: "api", category: "session_blocked", retryable, message, reason, userMessage: message, route: "/v1/agent/chat" }, blocker: { code, layer: "api", retryable, summary: message }, nextCommands, valuesRedacted: true, secretMaterialStored: false }; } function manualSessionNextCommands(session) { const sessionId = session?.id ?? ""; return [ `hwlab-cli client agent send --session-id ${sessionId} --message TEXT`, `hwlab-cli client agent session status ${sessionId}` ]; } async function readJsonObjectBody(request, bodyLimitBytes) { const body = await readBody(request, bodyLimitBytes); try { const value = body ? JSON.parse(body) : {}; if (!value || typeof value !== "object" || Array.isArray(value)) return { ok: false, code: "invalid_params", message: "body must be a JSON object" }; return { ok: true, value }; } catch (error) { return { ok: false, code: "parse_error", message: "Invalid JSON body", reason: error.message }; } } async function runCodeAgentChat(params, options) { return handleCodeAgentChat(params, await codeAgentChatExecutionOptions(options, params)); } function stripSyntheticConversationContext(params = {}, traceId, options = {}) { if (Array.isArray(params.conversationContext?.messages) || Array.isArray(params.messages)) { (options.traceStore ?? defaultCodeAgentTraceStore).append(traceId, { type: "synthetic-context", status: "ignored", label: "synthetic-context:ignored", message: "Synthetic conversation context was stripped; Code Agent continuation uses only Codex stdio native thread/resume and turn/start.", valuesPrinted: false }); } const { conversationContext, conversationContextTruncated, contextSource, messages, ...nativeParams } = params; return nativeParams; } async function codeAgentChatExecutionOptions(options = {}, params = {}) { const env = codeAgentProviderProfileEnv(options.env ?? process.env, params); Object.assign(env, await codeAgentAuthEnv(options, env, params)); return { callProvider: options.callCodeAgentProvider, timeoutMs: options.codeAgentTimeoutMs, hardTimeoutMs: options.codeAgentHardTimeoutMs, env, workspace: options.workspace, skillsDirs: options.skillsDirs, skillsDirsExact: options.skillsDirsExact, skillsDiscoveryDelayMs: options.skillsDiscoveryDelayMs, sessionRegistry: options.sessionRegistry, m3IoSkillRequestJson: options.m3IoSkillRequestJson ?? createCodeAgentM3HwlabApiRequestJson(options), codexStdioManager: options.codexStdioManager, traceStore: options.traceStore, gatewayRegistry: options.gatewayRegistry }; } async function codeAgentAuthEnv(options = {}, env = process.env, params = {}) { const ownerUserId = textValue(params.ownerUserId ?? options.actor?.id ?? ""); const store = options.accessController?.store; const key = ownerUserId && store?.findActiveDefaultApiKeyForUser ? await store.findActiveDefaultApiKeyForUser(ownerUserId) : null; const runtimeNamespace = runtimeNamespaceForEnv(env); const runtimeLane = runtimeLaneForNamespace(runtimeNamespace) ?? runtimeLaneForEnv(env); const inClusterApiUrl = internalCodeAgentApiUrl(env, runtimeNamespace); const inClusterWebUrl = internalCodeAgentWebUrl(env, runtimeNamespace); const apiUrl = firstNonEmptyValue( codeAgentAgentRunAdapterEnabled(env) ? inClusterApiUrl : null, env.HWLAB_RUNTIME_API_URL, sameRuntimeEndpoint(env.HWLAB_CLOUD_API_URL, runtimeNamespace, runtimeLane), env.HWLAB_PUBLIC_ENDPOINT, localCloudApiUrl(env) ); return { HWLAB_CLOUD_API_URL: apiUrl, HWLAB_RUNTIME_API_URL: apiUrl, HWLAB_RUNTIME_WEB_URL: firstNonEmptyValue(codeAgentAgentRunAdapterEnabled(env) ? inClusterWebUrl : null, env.HWLAB_RUNTIME_WEB_URL, apiUrl), HWLAB_RUNTIME_NAMESPACE: runtimeNamespace, HWLAB_RUNTIME_LANE: runtimeLane, HWLAB_RUNTIME_ENDPOINT_SOURCE: codeAgentAgentRunAdapterEnabled(env) ? "runtime-namespace" : "runtime-env", HWLAB_RUNTIME_ENDPOINT_LOCKED: "1", HWLAB_CODE_AGENT_ASSEMBLED_RUNTIME: "1", ...(options.actorApiKeySecret ? { HWLAB_API_KEY: options.actorApiKeySecret } : key?.displaySecret ? { HWLAB_API_KEY: key.displaySecret } : {}) }; } function internalCodeAgentApiUrl(env = process.env, namespace = runtimeNamespaceForEnv(env)) { const serviceName = firstNonEmptyValue(env.HWLAB_CODE_AGENT_INTERNAL_API_SERVICE_NAME, env.HWLAB_CLOUD_API_SERVICE_NAME, "hwlab-cloud-api"); const port = parsePositiveInteger(firstNonEmptyValue(env.HWLAB_CODE_AGENT_INTERNAL_API_PORT, env.HWLAB_CLOUD_API_PORT), 6667); return `http://${serviceName}.${namespace}.svc.cluster.local:${port}`; } function internalCodeAgentWebUrl(env = process.env, namespace = runtimeNamespaceForEnv(env)) { const serviceName = firstNonEmptyValue(env.HWLAB_CODE_AGENT_INTERNAL_WEB_SERVICE_NAME, env.HWLAB_CLOUD_WEB_SERVICE_NAME, "hwlab-cloud-web"); const port = parsePositiveInteger(firstNonEmptyValue(env.HWLAB_CODE_AGENT_INTERNAL_WEB_PORT, env.HWLAB_CLOUD_WEB_PORT), 8080); return `http://${serviceName}.${namespace}.svc.cluster.local:${port}`; } function runtimeNamespaceForEnv(env = process.env) { return firstNonEmptyValue( env.HWLAB_RUNTIME_NAMESPACE, env.POD_NAMESPACE, env.HWLAB_NAMESPACE, defaultRuntimeNamespace(env) ); } function runtimeLaneForEnv(env = process.env) { const profile = String(firstNonEmptyValue(env.HWLAB_RUNTIME_LANE, env.HWLAB_GITOPS_LANE, env.HWLAB_GITOPS_PROFILE, env.HWLAB_ENVIRONMENT, env.HWLAB_BOOT_REF, "dev") ?? "dev").trim().toLowerCase(); if (profile === "prod" || profile === "production") return "prod"; if (profile === "v02" || profile === "v0.2" || profile === "0.2") return "v02"; return "dev"; } function runtimeLaneForNamespace(namespace) { if (namespace === "hwlab-v02") return "v02"; if (namespace === "hwlab-prod") return "prod"; if (namespace === "hwlab-dev") return "dev"; return null; } function sameRuntimeEndpoint(value, namespace, lane) { const text = firstNonEmptyValue(value); if (!text) return null; const endpointLane = runtimeLaneForEndpoint(text); const endpointNamespace = runtimeNamespaceForEndpoint(text); if (namespace && endpointNamespace && endpointNamespace !== namespace) return null; if (lane && endpointLane && endpointLane !== lane) return null; return text; } function runtimeNamespaceForEndpoint(value) { const match = String(value ?? "").match(/\.((?:hwlab-[a-z0-9-]+))\.svc\.cluster\.local(?::|\/|$)/iu); return match?.[1] ?? null; } function runtimeLaneForEndpoint(value) { const text = String(value ?? "").toLowerCase(); if (/hwlab-v02|:19666(?:\/|$)|:19667(?:\/|$)/u.test(text)) return "v02"; if (/hwlab-prod|:18666(?:\/|$)|:18667(?:\/|$)/u.test(text)) return "prod"; if (/hwlab-dev|:17666(?:\/|$)|:17667(?:\/|$)|:16666(?:\/|$)|:16667(?:\/|$)/u.test(text)) return "dev"; return null; } function defaultRuntimeNamespace(env = process.env) { const profile = runtimeLaneForEnv(env); if (profile === "prod") return "hwlab-prod"; if (profile === "v02") return "hwlab-v02"; return "hwlab-dev"; } function localCloudApiUrl(env = process.env) { const port = parsePositiveInteger(env.HWLAB_CLOUD_API_PORT, 6667); return `http://127.0.0.1:${port}`; } function codeAgentProviderProfileEnv(env = process.env, params = {}) { const profile = normalizeCodeAgentProviderProfile(params.providerProfile ?? params.codeAgentProviderProfile ?? env.HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE); if (profile === "runtime-default") return env; const overlay = { ...env }; overlay.HWLAB_CODE_AGENT_SELECTED_PROVIDER_PROFILE = profile; overlay.HWLAB_CODE_AGENT_PROVIDER_PROFILE_LABEL = CODE_AGENT_PROVIDER_PROFILE_LABELS[profile] ?? profile; overlay.HWLAB_CODE_AGENT_PROVIDER = "codex-stdio"; if (profile === "codex-api") { overlay.HWLAB_CODE_AGENT_MODEL = firstNonEmptyValue(env.HWLAB_CODE_AGENT_CODEX_API_MODEL, env.HWLAB_CODE_AGENT_LEGACY_CODEX_MODEL, DEFAULT_CODE_AGENT_CODEX_API_MODEL); overlay.HWLAB_CODE_AGENT_OPENAI_BASE_URL = firstNonEmptyValue(env.HWLAB_CODE_AGENT_CODEX_API_BASE_URL, env.HWLAB_CODE_AGENT_LEGACY_OPENAI_BASE_URL, DEFAULT_CODE_AGENT_CODEX_API_BASE_URL); } else if (profile === "minimax-m3") { overlay.HWLAB_CODE_AGENT_MODEL = firstNonEmptyValue(env.HWLAB_CODE_AGENT_MINIMAX_M3_MODEL, DEFAULT_CODE_AGENT_MINIMAX_M3_MODEL); } else { const dynamicProfile = profile !== "deepseek"; overlay.HWLAB_CODE_AGENT_MODEL = dynamicProfile ? firstNonEmptyValue(env[`HWLAB_CODE_AGENT_${providerProfileEnvKey(profile)}_MODEL`], profile) : firstNonEmptyValue(env.HWLAB_CODE_AGENT_DEEPSEEK_MODEL, DEFAULT_CODE_AGENT_DEEPSEEK_MODEL); if (!dynamicProfile || !codeAgentAgentRunAdapterEnabled(env)) { overlay.HWLAB_CODE_AGENT_OPENAI_BASE_URL = firstNonEmptyValue(env.HWLAB_CODE_AGENT_DEEPSEEK_BASE_URL, defaultDeepSeekBaseUrlForEnv(env)); } } overlay.NO_PROXY = mergeNoProxyEntries(env.NO_PROXY, codeAgentClusterNoProxyEntries(env)); overlay.no_proxy = mergeNoProxyEntries(env.no_proxy ?? env.NO_PROXY, codeAgentClusterNoProxyEntries(env)); return overlay; } function normalizeCodeAgentProviderProfile(value) { const text = String(value ?? DEFAULT_CODE_AGENT_PROVIDER_PROFILE).trim().toLowerCase(); if (!text) return DEFAULT_CODE_AGENT_PROVIDER_PROFILE; if (text === "runtime-default") return text; const normalized = CODE_AGENT_PROVIDER_PROFILE_ALIASES[text] ?? text; return CODE_AGENT_PROVIDER_PROFILE_ID_PATTERN.test(normalized) ? normalized : DEFAULT_CODE_AGENT_PROVIDER_PROFILE; } function providerProfileEnvKey(profile) { return String(profile ?? "") .trim() .toUpperCase() .replace(/[^A-Z0-9]+/gu, "_") .replace(/^_+|_+$/gu, "") || "PROFILE"; } function defaultDeepSeekBaseUrlForEnv(env = process.env) { const namespace = env.HWLAB_GITOPS_PROFILE === "prod" || env.HWLAB_ENVIRONMENT === "prod" ? "hwlab-prod" : "hwlab-dev"; return `http://hwlab-deepseek-proxy.${namespace}.svc.cluster.local:4000/v1/responses`; } function codeAgentClusterNoProxyEntries(env = process.env) { const namespace = env.HWLAB_GITOPS_PROFILE === "prod" || env.HWLAB_ENVIRONMENT === "prod" ? "hwlab-prod" : "hwlab-dev"; return [ `${namespace}.svc.cluster.local`, ".svc", ".cluster.local", "127.0.0.1", "localhost", "::1", "10.0.0.0/8", "10.42.0.0/16", "10.43.0.0/16", "hyueapi.com", ".hyueapi.com", "hyui.com", ".hyui.com", "api.minimaxi.com", ".minimaxi.com" ]; } function mergeNoProxyEntries(current, additions = []) { return uniqueStrings([...String(current ?? "").split(","), ...additions]).join(","); } function firstNonEmptyValue(...values) { for (const value of values) { const text = String(value ?? "").trim(); if (text) return text; } return null; } function submitCodeAgentChatTurn({ params, options, traceId }) { const traceStore = options.traceStore ?? defaultCodeAgentTraceStore; const results = options.codeAgentChatResults ?? createCodeAgentChatResultStore(); const acceptedPayload = { accepted: true, status: "running", traceId, ...codeAgentTurnLifecycleFields(traceId, params), conversationId: safeConversationId(params.conversationId) || null, sessionId: safeSessionId(params.sessionId) || null, threadId: safeOpaqueId(params.threadId) || null, projectId: params.projectId ?? null, updatedAt: new Date().toISOString() }; void recordCodeAgentSessionOwner({ payload: acceptedPayload, params, options, status: "running" }); if (codeAgentAgentRunAdapterEnabled(options.env ?? process.env)) { const initial = withCodeAgentBillingReservation(initialAgentRunChatResult({ params, options, traceId }), params); results.set(traceId, annotateOwner(initial, params)); const run = async () => { let executionOptions = options; try { executionOptions = { ...options, ...(await codeAgentChatExecutionOptions(options, params)) }; const payload = await submitAgentRunChatTurn({ params, options: executionOptions, traceId, traceStore, results }); if (isCodeAgentResultCanceled(results.get(traceId))) return; const owned = annotateOwner(withCodeAgentBillingReservation(payload, params), params); await recordCodeAgentSessionOwner({ payload: owned, params, options: executionOptions, status: "running" }); results.set(traceId, owned); scheduleAgentRunProjectionSync({ traceId, params, options: executionOptions, traceStore, currentResult: owned }); } catch (error) { if (isCodeAgentResultCanceled(results.get(traceId))) return; const payload = annotateOwner({ ...initial, status: "failed", error: { code: error?.code ?? "agentrun_dispatch_failed", layer: "agentrun", retryable: true, message: error?.message ?? "AgentRun dispatch failed", userMessage: "AgentRun 调度失败;trace/result 轮询已保留错误。" }, blocker: { code: error?.code ?? "agentrun_dispatch_failed", layer: "agentrun", retryable: true, summary: error?.message ?? "AgentRun dispatch failed" }, runnerTrace: traceStore.snapshot(traceId), updatedAt: new Date().toISOString() }, params); recordCodeAgentConversationFact(payload, executionOptions); await finalizeCodeAgentBillingUsage({ payload, params, options: executionOptions }); results.set(traceId, payload); traceStore.append(traceId, { type: "result", status: "failed", label: "agentrun:dispatch:failed", errorCode: payload.error.code, message: payload.error.message, terminal: true }); await recordCodeAgentSessionOwner({ payload, params, options: executionOptions, status: "failed" }); } }; setImmediate(() => { run(); }); return; } results.set(traceId, acceptedPayload); traceStore.ensure(traceId, { runnerKind: "codex-app-server-stdio-runner", workspace: options.workspace ?? options.env?.HWLAB_CODE_AGENT_CODEX_WORKSPACE ?? options.env?.HWLAB_CODE_AGENT_WORKSPACE ?? null, sandbox: options.env?.HWLAB_CODE_AGENT_CODEX_SANDBOX ?? null, sessionMode: "codex-app-server-stdio-long-lived", implementationType: "repo-owned-codex-app-server-stdio-session" }); traceStore.append(traceId, { type: "request", status: "accepted", label: "request:accepted-short-connection", message: "Code Agent request accepted; client must poll trace/result with short HTTP requests.", waitingFor: "codex-stdio" }); const run = async () => { try { const payload = await runCodeAgentChat(params, options); if (isCodeAgentResultCanceled(results.get(traceId))) return; await finalizeCodeAgentBillingUsage({ payload, params, options }); await recordCodeAgentSessionOwner({ payload, params, options, status: codeAgentOwnerStatusForResult(payload) }); results.set(traceId, annotateOwner(payload, params)); traceStore.append(traceId, { type: "result", status: payload.status === "completed" ? "completed" : "failed", label: `result:${payload.status}`, message: payload.status === "completed" ? "Code Agent result is ready for short-connection polling." : payload.error?.message ?? "Code Agent completed without a successful reply.", sessionId: payload.sessionId ?? payload.session?.sessionId, sessionStatus: payload.session?.status, terminal: true }); } catch (error) { if (isCodeAgentResultCanceled(results.get(traceId))) return; const payload = { status: "failed", traceId, conversationId: safeConversationId(params.conversationId) || null, sessionId: safeSessionId(params.sessionId) || null, error: { code: "code_agent_background_failed", layer: "api", retryable: true, message: error?.message ?? "Code Agent background turn failed", userMessage: "Code Agent 后台任务失败;trace/result 轮询已保留错误。" }, updatedAt: new Date().toISOString() }; await finalizeCodeAgentBillingUsage({ payload, params, options }); results.set(traceId, payload); traceStore.append(traceId, { type: "result", status: "failed", label: "result:failed", errorCode: payload.error.code, message: payload.error.message, terminal: true }); } }; setImmediate(() => { run(); }); } function scheduleAgentRunProjectionSync({ traceId, params = {}, options = {}, traceStore = defaultCodeAgentTraceStore, currentResult = null } = {}) { if (!safeTraceId(traceId) || !currentResult?.agentRun?.runId || !currentResult?.agentRun?.commandId) return null; const env = options.env ?? process.env; const noResponseTimeoutMs = parsePositiveInteger(env.HWLAB_CODE_AGENT_AGENTRUN_NO_RESPONSE_TIMEOUT_MS, null); const pollIntervalMs = parsePositiveInteger(env.HWLAB_CODE_AGENT_AGENTRUN_PROJECTION_SYNC_POLL_INTERVAL_MS, 1_000); const refreshOptions = codeAgentTurnStatusRefreshOptions(options); return scheduleWorkbenchProjectionFinalizer({ traceId, currentResult, traceStore, noResponseTimeoutMs, pollIntervalMs, getCachedResult: () => options.codeAgentChatResults?.get?.(traceId), isCanceled: isCodeAgentResultCanceled, isTerminal: isTraceCommandTerminalStatus, activitySignature: agentRunProjectionActivitySignature, sleep: sleepAgentRunProjectionSync, syncResult: ({ result }) => syncAgentRunChatResult({ traceId, currentResult: result, options: refreshOptions, traceStore }), onTerminal: (payload, finalizerOptions = {}) => scheduleCodeAgentTerminalTurnStatusEffects({ payload, params, options, preserveLastTraceId: finalizerOptions.preserveLastTraceId === true }) }); } function agentRunProjectionActivitySignature(result, runnerTrace) { const agentRun = result?.agentRun && typeof result.agentRun === "object" ? result.agentRun : {}; const trace = runnerTrace && typeof runnerTrace === "object" ? runnerTrace : result?.runnerTrace; const events = Array.isArray(trace?.events) ? trace.events : []; const lastEvent = trace?.lastEvent ?? events.at(-1) ?? null; return [ result?.status, result?.updatedAt, agentRun.status, agentRun.runStatus, agentRun.commandState, agentRun.terminalStatus, agentRun.lastSeq, agentRun.updatedAt, trace?.status, trace?.eventCount ?? events.length, trace?.updatedAt, trace?.lastEventLabel, lastEvent?.seq, lastEvent?.sourceSeq, lastEvent?.label, lastEvent?.type, lastEvent?.status, lastEvent?.createdAt ].map((value) => value ?? "").join("|"); } function sleepAgentRunProjectionSync(ms) { return new Promise((resolve) => setTimeout(resolve, Math.max(0, Number(ms) || 0))); } function codeAgentChatShortConnectionRequested(request, params, options = {}) { const header = firstHeaderValue(request, "prefer"); const explicit = firstHeaderValue(request, "x-hwlab-short-connection"); const envValue = options.env?.HWLAB_CODE_AGENT_CHAT_SHORT_CONNECTION; return codeAgentAgentRunAdapterEnabled(options.env ?? process.env) || /(?:^|,)\s*respond-async\s*(?:,|$)/iu.test(String(header ?? "")) || truthyFlag(explicit) || params?.shortConnection === true || truthyFlag(envValue); } async function preflightCodeAgentBilling({ params = {}, options = {}, traceId, response } = {}) { const client = options.userBillingClient; if (!codeAgentBillingEnabled(options) || !client?.configured || !options.userBillingAuth?.active) return null; const estimatedCredits = parsePositiveInteger(options.env?.HWLAB_USER_BILLING_CODE_AGENT_ESTIMATED_CREDITS, 1); const body = { ...(options.actorApiKeySecret ? { apiKey: options.actorApiKeySecret } : { userId: options.actor?.id }), serviceId: "hwlab-code-agent", estimatedCredits, idempotencyKey: `code-agent:${traceId}:preflight`, metadata: codeAgentBillingMetadata(params, traceId, { stage: "preflight" }) }; const result = await client.billingPreflight(body); if (result.ok && result.body?.allowed !== false) return { reservation: sanitizeBillingReservation(result.body) }; const status = [402, 403, 429].includes(Number(result.status)) ? Number(result.status) : 503; sendJson(response, status, { ok: false, accepted: false, status: status === 402 ? "payment_required" : status === 403 ? "not_entitled" : status === 429 ? "rate_limited" : "billing_unavailable", traceId, error: { code: result.error?.code ?? (status === 402 ? "insufficient_credits" : "user_billing_preflight_failed"), layer: "billing", retryable: status === 429 || status === 503, message: result.error?.message ?? "Code Agent billing preflight failed", route: "/v1/agent/chat" }, blocker: { code: result.error?.code ?? (status === 402 ? "insufficient_credits" : "user_billing_preflight_failed"), layer: "billing", retryable: status === 429 || status === 503, summary: result.error?.message ?? "Code Agent billing preflight failed" }, valuesRedacted: true }); return { blocked: true }; } async function recordCodeAgentBillingUsage({ payload = {}, params = {}, options = {} } = {}) { const reservation = params.userBillingReservation ?? payload.userBillingReservation; const reservationId = typeof reservation?.reservationId === "string" ? reservation.reservationId : ""; const client = options.userBillingClient; if (payload.billing?.recorded === true || payload.billing?.released === true || payload.status === "running") return payload.billing ?? null; if (!reservationId || !client?.configured) return null; const traceId = safeTraceId(payload.traceId ?? params.traceId); const usedTokens = codeAgentUsedTokens(payload); const usedCredits = parsePositiveInteger(options.env?.HWLAB_USER_BILLING_CODE_AGENT_USED_CREDITS, 1); const result = await client.billingRecord({ reservationId, serviceId: "hwlab-code-agent", usedCredits, usedTokens, idempotencyKey: `code-agent:${traceId}:record`, metadata: codeAgentBillingMetadata(params, traceId, { stage: "record", status: payload.status ?? "unknown" }) }); const billing = result.ok ? sanitizeBillingRecord(result.body, reservation) : { recorded: false, reservationId, errorCode: result.error?.code ?? "user_billing_record_failed", valuesRedacted: true }; payload.billing = billing; const traceStore = options.traceStore ?? defaultCodeAgentTraceStore; if (traceId) { traceStore.append(traceId, { type: "billing", status: result.ok ? "recorded" : "degraded", label: result.ok ? "billing:recorded" : "billing:record_failed", reservationId, recordId: result.ok ? result.body?.recordId ?? null : null, errorCode: result.ok ? null : billing.errorCode, valuesPrinted: false }); } return billing; } async function finalizeCodeAgentBillingUsage({ payload = {}, params = {}, options = {} } = {}) { if (payload.billing?.recorded === true || payload.billing?.released === true) return payload.billing; if (payload.status === "running") return null; if (payload.status === "completed") { return recordCodeAgentBillingUsage({ payload, params, options }); } return releaseCodeAgentBillingReservation({ payload, params, options }); } async function releaseCodeAgentBillingReservation({ payload = {}, params = {}, options = {} } = {}) { const reservation = params.userBillingReservation ?? payload.userBillingReservation; const reservationId = typeof reservation?.reservationId === "string" ? reservation.reservationId : ""; const client = options.userBillingClient; if (payload.billing?.recorded === true || payload.billing?.released === true || !reservationId || !client?.configured) return payload.billing ?? null; const traceId = safeTraceId(payload.traceId ?? params.traceId); const releaseReason = String(payload.status ?? "not_completed").trim() || "not_completed"; const releaseBody = { reservationId, serviceId: "hwlab-code-agent", idempotencyKey: `code-agent:${traceId}:release`, reason: releaseReason, metadata: codeAgentBillingMetadata(params, traceId, { stage: "release", status: payload.status ?? "unknown", errorCode: payload.error?.code ?? payload.blocker?.code ?? null }) }; const result = typeof client.billingRelease === "function" ? await client.billingRelease(releaseBody) : { ok: false, error: { code: "user_billing_release_not_supported" } }; const billing = result.ok ? sanitizeBillingRelease(result.body, reservation) : { released: false, reservationId, errorCode: result.error?.code ?? "user_billing_release_failed", valuesRedacted: true }; payload.billing = billing; const traceStore = options.traceStore ?? defaultCodeAgentTraceStore; if (traceId) { traceStore.append(traceId, { type: "billing", status: result.ok ? "released" : "degraded", label: result.ok ? "billing:released" : "billing:release_failed", reservationId, reason: releaseReason, errorCode: result.ok ? null : billing.errorCode, valuesPrinted: false }); } return billing; } function withCodeAgentBillingReservation(payload = {}, params = {}) { if (!payload || typeof payload !== "object" || payload.userBillingReservation) return payload; const reservation = params.userBillingReservation; return reservation ? { ...payload, userBillingReservation: reservation } : payload; } function codeAgentBillingEnabled(options = {}) { const env = options.env ?? process.env; if (String(env.HWLAB_USER_BILLING_CODE_AGENT_ENABLED ?? "").trim() === "0") return false; return Boolean(options.userBillingClient?.configured); } function codeAgentBillingMetadata(params = {}, traceId, extra = {}) { return { traceId, conversationId: safeConversationId(params.conversationId) || null, sessionId: safeSessionId(params.sessionId) || null, projectId: textValue(params.projectId) || null, route: "/v1/agent/chat", resource: "code-agent-turn", ...extra, valuesRedacted: true }; } function sanitizeBillingReservation(value = {}) { return { allowed: value.allowed === true, reservationId: textValue(value.reservationId) || null, resourceType: textValue(value.resourceType) || null, planId: textValue(value.planId) || null, estimatedCredits: Number.isFinite(Number(value.estimatedCredits)) ? Number(value.estimatedCredits) : null, estimatedTokens: Number.isFinite(Number(value.estimatedTokens)) ? Number(value.estimatedTokens) : null, expiresAt: textValue(value.expiresAt) || null, valuesRedacted: true }; } function sanitizeBillingRecord(value = {}, reservation = {}) { return { recorded: true, reservationId: textValue(reservation.reservationId) || null, recordId: textValue(value.recordId) || null, credits: Number.isFinite(Number(value.credits)) ? Number(value.credits) : null, balance: Number.isFinite(Number(value.balance)) ? Number(value.balance) : null, valuesRedacted: true }; } function sanitizeBillingRelease(value = {}, reservation = {}) { return { released: true, reservationId: textValue(value.reservationId) || textValue(reservation.reservationId) || null, releasedCredits: Number.isFinite(Number(value.releasedCredits)) ? Number(value.releasedCredits) : null, status: textValue(value.status) || "cancelled", valuesRedacted: true }; } function codeAgentUsedTokens(payload = {}) { const usage = payload.usage && typeof payload.usage === "object" ? payload.usage : null; const traceSummary = payload.traceSummary && typeof payload.traceSummary === "object" ? payload.traceSummary : null; const candidates = [ usage?.totalTokens, usage?.total_tokens, usage?.tokens, Number(usage?.inputTokens ?? usage?.input_tokens ?? 0) + Number(usage?.outputTokens ?? usage?.output_tokens ?? 0), traceSummary?.tokenCount, traceSummary?.tokens ]; for (const value of candidates) { const parsed = Number(value); if (Number.isFinite(parsed) && parsed > 0) return Math.ceil(parsed); } return 0; } export async function handleCodeAgentChatResultHttp(request, response, url, options) { const parts = url.pathname.split("/").filter(Boolean); const traceId = decodeURIComponent(parts[4] ?? ""); if (!safeTraceId(traceId)) { sendJson(response, 400, { error: { code: "invalid_trace_id", message: "traceId must start with trc_ and contain only safe identifier characters" } }); return; } const results = options.codeAgentChatResults; const result = results?.get(traceId) ?? null; if (result && !canAccessOwnedResult(result, options.actor)) { sendJson(response, 403, { error: { code: "agent_session_owner_required", message: "Only the session owner or admin can read this Code Agent result" } }); return; } const adapterEnabled = codeAgentAgentRunAdapterEnabled(options.env ?? process.env); if ((result?.agentRun?.runId && adapterEnabled) || (!result && adapterEnabled)) { try { const synced = await syncAgentRunChatResult({ traceId, currentResult: result, options, traceStore: options.traceStore ?? defaultCodeAgentTraceStore }); if (synced.result && !canAccessOwnedResult(synced.result, options.actor)) { sendJson(response, 403, { error: { code: "agent_session_owner_required", message: "Only the session owner or admin can read this Code Agent result" } }); return; } if (synced.result && synced.result.status !== "running") { await finalizeCodeAgentBillingUsage({ payload: synced.result, params: synced.result, options }); recordCodeAgentConversationFact(synced.result, options); await recordCodeAgentSessionOwner({ payload: synced.result, params: synced.result, options, status: codeAgentOwnerStatusForResult(synced.result) }); sendJson(response, 200, compactCodeAgentChatResultPayload(synced.result, options)); return; } if (synced.result) { sendJson(response, 202, { accepted: true, status: "running", shortConnection: true, traceId, agentRun: synced.result.agentRun, runnerTrace: compactRunnerTraceForResult(synced.runnerTrace, resultTraceEventLimit(options)), waitingFor: synced.runnerTrace?.waitingFor ?? "agentrun-result" }); return; } } catch (error) { const traceStore = options.traceStore ?? defaultCodeAgentTraceStore; traceStore.append(traceId, { type: "result", status: "degraded", label: "agentrun:result:poll-failed", errorCode: error?.code ?? "agentrun_result_poll_failed", message: error?.message ?? "AgentRun result polling failed", runId: result?.agentRun?.runId ?? null, commandId: result?.agentRun?.commandId ?? null, timeoutMs: numberOrNull(error?.timeoutMs), timeoutStage: textValue(error?.timeoutStage) || null, upstreamRoute: textValue(error?.route ?? error?.path) || null, waitingFor: "agentrun-result", valuesPrinted: false }); if (result?.agentRun && result.status === "running") { sendJson(response, 202, { accepted: true, status: "running", shortConnection: true, traceId, agentRun: result.agentRun, runnerTrace: compactRunnerTraceForResult(traceStore.snapshot(traceId), resultTraceEventLimit(options)), waitingFor: "agentrun-result", degraded: true, error: codeAgentRefreshErrorPayload(error, traceId, result?.agentRun, "agentrun_result_poll_failed") }); return; } if (result?.agentRun) { sendJson(response, error?.statusCode === 404 ? 404 : 502, { error: { code: error?.code ?? "agentrun_result_poll_failed", message: error?.message ?? "AgentRun result polling failed", traceId, runId: result.agentRun.runId ?? null, commandId: result.agentRun.commandId ?? null } }); return; } } } if (result && result.status !== "running") { sendJson(response, 200, compactCodeAgentChatResultPayload(result, options)); return; } const traceStore = options.traceStore ?? defaultCodeAgentTraceStore; const runnerTrace = traceStore.snapshot(traceId); if (result || runnerTrace.status !== "missing") { sendJson(response, 202, { accepted: true, status: "running", shortConnection: true, traceId, runnerTrace: compactRunnerTraceForResult(runnerTrace, resultTraceEventLimit(options)), waitingFor: runnerTrace.waitingFor ?? "codex-stdio" }); return; } sendJson(response, 404, { error: { code: "code_agent_result_not_found", message: `No Code Agent result is registered for ${traceId}` } }); } export async function handleCodeAgentTurnHttp(request, response, url, options) { const parts = url.pathname.split("/").filter(Boolean); const traceId = decodeURIComponent(parts[3] ?? ""); if (!safeTraceId(traceId)) { sendJson(response, 400, { ok: false, status: "unknown", running: false, terminal: false, error: { code: "invalid_trace_id", message: "traceId must start with trc_ and contain only safe identifier characters" } }); return; } const requestOptions = codeAgentRequestScopedOptions(options); const projectMismatch = await measureCodeAgentHttpPhase(requestOptions, "turn_project_check", () => traceProjectMismatchSnapshot(traceId, url, requestOptions, "turn")); if (projectMismatch) { sendJson(response, projectMismatch.statusCode, projectMismatch.body); return; } const resolved = await measureCodeAgentHttpPhase(requestOptions, "turn_resolve_status", () => resolveCodeAgentTurnStatusSnapshot(traceId, requestOptions)); sendJson(response, resolved.statusCode, resolved.body); } async function resolveCodeAgentTurnStatusSnapshot(traceId, options) { const traceStore = options.traceStore ?? defaultCodeAgentTraceStore; const refreshOptions = codeAgentTurnStatusRefreshOptions(options); let result = options.codeAgentChatResults?.get(traceId) ?? null; if (result && !canAccessOwnedResult(result, options.actor)) return forbiddenTurnSnapshot(traceId); const adapterEnabled = codeAgentAgentRunAdapterEnabled(options.env ?? process.env); let resultPollError = null; let turnRefreshSatisfiedByResultSync = false; if (adapterEnabled && (result?.agentRun?.runId || !result)) { try { const synced = await measureCodeAgentHttpPhase(options, "turn_result_sync", () => syncAgentRunChatResult({ traceId, currentResult: result, options: refreshOptions, traceStore })); result = synced.result ?? result; turnRefreshSatisfiedByResultSync = synced.eventsRefreshed === true || synced.resultSynced === true || synced.terminalRefreshSkipped === true; if (result && !canAccessOwnedResult(result, options.actor)) return forbiddenTurnSnapshot(traceId); if (result && isTraceCommandTerminalStatus(result.status)) { scheduleCodeAgentTerminalTurnStatusEffects({ payload: result, params: result, options }); } } catch (error) { resultPollError = error; traceStore.append(traceId, { type: "turn-status", status: "degraded", label: "turn-status:result-sync-failed", errorCode: error?.code ?? "agentrun_result_poll_failed", message: error?.message ?? "AgentRun result polling failed", runId: result?.agentRun?.runId ?? null, commandId: result?.agentRun?.commandId ?? null, timeoutMs: numberOrNull(error?.timeoutMs), timeoutStage: textValue(error?.timeoutStage) || null, upstreamRoute: textValue(error?.route ?? error?.path) || null, waitingFor: "agentrun-result", valuesPrinted: false }); } } let agentRunResult = result?.agentRun ? result : null; if (!agentRunResult && adapterEnabled) { try { agentRunResult = await measureCodeAgentHttpPhase(options, "turn_load_persisted_result", () => loadPersistedAgentRunResult(traceId, options)); } catch { agentRunResult = null; } } if (agentRunResult && !canAccessOwnedResult(agentRunResult, options.actor)) return forbiddenTurnSnapshot(traceId); let refreshError = null; if (agentRunResult?.agentRun && !turnRefreshSatisfiedByResultSync && !resultPollError) { try { const refreshedTrace = await measureCodeAgentHttpPhase(options, "turn_trace_refresh", () => refreshAgentRunTrace({ traceId, result: agentRunResult, options: refreshOptions, traceStore })); agentRunResult = options.codeAgentChatResults?.get?.(traceId) ?? agentRunResult; if (traceNeedsCommandResultSync(agentRunResult, refreshedTrace)) { const synced = await measureCodeAgentHttpPhase(options, "turn_force_result_sync", () => syncAgentRunChatResult({ traceId, currentResult: agentRunResult, options: refreshOptions, traceStore, appendResultEvent: false, refreshEvents: false, forceResultSync: true })); agentRunResult = synced.result ?? agentRunResult; } if (isTraceCommandTerminalStatus(agentRunResult?.status)) { scheduleCodeAgentTerminalTurnStatusEffects({ payload: agentRunResult, params: agentRunResult, options, preserveLastTraceId: true }); } } catch (error) { refreshError = error; } } const body = await measureCodeAgentHttpPhase(options, "turn_payload", () => { const snapshot = traceSnapshotWithTerminalEvidence(traceStore.snapshot(traceId), agentRunResult ?? result, traceId, refreshError); return codeAgentTurnStatusPayload({ traceId, result: agentRunResult ?? result, snapshot, resultPollError, refreshError, options }); }); return { statusCode: body.ok ? 200 : 404, body }; } function codeAgentTurnStatusRefreshOptions(options = {}) { const env = options.env ?? process.env; const configuredBudgetMs = parsePositiveInteger(env.HWLAB_CODE_AGENT_TURN_STATUS_REFRESH_TIMEOUT_MS, DEFAULT_CODE_AGENT_TURN_STATUS_REFRESH_TIMEOUT_MS); const upstreamTimeoutMs = parsePositiveInteger(env.HWLAB_CODE_AGENT_AGENTRUN_HTTP_TIMEOUT_MS, configuredBudgetMs); const timeoutMs = Math.max(1, Math.min(configuredBudgetMs, upstreamTimeoutMs)); return { ...options, skipAgentRunTerminalRefreshIfComplete: true, env: { ...env, HWLAB_CODE_AGENT_AGENTRUN_HTTP_TIMEOUT_MS: String(timeoutMs), HWLAB_CODE_AGENT_TURN_STATUS_REFRESH_TIMEOUT_MS: String(timeoutMs) } }; } function codeAgentRequestScopedOptions(options = {}) { return { ...options, codeAgentTraceSessionCache: options.codeAgentTraceSessionCache instanceof Map ? options.codeAgentTraceSessionCache : new Map() }; } async function measureCodeAgentHttpPhase(options, phase, callback) { const perf = options?.backendPerformance; return perf && typeof perf.measure === "function" ? await perf.measure(phase, callback) : await callback(); } function forbiddenTurnSnapshot(traceId) { return { statusCode: 403, body: { ok: false, status: "unknown", running: false, terminal: false, traceId, error: { code: "agent_session_owner_required", message: "Only the session owner or admin can read this Code Agent turn status" } } }; } async function traceProjectMismatchSnapshot(traceId, url, options, resourceKind) { const requestedProjectId = textValue(url.searchParams.get("projectId")); if (!requestedProjectId || !options.accessController?.getAgentSessionByTraceId) return null; const session = await getCodeAgentSessionByTraceId(traceId, options); if (!session) return null; if (session.ownerUserId && options.actor?.role !== "admin" && session.ownerUserId !== options.actor?.id) return forbiddenTurnSnapshot(traceId); const actualProjectId = textValue(session.projectId); if (!actualProjectId || actualProjectId === requestedProjectId) return null; return { statusCode: 404, body: { ok: false, status: "not_found", running: false, terminal: false, traceId, error: { code: "trace_project_mismatch", message: `${resourceKind === "turn" ? "Agent turn" : "Agent trace"} is not visible in the requested project` } } }; } async function getCodeAgentSessionByTraceId(traceId, options = {}) { const safeId = safeTraceId(traceId); if (!safeId || typeof options.accessController?.getAgentSessionByTraceId !== "function") return null; const cache = options.codeAgentTraceSessionCache; if (cache instanceof Map) { if (cache.has(safeId)) return cache.get(safeId); const session = await options.accessController.getAgentSessionByTraceId(safeId); cache.set(safeId, session ?? null); return session ?? null; } return await options.accessController.getAgentSessionByTraceId(safeId); } function codeAgentTurnStatusPayload({ traceId, result, snapshot, resultPollError, refreshError, options }) { const resultObject = result && typeof result === "object" ? result : null; const snapshotObject = snapshot && typeof snapshot === "object" ? snapshot : null; const lifecycle = codeAgentTurnLifecycleFields(traceId, resultObject ?? snapshotObject ?? {}); const events = Array.isArray(snapshotObject?.events) ? snapshotObject.events : Array.isArray(resultObject?.runnerTrace?.events) ? resultObject.runnerTrace.events : []; const lastEvent = events.at(-1) ?? null; const status = normalizeTurnStatus( resultObject?.status, resultObject?.agentRun?.terminalStatus, resultObject?.agentRun?.commandState, resultObject?.agentRun?.status, snapshotObject?.terminalEvidence?.traceSummary?.terminalStatus, snapshotObject?.traceStatus, snapshotObject?.status, snapshotObject?.runnerTrace?.status ); const found = Boolean(resultObject || (snapshotObject && snapshotObject.status !== "missing") || snapshotObject?.persisted === true); const running = isTurnRunningStatus(status); const terminal = isTurnTerminalStatus(status); const runnerTrace = snapshotObject && snapshotObject.status !== "missing" ? snapshotObject : resultObject?.runnerTrace ?? null; return { ok: found, action: "code-agent.turn.status", contractVersion: "code-agent-turn-status-v1", status: found ? status ?? "unknown" : "unknown", running: found ? running : false, terminal: found ? terminal : false, traceId, ...lifecycle, conversationId: safeConversationId(resultObject?.conversationId ?? snapshotObject?.conversationId) || null, sessionId: safeSessionId(resultObject?.sessionId ?? resultObject?.session?.sessionId ?? snapshotObject?.sessionId) || null, threadId: safeOpaqueId(resultObject?.threadId ?? resultObject?.session?.threadId ?? snapshotObject?.threadId) || null, updatedAt: textValue(resultObject?.updatedAt ?? resultObject?.agentRun?.updatedAt ?? snapshotObject?.updatedAt) || null, lastEventLabel: textValue(snapshotObject?.lastEventLabel ?? runnerTrace?.lastEventLabel ?? lastEvent?.label ?? lastEvent?.type) || null, waitingFor: textValue(snapshotObject?.waitingFor ?? runnerTrace?.waitingFor) || null, resultUrl: `/v1/agent/chat/result/${encodeURIComponent(traceId)}`, traceUrl: `/v1/agent/traces/${encodeURIComponent(traceId)}`, turnUrl: `/v1/agent/turns/${encodeURIComponent(traceId)}`, runnerTrace: runnerTrace ? compactRunnerTraceForResult(runnerTrace, resultTraceEventLimit(options)) : null, agentRun: resultObject?.agentRun ?? snapshotObject?.agentRun ?? null, terminalEvidence: snapshotObject?.terminalEvidence ?? null, finalResponse: resultObject?.finalResponse ?? snapshotObject?.finalResponse ?? snapshotObject?.terminalEvidence?.finalResponse ?? null, traceSummary: resultObject?.traceSummary ?? snapshotObject?.traceSummary ?? snapshotObject?.terminalEvidence?.traceSummary ?? null, retention: snapshotObject?.retention ?? null, eventCount: numberOrNull(snapshotObject?.eventCount ?? runnerTrace?.eventCount ?? events.length), error: resultPollError || refreshError ? codeAgentRefreshErrorPayload(resultPollError ?? refreshError, traceId, resultObject?.agentRun ?? snapshotObject?.agentRun, "turn_status_degraded") : resultObject?.error ?? snapshotObject?.error ?? null, valuesRedacted: true, secretMaterialStored: false }; } function codeAgentRefreshErrorPayload(error, traceId, agentRun, fallbackCode) { return { code: error?.code ?? fallbackCode, layer: error?.layer ?? "agentrun", category: error?.category ?? (error?.code === "agentrun_timeout" ? "upstream-timeout" : "upstream-refresh-failed"), retryable: error?.retryable !== false, message: error?.message ?? "Code Agent turn status refresh degraded", traceId, runId: agentRun?.runId ?? error?.runId ?? null, commandId: agentRun?.commandId ?? error?.commandId ?? null, method: error?.method ?? null, route: error?.route ?? error?.path ?? null, timeoutMs: numberOrNull(error?.timeoutMs), timeoutStage: error?.timeoutStage ?? null, upstreamStatus: numberOrNull(error?.statusCode), managerHost: error?.managerHost ?? null, valuesPrinted: false }; } function normalizeTurnStatus(...values) { for (const value of values) { const text = textValue(value).toLowerCase().replace(/_/gu, "-"); if (!text) continue; if (["accepted", "pending", "processing", "running", "busy", "creating", "queued", "in-flight"].includes(text)) return "running"; if (["completed", "done", "succeeded", "success"].includes(text)) return "completed"; if (["failed", "failure", "error", "stale", "thread-resume-failed", "aborted", "interrupted", "expired"].includes(text)) return "failed"; if (["cancelled", "canceled"].includes(text)) return "canceled"; if (["blocked", "timeout"].includes(text)) return text; } return null; } function isTurnRunningStatus(status) { return status === "running"; } function isTurnTerminalStatus(status) { return CODE_AGENT_TERMINAL_STATUSES.has(String(status ?? "").trim().toLowerCase().replace(/_/gu, "-")); } export async function handleCodeAgentInspectHttp(request, response, url, options) { const query = { conversationId: safeConversationId(url.searchParams.get("conversationId")), sessionId: safeSessionId(url.searchParams.get("sessionId")), threadId: safeOpaqueId(url.searchParams.get("threadId")), traceId: safeTraceId(url.searchParams.get("traceId")) }; const sessionRegistry = options.sessionRegistry; const traceStore = options.traceStore ?? defaultCodeAgentTraceStore; const manager = options.codexStdioManager; const managerDescription = manager && typeof manager.describe === "function" ? manager.describe() : null; const managerRecentSessions = Array.isArray(managerDescription?.recentSessions) ? managerDescription.recentSessions : []; const directManagerSession = query.sessionId && manager && typeof manager.get === "function" ? manager.get(query.sessionId, { conversationId: query.conversationId }) : null; const matchedManagerSession = directManagerSession ?? managerRecentSessions.find((session) => sessionMatchesInspectQuery(session, query)) ?? null; const registryInspect = sessionRegistry && typeof sessionRegistry.inspect === "function" ? sessionRegistry.inspect(query) : { ok: false, status: "unavailable", traceIds: [], session: null, conversationFacts: null }; const resultEvidence = await codeAgentInspectResultEvidence(query.traceId, options); const session = matchedManagerSession ?? registryInspect.session ?? resultEvidence.session ?? null; const conversationFacts = registryInspect.conversationFacts ?? resultEvidence.conversationFacts ?? null; const requestedRunnerTrace = query.traceId ? traceStore.snapshot(query.traceId) : null; const requestedTraceFound = Boolean(requestedRunnerTrace && requestedRunnerTrace.status !== "missing"); const traceIds = uniqueStrings([ requestedTraceFound ? query.traceId : null, session?.currentTraceId, session?.lastTraceId, conversationFacts?.latestTraceId, resultEvidence.latestTraceId, ...(Array.isArray(conversationFacts?.traceIds) ? conversationFacts.traceIds : []), ...(Array.isArray(registryInspect.traceIds) ? registryInspect.traceIds : []) ]); const latestTraceId = traceIds[0] ?? null; const runnerTrace = latestTraceId ? latestTraceId === query.traceId && requestedRunnerTrace ? requestedRunnerTrace : traceStore.snapshot(latestTraceId) : null; const found = Boolean(registryInspect.ok || session || latestTraceId); sendJson(response, found ? 200 : 404, { ok: found, action: "code-agent.chat.inspect", status: found ? "found" : "not_found", query, session, conversationFacts, traceIds, latestTraceId, traceUrl: latestTraceId ? `/v1/agent/traces/${encodeURIComponent(latestTraceId)}` : null, resultUrl: latestTraceId ? `/v1/agent/chat/result/${encodeURIComponent(latestTraceId)}` : null, runnerTrace, valuesRedacted: true, secretMaterialStored: false }); } async function codeAgentInspectResultEvidence(traceId, options = {}) { if (!safeTraceId(traceId)) return { session: null, conversationFacts: null, latestTraceId: null }; const cached = options.codeAgentChatResults?.get?.(traceId) ?? null; const persisted = cached ? null : await loadPersistedAgentRunResult(traceId, options); const result = cached ?? persisted ?? null; if (!result || typeof result !== "object") return { session: null, conversationFacts: null, latestTraceId: null }; const agentRun = result.agentRun && typeof result.agentRun === "object" ? result.agentRun : null; const resultSession = result.session && typeof result.session === "object" ? result.session : null; const sessionReuse = result.sessionReuse && typeof result.sessionReuse === "object" ? result.sessionReuse : null; const providerTrace = result.providerTrace && typeof result.providerTrace === "object" ? result.providerTrace : null; const sessionId = safeSessionId(result.sessionId ?? resultSession?.sessionId ?? sessionReuse?.sessionId ?? agentRun?.sessionId) || null; const conversationId = safeConversationId(result.conversationId ?? resultSession?.conversationId ?? sessionReuse?.conversationId ?? agentRun?.conversationId) || null; const threadId = safeOpaqueId(result.threadId ?? resultSession?.threadId ?? sessionReuse?.threadId ?? providerTrace?.threadId ?? agentRun?.threadId) || null; const status = textValue(resultSession?.status ?? result.status ?? agentRun?.status) || null; const updatedAt = textValue(result.updatedAt ?? agentRun?.updatedAt ?? resultSession?.updatedAt) || null; const session = sessionId || conversationId || threadId ? { sessionId, conversationId, threadId, status, lastTraceId: traceId, source: "code-agent-result", agentRun: agentRun ? agentRunSessionEvidence(result).agentRun : null, valuesRedacted: true, secretMaterialStored: false } : null; const conversationFacts = conversationId ? { conversationId, sessionId, threadId, latestTraceId: traceId, traceIds: [traceId], turnCount: 1, source: "code-agent-result", latestStatus: status, updatedAt, valuesRedacted: true, secretMaterialStored: false } : null; return { session, conversationFacts, latestTraceId: traceId }; } function sessionMatchesInspectQuery(session, query) { if (!session || typeof session !== "object") return false; if (query.sessionId && session.sessionId === query.sessionId) return true; if (query.threadId && session.threadId === query.threadId) return true; if (query.conversationId && session.conversationId === query.conversationId) return true; if (query.traceId && (session.currentTraceId === query.traceId || session.lastTraceId === query.traceId)) return true; return false; } export async function handleCodeAgentCancelHttp(request, response, options) { const body = await readBody(request, options.bodyLimitBytes); let params = {}; try { params = body ? JSON.parse(body) : {}; } catch (error) { sendJson(response, 400, { ...createCodeAgentErrorPayload({ code: "parse_error", message: "Invalid JSON body", reason: error.message, traceId: getHeader(request, "x-trace-id") || "trc_unassigned", layer: "api", retryable: true }) }); return; } if (!params || typeof params !== "object" || Array.isArray(params)) { sendJson(response, 400, { ...createCodeAgentErrorPayload({ code: "invalid_params", message: "Code Agent cancel body must be a JSON object", traceId: getHeader(request, "x-trace-id") || "trc_unassigned", layer: "api", retryable: true }) }); return; } const traceId = safeTraceId(getHeader(request, "x-trace-id") || params.traceId); const traceStore = options.traceStore ?? defaultCodeAgentTraceStore; const snapshot = traceId ? traceStore.snapshot(traceId) : null; const currentResult = traceId ? options.codeAgentChatResults?.get(traceId) ?? await loadPersistedAgentRunResult(traceId, options) : null; if (currentResult?.agentRun?.commandId) { const mismatch = codeAgentCancelScopeMismatch(params, currentResult); if (mismatch) { traceStore.append(traceId, { type: "cancel", status: "blocked", label: "agentrun:cancel:scope_mismatch", errorCode: "cancel_scope_mismatch", message: `Cancel request ${mismatch.field} does not match the trace owner; AgentRun cancel was not forwarded.`, requested: mismatch.requested, expected: mismatch.expected, waitingFor: "cancel-scope", valuesPrinted: false }); sendJson(response, 409, cancelBlockedPayload({ code: "cancel_scope_mismatch", message: `取消请求的 ${mismatch.field} 与 trace 归属不一致,已拒绝转发 AgentRun cancel,避免误取消其他 session。`, traceId, conversationId: safeConversationId(params.conversationId) || safeConversationId(currentResult.conversationId) || null, sessionId: safeSessionId(params.sessionId) || safeSessionId(currentResult.sessionId) || null, runnerTrace: traceStore.snapshot(traceId), status: "blocked" })); return; } const payload = await cancelAgentRunChatTurn({ traceId, currentResult, options, traceStore }); if (payload) { await recordCodeAgentSessionOwner({ payload, params: { ...params, traceId, ownerUserId: options.actor?.id, ownerRole: options.actor?.role }, options, status: "canceled" }); sendJson(response, 200, payload); return; } } const sessionId = safeSessionId(params.sessionId) || safeSessionId(snapshot?.sessionId); const conversationId = safeConversationId(params.conversationId); const manager = options.codexStdioManager; if (!traceId) { sendJson(response, 400, cancelBlockedPayload({ code: "cancel_trace_missing", message: "traceId is required to cancel the current Code Agent request.", traceId: "trc_unassigned", conversationId, sessionId })); return; } if (!manager || typeof manager.get !== "function" || typeof manager.cancel !== "function") { traceStore.append(traceId, { type: "cancel", status: "unsupported", label: "cancel:unsupported", errorCode: "cancel_unsupported", message: "Codex stdio cancel/interrupt backend is not available on this runtime.", waitingFor: "session-control" }); const runnerTrace = traceStore.snapshot(traceId); sendJson(response, 501, cancelBlockedPayload({ code: "cancel_unsupported", message: "当前后端不支持 Code Agent interrupt/cancel;本次按 unsupported/degraded 返回,不会静默假装已中断。", traceId, conversationId, sessionId, runnerTrace, status: "degraded", unsupported: true, degraded: true })); return; } if (!sessionId) { traceStore.append(traceId, { type: "cancel", status: "blocked", label: "cancel:not_cancelable", errorCode: "cancel_session_missing", message: "Cancel request did not include a bound Codex stdio sessionId.", waitingFor: "session-binding" }); sendJson(response, 409, cancelBlockedPayload({ code: "cancel_session_missing", message: "当前请求尚未暴露可取消的 Codex stdio sessionId;页面不能只隐藏 UI,已保留输入和 trace。", traceId, conversationId, sessionId: null, runnerTrace: traceStore.snapshot(traceId) })); return; } const currentSession = manager.get(sessionId, { conversationId }) ?? null; if (!currentSession || !["busy", "creating"].includes(currentSession.status)) { traceStore.append(traceId, { type: "cancel", status: "blocked", label: "cancel:not_in_flight", errorCode: "cancel_not_in_flight", message: `Session ${sessionId} is not an in-flight Codex stdio request.`, sessionId, sessionStatus: currentSession?.status ?? "missing" }); sendJson(response, 409, cancelBlockedPayload({ code: currentSession ? "cancel_not_in_flight" : "cancel_session_not_found", message: currentSession ? `当前 session 状态为 ${currentSession.status},没有可取消的 in-flight Codex stdio 请求。` : `没有找到 sessionId=${sessionId} 的 Codex stdio session。`, traceId, conversationId, sessionId, session: currentSession, runnerTrace: traceStore.snapshot(traceId) })); return; } const canceledSession = manager.cancel(sessionId, { traceId, conversationId, reason: "user_cancel" }); traceStore.append(traceId, { type: "cancel", status: "canceled", label: "cancel:canceled", message: "User canceled the current Codex stdio request.", sessionId, sessionStatus: canceledSession?.status ?? "canceled", sessionLifecycleStatus: codeAgentSessionLifecycleSummary({ session: canceledSession, status: "canceled" }).status, waitingFor: "user-retry", terminal: true }); const runnerTraceSnapshot = traceStore.snapshot(traceId); const sessionSummary = codeAgentSessionLifecycleSummary({ session: canceledSession, runnerTrace: runnerTraceSnapshot, status: "canceled" }); const runnerTrace = { ...runnerTraceSnapshot, sessionLifecycleStatus: sessionSummary.status }; const payload = { accepted: true, canceled: true, status: "canceled", conversationId: conversationId ?? canceledSession?.conversationId ?? null, sessionId, traceId, session: canceledSession, sessionLifecycleStatus: sessionSummary.status, sessionLifecycle: sessionSummary, sessionSummary, runnerTrace, lastTraceEvent: runnerTrace.lastEvent, retryable: true, error: { code: "codex_stdio_canceled", layer: "session", category: "canceled", retryable: true, message: "user canceled current Code Agent request", userMessage: "当前 Codex stdio 请求已取消;输入、sessionId、traceId 和最后 trace event 已保留,可重试上一条消息。", traceId, route: "/v1/agent/chat/cancel", toolName: "codex-stdio.cancel" }, userMessage: "当前 Codex stdio 请求已取消;输入、sessionId、traceId 和最后 trace event 已保留,可重试上一条消息。", updatedAt: new Date().toISOString() }; await recordCodeAgentSessionOwner({ payload, params: { ...params, traceId, ownerUserId: options.actor?.id, ownerRole: options.actor?.role }, options, status: "canceled" }); recordCodeAgentConversationFact(payload, options); options.codeAgentChatResults?.set(traceId, annotateOwner(payload, { ownerUserId: options.actor?.id, ownerRole: options.actor?.role })); sendJson(response, 200, payload); } function recordCodeAgentConversationFact(payload = {}, options = {}) { const registry = options.sessionRegistry; const conversationId = safeConversationId(payload.conversationId); if (!conversationId || typeof registry?.recordFact !== "function") return null; try { return registry.recordFact(conversationId, { kind: payload.status === "completed" ? "runner_turn" : "runner_turn_terminal", conversationId, sessionId: payload.sessionId, traceId: payload.traceId, provider: payload.provider, backend: payload.backend, workspace: payload.workspace, sandbox: payload.sandbox, session: payload.session, sessionMode: payload.sessionMode, sessionReuse: payload.sessionReuse, implementationType: payload.implementationType, runner: payload.runner, runnerTrace: payload.runnerTrace, partialContext: payload.partialContext ?? payload.runnerTrace?.partialContext, capabilityLevel: payload.capabilityLevel, toolCalls: payload.toolCalls, skills: payload.skills }, { now: options.now }); } catch { return null; } } async function recordCodeAgentTerminalTurnStatusEffects({ payload = {}, params = {}, options = {}, preserveLastTraceId = false } = {}) { if (!payload || typeof payload !== "object" || !isTraceCommandTerminalStatus(payload.status)) return null; if (payload.turnStatusTerminalEffects?.recorded === true) return payload.turnStatusTerminalEffects; const billing = await finalizeCodeAgentBillingUsage({ payload, params, options }); recordCodeAgentConversationFact(payload, options); const owner = await recordCodeAgentSessionOwner({ payload, params, options, status: codeAgentOwnerStatusForResult(payload), preserveLastTraceId }); const billingSettled = codeAgentTerminalBillingSettled({ payload, params, options, billing }); const ownerRequired = Boolean(options.actor?.id && options.accessController?.recordAgentSessionOwner); const ownerSettled = !ownerRequired || Boolean(owner); const effects = { recorded: billingSettled && ownerSettled, pending: false, billingSettled, ownerSettled, preserveLastTraceId: Boolean(preserveLastTraceId), recordedAt: new Date().toISOString(), valuesPrinted: false }; payload.turnStatusTerminalEffects = effects; const traceId = safeTraceId(payload.traceId ?? params.traceId); if (traceId) options.codeAgentChatResults?.set?.(traceId, payload); return effects; } function scheduleCodeAgentTerminalTurnStatusEffects({ payload = {}, params = {}, options = {}, preserveLastTraceId = false } = {}) { if (!payload || typeof payload !== "object" || !isTraceCommandTerminalStatus(payload.status)) return null; const existing = payload.turnStatusTerminalEffects; if (existing?.recorded === true || existing?.pending === true) return existing; const traceId = safeTraceId(payload.traceId ?? params.traceId); const pending = { recorded: false, pending: true, billingSettled: false, ownerSettled: false, preserveLastTraceId: Boolean(preserveLastTraceId), scheduledAt: new Date().toISOString(), valuesPrinted: false }; payload.turnStatusTerminalEffects = pending; if (traceId) options.codeAgentChatResults?.set?.(traceId, payload); setImmediate(() => { void recordCodeAgentTerminalTurnStatusEffects({ payload, params, options, preserveLastTraceId }).catch((error) => { const failed = { recorded: false, pending: false, billingSettled: false, ownerSettled: false, preserveLastTraceId: Boolean(preserveLastTraceId), errorCode: error?.code ?? "terminal_turn_status_effects_failed", recordedAt: new Date().toISOString(), valuesPrinted: false }; payload.turnStatusTerminalEffects = failed; if (traceId) { options.codeAgentChatResults?.set?.(traceId, payload); (options.traceStore ?? defaultCodeAgentTraceStore).append(traceId, { type: "turn-status", status: "degraded", label: "turn-status:terminal-effects-failed", errorCode: failed.errorCode, message: error?.message ?? "Terminal turn status side effects failed and will retry on the next poll.", valuesPrinted: false }); } }); }); return pending; } function codeAgentTerminalBillingSettled({ payload = {}, params = {}, options = {}, billing = null } = {}) { const reservation = params.userBillingReservation ?? payload.userBillingReservation; const reservationId = typeof reservation?.reservationId === "string" ? reservation.reservationId : ""; if (!reservationId || !options.userBillingClient?.configured) return true; return billing?.recorded === true || billing?.released === true || payload.billing?.recorded === true || payload.billing?.released === true; } export async function handleCodeAgentSteerHttp(request, response, options) { const body = await readBody(request, options.bodyLimitBytes); let params = {}; try { params = body ? JSON.parse(body) : {}; } catch (error) { sendJson(response, 400, { ...createCodeAgentErrorPayload({ code: "parse_error", message: "Invalid JSON body", reason: error.message, traceId: getHeader(request, "x-trace-id") || "trc_unassigned", layer: "api", retryable: true, route: "/v1/agent/chat/steer" }) }); return; } if (!params || typeof params !== "object" || Array.isArray(params)) { sendJson(response, 400, { ...createCodeAgentErrorPayload({ code: "invalid_params", message: "Code Agent steer body must be a JSON object", traceId: getHeader(request, "x-trace-id") || "trc_unassigned", layer: "api", retryable: true, route: "/v1/agent/chat/steer" }) }); return; } const traceId = safeTraceId(getHeader(request, "x-trace-id") || params.traceId || params.targetTraceId); const message = firstNonEmptyValue(params.message, params.prompt, params.text); if (!traceId || !message) { sendJson(response, 400, { ...createCodeAgentErrorPayload({ code: !traceId ? "steer_trace_missing" : "steer_message_missing", message: !traceId ? "traceId is required to steer the current Code Agent turn." : "message is required to steer the current Code Agent turn.", traceId: traceId || "trc_unassigned", layer: "api", retryable: true, route: "/v1/agent/chat/steer" }) }); return; } const traceStore = options.traceStore ?? defaultCodeAgentTraceStore; const currentResult = options.codeAgentChatResults?.get?.(traceId) ?? await loadPersistedAgentRunResult(traceId, options); if (!canAccessOwnedResult(currentResult, options.actor)) { sendJson(response, 403, { ok: false, status: "forbidden", traceId, error: { code: "code_agent_trace_forbidden", message: "Code Agent trace is not visible to the current actor" } }); return; } if (!currentResult?.agentRun?.runId || !currentResult?.agentRun?.commandId) { sendJson(response, 404, { ok: false, status: "not_found", traceId, error: { code: "steer_trace_not_found", message: "No AgentRun-backed Code Agent turn was found for the requested traceId." }, route: "/v1/agent/chat/steer", runnerTrace: traceStore.snapshot(traceId) }); return; } if (isTraceCommandTerminalStatus(currentResult.status)) { sendJson(response, 409, { ok: false, accepted: false, status: "blocked", traceId, route: "/v1/agent/chat/steer", sessionId: safeSessionId(currentResult.sessionId ?? params.sessionId) || null, threadId: safeOpaqueId(currentResult.threadId ?? params.threadId) || null, agentRun: currentResult.agentRun, runnerTrace: traceStore.snapshot(traceId), error: { code: "steer_trace_terminal", layer: "api", category: "not_in_flight", retryable: false, message: `Trace ${traceId} is already terminal and cannot accept a steer command.`, traceId, route: "/v1/agent/chat/steer", toolName: "agentrun.command.steer" }, valuesPrinted: false }); return; } try { const payload = await steerAgentRunChatTurn({ traceId, currentResult, params: { ...params, message, ownerUserId: options.actor?.id ?? params.ownerUserId, ownerRole: options.actor?.role ?? params.ownerRole }, options, traceStore }); sendJson(response, 202, payload); setImmediate(() => { void recordCodeAgentSessionOwner({ payload: currentResult, params: { ...params, traceId, ownerUserId: options.actor?.id, ownerRole: options.actor?.role }, options, status: "running" }); }); } catch (error) { traceStore.append(traceId, { type: "backend", status: "failed", label: "agentrun:steer:failed", errorCode: error?.code ?? "agentrun_steer_failed", message: error?.message ?? "AgentRun steer command failed.", terminal: false, valuesPrinted: false }); sendJson(response, error?.statusCode === 404 ? 404 : 409, { ok: false, accepted: false, status: "failed", traceId, route: "/v1/agent/chat/steer", sessionId: safeSessionId(currentResult.sessionId ?? params.sessionId) || null, threadId: safeOpaqueId(currentResult.threadId ?? params.threadId) || null, agentRun: currentResult.agentRun, runnerTrace: traceStore.snapshot(traceId), error: { code: error?.code ?? "agentrun_steer_failed", layer: "agentrun", category: "steer_failed", retryable: true, message: error?.message ?? "AgentRun steer command failed.", traceId, route: "/v1/agent/chat/steer", toolName: "agentrun.command.steer" } }); } } async function recordCodeAgentSessionOwner({ payload = {}, params = {}, options = {}, status = "active", preserveLastTraceId = false } = {}) { const ownerUserId = options.actor?.id ?? params.ownerUserId; if (!ownerUserId || !options.accessController?.recordAgentSessionOwner) return null; const traceId = safeTraceId(payload.traceId ?? params.traceId); const session = payload.session && typeof payload.session === "object" ? payload.session : null; const sessionReuse = payload.sessionReuse && typeof payload.sessionReuse === "object" ? payload.sessionReuse : null; const sessionId = safeSessionId(payload.sessionId ?? session?.sessionId ?? sessionReuse?.sessionId ?? params.sessionId) || null; const conversationId = safeConversationId(payload.conversationId ?? session?.conversationId ?? sessionReuse?.conversationId ?? params.conversationId) || null; const threadId = safeOpaqueId(session?.threadId ?? sessionReuse?.threadId ?? payload.threadId ?? params.threadId) || null; return writeWorkbenchProjectionSession({ accessController: options.accessController, traceStore: options.traceStore ?? defaultCodeAgentTraceStore, traceId, ownerUserId, ownerRole: options.actor?.role ?? params.ownerRole ?? null, sessionId, projectId: params.projectId ?? payload.projectId ?? null, conversationId, threadId, status, preserveLastTraceId, session: codeAgentSessionOwnerEvidence(payload, params) }); } function codeAgentOwnerStatusForResult(result = {}) { const sessionStatus = textValue(result?.session?.status ?? result?.sessionSummary?.status ?? result?.sessionLifecycleStatus); if (sessionStatus === "thread-resume-failed") return "thread-resume-failed"; if (result?.status === "completed") return "completed"; if (result?.status === "canceled" || result?.status === "cancelled") return "canceled"; return result?.status ?? "active"; } async function resolveWorkbenchActiveTraceResult(traceId, options = {}) { if (!safeTraceId(traceId)) return null; const cached = options.codeAgentChatResults?.get?.(traceId) ?? null; if (cached?.agentRun?.runId) { try { const synced = await syncAgentRunChatResult({ traceId, currentResult: cached, options, traceStore: options.traceStore ?? defaultCodeAgentTraceStore }); return synced.result ?? null; } catch { return null; } } if (cached) return cached; if (!codeAgentAgentRunAdapterEnabled(options.env ?? process.env)) return null; try { const persisted = await loadPersistedAgentRunResult(traceId, options); if (!persisted?.agentRun?.runId) return persisted; const synced = await syncAgentRunChatResult({ traceId, currentResult: persisted, options, traceStore: options.traceStore ?? defaultCodeAgentTraceStore }); return synced.result ?? null; } catch { return null; } } function textValue(value) { return String(value ?? "").trim(); } function codeAgentSessionOwnerEvidence(payload = {}, params = {}) { const traceId = payload.traceId ?? params.traceId ?? null; const finalResponse = codeAgentFinalResponseEvidence(payload, traceId); const traceSummary = codeAgentTraceSummaryEvidence(payload, traceId, finalResponse); const messages = codeAgentConversationMessagesEvidence(payload, params, traceId, finalResponse); const firstUserMessagePreview = messages.find((message) => message.role === "user")?.text?.slice(0, 240) ?? null; const promptEvidence = codeAgentPromptMetadata(payload, params, traceId); const traceResult = codeAgentTraceResultEvidence(payload, params, traceId, finalResponse, traceSummary); return { provider: payload.provider ?? null, model: payload.model ?? null, backend: payload.backend ?? null, status: payload.status ?? null, sessionMode: payload.sessionMode ?? payload.session?.sessionMode ?? null, sessionLifecycleStatus: payload.sessionLifecycleStatus ?? null, runnerKind: payload.runner?.kind ?? payload.runnerTrace?.runnerKind ?? null, conversationId: payload.conversationId ?? params.conversationId ?? null, sessionId: payload.sessionId ?? payload.session?.sessionId ?? payload.sessionReuse?.sessionId ?? params.sessionId ?? null, threadId: payload.session?.threadId ?? payload.sessionReuse?.threadId ?? payload.threadId ?? params.threadId ?? null, traceId, projectId: payload.projectId ?? params.projectId ?? null, ...codeAgentPromptFields(promptEvidence), finalResponse, traceSummary, ...(traceResult ? { traceResults: { [traceResult.traceId]: traceResult } } : {}), ...(messages.length ? { messages, messageCount: messages.length } : {}), ...(firstUserMessagePreview ? { firstUserMessagePreview } : {}), ...agentRunSessionEvidence(payload), secretMaterialStored: false, valuesRedacted: true }; } function codeAgentTraceResultEvidence(payload = {}, params = {}, traceId = null, finalResponse = null, traceSummary = null) { const resolvedTraceId = safeTraceId(traceId); if (!resolvedTraceId) return null; const agentRun = agentRunSessionEvidence(payload).agentRun ?? null; const userBillingReservation = codeAgentBillingReservationEvidence(payload.userBillingReservation ?? params.userBillingReservation); const resultSession = payload.session && typeof payload.session === "object" ? payload.session : null; const sessionReuse = payload.sessionReuse && typeof payload.sessionReuse === "object" ? payload.sessionReuse : null; const conversationId = safeConversationId(payload.conversationId ?? agentRun?.conversationId ?? resultSession?.conversationId ?? sessionReuse?.conversationId ?? params.conversationId) || null; const sessionId = safeSessionId(payload.sessionId ?? resultSession?.sessionId ?? sessionReuse?.sessionId ?? params.sessionId) || null; const threadId = safeOpaqueId(payload.threadId ?? resultSession?.threadId ?? sessionReuse?.threadId ?? params.threadId ?? agentRun?.threadId) || null; const promptEvidence = codeAgentPromptMetadata(payload, params, resolvedTraceId); if (!agentRun && !finalResponse && !traceSummary) return null; return { traceId: resolvedTraceId, status: payload.status ?? agentRun?.terminalStatus ?? agentRun?.commandState ?? null, conversationId, sessionId, threadId, ...codeAgentPromptFields(promptEvidence), messageId: finalResponse?.messageId ?? payload.messageId ?? null, createdAt: payload.createdAt ?? finalResponse?.createdAt ?? null, updatedAt: payload.updatedAt ?? finalResponse?.updatedAt ?? null, finalResponse, traceSummary, agentRun, ...(userBillingReservation ? { userBillingReservation } : {}), valuesRedacted: true, secretMaterialStored: false }; } function codeAgentPromptMetadata(payload = {}, params = {}, traceId = null) { const prompt = payload?.prompt && typeof payload.prompt === "object" ? payload.prompt : null; const rawPrompt = firstNonEmptyValue( params.message, params.prompt, params.text, payload.userMessage, typeof payload.prompt === "string" ? payload.prompt : null ); const fromText = codeAgentPromptMetadataFromText(rawPrompt, traceId, "code-agent-request", { fullText: Boolean(rawPrompt) }); return codeAgentPromptMetadataFromParts({ traceId, source: prompt?.source ?? payload.promptSource ?? fromText?.prompt?.source ?? "code-agent-request", promptId: firstNonEmptyValue(payload.promptId, prompt?.id, fromText?.promptId), promptSha256: firstNonEmptyValue(payload.promptSha256, prompt?.sha256, fromText?.promptSha256), promptSummary: firstNonEmptyValue(payload.promptSummary, prompt?.summary, fromText?.promptSummary), promptPreview: firstNonEmptyValue(payload.promptPreview, prompt?.preview, fromText?.promptPreview), textChars: Number.isInteger(prompt?.textChars) ? prompt.textChars : fromText?.prompt?.textChars }); } function codeAgentPromptMetadataFromText(value, traceId = null, source = "code-agent-request", options = {}) { const promptText = String(value ?? "").trim(); if (!promptText) return null; return codeAgentPromptMetadataFromParts({ traceId, source, promptSha256: options.fullText === true ? sha256Text(promptText) : undefined, promptSummary: promptText, promptPreview: promptText, textChars: options.fullText === true ? promptText.length : undefined }); } function codeAgentPromptMetadataFromParts({ traceId = null, source = "code-agent-request", promptId = null, promptSha256 = null, promptSummary = null, promptPreview = null, textChars = undefined } = {}) { const digest = firstNonEmptyValue(promptSha256); const summary = clippedPromptText(firstNonEmptyValue(promptSummary, promptPreview), 240); const preview = clippedPromptText(firstNonEmptyValue(promptPreview, promptSummary), 500); const explicitId = firstNonEmptyValue(promptId); if (!explicitId && !digest && !summary && !preview) return null; const id = explicitId || codeAgentPromptId(traceId, digest); const prompt = compactCodeAgentObject({ id, sha256: digest || undefined, summary, preview, textChars: Number.isInteger(textChars) ? textChars : undefined, source, valuesPrinted: false }); return compactCodeAgentObject({ promptId: id, promptSha256: digest || undefined, promptSummary: summary, promptPreview: preview, prompt, valuesPrinted: false }) ?? null; } function codeAgentPromptFields(metadata = null) { if (!metadata) return {}; return compactCodeAgentObject({ promptId: metadata.promptId, promptSha256: metadata.promptSha256, promptSummary: metadata.promptSummary, promptPreview: metadata.promptPreview, prompt: metadata.prompt }) ?? {}; } function codeAgentPromptId(traceId = null, digest = null) { const traceSuffix = safeTraceId(traceId)?.slice(4).replace(/[^A-Za-z0-9_.:-]/gu, "_"); const digestSuffix = firstNonEmptyValue(digest)?.slice(0, 16); const suffix = firstNonEmptyValue(traceSuffix, digestSuffix); return suffix ? `prm_${suffix}` : undefined; } function clippedPromptText(value, limit) { const promptText = String(value ?? "").trim(); if (!promptText) return undefined; return promptText.length > limit ? `${promptText.slice(0, limit)}...` : promptText; } function sha256Text(value) { return createHash("sha256").update(String(value)).digest("hex"); } function compactCodeAgentObject(value) { const result = {}; for (const [key, item] of Object.entries(value ?? {})) { if (item === undefined || item === null) continue; if (Array.isArray(item) && item.length === 0) continue; if (typeof item === "object" && !Array.isArray(item) && Object.keys(item).length === 0) continue; result[key] = item; } return Object.keys(result).length > 0 ? result : undefined; } function codeAgentBillingReservationEvidence(value = null) { if (!value || typeof value !== "object") return null; const reservationId = textValue(value.reservationId); if (!reservationId) return null; return { reservationId, resourceType: textValue(value.resourceType) || null, planId: textValue(value.planId) || null, estimatedCredits: numberOrNull(value.estimatedCredits), estimatedTokens: numberOrNull(value.estimatedTokens), expiresAt: textValue(value.expiresAt) || null, valuesRedacted: true, secretMaterialStored: false }; } function codeAgentConversationMessagesEvidence(payload = {}, params = {}, traceId = null, finalResponse = null) { const userText = boundedConversationMessageText(params.message ?? params.prompt ?? payload.userMessage ?? payload.prompt); if (!userText) return []; const resolvedTraceId = safeTraceId(traceId) || null; const lifecycle = codeAgentTurnLifecycleFields(resolvedTraceId, payload); const session = payload.session && typeof payload.session === "object" ? payload.session : null; const sessionReuse = payload.sessionReuse && typeof payload.sessionReuse === "object" ? payload.sessionReuse : null; const conversationId = safeConversationId(payload.conversationId ?? session?.conversationId ?? sessionReuse?.conversationId ?? params.conversationId) || null; const sessionId = safeSessionId(payload.sessionId ?? session?.sessionId ?? sessionReuse?.sessionId ?? params.sessionId) || null; const threadId = safeOpaqueId(session?.threadId ?? sessionReuse?.threadId ?? payload.threadId ?? params.threadId) || null; const createdAt = payload.createdAt ?? payload.reply?.createdAt ?? new Date().toISOString(); const updatedAt = payload.updatedAt ?? createdAt; const userMessage = { id: lifecycle.userMessageId, messageId: lifecycle.userMessageId, role: "user", title: "用户", text: userText, status: "sent", traceId: resolvedTraceId, turnId: lifecycle.turnId, conversationId, sessionId, threadId, createdAt, updatedAt, source: "code-agent-submit", secretMaterialStored: false, valuesRedacted: true }; const agentText = boundedConversationMessageText( finalResponse?.text ?? payload.reply?.content ?? payload.message?.content ?? payload.assistantText ?? payload.error?.userMessage ?? payload.error?.message ?? payload.blocker?.userMessage ?? payload.blocker?.message ?? payload.blocker?.summary ); const agentStatus = codeAgentConversationAgentMessageStatus(payload); const agentMessage = { id: lifecycle.assistantMessageId, messageId: lifecycle.assistantMessageId, role: "agent", title: agentStatus === "failed" ? "Code Agent 返回阻塞" : agentStatus === "running" ? "Code Agent 处理中" : "Code Agent 回复", text: agentText || (agentStatus === "running" ? "" : "Code Agent 请求已结束,请查看 Trace 详情。"), status: agentStatus, traceId: resolvedTraceId, turnId: lifecycle.turnId, conversationId, sessionId, threadId, createdAt: payload.reply?.createdAt ?? updatedAt, updatedAt, source: "code-agent-result", ...(payload.runnerTrace && typeof payload.runnerTrace === "object" ? { runnerTrace: codeAgentConversationRunnerTraceEvidence(payload.runnerTrace, resolvedTraceId) } : {}), secretMaterialStored: false, valuesRedacted: true }; return [userMessage, agentMessage]; } function boundedConversationMessageText(value, limit = 12000) { const text = conversationText(value); if (!text) return ""; return text.length > limit ? text.slice(0, limit) : text; } function conversationText(value) { const extracted = conversationTextRaw(value).replace(/\s+/gu, " ").trim(); if (!extracted || extracted === "[object Object]") return ""; return extracted; } function conversationTextRaw(value) { if (value === undefined || value === null) return ""; if (typeof value === "string") return value; if (typeof value === "number" || typeof value === "boolean") return String(value); if (Array.isArray(value)) return value.map(conversationTextRaw).filter(Boolean).join("\n"); if (typeof value === "object") { for (const key of ["text", "content", "message", "prompt", "value", "summary", "preview", "title"]) { const text = conversationTextRaw(value[key]); if (text) return text; } } return ""; } function codeAgentMessageTraceSuffix(traceId) { const text = safeTraceId(traceId) || `local_${Date.now().toString(36)}`; return text.replace(/^trc_/u, "").replace(/[^A-Za-z0-9_.:-]/gu, "_").slice(0, 48) || "trace"; } function codeAgentTurnLifecycleFields(traceId, source = {}) { const resolvedTraceId = safeTraceId(source?.traceId ?? traceId) || safeTraceId(traceId) || null; const turnId = safeTurnId(source?.turnId) || resolvedTraceId; const traceSuffix = codeAgentMessageTraceSuffix(resolvedTraceId); return { turnId, userMessageId: safeMessageId(source?.userMessageId ?? source?.userMessage?.messageId) || codeAgentLifecycleMessageId(traceSuffix, "user"), assistantMessageId: safeMessageId(source?.assistantMessageId ?? source?.assistantMessage?.messageId) || codeAgentLifecycleMessageId(traceSuffix, "agent") }; } function codeAgentLifecycleMessageId(traceSuffix, role) { return `msg_${traceSuffix}_${role}`; } function safeTurnId(value) { const text = textValue(value); return /^turn_[A-Za-z0-9_.:-]+$/u.test(text) ? text : null; } function safeMessageId(value) { const text = textValue(value); return /^msg_[A-Za-z0-9_.:-]+$/u.test(text) ? text : null; } function codeAgentConversationAgentMessageStatus(payload = {}) { const status = textValue(payload.status ?? payload.agentRun?.terminalStatus ?? payload.commandState ?? payload.runStatus).toLowerCase(); if (["completed", "done", "success", "active"].includes(status)) return "completed"; if (["failed", "blocked", "error", "timeout", "canceled", "cancelled"].includes(status)) return "failed"; if (payload.error || payload.blocker) return "failed"; return "running"; } function codeAgentConversationRunnerTraceEvidence(runnerTrace = {}, traceId = null) { const events = Array.isArray(runnerTrace.events) ? runnerTrace.events : []; const lastEvent = runnerTrace.lastEvent && typeof runnerTrace.lastEvent === "object" ? runnerTrace.lastEvent : events.at(-1) ?? null; const eventCount = Number.isFinite(Number(runnerTrace.eventCount)) ? Number(runnerTrace.eventCount) : events.length; return { traceId: safeTraceId(runnerTrace.traceId ?? traceId) || traceId || null, status: runnerTrace.status ?? lastEvent?.status ?? null, sessionId: runnerTrace.sessionId ?? null, threadId: runnerTrace.threadId ?? null, runId: runnerTrace.runId ?? lastEvent?.runId ?? null, commandId: runnerTrace.commandId ?? lastEvent?.commandId ?? null, eventCount, lastEvent: lastEvent ? { label: lastEvent.label ?? null, status: lastEvent.status ?? null, terminal: lastEvent.terminal === true, createdAt: lastEvent.createdAt ?? null, message: boundedConversationMessageText(lastEvent.message ?? lastEvent.text, 1000), valuesPrinted: false } : null, eventsCompacted: true, fullTraceLoaded: false, valuesPrinted: false }; } function codeAgentFinalResponseEvidence(payload = {}, traceId = null) { const text = textValue(payload.reply?.content ?? payload.message?.content ?? payload.assistantText); if (!text) return null; return { text, textChars: text.length, messageId: payload.reply?.messageId ?? payload.messageId ?? null, role: payload.reply?.role ?? payload.message?.role ?? "assistant", status: payload.status ?? null, traceId, createdAt: payload.reply?.createdAt ?? payload.createdAt ?? null, updatedAt: payload.updatedAt ?? null, source: "code-agent-result", valuesPrinted: false }; } function codeAgentTraceSummaryEvidence(payload = {}, traceId = null, finalResponse = null) { const runnerTrace = payload.runnerTrace && typeof payload.runnerTrace === "object" ? payload.runnerTrace : null; const events = Array.isArray(runnerTrace?.events) ? runnerTrace.events : []; const terminalEvent = [...events].reverse().find((event) => event?.terminal === true) ?? runnerTrace?.lastEvent ?? null; return { traceId, source: "code-agent-derived-session-evidence", sourceEventCount: Number.isFinite(Number(runnerTrace?.eventCount)) ? Number(runnerTrace.eventCount) : events.length, terminalStatus: payload.agentRun?.terminalStatus ?? payload.status ?? terminalEvent?.status ?? null, lastEventLabel: terminalEvent?.label ?? null, finalAssistantRow: finalResponse ? { role: finalResponse.role, status: finalResponse.status, textChars: finalResponse.textChars, textPreview: finalResponse.text.slice(0, 240), messageId: finalResponse.messageId, valuesPrinted: false } : null, agentRun: payload.agentRun ? { runId: payload.agentRun.runId ?? null, commandId: payload.agentRun.commandId ?? null, attemptId: payload.agentRun.attemptId ?? null, runnerId: payload.agentRun.runnerId ?? null, jobName: payload.agentRun.jobName ?? null, namespace: payload.agentRun.namespace ?? null, lastSeq: payload.agentRun.lastSeq ?? null, valuesPrinted: false } : null, updatedAt: payload.updatedAt ?? null, valuesPrinted: false }; } function annotateOwner(payload, params = {}) { if (!params.ownerUserId) return payload; return { ...payload, ownerUserId: params.ownerUserId, ownerRole: params.ownerRole ?? null }; } function canAccessOwnedResult(result, actor) { if (!result?.ownerUserId || !actor) return true; return actor.role === "admin" || actor.id === result.ownerUserId; } function isCodeAgentResultCanceled(result) { return result?.status === "canceled" || result?.canceled === true || result?.error?.code === "codex_stdio_canceled"; } function codeAgentCancelScopeMismatch(params = {}, result = {}) { return cancelScopeFieldMismatch("conversationId", safeConversationId(params.conversationId), cancelExpectedValues(safeConversationId, result.conversationId, result.agentRun?.conversationId, result.session?.conversationId, result.sessionReuse?.conversationId, result.runnerTrace?.conversationId )) ?? cancelScopeFieldMismatch("sessionId", safeSessionId(params.sessionId), cancelExpectedValues(safeSessionId, result.sessionId, result.session?.sessionId, result.sessionReuse?.sessionId, result.agentRun?.hwlabSessionId )) ?? cancelScopeFieldMismatch("threadId", safeOpaqueId(params.threadId), cancelExpectedValues(safeOpaqueId, result.threadId, result.agentRun?.threadId, result.session?.threadId, result.sessionReuse?.threadId, result.runnerTrace?.threadId )); } function cancelExpectedValues(normalize, ...values) { return [...new Set(values.map((value) => normalize(value)).filter(Boolean))]; } function cancelScopeFieldMismatch(field, requested, expectedValues) { if (!requested || expectedValues.length === 0 || expectedValues.includes(requested)) return null; return { field, requested, expected: expectedValues[0] }; } function cancelBlockedPayload({ code, message, traceId, conversationId = null, sessionId = null, session = null, runnerTrace = null, status = "failed", unsupported = false, degraded = false }) { const sessionSummary = codeAgentSessionLifecycleSummary({ session, runnerTrace, status, unsupported, degraded, error: { code, userMessage: message, message } }); return { accepted: false, canceled: false, status, conversationId, sessionId, traceId, session, sessionLifecycleStatus: sessionSummary.status, sessionLifecycle: sessionSummary, sessionSummary, unsupported, degraded, runnerTrace, lastTraceEvent: runnerTrace?.lastEvent ?? null, error: { code, layer: "session", category: "cancel_blocked", retryable: true, userMessage: message, message, traceId, route: "/v1/agent/chat/cancel", toolName: "codex-stdio.cancel" }, blocker: { code, layer: "session", category: "cancel_blocked", retryable: true, summary: message, userMessage: message, traceId, route: "/v1/agent/chat/cancel", toolName: "codex-stdio.cancel" } }; } export async function handleCodeAgentTraceHttp(request, response, url, options) { const parts = url.pathname.split("/").filter(Boolean); const traceId = decodeURIComponent(parts[3] ?? ""); const streamSegment = parts[4]; const traceStore = options.traceStore ?? defaultCodeAgentTraceStore; const pageOptions = codeAgentTracePageOptions(url); if (!/^trc_[A-Za-z0-9_.:-]+$/u.test(traceId)) { sendJson(response, 400, { error: { code: "invalid_trace_id", message: "traceId must start with trc_ and contain only safe identifier characters" } }); return; } const requestOptions = codeAgentRequestScopedOptions(options); const projectMismatch = await measureCodeAgentHttpPhase(requestOptions, "trace_project_check", () => traceProjectMismatchSnapshot(traceId, url, requestOptions, "trace")); if (projectMismatch) { sendJson(response, projectMismatch.statusCode, projectMismatch.body); return; } const result = requestOptions.codeAgentChatResults?.get(traceId) ?? null; if (result && !canAccessOwnedResult(result, requestOptions.actor)) { sendJson(response, 403, { error: { code: "agent_session_owner_required", message: "Only the session owner or admin can read this Code Agent trace" } }); return; } let agentRunResult = result?.agentRun ? result : await measureCodeAgentHttpPhase(requestOptions, "trace_load_persisted_result", () => loadPersistedAgentRunResult(traceId, requestOptions)); let refreshError = null; if (agentRunResult && !canAccessOwnedResult(agentRunResult, requestOptions.actor)) { sendJson(response, 403, { error: { code: "agent_session_owner_required", message: "Only the session owner or admin can read this Code Agent trace" } }); return; } if (agentRunResult?.agentRun) { try { const existingSnapshot = traceStore.snapshot(traceId); const terminalSnapshotRefreshSatisfied = traceRefreshSatisfiedByTerminalSnapshot(agentRunResult, existingSnapshot); const snapshot = terminalSnapshotRefreshSatisfied ? existingSnapshot : await measureCodeAgentHttpPhase(requestOptions, "trace_trace_refresh", () => refreshAgentRunTrace({ traceId, result: agentRunResult, options: requestOptions, traceStore })); agentRunResult = requestOptions.codeAgentChatResults?.get?.(traceId) ?? agentRunResult; if (!terminalSnapshotRefreshSatisfied && traceNeedsCommandResultSync(agentRunResult, snapshot)) { const synced = await measureCodeAgentHttpPhase(requestOptions, "trace_result_sync", () => syncAgentRunChatResult({ traceId, currentResult: agentRunResult, options: requestOptions, traceStore, appendResultEvent: false, refreshEvents: false, forceResultSync: true })); agentRunResult = synced.result ?? agentRunResult; } if (isTraceCommandTerminalStatus(agentRunResult?.status)) { scheduleCodeAgentTerminalTurnStatusEffects({ payload: agentRunResult, params: agentRunResult, options: requestOptions, preserveLastTraceId: true }); } } catch (error) { refreshError = error; } } if (streamSegment === "stream") { sendTraceSse(response, traceStore, traceId, requestOptions); return; } const body = await measureCodeAgentHttpPhase(requestOptions, "trace_paginate", () => { const snapshot = traceStore.snapshot(traceId); return paginateTraceSnapshot(traceSnapshotWithTerminalEvidence(snapshot, agentRunResult, traceId, refreshError), pageOptions); }); sendJson(response, 200, body); } function codeAgentTracePageOptions(url) { const sinceSeq = nonNegativeInteger(url.searchParams.get("sinceSeq") ?? url.searchParams.get("since"), 0); const requestedLimit = parsePositiveInteger(url.searchParams.get("limit"), DEFAULT_CODE_AGENT_TRACE_PAGE_LIMIT); return { sinceSeq, limit: Math.min(requestedLimit, MAX_CODE_AGENT_TRACE_PAGE_LIMIT) }; } function paginateTraceSnapshot(snapshot, { sinceSeq, limit }) { const sourceEvents = Array.isArray(snapshot?.events) ? snapshot.events : []; const indexedEvents = sourceEvents.map((event, index) => ({ event, seq: traceEventSequence(event, index) })); const firstIndex = indexedEvents.findIndex((item) => item.seq > sinceSeq); const startIndex = firstIndex >= 0 ? firstIndex : indexedEvents.length; const pageItems = indexedEvents.slice(startIndex, startIndex + limit); const events = pageItems.map((item) => item.event); const fromSeq = pageItems.length > 0 ? pageItems[0].seq : null; const toSeq = pageItems.length > 0 ? pageItems[pageItems.length - 1].seq : sinceSeq; const hasMore = startIndex + pageItems.length < indexedEvents.length; const totalEvents = snapshot?.eventCount ?? indexedEvents.length; return { ...snapshot, events, eventCount: totalEvents, range: { sinceSeq, fromSeq, toSeq, limit, returned: events.length, total: totalEvents }, truncated: hasMore, hasMore, nextSinceSeq: toSeq, fullTraceLoaded: !hasMore }; } function traceEventSequence(event, index) { const seq = Number(event?.seq); return Number.isFinite(seq) && seq > 0 ? Math.trunc(seq) : index + 1; } function nonNegativeInteger(value, fallback) { const parsed = Number.parseInt(value ?? "", 10); return Number.isInteger(parsed) && parsed >= 0 ? parsed : fallback; } function traceNeedsCommandResultSync(result, snapshot) { if (!result?.agentRun) return false; const status = String(result.status ?? result.agentRun.status ?? result.agentRun.commandState ?? result.agentRun.terminalStatus ?? "running"); if (isTraceCommandTerminalStatus(status)) return true; if (snapshotHasTerminalEvent(snapshot)) return true; return false; } function isTraceCommandTerminalStatus(status) { return CODE_AGENT_TERMINAL_STATUSES.has(String(status ?? "").trim().toLowerCase().replace(/_/gu, "-")); } function snapshotHasTerminalEvent(snapshot) { const events = Array.isArray(snapshot?.events) ? snapshot.events : []; return events.some((event) => event?.terminal === true || (event?.type === "result" && isTraceCommandTerminalStatus(event?.status))); } function traceRefreshSatisfiedByTerminalSnapshot(result, snapshot) { if (!result?.agentRun || snapshot?.status === "missing") return false; const status = String(result.status ?? result.agentRun.terminalStatus ?? result.agentRun.commandState ?? result.agentRun.status ?? ""); if (!isTraceCommandTerminalStatus(status)) return false; const events = Array.isArray(snapshot?.events) ? snapshot.events : []; if (events.length === 0) return false; const commandId = textValue(result.agentRun.commandId); const terminalEvents = events.filter((event) => { if (!(event?.terminal === true || (event?.type === "result" && isTraceCommandTerminalStatus(event?.status)))) return false; return !commandId || textValue(event?.commandId) === commandId; }); if (terminalEvents.length === 0) return false; const expectedLastSeq = Number(result.agentRun.lastSeq ?? result.traceSummary?.agentRun?.lastSeq ?? 0); if (!Number.isFinite(expectedLastSeq) || expectedLastSeq <= 0) return true; const observedLastSeq = Math.max(0, ...events .filter((event) => !commandId || textValue(event?.commandId) === commandId) .map((event) => Number(event?.sourceSeq ?? 0)) .filter(Number.isFinite)); return observedLastSeq === 0 || observedLastSeq >= expectedLastSeq; } function traceSnapshotWithTerminalEvidence(snapshot, result, traceId, refreshError = null) { const evidence = agentRunTerminalTraceEvidence(result, traceId); if (snapshot?.status !== "missing") return traceSnapshotWithAttachedTerminalEvidence(snapshot, evidence, refreshError); if (!evidence) return { ...snapshot, ok: false, traceStatus: "missing", retention: traceRetentionSummary("missing") }; return { ...snapshot, ok: true, status: "expired", traceStatus: "expired", persisted: true, retention: traceRetentionSummary("expired"), conversationId: evidence.conversationId, sessionId: evidence.sessionId, threadId: evidence.threadId, ...codeAgentPromptFields(evidence), agentRun: evidence.agentRun, finalResponse: evidence.finalResponse, traceSummary: evidence.traceSummary, terminalEvidence: { available: true, source: evidence.source, refresh: refreshError ? { attempted: true, ok: false, code: refreshError?.code ?? "agentrun_trace_refresh_failed", message: refreshError?.message ?? "AgentRun trace events could not be refreshed; command result remains authoritative for final response.", valuesPrinted: false } : { attempted: false, ok: null }, conversationId: evidence.conversationId, sessionId: evidence.sessionId, threadId: evidence.threadId, ...codeAgentPromptFields(evidence), agentRun: evidence.agentRun, traceSummary: evidence.traceSummary, finalResponse: evidence.finalResponse, valuesPrinted: false } }; } function traceSnapshotWithAttachedTerminalEvidence(snapshot, evidence, refreshError = null) { if (!evidence) return snapshot; return { ...snapshot, conversationId: snapshot.conversationId ?? evidence.conversationId, sessionId: snapshot.sessionId ?? evidence.sessionId, threadId: snapshot.threadId ?? evidence.threadId, ...codeAgentPromptFields(evidence), agentRun: snapshot.agentRun ?? evidence.agentRun, finalResponse: snapshot.finalResponse ?? evidence.finalResponse, traceSummary: snapshot.traceSummary ?? evidence.traceSummary, terminalEvidence: snapshot.terminalEvidence ?? (refreshError ? { available: true, source: evidence.source, refresh: { attempted: true, ok: false, code: refreshError?.code ?? "agentrun_trace_refresh_failed", message: refreshError?.message ?? "AgentRun trace events could not be refreshed; live events may be partial.", valuesPrinted: false }, valuesPrinted: false } : undefined) }; } function agentRunTerminalTraceEvidence(result, traceId) { if (!result || typeof result !== "object") return null; const storedSummary = result.traceSummary && typeof result.traceSummary === "object" && result.traceSummary.source === "agentrun-command-result" ? result.traceSummary : null; const finalResponse = agentRunTerminalFinalResponse(result, traceId); const promptEvidence = codeAgentPromptMetadata(result, {}, traceId); const agentRun = result.agentRun && typeof result.agentRun === "object" ? { adapter: result.agentRun.adapter ?? null, runId: result.agentRun.runId ?? null, commandId: result.agentRun.commandId ?? null, attemptId: result.agentRun.attemptId ?? null, runnerId: result.agentRun.runnerId ?? null, jobName: result.agentRun.jobName ?? null, namespace: result.agentRun.namespace ?? null, terminalStatus: result.agentRun.terminalStatus ?? null, lastSeq: result.agentRun.lastSeq ?? null, valuesPrinted: false } : null; if (!agentRun?.runId || !agentRun?.commandId || (!storedSummary && !finalResponse)) return null; const traceSummary = { traceId, source: "agentrun-command-result", sourceEventCount: numberOrNull(storedSummary?.sourceEventCount ?? storedSummary?.eventCount ?? result.runnerTrace?.eventCount), renderedRowSummary: storedSummary?.renderedRowSummary ?? null, noiseEventCount: numberOrNull(storedSummary?.noiseEventCount), omittedNoiseCount: numberOrNull(storedSummary?.omittedNoiseCount), terminalStatus: storedSummary?.terminalStatus ?? result.agentRun?.terminalStatus ?? result.status ?? null, updatedAt: storedSummary?.updatedAt ?? result.updatedAt ?? null, valuesPrinted: false }; return { source: "agentrun-command-result", conversationId: safeConversationId(result.conversationId) || null, sessionId: safeSessionId(result.sessionId) || null, threadId: safeOpaqueId(result.threadId) || null, ...codeAgentPromptFields(promptEvidence), agentRun, finalResponse, traceSummary }; } function agentRunTerminalFinalResponse(result, traceId) { const stored = result.finalResponse && typeof result.finalResponse === "object" ? result.finalResponse : null; const text = textValue(stored?.text ?? result.reply?.content ?? result.message?.content ?? result.assistantText); if (!text) return null; const storedTraceId = safeTraceId(stored?.traceId ?? result.traceId) || null; if (storedTraceId && storedTraceId !== traceId) return null; return { text, textChars: text.length, messageId: stored?.messageId ?? result.reply?.messageId ?? result.messageId ?? null, role: stored?.role ?? result.reply?.role ?? "assistant", status: stored?.status ?? result.status ?? null, traceId: traceId, createdAt: stored?.createdAt ?? result.reply?.createdAt ?? result.createdAt ?? null, updatedAt: stored?.updatedAt ?? result.updatedAt ?? null, source: "agentrun-command-result", valuesPrinted: false }; } function traceRetentionSummary(status) { return { traceStatus: status, liveTraceStore: status === "missing" ? "missing" : "expired-or-evicted", policy: "live trace events are short-term storage; terminal final response and summary are resolved from AgentRun command result by traceId and commandId", replacementEvidence: status === "missing" ? "resolve the trace through AgentRun command registry/result or report the trace as missing" : "use terminalEvidence.finalResponse, terminalEvidence.traceSummary, conversationId, sessionId, threadId, and agentRun ids", valuesPrinted: false }; } function numberOrNull(value) { const parsed = Number(value); return Number.isFinite(parsed) ? parsed : null; } function sendTraceSse(response, traceStore, traceId, options = {}) { response.writeHead(200, { "content-type": "text/event-stream; charset=utf-8", "cache-control": "no-store", connection: "keep-alive", "x-accel-buffering": "no" }); const writeEvent = (eventName, payload) => { response.write(`event: ${eventName}\n`); response.write(`data: ${JSON.stringify(payload)}\n\n`); }; writeEvent("snapshot", traceStore.snapshot(traceId)); const unsubscribe = traceStore.subscribe(traceId, (event, snapshot) => { writeEvent("runnerTrace", { event, snapshot }); }); const heartbeatMs = parsePositiveInteger(options.env?.HWLAB_CODE_AGENT_TRACE_HEARTBEAT_MS, 15000); const heartbeat = setInterval(() => { writeEvent("heartbeat", traceStore.snapshot(traceId)); }, heartbeatMs); response.on("close", () => { clearInterval(heartbeat); unsubscribe(); }); } export function createCodeAgentChatResultStore({ maxResults = 256 } = {}) { const limit = positiveInteger(maxResults, 256); const results = new Map(); function set(traceId, payload) { const id = safeTraceId(traceId); if (!id) return; results.set(id, { ...payload, traceId: id, cachedAt: new Date().toISOString() }); while (results.size > limit) { const oldest = results.keys().next().value; if (!oldest) break; results.delete(oldest); } } return { set, get: (traceId) => results.get(safeTraceId(traceId)) ?? null, clear: () => results.clear() }; } function compactCodeAgentChatResultPayload(payload, options = {}) { if (!payload || typeof payload !== "object") return payload; const limit = resultTraceEventLimit(options); const terminalEvidence = agentRunTerminalTraceEvidence(payload, payload.traceId); const { userBillingReservation, ...publicPayload } = payload; return { ...publicPayload, ...codeAgentTurnLifecycleFields(publicPayload.traceId, publicPayload), ...(terminalEvidence ? { terminalEvidence: terminalEvidencePayload(terminalEvidence) } : {}), ...(publicPayload.runnerTrace && typeof publicPayload.runnerTrace === "object" ? { runnerTrace: compactRunnerTraceForResult(publicPayload.runnerTrace, limit) } : {}) }; } function terminalEvidencePayload(evidence) { return { available: true, source: evidence.source, conversationId: evidence.conversationId, sessionId: evidence.sessionId, threadId: evidence.threadId, ...codeAgentPromptFields(evidence), agentRun: evidence.agentRun, traceSummary: evidence.traceSummary, finalResponse: evidence.finalResponse, valuesPrinted: false }; } function compactRunnerTraceForResult(runnerTrace, limit = DEFAULT_CODE_AGENT_RESULT_TRACE_EVENT_LIMIT) { if (!runnerTrace || typeof runnerTrace !== "object") return runnerTrace; const events = Array.isArray(runnerTrace.events) ? runnerTrace.events : []; const total = Number.isInteger(runnerTrace.eventCount) ? runnerTrace.eventCount : events.length; const effectiveLimit = Math.max(8, positiveInteger(limit, DEFAULT_CODE_AGENT_RESULT_TRACE_EVENT_LIMIT)); if (events.length <= effectiveLimit) { return { ...runnerTrace, eventCount: total, eventsCompacted: false }; } const headCount = Math.min(24, Math.max(1, Math.floor(effectiveLimit / 4))); const tailCount = Math.max(1, effectiveLimit - headCount - 1); const omitted = Math.max(0, events.length - headCount - tailCount); const head = events.slice(0, headCount); const tail = events.slice(events.length - tailCount); const marker = { traceId: runnerTrace.traceId ?? head[0]?.traceId ?? tail[0]?.traceId ?? null, type: "trace", stage: "trace", status: "truncated", label: "trace:compacted", createdAt: tail[0]?.createdAt ?? runnerTrace.updatedAt ?? new Date().toISOString(), message: `Result polling response compacted ${omitted} trace events; fetch /v1/agent/traces/${encodeURIComponent(runnerTrace.traceId ?? "")} for the full trace.`, omittedEventCount: omitted, retainedEventCount: head.length + tail.length, totalEventCount: total, valuesPrinted: false }; const compactEvents = [...head, marker, ...tail]; return { ...runnerTrace, eventCount: total, events: compactEvents, eventLabels: compactEvents.map(traceEventLabel).filter(Boolean), eventsCompacted: true, eventWindow: { mode: "head-tail", retained: compactEvents.length, omitted, total } }; } function traceEventLabel(event) { return typeof event === "string" ? event : event?.label; } function resultTraceEventLimit(options = {}) { return positiveInteger( options.env?.HWLAB_CODE_AGENT_RESULT_TRACE_EVENT_LIMIT, DEFAULT_CODE_AGENT_RESULT_TRACE_EVENT_LIMIT ); } function createCodeAgentM3HwlabApiRequestJson(options = {}) { return async (targetUrl, request = {}) => { const url = new URL(targetUrl); const route = url.pathname; if (route === M3_IO_CONTROL_ROUTE && request.method === "POST") { return { ok: true, status: 200, body: await handleM3IoControl(request.body ?? {}, { runtimeStore: options.runtimeStore, now: options.now, env: options.env, requestJson: options.m3IoRequestJson }) }; } if (route === M3_STATUS_ROUTE && request.method === "GET") { return { ok: true, status: 200, body: await describeM3StatusLive(options) }; } return { ok: false, status: 404, body: { error: { code: "not_found", message: `Unsupported Code Agent M3 HWLAB API route ${route}` } }, error: `Unsupported Code Agent M3 HWLAB API route ${route}` }; }; } function uniqueStrings(values) { return [...new Set(values.map((value) => String(value ?? "").trim()).filter(Boolean))]; }