dbagent-cli 0.8.3__tar.gz → 0.8.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/PKG-INFO +1 -1
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/__init__.py +1 -1
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/ui/console.py +54 -19
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent_cli.egg-info/PKG-INFO +1 -1
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/pyproject.toml +1 -1
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/README.md +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/agent/confidence.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/agent/conversation.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/agent/doctor.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/agent/error_classifier.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/agent/generator.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/agent/pipeline.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/agent/recommender.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/agent/validator.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/cli.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/config.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/connectors/base.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/connectors/factory.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/connectors/mongo.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/connectors/relational.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/execution/__init__.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/execution/cache.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/execution/changeset.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/execution/cost.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/execution/recovery.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/execution/sandbox.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/execution/streaming.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/llm/anthropic_provider.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/llm/auto_setup.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/llm/base.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/llm/deepseek_provider.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/llm/factory.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/llm/gemini_provider.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/llm/groq_provider.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/llm/mistral_provider.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/llm/mock_provider.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/llm/ollama_provider.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/llm/openai_provider.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/llm/openrouter_provider.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/schema/cache.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/schema/formatter.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/schema/graph.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/schema/models.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/schema/retriever.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/schema/selector.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/security/__init__.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/security/audit.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/security/environment.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/security/masking.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/security/modes.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/security/rbac.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/semantic/__init__.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/semantic/dictionary.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/semantic/templates.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/sql/__init__.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/sql/optimizer.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/sql/validator.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/ui/chat_screen.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/ui/grid_window.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/ui/viewer.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent/ui/visualizer.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent_cli.egg-info/SOURCES.txt +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent_cli.egg-info/dependency_links.txt +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent_cli.egg-info/entry_points.txt +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent_cli.egg-info/requires.txt +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/dbagent_cli.egg-info/top_level.txt +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/setup.cfg +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/tests/test_cache.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/tests/test_cli.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/tests/test_connectors.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/tests/test_direct_sql.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/tests/test_doctor_and_viz.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/tests/test_generator.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/tests/test_graph.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/tests/test_providers.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/tests/test_recovery.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/tests/test_safety.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/tests/test_sandbox.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/tests/test_schema.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/tests/test_security.py +0 -0
- {dbagent_cli-0.8.3 → dbagent_cli-0.8.4}/tests/test_semantic.py +0 -0
|
@@ -81,16 +81,18 @@ def print_results_table(
|
|
|
81
81
|
col_page: int = 1,
|
|
82
82
|
cols_per_page: Optional[int] = None,
|
|
83
83
|
show_all: bool = False,
|
|
84
|
+
max_rows_display: int = 15,
|
|
84
85
|
) -> None:
|
|
85
86
|
"""
|
|
86
87
|
Print query results in a clean, readable Rich table.
|
|
87
|
-
Dynamically scales column count
|
|
88
|
+
Dynamically scales column count and limits vertical rows to fit viewport.
|
|
88
89
|
"""
|
|
89
90
|
if not columns or not rows:
|
|
90
91
|
console.print("[dim]Query returned 0 rows.[/dim]\n")
|
|
91
92
|
return
|
|
92
93
|
|
|
93
94
|
total_cols = len(columns)
|
|
95
|
+
total_rows = len(rows)
|
|
94
96
|
term_width = console.width or 120
|
|
95
97
|
auto_cols = max(8, term_width // 16)
|
|
96
98
|
|
|
@@ -110,12 +112,14 @@ def print_results_table(
|
|
|
110
112
|
if total_pages > 1 and not show_all:
|
|
111
113
|
tbl_title += f" [dim](Cols {start_idx + 1}–{end_idx} of {total_cols} | Page {current_page}/{total_pages})[/dim]"
|
|
112
114
|
|
|
113
|
-
table = Table(title=tbl_title, show_header=True, header_style="bold
|
|
115
|
+
table = Table(title=tbl_title, show_header=True, header_style="bold cyan", border_style="dim")
|
|
114
116
|
|
|
115
117
|
for col in display_cols:
|
|
116
118
|
table.add_column(str(col), overflow="ellipsis", max_width=35)
|
|
117
119
|
|
|
118
|
-
|
|
120
|
+
display_rows = rows if (show_all or total_rows <= max_rows_display) else rows[:max_rows_display]
|
|
121
|
+
|
|
122
|
+
for row in display_rows:
|
|
119
123
|
row_vals = []
|
|
120
124
|
for col in display_cols:
|
|
121
125
|
v = row.get(col)
|
|
@@ -128,11 +132,17 @@ def print_results_table(
|
|
|
128
132
|
console.print("")
|
|
129
133
|
console.print(table)
|
|
130
134
|
|
|
135
|
+
footer_items = []
|
|
136
|
+
if total_rows > max_rows_display and not show_all:
|
|
137
|
+
footer_items.append(f"[bold green]Showing {len(display_rows)} of {total_rows} rows[/bold green]")
|
|
138
|
+
footer_items.append("[dim]⚡ Type [bold white]:scroll[/bold white] for scroller · [bold white]:all[/bold white] to show all · [bold white]:window[/bold white] for GUI[/dim]")
|
|
139
|
+
else:
|
|
140
|
+
footer_items.append(f"[bold green]Total rows:[/bold green] {total_rows}")
|
|
141
|
+
|
|
131
142
|
if total_pages > 1 and not show_all:
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
console.print(f"[bold green]Total rows:[/bold green] {len(rows)}\n")
|
|
143
|
+
footer_items.append(f"[dim]· [bold]:page <1-{total_pages}>[/bold] | [bold]:card[/bold] (vertical)[/dim]")
|
|
144
|
+
|
|
145
|
+
console.print(" ".join(footer_items) + "\n")
|
|
136
146
|
|
|
137
147
|
|
|
138
148
|
def print_results_vertical(
|
|
@@ -162,35 +172,60 @@ def print_results_vertical(
|
|
|
162
172
|
|
|
163
173
|
def open_interactive_scroller(columns: List[str], rows: List[Dict[str, Any]]) -> None:
|
|
164
174
|
"""
|
|
165
|
-
Interactive
|
|
175
|
+
Interactive 2D Scroller allowing seamless navigation through both long rows and wide columns.
|
|
166
176
|
"""
|
|
167
177
|
if not columns or not rows:
|
|
168
178
|
console.print("[dim]No data to display.[/dim]\n")
|
|
169
179
|
return
|
|
170
180
|
|
|
171
181
|
cols_per_page = 6
|
|
182
|
+
rows_per_page = 15
|
|
172
183
|
total_cols = len(columns)
|
|
173
|
-
|
|
174
|
-
|
|
184
|
+
total_rows = len(rows)
|
|
185
|
+
total_col_pages = max(1, math.ceil(total_cols / cols_per_page))
|
|
186
|
+
total_row_pages = max(1, math.ceil(total_rows / rows_per_page))
|
|
187
|
+
|
|
188
|
+
current_col_page = 1
|
|
189
|
+
current_row_page = 1
|
|
175
190
|
|
|
176
191
|
from rich.prompt import Prompt
|
|
177
192
|
|
|
178
|
-
console.print(f"\n[bold cyan]─── Interactive
|
|
193
|
+
console.print(f"\n[bold cyan]─── 📜 Interactive 2D Scroller ({total_rows} rows × {total_cols} columns) ───[/bold cyan]")
|
|
179
194
|
while True:
|
|
180
|
-
|
|
195
|
+
start_row = (current_row_page - 1) * rows_per_page
|
|
196
|
+
end_row = min(start_row + rows_per_page, total_rows)
|
|
197
|
+
page_rows = rows[start_row:end_row]
|
|
198
|
+
|
|
199
|
+
print_results_table(
|
|
200
|
+
columns=columns,
|
|
201
|
+
rows=page_rows,
|
|
202
|
+
title=f"Scroller [dim](Rows {start_row + 1}–{end_row} of {total_rows} · Page {current_row_page}/{total_row_pages})[/dim]",
|
|
203
|
+
col_page=current_col_page,
|
|
204
|
+
cols_per_page=cols_per_page,
|
|
205
|
+
show_all=False,
|
|
206
|
+
max_rows_display=rows_per_page,
|
|
207
|
+
)
|
|
181
208
|
|
|
182
|
-
console.print(f"[bold cyan]
|
|
183
|
-
choice = Prompt.ask("[dim]scroller>[/dim]", default="
|
|
209
|
+
console.print(f"[bold cyan]Navigation:[/bold cyan] [bold]d[/bold]=Next Rows | [bold]u[/bold]=Prev Rows | [bold]n[/bold]=Next Cols | [bold]p[/bold]=Prev Cols | [bold]c[/bold]=Cards | [bold]q[/bold]=Exit")
|
|
210
|
+
choice = Prompt.ask("[dim]scroller>[/dim]", default="d").strip().lower()
|
|
184
211
|
|
|
185
212
|
if choice in ("q", "quit", "exit", "back"):
|
|
186
213
|
console.print("[dim]Exited scroller.[/dim]\n")
|
|
187
214
|
break
|
|
188
|
-
elif choice in ("
|
|
189
|
-
|
|
190
|
-
elif choice in ("
|
|
191
|
-
|
|
215
|
+
elif choice in ("d", "down", "next-row", ""):
|
|
216
|
+
current_row_page = 1 if current_row_page >= total_row_pages else current_row_page + 1
|
|
217
|
+
elif choice in ("u", "up", "prev-row"):
|
|
218
|
+
current_row_page = total_row_pages if current_row_page <= 1 else current_row_page - 1
|
|
219
|
+
elif choice in ("n", "next", "right", ">"):
|
|
220
|
+
current_col_page = 1 if current_col_page >= total_col_pages else current_col_page + 1
|
|
221
|
+
elif choice in ("p", "prev", "left", "<"):
|
|
222
|
+
current_col_page = total_col_pages if current_col_page <= 1 else current_col_page - 1
|
|
223
|
+
elif choice.isdigit():
|
|
224
|
+
val = int(choice)
|
|
225
|
+
if 1 <= val <= total_row_pages:
|
|
226
|
+
current_row_page = val
|
|
192
227
|
elif choice in ("c", "card", "v", "vertical"):
|
|
193
|
-
print_results_vertical(columns,
|
|
228
|
+
print_results_vertical(columns, page_rows)
|
|
194
229
|
Prompt.ask("[dim]Press Enter to return to scroller...[/dim]")
|
|
195
230
|
else:
|
|
196
231
|
try:
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "dbagent-cli"
|
|
7
|
-
version = "0.8.
|
|
7
|
+
version = "0.8.4"
|
|
8
8
|
description = "Enterprise AI Database Copilot, Schema Graph Introspector & Autonomous Recovery Agent (CLI)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|