codex-app-server-sdk 0.3.2__tar.gz → 0.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codex_app_server_sdk-0.4.1/.github/workflows/ci.yml +100 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/.github/workflows/docs.yml +15 -11
- codex_app_server_sdk-0.4.1/.github/workflows/publish.yml +110 -0
- codex_app_server_sdk-0.4.1/CHANGELOG.md +104 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/PKG-INFO +65 -8
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/README.md +61 -5
- codex_app_server_sdk-0.4.1/RELEASE.md +9 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/approvals-and-sandbox.md +43 -11
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/behavior-guarantees.md +16 -2
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/conversation.md +10 -0
- codex_app_server_sdk-0.4.1/docs/human-in-the-loop.md +161 -0
- codex_app_server_sdk-0.4.1/docs/index.md +102 -0
- codex_app_server_sdk-0.4.1/docs/migration-0.4.0.md +222 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/recipes/index.md +1 -0
- codex_app_server_sdk-0.4.1/docs/releasing.md +206 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/timeouts-continuation-cancel.md +27 -1
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/mkdocs.yml +3 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/pyproject.toml +24 -5
- codex_app_server_sdk-0.4.1/scripts/__init__.py +1 -0
- codex_app_server_sdk-0.4.1/scripts/check_quality.py +86 -0
- codex_app_server_sdk-0.4.1/scripts/check_release.py +264 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/src/codex_app_server_sdk/__init__.py +18 -0
- codex_app_server_sdk-0.4.1/src/codex_app_server_sdk/_version.py +7 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/src/codex_app_server_sdk/client.py +679 -231
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/src/codex_app_server_sdk/models.py +76 -4
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/src/codex_app_server_sdk/protocol.py +1 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/tests/test_chat_continuation.py +17 -3
- codex_app_server_sdk-0.4.1/tests/test_client_correctness.py +412 -0
- codex_app_server_sdk-0.4.1/tests/test_collaboration_mode.py +129 -0
- codex_app_server_sdk-0.4.1/tests/test_live_app_server.py +83 -0
- codex_app_server_sdk-0.4.1/tests/test_release_checks.py +292 -0
- codex_app_server_sdk-0.4.1/tests/test_user_input_requests.py +202 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/uv.lock +650 -622
- codex_app_server_sdk-0.3.2/.github/workflows/publish.yml +0 -52
- codex_app_server_sdk-0.3.2/RELEASE.md +0 -56
- codex_app_server_sdk-0.3.2/docs/index.md +0 -59
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/.gitignore +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/LICENSE +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/api/client.md +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/api/errors.md +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/api/index.md +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/api/models.md +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/api/package.md +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/api/protocol.md +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/api/transport.md +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/examples.md +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/getting-started.md +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/protocol-mapping.md +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/threads-and-config.md +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/docs/transports.md +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/examples/chat_session_stdio.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/examples/chat_session_websocket.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/examples/chat_steps_rich.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/examples/thread_concurrent_handles.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/examples/thread_config_and_fork.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/examples/thread_ops_showcase.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/examples/thread_resume_by_id.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/scripts/check_chat_method_links.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/src/codex_app_server_sdk/errors.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/src/codex_app_server_sdk/py.typed +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/src/codex_app_server_sdk/transport.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/tests/test_approval_requests.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/tests/test_chat_assembly_completed_item.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/tests/test_chat_steps.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/tests/test_client_chat_once.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/tests/test_client_lifecycle.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/tests/test_protocol.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/tests/test_thread_handle.py +0 -0
- {codex_app_server_sdk-0.3.2 → codex_app_server_sdk-0.4.1}/tests/test_transport.py +0 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main, master]
|
|
6
|
+
push:
|
|
7
|
+
branches: [main, master]
|
|
8
|
+
workflow_call:
|
|
9
|
+
inputs:
|
|
10
|
+
base_ref:
|
|
11
|
+
description: Previous release tag for changed-file quality checks
|
|
12
|
+
required: true
|
|
13
|
+
type: string
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
env:
|
|
19
|
+
CODEX_SDK_LIVE_TESTS: "0"
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
test:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
strategy:
|
|
25
|
+
fail-fast: false
|
|
26
|
+
matrix:
|
|
27
|
+
python: ["3.12", "3.13", "3.14"]
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v7.0.1
|
|
30
|
+
- uses: actions/setup-python@v7.0.0
|
|
31
|
+
with:
|
|
32
|
+
python-version: ${{ matrix.python }}
|
|
33
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
34
|
+
with:
|
|
35
|
+
version: "0.11.18"
|
|
36
|
+
- run: uv sync --locked --group dev
|
|
37
|
+
- run: uv run --locked python -m pytest -q
|
|
38
|
+
|
|
39
|
+
quality:
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v7.0.1
|
|
43
|
+
with:
|
|
44
|
+
fetch-depth: 0
|
|
45
|
+
- uses: actions/setup-python@v7.0.0
|
|
46
|
+
with:
|
|
47
|
+
python-version: "3.12"
|
|
48
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
49
|
+
with:
|
|
50
|
+
version: "0.11.18"
|
|
51
|
+
- run: uv sync --locked --group dev
|
|
52
|
+
- name: Check changed Python files in parallel
|
|
53
|
+
env:
|
|
54
|
+
BASE_REF: ${{ inputs.base_ref || github.event.pull_request.base.sha || github.event.before }}
|
|
55
|
+
run: uv run --locked python scripts/check_quality.py --base "$BASE_REF"
|
|
56
|
+
|
|
57
|
+
package:
|
|
58
|
+
needs: [test, quality]
|
|
59
|
+
runs-on: ubuntu-latest
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@v7.0.1
|
|
62
|
+
- uses: actions/setup-python@v7.0.0
|
|
63
|
+
with:
|
|
64
|
+
python-version: "3.12"
|
|
65
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
66
|
+
with:
|
|
67
|
+
version: "0.11.18"
|
|
68
|
+
- run: uv sync --locked --group dev
|
|
69
|
+
- name: Check documentation
|
|
70
|
+
run: |
|
|
71
|
+
uv run --locked python scripts/check_chat_method_links.py
|
|
72
|
+
uv run --locked zensical build
|
|
73
|
+
- name: Build and validate distributions
|
|
74
|
+
run: |
|
|
75
|
+
uv build --no-sources
|
|
76
|
+
uv run --locked twine check --strict dist/*
|
|
77
|
+
uv run --locked python scripts/check_release.py --dist-dir dist
|
|
78
|
+
- name: Smoke test the installed wheel outside the source environment
|
|
79
|
+
run: |
|
|
80
|
+
export EXPECTED_VERSION
|
|
81
|
+
EXPECTED_VERSION=$(uv version --short)
|
|
82
|
+
wheels=(dist/*.whl)
|
|
83
|
+
uv run --isolated --no-project --with "${wheels[0]}" python -I - <<'PY'
|
|
84
|
+
import os
|
|
85
|
+
from importlib.metadata import version
|
|
86
|
+
from importlib.resources import files
|
|
87
|
+
from codex_app_server_sdk import CodexClient, __version__
|
|
88
|
+
|
|
89
|
+
assert __version__ == version("codex-app-server-sdk") == os.environ["EXPECTED_VERSION"]
|
|
90
|
+
assert files("codex_app_server_sdk").joinpath("py.typed").is_file()
|
|
91
|
+
assert callable(CodexClient.connect_stdio)
|
|
92
|
+
PY
|
|
93
|
+
- name: Reject conflicting artifacts already on PyPI
|
|
94
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
95
|
+
run: uv run --locked python scripts/check_release.py --dist-dir dist --check-pypi
|
|
96
|
+
- uses: actions/upload-artifact@v7.0.1
|
|
97
|
+
with:
|
|
98
|
+
name: dist
|
|
99
|
+
path: dist/*
|
|
100
|
+
if-no-files-found: error
|
|
@@ -12,24 +12,26 @@ jobs:
|
|
|
12
12
|
runs-on: ubuntu-latest
|
|
13
13
|
steps:
|
|
14
14
|
- name: Checkout
|
|
15
|
-
uses: actions/checkout@
|
|
15
|
+
uses: actions/checkout@v7.0.1
|
|
16
16
|
|
|
17
17
|
- name: Setup Python
|
|
18
|
-
uses: actions/setup-python@
|
|
18
|
+
uses: actions/setup-python@v7.0.0
|
|
19
19
|
with:
|
|
20
20
|
python-version: "3.12"
|
|
21
21
|
|
|
22
22
|
- name: Setup uv
|
|
23
|
-
uses: astral-sh/setup-uv@
|
|
23
|
+
uses: astral-sh/setup-uv@v10.2.0
|
|
24
|
+
with:
|
|
25
|
+
version: "0.11.18"
|
|
24
26
|
|
|
25
27
|
- name: Install dependencies
|
|
26
|
-
run: uv sync --group dev
|
|
28
|
+
run: uv sync --locked --group dev
|
|
27
29
|
|
|
28
30
|
- name: Check method links
|
|
29
|
-
run: uv run python scripts/check_chat_method_links.py
|
|
31
|
+
run: uv run --locked python scripts/check_chat_method_links.py
|
|
30
32
|
|
|
31
33
|
- name: Build docs
|
|
32
|
-
run: uv run zensical build
|
|
34
|
+
run: uv run --locked zensical build
|
|
33
35
|
|
|
34
36
|
- name: Link check
|
|
35
37
|
uses: lycheeverse/lychee-action@v2
|
|
@@ -58,21 +60,23 @@ jobs:
|
|
|
58
60
|
url: ${{ steps.deployment.outputs.page_url }}
|
|
59
61
|
steps:
|
|
60
62
|
- name: Checkout
|
|
61
|
-
uses: actions/checkout@
|
|
63
|
+
uses: actions/checkout@v7.0.1
|
|
62
64
|
|
|
63
65
|
- name: Setup Python
|
|
64
|
-
uses: actions/setup-python@
|
|
66
|
+
uses: actions/setup-python@v7.0.0
|
|
65
67
|
with:
|
|
66
68
|
python-version: "3.12"
|
|
67
69
|
|
|
68
70
|
- name: Setup uv
|
|
69
|
-
uses: astral-sh/setup-uv@
|
|
71
|
+
uses: astral-sh/setup-uv@v10.2.0
|
|
72
|
+
with:
|
|
73
|
+
version: "0.11.18"
|
|
70
74
|
|
|
71
75
|
- name: Install dependencies
|
|
72
|
-
run: uv sync --group dev
|
|
76
|
+
run: uv sync --locked --group dev
|
|
73
77
|
|
|
74
78
|
- name: Build docs
|
|
75
|
-
run: uv run zensical build
|
|
79
|
+
run: uv run --locked zensical build
|
|
76
80
|
|
|
77
81
|
- name: Configure Pages
|
|
78
82
|
uses: actions/configure-pages@v5
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
name: publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: publish-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: false
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
validate:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
outputs:
|
|
20
|
+
version: ${{ steps.release.outputs.version }}
|
|
21
|
+
base_ref: ${{ steps.release.outputs.base_ref }}
|
|
22
|
+
prerelease: ${{ steps.release.outputs.prerelease }}
|
|
23
|
+
steps:
|
|
24
|
+
- name: Require a tag, including for manual runs
|
|
25
|
+
env:
|
|
26
|
+
REF_TYPE: ${{ github.ref_type }}
|
|
27
|
+
run: test "$REF_TYPE" = tag
|
|
28
|
+
- uses: actions/checkout@v7.0.1
|
|
29
|
+
with:
|
|
30
|
+
fetch-depth: 0
|
|
31
|
+
- uses: actions/setup-python@v7.0.0
|
|
32
|
+
with:
|
|
33
|
+
python-version: "3.12"
|
|
34
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
35
|
+
with:
|
|
36
|
+
version: "0.11.18"
|
|
37
|
+
- run: uv sync --locked --group dev
|
|
38
|
+
- name: Validate version, tag commit, and release notes
|
|
39
|
+
id: release
|
|
40
|
+
env:
|
|
41
|
+
RELEASE_TAG: ${{ github.ref_name }}
|
|
42
|
+
run: >-
|
|
43
|
+
uv run --locked python scripts/check_release.py
|
|
44
|
+
--tag "$RELEASE_TAG" --require-tag
|
|
45
|
+
--notes-file release-notes.md --github-output "$GITHUB_OUTPUT"
|
|
46
|
+
- uses: actions/upload-artifact@v7.0.1
|
|
47
|
+
with:
|
|
48
|
+
name: release-notes
|
|
49
|
+
path: release-notes.md
|
|
50
|
+
if-no-files-found: error
|
|
51
|
+
|
|
52
|
+
checks:
|
|
53
|
+
needs: validate
|
|
54
|
+
uses: ./.github/workflows/ci.yml
|
|
55
|
+
with:
|
|
56
|
+
base_ref: ${{ needs.validate.outputs.base_ref }}
|
|
57
|
+
|
|
58
|
+
publish:
|
|
59
|
+
needs: checks
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
environment:
|
|
62
|
+
name: pypi
|
|
63
|
+
url: https://pypi.org/p/codex-app-server-sdk
|
|
64
|
+
permissions:
|
|
65
|
+
id-token: write
|
|
66
|
+
steps:
|
|
67
|
+
- name: Download distributions
|
|
68
|
+
uses: actions/download-artifact@v8.0.1
|
|
69
|
+
with:
|
|
70
|
+
name: dist
|
|
71
|
+
path: dist
|
|
72
|
+
|
|
73
|
+
- name: Publish to PyPI
|
|
74
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
75
|
+
with:
|
|
76
|
+
# The package job first rejects same-name files with different hashes.
|
|
77
|
+
skip-existing: true
|
|
78
|
+
|
|
79
|
+
github-release:
|
|
80
|
+
needs: [validate, publish]
|
|
81
|
+
runs-on: ubuntu-latest
|
|
82
|
+
permissions:
|
|
83
|
+
contents: write
|
|
84
|
+
env:
|
|
85
|
+
GH_TOKEN: ${{ github.token }}
|
|
86
|
+
GH_REPO: ${{ github.repository }}
|
|
87
|
+
RELEASE_TAG: ${{ github.ref_name }}
|
|
88
|
+
PRERELEASE: ${{ needs.validate.outputs.prerelease }}
|
|
89
|
+
steps:
|
|
90
|
+
- uses: actions/download-artifact@v8.0.1
|
|
91
|
+
with:
|
|
92
|
+
name: dist
|
|
93
|
+
path: dist
|
|
94
|
+
- uses: actions/download-artifact@v8.0.1
|
|
95
|
+
with:
|
|
96
|
+
name: release-notes
|
|
97
|
+
- name: Publish release notes and the exact PyPI artifacts
|
|
98
|
+
run: |
|
|
99
|
+
if draft_status=$(gh release view "$RELEASE_TAG" --json isDraft --jq .isDraft 2>/dev/null); then
|
|
100
|
+
if [ "$draft_status" = false ]; then
|
|
101
|
+
echo "GitHub Release already published: $RELEASE_TAG"
|
|
102
|
+
exit 0
|
|
103
|
+
fi
|
|
104
|
+
else
|
|
105
|
+
gh release create "$RELEASE_TAG" --verify-tag --draft \
|
|
106
|
+
--title "$RELEASE_TAG" --notes-file release-notes.md
|
|
107
|
+
fi
|
|
108
|
+
gh release upload "$RELEASE_TAG" dist/* --clobber
|
|
109
|
+
gh release edit "$RELEASE_TAG" --draft=false \
|
|
110
|
+
--prerelease="$PRERELEASE" --notes-file release-notes.md
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Version headings identify prepared releases. Publication dates and artifacts
|
|
4
|
+
are recorded in GitHub Releases and PyPI.
|
|
5
|
+
|
|
6
|
+
## 0.4.1
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
- Convert the README's relative changelog and release-procedure links to
|
|
11
|
+
version-tagged GitHub URLs when building the PyPI description. The source
|
|
12
|
+
README keeps its relative links.
|
|
13
|
+
|
|
14
|
+
### Compatibility
|
|
15
|
+
|
|
16
|
+
- Packaging/documentation patch; the SDK API and behavior are unchanged from 0.4.0.
|
|
17
|
+
The 0.4.0 migration requirements below still apply.
|
|
18
|
+
- Source builds now use `hatch-fancy-pypi-readme` as a build dependency. Isolated
|
|
19
|
+
builds install it automatically; builds without isolation must provide it.
|
|
20
|
+
Wheel runtime dependencies are unchanged.
|
|
21
|
+
|
|
22
|
+
## 0.4.0
|
|
23
|
+
|
|
24
|
+
### Compatibility and required migration
|
|
25
|
+
|
|
26
|
+
**This release is not a drop-in behavior-compatible upgrade from 0.3.2.**
|
|
27
|
+
Read the [complete migration guide](https://emsi.github.io/codex-app-server-sdk/migration-0.4.0/)
|
|
28
|
+
before deploying an existing application. Existing public methods and imports
|
|
29
|
+
remain available, but callers may need the following changes:
|
|
30
|
+
|
|
31
|
+
- **Manual approvals:** set `approval_mode="manual"` when responding through
|
|
32
|
+
`approval_requests()` without a callback. Previously, these responses raced
|
|
33
|
+
automatic decline. The default still declines without a handler; a callback
|
|
34
|
+
handles requests in either mode. Consuming the stream does not select manual
|
|
35
|
+
mode. Late, duplicate, server-resolved, or mismatched approval responses now
|
|
36
|
+
fail stricter pending-request checks.
|
|
37
|
+
- **Unsuccessful turns:** both conversation APIs raise `CodexProtocolError`
|
|
38
|
+
for failed/interrupted terminal statuses, even after partial output. A stream
|
|
39
|
+
can yield steps before raising; partial assistant text is not proof of success.
|
|
40
|
+
- **Cancellation errors and ownership:** `cancel()` propagates interrupt RPC,
|
|
41
|
+
request-timeout, and transport failures. Missing terminal confirmation raises
|
|
42
|
+
`CodexTurnInactiveError` with the original continuation and cursor. It rejects
|
|
43
|
+
tokens for turns no longer retained by the same client, including repeated
|
|
44
|
+
cancellation after cleanup. Retain tokens on errors, but do not assume a
|
|
45
|
+
failed transport remains usable.
|
|
46
|
+
- **Cancellation results:** `was_interrupted` requires confirmed interruption;
|
|
47
|
+
`was_completed` means successful completion. Both can be false for a failed
|
|
48
|
+
terminal turn. An interrupt acknowledgement alone is not confirmation.
|
|
49
|
+
- **Low-level interruption:** pass `thread_id` to `interrupt_turn()` for turns
|
|
50
|
+
the SDK does not track. Missing or conflicting thread IDs raise `ValueError`.
|
|
51
|
+
- **Initialization:** the first successful call is cached. Later `initialize()`
|
|
52
|
+
calls return the same result and ignore new parameters/timeouts. Supply custom
|
|
53
|
+
settings before implicit initialization. Custom servers and tests must accept
|
|
54
|
+
the new `initialized` notification and the installed SDK version in default
|
|
55
|
+
`clientInfo.version`, replacing the hardcoded `0.1.0`.
|
|
56
|
+
- **Unanswered user questions:** `item/tool/requestUserInput` now waits up to
|
|
57
|
+
300 seconds without a callback or manual response, instead of immediately
|
|
58
|
+
returning unsupported-method error `-32601`. The default 180-second turn
|
|
59
|
+
inactivity timeout can fire first. Unattended clients can set
|
|
60
|
+
`user_input_response_timeout=0.0` for a prompt error response (`-32000`, not
|
|
61
|
+
the old code); manual UIs may use `None` with an active response loop.
|
|
62
|
+
- **Events and transports:** routing uses explicit turn/thread identifiers,
|
|
63
|
+
not arbitrary nested content. Ambiguous terminal events no longer complete
|
|
64
|
+
arbitrary turns. Raw event counts/timing can change; all waiting consumers
|
|
65
|
+
now receive connection failures. Custom transports and fixtures may need
|
|
66
|
+
updated envelopes and handshake expectations.
|
|
67
|
+
- **Installation and model shape:** package imports require installed
|
|
68
|
+
distribution metadata; use `uv sync` or an editable/wheel install rather
|
|
69
|
+
than copying source alone. `TurnOverrides` adds a field, affecting fixed
|
|
70
|
+
dataclass snapshots and tuple unpacking. Python and runtime dependency
|
|
71
|
+
requirements are unchanged.
|
|
72
|
+
|
|
73
|
+
### Added
|
|
74
|
+
|
|
75
|
+
- Collaboration mode configuration (`default` and `plan`) through turn overrides.
|
|
76
|
+
- Human input requests, typed answers, callbacks, and manual response streams.
|
|
77
|
+
- Explicit `approval_mode="manual"` for applications that collect approval
|
|
78
|
+
decisions from a person or UI.
|
|
79
|
+
- Public `__version__`, read from installed package metadata and used in the
|
|
80
|
+
app-server initialization handshake.
|
|
81
|
+
- Release validation shared with PR CI: Python 3.12–3.14 tests, changed-file
|
|
82
|
+
quality checks, package checks, and an isolated wheel import.
|
|
83
|
+
- Automated GitHub Releases with changelog notes and the same artifacts as
|
|
84
|
+
PyPI, with version/tag checks and recovery for interrupted uploads.
|
|
85
|
+
|
|
86
|
+
### Fixed
|
|
87
|
+
|
|
88
|
+
- Concurrent turns receive their own notifications, including events that
|
|
89
|
+
arrive before the turn-start response. Connection failures wake all waiters.
|
|
90
|
+
- Concurrent first calls initialize the connection once and send `initialized`.
|
|
91
|
+
- Failed and interrupted turns raise `CodexProtocolError` from both conversation
|
|
92
|
+
APIs, including when partial assistant text has already arrived.
|
|
93
|
+
- Interrupt requests include both thread and turn identifiers. Cancellation
|
|
94
|
+
retains continuations on errors or timeouts and cleans up after confirmation.
|
|
95
|
+
- Approval responses reject duplicate or already-resolved requests.
|
|
96
|
+
- Update release tooling to validate current Hatchling's core metadata 2.5.
|
|
97
|
+
- Make basedpyright warnings non-fatal consistently in local and GitHub
|
|
98
|
+
Actions checks; type errors remain a release gate.
|
|
99
|
+
|
|
100
|
+
### Validation
|
|
101
|
+
|
|
102
|
+
- Added deterministic regression tests and an opt-in live smoke test using
|
|
103
|
+
only `gpt-6-luna`. Concurrent turns and cancellation were tested with Codex
|
|
104
|
+
CLI 0.156.1; this does not imply complete coverage of its protocol.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: codex-app-server-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Async Python client for Codex app-server over stdio and websocket.
|
|
5
5
|
Project-URL: Documentation, https://emsi.github.io/codex-app-server-sdk/
|
|
6
6
|
Project-URL: Repository, https://github.com/emsi/codex-app-server-sdk
|
|
@@ -674,6 +674,7 @@ Classifier: License :: OSI Approved :: GNU Affero General Public License v3
|
|
|
674
674
|
Classifier: Programming Language :: Python :: 3
|
|
675
675
|
Classifier: Programming Language :: Python :: 3.12
|
|
676
676
|
Classifier: Programming Language :: Python :: 3.13
|
|
677
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
677
678
|
Classifier: Typing :: Typed
|
|
678
679
|
Requires-Python: >=3.12
|
|
679
680
|
Requires-Dist: pydantic>=2.8.0
|
|
@@ -682,7 +683,7 @@ Provides-Extra: dev
|
|
|
682
683
|
Requires-Dist: build>=1.2.2; extra == 'dev'
|
|
683
684
|
Requires-Dist: mkdocstrings-python>=1.18.2; extra == 'dev'
|
|
684
685
|
Requires-Dist: pytest>=8.2.0; extra == 'dev'
|
|
685
|
-
Requires-Dist: twine>=
|
|
686
|
+
Requires-Dist: twine>=7.0.0; extra == 'dev'
|
|
686
687
|
Requires-Dist: zensical>=0.0.23; extra == 'dev'
|
|
687
688
|
Description-Content-Type: text/markdown
|
|
688
689
|
|
|
@@ -694,6 +695,13 @@ It gives you a convenient conversation API over `stdio` or `websocket` without h
|
|
|
694
695
|
|
|
695
696
|
Documentation: https://emsi.github.io/codex-app-server-sdk/
|
|
696
697
|
|
|
698
|
+
> **Upgrading to 0.4.0? Behavior changes require review.** Read the
|
|
699
|
+
> [0.3.2 → 0.4.0 migration guide](https://emsi.github.io/codex-app-server-sdk/migration-0.4.0/)
|
|
700
|
+
> before upgrading.
|
|
701
|
+
> Stream-based approval responders must set `approval_mode="manual"`.
|
|
702
|
+
> Failed/interrupted turns now raise; cancellation, initialization, unanswered
|
|
703
|
+
> user questions, and custom transport expectations also change.
|
|
704
|
+
|
|
697
705
|
## Highlights
|
|
698
706
|
|
|
699
707
|
- simple one-shot turns with `chat_once(...)`
|
|
@@ -702,8 +710,46 @@ Documentation: https://emsi.github.io/codex-app-server-sdk/
|
|
|
702
710
|
- thread-scoped config + forking via `ThreadHandle`
|
|
703
711
|
- inactivity timeout continuation for long-running turns
|
|
704
712
|
- turn cancellation with unread-step/event drain via `cancel(...)`
|
|
713
|
+
- collaboration mode overrides (`default`/`plan`) via `TurnOverrides`
|
|
714
|
+
- human-in-the-loop user input handling (`item/tool/requestUserInput`)
|
|
705
715
|
- optional low-level `request(...)` access when needed
|
|
706
716
|
|
|
717
|
+
## Why use this client?
|
|
718
|
+
|
|
719
|
+
Protocol I/O and callbacks run directly on your application's `asyncio` event
|
|
720
|
+
loop, using asynchronous subprocess pipes or WebSockets. Thread handles share
|
|
721
|
+
one connection, and approvals can integrate with an async callback or a manual
|
|
722
|
+
UI response loop.
|
|
723
|
+
|
|
724
|
+
You control the Codex runtime: launch your chosen executable or connect to an
|
|
725
|
+
existing WebSocket server. The conversation API adds completed-step streaming,
|
|
726
|
+
resumable inactivity timeouts, and cancellation with unread-event recovery.
|
|
727
|
+
The `Transport` interface and raw `request(...)` method remain available for
|
|
728
|
+
application-specific integrations.
|
|
729
|
+
|
|
730
|
+
### Compared with `openai-codex`
|
|
731
|
+
|
|
732
|
+
Both libraries use the Codex app-server protocol. Their integration choices differ:
|
|
733
|
+
|
|
734
|
+
| Area | `codex-app-server-sdk` | `openai-codex` |
|
|
735
|
+
| --- | --- | --- |
|
|
736
|
+
| Execution | Native `asyncio` client; asynchronous protocol I/O on your event loop | Synchronous client with an async wrapper that offloads blocking operations to background threads |
|
|
737
|
+
| Transport | Public, replaceable `Transport`; built-in stdio and WebSocket support | SDK-managed subprocess communicating through line-delimited JSON over stdio |
|
|
738
|
+
| Protocol access | Flexible dictionary-based RPC via `request(...)`, plus high-level conversation models | Extensive generated types, typed responses, and typed notifications |
|
|
739
|
+
| Runtime management | You supply and manage Codex; choose an executable or connect to an existing WebSocket server | Installs an exactly pinned Codex runtime dependency by default |
|
|
740
|
+
|
|
741
|
+
This client fits applications that need native async I/O, custom transports,
|
|
742
|
+
connections to an existing server, or independent control over runtime upgrades.
|
|
743
|
+
The official SDK offers broader generated type coverage and a reproducible
|
|
744
|
+
runtime default. You are responsible for installing and updating Codex when
|
|
745
|
+
using this client.
|
|
746
|
+
|
|
747
|
+
Comparison verified against the published
|
|
748
|
+
[`openai-codex` 0.156.1](https://pypi.org/project/openai-codex/0.156.1/)
|
|
749
|
+
source and package metadata on 2026-09-23. The official SDK also supports a
|
|
750
|
+
[`CodexConfig(codex_bin=...)` override](https://learn.chatgpt.com/docs/codex-sdk)
|
|
751
|
+
for selecting a different local executable.
|
|
752
|
+
|
|
707
753
|
## Install
|
|
708
754
|
|
|
709
755
|
Install `uv` (if needed):
|
|
@@ -728,6 +774,10 @@ uv pip install codex-app-server-sdk
|
|
|
728
774
|
|
|
729
775
|
- Docs site: https://emsi.github.io/codex-app-server-sdk/
|
|
730
776
|
- PyPI: https://pypi.org/project/codex-app-server-sdk/
|
|
777
|
+
- Human-in-the-loop guide: https://emsi.github.io/codex-app-server-sdk/human-in-the-loop/
|
|
778
|
+
- Release procedure: [RELEASE.md](https://github.com/emsi/codex-app-server-sdk/blob/v0.4.1/RELEASE.md)
|
|
779
|
+
- Upgrading from 0.3.2: [0.4.0 migration guide](https://emsi.github.io/codex-app-server-sdk/migration-0.4.0/)
|
|
780
|
+
- Release notes and migration guidance: [CHANGELOG.md](https://github.com/emsi/codex-app-server-sdk/blob/v0.4.1/CHANGELOG.md)
|
|
731
781
|
|
|
732
782
|
## Quick start
|
|
733
783
|
|
|
@@ -1083,13 +1133,13 @@ uv run python examples/chat_session_websocket.py
|
|
|
1083
1133
|
- `compact_thread(thread_id)`: request context compaction.
|
|
1084
1134
|
- `chat(...)` (`text=None, thread_id=None, user=None, metadata=None, thread_config=None, turn_overrides=None, inactivity_timeout=None, continuation=None`): async iterator yielding completed non-delta step blocks.
|
|
1085
1135
|
- `chat_once(...)` (`text=None, thread_id=None, user=None, metadata=None, thread_config=None, turn_overrides=None, inactivity_timeout=None, continuation=None`): send one user message and wait for completed turn.
|
|
1086
|
-
- `cancel(continuation, timeout=None)`: interrupt
|
|
1136
|
+
- `cancel(continuation, timeout=None)`: interrupt a turn and return unread steps/events after terminal confirmation; retain the continuation if cancellation fails or times out.
|
|
1087
1137
|
- `steer_turn(thread_id=..., expected_turn_id=..., input_items=...)`: steer active turn input.
|
|
1088
1138
|
- `start_review(thread_id=..., target=..., delivery=None)`: run review mode.
|
|
1089
1139
|
- `list_models(...)`: discover available models.
|
|
1090
1140
|
- `exec_command(command, ...)`: run one command via server command API.
|
|
1091
1141
|
- `read_config(...)`, `read_config_requirements()`, `write_config_value(...)`, `batch_write_config(...)`: config APIs.
|
|
1092
|
-
- `interrupt_turn(turn_id, timeout=None)`: low-level
|
|
1142
|
+
- `interrupt_turn(turn_id, thread_id=None, timeout=None)`: low-level interruption request; infer the thread for tracked turns or pass it explicitly.
|
|
1093
1143
|
- `close()`: cancel receive loop and close transport.
|
|
1094
1144
|
|
|
1095
1145
|
### `Transport` and implementations (`src/codex_app_server_sdk/transport.py`)
|
|
@@ -1138,7 +1188,9 @@ uv run python examples/chat_session_websocket.py
|
|
|
1138
1188
|
- `chat_once(...)` resolves final text from completed `agentMessage` items (`item/completed`), with `thread/read(includeTurns=true)` fallback.
|
|
1139
1189
|
- `turn_timeout` is intentionally removed to avoid conflicting timeout semantics.
|
|
1140
1190
|
- Turn waits are controlled by `inactivity_timeout` (or unbounded when `None`).
|
|
1141
|
-
- `cancel(...)`
|
|
1191
|
+
- `cancel(...)` releases turn state only after a terminal event. RPC failures propagate; a confirmation timeout raises `CodexTurnInactiveError` with the original continuation.
|
|
1192
|
+
- Failed or interrupted turns raise `CodexProtocolError` from both chat APIs, even if partial assistant text was received.
|
|
1193
|
+
- Use `approval_mode="manual"` on either connection factory to answer `approval_requests()` yourself. Without a callback, the default `"auto"` mode declines requests.
|
|
1142
1194
|
- Advanced thread-level config/fork uses protocol v2 methods (`thread/start`, `thread/resume`, `thread/fork`) exposed via `ThreadHandle` and `ThreadConfig`.
|
|
1143
1195
|
- `metadata` is applied on `turn/start` payloads for message turns; thread-level config uses schema-aligned fields on thread methods.
|
|
1144
1196
|
- preferred lifecycle is `async with CodexClient.connect_*() as client:`; manual `start()/close()` remains available for advanced control.
|
|
@@ -1157,14 +1209,16 @@ uv run python examples/chat_session_websocket.py
|
|
|
1157
1209
|
|
|
1158
1210
|
### Default initialize payload
|
|
1159
1211
|
|
|
1160
|
-
When `params=None`, the client sends
|
|
1212
|
+
When `params=None`, the client sends the following payload. The version
|
|
1213
|
+
placeholder is replaced with the installed package version, also available as
|
|
1214
|
+
`codex_app_server_sdk.__version__`:
|
|
1161
1215
|
|
|
1162
1216
|
```json
|
|
1163
1217
|
{
|
|
1164
1218
|
"protocolVersion": "1",
|
|
1165
1219
|
"clientInfo": {
|
|
1166
1220
|
"name": "codex-app-server-sdk",
|
|
1167
|
-
"version": "
|
|
1221
|
+
"version": "<installed SDK version>"
|
|
1168
1222
|
},
|
|
1169
1223
|
"capabilities": {
|
|
1170
1224
|
"optOutNotificationMethods": [
|
|
@@ -1206,6 +1260,9 @@ Merge rules:
|
|
|
1206
1260
|
|
|
1207
1261
|
### Example: explicit initialize
|
|
1208
1262
|
|
|
1263
|
+
The custom `clientInfo.version` below identifies your application, independently
|
|
1264
|
+
of the SDK version.
|
|
1265
|
+
|
|
1209
1266
|
```python
|
|
1210
1267
|
import asyncio
|
|
1211
1268
|
from codex_app_server_sdk import CodexClient
|
|
@@ -6,6 +6,13 @@ It gives you a convenient conversation API over `stdio` or `websocket` without h
|
|
|
6
6
|
|
|
7
7
|
Documentation: https://emsi.github.io/codex-app-server-sdk/
|
|
8
8
|
|
|
9
|
+
> **Upgrading to 0.4.0? Behavior changes require review.** Read the
|
|
10
|
+
> [0.3.2 → 0.4.0 migration guide](https://emsi.github.io/codex-app-server-sdk/migration-0.4.0/)
|
|
11
|
+
> before upgrading.
|
|
12
|
+
> Stream-based approval responders must set `approval_mode="manual"`.
|
|
13
|
+
> Failed/interrupted turns now raise; cancellation, initialization, unanswered
|
|
14
|
+
> user questions, and custom transport expectations also change.
|
|
15
|
+
|
|
9
16
|
## Highlights
|
|
10
17
|
|
|
11
18
|
- simple one-shot turns with `chat_once(...)`
|
|
@@ -14,8 +21,46 @@ Documentation: https://emsi.github.io/codex-app-server-sdk/
|
|
|
14
21
|
- thread-scoped config + forking via `ThreadHandle`
|
|
15
22
|
- inactivity timeout continuation for long-running turns
|
|
16
23
|
- turn cancellation with unread-step/event drain via `cancel(...)`
|
|
24
|
+
- collaboration mode overrides (`default`/`plan`) via `TurnOverrides`
|
|
25
|
+
- human-in-the-loop user input handling (`item/tool/requestUserInput`)
|
|
17
26
|
- optional low-level `request(...)` access when needed
|
|
18
27
|
|
|
28
|
+
## Why use this client?
|
|
29
|
+
|
|
30
|
+
Protocol I/O and callbacks run directly on your application's `asyncio` event
|
|
31
|
+
loop, using asynchronous subprocess pipes or WebSockets. Thread handles share
|
|
32
|
+
one connection, and approvals can integrate with an async callback or a manual
|
|
33
|
+
UI response loop.
|
|
34
|
+
|
|
35
|
+
You control the Codex runtime: launch your chosen executable or connect to an
|
|
36
|
+
existing WebSocket server. The conversation API adds completed-step streaming,
|
|
37
|
+
resumable inactivity timeouts, and cancellation with unread-event recovery.
|
|
38
|
+
The `Transport` interface and raw `request(...)` method remain available for
|
|
39
|
+
application-specific integrations.
|
|
40
|
+
|
|
41
|
+
### Compared with `openai-codex`
|
|
42
|
+
|
|
43
|
+
Both libraries use the Codex app-server protocol. Their integration choices differ:
|
|
44
|
+
|
|
45
|
+
| Area | `codex-app-server-sdk` | `openai-codex` |
|
|
46
|
+
| --- | --- | --- |
|
|
47
|
+
| Execution | Native `asyncio` client; asynchronous protocol I/O on your event loop | Synchronous client with an async wrapper that offloads blocking operations to background threads |
|
|
48
|
+
| Transport | Public, replaceable `Transport`; built-in stdio and WebSocket support | SDK-managed subprocess communicating through line-delimited JSON over stdio |
|
|
49
|
+
| Protocol access | Flexible dictionary-based RPC via `request(...)`, plus high-level conversation models | Extensive generated types, typed responses, and typed notifications |
|
|
50
|
+
| Runtime management | You supply and manage Codex; choose an executable or connect to an existing WebSocket server | Installs an exactly pinned Codex runtime dependency by default |
|
|
51
|
+
|
|
52
|
+
This client fits applications that need native async I/O, custom transports,
|
|
53
|
+
connections to an existing server, or independent control over runtime upgrades.
|
|
54
|
+
The official SDK offers broader generated type coverage and a reproducible
|
|
55
|
+
runtime default. You are responsible for installing and updating Codex when
|
|
56
|
+
using this client.
|
|
57
|
+
|
|
58
|
+
Comparison verified against the published
|
|
59
|
+
[`openai-codex` 0.156.1](https://pypi.org/project/openai-codex/0.156.1/)
|
|
60
|
+
source and package metadata on 2026-09-23. The official SDK also supports a
|
|
61
|
+
[`CodexConfig(codex_bin=...)` override](https://learn.chatgpt.com/docs/codex-sdk)
|
|
62
|
+
for selecting a different local executable.
|
|
63
|
+
|
|
19
64
|
## Install
|
|
20
65
|
|
|
21
66
|
Install `uv` (if needed):
|
|
@@ -40,6 +85,10 @@ uv pip install codex-app-server-sdk
|
|
|
40
85
|
|
|
41
86
|
- Docs site: https://emsi.github.io/codex-app-server-sdk/
|
|
42
87
|
- PyPI: https://pypi.org/project/codex-app-server-sdk/
|
|
88
|
+
- Human-in-the-loop guide: https://emsi.github.io/codex-app-server-sdk/human-in-the-loop/
|
|
89
|
+
- Release procedure: [RELEASE.md](RELEASE.md)
|
|
90
|
+
- Upgrading from 0.3.2: [0.4.0 migration guide](https://emsi.github.io/codex-app-server-sdk/migration-0.4.0/)
|
|
91
|
+
- Release notes and migration guidance: [CHANGELOG.md](CHANGELOG.md)
|
|
43
92
|
|
|
44
93
|
## Quick start
|
|
45
94
|
|
|
@@ -395,13 +444,13 @@ uv run python examples/chat_session_websocket.py
|
|
|
395
444
|
- `compact_thread(thread_id)`: request context compaction.
|
|
396
445
|
- `chat(...)` (`text=None, thread_id=None, user=None, metadata=None, thread_config=None, turn_overrides=None, inactivity_timeout=None, continuation=None`): async iterator yielding completed non-delta step blocks.
|
|
397
446
|
- `chat_once(...)` (`text=None, thread_id=None, user=None, metadata=None, thread_config=None, turn_overrides=None, inactivity_timeout=None, continuation=None`): send one user message and wait for completed turn.
|
|
398
|
-
- `cancel(continuation, timeout=None)`: interrupt
|
|
447
|
+
- `cancel(continuation, timeout=None)`: interrupt a turn and return unread steps/events after terminal confirmation; retain the continuation if cancellation fails or times out.
|
|
399
448
|
- `steer_turn(thread_id=..., expected_turn_id=..., input_items=...)`: steer active turn input.
|
|
400
449
|
- `start_review(thread_id=..., target=..., delivery=None)`: run review mode.
|
|
401
450
|
- `list_models(...)`: discover available models.
|
|
402
451
|
- `exec_command(command, ...)`: run one command via server command API.
|
|
403
452
|
- `read_config(...)`, `read_config_requirements()`, `write_config_value(...)`, `batch_write_config(...)`: config APIs.
|
|
404
|
-
- `interrupt_turn(turn_id, timeout=None)`: low-level
|
|
453
|
+
- `interrupt_turn(turn_id, thread_id=None, timeout=None)`: low-level interruption request; infer the thread for tracked turns or pass it explicitly.
|
|
405
454
|
- `close()`: cancel receive loop and close transport.
|
|
406
455
|
|
|
407
456
|
### `Transport` and implementations (`src/codex_app_server_sdk/transport.py`)
|
|
@@ -450,7 +499,9 @@ uv run python examples/chat_session_websocket.py
|
|
|
450
499
|
- `chat_once(...)` resolves final text from completed `agentMessage` items (`item/completed`), with `thread/read(includeTurns=true)` fallback.
|
|
451
500
|
- `turn_timeout` is intentionally removed to avoid conflicting timeout semantics.
|
|
452
501
|
- Turn waits are controlled by `inactivity_timeout` (or unbounded when `None`).
|
|
453
|
-
- `cancel(...)`
|
|
502
|
+
- `cancel(...)` releases turn state only after a terminal event. RPC failures propagate; a confirmation timeout raises `CodexTurnInactiveError` with the original continuation.
|
|
503
|
+
- Failed or interrupted turns raise `CodexProtocolError` from both chat APIs, even if partial assistant text was received.
|
|
504
|
+
- Use `approval_mode="manual"` on either connection factory to answer `approval_requests()` yourself. Without a callback, the default `"auto"` mode declines requests.
|
|
454
505
|
- Advanced thread-level config/fork uses protocol v2 methods (`thread/start`, `thread/resume`, `thread/fork`) exposed via `ThreadHandle` and `ThreadConfig`.
|
|
455
506
|
- `metadata` is applied on `turn/start` payloads for message turns; thread-level config uses schema-aligned fields on thread methods.
|
|
456
507
|
- preferred lifecycle is `async with CodexClient.connect_*() as client:`; manual `start()/close()` remains available for advanced control.
|
|
@@ -469,14 +520,16 @@ uv run python examples/chat_session_websocket.py
|
|
|
469
520
|
|
|
470
521
|
### Default initialize payload
|
|
471
522
|
|
|
472
|
-
When `params=None`, the client sends
|
|
523
|
+
When `params=None`, the client sends the following payload. The version
|
|
524
|
+
placeholder is replaced with the installed package version, also available as
|
|
525
|
+
`codex_app_server_sdk.__version__`:
|
|
473
526
|
|
|
474
527
|
```json
|
|
475
528
|
{
|
|
476
529
|
"protocolVersion": "1",
|
|
477
530
|
"clientInfo": {
|
|
478
531
|
"name": "codex-app-server-sdk",
|
|
479
|
-
"version": "
|
|
532
|
+
"version": "<installed SDK version>"
|
|
480
533
|
},
|
|
481
534
|
"capabilities": {
|
|
482
535
|
"optOutNotificationMethods": [
|
|
@@ -518,6 +571,9 @@ Merge rules:
|
|
|
518
571
|
|
|
519
572
|
### Example: explicit initialize
|
|
520
573
|
|
|
574
|
+
The custom `clientInfo.version` below identifies your application, independently
|
|
575
|
+
of the SDK version.
|
|
576
|
+
|
|
521
577
|
```python
|
|
522
578
|
import asyncio
|
|
523
579
|
from codex_app_server_sdk import CodexClient
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Releasing codex-app-server-sdk
|
|
2
|
+
|
|
3
|
+
The maintained procedure is in [the release guide](docs/releasing.md), also
|
|
4
|
+
published on the [documentation site](https://emsi.github.io/codex-app-server-sdk/releasing/).
|
|
5
|
+
|
|
6
|
+
Prepare the version and changelog locally, then push the reviewed version tag.
|
|
7
|
+
GitHub Actions validates, builds, publishes to PyPI, and creates a GitHub Release
|
|
8
|
+
with the same distributions. Do not manually upload packages before pushing the
|
|
9
|
+
tag: the tag already triggers publication.
|