Skip to content

Commit 05734e2

Browse files
committed
refactor: migrate ConsolePresenter to nl2sql_cli and enhance reporting features
- Moved ConsolePresenter from core to nl2sql_cli, streamlining the CLI reporting structure. - Introduced new methods for interactive status updates, task management, and enhanced error/warning messages. - Updated various command files to utilize the new ConsolePresenter methods for improved user feedback during operations. - Removed the old reporting module from the core package to reduce redundancy and improve maintainability.
1 parent 881fa9f commit 05734e2

12 files changed

Lines changed: 961 additions & 846 deletions

File tree

packages/cli/src/nl2sql_cli/commands/benchmark.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from nl2sql.datasources import DatasourceRegistry
55
from nl2sql.indexing.vector_store import VectorStore
66
from nl2sql.evaluation.evaluator import ModelEvaluator
7-
from nl2sql.reporting import ConsolePresenter
7+
from nl2sql_cli.reporting import ConsolePresenter
88
from nl2sql.runners.benchmark_runner import BenchmarkRunner
99
from nl2sql_cli.types import BenchmarkConfig
1010
from nl2sql_cli.common.decorators import handle_cli_errors

packages/cli/src/nl2sql_cli/commands/indexing.py

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import json
12
import sys
2-
from typing import Dict, Any
3+
from typing import Any, Dict
34
from nl2sql_cli.reporting import ConsolePresenter
45
from nl2sql.indexing.vector_store import VectorStore
56
from nl2sql.datasources import DatasourceRegistry
@@ -28,33 +29,89 @@ def run_indexing(
2829
orchestrator = IndexingOrchestrator(ctx)
2930
stats = []
3031
errors = []
32+
empty_stats = []
3133

3234
presenter.start_interactive_status("Clearing existing data...")
33-
orchestrator.clear_store()
35+
try:
36+
orchestrator.clear_store()
37+
except Exception as e:
38+
presenter.stop_interactive_status()
39+
presenter.print_error(f"Failed to clear existing data: {e}")
40+
sys.exit(1)
3441
presenter.stop_interactive_status()
3542
presenter.print_success("Cleared existing data.")
3643

37-
presenter.start_interactive_status("Indexing...")
38-
3944
for adapter in adapters:
4045
ds_id = adapter.datasource_id
4146

4247
try:
43-
with presenter.status_context(f"{ds_id}..."):
44-
schema_stats = orchestrator.index_datasource(adapter)
48+
task = presenter.start_task_line(f"Indexing {ds_id}...")
49+
schema_stats = orchestrator.index_datasource(adapter)
50+
if schema_stats:
4551
stats.append(schema_stats)
52+
else:
53+
empty_stats.append(ds_id)
54+
presenter.finish_task_line(task, f"{ds_id} indexed", success=True)
4655
except Exception as e:
56+
if "task" in locals():
57+
presenter.finish_task_line(task, f"{ds_id} failed", success=False)
4758
presenter.print_error(f"Failed to index {ds_id}: {e}")
4859
errors.append(
4960
{"datasource_id": ds_id, "error": str(e)}
5061
)
51-
52-
presenter.stop_interactive_status()
5362

5463
if errors:
55-
presenter.print_table(errors, "Indexing Errors")
64+
presenter.print_table(errors, "Indexing Errors", columns=["datasource_id", "error"])
5665

5766
if stats:
58-
presenter.print_table(stats, "Indexing Summary")
67+
summary_rows = []
68+
total_chunks = 0
69+
totals_by_type: Dict[str, int] = {}
70+
71+
for s in stats:
72+
ds_id = s.get("datasource_id", "unknown")
73+
schema_version = s.get("schema_version", "-")
74+
chunk_stats = {
75+
k: v for k, v in s.items()
76+
if k not in ("datasource_id", "schema_version")
77+
}
78+
ds_total = sum(v for v in chunk_stats.values() if isinstance(v, int))
79+
total_chunks += ds_total
80+
for key, val in chunk_stats.items():
81+
if isinstance(val, int):
82+
totals_by_type[key] = totals_by_type.get(key, 0) + val
83+
84+
summary_rows.append(
85+
{
86+
"datasource_id": ds_id,
87+
"schema_version": schema_version,
88+
"total_chunks": ds_total,
89+
"chunks": json.dumps(chunk_stats, separators=(",", ":")),
90+
}
91+
)
5992

60-
presenter.print_success("Indexing complete.")
93+
presenter.print_table(
94+
summary_rows,
95+
"Indexing Summary",
96+
columns=["datasource_id", "schema_version", "total_chunks", "chunks"],
97+
)
98+
99+
if totals_by_type:
100+
totals_str = ", ".join([f"{k}={v}" for k, v in sorted(totals_by_type.items())])
101+
presenter.print_info(f"Total chunks indexed: {total_chunks} ({totals_str})")
102+
103+
total_adapters = len(adapters)
104+
succeeded = len(stats)
105+
failed = len(errors)
106+
skipped = len(empty_stats)
107+
presenter.print_info(
108+
f"Datasources: total={total_adapters}, succeeded={succeeded}, failed={failed}, empty={skipped}"
109+
)
110+
111+
if empty_stats:
112+
presenter.print_warning(f"Datasources with empty stats: {', '.join(empty_stats)}")
113+
114+
if errors:
115+
presenter.print_warning("Indexing completed with errors.")
116+
else:
117+
presenter.print_success("Indexing complete.")

packages/cli/src/nl2sql_cli/commands/run.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from nl2sql.datasources import DatasourceRegistry
66
from nl2sql.llm import LLMRegistry
77
from nl2sql.indexing.vector_store import VectorStore
8-
from nl2sql.reporting import ConsolePresenter
8+
from nl2sql_cli.reporting import ConsolePresenter
99
from nl2sql.runners.pipeline_runner import PipelineRunner
1010
from nl2sql.common.settings import settings
1111
from nl2sql_cli.types import RunConfig
@@ -23,6 +23,8 @@ def run_pipeline(
2323

2424
presenter = ConsolePresenter()
2525
presenter.print_info(f"Query: {config.query}")
26+
if config.no_exec:
27+
presenter.print_warning("Execution disabled (no_exec). Only SQL/plan output will be shown.")
2628

2729
# Instantiate Runner
2830
runner = PipelineRunner(ctx)
@@ -111,13 +113,30 @@ def run_pipeline(
111113
if errors:
112114
presenter.print_pipeline_errors(errors)
113115

116+
warnings = final_state.get("warnings") or []
117+
for warning in warnings:
118+
if isinstance(warning, dict):
119+
presenter.print_warning(json.dumps(warning, default=str))
120+
else:
121+
presenter.print_warning(str(warning))
122+
123+
answer_payload = None
124+
answer_synth = final_state.get("answer_synthesizer_response")
125+
if answer_synth:
126+
if isinstance(answer_synth, dict):
127+
answer_payload = answer_synth.get("final_answer")
128+
else:
129+
answer_payload = getattr(answer_synth, "final_answer", None)
130+
if isinstance(answer_payload, dict) and answer_payload:
131+
presenter.print_answer_synthesizer_output(answer_payload)
132+
114133
final_answer = final_state.get("final_answer")
115-
if type(final_answer) == str and final_answer:
134+
if isinstance(final_answer, dict) and final_answer:
135+
presenter.print_answer_synthesizer_output(final_answer)
136+
elif type(final_answer) == str and final_answer:
116137
presenter.print_final_answer(final_answer)
117138
elif type(final_answer) == list and final_answer:
118139
presenter.print_execution_result(final_answer)
119-
else:
120-
return
121140

122141
execution = final_state.get("execution")
123142
if execution:

packages/cli/src/nl2sql_cli/commands/visualize.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import List, Dict, Any
22
from langgraph.graph.state import CompiledStateGraph
3-
from nl2sql.reporting import ConsolePresenter
3+
from nl2sql_cli.reporting import ConsolePresenter
44

55
from nl2sql_cli.common.decorators import handle_cli_errors
66

0 commit comments

Comments
 (0)