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,576 @@
1
+ """
2
+ Browser Action System for AI-Parrot WebScrapingTool
3
+ Object-oriented action hierarchy for LLM-directed browser automation
4
+ """
5
+ from __future__ import annotations
6
+ from typing import Optional, List, Dict, Any, Union, Literal, Annotated
7
+ from abc import ABC
8
+ import time
9
+ from dataclasses import dataclass, field
10
+ from pydantic import BaseModel, Field, field_validator
11
+ from bs4 import BeautifulSoup
12
+
13
+
14
+ class BrowserAction(BaseModel, ABC):
15
+ """Base class for all browser actions"""
16
+ name: str = Field(default="", description="Optional name for this action")
17
+ # add a generic action field so the key exists on all models
18
+ action: str = Field(default="", description="Action opcode used for union discrimination")
19
+ description: str = Field(default="", description="Human-readable description of this action")
20
+ timeout: Optional[int] = Field(
21
+ default=None, description="Maximum time to wait for action completion (seconds), None for no wait."
22
+ )
23
+
24
+ def get_action_type(self) -> str:
25
+ """Return the action type identifier"""
26
+ return self.name
27
+
28
+
29
+ class Navigate(BrowserAction):
30
+ """Navigate to a URL"""
31
+ name: str = 'navigate'
32
+ action: Literal["navigate"] = "navigate"
33
+ url: str = Field(description="Target URL to navigate to")
34
+ description: str = Field(default="Navigate to a URL", description="navigating to a specific URL")
35
+
36
+
37
+ class Click(BrowserAction):
38
+ """Click on a web page element"""
39
+ name: str = "click"
40
+ action: Literal["click"] = "click"
41
+ selector: str = Field(description="CSS or XPATH selector to identify the target element")
42
+ description: str = Field(default="Click on an element", description="clicking on a specific element")
43
+ selector_type: Literal["css", "xpath", "text"] = Field(
44
+ default="css",
45
+ description="Type of selector: 'css' for CSS selectors, 'xpath' for XPath, 'text' for text matching"
46
+ )
47
+ click_type: Literal["single", "double", "right"] = Field(
48
+ default="single",
49
+ description="Type of click action"
50
+ )
51
+ wait_after_click: Optional[str] = Field(
52
+ default=None,
53
+ description="Optional CSS selector of element to wait for after clicking"
54
+ )
55
+ wait_timeout: int = Field(default=2, description="Timeout for post-click wait (seconds)")
56
+ no_wait: bool = Field(default=False, description="Skip any waiting after click")
57
+
58
+ class Fill(BrowserAction):
59
+ """Fill text into an input field"""
60
+ name: str = 'fill'
61
+ action: Literal['fill'] = 'fill'
62
+ description: str = Field(default="Fill an input field", description="Filling a specific input field")
63
+ selector: str = Field(description="CSS selector to identify the input field")
64
+ value: str = Field(description="Text to enter into the field")
65
+ clear_first: bool = Field(default=True, description="Clear existing content before filling")
66
+ press_enter: bool = Field(default=False, description="Press Enter after filling")
67
+
68
+ class Select(BrowserAction):
69
+ """ Select an option from a dropdown/select element."""
70
+ name: str = 'select'
71
+ action: Literal['select'] = 'select'
72
+ description: str = Field(
73
+ default="Select dropdown option",
74
+ description="Selecting an option from a dropdown/select element"
75
+ )
76
+ selector: str = Field(description="CSS selector to identify the select element")
77
+ value: Optional[str] = Field(
78
+ default=None,
79
+ description="Value attribute of the option to select"
80
+ )
81
+ text: Optional[str] = Field(
82
+ default=None,
83
+ description="Visible text of the option to select"
84
+ )
85
+ index: Optional[int] = Field(
86
+ default=None,
87
+ description="Index of the option to select (0-based)"
88
+ )
89
+ by: Literal['value', 'text', 'index'] = Field(
90
+ default='value',
91
+ description="Selection method: 'value' (by value attribute), 'text' (by visible text), or 'index' (by position)"
92
+ )
93
+ blur_after: bool = Field(
94
+ default=True,
95
+ description="Trigger blur/change events after selection (lose focus)"
96
+ )
97
+ wait_after_select: Optional[str] = Field(
98
+ default=None,
99
+ description="Optional CSS selector to wait for after selecting"
100
+ )
101
+ wait_timeout: int = Field(
102
+ default=2,
103
+ description="Timeout for post-select wait (seconds)"
104
+ )
105
+
106
+ @field_validator('value', 'text', 'index')
107
+ @classmethod
108
+ def validate_selection_params(cls, v, info):
109
+ """Ensure at least one selection parameter is provided"""
110
+ if info.data.get('by') == 'value' and not info.data.get('value'):
111
+ raise ValueError("'value' must be provided when by='value'")
112
+ if info.data.get('by') == 'text' and not info.data.get('text'):
113
+ raise ValueError("'text' must be provided when by='text'")
114
+ if info.data.get('by') == 'index' and info.data.get('index') is None:
115
+ raise ValueError("'index' must be provided when by='index'")
116
+ return v
117
+
118
+
119
+ class Evaluate(BrowserAction):
120
+ """Execute JavaScript code in the browser context"""
121
+ name: str = 'evaluate'
122
+ action: Literal['evaluate'] = 'evaluate'
123
+ description: str = Field(default="Evaluate JavaScript", description="Executing custom JavaScript code")
124
+ script: Optional[str] = Field(default=None, description="JavaScript code to execute")
125
+ script_file: Optional[str] = Field(default=None, description="Path to JavaScript file to load and execute")
126
+ args: List[Any] = Field(default_factory=list, description="Arguments to pass to the script")
127
+ return_value: bool = Field(
128
+ default=True,
129
+ description="Whether to return the script's result"
130
+ )
131
+
132
+ @field_validator('script', 'script_file')
133
+ @classmethod
134
+ def validate_script_source(cls, v, info):
135
+ """Ensure either script or script_file is provided, but not both"""
136
+ script = info.data.get('script')
137
+ if script and v:
138
+ raise ValueError("Provide either 'script' or 'script_file', not both")
139
+ return v
140
+
141
+
142
+ class PressKey(BrowserAction):
143
+ """Press keyboard keys"""
144
+ name: str = 'press_key'
145
+ action: Literal['press_key'] = 'press_key'
146
+ description: str = Field(default="Press keyboard keys", description="Pressing specified keyboard keys")
147
+ keys: List[str] = Field(description="List of keys to press (e.g., ['Tab', 'Enter', 'Escape'])")
148
+ sequential: bool = Field(default=True, description="Press keys sequentially or as a combination")
149
+ target: Optional[str] = Field(default=None, description="CSS selector to focus before pressing keys")
150
+
151
+
152
+ class Refresh(BrowserAction):
153
+ """Reload the current web page"""
154
+ name: str = 'refresh'
155
+ action: Literal['refresh'] = 'refresh'
156
+ description: str = Field(default="Refresh the page", description="Reloading the current page")
157
+ hard: bool = Field(default=False, description="Perform hard refresh (clear cache)")
158
+
159
+
160
+ class Back(BrowserAction):
161
+ """Navigate back to the previous page"""
162
+ name: str = 'back'
163
+ action: Literal['back'] = 'back'
164
+ description: str = Field(default="Go back in history", description="Navigating back in browser history")
165
+ steps: int = Field(default=1, description="Number of steps to go back in history")
166
+
167
+
168
+ class Scroll(BrowserAction):
169
+ """Scroll the page or an element"""
170
+ name: str = 'scroll'
171
+ action: Literal['scroll'] = 'scroll'
172
+ description: str = Field(default="Scroll the page or an element", description="Scrolling the page or a specific element")
173
+ direction: Literal["up", "down", "top", "bottom"] = Field(description="Scroll direction")
174
+ amount: Optional[int] = Field(default=None, description="Pixels to scroll (if not to top/bottom)")
175
+ selector: Optional[str] = Field(default=None, description="CSS selector of element to scroll (default: page)")
176
+ smooth: bool = Field(default=True, description="Use smooth scrolling animation")
177
+
178
+
179
+ class GetCookies(BrowserAction):
180
+ """Extract and evaluate cookies"""
181
+ name: str = 'get_cookies'
182
+ action: Literal['get_cookies'] = 'get_cookies'
183
+ description: str = Field(default="Get cookies", description="Extracting cookies from the browser")
184
+ names: Optional[List[str]] = Field(default=None, description="Specific cookie names to retrieve (None = all)")
185
+ domain: Optional[str] = Field(default=None, description="Filter cookies by domain")
186
+
187
+
188
+ class SetCookies(BrowserAction):
189
+ """Set cookies on the current page or domain"""
190
+ name: str = 'set_cookies'
191
+ action: Literal['set_cookies'] = 'set_cookies'
192
+ description: str = Field(default="Set cookies", description="Setting cookies in the browser")
193
+ cookies: List[Dict[str, Any]] = Field(
194
+ description="List of cookie objects with 'name', 'value', and optional 'domain', 'path', 'secure', etc."
195
+ )
196
+
197
+
198
+ class Wait(BrowserAction):
199
+ """Wait for a condition to be met"""
200
+ name: str = 'wait'
201
+ action: Literal['wait'] = 'wait'
202
+ description: str = Field(default="Wait for a condition", description="Waiting for a specific condition")
203
+ condition: Optional[str] = Field(default=None, description="Value for the condition (selector, URL substring, etc.)")
204
+ condition_type: Literal["simple", "selector", "url_contains", "url_is", "title_contains", "custom"] = Field(
205
+ default="selector",
206
+ description="Type of condition to wait for"
207
+ )
208
+ custom_script: Optional[str] = Field(
209
+ default=None,
210
+ description="JavaScript that returns true when condition is met (for custom type)"
211
+ )
212
+ timeout: int = Field(default=None, description="Maximum wait time (seconds)")
213
+
214
+
215
+ class Authenticate(BrowserAction):
216
+ """Handle authentication flows"""
217
+ name: str = 'authenticate'
218
+ action: Literal['authenticate'] = 'authenticate'
219
+ description: str = Field(default="Authenticate user", description="Performing user authentication")
220
+ method: Literal["form", "basic", "oauth", "custom"] = Field(default="form", description="Authentication method")
221
+ username: Optional[str] = Field(default=None, description="Username/email")
222
+ password: Optional[str] = Field(default=None, description="Password")
223
+ username_selector: str = Field(default="#username", description="CSS selector for username field")
224
+ enter_on_username: bool = Field(
225
+ default=False,
226
+ description="Press Enter after filling username (for multi-step logins)"
227
+ )
228
+ password_selector: str = Field(default="#password", description="CSS selector for password field")
229
+ submit_selector: str = Field(
230
+ default='input[type="submit"], button[type="submit"]',
231
+ description="CSS selector for submit button"
232
+ )
233
+ custom_steps: Optional[List[BrowserAction]] = Field(
234
+ default=None,
235
+ description="Custom action sequence for complex authentication"
236
+ )
237
+ token: Optional[str] = Field(
238
+ default=None,
239
+ description="The bearer token value (for 'bearer' method)"
240
+ )
241
+ header_name: str = Field(
242
+ default="Authorization",
243
+ description="The name of the HTTP header to set, e.g., 'Authorization' or 'X-API-Key' (for 'bearer' method)"
244
+ )
245
+ header_value_format: str = Field(
246
+ default="Bearer {}",
247
+ description="Format for the header value, where '{}' will be replaced by the token (for 'bearer' method)"
248
+ )
249
+
250
+
251
+ class AwaitHuman(BrowserAction):
252
+ """Pause and wait for human intervention"""
253
+ name: str = 'await_human'
254
+ action: Literal['await_human'] = 'await_human'
255
+ description: str = Field(default="Wait for human intervention", description="Waiting for user to complete a task")
256
+ target: Optional[str] = Field(
257
+ default=None,
258
+ description="Target or condition value (e.g., CSS selector) to detect completion"
259
+ )
260
+ condition_type: Literal["selector", "url_contains", "title_contains", "manual"] = Field(
261
+ default="selector",
262
+ description="Condition type that indicates human completed their task"
263
+ )
264
+ message: str = Field(
265
+ default="Waiting for human intervention...",
266
+ description="Message to display while waiting"
267
+ )
268
+ timeout: int = Field(default=300, description="Maximum wait time (default: 5 minutes)")
269
+
270
+
271
+ class AwaitKeyPress(BrowserAction):
272
+ """Wait for human to press a key in console"""
273
+ name: str = 'await_keypress'
274
+ action: Literal['await_keypress'] = 'await_keypress'
275
+ description: str = Field(default="Wait for key press", description="Waiting for user to press a key")
276
+ expected_key: Optional[str] = Field(
277
+ default=None,
278
+ description="Specific key to wait for (None = any key)"
279
+ )
280
+ message: str = Field(
281
+ default="Press any key to continue...",
282
+ description="Message to display to user"
283
+ )
284
+ timeout: int = Field(default=300, description="Maximum wait time (default: 5 minutes)")
285
+
286
+ class AwaitBrowserEvent(BrowserAction):
287
+ """Wait for human interaction in the browser"""
288
+ name: str = 'await_browser_event'
289
+ action: Literal['await_browser_event'] = 'await_browser_event'
290
+ target: Optional[Union[str, Dict[str, Any]]] = Field(
291
+ default=None,
292
+ description="Target or condition value to detect completion (e.g., key combo, local storage key)"
293
+ )
294
+ description: str = Field(
295
+ default="Wait for browser event",
296
+ description="Waiting for user to trigger a browser event"
297
+ )
298
+ wait_condition: Dict[str, Any] = Field(
299
+ default_factory=dict,
300
+ description="Condition to detect human completion (e.g., key combo, button or local storage key)"
301
+ )
302
+ timeout: int = Field(default=300, description="Maximum wait time (default: 5 minutes)")
303
+
304
+ def get_action_type(self) -> str:
305
+ return "await_browser_event"
306
+
307
+ class GetText(BrowserAction):
308
+ """Extract pure text content from elements matching selector"""
309
+ name: str = 'get_text'
310
+ action: Literal['get_text'] = 'get_text'
311
+ description: str = Field(default="Extract text content", description="Extracting text from elements")
312
+ selector: str = Field(description="CSS selector to identify elements to extract text from")
313
+ multiple: bool = Field(default=False, description="Extract from all matching elements or just first")
314
+ extract_name: str = Field(default="extracted_text", description="Name for the extracted data in results")
315
+
316
+ class Screenshot(BrowserAction):
317
+ """Take a screenshot of the page or a specific element"""
318
+ name: str = 'screenshot'
319
+ action: Literal['screenshot'] = 'screenshot'
320
+ description: str = Field(default="Take screenshot", description="Taking a screenshot")
321
+ selector: Optional[str] = Field(default=None, description="CSS selector of element to screenshot (None = full page)")
322
+ full_page: bool = Field(default=True, description="Capture full scrollable page")
323
+ output_path: Optional[str] = Field(default=None, description="Directory path to save screenshot (e.g., 'screenshots/') ")
324
+ output_name: Optional[str] = Field(default=None, description="Filename for the screenshot (e.g., 'page.png'). If None, a timestamped name will be used.")
325
+ return_base64: bool = Field(default=False, description="Return screenshot as base64 string in results")
326
+
327
+ def get_filename(self) -> str:
328
+ """Generate a filename for the screenshot"""
329
+ if self.output_name:
330
+ if not self.output_name.lower().endswith('.png'): # pylint: disable=E1101 # noqa
331
+ return f"{self.output_name}.png"
332
+ return self.output_name
333
+ return f"screenshot_{int(time.time())}.png"
334
+
335
+ class GetHTML(BrowserAction):
336
+ """Extract complete HTML content from elements matching selector"""
337
+ name: str = 'get_html'
338
+ action: Literal['get_html'] = 'get_html'
339
+ description: str = Field(default="Extract HTML content", description="Extracting HTML from elements")
340
+ selector: str = Field(description="CSS or XPath selector to identify elements to extract HTML from")
341
+ selector_type: Literal["css", "xpath"] = Field(
342
+ default="css",
343
+ description="Type of selector: 'css' for CSS selectors, 'xpath' for XPath"
344
+ )
345
+ multiple: bool = Field(default=False, description="Extract from all matching elements or just first")
346
+ extract_name: str = Field(default="extracted_html", description="Name for the extracted data in results")
347
+
348
+
349
+ class WaitForDownload(BrowserAction):
350
+ """Wait for a file download to complete"""
351
+ name: str = 'wait_for_download'
352
+ action: Literal['wait_for_download'] = 'wait_for_download'
353
+ description: str = Field(default="Wait for download", description="Waiting for file download to complete")
354
+ filename_pattern: Optional[str] = Field(
355
+ default=None,
356
+ description="Filename pattern to match (e.g., '*.pdf', 'report*.xlsx'). None = any file"
357
+ )
358
+ download_path: Optional[str] = Field(
359
+ default=None,
360
+ description="Directory to monitor for downloads (None = browser default download directory)"
361
+ )
362
+ timeout: int = Field(default=60, description="Maximum time to wait for download (seconds)")
363
+ move_to: Optional[str] = Field(
364
+ default=None,
365
+ description="Optional path to move the downloaded file after completion"
366
+ )
367
+ delete_after: bool = Field(default=False, description="Delete the file after successful download detection")
368
+
369
+
370
+ class UploadFile(BrowserAction):
371
+ """Upload a file to a file input element"""
372
+ name: str = 'upload_file'
373
+ action: Literal['upload_file'] = 'upload_file'
374
+ description: str = Field(default="Upload file", description="Uploading a file to an input element")
375
+ selector: str = Field(description="CSS selector for the file input element")
376
+ file_path: str = Field(description="Absolute or relative path to the file to upload")
377
+ wait_after_upload: Optional[str] = Field(
378
+ default=None,
379
+ description="Optional CSS selector to wait for after upload (e.g., confirmation message)"
380
+ )
381
+ wait_timeout: int = Field(default=10, description="Timeout for post-upload wait (seconds)")
382
+ multiple_files: bool = Field(default=False, description="Whether uploading multiple files")
383
+ file_paths: Optional[List[str]] = Field(
384
+ default=None,
385
+ description="List of file paths for multiple file upload"
386
+ )
387
+
388
+ class Conditional(BrowserAction):
389
+ """Execute actions conditionally based on a JavaScript expression"""
390
+ name: str = 'conditional'
391
+ action: Literal['conditional'] = 'conditional'
392
+ description: str = Field(default="Conditional action execution", description="Executing actions based on a condition")
393
+ target: Optional[str] = Field(
394
+ default=None,
395
+ description="Target or condition value (e.g., XPATH or CSS selector) to detect completion"
396
+ )
397
+ target_type: Literal["css", "xpath"] = Field(
398
+ default="css",
399
+ description="Type of target selector"
400
+ )
401
+ condition_type: Literal["text_contains", "exists", "not_exists", "text_equals", "attribute_equals"] = Field(
402
+ default="text_contains",
403
+ description="Condition type that determines how to evaluate the target"
404
+ )
405
+ expected_value: str = Field(description="Value that evaluates to true or false")
406
+ timeout: int = Field(default=5, description="Maximum time to wait for condition evaluation (seconds)")
407
+ actions_if_true: Optional[List["ActionList"]] = Field(
408
+ default=None,
409
+ description="List of actions to execute if condition is true"
410
+ )
411
+ actions_if_false: Optional[List["ActionList"]] = Field(
412
+ default=None,
413
+ description="List of actions to execute if condition is false"
414
+ )
415
+
416
+ class Loop(BrowserAction):
417
+ """Repeat a sequence of actions multiple times"""
418
+ name: str = "loop"
419
+ action: Literal["loop"] = "loop"
420
+ description: str = Field(default="Loop over actions", description="Repeating a set of actions")
421
+ actions: List["ActionList"] = Field(description="List of actions to execute in each iteration")
422
+ iterations: Optional[int] = Field(default=None, description="Number of times to repeat (None = until condition)")
423
+ condition: Optional[str] = Field(
424
+ default=None,
425
+ description="JavaScript condition to evaluate; loop continues while true"
426
+ )
427
+ values: Optional[List[Any]] = Field(
428
+ default=None,
429
+ description="List of values to iterate over. When provided, iterations is automatically set to len(values)"
430
+ )
431
+ value_name: Optional[str] = Field(
432
+ default="value",
433
+ description="Name of the variable to hold the current value in each iteration"
434
+ )
435
+ break_on_error: bool = Field(default=True, description="Stop loop if any action fails")
436
+ max_iterations: int = Field(default=100, description="Safety limit for condition-based loops")
437
+ start_index: int = Field(
438
+ default=0,
439
+ description="Starting index for iteration counter (default: 0 for 0-based indexing)"
440
+ )
441
+ do_replace: bool = Field(
442
+ default=True,
443
+ description="Whether to replace {{index}} and {{index_1}} in action parameters"
444
+ )
445
+
446
+ ActionList = Annotated[
447
+ Union[
448
+ Navigate, Click, Fill, Select, Evaluate, PressKey, Refresh, Back, Scroll,
449
+ GetCookies, SetCookies, Wait, Authenticate,
450
+ AwaitHuman, AwaitKeyPress, AwaitBrowserEvent,
451
+ GetText, GetHTML, WaitForDownload, UploadFile, Screenshot, Loop, Conditional
452
+ ],
453
+ Field(discriminator='action')
454
+ ]
455
+
456
+
457
+ # Update Forward References (required for Loop containing BrowserAction)
458
+ Authenticate.model_rebuild()
459
+ Loop.model_rebuild()
460
+ Conditional.model_rebuild()
461
+
462
+ # Map action types to classes
463
+ ACTION_MAP = {
464
+ "navigate": Navigate,
465
+ "click": Click,
466
+ "fill": Fill,
467
+ "select": Select,
468
+ "evaluate": Evaluate,
469
+ "press_key": PressKey,
470
+ "refresh": Refresh,
471
+ "back": Back,
472
+ "scroll": Scroll,
473
+ "get_cookies": GetCookies,
474
+ "set_cookies": SetCookies,
475
+ "wait": Wait,
476
+ "authenticate": Authenticate,
477
+ "await_human": AwaitHuman,
478
+ "await_keypress": AwaitKeyPress,
479
+ "await_browser_event": AwaitBrowserEvent,
480
+ "loop": Loop,
481
+ "get_text": GetText,
482
+ "get_html": GetHTML,
483
+ "wait_for_download": WaitForDownload,
484
+ "upload_file": UploadFile,
485
+ "screenshot": Screenshot,
486
+ "conditional": Conditional
487
+ } # :contentReference[oaicite:4]{index=4}
488
+
489
+ @dataclass
490
+ class ScrapingStep:
491
+ """
492
+ ScrapingStep that wraps a BrowserAction.
493
+
494
+ Used to define a step in a scraping sequence.
495
+
496
+ Example:
497
+ {
498
+ 'action': 'navigate',
499
+ 'target': 'https://www.consumeraffairs.com/homeowners/service-protection-advantage.html',
500
+ 'description': 'Consumer Affairs home'
501
+ },
502
+ """
503
+ action: BrowserAction
504
+ description: str = field(default="")
505
+
506
+ def to_dict(self) -> Dict[str, Any]:
507
+ """Convert to dictionary for serialization"""
508
+ name = self.action.name
509
+ data = self.action.model_dump()
510
+ # Remove action_type from data
511
+ data.pop("action_type", None)
512
+ # remove attributes "name" and "description" from data since they are top-level keys
513
+ data.pop("name", None)
514
+ data.pop("description", None)
515
+ return {
516
+ 'action': name,
517
+ **data
518
+ }
519
+
520
+ @classmethod
521
+ def from_dict(cls, data: Dict[str, Any]) -> 'ScrapingStep':
522
+ """Create ScrapingStep from dictionary"""
523
+ action_type = data.get('action')
524
+ action_data = {k: v for k, v in data.items() if k != 'action'}
525
+
526
+ action_class = ACTION_MAP.get(action_type)
527
+ if not action_class:
528
+ raise ValueError(
529
+ f"Unknown action type: {action_type}"
530
+ )
531
+
532
+ action = action_class(**action_data)
533
+ obj = cls(action=action)
534
+ obj.description = data.get('description', action.description)
535
+ if action_type == 'loop' and 'actions' in data:
536
+ # Recursively convert nested actions
537
+ obj.action.actions = [cls.from_dict(a).action for a in data['actions'] if isinstance(a, dict)]
538
+ return obj
539
+
540
+
541
+ # Convenience function for LLM integration
542
+ def create_action(action_type: str, **kwargs) -> BrowserAction:
543
+ """
544
+ Factory function to create actions by type name
545
+ Useful for LLM-generated action sequences
546
+ """
547
+ action_class = ACTION_MAP.get(action_type)
548
+ if not action_class:
549
+ raise ValueError(
550
+ f"Unknown action type: {action_type}"
551
+ )
552
+
553
+ return action_class(**kwargs)
554
+
555
+
556
+ @dataclass
557
+ class ScrapingSelector:
558
+ """Defines what content to extract from a page"""
559
+ name: str # Friendly name for the content
560
+ selector: str # CSS selector, XPath, or 'body' for full content
561
+ selector_type: Literal['css', 'xpath', 'tag'] = 'css'
562
+ extract_type: Literal['text', 'html', 'attribute'] = 'text'
563
+ attribute: Optional[str] = None # For attribute extraction
564
+ multiple: bool = False # Whether to extract all matching elements
565
+
566
+ @dataclass
567
+ class ScrapingResult:
568
+ """Stores results from a single page scrape"""
569
+ url: str
570
+ content: str # Raw HTML content
571
+ bs_soup: BeautifulSoup # Parsed BeautifulSoup object
572
+ extracted_data: Dict[str, Any] = field(default_factory=dict)
573
+ metadata: Dict[str, Any] = field(default_factory=dict)
574
+ timestamp: str = ""
575
+ success: bool = True
576
+ error_message: Optional[str] = None
@@ -0,0 +1,85 @@
1
+ USER_AGENTS = [
2
+ # Chrome - Desktop (Windows)
3
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
4
+ # Chrome - Desktop (Mac)
5
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", # noqa
6
+ # Safari - Desktop (Mac)
7
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15", # noqa
8
+ # Firefox - Desktop (Windows)
9
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/118.0",
10
+ # Edge - Desktop (Windows)
11
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 Edg/118.0.2088.46", # noqa
12
+ # Chrome - Mobile (Android)
13
+ "Mozilla/5.0 (Linux; Android 13; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Mobile Safari/537.36", # noqa
14
+ # Safari - Mobile (iOS)
15
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1", # noqa
16
+ # Samsung Internet - Mobile (Android)
17
+ "Mozilla/5.0 (Linux; Android 13; SAMSUNG SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/21.0 Chrome/118.0.0.0 Mobile Safari/537.36", # noqa
18
+ # Firefox - Mobile (Android)
19
+ "Mozilla/5.0 (Android 13; Mobile; rv:118.0) Gecko/118.0 Firefox/118.0",
20
+ # Opera - Desktop (Windows)
21
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 OPR/104.0.0.0" # noqa
22
+ # Firefox - Desktop (Linux)
23
+ "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:133.0) Gecko/20100101 Firefox/133.0",
24
+ # Chrome - Desktop (Linux)
25
+ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36",
26
+ # Other:
27
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", # noqa
28
+ ] # noqa
29
+
30
+
31
+ DESKTOP_USER_AGENTS = [
32
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
33
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
34
+ 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
35
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/121.0',
36
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/121.0'
37
+ ]
38
+
39
+ MOBILE_USER_AGENTS = [
40
+ 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1',
41
+ 'Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36',
42
+ 'Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36'
43
+ ]
44
+
45
+ MOBILE_DEVICES = [
46
+ 'iPhone X',
47
+ 'iPhone 12 Pro',
48
+ 'iPhone 14 Pro Max',
49
+ 'Google Nexus 7',
50
+ 'Pixel 2',
51
+ 'Pixel 5',
52
+ 'Samsung Galaxy S21',
53
+ 'Samsung Galaxy Tab',
54
+ 'iPad Pro'
55
+ ]
56
+
57
+ # Browser options configurations
58
+ CHROME_OPTIONS = [
59
+ "--disable-gpu",
60
+ "--no-sandbox",
61
+ "--enable-automation",
62
+ "--lang=en",
63
+ "--disable-dev-shm-usage",
64
+ "--disable-features=VizDisplayCompositor",
65
+ "--disable-features=IsolateOrigins",
66
+ "--disable-blink-features=AutomationControlled",
67
+ "--disable-extensions",
68
+ "--window-size=1920,1080"
69
+ ]
70
+
71
+ UNDETECTED_OPTIONS = [
72
+ "--disable-gpu",
73
+ "--no-sandbox",
74
+ "--enable-automation",
75
+ "--disable-blink-features=AutomationControlled",
76
+ "--disable-features=NetworkService,NetworkServiceInProcess",
77
+ "--disable-dev-shm-usage",
78
+ ]
79
+
80
+ FIREFOX_OPTIONS = [
81
+ "--no-sandbox",
82
+ "--disable-gpu",
83
+ "--width=1920",
84
+ "--height=1080"
85
+ ]