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.
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,151 @@
1
+ import traceback
2
+ from difflib import SequenceMatcher
3
+ from typing import List, Optional, Tuple
4
+
5
+ from pygeai import logger
6
+ from pygeai.cli.commands import Command, Option
7
+ from pygeai.core.utils.console import Console
8
+
9
+
10
+ FUZZY_MATCH_THRESHOLD = 0.6
11
+ MAX_FUZZY_SUGGESTIONS = 3
12
+
13
+
14
+ class ExitCode:
15
+ SUCCESS = 0
16
+ USER_INPUT_ERROR = 1
17
+ MISSING_REQUIREMENT = 2
18
+ SERVICE_ERROR = 3
19
+ KEYBOARD_INTERRUPT = 130
20
+ UNEXPECTED_ERROR = 255
21
+
22
+
23
+ class ErrorHandler:
24
+
25
+ @staticmethod
26
+ def format_error(
27
+ error_type: str,
28
+ message: str,
29
+ suggestion: Optional[str] = None,
30
+ show_help: bool = True,
31
+ example: Optional[str] = None
32
+ ) -> str:
33
+ """
34
+ Formats an error message with optional suggestion and example.
35
+
36
+ :param error_type: str - Type of error (e.g., "Unknown Command").
37
+ :param message: str - The error message.
38
+ :param suggestion: Optional[str] - Suggested fix or next steps.
39
+ :param show_help: bool - Whether to show help command hint.
40
+ :param example: Optional[str] - Example of correct usage.
41
+ :return: str - Formatted error message.
42
+ """
43
+ output = f"ERROR [{error_type}]: {message}"
44
+
45
+ if suggestion:
46
+ output += f"\n → {suggestion}"
47
+
48
+ if example:
49
+ output += f"\n\n Example:\n {example}"
50
+
51
+ if show_help:
52
+ output += "\n\nRun 'geai help' for usage information."
53
+
54
+ return output
55
+
56
+ @staticmethod
57
+ def find_similar_items(
58
+ item: str,
59
+ available_items: List[str],
60
+ threshold: float = FUZZY_MATCH_THRESHOLD
61
+ ) -> List[str]:
62
+ """
63
+ Finds similar items using fuzzy string matching.
64
+
65
+ :param item: str - The item to match against.
66
+ :param available_items: List[str] - List of available items.
67
+ :param threshold: float - Minimum similarity ratio (0.0 to 1.0).
68
+ :return: List[str] - List of similar items, up to MAX_FUZZY_SUGGESTIONS.
69
+ """
70
+ similarities: List[Tuple[str, float]] = []
71
+ for available in available_items:
72
+ ratio = SequenceMatcher(None, item.lower(), available.lower()).ratio()
73
+ if ratio >= threshold:
74
+ similarities.append((available, ratio))
75
+
76
+ similarities.sort(key=lambda x: x[1], reverse=True)
77
+ return [item[0] for item in similarities[:MAX_FUZZY_SUGGESTIONS]]
78
+
79
+ @staticmethod
80
+ def get_available_commands(commands: List[Command]) -> List[str]:
81
+ all_identifiers = []
82
+ for cmd in commands:
83
+ all_identifiers.extend(cmd.identifiers)
84
+ return all_identifiers
85
+
86
+ @staticmethod
87
+ def get_available_options(options: List[Option]) -> List[str]:
88
+ all_identifiers = []
89
+ for opt in options:
90
+ all_identifiers.extend(opt.identifiers)
91
+ return all_identifiers
92
+
93
+ @staticmethod
94
+ def handle_unknown_command(command: str, available_commands: List[Command]) -> str:
95
+ cmd_identifiers = ErrorHandler.get_available_commands(available_commands)
96
+ similar = ErrorHandler.find_similar_items(command, cmd_identifiers)
97
+
98
+ message = f"'{command}' is not a valid command."
99
+
100
+ if similar:
101
+ suggestion = f"Did you mean: {', '.join(similar)}?"
102
+ else:
103
+ suggestion = f"Available commands: {', '.join(sorted(set([cmd.identifiers[0] for cmd in available_commands])))}"
104
+
105
+ return ErrorHandler.format_error("Unknown Command", message, suggestion)
106
+
107
+ @staticmethod
108
+ def handle_unknown_option(option: str, available_options: List[Option]) -> str:
109
+ opt_identifiers = ErrorHandler.get_available_options(available_options)
110
+ similar = ErrorHandler.find_similar_items(option, opt_identifiers)
111
+
112
+ message = f"'{option}' is not a valid option."
113
+
114
+ if similar:
115
+ suggestion = f"Did you mean: {', '.join(similar)}?"
116
+ else:
117
+ suggestion = f"Available options: {', '.join(sorted(set([opt.identifiers[0] for opt in available_options])))}"
118
+
119
+ return ErrorHandler.format_error("Unknown Option", message, suggestion)
120
+
121
+ @staticmethod
122
+ def handle_missing_requirement(requirement_message: str) -> str:
123
+ message = requirement_message
124
+ suggestion = "Please provide all required parameters."
125
+ return ErrorHandler.format_error("Missing Requirement", message, suggestion)
126
+
127
+ @staticmethod
128
+ def handle_invalid_agent(error_message: str) -> str:
129
+ message = f"Failed to retrieve or validate the agent.\n Details: {error_message}"
130
+ suggestion = "Check your agent configuration and ensure the agent exists."
131
+ return ErrorHandler.format_error("Invalid Agent", message, suggestion)
132
+
133
+ @staticmethod
134
+ def handle_wrong_argument(error_message: str, usage: str) -> str:
135
+ Console.write_stderr(f"usage: {usage}")
136
+ message = error_message
137
+ suggestion = "Check the command syntax and try again."
138
+ return ErrorHandler.format_error("Invalid Argument", message, suggestion)
139
+
140
+ @staticmethod
141
+ def handle_keyboard_interrupt() -> str:
142
+ return "\n\nOperation cancelled by user."
143
+
144
+ @staticmethod
145
+ def handle_unexpected_error(exception: Exception) -> str:
146
+ logger.error(f"Unexpected error occurred: {exception}")
147
+ logger.error(traceback.format_exc())
148
+
149
+ message = "An unexpected error occurred. This may be a bug."
150
+ suggestion = f"Please report this issue to geai-sdk@globant.com with the following details:\n Error: {str(exception)}\n Run with geai-dbg for more details."
151
+ return ErrorHandler.format_error("Critical Error", message, suggestion, show_help=False)
pygeai/cli/geai.py CHANGED
@@ -1,37 +1,104 @@
1
1
  import sys
2
+ import logging
3
+ from typing import List, Optional
2
4
 
3
5
  from pygeai import logger
4
6
  from pygeai.cli.commands.base import base_commands, base_options
5
7
  from pygeai.cli.commands import ArgumentsEnum, Command
6
8
  from pygeai.cli.parsers import CommandParser
7
9
  from pygeai.cli.texts.help import CLI_USAGE
10
+ from pygeai.cli.error_handler import ErrorHandler, ExitCode
8
11
  from pygeai.core.base.session import get_session
9
- from pygeai.core.common.exceptions import UnknownArgumentError, MissingRequirementException, WrongArgumentError
10
-
11
-
12
- def main():
13
- driver = CLIDriver()
14
- return driver.main()
12
+ from pygeai.core.common.exceptions import UnknownArgumentError, MissingRequirementException, WrongArgumentError, \
13
+ InvalidAgentException
14
+ from pygeai.core.utils.console import Console
15
+
16
+
17
+ def setup_verbose_logging() -> None:
18
+ """
19
+ Configure verbose logging for the CLI.
20
+
21
+ Sets up a console handler with DEBUG level logging and a formatted output
22
+ that includes timestamp, logger name, level, and message.
23
+ """
24
+ if logger.handlers:
25
+ for handler in logger.handlers:
26
+ if not isinstance(handler, logging.NullHandler):
27
+ return
28
+
29
+ logger.setLevel(logging.DEBUG)
30
+ console_handler = logging.StreamHandler(sys.stderr)
31
+ console_handler.setLevel(logging.DEBUG)
32
+ formatter = logging.Formatter(
33
+ '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
34
+ datefmt='%Y-%m-%d %H:%M:%S'
35
+ )
36
+ console_handler.setFormatter(formatter)
37
+ logger.addHandler(console_handler)
38
+ logger.propagate = False
39
+ logger.debug("Verbose mode enabled")
40
+
41
+
42
+ def main() -> int:
43
+ """
44
+ Main entry point for the GEAI CLI application.
45
+
46
+ :return: int - Exit code indicating success or error.
47
+ """
48
+ try:
49
+ driver = CLIDriver()
50
+ return driver.main()
51
+ except MissingRequirementException as e:
52
+ error_msg = ErrorHandler.handle_missing_requirement(str(e))
53
+ Console.write_stderr(error_msg)
54
+ return ExitCode.MISSING_REQUIREMENT
15
55
 
16
56
 
17
57
  class CLIDriver:
18
-
19
- def __init__(self, session=None):
58
+ """
59
+ Main CLI driver for the GEAI command-line interface.
60
+
61
+ The CLIDriver orchestrates command parsing, execution, and error handling
62
+ for all GEAI CLI operations. It supports multi-profile session management
63
+ via the --alias flag and provides comprehensive error handling with
64
+ user-friendly messages.
65
+ """
66
+
67
+ def __init__(self, session=None, credentials_file=None) -> None:
20
68
  """
21
- Sets session to be used while running the command, either with a specified alias,
22
- environment variables or function parameters.
23
- Once the session is defined, it won't change during the curse of the execution.
69
+ Initialize the CLI driver with optional session and credentials file.
70
+
71
+ Sets up the session to be used while running commands, either with a
72
+ specified alias, environment variables, or function parameters.
73
+ Once the session is defined, it won't change during the execution.
74
+
75
+ :param session: Optional session object. If None, uses 'default' or
76
+ alias-specified session from command-line arguments.
77
+ :param credentials_file: Optional path to custom credentials file.
24
78
  """
79
+ from pygeai.core.common.config import get_settings
80
+
25
81
  arguments = sys.argv
82
+
83
+ if credentials_file or "--credentials" in arguments or "--creds" in arguments:
84
+ if not credentials_file:
85
+ credentials_file = self._get_credentials_file(arguments)
86
+ get_settings(credentials_file=credentials_file)
87
+ logger.debug(f"Using custom credentials file: {credentials_file}")
88
+
26
89
  if "-a" in arguments or "--alias" in arguments:
27
90
  alias = self._get_alias(arguments)
28
91
  session = get_session(alias)
29
92
 
30
- self.session = get_session() if session is None else session
93
+ self.session = get_session("default") if session is None else session
31
94
 
32
- def _get_alias(self, arguments: list):
95
+ def _get_alias(self, arguments: List[str]) -> str:
33
96
  """
34
- Retrieves and removes alias and alias flag from argument list
97
+ Retrieves and removes alias and alias flag from argument list.
98
+
99
+ :param arguments: List[str] - Command line arguments.
100
+ :return: str - The alias value.
101
+ :raises ValueError: If alias flag is present but no value provided.
35
102
  """
36
103
  alias_index = None
37
104
 
@@ -43,64 +110,136 @@ class CLIDriver:
43
110
  _ = arguments.pop(alias_index)
44
111
  alias = arguments.pop(alias_index)
45
112
  return alias
113
+
114
+ def _get_credentials_file(self, arguments: List[str]) -> str:
115
+ """
116
+ Retrieves and removes credentials file path and flag from argument list.
117
+
118
+ :param arguments: List[str] - Command line arguments.
119
+ :return: str - The credentials file path.
120
+ :raises ValueError: If credentials flag is present but no value provided.
121
+ """
122
+ creds_index = None
46
123
 
47
- def main(self, args=None):
124
+ if "--credentials" in arguments:
125
+ creds_index = arguments.index("--credentials")
126
+ elif "--creds" in arguments:
127
+ creds_index = arguments.index("--creds")
128
+
129
+ _ = arguments.pop(creds_index)
130
+ credentials_file = arguments.pop(creds_index)
131
+ return credentials_file
132
+
133
+ def main(self, args: Optional[List[str]] = None) -> int:
48
134
  """
49
- If not argument is received, it defaults to help (first command in base_command list).
135
+ Execute the CLI command based on provided arguments.
136
+
137
+ If no argument is received, it defaults to help (first command in base_command list).
50
138
  Otherwise, it parses the arguments received to identify the appropriate command and either
51
139
  execute it or parse it again to detect subcommands.
140
+
141
+ :param args: Optional[List[str]] - Command line arguments. If None, uses sys.argv.
142
+ :return: int - Exit code (0 for success, non-zero for errors).
52
143
  """
53
144
  try:
54
- logger.info(f"Running geai with: {sys.argv}")
55
- if len(sys.argv) > 1:
56
- arg = sys.argv[1] if args is None else args[1]
57
- arguments = sys.argv[2:] if args is None else args[2:]
58
-
145
+ argv = sys.argv if args is None else args
146
+
147
+ if "--verbose" in argv or "-v" in argv:
148
+ setup_verbose_logging()
149
+ argv_copy = [a for a in argv if a not in ("--verbose", "-v")]
150
+ if args is None:
151
+ sys.argv = argv_copy
152
+ else:
153
+ args = argv_copy
154
+ argv = argv_copy
155
+
156
+ logger.debug(f"Running geai with: {' '.join(a for a in argv)}")
157
+ logger.debug(f"Session: {self.session.alias if hasattr(self.session, 'alias') else 'default'}")
158
+
159
+ if len(argv) > 1:
160
+ arg = argv[1] if args is None else args[1]
161
+ arguments = argv[2:] if args is None else args[2:]
162
+
163
+ logger.debug(f"Identifying command for argument: {arg}")
59
164
  command = CommandParser(base_commands, base_options).identify_command(arg)
165
+ logger.debug(f"Command identified: {command.name}")
60
166
  else:
167
+ logger.debug("No arguments provided, defaulting to help command")
61
168
  command = base_commands[0]
62
169
  arguments = []
63
170
 
64
171
  self.process_command(command, arguments)
65
- except (UnknownArgumentError, WrongArgumentError) as e:
66
- sys.stderr.write(f"usage: {CLI_USAGE}")
67
- sys.stderr.write(str(e))
68
- sys.stderr.write("\n")
172
+ logger.debug(f"Command completed successfully")
173
+ return ExitCode.SUCCESS
174
+ except UnknownArgumentError as e:
175
+ if hasattr(e, 'available_commands') and e.available_commands:
176
+ error_msg = ErrorHandler.handle_unknown_command(e.arg, e.available_commands)
177
+ elif hasattr(e, 'available_options') and e.available_options:
178
+ error_msg = ErrorHandler.handle_unknown_option(e.arg, e.available_options)
179
+ else:
180
+ error_msg = ErrorHandler.format_error("Unknown Argument", str(e))
181
+
182
+ Console.write_stderr(error_msg)
183
+ return ExitCode.USER_INPUT_ERROR
184
+ except WrongArgumentError as e:
185
+ error_msg = ErrorHandler.handle_wrong_argument(str(e), CLI_USAGE)
186
+ Console.write_stderr(error_msg)
187
+ return ExitCode.USER_INPUT_ERROR
69
188
  except MissingRequirementException as e:
70
- sys.stderr.write(f"ERROR: Something is missing! {e}")
189
+ error_msg = ErrorHandler.handle_missing_requirement(str(e))
190
+ Console.write_stderr(error_msg)
191
+ return ExitCode.MISSING_REQUIREMENT
192
+ except InvalidAgentException as e:
193
+ error_msg = ErrorHandler.handle_invalid_agent(str(e))
194
+ Console.write_stderr(error_msg)
195
+ return ExitCode.SERVICE_ERROR
71
196
  except KeyboardInterrupt:
72
- sys.stdout.write("\n")
197
+ message = ErrorHandler.handle_keyboard_interrupt()
198
+ Console.write_stdout(message)
199
+ return ExitCode.KEYBOARD_INTERRUPT
73
200
  except Exception as e:
74
- sys.stderr.write(f"Unexpected error. Please report this bug to the developers. Error: {e}")
75
- return 255
201
+ error_msg = ErrorHandler.handle_unexpected_error(e)
202
+ Console.write_stderr(error_msg)
203
+ return ExitCode.UNEXPECTED_ERROR
76
204
 
77
205
  def process_command(self, command: Command, arguments: list[str]):
78
206
  """
79
207
  If the command has no action associated with it, it means it has subcommands, so it must be parsed again
80
208
  to identify it.
81
209
  """
210
+ logger.debug(f"Processing command: {command.name}, arguments: {arguments}")
211
+
82
212
  if command.action:
83
213
  if command.additional_args == ArgumentsEnum.NOT_AVAILABLE:
214
+ logger.debug(f"Executing command {command.name} without arguments")
84
215
  command.action()
85
216
  else:
217
+ logger.debug(f"Extracting options for command {command.name}")
86
218
  option_list = CommandParser(base_commands, command.options).extract_option_list(arguments)
219
+ logger.debug(f"Options extracted: {len(option_list)} items")
87
220
  command.action(option_list)
88
221
  elif command.subcommands:
89
222
  subcommand_arg = arguments[0] if len(arguments) > 0 else None
90
223
  subcommand_arguments = arguments[1:] if len(arguments) > 1 else []
91
-
224
+
225
+ logger.debug(f"Command has subcommands, identifying: {subcommand_arg}")
226
+
92
227
  available_commands = command.subcommands
93
228
  available_options = command.options
94
229
  parser = CommandParser(available_commands, available_options)
95
230
 
96
231
  if not subcommand_arg:
232
+ logger.debug(f"No subcommand specified, using default: {command.subcommands[0].name}")
97
233
  subcommand = command.subcommands[0]
98
234
  else:
99
235
  subcommand = parser.identify_command(subcommand_arg)
236
+ logger.debug(f"Subcommand identified: {subcommand.name}")
100
237
 
101
238
  if subcommand.additional_args == ArgumentsEnum.NOT_AVAILABLE:
239
+ logger.debug(f"Executing subcommand {subcommand.name} without arguments")
102
240
  subcommand.action()
103
241
  else:
242
+ logger.debug(f"Extracting options for subcommand {subcommand.name}")
104
243
  option_list = CommandParser(None, subcommand.options).extract_option_list(subcommand_arguments)
244
+ logger.debug(f"Options extracted: {len(option_list)} items")
105
245
  subcommand.action(option_list)
106
-
pygeai/cli/geai_proxy.py CHANGED
@@ -2,13 +2,45 @@
2
2
  import json
3
3
  import asyncio
4
4
  import sys
5
+ from typing import Final
5
6
  import argparse
6
7
  import uuid
7
8
  import yaml
8
9
  from pygeai import logger
9
10
  from pygeai.proxy.managers import ServerManager
10
11
  from pygeai.proxy.config import ProxySettingsManager
11
-
12
+ from pygeai.admin.clients import AdminClient
13
+ from pygeai.core.utils.console import Console, StreamWriter
14
+ class CustomProxyStream(StreamWriter):
15
+ """
16
+ Custom stream writer for proxy output with color support for TTY terminals.
17
+ """
18
+ IS_TTY: Final[bool] = sys.stderr.isatty()
19
+ RED: Final[str] = "\033[91m" if IS_TTY else ""
20
+ RESET: Final[str] = "\033[0m" if IS_TTY else ""
21
+
22
+ def write_stdout(self, message: str, end: str = "\n"):
23
+ """
24
+ Write message to stdout and log as info.
25
+ """
26
+ sys.stdout.write(f"{message}{end}")
27
+ logger.info(f"{message}{end}")
28
+
29
+ def write_stderr(self, message: str, end: str = "\n"):
30
+ """
31
+ Write message to stderr with red color and log as error.
32
+ """
33
+ sys.stderr.write(f"{self.RED}{message}{self.RESET}{end}")
34
+ logger.error(f"{message}{end}")
35
+
36
+ def write_exception(self, message: str, exception: Exception, end: str = "\n"):
37
+ """
38
+ Write exception message to stderr with red color and log as exception.
39
+ """
40
+ sys.stderr.write(f"{self.RED}{message}{self.RESET} {str(exception)}{end}")
41
+ logger.exception(f"{message}{end}", exception)
42
+
43
+ Console.set_writer(CustomProxyStream())
12
44
 
13
45
  def load_config(path: str) -> list:
14
46
  """
@@ -22,13 +54,22 @@ def load_config(path: str) -> list:
22
54
  try:
23
55
  with open(path, 'r', encoding='utf-8') as f:
24
56
  config = yaml.safe_load(f) if path.endswith(('.yaml', '.yml')) else json.load(f)
25
- if 'mcpServers' not in config:
26
- raise ValueError(f"Config file '{path}' must contain 'mcpServers' key")
27
-
28
57
  servers = []
29
- for name, server_cfg in config['mcpServers'].items():
30
- server_cfg['name'] = name
31
- servers.append(server_cfg)
58
+ if 'mcpServers' in config:
59
+ for name, server_cfg in config['mcpServers'].items():
60
+ server_cfg['name'] = name
61
+ server_cfg['type'] = 'mcp'
62
+ servers.append(server_cfg)
63
+
64
+ if 'a2aServers' in config:
65
+ for name, server_cfg in config['a2aServers'].items():
66
+ server_cfg['name'] = name
67
+ server_cfg['type'] = 'a2a'
68
+ servers.append(server_cfg)
69
+
70
+ if not 'a2aServers' in config and not 'mcpServers' in config:
71
+ Console.write_stderr("Error: MCP servers or A2A servers are required")
72
+
32
73
  return servers
33
74
  except FileNotFoundError as exc:
34
75
  raise FileNotFoundError(f"Configuration file '{path}' not found") from exc
@@ -58,12 +99,12 @@ def configure_proxy_settings(settings: ProxySettingsManager, args: argparse.Name
58
99
  #first_time = all(not x for x in [ current_id, current_name, current_description, current_api_key, current_base_url])
59
100
 
60
101
  if not only_missing or any(not x for x in [current_id, current_name, current_description, current_api_key, current_base_url]):
61
- sys.stdout.write("# Configuring GEAI proxy settings...\n")
102
+ Console.write_stdout("# Configuring GEAI proxy settings...")
62
103
 
63
104
  if not current_id:
64
105
  current_id = uuid.uuid4()
65
106
  settings.set_proxy_id(current_id, alias)
66
- sys.stdout.write(f"Generated new proxy ID: {current_id}\n")
107
+ Console.write_stdout(f"Generated new proxy ID: {current_id}")
67
108
 
68
109
  if not only_missing or not current_id:
69
110
  server_id = input(f"-> Insert proxy ID (UUID) (Current: {current_id}, Leave empty to keep): ")
@@ -71,7 +112,7 @@ def configure_proxy_settings(settings: ProxySettingsManager, args: argparse.Name
71
112
  try:
72
113
  settings.set_proxy_id(uuid.UUID(server_id), alias)
73
114
  except ValueError:
74
- sys.stderr.write("Error: Invalid UUID format\n")
115
+ Console.write_stdout("Error: Invalid UUID format")
75
116
  return
76
117
  if not only_missing or not current_api_key:
77
118
  if current_api_key:
@@ -122,7 +163,7 @@ def configure_proxy_settings(settings: ProxySettingsManager, args: argparse.Name
122
163
  try:
123
164
  settings.set_proxy_id(uuid.UUID(args.proxy_id), alias)
124
165
  except ValueError:
125
- sys.stderr.write("Error: Invalid UUID format for proxy ID\n")
166
+ Console.write_stderr("Error: Invalid UUID format for proxy ID")
126
167
  return
127
168
  elif not only_missing or not settings.get_proxy_id(alias):
128
169
  # Generate new UUID if no ID is provided
@@ -130,7 +171,7 @@ def configure_proxy_settings(settings: ProxySettingsManager, args: argparse.Name
130
171
  if not current_id:
131
172
  current_id = uuid.uuid4()
132
173
  settings.set_proxy_id(current_id, alias)
133
- sys.stdout.write(f"Generated new proxy ID: {current_id}\n")
174
+ Console.write_stdout(f"Generated new proxy ID: {current_id}")
134
175
 
135
176
  if args.proxy_name:
136
177
  settings.set_proxy_name(args.proxy_name, alias)
@@ -151,7 +192,7 @@ def configure_proxy_settings(settings: ProxySettingsManager, args: argparse.Name
151
192
  #elif not only_missing or not settings.get_proxy_affinity(alias):
152
193
  # pass # Affinity is not requested if not in args and only_missing is True
153
194
 
154
- sys.stdout.write(f"Proxy settings for alias '{alias}' saved successfully!\n")
195
+ Console.write_stdout(f"Proxy settings for alias '{alias}' saved successfully!")
155
196
 
156
197
 
157
198
  async def main():
@@ -160,6 +201,7 @@ async def main():
160
201
 
161
202
  :return: int - Exit code (0 for success, 1 for error)
162
203
  """
204
+
163
205
  logger.info("Starting GEAI proxy CLI")
164
206
  parser = argparse.ArgumentParser(
165
207
  description="Proxy CLI between GEAI and MCP servers",
@@ -183,7 +225,7 @@ async def main():
183
225
  else:
184
226
  settings.set_current_alias(args.alias)
185
227
 
186
- sys.stdout.write(f"Using alias: {args.alias}\n")
228
+ Console.write_stdout(f"Using alias: {args.alias}")
187
229
 
188
230
  only_configure = args.configure
189
231
  while True:
@@ -196,35 +238,54 @@ async def main():
196
238
  ]):
197
239
 
198
240
  if args.alias not in settings.config:
199
- sys.stdout.write(f"Created new alias '{args.alias}' in the configuration file.\n\n")
241
+ Console.write_stdout(f"Created new alias '{args.alias}' in the configuration file.","\n\n")
200
242
  settings.config.add_section(args.alias)
201
243
  else:
202
244
  if not args.configure:
203
- sys.stdout.write("\nProxy configuration required. Please complete all required fields.\n\n")
245
+ Console.write_stdout("\nProxy configuration required. Please complete all required fields.","\n\n")
204
246
  else:
205
- sys.stdout.write("\nProxy configuration.\n\n")
247
+ Console.write_stdout("\nProxy configuration.","\n\n")
206
248
 
207
249
  if (key := settings.get_api_key(args.alias)):
208
- sys.stdout.write(f"API_KEY: {key}\n")
250
+ Console.write_stdout(f"API_KEY: {key}")
209
251
  if (url := settings.get_base_url(args.alias)):
210
- sys.stdout.write(f"BASE_URL: {url}\n")
252
+ Console.write_stdout(f"BASE_URL: {url}")
211
253
 
212
- sys.stdout.write("\n")
254
+ Console.write_stdout("")
213
255
  configure_proxy_settings(settings, args, only_missing=not args.configure)
214
256
  args.configure = False
215
257
  else:
216
258
  break
217
259
 
218
260
  if only_configure:
219
- sys.stdout.write("Proxy configuration completed successfully!\n")
261
+ Console.write_stdout("Proxy configuration completed successfully!")
220
262
  return 0
221
263
 
222
264
  if not args.config:
223
- sys.stderr.write("Error: MCP servers Configuration file path is required\n")
265
+ Console.write_stderr("Error: MCP servers Configuration file path is required")
224
266
  return 1
225
267
 
226
268
  servers_cfg = load_config(args.config)
227
269
  server_manager = ServerManager(servers_cfg, settings)
270
+
271
+ try:
272
+ Console.write_stdout(f"Contacting Globant Enteprise AI at {settings.get_base_url(args.alias)}...","")
273
+ admin_client = AdminClient(api_key=settings.get_api_key(args.alias), base_url=settings.get_base_url(args.alias))
274
+ result = admin_client.validate_api_token()
275
+ if result.get('errors'):
276
+ Console.write_stdout("Invalid API token")
277
+ for error in result.get('errors'):
278
+ Console.write_stderr(f"{error.get('description')}")
279
+
280
+ return 1
281
+ else:
282
+ Console.write_stdout(f" Done!")
283
+ Console.write_stdout(f"Organization: {result.get('organizationName')}")
284
+ Console.write_stdout(f"Project: {result.get('projectName')}")
285
+ except Exception as e:
286
+ Console.write_exception("Error:", e, "\n")
287
+ return 1
288
+
228
289
  await server_manager.start()
229
290
 
230
291
  return 0
@@ -239,10 +300,10 @@ def cli_entry() -> int:
239
300
  try:
240
301
  return asyncio.run(main())
241
302
  except KeyboardInterrupt:
242
- sys.stdout.write("\nExiting...\n")
303
+ Console.write_stdout("\nExiting...")
243
304
  return 0
244
305
  except (RuntimeError, ConnectionError, ValueError) as e:
245
- sys.stderr.write(f"Error: {e}\n")
306
+ Console.write_exception("Error:", e, "\n")
246
307
  return 1
247
308
 
248
309
 
@@ -251,7 +312,7 @@ if __name__ == "__main__":
251
312
  import os
252
313
  script_dir = os.path.dirname(os.path.abspath(__file__))
253
314
  config_path = os.path.join(os.path.dirname(script_dir), "proxy", "sample-mcp-config.json")
254
- sys.stdout.write(f"Config file path: {config_path}\n")
315
+ Console.write_stdout(f"Config file path: {config_path}")
255
316
 
256
317
  sys.argv.extend([config_path])
257
318
  sys.exit(cli_entry())