Import the pre-repair source tree as the history baseline. Runtime data (data/), virtualenvs, bytecode caches and logs are gitignored so local secrets and user state stay out of the repo.
79 lines
2.8 KiB
Python
79 lines
2.8 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""统一调试日志 + 调试器窗口控制协议(纯文件通信,与主窗口 UI 零耦合)
|
||
|
||
日志文件: data/debug_session.log (环境变量 HAOCODE_DEBUG_LOG 可覆盖)
|
||
控制文件: data/debug_window.cmd (环境变量 HAOCODE_DEBUG_CMD 可覆盖)
|
||
|
||
三方写入协议:
|
||
[USER] 用户在调试窗口输入框手输的观察情况
|
||
[AGENT] 代理(外部脚本/命令行)注入的指令与备注
|
||
[APP] 应用自身事件(上下文标签变化/usage/发送/完成/报错/压缩)
|
||
[SYS] 调试窗口自身的开关事件
|
||
|
||
行格式: [YYYY-MM-DD HH:MM:SS.mmm] [TAG] 内容
|
||
|
||
控制协议: 代理往 debug_window.cmd 写入 "show" 或 "hide"(一行),
|
||
app 侧 2s QTimer 轮询并消费(读完即删)。
|
||
"""
|
||
import os
|
||
import threading
|
||
import time
|
||
|
||
_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||
_DATA_DIR = os.path.join(_ROOT, "data")
|
||
|
||
DEBUG_LOG_PATH = (os.environ.get("HAOCODE_DEBUG_LOG")
|
||
or os.path.join(_DATA_DIR, "debug_session.log"))
|
||
DEBUG_CMD_PATH = (os.environ.get("HAOCODE_DEBUG_CMD")
|
||
or os.path.join(_DATA_DIR, "debug_window.cmd"))
|
||
|
||
_lock = threading.Lock()
|
||
|
||
|
||
def _stamp() -> str:
|
||
t = time.time()
|
||
return (f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(t))}"
|
||
f".{int(t * 1000) % 1000:03d}")
|
||
|
||
|
||
def debug_log(msg: str, tag: str = "APP") -> None:
|
||
"""线程安全追加一条日志(worker 线程亦可调用)。
|
||
静默吞掉一切异常——本模块绝不影响主流程。"""
|
||
try:
|
||
with _lock:
|
||
with open(DEBUG_LOG_PATH, "a", encoding="utf-8") as f:
|
||
f.write(f"[{_stamp()}] [{tag}] {msg}\n")
|
||
except Exception:
|
||
pass
|
||
|
||
|
||
def poll_debug_cmd():
|
||
"""消费控制文件,返回 'show' / 'hide' / None。由主线程 QTimer 周期调用。"""
|
||
try:
|
||
if os.path.exists(DEBUG_CMD_PATH):
|
||
with open(DEBUG_CMD_PATH, "r", encoding="utf-8") as f:
|
||
action = (f.read() or "").strip().lower()
|
||
try:
|
||
os.remove(DEBUG_CMD_PATH)
|
||
except Exception:
|
||
pass
|
||
if action in ("show", "hide"):
|
||
return action
|
||
except Exception:
|
||
pass
|
||
return None
|
||
|
||
|
||
def autostart_debug_window(cfg: dict) -> bool:
|
||
"""调试窗口随程序启动:cfg["debug_window_autostart"] 为 true(缺省也是 true)
|
||
时向控制文件写 "show",主窗口事件循环启动后 2s 轮询即开窗。
|
||
纯文件操作(不依赖 Qt),返回是否写入。"""
|
||
try:
|
||
if not bool(cfg.get("debug_window_autostart", True)):
|
||
return False
|
||
with open(DEBUG_CMD_PATH, "w", encoding="utf-8") as f:
|
||
f.write("show\n")
|
||
return True
|
||
except Exception:
|
||
return False
|