chasm-cli 1.5.4

Universal chat session manager - harvest, merge, and analyze AI chat history from VS Code, Cursor, and other editors
Documentation
import sqlite3, json, os, base64

WS_STORAGE = r"C:\Users\adamm\AppData\Roaming\Code\User\workspaceStorage"
BROKEN_HASH = "5ec71800c69c79b96b06a37e38537907"

def get_db_value(ws_hash, key):
    db_path = os.path.join(WS_STORAGE, ws_hash, "state.vscdb")
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    cursor.execute("SELECT value FROM ItemTable WHERE key = ?", (key,))
    row = cursor.fetchone()
    conn.close()
    return row[0] if row else None

print("=== BROKEN WORKSPACE (Agentic) ===\n")

# Session index
raw = get_db_value(BROKEN_HASH, "chat.ChatSessionStore.index")
if raw:
    data = json.loads(raw)
    print(f"chat.ChatSessionStore.index: {len(data)} entries")
    for entry in data:
        sid = entry.get("sessionId", "unknown")
        active = entry.get("isActive")
        print(f"  sessionId={sid}, isActive={active}")
        for k, v in entry.items():
            if k not in ("sessionId", "isActive"):
                print(f"    {k}={str(v)[:100]}")
else:
    print("NO session index!")

# Model cache
raw = get_db_value(BROKEN_HASH, "agentSessions.model.cache")
if raw:
    data = json.loads(raw)
    print(f"\nagentSessions.model.cache: {len(data)} entries")
    for i, entry in enumerate(data):
        resource = entry.get("resource", "unknown")
        label = entry.get("label", "unknown")
        print(f"  [{i}] label='{label}', resource='{resource}'")
        
        # Decode the base64 session ID from the resource URI
        if "vscode-chat-session://" in resource:
            b64part = resource.split("/")[-1]
            try:
                decoded = base64.b64decode(b64part).decode('utf-8')
                print(f"       decoded sessionId: {decoded}")
            except:
                print(f"       (could not decode b64)")
        
        for k, v in entry.items():
            if k not in ("resource", "label"):
                print(f"       {k}={json.dumps(v)[:200]}")
else:
    print("\nNO model cache!")

# Check session files
sessions_dir = os.path.join(WS_STORAGE, BROKEN_HASH, "chatSessions")
if os.path.isdir(sessions_dir):
    files = [f for f in os.listdir(sessions_dir) if f.endswith('.jsonl')]
    print(f"\nchatSessions/ files: {len(files)}")
    for f in sorted(files):
        fpath = os.path.join(sessions_dir, f)
        size = os.path.getsize(fpath)
        sid = f.replace('.jsonl', '')
        
        with open(fpath, 'r', encoding='utf-8') as fp:
            content = fp.read()
        
        decoder = json.JSONDecoder()
        try:
            obj, _ = decoder.raw_decode(content.strip())
            v = obj.get("v", {})
            reqs = v.get("requests", [])
            title = v.get("customTitle", "no title")
            version = v.get("version", "?")
            
            # Check each request's message format
            for ridx, req in enumerate(reqs):
                msg = req.get("message")
                if isinstance(msg, dict):
                    parts = msg.get("parts", [])
                    for pidx, part in enumerate(parts):
                        if isinstance(part, dict):
                            rng = part.get("range")
                            kind = part.get("kind")
                            if rng is None:
                                print(f"  {sid}: {size}b, v{version}, {len(reqs)} reqs, title='{title}'")
                                print(f"    !! REQ[{ridx}].msg.parts[{pidx}] ({kind}): range=null!")
                            elif isinstance(rng, dict) and "start" not in rng:
                                print(f"  {sid}: {size}b, v{version}, {len(reqs)} reqs, title='{title}'")
                                print(f"    !! REQ[{ridx}].msg.parts[{pidx}] ({kind}): range has no start! keys={list(rng.keys())}")
                
                # Check response parts for range issues
                resp = req.get("response", [])
                if isinstance(resp, list):
                    for pidx, rpart in enumerate(resp):
                        if isinstance(rpart, dict):
                            val = rpart.get("value")
                            if isinstance(val, dict):
                                uri = val.get("uri")
                                if isinstance(uri, dict):
                                    scheme = uri.get("scheme", "")
                                    ext = uri.get("external", "")
                                    if ext and ":" in ext:
                                        uri_scheme = ext.split(":")[0]
                                        import re
                                        if not re.match(r'^[a-zA-Z][a-zA-Z0-9+.\-]*$', uri_scheme):
                                            print(f"    !! REQ[{ridx}].resp[{pidx}].value.uri: bad scheme '{uri_scheme}'")
            
            print(f"  {sid}: {size}b, v{version}, {len(reqs)} reqs, title='{title}' - OK")
        except Exception as e:
            print(f"  {sid}: {size}b, PARSE ERROR: {e}")

# Check pending requests in model cache sessions vs JSONL
print("\n\n=== CHECKING PENDING REQUESTS ===")
raw = get_db_value(BROKEN_HASH, "chat.ChatSessionStore.index")
if raw:
    index = json.loads(raw)
    for entry in index:
        sid = entry.get("sessionId")
        if not sid:
            continue
        fpath = os.path.join(sessions_dir, f"{sid}.jsonl")
        if os.path.exists(fpath):
            with open(fpath, 'r', encoding='utf-8') as fp:
                content = fp.read()
            decoder = json.JSONDecoder()
            obj, _ = decoder.raw_decode(content.strip())
            v = obj.get("v", {})
            pending = v.get("pendingRequests", [])
            if pending:
                print(f"  {sid}: HAS {len(pending)} pending requests!")
                print(f"    First pending: {json.dumps(pending[0])[:200]}")
        else:
            print(f"  {sid}: file NOT FOUND on disk!")