fix: scope web probe trace fetch by project (#1443)

This commit is contained in:
Lyon
2026-06-18 00:43:45 +08:00
committed by GitHub
parent c614689e61
commit f51bf6b830
+34 -13
View File
@@ -277,9 +277,10 @@ export async function runProbe(args) {
sessionSummary = summarizeSessionRun(actions, dom);
traceSummary = summarizeTraceRun(traceSamples, dom, sessionSummary);
performanceSummary = summarizeProbePerformance(actions, startedAt, traceSamples, traceSummary);
const degradedReason = runProbeDegradedReason({ traceSummary, sessionSummary, promptValidation });
result = {
ok: true,
status: dom.requiredSelectors.workspace && dom.requiredSelectors.commandInput && dom.requiredSelectors.conversationList && promptValidation.ok ? "pass" : "blocked",
status: dom.requiredSelectors.workspace && dom.requiredSelectors.commandInput && dom.requiredSelectors.conversationList && promptValidation.ok && !degradedReason ? "pass" : "blocked",
command: "web-live-dom-probe run",
generatedAt: new Date().toISOString(),
startedAt,
@@ -296,7 +297,7 @@ export async function runProbe(args) {
traceSamples,
dom,
promptValidation,
degradedReason: runProbeDegradedReason({ traceSummary, sessionSummary, promptValidation }),
degradedReason,
artifacts: { reportPath, screenshotPath },
safety: {
repoOwnedLauncher: true,
@@ -846,6 +847,7 @@ function summarizeWorkspaceFetch(fetchResult) {
error: fetchResult?.error ?? null,
bodyPreview: fetchResult?.ok === true ? null : fetchResult?.bodyPreview ?? null,
workspaceId: workspace?.workspaceId ?? null,
projectId: normalizeProbeProjectId(workspace?.projectId) ?? null,
revision: workspace?.revision ?? null,
selectedConversationId: workspace?.selectedConversationId ?? selected?.conversationId ?? null,
selectedAgentSessionId: workspace?.selectedAgentSessionId ?? selected?.sessionId ?? null,
@@ -870,6 +872,7 @@ function summarizeConversationsFetch(fetchResult) {
count: conversations.length,
items: conversations.slice(0, 16).map((item) => ({
conversationId: item?.conversationId ?? null,
projectId: normalizeProbeProjectId(item?.projectId) ?? null,
sessionId: item?.sessionId ?? null,
threadId: item?.threadId ?? null,
status: item?.status ?? null,
@@ -954,27 +957,37 @@ async function collectTraceTimelineSample(page, args, index) {
const conversationId = firstNonEmpty(session.routeConversationId, session.api?.workspace?.selectedConversationId, session.activeTab?.conversationId);
const conversation = conversationId ? session.api?.conversations?.items?.find((item) => item.conversationId === conversationId) ?? null : null;
const traceId = firstNonEmpty(conversation?.lastTraceId, session.api?.workspace?.activeTraceId);
const traceProjectId = normalizeProbeProjectId(conversation?.projectId) ?? normalizeProbeProjectId(session.api?.workspace?.projectId) ?? normalizeProbeProjectId(args.projectId);
const traceFetch = traceId
? await fetchTraceSummaryWithRetry(page, args, traceId)
? await fetchTraceSummaryWithRetry(page, args, traceId, traceProjectId)
: { ok: false, traceId: null, degradedReason: "trace-id-missing", attempts: [] };
return { ...dom, conversationId, sessionId: conversation?.sessionId ?? session.activeTab?.sessionId ?? null, traceId, traceFetch };
return { ...dom, conversationId, projectId: traceProjectId, sessionId: conversation?.sessionId ?? session.activeTab?.sessionId ?? null, traceId, traceFetch };
}
async function fetchTraceSummaryWithRetry(page, args, traceId) {
const path = `/v1/agent/traces/${encodeURIComponent(traceId)}?projectId=${encodeURIComponent(args.projectId)}&sinceSeq=0&limit=20`;
async function fetchTraceSummaryWithRetry(page, args, traceId, projectId) {
const paths = [traceSummaryPath(traceId, projectId), ...(projectId ? [traceSummaryPath(traceId, null)] : [])];
const attempts = [];
for (let attempt = 1; attempt <= 3; attempt += 1) {
const fetched = await fetchJsonFromPage(page, path, { timeoutMs: 8000 });
const summary = summarizeTraceFetch(fetched, traceId, attempt);
attempts.push(summary);
if (summary.ok) return { ...summary, attempts };
if (attempt < 3) await page.waitForTimeout(500 * attempt);
for (const candidate of paths) {
for (let attempt = 1; attempt <= 3; attempt += 1) {
const fetched = await fetchJsonFromPage(page, candidate.path, { timeoutMs: 8000 });
const summary = summarizeTraceFetch(fetched, traceId, attempt, candidate);
attempts.push(summary);
if (summary.ok) return { ...summary, attempts };
if (summary.errorCode === "trace_project_mismatch" && candidate.projectId) break;
if (attempt < 3) await page.waitForTimeout(500 * attempt);
}
}
const last = attempts.at(-1) ?? { ok: false, traceId, degradedReason: "trace-fetch-failed" };
return { ...last, attempts, degradedReason: last.degradedReason ?? "trace-fetch-failed" };
}
function summarizeTraceFetch(fetchResult, expectedTraceId, attempt) {
function traceSummaryPath(traceId, projectId) {
const params = new URLSearchParams({ sinceSeq: "0", limit: "20" });
if (projectId) params.set("projectId", projectId);
return { path: `/v1/agent/traces/${encodeURIComponent(traceId)}?${params.toString()}`, projectId, scoped: Boolean(projectId) };
}
function summarizeTraceFetch(fetchResult, expectedTraceId, attempt, request) {
const body = fetchResult?.json?.data ?? fetchResult?.json ?? null;
const trace = body?.trace ?? body?.runnerTrace ?? body;
const events = Array.isArray(trace?.events) ? trace.events : Array.isArray(body?.events) ? body.events : [];
@@ -983,6 +996,8 @@ function summarizeTraceFetch(fetchResult, expectedTraceId, attempt) {
return {
ok,
attempt,
requestProjectId: request?.projectId ?? null,
requestScoped: request?.scoped === true,
path: fetchResult?.path ?? null,
httpStatus: fetchResult?.status ?? null,
elapsedMs: fetchResult?.elapsedMs ?? null,
@@ -995,6 +1010,7 @@ function summarizeTraceFetch(fetchResult, expectedTraceId, attempt) {
latestEventAt: latest?.createdAt ?? latest?.at ?? null,
latestEventPreview: latest ? JSON.stringify(latest).replace(/\s+/gu, " ").slice(0, 300) : null,
error: fetchResult?.error ?? null,
errorCode: body?.error?.code ?? null,
bodyPreview: ok ? null : fetchResult?.bodyPreview ?? null,
degradedReason: ok ? null : fetchResult?.status ? "trace-fetch-http-status" : "trace-fetch-failed"
};
@@ -1101,6 +1117,11 @@ function firstNonEmpty(...values) {
return null;
}
function normalizeProbeProjectId(value) {
const text = typeof value === "string" ? value.trim() : "";
return /^prj_[A-Za-z0-9_.:-]{3,96}$/u.test(text) ? text : null;
}
async function waitForCommandReady(page, args, actions) {
const timeoutMs = Math.min(args.timeoutMs, 30000);
const before = await collectCommandState(page);