Retire the personality feature flag and document deprecated settings (#45809)

## What changed

- Accept and ignore `features.personality` in user configuration, profiles, and managed requirements.
- Remove feature gating from `personality = "none"`, which strips the literal `# Personality` section when preparing model catalog instructions. Preserve explicit base instructions and existing thread instructions.
- Document deprecated personality fields in configuration, app-server schemas, and the Python SDK: `friendly` and `pragmatic` no longer select a style, and `supportsPersonality` is always `false`.

## Testing

Add regression coverage for ignored legacy flag values and managed requirements, personality opt-out behavior with the flag absent or set to either value, role overrides, and preservation of explicit base instructions, including empty strings.

GitOrigin-RevId: 4e12c66b42bfc59d6f151a5b3c28fadc6654ae99
This commit is contained in:
rhan-oai
2026-09-15 23:39:40 +00:00
committed by copyberry
parent 4d2807023a
commit 883af106b9
54 changed files with 389 additions and 264 deletions
+26
View File
@@ -40,6 +40,7 @@ from openai_codex.types import (
CancelLoginAccountStatus,
GetAccountResponse,
InitializeResponse,
Personality,
ThreadItem,
ThreadTokenUsage,
TurnError,
@@ -88,6 +89,27 @@ server's default behavior. This does not remove history from the model's
context. Both methods return a thread handle; use `thread.read(include_turns=True)`
to retrieve its history.
### Deprecated personality selection
`thread_start(...)`, `thread_resume(...)`, and the thread's `run(...)` and
`turn(...)` still accept `personality` for compatibility. The current app-server
accepts `Personality.friendly` and `Personality.pragmatic`, but they no longer
select a style; model instructions define the tone.
Python `None` or omitting the option leaves it unset. Explicit `Personality.none`
(wire value `"none"`) strips the literal `# Personality` section the next time
Codex prepares instructions from the model catalog, such as when starting a
thread or switching models. It does not change explicitly supplied base
instructions or rewrite an existing thread's instructions when resuming or
starting a turn. Either legacy value can replace a previous `Personality.none`
setting for future model instructions. The old `features.personality` flag is
ignored.
Models returned by `models(...)` still expose `supports_personality` for
compatibility. This field is deprecated and always `False` on the current
app-server; it describes selectable personality, not the separate
`Personality.none` opt-out.
## AsyncCodex (async parity)
```python
@@ -121,6 +143,9 @@ Properties/methods:
- `thread_unarchive(thread_id: str) -> Awaitable[AsyncThread]`
- `models(*, include_hidden: bool = False) -> Awaitable[ModelListResponse]`
The [deprecated personality selection](#deprecated-personality-selection)
notes also apply to the async methods and model results.
Async context manager:
```python
@@ -198,6 +223,7 @@ These options have the same behavior on sync and async `run(...)` and `turn(...)
| Option | Behavior |
| --- | --- |
| `personality: Personality \| None = None` | `Personality.friendly` and `Personality.pragmatic` are deprecated and no longer select a style. See [deprecated personality selection](#deprecated-personality-selection). |
| `service_tier: str | None = None` | Sets the thread's service tier for this and subsequent turns. |
| `turn_service_tier: str | None = None` | Overrides the tier for a newly started turn only. `None` inherits the thread setting; `"default"` selects standard speed. Does not change the thread default and is ignored when input joins an active turn. |
| `source: str | None = None` | Labels the caller that initiated a new turn, such as `"review_ui"`. This is metadata; it does not schedule work or grant authority. Ignored when input joins an active turn. |
+10 -1
View File
@@ -297,7 +297,11 @@ class Codex:
# END GENERATED: Codex.flat_methods
def models(self, *, include_hidden: bool = False) -> ModelListResponse:
"""List available models reported by Codex."""
"""List available models reported by Codex.
The deprecated ``Model.supports_personality`` field is always ``False``
on the current app-server.
"""
return self._client.model_list(include_hidden=include_hidden)
@@ -557,6 +561,11 @@ class AsyncCodex:
# END GENERATED: AsyncCodex.flat_methods
async def models(self, *, include_hidden: bool = False) -> ModelListResponse:
"""List available models reported by Codex.
The deprecated ``Model.supports_personality`` field is always ``False``
on the current app-server.
"""
await self._ensure_initialized()
return await self._client.model_list(include_hidden=include_hidden)
@@ -5834,7 +5834,12 @@ class ThreadResumeParams(BaseModel):
str | None, Field(description="Configuration overrides for the resumed thread, if any.")
] = None
model_provider: Annotated[str | None, Field(alias="modelProvider")] = None
personality: Personality | None = None
personality: Annotated[
Personality | None,
Field(
description="@deprecated `friendly` and `pragmatic` no longer select a style. Changing this does not rewrite the thread's existing instructions."
),
] = None
sandbox: SandboxMode | None = None
service_tier: Annotated[str | None, Field(alias="serviceTier")] = None
thread_id: Annotated[str, Field(alias="threadId")]
@@ -8521,7 +8526,13 @@ class Model(BaseModel):
supported_reasoning_efforts: Annotated[
list[ReasoningEffortOption], Field(alias="supportedReasoningEfforts")
]
supports_personality: Annotated[bool | None, Field(alias="supportsPersonality")] = False
supports_personality: Annotated[
bool | None,
Field(
alias="supportsPersonality",
description="@deprecated Always false; models no longer support personality selection.",
),
] = False
upgrade: str | None = None
upgrade_info: Annotated[ModelUpgradeInfo | None, Field(alias="upgradeInfo")] = None
@@ -9971,7 +9982,12 @@ class ThreadSettings(BaseModel):
effort: ReasoningEffort | None = None
model: str
model_provider: Annotated[str, Field(alias="modelProvider")]
personality: Personality | None = None
personality: Annotated[
Personality | None,
Field(
description="@deprecated Reports the saved setting; `friendly` and `pragmatic` no longer select a style."
),
] = None
sandbox_policy: Annotated[SandboxPolicy, Field(alias="sandboxPolicy")]
service_tier: Annotated[str | None, Field(alias="serviceTier")] = None
summary: ReasoningSummary | None = None
@@ -10004,7 +10020,10 @@ class ThreadStartParams(BaseModel):
ephemeral: bool | None = None
model: str | None = None
model_provider: Annotated[str | None, Field(alias="modelProvider")] = None
personality: Personality | None = None
personality: Annotated[
Personality | None,
Field(description="@deprecated `friendly` and `pragmatic` no longer select a style."),
] = None
sandbox: SandboxMode | None = None
service_name: Annotated[str | None, Field(alias="serviceName")] = None
service_tier: Annotated[str | None, Field(alias="serviceTier")] = None
@@ -10424,7 +10443,7 @@ class ConfigBatchWriteParams(BaseModel):
bool | None,
Field(
alias="reloadUserConfig",
description="When true, hot-reload updated runtime settings into loaded threads after writing. Session-static model, reasoning-effort, Plan-mode reasoning-effort, service-tier, and personality defaults are not reloaded.",
description="When true, hot-reload updated runtime settings into loaded threads after writing. Session-static model, reasoning-effort, Plan-mode reasoning-effort, and service-tier defaults are not reloaded. The deprecated personality setting is also not reloaded.",
),
] = None
@@ -12141,7 +12160,9 @@ class TurnStartParams(BaseModel):
] = None
personality: Annotated[
Personality | None,
Field(description="Override the personality for this turn and subsequent turns."),
Field(
description="@deprecated `friendly` and `pragmatic` no longer select a style. Changing this does not rewrite the thread's existing instructions."
),
] = None
sandbox_policy: Annotated[
SandboxPolicy | None,