feat(logs): Harden session restoration for legacy logs and offloaded data resolution
This commit is contained in:
@@ -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."""
|
||||||
|
|||||||
Reference in New Issue
Block a user