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
@@ -1,21 +1,19 @@
1
1
  import json
2
- from json import JSONDecodeError
3
2
 
4
- from pygeai.core.base.clients import BaseClient
3
+ from pygeai import logger
4
+ from pygeai.core.common.exceptions import InvalidAPIResponseException, MissingRequirementException, APIResponseError
5
+ from pygeai.core.utils.validators import validate_status_code
6
+ from pygeai.core.utils.parsers import parse_json_response
7
+ from pygeai.lab.constants import VALID_SCOPES, VALID_ACCESS_SCOPES, VALID_REPORT_EVENTS
5
8
  from pygeai.lab.tools.endpoints import CREATE_TOOL_V2, LIST_TOOLS_V2, GET_TOOL_V2, UPDATE_TOOL_V2, UPSERT_TOOL_V2, \
6
9
  PUBLISH_TOOL_REVISION_V2, GET_PARAMETER_V2, SET_PARAMETER_V2, DELETE_TOOL_V2
10
+ from pygeai.lab.clients import AILabClient
7
11
 
8
12
 
9
- VALID_SCOPES = ["builtin", "external", "api", "proxied"]
10
- VALID_ACCESS_SCOPES = ["public", "private"]
11
- VALID_REPORT_EVENTS = ["None", "All", "Start", "Finish", "Progress"]
12
-
13
-
14
- class ToolClient(BaseClient):
13
+ class ToolClient(AILabClient):
15
14
 
16
15
  def create_tool(
17
16
  self,
18
- project_id: str,
19
17
  name: str,
20
18
  description: str = None,
21
19
  scope: str = None,
@@ -31,7 +29,6 @@ class ToolClient(BaseClient):
31
29
  """
32
30
  Creates a new tool in the specified project.
33
31
 
34
- :param project_id: str - Unique identifier of the project where the tool will be created.
35
32
  :param name: str - Name of the tool. Must be non-empty, unique within the project, and exclude ':' or '/'.
36
33
  :param description: str - Description of the tool's purpose, helping agents decide when to use it. Optional.
37
34
  :param scope: str - Scope of the tool, either 'builtin', 'external', or 'api'. Optional.
@@ -100,33 +97,22 @@ class ToolClient(BaseClient):
100
97
  if parameters:
101
98
  data["tool"]["parameters"] = parameters
102
99
 
100
+ logger.debug(f"Creating new tool with data: {data}")
101
+
103
102
  endpoint = CREATE_TOOL_V2
104
103
  if automatic_publish:
105
104
  endpoint = f"{endpoint}?automaticPublish=true"
106
105
 
107
- headers = {
108
- "Accept": "application/json",
109
- "Content-Type": "application/json",
110
- "Authorization": self.api_service.token,
111
- "ProjectId": project_id
112
- }
113
-
114
106
  response = self.api_service.post(
115
107
  endpoint=endpoint,
116
- headers=headers,
117
108
  data=data
118
109
  )
119
-
120
- try:
121
- result = response.json()
122
- except JSONDecodeError as e:
123
- result = response.text
124
-
125
- return result
110
+
111
+ validate_status_code(response)
112
+ return parse_json_response(response, f"create tool for project {self.project_id}")
126
113
 
127
114
  def list_tools(
128
115
  self,
129
- project_id: str,
130
116
  id: str = "",
131
117
  count: str = "100",
132
118
  access_scope: str = "public",
@@ -137,7 +123,6 @@ class ToolClient(BaseClient):
137
123
  """
138
124
  Retrieves a list of tools associated with the specified project.
139
125
 
140
- :param project_id: str - Unique identifier of the project.
141
126
  :param id: str - ID of the tool to filter by. Defaults to "" (no filtering).
142
127
  :param count: str - Number of tools to retrieve. Defaults to "100".
143
128
  :param access_scope: str - Access scope of the tools, either "public" or "private". Defaults to "public".
@@ -147,17 +132,14 @@ class ToolClient(BaseClient):
147
132
  :return: dict or str - JSON response containing the list of tools if successful, otherwise the raw response text.
148
133
  """
149
134
  endpoint = LIST_TOOLS_V2
150
- headers = {
151
- "Authorization": self.api_service.token,
152
- "ProjectId": project_id
153
- }
154
135
 
155
136
  if scope and scope not in VALID_SCOPES:
156
137
  raise ValueError(f"Scope must be one of {', '.join(VALID_SCOPES)}.")
157
138
 
139
+ logger.debug(f"Listing tools available for the project with ID: {self.project_id}")
140
+
158
141
  response = self.api_service.get(
159
142
  endpoint=endpoint,
160
- headers=headers,
161
143
  params={
162
144
  "id": id,
163
145
  "count": count,
@@ -167,16 +149,11 @@ class ToolClient(BaseClient):
167
149
  "allowExternal": allow_external
168
150
  }
169
151
  )
170
- try:
171
- result = response.json()
172
- except JSONDecodeError as e:
173
- result = response.text
174
-
175
- return result
152
+ validate_status_code(response)
153
+ return parse_json_response(response, f"list tools for project {self.project_id}")
176
154
 
177
155
  def get_tool(
178
156
  self,
179
- project_id: str,
180
157
  tool_id: str,
181
158
  revision: str = 0,
182
159
  version: int = 0,
@@ -185,7 +162,6 @@ class ToolClient(BaseClient):
185
162
  """
186
163
  Retrieves details of a specific tool from the specified project.
187
164
 
188
- :param project_id: str - Unique identifier of the project.
189
165
  :param tool_id: str - Unique identifier of the tool to retrieve.
190
166
  :param revision: str - Revision of the tool to retrieve. Defaults to 0 (latest revision).
191
167
  :param version: int - Version of the tool to retrieve. Defaults to 0 (latest version).
@@ -193,37 +169,28 @@ class ToolClient(BaseClient):
193
169
  :return: dict or str - JSON response containing the tool details if successful, otherwise the raw response text.
194
170
  """
195
171
  endpoint = GET_TOOL_V2.format(toolId=tool_id)
196
- headers = {
197
- "Authorization": self.api_service.token,
198
- "ProjectId": project_id
199
- }
172
+ logger.debug(f"Retrieving detail of tool with ID: {tool_id}")
200
173
 
201
174
  response = self.api_service.get(
202
175
  endpoint=endpoint,
203
- headers=headers,
204
176
  params={
205
177
  "revision": revision,
206
178
  "version": version,
207
179
  "allowDrafts": allow_drafts,
208
180
  }
209
181
  )
210
- try:
211
- result = response.json()
212
- except JSONDecodeError as e:
213
- result = response.text
182
+ validate_status_code(response)
183
+ return parse_json_response(response, f"retrieve tool {tool_id} for project {self.project_id}")
214
184
 
215
- return result
216
185
 
217
186
  def delete_tool(
218
187
  self,
219
- project_id: str,
220
188
  tool_id: str = None,
221
189
  tool_name: str = None
222
190
  ) -> dict | str:
223
191
  """
224
192
  Deletes a specific tool from the specified project.
225
193
 
226
- :param project_id: str - Unique identifier of the project.
227
194
  :param tool_id: str, optional - Unique identifier of the tool to delete. Defaults to None.
228
195
  :param tool_name: str, optional - Name of the tool to delete. Defaults to None.
229
196
  :return: dict or str - JSON response containing the result of the delete operation if successful,
@@ -234,27 +201,26 @@ class ToolClient(BaseClient):
234
201
  raise ValueError("Either tool_id or tool_name must be provided.")
235
202
 
236
203
  endpoint = DELETE_TOOL_V2.format(toolId=tool_id if tool_id else tool_name)
237
- headers = {
238
- "Authorization": self.api_service.token,
239
- "ProjectId": project_id
240
- }
204
+
205
+ if tool_id:
206
+ logger.debug(f"Deleting tool with ID {tool_id}")
207
+ else:
208
+ logger.debug(f"Deleting tool with name '{tool_name}'")
241
209
 
242
210
  response = self.api_service.delete(
243
211
  endpoint=endpoint,
244
- headers=headers
245
212
  )
213
+ validate_status_code(response)
246
214
 
247
- try:
248
- result = response.json()
249
- except JSONDecodeError as e:
250
- result = response.text
251
-
252
- return result
215
+ if response.status_code != 204:
216
+ logger.error(f"Unable to delete tool {tool_id or tool_name} in project {self.project_id}: JSON parsing error (status {response.status_code}). Response: {response.text}")
217
+ raise InvalidAPIResponseException(f"Unable to delete tool {tool_id or tool_name} in project {self.project_id}: {response.text}")
218
+ else:
219
+ return {}
253
220
 
254
221
  def update_tool(
255
222
  self,
256
- project_id: str,
257
- tool_id: str,
223
+ tool_id: str = None,
258
224
  name: str = None,
259
225
  description: str = None,
260
226
  scope: str = None,
@@ -271,7 +237,6 @@ class ToolClient(BaseClient):
271
237
  """
272
238
  Updates an existing tool in the specified project or upserts it if specified.
273
239
 
274
- :param project_id: str - Unique identifier of the project containing the tool.
275
240
  :param tool_id: str - Unique identifier of the tool to update. Required for update operations.
276
241
  :param name: str - Updated name of the tool. Must be non-empty, unique within the project, and exclude ':' or '/' if provided. Optional.
277
242
  :param description: str - Updated description of the tool's purpose, helping agents decide when to use it. Optional.
@@ -312,6 +277,8 @@ class ToolClient(BaseClient):
312
277
  :raises JSONDecodeError: Caught internally if the response cannot be parsed as JSON; returns raw response text.
313
278
  :raises Exception: May be raised by `api_service.put` for network issues, authentication errors, or server-side problems (not caught here).
314
279
  """
280
+ if not (tool_id or name):
281
+ raise ValueError(f"Either tool ID or tool Name must be defined in order to update tool.")
315
282
  if scope and scope not in VALID_SCOPES:
316
283
  raise ValueError(f"Scope must be one of {', '.join(VALID_SCOPES)}.")
317
284
  if access_scope and access_scope not in VALID_ACCESS_SCOPES:
@@ -344,66 +311,48 @@ class ToolClient(BaseClient):
344
311
  if parameters:
345
312
  data["tool"]["parameters"] = parameters
346
313
 
314
+ logger.debug(f"Updating tool with ID {tool_id} with data: {data}")
315
+
347
316
  endpoint = UPSERT_TOOL_V2 if upsert else UPDATE_TOOL_V2
348
317
  endpoint = endpoint.format(toolId=tool_id) if tool_id else endpoint.format(toolId=name)
349
318
 
350
319
  if automatic_publish:
351
320
  endpoint = f"{endpoint}?automaticPublish=true"
352
321
 
353
- headers = {
354
- "Authorization": self.api_service.token,
355
- "ProjectId": project_id
356
- }
357
322
  response = self.api_service.put(
358
323
  endpoint=endpoint,
359
- headers=headers,
360
324
  data=data
361
325
  )
362
-
363
- try:
364
- result = response.json()
365
- except JSONDecodeError as e:
366
- result = response.text
367
-
368
- return result
326
+ validate_status_code(response)
327
+ return parse_json_response(response, f"update tool {tool_id} in project {self.project_id}")
369
328
 
370
329
  def publish_tool_revision(
371
330
  self,
372
- project_id: str,
373
331
  tool_id: str,
374
332
  revision: str
375
333
  ):
376
334
  """
377
335
  Publishes a specific revision of a tool in the specified project.
378
336
 
379
- :param project_id: str - Unique identifier of the project.
380
337
  :param tool_id: str - Unique identifier of the tool to publish.
381
338
  :param revision: str - Revision of the tool to publish.
382
339
  :return: dict or str - JSON response containing the result of the publish operation if successful, otherwise the raw response text.
383
340
  """
384
341
  endpoint = PUBLISH_TOOL_REVISION_V2.format(toolId=tool_id)
385
- headers = {
386
- "Authorization": self.api_service.token,
387
- "ProjectId": project_id
388
- }
342
+ logger.debug(f"Publishing revision {revision} for tool with ID {tool_id}")
389
343
 
390
344
  response = self.api_service.post(
391
345
  endpoint=endpoint,
392
- headers=headers,
393
346
  data={
394
347
  "revision": revision,
395
348
  }
396
349
  )
397
- try:
398
- result = response.json()
399
- except JSONDecodeError as e:
400
- result = response.text
350
+ validate_status_code(response)
351
+ return parse_json_response(response, f"publish revision {revision} for tool {tool_id} in project {self.project_id}")
401
352
 
402
- return result
403
353
 
404
354
  def get_parameter(
405
355
  self,
406
- project_id: str,
407
356
  tool_id: str = None,
408
357
  tool_public_name: str = None,
409
358
  revision: str = 0,
@@ -413,7 +362,6 @@ class ToolClient(BaseClient):
413
362
  """
414
363
  Retrieves details of parameters for a specific tool identified by either its ID or public name in the specified project.
415
364
 
416
- :param project_id: str - Unique identifier of the project.
417
365
  :param tool_id: str, optional - Unique identifier of the tool whose parameters are to be retrieved. Defaults to None.
418
366
  :param tool_public_name: str, optional - Public name of the tool whose parameters are to be retrieved. Defaults to None.
419
367
  :param revision: str - Revision of the parameters to retrieve. Defaults to "0" (latest revision).
@@ -425,31 +373,26 @@ class ToolClient(BaseClient):
425
373
  if not (tool_id or tool_public_name):
426
374
  raise ValueError("Either tool_id or tool_public_name must be provided.")
427
375
 
428
- endpoint = GET_PARAMETER_V2.format(toolPublicName=tool_public_name) if tool_public_name else GET_PARAMETER_V2.format(toolPublicName=tool_id)
429
- headers = {
430
- "Authorization": self.api_service.token,
431
- "ProjectId": project_id
432
- }
376
+ if tool_id:
377
+ logger.debug(f"Retrieving parameter for tool with ID {tool_id}")
378
+ else:
379
+ logger.debug(f"Retrieving parameter for tool with name '{tool_public_name}'")
433
380
 
381
+ endpoint = GET_PARAMETER_V2.format(toolPublicName=tool_public_name) if tool_public_name else GET_PARAMETER_V2.format(toolPublicName=tool_id)
434
382
  response = self.api_service.get(
435
383
  endpoint=endpoint,
436
- headers=headers,
437
384
  params={
438
385
  "revision": revision,
439
386
  "version": version,
440
387
  "allowDrafts": allow_drafts,
441
388
  }
442
389
  )
443
- try:
444
- result = response.json()
445
- except JSONDecodeError as e:
446
- result = response.text
447
-
448
- return result
390
+ validate_status_code(response)
391
+ tool_identifier = tool_id or tool_public_name
392
+ return parse_json_response(response, f"retrieve parameters for tool {tool_identifier} in project {self.project_id}")
449
393
 
450
394
  def set_parameter(
451
395
  self,
452
- project_id: str,
453
396
  tool_id: str = None,
454
397
  tool_public_name: str = None,
455
398
  parameters: list = None
@@ -457,7 +400,6 @@ class ToolClient(BaseClient):
457
400
  """
458
401
  Sets or updates parameters for a specific tool identified by either its ID or public name in the specified project.
459
402
 
460
- :param project_id: str - Unique identifier of the project.
461
403
  :param tool_id: str, optional - Unique identifier of the tool whose parameters are to be set. Defaults to None.
462
404
  :param tool_public_name: str, optional - Public name of the tool whose parameters are to be set. Defaults to None.
463
405
  :param parameters: list - List of parameter dictionaries defining the tool's parameters.
@@ -472,12 +414,6 @@ class ToolClient(BaseClient):
472
414
  raise ValueError("Parameters list must be provided and non-empty.")
473
415
 
474
416
  endpoint = SET_PARAMETER_V2.format(toolPublicName=tool_public_name) if tool_public_name else SET_PARAMETER_V2.format(toolPublicName=tool_id)
475
- headers = {
476
- "Authorization": self.api_service.token,
477
- "ProjectId": project_id,
478
- "Content-Type": "application/json",
479
- "Accept": "application/json"
480
- }
481
417
 
482
418
  data = {
483
419
  "parameterDefinition": {
@@ -485,14 +421,45 @@ class ToolClient(BaseClient):
485
421
  }
486
422
  }
487
423
 
424
+ if tool_id:
425
+ logger.debug(f"Setting parameter for tool with ID {tool_id} with data: {data}")
426
+ else:
427
+ logger.debug(f"Setting parameter for tool with name '{tool_public_name}' with data: {data}")
428
+
488
429
  response = self.api_service.post(
489
430
  endpoint=endpoint,
490
- headers=headers,
491
431
  data=data
492
432
  )
493
- try:
494
- result = response.json()
495
- except JSONDecodeError as e:
496
- result = response.text
433
+ if response.status_code != 204:
434
+ logger.error(f"Unable to set parameters for tool {tool_id or tool_public_name} in project {self.project_id}: JSON parsing error (status {response.status_code}). Response: {response.text}")
435
+ raise InvalidAPIResponseException(f"Unable to set parameters for tool {tool_id or tool_public_name} in project {self.project_id}: {response.text}")
436
+ else:
437
+ return {}
438
+
439
+ '''
440
+ def export_tool(
441
+ self,
442
+ tool_id: str,
443
+ ) -> dict:
444
+ """
445
+ Retrieves details of a specific tool from the specified project.
446
+
447
+ :param tool_id: str - Unique identifier of the tool to retrieve.
448
+ :return: dict - JSON response containing the tool details.
449
+ :raises InvalidAPIResponseException: If the response cannot be parsed as JSON or an error occurs.
450
+ :raises MissingRequirementException: If project_id or tool_id is not provided.
451
+ """
452
+
453
+ if not tool_id:
454
+ raise MissingRequirementException("tool_id must be specified in order to retrieve the tool")
455
+
456
+ endpoint = EXPORT_TOOL_V4.format(toolId=tool_id)
457
+ logger.debug(f"Exporting tool with ID {tool_id}")
458
+
459
+ response = self.api_service.get(
460
+ endpoint=endpoint,
461
+ )
462
+ validate_status_code(response)
463
+ return parse_json_response(response, f"export tool {tool_id} for project {self.project_id}")
497
464
 
498
- return result
465
+ '''
@@ -7,3 +7,7 @@ UPSERT_TOOL_V2 = "v2/tools/{toolId}/upsert" # PUT -> Update or insert tool data
7
7
  PUBLISH_TOOL_REVISION_V2 = "v2/tools/{toolId}/publish-revision" # POST -> Publish Tool revision
8
8
  GET_PARAMETER_V2 = "v2/tools/{toolPublicName}/config" # GET -> Get tool parameter
9
9
  SET_PARAMETER_V2 = "v2/tools/{toolPublicName}/config" # POST -> Set tool parameter
10
+ EXPORT_TOOL_V2 = "v2/tools/{toolId}/export" # GET -> Export tool
11
+ IMPORT_TOOL_V2 = "v2/tools/import" # POST -> Import tool
12
+ EXPORT_TOOL_V4 = "v4/tools/{toolId}/export" # GET -> Export tool
13
+ IMPORT_TOOL_V4 = "v4/tools/import" # POST -> Import tool
@@ -37,8 +37,8 @@ class ToolMapper:
37
37
  """
38
38
  return [
39
39
  ToolMessage(
40
- description=msg["description"],
41
- type=msg["type"]
40
+ description=msg.get("description"),
41
+ type=msg.get("type")
42
42
  )
43
43
  for msg in messages_data
44
44
  ]
@@ -55,9 +55,9 @@ class ToolMapper:
55
55
  """
56
56
  tool_data = data.get("tool", data)
57
57
 
58
- name = tool_data["name"]
59
- description = tool_data["description"]
60
- scope = tool_data["scope"]
58
+ name = tool_data.get("name")
59
+ description = tool_data.get("description")
60
+ scope = tool_data.get("scope")
61
61
  parameter_data = tool_data.get("parameters")
62
62
  parameters = cls._map_parameters(parameter_data) if parameter_data else None
63
63
 
@@ -58,6 +58,17 @@ The configuration file should be in JSON format with the following structure:
58
58
  }
59
59
  .fi
60
60
  .TP
61
+ .B Example: HTTP+SSE Server
62
+ .nf
63
+ {
64
+ "mcpServers": {
65
+ "markitdown": {
66
+ "uri": "http://localhost:5000/sse"
67
+ }
68
+ }
69
+ }
70
+ .fi
71
+ .TP
61
72
  .B Example: Multiple Servers Combined
62
73
  .nf
63
74
  {
@@ -70,6 +81,9 @@ The configuration file should be in JSON format with the following structure:
70
81
  "command": "npx",
71
82
  "args": ["-y", "@modelcontextprotocol/server-filesystem", "~/mcp-shared-folder"]
72
83
  },
84
+ "markitdown": {
85
+ "uri": "http://localhost:5000/sse"
86
+ },
73
87
  "custom-server": {
74
88
  "command": "python",
75
89
  "args": ["path/to/your/custom_mcp_server.py"]
@@ -78,6 +92,55 @@ The configuration file should be in JSON format with the following structure:
78
92
  }
79
93
  .fi
80
94
 
95
+ .SH PUBLIC TOOL REGISTRATION
96
+ Tools provided by both MCP and A2A servers can be published to GEAI under a public namespace
97
+ by including the \fBpublic_prefix\fR field in their configuration entry.
98
+
99
+ This allows tools to be registered under a well-defined global identifier, making them
100
+ discoverable and shareable across proxies and clients.
101
+
102
+ .SS MCP SERVER EXAMPLE WITH PUBLIC PREFIX
103
+ The following configuration registers all tools from the \fBpuppeteer\fR MCP server under
104
+ the public prefix \fIcom.globant.puppeteer\fR:
105
+
106
+ .nf
107
+ {
108
+ "mcpServers": {
109
+ "public_prefix": "com.globant.puppeteer",
110
+ "puppeteer": {
111
+ "command": "npx",
112
+ "args": ["-y", "@modelcontextprotocol/server-puppeteer"]
113
+ }
114
+ }
115
+ }
116
+ .fi
117
+
118
+ .SS A2A SERVER EXAMPLE WITH PUBLIC PREFIX
119
+ The following configuration registers the tools provided by the \fBhello-world\fR A2A agent
120
+ under the prefix \fIcom.genexus.a2a.sampleagent\fR:
121
+
122
+ .nf
123
+ {
124
+ "a2aServers": {
125
+ "hello-world": {
126
+ "public_prefix": "com.genexus.a2a.sampleagent",
127
+ "url": "http://localhost:9999",
128
+ "headers": {
129
+ "Authorization": "Bearer fh84ff...."
130
+ }
131
+ }
132
+ }
133
+ }
134
+ .fi
135
+
136
+ .SS RESULTING TOOL IDENTIFIERS
137
+ When this prefix is set, all tools will be published using it. For example, a tool named
138
+ \fBtranslate_text\fR would be available as:
139
+
140
+ .nf
141
+ com.genexus.a2a.sampleagent.translate_text
142
+ .fi
143
+
81
144
  .SS 2. Proxy Authentication Configuration
82
145
  This section establishes the connection between the proxy and GEAI and manages user aliases.
83
146
  .TP
@@ -102,6 +165,48 @@ Generated new proxy ID: 37bae96b-bc99-4110-bb61-b912b28f9e32
102
165
  -> Insert proxy description:
103
166
  .fi
104
167
 
168
+ .SH PROXY CONFIGURATION PARAMETERS
169
+ During interactive setup, the following parameters are requested:
170
+
171
+ .TP
172
+ \fBproxy ID (UUID)\fR
173
+ A unique identifier for this proxy instance. If left empty, the automatically generated UUID
174
+ will be used.
175
+
176
+ .TP
177
+ \fBproxy API key\fR
178
+ The API key used to authenticate the proxy with the GEAI backend. This must be an API token
179
+ generated in GEAI for a specific project.
180
+
181
+ .TP
182
+ \fBproxy base URL\fR
183
+ The base URL of the GEAI installation this proxy will connect to.
184
+ For example: \fIhttps://api.beta.saia.ai\fR
185
+
186
+ .TP
187
+ \fBproxy name\fR
188
+ A human-readable name assigned to this instance of \fBgeai-proxy\fR. This name is stored under the configured alias.
189
+
190
+ .TP
191
+ \fBproxy description\fR
192
+ An optional description to help identify this proxy instance, especially when multiple proxies are used under different aliases.
193
+
194
+ .SS Environment Variables
195
+ The above configuration parameters can also be set using environment variables:
196
+
197
+ .TP
198
+ \fBGEAI_API_KEY\fR
199
+ .TP
200
+ \fBGEAI_API_BASE_URL\fR
201
+ .TP
202
+ \fBPROXY_ID\fR
203
+ .TP
204
+ \fBPROXY_NAME\fR
205
+ .TP
206
+ \fBPROXY_DESCRIPTION\fR
207
+
208
+ These environment variables override or represent the configuration of the \fBdefault alias\fR. Therefore, they are only taken into account if the proxy is invoked with \fB\-\-alias default\fR. When using a different alias, these variables are ignored.
209
+
105
210
  .SH USAGE
106
211
  To start the proxy server with a specific configuration and alias:
107
212
  .nf
@@ -123,6 +228,17 @@ Reconfigure proxy authentication settings.
123
228
  Sample configuration file for MCP servers.
124
229
  .SH SEE ALSO
125
230
  .BR pygeai (1)
231
+ .SH THIRD-PARTY COMPONENTS
232
+ This software includes code from the \fBa2a-python\fR project developed by Google LLC, which is licensed under the Apache License, Version 2.0.
233
+
234
+ Only the vendored component located in \fIpygeai/vendor/a2a/\fR is subject to the Apache License. The rest of this software is licensed under the MIT License.
235
+
236
+ For full license details, see:
237
+ .IP \[bu]
238
+ https://github.com/google/a2a-python
239
+ .IP \[bu]
240
+ pygeai/vendor/a2a/LICENSE
241
+
126
242
  .SH AUTHOR
127
243
  Written by the GEAI development team.
128
244
  .SH COPYRIGHT