vanna 0.7.9__py3-none-any.whl → 2.0.0rc1__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 +439 -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 +224 -217
  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.0rc1.dist-info/METADATA +868 -0
  251. vanna-2.0.0rc1.dist-info/RECORD +289 -0
  252. vanna-2.0.0rc1.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.9.dist-info/METADATA +0 -408
  265. vanna-0.7.9.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.9.dist-info → vanna-2.0.0rc1.dist-info}/WHEEL +0 -0
  302. {vanna-0.7.9.dist-info → vanna-2.0.0rc1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,111 @@
1
+ """
2
+ Request and response models for server endpoints.
3
+ """
4
+
5
+ import time
6
+ import uuid
7
+ from typing import Any, Dict, List, Optional, Union
8
+
9
+ from pydantic import BaseModel, Field
10
+
11
+ from ...components import UiComponent, RichComponent
12
+ from ...core.component_manager import ComponentUpdate
13
+ from ...core.user.request_context import RequestContext
14
+
15
+
16
+ class ChatRequest(BaseModel):
17
+ """Request model for chat endpoints."""
18
+
19
+ message: str = Field(description="User message")
20
+ conversation_id: Optional[str] = Field(default=None, description="Conversation ID")
21
+ request_id: Optional[str] = Field(
22
+ default=None, description="Request ID for tracing"
23
+ )
24
+ request_context: RequestContext = Field(
25
+ default_factory=RequestContext,
26
+ description="Request context for user resolution",
27
+ )
28
+ metadata: Dict[str, Any] = Field(
29
+ default_factory=dict, description="Additional metadata"
30
+ )
31
+
32
+
33
+ class ChatStreamChunk(BaseModel):
34
+ """Single chunk in a streaming chat response."""
35
+
36
+ rich: Dict[str, Any] = Field(description="Rich component data for advanced UIs")
37
+ simple: Optional[Dict[str, Any]] = Field(
38
+ default=None, description="Simple component data for basic UIs"
39
+ )
40
+
41
+ # Stream metadata
42
+ conversation_id: str = Field(description="Conversation ID")
43
+ request_id: str = Field(description="Request ID")
44
+ timestamp: float = Field(default_factory=time.time, description="Timestamp")
45
+
46
+ @classmethod
47
+ def from_component(
48
+ cls,
49
+ component: Union[UiComponent, RichComponent],
50
+ conversation_id: str,
51
+ request_id: str,
52
+ ) -> "ChatStreamChunk":
53
+ """Create chunk from UI component or rich component."""
54
+
55
+ if isinstance(component, UiComponent):
56
+ # Full UiComponent with both rich and simple
57
+ rich_data = component.rich_component.serialize_for_frontend()
58
+ simple_data = None
59
+ if component.simple_component:
60
+ simple_data = component.simple_component.serialize_for_frontend()
61
+
62
+ return cls(
63
+ rich=rich_data,
64
+ simple=simple_data,
65
+ conversation_id=conversation_id,
66
+ request_id=request_id,
67
+ )
68
+
69
+ # Rich component only (no simple fallback)
70
+ rich_data = component.serialize_for_frontend()
71
+ return cls(
72
+ rich=rich_data,
73
+ simple=None,
74
+ conversation_id=conversation_id,
75
+ request_id=request_id,
76
+ )
77
+
78
+ @classmethod
79
+ def from_component_update(
80
+ cls, update: ComponentUpdate, conversation_id: str, request_id: str
81
+ ) -> "ChatStreamChunk":
82
+ """Create chunk from component update."""
83
+ update_payload = update.serialize_for_frontend()
84
+ return cls(
85
+ rich=update_payload,
86
+ simple=None, # Component updates don't have simple representations
87
+ conversation_id=conversation_id,
88
+ request_id=request_id,
89
+ )
90
+
91
+
92
+ class ChatResponse(BaseModel):
93
+ """Complete chat response for polling endpoints."""
94
+
95
+ chunks: List[ChatStreamChunk] = Field(description="Response chunks")
96
+ conversation_id: str = Field(description="Conversation ID")
97
+ request_id: str = Field(description="Request ID")
98
+ total_chunks: int = Field(description="Total number of chunks")
99
+
100
+ @classmethod
101
+ def from_chunks(cls, chunks: List[ChatStreamChunk]) -> "ChatResponse":
102
+ """Create response from chunks."""
103
+ if not chunks:
104
+ return cls(chunks=[], conversation_id="", request_id="", total_chunks=0)
105
+
106
+ return cls(
107
+ chunks=chunks,
108
+ conversation_id=chunks[0].conversation_id,
109
+ request_id=chunks[0].request_id,
110
+ total_chunks=len(chunks),
111
+ )
@@ -0,0 +1,141 @@
1
+ # """
2
+ # Rich component-aware chat handling logic.
3
+ # """
4
+
5
+ # import uuid
6
+ # from typing import AsyncGenerator, Callable, List, Optional, Union
7
+
8
+ # from ...core import Agent, User
9
+ # from ...core.rich_components import RichComponent
10
+ # from ...core.component_manager import ComponentManager, ComponentUpdate
11
+ # from .models import ChatRequest, ChatResponse, ChatStreamChunk
12
+
13
+
14
+ # class RichChatHandler:
15
+ # """Rich component-aware chat handling logic."""
16
+
17
+ # def __init__(
18
+ # self,
19
+ # agent: Agent,
20
+ # default_user_factory: Optional[Callable[[Optional[str]], User]] = None,
21
+ # ):
22
+ # """Initialize rich chat handler.
23
+
24
+ # Args:
25
+ # agent: The agent to handle chat requests
26
+ # default_user_factory: Function to create default user from user_id
27
+ # """
28
+ # self.agent = agent
29
+ # self.default_user_factory = default_user_factory or self._create_default_user
30
+ # self.component_managers: dict[str, ComponentManager] = {} # Per conversation
31
+
32
+ # async def handle_stream(
33
+ # self, request: ChatRequest
34
+ # ) -> AsyncGenerator[ChatStreamChunk, None]:
35
+ # """Stream chat responses with rich component support.
36
+
37
+ # Args:
38
+ # request: Chat request
39
+
40
+ # Yields:
41
+ # Chat stream chunks including rich component updates
42
+ # """
43
+ # user = self._resolve_user(request.user_id)
44
+ # conversation_id = request.conversation_id or self._generate_conversation_id()
45
+ # request_id = request.request_id or str(uuid.uuid4())
46
+
47
+ # # Get or create component manager for this conversation
48
+ # if conversation_id not in self.component_managers:
49
+ # self.component_managers[conversation_id] = ComponentManager()
50
+
51
+ # component_manager = self.component_managers[conversation_id]
52
+
53
+ # async for component in self.agent.send_message(
54
+ # conversation_id=conversation_id,
55
+ # user=user,
56
+ # message=request.message,
57
+ # request_id=request_id,
58
+ # ):
59
+ # if isinstance(component, RichComponent):
60
+ # # Handle rich component through manager
61
+ # update = component_manager.emit(component)
62
+ # yield ChatStreamChunk.from_component_update(update, conversation_id, request_id)
63
+ # else:
64
+ # # Handle legacy components
65
+ # yield ChatStreamChunk.from_component(component, conversation_id, request_id)
66
+
67
+ # async def handle_poll(self, request: ChatRequest) -> ChatResponse:
68
+ # """Handle polling request with rich component support.
69
+
70
+ # Args:
71
+ # request: Chat request
72
+
73
+ # Returns:
74
+ # Complete chat response with all components
75
+ # """
76
+ # chunks: List[ChatStreamChunk] = []
77
+
78
+ # async for chunk in self.handle_stream(request):
79
+ # chunks.append(chunk)
80
+
81
+ # return ChatResponse.from_chunks(chunks)
82
+
83
+ # def get_component_manager(self, conversation_id: str) -> Optional[ComponentManager]:
84
+ # """Get the component manager for a conversation."""
85
+ # return self.component_managers.get(conversation_id)
86
+
87
+ # def get_component(self, conversation_id: str, component_id: str) -> Optional[RichComponent]:
88
+ # """Get a specific component from a conversation."""
89
+ # manager = self.get_component_manager(conversation_id)
90
+ # return manager.get_component(component_id) if manager else None
91
+
92
+ # def get_all_components(self, conversation_id: str) -> List[RichComponent]:
93
+ # """Get all components in a conversation."""
94
+ # manager = self.get_component_manager(conversation_id)
95
+ # return manager.get_all_components() if manager else []
96
+
97
+ # def update_component(
98
+ # self,
99
+ # conversation_id: str,
100
+ # component_id: str,
101
+ # **updates
102
+ # ) -> Optional[ComponentUpdate]:
103
+ # """Update a component in a conversation."""
104
+ # manager = self.get_component_manager(conversation_id)
105
+ # return manager.update_component(component_id, **updates) if manager else None
106
+
107
+ # def remove_component(
108
+ # self,
109
+ # conversation_id: str,
110
+ # component_id: str
111
+ # ) -> Optional[ComponentUpdate]:
112
+ # """Remove a component from a conversation."""
113
+ # manager = self.get_component_manager(conversation_id)
114
+ # return manager.remove_component(component_id) if manager else None
115
+
116
+ # def clear_conversation_components(self, conversation_id: str):
117
+ # """Clear all components for a conversation."""
118
+ # if conversation_id in self.component_managers:
119
+ # del self.component_managers[conversation_id]
120
+
121
+ # def _resolve_user(self, user_id: Optional[str]) -> User:
122
+ # """Resolve user from ID or create default."""
123
+ # if user_id:
124
+ # # In a real implementation, you'd fetch from a user store
125
+ # return User(id=user_id, username=f"user_{user_id}", email="", permissions=[])
126
+
127
+ # return self.default_user_factory(user_id)
128
+
129
+ # def _create_default_user(self, user_id: Optional[str]) -> User:
130
+ # """Create a default user."""
131
+ # user_id = user_id or "anonymous"
132
+ # return User(
133
+ # id=user_id,
134
+ # username=f"user_{user_id}",
135
+ # email="",
136
+ # permissions=[]
137
+ # )
138
+
139
+ # def _generate_conversation_id(self) -> str:
140
+ # """Generate a new conversation ID."""
141
+ # return str(uuid.uuid4())
@@ -0,0 +1,331 @@
1
+ """
2
+ HTML templates for Vanna Agents servers.
3
+ """
4
+
5
+ from typing import Optional
6
+
7
+
8
+ def get_vanna_component_script(
9
+ dev_mode: bool = False,
10
+ static_path: str = "/static",
11
+ cdn_url: str = "https://img.vanna.ai/vanna-components.js",
12
+ ) -> str:
13
+ """Get the script tag for loading Vanna web components.
14
+
15
+ Args:
16
+ dev_mode: If True, load from local static files
17
+ static_path: Path to static assets in dev mode
18
+ cdn_url: CDN URL for production
19
+
20
+ Returns:
21
+ HTML script tag for loading components
22
+ """
23
+ if dev_mode:
24
+ return (
25
+ f'<script type="module" src="{static_path}/vanna-components.js"></script>'
26
+ )
27
+ else:
28
+ return f'<script type="module" src="{cdn_url}"></script>'
29
+
30
+
31
+ def get_index_html(
32
+ dev_mode: bool = False,
33
+ static_path: str = "/static",
34
+ cdn_url: str = "https://img.vanna.ai/vanna-components.js",
35
+ api_base_url: str = "",
36
+ ) -> str:
37
+ """Generate index HTML with configurable component loading.
38
+
39
+ Args:
40
+ dev_mode: If True, load components from local static files
41
+ static_path: Path to static assets in dev mode
42
+ cdn_url: CDN URL for production components
43
+ api_base_url: Base URL for API endpoints
44
+
45
+ Returns:
46
+ Complete HTML page as string
47
+ """
48
+ component_script = get_vanna_component_script(dev_mode, static_path, cdn_url)
49
+
50
+ return f"""<!DOCTYPE html>
51
+ <html lang="en">
52
+ <head>
53
+ <meta charset="UTF-8">
54
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
55
+ <title>Vanna Agents Chat</title>
56
+ <link rel="preconnect" href="https://fonts.googleapis.com">
57
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
58
+ <link href="https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400;500;600;700&family=Space+Grotesk:wght@300;400;500;600;700&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet">
59
+ <script src="https://cdn.tailwindcss.com"></script>
60
+ <script>
61
+ tailwind.config = {{
62
+ theme: {{
63
+ extend: {{
64
+ colors: {{
65
+ 'vanna-navy': '#023d60',
66
+ 'vanna-cream': '#e7e1cf',
67
+ 'vanna-teal': '#15a8a8',
68
+ 'vanna-orange': '#fe5d26',
69
+ 'vanna-magenta': '#bf1363',
70
+ }},
71
+ fontFamily: {{
72
+ 'sans': ['Space Grotesk', 'ui-sans-serif', 'system-ui'],
73
+ 'serif': ['Roboto Slab', 'ui-serif', 'Georgia'],
74
+ 'mono': ['Space Mono', 'ui-monospace', 'monospace'],
75
+ }}
76
+ }}
77
+ }}
78
+ }}
79
+ </script>
80
+ <style>
81
+ body {{
82
+ background: linear-gradient(to bottom, #e7e1cf, #ffffff, #e7e1cf);
83
+ min-height: 100vh;
84
+ position: relative;
85
+ overflow-x: hidden;
86
+ }}
87
+
88
+ /* Background decorations matching landing page */
89
+ body::before {{
90
+ content: '';
91
+ position: fixed;
92
+ inset: 0;
93
+ pointer-events: none;
94
+ z-index: 0;
95
+ /* Radial gradients with brand colors */
96
+ background:
97
+ radial-gradient(circle at top left, rgba(21, 168, 168, 0.12), transparent 60%),
98
+ radial-gradient(circle at bottom right, rgba(254, 93, 38, 0.08), transparent 65%);
99
+ }}
100
+
101
+ body::after {{
102
+ content: '';
103
+ position: fixed;
104
+ inset: 0;
105
+ pointer-events: none;
106
+ z-index: 0;
107
+ /* Dot pattern with retro computing aesthetic */
108
+ background-image: radial-gradient(circle at 2px 2px, rgba(2, 61, 96, 0.3) 1px, transparent 0);
109
+ background-size: 32px 32px;
110
+ /* Grid overlay */
111
+ background-image:
112
+ radial-gradient(circle at 2px 2px, rgba(2, 61, 96, 0.3) 1px, transparent 0),
113
+ linear-gradient(rgba(2, 61, 96, 0.1) 1px, transparent 1px),
114
+ linear-gradient(90deg, rgba(2, 61, 96, 0.1) 1px, transparent 1px);
115
+ background-size: 32px 32px, 100px 100px, 100px 100px;
116
+ }}
117
+
118
+ /* Ensure content is above background */
119
+ body > * {{
120
+ position: relative;
121
+ z-index: 1;
122
+ }}
123
+
124
+ vanna-chat {{
125
+ width: 100%;
126
+ height: 100%;
127
+ display: block;
128
+ }}
129
+ </style>
130
+ {component_script}
131
+ </head>
132
+ <body>
133
+ <div class="max-w-6xl mx-auto p-5">
134
+ <!-- Header -->
135
+ <div class="text-center mb-8">
136
+ <h1 class="text-4xl font-bold text-vanna-navy mb-2 font-serif">Vanna Agents</h1>
137
+ <p class="text-lg font-mono font-bold text-vanna-teal mb-4">DATA-FIRST AGENTS</p>
138
+ <p class="text-slate-600 mb-4">Interactive AI Assistant powered by Vanna Agents Framework</p>
139
+ <a href="javascript:window.location='view-source:'+window.location.href" class="inline-flex items-center gap-2 px-4 py-2 bg-vanna-teal text-white text-sm font-medium rounded-lg hover:bg-vanna-navy transition">
140
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
141
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"/>
142
+ </svg>
143
+ View Page Source
144
+ </a>
145
+ </div>
146
+
147
+ {(' <div class="bg-vanna-orange/10 border border-vanna-orange/30 rounded-lg p-3 mb-5 text-vanna-orange text-sm font-medium">📦 Development Mode: Loading components from local assets</div>' if dev_mode else "")}
148
+
149
+ <!-- Login Form -->
150
+ <div id="loginContainer" class="max-w-md mx-auto mb-10 bg-white p-8 rounded-xl shadow-lg border border-vanna-teal/30">
151
+ <div class="text-center mb-6">
152
+ <h2 class="text-2xl font-semibold text-vanna-navy mb-2 font-serif">Login to Continue</h2>
153
+ <p class="text-sm text-slate-600">Select your email to access the chat</p>
154
+ </div>
155
+
156
+ <div class="mb-5">
157
+ <label for="emailInput" class="block mb-2 text-sm font-medium text-vanna-navy">Email Address</label>
158
+ <select
159
+ id="emailInput"
160
+ class="w-full px-4 py-3 text-sm border border-vanna-teal/30 rounded-lg focus:outline-none focus:ring-2 focus:ring-vanna-teal focus:border-transparent bg-white"
161
+ >
162
+ <option value="">Select an email...</option>
163
+ <option value="admin@example.com">admin@example.com</option>
164
+ <option value="user@example.com">user@example.com</option>
165
+ </select>
166
+ </div>
167
+
168
+ <button id="loginButton" class="w-full px-4 py-3 bg-vanna-teal text-white text-sm font-medium rounded-lg hover:bg-vanna-navy focus:outline-none focus:ring-2 focus:ring-vanna-teal focus:ring-offset-2 transition disabled:bg-gray-400 disabled:cursor-not-allowed">
169
+ Continue
170
+ </button>
171
+
172
+ <div class="mt-5 p-3 bg-vanna-teal/10 border-l-4 border-vanna-teal rounded text-xs text-vanna-navy leading-relaxed">
173
+ <strong>Demo Mode:</strong> This is a frontend-only authentication demo.
174
+ Your email will be stored as a cookie and automatically sent with all API requests.
175
+ </div>
176
+ </div>
177
+
178
+ <!-- Logged In Status (hidden by default) -->
179
+ <div id="loggedInStatus" class="hidden text-center p-4 bg-vanna-teal/10 border border-vanna-teal/30 rounded-lg mb-5">
180
+ Logged in as <span id="loggedInEmail" class="font-semibold text-vanna-navy"></span>
181
+ <br>
182
+ <button id="logoutButton" class="mt-2 px-3 py-1.5 bg-vanna-navy text-white text-xs rounded hover:bg-vanna-teal transition">
183
+ Logout
184
+ </button>
185
+ </div>
186
+
187
+ <!-- Chat Container (hidden by default) -->
188
+ <div id="chatSections" class="hidden">
189
+ <div class="bg-white rounded-xl shadow-lg h-[600px] overflow-hidden border border-vanna-teal/30">
190
+ <vanna-chat
191
+ api-base="{api_base_url}"
192
+ sse-endpoint="{api_base_url}/api/vanna/v2/chat_sse"
193
+ ws-endpoint="{api_base_url}/api/vanna/v2/chat_websocket"
194
+ poll-endpoint="{api_base_url}/api/vanna/v2/chat_poll">
195
+ </vanna-chat>
196
+ </div>
197
+
198
+ <div class="mt-8 p-5 bg-white rounded-lg shadow border border-vanna-teal/30">
199
+ <h3 class="text-lg font-semibold text-vanna-navy mb-3 font-serif">API Endpoints</h3>
200
+ <ul class="space-y-2">
201
+ <li class="p-2 bg-vanna-cream/50 rounded font-mono text-sm">
202
+ <span class="font-bold text-vanna-teal mr-2">POST</span>{api_base_url}/api/vanna/v2/chat_sse - Server-Sent Events streaming
203
+ </li>
204
+ <li class="p-2 bg-vanna-cream/50 rounded font-mono text-sm">
205
+ <span class="font-bold text-vanna-teal mr-2">WS</span>{api_base_url}/api/vanna/v2/chat_websocket - WebSocket real-time chat
206
+ </li>
207
+ <li class="p-2 bg-vanna-cream/50 rounded font-mono text-sm">
208
+ <span class="font-bold text-vanna-teal mr-2">POST</span>{api_base_url}/api/vanna/v2/chat_poll - Request/response polling
209
+ </li>
210
+ <li class="p-2 bg-vanna-cream/50 rounded font-mono text-sm">
211
+ <span class="font-bold text-vanna-teal mr-2">GET</span>{api_base_url}/health - Health check
212
+ </li>
213
+ </ul>
214
+ </div>
215
+ </div>
216
+ </div>
217
+
218
+ <script>
219
+ // Cookie helpers
220
+ const getCookie = (name) => {{
221
+ const value = `; ${{document.cookie}}`;
222
+ const parts = value.split(`; ${{name}}=`);
223
+ return parts.length === 2 ? parts.pop().split(';').shift() : null;
224
+ }};
225
+
226
+ const setCookie = (name, value) => {{
227
+ const expires = new Date(Date.now() + 365 * 864e5).toUTCString();
228
+ document.cookie = `${{name}}=${{value}}; expires=${{expires}}; path=/; SameSite=Lax`;
229
+ }};
230
+
231
+ const deleteCookie = (name) => {{
232
+ document.cookie = `${{name}}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
233
+ }};
234
+
235
+ // Login/Logout
236
+ document.addEventListener('DOMContentLoaded', () => {{
237
+ const email = getCookie('vanna_email');
238
+
239
+ // Check if already logged in
240
+ if (email) {{
241
+ loginContainer.classList.add('hidden');
242
+ loggedInStatus.classList.remove('hidden');
243
+ chatSections.classList.remove('hidden');
244
+ loggedInEmail.textContent = email;
245
+ }}
246
+
247
+ // Login button
248
+ loginButton.addEventListener('click', () => {{
249
+ const email = emailInput.value.trim();
250
+ if (!email) {{
251
+ alert('Please select an email address');
252
+ return;
253
+ }}
254
+ setCookie('vanna_email', email);
255
+ loginContainer.classList.add('hidden');
256
+ loggedInStatus.classList.remove('hidden');
257
+ chatSections.classList.remove('hidden');
258
+ loggedInEmail.textContent = email;
259
+ }});
260
+
261
+ // Logout button
262
+ logoutButton.addEventListener('click', () => {{
263
+ deleteCookie('vanna_email');
264
+ loginContainer.classList.remove('hidden');
265
+ loggedInStatus.classList.add('hidden');
266
+ chatSections.classList.add('hidden');
267
+ emailInput.value = '';
268
+ }});
269
+
270
+ // Enter key
271
+ emailInput.addEventListener('keypress', (e) => {{
272
+ if (e.key === 'Enter') loginButton.click();
273
+ }});
274
+ }});
275
+ </script>
276
+
277
+ <script>
278
+ // Artifact demo event listener
279
+ document.addEventListener('DOMContentLoaded', () => {{
280
+ const vannaChat = document.querySelector('vanna-chat');
281
+
282
+ if (vannaChat) {{
283
+ // Add artifact event listener to demonstrate external rendering
284
+ vannaChat.addEventListener('artifact-opened', (event) => {{
285
+ const {{ artifactId, type, title, trigger }} = event.detail;
286
+
287
+ console.log('🎨 Artifact Event:', {{ artifactId, type, title, trigger }});
288
+
289
+ // For demo: open all artifacts externally
290
+ setTimeout(() => {{
291
+ const newWindow = window.open('', '_blank', 'width=900,height=700');
292
+ if (newWindow) {{
293
+ newWindow.document.write(event.detail.getStandaloneHTML());
294
+ newWindow.document.close();
295
+ newWindow.document.title = title || 'Vanna Artifact';
296
+ console.log(`📱 Opened ${{title}} in new window`);
297
+ }}
298
+ }}, 100);
299
+
300
+ // Prevent default in-chat rendering
301
+ event.detail.preventDefault();
302
+ console.log('✋ Showing placeholder in chat instead of full artifact');
303
+ }});
304
+
305
+ console.log('🎯 Artifact demo mode: All artifacts will open externally');
306
+ }}
307
+ }});
308
+
309
+ // Fallback if web component doesn't load
310
+ if (!customElements.get('vanna-chat')) {{
311
+ setTimeout(() => {{
312
+ if (!customElements.get('vanna-chat')) {{
313
+ document.querySelector('vanna-chat').innerHTML = `
314
+ <div class="p-10 text-center text-gray-600">
315
+ <h3 class="text-xl font-semibold mb-2">Vanna Chat Component</h3>
316
+ <p class="mb-2">Web component failed to load. Please check your connection.</p>
317
+ <p class="text-sm text-gray-400">
318
+ {("Loading from: local static assets" if dev_mode else f"Loading from: {cdn_url}")}
319
+ </p>
320
+ </div>
321
+ `;
322
+ }}
323
+ }}, 2000);
324
+ }}
325
+ </script>
326
+ </body>
327
+ </html>"""
328
+
329
+
330
+ # Backward compatibility - default production HTML
331
+ INDEX_HTML = get_index_html()
@@ -0,0 +1,7 @@
1
+ """
2
+ CLI components for Vanna Agents servers.
3
+ """
4
+
5
+ from .server_runner import ExampleAgentLoader
6
+
7
+ __all__ = ["ExampleAgentLoader"]