Skip to content
Merged
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
75 changes: 75 additions & 0 deletions docs/custom-fork/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# 架构与进程边界

## 目标拓扑

```text
手机或电脑浏览器
|
| HTTPS/HTTP + WebSocket
v
FRP
|
v
codexapp Node/Express/Vite 后端
|
| stdin/stdout JSON-RPC
v
Codex App Server 子进程
|
+--> Codex CLI 安装/命令解析
+--> 项目目录与 Git worktree
+--> CODEX_HOME 中的会话、配置与认证状态
```

Windows 11 与 Ubuntu 24.04 各自运行这一整套链路。两台主机不能共享 PID、内存状态或本地项目路径;需要共享的会话信息只能通过各自主机可访问的 `CODEX_HOME`/项目存储机制协调。

## 当前实现

- `src/server/codexAppServerBridge.ts` 中的 `AppServerProcess` 负责解析 Codex 命令、启动 app-server、初始化 JSON-RPC、维护 pending RPC、server request、通知订阅和部分 thread 缓存。
- 主 app-server、登录流程和临时 app-server 在 PR #203 后统一使用 `resolveCodexCommand()` 与 `getSpawnInvocation()`。
- 浏览器通过 `/codex-api/rpc` 和 `/codex-api/ws` 访问 bridge。WebSocket `close` 只取消通知 listener;当前代码不会因浏览器断开自动调用 `turn/interrupt`。
- app-server 退出时,当前 pending RPC 会被 reject,pending approval/request map 会清空。
- `dispose()` 会结束 stdin、发送 `SIGTERM`,并在 1.5 秒后尝试 `SIGKILL`。Windows 上 signal 的最终语义必须通过集成测试确认。

## 生命周期结论

### 浏览器关闭

- 应只影响浏览器连接和 WebSocket notification subscription。
- 不应停止 `codexapp`,不应停止 app-server,不应中断活动 turn。
- 重新打开后应依赖 `thread/read`/`thread/list` 与持久状态重新对账,而不是依赖旧浏览器内存。

### codexapp 退出

- HTTP/WS 服务消失,bridge 内存状态丢失。
- 由该 bridge 创建的 app-server 不再可被可靠控制;部署和退出处理必须确保子进程被回收。
- 这与单纯关闭浏览器不同。

### app-server 重启

- 活动 turn 可能被中断。
- 所有旧 generation 的 pending RPC、approval 和 notification 不能继续被视为有效。
- Web 端口、FRP 地址和 Node/Express 进程可以保持不变。这是未来 Runtime Reload 的边界。

## 配置签名现状

当前 `getAppServerConfigSignature()` 只序列化最终 app-server `args` 和 bridge 额外注入的 `env`。它不直接哈希 `config.toml`、`auth.json` 或这些文件的 mtime/content,因此不能声称 CC Switch 对任意配置/认证变化都一定触发自动重启。

未来实现必须:

- 只对允许的文件元数据或脱敏摘要做签名;绝不记录原文或 Token。
- 手动重载始终重新解析 Codex 命令、Provider、模型和当前环境。
- 为每次 app-server 实例分配单调递增 generation。
- 所有旧 generation 的 RPC 和审批必须快速失败,不得永久挂起。

## Codex Desktop 边界

- Codex Desktop 与 `codexapp` 通常各自启动 app-server;重载其中一个不等于重启另一个。
- 两者可读取相同 `CODEX_HOME`,但内存缓存、项目白名单、workspace roots、选中 thread 和流式状态仍可能不同。
- Desktop 状态文件只能只读解析已确认的项目字段;不得修改或把完整 JSON 返回浏览器。

## 未来模块边界

- Runtime lifecycle 应集中在 bridge/runtime 模块,不把 restart 逻辑散落到路由和 Vue 组件。
- Project discovery 应拆成 Desktop state reader、thread pagination、path canonicalization、matching 和 preview/apply 五个可测试边界。
- Timeline 先建立纯 reducer 和旧 `UiMessage[]` 适配器,再迁移组件;不得一次性删除 `ThreadConversation.vue`。
48 changes: 48 additions & 0 deletions docs/custom-fork/CODEX_DESKTOP_PARITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Codex Desktop Parity 工作流

Parity 的目标是对齐可观察行为和数据语义,不是复制 Desktop 私有源码、解包资源或内部实现。

## 每个可见改动的顺序

1. 在同一任务、同类 thread 和接近的窗口尺寸下观察 Codex Desktop。
2. 记录布局、间距、字体层级、状态文案、事件顺序、展开/折叠、滚动与断线恢复。
3. 保存 `codex-desktop-reference`、`web-before`、`web-after` 截图。
4. 建立差异清单,并给每项标记 `fixed`、`intentional deviation` 或 `needs follow-up`。
5. 基于 Codex App Server 的公开 Thread/Turn/Item 数据自行实现。
6. 在 light/dark、375x812、768x1024 和桌面视口复测。

## 数据模型目标

```text
Thread
Turn
TimelineEntry
```

`TimelineEntry` 至少覆盖 user/assistant、reasoning、commandExecution、fileChange、plan、approval、mcpTool、error、image、attachment。持久历史与实时事件必须进入同一 reducer,并按 threadId/turnId/itemId 去重。

## 渐进迁移

1. 新建纯数据结构和 `applyTimelineEvent(state, event)` 单测。
2. 建立从现有 `UiMessage[]` 到 Timeline 的适配层。
3. 先让新 reducer 在影子模式对账,不改变 UI。
4. 逐类迁移 Worked、command、fileChange、plan、approval。
5. 最后替换主 conversation 容器;在此之前保留 `ThreadConversation.vue` 回退。

## 当前差异与状态

| 项目 | 状态 | 说明 |
| --- | --- | --- |
| 模型能力菜单 | fixed in integration | PR #209 按真实 metadata 限定 reasoning levels |
| Windows 本地链接 | fixed in integration | PR #212 修复 `/C:/...` 后端解析 |
| Turn 分组与统一 reducer | needs follow-up | 当前仍主要使用扁平 `UiMessage[]` |
| Worked/文件修改主数据源 | needs follow-up | 需要统一 fileChange/item/diff/persisted 优先级 |
| 断线恢复 | needs follow-up | 先做诊断与 reducer 对账 |
| Desktop 项目同步 | needs follow-up | 当前 workspace roots 与 Desktop 状态独立 |

## 禁止事项

- 不提交 Desktop 解包代码、私有资源、字体或图标。
- 不只凭颜色/像素模仿而忽略 event/data model。
- 不为一次截图删除窗口化、懒加载或错误恢复。
- 不一次性删除旧 conversation 实现。
117 changes: 117 additions & 0 deletions docs/custom-fork/DEPLOYMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Windows 11 与 Ubuntu 24.04 部署

本文只记录可审计的部署形态。任何 `auth.json`、Token、API Key、FRP authentication token 或完整 `config.toml` 都不得写入仓库、命令输出或日志。

## 共同前置条件

- 从本 Fork 的固定 commit 构建,不直接信任来源不明的 npm 构建产物。
- Node.js 18+;当前 Windows 验证版本为 22.16.0。
- 当前仓库没有 lockfile。增加 lockfile 前,依赖安装不能声称完全可复现;生产更新必须保留上一个 build 和 commit 作为回滚点。
- 使用已经登录的全局 Codex CLI;除非明确要求隔离,不复制认证文件到临时项目。
- 对外访问通过 FRP/反向代理,`codexapp` 本身只监听预期接口和端口。

## 构建

当前可验证命令:

```powershell
$env:COREPACK_ENABLE_PROJECT_SPEC = '0'
corepack pnpm@10.18.3 install --lockfile=false
corepack pnpm@10.18.3 run test:unit
corepack pnpm@10.18.3 run build
node dist-cli/index.js --help
```

`test:unit` 在 Windows 的两项平台限制见 `TEST_PLAN.md`,不能把非零退出码简单忽略;必须确认失败集合没有扩大。

## Windows 11

### 建议目录与环境

| 项目 | 建议值 |
| --- | --- |
| 运行用户 | 登录并持有 Codex CLI 认证的普通用户,不使用 SYSTEM 启动 codexapp |
| `CODEX_HOME` | `%USERPROFILE%\.codex`,或明确配置的用户级目录 |
| 工作目录 | 本 Fork 固定 commit 的 checkout 或只读 release 目录 |
| 监听端口 | 例如 `5900`,与 FRP `local_port` 一致 |
| 日志 | 用户可写的独立日志目录;定期轮转,不记录环境变量全文 |

### 启动命令

```powershell
$env:CODEX_HOME = "$env:USERPROFILE\.codex"
node D:\path\to\codex-mobile\dist-cli\index.js `
--port 5900 `
--no-open `
--no-tunnel `
--no-login
```

计划任务建议:

- 触发器:目标用户登录时。
- 用户:持有认证的普通用户。
- `Start in`:固定 checkout/release 目录。
- 失败重试:有限次数并写事件/文本日志,避免无限重启循环。
- 不把 Token 放在任务参数中;敏感配置使用既有用户级安全存储。

FRP 建议作为独立服务/任务运行,配置只包含本地地址、端口和服务端分配信息;仓库只记录脱敏模板:

```toml
[[proxies]]
name = "codexapp-windows"
type = "tcp"
localIP = "127.0.0.1"
localPort = 5900
remotePort = 0 # 由部署环境填写
```

完整 codexapp 重启会影响 bridge 和 app-server。未来的 `Reload Codex Engine` 只重启 app-server,不能替代进程级升级重启。

## Ubuntu 24.04

建议使用 `systemd --user`,让服务以持有 Codex 认证的登录用户运行。

```ini
[Unit]
Description=CodexApp custom fork
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
WorkingDirectory=/opt/codex-mobile
Environment=CODEX_HOME=%h/.codex
ExecStart=/usr/bin/node /opt/codex-mobile/dist-cli/index.js --port 5900 --no-open --no-tunnel --no-login
Restart=on-failure
RestartSec=5

[Install]
WantedBy=default.target
```

启用与日志:

```bash
systemctl --user daemon-reload
systemctl --user enable --now codexapp.service
journalctl --user -u codexapp.service -n 200 --no-pager
```

需要无交互登录后继续运行时,单独评审 `loginctl enable-linger <user>` 的安全影响。FRP 使用独立 user/system service,不能把 Codex 认证写入 FRP unit。

## 升级流程

1. 记录生产 commit、Node/Codex CLI 版本和当前健康状态。
2. 在非生产目录构建并运行单测、build、CLI smoke。
3. 备份可恢复的部署配置与当前 build;不复制或打印认证内容。
4. 选择维护窗口,确认没有活动 turn 或明确接受中断。
5. 切换到新 build,重启 codexapp 服务。
6. 验证 HTTP、WebSocket、thread/list、模型列表和一个只读项目路径。
7. 失败时恢复旧 build/commit 并重启,不对 `CODEX_HOME` 做破坏性清理。

## 当前待补实测

- Windows 计划任务的最终名称、启动脚本和日志路径需要在部署主机确认后填写。
- Ubuntu unit 尚未在目标 24.04 主机执行。
- FRP TLS/auth、服务端端口和防火墙策略属于部署私密配置,不进入仓库。
53 changes: 53 additions & 0 deletions docs/custom-fork/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Custom Fork 维护入口

本目录记录 `CYZice/codex-mobile` 相对 `friuns2/codex-mobile` 的维护边界、运行架构、需求、测试证据和后续路线。目标环境是 Windows 11 主机与 Ubuntu 24.04 主机,各自运行独立的 `codexapp`,通过 FRP 提供受控的远程浏览器访问。

## 核心关系

```text
浏览器
-> FRP
-> codexapp HTTP/WebSocket
-> codex app-server JSON-RPC
-> Codex CLI + 项目目录 + CODEX_HOME
```

- Codex Desktop 不需要保持开启,`codexapp` 自己创建并持有 app-server。
- 浏览器关闭只应断开 UI/通知订阅,不应自动调用 `turn/interrupt`。
- `codexapp` 后端必须持续运行;其退出或 app-server 重载会影响活动 turn。
- Codex Desktop 与 `codexapp` 通常拥有不同的 app-server 进程。两者可读取同一个 `CODEX_HOME`,但项目白名单、缓存和 UI 状态不保证一致。
- 不在仓库、日志、文档或浏览器响应中保存 `auth.json`、API Key、Access Token、Refresh Token。

## 当前状态

截至 2026-07-27,以下工作位于 `integration/upstream-prs`,尚未声明已经进入 `main`:

- 已选择性集成 PR #203:Windows Codex CLI 解析。
- 已选择性集成 PR #209:按模型能力显示 `max/ultra` 推理等级,并增加无元数据模型的保守回退。
- 已选择性集成 PR #212:Windows `/C:/...` 本地浏览路径修复。
- 已建立本目录的维护、架构、部署、安全、同步、需求、测试和 Desktop parity 文档。
- PR #211 Goal mode 按用户要求排除。
- Runtime Reload、Project Sync、Timeline 重构和断线诊断仍为规划项,未实现。

## 已知限制

- 仓库当前没有 lockfile,也没有固定 `packageManager`,依赖安装不能视为完全可复现。
- Windows 11 / Node 22.16.0 下,`pnpm run dev --host 127.0.0.1 --port 4173` 会因 `scripts/dev.cjs` 直接启动 `vite.cmd` 而报 `EINVAL`;本轮 UI 验证使用 Vite JS 入口。
- 全量单元测试存在两项基线 Windows 限制:非管理员 symlink 创建失败,以及 POSIX `0600` mode 断言在 Windows 上不成立。
- 本次真实 RPC 验证中 Codex CLI 0.144.6 的 app-server 启动后退出;涉及模型菜单的 UI 验证使用按 JSON-RPC method 的隔离 stub,不能替代真实 app-server 兼容性验证。

## 文档导航

- [路线图](ROADMAP.md)
- [架构](ARCHITECTURE.md)
- [部署](DEPLOYMENT.md)
- [安全](SECURITY.md)
- [上游同步](UPSTREAM_SYNC.md)
- [需求](REQUIREMENTS.md)
- [测试计划](TEST_PLAN.md)
- [上游 PR 审计](UPSTREAM_PR_AUDIT.md)
- [Codex Desktop Parity](CODEX_DESKTOP_PARITY.md)

## 完成定义

一个阶段只有同时满足以下条件才可标记为完成:代码已提交;相关单测和 build 有真实结果;手动测试步骤已更新;性能风险已审计;已知限制与回滚方式已记录;需要发布时,目标 GitHub 分支和部署环境均已验证。
Loading