feat(logs): Harden session restoration for legacy logs and offloaded data resolution

This commit is contained in:
2026-03-08 21:17:27 -04:00
parent 3489b3c4b8
commit bbe0209403

View File

@@ -821,13 +821,35 @@ class AppController:
log_path = Path(path) log_path = Path(path)
if log_path.is_dir(): if log_path.is_dir():
log_file = log_path / "comms.log" log_file = log_path / "comms.log"
session_dir = log_path
else: else:
log_file = log_path log_file = log_path
session_dir = log_path.parent
if not log_file.exists(): if not log_file.exists():
self._set_status(f"log file not found: {log_file}") self._set_status(f"log file not found: {log_file}")
return return
def _resolve_log_ref(content: Any, session_dir: Path) -> str:
if not content or not isinstance(content, str) or "[REF:" not in content:
return str(content) if content is not None else ""
pattern = r'\[REF:([^\]]+)\]'
def replace_ref(match):
ref_file = match.group(1)
paths_to_check = [
session_dir / "outputs" / ref_file,
session_dir / "scripts" / ref_file
]
for p in paths_to_check:
if p.exists():
try:
with open(p, "r", encoding="utf-8") as rf:
return rf.read()
except Exception:
return f"[ERROR READING REF: {ref_file}]"
return match.group(0)
return re.sub(pattern, replace_ref, content)
entries = [] entries = []
disc_entries = [] disc_entries = []
try: try:
@@ -838,35 +860,57 @@ class AppController:
try: try:
entry = json.loads(line) entry = json.loads(line)
entries.append(entry) entries.append(entry)
kind = entry.get("kind") kind = entry.get("kind", entry.get("type", ""))
payload = entry.get("payload", {}) payload = entry.get("payload", {})
ts = entry.get("ts", "") ts = entry.get("ts", "")
if kind == "history_add": if kind == "history_add":
content = payload.get("content", payload.get("text", payload.get("message", "")))
content = _resolve_log_ref(content, session_dir)
disc_entries.append({ disc_entries.append({
"role": payload.get("role", "AI"), "role": payload.get("role", "AI"),
"content": payload.get("content", ""), "content": content,
"collapsed": payload.get("collapsed", False), "collapsed": payload.get("collapsed", False),
"ts": ts "ts": ts
}) })
elif kind == "request": elif kind == "request":
content = payload.get("message", payload.get("content", payload.get("text", "")))
content = _resolve_log_ref(content, session_dir)
disc_entries.append({ disc_entries.append({
"role": "User", "role": "User",
"content": payload.get("message", ""), "content": content,
"collapsed": False, "collapsed": False,
"ts": ts "ts": ts
}) })
elif kind == "response": elif kind == "response":
text = payload.get("text", payload.get("content", payload.get("message", "")))
text = _resolve_log_ref(text, session_dir)
tool_calls = payload.get("tool_calls", [])
content = text
if tool_calls:
try:
tc_str = json.dumps(tool_calls, indent=1)
if content:
content += f"\n\n[TOOL CALLS]\n{tc_str}"
else:
content = f"[TOOL CALLS]\n{tc_str}"
except:
if content:
content += f"\n\n[TOOL CALLS PRESENT]"
else:
content = "[TOOL CALLS PRESENT]"
disc_entries.append({ disc_entries.append({
"role": "AI", "role": "AI",
"content": payload.get("text", ""), "content": content,
"collapsed": False, "collapsed": False,
"ts": ts "ts": ts
}) })
elif kind == "tool_result": elif kind == "tool_result":
output = payload.get("output", payload.get("content", ""))
output = _resolve_log_ref(output, session_dir)
disc_entries.append({ disc_entries.append({
"role": "Tool", "role": "Tool",
"content": f"[TOOL RESULT]\n{payload.get('output', '')}", "content": f"[TOOL RESULT]\n{output}",
"collapsed": True, "collapsed": True,
"ts": ts "ts": ts
}) })
@@ -879,7 +923,7 @@ class AppController:
self.prior_session_entries = entries self.prior_session_entries = entries
self.prior_disc_entries = disc_entries self.prior_disc_entries = disc_entries
self.is_viewing_prior_session = True self.is_viewing_prior_session = True
self._set_status(f"viewing prior session: {log_path.name} ({len(entries)} entries)") self._set_status(f"viewing prior session: {session_dir.name} ({len(entries)} entries)")
def cb_prune_logs(self) -> None: def cb_prune_logs(self) -> None:
"""Manually triggers the log pruning process with aggressive thresholds.""" """Manually triggers the log pruning process with aggressive thresholds."""