dbagent-cli 0.9.1__tar.gz → 0.9.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 (84) hide show
  1. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/PKG-INFO +1 -1
  2. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/__init__.py +1 -1
  3. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/agent/conversation.py +5 -1
  4. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/agent/generator.py +41 -25
  5. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/agent/pipeline.py +13 -1
  6. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/connectors/base.py +32 -4
  7. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent_cli.egg-info/PKG-INFO +1 -1
  8. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/pyproject.toml +1 -1
  9. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/README.md +0 -0
  10. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/agent/confidence.py +0 -0
  11. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/agent/doctor.py +0 -0
  12. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/agent/error_classifier.py +0 -0
  13. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/agent/recommender.py +0 -0
  14. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/agent/validator.py +0 -0
  15. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/cli.py +0 -0
  16. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/config.py +0 -0
  17. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/connectors/factory.py +0 -0
  18. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/connectors/mongo.py +0 -0
  19. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/connectors/relational.py +0 -0
  20. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/execution/__init__.py +0 -0
  21. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/execution/cache.py +0 -0
  22. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/execution/changeset.py +0 -0
  23. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/execution/cost.py +0 -0
  24. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/execution/recovery.py +0 -0
  25. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/execution/sandbox.py +0 -0
  26. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/execution/streaming.py +0 -0
  27. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/llm/anthropic_provider.py +0 -0
  28. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/llm/auto_setup.py +0 -0
  29. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/llm/base.py +0 -0
  30. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/llm/deepseek_provider.py +0 -0
  31. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/llm/factory.py +0 -0
  32. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/llm/gemini_provider.py +0 -0
  33. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/llm/groq_provider.py +0 -0
  34. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/llm/mistral_provider.py +0 -0
  35. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/llm/mock_provider.py +0 -0
  36. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/llm/ollama_provider.py +0 -0
  37. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/llm/openai_provider.py +0 -0
  38. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/llm/openrouter_provider.py +0 -0
  39. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/schema/cache.py +0 -0
  40. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/schema/formatter.py +0 -0
  41. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/schema/graph.py +0 -0
  42. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/schema/ground_truth.py +0 -0
  43. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/schema/models.py +0 -0
  44. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/schema/retriever.py +0 -0
  45. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/schema/selector.py +0 -0
  46. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/security/__init__.py +0 -0
  47. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/security/audit.py +0 -0
  48. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/security/environment.py +0 -0
  49. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/security/masking.py +0 -0
  50. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/security/modes.py +0 -0
  51. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/security/rbac.py +0 -0
  52. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/semantic/__init__.py +0 -0
  53. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/semantic/dictionary.py +0 -0
  54. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/semantic/knowledge.py +0 -0
  55. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/semantic/templates.py +0 -0
  56. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/sql/__init__.py +0 -0
  57. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/sql/optimizer.py +0 -0
  58. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/sql/validator.py +0 -0
  59. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/ui/chat_screen.py +0 -0
  60. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/ui/console.py +0 -0
  61. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/ui/grid_window.py +0 -0
  62. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/ui/viewer.py +0 -0
  63. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent/ui/visualizer.py +0 -0
  64. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent_cli.egg-info/SOURCES.txt +0 -0
  65. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent_cli.egg-info/dependency_links.txt +0 -0
  66. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent_cli.egg-info/entry_points.txt +0 -0
  67. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent_cli.egg-info/requires.txt +0 -0
  68. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/dbagent_cli.egg-info/top_level.txt +0 -0
  69. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/setup.cfg +0 -0
  70. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/tests/test_cache.py +0 -0
  71. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/tests/test_cli.py +0 -0
  72. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/tests/test_connectors.py +0 -0
  73. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/tests/test_direct_sql.py +0 -0
  74. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/tests/test_doctor_and_viz.py +0 -0
  75. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/tests/test_generator.py +0 -0
  76. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/tests/test_graph.py +0 -0
  77. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/tests/test_knowledge.py +0 -0
  78. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/tests/test_providers.py +0 -0
  79. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/tests/test_recovery.py +0 -0
  80. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/tests/test_safety.py +0 -0
  81. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/tests/test_sandbox.py +0 -0
  82. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/tests/test_schema.py +0 -0
  83. {dbagent_cli-0.9.1 → dbagent_cli-0.9.2}/tests/test_security.py +0 -0
  84. {dbagent_cli-0.9.1 → dbagent_cli-0.9.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.9.1
3
+ Version: 0.9.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.9.1"
5
+ __version__ = "0.9.2"
6
6
  __author__ = "Santhosh Gupta"
@@ -54,9 +54,13 @@ class ConversationContext:
54
54
  if len(self.turns) > self.max_history:
55
55
  self.turns.pop(0)
56
56
 
57
- if tables and not is_chat:
57
+ if tables:
58
58
  self.active_tables.update(t.lower() for t in tables)
59
59
 
60
+ def get_active_tables(self) -> List[str]:
61
+ """Returns currently active database table names discussed in this session."""
62
+ return list(self.active_tables)
63
+
60
64
  def get_last_turn(self) -> Optional[ConversationTurn]:
61
65
  if self.turns:
62
66
  return self.turns[-1]
@@ -106,6 +106,11 @@ Provide ready-to-run, dialect-accurate SQL JOIN queries answering the user's spe
106
106
 
107
107
  ### 4. 💡 Architectural Insights & Best Practices
108
108
  Mention indexing recommendations, cascade rules, or performance considerations for these join paths.
109
+
110
+ ### 🛑 Critical Operational Directives:
111
+ 1. NEVER ask passive questions like "Would you like me to inspect tables?" or "Should I run a query?". Always proactively inspect and deliver the full architectural blueprint immediately.
112
+ 2. NEVER give generic textbook definitions. Always ground every explanation in the real database schema provided above.
113
+ 3. Always include ALL 4 sections (Diagram, Theoretical Breakdown, SQL Queries, and Insights).
109
114
  """
110
115
 
111
116
 
@@ -142,37 +147,52 @@ class ScriptGenerator:
142
147
  prompt_lower = user_prompt.lower().strip()
143
148
  clean_prompt = prompt_lower.rstrip(".!?,:;~ ")
144
149
 
145
- # Chat / Conversational indicators (greetings, feedback, praise, acknowledgements)
146
- chat_triggers = [
147
- "hello", "hi", "hey", "howdy", "greetings", "good morning", "good evening", "good afternoon",
148
- "who are you", "what can you do", "what are you", "help me", "how to use",
149
- "what is this", "tell me about this database", "how does this work",
150
- "can you help", "thanks", "thank you", "thx", "bye", "goodbye", "see ya",
151
- "good", "great", "nice", "cool", "awesome", "perfect", "ok", "okay",
152
- "yes", "no", "sure", "got it", "understood", "nice work", "well done",
153
- "sounds good", "looks good", "alright", "super", "neat", "excellent",
154
- "amazing", "wonderful", "cool thanks", "great thanks", "thanks a lot",
155
- ]
156
- for trig in chat_triggers:
157
- if clean_prompt == trig or prompt_lower.startswith(f"{trig} ") or prompt_lower.startswith(f"{trig},") or prompt_lower.startswith(f"{trig}!"):
158
- return "chat"
159
-
160
- # Architecture / Relationship / Linkage / Analysis indicators
150
+ # 1. Architecture / Relationship / Linkage / Analysis indicators (Highest Priority)
161
151
  analysis_keywords = [
162
152
  "linkage architecture", "linkage", "architecture", "relationship between",
163
153
  "how are", "how is", "how were", "how they were related", "how were they related",
164
- "how they were mapped", "how to map", "mapped to", "er diagram", "diagram of",
154
+ "how they were mapped", "how to map", "where they mapped", "where is it mapped",
155
+ "how they were assigned", "how are they assigned", "how will be linked", "how is it linked",
156
+ "mapped to", "mapped with", "er diagram", "diagram of",
165
157
  "data model", "explain relationship", "explain schema", "schema analysis",
166
158
  "analyze the database", "analyze database", "table relationship",
167
159
  "foreign key relationship", "how are tables related", "which sites in",
168
160
  "how to know that which", "how to know which", "mapping architecture",
169
161
  "entity relationship", "theoritical information", "theoretical information",
162
+ "check with my previous context", "check with previous context", "previous context",
163
+ "complete architecture", "scope architecture", "tenant level to user level",
164
+ "tenant level", "user level",
170
165
  ]
171
166
  for kw in analysis_keywords:
172
167
  if kw in prompt_lower:
173
168
  return "analysis"
174
169
 
175
- # DDL indicators
170
+ # Contextual clarification for analysis (e.g. "i mean ivis_scope", "i mean table_x")
171
+ if re.search(r'\bi mean\b', prompt_lower) and not re.search(r'\b(insert|update|delete|drop)\b', prompt_lower):
172
+ return "analysis"
173
+
174
+ # 2. Pure Greeting / Feedback / Help triggers (Only when not asking a technical question)
175
+ pure_chat_greetings = ["hello", "hi", "hey", "howdy", "greetings", "good morning", "good evening", "good afternoon"]
176
+ pure_chat_feedback = [
177
+ "thanks", "thank you", "thx", "bye", "goodbye", "see ya",
178
+ "good", "great", "nice", "cool", "awesome", "perfect", "ok", "okay",
179
+ "yes", "no", "sure", "got it", "understood", "nice work", "well done",
180
+ "sounds good", "looks good", "alright", "super", "neat", "excellent",
181
+ "amazing", "wonderful", "cool thanks", "great thanks", "thanks a lot",
182
+ ]
183
+ pure_chat_help = [
184
+ "who are you", "what can you do", "what are you", "help me", "how to use",
185
+ "what is this", "tell me about this database", "how does this work", "can you help",
186
+ ]
187
+
188
+ if clean_prompt in pure_chat_greetings or clean_prompt in pure_chat_feedback or clean_prompt in pure_chat_help:
189
+ return "chat"
190
+
191
+ for trig in pure_chat_greetings + pure_chat_help:
192
+ if prompt_lower.startswith(f"{trig} ") or prompt_lower.startswith(f"{trig},") or prompt_lower.startswith(f"{trig}!"):
193
+ return "chat"
194
+
195
+ # 3. DDL indicators
176
196
  ddl_keywords = [
177
197
  "create table", "alter table", "drop table", "add column",
178
198
  "remove column", "rename column", "rename table", "modify column",
@@ -182,7 +202,7 @@ class ScriptGenerator:
182
202
  if kw in prompt_lower:
183
203
  return "ddl"
184
204
 
185
- # Write indicators (word-boundary matching to avoid false positives like "show dataset")
205
+ # 4. Write indicators (word-boundary matching to avoid false positives like "show dataset")
186
206
  write_phrases = [
187
207
  "insert", "add record", "add row", "add new",
188
208
  "update", "delete", "drop record",
@@ -191,14 +211,10 @@ class ScriptGenerator:
191
211
  for kw in write_phrases:
192
212
  if kw in prompt_lower:
193
213
  return "write"
194
- # Single-word write verbs need word boundary to avoid false positives
195
- # e.g. "set" should not match "dataset", "change" should not match "show changes"
196
- import re as _re
197
214
  write_verbs = ["set", "change", "modify", "remove"]
198
215
  for verb in write_verbs:
199
- if _re.search(r'\b' + verb + r'\b', prompt_lower):
200
- # Exclude when preceded by 'show', 'list', 'display', 'view', 'get'
201
- read_context = _re.search(r'\b(?:show|list|display|view|get|count)\b.*\b' + verb, prompt_lower)
216
+ if re.search(r'\b' + verb + r'\b', prompt_lower):
217
+ read_context = re.search(r'\b(?:show|list|display|view|get|count)\b.*\b' + verb, prompt_lower)
202
218
  if not read_context:
203
219
  return "write"
204
220
 
@@ -214,6 +214,12 @@ class QueryPipeline:
214
214
  except Exception:
215
215
  exact, fuzzy = [], []
216
216
 
217
+ # Inherit active tables from conversation context if follow-up prompt doesn't name tables explicitly
218
+ if not exact and not fuzzy:
219
+ inherited = self.conversation.get_active_tables()
220
+ if inherited:
221
+ exact = inherited[:4]
222
+
217
223
  sub_schema, join_steps = self._get_fast_schema_context(user_prompt, exact, fuzzy)
218
224
  result.schema = sub_schema
219
225
  result.join_steps = join_steps
@@ -244,7 +250,13 @@ class QueryPipeline:
244
250
  result.was_executed = True
245
251
  result.query_type = "analysis"
246
252
  result.execution_time_ms = (time.time() - t_start) * 1000
247
- self.conversation.add_turn(user_prompt=user_prompt, sql="", assistant_response=result.message, is_chat=True)
253
+ self.conversation.add_turn(
254
+ user_prompt=user_prompt,
255
+ sql="",
256
+ assistant_response=result.message,
257
+ tables=exact + fuzzy,
258
+ is_chat=True,
259
+ )
248
260
  return result
249
261
  except Exception as e:
250
262
  result.error = f"Architecture analysis failed: {str(e)}"
@@ -44,14 +44,42 @@ class BaseConnector(ABC):
44
44
 
45
45
  def resolve_tables(self, user_prompt: str) -> Tuple[List[str], List[str]]:
46
46
  """
47
- Resolve which tables the user is referring to.
47
+ Resolve which tables the user is referring to with prefix stripping, pluralization handling, and fuzzy matching.
48
48
  Returns (exact_matches, fuzzy_matches).
49
- Default implementation uses get_table_names with simple substring matching.
50
49
  """
50
+ import re
51
51
  all_tables = self.get_table_names()
52
52
  prompt_lower = user_prompt.lower()
53
- exact = [t for t in all_tables if t.lower() in prompt_lower]
54
- return exact, []
53
+ exact = []
54
+ fuzzy = []
55
+
56
+ tokens = set(re.findall(r'\b[a-zA-Z0-9_]+\b', prompt_lower))
57
+
58
+ for t in all_tables:
59
+ t_lower = t.lower()
60
+ # 1. Exact full table name in prompt
61
+ if re.search(r'\b' + re.escape(t_lower) + r'\b', prompt_lower):
62
+ exact.append(t)
63
+ continue
64
+
65
+ # 2. Match without common prefixes (e.g. "ivis_scope" -> "scope", "scopes")
66
+ unprefixed = re.sub(r'^(?:ivis_|tbl_|table_|app_)', '', t_lower)
67
+ if unprefixed and len(unprefixed) >= 3:
68
+ if (unprefixed in tokens or
69
+ f"{unprefixed}s" in tokens or
70
+ f"{unprefixed}es" in tokens or
71
+ re.search(r'\b' + re.escape(unprefixed) + r'(?:s|es)?\b', prompt_lower)):
72
+ if t not in exact:
73
+ exact.append(t)
74
+ continue
75
+
76
+ # 3. Fuzzy partial match
77
+ for tok in tokens:
78
+ if len(tok) >= 4 and (tok in t_lower or t_lower in tok):
79
+ if t not in exact and t not in fuzzy:
80
+ fuzzy.append(t)
81
+
82
+ return exact, fuzzy
55
83
 
56
84
  def refresh_cache(self) -> None:
57
85
  """Invalidate any cached metadata. Override in subclasses."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbagent-cli
3
- Version: 0.9.1
3
+ Version: 0.9.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.9.1"
7
+ version = "0.9.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"
File without changes
File without changes
File without changes