Skip to content

Commit 32eabb3

Browse files
authored
Merge dev for v2.1.6
Merge dev into main for npm release v2.1.6.
2 parents bbd84b1 + 73de1f3 commit 32eabb3

30 files changed

Lines changed: 1822 additions & 65 deletions

README.ko.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ codex -m "xai/grok-4" "이 PR을 리뷰해 줘"
112112
|---|---|---|
113113
| OpenAI (ChatGPT 로그인) | `openai-responses` | forward (키 불필요) |
114114
| OpenAI (API 키) | `openai-responses` | key |
115+
| Umans AI Coding Plan | `anthropic` | key |
115116
| Anthropic Claude | `anthropic` | oauth / key |
116117
| xAI Grok | `openai-chat` | oauth / key |
117118
| Kimi (Moonshot) | `openai-chat` | oauth / key |

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ Routed models also appear in the **Codex App** model picker with per-model reaso
132132
|---|---|---|
133133
| OpenAI (ChatGPT login) | `openai-responses` | forward (no key) |
134134
| OpenAI (API key) | `openai-responses` | key |
135+
| Umans AI Coding Plan | `anthropic` | key |
135136
| Anthropic Claude | `anthropic` | oauth / key |
136137
| xAI Grok | `openai-chat` | oauth / key |
137138
| Kimi (Moonshot) | `openai-chat` | oauth / key |
@@ -243,6 +244,22 @@ Local models work too. Point opencodex at any OpenAI-compatible server running o
243244

244245
WebSocket transport is off by default. Set `"websockets": true` only if you want Codex to advertise and use the Responses WebSocket path instead of HTTP/SSE.
245246

247+
opencodex leaves existing Codex resume history untouched by default. This avoids changing Codex's
248+
local thread index just because the proxy started, but Codex App may hide old OpenAI-backed project
249+
threads and opencodex-created `exec` threads while `opencodex` is the active provider. If you want
250+
those chats to appear while the proxy is active, enable the reversible compatibility remap with
251+
`"syncResumeHistory": true`. opencodex records the original provider/source metadata in
252+
`~/.opencodex/codex-history-backup.json`. `ocx stop` / `ocx restore` restores backed-up OpenAI rows
253+
to OpenAI, and ejects any remaining opencodex user threads to OpenAI as well so native Codex does not
254+
try to resume a thread whose provider no longer exists in `config.toml`.
255+
256+
If you tested an older development build where `syncResumeHistory` already remapped history before
257+
backup support existed, you can also run the explicit recovery command:
258+
259+
```bash
260+
ocx recover-history --legacy-openai
261+
```
262+
246263
See the **[Configuration reference](https://lidge-jun.github.io/opencodex/reference/configuration/)** for every field.
247264

248265
## Documentation

README.zh-CN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ codex -m "deepseek/deepseek-r1" "分析这个性能瓶颈"
106106
|---|---|---|
107107
| OpenAI(ChatGPT 登录) | `openai-responses` | 转发(无需 key) |
108108
| OpenAI(API key) | `openai-responses` | key |
109+
| Umans AI Coding Plan | `anthropic` | key |
109110
| Anthropic Claude | `anthropic` | oauth / key |
110111
| xAI Grok | `openai-chat` | oauth / key |
111112
| Kimi(Moonshot) | `openai-chat` | oauth / key |
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# 220 Codex App history visibility
2+
3+
## Goal
4+
5+
Investigate and fix the Codex App project-sidebar history visibility regression around `ocx start` / `ocx stop`, issue #11, and PR #13.
6+
7+
The fix must preserve user data by default, document the exact reproduction, explain the Codex App filtering semantics we can infer from `codex-rs` and local state, and avoid broad irreversible mutation of the user's real `~/.codex/state_5.sqlite`.
8+
9+
## User reproduction
10+
11+
The local `ocx` binary is the development checkout:
12+
13+
- `/Users/jun/.local/bin/ocx`
14+
- `/Users/jun/Developer/new/700_projects/opencodex/dist/bin/ocx`
15+
- `/Users/jun/Developer/new/700_projects/opencodex/src/cli.ts`
16+
17+
Observed behavior:
18+
19+
1. `ocx start` makes all Codex App project conversations disappear from the sidebar, including old OpenAI conversations and conversations created while opencodex was active.
20+
2. `ocx stop` makes old OpenAI-side conversations visible again.
21+
3. Conversations created while opencodex was active remain invisible after `ocx stop`.
22+
23+
## Current evidence
24+
25+
Local config evidence:
26+
27+
- `/Users/jun/.opencodex/config.json` currently has no `syncResumeHistory` key, so PR #13's default is "do not rewrite resume history".
28+
- `~/.codex/config.toml` can be in native mode after `ocx stop`, with no root `model_provider = "opencodex"`.
29+
30+
Local Codex state evidence from `~/.codex/state_5.sqlite`:
31+
32+
| Row set | model_provider | source | Count / effect |
33+
| --- | --- | --- | --- |
34+
| App/CLI resumable rows | `openai` | `cli`, `vscode` | Visible when native OpenAI provider is active |
35+
| opencodex-created project rows | `opencodex` | `exec` | Not visible in Codex App project sidebar |
36+
| opencodex `cli`/`vscode` rows | `opencodex` | `cli`, `vscode` | None found in current local state |
37+
38+
Working hypothesis:
39+
40+
- Codex App visibility is not controlled by provider alone.
41+
- It likely filters by both `threads.model_provider` and a resumable/source classification.
42+
- Old OpenAI rows disappear during `ocx start` because the active/root provider becomes `opencodex`.
43+
- opencodex-created rows stay hidden because they are mostly `source = 'exec'`, not `cli` or `vscode`.
44+
45+
## Current PR #13 behavior
46+
47+
PR #13 is already merged locally on `dev` for testing.
48+
49+
It changes the default from automatic resume-history rewriting to explicit opt-in:
50+
51+
- Default: leave history unchanged.
52+
- `syncResumeHistory: true`: remap resumable OpenAI rows to opencodex during `ocx start`.
53+
- `ocx stop`: remap opencodex rows back to OpenAI using the existing restoration path.
54+
55+
Limitation:
56+
57+
- #13 is a safety improvement, not the full #11 fix.
58+
- It only addresses the provider-label side of the problem.
59+
- It does not make opencodex-created `source = 'exec'` rows visible in Codex App.
60+
61+
## Plan
62+
63+
### P / A: document and audit
64+
65+
- Create this devlog file as the durable issue record.
66+
- Correctly notify GitHub issue #11 and PR #13 that investigation is underway with the refined reproduction and current hypothesis.
67+
- Run a read-only audit worker against the plan and the local code anchors before editing behavior.
68+
69+
### B: investigate and implement
70+
71+
- Inspect local `codex-rs` / Codex App sources or installed artifacts for thread filtering semantics around `model_provider`, `source`, `thread_source`, `cwd`, `archived`, and `has_user_event`.
72+
- Re-check the local SQLite schema and representative rows without mutating the real DB.
73+
- Design the smallest opencodex-side compatibility fix that can make old OpenAI rows and opencodex-created rows visible without unsafe broad mutation.
74+
- Preserve reversibility. If metadata must be changed, record original values before changing them and restore only rows opencodex touched.
75+
76+
### C: verify
77+
78+
- Add unit tests against temporary SQLite fixtures only.
79+
- Run targeted tests first, then full `bun test tests`.
80+
- Run `bun run typecheck`.
81+
- Verify no test or script mutates the real `~/.codex/state_5.sqlite`.
82+
83+
### D: report
84+
85+
- Summarize the root cause in plain Korean.
86+
- List exact files changed.
87+
- Include verification commands and results.
88+
- Note remaining Codex App upstream limitation if any behavior can only be fully fixed in `codex-rs`.
89+
90+
## Likely files
91+
92+
Likely code files:
93+
94+
- `/Users/jun/Developer/new/700_projects/opencodex/src/codex-history-provider.ts`
95+
- `/Users/jun/Developer/new/700_projects/opencodex/src/codex-inject.ts`
96+
- `/Users/jun/Developer/new/700_projects/opencodex/src/types.ts`
97+
98+
Likely tests:
99+
100+
- `/Users/jun/Developer/new/700_projects/opencodex/tests/codex-history-provider.test.ts`
101+
- `/Users/jun/Developer/new/700_projects/opencodex/tests/codex-inject.test.ts`
102+
103+
Likely docs:
104+
105+
- `/Users/jun/Developer/new/700_projects/opencodex/README.md`
106+
- `/Users/jun/Developer/new/700_projects/opencodex/docs-site/src/content/docs/reference/configuration.md`
107+
- `/Users/jun/Developer/new/700_projects/opencodex/docs-site/src/content/docs/ko/reference/configuration.md`
108+
- `/Users/jun/Developer/new/700_projects/opencodex/docs-site/src/content/docs/zh/reference/configuration.md`
109+
110+
## Safety rules
111+
112+
- Do not mutate the user's real Codex DB while testing.
113+
- Do not broaden `ocx start` default behavior into silent history rewriting without an explicit config or user action.
114+
- Do not let `ocx stop` broadly rewrite all `opencodex` rows to `openai` if the implementation starts producing genuinely opencodex-owned visible rows.
115+
- Prefer reversible metadata backup over pattern-based rollback.
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# Codex App / codex-rs findings
2+
3+
## Summary
4+
5+
The sidebar disappearance is caused by two independent filters in Codex App / app-server:
6+
7+
1. Provider filter: when `model_providers` is omitted, app-server defaults to the active configured provider.
8+
2. Source filter: when `source_kinds` is omitted or empty, app-server defaults to `INTERACTIVE_SESSION_SOURCES`.
9+
10+
In the local codex-rs checkout at `/Users/jun/Developer/codex/codex-cli/codex-rs`, `INTERACTIVE_SESSION_SOURCES` is:
11+
12+
```text
13+
cli
14+
vscode
15+
custom atlas
16+
custom chatgpt
17+
```
18+
19+
It does not include `exec`.
20+
21+
## Source anchors
22+
23+
codex-rs source anchors:
24+
25+
- `/Users/jun/Developer/codex/codex-cli/codex-rs/rollout/src/lib.rs`
26+
- `INTERACTIVE_SESSION_SOURCES` includes `Cli`, `VSCode`, `Custom("atlas")`, `Custom("chatgpt")`.
27+
- `/Users/jun/Developer/codex/codex-cli/codex-rs/app-server/src/filters.rs`
28+
- `compute_source_filters(None)` returns `INTERACTIVE_SESSION_SOURCES`.
29+
- `compute_source_filters(Some(Vec::new()))` also returns `INTERACTIVE_SESSION_SOURCES`.
30+
- `ThreadSourceKind::Exec` requires an explicit source filter.
31+
- `/Users/jun/Developer/codex/codex-cli/codex-rs/app-server/src/request_processors/thread_processor.rs`
32+
- `model_providers: None` becomes `Some(vec![self.config.model_provider_id.clone()])`.
33+
- `source_kinds` flows through `compute_source_filters()`.
34+
- Those filters are passed to `thread_store.list_threads()`.
35+
- `/Users/jun/Developer/codex/codex-cli/codex-rs/state/src/runtime/threads.rs`
36+
- SQL filter applies `threads.archived = 0`, `threads.preview <> ''`, optional `threads.source IN (...)`, optional `threads.model_provider IN (...)`, and optional `threads.cwd IN (...)`.
37+
38+
## Local DB evidence
39+
40+
Read-only query against `/Users/jun/.codex/state_5.sqlite` for project cwd `/Users/jun/Developer/new/700_projects/opencodex`:
41+
42+
| model_provider | source | count |
43+
| --- | --- | ---: |
44+
| `openai` | `cli` | 7 |
45+
| `openai` | `exec` | 2 |
46+
| `opencodex` | `exec` | 43 |
47+
| `opencodex` | subagent thread-spawn JSON | 2 |
48+
49+
Default Codex App list while opencodex is active:
50+
51+
```sql
52+
WHERE archived = 0
53+
AND preview <> ''
54+
AND source IN ('cli', 'vscode', 'atlas', 'chatgpt')
55+
AND model_provider = 'opencodex'
56+
```
57+
58+
That returns zero rows locally because opencodex-created project rows are `source = 'exec'`.
59+
60+
## Upstream patch direction
61+
62+
The cleaner upstream fix would be in Codex App / codex-rs:
63+
64+
- either request `sourceKinds` including `exec` for the project sidebar,
65+
- or make the project sidebar intentionally provider/source agnostic when the user is browsing project history,
66+
- or expose a UI affordance for source filtering.
67+
68+
opencodex cannot change Codex App's `thread/list` request payload. The opencodex-side fix therefore must be an explicit compatibility mode that temporarily adjusts local metadata and restores it later.
69+
70+
## opencodex fix direction
71+
72+
For `syncResumeHistory: true`:
73+
74+
- backup original thread metadata into `~/.opencodex/codex-history-backup.json`;
75+
- remap old OpenAI `cli`/`vscode` rows to `model_provider = 'opencodex'`;
76+
- promote opencodex-created user `exec` rows to `source = 'cli'`;
77+
- update the rollout JSONL first `session_meta` line consistently so Codex's rollout scanner does not repair the DB back to the hidden state;
78+
- on `ocx stop` / `ocx restore`, restore only rows recorded in the backup manifest.
79+
80+
Default remains unchanged: no history mutation unless the user explicitly enables `syncResumeHistory`.
81+
82+
## Legacy PR #13 upgrade edge
83+
84+
There is one unsafe-to-automate edge case:
85+
86+
1. A user enabled `syncResumeHistory: true` on a development build before backup support existed.
87+
2. That build remapped old `openai` interactive rows to `opencodex`.
88+
3. The user upgrades while those rows are still remapped.
89+
4. The new backup manifest does not exist, so `ocx stop` cannot know which `opencodex` interactive rows were originally OpenAI rows.
90+
91+
The fix must not silently rewrite all `opencodex` `cli`/`vscode` rows to `openai`, because future or app-created rows can legitimately be opencodex-owned. Instead:
92+
93+
- normal `ocx stop` detects and reports ambiguous unbacked rows;
94+
- it leaves them unchanged by default;
95+
- `ocx recover-history --legacy-openai` is the explicit manual recovery path for users who know those rows came from the old remap.
96+
97+
## 2026-06-22 correction: native restore cannot leave opencodex providers behind
98+
99+
Live local testing showed that the conservative "leave unbacked opencodex rows unchanged" approach
100+
breaks Codex App after `ocx stop`:
101+
102+
```text
103+
Codex can't load config.toml, so this thread can't resume.
104+
Fix config.toml: Model provider `opencodex` not found.
105+
```
106+
107+
The root cause is straightforward: `ocx stop` removes `[model_providers.opencodex]` from
108+
`~/.codex/config.toml`. Any remaining `threads.model_provider = 'opencodex'` row can therefore point
109+
Codex App at a provider id that no longer exists. This applies not only to legacy `cli`/`vscode` rows,
110+
but also to opencodex-created `exec` rows and subagent rows if the user resumes them directly.
111+
112+
Revised opencodex invariant:
113+
114+
- while opencodex is active, `syncResumeHistory: true` may remap/promote history so the App sidebar is visible;
115+
- after native restore (`ocx stop`, `ocx restore`, uninstall), no user thread should be left with
116+
`model_provider = 'opencodex'` unless the Codex config still contains that provider;
117+
- backed-up OpenAI rows restore to OpenAI;
118+
- opencodex-owned user rows are ejected to `openai`, and `exec` source is promoted to `cli`, so native
119+
Codex can list/resume them after the proxy provider has been removed;
120+
- root `model = "provider/model"` values are also stripped on native restore because provider-prefixed
121+
routed model ids are invalid without the opencodex provider/catalog.
122+
123+
Local repair evidence after the correction:
124+
125+
- `ocx recover-history --legacy-openai` recovered 218 user thread rows to `openai`;
126+
- `ocx stop` left zero user rows with `model_provider = 'opencodex'`;
127+
- `~/.codex/config.toml` no longer contains `[model_providers.opencodex]`, root
128+
`model_provider = "opencodex"`, or root `model = "provider/model"`.

0 commit comments

Comments
 (0)