diff --git a/sdk/python/README.md b/sdk/python/README.md index d5bffc2ab7..5fbb145c70 100644 --- a/sdk/python/README.md +++ b/sdk/python/README.md @@ -1,4 +1,4 @@ -# OpenAI Codex Python SDK (Beta) +# OpenAI Codex Python SDK Build Python applications that start Codex threads, run turns, stream progress, and control workspace access. diff --git a/sdk/python/docs/api-reference.md b/sdk/python/docs/api-reference.md index f253185dc5..fbf1abb49c 100644 --- a/sdk/python/docs/api-reference.md +++ b/sdk/python/docs/api-reference.md @@ -1,8 +1,8 @@ -# OpenAI Codex Python SDK (Beta) - API Reference +# OpenAI Codex Python SDK - API Reference Public surface of `openai_codex` for Codex workflows. -This SDK is in beta. Public APIs may change before `1.0`. Turn streams are routed by turn ID so one client can consume multiple active turns concurrently. +Turn streams are routed by turn ID so one client can consume multiple active turns concurrently. Thread starts default to `ApprovalMode.auto_review`; turn starts accept an optional `approval_mode` override. ## Package Entry diff --git a/sdk/python/docs/faq.md b/sdk/python/docs/faq.md index 6fff536a71..c21624a283 100644 --- a/sdk/python/docs/faq.md +++ b/sdk/python/docs/faq.md @@ -2,15 +2,13 @@ ## Is the Python SDK stable? -`openai-codex` is a public beta. Install it with -`pip install openai-codex`; public APIs may change before `1.0`. While beta -releases are the only published SDK releases, pip selects the latest beta. -After a stable release exists, pass `--pre` to opt into newer prereleases. +`openai-codex` publishes stable releases. Install the latest one with +`pip install openai-codex`. ## Why does the SDK install a runtime package? -The SDK and runtime packages are versioned independently. Each SDK release -pins and installs one compatible runtime dependency automatically. +The SDK version tracks the corresponding Codex CLI release. Each SDK release +pins and installs its matching runtime dependency automatically. ## Thread vs turn diff --git a/sdk/python/docs/getting-started.md b/sdk/python/docs/getting-started.md index 96d22ec3c2..af7b71026f 100644 --- a/sdk/python/docs/getting-started.md +++ b/sdk/python/docs/getting-started.md @@ -1,6 +1,6 @@ # Getting Started -This guide gets a published OpenAI Codex Python SDK beta installation running +This guide gets a published OpenAI Codex Python SDK installation running with a multi-turn thread. ## 1. Install @@ -16,10 +16,8 @@ Requirements: - Python `>=3.10` - An existing Codex account session, or one of the login flows below -The SDK installs its compatible `openai-codex-cli-bin` runtime dependency -automatically. While beta releases are the only published SDK releases, this -normal install command selects the latest beta. After a stable release exists, -use `pip install --pre openai-codex` to opt into a newer prerelease. +The SDK installs its matching `openai-codex-cli-bin` runtime dependency +automatically. SDK release versions track the corresponding Codex CLI release. ## 2. Authenticate When Needed diff --git a/sdk/python/examples/README.md b/sdk/python/examples/README.md index a86580cc76..79be5890ed 100644 --- a/sdk/python/examples/README.md +++ b/sdk/python/examples/README.md @@ -16,7 +16,7 @@ multimodal or structured input lists. - Python `>=3.10` - Install the SDK for the same Python interpreter you will use to run examples -Install the published beta: +Install the published SDK: ```bash python -m pip install openai-codex diff --git a/sdk/python/pyproject.toml b/sdk/python/pyproject.toml index 44bdf00c11..a6ff55ee74 100644 --- a/sdk/python/pyproject.toml +++ b/sdk/python/pyproject.toml @@ -12,11 +12,11 @@ license = "Apache-2.0" authors = [{ name = "OpenAI" }] keywords = ["codex", "sdk", "llm", "ai", "agents"] classifiers = [ - "Development Status :: 4 - Beta", + "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Topic :: Software Development :: Libraries :: Python Modules", ] -dependencies = ["pydantic>=2.12", "openai-codex-cli-bin==0.137.0a4"] +dependencies = ["pydantic>=2.12", "openai-codex-cli-bin==0.144.4"] [project.urls] Homepage = "https://github.com/openai/codex" @@ -65,10 +65,10 @@ combine-as-imports = true [tool.uv] exclude-newer = "7 days" -exclude-newer-package = { openai-codex-cli-bin = "2026-06-03T19:00:00Z" } +exclude-newer-package = { openai-codex-cli-bin = "2026-07-15T01:00:00Z" } index-strategy = "first-index" [tool.uv.pip] exclude-newer = "7 days" -exclude-newer-package = { openai-codex-cli-bin = "2026-06-03T19:00:00Z" } +exclude-newer-package = { openai-codex-cli-bin = "2026-07-15T01:00:00Z" } index-strategy = "first-index" diff --git a/sdk/python/scripts/update_sdk_artifacts.py b/sdk/python/scripts/update_sdk_artifacts.py index 1c6ec59402..463472e5f9 100755 --- a/sdk/python/scripts/update_sdk_artifacts.py +++ b/sdk/python/scripts/update_sdk_artifacts.py @@ -616,6 +616,8 @@ def generate_v2_all(schema_dir: Path) -> None: cwd=sdk_root(), ) _require_nullable_chatgpt_account_email(out_path) + _preserve_reasoning_effort_enum(out_path) + _preserve_thread_source_enum(out_path) _normalize_generated_timestamps(out_path) @@ -643,6 +645,66 @@ def _require_nullable_chatgpt_account_email(out_path: Path) -> None: out_path.write_text(source[:class_start] + class_source + source[class_end:]) +def _preserve_reasoning_effort_enum(out_path: Path) -> None: + """Keep the public effort constants while accepting future wire values.""" + source = out_path.read_text() + class_start = source.find("class ReasoningEffort(RootModel[str]):") + if class_start == -1: + raise RuntimeError("Generated SDK is missing the open ReasoningEffort model") + class_end = source.find("\n\nclass ", class_start) + if class_end == -1: + class_end = len(source) + + class_source = source[class_start:class_end] + if "min_length=1" not in class_source: + raise RuntimeError("Generated ReasoningEffort did not preserve the non-empty constraint") + open_enum = """class ReasoningEffort(str, Enum): + none = "none" + minimal = "minimal" + low = "low" + medium = "medium" + high = "high" + xhigh = "xhigh" + + @classmethod + def _missing_(cls, value: object) -> ReasoningEffort | None: + if not isinstance(value, str) or not value: + return None + member = str.__new__(cls, value) + member._name_ = value + member._value_ = value + return member +""" + out_path.write_text(source[:class_start] + open_enum + source[class_end:]) + + +def _preserve_thread_source_enum(out_path: Path) -> None: + """Keep the public thread-source constants while accepting future wire values.""" + source = out_path.read_text() + class_start = source.find("class ThreadSource(RootModel[str]):") + if class_start == -1: + raise RuntimeError("Generated SDK is missing the open ThreadSource model") + class_end = source.find("\n\nclass ", class_start) + if class_end == -1: + class_end = len(source) + + open_enum = """class ThreadSource(str, Enum): + user = "user" + subagent = "subagent" + memory_consolidation = "memory_consolidation" + + @classmethod + def _missing_(cls, value: object) -> ThreadSource | None: + if not isinstance(value, str): + return None + member = str.__new__(cls, value) + member._name_ = value + member._value_ = value + return member +""" + out_path.write_text(source[:class_start] + open_enum + source[class_end:]) + + def _notification_specs(schema_dir: Path) -> list[tuple[str, str]]: """Map each server notification method to its generated payload model class.""" server_notifications = json.loads((schema_dir / "ServerNotification.json").read_text()) @@ -1217,7 +1279,7 @@ def generate_public_api_flat_methods() -> None: thread_fork_fields = _load_public_fields( "openai_codex.generated.v2_all", "ThreadForkParams", - exclude={"thread_id", *approval_fields}, + exclude={"thread_id", "last_turn_id", *approval_fields}, ) thread_fork_fields = _replace_public_sandbox_field(thread_fork_fields, wire_name="sandbox") turn_start_fields = _load_public_fields( @@ -1299,7 +1361,7 @@ def build_parser() -> argparse.ArgumentParser: required=True, help=( "Python SDK release version to write into the staged package. " - "Accepts PEP 440 versions such as 0.1.0b1." + "Accepts PEP 440 versions such as 0.144.4." ), ) diff --git a/sdk/python/src/openai_codex/generated/notification_registry.py b/sdk/python/src/openai_codex/generated/notification_registry.py index d5e620a7a3..25b47b7724 100644 --- a/sdk/python/src/openai_codex/generated/notification_registry.py +++ b/sdk/python/src/openai_codex/generated/notification_registry.py @@ -17,6 +17,7 @@ from .v2_all import ContextCompactedNotification from .v2_all import DeprecationNoticeNotification from .v2_all import ErrorNotification from .v2_all import ExternalAgentConfigImportCompletedNotification +from .v2_all import ExternalAgentConfigImportProgressNotification from .v2_all import FileChangeOutputDeltaNotification from .v2_all import FileChangePatchUpdatedNotification from .v2_all import FsChangedNotification @@ -33,6 +34,7 @@ from .v2_all import McpServerOauthLoginCompletedNotification from .v2_all import McpServerStatusUpdatedNotification from .v2_all import McpToolCallProgressNotification from .v2_all import ModelReroutedNotification +from .v2_all import ModelSafetyBufferingUpdatedNotification from .v2_all import ModelVerificationNotification from .v2_all import PlanDeltaNotification from .v2_all import ProcessExitedNotification @@ -46,6 +48,7 @@ from .v2_all import SkillsChangedNotification from .v2_all import TerminalInteractionNotification from .v2_all import ThreadArchivedNotification from .v2_all import ThreadClosedNotification +from .v2_all import ThreadDeletedNotification from .v2_all import ThreadGoalClearedNotification from .v2_all import ThreadGoalUpdatedNotification from .v2_all import ThreadNameUpdatedNotification @@ -64,6 +67,7 @@ from .v2_all import ThreadTokenUsageUpdatedNotification from .v2_all import ThreadUnarchivedNotification from .v2_all import TurnCompletedNotification from .v2_all import TurnDiffUpdatedNotification +from .v2_all import TurnModerationMetadataNotification from .v2_all import TurnPlanUpdatedNotification from .v2_all import TurnStartedNotification from .v2_all import WarningNotification @@ -80,6 +84,7 @@ NOTIFICATION_MODELS: dict[str, type[BaseModel]] = { "deprecationNotice": DeprecationNoticeNotification, "error": ErrorNotification, "externalAgentConfig/import/completed": ExternalAgentConfigImportCompletedNotification, + "externalAgentConfig/import/progress": ExternalAgentConfigImportProgressNotification, "fs/changed": FsChangedNotification, "fuzzyFileSearch/sessionCompleted": FuzzyFileSearchSessionCompletedNotification, "fuzzyFileSearch/sessionUpdated": FuzzyFileSearchSessionUpdatedNotification, @@ -103,6 +108,7 @@ NOTIFICATION_MODELS: dict[str, type[BaseModel]] = { "mcpServer/oauthLogin/completed": McpServerOauthLoginCompletedNotification, "mcpServer/startupStatus/updated": McpServerStatusUpdatedNotification, "model/rerouted": ModelReroutedNotification, + "model/safetyBuffering/updated": ModelSafetyBufferingUpdatedNotification, "model/verification": ModelVerificationNotification, "process/exited": ProcessExitedNotification, "process/outputDelta": ProcessOutputDeltaNotification, @@ -112,6 +118,7 @@ NOTIFICATION_MODELS: dict[str, type[BaseModel]] = { "thread/archived": ThreadArchivedNotification, "thread/closed": ThreadClosedNotification, "thread/compacted": ContextCompactedNotification, + "thread/deleted": ThreadDeletedNotification, "thread/goal/cleared": ThreadGoalClearedNotification, "thread/goal/updated": ThreadGoalUpdatedNotification, "thread/name/updated": ThreadNameUpdatedNotification, @@ -130,6 +137,7 @@ NOTIFICATION_MODELS: dict[str, type[BaseModel]] = { "thread/unarchived": ThreadUnarchivedNotification, "turn/completed": TurnCompletedNotification, "turn/diff/updated": TurnDiffUpdatedNotification, + "turn/moderationMetadata": TurnModerationMetadataNotification, "turn/plan/updated": TurnPlanUpdatedNotification, "turn/started": TurnStartedNotification, "warning": WarningNotification, @@ -152,6 +160,7 @@ DIRECT_TURN_ID_NOTIFICATION_TYPES: tuple[type[BaseModel], ...] = ( ItemStartedNotification, McpToolCallProgressNotification, ModelReroutedNotification, + ModelSafetyBufferingUpdatedNotification, ModelVerificationNotification, PlanDeltaNotification, ReasoningSummaryPartAddedNotification, @@ -161,6 +170,7 @@ DIRECT_TURN_ID_NOTIFICATION_TYPES: tuple[type[BaseModel], ...] = ( ThreadGoalUpdatedNotification, ThreadTokenUsageUpdatedNotification, TurnDiffUpdatedNotification, + TurnModerationMetadataNotification, TurnPlanUpdatedNotification, ) diff --git a/sdk/python/src/openai_codex/generated/v2_all.py b/sdk/python/src/openai_codex/generated/v2_all.py index c024a2c8c0..e31c9115d7 100644 --- a/sdk/python/src/openai_codex/generated/v2_all.py +++ b/sdk/python/src/openai_codex/generated/v2_all.py @@ -33,13 +33,6 @@ class ApiKeyAccount(BaseModel): type: Annotated[Literal["apiKey"], Field(title="ApiKeyAccountType")] -class AmazonBedrockAccount(BaseModel): - model_config = ConfigDict( - populate_by_name=True, - ) - type: Annotated[Literal["amazonBedrock"], Field(title="AmazonBedrockAccountType")] - - class AccountLoginCompletedNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -49,6 +42,25 @@ class AccountLoginCompletedNotification(BaseModel): success: bool +class AccountTokenUsageDailyBucket(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + start_date: Annotated[str, Field(alias="startDate")] + tokens: int + + +class AccountTokenUsageSummary(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + current_streak_days: Annotated[int | None, Field(alias="currentStreakDays")] = None + lifetime_tokens: Annotated[int | None, Field(alias="lifetimeTokens")] = None + longest_running_turn_sec: Annotated[int | None, Field(alias="longestRunningTurnSec")] = None + longest_streak_days: Annotated[int | None, Field(alias="longestStreakDays")] = None + peak_daily_tokens: Annotated[int | None, Field(alias="peakDailyTokens")] = None + + class ActivePermissionProfile(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -99,6 +111,33 @@ class AgentMessageDeltaNotification(BaseModel): turn_id: Annotated[str, Field(alias="turnId")] +class InputTextAgentMessageInputContent(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + text: str + type: Annotated[Literal["input_text"], Field(title="InputTextAgentMessageInputContentType")] + + +class EncryptedContentAgentMessageInputContent(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + encrypted_content: str + type: Annotated[ + Literal["encrypted_content"], Field(title="EncryptedContentAgentMessageInputContentType") + ] + + +class AgentMessageInputContent( + RootModel[InputTextAgentMessageInputContent | EncryptedContentAgentMessageInputContent] +): + model_config = ConfigDict( + populate_by_name=True, + ) + root: InputTextAgentMessageInputContent | EncryptedContentAgentMessageInputContent + + class AgentPath(RootModel[str]): model_config = ConfigDict( populate_by_name=True, @@ -106,6 +145,11 @@ class AgentPath(RootModel[str]): root: str +class AmazonBedrockCredentialSource(Enum): + codex_managed = "codexManaged" + aws_managed = "awsManaged" + + class AnalyticsConfig(BaseModel): model_config = ConfigDict( extra="allow", @@ -146,16 +190,22 @@ class AppSummary(BaseModel): model_config = ConfigDict( populate_by_name=True, ) + category: str | None = None description: str | None = None id: str install_url: Annotated[str | None, Field(alias="installUrl")] = None name: str - needs_auth: Annotated[bool, Field(alias="needsAuth")] + + +class AppTemplateUnavailableReason(Enum): + not_configured_for_workspace = "NOT_CONFIGURED_FOR_WORKSPACE" + no_active_workspace = "NO_ACTIVE_WORKSPACE" class AppToolApproval(Enum): auto = "auto" prompt = "prompt" + writes = "writes" approve = "approve" @@ -184,6 +234,8 @@ class AppsDefaultConfig(BaseModel): model_config = ConfigDict( populate_by_name=True, ) + approvals_reviewer: ApprovalsReviewer | None = None + default_tools_approval_mode: AppToolApproval | None = None destructive_enabled: bool | None = True enabled: bool | None = True open_world_enabled: bool | None = True @@ -218,7 +270,6 @@ class AppsListParams(BaseModel): class AskForApprovalValue(Enum): untrusted = "untrusted" - on_failure = "on-failure" on_request = "on-request" never = "never" @@ -253,7 +304,10 @@ class AuthMode(Enum): apikey = "apikey" chatgpt = "chatgpt" chatgpt_auth_tokens = "chatgptAuthTokens" + headers = "headers" agent_identity = "agentIdentity" + personal_access_token = "personalAccessToken" + bedrock_api_key = "bedrockApiKey" class AutoCompactTokenLimitScope(Enum): @@ -293,6 +347,27 @@ class CancelLoginAccountStatus(Enum): not_found = "notFound" +class EnvironmentCapabilityRootLocation(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + environment_id: Annotated[str, Field(alias="environmentId")] + path: Annotated[ + str, Field(description="Absolute path for the root in the selected environment.") + ] + type: Annotated[Literal["environment"], Field(title="EnvironmentCapabilityRootLocationType")] + + +class CapabilityRootLocation(RootModel[EnvironmentCapabilityRootLocation]): + model_config = ConfigDict( + populate_by_name=True, + ) + root: Annotated[ + EnvironmentCapabilityRootLocation, + Field(description="Location used to resolve a selected capability root."), + ] + + class ClientInfo(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -304,6 +379,7 @@ class ClientInfo(BaseModel): class CodexErrorInfoValue(Enum): context_window_exceeded = "contextWindowExceeded" + session_budget_exceeded = "sessionBudgetExceeded" usage_limit_exceeded = "usageLimitExceeded" server_overloaded = "serverOverloaded" cyber_policy = "cyberPolicy" @@ -758,6 +834,40 @@ class ConfiguredHookMatcherGroup(BaseModel): matcher: str | None = None +class ConsumeAccountRateLimitResetCreditOutcome(Enum): + reset = "reset" + nothing_to_reset = "nothingToReset" + no_credit = "noCredit" + already_redeemed = "alreadyRedeemed" + + +class ConsumeAccountRateLimitResetCreditParams(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + credit_id: Annotated[ + str | None, + Field( + alias="creditId", + description="Opaque reset-credit identifier to redeem. When omitted, the backend selects the next available credit.", + ), + ] = None + idempotency_key: Annotated[ + str, + Field( + alias="idempotencyKey", + description="Identifies one logical reset attempt. A UUID is recommended; reuse the same value when retrying that attempt.", + ), + ] + + +class ConsumeAccountRateLimitResetCreditResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + outcome: ConsumeAccountRateLimitResetCreditOutcome + + class InputTextContentItem(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -782,6 +892,12 @@ class ContextCompactedNotification(BaseModel): turn_id: Annotated[str, Field(alias="turnId")] +class ConversationTextRole(Enum): + user = "user" + developer = "developer" + assistant = "assistant" + + class CreditsSnapshot(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -839,7 +955,7 @@ class DynamicToolCallStatus(Enum): failed = "failed" -class DynamicToolSpec(BaseModel): +class FunctionDynamicToolNamespaceTool(BaseModel): model_config = ConfigDict( populate_by_name=True, ) @@ -847,7 +963,42 @@ class DynamicToolSpec(BaseModel): description: str input_schema: Annotated[Any, Field(alias="inputSchema")] name: str - namespace: str | None = None + type: Annotated[Literal["function"], Field(title="FunctionDynamicToolNamespaceToolType")] + + +class DynamicToolNamespaceTool(RootModel[FunctionDynamicToolNamespaceTool]): + model_config = ConfigDict( + populate_by_name=True, + ) + root: FunctionDynamicToolNamespaceTool + + +class FunctionDynamicToolSpec(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + defer_loading: Annotated[bool | None, Field(alias="deferLoading")] = None + description: str + input_schema: Annotated[Any, Field(alias="inputSchema")] + name: str + type: Annotated[Literal["function"], Field(title="FunctionDynamicToolSpecType")] + + +class NamespaceDynamicToolSpec(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + description: str + name: str + tools: list[DynamicToolNamespaceTool] + type: Annotated[Literal["namespace"], Field(title="NamespaceDynamicToolSpecType")] + + +class DynamicToolSpec(RootModel[FunctionDynamicToolSpec | NamespaceDynamicToolSpec]): + model_config = ConfigDict( + populate_by_name=True, + ) + root: FunctionDynamicToolSpec | NamespaceDynamicToolSpec class ExperimentalFeatureEnablementSetParams(BaseModel): @@ -911,23 +1062,16 @@ class ExternalAgentConfigDetectParams(BaseModel): bool | None, Field( alias="includeHome", - description="If true, include detection under the user's home (~/.claude, ~/.codex, etc.).", + description="If true, include detection under the user's home directory.", ), ] = None -class ExternalAgentConfigImportCompletedNotification(BaseModel): - pass - model_config = ConfigDict( - populate_by_name=True, - ) - - class ExternalAgentConfigImportResponse(BaseModel): - pass model_config = ConfigDict( populate_by_name=True, ) + import_id: Annotated[str, Field(alias="importId")] class ExternalAgentConfigMigrationItemType(Enum): @@ -977,14 +1121,6 @@ class FileSystemAccessMode(Enum): deny = "deny" -class PathFileSystemPath(BaseModel): - model_config = ConfigDict( - populate_by_name=True, - ) - path: AbsolutePathBuf - type: Annotated[Literal["path"], Field(title="PathFileSystemPathType")] - - class GlobPatternFileSystemPath(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -1384,6 +1520,16 @@ class GetAccountParams(BaseModel): ] = None +class GetAccountTokenUsageResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + daily_usage_buckets: Annotated[ + list[AccountTokenUsageDailyBucket] | None, Field(alias="dailyUsageBuckets") + ] = None + summary: AccountTokenUsageSummary + + class GitInfo(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -1572,6 +1718,13 @@ class InitializeCapabilities(BaseModel): description="Opt into receiving experimental API methods and fields.", ), ] = False + mcp_server_openai_form_elicitation: Annotated[ + bool | None, + Field( + alias="mcpServerOpenaiFormElicitation", + description="Allow downstream MCP servers to request OpenAI extended form elicitations.", + ), + ] = None opt_out_notification_methods: Annotated[ list[str] | None, Field( @@ -1601,6 +1754,20 @@ class InputModality(Enum): image = "image" +class InternalChatMessageMetadataPassthrough(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + turn_id: str | None = None + + +class LegacyAppPathString(RootModel[str]): + model_config = ConfigDict( + populate_by_name=True, + ) + root: str + + class ExecLocalShellAction(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -1634,14 +1801,6 @@ class ApiKeyLoginAccountParams(BaseModel): type: Annotated[Literal["apiKey"], Field(title="ApiKeyv2::LoginAccountParamsType")] -class ChatgptLoginAccountParams(BaseModel): - model_config = ConfigDict( - populate_by_name=True, - ) - codex_streamlined_login: Annotated[bool | None, Field(alias="codexStreamlinedLogin")] = None - type: Annotated[Literal["chatgpt"], Field(title="Chatgptv2::LoginAccountParamsType")] - - class ChatgptDeviceCodeLoginAccountParams(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -1681,26 +1840,6 @@ class ChatgptAuthTokensLoginAccountParams(BaseModel): ] -class LoginAccountParams( - RootModel[ - ApiKeyLoginAccountParams - | ChatgptLoginAccountParams - | ChatgptDeviceCodeLoginAccountParams - | ChatgptAuthTokensLoginAccountParams - ] -): - model_config = ConfigDict( - populate_by_name=True, - ) - root: Annotated[ - ApiKeyLoginAccountParams - | ChatgptLoginAccountParams - | ChatgptDeviceCodeLoginAccountParams - | ChatgptAuthTokensLoginAccountParams, - Field(title="LoginAccountParams"), - ] - - class ApiKeyLoginAccountResponse(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -1773,6 +1912,11 @@ class LoginAccountResponse( ] +class LoginAppBrand(Enum): + codex = "codex" + chatgpt = "chatgpt" + + class LogoutAccountResponse(BaseModel): pass model_config = ConfigDict( @@ -1914,6 +2058,7 @@ class McpServerOauthLoginCompletedNotification(BaseModel): error: str | None = None name: str success: bool + thread_id: Annotated[str | None, Field(alias="threadId")] = None class McpServerOauthLoginParams(BaseModel): @@ -1922,6 +2067,7 @@ class McpServerOauthLoginParams(BaseModel): ) name: str scopes: list[str] | None = None + thread_id: Annotated[str | None, Field(alias="threadId")] = None timeout_secs: Annotated[int | None, Field(alias="timeoutSecs")] = None @@ -1939,6 +2085,13 @@ class McpServerRefreshResponse(BaseModel): ) +class McpServerStartupFailureReason(RootModel[Literal["reauthenticationRequired"]]): + model_config = ConfigDict( + populate_by_name=True, + ) + root: Literal["reauthenticationRequired"] + + class McpServerStartupState(Enum): starting = "starting" ready = "ready" @@ -1956,8 +2109,12 @@ class McpServerStatusUpdatedNotification(BaseModel): populate_by_name=True, ) error: str | None = None + failure_reason: Annotated[ + McpServerStartupFailureReason | None, Field(alias="failureReason") + ] = None name: str status: McpServerStartupState + thread_id: Annotated[str | None, Field(alias="threadId")] = None class McpServerToolCallParams(BaseModel): @@ -1981,6 +2138,18 @@ class McpServerToolCallResponse(BaseModel): structured_content: Annotated[Any | None, Field(alias="structuredContent")] = None +class McpToolCallAppContext(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + action_name: Annotated[str | None, Field(alias="actionName")] = None + app_name: Annotated[str | None, Field(alias="appName")] = None + connector_id: Annotated[str, Field(alias="connectorId")] + link_id: Annotated[str | None, Field(alias="linkId")] = None + resource_uri: Annotated[str | None, Field(alias="resourceUri")] = None + template_id: Annotated[str | None, Field(alias="templateId")] = None + + class McpToolCallError(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -2099,6 +2268,19 @@ class ModelReroutedNotification(BaseModel): turn_id: Annotated[str, Field(alias="turnId")] +class ModelSafetyBufferingUpdatedNotification(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + faster_model: Annotated[str | None, Field(alias="fasterModel")] = None + model: str + reasons: list[str] + show_buffering_ui: Annotated[bool, Field(alias="showBufferingUi")] + thread_id: Annotated[str, Field(alias="threadId")] + turn_id: Annotated[str, Field(alias="turnId")] + use_cases: Annotated[list[str], Field(alias="useCases")] + + class ModelServiceTier(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -2134,6 +2316,31 @@ class ModelVerificationNotification(BaseModel): verifications: list[ModelVerification] +class MultiAgentModeValue(Enum): + explicit_request_only = "explicitRequestOnly" + proactive = "proactive" + + +class CustomMultiAgentMode(BaseModel): + model_config = ConfigDict( + extra="forbid", + populate_by_name=True, + ) + custom: str + + +class MultiAgentMode(RootModel[MultiAgentModeValue | CustomMultiAgentMode]): + model_config = ConfigDict( + populate_by_name=True, + ) + root: Annotated[ + MultiAgentModeValue | CustomMultiAgentMode, + Field( + description="Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy." + ), + ] + + class NetworkAccess(Enum): restricted = "restricted" enabled = "enabled" @@ -2273,6 +2480,9 @@ class PermissionProfileSummary(BaseModel): model_config = ConfigDict( populate_by_name=True, ) + allowed: Annotated[ + bool, Field(description="Whether the effective requirements allow selecting this profile.") + ] description: Annotated[ str | None, Field(description="Optional user-facing description for display in clients.") ] = None @@ -2343,6 +2553,11 @@ class PluginInstallPolicy(Enum): installed_by_default = "INSTALLED_BY_DEFAULT" +class PluginInstallPolicySource(Enum): + workspace_setting = "WORKSPACE_SETTING" + implicit_canonical_app = "IMPLICIT_CANONICAL_APP" + + class PluginInstallResponse(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -2401,9 +2616,22 @@ class PluginInterface(BaseModel): AbsolutePathBuf | None, Field(description="Local logo path, resolved from the installed plugin package."), ] = None + logo_dark: Annotated[ + AbsolutePathBuf | None, + Field( + alias="logoDark", + description="Local dark-mode logo path, resolved from the installed plugin package.", + ), + ] = None logo_url: Annotated[ str | None, Field(alias="logoUrl", description="Remote logo URL from the plugin catalog.") ] = None + logo_url_dark: Annotated[ + str | None, + Field( + alias="logoUrlDark", description="Remote dark-mode logo URL from the plugin catalog." + ), + ] = None long_description: Annotated[str | None, Field(alias="longDescription")] = None privacy_policy_url: Annotated[str | None, Field(alias="privacyPolicyUrl")] = None screenshot_urls: Annotated[ @@ -2426,6 +2654,7 @@ class PluginListMarketplaceKind(Enum): vertical = "vertical" workspace_directory = "workspace-directory" shared_with_me = "shared-with-me" + created_by_me_remote = "created-by-me-remote" class PluginListParams(BaseModel): @@ -2568,6 +2797,23 @@ class GitPluginSource(BaseModel): url: str +class NpmPluginSource(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + package: str + registry: Annotated[ + str | None, + Field( + description="Optional HTTPS registry URL. Authentication stays in the user's npm config." + ), + ] = None + type: Annotated[Literal["npm"], Field(title="NpmPluginSourceType")] + version: Annotated[str | None, Field(description="Optional npm version or version range.")] = ( + None + ) + + class RemotePluginSource(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -2575,11 +2821,13 @@ class RemotePluginSource(BaseModel): type: Annotated[Literal["remote"], Field(title="RemotePluginSourceType")] -class PluginSource(RootModel[LocalPluginSource | GitPluginSource | RemotePluginSource]): +class PluginSource( + RootModel[LocalPluginSource | GitPluginSource | NpmPluginSource | RemotePluginSource] +): model_config = ConfigDict( populate_by_name=True, ) - root: LocalPluginSource | GitPluginSource | RemotePluginSource + root: LocalPluginSource | GitPluginSource | NpmPluginSource | RemotePluginSource class PluginUninstallParams(BaseModel): @@ -2665,6 +2913,18 @@ class RateLimitReachedType(Enum): workspace_member_usage_limit_reached = "workspace_member_usage_limit_reached" +class RateLimitResetCreditStatus(Enum): + available = "available" + redeeming = "redeeming" + redeemed = "redeemed" + unknown = "unknown" + + +class RateLimitResetType(Enum): + codex_rate_limits = "codexRateLimits" + unknown = "unknown" + + class RateLimitWindow(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -2716,7 +2976,7 @@ class RealtimeVoicesList(BaseModel): v2: list[RealtimeVoice] -class ReasoningEffort(Enum): +class ReasoningEffort(str, Enum): none = "none" minimal = "minimal" low = "low" @@ -2724,6 +2984,15 @@ class ReasoningEffort(Enum): high = "high" xhigh = "xhigh" + @classmethod + def _missing_(cls, value: object) -> ReasoningEffort | None: + if not isinstance(value, str) or not value: + return None + member = str.__new__(cls, value) + member._name_ = value + member._value_ = value + return member + class ReasoningEffortOption(BaseModel): model_config = ConfigDict( @@ -2830,6 +3099,20 @@ class RemoteControlConnectionStatus(Enum): errored = "errored" +class RemoteControlDisableParams(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + ephemeral: bool | None = None + + +class RemoteControlEnableParams(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + ephemeral: bool | None = None + + class RemoteControlStatusChangedNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -2911,12 +3194,26 @@ class ResourceTemplate(BaseModel): uri_template: Annotated[str, Field(alias="uriTemplate")] +class AgentMessageResponseItem(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + author: str + content: list[AgentMessageInputContent] + id: str | None = None + internal_chat_message_metadata_passthrough: InternalChatMessageMetadataPassthrough | None = None + recipient: str + type: Annotated[Literal["agent_message"], Field(title="AgentMessageResponseItemType")] + + class ReasoningResponseItem(BaseModel): model_config = ConfigDict( populate_by_name=True, ) content: list[ReasoningItemContent] | None = None encrypted_content: str | None = None + id: str | None = None + internal_chat_message_metadata_passthrough: InternalChatMessageMetadataPassthrough | None = None summary: list[ReasoningItemReasoningSummary] type: Annotated[Literal["reasoning"], Field(title="ReasoningResponseItemType")] @@ -2931,6 +3228,7 @@ class LocalShellCallResponseItem(BaseModel): str | None, Field(description="Legacy id field retained for compatibility with older payloads."), ] = None + internal_chat_message_metadata_passthrough: InternalChatMessageMetadataPassthrough | None = None status: LocalShellStatus type: Annotated[Literal["local_shell_call"], Field(title="LocalShellCallResponseItemType")] @@ -2942,6 +3240,7 @@ class FunctionCallResponseItem(BaseModel): arguments: str call_id: str id: str | None = None + internal_chat_message_metadata_passthrough: InternalChatMessageMetadataPassthrough | None = None name: str namespace: str | None = None type: Annotated[Literal["function_call"], Field(title="FunctionCallResponseItemType")] @@ -2955,6 +3254,7 @@ class ToolSearchCallResponseItem(BaseModel): call_id: str | None = None execution: str id: str | None = None + internal_chat_message_metadata_passthrough: InternalChatMessageMetadataPassthrough | None = None status: str | None = None type: Annotated[Literal["tool_search_call"], Field(title="ToolSearchCallResponseItemType")] @@ -2966,7 +3266,9 @@ class CustomToolCallResponseItem(BaseModel): call_id: str id: str | None = None input: str + internal_chat_message_metadata_passthrough: InternalChatMessageMetadataPassthrough | None = None name: str + namespace: str | None = None status: str | None = None type: Annotated[Literal["custom_tool_call"], Field(title="CustomToolCallResponseItemType")] @@ -2977,6 +3279,8 @@ class ToolSearchOutputResponseItem(BaseModel): ) call_id: str | None = None execution: str + id: str | None = None + internal_chat_message_metadata_passthrough: InternalChatMessageMetadataPassthrough | None = None status: str tools: list type: Annotated[Literal["tool_search_output"], Field(title="ToolSearchOutputResponseItemType")] @@ -2986,7 +3290,8 @@ class ImageGenerationCallResponseItem(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - id: str + id: str | None = None + internal_chat_message_metadata_passthrough: InternalChatMessageMetadataPassthrough | None = None result: str revised_prompt: str | None = None status: str @@ -3000,6 +3305,8 @@ class CompactionResponseItem(BaseModel): populate_by_name=True, ) encrypted_content: str + id: str | None = None + internal_chat_message_metadata_passthrough: InternalChatMessageMetadataPassthrough | None = None type: Annotated[Literal["compaction"], Field(title="CompactionResponseItemType")] @@ -3015,6 +3322,8 @@ class ContextCompactionResponseItem(BaseModel): populate_by_name=True, ) encrypted_content: str | None = None + id: str | None = None + internal_chat_message_metadata_passthrough: InternalChatMessageMetadataPassthrough | None = None type: Annotated[Literal["context_compaction"], Field(title="ContextCompactionResponseItemType")] @@ -3209,6 +3518,18 @@ class SandboxWorkspaceWrite(BaseModel): writable_roots: list[str] | None = [] +class SelectedCapabilityRoot(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: Annotated[ + str, Field(description="Stable identifier supplied by the capability selection platform.") + ] + location: Annotated[ + CapabilityRootLocation, Field(description="Where the selected root can be resolved.") + ] + + class SendAddCreditsNudgeEmailParams(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -3315,17 +3636,6 @@ class RemoteControlStatusChangedServerNotification(BaseModel): params: RemoteControlStatusChangedNotification -class ExternalAgentConfigImportCompletedServerNotification(BaseModel): - model_config = ConfigDict( - populate_by_name=True, - ) - method: Annotated[ - Literal["externalAgentConfig/import/completed"], - Field(title="ExternalAgentConfig/import/completedNotificationMethod"), - ] - params: ExternalAgentConfigImportCompletedNotification - - class FsChangedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -3395,6 +3705,17 @@ class ModelVerificationServerNotification(BaseModel): params: ModelVerificationNotification +class ModelSafetyBufferingUpdatedServerNotification(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + method: Annotated[ + Literal["model/safetyBuffering/updated"], + Field(title="Model/safetyBuffering/updatedNotificationMethod"), + ] + params: ModelSafetyBufferingUpdatedNotification + + class GuardianWarningServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -3507,6 +3828,13 @@ class SkillInterface(BaseModel): short_description: Annotated[str | None, Field(alias="shortDescription")] = None +class SkillMigration(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + name: str + + class SkillScope(Enum): user = "user" repo = "repo" @@ -3607,6 +3935,12 @@ class SpendControlLimitSnapshot(BaseModel): used: str +class SubAgentActivityKind(Enum): + started = "started" + interacted = "interacted" + interrupted = "interrupted" + + class SubAgentSourceValue(Enum): review = "review" compact = "compact" @@ -3740,6 +4074,34 @@ class ThreadCompactStartResponse(BaseModel): ) +class ThreadDeleteParams(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + thread_id: Annotated[str, Field(alias="threadId")] + + +class ThreadDeleteResponse(BaseModel): + pass + model_config = ConfigDict( + populate_by_name=True, + ) + + +class ThreadDeletedNotification(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + thread_id: Annotated[str, Field(alias="threadId")] + + +class ThreadExtra(BaseModel): + pass + model_config = ConfigDict( + populate_by_name=True, + ) + + class ThreadGoalClearParams(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -3777,6 +4139,11 @@ class ThreadGoalStatus(Enum): complete = "complete" +class ThreadHistoryMode(Enum): + legacy = "legacy" + paginated = "paginated" + + class ThreadId(RootModel[str]): model_config = ConfigDict( populate_by_name=True, @@ -3851,7 +4218,7 @@ class CommandExecutionThreadItem(BaseModel): description="A best-effort parsing of the command to understand the action(s) it will perform. This returns a list of CommandAction objects because a single shell command may be composed of many commands piped together.", ), ] - cwd: Annotated[AbsolutePathBuf, Field(description="The command's working directory.")] + cwd: Annotated[LegacyAppPathString, Field(description="The command's working directory.")] duration_ms: Annotated[ int | None, Field( @@ -3878,6 +4245,7 @@ class McpToolCallThreadItem(BaseModel): model_config = ConfigDict( populate_by_name=True, ) + app_context: Annotated[McpToolCallAppContext | None, Field(alias="appContext")] = None arguments: Any duration_ms: Annotated[ int | None, @@ -3885,7 +4253,13 @@ class McpToolCallThreadItem(BaseModel): ] = None error: McpToolCallError | None = None id: str - mcp_app_resource_uri: Annotated[str | None, Field(alias="mcpAppResourceUri")] = None + mcp_app_resource_uri: Annotated[ + str | None, + Field( + alias="mcpAppResourceUri", + description="Deprecated: use `appContext.resourceUri` instead.", + ), + ] = None plugin_id: Annotated[str | None, Field(alias="pluginId")] = None result: McpToolCallResult | None = None server: str @@ -3916,15 +4290,35 @@ class DynamicToolCallThreadItem(BaseModel): type: Annotated[Literal["dynamicToolCall"], Field(title="DynamicToolCallThreadItemType")] +class SubAgentActivityThreadItem(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + agent_path: Annotated[str, Field(alias="agentPath")] + agent_thread_id: Annotated[str, Field(alias="agentThreadId")] + id: str + kind: SubAgentActivityKind + type: Annotated[Literal["subAgentActivity"], Field(title="SubAgentActivityThreadItemType")] + + class ImageViewThreadItem(BaseModel): model_config = ConfigDict( populate_by_name=True, ) id: str - path: AbsolutePathBuf + path: LegacyAppPathString type: Annotated[Literal["imageView"], Field(title="ImageViewThreadItemType")] +class SleepThreadItem(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + duration_ms: Annotated[int, Field(alias="durationMs", ge=0)] + id: str + type: Annotated[Literal["sleep"], Field(title="SleepThreadItemType")] + + class ImageGenerationThreadItem(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -4253,13 +4647,23 @@ class ThreadShellCommandResponse(BaseModel): class ThreadSortKey(Enum): created_at = "created_at" updated_at = "updated_at" + recency_at = "recency_at" -class ThreadSource(Enum): +class ThreadSource(str, Enum): user = "user" subagent = "subagent" memory_consolidation = "memory_consolidation" + @classmethod + def _missing_(cls, value: object) -> ThreadSource | None: + if not isinstance(value, str): + return None + member = str.__new__(cls, value) + member._name_ = value + member._value_ = value + return member + class ThreadSourceKind(Enum): cli = "cli" @@ -4392,7 +4796,7 @@ class TurnEnvironmentParams(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - cwd: AbsolutePathBuf + cwd: LegacyAppPathString environment_id: Annotated[str, Field(alias="environmentId")] @@ -4417,6 +4821,15 @@ class TurnItemsView(Enum): full = "full" +class TurnModerationMetadataNotification(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + metadata: Any + thread_id: Annotated[str, Field(alias="threadId")] + turn_id: Annotated[str, Field(alias="turnId")] + + class TurnPlanStepStatus(Enum): pending = "pending" in_progress = "inProgress" @@ -4590,6 +5003,7 @@ class WebSearchLocation(BaseModel): class WebSearchMode(Enum): disabled = "disabled" cached = "cached" + indexed = "indexed" live = "live" @@ -4645,6 +5059,12 @@ class WindowsWorldWritableWarningNotification(BaseModel): sample_paths: Annotated[list[str], Field(alias="samplePaths")] +class WorkspaceMessageType(Enum): + headline = "headline" + announcement = "announcement" + unknown = "unknown" + + class WriteStatus(Enum): ok = "ok" ok_overridden = "okOverridden" @@ -4659,6 +5079,16 @@ class ChatgptAccount(BaseModel): type: Annotated[Literal["chatgpt"], Field(title="ChatgptAccountType")] +class AmazonBedrockAccount(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + credential_source: Annotated[ + AmazonBedrockCredentialSource | None, Field(alias="credentialSource") + ] = "awsManaged" + type: Annotated[Literal["amazonBedrock"], Field(title="AmazonBedrockAccountType")] + + class Account(RootModel[ApiKeyAccount | ChatgptAccount | AmazonBedrockAccount]): model_config = ConfigDict( populate_by_name=True, @@ -4717,6 +5147,21 @@ class AppMetadata(BaseModel): version_notes: Annotated[str | None, Field(alias="versionNotes")] = None +class AppTemplateSummary(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + canonical_connector_id: Annotated[str | None, Field(alias="canonicalConnectorId")] = None + category: str | None = None + description: str | None = None + logo_url: Annotated[str | None, Field(alias="logoUrl")] = None + logo_url_dark: Annotated[str | None, Field(alias="logoUrlDark")] = None + materialized_app_ids: Annotated[list[str], Field(alias="materializedAppIds")] + name: str + reason: AppTemplateUnavailableReason | None = None + template_id: Annotated[str, Field(alias="templateId")] + + class AppsConfig(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -4758,6 +5203,15 @@ class ThreadArchiveRequest(BaseModel): params: ThreadArchiveParams +class ThreadDeleteRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: RequestId + method: Annotated[Literal["thread/delete"], Field(title="Thread/deleteRequestMethod")] + params: ThreadDeleteParams + + class ThreadUnsubscribeRequest(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -5260,17 +5714,6 @@ class WindowsSandboxReadinessRequest(BaseModel): params: None = None -class AccountLoginStartRequest(BaseModel): - model_config = ConfigDict( - populate_by_name=True, - ) - id: RequestId - method: Annotated[ - Literal["account/login/start"], Field(title="Account/login/startRequestMethod") - ] - params: LoginAccountParams - - class AccountLoginCancelRequest(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -5302,6 +5745,39 @@ class AccountRateLimitsReadRequest(BaseModel): params: None = None +class AccountRateLimitResetCreditConsumeRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: RequestId + method: Annotated[ + Literal["account/rateLimitResetCredit/consume"], + Field(title="Account/rateLimitResetCredit/consumeRequestMethod"), + ] + params: ConsumeAccountRateLimitResetCreditParams + + +class AccountUsageReadRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: RequestId + method: Annotated[Literal["account/usage/read"], Field(title="Account/usage/readRequestMethod")] + params: None = None + + +class AccountWorkspaceMessagesReadRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: RequestId + method: Annotated[ + Literal["account/workspaceMessages/read"], + Field(title="Account/workspaceMessages/readRequestMethod"), + ] + params: None = None + + class AccountSendAddCreditsNudgeEmailRequest(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -5364,6 +5840,18 @@ class ExternalAgentConfigDetectRequest(BaseModel): params: ExternalAgentConfigDetectParams +class ExternalAgentConfigImportReadHistoriesRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: RequestId + method: Annotated[ + Literal["externalAgentConfig/import/readHistories"], + Field(title="ExternalAgentConfig/import/readHistoriesRequestMethod"), + ] + params: None = None + + class ConfigRequirementsReadRequest(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -5614,46 +6102,6 @@ class ConfigLayerMetadata(BaseModel): version: str -class ConfigRequirements(BaseModel): - model_config = ConfigDict( - populate_by_name=True, - ) - allow_appshots: Annotated[bool | None, Field(alias="allowAppshots")] = None - allow_managed_hooks_only: Annotated[bool | None, Field(alias="allowManagedHooksOnly")] = None - allowed_approval_policies: Annotated[ - list[AskForApproval] | None, Field(alias="allowedApprovalPolicies") - ] = None - allowed_permissions: Annotated[list[str] | None, Field(alias="allowedPermissions")] = None - allowed_sandbox_modes: Annotated[ - list[SandboxMode] | None, Field(alias="allowedSandboxModes") - ] = None - allowed_web_search_modes: Annotated[ - list[WebSearchMode] | None, Field(alias="allowedWebSearchModes") - ] = None - allowed_windows_sandbox_implementations: Annotated[ - list[WindowsSandboxSetupMode] | None, Field(alias="allowedWindowsSandboxImplementations") - ] = None - computer_use: Annotated[ComputerUseRequirements | None, Field(alias="computerUse")] = None - enforce_residency: Annotated[ResidencyRequirement | None, Field(alias="enforceResidency")] = ( - None - ) - feature_requirements: Annotated[dict[str, Any] | None, Field(alias="featureRequirements")] = ( - None - ) - - -class ConfigRequirementsReadResponse(BaseModel): - model_config = ConfigDict( - populate_by_name=True, - ) - requirements: Annotated[ - ConfigRequirements | None, - Field( - description="Null if no requirements are configured (e.g. no requirements.toml/MDM entries)." - ), - ] = None - - class ConfigValueWriteParams(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -5755,6 +6203,45 @@ class ExperimentalFeatureListResponse(BaseModel): ] = None +class ExternalAgentConfigImportItemTypeFailure(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + cwd: str | None = None + error_type: Annotated[str | None, Field(alias="errorType")] = None + failure_stage: Annotated[str, Field(alias="failureStage")] + item_type: Annotated[ExternalAgentConfigMigrationItemType, Field(alias="itemType")] + message: str + source: str | None = None + + +class ExternalAgentConfigImportItemTypeSuccess(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + cwd: str | None = None + item_type: Annotated[ExternalAgentConfigMigrationItemType, Field(alias="itemType")] + source: str | None = None + target: str | None = None + + +class ExternalAgentConfigImportTypeResult(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + failures: list[ExternalAgentConfigImportItemTypeFailure] + item_type: Annotated[ExternalAgentConfigMigrationItemType, Field(alias="itemType")] + successes: list[ExternalAgentConfigImportItemTypeSuccess] + + +class PathFileSystemPath(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + path: LegacyAppPathString + type: Annotated[Literal["path"], Field(title="PathFileSystemPathType")] + + class SpecialFileSystemPath(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -5969,6 +6456,38 @@ class ListMcpServerStatusParams(BaseModel): thread_id: Annotated[str | None, Field(alias="threadId")] = None +class ChatgptLoginAccountParams(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + app_brand: Annotated[LoginAppBrand | None, Field(alias="appBrand")] = None + codex_streamlined_login: Annotated[bool | None, Field(alias="codexStreamlinedLogin")] = None + type: Annotated[Literal["chatgpt"], Field(title="Chatgptv2::LoginAccountParamsType")] + use_hosted_login_success_page: Annotated[ + bool | None, Field(alias="useHostedLoginSuccessPage") + ] = None + + +class LoginAccountParams( + RootModel[ + ApiKeyLoginAccountParams + | ChatgptLoginAccountParams + | ChatgptDeviceCodeLoginAccountParams + | ChatgptAuthTokensLoginAccountParams + ] +): + model_config = ConfigDict( + populate_by_name=True, + ) + root: Annotated[ + ApiKeyLoginAccountParams + | ChatgptLoginAccountParams + | ChatgptDeviceCodeLoginAccountParams + | ChatgptAuthTokensLoginAccountParams, + Field(title="LoginAccountParams"), + ] + + class McpResourceReadResponse(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -6005,6 +6524,7 @@ class MigrationDetails(BaseModel): mcp_servers: Annotated[list[McpServerMigration] | None, Field(alias="mcpServers")] = [] plugins: list[PluginsMigration] | None = [] sessions: list[SessionMigration] | None = [] + skills: list[SkillMigration] | None = [] subagents: list[SubagentMigration] | None = [] @@ -6058,6 +6578,17 @@ class ModelListResponse(BaseModel): ] = None +class NewThreadModelDefaults(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + model: str | None = None + model_reasoning_effort: Annotated[ + ReasoningEffort | None, Field(alias="modelReasoningEffort") + ] = None + service_tier: Annotated[str | None, Field(alias="serviceTier")] = None + + class OverriddenMetadata(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -6143,6 +6674,53 @@ class ProcessOutputDeltaNotification(BaseModel): ] +class RateLimitResetCredit(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + description: Annotated[ + str | None, + Field( + description="Backend-provided display description for this credit, or `null` when unavailable." + ), + ] = None + expires_at: Annotated[ + int | None, + Field( + alias="expiresAt", + description="Unix timestamp in seconds when the credit expires, or `null` if it does not expire.", + ), + ] = None + granted_at: Annotated[ + int, + Field( + alias="grantedAt", description="Unix timestamp in seconds when the credit was granted." + ), + ] + id: Annotated[str, Field(description="Opaque backend identifier for this reset credit.")] + reset_type: Annotated[RateLimitResetType, Field(alias="resetType")] + status: RateLimitResetCreditStatus + title: Annotated[ + str | None, + Field( + description="Backend-provided display title for this credit, or `null` when unavailable." + ), + ] = None + + +class RateLimitResetCreditsSummary(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + available_count: Annotated[int, Field(alias="availableCount")] + credits: Annotated[ + list[RateLimitResetCredit] | None, + Field( + description="Detail rows for available reset credits, when the backend provides them.\n\n`null` means only `availableCount` is known, while an empty array means details were fetched and no available credits were returned. The backend may cap this list, so its length can be less than `availableCount`." + ), + ] = None + + class RateLimitSnapshot(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -6167,6 +6745,7 @@ class MessageResponseItem(BaseModel): ) content: list[ContentItem] id: str | None = None + internal_chat_message_metadata_passthrough: InternalChatMessageMetadataPassthrough | None = None phase: MessagePhase | None = None role: str type: Annotated[Literal["message"], Field(title="MessageResponseItemType")] @@ -6178,6 +6757,7 @@ class WebSearchCallResponseItem(BaseModel): ) action: ResponsesApiWebSearchAction | None = None id: str | None = None + internal_chat_message_metadata_passthrough: InternalChatMessageMetadataPassthrough | None = None status: str | None = None type: Annotated[Literal["web_search_call"], Field(title="WebSearchCallResponseItemType")] @@ -6214,6 +6794,14 @@ class ThreadArchivedServerNotification(BaseModel): params: ThreadArchivedNotification +class ThreadDeletedServerNotification(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + method: Annotated[Literal["thread/deleted"], Field(title="Thread/deletedNotificationMethod")] + params: ThreadDeletedNotification + + class ThreadUnarchivedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -6328,6 +6916,16 @@ class AccountUpdatedServerNotification(BaseModel): params: AccountUpdatedNotification +class TurnModerationMetadataServerNotification(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + method: Annotated[ + Literal["turn/moderationMetadata"], Field(title="Turn/moderationMetadataNotificationMethod") + ] + params: TurnModerationMetadataNotification + + class WarningServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -6527,6 +7125,13 @@ class ThreadForkParams(BaseModel): cwd: str | None = None developer_instructions: Annotated[str | None, Field(alias="developerInstructions")] = None ephemeral: bool | None = None + last_turn_id: Annotated[ + str | None, + Field( + alias="lastTurnId", + description="Optional last turn id to fork through, inclusive.\n\nWhen specified, turns after `last_turn_id` are omitted from the fork. The referenced turn cannot be in progress.", + ), + ] = None model: Annotated[ str | None, Field(description="Configuration overrides for the forked thread, if any.") ] = None @@ -6691,8 +7296,10 @@ class ThreadItem( | McpToolCallThreadItem | DynamicToolCallThreadItem | CollabAgentToolCallThreadItem + | SubAgentActivityThreadItem | WebSearchThreadItem | ImageViewThreadItem + | SleepThreadItem | ImageGenerationThreadItem | EnteredReviewModeThreadItem | ExitedReviewModeThreadItem @@ -6713,8 +7320,10 @@ class ThreadItem( | McpToolCallThreadItem | DynamicToolCallThreadItem | CollabAgentToolCallThreadItem + | SubAgentActivityThreadItem | WebSearchThreadItem | ImageViewThreadItem + | SleepThreadItem | ImageGenerationThreadItem | EnteredReviewModeThreadItem | ExitedReviewModeThreadItem @@ -7017,6 +7626,29 @@ class WindowsSandboxSetupCompletedNotification(BaseModel): success: bool +class WorkspaceMessage(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + archived_at: Annotated[ + int | None, + Field( + alias="archivedAt", + description="Unix timestamp (in seconds) when the message was archived.", + ), + ] = None + created_at: Annotated[ + int | None, + Field( + alias="createdAt", + description="Unix timestamp (in seconds) when the message was created.", + ), + ] = None + message_body: Annotated[str, Field(alias="messageBody")] + message_id: Annotated[str, Field(alias="messageId")] + message_type: Annotated[WorkspaceMessageType, Field(alias="messageType")] + + class AccountRateLimitsUpdatedNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -7031,11 +7663,11 @@ class AdditionalFileSystemPermissions(BaseModel): entries: list[FileSystemSandboxEntry] | None = None glob_scan_max_depth: Annotated[int | None, Field(alias="globScanMaxDepth", ge=1)] = None read: Annotated[ - list[AbsolutePathBuf] | None, + list[LegacyAppPathString] | None, Field(description="This will be removed in favor of `entries`."), ] = None write: Annotated[ - list[AbsolutePathBuf] | None, + list[LegacyAppPathString] | None, Field(description="This will be removed in favor of `entries`."), ] = None @@ -7048,6 +7680,8 @@ class AppInfo(BaseModel): branding: AppBranding | None = None description: str | None = None distribution_channel: Annotated[str | None, Field(alias="distributionChannel")] = None + icon_assets: Annotated[dict[str, Any] | None, Field(alias="iconAssets")] = None + icon_dark_assets: Annotated[dict[str, Any] | None, Field(alias="iconDarkAssets")] = None id: str install_url: Annotated[str | None, Field(alias="installUrl")] = None is_accessible: Annotated[bool | None, Field(alias="isAccessible")] = False @@ -7172,6 +7806,17 @@ class McpServerStatusListRequest(BaseModel): params: ListMcpServerStatusParams +class AccountLoginStartRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: RequestId + method: Annotated[ + Literal["account/login/start"], Field(title="Account/login/startRequestMethod") + ] + params: LoginAccountParams + + class CommandExecRequest(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -7292,6 +7937,36 @@ class ErrorNotification(BaseModel): will_retry: Annotated[bool, Field(alias="willRetry")] +class ExternalAgentConfigImportCompletedNotification(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + import_id: Annotated[str, Field(alias="importId")] + item_type_results: Annotated[ + list[ExternalAgentConfigImportTypeResult], Field(alias="itemTypeResults") + ] + + +class ExternalAgentConfigImportHistory(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + completed_at_ms: Annotated[int, Field(alias="completedAtMs")] + failures: list[ExternalAgentConfigImportItemTypeFailure] + import_id: Annotated[str, Field(alias="importId")] + successes: list[ExternalAgentConfigImportItemTypeSuccess] + + +class ExternalAgentConfigImportProgressNotification(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + import_id: Annotated[str, Field(alias="importId")] + item_type_results: Annotated[ + list[ExternalAgentConfigImportTypeResult], Field(alias="itemTypeResults") + ] + + class ExternalAgentConfigMigrationItem(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -7328,6 +8003,9 @@ class GetAccountRateLimitsResponse(BaseModel): model_config = ConfigDict( populate_by_name=True, ) + rate_limit_reset_credits: Annotated[ + RateLimitResetCreditsSummary | None, Field(alias="rateLimitResetCredits") + ] = None rate_limits: Annotated[ RateLimitSnapshot, Field( @@ -7344,6 +8022,23 @@ class GetAccountRateLimitsResponse(BaseModel): ] = None +class GetWorkspaceMessagesResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + feature_enabled: Annotated[ + bool, + Field( + alias="featureEnabled", + description="Whether the workspace-message backend route is available for this client.", + ), + ] + messages: Annotated[ + list[WorkspaceMessage], + Field(description="Active workspace messages returned by the backend."), + ] + + class HookCompletedNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -7399,6 +8094,13 @@ class ListMcpServerStatusResponse(BaseModel): ] = None +class ModelsRequirements(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + new_thread: Annotated[NewThreadModelDefaults | None, Field(alias="newThread")] = None + + class PluginShareContext(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -7442,6 +8144,9 @@ class PluginSummary(BaseModel): enabled: bool id: str install_policy: Annotated[PluginInstallPolicy, Field(alias="installPolicy")] + install_policy_source: Annotated[ + PluginInstallPolicySource | None, Field(alias="installPolicySource") + ] = None installed: bool interface: PluginInterface | None = None keywords: list[str] | None = [] @@ -7467,6 +8172,10 @@ class PluginSummary(BaseModel): ), ] = None source: PluginSource + version: Annotated[ + str | None, + Field(description="Version advertised by the remote marketplace backend when available."), + ] = None class RequestPermissionProfile(BaseModel): @@ -7483,6 +8192,8 @@ class FunctionCallOutputResponseItem(BaseModel): populate_by_name=True, ) call_id: str + id: str | None = None + internal_chat_message_metadata_passthrough: InternalChatMessageMetadataPassthrough | None = None output: FunctionCallOutputBody type: Annotated[ Literal["function_call_output"], Field(title="FunctionCallOutputResponseItemType") @@ -7494,6 +8205,8 @@ class CustomToolCallOutputResponseItem(BaseModel): populate_by_name=True, ) call_id: str + id: str | None = None + internal_chat_message_metadata_passthrough: InternalChatMessageMetadataPassthrough | None = None name: str | None = None output: FunctionCallOutputBody type: Annotated[ @@ -7504,6 +8217,7 @@ class CustomToolCallOutputResponseItem(BaseModel): class ResponseItem( RootModel[ MessageResponseItem + | AgentMessageResponseItem | ReasoningResponseItem | LocalShellCallResponseItem | FunctionCallResponseItem @@ -7525,6 +8239,7 @@ class ResponseItem( ) root: ( MessageResponseItem + | AgentMessageResponseItem | ReasoningResponseItem | LocalShellCallResponseItem | FunctionCallResponseItem @@ -7647,6 +8362,28 @@ class AppListUpdatedServerNotification(BaseModel): params: AppListUpdatedNotification +class ExternalAgentConfigImportProgressServerNotification(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + method: Annotated[ + Literal["externalAgentConfig/import/progress"], + Field(title="ExternalAgentConfig/import/progressNotificationMethod"), + ] + params: ExternalAgentConfigImportProgressNotification + + +class ExternalAgentConfigImportCompletedServerNotification(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + method: Annotated[ + Literal["externalAgentConfig/import/completed"], + Field(title="ExternalAgentConfig/import/completedNotificationMethod"), + ] + params: ExternalAgentConfigImportCompletedNotification + + class WindowsSandboxSetupCompletedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -7693,7 +8430,9 @@ class Turn(BaseModel): error: Annotated[ TurnError | None, Field(description="Only populated when the Turn's status is failed.") ] = None - id: str + id: Annotated[ + str, Field(description="Identifier for this turn. Codex-generated turn IDs are UUIDv7.") + ] items: Annotated[ list[ThreadItem], Field(description="Thread items currently included in this turn payload.") ] @@ -7761,6 +8500,51 @@ class ConfigBatchWriteRequest(BaseModel): params: ConfigBatchWriteParams +class ConfigRequirements(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + allow_appshots: Annotated[bool | None, Field(alias="allowAppshots")] = None + allow_managed_hooks_only: Annotated[bool | None, Field(alias="allowManagedHooksOnly")] = None + allow_remote_control: Annotated[bool | None, Field(alias="allowRemoteControl")] = None + allowed_approval_policies: Annotated[ + list[AskForApproval] | None, Field(alias="allowedApprovalPolicies") + ] = None + allowed_permission_profiles: Annotated[ + dict[str, Any] | None, Field(alias="allowedPermissionProfiles") + ] = None + allowed_sandbox_modes: Annotated[ + list[SandboxMode] | None, Field(alias="allowedSandboxModes") + ] = None + allowed_web_search_modes: Annotated[ + list[WebSearchMode] | None, Field(alias="allowedWebSearchModes") + ] = None + allowed_windows_sandbox_implementations: Annotated[ + list[WindowsSandboxSetupMode] | None, Field(alias="allowedWindowsSandboxImplementations") + ] = None + computer_use: Annotated[ComputerUseRequirements | None, Field(alias="computerUse")] = None + default_permissions: Annotated[str | None, Field(alias="defaultPermissions")] = None + enforce_residency: Annotated[ResidencyRequirement | None, Field(alias="enforceResidency")] = ( + None + ) + feature_requirements: Annotated[dict[str, Any] | None, Field(alias="featureRequirements")] = ( + None + ) + models: ModelsRequirements | None = None + + +class ConfigRequirementsReadResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + requirements: Annotated[ + ConfigRequirements | None, + Field( + description="Null if no requirements are configured (e.g. no requirements.toml/MDM entries)." + ), + ] = None + + class ExternalAgentConfigDetectResponse(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -7768,6 +8552,13 @@ class ExternalAgentConfigDetectResponse(BaseModel): items: list[ExternalAgentConfigMigrationItem] +class ExternalAgentConfigImportHistoriesReadResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + data: list[ExternalAgentConfigImportHistory] + + class ExternalAgentConfigImportParams(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -7775,6 +8566,12 @@ class ExternalAgentConfigImportParams(BaseModel): migration_items: Annotated[ list[ExternalAgentConfigMigrationItem], Field(alias="migrationItems") ] + source: Annotated[ + str | None, + Field( + description="Source product that produced the migration items. Missing means unspecified." + ), + ] = None class RequestPermissionsGuardianApprovalReviewAction(BaseModel): @@ -7878,12 +8675,14 @@ class PluginDetail(BaseModel): model_config = ConfigDict( populate_by_name=True, ) + app_templates: Annotated[list[AppTemplateSummary], Field(alias="appTemplates")] apps: list[AppSummary] description: str | None = None hooks: list[PluginHookSummary] marketplace_name: Annotated[str, Field(alias="marketplaceName")] marketplace_path: Annotated[AbsolutePathBuf | None, Field(alias="marketplacePath")] = None mcp_servers: Annotated[list[str], Field(alias="mcpServers")] + share_url: Annotated[str | None, Field(alias="shareUrl")] = None skills: list[SkillSummary] summary: PluginSummary @@ -8035,7 +8834,9 @@ class Thread(BaseModel): description="Optional Git metadata captured when the thread was created.", ), ] = None - id: str + id: Annotated[ + str, Field(description="Identifier for this thread. Codex-generated thread IDs are UUIDv7.") + ] model_provider: Annotated[ str, Field( @@ -8055,6 +8856,13 @@ class Thread(BaseModel): preview: Annotated[ str, Field(description="Usually the first user message in the thread, if available.") ] + recency_at: Annotated[ + int | None, + Field( + alias="recencyAt", + description="Unix timestamp (in seconds) used for thread recency ordering.", + ), + ] = None session_id: Annotated[ str, Field( @@ -8105,10 +8913,10 @@ class ThreadForkResponse(BaseModel): ] cwd: AbsolutePathBuf instruction_sources: Annotated[ - list[AbsolutePathBuf] | None, + list[LegacyAppPathString] | None, Field( alias="instructionSources", - description="Instruction source files currently loaded for this thread.", + description="Environment-native paths to instruction source files currently loaded for this thread.", ), ] = [] model: str @@ -8173,10 +8981,10 @@ class ThreadResumeResponse(BaseModel): ] cwd: AbsolutePathBuf instruction_sources: Annotated[ - list[AbsolutePathBuf] | None, + list[LegacyAppPathString] | None, Field( alias="instructionSources", - description="Instruction source files currently loaded for this thread.", + description="Environment-native paths to instruction source files currently loaded for this thread.", ), ] = [] model: str @@ -8226,10 +9034,10 @@ class ThreadStartResponse(BaseModel): ] cwd: AbsolutePathBuf instruction_sources: Annotated[ - list[AbsolutePathBuf] | None, + list[LegacyAppPathString] | None, Field( alias="instructionSources", - description="Instruction source files currently loaded for this thread.", + description="Environment-native paths to instruction source files currently loaded for this thread.", ), ] = [] model: str @@ -8278,6 +9086,7 @@ class ClientRequest( | ThreadResumeRequest | ThreadForkRequest | ThreadArchiveRequest + | ThreadDeleteRequest | ThreadUnsubscribeRequest | ThreadNameSetRequest | ThreadGoalSetRequest @@ -8341,6 +9150,9 @@ class ClientRequest( | AccountLoginCancelRequest | AccountLogoutRequest | AccountRateLimitsReadRequest + | AccountRateLimitResetCreditConsumeRequest + | AccountUsageReadRequest + | AccountWorkspaceMessagesReadRequest | AccountSendAddCreditsNudgeEmailRequest | FeedbackUploadRequest | CommandExecRequest @@ -8350,6 +9162,7 @@ class ClientRequest( | ConfigReadRequest | ExternalAgentConfigDetectRequest | ExternalAgentConfigImportRequest + | ExternalAgentConfigImportReadHistoriesRequest | ConfigValueWriteRequest | ConfigBatchWriteRequest | ConfigRequirementsReadRequest @@ -8366,6 +9179,7 @@ class ClientRequest( | ThreadResumeRequest | ThreadForkRequest | ThreadArchiveRequest + | ThreadDeleteRequest | ThreadUnsubscribeRequest | ThreadNameSetRequest | ThreadGoalSetRequest @@ -8429,6 +9243,9 @@ class ClientRequest( | AccountLoginCancelRequest | AccountLogoutRequest | AccountRateLimitsReadRequest + | AccountRateLimitResetCreditConsumeRequest + | AccountUsageReadRequest + | AccountWorkspaceMessagesReadRequest | AccountSendAddCreditsNudgeEmailRequest | FeedbackUploadRequest | CommandExecRequest @@ -8438,6 +9255,7 @@ class ClientRequest( | ConfigReadRequest | ExternalAgentConfigDetectRequest | ExternalAgentConfigImportRequest + | ExternalAgentConfigImportReadHistoriesRequest | ConfigValueWriteRequest | ConfigBatchWriteRequest | ConfigRequirementsReadRequest @@ -8482,6 +9300,7 @@ class ServerNotification( | ThreadStartedServerNotification | ThreadStatusChangedServerNotification | ThreadArchivedServerNotification + | ThreadDeletedServerNotification | ThreadUnarchivedServerNotification | ThreadClosedServerNotification | SkillsChangedServerNotification @@ -8517,6 +9336,7 @@ class ServerNotification( | AccountRateLimitsUpdatedServerNotification | AppListUpdatedServerNotification | RemoteControlStatusChangedServerNotification + | ExternalAgentConfigImportProgressServerNotification | ExternalAgentConfigImportCompletedServerNotification | FsChangedServerNotification | ItemReasoningSummaryTextDeltaServerNotification @@ -8525,6 +9345,8 @@ class ServerNotification( | ThreadCompactedServerNotification | ModelReroutedServerNotification | ModelVerificationServerNotification + | TurnModerationMetadataServerNotification + | ModelSafetyBufferingUpdatedServerNotification | WarningServerNotification | GuardianWarningServerNotification | DeprecationNoticeServerNotification @@ -8552,6 +9374,7 @@ class ServerNotification( | ThreadStartedServerNotification | ThreadStatusChangedServerNotification | ThreadArchivedServerNotification + | ThreadDeletedServerNotification | ThreadUnarchivedServerNotification | ThreadClosedServerNotification | SkillsChangedServerNotification @@ -8587,6 +9410,7 @@ class ServerNotification( | AccountRateLimitsUpdatedServerNotification | AppListUpdatedServerNotification | RemoteControlStatusChangedServerNotification + | ExternalAgentConfigImportProgressServerNotification | ExternalAgentConfigImportCompletedServerNotification | FsChangedServerNotification | ItemReasoningSummaryTextDeltaServerNotification @@ -8595,6 +9419,8 @@ class ServerNotification( | ThreadCompactedServerNotification | ModelReroutedServerNotification | ModelVerificationServerNotification + | TurnModerationMetadataServerNotification + | ModelSafetyBufferingUpdatedServerNotification | WarningServerNotification | GuardianWarningServerNotification | DeprecationNoticeServerNotification diff --git a/sdk/python/tests/test_artifact_workflow_and_binaries.py b/sdk/python/tests/test_artifact_workflow_and_binaries.py index ad1262e836..437ee860e9 100644 --- a/sdk/python/tests/test_artifact_workflow_and_binaries.py +++ b/sdk/python/tests/test_artifact_workflow_and_binaries.py @@ -373,6 +373,7 @@ def test_schema_normalization_only_flattens_string_literal_oneofs( "ExperimentalFeatureStage", "ProcessOutputStream", "CommandExecOutputStream", + "ConsumeAccountRateLimitResetCreditOutcome", "AutoCompactTokenLimitScope", ] @@ -501,32 +502,33 @@ def test_source_sdk_template_pins_published_runtime() -> None: "dependencies": pyproject["project"]["dependencies"], } == { "sdk_template_version": "0.0.0-dev", - "runtime_pin": "0.137.0a4", + "runtime_pin": "0.144.4", "dependencies": [ "pydantic>=2.12", - "openai-codex-cli-bin==0.137.0a4", + "openai-codex-cli-bin==0.144.4", ], } -def test_source_sdk_package_declares_beta_documentation() -> None: - """Public package metadata should link beta docs.""" +def test_source_sdk_package_declares_stable_documentation() -> None: + """Public package metadata should link stable docs.""" pyproject = tomllib.loads((ROOT / "pyproject.toml").read_text()) readme = (ROOT / "README.md").read_text() assert { "description": pyproject["project"]["description"], - "is_beta": "Development Status :: 4 - Beta" in pyproject["project"]["classifiers"], + "is_stable": "Development Status :: 5 - Production/Stable" + in pyproject["project"]["classifiers"], "license": pyproject["project"]["license"], "documentation": pyproject["project"]["urls"]["Documentation"], - "readme_is_beta": "# OpenAI Codex Python SDK (Beta)" in readme, + "readme_is_stable": "# OpenAI Codex Python SDK\n" in readme, "local_license_file": (ROOT / "LICENSE").exists(), } == { "description": "Python SDK for Codex", - "is_beta": True, + "is_stable": True, "license": "Apache-2.0", "documentation": "https://github.com/openai/codex/tree/main/sdk/python/docs", - "readme_is_beta": True, + "readme_is_stable": True, "local_license_file": False, } @@ -558,7 +560,7 @@ def test_release_metadata_retries_without_invalid_auth( def test_runtime_setup_reads_independent_runtime_pin_and_release_tags() -> None: - """Runtime package pins remain independent of the SDK beta version.""" + """Runtime package pins remain independent of the SDK template version.""" runtime_setup = _load_runtime_setup_module() pyproject = tomllib.loads((ROOT / "pyproject.toml").read_text()) @@ -573,7 +575,7 @@ def test_runtime_setup_reads_independent_runtime_pin_and_release_tags() -> None: } == { "package_name": "openai-codex-cli-bin", "sdk_template_version": "0.0.0-dev", - "runtime_pin": "0.137.0a4", + "runtime_pin": "0.144.4", "normalized_release_version": "0.116.0a1", "release_tag": "rust-v0.116.0-alpha.1", } @@ -777,7 +779,7 @@ def test_stage_sdk_release_preserves_reviewed_runtime_pin(tmp_path: Path) -> Non script = _load_update_script_module() staged = script.stage_python_sdk_package( tmp_path / "sdk-stage", - "0.1.0b1", + "0.144.4", ) pyproject = tomllib.loads((staged / "pyproject.toml").read_text()) @@ -787,18 +789,18 @@ def test_stage_sdk_release_preserves_reviewed_runtime_pin(tmp_path: Path) -> Non "dependencies": pyproject["project"]["dependencies"], } == { "name": "openai-codex", - "version": "0.1.0b1", + "version": "0.144.4", "dependencies": [ "pydantic>=2.12", - "openai-codex-cli-bin==0.137.0a4", + "openai-codex-cli-bin==0.144.4", ], } assert ( - '__version__ = "0.1.0b1"' + '__version__ = "0.144.4"' not in (staged / "src" / "openai_codex" / "__init__.py").read_text() ) assert ( - 'client_version: str = "0.1.0b1"' + 'client_version: str = "0.144.4"' not in (staged / "src" / "openai_codex" / "client.py").read_text() ) assert not any((staged / "src" / "openai_codex").glob("bin/**")) @@ -811,23 +813,23 @@ def test_stage_sdk_release_replaces_existing_staging_dir(tmp_path: Path) -> None old_file.parent.mkdir(parents=True) old_file.write_text("stale") - staged = script.stage_python_sdk_package(staging_dir, "0.1.0b1") + staged = script.stage_python_sdk_package(staging_dir, "0.144.4") assert staged == staging_dir assert not old_file.exists() -def test_sdk_beta_release_can_pin_stable_runtime(tmp_path: Path) -> None: +def test_sdk_release_matches_stable_runtime(tmp_path: Path) -> None: script = _load_update_script_module() package_archive = _write_fake_codex_package_archive(tmp_path, script) sdk_stage = script.stage_python_sdk_package( tmp_path / "sdk-stage", - "0.1.0b1", + "0.144.4", ) runtime_stage = script.stage_python_runtime_package( tmp_path / "runtime-stage", - "0.137.0a4", + "0.144.4", package_archive, ) @@ -839,11 +841,11 @@ def test_sdk_beta_release_can_pin_stable_runtime(tmp_path: Path) -> None: "runtime_version": runtime_pyproject["project"]["version"], "sdk_dependencies": sdk_pyproject["project"]["dependencies"], } == { - "sdk_version": "0.1.0b1", - "runtime_version": "0.137.0a4", + "sdk_version": "0.144.4", + "runtime_version": "0.144.4", "sdk_dependencies": [ "pydantic>=2.12", - "openai-codex-cli-bin==0.137.0a4", + "openai-codex-cli-bin==0.144.4", ], } @@ -856,7 +858,7 @@ def test_stage_sdk_runs_type_generation_before_staging(tmp_path: Path) -> None: "stage-sdk", str(tmp_path / "sdk-stage"), "--sdk-version", - "0.1.0b1", + "0.144.4", ] ) @@ -887,7 +889,7 @@ def test_stage_sdk_runs_type_generation_before_staging(tmp_path: Path) -> None: script.run_command(args, ops) - assert calls == ["generate_types", "stage_sdk:0.1.0b1"] + assert calls == ["generate_types", "stage_sdk:0.144.4"] def test_stage_runtime_stages_package_without_type_generation(tmp_path: Path) -> None: diff --git a/sdk/python/tests/test_client_rpc_methods.py b/sdk/python/tests/test_client_rpc_methods.py index 15be24f3b4..1441d2df38 100644 --- a/sdk/python/tests/test_client_rpc_methods.py +++ b/sdk/python/tests/test_client_rpc_methods.py @@ -7,13 +7,19 @@ from openai_codex.generated.notification_registry import notification_turn_id from openai_codex.generated.v2_all import ( AgentMessageDeltaNotification, ApprovalsReviewer, + ReasoningEffort, + ReasoningEffortOption, + ThreadForkParams, ThreadListParams, ThreadResumeResponse, + ThreadStartParams, ThreadTokenUsageUpdatedNotification, TurnCompletedNotification, + TurnStartParams, WarningNotification, ) from openai_codex.models import Notification, UnknownNotification +from openai_codex.types import ThreadSource ROOT = Path(__file__).resolve().parents[1] @@ -31,6 +37,56 @@ def test_generated_v2_bundle_has_single_shared_plan_type_definition() -> None: assert source.count("class PlanType(") == 1 +def test_reasoning_effort_preserves_enum_constants_and_accepts_future_values() -> None: + """Known effort members and new runtime values should share the enum-style API.""" + known_option = ReasoningEffortOption.model_validate( + {"description": "Balanced", "reasoningEffort": "medium"} + ) + future_option = ReasoningEffortOption.model_validate( + {"description": "Future", "reasoningEffort": "ultra"} + ) + turn_params = TurnStartParams( + thread_id="thread-1", + input=[], + effort=ReasoningEffort.medium, + ) + + assert { + "known_member": ReasoningEffort.medium.value, + "known_option": known_option.reasoning_effort.value, + "future_option": future_option.reasoning_effort.value, + "turn_effort": _params_dict(turn_params)["effort"], + } == { + "known_member": "medium", + "known_option": "medium", + "future_option": "ultra", + "turn_effort": "medium", + } + + +def test_thread_source_preserves_enum_constants_and_accepts_future_values() -> None: + """Known thread sources and new runtime values should share the enum-style API.""" + start_params = ThreadStartParams(thread_source=ThreadSource.user) + fork_params = ThreadForkParams( + thread_id="thread-1", + thread_source=ThreadSource("future_source"), + ) + + assert { + "known_member": ThreadSource.user.value, + "subagent_member": ThreadSource.subagent.value, + "memory_member": ThreadSource.memory_consolidation.value, + "start_source": _params_dict(start_params)["threadSource"], + "fork_source": _params_dict(fork_params)["threadSource"], + } == { + "known_member": "user", + "subagent_member": "subagent", + "memory_member": "memory_consolidation", + "start_source": "user", + "fork_source": "future_source", + } + + def test_thread_resume_response_accepts_auto_review_reviewer() -> None: """Generated response models should keep accepting the auto review enum value.""" response = ThreadResumeResponse.model_validate( diff --git a/sdk/python/tests/test_contract_generation.py b/sdk/python/tests/test_contract_generation.py index 36d37735c7..81d1692bdf 100644 --- a/sdk/python/tests/test_contract_generation.py +++ b/sdk/python/tests/test_contract_generation.py @@ -40,7 +40,7 @@ def test_generated_files_are_up_to_date(): # Regenerate contract artifacts via the pinned runtime package, not a local # app-server binary from the checkout or CI environment. - assert importlib.metadata.version("openai-codex-cli-bin") == "0.137.0a4" + assert importlib.metadata.version("openai-codex-cli-bin") == "0.144.4" env = os.environ.copy() env.pop("CODEX_EXEC_PATH", None) python_bin = str(Path(sys.executable).parent) diff --git a/sdk/python/uv.lock b/sdk/python/uv.lock index b8a777240a..33618337a3 100644 --- a/sdk/python/uv.lock +++ b/sdk/python/uv.lock @@ -7,7 +7,7 @@ exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for exclude-newer-span = "P7D" [options.exclude-newer-package] -openai-codex-cli-bin = "2026-06-03T19:00:00Z" +openai-codex-cli-bin = "2026-07-15T01:00:00Z" [[package]] name = "annotated-types" @@ -306,7 +306,7 @@ test = [ [package.metadata] requires-dist = [ - { name = "openai-codex-cli-bin", specifier = "==0.137.0a4" }, + { name = "openai-codex-cli-bin", specifier = "==0.144.4" }, { name = "pydantic", specifier = ">=2.12" }, ] @@ -325,17 +325,17 @@ test = [ [[package]] name = "openai-codex-cli-bin" -version = "0.137.0a4" +version = "0.144.4" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/60/af73ef1676cd477fa83ed4b889bf3b57c63c47dd87025b2cc4262793cff6/openai_codex_cli_bin-0.137.0a4-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:b33c3917e0b58d527ee11a11a78ad390f7d8e6aa25577dd21665ab3c8bf5cf9a", size = 94300191, upload-time = "2026-06-03T18:44:36.312Z" }, - { url = "https://files.pythonhosted.org/packages/92/8f/d1a5f8c87176e00ef6a85798794f4530f5eb04e5a1a13468b5b3c3a361f9/openai_codex_cli_bin-0.137.0a4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3d0f0bc5becc88c61952fbfa9bd792ac9d74fa78b3a6bd40f545b612048b07eb", size = 83924479, upload-time = "2026-06-03T18:44:40.854Z" }, - { url = "https://files.pythonhosted.org/packages/3e/3c/fc00bcdc0c302208317d5eb1d0bfaab3024f351cd0121400f19baa6b19aa/openai_codex_cli_bin-0.137.0a4-py3-none-manylinux_2_17_aarch64.whl", hash = "sha256:2f1656339e2736868c4cce59f6d9e5c633879123687169b03b1137d42bf2c11a", size = 83363315, upload-time = "2026-06-03T18:44:44.851Z" }, - { url = "https://files.pythonhosted.org/packages/ec/09/39362e944ebeb12fcbfb86881fbb4dd6e806f77f7541c1f1f993bb9351a0/openai_codex_cli_bin-0.137.0a4-py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:6454f838d44c56c1ed07a29b391fa412785e5dd2ffd06db0b62e62478c19bb64", size = 90611239, upload-time = "2026-06-03T18:44:49.338Z" }, - { url = "https://files.pythonhosted.org/packages/fa/38/87b1247fdfe95cddce7f7fe8331d6843cf037e14292c0f5004e23247133b/openai_codex_cli_bin-0.137.0a4-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:f5ae7401d00c65d56a75d9645d7bf87d809566a12d238e4b2a8b328a02f2316e", size = 83363315, upload-time = "2026-06-03T18:44:53.428Z" }, - { url = "https://files.pythonhosted.org/packages/fb/c4/3c693ad07e587f6b3a28128c417f2e831d81a40cdbd85c0e5f0f36aaff82/openai_codex_cli_bin-0.137.0a4-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:3dcec1e649448be498d6e7ec0e1f71dca83efa76063d90890dafb41e987069b7", size = 90611238, upload-time = "2026-06-03T18:44:57.612Z" }, - { url = "https://files.pythonhosted.org/packages/9e/26/81e037066b9b8d312a6f9e09015e452ce17630d5ab88e02a4c1d9503e4e8/openai_codex_cli_bin-0.137.0a4-py3-none-win_amd64.whl", hash = "sha256:9e13bf68e18e36bd3a0efd51213281c83e9f6ec22bdb7a45bd2e0211822733a9", size = 94744969, upload-time = "2026-06-03T18:45:02.23Z" }, - { url = "https://files.pythonhosted.org/packages/0d/a3/952bc2a5d62373a51fea161effe3b338b3417c2f6e65fe467ed91b205e2b/openai_codex_cli_bin-0.137.0a4-py3-none-win_arm64.whl", hash = "sha256:5ec4303ca2dcb5f838e0de3ca7f44050b6bcdd41d281a178c3a1420a985a515d", size = 86963504, upload-time = "2026-06-03T18:45:07.131Z" }, + { url = "https://files.pythonhosted.org/packages/79/30/7e457c007a32aa7333a78438a9f532504c3b77a1ea57e7808855712c2c0f/openai_codex_cli_bin-0.144.4-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:4d587d152d5f0aa25f21ded4d08aac5150da48639b29fc3e57b2a8b413d06903", size = 126851183, upload-time = "2026-07-15T00:14:00.171Z" }, + { url = "https://files.pythonhosted.org/packages/65/eb/64c180514a2cc3e2500e486813f5a8d7f7e349342e9bebd78d99ddd9791a/openai_codex_cli_bin-0.144.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:05db505a9c7f020f58b70837a94e00d32a50086986c267bcc44ea97b573d4a05", size = 116474758, upload-time = "2026-07-15T00:14:08.177Z" }, + { url = "https://files.pythonhosted.org/packages/85/34/921ab692c7ed140941a91e39b84c6deafddb45072793f3a5f6dcbf86f59a/openai_codex_cli_bin-0.144.4-py3-none-manylinux_2_17_aarch64.whl", hash = "sha256:cd4bb31b8a477a3adba22139c8c493693fa5292ba21e86eef08ace3e96c41294", size = 119437596, upload-time = "2026-07-15T00:14:17.418Z" }, + { url = "https://files.pythonhosted.org/packages/25/62/39e630cf8b7b2e2444a5a6669235a6cd88004869a25bb7f3f629ed35638c/openai_codex_cli_bin-0.144.4-py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:4106229c38f37245c3eea8d904426afd45b8bf19831765715647f5402f757c06", size = 128817757, upload-time = "2026-07-15T00:14:30.539Z" }, + { url = "https://files.pythonhosted.org/packages/23/24/318f91a95baaff845307e529d138d42a7202e6bd0e626556058eab3dead5/openai_codex_cli_bin-0.144.4-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:d2d3fada11731938e3d3e3660819d5324b7f92e825a0ed5aede63100b36ffc9a", size = 119437594, upload-time = "2026-07-15T00:14:39.327Z" }, + { url = "https://files.pythonhosted.org/packages/2e/a0/65e6fd3a6fba52639937801d9ce517b0c48026458723bb9f08eb07a1dd35/openai_codex_cli_bin-0.144.4-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:70fb62ed7755e332dd8b00ed48e22ee16df10f4a977335039e237cd330490df3", size = 128817755, upload-time = "2026-07-15T00:14:47.849Z" }, + { url = "https://files.pythonhosted.org/packages/e3/8a/3ab5fc97352e8f780d472c8dd6d7504d6a670cd7dede106d461ac1171999/openai_codex_cli_bin-0.144.4-py3-none-win_amd64.whl", hash = "sha256:56e142974467332f1f669b89f2636e06b3ada09413512abb2f24c33b4a4f59fc", size = 140595092, upload-time = "2026-07-15T00:14:58.484Z" }, + { url = "https://files.pythonhosted.org/packages/70/1a/3aa52ab8f89e0f596b6eea835e3f3494697da51917d3231f5f48f92e2bcb/openai_codex_cli_bin-0.144.4-py3-none-win_arm64.whl", hash = "sha256:2ad01058db7181323ae7c6217e560702e38c4f107595b99ab1d0abc9f184890a", size = 130665105, upload-time = "2026-07-15T00:15:08.861Z" }, ] [[package]]