import debug from "debug" export type LoggerNamespace = "sse" | "api" | "session" | "actions" | "solo" | "multix-chat" interface Logger { log: (...args: unknown[]) => void info: (...args: unknown[]) => void warn: (...args: unknown[]) => void error: (...args: unknown[]) => void } export interface NamespaceState { name: LoggerNamespace enabled: boolean } export interface LoggerControls { listLoggerNamespaces: () => NamespaceState[] enableLogger: (namespace: LoggerNamespace) => void disableLogger: (namespace: LoggerNamespace) => void enableAllLoggers: () => void disableAllLoggers: () => void } const KNOWN_NAMESPACES: LoggerNamespace[] = ["sse", "api", "session", "actions", "solo", "multix-chat"] const STORAGE_KEY = "opencode:logger:namespaces" const namespaceLoggers = new Map() const enabledNamespaces = new Set() const rawConsole = typeof globalThis !== "undefined" ? globalThis.console : undefined function applyEnabledNamespaces(): void { if (enabledNamespaces.size === 0) { debug.disable() } else { debug.enable(Array.from(enabledNamespaces).join(",")) } } function persistEnabledNamespaces(): void { if (typeof window === "undefined" || !window?.localStorage) return try { window.localStorage.setItem(STORAGE_KEY, JSON.stringify(Array.from(enabledNamespaces))) } catch (error) { rawConsole?.warn?.("Failed to persist logger namespaces", error) } } function hydrateNamespacesFromStorage(): void { if (typeof window === "undefined" || !window?.localStorage) return try { const stored = window.localStorage.getItem(STORAGE_KEY) if (!stored) return const parsed: unknown = JSON.parse(stored) if (!Array.isArray(parsed)) return for (const name of parsed) { if (KNOWN_NAMESPACES.includes(name as LoggerNamespace)) { enabledNamespaces.add(name as LoggerNamespace) } } } catch (error) { rawConsole?.warn?.("Failed to hydrate logger namespaces", error) } } hydrateNamespacesFromStorage() applyEnabledNamespaces() function buildLogger(namespace: LoggerNamespace): Logger { const base = debug(namespace) const baseLogger: (...args: any[]) => void = base const formatAndLog = (level: string, args: any[]) => { baseLogger(level, ...args) } return { log: (...args: any[]) => baseLogger(...args), info: (...args: any[]) => baseLogger(...args), warn: (...args: any[]) => formatAndLog("[warn]", args), error: (...args: any[]) => formatAndLog("[error]", args), } } function getLogger(namespace: string): Logger { const ns = namespace as LoggerNamespace if (!namespaceLoggers.has(ns)) { namespaceLoggers.set(ns, buildLogger(ns)) } return namespaceLoggers.get(ns)! } function listLoggerNamespaces(): NamespaceState[] { return Array.from(namespaceLoggers.keys()).map((name) => ({ name, enabled: enabledNamespaces.has(name) })) } function enableLogger(namespace: string): void { const ns = namespace as LoggerNamespace if (enabledNamespaces.has(ns)) return enabledNamespaces.add(ns) persistEnabledNamespaces() applyEnabledNamespaces() } function disableLogger(namespace: string): void { const ns = namespace as LoggerNamespace if (!enabledNamespaces.has(ns)) return enabledNamespaces.delete(ns) persistEnabledNamespaces() applyEnabledNamespaces() } function disableAllLoggers(): void { enabledNamespaces.clear() persistEnabledNamespaces() applyEnabledNamespaces() } function enableAllLoggers(): void { namespaceLoggers.forEach((_, ns) => enabledNamespaces.add(ns)) persistEnabledNamespaces() applyEnabledNamespaces() } const loggerControls: LoggerControls = { listLoggerNamespaces, enableLogger, disableLogger, enableAllLoggers, disableAllLoggers, } function exposeLoggerControls(): void { if (typeof window === "undefined") return window.codenomadLogger = loggerControls } exposeLoggerControls() export { getLogger, listLoggerNamespaces, enableLogger, disableLogger, enableAllLoggers, disableAllLoggers, }