From 42da4dec9b907d34d804701bead83543f2df7445 Mon Sep 17 00:00:00 2001 From: Lyon <88232613+pikasTech@users.noreply.github.com> Date: Thu, 25 Jun 2026 14:06:31 +0800 Subject: [PATCH] fix: expose trace-frame missing-row diagnostics (#873) Co-authored-by: Codex --- scripts/src/hwlab-node-web-observe-collect.ts | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/scripts/src/hwlab-node-web-observe-collect.ts b/scripts/src/hwlab-node-web-observe-collect.ts index c01f5736..0fa5b681 100644 --- a/scripts/src/hwlab-node-web-observe-collect.ts +++ b/scripts/src/hwlab-node-web-observe-collect.ts @@ -274,6 +274,30 @@ function renderTurnSummary(rows){ const body=rows.map((row)=>pad(row.round,5)+' '+pad((row.userHash?row.userHash.slice(0,18)+' ':'')+row.userPreview,32)+' '+pad(row.traceId||'-',12)+' '+pad(row.status,10)+' '+pad(fmtDuration(row.elapsedSeconds)+'/'+(row.recentUpdateSeconds===null?'-':String(row.recentUpdateSeconds)+'s'),13)+' '+pad(row.marks,11)+' '+short(row.finalResponse?.preview||'(空内容)',80)).join('\\n'); return [title,'=======================================================',header,body||'(空内容)','', 'NEXT', ' detail: bun scripts/cli.ts hwlab nodes web-probe observe collect '+(manifest.jobId||'')+' --view trace-frame --trace-id --sample-seq '].join('\\n'); } +function diagnosticRows(label,items,limit=6){ + const selected=items.slice(-limit); + const skipped=Math.max(0,items.length-selected.length); + const prefix=skipped>0?'last '+selected.length+'/'+items.length:items.length+''; + return selected.map((item,index)=>{ + const traceId=itemTraceId(item)||item.traceId||'-'; + const status=String(item?.status||item?.kind||item?.type||'-'); + return label+' '+prefix+' #'+(skipped+index+1)+' trace='+short(traceId,22)+' status='+short(status,18)+' text='+short(textOf(item),120); + }); +} +function traceFrameDiagnosticLines(sample,traceId,matchedTraceRows){ + const allTraceRows=Array.isArray(sample.traceRows)?sample.traceRows:[]; + const allTurns=Array.isArray(sample.turns)?sample.turns:[]; + const allMessages=Array.isArray(sample.messages)?sample.messages:[]; + const allIds=unique([...allTraceRows,...allTurns,...allMessages].map((item)=>itemTraceId(item)||item?.traceId||firstTraceId(textOf(item)))).slice(0,12); + return [ + 'TRACE DIAGNOSTIC', + 'pageRole='+(sample.pageRole||'-')+' pageId='+(sample.pageId||'-')+' traceRows='+allTraceRows.length+' turns='+allTurns.length+' messages='+allMessages.length, + 'requestedTraceId='+(traceId||'-')+' matchedTraceRows='+matchedTraceRows.length+' sampleTraceIds='+(allIds.join(',')||'-'), + ...diagnosticRows('traceRow',allTraceRows), + ...diagnosticRows('turn',allTurns,4), + ...diagnosticRows('message',allMessages,4), + ]; +} function selectSample(rows){ if(requestedSampleSeq!==null){const exact=samples.find((sample)=>Number(sample.seq)===requestedSampleSeq); if(exact)return exact;} if(requestedTimestamp){const target=tsMs(requestedTimestamp); if(target!==null){const before=samples.filter((sample)=>{const ms=tsMs(sample.ts); return ms!==null&&ms<=target}).slice(-1)[0]; if(before)return before;}} @@ -293,8 +317,10 @@ function renderTraceFrame(sample,rows){ const visibleTraceRows=traceRows.slice(-24); const rowLines=visibleTraceRows.map((row,index)=>{const text=textOf(row); return short((row.status?row.status+' ':'')+text,180)||('row#'+index+' '+(row.textHash||'-'));}); if(traceRows.length>visibleTraceRows.length) rowLines.unshift('(已省略 '+(traceRows.length-visibleTraceRows.length)+' 条较早 trace rows;需要原始数据请看 samples.jsonl)'); - const rendered=['Code Agent 耗时 '+(elapsed>=0?fmtDuration(elapsed):'-')+' 最近 '+(recent>=0?String(recent)+' 秒前':'-')+' ('+status+')','=======================================================','sample seq='+(sample.seq??'-')+' ts='+(sample.ts||'-')+' traceId='+(traceId||'-')+' routeSession='+(sample.routeSessionId||'-')+' activeSession='+(sample.activeSessionId||'-'),...(rowLines.length?rowLines:['(无 trace rows;这是 blocker,不能当业务通过证据)']),'==========================','Final Response',finalResponse.preview||'(空内容)'].join('\\n'); - return {ok:rowLines.length>0,renderedText:rendered,blocker:rowLines.length>0?null:'trace-rows-missing',sampleSeq:sample.seq??null,traceId,finalResponse,valuesRedacted:true}; + const missingRows=rowLines.length===0; + const bodyRows=missingRows?['(无 trace rows;这是 blocker,不能当业务通过证据)',...traceFrameDiagnosticLines(sample,traceId,traceRows)]:rowLines; + const rendered=['Code Agent 耗时 '+(elapsed>=0?fmtDuration(elapsed):'-')+' 最近 '+(recent>=0?String(recent)+' 秒前':'-')+' ('+status+')','=======================================================','sample seq='+(sample.seq??'-')+' ts='+(sample.ts||'-')+' traceId='+(traceId||'-')+' routeSession='+(sample.routeSessionId||'-')+' activeSession='+(sample.activeSessionId||'-'),...bodyRows,'==========================','Final Response',finalResponse.preview||'(空内容)'].join('\\n'); + return {ok:!missingRows,renderedText:rendered,blocker:missingRows?'trace-rows-missing':null,sampleSeq:sample.seq??null,traceId,finalResponse,traceDiagnostic:missingRows?{pageRole:sample.pageRole||null,pageId:sample.pageId||null,traceRows:Array.isArray(sample.traceRows)?sample.traceRows.length:0,turns:Array.isArray(sample.turns)?sample.turns.length:0,messages:Array.isArray(sample.messages)?sample.messages.length:0,sampleTraceIds:traceIdsFromSamples([sample]).slice(0,12)}:null,valuesRedacted:true}; } const rows=turnSummaryRows(); if(view==='turn-summary'){