Add file-backed personality support and listing

This commit is contained in:
Eric Traut
2026-03-30 14:43:42 -06:00
parent ae057e0bb9
commit 8e00fec700
61 changed files with 1741 additions and 366 deletions

View File

@@ -16,7 +16,6 @@ from .errors import (
)
from .generated.v2_all import (
AskForApproval,
Personality,
PlanType,
ReasoningEffort,
ReasoningSummary,
@@ -36,6 +35,7 @@ from .generated.v2_all import (
TurnStatus,
TurnSteerParams,
)
from .personality import Personality
from .models import InitializeResponse
from .api import (
AsyncCodex,

View File

@@ -10,7 +10,6 @@ from .generated.v2_all import (
ApprovalsReviewer,
AskForApproval,
ModelListResponse,
Personality,
ReasoningEffort,
ReasoningSummary,
SandboxMode,
@@ -34,6 +33,9 @@ from .generated.v2_all import (
TurnSteerResponse,
)
from .models import InitializeResponse, JsonObject, Notification, ServerInfo
from .personality import Personality
from .personality import PersonalityLike
from .personality import personality_value
from ._inputs import (
ImageInput,
Input,
@@ -142,7 +144,7 @@ class Codex:
ephemeral: bool | None = None,
model: str | None = None,
model_provider: str | None = None,
personality: Personality | None = None,
personality: PersonalityLike | None = None,
sandbox: SandboxMode | None = None,
service_name: str | None = None,
service_tier: ServiceTier | None = None,
@@ -157,7 +159,7 @@ class Codex:
ephemeral=ephemeral,
model=model,
model_provider=model_provider,
personality=personality,
personality=personality_value(personality),
sandbox=sandbox,
service_name=service_name,
service_tier=service_tier,
@@ -201,7 +203,7 @@ class Codex:
developer_instructions: str | None = None,
model: str | None = None,
model_provider: str | None = None,
personality: Personality | None = None,
personality: PersonalityLike | None = None,
sandbox: SandboxMode | None = None,
service_tier: ServiceTier | None = None,
) -> Thread:
@@ -215,7 +217,7 @@ class Codex:
developer_instructions=developer_instructions,
model=model,
model_provider=model_provider,
personality=personality,
personality=personality_value(personality),
sandbox=sandbox,
service_tier=service_tier,
)
@@ -332,7 +334,7 @@ class AsyncCodex:
ephemeral: bool | None = None,
model: str | None = None,
model_provider: str | None = None,
personality: Personality | None = None,
personality: PersonalityLike | None = None,
sandbox: SandboxMode | None = None,
service_name: str | None = None,
service_tier: ServiceTier | None = None,
@@ -348,7 +350,7 @@ class AsyncCodex:
ephemeral=ephemeral,
model=model,
model_provider=model_provider,
personality=personality,
personality=personality_value(personality),
sandbox=sandbox,
service_name=service_name,
service_tier=service_tier,
@@ -393,7 +395,7 @@ class AsyncCodex:
developer_instructions: str | None = None,
model: str | None = None,
model_provider: str | None = None,
personality: Personality | None = None,
personality: PersonalityLike | None = None,
sandbox: SandboxMode | None = None,
service_tier: ServiceTier | None = None,
) -> AsyncThread:
@@ -408,7 +410,7 @@ class AsyncCodex:
developer_instructions=developer_instructions,
model=model,
model_provider=model_provider,
personality=personality,
personality=personality_value(personality),
sandbox=sandbox,
service_tier=service_tier,
)
@@ -479,7 +481,7 @@ class Thread:
effort: ReasoningEffort | None = None,
model: str | None = None,
output_schema: JsonObject | None = None,
personality: Personality | None = None,
personality: PersonalityLike | None = None,
sandbox_policy: SandboxPolicy | None = None,
service_tier: ServiceTier | None = None,
summary: ReasoningSummary | None = None,
@@ -492,7 +494,7 @@ class Thread:
effort=effort,
model=model,
output_schema=output_schema,
personality=personality,
personality=personality_value(personality),
sandbox_policy=sandbox_policy,
service_tier=service_tier,
summary=summary,
@@ -514,7 +516,7 @@ class Thread:
effort: ReasoningEffort | None = None,
model: str | None = None,
output_schema: JsonObject | None = None,
personality: Personality | None = None,
personality: PersonalityLike | None = None,
sandbox_policy: SandboxPolicy | None = None,
service_tier: ServiceTier | None = None,
summary: ReasoningSummary | None = None,
@@ -529,7 +531,7 @@ class Thread:
effort=effort,
model=model,
output_schema=output_schema,
personality=personality,
personality=personality_value(personality),
sandbox_policy=sandbox_policy,
service_tier=service_tier,
summary=summary,
@@ -563,7 +565,7 @@ class AsyncThread:
effort: ReasoningEffort | None = None,
model: str | None = None,
output_schema: JsonObject | None = None,
personality: Personality | None = None,
personality: PersonalityLike | None = None,
sandbox_policy: SandboxPolicy | None = None,
service_tier: ServiceTier | None = None,
summary: ReasoningSummary | None = None,
@@ -576,7 +578,7 @@ class AsyncThread:
effort=effort,
model=model,
output_schema=output_schema,
personality=personality,
personality=personality_value(personality),
sandbox_policy=sandbox_policy,
service_tier=service_tier,
summary=summary,
@@ -598,7 +600,7 @@ class AsyncThread:
effort: ReasoningEffort | None = None,
model: str | None = None,
output_schema: JsonObject | None = None,
personality: Personality | None = None,
personality: PersonalityLike | None = None,
sandbox_policy: SandboxPolicy | None = None,
service_tier: ServiceTier | None = None,
summary: ReasoningSummary | None = None,
@@ -614,7 +616,7 @@ class AsyncThread:
effort=effort,
model=model,
output_schema=output_schema,
personality=personality,
personality=personality_value(personality),
sandbox_policy=sandbox_policy,
service_tier=service_tier,
summary=summary,

View File

@@ -1358,6 +1358,16 @@ class ChatgptLoginAccountParams(BaseModel):
]
class ChatgptDeviceCodeLoginAccountParams(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
)
type: Annotated[
Literal["chatgptDeviceCode"],
Field(title="ChatgptDeviceCodev2::LoginAccountParamsType"),
]
class ChatgptAuthTokensLoginAccountParams(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
@@ -1393,6 +1403,7 @@ class LoginAccountParams(
RootModel[
ApiKeyLoginAccountParams
| ChatgptLoginAccountParams
| ChatgptDeviceCodeLoginAccountParams
| ChatgptAuthTokensLoginAccountParams
]
):
@@ -1402,6 +1413,7 @@ class LoginAccountParams(
root: Annotated[
ApiKeyLoginAccountParams
| ChatgptLoginAccountParams
| ChatgptDeviceCodeLoginAccountParams
| ChatgptAuthTokensLoginAccountParams,
Field(title="LoginAccountParams"),
]
@@ -1433,6 +1445,31 @@ class ChatgptLoginAccountResponse(BaseModel):
]
class ChatgptDeviceCodeLoginAccountResponse(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
)
login_id: Annotated[str, Field(alias="loginId")]
type: Annotated[
Literal["chatgptDeviceCode"],
Field(title="ChatgptDeviceCodev2::LoginAccountResponseType"),
]
user_code: Annotated[
str,
Field(
alias="userCode",
description="One-time code the user must enter after signing in.",
),
]
verification_url: Annotated[
str,
Field(
alias="verificationUrl",
description="URL the client should open in a browser to complete device code authorization.",
),
]
class ChatgptAuthTokensLoginAccountResponse(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
@@ -1447,6 +1484,7 @@ class LoginAccountResponse(
RootModel[
ApiKeyLoginAccountResponse
| ChatgptLoginAccountResponse
| ChatgptDeviceCodeLoginAccountResponse
| ChatgptAuthTokensLoginAccountResponse
]
):
@@ -1456,6 +1494,7 @@ class LoginAccountResponse(
root: Annotated[
ApiKeyLoginAccountResponse
| ChatgptLoginAccountResponse
| ChatgptDeviceCodeLoginAccountResponse
| ChatgptAuthTokensLoginAccountResponse,
Field(title="LoginAccountResponse"),
]
@@ -1658,28 +1697,74 @@ class NetworkAccess(Enum):
enabled = "enabled"
class NetworkDomainPermission(Enum):
allow = "allow"
deny = "deny"
class NetworkRequirements(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
)
allow_local_binding: Annotated[bool | None, Field(alias="allowLocalBinding")] = None
allow_unix_sockets: Annotated[list[str] | None, Field(alias="allowUnixSockets")] = (
None
)
allow_unix_sockets: Annotated[
list[str] | None,
Field(
alias="allowUnixSockets",
description="Legacy compatibility view derived from `unix_sockets`.",
),
] = None
allow_upstream_proxy: Annotated[bool | None, Field(alias="allowUpstreamProxy")] = (
None
)
allowed_domains: Annotated[list[str] | None, Field(alias="allowedDomains")] = None
allowed_domains: Annotated[
list[str] | None,
Field(
alias="allowedDomains",
description="Legacy compatibility view derived from `domains`.",
),
] = None
dangerously_allow_all_unix_sockets: Annotated[
bool | None, Field(alias="dangerouslyAllowAllUnixSockets")
] = None
dangerously_allow_non_loopback_proxy: Annotated[
bool | None, Field(alias="dangerouslyAllowNonLoopbackProxy")
] = None
denied_domains: Annotated[list[str] | None, Field(alias="deniedDomains")] = None
denied_domains: Annotated[
list[str] | None,
Field(
alias="deniedDomains",
description="Legacy compatibility view derived from `domains`.",
),
] = None
domains: Annotated[
dict[str, Any] | None,
Field(
description="Canonical network permission map for `experimental_network`."
),
] = None
enabled: bool | None = None
http_port: Annotated[int | None, Field(alias="httpPort", ge=0)] = None
managed_allowed_domains_only: Annotated[
bool | None,
Field(
alias="managedAllowedDomainsOnly",
description="When true, only managed allowlist entries are respected while managed network enforcement is active.",
),
] = None
socks_port: Annotated[int | None, Field(alias="socksPort", ge=0)] = None
unix_sockets: Annotated[
dict[str, Any] | None,
Field(
alias="unixSockets",
description="Canonical unix socket permission map for `experimental_network`.",
),
] = None
class NetworkUnixSocketPermission(Enum):
allow = "allow"
none = "none"
class NonSteerableTurnKind(Enum):
@@ -1725,10 +1810,17 @@ class PatchChangeKind(
root: AddPatchChangeKind | DeletePatchChangeKind | UpdatePatchChangeKind
class Personality(Enum):
none = "none"
friendly = "friendly"
pragmatic = "pragmatic"
class PersonalitiesListParams(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
)
cwds: list[AbsolutePathBuf] | None = None
class PersonalityScope(Enum):
builtin = "builtin"
user = "user"
repo = "repo"
class PlanDeltaNotification(BaseModel):
@@ -3265,7 +3357,7 @@ class ThreadResumeParams(BaseModel):
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: str | None = None
sandbox: SandboxMode | None = None
service_tier: Annotated[ServiceTier | None, Field(alias="serviceTier")] = None
thread_id: Annotated[str, Field(alias="threadId")]
@@ -3362,7 +3454,7 @@ 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: str | None = None
sandbox: SandboxMode | None = None
service_name: Annotated[str | None, Field(alias="serviceName")] = None
service_tier: Annotated[ServiceTier | None, Field(alias="serviceTier")] = None
@@ -3943,6 +4035,17 @@ class SkillsListRequest(BaseModel):
params: SkillsListParams
class PersonalitiesListRequest(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
)
id: RequestId
method: Annotated[
Literal["personalities/list"], Field(title="Personalities/listRequestMethod")
]
params: PersonalitiesListParams
class PluginListRequest(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
@@ -4873,6 +4976,16 @@ class OverriddenMetadata(BaseModel):
overriding_layer: Annotated[ConfigLayerMetadata, Field(alias="overridingLayer")]
class PersonalityMetadata(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
)
description: str
is_built_in: Annotated[bool, Field(alias="isBuiltIn")]
name: str
scope: PersonalityScope
class PluginDetail(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
@@ -5551,7 +5664,7 @@ class TurnStartParams(BaseModel):
),
] = None
personality: Annotated[
Personality | None,
str | None,
Field(
description="Override the personality for this turn and subsequent turns."
),
@@ -5861,6 +5974,21 @@ class ListMcpServerStatusResponse(BaseModel):
] = None
class PersonalitiesListEntry(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
)
cwd: str
personalities: list[PersonalityMetadata]
class PersonalitiesListResponse(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
)
data: list[PersonalitiesListEntry]
class PluginListResponse(BaseModel):
model_config = ConfigDict(
populate_by_name=True,
@@ -6152,6 +6280,7 @@ class ClientRequest(
| ThreadLoadedListRequest
| ThreadReadRequest
| SkillsListRequest
| PersonalitiesListRequest
| PluginListRequest
| PluginReadRequest
| AppListRequest
@@ -6217,6 +6346,7 @@ class ClientRequest(
| ThreadLoadedListRequest
| ThreadReadRequest
| SkillsListRequest
| PersonalitiesListRequest
| PluginListRequest
| PluginReadRequest
| AppListRequest

View File

@@ -0,0 +1,18 @@
from __future__ import annotations
from enum import Enum
class Personality(str, Enum):
NONE = "none"
FRIENDLY = "friendly"
PRAGMATIC = "pragmatic"
PersonalityLike = str | Personality
def personality_value(personality: PersonalityLike | None) -> str | None:
if isinstance(personality, Personality):
return personality.value
return personality