pygeai 0.1.51b3__py3-none-any.whl → 0.6.0b15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pygeai might be problematic. Click here for more details.
- pygeai/__init__.py +9 -1
- pygeai/_docs/Makefile +20 -0
- pygeai/_docs/make.bat +35 -0
- pygeai/_docs/source/conf.py +117 -0
- pygeai/_docs/source/content/ai_lab/cli.rst +747 -0
- pygeai/_docs/source/content/ai_lab/models.rst +1734 -0
- pygeai/_docs/source/content/ai_lab/runner.rst +253 -0
- pygeai/_docs/source/content/ai_lab/spec.rst +431 -0
- pygeai/_docs/source/content/ai_lab/usage.rst +1011 -0
- pygeai/_docs/source/content/ai_lab.rst +102 -0
- pygeai/_docs/source/content/analytics.rst +598 -0
- pygeai/_docs/source/content/api_reference/admin.rst +161 -0
- pygeai/_docs/source/content/api_reference/assistant.rst +326 -0
- pygeai/_docs/source/content/api_reference/auth.rst +379 -0
- pygeai/_docs/source/content/api_reference/chat.rst +754 -0
- pygeai/_docs/source/content/api_reference/embeddings.rst +154 -0
- pygeai/_docs/source/content/api_reference/evaluation.rst +590 -0
- pygeai/_docs/source/content/api_reference/feedback.rst +237 -0
- pygeai/_docs/source/content/api_reference/files.rst +592 -0
- pygeai/_docs/source/content/api_reference/gam.rst +401 -0
- pygeai/_docs/source/content/api_reference/health.rst +58 -0
- pygeai/_docs/source/content/api_reference/project.rst +738 -0
- pygeai/_docs/source/content/api_reference/proxy.rst +318 -0
- pygeai/_docs/source/content/api_reference/rag.rst +710 -0
- pygeai/_docs/source/content/api_reference/rerank.rst +94 -0
- pygeai/_docs/source/content/api_reference/secrets.rst +495 -0
- pygeai/_docs/source/content/api_reference/usage_limits.rst +390 -0
- pygeai/_docs/source/content/api_reference.rst +58 -0
- pygeai/_docs/source/content/authentication.rst +295 -0
- pygeai/_docs/source/content/chat_gui.rst +121 -0
- pygeai/_docs/source/content/cli.rst +203 -0
- pygeai/_docs/source/content/debugger.rst +651 -0
- pygeai/_docs/source/content/intro.rst +67 -0
- pygeai/_docs/source/content/migration.rst +929 -0
- pygeai/_docs/source/content/modules.rst +7 -0
- pygeai/_docs/source/content/quickstart.rst +143 -0
- pygeai/_docs/source/content/samples.rst +394 -0
- pygeai/_docs/source/index.rst +75 -0
- pygeai/_docs/source/modules.rst +7 -0
- pygeai/_docs/source/pygeai.admin.rst +29 -0
- pygeai/_docs/source/pygeai.analytics.rst +53 -0
- pygeai/_docs/source/pygeai.assistant.data.rst +21 -0
- pygeai/_docs/source/pygeai.assistant.data_analyst.rst +29 -0
- pygeai/_docs/source/pygeai.assistant.rag.rst +53 -0
- pygeai/_docs/source/pygeai.assistant.rst +55 -0
- pygeai/_docs/source/pygeai.auth.rst +29 -0
- pygeai/_docs/source/pygeai.chat.rst +69 -0
- pygeai/_docs/source/pygeai.cli.commands.flows.rst +10 -0
- pygeai/_docs/source/pygeai.cli.commands.lab.rst +53 -0
- pygeai/_docs/source/pygeai.cli.commands.rst +222 -0
- pygeai/_docs/source/pygeai.cli.rst +62 -0
- pygeai/_docs/source/pygeai.cli.texts.rst +21 -0
- pygeai/_docs/source/pygeai.core.base.rst +53 -0
- pygeai/_docs/source/pygeai.core.common.rst +37 -0
- pygeai/_docs/source/pygeai.core.embeddings.rst +61 -0
- pygeai/_docs/source/pygeai.core.feedback.rst +37 -0
- pygeai/_docs/source/pygeai.core.files.rst +61 -0
- pygeai/_docs/source/pygeai.core.llm.rst +29 -0
- pygeai/_docs/source/pygeai.core.plugins.rst +37 -0
- pygeai/_docs/source/pygeai.core.rerank.rst +53 -0
- pygeai/_docs/source/pygeai.core.rst +63 -0
- pygeai/_docs/source/pygeai.core.secrets.rst +29 -0
- pygeai/_docs/source/pygeai.core.services.llm.rst +29 -0
- pygeai/_docs/source/pygeai.core.services.rst +37 -0
- pygeai/_docs/source/pygeai.core.utils.rst +37 -0
- pygeai/_docs/source/pygeai.dbg.rst +21 -0
- pygeai/_docs/source/pygeai.evaluation.dataset.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.plan.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.result.rst +29 -0
- pygeai/_docs/source/pygeai.evaluation.rst +31 -0
- pygeai/_docs/source/pygeai.flows.rst +29 -0
- pygeai/_docs/source/pygeai.gam.rst +29 -0
- pygeai/_docs/source/pygeai.health.rst +29 -0
- pygeai/_docs/source/pygeai.lab.agents.rst +37 -0
- pygeai/_docs/source/pygeai.lab.processes.rst +37 -0
- pygeai/_docs/source/pygeai.lab.rst +65 -0
- pygeai/_docs/source/pygeai.lab.spec.rst +29 -0
- pygeai/_docs/source/pygeai.lab.strategies.rst +37 -0
- pygeai/_docs/source/pygeai.lab.tools.rst +37 -0
- pygeai/_docs/source/pygeai.man.man1.rst +10 -0
- pygeai/_docs/source/pygeai.man.rst +18 -0
- pygeai/_docs/source/pygeai.migration.rst +29 -0
- pygeai/_docs/source/pygeai.organization.limits.rst +45 -0
- pygeai/_docs/source/pygeai.organization.rst +61 -0
- pygeai/_docs/source/pygeai.proxy.rst +53 -0
- pygeai/_docs/source/pygeai.rst +35 -0
- pygeai/_docs/source/pygeai.tests.admin.rst +21 -0
- pygeai/_docs/source/pygeai.tests.analytics.rst +45 -0
- pygeai/_docs/source/pygeai.tests.assistants.rag.rst +37 -0
- pygeai/_docs/source/pygeai.tests.assistants.rst +45 -0
- pygeai/_docs/source/pygeai.tests.auth.rst +29 -0
- pygeai/_docs/source/pygeai.tests.chat.rst +45 -0
- pygeai/_docs/source/pygeai.tests.cli.commands.lab.rst +37 -0
- pygeai/_docs/source/pygeai.tests.cli.commands.rst +165 -0
- pygeai/_docs/source/pygeai.tests.cli.docker.rst +10 -0
- pygeai/_docs/source/pygeai.tests.cli.rst +46 -0
- pygeai/_docs/source/pygeai.tests.core.base.data.rst +29 -0
- pygeai/_docs/source/pygeai.tests.core.base.rst +45 -0
- pygeai/_docs/source/pygeai.tests.core.common.data.rst +10 -0
- pygeai/_docs/source/pygeai.tests.core.common.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.embeddings.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.feedback.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.files.rst +53 -0
- pygeai/_docs/source/pygeai.tests.core.llm.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.plugins.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.rerank.rst +37 -0
- pygeai/_docs/source/pygeai.tests.core.rst +39 -0
- pygeai/_docs/source/pygeai.tests.core.secrets.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.services.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.utils.rst +21 -0
- pygeai/_docs/source/pygeai.tests.dbg.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.dataset.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.plan.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.result.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.rst +20 -0
- pygeai/_docs/source/pygeai.tests.gam.rst +21 -0
- pygeai/_docs/source/pygeai.tests.health.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.assistants.rag.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.assistants.rst +18 -0
- pygeai/_docs/source/pygeai.tests.integration.chat.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.agents.rst +69 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.processes.rst +77 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.reasoning_strategies.rst +37 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.rst +21 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.tools.rst +77 -0
- pygeai/_docs/source/pygeai.tests.integration.rst +20 -0
- pygeai/_docs/source/pygeai.tests.lab.agents.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.processes.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.rst +49 -0
- pygeai/_docs/source/pygeai.tests.lab.spec.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.strategies.rst +29 -0
- pygeai/_docs/source/pygeai.tests.lab.tools.rst +29 -0
- pygeai/_docs/source/pygeai.tests.migration.rst +29 -0
- pygeai/_docs/source/pygeai.tests.organization.limits.rst +29 -0
- pygeai/_docs/source/pygeai.tests.organization.rst +53 -0
- pygeai/_docs/source/pygeai.tests.proxy.rst +61 -0
- pygeai/_docs/source/pygeai.tests.rst +33 -0
- pygeai/admin/clients.py +14 -11
- pygeai/admin/endpoints.py +2 -2
- pygeai/analytics/clients.py +505 -0
- pygeai/analytics/endpoints.py +35 -0
- pygeai/analytics/managers.py +606 -0
- pygeai/analytics/mappers.py +207 -0
- pygeai/analytics/responses.py +240 -0
- pygeai/assistant/clients.py +18 -45
- pygeai/assistant/data/clients.py +1 -0
- pygeai/assistant/data_analyst/clients.py +8 -12
- pygeai/assistant/managers.py +195 -157
- pygeai/assistant/mappers.py +4 -2
- pygeai/assistant/rag/clients.py +27 -67
- pygeai/assistant/rag/mappers.py +12 -6
- pygeai/assistant/rag/models.py +301 -159
- pygeai/auth/__init__.py +0 -0
- pygeai/auth/clients.py +129 -0
- pygeai/auth/endpoints.py +6 -0
- pygeai/chat/clients.py +308 -37
- pygeai/chat/endpoints.py +3 -0
- pygeai/chat/iris.py +2 -8
- pygeai/chat/managers.py +9 -6
- pygeai/chat/session.py +38 -0
- pygeai/chat/settings.py +6 -0
- pygeai/chat/ui.py +678 -0
- pygeai/cli/__init__.py +0 -1
- pygeai/cli/commands/admin.py +7 -10
- pygeai/cli/commands/analytics.py +533 -0
- pygeai/cli/commands/assistant.py +9 -9
- pygeai/cli/commands/auth.py +299 -0
- pygeai/cli/commands/base.py +71 -9
- pygeai/cli/commands/chat.py +676 -19
- pygeai/cli/commands/common.py +28 -24
- pygeai/cli/commands/configuration.py +66 -13
- pygeai/cli/commands/docs.py +105 -0
- pygeai/cli/commands/embeddings.py +58 -11
- pygeai/cli/commands/evaluation.py +38 -38
- pygeai/cli/commands/feedback.py +3 -4
- pygeai/cli/commands/files.py +7 -8
- pygeai/cli/commands/gam.py +85 -10
- pygeai/cli/commands/lab/ai_lab.py +340 -484
- pygeai/cli/commands/lab/options.py +8 -0
- pygeai/cli/commands/lab/spec.py +273 -0
- pygeai/cli/commands/lab/utils.py +13 -0
- pygeai/cli/commands/llm.py +6 -7
- pygeai/cli/commands/migrate.py +1064 -436
- pygeai/cli/commands/organization.py +516 -11
- pygeai/cli/commands/rag.py +13 -14
- pygeai/cli/commands/rerank.py +3 -5
- pygeai/cli/commands/secrets.py +8 -9
- pygeai/cli/commands/usage_limits.py +18 -20
- pygeai/cli/commands/validators.py +144 -1
- pygeai/cli/commands/version.py +4 -5
- pygeai/cli/error_handler.py +151 -0
- pygeai/cli/geai.py +170 -31
- pygeai/cli/geai_proxy.py +86 -25
- pygeai/cli/install_man.py +93 -22
- pygeai/cli/parsers.py +75 -25
- pygeai/cli/texts/help.py +265 -28
- pygeai/core/base/clients.py +53 -12
- pygeai/core/base/mappers.py +11 -2
- pygeai/core/base/session.py +95 -11
- pygeai/core/common/config.py +78 -14
- pygeai/core/common/exceptions.py +96 -6
- pygeai/core/embeddings/__init__.py +19 -0
- pygeai/core/embeddings/clients.py +23 -5
- pygeai/core/embeddings/managers.py +9 -4
- pygeai/core/embeddings/mappers.py +16 -2
- pygeai/core/embeddings/responses.py +9 -2
- pygeai/core/feedback/clients.py +8 -3
- pygeai/core/files/clients.py +23 -24
- pygeai/core/files/managers.py +121 -30
- pygeai/core/files/responses.py +4 -3
- pygeai/core/handlers.py +10 -1
- pygeai/core/llm/clients.py +22 -29
- pygeai/core/models.py +127 -11
- pygeai/core/plugins/clients.py +6 -6
- pygeai/core/rerank/clients.py +9 -3
- pygeai/core/rerank/managers.py +22 -5
- pygeai/core/secrets/clients.py +16 -37
- pygeai/core/services/response.py +18 -0
- pygeai/core/services/rest.py +159 -49
- pygeai/core/utils/__init__.py +0 -0
- pygeai/core/utils/console.py +83 -0
- pygeai/core/utils/parsers.py +32 -0
- pygeai/core/utils/validators.py +10 -0
- pygeai/dbg/__init__.py +3 -0
- pygeai/dbg/debugger.py +854 -14
- pygeai/evaluation/clients.py +7 -4
- pygeai/evaluation/dataset/clients.py +46 -44
- pygeai/evaluation/plan/clients.py +28 -26
- pygeai/evaluation/result/clients.py +38 -5
- pygeai/gam/clients.py +50 -28
- pygeai/gam/endpoints.py +2 -1
- pygeai/health/__init__.py +0 -0
- pygeai/health/clients.py +24 -0
- pygeai/health/endpoints.py +1 -0
- pygeai/lab/__init__.py +0 -90
- pygeai/lab/agents/clients.py +203 -162
- pygeai/lab/agents/endpoints.py +4 -0
- pygeai/lab/agents/mappers.py +57 -7
- pygeai/lab/clients.py +24 -0
- pygeai/lab/constants.py +3 -0
- pygeai/lab/managers.py +571 -541
- pygeai/lab/models.py +108 -19
- pygeai/lab/processes/clients.py +332 -340
- pygeai/lab/processes/mappers.py +3 -3
- pygeai/lab/runners.py +90 -0
- pygeai/lab/spec/__init__.py +0 -0
- pygeai/lab/spec/loader.py +24 -0
- pygeai/lab/spec/parsers.py +39 -0
- pygeai/lab/strategies/clients.py +67 -63
- pygeai/lab/strategies/mappers.py +1 -1
- pygeai/lab/tools/clients.py +85 -118
- pygeai/lab/tools/endpoints.py +4 -0
- pygeai/lab/tools/mappers.py +5 -5
- pygeai/man/man1/geai-proxy.1 +116 -0
- pygeai/man/man1/geai.1 +2580 -66
- pygeai/migration/__init__.py +33 -0
- pygeai/migration/strategies.py +468 -146
- pygeai/migration/tools.py +170 -3
- pygeai/organization/clients.py +245 -50
- pygeai/organization/endpoints.py +17 -8
- pygeai/organization/limits/clients.py +34 -32
- pygeai/organization/limits/managers.py +108 -49
- pygeai/organization/managers.py +347 -53
- pygeai/organization/mappers.py +102 -2
- pygeai/organization/responses.py +58 -1
- pygeai/proxy/clients.py +6 -3
- pygeai/proxy/config.py +14 -1
- pygeai/proxy/managers.py +61 -33
- pygeai/proxy/servers.py +196 -51
- pygeai/proxy/tool.py +33 -16
- pygeai/tests/admin/__init__.py +0 -0
- pygeai/tests/admin/test_clients.py +148 -0
- pygeai/tests/analytics/__init__.py +0 -0
- pygeai/tests/analytics/test_clients.py +86 -0
- pygeai/tests/analytics/test_managers.py +94 -0
- pygeai/tests/analytics/test_mappers.py +84 -0
- pygeai/tests/analytics/test_responses.py +73 -0
- pygeai/tests/assistants/rag/test_clients.py +346 -0
- pygeai/tests/assistants/rag/test_models.py +292 -0
- pygeai/tests/assistants/test_clients.py +176 -82
- pygeai/tests/assistants/test_managers.py +191 -57
- pygeai/tests/auth/__init__.py +0 -0
- pygeai/tests/auth/test_clients.py +289 -0
- pygeai/tests/auth/test_oauth.py +172 -0
- pygeai/tests/auth/test_session_logging.py +150 -0
- pygeai/tests/chat/__init__.py +0 -0
- pygeai/tests/chat/test_clients.py +393 -0
- pygeai/tests/chat/test_iris.py +38 -0
- pygeai/tests/chat/test_session.py +62 -0
- pygeai/tests/chat/test_ui.py +224 -0
- pygeai/tests/cli/commands/__init__.py +0 -0
- pygeai/tests/cli/commands/lab/__init__.py +0 -0
- pygeai/tests/cli/commands/lab/test_ai_lab.py +786 -0
- pygeai/tests/cli/commands/lab/test_common.py +208 -0
- pygeai/tests/cli/commands/lab/test_spec.py +246 -0
- pygeai/tests/cli/commands/test_assistant.py +202 -0
- pygeai/tests/cli/commands/test_chat.py +130 -0
- pygeai/tests/cli/commands/test_common.py +350 -0
- pygeai/tests/cli/commands/test_embeddings.py +132 -0
- pygeai/tests/cli/commands/test_evaluation.py +656 -0
- pygeai/tests/cli/commands/test_feedback.py +65 -0
- pygeai/tests/cli/commands/test_files.py +161 -0
- pygeai/tests/cli/commands/test_gam.py +201 -0
- pygeai/tests/cli/commands/test_llm.py +114 -0
- pygeai/tests/cli/commands/test_migrate.py +176 -0
- pygeai/tests/cli/commands/test_organization.py +276 -0
- pygeai/tests/cli/commands/test_rag.py +266 -0
- pygeai/tests/cli/commands/test_rerank.py +110 -0
- pygeai/tests/cli/commands/test_secrets.py +171 -0
- pygeai/tests/cli/commands/test_show_help.py +41 -0
- pygeai/tests/cli/commands/test_usage_limits.py +412 -0
- pygeai/tests/cli/commands/test_validators.py +160 -0
- pygeai/tests/cli/commands/test_version.py +81 -0
- pygeai/tests/cli/docker/__init__.py +0 -0
- pygeai/tests/cli/test_credentials_flag.py +316 -0
- pygeai/tests/cli/test_error_handler.py +225 -0
- pygeai/tests/cli/test_geai_driver.py +154 -0
- pygeai/tests/cli/test_parsers.py +5 -5
- pygeai/tests/core/base/data/models.py +7 -0
- pygeai/tests/core/base/test_mappers.py +43 -11
- pygeai/tests/core/base/test_models.py +3 -1
- pygeai/tests/core/base/test_responses.py +53 -0
- pygeai/tests/core/common/__init__.py +0 -0
- pygeai/tests/core/common/data/__init__.py +0 -0
- pygeai/tests/core/common/test_config.py +186 -0
- pygeai/tests/core/common/test_decorators.py +69 -0
- pygeai/tests/core/embeddings/__init__.py +0 -0
- pygeai/tests/core/embeddings/test_clients.py +225 -0
- pygeai/tests/core/embeddings/test_managers.py +171 -0
- pygeai/tests/core/embeddings/test_mappers.py +142 -0
- pygeai/tests/core/feedback/__init__.py +0 -0
- pygeai/tests/core/feedback/test_clients.py +64 -0
- pygeai/tests/core/files/test_clients.py +128 -0
- pygeai/tests/core/files/test_managers.py +124 -78
- pygeai/tests/core/files/test_mappers.py +137 -0
- pygeai/tests/core/files/test_models.py +103 -0
- pygeai/tests/core/files/test_responses.py +122 -0
- pygeai/tests/core/llm/__init__.py +0 -0
- pygeai/tests/core/llm/test_clients.py +142 -0
- pygeai/tests/core/plugins/__init__.py +0 -0
- pygeai/tests/core/plugins/test_clients.py +66 -0
- pygeai/tests/core/rerank/test_clients.py +76 -0
- pygeai/tests/core/rerank/test_managers.py +61 -39
- pygeai/tests/core/secrets/__init__.py +0 -0
- pygeai/tests/core/secrets/test_clients.py +264 -0
- pygeai/tests/core/services/__init__.py +0 -0
- pygeai/tests/core/services/test_rest.py +273 -0
- pygeai/tests/core/test_handlers.py +66 -0
- pygeai/tests/core/utils/__init__.py +0 -0
- pygeai/tests/core/utils/test_console.py +80 -0
- pygeai/tests/dbg/__init__.py +0 -0
- pygeai/tests/dbg/test_debugger.py +591 -0
- pygeai/tests/evaluation/__init__.py +0 -0
- pygeai/tests/evaluation/dataset/__init__.py +0 -0
- pygeai/tests/evaluation/dataset/test_clients.py +265 -0
- pygeai/tests/evaluation/plan/__init__.py +0 -0
- pygeai/tests/evaluation/plan/test_clients.py +195 -0
- pygeai/tests/evaluation/result/__init__.py +0 -0
- pygeai/tests/evaluation/result/test_clients.py +66 -0
- pygeai/tests/gam/__init__.py +0 -0
- pygeai/tests/gam/test_clients.py +195 -0
- pygeai/tests/health/__init__.py +0 -0
- pygeai/tests/health/test_clients.py +41 -0
- pygeai/tests/integration/__init__.py +0 -0
- pygeai/tests/integration/assistants/__init__.py +0 -0
- pygeai/tests/integration/assistants/rag/__init__.py +0 -0
- pygeai/tests/integration/assistants/rag/test_create_rag.py +91 -0
- pygeai/tests/integration/chat/__init__.py +0 -0
- pygeai/tests/integration/chat/test_generate_image.py +158 -0
- pygeai/tests/integration/lab/__init__.py +0 -0
- pygeai/tests/integration/lab/agents/__init__.py +0 -0
- pygeai/tests/integration/lab/agents/test_agents_list.py +106 -0
- pygeai/tests/integration/lab/agents/test_create_agent.py +319 -0
- pygeai/tests/integration/lab/agents/test_create_sharing_link.py +70 -0
- pygeai/tests/integration/lab/agents/test_delete_agent.py +75 -0
- pygeai/tests/integration/lab/agents/test_get_agent.py +94 -0
- pygeai/tests/integration/lab/agents/test_publish_agent_revision.py +127 -0
- pygeai/tests/integration/lab/agents/test_update_agent.py +250 -0
- pygeai/tests/integration/lab/processes/__init__.py +0 -0
- pygeai/tests/integration/lab/processes/test_create_process.py +345 -0
- pygeai/tests/integration/lab/processes/test_create_task.py +211 -0
- pygeai/tests/integration/lab/processes/test_delete_process.py +111 -0
- pygeai/tests/integration/lab/processes/test_get_process.py +201 -0
- pygeai/tests/integration/lab/processes/test_list_process_instances.py +91 -0
- pygeai/tests/integration/lab/processes/test_list_processes.py +138 -0
- pygeai/tests/integration/lab/processes/test_publish_process_revision.py +232 -0
- pygeai/tests/integration/lab/processes/test_update_process.py +289 -0
- pygeai/tests/integration/lab/reasoning_strategies/__init__.py +0 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_get_reasoning_strategy.py +70 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_list_reasoning_strategies.py +93 -0
- pygeai/tests/integration/lab/reasoning_strategies/test_update_reasoning_strategy.py +149 -0
- pygeai/tests/integration/lab/tools/__init__.py +0 -0
- pygeai/tests/integration/lab/tools/test_create_tool.py +288 -0
- pygeai/tests/integration/lab/tools/test_delete_tool.py +87 -0
- pygeai/tests/integration/lab/tools/test_get_parameter.py +98 -0
- pygeai/tests/integration/lab/tools/test_get_tool.py +91 -0
- pygeai/tests/integration/lab/tools/test_list_tools.py +106 -0
- pygeai/tests/integration/lab/tools/test_publish_tool_revision.py +119 -0
- pygeai/tests/integration/lab/tools/test_set_parameter.py +114 -0
- pygeai/tests/integration/lab/tools/test_update_tool.py +267 -0
- pygeai/tests/lab/agents/__init__.py +0 -0
- pygeai/tests/lab/agents/test_clients.py +481 -0
- pygeai/tests/lab/agents/test_mappers.py +440 -0
- pygeai/tests/lab/processes/__init__.py +0 -0
- pygeai/tests/lab/processes/test_clients.py +1416 -0
- pygeai/tests/lab/processes/test_mappers.py +1092 -0
- pygeai/tests/lab/spec/__init__.py +0 -0
- pygeai/tests/lab/spec/test_loader.py +59 -0
- pygeai/tests/lab/spec/test_parsers.py +182 -0
- pygeai/tests/lab/strategies/__init__.py +0 -0
- pygeai/tests/lab/strategies/test_clients.py +241 -0
- pygeai/tests/lab/strategies/test_mappers.py +132 -0
- pygeai/tests/lab/test_managers.py +553 -0
- pygeai/tests/lab/test_models.py +500 -3
- pygeai/tests/lab/tools/__init__.py +0 -0
- pygeai/tests/lab/tools/test_clients.py +521 -0
- pygeai/tests/lab/tools/test_mappers.py +198 -0
- pygeai/tests/migration/__init__.py +0 -0
- pygeai/tests/migration/test_strategies.py +405 -0
- pygeai/tests/migration/test_tools.py +159 -0
- pygeai/tests/organization/limits/test_clients.py +567 -0
- pygeai/tests/organization/limits/test_managers.py +298 -56
- pygeai/tests/organization/test_clients.py +600 -30
- pygeai/tests/organization/test_managers.py +424 -0
- pygeai/tests/organization/test_mappers.py +153 -0
- pygeai/tests/organization/test_responses.py +137 -0
- pygeai/tests/proxy/__init__.py +1 -0
- pygeai/tests/proxy/test_clients.py +397 -0
- pygeai/tests/proxy/test_config.py +171 -0
- pygeai/tests/proxy/test_integration.py +305 -0
- pygeai/tests/proxy/test_managers.py +312 -0
- pygeai/tests/proxy/test_servers.py +387 -0
- pygeai/tests/proxy/test_tool.py +176 -0
- pygeai/tests/snippets/analytics/__init__.py +0 -0
- pygeai/tests/snippets/analytics/get_agent_usage_per_user.py +16 -0
- pygeai/tests/snippets/analytics/get_agents_created_and_modified.py +11 -0
- pygeai/tests/snippets/analytics/get_average_cost_per_request.py +10 -0
- pygeai/tests/snippets/analytics/get_overall_error_rate.py +10 -0
- pygeai/tests/snippets/analytics/get_top_10_agents_by_requests.py +12 -0
- pygeai/tests/snippets/analytics/get_total_active_users.py +10 -0
- pygeai/tests/snippets/analytics/get_total_cost.py +10 -0
- pygeai/tests/snippets/analytics/get_total_requests_per_day.py +12 -0
- pygeai/tests/snippets/analytics/get_total_tokens.py +12 -0
- pygeai/tests/snippets/auth/__init__.py +0 -0
- pygeai/tests/snippets/chat/chat_completion_with_reasoning_effort.py +18 -0
- pygeai/tests/snippets/chat/get_response.py +15 -0
- pygeai/tests/snippets/chat/get_response_complete_example.py +67 -0
- pygeai/tests/snippets/chat/get_response_streaming.py +20 -0
- pygeai/tests/snippets/chat/get_response_with_files.py +16 -0
- pygeai/tests/snippets/chat/get_response_with_instructions.py +19 -0
- pygeai/tests/snippets/chat/get_response_with_metadata.py +24 -0
- pygeai/tests/snippets/chat/get_response_with_parallel_tools.py +58 -0
- pygeai/tests/snippets/chat/get_response_with_reasoning.py +21 -0
- pygeai/tests/snippets/chat/get_response_with_store.py +38 -0
- pygeai/tests/snippets/chat/get_response_with_tools.py +36 -0
- pygeai/tests/snippets/chat/get_response_with_truncation.py +24 -0
- pygeai/tests/snippets/dbg/__init__.py +0 -0
- pygeai/tests/snippets/dbg/basic_debugging.py +32 -0
- pygeai/tests/snippets/dbg/breakpoint_management.py +48 -0
- pygeai/tests/snippets/dbg/file_debugging.py +72 -0
- pygeai/tests/snippets/dbg/module_debugging.py +61 -0
- pygeai/tests/snippets/dbg/stack_navigation.py +45 -0
- pygeai/tests/snippets/dbg/stepping_example.py +40 -0
- pygeai/tests/snippets/embeddings/cache_example.py +31 -0
- pygeai/tests/snippets/embeddings/cohere_example.py +41 -0
- pygeai/tests/snippets/embeddings/openai_base64_example.py +27 -0
- pygeai/tests/snippets/embeddings/openai_example.py +30 -0
- pygeai/tests/snippets/embeddings/similarity_example.py +42 -0
- pygeai/tests/snippets/evaluation/dataset/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/dataset/complete_workflow_example.py +195 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset.py +26 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset_from_file.py +11 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset_row.py +17 -0
- pygeai/tests/snippets/evaluation/dataset/create_expected_source.py +18 -0
- pygeai/tests/snippets/evaluation/dataset/create_filter_variable.py +19 -0
- pygeai/tests/snippets/evaluation/dataset/delete_dataset.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/delete_dataset_row.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/delete_expected_source.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/delete_filter_variable.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/get_dataset.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/get_dataset_row.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/get_expected_source.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/get_filter_variable.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/list_dataset_rows.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/list_datasets.py +6 -0
- pygeai/tests/snippets/evaluation/dataset/list_expected_sources.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/list_filter_variables.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/update_dataset.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/update_dataset_row.py +20 -0
- pygeai/tests/snippets/evaluation/dataset/update_expected_source.py +18 -0
- pygeai/tests/snippets/evaluation/dataset/update_filter_variable.py +19 -0
- pygeai/tests/snippets/evaluation/dataset/upload_dataset_rows_file.py +10 -0
- pygeai/tests/snippets/evaluation/plan/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/plan/add_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/complete_workflow_example.py +136 -0
- pygeai/tests/snippets/evaluation/plan/create_evaluation_plan.py +24 -0
- pygeai/tests/snippets/evaluation/plan/create_rag_evaluation_plan.py +22 -0
- pygeai/tests/snippets/evaluation/plan/delete_evaluation_plan.py +9 -0
- pygeai/tests/snippets/evaluation/plan/delete_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/execute_evaluation_plan.py +11 -0
- pygeai/tests/snippets/evaluation/plan/get_evaluation_plan.py +9 -0
- pygeai/tests/snippets/evaluation/plan/get_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/get_system_metric.py +9 -0
- pygeai/tests/snippets/evaluation/plan/list_evaluation_plans.py +7 -0
- pygeai/tests/snippets/evaluation/plan/list_plan_system_metrics.py +9 -0
- pygeai/tests/snippets/evaluation/plan/list_system_metrics.py +7 -0
- pygeai/tests/snippets/evaluation/plan/update_evaluation_plan.py +22 -0
- pygeai/tests/snippets/evaluation/plan/update_plan_system_metric.py +14 -0
- pygeai/tests/snippets/evaluation/result/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/result/complete_workflow_example.py +150 -0
- pygeai/tests/snippets/evaluation/result/get_evaluation_result.py +26 -0
- pygeai/tests/snippets/evaluation/result/list_evaluation_results.py +17 -0
- pygeai/tests/snippets/files/delete_file.py +1 -4
- pygeai/tests/snippets/files/get_file_content.py +2 -4
- pygeai/tests/snippets/files/get_file_data.py +1 -4
- pygeai/tests/snippets/files/get_file_list.py +1 -6
- pygeai/tests/snippets/files/upload_file.py +1 -5
- pygeai/tests/snippets/gam/gam_access_token.py +87 -0
- pygeai/tests/snippets/lab/agentic_flow_example_1.py +25 -23
- pygeai/tests/snippets/lab/agentic_flow_example_4.py +23 -23
- pygeai/tests/snippets/lab/agents/create_agent.py +5 -8
- pygeai/tests/snippets/lab/agents/create_agent_2.py +1 -5
- pygeai/tests/snippets/lab/agents/create_agent_edge_case.py +48 -0
- pygeai/tests/snippets/lab/agents/create_agent_with_permissions.py +39 -0
- pygeai/tests/snippets/lab/agents/create_agent_with_properties.py +46 -0
- pygeai/tests/snippets/lab/agents/create_agent_without_instructions.py +48 -0
- pygeai/tests/snippets/lab/agents/delete_agent.py +1 -5
- pygeai/tests/snippets/lab/agents/get_agent.py +2 -11
- pygeai/tests/snippets/lab/agents/get_agent_with_new_fields.py +62 -0
- pygeai/tests/snippets/lab/agents/get_sharing_link.py +2 -7
- pygeai/tests/snippets/lab/agents/list_agents.py +4 -7
- pygeai/tests/snippets/lab/agents/publish_agent_revision.py +2 -6
- pygeai/tests/snippets/lab/agents/update_agent.py +1 -5
- pygeai/tests/snippets/lab/agents/update_agent_properties.py +50 -0
- pygeai/tests/snippets/lab/assistant_to_agent.py +191 -0
- pygeai/tests/snippets/lab/crud_ui.py +462 -0
- pygeai/tests/snippets/lab/processes/create_process.py +3 -5
- pygeai/tests/snippets/lab/processes/create_task.py +3 -5
- pygeai/tests/snippets/lab/processes/jobs/list_jobs.py +10 -19
- pygeai/tests/snippets/lab/processes/kbs/create_kb.py +2 -5
- pygeai/tests/snippets/lab/processes/kbs/get_kb.py +10 -16
- pygeai/tests/snippets/lab/processes/kbs/list_kbs.py +13 -20
- pygeai/tests/snippets/lab/processes/kbs/try_all.py +5 -7
- pygeai/tests/snippets/lab/processes/list_processes.py +5 -7
- pygeai/tests/snippets/lab/runner_1.py +1 -1
- pygeai/tests/snippets/lab/samples/summarize_files.py +3 -3
- pygeai/tests/snippets/lab/strategies/create_reasoning_strategy.py +2 -5
- pygeai/tests/snippets/lab/strategies/get_reasoning_strategy.py +2 -5
- pygeai/tests/snippets/lab/strategies/list_reasoning_strategies.py +3 -6
- pygeai/tests/snippets/lab/strategies/update_reasoning_strategy.py +2 -5
- pygeai/tests/snippets/lab/tools/create_tool.py +4 -10
- pygeai/tests/snippets/lab/tools/create_tool_edge_case.py +50 -0
- pygeai/tests/snippets/lab/tools/delete_tool.py +2 -6
- pygeai/tests/snippets/lab/tools/get_parameter.py +5 -7
- pygeai/tests/snippets/lab/tools/get_tool.py +5 -7
- pygeai/tests/snippets/lab/tools/list_tools.py +3 -7
- pygeai/tests/snippets/lab/tools/publish_tool_revision.py +3 -5
- pygeai/tests/snippets/lab/tools/set_parameters.py +4 -9
- pygeai/tests/snippets/lab/tools/update_tool.py +4 -8
- pygeai/tests/snippets/lab/use_cases/__init__.py +0 -0
- pygeai/tests/snippets/lab/use_cases/create_cli_expert.py +1640 -0
- pygeai/tests/snippets/lab/use_cases/create_lab_expert.py +4541 -0
- pygeai/tests/snippets/lab/use_cases/create_tool_headless_web_browser.py +133 -0
- pygeai/tests/snippets/lab/use_cases/create_web_designer.py +189 -0
- pygeai/tests/snippets/lab/use_cases/create_web_reader.py +185 -0
- pygeai/tests/snippets/lab/{file_summarizer_example.py → use_cases/file_summarizer_example.py} +3 -3
- pygeai/tests/snippets/lab/{file_summarizer_example_2.py → use_cases/file_summarizer_example_2.py} +12 -12
- pygeai/tests/snippets/lab/use_cases/update_cli_expert.py +1773 -0
- pygeai/tests/snippets/lab/use_cases/update_lab_expert.py +4541 -0
- pygeai/tests/snippets/lab/use_cases/update_web_designer.py +188 -0
- pygeai/tests/snippets/lab/use_cases/update_web_reader.py +195 -0
- pygeai/tests/snippets/lab/use_cases/update_web_reader_with_tool.py +210 -0
- pygeai/tests/snippets/migrate/__init__.py +45 -0
- pygeai/tests/snippets/migrate/agent_migration.py +110 -0
- pygeai/tests/snippets/migrate/assistant_migration.py +64 -0
- pygeai/tests/snippets/migrate/orchestrator_examples.py +179 -0
- pygeai/tests/snippets/migrate/process_migration.py +64 -0
- pygeai/tests/snippets/migrate/project_migration.py +42 -0
- pygeai/tests/snippets/migrate/tool_migration.py +64 -0
- pygeai/tests/snippets/organization/add_project_member.py +10 -0
- pygeai/tests/snippets/organization/add_project_member_batch.py +44 -0
- pygeai/tests/snippets/organization/create_project.py +2 -2
- pygeai/tests/snippets/organization/get_memberships.py +12 -0
- pygeai/tests/snippets/organization/get_organization_members.py +6 -0
- pygeai/tests/snippets/organization/get_project_members.py +6 -0
- pygeai/tests/snippets/organization/get_project_memberships.py +12 -0
- pygeai/tests/snippets/organization/get_project_roles.py +6 -0
- pygeai/vendor/a2a/__init__.py +1 -0
- pygeai/vendor/a2a/auth/__init__.py +0 -0
- pygeai/vendor/a2a/auth/user.py +31 -0
- pygeai/vendor/a2a/client/__init__.py +19 -0
- pygeai/vendor/a2a/client/client.py +425 -0
- pygeai/vendor/a2a/client/errors.py +33 -0
- pygeai/vendor/a2a/client/helpers.py +22 -0
- pygeai/vendor/a2a/py.typed +0 -0
- pygeai/vendor/a2a/server/__init__.py +1 -0
- pygeai/vendor/a2a/server/agent_execution/__init__.py +18 -0
- pygeai/vendor/a2a/server/agent_execution/agent_executor.py +44 -0
- pygeai/vendor/a2a/server/agent_execution/context.py +155 -0
- pygeai/vendor/a2a/server/agent_execution/request_context_builder.py +20 -0
- pygeai/vendor/a2a/server/agent_execution/simple_request_context_builder.py +77 -0
- pygeai/vendor/a2a/server/apps/__init__.py +16 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/__init__.py +16 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/fastapi_app.py +88 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/jsonrpc_app.py +426 -0
- pygeai/vendor/a2a/server/apps/jsonrpc/starlette_app.py +123 -0
- pygeai/vendor/a2a/server/context.py +23 -0
- pygeai/vendor/a2a/server/events/__init__.py +21 -0
- pygeai/vendor/a2a/server/events/event_consumer.py +149 -0
- pygeai/vendor/a2a/server/events/event_queue.py +156 -0
- pygeai/vendor/a2a/server/events/in_memory_queue_manager.py +85 -0
- pygeai/vendor/a2a/server/events/queue_manager.py +35 -0
- pygeai/vendor/a2a/server/request_handlers/__init__.py +20 -0
- pygeai/vendor/a2a/server/request_handlers/default_request_handler.py +435 -0
- pygeai/vendor/a2a/server/request_handlers/jsonrpc_handler.py +327 -0
- pygeai/vendor/a2a/server/request_handlers/request_handler.py +161 -0
- pygeai/vendor/a2a/server/request_handlers/response_helpers.py +133 -0
- pygeai/vendor/a2a/server/tasks/__init__.py +20 -0
- pygeai/vendor/a2a/server/tasks/inmemory_push_notifier.py +62 -0
- pygeai/vendor/a2a/server/tasks/inmemory_task_store.py +51 -0
- pygeai/vendor/a2a/server/tasks/push_notifier.py +25 -0
- pygeai/vendor/a2a/server/tasks/result_aggregator.py +151 -0
- pygeai/vendor/a2a/server/tasks/task_manager.py +253 -0
- pygeai/vendor/a2a/server/tasks/task_store.py +22 -0
- pygeai/vendor/a2a/server/tasks/task_updater.py +155 -0
- pygeai/vendor/a2a/types.py +1624 -0
- pygeai/vendor/a2a/utils/__init__.py +40 -0
- pygeai/vendor/a2a/utils/artifact.py +72 -0
- pygeai/vendor/a2a/utils/errors.py +69 -0
- pygeai/vendor/a2a/utils/helpers.py +176 -0
- pygeai/vendor/a2a/utils/message.py +83 -0
- pygeai/vendor/a2a/utils/task.py +57 -0
- pygeai/vendor/a2a/utils/telemetry.py +299 -0
- pygeai-0.6.0b15.dist-info/METADATA +205 -0
- pygeai-0.6.0b15.dist-info/RECORD +799 -0
- {pygeai-0.1.51b3.dist-info → pygeai-0.6.0b15.dist-info}/WHEEL +1 -1
- {pygeai-0.1.51b3.dist-info → pygeai-0.6.0b15.dist-info}/entry_points.txt +2 -1
- {pygeai-0.1.51b3.dist-info → pygeai-0.6.0b15.dist-info}/licenses/LICENSE +13 -1
- pygeai-0.6.0b15.dist-info/top_level.txt +1 -0
- docs/geai-proxy/README.md +0 -145
- docs/source/conf.py +0 -45
- pygeai/tests/core/test_managers.py +0 -233
- pygeai-0.1.51b3.dist-info/METADATA +0 -130
- pygeai-0.1.51b3.dist-info/RECORD +0 -324
- pygeai-0.1.51b3.dist-info/top_level.txt +0 -3
- scripts/bump_beta_version.py +0 -56
- {scripts → pygeai/analytics}/__init__.py +0 -0
- /pygeai/tests/snippets/lab/{c_code_fixer_agent_flow.py → use_cases/c_code_fixer_agent_flow.py} +0 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
from a2a.server.tasks.task_store import TaskStore
|
|
5
|
+
from a2a.types import Task
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class InMemoryTaskStore(TaskStore):
|
|
12
|
+
"""In-memory implementation of TaskStore.
|
|
13
|
+
|
|
14
|
+
Stores task objects in a dictionary in memory. Task data is lost when the
|
|
15
|
+
server process stops.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self) -> None:
|
|
19
|
+
"""Initializes the InMemoryTaskStore."""
|
|
20
|
+
logger.debug('Initializing InMemoryTaskStore')
|
|
21
|
+
self.tasks: dict[str, Task] = {}
|
|
22
|
+
self.lock = asyncio.Lock()
|
|
23
|
+
|
|
24
|
+
async def save(self, task: Task) -> None:
|
|
25
|
+
"""Saves or updates a task in the in-memory store."""
|
|
26
|
+
async with self.lock:
|
|
27
|
+
self.tasks[task.id] = task
|
|
28
|
+
logger.debug('Task %s saved successfully.', task.id)
|
|
29
|
+
|
|
30
|
+
async def get(self, task_id: str) -> Task | None:
|
|
31
|
+
"""Retrieves a task from the in-memory store by ID."""
|
|
32
|
+
async with self.lock:
|
|
33
|
+
logger.debug('Attempting to get task with id: %s', task_id)
|
|
34
|
+
task = self.tasks.get(task_id)
|
|
35
|
+
if task:
|
|
36
|
+
logger.debug('Task %s retrieved successfully.', task_id)
|
|
37
|
+
else:
|
|
38
|
+
logger.debug('Task %s not found in store.', task_id)
|
|
39
|
+
return task
|
|
40
|
+
|
|
41
|
+
async def delete(self, task_id: str) -> None:
|
|
42
|
+
"""Deletes a task from the in-memory store by ID."""
|
|
43
|
+
async with self.lock:
|
|
44
|
+
logger.debug('Attempting to delete task with id: %s', task_id)
|
|
45
|
+
if task_id in self.tasks:
|
|
46
|
+
del self.tasks[task_id]
|
|
47
|
+
logger.debug('Task %s deleted successfully.', task_id)
|
|
48
|
+
else:
|
|
49
|
+
logger.warning(
|
|
50
|
+
'Attempted to delete nonexistent task with id: %s', task_id
|
|
51
|
+
)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
from a2a.types import PushNotificationConfig, Task
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class PushNotifier(ABC):
|
|
7
|
+
"""PushNotifier interface to store, retrieve push notification for tasks and send push notifications."""
|
|
8
|
+
|
|
9
|
+
@abstractmethod
|
|
10
|
+
async def set_info(
|
|
11
|
+
self, task_id: str, notification_config: PushNotificationConfig
|
|
12
|
+
) -> None:
|
|
13
|
+
"""Sets or updates the push notification configuration for a task."""
|
|
14
|
+
|
|
15
|
+
@abstractmethod
|
|
16
|
+
async def get_info(self, task_id: str) -> PushNotificationConfig | None:
|
|
17
|
+
"""Retrieves the push notification configuration for a task."""
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
async def delete_info(self, task_id: str) -> None:
|
|
21
|
+
"""Deletes the push notification configuration for a task."""
|
|
22
|
+
|
|
23
|
+
@abstractmethod
|
|
24
|
+
async def send_notification(self, task: Task) -> None:
|
|
25
|
+
"""Sends a push notification containing the latest task state."""
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
from collections.abc import AsyncGenerator, AsyncIterator
|
|
5
|
+
|
|
6
|
+
from a2a.server.events import Event, EventConsumer
|
|
7
|
+
from a2a.server.tasks.task_manager import TaskManager
|
|
8
|
+
from a2a.types import Message, Task, TaskState, TaskStatusUpdateEvent
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ResultAggregator:
|
|
15
|
+
"""ResultAggregator is used to process the event streams from an AgentExecutor.
|
|
16
|
+
|
|
17
|
+
There are three main ways to use the ResultAggregator:
|
|
18
|
+
1) As part of a processing pipe. consume_and_emit will construct the updated
|
|
19
|
+
task as the events arrive, and re-emit those events for another consumer
|
|
20
|
+
2) As part of a blocking call. consume_all will process the entire stream and
|
|
21
|
+
return the final Task or Message object
|
|
22
|
+
3) As part of a push solution where the latest Task is emitted after processing an event.
|
|
23
|
+
consume_and_emit_task will consume the Event stream, process the events to the current
|
|
24
|
+
Task object and emit that Task object.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, task_manager: TaskManager):
|
|
28
|
+
"""Initializes the ResultAggregator.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
task_manager: The `TaskManager` instance to use for processing events
|
|
32
|
+
and managing the task state.
|
|
33
|
+
"""
|
|
34
|
+
self.task_manager = task_manager
|
|
35
|
+
self._message: Message | None = None
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
async def current_result(self) -> Task | Message | None:
|
|
39
|
+
"""Returns the current aggregated result (Task or Message).
|
|
40
|
+
|
|
41
|
+
This is the latest state processed from the event stream.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
The current `Task` object managed by the `TaskManager`, or the final
|
|
45
|
+
`Message` if one was received, or `None` if no result has been produced yet.
|
|
46
|
+
"""
|
|
47
|
+
if self._message:
|
|
48
|
+
return self._message
|
|
49
|
+
return await self.task_manager.get_task()
|
|
50
|
+
|
|
51
|
+
async def consume_and_emit(
|
|
52
|
+
self, consumer: EventConsumer
|
|
53
|
+
) -> AsyncGenerator[Event]:
|
|
54
|
+
"""Processes the event stream from the consumer, updates the task state, and re-emits the same events.
|
|
55
|
+
|
|
56
|
+
Useful for streaming scenarios where the server needs to observe and
|
|
57
|
+
process events (e.g., save task state, send push notifications) while
|
|
58
|
+
forwarding them to the client.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
consumer: The `EventConsumer` to read events from.
|
|
62
|
+
|
|
63
|
+
Yields:
|
|
64
|
+
The `Event` objects consumed from the `EventConsumer`.
|
|
65
|
+
"""
|
|
66
|
+
async for event in consumer.consume_all():
|
|
67
|
+
await self.task_manager.process(event)
|
|
68
|
+
yield event
|
|
69
|
+
|
|
70
|
+
async def consume_all(
|
|
71
|
+
self, consumer: EventConsumer
|
|
72
|
+
) -> Task | Message | None:
|
|
73
|
+
"""Processes the entire event stream from the consumer and returns the final result.
|
|
74
|
+
|
|
75
|
+
Blocks until the event stream ends (queue is closed after final event or exception).
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
consumer: The `EventConsumer` to read events from.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
The final `Task` object or `Message` object after the stream is exhausted.
|
|
82
|
+
Returns `None` if the stream ends without producing a final result.
|
|
83
|
+
|
|
84
|
+
Raises:
|
|
85
|
+
BaseException: If the `EventConsumer` raises an exception during consumption.
|
|
86
|
+
"""
|
|
87
|
+
async for event in consumer.consume_all():
|
|
88
|
+
if isinstance(event, Message):
|
|
89
|
+
self._message = event
|
|
90
|
+
return event
|
|
91
|
+
await self.task_manager.process(event)
|
|
92
|
+
return await self.task_manager.get_task()
|
|
93
|
+
|
|
94
|
+
async def consume_and_break_on_interrupt(
|
|
95
|
+
self, consumer: EventConsumer
|
|
96
|
+
) -> tuple[Task | Message | None, bool]:
|
|
97
|
+
"""Processes the event stream until completion or an interruptable state is encountered.
|
|
98
|
+
|
|
99
|
+
Interruptable states currently include `TaskState.auth_required`.
|
|
100
|
+
If interrupted, consumption continues in a background task.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
consumer: The `EventConsumer` to read events from.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
A tuple containing:
|
|
107
|
+
- The current aggregated result (`Task` or `Message`) at the point of completion or interruption.
|
|
108
|
+
- A boolean indicating whether the consumption was interrupted (`True`) or completed naturally (`False`).
|
|
109
|
+
|
|
110
|
+
Raises:
|
|
111
|
+
BaseException: If the `EventConsumer` raises an exception during consumption.
|
|
112
|
+
"""
|
|
113
|
+
event_stream = consumer.consume_all()
|
|
114
|
+
interrupted = False
|
|
115
|
+
async for event in event_stream:
|
|
116
|
+
if isinstance(event, Message):
|
|
117
|
+
self._message = event
|
|
118
|
+
return event, False
|
|
119
|
+
await self.task_manager.process(event)
|
|
120
|
+
if (
|
|
121
|
+
isinstance(event, Task | TaskStatusUpdateEvent)
|
|
122
|
+
and event.status.state == TaskState.auth_required
|
|
123
|
+
):
|
|
124
|
+
# auth-required is a special state: the message should be
|
|
125
|
+
# escalated back to the caller, but the agent is expected to
|
|
126
|
+
# continue producing events once the authorization is received
|
|
127
|
+
# out-of-band. This is in contrast to input-required, where a
|
|
128
|
+
# new request is expected in order for the agent to make progress,
|
|
129
|
+
# so the agent should exit.
|
|
130
|
+
logger.debug(
|
|
131
|
+
'Encountered an auth-required task: breaking synchronous message/send flow.'
|
|
132
|
+
)
|
|
133
|
+
# TODO: We should track all outstanding tasks to ensure they eventually complete.
|
|
134
|
+
asyncio.create_task(self._continue_consuming(event_stream)) # noqa: RUF006
|
|
135
|
+
interrupted = True
|
|
136
|
+
break
|
|
137
|
+
return await self.task_manager.get_task(), interrupted
|
|
138
|
+
|
|
139
|
+
async def _continue_consuming(
|
|
140
|
+
self, event_stream: AsyncIterator[Event]
|
|
141
|
+
) -> None:
|
|
142
|
+
"""Continues processing an event stream in a background task.
|
|
143
|
+
|
|
144
|
+
Used after an interruptable state (like auth_required) is encountered
|
|
145
|
+
in the synchronous consumption flow.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
event_stream: The remaining `AsyncIterator` of events from the consumer.
|
|
149
|
+
"""
|
|
150
|
+
async for event in event_stream:
|
|
151
|
+
await self.task_manager.process(event)
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from a2a.server.events.event_queue import Event
|
|
4
|
+
from a2a.server.tasks.task_store import TaskStore
|
|
5
|
+
from a2a.types import (
|
|
6
|
+
InvalidParamsError,
|
|
7
|
+
Message,
|
|
8
|
+
Task,
|
|
9
|
+
TaskArtifactUpdateEvent,
|
|
10
|
+
TaskState,
|
|
11
|
+
TaskStatus,
|
|
12
|
+
TaskStatusUpdateEvent,
|
|
13
|
+
)
|
|
14
|
+
from a2a.utils import append_artifact_to_task
|
|
15
|
+
from a2a.utils.errors import ServerError
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TaskManager:
|
|
22
|
+
"""Helps manage a task's lifecycle during execution of a request.
|
|
23
|
+
|
|
24
|
+
Responsible for retrieving, saving, and updating the `Task` object based on
|
|
25
|
+
events received from the agent.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
task_id: str | None,
|
|
31
|
+
context_id: str | None,
|
|
32
|
+
task_store: TaskStore,
|
|
33
|
+
initial_message: Message | None,
|
|
34
|
+
):
|
|
35
|
+
"""Initializes the TaskManager.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
task_id: The ID of the task, if known from the request.
|
|
39
|
+
context_id: The ID of the context, if known from the request.
|
|
40
|
+
task_store: The `TaskStore` instance for persistence.
|
|
41
|
+
initial_message: The `Message` that initiated the task, if any.
|
|
42
|
+
Used when creating a new task object.
|
|
43
|
+
"""
|
|
44
|
+
self.task_id = task_id
|
|
45
|
+
self.context_id = context_id
|
|
46
|
+
self.task_store = task_store
|
|
47
|
+
self._initial_message = initial_message
|
|
48
|
+
self._current_task: Task | None = None
|
|
49
|
+
logger.debug(
|
|
50
|
+
'TaskManager initialized with task_id: %s, context_id: %s',
|
|
51
|
+
task_id,
|
|
52
|
+
context_id,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
async def get_task(self) -> Task | None:
|
|
56
|
+
"""Retrieves the current task object, either from memory or the store.
|
|
57
|
+
|
|
58
|
+
If `task_id` is set, it first checks the in-memory `_current_task`,
|
|
59
|
+
then attempts to load it from the `task_store`.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
The `Task` object if found, otherwise `None`.
|
|
63
|
+
"""
|
|
64
|
+
if not self.task_id:
|
|
65
|
+
logger.debug('task_id is not set, cannot get task.')
|
|
66
|
+
return None
|
|
67
|
+
|
|
68
|
+
if self._current_task:
|
|
69
|
+
return self._current_task
|
|
70
|
+
|
|
71
|
+
logger.debug(
|
|
72
|
+
'Attempting to get task from store with id: %s', self.task_id
|
|
73
|
+
)
|
|
74
|
+
self._current_task = await self.task_store.get(self.task_id)
|
|
75
|
+
if self._current_task:
|
|
76
|
+
logger.debug('Task %s retrieved successfully.', self.task_id)
|
|
77
|
+
else:
|
|
78
|
+
logger.debug('Task %s not found.', self.task_id)
|
|
79
|
+
return self._current_task
|
|
80
|
+
|
|
81
|
+
async def save_task_event(
|
|
82
|
+
self, event: Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent
|
|
83
|
+
) -> Task | None:
|
|
84
|
+
"""Processes a task-related event (Task, Status, Artifact) and saves the updated task state.
|
|
85
|
+
|
|
86
|
+
Ensures task and context IDs match or are set from the event.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
event: The task-related event (`Task`, `TaskStatusUpdateEvent`, or `TaskArtifactUpdateEvent`).
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
The updated `Task` object after processing the event.
|
|
93
|
+
|
|
94
|
+
Raises:
|
|
95
|
+
ServerError: If the task ID in the event conflicts with the TaskManager's ID
|
|
96
|
+
when the TaskManager's ID is already set.
|
|
97
|
+
"""
|
|
98
|
+
task_id_from_event = (
|
|
99
|
+
event.id if isinstance(event, Task) else event.taskId
|
|
100
|
+
)
|
|
101
|
+
# If task id is known, make sure it is matched
|
|
102
|
+
if self.task_id and self.task_id != task_id_from_event:
|
|
103
|
+
raise ServerError(
|
|
104
|
+
error=InvalidParamsError(
|
|
105
|
+
message=f"Task in event doesn't match TaskManager {self.task_id} : {task_id_from_event}"
|
|
106
|
+
)
|
|
107
|
+
)
|
|
108
|
+
if not self.task_id:
|
|
109
|
+
self.task_id = task_id_from_event
|
|
110
|
+
if not self.context_id and self.context_id != event.contextId:
|
|
111
|
+
self.context_id = event.contextId
|
|
112
|
+
|
|
113
|
+
logger.debug(
|
|
114
|
+
'Processing save of task event of type %s for task_id: %s',
|
|
115
|
+
type(event).__name__,
|
|
116
|
+
task_id_from_event,
|
|
117
|
+
)
|
|
118
|
+
if isinstance(event, Task):
|
|
119
|
+
await self._save_task(event)
|
|
120
|
+
return event
|
|
121
|
+
|
|
122
|
+
task: Task = await self.ensure_task(event)
|
|
123
|
+
|
|
124
|
+
if isinstance(event, TaskStatusUpdateEvent):
|
|
125
|
+
logger.debug(
|
|
126
|
+
'Updating task %s status to: %s', task.id, event.status.state
|
|
127
|
+
)
|
|
128
|
+
if task.status.message:
|
|
129
|
+
if not task.history:
|
|
130
|
+
task.history = [task.status.message]
|
|
131
|
+
else:
|
|
132
|
+
task.history.append(task.status.message)
|
|
133
|
+
|
|
134
|
+
task.status = event.status
|
|
135
|
+
else:
|
|
136
|
+
logger.debug('Appending artifact to task %s', task.id)
|
|
137
|
+
append_artifact_to_task(task, event)
|
|
138
|
+
|
|
139
|
+
await self._save_task(task)
|
|
140
|
+
return task
|
|
141
|
+
|
|
142
|
+
async def ensure_task(
|
|
143
|
+
self, event: TaskStatusUpdateEvent | TaskArtifactUpdateEvent
|
|
144
|
+
) -> Task:
|
|
145
|
+
"""Ensures a Task object exists in memory, loading from store or creating new if needed.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
event: The task-related event triggering the need for a Task object.
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
An existing or newly created `Task` object.
|
|
152
|
+
"""
|
|
153
|
+
task: Task | None = self._current_task
|
|
154
|
+
if not task and self.task_id:
|
|
155
|
+
logger.debug(
|
|
156
|
+
'Attempting to retrieve existing task with id: %s', self.task_id
|
|
157
|
+
)
|
|
158
|
+
task = await self.task_store.get(self.task_id)
|
|
159
|
+
|
|
160
|
+
if not task:
|
|
161
|
+
logger.info(
|
|
162
|
+
'Task not found or task_id not set. Creating new task for event (task_id: %s, context_id: %s).',
|
|
163
|
+
event.taskId,
|
|
164
|
+
event.contextId,
|
|
165
|
+
)
|
|
166
|
+
# streaming agent did not previously stream task object.
|
|
167
|
+
# Create a task object with the available information and persist the event
|
|
168
|
+
task = self._init_task_obj(event.taskId, event.contextId)
|
|
169
|
+
await self._save_task(task)
|
|
170
|
+
|
|
171
|
+
return task
|
|
172
|
+
|
|
173
|
+
async def process(self, event: Event) -> Event:
|
|
174
|
+
"""Processes an event, updates the task state if applicable, stores it, and returns the event.
|
|
175
|
+
|
|
176
|
+
If the event is task-related (`Task`, `TaskStatusUpdateEvent`, `TaskArtifactUpdateEvent`),
|
|
177
|
+
the internal task state is updated and persisted.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
event: The event object received from the agent.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
The same event object that was processed.
|
|
184
|
+
"""
|
|
185
|
+
if isinstance(
|
|
186
|
+
event, Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent
|
|
187
|
+
):
|
|
188
|
+
await self.save_task_event(event)
|
|
189
|
+
|
|
190
|
+
return event
|
|
191
|
+
|
|
192
|
+
def _init_task_obj(self, task_id: str, context_id: str) -> Task:
|
|
193
|
+
"""Initializes a new task object in memory.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
task_id: The ID for the new task.
|
|
197
|
+
context_id: The context ID for the new task.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
A new `Task` object with initial status and potentially the initial message in history.
|
|
201
|
+
"""
|
|
202
|
+
logger.debug(
|
|
203
|
+
'Initializing new Task object with task_id: %s, context_id: %s',
|
|
204
|
+
task_id,
|
|
205
|
+
context_id,
|
|
206
|
+
)
|
|
207
|
+
history = [self._initial_message] if self._initial_message else []
|
|
208
|
+
return Task(
|
|
209
|
+
id=task_id,
|
|
210
|
+
contextId=context_id,
|
|
211
|
+
status=TaskStatus(state=TaskState.submitted),
|
|
212
|
+
history=history,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
async def _save_task(self, task: Task) -> None:
|
|
216
|
+
"""Saves the given task to the task store and updates the in-memory `_current_task`.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
task: The `Task` object to save.
|
|
220
|
+
"""
|
|
221
|
+
logger.debug('Saving task with id: %s', task.id)
|
|
222
|
+
await self.task_store.save(task)
|
|
223
|
+
self._current_task = task
|
|
224
|
+
if not self.task_id:
|
|
225
|
+
logger.info('New task created with id: %s', task.id)
|
|
226
|
+
self.task_id = task.id
|
|
227
|
+
self.context_id = task.contextId
|
|
228
|
+
|
|
229
|
+
def update_with_message(self, message: Message, task: Task) -> Task:
|
|
230
|
+
"""Updates a task object in memory by adding a new message to its history.
|
|
231
|
+
|
|
232
|
+
If the task has a message in its current status, that message is moved
|
|
233
|
+
to the history first.
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
message: The new `Message` to add to the history.
|
|
237
|
+
task: The `Task` object to update.
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
The updated `Task` object (updated in-place).
|
|
241
|
+
"""
|
|
242
|
+
if task.status.message:
|
|
243
|
+
if task.history:
|
|
244
|
+
task.history.append(task.status.message)
|
|
245
|
+
else:
|
|
246
|
+
task.history = [task.status.message]
|
|
247
|
+
task.status.message = None
|
|
248
|
+
if task.history:
|
|
249
|
+
task.history.append(message)
|
|
250
|
+
else:
|
|
251
|
+
task.history = [message]
|
|
252
|
+
self._current_task = task
|
|
253
|
+
return task
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
from a2a.types import Task
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TaskStore(ABC):
|
|
7
|
+
"""Agent Task Store interface.
|
|
8
|
+
|
|
9
|
+
Defines the methods for persisting and retrieving `Task` objects.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
@abstractmethod
|
|
13
|
+
async def save(self, task: Task) -> None:
|
|
14
|
+
"""Saves or updates a task in the store."""
|
|
15
|
+
|
|
16
|
+
@abstractmethod
|
|
17
|
+
async def get(self, task_id: str) -> Task | None:
|
|
18
|
+
"""Retrieves a task from the store by ID."""
|
|
19
|
+
|
|
20
|
+
@abstractmethod
|
|
21
|
+
async def delete(self, task_id: str) -> None:
|
|
22
|
+
"""Deletes a task from the store by ID."""
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
from datetime import datetime, timezone
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from a2a.server.events import EventQueue
|
|
7
|
+
from a2a.types import (
|
|
8
|
+
Artifact,
|
|
9
|
+
Message,
|
|
10
|
+
Part,
|
|
11
|
+
Role,
|
|
12
|
+
TaskArtifactUpdateEvent,
|
|
13
|
+
TaskState,
|
|
14
|
+
TaskStatus,
|
|
15
|
+
TaskStatusUpdateEvent,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TaskUpdater:
|
|
20
|
+
"""Helper class for agents to publish updates to a task's event queue.
|
|
21
|
+
|
|
22
|
+
Simplifies the process of creating and enqueueing standard task events.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, event_queue: EventQueue, task_id: str, context_id: str):
|
|
26
|
+
"""Initializes the TaskUpdater.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
event_queue: The `EventQueue` associated with the task.
|
|
30
|
+
task_id: The ID of the task.
|
|
31
|
+
context_id: The context ID of the task.
|
|
32
|
+
"""
|
|
33
|
+
self.event_queue = event_queue
|
|
34
|
+
self.task_id = task_id
|
|
35
|
+
self.context_id = context_id
|
|
36
|
+
|
|
37
|
+
async def update_status(
|
|
38
|
+
self,
|
|
39
|
+
state: TaskState,
|
|
40
|
+
message: Message | None = None,
|
|
41
|
+
final: bool = False,
|
|
42
|
+
timestamp: str | None = None,
|
|
43
|
+
) -> None:
|
|
44
|
+
"""Updates the status of the task and publishes a `TaskStatusUpdateEvent`.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
state: The new state of the task.
|
|
48
|
+
message: An optional message associated with the status update.
|
|
49
|
+
final: If True, indicates this is the final status update for the task.
|
|
50
|
+
timestamp: Optional ISO 8601 datetime string. Defaults to current time.
|
|
51
|
+
"""
|
|
52
|
+
current_timestamp = (
|
|
53
|
+
timestamp if timestamp else datetime.now(timezone.utc).isoformat()
|
|
54
|
+
)
|
|
55
|
+
await self.event_queue.enqueue_event(
|
|
56
|
+
TaskStatusUpdateEvent(
|
|
57
|
+
taskId=self.task_id,
|
|
58
|
+
contextId=self.context_id,
|
|
59
|
+
final=final,
|
|
60
|
+
status=TaskStatus(
|
|
61
|
+
state=state,
|
|
62
|
+
message=message,
|
|
63
|
+
timestamp=current_timestamp,
|
|
64
|
+
),
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
async def add_artifact(
|
|
69
|
+
self,
|
|
70
|
+
parts: list[Part],
|
|
71
|
+
artifact_id: str | None = None,
|
|
72
|
+
name: str | None = None,
|
|
73
|
+
metadata: dict[str, Any] | None = None,
|
|
74
|
+
) -> None:
|
|
75
|
+
"""Adds an artifact chunk to the task and publishes a `TaskArtifactUpdateEvent`.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
parts: A list of `Part` objects forming the artifact chunk.
|
|
79
|
+
artifact_id: The ID of the artifact. A new UUID is generated if not provided.
|
|
80
|
+
name: Optional name for the artifact.
|
|
81
|
+
metadata: Optional metadata for the artifact.
|
|
82
|
+
"""
|
|
83
|
+
if not artifact_id:
|
|
84
|
+
artifact_id = str(uuid.uuid4())
|
|
85
|
+
|
|
86
|
+
await self.event_queue.enqueue_event(
|
|
87
|
+
TaskArtifactUpdateEvent(
|
|
88
|
+
taskId=self.task_id,
|
|
89
|
+
contextId=self.context_id,
|
|
90
|
+
artifact=Artifact(
|
|
91
|
+
artifactId=artifact_id,
|
|
92
|
+
name=name,
|
|
93
|
+
parts=parts,
|
|
94
|
+
metadata=metadata,
|
|
95
|
+
),
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
async def complete(self, message: Message | None = None) -> None:
|
|
100
|
+
"""Marks the task as completed and publishes a final status update."""
|
|
101
|
+
await self.update_status(
|
|
102
|
+
TaskState.completed,
|
|
103
|
+
message=message,
|
|
104
|
+
final=True,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
async def failed(self, message: Message | None = None) -> None:
|
|
108
|
+
"""Marks the task as failed and publishes a final status update."""
|
|
109
|
+
await self.update_status(TaskState.failed, message=message, final=True)
|
|
110
|
+
|
|
111
|
+
async def reject(self, message: Message | None = None) -> None:
|
|
112
|
+
"""Marks the task as rejected and publishes a final status update."""
|
|
113
|
+
await self.update_status(
|
|
114
|
+
TaskState.rejected, message=message, final=True
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
async def submit(self, message: Message | None = None) -> None:
|
|
118
|
+
"""Marks the task as submitted and publishes a status update."""
|
|
119
|
+
await self.update_status(
|
|
120
|
+
TaskState.submitted,
|
|
121
|
+
message=message,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
async def start_work(self, message: Message | None = None) -> None:
|
|
125
|
+
"""Marks the task as working and publishes a status update."""
|
|
126
|
+
await self.update_status(
|
|
127
|
+
TaskState.working,
|
|
128
|
+
message=message,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
def new_agent_message(
|
|
132
|
+
self,
|
|
133
|
+
parts: list[Part],
|
|
134
|
+
metadata: dict[str, Any] | None = None,
|
|
135
|
+
) -> Message:
|
|
136
|
+
"""Creates a new message object sent by the agent for this task/context.
|
|
137
|
+
|
|
138
|
+
Note: This method only *creates* the message object. It does not
|
|
139
|
+
automatically enqueue it.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
parts: A list of `Part` objects for the message content.
|
|
143
|
+
metadata: Optional metadata for the message.
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
A new `Message` object.
|
|
147
|
+
"""
|
|
148
|
+
return Message(
|
|
149
|
+
role=Role.agent,
|
|
150
|
+
taskId=self.task_id,
|
|
151
|
+
contextId=self.context_id,
|
|
152
|
+
messageId=str(uuid.uuid4()),
|
|
153
|
+
metadata=metadata,
|
|
154
|
+
parts=parts,
|
|
155
|
+
)
|