* Render the approval dialog mid-call via `setToolJSX` + `Promise`, wait for * the user. Mirrors `spawnMultiAgent.ts:419-436` (the `It2SetupPrompt` pattern). * * The merge-into-AppState that used to live here (dedupe + truthy-only flags) * is now in the package's `bindSessionContext` → `onAllowe
(req: CuPermissionRequest)
| 333 | * is now in the package's `bindSessionContext` → `onAllowedAppsChanged`. |
| 334 | */ |
| 335 | async function runPermissionDialog(req: CuPermissionRequest): Promise<CuPermissionResponse> { |
| 336 | const context = tuc(); |
| 337 | const setToolJSX = context.setToolJSX; |
| 338 | if (!setToolJSX) { |
| 339 | // Shouldn't happen — main.tsx gate excludes non-interactive. Fail safe. |
| 340 | return { granted: [], denied: [], flags: DEFAULT_GRANT_FLAGS }; |
| 341 | } |
| 342 | |
| 343 | try { |
| 344 | return await new Promise<CuPermissionResponse>((resolve, reject) => { |
| 345 | const signal = context.abortController.signal; |
| 346 | // If already aborted, addEventListener won't fire — reject now so the |
| 347 | // promise doesn't hang waiting for a user who Ctrl+C'd. |
| 348 | if (signal.aborted) { |
| 349 | reject(new Error('Computer Use permission dialog aborted')); |
| 350 | return; |
| 351 | } |
| 352 | const onAbort = (): void => { |
| 353 | signal.removeEventListener('abort', onAbort); |
| 354 | reject(new Error('Computer Use permission dialog aborted')); |
| 355 | }; |
| 356 | signal.addEventListener('abort', onAbort); |
| 357 | |
| 358 | setToolJSX({ |
| 359 | jsx: React.createElement(ComputerUseApproval, { |
| 360 | request: req, |
| 361 | onDone: (resp: CuPermissionResponse) => { |
| 362 | signal.removeEventListener('abort', onAbort); |
| 363 | resolve(resp); |
| 364 | }, |
| 365 | }), |
| 366 | shouldHidePromptInput: true, |
| 367 | }); |
| 368 | }); |
| 369 | } finally { |
| 370 | setToolJSX(null); |
| 371 | } |
| 372 | } |
no test coverage detected