Fix deployment and load latest Codex models
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
"""Runs tasks through the OpenAI Codex Python SDK and yields progress events."""
|
||||
|
||||
import asyncio
|
||||
import shutil
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, AsyncIterator
|
||||
|
||||
from openai_codex import ApprovalMode, AsyncCodex, CodexConfig, Sandbox
|
||||
from openai_codex.types import ReasoningEffort, ThreadItem, ThreadTokenUsage, Turn
|
||||
from openai_codex.types import ThreadItem, ThreadTokenUsage, Turn
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
from . import config
|
||||
|
||||
@@ -73,6 +75,32 @@ class ModelOptions:
|
||||
return tuple(efforts)
|
||||
|
||||
|
||||
class _ModelEffort(BaseModel):
|
||||
model_config = ConfigDict(populate_by_name=True, extra="ignore")
|
||||
|
||||
reasoning_effort: str = Field(alias="reasoningEffort")
|
||||
|
||||
|
||||
class _Model(BaseModel):
|
||||
model_config = ConfigDict(populate_by_name=True, extra="ignore")
|
||||
|
||||
id: str
|
||||
model: str
|
||||
display_name: str = Field(alias="displayName")
|
||||
hidden: bool = False
|
||||
is_default: bool = Field(default=False, alias="isDefault")
|
||||
supported_reasoning_efforts: list[_ModelEffort] = Field(
|
||||
default_factory=list,
|
||||
alias="supportedReasoningEfforts",
|
||||
)
|
||||
|
||||
|
||||
class _ModelListResponse(BaseModel):
|
||||
model_config = ConfigDict(populate_by_name=True, extra="ignore")
|
||||
|
||||
data: list[_Model]
|
||||
|
||||
|
||||
def _shorten(text: str, limit: int = TOOL_INPUT_PREVIEW_LEN) -> str:
|
||||
text = " ".join(text.split())
|
||||
if len(text) > limit:
|
||||
@@ -193,24 +221,15 @@ def _approval_mode() -> ApprovalMode:
|
||||
) from exc
|
||||
|
||||
|
||||
def _effort(value: str | None) -> ReasoningEffort | None:
|
||||
if value is None:
|
||||
return None
|
||||
try:
|
||||
return ReasoningEffort(value)
|
||||
except ValueError as exc:
|
||||
valid = ", ".join(effort.value for effort in ReasoningEffort)
|
||||
raise RuntimeError(f"Unsupported reasoning effort={value!r}; use one of: {valid}") from exc
|
||||
|
||||
|
||||
def _codex_config() -> CodexConfig:
|
||||
return CodexConfig(codex_bin=config.CODEX_BIN)
|
||||
return CodexConfig(codex_bin=config.CODEX_BIN or shutil.which("codex"))
|
||||
|
||||
|
||||
def _reasoning_efforts(raw_options: Any) -> tuple[str, ...]:
|
||||
efforts: list[str] = []
|
||||
for option in raw_options or []:
|
||||
value = getattr(getattr(option, "reasoning_effort", None), "value", None)
|
||||
raw_value = getattr(option, "reasoning_effort", None)
|
||||
value = getattr(raw_value, "value", raw_value)
|
||||
if value and value not in efforts:
|
||||
efforts.append(value)
|
||||
return tuple(efforts)
|
||||
@@ -223,7 +242,14 @@ async def list_model_options() -> ModelOptions:
|
||||
if config.OPENAI_API_KEY:
|
||||
await codex.login_api_key(config.OPENAI_API_KEY)
|
||||
|
||||
response = await codex.models()
|
||||
# The app-server catalog evolves faster than the beta Python SDK's
|
||||
# generated enums. Parse this one response permissively so newly
|
||||
# introduced reasoning levels appear without an SDK release.
|
||||
response = await codex._client.request(
|
||||
"model/list",
|
||||
{"includeHidden": False},
|
||||
response_model=_ModelListResponse,
|
||||
)
|
||||
except Exception as exc:
|
||||
return ModelOptions(models=(), error=str(exc))
|
||||
|
||||
@@ -318,7 +344,6 @@ async def run_task(
|
||||
prompt,
|
||||
approval_mode=_approval_mode(),
|
||||
cwd=config.WORK_DIR,
|
||||
effort=_effort(effort),
|
||||
model=selected_model,
|
||||
sandbox=_sandbox(),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user