Settle in-flight run when the session is replaced or disposed
Claude-Session: https://claude.ai/code/session_01JtuZTCMW9TyogEmBgGf8JT
This commit is contained in:
@@ -184,6 +184,25 @@ describe("AgentHost", () => {
|
||||
expect(events.filter((e) => e.type === "run_settled")).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("settles an in-flight run as aborted when the session is replaced", async () => {
|
||||
const { session, host, events } = await setup();
|
||||
let release!: () => void;
|
||||
session.promptImpl = async () => {
|
||||
session.emit({ type: "agent_start" });
|
||||
await new Promise<void>((r) => (release = r));
|
||||
};
|
||||
const sending = host.send({ text: "x" });
|
||||
await new Promise((r) => setTimeout(r, 0));
|
||||
expect(events).toEqual([{ type: "run_started" }]);
|
||||
await host.newSession();
|
||||
expect(session.calls).toContain("abort");
|
||||
expect(events.at(-1)).toEqual({ type: "run_settled", finalText: "", aborted: true });
|
||||
release();
|
||||
await sending;
|
||||
session.emit({ type: "agent_settled" });
|
||||
expect(events.filter((e) => e.type === "run_settled" || e.type === "run_error")).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("emits run_error when prompt rejects", async () => {
|
||||
const { session, host, events } = await setup();
|
||||
session.promptImpl = async () => {
|
||||
|
||||
@@ -71,10 +71,14 @@ export class AgentHost {
|
||||
}
|
||||
|
||||
async newSession(): Promise<void> {
|
||||
if (this.busy) {
|
||||
await this.session?.abort().catch(() => undefined);
|
||||
}
|
||||
this.attach(await this.backend.newSession());
|
||||
}
|
||||
|
||||
async dispose(): Promise<void> {
|
||||
this.settleActiveRun();
|
||||
this.unsubscribe?.();
|
||||
this.unsubscribe = undefined;
|
||||
await this.backend.dispose();
|
||||
@@ -142,12 +146,20 @@ export class AgentHost {
|
||||
}
|
||||
|
||||
private attach(session: SessionLike): void {
|
||||
this.settleActiveRun();
|
||||
this.unsubscribe?.();
|
||||
this.session = session;
|
||||
this.run = { texts: [], terminalEmitted: true, retrying: false };
|
||||
this.unsubscribe = session.subscribe((event) => this.onSessionEvent(event));
|
||||
}
|
||||
|
||||
/** Closes out an in-flight run as an aborted settle before the session is swapped or torn down. */
|
||||
private settleActiveRun(): void {
|
||||
if (!this.run.terminalEmitted) {
|
||||
this.finishRun({ type: "run_settled", finalText: "", aborted: true });
|
||||
}
|
||||
}
|
||||
|
||||
private onSessionEvent(event: SessionEvent): void {
|
||||
switch (event.type) {
|
||||
case "agent_start":
|
||||
|
||||
Reference in New Issue
Block a user