pygeai 0.1.51b3__py3-none-any.whl → 0.6.0b15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pygeai might be problematic. Click here for more details.
- pygeai/__init__.py +9 -1
- 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 +18 -45
- pygeai/assistant/data/clients.py +1 -0
- pygeai/assistant/data_analyst/clients.py +8 -12
- pygeai/assistant/managers.py +195 -157
- pygeai/assistant/mappers.py +4 -2
- pygeai/assistant/rag/clients.py +27 -67
- pygeai/assistant/rag/mappers.py +12 -6
- pygeai/assistant/rag/models.py +301 -159
- pygeai/auth/__init__.py +0 -0
- pygeai/auth/clients.py +129 -0
- pygeai/auth/endpoints.py +6 -0
- pygeai/chat/clients.py +308 -37
- pygeai/chat/endpoints.py +3 -0
- pygeai/chat/iris.py +2 -8
- pygeai/chat/managers.py +9 -6
- 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 +7 -10
- pygeai/cli/commands/analytics.py +533 -0
- pygeai/cli/commands/assistant.py +9 -9
- pygeai/cli/commands/auth.py +299 -0
- pygeai/cli/commands/base.py +71 -9
- pygeai/cli/commands/chat.py +676 -19
- pygeai/cli/commands/common.py +28 -24
- pygeai/cli/commands/configuration.py +66 -13
- pygeai/cli/commands/docs.py +105 -0
- pygeai/cli/commands/embeddings.py +58 -11
- pygeai/cli/commands/evaluation.py +38 -38
- pygeai/cli/commands/feedback.py +3 -4
- pygeai/cli/commands/files.py +7 -8
- pygeai/cli/commands/gam.py +85 -10
- pygeai/cli/commands/lab/ai_lab.py +340 -484
- 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 +6 -7
- pygeai/cli/commands/migrate.py +1064 -436
- pygeai/cli/commands/organization.py +516 -11
- pygeai/cli/commands/rag.py +13 -14
- pygeai/cli/commands/rerank.py +3 -5
- pygeai/cli/commands/secrets.py +8 -9
- pygeai/cli/commands/usage_limits.py +18 -20
- pygeai/cli/commands/validators.py +144 -1
- pygeai/cli/commands/version.py +4 -5
- pygeai/cli/error_handler.py +151 -0
- pygeai/cli/geai.py +170 -31
- pygeai/cli/geai_proxy.py +86 -25
- pygeai/cli/install_man.py +93 -22
- pygeai/cli/parsers.py +75 -25
- pygeai/cli/texts/help.py +265 -28
- pygeai/core/base/clients.py +53 -12
- pygeai/core/base/mappers.py +11 -2
- pygeai/core/base/session.py +95 -11
- pygeai/core/common/config.py +78 -14
- pygeai/core/common/exceptions.py +96 -6
- pygeai/core/embeddings/__init__.py +19 -0
- pygeai/core/embeddings/clients.py +23 -5
- pygeai/core/embeddings/managers.py +9 -4
- pygeai/core/embeddings/mappers.py +16 -2
- pygeai/core/embeddings/responses.py +9 -2
- pygeai/core/feedback/clients.py +8 -3
- pygeai/core/files/clients.py +23 -24
- pygeai/core/files/managers.py +121 -30
- pygeai/core/files/responses.py +4 -3
- pygeai/core/handlers.py +10 -1
- pygeai/core/llm/clients.py +22 -29
- pygeai/core/models.py +127 -11
- pygeai/core/plugins/clients.py +6 -6
- pygeai/core/rerank/clients.py +9 -3
- pygeai/core/rerank/managers.py +22 -5
- pygeai/core/secrets/clients.py +16 -37
- pygeai/core/services/response.py +18 -0
- pygeai/core/services/rest.py +159 -49
- 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 +854 -14
- pygeai/evaluation/clients.py +7 -4
- pygeai/evaluation/dataset/clients.py +46 -44
- pygeai/evaluation/plan/clients.py +28 -26
- pygeai/evaluation/result/clients.py +38 -5
- pygeai/gam/clients.py +50 -28
- pygeai/gam/endpoints.py +2 -1
- pygeai/health/__init__.py +0 -0
- pygeai/health/clients.py +24 -0
- pygeai/health/endpoints.py +1 -0
- pygeai/lab/__init__.py +0 -90
- pygeai/lab/agents/clients.py +203 -162
- pygeai/lab/agents/endpoints.py +4 -0
- pygeai/lab/agents/mappers.py +57 -7
- pygeai/lab/clients.py +24 -0
- pygeai/lab/constants.py +3 -0
- pygeai/lab/managers.py +571 -541
- pygeai/lab/models.py +108 -19
- pygeai/lab/processes/clients.py +332 -340
- pygeai/lab/processes/mappers.py +3 -3
- 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/clients.py +67 -63
- pygeai/lab/strategies/mappers.py +1 -1
- pygeai/lab/tools/clients.py +85 -118
- pygeai/lab/tools/endpoints.py +4 -0
- pygeai/lab/tools/mappers.py +5 -5
- pygeai/man/man1/geai-proxy.1 +116 -0
- pygeai/man/man1/geai.1 +2580 -66
- pygeai/migration/__init__.py +33 -0
- pygeai/migration/strategies.py +468 -146
- pygeai/migration/tools.py +170 -3
- pygeai/organization/clients.py +245 -50
- pygeai/organization/endpoints.py +17 -8
- pygeai/organization/limits/clients.py +34 -32
- pygeai/organization/limits/managers.py +108 -49
- pygeai/organization/managers.py +347 -53
- pygeai/organization/mappers.py +102 -2
- pygeai/organization/responses.py +58 -1
- pygeai/proxy/clients.py +6 -3
- pygeai/proxy/config.py +14 -1
- pygeai/proxy/managers.py +61 -33
- pygeai/proxy/servers.py +196 -51
- pygeai/proxy/tool.py +33 -16
- 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/test_clients.py +346 -0
- pygeai/tests/assistants/rag/test_models.py +292 -0
- pygeai/tests/assistants/test_clients.py +176 -82
- pygeai/tests/assistants/test_managers.py +191 -57
- 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/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 +5 -5
- pygeai/tests/core/base/data/models.py +7 -0
- pygeai/tests/core/base/test_mappers.py +43 -11
- pygeai/tests/core/base/test_models.py +3 -1
- 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/test_clients.py +128 -0
- pygeai/tests/core/files/test_managers.py +124 -78
- 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/test_clients.py +76 -0
- pygeai/tests/core/rerank/test_managers.py +61 -39
- 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/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_models.py +500 -3
- 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/test_clients.py +567 -0
- pygeai/tests/organization/limits/test_managers.py +298 -56
- pygeai/tests/organization/test_clients.py +600 -30
- 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/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/auth/__init__.py +0 -0
- pygeai/tests/snippets/chat/chat_completion_with_reasoning_effort.py +18 -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/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/cache_example.py +31 -0
- pygeai/tests/snippets/embeddings/cohere_example.py +41 -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/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/delete_file.py +1 -4
- pygeai/tests/snippets/files/get_file_content.py +2 -4
- pygeai/tests/snippets/files/get_file_data.py +1 -4
- pygeai/tests/snippets/files/get_file_list.py +1 -6
- pygeai/tests/snippets/files/upload_file.py +1 -5
- pygeai/tests/snippets/gam/gam_access_token.py +87 -0
- pygeai/tests/snippets/lab/agentic_flow_example_1.py +25 -23
- pygeai/tests/snippets/lab/agentic_flow_example_4.py +23 -23
- pygeai/tests/snippets/lab/agents/create_agent.py +5 -8
- pygeai/tests/snippets/lab/agents/create_agent_2.py +1 -5
- 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 +1 -5
- pygeai/tests/snippets/lab/agents/get_agent.py +2 -11
- pygeai/tests/snippets/lab/agents/get_agent_with_new_fields.py +62 -0
- pygeai/tests/snippets/lab/agents/get_sharing_link.py +2 -7
- pygeai/tests/snippets/lab/agents/list_agents.py +4 -7
- pygeai/tests/snippets/lab/agents/publish_agent_revision.py +2 -6
- pygeai/tests/snippets/lab/agents/update_agent.py +1 -5
- 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/create_process.py +3 -5
- pygeai/tests/snippets/lab/processes/create_task.py +3 -5
- pygeai/tests/snippets/lab/processes/jobs/list_jobs.py +10 -19
- pygeai/tests/snippets/lab/processes/kbs/create_kb.py +2 -5
- pygeai/tests/snippets/lab/processes/kbs/get_kb.py +10 -16
- pygeai/tests/snippets/lab/processes/kbs/list_kbs.py +13 -20
- pygeai/tests/snippets/lab/processes/kbs/try_all.py +5 -7
- pygeai/tests/snippets/lab/processes/list_processes.py +5 -7
- pygeai/tests/snippets/lab/runner_1.py +1 -1
- pygeai/tests/snippets/lab/samples/summarize_files.py +3 -3
- pygeai/tests/snippets/lab/strategies/create_reasoning_strategy.py +2 -5
- pygeai/tests/snippets/lab/strategies/get_reasoning_strategy.py +2 -5
- pygeai/tests/snippets/lab/strategies/list_reasoning_strategies.py +3 -6
- pygeai/tests/snippets/lab/strategies/update_reasoning_strategy.py +2 -5
- pygeai/tests/snippets/lab/tools/create_tool.py +4 -10
- pygeai/tests/snippets/lab/tools/create_tool_edge_case.py +50 -0
- pygeai/tests/snippets/lab/tools/delete_tool.py +2 -6
- pygeai/tests/snippets/lab/tools/get_parameter.py +5 -7
- pygeai/tests/snippets/lab/tools/get_tool.py +5 -7
- pygeai/tests/snippets/lab/tools/list_tools.py +3 -7
- pygeai/tests/snippets/lab/tools/publish_tool_revision.py +3 -5
- pygeai/tests/snippets/lab/tools/set_parameters.py +4 -9
- pygeai/tests/snippets/lab/tools/update_tool.py +4 -8
- pygeai/tests/snippets/lab/use_cases/__init__.py +0 -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/{file_summarizer_example.py → use_cases/file_summarizer_example.py} +3 -3
- pygeai/tests/snippets/lab/{file_summarizer_example_2.py → use_cases/file_summarizer_example_2.py} +12 -12
- 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/add_project_member.py +10 -0
- pygeai/tests/snippets/organization/add_project_member_batch.py +44 -0
- pygeai/tests/snippets/organization/create_project.py +2 -2
- 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_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/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.51b3.dist-info → pygeai-0.6.0b15.dist-info}/WHEEL +1 -1
- {pygeai-0.1.51b3.dist-info → pygeai-0.6.0b15.dist-info}/entry_points.txt +2 -1
- {pygeai-0.1.51b3.dist-info → pygeai-0.6.0b15.dist-info}/licenses/LICENSE +13 -1
- pygeai-0.6.0b15.dist-info/top_level.txt +1 -0
- docs/geai-proxy/README.md +0 -145
- docs/source/conf.py +0 -45
- pygeai/tests/core/test_managers.py +0 -233
- pygeai-0.1.51b3.dist-info/METADATA +0 -130
- pygeai-0.1.51b3.dist-info/RECORD +0 -324
- pygeai-0.1.51b3.dist-info/top_level.txt +0 -3
- scripts/bump_beta_version.py +0 -56
- {scripts → pygeai/analytics}/__init__.py +0 -0
- /pygeai/tests/snippets/lab/{c_code_fixer_agent_flow.py → use_cases/c_code_fixer_agent_flow.py} +0 -0
pygeai/cli/commands/migrate.py
CHANGED
|
@@ -1,516 +1,1181 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
from typing import Tuple, Dict, Any, Optional, List
|
|
2
|
+
from pygeai import logger
|
|
3
3
|
from pygeai.cli.commands import Command, Option, ArgumentsEnum
|
|
4
4
|
from pygeai.cli.commands.builders import build_help_text
|
|
5
5
|
from pygeai.cli.texts.help import MIGRATE_HELP_TEXT
|
|
6
6
|
from pygeai.core.common.exceptions import MissingRequirementException
|
|
7
|
-
from pygeai.
|
|
8
|
-
|
|
9
|
-
from pygeai.
|
|
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
|
|
10
28
|
|
|
11
29
|
|
|
12
|
-
def show_help():
|
|
30
|
+
def show_help() -> None:
|
|
13
31
|
"""
|
|
14
|
-
Displays help text in stdout
|
|
32
|
+
Displays help text in stdout.
|
|
15
33
|
"""
|
|
16
34
|
help_text = build_help_text(migrate_commands, MIGRATE_HELP_TEXT)
|
|
17
|
-
|
|
35
|
+
Console.write_stdout(help_text)
|
|
18
36
|
|
|
19
37
|
|
|
20
|
-
def
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
|
25
63
|
|
|
26
|
-
for option_flag, option_arg in option_list:
|
|
27
|
-
if option_flag.name == "from_api_key":
|
|
28
|
-
from_api_key = option_arg
|
|
29
|
-
if option_flag.name == "from_instance":
|
|
30
|
-
from_instance = option_arg
|
|
31
|
-
if option_flag.name == "to_api_key":
|
|
32
|
-
to_api_key = option_arg
|
|
33
|
-
if option_flag.name == "to_instance":
|
|
34
|
-
to_instance = option_arg
|
|
35
64
|
|
|
36
|
-
|
|
37
|
-
|
|
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
|
|
38
118
|
|
|
39
|
-
return from_api_key, from_instance, to_api_key, to_instance
|
|
40
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
|
|
41
136
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
"Destination
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
|
68
182
|
|
|
69
183
|
|
|
70
|
-
def
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
|
75
198
|
to_project_name = None
|
|
76
|
-
to_instance = None
|
|
77
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
|
|
78
215
|
|
|
79
|
-
for option_flag, option_arg in option_list:
|
|
80
|
-
if option_flag.name == "from_api_key":
|
|
81
|
-
from_api_key = option_arg
|
|
82
|
-
if option_flag.name == "from_project_id":
|
|
83
|
-
from_project_id = option_arg
|
|
84
|
-
if option_flag.name == "from_instance":
|
|
85
|
-
from_instance = option_arg
|
|
86
|
-
if option_flag.name == "to_api_key":
|
|
87
|
-
to_api_key = option_arg
|
|
88
|
-
if option_flag.name == "to_project_name":
|
|
89
|
-
to_project_name = option_arg
|
|
90
|
-
if option_flag.name == "to_instance":
|
|
91
|
-
to_instance = option_arg
|
|
92
|
-
if option_flag.name == "admin_email":
|
|
93
|
-
admin_email = option_arg
|
|
94
216
|
|
|
95
|
-
|
|
96
|
-
|
|
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
|
|
97
247
|
|
|
98
|
-
if not admin_email:
|
|
99
|
-
raise MissingRequirementException("Admin email for new project must be defined.")
|
|
100
248
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
|
112
265
|
|
|
113
|
-
sys.stdout.write(f"Migration result: \n{response}\n")
|
|
114
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
|
|
115
283
|
|
|
116
|
-
clone_project_options = [
|
|
117
|
-
Option(
|
|
118
|
-
"from_api_key",
|
|
119
|
-
["--from-api-key", "--fak"],
|
|
120
|
-
"API key for the source instance",
|
|
121
|
-
True
|
|
122
|
-
),
|
|
123
|
-
Option(
|
|
124
|
-
"from_project_id",
|
|
125
|
-
["--from-project-id", "--fpid"],
|
|
126
|
-
"ID of the source project to migrate from",
|
|
127
|
-
True
|
|
128
|
-
),
|
|
129
|
-
Option(
|
|
130
|
-
"from_instance",
|
|
131
|
-
["--from-instance", "--fi"],
|
|
132
|
-
"URL from the source instance to migrate from",
|
|
133
|
-
True
|
|
134
|
-
),
|
|
135
|
-
Option(
|
|
136
|
-
"to_api_key",
|
|
137
|
-
["--to-api-key", "--tak"],
|
|
138
|
-
"API key for the destination instance. If not specified, the same instance's API key will be used",
|
|
139
|
-
True
|
|
140
|
-
),
|
|
141
|
-
Option(
|
|
142
|
-
"to_project_name",
|
|
143
|
-
["--to-project-name", "--tpn"],
|
|
144
|
-
"Name of the destination project to migrate to",
|
|
145
|
-
True
|
|
146
|
-
),
|
|
147
|
-
Option(
|
|
148
|
-
"to_instance",
|
|
149
|
-
["--to-instance", "--ti"],
|
|
150
|
-
"URL from the destination instance to migrate to. If not specified, the same instance's URL will be used",
|
|
151
|
-
True
|
|
152
|
-
),
|
|
153
|
-
Option(
|
|
154
|
-
"admin_email",
|
|
155
|
-
["--admin-email", "--ae"],
|
|
156
|
-
"Email from destination project's administrator",
|
|
157
|
-
True
|
|
158
|
-
),
|
|
159
|
-
]
|
|
160
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
|
|
161
301
|
|
|
162
|
-
def clone_agent(option_list: list):
|
|
163
|
-
from_api_key = None
|
|
164
|
-
from_project_id = None
|
|
165
|
-
from_instance = None
|
|
166
|
-
to_api_key = None
|
|
167
|
-
to_project_id = None
|
|
168
|
-
to_instance = None
|
|
169
|
-
agent_id = None
|
|
170
302
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if not (from_project_id and from_instance and agent_id):
|
|
188
|
-
raise MissingRequirementException("Cannot migrate resources without indicating source: project, instance and agent id")
|
|
189
|
-
|
|
190
|
-
migration_strategy = AgentMigrationStrategy(
|
|
191
|
-
from_api_key=from_api_key,
|
|
192
|
-
from_project_id=from_project_id,
|
|
193
|
-
from_instance=from_instance,
|
|
194
|
-
to_api_key=to_api_key,
|
|
195
|
-
to_project_id=to_project_id,
|
|
196
|
-
to_instance=to_instance,
|
|
197
|
-
agent_id=agent_id
|
|
198
|
-
)
|
|
199
|
-
tool = MigrationTool(migration_strategy)
|
|
200
|
-
response = tool.run_migration()
|
|
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
|
|
201
319
|
|
|
202
320
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
Option(
|
|
223
|
-
"to_api_key",
|
|
224
|
-
["--to-api-key", "--tak"],
|
|
225
|
-
"API key for the destination instance. If not specified, the same instance's API key will be used",
|
|
226
|
-
True
|
|
227
|
-
),
|
|
228
|
-
Option(
|
|
229
|
-
"to_project_id",
|
|
230
|
-
["--to-project-id", "--tpid"],
|
|
231
|
-
"ID of the destination project to migrate to",
|
|
232
|
-
True
|
|
233
|
-
),
|
|
234
|
-
Option(
|
|
235
|
-
"to_instance",
|
|
236
|
-
["--to-instance", "--ti"],
|
|
237
|
-
"URL from the destination instance to migrate to. If not specified, the same instance's URL will be used",
|
|
238
|
-
True
|
|
239
|
-
),
|
|
240
|
-
Option(
|
|
241
|
-
"agent_id",
|
|
242
|
-
["--agent-id", "--aid"],
|
|
243
|
-
"Unique identifier from the agent to be migrated",
|
|
244
|
-
True
|
|
245
|
-
),
|
|
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
|
|
246
340
|
|
|
247
|
-
|
|
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
|
|
248
395
|
|
|
249
396
|
|
|
250
|
-
def
|
|
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
|
+
|
|
251
619
|
from_api_key = None
|
|
252
|
-
|
|
620
|
+
from_organization_api_key = None
|
|
253
621
|
from_instance = None
|
|
622
|
+
from_project_id = None
|
|
623
|
+
from_organization_id = None
|
|
254
624
|
to_api_key = None
|
|
255
|
-
|
|
625
|
+
to_organization_api_key = None
|
|
256
626
|
to_instance = None
|
|
257
|
-
|
|
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
|
|
258
651
|
|
|
259
652
|
for option_flag, option_arg in option_list:
|
|
260
653
|
if option_flag.name == "from_api_key":
|
|
261
654
|
from_api_key = option_arg
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
655
|
+
elif option_flag.name == "from_organization_api_key":
|
|
656
|
+
from_organization_api_key = option_arg
|
|
657
|
+
elif option_flag.name == "from_instance":
|
|
265
658
|
from_instance = option_arg
|
|
266
|
-
|
|
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":
|
|
267
664
|
to_api_key = option_arg
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
665
|
+
elif option_flag.name == "to_organization_api_key":
|
|
666
|
+
to_organization_api_key = option_arg
|
|
667
|
+
elif option_flag.name == "to_instance":
|
|
271
668
|
to_instance = option_arg
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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
|
+
))
|
|
289
1019
|
|
|
1020
|
+
if not strategies:
|
|
1021
|
+
Console.write_stdout("No migration strategies configured. Use flags like --agents, --tools, --all, etc.")
|
|
1022
|
+
return
|
|
290
1023
|
|
|
291
|
-
|
|
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
|
+
),
|
|
292
1044
|
Option(
|
|
293
1045
|
"from_api_key",
|
|
294
|
-
["--from-api-key", "--
|
|
295
|
-
"
|
|
1046
|
+
["--from-api-key", "--from-key"],
|
|
1047
|
+
"Source instance project scope API key (required)",
|
|
296
1048
|
True
|
|
297
1049
|
),
|
|
298
1050
|
Option(
|
|
299
|
-
"
|
|
300
|
-
["--from-
|
|
301
|
-
"
|
|
1051
|
+
"from_organization_api_key",
|
|
1052
|
+
["--from-org-key", "--from-organization-key"],
|
|
1053
|
+
"Source instance organization scope API key (optional, for project creation)",
|
|
302
1054
|
True
|
|
303
1055
|
),
|
|
304
1056
|
Option(
|
|
305
1057
|
"from_instance",
|
|
306
|
-
["--from-instance", "--
|
|
307
|
-
"
|
|
1058
|
+
["--from-instance", "--from-url"],
|
|
1059
|
+
"Source instance URL (required)",
|
|
308
1060
|
True
|
|
309
1061
|
),
|
|
310
1062
|
Option(
|
|
311
|
-
"
|
|
312
|
-
["--
|
|
313
|
-
"
|
|
1063
|
+
"from_project_id",
|
|
1064
|
+
["--from-project-id", "--from-pid"],
|
|
1065
|
+
"Source project ID (required)",
|
|
314
1066
|
True
|
|
315
1067
|
),
|
|
316
1068
|
Option(
|
|
317
|
-
"
|
|
318
|
-
["--
|
|
319
|
-
"ID
|
|
1069
|
+
"from_organization_id",
|
|
1070
|
+
["--from-organization-id", "--from-oid"],
|
|
1071
|
+
"Source organization ID (required for usage limits and files)",
|
|
320
1072
|
True
|
|
321
1073
|
),
|
|
322
1074
|
Option(
|
|
323
|
-
"
|
|
324
|
-
["--to-
|
|
325
|
-
"
|
|
1075
|
+
"to_api_key",
|
|
1076
|
+
["--to-api-key", "--to-key"],
|
|
1077
|
+
"Destination instance project scope API key (optional, defaults to source key)",
|
|
326
1078
|
True
|
|
327
1079
|
),
|
|
328
1080
|
Option(
|
|
329
|
-
"
|
|
330
|
-
["--
|
|
331
|
-
"
|
|
1081
|
+
"to_organization_api_key",
|
|
1082
|
+
["--to-org-key", "--to-organization-key"],
|
|
1083
|
+
"Destination instance organization scope API key (optional, for project creation)",
|
|
332
1084
|
True
|
|
333
1085
|
),
|
|
334
|
-
]
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
def clone_process(option_list: list):
|
|
338
|
-
from_api_key = None
|
|
339
|
-
from_project_id = None
|
|
340
|
-
from_instance = None
|
|
341
|
-
to_api_key = None
|
|
342
|
-
to_project_id = None
|
|
343
|
-
to_instance = None
|
|
344
|
-
process_id = None
|
|
345
|
-
|
|
346
|
-
for option_flag, option_arg in option_list:
|
|
347
|
-
if option_flag.name == "from_api_key":
|
|
348
|
-
from_api_key = option_arg
|
|
349
|
-
if option_flag.name == "from_project_id":
|
|
350
|
-
from_project_id = option_arg
|
|
351
|
-
if option_flag.name == "from_instance":
|
|
352
|
-
from_instance = option_arg
|
|
353
|
-
if option_flag.name == "to_api_key":
|
|
354
|
-
to_api_key = option_arg
|
|
355
|
-
if option_flag.name == "to_project_id":
|
|
356
|
-
to_project_id = option_arg
|
|
357
|
-
if option_flag.name == "to_instance":
|
|
358
|
-
to_instance = option_arg
|
|
359
|
-
if option_flag.name == "process_id":
|
|
360
|
-
process_id = option_arg
|
|
361
|
-
|
|
362
|
-
if not (from_project_id and from_instance and process_id):
|
|
363
|
-
raise MissingRequirementException("Cannot migrate resources without indicating source: project, instance, and process ID")
|
|
364
|
-
|
|
365
|
-
migration_strategy = AgenticProcessMigrationStrategy(
|
|
366
|
-
from_api_key=from_api_key,
|
|
367
|
-
from_project_id=from_project_id,
|
|
368
|
-
from_instance=from_instance,
|
|
369
|
-
to_api_key=to_api_key,
|
|
370
|
-
to_project_id=to_project_id,
|
|
371
|
-
to_instance=to_instance,
|
|
372
|
-
process_id=process_id
|
|
373
|
-
)
|
|
374
|
-
tool = MigrationTool(migration_strategy)
|
|
375
|
-
tool.run_migration()
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
clone_process_options = [
|
|
379
1086
|
Option(
|
|
380
|
-
"
|
|
381
|
-
["--
|
|
382
|
-
"
|
|
1087
|
+
"to_instance",
|
|
1088
|
+
["--to-instance", "--to-url"],
|
|
1089
|
+
"Destination instance URL (optional, defaults to source URL)",
|
|
383
1090
|
True
|
|
384
1091
|
),
|
|
385
1092
|
Option(
|
|
386
|
-
"
|
|
387
|
-
["--
|
|
388
|
-
"
|
|
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)",
|
|
389
1096
|
True
|
|
390
1097
|
),
|
|
391
1098
|
Option(
|
|
392
|
-
"
|
|
393
|
-
["--
|
|
394
|
-
"
|
|
1099
|
+
"admin_email",
|
|
1100
|
+
["--admin-email"],
|
|
1101
|
+
"Admin email for new project (required when creating new project)",
|
|
395
1102
|
True
|
|
396
1103
|
),
|
|
397
1104
|
Option(
|
|
398
|
-
"
|
|
399
|
-
["--to-
|
|
400
|
-
"
|
|
1105
|
+
"to_project_id",
|
|
1106
|
+
["--to-project-id", "--to-pid"],
|
|
1107
|
+
"Destination project ID (optional for files)",
|
|
401
1108
|
True
|
|
402
1109
|
),
|
|
403
1110
|
Option(
|
|
404
|
-
"
|
|
405
|
-
["--to-
|
|
406
|
-
"ID
|
|
1111
|
+
"to_organization_id",
|
|
1112
|
+
["--to-organization-id", "--to-oid"],
|
|
1113
|
+
"Destination organization ID (optional for usage limits and files)",
|
|
407
1114
|
True
|
|
408
1115
|
),
|
|
409
1116
|
Option(
|
|
410
|
-
"
|
|
411
|
-
["--
|
|
412
|
-
"
|
|
413
|
-
|
|
1117
|
+
"all",
|
|
1118
|
+
["--all"],
|
|
1119
|
+
"Migrate all available components",
|
|
1120
|
+
False
|
|
414
1121
|
),
|
|
415
1122
|
Option(
|
|
416
|
-
"
|
|
417
|
-
["--
|
|
418
|
-
"
|
|
1123
|
+
"agents",
|
|
1124
|
+
["--agents"],
|
|
1125
|
+
"Agent IDs to migrate: comma-separated IDs or 'all'",
|
|
419
1126
|
True
|
|
420
1127
|
),
|
|
421
|
-
]
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
def clone_task(option_list: list):
|
|
425
|
-
from_api_key = None
|
|
426
|
-
from_project_id = None
|
|
427
|
-
from_instance = None
|
|
428
|
-
to_api_key = None
|
|
429
|
-
to_project_id = None
|
|
430
|
-
to_instance = None
|
|
431
|
-
task_id = None
|
|
432
|
-
|
|
433
|
-
for option_flag, option_arg in option_list:
|
|
434
|
-
if option_flag.name == "from_api_key":
|
|
435
|
-
from_api_key = option_arg
|
|
436
|
-
if option_flag.name == "from_project_id":
|
|
437
|
-
from_project_id = option_arg
|
|
438
|
-
if option_flag.name == "from_instance":
|
|
439
|
-
from_instance = option_arg
|
|
440
|
-
if option_flag.name == "to_api_key":
|
|
441
|
-
to_api_key = option_arg
|
|
442
|
-
if option_flag.name == "to_project_id":
|
|
443
|
-
to_project_id = option_arg
|
|
444
|
-
if option_flag.name == "to_instance":
|
|
445
|
-
to_instance = option_arg
|
|
446
|
-
if option_flag.name == "task_id":
|
|
447
|
-
task_id = option_arg
|
|
448
|
-
|
|
449
|
-
if not (from_project_id and from_instance and task_id):
|
|
450
|
-
raise MissingRequirementException("Cannot migrate resources without indicating source: project, instance, and task ID")
|
|
451
|
-
|
|
452
|
-
migration_strategy = TaskMigrationStrategy(
|
|
453
|
-
from_api_key=from_api_key,
|
|
454
|
-
from_project_id=from_project_id,
|
|
455
|
-
from_instance=from_instance,
|
|
456
|
-
to_api_key=to_api_key,
|
|
457
|
-
to_project_id=to_project_id,
|
|
458
|
-
to_instance=to_instance,
|
|
459
|
-
task_id=task_id
|
|
460
|
-
)
|
|
461
|
-
tool = MigrationTool(migration_strategy)
|
|
462
|
-
response = tool.run_migration()
|
|
463
|
-
|
|
464
|
-
sys.stdout.write(f"Migration result: \n{response}\n")
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
clone_task_options = [
|
|
468
1128
|
Option(
|
|
469
|
-
"
|
|
470
|
-
["--
|
|
471
|
-
"
|
|
1129
|
+
"tools",
|
|
1130
|
+
["--tools"],
|
|
1131
|
+
"Tool IDs to migrate: comma-separated IDs or 'all'",
|
|
472
1132
|
True
|
|
473
1133
|
),
|
|
474
1134
|
Option(
|
|
475
|
-
"
|
|
476
|
-
["--
|
|
477
|
-
"
|
|
1135
|
+
"agentic_processes",
|
|
1136
|
+
["--agentic-processes", "--processes"],
|
|
1137
|
+
"Agentic process IDs to migrate: comma-separated IDs or 'all'",
|
|
478
1138
|
True
|
|
479
1139
|
),
|
|
480
1140
|
Option(
|
|
481
|
-
"
|
|
482
|
-
["--
|
|
483
|
-
"
|
|
1141
|
+
"tasks",
|
|
1142
|
+
["--tasks"],
|
|
1143
|
+
"Task IDs to migrate: comma-separated IDs or 'all'",
|
|
484
1144
|
True
|
|
485
1145
|
),
|
|
486
1146
|
Option(
|
|
487
|
-
"
|
|
488
|
-
["--
|
|
489
|
-
"
|
|
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'",
|
|
490
1156
|
True
|
|
491
1157
|
),
|
|
492
1158
|
Option(
|
|
493
|
-
"
|
|
494
|
-
["--
|
|
495
|
-
"
|
|
1159
|
+
"files",
|
|
1160
|
+
["--files"],
|
|
1161
|
+
"File IDs to migrate: comma-separated IDs or 'all' (requires org/project IDs)",
|
|
496
1162
|
True
|
|
497
1163
|
),
|
|
498
1164
|
Option(
|
|
499
|
-
"
|
|
500
|
-
["--
|
|
501
|
-
"
|
|
1165
|
+
"secrets",
|
|
1166
|
+
["--secrets"],
|
|
1167
|
+
"Secret IDs to migrate: comma-separated IDs or 'all'",
|
|
502
1168
|
True
|
|
503
1169
|
),
|
|
504
1170
|
Option(
|
|
505
|
-
"
|
|
506
|
-
["--
|
|
507
|
-
"
|
|
1171
|
+
"stop_on_error",
|
|
1172
|
+
["--stop-on-error", "--soe"],
|
|
1173
|
+
"Stop migration on first error: 0: False, 1: True (default: 1)",
|
|
508
1174
|
True
|
|
509
1175
|
),
|
|
510
1176
|
]
|
|
511
1177
|
|
|
512
1178
|
|
|
513
|
-
|
|
514
1179
|
migrate_commands = [
|
|
515
1180
|
Command(
|
|
516
1181
|
"help",
|
|
@@ -524,47 +1189,10 @@ migrate_commands = [
|
|
|
524
1189
|
Command(
|
|
525
1190
|
"clone_project",
|
|
526
1191
|
["clone-project"],
|
|
527
|
-
"Clone project
|
|
1192
|
+
"Clone project components between instances",
|
|
528
1193
|
clone_project,
|
|
529
1194
|
ArgumentsEnum.REQUIRED,
|
|
530
1195
|
[],
|
|
531
1196
|
clone_project_options
|
|
532
1197
|
),
|
|
533
|
-
Command(
|
|
534
|
-
"clone_agent",
|
|
535
|
-
["clone-agent"],
|
|
536
|
-
"Clone agentt from instance",
|
|
537
|
-
clone_agent,
|
|
538
|
-
ArgumentsEnum.REQUIRED,
|
|
539
|
-
[],
|
|
540
|
-
clone_agent_options
|
|
541
|
-
),
|
|
542
|
-
Command(
|
|
543
|
-
"clone_tool",
|
|
544
|
-
["clone-tool"],
|
|
545
|
-
"Clone tool from instance",
|
|
546
|
-
clone_tool,
|
|
547
|
-
ArgumentsEnum.REQUIRED,
|
|
548
|
-
[],
|
|
549
|
-
clone_tool_options
|
|
550
|
-
),
|
|
551
|
-
Command(
|
|
552
|
-
"clone_process",
|
|
553
|
-
["clone-process"],
|
|
554
|
-
"Clone process from instance",
|
|
555
|
-
clone_process,
|
|
556
|
-
ArgumentsEnum.REQUIRED,
|
|
557
|
-
[],
|
|
558
|
-
clone_process_options
|
|
559
|
-
),
|
|
560
|
-
# TODO -> Remove clone-task: clone-process includes cloning tasks
|
|
561
|
-
# Command(
|
|
562
|
-
# "clone_task",
|
|
563
|
-
# ["clone-task"],
|
|
564
|
-
# "Clone task from instance",
|
|
565
|
-
# clone_task,
|
|
566
|
-
# ArgumentsEnum.REQUIRED,
|
|
567
|
-
# [],
|
|
568
|
-
# clone_task_options
|
|
569
|
-
#),
|
|
570
1198
|
]
|