fix: keep workbench agent provider profile across recovery
This commit is contained in:
@@ -706,6 +706,14 @@ export async function syncAgentRunChatResult({ traceId, currentResult = null, op
|
||||
const eventsResponse = refreshEvents ? await measuredAgentRunEventsFetch({ performanceStore, fetchImpl, managerUrl, timeoutMs, env, mapping: { ...mapped.agentRun, lastSeq: fetchPlan.afterSeq, afterSeqOverride: fetchPlan.afterSeq, eventsPageLimit: fetchPlan.limit, traceSummary: mapped.traceSummary } }) : null;
|
||||
if (eventsResponse) appendAgentRunEventsToTrace(traceStore, traceId, eventsResponse.events, mapped.agentRun);
|
||||
const nextLastSeq = eventsResponse ? agentRunTraceCursorSeq(eventsResponse, mapped.agentRun.lastSeq) : mapped.agentRun.lastSeq;
|
||||
const backendProfile = resolveAgentRunBackendProfile(env, {
|
||||
providerProfile: firstNonEmpty(
|
||||
projectionRetryParams?.providerProfile,
|
||||
projectionRetryParams?.codeAgentProviderProfile,
|
||||
projectionRetryParams?.backendProfile,
|
||||
mapped.agentRun.backendProfile
|
||||
)
|
||||
});
|
||||
recordAgentRunEventsProjectionMetrics(performanceStore, eventsResponse, previousLastSeq, nextLastSeq);
|
||||
const terminalFromEvents = agentRunTerminalStatusFromEvents(eventsResponse?.events);
|
||||
await writeWorkbenchProjectionStateForAgentRun(options.runtimeStore, {
|
||||
@@ -2090,6 +2098,7 @@ function agentRunResultToCodeAgentPayload({ base, result, traceStore, traceId, a
|
||||
return {
|
||||
...base,
|
||||
status: "completed",
|
||||
messageId: finalResponse?.messageId ?? base.messageId ?? `msg_${traceId.slice(4)}`,
|
||||
threadId: agentRunEffectiveThreadId(base),
|
||||
updatedAt: now,
|
||||
workspace: base.workspace ?? "/home/agentrun/workspace",
|
||||
@@ -2148,6 +2157,7 @@ function agentRunResultToCodeAgentPayload({ base, result, traceStore, traceId, a
|
||||
return {
|
||||
...base,
|
||||
status: canceled ? "canceled" : "failed",
|
||||
messageId: finalResponse.messageId,
|
||||
threadId: agentRunEffectiveThreadId(base),
|
||||
canceled,
|
||||
updatedAt: now,
|
||||
|
||||
@@ -1989,6 +1989,7 @@ test("cloud api AgentRun adapter keeps AgentRun sessions scoped to HWLAB session
|
||||
commandState: "completed",
|
||||
terminalStatus: "completed",
|
||||
completed: true,
|
||||
messageId: "msg_profile_switch_m3",
|
||||
reply: "AGENTRUN_HWLAB_MINIMAX_M3_OK",
|
||||
lastSeq: 3,
|
||||
eventCount: 3,
|
||||
@@ -2048,17 +2049,15 @@ test("cloud api AgentRun adapter keeps AgentRun sessions scoped to HWLAB session
|
||||
assert.equal(submit.status, 202);
|
||||
|
||||
const payload = await pollAgentResult(port, traceId);
|
||||
validateCodeAgentChatSchema(payload);
|
||||
assert.equal(payload.status, "completed");
|
||||
assert.equal(payload.sessionId, hwlabSessionId);
|
||||
assert.equal(payload.infrastructureBackend, "agentrun-v01/minimax-m3");
|
||||
assert.equal(payload.agentRun.backendProfile, "minimax-m3");
|
||||
assert.equal(payload.agentRun.runId, "run_hwlab_profile_switch_m3");
|
||||
assert.equal(payload.agentRun.sessionId, minimaxSessionId);
|
||||
assert.equal(payload.reply.content, "AGENTRUN_HWLAB_MINIMAX_M3_OK");
|
||||
assert.equal(calls.some((call) => call.method === "GET" && call.path === "/api/v1/runs/run_existing_deepseek"), false);
|
||||
assert.equal(calls.filter((call) => call.method === "POST" && call.path === "/api/v1/runs").length, 1);
|
||||
const stored = ownerSessions.get(hwlabSessionId);
|
||||
assert.equal(stored.session.providerProfile, "minimax-m3");
|
||||
assert.equal(stored.session.agentRun.backendProfile, "minimax-m3");
|
||||
assert.equal(stored.session.agentRun.sessionId, minimaxSessionId);
|
||||
} finally {
|
||||
@@ -2067,6 +2066,167 @@ test("cloud api AgentRun adapter keeps AgentRun sessions scoped to HWLAB session
|
||||
}
|
||||
});
|
||||
|
||||
test("cloud api AgentRun adapter inherits session provider profile when a recovered Workbench page omits it", async () => {
|
||||
const calls = [];
|
||||
const hwlabSessionId = "ses_server-test-profile-inherit";
|
||||
const agentRunSessionId = "ses_agentrun_server_test_profile_inherit";
|
||||
const conversationId = "cnv_server-test-profile-inherit";
|
||||
const threadId = "019e8078-db67-7750-a5d9-1a99f3abd446";
|
||||
const ownerSessions = new Map([[hwlabSessionId, testAgentSessionRecord({
|
||||
sessionId: hwlabSessionId,
|
||||
conversationId,
|
||||
threadId,
|
||||
traceId: "trc_existing_dsflash_go",
|
||||
status: "active",
|
||||
session: {
|
||||
providerProfile: "dsflash-go",
|
||||
codeAgentProviderProfile: "dsflash-go",
|
||||
agentRun: {
|
||||
adapter: "agentrun-v01",
|
||||
backendProfile: "dsflash-go",
|
||||
runId: "run_existing_dsflash_go",
|
||||
commandId: "cmd_existing_dsflash_go",
|
||||
sessionId: agentRunSessionId,
|
||||
terminalStatus: "completed",
|
||||
reuseEligible: false
|
||||
}
|
||||
}
|
||||
})]]);
|
||||
|
||||
const agentRunServer = createHttpServer(async (request, response) => {
|
||||
const url = new URL(request.url || "/", "http://127.0.0.1");
|
||||
const chunks = [];
|
||||
for await (const chunk of request) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
||||
const body = chunks.length ? JSON.parse(Buffer.concat(chunks).toString("utf8")) : null;
|
||||
calls.push({ method: request.method, path: url.pathname, body });
|
||||
const send = (data) => {
|
||||
response.writeHead(200, { "content-type": "application/json" });
|
||||
response.end(`${JSON.stringify({ ok: true, data, traceId: "trc_fake_profile_inherit" })}\n`);
|
||||
};
|
||||
if (request.method === "POST" && url.pathname === "/api/v1/runs") {
|
||||
assert.equal(body.backendProfile, "dsflash-go");
|
||||
assert.equal(body.sessionRef.sessionId, agentRunSessionId);
|
||||
assert.equal(body.sessionRef.metadata.hwlabSessionId, hwlabSessionId);
|
||||
assert.equal(body.sessionRef.metadata.agentRunSessionProfile, "dsflash-go");
|
||||
return send({ id: "run_hwlab_profile_inherit", status: "pending", backendProfile: "dsflash-go", sessionRef: body.sessionRef, resourceBundleRef: body.resourceBundleRef });
|
||||
}
|
||||
if (request.method === "POST" && url.pathname === "/api/v1/runs/run_hwlab_profile_inherit/commands") {
|
||||
assert.equal(body.payload.providerProfile, "dsflash-go");
|
||||
assert.equal(body.payload.sessionId, agentRunSessionId);
|
||||
assert.equal(body.payload.hwlabSessionId, hwlabSessionId);
|
||||
assert.equal(body.payload.threadId, null);
|
||||
return send({ id: "cmd_hwlab_profile_inherit", runId: "run_hwlab_profile_inherit", state: "pending", type: "turn", seq: 1 });
|
||||
}
|
||||
if (request.method === "GET" && url.pathname === "/api/v1/runs/run_hwlab_profile_inherit/commands") {
|
||||
return send({ items: [
|
||||
{ id: "cmd_hwlab_profile_inherit", runId: "run_hwlab_profile_inherit", state: "completed", type: "turn", seq: 1, idempotencyKey: "trc_server-test-agentrun-profile-inherit", payload: { traceId: "trc_server-test-agentrun-profile-inherit", conversationId, hwlabSessionId, threadId, providerProfile: "dsflash-go" } }
|
||||
] });
|
||||
}
|
||||
if (request.method === "POST" && url.pathname === "/api/v1/runs/run_hwlab_profile_inherit/runner-jobs") {
|
||||
assert.equal(body.commandId, "cmd_hwlab_profile_inherit");
|
||||
return send({
|
||||
action: "create-kubernetes-job",
|
||||
runId: "run_hwlab_profile_inherit",
|
||||
commandId: "cmd_hwlab_profile_inherit",
|
||||
attemptId: "attempt_hwlab_profile_inherit",
|
||||
runnerId: "runner_hwlab_profile_inherit",
|
||||
namespace: "agentrun-v01",
|
||||
jobName: "agentrun-v01-runner-profile-inherit",
|
||||
jobIdentity: { namespace: "agentrun-v01", name: "agentrun-v01-runner-profile-inherit" },
|
||||
runner: { attemptId: "attempt_hwlab_profile_inherit", runnerId: "runner_hwlab_profile_inherit" }
|
||||
});
|
||||
}
|
||||
if (request.method === "GET" && url.pathname === "/api/v1/runs/run_hwlab_profile_inherit/events") {
|
||||
return send({ items: [
|
||||
{ id: "evt_profile_inherit_1", runId: "run_hwlab_profile_inherit", seq: 1, type: "backend_status", payload: { phase: "runner-job-created", commandId: "cmd_hwlab_profile_inherit", attemptId: "attempt_hwlab_profile_inherit", jobName: "agentrun-v01-runner-profile-inherit", namespace: "agentrun-v01" }, createdAt: "2026-06-02T00:00:00.000Z" },
|
||||
{ id: "evt_profile_inherit_2", runId: "run_hwlab_profile_inherit", seq: 2, type: "assistant_message", payload: { commandId: "cmd_hwlab_profile_inherit", text: "AGENTRUN_DSFLASH_GO_OK" }, createdAt: "2026-06-02T00:00:01.000Z" },
|
||||
{ id: "evt_profile_inherit_3", runId: "run_hwlab_profile_inherit", seq: 3, type: "terminal_status", payload: { commandId: "cmd_hwlab_profile_inherit", terminalStatus: "completed" }, createdAt: "2026-06-02T00:00:02.000Z" }
|
||||
] });
|
||||
}
|
||||
if (request.method === "GET" && url.pathname === "/api/v1/runs/run_hwlab_profile_inherit/commands/cmd_hwlab_profile_inherit/result") {
|
||||
return send({
|
||||
runId: "run_hwlab_profile_inherit",
|
||||
commandId: "cmd_hwlab_profile_inherit",
|
||||
attemptId: "attempt_hwlab_profile_inherit",
|
||||
runnerId: "runner_hwlab_profile_inherit",
|
||||
jobName: "agentrun-v01-runner-profile-inherit",
|
||||
namespace: "agentrun-v01",
|
||||
status: "completed",
|
||||
runStatus: "completed",
|
||||
commandState: "completed",
|
||||
terminalStatus: "completed",
|
||||
completed: true,
|
||||
messageId: "msg_profile_inherit",
|
||||
reply: "AGENTRUN_DSFLASH_GO_OK",
|
||||
lastSeq: 3,
|
||||
eventCount: 3,
|
||||
sessionRef: { sessionId: agentRunSessionId, conversationId, threadId }
|
||||
});
|
||||
}
|
||||
response.writeHead(404, { "content-type": "application/json" });
|
||||
response.end(`${JSON.stringify({ ok: false, failureKind: "schema-invalid", message: `unexpected ${request.method} ${url.pathname}`, traceId: "trc_fake_profile_inherit" })}\n`);
|
||||
});
|
||||
await new Promise((resolve) => agentRunServer.listen(0, "127.0.0.1", resolve));
|
||||
|
||||
const agentRunPort = agentRunServer.address().port;
|
||||
const server = createCloudApiServer({
|
||||
env: {
|
||||
HWLAB_CODE_AGENT_ADAPTER: "agentrun-v01",
|
||||
AGENTRUN_MGR_URL: `http://127.0.0.1:${agentRunPort}`,
|
||||
HWLAB_CODE_AGENT_AGENTRUN_ALLOW_NON_K3S_URL: "1",
|
||||
HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID: "D601",
|
||||
HWLAB_CODE_AGENT_AGENTRUN_SOURCE_COMMIT: "0123456789abcdef0123456789abcdef01234567",
|
||||
HWLAB_CODE_AGENT_DEFAULT_PROVIDER_PROFILE: "codex",
|
||||
HWLAB_ENVIRONMENT: "v02",
|
||||
HWLAB_GITOPS_PROFILE: "v02"
|
||||
},
|
||||
accessController: {
|
||||
required: false,
|
||||
async authenticate() {
|
||||
return { ok: true, actor: TEST_AGENT_ACTOR, session: TEST_AUTH_SESSION };
|
||||
},
|
||||
async recordAgentSessionOwner(input) {
|
||||
const previous = ownerSessions.get(input.sessionId)?.session ?? {};
|
||||
const record = testAgentSessionRecord({ ...input, session: { ...previous, ...(input.session ?? {}) } });
|
||||
ownerSessions.set(record.id, record);
|
||||
return record;
|
||||
},
|
||||
async getAgentSession(sessionId) {
|
||||
return ownerSessions.get(sessionId) ?? null;
|
||||
}
|
||||
}
|
||||
});
|
||||
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
||||
|
||||
try {
|
||||
const { port } = server.address();
|
||||
const traceId = "trc_server-test-agentrun-profile-inherit";
|
||||
const submit = await fetch(`http://127.0.0.1:${port}/v1/agent/chat`, {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json", "x-trace-id": traceId, cookie: "hwlab_session=test-stub-session" },
|
||||
body: JSON.stringify({
|
||||
conversationId,
|
||||
sessionId: hwlabSessionId,
|
||||
ownerUserId: "usr_agent_owner",
|
||||
ownerRole: "user",
|
||||
message: "Continue with the Workbench session provider profile"
|
||||
})
|
||||
});
|
||||
assert.equal(submit.status, 202);
|
||||
|
||||
const payload = await pollAgentResult(port, traceId);
|
||||
assert.equal(payload.status, "completed");
|
||||
assert.equal(payload.agentRun.backendProfile, "dsflash-go");
|
||||
assert.equal(calls.filter((call) => call.method === "POST" && call.path === "/api/v1/runs").length, 1);
|
||||
const stored = ownerSessions.get(hwlabSessionId);
|
||||
assert.equal(stored.session.providerProfile, "dsflash-go");
|
||||
assert.equal(stored.session.agentRun.backendProfile, "dsflash-go");
|
||||
} finally {
|
||||
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
|
||||
await new Promise((resolve, reject) => agentRunServer.close((error) => (error ? reject(error) : resolve())));
|
||||
}
|
||||
});
|
||||
|
||||
test("cloud api AgentRun adapter rejects non-internal manager URLs by default", async () => {
|
||||
const server = createCloudApiServer({
|
||||
env: {
|
||||
@@ -3194,6 +3354,11 @@ test("cloud api projection resume retries evicted AgentRun session with stored p
|
||||
HWLAB_CODE_AGENT_AGENTRUN_SOURCE_COMMIT: "a".repeat(40),
|
||||
HWLAB_CODE_AGENT_AGENTRUN_PROVIDER_ID: "JD01",
|
||||
HWLAB_RUNTIME_NAMESPACE: "hwlab-v03",
|
||||
HWLAB_RUNTIME_LANE: "v03",
|
||||
HWLAB_RUNTIME_API_URL: "http://hwlab-cloud-api.hwlab-v03.svc.cluster.local:6667",
|
||||
HWLAB_RUNTIME_WEB_URL: "http://hwlab-cloud-web.hwlab-v03.svc.cluster.local:8080",
|
||||
HWLAB_RUNTIME_ENDPOINT_LOCKED: "1",
|
||||
HWLAB_CODE_AGENT_ASSEMBLED_RUNTIME: "1",
|
||||
HWLAB_CODE_AGENT_AGENTRUN_BACKEND_PROFILE: "dsflash-go",
|
||||
HWLAB_CODE_AGENT_AGENTRUN_PROJECTION_RESUME_ENABLED: "1",
|
||||
HWLAB_CODE_AGENT_AGENTRUN_PROJECTION_RESUME_INITIAL_DELAY_MS: "1",
|
||||
@@ -3205,7 +3370,7 @@ test("cloud api projection resume retries evicted AgentRun session with stored p
|
||||
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
||||
|
||||
try {
|
||||
for (let index = 0; index < 100 && !calls.some((call) => call.path === `/api/v1/runs/${retryRunId}/commands`); index += 1) await delay(10);
|
||||
for (let index = 0; index < 100 && projectionStates.get(traceId)?.runId !== retryRunId; index += 1) await delay(10);
|
||||
assert.equal(calls.some((call) => call.path === `/api/v1/runs/${runId}/commands/${commandId}/result`), true);
|
||||
assert.equal(calls.some((call) => call.path === `/api/v1/runs/${retryRunId}/commands`), true);
|
||||
const state = projectionStates.get(traceId);
|
||||
|
||||
@@ -424,10 +424,57 @@ async function prepareManualCodeAgentSession({ params, options, traceId, respons
|
||||
params.conversationId = conversationId;
|
||||
params.sessionId = sessionId;
|
||||
params.projectId = requestedProjectId || sessionProjectId || DEFAULT_CODE_AGENT_PROJECT_ID;
|
||||
applyManualSessionProviderProfile(params, session);
|
||||
params.threadId = profileRecovery ? undefined : safeOpaqueId(params.threadId) || safeOpaqueId(session.threadId) || undefined;
|
||||
return { session };
|
||||
}
|
||||
|
||||
function applyManualSessionProviderProfile(params = {}, session = null) {
|
||||
const requested = firstNonEmptyValue(params.providerProfile, params.codeAgentProviderProfile);
|
||||
if (requested) {
|
||||
const normalized = normalizeCodeAgentProviderProfile(requested);
|
||||
params.providerProfile = normalized;
|
||||
params.codeAgentProviderProfile = normalized;
|
||||
params.providerProfileSource = "request";
|
||||
return normalized;
|
||||
}
|
||||
const stored = manualSessionStoredProviderProfile(session);
|
||||
if (!stored) return null;
|
||||
params.providerProfile = stored;
|
||||
params.codeAgentProviderProfile = stored;
|
||||
params.providerProfileSource = "session";
|
||||
return stored;
|
||||
}
|
||||
|
||||
function manualSessionStoredProviderProfile(session = null) {
|
||||
const evidence = session?.session && typeof session.session === "object" ? session.session : {};
|
||||
const traceProfile = latestCompletedTraceResultProviderProfile(evidence.traceResults);
|
||||
const raw = firstNonEmptyValue(
|
||||
traceProfile,
|
||||
evidence.agentRun?.backendProfile,
|
||||
evidence.providerProfile,
|
||||
evidence.codeAgentProviderProfile,
|
||||
evidence.backendProfile
|
||||
);
|
||||
if (!raw) return null;
|
||||
const normalized = normalizeCodeAgentProviderProfile(raw);
|
||||
return normalized === "runtime-default" ? null : normalized;
|
||||
}
|
||||
|
||||
function latestCompletedTraceResultProviderProfile(traceResults = null) {
|
||||
if (!traceResults || typeof traceResults !== "object") return null;
|
||||
const entries = Object.values(traceResults).filter((value) => value && typeof value === "object");
|
||||
for (const result of entries.reverse()) {
|
||||
const agentRun = result.agentRun && typeof result.agentRun === "object" ? result.agentRun : null;
|
||||
if (!agentRun) continue;
|
||||
const status = normalizeTurnStatus(result.status ?? agentRun.terminalStatus ?? agentRun.commandState ?? agentRun.status);
|
||||
if (status && status !== "completed") continue;
|
||||
const profile = firstNonEmptyValue(agentRun.backendProfile, result.providerProfile, result.codeAgentProviderProfile);
|
||||
if (profile) return profile;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function manualSessionProfileRecoveryAllowed(session, params = {}) {
|
||||
const status = String(session?.status ?? "").trim().toLowerCase().replace(/_/gu, "-");
|
||||
if (status !== "thread-resume-failed") return false;
|
||||
@@ -863,6 +910,8 @@ function agentChatOtelAttributes(params = {}) {
|
||||
const execution = mdtodoExecutionContextFromParams(params);
|
||||
return {
|
||||
"agent.chat.session_id": safeSessionId(params.sessionId) || null,
|
||||
"agent.chat.provider_profile": safeOtelConfigText(params.providerProfile ?? params.codeAgentProviderProfile),
|
||||
"agent.chat.provider_profile_source": safeOtelConfigText(params.providerProfileSource),
|
||||
"agent.chat.task_ref": safeOtelText(params.taskRef ?? execution?.taskRef),
|
||||
"agent.chat.source_id": safeOtelConfigText(execution?.sourceId ?? params.sourceId),
|
||||
"agent.chat.hwpod_id": safeOtelText(execution?.hwpodId),
|
||||
@@ -1594,7 +1643,8 @@ async function runAgentRunProjectionResumePass({ options = {}, traceStore = defa
|
||||
attempts: retryAttempt,
|
||||
nextRetryAtMs,
|
||||
exhausted: retryExhausted,
|
||||
lastErrorCode: error?.code ?? "projection_resume_sync_failed"
|
||||
lastErrorCode: error?.code ?? "projection_resume_sync_failed",
|
||||
lastErrorMessage: safeOtelText(error?.message, 300)
|
||||
});
|
||||
appendProjectionResumeError(traceStore, candidate, error, { retryAttempt, retryMaxAttempts: candidateRetryMaxAttempts, retryLabel: retryAttempt + "/" + candidateRetryMaxAttempts, retryDelayMs, nextRetryAt, retryExhausted });
|
||||
}
|
||||
@@ -1615,12 +1665,23 @@ async function runAgentRunProjectionResumePass({ options = {}, traceStore = defa
|
||||
skippedCooldown,
|
||||
skippedExhausted,
|
||||
candidateRetryTracked: candidateRetryState.size,
|
||||
candidateRetryLastErrorCode: latestProjectionResumeRetryField(candidateRetryState, "lastErrorCode"),
|
||||
candidateRetryLastErrorMessage: latestProjectionResumeRetryField(candidateRetryState, "lastErrorMessage"),
|
||||
candidateRetryMaxAttempts,
|
||||
valuesRedacted: true
|
||||
});
|
||||
return { offset, scannedSessions: sessions.length, candidates: candidates.length, resumed, terminal, nonTerminal, failed, skippedCooldown, skippedExhausted };
|
||||
}
|
||||
|
||||
function latestProjectionResumeRetryField(candidateRetryState, field) {
|
||||
const values = [...candidateRetryState.values()];
|
||||
for (let index = values.length - 1; index >= 0; index -= 1) {
|
||||
const text = textValue(values[index]?.[field]);
|
||||
if (text) return text;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function listAgentRunProjectionResumeStateCandidates(options = {}, batchSize = DEFAULT_AGENTRUN_PROJECTION_RESUME_BATCH_SIZE, offset = 0, { minAgeMs = DEFAULT_AGENTRUN_PROJECTION_RESUME_MIN_AGE_MS } = {}) {
|
||||
const runtimeStore = options.runtimeStore;
|
||||
if (typeof runtimeStore?.queryWorkbenchProjectionStates !== "function") return [];
|
||||
@@ -3450,7 +3511,9 @@ function codeAgentSessionOwnerEvidence(payload = {}, params = {}) {
|
||||
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);
|
||||
return {
|
||||
...(providerProfile ? { providerProfile, codeAgentProviderProfile: providerProfile } : {}),
|
||||
provider: payload.provider ?? null,
|
||||
model: payload.model ?? null,
|
||||
backend: payload.backend ?? null,
|
||||
@@ -3475,6 +3538,21 @@ function codeAgentSessionOwnerEvidence(payload = {}, params = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user