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/exceptions.pxd ADDED
@@ -0,0 +1,22 @@
1
+ # cython: language_level=3, embedsignature=True, boundscheck=False, wraparound=True, initializedcheck=False
2
+ # Copyright (C) 2018-present Jesus Lara
3
+
4
+ cdef class ParrotError(Exception):
5
+ cdef object message
6
+ cdef object stacktrace
7
+
8
+ cdef class ConfigError(ParrotError):
9
+ pass
10
+
11
+ cdef class SpeechGenerationError(ParrotError):
12
+ """Capture Errors related to speech generation."""
13
+ pass
14
+
15
+
16
+ cdef class DriverError(ParrotError):
17
+ """Capture Errors related to driver operations."""
18
+ pass
19
+
20
+ cdef class ToolError(ParrotError):
21
+ """Capture Errors related to tool operations."""
22
+ pass
parrot/exceptions.pxi ADDED
@@ -0,0 +1,15 @@
1
+ # parrot/exceptions.pyi
2
+ from typing import Any, Optional
3
+
4
+ class ParrotError(Exception):
5
+ message: Any
6
+ stacktrace: Optional[Any]
7
+ def __init__(self, message: Any, *args, **kwargs) -> None: ...
8
+ def __repr__(self) -> str: ...
9
+ def __str__(self) -> str: ...
10
+ def get(self) -> Any: ...
11
+
12
+ class ConfigError(ParrotError): ...
13
+ class SpeechGenerationError(ParrotError): ...
14
+ class DriverError(ParrotError): ...
15
+ class ToolError(ParrotError): ...
parrot/exceptions.pyx ADDED
@@ -0,0 +1,44 @@
1
+ # cython: language_level=3, embedsignature=True, boundscheck=False, wraparound=True, initializedcheck=False
2
+ # Copyright (C) 2018-present Jesus Lara
3
+ #
4
+ cdef class ParrotError(Exception):
5
+ """Base class for other exceptions"""
6
+
7
+ def __init__(self, object message, *args, **kwargs):
8
+ super().__init__(message)
9
+ if hasattr(message, 'message'):
10
+ self.message = message.message
11
+ else:
12
+ self.message = str(message)
13
+ self.stacktrace = None
14
+ if 'stacktrace' in kwargs:
15
+ self.stacktrace = kwargs['stacktrace']
16
+ self.args = kwargs
17
+
18
+ def __repr__(self):
19
+ return f"{self.message}"
20
+
21
+ def __str__(self):
22
+ return f"{self.message}"
23
+
24
+ def get(self):
25
+ """Return the message of the exception."""
26
+ return self.message
27
+
28
+
29
+ cdef class ConfigError(ParrotError):
30
+ pass
31
+
32
+
33
+ cdef class SpeechGenerationError(ParrotError):
34
+ """Capture Errors related to speech generation."""
35
+ pass
36
+
37
+
38
+ cdef class DriverError(ParrotError):
39
+ """Capture Errors related to driver operations."""
40
+ pass
41
+
42
+ cdef class ToolError(ParrotError):
43
+ """Capture Errors related to tool operations."""
44
+ pass
@@ -0,0 +1,29 @@
1
+ """
2
+ Web App Generator Implementation for AI-Parrot
3
+ ========================================================
4
+
5
+ This module provides generators for creating full web applications with LLMs.
6
+
7
+ Directory structure to create:
8
+ parrot/
9
+ ├── generators/
10
+ │ ├── __init__.py # This file
11
+ │ ├── base.py # Base generator class
12
+ │ ├── streamlit.py # Streamlit generator
13
+ │ ├── react.py # React generator
14
+ │ └── html.py # HTML/JS generator
15
+ """
16
+ from .base import WebAppGenerator
17
+ from .streamlit import StreamlitGenerator, StreamlitApp
18
+ from .react import ReactGenerator, ReactApp
19
+ from .html import HTMLGenerator, HTMLApp
20
+
21
+ __all__ = [
22
+ 'WebAppGenerator',
23
+ 'StreamlitGenerator',
24
+ 'StreamlitApp',
25
+ 'ReactGenerator',
26
+ 'ReactApp',
27
+ 'HTMLGenerator',
28
+ 'HTMLApp'
29
+ ]
@@ -0,0 +1,200 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Optional, Type, Dict, Any, Union
3
+ import datetime
4
+ from pathlib import Path
5
+ from pydantic import BaseModel
6
+ from navconfig.logging import logging
7
+ from ..models.responses import AIMessage
8
+
9
+
10
+ class WebAppGenerator(ABC):
11
+ """
12
+ Base class for web application generators.
13
+
14
+ Subclass this to create generators for specific app types (Streamlit, React, etc.)
15
+ """
16
+
17
+ def __init__(
18
+ self,
19
+ llm_client,
20
+ output_dir: Optional[Path] = None
21
+ ):
22
+ """
23
+ Initialize the generator.
24
+
25
+ Args:
26
+ llm_client: LLM client instance (GoogleClient, OpenAIClient, etc.)
27
+ output_dir: Optional directory to save generated apps
28
+ """
29
+ self.llm = llm_client
30
+ self.output_dir = output_dir
31
+ self.app_type = self.__class__.__name__.replace('Generator', '').lower()
32
+ self.logger = logging.getLogger(
33
+ f'Parrot.Generator.{self.app_type}'
34
+ )
35
+
36
+ @abstractmethod
37
+ def get_system_prompt(self) -> str:
38
+ """
39
+ Return the system prompt template for this generator.
40
+
41
+ Should include placeholders for: {user_description}, {additional_requirements},
42
+ {high_quality_example}
43
+ """
44
+ pass
45
+
46
+ @abstractmethod
47
+ def get_output_schema(self) -> Type[BaseModel]:
48
+ """Return the Pydantic schema for structured output."""
49
+ pass
50
+
51
+ @abstractmethod
52
+ def get_examples(self) -> str:
53
+ """Return high-quality example code to guide the LLM."""
54
+ pass
55
+
56
+ def build_prompt(
57
+ self,
58
+ user_description: str,
59
+ additional_requirements: str = "",
60
+ **kwargs
61
+ ) -> str:
62
+ """
63
+ Build the complete generation prompt.
64
+
65
+ Args:
66
+ user_description: User's description of desired app
67
+ additional_requirements: Extra technical requirements
68
+ **kwargs: Additional template variables
69
+
70
+ Returns:
71
+ Formatted prompt string
72
+ """
73
+ template = self.get_system_prompt()
74
+ examples = self.get_examples()
75
+
76
+ return template.format(
77
+ user_description=user_description,
78
+ additional_requirements=additional_requirements,
79
+ high_quality_example=examples,
80
+ **kwargs
81
+ )
82
+
83
+ async def generate(
84
+ self,
85
+ description: str,
86
+ additional_requirements: Optional[str] = None,
87
+ use_structured_output: bool = True,
88
+ save_to_file: bool = False,
89
+ filename: Optional[str] = None,
90
+ temperature: float = 0.3,
91
+ max_tokens: int = 4096,
92
+ **kwargs
93
+ ) -> AIMessage:
94
+ """
95
+ Generate a web application based on description.
96
+
97
+ Args:
98
+ description: Detailed description of the app to build
99
+ additional_requirements: Optional extra requirements
100
+ use_structured_output: Whether to use structured output schema
101
+ save_to_file: Whether to save generated code to file
102
+ filename: Custom filename (auto-generated if None)
103
+ temperature: LLM temperature for generation
104
+ max_tokens: Maximum tokens for generation
105
+ **kwargs: Additional arguments passed to LLM
106
+
107
+ Returns:
108
+ AIMessage with generated app code
109
+ """
110
+ self.logger.info(f"Generating {self.app_type} app...")
111
+
112
+ # Build the prompt
113
+ prompt = self.build_prompt(
114
+ user_description=description,
115
+ additional_requirements=additional_requirements or ""
116
+ )
117
+
118
+ # Get structured output schema
119
+ output_schema = self.get_output_schema() if use_structured_output else None
120
+
121
+ # Generate with LLM
122
+ response = await self.llm.ask(
123
+ prompt=prompt,
124
+ structured_output=output_schema,
125
+ temperature=temperature,
126
+ max_tokens=max_tokens,
127
+ **kwargs
128
+ )
129
+
130
+ # Validate and optionally save
131
+ if response.output:
132
+ code = self._extract_code(response.output)
133
+ validation = self.validate_output(code)
134
+
135
+ if not validation['valid']:
136
+ self.logger.warning(f"Generated code has issues: {validation['errors']}")
137
+
138
+ if save_to_file:
139
+ filepath = self._save_to_file(response.output, filename)
140
+ self.logger.info(f"Saved app to: {filepath}")
141
+ response.metadata = response.metadata or {}
142
+ response.metadata['saved_path'] = str(filepath)
143
+
144
+ return response
145
+
146
+ def _extract_code(self, output: Union[BaseModel, str]) -> str:
147
+ """Extract code string from output."""
148
+ if isinstance(output, str):
149
+ return output
150
+ if hasattr(output, 'code'):
151
+ return output.code
152
+ return str(output)
153
+
154
+ def _save_to_file(self, output: BaseModel, filename: Optional[str] = None) -> Path:
155
+ """Save generated code to file."""
156
+ if self.output_dir is None:
157
+ raise ValueError("output_dir must be set to save files")
158
+
159
+ self.output_dir.mkdir(parents=True, exist_ok=True)
160
+
161
+ if filename is None:
162
+ # Auto-generate filename from title or timestamp
163
+ timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
164
+ title = getattr(output, 'title', f'{self.app_type}_app')
165
+ title = title.lower().replace(' ', '_')
166
+ filename = f"{title}_{timestamp}"
167
+
168
+ # Add appropriate extension
169
+ extension = self._get_file_extension()
170
+ if not filename.endswith(extension):
171
+ filename += extension
172
+
173
+ filepath = self.output_dir / filename
174
+ filepath.write_text(output.code)
175
+
176
+ return filepath
177
+
178
+ def _get_file_extension(self) -> str:
179
+ """Get appropriate file extension for this app type."""
180
+ extensions = {
181
+ 'streamlit': '.py',
182
+ 'react': '.jsx',
183
+ 'html': '.html'
184
+ }
185
+ return extensions.get(self.app_type, '.txt')
186
+
187
+ def validate_output(self, code: str) -> Dict[str, Any]:
188
+ """
189
+ Validate the generated code.
190
+
191
+ Override in subclasses for app-specific validation.
192
+
193
+ Returns:
194
+ Dict with 'valid', 'errors', 'warnings' keys
195
+ """
196
+ return {
197
+ "valid": True,
198
+ "errors": [],
199
+ "warnings": []
200
+ }
@@ -0,0 +1,293 @@
1
+ from typing import Type, List
2
+ from pydantic import BaseModel, Field
3
+ from .base import WebAppGenerator
4
+
5
+
6
+ class HTMLApp(BaseModel):
7
+ """Pydantic schema for HTML application output."""
8
+ code: str = Field(description="Complete HTML code with embedded CSS and JS")
9
+ title: str = Field(description="Page title")
10
+ description: str = Field(description="App description")
11
+ features: List[str] = Field(description="Key features implemented")
12
+
13
+
14
+ class HTMLGenerator(WebAppGenerator):
15
+ """Generator for standalone HTML/CSS/JS applications."""
16
+
17
+ def get_system_prompt(self) -> str:
18
+ return """You are an expert web developer creating modern, self-contained HTML applications.
19
+
20
+ **User Requirements:**
21
+ {user_description}
22
+
23
+ **Technical Requirements:**
24
+ - Complete HTML5 document in a single file
25
+ - Embedded CSS using <style> tags
26
+ - Embedded JavaScript using <script> tags
27
+ - Vanilla JavaScript (ES6+) - no frameworks required
28
+ - Responsive design with mobile-first approach
29
+ - Cross-browser compatible (Chrome, Firefox, Safari, Edge)
30
+
31
+ **Libraries Available via CDN (if needed):**
32
+ - Chart.js for charts: https://cdn.jsdelivr.net/npm/chart.js
33
+ - Tailwind CSS: https://cdn.tailwindcss.com
34
+ - Alpine.js for reactivity: https://unpkg.com/alpinejs
35
+
36
+ **HTML Structure:**
37
+ 1. <!DOCTYPE html> declaration
38
+ 2. <html lang="en"> with proper lang attribute
39
+ 3. <head> with meta tags, title, and styles
40
+ 4. <body> with semantic HTML5 elements
41
+ 5. <script> section at the end
42
+
43
+ **CSS Standards:**
44
+ - Modern CSS with flexbox/grid layouts
45
+ - CSS custom properties for theming
46
+ - Smooth transitions and animations
47
+ - Mobile-responsive with media queries
48
+ - Clean, maintainable styling
49
+
50
+ **JavaScript Standards:**
51
+ - ES6+ syntax (const, let, arrow functions)
52
+ - Event delegation for better performance
53
+ - Error handling with try-catch
54
+ - Local storage for data persistence (if appropriate)
55
+ - Form validation
56
+ - Loading states for async operations
57
+
58
+ **Design Requirements:**
59
+ - Modern, clean aesthetic
60
+ - Intuitive user interface
61
+ - Loading indicators for async operations
62
+ - Error messages for validation
63
+ - Smooth animations and transitions
64
+ - Accessible (ARIA labels, keyboard navigation)
65
+
66
+ Generate a complete, production-ready HTML application."""
67
+
68
+ def get_output_schema(self) -> Type[BaseModel]:
69
+ return HTMLApp
70
+
71
+ def get_examples(self) -> str:
72
+ return '''
73
+ <!DOCTYPE html>
74
+ <html lang="en">
75
+ <head>
76
+ <meta charset="UTF-8">
77
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
78
+ <title>Task Manager</title>
79
+ <style>
80
+ * {
81
+ margin: 0;
82
+ padding: 0;
83
+ box-sizing: border-box;
84
+ }
85
+
86
+ :root {
87
+ --primary: #3b82f6;
88
+ --primary-dark: #2563eb;
89
+ --bg: #f9fafb;
90
+ --card: #ffffff;
91
+ --text: #1f2937;
92
+ --text-light: #6b7280;
93
+ --border: #e5e7eb;
94
+ }
95
+
96
+ body {
97
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
98
+ background: var(--bg);
99
+ color: var(--text);
100
+ line-height: 1.6;
101
+ }
102
+
103
+ .container {
104
+ max-width: 800px;
105
+ margin: 0 auto;
106
+ padding: 2rem;
107
+ }
108
+
109
+ .header {
110
+ background: var(--card);
111
+ padding: 2rem;
112
+ border-radius: 1rem;
113
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
114
+ margin-bottom: 2rem;
115
+ }
116
+
117
+ h1 {
118
+ font-size: 2rem;
119
+ margin-bottom: 0.5rem;
120
+ }
121
+
122
+ .input-group {
123
+ display: flex;
124
+ gap: 1rem;
125
+ margin-top: 1rem;
126
+ }
127
+
128
+ input {
129
+ flex: 1;
130
+ padding: 0.75rem;
131
+ border: 1px solid var(--border);
132
+ border-radius: 0.5rem;
133
+ font-size: 1rem;
134
+ }
135
+
136
+ button {
137
+ padding: 0.75rem 1.5rem;
138
+ background: var(--primary);
139
+ color: white;
140
+ border: none;
141
+ border-radius: 0.5rem;
142
+ font-size: 1rem;
143
+ cursor: pointer;
144
+ transition: background 0.3s;
145
+ }
146
+
147
+ button:hover {
148
+ background: var(--primary-dark);
149
+ }
150
+
151
+ .task-list {
152
+ display: flex;
153
+ flex-direction: column;
154
+ gap: 1rem;
155
+ }
156
+
157
+ .task {
158
+ background: var(--card);
159
+ padding: 1rem;
160
+ border-radius: 0.5rem;
161
+ display: flex;
162
+ align-items: center;
163
+ gap: 1rem;
164
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
165
+ transition: transform 0.2s;
166
+ }
167
+
168
+ .task:hover {
169
+ transform: translateY(-2px);
170
+ }
171
+
172
+ .task.completed {
173
+ opacity: 0.6;
174
+ text-decoration: line-through;
175
+ }
176
+
177
+ @media (max-width: 640px) {
178
+ .container {
179
+ padding: 1rem;
180
+ }
181
+ .input-group {
182
+ flex-direction: column;
183
+ }
184
+ }
185
+ </style>
186
+ </head>
187
+ <body>
188
+ <div class="container">
189
+ <div class="header">
190
+ <h1>📝 Task Manager</h1>
191
+ <p style="color: var(--text-light)">Manage your daily tasks efficiently</p>
192
+
193
+ <div class="input-group">
194
+ <input
195
+ type="text"
196
+ id="taskInput"
197
+ placeholder="Enter a new task..."
198
+ aria-label="New task input"
199
+ >
200
+ <button onclick="addTask()" aria-label="Add task">
201
+ Add Task
202
+ </button>
203
+ </div>
204
+ </div>
205
+
206
+ <div class="task-list" id="taskList"></div>
207
+ </div>
208
+
209
+ <script>
210
+ // Load tasks from localStorage
211
+ let tasks = JSON.parse(localStorage.getItem('tasks') || '[]');
212
+
213
+ // Initialize on page load
214
+ document.addEventListener('DOMContentLoaded', () => {
215
+ renderTasks();
216
+
217
+ // Allow Enter key to add task
218
+ document.getElementById('taskInput').addEventListener('keypress', (e) => {
219
+ if (e.key === 'Enter') addTask();
220
+ });
221
+ });
222
+
223
+ function addTask() {
224
+ const input = document.getElementById('taskInput');
225
+ const text = input.value.trim();
226
+
227
+ if (!text) {
228
+ alert('Please enter a task');
229
+ return;
230
+ }
231
+
232
+ tasks.push({
233
+ id: Date.now(),
234
+ text: text,
235
+ completed: false,
236
+ createdAt: new Date().toISOString()
237
+ });
238
+
239
+ saveTasks();
240
+ renderTasks();
241
+ input.value = '';
242
+ input.focus();
243
+ }
244
+
245
+ function toggleTask(id) {
246
+ tasks = tasks.map(task =>
247
+ task.id === id ? {...task, completed: !task.completed} : task
248
+ );
249
+ saveTasks();
250
+ renderTasks();
251
+ }
252
+
253
+ function deleteTask(id) {
254
+ tasks = tasks.filter(task => task.id !== id);
255
+ saveTasks();
256
+ renderTasks();
257
+ }
258
+
259
+ function saveTasks() {
260
+ localStorage.setItem('tasks', JSON.stringify(tasks));
261
+ }
262
+
263
+ function renderTasks() {
264
+ const listEl = document.getElementById('taskList');
265
+
266
+ if (tasks.length === 0) {
267
+ listEl.innerHTML = '<p style="text-align:center;color:var(--text-light)">No tasks yet. Add one above!</p>';
268
+ return;
269
+ }
270
+
271
+ listEl.innerHTML = tasks.map(task => `
272
+ <div class="task ${task.completed ? 'completed' : ''}">
273
+ <input
274
+ type="checkbox"
275
+ ${task.completed ? 'checked' : ''}
276
+ onchange="toggleTask(${task.id})"
277
+ aria-label="Toggle task completion"
278
+ >
279
+ <span style="flex:1">${task.text}</span>
280
+ <button
281
+ onclick="deleteTask(${task.id})"
282
+ style="background:#ef4444;padding:0.5rem 1rem"
283
+ aria-label="Delete task"
284
+ >
285
+ Delete
286
+ </button>
287
+ </div>
288
+ `).join('');
289
+ }
290
+ </script>
291
+ </body>
292
+ </html>
293
+ '''