pygeai 0.1.51b3__py3-none-any.whl → 0.6.0b15__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pygeai might be problematic. Click here for more details.

Files changed (648) hide show
  1. pygeai/__init__.py +9 -1
  2. pygeai/_docs/Makefile +20 -0
  3. pygeai/_docs/make.bat +35 -0
  4. pygeai/_docs/source/conf.py +117 -0
  5. pygeai/_docs/source/content/ai_lab/cli.rst +747 -0
  6. pygeai/_docs/source/content/ai_lab/models.rst +1734 -0
  7. pygeai/_docs/source/content/ai_lab/runner.rst +253 -0
  8. pygeai/_docs/source/content/ai_lab/spec.rst +431 -0
  9. pygeai/_docs/source/content/ai_lab/usage.rst +1011 -0
  10. pygeai/_docs/source/content/ai_lab.rst +102 -0
  11. pygeai/_docs/source/content/analytics.rst +598 -0
  12. pygeai/_docs/source/content/api_reference/admin.rst +161 -0
  13. pygeai/_docs/source/content/api_reference/assistant.rst +326 -0
  14. pygeai/_docs/source/content/api_reference/auth.rst +379 -0
  15. pygeai/_docs/source/content/api_reference/chat.rst +754 -0
  16. pygeai/_docs/source/content/api_reference/embeddings.rst +154 -0
  17. pygeai/_docs/source/content/api_reference/evaluation.rst +590 -0
  18. pygeai/_docs/source/content/api_reference/feedback.rst +237 -0
  19. pygeai/_docs/source/content/api_reference/files.rst +592 -0
  20. pygeai/_docs/source/content/api_reference/gam.rst +401 -0
  21. pygeai/_docs/source/content/api_reference/health.rst +58 -0
  22. pygeai/_docs/source/content/api_reference/project.rst +738 -0
  23. pygeai/_docs/source/content/api_reference/proxy.rst +318 -0
  24. pygeai/_docs/source/content/api_reference/rag.rst +710 -0
  25. pygeai/_docs/source/content/api_reference/rerank.rst +94 -0
  26. pygeai/_docs/source/content/api_reference/secrets.rst +495 -0
  27. pygeai/_docs/source/content/api_reference/usage_limits.rst +390 -0
  28. pygeai/_docs/source/content/api_reference.rst +58 -0
  29. pygeai/_docs/source/content/authentication.rst +295 -0
  30. pygeai/_docs/source/content/chat_gui.rst +121 -0
  31. pygeai/_docs/source/content/cli.rst +203 -0
  32. pygeai/_docs/source/content/debugger.rst +651 -0
  33. pygeai/_docs/source/content/intro.rst +67 -0
  34. pygeai/_docs/source/content/migration.rst +929 -0
  35. pygeai/_docs/source/content/modules.rst +7 -0
  36. pygeai/_docs/source/content/quickstart.rst +143 -0
  37. pygeai/_docs/source/content/samples.rst +394 -0
  38. pygeai/_docs/source/index.rst +75 -0
  39. pygeai/_docs/source/modules.rst +7 -0
  40. pygeai/_docs/source/pygeai.admin.rst +29 -0
  41. pygeai/_docs/source/pygeai.analytics.rst +53 -0
  42. pygeai/_docs/source/pygeai.assistant.data.rst +21 -0
  43. pygeai/_docs/source/pygeai.assistant.data_analyst.rst +29 -0
  44. pygeai/_docs/source/pygeai.assistant.rag.rst +53 -0
  45. pygeai/_docs/source/pygeai.assistant.rst +55 -0
  46. pygeai/_docs/source/pygeai.auth.rst +29 -0
  47. pygeai/_docs/source/pygeai.chat.rst +69 -0
  48. pygeai/_docs/source/pygeai.cli.commands.flows.rst +10 -0
  49. pygeai/_docs/source/pygeai.cli.commands.lab.rst +53 -0
  50. pygeai/_docs/source/pygeai.cli.commands.rst +222 -0
  51. pygeai/_docs/source/pygeai.cli.rst +62 -0
  52. pygeai/_docs/source/pygeai.cli.texts.rst +21 -0
  53. pygeai/_docs/source/pygeai.core.base.rst +53 -0
  54. pygeai/_docs/source/pygeai.core.common.rst +37 -0
  55. pygeai/_docs/source/pygeai.core.embeddings.rst +61 -0
  56. pygeai/_docs/source/pygeai.core.feedback.rst +37 -0
  57. pygeai/_docs/source/pygeai.core.files.rst +61 -0
  58. pygeai/_docs/source/pygeai.core.llm.rst +29 -0
  59. pygeai/_docs/source/pygeai.core.plugins.rst +37 -0
  60. pygeai/_docs/source/pygeai.core.rerank.rst +53 -0
  61. pygeai/_docs/source/pygeai.core.rst +63 -0
  62. pygeai/_docs/source/pygeai.core.secrets.rst +29 -0
  63. pygeai/_docs/source/pygeai.core.services.llm.rst +29 -0
  64. pygeai/_docs/source/pygeai.core.services.rst +37 -0
  65. pygeai/_docs/source/pygeai.core.utils.rst +37 -0
  66. pygeai/_docs/source/pygeai.dbg.rst +21 -0
  67. pygeai/_docs/source/pygeai.evaluation.dataset.rst +29 -0
  68. pygeai/_docs/source/pygeai.evaluation.plan.rst +29 -0
  69. pygeai/_docs/source/pygeai.evaluation.result.rst +29 -0
  70. pygeai/_docs/source/pygeai.evaluation.rst +31 -0
  71. pygeai/_docs/source/pygeai.flows.rst +29 -0
  72. pygeai/_docs/source/pygeai.gam.rst +29 -0
  73. pygeai/_docs/source/pygeai.health.rst +29 -0
  74. pygeai/_docs/source/pygeai.lab.agents.rst +37 -0
  75. pygeai/_docs/source/pygeai.lab.processes.rst +37 -0
  76. pygeai/_docs/source/pygeai.lab.rst +65 -0
  77. pygeai/_docs/source/pygeai.lab.spec.rst +29 -0
  78. pygeai/_docs/source/pygeai.lab.strategies.rst +37 -0
  79. pygeai/_docs/source/pygeai.lab.tools.rst +37 -0
  80. pygeai/_docs/source/pygeai.man.man1.rst +10 -0
  81. pygeai/_docs/source/pygeai.man.rst +18 -0
  82. pygeai/_docs/source/pygeai.migration.rst +29 -0
  83. pygeai/_docs/source/pygeai.organization.limits.rst +45 -0
  84. pygeai/_docs/source/pygeai.organization.rst +61 -0
  85. pygeai/_docs/source/pygeai.proxy.rst +53 -0
  86. pygeai/_docs/source/pygeai.rst +35 -0
  87. pygeai/_docs/source/pygeai.tests.admin.rst +21 -0
  88. pygeai/_docs/source/pygeai.tests.analytics.rst +45 -0
  89. pygeai/_docs/source/pygeai.tests.assistants.rag.rst +37 -0
  90. pygeai/_docs/source/pygeai.tests.assistants.rst +45 -0
  91. pygeai/_docs/source/pygeai.tests.auth.rst +29 -0
  92. pygeai/_docs/source/pygeai.tests.chat.rst +45 -0
  93. pygeai/_docs/source/pygeai.tests.cli.commands.lab.rst +37 -0
  94. pygeai/_docs/source/pygeai.tests.cli.commands.rst +165 -0
  95. pygeai/_docs/source/pygeai.tests.cli.docker.rst +10 -0
  96. pygeai/_docs/source/pygeai.tests.cli.rst +46 -0
  97. pygeai/_docs/source/pygeai.tests.core.base.data.rst +29 -0
  98. pygeai/_docs/source/pygeai.tests.core.base.rst +45 -0
  99. pygeai/_docs/source/pygeai.tests.core.common.data.rst +10 -0
  100. pygeai/_docs/source/pygeai.tests.core.common.rst +37 -0
  101. pygeai/_docs/source/pygeai.tests.core.embeddings.rst +37 -0
  102. pygeai/_docs/source/pygeai.tests.core.feedback.rst +21 -0
  103. pygeai/_docs/source/pygeai.tests.core.files.rst +53 -0
  104. pygeai/_docs/source/pygeai.tests.core.llm.rst +21 -0
  105. pygeai/_docs/source/pygeai.tests.core.plugins.rst +21 -0
  106. pygeai/_docs/source/pygeai.tests.core.rerank.rst +37 -0
  107. pygeai/_docs/source/pygeai.tests.core.rst +39 -0
  108. pygeai/_docs/source/pygeai.tests.core.secrets.rst +21 -0
  109. pygeai/_docs/source/pygeai.tests.core.services.rst +21 -0
  110. pygeai/_docs/source/pygeai.tests.core.utils.rst +21 -0
  111. pygeai/_docs/source/pygeai.tests.dbg.rst +21 -0
  112. pygeai/_docs/source/pygeai.tests.evaluation.dataset.rst +21 -0
  113. pygeai/_docs/source/pygeai.tests.evaluation.plan.rst +21 -0
  114. pygeai/_docs/source/pygeai.tests.evaluation.result.rst +21 -0
  115. pygeai/_docs/source/pygeai.tests.evaluation.rst +20 -0
  116. pygeai/_docs/source/pygeai.tests.gam.rst +21 -0
  117. pygeai/_docs/source/pygeai.tests.health.rst +21 -0
  118. pygeai/_docs/source/pygeai.tests.integration.assistants.rag.rst +21 -0
  119. pygeai/_docs/source/pygeai.tests.integration.assistants.rst +18 -0
  120. pygeai/_docs/source/pygeai.tests.integration.chat.rst +21 -0
  121. pygeai/_docs/source/pygeai.tests.integration.lab.agents.rst +69 -0
  122. pygeai/_docs/source/pygeai.tests.integration.lab.processes.rst +77 -0
  123. pygeai/_docs/source/pygeai.tests.integration.lab.reasoning_strategies.rst +37 -0
  124. pygeai/_docs/source/pygeai.tests.integration.lab.rst +21 -0
  125. pygeai/_docs/source/pygeai.tests.integration.lab.tools.rst +77 -0
  126. pygeai/_docs/source/pygeai.tests.integration.rst +20 -0
  127. pygeai/_docs/source/pygeai.tests.lab.agents.rst +29 -0
  128. pygeai/_docs/source/pygeai.tests.lab.processes.rst +29 -0
  129. pygeai/_docs/source/pygeai.tests.lab.rst +49 -0
  130. pygeai/_docs/source/pygeai.tests.lab.spec.rst +29 -0
  131. pygeai/_docs/source/pygeai.tests.lab.strategies.rst +29 -0
  132. pygeai/_docs/source/pygeai.tests.lab.tools.rst +29 -0
  133. pygeai/_docs/source/pygeai.tests.migration.rst +29 -0
  134. pygeai/_docs/source/pygeai.tests.organization.limits.rst +29 -0
  135. pygeai/_docs/source/pygeai.tests.organization.rst +53 -0
  136. pygeai/_docs/source/pygeai.tests.proxy.rst +61 -0
  137. pygeai/_docs/source/pygeai.tests.rst +33 -0
  138. pygeai/admin/clients.py +14 -11
  139. pygeai/admin/endpoints.py +2 -2
  140. pygeai/analytics/clients.py +505 -0
  141. pygeai/analytics/endpoints.py +35 -0
  142. pygeai/analytics/managers.py +606 -0
  143. pygeai/analytics/mappers.py +207 -0
  144. pygeai/analytics/responses.py +240 -0
  145. pygeai/assistant/clients.py +18 -45
  146. pygeai/assistant/data/clients.py +1 -0
  147. pygeai/assistant/data_analyst/clients.py +8 -12
  148. pygeai/assistant/managers.py +195 -157
  149. pygeai/assistant/mappers.py +4 -2
  150. pygeai/assistant/rag/clients.py +27 -67
  151. pygeai/assistant/rag/mappers.py +12 -6
  152. pygeai/assistant/rag/models.py +301 -159
  153. pygeai/auth/__init__.py +0 -0
  154. pygeai/auth/clients.py +129 -0
  155. pygeai/auth/endpoints.py +6 -0
  156. pygeai/chat/clients.py +308 -37
  157. pygeai/chat/endpoints.py +3 -0
  158. pygeai/chat/iris.py +2 -8
  159. pygeai/chat/managers.py +9 -6
  160. pygeai/chat/session.py +38 -0
  161. pygeai/chat/settings.py +6 -0
  162. pygeai/chat/ui.py +678 -0
  163. pygeai/cli/__init__.py +0 -1
  164. pygeai/cli/commands/admin.py +7 -10
  165. pygeai/cli/commands/analytics.py +533 -0
  166. pygeai/cli/commands/assistant.py +9 -9
  167. pygeai/cli/commands/auth.py +299 -0
  168. pygeai/cli/commands/base.py +71 -9
  169. pygeai/cli/commands/chat.py +676 -19
  170. pygeai/cli/commands/common.py +28 -24
  171. pygeai/cli/commands/configuration.py +66 -13
  172. pygeai/cli/commands/docs.py +105 -0
  173. pygeai/cli/commands/embeddings.py +58 -11
  174. pygeai/cli/commands/evaluation.py +38 -38
  175. pygeai/cli/commands/feedback.py +3 -4
  176. pygeai/cli/commands/files.py +7 -8
  177. pygeai/cli/commands/gam.py +85 -10
  178. pygeai/cli/commands/lab/ai_lab.py +340 -484
  179. pygeai/cli/commands/lab/options.py +8 -0
  180. pygeai/cli/commands/lab/spec.py +273 -0
  181. pygeai/cli/commands/lab/utils.py +13 -0
  182. pygeai/cli/commands/llm.py +6 -7
  183. pygeai/cli/commands/migrate.py +1064 -436
  184. pygeai/cli/commands/organization.py +516 -11
  185. pygeai/cli/commands/rag.py +13 -14
  186. pygeai/cli/commands/rerank.py +3 -5
  187. pygeai/cli/commands/secrets.py +8 -9
  188. pygeai/cli/commands/usage_limits.py +18 -20
  189. pygeai/cli/commands/validators.py +144 -1
  190. pygeai/cli/commands/version.py +4 -5
  191. pygeai/cli/error_handler.py +151 -0
  192. pygeai/cli/geai.py +170 -31
  193. pygeai/cli/geai_proxy.py +86 -25
  194. pygeai/cli/install_man.py +93 -22
  195. pygeai/cli/parsers.py +75 -25
  196. pygeai/cli/texts/help.py +265 -28
  197. pygeai/core/base/clients.py +53 -12
  198. pygeai/core/base/mappers.py +11 -2
  199. pygeai/core/base/session.py +95 -11
  200. pygeai/core/common/config.py +78 -14
  201. pygeai/core/common/exceptions.py +96 -6
  202. pygeai/core/embeddings/__init__.py +19 -0
  203. pygeai/core/embeddings/clients.py +23 -5
  204. pygeai/core/embeddings/managers.py +9 -4
  205. pygeai/core/embeddings/mappers.py +16 -2
  206. pygeai/core/embeddings/responses.py +9 -2
  207. pygeai/core/feedback/clients.py +8 -3
  208. pygeai/core/files/clients.py +23 -24
  209. pygeai/core/files/managers.py +121 -30
  210. pygeai/core/files/responses.py +4 -3
  211. pygeai/core/handlers.py +10 -1
  212. pygeai/core/llm/clients.py +22 -29
  213. pygeai/core/models.py +127 -11
  214. pygeai/core/plugins/clients.py +6 -6
  215. pygeai/core/rerank/clients.py +9 -3
  216. pygeai/core/rerank/managers.py +22 -5
  217. pygeai/core/secrets/clients.py +16 -37
  218. pygeai/core/services/response.py +18 -0
  219. pygeai/core/services/rest.py +159 -49
  220. pygeai/core/utils/__init__.py +0 -0
  221. pygeai/core/utils/console.py +83 -0
  222. pygeai/core/utils/parsers.py +32 -0
  223. pygeai/core/utils/validators.py +10 -0
  224. pygeai/dbg/__init__.py +3 -0
  225. pygeai/dbg/debugger.py +854 -14
  226. pygeai/evaluation/clients.py +7 -4
  227. pygeai/evaluation/dataset/clients.py +46 -44
  228. pygeai/evaluation/plan/clients.py +28 -26
  229. pygeai/evaluation/result/clients.py +38 -5
  230. pygeai/gam/clients.py +50 -28
  231. pygeai/gam/endpoints.py +2 -1
  232. pygeai/health/__init__.py +0 -0
  233. pygeai/health/clients.py +24 -0
  234. pygeai/health/endpoints.py +1 -0
  235. pygeai/lab/__init__.py +0 -90
  236. pygeai/lab/agents/clients.py +203 -162
  237. pygeai/lab/agents/endpoints.py +4 -0
  238. pygeai/lab/agents/mappers.py +57 -7
  239. pygeai/lab/clients.py +24 -0
  240. pygeai/lab/constants.py +3 -0
  241. pygeai/lab/managers.py +571 -541
  242. pygeai/lab/models.py +108 -19
  243. pygeai/lab/processes/clients.py +332 -340
  244. pygeai/lab/processes/mappers.py +3 -3
  245. pygeai/lab/runners.py +90 -0
  246. pygeai/lab/spec/__init__.py +0 -0
  247. pygeai/lab/spec/loader.py +24 -0
  248. pygeai/lab/spec/parsers.py +39 -0
  249. pygeai/lab/strategies/clients.py +67 -63
  250. pygeai/lab/strategies/mappers.py +1 -1
  251. pygeai/lab/tools/clients.py +85 -118
  252. pygeai/lab/tools/endpoints.py +4 -0
  253. pygeai/lab/tools/mappers.py +5 -5
  254. pygeai/man/man1/geai-proxy.1 +116 -0
  255. pygeai/man/man1/geai.1 +2580 -66
  256. pygeai/migration/__init__.py +33 -0
  257. pygeai/migration/strategies.py +468 -146
  258. pygeai/migration/tools.py +170 -3
  259. pygeai/organization/clients.py +245 -50
  260. pygeai/organization/endpoints.py +17 -8
  261. pygeai/organization/limits/clients.py +34 -32
  262. pygeai/organization/limits/managers.py +108 -49
  263. pygeai/organization/managers.py +347 -53
  264. pygeai/organization/mappers.py +102 -2
  265. pygeai/organization/responses.py +58 -1
  266. pygeai/proxy/clients.py +6 -3
  267. pygeai/proxy/config.py +14 -1
  268. pygeai/proxy/managers.py +61 -33
  269. pygeai/proxy/servers.py +196 -51
  270. pygeai/proxy/tool.py +33 -16
  271. pygeai/tests/admin/__init__.py +0 -0
  272. pygeai/tests/admin/test_clients.py +148 -0
  273. pygeai/tests/analytics/__init__.py +0 -0
  274. pygeai/tests/analytics/test_clients.py +86 -0
  275. pygeai/tests/analytics/test_managers.py +94 -0
  276. pygeai/tests/analytics/test_mappers.py +84 -0
  277. pygeai/tests/analytics/test_responses.py +73 -0
  278. pygeai/tests/assistants/rag/test_clients.py +346 -0
  279. pygeai/tests/assistants/rag/test_models.py +292 -0
  280. pygeai/tests/assistants/test_clients.py +176 -82
  281. pygeai/tests/assistants/test_managers.py +191 -57
  282. pygeai/tests/auth/__init__.py +0 -0
  283. pygeai/tests/auth/test_clients.py +289 -0
  284. pygeai/tests/auth/test_oauth.py +172 -0
  285. pygeai/tests/auth/test_session_logging.py +150 -0
  286. pygeai/tests/chat/__init__.py +0 -0
  287. pygeai/tests/chat/test_clients.py +393 -0
  288. pygeai/tests/chat/test_iris.py +38 -0
  289. pygeai/tests/chat/test_session.py +62 -0
  290. pygeai/tests/chat/test_ui.py +224 -0
  291. pygeai/tests/cli/commands/__init__.py +0 -0
  292. pygeai/tests/cli/commands/lab/__init__.py +0 -0
  293. pygeai/tests/cli/commands/lab/test_ai_lab.py +786 -0
  294. pygeai/tests/cli/commands/lab/test_common.py +208 -0
  295. pygeai/tests/cli/commands/lab/test_spec.py +246 -0
  296. pygeai/tests/cli/commands/test_assistant.py +202 -0
  297. pygeai/tests/cli/commands/test_chat.py +130 -0
  298. pygeai/tests/cli/commands/test_common.py +350 -0
  299. pygeai/tests/cli/commands/test_embeddings.py +132 -0
  300. pygeai/tests/cli/commands/test_evaluation.py +656 -0
  301. pygeai/tests/cli/commands/test_feedback.py +65 -0
  302. pygeai/tests/cli/commands/test_files.py +161 -0
  303. pygeai/tests/cli/commands/test_gam.py +201 -0
  304. pygeai/tests/cli/commands/test_llm.py +114 -0
  305. pygeai/tests/cli/commands/test_migrate.py +176 -0
  306. pygeai/tests/cli/commands/test_organization.py +276 -0
  307. pygeai/tests/cli/commands/test_rag.py +266 -0
  308. pygeai/tests/cli/commands/test_rerank.py +110 -0
  309. pygeai/tests/cli/commands/test_secrets.py +171 -0
  310. pygeai/tests/cli/commands/test_show_help.py +41 -0
  311. pygeai/tests/cli/commands/test_usage_limits.py +412 -0
  312. pygeai/tests/cli/commands/test_validators.py +160 -0
  313. pygeai/tests/cli/commands/test_version.py +81 -0
  314. pygeai/tests/cli/docker/__init__.py +0 -0
  315. pygeai/tests/cli/test_credentials_flag.py +316 -0
  316. pygeai/tests/cli/test_error_handler.py +225 -0
  317. pygeai/tests/cli/test_geai_driver.py +154 -0
  318. pygeai/tests/cli/test_parsers.py +5 -5
  319. pygeai/tests/core/base/data/models.py +7 -0
  320. pygeai/tests/core/base/test_mappers.py +43 -11
  321. pygeai/tests/core/base/test_models.py +3 -1
  322. pygeai/tests/core/base/test_responses.py +53 -0
  323. pygeai/tests/core/common/__init__.py +0 -0
  324. pygeai/tests/core/common/data/__init__.py +0 -0
  325. pygeai/tests/core/common/test_config.py +186 -0
  326. pygeai/tests/core/common/test_decorators.py +69 -0
  327. pygeai/tests/core/embeddings/__init__.py +0 -0
  328. pygeai/tests/core/embeddings/test_clients.py +225 -0
  329. pygeai/tests/core/embeddings/test_managers.py +171 -0
  330. pygeai/tests/core/embeddings/test_mappers.py +142 -0
  331. pygeai/tests/core/feedback/__init__.py +0 -0
  332. pygeai/tests/core/feedback/test_clients.py +64 -0
  333. pygeai/tests/core/files/test_clients.py +128 -0
  334. pygeai/tests/core/files/test_managers.py +124 -78
  335. pygeai/tests/core/files/test_mappers.py +137 -0
  336. pygeai/tests/core/files/test_models.py +103 -0
  337. pygeai/tests/core/files/test_responses.py +122 -0
  338. pygeai/tests/core/llm/__init__.py +0 -0
  339. pygeai/tests/core/llm/test_clients.py +142 -0
  340. pygeai/tests/core/plugins/__init__.py +0 -0
  341. pygeai/tests/core/plugins/test_clients.py +66 -0
  342. pygeai/tests/core/rerank/test_clients.py +76 -0
  343. pygeai/tests/core/rerank/test_managers.py +61 -39
  344. pygeai/tests/core/secrets/__init__.py +0 -0
  345. pygeai/tests/core/secrets/test_clients.py +264 -0
  346. pygeai/tests/core/services/__init__.py +0 -0
  347. pygeai/tests/core/services/test_rest.py +273 -0
  348. pygeai/tests/core/test_handlers.py +66 -0
  349. pygeai/tests/core/utils/__init__.py +0 -0
  350. pygeai/tests/core/utils/test_console.py +80 -0
  351. pygeai/tests/dbg/__init__.py +0 -0
  352. pygeai/tests/dbg/test_debugger.py +591 -0
  353. pygeai/tests/evaluation/__init__.py +0 -0
  354. pygeai/tests/evaluation/dataset/__init__.py +0 -0
  355. pygeai/tests/evaluation/dataset/test_clients.py +265 -0
  356. pygeai/tests/evaluation/plan/__init__.py +0 -0
  357. pygeai/tests/evaluation/plan/test_clients.py +195 -0
  358. pygeai/tests/evaluation/result/__init__.py +0 -0
  359. pygeai/tests/evaluation/result/test_clients.py +66 -0
  360. pygeai/tests/gam/__init__.py +0 -0
  361. pygeai/tests/gam/test_clients.py +195 -0
  362. pygeai/tests/health/__init__.py +0 -0
  363. pygeai/tests/health/test_clients.py +41 -0
  364. pygeai/tests/integration/__init__.py +0 -0
  365. pygeai/tests/integration/assistants/__init__.py +0 -0
  366. pygeai/tests/integration/assistants/rag/__init__.py +0 -0
  367. pygeai/tests/integration/assistants/rag/test_create_rag.py +91 -0
  368. pygeai/tests/integration/chat/__init__.py +0 -0
  369. pygeai/tests/integration/chat/test_generate_image.py +158 -0
  370. pygeai/tests/integration/lab/__init__.py +0 -0
  371. pygeai/tests/integration/lab/agents/__init__.py +0 -0
  372. pygeai/tests/integration/lab/agents/test_agents_list.py +106 -0
  373. pygeai/tests/integration/lab/agents/test_create_agent.py +319 -0
  374. pygeai/tests/integration/lab/agents/test_create_sharing_link.py +70 -0
  375. pygeai/tests/integration/lab/agents/test_delete_agent.py +75 -0
  376. pygeai/tests/integration/lab/agents/test_get_agent.py +94 -0
  377. pygeai/tests/integration/lab/agents/test_publish_agent_revision.py +127 -0
  378. pygeai/tests/integration/lab/agents/test_update_agent.py +250 -0
  379. pygeai/tests/integration/lab/processes/__init__.py +0 -0
  380. pygeai/tests/integration/lab/processes/test_create_process.py +345 -0
  381. pygeai/tests/integration/lab/processes/test_create_task.py +211 -0
  382. pygeai/tests/integration/lab/processes/test_delete_process.py +111 -0
  383. pygeai/tests/integration/lab/processes/test_get_process.py +201 -0
  384. pygeai/tests/integration/lab/processes/test_list_process_instances.py +91 -0
  385. pygeai/tests/integration/lab/processes/test_list_processes.py +138 -0
  386. pygeai/tests/integration/lab/processes/test_publish_process_revision.py +232 -0
  387. pygeai/tests/integration/lab/processes/test_update_process.py +289 -0
  388. pygeai/tests/integration/lab/reasoning_strategies/__init__.py +0 -0
  389. pygeai/tests/integration/lab/reasoning_strategies/test_get_reasoning_strategy.py +70 -0
  390. pygeai/tests/integration/lab/reasoning_strategies/test_list_reasoning_strategies.py +93 -0
  391. pygeai/tests/integration/lab/reasoning_strategies/test_update_reasoning_strategy.py +149 -0
  392. pygeai/tests/integration/lab/tools/__init__.py +0 -0
  393. pygeai/tests/integration/lab/tools/test_create_tool.py +288 -0
  394. pygeai/tests/integration/lab/tools/test_delete_tool.py +87 -0
  395. pygeai/tests/integration/lab/tools/test_get_parameter.py +98 -0
  396. pygeai/tests/integration/lab/tools/test_get_tool.py +91 -0
  397. pygeai/tests/integration/lab/tools/test_list_tools.py +106 -0
  398. pygeai/tests/integration/lab/tools/test_publish_tool_revision.py +119 -0
  399. pygeai/tests/integration/lab/tools/test_set_parameter.py +114 -0
  400. pygeai/tests/integration/lab/tools/test_update_tool.py +267 -0
  401. pygeai/tests/lab/agents/__init__.py +0 -0
  402. pygeai/tests/lab/agents/test_clients.py +481 -0
  403. pygeai/tests/lab/agents/test_mappers.py +440 -0
  404. pygeai/tests/lab/processes/__init__.py +0 -0
  405. pygeai/tests/lab/processes/test_clients.py +1416 -0
  406. pygeai/tests/lab/processes/test_mappers.py +1092 -0
  407. pygeai/tests/lab/spec/__init__.py +0 -0
  408. pygeai/tests/lab/spec/test_loader.py +59 -0
  409. pygeai/tests/lab/spec/test_parsers.py +182 -0
  410. pygeai/tests/lab/strategies/__init__.py +0 -0
  411. pygeai/tests/lab/strategies/test_clients.py +241 -0
  412. pygeai/tests/lab/strategies/test_mappers.py +132 -0
  413. pygeai/tests/lab/test_managers.py +553 -0
  414. pygeai/tests/lab/test_models.py +500 -3
  415. pygeai/tests/lab/tools/__init__.py +0 -0
  416. pygeai/tests/lab/tools/test_clients.py +521 -0
  417. pygeai/tests/lab/tools/test_mappers.py +198 -0
  418. pygeai/tests/migration/__init__.py +0 -0
  419. pygeai/tests/migration/test_strategies.py +405 -0
  420. pygeai/tests/migration/test_tools.py +159 -0
  421. pygeai/tests/organization/limits/test_clients.py +567 -0
  422. pygeai/tests/organization/limits/test_managers.py +298 -56
  423. pygeai/tests/organization/test_clients.py +600 -30
  424. pygeai/tests/organization/test_managers.py +424 -0
  425. pygeai/tests/organization/test_mappers.py +153 -0
  426. pygeai/tests/organization/test_responses.py +137 -0
  427. pygeai/tests/proxy/__init__.py +1 -0
  428. pygeai/tests/proxy/test_clients.py +397 -0
  429. pygeai/tests/proxy/test_config.py +171 -0
  430. pygeai/tests/proxy/test_integration.py +305 -0
  431. pygeai/tests/proxy/test_managers.py +312 -0
  432. pygeai/tests/proxy/test_servers.py +387 -0
  433. pygeai/tests/proxy/test_tool.py +176 -0
  434. pygeai/tests/snippets/analytics/__init__.py +0 -0
  435. pygeai/tests/snippets/analytics/get_agent_usage_per_user.py +16 -0
  436. pygeai/tests/snippets/analytics/get_agents_created_and_modified.py +11 -0
  437. pygeai/tests/snippets/analytics/get_average_cost_per_request.py +10 -0
  438. pygeai/tests/snippets/analytics/get_overall_error_rate.py +10 -0
  439. pygeai/tests/snippets/analytics/get_top_10_agents_by_requests.py +12 -0
  440. pygeai/tests/snippets/analytics/get_total_active_users.py +10 -0
  441. pygeai/tests/snippets/analytics/get_total_cost.py +10 -0
  442. pygeai/tests/snippets/analytics/get_total_requests_per_day.py +12 -0
  443. pygeai/tests/snippets/analytics/get_total_tokens.py +12 -0
  444. pygeai/tests/snippets/auth/__init__.py +0 -0
  445. pygeai/tests/snippets/chat/chat_completion_with_reasoning_effort.py +18 -0
  446. pygeai/tests/snippets/chat/get_response.py +15 -0
  447. pygeai/tests/snippets/chat/get_response_complete_example.py +67 -0
  448. pygeai/tests/snippets/chat/get_response_streaming.py +20 -0
  449. pygeai/tests/snippets/chat/get_response_with_files.py +16 -0
  450. pygeai/tests/snippets/chat/get_response_with_instructions.py +19 -0
  451. pygeai/tests/snippets/chat/get_response_with_metadata.py +24 -0
  452. pygeai/tests/snippets/chat/get_response_with_parallel_tools.py +58 -0
  453. pygeai/tests/snippets/chat/get_response_with_reasoning.py +21 -0
  454. pygeai/tests/snippets/chat/get_response_with_store.py +38 -0
  455. pygeai/tests/snippets/chat/get_response_with_tools.py +36 -0
  456. pygeai/tests/snippets/chat/get_response_with_truncation.py +24 -0
  457. pygeai/tests/snippets/dbg/__init__.py +0 -0
  458. pygeai/tests/snippets/dbg/basic_debugging.py +32 -0
  459. pygeai/tests/snippets/dbg/breakpoint_management.py +48 -0
  460. pygeai/tests/snippets/dbg/file_debugging.py +72 -0
  461. pygeai/tests/snippets/dbg/module_debugging.py +61 -0
  462. pygeai/tests/snippets/dbg/stack_navigation.py +45 -0
  463. pygeai/tests/snippets/dbg/stepping_example.py +40 -0
  464. pygeai/tests/snippets/embeddings/cache_example.py +31 -0
  465. pygeai/tests/snippets/embeddings/cohere_example.py +41 -0
  466. pygeai/tests/snippets/embeddings/openai_base64_example.py +27 -0
  467. pygeai/tests/snippets/embeddings/openai_example.py +30 -0
  468. pygeai/tests/snippets/embeddings/similarity_example.py +42 -0
  469. pygeai/tests/snippets/evaluation/dataset/__init__.py +0 -0
  470. pygeai/tests/snippets/evaluation/dataset/complete_workflow_example.py +195 -0
  471. pygeai/tests/snippets/evaluation/dataset/create_dataset.py +26 -0
  472. pygeai/tests/snippets/evaluation/dataset/create_dataset_from_file.py +11 -0
  473. pygeai/tests/snippets/evaluation/dataset/create_dataset_row.py +17 -0
  474. pygeai/tests/snippets/evaluation/dataset/create_expected_source.py +18 -0
  475. pygeai/tests/snippets/evaluation/dataset/create_filter_variable.py +19 -0
  476. pygeai/tests/snippets/evaluation/dataset/delete_dataset.py +9 -0
  477. pygeai/tests/snippets/evaluation/dataset/delete_dataset_row.py +10 -0
  478. pygeai/tests/snippets/evaluation/dataset/delete_expected_source.py +15 -0
  479. pygeai/tests/snippets/evaluation/dataset/delete_filter_variable.py +15 -0
  480. pygeai/tests/snippets/evaluation/dataset/get_dataset.py +9 -0
  481. pygeai/tests/snippets/evaluation/dataset/get_dataset_row.py +10 -0
  482. pygeai/tests/snippets/evaluation/dataset/get_expected_source.py +15 -0
  483. pygeai/tests/snippets/evaluation/dataset/get_filter_variable.py +15 -0
  484. pygeai/tests/snippets/evaluation/dataset/list_dataset_rows.py +9 -0
  485. pygeai/tests/snippets/evaluation/dataset/list_datasets.py +6 -0
  486. pygeai/tests/snippets/evaluation/dataset/list_expected_sources.py +10 -0
  487. pygeai/tests/snippets/evaluation/dataset/list_filter_variables.py +10 -0
  488. pygeai/tests/snippets/evaluation/dataset/update_dataset.py +15 -0
  489. pygeai/tests/snippets/evaluation/dataset/update_dataset_row.py +20 -0
  490. pygeai/tests/snippets/evaluation/dataset/update_expected_source.py +18 -0
  491. pygeai/tests/snippets/evaluation/dataset/update_filter_variable.py +19 -0
  492. pygeai/tests/snippets/evaluation/dataset/upload_dataset_rows_file.py +10 -0
  493. pygeai/tests/snippets/evaluation/plan/__init__.py +0 -0
  494. pygeai/tests/snippets/evaluation/plan/add_plan_system_metric.py +13 -0
  495. pygeai/tests/snippets/evaluation/plan/complete_workflow_example.py +136 -0
  496. pygeai/tests/snippets/evaluation/plan/create_evaluation_plan.py +24 -0
  497. pygeai/tests/snippets/evaluation/plan/create_rag_evaluation_plan.py +22 -0
  498. pygeai/tests/snippets/evaluation/plan/delete_evaluation_plan.py +9 -0
  499. pygeai/tests/snippets/evaluation/plan/delete_plan_system_metric.py +13 -0
  500. pygeai/tests/snippets/evaluation/plan/execute_evaluation_plan.py +11 -0
  501. pygeai/tests/snippets/evaluation/plan/get_evaluation_plan.py +9 -0
  502. pygeai/tests/snippets/evaluation/plan/get_plan_system_metric.py +13 -0
  503. pygeai/tests/snippets/evaluation/plan/get_system_metric.py +9 -0
  504. pygeai/tests/snippets/evaluation/plan/list_evaluation_plans.py +7 -0
  505. pygeai/tests/snippets/evaluation/plan/list_plan_system_metrics.py +9 -0
  506. pygeai/tests/snippets/evaluation/plan/list_system_metrics.py +7 -0
  507. pygeai/tests/snippets/evaluation/plan/update_evaluation_plan.py +22 -0
  508. pygeai/tests/snippets/evaluation/plan/update_plan_system_metric.py +14 -0
  509. pygeai/tests/snippets/evaluation/result/__init__.py +0 -0
  510. pygeai/tests/snippets/evaluation/result/complete_workflow_example.py +150 -0
  511. pygeai/tests/snippets/evaluation/result/get_evaluation_result.py +26 -0
  512. pygeai/tests/snippets/evaluation/result/list_evaluation_results.py +17 -0
  513. pygeai/tests/snippets/files/delete_file.py +1 -4
  514. pygeai/tests/snippets/files/get_file_content.py +2 -4
  515. pygeai/tests/snippets/files/get_file_data.py +1 -4
  516. pygeai/tests/snippets/files/get_file_list.py +1 -6
  517. pygeai/tests/snippets/files/upload_file.py +1 -5
  518. pygeai/tests/snippets/gam/gam_access_token.py +87 -0
  519. pygeai/tests/snippets/lab/agentic_flow_example_1.py +25 -23
  520. pygeai/tests/snippets/lab/agentic_flow_example_4.py +23 -23
  521. pygeai/tests/snippets/lab/agents/create_agent.py +5 -8
  522. pygeai/tests/snippets/lab/agents/create_agent_2.py +1 -5
  523. pygeai/tests/snippets/lab/agents/create_agent_edge_case.py +48 -0
  524. pygeai/tests/snippets/lab/agents/create_agent_with_permissions.py +39 -0
  525. pygeai/tests/snippets/lab/agents/create_agent_with_properties.py +46 -0
  526. pygeai/tests/snippets/lab/agents/create_agent_without_instructions.py +48 -0
  527. pygeai/tests/snippets/lab/agents/delete_agent.py +1 -5
  528. pygeai/tests/snippets/lab/agents/get_agent.py +2 -11
  529. pygeai/tests/snippets/lab/agents/get_agent_with_new_fields.py +62 -0
  530. pygeai/tests/snippets/lab/agents/get_sharing_link.py +2 -7
  531. pygeai/tests/snippets/lab/agents/list_agents.py +4 -7
  532. pygeai/tests/snippets/lab/agents/publish_agent_revision.py +2 -6
  533. pygeai/tests/snippets/lab/agents/update_agent.py +1 -5
  534. pygeai/tests/snippets/lab/agents/update_agent_properties.py +50 -0
  535. pygeai/tests/snippets/lab/assistant_to_agent.py +191 -0
  536. pygeai/tests/snippets/lab/crud_ui.py +462 -0
  537. pygeai/tests/snippets/lab/processes/create_process.py +3 -5
  538. pygeai/tests/snippets/lab/processes/create_task.py +3 -5
  539. pygeai/tests/snippets/lab/processes/jobs/list_jobs.py +10 -19
  540. pygeai/tests/snippets/lab/processes/kbs/create_kb.py +2 -5
  541. pygeai/tests/snippets/lab/processes/kbs/get_kb.py +10 -16
  542. pygeai/tests/snippets/lab/processes/kbs/list_kbs.py +13 -20
  543. pygeai/tests/snippets/lab/processes/kbs/try_all.py +5 -7
  544. pygeai/tests/snippets/lab/processes/list_processes.py +5 -7
  545. pygeai/tests/snippets/lab/runner_1.py +1 -1
  546. pygeai/tests/snippets/lab/samples/summarize_files.py +3 -3
  547. pygeai/tests/snippets/lab/strategies/create_reasoning_strategy.py +2 -5
  548. pygeai/tests/snippets/lab/strategies/get_reasoning_strategy.py +2 -5
  549. pygeai/tests/snippets/lab/strategies/list_reasoning_strategies.py +3 -6
  550. pygeai/tests/snippets/lab/strategies/update_reasoning_strategy.py +2 -5
  551. pygeai/tests/snippets/lab/tools/create_tool.py +4 -10
  552. pygeai/tests/snippets/lab/tools/create_tool_edge_case.py +50 -0
  553. pygeai/tests/snippets/lab/tools/delete_tool.py +2 -6
  554. pygeai/tests/snippets/lab/tools/get_parameter.py +5 -7
  555. pygeai/tests/snippets/lab/tools/get_tool.py +5 -7
  556. pygeai/tests/snippets/lab/tools/list_tools.py +3 -7
  557. pygeai/tests/snippets/lab/tools/publish_tool_revision.py +3 -5
  558. pygeai/tests/snippets/lab/tools/set_parameters.py +4 -9
  559. pygeai/tests/snippets/lab/tools/update_tool.py +4 -8
  560. pygeai/tests/snippets/lab/use_cases/__init__.py +0 -0
  561. pygeai/tests/snippets/lab/use_cases/create_cli_expert.py +1640 -0
  562. pygeai/tests/snippets/lab/use_cases/create_lab_expert.py +4541 -0
  563. pygeai/tests/snippets/lab/use_cases/create_tool_headless_web_browser.py +133 -0
  564. pygeai/tests/snippets/lab/use_cases/create_web_designer.py +189 -0
  565. pygeai/tests/snippets/lab/use_cases/create_web_reader.py +185 -0
  566. pygeai/tests/snippets/lab/{file_summarizer_example.py → use_cases/file_summarizer_example.py} +3 -3
  567. pygeai/tests/snippets/lab/{file_summarizer_example_2.py → use_cases/file_summarizer_example_2.py} +12 -12
  568. pygeai/tests/snippets/lab/use_cases/update_cli_expert.py +1773 -0
  569. pygeai/tests/snippets/lab/use_cases/update_lab_expert.py +4541 -0
  570. pygeai/tests/snippets/lab/use_cases/update_web_designer.py +188 -0
  571. pygeai/tests/snippets/lab/use_cases/update_web_reader.py +195 -0
  572. pygeai/tests/snippets/lab/use_cases/update_web_reader_with_tool.py +210 -0
  573. pygeai/tests/snippets/migrate/__init__.py +45 -0
  574. pygeai/tests/snippets/migrate/agent_migration.py +110 -0
  575. pygeai/tests/snippets/migrate/assistant_migration.py +64 -0
  576. pygeai/tests/snippets/migrate/orchestrator_examples.py +179 -0
  577. pygeai/tests/snippets/migrate/process_migration.py +64 -0
  578. pygeai/tests/snippets/migrate/project_migration.py +42 -0
  579. pygeai/tests/snippets/migrate/tool_migration.py +64 -0
  580. pygeai/tests/snippets/organization/add_project_member.py +10 -0
  581. pygeai/tests/snippets/organization/add_project_member_batch.py +44 -0
  582. pygeai/tests/snippets/organization/create_project.py +2 -2
  583. pygeai/tests/snippets/organization/get_memberships.py +12 -0
  584. pygeai/tests/snippets/organization/get_organization_members.py +6 -0
  585. pygeai/tests/snippets/organization/get_project_members.py +6 -0
  586. pygeai/tests/snippets/organization/get_project_memberships.py +12 -0
  587. pygeai/tests/snippets/organization/get_project_roles.py +6 -0
  588. pygeai/vendor/a2a/__init__.py +1 -0
  589. pygeai/vendor/a2a/auth/__init__.py +0 -0
  590. pygeai/vendor/a2a/auth/user.py +31 -0
  591. pygeai/vendor/a2a/client/__init__.py +19 -0
  592. pygeai/vendor/a2a/client/client.py +425 -0
  593. pygeai/vendor/a2a/client/errors.py +33 -0
  594. pygeai/vendor/a2a/client/helpers.py +22 -0
  595. pygeai/vendor/a2a/py.typed +0 -0
  596. pygeai/vendor/a2a/server/__init__.py +1 -0
  597. pygeai/vendor/a2a/server/agent_execution/__init__.py +18 -0
  598. pygeai/vendor/a2a/server/agent_execution/agent_executor.py +44 -0
  599. pygeai/vendor/a2a/server/agent_execution/context.py +155 -0
  600. pygeai/vendor/a2a/server/agent_execution/request_context_builder.py +20 -0
  601. pygeai/vendor/a2a/server/agent_execution/simple_request_context_builder.py +77 -0
  602. pygeai/vendor/a2a/server/apps/__init__.py +16 -0
  603. pygeai/vendor/a2a/server/apps/jsonrpc/__init__.py +16 -0
  604. pygeai/vendor/a2a/server/apps/jsonrpc/fastapi_app.py +88 -0
  605. pygeai/vendor/a2a/server/apps/jsonrpc/jsonrpc_app.py +426 -0
  606. pygeai/vendor/a2a/server/apps/jsonrpc/starlette_app.py +123 -0
  607. pygeai/vendor/a2a/server/context.py +23 -0
  608. pygeai/vendor/a2a/server/events/__init__.py +21 -0
  609. pygeai/vendor/a2a/server/events/event_consumer.py +149 -0
  610. pygeai/vendor/a2a/server/events/event_queue.py +156 -0
  611. pygeai/vendor/a2a/server/events/in_memory_queue_manager.py +85 -0
  612. pygeai/vendor/a2a/server/events/queue_manager.py +35 -0
  613. pygeai/vendor/a2a/server/request_handlers/__init__.py +20 -0
  614. pygeai/vendor/a2a/server/request_handlers/default_request_handler.py +435 -0
  615. pygeai/vendor/a2a/server/request_handlers/jsonrpc_handler.py +327 -0
  616. pygeai/vendor/a2a/server/request_handlers/request_handler.py +161 -0
  617. pygeai/vendor/a2a/server/request_handlers/response_helpers.py +133 -0
  618. pygeai/vendor/a2a/server/tasks/__init__.py +20 -0
  619. pygeai/vendor/a2a/server/tasks/inmemory_push_notifier.py +62 -0
  620. pygeai/vendor/a2a/server/tasks/inmemory_task_store.py +51 -0
  621. pygeai/vendor/a2a/server/tasks/push_notifier.py +25 -0
  622. pygeai/vendor/a2a/server/tasks/result_aggregator.py +151 -0
  623. pygeai/vendor/a2a/server/tasks/task_manager.py +253 -0
  624. pygeai/vendor/a2a/server/tasks/task_store.py +22 -0
  625. pygeai/vendor/a2a/server/tasks/task_updater.py +155 -0
  626. pygeai/vendor/a2a/types.py +1624 -0
  627. pygeai/vendor/a2a/utils/__init__.py +40 -0
  628. pygeai/vendor/a2a/utils/artifact.py +72 -0
  629. pygeai/vendor/a2a/utils/errors.py +69 -0
  630. pygeai/vendor/a2a/utils/helpers.py +176 -0
  631. pygeai/vendor/a2a/utils/message.py +83 -0
  632. pygeai/vendor/a2a/utils/task.py +57 -0
  633. pygeai/vendor/a2a/utils/telemetry.py +299 -0
  634. pygeai-0.6.0b15.dist-info/METADATA +205 -0
  635. pygeai-0.6.0b15.dist-info/RECORD +799 -0
  636. {pygeai-0.1.51b3.dist-info → pygeai-0.6.0b15.dist-info}/WHEEL +1 -1
  637. {pygeai-0.1.51b3.dist-info → pygeai-0.6.0b15.dist-info}/entry_points.txt +2 -1
  638. {pygeai-0.1.51b3.dist-info → pygeai-0.6.0b15.dist-info}/licenses/LICENSE +13 -1
  639. pygeai-0.6.0b15.dist-info/top_level.txt +1 -0
  640. docs/geai-proxy/README.md +0 -145
  641. docs/source/conf.py +0 -45
  642. pygeai/tests/core/test_managers.py +0 -233
  643. pygeai-0.1.51b3.dist-info/METADATA +0 -130
  644. pygeai-0.1.51b3.dist-info/RECORD +0 -324
  645. pygeai-0.1.51b3.dist-info/top_level.txt +0 -3
  646. scripts/bump_beta_version.py +0 -56
  647. {scripts → pygeai/analytics}/__init__.py +0 -0
  648. /pygeai/tests/snippets/lab/{c_code_fixer_agent_flow.py → use_cases/c_code_fixer_agent_flow.py} +0 -0
@@ -0,0 +1,51 @@
1
+ import asyncio
2
+ import logging
3
+
4
+ from a2a.server.tasks.task_store import TaskStore
5
+ from a2a.types import Task
6
+
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class InMemoryTaskStore(TaskStore):
12
+ """In-memory implementation of TaskStore.
13
+
14
+ Stores task objects in a dictionary in memory. Task data is lost when the
15
+ server process stops.
16
+ """
17
+
18
+ def __init__(self) -> None:
19
+ """Initializes the InMemoryTaskStore."""
20
+ logger.debug('Initializing InMemoryTaskStore')
21
+ self.tasks: dict[str, Task] = {}
22
+ self.lock = asyncio.Lock()
23
+
24
+ async def save(self, task: Task) -> None:
25
+ """Saves or updates a task in the in-memory store."""
26
+ async with self.lock:
27
+ self.tasks[task.id] = task
28
+ logger.debug('Task %s saved successfully.', task.id)
29
+
30
+ async def get(self, task_id: str) -> Task | None:
31
+ """Retrieves a task from the in-memory store by ID."""
32
+ async with self.lock:
33
+ logger.debug('Attempting to get task with id: %s', task_id)
34
+ task = self.tasks.get(task_id)
35
+ if task:
36
+ logger.debug('Task %s retrieved successfully.', task_id)
37
+ else:
38
+ logger.debug('Task %s not found in store.', task_id)
39
+ return task
40
+
41
+ async def delete(self, task_id: str) -> None:
42
+ """Deletes a task from the in-memory store by ID."""
43
+ async with self.lock:
44
+ logger.debug('Attempting to delete task with id: %s', task_id)
45
+ if task_id in self.tasks:
46
+ del self.tasks[task_id]
47
+ logger.debug('Task %s deleted successfully.', task_id)
48
+ else:
49
+ logger.warning(
50
+ 'Attempted to delete nonexistent task with id: %s', task_id
51
+ )
@@ -0,0 +1,25 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ from a2a.types import PushNotificationConfig, Task
4
+
5
+
6
+ class PushNotifier(ABC):
7
+ """PushNotifier interface to store, retrieve push notification for tasks and send push notifications."""
8
+
9
+ @abstractmethod
10
+ async def set_info(
11
+ self, task_id: str, notification_config: PushNotificationConfig
12
+ ) -> None:
13
+ """Sets or updates the push notification configuration for a task."""
14
+
15
+ @abstractmethod
16
+ async def get_info(self, task_id: str) -> PushNotificationConfig | None:
17
+ """Retrieves the push notification configuration for a task."""
18
+
19
+ @abstractmethod
20
+ async def delete_info(self, task_id: str) -> None:
21
+ """Deletes the push notification configuration for a task."""
22
+
23
+ @abstractmethod
24
+ async def send_notification(self, task: Task) -> None:
25
+ """Sends a push notification containing the latest task state."""
@@ -0,0 +1,151 @@
1
+ import asyncio
2
+ import logging
3
+
4
+ from collections.abc import AsyncGenerator, AsyncIterator
5
+
6
+ from a2a.server.events import Event, EventConsumer
7
+ from a2a.server.tasks.task_manager import TaskManager
8
+ from a2a.types import Message, Task, TaskState, TaskStatusUpdateEvent
9
+
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ class ResultAggregator:
15
+ """ResultAggregator is used to process the event streams from an AgentExecutor.
16
+
17
+ There are three main ways to use the ResultAggregator:
18
+ 1) As part of a processing pipe. consume_and_emit will construct the updated
19
+ task as the events arrive, and re-emit those events for another consumer
20
+ 2) As part of a blocking call. consume_all will process the entire stream and
21
+ return the final Task or Message object
22
+ 3) As part of a push solution where the latest Task is emitted after processing an event.
23
+ consume_and_emit_task will consume the Event stream, process the events to the current
24
+ Task object and emit that Task object.
25
+ """
26
+
27
+ def __init__(self, task_manager: TaskManager):
28
+ """Initializes the ResultAggregator.
29
+
30
+ Args:
31
+ task_manager: The `TaskManager` instance to use for processing events
32
+ and managing the task state.
33
+ """
34
+ self.task_manager = task_manager
35
+ self._message: Message | None = None
36
+
37
+ @property
38
+ async def current_result(self) -> Task | Message | None:
39
+ """Returns the current aggregated result (Task or Message).
40
+
41
+ This is the latest state processed from the event stream.
42
+
43
+ Returns:
44
+ The current `Task` object managed by the `TaskManager`, or the final
45
+ `Message` if one was received, or `None` if no result has been produced yet.
46
+ """
47
+ if self._message:
48
+ return self._message
49
+ return await self.task_manager.get_task()
50
+
51
+ async def consume_and_emit(
52
+ self, consumer: EventConsumer
53
+ ) -> AsyncGenerator[Event]:
54
+ """Processes the event stream from the consumer, updates the task state, and re-emits the same events.
55
+
56
+ Useful for streaming scenarios where the server needs to observe and
57
+ process events (e.g., save task state, send push notifications) while
58
+ forwarding them to the client.
59
+
60
+ Args:
61
+ consumer: The `EventConsumer` to read events from.
62
+
63
+ Yields:
64
+ The `Event` objects consumed from the `EventConsumer`.
65
+ """
66
+ async for event in consumer.consume_all():
67
+ await self.task_manager.process(event)
68
+ yield event
69
+
70
+ async def consume_all(
71
+ self, consumer: EventConsumer
72
+ ) -> Task | Message | None:
73
+ """Processes the entire event stream from the consumer and returns the final result.
74
+
75
+ Blocks until the event stream ends (queue is closed after final event or exception).
76
+
77
+ Args:
78
+ consumer: The `EventConsumer` to read events from.
79
+
80
+ Returns:
81
+ The final `Task` object or `Message` object after the stream is exhausted.
82
+ Returns `None` if the stream ends without producing a final result.
83
+
84
+ Raises:
85
+ BaseException: If the `EventConsumer` raises an exception during consumption.
86
+ """
87
+ async for event in consumer.consume_all():
88
+ if isinstance(event, Message):
89
+ self._message = event
90
+ return event
91
+ await self.task_manager.process(event)
92
+ return await self.task_manager.get_task()
93
+
94
+ async def consume_and_break_on_interrupt(
95
+ self, consumer: EventConsumer
96
+ ) -> tuple[Task | Message | None, bool]:
97
+ """Processes the event stream until completion or an interruptable state is encountered.
98
+
99
+ Interruptable states currently include `TaskState.auth_required`.
100
+ If interrupted, consumption continues in a background task.
101
+
102
+ Args:
103
+ consumer: The `EventConsumer` to read events from.
104
+
105
+ Returns:
106
+ A tuple containing:
107
+ - The current aggregated result (`Task` or `Message`) at the point of completion or interruption.
108
+ - A boolean indicating whether the consumption was interrupted (`True`) or completed naturally (`False`).
109
+
110
+ Raises:
111
+ BaseException: If the `EventConsumer` raises an exception during consumption.
112
+ """
113
+ event_stream = consumer.consume_all()
114
+ interrupted = False
115
+ async for event in event_stream:
116
+ if isinstance(event, Message):
117
+ self._message = event
118
+ return event, False
119
+ await self.task_manager.process(event)
120
+ if (
121
+ isinstance(event, Task | TaskStatusUpdateEvent)
122
+ and event.status.state == TaskState.auth_required
123
+ ):
124
+ # auth-required is a special state: the message should be
125
+ # escalated back to the caller, but the agent is expected to
126
+ # continue producing events once the authorization is received
127
+ # out-of-band. This is in contrast to input-required, where a
128
+ # new request is expected in order for the agent to make progress,
129
+ # so the agent should exit.
130
+ logger.debug(
131
+ 'Encountered an auth-required task: breaking synchronous message/send flow.'
132
+ )
133
+ # TODO: We should track all outstanding tasks to ensure they eventually complete.
134
+ asyncio.create_task(self._continue_consuming(event_stream)) # noqa: RUF006
135
+ interrupted = True
136
+ break
137
+ return await self.task_manager.get_task(), interrupted
138
+
139
+ async def _continue_consuming(
140
+ self, event_stream: AsyncIterator[Event]
141
+ ) -> None:
142
+ """Continues processing an event stream in a background task.
143
+
144
+ Used after an interruptable state (like auth_required) is encountered
145
+ in the synchronous consumption flow.
146
+
147
+ Args:
148
+ event_stream: The remaining `AsyncIterator` of events from the consumer.
149
+ """
150
+ async for event in event_stream:
151
+ await self.task_manager.process(event)
@@ -0,0 +1,253 @@
1
+ import logging
2
+
3
+ from a2a.server.events.event_queue import Event
4
+ from a2a.server.tasks.task_store import TaskStore
5
+ from a2a.types import (
6
+ InvalidParamsError,
7
+ Message,
8
+ Task,
9
+ TaskArtifactUpdateEvent,
10
+ TaskState,
11
+ TaskStatus,
12
+ TaskStatusUpdateEvent,
13
+ )
14
+ from a2a.utils import append_artifact_to_task
15
+ from a2a.utils.errors import ServerError
16
+
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ class TaskManager:
22
+ """Helps manage a task's lifecycle during execution of a request.
23
+
24
+ Responsible for retrieving, saving, and updating the `Task` object based on
25
+ events received from the agent.
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ task_id: str | None,
31
+ context_id: str | None,
32
+ task_store: TaskStore,
33
+ initial_message: Message | None,
34
+ ):
35
+ """Initializes the TaskManager.
36
+
37
+ Args:
38
+ task_id: The ID of the task, if known from the request.
39
+ context_id: The ID of the context, if known from the request.
40
+ task_store: The `TaskStore` instance for persistence.
41
+ initial_message: The `Message` that initiated the task, if any.
42
+ Used when creating a new task object.
43
+ """
44
+ self.task_id = task_id
45
+ self.context_id = context_id
46
+ self.task_store = task_store
47
+ self._initial_message = initial_message
48
+ self._current_task: Task | None = None
49
+ logger.debug(
50
+ 'TaskManager initialized with task_id: %s, context_id: %s',
51
+ task_id,
52
+ context_id,
53
+ )
54
+
55
+ async def get_task(self) -> Task | None:
56
+ """Retrieves the current task object, either from memory or the store.
57
+
58
+ If `task_id` is set, it first checks the in-memory `_current_task`,
59
+ then attempts to load it from the `task_store`.
60
+
61
+ Returns:
62
+ The `Task` object if found, otherwise `None`.
63
+ """
64
+ if not self.task_id:
65
+ logger.debug('task_id is not set, cannot get task.')
66
+ return None
67
+
68
+ if self._current_task:
69
+ return self._current_task
70
+
71
+ logger.debug(
72
+ 'Attempting to get task from store with id: %s', self.task_id
73
+ )
74
+ self._current_task = await self.task_store.get(self.task_id)
75
+ if self._current_task:
76
+ logger.debug('Task %s retrieved successfully.', self.task_id)
77
+ else:
78
+ logger.debug('Task %s not found.', self.task_id)
79
+ return self._current_task
80
+
81
+ async def save_task_event(
82
+ self, event: Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent
83
+ ) -> Task | None:
84
+ """Processes a task-related event (Task, Status, Artifact) and saves the updated task state.
85
+
86
+ Ensures task and context IDs match or are set from the event.
87
+
88
+ Args:
89
+ event: The task-related event (`Task`, `TaskStatusUpdateEvent`, or `TaskArtifactUpdateEvent`).
90
+
91
+ Returns:
92
+ The updated `Task` object after processing the event.
93
+
94
+ Raises:
95
+ ServerError: If the task ID in the event conflicts with the TaskManager's ID
96
+ when the TaskManager's ID is already set.
97
+ """
98
+ task_id_from_event = (
99
+ event.id if isinstance(event, Task) else event.taskId
100
+ )
101
+ # If task id is known, make sure it is matched
102
+ if self.task_id and self.task_id != task_id_from_event:
103
+ raise ServerError(
104
+ error=InvalidParamsError(
105
+ message=f"Task in event doesn't match TaskManager {self.task_id} : {task_id_from_event}"
106
+ )
107
+ )
108
+ if not self.task_id:
109
+ self.task_id = task_id_from_event
110
+ if not self.context_id and self.context_id != event.contextId:
111
+ self.context_id = event.contextId
112
+
113
+ logger.debug(
114
+ 'Processing save of task event of type %s for task_id: %s',
115
+ type(event).__name__,
116
+ task_id_from_event,
117
+ )
118
+ if isinstance(event, Task):
119
+ await self._save_task(event)
120
+ return event
121
+
122
+ task: Task = await self.ensure_task(event)
123
+
124
+ if isinstance(event, TaskStatusUpdateEvent):
125
+ logger.debug(
126
+ 'Updating task %s status to: %s', task.id, event.status.state
127
+ )
128
+ if task.status.message:
129
+ if not task.history:
130
+ task.history = [task.status.message]
131
+ else:
132
+ task.history.append(task.status.message)
133
+
134
+ task.status = event.status
135
+ else:
136
+ logger.debug('Appending artifact to task %s', task.id)
137
+ append_artifact_to_task(task, event)
138
+
139
+ await self._save_task(task)
140
+ return task
141
+
142
+ async def ensure_task(
143
+ self, event: TaskStatusUpdateEvent | TaskArtifactUpdateEvent
144
+ ) -> Task:
145
+ """Ensures a Task object exists in memory, loading from store or creating new if needed.
146
+
147
+ Args:
148
+ event: The task-related event triggering the need for a Task object.
149
+
150
+ Returns:
151
+ An existing or newly created `Task` object.
152
+ """
153
+ task: Task | None = self._current_task
154
+ if not task and self.task_id:
155
+ logger.debug(
156
+ 'Attempting to retrieve existing task with id: %s', self.task_id
157
+ )
158
+ task = await self.task_store.get(self.task_id)
159
+
160
+ if not task:
161
+ logger.info(
162
+ 'Task not found or task_id not set. Creating new task for event (task_id: %s, context_id: %s).',
163
+ event.taskId,
164
+ event.contextId,
165
+ )
166
+ # streaming agent did not previously stream task object.
167
+ # Create a task object with the available information and persist the event
168
+ task = self._init_task_obj(event.taskId, event.contextId)
169
+ await self._save_task(task)
170
+
171
+ return task
172
+
173
+ async def process(self, event: Event) -> Event:
174
+ """Processes an event, updates the task state if applicable, stores it, and returns the event.
175
+
176
+ If the event is task-related (`Task`, `TaskStatusUpdateEvent`, `TaskArtifactUpdateEvent`),
177
+ the internal task state is updated and persisted.
178
+
179
+ Args:
180
+ event: The event object received from the agent.
181
+
182
+ Returns:
183
+ The same event object that was processed.
184
+ """
185
+ if isinstance(
186
+ event, Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent
187
+ ):
188
+ await self.save_task_event(event)
189
+
190
+ return event
191
+
192
+ def _init_task_obj(self, task_id: str, context_id: str) -> Task:
193
+ """Initializes a new task object in memory.
194
+
195
+ Args:
196
+ task_id: The ID for the new task.
197
+ context_id: The context ID for the new task.
198
+
199
+ Returns:
200
+ A new `Task` object with initial status and potentially the initial message in history.
201
+ """
202
+ logger.debug(
203
+ 'Initializing new Task object with task_id: %s, context_id: %s',
204
+ task_id,
205
+ context_id,
206
+ )
207
+ history = [self._initial_message] if self._initial_message else []
208
+ return Task(
209
+ id=task_id,
210
+ contextId=context_id,
211
+ status=TaskStatus(state=TaskState.submitted),
212
+ history=history,
213
+ )
214
+
215
+ async def _save_task(self, task: Task) -> None:
216
+ """Saves the given task to the task store and updates the in-memory `_current_task`.
217
+
218
+ Args:
219
+ task: The `Task` object to save.
220
+ """
221
+ logger.debug('Saving task with id: %s', task.id)
222
+ await self.task_store.save(task)
223
+ self._current_task = task
224
+ if not self.task_id:
225
+ logger.info('New task created with id: %s', task.id)
226
+ self.task_id = task.id
227
+ self.context_id = task.contextId
228
+
229
+ def update_with_message(self, message: Message, task: Task) -> Task:
230
+ """Updates a task object in memory by adding a new message to its history.
231
+
232
+ If the task has a message in its current status, that message is moved
233
+ to the history first.
234
+
235
+ Args:
236
+ message: The new `Message` to add to the history.
237
+ task: The `Task` object to update.
238
+
239
+ Returns:
240
+ The updated `Task` object (updated in-place).
241
+ """
242
+ if task.status.message:
243
+ if task.history:
244
+ task.history.append(task.status.message)
245
+ else:
246
+ task.history = [task.status.message]
247
+ task.status.message = None
248
+ if task.history:
249
+ task.history.append(message)
250
+ else:
251
+ task.history = [message]
252
+ self._current_task = task
253
+ return task
@@ -0,0 +1,22 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ from a2a.types import Task
4
+
5
+
6
+ class TaskStore(ABC):
7
+ """Agent Task Store interface.
8
+
9
+ Defines the methods for persisting and retrieving `Task` objects.
10
+ """
11
+
12
+ @abstractmethod
13
+ async def save(self, task: Task) -> None:
14
+ """Saves or updates a task in the store."""
15
+
16
+ @abstractmethod
17
+ async def get(self, task_id: str) -> Task | None:
18
+ """Retrieves a task from the store by ID."""
19
+
20
+ @abstractmethod
21
+ async def delete(self, task_id: str) -> None:
22
+ """Deletes a task from the store by ID."""
@@ -0,0 +1,155 @@
1
+ import uuid
2
+
3
+ from datetime import datetime, timezone
4
+ from typing import Any
5
+
6
+ from a2a.server.events import EventQueue
7
+ from a2a.types import (
8
+ Artifact,
9
+ Message,
10
+ Part,
11
+ Role,
12
+ TaskArtifactUpdateEvent,
13
+ TaskState,
14
+ TaskStatus,
15
+ TaskStatusUpdateEvent,
16
+ )
17
+
18
+
19
+ class TaskUpdater:
20
+ """Helper class for agents to publish updates to a task's event queue.
21
+
22
+ Simplifies the process of creating and enqueueing standard task events.
23
+ """
24
+
25
+ def __init__(self, event_queue: EventQueue, task_id: str, context_id: str):
26
+ """Initializes the TaskUpdater.
27
+
28
+ Args:
29
+ event_queue: The `EventQueue` associated with the task.
30
+ task_id: The ID of the task.
31
+ context_id: The context ID of the task.
32
+ """
33
+ self.event_queue = event_queue
34
+ self.task_id = task_id
35
+ self.context_id = context_id
36
+
37
+ async def update_status(
38
+ self,
39
+ state: TaskState,
40
+ message: Message | None = None,
41
+ final: bool = False,
42
+ timestamp: str | None = None,
43
+ ) -> None:
44
+ """Updates the status of the task and publishes a `TaskStatusUpdateEvent`.
45
+
46
+ Args:
47
+ state: The new state of the task.
48
+ message: An optional message associated with the status update.
49
+ final: If True, indicates this is the final status update for the task.
50
+ timestamp: Optional ISO 8601 datetime string. Defaults to current time.
51
+ """
52
+ current_timestamp = (
53
+ timestamp if timestamp else datetime.now(timezone.utc).isoformat()
54
+ )
55
+ await self.event_queue.enqueue_event(
56
+ TaskStatusUpdateEvent(
57
+ taskId=self.task_id,
58
+ contextId=self.context_id,
59
+ final=final,
60
+ status=TaskStatus(
61
+ state=state,
62
+ message=message,
63
+ timestamp=current_timestamp,
64
+ ),
65
+ )
66
+ )
67
+
68
+ async def add_artifact(
69
+ self,
70
+ parts: list[Part],
71
+ artifact_id: str | None = None,
72
+ name: str | None = None,
73
+ metadata: dict[str, Any] | None = None,
74
+ ) -> None:
75
+ """Adds an artifact chunk to the task and publishes a `TaskArtifactUpdateEvent`.
76
+
77
+ Args:
78
+ parts: A list of `Part` objects forming the artifact chunk.
79
+ artifact_id: The ID of the artifact. A new UUID is generated if not provided.
80
+ name: Optional name for the artifact.
81
+ metadata: Optional metadata for the artifact.
82
+ """
83
+ if not artifact_id:
84
+ artifact_id = str(uuid.uuid4())
85
+
86
+ await self.event_queue.enqueue_event(
87
+ TaskArtifactUpdateEvent(
88
+ taskId=self.task_id,
89
+ contextId=self.context_id,
90
+ artifact=Artifact(
91
+ artifactId=artifact_id,
92
+ name=name,
93
+ parts=parts,
94
+ metadata=metadata,
95
+ ),
96
+ )
97
+ )
98
+
99
+ async def complete(self, message: Message | None = None) -> None:
100
+ """Marks the task as completed and publishes a final status update."""
101
+ await self.update_status(
102
+ TaskState.completed,
103
+ message=message,
104
+ final=True,
105
+ )
106
+
107
+ async def failed(self, message: Message | None = None) -> None:
108
+ """Marks the task as failed and publishes a final status update."""
109
+ await self.update_status(TaskState.failed, message=message, final=True)
110
+
111
+ async def reject(self, message: Message | None = None) -> None:
112
+ """Marks the task as rejected and publishes a final status update."""
113
+ await self.update_status(
114
+ TaskState.rejected, message=message, final=True
115
+ )
116
+
117
+ async def submit(self, message: Message | None = None) -> None:
118
+ """Marks the task as submitted and publishes a status update."""
119
+ await self.update_status(
120
+ TaskState.submitted,
121
+ message=message,
122
+ )
123
+
124
+ async def start_work(self, message: Message | None = None) -> None:
125
+ """Marks the task as working and publishes a status update."""
126
+ await self.update_status(
127
+ TaskState.working,
128
+ message=message,
129
+ )
130
+
131
+ def new_agent_message(
132
+ self,
133
+ parts: list[Part],
134
+ metadata: dict[str, Any] | None = None,
135
+ ) -> Message:
136
+ """Creates a new message object sent by the agent for this task/context.
137
+
138
+ Note: This method only *creates* the message object. It does not
139
+ automatically enqueue it.
140
+
141
+ Args:
142
+ parts: A list of `Part` objects for the message content.
143
+ metadata: Optional metadata for the message.
144
+
145
+ Returns:
146
+ A new `Message` object.
147
+ """
148
+ return Message(
149
+ role=Role.agent,
150
+ taskId=self.task_id,
151
+ contextId=self.context_id,
152
+ messageId=str(uuid.uuid4()),
153
+ metadata=metadata,
154
+ parts=parts,
155
+ )