| import { normalizeNameForMCP } from '../../services/mcp/normalization.js' | |
| import { env } from '../env.js' | |
| export const COMPUTER_USE_MCP_SERVER_NAME = 'computer-use' | |
| /** | |
| * Sentinel bundle ID for the frontmost gate. Claude Code is a terminal β it has | |
| * no window. This never matches a real `NSWorkspace.frontmostApplication`, so | |
| * the package's "host is frontmost" branch (mouse click-through exemption, | |
| * keyboard safety-net) is dead code for us. `prepareForAction`'s "exempt our | |
| * own window" is likewise a no-op β there is no window to exempt. | |
| */ | |
| export const CLI_HOST_BUNDLE_ID = 'com.anthropic.claude-code.cli-no-window' | |
| /** | |
| * Fallback `env.terminal` β bundleId map for when `__CFBundleIdentifier` is | |
| * unset. Covers the macOS terminals we can distinguish β Linux entries | |
| * (konsole, gnome-terminal, xterm) are deliberately absent since | |
| * `createCliExecutor` is darwin-guarded. | |
| */ | |
| const TERMINAL_BUNDLE_ID_FALLBACK: Readonly<Record<string, string>> = { | |
| 'iTerm.app': 'com.googlecode.iterm2', | |
| Apple_Terminal: 'com.apple.Terminal', | |
| ghostty: 'com.mitchellh.ghostty', | |
| kitty: 'net.kovidgoyal.kitty', | |
| WarpTerminal: 'dev.warp.Warp-Stable', | |
| vscode: 'com.microsoft.VSCode', | |
| } | |
| /** | |
| * Bundle ID of the terminal emulator we're running inside, so `prepareDisplay` | |
| * can exempt it from hiding and `captureExcluding` can keep it out of | |
| * screenshots. Returns null when undetectable (ssh, cleared env, unknown | |
| * terminal) β caller must handle the null case. | |
| * | |
| * `__CFBundleIdentifier` is set by LaunchServices when a .app bundle spawns a | |
| * process and is inherited by children. It's the exact bundleId, no lookup | |
| * needed β handles terminals the fallback table doesn't know about. Under | |
| * tmux/screen it reflects the terminal that started the SERVER, which may | |
| * differ from the attached client. That's harmless here: we exempt A | |
| * terminal window, and the screenshots exclude it regardless. | |
| */ | |
| export function getTerminalBundleId(): string | null { | |
| const cfBundleId = process.env.__CFBundleIdentifier | |
| if (cfBundleId) return cfBundleId | |
| return TERMINAL_BUNDLE_ID_FALLBACK[env.terminal ?? ''] ?? null | |
| } | |
| /** | |
| * Static capabilities for macOS CLI. `hostBundleId` is not here β it's added | |
| * by `executor.ts` per `ComputerExecutor.capabilities`. `buildComputerUseTools` | |
| * takes this shape (no `hostBundleId`, no `teachMode`). | |
| */ | |
| export const CLI_CU_CAPABILITIES = { | |
| screenshotFiltering: 'native' as const, | |
| platform: 'darwin' as const, | |
| } | |
| export function isComputerUseMCPServer(name: string): boolean { | |
| return normalizeNameForMCP(name) === COMPUTER_USE_MCP_SERVER_NAME | |
| } | |