fix: refresh full trace aggregates in caserun
This commit is contained in:
@@ -24,6 +24,7 @@ rmSync(checkoutDir, { recursive: true, force: true });
|
||||
run("git", ["clone", "--no-checkout", "--single-branch", "--branch", bootRef, readUrl, checkoutDir], "/");
|
||||
run("git", ["checkout", "--detach", bootCommit], checkoutDir);
|
||||
linkNodeModules();
|
||||
ensureRuntimeDependencies();
|
||||
installHwpodAliases();
|
||||
|
||||
const scriptPath = path.join(checkoutDir, bootSh);
|
||||
@@ -49,6 +50,30 @@ function linkNodeModules(): void {
|
||||
symlinkSync(runtimeNodeModules, target, "dir");
|
||||
}
|
||||
|
||||
function ensureRuntimeDependencies(): void {
|
||||
const packageJson = path.join(checkoutDir, "package.json");
|
||||
if (!existsSync(packageJson)) return;
|
||||
if (canResolvePackage("yaml")) {
|
||||
process.stdout.write(`${JSON.stringify({ event: "hwlab-env-reuse-dependencies", status: "cached", package: "yaml" })}\n`);
|
||||
return;
|
||||
}
|
||||
|
||||
const npmCommand = process.env.HWLAB_NPM_COMMAND || "npm";
|
||||
process.stdout.write(`${JSON.stringify({ event: "hwlab-env-reuse-dependencies", status: "installing", package: "yaml", manager: npmCommand })}\n`);
|
||||
run(npmCommand, ["install", "--omit=dev", "--include=optional", "--ignore-scripts", "--prefer-offline"], checkoutDir);
|
||||
if (!canResolvePackage("yaml")) fail("runtime dependency install completed but package yaml is still unavailable");
|
||||
process.stdout.write(`${JSON.stringify({ event: "hwlab-env-reuse-dependencies", status: "installed", package: "yaml", manager: npmCommand })}\n`);
|
||||
}
|
||||
|
||||
function canResolvePackage(packageName: string): boolean {
|
||||
const result = spawnSync(process.execPath, ["-e", `require.resolve(${JSON.stringify(packageName)})`], {
|
||||
cwd: checkoutDir,
|
||||
env: process.env,
|
||||
stdio: "ignore"
|
||||
});
|
||||
return !result.error && !result.signal && result.status === 0;
|
||||
}
|
||||
|
||||
function installHwpodAliases(): void {
|
||||
installHwpodAlias("hwpod", "tools/hwpod-cli.ts");
|
||||
installHwpodAlias("hwpod-ctl", "tools/hwpod-ctl.ts");
|
||||
|
||||
@@ -1799,7 +1799,7 @@ async function writeCaseAggregateFromRegistry(context: CaseContext, caseRepo: st
|
||||
if (!evidence && !run && !manifest) throw cliError("case_registry_run_not_found", "case registry run artifacts were not found", { caseRepoRunDir, caseId, runId });
|
||||
const outputRel = aggregateOutputRel(context);
|
||||
const outputPath = path.join(caseRepoRunDir, outputRel);
|
||||
const markdown = await renderCaseAggregateMarkdown({ caseRepoRunDir, caseId, runId, evidence, run, manifest });
|
||||
const markdown = await renderCaseAggregateMarkdown(context, { caseRepoRunDir, caseId, runId, evidence, run, manifest });
|
||||
await mkdir(path.dirname(outputPath), { recursive: true });
|
||||
await writeFile(outputPath, markdown, "utf8");
|
||||
const file = await registryAggregateFileRecord(outputPath);
|
||||
@@ -1829,16 +1829,16 @@ function aggregateOutputRel(context: CaseContext) {
|
||||
return rel;
|
||||
}
|
||||
|
||||
async function renderCaseAggregateMarkdown(input: { caseRepoRunDir: string; caseId: string; runId: string; evidence: any; run: any; manifest: any }) {
|
||||
async function renderCaseAggregateMarkdown(context: CaseContext, input: { caseRepoRunDir: string; caseId: string; runId: string; evidence: any; run: any; manifest: any }) {
|
||||
const prompt = await readTextIfExists(path.join(input.caseRepoRunDir, "agent-prompt.md"));
|
||||
const finalResponse = await readTextIfExists(path.join(input.caseRepoRunDir, "final-response.md"));
|
||||
const diffPatch = await readTextIfExists(path.join(input.caseRepoRunDir, "agent-diff.patch"));
|
||||
const traceMarkdown = await readTextIfExists(path.join(input.caseRepoRunDir, "agent-trace.md"));
|
||||
const specText = await readTextIfExists(path.join(input.caseRepoRunDir, ".hwlab", "hwpod-spec.yaml"));
|
||||
const messages = await readJsonIfExists(path.join(input.caseRepoRunDir, "agent-messages.json"));
|
||||
const evidence = input.evidence ?? {};
|
||||
const run = input.run ?? {};
|
||||
const manifest = input.manifest ?? {};
|
||||
const archivedMessages = await readJsonIfExists(path.join(input.caseRepoRunDir, "agent-messages.json"));
|
||||
const traceLookup = manifest.traceLookup ?? evidence.traceLookup ?? run.agent?.traceLookup;
|
||||
const commands = traceLookup?.commands ?? {};
|
||||
const agent = manifest.agent ?? manifest.trace ?? evidence.agent ?? run.agent ?? {};
|
||||
@@ -1847,6 +1847,7 @@ async function renderCaseAggregateMarkdown(input: { caseRepoRunDir: string; case
|
||||
const diff = manifest.diff ?? evidence.agentDiff ?? run.agentDiff ?? {};
|
||||
const keilJob = manifest.keilJob ?? evidence.keilJob ?? null;
|
||||
const agentStage = manifest.agentStage ?? agentStageSummary(evidence);
|
||||
const messages = await aggregateMessagesWithFreshFullTrace(context, { archivedMessages, traceLookup, traceId: agent.traceId ?? trace.traceId ?? traceLookup?.traceId, run, evidence, manifest });
|
||||
const traceBody = aggregateTraceBody(messages, traceMarkdown);
|
||||
return `${[
|
||||
`# HWPOD CaseRun Aggregate: ${input.caseId}`,
|
||||
@@ -1952,6 +1953,44 @@ function aggregateTraceBody(messages: any, traceMarkdown: string) {
|
||||
return `_No readable trace artifact was found._`;
|
||||
}
|
||||
|
||||
async function aggregateMessagesWithFreshFullTrace(context: CaseContext, input: { archivedMessages: any; traceLookup: any; traceId: unknown; run: any; evidence: any; manifest: any }) {
|
||||
const archivedMessages = input.archivedMessages;
|
||||
const traceId = text(input.traceId ?? input.traceLookup?.traceId ?? input.run?.agent?.traceId ?? input.evidence?.agent?.traceId ?? input.manifest?.agent?.traceId);
|
||||
const baseUrl = text(input.traceLookup?.baseUrl ?? input.run?.agent?.baseUrl ?? input.evidence?.agent?.baseUrl);
|
||||
const apiKey = text(context.env.HWLAB_API_KEY ?? process.env.HWLAB_API_KEY);
|
||||
if (!traceId || !baseUrl || !apiKey.startsWith(HWLAB_API_KEY_PREFIX)) return archivedMessages;
|
||||
const command = [process.execPath, path.join(context.cwd, "tools/hwlab-cli/bin/hwlab-cli.mjs"), "client", "agent", "trace", traceId, "--render", "web", "--full"];
|
||||
const result = await (context.runProcess ?? runProcess)(command, context.cwd, { ...process.env, ...context.env, HWLAB_RUNTIME_WEB_URL: baseUrl });
|
||||
if (result.exitCode !== 0) return archivedMessages;
|
||||
const parsed = parseJsonMaybe(result.stdout);
|
||||
const rendered = freshRenderedTraceBody(parsed);
|
||||
const rows = arrayOfObjects(rendered?.rows);
|
||||
if (rows.length === 0) return archivedMessages;
|
||||
return clean({
|
||||
...(archivedMessages && typeof archivedMessages === "object" ? archivedMessages : {}),
|
||||
renderer: rendered.renderer ?? archivedMessages?.renderer ?? CASE_TRACE_RENDERER,
|
||||
traceSource: rendered.source ?? archivedMessages?.traceSource,
|
||||
traceLookup: archivedMessages?.traceLookup ?? input.traceLookup,
|
||||
traceId: rendered.traceId ?? traceId,
|
||||
status: rendered.traceStatus ?? rendered.status ?? archivedMessages?.status,
|
||||
sourceEventCount: rendered.sourceEventCount ?? archivedMessages?.sourceEventCount,
|
||||
renderedRowCount: rendered.renderedRowCount ?? rows.length,
|
||||
returnedRowCount: rendered.returnedRowCount ?? rows.length,
|
||||
noiseEventCount: rendered.noiseEventCount ?? archivedMessages?.noiseEventCount,
|
||||
finalResponse: rendered.finalResponse ?? archivedMessages?.finalResponse,
|
||||
rows
|
||||
});
|
||||
}
|
||||
|
||||
function freshRenderedTraceBody(parsed: any) {
|
||||
if (!parsed || typeof parsed !== "object") return null;
|
||||
const body = parsed.body && typeof parsed.body === "object" ? parsed.body : null;
|
||||
if (Array.isArray(body?.rows)) return body;
|
||||
const data = parsed.data && typeof parsed.data === "object" ? parsed.data : null;
|
||||
if (Array.isArray(data?.rows)) return data;
|
||||
return Array.isArray(parsed.rows) ? parsed : null;
|
||||
}
|
||||
|
||||
function traceEventRowFromAggregate(row: Record<string, unknown>): TraceEventRow {
|
||||
const bodyFormat = text(row.bodyFormat);
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user