@@ -81,13 +81,67 @@ function wake(input: SuperviseDesktopCallInput, message: string, data: unknown)
8181 } )
8282}
8383
84+ /** Fails a call nobody claimed as not started; returns whether this settlement won. */
85+ async function failUnclaimed (
86+ input : SuperviseDesktopCallInput ,
87+ reason : 'offline' | 'not_responding' ,
88+ message : string ,
89+ deadlinePassed : boolean
90+ ) : Promise < boolean > {
91+ const state = await getDesktopCallState ( input . toolCallId )
92+ const result = await sealFailure ( input , state ?. result , { reason, message, notStarted : true } )
93+ const failed = await failUnclaimedDesktopCall ( {
94+ toolCallId : input . toolCallId ,
95+ runId : input . runId ,
96+ result,
97+ error : message ,
98+ deadlinePassed,
99+ } )
100+ if ( failed ) wake ( input , message , result )
101+ return failed
102+ }
103+
104+ /** Fails a claimed call whose lease lapsed as outcome unknown; returns whether this settlement won. */
105+ async function failLapsed (
106+ input : SuperviseDesktopCallInput ,
107+ ownerToken : string ,
108+ existing : unknown
109+ ) : Promise < boolean > {
110+ const result = await sealFailure ( input , existing , {
111+ reason : 'lease_lost' ,
112+ message : DESKTOP_LEASE_LOST_MESSAGE ,
113+ outcomeUnknown : true ,
114+ doNotRetry : true ,
115+ } )
116+ const failed = await failLapsedDesktopCall ( {
117+ toolCallId : input . toolCallId ,
118+ runId : input . runId ,
119+ ownerToken,
120+ result,
121+ error : DESKTOP_LEASE_LOST_MESSAGE ,
122+ } )
123+ if ( failed ) wake ( input , DESKTOP_LEASE_LOST_MESSAGE , result )
124+ return failed
125+ }
126+
127+ /** A call some supervisor offered (pickup window open or closed) or the device claimed. */
128+ function isOfferedOrClaimed ( state : Awaited < ReturnType < typeof getDesktopCallState > > ) : boolean {
129+ if ( ! state ) return false
130+ if ( state . status === ASYNC_TOOL_STATUS . pending )
131+ return ! state . ownerToken && state . msUntilLeaseEnd !== null
132+ return state . status === ASYNC_TOOL_STATUS . running && Boolean ( state . ownerToken )
133+ }
134+
84135/**
85136 * Owns a desktop call on a device-bound run from the moment it may run until it settles: offers
86137 * it to the device and rings the doorbell, fails it at once as not started when the device is
87138 * offline or after the pickup window when nobody claimed it, and fails it as outcome unknown when
88139 * a claimed call's lease lapses. A running call stays alive for as long as the device renews it.
89140 * Every settlement is a CAS against the device's own transitions, so exactly one wins, and every
90141 * failure is published so the run's waiter reads it at once.
142+ *
143+ * All of its state is on the row: when the process supervising a call restarts, the next wait on
144+ * the call (the worker's handoff re-dispatches it) resumes supervision from the stored deadline.
91145 */
92146export async function superviseDesktopCall (
93147 input : SuperviseDesktopCallInput
@@ -97,65 +151,27 @@ export async function superviseDesktopCall(
97151 runId : input . runId ,
98152 pickupGraceMs : input . pickupGraceMs ?? DESKTOP_CALL_PICKUP_GRACE_MS ,
99153 } )
100- if ( ! offered ) return 'not_offered'
101- ringDesktopInbox ( input . deviceId , 'call' )
102-
103- const failUnclaimed = async (
104- reason : 'offline' | 'not_responding' ,
105- message : string ,
106- deadlinePassed : boolean
107- ) => {
108- const state = await getDesktopCallState ( input . toolCallId )
109- const result = await sealFailure ( input , state ?. result , { reason, message, notStarted : true } )
110- const failed = await failUnclaimedDesktopCall ( {
111- toolCallId : input . toolCallId ,
112- runId : input . runId ,
113- result,
114- error : message ,
115- deadlinePassed,
116- } )
117- if ( failed ) wake ( input , message , result )
118- return failed
119- }
120-
121- if ( ! ( await isDesktopPresent ( input . deviceId ) . catch ( ( ) => false ) ) ) {
122- if ( await failUnclaimed ( 'offline' , DESKTOP_OFFLINE_MESSAGE , false ) ) return 'offline'
154+ if ( offered ) {
155+ ringDesktopInbox ( input . deviceId , 'call' )
156+ if ( ! ( await isDesktopPresent ( input . deviceId ) . catch ( ( ) => false ) ) ) {
157+ if ( await failUnclaimed ( input , 'offline' , DESKTOP_OFFLINE_MESSAGE , false ) ) return 'offline'
158+ }
159+ } else if ( ! isOfferedOrClaimed ( await getDesktopCallState ( input . toolCallId ) ) ) {
160+ return 'not_offered'
123161 }
124162
125163 for ( ; ; ) {
126164 if ( input . signal ?. aborted ) return 'aborted'
127165 const state = await getDesktopCallState ( input . toolCallId )
128166 if ( ! state || isTerminalAsyncStatus ( state . status ) ) return 'settled'
167+ if ( ! isOfferedOrClaimed ( state ) ) return 'settled'
129168 const remainingMs = state . msUntilLeaseEnd ?? 0
130- if ( state . status === ASYNC_TOOL_STATUS . pending && ! state . ownerToken ) {
131- if ( remainingMs <= 0 ) {
132- if ( await failUnclaimed ( 'not_responding' , DESKTOP_NOT_RESPONDING_MESSAGE , true ) )
133- return 'not_responding'
134- continue
135- }
136- } else if ( state . status === ASYNC_TOOL_STATUS . running && state . ownerToken ) {
137- if ( remainingMs <= 0 ) {
138- const result = await sealFailure ( input , state . result , {
139- reason : 'lease_lost' ,
140- message : DESKTOP_LEASE_LOST_MESSAGE ,
141- outcomeUnknown : true ,
142- doNotRetry : true ,
143- } )
144- const failed = await failLapsedDesktopCall ( {
145- toolCallId : input . toolCallId ,
146- runId : input . runId ,
147- ownerToken : state . ownerToken ,
148- result,
149- error : DESKTOP_LEASE_LOST_MESSAGE ,
150- } )
151- if ( failed ) {
152- wake ( input , DESKTOP_LEASE_LOST_MESSAGE , result )
153- return 'lease_lost'
154- }
155- continue
156- }
157- } else {
158- return 'settled'
169+ if ( remainingMs <= 0 ) {
170+ const won = state . ownerToken
171+ ? await failLapsed ( input , state . ownerToken , state . result )
172+ : await failUnclaimed ( input , 'not_responding' , DESKTOP_NOT_RESPONDING_MESSAGE , true )
173+ if ( won ) return state . ownerToken ? 'lease_lost' : 'not_responding'
174+ continue
159175 }
160176 await interruptibleSleep ( Math . min ( remainingMs + DEADLINE_SLACK_MS , MAX_WAIT_MS ) , input . signal )
161177 }
0 commit comments