(
allowlistBundleIds: string[],
displayId?: number,
)
| 300 | // ── Pre-action sequence (hide + defocus) ──────────────────────────── |
| 301 | |
| 302 | async prepareForAction( |
| 303 | allowlistBundleIds: string[], |
| 304 | displayId?: number, |
| 305 | ): Promise<string[]> { |
| 306 | if (!getHideBeforeActionEnabled()) { |
| 307 | return [] |
| 308 | } |
| 309 | // prepareDisplay isn't @MainActor (plain Task{}), but its .hide() calls |
| 310 | // trigger window-manager events that queue on CFRunLoop. Without the |
| 311 | // pump, those pile up during Swift's ~1s of usleeps and flush all at |
| 312 | // once when the next pumped call runs — visible window flashing. |
| 313 | // Electron drains CFRunLoop continuously so Cowork doesn't see this. |
| 314 | // Worst-case 100ms + 5×200ms safety-net ≈ 1.1s, well under the 30s |
| 315 | // drainRunLoop ceiling. |
| 316 | // |
| 317 | // "Continue with action execution even if switching fails" — the |
| 318 | // frontmost gate in toolCalls.ts catches any actual unsafe state. |
| 319 | return drainRunLoop(async () => { |
| 320 | try { |
| 321 | const result = await cu.apps.prepareDisplay( |
| 322 | allowlistBundleIds, |
| 323 | surrogateHost, |
| 324 | displayId, |
| 325 | ) |
| 326 | if (result.activated) { |
| 327 | logForDebugging( |
| 328 | `[computer-use] prepareForAction: activated ${result.activated}`, |
| 329 | ) |
| 330 | } |
| 331 | return result.hidden |
| 332 | } catch (err) { |
| 333 | logForDebugging( |
| 334 | `[computer-use] prepareForAction failed; continuing to action: ${errorMessage(err)}`, |
| 335 | { level: 'warn' }, |
| 336 | ) |
| 337 | return [] |
| 338 | } |
| 339 | }) |
| 340 | }, |
| 341 | |
| 342 | async previewHideSet( |
| 343 | allowlistBundleIds: string[], |
nothing calls this directly
no test coverage detected