python-codex 0.3.1__tar.gz → 0.3.2__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.
- {python_codex-0.3.1 → python_codex-0.3.2}/.github/workflows/publish.yml +11 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/PKG-INFO +31 -4
- {python_codex-0.3.1 → python_codex-0.3.2}/README.md +30 -3
- {python_codex-0.3.1 → python_codex-0.3.2}/README_ZH.md +26 -3
- {python_codex-0.3.1 → python_codex-0.3.2}/docs/ALIGNMENT.md +23 -0
- python_codex-0.3.2/docs/RELEASE_0.3.2.md +36 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/packages/pycodex-ws/README.md +9 -1
- {python_codex-0.3.1 → python_codex-0.3.2}/packages/pycodex-ws/pyproject.toml +2 -2
- python_codex-0.3.2/pycodex/__main__.py +4 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/model.py +11 -2
- {python_codex-0.3.1 → python_codex-0.3.2}/pyproject.toml +1 -1
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/TESTS.md +12 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_doctor.py +16 -4
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_model.py +88 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_packaging.py +28 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/.github/workflows/test.yml +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/.gitignore +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/AGENTS.md +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/LICENSE +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/docs/CONTEXT.md +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/docs/RELEASE_0.3.0.md +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/docs/RUNTIME.md +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/docs/responses_server/README.md +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/packages/pycodex-ws/pycodex_ws_meta/__init__.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/__init__.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/agent.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/bootstrap.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/cli.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/compat.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/context.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/doctor.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/events.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/feishu_card.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/feishu_link.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/model_metadata.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/portable.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/portable_server.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/prompts/default_base_instructions.md +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/prompts/models.json +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/never.md +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/on_failure.md +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/on_request.md +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/on_request_rule_request_permission.md +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/unless_trusted.md +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/prompts/permissions/sandbox_mode/danger_full_access.md +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/prompts/permissions/sandbox_mode/read_only.md +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/prompts/permissions/sandbox_mode/workspace_write.md +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/protocol.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/runtime.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/runtime_services.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/__init__.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/agent_tool_schemas.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/apply_patch_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/base_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/clock_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/close_agent_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/code_mode_manager.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/exec_command_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/exec_runtime.js +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/exec_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/grep_files_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/ipython_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/list_dir_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/read_file_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/request_permissions_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/request_user_input_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/resume_agent_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/send_input_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/shell_command_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/shell_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/spawn_agent_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/unified_exec_manager.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/update_plan_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/view_image_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/wait_agent_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/wait_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/web_search_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/tools/write_stdin_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/utils/__init__.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/utils/async_bridge.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/utils/compactor.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/utils/debug.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/utils/dotenv.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/utils/event_helpers.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/utils/get_env.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/utils/image_utils.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/utils/random_ids.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/utils/session_persist.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/pycodex/utils/truncation.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/responses_server/__init__.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/responses_server/__main__.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/responses_server/app.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/responses_server/config.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/responses_server/messages_api.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/responses_server/payload_processors.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/responses_server/server.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/responses_server/session_store.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/responses_server/stream_router.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/responses_server/tools/__init__.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/responses_server/tools/custom_adapter.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/responses_server/tools/web_search.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/responses_server/trajectory_dump.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/__init__.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/compare_context_requests.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/compare_steer_request_bodies.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/compare_tool_schemas.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/conftest.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/fake_responses_server.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/fakes.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/responses_server/fake_chat_completions_server.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/responses_server/test_server.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/responses_server/test_trajectory_dump.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_agent.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_agent_state.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_async_bridge.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_builtin_tools.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_cli.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_compactor.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_context.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_events.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_fake_responses_server.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_feishu_card.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_feishu_link.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_feishu_oauth.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_ipython_tool.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_owned_workspace_server.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_portable.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_py36_syntax.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_runtime_state.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_session_backend.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tests/test_workspace_server.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tools/feishu_oauth.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/tools/sync_model_prompts.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/workspace_server/__init__.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/workspace_server/__main__.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/workspace_server/app.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/workspace_server/owned_process.py +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/workspace_server/workspace.html +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/workspace_server/workspaces.html +0 -0
- {python_codex-0.3.1 → python_codex-0.3.2}/workspace_server/workspaces.py +0 -0
|
@@ -117,6 +117,17 @@ jobs:
|
|
|
117
117
|
python -m build --outdir dist/pycodex-ws packages/pycodex-ws
|
|
118
118
|
python -m twine check dist/python-codex/* dist/pycodex-ws/*
|
|
119
119
|
|
|
120
|
+
- name: Smoke test installed wheels
|
|
121
|
+
run: |
|
|
122
|
+
python -m venv "$RUNNER_TEMP/pycodex-wheel"
|
|
123
|
+
"$RUNNER_TEMP/pycodex-wheel/bin/python" -m pip install \
|
|
124
|
+
dist/python-codex/*.whl dist/pycodex-ws/*.whl
|
|
125
|
+
cd "$RUNNER_TEMP"
|
|
126
|
+
"$RUNNER_TEMP/pycodex-wheel/bin/pycodex" --help
|
|
127
|
+
"$RUNNER_TEMP/pycodex-wheel/bin/pycodex-ws" --help
|
|
128
|
+
"$RUNNER_TEMP/pycodex-wheel/bin/python" -m pycodex --help
|
|
129
|
+
"$RUNNER_TEMP/pycodex-wheel/bin/python" -m workspace_server --help
|
|
130
|
+
|
|
120
131
|
- name: Upload distributions
|
|
121
132
|
uses: actions/upload-artifact@v4
|
|
122
133
|
with:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-codex
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: A minimal Python extraction of Codex's main agent loop
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.6.2
|
|
@@ -25,6 +25,8 @@ Description-Content-Type: text/markdown
|
|
|
25
25
|
|
|
26
26
|
English README. Chinese version: `README_ZH.md`
|
|
27
27
|
|
|
28
|
+
0.3.2 startup fixes: [release notes](docs/RELEASE_0.3.2.md).
|
|
29
|
+
|
|
28
30
|
0.3.0 release preparation and Python API migration: `docs/RELEASE_0.3.0.md`.
|
|
29
31
|
|
|
30
32
|
PyPI distributions:
|
|
@@ -60,11 +62,24 @@ Relevant Rust reference points:
|
|
|
60
62
|
Install the full package or the workspace-oriented alias:
|
|
61
63
|
|
|
62
64
|
```bash
|
|
63
|
-
pip install python-codex
|
|
64
|
-
pip install pycodex-ws
|
|
65
|
+
python3 -m pip install python-codex
|
|
66
|
+
python3 -m pip install pycodex-ws
|
|
65
67
|
```
|
|
66
68
|
|
|
67
|
-
|
|
69
|
+
Use Python 3.6.2 or newer. Both console commands are installed into that
|
|
70
|
+
interpreter's scripts directory. On a machine with multiple Python installations,
|
|
71
|
+
you can select the same interpreter explicitly for startup:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
python3 -m pycodex
|
|
75
|
+
python3 -m workspace_server --help
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
If `pycodex` is missing from `PATH` or resolves to an older installation, use these
|
|
79
|
+
module entry points. `python3 -m pip --version` shows which Python environment
|
|
80
|
+
received the installation.
|
|
81
|
+
|
|
82
|
+
For development from this repository, install dependencies first:
|
|
68
83
|
|
|
69
84
|
```bash
|
|
70
85
|
uv sync
|
|
@@ -200,6 +215,18 @@ from pycodex import ResponsesModelClient
|
|
|
200
215
|
client = ResponsesModelClient.from_codex_config()
|
|
201
216
|
```
|
|
202
217
|
|
|
218
|
+
`model_provider` is optional and defaults to `openai`. The built-in provider
|
|
219
|
+
does not require a `[model_providers.openai]` table: it uses
|
|
220
|
+
`https://api.openai.com/v1` and reads `OPENAI_API_KEY`. Set `openai_base_url` to
|
|
221
|
+
override this address. Explicit provider tables retain their configured
|
|
222
|
+
`base_url` and optional `env_key`; unknown provider names raise a configuration
|
|
223
|
+
error. The model still comes from `model` in the configuration or selected
|
|
224
|
+
profile.
|
|
225
|
+
|
|
226
|
+
Authentication currently uses API keys from environment variables or `.env`;
|
|
227
|
+
Codex desktop/CLI ChatGPT sign-in credentials in `auth.json` or the OS keychain
|
|
228
|
+
are not loaded.
|
|
229
|
+
|
|
203
230
|
The current implementation uses the streaming OpenAI-compatible `/responses`
|
|
204
231
|
endpoint. This path has already been validated against the local
|
|
205
232
|
`~/.codex/config.toml` setup.
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
English README. Chinese version: `README_ZH.md`
|
|
4
4
|
|
|
5
|
+
0.3.2 startup fixes: [release notes](docs/RELEASE_0.3.2.md).
|
|
6
|
+
|
|
5
7
|
0.3.0 release preparation and Python API migration: `docs/RELEASE_0.3.0.md`.
|
|
6
8
|
|
|
7
9
|
PyPI distributions:
|
|
@@ -37,11 +39,24 @@ Relevant Rust reference points:
|
|
|
37
39
|
Install the full package or the workspace-oriented alias:
|
|
38
40
|
|
|
39
41
|
```bash
|
|
40
|
-
pip install python-codex
|
|
41
|
-
pip install pycodex-ws
|
|
42
|
+
python3 -m pip install python-codex
|
|
43
|
+
python3 -m pip install pycodex-ws
|
|
42
44
|
```
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
Use Python 3.6.2 or newer. Both console commands are installed into that
|
|
47
|
+
interpreter's scripts directory. On a machine with multiple Python installations,
|
|
48
|
+
you can select the same interpreter explicitly for startup:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
python3 -m pycodex
|
|
52
|
+
python3 -m workspace_server --help
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
If `pycodex` is missing from `PATH` or resolves to an older installation, use these
|
|
56
|
+
module entry points. `python3 -m pip --version` shows which Python environment
|
|
57
|
+
received the installation.
|
|
58
|
+
|
|
59
|
+
For development from this repository, install dependencies first:
|
|
45
60
|
|
|
46
61
|
```bash
|
|
47
62
|
uv sync
|
|
@@ -177,6 +192,18 @@ from pycodex import ResponsesModelClient
|
|
|
177
192
|
client = ResponsesModelClient.from_codex_config()
|
|
178
193
|
```
|
|
179
194
|
|
|
195
|
+
`model_provider` is optional and defaults to `openai`. The built-in provider
|
|
196
|
+
does not require a `[model_providers.openai]` table: it uses
|
|
197
|
+
`https://api.openai.com/v1` and reads `OPENAI_API_KEY`. Set `openai_base_url` to
|
|
198
|
+
override this address. Explicit provider tables retain their configured
|
|
199
|
+
`base_url` and optional `env_key`; unknown provider names raise a configuration
|
|
200
|
+
error. The model still comes from `model` in the configuration or selected
|
|
201
|
+
profile.
|
|
202
|
+
|
|
203
|
+
Authentication currently uses API keys from environment variables or `.env`;
|
|
204
|
+
Codex desktop/CLI ChatGPT sign-in credentials in `auth.json` or the OS keychain
|
|
205
|
+
are not loaded.
|
|
206
|
+
|
|
180
207
|
The current implementation uses the streaming OpenAI-compatible `/responses`
|
|
181
208
|
endpoint. This path has already been validated against the local
|
|
182
209
|
`~/.codex/config.toml` setup.
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
中文 README。English version: `README.md`
|
|
4
4
|
|
|
5
|
+
0.3.2 启动修复:[发布说明](docs/RELEASE_0.3.2.md)。
|
|
6
|
+
|
|
5
7
|
0.3.0 发版准备与 Python API 迁移说明:`docs/RELEASE_0.3.0.md`。
|
|
6
8
|
|
|
7
9
|
PyPI distributions:
|
|
@@ -34,11 +36,22 @@ Import 路径仍保持 `pycodex`;CLI 命令为 `pycodex` 和 `pycodex-ws`。
|
|
|
34
36
|
安装完整包或 workspace 安装别名:
|
|
35
37
|
|
|
36
38
|
```bash
|
|
37
|
-
pip install python-codex
|
|
38
|
-
pip install pycodex-ws
|
|
39
|
+
python3 -m pip install python-codex
|
|
40
|
+
python3 -m pip install pycodex-ws
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
要求 Python 3.6.2 或更新版本。两个命令会安装到该解释器的 scripts 目录。
|
|
44
|
+
在同时存在 Python 2/3 或多套 Python 的机器上,可以明确使用安装时的解释器启动:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
python3 -m pycodex
|
|
48
|
+
python3 -m workspace_server --help
|
|
39
49
|
```
|
|
40
50
|
|
|
41
|
-
|
|
51
|
+
如果 `PATH` 中找不到 `pycodex`,或者命中了旧安装,使用以上模块入口即可。
|
|
52
|
+
`python3 -m pip --version` 可确认包安装到了哪个 Python 环境。
|
|
53
|
+
|
|
54
|
+
从本仓库开发时,先安装依赖:
|
|
42
55
|
|
|
43
56
|
```bash
|
|
44
57
|
uv sync
|
|
@@ -188,6 +201,16 @@ from pycodex import ResponsesModelClient
|
|
|
188
201
|
client = ResponsesModelClient.from_codex_config()
|
|
189
202
|
```
|
|
190
203
|
|
|
204
|
+
`model_provider` 可省略,默认使用 `openai`。内置 provider 不要求
|
|
205
|
+
`[model_providers.openai]` 表,默认地址为 `https://api.openai.com/v1`,
|
|
206
|
+
从 `OPENAI_API_KEY` 读取密钥;可用 `openai_base_url` 覆盖地址。
|
|
207
|
+
显式 provider 表仍使用其配置的 `base_url` 和可选 `env_key`,
|
|
208
|
+
未知 provider 名称会报明确的配置错误。模型名仍从配置或所选 profile 的
|
|
209
|
+
`model` 字段读取。
|
|
210
|
+
|
|
211
|
+
当前认证通过环境变量或 `.env` 中的 API key 完成,尚不读取官方 Codex
|
|
212
|
+
桌面端/CLI 保存在 `auth.json` 或系统钥匙串中的 ChatGPT 登录凭据。
|
|
213
|
+
|
|
191
214
|
当前实现走 OpenAI-compatible Responses API 的流式 `/responses` 接口。这个点
|
|
192
215
|
已经用本机 `~/.codex/config.toml` 做过联调验证。
|
|
193
216
|
|
|
@@ -48,6 +48,29 @@ Tool-specific status uses two inputs:
|
|
|
48
48
|
- proxy captures of actual upstream Codex and `pycodex` requests/results
|
|
49
49
|
- source inspection against the latest upstream tool specifications
|
|
50
50
|
|
|
51
|
+
## Startup and provider defaults (2026-10-10)
|
|
52
|
+
|
|
53
|
+
Provider selection uses `openai` when `model_provider` is omitted, matching
|
|
54
|
+
[`config/mod.rs` at the 0.153.4 source baseline](https://github.com/openai/codex/blob/3d2ee51ca2d5db578f328aa75e20aa22c0197c9a/codex-rs/core/src/config/mod.rs).
|
|
55
|
+
The built-in OpenAI provider needs no user-defined provider table. For pycodex's
|
|
56
|
+
API-key transport, its default address is `https://api.openai.com/v1`, with the
|
|
57
|
+
top-level/profile `openai_base_url` override and `OPENAI_API_KEY` environment
|
|
58
|
+
variable. Custom providers must be selected explicitly; an unknown provider
|
|
59
|
+
raises a descriptive configuration error.
|
|
60
|
+
|
|
61
|
+
Two local boundaries remain: explicit provider tables retain their existing
|
|
62
|
+
pycodex override behavior, and authentication reads environment API keys rather
|
|
63
|
+
than Codex's stored ChatGPT credentials. `model` must still be specified in the
|
|
64
|
+
configuration or selected profile. This change aligns provider selection,
|
|
65
|
+
not the full upstream authentication or model-discovery surface.
|
|
66
|
+
|
|
67
|
+
The package also supports `python3 -m pycodex`, alongside the existing
|
|
68
|
+
`python3 -m workspace_server`, so installation and startup can use the same
|
|
69
|
+
interpreter on hosts with multiple Python installations. Console scripts remain
|
|
70
|
+
owned by `python-codex` and are generated by the installer. The publish workflow
|
|
71
|
+
installs the built wheels into a fresh environment and checks both console and
|
|
72
|
+
module entry points outside the source checkout before uploading artifacts.
|
|
73
|
+
|
|
51
74
|
## Context audit (2026-09-23)
|
|
52
75
|
|
|
53
76
|
This audit uses installed `codex-cli 0.153.4` and its matching
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# 0.3.2 release notes
|
|
2
|
+
|
|
3
|
+
Both `python-codex` and `pycodex-ws` use version **0.3.2**. The workspace
|
|
4
|
+
metapackage depends on exactly `python-codex==0.3.2`; publish the core package
|
|
5
|
+
first.
|
|
6
|
+
|
|
7
|
+
## Startup fixes
|
|
8
|
+
|
|
9
|
+
- Codex configurations may omit `model_provider`. In that case, use the built-in
|
|
10
|
+
`openai` provider without requiring a `[model_providers.openai]` table.
|
|
11
|
+
Its default API address is `https://api.openai.com/v1`, with
|
|
12
|
+
`openai_base_url` available as an override and `OPENAI_API_KEY` supplying
|
|
13
|
+
authentication. Existing explicit provider tables keep their behavior;
|
|
14
|
+
unknown provider names produce a descriptive configuration error.
|
|
15
|
+
- Add `python3 -m pycodex` so installation and startup can explicitly use the
|
|
16
|
+
same interpreter on hosts with multiple Python installations.
|
|
17
|
+
The browser frontend remains available through
|
|
18
|
+
`python3 -m workspace_server` or the `pycodex-ws` command.
|
|
19
|
+
- Check installed wheel entry points in a fresh environment before publication,
|
|
20
|
+
covering both console scripts and both module entry points outside the source
|
|
21
|
+
checkout. Add provider-selection and module-exit-status regressions.
|
|
22
|
+
|
|
23
|
+
The configuration still needs `model`, either at the top level or in the
|
|
24
|
+
selected profile. Authentication uses environment API keys or `.env`;
|
|
25
|
+
stored ChatGPT sign-in credentials from the official Codex CLI/desktop app
|
|
26
|
+
are not loaded.
|
|
27
|
+
|
|
28
|
+
## Upgrade
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
python3 -m pip install --upgrade pycodex-ws==0.3.2
|
|
32
|
+
python3 -m pycodex
|
|
33
|
+
python3 -m workspace_server --help
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`python3 -m pycodex-ws` is not a module entry point.
|
|
@@ -4,10 +4,18 @@
|
|
|
4
4
|
[`python-codex`](https://pypi.org/project/python-codex/).
|
|
5
5
|
|
|
6
6
|
```bash
|
|
7
|
-
pip install pycodex-ws
|
|
7
|
+
python3 -m pip install pycodex-ws
|
|
8
8
|
pycodex-ws --help
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
Requires Python 3.6.2 or newer. With multiple Python installations, use the
|
|
12
|
+
installing interpreter to launch either frontend directly:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
python3 -m workspace_server --help
|
|
16
|
+
python3 -m pycodex --help
|
|
17
|
+
```
|
|
18
|
+
|
|
11
19
|
This distribution intentionally contains only package metadata. It depends on
|
|
12
20
|
the exact matching `python-codex` version, which provides the `workspace_server`
|
|
13
21
|
implementation and the `pycodex-ws` console script.
|
|
@@ -4,12 +4,12 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pycodex-ws"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.2"
|
|
8
8
|
description = "Browser workspace install alias for python-codex"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.6.2"
|
|
11
11
|
dependencies = [
|
|
12
|
-
"python-codex==0.3.
|
|
12
|
+
"python-codex==0.3.2",
|
|
13
13
|
]
|
|
14
14
|
|
|
15
15
|
[tool.hatch.build.targets.wheel]
|
|
@@ -107,8 +107,17 @@ class ResponsesProviderConfig:
|
|
|
107
107
|
raise ValueError(f"unknown Codex profile: {profile}")
|
|
108
108
|
selected.update(overrides)
|
|
109
109
|
|
|
110
|
-
provider_name = selected
|
|
111
|
-
provider = data
|
|
110
|
+
provider_name = selected.get("model_provider", "openai")
|
|
111
|
+
provider = data.get("model_providers", {}).get(provider_name)
|
|
112
|
+
if provider is None:
|
|
113
|
+
if provider_name != "openai":
|
|
114
|
+
raise ValueError(f"unknown Codex model provider: {provider_name}")
|
|
115
|
+
provider = {
|
|
116
|
+
"base_url": (
|
|
117
|
+
selected.get("openai_base_url") or "https://api.openai.com/v1"
|
|
118
|
+
),
|
|
119
|
+
"env_key": "OPENAI_API_KEY",
|
|
120
|
+
}
|
|
112
121
|
wire_api = provider.get("wire_api", "responses")
|
|
113
122
|
if wire_api != "responses":
|
|
114
123
|
raise ValueError(f"unsupported wire_api for Python client: {wire_api}")
|
|
@@ -22,9 +22,21 @@
|
|
|
22
22
|
- 如果已推送的 tag 在 CI 初始化阶段失败,修复 workflow 后应从包含修复的
|
|
23
23
|
branch 手动运行 `publish`,并选择正确的 `repository`。直接重跑旧的
|
|
24
24
|
tag workflow 仍使用旧提交;不要为了 CI 修复强制移动已公开的 tag。
|
|
25
|
+
- `publish.yml` 构建两个 wheel 后,在新 venv 中通过 pip 安装 `pycodex-ws`
|
|
26
|
+
及同批 `python-codex`,离开源码目录后检查两个 console script 和
|
|
27
|
+
`python -m pycodex` / `python -m workspace_server`,成功后才上传发布产物。
|
|
28
|
+
`test_packaging.py` 另覆盖模块入口的帮助、doctor 分发及参数错误退出码。
|
|
25
29
|
|
|
26
30
|
## 自动化测试
|
|
27
31
|
|
|
32
|
+
### Provider 配置
|
|
33
|
+
|
|
34
|
+
- `test_model.py` 覆盖省略 `model_provider` / provider 表时默认使用内置
|
|
35
|
+
`openai`、显式选择内置 provider、profile 选择及 `openai_base_url` 覆盖、
|
|
36
|
+
保留显式 provider 表语义,以及未知 provider 的明确错误。
|
|
37
|
+
- `test_doctor.py` 用本地 Responses fixture 验证省略 provider 的配置可完成
|
|
38
|
+
配置、API key、连通性和模型请求检查,不访问真实模型服务。
|
|
39
|
+
|
|
28
40
|
### VS Code 前端
|
|
29
41
|
|
|
30
42
|
- `extensions/vscode` 使用 Node 22+,运行
|
|
@@ -30,9 +30,11 @@ def _write_config(
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
@pytest.mark.asyncio
|
|
33
|
+
@pytest.mark.parametrize("builtin_openai", [False, True])
|
|
33
34
|
async def test_collect_doctor_report_succeeds_with_live_check(
|
|
34
35
|
tmp_path,
|
|
35
36
|
monkeypatch,
|
|
37
|
+
builtin_openai,
|
|
36
38
|
) -> "None":
|
|
37
39
|
capture_store = CaptureStore(tmp_path / "capture")
|
|
38
40
|
httpd = ThreadingHTTPServer(
|
|
@@ -43,8 +45,18 @@ async def test_collect_doctor_report_succeeds_with_live_check(
|
|
|
43
45
|
server_thread.start()
|
|
44
46
|
|
|
45
47
|
config_path = tmp_path / "config.toml"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
base_url = f"http://127.0.0.1:{httpd.server_port}/v1"
|
|
49
|
+
if builtin_openai:
|
|
50
|
+
config_path.write_text(
|
|
51
|
+
'model = "gpt-5.4"\n'
|
|
52
|
+
f'openai_base_url = "{base_url}"\n',
|
|
53
|
+
encoding="utf-8",
|
|
54
|
+
)
|
|
55
|
+
env_key = "OPENAI_API_KEY"
|
|
56
|
+
else:
|
|
57
|
+
_write_config(config_path, base_url)
|
|
58
|
+
env_key = "DOCTOR_KEY"
|
|
59
|
+
monkeypatch.setenv(env_key, "dummy-key")
|
|
48
60
|
|
|
49
61
|
try:
|
|
50
62
|
report = await collect_doctor_report(
|
|
@@ -58,8 +70,8 @@ async def test_collect_doctor_report_succeeds_with_live_check(
|
|
|
58
70
|
httpd.server_close()
|
|
59
71
|
|
|
60
72
|
assert report.ok is True
|
|
61
|
-
assert report.provider_name == "neo"
|
|
62
|
-
assert report.api_key_env ==
|
|
73
|
+
assert report.provider_name == ("openai" if builtin_openai else "neo")
|
|
74
|
+
assert report.api_key_env == env_key
|
|
63
75
|
assert report.api_key_loaded is True
|
|
64
76
|
assert report.live_output_text == "OK"
|
|
65
77
|
assert {check.name for check in report.checks} == {
|
|
@@ -268,6 +268,94 @@ def test_provider_config_reads_codex_style_config_with_profile_override(
|
|
|
268
268
|
assert provider.beta_features_header == "guardian_approval"
|
|
269
269
|
|
|
270
270
|
|
|
271
|
+
@pytest.mark.parametrize("selection", ["", 'model_provider = "openai"\n'])
|
|
272
|
+
def test_provider_config_defaults_to_builtin_openai(
|
|
273
|
+
tmp_path, monkeypatch, selection
|
|
274
|
+
) -> "None":
|
|
275
|
+
config_path = tmp_path / "config.toml"
|
|
276
|
+
config_path.write_text(
|
|
277
|
+
'model = "gpt-5.4"\n' + selection,
|
|
278
|
+
encoding="utf-8",
|
|
279
|
+
)
|
|
280
|
+
monkeypatch.setenv("OPENAI_API_KEY", "test-key")
|
|
281
|
+
|
|
282
|
+
provider = ResponsesProviderConfig.from_codex_config(config_path)
|
|
283
|
+
client = ResponsesModelClient(provider)
|
|
284
|
+
|
|
285
|
+
assert provider.model == "gpt-5.4"
|
|
286
|
+
assert provider.provider_name == "openai"
|
|
287
|
+
assert client.responses_url() == "https://api.openai.com/v1/responses"
|
|
288
|
+
assert provider.api_key_env == "OPENAI_API_KEY"
|
|
289
|
+
assert provider.api_key() == "test-key"
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def test_provider_config_uses_openai_default_with_unselected_custom_provider(
|
|
293
|
+
tmp_path,
|
|
294
|
+
) -> "None":
|
|
295
|
+
config_path = tmp_path / "config.toml"
|
|
296
|
+
config_path.write_text(
|
|
297
|
+
'model = "gpt-5.4"\n'
|
|
298
|
+
"[model_providers.local]\n"
|
|
299
|
+
'base_url = "http://localhost:8000/v1"\n',
|
|
300
|
+
encoding="utf-8",
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
provider = ResponsesProviderConfig.from_codex_config(config_path)
|
|
304
|
+
|
|
305
|
+
assert provider.provider_name == "openai"
|
|
306
|
+
assert provider.base_url == "https://api.openai.com/v1"
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def test_provider_config_profile_selects_builtin_openai(tmp_path) -> "None":
|
|
310
|
+
config_path = tmp_path / "config.toml"
|
|
311
|
+
config_path.write_text(
|
|
312
|
+
'model = "base-model"\n'
|
|
313
|
+
'model_provider = "local"\n'
|
|
314
|
+
"[model_providers.local]\n"
|
|
315
|
+
'base_url = "http://localhost:8000/v1"\n'
|
|
316
|
+
"[profiles.openai]\n"
|
|
317
|
+
'model = "gpt-5.4"\n'
|
|
318
|
+
'model_provider = "openai"\n'
|
|
319
|
+
'openai_base_url = "https://example.invalid/v1"\n',
|
|
320
|
+
encoding="utf-8",
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
provider = ResponsesProviderConfig.from_codex_config(config_path, "openai")
|
|
324
|
+
|
|
325
|
+
assert provider.model == "gpt-5.4"
|
|
326
|
+
assert provider.provider_name == "openai"
|
|
327
|
+
assert provider.base_url == "https://example.invalid/v1"
|
|
328
|
+
assert provider.api_key_env == "OPENAI_API_KEY"
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def test_provider_config_preserves_explicit_openai_provider(tmp_path) -> "None":
|
|
332
|
+
config_path = tmp_path / "config.toml"
|
|
333
|
+
config_path.write_text(
|
|
334
|
+
'model = "local-model"\n'
|
|
335
|
+
'model_provider = "openai"\n'
|
|
336
|
+
"[model_providers.openai]\n"
|
|
337
|
+
'base_url = "http://localhost:8000/v1"\n',
|
|
338
|
+
encoding="utf-8",
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
provider = ResponsesProviderConfig.from_codex_config(config_path)
|
|
342
|
+
|
|
343
|
+
assert provider.base_url == "http://localhost:8000/v1"
|
|
344
|
+
assert provider.api_key_env is None
|
|
345
|
+
assert provider.api_key() is None
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
def test_provider_config_rejects_unknown_provider(tmp_path) -> "None":
|
|
349
|
+
config_path = tmp_path / "config.toml"
|
|
350
|
+
config_path.write_text(
|
|
351
|
+
'model = "gpt-5.4"\nmodel_provider = "missing"\n',
|
|
352
|
+
encoding="utf-8",
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
with pytest.raises(ValueError, match="unknown Codex model provider: missing"):
|
|
356
|
+
ResponsesProviderConfig.from_codex_config(config_path)
|
|
357
|
+
|
|
358
|
+
|
|
271
359
|
def test_build_payload_omits_tool_choice_when_no_tools() -> "None":
|
|
272
360
|
client = ResponsesModelClient(
|
|
273
361
|
ResponsesProviderConfig(
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import subprocess
|
|
3
|
+
import sys
|
|
1
4
|
from pathlib import Path
|
|
2
5
|
|
|
3
6
|
import pytest
|
|
@@ -30,6 +33,31 @@ def test_workspace_distribution_tracks_core_version() -> "None":
|
|
|
30
33
|
assert core["project"]["scripts"]["pycodex-ws"] == "workspace_server:main"
|
|
31
34
|
|
|
32
35
|
|
|
36
|
+
@pytest.mark.parametrize(
|
|
37
|
+
("arguments", "exit_code", "output"),
|
|
38
|
+
[
|
|
39
|
+
(["--help"], 0, "usage: pycodex "),
|
|
40
|
+
(["doctor", "--help"], 0, "usage: pycodex doctor "),
|
|
41
|
+
(["--unknown-option"], 2, "unrecognized arguments: --unknown-option"),
|
|
42
|
+
],
|
|
43
|
+
)
|
|
44
|
+
def test_python_module_entrypoint(tmp_path, arguments, exit_code, output):
|
|
45
|
+
environment = dict(os.environ)
|
|
46
|
+
environment["PYTHONPATH"] = str(ROOT)
|
|
47
|
+
result = subprocess.run(
|
|
48
|
+
[sys.executable, "-m", "pycodex"] + arguments,
|
|
49
|
+
cwd=str(tmp_path),
|
|
50
|
+
env=environment,
|
|
51
|
+
stdout=subprocess.PIPE,
|
|
52
|
+
stderr=subprocess.PIPE,
|
|
53
|
+
universal_newlines=True,
|
|
54
|
+
timeout=15,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
assert result.returncode == exit_code, result.stderr
|
|
58
|
+
assert output in result.stdout + result.stderr
|
|
59
|
+
|
|
60
|
+
|
|
33
61
|
@pytest.mark.parametrize("filename", ["test.yml", "publish.yml"])
|
|
34
62
|
def test_python36_workflows_install_yaml_dependency(filename):
|
|
35
63
|
path = ROOT / ".github" / "workflows" / filename
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_codex-0.3.1 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/never.md
RENAMED
|
File without changes
|
{python_codex-0.3.1 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/on_failure.md
RENAMED
|
File without changes
|
{python_codex-0.3.1 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/on_request.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_codex-0.3.1 → python_codex-0.3.2}/pycodex/prompts/permissions/sandbox_mode/read_only.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_codex-0.3.1 → python_codex-0.3.2}/tests/responses_server/fake_chat_completions_server.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|