pygeai 0.1.6__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 (788) hide show
  1. pygeai/__init__.py +11 -2
  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 +48 -57
  146. pygeai/assistant/data/__init__.py +0 -0
  147. pygeai/assistant/data/clients.py +15 -0
  148. pygeai/assistant/data_analyst/__init__.py +0 -0
  149. pygeai/assistant/data_analyst/clients.py +75 -0
  150. pygeai/assistant/data_analyst/endpoints.py +2 -0
  151. pygeai/assistant/endpoints.py +0 -2
  152. pygeai/assistant/managers.py +738 -0
  153. pygeai/assistant/mappers.py +153 -0
  154. pygeai/assistant/rag/clients.py +132 -21
  155. pygeai/assistant/rag/mappers.py +228 -0
  156. pygeai/assistant/rag/models.py +396 -0
  157. pygeai/assistant/rag/responses.py +10 -0
  158. pygeai/auth/__init__.py +0 -0
  159. pygeai/auth/clients.py +129 -0
  160. pygeai/auth/endpoints.py +6 -0
  161. pygeai/chat/clients.py +406 -31
  162. pygeai/chat/endpoints.py +3 -0
  163. pygeai/chat/iris.py +17 -0
  164. pygeai/chat/managers.py +64 -0
  165. pygeai/chat/session.py +38 -0
  166. pygeai/chat/settings.py +6 -0
  167. pygeai/chat/ui.py +678 -0
  168. pygeai/cli/__init__.py +0 -1
  169. pygeai/cli/commands/admin.py +9 -12
  170. pygeai/cli/commands/analytics.py +533 -0
  171. pygeai/cli/commands/assistant.py +11 -11
  172. pygeai/cli/commands/auth.py +299 -0
  173. pygeai/cli/commands/base.py +201 -7
  174. pygeai/cli/commands/chat.py +875 -14
  175. pygeai/cli/commands/common.py +30 -26
  176. pygeai/cli/commands/configuration.py +84 -9
  177. pygeai/cli/commands/docs.py +105 -0
  178. pygeai/cli/commands/embeddings.py +187 -0
  179. pygeai/cli/commands/evaluation.py +2069 -0
  180. pygeai/cli/commands/feedback.py +93 -0
  181. pygeai/cli/commands/files.py +312 -0
  182. pygeai/cli/commands/flows/__init__.py +0 -0
  183. pygeai/cli/commands/gam.py +349 -0
  184. pygeai/cli/commands/lab/__init__.py +0 -0
  185. pygeai/cli/commands/lab/ai_lab.py +4110 -0
  186. pygeai/cli/commands/lab/common.py +135 -0
  187. pygeai/cli/commands/lab/options.py +8 -0
  188. pygeai/cli/commands/lab/spec.py +273 -0
  189. pygeai/cli/commands/lab/utils.py +13 -0
  190. pygeai/cli/commands/llm.py +164 -0
  191. pygeai/cli/commands/migrate.py +1198 -0
  192. pygeai/cli/commands/options.py +86 -0
  193. pygeai/cli/commands/organization.py +560 -98
  194. pygeai/cli/commands/rag.py +306 -10
  195. pygeai/cli/commands/rerank.py +108 -0
  196. pygeai/cli/commands/secrets.py +357 -0
  197. pygeai/cli/commands/usage_limits.py +583 -0
  198. pygeai/cli/commands/validators.py +209 -0
  199. pygeai/cli/commands/version.py +44 -0
  200. pygeai/cli/error_handler.py +151 -0
  201. pygeai/cli/geai.py +171 -30
  202. pygeai/cli/geai_proxy.py +318 -0
  203. pygeai/cli/install_man.py +107 -0
  204. pygeai/cli/parsers.py +78 -25
  205. pygeai/cli/texts/help.py +712 -55
  206. pygeai/core/__init__.py +9 -1
  207. pygeai/core/base/clients.py +61 -10
  208. pygeai/core/base/mappers.py +208 -30
  209. pygeai/core/base/models.py +8 -308
  210. pygeai/core/base/responses.py +18 -1
  211. pygeai/core/base/session.py +110 -17
  212. pygeai/core/common/config.py +98 -16
  213. pygeai/core/common/decorators.py +44 -0
  214. pygeai/core/common/exceptions.py +104 -4
  215. pygeai/core/embeddings/__init__.py +19 -0
  216. pygeai/core/embeddings/clients.py +93 -0
  217. pygeai/core/embeddings/endpoints.py +1 -0
  218. pygeai/core/embeddings/managers.py +62 -0
  219. pygeai/core/embeddings/mappers.py +52 -0
  220. pygeai/core/embeddings/models.py +14 -0
  221. pygeai/core/embeddings/responses.py +31 -0
  222. pygeai/core/feedback/__init__.py +0 -0
  223. pygeai/core/feedback/clients.py +50 -0
  224. pygeai/core/feedback/endpoints.py +1 -0
  225. pygeai/core/feedback/models.py +10 -0
  226. pygeai/core/files/__init__.py +0 -0
  227. pygeai/core/files/clients.py +156 -0
  228. pygeai/core/files/endpoints.py +5 -0
  229. pygeai/core/files/managers.py +224 -0
  230. pygeai/core/files/mappers.py +44 -0
  231. pygeai/core/files/models.py +24 -0
  232. pygeai/core/files/responses.py +19 -0
  233. pygeai/core/handlers.py +32 -0
  234. pygeai/core/llm/__init__.py +0 -0
  235. pygeai/core/llm/clients.py +53 -0
  236. pygeai/core/llm/endpoints.py +4 -0
  237. pygeai/core/models.py +799 -0
  238. pygeai/core/plugins/__init__.py +0 -0
  239. pygeai/core/plugins/clients.py +32 -0
  240. pygeai/core/plugins/endpoints.py +1 -0
  241. pygeai/core/plugins/models.py +86 -0
  242. pygeai/core/rerank/__init__.py +0 -0
  243. pygeai/core/rerank/clients.py +35 -0
  244. pygeai/core/rerank/endpoints.py +1 -0
  245. pygeai/core/rerank/managers.py +47 -0
  246. pygeai/core/rerank/mappers.py +23 -0
  247. pygeai/core/rerank/models.py +27 -0
  248. pygeai/core/responses.py +104 -0
  249. pygeai/core/secrets/__init__.py +0 -0
  250. pygeai/core/secrets/clients.py +212 -0
  251. pygeai/core/secrets/endpoints.py +7 -0
  252. pygeai/core/services/llm/__init__.py +0 -0
  253. pygeai/core/services/llm/model.py +186 -0
  254. pygeai/core/services/llm/providers.py +15 -0
  255. pygeai/core/services/response.py +18 -0
  256. pygeai/core/services/rest.py +311 -89
  257. pygeai/core/utils/__init__.py +0 -0
  258. pygeai/core/utils/console.py +83 -0
  259. pygeai/core/utils/parsers.py +32 -0
  260. pygeai/core/utils/validators.py +10 -0
  261. pygeai/dbg/__init__.py +3 -0
  262. pygeai/dbg/debugger.py +870 -0
  263. pygeai/evaluation/__init__.py +0 -0
  264. pygeai/evaluation/clients.py +19 -0
  265. pygeai/evaluation/dataset/__init__.py +0 -0
  266. pygeai/evaluation/dataset/clients.py +514 -0
  267. pygeai/evaluation/dataset/endpoints.py +26 -0
  268. pygeai/evaluation/plan/__init__.py +0 -0
  269. pygeai/evaluation/plan/clients.py +302 -0
  270. pygeai/evaluation/plan/endpoints.py +16 -0
  271. pygeai/evaluation/result/__init__.py +0 -0
  272. pygeai/evaluation/result/clients.py +70 -0
  273. pygeai/evaluation/result/endpoints.py +2 -0
  274. pygeai/flows/__init__.py +0 -0
  275. pygeai/flows/endpoints.py +362 -0
  276. pygeai/flows/models.py +1304 -0
  277. pygeai/gam/__init__.py +0 -0
  278. pygeai/gam/clients.py +178 -0
  279. pygeai/gam/endpoints.py +4 -0
  280. pygeai/health/__init__.py +0 -0
  281. pygeai/health/clients.py +24 -0
  282. pygeai/health/endpoints.py +1 -0
  283. pygeai/lab/__init__.py +0 -0
  284. pygeai/lab/agents/__init__.py +0 -0
  285. pygeai/lab/agents/clients.py +426 -0
  286. pygeai/lab/agents/endpoints.py +12 -0
  287. pygeai/lab/agents/mappers.py +319 -0
  288. pygeai/lab/clients.py +24 -0
  289. pygeai/lab/constants.py +3 -0
  290. pygeai/lab/managers.py +1558 -0
  291. pygeai/lab/models.py +1719 -0
  292. pygeai/lab/processes/__init__.py +0 -0
  293. pygeai/lab/processes/clients.py +1051 -0
  294. pygeai/lab/processes/endpoints.py +26 -0
  295. pygeai/lab/processes/mappers.py +395 -0
  296. pygeai/lab/runners.py +90 -0
  297. pygeai/lab/spec/__init__.py +0 -0
  298. pygeai/lab/spec/loader.py +24 -0
  299. pygeai/lab/spec/parsers.py +39 -0
  300. pygeai/lab/strategies/__init__.py +0 -0
  301. pygeai/lab/strategies/clients.py +212 -0
  302. pygeai/lab/strategies/endpoints.py +5 -0
  303. pygeai/lab/strategies/mappers.py +58 -0
  304. pygeai/lab/tools/__init__.py +0 -0
  305. pygeai/lab/tools/clients.py +465 -0
  306. pygeai/lab/tools/endpoints.py +13 -0
  307. pygeai/lab/tools/mappers.py +131 -0
  308. pygeai/man/__init__.py +1 -0
  309. pygeai/man/man1/__init__.py +1 -0
  310. pygeai/man/man1/geai-proxy.1 +246 -0
  311. pygeai/man/man1/geai.1 +2615 -0
  312. pygeai/migration/__init__.py +33 -0
  313. pygeai/migration/strategies.py +603 -0
  314. pygeai/migration/tools.py +180 -0
  315. pygeai/organization/clients.py +246 -18
  316. pygeai/organization/endpoints.py +17 -8
  317. pygeai/organization/limits/__init__.py +0 -0
  318. pygeai/organization/limits/clients.py +281 -0
  319. pygeai/organization/limits/endpoints.py +15 -0
  320. pygeai/organization/limits/managers.py +331 -0
  321. pygeai/organization/limits/mappers.py +21 -0
  322. pygeai/organization/managers.py +537 -0
  323. pygeai/organization/mappers.py +111 -46
  324. pygeai/organization/responses.py +61 -11
  325. pygeai/proxy/__init__.py +0 -0
  326. pygeai/proxy/clients.py +216 -0
  327. pygeai/proxy/config.py +128 -0
  328. pygeai/proxy/managers.py +232 -0
  329. pygeai/proxy/servers.py +304 -0
  330. pygeai/proxy/tool.py +69 -0
  331. pygeai/tests/admin/__init__.py +0 -0
  332. pygeai/tests/admin/test_clients.py +148 -0
  333. pygeai/tests/analytics/__init__.py +0 -0
  334. pygeai/tests/analytics/test_clients.py +86 -0
  335. pygeai/tests/analytics/test_managers.py +94 -0
  336. pygeai/tests/analytics/test_mappers.py +84 -0
  337. pygeai/tests/analytics/test_responses.py +73 -0
  338. pygeai/tests/assistants/rag/__init__.py +0 -0
  339. pygeai/tests/assistants/rag/test_clients.py +346 -0
  340. pygeai/tests/assistants/rag/test_mappers.py +189 -0
  341. pygeai/tests/assistants/rag/test_models.py +292 -0
  342. pygeai/tests/assistants/test_clients.py +176 -80
  343. pygeai/tests/assistants/test_managers.py +198 -0
  344. pygeai/tests/assistants/test_mappers.py +111 -0
  345. pygeai/tests/auth/__init__.py +0 -0
  346. pygeai/tests/auth/test_clients.py +289 -0
  347. pygeai/tests/auth/test_oauth.py +172 -0
  348. pygeai/tests/auth/test_session_logging.py +150 -0
  349. pygeai/tests/chat/__init__.py +0 -0
  350. pygeai/tests/chat/test_clients.py +393 -0
  351. pygeai/tests/chat/test_iris.py +38 -0
  352. pygeai/tests/chat/test_session.py +62 -0
  353. pygeai/tests/chat/test_ui.py +224 -0
  354. pygeai/tests/cli/__init__.py +0 -0
  355. pygeai/tests/cli/commands/__init__.py +0 -0
  356. pygeai/tests/cli/commands/lab/__init__.py +0 -0
  357. pygeai/tests/cli/commands/lab/test_ai_lab.py +786 -0
  358. pygeai/tests/cli/commands/lab/test_common.py +208 -0
  359. pygeai/tests/cli/commands/lab/test_spec.py +246 -0
  360. pygeai/tests/cli/commands/test_assistant.py +202 -0
  361. pygeai/tests/cli/commands/test_chat.py +130 -0
  362. pygeai/tests/cli/commands/test_common.py +350 -0
  363. pygeai/tests/cli/commands/test_embeddings.py +132 -0
  364. pygeai/tests/cli/commands/test_evaluation.py +656 -0
  365. pygeai/tests/cli/commands/test_feedback.py +65 -0
  366. pygeai/tests/cli/commands/test_files.py +161 -0
  367. pygeai/tests/cli/commands/test_gam.py +201 -0
  368. pygeai/tests/cli/commands/test_llm.py +114 -0
  369. pygeai/tests/cli/commands/test_migrate.py +176 -0
  370. pygeai/tests/cli/commands/test_organization.py +276 -0
  371. pygeai/tests/cli/commands/test_rag.py +266 -0
  372. pygeai/tests/cli/commands/test_rerank.py +110 -0
  373. pygeai/tests/cli/commands/test_secrets.py +171 -0
  374. pygeai/tests/cli/commands/test_show_help.py +41 -0
  375. pygeai/tests/cli/commands/test_usage_limits.py +412 -0
  376. pygeai/tests/cli/commands/test_validators.py +160 -0
  377. pygeai/tests/cli/commands/test_version.py +81 -0
  378. pygeai/tests/cli/docker/__init__.py +0 -0
  379. pygeai/tests/cli/test_credentials_flag.py +316 -0
  380. pygeai/tests/cli/test_error_handler.py +225 -0
  381. pygeai/tests/cli/test_geai_driver.py +154 -0
  382. pygeai/tests/cli/test_parsers.py +154 -0
  383. pygeai/tests/core/base/__init__.py +0 -0
  384. pygeai/tests/core/base/data/__init__.py +0 -0
  385. pygeai/tests/core/base/data/mappers.py +117 -0
  386. pygeai/tests/core/base/data/models.py +312 -0
  387. pygeai/tests/core/base/test_mappers.py +569 -0
  388. pygeai/tests/core/base/test_models.py +261 -0
  389. pygeai/tests/core/base/test_responses.py +53 -0
  390. pygeai/tests/core/common/__init__.py +0 -0
  391. pygeai/tests/core/common/data/__init__.py +0 -0
  392. pygeai/tests/core/common/test_config.py +186 -0
  393. pygeai/tests/core/common/test_decorators.py +69 -0
  394. pygeai/tests/core/embeddings/__init__.py +0 -0
  395. pygeai/tests/core/embeddings/test_clients.py +225 -0
  396. pygeai/tests/core/embeddings/test_managers.py +171 -0
  397. pygeai/tests/core/embeddings/test_mappers.py +142 -0
  398. pygeai/tests/core/feedback/__init__.py +0 -0
  399. pygeai/tests/core/feedback/test_clients.py +64 -0
  400. pygeai/tests/core/files/__init__.py +0 -0
  401. pygeai/tests/core/files/test_clients.py +128 -0
  402. pygeai/tests/core/files/test_managers.py +219 -0
  403. pygeai/tests/core/files/test_mappers.py +137 -0
  404. pygeai/tests/core/files/test_models.py +103 -0
  405. pygeai/tests/core/files/test_responses.py +122 -0
  406. pygeai/tests/core/llm/__init__.py +0 -0
  407. pygeai/tests/core/llm/test_clients.py +142 -0
  408. pygeai/tests/core/plugins/__init__.py +0 -0
  409. pygeai/tests/core/plugins/test_clients.py +66 -0
  410. pygeai/tests/core/rerank/__init__.py +0 -0
  411. pygeai/tests/core/rerank/test_clients.py +76 -0
  412. pygeai/tests/core/rerank/test_managers.py +99 -0
  413. pygeai/tests/core/rerank/test_mappers.py +54 -0
  414. pygeai/tests/core/secrets/__init__.py +0 -0
  415. pygeai/tests/core/secrets/test_clients.py +264 -0
  416. pygeai/tests/core/services/__init__.py +0 -0
  417. pygeai/tests/core/services/test_rest.py +273 -0
  418. pygeai/tests/core/test_handlers.py +66 -0
  419. pygeai/tests/core/utils/__init__.py +0 -0
  420. pygeai/tests/core/utils/test_console.py +80 -0
  421. pygeai/tests/dbg/__init__.py +0 -0
  422. pygeai/tests/dbg/test_debugger.py +591 -0
  423. pygeai/tests/evaluation/__init__.py +0 -0
  424. pygeai/tests/evaluation/dataset/__init__.py +0 -0
  425. pygeai/tests/evaluation/dataset/test_clients.py +265 -0
  426. pygeai/tests/evaluation/plan/__init__.py +0 -0
  427. pygeai/tests/evaluation/plan/test_clients.py +195 -0
  428. pygeai/tests/evaluation/result/__init__.py +0 -0
  429. pygeai/tests/evaluation/result/test_clients.py +66 -0
  430. pygeai/tests/gam/__init__.py +0 -0
  431. pygeai/tests/gam/test_clients.py +195 -0
  432. pygeai/tests/health/__init__.py +0 -0
  433. pygeai/tests/health/test_clients.py +41 -0
  434. pygeai/tests/integration/__init__.py +0 -0
  435. pygeai/tests/integration/assistants/__init__.py +0 -0
  436. pygeai/tests/integration/assistants/rag/__init__.py +0 -0
  437. pygeai/tests/integration/assistants/rag/test_create_rag.py +91 -0
  438. pygeai/tests/integration/chat/__init__.py +0 -0
  439. pygeai/tests/integration/chat/test_generate_image.py +158 -0
  440. pygeai/tests/integration/lab/__init__.py +0 -0
  441. pygeai/tests/integration/lab/agents/__init__.py +0 -0
  442. pygeai/tests/integration/lab/agents/test_agents_list.py +106 -0
  443. pygeai/tests/integration/lab/agents/test_create_agent.py +319 -0
  444. pygeai/tests/integration/lab/agents/test_create_sharing_link.py +70 -0
  445. pygeai/tests/integration/lab/agents/test_delete_agent.py +75 -0
  446. pygeai/tests/integration/lab/agents/test_get_agent.py +94 -0
  447. pygeai/tests/integration/lab/agents/test_publish_agent_revision.py +127 -0
  448. pygeai/tests/integration/lab/agents/test_update_agent.py +250 -0
  449. pygeai/tests/integration/lab/processes/__init__.py +0 -0
  450. pygeai/tests/integration/lab/processes/test_create_process.py +345 -0
  451. pygeai/tests/integration/lab/processes/test_create_task.py +211 -0
  452. pygeai/tests/integration/lab/processes/test_delete_process.py +111 -0
  453. pygeai/tests/integration/lab/processes/test_get_process.py +201 -0
  454. pygeai/tests/integration/lab/processes/test_list_process_instances.py +91 -0
  455. pygeai/tests/integration/lab/processes/test_list_processes.py +138 -0
  456. pygeai/tests/integration/lab/processes/test_publish_process_revision.py +232 -0
  457. pygeai/tests/integration/lab/processes/test_update_process.py +289 -0
  458. pygeai/tests/integration/lab/reasoning_strategies/__init__.py +0 -0
  459. pygeai/tests/integration/lab/reasoning_strategies/test_get_reasoning_strategy.py +70 -0
  460. pygeai/tests/integration/lab/reasoning_strategies/test_list_reasoning_strategies.py +93 -0
  461. pygeai/tests/integration/lab/reasoning_strategies/test_update_reasoning_strategy.py +149 -0
  462. pygeai/tests/integration/lab/tools/__init__.py +0 -0
  463. pygeai/tests/integration/lab/tools/test_create_tool.py +288 -0
  464. pygeai/tests/integration/lab/tools/test_delete_tool.py +87 -0
  465. pygeai/tests/integration/lab/tools/test_get_parameter.py +98 -0
  466. pygeai/tests/integration/lab/tools/test_get_tool.py +91 -0
  467. pygeai/tests/integration/lab/tools/test_list_tools.py +106 -0
  468. pygeai/tests/integration/lab/tools/test_publish_tool_revision.py +119 -0
  469. pygeai/tests/integration/lab/tools/test_set_parameter.py +114 -0
  470. pygeai/tests/integration/lab/tools/test_update_tool.py +267 -0
  471. pygeai/tests/lab/__init__.py +0 -0
  472. pygeai/tests/lab/agents/__init__.py +0 -0
  473. pygeai/tests/lab/agents/test_clients.py +481 -0
  474. pygeai/tests/lab/agents/test_mappers.py +440 -0
  475. pygeai/tests/lab/processes/__init__.py +0 -0
  476. pygeai/tests/lab/processes/test_clients.py +1416 -0
  477. pygeai/tests/lab/processes/test_mappers.py +1092 -0
  478. pygeai/tests/lab/spec/__init__.py +0 -0
  479. pygeai/tests/lab/spec/test_loader.py +59 -0
  480. pygeai/tests/lab/spec/test_parsers.py +182 -0
  481. pygeai/tests/lab/strategies/__init__.py +0 -0
  482. pygeai/tests/lab/strategies/test_clients.py +241 -0
  483. pygeai/tests/lab/strategies/test_mappers.py +132 -0
  484. pygeai/tests/lab/test_managers.py +553 -0
  485. pygeai/tests/lab/test_mappers.py +245 -0
  486. pygeai/tests/lab/test_models.py +1154 -0
  487. pygeai/tests/lab/tools/__init__.py +0 -0
  488. pygeai/tests/lab/tools/test_clients.py +521 -0
  489. pygeai/tests/lab/tools/test_mappers.py +198 -0
  490. pygeai/tests/migration/__init__.py +0 -0
  491. pygeai/tests/migration/test_strategies.py +405 -0
  492. pygeai/tests/migration/test_tools.py +159 -0
  493. pygeai/tests/organization/limits/__init__.py +0 -0
  494. pygeai/tests/organization/limits/test_clients.py +567 -0
  495. pygeai/tests/organization/limits/test_managers.py +402 -0
  496. pygeai/tests/organization/test_clients.py +615 -64
  497. pygeai/tests/organization/test_managers.py +424 -0
  498. pygeai/tests/organization/test_mappers.py +153 -0
  499. pygeai/tests/organization/test_responses.py +137 -0
  500. pygeai/tests/proxy/__init__.py +1 -0
  501. pygeai/tests/proxy/test_clients.py +397 -0
  502. pygeai/tests/proxy/test_config.py +171 -0
  503. pygeai/tests/proxy/test_integration.py +305 -0
  504. pygeai/tests/proxy/test_managers.py +312 -0
  505. pygeai/tests/proxy/test_servers.py +387 -0
  506. pygeai/tests/proxy/test_tool.py +176 -0
  507. pygeai/tests/snippets/__init__.py +0 -0
  508. pygeai/tests/snippets/analytics/__init__.py +0 -0
  509. pygeai/tests/snippets/analytics/get_agent_usage_per_user.py +16 -0
  510. pygeai/tests/snippets/analytics/get_agents_created_and_modified.py +11 -0
  511. pygeai/tests/snippets/analytics/get_average_cost_per_request.py +10 -0
  512. pygeai/tests/snippets/analytics/get_overall_error_rate.py +10 -0
  513. pygeai/tests/snippets/analytics/get_top_10_agents_by_requests.py +12 -0
  514. pygeai/tests/snippets/analytics/get_total_active_users.py +10 -0
  515. pygeai/tests/snippets/analytics/get_total_cost.py +10 -0
  516. pygeai/tests/snippets/analytics/get_total_requests_per_day.py +12 -0
  517. pygeai/tests/snippets/analytics/get_total_tokens.py +12 -0
  518. pygeai/tests/snippets/assistants/__init__.py +0 -0
  519. pygeai/tests/snippets/assistants/create_chat_assistant.py +54 -0
  520. pygeai/tests/snippets/assistants/create_text_assistant.py +51 -0
  521. pygeai/tests/snippets/assistants/data_analyst/__init__.py +0 -0
  522. pygeai/tests/snippets/assistants/data_analyst/extend_and_check.py +100 -0
  523. pygeai/tests/snippets/assistants/data_analyst/extend_dataset.py +9 -0
  524. pygeai/tests/snippets/assistants/data_analyst/get_status.py +9 -0
  525. pygeai/tests/snippets/assistants/file_summarizer_assistant.py +149 -0
  526. pygeai/tests/snippets/assistants/get_assistant_data.py +8 -0
  527. pygeai/tests/snippets/assistants/get_assistant_list.py +7 -0
  528. pygeai/tests/snippets/assistants/rag/__init__.py +0 -0
  529. pygeai/tests/snippets/assistants/rag/create_rag_assistant.py +65 -0
  530. pygeai/tests/snippets/assistants/rag/delete_al_documents.py +7 -0
  531. pygeai/tests/snippets/assistants/rag/delete_document.py +10 -0
  532. pygeai/tests/snippets/assistants/rag/delete_rag_assistant.py +8 -0
  533. pygeai/tests/snippets/assistants/rag/get_document.py +10 -0
  534. pygeai/tests/snippets/assistants/rag/get_documents.py +7 -0
  535. pygeai/tests/snippets/assistants/rag/get_rag_assistant_data.py +8 -0
  536. pygeai/tests/snippets/assistants/rag/update_rag_assistant.py +48 -0
  537. pygeai/tests/snippets/assistants/rag/upload_document.py +19 -0
  538. pygeai/tests/snippets/assistants/send_feedback.py +14 -0
  539. pygeai/tests/snippets/assistants/update_chat_assistant.py +63 -0
  540. pygeai/tests/snippets/auth/__init__.py +0 -0
  541. pygeai/tests/snippets/chat/__init__.py +0 -0
  542. pygeai/tests/snippets/chat/cancel_request.py +7 -0
  543. pygeai/tests/snippets/chat/chat_completion.py +28 -0
  544. pygeai/tests/snippets/chat/chat_completion_1.py +40 -0
  545. pygeai/tests/snippets/chat/chat_completion_2.py +60 -0
  546. pygeai/tests/snippets/chat/chat_completion_3.py +27 -0
  547. pygeai/tests/snippets/chat/chat_completion_4.py +67 -0
  548. pygeai/tests/snippets/chat/chat_completion_streaming.py +63 -0
  549. pygeai/tests/snippets/chat/chat_completion_with_reasoning_effort.py +18 -0
  550. pygeai/tests/snippets/chat/get_request_status.py +7 -0
  551. pygeai/tests/snippets/chat/get_response.py +15 -0
  552. pygeai/tests/snippets/chat/get_response_complete_example.py +67 -0
  553. pygeai/tests/snippets/chat/get_response_streaming.py +20 -0
  554. pygeai/tests/snippets/chat/get_response_with_files.py +16 -0
  555. pygeai/tests/snippets/chat/get_response_with_instructions.py +19 -0
  556. pygeai/tests/snippets/chat/get_response_with_metadata.py +24 -0
  557. pygeai/tests/snippets/chat/get_response_with_parallel_tools.py +58 -0
  558. pygeai/tests/snippets/chat/get_response_with_reasoning.py +21 -0
  559. pygeai/tests/snippets/chat/get_response_with_store.py +38 -0
  560. pygeai/tests/snippets/chat/get_response_with_tools.py +36 -0
  561. pygeai/tests/snippets/chat/get_response_with_truncation.py +24 -0
  562. pygeai/tests/snippets/chat/send_chat_request.py +33 -0
  563. pygeai/tests/snippets/dbg/__init__.py +0 -0
  564. pygeai/tests/snippets/dbg/basic_debugging.py +32 -0
  565. pygeai/tests/snippets/dbg/breakpoint_management.py +48 -0
  566. pygeai/tests/snippets/dbg/file_debugging.py +72 -0
  567. pygeai/tests/snippets/dbg/module_debugging.py +61 -0
  568. pygeai/tests/snippets/dbg/stack_navigation.py +45 -0
  569. pygeai/tests/snippets/dbg/stepping_example.py +40 -0
  570. pygeai/tests/snippets/embeddings/__init__.py +0 -0
  571. pygeai/tests/snippets/embeddings/cache_example.py +31 -0
  572. pygeai/tests/snippets/embeddings/cohere_example.py +41 -0
  573. pygeai/tests/snippets/embeddings/generate_embeddings.py +26 -0
  574. pygeai/tests/snippets/embeddings/openai_base64_example.py +27 -0
  575. pygeai/tests/snippets/embeddings/openai_example.py +30 -0
  576. pygeai/tests/snippets/embeddings/similarity_example.py +42 -0
  577. pygeai/tests/snippets/evaluation/__init__.py +0 -0
  578. pygeai/tests/snippets/evaluation/dataset/__init__.py +0 -0
  579. pygeai/tests/snippets/evaluation/dataset/complete_workflow_example.py +195 -0
  580. pygeai/tests/snippets/evaluation/dataset/create_dataset.py +26 -0
  581. pygeai/tests/snippets/evaluation/dataset/create_dataset_from_file.py +11 -0
  582. pygeai/tests/snippets/evaluation/dataset/create_dataset_row.py +17 -0
  583. pygeai/tests/snippets/evaluation/dataset/create_expected_source.py +18 -0
  584. pygeai/tests/snippets/evaluation/dataset/create_filter_variable.py +19 -0
  585. pygeai/tests/snippets/evaluation/dataset/delete_dataset.py +9 -0
  586. pygeai/tests/snippets/evaluation/dataset/delete_dataset_row.py +10 -0
  587. pygeai/tests/snippets/evaluation/dataset/delete_expected_source.py +15 -0
  588. pygeai/tests/snippets/evaluation/dataset/delete_filter_variable.py +15 -0
  589. pygeai/tests/snippets/evaluation/dataset/get_dataset.py +9 -0
  590. pygeai/tests/snippets/evaluation/dataset/get_dataset_row.py +10 -0
  591. pygeai/tests/snippets/evaluation/dataset/get_expected_source.py +15 -0
  592. pygeai/tests/snippets/evaluation/dataset/get_filter_variable.py +15 -0
  593. pygeai/tests/snippets/evaluation/dataset/list_dataset_rows.py +9 -0
  594. pygeai/tests/snippets/evaluation/dataset/list_datasets.py +6 -0
  595. pygeai/tests/snippets/evaluation/dataset/list_expected_sources.py +10 -0
  596. pygeai/tests/snippets/evaluation/dataset/list_filter_variables.py +10 -0
  597. pygeai/tests/snippets/evaluation/dataset/update_dataset.py +15 -0
  598. pygeai/tests/snippets/evaluation/dataset/update_dataset_row.py +20 -0
  599. pygeai/tests/snippets/evaluation/dataset/update_expected_source.py +18 -0
  600. pygeai/tests/snippets/evaluation/dataset/update_filter_variable.py +19 -0
  601. pygeai/tests/snippets/evaluation/dataset/upload_dataset_rows_file.py +10 -0
  602. pygeai/tests/snippets/evaluation/plan/__init__.py +0 -0
  603. pygeai/tests/snippets/evaluation/plan/add_plan_system_metric.py +13 -0
  604. pygeai/tests/snippets/evaluation/plan/complete_workflow_example.py +136 -0
  605. pygeai/tests/snippets/evaluation/plan/create_evaluation_plan.py +24 -0
  606. pygeai/tests/snippets/evaluation/plan/create_rag_evaluation_plan.py +22 -0
  607. pygeai/tests/snippets/evaluation/plan/delete_evaluation_plan.py +9 -0
  608. pygeai/tests/snippets/evaluation/plan/delete_plan_system_metric.py +13 -0
  609. pygeai/tests/snippets/evaluation/plan/execute_evaluation_plan.py +11 -0
  610. pygeai/tests/snippets/evaluation/plan/get_evaluation_plan.py +9 -0
  611. pygeai/tests/snippets/evaluation/plan/get_plan_system_metric.py +13 -0
  612. pygeai/tests/snippets/evaluation/plan/get_system_metric.py +9 -0
  613. pygeai/tests/snippets/evaluation/plan/list_evaluation_plans.py +7 -0
  614. pygeai/tests/snippets/evaluation/plan/list_plan_system_metrics.py +9 -0
  615. pygeai/tests/snippets/evaluation/plan/list_system_metrics.py +7 -0
  616. pygeai/tests/snippets/evaluation/plan/update_evaluation_plan.py +22 -0
  617. pygeai/tests/snippets/evaluation/plan/update_plan_system_metric.py +14 -0
  618. pygeai/tests/snippets/evaluation/result/__init__.py +0 -0
  619. pygeai/tests/snippets/evaluation/result/complete_workflow_example.py +150 -0
  620. pygeai/tests/snippets/evaluation/result/get_evaluation_result.py +26 -0
  621. pygeai/tests/snippets/evaluation/result/list_evaluation_results.py +17 -0
  622. pygeai/tests/snippets/files/__init__.py +0 -0
  623. pygeai/tests/snippets/files/delete_file.py +9 -0
  624. pygeai/tests/snippets/files/get_file_content.py +10 -0
  625. pygeai/tests/snippets/files/get_file_data.py +9 -0
  626. pygeai/tests/snippets/files/get_file_list.py +6 -0
  627. pygeai/tests/snippets/files/upload_file.py +13 -0
  628. pygeai/tests/snippets/gam/__init__.py +0 -0
  629. pygeai/tests/snippets/gam/gam_access_token.py +87 -0
  630. pygeai/tests/snippets/lab/__init__.py +0 -0
  631. pygeai/tests/snippets/lab/agentic_flow_example_1.py +326 -0
  632. pygeai/tests/snippets/lab/agentic_flow_example_2.py +206 -0
  633. pygeai/tests/snippets/lab/agentic_flow_example_3.py +486 -0
  634. pygeai/tests/snippets/lab/agentic_flow_example_4.py +446 -0
  635. pygeai/tests/snippets/lab/agents/__init__.py +0 -0
  636. pygeai/tests/snippets/lab/agents/create_agent.py +48 -0
  637. pygeai/tests/snippets/lab/agents/create_agent_2.py +48 -0
  638. pygeai/tests/snippets/lab/agents/create_agent_edge_case.py +48 -0
  639. pygeai/tests/snippets/lab/agents/create_agent_with_permissions.py +39 -0
  640. pygeai/tests/snippets/lab/agents/create_agent_with_properties.py +46 -0
  641. pygeai/tests/snippets/lab/agents/create_agent_without_instructions.py +48 -0
  642. pygeai/tests/snippets/lab/agents/delete_agent.py +12 -0
  643. pygeai/tests/snippets/lab/agents/get_agent.py +24 -0
  644. pygeai/tests/snippets/lab/agents/get_agent_with_new_fields.py +62 -0
  645. pygeai/tests/snippets/lab/agents/get_sharing_link.py +13 -0
  646. pygeai/tests/snippets/lab/agents/list_agents.py +18 -0
  647. pygeai/tests/snippets/lab/agents/publish_agent_revision.py +12 -0
  648. pygeai/tests/snippets/lab/agents/update_agent.py +50 -0
  649. pygeai/tests/snippets/lab/agents/update_agent_properties.py +50 -0
  650. pygeai/tests/snippets/lab/assistant_to_agent.py +191 -0
  651. pygeai/tests/snippets/lab/crud_ui.py +462 -0
  652. pygeai/tests/snippets/lab/processes/__init__.py +0 -0
  653. pygeai/tests/snippets/lab/processes/create_process.py +24 -0
  654. pygeai/tests/snippets/lab/processes/create_task.py +8 -0
  655. pygeai/tests/snippets/lab/processes/jobs/__init__.py +0 -0
  656. pygeai/tests/snippets/lab/processes/jobs/list_jobs.py +21 -0
  657. pygeai/tests/snippets/lab/processes/kbs/__init__.py +0 -0
  658. pygeai/tests/snippets/lab/processes/kbs/create_kb.py +18 -0
  659. pygeai/tests/snippets/lab/processes/kbs/get_kb.py +26 -0
  660. pygeai/tests/snippets/lab/processes/kbs/list_kbs.py +30 -0
  661. pygeai/tests/snippets/lab/processes/kbs/try_all.py +73 -0
  662. pygeai/tests/snippets/lab/processes/list_processes.py +10 -0
  663. pygeai/tests/snippets/lab/runner_1.py +212 -0
  664. pygeai/tests/snippets/lab/samples/__init__.py +0 -0
  665. pygeai/tests/snippets/lab/samples/summarize_files.py +162 -0
  666. pygeai/tests/snippets/lab/strategies/__init__.py +0 -0
  667. pygeai/tests/snippets/lab/strategies/create_reasoning_strategy.py +22 -0
  668. pygeai/tests/snippets/lab/strategies/get_reasoning_strategy.py +10 -0
  669. pygeai/tests/snippets/lab/strategies/list_reasoning_strategies.py +16 -0
  670. pygeai/tests/snippets/lab/strategies/update_reasoning_strategy.py +26 -0
  671. pygeai/tests/snippets/lab/tools/__init__.py +0 -0
  672. pygeai/tests/snippets/lab/tools/create_tool.py +48 -0
  673. pygeai/tests/snippets/lab/tools/create_tool_edge_case.py +50 -0
  674. pygeai/tests/snippets/lab/tools/delete_tool.py +21 -0
  675. pygeai/tests/snippets/lab/tools/get_parameter.py +21 -0
  676. pygeai/tests/snippets/lab/tools/get_tool.py +22 -0
  677. pygeai/tests/snippets/lab/tools/list_tools.py +23 -0
  678. pygeai/tests/snippets/lab/tools/publish_tool_revision.py +13 -0
  679. pygeai/tests/snippets/lab/tools/set_parameters.py +33 -0
  680. pygeai/tests/snippets/lab/tools/update_tool.py +52 -0
  681. pygeai/tests/snippets/lab/use_cases/__init__.py +0 -0
  682. pygeai/tests/snippets/lab/use_cases/c_code_fixer_agent_flow.py +238 -0
  683. pygeai/tests/snippets/lab/use_cases/create_cli_expert.py +1640 -0
  684. pygeai/tests/snippets/lab/use_cases/create_lab_expert.py +4541 -0
  685. pygeai/tests/snippets/lab/use_cases/create_tool_headless_web_browser.py +133 -0
  686. pygeai/tests/snippets/lab/use_cases/create_web_designer.py +189 -0
  687. pygeai/tests/snippets/lab/use_cases/create_web_reader.py +185 -0
  688. pygeai/tests/snippets/lab/use_cases/file_summarizer_example.py +157 -0
  689. pygeai/tests/snippets/lab/use_cases/file_summarizer_example_2.py +157 -0
  690. pygeai/tests/snippets/lab/use_cases/update_cli_expert.py +1773 -0
  691. pygeai/tests/snippets/lab/use_cases/update_lab_expert.py +4541 -0
  692. pygeai/tests/snippets/lab/use_cases/update_web_designer.py +188 -0
  693. pygeai/tests/snippets/lab/use_cases/update_web_reader.py +195 -0
  694. pygeai/tests/snippets/lab/use_cases/update_web_reader_with_tool.py +210 -0
  695. pygeai/tests/snippets/migrate/__init__.py +45 -0
  696. pygeai/tests/snippets/migrate/agent_migration.py +110 -0
  697. pygeai/tests/snippets/migrate/assistant_migration.py +64 -0
  698. pygeai/tests/snippets/migrate/orchestrator_examples.py +179 -0
  699. pygeai/tests/snippets/migrate/process_migration.py +64 -0
  700. pygeai/tests/snippets/migrate/project_migration.py +42 -0
  701. pygeai/tests/snippets/migrate/tool_migration.py +64 -0
  702. pygeai/tests/snippets/organization/__init__.py +0 -0
  703. pygeai/tests/snippets/organization/add_project_member.py +10 -0
  704. pygeai/tests/snippets/organization/add_project_member_batch.py +44 -0
  705. pygeai/tests/snippets/organization/create_project.py +23 -0
  706. pygeai/tests/snippets/organization/delete_project.py +7 -0
  707. pygeai/tests/snippets/organization/export_request_data.py +7 -0
  708. pygeai/tests/snippets/organization/get_memberships.py +12 -0
  709. pygeai/tests/snippets/organization/get_organization_members.py +6 -0
  710. pygeai/tests/snippets/organization/get_project_data.py +7 -0
  711. pygeai/tests/snippets/organization/get_project_list.py +8 -0
  712. pygeai/tests/snippets/organization/get_project_members.py +6 -0
  713. pygeai/tests/snippets/organization/get_project_memberships.py +12 -0
  714. pygeai/tests/snippets/organization/get_project_roles.py +6 -0
  715. pygeai/tests/snippets/organization/get_project_tokens.py +7 -0
  716. pygeai/tests/snippets/organization/update_project.py +14 -0
  717. pygeai/tests/snippets/rerank/__init__.py +0 -0
  718. pygeai/tests/snippets/rerank/rerank_chunks.py +19 -0
  719. pygeai/tests/snippets/secrets/__init__.py +0 -0
  720. pygeai/tests/snippets/usage_limit/__init__.py +0 -0
  721. pygeai/tests/snippets/usage_limit/delete_usage_limit.py +16 -0
  722. pygeai/tests/snippets/usage_limit/get_all_usage_limit_from_organization.py +12 -0
  723. pygeai/tests/snippets/usage_limit/get_usage_limit_from_organization.py +11 -0
  724. pygeai/tests/snippets/usage_limit/get_usage_limit_from_project.py +13 -0
  725. pygeai/tests/snippets/usage_limit/set_usage_limit_organization.py +22 -0
  726. pygeai/tests/snippets/usage_limit/set_usage_limit_project.py +23 -0
  727. pygeai/tests/snippets/usage_limit/update_usage_limit_organization.py +23 -0
  728. pygeai/tests/snippets/usage_limit/update_usage_limit_project.py +24 -0
  729. pygeai/vendor/a2a/__init__.py +1 -0
  730. pygeai/vendor/a2a/auth/__init__.py +0 -0
  731. pygeai/vendor/a2a/auth/user.py +31 -0
  732. pygeai/vendor/a2a/client/__init__.py +19 -0
  733. pygeai/vendor/a2a/client/client.py +425 -0
  734. pygeai/vendor/a2a/client/errors.py +33 -0
  735. pygeai/vendor/a2a/client/helpers.py +22 -0
  736. pygeai/vendor/a2a/py.typed +0 -0
  737. pygeai/vendor/a2a/server/__init__.py +1 -0
  738. pygeai/vendor/a2a/server/agent_execution/__init__.py +18 -0
  739. pygeai/vendor/a2a/server/agent_execution/agent_executor.py +44 -0
  740. pygeai/vendor/a2a/server/agent_execution/context.py +155 -0
  741. pygeai/vendor/a2a/server/agent_execution/request_context_builder.py +20 -0
  742. pygeai/vendor/a2a/server/agent_execution/simple_request_context_builder.py +77 -0
  743. pygeai/vendor/a2a/server/apps/__init__.py +16 -0
  744. pygeai/vendor/a2a/server/apps/jsonrpc/__init__.py +16 -0
  745. pygeai/vendor/a2a/server/apps/jsonrpc/fastapi_app.py +88 -0
  746. pygeai/vendor/a2a/server/apps/jsonrpc/jsonrpc_app.py +426 -0
  747. pygeai/vendor/a2a/server/apps/jsonrpc/starlette_app.py +123 -0
  748. pygeai/vendor/a2a/server/context.py +23 -0
  749. pygeai/vendor/a2a/server/events/__init__.py +21 -0
  750. pygeai/vendor/a2a/server/events/event_consumer.py +149 -0
  751. pygeai/vendor/a2a/server/events/event_queue.py +156 -0
  752. pygeai/vendor/a2a/server/events/in_memory_queue_manager.py +85 -0
  753. pygeai/vendor/a2a/server/events/queue_manager.py +35 -0
  754. pygeai/vendor/a2a/server/request_handlers/__init__.py +20 -0
  755. pygeai/vendor/a2a/server/request_handlers/default_request_handler.py +435 -0
  756. pygeai/vendor/a2a/server/request_handlers/jsonrpc_handler.py +327 -0
  757. pygeai/vendor/a2a/server/request_handlers/request_handler.py +161 -0
  758. pygeai/vendor/a2a/server/request_handlers/response_helpers.py +133 -0
  759. pygeai/vendor/a2a/server/tasks/__init__.py +20 -0
  760. pygeai/vendor/a2a/server/tasks/inmemory_push_notifier.py +62 -0
  761. pygeai/vendor/a2a/server/tasks/inmemory_task_store.py +51 -0
  762. pygeai/vendor/a2a/server/tasks/push_notifier.py +25 -0
  763. pygeai/vendor/a2a/server/tasks/result_aggregator.py +151 -0
  764. pygeai/vendor/a2a/server/tasks/task_manager.py +253 -0
  765. pygeai/vendor/a2a/server/tasks/task_store.py +22 -0
  766. pygeai/vendor/a2a/server/tasks/task_updater.py +155 -0
  767. pygeai/vendor/a2a/types.py +1624 -0
  768. pygeai/vendor/a2a/utils/__init__.py +40 -0
  769. pygeai/vendor/a2a/utils/artifact.py +72 -0
  770. pygeai/vendor/a2a/utils/errors.py +69 -0
  771. pygeai/vendor/a2a/utils/helpers.py +176 -0
  772. pygeai/vendor/a2a/utils/message.py +83 -0
  773. pygeai/vendor/a2a/utils/task.py +57 -0
  774. pygeai/vendor/a2a/utils/telemetry.py +299 -0
  775. pygeai-0.6.0b15.dist-info/METADATA +205 -0
  776. pygeai-0.6.0b15.dist-info/RECORD +799 -0
  777. {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info}/WHEEL +1 -1
  778. pygeai-0.6.0b15.dist-info/entry_points.txt +5 -0
  779. {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info/licenses}/LICENSE +13 -1
  780. {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info}/top_level.txt +0 -1
  781. docs/source/conf.py +0 -45
  782. pygeai/core/clients.py +0 -240
  783. pygeai/tests/core/test_clients.py +0 -49
  784. pygeai-0.1.6.dist-info/METADATA +0 -92
  785. pygeai-0.1.6.dist-info/RECORD +0 -65
  786. pygeai-0.1.6.dist-info/SOURCES.sync-conflict-20241223-145950-3QD4F42.txt +0 -41
  787. pygeai-0.1.6.dist-info/entry_points.txt +0 -2
  788. /pygeai/{agent → analytics}/__init__.py +0 -0
@@ -0,0 +1,1198 @@
1
+ from typing import Tuple, Dict, Any, Optional, List
2
+ from pygeai import logger
3
+ from pygeai.cli.commands import Command, Option, ArgumentsEnum
4
+ from pygeai.cli.commands.builders import build_help_text
5
+ from pygeai.cli.texts.help import MIGRATE_HELP_TEXT
6
+ from pygeai.core.common.exceptions import MissingRequirementException
7
+ from pygeai.core.utils.console import Console
8
+ from pygeai.lab.managers import AILabManager
9
+ from pygeai.lab.models import FilterSettings
10
+ from pygeai.assistant.managers import AssistantManager
11
+ from pygeai.assistant.rag.clients import RAGAssistantClient
12
+ from pygeai.assistant.rag.mappers import RAGAssistantMapper
13
+ from pygeai.core.files.managers import FileManager
14
+ from pygeai.core.secrets.clients import SecretClient
15
+ from pygeai.migration.strategies import (
16
+ ProjectMigrationStrategy,
17
+ AgentMigrationStrategy,
18
+ ToolMigrationStrategy,
19
+ AgenticProcessMigrationStrategy,
20
+ TaskMigrationStrategy,
21
+ UsageLimitMigrationStrategy,
22
+ RAGAssistantMigrationStrategy,
23
+ FileMigrationStrategy,
24
+ SecretMigrationStrategy
25
+ )
26
+ from pygeai.migration.tools import MigrationTool, MigrationPlan, MigrationOrchestrator
27
+ from pygeai.admin.clients import AdminClient
28
+
29
+
30
+ def show_help() -> None:
31
+ """
32
+ Displays help text in stdout.
33
+ """
34
+ help_text = build_help_text(migrate_commands, MIGRATE_HELP_TEXT)
35
+ Console.write_stdout(help_text)
36
+
37
+
38
+ def prompt_with_retry(
39
+ prompt_message: str,
40
+ valid_choices: Optional[list] = None,
41
+ allow_empty: bool = False
42
+ ) -> str:
43
+ """
44
+ Prompt user for input with validation and retry logic.
45
+
46
+ :param prompt_message: Message to display when prompting
47
+ :param valid_choices: Optional list of valid input choices
48
+ :param allow_empty: Whether to allow empty input
49
+ :return: User's validated input string
50
+ """
51
+ while True:
52
+ user_input = input(prompt_message).strip()
53
+
54
+ if not user_input and not allow_empty:
55
+ Console.write_stdout("Error: Input cannot be empty. Please try again.")
56
+ continue
57
+
58
+ if valid_choices and user_input not in valid_choices:
59
+ Console.write_stdout(f"Error: Invalid choice '{user_input}'. Valid options: {', '.join(valid_choices)}")
60
+ continue
61
+
62
+ return user_input
63
+
64
+
65
+ def prompt_resource_selection(
66
+ resource_type: str,
67
+ items: list,
68
+ id_field: str = "id",
69
+ name_field: str = "name"
70
+ ) -> Optional[str]:
71
+ """
72
+ Display a list of resources and let the user select which ones to migrate.
73
+
74
+ :param resource_type: Type of resource being selected (for display purposes)
75
+ :param items: List of resource items to display
76
+ :param id_field: Name of the attribute containing the resource ID
77
+ :param name_field: Name of the attribute containing the resource name
78
+ :return: Comma-separated string of selected IDs, 'all' for all resources, or None to cancel
79
+ """
80
+ if not items:
81
+ Console.write_stdout(f"No {resource_type} found.")
82
+ return None
83
+
84
+ Console.write_stdout(f"\nAvailable {resource_type}:")
85
+ Console.write_stdout(" 0. Cancel (don't migrate this resource type)")
86
+
87
+ for idx, item in enumerate(items, 1):
88
+ item_id = getattr(item, id_field, None)
89
+ item_name = getattr(item, name_field, None) if hasattr(item, name_field) else None
90
+ if item_name:
91
+ Console.write_stdout(f" {idx}. {item_name} (ID: {item_id})")
92
+ else:
93
+ Console.write_stdout(f" {idx}. {item_id}")
94
+
95
+ while True:
96
+ selection = input(f"\nSelect {resource_type} (comma-separated numbers, or empty for all): ").strip()
97
+
98
+ if not selection:
99
+ return "all"
100
+
101
+ if selection == "0":
102
+ return None
103
+
104
+ try:
105
+ indices = [int(x.strip()) for x in selection.split(",")]
106
+ if any(i < 0 or i > len(items) for i in indices):
107
+ Console.write_stdout(f"Error: Invalid selection. Numbers must be between 0 and {len(items)}.")
108
+ continue
109
+
110
+ if 0 in indices:
111
+ return None
112
+
113
+ selected_ids = [getattr(items[i-1], id_field) for i in indices]
114
+ return ",".join(str(sid) for sid in selected_ids)
115
+ except (ValueError, IndexError) as e:
116
+ Console.write_stdout(f"Error: Invalid input format. Please enter comma-separated numbers.")
117
+ continue
118
+
119
+
120
+ def get_source_configuration() -> Tuple[str, str, str, Optional[str]]:
121
+ """
122
+ Prompt user for source configuration and retrieve organization ID.
123
+
124
+ :return: Tuple of (api_key, instance_url, project_id, organization_id)
125
+ """
126
+ Console.write_stdout("\n--- Source Configuration ---")
127
+ from_api_key = prompt_with_retry("Source API key: ")
128
+ from_instance = prompt_with_retry("Source instance URL: ")
129
+ from_project_id = prompt_with_retry("Source project ID: ")
130
+
131
+ admin_client = AdminClient(api_key=from_api_key, base_url=from_instance)
132
+ source_token_info = admin_client.validate_api_token()
133
+ from_organization_id = source_token_info.get("organizationId")
134
+
135
+ return from_api_key, from_instance, from_project_id, from_organization_id
136
+
137
+
138
+ def get_destination_configuration(
139
+ same_instance: bool,
140
+ from_instance: str,
141
+ from_api_key: str,
142
+ from_organization_id: Optional[str],
143
+ creating_project: bool
144
+ ) -> Tuple[str, Optional[str], Optional[str]]:
145
+ """
146
+ Configure destination instance settings based on migration type.
147
+
148
+ :param same_instance: Whether migration is within the same instance
149
+ :param from_instance: Source instance URL
150
+ :param from_api_key: Source API key
151
+ :param from_organization_id: Source organization ID
152
+ :param creating_project: Whether a new project will be created
153
+ :return: Tuple of (instance_url, api_key, organization_id)
154
+ """
155
+ if same_instance:
156
+ to_instance = from_instance
157
+ to_organization_id = from_organization_id
158
+ Console.write_stdout(f"Destination instance: {to_instance} (same as source)")
159
+ Console.write_stdout(f"Destination organization ID: {to_organization_id} (same as source)")
160
+
161
+ if creating_project:
162
+ to_api_key = None
163
+ Console.write_stdout("Destination API key: (will be created after project creation)")
164
+ else:
165
+ to_api_key = prompt_with_retry("Destination API key: ")
166
+ else:
167
+ Console.write_stdout("\n--- Destination Configuration ---")
168
+ to_instance = prompt_with_retry("Destination instance URL: ")
169
+
170
+ if creating_project:
171
+ to_api_key = None
172
+ to_organization_id = None
173
+ Console.write_stdout("Destination API key: (will be created after project creation)")
174
+ Console.write_stdout("Destination organization ID: (will be retrieved after project creation)")
175
+ else:
176
+ to_api_key = prompt_with_retry("Destination API key: ")
177
+ dest_admin_client = AdminClient(api_key=to_api_key, base_url=to_instance)
178
+ dest_token_info = dest_admin_client.validate_api_token()
179
+ to_organization_id = dest_token_info.get("organizationId")
180
+
181
+ return to_instance, to_api_key, to_organization_id
182
+
183
+
184
+ def get_project_creation_info(same_instance: bool) -> Tuple[Optional[str], Optional[str], Optional[str], Optional[str], Optional[str]]:
185
+ """
186
+ Prompt user for project creation information.
187
+
188
+ :param same_instance: Whether migration is within the same instance
189
+ :return: Tuple of (from_org_api_key, to_org_api_key, project_name, admin_email, project_id)
190
+ """
191
+ create_project = prompt_with_retry(
192
+ "Create new destination project? (y/n): ",
193
+ valid_choices=["y", "n"]
194
+ )
195
+
196
+ from_organization_api_key = None
197
+ to_organization_api_key = None
198
+ to_project_name = None
199
+ admin_email = None
200
+ to_project_id = None
201
+
202
+ if create_project == "y":
203
+ from_organization_api_key = prompt_with_retry("Source organization API key: ")
204
+ if same_instance:
205
+ to_organization_api_key = from_organization_api_key
206
+ Console.write_stdout("Destination organization API key: (same as source)")
207
+ else:
208
+ to_organization_api_key = prompt_with_retry("Destination organization API key: ")
209
+ to_project_name = prompt_with_retry("New project name: ")
210
+ admin_email = prompt_with_retry("Admin email: ")
211
+ else:
212
+ to_project_id = prompt_with_retry("Destination project ID: ")
213
+
214
+ return from_organization_api_key, to_organization_api_key, to_project_name, admin_email, to_project_id
215
+
216
+
217
+ def select_resource_types() -> List[int]:
218
+ """
219
+ Prompt user to select which resource types to migrate.
220
+
221
+ :return: List of integers representing selected resource types (1-8)
222
+ """
223
+ Console.write_stdout("\n--- Resource Type Selection ---")
224
+ Console.write_stdout("Which resource types do you want to migrate?")
225
+ Console.write_stdout(" 1. Agents")
226
+ Console.write_stdout(" 2. Tools")
227
+ Console.write_stdout(" 3. Agentic Processes")
228
+ Console.write_stdout(" 4. Tasks")
229
+ Console.write_stdout(" 5. RAG Assistants")
230
+ Console.write_stdout(" 6. Files")
231
+ Console.write_stdout(" 7. Usage Limits")
232
+ Console.write_stdout(" 8. Secrets")
233
+
234
+ while True:
235
+ resource_choice = input("\nSelect resource types (comma-separated numbers, or empty for all): ").strip()
236
+ if not resource_choice:
237
+ return [1, 2, 3, 4, 5, 6, 7, 8]
238
+ try:
239
+ resource_types = [int(x.strip()) for x in resource_choice.split(",")]
240
+ if any(i < 1 or i > 8 for i in resource_types):
241
+ Console.write_stdout("Error: Invalid selection. Numbers must be between 1 and 8.")
242
+ continue
243
+ return resource_types
244
+ except ValueError:
245
+ Console.write_stdout("Error: Invalid input format. Please enter comma-separated numbers.")
246
+ continue
247
+
248
+
249
+ def fetch_and_select_agents(lab_manager: AILabManager) -> Optional[str]:
250
+ """
251
+ Fetch and prompt user to select agents for migration.
252
+
253
+ :param lab_manager: AI Lab manager instance
254
+ :return: Comma-separated IDs, 'all', or None
255
+ """
256
+ try:
257
+ agent_list = lab_manager.get_agent_list(FilterSettings(count=1000))
258
+ agents = [a for a in agent_list.agents if a.id]
259
+ if agents:
260
+ selection = prompt_resource_selection("agents", agents, id_field="id", name_field="name")
261
+ return selection
262
+ except Exception as e:
263
+ Console.write_stdout(f"Warning: Could not retrieve agents: {e}")
264
+ return None
265
+
266
+
267
+ def fetch_and_select_tools(lab_manager: AILabManager) -> Optional[str]:
268
+ """
269
+ Fetch and prompt user to select tools for migration.
270
+
271
+ :param lab_manager: AI Lab manager instance
272
+ :return: Comma-separated IDs, 'all', or None
273
+ """
274
+ try:
275
+ tool_list = lab_manager.list_tools(FilterSettings(count=1000))
276
+ tools = [t for t in tool_list.tools if t.id]
277
+ if tools:
278
+ selection = prompt_resource_selection("tools", tools, id_field="id", name_field="name")
279
+ return selection
280
+ except Exception as e:
281
+ Console.write_stdout(f"Warning: Could not retrieve tools: {e}")
282
+ return None
283
+
284
+
285
+ def fetch_and_select_processes(lab_manager: AILabManager) -> Optional[str]:
286
+ """
287
+ Fetch and prompt user to select processes for migration.
288
+
289
+ :param lab_manager: AI Lab manager instance
290
+ :return: Comma-separated IDs, 'all', or None
291
+ """
292
+ try:
293
+ process_list = lab_manager.list_processes(FilterSettings(count=1000))
294
+ processes = [p for p in process_list.processes if p.id]
295
+ if processes:
296
+ selection = prompt_resource_selection("agentic processes", processes, id_field="id", name_field="name")
297
+ return selection
298
+ except Exception as e:
299
+ Console.write_stdout(f"Warning: Could not retrieve agentic processes: {e}")
300
+ return None
301
+
302
+
303
+ def fetch_and_select_tasks(lab_manager: AILabManager) -> Optional[str]:
304
+ """
305
+ Fetch and prompt user to select tasks for migration.
306
+
307
+ :param lab_manager: AI Lab manager instance
308
+ :return: Comma-separated IDs, 'all', or None
309
+ """
310
+ try:
311
+ task_list = lab_manager.list_tasks(FilterSettings(count=1000))
312
+ tasks = [t for t in task_list.tasks if t.id]
313
+ if tasks:
314
+ selection = prompt_resource_selection("tasks", tasks, id_field="id", name_field="name")
315
+ return selection
316
+ except Exception as e:
317
+ Console.write_stdout(f"Warning: Could not retrieve tasks: {e}")
318
+ return None
319
+
320
+
321
+ def fetch_and_select_rag_assistants(from_api_key: str, from_instance: str) -> Optional[str]:
322
+ """
323
+ Fetch and prompt user to select RAG assistants for migration.
324
+
325
+ :param from_api_key: Source API key
326
+ :param from_instance: Source instance URL
327
+ :return: Comma-separated names, 'all', or None
328
+ """
329
+ try:
330
+ rag_client = RAGAssistantClient(api_key=from_api_key, base_url=from_instance)
331
+ assistant_data = rag_client.get_assistants_from_project()
332
+ assistants_raw = assistant_data.get("assistants", [])
333
+ assistant_list = [RAGAssistantMapper.map_to_rag_assistant(a) for a in assistants_raw] if assistants_raw else []
334
+ if assistant_list:
335
+ selection = prompt_resource_selection("RAG assistants", assistant_list, id_field="name", name_field="name")
336
+ return selection
337
+ except Exception as e:
338
+ Console.write_stdout(f"Warning: Could not retrieve RAG assistants: {e}")
339
+ return None
340
+
341
+
342
+ def fetch_and_select_files(
343
+ from_api_key: str,
344
+ from_instance: str,
345
+ from_organization_id: str,
346
+ from_project_id: str
347
+ ) -> Optional[str]:
348
+ """
349
+ Fetch and prompt user to select files for migration.
350
+
351
+ :param from_api_key: Source API key
352
+ :param from_instance: Source instance URL
353
+ :param from_organization_id: Source organization ID
354
+ :param from_project_id: Source project ID
355
+ :return: Comma-separated file IDs, 'all', or None
356
+ """
357
+ try:
358
+ file_manager = FileManager(
359
+ api_key=from_api_key,
360
+ base_url=from_instance,
361
+ organization_id=from_organization_id,
362
+ project_id=from_project_id
363
+ )
364
+ file_list_response = file_manager.get_file_list()
365
+ files = [f for f in file_list_response.files if f.id]
366
+ if files:
367
+ selection = prompt_resource_selection("files", files, id_field="id", name_field="filename")
368
+ return selection
369
+ except Exception as e:
370
+ Console.write_stdout(f"Warning: Could not retrieve files: {e}")
371
+ return None
372
+
373
+
374
+ def fetch_and_select_secrets(from_api_key: str, from_instance: str) -> Optional[str]:
375
+ """
376
+ Fetch and prompt user to select secrets for migration.
377
+
378
+ :param from_api_key: Source API key
379
+ :param from_instance: Source instance URL
380
+ :return: Comma-separated secret IDs, 'all', or None
381
+ """
382
+ try:
383
+ secret_client = SecretClient(api_key=from_api_key, base_url=from_instance)
384
+ secrets_data = secret_client.list_secrets(count=1000)
385
+ secrets_list = secrets_data.get("secrets", []) if isinstance(secrets_data, dict) else []
386
+
387
+ if secrets_list:
388
+ secrets_objects = [type('obj', (object,), {'id': s.get('id'), 'name': s.get('name')})()
389
+ for s in secrets_list if s.get('id')]
390
+ selection = prompt_resource_selection("secrets", secrets_objects, id_field="id", name_field="name")
391
+ return selection
392
+ except Exception as e:
393
+ Console.write_stdout(f"Warning: Could not retrieve secrets: {e}")
394
+ return None
395
+
396
+
397
+ def handle_usage_limits_keys(
398
+ same_instance: bool,
399
+ from_organization_api_key: Optional[str],
400
+ to_organization_api_key: Optional[str]
401
+ ) -> Tuple[str, str]:
402
+ """
403
+ Ensure organization API keys are available for usage limits migration.
404
+
405
+ :param same_instance: Whether migration is within the same instance
406
+ :param from_organization_api_key: Source organization API key (may be None)
407
+ :param to_organization_api_key: Destination organization API key (may be None)
408
+ :return: Tuple of (from_org_api_key, to_org_api_key)
409
+ """
410
+ if not from_organization_api_key:
411
+ from_organization_api_key = prompt_with_retry("Source organization API key (required for usage limits): ")
412
+ if same_instance:
413
+ to_organization_api_key = from_organization_api_key
414
+ elif not to_organization_api_key:
415
+ to_organization_api_key = prompt_with_retry("Destination organization API key (required for usage limits): ")
416
+
417
+ return from_organization_api_key, to_organization_api_key
418
+
419
+
420
+ def show_summary_and_confirm(
421
+ from_instance: str,
422
+ from_project_id: str,
423
+ to_instance: str,
424
+ to_project_name: Optional[str],
425
+ to_project_id: Optional[str],
426
+ selected_resources: Dict[str, Any]
427
+ ) -> Tuple[bool, bool]:
428
+ """
429
+ Display migration summary and prompt user for confirmation and error handling preference.
430
+
431
+ :param from_instance: Source instance URL
432
+ :param from_project_id: Source project ID
433
+ :param to_instance: Destination instance URL
434
+ :param to_project_name: Destination project name (if creating new project)
435
+ :param to_project_id: Destination project ID (if using existing project)
436
+ :param selected_resources: Dictionary of selected resources to migrate
437
+ :return: Tuple of (confirmation, stop_on_error) - whether user confirmed migration and whether to stop on errors
438
+ """
439
+ Console.write_stdout("\n--- Migration Summary ---")
440
+ Console.write_stdout(f"Source: {from_instance} / Project: {from_project_id}")
441
+ Console.write_stdout(f"Destination: {to_instance} / Project: {to_project_name or to_project_id}")
442
+ Console.write_stdout(f"Resources: {', '.join(selected_resources.keys()) if selected_resources else 'None'}")
443
+ Console.write_stdout("")
444
+
445
+ stop_on_error_response = prompt_with_retry("Stop migration on first error? (Y/n): ", valid_choices=["y", "n", "Y", "N", ""])
446
+ stop_on_error = stop_on_error_response.lower() != "n"
447
+
448
+ confirm = prompt_with_retry("Proceed with migration? (y/n): ", valid_choices=["y", "n"])
449
+ return confirm == "y", stop_on_error
450
+
451
+
452
+ def build_option_list_and_execute(
453
+ from_api_key: str,
454
+ from_instance: str,
455
+ from_project_id: str,
456
+ from_organization_id: Optional[str],
457
+ from_organization_api_key: Optional[str],
458
+ to_api_key: Optional[str],
459
+ to_instance: str,
460
+ to_project_id: Optional[str],
461
+ to_organization_id: Optional[str],
462
+ to_organization_api_key: Optional[str],
463
+ to_project_name: Optional[str],
464
+ admin_email: Optional[str],
465
+ selected_resources: Dict[str, Any],
466
+ stop_on_error: bool
467
+ ) -> None:
468
+ """
469
+ Build option list from interactive mode selections and execute migration.
470
+
471
+ :param from_api_key: Source API key
472
+ :param from_instance: Source instance URL
473
+ :param from_project_id: Source project ID
474
+ :param from_organization_id: Source organization ID
475
+ :param from_organization_api_key: Source organization API key
476
+ :param to_api_key: Destination API key
477
+ :param to_instance: Destination instance URL
478
+ :param to_project_id: Destination project ID
479
+ :param to_organization_id: Destination organization ID
480
+ :param to_organization_api_key: Destination organization API key
481
+ :param to_project_name: New project name (if creating)
482
+ :param admin_email: Admin email (if creating project)
483
+ :param selected_resources: Dictionary of selected resources to migrate
484
+ :param stop_on_error: Whether to stop migration on first error
485
+ """
486
+ option_list = []
487
+ option_list.append((type('obj', (object,), {'name': 'from_api_key'})(), from_api_key))
488
+ option_list.append((type('obj', (object,), {'name': 'from_instance'})(), from_instance))
489
+ option_list.append((type('obj', (object,), {'name': 'from_project_id'})(), from_project_id))
490
+ option_list.append((type('obj', (object,), {'name': 'from_organization_api_key'})(), from_organization_api_key))
491
+
492
+ if from_organization_id:
493
+ option_list.append((type('obj', (object,), {'name': 'from_organization_id'})(), from_organization_id))
494
+
495
+ option_list.append((type('obj', (object,), {'name': 'to_api_key'})(), to_api_key))
496
+ option_list.append((type('obj', (object,), {'name': 'to_instance'})(), to_instance))
497
+ option_list.append((type('obj', (object,), {'name': 'to_organization_api_key'})(), to_organization_api_key))
498
+
499
+ if to_project_id:
500
+ option_list.append((type('obj', (object,), {'name': 'to_project_id'})(), to_project_id))
501
+ if to_project_name:
502
+ option_list.append((type('obj', (object,), {'name': 'to_project_name'})(), to_project_name))
503
+ if admin_email:
504
+ option_list.append((type('obj', (object,), {'name': 'admin_email'})(), admin_email))
505
+ if to_organization_id:
506
+ option_list.append((type('obj', (object,), {'name': 'to_organization_id'})(), to_organization_id))
507
+
508
+ for resource_type, value in selected_resources.items():
509
+ option_list.append((type('obj', (object,), {'name': resource_type})(), value))
510
+
511
+ option_list.append((type('obj', (object,), {'name': 'stop_on_error'})(), "1" if stop_on_error else "0"))
512
+
513
+ clone_project(option_list)
514
+
515
+
516
+ def clone_project_interactively() -> None:
517
+ """
518
+ Run interactive migration wizard with step-by-step prompts for all configuration.
519
+ """
520
+ Console.write_stdout("")
521
+ Console.write_stdout("=" * 80)
522
+ Console.write_stdout("PROJECT MIGRATION ASSISTANT")
523
+ Console.write_stdout("=" * 80)
524
+ Console.write_stdout("")
525
+
526
+ migration_type = prompt_with_retry(
527
+ "Migration type (1=same instance, 2=cross instance): ",
528
+ valid_choices=["1", "2"]
529
+ )
530
+ same_instance = migration_type == "1"
531
+
532
+ from_api_key, from_instance, from_project_id, from_organization_id = get_source_configuration()
533
+ from_organization_api_key, to_organization_api_key, to_project_name, admin_email, to_project_id = get_project_creation_info(same_instance)
534
+
535
+ creating_project = bool(to_project_name and admin_email)
536
+ to_instance, to_api_key, to_organization_id = get_destination_configuration(
537
+ same_instance, from_instance, from_api_key, from_organization_id, creating_project
538
+ )
539
+
540
+ resource_types_to_migrate = select_resource_types()
541
+
542
+ Console.write_stdout("\n--- Retrieving Available Resources ---")
543
+ lab_manager = AILabManager(api_key=from_api_key, base_url=from_instance)
544
+
545
+ selected_resources = {}
546
+
547
+ if 1 in resource_types_to_migrate:
548
+ selection = fetch_and_select_agents(lab_manager)
549
+ if selection:
550
+ selected_resources["agents"] = selection
551
+
552
+ if 2 in resource_types_to_migrate:
553
+ selection = fetch_and_select_tools(lab_manager)
554
+ if selection:
555
+ selected_resources["tools"] = selection
556
+
557
+ if 3 in resource_types_to_migrate:
558
+ selection = fetch_and_select_processes(lab_manager)
559
+ if selection:
560
+ selected_resources["agentic_processes"] = selection
561
+
562
+ if 4 in resource_types_to_migrate:
563
+ selection = fetch_and_select_tasks(lab_manager)
564
+ if selection:
565
+ selected_resources["tasks"] = selection
566
+
567
+ if 5 in resource_types_to_migrate:
568
+ selection = fetch_and_select_rag_assistants(from_api_key, from_instance)
569
+ if selection:
570
+ selected_resources["rag_assistants"] = selection
571
+
572
+ if 6 in resource_types_to_migrate:
573
+ selection = fetch_and_select_files(from_api_key, from_instance, from_organization_id, from_project_id)
574
+ if selection:
575
+ selected_resources["files"] = selection
576
+
577
+ if 7 in resource_types_to_migrate:
578
+ from_organization_api_key, to_organization_api_key = handle_usage_limits_keys(
579
+ same_instance, from_organization_api_key, to_organization_api_key
580
+ )
581
+ selected_resources["usage_limits"] = True
582
+
583
+ if 8 in resource_types_to_migrate:
584
+ selection = fetch_and_select_secrets(from_api_key, from_instance)
585
+ if selection:
586
+ selected_resources["secrets"] = selection
587
+
588
+ confirmed, stop_on_error = show_summary_and_confirm(from_instance, from_project_id, to_instance, to_project_name, to_project_id, selected_resources)
589
+ if not confirmed:
590
+ Console.write_stdout("Migration cancelled.")
591
+ return
592
+
593
+ build_option_list_and_execute(
594
+ from_api_key, from_instance, from_project_id, from_organization_id, from_organization_api_key,
595
+ to_api_key, to_instance, to_project_id, to_organization_id, to_organization_api_key,
596
+ to_project_name, admin_email, selected_resources, stop_on_error
597
+ )
598
+
599
+
600
+ def clone_project(option_list: list) -> None:
601
+ """
602
+ Clone a project with selected components from source to destination instance.
603
+
604
+ Supports migration of agents, tools, agentic processes, tasks, usage limits,
605
+ RAG assistants, files, and secrets between GEAI instances.
606
+
607
+ :param option_list: List of (option_flag, option_value) tuples from CLI parsing
608
+ """
609
+ interactive_mode = False
610
+ for option_flag, option_arg in option_list:
611
+ if option_flag.name == "interactive":
612
+ interactive_mode = True
613
+ break
614
+
615
+ if interactive_mode:
616
+ clone_project_interactively()
617
+ return
618
+
619
+ from_api_key = None
620
+ from_organization_api_key = None
621
+ from_instance = None
622
+ from_project_id = None
623
+ from_organization_id = None
624
+ to_api_key = None
625
+ to_organization_api_key = None
626
+ to_instance = None
627
+ to_project_id = None
628
+ to_organization_id = None
629
+ to_project_name = None
630
+ admin_email = None
631
+
632
+ migrate_all = False
633
+ migrate_agents = False
634
+ migrate_tools = False
635
+ migrate_processes = False
636
+ migrate_tasks = False
637
+ migrate_usage_limits = False
638
+ migrate_rag_assistants = False
639
+ migrate_files = False
640
+ migrate_secrets = False
641
+
642
+ agent_ids = None
643
+ tool_ids = None
644
+ process_ids = None
645
+ task_ids = None
646
+ assistant_names = None
647
+ file_ids = None
648
+ secret_ids = None
649
+
650
+ stop_on_error = True
651
+
652
+ for option_flag, option_arg in option_list:
653
+ if option_flag.name == "from_api_key":
654
+ from_api_key = option_arg
655
+ elif option_flag.name == "from_organization_api_key":
656
+ from_organization_api_key = option_arg
657
+ elif option_flag.name == "from_instance":
658
+ from_instance = option_arg
659
+ elif option_flag.name == "from_project_id":
660
+ from_project_id = option_arg
661
+ elif option_flag.name == "from_organization_id":
662
+ from_organization_id = option_arg
663
+ elif option_flag.name == "to_api_key":
664
+ to_api_key = option_arg
665
+ elif option_flag.name == "to_organization_api_key":
666
+ to_organization_api_key = option_arg
667
+ elif option_flag.name == "to_instance":
668
+ to_instance = option_arg
669
+ elif option_flag.name == "to_project_id":
670
+ to_project_id = option_arg
671
+ elif option_flag.name == "to_organization_id":
672
+ to_organization_id = option_arg
673
+ elif option_flag.name == "to_project_name":
674
+ to_project_name = option_arg
675
+ elif option_flag.name == "admin_email":
676
+ admin_email = option_arg
677
+ elif option_flag.name == "all":
678
+ migrate_all = True
679
+ elif option_flag.name == "agents":
680
+ migrate_agents = True
681
+ agent_ids = option_arg if option_arg else "all"
682
+ elif option_flag.name == "tools":
683
+ migrate_tools = True
684
+ tool_ids = option_arg if option_arg else "all"
685
+ elif option_flag.name == "agentic_processes":
686
+ migrate_processes = True
687
+ process_ids = option_arg if option_arg else "all"
688
+ elif option_flag.name == "tasks":
689
+ migrate_tasks = True
690
+ task_ids = option_arg if option_arg else "all"
691
+ elif option_flag.name == "usage_limits":
692
+ migrate_usage_limits = True
693
+ elif option_flag.name == "rag_assistants":
694
+ migrate_rag_assistants = True
695
+ assistant_names = option_arg if option_arg else "all"
696
+ elif option_flag.name == "files":
697
+ migrate_files = True
698
+ file_ids = option_arg if option_arg else "all"
699
+ elif option_flag.name == "secrets":
700
+ migrate_secrets = True
701
+ secret_ids = option_arg if option_arg else "all"
702
+ elif option_flag.name == "stop_on_error":
703
+ from pygeai.cli.commands.common import get_boolean_value
704
+ stop_on_error = get_boolean_value(option_arg)
705
+
706
+ if not all([from_api_key, from_instance, from_project_id]):
707
+ raise MissingRequirementException("Source API key, instance, and project ID are required")
708
+
709
+ if (to_project_name or admin_email) and not (to_project_name and admin_email):
710
+ raise MissingRequirementException(
711
+ "Both --to-project-name and --admin-email are required when creating a new project"
712
+ )
713
+
714
+ if to_project_id and (to_project_name or admin_email):
715
+ raise MissingRequirementException(
716
+ "Cannot specify both --to-project-id and project creation parameters (--to-project-name, --admin-email)"
717
+ )
718
+
719
+ if not to_project_id and not (to_project_name and admin_email):
720
+ raise MissingRequirementException(
721
+ "Must specify either --to-project-id (for existing project) or both --to-project-name and --admin-email (to create new project)"
722
+ )
723
+
724
+ if to_project_id and not to_api_key:
725
+ raise MissingRequirementException(
726
+ "Destination project API key (--to-api-key) is required when migrating to an existing project (--to-project-id)"
727
+ )
728
+
729
+ if to_project_name and admin_email:
730
+ if not from_organization_api_key:
731
+ raise MissingRequirementException(
732
+ "Source organization scope API key (--from-org-key) is required for project creation"
733
+ )
734
+ if not (to_organization_api_key or from_organization_api_key):
735
+ raise MissingRequirementException(
736
+ "Destination organization scope API key (--to-org-key) is required for project creation in a different "
737
+ "instance. Alternatively source organization scope (--from-org-key) can be used if project needs to be "
738
+ "created in the same instance."
739
+ )
740
+
741
+ # Validate organization scope keys for usage limits migration
742
+ if migrate_usage_limits:
743
+ if not from_organization_api_key:
744
+ raise MissingRequirementException(
745
+ "Source organization scope API key (--from-org-key) is required for usage limits migration"
746
+ )
747
+ if not (to_organization_api_key or from_organization_api_key):
748
+ raise MissingRequirementException(
749
+ "Destination organization scope API key (--to-org-key) is required for usage limits migration in a "
750
+ "different instance. Alternatively source organization scope (--from-org-key) can be used if limits "
751
+ "need to be migrated in the same instance."
752
+ )
753
+
754
+ if to_project_name and admin_email:
755
+ Console.write_stdout(f"Creating new project '{to_project_name}'...")
756
+
757
+ org_key_to_use = to_organization_api_key or from_organization_api_key
758
+ logger.debug(f"DEBUG: Preparing to create project with organization API key")
759
+ logger.debug(f" - to_organization_api_key exists: {to_organization_api_key is not None}")
760
+ logger.debug(f" - from_organization_api_key exists: {from_organization_api_key is not None}")
761
+ logger.debug(f" - Using key (first 20 chars): {org_key_to_use[:20] if org_key_to_use else 'None'}...")
762
+ Console.write_stderr(f"DEBUG: Using org key for project creation (first 20 chars): {org_key_to_use[:20] if org_key_to_use else 'None'}...")
763
+
764
+ project_strategy = ProjectMigrationStrategy(
765
+ from_api_key=from_organization_api_key,
766
+ from_instance=from_instance,
767
+ from_project_id=from_project_id,
768
+ to_project_name=to_project_name,
769
+ admin_email=admin_email,
770
+ to_api_key=org_key_to_use,
771
+ to_instance=to_instance
772
+ )
773
+ project_tool = MigrationTool(project_strategy)
774
+ to_project_id = project_tool.run_migration()
775
+
776
+ if not to_project_id:
777
+ raise ValueError("Project creation did not return a project ID")
778
+
779
+ Console.write_stdout(f"Project '{to_project_name}' created successfully with ID: {to_project_id}")
780
+
781
+ from pygeai.auth.clients import AuthClient
782
+ Console.write_stdout(f"Creating project API key for new project...")
783
+
784
+ org_key_for_token_creation = to_organization_api_key or from_organization_api_key
785
+ auth_client = AuthClient(
786
+ api_key=org_key_for_token_creation,
787
+ base_url=to_instance or from_instance
788
+ )
789
+
790
+ token_response = auth_client.create_project_api_token(
791
+ project_id=to_project_id,
792
+ name=f"Migration API Key for {to_project_name}",
793
+ description=f"Auto-generated API key for project migration to {to_project_name}"
794
+ )
795
+
796
+ if not token_response or 'id' not in token_response:
797
+ raise ValueError("Failed to create project API key")
798
+
799
+ to_api_key = token_response['id']
800
+ Console.write_stdout(f"Project API key created successfully")
801
+
802
+ if not to_organization_id:
803
+ Console.write_stdout(f"Retrieving destination organization ID...")
804
+ dest_admin_client = AdminClient(api_key=to_api_key, base_url=to_instance or from_instance)
805
+ dest_token_info = dest_admin_client.validate_api_token()
806
+ to_organization_id = dest_token_info.get("organizationId")
807
+ Console.write_stdout(f"Destination organization ID: {to_organization_id}")
808
+
809
+ if migrate_all:
810
+ migrate_agents = True
811
+ migrate_tools = True
812
+ migrate_processes = True
813
+ migrate_tasks = True
814
+ migrate_usage_limits = True if from_organization_id and to_organization_id else False
815
+ migrate_rag_assistants = True
816
+ migrate_files = True if from_organization_id and to_organization_id else False
817
+ migrate_secrets = True
818
+ agent_ids = "all"
819
+ tool_ids = "all"
820
+ process_ids = "all"
821
+ task_ids = "all"
822
+ assistant_names = "all"
823
+ file_ids = "all"
824
+ secret_ids = "all"
825
+
826
+ strategies = []
827
+
828
+ lab_manager = AILabManager(api_key=from_api_key, base_url=from_instance)
829
+
830
+ if migrate_agents:
831
+ if agent_ids == "all":
832
+ agent_list = lab_manager.get_agent_list(FilterSettings(count=1000))
833
+ discovered_agents = [agent.id for agent in agent_list.agents if agent.id]
834
+ Console.write_stdout(f"Discovered {len(discovered_agents)} agents")
835
+ for agent_id in discovered_agents:
836
+ strategies.append(AgentMigrationStrategy(
837
+ from_api_key=from_api_key,
838
+ from_instance=from_instance,
839
+ agent_id=agent_id,
840
+ to_api_key=to_api_key,
841
+ to_instance=to_instance
842
+ ))
843
+ elif agent_ids:
844
+ for agent_id in agent_ids.split(','):
845
+ strategies.append(AgentMigrationStrategy(
846
+ from_api_key=from_api_key,
847
+ from_instance=from_instance,
848
+ agent_id=agent_id.strip(),
849
+ to_api_key=to_api_key,
850
+ to_instance=to_instance
851
+ ))
852
+
853
+ if migrate_tools:
854
+ if tool_ids == "all":
855
+ tool_list = lab_manager.list_tools(FilterSettings(count=1000))
856
+ discovered_tools = [tool.id for tool in tool_list.tools if tool.id]
857
+ Console.write_stdout(f"Discovered {len(discovered_tools)} tools")
858
+ for tool_id in discovered_tools:
859
+ strategies.append(ToolMigrationStrategy(
860
+ from_api_key=from_api_key,
861
+ from_instance=from_instance,
862
+ tool_id=tool_id,
863
+ to_api_key=to_api_key,
864
+ to_instance=to_instance
865
+ ))
866
+ elif tool_ids:
867
+ for tool_id in tool_ids.split(','):
868
+ strategies.append(ToolMigrationStrategy(
869
+ from_api_key=from_api_key,
870
+ from_instance=from_instance,
871
+ tool_id=tool_id.strip(),
872
+ to_api_key=to_api_key,
873
+ to_instance=to_instance
874
+ ))
875
+
876
+ if migrate_processes:
877
+ if process_ids == "all":
878
+ process_list = lab_manager.list_processes(FilterSettings(count=1000))
879
+ discovered_processes = [proc.id for proc in process_list.processes if proc.id]
880
+ Console.write_stdout(f"Discovered {len(discovered_processes)} agentic processes")
881
+ for process_id in discovered_processes:
882
+ strategies.append(AgenticProcessMigrationStrategy(
883
+ from_api_key=from_api_key,
884
+ from_instance=from_instance,
885
+ process_id=process_id,
886
+ to_api_key=to_api_key,
887
+ to_instance=to_instance
888
+ ))
889
+ elif process_ids:
890
+ for process_id in process_ids.split(','):
891
+ strategies.append(AgenticProcessMigrationStrategy(
892
+ from_api_key=from_api_key,
893
+ from_instance=from_instance,
894
+ process_id=process_id.strip(),
895
+ to_api_key=to_api_key,
896
+ to_instance=to_instance
897
+ ))
898
+
899
+ if migrate_tasks:
900
+ if task_ids == "all":
901
+ task_list = lab_manager.list_tasks(FilterSettings(count=1000))
902
+ discovered_tasks = [task.id for task in task_list.tasks if task.id]
903
+ Console.write_stdout(f"Discovered {len(discovered_tasks)} tasks")
904
+ for task_id in discovered_tasks:
905
+ strategies.append(TaskMigrationStrategy(
906
+ from_api_key=from_api_key,
907
+ from_instance=from_instance,
908
+ task_id=task_id,
909
+ to_api_key=to_api_key,
910
+ to_instance=to_instance
911
+ ))
912
+ elif task_ids:
913
+ for task_id in task_ids.split(','):
914
+ strategies.append(TaskMigrationStrategy(
915
+ from_api_key=from_api_key,
916
+ from_instance=from_instance,
917
+ task_id=task_id.strip(),
918
+ to_api_key=to_api_key,
919
+ to_instance=to_instance
920
+ ))
921
+
922
+ if migrate_usage_limits and from_organization_id and to_organization_id:
923
+ strategies.append(UsageLimitMigrationStrategy(
924
+ from_api_key=from_organization_api_key,
925
+ from_instance=from_instance,
926
+ from_organization_id=from_organization_id,
927
+ to_organization_id=to_organization_id,
928
+ to_api_key=to_organization_api_key or from_organization_api_key,
929
+ to_instance=to_instance
930
+ ))
931
+
932
+ if migrate_rag_assistants:
933
+ rag_client = RAGAssistantClient(api_key=from_api_key, base_url=from_instance)
934
+ if assistant_names == "all":
935
+ assistant_data = rag_client.get_assistants_from_project()
936
+ assistants_raw = assistant_data.get("assistants", [])
937
+ assistant_list = [RAGAssistantMapper.map_to_rag_assistant(a) for a in assistants_raw] if assistants_raw else []
938
+ discovered_assistants = [assistant.name for assistant in assistant_list if assistant.name]
939
+ Console.write_stdout(f"Discovered {len(discovered_assistants)} RAG assistants")
940
+ for assistant_name in discovered_assistants:
941
+ strategies.append(RAGAssistantMigrationStrategy(
942
+ from_api_key=from_api_key,
943
+ from_instance=from_instance,
944
+ assistant_name=assistant_name,
945
+ to_api_key=to_api_key,
946
+ to_instance=to_instance
947
+ ))
948
+ elif assistant_names:
949
+ for assistant_name in assistant_names.split(','):
950
+ strategies.append(RAGAssistantMigrationStrategy(
951
+ from_api_key=from_api_key,
952
+ from_instance=from_instance,
953
+ assistant_name=assistant_name.strip(),
954
+ to_api_key=to_api_key,
955
+ to_instance=to_instance
956
+ ))
957
+
958
+ if migrate_files and from_organization_id and from_project_id and to_organization_id and to_project_id:
959
+ file_manager = FileManager(
960
+ api_key=from_api_key,
961
+ base_url=from_instance,
962
+ organization_id=from_organization_id,
963
+ project_id=from_project_id
964
+ )
965
+ if file_ids == "all":
966
+ file_list_response = file_manager.get_file_list()
967
+ discovered_files = [f.id for f in file_list_response.files if f.id]
968
+ Console.write_stdout(f"Discovered {len(discovered_files)} files")
969
+ for file_id in discovered_files:
970
+ strategies.append(FileMigrationStrategy(
971
+ from_api_key=from_api_key,
972
+ from_instance=from_instance,
973
+ from_organization_id=from_organization_id,
974
+ from_project_id=from_project_id,
975
+ to_organization_id=to_organization_id,
976
+ to_project_id=to_project_id,
977
+ file_id=file_id,
978
+ to_api_key=to_api_key,
979
+ to_instance=to_instance
980
+ ))
981
+ elif file_ids:
982
+ for file_id in file_ids.split(','):
983
+ strategies.append(FileMigrationStrategy(
984
+ from_api_key=from_api_key,
985
+ from_instance=from_instance,
986
+ from_organization_id=from_organization_id,
987
+ from_project_id=from_project_id,
988
+ to_organization_id=to_organization_id,
989
+ to_project_id=to_project_id,
990
+ file_id=file_id.strip(),
991
+ to_api_key=to_api_key,
992
+ to_instance=to_instance
993
+ ))
994
+
995
+ if migrate_secrets:
996
+ secret_client = SecretClient(api_key=from_api_key, base_url=from_instance)
997
+ if secret_ids == "all":
998
+ secrets_data = secret_client.list_secrets(count=1000)
999
+ secrets_list = secrets_data.get("secrets", []) if isinstance(secrets_data, dict) else []
1000
+ discovered_secrets = [s.get('id') for s in secrets_list if s.get('id')]
1001
+ Console.write_stdout(f"Discovered {len(discovered_secrets)} secrets")
1002
+ for secret_id in discovered_secrets:
1003
+ strategies.append(SecretMigrationStrategy(
1004
+ from_api_key=from_api_key,
1005
+ from_instance=from_instance,
1006
+ secret_id=secret_id,
1007
+ to_api_key=to_api_key,
1008
+ to_instance=to_instance
1009
+ ))
1010
+ elif secret_ids:
1011
+ for secret_id in secret_ids.split(','):
1012
+ strategies.append(SecretMigrationStrategy(
1013
+ from_api_key=from_api_key,
1014
+ from_instance=from_instance,
1015
+ secret_id=secret_id.strip(),
1016
+ to_api_key=to_api_key,
1017
+ to_instance=to_instance
1018
+ ))
1019
+
1020
+ if not strategies:
1021
+ Console.write_stdout("No migration strategies configured. Use flags like --agents, --tools, --all, etc.")
1022
+ return
1023
+
1024
+ plan = MigrationPlan(strategies=strategies, stop_on_error=stop_on_error)
1025
+ orchestrator = MigrationOrchestrator(plan)
1026
+
1027
+ try:
1028
+ result = orchestrator.execute()
1029
+ Console.write_stdout(f"Migration completed: {result['completed']}/{result['total']} successful")
1030
+ logger.info(f"Project cloning completed: {result}")
1031
+ except Exception as e:
1032
+ Console.write_stderr(f"Migration failed: {e}")
1033
+ logger.error(f"Project cloning failed: {e}")
1034
+ raise
1035
+
1036
+
1037
+ clone_project_options = [
1038
+ Option(
1039
+ "interactive",
1040
+ ["-i", "--interactive"],
1041
+ "Interactive mode: guided step-by-step migration wizard",
1042
+ False
1043
+ ),
1044
+ Option(
1045
+ "from_api_key",
1046
+ ["--from-api-key", "--from-key"],
1047
+ "Source instance project scope API key (required)",
1048
+ True
1049
+ ),
1050
+ Option(
1051
+ "from_organization_api_key",
1052
+ ["--from-org-key", "--from-organization-key"],
1053
+ "Source instance organization scope API key (optional, for project creation)",
1054
+ True
1055
+ ),
1056
+ Option(
1057
+ "from_instance",
1058
+ ["--from-instance", "--from-url"],
1059
+ "Source instance URL (required)",
1060
+ True
1061
+ ),
1062
+ Option(
1063
+ "from_project_id",
1064
+ ["--from-project-id", "--from-pid"],
1065
+ "Source project ID (required)",
1066
+ True
1067
+ ),
1068
+ Option(
1069
+ "from_organization_id",
1070
+ ["--from-organization-id", "--from-oid"],
1071
+ "Source organization ID (required for usage limits and files)",
1072
+ True
1073
+ ),
1074
+ Option(
1075
+ "to_api_key",
1076
+ ["--to-api-key", "--to-key"],
1077
+ "Destination instance project scope API key (optional, defaults to source key)",
1078
+ True
1079
+ ),
1080
+ Option(
1081
+ "to_organization_api_key",
1082
+ ["--to-org-key", "--to-organization-key"],
1083
+ "Destination instance organization scope API key (optional, for project creation)",
1084
+ True
1085
+ ),
1086
+ Option(
1087
+ "to_instance",
1088
+ ["--to-instance", "--to-url"],
1089
+ "Destination instance URL (optional, defaults to source URL)",
1090
+ True
1091
+ ),
1092
+ Option(
1093
+ "to_project_name",
1094
+ ["--to-project-name", "--to-name"],
1095
+ "Name for the new destination project (creates new project if specified with --admin-email)",
1096
+ True
1097
+ ),
1098
+ Option(
1099
+ "admin_email",
1100
+ ["--admin-email"],
1101
+ "Admin email for new project (required when creating new project)",
1102
+ True
1103
+ ),
1104
+ Option(
1105
+ "to_project_id",
1106
+ ["--to-project-id", "--to-pid"],
1107
+ "Destination project ID (optional for files)",
1108
+ True
1109
+ ),
1110
+ Option(
1111
+ "to_organization_id",
1112
+ ["--to-organization-id", "--to-oid"],
1113
+ "Destination organization ID (optional for usage limits and files)",
1114
+ True
1115
+ ),
1116
+ Option(
1117
+ "all",
1118
+ ["--all"],
1119
+ "Migrate all available components",
1120
+ False
1121
+ ),
1122
+ Option(
1123
+ "agents",
1124
+ ["--agents"],
1125
+ "Agent IDs to migrate: comma-separated IDs or 'all'",
1126
+ True
1127
+ ),
1128
+ Option(
1129
+ "tools",
1130
+ ["--tools"],
1131
+ "Tool IDs to migrate: comma-separated IDs or 'all'",
1132
+ True
1133
+ ),
1134
+ Option(
1135
+ "agentic_processes",
1136
+ ["--agentic-processes", "--processes"],
1137
+ "Agentic process IDs to migrate: comma-separated IDs or 'all'",
1138
+ True
1139
+ ),
1140
+ Option(
1141
+ "tasks",
1142
+ ["--tasks"],
1143
+ "Task IDs to migrate: comma-separated IDs or 'all'",
1144
+ True
1145
+ ),
1146
+ Option(
1147
+ "usage_limits",
1148
+ ["--usage-limits"],
1149
+ "Migrate usage limits (requires organization IDs)",
1150
+ False
1151
+ ),
1152
+ Option(
1153
+ "rag_assistants",
1154
+ ["--rag-assistants"],
1155
+ "RAG assistant names to migrate: comma-separated names or 'all'",
1156
+ True
1157
+ ),
1158
+ Option(
1159
+ "files",
1160
+ ["--files"],
1161
+ "File IDs to migrate: comma-separated IDs or 'all' (requires org/project IDs)",
1162
+ True
1163
+ ),
1164
+ Option(
1165
+ "secrets",
1166
+ ["--secrets"],
1167
+ "Secret IDs to migrate: comma-separated IDs or 'all'",
1168
+ True
1169
+ ),
1170
+ Option(
1171
+ "stop_on_error",
1172
+ ["--stop-on-error", "--soe"],
1173
+ "Stop migration on first error: 0: False, 1: True (default: 1)",
1174
+ True
1175
+ ),
1176
+ ]
1177
+
1178
+
1179
+ migrate_commands = [
1180
+ Command(
1181
+ "help",
1182
+ ["help", "h"],
1183
+ "Display help text",
1184
+ show_help,
1185
+ ArgumentsEnum.NOT_AVAILABLE,
1186
+ [],
1187
+ []
1188
+ ),
1189
+ Command(
1190
+ "clone_project",
1191
+ ["clone-project"],
1192
+ "Clone project components between instances",
1193
+ clone_project,
1194
+ ArgumentsEnum.REQUIRED,
1195
+ [],
1196
+ clone_project_options
1197
+ ),
1198
+ ]