fix(swads): make daily report generation resilient

This commit is contained in:
Jeffrey Wu
2026-09-09 17:59:05 +08:00
parent f4e3f41c2c
commit 8361b10c66
13 changed files with 278 additions and 38 deletions
+8 -5
View File
@@ -102,11 +102,9 @@ export class HarnessClientStore {
} else if (event.type === "assistant.completed") {
messages = updateAssistant(messages, event.payload.messageId, event.timestamp, (parts) => parts, { type: "complete", reason: "stop" }, event.runId);
} else if (event.type === "report.generated") {
const { artifact, assistantMessageId } = event.payload;
if (artifact.previewUrl) {
messages = updateAssistant(messages, assistantMessageId, event.timestamp, (parts) => parts, { type: "running" }, event.runId);
void this.loadReportImage(event);
}
const { artifact, assistantMessageId, markdown } = event.payload;
messages = updateAssistant(messages, assistantMessageId, event.timestamp, (parts) => markdown ? insertReportMarkdown(parts, markdown) : parts, { type: "running" }, event.runId);
if (artifact.previewUrl) void this.loadReportImage(event);
} else if (event.type === "tool.requested") {
const id = assistantIdForRun(messages, event.runId);
messages = updateAssistant(messages, id, event.timestamp, (parts) => upsertToolCall(parts, event.payload.toolCallId, event.payload.toolName, asArgs(event.payload.arguments)), { type: "running" }, event.runId);
@@ -243,6 +241,11 @@ function updateAssistant(messages: ThreadMessageLike[], id: string, timestamp: s
return messages.map((item, current) => current === index ? { ...item, id, content: change(typeof item.content === "string" ? [{ type: "text", text: item.content }] : item.content), status } : item);
}
function appendText(parts: ContentParts, delta: string): ContentParts { const last = parts.at(-1); return last?.type === "text" ? [...parts.slice(0, -1), { ...last, text: last.text + delta }] : [...parts, { type: "text", text: delta }]; }
function insertReportMarkdown(parts: ContentParts, markdown: string): ContentParts {
if (parts.some((part) => part.type === "text" && part.text.trim())) return parts;
const renderIndex = parts.findIndex((part) => part.type === "tool-call" && part.toolName === "render_swads_daily_report");
return renderIndex < 0 ? [...parts, { type: "text", text: markdown }] : [...parts.slice(0, renderIndex), { type: "text", text: markdown }, ...parts.slice(renderIndex)];
}
function upsertToolCall(parts: ContentParts, toolCallId: string, toolName: string, args: Record<string, string | number | boolean | null>): ContentParts {
const index = parts.findIndex((part) => part.type === "tool-call" && part.toolCallId === toolCallId);
if (index < 0) return [...parts, { type: "tool-call", toolCallId, toolName, args }];