pygeai 0.1.6__py3-none-any.whl → 0.6.0b15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pygeai might be problematic. Click here for more details.
- pygeai/__init__.py +11 -2
- pygeai/_docs/Makefile +20 -0
- pygeai/_docs/make.bat +35 -0
- pygeai/_docs/source/conf.py +117 -0
- pygeai/_docs/source/content/ai_lab/cli.rst +747 -0
- pygeai/_docs/source/content/ai_lab/models.rst +1734 -0
- pygeai/_docs/source/content/ai_lab/runner.rst +253 -0
- pygeai/_docs/source/content/ai_lab/spec.rst +431 -0
- pygeai/_docs/source/content/ai_lab/usage.rst +1011 -0
- pygeai/_docs/source/content/ai_lab.rst +102 -0
- pygeai/_docs/source/content/analytics.rst +598 -0
- pygeai/_docs/source/content/api_reference/admin.rst +161 -0
- pygeai/_docs/source/content/api_reference/assistant.rst +326 -0
- pygeai/_docs/source/content/api_reference/auth.rst +379 -0
- pygeai/_docs/source/content/api_reference/chat.rst +754 -0
- pygeai/_docs/source/content/api_reference/embeddings.rst +154 -0
- pygeai/_docs/source/content/api_reference/evaluation.rst +590 -0
- pygeai/_docs/source/content/api_reference/feedback.rst +237 -0
- pygeai/_docs/source/content/api_reference/files.rst +592 -0
- pygeai/_docs/source/content/api_reference/gam.rst +401 -0
- pygeai/_docs/source/content/api_reference/health.rst +58 -0
- pygeai/_docs/source/content/api_reference/project.rst +738 -0
- pygeai/_docs/source/content/api_reference/proxy.rst +318 -0
- pygeai/_docs/source/content/api_reference/rag.rst +710 -0
- pygeai/_docs/source/content/api_reference/rerank.rst +94 -0
- pygeai/_docs/source/content/api_reference/secrets.rst +495 -0
- pygeai/_docs/source/content/api_reference/usage_limits.rst +390 -0
- pygeai/_docs/source/content/api_reference.rst +58 -0
- pygeai/_docs/source/content/authentication.rst +295 -0
- pygeai/_docs/source/content/chat_gui.rst +121 -0
- pygeai/_docs/source/content/cli.rst +203 -0
- pygeai/_docs/source/content/debugger.rst +651 -0
- pygeai/_docs/source/content/intro.rst +67 -0
- pygeai/_docs/source/content/migration.rst +929 -0
- pygeai/_docs/source/content/modules.rst +7 -0
- pygeai/_docs/source/content/quickstart.rst +143 -0
- pygeai/_docs/source/content/samples.rst +394 -0
- pygeai/_docs/source/index.rst +75 -0
- pygeai/_docs/source/modules.rst +7 -0
- pygeai/_docs/source/pygeai.admin.rst +29 -0
- pygeai/_docs/source/pygeai.analytics.rst +53 -0
- pygeai/_docs/source/pygeai.assistant.data.rst +21 -0
- pygeai/_docs/source/pygeai.assistant.data_analyst.rst +29 -0
- pygeai/_docs/source/pygeai.assistant.rag.rst +53 -0
- pygeai/_docs/source/pygeai.assistant.rst +55 -0
- pygeai/_docs/source/pygeai.auth.rst +29 -0
- pygeai/_docs/source/pygeai.chat.rst +69 -0
- pygeai/_docs/source/pygeai.cli.commands.flows.rst +10 -0
- pygeai/_docs/source/pygeai.cli.commands.lab.rst +53 -0
- pygeai/_docs/source/pygeai.cli.commands.rst +222 -0
- pygeai/_docs/source/pygeai.cli.rst +62 -0
- pygeai/_docs/source/pygeai.cli.texts.rst +21 -0
- pygeai/_docs/source/pygeai.core.base.rst +53 -0
- pygeai/_docs/source/pygeai.core.common.rst +37 -0
- pygeai/_docs/source/pygeai.core.embeddings.rst +61 -0
- pygeai/_docs/source/pygeai.core.feedback.rst +37 -0
- pygeai/_docs/source/pygeai.core.files.rst +61 -0
- pygeai/_docs/source/pygeai.core.llm.rst +29 -0
- pygeai/_docs/source/pygeai.core.plugins.rst +37 -0
- pygeai/_docs/source/pygeai.core.rerank.rst +53 -0
- pygeai/_docs/source/pygeai.core.rst +63 -0
- pygeai/_docs/source/pygeai.core.secrets.rst +29 -0
- pygeai/_docs/source/pygeai.core.services.llm.rst +29 -0
- pygeai/_docs/source/pygeai.core.services.rst +37 -0
- pygeai/_docs/source/pygeai.core.utils.rst +37 -0
- pygeai/_docs/source/pygeai.dbg.rst +21 -0
- pygeai/_docs/source/pygeai.evaluation.dataset.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.plan.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.result.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.rst +31 -0
- pygeai/_docs/source/pygeai.flows.rst +29 -0
- pygeai/_docs/source/pygeai.gam.rst +29 -0
- pygeai/_docs/source/pygeai.health.rst +29 -0
- pygeai/_docs/source/pygeai.lab.agents.rst +37 -0
- pygeai/_docs/source/pygeai.lab.processes.rst +37 -0
- pygeai/_docs/source/pygeai.lab.rst +65 -0
- pygeai/_docs/source/pygeai.lab.spec.rst +29 -0
- pygeai/_docs/source/pygeai.lab.strategies.rst +37 -0
- pygeai/_docs/source/pygeai.lab.tools.rst +37 -0
- pygeai/_docs/source/pygeai.man.man1.rst +10 -0
- pygeai/_docs/source/pygeai.man.rst +18 -0
- pygeai/_docs/source/pygeai.migration.rst +29 -0
- pygeai/_docs/source/pygeai.organization.limits.rst +45 -0
- pygeai/_docs/source/pygeai.organization.rst +61 -0
- pygeai/_docs/source/pygeai.proxy.rst +53 -0
- pygeai/_docs/source/pygeai.rst +35 -0
- pygeai/_docs/source/pygeai.tests.admin.rst +21 -0
- pygeai/_docs/source/pygeai.tests.analytics.rst +45 -0
- pygeai/_docs/source/pygeai.tests.assistants.rag.rst +37 -0
- pygeai/_docs/source/pygeai.tests.assistants.rst +45 -0
- pygeai/_docs/source/pygeai.tests.auth.rst +29 -0
- pygeai/_docs/source/pygeai.tests.chat.rst +45 -0
- pygeai/_docs/source/pygeai.tests.cli.commands.lab.rst +37 -0
- pygeai/_docs/source/pygeai.tests.cli.commands.rst +165 -0
- pygeai/_docs/source/pygeai.tests.cli.docker.rst +10 -0
- pygeai/_docs/source/pygeai.tests.cli.rst +46 -0
- pygeai/_docs/source/pygeai.tests.core.base.data.rst +29 -0
- pygeai/_docs/source/pygeai.tests.core.base.rst +45 -0
- pygeai/_docs/source/pygeai.tests.core.common.data.rst +10 -0
- pygeai/_docs/source/pygeai.tests.core.common.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.embeddings.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.feedback.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.files.rst +53 -0
- pygeai/_docs/source/pygeai.tests.core.llm.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.plugins.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.rerank.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.rst +39 -0
- pygeai/_docs/source/pygeai.tests.core.secrets.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.services.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.utils.rst +21 -0
- pygeai/_docs/source/pygeai.tests.dbg.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.dataset.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.plan.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.result.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.rst +20 -0
- pygeai/_docs/source/pygeai.tests.gam.rst +21 -0
- pygeai/_docs/source/pygeai.tests.health.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.assistants.rag.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.assistants.rst +18 -0
- pygeai/_docs/source/pygeai.tests.integration.chat.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.agents.rst +69 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.processes.rst +77 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.reasoning_strategies.rst +37 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.tools.rst +77 -0
- pygeai/_docs/source/pygeai.tests.integration.rst +20 -0
- pygeai/_docs/source/pygeai.tests.lab.agents.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.processes.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.rst +49 -0
- pygeai/_docs/source/pygeai.tests.lab.spec.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.strategies.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.tools.rst +29 -0
- pygeai/_docs/source/pygeai.tests.migration.rst +29 -0
- pygeai/_docs/source/pygeai.tests.organization.limits.rst +29 -0
- pygeai/_docs/source/pygeai.tests.organization.rst +53 -0
- pygeai/_docs/source/pygeai.tests.proxy.rst +61 -0
- pygeai/_docs/source/pygeai.tests.rst +33 -0
- pygeai/admin/clients.py +14 -11
- pygeai/admin/endpoints.py +2 -2
- pygeai/analytics/clients.py +505 -0
- pygeai/analytics/endpoints.py +35 -0
- pygeai/analytics/managers.py +606 -0
- pygeai/analytics/mappers.py +207 -0
- pygeai/analytics/responses.py +240 -0
- pygeai/assistant/clients.py +48 -57
- pygeai/assistant/data/__init__.py +0 -0
- pygeai/assistant/data/clients.py +15 -0
- pygeai/assistant/data_analyst/__init__.py +0 -0
- pygeai/assistant/data_analyst/clients.py +75 -0
- pygeai/assistant/data_analyst/endpoints.py +2 -0
- pygeai/assistant/endpoints.py +0 -2
- pygeai/assistant/managers.py +738 -0
- pygeai/assistant/mappers.py +153 -0
- pygeai/assistant/rag/clients.py +132 -21
- pygeai/assistant/rag/mappers.py +228 -0
- pygeai/assistant/rag/models.py +396 -0
- pygeai/assistant/rag/responses.py +10 -0
- pygeai/auth/__init__.py +0 -0
- pygeai/auth/clients.py +129 -0
- pygeai/auth/endpoints.py +6 -0
- pygeai/chat/clients.py +406 -31
- pygeai/chat/endpoints.py +3 -0
- pygeai/chat/iris.py +17 -0
- pygeai/chat/managers.py +64 -0
- pygeai/chat/session.py +38 -0
- pygeai/chat/settings.py +6 -0
- pygeai/chat/ui.py +678 -0
- pygeai/cli/__init__.py +0 -1
- pygeai/cli/commands/admin.py +9 -12
- pygeai/cli/commands/analytics.py +533 -0
- pygeai/cli/commands/assistant.py +11 -11
- pygeai/cli/commands/auth.py +299 -0
- pygeai/cli/commands/base.py +201 -7
- pygeai/cli/commands/chat.py +875 -14
- pygeai/cli/commands/common.py +30 -26
- pygeai/cli/commands/configuration.py +84 -9
- pygeai/cli/commands/docs.py +105 -0
- pygeai/cli/commands/embeddings.py +187 -0
- pygeai/cli/commands/evaluation.py +2069 -0
- pygeai/cli/commands/feedback.py +93 -0
- pygeai/cli/commands/files.py +312 -0
- pygeai/cli/commands/flows/__init__.py +0 -0
- pygeai/cli/commands/gam.py +349 -0
- pygeai/cli/commands/lab/__init__.py +0 -0
- pygeai/cli/commands/lab/ai_lab.py +4110 -0
- pygeai/cli/commands/lab/common.py +135 -0
- pygeai/cli/commands/lab/options.py +8 -0
- pygeai/cli/commands/lab/spec.py +273 -0
- pygeai/cli/commands/lab/utils.py +13 -0
- pygeai/cli/commands/llm.py +164 -0
- pygeai/cli/commands/migrate.py +1198 -0
- pygeai/cli/commands/options.py +86 -0
- pygeai/cli/commands/organization.py +560 -98
- pygeai/cli/commands/rag.py +306 -10
- pygeai/cli/commands/rerank.py +108 -0
- pygeai/cli/commands/secrets.py +357 -0
- pygeai/cli/commands/usage_limits.py +583 -0
- pygeai/cli/commands/validators.py +209 -0
- pygeai/cli/commands/version.py +44 -0
- pygeai/cli/error_handler.py +151 -0
- pygeai/cli/geai.py +171 -30
- pygeai/cli/geai_proxy.py +318 -0
- pygeai/cli/install_man.py +107 -0
- pygeai/cli/parsers.py +78 -25
- pygeai/cli/texts/help.py +712 -55
- pygeai/core/__init__.py +9 -1
- pygeai/core/base/clients.py +61 -10
- pygeai/core/base/mappers.py +208 -30
- pygeai/core/base/models.py +8 -308
- pygeai/core/base/responses.py +18 -1
- pygeai/core/base/session.py +110 -17
- pygeai/core/common/config.py +98 -16
- pygeai/core/common/decorators.py +44 -0
- pygeai/core/common/exceptions.py +104 -4
- pygeai/core/embeddings/__init__.py +19 -0
- pygeai/core/embeddings/clients.py +93 -0
- pygeai/core/embeddings/endpoints.py +1 -0
- pygeai/core/embeddings/managers.py +62 -0
- pygeai/core/embeddings/mappers.py +52 -0
- pygeai/core/embeddings/models.py +14 -0
- pygeai/core/embeddings/responses.py +31 -0
- pygeai/core/feedback/__init__.py +0 -0
- pygeai/core/feedback/clients.py +50 -0
- pygeai/core/feedback/endpoints.py +1 -0
- pygeai/core/feedback/models.py +10 -0
- pygeai/core/files/__init__.py +0 -0
- pygeai/core/files/clients.py +156 -0
- pygeai/core/files/endpoints.py +5 -0
- pygeai/core/files/managers.py +224 -0
- pygeai/core/files/mappers.py +44 -0
- pygeai/core/files/models.py +24 -0
- pygeai/core/files/responses.py +19 -0
- pygeai/core/handlers.py +32 -0
- pygeai/core/llm/__init__.py +0 -0
- pygeai/core/llm/clients.py +53 -0
- pygeai/core/llm/endpoints.py +4 -0
- pygeai/core/models.py +799 -0
- pygeai/core/plugins/__init__.py +0 -0
- pygeai/core/plugins/clients.py +32 -0
- pygeai/core/plugins/endpoints.py +1 -0
- pygeai/core/plugins/models.py +86 -0
- pygeai/core/rerank/__init__.py +0 -0
- pygeai/core/rerank/clients.py +35 -0
- pygeai/core/rerank/endpoints.py +1 -0
- pygeai/core/rerank/managers.py +47 -0
- pygeai/core/rerank/mappers.py +23 -0
- pygeai/core/rerank/models.py +27 -0
- pygeai/core/responses.py +104 -0
- pygeai/core/secrets/__init__.py +0 -0
- pygeai/core/secrets/clients.py +212 -0
- pygeai/core/secrets/endpoints.py +7 -0
- pygeai/core/services/llm/__init__.py +0 -0
- pygeai/core/services/llm/model.py +186 -0
- pygeai/core/services/llm/providers.py +15 -0
- pygeai/core/services/response.py +18 -0
- pygeai/core/services/rest.py +311 -89
- pygeai/core/utils/__init__.py +0 -0
- pygeai/core/utils/console.py +83 -0
- pygeai/core/utils/parsers.py +32 -0
- pygeai/core/utils/validators.py +10 -0
- pygeai/dbg/__init__.py +3 -0
- pygeai/dbg/debugger.py +870 -0
- pygeai/evaluation/__init__.py +0 -0
- pygeai/evaluation/clients.py +19 -0
- pygeai/evaluation/dataset/__init__.py +0 -0
- pygeai/evaluation/dataset/clients.py +514 -0
- pygeai/evaluation/dataset/endpoints.py +26 -0
- pygeai/evaluation/plan/__init__.py +0 -0
- pygeai/evaluation/plan/clients.py +302 -0
- pygeai/evaluation/plan/endpoints.py +16 -0
- pygeai/evaluation/result/__init__.py +0 -0
- pygeai/evaluation/result/clients.py +70 -0
- pygeai/evaluation/result/endpoints.py +2 -0
- pygeai/flows/__init__.py +0 -0
- pygeai/flows/endpoints.py +362 -0
- pygeai/flows/models.py +1304 -0
- pygeai/gam/__init__.py +0 -0
- pygeai/gam/clients.py +178 -0
- pygeai/gam/endpoints.py +4 -0
- pygeai/health/__init__.py +0 -0
- pygeai/health/clients.py +24 -0
- pygeai/health/endpoints.py +1 -0
- pygeai/lab/__init__.py +0 -0
- pygeai/lab/agents/__init__.py +0 -0
- pygeai/lab/agents/clients.py +426 -0
- pygeai/lab/agents/endpoints.py +12 -0
- pygeai/lab/agents/mappers.py +319 -0
- pygeai/lab/clients.py +24 -0
- pygeai/lab/constants.py +3 -0
- pygeai/lab/managers.py +1558 -0
- pygeai/lab/models.py +1719 -0
- pygeai/lab/processes/__init__.py +0 -0
- pygeai/lab/processes/clients.py +1051 -0
- pygeai/lab/processes/endpoints.py +26 -0
- pygeai/lab/processes/mappers.py +395 -0
- pygeai/lab/runners.py +90 -0
- pygeai/lab/spec/__init__.py +0 -0
- pygeai/lab/spec/loader.py +24 -0
- pygeai/lab/spec/parsers.py +39 -0
- pygeai/lab/strategies/__init__.py +0 -0
- pygeai/lab/strategies/clients.py +212 -0
- pygeai/lab/strategies/endpoints.py +5 -0
- pygeai/lab/strategies/mappers.py +58 -0
- pygeai/lab/tools/__init__.py +0 -0
- pygeai/lab/tools/clients.py +465 -0
- pygeai/lab/tools/endpoints.py +13 -0
- pygeai/lab/tools/mappers.py +131 -0
- pygeai/man/__init__.py +1 -0
- pygeai/man/man1/__init__.py +1 -0
- pygeai/man/man1/geai-proxy.1 +246 -0
- pygeai/man/man1/geai.1 +2615 -0
- pygeai/migration/__init__.py +33 -0
- pygeai/migration/strategies.py +603 -0
- pygeai/migration/tools.py +180 -0
- pygeai/organization/clients.py +246 -18
- pygeai/organization/endpoints.py +17 -8
- pygeai/organization/limits/__init__.py +0 -0
- pygeai/organization/limits/clients.py +281 -0
- pygeai/organization/limits/endpoints.py +15 -0
- pygeai/organization/limits/managers.py +331 -0
- pygeai/organization/limits/mappers.py +21 -0
- pygeai/organization/managers.py +537 -0
- pygeai/organization/mappers.py +111 -46
- pygeai/organization/responses.py +61 -11
- pygeai/proxy/__init__.py +0 -0
- pygeai/proxy/clients.py +216 -0
- pygeai/proxy/config.py +128 -0
- pygeai/proxy/managers.py +232 -0
- pygeai/proxy/servers.py +304 -0
- pygeai/proxy/tool.py +69 -0
- pygeai/tests/admin/__init__.py +0 -0
- pygeai/tests/admin/test_clients.py +148 -0
- pygeai/tests/analytics/__init__.py +0 -0
- pygeai/tests/analytics/test_clients.py +86 -0
- pygeai/tests/analytics/test_managers.py +94 -0
- pygeai/tests/analytics/test_mappers.py +84 -0
- pygeai/tests/analytics/test_responses.py +73 -0
- pygeai/tests/assistants/rag/__init__.py +0 -0
- pygeai/tests/assistants/rag/test_clients.py +346 -0
- pygeai/tests/assistants/rag/test_mappers.py +189 -0
- pygeai/tests/assistants/rag/test_models.py +292 -0
- pygeai/tests/assistants/test_clients.py +176 -80
- pygeai/tests/assistants/test_managers.py +198 -0
- pygeai/tests/assistants/test_mappers.py +111 -0
- pygeai/tests/auth/__init__.py +0 -0
- pygeai/tests/auth/test_clients.py +289 -0
- pygeai/tests/auth/test_oauth.py +172 -0
- pygeai/tests/auth/test_session_logging.py +150 -0
- pygeai/tests/chat/__init__.py +0 -0
- pygeai/tests/chat/test_clients.py +393 -0
- pygeai/tests/chat/test_iris.py +38 -0
- pygeai/tests/chat/test_session.py +62 -0
- pygeai/tests/chat/test_ui.py +224 -0
- pygeai/tests/cli/__init__.py +0 -0
- pygeai/tests/cli/commands/__init__.py +0 -0
- pygeai/tests/cli/commands/lab/__init__.py +0 -0
- pygeai/tests/cli/commands/lab/test_ai_lab.py +786 -0
- pygeai/tests/cli/commands/lab/test_common.py +208 -0
- pygeai/tests/cli/commands/lab/test_spec.py +246 -0
- pygeai/tests/cli/commands/test_assistant.py +202 -0
- pygeai/tests/cli/commands/test_chat.py +130 -0
- pygeai/tests/cli/commands/test_common.py +350 -0
- pygeai/tests/cli/commands/test_embeddings.py +132 -0
- pygeai/tests/cli/commands/test_evaluation.py +656 -0
- pygeai/tests/cli/commands/test_feedback.py +65 -0
- pygeai/tests/cli/commands/test_files.py +161 -0
- pygeai/tests/cli/commands/test_gam.py +201 -0
- pygeai/tests/cli/commands/test_llm.py +114 -0
- pygeai/tests/cli/commands/test_migrate.py +176 -0
- pygeai/tests/cli/commands/test_organization.py +276 -0
- pygeai/tests/cli/commands/test_rag.py +266 -0
- pygeai/tests/cli/commands/test_rerank.py +110 -0
- pygeai/tests/cli/commands/test_secrets.py +171 -0
- pygeai/tests/cli/commands/test_show_help.py +41 -0
- pygeai/tests/cli/commands/test_usage_limits.py +412 -0
- pygeai/tests/cli/commands/test_validators.py +160 -0
- pygeai/tests/cli/commands/test_version.py +81 -0
- pygeai/tests/cli/docker/__init__.py +0 -0
- pygeai/tests/cli/test_credentials_flag.py +316 -0
- pygeai/tests/cli/test_error_handler.py +225 -0
- pygeai/tests/cli/test_geai_driver.py +154 -0
- pygeai/tests/cli/test_parsers.py +154 -0
- pygeai/tests/core/base/__init__.py +0 -0
- pygeai/tests/core/base/data/__init__.py +0 -0
- pygeai/tests/core/base/data/mappers.py +117 -0
- pygeai/tests/core/base/data/models.py +312 -0
- pygeai/tests/core/base/test_mappers.py +569 -0
- pygeai/tests/core/base/test_models.py +261 -0
- pygeai/tests/core/base/test_responses.py +53 -0
- pygeai/tests/core/common/__init__.py +0 -0
- pygeai/tests/core/common/data/__init__.py +0 -0
- pygeai/tests/core/common/test_config.py +186 -0
- pygeai/tests/core/common/test_decorators.py +69 -0
- pygeai/tests/core/embeddings/__init__.py +0 -0
- pygeai/tests/core/embeddings/test_clients.py +225 -0
- pygeai/tests/core/embeddings/test_managers.py +171 -0
- pygeai/tests/core/embeddings/test_mappers.py +142 -0
- pygeai/tests/core/feedback/__init__.py +0 -0
- pygeai/tests/core/feedback/test_clients.py +64 -0
- pygeai/tests/core/files/__init__.py +0 -0
- pygeai/tests/core/files/test_clients.py +128 -0
- pygeai/tests/core/files/test_managers.py +219 -0
- pygeai/tests/core/files/test_mappers.py +137 -0
- pygeai/tests/core/files/test_models.py +103 -0
- pygeai/tests/core/files/test_responses.py +122 -0
- pygeai/tests/core/llm/__init__.py +0 -0
- pygeai/tests/core/llm/test_clients.py +142 -0
- pygeai/tests/core/plugins/__init__.py +0 -0
- pygeai/tests/core/plugins/test_clients.py +66 -0
- pygeai/tests/core/rerank/__init__.py +0 -0
- pygeai/tests/core/rerank/test_clients.py +76 -0
- pygeai/tests/core/rerank/test_managers.py +99 -0
- pygeai/tests/core/rerank/test_mappers.py +54 -0
- pygeai/tests/core/secrets/__init__.py +0 -0
- pygeai/tests/core/secrets/test_clients.py +264 -0
- pygeai/tests/core/services/__init__.py +0 -0
- pygeai/tests/core/services/test_rest.py +273 -0
- pygeai/tests/core/test_handlers.py +66 -0
- pygeai/tests/core/utils/__init__.py +0 -0
- pygeai/tests/core/utils/test_console.py +80 -0
- pygeai/tests/dbg/__init__.py +0 -0
- pygeai/tests/dbg/test_debugger.py +591 -0
- pygeai/tests/evaluation/__init__.py +0 -0
- pygeai/tests/evaluation/dataset/__init__.py +0 -0
- pygeai/tests/evaluation/dataset/test_clients.py +265 -0
- pygeai/tests/evaluation/plan/__init__.py +0 -0
- pygeai/tests/evaluation/plan/test_clients.py +195 -0
- pygeai/tests/evaluation/result/__init__.py +0 -0
- pygeai/tests/evaluation/result/test_clients.py +66 -0
- pygeai/tests/gam/__init__.py +0 -0
- pygeai/tests/gam/test_clients.py +195 -0
- pygeai/tests/health/__init__.py +0 -0
- pygeai/tests/health/test_clients.py +41 -0
- pygeai/tests/integration/__init__.py +0 -0
- pygeai/tests/integration/assistants/__init__.py +0 -0
- pygeai/tests/integration/assistants/rag/__init__.py +0 -0
- pygeai/tests/integration/assistants/rag/test_create_rag.py +91 -0
- pygeai/tests/integration/chat/__init__.py +0 -0
- pygeai/tests/integration/chat/test_generate_image.py +158 -0
- pygeai/tests/integration/lab/__init__.py +0 -0
- pygeai/tests/integration/lab/agents/__init__.py +0 -0
- pygeai/tests/integration/lab/agents/test_agents_list.py +106 -0
- pygeai/tests/integration/lab/agents/test_create_agent.py +319 -0
- pygeai/tests/integration/lab/agents/test_create_sharing_link.py +70 -0
- pygeai/tests/integration/lab/agents/test_delete_agent.py +75 -0
- pygeai/tests/integration/lab/agents/test_get_agent.py +94 -0
- pygeai/tests/integration/lab/agents/test_publish_agent_revision.py +127 -0
- pygeai/tests/integration/lab/agents/test_update_agent.py +250 -0
- pygeai/tests/integration/lab/processes/__init__.py +0 -0
- pygeai/tests/integration/lab/processes/test_create_process.py +345 -0
- pygeai/tests/integration/lab/processes/test_create_task.py +211 -0
- pygeai/tests/integration/lab/processes/test_delete_process.py +111 -0
- pygeai/tests/integration/lab/processes/test_get_process.py +201 -0
- pygeai/tests/integration/lab/processes/test_list_process_instances.py +91 -0
- pygeai/tests/integration/lab/processes/test_list_processes.py +138 -0
- pygeai/tests/integration/lab/processes/test_publish_process_revision.py +232 -0
- pygeai/tests/integration/lab/processes/test_update_process.py +289 -0
- pygeai/tests/integration/lab/reasoning_strategies/__init__.py +0 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_get_reasoning_strategy.py +70 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_list_reasoning_strategies.py +93 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_update_reasoning_strategy.py +149 -0
- pygeai/tests/integration/lab/tools/__init__.py +0 -0
- pygeai/tests/integration/lab/tools/test_create_tool.py +288 -0
- pygeai/tests/integration/lab/tools/test_delete_tool.py +87 -0
- pygeai/tests/integration/lab/tools/test_get_parameter.py +98 -0
- pygeai/tests/integration/lab/tools/test_get_tool.py +91 -0
- pygeai/tests/integration/lab/tools/test_list_tools.py +106 -0
- pygeai/tests/integration/lab/tools/test_publish_tool_revision.py +119 -0
- pygeai/tests/integration/lab/tools/test_set_parameter.py +114 -0
- pygeai/tests/integration/lab/tools/test_update_tool.py +267 -0
- pygeai/tests/lab/__init__.py +0 -0
- pygeai/tests/lab/agents/__init__.py +0 -0
- pygeai/tests/lab/agents/test_clients.py +481 -0
- pygeai/tests/lab/agents/test_mappers.py +440 -0
- pygeai/tests/lab/processes/__init__.py +0 -0
- pygeai/tests/lab/processes/test_clients.py +1416 -0
- pygeai/tests/lab/processes/test_mappers.py +1092 -0
- pygeai/tests/lab/spec/__init__.py +0 -0
- pygeai/tests/lab/spec/test_loader.py +59 -0
- pygeai/tests/lab/spec/test_parsers.py +182 -0
- pygeai/tests/lab/strategies/__init__.py +0 -0
- pygeai/tests/lab/strategies/test_clients.py +241 -0
- pygeai/tests/lab/strategies/test_mappers.py +132 -0
- pygeai/tests/lab/test_managers.py +553 -0
- pygeai/tests/lab/test_mappers.py +245 -0
- pygeai/tests/lab/test_models.py +1154 -0
- pygeai/tests/lab/tools/__init__.py +0 -0
- pygeai/tests/lab/tools/test_clients.py +521 -0
- pygeai/tests/lab/tools/test_mappers.py +198 -0
- pygeai/tests/migration/__init__.py +0 -0
- pygeai/tests/migration/test_strategies.py +405 -0
- pygeai/tests/migration/test_tools.py +159 -0
- pygeai/tests/organization/limits/__init__.py +0 -0
- pygeai/tests/organization/limits/test_clients.py +567 -0
- pygeai/tests/organization/limits/test_managers.py +402 -0
- pygeai/tests/organization/test_clients.py +615 -64
- pygeai/tests/organization/test_managers.py +424 -0
- pygeai/tests/organization/test_mappers.py +153 -0
- pygeai/tests/organization/test_responses.py +137 -0
- pygeai/tests/proxy/__init__.py +1 -0
- pygeai/tests/proxy/test_clients.py +397 -0
- pygeai/tests/proxy/test_config.py +171 -0
- pygeai/tests/proxy/test_integration.py +305 -0
- pygeai/tests/proxy/test_managers.py +312 -0
- pygeai/tests/proxy/test_servers.py +387 -0
- pygeai/tests/proxy/test_tool.py +176 -0
- pygeai/tests/snippets/__init__.py +0 -0
- pygeai/tests/snippets/analytics/__init__.py +0 -0
- pygeai/tests/snippets/analytics/get_agent_usage_per_user.py +16 -0
- pygeai/tests/snippets/analytics/get_agents_created_and_modified.py +11 -0
- pygeai/tests/snippets/analytics/get_average_cost_per_request.py +10 -0
- pygeai/tests/snippets/analytics/get_overall_error_rate.py +10 -0
- pygeai/tests/snippets/analytics/get_top_10_agents_by_requests.py +12 -0
- pygeai/tests/snippets/analytics/get_total_active_users.py +10 -0
- pygeai/tests/snippets/analytics/get_total_cost.py +10 -0
- pygeai/tests/snippets/analytics/get_total_requests_per_day.py +12 -0
- pygeai/tests/snippets/analytics/get_total_tokens.py +12 -0
- pygeai/tests/snippets/assistants/__init__.py +0 -0
- pygeai/tests/snippets/assistants/create_chat_assistant.py +54 -0
- pygeai/tests/snippets/assistants/create_text_assistant.py +51 -0
- pygeai/tests/snippets/assistants/data_analyst/__init__.py +0 -0
- pygeai/tests/snippets/assistants/data_analyst/extend_and_check.py +100 -0
- pygeai/tests/snippets/assistants/data_analyst/extend_dataset.py +9 -0
- pygeai/tests/snippets/assistants/data_analyst/get_status.py +9 -0
- pygeai/tests/snippets/assistants/file_summarizer_assistant.py +149 -0
- pygeai/tests/snippets/assistants/get_assistant_data.py +8 -0
- pygeai/tests/snippets/assistants/get_assistant_list.py +7 -0
- pygeai/tests/snippets/assistants/rag/__init__.py +0 -0
- pygeai/tests/snippets/assistants/rag/create_rag_assistant.py +65 -0
- pygeai/tests/snippets/assistants/rag/delete_al_documents.py +7 -0
- pygeai/tests/snippets/assistants/rag/delete_document.py +10 -0
- pygeai/tests/snippets/assistants/rag/delete_rag_assistant.py +8 -0
- pygeai/tests/snippets/assistants/rag/get_document.py +10 -0
- pygeai/tests/snippets/assistants/rag/get_documents.py +7 -0
- pygeai/tests/snippets/assistants/rag/get_rag_assistant_data.py +8 -0
- pygeai/tests/snippets/assistants/rag/update_rag_assistant.py +48 -0
- pygeai/tests/snippets/assistants/rag/upload_document.py +19 -0
- pygeai/tests/snippets/assistants/send_feedback.py +14 -0
- pygeai/tests/snippets/assistants/update_chat_assistant.py +63 -0
- pygeai/tests/snippets/auth/__init__.py +0 -0
- pygeai/tests/snippets/chat/__init__.py +0 -0
- pygeai/tests/snippets/chat/cancel_request.py +7 -0
- pygeai/tests/snippets/chat/chat_completion.py +28 -0
- pygeai/tests/snippets/chat/chat_completion_1.py +40 -0
- pygeai/tests/snippets/chat/chat_completion_2.py +60 -0
- pygeai/tests/snippets/chat/chat_completion_3.py +27 -0
- pygeai/tests/snippets/chat/chat_completion_4.py +67 -0
- pygeai/tests/snippets/chat/chat_completion_streaming.py +63 -0
- pygeai/tests/snippets/chat/chat_completion_with_reasoning_effort.py +18 -0
- pygeai/tests/snippets/chat/get_request_status.py +7 -0
- pygeai/tests/snippets/chat/get_response.py +15 -0
- pygeai/tests/snippets/chat/get_response_complete_example.py +67 -0
- pygeai/tests/snippets/chat/get_response_streaming.py +20 -0
- pygeai/tests/snippets/chat/get_response_with_files.py +16 -0
- pygeai/tests/snippets/chat/get_response_with_instructions.py +19 -0
- pygeai/tests/snippets/chat/get_response_with_metadata.py +24 -0
- pygeai/tests/snippets/chat/get_response_with_parallel_tools.py +58 -0
- pygeai/tests/snippets/chat/get_response_with_reasoning.py +21 -0
- pygeai/tests/snippets/chat/get_response_with_store.py +38 -0
- pygeai/tests/snippets/chat/get_response_with_tools.py +36 -0
- pygeai/tests/snippets/chat/get_response_with_truncation.py +24 -0
- pygeai/tests/snippets/chat/send_chat_request.py +33 -0
- pygeai/tests/snippets/dbg/__init__.py +0 -0
- pygeai/tests/snippets/dbg/basic_debugging.py +32 -0
- pygeai/tests/snippets/dbg/breakpoint_management.py +48 -0
- pygeai/tests/snippets/dbg/file_debugging.py +72 -0
- pygeai/tests/snippets/dbg/module_debugging.py +61 -0
- pygeai/tests/snippets/dbg/stack_navigation.py +45 -0
- pygeai/tests/snippets/dbg/stepping_example.py +40 -0
- pygeai/tests/snippets/embeddings/__init__.py +0 -0
- pygeai/tests/snippets/embeddings/cache_example.py +31 -0
- pygeai/tests/snippets/embeddings/cohere_example.py +41 -0
- pygeai/tests/snippets/embeddings/generate_embeddings.py +26 -0
- pygeai/tests/snippets/embeddings/openai_base64_example.py +27 -0
- pygeai/tests/snippets/embeddings/openai_example.py +30 -0
- pygeai/tests/snippets/embeddings/similarity_example.py +42 -0
- pygeai/tests/snippets/evaluation/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/dataset/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/dataset/complete_workflow_example.py +195 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset.py +26 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset_from_file.py +11 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset_row.py +17 -0
- pygeai/tests/snippets/evaluation/dataset/create_expected_source.py +18 -0
- pygeai/tests/snippets/evaluation/dataset/create_filter_variable.py +19 -0
- pygeai/tests/snippets/evaluation/dataset/delete_dataset.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/delete_dataset_row.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/delete_expected_source.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/delete_filter_variable.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/get_dataset.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/get_dataset_row.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/get_expected_source.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/get_filter_variable.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/list_dataset_rows.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/list_datasets.py +6 -0
- pygeai/tests/snippets/evaluation/dataset/list_expected_sources.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/list_filter_variables.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/update_dataset.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/update_dataset_row.py +20 -0
- pygeai/tests/snippets/evaluation/dataset/update_expected_source.py +18 -0
- pygeai/tests/snippets/evaluation/dataset/update_filter_variable.py +19 -0
- pygeai/tests/snippets/evaluation/dataset/upload_dataset_rows_file.py +10 -0
- pygeai/tests/snippets/evaluation/plan/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/plan/add_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/complete_workflow_example.py +136 -0
- pygeai/tests/snippets/evaluation/plan/create_evaluation_plan.py +24 -0
- pygeai/tests/snippets/evaluation/plan/create_rag_evaluation_plan.py +22 -0
- pygeai/tests/snippets/evaluation/plan/delete_evaluation_plan.py +9 -0
- pygeai/tests/snippets/evaluation/plan/delete_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/execute_evaluation_plan.py +11 -0
- pygeai/tests/snippets/evaluation/plan/get_evaluation_plan.py +9 -0
- pygeai/tests/snippets/evaluation/plan/get_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/get_system_metric.py +9 -0
- pygeai/tests/snippets/evaluation/plan/list_evaluation_plans.py +7 -0
- pygeai/tests/snippets/evaluation/plan/list_plan_system_metrics.py +9 -0
- pygeai/tests/snippets/evaluation/plan/list_system_metrics.py +7 -0
- pygeai/tests/snippets/evaluation/plan/update_evaluation_plan.py +22 -0
- pygeai/tests/snippets/evaluation/plan/update_plan_system_metric.py +14 -0
- pygeai/tests/snippets/evaluation/result/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/result/complete_workflow_example.py +150 -0
- pygeai/tests/snippets/evaluation/result/get_evaluation_result.py +26 -0
- pygeai/tests/snippets/evaluation/result/list_evaluation_results.py +17 -0
- pygeai/tests/snippets/files/__init__.py +0 -0
- pygeai/tests/snippets/files/delete_file.py +9 -0
- pygeai/tests/snippets/files/get_file_content.py +10 -0
- pygeai/tests/snippets/files/get_file_data.py +9 -0
- pygeai/tests/snippets/files/get_file_list.py +6 -0
- pygeai/tests/snippets/files/upload_file.py +13 -0
- pygeai/tests/snippets/gam/__init__.py +0 -0
- pygeai/tests/snippets/gam/gam_access_token.py +87 -0
- pygeai/tests/snippets/lab/__init__.py +0 -0
- pygeai/tests/snippets/lab/agentic_flow_example_1.py +326 -0
- pygeai/tests/snippets/lab/agentic_flow_example_2.py +206 -0
- pygeai/tests/snippets/lab/agentic_flow_example_3.py +486 -0
- pygeai/tests/snippets/lab/agentic_flow_example_4.py +446 -0
- pygeai/tests/snippets/lab/agents/__init__.py +0 -0
- pygeai/tests/snippets/lab/agents/create_agent.py +48 -0
- pygeai/tests/snippets/lab/agents/create_agent_2.py +48 -0
- pygeai/tests/snippets/lab/agents/create_agent_edge_case.py +48 -0
- pygeai/tests/snippets/lab/agents/create_agent_with_permissions.py +39 -0
- pygeai/tests/snippets/lab/agents/create_agent_with_properties.py +46 -0
- pygeai/tests/snippets/lab/agents/create_agent_without_instructions.py +48 -0
- pygeai/tests/snippets/lab/agents/delete_agent.py +12 -0
- pygeai/tests/snippets/lab/agents/get_agent.py +24 -0
- pygeai/tests/snippets/lab/agents/get_agent_with_new_fields.py +62 -0
- pygeai/tests/snippets/lab/agents/get_sharing_link.py +13 -0
- pygeai/tests/snippets/lab/agents/list_agents.py +18 -0
- pygeai/tests/snippets/lab/agents/publish_agent_revision.py +12 -0
- pygeai/tests/snippets/lab/agents/update_agent.py +50 -0
- pygeai/tests/snippets/lab/agents/update_agent_properties.py +50 -0
- pygeai/tests/snippets/lab/assistant_to_agent.py +191 -0
- pygeai/tests/snippets/lab/crud_ui.py +462 -0
- pygeai/tests/snippets/lab/processes/__init__.py +0 -0
- pygeai/tests/snippets/lab/processes/create_process.py +24 -0
- pygeai/tests/snippets/lab/processes/create_task.py +8 -0
- pygeai/tests/snippets/lab/processes/jobs/__init__.py +0 -0
- pygeai/tests/snippets/lab/processes/jobs/list_jobs.py +21 -0
- pygeai/tests/snippets/lab/processes/kbs/__init__.py +0 -0
- pygeai/tests/snippets/lab/processes/kbs/create_kb.py +18 -0
- pygeai/tests/snippets/lab/processes/kbs/get_kb.py +26 -0
- pygeai/tests/snippets/lab/processes/kbs/list_kbs.py +30 -0
- pygeai/tests/snippets/lab/processes/kbs/try_all.py +73 -0
- pygeai/tests/snippets/lab/processes/list_processes.py +10 -0
- pygeai/tests/snippets/lab/runner_1.py +212 -0
- pygeai/tests/snippets/lab/samples/__init__.py +0 -0
- pygeai/tests/snippets/lab/samples/summarize_files.py +162 -0
- pygeai/tests/snippets/lab/strategies/__init__.py +0 -0
- pygeai/tests/snippets/lab/strategies/create_reasoning_strategy.py +22 -0
- pygeai/tests/snippets/lab/strategies/get_reasoning_strategy.py +10 -0
- pygeai/tests/snippets/lab/strategies/list_reasoning_strategies.py +16 -0
- pygeai/tests/snippets/lab/strategies/update_reasoning_strategy.py +26 -0
- pygeai/tests/snippets/lab/tools/__init__.py +0 -0
- pygeai/tests/snippets/lab/tools/create_tool.py +48 -0
- pygeai/tests/snippets/lab/tools/create_tool_edge_case.py +50 -0
- pygeai/tests/snippets/lab/tools/delete_tool.py +21 -0
- pygeai/tests/snippets/lab/tools/get_parameter.py +21 -0
- pygeai/tests/snippets/lab/tools/get_tool.py +22 -0
- pygeai/tests/snippets/lab/tools/list_tools.py +23 -0
- pygeai/tests/snippets/lab/tools/publish_tool_revision.py +13 -0
- pygeai/tests/snippets/lab/tools/set_parameters.py +33 -0
- pygeai/tests/snippets/lab/tools/update_tool.py +52 -0
- pygeai/tests/snippets/lab/use_cases/__init__.py +0 -0
- pygeai/tests/snippets/lab/use_cases/c_code_fixer_agent_flow.py +238 -0
- pygeai/tests/snippets/lab/use_cases/create_cli_expert.py +1640 -0
- pygeai/tests/snippets/lab/use_cases/create_lab_expert.py +4541 -0
- pygeai/tests/snippets/lab/use_cases/create_tool_headless_web_browser.py +133 -0
- pygeai/tests/snippets/lab/use_cases/create_web_designer.py +189 -0
- pygeai/tests/snippets/lab/use_cases/create_web_reader.py +185 -0
- pygeai/tests/snippets/lab/use_cases/file_summarizer_example.py +157 -0
- pygeai/tests/snippets/lab/use_cases/file_summarizer_example_2.py +157 -0
- pygeai/tests/snippets/lab/use_cases/update_cli_expert.py +1773 -0
- pygeai/tests/snippets/lab/use_cases/update_lab_expert.py +4541 -0
- pygeai/tests/snippets/lab/use_cases/update_web_designer.py +188 -0
- pygeai/tests/snippets/lab/use_cases/update_web_reader.py +195 -0
- pygeai/tests/snippets/lab/use_cases/update_web_reader_with_tool.py +210 -0
- pygeai/tests/snippets/migrate/__init__.py +45 -0
- pygeai/tests/snippets/migrate/agent_migration.py +110 -0
- pygeai/tests/snippets/migrate/assistant_migration.py +64 -0
- pygeai/tests/snippets/migrate/orchestrator_examples.py +179 -0
- pygeai/tests/snippets/migrate/process_migration.py +64 -0
- pygeai/tests/snippets/migrate/project_migration.py +42 -0
- pygeai/tests/snippets/migrate/tool_migration.py +64 -0
- pygeai/tests/snippets/organization/__init__.py +0 -0
- pygeai/tests/snippets/organization/add_project_member.py +10 -0
- pygeai/tests/snippets/organization/add_project_member_batch.py +44 -0
- pygeai/tests/snippets/organization/create_project.py +23 -0
- pygeai/tests/snippets/organization/delete_project.py +7 -0
- pygeai/tests/snippets/organization/export_request_data.py +7 -0
- pygeai/tests/snippets/organization/get_memberships.py +12 -0
- pygeai/tests/snippets/organization/get_organization_members.py +6 -0
- pygeai/tests/snippets/organization/get_project_data.py +7 -0
- pygeai/tests/snippets/organization/get_project_list.py +8 -0
- pygeai/tests/snippets/organization/get_project_members.py +6 -0
- pygeai/tests/snippets/organization/get_project_memberships.py +12 -0
- pygeai/tests/snippets/organization/get_project_roles.py +6 -0
- pygeai/tests/snippets/organization/get_project_tokens.py +7 -0
- pygeai/tests/snippets/organization/update_project.py +14 -0
- pygeai/tests/snippets/rerank/__init__.py +0 -0
- pygeai/tests/snippets/rerank/rerank_chunks.py +19 -0
- pygeai/tests/snippets/secrets/__init__.py +0 -0
- pygeai/tests/snippets/usage_limit/__init__.py +0 -0
- pygeai/tests/snippets/usage_limit/delete_usage_limit.py +16 -0
- pygeai/tests/snippets/usage_limit/get_all_usage_limit_from_organization.py +12 -0
- pygeai/tests/snippets/usage_limit/get_usage_limit_from_organization.py +11 -0
- pygeai/tests/snippets/usage_limit/get_usage_limit_from_project.py +13 -0
- pygeai/tests/snippets/usage_limit/set_usage_limit_organization.py +22 -0
- pygeai/tests/snippets/usage_limit/set_usage_limit_project.py +23 -0
- pygeai/tests/snippets/usage_limit/update_usage_limit_organization.py +23 -0
- pygeai/tests/snippets/usage_limit/update_usage_limit_project.py +24 -0
- pygeai/vendor/a2a/__init__.py +1 -0
- pygeai/vendor/a2a/auth/__init__.py +0 -0
- pygeai/vendor/a2a/auth/user.py +31 -0
- pygeai/vendor/a2a/client/__init__.py +19 -0
- pygeai/vendor/a2a/client/client.py +425 -0
- pygeai/vendor/a2a/client/errors.py +33 -0
- pygeai/vendor/a2a/client/helpers.py +22 -0
- pygeai/vendor/a2a/py.typed +0 -0
- pygeai/vendor/a2a/server/__init__.py +1 -0
- pygeai/vendor/a2a/server/agent_execution/__init__.py +18 -0
- pygeai/vendor/a2a/server/agent_execution/agent_executor.py +44 -0
- pygeai/vendor/a2a/server/agent_execution/context.py +155 -0
- pygeai/vendor/a2a/server/agent_execution/request_context_builder.py +20 -0
- pygeai/vendor/a2a/server/agent_execution/simple_request_context_builder.py +77 -0
- pygeai/vendor/a2a/server/apps/__init__.py +16 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/__init__.py +16 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/fastapi_app.py +88 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/jsonrpc_app.py +426 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/starlette_app.py +123 -0
- pygeai/vendor/a2a/server/context.py +23 -0
- pygeai/vendor/a2a/server/events/__init__.py +21 -0
- pygeai/vendor/a2a/server/events/event_consumer.py +149 -0
- pygeai/vendor/a2a/server/events/event_queue.py +156 -0
- pygeai/vendor/a2a/server/events/in_memory_queue_manager.py +85 -0
- pygeai/vendor/a2a/server/events/queue_manager.py +35 -0
- pygeai/vendor/a2a/server/request_handlers/__init__.py +20 -0
- pygeai/vendor/a2a/server/request_handlers/default_request_handler.py +435 -0
- pygeai/vendor/a2a/server/request_handlers/jsonrpc_handler.py +327 -0
- pygeai/vendor/a2a/server/request_handlers/request_handler.py +161 -0
- pygeai/vendor/a2a/server/request_handlers/response_helpers.py +133 -0
- pygeai/vendor/a2a/server/tasks/__init__.py +20 -0
- pygeai/vendor/a2a/server/tasks/inmemory_push_notifier.py +62 -0
- pygeai/vendor/a2a/server/tasks/inmemory_task_store.py +51 -0
- pygeai/vendor/a2a/server/tasks/push_notifier.py +25 -0
- pygeai/vendor/a2a/server/tasks/result_aggregator.py +151 -0
- pygeai/vendor/a2a/server/tasks/task_manager.py +253 -0
- pygeai/vendor/a2a/server/tasks/task_store.py +22 -0
- pygeai/vendor/a2a/server/tasks/task_updater.py +155 -0
- pygeai/vendor/a2a/types.py +1624 -0
- pygeai/vendor/a2a/utils/__init__.py +40 -0
- pygeai/vendor/a2a/utils/artifact.py +72 -0
- pygeai/vendor/a2a/utils/errors.py +69 -0
- pygeai/vendor/a2a/utils/helpers.py +176 -0
- pygeai/vendor/a2a/utils/message.py +83 -0
- pygeai/vendor/a2a/utils/task.py +57 -0
- pygeai/vendor/a2a/utils/telemetry.py +299 -0
- pygeai-0.6.0b15.dist-info/METADATA +205 -0
- pygeai-0.6.0b15.dist-info/RECORD +799 -0
- {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info}/WHEEL +1 -1
- pygeai-0.6.0b15.dist-info/entry_points.txt +5 -0
- {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info/licenses}/LICENSE +13 -1
- {pygeai-0.1.6.dist-info → pygeai-0.6.0b15.dist-info}/top_level.txt +0 -1
- docs/source/conf.py +0 -45
- pygeai/core/clients.py +0 -240
- pygeai/tests/core/test_clients.py +0 -49
- pygeai-0.1.6.dist-info/METADATA +0 -92
- pygeai-0.1.6.dist-info/RECORD +0 -65
- pygeai-0.1.6.dist-info/SOURCES.sync-conflict-20241223-145950-3QD4F42.txt +0 -41
- pygeai-0.1.6.dist-info/entry_points.txt +0 -2
- /pygeai/{agent → analytics}/__init__.py +0 -0
pygeai/lab/models.py
ADDED
|
@@ -0,0 +1,1719 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Literal, Optional, List, Dict, Any, Union, Iterator
|
|
3
|
+
|
|
4
|
+
from pydantic import model_validator, Field, field_validator
|
|
5
|
+
|
|
6
|
+
from pygeai.core import CustomBaseModel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FilterSettings(CustomBaseModel):
|
|
10
|
+
"""
|
|
11
|
+
Represents filter settings for querying or filtering data.
|
|
12
|
+
|
|
13
|
+
:param id: str - The ID to filter by (e.g., an agent's ID), defaults to an empty string.
|
|
14
|
+
:param name: str - The name to filter by (e.g., reasoning strategy name), defaults to an empty string.
|
|
15
|
+
:param status: str - Status filter, defaults to None.
|
|
16
|
+
:param start: int - Starting index for pagination, defaults to None.
|
|
17
|
+
:param count: int - Number of items to return, defaults to None.
|
|
18
|
+
:param is_active: bool - If it's active. Defaults to false.
|
|
19
|
+
:param access_scope: str - Access scope filter, defaults to "private".
|
|
20
|
+
:param allow_drafts: bool - Whether to include draft items, defaults to True.
|
|
21
|
+
:param allow_external: bool - Whether to include external items, defaults to False.
|
|
22
|
+
:param revision: str - Revision of the agent, defaults to 0.
|
|
23
|
+
:param version: str - Version of the agent, defaults to 0
|
|
24
|
+
:param scope: Optional[str] - Filter by scope (e.g., "builtin", "external", "api").
|
|
25
|
+
"""
|
|
26
|
+
id: Optional[str] = Field(default=None, description="The ID to filter by (e.g., an agent's ID)")
|
|
27
|
+
name: Optional[str] = Field(default=None, description="The name to filter by (e.g., a reasoning strategy name)")
|
|
28
|
+
status: Optional[str] = Field(default=None, description="Status filter")
|
|
29
|
+
start: Optional[int] = Field(default=None, description="Starting index for pagination")
|
|
30
|
+
count: Optional[int] = Field(default=None, description="Number of items to return")
|
|
31
|
+
access_scope: Optional[str] = Field(default="private", alias="accessScope", description="Access scope filter")
|
|
32
|
+
allow_drafts: Optional[bool] = Field(default=True, alias="allowDrafts", description="Whether to include draft items")
|
|
33
|
+
allow_external: Optional[bool] = Field(default=False, alias="allowExternal", description="Whether to include external items")
|
|
34
|
+
is_active: Optional[bool] = Field(default=False, alias="isActive", description="Whether it's active")
|
|
35
|
+
revision: Optional[str] = Field(default=None, description="Revision of the agent")
|
|
36
|
+
version: Optional[int] = Field(default=None, description="Version of the agent")
|
|
37
|
+
scope: Optional[str] = Field(None, description="Filter by scope (e.g., 'builtin', 'external', 'api')")
|
|
38
|
+
|
|
39
|
+
def to_dict(self):
|
|
40
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
41
|
+
|
|
42
|
+
def __str__(self):
|
|
43
|
+
return str(self.to_dict())
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Sampling(CustomBaseModel):
|
|
47
|
+
"""
|
|
48
|
+
Represents sampling configuration for an LLM.
|
|
49
|
+
|
|
50
|
+
:param temperature: float - Temperature value for sampling, controlling randomness.
|
|
51
|
+
:param top_k: int - Top-K sampling parameter, limiting to the top K probable tokens.
|
|
52
|
+
:param top_p: float - Top-P (nucleus) sampling parameter, limiting to the smallest set of tokens whose cumulative probability exceeds P.
|
|
53
|
+
"""
|
|
54
|
+
temperature: float = Field(1.0, alias="temperature")
|
|
55
|
+
top_k: int = Field(50, alias="topK")
|
|
56
|
+
top_p: float = Field(1.0, alias="topP")
|
|
57
|
+
|
|
58
|
+
def to_dict(self):
|
|
59
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
60
|
+
|
|
61
|
+
def __str__(self):
|
|
62
|
+
return str(self.to_dict())
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class LlmConfig(CustomBaseModel):
|
|
66
|
+
"""
|
|
67
|
+
Represents the configuration parameters for an LLM.
|
|
68
|
+
|
|
69
|
+
:param max_tokens: int - Maximum number of tokens the LLM can generate.
|
|
70
|
+
:param timeout: int - Timeout value in seconds (0 means no timeout).
|
|
71
|
+
:param sampling: Sampling - Sampling configuration for the LLM.
|
|
72
|
+
"""
|
|
73
|
+
max_tokens: int = Field(..., alias="maxTokens")
|
|
74
|
+
timeout: Optional[int] = Field(60, alias="timeout")
|
|
75
|
+
sampling: Optional[Sampling] = Field(Sampling(), alias="sampling")
|
|
76
|
+
|
|
77
|
+
def to_dict(self):
|
|
78
|
+
result = {
|
|
79
|
+
"maxTokens": self.max_tokens,
|
|
80
|
+
"timeout": self.timeout,
|
|
81
|
+
"sampling": self.sampling.to_dict() if self.sampling else None
|
|
82
|
+
}
|
|
83
|
+
return {k: v for k, v in result.items() if v is not None}
|
|
84
|
+
|
|
85
|
+
def __str__(self):
|
|
86
|
+
return str(self.to_dict())
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class Model(CustomBaseModel):
|
|
90
|
+
"""
|
|
91
|
+
Represents a language model configuration used by an agent.
|
|
92
|
+
|
|
93
|
+
:param name: str - The unique name identifying the model.
|
|
94
|
+
:param llm_config: Optional[LlmConfig] - Overrides default agent LLM settings.
|
|
95
|
+
:param prompt: Optional[dict] - A tailored prompt specific to this model.
|
|
96
|
+
"""
|
|
97
|
+
name: Optional[str] = Field(None, alias="name")
|
|
98
|
+
llm_config: Optional[LlmConfig] = Field(None, alias="llmConfig")
|
|
99
|
+
prompt: Optional[Dict[str, Any]] = Field(None, alias="prompt")
|
|
100
|
+
|
|
101
|
+
@field_validator("llm_config", mode="before")
|
|
102
|
+
@classmethod
|
|
103
|
+
def normalize_llm_config(cls, value):
|
|
104
|
+
if isinstance(value, dict):
|
|
105
|
+
return LlmConfig.model_validate(value)
|
|
106
|
+
return value
|
|
107
|
+
|
|
108
|
+
def to_dict(self):
|
|
109
|
+
result = {"name": self.name}
|
|
110
|
+
if self.llm_config is not None:
|
|
111
|
+
result["llmConfig"] = self.llm_config.to_dict()
|
|
112
|
+
if self.prompt is not None:
|
|
113
|
+
result["prompt"] = self.prompt
|
|
114
|
+
return result
|
|
115
|
+
|
|
116
|
+
def __str__(self):
|
|
117
|
+
return str(self.to_dict())
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class PromptExample(CustomBaseModel):
|
|
121
|
+
"""
|
|
122
|
+
Represents an example for the prompt configuration.
|
|
123
|
+
|
|
124
|
+
:param input_data: str - Example input data provided to the agent.
|
|
125
|
+
:param output: str - Example output in JSON string format.
|
|
126
|
+
"""
|
|
127
|
+
input_data: str = Field(..., alias="inputData")
|
|
128
|
+
output: str = Field(..., alias="output")
|
|
129
|
+
|
|
130
|
+
def to_dict(self):
|
|
131
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
132
|
+
|
|
133
|
+
def __str__(self):
|
|
134
|
+
return str(self.to_dict())
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class PromptOutput(CustomBaseModel):
|
|
138
|
+
"""
|
|
139
|
+
Represents an output definition for the prompt configuration.
|
|
140
|
+
|
|
141
|
+
:param key: str - Key identifying the output.
|
|
142
|
+
:param description: str - Description of the output's purpose and format.
|
|
143
|
+
"""
|
|
144
|
+
key: str = Field(..., alias="key")
|
|
145
|
+
description: str = Field(..., alias="description")
|
|
146
|
+
|
|
147
|
+
def to_dict(self):
|
|
148
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
149
|
+
|
|
150
|
+
def __str__(self):
|
|
151
|
+
return str(self.to_dict())
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class Prompt(CustomBaseModel):
|
|
155
|
+
"""
|
|
156
|
+
Represents the prompt configuration for an agent.
|
|
157
|
+
|
|
158
|
+
:param instructions: str - Instructions for the agent's behavior.
|
|
159
|
+
:param inputs: List[str] - List of input parameters the agent expects.
|
|
160
|
+
:param outputs: List[PromptOutput] - List of output definitions the agent produces.
|
|
161
|
+
:param context: Optional[str] - Background context for the agent # NOT IMPLEMENTED YET
|
|
162
|
+
:param examples: List[PromptExample] - List of example input-output pairs.
|
|
163
|
+
"""
|
|
164
|
+
instructions: Optional[str] = Field(None, alias="instructions")
|
|
165
|
+
inputs: Optional[List[str]] = Field(None, alias="inputs")
|
|
166
|
+
outputs: Optional[List[PromptOutput]] = Field([], alias="outputs")
|
|
167
|
+
context: Optional[str] = Field(None, alias="context", description="Background context for the agent")
|
|
168
|
+
examples: Optional[List[PromptExample]] = Field(None, alias="examples")
|
|
169
|
+
|
|
170
|
+
'''
|
|
171
|
+
@field_validator("instructions")
|
|
172
|
+
@classmethod
|
|
173
|
+
def validate_instructions(cls, value: str) -> str:
|
|
174
|
+
if not value.strip():
|
|
175
|
+
raise ValueError("instructions cannot be blank")
|
|
176
|
+
|
|
177
|
+
return value
|
|
178
|
+
'''
|
|
179
|
+
|
|
180
|
+
@field_validator("outputs", mode="before")
|
|
181
|
+
@classmethod
|
|
182
|
+
def normalize_outputs(cls, value):
|
|
183
|
+
if isinstance(value, list):
|
|
184
|
+
return [PromptOutput.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
185
|
+
return value
|
|
186
|
+
|
|
187
|
+
@field_validator("examples", mode="before")
|
|
188
|
+
@classmethod
|
|
189
|
+
def normalize_examples(cls, value):
|
|
190
|
+
if isinstance(value, list):
|
|
191
|
+
return [PromptExample.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
192
|
+
return value
|
|
193
|
+
|
|
194
|
+
def to_dict(self):
|
|
195
|
+
result = {
|
|
196
|
+
"instructions": self.instructions,
|
|
197
|
+
"context": self.context,
|
|
198
|
+
"inputs": self.inputs,
|
|
199
|
+
"outputs": [output.to_dict() for output in self.outputs] if self.outputs else None,
|
|
200
|
+
"examples": [example.to_dict() for example in self.examples] if self.examples else None
|
|
201
|
+
}
|
|
202
|
+
return {k: v for k, v in result.items() if v is not None}
|
|
203
|
+
|
|
204
|
+
def __str__(self):
|
|
205
|
+
return str(self.to_dict())
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
class ModelList(CustomBaseModel):
|
|
209
|
+
models: List[Model] = Field(..., alias="models")
|
|
210
|
+
|
|
211
|
+
@field_validator("models", mode="before")
|
|
212
|
+
@classmethod
|
|
213
|
+
def normalize_models(cls, value):
|
|
214
|
+
if isinstance(value, list):
|
|
215
|
+
return [Model.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
216
|
+
return value
|
|
217
|
+
|
|
218
|
+
def to_dict(self):
|
|
219
|
+
return [model.to_dict() for model in self.models]
|
|
220
|
+
|
|
221
|
+
def __getitem__(self, index: int) -> Model:
|
|
222
|
+
if self.models is None:
|
|
223
|
+
raise IndexError("ModelList is empty")
|
|
224
|
+
return self.models[index]
|
|
225
|
+
|
|
226
|
+
def __len__(self) -> int:
|
|
227
|
+
return len(self.models) if self.models else 0
|
|
228
|
+
|
|
229
|
+
def __iter__(self):
|
|
230
|
+
"""Make ModelList iterable over its models."""
|
|
231
|
+
if self.models is None:
|
|
232
|
+
return iter([])
|
|
233
|
+
return iter(self.models)
|
|
234
|
+
|
|
235
|
+
def append(self, item: Model) -> None:
|
|
236
|
+
"""Append a Model instance to the models list."""
|
|
237
|
+
if self.models is None:
|
|
238
|
+
self.models = []
|
|
239
|
+
self.models.append(item)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
class ResourcePoolTool(CustomBaseModel):
|
|
243
|
+
"""
|
|
244
|
+
Represents a tool within a resource pool.
|
|
245
|
+
|
|
246
|
+
:param name: str - The ID or name of the tool.
|
|
247
|
+
:param revision: Optional[int] - Specific revision of the tool; if None, uses latest published version.
|
|
248
|
+
"""
|
|
249
|
+
name: str = Field(..., alias="name", description="The ID or name of the tool")
|
|
250
|
+
revision: Optional[int] = Field(None, alias="revision", description="Specific revision of the tool; if None, uses latest published version")
|
|
251
|
+
|
|
252
|
+
@field_validator("name")
|
|
253
|
+
@classmethod
|
|
254
|
+
def validate_name(cls, value: str) -> str:
|
|
255
|
+
if not value.strip():
|
|
256
|
+
raise ValueError("name cannot be blank")
|
|
257
|
+
if ":" in value or "/" in value:
|
|
258
|
+
raise ValueError("name cannot contain ':' or '/'")
|
|
259
|
+
return value
|
|
260
|
+
|
|
261
|
+
def to_dict(self):
|
|
262
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
263
|
+
|
|
264
|
+
def __str__(self):
|
|
265
|
+
return str(self.to_dict())
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
class ResourcePoolAgent(CustomBaseModel):
|
|
269
|
+
"""
|
|
270
|
+
Represents a helper agent within a resource pool.
|
|
271
|
+
|
|
272
|
+
:param name: str - The ID or name of the agent.
|
|
273
|
+
:param revision: Optional[int] - Specific revision of the agent; if None, uses latest published version.
|
|
274
|
+
"""
|
|
275
|
+
name: str = Field(..., alias="name", description="The ID or name of the agent")
|
|
276
|
+
revision: Optional[int] = Field(None, alias="revision", description="Specific revision of the agent; if None, uses latest published version")
|
|
277
|
+
|
|
278
|
+
@field_validator("name")
|
|
279
|
+
@classmethod
|
|
280
|
+
def validate_name(cls, value: str) -> str:
|
|
281
|
+
if not value.strip():
|
|
282
|
+
raise ValueError("name cannot be blank")
|
|
283
|
+
if ":" in value or "/" in value:
|
|
284
|
+
raise ValueError("name cannot contain ':' or '/'")
|
|
285
|
+
return value
|
|
286
|
+
|
|
287
|
+
def to_dict(self):
|
|
288
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
289
|
+
|
|
290
|
+
def __str__(self):
|
|
291
|
+
return str(self.to_dict())
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class ResourcePool(CustomBaseModel):
|
|
295
|
+
"""
|
|
296
|
+
Represents a resource pool organizing tools and helper agents.
|
|
297
|
+
|
|
298
|
+
:param name: str - The name of the resource pool.
|
|
299
|
+
:param tools: Optional[List[ResourcePoolTool]] - List of tools in the pool.
|
|
300
|
+
:param agents: Optional[List[ResourcePoolAgent]] - List of helper agents in the pool.
|
|
301
|
+
"""
|
|
302
|
+
name: str = Field(..., alias="name", description="The name of the resource pool")
|
|
303
|
+
tools: Optional[List[ResourcePoolTool]] = Field(None, alias="tools", description="List of tools in the pool")
|
|
304
|
+
agents: Optional[List[ResourcePoolAgent]] = Field(None, alias="agents", description="List of helper agents in the pool")
|
|
305
|
+
|
|
306
|
+
@field_validator("name")
|
|
307
|
+
@classmethod
|
|
308
|
+
def validate_name(cls, value: str) -> str:
|
|
309
|
+
if not value.strip():
|
|
310
|
+
raise ValueError("name cannot be blank")
|
|
311
|
+
if ":" in value or "/" in value:
|
|
312
|
+
raise ValueError("name cannot contain ':' or '/'")
|
|
313
|
+
return value
|
|
314
|
+
|
|
315
|
+
@field_validator("tools", mode="before")
|
|
316
|
+
@classmethod
|
|
317
|
+
def normalize_tools(cls, value):
|
|
318
|
+
if isinstance(value, list):
|
|
319
|
+
return [ResourcePoolTool.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
320
|
+
return value
|
|
321
|
+
|
|
322
|
+
@field_validator("agents", mode="before")
|
|
323
|
+
@classmethod
|
|
324
|
+
def normalize_agents(cls, value):
|
|
325
|
+
if isinstance(value, list):
|
|
326
|
+
return [ResourcePoolAgent.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
327
|
+
return value
|
|
328
|
+
|
|
329
|
+
def to_dict(self):
|
|
330
|
+
result = {
|
|
331
|
+
"name": self.name,
|
|
332
|
+
"tools": [tool.to_dict() for tool in self.tools] if self.tools else None,
|
|
333
|
+
"agents": [agent.to_dict() for agent in self.agents] if self.agents else None
|
|
334
|
+
}
|
|
335
|
+
return {k: v for k, v in result.items() if v is not None}
|
|
336
|
+
|
|
337
|
+
def __str__(self):
|
|
338
|
+
return str(self.to_dict())
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
class ResourcePoolList(CustomBaseModel):
|
|
342
|
+
"""
|
|
343
|
+
Represents a list of resource pools for an agent.
|
|
344
|
+
|
|
345
|
+
:param resource_pools: List[ResourcePool] - The list of resource pools.
|
|
346
|
+
"""
|
|
347
|
+
resource_pools: List[ResourcePool] = Field(..., alias="resourcePools", description="The list of resource pools")
|
|
348
|
+
|
|
349
|
+
@field_validator("resource_pools", mode="before")
|
|
350
|
+
@classmethod
|
|
351
|
+
def normalize_resource_pools(cls, value):
|
|
352
|
+
if isinstance(value, list):
|
|
353
|
+
return [ResourcePool.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
354
|
+
raise ValueError("resource_pools must be a list of ResourcePool instances or dictionaries")
|
|
355
|
+
|
|
356
|
+
def to_dict(self):
|
|
357
|
+
"""
|
|
358
|
+
Serializes the ResourcePoolList to a list of dictionaries.
|
|
359
|
+
|
|
360
|
+
:return: List[Dict] - A list of dictionary representations of the resource pools.
|
|
361
|
+
"""
|
|
362
|
+
return [pool.to_dict() for pool in self.resource_pools]
|
|
363
|
+
|
|
364
|
+
def __str__(self):
|
|
365
|
+
return str(self.to_dict())
|
|
366
|
+
|
|
367
|
+
def __getitem__(self, index: int) -> ResourcePool:
|
|
368
|
+
if self.resource_pools is None:
|
|
369
|
+
raise IndexError("ResourcePoolList is empty")
|
|
370
|
+
return self.resource_pools[index]
|
|
371
|
+
|
|
372
|
+
def __len__(self) -> int:
|
|
373
|
+
return len(self.resource_pools) if self.resource_pools else 0
|
|
374
|
+
|
|
375
|
+
def __iter__(self) -> Iterator[ResourcePool]:
|
|
376
|
+
"""Make ResourcePoolList iterable over its resource pools."""
|
|
377
|
+
if self.resource_pools is None:
|
|
378
|
+
return iter([])
|
|
379
|
+
return iter(self.resource_pools)
|
|
380
|
+
|
|
381
|
+
def append(self, item: ResourcePool) -> None:
|
|
382
|
+
"""Append a ResourcePool instance to the resource_pools list."""
|
|
383
|
+
if self.resource_pools is None:
|
|
384
|
+
self.resource_pools = []
|
|
385
|
+
self.resource_pools.append(item)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
class Permission(CustomBaseModel):
|
|
389
|
+
"""
|
|
390
|
+
Represents permission settings for an agent.
|
|
391
|
+
|
|
392
|
+
:param chat_sharing: Literal["none", "organization", "project"] - Chat sharing permission level.
|
|
393
|
+
:param external_execution: Literal["none", "organization", "project"] - External execution permission level.
|
|
394
|
+
"""
|
|
395
|
+
chat_sharing: Optional[Literal["none", "organization", "project"]] = Field(None, alias="chatSharing", description="Chat sharing permission level")
|
|
396
|
+
external_execution: Optional[Literal["none", "organization", "project"]] = Field(None, alias="externalExecution", description="External execution permission level")
|
|
397
|
+
|
|
398
|
+
def to_dict(self):
|
|
399
|
+
"""Convert Permission to dictionary with API aliases."""
|
|
400
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
class Property(CustomBaseModel):
|
|
404
|
+
"""
|
|
405
|
+
Represents a property key-value pair with data type.
|
|
406
|
+
|
|
407
|
+
:param data_type: str - Data type of the property (e.g., "String", "Number", "Boolean").
|
|
408
|
+
:param key: str - Property key identifier.
|
|
409
|
+
:param value: str - Property value.
|
|
410
|
+
"""
|
|
411
|
+
data_type: str = Field(..., alias="dataType", description="Data type of the property")
|
|
412
|
+
key: str = Field(..., alias="key", description="Property key identifier")
|
|
413
|
+
value: str = Field(..., alias="value", description="Property value")
|
|
414
|
+
|
|
415
|
+
def to_dict(self):
|
|
416
|
+
"""Convert Property to dictionary with API aliases."""
|
|
417
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
class AgentData(CustomBaseModel):
|
|
421
|
+
"""
|
|
422
|
+
Represents the detailed configuration data for an agent.
|
|
423
|
+
|
|
424
|
+
:param prompt: dict - Prompt instructions, inputs, outputs, and examples for the agent.
|
|
425
|
+
:param llm_config: dict - Configuration parameters for the LLM (e.g., max tokens, timeout, temperature).
|
|
426
|
+
:param strategy_name: str - Strategy name used for the agent (e.g., Dynamic Prompting, Chain of Thought, Question Refinement, etc)
|
|
427
|
+
:param models: ModelList - List of models available for the agent.
|
|
428
|
+
:param resource_pools: Optional[List[ResourcePool]] - List of resource pools organizing tools and helper agents.
|
|
429
|
+
"""
|
|
430
|
+
prompt: Prompt = Field(..., alias="prompt")
|
|
431
|
+
llm_config: LlmConfig = Field(..., alias="llmConfig")
|
|
432
|
+
strategy_name: Optional[str] = Field("Dynamic Prompting", alias="strategyName")
|
|
433
|
+
models: Optional[Union[ModelList, List[Model]]] = Field(None, alias="models")
|
|
434
|
+
resource_pools: Optional[ResourcePoolList] = Field(None, alias="resourcePools", description="List of resource pools organizing tools and helper agents")
|
|
435
|
+
properties: Optional[List[Property]] = Field(None, alias="properties", description="List of agent properties")
|
|
436
|
+
|
|
437
|
+
@field_validator("prompt", mode="before")
|
|
438
|
+
@classmethod
|
|
439
|
+
def normalize_prompt(cls, value):
|
|
440
|
+
if isinstance(value, dict):
|
|
441
|
+
return Prompt.model_validate(value)
|
|
442
|
+
return value
|
|
443
|
+
|
|
444
|
+
@field_validator("llm_config", mode="before")
|
|
445
|
+
@classmethod
|
|
446
|
+
def normalize_llm_config(cls, value):
|
|
447
|
+
if isinstance(value, dict):
|
|
448
|
+
return LlmConfig.model_validate(value)
|
|
449
|
+
return value
|
|
450
|
+
|
|
451
|
+
@field_validator("models", mode="before")
|
|
452
|
+
@classmethod
|
|
453
|
+
def normalize_models(cls, value):
|
|
454
|
+
if value is None:
|
|
455
|
+
return None
|
|
456
|
+
if isinstance(value, ModelList):
|
|
457
|
+
return value
|
|
458
|
+
elif isinstance(value, list):
|
|
459
|
+
return ModelList(models=[Model.model_validate(item) if isinstance(item, dict) else item for item in value])
|
|
460
|
+
raise ValueError("models must be a ModelList or a list of Model instances/dictionaries")
|
|
461
|
+
|
|
462
|
+
@field_validator("resource_pools", mode="before")
|
|
463
|
+
@classmethod
|
|
464
|
+
def normalize_resource_pools(cls, value):
|
|
465
|
+
if isinstance(value, ResourcePoolList):
|
|
466
|
+
return value
|
|
467
|
+
elif isinstance(value, list):
|
|
468
|
+
return ResourcePoolList(resource_pools=[ResourcePool.model_validate(item) if isinstance(item, dict) else item for item in value])
|
|
469
|
+
return value
|
|
470
|
+
|
|
471
|
+
@field_validator("properties", mode="before")
|
|
472
|
+
@classmethod
|
|
473
|
+
def normalize_properties(cls, value):
|
|
474
|
+
if isinstance(value, list):
|
|
475
|
+
return [Property.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
476
|
+
return value
|
|
477
|
+
|
|
478
|
+
@model_validator(mode="after")
|
|
479
|
+
def validate_resource_pools_unique_names(self):
|
|
480
|
+
if self.resource_pools:
|
|
481
|
+
pools = self.resource_pools.resource_pools if isinstance(self.resource_pools, ResourcePoolList) else self.resource_pools
|
|
482
|
+
names = [pool.name for pool in pools]
|
|
483
|
+
if len(names) != len(set(names)):
|
|
484
|
+
raise ValueError("Resource pool names must be unique within agentData")
|
|
485
|
+
return self
|
|
486
|
+
|
|
487
|
+
def to_dict(self):
|
|
488
|
+
"""
|
|
489
|
+
Serializes the AgentData instance to a dictionary, ensuring each Model in models calls its to_dict method.
|
|
490
|
+
|
|
491
|
+
:return: dict - A dictionary representation of the agent data with aliases.
|
|
492
|
+
"""
|
|
493
|
+
result = {
|
|
494
|
+
"prompt": self.prompt.to_dict(),
|
|
495
|
+
"llmConfig": self.llm_config.to_dict(),
|
|
496
|
+
"strategyName": self.strategy_name,
|
|
497
|
+
"models": self.models.to_dict() if self.models else None,
|
|
498
|
+
"resourcePools": [pool.to_dict() for pool in self.resource_pools] if self.resource_pools else None,
|
|
499
|
+
"properties": [prop.to_dict() for prop in self.properties] if self.properties else None
|
|
500
|
+
}
|
|
501
|
+
return {k: v for k, v in result.items() if v is not None}
|
|
502
|
+
|
|
503
|
+
def __str__(self):
|
|
504
|
+
return str(self.to_dict())
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
class Agent(CustomBaseModel):
|
|
508
|
+
"""
|
|
509
|
+
Represents an agent configuration returned by the API.
|
|
510
|
+
|
|
511
|
+
:param id: str - Unique identifier for the agent.
|
|
512
|
+
:param status: Literal["active", "inactive"] - Current status of the agent.
|
|
513
|
+
:param name: str - Name of the agent.
|
|
514
|
+
:param access_scope: Literal["public", "private"] - Access scope of the agent.
|
|
515
|
+
:param public_name: Optional[str] - Public identifier for the agent, required if access_scope is "public".
|
|
516
|
+
:param avatar_image: Optional[str] - URL to the agent's avatar image.
|
|
517
|
+
:param description: str - Description of the agent's purpose.
|
|
518
|
+
:param job_description: Optional[str] - Detailed job description of the agent.
|
|
519
|
+
:param is_draft: bool - Indicates if the agent is in draft mode.
|
|
520
|
+
:param is_readonly: bool - Indicates if the agent is read-only.
|
|
521
|
+
:param revision: int - Revision number of the agent.
|
|
522
|
+
:param version: Optional[int] - Version number of the agent, if applicable.
|
|
523
|
+
:param agent_data: AgentData - Detailed configuration data for the agent.
|
|
524
|
+
"""
|
|
525
|
+
id: str = Field(None, alias="id")
|
|
526
|
+
status: Optional[Literal["active", "inactive", "pending"]] = Field("active", alias="status")
|
|
527
|
+
name: str = Field(..., alias="name")
|
|
528
|
+
access_scope: Literal["public", "private"] = Field("private", alias="accessScope")
|
|
529
|
+
public_name: Optional[str] = Field(None, alias="publicName")
|
|
530
|
+
avatar_image: Optional[str] = Field(None, alias="avatarImage")
|
|
531
|
+
description: Optional[str] = Field(None, alias="description")
|
|
532
|
+
job_description: Optional[str] = Field(None, alias="jobDescription")
|
|
533
|
+
is_draft: Optional[bool] = Field(True, alias="isDraft")
|
|
534
|
+
is_readonly: Optional[bool] = Field(False, alias="isReadonly")
|
|
535
|
+
revision: Optional[int] = Field(None, alias="revision")
|
|
536
|
+
version: Optional[Union[int | float]] = Field(None, alias="version")
|
|
537
|
+
sharing_scope: Optional[str] = Field(None, alias="sharingScope", description="Sharing scope of the agent")
|
|
538
|
+
permissions: Optional[Permission] = Field(None, alias="permissions", description="Permission settings")
|
|
539
|
+
effective_permissions: Optional[Permission] = Field(None, alias="effectivePermissions", description="Effective permission settings")
|
|
540
|
+
agent_data: Optional[AgentData] = Field(None, alias="agentData")
|
|
541
|
+
|
|
542
|
+
@field_validator("name")
|
|
543
|
+
@classmethod
|
|
544
|
+
def validate_name(cls, value: str) -> str:
|
|
545
|
+
if not value.strip():
|
|
546
|
+
raise ValueError("name cannot be blank")
|
|
547
|
+
if ":" in value or "/" in value:
|
|
548
|
+
raise ValueError("name cannot contain ':' or '/'")
|
|
549
|
+
return value
|
|
550
|
+
|
|
551
|
+
@field_validator("public_name")
|
|
552
|
+
@classmethod
|
|
553
|
+
def validate_public_name_format(cls, value: Optional[str], values: dict) -> Optional[str]:
|
|
554
|
+
access_scope = values.data.get("access_scope", "private")
|
|
555
|
+
if access_scope == "public" and not value:
|
|
556
|
+
raise ValueError("public_name is required if access_scope is 'public'")
|
|
557
|
+
if value and not all(c.isalnum() or c in ".-_" for c in value):
|
|
558
|
+
raise ValueError("public_name must contain only letters, numbers, periods, dashes, or underscores")
|
|
559
|
+
return value
|
|
560
|
+
|
|
561
|
+
@model_validator(mode="after")
|
|
562
|
+
def validate_agent_data_for_publication(self):
|
|
563
|
+
if self.is_draft is False and self.agent_data:
|
|
564
|
+
if not self.agent_data.models or len(self.agent_data.models) == 0:
|
|
565
|
+
raise ValueError("At least one valid model must be provided in agent_data.models for publication")
|
|
566
|
+
# if not (self.agent_data.prompt.instructions or self.agent_data.prompt.context): # TODO -> Review implementation of context vs instructions
|
|
567
|
+
if not self.agent_data.prompt.instructions:
|
|
568
|
+
raise ValueError("agent_data.prompt must have at least instructions for publication")
|
|
569
|
+
return self
|
|
570
|
+
|
|
571
|
+
@field_validator("agent_data", mode="before")
|
|
572
|
+
@classmethod
|
|
573
|
+
def normalize_agent_data(cls, value):
|
|
574
|
+
if isinstance(value, dict):
|
|
575
|
+
return AgentData.model_validate(value)
|
|
576
|
+
return value
|
|
577
|
+
|
|
578
|
+
@field_validator("permissions", mode="before")
|
|
579
|
+
@classmethod
|
|
580
|
+
def normalize_permissions(cls, value):
|
|
581
|
+
if isinstance(value, dict):
|
|
582
|
+
return Permission.model_validate(value)
|
|
583
|
+
return value
|
|
584
|
+
|
|
585
|
+
@field_validator("effective_permissions", mode="before")
|
|
586
|
+
@classmethod
|
|
587
|
+
def normalize_effective_permissions(cls, value):
|
|
588
|
+
if isinstance(value, dict):
|
|
589
|
+
return Permission.model_validate(value)
|
|
590
|
+
return value
|
|
591
|
+
|
|
592
|
+
@model_validator(mode="after")
|
|
593
|
+
def check_public_name(self):
|
|
594
|
+
"""
|
|
595
|
+
Validates that public_name is provided if access_scope is set to "public".
|
|
596
|
+
|
|
597
|
+
:raises ValueError: If access_scope is "public" but public_name is missing.
|
|
598
|
+
"""
|
|
599
|
+
if self.access_scope == "public" and not self.public_name:
|
|
600
|
+
raise ValueError("public_name is required if access_scope is public")
|
|
601
|
+
return self
|
|
602
|
+
|
|
603
|
+
def to_dict(self):
|
|
604
|
+
result = {
|
|
605
|
+
"id": self.id,
|
|
606
|
+
"status": self.status,
|
|
607
|
+
"name": self.name,
|
|
608
|
+
"accessScope": self.access_scope,
|
|
609
|
+
"publicName": self.public_name,
|
|
610
|
+
"avatarImage": self.avatar_image,
|
|
611
|
+
"description": self.description,
|
|
612
|
+
"jobDescription": self.job_description,
|
|
613
|
+
"isDraft": self.is_draft,
|
|
614
|
+
"isReadonly": self.is_readonly,
|
|
615
|
+
"revision": self.revision,
|
|
616
|
+
"version": self.version,
|
|
617
|
+
"sharingScope": self.sharing_scope,
|
|
618
|
+
"permissions": self.permissions.to_dict() if self.permissions else None,
|
|
619
|
+
"effectivePermissions": self.effective_permissions.to_dict() if self.effective_permissions else None,
|
|
620
|
+
"agentData": self.agent_data.to_dict() if self.agent_data else None
|
|
621
|
+
}
|
|
622
|
+
return {k: v for k, v in result.items() if v is not None}
|
|
623
|
+
|
|
624
|
+
def __str__(self):
|
|
625
|
+
return str(self.to_dict())
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
class AgentList(CustomBaseModel):
|
|
629
|
+
"""
|
|
630
|
+
Represents a list of agents returned by the API.
|
|
631
|
+
|
|
632
|
+
:param agents: List[Agent] - List of agent configurations.
|
|
633
|
+
"""
|
|
634
|
+
agents: List[Agent] = Field(..., alias="agents")
|
|
635
|
+
|
|
636
|
+
@field_validator("agents", mode="before")
|
|
637
|
+
@classmethod
|
|
638
|
+
def normalize_agents(cls, value):
|
|
639
|
+
if isinstance(value, list):
|
|
640
|
+
return [Agent.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
641
|
+
return value
|
|
642
|
+
|
|
643
|
+
def to_list(self):
|
|
644
|
+
return [agent.to_dict() for agent in self.agents] if self.agents else []
|
|
645
|
+
|
|
646
|
+
def __getitem__(self, index: int) -> Agent:
|
|
647
|
+
if self.agents is None:
|
|
648
|
+
raise IndexError("AgentList is empty")
|
|
649
|
+
return self.agents[index]
|
|
650
|
+
|
|
651
|
+
def __len__(self) -> int:
|
|
652
|
+
return len(self.agents) if self.agents else 0
|
|
653
|
+
|
|
654
|
+
def __iter__(self):
|
|
655
|
+
"""Make AgentList iterable over its agents."""
|
|
656
|
+
if self.agents is None:
|
|
657
|
+
return iter([])
|
|
658
|
+
return iter(self.agents)
|
|
659
|
+
|
|
660
|
+
def append(self, item: Agent) -> None:
|
|
661
|
+
"""Append an Agent instance to the agents list."""
|
|
662
|
+
if self.agents is None:
|
|
663
|
+
self.agents = []
|
|
664
|
+
self.agents.append(item)
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
class SharingLink(CustomBaseModel):
|
|
668
|
+
"""
|
|
669
|
+
Represents a sharing link for an agent.
|
|
670
|
+
|
|
671
|
+
:param agent_id: str - Unique identifier of the agent.
|
|
672
|
+
:param api_token: str - API token associated with the sharing link.
|
|
673
|
+
:param shared_link: str - The full URL of the sharing link.
|
|
674
|
+
"""
|
|
675
|
+
agent_id: str = Field(..., alias="agentId", description="Unique identifier of the agent")
|
|
676
|
+
api_token: str = Field(..., alias="apiToken", description="API token associated with the sharing link")
|
|
677
|
+
shared_link: str = Field(..., alias="sharedLink", description="The full URL of the sharing link")
|
|
678
|
+
|
|
679
|
+
def to_dict(self):
|
|
680
|
+
"""
|
|
681
|
+
Serializes the SharingLink instance to a dictionary.
|
|
682
|
+
|
|
683
|
+
:return: dict - A dictionary representation of the sharing link with aliases.
|
|
684
|
+
"""
|
|
685
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
686
|
+
|
|
687
|
+
def __str__(self):
|
|
688
|
+
return str(self.to_dict())
|
|
689
|
+
|
|
690
|
+
|
|
691
|
+
class ToolParameter(CustomBaseModel):
|
|
692
|
+
"""
|
|
693
|
+
Represents a parameter for a tool.
|
|
694
|
+
|
|
695
|
+
:param key: str - The identifier of the parameter.
|
|
696
|
+
:param data_type: str - The data type of the parameter (e.g., "String").
|
|
697
|
+
:param description: str - Description of the parameter's purpose.
|
|
698
|
+
:param is_required: bool - Whether the parameter is required.
|
|
699
|
+
:param type: Optional[str] - Type of parameter (e.g., "config"), defaults to None.
|
|
700
|
+
:param from_secret: Optional[bool] - Whether the value comes from a secret manager, defaults to None.
|
|
701
|
+
:param value: Optional[str] - The static value of the parameter, defaults to None.
|
|
702
|
+
"""
|
|
703
|
+
key: str = Field(..., alias="key", description="The identifier of the parameter")
|
|
704
|
+
data_type: str = Field(..., alias="dataType", description="The data type of the parameter (e.g., 'String')")
|
|
705
|
+
description: str = Field(..., alias="description", description="Description of the parameter's purpose")
|
|
706
|
+
is_required: bool = Field(..., alias="isRequired", description="Whether the parameter is required")
|
|
707
|
+
type: Optional[Literal["config", "app", "context"]] = Field("app", alias="type", description="Type of parameter (e.g., 'config')")
|
|
708
|
+
from_secret: Optional[bool] = Field(None, alias="fromSecret", description="Whether the value comes from a secret manager")
|
|
709
|
+
value: Optional[str] = Field(None, alias="value", description="The static value of the parameter")
|
|
710
|
+
|
|
711
|
+
def to_dict(self):
|
|
712
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
713
|
+
|
|
714
|
+
def __str__(self):
|
|
715
|
+
return str(self.to_dict())
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
class ToolMessage(CustomBaseModel):
|
|
719
|
+
"""
|
|
720
|
+
Represents a message (e.g., warning or error) in the tool response.
|
|
721
|
+
|
|
722
|
+
:param description: str - Description of the message.
|
|
723
|
+
:param type: str - Type of the message (e.g., "warning", "error").
|
|
724
|
+
"""
|
|
725
|
+
description: str = Field(..., alias="description", description="Description of the message")
|
|
726
|
+
type: str = Field(..., alias="type", description="Type of the message (e.g., 'warning', 'error')")
|
|
727
|
+
|
|
728
|
+
def to_dict(self):
|
|
729
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
730
|
+
|
|
731
|
+
def __str__(self):
|
|
732
|
+
return str(self.to_dict())
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
class Tool(CustomBaseModel):
|
|
736
|
+
"""
|
|
737
|
+
Represents a tool configuration, used for both input and output.
|
|
738
|
+
|
|
739
|
+
:param name: str - The name of the tool.
|
|
740
|
+
:param description: str - Description of the tool's purpose.
|
|
741
|
+
:param scope: str - The scope of the tool (e.g., "builtin", "external", "api").
|
|
742
|
+
:param parameters: List[ToolParameter] - List of parameters required by the tool.
|
|
743
|
+
:param access_scope: Optional[str] - The access scope of the tool ("public" or "private"), defaults to None.
|
|
744
|
+
:param public_name: Optional[str] - Public name of the tool, required if access_scope is "public", defaults to None.
|
|
745
|
+
:param icon: Optional[str] - URL for the tool's icon or avatar, defaults to None.
|
|
746
|
+
:param open_api: Optional[str] - URL where the OpenAPI specification can be loaded, defaults to None.
|
|
747
|
+
:param open_api_json: Optional[dict] - OpenAPI specification as a dictionary, defaults to None.
|
|
748
|
+
:param report_events: Optional[str] - Event reporting mode ("None", "All", "Start", "Finish", "Progress"), defaults to None.
|
|
749
|
+
:param id: Optional[str] - Unique identifier of the tool, defaults to None.
|
|
750
|
+
:param is_draft: Optional[bool] - Whether the tool is in draft mode, defaults to None.
|
|
751
|
+
:param messages: Optional[List[ToolMessage]] - List of messages (e.g., warnings or errors), defaults to None.
|
|
752
|
+
:param revision: Optional[int] - Revision number of the tool, defaults to None.
|
|
753
|
+
:param status: Optional[str] - Current status of the tool (e.g., "active"), defaults to None.
|
|
754
|
+
"""
|
|
755
|
+
name: str = Field(..., alias="name", description="The name of the tool")
|
|
756
|
+
description: Optional[str] = Field(None, alias="description", description="Description of the tool's purpose")
|
|
757
|
+
scope: str = Field("builtin", alias="scope", description="The scope of the tool (e.g., 'builtin', 'external', 'api')")
|
|
758
|
+
parameters: Optional[List[ToolParameter]] = Field(None, alias="parameters", description="List of parameters required by the tool")
|
|
759
|
+
access_scope: Optional[str] = Field(None, alias="accessScope", description="The access scope of the tool ('public' or 'private')")
|
|
760
|
+
public_name: Optional[str] = Field(None, alias="publicName", description="Public name of the tool, required if access_scope is 'public'")
|
|
761
|
+
icon: Optional[str] = Field(None, alias="icon", description="URL for the tool's icon or avatar")
|
|
762
|
+
open_api: Optional[str] = Field(None, alias="openApi", description="URL where the OpenAPI specification can be loaded")
|
|
763
|
+
open_api_json: Optional[dict] = Field(None, alias="openApiJson", description="OpenAPI specification as a dictionary")
|
|
764
|
+
report_events: Optional[Literal['None', 'All', 'Start', 'Finish', 'Progress']] = Field("None", alias="reportEvents", description="Event reporting mode ('None', 'All', 'Start', 'Finish', 'Progress')")
|
|
765
|
+
id: Optional[str] = Field(None, alias="id", description="Unique identifier of the tool")
|
|
766
|
+
is_draft: Optional[bool] = Field(None, alias="isDraft", description="Whether the tool is in draft mode")
|
|
767
|
+
messages: Optional[List[ToolMessage]] = Field(None, alias="messages", description="List of messages (e.g., warnings or errors)")
|
|
768
|
+
revision: Optional[int] = Field(None, alias="revision", description="Revision number of the tool")
|
|
769
|
+
status: Optional[str] = Field(None, alias="status", description="Current status of the tool (e.g., 'active')")
|
|
770
|
+
|
|
771
|
+
@field_validator("name")
|
|
772
|
+
@classmethod
|
|
773
|
+
def validate_name(cls, value: str) -> str:
|
|
774
|
+
if not value.strip():
|
|
775
|
+
raise ValueError("name cannot be blank")
|
|
776
|
+
if ":" in value or "/" in value:
|
|
777
|
+
raise ValueError("name cannot contain ':' or '/'")
|
|
778
|
+
# if not re.match(r'^[A-Za-z0-9_-]{1,64}$', value):
|
|
779
|
+
# raise ValueError(
|
|
780
|
+
# "name must contain only letters, numbers, underscores, or hyphens, and be 1-64 characters long")
|
|
781
|
+
return value
|
|
782
|
+
|
|
783
|
+
@field_validator("public_name")
|
|
784
|
+
@classmethod
|
|
785
|
+
def validate_public_name_format(cls, value: Optional[str], values: dict) -> Optional[str]:
|
|
786
|
+
access_scope = values.data.get("access_scope", "private")
|
|
787
|
+
if access_scope == "public" and not value:
|
|
788
|
+
raise ValueError("public_name is required if access_scope is 'public'")
|
|
789
|
+
if value and not all(c.isalnum() or c in ".-_" for c in value):
|
|
790
|
+
raise ValueError("public_name must contain only letters, numbers, periods, dashes, or underscores")
|
|
791
|
+
return value
|
|
792
|
+
|
|
793
|
+
@model_validator(mode="after")
|
|
794
|
+
def check_public_name(self):
|
|
795
|
+
if self.access_scope == "public" and not self.public_name:
|
|
796
|
+
raise ValueError("public_name is required if access_scope is 'public'")
|
|
797
|
+
return self
|
|
798
|
+
|
|
799
|
+
'''
|
|
800
|
+
@model_validator(mode="after")
|
|
801
|
+
def validate_api_tool_requirements(self):
|
|
802
|
+
if self.scope == "api" and not (self.open_api or self.open_api_json):
|
|
803
|
+
raise ValueError("For scope='api', either open_api or open_api_json must be provided")
|
|
804
|
+
if self.parameters:
|
|
805
|
+
param_keys = [p.key for p in self.parameters]
|
|
806
|
+
if len(param_keys) != len(set(param_keys)):
|
|
807
|
+
raise ValueError("All parameter keys must be unique within the tool")
|
|
808
|
+
return self
|
|
809
|
+
'''
|
|
810
|
+
|
|
811
|
+
@field_validator("parameters", mode="before")
|
|
812
|
+
@classmethod
|
|
813
|
+
def normalize_parameters(cls, value):
|
|
814
|
+
if isinstance(value, list):
|
|
815
|
+
return [ToolParameter.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
816
|
+
return value
|
|
817
|
+
|
|
818
|
+
@field_validator("messages", mode="before")
|
|
819
|
+
@classmethod
|
|
820
|
+
def normalize_messages(cls, value):
|
|
821
|
+
if isinstance(value, list):
|
|
822
|
+
return [ToolMessage.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
823
|
+
return value
|
|
824
|
+
|
|
825
|
+
def to_dict(self):
|
|
826
|
+
result = {
|
|
827
|
+
"name": self.name,
|
|
828
|
+
"description": self.description,
|
|
829
|
+
"scope": self.scope,
|
|
830
|
+
"parameters": [param.to_dict() for param in self.parameters] if self.parameters else None,
|
|
831
|
+
"accessScope": self.access_scope,
|
|
832
|
+
"publicName": self.public_name,
|
|
833
|
+
"icon": self.icon,
|
|
834
|
+
"openApi": self.open_api,
|
|
835
|
+
"openApiJson": self.open_api_json,
|
|
836
|
+
"reportEvents": self.report_events,
|
|
837
|
+
"id": self.id,
|
|
838
|
+
"isDraft": self.is_draft,
|
|
839
|
+
"messages": [msg.to_dict() for msg in self.messages] if self.messages else None,
|
|
840
|
+
"revision": self.revision,
|
|
841
|
+
"status": self.status
|
|
842
|
+
}
|
|
843
|
+
return {k: v for k, v in result.items() if v is not None}
|
|
844
|
+
|
|
845
|
+
def __str__(self):
|
|
846
|
+
return str(self.to_dict())
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
class ToolList(CustomBaseModel):
|
|
850
|
+
"""
|
|
851
|
+
Represents a list of Tool objects retrieved from an API response.
|
|
852
|
+
|
|
853
|
+
:param tools: List[Tool] - The list of tools.
|
|
854
|
+
"""
|
|
855
|
+
tools: List[Tool] = Field(..., alias="tools", description="The list of tools")
|
|
856
|
+
|
|
857
|
+
@field_validator("tools", mode="before")
|
|
858
|
+
@classmethod
|
|
859
|
+
def normalize_tools(cls, value):
|
|
860
|
+
if isinstance(value, list):
|
|
861
|
+
return [Tool.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
862
|
+
return value
|
|
863
|
+
|
|
864
|
+
def to_dict(self):
|
|
865
|
+
return {"tools": [tool.to_dict() for tool in self.tools]}
|
|
866
|
+
|
|
867
|
+
def __str__(self):
|
|
868
|
+
return str(self.to_dict())
|
|
869
|
+
|
|
870
|
+
def __getitem__(self, index: int) -> Tool:
|
|
871
|
+
if self.tools is None:
|
|
872
|
+
raise IndexError("ToolList is empty")
|
|
873
|
+
return self.tools[index]
|
|
874
|
+
|
|
875
|
+
def __len__(self) -> int:
|
|
876
|
+
return len(self.tools) if self.tools else 0
|
|
877
|
+
|
|
878
|
+
def __iter__(self):
|
|
879
|
+
"""Make ToolList iterable over its tools."""
|
|
880
|
+
if self.tools is None:
|
|
881
|
+
return iter([])
|
|
882
|
+
return iter(self.tools)
|
|
883
|
+
|
|
884
|
+
def append(self, item: Tool) -> None:
|
|
885
|
+
"""Append a Tool instance to the tools list."""
|
|
886
|
+
if self.tools is None:
|
|
887
|
+
self.tools = []
|
|
888
|
+
self.tools.append(item)
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
class LocalizedDescription(CustomBaseModel):
|
|
892
|
+
"""
|
|
893
|
+
Represents a localized description for a reasoning strategy.
|
|
894
|
+
|
|
895
|
+
:param language: str - The language of the description (e.g., "english", "spanish").
|
|
896
|
+
:param description: str - The description text in the specified language.
|
|
897
|
+
"""
|
|
898
|
+
language: str = Field(..., description="The language of the description")
|
|
899
|
+
description: str = Field(..., description="The description text in the specified language")
|
|
900
|
+
|
|
901
|
+
def to_dict(self):
|
|
902
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
class ReasoningStrategy(CustomBaseModel):
|
|
906
|
+
"""
|
|
907
|
+
Represents a reasoning strategy configuration.
|
|
908
|
+
|
|
909
|
+
:param name: str - The name of the reasoning strategy.
|
|
910
|
+
:param system_prompt: str - The system prompt for the reasoning strategy.
|
|
911
|
+
:param access_scope: str - The access scope of the strategy (e.g., "private", "public").
|
|
912
|
+
:param type: str - The type of the reasoning strategy (e.g., "addendum").
|
|
913
|
+
:param localized_descriptions: List[LocalizedDescription] - List of localized descriptions.
|
|
914
|
+
:param id: Optional[str] - Unique identifier of the strategy, set by the API on creation.
|
|
915
|
+
"""
|
|
916
|
+
name: str = Field(..., description="The name of the reasoning strategy")
|
|
917
|
+
system_prompt: Optional[str] = Field(None, alias="systemPrompt", description="The system prompt for the reasoning strategy")
|
|
918
|
+
access_scope: str = Field(..., alias="accessScope", description="The access scope of the strategy (e.g., 'private', 'public')")
|
|
919
|
+
type: str = Field(..., description="The type of the reasoning strategy (e.g., 'addendum')")
|
|
920
|
+
localized_descriptions: Optional[List[LocalizedDescription]] = Field(None, alias="localizedDescriptions", description="List of localized descriptions")
|
|
921
|
+
id: Optional[str] = Field(None, description="Unique identifier of the strategy, set by the API on creation")
|
|
922
|
+
|
|
923
|
+
@field_validator("localized_descriptions", mode="before")
|
|
924
|
+
@classmethod
|
|
925
|
+
def normalize_localized_descriptions(cls, value):
|
|
926
|
+
if isinstance(value, list):
|
|
927
|
+
return [LocalizedDescription.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
928
|
+
return value
|
|
929
|
+
|
|
930
|
+
def to_dict(self):
|
|
931
|
+
result = {
|
|
932
|
+
"name": self.name,
|
|
933
|
+
"systemPrompt": self.system_prompt,
|
|
934
|
+
"accessScope": self.access_scope,
|
|
935
|
+
"type": self.type,
|
|
936
|
+
"localizedDescriptions": [desc.to_dict() for desc in self.localized_descriptions] if isinstance(self.localized_descriptions, list) else None,
|
|
937
|
+
"id": self.id
|
|
938
|
+
}
|
|
939
|
+
return {k: v for k, v in result.items() if v is not None}
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
class ReasoningStrategyList(CustomBaseModel):
|
|
943
|
+
strategies: List[ReasoningStrategy] = Field(..., alias="strategies", description="The list of reasoning strategies")
|
|
944
|
+
|
|
945
|
+
@field_validator("strategies", mode="before")
|
|
946
|
+
@classmethod
|
|
947
|
+
def normalize_strategies(cls, value):
|
|
948
|
+
if isinstance(value, list):
|
|
949
|
+
return [ReasoningStrategy.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
950
|
+
return value
|
|
951
|
+
|
|
952
|
+
def to_dict(self):
|
|
953
|
+
return [strategy.to_dict() for strategy in self.strategies]
|
|
954
|
+
|
|
955
|
+
def __str__(self):
|
|
956
|
+
return str(self.to_dict())
|
|
957
|
+
|
|
958
|
+
def __getitem__(self, index: int) -> ReasoningStrategy:
|
|
959
|
+
if self.strategies is None:
|
|
960
|
+
raise IndexError("ReasoningStrategyList is empty")
|
|
961
|
+
return self.strategies[index]
|
|
962
|
+
|
|
963
|
+
def __len__(self) -> int:
|
|
964
|
+
return len(self.strategies) if self.strategies else 0
|
|
965
|
+
|
|
966
|
+
def __iter__(self):
|
|
967
|
+
"""Make ReasoningStrategyList iterable over its strategies."""
|
|
968
|
+
if self.strategies is None:
|
|
969
|
+
return iter([])
|
|
970
|
+
return iter(self.strategies)
|
|
971
|
+
|
|
972
|
+
def append(self, item: ReasoningStrategy) -> None:
|
|
973
|
+
"""Append a ReasoningStrategy instance to the strategies list."""
|
|
974
|
+
if self.strategies is None:
|
|
975
|
+
self.strategies = []
|
|
976
|
+
self.strategies.append(item)
|
|
977
|
+
|
|
978
|
+
|
|
979
|
+
class KnowledgeBase(CustomBaseModel):
|
|
980
|
+
id: Optional[str] = Field(None, description="Unique identifier of the knowledge base, set by API")
|
|
981
|
+
name: str = Field(..., description="Name of the knowledge base")
|
|
982
|
+
artifact_type_name: Optional[List[str]] = Field(None, alias="artifactTypeName", description="List of artifact type names")
|
|
983
|
+
artifacts: Optional[List[str]] = Field(None, description="List of artifact identifiers")
|
|
984
|
+
metadata: Optional[List[str]] = Field(None, description="List of metadata identifiers")
|
|
985
|
+
created_at: Optional[str] = Field(None, alias="createdAt", description="Timestamp when the knowledge base was created")
|
|
986
|
+
|
|
987
|
+
@field_validator("artifacts")
|
|
988
|
+
@classmethod
|
|
989
|
+
def validate_artifacts(cls, value: Optional[List[str]]) -> Optional[List[str]]:
|
|
990
|
+
if value is not None:
|
|
991
|
+
for artifact in value:
|
|
992
|
+
if not artifact.strip():
|
|
993
|
+
raise ValueError("Artifact identifiers cannot be empty")
|
|
994
|
+
return value
|
|
995
|
+
|
|
996
|
+
@field_validator("metadata")
|
|
997
|
+
@classmethod
|
|
998
|
+
def validate_metadata(cls, value: Optional[List[str]]) -> Optional[List[str]]:
|
|
999
|
+
if value is not None:
|
|
1000
|
+
for meta in value:
|
|
1001
|
+
if not meta.strip():
|
|
1002
|
+
raise ValueError("Metadata identifiers cannot be empty")
|
|
1003
|
+
return value
|
|
1004
|
+
|
|
1005
|
+
def to_dict(self):
|
|
1006
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
class KnowledgeBaseList(CustomBaseModel):
|
|
1010
|
+
knowledge_bases: List[KnowledgeBase] = Field(..., alias="knowledgeBases")
|
|
1011
|
+
|
|
1012
|
+
@field_validator("knowledge_bases", mode="before")
|
|
1013
|
+
@classmethod
|
|
1014
|
+
def normalize_knowledge_bases(cls, value):
|
|
1015
|
+
if isinstance(value, list):
|
|
1016
|
+
return [KnowledgeBase.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
1017
|
+
return value
|
|
1018
|
+
|
|
1019
|
+
def to_dict(self):
|
|
1020
|
+
return [kb.to_dict() for kb in self.knowledge_bases]
|
|
1021
|
+
|
|
1022
|
+
def __getitem__(self, index: int) -> KnowledgeBase:
|
|
1023
|
+
if self.knowledge_bases is None:
|
|
1024
|
+
raise IndexError("KnowledgeBaseList is empty")
|
|
1025
|
+
return self.knowledge_bases[index]
|
|
1026
|
+
|
|
1027
|
+
def __len__(self) -> int:
|
|
1028
|
+
return len(self.knowledge_bases) if self.knowledge_bases else 0
|
|
1029
|
+
|
|
1030
|
+
def __iter__(self):
|
|
1031
|
+
"""Make KnowledgeBaseList iterable over its knowledge bases."""
|
|
1032
|
+
if self.knowledge_bases is None:
|
|
1033
|
+
return iter([])
|
|
1034
|
+
return iter(self.knowledge_bases)
|
|
1035
|
+
|
|
1036
|
+
def append(self, item: KnowledgeBase) -> None:
|
|
1037
|
+
"""Append a KnowledgeBase instance to the knowledge_bases list."""
|
|
1038
|
+
if self.knowledge_bases is None:
|
|
1039
|
+
self.knowledge_bases = []
|
|
1040
|
+
self.knowledge_bases.append(item)
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
class AgenticActivity(CustomBaseModel):
|
|
1044
|
+
key: str = Field(..., description="Unique key for the activity")
|
|
1045
|
+
name: str = Field(..., description="Name of the activity")
|
|
1046
|
+
task_name: str = Field(..., alias="taskName", description="Name of the task")
|
|
1047
|
+
agent_name: str = Field(..., alias="agentName", description="Name of the agent")
|
|
1048
|
+
agent_revision_id: int = Field(..., alias="agentRevisionId", description="Revision ID of the agent")
|
|
1049
|
+
agent_id: Optional[str] = Field(None, alias="agentId", description="Unique identifier of the agent, set by API")
|
|
1050
|
+
task_id: Optional[str] = Field(None, alias="taskId", description="Unique identifier of the task, set by API")
|
|
1051
|
+
task_revision_id: Optional[int] = Field(None, alias="taskRevisionId", description="Revision ID of the task, set by API")
|
|
1052
|
+
|
|
1053
|
+
def to_dict(self):
|
|
1054
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
class ArtifactSignal(CustomBaseModel):
|
|
1058
|
+
key: str = Field(..., description="Unique key for the artifact signal")
|
|
1059
|
+
name: str = Field(..., description="Name of the artifact signal")
|
|
1060
|
+
handling_type: str = Field(..., alias="handlingType", description="Handling type (e.g., 'C')")
|
|
1061
|
+
artifact_type_name: List[str] = Field(..., alias="artifactTypeName", description="List of artifact type names")
|
|
1062
|
+
|
|
1063
|
+
def to_dict(self):
|
|
1064
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
class UserSignal(CustomBaseModel):
|
|
1068
|
+
key: str = Field(..., description="Unique key for the user signal")
|
|
1069
|
+
name: str = Field(..., description="Name of the user signal")
|
|
1070
|
+
|
|
1071
|
+
def to_dict(self):
|
|
1072
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
class Event(CustomBaseModel):
|
|
1076
|
+
key: str = Field(..., description="Unique key for the event")
|
|
1077
|
+
name: str = Field(..., description="Name of the event")
|
|
1078
|
+
|
|
1079
|
+
def to_dict(self):
|
|
1080
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
class SequenceFlow(CustomBaseModel):
|
|
1084
|
+
key: str = Field(..., description="Unique key for the sequence flow")
|
|
1085
|
+
source_key: str = Field(..., alias="sourceKey", description="Key of the source event/activity/signal")
|
|
1086
|
+
target_key: str = Field(..., alias="targetKey", description="Key of the target event/activity/signal")
|
|
1087
|
+
|
|
1088
|
+
def to_dict(self):
|
|
1089
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
1090
|
+
|
|
1091
|
+
|
|
1092
|
+
class Variable(CustomBaseModel):
|
|
1093
|
+
key: str = Field(..., description="Key of the variable")
|
|
1094
|
+
value: str = Field(..., description="Value of the variable")
|
|
1095
|
+
|
|
1096
|
+
def to_dict(self):
|
|
1097
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
1098
|
+
|
|
1099
|
+
|
|
1100
|
+
class VariableList(CustomBaseModel):
|
|
1101
|
+
variables: Optional[List[Variable]] = Field(None, description="List of variables")
|
|
1102
|
+
|
|
1103
|
+
@field_validator("variables", mode="before")
|
|
1104
|
+
@classmethod
|
|
1105
|
+
def normalize_variables(cls, value):
|
|
1106
|
+
if isinstance(value, list):
|
|
1107
|
+
return [Variable.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
1108
|
+
return value
|
|
1109
|
+
|
|
1110
|
+
def to_dict(self):
|
|
1111
|
+
return [var.to_dict() for var in self.variables] if self.variables else None
|
|
1112
|
+
|
|
1113
|
+
def __getitem__(self, index: int) -> Variable:
|
|
1114
|
+
if self.variables is None:
|
|
1115
|
+
raise IndexError("VariableList is empty")
|
|
1116
|
+
return self.variables[index]
|
|
1117
|
+
|
|
1118
|
+
def __len__(self) -> int:
|
|
1119
|
+
return len(self.variables) if self.variables else 0
|
|
1120
|
+
|
|
1121
|
+
def __iter__(self) -> Iterator[Variable]:
|
|
1122
|
+
"""Make VariableList iterable over its variables."""
|
|
1123
|
+
if self.variables is None:
|
|
1124
|
+
return iter([])
|
|
1125
|
+
return iter(self.variables)
|
|
1126
|
+
|
|
1127
|
+
def append(self, item: Variable) -> None:
|
|
1128
|
+
"""Append a Variable instance to the variables list."""
|
|
1129
|
+
if self.variables is None:
|
|
1130
|
+
self.variables = []
|
|
1131
|
+
self.variables.append(item)
|
|
1132
|
+
|
|
1133
|
+
|
|
1134
|
+
class AgenticProcess(CustomBaseModel):
|
|
1135
|
+
key: Optional[str] = Field(None, description="Unique key for the process")
|
|
1136
|
+
name: str = Field(..., description="Name of the process")
|
|
1137
|
+
description: Optional[str] = Field(None, description="Description of the process")
|
|
1138
|
+
kb: Optional[KnowledgeBase] = Field(None, description="Knowledge base configuration")
|
|
1139
|
+
agentic_activities: Optional[List[AgenticActivity]] = Field(None, alias="agenticActivities", description="List of agentic activities")
|
|
1140
|
+
artifact_signals: Optional[List[ArtifactSignal]] = Field(None, alias="artifactSignals", description="List of artifact signals")
|
|
1141
|
+
user_signals: Optional[List[UserSignal]] = Field(None, alias="userSignals", description="List of user signals")
|
|
1142
|
+
start_event: Optional[Event] = Field(None, alias="startEvent", description="Start event of the process")
|
|
1143
|
+
end_event: Optional[Event] = Field(None, alias="endEvent", description="End event of the process")
|
|
1144
|
+
sequence_flows: Optional[List[SequenceFlow]] = Field(None, alias="sequenceFlows", description="List of sequence flows")
|
|
1145
|
+
variables: Optional[VariableList] = Field(None, alias="variables", description="List of variables")
|
|
1146
|
+
id: Optional[str] = Field(None, description="Unique identifier of the process, set by API")
|
|
1147
|
+
status: Optional[str] = Field(None, alias="status", description="Status of the process (e.g., 'active')")
|
|
1148
|
+
version_id: Optional[int] = Field(None, alias="versionId", description="Version ID of the process")
|
|
1149
|
+
is_draft: Optional[bool] = Field(None, alias="isDraft", description="Whether the process is a draft")
|
|
1150
|
+
revision: Optional[int] = Field(None, description="Revision number of the process")
|
|
1151
|
+
|
|
1152
|
+
@field_validator("name")
|
|
1153
|
+
@classmethod
|
|
1154
|
+
def validate_name(cls, value: str) -> str:
|
|
1155
|
+
if not value.strip():
|
|
1156
|
+
raise ValueError("name cannot be blank")
|
|
1157
|
+
if ":" in value or "/" in value:
|
|
1158
|
+
raise ValueError("name cannot contain ':' or '/'")
|
|
1159
|
+
return value
|
|
1160
|
+
|
|
1161
|
+
@field_validator("kb", mode="before")
|
|
1162
|
+
@classmethod
|
|
1163
|
+
def normalize_kb(cls, value):
|
|
1164
|
+
if isinstance(value, dict):
|
|
1165
|
+
return KnowledgeBase.model_validate(value)
|
|
1166
|
+
return value
|
|
1167
|
+
|
|
1168
|
+
@field_validator("agentic_activities", mode="before")
|
|
1169
|
+
@classmethod
|
|
1170
|
+
def normalize_agentic_activities(cls, value):
|
|
1171
|
+
if isinstance(value, list):
|
|
1172
|
+
return [AgenticActivity.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
1173
|
+
return value
|
|
1174
|
+
|
|
1175
|
+
@field_validator("artifact_signals", mode="before")
|
|
1176
|
+
@classmethod
|
|
1177
|
+
def normalize_artifact_signals(cls, value):
|
|
1178
|
+
if isinstance(value, list):
|
|
1179
|
+
return [ArtifactSignal.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
1180
|
+
return value
|
|
1181
|
+
|
|
1182
|
+
@field_validator("user_signals", mode="before")
|
|
1183
|
+
@classmethod
|
|
1184
|
+
def normalize_user_signals(cls, value):
|
|
1185
|
+
if isinstance(value, list):
|
|
1186
|
+
return [UserSignal.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
1187
|
+
return value
|
|
1188
|
+
|
|
1189
|
+
@field_validator("start_event", mode="before")
|
|
1190
|
+
@classmethod
|
|
1191
|
+
def normalize_start_event(cls, value):
|
|
1192
|
+
if isinstance(value, dict):
|
|
1193
|
+
return Event.model_validate(value)
|
|
1194
|
+
return value
|
|
1195
|
+
|
|
1196
|
+
@field_validator("end_event", mode="before")
|
|
1197
|
+
@classmethod
|
|
1198
|
+
def normalize_end_event(cls, value):
|
|
1199
|
+
if isinstance(value, dict):
|
|
1200
|
+
return Event.model_validate(value)
|
|
1201
|
+
return value
|
|
1202
|
+
|
|
1203
|
+
@field_validator("sequence_flows", mode="before")
|
|
1204
|
+
@classmethod
|
|
1205
|
+
def normalize_sequence_flows(cls, value):
|
|
1206
|
+
if isinstance(value, list):
|
|
1207
|
+
return [SequenceFlow.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
1208
|
+
return value
|
|
1209
|
+
|
|
1210
|
+
@field_validator("variables", mode="before")
|
|
1211
|
+
@classmethod
|
|
1212
|
+
def normalize_variables(cls, value):
|
|
1213
|
+
"""
|
|
1214
|
+
Normalizes the variables input to a VariableList instance.
|
|
1215
|
+
|
|
1216
|
+
:param value: Union[VariableList, List[Variable]] - The input value for variables.
|
|
1217
|
+
:return: VariableList - A VariableList instance containing the models.
|
|
1218
|
+
"""
|
|
1219
|
+
if isinstance(value, VariableList):
|
|
1220
|
+
return value
|
|
1221
|
+
elif isinstance(value, (list, tuple)):
|
|
1222
|
+
return VariableList(variables=[Variable.model_validate(item) if isinstance(item, dict) else item for item in value])
|
|
1223
|
+
elif value is None:
|
|
1224
|
+
return VariableList(variables=[])
|
|
1225
|
+
|
|
1226
|
+
raise ValueError("variables must be a VariableList or a list of Variable instances")
|
|
1227
|
+
|
|
1228
|
+
def to_dict(self):
|
|
1229
|
+
"""
|
|
1230
|
+
Serializes the AgenticProcess instance to a dictionary, explicitly mapping fields to their aliases
|
|
1231
|
+
and invoking to_dict for nested objects in lists.
|
|
1232
|
+
|
|
1233
|
+
:return: dict - A dictionary representation of the process with aliases, excluding None values.
|
|
1234
|
+
"""
|
|
1235
|
+
result = {
|
|
1236
|
+
"key": self.key,
|
|
1237
|
+
"name": self.name,
|
|
1238
|
+
"description": self.description,
|
|
1239
|
+
"kb": self.kb.to_dict() if self.kb else None,
|
|
1240
|
+
"agenticActivities": [activity.to_dict() for activity in self.agentic_activities] if self.agentic_activities else None,
|
|
1241
|
+
"artifactSignals": [signal.to_dict() for signal in self.artifact_signals] if self.artifact_signals else None,
|
|
1242
|
+
"userSignals": [signal.to_dict() for signal in self.user_signals] if self.user_signals else None,
|
|
1243
|
+
"startEvent": self.start_event.to_dict() if self.start_event else None,
|
|
1244
|
+
"endEvent": self.end_event.to_dict() if self.end_event else None,
|
|
1245
|
+
"sequenceFlows": [flow.to_dict() for flow in self.sequence_flows] if self.sequence_flows else None,
|
|
1246
|
+
"variables": self.variables.to_dict() if self.variables else None,
|
|
1247
|
+
"id": self.id,
|
|
1248
|
+
"status": self.status,
|
|
1249
|
+
"versionId": self.version_id,
|
|
1250
|
+
"isDraft": self.is_draft,
|
|
1251
|
+
"revision": self.revision
|
|
1252
|
+
}
|
|
1253
|
+
return {k: v for k, v in result.items() if v is not None}
|
|
1254
|
+
|
|
1255
|
+
|
|
1256
|
+
class ArtifactType(CustomBaseModel):
|
|
1257
|
+
"""
|
|
1258
|
+
Represents an artifact type configuration for a task.
|
|
1259
|
+
|
|
1260
|
+
:param name: str - Name of the artifact type.
|
|
1261
|
+
:param description: str - Description of the artifact type.
|
|
1262
|
+
:param is_required: bool - Whether the artifact is required.
|
|
1263
|
+
:param usage_type: str - Usage type of the artifact (e.g., 'input', 'output').
|
|
1264
|
+
:param artifact_variable_key: str - Variable key for the artifact in the task.
|
|
1265
|
+
"""
|
|
1266
|
+
name: str = Field(..., alias="name", description="Name of the artifact type")
|
|
1267
|
+
description: Optional[str] = Field(None, alias="description", description="Description of the artifact type")
|
|
1268
|
+
is_required: Optional[bool] = Field(False, alias="isRequired", description="Whether the artifact is required")
|
|
1269
|
+
usage_type: str = Field(..., alias="usageType", description="Usage type of the artifact (e.g., 'input', 'output')")
|
|
1270
|
+
artifact_variable_key: Optional[str] = Field(None, alias="artifactVariableKey", description="Variable key for the artifact in the task")
|
|
1271
|
+
|
|
1272
|
+
def to_dict(self):
|
|
1273
|
+
"""
|
|
1274
|
+
Serializes the ArtifactType instance to a dictionary.
|
|
1275
|
+
|
|
1276
|
+
:return: dict - A dictionary representation of the artifact type with aliases.
|
|
1277
|
+
"""
|
|
1278
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
1279
|
+
|
|
1280
|
+
|
|
1281
|
+
class ArtifactTypeList(CustomBaseModel):
|
|
1282
|
+
"""
|
|
1283
|
+
Represents a list of ArtifactType objects.
|
|
1284
|
+
|
|
1285
|
+
:param artifact_types: List[ArtifactType] - The list of artifact types.
|
|
1286
|
+
"""
|
|
1287
|
+
artifact_types: Optional[List[ArtifactType]] = Field(None, description="List of artifact types")
|
|
1288
|
+
|
|
1289
|
+
@field_validator("artifact_types", mode="before")
|
|
1290
|
+
@classmethod
|
|
1291
|
+
def normalize_artifact_types(cls, value):
|
|
1292
|
+
if isinstance(value, list):
|
|
1293
|
+
return [ArtifactType.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
1294
|
+
return value
|
|
1295
|
+
|
|
1296
|
+
def to_dict(self):
|
|
1297
|
+
"""
|
|
1298
|
+
Serializes the ArtifactTypeList instance to a list of dictionaries.
|
|
1299
|
+
|
|
1300
|
+
:return: List[dict] - A list of dictionary representations of the artifact types.
|
|
1301
|
+
"""
|
|
1302
|
+
return [artifact.to_dict() for artifact in self.artifact_types] if self.artifact_types else None
|
|
1303
|
+
|
|
1304
|
+
def __getitem__(self, index: int) -> ArtifactType:
|
|
1305
|
+
if self.artifact_types is None:
|
|
1306
|
+
raise IndexError("ArtifactTypeList is empty")
|
|
1307
|
+
return self.artifact_types[index]
|
|
1308
|
+
|
|
1309
|
+
def __len__(self) -> int:
|
|
1310
|
+
return len(self.artifact_types) if self.artifact_types else 0
|
|
1311
|
+
|
|
1312
|
+
def __iter__(self) -> Iterator[ArtifactType]:
|
|
1313
|
+
"""Make ArtifactTypeList iterable over its artifact_types."""
|
|
1314
|
+
if self.artifact_types is None:
|
|
1315
|
+
return iter([])
|
|
1316
|
+
return iter(self.artifact_types)
|
|
1317
|
+
|
|
1318
|
+
def append(self, item: ArtifactType) -> None:
|
|
1319
|
+
"""Append an ArtifactType instance to the artifact_types list."""
|
|
1320
|
+
if self.artifact_types is None:
|
|
1321
|
+
self.artifact_types = []
|
|
1322
|
+
self.artifact_types.append(item)
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
class Task(CustomBaseModel):
|
|
1326
|
+
"""
|
|
1327
|
+
Represents a task configuration used for both input and output.
|
|
1328
|
+
|
|
1329
|
+
:param name: str - Required name of the task, must be unique within the project and exclude ':' or '/'.
|
|
1330
|
+
:param description: Optional[str] - Description of what the task does, for user understanding (not used by agents).
|
|
1331
|
+
:param title_template: Optional[str] - Template for naming task instances (e.g., 'specs for {{issue}}').
|
|
1332
|
+
:param id: Optional[str] - Unique identifier of the task, set by API or provided in insert mode for custom ID.
|
|
1333
|
+
:param prompt_data: Optional[Prompt] - Prompt configuration (same structure as AgentData prompt), combined with agent prompt during execution.
|
|
1334
|
+
:param artifact_types: Optional[List[dict]] - List of artifact types with 'name', 'description', 'isRequired', 'usageType', and 'artifactVariableKey'.
|
|
1335
|
+
:param is_draft: Optional[bool] - Whether the task is in draft mode.
|
|
1336
|
+
:param revision: Optional[int] - Revision number of the task.
|
|
1337
|
+
:param version: Optional[int] - Version number of the task.
|
|
1338
|
+
:param status: Optional[str] - Current status of the task (e.g., 'active').
|
|
1339
|
+
"""
|
|
1340
|
+
name: str = Field(..., description="Name of the task")
|
|
1341
|
+
description: Optional[str] = Field(None, description="Description of the task")
|
|
1342
|
+
title_template: Optional[str] = Field(None, alias="titleTemplate", description="Title template for the task")
|
|
1343
|
+
id: Optional[str] = Field(None, description="Unique identifier of the task, set by API")
|
|
1344
|
+
prompt_data: Optional[Prompt] = Field(None, alias="promptData", description="Prompt configuration for the task, combined with agent prompt during execution")
|
|
1345
|
+
artifact_types: Optional[Union[List[Dict[str, Any]], List[ArtifactType], ArtifactTypeList]] = Field(None, alias="artifactTypes", description="List of artifact types for the task")
|
|
1346
|
+
is_draft: Optional[bool] = Field(None, alias="isDraft", description="Whether the task is a draft")
|
|
1347
|
+
revision: Optional[int] = Field(None, description="Revision number of the task")
|
|
1348
|
+
version: Optional[int] = Field(None, description="Version number of the task")
|
|
1349
|
+
status: Optional[str] = Field(None, description="Status of the task (e.g., 'active')")
|
|
1350
|
+
|
|
1351
|
+
@field_validator("name")
|
|
1352
|
+
@classmethod
|
|
1353
|
+
def validate_name(cls, value: str) -> str:
|
|
1354
|
+
"""
|
|
1355
|
+
Ensures the task name does not contain forbidden characters ':' or '/'.
|
|
1356
|
+
|
|
1357
|
+
:param value: str - The name to validate.
|
|
1358
|
+
:return: str - The validated name.
|
|
1359
|
+
:raises ValueError: If the name contains ':' or '/'.
|
|
1360
|
+
"""
|
|
1361
|
+
if not value.strip():
|
|
1362
|
+
raise ValueError("name cannot be blank")
|
|
1363
|
+
if ":" in value or "/" in value:
|
|
1364
|
+
raise ValueError("Task name cannot contain ':' or '/'")
|
|
1365
|
+
return value
|
|
1366
|
+
|
|
1367
|
+
@field_validator("prompt_data", mode="before")
|
|
1368
|
+
@classmethod
|
|
1369
|
+
def normalize_prompt_data(cls, value: Union[Prompt, Dict[str, Any], None]) -> Optional[Prompt]:
|
|
1370
|
+
"""
|
|
1371
|
+
Normalizes the prompt_data input to a Prompt instance.
|
|
1372
|
+
|
|
1373
|
+
:param value: Union[Prompt, Dict[str, Any], None] - The input value for prompt_data.
|
|
1374
|
+
:return: Optional[Prompt] - A Prompt instance or None if the input is None.
|
|
1375
|
+
:raises ValueError: If the value is neither a Prompt, dict, nor None.
|
|
1376
|
+
"""
|
|
1377
|
+
if isinstance(value, Prompt):
|
|
1378
|
+
return value
|
|
1379
|
+
elif isinstance(value, dict):
|
|
1380
|
+
return Prompt.model_validate(value)
|
|
1381
|
+
elif value is None:
|
|
1382
|
+
return None
|
|
1383
|
+
raise ValueError("prompt_data must be a Prompt instance, a dictionary, or None")
|
|
1384
|
+
|
|
1385
|
+
@field_validator("artifact_types", mode="before")
|
|
1386
|
+
@classmethod
|
|
1387
|
+
def normalize_artifact_types(cls, value: Union[List[Dict[str, Any]], List[ArtifactType], ArtifactTypeList, None]) -> Optional[ArtifactTypeList]:
|
|
1388
|
+
"""
|
|
1389
|
+
Normalizes the artifact_types input to an ArtifactTypeList instance.
|
|
1390
|
+
|
|
1391
|
+
:param value: Union[List[Dict[str, Any]], List[ArtifactType], ArtifactTypeList, None] - The input value for artifact_types.
|
|
1392
|
+
:return: Optional[ArtifactTypeList] - An ArtifactTypeList instance or None if the input is None.
|
|
1393
|
+
:raises ValueError: If the value is not a valid input type.
|
|
1394
|
+
"""
|
|
1395
|
+
if isinstance(value, ArtifactTypeList):
|
|
1396
|
+
return value
|
|
1397
|
+
elif isinstance(value, list):
|
|
1398
|
+
artifact_list = []
|
|
1399
|
+
for item in value:
|
|
1400
|
+
if isinstance(item, dict):
|
|
1401
|
+
artifact_list.append(ArtifactType.model_validate(item))
|
|
1402
|
+
elif isinstance(item, ArtifactType):
|
|
1403
|
+
artifact_list.append(item)
|
|
1404
|
+
else:
|
|
1405
|
+
raise ValueError("artifact_types list items must be dictionaries or ArtifactType instances")
|
|
1406
|
+
return ArtifactTypeList(artifact_types=artifact_list)
|
|
1407
|
+
elif value is None:
|
|
1408
|
+
return None
|
|
1409
|
+
raise ValueError("artifact_types must be an ArtifactTypeList, a list of dictionaries/ArtifactType, or None")
|
|
1410
|
+
|
|
1411
|
+
@model_validator(mode="after")
|
|
1412
|
+
def validate_artifact_types_constraints(self):
|
|
1413
|
+
if self.artifact_types and self.artifact_types.artifact_types:
|
|
1414
|
+
for artifact in self.artifact_types.artifact_types:
|
|
1415
|
+
if artifact.artifact_variable_key and len(artifact.artifact_variable_key) > 20:
|
|
1416
|
+
raise ValueError(
|
|
1417
|
+
f"artifactVariableKey '{artifact.artifact_variable_key}' must be 20 characters or less")
|
|
1418
|
+
if artifact.usage_type not in ["input", "output"]:
|
|
1419
|
+
raise ValueError(f"usageType must be 'input' or 'output', got '{artifact.usage_type}'")
|
|
1420
|
+
return self
|
|
1421
|
+
|
|
1422
|
+
def to_dict(self):
|
|
1423
|
+
"""
|
|
1424
|
+
Serializes the Task instance to a dictionary, using aliases and excluding None values.
|
|
1425
|
+
|
|
1426
|
+
:return: dict - A dictionary representation of the task configuration.
|
|
1427
|
+
"""
|
|
1428
|
+
result = {
|
|
1429
|
+
"name": self.name,
|
|
1430
|
+
"description": self.description,
|
|
1431
|
+
"titleTemplate": self.title_template,
|
|
1432
|
+
"id": self.id,
|
|
1433
|
+
"promptData": self.prompt_data.to_dict() if self.prompt_data else None,
|
|
1434
|
+
"artifactTypes": self.artifact_types.to_dict() if self.artifact_types else None,
|
|
1435
|
+
"isDraft": self.is_draft,
|
|
1436
|
+
"revision": self.revision,
|
|
1437
|
+
"version": self.version,
|
|
1438
|
+
"status": self.status
|
|
1439
|
+
}
|
|
1440
|
+
return {k: v for k, v in result.items() if v is not None}
|
|
1441
|
+
|
|
1442
|
+
def __str__(self):
|
|
1443
|
+
return str(self.to_dict())
|
|
1444
|
+
|
|
1445
|
+
|
|
1446
|
+
class AgenticProcessList(CustomBaseModel):
|
|
1447
|
+
processes: List[AgenticProcess] = Field(..., alias="processes", description="List of agentic processes")
|
|
1448
|
+
|
|
1449
|
+
@field_validator("processes", mode="before")
|
|
1450
|
+
@classmethod
|
|
1451
|
+
def normalize_processes(cls, value):
|
|
1452
|
+
if isinstance(value, list):
|
|
1453
|
+
return [AgenticProcess.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
1454
|
+
return value
|
|
1455
|
+
|
|
1456
|
+
def to_dict(self):
|
|
1457
|
+
return {"processes": [process.to_dict() for process in self.processes]}
|
|
1458
|
+
|
|
1459
|
+
def __getitem__(self, index: int) -> AgenticProcess:
|
|
1460
|
+
if self.processes is None:
|
|
1461
|
+
raise IndexError("AgenticProcessList is empty")
|
|
1462
|
+
return self.processes[index]
|
|
1463
|
+
|
|
1464
|
+
def __len__(self) -> int:
|
|
1465
|
+
return len(self.processes) if self.processes else 0
|
|
1466
|
+
|
|
1467
|
+
def __iter__(self):
|
|
1468
|
+
"""Make AgenticProcessList iterable over its processes."""
|
|
1469
|
+
if self.processes is None:
|
|
1470
|
+
return iter([])
|
|
1471
|
+
return iter(self.processes)
|
|
1472
|
+
|
|
1473
|
+
def append(self, item: AgenticProcess) -> None:
|
|
1474
|
+
"""Append an AgenticProcess instance to the processes list."""
|
|
1475
|
+
if self.processes is None:
|
|
1476
|
+
self.processes = []
|
|
1477
|
+
self.processes.append(item)
|
|
1478
|
+
|
|
1479
|
+
|
|
1480
|
+
class TaskList(CustomBaseModel):
|
|
1481
|
+
tasks: List[Task] = Field(..., alias="tasks", description="List of tasks")
|
|
1482
|
+
|
|
1483
|
+
@field_validator("tasks", mode="before")
|
|
1484
|
+
@classmethod
|
|
1485
|
+
def normalize_tasks(cls, value):
|
|
1486
|
+
if isinstance(value, list):
|
|
1487
|
+
return [Task.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
1488
|
+
return value
|
|
1489
|
+
|
|
1490
|
+
def to_dict(self):
|
|
1491
|
+
return [task.to_dict() for task in self.tasks]
|
|
1492
|
+
|
|
1493
|
+
def __getitem__(self, index: int) -> Task:
|
|
1494
|
+
if self.tasks is None:
|
|
1495
|
+
raise IndexError("TaskList is empty")
|
|
1496
|
+
return self.tasks[index]
|
|
1497
|
+
|
|
1498
|
+
def __len__(self) -> int:
|
|
1499
|
+
return len(self.tasks) if self.tasks else 0
|
|
1500
|
+
|
|
1501
|
+
def __iter__(self):
|
|
1502
|
+
"""Make TaskList iterable over its tasks."""
|
|
1503
|
+
if self.tasks is None:
|
|
1504
|
+
return iter([])
|
|
1505
|
+
return iter(self.tasks)
|
|
1506
|
+
|
|
1507
|
+
def append(self, item: Task) -> None:
|
|
1508
|
+
"""Append a Task instance to the tasks list."""
|
|
1509
|
+
if self.tasks is None:
|
|
1510
|
+
self.tasks = []
|
|
1511
|
+
self.tasks.append(item)
|
|
1512
|
+
|
|
1513
|
+
|
|
1514
|
+
class ProcessInstance(CustomBaseModel):
|
|
1515
|
+
id: Optional[str] = Field(None, alias="id", description="Unique identifier of the process instance, set by API")
|
|
1516
|
+
process: AgenticProcess = Field(..., alias="process", description="The process configuration")
|
|
1517
|
+
created_at: Optional[str] = Field(None, alias="createdAt", description="Timestamp when the instance was created")
|
|
1518
|
+
subject: str = Field(..., description="Subject of the instance")
|
|
1519
|
+
variables: Optional[Union[List[Variable] | VariableList]] = Field(None, alias="variables", description="List of instance variables")
|
|
1520
|
+
status: Optional[str] = Field(None, description="Status of the instance (e.g., 'active', 'completed')")
|
|
1521
|
+
|
|
1522
|
+
@field_validator("process", mode="before")
|
|
1523
|
+
@classmethod
|
|
1524
|
+
def normalize_process(cls, value):
|
|
1525
|
+
"""
|
|
1526
|
+
Normalizes the process input to an AgenticProcess instance if it's a dictionary.
|
|
1527
|
+
|
|
1528
|
+
:param value: The input value for process (dict or AgenticProcess).
|
|
1529
|
+
:return: AgenticProcess - An AgenticProcess instance.
|
|
1530
|
+
:raises ValueError: If the value is neither a dict nor an AgenticProcess.
|
|
1531
|
+
"""
|
|
1532
|
+
if isinstance(value, dict):
|
|
1533
|
+
return AgenticProcess.model_validate(value)
|
|
1534
|
+
elif isinstance(value, AgenticProcess):
|
|
1535
|
+
return value
|
|
1536
|
+
raise ValueError("process must be a dictionary or an AgenticProcess instance")
|
|
1537
|
+
|
|
1538
|
+
@field_validator("variables", mode="before")
|
|
1539
|
+
@classmethod
|
|
1540
|
+
def normalize_variables(cls, value):
|
|
1541
|
+
"""
|
|
1542
|
+
Normalizes the variables input to a VariableList instance.
|
|
1543
|
+
|
|
1544
|
+
:param value: Union[VariableList, List[Variable]] - The input value for variables.
|
|
1545
|
+
:return: VariableList - A VariableList instance containing the models.
|
|
1546
|
+
"""
|
|
1547
|
+
if isinstance(value, VariableList):
|
|
1548
|
+
return value
|
|
1549
|
+
elif isinstance(value, (list, tuple)):
|
|
1550
|
+
return VariableList(variables=[Variable.model_validate(item) if isinstance(item, dict) else item for item in value])
|
|
1551
|
+
elif value is None:
|
|
1552
|
+
return VariableList(variables=[])
|
|
1553
|
+
|
|
1554
|
+
raise ValueError("variables must be a VariableList or a list of Variable instances")
|
|
1555
|
+
|
|
1556
|
+
def to_dict(self):
|
|
1557
|
+
result = {
|
|
1558
|
+
"id": self.id,
|
|
1559
|
+
"process": self.process.to_dict() if self.process else None,
|
|
1560
|
+
"createdAt": self.created_at,
|
|
1561
|
+
"subject": self.subject,
|
|
1562
|
+
"variables": self.variables.to_dict() if self.variables else None,
|
|
1563
|
+
"status": self.status,
|
|
1564
|
+
}
|
|
1565
|
+
return {k: v for k, v in result.items() if v is not None}
|
|
1566
|
+
|
|
1567
|
+
|
|
1568
|
+
class ProcessInstanceList(CustomBaseModel):
|
|
1569
|
+
instances: List[ProcessInstance] = Field(..., alias="instances", description="List of process instances")
|
|
1570
|
+
|
|
1571
|
+
@field_validator("instances", mode="before")
|
|
1572
|
+
@classmethod
|
|
1573
|
+
def normalize_instances(cls, value):
|
|
1574
|
+
if isinstance(value, list):
|
|
1575
|
+
return [ProcessInstance.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
1576
|
+
return value
|
|
1577
|
+
|
|
1578
|
+
def to_dict(self):
|
|
1579
|
+
return [instance.to_dict() for instance in self.instances] if self.instances else None
|
|
1580
|
+
|
|
1581
|
+
def __getitem__(self, index: int) -> ProcessInstance:
|
|
1582
|
+
if self.instances is None:
|
|
1583
|
+
raise IndexError("ProcessInstanceList is empty")
|
|
1584
|
+
return self.instances[index]
|
|
1585
|
+
|
|
1586
|
+
def __len__(self) -> int:
|
|
1587
|
+
return len(self.instances) if self.instances else 0
|
|
1588
|
+
|
|
1589
|
+
def __iter__(self):
|
|
1590
|
+
"""Make ProcessInstanceList iterable over its instances."""
|
|
1591
|
+
if self.instances is None:
|
|
1592
|
+
return iter([])
|
|
1593
|
+
return iter(self.instances)
|
|
1594
|
+
|
|
1595
|
+
def append(self, item: ProcessInstance) -> None:
|
|
1596
|
+
"""Append a ProcessInstance instance to the instances list."""
|
|
1597
|
+
if self.instances is None:
|
|
1598
|
+
self.instances = []
|
|
1599
|
+
self.instances.append(item)
|
|
1600
|
+
|
|
1601
|
+
|
|
1602
|
+
class JobParameter(CustomBaseModel):
|
|
1603
|
+
"""
|
|
1604
|
+
Represents a parameter for a job.
|
|
1605
|
+
|
|
1606
|
+
:param Name: str - The name of the parameter.
|
|
1607
|
+
:param Value: str - The value of the parameter.
|
|
1608
|
+
"""
|
|
1609
|
+
Name: str = Field(..., alias="Name", description="The name of the parameter")
|
|
1610
|
+
Value: str = Field(..., alias="Value", description="The value of the parameter")
|
|
1611
|
+
|
|
1612
|
+
@field_validator("Name")
|
|
1613
|
+
@classmethod
|
|
1614
|
+
def validate_name(cls, value: str) -> str:
|
|
1615
|
+
if not value.strip():
|
|
1616
|
+
raise ValueError("Parameter name cannot be blank")
|
|
1617
|
+
return value
|
|
1618
|
+
|
|
1619
|
+
def to_dict(self):
|
|
1620
|
+
return self.model_dump(by_alias=True, exclude_none=True)
|
|
1621
|
+
|
|
1622
|
+
def __str__(self):
|
|
1623
|
+
return str(self.to_dict())
|
|
1624
|
+
|
|
1625
|
+
|
|
1626
|
+
class Job(CustomBaseModel):
|
|
1627
|
+
"""
|
|
1628
|
+
Represents a single job configuration returned by the API.
|
|
1629
|
+
|
|
1630
|
+
:param caption: str - Description of the job's status and completion time.
|
|
1631
|
+
:param name: str - Name of the job (e.g., 'execute_workitem_jobrunner', 'publish_artifact').
|
|
1632
|
+
:param parameters: List[JobParameter] - List of parameters for the job.
|
|
1633
|
+
:param request: str - Timestamp when the job was requested.
|
|
1634
|
+
:param token: str - Unique token identifier for the job.
|
|
1635
|
+
:param topic: str - Topic associated with the job (e.g., 'Default', 'Event').
|
|
1636
|
+
:param info: Optional[str] - Additional information, typically for failed jobs.
|
|
1637
|
+
"""
|
|
1638
|
+
caption: str = Field(..., alias="caption", description="Description of the job's status and completion time")
|
|
1639
|
+
name: str = Field(..., alias="name", description="Name of the job")
|
|
1640
|
+
parameters: Optional[List[JobParameter]] = Field([], alias="parameters", description="List of parameters for the job")
|
|
1641
|
+
request: str = Field(..., alias="request", description="Timestamp when the job was requested")
|
|
1642
|
+
token: str = Field(..., alias="token", description="Unique token identifier for the job")
|
|
1643
|
+
topic: str = Field(..., alias="topic", description="Topic associated with the job")
|
|
1644
|
+
info: Optional[str] = Field(None, alias="info", description="Additional information, typically for failed jobs")
|
|
1645
|
+
|
|
1646
|
+
@field_validator("name")
|
|
1647
|
+
@classmethod
|
|
1648
|
+
def validate_name(cls, value: str) -> str:
|
|
1649
|
+
if not value.strip():
|
|
1650
|
+
raise ValueError("Job name cannot be blank")
|
|
1651
|
+
return value
|
|
1652
|
+
|
|
1653
|
+
@field_validator("token")
|
|
1654
|
+
@classmethod
|
|
1655
|
+
def validate_token(cls, value: str) -> str:
|
|
1656
|
+
if not value.strip():
|
|
1657
|
+
raise ValueError("Token cannot be blank")
|
|
1658
|
+
return value
|
|
1659
|
+
|
|
1660
|
+
@field_validator("parameters", mode="before")
|
|
1661
|
+
@classmethod
|
|
1662
|
+
def normalize_parameters(cls, value):
|
|
1663
|
+
if isinstance(value, list):
|
|
1664
|
+
return [JobParameter.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
1665
|
+
return value
|
|
1666
|
+
|
|
1667
|
+
def to_dict(self):
|
|
1668
|
+
result = {
|
|
1669
|
+
"caption": self.caption,
|
|
1670
|
+
"name": self.name,
|
|
1671
|
+
"parameters": [param.to_dict() for param in self.parameters] if self.parameters else [],
|
|
1672
|
+
"request": self.request,
|
|
1673
|
+
"token": self.token,
|
|
1674
|
+
"topic": self.topic,
|
|
1675
|
+
"info": self.info
|
|
1676
|
+
}
|
|
1677
|
+
return {k: v for k, v in result.items() if v is not None}
|
|
1678
|
+
|
|
1679
|
+
def __str__(self):
|
|
1680
|
+
return str(self.to_dict())
|
|
1681
|
+
|
|
1682
|
+
|
|
1683
|
+
class JobList(CustomBaseModel):
|
|
1684
|
+
"""
|
|
1685
|
+
Represents a list of jobs returned by the API.
|
|
1686
|
+
|
|
1687
|
+
:param jobs: List[Job] - List of job configurations.
|
|
1688
|
+
"""
|
|
1689
|
+
jobs: List[Job] = Field(..., alias="jobs", description="List of job configurations")
|
|
1690
|
+
|
|
1691
|
+
@field_validator("jobs", mode="before")
|
|
1692
|
+
@classmethod
|
|
1693
|
+
def normalize_jobs(cls, value):
|
|
1694
|
+
if isinstance(value, list):
|
|
1695
|
+
return [Job.model_validate(item) if isinstance(item, dict) else item for item in value]
|
|
1696
|
+
return value
|
|
1697
|
+
|
|
1698
|
+
def to_dict(self):
|
|
1699
|
+
return [job.to_dict() for job in self.jobs]
|
|
1700
|
+
|
|
1701
|
+
def __getitem__(self, index: int) -> Job:
|
|
1702
|
+
if self.jobs is None:
|
|
1703
|
+
raise IndexError("JobList is empty")
|
|
1704
|
+
return self.jobs[index]
|
|
1705
|
+
|
|
1706
|
+
def __len__(self) -> int:
|
|
1707
|
+
return len(self.jobs) if self.jobs else 0
|
|
1708
|
+
|
|
1709
|
+
def __iter__(self):
|
|
1710
|
+
"""Make JobList iterable over its jobs."""
|
|
1711
|
+
if self.jobs is None:
|
|
1712
|
+
return iter([])
|
|
1713
|
+
return iter(self.jobs)
|
|
1714
|
+
|
|
1715
|
+
def append(self, item: Job) -> None:
|
|
1716
|
+
"""Append a Job instance to the jobs list."""
|
|
1717
|
+
if self.jobs is None:
|
|
1718
|
+
self.jobs = []
|
|
1719
|
+
self.jobs.append(item)
|