11from __future__ import annotations
22
33import json
4+ import logging
45import os
56import sqlite3
67from datetime import datetime , timezone
78
9+ _logger = logging .getLogger (__name__ )
10+
811from utils .cli_chat_reader import list_cli_projects
912from utils .exclusion_rules import build_searchable_text , is_excluded_by_rules
1013from utils .path_helpers import (
1114 get_workspace_folder_paths ,
1215 normalize_file_path ,
1316 to_epoch_ms ,
17+ warn_workspace_json_read ,
1418)
1519from utils .workspace_descriptor import read_json_file
1620from utils .workspace_path import get_cli_chats_path
21+ from models import Composer , SchemaError
1722from services .workspace_db import (
1823 _build_composer_id_to_workspace_id ,
1924 _collect_invalid_workspace_ids ,
@@ -72,7 +77,32 @@ def _safe_fetchall(query: str, params: tuple = ()) -> list:
7277 for row in composer_rows :
7378 cid = row ["key" ].split (":" )[1 ]
7479 try :
75- cd = json .loads (row ["value" ])
80+ parsed = json .loads (row ["value" ])
81+ except (json .JSONDecodeError , TypeError , ValueError ) as e :
82+ _logger .warning (
83+ "Failed to decode Composer from composerData:%s: %s" ,
84+ cid ,
85+ e ,
86+ )
87+ continue
88+ if not isinstance (parsed , dict ):
89+ _logger .warning (
90+ "Failed to parse Composer from composerData:%s: expected object, got %s" ,
91+ cid ,
92+ type (parsed ).__name__ ,
93+ )
94+ continue
95+ try :
96+ composer = Composer .from_dict (parsed , composer_id = cid )
97+ except SchemaError as e :
98+ _logger .warning (
99+ "Failed to parse Composer from composerData:%s: %s" ,
100+ cid ,
101+ e ,
102+ )
103+ continue
104+ cd = composer .raw
105+ try :
76106 pid = _determine_project_for_conversation (
77107 cd , cid , project_layouts_map ,
78108 project_name_map , workspace_path_map ,
@@ -98,10 +128,14 @@ def _safe_fetchall(query: str, params: tuple = ()) -> list:
98128 "lastUpdatedAt" : to_epoch_ms (cd .get ("lastUpdatedAt" )) or to_epoch_ms (cd .get ("createdAt" )) or 0 ,
99129 "createdAt" : to_epoch_ms (cd .get ("createdAt" )) or 0 ,
100130 })
101- except Exception :
102- pass
131+ except Exception as e :
132+ _logger .warning (
133+ "Failed to process Composer from composerData:%s: %s" ,
134+ cid ,
135+ e ,
136+ )
103137 except Exception :
104- pass
138+ _logger . exception ( "Failed to load composer rows from global storage" )
105139
106140 # Group workspace entries by normalized folder path
107141 folder_to_entries : dict [str , list ] = {}
@@ -114,8 +148,8 @@ def _safe_fetchall(query: str, params: tuple = ()) -> list:
114148 first_folder = folders [0 ] if folders else None
115149 if first_folder :
116150 norm_folder = normalize_file_path (first_folder )
117- except Exception :
118- pass
151+ except Exception as e :
152+ warn_workspace_json_read ( _logger , entry [ "name" ], e )
119153 if not norm_folder :
120154 norm_folder = entry ["name" ] # fallback to workspace ID
121155 entry_folder_map [entry ["name" ]] = norm_folder
@@ -139,7 +173,12 @@ def _safe_fetchall(query: str, params: tuple = ()) -> list:
139173 for e in group
140174 if os .path .isfile (os .path .join (workspace_path , e ["name" ], "state.vscdb" ))
141175 )
142- except Exception :
176+ except Exception as e :
177+ _logger .warning (
178+ "Failed to resolve mtime for workspace folder %s: %s" ,
179+ norm_folder ,
180+ e ,
181+ )
143182 mtime = 0
144183
145184 workspace_name = _get_workspace_display_name (workspace_path , primary ["name" ])
@@ -238,7 +277,7 @@ def _safe_fetchall(query: str, params: tuple = ()) -> list:
238277 "source" : "cli" ,
239278 })
240279 except Exception as e :
241- print ( f "Failed to load CLI projects: { e } " )
280+ _logger . warning ( "Failed to load CLI projects: %s" , e )
242281
243282 projects .sort (key = lambda p : p ["lastModified" ], reverse = True )
244283 return projects
0 commit comments