dbagent-cli 0.8.5__tar.gz → 0.8.7__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.8.5 → dbagent_cli-0.8.7}/PKG-INFO +1 -1
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/__init__.py +1 -1
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/agent/generator.py +86 -1
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/agent/pipeline.py +28 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/ui/chat_screen.py +16 -17
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent_cli.egg-info/PKG-INFO +1 -1
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/pyproject.toml +1 -1
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/tests/test_generator.py +20 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/README.md +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/agent/confidence.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/agent/conversation.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/agent/doctor.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/agent/error_classifier.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/agent/recommender.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/agent/validator.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/cli.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/config.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/connectors/base.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/connectors/factory.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/connectors/mongo.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/connectors/relational.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/execution/__init__.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/execution/cache.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/execution/changeset.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/execution/cost.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/execution/recovery.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/execution/sandbox.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/execution/streaming.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/llm/anthropic_provider.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/llm/auto_setup.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/llm/base.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/llm/deepseek_provider.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/llm/factory.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/llm/gemini_provider.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/llm/groq_provider.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/llm/mistral_provider.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/llm/mock_provider.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/llm/ollama_provider.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/llm/openai_provider.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/llm/openrouter_provider.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/schema/cache.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/schema/formatter.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/schema/graph.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/schema/models.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/schema/retriever.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/schema/selector.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/security/__init__.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/security/audit.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/security/environment.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/security/masking.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/security/modes.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/security/rbac.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/semantic/__init__.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/semantic/dictionary.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/semantic/templates.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/sql/__init__.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/sql/optimizer.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/sql/validator.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/ui/console.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/ui/grid_window.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/ui/viewer.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent/ui/visualizer.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent_cli.egg-info/SOURCES.txt +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent_cli.egg-info/dependency_links.txt +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent_cli.egg-info/entry_points.txt +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent_cli.egg-info/requires.txt +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/dbagent_cli.egg-info/top_level.txt +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/setup.cfg +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/tests/test_cache.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/tests/test_cli.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/tests/test_connectors.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/tests/test_direct_sql.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/tests/test_doctor_and_viz.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/tests/test_graph.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/tests/test_providers.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/tests/test_recovery.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/tests/test_safety.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/tests/test_sandbox.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/tests/test_schema.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/tests/test_security.py +0 -0
- {dbagent_cli-0.8.5 → dbagent_cli-0.8.7}/tests/test_semantic.py +0 -0
|
@@ -84,6 +84,43 @@ You are chatting with the user in the interactive database shell.
|
|
|
84
84
|
"""
|
|
85
85
|
|
|
86
86
|
|
|
87
|
+
# --- Architectural / Linkage analysis prompt ---
|
|
88
|
+
|
|
89
|
+
ARCHITECTURE_SYSTEM_PROMPT = """You are DB-Agent, a Principal Database Architect, Data Modeler, and Systems Engineer.
|
|
90
|
+
Target Database Context:
|
|
91
|
+
- **Dialect**: {dialect_name}
|
|
92
|
+
- **Database Name**: {database_name}
|
|
93
|
+
|
|
94
|
+
### Detailed Schema Sub-Graph Context (Tables, Columns, Primary Keys, Foreign Keys, Sample Data):
|
|
95
|
+
{schema_context}
|
|
96
|
+
|
|
97
|
+
The user is asking for architectural analysis, entity relationships, linkages, mappings, or how tables relate to each other in this database.
|
|
98
|
+
|
|
99
|
+
Provide a comprehensive, high-quality, professional Architectural Report structured as follows:
|
|
100
|
+
|
|
101
|
+
### 1. 🗺️ Entity-Relationship & Linkage Architecture Diagram
|
|
102
|
+
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.
|
|
103
|
+
Example structure:
|
|
104
|
+
```text
|
|
105
|
+
┌──────────────┐ ┌──────────────────────┐ ┌───────────────┐
|
|
106
|
+
│ ivis_user │ 1 ──── * │ ivis_tenant_user_map │ * ──── 1 │ ivis_tenant │
|
|
107
|
+
└──────────────┘ └──────────────────────┘ └───────────────┘
|
|
108
|
+
(pk_user_id) (fk_user_id) (pk_tenant_id)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 2. 📐 Architectural & Theoretical Breakdown
|
|
112
|
+
- Explain in clear theoretical and domain terms how the entities map to each other.
|
|
113
|
+
- Highlight the mapping mechanism (direct foreign key vs junction/mapping table vs hierarchical tree).
|
|
114
|
+
- Detail the cardinality, tenant isolation, and user access models represented in the schema.
|
|
115
|
+
|
|
116
|
+
### 3. 🔍 How to Query & Verify Mappings (SQL Examples)
|
|
117
|
+
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.
|
|
118
|
+
|
|
119
|
+
### 4. 💡 Architectural Insights & Best Practices
|
|
120
|
+
Mention indexing recommendations, cascade rules, or performance considerations for these join paths.
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
|
|
87
124
|
# --- Retry prompt when SQL fails ---
|
|
88
125
|
|
|
89
126
|
RETRY_PROMPT_TEMPLATE = """The previous SQL query failed with this error:
|
|
@@ -111,7 +148,7 @@ class ScriptGenerator:
|
|
|
111
148
|
@staticmethod
|
|
112
149
|
def classify_intent(user_prompt: str) -> str:
|
|
113
150
|
"""
|
|
114
|
-
Classify user's natural language intent as 'chat', 'read', 'write', or 'ddl'.
|
|
151
|
+
Classify user's natural language intent as 'chat', 'analysis', 'read', 'write', or 'ddl'.
|
|
115
152
|
Used before SQL generation to predict the query type.
|
|
116
153
|
"""
|
|
117
154
|
prompt_lower = user_prompt.lower().strip()
|
|
@@ -132,6 +169,21 @@ class ScriptGenerator:
|
|
|
132
169
|
if clean_prompt == trig or prompt_lower.startswith(f"{trig} ") or prompt_lower.startswith(f"{trig},") or prompt_lower.startswith(f"{trig}!"):
|
|
133
170
|
return "chat"
|
|
134
171
|
|
|
172
|
+
# Architecture / Relationship / Linkage / Analysis indicators
|
|
173
|
+
analysis_keywords = [
|
|
174
|
+
"linkage architecture", "linkage", "architecture", "relationship between",
|
|
175
|
+
"how are", "how is", "how were", "how they were related", "how were they related",
|
|
176
|
+
"how they were mapped", "how to map", "mapped to", "er diagram", "diagram of",
|
|
177
|
+
"data model", "explain relationship", "explain schema", "schema analysis",
|
|
178
|
+
"analyze the database", "analyze database", "table relationship",
|
|
179
|
+
"foreign key relationship", "how are tables related", "which sites in",
|
|
180
|
+
"how to know that which", "how to know which", "mapping architecture",
|
|
181
|
+
"entity relationship", "theoritical information", "theoretical information",
|
|
182
|
+
]
|
|
183
|
+
for kw in analysis_keywords:
|
|
184
|
+
if kw in prompt_lower:
|
|
185
|
+
return "analysis"
|
|
186
|
+
|
|
135
187
|
# DDL indicators
|
|
136
188
|
ddl_keywords = [
|
|
137
189
|
"create table", "alter table", "drop table", "add column",
|
|
@@ -194,6 +246,39 @@ class ScriptGenerator:
|
|
|
194
246
|
model=model,
|
|
195
247
|
)
|
|
196
248
|
|
|
249
|
+
def generate_analysis_response(
|
|
250
|
+
self,
|
|
251
|
+
schema: DatabaseSchema,
|
|
252
|
+
user_prompt: str,
|
|
253
|
+
conversation_history: Optional[str] = None,
|
|
254
|
+
model: Optional[str] = None,
|
|
255
|
+
) -> str:
|
|
256
|
+
"""Generate a comprehensive architectural analysis report with ASCII diagrams, theory, and SQL queries."""
|
|
257
|
+
# 1. Filter relevant tables including foreign keys and junction tables
|
|
258
|
+
relevant_tables = SchemaSelector.select_relevant_tables(schema, user_prompt, max_tables=20)
|
|
259
|
+
schema_markdown = SchemaFormatter.to_markdown(
|
|
260
|
+
schema,
|
|
261
|
+
selected_tables=relevant_tables,
|
|
262
|
+
include_samples=True,
|
|
263
|
+
max_sample_rows=2,
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
system_prompt = ARCHITECTURE_SYSTEM_PROMPT.format(
|
|
267
|
+
dialect_name=schema.dialect_name,
|
|
268
|
+
database_name=schema.database_name,
|
|
269
|
+
schema_context=schema_markdown,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
full_prompt = user_prompt
|
|
273
|
+
if conversation_history:
|
|
274
|
+
full_prompt = f"{conversation_history}\n\nUser: {user_prompt}"
|
|
275
|
+
|
|
276
|
+
return self.llm.generate(
|
|
277
|
+
prompt=full_prompt,
|
|
278
|
+
system_prompt=system_prompt,
|
|
279
|
+
model=model,
|
|
280
|
+
)
|
|
281
|
+
|
|
197
282
|
# --- Full generation (for `generate` command) ---
|
|
198
283
|
|
|
199
284
|
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(";") + ";"
|
|
@@ -91,13 +91,12 @@ def render_chat_header(
|
|
|
91
91
|
|
|
92
92
|
|
|
93
93
|
def render_user_turn(user_prompt: str) -> None:
|
|
94
|
-
"""Render a user
|
|
95
|
-
user_text = Text()
|
|
96
|
-
user_text.append("💬 You: ", style="bold blue")
|
|
97
|
-
user_text.append(user_prompt, style="bold white")
|
|
94
|
+
"""Render a clean highlighted user prompt bar like Claude Code."""
|
|
98
95
|
console.print("")
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
prompt_text = Text()
|
|
97
|
+
prompt_text.append("❯ ", style="bold cyan")
|
|
98
|
+
prompt_text.append(f"{user_prompt}", style="bold white")
|
|
99
|
+
console.print(Panel(prompt_text, box=None, style="on grey15", padding=(0, 1)))
|
|
101
100
|
|
|
102
101
|
|
|
103
102
|
def render_assistant_turn(
|
|
@@ -107,38 +106,38 @@ def render_assistant_turn(
|
|
|
107
106
|
ai_model: Optional[str] = None,
|
|
108
107
|
) -> None:
|
|
109
108
|
"""Render the assistant response card with SQL, data grid, and execution timing."""
|
|
109
|
+
timing_str = f"⚡ {result.execution_time_ms / 1000:.2f}s" if result.execution_time_ms > 0 else ""
|
|
110
|
+
|
|
110
111
|
if result.is_direct_sql and result.retries == 0:
|
|
111
|
-
agent_title = "[bold cyan]
|
|
112
|
+
agent_title = f"[bold cyan]● DB-Agent[/bold cyan] [dim](Direct SQL • 0 tokens · {timing_str})[/dim]"
|
|
112
113
|
else:
|
|
113
114
|
model_display = f" ({ai_model})" if ai_model else ""
|
|
114
|
-
agent_title = f"[bold cyan]
|
|
115
|
-
|
|
116
|
-
timing_str = f"⚡ {result.execution_time_ms / 1000:.2f}s" if result.execution_time_ms > 0 else ""
|
|
115
|
+
agent_title = f"[bold cyan]● DB-Agent{model_display}[/bold cyan] [dim]{timing_str}[/dim]"
|
|
117
116
|
|
|
118
117
|
# Conversational Chat Response
|
|
119
118
|
if result.is_chat and result.message:
|
|
120
|
-
console.print(f"\n{agent_title}
|
|
119
|
+
console.print(f"\n{agent_title}")
|
|
121
120
|
console.print(Markdown(result.message))
|
|
122
121
|
console.print("")
|
|
123
122
|
return
|
|
124
123
|
|
|
125
124
|
# Error Response
|
|
126
125
|
if result.error:
|
|
127
|
-
console.print(f"\n[bold red]
|
|
126
|
+
console.print(f"\n[bold red]● DB-Agent (Error)[/bold red] [dim]{timing_str}[/dim]")
|
|
128
127
|
if result.friendly_error:
|
|
129
|
-
|
|
128
|
+
console.print(f" [dim]└[/dim] [bold yellow]{result.friendly_error}[/bold yellow]")
|
|
130
129
|
else:
|
|
131
|
-
|
|
130
|
+
console.print(f" [dim]└[/dim] [bold red]{result.error}[/bold red]")
|
|
132
131
|
|
|
133
132
|
if result.error_suggestions:
|
|
134
|
-
console.print(f"[dim]Did you mean: {', '.join(result.error_suggestions)}[/dim]")
|
|
133
|
+
console.print(f" [dim]└ Did you mean: {', '.join(result.error_suggestions)}[/dim]")
|
|
135
134
|
|
|
136
135
|
if result.sql:
|
|
137
|
-
console.print("[dim]Generated SQL:[/dim]")
|
|
136
|
+
console.print(" [dim]Generated SQL:[/dim]")
|
|
138
137
|
syntax = Syntax(result.sql.strip(), "sql", theme="monokai", line_numbers=False)
|
|
139
138
|
console.print(Panel(syntax, border_style="red", padding=(0, 1)))
|
|
140
139
|
if result.retries > 0:
|
|
141
|
-
console.print(f"[dim](Retried {result.retries} time(s))[/dim]")
|
|
140
|
+
console.print(f" [dim]└ (Retried {result.retries} time(s))[/dim]")
|
|
142
141
|
console.print("")
|
|
143
142
|
return
|
|
144
143
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "dbagent-cli"
|
|
7
|
-
version = "0.8.
|
|
7
|
+
version = "0.8.7"
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|