dbagent-cli 0.9.7__tar.gz → 0.9.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 (84) hide show
  1. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/PKG-INFO +1 -1
  2. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/__init__.py +1 -1
  3. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/agent/generator.py +4 -0
  4. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/agent/pipeline.py +14 -1
  5. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/cli.py +43 -7
  6. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/ui/chat_screen.py +8 -1
  7. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent_cli.egg-info/PKG-INFO +1 -1
  8. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/pyproject.toml +1 -1
  9. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/tests/test_cli.py +19 -2
  10. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/README.md +0 -0
  11. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/agent/confidence.py +0 -0
  12. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/agent/conversation.py +0 -0
  13. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/agent/doctor.py +0 -0
  14. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/agent/error_classifier.py +0 -0
  15. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/agent/recommender.py +0 -0
  16. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/agent/validator.py +0 -0
  17. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/config.py +0 -0
  18. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/connectors/base.py +0 -0
  19. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/connectors/factory.py +0 -0
  20. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/connectors/mongo.py +0 -0
  21. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/connectors/relational.py +0 -0
  22. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/execution/__init__.py +0 -0
  23. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/execution/cache.py +0 -0
  24. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/execution/changeset.py +0 -0
  25. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/execution/cost.py +0 -0
  26. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/execution/recovery.py +0 -0
  27. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/execution/sandbox.py +0 -0
  28. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/execution/streaming.py +0 -0
  29. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/llm/anthropic_provider.py +0 -0
  30. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/llm/auto_setup.py +0 -0
  31. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/llm/base.py +0 -0
  32. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/llm/deepseek_provider.py +0 -0
  33. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/llm/factory.py +0 -0
  34. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/llm/gemini_provider.py +0 -0
  35. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/llm/groq_provider.py +0 -0
  36. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/llm/mistral_provider.py +0 -0
  37. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/llm/mock_provider.py +0 -0
  38. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/llm/ollama_provider.py +0 -0
  39. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/llm/openai_provider.py +0 -0
  40. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/llm/openrouter_provider.py +0 -0
  41. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/schema/cache.py +0 -0
  42. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/schema/formatter.py +0 -0
  43. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/schema/graph.py +0 -0
  44. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/schema/ground_truth.py +0 -0
  45. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/schema/models.py +0 -0
  46. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/schema/retriever.py +0 -0
  47. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/schema/selector.py +0 -0
  48. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/security/__init__.py +0 -0
  49. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/security/audit.py +0 -0
  50. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/security/environment.py +0 -0
  51. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/security/masking.py +0 -0
  52. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/security/modes.py +0 -0
  53. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/security/rbac.py +0 -0
  54. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/semantic/__init__.py +0 -0
  55. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/semantic/dictionary.py +0 -0
  56. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/semantic/knowledge.py +0 -0
  57. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/semantic/templates.py +0 -0
  58. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/sql/__init__.py +0 -0
  59. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/sql/optimizer.py +0 -0
  60. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/sql/validator.py +0 -0
  61. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/ui/console.py +0 -0
  62. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/ui/grid_window.py +0 -0
  63. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/ui/viewer.py +0 -0
  64. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent/ui/visualizer.py +0 -0
  65. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent_cli.egg-info/SOURCES.txt +0 -0
  66. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent_cli.egg-info/dependency_links.txt +0 -0
  67. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent_cli.egg-info/entry_points.txt +0 -0
  68. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent_cli.egg-info/requires.txt +0 -0
  69. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/dbagent_cli.egg-info/top_level.txt +0 -0
  70. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/setup.cfg +0 -0
  71. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/tests/test_cache.py +0 -0
  72. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/tests/test_connectors.py +0 -0
  73. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/tests/test_direct_sql.py +0 -0
  74. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/tests/test_doctor_and_viz.py +0 -0
  75. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/tests/test_generator.py +0 -0
  76. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/tests/test_graph.py +0 -0
  77. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/tests/test_knowledge.py +0 -0
  78. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/tests/test_providers.py +0 -0
  79. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/tests/test_recovery.py +0 -0
  80. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/tests/test_safety.py +0 -0
  81. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/tests/test_sandbox.py +0 -0
  82. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/tests/test_schema.py +0 -0
  83. {dbagent_cli-0.9.7 → dbagent_cli-0.9.8}/tests/test_security.py +0 -0
  84. {dbagent_cli-0.9.7 → dbagent_cli-0.9.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.9.7
3
+ Version: 0.9.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.9.7"
5
+ __version__ = "0.9.8"
6
6
  __author__ = "Santhosh Gupta"
@@ -247,6 +247,7 @@ class ScriptGenerator:
247
247
  user_prompt: str,
248
248
  conversation_history: Optional[str] = None,
249
249
  model: Optional[str] = None,
250
+ stream_callback: Optional[Callable[[str], None]] = None,
250
251
  ) -> str:
251
252
  """Generate a natural conversational response to the user's message with full session memory."""
252
253
  table_names = [t.name for t in schema.tables]
@@ -268,6 +269,7 @@ class ScriptGenerator:
268
269
  prompt=full_prompt,
269
270
  system_prompt=system_prompt,
270
271
  model=model,
272
+ stream_callback=stream_callback,
271
273
  )
272
274
 
273
275
  def generate_analysis_response(
@@ -276,6 +278,7 @@ class ScriptGenerator:
276
278
  user_prompt: str,
277
279
  conversation_history: Optional[str] = None,
278
280
  model: Optional[str] = None,
281
+ stream_callback: Optional[Callable[[str], None]] = None,
279
282
  ) -> str:
280
283
  """Generate a comprehensive architectural analysis report with ASCII diagrams, theory, and SQL queries."""
281
284
  # 1. Filter relevant tables including foreign keys and junction tables
@@ -301,6 +304,7 @@ class ScriptGenerator:
301
304
  prompt=full_prompt,
302
305
  system_prompt=system_prompt,
303
306
  model=model,
307
+ stream_callback=stream_callback,
304
308
  )
305
309
 
306
310
  # --- Full generation (for `generate` command) ---
@@ -56,6 +56,7 @@ class PipelineResult:
56
56
  # Conversational chat response
57
57
  is_chat: bool = False
58
58
  is_direct_sql: bool = False
59
+ was_streamed: bool = False
59
60
  message: str = ""
60
61
  # Query classification
61
62
  query_type: str = "unknown" # read, write, ddl, chat, unknown
@@ -192,7 +193,13 @@ class QueryPipeline:
192
193
  retriever = ContextRetriever(targeted)
193
194
  return retriever.retrieve_context(user_prompt, exact_tables=exact, fuzzy_tables=fuzzy, max_tables=12)
194
195
 
195
- def run(self, user_prompt: str, force: bool = False, bypass_cache: bool = False) -> PipelineResult:
196
+ def run(
197
+ self,
198
+ user_prompt: str,
199
+ force: bool = False,
200
+ bypass_cache: bool = False,
201
+ stream_callback: Optional[Callable[[str], None]] = None,
202
+ ) -> PipelineResult:
196
203
  """
197
204
  Executes end-to-end pipeline: Prompt -> Security/Semantics -> SQL -> Safe Exec -> Results.
198
205
  """
@@ -217,7 +224,10 @@ class QueryPipeline:
217
224
  user_prompt=user_prompt,
218
225
  conversation_history=conv_history,
219
226
  model=self.model,
227
+ stream_callback=stream_callback,
220
228
  )
229
+ if stream_callback:
230
+ result.was_streamed = True
221
231
  result.is_chat = True
222
232
  result.was_executed = True
223
233
  result.query_type = "chat"
@@ -273,7 +283,10 @@ class QueryPipeline:
273
283
  user_prompt=analysis_prompt,
274
284
  conversation_history=conv_history,
275
285
  model=self.model,
286
+ stream_callback=stream_callback,
276
287
  )
288
+ if stream_callback:
289
+ result.was_streamed = True
277
290
  result.ground_truth = SchemaGroundTruthValidator.validate_response(result.message, sub_schema)
278
291
  result.is_chat = True
279
292
  result.was_executed = True
@@ -339,7 +339,10 @@ def _display_pipeline_result(result: PipelineResult, show_sql: bool = True) -> N
339
339
 
340
340
  if result.is_chat and result.message:
341
341
  console.print("")
342
- console.print(Markdown(result.message))
342
+ if not result.was_streamed:
343
+ console.print(Markdown(result.message))
344
+ if result.ground_truth:
345
+ console.print(result.ground_truth.format_summary())
343
346
  if result.execution_time_ms > 0:
344
347
  print_timing(result.execution_time_ms)
345
348
  console.print("")
@@ -527,8 +530,25 @@ def ask_command(
527
530
  choice_callback=_choice_callback,
528
531
  )
529
532
 
530
- with DynamicSpinner():
531
- result = pipeline.run(user_prompt=prompt, force=force, bypass_cache=no_cache)
533
+ spinner = DynamicSpinner.for_prompt(prompt, model_name=model or getattr(llm, "default_model", None), connector=connector)
534
+ stream_started = [False]
535
+
536
+ def _query_stream_callback(chunk: str) -> None:
537
+ if not stream_started[0]:
538
+ stream_started[0] = True
539
+ spinner.pause()
540
+ timing_str = f"⚡ {spinner.elapsed_ms / 1000:.2f}s" if spinner.elapsed_ms > 0 else ""
541
+ active_model = model or getattr(llm, "default_model", None)
542
+ model_display = f" ({active_model})" if active_model else ""
543
+ console.print(f"\n[bold cyan]● DB-Agent{model_display}[/bold cyan] [dim]{timing_str}[/dim]")
544
+ try:
545
+ sys.stdout.write(chunk)
546
+ sys.stdout.flush()
547
+ except Exception:
548
+ pass
549
+
550
+ with spinner:
551
+ result = pipeline.run(user_prompt=prompt, force=force, bypass_cache=no_cache, stream_callback=_query_stream_callback)
532
552
 
533
553
  _display_pipeline_result(result, show_sql=True)
534
554
  connector.close()
@@ -1094,14 +1114,30 @@ def chat_command(
1094
1114
  console.print("[bold cyan]Goodbye![/bold cyan]")
1095
1115
  break
1096
1116
 
1097
- # --- Natural language query via pipeline ---
1098
- # Update pipeline settings in-place (pipeline was created once before the loop)
1117
+ # --- Natural language query via pipeline with live streaming ---
1099
1118
  pipeline.model = model
1100
1119
  pipeline.mode = current_mode
1101
1120
  pipeline.auto_execute = auto_execute
1102
1121
 
1103
- with DynamicSpinner.for_prompt(user_input, model_name=model or getattr(llm, "default_model", None), connector=connector):
1104
- result = pipeline.run(user_prompt=user_input)
1122
+ spinner = DynamicSpinner.for_prompt(user_input, model_name=model or getattr(llm, "default_model", None), connector=connector)
1123
+ stream_started = [False]
1124
+
1125
+ def _live_stream_callback(chunk: str) -> None:
1126
+ if not stream_started[0]:
1127
+ stream_started[0] = True
1128
+ spinner.pause()
1129
+ timing_str = f"⚡ {spinner.elapsed_ms / 1000:.2f}s" if spinner.elapsed_ms > 0 else ""
1130
+ active_model = model or getattr(llm, "default_model", None)
1131
+ model_display = f" ({active_model})" if active_model else ""
1132
+ console.print(f"\n[bold cyan]● DB-Agent{model_display}[/bold cyan] [dim]{timing_str}[/dim]")
1133
+ try:
1134
+ sys.stdout.write(chunk)
1135
+ sys.stdout.flush()
1136
+ except Exception:
1137
+ pass
1138
+
1139
+ with spinner:
1140
+ result = pipeline.run(user_prompt=user_input, stream_callback=_live_stream_callback)
1105
1141
 
1106
1142
  render_assistant_turn(
1107
1143
  result,
@@ -114,8 +114,15 @@ def render_assistant_turn(
114
114
  model_display = f" ({ai_model})" if ai_model else ""
115
115
  agent_title = f"[bold cyan]● DB-Agent{model_display}[/bold cyan] [dim]{timing_str}[/dim]"
116
116
 
117
- # Conversational Chat Response
117
+ # Conversational Chat / Architectural Analysis Response
118
118
  if result.is_chat and result.message:
119
+ if result.was_streamed:
120
+ console.print("")
121
+ if result.ground_truth:
122
+ console.print(result.ground_truth.format_summary())
123
+ console.print("")
124
+ return
125
+
119
126
  console.print(f"\n{agent_title}")
120
127
  console.print(Markdown(result.message))
121
128
  if result.ground_truth:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbagent-cli
3
- Version: 0.9.7
3
+ Version: 0.9.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.9.7"
7
+ version = "0.9.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"
@@ -481,6 +481,25 @@ def test_cli_changes_and_audit_commands():
481
481
  assert res_audit.exit_code == 0
482
482
 
483
483
 
484
+ def test_pipeline_streaming_callback(sample_db: str):
485
+ from dbagent.connectors.factory import create_connector
486
+ from dbagent.llm.mock_provider import MockProvider
487
+ from dbagent.agent.pipeline import QueryPipeline
488
+
489
+ connector = create_connector(sample_db)
490
+ llm = MockProvider()
491
+ pipeline = QueryPipeline(connector=connector, llm=llm)
492
+
493
+ chunks = []
494
+ def callback(token: str):
495
+ chunks.append(token)
496
+
497
+ result = pipeline.run("hello assistant", stream_callback=callback)
498
+ assert result.was_streamed is True
499
+ assert result.is_chat is True
500
+ connector.close()
501
+
502
+
484
503
  def test_cli_recovery_commands():
485
504
  res_list = runner.invoke(app, ["recovery", "list"])
486
505
  assert res_list.exit_code == 0
@@ -491,5 +510,3 @@ def test_cli_recovery_commands():
491
510
 
492
511
  res_cleanup = runner.invoke(app, ["recovery", "cleanup"])
493
512
  assert res_cleanup.exit_code == 0
494
-
495
-
File without changes
File without changes