ai-parrot 0.17.2__cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.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 (535) hide show
  1. agentui/.prettierrc +15 -0
  2. agentui/QUICKSTART.md +272 -0
  3. agentui/README.md +59 -0
  4. agentui/env.example +16 -0
  5. agentui/jsconfig.json +14 -0
  6. agentui/package-lock.json +4242 -0
  7. agentui/package.json +34 -0
  8. agentui/scripts/postinstall/apply-patches.mjs +260 -0
  9. agentui/src/app.css +61 -0
  10. agentui/src/app.d.ts +13 -0
  11. agentui/src/app.html +12 -0
  12. agentui/src/components/LoadingSpinner.svelte +64 -0
  13. agentui/src/components/ThemeSwitcher.svelte +159 -0
  14. agentui/src/components/index.js +4 -0
  15. agentui/src/lib/api/bots.ts +60 -0
  16. agentui/src/lib/api/chat.ts +22 -0
  17. agentui/src/lib/api/http.ts +25 -0
  18. agentui/src/lib/components/BotCard.svelte +33 -0
  19. agentui/src/lib/components/ChatBubble.svelte +63 -0
  20. agentui/src/lib/components/Toast.svelte +21 -0
  21. agentui/src/lib/config.ts +20 -0
  22. agentui/src/lib/stores/auth.svelte.ts +73 -0
  23. agentui/src/lib/stores/theme.svelte.js +64 -0
  24. agentui/src/lib/stores/toast.svelte.ts +31 -0
  25. agentui/src/lib/utils/conversation.ts +39 -0
  26. agentui/src/routes/+layout.svelte +20 -0
  27. agentui/src/routes/+page.svelte +232 -0
  28. agentui/src/routes/login/+page.svelte +200 -0
  29. agentui/src/routes/talk/[agentId]/+page.svelte +297 -0
  30. agentui/src/routes/talk/[agentId]/+page.ts +7 -0
  31. agentui/static/README.md +1 -0
  32. agentui/svelte.config.js +11 -0
  33. agentui/tailwind.config.ts +53 -0
  34. agentui/tsconfig.json +3 -0
  35. agentui/vite.config.ts +10 -0
  36. ai_parrot-0.17.2.dist-info/METADATA +472 -0
  37. ai_parrot-0.17.2.dist-info/RECORD +535 -0
  38. ai_parrot-0.17.2.dist-info/WHEEL +6 -0
  39. ai_parrot-0.17.2.dist-info/entry_points.txt +2 -0
  40. ai_parrot-0.17.2.dist-info/licenses/LICENSE +21 -0
  41. ai_parrot-0.17.2.dist-info/top_level.txt +6 -0
  42. crew-builder/.prettierrc +15 -0
  43. crew-builder/QUICKSTART.md +259 -0
  44. crew-builder/README.md +113 -0
  45. crew-builder/env.example +17 -0
  46. crew-builder/jsconfig.json +14 -0
  47. crew-builder/package-lock.json +4182 -0
  48. crew-builder/package.json +37 -0
  49. crew-builder/scripts/postinstall/apply-patches.mjs +260 -0
  50. crew-builder/src/app.css +62 -0
  51. crew-builder/src/app.d.ts +13 -0
  52. crew-builder/src/app.html +12 -0
  53. crew-builder/src/components/LoadingSpinner.svelte +64 -0
  54. crew-builder/src/components/ThemeSwitcher.svelte +149 -0
  55. crew-builder/src/components/index.js +9 -0
  56. crew-builder/src/lib/api/bots.ts +60 -0
  57. crew-builder/src/lib/api/chat.ts +80 -0
  58. crew-builder/src/lib/api/client.ts +56 -0
  59. crew-builder/src/lib/api/crew/crew.ts +136 -0
  60. crew-builder/src/lib/api/index.ts +5 -0
  61. crew-builder/src/lib/api/o365/auth.ts +65 -0
  62. crew-builder/src/lib/auth/auth.ts +54 -0
  63. crew-builder/src/lib/components/AgentNode.svelte +43 -0
  64. crew-builder/src/lib/components/BotCard.svelte +33 -0
  65. crew-builder/src/lib/components/ChatBubble.svelte +67 -0
  66. crew-builder/src/lib/components/ConfigPanel.svelte +278 -0
  67. crew-builder/src/lib/components/JsonTreeNode.svelte +76 -0
  68. crew-builder/src/lib/components/JsonViewer.svelte +24 -0
  69. crew-builder/src/lib/components/MarkdownEditor.svelte +48 -0
  70. crew-builder/src/lib/components/ThemeToggle.svelte +36 -0
  71. crew-builder/src/lib/components/Toast.svelte +67 -0
  72. crew-builder/src/lib/components/Toolbar.svelte +157 -0
  73. crew-builder/src/lib/components/index.ts +10 -0
  74. crew-builder/src/lib/config.ts +8 -0
  75. crew-builder/src/lib/stores/auth.svelte.ts +228 -0
  76. crew-builder/src/lib/stores/crewStore.ts +369 -0
  77. crew-builder/src/lib/stores/theme.svelte.js +145 -0
  78. crew-builder/src/lib/stores/toast.svelte.ts +69 -0
  79. crew-builder/src/lib/utils/conversation.ts +39 -0
  80. crew-builder/src/lib/utils/markdown.ts +122 -0
  81. crew-builder/src/lib/utils/talkHistory.ts +47 -0
  82. crew-builder/src/routes/+layout.svelte +20 -0
  83. crew-builder/src/routes/+page.svelte +539 -0
  84. crew-builder/src/routes/agents/+page.svelte +247 -0
  85. crew-builder/src/routes/agents/[agentId]/+page.svelte +288 -0
  86. crew-builder/src/routes/agents/[agentId]/+page.ts +7 -0
  87. crew-builder/src/routes/builder/+page.svelte +204 -0
  88. crew-builder/src/routes/crew/ask/+page.svelte +1052 -0
  89. crew-builder/src/routes/crew/ask/+page.ts +1 -0
  90. crew-builder/src/routes/integrations/o365/+page.svelte +304 -0
  91. crew-builder/src/routes/login/+page.svelte +197 -0
  92. crew-builder/src/routes/talk/[agentId]/+page.svelte +487 -0
  93. crew-builder/src/routes/talk/[agentId]/+page.ts +7 -0
  94. crew-builder/static/README.md +1 -0
  95. crew-builder/svelte.config.js +11 -0
  96. crew-builder/tailwind.config.ts +53 -0
  97. crew-builder/tsconfig.json +3 -0
  98. crew-builder/vite.config.ts +10 -0
  99. mcp_servers/calculator_server.py +309 -0
  100. parrot/__init__.py +27 -0
  101. parrot/__pycache__/__init__.cpython-310.pyc +0 -0
  102. parrot/__pycache__/version.cpython-310.pyc +0 -0
  103. parrot/_version.py +34 -0
  104. parrot/a2a/__init__.py +48 -0
  105. parrot/a2a/client.py +658 -0
  106. parrot/a2a/discovery.py +89 -0
  107. parrot/a2a/mixin.py +257 -0
  108. parrot/a2a/models.py +376 -0
  109. parrot/a2a/server.py +770 -0
  110. parrot/agents/__init__.py +29 -0
  111. parrot/bots/__init__.py +12 -0
  112. parrot/bots/a2a_agent.py +19 -0
  113. parrot/bots/abstract.py +3139 -0
  114. parrot/bots/agent.py +1129 -0
  115. parrot/bots/basic.py +9 -0
  116. parrot/bots/chatbot.py +669 -0
  117. parrot/bots/data.py +1618 -0
  118. parrot/bots/database/__init__.py +5 -0
  119. parrot/bots/database/abstract.py +3071 -0
  120. parrot/bots/database/cache.py +286 -0
  121. parrot/bots/database/models.py +468 -0
  122. parrot/bots/database/prompts.py +154 -0
  123. parrot/bots/database/retries.py +98 -0
  124. parrot/bots/database/router.py +269 -0
  125. parrot/bots/database/sql.py +41 -0
  126. parrot/bots/db/__init__.py +6 -0
  127. parrot/bots/db/abstract.py +556 -0
  128. parrot/bots/db/bigquery.py +602 -0
  129. parrot/bots/db/cache.py +85 -0
  130. parrot/bots/db/documentdb.py +668 -0
  131. parrot/bots/db/elastic.py +1014 -0
  132. parrot/bots/db/influx.py +898 -0
  133. parrot/bots/db/mock.py +96 -0
  134. parrot/bots/db/multi.py +783 -0
  135. parrot/bots/db/prompts.py +185 -0
  136. parrot/bots/db/sql.py +1255 -0
  137. parrot/bots/db/tools.py +212 -0
  138. parrot/bots/document.py +680 -0
  139. parrot/bots/hrbot.py +15 -0
  140. parrot/bots/kb.py +170 -0
  141. parrot/bots/mcp.py +36 -0
  142. parrot/bots/orchestration/README.md +463 -0
  143. parrot/bots/orchestration/__init__.py +1 -0
  144. parrot/bots/orchestration/agent.py +155 -0
  145. parrot/bots/orchestration/crew.py +3330 -0
  146. parrot/bots/orchestration/fsm.py +1179 -0
  147. parrot/bots/orchestration/hr.py +434 -0
  148. parrot/bots/orchestration/storage/__init__.py +4 -0
  149. parrot/bots/orchestration/storage/memory.py +100 -0
  150. parrot/bots/orchestration/storage/mixin.py +119 -0
  151. parrot/bots/orchestration/verify.py +202 -0
  152. parrot/bots/product.py +204 -0
  153. parrot/bots/prompts/__init__.py +96 -0
  154. parrot/bots/prompts/agents.py +155 -0
  155. parrot/bots/prompts/data.py +216 -0
  156. parrot/bots/prompts/output_generation.py +8 -0
  157. parrot/bots/scraper/__init__.py +3 -0
  158. parrot/bots/scraper/models.py +122 -0
  159. parrot/bots/scraper/scraper.py +1173 -0
  160. parrot/bots/scraper/templates.py +115 -0
  161. parrot/bots/stores/__init__.py +5 -0
  162. parrot/bots/stores/local.py +172 -0
  163. parrot/bots/webdev.py +81 -0
  164. parrot/cli.py +17 -0
  165. parrot/clients/__init__.py +16 -0
  166. parrot/clients/base.py +1491 -0
  167. parrot/clients/claude.py +1191 -0
  168. parrot/clients/factory.py +129 -0
  169. parrot/clients/google.py +4567 -0
  170. parrot/clients/gpt.py +1975 -0
  171. parrot/clients/grok.py +432 -0
  172. parrot/clients/groq.py +986 -0
  173. parrot/clients/hf.py +582 -0
  174. parrot/clients/models.py +18 -0
  175. parrot/conf.py +395 -0
  176. parrot/embeddings/__init__.py +9 -0
  177. parrot/embeddings/base.py +157 -0
  178. parrot/embeddings/google.py +98 -0
  179. parrot/embeddings/huggingface.py +74 -0
  180. parrot/embeddings/openai.py +84 -0
  181. parrot/embeddings/processor.py +88 -0
  182. parrot/exceptions.c +13868 -0
  183. parrot/exceptions.cpython-310-x86_64-linux-gnu.so +0 -0
  184. parrot/exceptions.pxd +22 -0
  185. parrot/exceptions.pxi +15 -0
  186. parrot/exceptions.pyx +44 -0
  187. parrot/generators/__init__.py +29 -0
  188. parrot/generators/base.py +200 -0
  189. parrot/generators/html.py +293 -0
  190. parrot/generators/react.py +205 -0
  191. parrot/generators/streamlit.py +203 -0
  192. parrot/generators/template.py +105 -0
  193. parrot/handlers/__init__.py +4 -0
  194. parrot/handlers/agent.py +861 -0
  195. parrot/handlers/agents/__init__.py +1 -0
  196. parrot/handlers/agents/abstract.py +900 -0
  197. parrot/handlers/bots.py +338 -0
  198. parrot/handlers/chat.py +915 -0
  199. parrot/handlers/creation.sql +192 -0
  200. parrot/handlers/crew/ARCHITECTURE.md +362 -0
  201. parrot/handlers/crew/README_BOTMANAGER_PERSISTENCE.md +303 -0
  202. parrot/handlers/crew/README_REDIS_PERSISTENCE.md +366 -0
  203. parrot/handlers/crew/__init__.py +0 -0
  204. parrot/handlers/crew/handler.py +801 -0
  205. parrot/handlers/crew/models.py +229 -0
  206. parrot/handlers/crew/redis_persistence.py +523 -0
  207. parrot/handlers/jobs/__init__.py +10 -0
  208. parrot/handlers/jobs/job.py +384 -0
  209. parrot/handlers/jobs/mixin.py +627 -0
  210. parrot/handlers/jobs/models.py +115 -0
  211. parrot/handlers/jobs/worker.py +31 -0
  212. parrot/handlers/models.py +596 -0
  213. parrot/handlers/o365_auth.py +105 -0
  214. parrot/handlers/stream.py +337 -0
  215. parrot/interfaces/__init__.py +6 -0
  216. parrot/interfaces/aws.py +143 -0
  217. parrot/interfaces/credentials.py +113 -0
  218. parrot/interfaces/database.py +27 -0
  219. parrot/interfaces/google.py +1123 -0
  220. parrot/interfaces/hierarchy.py +1227 -0
  221. parrot/interfaces/http.py +651 -0
  222. parrot/interfaces/images/__init__.py +0 -0
  223. parrot/interfaces/images/plugins/__init__.py +24 -0
  224. parrot/interfaces/images/plugins/abstract.py +58 -0
  225. parrot/interfaces/images/plugins/analisys.py +148 -0
  226. parrot/interfaces/images/plugins/classify.py +150 -0
  227. parrot/interfaces/images/plugins/classifybase.py +182 -0
  228. parrot/interfaces/images/plugins/detect.py +150 -0
  229. parrot/interfaces/images/plugins/exif.py +1103 -0
  230. parrot/interfaces/images/plugins/hash.py +52 -0
  231. parrot/interfaces/images/plugins/vision.py +104 -0
  232. parrot/interfaces/images/plugins/yolo.py +66 -0
  233. parrot/interfaces/images/plugins/zerodetect.py +197 -0
  234. parrot/interfaces/o365.py +978 -0
  235. parrot/interfaces/onedrive.py +822 -0
  236. parrot/interfaces/sharepoint.py +1435 -0
  237. parrot/interfaces/soap.py +257 -0
  238. parrot/loaders/__init__.py +8 -0
  239. parrot/loaders/abstract.py +1131 -0
  240. parrot/loaders/audio.py +199 -0
  241. parrot/loaders/basepdf.py +53 -0
  242. parrot/loaders/basevideo.py +1568 -0
  243. parrot/loaders/csv.py +409 -0
  244. parrot/loaders/docx.py +116 -0
  245. parrot/loaders/epubloader.py +316 -0
  246. parrot/loaders/excel.py +199 -0
  247. parrot/loaders/factory.py +55 -0
  248. parrot/loaders/files/__init__.py +0 -0
  249. parrot/loaders/files/abstract.py +39 -0
  250. parrot/loaders/files/html.py +26 -0
  251. parrot/loaders/files/text.py +63 -0
  252. parrot/loaders/html.py +152 -0
  253. parrot/loaders/markdown.py +442 -0
  254. parrot/loaders/pdf.py +373 -0
  255. parrot/loaders/pdfmark.py +320 -0
  256. parrot/loaders/pdftables.py +506 -0
  257. parrot/loaders/ppt.py +476 -0
  258. parrot/loaders/qa.py +63 -0
  259. parrot/loaders/splitters/__init__.py +10 -0
  260. parrot/loaders/splitters/base.py +138 -0
  261. parrot/loaders/splitters/md.py +228 -0
  262. parrot/loaders/splitters/token.py +143 -0
  263. parrot/loaders/txt.py +26 -0
  264. parrot/loaders/video.py +89 -0
  265. parrot/loaders/videolocal.py +218 -0
  266. parrot/loaders/videounderstanding.py +377 -0
  267. parrot/loaders/vimeo.py +167 -0
  268. parrot/loaders/web.py +599 -0
  269. parrot/loaders/youtube.py +504 -0
  270. parrot/manager/__init__.py +5 -0
  271. parrot/manager/manager.py +1030 -0
  272. parrot/mcp/__init__.py +28 -0
  273. parrot/mcp/adapter.py +105 -0
  274. parrot/mcp/cli.py +174 -0
  275. parrot/mcp/client.py +119 -0
  276. parrot/mcp/config.py +75 -0
  277. parrot/mcp/integration.py +842 -0
  278. parrot/mcp/oauth.py +933 -0
  279. parrot/mcp/server.py +225 -0
  280. parrot/mcp/transports/__init__.py +3 -0
  281. parrot/mcp/transports/base.py +279 -0
  282. parrot/mcp/transports/grpc_session.py +163 -0
  283. parrot/mcp/transports/http.py +312 -0
  284. parrot/mcp/transports/mcp.proto +108 -0
  285. parrot/mcp/transports/quic.py +1082 -0
  286. parrot/mcp/transports/sse.py +330 -0
  287. parrot/mcp/transports/stdio.py +309 -0
  288. parrot/mcp/transports/unix.py +395 -0
  289. parrot/mcp/transports/websocket.py +547 -0
  290. parrot/memory/__init__.py +16 -0
  291. parrot/memory/abstract.py +209 -0
  292. parrot/memory/agent.py +32 -0
  293. parrot/memory/cache.py +175 -0
  294. parrot/memory/core.py +555 -0
  295. parrot/memory/file.py +153 -0
  296. parrot/memory/mem.py +131 -0
  297. parrot/memory/redis.py +613 -0
  298. parrot/models/__init__.py +46 -0
  299. parrot/models/basic.py +118 -0
  300. parrot/models/compliance.py +208 -0
  301. parrot/models/crew.py +395 -0
  302. parrot/models/detections.py +654 -0
  303. parrot/models/generation.py +85 -0
  304. parrot/models/google.py +223 -0
  305. parrot/models/groq.py +23 -0
  306. parrot/models/openai.py +30 -0
  307. parrot/models/outputs.py +285 -0
  308. parrot/models/responses.py +938 -0
  309. parrot/notifications/__init__.py +743 -0
  310. parrot/openapi/__init__.py +3 -0
  311. parrot/openapi/components.yaml +641 -0
  312. parrot/openapi/config.py +322 -0
  313. parrot/outputs/__init__.py +32 -0
  314. parrot/outputs/formats/__init__.py +108 -0
  315. parrot/outputs/formats/altair.py +359 -0
  316. parrot/outputs/formats/application.py +122 -0
  317. parrot/outputs/formats/base.py +351 -0
  318. parrot/outputs/formats/bokeh.py +356 -0
  319. parrot/outputs/formats/card.py +424 -0
  320. parrot/outputs/formats/chart.py +436 -0
  321. parrot/outputs/formats/d3.py +255 -0
  322. parrot/outputs/formats/echarts.py +310 -0
  323. parrot/outputs/formats/generators/__init__.py +0 -0
  324. parrot/outputs/formats/generators/abstract.py +61 -0
  325. parrot/outputs/formats/generators/panel.py +145 -0
  326. parrot/outputs/formats/generators/streamlit.py +86 -0
  327. parrot/outputs/formats/generators/terminal.py +63 -0
  328. parrot/outputs/formats/holoviews.py +310 -0
  329. parrot/outputs/formats/html.py +147 -0
  330. parrot/outputs/formats/jinja2.py +46 -0
  331. parrot/outputs/formats/json.py +87 -0
  332. parrot/outputs/formats/map.py +933 -0
  333. parrot/outputs/formats/markdown.py +172 -0
  334. parrot/outputs/formats/matplotlib.py +237 -0
  335. parrot/outputs/formats/mixins/__init__.py +0 -0
  336. parrot/outputs/formats/mixins/emaps.py +855 -0
  337. parrot/outputs/formats/plotly.py +341 -0
  338. parrot/outputs/formats/seaborn.py +310 -0
  339. parrot/outputs/formats/table.py +397 -0
  340. parrot/outputs/formats/template_report.py +138 -0
  341. parrot/outputs/formats/yaml.py +125 -0
  342. parrot/outputs/formatter.py +152 -0
  343. parrot/outputs/templates/__init__.py +95 -0
  344. parrot/pipelines/__init__.py +0 -0
  345. parrot/pipelines/abstract.py +210 -0
  346. parrot/pipelines/detector.py +124 -0
  347. parrot/pipelines/models.py +90 -0
  348. parrot/pipelines/planogram.py +3002 -0
  349. parrot/pipelines/table.sql +97 -0
  350. parrot/plugins/__init__.py +106 -0
  351. parrot/plugins/importer.py +80 -0
  352. parrot/py.typed +0 -0
  353. parrot/registry/__init__.py +18 -0
  354. parrot/registry/registry.py +594 -0
  355. parrot/scheduler/__init__.py +1189 -0
  356. parrot/scheduler/models.py +60 -0
  357. parrot/security/__init__.py +16 -0
  358. parrot/security/prompt_injection.py +268 -0
  359. parrot/security/security_events.sql +25 -0
  360. parrot/services/__init__.py +1 -0
  361. parrot/services/mcp/__init__.py +8 -0
  362. parrot/services/mcp/config.py +13 -0
  363. parrot/services/mcp/server.py +295 -0
  364. parrot/services/o365_remote_auth.py +235 -0
  365. parrot/stores/__init__.py +7 -0
  366. parrot/stores/abstract.py +352 -0
  367. parrot/stores/arango.py +1090 -0
  368. parrot/stores/bigquery.py +1377 -0
  369. parrot/stores/cache.py +106 -0
  370. parrot/stores/empty.py +10 -0
  371. parrot/stores/faiss_store.py +1157 -0
  372. parrot/stores/kb/__init__.py +9 -0
  373. parrot/stores/kb/abstract.py +68 -0
  374. parrot/stores/kb/cache.py +165 -0
  375. parrot/stores/kb/doc.py +325 -0
  376. parrot/stores/kb/hierarchy.py +346 -0
  377. parrot/stores/kb/local.py +457 -0
  378. parrot/stores/kb/prompt.py +28 -0
  379. parrot/stores/kb/redis.py +659 -0
  380. parrot/stores/kb/store.py +115 -0
  381. parrot/stores/kb/user.py +374 -0
  382. parrot/stores/models.py +59 -0
  383. parrot/stores/pgvector.py +3 -0
  384. parrot/stores/postgres.py +2853 -0
  385. parrot/stores/utils/__init__.py +0 -0
  386. parrot/stores/utils/chunking.py +197 -0
  387. parrot/telemetry/__init__.py +3 -0
  388. parrot/telemetry/mixin.py +111 -0
  389. parrot/template/__init__.py +3 -0
  390. parrot/template/engine.py +259 -0
  391. parrot/tools/__init__.py +23 -0
  392. parrot/tools/abstract.py +644 -0
  393. parrot/tools/agent.py +363 -0
  394. parrot/tools/arangodbsearch.py +537 -0
  395. parrot/tools/arxiv_tool.py +188 -0
  396. parrot/tools/calculator/__init__.py +3 -0
  397. parrot/tools/calculator/operations/__init__.py +38 -0
  398. parrot/tools/calculator/operations/calculus.py +80 -0
  399. parrot/tools/calculator/operations/statistics.py +76 -0
  400. parrot/tools/calculator/tool.py +150 -0
  401. parrot/tools/cloudwatch.py +988 -0
  402. parrot/tools/codeinterpreter/__init__.py +127 -0
  403. parrot/tools/codeinterpreter/executor.py +371 -0
  404. parrot/tools/codeinterpreter/internals.py +473 -0
  405. parrot/tools/codeinterpreter/models.py +643 -0
  406. parrot/tools/codeinterpreter/prompts.py +224 -0
  407. parrot/tools/codeinterpreter/tool.py +664 -0
  408. parrot/tools/company_info/__init__.py +6 -0
  409. parrot/tools/company_info/tool.py +1138 -0
  410. parrot/tools/correlationanalysis.py +437 -0
  411. parrot/tools/database/abstract.py +286 -0
  412. parrot/tools/database/bq.py +115 -0
  413. parrot/tools/database/cache.py +284 -0
  414. parrot/tools/database/models.py +95 -0
  415. parrot/tools/database/pg.py +343 -0
  416. parrot/tools/databasequery.py +1159 -0
  417. parrot/tools/db.py +1800 -0
  418. parrot/tools/ddgo.py +370 -0
  419. parrot/tools/decorators.py +271 -0
  420. parrot/tools/dftohtml.py +282 -0
  421. parrot/tools/document.py +549 -0
  422. parrot/tools/ecs.py +819 -0
  423. parrot/tools/edareport.py +368 -0
  424. parrot/tools/elasticsearch.py +1049 -0
  425. parrot/tools/employees.py +462 -0
  426. parrot/tools/epson/__init__.py +96 -0
  427. parrot/tools/excel.py +683 -0
  428. parrot/tools/file/__init__.py +13 -0
  429. parrot/tools/file/abstract.py +76 -0
  430. parrot/tools/file/gcs.py +378 -0
  431. parrot/tools/file/local.py +284 -0
  432. parrot/tools/file/s3.py +511 -0
  433. parrot/tools/file/tmp.py +309 -0
  434. parrot/tools/file/tool.py +501 -0
  435. parrot/tools/file_reader.py +129 -0
  436. parrot/tools/flowtask/__init__.py +19 -0
  437. parrot/tools/flowtask/tool.py +761 -0
  438. parrot/tools/gittoolkit.py +508 -0
  439. parrot/tools/google/__init__.py +18 -0
  440. parrot/tools/google/base.py +169 -0
  441. parrot/tools/google/tools.py +1251 -0
  442. parrot/tools/googlelocation.py +5 -0
  443. parrot/tools/googleroutes.py +5 -0
  444. parrot/tools/googlesearch.py +5 -0
  445. parrot/tools/googlesitesearch.py +5 -0
  446. parrot/tools/googlevoice.py +2 -0
  447. parrot/tools/gvoice.py +695 -0
  448. parrot/tools/ibisworld/README.md +225 -0
  449. parrot/tools/ibisworld/__init__.py +11 -0
  450. parrot/tools/ibisworld/tool.py +366 -0
  451. parrot/tools/jiratoolkit.py +1718 -0
  452. parrot/tools/manager.py +1098 -0
  453. parrot/tools/math.py +152 -0
  454. parrot/tools/metadata.py +476 -0
  455. parrot/tools/msteams.py +1621 -0
  456. parrot/tools/msword.py +635 -0
  457. parrot/tools/multidb.py +580 -0
  458. parrot/tools/multistoresearch.py +369 -0
  459. parrot/tools/networkninja.py +167 -0
  460. parrot/tools/nextstop/__init__.py +4 -0
  461. parrot/tools/nextstop/base.py +286 -0
  462. parrot/tools/nextstop/employee.py +733 -0
  463. parrot/tools/nextstop/store.py +462 -0
  464. parrot/tools/notification.py +435 -0
  465. parrot/tools/o365/__init__.py +42 -0
  466. parrot/tools/o365/base.py +295 -0
  467. parrot/tools/o365/bundle.py +522 -0
  468. parrot/tools/o365/events.py +554 -0
  469. parrot/tools/o365/mail.py +992 -0
  470. parrot/tools/o365/onedrive.py +497 -0
  471. parrot/tools/o365/sharepoint.py +641 -0
  472. parrot/tools/openapi_toolkit.py +904 -0
  473. parrot/tools/openweather.py +527 -0
  474. parrot/tools/pdfprint.py +1001 -0
  475. parrot/tools/powerbi.py +518 -0
  476. parrot/tools/powerpoint.py +1113 -0
  477. parrot/tools/pricestool.py +146 -0
  478. parrot/tools/products/__init__.py +246 -0
  479. parrot/tools/prophet_tool.py +171 -0
  480. parrot/tools/pythonpandas.py +630 -0
  481. parrot/tools/pythonrepl.py +910 -0
  482. parrot/tools/qsource.py +436 -0
  483. parrot/tools/querytoolkit.py +395 -0
  484. parrot/tools/quickeda.py +827 -0
  485. parrot/tools/resttool.py +553 -0
  486. parrot/tools/retail/__init__.py +0 -0
  487. parrot/tools/retail/bby.py +528 -0
  488. parrot/tools/sandboxtool.py +703 -0
  489. parrot/tools/sassie/__init__.py +352 -0
  490. parrot/tools/scraping/__init__.py +7 -0
  491. parrot/tools/scraping/docs/select.md +466 -0
  492. parrot/tools/scraping/documentation.md +1278 -0
  493. parrot/tools/scraping/driver.py +436 -0
  494. parrot/tools/scraping/models.py +576 -0
  495. parrot/tools/scraping/options.py +85 -0
  496. parrot/tools/scraping/orchestrator.py +517 -0
  497. parrot/tools/scraping/readme.md +740 -0
  498. parrot/tools/scraping/tool.py +3115 -0
  499. parrot/tools/seasonaldetection.py +642 -0
  500. parrot/tools/shell_tool/__init__.py +5 -0
  501. parrot/tools/shell_tool/actions.py +408 -0
  502. parrot/tools/shell_tool/engine.py +155 -0
  503. parrot/tools/shell_tool/models.py +322 -0
  504. parrot/tools/shell_tool/tool.py +442 -0
  505. parrot/tools/site_search.py +214 -0
  506. parrot/tools/textfile.py +418 -0
  507. parrot/tools/think.py +378 -0
  508. parrot/tools/toolkit.py +298 -0
  509. parrot/tools/webapp_tool.py +187 -0
  510. parrot/tools/whatif.py +1279 -0
  511. parrot/tools/workday/MULTI_WSDL_EXAMPLE.md +249 -0
  512. parrot/tools/workday/__init__.py +6 -0
  513. parrot/tools/workday/models.py +1389 -0
  514. parrot/tools/workday/tool.py +1293 -0
  515. parrot/tools/yfinance_tool.py +306 -0
  516. parrot/tools/zipcode.py +217 -0
  517. parrot/utils/__init__.py +2 -0
  518. parrot/utils/helpers.py +73 -0
  519. parrot/utils/parsers/__init__.py +5 -0
  520. parrot/utils/parsers/toml.c +12078 -0
  521. parrot/utils/parsers/toml.cpython-310-x86_64-linux-gnu.so +0 -0
  522. parrot/utils/parsers/toml.pyx +21 -0
  523. parrot/utils/toml.py +11 -0
  524. parrot/utils/types.cpp +20936 -0
  525. parrot/utils/types.cpython-310-x86_64-linux-gnu.so +0 -0
  526. parrot/utils/types.pyx +213 -0
  527. parrot/utils/uv.py +11 -0
  528. parrot/version.py +10 -0
  529. parrot/yaml-rs/Cargo.lock +350 -0
  530. parrot/yaml-rs/Cargo.toml +19 -0
  531. parrot/yaml-rs/pyproject.toml +19 -0
  532. parrot/yaml-rs/python/yaml_rs/__init__.py +81 -0
  533. parrot/yaml-rs/src/lib.rs +222 -0
  534. requirements/docker-compose.yml +24 -0
  535. requirements/requirements-dev.txt +21 -0
@@ -0,0 +1,556 @@
1
+ """
2
+ Database Agent Architecture for AI-Parrot.
3
+
4
+ This module provides an abstract base for database introspection agents
5
+ that can analyze database schemas and generate queries from natural language.
6
+ """
7
+
8
+ from abc import abstractmethod
9
+ from typing import Dict, Any, List, Optional, Union
10
+ import uuid
11
+ import json
12
+ import asyncio
13
+ from string import Template
14
+ from sqlalchemy.ext.asyncio import AsyncEngine
15
+ from ..abstract import AbstractBot
16
+ from ...tools.manager import (
17
+ ToolManager,
18
+ )
19
+ from ...stores.abstract import AbstractStore
20
+ from .prompts import DB_AGENT_PROMPT, BASIC_HUMAN_PROMPT
21
+ from .tools import (
22
+ SchemaSearchTool,
23
+ QueryGenerationTool,
24
+ DatabaseSchema,
25
+ TableMetadata,
26
+ ExplainQueryTool,
27
+ )
28
+ from ...models import AIMessage
29
+ from ...tools.databasequery import DatabaseQueryTool
30
+ from .cache import SchemaCache
31
+ from ...memory import ConversationTurn
32
+
33
+ class AbstractDBAgent(AbstractBot):
34
+ """
35
+ Abstract base class for database introspection agents.
36
+
37
+ This agent analyzes database schemas, stores metadata in a knowledge base,
38
+ and generates queries from natural language descriptions.
39
+ """
40
+ system_prompt_template: str = DB_AGENT_PROMPT
41
+ human_prompt_template = BASIC_HUMAN_PROMPT
42
+ _default_temperature: float = 0.0
43
+ max_tokens: int = 8192
44
+
45
+ def __init__(
46
+ self,
47
+ name: str = "DatabaseAgent",
48
+ credentials: Union[str, Dict[str, Any]] = None,
49
+ schema_name: Optional[str] = None,
50
+ knowledge_store: AbstractStore = None,
51
+ auto_analyze_schema: bool = True,
52
+ cache_ttl: int = 3600, # Cache TTL in seconds
53
+ **kwargs
54
+ ):
55
+ """
56
+ Initialize the database agent.
57
+
58
+ Args:
59
+ name: Agent name
60
+ credentials: Database connection credentials
61
+ schema_name: Target schema name (optional)
62
+ knowledge_store: Vector store for schema metadata
63
+ auto_analyze_schema: Whether to automatically analyze schema on init
64
+ """
65
+ kwargs.setdefault('temperature', self._default_temperature)
66
+ super().__init__(name=name, **kwargs)
67
+ self.role = kwargs.get(
68
+ 'role', 'Database Analysis Assistant'
69
+ )
70
+ self.goal = kwargs.get(
71
+ 'goal', 'Help users interact with databases using natural language'
72
+ )
73
+ self.capabilities = kwargs.get(
74
+ 'capabilities',
75
+ 'Database schema analysis, query generation, and data retrieval'
76
+ )
77
+ self.backstory = kwargs.get(
78
+ 'backstory',
79
+ 'Expert database assistant with deep knowledge of SQL and data analysis'
80
+ )
81
+
82
+ self.credentials = credentials
83
+ self.schema_name = schema_name
84
+ self.knowledge_store = knowledge_store
85
+ # Schema cache for metadata
86
+ self.cache = SchemaCache(ttl=cache_ttl)
87
+ self.auto_analyze_schema = auto_analyze_schema
88
+
89
+ # Initialize database-specific components
90
+ self.engine: Optional[AsyncEngine] = None
91
+ self.schema_metadata: Optional[DatabaseSchema] = None
92
+
93
+ # Initialize tool manager
94
+ self.tool_manager = ToolManager(
95
+ logger=self.logger,
96
+ debug=self._debug
97
+ )
98
+
99
+ # Add database-specific tools
100
+ self._setup_database_tools()
101
+ try:
102
+ self.loop = asyncio.get_running_loop()
103
+ except RuntimeError:
104
+ raise RuntimeError(
105
+ "An event loop is required to initialize the AbstractDBAgent."
106
+ )
107
+ asyncio.set_event_loop(self.loop)
108
+
109
+ @property
110
+ def tools(self):
111
+ """Get list of registered tools from manager."""
112
+ return self.tool_manager.get_all_tools() if self.tool_manager else []
113
+
114
+ async def initialize_schema(self):
115
+ """Initialize database connection and analyze schema."""
116
+ try:
117
+ await self.connect_database()
118
+ self.schema_metadata = await self.extract_schema_metadata()
119
+
120
+ if self.knowledge_store:
121
+ await self.store_schema_in_knowledge_base()
122
+
123
+ except Exception as e:
124
+ self.logger.error(
125
+ f"Failed to initialize schema: {e}"
126
+ )
127
+ raise
128
+
129
+ def _setup_database_tools(self):
130
+ """Setup database-specific tools."""
131
+ # Add schema search tool
132
+ schema_search_tool = SchemaSearchTool(agent=self)
133
+ self.tool_manager.register_tool(schema_search_tool)
134
+
135
+ # Add query generation tool
136
+ query_gen_tool = QueryGenerationTool(agent=self)
137
+ self.tool_manager.register_tool(query_gen_tool)
138
+
139
+ # Add database query tool
140
+ db_query_tool = DatabaseQueryTool(agent=self)
141
+ self.tool_manager.register_tool(db_query_tool)
142
+
143
+ # Add explain query tool
144
+ explain_query_tool = ExplainQueryTool(agent=self)
145
+ self.tool_manager.register_tool(explain_query_tool)
146
+
147
+ async def configure(self, app=None) -> None:
148
+ """Configure the database agent."""
149
+ await super().configure(app)
150
+ await self.initialize_schema()
151
+
152
+ def _define_prompt(self, config: Optional[dict] = None, **kwargs):
153
+ """
154
+ Define the System Prompt and replace variables.
155
+ """
156
+ # setup the prompt variables:
157
+ if config:
158
+ for key, val in config.items():
159
+ setattr(self, key, val)
160
+
161
+ tmpl = Template(self.system_prompt_template)
162
+ final_prompt = tmpl.safe_substitute(
163
+ name=self.name,
164
+ role=getattr(self, 'role', 'Database Analysis Assistant'),
165
+ goal=getattr(self, 'goal', 'Help users interact with databases using natural language'),
166
+ capabilities=getattr(self, 'capabilities', 'Database schema analysis, query generation, and data retrieval'),
167
+ backstory=getattr(self, 'backstory', 'Expert database assistant with deep knowledge of SQL and data analysis'),
168
+ rationale=getattr(self, 'rationale', 'Providing precise and helpful database interactions'),
169
+ **kwargs
170
+ )
171
+ self.system_prompt_template = final_prompt
172
+
173
+ async def create_system_prompt(
174
+ self,
175
+ user_context: str = "",
176
+ context: str = "",
177
+ vector_context: str = "",
178
+ pre_context: str = "",
179
+ conversation_context: str = "",
180
+ metadata: Optional[Dict[str, Any]] = None,
181
+ **kwargs
182
+ ) -> str:
183
+ """
184
+ Create the complete system prompt for the LLM with user context support.
185
+
186
+ Args:
187
+ user_context: User-specific context for the database interaction
188
+ vector_context: Vector store context
189
+ conversation_context: Previous conversation context
190
+ metadata: Additional metadata
191
+ **kwargs: Additional template variables
192
+ """
193
+ # Process contexts
194
+ context_parts = []
195
+
196
+ # Add user context if provided
197
+ if user_context:
198
+ context_parts.append(f"""
199
+ Use the following information about user's data to guide your responses:
200
+ **User Context:**
201
+ {user_context}
202
+ Based on the user context above, please tailor your response to their specific:
203
+ - Role and responsibilities
204
+ - Technical expertise level
205
+ - Business objectives
206
+ - Preferred communication style
207
+ """)
208
+ if context:
209
+ context_parts.append(f"**Additional Context:**\n{context}")
210
+
211
+ # Add vector context
212
+ if vector_context:
213
+ context_parts.append(f"**Database Context:**\n{vector_context}")
214
+
215
+ # Add metadata
216
+ if metadata:
217
+ metadata_text = "**Database Metadata:**\n"
218
+ for key, value in metadata.items():
219
+ if key == 'sources' and isinstance(value, list):
220
+ metadata_text += f"- {key}: {', '.join(value[:3])}{'...' if len(value) > 3 else ''}\n"
221
+ else:
222
+ metadata_text += f"- {key}: {value}\n"
223
+ context_parts.append(metadata_text)
224
+
225
+ # Format conversation context
226
+ chat_history_section = ""
227
+ if conversation_context:
228
+ chat_history_section = f"**Conversation History:**\n{conversation_context}"
229
+
230
+ # Database-specific context
231
+ db_context_parts = []
232
+ if self.schema_metadata:
233
+ db_info = f"**Database Information:**\n"
234
+ db_info += f"- Database: {self.schema_metadata.database_name}\n"
235
+ db_info += f"- Type: {self.schema_metadata.database_type}\n"
236
+ db_info += f"- Tables: {len(self.schema_metadata.tables)}\n"
237
+ db_info += f"- Views: {len(self.schema_metadata.views)}\n"
238
+ db_context_parts.append(db_info)
239
+
240
+ # Apply template substitution
241
+ tmpl = Template(self.system_prompt_template)
242
+ system_prompt = tmpl.safe_substitute(
243
+ user_context=user_context,
244
+ pre_context=pre_context,
245
+ context="\n\n".join(context_parts) if context_parts else "",
246
+ database_context="\n\n".join(db_context_parts) if db_context_parts else "",
247
+ chat_history=chat_history_section,
248
+ **kwargs
249
+ )
250
+ return system_prompt
251
+
252
+ async def cleanup(self) -> None:
253
+ """Cleanup resources including cache connections."""
254
+ await self.cache.close()
255
+ await super().cleanup() if hasattr(super(), 'cleanup') else None
256
+
257
+ @abstractmethod
258
+ async def connect_database(self) -> None:
259
+ """Connect to the database. Must be implemented by subclasses."""
260
+ pass
261
+
262
+ @abstractmethod
263
+ async def extract_schema_metadata(self) -> DatabaseSchema:
264
+ """
265
+ Extract complete schema metadata from the database.
266
+ Must be implemented by subclasses based on database type.
267
+ """
268
+ pass
269
+
270
+ @abstractmethod
271
+ async def generate_query(
272
+ self,
273
+ natural_language_query: str,
274
+ target_tables: Optional[List[str]] = None,
275
+ query_type: str = "SELECT"
276
+ ) -> Dict[str, Any]:
277
+ """
278
+ Generate database query from natural language.
279
+ Must be implemented by subclasses based on database type.
280
+ """
281
+ pass
282
+
283
+ @abstractmethod
284
+ async def execute_query(self, query: str) -> Dict[str, Any]:
285
+ """
286
+ Execute a query against the database.
287
+ Must be implemented by subclasses based on database type.
288
+ """
289
+ pass
290
+
291
+ @abstractmethod
292
+ async def explain_query(self, query: str) -> str:
293
+ """
294
+ Explain a database query (e.g. EXPLAIN ANALYZE).
295
+ Must be implemented by subclasses based on database type.
296
+ """
297
+ pass
298
+
299
+ async def search_schema(
300
+ self,
301
+ search_term: str,
302
+ search_type: str = "all",
303
+ limit: int = 10
304
+ ) -> List[Dict[str, Any]]:
305
+ """
306
+ Search the database schema for tables or columns matching the term.
307
+ """
308
+ if not self.schema_metadata:
309
+ # Try to load from cache or re-extract
310
+ return []
311
+
312
+ results = []
313
+ term = search_term.lower()
314
+
315
+ # Helper to check string match
316
+ def matches(text: Optional[str]) -> bool:
317
+ return bool(text and term in text.lower())
318
+
319
+ for table in self.schema_metadata.tables:
320
+ table_match = False
321
+ # Check table name and description
322
+ if search_type in ["all", "tables"]:
323
+ full_name = f"{table.schema}.{table.name}" if table.schema else table.name
324
+ if matches(table.name) or matches(table.description) or matches(full_name):
325
+ results.append({
326
+ "type": "table",
327
+ "name": table.name,
328
+ "schema": table.schema,
329
+ "description": table.description
330
+ })
331
+ table_match = True
332
+
333
+ # Check columns
334
+ if search_type in ["all", "columns"]:
335
+ for col in table.columns:
336
+ if matches(col.get("name")) or matches(col.get("description")):
337
+ # Add table context if not already added/searching specifically for columns
338
+ if not table_match:
339
+ results.append({
340
+ "type": "column",
341
+ "table": table.name,
342
+ "schema": table.schema,
343
+ "name": col.get("name"),
344
+ "description": col.get("description"),
345
+ "metadata": f"Type: {col.get('type')}"
346
+ })
347
+
348
+ # Sort by relevance (exact matches first? undefined for now) and limit
349
+ return results[:limit]
350
+
351
+ async def store_schema_in_knowledge_base(self) -> None:
352
+ """Store schema metadata in the knowledge base for retrieval."""
353
+ if not self.knowledge_store or not self.schema_metadata:
354
+ return
355
+
356
+ documents = []
357
+
358
+ # Store table metadata
359
+ for table in self.schema_metadata.tables:
360
+ table_doc = {
361
+ "content": self._format_table_for_storage(table),
362
+ "metadata": {
363
+ "type": "table_schema",
364
+ "database": self.schema_metadata.database_name,
365
+ "schema": table.schema,
366
+ "tablename": table.tablename,
367
+ "database_type": self.schema_metadata.database_type
368
+ }
369
+ }
370
+ documents.append(table_doc)
371
+
372
+ # Store view metadata
373
+ for view in self.schema_metadata.views:
374
+ view_doc = {
375
+ "content": self._format_table_for_storage(view, is_view=True),
376
+ "metadata": {
377
+ "type": "view_schema",
378
+ "database": self.schema_metadata.database_name,
379
+ "schema": view.schema,
380
+ "view_name": view.tablename,
381
+ "database_type": self.schema_metadata.database_type
382
+ }
383
+ }
384
+ documents.append(view_doc)
385
+
386
+ # Store in knowledge base
387
+ await self.knowledge_store.add_documents(documents)
388
+
389
+ def _format_table_for_storage(self, table: TableMetadata, is_view: bool = False) -> str:
390
+ """Format table metadata for storage in knowledge base."""
391
+ object_type = "VIEW" if is_view else "TABLE"
392
+
393
+ content = f"""
394
+ {object_type}: {table.schema}.{table.tablename}
395
+ Description: {table.description or 'No description available'}
396
+
397
+ Columns:
398
+ """
399
+ for col in table.columns:
400
+ nullable = "NULL" if col.get('nullable', True) else "NOT NULL"
401
+ default = f" DEFAULT {col['default']}" if col.get('default') else ""
402
+ content += f" - {col['name']}: {col['type']} {nullable}{default}\n"
403
+ if col.get('description'):
404
+ content += f" Description: {col['description']}\n"
405
+
406
+ if table.primary_keys:
407
+ content += f"\nPrimary Keys: {', '.join(table.primary_keys)}\n"
408
+
409
+ if table.foreign_keys:
410
+ content += "\nForeign Keys:\n"
411
+ for fk in table.foreign_keys:
412
+ content += f" - {fk['column']} -> {fk['referenced_table']}.{fk['referenced_column']}\n"
413
+
414
+ if table.indexes:
415
+ content += "\nIndexes:\n"
416
+ for idx in table.indexes:
417
+ content += f" - {idx['name']}: {', '.join(idx['columns'])}\n"
418
+
419
+ if table.sample_data:
420
+ content += "\nSample Data:\n"
421
+ for i, row in enumerate(table.sample_data[:3]): # Limit to 3 rows
422
+ content += f" Row {i+1}: {json.dumps(row, default=str)}\n"
423
+
424
+ return content
425
+
426
+ async def ask(
427
+ self,
428
+ question: str = None,
429
+ user_context: Optional[str] = None,
430
+ context: Optional[str] = None,
431
+ session_id: Optional[str] = None,
432
+ user_id: Optional[str] = None,
433
+ use_conversation_history: bool = True,
434
+ **kwargs
435
+ ) -> AIMessage:
436
+ """
437
+ Database-specific ask method with user context support and agentic mode.
438
+
439
+ Args:
440
+ question: The user's question about the database
441
+ user_context: User-specific context for database interaction
442
+ session_id: Session identifier for conversation history
443
+ user_id: User identifier
444
+ use_conversation_history: Whether to use conversation history
445
+ **kwargs: Additional arguments for LLM
446
+
447
+ Returns:
448
+ AIMessage: The response from the LLM
449
+ """
450
+ # Backwards compatibility for prompt
451
+ if question is None:
452
+ question = kwargs.get('prompt')
453
+
454
+ prompt = question # internal usage expects prompt variable name in logic below
455
+ # Force agentic mode for database operations
456
+ effective_mode = "agentic"
457
+
458
+ # Override temperature to ensure consistent database operations
459
+ kwargs['temperature'] = kwargs.get('temperature', self._default_temperature)
460
+
461
+ # Generate session ID if not provided
462
+ if not session_id:
463
+ session_id = f"db_session_{hash(prompt + str(user_id))}"
464
+
465
+ try:
466
+ # Get conversation history if enabled
467
+ conversation_history = None
468
+ conversation_context = ""
469
+
470
+ if use_conversation_history and self.conversation_memory:
471
+ conversation_history = await self.get_conversation_history(user_id, session_id)
472
+ if not conversation_history:
473
+ conversation_history = await self.create_conversation_history(
474
+ user_id, session_id
475
+ )
476
+ conversation_context = self.build_conversation_context(conversation_history)
477
+
478
+ # Get vector context from knowledge store if available
479
+ vector_context = ""
480
+ vector_metadata = {}
481
+ if self.knowledge_store:
482
+ try:
483
+ # Search for relevant schema information
484
+ search_results = await self.knowledge_store.similarity_search(
485
+ prompt, k=5
486
+ )
487
+ if search_results:
488
+ vector_context = "\n\n".join([doc.page_content for doc in search_results])
489
+ vector_metadata = {
490
+ 'sources': [doc.metadata.get('source', 'unknown') for doc in search_results],
491
+ 'tables_referenced': [doc.metadata.get('table_name') for doc in search_results if doc.metadata.get('table_name')]
492
+ }
493
+ except Exception as e:
494
+ self.logger.warning(f"Error retrieving vector context: {e}")
495
+
496
+ # Create system prompt with user context
497
+ system_prompt = await self.create_system_prompt(
498
+ user_context=user_context,
499
+ context=context or "",
500
+ vector_context=vector_context,
501
+ conversation_context=conversation_context,
502
+ metadata=vector_metadata,
503
+ **kwargs
504
+ )
505
+
506
+ # Log the operation
507
+ self.logger.info(
508
+ f"Database query in agentic mode: use_tools=True, "
509
+ f"effective_mode={effective_mode}, available_tools={len(self.tools)}"
510
+ )
511
+
512
+ # Make the LLM call with tools enabled
513
+ async with self._llm as client:
514
+ response = await client.ask(
515
+ prompt=prompt,
516
+ model=kwargs.get('model', self._llm_model),
517
+ system_prompt=system_prompt,
518
+ user_id=user_id,
519
+ session_id=session_id,
520
+ temperature=kwargs.get('temperature', self._default_temperature),
521
+ tools=self.tools if self.tools else None,
522
+ **{k: v for k, v in kwargs.items() if k not in ['model', 'temperature']}
523
+ )
524
+
525
+ # Update conversation memory
526
+ if use_conversation_history and conversation_history:
527
+ assistant_content = str(response.output) if response.output is not None else (response.response or "")
528
+
529
+ turn = ConversationTurn(
530
+ turn_id=str(uuid.uuid4()),
531
+ user_id=user_id,
532
+ user_message=prompt,
533
+ assistant_response=assistant_content,
534
+ metadata={
535
+ 'user_context': user_context,
536
+ 'effective_mode': effective_mode,
537
+ 'tools_used': [tool.name for tool in response.tool_calls] if response.tool_calls else []
538
+ }
539
+ )
540
+ chatbot_key = getattr(self, 'chatbot_id', None)
541
+ if chatbot_key is not None:
542
+ chatbot_key = str(chatbot_key)
543
+ await self.conversation_memory.add_turn(
544
+ user_id,
545
+ session_id,
546
+ turn,
547
+ chatbot_id=chatbot_key
548
+ )
549
+
550
+ return response
551
+
552
+ except Exception as e:
553
+ self.logger.error(
554
+ f"Error in database ask method: {e}"
555
+ )
556
+ raise