1414
1515from ...config import get_config
1616from ...core .llm import simple_call
17- from ..app import app , console , get_json_mode
17+ from ..app import app , console , get_study_path , is_agent_mode
18+ from ..study import StudyContext , detect_study_folder
19+ from ..utils import Output
1820
1921chat_app = typer .Typer (help = "Chat with simulated agents using DB-backed history" )
2022app .add_typer (chat_app , name = "chat" )
2123
2224
25+ def _get_study_db () -> Path :
26+ """Resolve study DB path via auto-detection or --study flag."""
27+ study_path = get_study_path ()
28+ detected = detect_study_folder (study_path )
29+ if detected is None :
30+ console .print (
31+ "[red]✗[/red] Not in a study folder. "
32+ "Use --study to specify or run from a study folder."
33+ )
34+ raise typer .Exit (1 )
35+ study_ctx = StudyContext (detected )
36+ if not study_ctx .db_path .exists ():
37+ console .print (f"[red]✗[/red] Study DB not found: { study_ctx .db_path } " )
38+ raise typer .Exit (1 )
39+ return study_ctx .db_path
40+
41+
2342def _now_iso () -> str :
2443 return datetime .now ().isoformat ()
2544
@@ -383,16 +402,14 @@ def _resolve_run_and_agent(
383402
384403@chat_app .command ("list" )
385404def chat_list (
386- study_db : Path = typer .Option (..., "--study-db" ),
387405 limit_runs : int = typer .Option (10 , "--limit-runs" , min = 1 , max = 100 ),
388406 agents_per_run : int = typer .Option (5 , "--agents-per-run" , min = 1 , max = 25 ),
389- json_output : bool = typer .Option (False , "--json" ),
390407):
391408 """List recent runs with sample agents for quick chat selection."""
392- if not study_db .exists ():
393- console .print (f"[red]✗[/red] Study DB not found: { study_db } " )
394- raise typer .Exit (1 )
409+ agent_mode = is_agent_mode ()
410+ out = Output (console , json_mode = agent_mode )
395411
412+ study_db = _get_study_db ()
396413 conn = sqlite3 .connect (str (study_db ))
397414 conn .row_factory = sqlite3 .Row
398415 try :
@@ -437,10 +454,11 @@ def chat_list(
437454 finally :
438455 conn .close ()
439456
440- payload = {"study_db" : str (study_db ), "runs" : runs }
441- if json_output or get_json_mode ():
442- console .print_json (data = payload )
443- return
457+ out .set_data ("study_db" , str (study_db ))
458+ out .set_data ("runs" , runs )
459+
460+ if agent_mode :
461+ raise typer .Exit (out .finish ())
444462
445463 if not runs :
446464 console .print ("[yellow]No simulation runs found.[/yellow]" )
@@ -457,27 +475,19 @@ def chat_list(
457475@chat_app .callback (invoke_without_command = True )
458476def chat_interactive (
459477 ctx : typer .Context ,
460- study_db : Path | None = typer .Option (None , "--study-db" ),
461478 run_id : str | None = typer .Option (None , "--run-id" ),
462479 agent_id : str | None = typer .Option (None , "--agent-id" ),
463480 session_id : str | None = typer .Option (None , "--session-id" ),
464481):
465482 """Interactive chat REPL.
466483
467484 Example:
468- extropy chat --study-db study.db -- run-id run_123 --agent-id a_42
485+ extropy chat --run-id run_123 --agent-id a_42
469486 """
470487 if ctx .invoked_subcommand is not None :
471488 return
472489
473- if not study_db :
474- console .print ("[red]✗[/red] interactive chat requires --study-db" )
475- raise typer .Exit (1 )
476-
477- if not study_db .exists ():
478- console .print (f"[red]✗[/red] Study DB not found: { study_db } " )
479- raise typer .Exit (1 )
480-
490+ study_db = _get_study_db ()
481491 conn = sqlite3 .connect (str (study_db ))
482492 conn .row_factory = sqlite3 .Row
483493 try :
@@ -579,22 +589,20 @@ def chat_interactive(
579589
580590@chat_app .command ("ask" )
581591def chat_ask (
582- study_db : Path = typer .Option (..., "--study-db" ),
583592 run_id : str | None = typer .Option (None , "--run-id" ),
584593 agent_id : str | None = typer .Option (None , "--agent-id" ),
585594 prompt : str = typer .Option (..., "--prompt" ),
586595 session_id : str | None = typer .Option (None , "--session-id" ),
587- json_output : bool = typer .Option (False , "--json" ),
588596):
589597 """Non-interactive chat API for automation.
590598
591599 Example:
592- extropy chat ask --study-db study.db -- run-id r1 --agent-id a1 --prompt "What changed?" --json
600+ extropy chat ask --run-id r1 --agent-id a1 --prompt "What changed?"
593601 """
594- if not study_db .exists ():
595- console .print (f"[red]✗[/red] Study DB not found: { study_db } " )
596- raise typer .Exit (1 )
602+ agent_mode = is_agent_mode ()
603+ out = Output (console , json_mode = agent_mode )
597604
605+ study_db = _get_study_db ()
598606 started = time .time ()
599607 conn = sqlite3 .connect (str (study_db ))
600608 conn .row_factory = sqlite3 .Row
@@ -639,19 +647,17 @@ def chat_ask(
639647 finally :
640648 conn .close ()
641649
642- payload = {
643- "session_id" : sid ,
644- "run_id" : resolved_run_id ,
645- "agent_id" : resolved_agent_id ,
646- "user_turn_index" : user_turn ,
647- "turn_index" : assistant_turn ,
648- "assistant_text" : answer ,
649- "citations" : {"sources" : citations },
650- "token_usage" : {"input_tokens" : 0 , "output_tokens" : 0 },
651- "latency_ms" : latency_ms ,
652- }
650+ out .set_data ("session_id" , sid )
651+ out .set_data ("run_id" , resolved_run_id )
652+ out .set_data ("agent_id" , resolved_agent_id )
653+ out .set_data ("user_turn_index" , user_turn )
654+ out .set_data ("turn_index" , assistant_turn )
655+ out .set_data ("assistant_text" , answer )
656+ out .set_data ("citations" , {"sources" : citations })
657+ out .set_data ("token_usage" , {"input_tokens" : 0 , "output_tokens" : 0 })
658+ out .set_data ("latency_ms" , latency_ms )
653659
654- if json_output or get_json_mode () :
655- console . print_json ( data = payload )
656- else :
657- console .print (answer )
660+ if agent_mode :
661+ raise typer . Exit ( out . finish () )
662+
663+ console .print (answer )
0 commit comments