dbagent-cli 0.3.7__tar.gz → 0.3.9__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.3.7 → dbagent_cli-0.3.9}/PKG-INFO +2 -2
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/__init__.py +1 -1
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/cli.py +24 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/ui/console.py +19 -9
- dbagent_cli-0.3.9/dbagent/ui/grid_window.py +245 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent_cli.egg-info/PKG-INFO +2 -2
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent_cli.egg-info/SOURCES.txt +1 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/pyproject.toml +2 -2
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/README.md +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/agent/confidence.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/agent/conversation.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/agent/doctor.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/agent/error_classifier.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/agent/generator.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/agent/pipeline.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/agent/recommender.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/agent/validator.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/config.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/connectors/base.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/connectors/factory.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/connectors/mongo.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/connectors/relational.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/execution/__init__.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/execution/cache.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/execution/changeset.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/execution/cost.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/execution/recovery.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/execution/sandbox.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/execution/streaming.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/llm/auto_setup.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/llm/base.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/llm/factory.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/llm/gemini_provider.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/llm/groq_provider.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/llm/mock_provider.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/llm/ollama_provider.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/llm/openrouter_provider.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/schema/cache.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/schema/formatter.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/schema/graph.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/schema/models.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/schema/retriever.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/schema/selector.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/security/__init__.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/security/audit.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/security/environment.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/security/masking.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/security/modes.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/security/rbac.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/semantic/__init__.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/semantic/dictionary.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/semantic/templates.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/sql/__init__.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/sql/optimizer.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/sql/validator.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/ui/viewer.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent/ui/visualizer.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent_cli.egg-info/dependency_links.txt +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent_cli.egg-info/entry_points.txt +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent_cli.egg-info/requires.txt +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/dbagent_cli.egg-info/top_level.txt +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/setup.cfg +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/tests/test_cache.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/tests/test_cli.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/tests/test_connectors.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/tests/test_doctor_and_viz.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/tests/test_generator.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/tests/test_graph.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/tests/test_recovery.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/tests/test_safety.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/tests/test_sandbox.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/tests/test_schema.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/tests/test_security.py +0 -0
- {dbagent_cli-0.3.7 → dbagent_cli-0.3.9}/tests/test_semantic.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dbagent-cli
|
|
3
|
-
Version: 0.3.
|
|
4
|
-
Summary: Production-Grade AI Database Copilot with
|
|
3
|
+
Version: 0.3.9
|
|
4
|
+
Summary: Production-Grade AI Database Copilot with Interactive Desktop & Browser Data Grid Viewers (CLI)
|
|
5
5
|
Author: Santhosh Gupta
|
|
6
6
|
Requires-Python: >=3.9
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
@@ -60,6 +60,7 @@ from dbagent.ui.console import (
|
|
|
60
60
|
open_interactive_scroller,
|
|
61
61
|
)
|
|
62
62
|
from dbagent.ui.viewer import SchemaViewer
|
|
63
|
+
from dbagent.ui.grid_window import open_desktop_grid_window, open_browser_grid_window
|
|
63
64
|
|
|
64
65
|
app = typer.Typer(
|
|
65
66
|
name="db-agent",
|
|
@@ -629,6 +630,29 @@ def chat_command(
|
|
|
629
630
|
print_results_vertical(last_result.columns, last_result.rows)
|
|
630
631
|
continue
|
|
631
632
|
|
|
633
|
+
if cmd_name in [":wide", ":all", ":raw"]:
|
|
634
|
+
if not last_result or not last_result.rows:
|
|
635
|
+
print_warning("No previous query results to display.")
|
|
636
|
+
continue
|
|
637
|
+
print_results_table(last_result.columns, last_result.rows, title="All Columns (Wide View)", show_all=True)
|
|
638
|
+
continue
|
|
639
|
+
|
|
640
|
+
if cmd_name in [":window", ":gui", ":grid", ":w"]:
|
|
641
|
+
if not last_result or not last_result.rows:
|
|
642
|
+
print_warning("No previous query results to display.")
|
|
643
|
+
continue
|
|
644
|
+
print_info("Opening desktop interactive window with horizontal & vertical scrollbars...")
|
|
645
|
+
open_desktop_grid_window(last_result.columns, last_result.rows, title=f"DB-Agent Data Grid")
|
|
646
|
+
continue
|
|
647
|
+
|
|
648
|
+
if cmd_name in [":web", ":browser", ":html"]:
|
|
649
|
+
if not last_result or not last_result.rows:
|
|
650
|
+
print_warning("No previous query results to display.")
|
|
651
|
+
continue
|
|
652
|
+
print_info("Opening browser interactive data table...")
|
|
653
|
+
open_browser_grid_window(last_result.columns, last_result.rows, title=f"DB-Agent Data View")
|
|
654
|
+
continue
|
|
655
|
+
|
|
632
656
|
if cmd_name in [":scroll", ":scroller", ":pager"]:
|
|
633
657
|
if not last_result or not last_result.rows:
|
|
634
658
|
print_warning("No previous query results to scroll.")
|
|
@@ -62,25 +62,35 @@ def print_results_table(
|
|
|
62
62
|
rows: List[Dict[str, Any]],
|
|
63
63
|
title: str = "Results",
|
|
64
64
|
col_page: int = 1,
|
|
65
|
-
cols_per_page: int =
|
|
65
|
+
cols_per_page: Optional[int] = None,
|
|
66
|
+
show_all: bool = False,
|
|
66
67
|
) -> None:
|
|
67
68
|
"""
|
|
68
|
-
Print query results in a clean, readable Rich table
|
|
69
|
+
Print query results in a clean, readable Rich table.
|
|
70
|
+
Dynamically scales column count based on terminal zoom-out/width.
|
|
69
71
|
"""
|
|
70
72
|
if not columns or not rows:
|
|
71
73
|
console.print("[dim]Query returned 0 rows.[/dim]\n")
|
|
72
74
|
return
|
|
73
75
|
|
|
74
76
|
total_cols = len(columns)
|
|
75
|
-
|
|
77
|
+
term_width = console.width or 120
|
|
78
|
+
auto_cols = max(8, term_width // 16)
|
|
79
|
+
|
|
80
|
+
if show_all or total_cols <= auto_cols:
|
|
81
|
+
effective_cols_per_page = total_cols
|
|
82
|
+
else:
|
|
83
|
+
effective_cols_per_page = cols_per_page or auto_cols
|
|
84
|
+
|
|
85
|
+
total_pages = max(1, math.ceil(total_cols / effective_cols_per_page))
|
|
76
86
|
current_page = max(1, min(col_page, total_pages))
|
|
77
87
|
|
|
78
|
-
start_idx = (current_page - 1) *
|
|
79
|
-
end_idx = min(start_idx +
|
|
80
|
-
display_cols = columns[start_idx:end_idx]
|
|
88
|
+
start_idx = (current_page - 1) * effective_cols_per_page
|
|
89
|
+
end_idx = min(start_idx + effective_cols_per_page, total_cols)
|
|
90
|
+
display_cols = columns if show_all else columns[start_idx:end_idx]
|
|
81
91
|
|
|
82
92
|
tbl_title = f"[bold cyan]{title}[/bold cyan]"
|
|
83
|
-
if total_pages > 1:
|
|
93
|
+
if total_pages > 1 and not show_all:
|
|
84
94
|
tbl_title += f" [dim](Cols {start_idx + 1}–{end_idx} of {total_cols} | Page {current_page}/{total_pages})[/dim]"
|
|
85
95
|
|
|
86
96
|
table = Table(title=tbl_title, show_header=True, header_style="bold magenta", border_style="dim")
|
|
@@ -101,9 +111,9 @@ def print_results_table(
|
|
|
101
111
|
console.print("")
|
|
102
112
|
console.print(table)
|
|
103
113
|
|
|
104
|
-
if total_pages > 1:
|
|
114
|
+
if total_pages > 1 and not show_all:
|
|
105
115
|
console.print(
|
|
106
|
-
f"[dim]⚡ [bold]:page <1-{total_pages}>[/bold]
|
|
116
|
+
f"[dim]⚡ [bold]:window[/bold] (GUI scroll window) | [bold]:page <1-{total_pages}>[/bold] | [bold]:card[/bold] (vertical) | [bold]:wide[/bold] (zoom-out)[/dim]"
|
|
107
117
|
)
|
|
108
118
|
console.print(f"[bold green]Total rows:[/bold green] {len(rows)}\n")
|
|
109
119
|
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Interactive Desktop and Browser Data Grid Viewers with Horizontal & Vertical Scrollbars.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import tempfile
|
|
7
|
+
import webbrowser
|
|
8
|
+
import threading
|
|
9
|
+
from typing import List, Dict, Any, Optional
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def open_desktop_grid_window(
|
|
13
|
+
columns: List[str],
|
|
14
|
+
rows: List[Dict[str, Any]],
|
|
15
|
+
title: str = "DB-Agent Interactive Data Viewer",
|
|
16
|
+
) -> None:
|
|
17
|
+
"""
|
|
18
|
+
Opens a native desktop GUI window with smooth horizontal and vertical scrollbars,
|
|
19
|
+
search/filter bar, and resizable columns. Runs in a separate thread.
|
|
20
|
+
"""
|
|
21
|
+
if not columns or not rows:
|
|
22
|
+
return
|
|
23
|
+
|
|
24
|
+
def _launch_gui():
|
|
25
|
+
try:
|
|
26
|
+
import tkinter as tk
|
|
27
|
+
from tkinter import ttk, messagebox, filedialog
|
|
28
|
+
import csv
|
|
29
|
+
|
|
30
|
+
root = tk.Tk()
|
|
31
|
+
root.title(f"{title} - ({len(rows)} rows, {len(columns)} columns)")
|
|
32
|
+
root.geometry("1100x650")
|
|
33
|
+
root.minsize(700, 400)
|
|
34
|
+
|
|
35
|
+
# Modern Styling
|
|
36
|
+
style = ttk.Style()
|
|
37
|
+
try:
|
|
38
|
+
style.theme_use("clam")
|
|
39
|
+
except Exception:
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
style.configure("Treeview.Heading", font=("Segoe UI", 10, "bold"), background="#2c3e50", foreground="white")
|
|
43
|
+
style.configure("Treeview", font=("Segoe UI", 9), rowheight=24)
|
|
44
|
+
style.map("Treeview", background=[("selected", "#3498db")])
|
|
45
|
+
|
|
46
|
+
# Top toolbar (Search & Export)
|
|
47
|
+
top_frame = ttk.Frame(root, padding=8)
|
|
48
|
+
top_frame.pack(fill=tk.X, side=tk.TOP)
|
|
49
|
+
|
|
50
|
+
ttk.Label(top_frame, text="🔍 Search / Filter:", font=("Segoe UI", 9, "bold")).pack(side=tk.LEFT, padx=(0, 5))
|
|
51
|
+
search_var = tk.StringVar()
|
|
52
|
+
search_entry = ttk.Entry(top_frame, textvariable=search_var, width=30)
|
|
53
|
+
search_entry.pack(side=tk.LEFT, padx=5)
|
|
54
|
+
|
|
55
|
+
status_lbl = ttk.Label(top_frame, text=f"Total: {len(rows)} records, {len(columns)} columns", font=("Segoe UI", 9))
|
|
56
|
+
status_lbl.pack(side=tk.LEFT, padx=15)
|
|
57
|
+
|
|
58
|
+
def _export_csv():
|
|
59
|
+
fpath = filedialog.asksaveasfilename(
|
|
60
|
+
defaultextension=".csv",
|
|
61
|
+
filetypes=[("CSV Files", "*.csv"), ("All Files", "*.*")],
|
|
62
|
+
initialfile="query_results.csv",
|
|
63
|
+
)
|
|
64
|
+
if fpath:
|
|
65
|
+
try:
|
|
66
|
+
with open(fpath, "w", newline="", encoding="utf-8") as f:
|
|
67
|
+
writer = csv.writer(f)
|
|
68
|
+
writer.writerow(columns)
|
|
69
|
+
for r in rows:
|
|
70
|
+
writer.writerow([r.get(c, "") for c in columns])
|
|
71
|
+
messagebox.showinfo("Export Success", f"Exported {len(rows)} rows to:\n{fpath}")
|
|
72
|
+
except Exception as e:
|
|
73
|
+
messagebox.showerror("Export Failed", str(e))
|
|
74
|
+
|
|
75
|
+
export_btn = ttk.Button(top_frame, text="💾 Export to CSV", command=_export_csv)
|
|
76
|
+
export_btn.pack(side=tk.RIGHT, padx=5)
|
|
77
|
+
|
|
78
|
+
# Center Data Grid Frame with Both Scrollbars
|
|
79
|
+
grid_frame = ttk.Frame(root)
|
|
80
|
+
grid_frame.pack(fill=tk.BOTH, expand=True, padx=8, pady=(0, 8))
|
|
81
|
+
|
|
82
|
+
# Vertical Scrollbar
|
|
83
|
+
v_scroll = ttk.Scrollbar(grid_frame, orient=tk.VERTICAL)
|
|
84
|
+
v_scroll.pack(side=tk.RIGHT, fill=tk.Y)
|
|
85
|
+
|
|
86
|
+
# Horizontal Scrollbar
|
|
87
|
+
h_scroll = ttk.Scrollbar(grid_frame, orient=tk.HORIZONTAL)
|
|
88
|
+
h_scroll.pack(side=tk.BOTTOM, fill=tk.X)
|
|
89
|
+
|
|
90
|
+
# Treeview Table
|
|
91
|
+
tree = ttk.Treeview(
|
|
92
|
+
grid_frame,
|
|
93
|
+
columns=columns,
|
|
94
|
+
show="headings",
|
|
95
|
+
yscrollcommand=v_scroll.set,
|
|
96
|
+
xscrollcommand=h_scroll.set,
|
|
97
|
+
)
|
|
98
|
+
v_scroll.config(command=tree.yview)
|
|
99
|
+
h_scroll.config(command=tree.xview)
|
|
100
|
+
tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
|
101
|
+
|
|
102
|
+
# Configure Columns
|
|
103
|
+
for col in columns:
|
|
104
|
+
tree.heading(col, text=col)
|
|
105
|
+
# Dynamic column width based on column name length
|
|
106
|
+
col_w = max(120, min(280, len(str(col)) * 12))
|
|
107
|
+
tree.column(col, width=col_w, minwidth=80, stretch=False)
|
|
108
|
+
|
|
109
|
+
def populate_table(filter_text=""):
|
|
110
|
+
tree.delete(*tree.get_children())
|
|
111
|
+
f_lower = filter_text.strip().lower()
|
|
112
|
+
count = 0
|
|
113
|
+
for r in rows:
|
|
114
|
+
row_vals = [str(r.get(c, "")) if r.get(c) is not None else "NULL" for c in columns]
|
|
115
|
+
if f_lower:
|
|
116
|
+
if not any(f_lower in v.lower() for v in row_vals):
|
|
117
|
+
continue
|
|
118
|
+
tree.insert("", tk.END, values=row_vals)
|
|
119
|
+
count += 1
|
|
120
|
+
status_lbl.config(text=f"Showing: {count} of {len(rows)} rows ({len(columns)} columns)")
|
|
121
|
+
|
|
122
|
+
populate_table()
|
|
123
|
+
|
|
124
|
+
def on_search_change(*args):
|
|
125
|
+
populate_table(search_var.get())
|
|
126
|
+
|
|
127
|
+
search_var.trace_add("write", on_search_change)
|
|
128
|
+
|
|
129
|
+
root.mainloop()
|
|
130
|
+
except Exception as e:
|
|
131
|
+
print(f"[DB-Agent GUI Error] Could not launch desktop window: {e}")
|
|
132
|
+
|
|
133
|
+
# Launch GUI in background thread so CLI prompt stays responsive
|
|
134
|
+
thread = threading.Thread(target=_launch_gui, daemon=True)
|
|
135
|
+
thread.start()
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def open_browser_grid_window(
|
|
139
|
+
columns: List[str],
|
|
140
|
+
rows: List[Dict[str, Any]],
|
|
141
|
+
title: str = "DB-Agent Interactive Data Grid",
|
|
142
|
+
) -> None:
|
|
143
|
+
"""
|
|
144
|
+
Generates a standalone, ultra-fast HTML data grid with frozen headers,
|
|
145
|
+
instant horizontal & vertical scrolling, search, and CSV export, then opens it in browser.
|
|
146
|
+
"""
|
|
147
|
+
if not columns or not rows:
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
import json
|
|
151
|
+
|
|
152
|
+
cols_json = json.dumps([{"title": c, "field": c, "headerFilter": "input", "resizable": True} for c in columns])
|
|
153
|
+
data_json = json.dumps(rows, default=str)
|
|
154
|
+
|
|
155
|
+
html_content = f"""<!DOCTYPE html>
|
|
156
|
+
<html lang="en">
|
|
157
|
+
<head>
|
|
158
|
+
<meta charset="UTF-8">
|
|
159
|
+
<title>{title}</title>
|
|
160
|
+
<link href="https://unpkg.com/tabulator-tables@5.5.0/dist/css/tabulator_midnight.min.css" rel="stylesheet">
|
|
161
|
+
<script type="text/javascript" src="https://unpkg.com/tabulator-tables@5.5.0/dist/js/tabulator.min.js"></script>
|
|
162
|
+
<style>
|
|
163
|
+
body {{
|
|
164
|
+
margin: 0;
|
|
165
|
+
padding: 16px;
|
|
166
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
167
|
+
background: #0f172a;
|
|
168
|
+
color: #f8fafc;
|
|
169
|
+
}}
|
|
170
|
+
.header {{
|
|
171
|
+
display: flex;
|
|
172
|
+
justify-content: space-between;
|
|
173
|
+
align-items: center;
|
|
174
|
+
margin-bottom: 12px;
|
|
175
|
+
}}
|
|
176
|
+
h1 {{
|
|
177
|
+
margin: 0;
|
|
178
|
+
font-size: 1.3rem;
|
|
179
|
+
color: #38bdf8;
|
|
180
|
+
}}
|
|
181
|
+
.badge {{
|
|
182
|
+
background: #1e293b;
|
|
183
|
+
padding: 4px 10px;
|
|
184
|
+
border-radius: 6px;
|
|
185
|
+
font-size: 0.85rem;
|
|
186
|
+
color: #94a3b8;
|
|
187
|
+
border: 1px solid #334155;
|
|
188
|
+
}}
|
|
189
|
+
.btn {{
|
|
190
|
+
background: #0284c7;
|
|
191
|
+
color: white;
|
|
192
|
+
border: none;
|
|
193
|
+
padding: 6px 14px;
|
|
194
|
+
border-radius: 6px;
|
|
195
|
+
font-weight: 600;
|
|
196
|
+
cursor: pointer;
|
|
197
|
+
}}
|
|
198
|
+
.btn:hover {{
|
|
199
|
+
background: #0369a1;
|
|
200
|
+
}}
|
|
201
|
+
#data-table {{
|
|
202
|
+
height: calc(100vh - 85px);
|
|
203
|
+
background: #1e293b;
|
|
204
|
+
border-radius: 8px;
|
|
205
|
+
border: 1px solid #334155;
|
|
206
|
+
}}
|
|
207
|
+
</style>
|
|
208
|
+
</head>
|
|
209
|
+
<body>
|
|
210
|
+
<div class="header">
|
|
211
|
+
<div>
|
|
212
|
+
<h1>📊 {title}</h1>
|
|
213
|
+
<span class="badge">{len(rows)} Records • {len(columns)} Columns</span>
|
|
214
|
+
</div>
|
|
215
|
+
<div>
|
|
216
|
+
<button class="btn" onclick="table.download('csv', 'data_export.csv')">💾 Download CSV</button>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
<div id="data-table"></div>
|
|
220
|
+
|
|
221
|
+
<script>
|
|
222
|
+
const tableData = {data_json};
|
|
223
|
+
const tableCols = {cols_json};
|
|
224
|
+
|
|
225
|
+
const table = new Tabulator("#data-table", {{
|
|
226
|
+
data: tableData,
|
|
227
|
+
columns: tableCols,
|
|
228
|
+
layout: "fitData",
|
|
229
|
+
pagination: false,
|
|
230
|
+
renderVertical: "virtual",
|
|
231
|
+
renderHorizontal: "virtual",
|
|
232
|
+
movableColumns: true,
|
|
233
|
+
responsiveLayout: false,
|
|
234
|
+
}});
|
|
235
|
+
</script>
|
|
236
|
+
</body>
|
|
237
|
+
</html>
|
|
238
|
+
"""
|
|
239
|
+
|
|
240
|
+
temp_dir = tempfile.gettempdir()
|
|
241
|
+
temp_path = os.path.join(temp_dir, "dbagent_data_grid.html")
|
|
242
|
+
with open(temp_path, "w", encoding="utf-8") as f:
|
|
243
|
+
f.write(html_content)
|
|
244
|
+
|
|
245
|
+
webbrowser.open(f"file://{temp_path}")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dbagent-cli
|
|
3
|
-
Version: 0.3.
|
|
4
|
-
Summary: Production-Grade AI Database Copilot with
|
|
3
|
+
Version: 0.3.9
|
|
4
|
+
Summary: Production-Grade AI Database Copilot with Interactive Desktop & Browser Data Grid Viewers (CLI)
|
|
5
5
|
Author: Santhosh Gupta
|
|
6
6
|
Requires-Python: >=3.9
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "dbagent-cli"
|
|
7
|
-
version = "0.3.
|
|
8
|
-
description = "Production-Grade AI Database Copilot with
|
|
7
|
+
version = "0.3.9"
|
|
8
|
+
description = "Production-Grade AI Database Copilot with Interactive Desktop & Browser Data Grid Viewers (CLI)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
11
11
|
authors = [
|
|
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
|