import { NOTIFY_ENV } from "./constants.ts"; import { sendCmuxNotification, isInsideTmux, isInsideZellij, wrapTmuxPassthrough } from "./mux.ts"; import { normalizeNotification, NotifyProtocol, type NotificationInput } from "./notify-protocol.ts"; import { sendDesktopNotification } from "./desktop-notify.ts"; import { formatNotification } from "./osc99.ts"; import { detectTerminal, type TerminalCapabilities } from "./terminal-detect.ts"; import { createRuntime, type Runtime } from "./runtime.ts"; export interface SendOptions { runtime?: Runtime; terminal?: TerminalCapabilities; } function globallySuppressed(runtime: Runtime): boolean { return runtime.env[NOTIFY_ENV.global] !== undefined && /^(?:off|0|false)$/iu.test(runtime.env[NOTIFY_ENV.global]!.trim()); } export function isNotificationSuppressed(runtime: Runtime = createRuntime()): boolean { return globallySuppressed(runtime); } function richOsc99(runtime: Runtime): boolean { return runtime.env[NOTIFY_ENV.osc99Rich]?.trim() === "1"; } export function sendNotification(input: unknown, options: SendOptions = {}): void { const runtime = options.runtime ?? createRuntime(); try { if (isNotificationSuppressed(runtime) || !runtime.stdoutIsTTY) return; const notification = normalizeNotification(input); if (!notification) return; if (sendCmuxNotification(notification, runtime)) return; const terminal = options.terminal ?? detectTerminal(runtime.env, undefined, () => runtime.readFileSync("/proc/version")); const formatted = formatNotification(notification, terminal.protocol, richOsc99(runtime)); let output = formatted; if (terminal.protocol !== NotifyProtocol.Bell && terminal.insideTmux) output = `${wrapTmuxPassthrough(formatted)}\x07`; else if (terminal.protocol !== NotifyProtocol.Bell && terminal.insideZellij) output = `${formatted}\x07`; runtime.writeStdout(output); if (terminal.protocol === NotifyProtocol.Bell) sendDesktopNotification(notification, runtime, terminal.protocol); } catch { // Notification delivery is strictly best-effort. } }