vanna 0.7.8__py3-none-any.whl → 2.0.0__py3-none-any.whl

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 (302) hide show
  1. vanna/__init__.py +167 -395
  2. vanna/agents/__init__.py +7 -0
  3. vanna/capabilities/__init__.py +17 -0
  4. vanna/capabilities/agent_memory/__init__.py +21 -0
  5. vanna/capabilities/agent_memory/base.py +103 -0
  6. vanna/capabilities/agent_memory/models.py +53 -0
  7. vanna/capabilities/file_system/__init__.py +14 -0
  8. vanna/capabilities/file_system/base.py +71 -0
  9. vanna/capabilities/file_system/models.py +25 -0
  10. vanna/capabilities/sql_runner/__init__.py +13 -0
  11. vanna/capabilities/sql_runner/base.py +37 -0
  12. vanna/capabilities/sql_runner/models.py +13 -0
  13. vanna/components/__init__.py +92 -0
  14. vanna/components/base.py +11 -0
  15. vanna/components/rich/__init__.py +83 -0
  16. vanna/components/rich/containers/__init__.py +7 -0
  17. vanna/components/rich/containers/card.py +20 -0
  18. vanna/components/rich/data/__init__.py +9 -0
  19. vanna/components/rich/data/chart.py +17 -0
  20. vanna/components/rich/data/dataframe.py +93 -0
  21. vanna/components/rich/feedback/__init__.py +21 -0
  22. vanna/components/rich/feedback/badge.py +16 -0
  23. vanna/components/rich/feedback/icon_text.py +14 -0
  24. vanna/components/rich/feedback/log_viewer.py +41 -0
  25. vanna/components/rich/feedback/notification.py +19 -0
  26. vanna/components/rich/feedback/progress.py +37 -0
  27. vanna/components/rich/feedback/status_card.py +28 -0
  28. vanna/components/rich/feedback/status_indicator.py +14 -0
  29. vanna/components/rich/interactive/__init__.py +21 -0
  30. vanna/components/rich/interactive/button.py +95 -0
  31. vanna/components/rich/interactive/task_list.py +58 -0
  32. vanna/components/rich/interactive/ui_state.py +93 -0
  33. vanna/components/rich/specialized/__init__.py +7 -0
  34. vanna/components/rich/specialized/artifact.py +20 -0
  35. vanna/components/rich/text.py +16 -0
  36. vanna/components/simple/__init__.py +15 -0
  37. vanna/components/simple/image.py +15 -0
  38. vanna/components/simple/link.py +15 -0
  39. vanna/components/simple/text.py +11 -0
  40. vanna/core/__init__.py +193 -0
  41. vanna/core/_compat.py +19 -0
  42. vanna/core/agent/__init__.py +10 -0
  43. vanna/core/agent/agent.py +1407 -0
  44. vanna/core/agent/config.py +123 -0
  45. vanna/core/audit/__init__.py +28 -0
  46. vanna/core/audit/base.py +299 -0
  47. vanna/core/audit/models.py +131 -0
  48. vanna/core/component_manager.py +329 -0
  49. vanna/core/components.py +53 -0
  50. vanna/core/enhancer/__init__.py +11 -0
  51. vanna/core/enhancer/base.py +94 -0
  52. vanna/core/enhancer/default.py +118 -0
  53. vanna/core/enricher/__init__.py +10 -0
  54. vanna/core/enricher/base.py +59 -0
  55. vanna/core/errors.py +47 -0
  56. vanna/core/evaluation/__init__.py +81 -0
  57. vanna/core/evaluation/base.py +186 -0
  58. vanna/core/evaluation/dataset.py +254 -0
  59. vanna/core/evaluation/evaluators.py +376 -0
  60. vanna/core/evaluation/report.py +289 -0
  61. vanna/core/evaluation/runner.py +313 -0
  62. vanna/core/filter/__init__.py +10 -0
  63. vanna/core/filter/base.py +67 -0
  64. vanna/core/lifecycle/__init__.py +10 -0
  65. vanna/core/lifecycle/base.py +83 -0
  66. vanna/core/llm/__init__.py +16 -0
  67. vanna/core/llm/base.py +40 -0
  68. vanna/core/llm/models.py +61 -0
  69. vanna/core/middleware/__init__.py +10 -0
  70. vanna/core/middleware/base.py +69 -0
  71. vanna/core/observability/__init__.py +11 -0
  72. vanna/core/observability/base.py +88 -0
  73. vanna/core/observability/models.py +47 -0
  74. vanna/core/recovery/__init__.py +11 -0
  75. vanna/core/recovery/base.py +84 -0
  76. vanna/core/recovery/models.py +32 -0
  77. vanna/core/registry.py +278 -0
  78. vanna/core/rich_component.py +156 -0
  79. vanna/core/simple_component.py +27 -0
  80. vanna/core/storage/__init__.py +14 -0
  81. vanna/core/storage/base.py +46 -0
  82. vanna/core/storage/models.py +46 -0
  83. vanna/core/system_prompt/__init__.py +13 -0
  84. vanna/core/system_prompt/base.py +36 -0
  85. vanna/core/system_prompt/default.py +157 -0
  86. vanna/core/tool/__init__.py +18 -0
  87. vanna/core/tool/base.py +70 -0
  88. vanna/core/tool/models.py +84 -0
  89. vanna/core/user/__init__.py +17 -0
  90. vanna/core/user/base.py +29 -0
  91. vanna/core/user/models.py +25 -0
  92. vanna/core/user/request_context.py +70 -0
  93. vanna/core/user/resolver.py +42 -0
  94. vanna/core/validation.py +164 -0
  95. vanna/core/workflow/__init__.py +12 -0
  96. vanna/core/workflow/base.py +254 -0
  97. vanna/core/workflow/default.py +789 -0
  98. vanna/examples/__init__.py +1 -0
  99. vanna/examples/__main__.py +44 -0
  100. vanna/examples/anthropic_quickstart.py +80 -0
  101. vanna/examples/artifact_example.py +293 -0
  102. vanna/examples/claude_sqlite_example.py +236 -0
  103. vanna/examples/coding_agent_example.py +300 -0
  104. vanna/examples/custom_system_prompt_example.py +174 -0
  105. vanna/examples/default_workflow_handler_example.py +208 -0
  106. vanna/examples/email_auth_example.py +340 -0
  107. vanna/examples/evaluation_example.py +269 -0
  108. vanna/examples/extensibility_example.py +262 -0
  109. vanna/examples/minimal_example.py +67 -0
  110. vanna/examples/mock_auth_example.py +227 -0
  111. vanna/examples/mock_custom_tool.py +311 -0
  112. vanna/examples/mock_quickstart.py +79 -0
  113. vanna/examples/mock_quota_example.py +145 -0
  114. vanna/examples/mock_rich_components_demo.py +396 -0
  115. vanna/examples/mock_sqlite_example.py +223 -0
  116. vanna/examples/openai_quickstart.py +83 -0
  117. vanna/examples/primitive_components_demo.py +305 -0
  118. vanna/examples/quota_lifecycle_example.py +139 -0
  119. vanna/examples/visualization_example.py +251 -0
  120. vanna/integrations/__init__.py +17 -0
  121. vanna/integrations/anthropic/__init__.py +9 -0
  122. vanna/integrations/anthropic/llm.py +270 -0
  123. vanna/integrations/azureopenai/__init__.py +9 -0
  124. vanna/integrations/azureopenai/llm.py +329 -0
  125. vanna/integrations/azuresearch/__init__.py +7 -0
  126. vanna/integrations/azuresearch/agent_memory.py +413 -0
  127. vanna/integrations/bigquery/__init__.py +5 -0
  128. vanna/integrations/bigquery/sql_runner.py +81 -0
  129. vanna/integrations/chromadb/__init__.py +104 -0
  130. vanna/integrations/chromadb/agent_memory.py +416 -0
  131. vanna/integrations/clickhouse/__init__.py +5 -0
  132. vanna/integrations/clickhouse/sql_runner.py +82 -0
  133. vanna/integrations/duckdb/__init__.py +5 -0
  134. vanna/integrations/duckdb/sql_runner.py +65 -0
  135. vanna/integrations/faiss/__init__.py +7 -0
  136. vanna/integrations/faiss/agent_memory.py +431 -0
  137. vanna/integrations/google/__init__.py +9 -0
  138. vanna/integrations/google/gemini.py +370 -0
  139. vanna/integrations/hive/__init__.py +5 -0
  140. vanna/integrations/hive/sql_runner.py +87 -0
  141. vanna/integrations/local/__init__.py +17 -0
  142. vanna/integrations/local/agent_memory/__init__.py +7 -0
  143. vanna/integrations/local/agent_memory/in_memory.py +285 -0
  144. vanna/integrations/local/audit.py +59 -0
  145. vanna/integrations/local/file_system.py +242 -0
  146. vanna/integrations/local/file_system_conversation_store.py +255 -0
  147. vanna/integrations/local/storage.py +62 -0
  148. vanna/integrations/marqo/__init__.py +7 -0
  149. vanna/integrations/marqo/agent_memory.py +354 -0
  150. vanna/integrations/milvus/__init__.py +7 -0
  151. vanna/integrations/milvus/agent_memory.py +458 -0
  152. vanna/integrations/mock/__init__.py +9 -0
  153. vanna/integrations/mock/llm.py +65 -0
  154. vanna/integrations/mssql/__init__.py +5 -0
  155. vanna/integrations/mssql/sql_runner.py +66 -0
  156. vanna/integrations/mysql/__init__.py +5 -0
  157. vanna/integrations/mysql/sql_runner.py +92 -0
  158. vanna/integrations/ollama/__init__.py +7 -0
  159. vanna/integrations/ollama/llm.py +252 -0
  160. vanna/integrations/openai/__init__.py +10 -0
  161. vanna/integrations/openai/llm.py +267 -0
  162. vanna/integrations/openai/responses.py +163 -0
  163. vanna/integrations/opensearch/__init__.py +7 -0
  164. vanna/integrations/opensearch/agent_memory.py +411 -0
  165. vanna/integrations/oracle/__init__.py +5 -0
  166. vanna/integrations/oracle/sql_runner.py +75 -0
  167. vanna/integrations/pinecone/__init__.py +7 -0
  168. vanna/integrations/pinecone/agent_memory.py +329 -0
  169. vanna/integrations/plotly/__init__.py +5 -0
  170. vanna/integrations/plotly/chart_generator.py +313 -0
  171. vanna/integrations/postgres/__init__.py +9 -0
  172. vanna/integrations/postgres/sql_runner.py +112 -0
  173. vanna/integrations/premium/agent_memory/__init__.py +7 -0
  174. vanna/integrations/premium/agent_memory/premium.py +186 -0
  175. vanna/integrations/presto/__init__.py +5 -0
  176. vanna/integrations/presto/sql_runner.py +107 -0
  177. vanna/integrations/qdrant/__init__.py +7 -0
  178. vanna/integrations/qdrant/agent_memory.py +461 -0
  179. vanna/integrations/snowflake/__init__.py +5 -0
  180. vanna/integrations/snowflake/sql_runner.py +147 -0
  181. vanna/integrations/sqlite/__init__.py +9 -0
  182. vanna/integrations/sqlite/sql_runner.py +65 -0
  183. vanna/integrations/weaviate/__init__.py +7 -0
  184. vanna/integrations/weaviate/agent_memory.py +428 -0
  185. vanna/{ZhipuAI → legacy/ZhipuAI}/ZhipuAI_embeddings.py +11 -11
  186. vanna/legacy/__init__.py +403 -0
  187. vanna/legacy/adapter.py +463 -0
  188. vanna/{advanced → legacy/advanced}/__init__.py +3 -1
  189. vanna/{anthropic → legacy/anthropic}/anthropic_chat.py +9 -7
  190. vanna/{azuresearch → legacy/azuresearch}/azuresearch_vector.py +79 -41
  191. vanna/{base → legacy/base}/base.py +247 -223
  192. vanna/legacy/bedrock/__init__.py +1 -0
  193. vanna/{bedrock → legacy/bedrock}/bedrock_converse.py +13 -12
  194. vanna/{chromadb → legacy/chromadb}/chromadb_vector.py +3 -1
  195. vanna/legacy/cohere/__init__.py +2 -0
  196. vanna/{cohere → legacy/cohere}/cohere_chat.py +19 -14
  197. vanna/{cohere → legacy/cohere}/cohere_embeddings.py +25 -19
  198. vanna/{deepseek → legacy/deepseek}/deepseek_chat.py +5 -6
  199. vanna/legacy/faiss/__init__.py +1 -0
  200. vanna/{faiss → legacy/faiss}/faiss.py +113 -59
  201. vanna/{flask → legacy/flask}/__init__.py +84 -43
  202. vanna/{flask → legacy/flask}/assets.py +5 -5
  203. vanna/{flask → legacy/flask}/auth.py +5 -4
  204. vanna/{google → legacy/google}/bigquery_vector.py +75 -42
  205. vanna/{google → legacy/google}/gemini_chat.py +7 -3
  206. vanna/{hf → legacy/hf}/hf.py +0 -1
  207. vanna/{milvus → legacy/milvus}/milvus_vector.py +58 -35
  208. vanna/{mock → legacy/mock}/llm.py +0 -1
  209. vanna/legacy/mock/vectordb.py +67 -0
  210. vanna/legacy/ollama/ollama.py +110 -0
  211. vanna/{openai → legacy/openai}/openai_chat.py +2 -6
  212. vanna/legacy/opensearch/opensearch_vector.py +369 -0
  213. vanna/legacy/opensearch/opensearch_vector_semantic.py +200 -0
  214. vanna/legacy/oracle/oracle_vector.py +584 -0
  215. vanna/{pgvector → legacy/pgvector}/pgvector.py +42 -13
  216. vanna/{qdrant → legacy/qdrant}/qdrant.py +2 -6
  217. vanna/legacy/qianfan/Qianfan_Chat.py +170 -0
  218. vanna/legacy/qianfan/Qianfan_embeddings.py +36 -0
  219. vanna/legacy/qianwen/QianwenAI_chat.py +132 -0
  220. vanna/{remote.py → legacy/remote.py} +28 -26
  221. vanna/{utils.py → legacy/utils.py} +6 -11
  222. vanna/{vannadb → legacy/vannadb}/vannadb_vector.py +115 -46
  223. vanna/{vllm → legacy/vllm}/vllm.py +5 -6
  224. vanna/{weaviate → legacy/weaviate}/weaviate_vector.py +59 -40
  225. vanna/{xinference → legacy/xinference}/xinference.py +6 -6
  226. vanna/py.typed +0 -0
  227. vanna/servers/__init__.py +16 -0
  228. vanna/servers/__main__.py +8 -0
  229. vanna/servers/base/__init__.py +18 -0
  230. vanna/servers/base/chat_handler.py +65 -0
  231. vanna/servers/base/models.py +111 -0
  232. vanna/servers/base/rich_chat_handler.py +141 -0
  233. vanna/servers/base/templates.py +331 -0
  234. vanna/servers/cli/__init__.py +7 -0
  235. vanna/servers/cli/server_runner.py +204 -0
  236. vanna/servers/fastapi/__init__.py +7 -0
  237. vanna/servers/fastapi/app.py +163 -0
  238. vanna/servers/fastapi/routes.py +183 -0
  239. vanna/servers/flask/__init__.py +7 -0
  240. vanna/servers/flask/app.py +132 -0
  241. vanna/servers/flask/routes.py +137 -0
  242. vanna/tools/__init__.py +41 -0
  243. vanna/tools/agent_memory.py +322 -0
  244. vanna/tools/file_system.py +879 -0
  245. vanna/tools/python.py +222 -0
  246. vanna/tools/run_sql.py +165 -0
  247. vanna/tools/visualize_data.py +195 -0
  248. vanna/utils/__init__.py +0 -0
  249. vanna/web_components/__init__.py +44 -0
  250. vanna-2.0.0.dist-info/METADATA +485 -0
  251. vanna-2.0.0.dist-info/RECORD +289 -0
  252. vanna-2.0.0.dist-info/entry_points.txt +3 -0
  253. vanna/bedrock/__init__.py +0 -1
  254. vanna/cohere/__init__.py +0 -2
  255. vanna/faiss/__init__.py +0 -1
  256. vanna/mock/vectordb.py +0 -55
  257. vanna/ollama/ollama.py +0 -103
  258. vanna/opensearch/opensearch_vector.py +0 -392
  259. vanna/opensearch/opensearch_vector_semantic.py +0 -175
  260. vanna/oracle/oracle_vector.py +0 -585
  261. vanna/qianfan/Qianfan_Chat.py +0 -165
  262. vanna/qianfan/Qianfan_embeddings.py +0 -36
  263. vanna/qianwen/QianwenAI_chat.py +0 -133
  264. vanna-0.7.8.dist-info/METADATA +0 -408
  265. vanna-0.7.8.dist-info/RECORD +0 -79
  266. /vanna/{ZhipuAI → legacy/ZhipuAI}/ZhipuAI_Chat.py +0 -0
  267. /vanna/{ZhipuAI → legacy/ZhipuAI}/__init__.py +0 -0
  268. /vanna/{anthropic → legacy/anthropic}/__init__.py +0 -0
  269. /vanna/{azuresearch → legacy/azuresearch}/__init__.py +0 -0
  270. /vanna/{base → legacy/base}/__init__.py +0 -0
  271. /vanna/{chromadb → legacy/chromadb}/__init__.py +0 -0
  272. /vanna/{deepseek → legacy/deepseek}/__init__.py +0 -0
  273. /vanna/{exceptions → legacy/exceptions}/__init__.py +0 -0
  274. /vanna/{google → legacy/google}/__init__.py +0 -0
  275. /vanna/{hf → legacy/hf}/__init__.py +0 -0
  276. /vanna/{local.py → legacy/local.py} +0 -0
  277. /vanna/{marqo → legacy/marqo}/__init__.py +0 -0
  278. /vanna/{marqo → legacy/marqo}/marqo.py +0 -0
  279. /vanna/{milvus → legacy/milvus}/__init__.py +0 -0
  280. /vanna/{mistral → legacy/mistral}/__init__.py +0 -0
  281. /vanna/{mistral → legacy/mistral}/mistral.py +0 -0
  282. /vanna/{mock → legacy/mock}/__init__.py +0 -0
  283. /vanna/{mock → legacy/mock}/embedding.py +0 -0
  284. /vanna/{ollama → legacy/ollama}/__init__.py +0 -0
  285. /vanna/{openai → legacy/openai}/__init__.py +0 -0
  286. /vanna/{openai → legacy/openai}/openai_embeddings.py +0 -0
  287. /vanna/{opensearch → legacy/opensearch}/__init__.py +0 -0
  288. /vanna/{oracle → legacy/oracle}/__init__.py +0 -0
  289. /vanna/{pgvector → legacy/pgvector}/__init__.py +0 -0
  290. /vanna/{pinecone → legacy/pinecone}/__init__.py +0 -0
  291. /vanna/{pinecone → legacy/pinecone}/pinecone_vector.py +0 -0
  292. /vanna/{qdrant → legacy/qdrant}/__init__.py +0 -0
  293. /vanna/{qianfan → legacy/qianfan}/__init__.py +0 -0
  294. /vanna/{qianwen → legacy/qianwen}/QianwenAI_embeddings.py +0 -0
  295. /vanna/{qianwen → legacy/qianwen}/__init__.py +0 -0
  296. /vanna/{types → legacy/types}/__init__.py +0 -0
  297. /vanna/{vannadb → legacy/vannadb}/__init__.py +0 -0
  298. /vanna/{vllm → legacy/vllm}/__init__.py +0 -0
  299. /vanna/{weaviate → legacy/weaviate}/__init__.py +0 -0
  300. /vanna/{xinference → legacy/xinference}/__init__.py +0 -0
  301. {vanna-0.7.8.dist-info → vanna-2.0.0.dist-info}/WHEEL +0 -0
  302. {vanna-0.7.8.dist-info → vanna-2.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,396 @@
1
+ """
2
+ Mock rich components demonstration example.
3
+
4
+ This example shows how to create an agent that emits rich, stateful components
5
+ including cards, task lists, and tool execution displays using a mock LLM service.
6
+
7
+ Usage:
8
+ PYTHONPATH=. python vanna/examples/mock_rich_components_demo.py
9
+ """
10
+
11
+ import asyncio
12
+ import time
13
+ from datetime import datetime
14
+ from typing import AsyncGenerator, Optional
15
+
16
+ from vanna import (
17
+ AgentConfig,
18
+ Agent,
19
+ MemoryConversationStore,
20
+ MockLlmService,
21
+ User,
22
+ )
23
+ from vanna.core.components import UiComponent
24
+ from vanna.core.rich_components import (
25
+ StatusCardComponent,
26
+ ProgressDisplayComponent,
27
+ LogViewerComponent,
28
+ BadgeComponent,
29
+ IconTextComponent,
30
+ RichTextComponent,
31
+ Task,
32
+ )
33
+
34
+
35
+ class RichComponentsAgent(Agent):
36
+ """Agent that demonstrates rich component capabilities."""
37
+
38
+ async def send_message(
39
+ self,
40
+ user: User,
41
+ message: str,
42
+ *,
43
+ conversation_id: Optional[str] = None,
44
+ ) -> AsyncGenerator[UiComponent, None]:
45
+ """Send message and yield UiComponent(rich_component=rich) components."""
46
+
47
+ # Welcome message using IconText
48
+ yield UiComponent(
49
+ rich_component=IconTextComponent(
50
+ id="welcome-message",
51
+ icon="👋",
52
+ text=f"Hello {user.username}! I'll demonstrate primitive components.",
53
+ variant="primary",
54
+ size="large",
55
+ )
56
+ )
57
+
58
+ # Status card showing we're processing
59
+ status_card = StatusCardComponent(
60
+ id="processing-status",
61
+ title="Processing Request",
62
+ status="running",
63
+ description="Processing your request...",
64
+ icon="⚙️",
65
+ )
66
+ yield UiComponent(rich_component=status_card)
67
+
68
+ # Simulate some processing time
69
+ await asyncio.sleep(1)
70
+
71
+ # Update status to success
72
+ yield UiComponent(
73
+ rich_component=status_card.set_status(
74
+ "success", "Request processed successfully!"
75
+ )
76
+ )
77
+
78
+ # Create a status card for overall demo progress
79
+ demo_card = StatusCardComponent(
80
+ id="demo-progress",
81
+ title="Demo Progress",
82
+ status="running",
83
+ description="Starting primitive components demonstration...",
84
+ icon="🎯",
85
+ )
86
+ yield UiComponent(rich_component=demo_card)
87
+
88
+ # Create badges for different stages
89
+ stages = [
90
+ ("Initialize", "success", "✅"),
91
+ ("Components", "running", "⚙️"),
92
+ ("Progress", "pending", "⏳"),
93
+ ("Logs", "pending", "📋"),
94
+ ("Complete", "pending", "🎉"),
95
+ ]
96
+
97
+ for stage_name, stage_status, stage_icon in stages:
98
+ yield UiComponent(
99
+ rich_component=BadgeComponent(
100
+ id=f"stage-{stage_name.lower()}",
101
+ text=stage_name,
102
+ variant=stage_status if stage_status != "pending" else "default",
103
+ icon=stage_icon,
104
+ size="md",
105
+ )
106
+ )
107
+
108
+ # Progress display
109
+ progress_display = ProgressDisplayComponent(
110
+ id="demo-progress-bar",
111
+ label="Overall Progress",
112
+ value=0.2,
113
+ description="Initializing demonstration...",
114
+ status="info",
115
+ animated=True,
116
+ )
117
+ yield UiComponent(rich_component=progress_display)
118
+
119
+ # Create log viewer for detailed progress
120
+ log_viewer = LogViewerComponent(id="demo-logs", title="Demo Activity Log")
121
+ yield UiComponent(rich_component=log_viewer)
122
+
123
+ # Simulate work with updates
124
+ for i in range(3):
125
+ await asyncio.sleep(1)
126
+
127
+ # Update progress
128
+ progress_value = 0.2 + (i + 1) * 0.2
129
+ step_name = ["Creating components", "Updating progress", "Finalizing demo"][
130
+ i
131
+ ]
132
+
133
+ yield UiComponent(
134
+ rich_component=progress_display.update_progress(
135
+ progress_value, f"Step {i + 2} of 5: {step_name}..."
136
+ )
137
+ )
138
+
139
+ # Update demo card
140
+ yield UiComponent(
141
+ rich_component=demo_card.set_status(
142
+ "running",
143
+ f"Step {i + 2} of 5 completed. Progress: {int(progress_value * 100)}%",
144
+ )
145
+ )
146
+
147
+ # Add log entry
148
+ yield UiComponent(
149
+ rich_component=log_viewer.add_entry(
150
+ f"Completed step: {step_name}", "info"
151
+ )
152
+ )
153
+
154
+ # Update stage badges
155
+ if i == 0:
156
+ yield UiComponent(
157
+ rich_component=BadgeComponent(
158
+ id="stage-components",
159
+ text="Components",
160
+ variant="success",
161
+ icon="✅",
162
+ size="md",
163
+ )
164
+ )
165
+ elif i == 1:
166
+ yield UiComponent(
167
+ rich_component=BadgeComponent(
168
+ id="stage-progress",
169
+ text="Progress",
170
+ variant="success",
171
+ icon="✅",
172
+ size="md",
173
+ )
174
+ )
175
+ yield UiComponent(
176
+ rich_component=BadgeComponent(
177
+ id="stage-logs",
178
+ text="Logs",
179
+ variant="running",
180
+ icon="📋",
181
+ size="md",
182
+ )
183
+ )
184
+
185
+ # Tool execution using primitive components
186
+ tool_status = StatusCardComponent(
187
+ id="demo-tool",
188
+ title="Analyze Data Tool",
189
+ status="running",
190
+ description="Running regression analysis on user_data.csv",
191
+ icon="🔬",
192
+ )
193
+ yield UiComponent(rich_component=tool_status)
194
+
195
+ # Tool progress
196
+ tool_progress = ProgressDisplayComponent(
197
+ id="tool-progress",
198
+ label="Tool Execution",
199
+ value=0.0,
200
+ description="Initializing tool...",
201
+ animated=True,
202
+ )
203
+ yield UiComponent(rich_component=tool_progress)
204
+
205
+ # Tool logs
206
+ tool_logs = LogViewerComponent(id="tool-logs", title="Tool Execution Log")
207
+ yield UiComponent(rich_component=tool_logs)
208
+
209
+ # Simulate tool execution steps
210
+ tool_steps = [
211
+ (0.2, "Loading dataset...", "info"),
212
+ (0.4, "Dataset loaded: 1000 rows, 5 columns", "info"),
213
+ (0.6, "Preprocessing data...", "info"),
214
+ (0.8, "Running regression analysis...", "info"),
215
+ (1.0, "Analysis complete!", "info"),
216
+ ]
217
+
218
+ for progress_val, log_message, log_level in tool_steps:
219
+ await asyncio.sleep(0.5)
220
+
221
+ yield UiComponent(
222
+ rich_component=tool_progress.update_progress(
223
+ progress_val, f"Progress: {int(progress_val * 100)}%"
224
+ )
225
+ )
226
+ yield UiComponent(
227
+ rich_component=tool_logs.add_entry(log_message, log_level)
228
+ )
229
+
230
+ # Complete tool execution
231
+ yield UiComponent(
232
+ rich_component=tool_status.set_status(
233
+ "success",
234
+ "Tool completed successfully. R² = 0.85, strong correlation found.",
235
+ )
236
+ )
237
+
238
+ # Show results using IconText
239
+ yield UiComponent(
240
+ rich_component=IconTextComponent(
241
+ id="tool-results",
242
+ icon="📊",
243
+ text="Analysis Results: R² = 0.85 (Strong correlation)",
244
+ variant="success",
245
+ size="medium",
246
+ )
247
+ )
248
+
249
+ # Update final stage badge
250
+ yield UiComponent(
251
+ rich_component=BadgeComponent(
252
+ id="stage-logs", text="Logs", variant="success", icon="✅", size="md"
253
+ )
254
+ )
255
+ yield UiComponent(
256
+ rich_component=BadgeComponent(
257
+ id="stage-complete",
258
+ text="Complete",
259
+ variant="success",
260
+ icon="🎉",
261
+ size="md",
262
+ )
263
+ )
264
+
265
+ # Final updates
266
+ yield UiComponent(
267
+ rich_component=progress_display.update_progress(
268
+ 1.0, "Demo completed successfully!"
269
+ )
270
+ )
271
+
272
+ yield UiComponent(
273
+ rich_component=demo_card.set_status(
274
+ "success", "Primitive components demonstration finished successfully!"
275
+ )
276
+ )
277
+
278
+ # Add final log entry
279
+ yield UiComponent(
280
+ rich_component=tool_logs.add_entry("Demo completed successfully!", "info")
281
+ )
282
+
283
+ # Add final text response
284
+ yield UiComponent(
285
+ rich_component=RichTextComponent(
286
+ content=f"""## Primitive Components Demo Complete!
287
+
288
+ I've demonstrated the new primitive component system:
289
+
290
+ - **Status Cards**: Domain-agnostic status displays that work for any process
291
+ - **Progress Displays**: Reusable progress indicators with animations
292
+ - **Log Viewers**: Structured log display for any activity
293
+ - **Badges**: Flexible status and category indicators
294
+ - **Icon Text**: Composable icon+text combinations
295
+
296
+ ### Key Benefits of Primitive Components:
297
+
298
+ - **Separation of Concerns**: UI components are purely presentational
299
+ - **Reusability**: Components work across different domains and tools
300
+ - **Composability**: Tools build exactly the UI they need from primitives
301
+ - **Maintainability**: Business logic changes don't affect UI components
302
+ - **Extensibility**: New tools don't require new component types
303
+
304
+ **Primitive Components**: Compose UI from domain-agnostic building blocks
305
+ **After**: Tools compose UI from primitive `StatusCard` + `ProgressDisplay` + `LogViewer`
306
+
307
+ Your message was: "{message}"
308
+ """,
309
+ markdown=True,
310
+ )
311
+ )
312
+
313
+
314
+ # CLI compatibility alias
315
+ create_demo_agent = lambda: create_rich_demo_agent()
316
+
317
+
318
+ def create_rich_demo_agent() -> RichComponentsAgent:
319
+ """Create a primitive components demo agent.
320
+
321
+ Returns:
322
+ Configured RichComponentsAgent instance
323
+ """
324
+ llm_service = MockLlmService(response_content="Primitive components demo response")
325
+
326
+ return RichComponentsAgent(
327
+ llm_service=llm_service,
328
+ config=AgentConfig(
329
+ stream_responses=True,
330
+ include_thinking_indicators=False, # We'll use custom status cards
331
+ ),
332
+ )
333
+
334
+
335
+ async def main() -> None:
336
+ """Run the primitive components demo."""
337
+
338
+ # Create agent
339
+ agent = create_rich_demo_agent()
340
+
341
+ # Create a test user
342
+ user = User(
343
+ id="user123", username="demo_user", email="demo@example.com", permissions=[]
344
+ )
345
+
346
+ # Start a conversation
347
+ conversation_id = "primitive_demo_123"
348
+ user_message = "Show me the primitive components demo!"
349
+
350
+ print(f"User: {user_message}")
351
+ print("Agent response (primitive components):")
352
+ print("=" * 50)
353
+
354
+ # Send message and display components
355
+ component_count = 0
356
+ async for component in agent.send_message(
357
+ user=user, message=user_message, conversation_id=conversation_id
358
+ ):
359
+ component_count += 1
360
+ rich_comp = component.rich_component
361
+ component_type = getattr(rich_comp, "type", rich_comp.__class__.__name__)
362
+ component_id = getattr(rich_comp, "id", "N/A")
363
+ lifecycle = getattr(rich_comp, "lifecycle", "N/A")
364
+
365
+ print(
366
+ f"[{component_count:2d}] {component_type} (id: {component_id[:8]}, lifecycle: {lifecycle})"
367
+ )
368
+
369
+ # Show some component details
370
+ if hasattr(rich_comp, "title"):
371
+ print(f" Title: {rich_comp.title}")
372
+ if hasattr(rich_comp, "content") and len(str(rich_comp.content)) < 100:
373
+ print(f" Content: {rich_comp.content}")
374
+ if hasattr(rich_comp, "status"):
375
+ print(f" Status: {rich_comp.status}")
376
+ if (
377
+ hasattr(rich_comp, "value")
378
+ and hasattr(rich_comp.type, "value")
379
+ and rich_comp.type.value == "progress_bar"
380
+ ):
381
+ print(f" Progress: {rich_comp.value:.1%}")
382
+
383
+ print()
384
+
385
+ print("=" * 50)
386
+ print(f"Total components emitted: {component_count}")
387
+
388
+
389
+ def run_interactive() -> None:
390
+ """Entry point for interactive usage."""
391
+ print("Starting Primitive Components Demo...")
392
+ asyncio.run(main())
393
+
394
+
395
+ if __name__ == "__main__":
396
+ run_interactive()
@@ -0,0 +1,223 @@
1
+ """
2
+ Mock example showing how to use the SQL query tool with the Chinook database.
3
+
4
+ This example demonstrates using the RunSqlTool with SqliteRunner and a mock LLM service
5
+ that automatically executes sample SQL queries against the Chinook database.
6
+
7
+ Usage:
8
+ Template: Copy this file and modify for your custom database
9
+ Interactive: python -m vanna.examples.mock_sqlite_example
10
+ REPL: from vanna.examples.mock_sqlite_example import create_demo_agent
11
+ Server: python -m vanna.servers --example mock_sqlite_example
12
+ """
13
+
14
+ import asyncio
15
+ import os
16
+ import random
17
+ import uuid
18
+ from typing import AsyncGenerator, Dict, List, Optional, Type
19
+
20
+ from pydantic import BaseModel, Field
21
+
22
+ from vanna import (
23
+ AgentConfig,
24
+ Agent,
25
+ Tool,
26
+ ToolContext,
27
+ ToolRegistry,
28
+ ToolResult,
29
+ User,
30
+ UiComponent,
31
+ )
32
+ from vanna.core.interfaces import LlmService
33
+ from vanna.core.models import (
34
+ LlmRequest,
35
+ LlmResponse,
36
+ LlmStreamChunk,
37
+ ToolCall,
38
+ ToolSchema,
39
+ )
40
+ from vanna.core.rich_components import (
41
+ CardComponent,
42
+ NotificationComponent,
43
+ ComponentType,
44
+ )
45
+ from vanna.core.simple_components import (
46
+ SimpleTextComponent,
47
+ )
48
+ from vanna.tools import RunSqlTool
49
+ from vanna.integrations.sqlite import SqliteRunner
50
+
51
+
52
+ class MockSqliteLlmService(LlmService):
53
+ """LLM service that exercises the SQLite query tool with sample queries."""
54
+
55
+ def __init__(self, seed: Optional[int] = None):
56
+ self._random = random.Random(seed)
57
+ self._sample_queries = [
58
+ "SELECT name FROM sqlite_master WHERE type='table'",
59
+ "SELECT COUNT(*) as total_customers FROM Customer",
60
+ "SELECT FirstName, LastName FROM Customer LIMIT 5",
61
+ "SELECT Name, Composer FROM Track WHERE Composer IS NOT NULL LIMIT 5",
62
+ "SELECT COUNT(*) as album_count FROM Album",
63
+ "SELECT Name FROM Artist LIMIT 10",
64
+ "SELECT AVG(Total) as avg_invoice_total FROM Invoice",
65
+ "SELECT GenreId, COUNT(*) as track_count FROM Track GROUP BY GenreId LIMIT 5",
66
+ ]
67
+
68
+ async def send_request(self, request: LlmRequest) -> LlmResponse:
69
+ """Handle non-streaming SQLite interactions."""
70
+ await asyncio.sleep(0.1)
71
+ return self._build_response(request)
72
+
73
+ async def stream_request(
74
+ self, request: LlmRequest
75
+ ) -> AsyncGenerator[LlmStreamChunk, None]:
76
+ """Provide streaming compatibility by yielding a single chunk."""
77
+ await asyncio.sleep(0.1)
78
+ response = self._build_response(request)
79
+
80
+ if response.tool_calls:
81
+ yield LlmStreamChunk(tool_calls=response.tool_calls)
82
+ if response.content is not None:
83
+ yield LlmStreamChunk(
84
+ content=response.content, finish_reason=response.finish_reason
85
+ )
86
+ else:
87
+ yield LlmStreamChunk(finish_reason=response.finish_reason)
88
+
89
+ async def validate_tools(self, tools: List[ToolSchema]) -> List[str]:
90
+ """Mock validation - no errors."""
91
+ return []
92
+
93
+ def _build_response(self, request: LlmRequest) -> LlmResponse:
94
+ """Create a response that either calls the tool or explains its result."""
95
+ last_message = request.messages[-1] if request.messages else None
96
+
97
+ if last_message and last_message.role == "tool":
98
+ # Respond to tool result
99
+ result = last_message.content or "No result provided"
100
+ return LlmResponse(
101
+ content=f"Here's what I found in the database:\n\n{result}",
102
+ finish_reason="stop",
103
+ usage={
104
+ "prompt_tokens": 40,
105
+ "completion_tokens": 20,
106
+ "total_tokens": 60,
107
+ },
108
+ )
109
+
110
+ # Generate a random SQL query
111
+ sql_query = self._random.choice(self._sample_queries)
112
+ tool_call = ToolCall(
113
+ id=f"call_{uuid.uuid4().hex[:8]}",
114
+ name="run_sql",
115
+ arguments={"sql": sql_query},
116
+ )
117
+
118
+ return LlmResponse(
119
+ content="Let me query the Chinook database for you...",
120
+ tool_calls=[tool_call],
121
+ finish_reason="tool_calls",
122
+ usage={"prompt_tokens": 30, "completion_tokens": 10, "total_tokens": 40},
123
+ )
124
+
125
+
126
+ def create_demo_agent() -> Agent:
127
+ """Create a demo agent with SQLite query tool.
128
+
129
+ Returns:
130
+ Configured Agent with SQLite tool and mock LLM
131
+ """
132
+ # Get the path to the Chinook database
133
+ database_path = os.path.join(
134
+ os.path.dirname(__file__), "..", "..", "Chinook.sqlite"
135
+ )
136
+ database_path = os.path.abspath(database_path)
137
+
138
+ if not os.path.exists(database_path):
139
+ raise FileNotFoundError(
140
+ f"Chinook database not found at {database_path}. Please download it from https://vanna.ai/Chinook.sqlite"
141
+ )
142
+
143
+ tool_registry = ToolRegistry()
144
+ sqlite_runner = SqliteRunner(database_path=database_path)
145
+ sql_tool = RunSqlTool(sql_runner=sqlite_runner)
146
+ tool_registry.register(sql_tool)
147
+
148
+ llm_service = MockSqliteLlmService()
149
+
150
+ return Agent(
151
+ llm_service=llm_service,
152
+ tool_registry=tool_registry,
153
+ config=AgentConfig(
154
+ stream_responses=False,
155
+ include_thinking_indicators=False,
156
+ ),
157
+ )
158
+
159
+
160
+ async def main() -> None:
161
+ """Run the mock SQLite example."""
162
+
163
+ # Create agent using factory function
164
+ agent = create_demo_agent()
165
+ tool_registry = agent.tool_registry
166
+
167
+ # Create a test user
168
+ user = User(id="user123", username="testuser", permissions=[])
169
+
170
+ # Test the tool directly
171
+ print("Testing SQL tool directly:")
172
+ tool_call = ToolCall(
173
+ id="test123",
174
+ name="run_sql",
175
+ arguments={"sql": "SELECT name FROM sqlite_master WHERE type='table'"},
176
+ )
177
+
178
+ context = ToolContext(user=user, conversation_id="test", request_id="test")
179
+
180
+ result = await tool_registry.execute(tool_call, context)
181
+ print(
182
+ f"Tables in database:\n{result.result_for_llm if result.success else result.error}"
183
+ )
184
+
185
+ # Show available tools
186
+ schemas = await tool_registry.get_schemas(user)
187
+ print(f"\nAvailable tools for user: {[schema.name for schema in schemas]}")
188
+
189
+ # Demonstrate the mock LLM triggering SQL queries
190
+ print("\n" + "=" * 50)
191
+ print("Agent conversation demo:")
192
+ print("=" * 50)
193
+
194
+ conversation_id = "sqlite-demo"
195
+
196
+ # Run multiple queries to show different results
197
+ for i in range(3):
198
+ print(f"\n--- Query {i + 1} ---")
199
+ async for component in agent.send_message(
200
+ user=user,
201
+ message=f"Show me some data from the database (query {i + 1})",
202
+ conversation_id=conversation_id,
203
+ ):
204
+ if (
205
+ hasattr(component.rich_component, "content")
206
+ and component.rich_component.content
207
+ ):
208
+ print(f"Assistant: {component.rich_component.content}")
209
+ elif component.simple_component and hasattr(
210
+ component.simple_component, "text"
211
+ ):
212
+ print(f"Assistant: {component.simple_component.text}")
213
+
214
+
215
+ def run_interactive() -> None:
216
+ """Entry point for interactive usage."""
217
+ print("Starting mock SQLite example...")
218
+ print("This example uses the Chinook database to demonstrate SQL queries.")
219
+ asyncio.run(main())
220
+
221
+
222
+ if __name__ == "__main__":
223
+ run_interactive()
@@ -0,0 +1,83 @@
1
+ """
2
+ OpenAI example using OpenAILlmService.
3
+
4
+ Loads environment from .env (via python-dotenv), uses model 'gpt-5' by default,
5
+ and sends a simple message through a Agent.
6
+
7
+ Run:
8
+ PYTHONPATH=. python vanna/examples/openai_quickstart.py
9
+ """
10
+
11
+ import asyncio
12
+ import importlib.util
13
+ import os
14
+ import sys
15
+
16
+
17
+ def ensure_env() -> None:
18
+ if importlib.util.find_spec("dotenv") is not None:
19
+ from dotenv import load_dotenv
20
+
21
+ # Load from local .env without overriding existing env
22
+ load_dotenv(dotenv_path=os.path.join(os.getcwd(), ".env"), override=False)
23
+ else:
24
+ print(
25
+ "[warn] python-dotenv not installed; skipping .env load. Install with: pip install python-dotenv"
26
+ )
27
+
28
+ if not os.getenv("OPENAI_API_KEY"):
29
+ print(
30
+ "[error] OPENAI_API_KEY is not set. Add it to your environment or .env file."
31
+ )
32
+ sys.exit(1)
33
+
34
+
35
+ async def main() -> None:
36
+ ensure_env()
37
+
38
+ # Lazy import after env load to allow custom base_url/org via env
39
+ try:
40
+ from vanna.integrations.anthropic import OpenAILlmService
41
+ except ImportError as e:
42
+ print(
43
+ "[error] openai extra not installed. Install with: pip install -e .[openai]"
44
+ )
45
+ raise
46
+
47
+ from vanna import AgentConfig, Agent, User
48
+ from vanna.core.registry import ToolRegistry
49
+ from vanna.tools import ListFilesTool
50
+
51
+ # Default to 'gpt-5' for this demo; override via $OPENAI_MODEL if desired
52
+ model = os.getenv("OPENAI_MODEL", "gpt-5")
53
+ print(f"Using OpenAI model: {model}")
54
+
55
+ llm = OpenAILlmService(model=model)
56
+
57
+ # Create tool registry and register the list_files tool
58
+ tool_registry = ToolRegistry()
59
+ list_files_tool = ListFilesTool()
60
+ tool_registry.register(list_files_tool)
61
+
62
+ # Some models (e.g., reasoning/gpt-5) only support the default temperature=1.0
63
+ agent = Agent(
64
+ llm_service=llm,
65
+ config=AgentConfig(stream_responses=False, temperature=1.0),
66
+ tool_registry=tool_registry,
67
+ )
68
+
69
+ user = User(id="demo-user", username="demo")
70
+ conversation_id = "openai-demo"
71
+
72
+ print("Sending: 'List the files in the current directory'\n")
73
+ async for component in agent.send_message(
74
+ user=user,
75
+ message="List the files in the current directory",
76
+ conversation_id=conversation_id,
77
+ ):
78
+ if hasattr(component, "content") and component.content:
79
+ print("Assistant:", component.content)
80
+
81
+
82
+ if __name__ == "__main__":
83
+ asyncio.run(main())