agentex-sdk 0.1.0a6__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.
- agentex/__init__.py +103 -0
- agentex/_base_client.py +1992 -0
- agentex/_client.py +506 -0
- agentex/_compat.py +219 -0
- agentex/_constants.py +14 -0
- agentex/_exceptions.py +108 -0
- agentex/_files.py +123 -0
- agentex/_models.py +829 -0
- agentex/_qs.py +150 -0
- agentex/_resource.py +43 -0
- agentex/_response.py +830 -0
- agentex/_streaming.py +333 -0
- agentex/_types.py +219 -0
- agentex/_utils/__init__.py +57 -0
- agentex/_utils/_logs.py +25 -0
- agentex/_utils/_proxy.py +65 -0
- agentex/_utils/_reflection.py +42 -0
- agentex/_utils/_resources_proxy.py +24 -0
- agentex/_utils/_streams.py +12 -0
- agentex/_utils/_sync.py +86 -0
- agentex/_utils/_transform.py +447 -0
- agentex/_utils/_typing.py +151 -0
- agentex/_utils/_utils.py +422 -0
- agentex/_version.py +4 -0
- agentex/lib/.keep +4 -0
- agentex/lib/__init__.py +0 -0
- agentex/lib/adk/__init__.py +41 -0
- agentex/lib/adk/_modules/__init__.py +0 -0
- agentex/lib/adk/_modules/acp.py +247 -0
- agentex/lib/adk/_modules/agent_task_tracker.py +176 -0
- agentex/lib/adk/_modules/agents.py +77 -0
- agentex/lib/adk/_modules/events.py +141 -0
- agentex/lib/adk/_modules/messages.py +285 -0
- agentex/lib/adk/_modules/state.py +291 -0
- agentex/lib/adk/_modules/streaming.py +75 -0
- agentex/lib/adk/_modules/tasks.py +124 -0
- agentex/lib/adk/_modules/tracing.py +194 -0
- agentex/lib/adk/providers/__init__.py +9 -0
- agentex/lib/adk/providers/_modules/__init__.py +0 -0
- agentex/lib/adk/providers/_modules/litellm.py +232 -0
- agentex/lib/adk/providers/_modules/openai.py +416 -0
- agentex/lib/adk/providers/_modules/sgp.py +85 -0
- agentex/lib/adk/utils/__init__.py +5 -0
- agentex/lib/adk/utils/_modules/__init__.py +0 -0
- agentex/lib/adk/utils/_modules/templating.py +94 -0
- agentex/lib/cli/__init__.py +0 -0
- agentex/lib/cli/commands/__init__.py +0 -0
- agentex/lib/cli/commands/agents.py +328 -0
- agentex/lib/cli/commands/init.py +227 -0
- agentex/lib/cli/commands/main.py +33 -0
- agentex/lib/cli/commands/secrets.py +169 -0
- agentex/lib/cli/commands/tasks.py +118 -0
- agentex/lib/cli/commands/uv.py +133 -0
- agentex/lib/cli/handlers/__init__.py +0 -0
- agentex/lib/cli/handlers/agent_handlers.py +160 -0
- agentex/lib/cli/handlers/cleanup_handlers.py +186 -0
- agentex/lib/cli/handlers/deploy_handlers.py +351 -0
- agentex/lib/cli/handlers/run_handlers.py +452 -0
- agentex/lib/cli/handlers/secret_handlers.py +670 -0
- agentex/lib/cli/templates/default/.dockerignore.j2 +43 -0
- agentex/lib/cli/templates/default/Dockerfile-uv.j2 +42 -0
- agentex/lib/cli/templates/default/Dockerfile.j2 +42 -0
- agentex/lib/cli/templates/default/README.md.j2 +193 -0
- agentex/lib/cli/templates/default/deploy/example.yaml.j2 +55 -0
- agentex/lib/cli/templates/default/manifest.yaml.j2 +116 -0
- agentex/lib/cli/templates/default/project/acp.py.j2 +29 -0
- agentex/lib/cli/templates/default/pyproject.toml.j2 +33 -0
- agentex/lib/cli/templates/default/requirements.txt.j2 +5 -0
- agentex/lib/cli/templates/deploy/Screenshot 2025-03-19 at 10.36.57/342/200/257AM.png +0 -0
- agentex/lib/cli/templates/deploy/example.yaml.j2 +55 -0
- agentex/lib/cli/templates/sync/.dockerignore.j2 +43 -0
- agentex/lib/cli/templates/sync/Dockerfile-uv.j2 +42 -0
- agentex/lib/cli/templates/sync/Dockerfile.j2 +42 -0
- agentex/lib/cli/templates/sync/README.md.j2 +293 -0
- agentex/lib/cli/templates/sync/deploy/example.yaml.j2 +55 -0
- agentex/lib/cli/templates/sync/manifest.yaml.j2 +116 -0
- agentex/lib/cli/templates/sync/project/acp.py.j2 +26 -0
- agentex/lib/cli/templates/sync/pyproject.toml.j2 +33 -0
- agentex/lib/cli/templates/sync/requirements.txt.j2 +5 -0
- agentex/lib/cli/templates/temporal/.dockerignore.j2 +43 -0
- agentex/lib/cli/templates/temporal/Dockerfile-uv.j2 +48 -0
- agentex/lib/cli/templates/temporal/Dockerfile.j2 +48 -0
- agentex/lib/cli/templates/temporal/README.md.j2 +316 -0
- agentex/lib/cli/templates/temporal/deploy/example.yaml.j2 +55 -0
- agentex/lib/cli/templates/temporal/manifest.yaml.j2 +137 -0
- agentex/lib/cli/templates/temporal/project/acp.py.j2 +30 -0
- agentex/lib/cli/templates/temporal/project/run_worker.py.j2 +33 -0
- agentex/lib/cli/templates/temporal/project/workflow.py.j2 +66 -0
- agentex/lib/cli/templates/temporal/pyproject.toml.j2 +34 -0
- agentex/lib/cli/templates/temporal/requirements.txt.j2 +5 -0
- agentex/lib/cli/utils/cli_utils.py +14 -0
- agentex/lib/cli/utils/credential_utils.py +103 -0
- agentex/lib/cli/utils/exceptions.py +6 -0
- agentex/lib/cli/utils/kubectl_utils.py +135 -0
- agentex/lib/cli/utils/kubernetes_secrets_utils.py +185 -0
- agentex/lib/core/__init__.py +0 -0
- agentex/lib/core/adapters/__init__.py +0 -0
- agentex/lib/core/adapters/llm/__init__.py +1 -0
- agentex/lib/core/adapters/llm/adapter_litellm.py +46 -0
- agentex/lib/core/adapters/llm/adapter_sgp.py +55 -0
- agentex/lib/core/adapters/llm/port.py +24 -0
- agentex/lib/core/adapters/streams/adapter_redis.py +128 -0
- agentex/lib/core/adapters/streams/port.py +50 -0
- agentex/lib/core/clients/__init__.py +1 -0
- agentex/lib/core/clients/temporal/__init__.py +0 -0
- agentex/lib/core/clients/temporal/temporal_client.py +181 -0
- agentex/lib/core/clients/temporal/types.py +47 -0
- agentex/lib/core/clients/temporal/utils.py +56 -0
- agentex/lib/core/services/__init__.py +0 -0
- agentex/lib/core/services/adk/__init__.py +0 -0
- agentex/lib/core/services/adk/acp/__init__.py +0 -0
- agentex/lib/core/services/adk/acp/acp.py +210 -0
- agentex/lib/core/services/adk/agent_task_tracker.py +85 -0
- agentex/lib/core/services/adk/agents.py +43 -0
- agentex/lib/core/services/adk/events.py +61 -0
- agentex/lib/core/services/adk/messages.py +164 -0
- agentex/lib/core/services/adk/providers/__init__.py +0 -0
- agentex/lib/core/services/adk/providers/litellm.py +256 -0
- agentex/lib/core/services/adk/providers/openai.py +723 -0
- agentex/lib/core/services/adk/providers/sgp.py +99 -0
- agentex/lib/core/services/adk/state.py +120 -0
- agentex/lib/core/services/adk/streaming.py +262 -0
- agentex/lib/core/services/adk/tasks.py +69 -0
- agentex/lib/core/services/adk/tracing.py +36 -0
- agentex/lib/core/services/adk/utils/__init__.py +0 -0
- agentex/lib/core/services/adk/utils/templating.py +58 -0
- agentex/lib/core/temporal/__init__.py +0 -0
- agentex/lib/core/temporal/activities/__init__.py +207 -0
- agentex/lib/core/temporal/activities/activity_helpers.py +37 -0
- agentex/lib/core/temporal/activities/adk/__init__.py +0 -0
- agentex/lib/core/temporal/activities/adk/acp/__init__.py +0 -0
- agentex/lib/core/temporal/activities/adk/acp/acp_activities.py +86 -0
- agentex/lib/core/temporal/activities/adk/agent_task_tracker_activities.py +76 -0
- agentex/lib/core/temporal/activities/adk/agents_activities.py +35 -0
- agentex/lib/core/temporal/activities/adk/events_activities.py +50 -0
- agentex/lib/core/temporal/activities/adk/messages_activities.py +94 -0
- agentex/lib/core/temporal/activities/adk/providers/__init__.py +0 -0
- agentex/lib/core/temporal/activities/adk/providers/litellm_activities.py +71 -0
- agentex/lib/core/temporal/activities/adk/providers/openai_activities.py +210 -0
- agentex/lib/core/temporal/activities/adk/providers/sgp_activities.py +42 -0
- agentex/lib/core/temporal/activities/adk/state_activities.py +85 -0
- agentex/lib/core/temporal/activities/adk/streaming_activities.py +33 -0
- agentex/lib/core/temporal/activities/adk/tasks_activities.py +48 -0
- agentex/lib/core/temporal/activities/adk/tracing_activities.py +55 -0
- agentex/lib/core/temporal/activities/adk/utils/__init__.py +0 -0
- agentex/lib/core/temporal/activities/adk/utils/templating_activities.py +41 -0
- agentex/lib/core/temporal/services/__init__.py +0 -0
- agentex/lib/core/temporal/services/temporal_task_service.py +69 -0
- agentex/lib/core/temporal/types/__init__.py +0 -0
- agentex/lib/core/temporal/types/workflow.py +5 -0
- agentex/lib/core/temporal/workers/__init__.py +0 -0
- agentex/lib/core/temporal/workers/worker.py +162 -0
- agentex/lib/core/temporal/workflows/workflow.py +26 -0
- agentex/lib/core/tracing/__init__.py +5 -0
- agentex/lib/core/tracing/processors/agentex_tracing_processor.py +117 -0
- agentex/lib/core/tracing/processors/sgp_tracing_processor.py +119 -0
- agentex/lib/core/tracing/processors/tracing_processor_interface.py +40 -0
- agentex/lib/core/tracing/trace.py +311 -0
- agentex/lib/core/tracing/tracer.py +70 -0
- agentex/lib/core/tracing/tracing_processor_manager.py +62 -0
- agentex/lib/environment_variables.py +87 -0
- agentex/lib/py.typed +0 -0
- agentex/lib/sdk/__init__.py +0 -0
- agentex/lib/sdk/config/__init__.py +0 -0
- agentex/lib/sdk/config/agent_config.py +61 -0
- agentex/lib/sdk/config/agent_manifest.py +219 -0
- agentex/lib/sdk/config/build_config.py +35 -0
- agentex/lib/sdk/config/deployment_config.py +117 -0
- agentex/lib/sdk/config/local_development_config.py +56 -0
- agentex/lib/sdk/config/project_config.py +103 -0
- agentex/lib/sdk/fastacp/__init__.py +3 -0
- agentex/lib/sdk/fastacp/base/base_acp_server.py +406 -0
- agentex/lib/sdk/fastacp/fastacp.py +74 -0
- agentex/lib/sdk/fastacp/impl/agentic_base_acp.py +72 -0
- agentex/lib/sdk/fastacp/impl/sync_acp.py +109 -0
- agentex/lib/sdk/fastacp/impl/temporal_acp.py +97 -0
- agentex/lib/sdk/fastacp/tests/README.md +297 -0
- agentex/lib/sdk/fastacp/tests/conftest.py +307 -0
- agentex/lib/sdk/fastacp/tests/pytest.ini +10 -0
- agentex/lib/sdk/fastacp/tests/run_tests.py +227 -0
- agentex/lib/sdk/fastacp/tests/test_base_acp_server.py +450 -0
- agentex/lib/sdk/fastacp/tests/test_fastacp_factory.py +344 -0
- agentex/lib/sdk/fastacp/tests/test_integration.py +477 -0
- agentex/lib/sdk/state_machine/__init__.py +6 -0
- agentex/lib/sdk/state_machine/noop_workflow.py +21 -0
- agentex/lib/sdk/state_machine/state.py +10 -0
- agentex/lib/sdk/state_machine/state_machine.py +189 -0
- agentex/lib/sdk/state_machine/state_workflow.py +16 -0
- agentex/lib/sdk/utils/__init__.py +0 -0
- agentex/lib/sdk/utils/messages.py +223 -0
- agentex/lib/types/__init__.py +0 -0
- agentex/lib/types/acp.py +94 -0
- agentex/lib/types/agent_configs.py +79 -0
- agentex/lib/types/agent_results.py +29 -0
- agentex/lib/types/credentials.py +34 -0
- agentex/lib/types/fastacp.py +61 -0
- agentex/lib/types/files.py +13 -0
- agentex/lib/types/json_rpc.py +49 -0
- agentex/lib/types/llm_messages.py +354 -0
- agentex/lib/types/task_message_updates.py +171 -0
- agentex/lib/types/tracing.py +34 -0
- agentex/lib/utils/__init__.py +0 -0
- agentex/lib/utils/completions.py +131 -0
- agentex/lib/utils/console.py +14 -0
- agentex/lib/utils/io.py +29 -0
- agentex/lib/utils/iterables.py +14 -0
- agentex/lib/utils/json_schema.py +23 -0
- agentex/lib/utils/logging.py +31 -0
- agentex/lib/utils/mcp.py +17 -0
- agentex/lib/utils/model_utils.py +46 -0
- agentex/lib/utils/parsing.py +15 -0
- agentex/lib/utils/regex.py +6 -0
- agentex/lib/utils/temporal.py +13 -0
- agentex/py.typed +0 -0
- agentex/resources/__init__.py +103 -0
- agentex/resources/agents.py +707 -0
- agentex/resources/events.py +294 -0
- agentex/resources/messages/__init__.py +33 -0
- agentex/resources/messages/batch.py +271 -0
- agentex/resources/messages/messages.py +492 -0
- agentex/resources/spans.py +557 -0
- agentex/resources/states.py +544 -0
- agentex/resources/tasks.py +615 -0
- agentex/resources/tracker.py +384 -0
- agentex/types/__init__.py +56 -0
- agentex/types/acp_type.py +7 -0
- agentex/types/agent.py +29 -0
- agentex/types/agent_list_params.py +13 -0
- agentex/types/agent_list_response.py +10 -0
- agentex/types/agent_rpc_by_name_params.py +21 -0
- agentex/types/agent_rpc_params.py +51 -0
- agentex/types/agent_rpc_params1.py +21 -0
- agentex/types/agent_rpc_response.py +20 -0
- agentex/types/agent_rpc_result.py +90 -0
- agentex/types/agent_task_tracker.py +34 -0
- agentex/types/data_content.py +30 -0
- agentex/types/data_content_param.py +31 -0
- agentex/types/data_delta.py +14 -0
- agentex/types/event.py +29 -0
- agentex/types/event_list_params.py +22 -0
- agentex/types/event_list_response.py +10 -0
- agentex/types/message_author.py +7 -0
- agentex/types/message_create_params.py +18 -0
- agentex/types/message_list_params.py +14 -0
- agentex/types/message_list_response.py +10 -0
- agentex/types/message_style.py +7 -0
- agentex/types/message_update_params.py +18 -0
- agentex/types/messages/__init__.py +8 -0
- agentex/types/messages/batch_create_params.py +16 -0
- agentex/types/messages/batch_create_response.py +10 -0
- agentex/types/messages/batch_update_params.py +16 -0
- agentex/types/messages/batch_update_response.py +10 -0
- agentex/types/shared/__init__.py +3 -0
- agentex/types/shared/task_message_update.py +83 -0
- agentex/types/span.py +36 -0
- agentex/types/span_create_params.py +40 -0
- agentex/types/span_list_params.py +12 -0
- agentex/types/span_list_response.py +10 -0
- agentex/types/span_update_params.py +37 -0
- agentex/types/state.py +25 -0
- agentex/types/state_create_params.py +16 -0
- agentex/types/state_list_params.py +16 -0
- agentex/types/state_list_response.py +10 -0
- agentex/types/state_update_params.py +16 -0
- agentex/types/task.py +23 -0
- agentex/types/task_delete_by_name_response.py +8 -0
- agentex/types/task_delete_response.py +8 -0
- agentex/types/task_list_response.py +10 -0
- agentex/types/task_message.py +33 -0
- agentex/types/task_message_content.py +16 -0
- agentex/types/task_message_content_param.py +17 -0
- agentex/types/task_message_delta.py +16 -0
- agentex/types/text_content.py +53 -0
- agentex/types/text_content_param.py +54 -0
- agentex/types/text_delta.py +14 -0
- agentex/types/tool_request_content.py +36 -0
- agentex/types/tool_request_content_param.py +37 -0
- agentex/types/tool_request_delta.py +18 -0
- agentex/types/tool_response_content.py +36 -0
- agentex/types/tool_response_content_param.py +36 -0
- agentex/types/tool_response_delta.py +18 -0
- agentex/types/tracker_list_params.py +16 -0
- agentex/types/tracker_list_response.py +10 -0
- agentex/types/tracker_update_params.py +19 -0
- agentex_sdk-0.1.0a6.dist-info/METADATA +426 -0
- agentex_sdk-0.1.0a6.dist-info/RECORD +289 -0
- agentex_sdk-0.1.0a6.dist-info/WHEEL +4 -0
- agentex_sdk-0.1.0a6.dist-info/entry_points.txt +2 -0
- agentex_sdk-0.1.0a6.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,723 @@
|
|
1
|
+
# Standard library imports
|
2
|
+
import json
|
3
|
+
from contextlib import AsyncExitStack, asynccontextmanager
|
4
|
+
from typing import Any, Literal
|
5
|
+
|
6
|
+
from agents import Agent, Runner, RunResult, RunResultStreaming
|
7
|
+
from agents.agent import StopAtTools, ToolsToFinalOutputFunction
|
8
|
+
from agents.mcp import MCPServerStdio
|
9
|
+
from mcp import StdioServerParameters
|
10
|
+
from openai.types.responses import (
|
11
|
+
ResponseCompletedEvent,
|
12
|
+
ResponseFunctionToolCall,
|
13
|
+
ResponseOutputItemDoneEvent,
|
14
|
+
ResponseTextDeltaEvent,
|
15
|
+
)
|
16
|
+
from pydantic import BaseModel
|
17
|
+
|
18
|
+
# Local imports
|
19
|
+
from agentex import AsyncAgentex
|
20
|
+
from agentex.lib.core.services.adk.streaming import (
|
21
|
+
StreamingService,
|
22
|
+
StreamingTaskMessageContext,
|
23
|
+
)
|
24
|
+
from agentex.lib.core.tracing.tracer import AsyncTracer
|
25
|
+
from agentex.lib.types.task_message_updates import (
|
26
|
+
StreamTaskMessageDelta,
|
27
|
+
StreamTaskMessageFull,
|
28
|
+
TextDelta,
|
29
|
+
)
|
30
|
+
from agentex.types.task_message_content import (
|
31
|
+
TextContent,
|
32
|
+
ToolRequestContent,
|
33
|
+
ToolResponseContent,
|
34
|
+
)
|
35
|
+
from agentex.lib.utils import logging
|
36
|
+
from agentex.lib.utils.mcp import redact_mcp_server_params
|
37
|
+
from agentex.lib.utils.temporal import heartbeat_if_in_workflow
|
38
|
+
|
39
|
+
logger = logging.make_logger(__name__)
|
40
|
+
|
41
|
+
|
42
|
+
@asynccontextmanager
|
43
|
+
async def mcp_server_context(
|
44
|
+
mcp_server_params: list[StdioServerParameters],
|
45
|
+
mcp_timeout_seconds: int | None = None,
|
46
|
+
):
|
47
|
+
"""Context manager for MCP servers."""
|
48
|
+
servers = []
|
49
|
+
for params in mcp_server_params:
|
50
|
+
server = MCPServerStdio(
|
51
|
+
name=f"Server: {params.command}",
|
52
|
+
params=params.model_dump(),
|
53
|
+
cache_tools_list=True,
|
54
|
+
client_session_timeout_seconds=mcp_timeout_seconds,
|
55
|
+
)
|
56
|
+
servers.append(server)
|
57
|
+
|
58
|
+
async with AsyncExitStack() as stack:
|
59
|
+
for server in servers:
|
60
|
+
await stack.enter_async_context(server)
|
61
|
+
yield servers
|
62
|
+
|
63
|
+
|
64
|
+
class OpenAIService:
|
65
|
+
"""Service for OpenAI agent operations using the agents library."""
|
66
|
+
|
67
|
+
def __init__(
|
68
|
+
self,
|
69
|
+
agentex_client: AsyncAgentex | None = None,
|
70
|
+
streaming_service: StreamingService | None = None,
|
71
|
+
tracer: AsyncTracer | None = None,
|
72
|
+
):
|
73
|
+
self.agentex_client = agentex_client
|
74
|
+
self.streaming_service = streaming_service
|
75
|
+
self.tracer = tracer
|
76
|
+
|
77
|
+
async def run_agent(
|
78
|
+
self,
|
79
|
+
input_list: list[dict[str, Any]],
|
80
|
+
mcp_server_params: list[StdioServerParameters],
|
81
|
+
agent_name: str,
|
82
|
+
agent_instructions: str,
|
83
|
+
trace_id: str | None = None,
|
84
|
+
parent_span_id: str | None = None,
|
85
|
+
handoff_description: str | None = None,
|
86
|
+
handoffs: list[BaseModel] | None = None,
|
87
|
+
model: str | None = None,
|
88
|
+
model_settings: BaseModel | None = None,
|
89
|
+
tools: list[BaseModel] | None = None,
|
90
|
+
output_type: type[Any] | None = None,
|
91
|
+
tool_use_behavior: (
|
92
|
+
Literal["run_llm_again", "stop_on_first_tool"]
|
93
|
+
| StopAtTools
|
94
|
+
| ToolsToFinalOutputFunction
|
95
|
+
) = "run_llm_again",
|
96
|
+
mcp_timeout_seconds: int | None = None,
|
97
|
+
) -> RunResult:
|
98
|
+
"""
|
99
|
+
Run an agent without streaming or TaskMessage creation.
|
100
|
+
|
101
|
+
Args:
|
102
|
+
input_list: List of input data for the agent.
|
103
|
+
mcp_server_params: MCP server parameters for the agent.
|
104
|
+
agent_name: The name of the agent to run.
|
105
|
+
agent_instructions: Instructions for the agent.
|
106
|
+
trace_id: Optional trace ID for tracing.
|
107
|
+
parent_span_id: Optional parent span ID for tracing.
|
108
|
+
handoff_description: Optional description of the handoff.
|
109
|
+
handoffs: Optional list of handoffs.
|
110
|
+
model: Optional model to use.
|
111
|
+
model_settings: Optional model settings.
|
112
|
+
tools: Optional list of tools.
|
113
|
+
output_type: Optional output type.
|
114
|
+
tool_use_behavior: Optional tool use behavior.
|
115
|
+
mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
|
116
|
+
|
117
|
+
Returns:
|
118
|
+
SerializableRunResult: The result of the agent run.
|
119
|
+
"""
|
120
|
+
redacted_params = redact_mcp_server_params(mcp_server_params)
|
121
|
+
|
122
|
+
trace = self.tracer.trace(trace_id)
|
123
|
+
async with trace.span(
|
124
|
+
parent_id=parent_span_id,
|
125
|
+
name="run_agent",
|
126
|
+
input={
|
127
|
+
"input_list": input_list,
|
128
|
+
"mcp_server_params": redacted_params,
|
129
|
+
"agent_name": agent_name,
|
130
|
+
"agent_instructions": agent_instructions,
|
131
|
+
"handoff_description": handoff_description,
|
132
|
+
"handoffs": handoffs,
|
133
|
+
"model": model,
|
134
|
+
"model_settings": model_settings,
|
135
|
+
"tools": tools,
|
136
|
+
"output_type": output_type,
|
137
|
+
"tool_use_behavior": tool_use_behavior,
|
138
|
+
},
|
139
|
+
) as span:
|
140
|
+
heartbeat_if_in_workflow("run agent")
|
141
|
+
|
142
|
+
async with mcp_server_context(
|
143
|
+
mcp_server_params, mcp_timeout_seconds
|
144
|
+
) as servers:
|
145
|
+
tools = [tool.to_oai_function_tool() for tool in tools] if tools else []
|
146
|
+
handoffs = (
|
147
|
+
[Agent(**handoff.model_dump()) for handoff in handoffs]
|
148
|
+
if handoffs
|
149
|
+
else []
|
150
|
+
)
|
151
|
+
|
152
|
+
agent_kwargs = {
|
153
|
+
"name": agent_name,
|
154
|
+
"instructions": agent_instructions,
|
155
|
+
"mcp_servers": servers,
|
156
|
+
"handoff_description": handoff_description,
|
157
|
+
"handoffs": handoffs,
|
158
|
+
"model": model,
|
159
|
+
"tools": tools,
|
160
|
+
"output_type": output_type,
|
161
|
+
"tool_use_behavior": tool_use_behavior,
|
162
|
+
}
|
163
|
+
if model_settings is not None:
|
164
|
+
agent_kwargs["model_settings"] = (
|
165
|
+
model_settings.to_oai_model_settings()
|
166
|
+
)
|
167
|
+
|
168
|
+
agent = Agent(**agent_kwargs)
|
169
|
+
|
170
|
+
# Run without streaming
|
171
|
+
result = await Runner.run(starting_agent=agent, input=input_list)
|
172
|
+
|
173
|
+
if span:
|
174
|
+
span.output = {
|
175
|
+
"new_items": [
|
176
|
+
item.raw_item.model_dump()
|
177
|
+
if isinstance(item.raw_item, BaseModel)
|
178
|
+
else item.raw_item
|
179
|
+
for item in result.new_items
|
180
|
+
],
|
181
|
+
"final_output": result.final_output,
|
182
|
+
}
|
183
|
+
|
184
|
+
return result
|
185
|
+
|
186
|
+
async def run_agent_auto_send(
|
187
|
+
self,
|
188
|
+
task_id: str,
|
189
|
+
input_list: list[dict[str, Any]],
|
190
|
+
mcp_server_params: list[StdioServerParameters],
|
191
|
+
agent_name: str,
|
192
|
+
agent_instructions: str,
|
193
|
+
trace_id: str | None = None,
|
194
|
+
parent_span_id: str | None = None,
|
195
|
+
handoff_description: str | None = None,
|
196
|
+
handoffs: list[BaseModel] | None = None,
|
197
|
+
model: str | None = None,
|
198
|
+
model_settings: BaseModel | None = None,
|
199
|
+
tools: list[BaseModel] | None = None,
|
200
|
+
output_type: type[Any] | None = None,
|
201
|
+
tool_use_behavior: (
|
202
|
+
Literal["run_llm_again", "stop_on_first_tool"]
|
203
|
+
| StopAtTools
|
204
|
+
| ToolsToFinalOutputFunction
|
205
|
+
) = "run_llm_again",
|
206
|
+
mcp_timeout_seconds: int | None = None,
|
207
|
+
) -> RunResult:
|
208
|
+
"""
|
209
|
+
Run an agent with automatic TaskMessage creation.
|
210
|
+
|
211
|
+
Args:
|
212
|
+
task_id: The ID of the task to run the agent for.
|
213
|
+
input_list: List of input data for the agent.
|
214
|
+
mcp_server_params: MCP server parameters for the agent.
|
215
|
+
agent_name: The name of the agent to run.
|
216
|
+
agent_instructions: Instructions for the agent.
|
217
|
+
trace_id: Optional trace ID for tracing.
|
218
|
+
parent_span_id: Optional parent span ID for tracing.
|
219
|
+
handoff_description: Optional description of the handoff.
|
220
|
+
handoffs: Optional list of handoffs.
|
221
|
+
model: Optional model to use.
|
222
|
+
model_settings: Optional model settings.
|
223
|
+
tools: Optional list of tools.
|
224
|
+
output_type: Optional output type.
|
225
|
+
tool_use_behavior: Optional tool use behavior.
|
226
|
+
mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
|
227
|
+
|
228
|
+
Returns:
|
229
|
+
SerializableRunResult: The result of the agent run.
|
230
|
+
"""
|
231
|
+
if self.streaming_service is None:
|
232
|
+
raise ValueError("StreamingService must be available for auto_send methods")
|
233
|
+
if self.agentex_client is None:
|
234
|
+
raise ValueError("Agentex client must be provided for auto_send methods")
|
235
|
+
|
236
|
+
redacted_params = redact_mcp_server_params(mcp_server_params)
|
237
|
+
|
238
|
+
trace = self.tracer.trace(trace_id)
|
239
|
+
async with trace.span(
|
240
|
+
parent_id=parent_span_id,
|
241
|
+
name="run_agent_auto_send",
|
242
|
+
input={
|
243
|
+
"task_id": task_id,
|
244
|
+
"input_list": input_list,
|
245
|
+
"mcp_server_params": redacted_params,
|
246
|
+
"agent_name": agent_name,
|
247
|
+
"agent_instructions": agent_instructions,
|
248
|
+
"handoff_description": handoff_description,
|
249
|
+
"handoffs": handoffs,
|
250
|
+
"model": model,
|
251
|
+
"model_settings": model_settings,
|
252
|
+
"tools": tools,
|
253
|
+
"output_type": output_type,
|
254
|
+
"tool_use_behavior": tool_use_behavior,
|
255
|
+
},
|
256
|
+
) as span:
|
257
|
+
heartbeat_if_in_workflow("run agent auto send")
|
258
|
+
|
259
|
+
async with mcp_server_context(
|
260
|
+
mcp_server_params, mcp_timeout_seconds
|
261
|
+
) as servers:
|
262
|
+
tools = [tool.to_oai_function_tool() for tool in tools] if tools else []
|
263
|
+
handoffs = (
|
264
|
+
[Agent(**handoff.model_dump()) for handoff in handoffs]
|
265
|
+
if handoffs
|
266
|
+
else []
|
267
|
+
)
|
268
|
+
agent_kwargs = {
|
269
|
+
"name": agent_name,
|
270
|
+
"instructions": agent_instructions,
|
271
|
+
"mcp_servers": servers,
|
272
|
+
"handoff_description": handoff_description,
|
273
|
+
"handoffs": handoffs,
|
274
|
+
"model": model,
|
275
|
+
"tools": tools,
|
276
|
+
"output_type": output_type,
|
277
|
+
"tool_use_behavior": tool_use_behavior,
|
278
|
+
}
|
279
|
+
if model_settings is not None:
|
280
|
+
agent_kwargs["model_settings"] = (
|
281
|
+
model_settings.to_oai_model_settings()
|
282
|
+
)
|
283
|
+
|
284
|
+
agent = Agent(**agent_kwargs)
|
285
|
+
|
286
|
+
# Run without streaming
|
287
|
+
result = await Runner.run(starting_agent=agent, input=input_list)
|
288
|
+
|
289
|
+
if span:
|
290
|
+
span.output = {
|
291
|
+
"new_items": [
|
292
|
+
item.raw_item.model_dump()
|
293
|
+
if isinstance(item.raw_item, BaseModel)
|
294
|
+
else item.raw_item
|
295
|
+
for item in result.new_items
|
296
|
+
],
|
297
|
+
"final_output": result.final_output,
|
298
|
+
}
|
299
|
+
|
300
|
+
tool_call_map: dict[str, ResponseFunctionToolCall] = {}
|
301
|
+
|
302
|
+
for item in result.new_items:
|
303
|
+
if item.type == "message_output_item":
|
304
|
+
text_content = TextContent(
|
305
|
+
author="agent",
|
306
|
+
content=item.raw_item.content[0].text,
|
307
|
+
)
|
308
|
+
# Create message for the final result using streaming context
|
309
|
+
async with (
|
310
|
+
self.streaming_service.streaming_task_message_context(
|
311
|
+
task_id=task_id,
|
312
|
+
initial_content=text_content,
|
313
|
+
) as streaming_context
|
314
|
+
):
|
315
|
+
await streaming_context.stream_update(
|
316
|
+
update=StreamTaskMessageFull(
|
317
|
+
parent_task_message=streaming_context.task_message,
|
318
|
+
content=text_content,
|
319
|
+
),
|
320
|
+
)
|
321
|
+
|
322
|
+
elif item.type == "tool_call_item":
|
323
|
+
tool_call_map[item.raw_item.call_id] = item.raw_item
|
324
|
+
|
325
|
+
tool_request_content = ToolRequestContent(
|
326
|
+
author="agent",
|
327
|
+
tool_call_id=item.raw_item.call_id,
|
328
|
+
name=item.raw_item.name,
|
329
|
+
arguments=json.loads(item.raw_item.arguments),
|
330
|
+
)
|
331
|
+
|
332
|
+
# Create tool request using streaming context
|
333
|
+
async with (
|
334
|
+
self.streaming_service.streaming_task_message_context(
|
335
|
+
task_id=task_id,
|
336
|
+
initial_content=tool_request_content,
|
337
|
+
) as streaming_context
|
338
|
+
):
|
339
|
+
await streaming_context.stream_update(
|
340
|
+
update=StreamTaskMessageFull(
|
341
|
+
parent_task_message=streaming_context.task_message,
|
342
|
+
content=tool_request_content,
|
343
|
+
),
|
344
|
+
)
|
345
|
+
|
346
|
+
elif item.type == "tool_call_output_item":
|
347
|
+
tool_output_item = item.raw_item
|
348
|
+
|
349
|
+
tool_response_content = ToolResponseContent(
|
350
|
+
author="agent",
|
351
|
+
tool_call_id=tool_output_item["call_id"],
|
352
|
+
name=tool_call_map[tool_output_item["call_id"]].name,
|
353
|
+
content=tool_output_item["output"],
|
354
|
+
)
|
355
|
+
# Create tool response using streaming context
|
356
|
+
async with (
|
357
|
+
self.streaming_service.streaming_task_message_context(
|
358
|
+
task_id=task_id,
|
359
|
+
initial_content=tool_response_content,
|
360
|
+
) as streaming_context
|
361
|
+
):
|
362
|
+
await streaming_context.stream_update(
|
363
|
+
update=StreamTaskMessageFull(
|
364
|
+
parent_task_message=streaming_context.task_message,
|
365
|
+
content=tool_response_content,
|
366
|
+
),
|
367
|
+
)
|
368
|
+
|
369
|
+
# Convert to serializable result
|
370
|
+
return result
|
371
|
+
|
372
|
+
async def run_agent_streamed(
|
373
|
+
self,
|
374
|
+
input_list: list[dict[str, Any]],
|
375
|
+
mcp_server_params: list[StdioServerParameters],
|
376
|
+
agent_name: str,
|
377
|
+
agent_instructions: str,
|
378
|
+
trace_id: str | None = None,
|
379
|
+
parent_span_id: str | None = None,
|
380
|
+
handoff_description: str | None = None,
|
381
|
+
handoffs: list[BaseModel] | None = None,
|
382
|
+
model: str | None = None,
|
383
|
+
model_settings: BaseModel | None = None,
|
384
|
+
tools: list[BaseModel] | None = None,
|
385
|
+
output_type: type[Any] | None = None,
|
386
|
+
tool_use_behavior: (
|
387
|
+
Literal["run_llm_again", "stop_on_first_tool"]
|
388
|
+
| StopAtTools
|
389
|
+
| ToolsToFinalOutputFunction
|
390
|
+
) = "run_llm_again",
|
391
|
+
mcp_timeout_seconds: int | None = None,
|
392
|
+
) -> RunResultStreaming:
|
393
|
+
"""
|
394
|
+
Run an agent with streaming enabled but no TaskMessage creation.
|
395
|
+
|
396
|
+
Args:
|
397
|
+
input_list: List of input data for the agent.
|
398
|
+
mcp_server_params: MCP server parameters for the agent.
|
399
|
+
agent_name: The name of the agent to run.
|
400
|
+
agent_instructions: Instructions for the agent.
|
401
|
+
trace_id: Optional trace ID for tracing.
|
402
|
+
parent_span_id: Optional parent span ID for tracing.
|
403
|
+
handoff_description: Optional description of the handoff.
|
404
|
+
handoffs: Optional list of handoffs.
|
405
|
+
model: Optional model to use.
|
406
|
+
model_settings: Optional model settings.
|
407
|
+
tools: Optional list of tools.
|
408
|
+
output_type: Optional output type.
|
409
|
+
tool_use_behavior: Optional tool use behavior.
|
410
|
+
mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
|
411
|
+
|
412
|
+
Returns:
|
413
|
+
RunResultStreaming: The result of the agent run with streaming.
|
414
|
+
"""
|
415
|
+
trace = self.tracer.trace(trace_id)
|
416
|
+
redacted_params = redact_mcp_server_params(mcp_server_params)
|
417
|
+
|
418
|
+
async with trace.span(
|
419
|
+
parent_id=parent_span_id,
|
420
|
+
name="run_agent_streamed",
|
421
|
+
input={
|
422
|
+
"input_list": input_list,
|
423
|
+
"mcp_server_params": redacted_params,
|
424
|
+
"agent_name": agent_name,
|
425
|
+
"agent_instructions": agent_instructions,
|
426
|
+
"handoff_description": handoff_description,
|
427
|
+
"handoffs": handoffs,
|
428
|
+
"model": model,
|
429
|
+
"model_settings": model_settings,
|
430
|
+
"tools": tools,
|
431
|
+
"output_type": output_type,
|
432
|
+
"tool_use_behavior": tool_use_behavior,
|
433
|
+
},
|
434
|
+
) as span:
|
435
|
+
heartbeat_if_in_workflow("run agent streamed")
|
436
|
+
|
437
|
+
async with mcp_server_context(
|
438
|
+
mcp_server_params, mcp_timeout_seconds
|
439
|
+
) as servers:
|
440
|
+
tools = [tool.to_oai_function_tool() for tool in tools] if tools else []
|
441
|
+
handoffs = (
|
442
|
+
[Agent(**handoff.model_dump()) for handoff in handoffs]
|
443
|
+
if handoffs
|
444
|
+
else []
|
445
|
+
)
|
446
|
+
agent_kwargs = {
|
447
|
+
"name": agent_name,
|
448
|
+
"instructions": agent_instructions,
|
449
|
+
"mcp_servers": servers,
|
450
|
+
"handoff_description": handoff_description,
|
451
|
+
"handoffs": handoffs,
|
452
|
+
"model": model,
|
453
|
+
"tools": tools,
|
454
|
+
"output_type": output_type,
|
455
|
+
"tool_use_behavior": tool_use_behavior,
|
456
|
+
}
|
457
|
+
if model_settings is not None:
|
458
|
+
agent_kwargs["model_settings"] = (
|
459
|
+
model_settings.to_oai_model_settings()
|
460
|
+
)
|
461
|
+
|
462
|
+
agent = Agent(**agent_kwargs)
|
463
|
+
|
464
|
+
# Run with streaming (but no TaskMessage creation)
|
465
|
+
result = Runner.run_streamed(starting_agent=agent, input=input_list)
|
466
|
+
|
467
|
+
if span:
|
468
|
+
span.output = {
|
469
|
+
"new_items": [
|
470
|
+
item.raw_item.model_dump()
|
471
|
+
if isinstance(item.raw_item, BaseModel)
|
472
|
+
else item.raw_item
|
473
|
+
for item in result.new_items
|
474
|
+
],
|
475
|
+
"final_output": result.final_output,
|
476
|
+
}
|
477
|
+
|
478
|
+
return result
|
479
|
+
|
480
|
+
async def run_agent_streamed_auto_send(
|
481
|
+
self,
|
482
|
+
task_id: str,
|
483
|
+
input_list: list[dict[str, Any]],
|
484
|
+
mcp_server_params: list[StdioServerParameters],
|
485
|
+
agent_name: str,
|
486
|
+
agent_instructions: str,
|
487
|
+
trace_id: str | None = None,
|
488
|
+
parent_span_id: str | None = None,
|
489
|
+
handoff_description: str | None = None,
|
490
|
+
handoffs: list[BaseModel] | None = None,
|
491
|
+
model: str | None = None,
|
492
|
+
model_settings: BaseModel | None = None,
|
493
|
+
tools: list[BaseModel] | None = None,
|
494
|
+
output_type: type[Any] | None = None,
|
495
|
+
tool_use_behavior: (
|
496
|
+
Literal["run_llm_again", "stop_on_first_tool"]
|
497
|
+
| StopAtTools
|
498
|
+
| ToolsToFinalOutputFunction
|
499
|
+
) = "run_llm_again",
|
500
|
+
mcp_timeout_seconds: int | None = None,
|
501
|
+
) -> RunResultStreaming:
|
502
|
+
"""
|
503
|
+
Run an agent with streaming enabled and automatic TaskMessage creation.
|
504
|
+
|
505
|
+
Args:
|
506
|
+
task_id: The ID of the task to run the agent for.
|
507
|
+
input_list: List of input data for the agent.
|
508
|
+
mcp_server_params: MCP server parameters for the agent.
|
509
|
+
agent_name: The name of the agent to run.
|
510
|
+
agent_instructions: Instructions for the agent.
|
511
|
+
trace_id: Optional trace ID for tracing.
|
512
|
+
parent_span_id: Optional parent span ID for tracing.
|
513
|
+
handoff_description: Optional description of the handoff.
|
514
|
+
handoffs: Optional list of handoffs.
|
515
|
+
model: Optional model to use.
|
516
|
+
model_settings: Optional model settings.
|
517
|
+
tools: Optional list of tools.
|
518
|
+
output_type: Optional output type.
|
519
|
+
tool_use_behavior: Optional tool use behavior.
|
520
|
+
mcp_timeout_seconds: Optional param to set the timeout threshold for the MCP servers. Defaults to 5 seconds.
|
521
|
+
|
522
|
+
Returns:
|
523
|
+
RunResultStreaming: The result of the agent run with streaming.
|
524
|
+
"""
|
525
|
+
if self.streaming_service is None:
|
526
|
+
raise ValueError("StreamingService must be available for auto_send methods")
|
527
|
+
if self.agentex_client is None:
|
528
|
+
raise ValueError("Agentex client must be provided for auto_send methods")
|
529
|
+
|
530
|
+
tool_call_map: dict[str, ResponseFunctionToolCall] = {}
|
531
|
+
|
532
|
+
trace = self.tracer.trace(trace_id)
|
533
|
+
redacted_params = redact_mcp_server_params(mcp_server_params)
|
534
|
+
|
535
|
+
async with trace.span(
|
536
|
+
parent_id=parent_span_id,
|
537
|
+
name="run_agent_streamed_auto_send",
|
538
|
+
input={
|
539
|
+
"task_id": task_id,
|
540
|
+
"input_list": input_list,
|
541
|
+
"mcp_server_params": redacted_params,
|
542
|
+
"agent_name": agent_name,
|
543
|
+
"agent_instructions": agent_instructions,
|
544
|
+
"handoff_description": handoff_description,
|
545
|
+
"handoffs": handoffs,
|
546
|
+
"model": model,
|
547
|
+
"model_settings": model_settings,
|
548
|
+
"tools": tools,
|
549
|
+
"output_type": output_type,
|
550
|
+
"tool_use_behavior": tool_use_behavior,
|
551
|
+
},
|
552
|
+
) as span:
|
553
|
+
heartbeat_if_in_workflow("run agent streamed auto send")
|
554
|
+
|
555
|
+
async with mcp_server_context(
|
556
|
+
mcp_server_params, mcp_timeout_seconds
|
557
|
+
) as servers:
|
558
|
+
tools = [tool.to_oai_function_tool() for tool in tools] if tools else []
|
559
|
+
handoffs = (
|
560
|
+
[Agent(**handoff.model_dump()) for handoff in handoffs]
|
561
|
+
if handoffs
|
562
|
+
else []
|
563
|
+
)
|
564
|
+
agent_kwargs = {
|
565
|
+
"name": agent_name,
|
566
|
+
"instructions": agent_instructions,
|
567
|
+
"mcp_servers": servers,
|
568
|
+
"handoff_description": handoff_description,
|
569
|
+
"handoffs": handoffs,
|
570
|
+
"model": model,
|
571
|
+
"tools": tools,
|
572
|
+
"output_type": output_type,
|
573
|
+
"tool_use_behavior": tool_use_behavior,
|
574
|
+
}
|
575
|
+
if model_settings is not None:
|
576
|
+
agent_kwargs["model_settings"] = (
|
577
|
+
model_settings.to_oai_model_settings()
|
578
|
+
)
|
579
|
+
|
580
|
+
agent = Agent(**agent_kwargs)
|
581
|
+
|
582
|
+
# Run with streaming
|
583
|
+
result = Runner.run_streamed(starting_agent=agent, input=input_list)
|
584
|
+
|
585
|
+
item_id_to_streaming_context: dict[
|
586
|
+
str, StreamingTaskMessageContext
|
587
|
+
] = {}
|
588
|
+
unclosed_item_ids: set[str] = set()
|
589
|
+
|
590
|
+
try:
|
591
|
+
# Process streaming events with TaskMessage creation
|
592
|
+
async for event in result.stream_events():
|
593
|
+
heartbeat_if_in_workflow(
|
594
|
+
"processing stream event with auto send"
|
595
|
+
)
|
596
|
+
|
597
|
+
if event.type == "run_item_stream_event":
|
598
|
+
if event.item.type == "tool_call_item":
|
599
|
+
tool_call_item = event.item.raw_item
|
600
|
+
tool_call_map[tool_call_item.call_id] = tool_call_item
|
601
|
+
|
602
|
+
tool_request_content = ToolRequestContent(
|
603
|
+
author="agent",
|
604
|
+
tool_call_id=tool_call_item.call_id,
|
605
|
+
name=tool_call_item.name,
|
606
|
+
arguments=json.loads(tool_call_item.arguments),
|
607
|
+
)
|
608
|
+
|
609
|
+
# Create tool request using streaming context (immediate completion)
|
610
|
+
async with (
|
611
|
+
self.streaming_service.streaming_task_message_context(
|
612
|
+
task_id=task_id,
|
613
|
+
initial_content=tool_request_content,
|
614
|
+
) as streaming_context
|
615
|
+
):
|
616
|
+
# The message has already been persisted, but we still need to send an upda
|
617
|
+
await streaming_context.stream_update(
|
618
|
+
update=StreamTaskMessageFull(
|
619
|
+
parent_task_message=streaming_context.task_message,
|
620
|
+
content=tool_request_content,
|
621
|
+
),
|
622
|
+
)
|
623
|
+
|
624
|
+
elif event.item.type == "tool_call_output_item":
|
625
|
+
tool_output_item = event.item.raw_item
|
626
|
+
|
627
|
+
tool_response_content = ToolResponseContent(
|
628
|
+
author="agent",
|
629
|
+
tool_call_id=tool_output_item["call_id"],
|
630
|
+
name=tool_call_map[
|
631
|
+
tool_output_item["call_id"]
|
632
|
+
].name,
|
633
|
+
content=tool_output_item["output"],
|
634
|
+
)
|
635
|
+
|
636
|
+
# Create tool response using streaming context (immediate completion)
|
637
|
+
async with (
|
638
|
+
self.streaming_service.streaming_task_message_context(
|
639
|
+
task_id=task_id,
|
640
|
+
initial_content=tool_response_content,
|
641
|
+
) as streaming_context
|
642
|
+
):
|
643
|
+
# The message has already been persisted, but we still need to send an update
|
644
|
+
await streaming_context.stream_update(
|
645
|
+
update=StreamTaskMessageFull(
|
646
|
+
parent_task_message=streaming_context.task_message,
|
647
|
+
content=tool_response_content,
|
648
|
+
),
|
649
|
+
)
|
650
|
+
|
651
|
+
elif event.type == "raw_response_event":
|
652
|
+
if isinstance(event.data, ResponseTextDeltaEvent):
|
653
|
+
# Handle text delta
|
654
|
+
item_id = event.data.item_id
|
655
|
+
|
656
|
+
# Check if we already have a streaming context for this item
|
657
|
+
if item_id not in item_id_to_streaming_context:
|
658
|
+
# Create a new streaming context for this item
|
659
|
+
streaming_context = self.streaming_service.streaming_task_message_context(
|
660
|
+
task_id=task_id,
|
661
|
+
initial_content=TextContent(
|
662
|
+
author="agent",
|
663
|
+
content="",
|
664
|
+
),
|
665
|
+
)
|
666
|
+
# Open the streaming context
|
667
|
+
item_id_to_streaming_context[
|
668
|
+
item_id
|
669
|
+
] = await streaming_context.open()
|
670
|
+
unclosed_item_ids.add(item_id)
|
671
|
+
else:
|
672
|
+
streaming_context = item_id_to_streaming_context[
|
673
|
+
item_id
|
674
|
+
]
|
675
|
+
|
676
|
+
# Stream the delta through the streaming service
|
677
|
+
await streaming_context.stream_update(
|
678
|
+
update=StreamTaskMessageDelta(
|
679
|
+
parent_task_message=streaming_context.task_message,
|
680
|
+
delta=TextDelta(text_delta=event.data.delta),
|
681
|
+
),
|
682
|
+
)
|
683
|
+
|
684
|
+
elif isinstance(event.data, ResponseOutputItemDoneEvent):
|
685
|
+
# Handle item completion
|
686
|
+
item_id = event.data.item.id
|
687
|
+
|
688
|
+
# Finish the streaming context (sends DONE event and updates message)
|
689
|
+
if item_id in item_id_to_streaming_context:
|
690
|
+
streaming_context = item_id_to_streaming_context[
|
691
|
+
item_id
|
692
|
+
]
|
693
|
+
await streaming_context.close()
|
694
|
+
unclosed_item_ids.remove(item_id)
|
695
|
+
|
696
|
+
elif isinstance(event.data, ResponseCompletedEvent):
|
697
|
+
# All items complete, finish all remaining streaming contexts for this session
|
698
|
+
for item_id in unclosed_item_ids:
|
699
|
+
streaming_context = item_id_to_streaming_context[
|
700
|
+
item_id
|
701
|
+
]
|
702
|
+
await streaming_context.close()
|
703
|
+
unclosed_item_ids.remove(item_id)
|
704
|
+
|
705
|
+
finally:
|
706
|
+
# Cleanup: ensure all streaming contexts for this session are properly finished
|
707
|
+
for item_id in unclosed_item_ids:
|
708
|
+
streaming_context = item_id_to_streaming_context[item_id]
|
709
|
+
await streaming_context.close()
|
710
|
+
unclosed_item_ids.remove(item_id)
|
711
|
+
|
712
|
+
if span:
|
713
|
+
span.output = {
|
714
|
+
"new_items": [
|
715
|
+
item.raw_item.model_dump()
|
716
|
+
if isinstance(item.raw_item, BaseModel)
|
717
|
+
else item.raw_item
|
718
|
+
for item in result.new_items
|
719
|
+
],
|
720
|
+
"final_output": result.final_output,
|
721
|
+
}
|
722
|
+
|
723
|
+
return result
|