Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
687e974
fix: handle cancelled single function tools as tool failures (#2762)
elainegan-openai Mar 25, 2026
9088496
fix: optionize initialized notification tolerance (#2765)
elainegan-openai Mar 25, 2026
881f402
fix: harden example auto-runs against PATH and port conflicts (#2770)
seratch Mar 25, 2026
0a5b8c9
Release 0.13.1 (#2768)
github-actions[bot] Mar 25, 2026
13f4a74
docs: update pages to add any-llm adapter (#2715)
seratch Mar 25, 2026
7dc7fa2
docs: update translated document pages (#2771)
github-actions[bot] Mar 25, 2026
abd5cef
fix: pin liteLLM upper bound to 1.82.6 to mitigate supply chain attac…
gn00295120 Mar 25, 2026
8fdb45d
fix: update default reasoning effort for newer models (#2773)
seratch Mar 25, 2026
67fa4d8
chore: make sync
seratch Mar 26, 2026
9a96d9e
fix: #2778 keep LiteLLM reasoning_effort portable across providers (#…
seratch Mar 26, 2026
c2f6690
fix: #2776 keep private tool metadata out of persisted session items …
seratch Mar 26, 2026
570b114
docs: update readme
seratch Mar 26, 2026
c52d25f
feat: #2785 add external_web_access to WebSearchTool (#2786)
ymuichiro Mar 26, 2026
7fea1a5
fix: improve a flaky test for realtime module (#2787)
seratch Mar 26, 2026
c5e1321
fix: #2783 depend on griffelib directly for docstring parsing (#2791)
seratch Mar 26, 2026
dddbce1
Release 0.13.2 (#2774)
github-actions[bot] Mar 26, 2026
149f5ce
docs: add non-OpenAI provider code example (#2792)
Muttaqi110 Mar 27, 2026
a4db3e5
docs: update translated document pages (#2793)
github-actions[bot] Mar 27, 2026
ce0d792
docs: tweak for #2792 changes
seratch Mar 27, 2026
9ed6dad
chore: add Codex Stop hook for targeted Ruff tidy (#2795)
seratch Mar 27, 2026
a7b4851
fix: #2797 accept raw image_url content parts on chat completions inp…
seratch Mar 28, 2026
9f5575a
fix: #2798 avoid stale hydrated input ids in server conversation trac…
seratch Mar 28, 2026
d86c2e2
Release 0.13.3 (#2801)
github-actions[bot] Mar 31, 2026
5e0e6d2
fix: map extensions changes to the feature:extensions label (#2814)
seratch Mar 31, 2026
40aada1
fix: #2806 sanitize AnyLLM responses replay input before validation (…
seratch Mar 31, 2026
051c2ea
Release 0.13.4 (#2815)
github-actions[bot] Apr 1, 2026
976bcce
feat: #2807 support callable approval policies for local MCP servers …
seratch Apr 1, 2026
70939dc
chore(deps): bump openai/codex-action from 1.4 to 1.6 (#2819)
dependabot[bot] Apr 1, 2026
c940055
chore(deps): bump astral-sh/setup-uv from 7.3.1 to 8.0.0 (#2820)
dependabot[bot] Apr 1, 2026
f75a40e
docs: sync examples.md with current examples directory (#2827)
AbdullahBapra Apr 2, 2026
fe9e70f
fix: #2823 AnyLLM reasoning extraction for iterable vLLM/any-llm Reas…
ziqi-cn Apr 2, 2026
76f419f
docs: update translated document pages (#2828)
github-actions[bot] Apr 2, 2026
6a89f1b
fix: serialize SQLite session writes with shared file locks (#2843)
seratch Apr 4, 2026
7a3f6b7
feat: #2135 add public flush_traces API (#2844)
seratch Apr 4, 2026
b0ab25c
Release 0.13.5 (#2821)
github-actions[bot] Apr 6, 2026
e1d861c
docs: updates for #2844 changes (#2845)
seratch Apr 6, 2026
fa50899
docs: update translated document pages (#2847)
github-actions[bot] Apr 6, 2026
0386210
docs(tracing): add HoneyHive to tracing integrations list (#2851)
m1lestones Apr 7, 2026
aeb653e
docs: update translated document pages (#2853)
github-actions[bot] Apr 7, 2026
c06cd45
fix: harden SQLAlchemySession against transient SQLite locks (#2854)
seratch Apr 7, 2026
8a4c875
Merge remote-tracking branch 'upstream/main' into chore/wave4-upstrea…
ashsolei Apr 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .codex/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#:schema https://developers.openai.com/codex/config-schema.json

[features]
codex_hooks = true
15 changes: 15 additions & 0 deletions .codex/hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "uv run python \"$(git rev-parse --show-toplevel)/.codex/hooks/stop_repo_tidy.py\"",
"timeout": 20
}
]
}
]
}
}
222 changes: 222 additions & 0 deletions .codex/hooks/stop_repo_tidy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
#!/usr/bin/env python3

from __future__ import annotations

import hashlib
import json
import subprocess
import sys
import tempfile
from dataclasses import asdict, dataclass
from pathlib import Path

MAX_RUFF_FIX_FILES = 20
PYTHON_SUFFIXES = {".py", ".pyi"}


@dataclass
class HookState:
last_tidy_fingerprint: str | None = None


def write_stop_block(reason: str, system_message: str) -> None:
sys.stdout.write(
json.dumps(
{
"decision": "block",
"reason": reason,
"systemMessage": system_message,
}
)
)


def run_command(cwd: str, *args: str) -> subprocess.CompletedProcess[str]:
try:
return subprocess.run(
args,
cwd=cwd,
capture_output=True,
check=False,
text=True,
)
except FileNotFoundError as exc:
return subprocess.CompletedProcess(args, returncode=127, stdout="", stderr=str(exc))


def run_git(cwd: str, *args: str) -> subprocess.CompletedProcess[str]:
return run_command(cwd, "git", *args)


def git_root(cwd: str) -> str:
result = run_git(cwd, "rev-parse", "--show-toplevel")
if result.returncode != 0:
raise RuntimeError(result.stderr.strip() or "git root lookup failed")
return result.stdout.strip()


def parse_status_paths(repo_root: str) -> list[str]:
unstaged = run_git(repo_root, "diff", "--name-only", "--diff-filter=ACMR")
untracked = run_git(repo_root, "ls-files", "--others", "--exclude-standard")
if unstaged.returncode != 0 or untracked.returncode != 0:
return []

paths = {
line.strip()
for result in (unstaged, untracked)
for line in result.stdout.splitlines()
if line.strip()
}
return sorted(paths)


def untracked_paths(repo_root: str, paths: list[str]) -> set[str]:
if not paths:
return set()

result = run_git(repo_root, "ls-files", "--others", "--exclude-standard", "--", *paths)
if result.returncode != 0:
return set()

return {line.strip() for line in result.stdout.splitlines() if line.strip()}


def fingerprint_for_paths(repo_root: str, paths: list[str]) -> str | None:
if not paths:
return None

repo_root_path = Path(repo_root)
untracked = untracked_paths(repo_root, paths)
tracked_paths = [file_path for file_path in paths if file_path not in untracked]
diff_parts: list[str] = []

if tracked_paths:
diff = run_git(repo_root, "diff", "--no-ext-diff", "--binary", "--", *tracked_paths)
if diff.returncode == 0:
diff_parts.append(diff.stdout)

for file_path in sorted(untracked):
try:
digest = hashlib.sha256((repo_root_path / file_path).read_bytes()).hexdigest()
except OSError:
continue
diff_parts.append(f"untracked:{file_path}:{digest}")

if not diff_parts:
return None

return hashlib.sha256("\n".join(diff_parts).encode("utf-8")).hexdigest()


def state_dir() -> Path:
return Path(tempfile.gettempdir()) / "openai-agents-python-codex-hooks"


def state_path(session_id: str, repo_root: str) -> Path:
root_hash = hashlib.sha256(repo_root.encode("utf-8")).hexdigest()[:12]
safe_session_id = "".join(
ch if ch.isascii() and (ch.isalnum() or ch in "._-") else "_" for ch in session_id
)
return state_dir() / f"{safe_session_id}-{root_hash}.json"


def load_state(session_id: str, repo_root: str) -> HookState:
file_path = state_path(session_id, repo_root)
if not file_path.exists():
return HookState()

try:
payload = json.loads(file_path.read_text())
except (OSError, json.JSONDecodeError):
return HookState()

return HookState(last_tidy_fingerprint=payload.get("last_tidy_fingerprint"))


def save_state(session_id: str, repo_root: str, state: HookState) -> None:
file_path = state_path(session_id, repo_root)
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text(json.dumps(asdict(state), indent=2))


def lint_fix_paths(repo_root: str) -> list[str]:
return [
file_path
for file_path in parse_status_paths(repo_root)
if Path(file_path).suffix in PYTHON_SUFFIXES
]


def main() -> None:
try:
payload = json.loads(sys.stdin.read() or "null")
except json.JSONDecodeError:
return

if not isinstance(payload, dict):
return

session_id = payload.get("session_id")
cwd = payload.get("cwd")
if not isinstance(session_id, str) or not isinstance(cwd, str):
return

if payload.get("stop_hook_active"):
return

repo_root = git_root(cwd)
current_paths = lint_fix_paths(repo_root)
if not current_paths or len(current_paths) > MAX_RUFF_FIX_FILES:
return

state = load_state(session_id, repo_root)
current_fingerprint = fingerprint_for_paths(repo_root, current_paths)
if current_fingerprint is None or state.last_tidy_fingerprint == current_fingerprint:
return

format_result = run_command(repo_root, "uv", "run", "ruff", "format", "--", *current_paths)
check_result: subprocess.CompletedProcess[str] | None = None
if format_result.returncode == 0:
check_result = run_command(
repo_root,
"uv",
"run",
"ruff",
"check",
"--fix",
"--",
*current_paths,
)

if format_result.returncode != 0:
write_stop_block(
"`uv run ruff format -- ...` failed for the touched Python files. "
"Review the formatting step before wrapping up.",
"Repo hook: targeted Ruff format failed.",
)
return

if check_result and check_result.returncode != 0:
write_stop_block(
"`uv run ruff check --fix -- ...` failed for the touched Python files. "
"Review the lint output before wrapping up.",
"Repo hook: targeted Ruff lint fix failed.",
)
return

updated_paths = lint_fix_paths(repo_root)
updated_fingerprint = fingerprint_for_paths(repo_root, updated_paths)
state.last_tidy_fingerprint = updated_fingerprint
save_state(session_id, repo_root, state)

if updated_fingerprint != current_fingerprint:
write_stop_block(
"I ran targeted tidy steps on the touched Python files "
"(`ruff format` and `ruff check --fix`). Review the updated diff, "
"then continue or wrap up.",
"Repo hook: ran targeted Ruff tidy on touched files.",
)


if __name__ == "__main__":
main()
4 changes: 2 additions & 2 deletions .github/codex/prompts/pr-labels.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Allowed labels:
- dependencies
- feature:chat-completions
- feature:core
- feature:lite-llm
- feature:extensions
- feature:mcp
- feature:realtime
- feature:sessions
Expand All @@ -45,7 +45,7 @@ Label rules:
- bug vs enhancement: Prefer exactly one of these. Include both only when the PR clearly contains two separate substantial changes and both are first-order outcomes.
- feature:chat-completions: Chat Completions support or conversion is a primary deliverable of the PR. Do not add it for a small compatibility guard or parity update in `chatcmpl_converter.py`.
- feature:core: Core agent loop, tool calls, run pipeline, or other central runtime behavior is a primary surface of the PR. For cross-cutting runtime changes, this is usually the single best feature label.
- feature:lite-llm: LiteLLM adapter/provider behavior is a primary deliverable of the PR.
- feature:extensions: `src/agents/extensions/` surfaces are a primary deliverable of the PR, including extension models/providers such as Any-LLM and LiteLLM.
- feature:mcp: MCP-specific behavior or APIs are a primary deliverable of the PR. Do not add it for incidental hosted/deferred tool plumbing touched by broader runtime work.
- feature:realtime: Realtime-specific behavior, API shape, or session semantics are a primary deliverable of the PR. Do not add it for small parity updates in realtime adapters.
- feature:sessions: Session or memory behavior is a primary deliverable of the PR. Do not add it for persistence updates that merely support a broader feature.
Expand Down
2 changes: 1 addition & 1 deletion .github/codex/schemas/pr-labels.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"dependencies",
"feature:chat-completions",
"feature:core",
"feature:lite-llm",
"feature:extensions",
"feature:mcp",
"feature:realtime",
"feature:sessions",
Expand Down
10 changes: 2 additions & 8 deletions .github/scripts/pr_labels.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"dependencies",
"feature:chat-completions",
"feature:core",
"feature:lite-llm",
"feature:extensions",
"feature:mcp",
"feature:realtime",
"feature:sessions",
Expand All @@ -27,6 +27,7 @@
}

SOURCE_FEATURE_PREFIXES: Final[dict[str, tuple[str, ...]]] = {
"feature:extensions": ("src/agents/extensions/",),
"feature:realtime": ("src/agents/realtime/",),
"feature:voice": ("src/agents/voice/",),
"feature:mcp": ("src/agents/mcp/",),
Expand Down Expand Up @@ -170,13 +171,6 @@ def infer_specific_feature_labels(changed_files: Sequence[str]) -> set[str]:
):
labels.add("feature:chat-completions")

if any(
path.startswith(("src/agents/models/", "src/agents/extensions/models/"))
and "litellm" in path
for path in source_files
):
labels.add("feature:lite-llm")

return labels


Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
fi
- name: Setup uv
if: steps.docs-only.outputs.skip != 'true'
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57
with:
enable-cache: true
- name: Install dependencies
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-labels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ jobs:
- name: Run Codex labeling
id: run_codex
if: ${{ (github.event_name == 'workflow_dispatch' || steps.pr.outputs.is_fork != 'true') && github.actor != 'dependabot[bot]' }}
uses: openai/codex-action@086169432f1d2ab2f4057540b1754d550f6a1189
uses: openai/codex-action@c25d10f3f498316d4b2496cc4c6dd58057a7b031
with:
openai-api-key: ${{ secrets.PROD_OPENAI_API_KEY }}
prompt-file: .github/codex/prompts/pr-labels.md
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Setup uv
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57
with:
enable-cache: true
- name: Install dependencies
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-pr-update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
echo "output_file=${output_file}" >> "$GITHUB_OUTPUT"
- name: Run Codex release review
if: steps.find.outputs.found == 'true'
uses: openai/codex-action@086169432f1d2ab2f4057540b1754d550f6a1189
uses: openai/codex-action@c25d10f3f498316d4b2496cc4c6dd58057a7b031
with:
openai-api-key: ${{ secrets.PROD_OPENAI_API_KEY }}
prompt-file: .github/codex/prompts/release-review.md
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
fetch-depth: 0
ref: main
- name: Setup uv
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57
with:
enable-cache: true
- name: Fetch tags
Expand Down Expand Up @@ -101,7 +101,7 @@ jobs:
mkdir -p "$output_dir"
echo "output_file=${output_file}" >> "$GITHUB_OUTPUT"
- name: Run Codex release review
uses: openai/codex-action@086169432f1d2ab2f4057540b1754d550f6a1189
uses: openai/codex-action@c25d10f3f498316d4b2496cc4c6dd58057a7b031
with:
openai-api-key: ${{ secrets.PROD_OPENAI_API_KEY }}
prompt-file: .github/codex/prompts/release-review.md
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
run: ./.github/scripts/detect-changes.sh code "${{ github.event.pull_request.base.sha || github.event.before }}" "${{ github.sha }}"
- name: Setup uv
if: steps.changes.outputs.run == 'true'
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57
with:
enable-cache: true
- name: Install dependencies
Expand All @@ -50,7 +50,7 @@ jobs:
run: ./.github/scripts/detect-changes.sh code "${{ github.event.pull_request.base.sha || github.event.before }}" "${{ github.sha }}"
- name: Setup uv
if: steps.changes.outputs.run == 'true'
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57
with:
enable-cache: true
- name: Install dependencies
Expand Down Expand Up @@ -84,7 +84,7 @@ jobs:
run: ./.github/scripts/detect-changes.sh code "${{ github.event.pull_request.base.sha || github.event.before }}" "${{ github.sha }}"
- name: Setup uv
if: steps.changes.outputs.run == 'true'
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
Expand Down Expand Up @@ -116,7 +116,7 @@ jobs:
run: ./.github/scripts/detect-changes.sh docs "${{ github.event.pull_request.base.sha || github.event.before }}" "${{ github.sha }}"
- name: Setup uv
if: steps.changes.outputs.run == 'true'
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57
with:
enable-cache: true
- name: Install dependencies
Expand Down
Loading
Loading