dbagent-cli 0.8.6__tar.gz → 0.8.8__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 (81) hide show
  1. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/PKG-INFO +1 -1
  2. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/__init__.py +1 -1
  3. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/agent/generator.py +82 -9
  4. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/agent/pipeline.py +28 -0
  5. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent_cli.egg-info/PKG-INFO +1 -1
  6. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/pyproject.toml +1 -1
  7. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/tests/test_generator.py +20 -0
  8. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/README.md +0 -0
  9. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/agent/confidence.py +0 -0
  10. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/agent/conversation.py +0 -0
  11. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/agent/doctor.py +0 -0
  12. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/agent/error_classifier.py +0 -0
  13. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/agent/recommender.py +0 -0
  14. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/agent/validator.py +0 -0
  15. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/cli.py +0 -0
  16. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/config.py +0 -0
  17. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/connectors/base.py +0 -0
  18. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/connectors/factory.py +0 -0
  19. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/connectors/mongo.py +0 -0
  20. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/connectors/relational.py +0 -0
  21. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/execution/__init__.py +0 -0
  22. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/execution/cache.py +0 -0
  23. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/execution/changeset.py +0 -0
  24. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/execution/cost.py +0 -0
  25. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/execution/recovery.py +0 -0
  26. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/execution/sandbox.py +0 -0
  27. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/execution/streaming.py +0 -0
  28. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/llm/anthropic_provider.py +0 -0
  29. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/llm/auto_setup.py +0 -0
  30. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/llm/base.py +0 -0
  31. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/llm/deepseek_provider.py +0 -0
  32. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/llm/factory.py +0 -0
  33. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/llm/gemini_provider.py +0 -0
  34. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/llm/groq_provider.py +0 -0
  35. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/llm/mistral_provider.py +0 -0
  36. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/llm/mock_provider.py +0 -0
  37. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/llm/ollama_provider.py +0 -0
  38. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/llm/openai_provider.py +0 -0
  39. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/llm/openrouter_provider.py +0 -0
  40. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/schema/cache.py +0 -0
  41. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/schema/formatter.py +0 -0
  42. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/schema/graph.py +0 -0
  43. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/schema/models.py +0 -0
  44. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/schema/retriever.py +0 -0
  45. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/schema/selector.py +0 -0
  46. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/security/__init__.py +0 -0
  47. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/security/audit.py +0 -0
  48. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/security/environment.py +0 -0
  49. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/security/masking.py +0 -0
  50. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/security/modes.py +0 -0
  51. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/security/rbac.py +0 -0
  52. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/semantic/__init__.py +0 -0
  53. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/semantic/dictionary.py +0 -0
  54. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/semantic/templates.py +0 -0
  55. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/sql/__init__.py +0 -0
  56. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/sql/optimizer.py +0 -0
  57. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/sql/validator.py +0 -0
  58. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/ui/chat_screen.py +0 -0
  59. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/ui/console.py +0 -0
  60. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/ui/grid_window.py +0 -0
  61. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/ui/viewer.py +0 -0
  62. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent/ui/visualizer.py +0 -0
  63. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent_cli.egg-info/SOURCES.txt +0 -0
  64. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent_cli.egg-info/dependency_links.txt +0 -0
  65. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent_cli.egg-info/entry_points.txt +0 -0
  66. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent_cli.egg-info/requires.txt +0 -0
  67. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/dbagent_cli.egg-info/top_level.txt +0 -0
  68. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/setup.cfg +0 -0
  69. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/tests/test_cache.py +0 -0
  70. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/tests/test_cli.py +0 -0
  71. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/tests/test_connectors.py +0 -0
  72. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/tests/test_direct_sql.py +0 -0
  73. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/tests/test_doctor_and_viz.py +0 -0
  74. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/tests/test_graph.py +0 -0
  75. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/tests/test_providers.py +0 -0
  76. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/tests/test_recovery.py +0 -0
  77. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/tests/test_safety.py +0 -0
  78. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/tests/test_sandbox.py +0 -0
  79. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/tests/test_schema.py +0 -0
  80. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/tests/test_security.py +0 -0
  81. {dbagent_cli-0.8.6 → dbagent_cli-0.8.8}/tests/test_semantic.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbagent-cli
3
- Version: 0.8.6
3
+ Version: 0.8.8
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.8.6"
5
+ __version__ = "0.8.8"
6
6
  __author__ = "Santhosh Gupta"
@@ -47,17 +47,12 @@ Generate ONLY the raw executable SQL query for the given database. No markdown f
47
47
  {schema_context}
48
48
 
49
49
  ### Rules:
50
- 1. Output ONLY the SQL query — nothing else. No ```sql fences, no explanations.
50
+ 1. Output ONLY the executable SQL query — nothing else. No ```sql fences, no explanations.
51
51
  2. Use the exact table and column names from the schema above.
52
52
  3. Use dialect-specific syntax for `{dialect_name}`.
53
53
  4. Write clean, optimized SQL with uppercase keywords.
54
- 5. If the user asks for recent/time-based data, use native datetime functions (e.g. for PostgreSQL: `NOW() - INTERVAL '1 hour'`, for SQLite: `datetime('now', '-1 hour')`, for MySQL: `NOW() - INTERVAL 1 HOUR`).
55
- 6. For queries inspecting PostgreSQL foreign key mappings or table relationships via system catalog, use standard joins:
56
- SELECT tc.table_name, kcu.column_name, ccu.table_name AS foreign_table_name, ccu.column_name AS foreign_column_name
57
- FROM information_schema.table_constraints tc
58
- JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name
59
- JOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name
60
- WHERE tc.constraint_type = 'FOREIGN KEY';
54
+ 5. Always query the user's actual database tables and junction/mapping tables from the schema context, using foreign key relationships for JOINs.
55
+ 6. If the user asks for recent/time-based data, use native datetime functions (e.g. for PostgreSQL: `NOW() - INTERVAL '1 hour'`, for SQLite: `datetime('now', '-1 hour')`, for MySQL: `NOW() - INTERVAL 1 HOUR`).
61
56
  7. Always include appropriate WHERE clauses, JOINs, and ORDER BY as needed.
62
57
  8. Default to LIMIT 50 unless the user specifies a count.
63
58
  9. For status, active, or flag columns (e.g. `active`, `is_active`, `status`, `enabled`, `deleted`):
@@ -84,6 +79,36 @@ You are chatting with the user in the interactive database shell.
84
79
  """
85
80
 
86
81
 
82
+ # --- Architectural / Linkage analysis prompt ---
83
+
84
+ ARCHITECTURE_SYSTEM_PROMPT = """You are DB-Agent, an elite Principal Database Architect, Data Modeler, and Systems Engineer.
85
+ Target Database Context:
86
+ - **Dialect**: {dialect_name}
87
+ - **Database Name**: {database_name}
88
+
89
+ ### Detailed Schema Sub-Graph Context (Tables, Columns, Primary Keys, Foreign Keys, Sample Data):
90
+ {schema_context}
91
+
92
+ The user is asking a question regarding database architecture, entity relationships, linkages, mappings, data flows, or structural design.
93
+
94
+ Analyze the provided schema and the user's question, and produce a clear, authoritative, and comprehensive architectural response structured as follows:
95
+
96
+ ### 1. 🗺️ Entity-Relationship & Linkage Architecture Diagram
97
+ Provide a clean, readable ASCII / Unicode box diagram showing the entities, relationship paths, cardinality (1:1, 1:N, N:M junction tables), and the exact connecting foreign keys / join keys.
98
+
99
+ ### 2. 📐 Architectural & Theoretical Breakdown
100
+ - Explain in clear theoretical and domain terms how the entities map to each other in this database.
101
+ - Highlight the mapping mechanisms (direct foreign keys, junction/mapping tables, hierarchical ownership).
102
+ - Detail the cardinality, tenant isolation, and user access models represented in the schema.
103
+
104
+ ### 3. 🔍 How to Query & Verify Mappings (SQL Examples)
105
+ Provide ready-to-run, dialect-accurate SQL JOIN queries answering the user's specific questions (e.g. how to find all sites mapped to a user, how to get tenant membership for a user). Format all SQL in ```sql blocks.
106
+
107
+ ### 4. 💡 Architectural Insights & Best Practices
108
+ Mention indexing recommendations, cascade rules, or performance considerations for these join paths.
109
+ """
110
+
111
+
87
112
  # --- Retry prompt when SQL fails ---
88
113
 
89
114
  RETRY_PROMPT_TEMPLATE = """The previous SQL query failed with this error:
@@ -111,7 +136,7 @@ class ScriptGenerator:
111
136
  @staticmethod
112
137
  def classify_intent(user_prompt: str) -> str:
113
138
  """
114
- Classify user's natural language intent as 'chat', 'read', 'write', or 'ddl'.
139
+ Classify user's natural language intent as 'chat', 'analysis', 'read', 'write', or 'ddl'.
115
140
  Used before SQL generation to predict the query type.
116
141
  """
117
142
  prompt_lower = user_prompt.lower().strip()
@@ -132,6 +157,21 @@ class ScriptGenerator:
132
157
  if clean_prompt == trig or prompt_lower.startswith(f"{trig} ") or prompt_lower.startswith(f"{trig},") or prompt_lower.startswith(f"{trig}!"):
133
158
  return "chat"
134
159
 
160
+ # Architecture / Relationship / Linkage / Analysis indicators
161
+ analysis_keywords = [
162
+ "linkage architecture", "linkage", "architecture", "relationship between",
163
+ "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",
165
+ "data model", "explain relationship", "explain schema", "schema analysis",
166
+ "analyze the database", "analyze database", "table relationship",
167
+ "foreign key relationship", "how are tables related", "which sites in",
168
+ "how to know that which", "how to know which", "mapping architecture",
169
+ "entity relationship", "theoritical information", "theoretical information",
170
+ ]
171
+ for kw in analysis_keywords:
172
+ if kw in prompt_lower:
173
+ return "analysis"
174
+
135
175
  # DDL indicators
136
176
  ddl_keywords = [
137
177
  "create table", "alter table", "drop table", "add column",
@@ -194,6 +234,39 @@ class ScriptGenerator:
194
234
  model=model,
195
235
  )
196
236
 
237
+ def generate_analysis_response(
238
+ self,
239
+ schema: DatabaseSchema,
240
+ user_prompt: str,
241
+ conversation_history: Optional[str] = None,
242
+ model: Optional[str] = None,
243
+ ) -> str:
244
+ """Generate a comprehensive architectural analysis report with ASCII diagrams, theory, and SQL queries."""
245
+ # 1. Filter relevant tables including foreign keys and junction tables
246
+ relevant_tables = SchemaSelector.select_relevant_tables(schema, user_prompt, max_tables=20)
247
+ schema_markdown = SchemaFormatter.to_markdown(
248
+ schema,
249
+ selected_tables=relevant_tables,
250
+ include_samples=True,
251
+ max_sample_rows=2,
252
+ )
253
+
254
+ system_prompt = ARCHITECTURE_SYSTEM_PROMPT.format(
255
+ dialect_name=schema.dialect_name,
256
+ database_name=schema.database_name,
257
+ schema_context=schema_markdown,
258
+ )
259
+
260
+ full_prompt = user_prompt
261
+ if conversation_history:
262
+ full_prompt = f"{conversation_history}\n\nUser: {user_prompt}"
263
+
264
+ return self.llm.generate(
265
+ prompt=full_prompt,
266
+ system_prompt=system_prompt,
267
+ model=model,
268
+ )
269
+
197
270
  # --- Full generation (for `generate` command) ---
198
271
 
199
272
  def generate_script(
@@ -202,6 +202,34 @@ class QueryPipeline:
202
202
  result.execution_time_ms = (time.time() - t_start) * 1000
203
203
  return result
204
204
 
205
+ # --- 1.2. Architectural / Linkage Analysis Path ---
206
+ if result.intent == "analysis":
207
+ try:
208
+ cached = self.cache_mgr.load_cached_schema(self.db_id)
209
+ if cached:
210
+ schema = cached
211
+ else:
212
+ schema = self.connector.inspect_schema(include_samples=True, max_samples=2)
213
+
214
+ result.schema = schema
215
+ conv_history = self.conversation.format_context_for_prompt()
216
+ result.message = self.generator.generate_analysis_response(
217
+ schema=schema,
218
+ user_prompt=user_prompt,
219
+ conversation_history=conv_history,
220
+ model=self.model,
221
+ )
222
+ result.is_chat = True
223
+ result.was_executed = True
224
+ result.query_type = "analysis"
225
+ result.execution_time_ms = (time.time() - t_start) * 1000
226
+ self.conversation.add_turn(user_prompt=user_prompt, sql="", assistant_response=result.message, is_chat=True)
227
+ return result
228
+ except Exception as e:
229
+ result.error = f"Architecture analysis failed: {str(e)}"
230
+ result.execution_time_ms = (time.time() - t_start) * 1000
231
+ return result
232
+
205
233
  # --- 1.5. Direct Raw SQL Fast-Path (0ms AI latency, 0 tokens) ---
206
234
  if SQLValidator.is_direct_sql(user_prompt):
207
235
  raw_sql = user_prompt.strip().rstrip(";") + ";"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbagent-cli
3
- Version: 0.8.6
3
+ Version: 0.8.8
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.8.6"
7
+ version = "0.8.8"
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"
@@ -71,3 +71,23 @@ def test_validator_destructive_delete_without_where():
71
71
  is_safe, warnings = ScriptValidator.analyze_safety("DELETE FROM orders")
72
72
  assert is_safe is False
73
73
  assert any("without WHERE" in w for w in warnings)
74
+
75
+
76
+ def test_classify_intent_analysis():
77
+ prompt = "analyze the database and give me the linkage architecture that how ivis_user and ivis_tenant was related and how they were mapped and how to know that which sites in ivis_site were mapped to which user"
78
+ assert ScriptGenerator.classify_intent(prompt) == "analysis"
79
+
80
+ assert ScriptGenerator.classify_intent("how are users and orders related?") == "analysis"
81
+ assert ScriptGenerator.classify_intent("explain the relationship between customers and payments") == "analysis"
82
+ assert ScriptGenerator.classify_intent("give me the ER diagram and linkage architecture") == "analysis"
83
+
84
+
85
+ def test_generate_analysis_response(mock_schema):
86
+ provider = MockProvider()
87
+ generator = ScriptGenerator(provider)
88
+ result = generator.generate_analysis_response(
89
+ mock_schema,
90
+ "analyze the linkage architecture between events and users",
91
+ )
92
+ assert result is not None
93
+ assert len(result) > 0
File without changes
File without changes
File without changes