diff --git a/.github/workflows/python-sdk-release.yml b/.github/workflows/python-sdk-release.yml index 654dd8d8225..96870db171d 100644 --- a/.github/workflows/python-sdk-release.yml +++ b/.github/workflows/python-sdk-release.yml @@ -34,8 +34,8 @@ jobs: exit 1 fi - # The pinned runtime currently publishes a musllinux Linux wheel. - # Build in Alpine so release type generation installs that wheel. + # Build in a glibc Linux image so release type generation installs + # the pinned manylinux runtime wheel. docker run --rm \ --user "$(id -u):$(id -g)" \ -e HOME=/tmp/codex-python-sdk-home \ @@ -46,7 +46,7 @@ jobs: -v "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}" \ -v "${RUNNER_TEMP}:${RUNNER_TEMP}" \ -w "${GITHUB_WORKSPACE}/sdk/python" \ - python:3.12-alpine \ + python:3.12-slim \ sh -euxc ' python -m venv /tmp/release-tools /tmp/release-tools/bin/python -m pip install build twine uv==0.11.3 diff --git a/.github/workflows/sdk.yml b/.github/workflows/sdk.yml index 54ed8dc558e..4103a948cd0 100644 --- a/.github/workflows/sdk.yml +++ b/.github/workflows/sdk.yml @@ -23,15 +23,15 @@ jobs: run: | set -euo pipefail - # Run inside Alpine so dependency resolution exercises the pinned - # runtime wheel on the same Linux wheel family that CI installs. + # Run inside a glibc Linux image so dependency resolution exercises + # the pinned manylinux runtime wheel that users install. docker run --rm \ --user "$(id -u):$(id -g)" \ -e HOME=/tmp/codex-python-sdk-home \ -e UV_LINK_MODE=copy \ -v "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}" \ -w "${GITHUB_WORKSPACE}/sdk/python" \ - python:3.12-alpine \ + python:3.12-slim \ sh -euxc ' python -m venv /tmp/uv /tmp/uv/bin/python -m pip install uv==0.11.3 diff --git a/sdk/python/pyproject.toml b/sdk/python/pyproject.toml index 9c93be69a5d..6b7bbddd878 100644 --- a/sdk/python/pyproject.toml +++ b/sdk/python/pyproject.toml @@ -16,7 +16,7 @@ classifiers = [ "Intended Audience :: Developers", "Topic :: Software Development :: Libraries :: Python Modules", ] -dependencies = ["pydantic>=2.12", "openai-codex-cli-bin==0.132.0"] +dependencies = ["pydantic>=2.12", "openai-codex-cli-bin==0.136.0"] [project.urls] Homepage = "https://github.com/openai/codex" @@ -78,10 +78,10 @@ combine-as-imports = true [tool.uv] exclude-newer = "7 days" -exclude-newer-package = { openai-codex-cli-bin = "2026-05-20T21:00:00Z" } +exclude-newer-package = { openai-codex-cli-bin = "2026-06-01T20:00:00Z" } index-strategy = "first-index" [tool.uv.pip] exclude-newer = "7 days" -exclude-newer-package = { openai-codex-cli-bin = "2026-05-20T21:00:00Z" } +exclude-newer-package = { openai-codex-cli-bin = "2026-06-01T20: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 1742ced547e..a4af5d605e1 100755 --- a/sdk/python/scripts/update_sdk_artifacts.py +++ b/sdk/python/scripts/update_sdk_artifacts.py @@ -1163,7 +1163,9 @@ def generate_public_api_flat_methods() -> None: turn_start_fields = _load_public_fields( "openai_codex.generated.v2_all", "TurnStartParams", - exclude={"thread_id", "input", *approval_fields}, + # Keep the wire model current without exposing this app-server field + # through the ergonomic Python API yet. + exclude={"thread_id", "input", "client_user_message_id", *approval_fields}, ) turn_start_fields = _replace_public_sandbox_field(turn_start_fields, wire_name="sandbox_policy") @@ -1267,7 +1269,7 @@ def build_parser() -> argparse.ArgumentParser: "--platform-tag", help=( "Optional wheel platform tag override, for example " - "macosx_11_0_arm64 or musllinux_1_1_x86_64." + "macosx_11_0_arm64 or manylinux_2_17_x86_64." ), ) return parser diff --git a/sdk/python/src/openai_codex/generated/notification_registry.py b/sdk/python/src/openai_codex/generated/notification_registry.py index c55eb5b9b75..d5e620a7a3c 100644 --- a/sdk/python/src/openai_codex/generated/notification_registry.py +++ b/sdk/python/src/openai_codex/generated/notification_registry.py @@ -57,6 +57,7 @@ from .v2_all import ThreadRealtimeStartedNotification from .v2_all import ThreadRealtimeTranscriptDeltaNotification from .v2_all import ThreadRealtimeTranscriptDoneNotification +from .v2_all import ThreadSettingsUpdatedNotification from .v2_all import ThreadStartedNotification from .v2_all import ThreadStatusChangedNotification from .v2_all import ThreadTokenUsageUpdatedNotification @@ -122,6 +123,7 @@ "thread/realtime/started": ThreadRealtimeStartedNotification, "thread/realtime/transcript/delta": ThreadRealtimeTranscriptDeltaNotification, "thread/realtime/transcript/done": ThreadRealtimeTranscriptDoneNotification, + "thread/settings/updated": ThreadSettingsUpdatedNotification, "thread/started": ThreadStartedNotification, "thread/status/changed": ThreadStatusChangedNotification, "thread/tokenUsage/updated": ThreadTokenUsageUpdatedNotification, diff --git a/sdk/python/src/openai_codex/generated/v2_all.py b/sdk/python/src/openai_codex/generated/v2_all.py index 85120b82932..c27a8f75caa 100644 --- a/sdk/python/src/openai_codex/generated/v2_all.py +++ b/sdk/python/src/openai_codex/generated/v2_all.py @@ -56,7 +56,7 @@ class ActivePermissionProfile(BaseModel): extends: Annotated[ str | None, Field( - description="Parent profile identifier once permissions profiles support inheritance. This is currently always `null`." + description="Parent profile identifier from the selected permissions profile's `extends` setting, when present." ), ] = None id: Annotated[ @@ -77,6 +77,11 @@ class AddCreditsNudgeEmailStatus(Enum): cooldown_active = "cooldown_active" +class AdditionalContextKind(Enum): + untrusted = "untrusted" + application = "application" + + class AdditionalNetworkPermissions(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -251,6 +256,11 @@ class AuthMode(Enum): agent_identity = "agentIdentity" +class AutoCompactTokenLimitScope(Enum): + total = "total" + body_after_prefix = "body_after_prefix" + + class AutoReviewDecisionSource(RootModel[Literal["agent"]]): model_config = ConfigDict( populate_by_name=True, @@ -563,6 +573,13 @@ class CommandMigration(BaseModel): name: str +class ComputerUseRequirements(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + allow_locked_computer_use: Annotated[bool | None, Field(alias="allowLockedComputerUse")] = None + + class MdmConfigLayerSource(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -675,7 +692,7 @@ class ConfigReadParams(BaseModel): description="Optional working directory to resolve project config layers. If specified, return the effective config as seen from that directory (i.e., including any project layers between `cwd` and the project/repo root)." ), ] = None - include_layers: Annotated[bool | None, Field(alias="includeLayers")] = False + include_layers: Annotated[bool | None, Field(alias="includeLayers")] = None class CommandConfiguredHookHandler(BaseModel): @@ -913,7 +930,7 @@ class FeedbackUploadParams(BaseModel): ) classification: str extra_log_files: Annotated[list[str] | None, Field(alias="extraLogFiles")] = None - include_logs: Annotated[bool, Field(alias="includeLogs")] + include_logs: Annotated[bool | None, Field(alias="includeLogs")] = None reason: str | None = None tags: dict[str, Any] | None = None thread_id: Annotated[str | None, Field(alias="threadId")] = None @@ -939,7 +956,7 @@ class FileChangeOutputDeltaNotification(BaseModel): class FileSystemAccessMode(Enum): read = "read" write = "write" - none = "none" + deny = "deny" class PathFileSystemPath(BaseModel): @@ -1276,6 +1293,17 @@ class InputTextFunctionCallOutputContentItem(BaseModel): ] +class EncryptedContentFunctionCallOutputContentItem(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + encrypted_content: str + type: Annotated[ + Literal["encrypted_content"], + Field(title="EncryptedContentFunctionCallOutputContentItemType"), + ] + + class FuzzyFileSearchMatchType(Enum): file = "file" directory = "directory" @@ -1335,7 +1363,7 @@ class GetAccountParams(BaseModel): alias="refreshToken", description="When `true`, requests a proactive token refresh before returning.\n\nIn managed auth mode this triggers the normal refresh-token flow. In external auth mode this flag is ignored. Clients should refresh tokens themselves and call `account/login/start` with `chatgptAuthTokens`.", ), - ] = False + ] = None class GitInfo(BaseModel): @@ -1425,6 +1453,8 @@ class HookEventName(Enum): post_compact = "postCompact" session_start = "sessionStart" user_prompt_submit = "userPromptSubmit" + subagent_start = "subagentStart" + subagent_stop = "subagentStop" stop = "stop" @@ -1506,6 +1536,8 @@ class HooksListParams(BaseModel): class ImageDetail(Enum): + auto = "auto" + low = "low" high = "high" original = "original" @@ -1742,6 +1774,8 @@ class ManagedHooksRequirements(BaseModel): pre_tool_use: Annotated[list[ConfiguredHookMatcherGroup], Field(alias="PreToolUse")] session_start: Annotated[list[ConfiguredHookMatcherGroup], Field(alias="SessionStart")] stop: Annotated[list[ConfiguredHookMatcherGroup], Field(alias="Stop")] + subagent_start: Annotated[list[ConfiguredHookMatcherGroup], Field(alias="SubagentStart")] + subagent_stop: Annotated[list[ConfiguredHookMatcherGroup], Field(alias="SubagentStop")] user_prompt_submit: Annotated[list[ConfiguredHookMatcherGroup], Field(alias="UserPromptSubmit")] managed_dir: Annotated[str | None, Field(alias="managedDir")] = None windows_managed_dir: Annotated[str | None, Field(alias="windowsManagedDir")] = None @@ -1835,6 +1869,18 @@ class McpResourceReadParams(BaseModel): uri: str +class McpServerInfo(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + description: str | None = None + icons: list | None = None + name: str + title: str | None = None + version: str + website_url: Annotated[str | None, Field(alias="websiteUrl")] = None + + class McpServerMigration(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -2142,7 +2188,7 @@ class NetworkRequirements(BaseModel): class NetworkUnixSocketPermission(Enum): allow = "allow" - none = "none" + deny = "deny" class NonSteerableTurnKind(Enum): @@ -2188,6 +2234,32 @@ class PatchChangeKind( root: AddPatchChangeKind | DeletePatchChangeKind | UpdatePatchChangeKind +class PermissionProfileListParams(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + cursor: Annotated[ + str | None, Field(description="Opaque pagination cursor returned by a previous call.") + ] = None + cwd: Annotated[ + str | None, + Field(description="Optional working directory to resolve project config layers."), + ] = None + limit: Annotated[ + int | None, Field(description="Optional page size; defaults to the full result set.", ge=0) + ] = None + + +class PermissionProfileSummary(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + description: Annotated[ + str | None, Field(description="Optional user-facing description for display in clients.") + ] = None + id: Annotated[str, Field(description="Available permission profile identifier.")] + + class Personality(Enum): none = "none" friendly = "friendly" @@ -2332,6 +2404,7 @@ class PluginInterface(BaseModel): class PluginListMarketplaceKind(Enum): local = "local" + vertical = "vertical" workspace_directory = "workspace-directory" shared_with_me = "shared-with-me" @@ -3469,6 +3542,20 @@ class SkillsConfigWriteResponse(BaseModel): effective_enabled: Annotated[bool, Field(alias="effectiveEnabled")] +class SkillsExtraRootsSetParams(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + extra_roots: Annotated[list[AbsolutePathBuf], Field(alias="extraRoots")] + + +class SkillsExtraRootsSetResponse(BaseModel): + pass + model_config = ConfigDict( + populate_by_name=True, + ) + + class SkillsListParams(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -3624,6 +3711,20 @@ class ThreadCompactStartResponse(BaseModel): ) +class ThreadGoalClearParams(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + thread_id: Annotated[str, Field(alias="threadId")] + + +class ThreadGoalClearResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + cleared: bool + + class ThreadGoalClearedNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -3631,6 +3732,13 @@ class ThreadGoalClearedNotification(BaseModel): thread_id: Annotated[str, Field(alias="threadId")] +class ThreadGoalGetParams(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + thread_id: Annotated[str, Field(alias="threadId")] + + class ThreadGoalStatus(Enum): active = "active" paused = "paused" @@ -3749,6 +3857,7 @@ class McpToolCallThreadItem(BaseModel): error: McpToolCallError | None = None id: str mcp_app_resource_uri: Annotated[str | None, Field(alias="mcpAppResourceUri")] = None + plugin_id: Annotated[str | None, Field(alias="pluginId")] = None result: McpToolCallResult | None = None server: str status: McpToolCallStatus @@ -3922,7 +4031,7 @@ class ThreadReadParams(BaseModel): alias="includeTurns", description="When true, include turns and their items from rollout history.", ), - ] = False + ] = None thread_id: Annotated[str, Field(alias="threadId")] @@ -4536,6 +4645,14 @@ class AccountUpdatedNotification(BaseModel): plan_type: Annotated[PlanType | None, Field(alias="planType")] = None +class AdditionalContextEntry(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + kind: AdditionalContextKind + value: str + + class AppConfig(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -4629,6 +4746,24 @@ class ThreadNameSetRequest(BaseModel): params: ThreadSetNameParams +class ThreadGoalGetRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: RequestId + method: Annotated[Literal["thread/goal/get"], Field(title="Thread/goal/getRequestMethod")] + params: ThreadGoalGetParams + + +class ThreadGoalClearRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: RequestId + method: Annotated[Literal["thread/goal/clear"], Field(title="Thread/goal/clearRequestMethod")] + params: ThreadGoalClearParams + + class ThreadMetadataUpdateRequest(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -4730,6 +4865,17 @@ class SkillsListRequest(BaseModel): params: SkillsListParams +class SkillsExtraRootsSetRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: RequestId + method: Annotated[ + Literal["skills/extraRoots/set"], Field(title="Skills/extraRoots/setRequestMethod") + ] + params: SkillsExtraRootsSetParams + + class HooksListRequest(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -4995,6 +5141,17 @@ class ExperimentalFeatureListRequest(BaseModel): params: ExperimentalFeatureListParams +class PermissionProfileListRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: RequestId + method: Annotated[ + Literal["permissionProfile/list"], Field(title="PermissionProfile/listRequestMethod") + ] + params: PermissionProfileListParams + + class ExperimentalFeatureEnablementSetRequest(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -5431,16 +5588,22 @@ 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 ) @@ -5608,13 +5771,19 @@ class InputImageFunctionCallOutputContentItem(BaseModel): class FunctionCallOutputContentItem( - RootModel[InputTextFunctionCallOutputContentItem | InputImageFunctionCallOutputContentItem] + RootModel[ + InputTextFunctionCallOutputContentItem + | InputImageFunctionCallOutputContentItem + | EncryptedContentFunctionCallOutputContentItem + ] ): model_config = ConfigDict( populate_by_name=True, ) root: Annotated[ - InputTextFunctionCallOutputContentItem | InputImageFunctionCallOutputContentItem, + InputTextFunctionCallOutputContentItem + | InputImageFunctionCallOutputContentItem + | EncryptedContentFunctionCallOutputContentItem, Field( description="Responses API compatible content items that can be returned by a tool call. This is a subset of ContentItem with the types we support as function call outputs." ), @@ -5767,6 +5936,7 @@ class ListMcpServerStatusParams(BaseModel): int | None, Field(description="Optional page size; defaults to a server-defined value.", ge=0), ] = None + thread_id: Annotated[str | None, Field(alias="threadId")] = None class McpResourceReadResponse(BaseModel): @@ -5784,6 +5954,7 @@ class McpServerStatus(BaseModel): name: str resource_templates: Annotated[list[ResourceTemplate], Field(alias="resourceTemplates")] resources: list[Resource] + server_info: Annotated[McpServerInfo | None, Field(alias="serverInfo")] = None tools: dict[str, Tool] @@ -5817,6 +5988,13 @@ class Model(BaseModel): ] = [] availability_nux: Annotated[ModelAvailabilityNux | None, Field(alias="availabilityNux")] = None default_reasoning_effort: Annotated[ReasoningEffort, Field(alias="defaultReasoningEffort")] + default_service_tier: Annotated[ + str | None, + Field( + alias="defaultServiceTier", + description="Catalog default service tier id for this model, when one is configured.", + ), + ] = None description: str display_name: Annotated[str, Field(alias="displayName")] hidden: bool @@ -5859,6 +6037,20 @@ class OverriddenMetadata(BaseModel): overriding_layer: Annotated[ConfigLayerMetadata, Field(alias="overridingLayer")] +class PermissionProfileListResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + data: list[PermissionProfileSummary] + next_cursor: Annotated[ + str | None, + Field( + alias="nextCursor", + description="Opaque cursor to pass to the next call to continue after the last item. If None, there are no more items to return.", + ), + ] = None + + class PluginSharePrincipal(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -6332,6 +6524,30 @@ class ThreadGoal(BaseModel): updated_at: Annotated[int, Field(alias="updatedAt")] +class ThreadGoalGetResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + goal: ThreadGoal | None = None + + +class ThreadGoalSetParams(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + objective: str | None = None + status: ThreadGoalStatus | None = None + thread_id: Annotated[str, Field(alias="threadId")] + token_budget: Annotated[int | None, Field(alias="tokenBudget")] = None + + +class ThreadGoalSetResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + goal: ThreadGoal + + class ThreadGoalUpdatedNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -6345,6 +6561,7 @@ class UserMessageThreadItem(BaseModel): model_config = ConfigDict( populate_by_name=True, ) + client_id: Annotated[str | None, Field(alias="clientId")] = None content: list[UserInput] id: str type: Annotated[Literal["userMessage"], Field(title="UserMessageThreadItemType")] @@ -6536,6 +6753,55 @@ class ThreadListParams(BaseModel): ] = None +class ThreadResumeInitialTurnsPageParams(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + items_view: Annotated[ + TurnItemsView | None, + Field( + alias="itemsView", + description="How much item detail to include for each returned turn; defaults to summary.", + ), + ] = None + limit: Annotated[int | None, Field(description="Optional turn page size.", ge=0)] = None + sort_direction: Annotated[ + SortDirection | None, + Field( + alias="sortDirection", + description="Optional turn pagination direction; defaults to descending.", + ), + ] = None + + +class ThreadSettings(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + active_permission_profile: Annotated[ + ActivePermissionProfile | None, Field(alias="activePermissionProfile") + ] = None + approval_policy: Annotated[AskForApproval, Field(alias="approvalPolicy")] + approvals_reviewer: Annotated[ApprovalsReviewer, Field(alias="approvalsReviewer")] + collaboration_mode: Annotated[CollaborationMode, Field(alias="collaborationMode")] + cwd: AbsolutePathBuf + effort: ReasoningEffort | None = None + model: str + model_provider: Annotated[str, Field(alias="modelProvider")] + personality: Personality | None = None + sandbox_policy: Annotated[SandboxPolicy, Field(alias="sandboxPolicy")] + service_tier: Annotated[str | None, Field(alias="serviceTier")] = None + summary: ReasoningSummary | None = None + + +class ThreadSettingsUpdatedNotification(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + thread_id: Annotated[str, Field(alias="threadId")] + thread_settings: Annotated[ThreadSettings, Field(alias="threadSettings")] + + class ThreadStartParams(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -6648,6 +6914,7 @@ class TurnStartParams(BaseModel): description="Override where approval requests are routed for review on this turn and subsequent turns.", ), ] = None + client_user_message_id: Annotated[str | None, Field(alias="clientUserMessageId")] = None cwd: Annotated[ str | None, Field(description="Override the working directory for this turn and subsequent turns."), @@ -6696,6 +6963,7 @@ class TurnSteerParams(BaseModel): model_config = ConfigDict( populate_by_name=True, ) + client_user_message_id: Annotated[str | None, Field(alias="clientUserMessageId")] = None expected_turn_id: Annotated[ str, Field( @@ -6803,6 +7071,15 @@ class ThreadForkRequest(BaseModel): params: ThreadForkParams +class ThreadGoalSetRequest(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + id: RequestId + method: Annotated[Literal["thread/goal/set"], Field(title="Thread/goal/setRequestMethod")] + params: ThreadGoalSetParams + + class ThreadListRequest(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -6891,6 +7168,41 @@ class ConfigValueWriteRequest(BaseModel): params: ConfigValueWriteParams +class Config(BaseModel): + model_config = ConfigDict( + extra="allow", + populate_by_name=True, + ) + analytics: AnalyticsConfig | None = None + approval_policy: AskForApproval | None = None + approvals_reviewer: Annotated[ + ApprovalsReviewer | None, + Field( + description="[UNSTABLE] Optional default for where approval requests are routed for review." + ), + ] = None + compact_prompt: str | None = None + desktop: dict[str, Any] | None = None + developer_instructions: str | None = None + forced_chatgpt_workspace_id: ForcedChatgptWorkspaceIds | None = None + forced_login_method: ForcedLoginMethod | None = None + instructions: str | None = None + model: str | None = None + model_auto_compact_token_limit: int | None = None + model_auto_compact_token_limit_scope: AutoCompactTokenLimitScope | None = None + model_context_window: int | None = None + model_provider: str | None = None + model_reasoning_effort: ReasoningEffort | None = None + model_reasoning_summary: ReasoningSummary | None = None + model_verbosity: Verbosity | None = None + review_model: str | None = None + sandbox_mode: SandboxMode | None = None + sandbox_workspace_write: SandboxWorkspaceWrite | None = None + service_tier: str | None = None + tools: ToolsV2 | None = None + web_search: WebSearchMode | None = None + + class ConfigBatchWriteParams(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -6913,6 +7225,15 @@ class ConfigBatchWriteParams(BaseModel): ] = None +class ConfigReadResponse(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + config: Config + layers: list[ConfigLayer] | None = None + origins: dict[str, ConfigLayerMetadata] + + class ConfigWriteResponse(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -7115,29 +7436,6 @@ class PluginSummary(BaseModel): source: PluginSource -class ProfileV2(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - approval_policy: AskForApproval | None = None - approvals_reviewer: Annotated[ - ApprovalsReviewer | None, - Field( - description="[UNSTABLE] Optional profile-level override for where approval requests are routed for review. If omitted, the enclosing config default is used." - ), - ] = None - chatgpt_base_url: str | None = None - model: str | None = None - model_provider: str | None = None - model_reasoning_effort: ReasoningEffort | None = None - model_reasoning_summary: ReasoningSummary | None = None - model_verbosity: Verbosity | None = None - service_tier: str | None = None - tools: ToolsV2 | None = None - web_search: WebSearchMode | None = None - - class RequestPermissionProfile(BaseModel): model_config = ConfigDict( extra="forbid", @@ -7229,6 +7527,16 @@ class ThreadGoalUpdatedServerNotification(BaseModel): params: ThreadGoalUpdatedNotification +class ThreadSettingsUpdatedServerNotification(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + method: Annotated[ + Literal["thread/settings/updated"], Field(title="Thread/settings/updatedNotificationMethod") + ] + params: ThreadSettingsUpdatedNotification + + class ThreadTokenUsageUpdatedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -7393,6 +7701,15 @@ class TurnStartedNotification(BaseModel): turn: Turn +class TurnsPage(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + backwards_cursor: Annotated[str | None, Field(alias="backwardsCursor")] = None + data: list[Turn] + next_cursor: Annotated[str | None, Field(alias="nextCursor")] = None + + class PluginShareSaveRequest(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -7411,51 +7728,6 @@ class ConfigBatchWriteRequest(BaseModel): params: ConfigBatchWriteParams -class Config(BaseModel): - model_config = ConfigDict( - extra="allow", - populate_by_name=True, - ) - analytics: AnalyticsConfig | None = None - approval_policy: AskForApproval | None = None - approvals_reviewer: Annotated[ - ApprovalsReviewer | None, - Field( - description="[UNSTABLE] Optional default for where approval requests are routed for review." - ), - ] = None - compact_prompt: str | None = None - desktop: dict[str, Any] | None = None - developer_instructions: str | None = None - forced_chatgpt_workspace_id: ForcedChatgptWorkspaceIds | None = None - forced_login_method: ForcedLoginMethod | None = None - instructions: str | None = None - model: str | None = None - model_auto_compact_token_limit: int | None = None - model_context_window: int | None = None - model_provider: str | None = None - model_reasoning_effort: ReasoningEffort | None = None - model_reasoning_summary: ReasoningSummary | None = None - model_verbosity: Verbosity | None = None - profile: str | None = None - profiles: dict[str, ProfileV2] | None = {} - review_model: str | None = None - sandbox_mode: SandboxMode | None = None - sandbox_workspace_write: SandboxWorkspaceWrite | None = None - service_tier: str | None = None - tools: ToolsV2 | None = None - web_search: WebSearchMode | None = None - - -class ConfigReadResponse(BaseModel): - model_config = ConfigDict( - populate_by_name=True, - ) - config: Config - layers: list[ConfigLayer] | None = None - origins: dict[str, ConfigLayerMetadata] - - class ExternalAgentConfigDetectResponse(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -7892,6 +8164,14 @@ class ThreadRollbackResponse(BaseModel): ] +class ThreadSearchResult(BaseModel): + model_config = ConfigDict( + populate_by_name=True, + ) + snippet: str + thread: Thread + + class ThreadStartResponse(BaseModel): model_config = ConfigDict( populate_by_name=True, @@ -7960,6 +8240,9 @@ class ClientRequest( | ThreadArchiveRequest | ThreadUnsubscribeRequest | ThreadNameSetRequest + | ThreadGoalSetRequest + | ThreadGoalGetRequest + | ThreadGoalClearRequest | ThreadMetadataUpdateRequest | ThreadUnarchiveRequest | ThreadCompactStartRequest @@ -7971,6 +8254,7 @@ class ClientRequest( | ThreadReadRequest | ThreadInjectItemsRequest | SkillsListRequest + | SkillsExtraRootsSetRequest | HooksListRequest | MarketplaceAddRequest | MarketplaceRemoveRequest @@ -8004,6 +8288,7 @@ class ClientRequest( | ModelListRequest | ModelProviderCapabilitiesReadRequest | ExperimentalFeatureListRequest + | PermissionProfileListRequest | ExperimentalFeatureEnablementSetRequest | McpServerOauthLoginRequest | ConfigMcpServerReloadRequest @@ -8043,6 +8328,9 @@ class ClientRequest( | ThreadArchiveRequest | ThreadUnsubscribeRequest | ThreadNameSetRequest + | ThreadGoalSetRequest + | ThreadGoalGetRequest + | ThreadGoalClearRequest | ThreadMetadataUpdateRequest | ThreadUnarchiveRequest | ThreadCompactStartRequest @@ -8054,6 +8342,7 @@ class ClientRequest( | ThreadReadRequest | ThreadInjectItemsRequest | SkillsListRequest + | SkillsExtraRootsSetRequest | HooksListRequest | MarketplaceAddRequest | MarketplaceRemoveRequest @@ -8087,6 +8376,7 @@ class ClientRequest( | ModelListRequest | ModelProviderCapabilitiesReadRequest | ExperimentalFeatureListRequest + | PermissionProfileListRequest | ExperimentalFeatureEnablementSetRequest | McpServerOauthLoginRequest | ConfigMcpServerReloadRequest @@ -8158,6 +8448,7 @@ class ServerNotification( | ThreadNameUpdatedServerNotification | ThreadGoalUpdatedServerNotification | ThreadGoalClearedServerNotification + | ThreadSettingsUpdatedServerNotification | ThreadTokenUsageUpdatedServerNotification | TurnStartedServerNotification | HookStartedServerNotification @@ -8227,6 +8518,7 @@ class ServerNotification( | ThreadNameUpdatedServerNotification | ThreadGoalUpdatedServerNotification | ThreadGoalClearedServerNotification + | ThreadSettingsUpdatedServerNotification | ThreadTokenUsageUpdatedServerNotification | TurnStartedServerNotification | HookStartedServerNotification diff --git a/sdk/python/tests/test_artifact_workflow_and_binaries.py b/sdk/python/tests/test_artifact_workflow_and_binaries.py index a8dda48854c..5a8f1275d6b 100644 --- a/sdk/python/tests/test_artifact_workflow_and_binaries.py +++ b/sdk/python/tests/test_artifact_workflow_and_binaries.py @@ -265,8 +265,9 @@ def test_schema_normalization_only_flattens_string_literal_oneofs( "AuthMode", "InputModality", "ExperimentalFeatureStage", - "ProcessOutputStream", + "AutoCompactTokenLimitScope", "CommandExecOutputStream", + "ProcessOutputStream", ] @@ -357,10 +358,10 @@ def test_source_sdk_template_pins_published_runtime() -> None: "dependencies": pyproject["project"]["dependencies"], } == { "sdk_template_version": "0.0.0-dev", - "runtime_pin": "0.132.0", + "runtime_pin": "0.136.0", "dependencies": [ "pydantic>=2.12", - "openai-codex-cli-bin==0.132.0", + "openai-codex-cli-bin==0.136.0", ], } @@ -435,7 +436,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.132.0", + "runtime_pin": "0.136.0", "normalized_release_version": "0.116.0a1", "release_tag": "rust-v0.116.0-alpha.1", } @@ -594,11 +595,11 @@ def test_stage_runtime_release_can_pin_wheel_platform_tag(tmp_path: Path) -> Non tmp_path / "runtime-stage", "0.116.0a1", package_archive, - platform_tag="musllinux_1_1_x86_64", + platform_tag="manylinux_2_17_x86_64", ) pyproject = (staged / "pyproject.toml").read_text() - assert 'platform-tag = "musllinux_1_1_x86_64"' in pyproject + assert 'platform-tag = "manylinux_2_17_x86_64"' in pyproject def test_stage_runtime_release_rejects_incomplete_package_layout(tmp_path: Path) -> None: @@ -650,7 +651,7 @@ def test_stage_sdk_release_preserves_reviewed_runtime_pin(tmp_path: Path) -> Non "version": "0.1.0b1", "dependencies": [ "pydantic>=2.12", - "openai-codex-cli-bin==0.132.0", + "openai-codex-cli-bin==0.136.0", ], } assert ( @@ -687,7 +688,7 @@ def test_sdk_beta_release_can_pin_stable_runtime(tmp_path: Path) -> None: ) runtime_stage = script.stage_python_runtime_package( tmp_path / "runtime-stage", - "0.132.0", + "0.136.0", package_archive, ) @@ -700,10 +701,10 @@ def test_sdk_beta_release_can_pin_stable_runtime(tmp_path: Path) -> None: "sdk_dependencies": sdk_pyproject["project"]["dependencies"], } == { "sdk_version": "0.1.0b1", - "runtime_version": "0.132.0", + "runtime_version": "0.136.0", "sdk_dependencies": [ "pydantic>=2.12", - "openai-codex-cli-bin==0.132.0", + "openai-codex-cli-bin==0.136.0", ], } @@ -762,7 +763,7 @@ def test_stage_runtime_stages_package_without_type_generation(tmp_path: Path) -> "--codex-version", "rust-v0.116.0-alpha.1", "--platform-tag", - "musllinux_1_1_x86_64", + "manylinux_2_17_x86_64", ] ) @@ -793,7 +794,7 @@ def fake_current_sdk_version() -> str: script.run_command(args, ops) - assert calls == ["stage_runtime:0.116.0a1:musllinux_1_1_x86_64:codex-package.tar.gz"] + assert calls == ["stage_runtime:0.116.0a1:manylinux_2_17_x86_64:codex-package.tar.gz"] def test_default_runtime_is_resolved_from_installed_runtime_package( diff --git a/sdk/python/tests/test_contract_generation.py b/sdk/python/tests/test_contract_generation.py index 2c95d06a3e7..a6d3d2fdc45 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.132.0" + assert importlib.metadata.version("openai-codex-cli-bin") == "0.136.0" 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 6d9e40e37a0..9dabd34d715 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-05-20T21:00:00Z" +openai-codex-cli-bin = "2026-06-01T20:00:00Z" [[package]] name = "annotated-types" @@ -299,7 +299,7 @@ dev = [ [package.metadata] requires-dist = [ { name = "datamodel-code-generator", marker = "extra == 'dev'", specifier = "==0.31.2" }, - { name = "openai-codex-cli-bin", specifier = "==0.132.0" }, + { name = "openai-codex-cli-bin", specifier = "==0.136.0" }, { name = "pydantic", specifier = ">=2.12" }, { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0" }, { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.15.8" }, @@ -308,15 +308,15 @@ provides-extras = ["dev"] [[package]] name = "openai-codex-cli-bin" -version = "0.132.0" +version = "0.136.0" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/be/a1/b92b7a1b73a83785d2e1dcd0faecd1b7f886a38cf02a30abe1c35f42f0f7/openai_codex_cli_bin-0.132.0-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:1c22b51dbd679413f84f00b9d8fd4e5cf8a1c0d1c7cc8c42bcb3f9f1b33e2334", size = 89403211, upload-time = "2026-05-20T02:37:22.311Z" }, - { url = "https://files.pythonhosted.org/packages/5f/68/163272e582de55a7f460e2329281267908d75d0fbcbbbb2c6749a6329e6b/openai_codex_cli_bin-0.132.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:56217495e6635c8a5d96df820cc0da5f46cd9b6ec6f3a5f67f1607d69ef74256", size = 79058685, upload-time = "2026-05-20T02:37:27.165Z" }, - { url = "https://files.pythonhosted.org/packages/0b/18/a60c6b137e7cd3959cae16ba757f57ca5702979b0ea107a21f516ba15d98/openai_codex_cli_bin-0.132.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:09642e7578a3078bfccc82af4077b085d42b0022b529e4b5c645e0a0af3397a4", size = 78689038, upload-time = "2026-05-20T02:37:31.548Z" }, - { url = "https://files.pythonhosted.org/packages/f8/eb/1b184307a67c1006d59b61636bcfcea73a89aa95271f6516ed28dce554ca/openai_codex_cli_bin-0.132.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:85aec095f9d144d7a2d1aff39fce77b7240f42014580c35801ba74b9317aa5f7", size = 85528820, upload-time = "2026-05-20T02:37:36.559Z" }, - { url = "https://files.pythonhosted.org/packages/0e/e8/1b823a8bf7b96d1513905ad79b16a146d797f81a19a6bc350a2f95a16661/openai_codex_cli_bin-0.132.0-py3-none-win_amd64.whl", hash = "sha256:3cb5c90c55baa39bd5ddc890d2068d3e1322a57a54d1d0e623819009a205c7f5", size = 86916218, upload-time = "2026-05-20T02:37:41.886Z" }, - { url = "https://files.pythonhosted.org/packages/6b/e6/bb8634bd4f3adaea299c95d7b03105ac417e32dd6d8bc2af5dda141d6f28/openai_codex_cli_bin-0.132.0-py3-none-win_arm64.whl", hash = "sha256:74ef93d3deef7cb83c71d19fc667defe749cdab337ec331f59a23511561b6f6a", size = 79892931, upload-time = "2026-05-20T02:37:46.828Z" }, + { url = "https://files.pythonhosted.org/packages/45/2e/09764338fcb104ebcb1ebf2490d71ab4b8339b5d6f8bdce19480adad5a99/openai_codex_cli_bin-0.136.0-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:9ded24a9977221f67173f49b8c3ba3a944787b7323dbd664dd8e8ae1a5efc0aa", size = 94036262, upload-time = "2026-06-01T19:28:13.291Z" }, + { url = "https://files.pythonhosted.org/packages/44/46/10dea458f8ead97b6449a1c05b65883ffe28724204c05e6169439576ee48/openai_codex_cli_bin-0.136.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8d194688c1afe87bf85705528cbcbdb762cb378d8c58c64162402babbd795436", size = 83713829, upload-time = "2026-06-01T19:28:17.39Z" }, + { url = "https://files.pythonhosted.org/packages/7d/83/21402a805f3312196a4f4bef0b6a45d3dee301e3db3ddeee117b4b1e612b/openai_codex_cli_bin-0.136.0-py3-none-manylinux_2_17_aarch64.whl", hash = "sha256:bdbdfeeac5bb2e744bd810cb60c55313c280d0f6ff9e93699431bcfc2040c9c2", size = 82981863, upload-time = "2026-06-01T19:28:21.246Z" }, + { url = "https://files.pythonhosted.org/packages/33/79/1617e008381345391def39254404c0248a425739bd13c95d9fbe3e63d16f/openai_codex_cli_bin-0.136.0-py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:37b353435f354c6d1bcc32e3b83e40ef9d1ef7294c8adedd229fbaedc82a6f74", size = 90187224, upload-time = "2026-06-01T19:28:24.89Z" }, + { url = "https://files.pythonhosted.org/packages/f4/bc/a591d4464f999e0fab6abb5ba369463eee99a82e7c298e2cff257d80b849/openai_codex_cli_bin-0.136.0-py3-none-win_amd64.whl", hash = "sha256:c91ffbb1d903970e74b65958f7d1fa548fac8abdfe9b3a098f3da7f47dbb2575", size = 91137642, upload-time = "2026-06-01T19:28:28.512Z" }, + { url = "https://files.pythonhosted.org/packages/89/f3/e8ccd644e7a87a25229022088abf4d724d3d608fcda7123f9a11515409ca/openai_codex_cli_bin-0.136.0-py3-none-win_arm64.whl", hash = "sha256:9073f7283c47ad3e585e23598ebbef554e85d280cabb637b6cb9a078c5e7086a", size = 83623904, upload-time = "2026-06-01T19:28:32.734Z" }, ] [[package]]