66import functools
77import logging
88import os
9- import sys
109from collections .abc import Callable
1110from pathlib import Path
1211from typing import TypeVar
1312
1413import typer
1514
16- from vectorless_code import __version__
17-
18- logger = logging .getLogger (__name__ )
19- from vectorless_code .daemon_client import DaemonStartError , is_daemon_running , start_daemon , stop_daemon
2015from vectorless_code .daemon .protocol import (
2116 DoctorCheckResult ,
2217 IndexingProgress ,
2318 ProjectStatusResponse ,
2419 SearchResponse ,
2520)
21+ from vectorless_code .daemon_client import (
22+ DaemonStartError ,
23+ is_daemon_running ,
24+ start_daemon ,
25+ stop_daemon ,
26+ )
2627from vectorless_code .settings import (
2728 add_to_gitignore ,
28- data_dir ,
2929 find_project_root ,
3030 load_user_settings ,
3131 normalize_path ,
3535 settings_path ,
3636)
3737
38+ logger = logging .getLogger (__name__ )
39+
3840app = typer .Typer (
3941 name = "vcc" ,
4042 help = "vectorless-code — Code-aware search and navigation engine." ,
@@ -203,7 +205,13 @@ async def _on_waiting_async() -> None:
203205
204206 try :
205207 client = DaemonClient ()
206- resp = asyncio .run (client .index (project_root , on_progress = _on_progress_async , on_waiting = _on_waiting_async ))
208+ resp = asyncio .run (
209+ client .index (
210+ project_root ,
211+ on_progress = _on_progress_async ,
212+ on_waiting = _on_waiting_async ,
213+ )
214+ )
207215 except RuntimeError as e :
208216 live .stop ()
209217 if isinstance (e , DaemonStartError ):
@@ -214,14 +222,14 @@ async def _on_waiting_async() -> None:
214222 if last_progress_line is not None :
215223 typer .echo (last_progress_line , err = True )
216224
217- if not resp .get (' success' , False ):
225+ if not resp .get (" success" , False ):
218226 typer .echo (f"Indexing failed: { resp .get ('message' , 'Unknown error' )} " , err = True )
219227 raise typer .Exit (code = 1 )
220228
221229 typer .echo (f"Files: { resp .get ('file_count' , 0 )} " )
222230 typer .echo (f"Lines: { resp .get ('total_lines' , 0 )} " )
223231 typer .echo (f"Size: { resp .get ('total_bytes' , 0 )} bytes" )
224- languages = resp .get (' languages' , {})
232+ languages = resp .get (" languages" , {})
225233 if languages :
226234 typer .echo ("Languages:" )
227235 for lang , count in sorted (languages .items (), key = lambda x : - x [1 ]):
@@ -253,14 +261,16 @@ async def _on_waiting_async() -> None:
253261 )
254262
255263 client = DaemonClient ()
256- resp = asyncio .run (client .search (
257- project_root = project_root ,
258- query = query ,
259- doc_ids = doc_ids ,
260- limit = limit ,
261- offset = offset ,
262- on_waiting = _on_waiting_async ,
263- ))
264+ resp = asyncio .run (
265+ client .search (
266+ project_root = project_root ,
267+ query = query ,
268+ doc_ids = doc_ids ,
269+ limit = limit ,
270+ offset = offset ,
271+ on_waiting = _on_waiting_async ,
272+ )
273+ )
264274
265275 return resp
266276
@@ -355,18 +365,18 @@ def status() -> None:
355365 try :
356366 client = DaemonClient ()
357367 resp = asyncio .run (client .project_status (project_root ))
358-
368+
359369 # Adapt dictionary response to ProjectStatusResponse or handle directly
360370 # Assuming the daemon returns a dict that can be unpacked or handled
361371 # If strict typing is needed, we might construct ProjectStatusResponse if fields match
362372 # For now, printing basic info based on typical status response
363-
364- if resp .get (' indexed' , False ):
373+
374+ if resp .get (" indexed" , False ):
365375 typer .echo ("Status: Indexed" )
366376 typer .echo (f"Files: { resp .get ('file_count' , 0 )} " )
367377 typer .echo (f"Nodes: { resp .get ('node_count' , 0 )} " )
368378 typer .echo (f"Size: { resp .get ('total_bytes' , 0 )} bytes" )
369- if ' last_modified' in resp :
379+ if " last_modified" in resp :
370380 typer .echo (f"Last modified: { resp ['last_modified' ]} " )
371381 else :
372382 typer .echo ("Status: Not indexed" )
@@ -411,10 +421,10 @@ def reset(
411421 raise typer .Exit (code = 0 )
412422
413423 # Remove project from daemon first
424+ # Note: The new daemon doesn't have a remove_project method
425+ # Projects are automatically unloaded when the daemon stops
414426 try :
415- from vectorless_code import client as _client
416-
417- _client .remove_project (str (project_root ))
427+ pass
418428 except (ConnectionRefusedError , OSError , RuntimeError ):
419429 pass
420430
@@ -482,66 +492,32 @@ def _ok_fail_tag(ok: bool) -> str:
482492@_catch_daemon_start_error
483493def doctor () -> None :
484494 """Check system health and report issues."""
485- from vectorless_code import client as _client
486- from vectorless_code .settings import load_user_settings as _load_user_settings
487-
488495 _print_section ("User Settings" )
489496 user_settings_path , _ = require_user_settings ()
490497 typer .echo (f" Settings: { user_settings_path } " )
491498
492499 _print_section ("Daemon" )
493- daemon_ok = False
494500 try :
495501 from vectorless_code .daemon_client import DaemonClient
502+
496503 client = DaemonClient ()
497504 st_dict = asyncio .run (client .daemon_status ())
498505 # Construct a simple object or access dict keys
499506 # Assuming st_dict has version, uptime_seconds, projects
500507 typer .echo (f" Version: { st_dict .get ('version' , 'unknown' )} " )
501508 typer .echo (f" Uptime: { st_dict .get ('uptime_seconds' , 0 ):.1f} s" )
502- projects = st_dict .get (' projects' , [])
509+ projects = st_dict .get (" projects" , [])
503510 typer .echo (f" Loaded projects: { len (projects )} " )
504- daemon_ok = True
505511 except Exception as e :
506512 _print_error (f"Cannot connect to daemon: { e } " )
507513
508- if daemon_ok :
509- try :
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 :
514- typer .echo (" Path mappings:" )
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 } " )
521- except Exception as e :
522- _print_error (f"Failed to get daemon env: { e } " )
523-
524514 project_root = find_project_root (Path .cwd ())
525515
526516 if project_root is not None :
527517 _print_section ("Project Settings" )
528518 ps_path = settings_path (project_root )
529519 typer .echo (f" Settings: { ps_path } " )
530520
531- if daemon_ok :
532- try :
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 (
539- project_root = str (project_root ),
540- on_result = _on_result_async ,
541- )
542- except Exception as e :
543- _print_error (f"Project checks failed: { e } " )
544-
545521 _print_section ("Log Files" )
546522 from vectorless_code .daemon_paths import daemon_log_path as _daemon_log_path
547523
@@ -557,10 +533,17 @@ def mcp() -> None:
557533 project_root = str (require_project_root ())
558534
559535 async def _run_mcp () -> None :
536+ from vectorless_code .daemon_client import DaemonClient
560537 from vectorless_code .server import create_mcp_server
561- from vectorless_code .client import _bg_index
562538
563- asyncio .create_task (_bg_index (project_root ))
539+ # The daemon handles auto-indexing through file watching
540+ # Just ensure the project is compiled
541+ client = DaemonClient ()
542+ try :
543+ await client .index (project_root )
544+ except Exception as e :
545+ logger .warning ("Failed to index project: %s" , e )
546+
564547 mcp_server = create_mcp_server (project_root )
565548 await mcp_server .run_stdio_async ()
566549
@@ -580,17 +563,17 @@ def daemon_status() -> None:
580563
581564 client = DaemonClient ()
582565 resp_dict = asyncio .run (client .daemon_status ())
583-
566+
584567 typer .echo (f"Daemon version: { resp_dict .get ('version' , 'unknown' )} " )
585568 typer .echo (f"Uptime: { resp_dict .get ('uptime_seconds' , 0 ):.1f} s" )
586- projects = resp_dict .get (' projects' , [])
569+ projects = resp_dict .get (" projects" , [])
587570 if projects :
588571 typer .echo ("Projects:" )
589572 for p in projects :
590573 # p might be dict or object
591574 if isinstance (p , dict ):
592- root = p .get (' project_root' , ' unknown' )
593- indexing = p .get (' indexing' , False )
575+ root = p .get (" project_root" , " unknown" )
576+ indexing = p .get (" indexing" , False )
594577 else :
595578 root = p .project_root
596579 indexing = p .indexing
@@ -604,7 +587,7 @@ def daemon_status() -> None:
604587@_catch_daemon_start_error
605588def daemon_restart () -> None :
606589 """Restart the daemon."""
607- from vectorless_code .client import _wait_for_daemon
590+ from vectorless_code .daemon_client import _wait_for_daemon
608591
609592 typer .echo ("Stopping daemon..." )
610593 stop_daemon ()
@@ -619,7 +602,6 @@ def daemon_restart() -> None:
619602def daemon_stop () -> None :
620603 """Stop the daemon."""
621604 from vectorless_code .daemon_paths import daemon_pid_path
622- from vectorless_code .client import is_daemon_running
623605
624606 pid_path = daemon_pid_path ()
625607 if not pid_path .exists () and not is_daemon_running ():
@@ -645,7 +627,7 @@ def daemon_stop() -> None:
645627@app .command ("run-daemon" , hidden = True )
646628def run_daemon_cmd () -> None :
647629 """Internal: run the daemon process."""
648- from vectorless_code .daemon import run_daemon
630+ from vectorless_code .daemon . server import run_daemon
649631
650632 run_daemon ()
651633
0 commit comments