dbagent-cli 0.3.1__tar.gz → 0.3.3__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.3.1 → dbagent_cli-0.3.3}/PKG-INFO +2 -2
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/__init__.py +1 -1
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/agent/pipeline.py +44 -11
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/agent/recommender.py +19 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/cli.py +20 -10
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent_cli.egg-info/PKG-INFO +2 -2
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/pyproject.toml +2 -2
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/README.md +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/agent/confidence.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/agent/conversation.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/agent/doctor.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/agent/error_classifier.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/agent/generator.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/agent/validator.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/config.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/connectors/base.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/connectors/factory.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/connectors/mongo.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/connectors/relational.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/execution/__init__.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/execution/cache.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/execution/changeset.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/execution/cost.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/execution/recovery.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/execution/sandbox.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/execution/streaming.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/llm/auto_setup.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/llm/base.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/llm/factory.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/llm/gemini_provider.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/llm/groq_provider.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/llm/mock_provider.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/llm/ollama_provider.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/llm/openrouter_provider.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/schema/cache.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/schema/formatter.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/schema/graph.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/schema/models.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/schema/retriever.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/schema/selector.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/security/__init__.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/security/audit.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/security/environment.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/security/masking.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/security/modes.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/security/rbac.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/semantic/__init__.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/semantic/dictionary.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/semantic/templates.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/sql/__init__.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/sql/optimizer.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/sql/validator.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/ui/console.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/ui/viewer.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent/ui/visualizer.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent_cli.egg-info/SOURCES.txt +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent_cli.egg-info/dependency_links.txt +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent_cli.egg-info/entry_points.txt +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent_cli.egg-info/requires.txt +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/dbagent_cli.egg-info/top_level.txt +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/setup.cfg +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/tests/test_cache.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/tests/test_cli.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/tests/test_connectors.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/tests/test_doctor_and_viz.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/tests/test_generator.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/tests/test_graph.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/tests/test_recovery.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/tests/test_safety.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/tests/test_sandbox.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/tests/test_schema.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/tests/test_security.py +0 -0
- {dbagent_cli-0.3.1 → dbagent_cli-0.3.3}/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.
|
|
4
|
-
Summary: Enterprise AI Database Copilot with
|
|
3
|
+
Version: 0.3.3
|
|
4
|
+
Summary: Enterprise AI Database Copilot with Instant Schema Caching & Zero-Latency Chat (CLI)
|
|
5
5
|
Author: Santhosh Gupta
|
|
6
6
|
Requires-Python: >=3.9
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
@@ -129,6 +129,40 @@ class QueryPipeline:
|
|
|
129
129
|
self.db_name = "database"
|
|
130
130
|
if hasattr(connector, "engine") and connector.engine:
|
|
131
131
|
self.db_name = connector.engine.url.database or "database"
|
|
132
|
+
self.db_id = str(connector.engine.url)
|
|
133
|
+
else:
|
|
134
|
+
self.db_id = self.db_name
|
|
135
|
+
self.cache_mgr = SchemaCacheManager()
|
|
136
|
+
|
|
137
|
+
def _get_fast_schema_context(
|
|
138
|
+
self,
|
|
139
|
+
user_prompt: str,
|
|
140
|
+
exact: List[str],
|
|
141
|
+
fuzzy: List[str],
|
|
142
|
+
) -> Tuple[DatabaseSchema, List[JoinStep]]:
|
|
143
|
+
"""Fast schema sub-graph retrieval using cache (<5ms) or targeted introspection (<50ms)."""
|
|
144
|
+
# 1. Try local schema cache (< 5ms)
|
|
145
|
+
cached = self.cache_mgr.load_cached_schema(self.db_id)
|
|
146
|
+
if cached:
|
|
147
|
+
retriever = ContextRetriever(cached)
|
|
148
|
+
return retriever.retrieve_context(
|
|
149
|
+
user_prompt=user_prompt,
|
|
150
|
+
exact_tables=exact,
|
|
151
|
+
fuzzy_tables=fuzzy,
|
|
152
|
+
max_tables=8,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# 2. Targeted on-demand table introspection (~50ms instead of 5000ms for full scan)
|
|
156
|
+
target_names = list(set(exact + fuzzy))
|
|
157
|
+
if target_names:
|
|
158
|
+
targeted = self.connector.inspect_schema(table_names=target_names, include_samples=False, max_samples=0)
|
|
159
|
+
retriever = ContextRetriever(targeted)
|
|
160
|
+
return retriever.retrieve_context(user_prompt, exact_tables=exact, fuzzy_tables=fuzzy, max_tables=8)
|
|
161
|
+
|
|
162
|
+
# 3. Fallback: inspect targeted
|
|
163
|
+
targeted = self.connector.inspect_targeted(user_prompt, max_tables=8)
|
|
164
|
+
retriever = ContextRetriever(targeted)
|
|
165
|
+
return retriever.retrieve_context(user_prompt, exact_tables=exact, fuzzy_tables=fuzzy, max_tables=8)
|
|
132
166
|
|
|
133
167
|
def run(self, user_prompt: str, force: bool = False, bypass_cache: bool = False) -> PipelineResult:
|
|
134
168
|
"""
|
|
@@ -138,10 +172,16 @@ class QueryPipeline:
|
|
|
138
172
|
result = PipelineResult()
|
|
139
173
|
result.intent = ScriptGenerator.classify_intent(user_prompt)
|
|
140
174
|
|
|
141
|
-
# --- 1. Conversational Chat Fast-Path ---
|
|
175
|
+
# --- 1. Conversational Chat Fast-Path (<10ms schema load) ---
|
|
142
176
|
if result.intent == "chat":
|
|
143
177
|
try:
|
|
144
|
-
|
|
178
|
+
cached = self.cache_mgr.load_cached_schema(self.db_id)
|
|
179
|
+
if cached:
|
|
180
|
+
schema = cached
|
|
181
|
+
else:
|
|
182
|
+
quick_tables = self.connector.get_table_names()[:25]
|
|
183
|
+
schema = self.connector.inspect_schema(table_names=quick_tables, include_samples=False, max_samples=0)
|
|
184
|
+
|
|
145
185
|
result.schema = schema
|
|
146
186
|
result.message = self.generator.generate_chat_response(
|
|
147
187
|
schema=schema,
|
|
@@ -177,16 +217,9 @@ class QueryPipeline:
|
|
|
177
217
|
result.error = "Ambiguous table reference — please specify table name."
|
|
178
218
|
return result
|
|
179
219
|
|
|
180
|
-
# --- 3. Fast AI Context Retrieval (Minimal sub-graph) ---
|
|
220
|
+
# --- 3. Fast AI Context Retrieval (Minimal sub-graph < 5ms) ---
|
|
181
221
|
try:
|
|
182
|
-
|
|
183
|
-
retriever = ContextRetriever(full_schema)
|
|
184
|
-
sub_schema, join_steps = retriever.retrieve_context(
|
|
185
|
-
user_prompt=user_prompt,
|
|
186
|
-
exact_tables=exact,
|
|
187
|
-
fuzzy_tables=fuzzy,
|
|
188
|
-
max_tables=8,
|
|
189
|
-
)
|
|
222
|
+
sub_schema, join_steps = self._get_fast_schema_context(user_prompt, exact, fuzzy)
|
|
190
223
|
result.schema = sub_schema
|
|
191
224
|
result.join_steps = join_steps
|
|
192
225
|
except Exception as e:
|
|
@@ -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,11 +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
|
|
360
|
+
# Display AI recommendations on connect (instant <0.1ms with zero network overhead)
|
|
361
361
|
try:
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
recs = QueryRecommender.generate_recommendations(
|
|
362
|
+
cached_schema = cache_mgr.load_cached_schema(db_url)
|
|
363
|
+
if cached_schema:
|
|
364
|
+
recs = QueryRecommender.generate_recommendations(cached_schema, max_suggestions=3)
|
|
365
|
+
else:
|
|
366
|
+
recs = QueryRecommender.generate_from_table_names(table_names, max_suggestions=3)
|
|
365
367
|
if recs:
|
|
366
368
|
console.print("\n[bold cyan]💡 Try asking:[/bold cyan]")
|
|
367
369
|
for r in recs:
|
|
@@ -443,8 +445,12 @@ def chat_command(
|
|
|
443
445
|
continue
|
|
444
446
|
exact, fuzzy = connector.resolve_tables(cmd_arg)
|
|
445
447
|
target = exact[0] if exact else (fuzzy[0] if fuzzy else cmd_arg)
|
|
446
|
-
|
|
447
|
-
|
|
448
|
+
cached = cache_mgr.load_cached_schema(db_url)
|
|
449
|
+
if cached:
|
|
450
|
+
full_schema = cached
|
|
451
|
+
else:
|
|
452
|
+
with console.status(f"[bold cyan]Finding relationships for {target}...[/bold cyan]"):
|
|
453
|
+
full_schema = connector.inspect_schema(include_samples=False, max_samples=0)
|
|
448
454
|
|
|
449
455
|
tmodel = full_schema.get_table(target)
|
|
450
456
|
outgoing = tmodel.foreign_keys if tmodel else []
|
|
@@ -473,10 +479,14 @@ def chat_command(
|
|
|
473
479
|
if len(args) < 2:
|
|
474
480
|
print_warning("Usage: :path <start_table> <end_table> (e.g. :path users events)")
|
|
475
481
|
continue
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
482
|
+
cached = cache_mgr.load_cached_schema(db_url)
|
|
483
|
+
if cached:
|
|
484
|
+
full_schema = cached
|
|
485
|
+
else:
|
|
486
|
+
with console.status("[bold cyan]Traversing relationship graph...[/bold cyan]"):
|
|
487
|
+
full_schema = connector.inspect_schema(include_samples=False, max_samples=0)
|
|
488
|
+
graph = RelationshipGraph(full_schema)
|
|
489
|
+
path = graph.find_shortest_path(args[0], args[1])
|
|
480
490
|
if path:
|
|
481
491
|
console.print(f"\n[bold cyan]Shortest Relationship Path:[/bold cyan]\n{path.format_visual_path()}\n")
|
|
482
492
|
else:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dbagent-cli
|
|
3
|
-
Version: 0.3.
|
|
4
|
-
Summary: Enterprise AI Database Copilot with
|
|
3
|
+
Version: 0.3.3
|
|
4
|
+
Summary: Enterprise AI Database Copilot with Instant Schema Caching & Zero-Latency Chat (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.
|
|
8
|
-
description = "Enterprise AI Database Copilot with
|
|
7
|
+
version = "0.3.3"
|
|
8
|
+
description = "Enterprise AI Database Copilot with Instant Schema Caching & Zero-Latency Chat (CLI)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
11
11
|
authors = [
|
|
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
|