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
parrot/tools/think.py ADDED
@@ -0,0 +1,378 @@
1
+ """
2
+ ThinkTool - A metacognitive tool for explicit agent reasoning.
3
+
4
+ This tool implements the "Thinking as a Tool" pattern, a simplified version
5
+ of the ReAct (Reasoning + Acting) paradigm. By converting the agent's internal
6
+ reasoning into an explicit, observable action, it forces Chain-of-Thought
7
+ reasoning and improves decision-making quality.
8
+
9
+ Key benefits:
10
+ - Forces explicit reasoning before complex actions
11
+ - Makes the decision-making process observable and auditable
12
+ - Prevents impulsive actions by requiring deliberation
13
+ - Improves response quality through structured thinking
14
+
15
+ Usage:
16
+ from parrot.tools import ThinkTool, ToolManager
17
+
18
+ # Basic usage
19
+ think_tool = ThinkTool()
20
+
21
+ # With custom context for specific domains
22
+ data_think = ThinkTool(
23
+ extra_context="Focus on data quality, transformations, and analysis strategy."
24
+ )
25
+
26
+ # With custom output handler
27
+ def log_thoughts(input_data: ThinkInput) -> str:
28
+ print(f"Agent thinking: {input_data.thoughts}")
29
+ return "Reasoning recorded"
30
+
31
+ think_tool = ThinkTool(output_handler=log_thoughts)
32
+
33
+ # Register with ToolManager
34
+ tool_manager = ToolManager()
35
+ tool_manager.register_tool(think_tool)
36
+
37
+ Example agent interaction:
38
+ Agent: think(thoughts="The user wants correlation analysis between sales and
39
+ temperature. I should first check data types, handle
40
+ missing values, then compute Pearson correlation...")
41
+ Agent: execute_code("df[['sales', 'temperature']].dropna().corr()")
42
+ """
43
+ from typing import Callable, Dict, Optional, Type, Union
44
+ from pydantic import Field
45
+ from .abstract import (
46
+ AbstractTool,
47
+ AbstractToolArgsSchema,
48
+ ToolResult,
49
+ )
50
+
51
+
52
+ class ThinkInput(AbstractToolArgsSchema):
53
+ """
54
+ Input schema for the ThinkTool.
55
+
56
+ The thoughts field captures the agent's reasoning process, including:
57
+ - Problem analysis and clarification
58
+ - Assumptions being made
59
+ - Planned approach or strategy
60
+ - Potential issues or edge cases to consider
61
+
62
+ Note: A 'next_step' field was intentionally omitted as it tends to
63
+ cause hallucinations and rigid behavior in practice.
64
+ """
65
+ thoughts: str = Field(
66
+ ...,
67
+ description=(
68
+ "Describe your reasoning process: analyze the problem, "
69
+ "clarify assumptions, identify potential issues, and "
70
+ "outline your planned approach before taking action."
71
+ ),
72
+ min_length=10, # Encourage substantive thinking
73
+ )
74
+
75
+
76
+ class ThinkTool(AbstractTool):
77
+ """
78
+ A metacognitive tool that forces explicit reasoning before action.
79
+
80
+ This tool implements the "Thinking as a Tool" pattern, which converts
81
+ the agent's internal reasoning into an observable, recorded action.
82
+ The primary value is in the process (forcing deliberation) rather
83
+ than the output.
84
+
85
+ Use cases:
86
+ - Complex multi-step tasks requiring careful planning
87
+ - Debugging agent decision-making processes
88
+ - Improving response quality through deliberate thinking
89
+ - Auditing and understanding agent reasoning
90
+
91
+ When NOT to use:
92
+ - Simple, straightforward tasks where it adds unnecessary latency
93
+ - When using LLM's native extended_thinking (would be redundant)
94
+ - Highly structured workflows with predetermined reasoning
95
+
96
+ Attributes:
97
+ name: Tool identifier ("think" by default)
98
+ description: Tool description for the LLM
99
+ args_schema: Pydantic model for input validation (ThinkInput)
100
+
101
+ Example:
102
+ >>> think_tool = ThinkTool()
103
+ >>> result = await think_tool.execute(
104
+ ... thoughts="Analyzing the CSV structure: I see columns for date, "
105
+ ... "amount, and category. I should parse dates first, "
106
+ ... "then aggregate by category for the monthly report."
107
+ ... )
108
+ >>> print(result.status)
109
+ 'success'
110
+ """
111
+
112
+ name: str = "think"
113
+ description: str = (
114
+ "Use when you need to reason through a problem, clarify your "
115
+ "assumptions, or plan your approach before acting. Think before "
116
+ "complex operations, multi-step tasks, or when facing ambiguity."
117
+ )
118
+ args_schema: Type[AbstractToolArgsSchema] = ThinkInput
119
+
120
+ def __init__(
121
+ self,
122
+ name: Optional[str] = None,
123
+ description: Optional[str] = None,
124
+ extra_context: str = "",
125
+ output_handler: Optional[Union[str, Callable[[ThinkInput], str]]] = None,
126
+ **kwargs
127
+ ):
128
+ """
129
+ Initialize the ThinkTool.
130
+
131
+ Args:
132
+ name: Custom tool name (default: "think")
133
+ description: Custom description (appends extra_context if provided)
134
+ extra_context: Additional instructions appended to the description.
135
+ Useful for domain-specific thinking guidance.
136
+ output_handler: Either a static string response or a callable that
137
+ receives ThinkInput and returns a string. The callable
138
+ can be used for logging, metrics, or custom processing.
139
+ **kwargs: Additional arguments passed to AbstractTool
140
+
141
+ Example:
142
+ # Domain-specific thinking tool
143
+ scraping_think = ThinkTool(
144
+ name="plan_scraping",
145
+ extra_context="Consider page structure, anti-bot measures, "
146
+ "and optimal selectors before scraping."
147
+ )
148
+
149
+ # With custom output processing
150
+ def track_reasoning(input_data):
151
+ metrics.record_thought(input_data.thoughts)
152
+ return "Reasoning tracked"
153
+
154
+ tracked_think = ThinkTool(output_handler=track_reasoning)
155
+ """
156
+ # Handle name override
157
+ if name:
158
+ self.name = name
159
+
160
+ # Handle description with extra context
161
+ if description:
162
+ self.description = description
163
+ if extra_context:
164
+ self.description = f"{self.description} {extra_context}"
165
+
166
+ # Set output handler (default: simple acknowledgment)
167
+ self._output_handler: Union[str, Callable[[ThinkInput], str]] = (
168
+ output_handler if output_handler is not None else "OK"
169
+ )
170
+
171
+ super().__init__(**kwargs)
172
+
173
+ async def _execute(
174
+ self,
175
+ thoughts: str,
176
+ **kwargs
177
+ ) -> ToolResult:
178
+ """
179
+ Execute the think operation.
180
+
181
+ The actual value of this tool is in the process of thinking,
182
+ not in the execution result. The agent's thoughts are recorded
183
+ in the tool call history, making the reasoning process observable.
184
+
185
+ Args:
186
+ thoughts: The agent's reasoning/thinking content
187
+ **kwargs: Additional arguments (ignored)
188
+
189
+ Returns:
190
+ ToolResult with status and acknowledgment message
191
+ """
192
+ # Create input model for potential handler use
193
+ input_data = ThinkInput(thoughts=thoughts)
194
+
195
+ # Generate output based on handler type
196
+ if callable(self._output_handler):
197
+ try:
198
+ output = self._output_handler(input_data)
199
+ except Exception as e:
200
+ self.logger.warning(f"Output handler failed: {e}")
201
+ output = "OK"
202
+ else:
203
+ output = self._output_handler
204
+
205
+ return ToolResult(
206
+ status="success",
207
+ result=output,
208
+ metadata={
209
+ "thought_length": len(thoughts),
210
+ "tool_type": "metacognitive",
211
+ }
212
+ )
213
+
214
+
215
+ # =============================================================================
216
+ # Specialized Variants
217
+ # =============================================================================
218
+
219
+ class DataAnalysisThinkTool(ThinkTool):
220
+ """
221
+ Specialized thinking tool for data analysis tasks.
222
+
223
+ Guides the agent to consider data quality, transformations,
224
+ and analysis strategy before executing data operations.
225
+
226
+ Example:
227
+ >>> tool = DataAnalysisThinkTool()
228
+ >>> result = await tool.execute(
229
+ ... thoughts="Dataset has 10k rows with 3 date columns. "
230
+ ... "I'll parse dates, check for nulls in the amount "
231
+ ... "column, then create a pivot table by month."
232
+ ... )
233
+ """
234
+
235
+ name: str = "think_data_analysis"
236
+ description: str = (
237
+ "Use before data analysis operations. Reason about data quality, "
238
+ "required transformations, potential issues (nulls, types, outliers), "
239
+ "and your analysis strategy."
240
+ )
241
+
242
+
243
+ class ScrapingPlanTool(ThinkTool):
244
+ """
245
+ Specialized thinking tool for web scraping tasks.
246
+
247
+ Guides the agent to plan scraping strategy considering page structure,
248
+ anti-bot measures, and selector reliability.
249
+
250
+ Example:
251
+ >>> tool = ScrapingPlanTool()
252
+ >>> result = await tool.execute(
253
+ ... thoughts="Target page uses infinite scroll with lazy loading. "
254
+ ... "I'll use incremental scrolling with dynamic waits. "
255
+ ... "Product cards have consistent class 'product-item'."
256
+ ... )
257
+ """
258
+
259
+ name: str = "plan_scraping"
260
+ description: str = (
261
+ "Use before web scraping operations. Plan your approach considering "
262
+ "page structure (static/dynamic/SPA), anti-bot measures, pagination "
263
+ "type, and selector strategy. Identify reliable selectors and "
264
+ "potential failure points."
265
+ )
266
+
267
+
268
+ class QueryPlanTool(ThinkTool):
269
+ """
270
+ Specialized thinking tool for database query planning.
271
+
272
+ Guides the agent to consider query optimization, table relationships,
273
+ and potential performance issues.
274
+
275
+ Example:
276
+ >>> tool = QueryPlanTool()
277
+ >>> result = await tool.execute(
278
+ ... thoughts="Need to join orders with customers and products. "
279
+ ... "Orders table is large (~5M rows), should filter by "
280
+ ... "date range first. Index exists on order_date."
281
+ ... )
282
+ """
283
+
284
+ name: str = "plan_query"
285
+ description: str = (
286
+ "Use before complex database queries. Consider table relationships, "
287
+ "query optimization (indexes, filters), potential performance issues, "
288
+ "and the best approach to retrieve the required data."
289
+ )
290
+
291
+
292
+ class RAGRetrievalThinkTool(ThinkTool):
293
+ """
294
+ Specialized thinking tool for RAG retrieval strategy.
295
+
296
+ Guides the agent to plan retrieval approach based on query type,
297
+ expected document relevance, and retrieval method selection.
298
+
299
+ Particularly useful for Adaptive Agentic RAG implementations.
300
+
301
+ Example:
302
+ >>> tool = RAGRetrievalThinkTool()
303
+ >>> result = await tool.execute(
304
+ ... thoughts="User query is factual and specific. Dense retrieval "
305
+ ... "should work well. Will use top-5 chunks with "
306
+ ... "reranking. No need for hybrid search here."
307
+ ... )
308
+ """
309
+
310
+ name: str = "plan_retrieval"
311
+ description: str = (
312
+ "Use before RAG retrieval operations. Analyze query type (factual, "
313
+ "exploratory, comparative), decide on retrieval strategy (dense, "
314
+ "sparse, hybrid), determine chunk count, and consider if reranking "
315
+ "or query expansion is needed."
316
+ )
317
+
318
+
319
+ # =============================================================================
320
+ # Factory Function
321
+ # =============================================================================
322
+
323
+ def create_think_tool(
324
+ domain: Optional[str] = None,
325
+ name: Optional[str] = None,
326
+ extra_context: str = "",
327
+ output_handler: Optional[Union[str, Callable[[ThinkInput], str]]] = None,
328
+ ) -> ThinkTool:
329
+ """
330
+ Factory function to create domain-specific ThinkTool instances.
331
+
332
+ Args:
333
+ domain: Predefined domain ('data', 'scraping', 'query', 'rag')
334
+ or None for generic ThinkTool
335
+ name: Custom tool name (overrides domain default)
336
+ extra_context: Additional context appended to description
337
+ output_handler: Custom output handler
338
+
339
+ Returns:
340
+ Configured ThinkTool instance
341
+
342
+ Example:
343
+ # Using predefined domain
344
+ data_tool = create_think_tool(domain='data')
345
+
346
+ # Custom configuration
347
+ custom_tool = create_think_tool(
348
+ domain='scraping',
349
+ name='plan_ecommerce_scrape',
350
+ extra_context='Consider rate limiting for this e-commerce site.'
351
+ )
352
+ """
353
+ domain_map: Dict[str, Type[ThinkTool]] = {
354
+ 'data': DataAnalysisThinkTool,
355
+ 'data_analysis': DataAnalysisThinkTool,
356
+ 'scraping': ScrapingPlanTool,
357
+ 'web_scraping': ScrapingPlanTool,
358
+ 'query': QueryPlanTool,
359
+ 'database': QueryPlanTool,
360
+ 'rag': RAGRetrievalThinkTool,
361
+ 'retrieval': RAGRetrievalThinkTool,
362
+ }
363
+
364
+ if domain and domain.lower() in domain_map:
365
+ tool_class = domain_map[domain.lower()]
366
+ tool = tool_class(
367
+ name=name,
368
+ extra_context=extra_context,
369
+ output_handler=output_handler,
370
+ )
371
+ else:
372
+ tool = ThinkTool(
373
+ name=name,
374
+ extra_context=extra_context,
375
+ output_handler=output_handler,
376
+ )
377
+
378
+ return tool
@@ -0,0 +1,298 @@
1
+ """
2
+ AbstractToolkit for creating collections of tools from class methods.
3
+ """
4
+ import inspect
5
+ from typing import Dict, List, Type, Optional, Any, get_type_hints
6
+ from abc import ABC
7
+ from pydantic import BaseModel, create_model, Field
8
+ from navconfig.logging import logging
9
+ from datamodel.parsers.json import json_decoder, json_encoder # noqa pylint: disable=E0611
10
+ from ..conf import BASE_STATIC_URL
11
+ from .abstract import AbstractTool, AbstractToolArgsSchema
12
+
13
+
14
+ class ToolkitTool(AbstractTool):
15
+ """
16
+ A specialized AbstractTool that wraps a method from a toolkit.
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ name: str,
22
+ bound_method: callable,
23
+ description: str = None,
24
+ args_schema: Type[BaseModel] = None,
25
+ **kwargs
26
+ ):
27
+ """
28
+ Initialize a toolkit tool.
29
+
30
+ Args:
31
+ name: Tool name
32
+ bound_method: The bound coroutine method to wrap
33
+ description: Tool description
34
+ args_schema: Pydantic model for arguments
35
+ **kwargs: Additional arguments
36
+ """
37
+ self.bound_method = bound_method
38
+
39
+ # Set up the tool
40
+ super().__init__(
41
+ name=name,
42
+ description=description or bound_method.__doc__ or f"Tool: {name}",
43
+ **kwargs
44
+ )
45
+
46
+ # Set the args schema
47
+ if args_schema:
48
+ self.args_schema = args_schema
49
+ else:
50
+ # Try to generate schema from method signature
51
+ self.args_schema = self._generate_args_schema_from_method()
52
+
53
+ def _generate_args_schema_from_method(self) -> Type[BaseModel]:
54
+ """
55
+ Generate a Pydantic schema from the method's type hints.
56
+ """
57
+ try:
58
+ # Get method signature
59
+ sig = inspect.signature(self.bound_method)
60
+ type_hints = get_type_hints(self.bound_method)
61
+
62
+ # Build fields for Pydantic model
63
+ fields = {}
64
+
65
+ for param_name, param in sig.parameters.items():
66
+ # Skip 'self' parameter (shouldn't be there for bound methods, but just in case)
67
+ if param_name == 'self':
68
+ continue
69
+
70
+ # Get type hint
71
+ param_type = type_hints.get(param_name, Any)
72
+
73
+ # Handle Optional types and defaults
74
+ if param.default == param.empty:
75
+ # Required parameter
76
+ default_value = ...
77
+ else:
78
+ # Has default value
79
+ default_value = param.default
80
+
81
+ # Create field with description based on parameter name
82
+ description = f"Parameter: {param_name}"
83
+ fields[param_name] = (param_type, Field(default=default_value, description=description))
84
+
85
+ # Create dynamic Pydantic model
86
+ if fields:
87
+ return create_model(
88
+ f"{self.name}Args",
89
+ **fields
90
+ )
91
+ else:
92
+ # No parameters, return base schema
93
+ return AbstractToolArgsSchema
94
+
95
+ except Exception as e:
96
+ self.logger.warning(f"Could not generate schema for {self.name}: {e}")
97
+ return AbstractToolArgsSchema
98
+
99
+ async def _execute(self, **kwargs) -> Any:
100
+ """
101
+ Execute the toolkit method.
102
+
103
+ Args:
104
+ **kwargs: Method arguments
105
+
106
+ Returns:
107
+ Method result
108
+ """
109
+ return await self.bound_method(**kwargs)
110
+
111
+
112
+ class AbstractToolkit(ABC):
113
+ """
114
+ Abstract base class for creating toolkits - collections of related tools.
115
+
116
+ A toolkit automatically converts all public async methods into tools.
117
+ Each method becomes a tool with:
118
+ - Name: method name
119
+ - Description: method docstring
120
+ - Schema: automatically generated from type hints
121
+
122
+ Usage:
123
+ class MyToolkit(AbstractToolkit):
124
+ async def search_web(self, query: str) -> str:
125
+ '''Search the web for information.'''
126
+ # Implementation here
127
+ return result
128
+
129
+ async def calculate(self, expression: str) -> float:
130
+ '''Calculate a mathematical expression.'''
131
+ # Implementation here
132
+ return result
133
+
134
+ # Get all tools
135
+ toolkit = MyToolkit()
136
+ tools = toolkit.get_tools()
137
+ """
138
+
139
+ # Configuration
140
+ input_class: Optional[Type[BaseModel]] = None # Default input schema (optional)
141
+ return_direct: bool = False # Whether tools return results directly
142
+ json_encoder: Type[Any] = json_encoder
143
+ json_decoder: Type[Any] = json_decoder
144
+ base_url: str = BASE_STATIC_URL
145
+
146
+ def __init__(self, **kwargs):
147
+ """
148
+ Initialize the toolkit.
149
+
150
+ Args:
151
+ **kwargs: Configuration options
152
+ """
153
+ # Configuration
154
+ self.return_direct = kwargs.get('return_direct', self.return_direct)
155
+ self.base_url = kwargs.get('base_url', self.base_url)
156
+
157
+ # Tool cache
158
+ self._tool_cache: Dict[str, ToolkitTool] = {}
159
+ self._tools_generated = False
160
+
161
+ async def start(self) -> None:
162
+ """
163
+ Optional startup logic for the toolkit.
164
+ Override in subclasses if needed.
165
+ """
166
+ pass
167
+
168
+ async def stop(self) -> None:
169
+ """
170
+ Optional shutdown logic for the toolkit.
171
+ Override in subclasses if needed.
172
+ """
173
+ pass
174
+
175
+ async def cleanup(self) -> None:
176
+ """
177
+ Optional cleanup logic for the toolkit.
178
+ Override in subclasses if needed.
179
+ """
180
+ pass
181
+
182
+ def get_tools(self) -> List[AbstractTool]:
183
+ """
184
+ Get all tools from this toolkit.
185
+
186
+ Inspects all public async methods and converts them to tools.
187
+
188
+ Returns:
189
+ List of AbstractTool instances
190
+ """
191
+ if self._tools_generated and self._tool_cache:
192
+ return list(self._tool_cache.values())
193
+
194
+ tools = []
195
+
196
+ # Inspect all methods - get bound methods
197
+ for name in dir(self):
198
+ # Skip private methods and non-methods
199
+ if name.startswith('_'):
200
+ continue
201
+
202
+ # Skip toolkit management methods
203
+ if name in ('get_tools', 'get_tool', 'list_tool_names', 'start', 'stop', 'cleanup'):
204
+ continue
205
+
206
+ # Get the attribute
207
+ attr = getattr(self, name)
208
+
209
+ # Check if it's a coroutine function
210
+ if not inspect.iscoroutinefunction(attr):
211
+ continue
212
+
213
+ # Create tool from bound method
214
+ tool = self._create_tool_from_method(name, attr)
215
+ tools.append(tool)
216
+ self._tool_cache[name] = tool
217
+
218
+ self._tools_generated = True
219
+ return tools
220
+
221
+ def get_tool(self, name: str) -> Optional[AbstractTool]:
222
+ """
223
+ Get a specific tool by name.
224
+
225
+ Args:
226
+ name: Tool name
227
+
228
+ Returns:
229
+ AbstractTool instance or None if not found
230
+ """
231
+ if not self._tools_generated:
232
+ self.get_tools() # Ensure tools are generated
233
+
234
+ return self._tool_cache.get(name)
235
+
236
+ def list_tool_names(self) -> List[str]:
237
+ """
238
+ Get a list of all tool names in this toolkit.
239
+
240
+ Returns:
241
+ List of tool names
242
+ """
243
+ if not self._tools_generated:
244
+ self.get_tools()
245
+
246
+ return list(self._tool_cache.keys())
247
+
248
+ def _create_tool_from_method(self, name: str, bound_method: callable) -> ToolkitTool:
249
+ """
250
+ Create a ToolkitTool from a bound method.
251
+
252
+ Args:
253
+ name: Method name
254
+ bound_method: The bound coroutine method
255
+
256
+ Returns:
257
+ ToolkitTool instance
258
+ """
259
+ # Get description from docstring
260
+ description = bound_method.__doc__ or f"Tool: {name}"
261
+ description = description.strip()
262
+
263
+ # Determine args schema - prioritize method-specific schema
264
+ args_schema = getattr(bound_method, '_args_schema', None)
265
+
266
+ # If no custom schema is defined, always generate from method signature
267
+ # This ensures each method only gets the parameters it actually needs
268
+ if not args_schema:
269
+ args_schema = None # Let ToolkitTool generate it from the method signature
270
+
271
+ # Create the tool
272
+ tool = ToolkitTool(
273
+ name=name,
274
+ bound_method=bound_method,
275
+ description=description,
276
+ args_schema=args_schema,
277
+ return_direct=self.return_direct
278
+ )
279
+
280
+ return tool
281
+
282
+ def get_toolkit_info(self) -> Dict[str, Any]:
283
+ """
284
+ Get information about this toolkit.
285
+
286
+ Returns:
287
+ Dictionary with toolkit information
288
+ """
289
+ tools = self.get_tools()
290
+
291
+ return {
292
+ "toolkit_name": self.__class__.__name__,
293
+ "tool_count": len(tools),
294
+ "tool_names": [tool.name for tool in tools],
295
+ "tool_descriptions": {tool.name: tool.description for tool in tools},
296
+ "return_direct": self.return_direct,
297
+ "base_url": self.base_url
298
+ }