| 2015 | // as long as shouldContinueAnimation is true. This prevents deadlocks when |
| 2016 | // agents set background hints while waiting for user interaction. |
| 2017 | function getFocusedInputDialog(): 'message-selector' | 'sandbox-permission' | 'tool-permission' | 'prompt' | 'worker-sandbox-permission' | 'elicitation' | 'cost' | 'idle-return' | 'init-onboarding' | 'ide-onboarding' | 'model-switch' | 'undercover-callout' | 'effort-callout' | 'remote-callout' | 'lsp-recommendation' | 'plugin-hint' | 'desktop-upsell' | 'ultraplan-choice' | 'ultraplan-launch' | undefined { |
| 2018 | // Exit states always take precedence |
| 2019 | if (isExiting || exitFlow) return undefined; |
| 2020 | |
| 2021 | // High priority dialogs (always show regardless of typing) |
| 2022 | if (isMessageSelectorVisible) return 'message-selector'; |
| 2023 | |
| 2024 | // Suppress interrupt dialogs while user is actively typing |
| 2025 | if (isPromptInputActive) return undefined; |
| 2026 | if (sandboxPermissionRequestQueue[0]) return 'sandbox-permission'; |
| 2027 | |
| 2028 | // Permission/interactive dialogs (show unless blocked by toolJSX) |
| 2029 | const allowDialogsWithAnimation = !toolJSX || toolJSX.shouldContinueAnimation; |
| 2030 | if (allowDialogsWithAnimation && toolUseConfirmQueue[0]) return 'tool-permission'; |
| 2031 | if (allowDialogsWithAnimation && promptQueue[0]) return 'prompt'; |
| 2032 | // Worker sandbox permission prompts (network access) from swarm workers |
| 2033 | if (allowDialogsWithAnimation && workerSandboxPermissions.queue[0]) return 'worker-sandbox-permission'; |
| 2034 | if (allowDialogsWithAnimation && elicitation.queue[0]) return 'elicitation'; |
| 2035 | if (allowDialogsWithAnimation && showingCostDialog) return 'cost'; |
| 2036 | if (allowDialogsWithAnimation && idleReturnPending) return 'idle-return'; |
| 2037 | if (feature('ULTRAPLAN') && allowDialogsWithAnimation && !isLoading && ultraplanPendingChoice) return 'ultraplan-choice'; |
| 2038 | if (feature('ULTRAPLAN') && allowDialogsWithAnimation && !isLoading && ultraplanLaunchPending) return 'ultraplan-launch'; |
| 2039 | |
| 2040 | // Onboarding dialogs (special conditions) |
| 2041 | if (allowDialogsWithAnimation && showIdeOnboarding) return 'ide-onboarding'; |
| 2042 | |
| 2043 | // Model switch callout (ant-only, eliminated from external builds) |
| 2044 | if ("external" === 'ant' && allowDialogsWithAnimation && showModelSwitchCallout) return 'model-switch'; |
| 2045 | |
| 2046 | // Undercover auto-enable explainer (ant-only, eliminated from external builds) |
| 2047 | if ("external" === 'ant' && allowDialogsWithAnimation && showUndercoverCallout) return 'undercover-callout'; |
| 2048 | |
| 2049 | // Effort callout (shown once for Opus 4.6 users when effort is enabled) |
| 2050 | if (allowDialogsWithAnimation && showEffortCallout) return 'effort-callout'; |
| 2051 | |
| 2052 | // Remote callout (shown once before first bridge enable) |
| 2053 | if (allowDialogsWithAnimation && showRemoteCallout) return 'remote-callout'; |
| 2054 | |
| 2055 | // LSP plugin recommendation (lowest priority - non-blocking suggestion) |
| 2056 | if (allowDialogsWithAnimation && lspRecommendation) return 'lsp-recommendation'; |
| 2057 | |
| 2058 | // Plugin hint from CLI/SDK stderr (same priority band as LSP rec) |
| 2059 | if (allowDialogsWithAnimation && hintRecommendation) return 'plugin-hint'; |
| 2060 | |
| 2061 | // Desktop app upsell (max 3 launches, lowest priority) |
| 2062 | if (allowDialogsWithAnimation && showDesktopUpsellStartup) return 'desktop-upsell'; |
| 2063 | return undefined; |
| 2064 | } |
| 2065 | const focusedInputDialog = getFocusedInputDialog(); |
| 2066 | |
| 2067 | // True when permission prompts exist but are hidden because the user is typing |