Skip to content

Commit f6d9127

Browse files
committed
fix(desktop): a signed-out executor goes idle once and never speaks for its successor
dispose() now reports idle once. A recovered delivery that settles after sign-out no longer reports through the shared busy callback, where it could release the sleep blocker the next session's executor was holding.
1 parent c8897d1 commit f6d9127

2 files changed

Lines changed: 32 additions & 1 deletion

File tree

‎apps/desktop/src/main/desktop-executor/executor.test.ts‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,34 @@ describe('keeping the machine awake', () => {
488488
expect(sim.completions).toHaveLength(1)
489489
})
490490

491+
it('goes idle at sign-out and stays silent when a recovered delivery settles afterwards', async () => {
492+
const { sim, journal, executor, busy } = setup()
493+
const answer = deferred<void>()
494+
const complete = sim.client.complete
495+
let sending = false
496+
sim.client.complete = async (request) => {
497+
sending = true
498+
await answer.promise
499+
return complete(request)
500+
}
501+
await journal.put({
502+
toolCallId: 'r-1',
503+
state: 'result',
504+
executionToken: 't-1',
505+
completion: DONE,
506+
})
507+
await executor.recover()
508+
await vi.waitFor(() => expect(sending).toBe(true))
509+
expect(busy).toEqual([true])
510+
511+
await executor.dispose()
512+
expect(busy).toEqual([true, false])
513+
answer.resolve()
514+
await sleep(40)
515+
516+
expect(busy).toEqual([true, false])
517+
})
518+
491519
it('stays busy while a result a previous run left is still on its way to Sim', async () => {
492520
const { sim, journal, executor, busy } = setup()
493521
sim.completeErrors = [new DeviceRequestError(503, 'deploying')]

‎apps/desktop/src/main/desktop-executor/executor.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ export class DesktopExecutor {
188188
// cleared only after it, so its `claiming` record does not outlive the session.
189189
await this.reconciling?.catch(() => {})
190190
await Promise.all([stopping, this.dropHeld()])
191+
this.updateBusy()
191192
await this.options.journal.clear()
192193
}
193194

@@ -441,7 +442,9 @@ export class DesktopExecutor {
441442
}
442443

443444
private updateBusy(): void {
444-
const busy = this.held.size > 0 || this.recoveredInFlight > 0
445+
// A disposed executor reports idle once, at dispose; a delivery that settles later must not
446+
// speak for the executor that replaced it.
447+
const busy = !this.disposed && (this.held.size > 0 || this.recoveredInFlight > 0)
445448
if (busy === this.busy) return
446449
this.busy = busy
447450
this.options.onBusyChange?.(busy)

0 commit comments

Comments
 (0)