fix: scope web probe trace fetch by project (#1443)
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user