chasm-cli 1.5.4

Universal chat session manager - harvest, merge, and analyze AI chat history from VS Code, Cursor, and other editors
Documentation
"""Inspect the session JSONL that fails to load."""
import json

path = r'C:\Users\adamm\AppData\Roaming\Code\User\workspaceStorage\5ec71800c69c79b96b06a37e38537907\chatSessions\6be29cba-331e-4aa4-bc58-659cc20f4800.jsonl'
with open(path, 'r', encoding='utf-8') as f:
    content = f.read()

lines = content.strip().split('\n')
print(f"Total lines: {len(lines)}")
print(f"Total bytes: {len(content)}")
print(f"Trailing newline: {content.endswith(chr(10))}")
print(f"Trailing whitespace: {repr(content[-20:])}")

for i, line in enumerate(lines):
    obj = json.loads(line)
    kind = obj.get('kind')
    print(f"\nLine {i}: kind={kind}, length={len(line)}")
    
    if kind == 0:
        v = obj['v']
        top_keys = sorted(v.keys())
        print(f"  Top-level keys: {top_keys}")
        print(f"  version: {v.get('version')}")
        print(f"  sessionId: {v.get('sessionId')}")
        print(f"  customTitle: {v.get('customTitle')}")
        print(f"  hasPendingEdits: {v.get('hasPendingEdits')}")
        print(f"  initialLocation: {v.get('initialLocation')}")
        print(f"  responderUsername: {v.get('responderUsername')}")
        print(f"  pendingRequests: {v.get('pendingRequests')}")
        print(f"  requests count: {len(v.get('requests', []))}")
        
        # Check inputState
        inp = v.get('inputState', {})
        print(f"  inputState keys: {sorted(inp.keys()) if inp else 'None'}")
        
        for j, req in enumerate(v.get('requests', [])):
            print(f"\n  Request {j}:")
            req_keys = sorted(req.keys())
            print(f"    Keys: {req_keys}")
            print(f"    requestId: {req.get('requestId')}")
            print(f"    responseId: {req.get('responseId')}")
            print(f"    agent.id: {req.get('agent', {}).get('id') if req.get('agent') else None}")
            print(f"    modelId: {req.get('modelId')}")
            print(f"    modelState: {req.get('modelState')}")
            print(f"    confirmation: {req.get('confirmation')}")
            print(f"    codeCitations: {req.get('codeCitations')}")
            print(f"    contentReferences: {req.get('contentReferences')}")
            print(f"    timestamp: {req.get('timestamp')}")
            print(f"    timeSpentWaiting: {req.get('timeSpentWaiting')}")
            
            # variableData
            vd = req.get('variableData')
            if vd:
                print(f"    variableData: {json.dumps(vd)[:200]}")
            
            # Message
            msg = req.get('message', {})
            if isinstance(msg, str):
                print(f"    message (string): {msg[:100]}...")
            elif isinstance(msg, dict):
                print(f"    message.text: {msg.get('text', '')[:100]}")
                parts = msg.get('parts', [])
                print(f"    message.parts count: {len(parts)}")
                for k, p in enumerate(parts):
                    p_keys = sorted(p.keys())
                    print(f"      Part {k}: kind={p.get('kind')}, keys={p_keys}")
                    if p.get('range') is None:
                        print(f"        *** MISSING RANGE ***")
                    else:
                        print(f"        range: {p.get('range')}")
                    if p.get('editorRange') is None:
                        print(f"        *** MISSING editorRange ***")
            
            # Response
            resp = req.get('response', [])
            print(f"    response parts count: {len(resp)}")
            for k, rp in enumerate(resp):
                rp_keys = sorted(rp.keys())
                rp_kind = rp.get('kind', '[none/markdown]')
                print(f"      Resp {k}: kind={rp_kind}, keys={rp_keys}")
                # Check URIs
                if 'uri' in rp:
                    uri = rp['uri']
                    if isinstance(uri, dict):
                        print(f"        uri.scheme: {uri.get('scheme')}")
                        print(f"        uri.path: {uri.get('path', '')[:80]}")
                        print(f"        uri keys: {sorted(uri.keys())}")
                    else:
                        print(f"        uri: {uri}")
                # Check edits
                if 'edits' in rp:
                    edits_outer = rp['edits']
                    print(f"        edits: {len(edits_outer)} groups")
                    for g, group in enumerate(edits_outer):
                        print(f"          group {g}: {len(group)} edits")
                        for e_idx, edit in enumerate(group):
                            if isinstance(edit, dict):
                                print(f"            edit {e_idx}: keys={sorted(edit.keys())}")
                # Check value (markdown content)
                if 'value' in rp:
                    val = rp['value']
                    if isinstance(val, str):
                        print(f"        value: {repr(val[:60])}")
    
    elif kind == 1:
        print(f"  Delta: keys={sorted(obj.keys())}")
        
    elif kind == 2:
        print(f"  Splice: {json.dumps(obj)[:300]}")

# Also check the other session
path2 = r'C:\Users\adamm\AppData\Roaming\Code\User\workspaceStorage\5ec71800c69c79b96b06a37e38537907\chatSessions\1aab540b-8230-44c5-b6c1-3248fa997cac.jsonl'
with open(path2, 'r', encoding='utf-8') as f:
    content2 = f.read()
lines2 = content2.strip().split('\n')
print(f"\n\n=== Second session: 1aab540b ===")
print(f"Total lines: {len(lines2)}")
print(f"Total bytes: {len(content2)}")
for i, line in enumerate(lines2):
    obj = json.loads(line)
    kind = obj.get('kind')
    print(f"Line {i}: kind={kind}, length={len(line)}")
    if kind == 0:
        v = obj['v']
        print(f"  keys: {sorted(v.keys())}")
        print(f"  version: {v.get('version')}")
        print(f"  requests: {len(v.get('requests', []))}")
    elif kind == 2:
        print(f"  splice: {json.dumps(obj)[:300]}")