Repository navigation
Commit 5156261
authored
feat(desktop): bind turns to a desktop and enforce its deadlines from the row (#8650)
* feat(desktop): bind turns to a desktop and enforce its deadlines from the row
A turn sent from a desktop whose background executor is registered to the
same session (and with mothership-desktop-background-executor on) is bound
to that device at admission: copilot_runs.desktop_device_id. Its desktop
calls are persisted pending, offered to the device and claimed through the
executor's own fenced routes; the chat view's authorize and confirm answer
409 for them.
There is no supervisor. The single desktop wait (waitForDesktopToolCall)
branches on the binding: a bound call is offered (pickup_deadline_at, a new
nullable column) and the device's doorbell rung, then the existing durable
wait enforces every deadline from the row on each 5 s check, beside the
lease revocation that already lives there:
- an unclaimed call whose device is offline fails at once as not started
(reason offline); one still unclaimed past its pickup window fails the same
way (reason not_responding), as the inverse CAS of the claim;
- a claimed call whose lease lapsed fails as outcome unknown, revoking the
device's token so its late result is superseded, and rings it to cancel.
Every settlement is sealed like the device's own result. The stale-execution
cron settles, the same way, bound calls whose waiter died with its process.
One not-started builder carries a reason (chat_not_open, offline,
not_responding), and the server-owned failure helper now settles through the
shared client settlement. The device is rung when a bound call needs
approval, when the user answers, and on Stop.
* fix(desktop): refuse a claim past its pickup window and leave executor leases to their own settlement
A device could claim an offered call after its pickup deadline and before the wait's next check settled it, running an action the turn was about to report as not started. The claim and the inbox now treat a closed window as no longer offered. The generic Sim lease sweep no longer settles a desktop executor's lapsed lease with the Sim interrupted result: the bound wait and the stale-execution cron settle it as outcome unknown, so the model is told the action may already have taken effect.
* fix(desktop): settle Stop without the device, survive Redis errors, and only run offered calls
Stop on a call the background executor held never settled the turn's tool
executions unless the device acknowledged: the executor's claim marked a Sim
execution as started, and Stop does not settle that execution. A device that
was asleep, offline or signed out left abortRun unsettled and the next turn's
workbench pending. The executor's claim now takes only its owner token and
lease; no Sim handler runs for it, so Sim-execution quiescence ignores it, as
it already ignores the chat view's desktop claims.
An overdue unclaimed call now settles from its row when presence cannot be
read, and never fails early as offline on a failed read; each call in the
cron's sweep settles in its own try/catch; presence writes are best effort, so
a Redis error no longer fails a pull or a renewal.
The executor takes only a call Sim offered it, within its pickup window, and
the inbox lists unclaimed calls only while offered or waiting for the user. A
call Sim never got to offer gets an implicit deadline one pickup window after
it could first run, so the cron still settles it.
A revoked install id stays revoked on re-registration, a claim racing the
device binding answers "no longer waiting", Stop rings the device only after
its chat is validated, the two device lookups are one, and the desktop inbox
E2E runs in the http-e2e CI job against its own app with Redis.
* test(desktop): assert outcomes instead of mock calls, and drive Stop through abortRun
The desktop tests asserted that mocks were or were not called. They now assert what the caller sees: the 409, the sweep's settled count, and the device's own doorbell, which Stop now rings through the real abortRun against a stand-in worker.
* fix(desktop): never fail an awake device's call as offline because a presence write was lost
Presence writes are best effort, so a pull whose write failed left the key
missing and the next read took the device for offline, failing its pending
call early. A call now fails early as offline only when presence is absent and
the device has not pulled for longer than the presence TTL plus the interval
at which a pull writes last_seen_at; otherwise its pickup window decides.
The audit test no longer depends on the insertion order of audit writes,
which are not awaited.
* fix(desktop): pre-merge review fixes for the bound executor
- Terminal approvals carry their command at args.args.command, so the
inbox summary read nothing; it now reads the terminal call's real shape,
and the tests use it.
- A turn budget shorter than the pickup window left a bound call pending; an
unclaimed call is now settled as never started through the pending-only
path, as the chat-view wait does.
- Ringing the device is best effort: a publish that throws is logged and can
no longer break Stop or any other caller.
- Running claimed calls are no longer fetched for the inbox, and offered or
awaiting calls and cancel items are fetched with separate caps, so neither
can starve the other.
- No pickup window runs while the user decides: an offer refuses a call still
awaiting approval, and recording the decision clears any pickup deadline,
so an allowed call's window starts when it is offered after the answer.
- The per-user rate limit refills every second instead of in one lump a
minute, so a device that spent its burst can still renew its leases.
- The integration suites delete the audit rows they create.1 parent d8ba4bf commit 5156261
43 files changed
Lines changed: 32192 additions & 178 deletions
File tree
- .github/workflows
- apps/sim
- app/api
- copilot
- confirm
- tool-permission
- desktop/tool/authorize
- background
- lib
- api/server/routes
- desktop
- application
- executor
- mothership
- async-runs
- chat
- application
- persistence/tool-confirm
- request
- application
- handlers
- lifecycle
- tools
- scripts
- packages
- db
- migrations
- meta
- desktop-bridge/src
- testing/src/mocks
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
123 | 123 | | |
124 | 124 | | |
125 | 125 | | |
126 | | - | |
| 126 | + | |
| 127 | + | |
127 | 128 | | |
128 | 129 | | |
129 | 130 | | |
| |||
138 | 139 | | |
139 | 140 | | |
140 | 141 | | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
141 | 152 | | |
142 | 153 | | |
143 | 154 | | |
| |||
298 | 309 | | |
299 | 310 | | |
300 | 311 | | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
301 | 360 | | |
302 | 361 | | |
303 | 362 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
131 | 131 | | |
132 | 132 | | |
133 | 133 | | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
134 | 154 | | |
135 | 155 | | |
136 | 156 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
43 | | - | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
44 | 48 | | |
45 | 49 | | |
46 | 50 | | |
| |||
206 | 210 | | |
207 | 211 | | |
208 | 212 | | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
209 | 224 | | |
210 | 225 | | |
211 | 226 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
136 | 137 | | |
137 | 138 | | |
138 | 139 | | |
| 140 | + | |
| 141 | + | |
139 | 142 | | |
140 | 143 | | |
141 | 144 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
72 | 72 | | |
73 | 73 | | |
74 | 74 | | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
75 | 95 | | |
76 | 96 | | |
77 | 97 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
77 | 83 | | |
78 | 84 | | |
79 | 85 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
34 | 35 | | |
35 | 36 | | |
36 | 37 | | |
| |||
743 | 744 | | |
744 | 745 | | |
745 | 746 | | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
746 | 760 | | |
747 | 761 | | |
748 | 762 | | |
| |||
774 | 788 | | |
775 | 789 | | |
776 | 790 | | |
| 791 | + | |
777 | 792 | | |
778 | 793 | | |
779 | 794 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | | - | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
30 | 32 | | |
31 | 33 | | |
32 | 34 | | |
33 | | - | |
| 35 | + | |
34 | 36 | | |
0 commit comments