fix: bound web probe collect file output (#686)
Co-authored-by: Codex <codex@noreply.local>
This commit is contained in:
@@ -7753,13 +7753,15 @@ function runNodeWebProbeObserveCollect(options: NodeWebProbeObserveOptions, spec
|
||||
const result = runTransWorkspaceStdinScript(options.node, spec.workspace, script, options.commandTimeoutSeconds);
|
||||
const collect = parseJsonObject(result.stdout);
|
||||
return withWebObserveCollectRendered({
|
||||
ok: result.exitCode === 0 && collect?.ok !== false,
|
||||
status: result.exitCode === 0 ? "collected" : "blocked",
|
||||
ok: result.exitCode === 0 && collect !== null && collect.ok !== false,
|
||||
status: result.exitCode === 0 && collect !== null ? "collected" : "blocked",
|
||||
command: webObserveCommandLabel("collect", options),
|
||||
id: webObserveIdFromOptions(options),
|
||||
node: options.node,
|
||||
lane: options.lane,
|
||||
workspace: spec.workspace,
|
||||
requestedFile: options.collectFile,
|
||||
degradedReason: collect === null ? "collect-json-parse-failed" : null,
|
||||
collect,
|
||||
result: collect === null ? compactCommandResultWithStdoutTail(result) : compactCommandResult(result),
|
||||
valuesRedacted: true,
|
||||
@@ -7776,10 +7778,10 @@ function withWebObserveCollectRendered(value: Record<string, unknown>): Rendered
|
||||
}
|
||||
|
||||
function renderWebObserveCollectTable(value: Record<string, unknown>): string {
|
||||
const collect = record(value.collect);
|
||||
const collect = nullableRecord(value.collect);
|
||||
const result = record(value.result);
|
||||
const file = record(collect.file);
|
||||
const files = Array.isArray(collect.files) ? collect.files.map(record).filter((item): item is Record<string, unknown> => item !== null).slice(0, 20) : [];
|
||||
const file = record(collect?.file);
|
||||
const files = Array.isArray(collect?.files) ? collect.files.map(record).filter((item): item is Record<string, unknown> => item !== null).slice(0, 20) : [];
|
||||
const jsonlTail = Array.isArray(file.jsonlTail) ? file.jsonlTail.map(record).filter((item): item is Record<string, unknown> => item !== null).slice(-8) : [];
|
||||
const jsonSummary = record(file.jsonSummary);
|
||||
const jsonRunnerErrors = Array.isArray(jsonSummary.runnerErrors) ? jsonSummary.runnerErrors.map(record).filter((item): item is Record<string, unknown> => item !== null).slice(-8) : [];
|
||||
@@ -7791,11 +7793,29 @@ function renderWebObserveCollectTable(value: Record<string, unknown>): string {
|
||||
webObserveText(value.id),
|
||||
webObserveText(value.node),
|
||||
webObserveText(value.lane),
|
||||
webObserveText(collect.mode ?? "files"),
|
||||
webObserveShort(webObserveText(collect.stateDir), 88),
|
||||
webObserveText(collect?.mode ?? "files"),
|
||||
webObserveShort(webObserveText(collect?.stateDir), 88),
|
||||
]]),
|
||||
"",
|
||||
];
|
||||
if (collect === null) {
|
||||
lines.push(
|
||||
"Collect command:",
|
||||
webObserveTable(["REQUESTED", "REASON", "EXIT", "TIMED_OUT", "STDOUT_BYTES", "STDOUT_TAIL", "STDERR"], [[
|
||||
webObserveShort(webObserveText(value.requestedFile), 64),
|
||||
webObserveShort(webObserveText(value.degradedReason), 40),
|
||||
webObserveText(result.exitCode),
|
||||
webObserveText(result.timedOut),
|
||||
webObserveText(result.stdoutBytes),
|
||||
webObserveShort(webObserveText(result.stdoutTail), 160),
|
||||
webObserveShort(webObserveText(result.stderr), 160),
|
||||
]]),
|
||||
"",
|
||||
"Disclosure:",
|
||||
" collect stdout was not valid JSON; fix the collect command or rerun with a narrower --file after the root cause is visible.",
|
||||
);
|
||||
return lines.join("\n");
|
||||
}
|
||||
if (collect.mode === "file") {
|
||||
lines.push(
|
||||
"File:",
|
||||
@@ -9214,6 +9234,33 @@ const fs=require('fs'),path=require('path'),crypto=require('crypto');
|
||||
const dir=process.argv[1]; const selected=process.argv[2]||''; const maxFiles=${maxFiles}; const maxReadBytes=64*1024;
|
||||
const shaFile=(file)=>'sha256:'+crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex');
|
||||
const safeRel=(value)=>Boolean(value)&&!path.isAbsolute(value)&&!value.includes('..')&&!value.includes('\\\\')&&value.split('/').every((part)=>part&&part!=='.'&&part!=='..');
|
||||
const short=(value,max=180)=>value===undefined||value===null?undefined:String(value).replace(/\\s+/g,' ').slice(0,max);
|
||||
const slimJsonl=(value)=>{
|
||||
if(!value||typeof value!=='object'||Array.isArray(value)) return {value:short(value)};
|
||||
const readiness=value.readiness&&typeof value.readiness==='object'?value.readiness:null;
|
||||
const snapshot=value.snapshot&&typeof value.snapshot==='object'?value.snapshot:null;
|
||||
const error=value.error&&typeof value.error==='object'?value.error:null;
|
||||
return {
|
||||
ts:short(value.ts||value.timestamp||value.at,32),
|
||||
seq:value.seq,
|
||||
type:short(value.type,48),
|
||||
phase:short(value.phase,32),
|
||||
commandId:short(value.commandId,40),
|
||||
commandType:short(value.commandType||value.command?.type,40),
|
||||
pageRole:short(value.pageRole,20),
|
||||
path:short(value.path||value.routePath||snapshot?.path,80),
|
||||
routeSessionId:short(value.routeSessionId||snapshot?.routeSessionId,48),
|
||||
activeSessionId:short(value.activeSessionId||snapshot?.activeSessionId,48),
|
||||
messageCount:value.messageCount??snapshot?.messageCount,
|
||||
traceEventCount:value.traceEventCount??snapshot?.traceEventCount,
|
||||
method:short(value.method,12),
|
||||
status:value.status,
|
||||
url:short(value.url,120),
|
||||
failure:short(value.failure||value.failureText||value.errorText,120),
|
||||
readiness:readiness?{ok:readiness.ok,reason:short(readiness.reason,80),path:short(readiness.path,80),domReady:readiness.domReady,workbenchShellVisible:readiness.workbenchShellVisible,sessionCreateVisible:readiness.sessionCreateVisible,commandInputVisible:readiness.commandInputVisible}:undefined,
|
||||
message:short(value.message||error?.message||value.text,180)
|
||||
};
|
||||
};
|
||||
if(selected){
|
||||
if(!safeRel(selected)){console.log(JSON.stringify({ok:false,command:'web-probe-observe collect',stateDir:dir,mode:'file',reason:'unsafe-file',file:selected,valuesRedacted:true},null,2)); process.exit(2);}
|
||||
const file=path.join(dir,selected); const relative=path.relative(dir,file);
|
||||
@@ -9223,7 +9270,7 @@ if(selected){
|
||||
const lines=text.split(/\\r?\\n/).filter(Boolean); const isJsonl=selected.endsWith('.jsonl');
|
||||
let jsonSummary=null;
|
||||
if(selected.endsWith('.json')&&!truncated){try{const parsed=JSON.parse(text); jsonSummary={topLevelKeys:parsed&&typeof parsed==='object'&&!Array.isArray(parsed)?Object.keys(parsed).slice(0,40):[],counts:parsed&&parsed.counts||null,runnerErrors:Array.isArray(parsed&&parsed.runnerErrors)?parsed.runnerErrors.slice(-8):[],findings:Array.isArray(parsed&&parsed.findings)?parsed.findings.slice(0,8):[]}}catch(error){jsonSummary={parseError:String(error&&error.message||error).slice(0,160)}}}
|
||||
const jsonlTail=isJsonl?lines.slice(-20).map((line,index)=>{try{return JSON.parse(line)}catch(error){return {parseError:true,index,lineTail:line.slice(-500),error:String(error&&error.message||error).slice(0,160)}}}):null;
|
||||
const jsonlTail=isJsonl?lines.slice(-20).map((line,index)=>{try{return slimJsonl(JSON.parse(line))}catch(error){return {parseError:true,index,lineTail:line.slice(-240),error:String(error&&error.message||error).slice(0,160)}}}):null;
|
||||
console.log(JSON.stringify({ok:true,command:'web-probe-observe collect',stateDir:dir,mode:'file',file:{path:file,relative,byteCount:st.size,sha256:shaFile(file),truncated,content:isJsonl||jsonSummary?undefined:text,jsonlTail,jsonSummary,lineCount:lines.length},valuesRedacted:true},null,2));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user