Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/tweaks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Segmented docs for building Codex++ tweaks.
- [MCP servers](./mcp.md)
- [TypeScript and bundling](./typescript-and-bundling.md)
- [Distribution and debugging](./distribution-debugging.md)
- [QoderWork CN Bridge tweak](./qoderworkcn-bridge.md)
- [Owl runtime surface](../OWL-RUNTIME.md)
- [Owl bridge roadmap](../OWL-BRIDGE-ROADMAP.md)

Expand Down
110 changes: 110 additions & 0 deletions docs/tweaks/qoderworkcn-bridge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# QoderWork CN Bridge Tweak

`tweaks/qoderworkcn-bridge` is a bundled local tweak for using QoderWork CN
through Codex's OpenAI Responses provider settings.

It is intentionally implemented as a Codex++ tweak instead of a core runtime
patch:

- the bridge is a local HTTP Responses server, not an MCP server;
- main-process tweak code can start and stop the Node bridge in-process;
- renderer tweak code only shows health status in Codex++ Settings;
- Codex config changes are isolated in managed TOML blocks;
- completed Responses calls are also written to a CodexBar-style usage ledger.

## Local Development

```powershell
node --import tsx packages/installer/src/cli.ts validate-tweak tweaks/qoderworkcn-bridge
node --import tsx packages/installer/src/cli.ts dev tweaks/qoderworkcn-bridge --replace --no-watch
```

The live tweak link is created under:

```text
%APPDATA%\codex-plusplus\tweaks\com.qoderworkcn.responses-bridge
```

## Fresh Machine Setup

This bridge is included as a Codex++ tweak. A new machine still needs the local
QoderWork CN dependency:

1. Install QoderWork CN and sign in.
2. Confirm `qodercli.exe` exists, or set `QODER_CLI` to its path before
launching Codex++.
3. Install or repair Codex++ so the Codex++ runtime loads inside Codex.
4. Enable the tweak, for example from a source checkout:

```powershell
node --import tsx packages/installer/src/cli.ts dev tweaks/qoderworkcn-bridge --replace --no-watch
```

5. Launch Codex through Codex++ and open Settings -> Codex++ -> QoderWork CN
Bridge. The page should show `Bridge: Ready`, `Qoder CLI: Found`, and a
Responses endpoint such as `http://127.0.0.1:38441/v1`.
6. Use the `qoderworkcn-codex` model id from Codex.

Known blockers are missing QoderWork CN login, a non-default `qodercli.exe`
path, unavailable `qmodel` lane, bridge port conflicts, or launching Codex
without the Codex++ runtime.

## Codex Config

At startup, the main-process half updates:

```text
%APPDATA%\codex-plusplus\tweak-data\com.qoderworkcn.responses-bridge\codex-home\config.toml
%APPDATA%\codex-plusplus\tweak-data\com.qoderworkcn.responses-bridge\codex-home\qoderworkcn.config.toml
```

This is intentionally isolated from `%USERPROFILE%\.codex`. To target the
currently launched Codex profile instead, launch Codex++ with
`QODERWORKCN_CODEX_HOME` or `CODEX_HOME` set explicitly.

For Codex Beta isolation on Windows, use a launcher that sets
`CODEX_PLUSPLUS_HOME` to an isolated Codex++ home, points `CODEX_HOME` and
`QODERWORKCN_CODEX_HOME` at the tweak-managed profile in that home, and sets
`QODERWORKCN_BRIDGE_PORT=38442`.

The default model block sets:

```toml
model = "qoderworkcn-codex"
model_provider = "qoderworkcn-bridge"
model_reasoning_effort = "low"
```

The provider block sets `wire_api = "responses"` and points to:

```text
http://127.0.0.1:38441/v1
```

The Beta isolated launcher overrides this to `http://127.0.0.1:38442/v1` so it
does not collide with the default Codex++ Qoder bridge.

The model catalog path is the absolute path to the tweak's
`bridge/models_catalog.json`.

## CodexBar-Style Usage

Completed QoderWork bridge requests are appended to:

```text
<managed CODEX_HOME>\codexbar-qoderworkcn-usage.jsonl
```

The bridge exposes:

```text
GET http://127.0.0.1:38441/usage
GET http://127.0.0.1:38442/usage # isolated beta launcher
```

The payload mirrors CodexBar's local cost JSON shape: `provider`, `source`,
`updatedAt`, `sessionTokens`, `last30DaysTokens`, `daily[]`, `totals`, and
`modelBreakdowns[]`. Costs are `null` until per-million-token estimates are
provided through `QODERWORKCN_INPUT_USD_PER_1M`,
`QODERWORKCN_OUTPUT_USD_PER_1M`, and optionally
`QODERWORKCN_CACHED_INPUT_USD_PER_1M`.
5 changes: 5 additions & 0 deletions tweaks/qoderworkcn-bridge/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.codexpp-dev-reload
node_modules/
tmp/
*.log
codexbar-qoderworkcn-usage.jsonl
65 changes: 65 additions & 0 deletions tweaks/qoderworkcn-bridge/QODERWORK_BRIDGE_INCIDENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# QoderWork Bridge Repair Notes

## Scope Boundary

This repair must stay inside Codex++ and the QoderWork bridge. Do not patch the
Codex Beta application bundle.

Allowed areas:

- the Codex++ repository's `tweaks/qoderworkcn-bridge` directory
- the user's chosen isolated Codex++ home
- optional wrapper launchers that set isolated environment variables
- the isolated `CODEX_HOME` managed by the tweak

Do not edit:

- the installed Codex or Codex Beta application bundle
- patched app copies produced by Codex++ installers

## Failure

Codex Beta routed requests to QoderWork successfully, but subagents did not
start. The prior bridge appended a text warning when `body.tools` was present:

```text
Tool calling is unavailable through this local text bridge. Answer directly in text.
```

That converted Codex app tools into plain prompt text. QoderWork could execute
some local CLI work, but it could not ask Codex Beta to run native tools such as
`create_thread`.

## Fix Direction

The bridge now:

1. Injects available Responses tools into the QoderWork prompt.
2. Asks QoderWork to emit a strict `<codex_tool_calls>` JSON envelope.
3. Converts recognized calls into Responses `function_call` output items.
4. Includes later `function_call_output` results in the next QoderWork prompt.
5. Directly plans explicit `Subagent A/B/...` startup requests into
`create_thread` calls when QoderWork refuses host-tool envelopes.
6. Accepts both namespaced tools and flat names such as
`codex_app.create_thread` from Codex Beta.

Codex Beta remains responsible for actually executing native tools.

## Current Limits

- QoderWork must comply with the JSON envelope for tool calls.
- The bridge only converts tools that Codex Beta already sent in `body.tools`.
- Unknown tool names are ignored to avoid invalid Responses output.
- Tool execution remains owned by Codex Beta; this tweak does not call Codex
internals directly.
- The host-side subagent planner only handles explicit `Subagent X: ...` lines.
It is intentionally narrow to avoid surprising tool execution.

## Verification

Run from the Codex++ repository:

```powershell
npm test --prefix tweaks/qoderworkcn-bridge/bridge
node --import tsx packages/installer/src/cli.ts validate-tweak tweaks/qoderworkcn-bridge
```
162 changes: 162 additions & 0 deletions tweaks/qoderworkcn-bridge/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# QoderWork CN Bridge

Codex++ tweak that starts the local QoderWork CN Responses bridge and points
Codex at it.

## What It Installs

- Local endpoint: `http://127.0.0.1:38441/v1` by default
- Codex model id: `qoderworkcn-codex`
- QoderWork CN model lane: `qmodel`
- Display label: `QoderWork CN Qwen3.7-Max`
- CodexBar-style usage endpoint: `/usage`
- Structured tool-call bridge for Codex app tools such as background threads

By default the tweak writes managed Codex config into its own isolated profile:

```text
%APPDATA%\codex-plusplus\tweak-data\com.qoderworkcn.responses-bridge\codex-home
```

Set `QODERWORKCN_CODEX_HOME` or `CODEX_HOME` before launching Codex++ to target a
different profile. The first write backs up the existing config in that target
profile to a `config.toml.backup-codexpp-qoderworkcn-*` file.

## Fresh Machine Setup

Installing Codex++ alone only installs the tweak runtime. To use QoderWork CN as
a Codex model provider on a new machine:

1. Install and launch QoderWork CN, then sign in with the account that can use
the `qmodel` lane.
2. Confirm the QoderWork CLI exists. On Windows the default path is:

```text
%LOCALAPPDATA%\Programs\QoderWork CN\resources\bin\qodercli.exe
```

Set `QODER_CLI` before launching Codex++ if your installation uses a
different path.
3. Install/repair Codex++ so Codex loads the Codex++ runtime.
4. Link or install this tweak, for example from a source checkout:

```powershell
node --import tsx packages/installer/src/cli.ts dev tweaks/qoderworkcn-bridge --replace --no-watch
```

5. Start Codex through the Codex++ patched app or shortcut.
6. Open Settings -> Codex++ -> QoderWork CN Bridge and verify `Bridge: Ready`,
`Qoder CLI: Found`, and `Tool bridge: structured-json`.
7. Select or verify the `qoderworkcn-codex` model in Codex. The bridge endpoint
defaults to `http://127.0.0.1:38441/v1`.

Common setup blockers:

- QoderWork CN is not installed, not logged in, or installed at a non-default
path.
- `qmodel` is not available for the signed-in QoderWork CN account.
- another process already owns the configured bridge port.
- Codex was launched without the Codex++ runtime, so the tweak never starts.
- an isolated profile launcher sets a different port such as `38442`; check the
endpoint shown in the settings page.

For an isolated Codex Beta profile, launch Codex with a wrapper that sets
`CODEX_PLUSPLUS_HOME`, `CODEX_HOME`, and `QODERWORKCN_CODEX_HOME` only for that
child process. A separate port such as `QODERWORKCN_BRIDGE_PORT=38442` avoids
collisions with the default Codex++ Qoder bridge. Normal Codex launches keep
their existing profile and default port.

Long-running coding tasks can exceed QoderWork CLI's short interactive response
window. The embedded bridge defaults `QODER_BRIDGE_TIMEOUT_MS` to 2 hours and
keeps streamed Responses requests alive with SSE heartbeats while QoderWork is
still working. Set `QODER_BRIDGE_TIMEOUT_MS=0` to disable the bridge watchdog
entirely.

## CodexBar Usage

The bridge records completed Responses calls to a local JSONL ledger:

```text
<managed CODEX_HOME>\codexbar-qoderworkcn-usage.jsonl
```

`GET /usage` returns a CodexBar-style cost payload with today, rolling 30-day,
daily, total, and model-breakdown token counts. Token counts come from the
bridge's Responses `usage` object. Costs stay empty by default because QoderWork
CN is not billed through a public per-token OpenAI price table.

To enable estimated USD cost, launch Codex++ with per-million-token prices:

```powershell
$env:QODERWORKCN_INPUT_USD_PER_1M="2"
$env:QODERWORKCN_OUTPUT_USD_PER_1M="8"
$env:QODERWORKCN_CACHED_INPUT_USD_PER_1M="0.5"
```

## Development

From the Codex++ repository:

```powershell
node --import tsx packages/installer/src/cli.ts validate-tweak tweaks/qoderworkcn-bridge
node --import tsx packages/installer/src/cli.ts dev tweaks/qoderworkcn-bridge --replace --no-watch
```

Then start Codex through the Codex++ patched app or shortcut and open the
Codex++ settings page for `QoderWork CN Bridge`.

## Environment

The embedded bridge keeps the same environment variables as the standalone
`qoderworkcn-responses-bridge` project:

| Variable | Default |
| --- | --- |
| `QODER_CLI` | `%LOCALAPPDATA%\Programs\QoderWork CN\resources\bin\qodercli.exe` |
| `QODER_STORAGE_DIR` | `%USERPROFILE%\.qoderworkcn` |
| `QODER_RESOURCE_DIR` | same as `QODER_STORAGE_DIR` |
| `QODER_SITE` | `cn` |
| `QODER_MODEL` | `qmodel` |
| `QODER_BRIDGE_HOST` | `127.0.0.1` |
| `QODERWORKCN_BRIDGE_PORT` | `38441` |
| `QODER_BRIDGE_PORT` | `38441` legacy alias |
| `QODER_BRIDGE_TIMEOUT_MS` | `7200000` |
| `QODERWORKCN_CODEX_HOME` | Codex++ tweak-data isolated profile |
| `QODERWORKCN_USAGE_LEDGER` | `<CODEX_HOME>\codexbar-qoderworkcn-usage.jsonl` |
| `QODERWORKCN_INPUT_USD_PER_1M` | unset |
| `QODERWORKCN_OUTPUT_USD_PER_1M` | unset |
| `QODERWORKCN_CACHED_INPUT_USD_PER_1M` | unset |

`qmodel` is the QoderWork CN lane whose local dynamic text labels as
`Qwen3.7-Max`.

## Tool Calls / Subagents

Codex Beta sends Responses `tools` to the provider when app tools are available.
The bridge does not modify Codex Beta app files. Instead, it injects the exact
tool names and JSON schemas into QoderWork's prompt and asks QoderWork to return
tool calls in this envelope:

```text
<codex_tool_calls>
[{"name":"create_thread","arguments":{"prompt":"..."}}]
</codex_tool_calls>
```

The bridge converts that envelope into standard Responses `function_call` output
items. Codex Beta then executes its own native tools, such as `create_thread`,
and sends `function_call_output` items back on the next Responses request. The
bridge includes those tool results in the next QoderWork prompt so QoderWork can
continue or summarize.

Because QoderWork may reject host-tool envelopes as non-native tools, the bridge
also contains a narrow host-side planner for explicit subagent startup prompts.
When the user prompt clearly contains lines like `Subagent A: ...` and Codex
sent a `create_thread` tool, the bridge directly returns `create_thread`
function calls without invoking QoderWork first. This only starts the Codex
subagents; later tool outputs still flow back through the bridge for summary.
The planner accepts both namespace-shaped tools and flat tool names such as
`codex_app.create_thread`, matching the formats seen from Codex Beta.

Ordinary QoderWork text still returns as a normal assistant message. Unknown
tool names are ignored instead of returning invalid tool calls.
Loading