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,137 @@
1
+ """
2
+ Flask route implementations for Vanna Agents.
3
+ """
4
+
5
+ import asyncio
6
+ import json
7
+ import traceback
8
+ from typing import Any, AsyncGenerator, Dict, Generator, Optional, Union
9
+
10
+ from flask import Flask, Response, jsonify, request
11
+
12
+ from ..base import ChatHandler, ChatRequest
13
+ from ..base.templates import get_index_html
14
+ from ...core.user.request_context import RequestContext
15
+
16
+
17
+ def register_chat_routes(
18
+ app: Flask, chat_handler: ChatHandler, config: Optional[Dict[str, Any]] = None
19
+ ) -> None:
20
+ """Register chat routes on Flask app.
21
+
22
+ Args:
23
+ app: Flask application
24
+ chat_handler: Chat handler instance
25
+ config: Server configuration
26
+ """
27
+ config = config or {}
28
+
29
+ @app.route("/")
30
+ def index() -> str:
31
+ """Serve the main chat interface."""
32
+ dev_mode = config.get("dev_mode", False)
33
+ cdn_url = config.get("cdn_url", "https://img.vanna.ai/vanna-components.js")
34
+ api_base_url = config.get("api_base_url", "")
35
+
36
+ return get_index_html(
37
+ dev_mode=dev_mode, cdn_url=cdn_url, api_base_url=api_base_url
38
+ )
39
+
40
+ @app.route("/api/vanna/v2/chat_sse", methods=["POST"])
41
+ def chat_sse() -> Union[Response, tuple[Response, int]]:
42
+ """Server-Sent Events endpoint for streaming chat."""
43
+ try:
44
+ data = request.get_json()
45
+ if not data:
46
+ return jsonify({"error": "JSON body required"}), 400
47
+
48
+ # Extract request context for user resolution
49
+ data["request_context"] = RequestContext(
50
+ cookies=dict(request.cookies),
51
+ headers=dict(request.headers),
52
+ remote_addr=request.remote_addr,
53
+ query_params=dict(request.args),
54
+ )
55
+
56
+ chat_request = ChatRequest(**data)
57
+ except Exception as e:
58
+ traceback.print_stack()
59
+ traceback.print_exc()
60
+ return jsonify({"error": f"Invalid request: {str(e)}"}), 400
61
+
62
+ def generate() -> Generator[str, None, None]:
63
+ """Generate SSE stream."""
64
+ loop = asyncio.new_event_loop()
65
+ asyncio.set_event_loop(loop)
66
+
67
+ try:
68
+
69
+ async def async_generate() -> AsyncGenerator[str, None]:
70
+ async for chunk in chat_handler.handle_stream(chat_request):
71
+ chunk_json = chunk.model_dump_json()
72
+ yield f"data: {chunk_json}\n\n"
73
+
74
+ gen = async_generate()
75
+ try:
76
+ while True:
77
+ chunk = loop.run_until_complete(gen.__anext__())
78
+ yield chunk
79
+ except StopAsyncIteration:
80
+ yield "data: [DONE]\n\n"
81
+ finally:
82
+ loop.close()
83
+
84
+ return Response(
85
+ generate(),
86
+ mimetype="text/event-stream",
87
+ headers={
88
+ "Cache-Control": "no-cache",
89
+ "Connection": "keep-alive",
90
+ "X-Accel-Buffering": "no", # Disable nginx buffering
91
+ },
92
+ )
93
+
94
+ @app.route("/api/vanna/v2/chat_websocket")
95
+ def chat_websocket() -> tuple[Response, int]:
96
+ """WebSocket endpoint placeholder."""
97
+ return jsonify(
98
+ {
99
+ "error": "WebSocket endpoint not implemented in basic Flask example",
100
+ "suggestion": "Use Flask-SocketIO for WebSocket support",
101
+ }
102
+ ), 501
103
+
104
+ @app.route("/api/vanna/v2/chat_poll", methods=["POST"])
105
+ def chat_poll() -> Union[Response, tuple[Response, int]]:
106
+ """Polling endpoint for chat."""
107
+ try:
108
+ data = request.get_json()
109
+ if not data:
110
+ return jsonify({"error": "JSON body required"}), 400
111
+
112
+ # Extract request context for user resolution
113
+ data["request_context"] = RequestContext(
114
+ cookies=dict(request.cookies),
115
+ headers=dict(request.headers),
116
+ remote_addr=request.remote_addr,
117
+ query_params=dict(request.args),
118
+ )
119
+
120
+ chat_request = ChatRequest(**data)
121
+ except Exception as e:
122
+ traceback.print_stack()
123
+ traceback.print_exc()
124
+ return jsonify({"error": f"Invalid request: {str(e)}"}), 400
125
+
126
+ # Run async handler in new event loop
127
+ loop = asyncio.new_event_loop()
128
+ asyncio.set_event_loop(loop)
129
+ try:
130
+ result = loop.run_until_complete(chat_handler.handle_poll(chat_request))
131
+ return jsonify(result.model_dump())
132
+ except Exception as e:
133
+ traceback.print_stack()
134
+ traceback.print_exc()
135
+ return jsonify({"error": f"Chat failed: {str(e)}"}), 500
136
+ finally:
137
+ loop.close()
@@ -0,0 +1,41 @@
1
+ """Built-in tool implementations."""
2
+
3
+ from .file_system import (
4
+ CommandResult,
5
+ FileSystem,
6
+ ListFilesTool,
7
+ LocalFileSystem,
8
+ ReadFileTool,
9
+ SearchFilesTool,
10
+ WriteFileTool,
11
+ create_file_system_tools,
12
+ )
13
+ from .python import (
14
+ PipInstallTool,
15
+ RunPythonFileTool,
16
+ create_python_tools,
17
+ )
18
+ from vanna.integrations.plotly import PlotlyChartGenerator
19
+ from .run_sql import RunSqlTool
20
+ from .visualize_data import VisualizeDataTool
21
+
22
+ __all__ = [
23
+ # File system
24
+ "FileSystem",
25
+ "LocalFileSystem",
26
+ "ListFilesTool",
27
+ "SearchFilesTool",
28
+ "ReadFileTool",
29
+ "WriteFileTool",
30
+ "create_file_system_tools",
31
+ "CommandResult",
32
+ # Python tools
33
+ "RunPythonFileTool",
34
+ "PipInstallTool",
35
+ "create_python_tools",
36
+ # SQL
37
+ "RunSqlTool",
38
+ # Visualization
39
+ "PlotlyChartGenerator",
40
+ "VisualizeDataTool",
41
+ ]
@@ -0,0 +1,322 @@
1
+ """
2
+ Agent memory tools.
3
+
4
+ This module provides agent memory operations through an abstract AgentMemory interface,
5
+ allowing for different implementations (local vector DB, remote cloud service, etc.).
6
+ The tools access AgentMemory via ToolContext, which is populated by the Agent.
7
+ """
8
+
9
+ import logging
10
+ from typing import Any, Dict, List, Optional, Type
11
+ from pydantic import BaseModel, Field
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ from vanna.core.tool import Tool, ToolContext, ToolResult
16
+ from vanna.core.agent.config import UiFeature
17
+ from vanna.capabilities.agent_memory import AgentMemory
18
+ from vanna.components import (
19
+ UiComponent,
20
+ StatusBarUpdateComponent,
21
+ CardComponent,
22
+ )
23
+
24
+
25
+ class SaveQuestionToolArgsParams(BaseModel):
26
+ """Parameters for saving question-tool-argument combinations."""
27
+
28
+ question: str = Field(description="The original question that was asked")
29
+ tool_name: str = Field(
30
+ description="The name of the tool that was used successfully"
31
+ )
32
+ args: Dict[str, Any] = Field(
33
+ description="The arguments that were passed to the tool"
34
+ )
35
+
36
+
37
+ class SearchSavedCorrectToolUsesParams(BaseModel):
38
+ """Parameters for searching saved tool usage patterns."""
39
+
40
+ question: str = Field(
41
+ description="The question to find similar tool usage patterns for"
42
+ )
43
+ limit: Optional[int] = Field(
44
+ default=10, description="Maximum number of results to return"
45
+ )
46
+ similarity_threshold: Optional[float] = Field(
47
+ default=0.7, description="Minimum similarity score for results (0.0-1.0)"
48
+ )
49
+ tool_name_filter: Optional[str] = Field(
50
+ default=None, description="Filter results to specific tool name"
51
+ )
52
+
53
+
54
+ class SaveTextMemoryParams(BaseModel):
55
+ """Parameters for saving free-form text memories."""
56
+
57
+ content: str = Field(description="The text content to save as a memory")
58
+
59
+
60
+ class SaveQuestionToolArgsTool(Tool[SaveQuestionToolArgsParams]):
61
+ """Tool for saving successful question-tool-argument combinations."""
62
+
63
+ @property
64
+ def name(self) -> str:
65
+ return "save_question_tool_args"
66
+
67
+ @property
68
+ def description(self) -> str:
69
+ return (
70
+ "Save a successful question-tool-argument combination for future reference"
71
+ )
72
+
73
+ def get_args_schema(self) -> Type[SaveQuestionToolArgsParams]:
74
+ return SaveQuestionToolArgsParams
75
+
76
+ async def execute(
77
+ self, context: ToolContext, args: SaveQuestionToolArgsParams
78
+ ) -> ToolResult:
79
+ """Save the tool usage pattern to agent memory."""
80
+ try:
81
+ await context.agent_memory.save_tool_usage(
82
+ question=args.question,
83
+ tool_name=args.tool_name,
84
+ args=args.args,
85
+ context=context,
86
+ success=True,
87
+ )
88
+
89
+ success_msg = (
90
+ f"Successfully saved usage pattern for '{args.tool_name}' tool"
91
+ )
92
+ return ToolResult(
93
+ success=True,
94
+ result_for_llm=success_msg,
95
+ ui_component=UiComponent(
96
+ rich_component=StatusBarUpdateComponent(
97
+ status="success",
98
+ message="Saved to memory",
99
+ detail=f"Saved pattern for '{args.tool_name}'",
100
+ ),
101
+ simple_component=None,
102
+ ),
103
+ )
104
+
105
+ except Exception as e:
106
+ error_message = f"Failed to save memory: {str(e)}"
107
+ return ToolResult(
108
+ success=False,
109
+ result_for_llm=error_message,
110
+ ui_component=UiComponent(
111
+ rich_component=StatusBarUpdateComponent(
112
+ status="error", message="Failed to save memory", detail=str(e)
113
+ ),
114
+ simple_component=None,
115
+ ),
116
+ error=str(e),
117
+ )
118
+
119
+
120
+ class SearchSavedCorrectToolUsesTool(Tool[SearchSavedCorrectToolUsesParams]):
121
+ """Tool for searching saved tool usage patterns."""
122
+
123
+ @property
124
+ def name(self) -> str:
125
+ return "search_saved_correct_tool_uses"
126
+
127
+ @property
128
+ def description(self) -> str:
129
+ return "Search for similar tool usage patterns based on a question"
130
+
131
+ def get_args_schema(self) -> Type[SearchSavedCorrectToolUsesParams]:
132
+ return SearchSavedCorrectToolUsesParams
133
+
134
+ async def execute(
135
+ self, context: ToolContext, args: SearchSavedCorrectToolUsesParams
136
+ ) -> ToolResult:
137
+ """Search for similar tool usage patterns."""
138
+ try:
139
+ results = await context.agent_memory.search_similar_usage(
140
+ question=args.question,
141
+ context=context,
142
+ limit=args.limit or 10,
143
+ similarity_threshold=args.similarity_threshold or 0.7,
144
+ tool_name_filter=args.tool_name_filter,
145
+ )
146
+
147
+ if not results:
148
+ no_results_msg = (
149
+ "No similar tool usage patterns found for this question."
150
+ )
151
+
152
+ # Check if user has access to detailed memory results
153
+ ui_features_available = context.metadata.get(
154
+ "ui_features_available", []
155
+ )
156
+ show_detailed_results = (
157
+ UiFeature.UI_FEATURE_SHOW_MEMORY_DETAILED_RESULTS
158
+ in ui_features_available
159
+ )
160
+
161
+ # Create UI component based on access level
162
+ if show_detailed_results:
163
+ # Admin view: Show card indicating 0 results
164
+ ui_component = UiComponent(
165
+ rich_component=CardComponent(
166
+ title="🧠 Memory Search: 0 Results",
167
+ content="No similar tool usage patterns found for this question.\n\nSearched agent memory with no matches.",
168
+ icon="🔍",
169
+ status="info",
170
+ collapsible=True,
171
+ collapsed=True,
172
+ markdown=True,
173
+ ),
174
+ simple_component=None,
175
+ )
176
+ else:
177
+ # Non-admin view: Simple status message
178
+ ui_component = UiComponent(
179
+ rich_component=StatusBarUpdateComponent(
180
+ status="idle",
181
+ message="No similar patterns found",
182
+ detail="Searched agent memory",
183
+ ),
184
+ simple_component=None,
185
+ )
186
+
187
+ return ToolResult(
188
+ success=True,
189
+ result_for_llm=no_results_msg,
190
+ ui_component=ui_component,
191
+ )
192
+
193
+ # Format results for LLM
194
+ results_text = f"Found {len(results)} similar tool usage pattern(s):\n\n"
195
+ for i, result in enumerate(results, 1):
196
+ memory = result.memory
197
+ results_text += f"{i}. {memory.tool_name} (similarity: {result.similarity_score:.2f})\n"
198
+ results_text += f" Question: {memory.question}\n"
199
+ results_text += f" Args: {memory.args}\n\n"
200
+
201
+ logger.info(f"Agent memory search results: {results_text.strip()}")
202
+
203
+ # Check if user has access to detailed memory results
204
+ ui_features_available = context.metadata.get("ui_features_available", [])
205
+ show_detailed_results = (
206
+ UiFeature.UI_FEATURE_SHOW_MEMORY_DETAILED_RESULTS
207
+ in ui_features_available
208
+ )
209
+
210
+ # Create UI component based on access level
211
+ if show_detailed_results:
212
+ # Admin view: Show detailed results in collapsible card
213
+ detailed_content = "**Retrieved memories passed to LLM:**\n\n"
214
+ for i, result in enumerate(results, 1):
215
+ memory = result.memory
216
+ detailed_content += f"**{i}. {memory.tool_name}** (similarity: {result.similarity_score:.2f})\n"
217
+ detailed_content += f"- **Question:** {memory.question}\n"
218
+ detailed_content += f"- **Arguments:** `{memory.args}`\n"
219
+ if memory.timestamp:
220
+ detailed_content += f"- **Timestamp:** {memory.timestamp}\n"
221
+ if memory.memory_id:
222
+ detailed_content += f"- **ID:** `{memory.memory_id}`\n"
223
+ detailed_content += "\n"
224
+
225
+ ui_component = UiComponent(
226
+ rich_component=CardComponent(
227
+ title=f"🧠 Memory Search: {len(results)} Result(s)",
228
+ content=detailed_content.strip(),
229
+ icon="🔍",
230
+ status="info",
231
+ collapsible=True,
232
+ collapsed=True, # Start collapsed to avoid clutter
233
+ markdown=True, # Render content as markdown
234
+ ),
235
+ simple_component=None,
236
+ )
237
+ else:
238
+ # Non-admin view: Simple status message
239
+ ui_component = UiComponent(
240
+ rich_component=StatusBarUpdateComponent(
241
+ status="success",
242
+ message=f"Found {len(results)} similar pattern(s)",
243
+ detail="Retrieved from agent memory",
244
+ ),
245
+ simple_component=None,
246
+ )
247
+
248
+ return ToolResult(
249
+ success=True,
250
+ result_for_llm=results_text.strip(),
251
+ ui_component=ui_component,
252
+ )
253
+
254
+ except Exception as e:
255
+ error_message = f"Failed to search memories: {str(e)}"
256
+ return ToolResult(
257
+ success=False,
258
+ result_for_llm=error_message,
259
+ ui_component=UiComponent(
260
+ rich_component=StatusBarUpdateComponent(
261
+ status="error", message="Failed to search memory", detail=str(e)
262
+ ),
263
+ simple_component=None,
264
+ ),
265
+ error=str(e),
266
+ )
267
+
268
+
269
+ class SaveTextMemoryTool(Tool[SaveTextMemoryParams]):
270
+ """Tool for saving free-form text memories."""
271
+
272
+ @property
273
+ def name(self) -> str:
274
+ return "save_text_memory"
275
+
276
+ @property
277
+ def description(self) -> str:
278
+ return "Save free-form text memory for important insights, observations, or context"
279
+
280
+ def get_args_schema(self) -> Type[SaveTextMemoryParams]:
281
+ return SaveTextMemoryParams
282
+
283
+ async def execute(
284
+ self, context: ToolContext, args: SaveTextMemoryParams
285
+ ) -> ToolResult:
286
+ """Save a text memory to agent memory."""
287
+ try:
288
+ text_memory = await context.agent_memory.save_text_memory(
289
+ content=args.content, context=context
290
+ )
291
+
292
+ success_msg = (
293
+ f"Successfully saved text memory with ID: {text_memory.memory_id}"
294
+ )
295
+ return ToolResult(
296
+ success=True,
297
+ result_for_llm=success_msg,
298
+ ui_component=UiComponent(
299
+ rich_component=StatusBarUpdateComponent(
300
+ status="success",
301
+ message="Saved text memory",
302
+ detail=f"ID: {text_memory.memory_id}",
303
+ ),
304
+ simple_component=None,
305
+ ),
306
+ )
307
+
308
+ except Exception as e:
309
+ error_message = f"Failed to save text memory: {str(e)}"
310
+ return ToolResult(
311
+ success=False,
312
+ result_for_llm=error_message,
313
+ ui_component=UiComponent(
314
+ rich_component=StatusBarUpdateComponent(
315
+ status="error",
316
+ message="Failed to save text memory",
317
+ detail=str(e),
318
+ ),
319
+ simple_component=None,
320
+ ),
321
+ error=str(e),
322
+ )