dbagent-cli 0.5.0__tar.gz → 0.5.2__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 (74) hide show
  1. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/PKG-INFO +1 -1
  2. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/__init__.py +1 -1
  3. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/agent/generator.py +15 -5
  4. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/agent/pipeline.py +4 -2
  5. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/connectors/relational.py +3 -3
  6. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/llm/gemini_provider.py +7 -1
  7. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/schema/formatter.py +7 -1
  8. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent_cli.egg-info/PKG-INFO +1 -1
  9. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/pyproject.toml +1 -1
  10. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/tests/test_cli.py +5 -0
  11. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/README.md +0 -0
  12. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/agent/confidence.py +0 -0
  13. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/agent/conversation.py +0 -0
  14. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/agent/doctor.py +0 -0
  15. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/agent/error_classifier.py +0 -0
  16. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/agent/recommender.py +0 -0
  17. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/agent/validator.py +0 -0
  18. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/cli.py +0 -0
  19. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/config.py +0 -0
  20. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/connectors/base.py +0 -0
  21. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/connectors/factory.py +0 -0
  22. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/connectors/mongo.py +0 -0
  23. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/execution/__init__.py +0 -0
  24. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/execution/cache.py +0 -0
  25. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/execution/changeset.py +0 -0
  26. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/execution/cost.py +0 -0
  27. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/execution/recovery.py +0 -0
  28. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/execution/sandbox.py +0 -0
  29. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/execution/streaming.py +0 -0
  30. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/llm/auto_setup.py +0 -0
  31. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/llm/base.py +0 -0
  32. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/llm/factory.py +0 -0
  33. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/llm/groq_provider.py +0 -0
  34. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/llm/mock_provider.py +0 -0
  35. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/llm/ollama_provider.py +0 -0
  36. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/llm/openrouter_provider.py +0 -0
  37. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/schema/cache.py +0 -0
  38. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/schema/graph.py +0 -0
  39. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/schema/models.py +0 -0
  40. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/schema/retriever.py +0 -0
  41. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/schema/selector.py +0 -0
  42. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/security/__init__.py +0 -0
  43. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/security/audit.py +0 -0
  44. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/security/environment.py +0 -0
  45. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/security/masking.py +0 -0
  46. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/security/modes.py +0 -0
  47. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/security/rbac.py +0 -0
  48. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/semantic/__init__.py +0 -0
  49. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/semantic/dictionary.py +0 -0
  50. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/semantic/templates.py +0 -0
  51. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/sql/__init__.py +0 -0
  52. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/sql/optimizer.py +0 -0
  53. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/sql/validator.py +0 -0
  54. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/ui/console.py +0 -0
  55. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/ui/grid_window.py +0 -0
  56. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/ui/viewer.py +0 -0
  57. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent/ui/visualizer.py +0 -0
  58. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent_cli.egg-info/SOURCES.txt +0 -0
  59. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent_cli.egg-info/dependency_links.txt +0 -0
  60. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent_cli.egg-info/entry_points.txt +0 -0
  61. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent_cli.egg-info/requires.txt +0 -0
  62. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/dbagent_cli.egg-info/top_level.txt +0 -0
  63. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/setup.cfg +0 -0
  64. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/tests/test_cache.py +0 -0
  65. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/tests/test_connectors.py +0 -0
  66. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/tests/test_doctor_and_viz.py +0 -0
  67. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/tests/test_generator.py +0 -0
  68. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/tests/test_graph.py +0 -0
  69. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/tests/test_recovery.py +0 -0
  70. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/tests/test_safety.py +0 -0
  71. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/tests/test_sandbox.py +0 -0
  72. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/tests/test_schema.py +0 -0
  73. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/tests/test_security.py +0 -0
  74. {dbagent_cli-0.5.0 → dbagent_cli-0.5.2}/tests/test_semantic.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbagent-cli
3
- Version: 0.5.0
3
+ Version: 0.5.2
4
4
  Summary: Enterprise AI Database Copilot, Schema Graph Introspector & Autonomous Recovery Agent (CLI)
5
5
  Author: Santhosh Gupta
6
6
  Requires-Python: >=3.9
@@ -2,5 +2,5 @@
2
2
  DB-Agent: Universal Database Introspection and Script Generation AI Agent (CLI).
3
3
  """
4
4
 
5
- __version__ = "0.5.0"
5
+ __version__ = "0.5.2"
6
6
  __author__ = "Santhosh Gupta"
@@ -60,6 +60,10 @@ Generate ONLY the raw executable SQL query for the given database. No markdown f
60
60
  WHERE tc.constraint_type = 'FOREIGN KEY';
61
61
  7. Always include appropriate WHERE clauses, JOINs, and ORDER BY as needed.
62
62
  8. Default to LIMIT 50 unless the user specifies a count.
63
+ 9. For status, active, or flag columns (e.g. `active`, `is_active`, `status`, `enabled`, `deleted`):
64
+ - Check the column data type and sample values shown in the schema.
65
+ - If the column is VARCHAR(1) or CHAR(1) or text, check if values use 'Y'/'N', 'YES'/'NO', '1'/'0', 'ACTIVE'/'INACTIVE', 'TRUE'/'FALSE'.
66
+ - If sample values show 'Y'/'N' (or if it's a single-character VARCHAR/CHAR column), use `active = 'Y'` or `active IN ('Y', '1', 'true', 'TRUE')` for active/enabled status.
63
67
  """
64
68
 
65
69
 
@@ -72,7 +76,8 @@ Target Database Context:
72
76
  - **Available Tables**: {table_summary}
73
77
 
74
78
  You are chatting with the user in the interactive database shell.
75
- - If the user says hello, introduce yourself and mention the database you are connected to.
79
+ - If the user says hello or greets you, introduce yourself and mention the database you are connected to.
80
+ - If the user gives feedback or praise (e.g. "good", "great", "thanks", "nice"), acknowledge it warmly and ask what they would like to query next.
76
81
  - If the user asks what you can do or asks for help, explain that you can query data in plain English, inspect schemas (:table, :tables), find relationships (:fk), generate migrations/ETL pipelines, or execute SQL queries.
77
82
  - If the user asks general questions about the schema, tables, or database concepts, provide clear, concise, and helpful answers in formatted markdown.
78
83
  - Do NOT generate raw SQL queries or try to execute anything in this conversational mode unless the user explicitly asks for SQL examples.
@@ -110,16 +115,21 @@ class ScriptGenerator:
110
115
  Used before SQL generation to predict the query type.
111
116
  """
112
117
  prompt_lower = user_prompt.lower().strip()
118
+ clean_prompt = prompt_lower.rstrip(".!?,:;~ ")
113
119
 
114
- # Chat / Conversational indicators
120
+ # Chat / Conversational indicators (greetings, feedback, praise, acknowledgements)
115
121
  chat_triggers = [
116
- "hello", "hi", "hey", "howdy", "greetings", "good morning", "good evening",
122
+ "hello", "hi", "hey", "howdy", "greetings", "good morning", "good evening", "good afternoon",
117
123
  "who are you", "what can you do", "what are you", "help me", "how to use",
118
124
  "what is this", "tell me about this database", "how does this work",
119
- "can you help", "thanks", "thank you", "bye", "goodbye",
125
+ "can you help", "thanks", "thank you", "thx", "bye", "goodbye", "see ya",
126
+ "good", "great", "nice", "cool", "awesome", "perfect", "ok", "okay",
127
+ "yes", "no", "sure", "got it", "understood", "nice work", "well done",
128
+ "sounds good", "looks good", "alright", "super", "neat", "excellent",
129
+ "amazing", "wonderful", "cool thanks", "great thanks", "thanks a lot",
120
130
  ]
121
131
  for trig in chat_triggers:
122
- if prompt_lower == trig or prompt_lower.startswith(f"{trig} ") or prompt_lower.startswith(f"{trig},") or prompt_lower.startswith(f"{trig}!"):
132
+ if clean_prompt == trig or prompt_lower.startswith(f"{trig} ") or prompt_lower.startswith(f"{trig},") or prompt_lower.startswith(f"{trig}!"):
123
133
  return "chat"
124
134
 
125
135
  # DDL indicators
@@ -155,12 +155,12 @@ class QueryPipeline:
155
155
  # 2. Targeted on-demand table introspection (~50ms instead of 5000ms for full scan)
156
156
  target_names = list(set(exact + fuzzy))
157
157
  if target_names:
158
- targeted = self.connector.inspect_schema(table_names=target_names, include_samples=False, max_samples=0)
158
+ targeted = self.connector.inspect_schema(table_names=target_names, include_samples=True, max_samples=2)
159
159
  retriever = ContextRetriever(targeted)
160
160
  return retriever.retrieve_context(user_prompt, exact_tables=exact, fuzzy_tables=fuzzy, max_tables=8)
161
161
 
162
162
  # 3. Fallback: inspect targeted
163
- targeted = self.connector.inspect_targeted(user_prompt, max_tables=8)
163
+ targeted = self.connector.inspect_targeted(user_prompt, max_tables=8, include_samples=True)
164
164
  retriever = ContextRetriever(targeted)
165
165
  return retriever.retrieve_context(user_prompt, exact_tables=exact, fuzzy_tables=fuzzy, max_tables=8)
166
166
 
@@ -191,10 +191,12 @@ class QueryPipeline:
191
191
  result.is_chat = True
192
192
  result.was_executed = True
193
193
  result.query_type = "chat"
194
+ result.execution_time_ms = (time.time() - t_start) * 1000
194
195
  self.conversation.add_turn(user_prompt=user_prompt, sql="", is_chat=True)
195
196
  return result
196
197
  except Exception as e:
197
198
  result.error = f"Chat generation failed: {str(e)}"
199
+ result.execution_time_ms = (time.time() - t_start) * 1000
198
200
  return result
199
201
 
200
202
  # --- 2. Resolve Tables & Detect Ambiguity ---
@@ -246,7 +246,7 @@ class RelationalConnector(BaseConnector):
246
246
  self,
247
247
  user_prompt: str,
248
248
  max_tables: int = 4,
249
- include_samples: bool = False,
249
+ include_samples: bool = True,
250
250
  ) -> DatabaseSchema:
251
251
  """
252
252
  Ultra-fast on-demand targeted inspection with fuzzy matching (<30ms).
@@ -260,8 +260,8 @@ class RelationalConnector(BaseConnector):
260
260
 
261
261
  return self.inspect_schema(
262
262
  table_names=matched[:max_tables],
263
- include_samples=False,
264
- max_samples=0,
263
+ include_samples=include_samples,
264
+ max_samples=2 if include_samples else 0,
265
265
  include_views=False,
266
266
  include_row_counts=False,
267
267
  )
@@ -58,6 +58,8 @@ class GeminiProvider(BaseLLMProvider):
58
58
  for fb in self.FALLBACK_MODELS:
59
59
  if fb != requested_model and fb not in models_to_try:
60
60
  models_to_try.append(fb)
61
+ # Retry primary model once more at end as a last resort
62
+ models_to_try.append(requested_model)
61
63
 
62
64
  contents = []
63
65
  if system_prompt:
@@ -138,4 +140,8 @@ class GeminiProvider(BaseLLMProvider):
138
140
  last_error = str(e)
139
141
  continue
140
142
 
141
- raise RuntimeError(f"Gemini generation error: {last_error or 'All model attempts failed'}")
143
+ raise RuntimeError(
144
+ f"Gemini generation error: All {len(models_to_try)} models failed. "
145
+ f"Primary model '{requested_model}' — last error: {last_error or 'unknown'}. "
146
+ f"Check your API key and network connection."
147
+ )
@@ -119,5 +119,11 @@ class SchemaFormatter:
119
119
  for fk in t.foreign_keys:
120
120
  fks.append(f"{','.join(fk.constrained_columns)}->{fk.referred_table}({','.join(fk.referred_columns)})")
121
121
  fk_str = f" | FK: {'; '.join(fks)}" if fks else ""
122
- lines.append(f"- {t.name} ({', '.join(cols)}){fk_str}")
122
+ sample_str = ""
123
+ if t.sample_rows:
124
+ s = t.sample_rows[0]
125
+ sample_pairs = [f"{k}={repr(v)}" for k, v in list(s.items())[:8] if v is not None]
126
+ if sample_pairs:
127
+ sample_str = f" | Sample: {{{', '.join(sample_pairs)}}}"
128
+ lines.append(f"- {t.name} ({', '.join(cols)}){fk_str}{sample_str}")
123
129
  return "\n".join(lines)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbagent-cli
3
- Version: 0.5.0
3
+ Version: 0.5.2
4
4
  Summary: Enterprise AI Database Copilot, Schema Graph Introspector & Autonomous Recovery Agent (CLI)
5
5
  Author: Santhosh Gupta
6
6
  Requires-Python: >=3.9
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dbagent-cli"
7
- version = "0.5.0"
7
+ version = "0.5.2"
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"
@@ -417,6 +417,11 @@ def test_classify_intent():
417
417
  assert ScriptGenerator.classify_intent("create table products") == "ddl"
418
418
  assert ScriptGenerator.classify_intent("drop table temp_data") == "ddl"
419
419
  assert ScriptGenerator.classify_intent("add column age to users") == "ddl"
420
+ assert ScriptGenerator.classify_intent("good") == "chat"
421
+ assert ScriptGenerator.classify_intent("nice") == "chat"
422
+ assert ScriptGenerator.classify_intent("great") == "chat"
423
+ assert ScriptGenerator.classify_intent("thanks") == "chat"
424
+ assert ScriptGenerator.classify_intent("hello") == "chat"
420
425
 
421
426
 
422
427
  def test_strip_markdown_fences():
File without changes
File without changes
File without changes