{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,MAAM,WAAW,aAAa;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAaD,0DAA0D;AAC1D,wBAAgB,IAAI,IAAI,OAAO,CAI9B;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAkBnD","sourcesContent":["/**\n * Terminal notifications.\n *\n * Two surfaces:\n *\n *   1. `bell()` — emits a single `\\x07` BEL byte. Most modern terminals also\n *      generate a desktop notification when configured to.\n *   2. `notify({title, body})` — emits OSC 9 (iTerm2/Terminal.app) and OSC 777\n *      (urxvt/notify protocol). Falls back to writing the title to stderr\n *      when the terminal does not support either.\n *\n * Reference: claude-code ink/useTerminalNotification.ts:1.\n *\n * Notes:\n *   - We do not shell out to `osascript`/`terminal-notifier`. Doing so requires\n *     macOS-specific binaries and a permission grant. OSC 9 reaches every\n *     well-behaved modern terminal (iTerm2, WezTerm, Alacritty, kitty,\n *     Terminal.app), so it's the lowest-overhead path.\n *   - OSC sequences are silently ignored by terminals that don't understand\n *     them, so emitting both is safe.\n */\n\nimport { isatty } from \"node:tty\";\n\nexport interface NotifyOptions {\n\ttitle?: string;\n\tbody: string;\n\t/** Emit a BEL alongside the OSC notification. Default: true. */\n\tbell?: boolean;\n}\n\nfunction writeToStream(data: string): void {\n\ttry {\n\t\t// Prefer stderr because stdout may be piped/captured.\n\t\tif (process.stderr?.writable) {\n\t\t\tprocess.stderr.write(data);\n\t\t}\n\t} catch {\n\t\t/* swallow — terminal write must never throw */\n\t}\n}\n\n/** Single bell. Returns false when stderr isn't a TTY. */\nexport function bell(): boolean {\n\tif (!process.stderr || !isatty(process.stderr.fd)) return false;\n\twriteToStream(\"\\x07\");\n\treturn true;\n}\n\n/**\n * Send a desktop notification. Returns false when stderr isn't a TTY (so the\n * caller can fall back to a log line).\n */\nexport function notify(opts: NotifyOptions): boolean {\n\tif (!process.stderr || !isatty(process.stderr.fd)) {\n\t\t// Best-effort: write a single human-readable line so CI logs still\n\t\t// surface the alert text.\n\t\twriteToStream(`[notify] ${opts.title ? `${opts.title}: ` : \"\"}${opts.body}\\n`);\n\t\treturn false;\n\t}\n\n\tconst text = opts.title ? `${opts.title}: ${opts.body}` : opts.body;\n\tconst safe = text.replace(/[\\x00-\\x08\\x0b-\\x1f\\x7f]/g, \" \").slice(0, 256);\n\n\t// OSC 9 — iTerm2 / Terminal.app / WezTerm / Alacritty.\n\twriteToStream(`\\x1b]9;${safe}\\x07`);\n\t// OSC 777;notify — urxvt + notify protocol.\n\twriteToStream(`\\x1b]777;notify;${opts.title ?? \"cave\"};${safe}\\x07`);\n\n\tif (opts.bell !== false) bell();\n\treturn true;\n}\n"]}