Files
pikasTech-HWLAB/internal/cloud/server-code-agent-http-support.ts
T

1615 lines
67 KiB
TypeScript

// SPEC: PJ2026-0104010803 Workbench唯一投影 draft-2026-06-20-p2-terminal-outbox-recovery; PJ2026-010403 API契约 draft-2026-06-20-p2-terminal-outbox-recovery; PJ2026-010205 HWLAB接入 draft-2026-06-25-p0-session-warm-runner-contract; PJ2026-0102 Agent编排 draft-2026-06-17-r0; PJ2026-01060505 Workbench Performance draft-2026-06-17-p0.
// Responsibility: Shared Code Agent HTTP lifecycle, billing, ownership, projection-read, and response helpers.
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,
steerAgentRunChatTurn,
submitAgentRunChatTurn
} 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 { messageAuthorityTextValue } from "./code-agent-agentrun-prompt.ts";
import { recordWorkbenchSessionOwner } from "./workbench-projection-writer.ts";
import { createWorkbenchReadModel } from "./workbench-read-model.ts";
import { codeAgentOtelTraceFields, emitCodeAgentOtelSpan } from "./otel-trace.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",
"gpt.pika": "gpt.pika",
"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";
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 firstNonEmptyValue(...values) {
for (const value of values) {
const text = String(value ?? "").trim();
if (text) return text;
}
return null;
}
async function recordCodeAgentSessionInputFact({ params = {}, options = {}, traceId, delivery = "queue", status = "admitted", messageId = null, commandId = null, agentRun = null, error = null } = {}) {
const runtimeStore = options.runtimeStore ?? null;
if (typeof runtimeStore?.writeWorkbenchFacts !== "function") return null;
const fact = buildCodeAgentSessionInputFact({ params, options, traceId, delivery, status, messageId, commandId, agentRun, error });
if (!fact) return null;
return runtimeStore.writeWorkbenchFacts({ facts: { inputs: [fact] } }, codeAgentSessionInputRequestMeta(fact, params, options));
}
function buildCodeAgentSessionInputFact({ params = {}, options = {}, traceId, delivery = "queue", status = "admitted", messageId = null, commandId = null, agentRun = null, error = null } = {}) {
const resolvedTraceId = safeTraceId(traceId ?? params.traceId) || null;
const lifecycle = codeAgentTurnLifecycleFields(resolvedTraceId, params);
const sessionId = safeSessionId(params.sessionId ?? params.session?.sessionId) || null;
if (!sessionId) return null;
const resolvedMessageId = safeMessageId(messageId ?? params.messageId ?? lifecycle.userMessageId) || lifecycle.userMessageId;
const resolvedCommandId = textValue(commandId ?? agentRun?.commandId ?? params.commandId ?? params.agentRun?.commandId) || null;
const normalizedDelivery = codeAgentInputDelivery(delivery);
const normalizedStatus = codeAgentInputStatus(status);
const now = new Date().toISOString();
const sourceEventId = `${sessionId}:${lifecycle.turnId}:${normalizedDelivery}:${resolvedTraceId ?? resolvedCommandId ?? resolvedMessageId}`;
// Command allocation happens after the initial admitting write. Keep one stable
// row across admitting -> blocked/failed/promoted transitions for the trace.
const inputId = stableCodeAgentInputId({ sessionId, turnId: lifecycle.turnId, traceId: resolvedTraceId, messageId: resolvedMessageId, delivery: normalizedDelivery, sourceEventId });
return {
inputId,
sessionId,
turnId: lifecycle.turnId,
traceId: resolvedTraceId,
messageId: resolvedMessageId,
commandId: resolvedCommandId,
runId: textValue(agentRun?.runId ?? params.agentRun?.runId) || null,
dispatchIntentId: textValue(agentRun?.dispatchIntentId ?? params.agentRun?.dispatchIntentId) || null,
runnerJobId: textValue(agentRun?.runnerJobId ?? params.agentRun?.runnerJobId) || null,
durableDispatch: agentRun?.durableDispatch === true || params.agentRun?.durableDispatch === true,
delivery: normalizedDelivery,
status: normalizedStatus,
errorCode: textValue(error?.code ?? error?.error?.code) || null,
sourceEventId,
promptHash: params.message || params.prompt || params.text ? sha256Text(params.message ?? params.prompt ?? params.text).slice(0, 16) : null,
textBytes: params.message || params.prompt || params.text ? Buffer.byteLength(String(params.message ?? params.prompt ?? params.text), "utf8") : 0,
valuesRedacted: true,
secretMaterialStored: false,
createdAt: now,
updatedAt: now
};
}
function codeAgentSessionInputRequestMeta(fact, params = {}, options = {}) {
return {
sessionId: fact.sessionId,
traceId: fact.traceId,
turnId: fact.turnId,
messageId: fact.messageId,
ownerUserId: options.actor?.id ?? params.ownerUserId,
projectId: params.projectId ?? DEFAULT_CODE_AGENT_PROJECT_ID,
valuesPrinted: false
};
}
function stableCodeAgentInputId(value) {
const payload = Object.fromEntries(Object.entries(value ?? {}).filter(([, item]) => item !== undefined && item !== null && item !== "").sort(([left], [right]) => left.localeCompare(right)));
return `wsi_${sha256Text(JSON.stringify(payload)).slice(0, 32)}`;
}
function codeAgentInputDelivery(value) {
const text = textValue(value).toLowerCase();
return ["queue", "steer", "cancel"].includes(text) ? text : "queue";
}
function codeAgentInputStatus(value) {
const text = textValue(value).toLowerCase().replace(/-/gu, "_");
return ["admitting", "admitted", "promoted", "blocked", "failed", "canceled", "completed"].includes(text) ? text : "admitted";
}
function codeAgentResultTimingFields(...sources) {
const records = sources.filter((source) => source && typeof source === "object");
const timingSource = records.map((source) => source.timing).find((timing) => timing && typeof timing === "object") ?? {};
const startedAt = firstTimestampIso(timingSource.startedAt, ...records.map((source) => source.startedAt), ...records.map((source) => source.createdAt));
const lastEventAt = firstLatestTimestampIso(timingSource.lastEventAt, ...records.map((source) => source.lastEventAt), ...records.map((source) => source.updatedAt), ...records.map((source) => source.createdAt));
const finishedAt = firstLatestTimestampIso(timingSource.finishedAt, ...records.map((source) => source.finishedAt), ...records.map((source) => source.completedAt));
const durationMs = numberOrNull(timingSource.durationMs ?? records.map((source) => source.durationMs).find((value) => numberOrNull(value) !== null));
const observedAt = timestampIsoOrNull(timingSource.observedAt);
const lastEventAgeMs = numberOrNull(timingSource.lastEventAgeMs);
if (!startedAt && !lastEventAt && !finishedAt && durationMs === null && lastEventAgeMs === null) return {};
const timing = {
...(timingSource && typeof timingSource === "object" ? timingSource : {}),
startedAt: startedAt ?? null,
lastEventAt: lastEventAt ?? null,
finishedAt: finishedAt ?? null,
durationMs,
observedAt: observedAt ?? null,
lastEventAgeMs,
valuesRedacted: timingSource.valuesRedacted !== false
};
return {
timing,
startedAt: timing.startedAt,
lastEventAt: timing.lastEventAt,
finishedAt: timing.finishedAt,
durationMs: timing.durationMs
};
}
function firstTimestampIso(...values) {
for (const value of values) {
const timestamp = timestampIsoOrNull(value);
if (timestamp) return timestamp;
}
return null;
}
function firstLatestTimestampIso(...values) {
let latest = null;
let latestMs = Number.NEGATIVE_INFINITY;
for (const value of values) {
const timestamp = timestampIsoOrNull(value);
if (!timestamp) continue;
const ms = Date.parse(timestamp);
if (!Number.isFinite(ms) || ms < latestMs) continue;
latest = timestamp;
latestMs = ms;
}
return latest;
}
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, sendResponse = true } = {}) {
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;
const payload = {
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
};
if (sendResponse && response) sendJson(response, status, payload);
return { blocked: true, statusCode: status, payload, error: payload.error, blocker: payload.blocker };
}
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;
}
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 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 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 recordWorkbenchSessionOwner({
accessController: options.accessController,
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 (codeAgentFreshContinuationFailure(result)) return "thread-resume-failed";
if (codeAgentPayloadHasSealedFinalResponse(result)) return "completed";
if (result?.status === "completed") return "completed";
if (result?.status === "canceled" || result?.status === "cancelled") return "canceled";
return result?.status ?? "active";
}
function textValue(value) {
return String(value ?? "").trim();
}
function timestampIsoOrNow(value = null) {
const parsed = Date.parse(String(value ?? ""));
return Number.isFinite(parsed) ? new Date(parsed).toISOString() : new Date().toISOString();
}
function timestampIsoOrNull(value = null) {
const parsed = Date.parse(String(value ?? ""));
return Number.isFinite(parsed) ? new Date(parsed).toISOString() : null;
}
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);
const providerProfile = codeAgentProviderProfileEvidence(payload, params);
const continuation = codeAgentContinuationEvidence(payload, params);
const sessionLifecycleStatus = continuation.requiresFreshSession ? "thread-resume-failed" : payload.sessionLifecycleStatus ?? null;
return {
...(providerProfile ? { providerProfile, codeAgentProviderProfile: providerProfile } : {}),
provider: payload.provider ?? null,
model: payload.model ?? null,
backend: payload.backend ?? null,
status: payload.status ?? null,
sessionMode: payload.sessionMode ?? payload.session?.sessionMode ?? null,
sessionLifecycleStatus,
continuation,
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 codeAgentContinuationEvidence(payload = {}, params = {}) {
const failure = codeAgentFreshContinuationFailure(payload);
const providerProfile = codeAgentProviderProfileEvidence(payload, params);
const traceId = safeTraceId(payload.traceId ?? params.traceId) || null;
if (!failure) {
return {
requiresFreshSession: false,
providerProfile,
traceId,
valuesRedacted: true
};
}
return {
requiresFreshSession: true,
reasonCode: failure.code,
reason: failure.message,
staleThreadId: safeOpaqueId(payload.session?.threadId ?? payload.sessionReuse?.threadId ?? payload.threadId ?? params.threadId ?? payload.agentRun?.threadId) || null,
providerProfile,
traceId,
valuesRedacted: true
};
}
function codeAgentFreshContinuationFailure(payload = {}) {
if (!payload || typeof payload !== "object") return null;
const sessionStatus = String(payload.session?.status ?? payload.sessionLifecycleStatus ?? payload.sessionReuse?.status ?? "").trim().toLowerCase().replace(/_/gu, "-");
if (sessionStatus === "thread-resume-failed") return { code: "thread-resume-failed", message: "previous AgentRun thread/session resume failed", valuesRedacted: true };
const status = normalizeTurnStatus(payload.status, payload.agentRun?.terminalStatus, payload.agentRun?.commandState, payload.agentRun?.status, payload.session?.status, payload.sessionReuse?.status);
if (!status || !["failed", "blocked", "timeout"].includes(status)) return null;
const code = normalizeCodeAgentFailureKind(firstNonEmptyValue(
payload.error?.code,
payload.blocker?.code,
payload.providerTrace?.failureKind,
payload.providerTrace?.errorCode,
payload.agentRun?.failureKind,
payload.agentRun?.errorCode,
payload.transient?.failureKind,
payload.transient?.errorCode
));
const message = firstNonEmptyValue(
payload.error?.message,
payload.error?.userMessage,
payload.blocker?.summary,
payload.blocker?.message,
payload.providerTrace?.failureMessage,
payload.providerTrace?.summary,
payload.agentRun?.failureMessage,
payload.agentRun?.message
) ?? "";
if (!codeAgentFailureRequiresFreshContinuation(code, message)) return null;
return { code: code ?? "stale-continuation", message: message || code || "stale continuation", valuesRedacted: true };
}
function normalizeCodeAgentFailureKind(value) {
const normalized = String(value ?? "").trim().toLowerCase().replace(/_/gu, "-");
return normalized || null;
}
function codeAgentFailureRequiresFreshContinuation(code, message = "") {
const failureKind = normalizeCodeAgentFailureKind(code);
if (["thread-resume-failed", "session-store-evicted", "provider-stream-disconnected"].includes(failureKind)) return true;
return /session stor(?:e|age).*evicted|pvc-backed session|no rollout found for thread id|no rollout found|thread\/resume failed|provider stream disconnected/iu.test(String(message ?? ""));
}
function codeAgentProviderProfileEvidence(payload = {}, params = {}) {
const raw = firstNonEmptyValue(
params.providerProfile,
params.codeAgentProviderProfile,
payload.providerProfile,
payload.codeAgentProviderProfile,
payload.agentRun?.backendProfile,
payload.providerTrace?.backendProfile,
payload.backendProfile
);
if (!raw) return null;
const normalized = normalizeCodeAgentProviderProfile(raw);
return normalized === "runtime-default" ? null : normalized;
}
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: codeAgentPayloadHasSealedFinalResponse(payload) ? "completed" : 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(/\r\n?/gu, "\n");
if (!extracted.trim() || extracted.trim() === "[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 (codeAgentPayloadHasSealedFinalResponse(payload)) return "completed";
if (["completed", "done", "success"].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 codeAgentPayloadHasSealedFinalResponse(payload = {}) {
if (!payload || typeof payload !== "object") return false;
if (payload.error || payload.blocker) return false;
if (!codeAgentFinalResponseText(payload)) return false;
const agentRun = payload.agentRun && typeof payload.agentRun === "object" ? payload.agentRun : {};
return isTraceCommandTerminalStatus(payload.status) ||
isTraceCommandTerminalStatus(agentRun.status) ||
isTraceCommandTerminalStatus(agentRun.runStatus) ||
isTraceCommandTerminalStatus(agentRun.commandState) ||
isTraceCommandTerminalStatus(agentRun.terminalStatus);
}
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 = codeAgentFinalResponseText(payload);
if (!text) return null;
return {
text,
textChars: text.length,
messageId: payload.finalResponse?.messageId ?? payload.reply?.messageId ?? payload.messageId ?? null,
role: payload.reply?.role ?? payload.message?.role ?? "assistant",
status: codeAgentPayloadHasSealedFinalResponse(payload) ? "completed" : payload.finalResponse?.status ?? payload.status ?? null,
traceId,
createdAt: payload.finalResponse?.createdAt ?? payload.reply?.createdAt ?? payload.createdAt ?? null,
updatedAt: payload.finalResponse?.updatedAt ?? payload.updatedAt ?? null,
source: payload.finalResponse?.source ?? "code-agent-result",
valuesPrinted: false
};
}
function codeAgentFinalResponseText(payload = {}) {
for (const value of [
payload?.finalResponse?.text,
payload?.finalResponse?.content,
payload?.finalResponse,
payload?.reply?.content,
payload?.reply,
payload?.message?.content,
payload?.message,
payload?.assistantText,
payload?.finalText,
payload?.text,
payload?.content
]) {
const text = conversationText(value);
if (text) return text;
}
return "";
}
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"
}
};
}
function isTraceCommandTerminalStatus(status) {
return CODE_AGENT_TERMINAL_STATUSES.has(String(status ?? "").trim().toLowerCase().replace(/_/gu, "-"));
}
function traceSnapshotWithTerminalEvidence(snapshot, result, traceId, refreshError = null) {
const evidence = agentRunTerminalTraceEvidence(result, traceId);
if (snapshot && 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",
projectionStatus: "projecting",
projectionHealth: "degraded",
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;
const terminalStatus = normalizeTurnStatus(result.agentRun?.terminalStatus, result.agentRun?.commandState, result.agentRun?.status, result.agentRun?.runStatus);
if (!isTraceCommandTerminalStatus(terminalStatus)) return 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 ?? terminalStatus,
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 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: `Compatibility result 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 recordCodeAgentProjectionMetrics(options = {}, { result = null, trace = null, projection = null, refreshError = null } = {}) {
const performanceStore = options.backendPerformanceStore ?? options.backendPerformance;
if (!performanceStore?.recordWorkbenchProjection || !projection) return;
const sourceLatestSeq = sourceLatestSeqFromResult(result);
const lastProjectedSeq = Number(projection.lastProjectedSeq ?? 0);
if (!Number.isFinite(sourceLatestSeq) && !Number.isFinite(lastProjectedSeq)) return;
performanceStore.recordWorkbenchProjection({
sourceLatestSeq: Number.isFinite(sourceLatestSeq) ? sourceLatestSeq : lastProjectedSeq,
lastProjectedSeq: Number.isFinite(lastProjectedSeq) ? lastProjectedSeq : 0,
sourceLatestEventAt: sourceLatestAtFromResult(result, trace),
projectedLatestEventAt: projection.updatedAt ?? trace?.updatedAt ?? result?.updatedAt ?? null,
terminalSourceAt: terminalSourceAtFromResult(result),
terminalProjectedAt: projection.projectionStatus === "caught-up" ? projection.updatedAt ?? trace?.updatedAt ?? result?.updatedAt ?? null : null,
status: projection?.status ?? "unknown",
reason: projectionReason(projection, refreshError),
projectionStatus: projection.projectionStatus ?? "unknown",
source: "workbench_read_model"
});
}
function recordCodeAgentTurnReadMetric(options = {}, url, statusCode, body = {}, startedAt = nowMs()) {
const performanceStore = options.backendPerformanceStore ?? options.backendPerformance;
if (!performanceStore?.recordWorkbenchTurnRead) return;
performanceStore.recordWorkbenchTurnRead({
route: url?.pathname ?? "/v1/agent/turns/:id",
status: body?.status ?? statusClassLabel(statusCode),
degradedReason: turnReadDegradedReason(body),
durationMs: nowMs() - startedAt,
responseBytes: responseBodyBytes(body),
timedOut: statusCode === 504 || body?.error?.code === "timeout" || body?.refreshError?.code === "agentrun_timeout"
});
}
function turnReadDegradedReason(body = {}) {
if (body?.refreshError?.code) return body.refreshError.code;
if (body?.projection?.blocker?.code) return body.projection.blocker.code;
if (body?.blocker?.code) return body.blocker.code;
if (body?.error?.code) return body.error.code;
if (body?.projectionStatus === "projecting") return "projecting";
if (body?.projectionStatus === "blocked") return "projection_blocked";
return "none";
}
function responseBodyBytes(body = {}) {
try { return Buffer.byteLength(JSON.stringify(body)); } catch { return 0; }
}
function statusClassLabel(value) {
const status = Number(value);
if (!Number.isFinite(status) || status <= 0) return "unknown";
return `${Math.floor(status / 100)}xx`;
}
function sourceLatestSeqFromResult(result = null) {
const candidates = [
result?.agentRun?.lastSeq,
result?.traceSummary?.agentRun?.lastSeq,
result?.traceSummary?.lastSeq,
result?.providerTrace?.lastSeq,
result?.runnerTrace?.lastEvent?.sourceSeq,
result?.runnerTrace?.lastEvent?.seq,
result?.runnerTrace?.eventCount
];
for (const value of candidates) {
const seq = Number(value);
if (Number.isFinite(seq) && seq >= 0) return Math.floor(seq);
}
return NaN;
}
function sourceLatestAtFromResult(result = null, trace = null) {
return result?.traceSummary?.updatedAt
?? result?.agentRun?.updatedAt
?? result?.providerTrace?.updatedAt
?? result?.runnerTrace?.updatedAt
?? trace?.updatedAt
?? result?.updatedAt
?? null;
}
function terminalSourceAtFromResult(result = null) {
if (!result) return null;
const terminalStatus = result?.agentRun?.terminalStatus ?? result?.traceSummary?.terminalStatus ?? result?.status;
if (!isTraceCommandTerminalStatus(terminalStatus)) return null;
return result?.traceSummary?.updatedAt ?? result?.agentRun?.updatedAt ?? result?.updatedAt ?? null;
}
function projectionReason(projection = null, refreshError = null) {
if (refreshError) return refreshError.code ?? "refresh_error";
if (projection?.blocker) return projection.blocker.code ?? "projection_blocked";
if (projection?.projectionStatus === "projecting") return "projecting";
if (projection?.projectionStatus === "caught-up") return "none";
return projection?.projectionStatus ?? "unknown";
}
function nowMs() {
if (typeof performance !== "undefined" && typeof performance.now === "function") return performance.now();
return Date.now();
}
function uniqueStrings(values) {
return [...new Set(values.map((value) => String(value ?? "").trim()).filter(Boolean))];
}
export {
normalizeCodeAgentProviderProfile,
firstNonEmptyValue,
recordCodeAgentSessionInputFact,
buildCodeAgentSessionInputFact,
stableCodeAgentInputId,
codeAgentInputDelivery,
codeAgentInputStatus,
codeAgentResultTimingFields,
firstTimestampIso,
firstLatestTimestampIso,
codeAgentChatShortConnectionRequested,
preflightCodeAgentBilling,
recordCodeAgentBillingUsage,
finalizeCodeAgentBillingUsage,
releaseCodeAgentBillingReservation,
withCodeAgentBillingReservation,
codeAgentBillingEnabled,
codeAgentBillingMetadata,
sanitizeBillingReservation,
sanitizeBillingRecord,
sanitizeBillingRelease,
codeAgentUsedTokens,
normalizeTurnStatus,
recordCodeAgentConversationFact,
recordCodeAgentSessionOwner,
codeAgentOwnerStatusForResult,
textValue,
timestampIsoOrNow,
timestampIsoOrNull,
codeAgentSessionOwnerEvidence,
codeAgentContinuationEvidence,
codeAgentFreshContinuationFailure,
normalizeCodeAgentFailureKind,
codeAgentFailureRequiresFreshContinuation,
codeAgentProviderProfileEvidence,
codeAgentTraceResultEvidence,
codeAgentPromptMetadata,
codeAgentPromptMetadataFromText,
codeAgentPromptMetadataFromParts,
codeAgentPromptFields,
codeAgentPromptId,
clippedPromptText,
sha256Text,
compactCodeAgentObject,
codeAgentBillingReservationEvidence,
codeAgentConversationMessagesEvidence,
boundedConversationMessageText,
conversationText,
conversationTextRaw,
codeAgentMessageTraceSuffix,
codeAgentTurnLifecycleFields,
codeAgentLifecycleMessageId,
safeTurnId,
safeMessageId,
codeAgentConversationAgentMessageStatus,
codeAgentPayloadHasSealedFinalResponse,
codeAgentConversationRunnerTraceEvidence,
codeAgentFinalResponseEvidence,
codeAgentFinalResponseText,
codeAgentTraceSummaryEvidence,
annotateOwner,
canAccessOwnedResult,
isCodeAgentResultCanceled,
codeAgentCancelScopeMismatch,
cancelExpectedValues,
cancelScopeFieldMismatch,
cancelBlockedPayload,
isTraceCommandTerminalStatus,
traceSnapshotWithTerminalEvidence,
traceSnapshotWithAttachedTerminalEvidence,
agentRunTerminalTraceEvidence,
agentRunTerminalFinalResponse,
traceRetentionSummary,
numberOrNull,
createCodeAgentChatResultStore,
compactCodeAgentChatResultPayload,
terminalEvidencePayload,
compactRunnerTraceForResult,
traceEventLabel,
resultTraceEventLimit,
createCodeAgentM3HwlabApiRequestJson,
recordCodeAgentProjectionMetrics,
recordCodeAgentTurnReadMetric,
turnReadDegradedReason,
responseBodyBytes,
statusClassLabel,
sourceLatestSeqFromResult,
sourceLatestAtFromResult,
terminalSourceAtFromResult,
projectionReason,
nowMs,
uniqueStrings
};