fix(background): replay persisted updates before launch order
This commit is contained in:
19
index.ts
19
index.ts
@@ -110,7 +110,9 @@ export default function subagentsExtension(pi: ExtensionAPI, deps: any = {}) {
|
||||
}, { triggerTurn: false });
|
||||
} catch (e) {}
|
||||
} catch (e) {
|
||||
// monitorRun errors are non-fatal here
|
||||
// Monitoring runs happens in the background. Failures here should not
|
||||
// block tool registration or the foreground session; monitorRun errors
|
||||
// are best-effort and final failures are logged via result.json.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,18 +180,25 @@ export default function subagentsExtension(pi: ExtensionAPI, deps: any = {}) {
|
||||
// replay persisted runs if session manager provides entries
|
||||
try {
|
||||
const entries = ctx.sessionManager?.getEntries?.() ?? [];
|
||||
// clear existing registry and rebuild from session entries
|
||||
registry.replay([]);
|
||||
const launches: any[] = [];
|
||||
const updates: any[] = [];
|
||||
|
||||
for (const e of entries) {
|
||||
const type = (e.type ?? e.customType) as string | undefined;
|
||||
if (type === "pi-subagents:bg-run") {
|
||||
const run = e.data?.run ?? e.data;
|
||||
if (run && run.runId) registry.recordLaunch(run as any);
|
||||
if (run && run.runId) launches.push(run);
|
||||
} else if (type === "pi-subagents:bg-update") {
|
||||
const data = e.data;
|
||||
if (data && data.runId) registry.recordUpdate(data.runId, data as any);
|
||||
if (data && data.runId) updates.push(data);
|
||||
}
|
||||
}
|
||||
|
||||
// Rebuild in two passes so out-of-order persisted entries cannot drop
|
||||
// terminal updates that happen to appear before their launch entry.
|
||||
registry.replay([]);
|
||||
for (const run of launches) registry.recordLaunch(run as any);
|
||||
for (const update of updates) registry.recordUpdate(update.runId, update as any);
|
||||
} catch (e) {}
|
||||
|
||||
updateStatus();
|
||||
|
||||
@@ -535,3 +535,73 @@ test("background completion updates footer status, appends session updates, noti
|
||||
else process.env.PI_SUBAGENTS_CHILD = original;
|
||||
}
|
||||
});
|
||||
|
||||
test("session_start replay applies bg-update entries even when they appear before bg-run", async () => {
|
||||
const original = process.env.PI_SUBAGENTS_CHILD;
|
||||
if (original !== undefined) delete process.env.PI_SUBAGENTS_CHILD;
|
||||
|
||||
try {
|
||||
const handlers: any = {};
|
||||
const registeredTools: any[] = [];
|
||||
|
||||
subagentsExtension({
|
||||
on(event: string, handler: (event: any, ctx: any) => Promise<void> | void) {
|
||||
handlers[event] = handler;
|
||||
},
|
||||
registerTool(tool: any) {
|
||||
registeredTools.push(tool);
|
||||
},
|
||||
registerProvider() {},
|
||||
appendEntry() {},
|
||||
sendMessage() {},
|
||||
} as any);
|
||||
|
||||
await handlers.session_start?.(
|
||||
{ reason: "startup" },
|
||||
{
|
||||
modelRegistry: {
|
||||
getAvailable: () => [{ provider: "openai", id: "gpt-5" }],
|
||||
},
|
||||
ui: {
|
||||
notify() {},
|
||||
setStatus() {},
|
||||
},
|
||||
sessionManager: {
|
||||
getEntries: () => [
|
||||
{
|
||||
type: "pi-subagents:bg-update",
|
||||
data: { runId: "run-1", status: "completed", exitCode: 0, finalText: "done" },
|
||||
},
|
||||
{
|
||||
type: "pi-subagents:bg-run",
|
||||
data: {
|
||||
run: {
|
||||
runId: "run-1",
|
||||
preset: "repo-scout",
|
||||
task: "inspect auth",
|
||||
status: "running",
|
||||
startTime: Date.now(),
|
||||
paths: {
|
||||
eventsPath: "/tmp/run-1/events.jsonl",
|
||||
resultPath: "/tmp/run-1/result.json",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const statusTool = registeredTools.find((tool) => tool.name === "background_agent_status");
|
||||
assert(statusTool, "background_agent_status registered");
|
||||
|
||||
const result: any = await statusTool.execute("tool-1", { runId: "run-1" }, undefined, undefined, undefined);
|
||||
assert.equal(result.details.runs.length, 1);
|
||||
assert.equal(result.details.runs[0].status, "completed");
|
||||
assert.equal(result.details.counts.completed, 1);
|
||||
} finally {
|
||||
if (original === undefined) delete process.env.PI_SUBAGENTS_CHILD;
|
||||
else process.env.PI_SUBAGENTS_CHILD = original;
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user