mirror of
https://github.com/openai/codex.git
synced 2026-05-16 17:23:57 +00:00
## Why The Python SDK previously protected the stdio transport with a single active turn-consumer guard. That avoided competing reads from stdout, but it also meant one `Codex`/`AsyncCodex` client could not stream multiple active turns at the same time. Notifications could also arrive before the caller received a `TurnHandle` and registered for streaming, so the SDK needed an explicit routing layer instead of letting individual API calls read directly from the shared transport. ## What Changed - Added a private `MessageRouter` that owns per-request response queues, per-turn notification queues, pending turn-notification replay, and global notification delivery behind a single stdout reader thread. - Generated typed notification routing metadata so turn IDs come from known payload shapes instead of router-side attribute guessing, with explicit fallback handling for unknown notification payloads. - Updated sync and async turn streaming so `TurnHandle.stream()`/`run()` and `stream_text()` consume only notifications for their own turn ID, while `AsyncAppServerClient` no longer serializes all transport calls behind one async lock. - Cleared pending turn-notification buffers when unregistered turns complete so never-consumed turn handles do not leave stale queues behind. - Removed the internal stream-until helper now that turn completion waiting can register directly with routed turn notifications. - Updated Python SDK docs and focused tests for concurrent transport calls, interleaved turn routing, buffered early notifications, unknown notification routing, async delegation, and routed turn completion behavior. ## Validation - `uv run --extra dev ruff format scripts/update_sdk_artifacts.py src/codex_app_server/_message_router.py src/codex_app_server/client.py src/codex_app_server/generated/notification_registry.py tests/test_client_rpc_methods.py tests/test_public_api_runtime_behavior.py tests/test_async_client_behavior.py` - `uv run --extra dev ruff check scripts/update_sdk_artifacts.py src/codex_app_server/_message_router.py src/codex_app_server/client.py src/codex_app_server/generated/notification_registry.py tests/test_client_rpc_methods.py tests/test_public_api_runtime_behavior.py tests/test_async_client_behavior.py` - `uv run --extra dev pytest tests/test_client_rpc_methods.py tests/test_public_api_runtime_behavior.py tests/test_async_client_behavior.py` - `git diff --check` --------- Co-authored-by: Codex <noreply@openai.com>
173 lines
8.4 KiB
Python
173 lines
8.4 KiB
Python
# Auto-generated by scripts/update_sdk_artifacts.py
|
|
# DO NOT EDIT MANUALLY.
|
|
|
|
from __future__ import annotations
|
|
|
|
from pydantic import BaseModel
|
|
|
|
from .v2_all import AccountLoginCompletedNotification
|
|
from .v2_all import AccountRateLimitsUpdatedNotification
|
|
from .v2_all import AccountUpdatedNotification
|
|
from .v2_all import AgentMessageDeltaNotification
|
|
from .v2_all import AppListUpdatedNotification
|
|
from .v2_all import CommandExecOutputDeltaNotification
|
|
from .v2_all import CommandExecutionOutputDeltaNotification
|
|
from .v2_all import ConfigWarningNotification
|
|
from .v2_all import ContextCompactedNotification
|
|
from .v2_all import DeprecationNoticeNotification
|
|
from .v2_all import ErrorNotification
|
|
from .v2_all import ExternalAgentConfigImportCompletedNotification
|
|
from .v2_all import FileChangeOutputDeltaNotification
|
|
from .v2_all import FileChangePatchUpdatedNotification
|
|
from .v2_all import FsChangedNotification
|
|
from .v2_all import FuzzyFileSearchSessionCompletedNotification
|
|
from .v2_all import FuzzyFileSearchSessionUpdatedNotification
|
|
from .v2_all import GuardianWarningNotification
|
|
from .v2_all import HookCompletedNotification
|
|
from .v2_all import HookStartedNotification
|
|
from .v2_all import ItemCompletedNotification
|
|
from .v2_all import ItemGuardianApprovalReviewCompletedNotification
|
|
from .v2_all import ItemGuardianApprovalReviewStartedNotification
|
|
from .v2_all import ItemStartedNotification
|
|
from .v2_all import McpServerOauthLoginCompletedNotification
|
|
from .v2_all import McpServerStatusUpdatedNotification
|
|
from .v2_all import McpToolCallProgressNotification
|
|
from .v2_all import ModelReroutedNotification
|
|
from .v2_all import ModelVerificationNotification
|
|
from .v2_all import PlanDeltaNotification
|
|
from .v2_all import ReasoningSummaryPartAddedNotification
|
|
from .v2_all import ReasoningSummaryTextDeltaNotification
|
|
from .v2_all import ReasoningTextDeltaNotification
|
|
from .v2_all import RemoteControlStatusChangedNotification
|
|
from .v2_all import ServerRequestResolvedNotification
|
|
from .v2_all import SkillsChangedNotification
|
|
from .v2_all import TerminalInteractionNotification
|
|
from .v2_all import ThreadArchivedNotification
|
|
from .v2_all import ThreadClosedNotification
|
|
from .v2_all import ThreadGoalClearedNotification
|
|
from .v2_all import ThreadGoalUpdatedNotification
|
|
from .v2_all import ThreadNameUpdatedNotification
|
|
from .v2_all import ThreadRealtimeClosedNotification
|
|
from .v2_all import ThreadRealtimeErrorNotification
|
|
from .v2_all import ThreadRealtimeItemAddedNotification
|
|
from .v2_all import ThreadRealtimeOutputAudioDeltaNotification
|
|
from .v2_all import ThreadRealtimeSdpNotification
|
|
from .v2_all import ThreadRealtimeStartedNotification
|
|
from .v2_all import ThreadRealtimeTranscriptDeltaNotification
|
|
from .v2_all import ThreadRealtimeTranscriptDoneNotification
|
|
from .v2_all import ThreadStartedNotification
|
|
from .v2_all import ThreadStatusChangedNotification
|
|
from .v2_all import ThreadTokenUsageUpdatedNotification
|
|
from .v2_all import ThreadUnarchivedNotification
|
|
from .v2_all import TurnCompletedNotification
|
|
from .v2_all import TurnDiffUpdatedNotification
|
|
from .v2_all import TurnPlanUpdatedNotification
|
|
from .v2_all import TurnStartedNotification
|
|
from .v2_all import WarningNotification
|
|
from .v2_all import WindowsSandboxSetupCompletedNotification
|
|
from .v2_all import WindowsWorldWritableWarningNotification
|
|
|
|
NOTIFICATION_MODELS: dict[str, type[BaseModel]] = {
|
|
"account/login/completed": AccountLoginCompletedNotification,
|
|
"account/rateLimits/updated": AccountRateLimitsUpdatedNotification,
|
|
"account/updated": AccountUpdatedNotification,
|
|
"app/list/updated": AppListUpdatedNotification,
|
|
"command/exec/outputDelta": CommandExecOutputDeltaNotification,
|
|
"configWarning": ConfigWarningNotification,
|
|
"deprecationNotice": DeprecationNoticeNotification,
|
|
"error": ErrorNotification,
|
|
"externalAgentConfig/import/completed": ExternalAgentConfigImportCompletedNotification,
|
|
"fs/changed": FsChangedNotification,
|
|
"fuzzyFileSearch/sessionCompleted": FuzzyFileSearchSessionCompletedNotification,
|
|
"fuzzyFileSearch/sessionUpdated": FuzzyFileSearchSessionUpdatedNotification,
|
|
"guardianWarning": GuardianWarningNotification,
|
|
"hook/completed": HookCompletedNotification,
|
|
"hook/started": HookStartedNotification,
|
|
"item/agentMessage/delta": AgentMessageDeltaNotification,
|
|
"item/autoApprovalReview/completed": ItemGuardianApprovalReviewCompletedNotification,
|
|
"item/autoApprovalReview/started": ItemGuardianApprovalReviewStartedNotification,
|
|
"item/commandExecution/outputDelta": CommandExecutionOutputDeltaNotification,
|
|
"item/commandExecution/terminalInteraction": TerminalInteractionNotification,
|
|
"item/completed": ItemCompletedNotification,
|
|
"item/fileChange/outputDelta": FileChangeOutputDeltaNotification,
|
|
"item/fileChange/patchUpdated": FileChangePatchUpdatedNotification,
|
|
"item/mcpToolCall/progress": McpToolCallProgressNotification,
|
|
"item/plan/delta": PlanDeltaNotification,
|
|
"item/reasoning/summaryPartAdded": ReasoningSummaryPartAddedNotification,
|
|
"item/reasoning/summaryTextDelta": ReasoningSummaryTextDeltaNotification,
|
|
"item/reasoning/textDelta": ReasoningTextDeltaNotification,
|
|
"item/started": ItemStartedNotification,
|
|
"mcpServer/oauthLogin/completed": McpServerOauthLoginCompletedNotification,
|
|
"mcpServer/startupStatus/updated": McpServerStatusUpdatedNotification,
|
|
"model/rerouted": ModelReroutedNotification,
|
|
"model/verification": ModelVerificationNotification,
|
|
"remoteControl/status/changed": RemoteControlStatusChangedNotification,
|
|
"serverRequest/resolved": ServerRequestResolvedNotification,
|
|
"skills/changed": SkillsChangedNotification,
|
|
"thread/archived": ThreadArchivedNotification,
|
|
"thread/closed": ThreadClosedNotification,
|
|
"thread/compacted": ContextCompactedNotification,
|
|
"thread/goal/cleared": ThreadGoalClearedNotification,
|
|
"thread/goal/updated": ThreadGoalUpdatedNotification,
|
|
"thread/name/updated": ThreadNameUpdatedNotification,
|
|
"thread/realtime/closed": ThreadRealtimeClosedNotification,
|
|
"thread/realtime/error": ThreadRealtimeErrorNotification,
|
|
"thread/realtime/itemAdded": ThreadRealtimeItemAddedNotification,
|
|
"thread/realtime/outputAudio/delta": ThreadRealtimeOutputAudioDeltaNotification,
|
|
"thread/realtime/sdp": ThreadRealtimeSdpNotification,
|
|
"thread/realtime/started": ThreadRealtimeStartedNotification,
|
|
"thread/realtime/transcript/delta": ThreadRealtimeTranscriptDeltaNotification,
|
|
"thread/realtime/transcript/done": ThreadRealtimeTranscriptDoneNotification,
|
|
"thread/started": ThreadStartedNotification,
|
|
"thread/status/changed": ThreadStatusChangedNotification,
|
|
"thread/tokenUsage/updated": ThreadTokenUsageUpdatedNotification,
|
|
"thread/unarchived": ThreadUnarchivedNotification,
|
|
"turn/completed": TurnCompletedNotification,
|
|
"turn/diff/updated": TurnDiffUpdatedNotification,
|
|
"turn/plan/updated": TurnPlanUpdatedNotification,
|
|
"turn/started": TurnStartedNotification,
|
|
"warning": WarningNotification,
|
|
"windows/worldWritableWarning": WindowsWorldWritableWarningNotification,
|
|
"windowsSandbox/setupCompleted": WindowsSandboxSetupCompletedNotification,
|
|
}
|
|
|
|
DIRECT_TURN_ID_NOTIFICATION_TYPES: tuple[type[BaseModel], ...] = (
|
|
AgentMessageDeltaNotification,
|
|
CommandExecutionOutputDeltaNotification,
|
|
ContextCompactedNotification,
|
|
ErrorNotification,
|
|
FileChangeOutputDeltaNotification,
|
|
FileChangePatchUpdatedNotification,
|
|
HookCompletedNotification,
|
|
HookStartedNotification,
|
|
ItemCompletedNotification,
|
|
ItemGuardianApprovalReviewCompletedNotification,
|
|
ItemGuardianApprovalReviewStartedNotification,
|
|
ItemStartedNotification,
|
|
McpToolCallProgressNotification,
|
|
ModelReroutedNotification,
|
|
ModelVerificationNotification,
|
|
PlanDeltaNotification,
|
|
ReasoningSummaryPartAddedNotification,
|
|
ReasoningSummaryTextDeltaNotification,
|
|
ReasoningTextDeltaNotification,
|
|
TerminalInteractionNotification,
|
|
ThreadGoalUpdatedNotification,
|
|
ThreadTokenUsageUpdatedNotification,
|
|
TurnDiffUpdatedNotification,
|
|
TurnPlanUpdatedNotification,
|
|
)
|
|
|
|
NESTED_TURN_NOTIFICATION_TYPES: tuple[type[BaseModel], ...] = (
|
|
TurnCompletedNotification,
|
|
TurnStartedNotification,
|
|
)
|
|
|
|
|
|
def notification_turn_id(payload: BaseModel) -> str | None:
|
|
if isinstance(payload, DIRECT_TURN_ID_NOTIFICATION_TYPES):
|
|
return payload.turn_id if isinstance(payload.turn_id, str) else None
|
|
if isinstance(payload, NESTED_TURN_NOTIFICATION_TYPES):
|
|
return payload.turn.id
|
|
return None
|