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.
- pygeai/__init__.py +11 -2
- pygeai/_docs/Makefile +20 -0
- pygeai/_docs/make.bat +35 -0
- pygeai/_docs/source/conf.py +117 -0
- pygeai/_docs/source/content/ai_lab/cli.rst +747 -0
- pygeai/_docs/source/content/ai_lab/models.rst +1734 -0
- pygeai/_docs/source/content/ai_lab/runner.rst +253 -0
- pygeai/_docs/source/content/ai_lab/spec.rst +431 -0
- pygeai/_docs/source/content/ai_lab/usage.rst +1011 -0
- pygeai/_docs/source/content/ai_lab.rst +102 -0
- pygeai/_docs/source/content/analytics.rst +598 -0
- pygeai/_docs/source/content/api_reference/admin.rst +161 -0
- pygeai/_docs/source/content/api_reference/assistant.rst +326 -0
- pygeai/_docs/source/content/api_reference/auth.rst +379 -0
- pygeai/_docs/source/content/api_reference/chat.rst +754 -0
- pygeai/_docs/source/content/api_reference/embeddings.rst +154 -0
- pygeai/_docs/source/content/api_reference/evaluation.rst +590 -0
- pygeai/_docs/source/content/api_reference/feedback.rst +237 -0
- pygeai/_docs/source/content/api_reference/files.rst +592 -0
- pygeai/_docs/source/content/api_reference/gam.rst +401 -0
- pygeai/_docs/source/content/api_reference/health.rst +58 -0
- pygeai/_docs/source/content/api_reference/project.rst +738 -0
- pygeai/_docs/source/content/api_reference/proxy.rst +318 -0
- pygeai/_docs/source/content/api_reference/rag.rst +710 -0
- pygeai/_docs/source/content/api_reference/rerank.rst +94 -0
- pygeai/_docs/source/content/api_reference/secrets.rst +495 -0
- pygeai/_docs/source/content/api_reference/usage_limits.rst +390 -0
- pygeai/_docs/source/content/api_reference.rst +58 -0
- pygeai/_docs/source/content/authentication.rst +295 -0
- pygeai/_docs/source/content/chat_gui.rst +121 -0
- pygeai/_docs/source/content/cli.rst +203 -0
- pygeai/_docs/source/content/debugger.rst +651 -0
- pygeai/_docs/source/content/intro.rst +67 -0
- pygeai/_docs/source/content/migration.rst +929 -0
- pygeai/_docs/source/content/modules.rst +7 -0
- pygeai/_docs/source/content/quickstart.rst +143 -0
- pygeai/_docs/source/content/samples.rst +394 -0
- pygeai/_docs/source/index.rst +75 -0
- pygeai/_docs/source/modules.rst +7 -0
- pygeai/_docs/source/pygeai.admin.rst +29 -0
- pygeai/_docs/source/pygeai.analytics.rst +53 -0
- pygeai/_docs/source/pygeai.assistant.data.rst +21 -0
- pygeai/_docs/source/pygeai.assistant.data_analyst.rst +29 -0
- pygeai/_docs/source/pygeai.assistant.rag.rst +53 -0
- pygeai/_docs/source/pygeai.assistant.rst +55 -0
- pygeai/_docs/source/pygeai.auth.rst +29 -0
- pygeai/_docs/source/pygeai.chat.rst +69 -0
- pygeai/_docs/source/pygeai.cli.commands.flows.rst +10 -0
- pygeai/_docs/source/pygeai.cli.commands.lab.rst +53 -0
- pygeai/_docs/source/pygeai.cli.commands.rst +222 -0
- pygeai/_docs/source/pygeai.cli.rst +62 -0
- pygeai/_docs/source/pygeai.cli.texts.rst +21 -0
- pygeai/_docs/source/pygeai.core.base.rst +53 -0
- pygeai/_docs/source/pygeai.core.common.rst +37 -0
- pygeai/_docs/source/pygeai.core.embeddings.rst +61 -0
- pygeai/_docs/source/pygeai.core.feedback.rst +37 -0
- pygeai/_docs/source/pygeai.core.files.rst +61 -0
- pygeai/_docs/source/pygeai.core.llm.rst +29 -0
- pygeai/_docs/source/pygeai.core.plugins.rst +37 -0
- pygeai/_docs/source/pygeai.core.rerank.rst +53 -0
- pygeai/_docs/source/pygeai.core.rst +63 -0
- pygeai/_docs/source/pygeai.core.secrets.rst +29 -0
- pygeai/_docs/source/pygeai.core.services.llm.rst +29 -0
- pygeai/_docs/source/pygeai.core.services.rst +37 -0
- pygeai/_docs/source/pygeai.core.utils.rst +37 -0
- pygeai/_docs/source/pygeai.dbg.rst +21 -0
- pygeai/_docs/source/pygeai.evaluation.dataset.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.plan.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.result.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.rst +31 -0
- pygeai/_docs/source/pygeai.flows.rst +29 -0
- pygeai/_docs/source/pygeai.gam.rst +29 -0
- pygeai/_docs/source/pygeai.health.rst +29 -0
- pygeai/_docs/source/pygeai.lab.agents.rst +37 -0
- pygeai/_docs/source/pygeai.lab.processes.rst +37 -0
- pygeai/_docs/source/pygeai.lab.rst +65 -0
- pygeai/_docs/source/pygeai.lab.spec.rst +29 -0
- pygeai/_docs/source/pygeai.lab.strategies.rst +37 -0
- pygeai/_docs/source/pygeai.lab.tools.rst +37 -0
- pygeai/_docs/source/pygeai.man.man1.rst +10 -0
- pygeai/_docs/source/pygeai.man.rst +18 -0
- pygeai/_docs/source/pygeai.migration.rst +29 -0
- pygeai/_docs/source/pygeai.organization.limits.rst +45 -0
- pygeai/_docs/source/pygeai.organization.rst +61 -0
- pygeai/_docs/source/pygeai.proxy.rst +53 -0
- pygeai/_docs/source/pygeai.rst +35 -0
- pygeai/_docs/source/pygeai.tests.admin.rst +21 -0
- pygeai/_docs/source/pygeai.tests.analytics.rst +45 -0
- pygeai/_docs/source/pygeai.tests.assistants.rag.rst +37 -0
- pygeai/_docs/source/pygeai.tests.assistants.rst +45 -0
- pygeai/_docs/source/pygeai.tests.auth.rst +29 -0
- pygeai/_docs/source/pygeai.tests.chat.rst +45 -0
- pygeai/_docs/source/pygeai.tests.cli.commands.lab.rst +37 -0
- pygeai/_docs/source/pygeai.tests.cli.commands.rst +165 -0
- pygeai/_docs/source/pygeai.tests.cli.docker.rst +10 -0
- pygeai/_docs/source/pygeai.tests.cli.rst +46 -0
- pygeai/_docs/source/pygeai.tests.core.base.data.rst +29 -0
- pygeai/_docs/source/pygeai.tests.core.base.rst +45 -0
- pygeai/_docs/source/pygeai.tests.core.common.data.rst +10 -0
- pygeai/_docs/source/pygeai.tests.core.common.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.embeddings.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.feedback.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.files.rst +53 -0
- pygeai/_docs/source/pygeai.tests.core.llm.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.plugins.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.rerank.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.rst +39 -0
- pygeai/_docs/source/pygeai.tests.core.secrets.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.services.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.utils.rst +21 -0
- pygeai/_docs/source/pygeai.tests.dbg.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.dataset.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.plan.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.result.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.rst +20 -0
- pygeai/_docs/source/pygeai.tests.gam.rst +21 -0
- pygeai/_docs/source/pygeai.tests.health.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.assistants.rag.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.assistants.rst +18 -0
- pygeai/_docs/source/pygeai.tests.integration.chat.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.agents.rst +69 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.processes.rst +77 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.reasoning_strategies.rst +37 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.tools.rst +77 -0
- pygeai/_docs/source/pygeai.tests.integration.rst +20 -0
- pygeai/_docs/source/pygeai.tests.lab.agents.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.processes.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.rst +49 -0
- pygeai/_docs/source/pygeai.tests.lab.spec.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.strategies.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.tools.rst +29 -0
- pygeai/_docs/source/pygeai.tests.migration.rst +29 -0
- pygeai/_docs/source/pygeai.tests.organization.limits.rst +29 -0
- pygeai/_docs/source/pygeai.tests.organization.rst +53 -0
- pygeai/_docs/source/pygeai.tests.proxy.rst +61 -0
- pygeai/_docs/source/pygeai.tests.rst +33 -0
- pygeai/admin/clients.py +14 -11
- pygeai/admin/endpoints.py +2 -2
- pygeai/analytics/clients.py +505 -0
- pygeai/analytics/endpoints.py +35 -0
- pygeai/analytics/managers.py +606 -0
- pygeai/analytics/mappers.py +207 -0
- pygeai/analytics/responses.py +240 -0
- pygeai/assistant/clients.py +48 -57
- pygeai/assistant/data/__init__.py +0 -0
- pygeai/assistant/data/clients.py +15 -0
- pygeai/assistant/data_analyst/__init__.py +0 -0
- pygeai/assistant/data_analyst/clients.py +75 -0
- pygeai/assistant/data_analyst/endpoints.py +2 -0
- pygeai/assistant/endpoints.py +0 -2
- pygeai/assistant/managers.py +738 -0
- pygeai/assistant/mappers.py +153 -0
- pygeai/assistant/rag/clients.py +132 -21
- pygeai/assistant/rag/mappers.py +228 -0
- pygeai/assistant/rag/models.py +396 -0
- pygeai/assistant/rag/responses.py +10 -0
- pygeai/auth/__init__.py +0 -0
- pygeai/auth/clients.py +129 -0
- pygeai/auth/endpoints.py +6 -0
- pygeai/chat/clients.py +406 -31
- pygeai/chat/endpoints.py +3 -0
- pygeai/chat/iris.py +17 -0
- pygeai/chat/managers.py +64 -0
- pygeai/chat/session.py +38 -0
- pygeai/chat/settings.py +6 -0
- pygeai/chat/ui.py +678 -0
- pygeai/cli/__init__.py +0 -1
- pygeai/cli/commands/admin.py +9 -12
- pygeai/cli/commands/analytics.py +533 -0
- pygeai/cli/commands/assistant.py +11 -11
- pygeai/cli/commands/auth.py +299 -0
- pygeai/cli/commands/base.py +201 -7
- pygeai/cli/commands/chat.py +875 -14
- pygeai/cli/commands/common.py +30 -26
- pygeai/cli/commands/configuration.py +84 -9
- pygeai/cli/commands/docs.py +105 -0
- pygeai/cli/commands/embeddings.py +187 -0
- pygeai/cli/commands/evaluation.py +2069 -0
- pygeai/cli/commands/feedback.py +93 -0
- pygeai/cli/commands/files.py +312 -0
- pygeai/cli/commands/flows/__init__.py +0 -0
- pygeai/cli/commands/gam.py +349 -0
- pygeai/cli/commands/lab/__init__.py +0 -0
- pygeai/cli/commands/lab/ai_lab.py +4110 -0
- pygeai/cli/commands/lab/common.py +135 -0
- pygeai/cli/commands/lab/options.py +8 -0
- pygeai/cli/commands/lab/spec.py +273 -0
- pygeai/cli/commands/lab/utils.py +13 -0
- pygeai/cli/commands/llm.py +164 -0
- pygeai/cli/commands/migrate.py +1198 -0
- pygeai/cli/commands/options.py +86 -0
- pygeai/cli/commands/organization.py +560 -98
- pygeai/cli/commands/rag.py +306 -10
- pygeai/cli/commands/rerank.py +108 -0
- pygeai/cli/commands/secrets.py +357 -0
- pygeai/cli/commands/usage_limits.py +583 -0
- pygeai/cli/commands/validators.py +209 -0
- pygeai/cli/commands/version.py +44 -0
- pygeai/cli/error_handler.py +151 -0
- pygeai/cli/geai.py +171 -30
- pygeai/cli/geai_proxy.py +318 -0
- pygeai/cli/install_man.py +107 -0
- pygeai/cli/parsers.py +78 -25
- pygeai/cli/texts/help.py +712 -55
- pygeai/core/__init__.py +9 -1
- pygeai/core/base/clients.py +61 -10
- pygeai/core/base/mappers.py +208 -30
- pygeai/core/base/models.py +8 -308
- pygeai/core/base/responses.py +18 -1
- pygeai/core/base/session.py +110 -17
- pygeai/core/common/config.py +98 -16
- pygeai/core/common/decorators.py +44 -0
- pygeai/core/common/exceptions.py +104 -4
- pygeai/core/embeddings/__init__.py +19 -0
- pygeai/core/embeddings/clients.py +93 -0
- pygeai/core/embeddings/endpoints.py +1 -0
- pygeai/core/embeddings/managers.py +62 -0
- pygeai/core/embeddings/mappers.py +52 -0
- pygeai/core/embeddings/models.py +14 -0
- pygeai/core/embeddings/responses.py +31 -0
- pygeai/core/feedback/__init__.py +0 -0
- pygeai/core/feedback/clients.py +50 -0
- pygeai/core/feedback/endpoints.py +1 -0
- pygeai/core/feedback/models.py +10 -0
- pygeai/core/files/__init__.py +0 -0
- pygeai/core/files/clients.py +156 -0
- pygeai/core/files/endpoints.py +5 -0
- pygeai/core/files/managers.py +224 -0
- pygeai/core/files/mappers.py +44 -0
- pygeai/core/files/models.py +24 -0
- pygeai/core/files/responses.py +19 -0
- pygeai/core/handlers.py +32 -0
- pygeai/core/llm/__init__.py +0 -0
- pygeai/core/llm/clients.py +53 -0
- pygeai/core/llm/endpoints.py +4 -0
- pygeai/core/models.py +799 -0
- pygeai/core/plugins/__init__.py +0 -0
- pygeai/core/plugins/clients.py +32 -0
- pygeai/core/plugins/endpoints.py +1 -0
- pygeai/core/plugins/models.py +86 -0
- pygeai/core/rerank/__init__.py +0 -0
- pygeai/core/rerank/clients.py +35 -0
- pygeai/core/rerank/endpoints.py +1 -0
- pygeai/core/rerank/managers.py +47 -0
- pygeai/core/rerank/mappers.py +23 -0
- pygeai/core/rerank/models.py +27 -0
- pygeai/core/responses.py +104 -0
- pygeai/core/secrets/__init__.py +0 -0
- pygeai/core/secrets/clients.py +212 -0
- pygeai/core/secrets/endpoints.py +7 -0
- pygeai/core/services/llm/__init__.py +0 -0
- pygeai/core/services/llm/model.py +186 -0
- pygeai/core/services/llm/providers.py +15 -0
- pygeai/core/services/response.py +18 -0
- pygeai/core/services/rest.py +311 -89
- pygeai/core/utils/__init__.py +0 -0
- pygeai/core/utils/console.py +83 -0
- pygeai/core/utils/parsers.py +32 -0
- pygeai/core/utils/validators.py +10 -0
- pygeai/dbg/__init__.py +3 -0
- pygeai/dbg/debugger.py +870 -0
- pygeai/evaluation/__init__.py +0 -0
- pygeai/evaluation/clients.py +19 -0
- pygeai/evaluation/dataset/__init__.py +0 -0
- pygeai/evaluation/dataset/clients.py +514 -0
- pygeai/evaluation/dataset/endpoints.py +26 -0
- pygeai/evaluation/plan/__init__.py +0 -0
- pygeai/evaluation/plan/clients.py +302 -0
- pygeai/evaluation/plan/endpoints.py +16 -0
- pygeai/evaluation/result/__init__.py +0 -0
- pygeai/evaluation/result/clients.py +70 -0
- pygeai/evaluation/result/endpoints.py +2 -0
- pygeai/flows/__init__.py +0 -0
- pygeai/flows/endpoints.py +362 -0
- pygeai/flows/models.py +1304 -0
- pygeai/gam/__init__.py +0 -0
- pygeai/gam/clients.py +178 -0
- pygeai/gam/endpoints.py +4 -0
- pygeai/health/__init__.py +0 -0
- pygeai/health/clients.py +24 -0
- pygeai/health/endpoints.py +1 -0
- pygeai/lab/__init__.py +0 -0
- pygeai/lab/agents/__init__.py +0 -0
- pygeai/lab/agents/clients.py +426 -0
- pygeai/lab/agents/endpoints.py +12 -0
- pygeai/lab/agents/mappers.py +319 -0
- pygeai/lab/clients.py +24 -0
- pygeai/lab/constants.py +3 -0
- pygeai/lab/managers.py +1558 -0
- pygeai/lab/models.py +1719 -0
- pygeai/lab/processes/__init__.py +0 -0
- pygeai/lab/processes/clients.py +1051 -0
- pygeai/lab/processes/endpoints.py +26 -0
- pygeai/lab/processes/mappers.py +395 -0
- pygeai/lab/runners.py +90 -0
- pygeai/lab/spec/__init__.py +0 -0
- pygeai/lab/spec/loader.py +24 -0
- pygeai/lab/spec/parsers.py +39 -0
- pygeai/lab/strategies/__init__.py +0 -0
- pygeai/lab/strategies/clients.py +212 -0
- pygeai/lab/strategies/endpoints.py +5 -0
- pygeai/lab/strategies/mappers.py +58 -0
- pygeai/lab/tools/__init__.py +0 -0
- pygeai/lab/tools/clients.py +465 -0
- pygeai/lab/tools/endpoints.py +13 -0
- pygeai/lab/tools/mappers.py +131 -0
- pygeai/man/__init__.py +1 -0
- pygeai/man/man1/__init__.py +1 -0
- pygeai/man/man1/geai-proxy.1 +246 -0
- pygeai/man/man1/geai.1 +2615 -0
- pygeai/migration/__init__.py +33 -0
- pygeai/migration/strategies.py +603 -0
- pygeai/migration/tools.py +180 -0
- pygeai/organization/clients.py +246 -18
- pygeai/organization/endpoints.py +17 -8
- pygeai/organization/limits/__init__.py +0 -0
- pygeai/organization/limits/clients.py +281 -0
- pygeai/organization/limits/endpoints.py +15 -0
- pygeai/organization/limits/managers.py +331 -0
- pygeai/organization/limits/mappers.py +21 -0
- pygeai/organization/managers.py +537 -0
- pygeai/organization/mappers.py +111 -46
- pygeai/organization/responses.py +61 -11
- pygeai/proxy/__init__.py +0 -0
- pygeai/proxy/clients.py +216 -0
- pygeai/proxy/config.py +128 -0
- pygeai/proxy/managers.py +232 -0
- pygeai/proxy/servers.py +304 -0
- pygeai/proxy/tool.py +69 -0
- pygeai/tests/admin/__init__.py +0 -0
- pygeai/tests/admin/test_clients.py +148 -0
- pygeai/tests/analytics/__init__.py +0 -0
- pygeai/tests/analytics/test_clients.py +86 -0
- pygeai/tests/analytics/test_managers.py +94 -0
- pygeai/tests/analytics/test_mappers.py +84 -0
- pygeai/tests/analytics/test_responses.py +73 -0
- pygeai/tests/assistants/rag/__init__.py +0 -0
- pygeai/tests/assistants/rag/test_clients.py +346 -0
- pygeai/tests/assistants/rag/test_mappers.py +189 -0
- pygeai/tests/assistants/rag/test_models.py +292 -0
- pygeai/tests/assistants/test_clients.py +176 -80
- pygeai/tests/assistants/test_managers.py +198 -0
- pygeai/tests/assistants/test_mappers.py +111 -0
- pygeai/tests/auth/__init__.py +0 -0
- pygeai/tests/auth/test_clients.py +289 -0
- pygeai/tests/auth/test_oauth.py +172 -0
- pygeai/tests/auth/test_session_logging.py +150 -0
- pygeai/tests/chat/__init__.py +0 -0
- pygeai/tests/chat/test_clients.py +393 -0
- pygeai/tests/chat/test_iris.py +38 -0
- pygeai/tests/chat/test_session.py +62 -0
- pygeai/tests/chat/test_ui.py +224 -0
- pygeai/tests/cli/__init__.py +0 -0
- pygeai/tests/cli/commands/__init__.py +0 -0
- pygeai/tests/cli/commands/lab/__init__.py +0 -0
- pygeai/tests/cli/commands/lab/test_ai_lab.py +786 -0
- pygeai/tests/cli/commands/lab/test_common.py +208 -0
- pygeai/tests/cli/commands/lab/test_spec.py +246 -0
- pygeai/tests/cli/commands/test_assistant.py +202 -0
- pygeai/tests/cli/commands/test_chat.py +130 -0
- pygeai/tests/cli/commands/test_common.py +350 -0
- pygeai/tests/cli/commands/test_embeddings.py +132 -0
- pygeai/tests/cli/commands/test_evaluation.py +656 -0
- pygeai/tests/cli/commands/test_feedback.py +65 -0
- pygeai/tests/cli/commands/test_files.py +161 -0
- pygeai/tests/cli/commands/test_gam.py +201 -0
- pygeai/tests/cli/commands/test_llm.py +114 -0
- pygeai/tests/cli/commands/test_migrate.py +176 -0
- pygeai/tests/cli/commands/test_organization.py +276 -0
- pygeai/tests/cli/commands/test_rag.py +266 -0
- pygeai/tests/cli/commands/test_rerank.py +110 -0
- pygeai/tests/cli/commands/test_secrets.py +171 -0
- pygeai/tests/cli/commands/test_show_help.py +41 -0
- pygeai/tests/cli/commands/test_usage_limits.py +412 -0
- pygeai/tests/cli/commands/test_validators.py +160 -0
- pygeai/tests/cli/commands/test_version.py +81 -0
- pygeai/tests/cli/docker/__init__.py +0 -0
- pygeai/tests/cli/test_credentials_flag.py +316 -0
- pygeai/tests/cli/test_error_handler.py +225 -0
- pygeai/tests/cli/test_geai_driver.py +154 -0
- pygeai/tests/cli/test_parsers.py +154 -0
- pygeai/tests/core/base/__init__.py +0 -0
- pygeai/tests/core/base/data/__init__.py +0 -0
- pygeai/tests/core/base/data/mappers.py +117 -0
- pygeai/tests/core/base/data/models.py +312 -0
- pygeai/tests/core/base/test_mappers.py +569 -0
- pygeai/tests/core/base/test_models.py +261 -0
- pygeai/tests/core/base/test_responses.py +53 -0
- pygeai/tests/core/common/__init__.py +0 -0
- pygeai/tests/core/common/data/__init__.py +0 -0
- pygeai/tests/core/common/test_config.py +186 -0
- pygeai/tests/core/common/test_decorators.py +69 -0
- pygeai/tests/core/embeddings/__init__.py +0 -0
- pygeai/tests/core/embeddings/test_clients.py +225 -0
- pygeai/tests/core/embeddings/test_managers.py +171 -0
- pygeai/tests/core/embeddings/test_mappers.py +142 -0
- pygeai/tests/core/feedback/__init__.py +0 -0
- pygeai/tests/core/feedback/test_clients.py +64 -0
- pygeai/tests/core/files/__init__.py +0 -0
- pygeai/tests/core/files/test_clients.py +128 -0
- pygeai/tests/core/files/test_managers.py +219 -0
- pygeai/tests/core/files/test_mappers.py +137 -0
- pygeai/tests/core/files/test_models.py +103 -0
- pygeai/tests/core/files/test_responses.py +122 -0
- pygeai/tests/core/llm/__init__.py +0 -0
- pygeai/tests/core/llm/test_clients.py +142 -0
- pygeai/tests/core/plugins/__init__.py +0 -0
- pygeai/tests/core/plugins/test_clients.py +66 -0
- pygeai/tests/core/rerank/__init__.py +0 -0
- pygeai/tests/core/rerank/test_clients.py +76 -0
- pygeai/tests/core/rerank/test_managers.py +99 -0
- pygeai/tests/core/rerank/test_mappers.py +54 -0
- pygeai/tests/core/secrets/__init__.py +0 -0
- pygeai/tests/core/secrets/test_clients.py +264 -0
- pygeai/tests/core/services/__init__.py +0 -0
- pygeai/tests/core/services/test_rest.py +273 -0
- pygeai/tests/core/test_handlers.py +66 -0
- pygeai/tests/core/utils/__init__.py +0 -0
- pygeai/tests/core/utils/test_console.py +80 -0
- pygeai/tests/dbg/__init__.py +0 -0
- pygeai/tests/dbg/test_debugger.py +591 -0
- pygeai/tests/evaluation/__init__.py +0 -0
- pygeai/tests/evaluation/dataset/__init__.py +0 -0
- pygeai/tests/evaluation/dataset/test_clients.py +265 -0
- pygeai/tests/evaluation/plan/__init__.py +0 -0
- pygeai/tests/evaluation/plan/test_clients.py +195 -0
- pygeai/tests/evaluation/result/__init__.py +0 -0
- pygeai/tests/evaluation/result/test_clients.py +66 -0
- pygeai/tests/gam/__init__.py +0 -0
- pygeai/tests/gam/test_clients.py +195 -0
- pygeai/tests/health/__init__.py +0 -0
- pygeai/tests/health/test_clients.py +41 -0
- pygeai/tests/integration/__init__.py +0 -0
- pygeai/tests/integration/assistants/__init__.py +0 -0
- pygeai/tests/integration/assistants/rag/__init__.py +0 -0
- pygeai/tests/integration/assistants/rag/test_create_rag.py +91 -0
- pygeai/tests/integration/chat/__init__.py +0 -0
- pygeai/tests/integration/chat/test_generate_image.py +158 -0
- pygeai/tests/integration/lab/__init__.py +0 -0
- pygeai/tests/integration/lab/agents/__init__.py +0 -0
- pygeai/tests/integration/lab/agents/test_agents_list.py +106 -0
- pygeai/tests/integration/lab/agents/test_create_agent.py +319 -0
- pygeai/tests/integration/lab/agents/test_create_sharing_link.py +70 -0
- pygeai/tests/integration/lab/agents/test_delete_agent.py +75 -0
- pygeai/tests/integration/lab/agents/test_get_agent.py +94 -0
- pygeai/tests/integration/lab/agents/test_publish_agent_revision.py +127 -0
- pygeai/tests/integration/lab/agents/test_update_agent.py +250 -0
- pygeai/tests/integration/lab/processes/__init__.py +0 -0
- pygeai/tests/integration/lab/processes/test_create_process.py +345 -0
- pygeai/tests/integration/lab/processes/test_create_task.py +211 -0
- pygeai/tests/integration/lab/processes/test_delete_process.py +111 -0
- pygeai/tests/integration/lab/processes/test_get_process.py +201 -0
- pygeai/tests/integration/lab/processes/test_list_process_instances.py +91 -0
- pygeai/tests/integration/lab/processes/test_list_processes.py +138 -0
- pygeai/tests/integration/lab/processes/test_publish_process_revision.py +232 -0
- pygeai/tests/integration/lab/processes/test_update_process.py +289 -0
- pygeai/tests/integration/lab/reasoning_strategies/__init__.py +0 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_get_reasoning_strategy.py +70 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_list_reasoning_strategies.py +93 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_update_reasoning_strategy.py +149 -0
- pygeai/tests/integration/lab/tools/__init__.py +0 -0
- pygeai/tests/integration/lab/tools/test_create_tool.py +288 -0
- pygeai/tests/integration/lab/tools/test_delete_tool.py +87 -0
- pygeai/tests/integration/lab/tools/test_get_parameter.py +98 -0
- pygeai/tests/integration/lab/tools/test_get_tool.py +91 -0
- pygeai/tests/integration/lab/tools/test_list_tools.py +106 -0
- pygeai/tests/integration/lab/tools/test_publish_tool_revision.py +119 -0
- pygeai/tests/integration/lab/tools/test_set_parameter.py +114 -0
- pygeai/tests/integration/lab/tools/test_update_tool.py +267 -0
- pygeai/tests/lab/__init__.py +0 -0
- pygeai/tests/lab/agents/__init__.py +0 -0
- pygeai/tests/lab/agents/test_clients.py +481 -0
- pygeai/tests/lab/agents/test_mappers.py +440 -0
- pygeai/tests/lab/processes/__init__.py +0 -0
- pygeai/tests/lab/processes/test_clients.py +1416 -0
- pygeai/tests/lab/processes/test_mappers.py +1092 -0
- pygeai/tests/lab/spec/__init__.py +0 -0
- pygeai/tests/lab/spec/test_loader.py +59 -0
- pygeai/tests/lab/spec/test_parsers.py +182 -0
- pygeai/tests/lab/strategies/__init__.py +0 -0
- pygeai/tests/lab/strategies/test_clients.py +241 -0
- pygeai/tests/lab/strategies/test_mappers.py +132 -0
- pygeai/tests/lab/test_managers.py +553 -0
- pygeai/tests/lab/test_mappers.py +245 -0
- pygeai/tests/lab/test_models.py +1154 -0
- pygeai/tests/lab/tools/__init__.py +0 -0
- pygeai/tests/lab/tools/test_clients.py +521 -0
- pygeai/tests/lab/tools/test_mappers.py +198 -0
- pygeai/tests/migration/__init__.py +0 -0
- pygeai/tests/migration/test_strategies.py +405 -0
- pygeai/tests/migration/test_tools.py +159 -0
- pygeai/tests/organization/limits/__init__.py +0 -0
- pygeai/tests/organization/limits/test_clients.py +567 -0
- pygeai/tests/organization/limits/test_managers.py +402 -0
- pygeai/tests/organization/test_clients.py +615 -64
- pygeai/tests/organization/test_managers.py +424 -0
- pygeai/tests/organization/test_mappers.py +153 -0
- pygeai/tests/organization/test_responses.py +137 -0
- pygeai/tests/proxy/__init__.py +1 -0
- pygeai/tests/proxy/test_clients.py +397 -0
- pygeai/tests/proxy/test_config.py +171 -0
- pygeai/tests/proxy/test_integration.py +305 -0
- pygeai/tests/proxy/test_managers.py +312 -0
- pygeai/tests/proxy/test_servers.py +387 -0
- pygeai/tests/proxy/test_tool.py +176 -0
- pygeai/tests/snippets/__init__.py +0 -0
- pygeai/tests/snippets/analytics/__init__.py +0 -0
- pygeai/tests/snippets/analytics/get_agent_usage_per_user.py +16 -0
- pygeai/tests/snippets/analytics/get_agents_created_and_modified.py +11 -0
- pygeai/tests/snippets/analytics/get_average_cost_per_request.py +10 -0
- pygeai/tests/snippets/analytics/get_overall_error_rate.py +10 -0
- pygeai/tests/snippets/analytics/get_top_10_agents_by_requests.py +12 -0
- pygeai/tests/snippets/analytics/get_total_active_users.py +10 -0
- pygeai/tests/snippets/analytics/get_total_cost.py +10 -0
- pygeai/tests/snippets/analytics/get_total_requests_per_day.py +12 -0
- pygeai/tests/snippets/analytics/get_total_tokens.py +12 -0
- pygeai/tests/snippets/assistants/__init__.py +0 -0
- pygeai/tests/snippets/assistants/create_chat_assistant.py +54 -0
- pygeai/tests/snippets/assistants/create_text_assistant.py +51 -0
- pygeai/tests/snippets/assistants/data_analyst/__init__.py +0 -0
- pygeai/tests/snippets/assistants/data_analyst/extend_and_check.py +100 -0
- pygeai/tests/snippets/assistants/data_analyst/extend_dataset.py +9 -0
- pygeai/tests/snippets/assistants/data_analyst/get_status.py +9 -0
- pygeai/tests/snippets/assistants/file_summarizer_assistant.py +149 -0
- pygeai/tests/snippets/assistants/get_assistant_data.py +8 -0
- pygeai/tests/snippets/assistants/get_assistant_list.py +7 -0
- pygeai/tests/snippets/assistants/rag/__init__.py +0 -0
- pygeai/tests/snippets/assistants/rag/create_rag_assistant.py +65 -0
- pygeai/tests/snippets/assistants/rag/delete_al_documents.py +7 -0
- pygeai/tests/snippets/assistants/rag/delete_document.py +10 -0
- pygeai/tests/snippets/assistants/rag/delete_rag_assistant.py +8 -0
- pygeai/tests/snippets/assistants/rag/get_document.py +10 -0
- pygeai/tests/snippets/assistants/rag/get_documents.py +7 -0
- pygeai/tests/snippets/assistants/rag/get_rag_assistant_data.py +8 -0
- pygeai/tests/snippets/assistants/rag/update_rag_assistant.py +48 -0
- pygeai/tests/snippets/assistants/rag/upload_document.py +19 -0
- pygeai/tests/snippets/assistants/send_feedback.py +14 -0
- pygeai/tests/snippets/assistants/update_chat_assistant.py +63 -0
- pygeai/tests/snippets/auth/__init__.py +0 -0
- pygeai/tests/snippets/chat/__init__.py +0 -0
- pygeai/tests/snippets/chat/cancel_request.py +7 -0
- pygeai/tests/snippets/chat/chat_completion.py +28 -0
- pygeai/tests/snippets/chat/chat_completion_1.py +40 -0
- pygeai/tests/snippets/chat/chat_completion_2.py +60 -0
- pygeai/tests/snippets/chat/chat_completion_3.py +27 -0
- pygeai/tests/snippets/chat/chat_completion_4.py +67 -0
- pygeai/tests/snippets/chat/chat_completion_streaming.py +63 -0
- pygeai/tests/snippets/chat/chat_completion_with_reasoning_effort.py +18 -0
- pygeai/tests/snippets/chat/get_request_status.py +7 -0
- pygeai/tests/snippets/chat/get_response.py +15 -0
- pygeai/tests/snippets/chat/get_response_complete_example.py +67 -0
- pygeai/tests/snippets/chat/get_response_streaming.py +20 -0
- pygeai/tests/snippets/chat/get_response_with_files.py +16 -0
- pygeai/tests/snippets/chat/get_response_with_instructions.py +19 -0
- pygeai/tests/snippets/chat/get_response_with_metadata.py +24 -0
- pygeai/tests/snippets/chat/get_response_with_parallel_tools.py +58 -0
- pygeai/tests/snippets/chat/get_response_with_reasoning.py +21 -0
- pygeai/tests/snippets/chat/get_response_with_store.py +38 -0
- pygeai/tests/snippets/chat/get_response_with_tools.py +36 -0
- pygeai/tests/snippets/chat/get_response_with_truncation.py +24 -0
- pygeai/tests/snippets/chat/send_chat_request.py +33 -0
- pygeai/tests/snippets/dbg/__init__.py +0 -0
- pygeai/tests/snippets/dbg/basic_debugging.py +32 -0
- pygeai/tests/snippets/dbg/breakpoint_management.py +48 -0
- pygeai/tests/snippets/dbg/file_debugging.py +72 -0
- pygeai/tests/snippets/dbg/module_debugging.py +61 -0
- pygeai/tests/snippets/dbg/stack_navigation.py +45 -0
- pygeai/tests/snippets/dbg/stepping_example.py +40 -0
- pygeai/tests/snippets/embeddings/__init__.py +0 -0
- pygeai/tests/snippets/embeddings/cache_example.py +31 -0
- pygeai/tests/snippets/embeddings/cohere_example.py +41 -0
- pygeai/tests/snippets/embeddings/generate_embeddings.py +26 -0
- pygeai/tests/snippets/embeddings/openai_base64_example.py +27 -0
- pygeai/tests/snippets/embeddings/openai_example.py +30 -0
- pygeai/tests/snippets/embeddings/similarity_example.py +42 -0
- pygeai/tests/snippets/evaluation/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/dataset/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/dataset/complete_workflow_example.py +195 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset.py +26 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset_from_file.py +11 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset_row.py +17 -0
- pygeai/tests/snippets/evaluation/dataset/create_expected_source.py +18 -0
- pygeai/tests/snippets/evaluation/dataset/create_filter_variable.py +19 -0
- pygeai/tests/snippets/evaluation/dataset/delete_dataset.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/delete_dataset_row.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/delete_expected_source.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/delete_filter_variable.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/get_dataset.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/get_dataset_row.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/get_expected_source.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/get_filter_variable.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/list_dataset_rows.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/list_datasets.py +6 -0
- pygeai/tests/snippets/evaluation/dataset/list_expected_sources.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/list_filter_variables.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/update_dataset.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/update_dataset_row.py +20 -0
- pygeai/tests/snippets/evaluation/dataset/update_expected_source.py +18 -0
- pygeai/tests/snippets/evaluation/dataset/update_filter_variable.py +19 -0
- pygeai/tests/snippets/evaluation/dataset/upload_dataset_rows_file.py +10 -0
- pygeai/tests/snippets/evaluation/plan/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/plan/add_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/complete_workflow_example.py +136 -0
- pygeai/tests/snippets/evaluation/plan/create_evaluation_plan.py +24 -0
- pygeai/tests/snippets/evaluation/plan/create_rag_evaluation_plan.py +22 -0
- pygeai/tests/snippets/evaluation/plan/delete_evaluation_plan.py +9 -0
- pygeai/tests/snippets/evaluation/plan/delete_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/execute_evaluation_plan.py +11 -0
- pygeai/tests/snippets/evaluation/plan/get_evaluation_plan.py +9 -0
- pygeai/tests/snippets/evaluation/plan/get_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/get_system_metric.py +9 -0
- pygeai/tests/snippets/evaluation/plan/list_evaluation_plans.py +7 -0
- pygeai/tests/snippets/evaluation/plan/list_plan_system_metrics.py +9 -0
- pygeai/tests/snippets/evaluation/plan/list_system_metrics.py +7 -0
- pygeai/tests/snippets/evaluation/plan/update_evaluation_plan.py +22 -0
- pygeai/tests/snippets/evaluation/plan/update_plan_system_metric.py +14 -0
- pygeai/tests/snippets/evaluation/result/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/result/complete_workflow_example.py +150 -0
- pygeai/tests/snippets/evaluation/result/get_evaluation_result.py +26 -0
- pygeai/tests/snippets/evaluation/result/list_evaluation_results.py +17 -0
- pygeai/tests/snippets/files/__init__.py +0 -0
- pygeai/tests/snippets/files/delete_file.py +9 -0
- pygeai/tests/snippets/files/get_file_content.py +10 -0
- pygeai/tests/snippets/files/get_file_data.py +9 -0
- pygeai/tests/snippets/files/get_file_list.py +6 -0
- pygeai/tests/snippets/files/upload_file.py +13 -0
- pygeai/tests/snippets/gam/__init__.py +0 -0
- pygeai/tests/snippets/gam/gam_access_token.py +87 -0
- pygeai/tests/snippets/lab/__init__.py +0 -0
- pygeai/tests/snippets/lab/agentic_flow_example_1.py +326 -0
- pygeai/tests/snippets/lab/agentic_flow_example_2.py +206 -0
- pygeai/tests/snippets/lab/agentic_flow_example_3.py +486 -0
- pygeai/tests/snippets/lab/agentic_flow_example_4.py +446 -0
- pygeai/tests/snippets/lab/agents/__init__.py +0 -0
- pygeai/tests/snippets/lab/agents/create_agent.py +48 -0
- pygeai/tests/snippets/lab/agents/create_agent_2.py +48 -0
- pygeai/tests/snippets/lab/agents/create_agent_edge_case.py +48 -0
- pygeai/tests/snippets/lab/agents/create_agent_with_permissions.py +39 -0
- pygeai/tests/snippets/lab/agents/create_agent_with_properties.py +46 -0
- pygeai/tests/snippets/lab/agents/create_agent_without_instructions.py +48 -0
- pygeai/tests/snippets/lab/agents/delete_agent.py +12 -0
- pygeai/tests/snippets/lab/agents/get_agent.py +24 -0
- pygeai/tests/snippets/lab/agents/get_agent_with_new_fields.py +62 -0
- pygeai/tests/snippets/lab/agents/get_sharing_link.py +13 -0
- pygeai/tests/snippets/lab/agents/list_agents.py +18 -0
- pygeai/tests/snippets/lab/agents/publish_agent_revision.py +12 -0
- pygeai/tests/snippets/lab/agents/update_agent.py +50 -0
- pygeai/tests/snippets/lab/agents/update_agent_properties.py +50 -0
- pygeai/tests/snippets/lab/assistant_to_agent.py +191 -0
- pygeai/tests/snippets/lab/crud_ui.py +462 -0
- pygeai/tests/snippets/lab/processes/__init__.py +0 -0
- pygeai/tests/snippets/lab/processes/create_process.py +24 -0
- pygeai/tests/snippets/lab/processes/create_task.py +8 -0
- pygeai/tests/snippets/lab/processes/jobs/__init__.py +0 -0
- pygeai/tests/snippets/lab/processes/jobs/list_jobs.py +21 -0
- pygeai/tests/snippets/lab/processes/kbs/__init__.py +0 -0
- pygeai/tests/snippets/lab/processes/kbs/create_kb.py +18 -0
- pygeai/tests/snippets/lab/processes/kbs/get_kb.py +26 -0
- pygeai/tests/snippets/lab/processes/kbs/list_kbs.py +30 -0
- pygeai/tests/snippets/lab/processes/kbs/try_all.py +73 -0
- pygeai/tests/snippets/lab/processes/list_processes.py +10 -0
- pygeai/tests/snippets/lab/runner_1.py +212 -0
- pygeai/tests/snippets/lab/samples/__init__.py +0 -0
- pygeai/tests/snippets/lab/samples/summarize_files.py +162 -0
- pygeai/tests/snippets/lab/strategies/__init__.py +0 -0
- pygeai/tests/snippets/lab/strategies/create_reasoning_strategy.py +22 -0
- pygeai/tests/snippets/lab/strategies/get_reasoning_strategy.py +10 -0
- pygeai/tests/snippets/lab/strategies/list_reasoning_strategies.py +16 -0
- pygeai/tests/snippets/lab/strategies/update_reasoning_strategy.py +26 -0
- pygeai/tests/snippets/lab/tools/__init__.py +0 -0
- pygeai/tests/snippets/lab/tools/create_tool.py +48 -0
- pygeai/tests/snippets/lab/tools/create_tool_edge_case.py +50 -0
- pygeai/tests/snippets/lab/tools/delete_tool.py +21 -0
- pygeai/tests/snippets/lab/tools/get_parameter.py +21 -0
- pygeai/tests/snippets/lab/tools/get_tool.py +22 -0
- pygeai/tests/snippets/lab/tools/list_tools.py +23 -0
- pygeai/tests/snippets/lab/tools/publish_tool_revision.py +13 -0
- pygeai/tests/snippets/lab/tools/set_parameters.py +33 -0
- pygeai/tests/snippets/lab/tools/update_tool.py +52 -0
- pygeai/tests/snippets/lab/use_cases/__init__.py +0 -0
- pygeai/tests/snippets/lab/use_cases/c_code_fixer_agent_flow.py +238 -0
- pygeai/tests/snippets/lab/use_cases/create_cli_expert.py +1640 -0
- pygeai/tests/snippets/lab/use_cases/create_lab_expert.py +4541 -0
- pygeai/tests/snippets/lab/use_cases/create_tool_headless_web_browser.py +133 -0
- pygeai/tests/snippets/lab/use_cases/create_web_designer.py +189 -0
- pygeai/tests/snippets/lab/use_cases/create_web_reader.py +185 -0
- pygeai/tests/snippets/lab/use_cases/file_summarizer_example.py +157 -0
- pygeai/tests/snippets/lab/use_cases/file_summarizer_example_2.py +157 -0
- pygeai/tests/snippets/lab/use_cases/update_cli_expert.py +1773 -0
- pygeai/tests/snippets/lab/use_cases/update_lab_expert.py +4541 -0
- pygeai/tests/snippets/lab/use_cases/update_web_designer.py +188 -0
- pygeai/tests/snippets/lab/use_cases/update_web_reader.py +195 -0
- pygeai/tests/snippets/lab/use_cases/update_web_reader_with_tool.py +210 -0
- pygeai/tests/snippets/migrate/__init__.py +45 -0
- pygeai/tests/snippets/migrate/agent_migration.py +110 -0
- pygeai/tests/snippets/migrate/assistant_migration.py +64 -0
- pygeai/tests/snippets/migrate/orchestrator_examples.py +179 -0
- pygeai/tests/snippets/migrate/process_migration.py +64 -0
- pygeai/tests/snippets/migrate/project_migration.py +42 -0
- pygeai/tests/snippets/migrate/tool_migration.py +64 -0
- pygeai/tests/snippets/organization/__init__.py +0 -0
- pygeai/tests/snippets/organization/add_project_member.py +10 -0
- pygeai/tests/snippets/organization/add_project_member_batch.py +44 -0
- pygeai/tests/snippets/organization/create_project.py +23 -0
- pygeai/tests/snippets/organization/delete_project.py +7 -0
- pygeai/tests/snippets/organization/export_request_data.py +7 -0
- pygeai/tests/snippets/organization/get_memberships.py +12 -0
- pygeai/tests/snippets/organization/get_organization_members.py +6 -0
- pygeai/tests/snippets/organization/get_project_data.py +7 -0
- pygeai/tests/snippets/organization/get_project_list.py +8 -0
- pygeai/tests/snippets/organization/get_project_members.py +6 -0
- pygeai/tests/snippets/organization/get_project_memberships.py +12 -0
- pygeai/tests/snippets/organization/get_project_roles.py +6 -0
- pygeai/tests/snippets/organization/get_project_tokens.py +7 -0
- pygeai/tests/snippets/organization/update_project.py +14 -0
- pygeai/tests/snippets/rerank/__init__.py +0 -0
- pygeai/tests/snippets/rerank/rerank_chunks.py +19 -0
- pygeai/tests/snippets/secrets/__init__.py +0 -0
- pygeai/tests/snippets/usage_limit/__init__.py +0 -0
- pygeai/tests/snippets/usage_limit/delete_usage_limit.py +16 -0
- pygeai/tests/snippets/usage_limit/get_all_usage_limit_from_organization.py +12 -0
- pygeai/tests/snippets/usage_limit/get_usage_limit_from_organization.py +11 -0
- pygeai/tests/snippets/usage_limit/get_usage_limit_from_project.py +13 -0
- pygeai/tests/snippets/usage_limit/set_usage_limit_organization.py +22 -0
- pygeai/tests/snippets/usage_limit/set_usage_limit_project.py +23 -0
- pygeai/tests/snippets/usage_limit/update_usage_limit_organization.py +23 -0
- pygeai/tests/snippets/usage_limit/update_usage_limit_project.py +24 -0
- pygeai/vendor/a2a/__init__.py +1 -0
- pygeai/vendor/a2a/auth/__init__.py +0 -0
- pygeai/vendor/a2a/auth/user.py +31 -0
- pygeai/vendor/a2a/client/__init__.py +19 -0
- pygeai/vendor/a2a/client/client.py +425 -0
- pygeai/vendor/a2a/client/errors.py +33 -0
- pygeai/vendor/a2a/client/helpers.py +22 -0
- pygeai/vendor/a2a/py.typed +0 -0
- pygeai/vendor/a2a/server/__init__.py +1 -0
- pygeai/vendor/a2a/server/agent_execution/__init__.py +18 -0
- pygeai/vendor/a2a/server/agent_execution/agent_executor.py +44 -0
- pygeai/vendor/a2a/server/agent_execution/context.py +155 -0
- pygeai/vendor/a2a/server/agent_execution/request_context_builder.py +20 -0
- pygeai/vendor/a2a/server/agent_execution/simple_request_context_builder.py +77 -0
- pygeai/vendor/a2a/server/apps/__init__.py +16 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/__init__.py +16 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/fastapi_app.py +88 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/jsonrpc_app.py +426 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/starlette_app.py +123 -0
- pygeai/vendor/a2a/server/context.py +23 -0
- pygeai/vendor/a2a/server/events/__init__.py +21 -0
- pygeai/vendor/a2a/server/events/event_consumer.py +149 -0
- pygeai/vendor/a2a/server/events/event_queue.py +156 -0
- pygeai/vendor/a2a/server/events/in_memory_queue_manager.py +85 -0
- pygeai/vendor/a2a/server/events/queue_manager.py +35 -0
- pygeai/vendor/a2a/server/request_handlers/__init__.py +20 -0
- pygeai/vendor/a2a/server/request_handlers/default_request_handler.py +435 -0
- pygeai/vendor/a2a/server/request_handlers/jsonrpc_handler.py +327 -0
- pygeai/vendor/a2a/server/request_handlers/request_handler.py +161 -0
- pygeai/vendor/a2a/server/request_handlers/response_helpers.py +133 -0
- pygeai/vendor/a2a/server/tasks/__init__.py +20 -0
- pygeai/vendor/a2a/server/tasks/inmemory_push_notifier.py +62 -0
- pygeai/vendor/a2a/server/tasks/inmemory_task_store.py +51 -0
- pygeai/vendor/a2a/server/tasks/push_notifier.py +25 -0
- pygeai/vendor/a2a/server/tasks/result_aggregator.py +151 -0
- pygeai/vendor/a2a/server/tasks/task_manager.py +253 -0
- pygeai/vendor/a2a/server/tasks/task_store.py +22 -0
- pygeai/vendor/a2a/server/tasks/task_updater.py +155 -0
- pygeai/vendor/a2a/types.py +1624 -0
- pygeai/vendor/a2a/utils/__init__.py +40 -0
- pygeai/vendor/a2a/utils/artifact.py +72 -0
- pygeai/vendor/a2a/utils/errors.py +69 -0
- pygeai/vendor/a2a/utils/helpers.py +176 -0
- pygeai/vendor/a2a/utils/message.py +83 -0
- pygeai/vendor/a2a/utils/task.py +57 -0
- pygeai/vendor/a2a/utils/telemetry.py +299 -0
- pygeai-0.6.0b15.dist-info/METADATA +205 -0
- pygeai-0.6.0b15.dist-info/RECORD +799 -0
- {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info}/WHEEL +1 -1
- pygeai-0.6.0b15.dist-info/entry_points.txt +5 -0
- {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info/licenses}/LICENSE +13 -1
- {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info}/top_level.txt +0 -1
- docs/source/conf.py +0 -45
- pygeai/core/clients.py +0 -240
- pygeai/tests/core/test_clients.py +0 -49
- pygeai-0.1.6.dist-info/METADATA +0 -92
- pygeai-0.1.6.dist-info/RECORD +0 -65
- pygeai-0.1.6.dist-info/SOURCES.sync-conflict-20241223-145950-3QD4F42.txt +0 -41
- pygeai-0.1.6.dist-info/entry_points.txt +0 -2
- /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
|
+
]
|