Skip to content

Commit 1e63083

Browse files
committed
Enhance logging format in LocalSandboxSessionManager to markdown for improved readability
1 parent 4cbfd62 commit 1e63083

1 file changed

Lines changed: 111 additions & 5 deletions

File tree

predicators/agent_sdk/local_sandbox.py

Lines changed: 111 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ def _init_incremental_log(self, query: str) -> Optional[str]:
466466

467467
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
468468
filename = (f"local_sandbox_query_{self._query_count:03d}_"
469-
f"{timestamp}.json")
469+
f"{timestamp}.md")
470470
filepath = os.path.join(self._log_dir, filename)
471471
os.makedirs(self._log_dir, exist_ok=True)
472472

@@ -481,7 +481,113 @@ def _init_incremental_log(self, query: str) -> Optional[str]:
481481

482482
def _flush_log(self, filepath: str,
483483
response: List[Dict[str, Any]]) -> None:
484-
"""Rewrite log file with current accumulated response."""
485-
log_data = {**self._current_log_meta, "response": response}
486-
with open(filepath, "w") as f:
487-
json.dump(log_data, f, indent=2, default=str)
484+
"""Write current conversation state as markdown to the log file."""
485+
try:
486+
meta = self._current_log_meta
487+
lines: List[str] = []
488+
lines.append("# Local Sandbox Query\n")
489+
lines.append(f"- **Query:** {meta.get('query_number', '?')}")
490+
lines.append(f"- **Timestamp:** {meta.get('timestamp', '?')}")
491+
lines.append(f"- **Session:** {meta.get('session_id', '?')}")
492+
lines.append("")
493+
lines.append("## Prompt\n")
494+
lines.append(meta.get("query", ""))
495+
lines.append("\n")
496+
lines.append("## Conversation\n")
497+
turn_num = 0
498+
for entry in response:
499+
etype = entry.get("type", "")
500+
if etype == "assistant":
501+
turn_num += 1
502+
lines.append(f"### Turn {turn_num}\n")
503+
for block in entry.get("content", []):
504+
btype = block.get("type", "")
505+
if btype == "ThinkingBlock":
506+
thinking = block.get("thinking", "")
507+
if thinking:
508+
lines.append("*[thinking]*")
509+
for tline in thinking.splitlines():
510+
lines.append(f"> {tline}")
511+
lines.append("")
512+
elif btype == "text":
513+
lines.append(
514+
f"**Assistant:** "
515+
f"{block.get('text', '')}\n")
516+
elif btype == "tool_use":
517+
name = block.get("name", "?")
518+
tool_id = block.get("id", "")
519+
inp = block.get("input", {})
520+
lines.append(
521+
f"**Tool Call:** `{name}` "
522+
f"(id: `{tool_id}`)")
523+
lines.append("```json")
524+
lines.append(json.dumps(
525+
inp, indent=2, default=str))
526+
lines.append("```\n")
527+
else:
528+
lines.append(f"**{btype}:**")
529+
extra = {k: v for k, v in block.items()
530+
if k != "type" and v is not None}
531+
if extra:
532+
lines.append("```json")
533+
lines.append(json.dumps(
534+
extra, indent=2, default=str))
535+
lines.append("```")
536+
lines.append("")
537+
elif etype == "user":
538+
for block in entry.get("content", []):
539+
btype = block.get("type", "")
540+
if btype == "tool_result":
541+
tool_use_id = block.get("tool_use_id", "")
542+
content = block.get("content")
543+
is_error = block.get("is_error", False)
544+
label = ("Tool Error" if is_error
545+
else "Tool Result")
546+
lines.append(
547+
f"**{label}** "
548+
f"(tool_use_id: `{tool_use_id}`):")
549+
if isinstance(content, list):
550+
for item in content:
551+
if isinstance(item, dict):
552+
lines.append("```")
553+
lines.append(
554+
item.get("text", str(item)))
555+
lines.append("```")
556+
else:
557+
lines.append("```")
558+
lines.append(str(item))
559+
lines.append("```")
560+
elif content is not None:
561+
lines.append("```")
562+
lines.append(str(content))
563+
lines.append("```")
564+
lines.append("")
565+
elif btype == "text":
566+
lines.append(
567+
f"**User:** "
568+
f"{block.get('text', '')}\n")
569+
else:
570+
lines.append(f"**{btype}:**")
571+
extra = {k: v for k, v in block.items()
572+
if k != "type" and v is not None}
573+
if extra:
574+
lines.append("```json")
575+
lines.append(json.dumps(
576+
extra, indent=2, default=str))
577+
lines.append("```")
578+
lines.append("")
579+
elif etype == "result":
580+
turns = entry.get("num_turns", "?")
581+
cost = entry.get("total_cost_usd")
582+
cost_str = (f"${cost:.2f}" if cost is not None
583+
else "?")
584+
lines.append(
585+
f"---\n\n**Result:** "
586+
f"{turns} turns, {cost_str}\n")
587+
elif etype == "error":
588+
lines.append(
589+
f"**Error:** {entry.get('error', '')}\n")
590+
with open(filepath, "w") as lf:
591+
lf.write("\n".join(lines))
592+
except Exception:
593+
pass # Don't let logging errors break the agent

0 commit comments

Comments
 (0)