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
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import json
|
|
2
1
|
|
|
2
|
+
from pygeai import logger
|
|
3
3
|
from pygeai.core.base.clients import BaseClient
|
|
4
|
+
from pygeai.core.common.exceptions import InvalidAPIResponseException
|
|
5
|
+
from pygeai.core.utils.validators import validate_status_code
|
|
6
|
+
from pygeai.core.utils.parsers import parse_json_response
|
|
4
7
|
from pygeai.organization.limits.endpoints import SET_ORGANIZATION_USAGE_LIMIT_V2, GET_ORGANIZATION_LATEST_USAGE_LIMIT_V2, \
|
|
5
8
|
GET_ALL_ORGANIZATION_USAGE_LIMITS_V2, DELETE_ORGANIZATION_USAGE_LIMIT_V2, SET_ORGANIZATION_HARD_LIMIT_V2, \
|
|
6
9
|
SET_ORGANIZATION_SOFT_LIMIT_V2, SET_ORGANIZATION_RENEWAL_STATUS_V2, SET_PROJECT_USAGE_LIMIT_V2, \
|
|
@@ -27,13 +30,12 @@ class UsageLimitClient(BaseClient):
|
|
|
27
30
|
:return: dict - The API response as a JSON object containing details about the created usage limit.
|
|
28
31
|
"""
|
|
29
32
|
endpoint = SET_ORGANIZATION_USAGE_LIMIT_V2.format(organization=organization)
|
|
30
|
-
print(f"usage_limit: {usage_limit}")
|
|
31
33
|
response = self.api_service.post(
|
|
32
34
|
endpoint=endpoint,
|
|
33
35
|
data=usage_limit
|
|
34
36
|
)
|
|
35
|
-
|
|
36
|
-
return
|
|
37
|
+
validate_status_code(response)
|
|
38
|
+
return parse_json_response(response, f"set usage limit for organization", organization=organization)
|
|
37
39
|
|
|
38
40
|
def get_organization_latest_usage_limit(self, organization: str) -> dict:
|
|
39
41
|
"""
|
|
@@ -44,8 +46,8 @@ class UsageLimitClient(BaseClient):
|
|
|
44
46
|
"""
|
|
45
47
|
endpoint = GET_ORGANIZATION_LATEST_USAGE_LIMIT_V2.format(organization=organization)
|
|
46
48
|
response = self.api_service.get(endpoint=endpoint)
|
|
47
|
-
|
|
48
|
-
return
|
|
49
|
+
validate_status_code(response)
|
|
50
|
+
return parse_json_response(response, f"get latest usage limit for organization", organization=organization)
|
|
49
51
|
|
|
50
52
|
def get_all_usage_limits_from_organization(self, organization: str) -> dict:
|
|
51
53
|
"""
|
|
@@ -56,8 +58,8 @@ class UsageLimitClient(BaseClient):
|
|
|
56
58
|
"""
|
|
57
59
|
endpoint = GET_ALL_ORGANIZATION_USAGE_LIMITS_V2.format(organization=organization)
|
|
58
60
|
response = self.api_service.get(endpoint=endpoint)
|
|
59
|
-
|
|
60
|
-
return
|
|
61
|
+
validate_status_code(response)
|
|
62
|
+
return parse_json_response(response, f"get all usage limits for organization", organization=organization)
|
|
61
63
|
|
|
62
64
|
def delete_usage_limit_from_organization(self, organization: str, limit_id: str) -> dict:
|
|
63
65
|
"""
|
|
@@ -69,8 +71,8 @@ class UsageLimitClient(BaseClient):
|
|
|
69
71
|
"""
|
|
70
72
|
endpoint = DELETE_ORGANIZATION_USAGE_LIMIT_V2.format(organization=organization, id=limit_id)
|
|
71
73
|
response = self.api_service.delete(endpoint=endpoint)
|
|
72
|
-
|
|
73
|
-
return
|
|
74
|
+
validate_status_code(response)
|
|
75
|
+
return parse_json_response(response, f"delete usage limit with ID '{limit_id}' from organization", organization=organization)
|
|
74
76
|
|
|
75
77
|
def set_organization_hard_limit(self, organization: str, limit_id: str, hard_limit: float) -> dict:
|
|
76
78
|
"""
|
|
@@ -88,8 +90,8 @@ class UsageLimitClient(BaseClient):
|
|
|
88
90
|
"hardLimit": hard_limit
|
|
89
91
|
}
|
|
90
92
|
)
|
|
91
|
-
|
|
92
|
-
return
|
|
93
|
+
validate_status_code(response)
|
|
94
|
+
return parse_json_response(response, f"set hard limit for usage limit ID '{limit_id}' in organization", organization=organization)
|
|
93
95
|
|
|
94
96
|
def set_organization_soft_limit(self, organization: str, limit_id: str, soft_limit: float) -> dict:
|
|
95
97
|
"""
|
|
@@ -107,8 +109,8 @@ class UsageLimitClient(BaseClient):
|
|
|
107
109
|
"softLimit": soft_limit
|
|
108
110
|
}
|
|
109
111
|
)
|
|
110
|
-
|
|
111
|
-
return
|
|
112
|
+
validate_status_code(response)
|
|
113
|
+
return parse_json_response(response, f"set soft limit for usage limit ID '{limit_id}' in organization", organization=organization)
|
|
112
114
|
|
|
113
115
|
def set_organization_renewal_status(self, organization: str, limit_id: str, renewal_status: str) -> dict:
|
|
114
116
|
"""
|
|
@@ -126,8 +128,8 @@ class UsageLimitClient(BaseClient):
|
|
|
126
128
|
"renewalStatus": renewal_status
|
|
127
129
|
}
|
|
128
130
|
)
|
|
129
|
-
|
|
130
|
-
return
|
|
131
|
+
validate_status_code(response)
|
|
132
|
+
return parse_json_response(response, f"set renewal status for usage limit ID '{limit_id}' in organization", organization=organization)
|
|
131
133
|
|
|
132
134
|
def set_project_usage_limit(self, organization: str, project: str, usage_limit: dict) -> dict:
|
|
133
135
|
"""
|
|
@@ -150,8 +152,8 @@ class UsageLimitClient(BaseClient):
|
|
|
150
152
|
endpoint=endpoint,
|
|
151
153
|
data=usage_limit
|
|
152
154
|
)
|
|
153
|
-
|
|
154
|
-
return
|
|
155
|
+
validate_status_code(response)
|
|
156
|
+
return parse_json_response(response, f"set usage limit for project '{project}' in organization", organization=organization)
|
|
155
157
|
|
|
156
158
|
def get_all_usage_limits_from_project(self, organization: str, project: str) -> dict:
|
|
157
159
|
"""
|
|
@@ -163,8 +165,8 @@ class UsageLimitClient(BaseClient):
|
|
|
163
165
|
"""
|
|
164
166
|
endpoint = GET_ALL_PROJECT_USAGE_LIMIT_V2.format(organization=organization, project=project)
|
|
165
167
|
response = self.api_service.get(endpoint=endpoint)
|
|
166
|
-
|
|
167
|
-
return
|
|
168
|
+
validate_status_code(response)
|
|
169
|
+
return parse_json_response(response, f"get all usage limits for project '{project}' in organization", organization=organization)
|
|
168
170
|
|
|
169
171
|
def get_latest_usage_limit_from_project(self, organization: str, project: str) -> dict:
|
|
170
172
|
"""
|
|
@@ -176,8 +178,8 @@ class UsageLimitClient(BaseClient):
|
|
|
176
178
|
"""
|
|
177
179
|
endpoint = GET_LATEST_PROJECT_USAGE_LIMIT_V2.format(organization=organization, project=project)
|
|
178
180
|
response = self.api_service.get(endpoint=endpoint)
|
|
179
|
-
|
|
180
|
-
return
|
|
181
|
+
validate_status_code(response)
|
|
182
|
+
return parse_json_response(response, f"get latest usage limit for project '{project}' in organization", organization=organization)
|
|
181
183
|
|
|
182
184
|
def get_active_usage_limit_from_project(self, organization: str, project: str) -> dict:
|
|
183
185
|
"""
|
|
@@ -189,8 +191,8 @@ class UsageLimitClient(BaseClient):
|
|
|
189
191
|
"""
|
|
190
192
|
endpoint = GET_PROJECT_ACTIVE_USAGE_LIMIT_V2.format(organization=organization, project=project)
|
|
191
193
|
response = self.api_service.get(endpoint=endpoint)
|
|
192
|
-
|
|
193
|
-
return
|
|
194
|
+
validate_status_code(response)
|
|
195
|
+
return parse_json_response(response, f"get active usage limit for project '{project}' in organization", organization=organization)
|
|
194
196
|
|
|
195
197
|
def delete_usage_limit_from_project(self, organization: str, project: str, limit_id: str) -> dict:
|
|
196
198
|
"""
|
|
@@ -203,8 +205,8 @@ class UsageLimitClient(BaseClient):
|
|
|
203
205
|
"""
|
|
204
206
|
endpoint = DELETE_PROJECT_USAGE_LIMIT_V2.format(organization=organization, project=project, id=limit_id)
|
|
205
207
|
response = self.api_service.delete(endpoint=endpoint)
|
|
206
|
-
|
|
207
|
-
return
|
|
208
|
+
validate_status_code(response)
|
|
209
|
+
return parse_json_response(response, f"delete usage limit with ID '{limit_id}' for project '{project}' in organization", organization=organization)
|
|
208
210
|
|
|
209
211
|
def set_hard_limit_for_active_usage_limit_from_project(
|
|
210
212
|
self,
|
|
@@ -229,8 +231,8 @@ class UsageLimitClient(BaseClient):
|
|
|
229
231
|
"hardLimit": hard_limit
|
|
230
232
|
}
|
|
231
233
|
)
|
|
232
|
-
|
|
233
|
-
return
|
|
234
|
+
validate_status_code(response)
|
|
235
|
+
return parse_json_response(response, f"set hard limit for usage limit ID '{limit_id}' for project '{project}' in organization", organization=organization)
|
|
234
236
|
|
|
235
237
|
def set_soft_limit_for_active_usage_limit_from_project(
|
|
236
238
|
self,
|
|
@@ -255,8 +257,8 @@ class UsageLimitClient(BaseClient):
|
|
|
255
257
|
"softLimit": soft_limit
|
|
256
258
|
}
|
|
257
259
|
)
|
|
258
|
-
|
|
259
|
-
return
|
|
260
|
+
validate_status_code(response)
|
|
261
|
+
return parse_json_response(response, f"set soft limit for usage limit ID '{limit_id}' for project '{project}' in organization", organization=organization)
|
|
260
262
|
|
|
261
263
|
def set_project_renewal_status(self, organization: str, project: str, limit_id: str, renewal_status: str) -> dict:
|
|
262
264
|
"""
|
|
@@ -275,5 +277,5 @@ class UsageLimitClient(BaseClient):
|
|
|
275
277
|
"renewalStatus": renewal_status
|
|
276
278
|
}
|
|
277
279
|
)
|
|
278
|
-
|
|
279
|
-
return
|
|
280
|
+
validate_status_code(response)
|
|
281
|
+
return parse_json_response(response, f"set renewal status for usage limit ID '{limit_id}' for project '{project}' in organization", organization=organization)
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
from pygeai import logger
|
|
1
2
|
from pygeai.core.base.mappers import ErrorMapper, ModelMapper
|
|
2
3
|
from pygeai.core.models import UsageLimit
|
|
3
4
|
from pygeai.organization.limits.clients import UsageLimitClient
|
|
5
|
+
from pygeai.core.handlers import ErrorHandler
|
|
6
|
+
from pygeai.core.common.exceptions import APIError
|
|
7
|
+
import logging
|
|
8
|
+
|
|
9
|
+
|
|
4
10
|
|
|
5
11
|
|
|
6
12
|
class UsageLimitManager:
|
|
@@ -20,7 +26,7 @@ class UsageLimitManager:
|
|
|
20
26
|
self,
|
|
21
27
|
api_key: str = None,
|
|
22
28
|
base_url: str = None,
|
|
23
|
-
alias: str =
|
|
29
|
+
alias: str = None,
|
|
24
30
|
organization_id: str = None
|
|
25
31
|
):
|
|
26
32
|
self.__client = UsageLimitClient(api_key, base_url, alias)
|
|
@@ -30,61 +36,80 @@ class UsageLimitManager:
|
|
|
30
36
|
"""
|
|
31
37
|
Sets a new usage limit for the organization.
|
|
32
38
|
|
|
39
|
+
This method sends a request to the usage limit client to set a new usage limit
|
|
40
|
+
for the specified organization.
|
|
41
|
+
|
|
33
42
|
:param usage_limit: UsageLimit object containing the limit details.
|
|
34
43
|
:return: UsageLimit object with the created usage limit details.
|
|
44
|
+
:raises APIError: If the API returns errors.
|
|
35
45
|
"""
|
|
36
46
|
response_data = self.__client.set_organization_usage_limit(
|
|
37
47
|
organization=self.__organization_id,
|
|
38
48
|
usage_limit=usage_limit.to_dict()
|
|
39
49
|
)
|
|
40
50
|
|
|
41
|
-
if
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
51
|
+
if ErrorHandler.has_errors(response_data):
|
|
52
|
+
error = ErrorHandler.extract_error(response_data)
|
|
53
|
+
logger.error(f"Error received while setting organization usage limit: {error}")
|
|
54
|
+
raise APIError(f"Error received while setting organization usage limit: {error}")
|
|
45
55
|
|
|
56
|
+
result = ModelMapper.map_to_usage_limit(response_data)
|
|
46
57
|
return result
|
|
47
58
|
|
|
48
59
|
def get_latest_usage_limit_from_organization(self) -> UsageLimit:
|
|
49
60
|
"""
|
|
50
61
|
Retrieves the latest usage limit set for the organization.
|
|
51
62
|
|
|
63
|
+
This method queries the usage limit client to fetch the latest usage limit
|
|
64
|
+
for the specified organization.
|
|
65
|
+
|
|
52
66
|
:return: UsageLimit object containing the latest usage limit details.
|
|
67
|
+
:raises APIError: If the API returns errors.
|
|
53
68
|
"""
|
|
54
69
|
response_data = self.__client.get_organization_latest_usage_limit(
|
|
55
70
|
organization=self.__organization_id
|
|
56
71
|
)
|
|
57
72
|
|
|
58
|
-
if
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
73
|
+
if ErrorHandler.has_errors(response_data):
|
|
74
|
+
error = ErrorHandler.extract_error(response_data)
|
|
75
|
+
logger.error(f"Error received while retrieving latest organization usage limit: {error}")
|
|
76
|
+
raise APIError(f"Error received while retrieving latest organization usage limit: {error}")
|
|
62
77
|
|
|
78
|
+
result = ModelMapper.map_to_usage_limit(response_data)
|
|
63
79
|
return result
|
|
64
80
|
|
|
65
81
|
def get_all_usage_limits_from_organization(self) -> list[UsageLimit]:
|
|
66
82
|
"""
|
|
67
83
|
Retrieves all usage limits associated with the organization.
|
|
68
84
|
|
|
69
|
-
|
|
85
|
+
This method queries the usage limit client to fetch all usage limits
|
|
86
|
+
for the specified organization.
|
|
87
|
+
|
|
88
|
+
:return: list[UsageLimit] - A list of UsageLimit objects containing all usage limits for the organization.
|
|
89
|
+
:raises APIError: If the API returns errors.
|
|
70
90
|
"""
|
|
71
91
|
response_data = self.__client.get_all_usage_limits_from_organization(
|
|
72
92
|
organization=self.__organization_id
|
|
73
93
|
)
|
|
74
|
-
|
|
75
|
-
if "errors" in response_data:
|
|
76
|
-
result = ErrorMapper.map_to_error_list_response(response_data)
|
|
77
|
-
else:
|
|
78
|
-
result = ModelMapper.map_to_usage_limit_list(response_data)
|
|
79
94
|
|
|
95
|
+
if ErrorHandler.has_errors(response_data):
|
|
96
|
+
error = ErrorHandler.extract_error(response_data)
|
|
97
|
+
logger.error(f"Error received while retrieving all organization usage limits: {error}")
|
|
98
|
+
raise APIError(f"Error received while retrieving all organization usage limits: {error}")
|
|
99
|
+
|
|
100
|
+
result = ModelMapper.map_to_usage_limit_list(response_data)
|
|
80
101
|
return result
|
|
81
102
|
|
|
82
103
|
def update_organization_usage_limit(self, usage_limit: UsageLimit) -> UsageLimit:
|
|
83
104
|
"""
|
|
84
105
|
Updates the usage limits for an organization, including hard limit, soft limit, and renewal status.
|
|
85
106
|
|
|
107
|
+
This method sends requests to the usage limit client to update specific attributes
|
|
108
|
+
of the usage limit for the specified organization.
|
|
109
|
+
|
|
86
110
|
:param usage_limit: UsageLimit object containing the updated limit values.
|
|
87
111
|
:return: UsageLimit object with updated usage limit details.
|
|
112
|
+
:raises APIError: If the API returns errors.
|
|
88
113
|
"""
|
|
89
114
|
response_data = {}
|
|
90
115
|
if usage_limit.hard_limit:
|
|
@@ -106,39 +131,49 @@ class UsageLimitManager:
|
|
|
106
131
|
renewal_status=usage_limit.renewal_status
|
|
107
132
|
)
|
|
108
133
|
|
|
109
|
-
if
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
134
|
+
if ErrorHandler.has_errors(response_data):
|
|
135
|
+
error = ErrorHandler.extract_error(response_data)
|
|
136
|
+
logger.error(f"Error received while updating organization usage limit: {error}")
|
|
137
|
+
raise APIError(f"Error received while updating organization usage limit: {error}")
|
|
113
138
|
|
|
139
|
+
result = ModelMapper.map_to_usage_limit(response_data)
|
|
114
140
|
return result
|
|
115
141
|
|
|
116
142
|
def delete_usage_limit_from_organization(self, limit_id: str) -> UsageLimit:
|
|
117
143
|
"""
|
|
118
144
|
Deletes a usage limit from the organization.
|
|
119
145
|
|
|
146
|
+
This method sends a request to the usage limit client to delete a usage limit
|
|
147
|
+
identified by `limit_id` for the specified organization.
|
|
148
|
+
|
|
120
149
|
:param limit_id: The ID of the usage limit to be deleted.
|
|
121
150
|
:return: UsageLimit object representing the deleted limit details.
|
|
151
|
+
:raises APIError: If the API returns errors.
|
|
122
152
|
"""
|
|
123
153
|
response_data = self.__client.delete_usage_limit_from_organization(
|
|
124
154
|
organization=self.__organization_id,
|
|
125
155
|
limit_id=limit_id,
|
|
126
156
|
)
|
|
127
157
|
|
|
128
|
-
if
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
158
|
+
if ErrorHandler.has_errors(response_data):
|
|
159
|
+
error = ErrorHandler.extract_error(response_data)
|
|
160
|
+
logger.error(f"Error received while deleting organization usage limit: {error}")
|
|
161
|
+
raise APIError(f"Error received while deleting organization usage limit: {error}")
|
|
132
162
|
|
|
163
|
+
result = ModelMapper.map_to_usage_limit(response_data)
|
|
133
164
|
return result
|
|
134
165
|
|
|
135
166
|
def set_project_usage_limit(self, project_id: str, usage_limit: UsageLimit) -> UsageLimit:
|
|
136
167
|
"""
|
|
137
168
|
Sets a new usage limit for a specific project within the organization.
|
|
138
169
|
|
|
170
|
+
This method sends a request to the usage limit client to set a new usage limit
|
|
171
|
+
for the specified project.
|
|
172
|
+
|
|
139
173
|
:param project_id: The unique identifier of the project.
|
|
140
174
|
:param usage_limit: UsageLimit object containing the limit details.
|
|
141
175
|
:return: UsageLimit object with the created project usage limit details.
|
|
176
|
+
:raises APIError: If the API returns errors.
|
|
142
177
|
"""
|
|
143
178
|
response_data = self.__client.set_project_usage_limit(
|
|
144
179
|
organization=self.__organization_id,
|
|
@@ -146,77 +181,97 @@ class UsageLimitManager:
|
|
|
146
181
|
usage_limit=usage_limit.to_dict()
|
|
147
182
|
)
|
|
148
183
|
|
|
149
|
-
if
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
184
|
+
if ErrorHandler.has_errors(response_data):
|
|
185
|
+
error = ErrorHandler.extract_error(response_data)
|
|
186
|
+
logger.error(f"Error received while setting project usage limit: {error}")
|
|
187
|
+
raise APIError(f"Error received while setting project usage limit: {error}")
|
|
153
188
|
|
|
189
|
+
result = ModelMapper.map_to_usage_limit(response_data)
|
|
154
190
|
return result
|
|
155
191
|
|
|
156
192
|
def get_all_usage_limits_from_project(self, project_id: str) -> UsageLimit:
|
|
157
193
|
"""
|
|
158
194
|
Retrieves all usage limits associated with a specific project.
|
|
159
195
|
|
|
196
|
+
This method queries the usage limit client to fetch all usage limits
|
|
197
|
+
for the specified project.
|
|
198
|
+
|
|
160
199
|
:param project_id: The unique identifier of the project.
|
|
161
200
|
:return: UsageLimit object containing all usage limits for the project.
|
|
201
|
+
:raises APIError: If the API returns errors.
|
|
162
202
|
"""
|
|
163
203
|
response_data = self.__client.get_all_usage_limits_from_project(
|
|
164
204
|
organization=self.__organization_id,
|
|
165
205
|
project=project_id,
|
|
166
206
|
)
|
|
167
207
|
|
|
168
|
-
if
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
208
|
+
if ErrorHandler.has_errors(response_data):
|
|
209
|
+
error = ErrorHandler.extract_error(response_data)
|
|
210
|
+
logger.error(f"Error received while retrieving all project usage limits: {error}")
|
|
211
|
+
raise APIError(f"Error received while retrieving all project usage limits: {error}")
|
|
172
212
|
|
|
213
|
+
result = ModelMapper.map_to_usage_limit(response_data)
|
|
173
214
|
return result
|
|
174
215
|
|
|
175
216
|
def get_latest_usage_limit_from_project(self, project_id: str) -> UsageLimit:
|
|
176
217
|
"""
|
|
177
218
|
Retrieves the latest usage limit set for a specific project.
|
|
178
219
|
|
|
220
|
+
This method queries the usage limit client to fetch the latest usage limit
|
|
221
|
+
for the specified project.
|
|
222
|
+
|
|
179
223
|
:param project_id: The unique identifier of the project.
|
|
180
224
|
:return: UsageLimit object containing the latest usage limit details.
|
|
225
|
+
:raises APIError: If the API returns errors.
|
|
181
226
|
"""
|
|
182
227
|
response_data = self.__client.get_latest_usage_limit_from_project(
|
|
183
228
|
organization=self.__organization_id,
|
|
184
229
|
project=project_id,
|
|
185
230
|
)
|
|
186
231
|
|
|
187
|
-
if
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
232
|
+
if ErrorHandler.has_errors(response_data):
|
|
233
|
+
error = ErrorHandler.extract_error(response_data)
|
|
234
|
+
logger.error(f"Error received while retrieving latest project usage limit: {error}")
|
|
235
|
+
raise APIError(f"Error received while retrieving latest project usage limit: {error}")
|
|
191
236
|
|
|
237
|
+
result = ModelMapper.map_to_usage_limit(response_data)
|
|
192
238
|
return result
|
|
193
239
|
|
|
194
240
|
def get_active_usage_limit_from_project(self, project_id: str) -> UsageLimit:
|
|
195
241
|
"""
|
|
196
242
|
Retrieves the currently active usage limit for a specific project.
|
|
197
243
|
|
|
244
|
+
This method queries the usage limit client to fetch the active usage limit
|
|
245
|
+
for the specified project.
|
|
246
|
+
|
|
198
247
|
:param project_id: The unique identifier of the project.
|
|
199
248
|
:return: UsageLimit object containing the active usage limit details.
|
|
249
|
+
:raises APIError: If the API returns errors.
|
|
200
250
|
"""
|
|
201
251
|
response_data = self.__client.get_active_usage_limit_from_project(
|
|
202
252
|
organization=self.__organization_id,
|
|
203
253
|
project=project_id,
|
|
204
254
|
)
|
|
205
255
|
|
|
206
|
-
if
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
256
|
+
if ErrorHandler.has_errors(response_data):
|
|
257
|
+
error = ErrorHandler.extract_error(response_data)
|
|
258
|
+
logger.error(f"Error received while retrieving active project usage limit: {error}")
|
|
259
|
+
raise APIError(f"Error received while retrieving active project usage limit: {error}")
|
|
210
260
|
|
|
261
|
+
result = ModelMapper.map_to_usage_limit(response_data)
|
|
211
262
|
return result
|
|
212
263
|
|
|
213
264
|
def delete_usage_limit_from_project(self, project_id: str, usage_limit: UsageLimit) -> UsageLimit:
|
|
214
265
|
"""
|
|
215
266
|
Deletes a specified usage limit from a project.
|
|
216
267
|
|
|
268
|
+
This method sends a request to the usage limit client to delete a usage limit
|
|
269
|
+
identified by `usage_limit.id` for the specified project.
|
|
270
|
+
|
|
217
271
|
:param project_id: The unique identifier of the project.
|
|
218
272
|
:param usage_limit: The UsageLimit object representing the limit to be deleted.
|
|
219
273
|
:return: UsageLimit object representing the deleted usage limit details.
|
|
274
|
+
:raises APIError: If the API returns errors.
|
|
220
275
|
"""
|
|
221
276
|
response_data = self.__client.delete_usage_limit_from_project(
|
|
222
277
|
organization=self.__organization_id,
|
|
@@ -224,20 +279,25 @@ class UsageLimitManager:
|
|
|
224
279
|
limit_id=usage_limit.id
|
|
225
280
|
)
|
|
226
281
|
|
|
227
|
-
if
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
282
|
+
if ErrorHandler.has_errors(response_data):
|
|
283
|
+
error = ErrorHandler.extract_error(response_data)
|
|
284
|
+
logger.error(f"Error received while deleting project usage limit: {error}")
|
|
285
|
+
raise APIError(f"Error received while deleting project usage limit: {error}")
|
|
231
286
|
|
|
287
|
+
result = ModelMapper.map_to_usage_limit(response_data)
|
|
232
288
|
return result
|
|
233
289
|
|
|
234
290
|
def update_project_usage_limit(self, project_id: str, usage_limit: UsageLimit) -> UsageLimit:
|
|
235
291
|
"""
|
|
236
292
|
Updates the usage limits for a specific project, including hard limit, soft limit, and renewal status.
|
|
237
293
|
|
|
294
|
+
This method sends requests to the usage limit client to update specific attributes
|
|
295
|
+
of the usage limit for the specified project.
|
|
296
|
+
|
|
238
297
|
:param project_id: The unique identifier of the project.
|
|
239
298
|
:param usage_limit: UsageLimit object containing the updated limit values.
|
|
240
299
|
:return: UsageLimit object with updated usage limit details.
|
|
300
|
+
:raises APIError: If the API returns errors.
|
|
241
301
|
"""
|
|
242
302
|
response_data = {}
|
|
243
303
|
if usage_limit.hard_limit:
|
|
@@ -262,11 +322,10 @@ class UsageLimitManager:
|
|
|
262
322
|
renewal_status=usage_limit.renewal_status
|
|
263
323
|
)
|
|
264
324
|
|
|
265
|
-
if
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
325
|
+
if ErrorHandler.has_errors(response_data):
|
|
326
|
+
error = ErrorHandler.extract_error(response_data)
|
|
327
|
+
logger.error(f"Error received while updating project usage limit: {error}")
|
|
328
|
+
raise APIError(f"Error received while updating project usage limit: {error}")
|
|
269
329
|
|
|
330
|
+
result = ModelMapper.map_to_usage_limit(response_data)
|
|
270
331
|
return result
|
|
271
|
-
|
|
272
|
-
|