| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- """
- Reconstruct admin.html from JSONL conversation transcript.
- Only applies operations that succeeded (matched tool_result with no error).
- """
- import json
- import sys
- JSONL_PATH = r'C:/Users/Administrator/.claude/projects/h--lab-safety-monitor-exam-main-2026/369b78fb-8697-4ea6-b83e-eeb87cee0bba.jsonl'
- OUTPUT_PATH = r'H:/lab-safety-monitor/exam_main_2026/admin.html'
- # --- Pass 1: collect tool_use items for admin.html, keyed by tool_use_id ---
- tool_uses = {} # tool_use_id -> {'ts', 'name', 'input', 'order'}
- order = 0
- tool_results = {} # tool_use_id -> {'ts', 'is_error', 'content'}
- with open(JSONL_PATH, 'r', encoding='utf-8') as f:
- for raw_line in f:
- raw_line = raw_line.strip()
- if not raw_line:
- continue
- try:
- obj = json.loads(raw_line)
- except Exception:
- continue
- ts = obj.get('timestamp', '')
- msg = obj.get('message', {})
- if not isinstance(msg, dict):
- continue
- content = msg.get('content', [])
- if not isinstance(content, list):
- continue
- for item in content:
- if not isinstance(item, dict):
- continue
- if item.get('type') == 'tool_use':
- name = item.get('name', '')
- inp = item.get('input', {})
- fp = inp.get('file_path', '')
- if 'admin.html' in fp and name in ('Write', 'Edit'):
- tid = item.get('id', '')
- tool_uses[tid] = {
- 'ts': ts,
- 'name': name,
- 'input': inp,
- 'order': order,
- }
- order += 1
- elif item.get('type') == 'tool_result':
- tid = item.get('tool_use_id', '')
- is_error = item.get('is_error', False)
- tc = item.get('content', '')
- # Also check for error strings in content
- if isinstance(tc, list):
- tc_text = ' '.join(x.get('text', '') if isinstance(x, dict) else str(x) for x in tc)
- else:
- tc_text = str(tc)
- if '<tool_use_error>' in tc_text:
- is_error = True
- tool_results[tid] = {'ts': ts, 'is_error': is_error, 'content': tc_text}
- # Sort operations by original order
- ops = sorted(tool_uses.values(), key=lambda x: x['order'])
- print(f"Total admin.html operations: {len(ops)}")
- # Find the initial Write
- write_ops = [op for op in ops if op['name'] == 'Write']
- edit_ops = [op for op in ops if op['name'] == 'Edit']
- if not write_ops:
- print("ERROR: No Write operation found!")
- sys.exit(1)
- # Get the write that actually succeeded
- # Find tool_use_id for the write
- write_tid = None
- for tid, v in tool_uses.items():
- if v['name'] == 'Write' and 'admin.html' in v['input'].get('file_path', ''):
- r = tool_results.get(tid, {})
- if not r.get('is_error', True):
- write_tid = tid
- break
- if write_tid is None:
- print("WARNING: Write had no matching result, using it anyway")
- write_tid = [tid for tid, v in tool_uses.items() if v['name'] == 'Write'][0]
- file_content = tool_uses[write_tid]['input'].get('content', '')
- print(f"Initial Write content length: {len(file_content)}")
- # Apply edits in order, skipping failed ones
- skipped = 0
- applied = 0
- for tid, v in sorted([(tid, v) for tid, v in tool_uses.items() if v['name'] == 'Edit'],
- key=lambda x: x[1]['order']):
- result = tool_results.get(tid, {})
- if result.get('is_error', False):
- print(f" SKIP (original error): {v['ts']}")
- skipped += 1
- continue
- inp = v['input']
- old = inp.get('old_string', '')
- new = inp.get('new_string', '')
- replace_all = inp.get('replace_all', False)
- if replace_all:
- count = file_content.count(old)
- file_content = file_content.replace(old, new)
- print(f" replace_all {v['ts']}: {count} replacements, len={len(file_content)}")
- applied += 1
- else:
- count = file_content.count(old)
- if count == 0:
- print(f" WARNING not found: {v['ts']} old={repr(old[:80])}")
- # Still count as applied since original session said success
- elif count == 1:
- file_content = file_content.replace(old, new, 1)
- print(f" OK {v['ts']}: len={len(file_content)}")
- applied += 1
- else:
- # Multiple matches - replace first
- file_content = file_content.replace(old, new, 1)
- print(f" MULTI({count}) {v['ts']}: replaced first, len={len(file_content)}")
- applied += 1
- print(f"\nApplied: {applied}, Skipped: {skipped}")
- print(f"Final content length: {len(file_content)}")
- print(f"Final line count: {file_content.count(chr(10)) + 1}")
- with open(OUTPUT_PATH, 'w', encoding='utf-8') as f:
- f.write(file_content)
- print(f"\nWritten to: {OUTPUT_PATH}")
|