{"version":3,"file":"open-url.d.ts","sourceRoot":"","sources":["../../src/utils/open-url.ts"],"names":[],"mappings":"AAaA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAMlD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAgBzC","sourcesContent":["import { spawn } from \"node:child_process\";\n\n/**\n * Schemes a click may hand to the desktop.\n *\n * An allowlist rather than a denylist, because the desktop's URL handlers are\n * not a closed set: a machine can have a handler registered for very nearly\n * anything, and a transcript is full of text the model wrote. Anything outside\n * this list is a URL the user can still select and open themselves — it is just\n * not something one click does on their behalf.\n */\nconst OPENABLE_SCHEMES = new Set([\"http:\", \"https:\", \"mailto:\"]);\n\n/**\n * Whether `url` is something we are willing to hand to the desktop.\n *\n * Exported for the same reason it exists: the check has to be identical\n * everywhere, and a second hand-written copy of it is how an allowlist stops\n * being one.\n */\nexport function isOpenableUrl(url: string): boolean {\n\ttry {\n\t\treturn OPENABLE_SCHEMES.has(new URL(url).protocol);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Open a URL in the desktop's default handler.\n *\n * No shell, anywhere. The URL comes from a line of the transcript, which is\n * text a model wrote, and `exec(\"open \" + url)` hands that to `sh` — a URL with\n * a quote and a semicolon in it would be a command. Every platform gets the\n * argument as an argument. Windows is the awkward one: `start` is a `cmd`\n * builtin rather than a program, and its first quoted argument is the window\n * title, which is why the empty string is there.\n *\n * Detached and with stdio ignored: the handler is a GUI program that outlives\n * this process, and a live pipe to it would hold the TUI's terminal.\n */\nexport function openUrl(url: string): void {\n\tif (!isOpenableUrl(url)) return;\n\tconst [command, args] =\n\t\tprocess.platform === \"darwin\"\n\t\t\t? [\"open\", [url]]\n\t\t\t: process.platform === \"win32\"\n\t\t\t\t? [\"cmd\", [\"/c\", \"start\", \"\", url]]\n\t\t\t\t: [\"xdg-open\", [url]];\n\ttry {\n\t\tconst child = spawn(command, args as string[], { detached: true, stdio: \"ignore\" });\n\t\t// A browser that is not installed must not take the session down with it.\n\t\tchild.on(\"error\", () => {});\n\t\tchild.unref();\n\t} catch {\n\t\t// Nothing to say: the URL is on screen and selectable either way.\n\t}\n}\n"]}