python-codex 0.3.0__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.0 → python_codex-0.3.2}/.github/workflows/publish.yml +11 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/PKG-INFO +70 -4
- {python_codex-0.3.0 → python_codex-0.3.2}/README.md +69 -3
- {python_codex-0.3.0 → python_codex-0.3.2}/README_ZH.md +53 -3
- {python_codex-0.3.0 → 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.0 → python_codex-0.3.2}/docs/RUNTIME.md +92 -2
- {python_codex-0.3.0 → python_codex-0.3.2}/docs/responses_server/README.md +15 -1
- {python_codex-0.3.0 → python_codex-0.3.2}/packages/pycodex-ws/README.md +9 -1
- {python_codex-0.3.0 → 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.0 → python_codex-0.3.2}/pycodex/model.py +11 -2
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/models.json +176 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pyproject.toml +2 -2
- {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/app.py +1 -5
- {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/stream_router.py +108 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/TESTS.md +48 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/responses_server/test_server.py +257 -2
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_doctor.py +16 -4
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_model.py +398 -6
- python_codex-0.3.2/tests/test_owned_workspace_server.py +145 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_packaging.py +28 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_workspace_server.py +110 -12
- {python_codex-0.3.0 → python_codex-0.3.2}/workspace_server/app.py +4 -2
- python_codex-0.3.2/workspace_server/owned_process.py +27 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/workspace_server/workspace.html +2 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/workspace_server/workspaces.py +27 -28
- {python_codex-0.3.0 → python_codex-0.3.2}/.github/workflows/test.yml +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/.gitignore +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/AGENTS.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/LICENSE +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/docs/CONTEXT.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/docs/RELEASE_0.3.0.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/packages/pycodex-ws/pycodex_ws_meta/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/agent.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/bootstrap.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/cli.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/compat.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/context.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/doctor.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/events.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/feishu_card.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/feishu_link.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/model_metadata.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/portable.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/portable_server.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/default_base_instructions.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/never.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/on_failure.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/on_request.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/on_request_rule_request_permission.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/unless_trusted.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/sandbox_mode/danger_full_access.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/sandbox_mode/read_only.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/sandbox_mode/workspace_write.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/protocol.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/runtime.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/runtime_services.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/agent_tool_schemas.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/apply_patch_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/base_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/clock_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/close_agent_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/code_mode_manager.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/exec_command_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/exec_runtime.js +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/exec_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/grep_files_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/ipython_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/list_dir_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/read_file_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/request_permissions_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/request_user_input_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/resume_agent_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/send_input_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/shell_command_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/shell_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/spawn_agent_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/unified_exec_manager.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/update_plan_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/view_image_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/wait_agent_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/wait_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/web_search_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/write_stdin_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/async_bridge.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/compactor.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/debug.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/dotenv.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/event_helpers.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/get_env.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/image_utils.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/random_ids.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/session_persist.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/truncation.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/__main__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/config.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/messages_api.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/payload_processors.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/server.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/session_store.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/tools/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/tools/custom_adapter.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/tools/web_search.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/trajectory_dump.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/compare_context_requests.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/compare_steer_request_bodies.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/compare_tool_schemas.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/conftest.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/fake_responses_server.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/fakes.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/responses_server/fake_chat_completions_server.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/responses_server/test_trajectory_dump.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_agent.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_agent_state.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_async_bridge.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_builtin_tools.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_cli.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_compactor.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_context.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_events.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_fake_responses_server.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_feishu_card.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_feishu_link.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_feishu_oauth.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_ipython_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_portable.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_py36_syntax.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_runtime_state.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_session_backend.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tools/feishu_oauth.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/tools/sync_model_prompts.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/workspace_server/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/workspace_server/__main__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.2}/workspace_server/workspaces.html +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
|
|
67
|
+
```
|
|
68
|
+
|
|
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
|
|
65
76
|
```
|
|
66
77
|
|
|
67
|
-
|
|
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
|
|
@@ -77,6 +92,32 @@ uv run pycodex "Reply with exactly OK."
|
|
|
77
92
|
uv run pycodex
|
|
78
93
|
```
|
|
79
94
|
|
|
95
|
+
A VS Code frontend is available in [`extensions/vscode`](extensions/vscode/README.md).
|
|
96
|
+
It reuses an existing `python-codex>=0.3.1` installation. On first use, missing
|
|
97
|
+
or older backends are installed/upgraded with pip in the selected Python
|
|
98
|
+
environment on the workspace host; compatible versions need no network check.
|
|
99
|
+
It starts a dedicated `pycodex-ws` workspace on the project's host and opens a
|
|
100
|
+
chat in the left sidebar using VS Code's stable WebviewView API. Each chat
|
|
101
|
+
creates a workspace session with no code context attached. You can insert code
|
|
102
|
+
from editors, diffs or file-tree selections as editable tokens among your words.
|
|
103
|
+
Each token expands at its position when you send the message.
|
|
104
|
+
Previous chats fold into live status entries; each can be
|
|
105
|
+
reopened or closed, and models can be changed with `/model`.
|
|
106
|
+
Remote workspaces run Python on the remote host. A stdin pipe ties each backend
|
|
107
|
+
to its extension host; normal closure or host failure triggers draining and exit.
|
|
108
|
+
`pycodex-ws` always shuts down on stdin EOF, after accepted work finishes.
|
|
109
|
+
Keep stdin open while running the server; redirecting it from `/dev/null`
|
|
110
|
+
causes the server to shut down.
|
|
111
|
+
Workspace configuration uses a temporary JSON file passed to `--workspace-config`;
|
|
112
|
+
normal backend exit removes the temporary directory.
|
|
113
|
+
The extension uses that host's `~/.codex/config.toml` by default.
|
|
114
|
+
The chat settings menu selects a project venv or another Python interpreter
|
|
115
|
+
and edits the Codex profile. Changes offer a window reload when a backend is
|
|
116
|
+
already running.
|
|
117
|
+
Its context ring shows the same remaining budget and usage details as the
|
|
118
|
+
workspace web frontend.
|
|
119
|
+
See the extension README for building a VSIX, server setup and Remote SSH usage.
|
|
120
|
+
|
|
80
121
|
## Design Tradeoffs
|
|
81
122
|
|
|
82
123
|
This is not a 1:1 port of the Rust implementation. The current goal is a
|
|
@@ -111,6 +152,7 @@ nailing the core tool-augmented reasoning loop first.
|
|
|
111
152
|
- `pycodex/tools/`: concrete tool implementations
|
|
112
153
|
- `pycodex/agent.py`: inner turn loop
|
|
113
154
|
- `pycodex/runtime.py`: session commands, submission queues and frontend event subscriptions
|
|
155
|
+
- `extensions/vscode/`: VS Code chat frontend using the workspace HTTP API
|
|
114
156
|
- `tests/test_agent.py`: core behavior tests
|
|
115
157
|
|
|
116
158
|
## Current Alignment Status
|
|
@@ -158,6 +200,9 @@ Chained failures also retain `stream_error_cause_type` and, for HTTP errors,
|
|
|
158
200
|
`stream_error_http_status`; exception messages, headers and URLs are not
|
|
159
201
|
copied into these diagnostic fields.
|
|
160
202
|
|
|
203
|
+
Downstream errors include elapsed time, timeout, failure stage, response-header
|
|
204
|
+
and first-chunk timing, and received chunk count directly in the error message.
|
|
205
|
+
|
|
161
206
|
## Live Model Integration
|
|
162
207
|
|
|
163
208
|
If this machine already has a Codex CLI configuration, `pycodex` can reuse the
|
|
@@ -170,6 +215,18 @@ from pycodex import ResponsesModelClient
|
|
|
170
215
|
client = ResponsesModelClient.from_codex_config()
|
|
171
216
|
```
|
|
172
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
|
+
|
|
173
230
|
The current implementation uses the streaming OpenAI-compatible `/responses`
|
|
174
231
|
endpoint. This path has already been validated against the local
|
|
175
232
|
`~/.codex/config.toml` setup.
|
|
@@ -330,6 +387,15 @@ Current behavior:
|
|
|
330
387
|
reasoning, retries the same downstream request once, and only then emits
|
|
331
388
|
`response.failed` with `type = "model_output_invalid"` if the retry is still
|
|
332
389
|
reasoning-only
|
|
390
|
+
- malformed JSON in ordinary downstream function-call arguments is detected by
|
|
391
|
+
`responses_server` and returned as `response.failed` with `type = "server_error"`;
|
|
392
|
+
the client's existing `stream_max_retries` policy retries the current request
|
|
393
|
+
before its local tools execute
|
|
394
|
+
- downstream connection failures before HTTP response headers or during SSE
|
|
395
|
+
reading are converted to `response.failed` for provider retries. Downstream
|
|
396
|
+
requests honor environment proxies; see the
|
|
397
|
+
[connection troubleshooting notes](docs/responses_server/README.md#连接排查)
|
|
398
|
+
for `RemoteDisconnected` and proxy bypass configuration
|
|
333
399
|
- standalone `responses_server` now also supports downstream `/v1/messages`
|
|
334
400
|
backends via `--outcomming-api messages`, while keeping the internal
|
|
335
401
|
canonical request/route logic in chat-completions shape
|
|
@@ -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
|
|
44
|
+
```
|
|
45
|
+
|
|
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
|
|
42
53
|
```
|
|
43
54
|
|
|
44
|
-
|
|
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
|
|
@@ -54,6 +69,32 @@ uv run pycodex "Reply with exactly OK."
|
|
|
54
69
|
uv run pycodex
|
|
55
70
|
```
|
|
56
71
|
|
|
72
|
+
A VS Code frontend is available in [`extensions/vscode`](extensions/vscode/README.md).
|
|
73
|
+
It reuses an existing `python-codex>=0.3.1` installation. On first use, missing
|
|
74
|
+
or older backends are installed/upgraded with pip in the selected Python
|
|
75
|
+
environment on the workspace host; compatible versions need no network check.
|
|
76
|
+
It starts a dedicated `pycodex-ws` workspace on the project's host and opens a
|
|
77
|
+
chat in the left sidebar using VS Code's stable WebviewView API. Each chat
|
|
78
|
+
creates a workspace session with no code context attached. You can insert code
|
|
79
|
+
from editors, diffs or file-tree selections as editable tokens among your words.
|
|
80
|
+
Each token expands at its position when you send the message.
|
|
81
|
+
Previous chats fold into live status entries; each can be
|
|
82
|
+
reopened or closed, and models can be changed with `/model`.
|
|
83
|
+
Remote workspaces run Python on the remote host. A stdin pipe ties each backend
|
|
84
|
+
to its extension host; normal closure or host failure triggers draining and exit.
|
|
85
|
+
`pycodex-ws` always shuts down on stdin EOF, after accepted work finishes.
|
|
86
|
+
Keep stdin open while running the server; redirecting it from `/dev/null`
|
|
87
|
+
causes the server to shut down.
|
|
88
|
+
Workspace configuration uses a temporary JSON file passed to `--workspace-config`;
|
|
89
|
+
normal backend exit removes the temporary directory.
|
|
90
|
+
The extension uses that host's `~/.codex/config.toml` by default.
|
|
91
|
+
The chat settings menu selects a project venv or another Python interpreter
|
|
92
|
+
and edits the Codex profile. Changes offer a window reload when a backend is
|
|
93
|
+
already running.
|
|
94
|
+
Its context ring shows the same remaining budget and usage details as the
|
|
95
|
+
workspace web frontend.
|
|
96
|
+
See the extension README for building a VSIX, server setup and Remote SSH usage.
|
|
97
|
+
|
|
57
98
|
## Design Tradeoffs
|
|
58
99
|
|
|
59
100
|
This is not a 1:1 port of the Rust implementation. The current goal is a
|
|
@@ -88,6 +129,7 @@ nailing the core tool-augmented reasoning loop first.
|
|
|
88
129
|
- `pycodex/tools/`: concrete tool implementations
|
|
89
130
|
- `pycodex/agent.py`: inner turn loop
|
|
90
131
|
- `pycodex/runtime.py`: session commands, submission queues and frontend event subscriptions
|
|
132
|
+
- `extensions/vscode/`: VS Code chat frontend using the workspace HTTP API
|
|
91
133
|
- `tests/test_agent.py`: core behavior tests
|
|
92
134
|
|
|
93
135
|
## Current Alignment Status
|
|
@@ -135,6 +177,9 @@ Chained failures also retain `stream_error_cause_type` and, for HTTP errors,
|
|
|
135
177
|
`stream_error_http_status`; exception messages, headers and URLs are not
|
|
136
178
|
copied into these diagnostic fields.
|
|
137
179
|
|
|
180
|
+
Downstream errors include elapsed time, timeout, failure stage, response-header
|
|
181
|
+
and first-chunk timing, and received chunk count directly in the error message.
|
|
182
|
+
|
|
138
183
|
## Live Model Integration
|
|
139
184
|
|
|
140
185
|
If this machine already has a Codex CLI configuration, `pycodex` can reuse the
|
|
@@ -147,6 +192,18 @@ from pycodex import ResponsesModelClient
|
|
|
147
192
|
client = ResponsesModelClient.from_codex_config()
|
|
148
193
|
```
|
|
149
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
|
+
|
|
150
207
|
The current implementation uses the streaming OpenAI-compatible `/responses`
|
|
151
208
|
endpoint. This path has already been validated against the local
|
|
152
209
|
`~/.codex/config.toml` setup.
|
|
@@ -307,6 +364,15 @@ Current behavior:
|
|
|
307
364
|
reasoning, retries the same downstream request once, and only then emits
|
|
308
365
|
`response.failed` with `type = "model_output_invalid"` if the retry is still
|
|
309
366
|
reasoning-only
|
|
367
|
+
- malformed JSON in ordinary downstream function-call arguments is detected by
|
|
368
|
+
`responses_server` and returned as `response.failed` with `type = "server_error"`;
|
|
369
|
+
the client's existing `stream_max_retries` policy retries the current request
|
|
370
|
+
before its local tools execute
|
|
371
|
+
- downstream connection failures before HTTP response headers or during SSE
|
|
372
|
+
reading are converted to `response.failed` for provider retries. Downstream
|
|
373
|
+
requests honor environment proxies; see the
|
|
374
|
+
[connection troubleshooting notes](docs/responses_server/README.md#连接排查)
|
|
375
|
+
for `RemoteDisconnected` and proxy bypass configuration
|
|
310
376
|
- standalone `responses_server` now also supports downstream `/v1/messages`
|
|
311
377
|
backends via `--outcomming-api messages`, while keeping the internal
|
|
312
378
|
canonical request/route logic in chat-completions shape
|
|
@@ -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
|
|
39
41
|
```
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
要求 Python 3.6.2 或更新版本。两个命令会安装到该解释器的 scripts 目录。
|
|
44
|
+
在同时存在 Python 2/3 或多套 Python 的机器上,可以明确使用安装时的解释器启动:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
python3 -m pycodex
|
|
48
|
+
python3 -m workspace_server --help
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
如果 `PATH` 中找不到 `pycodex`,或者命中了旧安装,使用以上模块入口即可。
|
|
52
|
+
`python3 -m pip --version` 可确认包安装到了哪个 Python 环境。
|
|
53
|
+
|
|
54
|
+
从本仓库开发时,先安装依赖:
|
|
42
55
|
|
|
43
56
|
```bash
|
|
44
57
|
uv sync
|
|
@@ -82,6 +95,7 @@ uv run pycodex
|
|
|
82
95
|
- `pycodex/tools/`:具体工具实现
|
|
83
96
|
- `pycodex/agent.py`:主循环
|
|
84
97
|
- `pycodex/runtime.py`:统一会话命令、提交队列和前端事件订阅
|
|
98
|
+
- `extensions/vscode/`:通过 workspace HTTP API 接入的 VS Code 聊天前端
|
|
85
99
|
- `tests/test_agent.py`:核心行为测试
|
|
86
100
|
|
|
87
101
|
## 当前对齐状态
|
|
@@ -92,6 +106,32 @@ worker 启停及连接清理都由后端统一处理,前端只做输入和展
|
|
|
92
106
|
Web 不再导入或运行 CLI shell,飞书运行中也能提交 steer 和回答问题。
|
|
93
107
|
IPython 是明确的例外:`ipython_agent()` 仍返回裸 Agent。
|
|
94
108
|
|
|
109
|
+
VS Code 前端为每个项目在项目所在机器上启动独立的 workspace 后端,通过稳定
|
|
110
|
+
WebviewView 在左侧活动栏的 Pycodex 入口显示聊天。首次使用优先复用已有
|
|
111
|
+
`python-codex>=0.3.1`,版本足够时不联网;缺失或版本太旧时,在对应的 Python
|
|
112
|
+
环境中通过 pip 安装或升级。检查、安装和启动都在工作区所在主机完成。
|
|
113
|
+
新建 session 会展开新会话、
|
|
114
|
+
折叠上一个会话,保留后台任务和草稿;折叠条目继续更新状态,可直接点击展开或关闭。
|
|
115
|
+
每个会话提供 Markdown 回复和固定输入框,新会话默认没有代码上下文,也不绑定源文件。
|
|
116
|
+
需要引用代码时,可从编辑器、Diff(含只读一侧)或文件树/工作树右键插入上下文。
|
|
117
|
+
片段像 emoji 一样插在文字光标处,可点击编辑,也可整体删除或复制粘贴。
|
|
118
|
+
发送时按照文字和片段的原始顺序展开为普通 prompt,后续消息不会自动附加。
|
|
119
|
+
模型名称仅作展示,通过 `/model <name>` 切换模型,
|
|
120
|
+
`/model` 列出可用模型;关闭会话会等待后端正常收尾。隐藏侧边栏只解除订阅。
|
|
121
|
+
后端通过既有 `--workspace-config <path>` 读取临时 JSON 配置文件,正常退出后清理临时目录。
|
|
122
|
+
`pycodex-ws` 默认在 stdin EOF 时排空已接收任务并退出;运行期间须保持 stdin 打开,
|
|
123
|
+
重定向到 `/dev/null` 会触发关闭。扩展通过保持管道打开管理后端生命周期;
|
|
124
|
+
关闭项目或宿主崩溃使管道关闭,插件正常停用会等待退出确认。
|
|
125
|
+
Remote SSH 等远程工作区的 Python 后端在远程服务器上启动;
|
|
126
|
+
短暂断联但远端宿主仍在运行时,会话继续保留。
|
|
127
|
+
默认读取后端所在主机的 `~/.codex/config.toml`,欢迎页会说明这一点。
|
|
128
|
+
聊天栏设置菜单可选择项目 `.venv`、`venv` 或浏览其他 Python 解释器,
|
|
129
|
+
也可修改 Profile;例如 `step` 等价于 `--profile step`。
|
|
130
|
+
已有后端运行时会提示重新加载窗口后生效。输入框底部的 context meter 与 workspace 前端一致,
|
|
131
|
+
可查看剩余比例、最近一次模型上报的用量、压缩阈值和上下文上限。
|
|
132
|
+
构建 VSIX、Python 环境配置及 Remote SSH 用法见
|
|
133
|
+
[`extensions/vscode/README.md`](extensions/vscode/README.md)。
|
|
134
|
+
|
|
95
135
|
外部程序使用 `pycodex.bootstrap.build_model/build_agent/build_runtime` 装配,
|
|
96
136
|
通过 `await runtime.start()`、`runtime.attach(handler)`、
|
|
97
137
|
`await runtime.submit_input(text, sender)` 和 `await receipt.future` 交互。
|
|
@@ -161,6 +201,16 @@ from pycodex import ResponsesModelClient
|
|
|
161
201
|
client = ResponsesModelClient.from_codex_config()
|
|
162
202
|
```
|
|
163
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
|
+
|
|
164
214
|
当前实现走 OpenAI-compatible Responses API 的流式 `/responses` 接口。这个点
|
|
165
215
|
已经用本机 `~/.codex/config.toml` 做过联调验证。
|
|
166
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.
|
|
@@ -63,6 +63,7 @@ Session wrapper. Queue data remains internal to Runtime.
|
|
|
63
63
|
|
|
64
64
|
```text
|
|
65
65
|
CLI / Web / Feishu -> AgentRuntime -> Agent
|
|
66
|
+
VS Code -> workspace_server HTTP -> AgentRuntime
|
|
66
67
|
IPython ---------------------------> Agent
|
|
67
68
|
```
|
|
68
69
|
|
|
@@ -89,6 +90,69 @@ commands and invalid arguments produce explicit command errors. Destructive
|
|
|
89
90
|
commands reject active or queued work; a command lock serializes asynchronous
|
|
90
91
|
commands and lets close wait for accepted command work.
|
|
91
92
|
|
|
93
|
+
The [VS Code frontend](../extensions/vscode/README.md) starts a workspace backend
|
|
94
|
+
per project using the existing CLI. Before startup it reads package metadata
|
|
95
|
+
from the selected Python interpreter. Automatic detection resolves an existing
|
|
96
|
+
console script's interpreter or finds Python on the workspace host. A compatible
|
|
97
|
+
`python-codex>=0.3.1` is reused without a network check; missing or older packages
|
|
98
|
+
are installed/upgraded through that interpreter's pip, including the optional
|
|
99
|
+
`pycodex-ws` metapackage when present. It launches `python -m workspace_server`
|
|
100
|
+
with the same interpreter, including when a selected venv initially has no Pycodex.
|
|
101
|
+
Installation finishes before the backend startup deadline starts. Pending
|
|
102
|
+
installs are shared per Python environment, and closing during preparation waits
|
|
103
|
+
for pip before discarding the launch. No private environment is created.
|
|
104
|
+
It uses the backend host's
|
|
105
|
+
`~/.codex/config.toml` by default; the welcome screen explains the local/remote
|
|
106
|
+
configuration source. The header settings menu selects project `.venv`/`venv`
|
|
107
|
+
interpreters or browses for another Python, and edits the Profile name.
|
|
108
|
+
Selections are validated without installing packages and saved to the project's
|
|
109
|
+
`pycodex.pythonPath` and `pycodex.profile` settings. A profile adds
|
|
110
|
+
`--profile <name>` to the launch. Changing either setting through the menu
|
|
111
|
+
offers a window reload if the backend is running; existing sessions keep their
|
|
112
|
+
startup settings until it restarts.
|
|
113
|
+
Sessions have no source-file binding or
|
|
114
|
+
automatically attached editor context. On request, the frontend captures the
|
|
115
|
+
source file, one-based cursor/selection and a bounded editor-buffer excerpt.
|
|
116
|
+
Read-only Git diff documents and Explorer/SCM file selections use VS Code's
|
|
117
|
+
document API. Context appears as atomic tokens interleaved with ordinary text in
|
|
118
|
+
the composer. Insertion uses the saved cursor/selection; clicking a token edits
|
|
119
|
+
its content. Sending expands text and tokens in their original order into the
|
|
120
|
+
ordinary `prompt` field.
|
|
121
|
+
Commands and pending answers use
|
|
122
|
+
the same existing HTTP API.
|
|
123
|
+
Connections are keyed by workspace endpoint and session id.
|
|
124
|
+
Each new chat creates a session; clicking a collapsed entry
|
|
125
|
+
activates that chat. A stable WebviewView in the Pycodex activity-bar container
|
|
126
|
+
displays one expanded chat and collapsed entries for the others, preserving each
|
|
127
|
+
chat's draft. All opened entries retain live status while the
|
|
128
|
+
sidebar is visible; hiding it stops observation without closing sessions.
|
|
129
|
+
Model changes use typed `/model` commands; the model label is read-only.
|
|
130
|
+
Closing an entry uses the existing session DELETE endpoint and waits for normal
|
|
131
|
+
backend draining before removing the entry. HTTP snapshot polling uses the
|
|
132
|
+
existing Web projection. In remote workspaces, the extension host starts Python
|
|
133
|
+
and makes HTTP requests on the remote machine; the webview only exchanges
|
|
134
|
+
messages with the extension host.
|
|
135
|
+
The input footer's context ring uses the existing snapshot fields
|
|
136
|
+
`context_remaining_percent`, `usage_tokens`, `auto_compact_token_limit` and
|
|
137
|
+
`max_context_window`. It shares the Web meter semantics below, including compact
|
|
138
|
+
thresholds, unknown usage and reset after compaction. Hover/focus shows exact
|
|
139
|
+
values, click pins them, and Escape, outside click or session switching closes
|
|
140
|
+
the details. The frontend does not estimate draft tokens or recalculate limits.
|
|
141
|
+
The launcher writes UTF-8 workspace JSON into a private temporary directory
|
|
142
|
+
and passes the filename through the existing `--workspace-config` option.
|
|
143
|
+
It removes that directory after backend exit or failed startup; an abrupt host
|
|
144
|
+
crash can leave the temporary files behind. The `pycodex-ws` CLI always
|
|
145
|
+
shuts down on stdin EOF. Stdin stays open for the backend's lifetime.
|
|
146
|
+
EOF on folder removal, deactivation,
|
|
147
|
+
or extension-host death starts normal server shutdown, including when EOF arrives
|
|
148
|
+
before startup finishes. Accepted turns and queues drain through existing Runtime
|
|
149
|
+
closure; no turn timeout or forced cancellation is added. Deactivation waits for
|
|
150
|
+
all owned processes to exit. A temporary remote disconnection leaves sessions
|
|
151
|
+
running if their extension host remains alive.
|
|
152
|
+
Other CLI launchers must also keep stdin open; closed stdin (including
|
|
153
|
+
`/dev/null`) requests shutdown. Programmatic FastAPI app construction does not
|
|
154
|
+
read stdin.
|
|
155
|
+
|
|
92
156
|
Web command output preserves the event's plain text, including resume-list
|
|
93
157
|
numbering and line breaks.
|
|
94
158
|
Assistant replies render fenced `mermaid` blocks as diagrams. The browser loads
|
|
@@ -111,6 +175,9 @@ updating other tab state. A save targets the edited session even if another
|
|
|
111
175
|
tab is selected before its response arrives.
|
|
112
176
|
Selected tabs use a tinted background without a click-focus border; keyboard
|
|
113
177
|
focus on the title uses an underline.
|
|
178
|
+
The browser page title gains a `●` prefix while any session in the workspace
|
|
179
|
+
is running, using the same session summaries as the tab activity dots. It returns
|
|
180
|
+
to the original workspace title when all sessions are idle.
|
|
114
181
|
|
|
115
182
|
The workspace presents assistant replies as open text and user messages as
|
|
116
183
|
right-aligned bubbles. Commands and thinking use quieter secondary styling;
|
|
@@ -182,7 +249,13 @@ own; unlinking a Feishu card only detaches that frontend. Web submits directly
|
|
|
182
249
|
to the backend, including across its worker-thread boundary: it does not run a
|
|
183
250
|
CLI shell or maintain an extra prompt queue.
|
|
184
251
|
|
|
185
|
-
Workspace tab
|
|
252
|
+
Workspace state stores every open tab in order, starting when the tab is created.
|
|
253
|
+
An empty tab stores an empty title and rollout path, so restoring it creates a
|
|
254
|
+
fresh empty session without writing a rollout. Manual titles and first messages
|
|
255
|
+
are not prerequisites for keeping a tab across a server restart. Changes to
|
|
256
|
+
automatic or explicit titles and recorded paths update the same saved tab.
|
|
257
|
+
Startup restores the full tab list before saving it; closing a tab removes its
|
|
258
|
+
entry.
|
|
186
259
|
Once a fork's first turn or successful compact creates its rollout, the saved tab
|
|
187
260
|
points to that file, including when the model subsequently fails. Before the
|
|
188
261
|
file exists, the tab stores the recorded ancestor's path with an explicit
|
|
@@ -532,7 +605,8 @@ context; `ResponsesModelClient.model` uses the same provider config as metadata.
|
|
|
532
605
|
|
|
533
606
|
Only the Responses provider classifies external error text:
|
|
534
607
|
|
|
535
|
-
- Transient/disconnected streams
|
|
608
|
+
- Transient/disconnected streams and retryable `response.failed` events
|
|
609
|
+
use `ResponsesRetryableError`.
|
|
536
610
|
- Context overflow uses `ContextLengthExceeded`, with optional usage and limit
|
|
537
611
|
parsed from the provider's error details.
|
|
538
612
|
- A genuine terminal incomplete response uses `ResponsesIncompleteError` and
|
|
@@ -540,6 +614,22 @@ Only the Responses provider classifies external error text:
|
|
|
540
614
|
|
|
541
615
|
Custom clients must raise the corresponding exception rather than rely on
|
|
542
616
|
arbitrary `RuntimeError` text being reinterpreted by the Agent or compactor.
|
|
617
|
+
|
|
618
|
+
The local `responses_server` validates ordinary function-call arguments after
|
|
619
|
+
assembling the downstream stream. Malformed JSON produces `response.failed` with
|
|
620
|
+
`type = "server_error"` before any final output items are emitted. The error names
|
|
621
|
+
the tool and JSON parsing failure without including raw arguments.
|
|
622
|
+
`ResponsesModelClient` handles this through its generic provider error path and
|
|
623
|
+
retries only the current request under `stream_max_retries`; it does not classify
|
|
624
|
+
tool argument parse failures as retryable locally. Earlier completed tools stay
|
|
625
|
+
in history and retries do not restart the turn. Valid JSON that decodes to a
|
|
626
|
+
non-object still raises a terminal API error; freeform/custom tool inputs remain
|
|
627
|
+
plain text.
|
|
628
|
+
|
|
629
|
+
Assistant message text remains text, including content that resembles a tool
|
|
630
|
+
call. Tool parse errors require a structured tool item or an explicit provider
|
|
631
|
+
error; the client does not infer them from patterns in assistant prose.
|
|
632
|
+
|
|
543
633
|
For max-output incomplete responses, the Agent persists done assistant/reasoning
|
|
544
634
|
items for continuation, but not bare text deltas or tool calls without results.
|
|
545
635
|
|
|
@@ -35,8 +35,9 @@ prompt 渲染路径一致,也保留 provider 自定义 effort 值(例如 `ma
|
|
|
35
35
|
- vLLM 历史 `reasoning` item -> assistant message `reasoning` 字段回放
|
|
36
36
|
- vLLM streaming `usage` -> final `response.completed.response.usage`
|
|
37
37
|
- 当环境变量 `PYCODEX_DUMP` 存在时,为每条 outcomming 请求附加 `return_token_ids = true`,并把实际下发的 request body、下游 usage/cache、`prompt_token_ids` / `token_ids` 以 JSONL 追加到 `{PYCODEX_DUMP}/dump.jsonl`
|
|
38
|
-
-
|
|
38
|
+
- 下游请求在等待响应头或读流时失败,会返回 `response.failed`,错误直接包含耗时、timeout、失败阶段、响应头/首个 chunk 的时间和 chunk 数量
|
|
39
39
|
- 普通 function tools
|
|
40
|
+
- 普通 function-call 参数拼接完成后校验 JSON;解析失败返回 `response.failed(type=server_error)`,由客户端按现有策略重试
|
|
40
41
|
- custom tools 的 function-wrapper 兼容适配
|
|
41
42
|
- mock `web_search` 接口对齐(返回空结果)
|
|
42
43
|
- function / custom tool follow-up history 重建
|
|
@@ -123,6 +124,14 @@ template 不消费 `developer` role;使用该模板的 provider 应显式配
|
|
|
123
124
|
length-stopped thinking 被持久化成 terminal reasoning-only history,并在下一轮转换成
|
|
124
125
|
下游 chat 后端不接受的裸 assistant message。
|
|
125
126
|
|
|
127
|
+
普通 function-call 的 `arguments` 在拼接完成后由 server 校验 JSON。解析失败时,
|
|
128
|
+
server 在发出本次最终 output items 之前返回 `response.failed(type=server_error)`;
|
|
129
|
+
错误只包含工具名和解析位置,不包含原始参数。`ResponsesModelClient` 通过通用
|
|
130
|
+
`response.failed` 处理按 `stream_max_retries` 重试当前请求,默认最多重试 5 次。
|
|
131
|
+
这条路径不增加 server 内部重试,也不把本次失败响应里的工具交给 Agent 执行。
|
|
132
|
+
合法 JSON 的内容保持原样;非 object 的参数仍由客户端按既有契约报错。
|
|
133
|
+
custom/freeform 工具继续使用原有适配流程,assistant 正文也继续作为文本处理。
|
|
134
|
+
|
|
126
135
|
`messages` compat 则故意不改这层 canonical request:仍然先构造 chat 风格
|
|
127
136
|
`outcomming_request`,只有在真正发请求和读 SSE 时,才在边界把它翻译成
|
|
128
137
|
messages request / event。这样 tool hydration、mock `web_search`
|
|
@@ -132,6 +141,11 @@ follow-up、provider payload post-process 仍然复用同一套主逻辑。
|
|
|
132
141
|
`max_tokens`,则优先透传上游请求里的 `max_output_tokens` / `max_tokens`;
|
|
133
142
|
如果上游没给,当前默认补 `32000`,避免直接被下游 `400` 拒绝。
|
|
134
143
|
|
|
144
|
+
下游失败无需开启调试模式。正常错误里的 `phase=waiting_response_headers`
|
|
145
|
+
表示尚未收到响应头,`waiting_first_chunk` 表示响应头已到但尚无完整 chunk,
|
|
146
|
+
`reading_stream` 表示流已开始;`elapsed` 是本次请求耗时,`idle` 是距离
|
|
147
|
+
最近一个完整 chunk 的时间。SSE 心跳不计入 chunk 数。
|
|
148
|
+
|
|
135
149
|
## 验证
|
|
136
150
|
|
|
137
151
|
当前独立测试:
|
|
@@ -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]
|