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

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

Potentially problematic release.


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

Files changed (648) hide show
  1. pygeai/__init__.py +9 -1
  2. pygeai/_docs/Makefile +20 -0
  3. pygeai/_docs/make.bat +35 -0
  4. pygeai/_docs/source/conf.py +117 -0
  5. pygeai/_docs/source/content/ai_lab/cli.rst +747 -0
  6. pygeai/_docs/source/content/ai_lab/models.rst +1734 -0
  7. pygeai/_docs/source/content/ai_lab/runner.rst +253 -0
  8. pygeai/_docs/source/content/ai_lab/spec.rst +431 -0
  9. pygeai/_docs/source/content/ai_lab/usage.rst +1011 -0
  10. pygeai/_docs/source/content/ai_lab.rst +102 -0
  11. pygeai/_docs/source/content/analytics.rst +598 -0
  12. pygeai/_docs/source/content/api_reference/admin.rst +161 -0
  13. pygeai/_docs/source/content/api_reference/assistant.rst +326 -0
  14. pygeai/_docs/source/content/api_reference/auth.rst +379 -0
  15. pygeai/_docs/source/content/api_reference/chat.rst +754 -0
  16. pygeai/_docs/source/content/api_reference/embeddings.rst +154 -0
  17. pygeai/_docs/source/content/api_reference/evaluation.rst +590 -0
  18. pygeai/_docs/source/content/api_reference/feedback.rst +237 -0
  19. pygeai/_docs/source/content/api_reference/files.rst +592 -0
  20. pygeai/_docs/source/content/api_reference/gam.rst +401 -0
  21. pygeai/_docs/source/content/api_reference/health.rst +58 -0
  22. pygeai/_docs/source/content/api_reference/project.rst +738 -0
  23. pygeai/_docs/source/content/api_reference/proxy.rst +318 -0
  24. pygeai/_docs/source/content/api_reference/rag.rst +710 -0
  25. pygeai/_docs/source/content/api_reference/rerank.rst +94 -0
  26. pygeai/_docs/source/content/api_reference/secrets.rst +495 -0
  27. pygeai/_docs/source/content/api_reference/usage_limits.rst +390 -0
  28. pygeai/_docs/source/content/api_reference.rst +58 -0
  29. pygeai/_docs/source/content/authentication.rst +295 -0
  30. pygeai/_docs/source/content/chat_gui.rst +121 -0
  31. pygeai/_docs/source/content/cli.rst +203 -0
  32. pygeai/_docs/source/content/debugger.rst +651 -0
  33. pygeai/_docs/source/content/intro.rst +67 -0
  34. pygeai/_docs/source/content/migration.rst +929 -0
  35. pygeai/_docs/source/content/modules.rst +7 -0
  36. pygeai/_docs/source/content/quickstart.rst +143 -0
  37. pygeai/_docs/source/content/samples.rst +394 -0
  38. pygeai/_docs/source/index.rst +75 -0
  39. pygeai/_docs/source/modules.rst +7 -0
  40. pygeai/_docs/source/pygeai.admin.rst +29 -0
  41. pygeai/_docs/source/pygeai.analytics.rst +53 -0
  42. pygeai/_docs/source/pygeai.assistant.data.rst +21 -0
  43. pygeai/_docs/source/pygeai.assistant.data_analyst.rst +29 -0
  44. pygeai/_docs/source/pygeai.assistant.rag.rst +53 -0
  45. pygeai/_docs/source/pygeai.assistant.rst +55 -0
  46. pygeai/_docs/source/pygeai.auth.rst +29 -0
  47. pygeai/_docs/source/pygeai.chat.rst +69 -0
  48. pygeai/_docs/source/pygeai.cli.commands.flows.rst +10 -0
  49. pygeai/_docs/source/pygeai.cli.commands.lab.rst +53 -0
  50. pygeai/_docs/source/pygeai.cli.commands.rst +222 -0
  51. pygeai/_docs/source/pygeai.cli.rst +62 -0
  52. pygeai/_docs/source/pygeai.cli.texts.rst +21 -0
  53. pygeai/_docs/source/pygeai.core.base.rst +53 -0
  54. pygeai/_docs/source/pygeai.core.common.rst +37 -0
  55. pygeai/_docs/source/pygeai.core.embeddings.rst +61 -0
  56. pygeai/_docs/source/pygeai.core.feedback.rst +37 -0
  57. pygeai/_docs/source/pygeai.core.files.rst +61 -0
  58. pygeai/_docs/source/pygeai.core.llm.rst +29 -0
  59. pygeai/_docs/source/pygeai.core.plugins.rst +37 -0
  60. pygeai/_docs/source/pygeai.core.rerank.rst +53 -0
  61. pygeai/_docs/source/pygeai.core.rst +63 -0
  62. pygeai/_docs/source/pygeai.core.secrets.rst +29 -0
  63. pygeai/_docs/source/pygeai.core.services.llm.rst +29 -0
  64. pygeai/_docs/source/pygeai.core.services.rst +37 -0
  65. pygeai/_docs/source/pygeai.core.utils.rst +37 -0
  66. pygeai/_docs/source/pygeai.dbg.rst +21 -0
  67. pygeai/_docs/source/pygeai.evaluation.dataset.rst +29 -0
  68. pygeai/_docs/source/pygeai.evaluation.plan.rst +29 -0
  69. pygeai/_docs/source/pygeai.evaluation.result.rst +29 -0
  70. pygeai/_docs/source/pygeai.evaluation.rst +31 -0
  71. pygeai/_docs/source/pygeai.flows.rst +29 -0
  72. pygeai/_docs/source/pygeai.gam.rst +29 -0
  73. pygeai/_docs/source/pygeai.health.rst +29 -0
  74. pygeai/_docs/source/pygeai.lab.agents.rst +37 -0
  75. pygeai/_docs/source/pygeai.lab.processes.rst +37 -0
  76. pygeai/_docs/source/pygeai.lab.rst +65 -0
  77. pygeai/_docs/source/pygeai.lab.spec.rst +29 -0
  78. pygeai/_docs/source/pygeai.lab.strategies.rst +37 -0
  79. pygeai/_docs/source/pygeai.lab.tools.rst +37 -0
  80. pygeai/_docs/source/pygeai.man.man1.rst +10 -0
  81. pygeai/_docs/source/pygeai.man.rst +18 -0
  82. pygeai/_docs/source/pygeai.migration.rst +29 -0
  83. pygeai/_docs/source/pygeai.organization.limits.rst +45 -0
  84. pygeai/_docs/source/pygeai.organization.rst +61 -0
  85. pygeai/_docs/source/pygeai.proxy.rst +53 -0
  86. pygeai/_docs/source/pygeai.rst +35 -0
  87. pygeai/_docs/source/pygeai.tests.admin.rst +21 -0
  88. pygeai/_docs/source/pygeai.tests.analytics.rst +45 -0
  89. pygeai/_docs/source/pygeai.tests.assistants.rag.rst +37 -0
  90. pygeai/_docs/source/pygeai.tests.assistants.rst +45 -0
  91. pygeai/_docs/source/pygeai.tests.auth.rst +29 -0
  92. pygeai/_docs/source/pygeai.tests.chat.rst +45 -0
  93. pygeai/_docs/source/pygeai.tests.cli.commands.lab.rst +37 -0
  94. pygeai/_docs/source/pygeai.tests.cli.commands.rst +165 -0
  95. pygeai/_docs/source/pygeai.tests.cli.docker.rst +10 -0
  96. pygeai/_docs/source/pygeai.tests.cli.rst +46 -0
  97. pygeai/_docs/source/pygeai.tests.core.base.data.rst +29 -0
  98. pygeai/_docs/source/pygeai.tests.core.base.rst +45 -0
  99. pygeai/_docs/source/pygeai.tests.core.common.data.rst +10 -0
  100. pygeai/_docs/source/pygeai.tests.core.common.rst +37 -0
  101. pygeai/_docs/source/pygeai.tests.core.embeddings.rst +37 -0
  102. pygeai/_docs/source/pygeai.tests.core.feedback.rst +21 -0
  103. pygeai/_docs/source/pygeai.tests.core.files.rst +53 -0
  104. pygeai/_docs/source/pygeai.tests.core.llm.rst +21 -0
  105. pygeai/_docs/source/pygeai.tests.core.plugins.rst +21 -0
  106. pygeai/_docs/source/pygeai.tests.core.rerank.rst +37 -0
  107. pygeai/_docs/source/pygeai.tests.core.rst +39 -0
  108. pygeai/_docs/source/pygeai.tests.core.secrets.rst +21 -0
  109. pygeai/_docs/source/pygeai.tests.core.services.rst +21 -0
  110. pygeai/_docs/source/pygeai.tests.core.utils.rst +21 -0
  111. pygeai/_docs/source/pygeai.tests.dbg.rst +21 -0
  112. pygeai/_docs/source/pygeai.tests.evaluation.dataset.rst +21 -0
  113. pygeai/_docs/source/pygeai.tests.evaluation.plan.rst +21 -0
  114. pygeai/_docs/source/pygeai.tests.evaluation.result.rst +21 -0
  115. pygeai/_docs/source/pygeai.tests.evaluation.rst +20 -0
  116. pygeai/_docs/source/pygeai.tests.gam.rst +21 -0
  117. pygeai/_docs/source/pygeai.tests.health.rst +21 -0
  118. pygeai/_docs/source/pygeai.tests.integration.assistants.rag.rst +21 -0
  119. pygeai/_docs/source/pygeai.tests.integration.assistants.rst +18 -0
  120. pygeai/_docs/source/pygeai.tests.integration.chat.rst +21 -0
  121. pygeai/_docs/source/pygeai.tests.integration.lab.agents.rst +69 -0
  122. pygeai/_docs/source/pygeai.tests.integration.lab.processes.rst +77 -0
  123. pygeai/_docs/source/pygeai.tests.integration.lab.reasoning_strategies.rst +37 -0
  124. pygeai/_docs/source/pygeai.tests.integration.lab.rst +21 -0
  125. pygeai/_docs/source/pygeai.tests.integration.lab.tools.rst +77 -0
  126. pygeai/_docs/source/pygeai.tests.integration.rst +20 -0
  127. pygeai/_docs/source/pygeai.tests.lab.agents.rst +29 -0
  128. pygeai/_docs/source/pygeai.tests.lab.processes.rst +29 -0
  129. pygeai/_docs/source/pygeai.tests.lab.rst +49 -0
  130. pygeai/_docs/source/pygeai.tests.lab.spec.rst +29 -0
  131. pygeai/_docs/source/pygeai.tests.lab.strategies.rst +29 -0
  132. pygeai/_docs/source/pygeai.tests.lab.tools.rst +29 -0
  133. pygeai/_docs/source/pygeai.tests.migration.rst +29 -0
  134. pygeai/_docs/source/pygeai.tests.organization.limits.rst +29 -0
  135. pygeai/_docs/source/pygeai.tests.organization.rst +53 -0
  136. pygeai/_docs/source/pygeai.tests.proxy.rst +61 -0
  137. pygeai/_docs/source/pygeai.tests.rst +33 -0
  138. pygeai/admin/clients.py +14 -11
  139. pygeai/admin/endpoints.py +2 -2
  140. pygeai/analytics/clients.py +505 -0
  141. pygeai/analytics/endpoints.py +35 -0
  142. pygeai/analytics/managers.py +606 -0
  143. pygeai/analytics/mappers.py +207 -0
  144. pygeai/analytics/responses.py +240 -0
  145. pygeai/assistant/clients.py +18 -45
  146. pygeai/assistant/data/clients.py +1 -0
  147. pygeai/assistant/data_analyst/clients.py +8 -12
  148. pygeai/assistant/managers.py +195 -157
  149. pygeai/assistant/mappers.py +4 -2
  150. pygeai/assistant/rag/clients.py +27 -67
  151. pygeai/assistant/rag/mappers.py +12 -6
  152. pygeai/assistant/rag/models.py +301 -159
  153. pygeai/auth/__init__.py +0 -0
  154. pygeai/auth/clients.py +129 -0
  155. pygeai/auth/endpoints.py +6 -0
  156. pygeai/chat/clients.py +308 -37
  157. pygeai/chat/endpoints.py +3 -0
  158. pygeai/chat/iris.py +2 -8
  159. pygeai/chat/managers.py +9 -6
  160. pygeai/chat/session.py +38 -0
  161. pygeai/chat/settings.py +6 -0
  162. pygeai/chat/ui.py +678 -0
  163. pygeai/cli/__init__.py +0 -1
  164. pygeai/cli/commands/admin.py +7 -10
  165. pygeai/cli/commands/analytics.py +533 -0
  166. pygeai/cli/commands/assistant.py +9 -9
  167. pygeai/cli/commands/auth.py +299 -0
  168. pygeai/cli/commands/base.py +71 -9
  169. pygeai/cli/commands/chat.py +676 -19
  170. pygeai/cli/commands/common.py +28 -24
  171. pygeai/cli/commands/configuration.py +66 -13
  172. pygeai/cli/commands/docs.py +105 -0
  173. pygeai/cli/commands/embeddings.py +58 -11
  174. pygeai/cli/commands/evaluation.py +38 -38
  175. pygeai/cli/commands/feedback.py +3 -4
  176. pygeai/cli/commands/files.py +7 -8
  177. pygeai/cli/commands/gam.py +85 -10
  178. pygeai/cli/commands/lab/ai_lab.py +340 -484
  179. pygeai/cli/commands/lab/options.py +8 -0
  180. pygeai/cli/commands/lab/spec.py +273 -0
  181. pygeai/cli/commands/lab/utils.py +13 -0
  182. pygeai/cli/commands/llm.py +6 -7
  183. pygeai/cli/commands/migrate.py +1064 -436
  184. pygeai/cli/commands/organization.py +516 -11
  185. pygeai/cli/commands/rag.py +13 -14
  186. pygeai/cli/commands/rerank.py +3 -5
  187. pygeai/cli/commands/secrets.py +8 -9
  188. pygeai/cli/commands/usage_limits.py +18 -20
  189. pygeai/cli/commands/validators.py +144 -1
  190. pygeai/cli/commands/version.py +4 -5
  191. pygeai/cli/error_handler.py +151 -0
  192. pygeai/cli/geai.py +170 -31
  193. pygeai/cli/geai_proxy.py +86 -25
  194. pygeai/cli/install_man.py +93 -22
  195. pygeai/cli/parsers.py +75 -25
  196. pygeai/cli/texts/help.py +265 -28
  197. pygeai/core/base/clients.py +53 -12
  198. pygeai/core/base/mappers.py +11 -2
  199. pygeai/core/base/session.py +95 -11
  200. pygeai/core/common/config.py +78 -14
  201. pygeai/core/common/exceptions.py +96 -6
  202. pygeai/core/embeddings/__init__.py +19 -0
  203. pygeai/core/embeddings/clients.py +23 -5
  204. pygeai/core/embeddings/managers.py +9 -4
  205. pygeai/core/embeddings/mappers.py +16 -2
  206. pygeai/core/embeddings/responses.py +9 -2
  207. pygeai/core/feedback/clients.py +8 -3
  208. pygeai/core/files/clients.py +23 -24
  209. pygeai/core/files/managers.py +121 -30
  210. pygeai/core/files/responses.py +4 -3
  211. pygeai/core/handlers.py +10 -1
  212. pygeai/core/llm/clients.py +22 -29
  213. pygeai/core/models.py +127 -11
  214. pygeai/core/plugins/clients.py +6 -6
  215. pygeai/core/rerank/clients.py +9 -3
  216. pygeai/core/rerank/managers.py +22 -5
  217. pygeai/core/secrets/clients.py +16 -37
  218. pygeai/core/services/response.py +18 -0
  219. pygeai/core/services/rest.py +159 -49
  220. pygeai/core/utils/__init__.py +0 -0
  221. pygeai/core/utils/console.py +83 -0
  222. pygeai/core/utils/parsers.py +32 -0
  223. pygeai/core/utils/validators.py +10 -0
  224. pygeai/dbg/__init__.py +3 -0
  225. pygeai/dbg/debugger.py +854 -14
  226. pygeai/evaluation/clients.py +7 -4
  227. pygeai/evaluation/dataset/clients.py +46 -44
  228. pygeai/evaluation/plan/clients.py +28 -26
  229. pygeai/evaluation/result/clients.py +38 -5
  230. pygeai/gam/clients.py +50 -28
  231. pygeai/gam/endpoints.py +2 -1
  232. pygeai/health/__init__.py +0 -0
  233. pygeai/health/clients.py +24 -0
  234. pygeai/health/endpoints.py +1 -0
  235. pygeai/lab/__init__.py +0 -90
  236. pygeai/lab/agents/clients.py +203 -162
  237. pygeai/lab/agents/endpoints.py +4 -0
  238. pygeai/lab/agents/mappers.py +57 -7
  239. pygeai/lab/clients.py +24 -0
  240. pygeai/lab/constants.py +3 -0
  241. pygeai/lab/managers.py +571 -541
  242. pygeai/lab/models.py +108 -19
  243. pygeai/lab/processes/clients.py +332 -340
  244. pygeai/lab/processes/mappers.py +3 -3
  245. pygeai/lab/runners.py +90 -0
  246. pygeai/lab/spec/__init__.py +0 -0
  247. pygeai/lab/spec/loader.py +24 -0
  248. pygeai/lab/spec/parsers.py +39 -0
  249. pygeai/lab/strategies/clients.py +67 -63
  250. pygeai/lab/strategies/mappers.py +1 -1
  251. pygeai/lab/tools/clients.py +85 -118
  252. pygeai/lab/tools/endpoints.py +4 -0
  253. pygeai/lab/tools/mappers.py +5 -5
  254. pygeai/man/man1/geai-proxy.1 +116 -0
  255. pygeai/man/man1/geai.1 +2580 -66
  256. pygeai/migration/__init__.py +33 -0
  257. pygeai/migration/strategies.py +468 -146
  258. pygeai/migration/tools.py +170 -3
  259. pygeai/organization/clients.py +245 -50
  260. pygeai/organization/endpoints.py +17 -8
  261. pygeai/organization/limits/clients.py +34 -32
  262. pygeai/organization/limits/managers.py +108 -49
  263. pygeai/organization/managers.py +347 -53
  264. pygeai/organization/mappers.py +102 -2
  265. pygeai/organization/responses.py +58 -1
  266. pygeai/proxy/clients.py +6 -3
  267. pygeai/proxy/config.py +14 -1
  268. pygeai/proxy/managers.py +61 -33
  269. pygeai/proxy/servers.py +196 -51
  270. pygeai/proxy/tool.py +33 -16
  271. pygeai/tests/admin/__init__.py +0 -0
  272. pygeai/tests/admin/test_clients.py +148 -0
  273. pygeai/tests/analytics/__init__.py +0 -0
  274. pygeai/tests/analytics/test_clients.py +86 -0
  275. pygeai/tests/analytics/test_managers.py +94 -0
  276. pygeai/tests/analytics/test_mappers.py +84 -0
  277. pygeai/tests/analytics/test_responses.py +73 -0
  278. pygeai/tests/assistants/rag/test_clients.py +346 -0
  279. pygeai/tests/assistants/rag/test_models.py +292 -0
  280. pygeai/tests/assistants/test_clients.py +176 -82
  281. pygeai/tests/assistants/test_managers.py +191 -57
  282. pygeai/tests/auth/__init__.py +0 -0
  283. pygeai/tests/auth/test_clients.py +289 -0
  284. pygeai/tests/auth/test_oauth.py +172 -0
  285. pygeai/tests/auth/test_session_logging.py +150 -0
  286. pygeai/tests/chat/__init__.py +0 -0
  287. pygeai/tests/chat/test_clients.py +393 -0
  288. pygeai/tests/chat/test_iris.py +38 -0
  289. pygeai/tests/chat/test_session.py +62 -0
  290. pygeai/tests/chat/test_ui.py +224 -0
  291. pygeai/tests/cli/commands/__init__.py +0 -0
  292. pygeai/tests/cli/commands/lab/__init__.py +0 -0
  293. pygeai/tests/cli/commands/lab/test_ai_lab.py +786 -0
  294. pygeai/tests/cli/commands/lab/test_common.py +208 -0
  295. pygeai/tests/cli/commands/lab/test_spec.py +246 -0
  296. pygeai/tests/cli/commands/test_assistant.py +202 -0
  297. pygeai/tests/cli/commands/test_chat.py +130 -0
  298. pygeai/tests/cli/commands/test_common.py +350 -0
  299. pygeai/tests/cli/commands/test_embeddings.py +132 -0
  300. pygeai/tests/cli/commands/test_evaluation.py +656 -0
  301. pygeai/tests/cli/commands/test_feedback.py +65 -0
  302. pygeai/tests/cli/commands/test_files.py +161 -0
  303. pygeai/tests/cli/commands/test_gam.py +201 -0
  304. pygeai/tests/cli/commands/test_llm.py +114 -0
  305. pygeai/tests/cli/commands/test_migrate.py +176 -0
  306. pygeai/tests/cli/commands/test_organization.py +276 -0
  307. pygeai/tests/cli/commands/test_rag.py +266 -0
  308. pygeai/tests/cli/commands/test_rerank.py +110 -0
  309. pygeai/tests/cli/commands/test_secrets.py +171 -0
  310. pygeai/tests/cli/commands/test_show_help.py +41 -0
  311. pygeai/tests/cli/commands/test_usage_limits.py +412 -0
  312. pygeai/tests/cli/commands/test_validators.py +160 -0
  313. pygeai/tests/cli/commands/test_version.py +81 -0
  314. pygeai/tests/cli/docker/__init__.py +0 -0
  315. pygeai/tests/cli/test_credentials_flag.py +316 -0
  316. pygeai/tests/cli/test_error_handler.py +225 -0
  317. pygeai/tests/cli/test_geai_driver.py +154 -0
  318. pygeai/tests/cli/test_parsers.py +5 -5
  319. pygeai/tests/core/base/data/models.py +7 -0
  320. pygeai/tests/core/base/test_mappers.py +43 -11
  321. pygeai/tests/core/base/test_models.py +3 -1
  322. pygeai/tests/core/base/test_responses.py +53 -0
  323. pygeai/tests/core/common/__init__.py +0 -0
  324. pygeai/tests/core/common/data/__init__.py +0 -0
  325. pygeai/tests/core/common/test_config.py +186 -0
  326. pygeai/tests/core/common/test_decorators.py +69 -0
  327. pygeai/tests/core/embeddings/__init__.py +0 -0
  328. pygeai/tests/core/embeddings/test_clients.py +225 -0
  329. pygeai/tests/core/embeddings/test_managers.py +171 -0
  330. pygeai/tests/core/embeddings/test_mappers.py +142 -0
  331. pygeai/tests/core/feedback/__init__.py +0 -0
  332. pygeai/tests/core/feedback/test_clients.py +64 -0
  333. pygeai/tests/core/files/test_clients.py +128 -0
  334. pygeai/tests/core/files/test_managers.py +124 -78
  335. pygeai/tests/core/files/test_mappers.py +137 -0
  336. pygeai/tests/core/files/test_models.py +103 -0
  337. pygeai/tests/core/files/test_responses.py +122 -0
  338. pygeai/tests/core/llm/__init__.py +0 -0
  339. pygeai/tests/core/llm/test_clients.py +142 -0
  340. pygeai/tests/core/plugins/__init__.py +0 -0
  341. pygeai/tests/core/plugins/test_clients.py +66 -0
  342. pygeai/tests/core/rerank/test_clients.py +76 -0
  343. pygeai/tests/core/rerank/test_managers.py +61 -39
  344. pygeai/tests/core/secrets/__init__.py +0 -0
  345. pygeai/tests/core/secrets/test_clients.py +264 -0
  346. pygeai/tests/core/services/__init__.py +0 -0
  347. pygeai/tests/core/services/test_rest.py +273 -0
  348. pygeai/tests/core/test_handlers.py +66 -0
  349. pygeai/tests/core/utils/__init__.py +0 -0
  350. pygeai/tests/core/utils/test_console.py +80 -0
  351. pygeai/tests/dbg/__init__.py +0 -0
  352. pygeai/tests/dbg/test_debugger.py +591 -0
  353. pygeai/tests/evaluation/__init__.py +0 -0
  354. pygeai/tests/evaluation/dataset/__init__.py +0 -0
  355. pygeai/tests/evaluation/dataset/test_clients.py +265 -0
  356. pygeai/tests/evaluation/plan/__init__.py +0 -0
  357. pygeai/tests/evaluation/plan/test_clients.py +195 -0
  358. pygeai/tests/evaluation/result/__init__.py +0 -0
  359. pygeai/tests/evaluation/result/test_clients.py +66 -0
  360. pygeai/tests/gam/__init__.py +0 -0
  361. pygeai/tests/gam/test_clients.py +195 -0
  362. pygeai/tests/health/__init__.py +0 -0
  363. pygeai/tests/health/test_clients.py +41 -0
  364. pygeai/tests/integration/__init__.py +0 -0
  365. pygeai/tests/integration/assistants/__init__.py +0 -0
  366. pygeai/tests/integration/assistants/rag/__init__.py +0 -0
  367. pygeai/tests/integration/assistants/rag/test_create_rag.py +91 -0
  368. pygeai/tests/integration/chat/__init__.py +0 -0
  369. pygeai/tests/integration/chat/test_generate_image.py +158 -0
  370. pygeai/tests/integration/lab/__init__.py +0 -0
  371. pygeai/tests/integration/lab/agents/__init__.py +0 -0
  372. pygeai/tests/integration/lab/agents/test_agents_list.py +106 -0
  373. pygeai/tests/integration/lab/agents/test_create_agent.py +319 -0
  374. pygeai/tests/integration/lab/agents/test_create_sharing_link.py +70 -0
  375. pygeai/tests/integration/lab/agents/test_delete_agent.py +75 -0
  376. pygeai/tests/integration/lab/agents/test_get_agent.py +94 -0
  377. pygeai/tests/integration/lab/agents/test_publish_agent_revision.py +127 -0
  378. pygeai/tests/integration/lab/agents/test_update_agent.py +250 -0
  379. pygeai/tests/integration/lab/processes/__init__.py +0 -0
  380. pygeai/tests/integration/lab/processes/test_create_process.py +345 -0
  381. pygeai/tests/integration/lab/processes/test_create_task.py +211 -0
  382. pygeai/tests/integration/lab/processes/test_delete_process.py +111 -0
  383. pygeai/tests/integration/lab/processes/test_get_process.py +201 -0
  384. pygeai/tests/integration/lab/processes/test_list_process_instances.py +91 -0
  385. pygeai/tests/integration/lab/processes/test_list_processes.py +138 -0
  386. pygeai/tests/integration/lab/processes/test_publish_process_revision.py +232 -0
  387. pygeai/tests/integration/lab/processes/test_update_process.py +289 -0
  388. pygeai/tests/integration/lab/reasoning_strategies/__init__.py +0 -0
  389. pygeai/tests/integration/lab/reasoning_strategies/test_get_reasoning_strategy.py +70 -0
  390. pygeai/tests/integration/lab/reasoning_strategies/test_list_reasoning_strategies.py +93 -0
  391. pygeai/tests/integration/lab/reasoning_strategies/test_update_reasoning_strategy.py +149 -0
  392. pygeai/tests/integration/lab/tools/__init__.py +0 -0
  393. pygeai/tests/integration/lab/tools/test_create_tool.py +288 -0
  394. pygeai/tests/integration/lab/tools/test_delete_tool.py +87 -0
  395. pygeai/tests/integration/lab/tools/test_get_parameter.py +98 -0
  396. pygeai/tests/integration/lab/tools/test_get_tool.py +91 -0
  397. pygeai/tests/integration/lab/tools/test_list_tools.py +106 -0
  398. pygeai/tests/integration/lab/tools/test_publish_tool_revision.py +119 -0
  399. pygeai/tests/integration/lab/tools/test_set_parameter.py +114 -0
  400. pygeai/tests/integration/lab/tools/test_update_tool.py +267 -0
  401. pygeai/tests/lab/agents/__init__.py +0 -0
  402. pygeai/tests/lab/agents/test_clients.py +481 -0
  403. pygeai/tests/lab/agents/test_mappers.py +440 -0
  404. pygeai/tests/lab/processes/__init__.py +0 -0
  405. pygeai/tests/lab/processes/test_clients.py +1416 -0
  406. pygeai/tests/lab/processes/test_mappers.py +1092 -0
  407. pygeai/tests/lab/spec/__init__.py +0 -0
  408. pygeai/tests/lab/spec/test_loader.py +59 -0
  409. pygeai/tests/lab/spec/test_parsers.py +182 -0
  410. pygeai/tests/lab/strategies/__init__.py +0 -0
  411. pygeai/tests/lab/strategies/test_clients.py +241 -0
  412. pygeai/tests/lab/strategies/test_mappers.py +132 -0
  413. pygeai/tests/lab/test_managers.py +553 -0
  414. pygeai/tests/lab/test_models.py +500 -3
  415. pygeai/tests/lab/tools/__init__.py +0 -0
  416. pygeai/tests/lab/tools/test_clients.py +521 -0
  417. pygeai/tests/lab/tools/test_mappers.py +198 -0
  418. pygeai/tests/migration/__init__.py +0 -0
  419. pygeai/tests/migration/test_strategies.py +405 -0
  420. pygeai/tests/migration/test_tools.py +159 -0
  421. pygeai/tests/organization/limits/test_clients.py +567 -0
  422. pygeai/tests/organization/limits/test_managers.py +298 -56
  423. pygeai/tests/organization/test_clients.py +600 -30
  424. pygeai/tests/organization/test_managers.py +424 -0
  425. pygeai/tests/organization/test_mappers.py +153 -0
  426. pygeai/tests/organization/test_responses.py +137 -0
  427. pygeai/tests/proxy/__init__.py +1 -0
  428. pygeai/tests/proxy/test_clients.py +397 -0
  429. pygeai/tests/proxy/test_config.py +171 -0
  430. pygeai/tests/proxy/test_integration.py +305 -0
  431. pygeai/tests/proxy/test_managers.py +312 -0
  432. pygeai/tests/proxy/test_servers.py +387 -0
  433. pygeai/tests/proxy/test_tool.py +176 -0
  434. pygeai/tests/snippets/analytics/__init__.py +0 -0
  435. pygeai/tests/snippets/analytics/get_agent_usage_per_user.py +16 -0
  436. pygeai/tests/snippets/analytics/get_agents_created_and_modified.py +11 -0
  437. pygeai/tests/snippets/analytics/get_average_cost_per_request.py +10 -0
  438. pygeai/tests/snippets/analytics/get_overall_error_rate.py +10 -0
  439. pygeai/tests/snippets/analytics/get_top_10_agents_by_requests.py +12 -0
  440. pygeai/tests/snippets/analytics/get_total_active_users.py +10 -0
  441. pygeai/tests/snippets/analytics/get_total_cost.py +10 -0
  442. pygeai/tests/snippets/analytics/get_total_requests_per_day.py +12 -0
  443. pygeai/tests/snippets/analytics/get_total_tokens.py +12 -0
  444. pygeai/tests/snippets/auth/__init__.py +0 -0
  445. pygeai/tests/snippets/chat/chat_completion_with_reasoning_effort.py +18 -0
  446. pygeai/tests/snippets/chat/get_response.py +15 -0
  447. pygeai/tests/snippets/chat/get_response_complete_example.py +67 -0
  448. pygeai/tests/snippets/chat/get_response_streaming.py +20 -0
  449. pygeai/tests/snippets/chat/get_response_with_files.py +16 -0
  450. pygeai/tests/snippets/chat/get_response_with_instructions.py +19 -0
  451. pygeai/tests/snippets/chat/get_response_with_metadata.py +24 -0
  452. pygeai/tests/snippets/chat/get_response_with_parallel_tools.py +58 -0
  453. pygeai/tests/snippets/chat/get_response_with_reasoning.py +21 -0
  454. pygeai/tests/snippets/chat/get_response_with_store.py +38 -0
  455. pygeai/tests/snippets/chat/get_response_with_tools.py +36 -0
  456. pygeai/tests/snippets/chat/get_response_with_truncation.py +24 -0
  457. pygeai/tests/snippets/dbg/__init__.py +0 -0
  458. pygeai/tests/snippets/dbg/basic_debugging.py +32 -0
  459. pygeai/tests/snippets/dbg/breakpoint_management.py +48 -0
  460. pygeai/tests/snippets/dbg/file_debugging.py +72 -0
  461. pygeai/tests/snippets/dbg/module_debugging.py +61 -0
  462. pygeai/tests/snippets/dbg/stack_navigation.py +45 -0
  463. pygeai/tests/snippets/dbg/stepping_example.py +40 -0
  464. pygeai/tests/snippets/embeddings/cache_example.py +31 -0
  465. pygeai/tests/snippets/embeddings/cohere_example.py +41 -0
  466. pygeai/tests/snippets/embeddings/openai_base64_example.py +27 -0
  467. pygeai/tests/snippets/embeddings/openai_example.py +30 -0
  468. pygeai/tests/snippets/embeddings/similarity_example.py +42 -0
  469. pygeai/tests/snippets/evaluation/dataset/__init__.py +0 -0
  470. pygeai/tests/snippets/evaluation/dataset/complete_workflow_example.py +195 -0
  471. pygeai/tests/snippets/evaluation/dataset/create_dataset.py +26 -0
  472. pygeai/tests/snippets/evaluation/dataset/create_dataset_from_file.py +11 -0
  473. pygeai/tests/snippets/evaluation/dataset/create_dataset_row.py +17 -0
  474. pygeai/tests/snippets/evaluation/dataset/create_expected_source.py +18 -0
  475. pygeai/tests/snippets/evaluation/dataset/create_filter_variable.py +19 -0
  476. pygeai/tests/snippets/evaluation/dataset/delete_dataset.py +9 -0
  477. pygeai/tests/snippets/evaluation/dataset/delete_dataset_row.py +10 -0
  478. pygeai/tests/snippets/evaluation/dataset/delete_expected_source.py +15 -0
  479. pygeai/tests/snippets/evaluation/dataset/delete_filter_variable.py +15 -0
  480. pygeai/tests/snippets/evaluation/dataset/get_dataset.py +9 -0
  481. pygeai/tests/snippets/evaluation/dataset/get_dataset_row.py +10 -0
  482. pygeai/tests/snippets/evaluation/dataset/get_expected_source.py +15 -0
  483. pygeai/tests/snippets/evaluation/dataset/get_filter_variable.py +15 -0
  484. pygeai/tests/snippets/evaluation/dataset/list_dataset_rows.py +9 -0
  485. pygeai/tests/snippets/evaluation/dataset/list_datasets.py +6 -0
  486. pygeai/tests/snippets/evaluation/dataset/list_expected_sources.py +10 -0
  487. pygeai/tests/snippets/evaluation/dataset/list_filter_variables.py +10 -0
  488. pygeai/tests/snippets/evaluation/dataset/update_dataset.py +15 -0
  489. pygeai/tests/snippets/evaluation/dataset/update_dataset_row.py +20 -0
  490. pygeai/tests/snippets/evaluation/dataset/update_expected_source.py +18 -0
  491. pygeai/tests/snippets/evaluation/dataset/update_filter_variable.py +19 -0
  492. pygeai/tests/snippets/evaluation/dataset/upload_dataset_rows_file.py +10 -0
  493. pygeai/tests/snippets/evaluation/plan/__init__.py +0 -0
  494. pygeai/tests/snippets/evaluation/plan/add_plan_system_metric.py +13 -0
  495. pygeai/tests/snippets/evaluation/plan/complete_workflow_example.py +136 -0
  496. pygeai/tests/snippets/evaluation/plan/create_evaluation_plan.py +24 -0
  497. pygeai/tests/snippets/evaluation/plan/create_rag_evaluation_plan.py +22 -0
  498. pygeai/tests/snippets/evaluation/plan/delete_evaluation_plan.py +9 -0
  499. pygeai/tests/snippets/evaluation/plan/delete_plan_system_metric.py +13 -0
  500. pygeai/tests/snippets/evaluation/plan/execute_evaluation_plan.py +11 -0
  501. pygeai/tests/snippets/evaluation/plan/get_evaluation_plan.py +9 -0
  502. pygeai/tests/snippets/evaluation/plan/get_plan_system_metric.py +13 -0
  503. pygeai/tests/snippets/evaluation/plan/get_system_metric.py +9 -0
  504. pygeai/tests/snippets/evaluation/plan/list_evaluation_plans.py +7 -0
  505. pygeai/tests/snippets/evaluation/plan/list_plan_system_metrics.py +9 -0
  506. pygeai/tests/snippets/evaluation/plan/list_system_metrics.py +7 -0
  507. pygeai/tests/snippets/evaluation/plan/update_evaluation_plan.py +22 -0
  508. pygeai/tests/snippets/evaluation/plan/update_plan_system_metric.py +14 -0
  509. pygeai/tests/snippets/evaluation/result/__init__.py +0 -0
  510. pygeai/tests/snippets/evaluation/result/complete_workflow_example.py +150 -0
  511. pygeai/tests/snippets/evaluation/result/get_evaluation_result.py +26 -0
  512. pygeai/tests/snippets/evaluation/result/list_evaluation_results.py +17 -0
  513. pygeai/tests/snippets/files/delete_file.py +1 -4
  514. pygeai/tests/snippets/files/get_file_content.py +2 -4
  515. pygeai/tests/snippets/files/get_file_data.py +1 -4
  516. pygeai/tests/snippets/files/get_file_list.py +1 -6
  517. pygeai/tests/snippets/files/upload_file.py +1 -5
  518. pygeai/tests/snippets/gam/gam_access_token.py +87 -0
  519. pygeai/tests/snippets/lab/agentic_flow_example_1.py +25 -23
  520. pygeai/tests/snippets/lab/agentic_flow_example_4.py +23 -23
  521. pygeai/tests/snippets/lab/agents/create_agent.py +5 -8
  522. pygeai/tests/snippets/lab/agents/create_agent_2.py +1 -5
  523. pygeai/tests/snippets/lab/agents/create_agent_edge_case.py +48 -0
  524. pygeai/tests/snippets/lab/agents/create_agent_with_permissions.py +39 -0
  525. pygeai/tests/snippets/lab/agents/create_agent_with_properties.py +46 -0
  526. pygeai/tests/snippets/lab/agents/create_agent_without_instructions.py +48 -0
  527. pygeai/tests/snippets/lab/agents/delete_agent.py +1 -5
  528. pygeai/tests/snippets/lab/agents/get_agent.py +2 -11
  529. pygeai/tests/snippets/lab/agents/get_agent_with_new_fields.py +62 -0
  530. pygeai/tests/snippets/lab/agents/get_sharing_link.py +2 -7
  531. pygeai/tests/snippets/lab/agents/list_agents.py +4 -7
  532. pygeai/tests/snippets/lab/agents/publish_agent_revision.py +2 -6
  533. pygeai/tests/snippets/lab/agents/update_agent.py +1 -5
  534. pygeai/tests/snippets/lab/agents/update_agent_properties.py +50 -0
  535. pygeai/tests/snippets/lab/assistant_to_agent.py +191 -0
  536. pygeai/tests/snippets/lab/crud_ui.py +462 -0
  537. pygeai/tests/snippets/lab/processes/create_process.py +3 -5
  538. pygeai/tests/snippets/lab/processes/create_task.py +3 -5
  539. pygeai/tests/snippets/lab/processes/jobs/list_jobs.py +10 -19
  540. pygeai/tests/snippets/lab/processes/kbs/create_kb.py +2 -5
  541. pygeai/tests/snippets/lab/processes/kbs/get_kb.py +10 -16
  542. pygeai/tests/snippets/lab/processes/kbs/list_kbs.py +13 -20
  543. pygeai/tests/snippets/lab/processes/kbs/try_all.py +5 -7
  544. pygeai/tests/snippets/lab/processes/list_processes.py +5 -7
  545. pygeai/tests/snippets/lab/runner_1.py +1 -1
  546. pygeai/tests/snippets/lab/samples/summarize_files.py +3 -3
  547. pygeai/tests/snippets/lab/strategies/create_reasoning_strategy.py +2 -5
  548. pygeai/tests/snippets/lab/strategies/get_reasoning_strategy.py +2 -5
  549. pygeai/tests/snippets/lab/strategies/list_reasoning_strategies.py +3 -6
  550. pygeai/tests/snippets/lab/strategies/update_reasoning_strategy.py +2 -5
  551. pygeai/tests/snippets/lab/tools/create_tool.py +4 -10
  552. pygeai/tests/snippets/lab/tools/create_tool_edge_case.py +50 -0
  553. pygeai/tests/snippets/lab/tools/delete_tool.py +2 -6
  554. pygeai/tests/snippets/lab/tools/get_parameter.py +5 -7
  555. pygeai/tests/snippets/lab/tools/get_tool.py +5 -7
  556. pygeai/tests/snippets/lab/tools/list_tools.py +3 -7
  557. pygeai/tests/snippets/lab/tools/publish_tool_revision.py +3 -5
  558. pygeai/tests/snippets/lab/tools/set_parameters.py +4 -9
  559. pygeai/tests/snippets/lab/tools/update_tool.py +4 -8
  560. pygeai/tests/snippets/lab/use_cases/__init__.py +0 -0
  561. pygeai/tests/snippets/lab/use_cases/create_cli_expert.py +1640 -0
  562. pygeai/tests/snippets/lab/use_cases/create_lab_expert.py +4541 -0
  563. pygeai/tests/snippets/lab/use_cases/create_tool_headless_web_browser.py +133 -0
  564. pygeai/tests/snippets/lab/use_cases/create_web_designer.py +189 -0
  565. pygeai/tests/snippets/lab/use_cases/create_web_reader.py +185 -0
  566. pygeai/tests/snippets/lab/{file_summarizer_example.py → use_cases/file_summarizer_example.py} +3 -3
  567. pygeai/tests/snippets/lab/{file_summarizer_example_2.py → use_cases/file_summarizer_example_2.py} +12 -12
  568. pygeai/tests/snippets/lab/use_cases/update_cli_expert.py +1773 -0
  569. pygeai/tests/snippets/lab/use_cases/update_lab_expert.py +4541 -0
  570. pygeai/tests/snippets/lab/use_cases/update_web_designer.py +188 -0
  571. pygeai/tests/snippets/lab/use_cases/update_web_reader.py +195 -0
  572. pygeai/tests/snippets/lab/use_cases/update_web_reader_with_tool.py +210 -0
  573. pygeai/tests/snippets/migrate/__init__.py +45 -0
  574. pygeai/tests/snippets/migrate/agent_migration.py +110 -0
  575. pygeai/tests/snippets/migrate/assistant_migration.py +64 -0
  576. pygeai/tests/snippets/migrate/orchestrator_examples.py +179 -0
  577. pygeai/tests/snippets/migrate/process_migration.py +64 -0
  578. pygeai/tests/snippets/migrate/project_migration.py +42 -0
  579. pygeai/tests/snippets/migrate/tool_migration.py +64 -0
  580. pygeai/tests/snippets/organization/add_project_member.py +10 -0
  581. pygeai/tests/snippets/organization/add_project_member_batch.py +44 -0
  582. pygeai/tests/snippets/organization/create_project.py +2 -2
  583. pygeai/tests/snippets/organization/get_memberships.py +12 -0
  584. pygeai/tests/snippets/organization/get_organization_members.py +6 -0
  585. pygeai/tests/snippets/organization/get_project_members.py +6 -0
  586. pygeai/tests/snippets/organization/get_project_memberships.py +12 -0
  587. pygeai/tests/snippets/organization/get_project_roles.py +6 -0
  588. pygeai/vendor/a2a/__init__.py +1 -0
  589. pygeai/vendor/a2a/auth/__init__.py +0 -0
  590. pygeai/vendor/a2a/auth/user.py +31 -0
  591. pygeai/vendor/a2a/client/__init__.py +19 -0
  592. pygeai/vendor/a2a/client/client.py +425 -0
  593. pygeai/vendor/a2a/client/errors.py +33 -0
  594. pygeai/vendor/a2a/client/helpers.py +22 -0
  595. pygeai/vendor/a2a/py.typed +0 -0
  596. pygeai/vendor/a2a/server/__init__.py +1 -0
  597. pygeai/vendor/a2a/server/agent_execution/__init__.py +18 -0
  598. pygeai/vendor/a2a/server/agent_execution/agent_executor.py +44 -0
  599. pygeai/vendor/a2a/server/agent_execution/context.py +155 -0
  600. pygeai/vendor/a2a/server/agent_execution/request_context_builder.py +20 -0
  601. pygeai/vendor/a2a/server/agent_execution/simple_request_context_builder.py +77 -0
  602. pygeai/vendor/a2a/server/apps/__init__.py +16 -0
  603. pygeai/vendor/a2a/server/apps/jsonrpc/__init__.py +16 -0
  604. pygeai/vendor/a2a/server/apps/jsonrpc/fastapi_app.py +88 -0
  605. pygeai/vendor/a2a/server/apps/jsonrpc/jsonrpc_app.py +426 -0
  606. pygeai/vendor/a2a/server/apps/jsonrpc/starlette_app.py +123 -0
  607. pygeai/vendor/a2a/server/context.py +23 -0
  608. pygeai/vendor/a2a/server/events/__init__.py +21 -0
  609. pygeai/vendor/a2a/server/events/event_consumer.py +149 -0
  610. pygeai/vendor/a2a/server/events/event_queue.py +156 -0
  611. pygeai/vendor/a2a/server/events/in_memory_queue_manager.py +85 -0
  612. pygeai/vendor/a2a/server/events/queue_manager.py +35 -0
  613. pygeai/vendor/a2a/server/request_handlers/__init__.py +20 -0
  614. pygeai/vendor/a2a/server/request_handlers/default_request_handler.py +435 -0
  615. pygeai/vendor/a2a/server/request_handlers/jsonrpc_handler.py +327 -0
  616. pygeai/vendor/a2a/server/request_handlers/request_handler.py +161 -0
  617. pygeai/vendor/a2a/server/request_handlers/response_helpers.py +133 -0
  618. pygeai/vendor/a2a/server/tasks/__init__.py +20 -0
  619. pygeai/vendor/a2a/server/tasks/inmemory_push_notifier.py +62 -0
  620. pygeai/vendor/a2a/server/tasks/inmemory_task_store.py +51 -0
  621. pygeai/vendor/a2a/server/tasks/push_notifier.py +25 -0
  622. pygeai/vendor/a2a/server/tasks/result_aggregator.py +151 -0
  623. pygeai/vendor/a2a/server/tasks/task_manager.py +253 -0
  624. pygeai/vendor/a2a/server/tasks/task_store.py +22 -0
  625. pygeai/vendor/a2a/server/tasks/task_updater.py +155 -0
  626. pygeai/vendor/a2a/types.py +1624 -0
  627. pygeai/vendor/a2a/utils/__init__.py +40 -0
  628. pygeai/vendor/a2a/utils/artifact.py +72 -0
  629. pygeai/vendor/a2a/utils/errors.py +69 -0
  630. pygeai/vendor/a2a/utils/helpers.py +176 -0
  631. pygeai/vendor/a2a/utils/message.py +83 -0
  632. pygeai/vendor/a2a/utils/task.py +57 -0
  633. pygeai/vendor/a2a/utils/telemetry.py +299 -0
  634. pygeai-0.6.0b15.dist-info/METADATA +205 -0
  635. pygeai-0.6.0b15.dist-info/RECORD +799 -0
  636. {pygeai-0.1.51b3.dist-info → pygeai-0.6.0b15.dist-info}/WHEEL +1 -1
  637. {pygeai-0.1.51b3.dist-info → pygeai-0.6.0b15.dist-info}/entry_points.txt +2 -1
  638. {pygeai-0.1.51b3.dist-info → pygeai-0.6.0b15.dist-info}/licenses/LICENSE +13 -1
  639. pygeai-0.6.0b15.dist-info/top_level.txt +1 -0
  640. docs/geai-proxy/README.md +0 -145
  641. docs/source/conf.py +0 -45
  642. pygeai/tests/core/test_managers.py +0 -233
  643. pygeai-0.1.51b3.dist-info/METADATA +0 -130
  644. pygeai-0.1.51b3.dist-info/RECORD +0 -324
  645. pygeai-0.1.51b3.dist-info/top_level.txt +0 -3
  646. scripts/bump_beta_version.py +0 -56
  647. {scripts → pygeai/analytics}/__init__.py +0 -0
  648. /pygeai/tests/snippets/lab/{c_code_fixer_agent_flow.py → use_cases/c_code_fixer_agent_flow.py} +0 -0
@@ -0,0 +1,154 @@
1
+ import unittest
2
+ import sys
3
+ from unittest import TestCase
4
+ from unittest.mock import patch
5
+ from io import StringIO
6
+
7
+ from pygeai.cli.geai import CLIDriver
8
+ from pygeai.cli.error_handler import ExitCode
9
+
10
+
11
+ class TestCLIDriver(TestCase):
12
+ """
13
+ Test suite for CLIDriver error handling integration.
14
+ Run with: python -m unittest pygeai.tests.cli.test_geai_driver.TestCLIDriver
15
+ """
16
+
17
+ def setUp(self):
18
+ """Set up test fixtures"""
19
+ self.driver = CLIDriver()
20
+
21
+ @patch('sys.stderr', new_callable=StringIO)
22
+ def test_unknown_command_exit_code(self, mock_stderr):
23
+ """Test that unknown command returns correct exit code"""
24
+ sys.argv = ['geai', 'unknown_command_xyz']
25
+ exit_code = self.driver.main()
26
+ self.assertEqual(exit_code, ExitCode.USER_INPUT_ERROR)
27
+ output = mock_stderr.getvalue()
28
+ self.assertIn("'unknown_command_xyz' is not a valid command", output)
29
+
30
+ @patch('sys.stderr', new_callable=StringIO)
31
+ def test_unknown_command_with_fuzzy_match(self, mock_stderr):
32
+ """Test unknown command with fuzzy matching suggestion"""
33
+ sys.argv = ['geai', 'halp']
34
+ exit_code = self.driver.main()
35
+ self.assertEqual(exit_code, ExitCode.USER_INPUT_ERROR)
36
+ output = mock_stderr.getvalue()
37
+ self.assertIn("'halp' is not a valid command", output)
38
+ self.assertIn("Did you mean", output)
39
+
40
+ @patch('sys.stdout', new_callable=StringIO)
41
+ def test_help_command_exit_code(self, mock_stdout):
42
+ """Test that help command returns success exit code"""
43
+ sys.argv = ['geai', 'help']
44
+ exit_code = self.driver.main()
45
+ self.assertEqual(exit_code, ExitCode.SUCCESS)
46
+
47
+ @patch('sys.stdout', new_callable=StringIO)
48
+ def test_version_command_exit_code(self, mock_stdout):
49
+ """Test that version command returns success exit code"""
50
+ sys.argv = ['geai', 'version']
51
+ exit_code = self.driver.main()
52
+ self.assertEqual(exit_code, ExitCode.SUCCESS)
53
+
54
+ @patch('sys.stderr', new_callable=StringIO)
55
+ def test_invalid_option_exit_code(self, mock_stderr):
56
+ """Test that invalid option returns correct exit code"""
57
+ sys.argv = ['geai', 'configure', '--invalid-option-xyz']
58
+ exit_code = self.driver.main()
59
+ self.assertEqual(exit_code, ExitCode.USER_INPUT_ERROR)
60
+ output = mock_stderr.getvalue()
61
+ self.assertIn("'--invalid-option-xyz' is not a valid option", output)
62
+
63
+ @patch('sys.stderr', new_callable=StringIO)
64
+ def test_error_message_format(self, mock_stderr):
65
+ """Test that error messages follow the standard format"""
66
+ sys.argv = ['geai', 'invalidcmd']
67
+ exit_code = self.driver.main()
68
+ output = mock_stderr.getvalue()
69
+
70
+ # Check for standard error format
71
+ self.assertIn("ERROR [", output)
72
+ self.assertIn("→", output)
73
+ self.assertIn("Run 'geai help' for usage information", output)
74
+
75
+ @patch('sys.stderr', new_callable=StringIO)
76
+ def test_available_commands_shown(self, mock_stderr):
77
+ """Test that available commands are shown for unknown command"""
78
+ sys.argv = ['geai', 'xyz123']
79
+ exit_code = self.driver.main()
80
+ output = mock_stderr.getvalue()
81
+
82
+ # Should show available commands
83
+ self.assertIn("Available commands:", output)
84
+ self.assertIn("help", output)
85
+ self.assertIn("version", output)
86
+
87
+ @patch('sys.stderr', new_callable=StringIO)
88
+ def test_similar_command_suggestion(self, mock_stderr):
89
+ """Test that similar commands are suggested"""
90
+ sys.argv = ['geai', 'versoin'] # Typo in 'version'
91
+ exit_code = self.driver.main()
92
+ output = mock_stderr.getvalue()
93
+
94
+ self.assertIn("Did you mean", output)
95
+ self.assertIn("version", output)
96
+
97
+ @patch('sys.stdout', new_callable=StringIO)
98
+ def test_keyboard_interrupt_exit_code(self, mock_stdout):
99
+ """Test keyboard interrupt handling"""
100
+ sys.argv = ['geai', 'help']
101
+
102
+ with patch.object(self.driver, 'process_command', side_effect=KeyboardInterrupt):
103
+ exit_code = self.driver.main()
104
+ self.assertEqual(exit_code, ExitCode.KEYBOARD_INTERRUPT)
105
+ output = mock_stdout.getvalue()
106
+ self.assertIn("Operation cancelled", output)
107
+
108
+ @patch('sys.stderr', new_callable=StringIO)
109
+ def test_unexpected_error_exit_code(self, mock_stderr):
110
+ """Test unexpected error handling"""
111
+ sys.argv = ['geai', 'help']
112
+
113
+ with patch.object(self.driver, 'process_command', side_effect=RuntimeError("Test error")):
114
+ exit_code = self.driver.main()
115
+ self.assertEqual(exit_code, ExitCode.UNEXPECTED_ERROR)
116
+ output = mock_stderr.getvalue()
117
+ self.assertIn("unexpected error", output)
118
+ self.assertIn("Test error", output)
119
+
120
+ @patch('sys.stderr', new_callable=StringIO)
121
+ def test_configure_with_typo_in_option(self, mock_stderr):
122
+ """Test configure command with typo in option"""
123
+ sys.argv = ['geai', 'configure', '--kee'] # Typo in '--key'
124
+ exit_code = self.driver.main()
125
+ self.assertEqual(exit_code, ExitCode.USER_INPUT_ERROR)
126
+ output = mock_stderr.getvalue()
127
+ self.assertIn("'--kee' is not a valid option", output)
128
+
129
+ @patch('sys.stdout', new_callable=StringIO)
130
+ def test_default_to_help_when_no_args(self, mock_stdout):
131
+ """Test that CLI defaults to help when no arguments provided"""
132
+ sys.argv = ['geai']
133
+ exit_code = self.driver.main()
134
+ self.assertEqual(exit_code, ExitCode.SUCCESS)
135
+ output = mock_stdout.getvalue()
136
+ self.assertIn("GEAI CLI", output)
137
+
138
+ def test_exit_codes_are_different(self):
139
+ """Test that different error types have different exit codes"""
140
+ exit_codes = [
141
+ ExitCode.SUCCESS,
142
+ ExitCode.USER_INPUT_ERROR,
143
+ ExitCode.MISSING_REQUIREMENT,
144
+ ExitCode.SERVICE_ERROR,
145
+ ExitCode.KEYBOARD_INTERRUPT,
146
+ ExitCode.UNEXPECTED_ERROR,
147
+ ]
148
+
149
+ # All exit codes should be unique
150
+ self.assertEqual(len(exit_codes), len(set(exit_codes)))
151
+
152
+
153
+ if __name__ == '__main__':
154
+ unittest.main()
@@ -35,7 +35,7 @@ class TestCommandParser(TestCase):
35
35
  def test_identify_command_invalid(self):
36
36
  with self.assertRaises(UnknownArgumentError) as context:
37
37
  self.parser.identify_command('invalid')
38
- self.assertEqual(str(context.exception), "'invalid' is not a valid command. Run with help or h to check usage.")
38
+ self.assertEqual(str(context.exception), "'invalid' is not a valid command.")
39
39
 
40
40
  def test_extract_option_list_valid(self):
41
41
  args = ['--detail', 'full', '--name', 'Project1']
@@ -51,7 +51,7 @@ class TestCommandParser(TestCase):
51
51
  with self.assertRaises(UnknownArgumentError) as context:
52
52
  self.parser.extract_option_list(args)
53
53
  self.assertEqual(str(context.exception),
54
- "'--invalid' is not a valid option. Run with help or h to check usage.")
54
+ "'--invalid' is not a valid option.")
55
55
 
56
56
  def test_identify_command_valid_multiple_identifiers(self):
57
57
  command = self.parser.identify_command('organization')
@@ -77,7 +77,7 @@ class TestCommandParser(TestCase):
77
77
  def test_identify_command_empty_string(self):
78
78
  with self.assertRaises(UnknownArgumentError) as context:
79
79
  self.parser.identify_command('')
80
- self.assertEqual(str(context.exception), "'' is not a valid command. Run with help or h to check usage.")
80
+ self.assertEqual(str(context.exception), "'' is not a valid command.")
81
81
 
82
82
  def test_extract_option_list_empty_arguments(self):
83
83
  args = []
@@ -122,7 +122,7 @@ class TestCommandParser(TestCase):
122
122
  with self.assertRaises(UnknownArgumentError) as context:
123
123
  self.parser.extract_option_list(args)
124
124
  self.assertEqual(str(context.exception),
125
- "'--invalid' is not a valid option. Run with help or h to check usage.")
125
+ "'--invalid' is not a valid option.")
126
126
 
127
127
  def test_identify_command_subcommand(self):
128
128
  command_with_subcommands = Command(
@@ -151,4 +151,4 @@ class TestCommandParser(TestCase):
151
151
  with self.assertRaises(UnknownArgumentError) as context:
152
152
  self.parser.identify_command('nonexistent')
153
153
  self.assertEqual(str(context.exception),
154
- "'nonexistent' is not a valid command. Run with help or h to check usage.")
154
+ "'nonexistent' is not a valid command.")
@@ -149,12 +149,19 @@ LLM_SETTINGS_5 = {
149
149
  }
150
150
 
151
151
  REQUEST_ITEM = {
152
+ "apiToken": "test-api-token",
152
153
  "assistant": "N/D",
154
+ "cost": 0.001,
155
+ "elapsedTimeMs": 1500,
156
+ "endTimestamp": "2025-02-25T15:03:15.144",
153
157
  "intent": None,
154
158
  "timestamp": "2025-02-25T15:03:13.644",
155
159
  "prompt": None,
156
160
  "output": None,
157
161
  "inputText": None,
162
+ "module": "test-module",
163
+ "sessionId": "test-session-id",
164
+ "startTimestamp": "2025-02-25T15:03:13.644",
158
165
  "status": "succeeded"
159
166
  }
160
167
 
@@ -351,8 +351,22 @@ class TestModelMapper(TestCase):
351
351
  self.assertEqual(usage_limit.remaining_usage, 50)
352
352
 
353
353
  def test_map_to_item(self):
354
- data = {"assistant": "Assistant 1", "intent": "Intent 1", "timestamp": "2025-02-05T12:00:00Z",
355
- "prompt": "Test prompt", "output": "Test output", "inputText": "Test input", "status": "Success"}
354
+ data = {
355
+ "apiToken": "test-token",
356
+ "assistant": "Assistant 1",
357
+ "cost": 0.5,
358
+ "elapsedTimeMs": 100,
359
+ "endTimestamp": "2025-02-05T12:00:05Z",
360
+ "intent": "Intent 1",
361
+ "module": "test-module",
362
+ "timestamp": "2025-02-05T12:00:00Z",
363
+ "prompt": "Test prompt",
364
+ "output": "Test output",
365
+ "inputText": "Test input",
366
+ "sessionId": "test-session",
367
+ "startTimestamp": "2025-02-05T12:00:00Z",
368
+ "status": "succeeded"
369
+ }
356
370
  item = ModelMapper.map_to_item(data)
357
371
 
358
372
  self.assertTrue(isinstance(item, RequestItem))
@@ -472,45 +486,65 @@ class TestModelMapper(TestCase):
472
486
 
473
487
  def test_map_to_project_item(self):
474
488
  data = {
489
+ "apiToken": "test-token",
475
490
  "assistant": "Test Assistant",
491
+ "cost": 0.5,
492
+ "elapsedTimeMs": 100,
493
+ "endTimestamp": "2025-02-05T12:00:05Z",
476
494
  "intent": "Test Intent",
495
+ "module": "test-module",
477
496
  "timestamp": "2025-02-05T12:00:00Z",
478
497
  "prompt": "Test prompt",
479
498
  "output": "Test output",
480
499
  "inputText": "Test input text",
481
- "status": "active"
500
+ "sessionId": "test-session-id",
501
+ "startTimestamp": "2025-02-05T12:00:00Z",
502
+ "status": "succeeded"
482
503
  }
483
504
  item = ModelMapper.map_to_item(data)
484
505
 
485
506
  self.assertTrue(isinstance(item, RequestItem))
486
507
  self.assertEqual(item.assistant, "Test Assistant")
487
508
  self.assertEqual(item.intent, "Test Intent")
488
- self.assertEqual(item.timestamp, "2025-02-05T12:00:00Z")
489
509
  self.assertEqual(item.prompt, "Test prompt")
490
510
  self.assertEqual(item.output, "Test output")
491
511
  self.assertEqual(item.input_text, "Test input text")
492
- self.assertEqual(item.status, "active")
512
+ self.assertEqual(item.status, "succeeded")
493
513
 
494
514
  def test_map_to_item_list(self):
495
515
  data = {
496
516
  "items": [
497
517
  {
518
+ "apiToken": "test-token-1",
498
519
  "assistant": "Assistant 1",
520
+ "cost": 0.5,
521
+ "elapsedTimeMs": 100,
522
+ "endTimestamp": "2025-02-05T12:00:05Z",
499
523
  "intent": "Intent 1",
524
+ "module": "test-module",
500
525
  "timestamp": "2025-02-05T12:00:00Z",
501
526
  "prompt": "Prompt 1",
502
527
  "output": "Output 1",
503
528
  "inputText": "Input Text 1",
504
- "status": "active"
529
+ "sessionId": "test-session-1",
530
+ "startTimestamp": "2025-02-05T12:00:00Z",
531
+ "status": "succeeded"
505
532
  },
506
533
  {
534
+ "apiToken": "test-token-2",
507
535
  "assistant": "Assistant 2",
536
+ "cost": 0.7,
537
+ "elapsedTimeMs": 150,
538
+ "endTimestamp": "2025-02-05T12:05:10Z",
508
539
  "intent": "Intent 2",
540
+ "module": "test-module",
509
541
  "timestamp": "2025-02-05T12:05:00Z",
510
542
  "prompt": "Prompt 2",
511
543
  "output": "Output 2",
512
544
  "inputText": "Input Text 2",
513
- "status": "inactive"
545
+ "sessionId": "test-session-2",
546
+ "startTimestamp": "2025-02-05T12:05:00Z",
547
+ "status": "succeeded"
514
548
  }
515
549
  ]
516
550
  }
@@ -522,16 +556,14 @@ class TestModelMapper(TestCase):
522
556
 
523
557
  self.assertEqual(items[0].assistant, "Assistant 1")
524
558
  self.assertEqual(items[0].intent, "Intent 1")
525
- self.assertEqual(items[0].timestamp, "2025-02-05T12:00:00Z")
526
559
  self.assertEqual(items[0].prompt, "Prompt 1")
527
560
  self.assertEqual(items[0].output, "Output 1")
528
561
  self.assertEqual(items[0].input_text, "Input Text 1")
529
- self.assertEqual(items[0].status, "active")
562
+ self.assertEqual(items[0].status, "succeeded")
530
563
 
531
564
  self.assertEqual(items[1].assistant, "Assistant 2")
532
565
  self.assertEqual(items[1].intent, "Intent 2")
533
- self.assertEqual(items[1].timestamp, "2025-02-05T12:05:00Z")
534
566
  self.assertEqual(items[1].prompt, "Prompt 2")
535
567
  self.assertEqual(items[1].output, "Output 2")
536
568
  self.assertEqual(items[1].input_text, "Input Text 2")
537
- self.assertEqual(items[1].status, "inactive")
569
+ self.assertEqual(items[1].status, "succeeded")
@@ -192,7 +192,9 @@ class TestModels(TestCase):
192
192
  request_item = RequestItem.model_validate(request_item_data)
193
193
  self.assertEqual(request_item.assistant, request_item_data.get("assistant"))
194
194
  self.assertEqual(request_item.intent, request_item_data.get("intent"))
195
- self.assertEqual(request_item.timestamp, request_item_data.get("timestamp"))
195
+ # Compare timestamps by checking that the string representation starts with the expected value
196
+ expected_timestamp = request_item_data.get("timestamp").replace("Z", "+00:00") if request_item_data.get("timestamp").endswith("Z") else request_item_data.get("timestamp")
197
+ self.assertTrue(request_item.timestamp.isoformat().startswith(expected_timestamp))
196
198
  self.assertEqual(request_item.prompt, request_item_data.get("prompt"))
197
199
  self.assertEqual(request_item.output, request_item_data.get("output"))
198
200
  self.assertEqual(request_item.input_text, request_item_data.get("inputText"))
@@ -0,0 +1,53 @@
1
+ import unittest
2
+ from unittest.mock import MagicMock
3
+
4
+ from pygeai.core.base.responses import ErrorListResponse, EmptyResponse
5
+ from pygeai.core.base.models import Error
6
+
7
+
8
+ class TestCoreBaseResponses(unittest.TestCase):
9
+ """
10
+ python -m unittest pygeai.tests.core.base.test_responses.TestCoreBaseResponses
11
+ """
12
+
13
+ def test_error_list_response_to_dict(self):
14
+ error1 = MagicMock(spec=Error)
15
+ error1.to_dict.return_value = {"code": "E001", "message": "Error 1"}
16
+ error2 = MagicMock(spec=Error)
17
+ error2.to_dict.return_value = {"code": "E002", "message": "Error 2"}
18
+
19
+ response = ErrorListResponse(errors=[error1, error2])
20
+ result = response.to_dict()
21
+
22
+ self.assertEqual(len(result), 2)
23
+ self.assertEqual(result[0], {"code": "E001", "message": "Error 1"})
24
+ self.assertEqual(result[1], {"code": "E002", "message": "Error 2"})
25
+
26
+ def test_empty_response_with_dict_content(self):
27
+ response = EmptyResponse(content={"key": "value"})
28
+ result = response.to_dict()
29
+
30
+ self.assertEqual(result, {"content": {"key": "value"}})
31
+
32
+ def test_empty_response_with_string_content(self):
33
+ response = EmptyResponse(content="test message")
34
+ result = response.to_dict()
35
+
36
+ self.assertEqual(result, {"content": "test message"})
37
+
38
+ def test_empty_response_with_none_content(self):
39
+ response = EmptyResponse(content=None)
40
+ result = response.to_dict()
41
+
42
+ self.assertEqual(result, {})
43
+
44
+ def test_empty_response_str(self):
45
+ response = EmptyResponse(content={"test": "data"})
46
+ result = str(response)
47
+
48
+ self.assertIn("content", result)
49
+ self.assertIn("test", result)
50
+
51
+
52
+ if __name__ == '__main__':
53
+ unittest.main()
File without changes
File without changes
@@ -0,0 +1,186 @@
1
+ import unittest
2
+ from unittest import TestCase
3
+ from unittest.mock import patch, mock_open
4
+ import os
5
+ from pathlib import Path
6
+ from pygeai.core.common.config import SettingsManager, get_settings
7
+
8
+
9
+ class TestSettingsManager(TestCase):
10
+ """
11
+ python -m unittest pygeai.tests.core.common.test_config.TestSettingsManager
12
+ """
13
+
14
+ def setUp(self):
15
+ # Mock the credentials file path to use a sample file for testing
16
+ self.sample_creds_path = Path("pygeai/tests/core/common/data/credentials")
17
+ self.creds_content = """
18
+ [default]
19
+ GEAI_API_KEY = test_api_key
20
+ GEAI_API_BASE_URL = https://api.test.com
21
+ GEAI_API_EVAL_URL = https://eval.test.com
22
+
23
+ [alias1]
24
+ GEAI_API_KEY = alias1_key
25
+ GEAI_API_BASE_URL = https://api.alias1.com
26
+ """
27
+ # Mock file existence and content to avoid touching real filesystem
28
+ self.file_patch = patch('pathlib.Path.exists', return_value=True)
29
+ self.file_patch.start()
30
+ self.open_patch = patch('pathlib.Path.open', mock_open(read_data=self.creds_content))
31
+ self.open_patch.start()
32
+ self.touch_patch = patch('pathlib.Path.touch', return_value=None)
33
+ self.touch_patch.start()
34
+
35
+ # Mock configparser read to enforce our test content
36
+ self.config_read_patch = patch('configparser.ConfigParser.read')
37
+ self.mock_config_read = self.config_read_patch.start()
38
+ self.mock_config_read.return_value = None # We'll set up config manually in tests if needed
39
+
40
+ # Mock environment variables to be empty initially
41
+ self.env_patch = patch.dict('os.environ', {}, clear=True)
42
+ self.env_patch.start()
43
+
44
+ # Mock sys.stdout.write to capture output
45
+ self.stdout_patch = patch('sys.stdout.write')
46
+ self.mock_stdout = self.stdout_patch.start()
47
+
48
+ # Initialize SettingsManager with mocked settings dir and creds file
49
+ self.settings = SettingsManager()
50
+
51
+ # Manually set up config with test content for consistency
52
+ self.settings.config.clear()
53
+ self.settings.config.read_string(self.creds_content)
54
+
55
+ def tearDown(self):
56
+ self.file_patch.stop()
57
+ self.open_patch.stop()
58
+ self.touch_patch.stop()
59
+ self.env_patch.stop()
60
+ self.stdout_patch.stop()
61
+ self.config_read_patch.stop()
62
+
63
+ def test_init_with_existing_file(self):
64
+ self.assertTrue("default" in self.settings.config)
65
+ self.assertTrue("alias1" in self.settings.config)
66
+ self.assertEqual(self.settings.config["default"]["GEAI_API_KEY"], "test_api_key")
67
+ self.mock_stdout.assert_not_called() # No message since file exists
68
+
69
+ def test_init_with_non_existing_file(self):
70
+ with patch('pathlib.Path.exists', return_value=False):
71
+ settings = SettingsManager()
72
+ self.assertEqual(len(settings.config.sections()), 0) # No sections in empty config
73
+ self.mock_stdout.assert_called()
74
+ self.assertTrue(any("Credentials file not found" in str(call) for call in self.mock_stdout.call_args_list))
75
+
76
+ def test_has_value_existing(self):
77
+ result = self.settings.has_value("GEAI_API_KEY", "default")
78
+ self.assertTrue(result)
79
+
80
+ def test_has_value_non_existing_key(self):
81
+ result = self.settings.has_value("INVALID_KEY", "default")
82
+ self.assertFalse(result)
83
+
84
+ def test_has_value_non_existing_alias(self):
85
+ result = self.settings.has_value("GEAI_API_KEY", "invalid_alias")
86
+ self.assertFalse(result)
87
+
88
+ def test_get_setting_value_existing(self):
89
+ value = self.settings.get_setting_value("GEAI_API_KEY", "default")
90
+ self.assertEqual(value, "test_api_key")
91
+
92
+ def test_get_setting_value_non_existing_alias(self):
93
+ value = self.settings.get_setting_value("GEAI_API_KEY", "invalid_alias")
94
+ self.assertIsNone(value)
95
+
96
+ def test_get_setting_value_non_existing_key(self):
97
+ with patch('sys.stdout.write') as mock_write:
98
+ value = self.settings.get_setting_value("INVALID_KEY", "default")
99
+ self.assertEqual(value, "")
100
+ mock_write.assert_called()
101
+ self.assertIn("'INVALID_KEY' not found in alias 'default'", str(mock_write.call_args))
102
+
103
+ def test_get_setting_value_non_existing_key_eval_url(self):
104
+ with patch('sys.stdout.write') as mock_write:
105
+ with patch.object(self.settings, 'set_eval_url') as mock_set_eval:
106
+ value = self.settings.get_setting_value("GEAI_API_EVAL_URL", "default")
107
+ self.assertEqual(value, "https://eval.test.com") # From mocked content
108
+ mock_write.assert_not_called() # No message since it's in creds file
109
+ mock_set_eval.assert_not_called() # Not called since value exists
110
+
111
+ def test_set_setting_value_new_alias(self):
112
+ with patch('pathlib.Path.open', mock_open()) as mock_file:
113
+ self.settings.set_setting_value("NEW_KEY", "new_value", "new_alias")
114
+ self.assertTrue("new_alias" in self.settings.config)
115
+ self.assertEqual(self.settings.config["new_alias"]["NEW_KEY"], "new_value")
116
+ mock_file.assert_called_once()
117
+
118
+ def test_set_setting_value_existing_alias(self):
119
+ with patch('pathlib.Path.open', mock_open()) as mock_file:
120
+ self.settings.set_setting_value("GEAI_API_KEY", "updated_key", "default")
121
+ self.assertEqual(self.settings.config["default"]["GEAI_API_KEY"], "updated_key")
122
+ mock_file.assert_called_once()
123
+
124
+ def test_get_api_key_from_env(self):
125
+ with patch.dict('os.environ', {'GEAI_API_KEY': 'env_api_key'}, clear=True):
126
+ api_key = self.settings.get_api_key("default")
127
+ self.assertEqual(api_key, "env_api_key")
128
+
129
+ def test_get_api_key_from_file(self):
130
+ api_key = self.settings.get_api_key("default")
131
+ self.assertEqual(api_key, "test_api_key")
132
+
133
+ def test_get_api_key_alias(self):
134
+ api_key = self.settings.get_api_key("alias1")
135
+ self.assertEqual(api_key, "alias1_key")
136
+
137
+ def test_set_api_key(self):
138
+ with patch('pathlib.Path.open', mock_open()) as mock_file:
139
+ self.settings.set_api_key("new_api_key", "default")
140
+ self.assertEqual(self.settings.config["default"]["GEAI_API_KEY"], "new_api_key")
141
+ mock_file.assert_called_once()
142
+
143
+ def test_get_base_url_from_env(self):
144
+ with patch.dict('os.environ', {'GEAI_API_BASE_URL': 'https://env.test.com'}, clear=True):
145
+ base_url = self.settings.get_base_url("default")
146
+ self.assertEqual(base_url, "https://env.test.com")
147
+
148
+ def test_get_base_url_from_file(self):
149
+ base_url = self.settings.get_base_url("default")
150
+ self.assertEqual(base_url, "https://api.test.com")
151
+
152
+ def test_get_base_url_alias(self):
153
+ base_url = self.settings.get_base_url("alias1")
154
+ self.assertEqual(base_url, "https://api.alias1.com")
155
+
156
+ def test_set_base_url(self):
157
+ with patch('pathlib.Path.open', mock_open()) as mock_file:
158
+ self.settings.set_base_url("https://new.test.com", "default")
159
+ self.assertEqual(self.settings.config["default"]["GEAI_API_BASE_URL"], "https://new.test.com")
160
+ mock_file.assert_called_once()
161
+
162
+ def test_get_eval_url_from_env(self):
163
+ with patch.dict('os.environ', {'GEAI_API_EVAL_URL': 'https://env.eval.test.com'}, clear=True):
164
+ eval_url = self.settings.get_eval_url("default")
165
+ self.assertEqual(eval_url, "https://env.eval.test.com")
166
+
167
+ def test_get_eval_url_from_file(self):
168
+ eval_url = self.settings.get_eval_url("default")
169
+ self.assertEqual(eval_url, "https://eval.test.com")
170
+
171
+ def test_set_eval_url(self):
172
+ with patch('pathlib.Path.open', mock_open()) as mock_file:
173
+ self.settings.set_eval_url("https://new.eval.test.com", "default")
174
+ self.assertEqual(self.settings.config["default"]["GEAI_API_EVAL_URL"], "https://new.eval.test.com")
175
+ mock_file.assert_called_once()
176
+
177
+ def test_list_aliases(self):
178
+ aliases = self.settings.list_aliases()
179
+ self.assertEqual(len(aliases), 2)
180
+ self.assertEqual(aliases["default"], "https://api.test.com")
181
+ self.assertEqual(aliases["alias1"], "https://api.alias1.com")
182
+
183
+ def test_get_settings_lru_cache(self):
184
+ settings1 = get_settings()
185
+ settings2 = get_settings()
186
+ self.assertIs(settings1, settings2) # Should return the same instance due to lru_cache
@@ -0,0 +1,69 @@
1
+ import unittest
2
+ import io
3
+ import sys
4
+ from unittest.mock import patch
5
+ from pygeai.core.common.decorators import measure_execution_time, handler_server_error
6
+ from pygeai.core.common.exceptions import ServerResponseError
7
+
8
+
9
+ class TestDecorators(unittest.TestCase):
10
+ """
11
+ python -m unittest pygeai.tests.core.common.test_decorators.TestDecorators
12
+ """
13
+
14
+ def test_measure_execution_time_success(self):
15
+ @measure_execution_time
16
+ def sample_function():
17
+ return "Success"
18
+
19
+ # Capture stdout to verify printed messages
20
+ captured_output = io.StringIO()
21
+ sys.stdout = captured_output
22
+
23
+ result = sample_function()
24
+
25
+ sys.stdout = sys.__stdout__ # Restore stdout
26
+ output = captured_output.getvalue()
27
+ self.assertIn("Measuring execution time for: sample_function", output)
28
+ self.assertIn("Function sample_function executed in", output)
29
+ self.assertEqual(result, "Success")
30
+
31
+ def test_measure_execution_time_with_exception(self):
32
+ @measure_execution_time
33
+ def failing_function():
34
+ raise ValueError("Test error")
35
+
36
+ # Capture stdout to verify printed messages
37
+ captured_output = io.StringIO()
38
+ sys.stdout = captured_output
39
+
40
+ result = None
41
+ try:
42
+ result = failing_function()
43
+ except ValueError:
44
+ pass # The decorator catches the exception, so this won't be reached
45
+
46
+ sys.stdout = sys.__stdout__ # Restore stdout
47
+ output = captured_output.getvalue()
48
+ self.assertIn("Measuring execution time for: failing_function", output)
49
+ self.assertIn("Error measuring execution time: Test error", output)
50
+ self.assertIsNone(result) # No return value since exception was caught
51
+
52
+ def test_handler_server_error_no_error(self):
53
+ @handler_server_error
54
+ def successful_function():
55
+ return {"data": "Success"}
56
+
57
+ result = successful_function()
58
+ self.assertEqual(result, {"data": "Success"})
59
+
60
+ def test_handler_server_error_with_error(self):
61
+ @handler_server_error
62
+ def error_function():
63
+ return {"error": "Server error message"}
64
+
65
+ with self.assertRaises(ServerResponseError) as context:
66
+ error_function()
67
+
68
+ self.assertIn("There was an error communicating with the server: Server error message", str(context.exception))
69
+
File without changes