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.
Files changed (140) hide show
  1. {python_codex-0.3.0 → python_codex-0.3.2}/.github/workflows/publish.yml +11 -0
  2. {python_codex-0.3.0 → python_codex-0.3.2}/PKG-INFO +70 -4
  3. {python_codex-0.3.0 → python_codex-0.3.2}/README.md +69 -3
  4. {python_codex-0.3.0 → python_codex-0.3.2}/README_ZH.md +53 -3
  5. {python_codex-0.3.0 → python_codex-0.3.2}/docs/ALIGNMENT.md +23 -0
  6. python_codex-0.3.2/docs/RELEASE_0.3.2.md +36 -0
  7. {python_codex-0.3.0 → python_codex-0.3.2}/docs/RUNTIME.md +92 -2
  8. {python_codex-0.3.0 → python_codex-0.3.2}/docs/responses_server/README.md +15 -1
  9. {python_codex-0.3.0 → python_codex-0.3.2}/packages/pycodex-ws/README.md +9 -1
  10. {python_codex-0.3.0 → python_codex-0.3.2}/packages/pycodex-ws/pyproject.toml +2 -2
  11. python_codex-0.3.2/pycodex/__main__.py +4 -0
  12. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/model.py +11 -2
  13. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/models.json +176 -0
  14. {python_codex-0.3.0 → python_codex-0.3.2}/pyproject.toml +2 -2
  15. {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/app.py +1 -5
  16. {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/stream_router.py +108 -0
  17. {python_codex-0.3.0 → python_codex-0.3.2}/tests/TESTS.md +48 -0
  18. {python_codex-0.3.0 → python_codex-0.3.2}/tests/responses_server/test_server.py +257 -2
  19. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_doctor.py +16 -4
  20. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_model.py +398 -6
  21. python_codex-0.3.2/tests/test_owned_workspace_server.py +145 -0
  22. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_packaging.py +28 -0
  23. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_workspace_server.py +110 -12
  24. {python_codex-0.3.0 → python_codex-0.3.2}/workspace_server/app.py +4 -2
  25. python_codex-0.3.2/workspace_server/owned_process.py +27 -0
  26. {python_codex-0.3.0 → python_codex-0.3.2}/workspace_server/workspace.html +2 -0
  27. {python_codex-0.3.0 → python_codex-0.3.2}/workspace_server/workspaces.py +27 -28
  28. {python_codex-0.3.0 → python_codex-0.3.2}/.github/workflows/test.yml +0 -0
  29. {python_codex-0.3.0 → python_codex-0.3.2}/.gitignore +0 -0
  30. {python_codex-0.3.0 → python_codex-0.3.2}/AGENTS.md +0 -0
  31. {python_codex-0.3.0 → python_codex-0.3.2}/LICENSE +0 -0
  32. {python_codex-0.3.0 → python_codex-0.3.2}/docs/CONTEXT.md +0 -0
  33. {python_codex-0.3.0 → python_codex-0.3.2}/docs/RELEASE_0.3.0.md +0 -0
  34. {python_codex-0.3.0 → python_codex-0.3.2}/packages/pycodex-ws/pycodex_ws_meta/__init__.py +0 -0
  35. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/__init__.py +0 -0
  36. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/agent.py +0 -0
  37. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/bootstrap.py +0 -0
  38. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/cli.py +0 -0
  39. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/compat.py +0 -0
  40. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/context.py +0 -0
  41. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/doctor.py +0 -0
  42. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/events.py +0 -0
  43. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/feishu_card.py +0 -0
  44. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/feishu_link.py +0 -0
  45. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/model_metadata.py +0 -0
  46. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/portable.py +0 -0
  47. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/portable_server.py +0 -0
  48. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/default_base_instructions.md +0 -0
  49. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/never.md +0 -0
  50. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/on_failure.md +0 -0
  51. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/on_request.md +0 -0
  52. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/on_request_rule_request_permission.md +0 -0
  53. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/approval_policy/unless_trusted.md +0 -0
  54. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/sandbox_mode/danger_full_access.md +0 -0
  55. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/sandbox_mode/read_only.md +0 -0
  56. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/prompts/permissions/sandbox_mode/workspace_write.md +0 -0
  57. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/protocol.py +0 -0
  58. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/runtime.py +0 -0
  59. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/runtime_services.py +0 -0
  60. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/__init__.py +0 -0
  61. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/agent_tool_schemas.py +0 -0
  62. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/apply_patch_tool.py +0 -0
  63. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/base_tool.py +0 -0
  64. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/clock_tool.py +0 -0
  65. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/close_agent_tool.py +0 -0
  66. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/code_mode_manager.py +0 -0
  67. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/exec_command_tool.py +0 -0
  68. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/exec_runtime.js +0 -0
  69. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/exec_tool.py +0 -0
  70. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/grep_files_tool.py +0 -0
  71. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/ipython_tool.py +0 -0
  72. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/list_dir_tool.py +0 -0
  73. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/read_file_tool.py +0 -0
  74. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/request_permissions_tool.py +0 -0
  75. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/request_user_input_tool.py +0 -0
  76. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/resume_agent_tool.py +0 -0
  77. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/send_input_tool.py +0 -0
  78. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/shell_command_tool.py +0 -0
  79. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/shell_tool.py +0 -0
  80. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/spawn_agent_tool.py +0 -0
  81. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/unified_exec_manager.py +0 -0
  82. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/update_plan_tool.py +0 -0
  83. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/view_image_tool.py +0 -0
  84. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/wait_agent_tool.py +0 -0
  85. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/wait_tool.py +0 -0
  86. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/web_search_tool.py +0 -0
  87. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/tools/write_stdin_tool.py +0 -0
  88. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/__init__.py +0 -0
  89. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/async_bridge.py +0 -0
  90. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/compactor.py +0 -0
  91. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/debug.py +0 -0
  92. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/dotenv.py +0 -0
  93. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/event_helpers.py +0 -0
  94. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/get_env.py +0 -0
  95. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/image_utils.py +0 -0
  96. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/random_ids.py +0 -0
  97. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/session_persist.py +0 -0
  98. {python_codex-0.3.0 → python_codex-0.3.2}/pycodex/utils/truncation.py +0 -0
  99. {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/__init__.py +0 -0
  100. {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/__main__.py +0 -0
  101. {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/config.py +0 -0
  102. {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/messages_api.py +0 -0
  103. {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/payload_processors.py +0 -0
  104. {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/server.py +0 -0
  105. {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/session_store.py +0 -0
  106. {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/tools/__init__.py +0 -0
  107. {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/tools/custom_adapter.py +0 -0
  108. {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/tools/web_search.py +0 -0
  109. {python_codex-0.3.0 → python_codex-0.3.2}/responses_server/trajectory_dump.py +0 -0
  110. {python_codex-0.3.0 → python_codex-0.3.2}/tests/__init__.py +0 -0
  111. {python_codex-0.3.0 → python_codex-0.3.2}/tests/compare_context_requests.py +0 -0
  112. {python_codex-0.3.0 → python_codex-0.3.2}/tests/compare_steer_request_bodies.py +0 -0
  113. {python_codex-0.3.0 → python_codex-0.3.2}/tests/compare_tool_schemas.py +0 -0
  114. {python_codex-0.3.0 → python_codex-0.3.2}/tests/conftest.py +0 -0
  115. {python_codex-0.3.0 → python_codex-0.3.2}/tests/fake_responses_server.py +0 -0
  116. {python_codex-0.3.0 → python_codex-0.3.2}/tests/fakes.py +0 -0
  117. {python_codex-0.3.0 → python_codex-0.3.2}/tests/responses_server/fake_chat_completions_server.py +0 -0
  118. {python_codex-0.3.0 → python_codex-0.3.2}/tests/responses_server/test_trajectory_dump.py +0 -0
  119. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_agent.py +0 -0
  120. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_agent_state.py +0 -0
  121. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_async_bridge.py +0 -0
  122. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_builtin_tools.py +0 -0
  123. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_cli.py +0 -0
  124. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_compactor.py +0 -0
  125. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_context.py +0 -0
  126. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_events.py +0 -0
  127. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_fake_responses_server.py +0 -0
  128. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_feishu_card.py +0 -0
  129. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_feishu_link.py +0 -0
  130. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_feishu_oauth.py +0 -0
  131. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_ipython_tool.py +0 -0
  132. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_portable.py +0 -0
  133. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_py36_syntax.py +0 -0
  134. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_runtime_state.py +0 -0
  135. {python_codex-0.3.0 → python_codex-0.3.2}/tests/test_session_backend.py +0 -0
  136. {python_codex-0.3.0 → python_codex-0.3.2}/tools/feishu_oauth.py +0 -0
  137. {python_codex-0.3.0 → python_codex-0.3.2}/tools/sync_model_prompts.py +0 -0
  138. {python_codex-0.3.0 → python_codex-0.3.2}/workspace_server/__init__.py +0 -0
  139. {python_codex-0.3.0 → python_codex-0.3.2}/workspace_server/__main__.py +0 -0
  140. {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.0
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
- Install dependencies first:
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
- Install dependencies first:
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 persistence follows recording changes as well as explicit titles.
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 use `ResponsesRetryableError`.
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
- - 下游 chat stream 如果半路断开,会转成上游可解析的 `response.failed` 事件,而不是直接截断 HTTP body
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.0"
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.0",
12
+ "python-codex==0.3.2",
13
13
  ]
14
14
 
15
15
  [tool.hatch.build.targets.wheel]
@@ -0,0 +1,4 @@
1
+ from .cli import main
2
+
3
+ if __name__ == "__main__":
4
+ raise SystemExit(main())