pygeai 0.1.6__py3-none-any.whl → 0.6.0b15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pygeai/__init__.py +11 -2
- pygeai/_docs/Makefile +20 -0
- pygeai/_docs/make.bat +35 -0
- pygeai/_docs/source/conf.py +117 -0
- pygeai/_docs/source/content/ai_lab/cli.rst +747 -0
- pygeai/_docs/source/content/ai_lab/models.rst +1734 -0
- pygeai/_docs/source/content/ai_lab/runner.rst +253 -0
- pygeai/_docs/source/content/ai_lab/spec.rst +431 -0
- pygeai/_docs/source/content/ai_lab/usage.rst +1011 -0
- pygeai/_docs/source/content/ai_lab.rst +102 -0
- pygeai/_docs/source/content/analytics.rst +598 -0
- pygeai/_docs/source/content/api_reference/admin.rst +161 -0
- pygeai/_docs/source/content/api_reference/assistant.rst +326 -0
- pygeai/_docs/source/content/api_reference/auth.rst +379 -0
- pygeai/_docs/source/content/api_reference/chat.rst +754 -0
- pygeai/_docs/source/content/api_reference/embeddings.rst +154 -0
- pygeai/_docs/source/content/api_reference/evaluation.rst +590 -0
- pygeai/_docs/source/content/api_reference/feedback.rst +237 -0
- pygeai/_docs/source/content/api_reference/files.rst +592 -0
- pygeai/_docs/source/content/api_reference/gam.rst +401 -0
- pygeai/_docs/source/content/api_reference/health.rst +58 -0
- pygeai/_docs/source/content/api_reference/project.rst +738 -0
- pygeai/_docs/source/content/api_reference/proxy.rst +318 -0
- pygeai/_docs/source/content/api_reference/rag.rst +710 -0
- pygeai/_docs/source/content/api_reference/rerank.rst +94 -0
- pygeai/_docs/source/content/api_reference/secrets.rst +495 -0
- pygeai/_docs/source/content/api_reference/usage_limits.rst +390 -0
- pygeai/_docs/source/content/api_reference.rst +58 -0
- pygeai/_docs/source/content/authentication.rst +295 -0
- pygeai/_docs/source/content/chat_gui.rst +121 -0
- pygeai/_docs/source/content/cli.rst +203 -0
- pygeai/_docs/source/content/debugger.rst +651 -0
- pygeai/_docs/source/content/intro.rst +67 -0
- pygeai/_docs/source/content/migration.rst +929 -0
- pygeai/_docs/source/content/modules.rst +7 -0
- pygeai/_docs/source/content/quickstart.rst +143 -0
- pygeai/_docs/source/content/samples.rst +394 -0
- pygeai/_docs/source/index.rst +75 -0
- pygeai/_docs/source/modules.rst +7 -0
- pygeai/_docs/source/pygeai.admin.rst +29 -0
- pygeai/_docs/source/pygeai.analytics.rst +53 -0
- pygeai/_docs/source/pygeai.assistant.data.rst +21 -0
- pygeai/_docs/source/pygeai.assistant.data_analyst.rst +29 -0
- pygeai/_docs/source/pygeai.assistant.rag.rst +53 -0
- pygeai/_docs/source/pygeai.assistant.rst +55 -0
- pygeai/_docs/source/pygeai.auth.rst +29 -0
- pygeai/_docs/source/pygeai.chat.rst +69 -0
- pygeai/_docs/source/pygeai.cli.commands.flows.rst +10 -0
- pygeai/_docs/source/pygeai.cli.commands.lab.rst +53 -0
- pygeai/_docs/source/pygeai.cli.commands.rst +222 -0
- pygeai/_docs/source/pygeai.cli.rst +62 -0
- pygeai/_docs/source/pygeai.cli.texts.rst +21 -0
- pygeai/_docs/source/pygeai.core.base.rst +53 -0
- pygeai/_docs/source/pygeai.core.common.rst +37 -0
- pygeai/_docs/source/pygeai.core.embeddings.rst +61 -0
- pygeai/_docs/source/pygeai.core.feedback.rst +37 -0
- pygeai/_docs/source/pygeai.core.files.rst +61 -0
- pygeai/_docs/source/pygeai.core.llm.rst +29 -0
- pygeai/_docs/source/pygeai.core.plugins.rst +37 -0
- pygeai/_docs/source/pygeai.core.rerank.rst +53 -0
- pygeai/_docs/source/pygeai.core.rst +63 -0
- pygeai/_docs/source/pygeai.core.secrets.rst +29 -0
- pygeai/_docs/source/pygeai.core.services.llm.rst +29 -0
- pygeai/_docs/source/pygeai.core.services.rst +37 -0
- pygeai/_docs/source/pygeai.core.utils.rst +37 -0
- pygeai/_docs/source/pygeai.dbg.rst +21 -0
- pygeai/_docs/source/pygeai.evaluation.dataset.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.plan.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.result.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.rst +31 -0
- pygeai/_docs/source/pygeai.flows.rst +29 -0
- pygeai/_docs/source/pygeai.gam.rst +29 -0
- pygeai/_docs/source/pygeai.health.rst +29 -0
- pygeai/_docs/source/pygeai.lab.agents.rst +37 -0
- pygeai/_docs/source/pygeai.lab.processes.rst +37 -0
- pygeai/_docs/source/pygeai.lab.rst +65 -0
- pygeai/_docs/source/pygeai.lab.spec.rst +29 -0
- pygeai/_docs/source/pygeai.lab.strategies.rst +37 -0
- pygeai/_docs/source/pygeai.lab.tools.rst +37 -0
- pygeai/_docs/source/pygeai.man.man1.rst +10 -0
- pygeai/_docs/source/pygeai.man.rst +18 -0
- pygeai/_docs/source/pygeai.migration.rst +29 -0
- pygeai/_docs/source/pygeai.organization.limits.rst +45 -0
- pygeai/_docs/source/pygeai.organization.rst +61 -0
- pygeai/_docs/source/pygeai.proxy.rst +53 -0
- pygeai/_docs/source/pygeai.rst +35 -0
- pygeai/_docs/source/pygeai.tests.admin.rst +21 -0
- pygeai/_docs/source/pygeai.tests.analytics.rst +45 -0
- pygeai/_docs/source/pygeai.tests.assistants.rag.rst +37 -0
- pygeai/_docs/source/pygeai.tests.assistants.rst +45 -0
- pygeai/_docs/source/pygeai.tests.auth.rst +29 -0
- pygeai/_docs/source/pygeai.tests.chat.rst +45 -0
- pygeai/_docs/source/pygeai.tests.cli.commands.lab.rst +37 -0
- pygeai/_docs/source/pygeai.tests.cli.commands.rst +165 -0
- pygeai/_docs/source/pygeai.tests.cli.docker.rst +10 -0
- pygeai/_docs/source/pygeai.tests.cli.rst +46 -0
- pygeai/_docs/source/pygeai.tests.core.base.data.rst +29 -0
- pygeai/_docs/source/pygeai.tests.core.base.rst +45 -0
- pygeai/_docs/source/pygeai.tests.core.common.data.rst +10 -0
- pygeai/_docs/source/pygeai.tests.core.common.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.embeddings.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.feedback.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.files.rst +53 -0
- pygeai/_docs/source/pygeai.tests.core.llm.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.plugins.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.rerank.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.rst +39 -0
- pygeai/_docs/source/pygeai.tests.core.secrets.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.services.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.utils.rst +21 -0
- pygeai/_docs/source/pygeai.tests.dbg.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.dataset.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.plan.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.result.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.rst +20 -0
- pygeai/_docs/source/pygeai.tests.gam.rst +21 -0
- pygeai/_docs/source/pygeai.tests.health.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.assistants.rag.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.assistants.rst +18 -0
- pygeai/_docs/source/pygeai.tests.integration.chat.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.agents.rst +69 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.processes.rst +77 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.reasoning_strategies.rst +37 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.tools.rst +77 -0
- pygeai/_docs/source/pygeai.tests.integration.rst +20 -0
- pygeai/_docs/source/pygeai.tests.lab.agents.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.processes.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.rst +49 -0
- pygeai/_docs/source/pygeai.tests.lab.spec.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.strategies.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.tools.rst +29 -0
- pygeai/_docs/source/pygeai.tests.migration.rst +29 -0
- pygeai/_docs/source/pygeai.tests.organization.limits.rst +29 -0
- pygeai/_docs/source/pygeai.tests.organization.rst +53 -0
- pygeai/_docs/source/pygeai.tests.proxy.rst +61 -0
- pygeai/_docs/source/pygeai.tests.rst +33 -0
- pygeai/admin/clients.py +14 -11
- pygeai/admin/endpoints.py +2 -2
- pygeai/analytics/clients.py +505 -0
- pygeai/analytics/endpoints.py +35 -0
- pygeai/analytics/managers.py +606 -0
- pygeai/analytics/mappers.py +207 -0
- pygeai/analytics/responses.py +240 -0
- pygeai/assistant/clients.py +48 -57
- pygeai/assistant/data/__init__.py +0 -0
- pygeai/assistant/data/clients.py +15 -0
- pygeai/assistant/data_analyst/__init__.py +0 -0
- pygeai/assistant/data_analyst/clients.py +75 -0
- pygeai/assistant/data_analyst/endpoints.py +2 -0
- pygeai/assistant/endpoints.py +0 -2
- pygeai/assistant/managers.py +738 -0
- pygeai/assistant/mappers.py +153 -0
- pygeai/assistant/rag/clients.py +132 -21
- pygeai/assistant/rag/mappers.py +228 -0
- pygeai/assistant/rag/models.py +396 -0
- pygeai/assistant/rag/responses.py +10 -0
- pygeai/auth/__init__.py +0 -0
- pygeai/auth/clients.py +129 -0
- pygeai/auth/endpoints.py +6 -0
- pygeai/chat/clients.py +406 -31
- pygeai/chat/endpoints.py +3 -0
- pygeai/chat/iris.py +17 -0
- pygeai/chat/managers.py +64 -0
- pygeai/chat/session.py +38 -0
- pygeai/chat/settings.py +6 -0
- pygeai/chat/ui.py +678 -0
- pygeai/cli/__init__.py +0 -1
- pygeai/cli/commands/admin.py +9 -12
- pygeai/cli/commands/analytics.py +533 -0
- pygeai/cli/commands/assistant.py +11 -11
- pygeai/cli/commands/auth.py +299 -0
- pygeai/cli/commands/base.py +201 -7
- pygeai/cli/commands/chat.py +875 -14
- pygeai/cli/commands/common.py +30 -26
- pygeai/cli/commands/configuration.py +84 -9
- pygeai/cli/commands/docs.py +105 -0
- pygeai/cli/commands/embeddings.py +187 -0
- pygeai/cli/commands/evaluation.py +2069 -0
- pygeai/cli/commands/feedback.py +93 -0
- pygeai/cli/commands/files.py +312 -0
- pygeai/cli/commands/flows/__init__.py +0 -0
- pygeai/cli/commands/gam.py +349 -0
- pygeai/cli/commands/lab/__init__.py +0 -0
- pygeai/cli/commands/lab/ai_lab.py +4110 -0
- pygeai/cli/commands/lab/common.py +135 -0
- pygeai/cli/commands/lab/options.py +8 -0
- pygeai/cli/commands/lab/spec.py +273 -0
- pygeai/cli/commands/lab/utils.py +13 -0
- pygeai/cli/commands/llm.py +164 -0
- pygeai/cli/commands/migrate.py +1198 -0
- pygeai/cli/commands/options.py +86 -0
- pygeai/cli/commands/organization.py +560 -98
- pygeai/cli/commands/rag.py +306 -10
- pygeai/cli/commands/rerank.py +108 -0
- pygeai/cli/commands/secrets.py +357 -0
- pygeai/cli/commands/usage_limits.py +583 -0
- pygeai/cli/commands/validators.py +209 -0
- pygeai/cli/commands/version.py +44 -0
- pygeai/cli/error_handler.py +151 -0
- pygeai/cli/geai.py +171 -30
- pygeai/cli/geai_proxy.py +318 -0
- pygeai/cli/install_man.py +107 -0
- pygeai/cli/parsers.py +78 -25
- pygeai/cli/texts/help.py +712 -55
- pygeai/core/__init__.py +9 -1
- pygeai/core/base/clients.py +61 -10
- pygeai/core/base/mappers.py +208 -30
- pygeai/core/base/models.py +8 -308
- pygeai/core/base/responses.py +18 -1
- pygeai/core/base/session.py +110 -17
- pygeai/core/common/config.py +98 -16
- pygeai/core/common/decorators.py +44 -0
- pygeai/core/common/exceptions.py +104 -4
- pygeai/core/embeddings/__init__.py +19 -0
- pygeai/core/embeddings/clients.py +93 -0
- pygeai/core/embeddings/endpoints.py +1 -0
- pygeai/core/embeddings/managers.py +62 -0
- pygeai/core/embeddings/mappers.py +52 -0
- pygeai/core/embeddings/models.py +14 -0
- pygeai/core/embeddings/responses.py +31 -0
- pygeai/core/feedback/__init__.py +0 -0
- pygeai/core/feedback/clients.py +50 -0
- pygeai/core/feedback/endpoints.py +1 -0
- pygeai/core/feedback/models.py +10 -0
- pygeai/core/files/__init__.py +0 -0
- pygeai/core/files/clients.py +156 -0
- pygeai/core/files/endpoints.py +5 -0
- pygeai/core/files/managers.py +224 -0
- pygeai/core/files/mappers.py +44 -0
- pygeai/core/files/models.py +24 -0
- pygeai/core/files/responses.py +19 -0
- pygeai/core/handlers.py +32 -0
- pygeai/core/llm/__init__.py +0 -0
- pygeai/core/llm/clients.py +53 -0
- pygeai/core/llm/endpoints.py +4 -0
- pygeai/core/models.py +799 -0
- pygeai/core/plugins/__init__.py +0 -0
- pygeai/core/plugins/clients.py +32 -0
- pygeai/core/plugins/endpoints.py +1 -0
- pygeai/core/plugins/models.py +86 -0
- pygeai/core/rerank/__init__.py +0 -0
- pygeai/core/rerank/clients.py +35 -0
- pygeai/core/rerank/endpoints.py +1 -0
- pygeai/core/rerank/managers.py +47 -0
- pygeai/core/rerank/mappers.py +23 -0
- pygeai/core/rerank/models.py +27 -0
- pygeai/core/responses.py +104 -0
- pygeai/core/secrets/__init__.py +0 -0
- pygeai/core/secrets/clients.py +212 -0
- pygeai/core/secrets/endpoints.py +7 -0
- pygeai/core/services/llm/__init__.py +0 -0
- pygeai/core/services/llm/model.py +186 -0
- pygeai/core/services/llm/providers.py +15 -0
- pygeai/core/services/response.py +18 -0
- pygeai/core/services/rest.py +311 -89
- pygeai/core/utils/__init__.py +0 -0
- pygeai/core/utils/console.py +83 -0
- pygeai/core/utils/parsers.py +32 -0
- pygeai/core/utils/validators.py +10 -0
- pygeai/dbg/__init__.py +3 -0
- pygeai/dbg/debugger.py +870 -0
- pygeai/evaluation/__init__.py +0 -0
- pygeai/evaluation/clients.py +19 -0
- pygeai/evaluation/dataset/__init__.py +0 -0
- pygeai/evaluation/dataset/clients.py +514 -0
- pygeai/evaluation/dataset/endpoints.py +26 -0
- pygeai/evaluation/plan/__init__.py +0 -0
- pygeai/evaluation/plan/clients.py +302 -0
- pygeai/evaluation/plan/endpoints.py +16 -0
- pygeai/evaluation/result/__init__.py +0 -0
- pygeai/evaluation/result/clients.py +70 -0
- pygeai/evaluation/result/endpoints.py +2 -0
- pygeai/flows/__init__.py +0 -0
- pygeai/flows/endpoints.py +362 -0
- pygeai/flows/models.py +1304 -0
- pygeai/gam/__init__.py +0 -0
- pygeai/gam/clients.py +178 -0
- pygeai/gam/endpoints.py +4 -0
- pygeai/health/__init__.py +0 -0
- pygeai/health/clients.py +24 -0
- pygeai/health/endpoints.py +1 -0
- pygeai/lab/__init__.py +0 -0
- pygeai/lab/agents/__init__.py +0 -0
- pygeai/lab/agents/clients.py +426 -0
- pygeai/lab/agents/endpoints.py +12 -0
- pygeai/lab/agents/mappers.py +319 -0
- pygeai/lab/clients.py +24 -0
- pygeai/lab/constants.py +3 -0
- pygeai/lab/managers.py +1558 -0
- pygeai/lab/models.py +1719 -0
- pygeai/lab/processes/__init__.py +0 -0
- pygeai/lab/processes/clients.py +1051 -0
- pygeai/lab/processes/endpoints.py +26 -0
- pygeai/lab/processes/mappers.py +395 -0
- pygeai/lab/runners.py +90 -0
- pygeai/lab/spec/__init__.py +0 -0
- pygeai/lab/spec/loader.py +24 -0
- pygeai/lab/spec/parsers.py +39 -0
- pygeai/lab/strategies/__init__.py +0 -0
- pygeai/lab/strategies/clients.py +212 -0
- pygeai/lab/strategies/endpoints.py +5 -0
- pygeai/lab/strategies/mappers.py +58 -0
- pygeai/lab/tools/__init__.py +0 -0
- pygeai/lab/tools/clients.py +465 -0
- pygeai/lab/tools/endpoints.py +13 -0
- pygeai/lab/tools/mappers.py +131 -0
- pygeai/man/__init__.py +1 -0
- pygeai/man/man1/__init__.py +1 -0
- pygeai/man/man1/geai-proxy.1 +246 -0
- pygeai/man/man1/geai.1 +2615 -0
- pygeai/migration/__init__.py +33 -0
- pygeai/migration/strategies.py +603 -0
- pygeai/migration/tools.py +180 -0
- pygeai/organization/clients.py +246 -18
- pygeai/organization/endpoints.py +17 -8
- pygeai/organization/limits/__init__.py +0 -0
- pygeai/organization/limits/clients.py +281 -0
- pygeai/organization/limits/endpoints.py +15 -0
- pygeai/organization/limits/managers.py +331 -0
- pygeai/organization/limits/mappers.py +21 -0
- pygeai/organization/managers.py +537 -0
- pygeai/organization/mappers.py +111 -46
- pygeai/organization/responses.py +61 -11
- pygeai/proxy/__init__.py +0 -0
- pygeai/proxy/clients.py +216 -0
- pygeai/proxy/config.py +128 -0
- pygeai/proxy/managers.py +232 -0
- pygeai/proxy/servers.py +304 -0
- pygeai/proxy/tool.py +69 -0
- pygeai/tests/admin/__init__.py +0 -0
- pygeai/tests/admin/test_clients.py +148 -0
- pygeai/tests/analytics/__init__.py +0 -0
- pygeai/tests/analytics/test_clients.py +86 -0
- pygeai/tests/analytics/test_managers.py +94 -0
- pygeai/tests/analytics/test_mappers.py +84 -0
- pygeai/tests/analytics/test_responses.py +73 -0
- pygeai/tests/assistants/rag/__init__.py +0 -0
- pygeai/tests/assistants/rag/test_clients.py +346 -0
- pygeai/tests/assistants/rag/test_mappers.py +189 -0
- pygeai/tests/assistants/rag/test_models.py +292 -0
- pygeai/tests/assistants/test_clients.py +176 -80
- pygeai/tests/assistants/test_managers.py +198 -0
- pygeai/tests/assistants/test_mappers.py +111 -0
- pygeai/tests/auth/__init__.py +0 -0
- pygeai/tests/auth/test_clients.py +289 -0
- pygeai/tests/auth/test_oauth.py +172 -0
- pygeai/tests/auth/test_session_logging.py +150 -0
- pygeai/tests/chat/__init__.py +0 -0
- pygeai/tests/chat/test_clients.py +393 -0
- pygeai/tests/chat/test_iris.py +38 -0
- pygeai/tests/chat/test_session.py +62 -0
- pygeai/tests/chat/test_ui.py +224 -0
- pygeai/tests/cli/__init__.py +0 -0
- pygeai/tests/cli/commands/__init__.py +0 -0
- pygeai/tests/cli/commands/lab/__init__.py +0 -0
- pygeai/tests/cli/commands/lab/test_ai_lab.py +786 -0
- pygeai/tests/cli/commands/lab/test_common.py +208 -0
- pygeai/tests/cli/commands/lab/test_spec.py +246 -0
- pygeai/tests/cli/commands/test_assistant.py +202 -0
- pygeai/tests/cli/commands/test_chat.py +130 -0
- pygeai/tests/cli/commands/test_common.py +350 -0
- pygeai/tests/cli/commands/test_embeddings.py +132 -0
- pygeai/tests/cli/commands/test_evaluation.py +656 -0
- pygeai/tests/cli/commands/test_feedback.py +65 -0
- pygeai/tests/cli/commands/test_files.py +161 -0
- pygeai/tests/cli/commands/test_gam.py +201 -0
- pygeai/tests/cli/commands/test_llm.py +114 -0
- pygeai/tests/cli/commands/test_migrate.py +176 -0
- pygeai/tests/cli/commands/test_organization.py +276 -0
- pygeai/tests/cli/commands/test_rag.py +266 -0
- pygeai/tests/cli/commands/test_rerank.py +110 -0
- pygeai/tests/cli/commands/test_secrets.py +171 -0
- pygeai/tests/cli/commands/test_show_help.py +41 -0
- pygeai/tests/cli/commands/test_usage_limits.py +412 -0
- pygeai/tests/cli/commands/test_validators.py +160 -0
- pygeai/tests/cli/commands/test_version.py +81 -0
- pygeai/tests/cli/docker/__init__.py +0 -0
- pygeai/tests/cli/test_credentials_flag.py +316 -0
- pygeai/tests/cli/test_error_handler.py +225 -0
- pygeai/tests/cli/test_geai_driver.py +154 -0
- pygeai/tests/cli/test_parsers.py +154 -0
- pygeai/tests/core/base/__init__.py +0 -0
- pygeai/tests/core/base/data/__init__.py +0 -0
- pygeai/tests/core/base/data/mappers.py +117 -0
- pygeai/tests/core/base/data/models.py +312 -0
- pygeai/tests/core/base/test_mappers.py +569 -0
- pygeai/tests/core/base/test_models.py +261 -0
- pygeai/tests/core/base/test_responses.py +53 -0
- pygeai/tests/core/common/__init__.py +0 -0
- pygeai/tests/core/common/data/__init__.py +0 -0
- pygeai/tests/core/common/test_config.py +186 -0
- pygeai/tests/core/common/test_decorators.py +69 -0
- pygeai/tests/core/embeddings/__init__.py +0 -0
- pygeai/tests/core/embeddings/test_clients.py +225 -0
- pygeai/tests/core/embeddings/test_managers.py +171 -0
- pygeai/tests/core/embeddings/test_mappers.py +142 -0
- pygeai/tests/core/feedback/__init__.py +0 -0
- pygeai/tests/core/feedback/test_clients.py +64 -0
- pygeai/tests/core/files/__init__.py +0 -0
- pygeai/tests/core/files/test_clients.py +128 -0
- pygeai/tests/core/files/test_managers.py +219 -0
- pygeai/tests/core/files/test_mappers.py +137 -0
- pygeai/tests/core/files/test_models.py +103 -0
- pygeai/tests/core/files/test_responses.py +122 -0
- pygeai/tests/core/llm/__init__.py +0 -0
- pygeai/tests/core/llm/test_clients.py +142 -0
- pygeai/tests/core/plugins/__init__.py +0 -0
- pygeai/tests/core/plugins/test_clients.py +66 -0
- pygeai/tests/core/rerank/__init__.py +0 -0
- pygeai/tests/core/rerank/test_clients.py +76 -0
- pygeai/tests/core/rerank/test_managers.py +99 -0
- pygeai/tests/core/rerank/test_mappers.py +54 -0
- pygeai/tests/core/secrets/__init__.py +0 -0
- pygeai/tests/core/secrets/test_clients.py +264 -0
- pygeai/tests/core/services/__init__.py +0 -0
- pygeai/tests/core/services/test_rest.py +273 -0
- pygeai/tests/core/test_handlers.py +66 -0
- pygeai/tests/core/utils/__init__.py +0 -0
- pygeai/tests/core/utils/test_console.py +80 -0
- pygeai/tests/dbg/__init__.py +0 -0
- pygeai/tests/dbg/test_debugger.py +591 -0
- pygeai/tests/evaluation/__init__.py +0 -0
- pygeai/tests/evaluation/dataset/__init__.py +0 -0
- pygeai/tests/evaluation/dataset/test_clients.py +265 -0
- pygeai/tests/evaluation/plan/__init__.py +0 -0
- pygeai/tests/evaluation/plan/test_clients.py +195 -0
- pygeai/tests/evaluation/result/__init__.py +0 -0
- pygeai/tests/evaluation/result/test_clients.py +66 -0
- pygeai/tests/gam/__init__.py +0 -0
- pygeai/tests/gam/test_clients.py +195 -0
- pygeai/tests/health/__init__.py +0 -0
- pygeai/tests/health/test_clients.py +41 -0
- pygeai/tests/integration/__init__.py +0 -0
- pygeai/tests/integration/assistants/__init__.py +0 -0
- pygeai/tests/integration/assistants/rag/__init__.py +0 -0
- pygeai/tests/integration/assistants/rag/test_create_rag.py +91 -0
- pygeai/tests/integration/chat/__init__.py +0 -0
- pygeai/tests/integration/chat/test_generate_image.py +158 -0
- pygeai/tests/integration/lab/__init__.py +0 -0
- pygeai/tests/integration/lab/agents/__init__.py +0 -0
- pygeai/tests/integration/lab/agents/test_agents_list.py +106 -0
- pygeai/tests/integration/lab/agents/test_create_agent.py +319 -0
- pygeai/tests/integration/lab/agents/test_create_sharing_link.py +70 -0
- pygeai/tests/integration/lab/agents/test_delete_agent.py +75 -0
- pygeai/tests/integration/lab/agents/test_get_agent.py +94 -0
- pygeai/tests/integration/lab/agents/test_publish_agent_revision.py +127 -0
- pygeai/tests/integration/lab/agents/test_update_agent.py +250 -0
- pygeai/tests/integration/lab/processes/__init__.py +0 -0
- pygeai/tests/integration/lab/processes/test_create_process.py +345 -0
- pygeai/tests/integration/lab/processes/test_create_task.py +211 -0
- pygeai/tests/integration/lab/processes/test_delete_process.py +111 -0
- pygeai/tests/integration/lab/processes/test_get_process.py +201 -0
- pygeai/tests/integration/lab/processes/test_list_process_instances.py +91 -0
- pygeai/tests/integration/lab/processes/test_list_processes.py +138 -0
- pygeai/tests/integration/lab/processes/test_publish_process_revision.py +232 -0
- pygeai/tests/integration/lab/processes/test_update_process.py +289 -0
- pygeai/tests/integration/lab/reasoning_strategies/__init__.py +0 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_get_reasoning_strategy.py +70 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_list_reasoning_strategies.py +93 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_update_reasoning_strategy.py +149 -0
- pygeai/tests/integration/lab/tools/__init__.py +0 -0
- pygeai/tests/integration/lab/tools/test_create_tool.py +288 -0
- pygeai/tests/integration/lab/tools/test_delete_tool.py +87 -0
- pygeai/tests/integration/lab/tools/test_get_parameter.py +98 -0
- pygeai/tests/integration/lab/tools/test_get_tool.py +91 -0
- pygeai/tests/integration/lab/tools/test_list_tools.py +106 -0
- pygeai/tests/integration/lab/tools/test_publish_tool_revision.py +119 -0
- pygeai/tests/integration/lab/tools/test_set_parameter.py +114 -0
- pygeai/tests/integration/lab/tools/test_update_tool.py +267 -0
- pygeai/tests/lab/__init__.py +0 -0
- pygeai/tests/lab/agents/__init__.py +0 -0
- pygeai/tests/lab/agents/test_clients.py +481 -0
- pygeai/tests/lab/agents/test_mappers.py +440 -0
- pygeai/tests/lab/processes/__init__.py +0 -0
- pygeai/tests/lab/processes/test_clients.py +1416 -0
- pygeai/tests/lab/processes/test_mappers.py +1092 -0
- pygeai/tests/lab/spec/__init__.py +0 -0
- pygeai/tests/lab/spec/test_loader.py +59 -0
- pygeai/tests/lab/spec/test_parsers.py +182 -0
- pygeai/tests/lab/strategies/__init__.py +0 -0
- pygeai/tests/lab/strategies/test_clients.py +241 -0
- pygeai/tests/lab/strategies/test_mappers.py +132 -0
- pygeai/tests/lab/test_managers.py +553 -0
- pygeai/tests/lab/test_mappers.py +245 -0
- pygeai/tests/lab/test_models.py +1154 -0
- pygeai/tests/lab/tools/__init__.py +0 -0
- pygeai/tests/lab/tools/test_clients.py +521 -0
- pygeai/tests/lab/tools/test_mappers.py +198 -0
- pygeai/tests/migration/__init__.py +0 -0
- pygeai/tests/migration/test_strategies.py +405 -0
- pygeai/tests/migration/test_tools.py +159 -0
- pygeai/tests/organization/limits/__init__.py +0 -0
- pygeai/tests/organization/limits/test_clients.py +567 -0
- pygeai/tests/organization/limits/test_managers.py +402 -0
- pygeai/tests/organization/test_clients.py +615 -64
- pygeai/tests/organization/test_managers.py +424 -0
- pygeai/tests/organization/test_mappers.py +153 -0
- pygeai/tests/organization/test_responses.py +137 -0
- pygeai/tests/proxy/__init__.py +1 -0
- pygeai/tests/proxy/test_clients.py +397 -0
- pygeai/tests/proxy/test_config.py +171 -0
- pygeai/tests/proxy/test_integration.py +305 -0
- pygeai/tests/proxy/test_managers.py +312 -0
- pygeai/tests/proxy/test_servers.py +387 -0
- pygeai/tests/proxy/test_tool.py +176 -0
- pygeai/tests/snippets/__init__.py +0 -0
- pygeai/tests/snippets/analytics/__init__.py +0 -0
- pygeai/tests/snippets/analytics/get_agent_usage_per_user.py +16 -0
- pygeai/tests/snippets/analytics/get_agents_created_and_modified.py +11 -0
- pygeai/tests/snippets/analytics/get_average_cost_per_request.py +10 -0
- pygeai/tests/snippets/analytics/get_overall_error_rate.py +10 -0
- pygeai/tests/snippets/analytics/get_top_10_agents_by_requests.py +12 -0
- pygeai/tests/snippets/analytics/get_total_active_users.py +10 -0
- pygeai/tests/snippets/analytics/get_total_cost.py +10 -0
- pygeai/tests/snippets/analytics/get_total_requests_per_day.py +12 -0
- pygeai/tests/snippets/analytics/get_total_tokens.py +12 -0
- pygeai/tests/snippets/assistants/__init__.py +0 -0
- pygeai/tests/snippets/assistants/create_chat_assistant.py +54 -0
- pygeai/tests/snippets/assistants/create_text_assistant.py +51 -0
- pygeai/tests/snippets/assistants/data_analyst/__init__.py +0 -0
- pygeai/tests/snippets/assistants/data_analyst/extend_and_check.py +100 -0
- pygeai/tests/snippets/assistants/data_analyst/extend_dataset.py +9 -0
- pygeai/tests/snippets/assistants/data_analyst/get_status.py +9 -0
- pygeai/tests/snippets/assistants/file_summarizer_assistant.py +149 -0
- pygeai/tests/snippets/assistants/get_assistant_data.py +8 -0
- pygeai/tests/snippets/assistants/get_assistant_list.py +7 -0
- pygeai/tests/snippets/assistants/rag/__init__.py +0 -0
- pygeai/tests/snippets/assistants/rag/create_rag_assistant.py +65 -0
- pygeai/tests/snippets/assistants/rag/delete_al_documents.py +7 -0
- pygeai/tests/snippets/assistants/rag/delete_document.py +10 -0
- pygeai/tests/snippets/assistants/rag/delete_rag_assistant.py +8 -0
- pygeai/tests/snippets/assistants/rag/get_document.py +10 -0
- pygeai/tests/snippets/assistants/rag/get_documents.py +7 -0
- pygeai/tests/snippets/assistants/rag/get_rag_assistant_data.py +8 -0
- pygeai/tests/snippets/assistants/rag/update_rag_assistant.py +48 -0
- pygeai/tests/snippets/assistants/rag/upload_document.py +19 -0
- pygeai/tests/snippets/assistants/send_feedback.py +14 -0
- pygeai/tests/snippets/assistants/update_chat_assistant.py +63 -0
- pygeai/tests/snippets/auth/__init__.py +0 -0
- pygeai/tests/snippets/chat/__init__.py +0 -0
- pygeai/tests/snippets/chat/cancel_request.py +7 -0
- pygeai/tests/snippets/chat/chat_completion.py +28 -0
- pygeai/tests/snippets/chat/chat_completion_1.py +40 -0
- pygeai/tests/snippets/chat/chat_completion_2.py +60 -0
- pygeai/tests/snippets/chat/chat_completion_3.py +27 -0
- pygeai/tests/snippets/chat/chat_completion_4.py +67 -0
- pygeai/tests/snippets/chat/chat_completion_streaming.py +63 -0
- pygeai/tests/snippets/chat/chat_completion_with_reasoning_effort.py +18 -0
- pygeai/tests/snippets/chat/get_request_status.py +7 -0
- pygeai/tests/snippets/chat/get_response.py +15 -0
- pygeai/tests/snippets/chat/get_response_complete_example.py +67 -0
- pygeai/tests/snippets/chat/get_response_streaming.py +20 -0
- pygeai/tests/snippets/chat/get_response_with_files.py +16 -0
- pygeai/tests/snippets/chat/get_response_with_instructions.py +19 -0
- pygeai/tests/snippets/chat/get_response_with_metadata.py +24 -0
- pygeai/tests/snippets/chat/get_response_with_parallel_tools.py +58 -0
- pygeai/tests/snippets/chat/get_response_with_reasoning.py +21 -0
- pygeai/tests/snippets/chat/get_response_with_store.py +38 -0
- pygeai/tests/snippets/chat/get_response_with_tools.py +36 -0
- pygeai/tests/snippets/chat/get_response_with_truncation.py +24 -0
- pygeai/tests/snippets/chat/send_chat_request.py +33 -0
- pygeai/tests/snippets/dbg/__init__.py +0 -0
- pygeai/tests/snippets/dbg/basic_debugging.py +32 -0
- pygeai/tests/snippets/dbg/breakpoint_management.py +48 -0
- pygeai/tests/snippets/dbg/file_debugging.py +72 -0
- pygeai/tests/snippets/dbg/module_debugging.py +61 -0
- pygeai/tests/snippets/dbg/stack_navigation.py +45 -0
- pygeai/tests/snippets/dbg/stepping_example.py +40 -0
- pygeai/tests/snippets/embeddings/__init__.py +0 -0
- pygeai/tests/snippets/embeddings/cache_example.py +31 -0
- pygeai/tests/snippets/embeddings/cohere_example.py +41 -0
- pygeai/tests/snippets/embeddings/generate_embeddings.py +26 -0
- pygeai/tests/snippets/embeddings/openai_base64_example.py +27 -0
- pygeai/tests/snippets/embeddings/openai_example.py +30 -0
- pygeai/tests/snippets/embeddings/similarity_example.py +42 -0
- pygeai/tests/snippets/evaluation/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/dataset/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/dataset/complete_workflow_example.py +195 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset.py +26 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset_from_file.py +11 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset_row.py +17 -0
- pygeai/tests/snippets/evaluation/dataset/create_expected_source.py +18 -0
- pygeai/tests/snippets/evaluation/dataset/create_filter_variable.py +19 -0
- pygeai/tests/snippets/evaluation/dataset/delete_dataset.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/delete_dataset_row.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/delete_expected_source.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/delete_filter_variable.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/get_dataset.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/get_dataset_row.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/get_expected_source.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/get_filter_variable.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/list_dataset_rows.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/list_datasets.py +6 -0
- pygeai/tests/snippets/evaluation/dataset/list_expected_sources.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/list_filter_variables.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/update_dataset.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/update_dataset_row.py +20 -0
- pygeai/tests/snippets/evaluation/dataset/update_expected_source.py +18 -0
- pygeai/tests/snippets/evaluation/dataset/update_filter_variable.py +19 -0
- pygeai/tests/snippets/evaluation/dataset/upload_dataset_rows_file.py +10 -0
- pygeai/tests/snippets/evaluation/plan/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/plan/add_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/complete_workflow_example.py +136 -0
- pygeai/tests/snippets/evaluation/plan/create_evaluation_plan.py +24 -0
- pygeai/tests/snippets/evaluation/plan/create_rag_evaluation_plan.py +22 -0
- pygeai/tests/snippets/evaluation/plan/delete_evaluation_plan.py +9 -0
- pygeai/tests/snippets/evaluation/plan/delete_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/execute_evaluation_plan.py +11 -0
- pygeai/tests/snippets/evaluation/plan/get_evaluation_plan.py +9 -0
- pygeai/tests/snippets/evaluation/plan/get_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/get_system_metric.py +9 -0
- pygeai/tests/snippets/evaluation/plan/list_evaluation_plans.py +7 -0
- pygeai/tests/snippets/evaluation/plan/list_plan_system_metrics.py +9 -0
- pygeai/tests/snippets/evaluation/plan/list_system_metrics.py +7 -0
- pygeai/tests/snippets/evaluation/plan/update_evaluation_plan.py +22 -0
- pygeai/tests/snippets/evaluation/plan/update_plan_system_metric.py +14 -0
- pygeai/tests/snippets/evaluation/result/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/result/complete_workflow_example.py +150 -0
- pygeai/tests/snippets/evaluation/result/get_evaluation_result.py +26 -0
- pygeai/tests/snippets/evaluation/result/list_evaluation_results.py +17 -0
- pygeai/tests/snippets/files/__init__.py +0 -0
- pygeai/tests/snippets/files/delete_file.py +9 -0
- pygeai/tests/snippets/files/get_file_content.py +10 -0
- pygeai/tests/snippets/files/get_file_data.py +9 -0
- pygeai/tests/snippets/files/get_file_list.py +6 -0
- pygeai/tests/snippets/files/upload_file.py +13 -0
- pygeai/tests/snippets/gam/__init__.py +0 -0
- pygeai/tests/snippets/gam/gam_access_token.py +87 -0
- pygeai/tests/snippets/lab/__init__.py +0 -0
- pygeai/tests/snippets/lab/agentic_flow_example_1.py +326 -0
- pygeai/tests/snippets/lab/agentic_flow_example_2.py +206 -0
- pygeai/tests/snippets/lab/agentic_flow_example_3.py +486 -0
- pygeai/tests/snippets/lab/agentic_flow_example_4.py +446 -0
- pygeai/tests/snippets/lab/agents/__init__.py +0 -0
- pygeai/tests/snippets/lab/agents/create_agent.py +48 -0
- pygeai/tests/snippets/lab/agents/create_agent_2.py +48 -0
- pygeai/tests/snippets/lab/agents/create_agent_edge_case.py +48 -0
- pygeai/tests/snippets/lab/agents/create_agent_with_permissions.py +39 -0
- pygeai/tests/snippets/lab/agents/create_agent_with_properties.py +46 -0
- pygeai/tests/snippets/lab/agents/create_agent_without_instructions.py +48 -0
- pygeai/tests/snippets/lab/agents/delete_agent.py +12 -0
- pygeai/tests/snippets/lab/agents/get_agent.py +24 -0
- pygeai/tests/snippets/lab/agents/get_agent_with_new_fields.py +62 -0
- pygeai/tests/snippets/lab/agents/get_sharing_link.py +13 -0
- pygeai/tests/snippets/lab/agents/list_agents.py +18 -0
- pygeai/tests/snippets/lab/agents/publish_agent_revision.py +12 -0
- pygeai/tests/snippets/lab/agents/update_agent.py +50 -0
- pygeai/tests/snippets/lab/agents/update_agent_properties.py +50 -0
- pygeai/tests/snippets/lab/assistant_to_agent.py +191 -0
- pygeai/tests/snippets/lab/crud_ui.py +462 -0
- pygeai/tests/snippets/lab/processes/__init__.py +0 -0
- pygeai/tests/snippets/lab/processes/create_process.py +24 -0
- pygeai/tests/snippets/lab/processes/create_task.py +8 -0
- pygeai/tests/snippets/lab/processes/jobs/__init__.py +0 -0
- pygeai/tests/snippets/lab/processes/jobs/list_jobs.py +21 -0
- pygeai/tests/snippets/lab/processes/kbs/__init__.py +0 -0
- pygeai/tests/snippets/lab/processes/kbs/create_kb.py +18 -0
- pygeai/tests/snippets/lab/processes/kbs/get_kb.py +26 -0
- pygeai/tests/snippets/lab/processes/kbs/list_kbs.py +30 -0
- pygeai/tests/snippets/lab/processes/kbs/try_all.py +73 -0
- pygeai/tests/snippets/lab/processes/list_processes.py +10 -0
- pygeai/tests/snippets/lab/runner_1.py +212 -0
- pygeai/tests/snippets/lab/samples/__init__.py +0 -0
- pygeai/tests/snippets/lab/samples/summarize_files.py +162 -0
- pygeai/tests/snippets/lab/strategies/__init__.py +0 -0
- pygeai/tests/snippets/lab/strategies/create_reasoning_strategy.py +22 -0
- pygeai/tests/snippets/lab/strategies/get_reasoning_strategy.py +10 -0
- pygeai/tests/snippets/lab/strategies/list_reasoning_strategies.py +16 -0
- pygeai/tests/snippets/lab/strategies/update_reasoning_strategy.py +26 -0
- pygeai/tests/snippets/lab/tools/__init__.py +0 -0
- pygeai/tests/snippets/lab/tools/create_tool.py +48 -0
- pygeai/tests/snippets/lab/tools/create_tool_edge_case.py +50 -0
- pygeai/tests/snippets/lab/tools/delete_tool.py +21 -0
- pygeai/tests/snippets/lab/tools/get_parameter.py +21 -0
- pygeai/tests/snippets/lab/tools/get_tool.py +22 -0
- pygeai/tests/snippets/lab/tools/list_tools.py +23 -0
- pygeai/tests/snippets/lab/tools/publish_tool_revision.py +13 -0
- pygeai/tests/snippets/lab/tools/set_parameters.py +33 -0
- pygeai/tests/snippets/lab/tools/update_tool.py +52 -0
- pygeai/tests/snippets/lab/use_cases/__init__.py +0 -0
- pygeai/tests/snippets/lab/use_cases/c_code_fixer_agent_flow.py +238 -0
- pygeai/tests/snippets/lab/use_cases/create_cli_expert.py +1640 -0
- pygeai/tests/snippets/lab/use_cases/create_lab_expert.py +4541 -0
- pygeai/tests/snippets/lab/use_cases/create_tool_headless_web_browser.py +133 -0
- pygeai/tests/snippets/lab/use_cases/create_web_designer.py +189 -0
- pygeai/tests/snippets/lab/use_cases/create_web_reader.py +185 -0
- pygeai/tests/snippets/lab/use_cases/file_summarizer_example.py +157 -0
- pygeai/tests/snippets/lab/use_cases/file_summarizer_example_2.py +157 -0
- pygeai/tests/snippets/lab/use_cases/update_cli_expert.py +1773 -0
- pygeai/tests/snippets/lab/use_cases/update_lab_expert.py +4541 -0
- pygeai/tests/snippets/lab/use_cases/update_web_designer.py +188 -0
- pygeai/tests/snippets/lab/use_cases/update_web_reader.py +195 -0
- pygeai/tests/snippets/lab/use_cases/update_web_reader_with_tool.py +210 -0
- pygeai/tests/snippets/migrate/__init__.py +45 -0
- pygeai/tests/snippets/migrate/agent_migration.py +110 -0
- pygeai/tests/snippets/migrate/assistant_migration.py +64 -0
- pygeai/tests/snippets/migrate/orchestrator_examples.py +179 -0
- pygeai/tests/snippets/migrate/process_migration.py +64 -0
- pygeai/tests/snippets/migrate/project_migration.py +42 -0
- pygeai/tests/snippets/migrate/tool_migration.py +64 -0
- pygeai/tests/snippets/organization/__init__.py +0 -0
- pygeai/tests/snippets/organization/add_project_member.py +10 -0
- pygeai/tests/snippets/organization/add_project_member_batch.py +44 -0
- pygeai/tests/snippets/organization/create_project.py +23 -0
- pygeai/tests/snippets/organization/delete_project.py +7 -0
- pygeai/tests/snippets/organization/export_request_data.py +7 -0
- pygeai/tests/snippets/organization/get_memberships.py +12 -0
- pygeai/tests/snippets/organization/get_organization_members.py +6 -0
- pygeai/tests/snippets/organization/get_project_data.py +7 -0
- pygeai/tests/snippets/organization/get_project_list.py +8 -0
- pygeai/tests/snippets/organization/get_project_members.py +6 -0
- pygeai/tests/snippets/organization/get_project_memberships.py +12 -0
- pygeai/tests/snippets/organization/get_project_roles.py +6 -0
- pygeai/tests/snippets/organization/get_project_tokens.py +7 -0
- pygeai/tests/snippets/organization/update_project.py +14 -0
- pygeai/tests/snippets/rerank/__init__.py +0 -0
- pygeai/tests/snippets/rerank/rerank_chunks.py +19 -0
- pygeai/tests/snippets/secrets/__init__.py +0 -0
- pygeai/tests/snippets/usage_limit/__init__.py +0 -0
- pygeai/tests/snippets/usage_limit/delete_usage_limit.py +16 -0
- pygeai/tests/snippets/usage_limit/get_all_usage_limit_from_organization.py +12 -0
- pygeai/tests/snippets/usage_limit/get_usage_limit_from_organization.py +11 -0
- pygeai/tests/snippets/usage_limit/get_usage_limit_from_project.py +13 -0
- pygeai/tests/snippets/usage_limit/set_usage_limit_organization.py +22 -0
- pygeai/tests/snippets/usage_limit/set_usage_limit_project.py +23 -0
- pygeai/tests/snippets/usage_limit/update_usage_limit_organization.py +23 -0
- pygeai/tests/snippets/usage_limit/update_usage_limit_project.py +24 -0
- pygeai/vendor/a2a/__init__.py +1 -0
- pygeai/vendor/a2a/auth/__init__.py +0 -0
- pygeai/vendor/a2a/auth/user.py +31 -0
- pygeai/vendor/a2a/client/__init__.py +19 -0
- pygeai/vendor/a2a/client/client.py +425 -0
- pygeai/vendor/a2a/client/errors.py +33 -0
- pygeai/vendor/a2a/client/helpers.py +22 -0
- pygeai/vendor/a2a/py.typed +0 -0
- pygeai/vendor/a2a/server/__init__.py +1 -0
- pygeai/vendor/a2a/server/agent_execution/__init__.py +18 -0
- pygeai/vendor/a2a/server/agent_execution/agent_executor.py +44 -0
- pygeai/vendor/a2a/server/agent_execution/context.py +155 -0
- pygeai/vendor/a2a/server/agent_execution/request_context_builder.py +20 -0
- pygeai/vendor/a2a/server/agent_execution/simple_request_context_builder.py +77 -0
- pygeai/vendor/a2a/server/apps/__init__.py +16 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/__init__.py +16 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/fastapi_app.py +88 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/jsonrpc_app.py +426 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/starlette_app.py +123 -0
- pygeai/vendor/a2a/server/context.py +23 -0
- pygeai/vendor/a2a/server/events/__init__.py +21 -0
- pygeai/vendor/a2a/server/events/event_consumer.py +149 -0
- pygeai/vendor/a2a/server/events/event_queue.py +156 -0
- pygeai/vendor/a2a/server/events/in_memory_queue_manager.py +85 -0
- pygeai/vendor/a2a/server/events/queue_manager.py +35 -0
- pygeai/vendor/a2a/server/request_handlers/__init__.py +20 -0
- pygeai/vendor/a2a/server/request_handlers/default_request_handler.py +435 -0
- pygeai/vendor/a2a/server/request_handlers/jsonrpc_handler.py +327 -0
- pygeai/vendor/a2a/server/request_handlers/request_handler.py +161 -0
- pygeai/vendor/a2a/server/request_handlers/response_helpers.py +133 -0
- pygeai/vendor/a2a/server/tasks/__init__.py +20 -0
- pygeai/vendor/a2a/server/tasks/inmemory_push_notifier.py +62 -0
- pygeai/vendor/a2a/server/tasks/inmemory_task_store.py +51 -0
- pygeai/vendor/a2a/server/tasks/push_notifier.py +25 -0
- pygeai/vendor/a2a/server/tasks/result_aggregator.py +151 -0
- pygeai/vendor/a2a/server/tasks/task_manager.py +253 -0
- pygeai/vendor/a2a/server/tasks/task_store.py +22 -0
- pygeai/vendor/a2a/server/tasks/task_updater.py +155 -0
- pygeai/vendor/a2a/types.py +1624 -0
- pygeai/vendor/a2a/utils/__init__.py +40 -0
- pygeai/vendor/a2a/utils/artifact.py +72 -0
- pygeai/vendor/a2a/utils/errors.py +69 -0
- pygeai/vendor/a2a/utils/helpers.py +176 -0
- pygeai/vendor/a2a/utils/message.py +83 -0
- pygeai/vendor/a2a/utils/task.py +57 -0
- pygeai/vendor/a2a/utils/telemetry.py +299 -0
- pygeai-0.6.0b15.dist-info/METADATA +205 -0
- pygeai-0.6.0b15.dist-info/RECORD +799 -0
- {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info}/WHEEL +1 -1
- pygeai-0.6.0b15.dist-info/entry_points.txt +5 -0
- {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info/licenses}/LICENSE +13 -1
- {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info}/top_level.txt +0 -1
- docs/source/conf.py +0 -45
- pygeai/core/clients.py +0 -240
- pygeai/tests/core/test_clients.py +0 -49
- pygeai-0.1.6.dist-info/METADATA +0 -92
- pygeai-0.1.6.dist-info/RECORD +0 -65
- pygeai-0.1.6.dist-info/SOURCES.sync-conflict-20241223-145950-3QD4F42.txt +0 -41
- pygeai-0.1.6.dist-info/entry_points.txt +0 -2
- /pygeai/{agent → analytics}/__init__.py +0 -0
pygeai/proxy/managers.py
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
from contextlib import AsyncExitStack
|
|
2
|
+
from typing import Any, List, Dict, Tuple
|
|
3
|
+
import asyncio
|
|
4
|
+
import json
|
|
5
|
+
import sys
|
|
6
|
+
import requests
|
|
7
|
+
from urllib3.exceptions import MaxRetryError
|
|
8
|
+
import mcp.types as types
|
|
9
|
+
import a2a.types as a2a_types
|
|
10
|
+
from pygeai.proxy.servers import MCPServer, ToolServer, ProxiedTool, A2AServer
|
|
11
|
+
from pygeai.proxy.config import ProxySettingsManager
|
|
12
|
+
from pygeai.proxy.clients import ProxyClient, ToolProxyData, ToolProxyJobResult
|
|
13
|
+
from pygeai.core.utils.console import Console
|
|
14
|
+
|
|
15
|
+
class ServerManager:
|
|
16
|
+
"""
|
|
17
|
+
Manages multiple MCP servers.
|
|
18
|
+
|
|
19
|
+
:param servers_cfg: List[Dict[str, Any]] - List of server configurations
|
|
20
|
+
:param settings: ProxySettingsManager - Proxy settings manager
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, servers_cfg: List[Dict[str, Any]], settings: ProxySettingsManager):
|
|
24
|
+
"""
|
|
25
|
+
Initialize the server manager.
|
|
26
|
+
|
|
27
|
+
:param servers_cfg: List[Dict[str, Any]] - List of server configurations
|
|
28
|
+
:param settings: ProxySettingsManager - Proxy settings manager
|
|
29
|
+
"""
|
|
30
|
+
self.servers_cfg = servers_cfg
|
|
31
|
+
self.settings = settings
|
|
32
|
+
self.servers: Dict[str, ToolServer] = {}
|
|
33
|
+
self.tools: Dict[str, ProxiedTool] = {}
|
|
34
|
+
self.exit_stack: AsyncExitStack = AsyncExitStack()
|
|
35
|
+
|
|
36
|
+
async def _initialize_servers(self) -> None:
|
|
37
|
+
"""
|
|
38
|
+
Initialize all servers.
|
|
39
|
+
|
|
40
|
+
:return: None
|
|
41
|
+
:raises: Exception - If server initialization fails
|
|
42
|
+
"""
|
|
43
|
+
for server_cfg in self.servers_cfg:
|
|
44
|
+
Console.write_stdout(f"Initializing server {server_cfg['name']} type: {server_cfg['type']}")
|
|
45
|
+
if server_cfg['type'] == 'mcp':
|
|
46
|
+
server = MCPServer(server_cfg['name'], server_cfg, self.settings)
|
|
47
|
+
elif server_cfg['type'] == 'a2a':
|
|
48
|
+
server = A2AServer(server_cfg['name'], server_cfg, self.settings)
|
|
49
|
+
else:
|
|
50
|
+
raise ValueError(f"Invalid server type: {server_cfg['type']}")
|
|
51
|
+
try:
|
|
52
|
+
await self.exit_stack.enter_async_context(server.exit_stack)
|
|
53
|
+
await server.initialize()
|
|
54
|
+
self.servers[server.name] = server
|
|
55
|
+
Console.write_stdout(f"\nServer {server.name} initialized successfully", end="\n\n")
|
|
56
|
+
except Exception as e:
|
|
57
|
+
Console.write_exception(f"Failed to initialize server {server.name}:", e)
|
|
58
|
+
raise
|
|
59
|
+
|
|
60
|
+
for server in self.servers.values():
|
|
61
|
+
Console.write_stdout(f"Listing tools for server {server.name}", end="")
|
|
62
|
+
if server.public_prefix:
|
|
63
|
+
Console.write_stdout(f" | access scope:public prefix: {server.public_prefix}")
|
|
64
|
+
else:
|
|
65
|
+
Console.write_stdout(" ! access scope:private")
|
|
66
|
+
|
|
67
|
+
tools = await server.list_tools()
|
|
68
|
+
for tool in tools:
|
|
69
|
+
self.tools[tool.get_full_name()] = tool
|
|
70
|
+
Console.write_stdout(f"\tTool {tool.get_full_name()} added to server {server.name}")
|
|
71
|
+
|
|
72
|
+
async def _initialize_client(self) -> ProxyClient:
|
|
73
|
+
"""
|
|
74
|
+
Initialize the client.
|
|
75
|
+
|
|
76
|
+
:return: ProxyClient - Initialized client instance
|
|
77
|
+
:raises: ConnectionError - If connection fails
|
|
78
|
+
:raises: MaxRetryError - If max retries are exceeded
|
|
79
|
+
"""
|
|
80
|
+
try:
|
|
81
|
+
alias = self.settings.get_current_alias()
|
|
82
|
+
client = ProxyClient(self.settings.get_api_key(alias), self.settings.get_base_url(alias), self.settings.get_proxy_id(alias))
|
|
83
|
+
Console.write_stdout(f"\nRegistering proxy {self.settings.get_proxy_id(alias)} with name {self.settings.get_proxy_name(alias)} and description {self.settings.get_proxy_description(alias)}")
|
|
84
|
+
result = client.register(proxy_data=ToolProxyData(
|
|
85
|
+
id=self.settings.get_proxy_id(alias),
|
|
86
|
+
name=self.settings.get_proxy_name(alias),
|
|
87
|
+
description=self.settings.get_proxy_description(alias),
|
|
88
|
+
affinity=self.settings.get_proxy_affinity(alias),
|
|
89
|
+
tools=list(self.tools.values())
|
|
90
|
+
))
|
|
91
|
+
Console.write_stdout("----------------------------------")
|
|
92
|
+
Console.write_stdout(f"Proxy registered successfully:")
|
|
93
|
+
if isinstance(result, dict) and isinstance(result.get("Messages"), list):
|
|
94
|
+
for message in result["Messages"]:
|
|
95
|
+
description = message.get("Description", "")
|
|
96
|
+
message_type = message.get("Type", None)
|
|
97
|
+
|
|
98
|
+
if message_type == 1:
|
|
99
|
+
Console.write_stderr(description)
|
|
100
|
+
elif message_type == 2:
|
|
101
|
+
Console.write_stdout(description)
|
|
102
|
+
Console.write_stdout("----------------------------------")
|
|
103
|
+
return client
|
|
104
|
+
except (ConnectionError, MaxRetryError):
|
|
105
|
+
Console.write_exception(f"Error registering proxy {self.settings.get_proxy_id(alias)}:")
|
|
106
|
+
raise
|
|
107
|
+
|
|
108
|
+
async def execute_tool(
|
|
109
|
+
self,
|
|
110
|
+
server_name: str,
|
|
111
|
+
tool_name: str,
|
|
112
|
+
arguments: dict[str, Any],
|
|
113
|
+
retries: int = 2,
|
|
114
|
+
delay: float = 1.0,
|
|
115
|
+
) -> Any:
|
|
116
|
+
"""
|
|
117
|
+
Execute a tool with retry mechanism.
|
|
118
|
+
|
|
119
|
+
:param server_name: str - Name of the server to execute the tool on
|
|
120
|
+
:param tool_name: str - Name of the tool to execute
|
|
121
|
+
:param arguments: dict[str, Any] - Tool arguments
|
|
122
|
+
:param retries: int - Number of retry attempts
|
|
123
|
+
:param delay: float - Delay between retries in seconds
|
|
124
|
+
:return: Any - Tool execution result
|
|
125
|
+
:raises: RuntimeError - If server is not found or not initialized
|
|
126
|
+
:raises: Exception - If tool execution fails after all retries
|
|
127
|
+
"""
|
|
128
|
+
if server_name not in self.servers:
|
|
129
|
+
raise RuntimeError(f"Server {server_name} not found")
|
|
130
|
+
|
|
131
|
+
if tool_name not in self.tools:
|
|
132
|
+
raise RuntimeError(f"Tool {tool_name} not found")
|
|
133
|
+
|
|
134
|
+
server = self.servers[server_name]
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
result = await server.execute_tool(self.tools[tool_name].name, arguments, retries, delay)
|
|
138
|
+
return result
|
|
139
|
+
except (RuntimeError, ConnectionError, TimeoutError) as e:
|
|
140
|
+
raise Exception(f"Failed to execute tool {tool_name} on server {server_name}: {e}") from e
|
|
141
|
+
|
|
142
|
+
def extract_function_call_info(self, raw_json: str) -> Tuple[str, str]:
|
|
143
|
+
"""
|
|
144
|
+
Extract function call info from raw JSON.
|
|
145
|
+
|
|
146
|
+
:param raw_json: str - Raw JSON string
|
|
147
|
+
:return: Tuple[str, str] - Tuple containing function name and arguments
|
|
148
|
+
"""
|
|
149
|
+
try:
|
|
150
|
+
data = json.loads(raw_json)
|
|
151
|
+
return data['function']['name'], data['function']['arguments']
|
|
152
|
+
except (json.JSONDecodeError, KeyError) as e:
|
|
153
|
+
Console.write_stdout(f"Error extracting function call info: {e}")
|
|
154
|
+
return None, None
|
|
155
|
+
|
|
156
|
+
async def start(self) -> None:
|
|
157
|
+
"""
|
|
158
|
+
Main proxy session handler.
|
|
159
|
+
|
|
160
|
+
:return: None
|
|
161
|
+
"""
|
|
162
|
+
retry_count = 0
|
|
163
|
+
MAX_RETRIES = 10
|
|
164
|
+
while retry_count < MAX_RETRIES:
|
|
165
|
+
try:
|
|
166
|
+
await self._initialize_servers()
|
|
167
|
+
try:
|
|
168
|
+
client = await self._initialize_client()
|
|
169
|
+
except (ConnectionError, TimeoutError, RuntimeError) as e:
|
|
170
|
+
Console.write_exception(f"Error during client initialization:", e)
|
|
171
|
+
for i in range(15, 0, -1):
|
|
172
|
+
Console.write_stdout(f"\rRetrying in {i} seconds... ",'')
|
|
173
|
+
await asyncio.sleep(1)
|
|
174
|
+
Console.write_stdout("\rRetrying now... ")
|
|
175
|
+
retry_count += 1
|
|
176
|
+
continue
|
|
177
|
+
|
|
178
|
+
retry_count = 0
|
|
179
|
+
Console.write_stdout(f"Waiting for jobs...")
|
|
180
|
+
while True:
|
|
181
|
+
try:
|
|
182
|
+
jobs = client.dequeue()
|
|
183
|
+
retry_count = 0
|
|
184
|
+
except requests.exceptions.RequestException as e:
|
|
185
|
+
retry_count += 1
|
|
186
|
+
if retry_count >= MAX_RETRIES:
|
|
187
|
+
Console.write_stderr(f"Failed to dequeue jobs after {MAX_RETRIES} retries.")
|
|
188
|
+
Console.write_exception(f"Exception:", e, "\nExiting...")
|
|
189
|
+
return
|
|
190
|
+
Console.write_stderr(f"Failed to dequeue jobs (attempt {retry_count}/{MAX_RETRIES}):")
|
|
191
|
+
for i in range(15, 0, -1):
|
|
192
|
+
Console.write_stdout(f"\rRetrying in {i} seconds... ",'')
|
|
193
|
+
await asyncio.sleep(1)
|
|
194
|
+
Console.write_stdout("\rRetrying now... ")
|
|
195
|
+
continue
|
|
196
|
+
for job in jobs:
|
|
197
|
+
Console.write_stdout(f"----------------------------------Job: {job.id}----------------------------------")
|
|
198
|
+
tool_name, arguments = self.extract_function_call_info(job.input)
|
|
199
|
+
if tool_name:
|
|
200
|
+
Console.write_stdout(f"Executing tool {job.server}/{tool_name} with arguments {arguments}")
|
|
201
|
+
try:
|
|
202
|
+
result = await self.execute_tool(job.server, tool_name, json.loads(arguments))
|
|
203
|
+
except (Exception) as e:
|
|
204
|
+
Console.write_exception(f"Error executing tool {tool_name}:", e)
|
|
205
|
+
continue
|
|
206
|
+
|
|
207
|
+
if isinstance(result.content, list):
|
|
208
|
+
text_parts = []
|
|
209
|
+
for item in result.content:
|
|
210
|
+
if isinstance(item, types.TextContent):
|
|
211
|
+
text_parts.append(item.text)
|
|
212
|
+
elif isinstance(item, a2a_types.Part):
|
|
213
|
+
if isinstance(item.root, a2a_types.TextPart):
|
|
214
|
+
text_parts.append(item.root.text)
|
|
215
|
+
else:
|
|
216
|
+
Console.write_stdout(f"Unknown content type {type(item.root)}")
|
|
217
|
+
else:
|
|
218
|
+
Console.write_stdout(f"Unknown content type {type(item)}")
|
|
219
|
+
|
|
220
|
+
if text_parts:
|
|
221
|
+
job.output = "\n".join(text_parts)
|
|
222
|
+
Console.write_stdout(f"result: {job.output} success: {not result.isError}")
|
|
223
|
+
try:
|
|
224
|
+
client.send_result(ToolProxyJobResult(success=result.isError, job=job))
|
|
225
|
+
except (ConnectionError, TimeoutError, RuntimeError) as e:
|
|
226
|
+
Console.write_exception("Error sending result:", e)
|
|
227
|
+
else:
|
|
228
|
+
Console.write_stdout(f"{result}")
|
|
229
|
+
await asyncio.sleep(1)
|
|
230
|
+
finally:
|
|
231
|
+
Console.write_stdout("Proxy stopped")
|
|
232
|
+
await self.exit_stack.aclose()
|
pygeai/proxy/servers.py
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"""Server module for managing MCP server connections and tool execution."""
|
|
2
|
+
import asyncio
|
|
3
|
+
import os
|
|
4
|
+
import shutil
|
|
5
|
+
import httpx
|
|
6
|
+
from types import SimpleNamespace
|
|
7
|
+
from uuid import uuid4
|
|
8
|
+
from contextlib import AsyncExitStack
|
|
9
|
+
from abc import ABC, abstractmethod
|
|
10
|
+
from typing import Any, Dict
|
|
11
|
+
from mcp import ClientSession, StdioServerParameters
|
|
12
|
+
from mcp.client.stdio import stdio_client
|
|
13
|
+
from mcp.client.sse import sse_client
|
|
14
|
+
from pygeai.proxy.tool import ProxiedTool
|
|
15
|
+
from pygeai.proxy.config import ProxySettingsManager
|
|
16
|
+
from a2a.client import A2AClient, A2ACardResolver
|
|
17
|
+
from a2a.types import (
|
|
18
|
+
AgentCard, SendMessageRequest, MessageSendParams,
|
|
19
|
+
Message, Task, SendMessageSuccessResponse
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
from pygeai.core.utils.console import Console
|
|
23
|
+
|
|
24
|
+
class ToolServer(ABC):
|
|
25
|
+
"""
|
|
26
|
+
Interface for tool servers like MCP and A2A.
|
|
27
|
+
|
|
28
|
+
Subclasses must implement methods to initialize the server,
|
|
29
|
+
list available tools, and execute a tool.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, sever_name: str, config: Dict[str, Any], settings: ProxySettingsManager):
|
|
33
|
+
"""
|
|
34
|
+
Initialize the server.
|
|
35
|
+
|
|
36
|
+
:param sever_name: str - Name of the server
|
|
37
|
+
:param config: Dict[str, Any] - Server configuration
|
|
38
|
+
:param settings: ProxySettingsManager - Proxy settings manager
|
|
39
|
+
"""
|
|
40
|
+
self.config = config
|
|
41
|
+
self.settings = settings
|
|
42
|
+
self.name: str = sever_name
|
|
43
|
+
self.public_prefix: str | None = None
|
|
44
|
+
self.exit_stack: AsyncExitStack = AsyncExitStack()
|
|
45
|
+
|
|
46
|
+
@abstractmethod
|
|
47
|
+
async def initialize(self) -> None:
|
|
48
|
+
"""
|
|
49
|
+
Initialize the server connection.
|
|
50
|
+
|
|
51
|
+
:return: None
|
|
52
|
+
:raises: ValueError - If the command is invalid
|
|
53
|
+
:raises: RuntimeError - If server initialization fails
|
|
54
|
+
:raises: ConnectionError - If connection to server fails
|
|
55
|
+
"""
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
@abstractmethod
|
|
59
|
+
async def list_tools(self) -> list[ProxiedTool]:
|
|
60
|
+
"""
|
|
61
|
+
List available tools from the server.
|
|
62
|
+
|
|
63
|
+
:return: list[Tool] - List of available tools
|
|
64
|
+
:raises: RuntimeError - If server is not initialized
|
|
65
|
+
"""
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
@abstractmethod
|
|
69
|
+
async def execute_tool(
|
|
70
|
+
self,
|
|
71
|
+
tool_name: str,
|
|
72
|
+
arguments: dict[str, Any],
|
|
73
|
+
retries: int = 2,
|
|
74
|
+
delay: float = 1.0,
|
|
75
|
+
) -> Any:
|
|
76
|
+
"""
|
|
77
|
+
Execute a tool with retry mechanism.
|
|
78
|
+
|
|
79
|
+
:param tool_name: str - Name of the tool to execute
|
|
80
|
+
:param arguments: dict[str, Any] - Tool arguments
|
|
81
|
+
:param retries: int - Number of retry attempts
|
|
82
|
+
:param delay: float - Delay between retries in seconds
|
|
83
|
+
:return: Any - Tool execution result
|
|
84
|
+
:raises: RuntimeError - If server is not initialized
|
|
85
|
+
:raises: ConnectionError - If connection to server fails
|
|
86
|
+
:raises: ValueError - If tool execution fails
|
|
87
|
+
"""
|
|
88
|
+
pass
|
|
89
|
+
|
|
90
|
+
class A2AServer(ToolServer):
|
|
91
|
+
"""
|
|
92
|
+
Manages A2A server connections and tool execution.
|
|
93
|
+
"""
|
|
94
|
+
def __init__(self, sever_name: str, config: Dict[str, Any], settings: ProxySettingsManager):
|
|
95
|
+
super().__init__(sever_name, config, settings)
|
|
96
|
+
self.client: A2AClient | None = None
|
|
97
|
+
self.card_url: str = self.config["url"]
|
|
98
|
+
self.agent_card: AgentCard | None = None
|
|
99
|
+
self.httpx_client: httpx.AsyncClient | None = None
|
|
100
|
+
|
|
101
|
+
async def initialize(self) -> None:
|
|
102
|
+
"""
|
|
103
|
+
Initialize the A2A client from the agent card and convert agent skills into tools
|
|
104
|
+
compatible with OpenAI function call format.
|
|
105
|
+
"""
|
|
106
|
+
try:
|
|
107
|
+
self.httpx_client = httpx.AsyncClient(timeout=60.0)
|
|
108
|
+
self.public_prefix = self.config.get("public_prefix")
|
|
109
|
+
headers = self.config.get("headers")
|
|
110
|
+
if headers:
|
|
111
|
+
self.httpx_client.headers.update(headers)
|
|
112
|
+
resolver = A2ACardResolver(httpx_client=self.httpx_client, base_url=self.card_url)
|
|
113
|
+
self.agent_card = await resolver.get_agent_card()
|
|
114
|
+
self.client = A2AClient(httpx_client=self.httpx_client, agent_card=self.agent_card)
|
|
115
|
+
|
|
116
|
+
except httpx.HTTPError as e:
|
|
117
|
+
Console.write_exception(f"HTTP error initializing A2A server {self.name}:", e)
|
|
118
|
+
raise ConnectionError(f"Failed to connect to A2A server: {e}") from e
|
|
119
|
+
except ValueError as e:
|
|
120
|
+
Console.write_exception(f"Invalid configuration for A2A server {self.name}:" ,e)
|
|
121
|
+
raise ValueError(f"Invalid A2A server configuration: {e}") from e
|
|
122
|
+
except RuntimeError as e:
|
|
123
|
+
Console.write_exception(f"Runtime error initializing A2A server {self.name}:", e)
|
|
124
|
+
raise RuntimeError(f"A2A server initialization failed: {e}") from e
|
|
125
|
+
|
|
126
|
+
async def list_tools(self) -> list[ProxiedTool]:
|
|
127
|
+
if not self.client:
|
|
128
|
+
raise RuntimeError(f"Server {self.name} not initialized")
|
|
129
|
+
input_schema = {
|
|
130
|
+
"type": "object",
|
|
131
|
+
"properties": {
|
|
132
|
+
"input-text": {
|
|
133
|
+
"type": "string",
|
|
134
|
+
"description": "The input text to send to the agent for execution."
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
"required": ["input-text"]
|
|
138
|
+
}
|
|
139
|
+
tools = []
|
|
140
|
+
for skill in self.agent_card.skills:
|
|
141
|
+
tools.append(ProxiedTool(self.name, skill.id, skill.description, self.public_prefix, input_schema))
|
|
142
|
+
return tools
|
|
143
|
+
|
|
144
|
+
async def execute_tool(
|
|
145
|
+
self,
|
|
146
|
+
tool_name: str,
|
|
147
|
+
arguments: dict[str, Any],
|
|
148
|
+
retries: int = 2,
|
|
149
|
+
delay: float = 1.0,
|
|
150
|
+
) -> Any:
|
|
151
|
+
Console.write_stdout(f"Executing {tool_name}...")
|
|
152
|
+
message_id = uuid4().hex
|
|
153
|
+
send_message_payload: dict[str, Any] = {
|
|
154
|
+
'message': {
|
|
155
|
+
'role': 'user',
|
|
156
|
+
'parts': [
|
|
157
|
+
{
|
|
158
|
+
'kind': 'text',
|
|
159
|
+
'text': (
|
|
160
|
+
'Use your skill:' + tool_name +
|
|
161
|
+
' with this input:' + arguments["input-text"]
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
],
|
|
165
|
+
'messageId': message_id,
|
|
166
|
+
},
|
|
167
|
+
}
|
|
168
|
+
request = SendMessageRequest(
|
|
169
|
+
id=message_id,
|
|
170
|
+
params=MessageSendParams(**send_message_payload)
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
response = await self.client.send_message(request)
|
|
174
|
+
result = []
|
|
175
|
+
if isinstance(response.root, SendMessageSuccessResponse):
|
|
176
|
+
if isinstance(response.root.result, Message):
|
|
177
|
+
result = response.root.result.parts
|
|
178
|
+
elif isinstance(response.root, Task):
|
|
179
|
+
Console.write_stderr(f"Task response: {response.root.result}")
|
|
180
|
+
else:
|
|
181
|
+
Console.write_stderr(f"Unknown response type: {type(response.root)}")
|
|
182
|
+
raise ValueError(f"Unknown response type: {type(response.root)}")
|
|
183
|
+
|
|
184
|
+
return SimpleNamespace(content=result, isError=False)
|
|
185
|
+
|
|
186
|
+
class MCPServer(ToolServer):
|
|
187
|
+
"""
|
|
188
|
+
Manages MCP server connections and tool execution.
|
|
189
|
+
|
|
190
|
+
:param sever_name: str - Name of the server
|
|
191
|
+
:param config: Dict[str, Any] - Server configuration
|
|
192
|
+
:param settings: ProxySettingsManager - Proxy settings manager
|
|
193
|
+
"""
|
|
194
|
+
def __init__(self, sever_name: str, config: Dict[str, Any], settings: ProxySettingsManager):
|
|
195
|
+
super().__init__(sever_name, config, settings)
|
|
196
|
+
self.public_prefix = config.get("public_prefix")
|
|
197
|
+
self.stdio_context: Any | None = None
|
|
198
|
+
self.session: ClientSession | None = None
|
|
199
|
+
|
|
200
|
+
async def initialize(self) -> None:
|
|
201
|
+
self.public_prefix = self.config.get("public_prefix")
|
|
202
|
+
transport = self.config.get("transport") or (
|
|
203
|
+
"sse" if ("uri" in self.config or "url" in self.config) else "stdio"
|
|
204
|
+
)
|
|
205
|
+
try:
|
|
206
|
+
if transport == "stdio":
|
|
207
|
+
command = (
|
|
208
|
+
shutil.which("npx")
|
|
209
|
+
if self.config["command"] == "npx"
|
|
210
|
+
else self.config["command"]
|
|
211
|
+
)
|
|
212
|
+
if command is None:
|
|
213
|
+
raise ValueError("The command must be una cadena válida")
|
|
214
|
+
|
|
215
|
+
server_params = StdioServerParameters(
|
|
216
|
+
command=command,
|
|
217
|
+
args=self.config["args"],
|
|
218
|
+
env=(
|
|
219
|
+
{**os.environ, **self.config["env"]}
|
|
220
|
+
if self.config.get("env")
|
|
221
|
+
else None
|
|
222
|
+
),
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
stdio_transport = await self.exit_stack.enter_async_context(
|
|
226
|
+
stdio_client(server_params)
|
|
227
|
+
)
|
|
228
|
+
read, write = stdio_transport
|
|
229
|
+
elif transport == "sse":
|
|
230
|
+
uri = self.config.get("uri", self.config["url"])
|
|
231
|
+
if not uri:
|
|
232
|
+
raise ValueError("Missing 'uri' for sse transport")
|
|
233
|
+
try:
|
|
234
|
+
sse_transport = await self.exit_stack.enter_async_context(
|
|
235
|
+
sse_client(
|
|
236
|
+
url=uri,
|
|
237
|
+
headers=self.config.get("headers")
|
|
238
|
+
)
|
|
239
|
+
)
|
|
240
|
+
read, write = sse_transport
|
|
241
|
+
except httpx.HTTPStatusError as e:
|
|
242
|
+
Console.write_exception(f"HTTP error initializing MCP server {self.name}:", e)
|
|
243
|
+
else:
|
|
244
|
+
raise ValueError(f"Unsupported transport: {transport}")
|
|
245
|
+
|
|
246
|
+
session = await self.exit_stack.enter_async_context(
|
|
247
|
+
ClientSession(read, write)
|
|
248
|
+
)
|
|
249
|
+
await session.initialize()
|
|
250
|
+
self.session = session
|
|
251
|
+
except (RuntimeError, ConnectionError, ValueError) as e:
|
|
252
|
+
Console.write_exception(f"Error initializing server {self.name}:", e)
|
|
253
|
+
raise
|
|
254
|
+
|
|
255
|
+
async def list_tools(self) -> list[ProxiedTool]:
|
|
256
|
+
if not self.session:
|
|
257
|
+
raise RuntimeError(f"Server {self.name} not initialized")
|
|
258
|
+
|
|
259
|
+
tools_response = await self.session.list_tools()
|
|
260
|
+
tools = []
|
|
261
|
+
|
|
262
|
+
for item in tools_response:
|
|
263
|
+
if isinstance(item, tuple) and item[0] == "tools":
|
|
264
|
+
for tool in item[1]:
|
|
265
|
+
tools.append(
|
|
266
|
+
ProxiedTool(
|
|
267
|
+
self.name,
|
|
268
|
+
tool.name,
|
|
269
|
+
tool.description,
|
|
270
|
+
self.public_prefix,
|
|
271
|
+
tool.inputSchema
|
|
272
|
+
)
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
return tools
|
|
276
|
+
|
|
277
|
+
async def execute_tool(
|
|
278
|
+
self,
|
|
279
|
+
tool_name: str,
|
|
280
|
+
arguments: dict[str, Any],
|
|
281
|
+
retries: int = 2,
|
|
282
|
+
delay: float = 1.0,
|
|
283
|
+
) -> Any:
|
|
284
|
+
if not self.session:
|
|
285
|
+
raise RuntimeError(f"Server {self.name} not initialized")
|
|
286
|
+
|
|
287
|
+
attempt = 0
|
|
288
|
+
while attempt < retries:
|
|
289
|
+
try:
|
|
290
|
+
Console.write_stdout(f"Executing {tool_name}...")
|
|
291
|
+
result = await self.session.call_tool(tool_name, arguments)
|
|
292
|
+
return result
|
|
293
|
+
|
|
294
|
+
except (RuntimeError, ConnectionError, ValueError) as e:
|
|
295
|
+
attempt += 1
|
|
296
|
+
Console.write_exception(
|
|
297
|
+
"Error executing tool:", e, f". Attempt {attempt} of {retries}.\n"
|
|
298
|
+
)
|
|
299
|
+
if attempt < retries:
|
|
300
|
+
Console.write_stdout(f"Retrying in {delay} seconds...")
|
|
301
|
+
await asyncio.sleep(delay)
|
|
302
|
+
else:
|
|
303
|
+
Console.write_stdout("Max retries reached. Failing.")
|
|
304
|
+
raise
|
pygeai/proxy/tool.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ProxiedTool:
|
|
6
|
+
"""
|
|
7
|
+
Represents a tool exposed by an ToolServer (Multi-Channel Proxy).
|
|
8
|
+
|
|
9
|
+
:param server_name: str - Name of the server exposing the tool
|
|
10
|
+
:param name: str - Name of the tool
|
|
11
|
+
:param description: str - Description of the tool's functionality
|
|
12
|
+
:param public_prefix: str - Public prefix of the tool
|
|
13
|
+
:param input_schema: dict[str, Any] - JSON schema defining the expected input for the tool
|
|
14
|
+
:return: ProxiedTool - Instance of the ProxiedTool class
|
|
15
|
+
:raises: ValueError - If any required parameter is invalid or missing
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
server_name: str,
|
|
21
|
+
name: str,
|
|
22
|
+
description: str,
|
|
23
|
+
public_prefix: str,
|
|
24
|
+
input_schema: dict[str, Any]
|
|
25
|
+
) -> None:
|
|
26
|
+
self.server_name: str = server_name
|
|
27
|
+
self.name: str = name
|
|
28
|
+
self.openai_compatible_name: str = self._get_openai_compatible_name(name)
|
|
29
|
+
self.description: str = description
|
|
30
|
+
self.input_schema: dict[str, Any] = input_schema
|
|
31
|
+
self.public_prefix: str = public_prefix
|
|
32
|
+
|
|
33
|
+
def get_full_name(self) -> str:
|
|
34
|
+
"""Get the full name of the tool."""
|
|
35
|
+
return f"{self.server_name}__{self.openai_compatible_name}"
|
|
36
|
+
|
|
37
|
+
def is_public(self) -> bool:
|
|
38
|
+
"""Check if the tool is public."""
|
|
39
|
+
return self.public_prefix is not None
|
|
40
|
+
|
|
41
|
+
def get_public_name(self) -> str:
|
|
42
|
+
"""Get the public name of the tool."""
|
|
43
|
+
if not self.public_prefix:
|
|
44
|
+
return ""
|
|
45
|
+
if self.server_name in self.public_prefix:
|
|
46
|
+
return f"{self.public_prefix}.{self.name}"
|
|
47
|
+
else:
|
|
48
|
+
return f"{self.public_prefix}.{self.get_full_name()}"
|
|
49
|
+
|
|
50
|
+
def format_for_llm(self) -> str:
|
|
51
|
+
"""Format tool information for LLM.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
A formatted string describing the tool.
|
|
55
|
+
"""
|
|
56
|
+
return json.dumps({
|
|
57
|
+
'type': 'function',
|
|
58
|
+
'function': {
|
|
59
|
+
'name': self.get_full_name(),
|
|
60
|
+
'description': self.description or '',
|
|
61
|
+
'parameters': self.input_schema
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
def _get_openai_compatible_name(self, name: str) -> str:
|
|
66
|
+
compatible_name = ''.join(
|
|
67
|
+
c if c.isalnum() or c in '-_' else '_' for c in name.lower()
|
|
68
|
+
)
|
|
69
|
+
return compatible_name
|
|
File without changes
|