dbagent-cli 0.3.2__tar.gz → 0.3.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.
Files changed (73) hide show
  1. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/PKG-INFO +2 -2
  2. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/__init__.py +1 -1
  3. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/agent/recommender.py +19 -0
  4. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/cli.py +2 -4
  5. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/connectors/relational.py +10 -30
  6. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/ui/console.py +25 -10
  7. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent_cli.egg-info/PKG-INFO +2 -2
  8. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/pyproject.toml +2 -2
  9. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/README.md +0 -0
  10. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/agent/confidence.py +0 -0
  11. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/agent/conversation.py +0 -0
  12. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/agent/doctor.py +0 -0
  13. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/agent/error_classifier.py +0 -0
  14. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/agent/generator.py +0 -0
  15. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/agent/pipeline.py +0 -0
  16. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/agent/validator.py +0 -0
  17. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/config.py +0 -0
  18. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/connectors/base.py +0 -0
  19. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/connectors/factory.py +0 -0
  20. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/connectors/mongo.py +0 -0
  21. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/execution/__init__.py +0 -0
  22. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/execution/cache.py +0 -0
  23. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/execution/changeset.py +0 -0
  24. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/execution/cost.py +0 -0
  25. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/execution/recovery.py +0 -0
  26. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/execution/sandbox.py +0 -0
  27. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/execution/streaming.py +0 -0
  28. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/llm/auto_setup.py +0 -0
  29. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/llm/base.py +0 -0
  30. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/llm/factory.py +0 -0
  31. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/llm/gemini_provider.py +0 -0
  32. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/llm/groq_provider.py +0 -0
  33. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/llm/mock_provider.py +0 -0
  34. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/llm/ollama_provider.py +0 -0
  35. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/llm/openrouter_provider.py +0 -0
  36. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/schema/cache.py +0 -0
  37. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/schema/formatter.py +0 -0
  38. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/schema/graph.py +0 -0
  39. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/schema/models.py +0 -0
  40. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/schema/retriever.py +0 -0
  41. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/schema/selector.py +0 -0
  42. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/security/__init__.py +0 -0
  43. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/security/audit.py +0 -0
  44. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/security/environment.py +0 -0
  45. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/security/masking.py +0 -0
  46. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/security/modes.py +0 -0
  47. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/security/rbac.py +0 -0
  48. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/semantic/__init__.py +0 -0
  49. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/semantic/dictionary.py +0 -0
  50. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/semantic/templates.py +0 -0
  51. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/sql/__init__.py +0 -0
  52. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/sql/optimizer.py +0 -0
  53. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/sql/validator.py +0 -0
  54. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/ui/viewer.py +0 -0
  55. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent/ui/visualizer.py +0 -0
  56. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent_cli.egg-info/SOURCES.txt +0 -0
  57. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent_cli.egg-info/dependency_links.txt +0 -0
  58. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent_cli.egg-info/entry_points.txt +0 -0
  59. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent_cli.egg-info/requires.txt +0 -0
  60. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/dbagent_cli.egg-info/top_level.txt +0 -0
  61. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/setup.cfg +0 -0
  62. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/tests/test_cache.py +0 -0
  63. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/tests/test_cli.py +0 -0
  64. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/tests/test_connectors.py +0 -0
  65. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/tests/test_doctor_and_viz.py +0 -0
  66. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/tests/test_generator.py +0 -0
  67. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/tests/test_graph.py +0 -0
  68. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/tests/test_recovery.py +0 -0
  69. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/tests/test_safety.py +0 -0
  70. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/tests/test_sandbox.py +0 -0
  71. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/tests/test_schema.py +0 -0
  72. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/tests/test_security.py +0 -0
  73. {dbagent_cli-0.3.2 → dbagent_cli-0.3.4}/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.2
4
- Summary: Enterprise AI Database Copilot with High-Speed Schema Caching & Long-Term Recovery (CLI)
3
+ Version: 0.3.4
4
+ Summary: Enterprise AI Database Copilot with Instant Schema Caching & Clean Wide-Table Display (CLI)
5
5
  Author: Santhosh Gupta
6
6
  Requires-Python: >=3.9
7
7
  Description-Content-Type: text/markdown
@@ -2,5 +2,5 @@
2
2
  DB-Agent: Universal Database Introspection and Script Generation AI Agent (CLI).
3
3
  """
4
4
 
5
- __version__ = "0.3.2"
5
+ __version__ = "0.3.4"
6
6
  __author__ = "Santhosh Gupta"
@@ -59,3 +59,22 @@ class QueryRecommender:
59
59
  suggestions.append(f"Count total rows in `{tables[0].name}`")
60
60
 
61
61
  return suggestions[:max_suggestions]
62
+
63
+ @classmethod
64
+ def generate_from_table_names(cls, table_names: List[str], max_suggestions: int = 3) -> List[str]:
65
+ """Instant zero-query recommendation generator from table names (<0.01ms)."""
66
+ suggestions: List[str] = []
67
+ user_tables = [t for t in table_names if any(w in t.lower() for w in ["user", "customer", "account", "member"])]
68
+ if user_tables:
69
+ suggestions.append(f"List top 10 most recent records from `{user_tables[0]}`")
70
+ event_tables = [t for t in table_names if any(w in t.lower() for w in ["event", "log", "audit", "activity", "history", "camera", "device", "order"])]
71
+ if event_tables:
72
+ suggestions.append(f"Count total records in `{event_tables[0]}`")
73
+ for t in table_names:
74
+ if len(suggestions) >= max_suggestions:
75
+ break
76
+ candidate = f"Show recent rows from `{t}`"
77
+ if candidate not in suggestions:
78
+ suggestions.append(candidate)
79
+ return suggestions[:max_suggestions]
80
+
@@ -357,15 +357,13 @@ def chat_command(
357
357
  console.print(f"[bold cyan]AI:[/bold cyan] {llm.name} | [bold yellow]Mode:[/bold yellow] {current_mode.value}")
358
358
  console.print("[dim]Type your question in plain English or use colon commands (e.g. :help, :tables, :doctor).[/dim]")
359
359
 
360
- # Display AI recommendations on connect (instant via cache or top tables)
360
+ # Display AI recommendations on connect (instant <0.1ms with zero network overhead)
361
361
  try:
362
362
  cached_schema = cache_mgr.load_cached_schema(db_url)
363
363
  if cached_schema:
364
364
  recs = QueryRecommender.generate_recommendations(cached_schema, max_suggestions=3)
365
365
  else:
366
- quick_tables = table_names[:10]
367
- quick_schema = connector.inspect_schema(table_names=quick_tables, include_samples=False, max_samples=0)
368
- recs = QueryRecommender.generate_recommendations(quick_schema, max_suggestions=3)
366
+ recs = QueryRecommender.generate_from_table_names(table_names, max_suggestions=3)
369
367
  if recs:
370
368
  console.print("\n[bold cyan]💡 Try asking:[/bold cyan]")
371
369
  for r in recs:
@@ -249,44 +249,24 @@ class RelationalConnector(BaseConnector):
249
249
  def inspect_targeted(
250
250
  self,
251
251
  user_prompt: str,
252
- max_tables: int = 8,
253
- include_samples: bool = True,
252
+ max_tables: int = 4,
253
+ include_samples: bool = False,
254
254
  ) -> DatabaseSchema:
255
255
  """
256
- On-demand targeted inspection with fuzzy matching.
257
- Returns (schema, exact_matches, fuzzy_matches) for conflict resolution.
256
+ Ultra-fast on-demand targeted inspection with fuzzy matching (<30ms).
258
257
  """
259
258
  all_tables = self.get_table_names()
260
259
  exact, fuzzy = _fuzzy_match_tables(all_tables, user_prompt)
261
260
 
262
- # Combine exact + fuzzy, but prefer exact
263
- matched = exact[:]
264
- for f in fuzzy:
265
- if f not in matched:
266
- matched.append(f)
267
-
268
- if matched:
269
- # Also pull in FK-related tables for completeness
270
- fk_related = self._get_fk_related_tables(matched[:max_tables])
271
- all_to_inspect = matched[:max_tables]
272
- for r in fk_related:
273
- if r not in all_to_inspect and len(all_to_inspect) < max_tables:
274
- all_to_inspect.append(r)
275
-
276
- return self.inspect_schema(
277
- table_names=all_to_inspect,
278
- include_samples=include_samples,
279
- max_samples=2,
280
- include_views=False,
281
- include_row_counts=False,
282
- )
261
+ matched = exact[:] if exact else fuzzy[:max_tables]
262
+ if not matched:
263
+ matched = all_tables[:max_tables]
283
264
 
284
- # Fallback: inspect top max_tables
285
265
  return self.inspect_schema(
286
- table_names=all_tables[:max_tables],
287
- include_samples=include_samples,
288
- max_samples=2,
289
- include_views=True,
266
+ table_names=matched[:max_tables],
267
+ include_samples=False,
268
+ max_samples=0,
269
+ include_views=False,
290
270
  include_row_counts=False,
291
271
  )
292
272
 
@@ -56,22 +56,37 @@ def print_code(code: str, language: str = "sql", title: Optional[str] = None) ->
56
56
  console.print(panel)
57
57
 
58
58
 
59
- def print_results_table(columns: List[str], rows: List[Dict[str, Any]], title: str = "Query Results") -> None:
60
- """Print query results in a clean Rich table."""
61
- if not columns:
62
- console.print("[dim]Query returned no rows.[/dim]")
59
+ def print_results_table(columns: List[str], rows: List[Dict[str, Any]], title: str = "Results") -> None:
60
+ """Print query results in a clean, readable Rich table with wide-table protection."""
61
+ if not columns or not rows:
62
+ console.print("[dim]Query returned 0 rows.[/dim]\n")
63
63
  return
64
64
 
65
- table = Table(title=title, show_header=True, header_style="bold magenta", border_style="dim")
66
- for col in columns:
67
- table.add_column(str(col))
65
+ MAX_DISPLAY_COLS = 8
66
+ is_truncated = len(columns) > MAX_DISPLAY_COLS
67
+ display_cols = columns[:MAX_DISPLAY_COLS] if is_truncated else columns
68
+
69
+ table = Table(title=f"[bold cyan]{title}[/bold cyan]", show_header=True, header_style="bold magenta", border_style="dim")
70
+
71
+ for col in display_cols:
72
+ table.add_column(str(col), overflow="ellipsis", max_width=35)
68
73
 
69
74
  for row in rows:
70
75
  row_vals = []
71
- for col in columns:
76
+ for col in display_cols:
72
77
  v = row.get(col)
73
- row_vals.append(str(v) if v is not None else "[dim]NULL[/dim]")
78
+ val_str = str(v) if v is not None else "[dim]NULL[/dim]"
79
+ # Clean up excessively long raw json/strings
80
+ if len(val_str) > 40:
81
+ val_str = val_str[:37] + "..."
82
+ row_vals.append(val_str)
74
83
  table.add_row(*row_vals)
75
84
 
85
+ console.print("")
76
86
  console.print(table)
77
- console.print(f"[dim]Total rows: {len(rows)}[/dim]\n")
87
+ if is_truncated:
88
+ remaining = len(columns) - MAX_DISPLAY_COLS
89
+ console.print(f"[dim](Showing {MAX_DISPLAY_COLS} of {len(columns)} columns. Hidden: {', '.join(columns[MAX_DISPLAY_COLS:MAX_DISPLAY_COLS+5])}{'...' if remaining > 5 else ''})[/dim]")
90
+ console.print(f"[dim]Tip: Ask for specific fields (e.g., 'list id, username, email, status from ivis_user') for targeted view.[/dim]")
91
+ console.print(f"[bold green]Total rows:[/bold green] {len(rows)}\n")
92
+
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbagent-cli
3
- Version: 0.3.2
4
- Summary: Enterprise AI Database Copilot with High-Speed Schema Caching & Long-Term Recovery (CLI)
3
+ Version: 0.3.4
4
+ Summary: Enterprise AI Database Copilot with Instant Schema Caching & Clean Wide-Table Display (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.2"
8
- description = "Enterprise AI Database Copilot with High-Speed Schema Caching & Long-Term Recovery (CLI)"
7
+ version = "0.3.4"
8
+ description = "Enterprise AI Database Copilot with Instant Schema Caching & Clean Wide-Table Display (CLI)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
11
11
  authors = [
File without changes
File without changes