22
33from __future__ import annotations
44
5+ import asyncio
56import functools
67import logging
78import os
1516from vectorless_code import __version__
1617
1718logger = logging .getLogger (__name__ )
18- from vectorless_code .client import DaemonStartError , is_daemon_running , start_daemon , stop_daemon
19- from vectorless_code .protocol import (
19+ from vectorless_code .daemon_client import DaemonStartError , is_daemon_running , start_daemon , stop_daemon
20+ from vectorless_code .daemon . protocol import (
2021 DoctorCheckResult ,
2122 IndexingProgress ,
2223 ProjectStatusResponse ,
@@ -179,28 +180,30 @@ def _run_index_with_progress(project_root: str) -> None:
179180 from rich .live import Live
180181 from rich .spinner import Spinner
181182
182- from vectorless_code import client as _client
183+ from vectorless_code . daemon_client import DaemonClient
183184
184185 err_console = Console (stderr = True )
185186 last_progress_line : str | None = None
186187
187188 with Live (Spinner ("dots" , "Indexing..." ), console = err_console , transient = True ) as live :
188189
189- def _on_waiting () -> None :
190+ async def _on_progress_async (progress_data : dict ) -> None :
191+ nonlocal last_progress_line
192+ progress = IndexingProgress (** progress_data )
193+ last_progress_line = f"Indexing: { _format_progress (progress )} "
194+ live .update (Spinner ("dots" , last_progress_line ))
195+
196+ async def _on_waiting_async () -> None :
190197 live .update (
191198 Spinner (
192199 "dots" ,
193200 "Another indexing is ongoing, waiting for it to finish..." ,
194201 )
195202 )
196203
197- def _on_progress (progress : IndexingProgress ) -> None :
198- nonlocal last_progress_line
199- last_progress_line = f"Indexing: { _format_progress (progress )} "
200- live .update (Spinner ("dots" , last_progress_line ))
201-
202204 try :
203- resp = _client .index (project_root , on_progress = _on_progress , on_waiting = _on_waiting )
205+ client = DaemonClient ()
206+ resp = asyncio .run (client .index (project_root , on_progress = _on_progress_async , on_waiting = _on_waiting_async ))
204207 except RuntimeError as e :
205208 live .stop ()
206209 if isinstance (e , DaemonStartError ):
@@ -211,16 +214,17 @@ def _on_progress(progress: IndexingProgress) -> None:
211214 if last_progress_line is not None :
212215 typer .echo (last_progress_line , err = True )
213216
214- if not resp .success :
215- typer .echo (f"Indexing failed: { resp .message } " , err = True )
217+ if not resp .get ( ' success' , False ) :
218+ typer .echo (f"Indexing failed: { resp .get ( ' message' , 'Unknown error' ) } " , err = True )
216219 raise typer .Exit (code = 1 )
217220
218- typer .echo (f"Files: { resp .file_count } " )
219- typer .echo (f"Lines: { resp .total_lines } " )
220- typer .echo (f"Size: { resp .total_bytes } bytes" )
221- if resp .languages :
221+ typer .echo (f"Files: { resp .get ('file_count' , 0 )} " )
222+ typer .echo (f"Lines: { resp .get ('total_lines' , 0 )} " )
223+ typer .echo (f"Size: { resp .get ('total_bytes' , 0 )} bytes" )
224+ languages = resp .get ('languages' , {})
225+ if languages :
222226 typer .echo ("Languages:" )
223- for lang , count in sorted (resp . languages .items (), key = lambda x : - x [1 ]):
227+ for lang , count in sorted (languages .items (), key = lambda x : - x [1 ]):
224228 typer .echo (f" { lang } : { count } " )
225229
226230
@@ -230,32 +234,33 @@ def _search_with_wait_spinner(
230234 doc_ids : list [str ] | None = None ,
231235 limit : int = 5 ,
232236 offset : int = 0 ,
233- ) -> SearchResponse :
237+ ) -> dict :
234238 """Run search, showing a spinner if waiting for load-time indexing."""
235239 from rich .console import Console
236240 from rich .live import Live
237241 from rich .spinner import Spinner
238242
239- from vectorless_code import client as _client
243+ from vectorless_code . daemon_client import DaemonClient
240244
241245 err_console = Console (stderr = True )
242246
243247 with Live (Spinner ("dots" , "Searching..." ), console = err_console , transient = True ) as live :
244248
245- def _on_waiting () -> None :
249+ async def _on_waiting_async () -> None :
246250 live .update (
247251 Spinner ("dots" , "Waiting for indexing to complete..." ),
248252 refresh = True ,
249253 )
250254
251- resp = _client .search (
255+ client = DaemonClient ()
256+ resp = asyncio .run (client .search (
252257 project_root = project_root ,
253258 query = query ,
254259 doc_ids = doc_ids ,
255260 limit = limit ,
256261 offset = offset ,
257- on_waiting = _on_waiting ,
258- )
262+ on_waiting = _on_waiting_async ,
263+ ))
259264
260265 return resp
261266
@@ -308,8 +313,6 @@ def init() -> None:
308313@_catch_daemon_start_error
309314def compile_cmd () -> None :
310315 """Compile the codebase into a searchable index."""
311- from vectorless_code import client as _client
312-
313316 project_root = str (require_project_root ())
314317 logger .info ("Compiling project: %s" , project_root )
315318 print_project_header (project_root )
@@ -323,36 +326,57 @@ def ask(
323326 question : list [str ] = typer .Argument (..., help = "Question about the codebase" ),
324327) -> None :
325328 """Ask a question about the codebase."""
326- from vectorless_code import client as _client
327-
328329 project_root = str (require_project_root ())
329330 query_str = " " .join (question )
330331
331332 logger .info ("Querying project %s: %s" , project_root , query_str [:100 ])
332333 print_project_header (project_root )
333334
334- resp = _search_with_wait_spinner (
335+ resp_dict = _search_with_wait_spinner (
335336 project_root = project_root ,
336337 query = query_str ,
337338 limit = 10 ,
338339 )
339- print_search_results (resp )
340+ print_search_results (SearchResponse ( ** resp_dict ) )
340341
341342
342343@app .command ()
343344@_catch_daemon_start_error
344345def status () -> None :
345346 """Show compilation status and index statistics."""
346- from vectorless_code import client as _client
347+ from vectorless_code . daemon_client import DaemonClient
347348
348349 project_root_path = require_project_root ()
349350 project_root = str (project_root_path )
350351 print_project_header (project_root )
351352
352353 typer .echo (f"Settings: { settings_path (project_root_path )} " )
353354
354- st = _client .project_status (project_root )
355- print_index_stats (st )
355+ try :
356+ client = DaemonClient ()
357+ resp = asyncio .run (client .project_status (project_root ))
358+
359+ # Adapt dictionary response to ProjectStatusResponse or handle directly
360+ # Assuming the daemon returns a dict that can be unpacked or handled
361+ # If strict typing is needed, we might construct ProjectStatusResponse if fields match
362+ # For now, printing basic info based on typical status response
363+
364+ if resp .get ('indexed' , False ):
365+ typer .echo ("Status: Indexed" )
366+ typer .echo (f"Files: { resp .get ('file_count' , 0 )} " )
367+ typer .echo (f"Nodes: { resp .get ('node_count' , 0 )} " )
368+ typer .echo (f"Size: { resp .get ('total_bytes' , 0 )} bytes" )
369+ if 'last_modified' in resp :
370+ typer .echo (f"Last modified: { resp ['last_modified' ]} " )
371+ else :
372+ typer .echo ("Status: Not indexed" )
373+ typer .echo ("Run `vcc compile` to build the index." )
374+
375+ except RuntimeError as e :
376+ if isinstance (e , DaemonStartError ):
377+ raise
378+ typer .echo (f"Failed to get status: { e } " , err = True )
379+ raise typer .Exit (code = 1 )
356380
357381
358382@app .command ()
@@ -468,21 +492,32 @@ def doctor() -> None:
468492 _print_section ("Daemon" )
469493 daemon_ok = False
470494 try :
471- st = _client .daemon_status ()
472- typer .echo (f" Version: { st .version } " )
473- typer .echo (f" Uptime: { st .uptime_seconds :.1f} s" )
474- typer .echo (f" Loaded projects: { len (st .projects )} " )
495+ from vectorless_code .daemon_client import DaemonClient
496+ client = DaemonClient ()
497+ st_dict = asyncio .run (client .daemon_status ())
498+ # Construct a simple object or access dict keys
499+ # Assuming st_dict has version, uptime_seconds, projects
500+ typer .echo (f" Version: { st_dict .get ('version' , 'unknown' )} " )
501+ typer .echo (f" Uptime: { st_dict .get ('uptime_seconds' , 0 ):.1f} s" )
502+ projects = st_dict .get ('projects' , [])
503+ typer .echo (f" Loaded projects: { len (projects )} " )
475504 daemon_ok = True
476505 except Exception as e :
477506 _print_error (f"Cannot connect to daemon: { e } " )
478507
479508 if daemon_ok :
480509 try :
481- env_resp = _client .daemon_env ()
482- if env_resp .path_mappings :
510+ client = DaemonClient ()
511+ env_resp_dict = asyncio .run (client .daemon_env ())
512+ path_mappings = env_resp_dict .get ('path_mappings' , [])
513+ if path_mappings :
483514 typer .echo (" Path mappings:" )
484- for m in env_resp .path_mappings :
485- typer .echo (f" { m .source } → { m .target } " )
515+ for m in path_mappings :
516+ # m might be a dict or object depending on daemon protocol serialization
517+ if isinstance (m , dict ):
518+ typer .echo (f" { m .get ('source' )} → { m .get ('target' )} " )
519+ else :
520+ typer .echo (f" { m .source } → { m .target } " )
486521 except Exception as e :
487522 _print_error (f"Failed to get daemon env: { e } " )
488523
@@ -495,9 +530,14 @@ def doctor() -> None:
495530
496531 if daemon_ok :
497532 try :
498- _client .doctor (
533+ client = DaemonClient ()
534+
535+ async def _on_result_async (result_data : dict ) -> None :
536+ _print_doctor_result (DoctorCheckResult (** result_data ))
537+
538+ await client .doctor (
499539 project_root = str (project_root ),
500- on_result = _print_doctor_result ,
540+ on_result = _on_result_async ,
501541 )
502542 except Exception as e :
503543 _print_error (f"Project checks failed: { e } " )
@@ -536,16 +576,26 @@ async def _run_mcp() -> None:
536576@_catch_daemon_start_error
537577def daemon_status () -> None :
538578 """Show daemon status."""
539- from vectorless_code import client as _client
540-
541- resp = _client .daemon_status ()
542- typer .echo (f"Daemon version: { resp .version } " )
543- typer .echo (f"Uptime: { resp .uptime_seconds :.1f} s" )
544- if resp .projects :
579+ from vectorless_code .daemon_client import DaemonClient
580+
581+ client = DaemonClient ()
582+ resp_dict = asyncio .run (client .daemon_status ())
583+
584+ typer .echo (f"Daemon version: { resp_dict .get ('version' , 'unknown' )} " )
585+ typer .echo (f"Uptime: { resp_dict .get ('uptime_seconds' , 0 ):.1f} s" )
586+ projects = resp_dict .get ('projects' , [])
587+ if projects :
545588 typer .echo ("Projects:" )
546- for p in resp .projects :
547- state = "indexing" if p .indexing else "idle"
548- typer .echo (f" { p .project_root } [{ state } ]" )
589+ for p in projects :
590+ # p might be dict or object
591+ if isinstance (p , dict ):
592+ root = p .get ('project_root' , 'unknown' )
593+ indexing = p .get ('indexing' , False )
594+ else :
595+ root = p .project_root
596+ indexing = p .indexing
597+ state = "indexing" if indexing else "idle"
598+ typer .echo (f" { root } [{ state } ]" )
549599 else :
550600 typer .echo ("No projects loaded." )
551601
0 commit comments