{"version":3,"file":"agent-log.d.ts","sourceRoot":"","sources":["../../src/core/agent-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AASH;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAE1D;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAS9C","sourcesContent":["/**\n * Sink for the agent's operational log lines — subagent dispatch, warm-worker\n * fallback, lifeguard kills. These describe what the agent is doing to its own\n * machinery, not what the user asked for.\n *\n * They used to go straight to `console.error`. stdout is reserved for the JSON\n * event stream, so stderr looked free — but when the interactive TUI owns the\n * screen it is not. The TUI is a differential renderer: it tracks the frame it\n * painted (`previousLines`) and repositions by *relative* row deltas from its\n * own bookkeeping (`hardwareCursorRow`). A write it did not make scrolls the\n * terminal underneath it, and every later partial repaint lands one row off —\n * the visible result being duplicated rows (two `Agent [explore]` lines for one\n * dispatch) plus fragments of the log line wedged into the transcript, which\n * survive until something forces a full repaint. The TUI cannot defend itself\n * here; it has no way to learn that another writer touched the terminal. So the\n * writer has to hold back.\n *\n * Hence: silent while a TUI is attached, unchanged everywhere else (`--print`,\n * RPC, CI), where these lines are the only trace of a dispatch and where\n * `docs/routing.md`'s `[DISPATCH] … depth=2 …` check still has to work.\n *\n * Nothing is lost in the interactive case. A dispatch is already on screen as\n * the `Agent [explore]` tool row and its task-panel row, and every field of the\n * `[DISPATCH]` line is persisted to `dispatch-log.json`; warm-worker and\n * inherited-model fallbacks already surface as a `⚠` note on the task row.\n * Set `HOOCODE_DEBUG_AGENT_LOG=1` to tee the suppressed lines to\n * `~/.hoocode/agent/hoocode-debug.log` (mirrors HOOCODE_DEBUG_REDRAW).\n */\n\nimport { appendFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n/** True once an interactive TUI owns the terminal (see InteractiveMode.start/stop). */\nlet ownedByTui = false;\n\n/**\n * Declare whether a TUI currently owns the terminal. Interactive mode sets this\n * around the UI's lifetime; every other run mode leaves it false.\n */\nexport function setTerminalOwnedByTui(owned: boolean): void {\n\townedByTui = owned;\n}\n\n/** Whether operational logging is currently being withheld from the terminal. */\nexport function isTerminalOwnedByTui(): boolean {\n\treturn ownedByTui;\n}\n\n/**\n * Emit one operational log line, unless a TUI owns the terminal.\n *\n * Callers must not assume this reaches anyone: it is diagnostics, not a user\n * surface. Anything a user needs to see belongs in the transcript or the task\n * panel.\n */\nexport function agentLog(message: string): void {\n\tif (ownedByTui) {\n\t\tdebugTee(message);\n\t\treturn;\n\t}\n\t// Straight to fd 2 rather than console.error: this is explicitly a write to\n\t// the terminal, and test/extension hosts that swap `console` out from under\n\t// us would otherwise hide exactly the behavior that matters here.\n\tprocess.stderr.write(`${message}\\n`);\n}\n\n/** Best-effort file tee for suppressed lines, off unless explicitly enabled. */\nfunction debugTee(message: string): void {\n\tif (process.env.HOOCODE_DEBUG_AGENT_LOG !== \"1\") return;\n\ttry {\n\t\tconst agentDir = process.env.HOOCODE_CODING_AGENT_DIR ?? join(homedir(), \".hoocode\", \"agent\");\n\t\tappendFileSync(join(agentDir, \"hoocode-debug.log\"), `[${new Date().toISOString()}] ${message}\\n`);\n\t} catch {\n\t\t// Diagnostics only — never let logging break a dispatch.\n\t}\n}\n"]}