// SPEC: PJ2026-0104010803 Workbench唯一投影 draft-2026-06-19-p1-agentrun-incremental-cursor; draft-2026-06-20-p2-terminal-outbox-recovery; PJ2026-010205 HWLAB接入 draft-2026-06-17-r0; draft-2026-06-25-p0-session-warm-runner-contract; PJ2026-01060505 Workbench Performance draft-2026-06-17-p0.
// Responsibility: AgentRun command-result/event mapping and trace observability helpers; Kafka owns persistence.

import { randomUUID } from "node:crypto";

import { defaultCodeAgentTraceStore } from "./code-agent-trace-store.ts";
import { decorateCodeAgentSession } from "./code-agent-session-lifecycle.ts";
import {
  parsePositiveInteger,
  safeConversationId,
  safeOpaqueId,
  safeSessionId,
  safeTraceId,
  text
} from "./server-http-utils.ts";
import { currentBackendPerformanceContext } from "./backend-performance.ts";
import {
  DEFAULT_AGENTRUN_MGR_URL,
  agentRunJson,
  isAgentRunManagerInternalServiceHost,
  resolveAgentRunManagerUrl
} from "./code-agent-agentrun-runtime.ts";
import {
  agentRunAlreadyTerminalCancelPayload,
  agentRunCancelBlockedPayload,
  agentRunCancelTerminalStatus
} from "./code-agent-agentrun-cancel.ts";
import {
  DEFAULT_AGENTRUN_REPO_URL,
  agentRunAvailabilityBlocker,
  agentRunProviderIdOrNull,
  agentRunTraceMeta,
  backendForBackendProfile,
  modelForBackendProfile,
  providerForBackendProfile,
  requireAgentRunSourceCommit,
  resolveAgentRunBackendProfile,
  resolveAgentRunProviderId,
  resolveAgentRunRepoUrl
} from "./code-agent-agentrun-profile.ts";
import {
  agentRunPromptEventFields,
  agentRunPromptFields,
  agentRunPromptMetadataFromParams,
  agentRunPromptMetadataFromSession,
  agentRunPromptMetadataFromText,
  messageAuthorityTextValue
} from "./code-agent-agentrun-prompt.ts";
import { codeAgentOtelTraceFields, codeAgentOtelTraceContext, emitCodeAgentOtelSpan } from "./otel-trace.ts";

const ADAPTER_ID = "agentrun-v01";
const ADAPTER_IDS = new Set([ADAPTER_ID, "agentrun-v02"]);
const ADAPTER_ALIASES = new Set(["agentrun", "agentrun-v0.1", "agentrun-v0.2"]);
const DEFAULT_TENANT_ID = "hwlab";
const DEFAULT_PROJECT_ID = "pikasTech/HWLAB";
const DEFAULT_RUNNER_NAMESPACE = "agentrun-v01";
const DEFAULT_TIMEOUT_MS = 1_200_000;
const AGENTRUN_RUNNER_KIND = "agentrun-v01-shared-runner";
const AGENTRUN_SESSION_MODE = "agentrun-v01-durable-session";
const AGENTRUN_IMPLEMENTATION_TYPE = "agentrun-v01-shared-execution-infra";
const AGENTRUN_CAPABILITY_LEVEL = "agentrun-v01-shared-code-agent-session";
const AGENTRUN_PROVIDER_TRACE_PROTOCOL = "agentrun-v01-jsonrpc";
const AGENTRUN_PROVIDER_TRACE_WIRE_API = "agentrun-v01-command-result";
const THREAD_CONTINUITY_POLICY = "hwlab-agentrun-v01-reuse-runner-thread";
const SESSION_POLICY_RUN_LOCAL = "hwlab-agentrun-v01-session-runner-reuse";
const TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "blocked", "cancelled", "canceled"]);
const HWLAB_RESOURCE_GIT_BUNDLES = Object.freeze([
  Object.freeze({ name: "hwlab-tools", subpath: "tools", target_path: "tools" }),
  Object.freeze({ name: "hwlab-agent-skills", subpath: "skills", target_path: ".agents/skills" })
]);
const HWLAB_RESOURCE_PROMPT_REFS = Object.freeze([
  Object.freeze({ name: "hwlab-v02-runtime", path: "internal/agent/prompts/hwlab-v02-runtime.md", inject: "thread-start", required: true })
]);

const RETRYABLE_AGENTRUN_TRANSPORT_FAILURE_KINDS = new Set([
  "agentrun-connect-failed",
  "agentrun-proxy-exec-failed",
  "agentrun-manager-fetch-failed",
  "agentrun-timeout",
  "timeout",
  "fetch-failed",
  "connection-refused",
  "network-error"
]);

export function isRetryableAgentRunTransportFailureKind(failureKind) {
  return RETRYABLE_AGENTRUN_TRANSPORT_FAILURE_KINDS.has(normalizedFailureKind(failureKind));
}


export function agentRunSessionEvidence(payload = {}) {
  if (!payload?.agentRun) return {};
  return {
    agentRun: {
      adapter: ADAPTER_ID,
      runId: payload.agentRun.runId ?? null,
      commandId: payload.agentRun.commandId ?? null,
      attemptId: payload.agentRun.attemptId ?? null,
      runnerId: payload.agentRun.runnerId ?? null,
      runnerJobId: payload.agentRun.runnerJobId ?? null,
      jobName: payload.agentRun.jobName ?? null,
      namespace: payload.agentRun.namespace ?? null,
      backendProfile: payload.agentRun.backendProfile ?? null,
      managerUrl: payload.agentRun.managerUrl ?? DEFAULT_AGENTRUN_MGR_URL,
      repoUrl: payload.agentRun.repoUrl ?? DEFAULT_AGENTRUN_REPO_URL,
      status: payload.agentRun.status ?? null,
      runStatus: payload.agentRun.runStatus ?? null,
      commandState: payload.agentRun.commandState ?? null,
      terminalStatus: payload.agentRun.terminalStatus ?? null,
      dispatchIntentId: payload.agentRun.dispatchIntentId ?? null,
      dispatchIntentState: payload.agentRun.dispatchIntentState ?? null,
      durableDispatch: payload.agentRun.durableDispatch === true,
      traceId: payload.agentRun.traceId ?? payload.traceId ?? payload.providerTrace?.traceId ?? null,
      lastSeq: payload.agentRun.lastSeq ?? 0,
      providerId: payload.agentRun.providerId ?? agentRunProviderIdOrNull(),
      reuseEligible: payload.agentRun.reuseEligible ?? false,
      runnerJobCount: Number(payload.agentRun.runnerJobCount ?? 0),
      runnerReused: payload.agentRun.runnerReused === true,
      reused: payload.agentRun.reused === true,
      sessionId: payload.agentRun.sessionId ?? payload.sessionId ?? null,
      conversationId: payload.conversationId ?? payload.agentRun.conversationId ?? null,
      threadId: payload.threadId ?? payload.agentRun.threadId ?? null,
      providerTrace: payload.providerTrace ?? payload.agentRun.providerTrace ?? null,
      valuesPrinted: false
    }
  };
}


export function agentRunFailureRequiresFreshSession(failureKind, failureMessage) {
  const kind = String(failureKind ?? "").trim().toLowerCase().replace(/_/gu, "-");
  const message = String(failureMessage ?? "");
  return kind === "session-store-evicted" || kind === "thread-resume-failed" || /session stor(?:e|age).*evicted|pvc-backed session|no rollout found for thread id|thread\/resume failed/iu.test(message);
}


export function agentRunFreshSessionFailure(result = {}) {
  const code = result?.failureKind ?? result?.errorCode ?? result?.code ?? (result?.terminalStatus === "failed" ? "agentrun_failed" : null);
  const message = result?.failureMessage ?? result?.blocker?.message ?? result?.error?.message ?? result?.message ?? "";
  return {
    code: normalizedFailureKind(code) ?? "agentrun_failed",
    message,
    requiresFreshSession: agentRunFailureRequiresFreshSession(code, message),
    valuesPrinted: false
  };
}

export function providerCredentialSecretRef(profile, env) {
  const profileEnvKey = String(profile ?? "").toUpperCase().replace(/[^A-Z0-9]+/gu, "_");
  const secretEnvName = `HWLAB_CODE_AGENT_AGENTRUN_${profileEnvKey}_SECRET_NAME`;
  const secretName = firstNonEmpty(env[secretEnvName]);
  if (!secretName) {
    throw Object.assign(new Error(`AgentRun provider Secret name is not configured for profile ${profile}`), {
      code: "agentrun_provider_secret_not_configured",
      statusCode: 500,
      profile,
      envName: secretEnvName,
      valuesPrinted: false
    });
  }
  return {
    profile,
    secretRef: {
      namespace: firstNonEmpty(env.HWLAB_CODE_AGENT_AGENTRUN_SECRET_NAMESPACE, DEFAULT_RUNNER_NAMESPACE),
      name: secretName,
      keys: ["auth.json", "config.toml"],
      mountPath: firstNonEmpty(env.HWLAB_CODE_AGENT_AGENTRUN_CODEX_HOME_MOUNT, "~/.codex")
    }
  };
}

export function agentRunProviderTrace({ base = {}, result = {}, terminalStatus = null } = {}) {
  return {
    transport: "agentrun-v01",
    protocol: AGENTRUN_PROVIDER_TRACE_PROTOCOL,
    wireApi: AGENTRUN_PROVIDER_TRACE_WIRE_API,
    runnerKind: AGENTRUN_RUNNER_KIND,
    implementationType: AGENTRUN_IMPLEMENTATION_TYPE,
    command: "agentrun.v01.command.turn",
    toolName: "agentrun.v01.command.turn",
    source: ADAPTER_ID,
    backendProfile: base.agentRun?.backendProfile ?? null,
    runId: base.agentRun?.runId ?? result?.runId ?? null,
    commandId: base.agentRun?.commandId ?? result?.commandId ?? null,
    runnerId: base.agentRun?.runnerId ?? result?.runnerId ?? null,
    jobName: base.agentRun?.jobName ?? result?.jobName ?? null,
    namespace: base.agentRun?.namespace ?? result?.namespace ?? null,
    traceId: base.traceId ?? base.agentRun?.traceId ?? null,
    threadId: result?.sessionRef?.threadId ?? agentRunEffectiveThreadId(base),
    turnId: result?.turnId ?? null,
    terminalStatus: terminalStatus ?? result?.terminalStatus ?? null,
    failureKind: result?.failureKind ?? null,
    failureMessage: result?.failureMessage ?? result?.blocker?.message ?? null,
    willRetry: result?.willRetry === true ? true : undefined,
    valuesPrinted: false
  };
}

export function agentRunFailureAttribution({ code, message, canceled = false } = {}) {
  if (canceled) {
    return {
      category: "canceled",
      retryable: true,
      userMessage: "AgentRun 请求已取消。",
      summary: message || "AgentRun command was canceled."
    };
  }
  if (code === "provider-invalid-tool-call" || /invalid function arguments json string|invalid_prompt|tool_call_id/iu.test(String(message ?? ""))) {
    return {
      category: "provider_invalid_tool_call",
      retryable: true,
      userMessage: "AgentRun/provider 返回了无效 tool-call arguments JSON；这不是 HWPOD 或 Cloud API 端点失败，请查看 providerTrace.failureKind 和 runnerTrace 定位上游 tool_call_id。",
      summary: message || "AgentRun/provider returned invalid tool-call arguments JSON."
    };
  }
  if (code === "thread-resume-failed") {
    return {
      category: "thread_resume_failed",
      retryable: true,
      userMessage: "AgentRun 复用的 thread 已失效；当前 turn 会按失败终止，Workbench 会清理 stale continuation 指针，下一轮自动从新 session/thread 启动。",
      summary: message || "AgentRun thread/resume failed for an existing thread."
    };
  }
  return {
    category: "agentrun_failed",
    retryable: true,
    userMessage: "AgentRun 请求失败；请查看 runnerTrace、providerTrace 和 agentRun 字段定位 runId/commandId/jobName。",
    summary: message || "AgentRun command failed."
  };
}

export function agentRunLongLivedSessionGate(base = {}) {
  const session = agentRunSessionSummary(base, "idle");
  return {
    status: "pass",
    pass: true,
    requiredCapability: AGENTRUN_CAPABILITY_LEVEL,
    currentCapability: AGENTRUN_IMPLEMENTATION_TYPE,
    sessionId: session.sessionId ?? null,
    sessionStatus: session.status ?? null,
    runnerKind: AGENTRUN_RUNNER_KIND,
    provider: providerForBackendProfile(base.agentRun?.backendProfile ?? "deepseek"),
    sessionMode: AGENTRUN_SESSION_MODE,
    implementationType: AGENTRUN_IMPLEMENTATION_TYPE,
    adapter: ADAPTER_ID,
    delegatedToAgentRun: true,
    codexStdio: false,
    blockers: [],
    valuesPrinted: false
  };
}

export function agentRunToolCalls(result = {}, status = "completed", replyTextOverride = null) {
  const replyText = messageAuthorityTextValue(replyTextOverride) || agentRunReplyText(result);
  return [{
    name: "agentrun.v01.command.turn",
    status,
    runId: result?.runId ?? null,
    commandId: result?.commandId ?? null,
    outputSummary: replyText ? `assistantChars=${replyText.length}` : null,
    valuesPrinted: false
  }];
}

export function agentRunReplyText(result = {}) {
  for (const value of [result?.reply, result?.assistantMessage, result?.finalResponse, result?.content, result?.text, result?.message]) {
    const text = messageAuthorityTextValue(value);
    if (text) return text;
  }
  return "";
}

export function agentRunResultToCodeAgentPayload({ base, result, traceStore, traceId, appendResultEvent = true }) {
  const terminalStatus = String(result?.terminalStatus ?? "");
  const normalizedTerminalStatus = terminalStatus.trim().toLowerCase().replace(/_/gu, "-");
  const retryableInterruption = normalizedTerminalStatus !== "completed" && isRetryableProviderInterruptionPayload(result);
  const terminal = !retryableInterruption && ["completed", "failed", "blocked", "cancelled", "canceled"].includes(normalizedTerminalStatus);
  if (!terminal) {
    if (retryableInterruption && appendResultEvent) {
      traceStore.append(traceId, agentRunProviderRetryEvent({ base, payload: result, status: "retrying", label: "agentrun:provider-retry:provider-stream-disconnected" }), base.agentRun);
    }
    const runningMapping = retryableInterruption ? {
      ...base.agentRun,
      status: "retrying",
      commandState: "retrying",
      failureKind: normalizedFailureKind(result?.failureKind),
      willRetry: true
    } : base.agentRun;
    const running = decorateAgentRunRunningResult({ base, mapping: runningMapping, traceStore, traceId });
    if (!retryableInterruption) return running;
    return {
      ...running,
      status: "retrying",
      providerTrace: agentRunProviderTrace({ base, result, terminalStatus }),
      transient: { failureKind: normalizedFailureKind(result?.failureKind), willRetry: true, valuesRedacted: true },
      valuesPrinted: false
    };
  }
  const now = nowIso();
  const runnerTrace = traceStore.snapshot(traceId, agentRunTraceMeta({}, {}));
  const terminalEventCreatedAt = agentRunResultTraceCreatedAt(runnerTrace, now);
  const providerTrace = agentRunProviderTrace({ base, result, terminalStatus });
  const replyText = agentRunReplyText(result);
  if (normalizedTerminalStatus === "completed") {
    const traceReplyText = agentRunTraceTerminalAssistantText(runnerTrace);
    const completedReplyText = replyText || traceReplyText;
    const finalResponse = completedReplyText ? agentRunCompletedFinalResponse({ base, result, traceId, now, replyText: completedReplyText }) : null;
    const traceSummary = agentRunCompletedTraceSummary({ base, runnerTrace, finalResponse, traceId });
    if (appendResultEvent) {
      traceStore.append(traceId, agentRunTraceEvent({
        type: "result",
        status: "completed",
        label: "agentrun:result:completed",
        createdAt: terminalEventCreatedAt,
        message: "AgentRun result is committed to the Workbench projection event stream.",
        runId: base.agentRun.runId,
        commandId: base.agentRun.commandId,
        terminal: true,
        valuesPrinted: false
      }, base.agentRun));
    }
    return {
      ...base,
      status: "completed",
      messageId: finalResponse?.messageId ?? base.messageId ?? `msg_${traceId.slice(4)}`,
      threadId: agentRunEffectiveThreadId(base),
      updatedAt: now,
      workspace: base.workspace ?? "/home/agentrun/workspace",
      sandbox: base.sandbox ?? "danger-full-access",
      session: agentRunSessionSummary(base, "idle"),
      sessionReuse: agentRunSessionReuseSummary(base, base.agentRun.reused === true),
      runner: agentRunRunnerSummary(base.agentRun),
      runnerTrace: traceStore.snapshot(traceId, agentRunTraceMeta({}, {})),
      toolCalls: agentRunToolCalls(result, "completed", completedReplyText),
      skills: { status: "delegated", provider: ADAPTER_ID, count: 0, items: [], valuesPrinted: false },
      longLivedSessionGate: agentRunLongLivedSessionGate(base),
      providerTrace,
      finalResponse: finalResponse ?? null,
      traceSummary,
      reply: finalResponse ? {
        messageId: finalResponse.messageId,
        role: "assistant",
        content: finalResponse.text,
        createdAt: finalResponse.createdAt
      } : null,
      usage: null,
      agentRun: { ...base.agentRun, terminalStatus, completed: true, reuseEligible: true, providerTrace, valuesPrinted: false },
      valuesPrinted: false
    };
  }
  const canceled = terminalStatus === "cancelled";
  const code = canceled ? "agentrun_canceled" : result?.failureKind ?? (terminalStatus === "blocked" ? "agentrun_blocked" : "agentrun_failed");
  const message = result?.failureMessage ?? result?.blocker?.message ?? (canceled ? "AgentRun command was canceled" : "AgentRun command failed");
  const attribution = agentRunFailureAttribution({ code, message, canceled });
  const finalResponse = agentRunTerminalFailureFinalResponse({
    base,
    traceId,
    now,
    status: canceled ? "canceled" : "failed",
    text: firstNonEmpty(message, attribution.summary, attribution.userMessage)
  });
  const traceSummary = agentRunTerminalFailureTraceSummary({ base, runnerTrace, finalResponse, traceId, terminalStatus: canceled ? "canceled" : terminalStatus || "failed" });
  if (appendResultEvent) {
    traceStore.append(traceId, agentRunTraceEvent({
      type: "result",
      status: canceled ? "canceled" : "failed",
      label: `agentrun:result:${canceled ? "canceled" : terminalStatus || "failed"}`,
      createdAt: terminalEventCreatedAt,
      errorCode: code,
      message: attribution.summary,
      runId: base.agentRun.runId,
      commandId: base.agentRun.commandId,
      terminal: true,
      valuesPrinted: false
    }, base.agentRun));
  }
  const partialContext = partialAgentRunContext(runnerTrace);
  const freshSessionRequired = !canceled && agentRunFailureRequiresFreshSession(code, message);
  const failedSessionStatus = freshSessionRequired ? "thread-resume-failed" : "failed";
  const resumableAfterFailure = !canceled && !freshSessionRequired && Boolean(agentRunEffectiveThreadId(base));
  return {
    ...base,
    status: canceled ? "canceled" : "failed",
    messageId: finalResponse.messageId,
    threadId: agentRunEffectiveThreadId(base),
    canceled,
    updatedAt: now,
    session: agentRunSessionSummary(base, canceled ? "canceled" : failedSessionStatus),
    sessionReuse: agentRunSessionReuseSummary(base, base.agentRun.reused === true, { status: canceled ? undefined : freshSessionRequired ? "thread-resume-failed" : resumableAfterFailure ? "failed-resumable" : "failed-requires-new-session" }),
    runner: agentRunRunnerSummary(base.agentRun),
    runnerTrace: partialContext ? { ...runnerTrace, partialContext } : runnerTrace,
    toolCalls: agentRunToolCalls(result, canceled ? "canceled" : "failed"),
    skills: { status: "delegated", provider: ADAPTER_ID, count: 0, items: [], valuesPrinted: false },
    providerTrace,
    finalResponse,
    traceSummary,
    error: {
      code,
      layer: "agentrun",
      category: attribution.category,
      retryable: attribution.retryable,
      message,
      userMessage: attribution.userMessage,
      traceId,
      route: "/v1/agent/chat",
      toolName: "agentrun.manual-dispatch"
    },
    blocker: canceled ? null : {
      code,
      layer: "agentrun",
      category: attribution.category,
      retryable: attribution.retryable,
      summary: attribution.summary,
      traceId,
      route: "/v1/agent/chat",
      toolName: "agentrun.manual-dispatch"
    },
    agentRun: { ...base.agentRun, terminalStatus, completed: false, reuseEligible: resumableAfterFailure, providerTrace, valuesPrinted: false },
    reuseEligible: resumableAfterFailure,
    ...(partialContext ? { partialContext } : {}),
    valuesPrinted: false
  };
}

export function agentRunCompletedFinalResponse({ base, result, traceId, now, replyText = null }) {
  const textValue = messageAuthorityTextValue(replyText) || agentRunReplyText(result);
  return {
    text: textValue,
    textChars: textValue.length,
    role: "assistant",
    status: "completed",
    traceId,
    messageId: base.messageId ?? base.reply?.messageId ?? `msg_${traceId.slice(4)}`,
    createdAt: base.reply?.createdAt ?? base.createdAt ?? now,
    updatedAt: now,
    valuesPrinted: false
  };
}

export function agentRunTraceTerminalAssistantText(runnerTrace = {}) {
  const events = Array.isArray(runnerTrace?.events) ? runnerTrace.events : [];
  for (let index = events.length - 1; index >= 0; index -= 1) {
    const event = events[index];
    if (!event || typeof event !== "object") continue;
    if (!isAgentRunAssistantTraceEvent(event)) continue;
    if (!(event.terminal === true || event.final === true || event.replyAuthority === true)) continue;
    const textValue = messageAuthorityTextValue(event.finalResponse ?? event.text ?? event.content ?? event.message ?? event.summary ?? event.payload?.text ?? event.payload?.content ?? event.payload?.message);
    if (textValue) return textValue;
  }
  return "";
}

export function isAgentRunAssistantTraceEvent(event = {}) {
  const type = String(event.type ?? event.eventType ?? "").trim().toLowerCase();
  if (type === "assistant" || type === "assistant_message") return true;
  return /assistant:message|assistant_message/u.test(String(event.label ?? "").toLowerCase());
}

export function agentRunTerminalFailureFinalResponse({ base, traceId, now, status, text }) {
  const textValue = String(text ?? "").trim();
  return {
    text: textValue || "AgentRun command failed.",
    textChars: (textValue || "AgentRun command failed.").length,
    role: "assistant",
    status,
    traceId,
    messageId: base.messageId ?? base.reply?.messageId ?? `msg_${traceId.slice(4)}`,
    createdAt: base.reply?.createdAt ?? base.createdAt ?? now,
    updatedAt: now,
    valuesPrinted: false
  };
}

export function agentRunTerminalFailureTraceSummary({ base, runnerTrace, finalResponse, traceId, terminalStatus }) {
  const events = Array.isArray(runnerTrace?.events) ? runnerTrace.events : [];
  const lastSeq = Math.max(0, ...events.map((event) => Number(event?.seq ?? 0)).filter(Number.isFinite));
  return {
    traceId,
    source: "agentrun-command-result",
    sourceEventCount: Number(runnerTrace?.eventCount ?? events.length ?? 0),
    terminalStatus,
    finalAssistantRow: {
      role: finalResponse.role,
      status: finalResponse.status,
      textChars: finalResponse.textChars,
      textPreview: finalResponse.text.slice(0, 240),
      messageId: finalResponse.messageId,
      valuesPrinted: false
    },
    agentRun: {
      runId: base.agentRun?.runId ?? null,
      commandId: base.agentRun?.commandId ?? null,
      lastSeq,
      valuesPrinted: false
    },
    valuesPrinted: false
  };
}

export function agentRunCompletedTraceSummary({ base, runnerTrace, finalResponse, traceId }) {
  const events = Array.isArray(runnerTrace?.events) ? runnerTrace.events : [];
  const lastSeq = Math.max(0, ...events.map((event) => Number(event?.seq ?? 0)).filter(Number.isFinite));
  return {
    traceId,
    source: "agentrun-command-result",
    sourceEventCount: Number(runnerTrace?.eventCount ?? events.length ?? 0),
    terminalStatus: "completed",
    finalAssistantRow: finalResponse ? {
      role: finalResponse.role,
      status: finalResponse.status,
      textChars: finalResponse.textChars,
      textPreview: finalResponse.text.slice(0, 240),
      messageId: finalResponse.messageId,
      valuesPrinted: false
    } : null,
    agentRun: {
      runId: base.agentRun?.runId ?? null,
      commandId: base.agentRun?.commandId ?? null,
      lastSeq,
      valuesPrinted: false
    },
    valuesPrinted: false
  };
}

export function partialAgentRunContext(runnerTrace = {}) {
  const events = Array.isArray(runnerTrace.events) ? runnerTrace.events : [];
  const assistantMessages = events
    .filter((event) => event?.type === "assistant" && String(event.text ?? event.message ?? "").trim())
    .map((event) => String(event.text ?? event.message).trim())
    .slice(-4);
  const toolEvidence = events
    .filter((event) => event?.type === "tool_call" && String(event.status ?? "") === "completed")
    .map((event) => [event.toolName ?? event.label ?? "tool", event.command ?? event.outputSummary ?? event.stdoutSummary ?? event.message ?? ""].filter(Boolean).join(": "))
    .filter(Boolean)
    .slice(-6);
  if (assistantMessages.length === 0 && toolEvidence.length === 0) return null;
  return {
    status: "partial-before-terminal",
    summary: "AgentRun terminal 前已有可延续的 assistant/tool 上下文；后续同 conversation/session/thread 轮次必须能继续使用。",
    assistantMessages,
    toolEvidence,
    valuesPrinted: false
  };
}

export function agentRunResultTraceCreatedAt(runnerTrace = {}, fallback) {
  const last = String(runnerTrace?.lastEvent?.createdAt ?? runnerTrace?.updatedAt ?? "");
  return Number.isFinite(Date.parse(last)) ? last : fallback;
}

export function decorateAgentRunRunningResult({ base, mapping, traceStore, traceId }) {
  return {
    ...base,
    status: "running",
    threadId: agentRunEffectiveThreadId({ agentRun: mapping }),
    accepted: true,
    shortConnection: true,
    updatedAt: nowIso(),
    session: agentRunSessionSummary({ ...base, agentRun: mapping }, "running"),
    sessionReuse: agentRunSessionReuseSummary({ ...base, agentRun: mapping }, mapping.reused === true),
    runner: agentRunRunnerSummary(mapping),
    runnerTrace: traceStore.snapshot(traceId, agentRunTraceMeta({}, {})),
    agentRun: { ...mapping, adapter: ADAPTER_ID, valuesPrinted: false },
    valuesPrinted: false
  };
}

export function appendAgentRunEventsToTrace(traceStore, traceId, events, mapping = {}) {
  for (const event of events) {
    if (isForeignAgentRunCommandEvent(event, mapping)) continue;
    const normalized = mapAgentRunEvent(event, mapping);
    if (normalized) traceStore.append(traceId, normalized, agentRunTraceMeta({}, {}));
  }
}
function agentRunEventCommandId(event) {
  const payload = event?.payload && typeof event.payload === "object" ? event.payload : {};
  if (typeof event?.commandId === "string") return event.commandId;
  return typeof payload.commandId === "string" ? payload.commandId : "";
}

export function isForeignAgentRunCommandEvent(event, mapping = {}) {
  const currentCommandId = typeof mapping.commandId === "string" ? mapping.commandId : "";
  if (!currentCommandId) return false;
  const eventCommandId = agentRunEventCommandId(event);
  return Boolean(eventCommandId && eventCommandId !== currentCommandId);
}

export function mapAgentRunEvent(event, mapping = {}) {
  if (!event || typeof event !== "object") return null;
  const payload = event.payload && typeof event.payload === "object" ? event.payload : {};
  const base = {
    createdAt: event.createdAt ?? null,
    source: "agentrun",
    sourceSeq: event.seq ?? null,
    backend: backendForBackendProfile(mapping.backendProfile ?? payload.backendProfile ?? payload.providerProfile ?? "deepseek"),
    runId: event.runId ?? mapping.runId ?? null,
    commandId: payload.commandId ?? mapping.commandId ?? null,
    attemptId: payload.attemptId ?? mapping.attemptId ?? null,
    runnerId: payload.runnerId ?? mapping.runnerId ?? null,
    jobName: payload.jobName ?? mapping.jobName ?? null,
    namespace: payload.namespace ?? mapping.namespace ?? null,
    valuesPrinted: false
  };
  if (event.type === "backend_status") {
    const phase = String(payload.phase ?? "status");
    return {
      ...base,
      type: "backend",
      eventType: "backend",
      status: "running",
      label: `agentrun:backend:${phase}`,
      message: textPayload(payload, phase),
      waitingFor: waitingForForPhase(phase),
      details: agentRunBackendStatusDetails(phase, payload)
    };
  }
  if (event.type === "assistant_message") {
    const terminal = payload.replyAuthority === true || payload.final === true;
    return {
      ...base,
      type: "assistant",
      eventType: "assistant",
      status: terminal ? "completed" : "running",
      label: "agentrun:assistant:message",
      message: textPayload(payload, "assistant message"),
      text: textPayload(payload, ""),
      itemId: payload.itemId ?? null,
      messageIndex: payload.messageIndex ?? null,
      messageCount: payload.messageCount ?? null,
      replyAuthority: payload.replyAuthority === true,
      final: payload.final === true,
      terminal
    };
  }
  if (event.type === "tool_call") {
    const commandExecution = agentRunCommandExecutionEvent(base, payload);
    if (commandExecution) return commandExecution;
    const preview = agentRunToolCallPreviewSummary(payload);
    const toolName = firstNonEmpty(
      payload.toolName,
      payload.name,
      payload.item?.type,
      payload.type,
      preview.toolName,
      preview.name,
      preview.type,
      isProtocolToolLifecycleMethod(payload.method) ? null : payload.method,
      "tool call"
    );
    const command = firstNonEmpty(payload.command, payload.commandLine, payload.item?.command, payload.item?.commandLine, preview.command, preview.commandLine);
    const output = firstNonEmpty(payload.outputSummary, payload.stdoutSummary, preview.outputSummary, preview.stdoutSummary, payload.summary?.text, payload.itemPreview);
    return {
      ...base,
      type: "tool_call",
      eventType: "tool_call",
      status: String(payload.status ?? preview.status ?? (payload.method === "item/completed" ? "completed" : "running")),
      label: `agentrun:tool:${String(toolName)}`,
      itemId: payload.item?.id ?? payload.itemId ?? preview.itemId ?? null,
      toolName,
      command,
      exitCode: Number.isInteger(payload.item?.exitCode) ? payload.item.exitCode : Number.isInteger(payload.exitCode) ? payload.exitCode : undefined,
      durationMs: typeof payload.item?.durationMs === "number" ? payload.item.durationMs : typeof payload.durationMs === "number" ? payload.durationMs : undefined,
      stdoutSummary: output,
      outputSummary: output,
      message: output || command || textPayload(payload, "tool call"),
      outputBytes: typeof payload.outputBytes === "number" ? payload.outputBytes : payload.summary?.outputBytes,
      outputTruncated: payload.outputTruncated === true || payload.summary?.outputTruncated === true,
      ...(Array.isArray(payload.changes) ? { changes: payload.changes, fileCount: Number.isInteger(payload.fileCount) ? payload.fileCount : null } : {})
    };
  }
  if (event.type === "command_output") {
    const stream = payload.stream === "stderr" ? "stderr" : "stdout";
    return { ...base, type: "output", eventType: "status", status: "running", label: `agentrun:output:${stream}`, stream, message: textPayload(payload, ""), outputTruncated: payload.outputTruncated === true };
  }
  if (event.type === "diff") {
    return {
      ...base,
      type: "diff",
      eventType: "diff",
      status: String(payload.status ?? "updated"),
      label: "agentrun:diff",
      message: String(payload.diff ?? textPayload(payload, "diff")),
      diff: String(payload.diff ?? ""),
      threadId: payload.threadId ?? null,
      turnId: payload.turnId ?? null
    };
  }
  if (event.type === "error") {
    const failureKind = normalizedFailureKind(payload.failureKind ?? payload.errorCode ?? "backend") ?? "backend";
    const normalizedPayload = { ...payload, failureKind, errorCode: failureKind };
    if (isRetryableProviderInterruptionPayload(normalizedPayload, { activeError: true })) return agentRunProviderRetryEvent({ base, payload: { ...normalizedPayload, willRetry: true }, status: "retrying", label: `agentrun:provider-retry:${failureKind}` });
    return { ...base, type: "error", eventType: "error", status: "failed", label: `agentrun:error:${failureKind}`, errorCode: failureKind, failureKind, willRetry: payload.willRetry === true ? true : undefined, message: textPayload(payload, "AgentRun error") };
  }
  if (event.type === "terminal_status") {
    const terminalStatus = String(payload.terminalStatus ?? event.terminalStatus ?? payload.status ?? event.status ?? "failed");
    const failureKind = normalizedFailureKind(payload.failureKind ?? payload.errorCode ?? event.failureKind ?? event.errorCode) ?? null;
    const normalizedPayload = failureKind ? { ...payload, failureKind, errorCode: failureKind } : payload;
    if (isRetryableProviderInterruptionPayload(normalizedPayload)) return agentRunProviderRetryEvent({ base, payload: normalizedPayload, status: "retrying", label: `agentrun:provider-retry:${terminalStatus}` });
    return { ...base, type: "result", eventType: "terminal", status: terminalStatus === "cancelled" ? "canceled" : terminalStatus, label: `agentrun:terminal:${terminalStatus}`, errorCode: failureKind, failureKind, willRetry: payload.willRetry === true || event.willRetry === true ? true : undefined, message: textPayload({ ...event, ...payload }, `AgentRun terminal status ${terminalStatus}`), terminal: true };
  }
  return { ...base, type: "backend", eventType: "backend", status: "running", label: `agentrun:event:${String(event.type ?? "unknown")}`, message: textPayload(payload, "AgentRun event") };
}

export function agentRunProviderRetryEvent({ base = {}, payload = {}, status = "retrying", label = "agentrun:provider-retry" } = {}) {
  const failureKind = normalizedFailureKind(payload.failureKind ?? payload.errorCode ?? "provider-stream-disconnected");
  const retryMessage = providerRetryMessage(textPayload(payload, "Provider stream disconnected; AgentRun will retry."), payload);
  return {
    ...base,
    type: "provider_retry",
    eventType: "backend",
    status,
    label,
    errorCode: failureKind,
    failureKind,
    willRetry: payload.willRetry === true,
    retryable: true,
    transient: true,
    terminal: false,
    retryAttempt: numberOrNull(payload.retryAttempt),
    retryMax: numberOrNull(payload.retryMax),
    retryDelayMs: numberOrNull(payload.retryDelayMs),
    nextRetryAt: firstNonEmpty(payload.nextRetryAt) || null,
    retryOf: payload.retryOf ?? null,
    terminalStatus: payload.terminalStatus ?? null,
    message: retryMessage,
    valuesPrinted: false
  };
}

export function providerRetryMessage(message, payload = {}) {
  const attempt = numberOrNull(payload.retryAttempt);
  const max = numberOrNull(payload.retryMax);
  const delayMs = numberOrNull(payload.retryDelayMs);
  const nextRetryAt = firstNonEmpty(payload.nextRetryAt) || null;
  const parts = [];
  if (attempt !== null && max !== null) parts.push(`retry ${attempt}/${max}`);
  else if (attempt !== null) parts.push(`retry attempt ${attempt}`);
  else if (max !== null) parts.push(`retry max ${max}`);
  if (delayMs !== null) parts.push(`after ${delayMs}ms`);
  if (nextRetryAt) parts.push(`next=${nextRetryAt}`);
  if (parts.length === 0) return message;
  const text = String(message || "Provider stream disconnected; AgentRun will retry.").trim();
  if (attempt !== null && max !== null && text.includes(`${attempt}/${max}`)) return text;
  return text.replace(/[.。]\s*$/u, "") + `; ${parts.join(" ")}.`;
}

export function isRetryableProviderInterruptionPayload(payload = {}, options = {}) {
  const kind = normalizedFailureKind(payload?.failureKind ?? payload?.errorCode ?? payload?.code);
  if (kind === "provider-stream-disconnected") return payload?.willRetry === true;
  if (kind === "provider-unavailable") return payload?.willRetry === true || (options.activeError === true && payload?.terminal !== true && payload?.final !== true);
  if (isRetryableAgentRunTransportFailureKind(kind)) return payload?.willRetry === true;
  return false;
}

export function normalizedFailureKind(value) {
  const normalized = String(value ?? "").trim().toLowerCase().replace(/_/gu, "-") || null;
  if (normalized === "agentrun-unreachable") return "agentrun-connect-failed";
  if (normalized === "connectionrefused" || normalized === "econnrefused") return "connection-refused";
  return normalized;
}

export function numberOrNull(value) {
  const number = Number(value);
  return Number.isFinite(number) ? number : null;
}

export function agentRunTraceEvent(event = {}, backendSource = {}) {
  const source = backendSource && typeof backendSource === "object" ? backendSource : { backendProfile: backendSource };
  const backendProfile = firstNonEmpty(event.backendProfile, source.backendProfile, source.providerProfile, source.agentRun?.backendProfile);
  return {
    ...event,
    eventType: event.eventType ?? agentRunManualEventType(event),
    backend: event.backend ?? (backendProfile ? backendForBackendProfile(backendProfile) : null),
    backendProfile: event.backendProfile ?? backendProfile ?? null,
    valuesPrinted: event.valuesPrinted ?? false
  };
}

export function agentRunManualEventType(event = {}) {
  const type = String(event.type ?? "").trim().toLowerCase();
  if (type === "request") return "request";
  if (type === "cancel" || type === "result") return "terminal";
  if (type === "assistant") return "assistant";
  if (type === "tool" || type === "tool_call") return "tool_call";
  if (type === "error") return "error";
  if (type === "backend") return "backend";
  const raw = String(`${event.label ?? ""} ${event.status ?? ""}`).toLowerCase();
  if (/request|accepted/u.test(raw)) return "request";
  if (/cancel|terminal|complete|final/u.test(raw)) return "terminal";
  if (/assistant|message|reply/u.test(raw)) return "assistant";
  if (/error|fail|timeout/u.test(raw)) return "error";
  if (/backend|runner|agentrun/u.test(raw)) return "backend";
  return "status";
}

export function isProtocolToolLifecycleMethod(value) {
  return /^item\/(started|completed)$/u.test(String(value ?? ""));
}

export function agentRunToolCallPreviewSummary(payload = {}) {
  const text = firstNonEmpty(payload.itemPreview, payload.summary?.text);
  return {
    itemId: jsonPreviewStringField(text, "itemId"),
    type: jsonPreviewStringField(text, "type"),
    toolName: jsonPreviewStringField(text, "toolName"),
    name: jsonPreviewStringField(text, "name"),
    status: jsonPreviewStringField(text, "status"),
    command: jsonPreviewStringField(text, "command"),
    commandLine: jsonPreviewStringField(text, "commandLine"),
    outputSummary: jsonPreviewStringField(text, "outputSummary"),
    stdoutSummary: jsonPreviewStringField(text, "stdoutSummary")
  };
}

export function jsonPreviewStringField(text, key) {
  const body = String(text ?? "");
  if (!body || !/^[A-Za-z][A-Za-z0-9_]*$/u.test(key)) return null;
  const match = body.match(new RegExp(`"${key}"\\s*:\\s*"((?:\\\\.|[^"\\\\])*)"`, "u"));
  if (!match) return null;
  try {
    const parsed = JSON.parse(`"${match[1]}"`);
    return typeof parsed === "string" && parsed.trim() ? parsed.trim() : null;
  } catch {
    return match[1]?.trim() || null;
  }
}

export function agentRunBackendStatusDetails(phase, payload = {}) {
  if (phase === "initial-prompt-assembly") {
    return compactObject({
      initialPromptInjected: payload.initialPromptInjected === true,
      reason: firstNonEmpty(payload.reason),
      initialPrompt: agentRunResourceSummary(payload.initialPrompt),
      valuesPrinted: false
    });
  }
  if (phase === "resource-bundle-materialized") {
    return compactObject({
      kind: firstNonEmpty(payload.kind),
      commitId: firstNonEmpty(payload.commitId),
      bundles: agentRunResourceSummary(payload.bundles),
      tools: agentRunResourceSummary(payload.tools),
      promptRefs: agentRunResourceSummary(payload.promptRefs),
      skillDirs: agentRunResourceSummary(payload.skillDirs),
      initialPrompt: agentRunResourceSummary(payload.initialPrompt),
      valuesPrinted: false
    });
  }
  return undefined;
}

export function agentRunResourceSummary(value) {
  if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
  return compactObject({
    available: typeof value.available === "boolean" ? value.available : undefined,
    count: Number.isInteger(value.count) ? value.count : undefined,
    bytes: Number.isInteger(value.bytes) ? value.bytes : undefined,
    sha256: firstNonEmpty(value.sha256),
    promptRefCount: Number.isInteger(value.promptRefCount) ? value.promptRefCount : undefined,
    skillCount: Number.isInteger(value.skillCount) ? value.skillCount : undefined,
    toolCount: Number.isInteger(value.toolCount) ? value.toolCount : undefined,
    names: Array.isArray(value.names) ? value.names.map((item) => firstNonEmpty(item)).filter(Boolean).slice(0, 20) : undefined,
    targetPaths: Array.isArray(value.targetPaths) ? value.targetPaths.map((item) => firstNonEmpty(item)).filter(Boolean).slice(0, 20) : undefined,
    skillNames: Array.isArray(value.skillNames) ? value.skillNames.map((item) => firstNonEmpty(item)).filter(Boolean).slice(0, 20) : undefined,
    requiredMissing: Array.isArray(value.requiredMissing) ? value.requiredMissing.map((item) => firstNonEmpty(item)).filter(Boolean).slice(0, 20) : undefined,
    valuesPrinted: false
  });
}

export function compactObject(value) {
  if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
  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;
}

export function agentRunCommandExecutionEvent(base, payload = {}) {
  const item = payload.item && typeof payload.item === "object" ? payload.item : null;
  const payloadToolType = firstNonEmpty(payload.toolName, payload.type, payload.name);
  if (item?.type !== "commandExecution" && payloadToolType !== "commandExecution") return null;
  const method = String(payload.method ?? "");
  const completed = method === "item/completed" || payload.status === "completed" || item?.status === "completed";
  const output = firstNonEmpty(item?.aggregatedOutput, item?.stdout, item?.output, payload.outputSummary, payload.stdoutSummary, payload.summary?.text, payload.itemPreview);
  return {
    ...base,
    type: "tool_call",
    status: completed ? "completed" : "started",
    label: completed ? "item/commandExecution:completed" : "item/commandExecution:started",
    toolName: "commandExecution",
    itemId: item?.id ?? payload.itemId ?? null,
    command: firstNonEmpty(item?.command, item?.commandLine, payload.command, payload.commandLine),
    exitCode: Number.isInteger(item?.exitCode) ? item.exitCode : Number.isInteger(payload.exitCode) ? payload.exitCode : undefined,
    durationMs: typeof item?.durationMs === "number" ? item.durationMs : typeof payload.durationMs === "number" ? payload.durationMs : undefined,
    outputBytes: typeof payload.outputBytes === "number" ? payload.outputBytes : payload.summary?.outputBytes,
    stdoutSummary: output,
    outputSummary: output,
    outputTruncated: payload.outputTruncated === true || payload.summary?.outputTruncated === true,
    message: output || textPayload(payload, "commandExecution")
  };
}

export function nowMs() {
  if (typeof performance !== "undefined" && typeof performance.now === "function") return performance.now();
  return Date.now();
}

export function agentRunMapping({ env, managerUrl, backendProfile, run, command, dispatchIntent, traceId, startedAt, params = {} }) {
  if (dispatchIntent?.durable !== true) {
    throw new Error("AgentRun mapping requires a confirmed durable dispatch intent.");
  }
  const threadReused = Boolean(safeOpaqueId(params.threadId));
  return {
    adapter: ADAPTER_ID,
    managerUrl,
    backendProfile,
    providerId: resolveAgentRunProviderId(env),
    runId: run.id,
    commandId: command.id,
    attemptId: null,
    runnerId: null,
    runnerJobId: dispatchIntent.runnerJobId,
    jobName: null,
    namespace: firstNonEmpty(env.HWLAB_CODE_AGENT_AGENTRUN_RUNNER_NAMESPACE, env.AGENTRUN_RUNTIME_NAMESPACE, DEFAULT_RUNNER_NAMESPACE),
    status: `dispatch-intent-${dispatchIntent.state}`,
    dispatchIntentId: dispatchIntent.id,
    dispatchIntentState: dispatchIntent.state,
    durableDispatch: true,
    runStatus: run.status ?? null,
    commandState: command.state ?? null,
    terminalStatus: null,
    lastSeq: 0,
    traceId,
    ...codeAgentOtelTraceFields(traceId, env),
    sessionId: run?.sessionRef?.sessionId ?? null,
    conversationId: run?.sessionRef?.conversationId ?? null,
    threadId: run?.sessionRef?.threadId ?? null,
    runnerReused: false,
    runnerJobCount: dispatchIntent.state === "dispatched" ? 1 : 0,
    threadReused,
    persistentResume: threadReused,
    reused: false,
    reuseEligible: true,
    createdAt: startedAt,
    updatedAt: nowIso(),
    valuesPrinted: false
  };
}

export function agentRunReusedMapping({ previous = {}, run = {}, command = {}, traceId, startedAt, backendProfile, managerUrl, env }) {
  const threadReused = Boolean(safeOpaqueId(run?.sessionRef?.threadId ?? previous.threadId));
  return {
    ...previous,
    adapter: ADAPTER_ID,
    managerUrl,
    backendProfile,
    providerId: previous.providerId ?? resolveAgentRunProviderId(env),
    runId: previous.runId ?? run?.id,
    commandId: command.id,
    attemptId: previous.attemptId ?? null,
    runnerId: previous.runnerId ?? null,
    runnerJobId: previous.runnerJobId ?? null,
    jobName: previous.jobName ?? null,
    namespace: previous.namespace ?? DEFAULT_RUNNER_NAMESPACE,
    status: "runner-job-reused",
    runStatus: run?.status ?? previous.runStatus ?? null,
    commandState: command.state ?? null,
    terminalStatus: null,
    lastSeq: previous.lastSeq ?? 0,
    runnerJobCount: Number(previous.runnerJobCount ?? 0),
    traceId,
    sessionId: run?.sessionRef?.sessionId ?? previous.sessionId ?? null,
    conversationId: run?.sessionRef?.conversationId ?? previous.conversationId ?? null,
    threadId: run?.sessionRef?.threadId ?? previous.threadId ?? null,
    runnerReused: true,
    threadReused,
    persistentResume: threadReused,
    reused: true,
    reuseEligible: true,
    createdAt: previous.createdAt ?? startedAt,
    updatedAt: nowIso(),
    valuesPrinted: false
  };
}

export function agentRunResultRefs(result = {}) {
  const refs = {};
  for (const key of ["attemptId", "runnerId", "jobName", "namespace", "runnerJobCount"]) {
    if (result?.[key] !== undefined && result?.[key] !== null) refs[key] = result[key];
  }
  if (result?.sessionRef && typeof result.sessionRef === "object") {
    if (result.sessionRef.sessionId) refs.sessionId = result.sessionRef.sessionId;
    if (result.sessionRef.conversationId) refs.conversationId = result.sessionRef.conversationId;
    if (result.sessionRef.threadId) refs.threadId = result.sessionRef.threadId;
  }
  return refs;
}

export function withAgentRunRunnerJobCount(mapping = {}) {
  if (!mapping || typeof mapping !== "object") return mapping;
  const count = Number(mapping.runnerJobCount);
  if (Number.isFinite(count) && count >= 0) return mapping;
  const runnerJobEnsured = mapping.reused === true || mapping.status === "runner-job-ensured";
  if (runnerJobEnsured && (mapping.runnerJobId || mapping.jobName || mapping.attemptId || mapping.runnerId)) {
    return { ...mapping, runnerJobCount: 1 };
  }
  return mapping;
}

export function hwlabSessionIdForParams(params = {}) {
  return safeSessionId(params.sessionId) || null;
}

export function scopedAgentRunSessionIdForParams(params = {}, traceId) {
  const baseSessionId = hwlabSessionIdForParams(params, traceId);
  if (!safeSessionId(baseSessionId)) {
    throw adapterError(
      "agentrun_session_id_required",
      "AgentRun persistent session/PVC requires params.sessionId; refusing to derive sessionRef.sessionId from traceId because that would create a new PVC per turn."
    );
  }
  const base = String(baseSessionId).replace(/^ses_/u, "").replace(/[^A-Za-z0-9_]+/gu, "_").replace(/^_+|_+$/gu, "") || "session";
  return `ses_agentrun_${base}`;
}

export function agentRunSessionId(traceId) {
  return `ses_agentrun_${String(safeTraceId(traceId) || `trc_${randomUUID()}`).slice(4)}`;
}

export function agentRunEffectiveThreadId(base = {}) {
  const agentRun = base?.agentRun && typeof base.agentRun === "object" ? base.agentRun : null;
  if (agentRun && Object.hasOwn(agentRun, "threadId")) return safeOpaqueId(agentRun.threadId) || null;
  return safeOpaqueId(base?.threadId) || null;
}

export function agentRunSessionSummary(base, status) {
  return decorateCodeAgentSession({
    sessionId: base.sessionId ?? base.agentRun?.sessionId ?? null,
    conversationId: base.conversationId ?? base.agentRun?.conversationId ?? null,
    threadId: agentRunEffectiveThreadId(base),
    status,
    sessionMode: AGENTRUN_SESSION_MODE,
    runnerKind: AGENTRUN_RUNNER_KIND,
    lastTraceId: base.traceId ?? base.agentRun?.traceId ?? null,
    longLivedSession: true,
    codexStdio: false,
    delegatedToAgentRun: true,
    writeCapable: true,
    durable: true,
    durableSession: true,
    idleTimeoutMs: parsePositiveInteger(base.agentRun?.idleTimeoutMs, 600000),
    secretMaterialStored: false,
    valuesRedacted: true
  });
}

export function agentRunThreadReused(base = {}, options = {}) {
  if (options.status === "failed-requires-new-session") return false;
  if (base.agentRun?.threadReused === true || base.agentRun?.persistentResume === true) return true;
  return Boolean(agentRunEffectiveThreadId(base));
}

export function agentRunSessionReuseSummary(base, reused, options = {}) {
  const runnerReused = Boolean(reused);
  const threadReused = agentRunThreadReused(base, options);
  const persistentResume = threadReused;
  const sessionReused = runnerReused || persistentResume;
  return {
    sessionId: base.sessionId ?? base.agentRun?.sessionId ?? null,
    conversationId: base.conversationId ?? base.agentRun?.conversationId ?? null,
    threadId: agentRunEffectiveThreadId(base),
    reused: sessionReused,
    status: options.status ?? (runnerReused ? "reused" : persistentResume ? "thread-resumed" : "new"),
    runnerReused,
    threadReused,
    persistentResume,
    valuesRedacted: true
  };
}

export function agentRunRunnerSummary(mapping = {}) {
  return {
    kind: AGENTRUN_RUNNER_KIND,
    adapter: ADAPTER_ID,
    runId: mapping.runId ?? null,
    commandId: mapping.commandId ?? null,
    attemptId: mapping.attemptId ?? null,
    runnerId: mapping.runnerId ?? null,
    jobName: mapping.jobName ?? null,
    namespace: mapping.namespace ?? null,
    dispatchIntentId: mapping.dispatchIntentId ?? null,
    dispatchIntentState: mapping.dispatchIntentState ?? null,
    durableDispatch: mapping.durableDispatch === true,
    backendProfile: mapping.backendProfile ?? null,
    provider: providerForBackendProfile(mapping.backendProfile ?? "deepseek"),
    sessionMode: AGENTRUN_SESSION_MODE,
    implementationType: AGENTRUN_IMPLEMENTATION_TYPE,
    capabilityLevel: AGENTRUN_CAPABILITY_LEVEL,
    codexStdio: false,
    delegatedToAgentRun: true,
    writeCapable: true,
    durableSession: true,
    longLivedSession: true,
    sandbox: "danger-full-access",
    valuesPrinted: false
  };
}

export function hostForUrl(value) {
  if (!value) return null;
  try {
    return new URL(value).hostname.toLowerCase();
  } catch {
    return null;
  }
}

export function waitingForForPhase(phase) {
  if (phase.includes("runner-job")) return "agentrun-runner";
  if (phase.includes("resource-bundle")) return "agentrun-resource-bundle";
  if (phase.includes("backend")) return "agentrun-backend";
  return "agentrun-result";
}

export function textPayload(payload, fallback) {
  for (const key of ["message", "text", "content", "delta", "summary", "phase"]) {
    if (typeof payload?.[key] === "string" && payload[key].length > 0) return payload[key];
  }
  return fallback;
}

export function requiredString(value, fieldName) {
  if (typeof value === "string" && value.trim()) return value.trim();
  throw Object.assign(new Error(`AgentRun response missing ${fieldName}`), { code: "agentrun_response_invalid", statusCode: 502 });
}

export function firstNonEmpty(...values) {
  for (const value of values) {
    const text = String(value ?? "").trim();
    if (text) return text;
  }
  return null;
}

export function nowIso(now) {
  return typeof now === "function" ? now() : new Date().toISOString();
}

export function timestampIsoOrNow(value = null) {
  const parsed = Date.parse(String(value ?? ""));
  return Number.isFinite(parsed) ? new Date(parsed).toISOString() : new Date().toISOString();
}

export function redactUrl(value) {
  try {
    const url = new URL(value);
    if (url.username || url.password) {
      url.username = "***";
      url.password = "";
    }
    return url.toString();
  } catch {
    return "<invalid-url>";
  }
}
