python-codex 0.3.0__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_codex-0.3.0 → python_codex-0.3.1}/PKG-INFO +40 -1
- {python_codex-0.3.0 → python_codex-0.3.1}/README.md +39 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/README_ZH.md +27 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/docs/RUNTIME.md +92 -2
- {python_codex-0.3.0 → python_codex-0.3.1}/docs/responses_server/README.md +15 -1
- {python_codex-0.3.0 → python_codex-0.3.1}/packages/pycodex-ws/pyproject.toml +2 -2
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/prompts/models.json +176 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pyproject.toml +2 -2
- {python_codex-0.3.0 → python_codex-0.3.1}/responses_server/app.py +1 -5
- {python_codex-0.3.0 → python_codex-0.3.1}/responses_server/stream_router.py +108 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/TESTS.md +36 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/responses_server/test_server.py +257 -2
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_model.py +310 -6
- python_codex-0.3.1/tests/test_owned_workspace_server.py +145 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_workspace_server.py +110 -12
- {python_codex-0.3.0 → python_codex-0.3.1}/workspace_server/app.py +4 -2
- python_codex-0.3.1/workspace_server/owned_process.py +27 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/workspace_server/workspace.html +2 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/workspace_server/workspaces.py +27 -28
- {python_codex-0.3.0 → python_codex-0.3.1}/.github/workflows/publish.yml +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/.github/workflows/test.yml +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/.gitignore +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/AGENTS.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/LICENSE +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/docs/ALIGNMENT.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/docs/CONTEXT.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/docs/RELEASE_0.3.0.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/packages/pycodex-ws/README.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/packages/pycodex-ws/pycodex_ws_meta/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/agent.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/bootstrap.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/cli.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/compat.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/context.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/doctor.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/events.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/feishu_card.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/feishu_link.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/model.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/model_metadata.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/portable.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/portable_server.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/prompts/default_base_instructions.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/prompts/permissions/approval_policy/never.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/prompts/permissions/approval_policy/on_failure.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/prompts/permissions/approval_policy/on_request.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/prompts/permissions/approval_policy/on_request_rule_request_permission.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/prompts/permissions/approval_policy/unless_trusted.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/prompts/permissions/sandbox_mode/danger_full_access.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/prompts/permissions/sandbox_mode/read_only.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/prompts/permissions/sandbox_mode/workspace_write.md +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/protocol.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/runtime.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/runtime_services.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/agent_tool_schemas.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/apply_patch_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/base_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/clock_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/close_agent_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/code_mode_manager.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/exec_command_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/exec_runtime.js +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/exec_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/grep_files_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/ipython_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/list_dir_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/read_file_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/request_permissions_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/request_user_input_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/resume_agent_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/send_input_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/shell_command_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/shell_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/spawn_agent_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/unified_exec_manager.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/update_plan_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/view_image_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/wait_agent_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/wait_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/web_search_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/tools/write_stdin_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/utils/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/utils/async_bridge.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/utils/compactor.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/utils/debug.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/utils/dotenv.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/utils/event_helpers.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/utils/get_env.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/utils/image_utils.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/utils/random_ids.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/utils/session_persist.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/pycodex/utils/truncation.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/responses_server/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/responses_server/__main__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/responses_server/config.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/responses_server/messages_api.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/responses_server/payload_processors.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/responses_server/server.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/responses_server/session_store.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/responses_server/tools/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/responses_server/tools/custom_adapter.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/responses_server/tools/web_search.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/responses_server/trajectory_dump.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/compare_context_requests.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/compare_steer_request_bodies.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/compare_tool_schemas.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/conftest.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/fake_responses_server.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/fakes.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/responses_server/fake_chat_completions_server.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/responses_server/test_trajectory_dump.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_agent.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_agent_state.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_async_bridge.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_builtin_tools.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_cli.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_compactor.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_context.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_doctor.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_events.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_fake_responses_server.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_feishu_card.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_feishu_link.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_feishu_oauth.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_ipython_tool.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_packaging.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_portable.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_py36_syntax.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_runtime_state.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tests/test_session_backend.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tools/feishu_oauth.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/tools/sync_model_prompts.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/workspace_server/__init__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/workspace_server/__main__.py +0 -0
- {python_codex-0.3.0 → python_codex-0.3.1}/workspace_server/workspaces.html +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-codex
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
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
|
|
@@ -77,6 +77,32 @@ uv run pycodex "Reply with exactly OK."
|
|
|
77
77
|
uv run pycodex
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
+
A VS Code frontend is available in [`extensions/vscode`](extensions/vscode/README.md).
|
|
81
|
+
It reuses an existing `python-codex>=0.3.1` installation. On first use, missing
|
|
82
|
+
or older backends are installed/upgraded with pip in the selected Python
|
|
83
|
+
environment on the workspace host; compatible versions need no network check.
|
|
84
|
+
It starts a dedicated `pycodex-ws` workspace on the project's host and opens a
|
|
85
|
+
chat in the left sidebar using VS Code's stable WebviewView API. Each chat
|
|
86
|
+
creates a workspace session with no code context attached. You can insert code
|
|
87
|
+
from editors, diffs or file-tree selections as editable tokens among your words.
|
|
88
|
+
Each token expands at its position when you send the message.
|
|
89
|
+
Previous chats fold into live status entries; each can be
|
|
90
|
+
reopened or closed, and models can be changed with `/model`.
|
|
91
|
+
Remote workspaces run Python on the remote host. A stdin pipe ties each backend
|
|
92
|
+
to its extension host; normal closure or host failure triggers draining and exit.
|
|
93
|
+
`pycodex-ws` always shuts down on stdin EOF, after accepted work finishes.
|
|
94
|
+
Keep stdin open while running the server; redirecting it from `/dev/null`
|
|
95
|
+
causes the server to shut down.
|
|
96
|
+
Workspace configuration uses a temporary JSON file passed to `--workspace-config`;
|
|
97
|
+
normal backend exit removes the temporary directory.
|
|
98
|
+
The extension uses that host's `~/.codex/config.toml` by default.
|
|
99
|
+
The chat settings menu selects a project venv or another Python interpreter
|
|
100
|
+
and edits the Codex profile. Changes offer a window reload when a backend is
|
|
101
|
+
already running.
|
|
102
|
+
Its context ring shows the same remaining budget and usage details as the
|
|
103
|
+
workspace web frontend.
|
|
104
|
+
See the extension README for building a VSIX, server setup and Remote SSH usage.
|
|
105
|
+
|
|
80
106
|
## Design Tradeoffs
|
|
81
107
|
|
|
82
108
|
This is not a 1:1 port of the Rust implementation. The current goal is a
|
|
@@ -111,6 +137,7 @@ nailing the core tool-augmented reasoning loop first.
|
|
|
111
137
|
- `pycodex/tools/`: concrete tool implementations
|
|
112
138
|
- `pycodex/agent.py`: inner turn loop
|
|
113
139
|
- `pycodex/runtime.py`: session commands, submission queues and frontend event subscriptions
|
|
140
|
+
- `extensions/vscode/`: VS Code chat frontend using the workspace HTTP API
|
|
114
141
|
- `tests/test_agent.py`: core behavior tests
|
|
115
142
|
|
|
116
143
|
## Current Alignment Status
|
|
@@ -158,6 +185,9 @@ Chained failures also retain `stream_error_cause_type` and, for HTTP errors,
|
|
|
158
185
|
`stream_error_http_status`; exception messages, headers and URLs are not
|
|
159
186
|
copied into these diagnostic fields.
|
|
160
187
|
|
|
188
|
+
Downstream errors include elapsed time, timeout, failure stage, response-header
|
|
189
|
+
and first-chunk timing, and received chunk count directly in the error message.
|
|
190
|
+
|
|
161
191
|
## Live Model Integration
|
|
162
192
|
|
|
163
193
|
If this machine already has a Codex CLI configuration, `pycodex` can reuse the
|
|
@@ -330,6 +360,15 @@ Current behavior:
|
|
|
330
360
|
reasoning, retries the same downstream request once, and only then emits
|
|
331
361
|
`response.failed` with `type = "model_output_invalid"` if the retry is still
|
|
332
362
|
reasoning-only
|
|
363
|
+
- malformed JSON in ordinary downstream function-call arguments is detected by
|
|
364
|
+
`responses_server` and returned as `response.failed` with `type = "server_error"`;
|
|
365
|
+
the client's existing `stream_max_retries` policy retries the current request
|
|
366
|
+
before its local tools execute
|
|
367
|
+
- downstream connection failures before HTTP response headers or during SSE
|
|
368
|
+
reading are converted to `response.failed` for provider retries. Downstream
|
|
369
|
+
requests honor environment proxies; see the
|
|
370
|
+
[connection troubleshooting notes](docs/responses_server/README.md#连接排查)
|
|
371
|
+
for `RemoteDisconnected` and proxy bypass configuration
|
|
333
372
|
- standalone `responses_server` now also supports downstream `/v1/messages`
|
|
334
373
|
backends via `--outcomming-api messages`, while keeping the internal
|
|
335
374
|
canonical request/route logic in chat-completions shape
|
|
@@ -54,6 +54,32 @@ uv run pycodex "Reply with exactly OK."
|
|
|
54
54
|
uv run pycodex
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
A VS Code frontend is available in [`extensions/vscode`](extensions/vscode/README.md).
|
|
58
|
+
It reuses an existing `python-codex>=0.3.1` installation. On first use, missing
|
|
59
|
+
or older backends are installed/upgraded with pip in the selected Python
|
|
60
|
+
environment on the workspace host; compatible versions need no network check.
|
|
61
|
+
It starts a dedicated `pycodex-ws` workspace on the project's host and opens a
|
|
62
|
+
chat in the left sidebar using VS Code's stable WebviewView API. Each chat
|
|
63
|
+
creates a workspace session with no code context attached. You can insert code
|
|
64
|
+
from editors, diffs or file-tree selections as editable tokens among your words.
|
|
65
|
+
Each token expands at its position when you send the message.
|
|
66
|
+
Previous chats fold into live status entries; each can be
|
|
67
|
+
reopened or closed, and models can be changed with `/model`.
|
|
68
|
+
Remote workspaces run Python on the remote host. A stdin pipe ties each backend
|
|
69
|
+
to its extension host; normal closure or host failure triggers draining and exit.
|
|
70
|
+
`pycodex-ws` always shuts down on stdin EOF, after accepted work finishes.
|
|
71
|
+
Keep stdin open while running the server; redirecting it from `/dev/null`
|
|
72
|
+
causes the server to shut down.
|
|
73
|
+
Workspace configuration uses a temporary JSON file passed to `--workspace-config`;
|
|
74
|
+
normal backend exit removes the temporary directory.
|
|
75
|
+
The extension uses that host's `~/.codex/config.toml` by default.
|
|
76
|
+
The chat settings menu selects a project venv or another Python interpreter
|
|
77
|
+
and edits the Codex profile. Changes offer a window reload when a backend is
|
|
78
|
+
already running.
|
|
79
|
+
Its context ring shows the same remaining budget and usage details as the
|
|
80
|
+
workspace web frontend.
|
|
81
|
+
See the extension README for building a VSIX, server setup and Remote SSH usage.
|
|
82
|
+
|
|
57
83
|
## Design Tradeoffs
|
|
58
84
|
|
|
59
85
|
This is not a 1:1 port of the Rust implementation. The current goal is a
|
|
@@ -88,6 +114,7 @@ nailing the core tool-augmented reasoning loop first.
|
|
|
88
114
|
- `pycodex/tools/`: concrete tool implementations
|
|
89
115
|
- `pycodex/agent.py`: inner turn loop
|
|
90
116
|
- `pycodex/runtime.py`: session commands, submission queues and frontend event subscriptions
|
|
117
|
+
- `extensions/vscode/`: VS Code chat frontend using the workspace HTTP API
|
|
91
118
|
- `tests/test_agent.py`: core behavior tests
|
|
92
119
|
|
|
93
120
|
## Current Alignment Status
|
|
@@ -135,6 +162,9 @@ Chained failures also retain `stream_error_cause_type` and, for HTTP errors,
|
|
|
135
162
|
`stream_error_http_status`; exception messages, headers and URLs are not
|
|
136
163
|
copied into these diagnostic fields.
|
|
137
164
|
|
|
165
|
+
Downstream errors include elapsed time, timeout, failure stage, response-header
|
|
166
|
+
and first-chunk timing, and received chunk count directly in the error message.
|
|
167
|
+
|
|
138
168
|
## Live Model Integration
|
|
139
169
|
|
|
140
170
|
If this machine already has a Codex CLI configuration, `pycodex` can reuse the
|
|
@@ -307,6 +337,15 @@ Current behavior:
|
|
|
307
337
|
reasoning, retries the same downstream request once, and only then emits
|
|
308
338
|
`response.failed` with `type = "model_output_invalid"` if the retry is still
|
|
309
339
|
reasoning-only
|
|
340
|
+
- malformed JSON in ordinary downstream function-call arguments is detected by
|
|
341
|
+
`responses_server` and returned as `response.failed` with `type = "server_error"`;
|
|
342
|
+
the client's existing `stream_max_retries` policy retries the current request
|
|
343
|
+
before its local tools execute
|
|
344
|
+
- downstream connection failures before HTTP response headers or during SSE
|
|
345
|
+
reading are converted to `response.failed` for provider retries. Downstream
|
|
346
|
+
requests honor environment proxies; see the
|
|
347
|
+
[connection troubleshooting notes](docs/responses_server/README.md#连接排查)
|
|
348
|
+
for `RemoteDisconnected` and proxy bypass configuration
|
|
310
349
|
- standalone `responses_server` now also supports downstream `/v1/messages`
|
|
311
350
|
backends via `--outcomming-api messages`, while keeping the internal
|
|
312
351
|
canonical request/route logic in chat-completions shape
|
|
@@ -82,6 +82,7 @@ uv run pycodex
|
|
|
82
82
|
- `pycodex/tools/`:具体工具实现
|
|
83
83
|
- `pycodex/agent.py`:主循环
|
|
84
84
|
- `pycodex/runtime.py`:统一会话命令、提交队列和前端事件订阅
|
|
85
|
+
- `extensions/vscode/`:通过 workspace HTTP API 接入的 VS Code 聊天前端
|
|
85
86
|
- `tests/test_agent.py`:核心行为测试
|
|
86
87
|
|
|
87
88
|
## 当前对齐状态
|
|
@@ -92,6 +93,32 @@ worker 启停及连接清理都由后端统一处理,前端只做输入和展
|
|
|
92
93
|
Web 不再导入或运行 CLI shell,飞书运行中也能提交 steer 和回答问题。
|
|
93
94
|
IPython 是明确的例外:`ipython_agent()` 仍返回裸 Agent。
|
|
94
95
|
|
|
96
|
+
VS Code 前端为每个项目在项目所在机器上启动独立的 workspace 后端,通过稳定
|
|
97
|
+
WebviewView 在左侧活动栏的 Pycodex 入口显示聊天。首次使用优先复用已有
|
|
98
|
+
`python-codex>=0.3.1`,版本足够时不联网;缺失或版本太旧时,在对应的 Python
|
|
99
|
+
环境中通过 pip 安装或升级。检查、安装和启动都在工作区所在主机完成。
|
|
100
|
+
新建 session 会展开新会话、
|
|
101
|
+
折叠上一个会话,保留后台任务和草稿;折叠条目继续更新状态,可直接点击展开或关闭。
|
|
102
|
+
每个会话提供 Markdown 回复和固定输入框,新会话默认没有代码上下文,也不绑定源文件。
|
|
103
|
+
需要引用代码时,可从编辑器、Diff(含只读一侧)或文件树/工作树右键插入上下文。
|
|
104
|
+
片段像 emoji 一样插在文字光标处,可点击编辑,也可整体删除或复制粘贴。
|
|
105
|
+
发送时按照文字和片段的原始顺序展开为普通 prompt,后续消息不会自动附加。
|
|
106
|
+
模型名称仅作展示,通过 `/model <name>` 切换模型,
|
|
107
|
+
`/model` 列出可用模型;关闭会话会等待后端正常收尾。隐藏侧边栏只解除订阅。
|
|
108
|
+
后端通过既有 `--workspace-config <path>` 读取临时 JSON 配置文件,正常退出后清理临时目录。
|
|
109
|
+
`pycodex-ws` 默认在 stdin EOF 时排空已接收任务并退出;运行期间须保持 stdin 打开,
|
|
110
|
+
重定向到 `/dev/null` 会触发关闭。扩展通过保持管道打开管理后端生命周期;
|
|
111
|
+
关闭项目或宿主崩溃使管道关闭,插件正常停用会等待退出确认。
|
|
112
|
+
Remote SSH 等远程工作区的 Python 后端在远程服务器上启动;
|
|
113
|
+
短暂断联但远端宿主仍在运行时,会话继续保留。
|
|
114
|
+
默认读取后端所在主机的 `~/.codex/config.toml`,欢迎页会说明这一点。
|
|
115
|
+
聊天栏设置菜单可选择项目 `.venv`、`venv` 或浏览其他 Python 解释器,
|
|
116
|
+
也可修改 Profile;例如 `step` 等价于 `--profile step`。
|
|
117
|
+
已有后端运行时会提示重新加载窗口后生效。输入框底部的 context meter 与 workspace 前端一致,
|
|
118
|
+
可查看剩余比例、最近一次模型上报的用量、压缩阈值和上下文上限。
|
|
119
|
+
构建 VSIX、Python 环境配置及 Remote SSH 用法见
|
|
120
|
+
[`extensions/vscode/README.md`](extensions/vscode/README.md)。
|
|
121
|
+
|
|
95
122
|
外部程序使用 `pycodex.bootstrap.build_model/build_agent/build_runtime` 装配,
|
|
96
123
|
通过 `await runtime.start()`、`runtime.attach(handler)`、
|
|
97
124
|
`await runtime.submit_input(text, sender)` 和 `await receipt.future` 交互。
|
|
@@ -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,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.1"
|
|
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.1",
|
|
13
13
|
]
|
|
14
14
|
|
|
15
15
|
[tool.hatch.build.targets.wheel]
|