fix(FN-3187): stabilize agent run log streaming

This commit is contained in:
gsxdsm
2026-05-01 18:37:28 -07:00
parent 2f9364460a
commit a63e819ad0
6 changed files with 350 additions and 34 deletions

View File

@@ -2040,6 +2040,27 @@ describe("AgentStore", () => {
const completed = await store.getCompletedHeartbeatRuns(agent.id);
expect(completed.some((r) => r.id === structuredRun.id)).toBe(true);
});
it("appendRunLog emits run:log and persists the entry", async () => {
const agent = await store.createAgent({ name: "RunLogger", role: "executor" });
const run = await store.startHeartbeatRun(agent.id);
const onRunLog = vi.fn();
store.on("run:log", onRunLog);
const entry = {
timestamp: "2026-01-01T00:00:00.000Z",
taskId: "agent-run",
text: "streamed output",
type: "text" as const,
};
await store.appendRunLog(agent.id, run.id, entry);
expect(onRunLog).toHaveBeenCalledWith(agent.id, run.id, expect.objectContaining(entry));
await expect(store.getRunLogs(agent.id, run.id)).resolves.toEqual([
expect.objectContaining(entry),
]);
});
});
// ── blocked state persistence ─────────────────────────────────────

View File

@@ -88,6 +88,8 @@ export interface AgentStoreEvents {
"agent:assigned": (agent: Agent, taskId: string) => void;
/** Emitted when a rating is added */
"rating:added": (rating: AgentRating) => void;
/** Emitted when a log entry is appended to a run's JSONL log. */
"run:log": (agentId: string, runId: string, entry: AgentLogEntry) => void;
}
/** Options for AgentStore constructor */
@@ -1838,6 +1840,7 @@ export class AgentStore extends EventEmitter {
};
const line = JSON.stringify(safeEntry) + "\n";
await appendFile(this.runLogPath(agentId, runId), line, "utf-8");
this.emit("run:log", agentId, runId, safeEntry);
}
/**