codex-adaptive-effort 0.1.0-alpha.1
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.
- package/LICENSE +21 -0
- package/README.en.md +5 -0
- package/README.md +115 -0
- package/README.zh-CN.md +133 -0
- package/THIRD_PARTY_NOTICES.md +23 -0
- package/bin/cae-desktop-bridge.mjs +41 -0
- package/bin/cae.mjs +152 -0
- package/docs/DESKTOP_LAUNCHER.md +122 -0
- package/docs/LIMITATIONS.md +34 -0
- package/docs/LOCAL_VALIDATION.md +83 -0
- package/docs/NPM.md +73 -0
- package/package.json +56 -0
- package/src/audit.mjs +71 -0
- package/src/codex.mjs +101 -0
- package/src/config.mjs +74 -0
- package/src/context.mjs +87 -0
- package/src/controller.mjs +158 -0
- package/src/desktop.mjs +295 -0
- package/src/judge-timing.mjs +44 -0
- package/src/judge.mjs +105 -0
- package/src/proxy.mjs +183 -0
- package/src/stream.mjs +58 -0
- package/src/util.mjs +49 -0
- package/src/version.mjs +3 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Codex Adaptive Effort contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Codex Adaptive Effort
|
|
2
|
+
|
|
3
|
+
[](https://github.com/ppxu/codex-adaptive-effort/actions/workflows/ci.yml)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](package.json)
|
|
6
|
+
|
|
7
|
+
**Keep your Codex model. Adapt its reasoning effort.**
|
|
8
|
+
|
|
9
|
+
Codex Adaptive Effort (CAE) is an experimental local HTTP/SSE proxy that can change `reasoning.effort` for a fixed, user-selected model. It supports the Codex CLI and an isolated instance of the validated Codex desktop application. An optional TypeSafe Jev evaluator recommends effort levels from the model's actual capabilities.
|
|
10
|
+
|
|
11
|
+
[简体中文](README.zh-CN.md) · [Documentation](docs/README.md) · [Acceptance evidence](docs/LOCAL_ACCEPTANCE.md) · [Changelog](CHANGELOG.md)
|
|
12
|
+
|
|
13
|
+
> **Alpha: `0.1.0-alpha.1`.** This is an independent project, not an official OpenAI or TypeSafe plugin. Desktop support is limited to the exact macOS/app/CLI combination documented below. Task quality, cost savings and production reliability are not established.
|
|
14
|
+
|
|
15
|
+
## What it does
|
|
16
|
+
|
|
17
|
+
| Feature | Behavior |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| Fixed execution model | Keeps the selected model, provider, auth route and service tier; other models bypass adaptation |
|
|
20
|
+
| `off` | Forwards requests without evaluation or effort changes |
|
|
21
|
+
| `shadow` (default) | Records recommendations while forwarding the original request |
|
|
22
|
+
| `auto` | Applies a validated effort to eligible requests; preserves all other request fields |
|
|
23
|
+
| Optional Jev evaluation | Sends a bounded text projection to TypeSafe; uses separate credentials and a call limit |
|
|
24
|
+
| Safe fallback | Retains incoming effort on evaluator failure; unsupported histories bypass adaptation |
|
|
25
|
+
| Local controls | Authenticated loopback controls, manual locks, cancellation and bounded decision reuse |
|
|
26
|
+
| Evidence | Metadata-only decisions, actual send events and response completion; no invented savings |
|
|
27
|
+
|
|
28
|
+
The default evaluator is **baseline-only**, a transport test fixture rather than a complexity classifier. Live Jev processing must be explicitly enabled. CAE never rewrites global Codex configuration or reads native login files. Native Codex handles its own login.
|
|
29
|
+
|
|
30
|
+
## Install and run
|
|
31
|
+
|
|
32
|
+
Requires Node.js **22.16+**, npm and an existing Codex installation for native integration. There are no third-party runtime dependencies or install hooks. The npm package is prepared but **not yet published to the registry**. Until its first release, install a reviewed Git commit with npm (requires Git):
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Replace REVIEWED_COMMIT with the full tested Git commit SHA.
|
|
36
|
+
npm install --global --ignore-scripts github:ppxu/codex-adaptive-effort#REVIEWED_COMMIT
|
|
37
|
+
cae --version
|
|
38
|
+
cae --help
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
After the first alpha registry publication, installation will be `npm install --global --ignore-scripts codex-adaptive-effort@alpha`. See the [npm guide](docs/NPM.md) for local archives, upgrades, uninstalling and configuration locations. Global installation provides the command; configuration stays in your chosen working directory.
|
|
42
|
+
|
|
43
|
+
For source development:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://github.com/ppxu/codex-adaptive-effort.git
|
|
47
|
+
cd codex-adaptive-effort
|
|
48
|
+
npm ci --ignore-scripts
|
|
49
|
+
npm run verify
|
|
50
|
+
npm link --ignore-scripts
|
|
51
|
+
cae --help
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Verification uses synthetic data and local test servers; it does not call real model providers. CI runs on Linux, macOS and Windows with Node 22 and 24. Passing CI does not imply native integration on all these platforms.
|
|
55
|
+
|
|
56
|
+
## Quick start: inspect capabilities
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
mkdir cae-trial
|
|
60
|
+
cd cae-trial
|
|
61
|
+
cae doctor
|
|
62
|
+
cae probe > capabilities.local.json
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
These commands inspect the native CLI and query `model/list`; they do not generate model output. If Codex is not on `PATH`, pass `--codex /path/to/trusted/codex`. Select a real model ID and its supported effort values from the capture; do not assume every model supports every effort. Keep captures local and out of version control; this source repository includes ignore rules, but another working directory may not.
|
|
66
|
+
|
|
67
|
+
Continue with the [CLI validation guide](docs/LOCAL_VALIDATION.md) or the [desktop launcher guide](docs/DESKTOP_LAUNCHER.md).
|
|
68
|
+
|
|
69
|
+
## Desktop trial
|
|
70
|
+
|
|
71
|
+
Validated on **macOS 27.0 arm64**, **ChatGPT/Codex desktop 26.924.22138 (build 11645)** and its bundled **codex-cli 0.158.0-alpha.2.1**. The launcher checks the official application signature, exact version, current capabilities and effective provider. Other combinations are rejected pending validation; it does not install or replace native binaries.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Replace MODEL_ID with an ID returned by your native probe.
|
|
75
|
+
cae desktop start --model "$MODEL_ID" --auth chatgpt --enable-upstream
|
|
76
|
+
# In another terminal, from the same working directory:
|
|
77
|
+
cae desktop status
|
|
78
|
+
cae desktop stop
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Use a **new local Codex chat** in the experimental window and a directory containing only non-sensitive test material. Existing chats retain their providers. The instance has separate Electron data but shares native Codex home and login. Ordinary ChatGPT conversations and cloud tasks are outside this integration.
|
|
82
|
+
|
|
83
|
+
Starting the launcher does not submit a task. Sending a task uses the normal model allowance. The default is shadow + baseline. For real Jev evaluation, provide your own `TYPESAFE_API_KEY` through your normal environment setup and add `--enable-jev`:
|
|
84
|
+
|
|
85
|
+
- `--enable-jev`: process-only Jev shadow; `auto` and manual locks remain disabled.
|
|
86
|
+
- Add `--allow-jev-auto`: permits an explicit `control auto` after startup; it does not switch modes automatically.
|
|
87
|
+
- Optional `--jev-timeout-ms 2000`: replaces the timeout for this process only. The default ceiling remains 1500 ms.
|
|
88
|
+
|
|
89
|
+
Desktop Jev trials allow at most eight evaluations per process. A timeout or cancellation may still incur provider usage. Read the [complete controls and recovery procedure](docs/DESKTOP_LAUNCHER.md) before enabling auto.
|
|
90
|
+
|
|
91
|
+
## Validation status
|
|
92
|
+
|
|
93
|
+
Real tests on the documented installation covered CLI transport, desktop off, manual low/high locks, cancellation/recovery, Jev shadow, automatic `medium → high`, automatic `medium → low`, and timeout fallback. The latest downshift took 665 ms with a 2000 ms limit; **this does not show that increasing the limit improves reliability**. Some earlier evaluations timed out, and their root cause remains unresolved.
|
|
94
|
+
|
|
95
|
+
See [versioned acceptance evidence](docs/LOCAL_ACCEPTANCE.md) and [known limitations](docs/LIMITATIONS.md). WebSockets, packaged desktop plugins, `configuration_update`, automatic model routing and full cache optimization are not implemented. Structured tool-result, compacted, incremental or multimodal histories can bypass adaptation, including manual locks.
|
|
96
|
+
|
|
97
|
+
## Stop and restore
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
cae control off --config .cae/desktop/config.json
|
|
101
|
+
cae desktop stop
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`off` still uses the proxy. Stop the experimental instance and return to ordinary Codex to leave the proxy path. No global configuration or login files need restoring. A proxy crash does not automatically switch to a direct connection.
|
|
105
|
+
|
|
106
|
+
## Contribute and get help
|
|
107
|
+
|
|
108
|
+
- Read [Contributing](CONTRIBUTING.md) before opening a pull request.
|
|
109
|
+
- Use [Issues](https://github.com/ppxu/codex-adaptive-effort/issues) for bugs, questions and feature proposals with synthetic reproductions.
|
|
110
|
+
- Follow [Security](SECURITY.md) for vulnerabilities; never attach credentials, raw logs or private task histories.
|
|
111
|
+
- Follow the [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
112
|
+
|
|
113
|
+
## License and provenance
|
|
114
|
+
|
|
115
|
+
[MIT](LICENSE) for this project's original code. Design inspiration and fixed source references are recorded in [Third-party notices](THIRD_PARTY_NOTICES.md). No Codex, Astra-Ares or Jev Codex Router source or binaries are bundled. External services retain their own terms; no model-quality or billing guarantees are made.
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Codex Adaptive Effort(CAE)
|
|
2
|
+
|
|
3
|
+
**固定执行模型,动态调整思考强度。** 这是面向本地 Codex 的实验性开源控制器,设计借鉴 Astra-Ares 的固定模型/决策生命周期,以及 Jev Codex Router 的本地代理/有限判断摘要。
|
|
4
|
+
|
|
5
|
+
**当前版本:`0.1.0-alpha.1`。** 实验性 Node.js 实现,不是官方 Codex 桌面插件。已在一台 macOS arm64 机器上验收 ChatGPT 路线的原生 CLI,以及独立桌面实例的 HTTP/SSE、off、纯文本手动锁档及取消恢复;具体版本、能力和边界见 [本机验收记录](docs/LOCAL_ACCEPTANCE.md) 和 [桌面验收记录](docs/DESKTOP_ACCEPTANCE.md)。另有 8 次真实 Jev 合成样例判断通过协议检查,见 [Jev shadow 记录](docs/JEV_SHADOW_ACCEPTANCE.md);桌面 Jev 自动升档、降档与超时回退均已有真实通过样例,见 [auto 记录](docs/LOCAL_ACCEPTANCE.md);正式安装和其他环境仍未验收。没有节省费用、保持质量或生产可用性的保证。
|
|
6
|
+
|
|
7
|
+
[English](README.md) · [本地验收](docs/LOCAL_VALIDATION.md) · [架构](docs/ARCHITECTURE.md) · [验证记录](docs/VALIDATION.md) · [限制](docs/LIMITATIONS.md)
|
|
8
|
+
|
|
9
|
+
## 已实现
|
|
10
|
+
|
|
11
|
+
| 能力 | 本版行为 |
|
|
12
|
+
|---|---|
|
|
13
|
+
| 固定模型 | 只改已配置模型的 `reasoning.effort`,不自动切模型、服务商、速度档或计费渠道;用户选其他模型时透明旁路 |
|
|
14
|
+
| 三种模式 | 默认 `shadow`:评估但不改请求;`auto`:应用已校验档位;`off`:不评估、不改档 |
|
|
15
|
+
| Jev 判断 | TypeSafe System One 两个 Choice:思考强度、1–4 次生成的决策有效期;支持独立超时和调用次数上限 |
|
|
16
|
+
| 状态控制 | 同会话单活动请求;只有成功完成的请求可建立有效期;新输入、错误、历史改写、手动控制或超时会使旧决策失效 |
|
|
17
|
+
| 手动接管 | 本地认证控制接口,可锁档和取消锁档;只有 `auto` 模式实际改档,锁档不越过不兼容形态保护 |
|
|
18
|
+
| 文本摘要 | Jev 只收到有界文本证据,不接收执行模型认证、加密思考或系统指令;执行模型的完整请求历史不被删减 |
|
|
19
|
+
| 传输 | 只监听 `127.0.0.1`;本地随机令牌;Host/浏览器来源检查;HTTP/SSE 字节透传;不重试、不跟随重定向 |
|
|
20
|
+
| 可观察性 | 建议、准备、发送、响应结果分开记录;Jev 调用和已知用量单独记录;缺失值为未知,不造节省比例 |
|
|
21
|
+
| Codex 辅助 | `doctor`、原生 `model/list` 能力探针、一次性 CLI 启动参数;不修改日常 `config.toml` 或读取登录文件 |
|
|
22
|
+
|
|
23
|
+
**不实现:** WebSocket 代理、原生 Codex 补丁、自动桌面安装、`configuration_update` 注入、多模型路由、配额耗尽换渠道、完整缓存优化。含图片、未知增量上下文、未知历史条目或内容类型、非字符串工具结果、压缩历史或已有配置更新的请求会原样旁路,不调用判断器;手动锁档也不越过此边界。
|
|
24
|
+
|
|
25
|
+
## 用 npm 安装
|
|
26
|
+
|
|
27
|
+
需要 Node.js **22.16+**。npm 包已准备好,**尚未发布到 npm registry**。现在可以通过 npm 安装经过验证的 Git 提交(需要 Git),之后直接使用 `cae` 命令,不必保留源码目录:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# 把 REVIEWED_COMMIT 替换为经过验证的完整提交 SHA。
|
|
31
|
+
npm install --global --ignore-scripts github:ppxu/codex-adaptive-effort#REVIEWED_COMMIT
|
|
32
|
+
cae --version
|
|
33
|
+
cae --help
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
首次发布到 npm 后,安装命令可简化为 `npm install --global --ignore-scripts codex-adaptive-effort@alpha`。完整的安装、升级、卸载和桌面启动步骤见 [npm 使用说明](docs/NPM.md)。配置仍保存在你选择的工作目录;在同一目录执行 `cae desktop start/status/stop`,或者始终传入同一个 `--config`。后文的 `node bin/cae.mjs` 都可以替换成 `cae`。
|
|
37
|
+
|
|
38
|
+
## 从源码离线运行(不需要任何模型密钥)
|
|
39
|
+
|
|
40
|
+
Node.js **22.16+**。运行代码没有第三方 npm 依赖,也没有安装脚本。
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm ci --ignore-scripts
|
|
44
|
+
npm run verify
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`verify` 会做语法检查、自动化测试、五阶段 HTTP/SSE 演示。演示启动的判断器和模型后端都是本地模拟;它证明接线与状态控制,不证明 Jev 判断准确度或真实节省。
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
node bin/cae.mjs --help
|
|
51
|
+
node bin/cae.mjs doctor
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 本地 Codex 接入顺序
|
|
55
|
+
|
|
56
|
+
已验收版本的 macOS arm64 桌面可直接使用实验启动器:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
node bin/cae.mjs desktop start --model gpt-6-astra --auth chatgpt --enable-upstream
|
|
60
|
+
# 在另一终端检查或退出:
|
|
61
|
+
node bin/cae.mjs desktop status
|
|
62
|
+
node bin/cae.mjs desktop stop
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
首次自动创建独立 CAE 配置,每次查询实际模型能力并校验生效的 provider;默认 shadow + baseline,不启用 Jev。`--enable-jev` 显式启用进程级 Jev shadow,最多 8 次判断,禁止 auto/锁档;另外添加 `--allow-jev-auto` 才允许随后通过 `control auto` 开始实验性自动改档。第二组三条桌面 shadow 请求均成功;后续 auto 实测完成 medium → high,另一次 Jev 超时后保持 medium。后续 2000 ms 实验以 665 ms 完成 medium → low;降档通过,放宽超时的改善效果与日常稳定性仍未证实。可显式添加 `--jev-timeout-ms 2000` 进行仅本进程生效的超时实验,默认仍为 1500 ms。请在新实例中新建 Codex 本地任务,旧会话不会自动迁移。版本限制、实例辨认和控制命令见 [桌面启动器说明](docs/DESKTOP_LAUNCHER.md)。
|
|
66
|
+
|
|
67
|
+
先读 [LOCAL_VALIDATION.md](docs/LOCAL_VALIDATION.md),按「原版 → off → 手动 auto → Jev shadow → Jev auto」逐级验证。**这不是默认启用的桌面兼容承诺。** 首版提供可撤销的 CLI 路径验证代理;本机独立桌面实例已通过启动、纯文本 off/手动锁档及取消恢复,见 [桌面检查记录](docs/DESKTOP_ACCEPTANCE.md)。
|
|
68
|
+
|
|
69
|
+
仅查询本机 Codex 公布的模型/档位,不发起生成:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
node bin/cae.mjs probe > capabilities.local.json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
选取探针实际返回的模型 ID,保留原有认证方式。使用 ChatGPT 订阅时:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# MODEL_ID 必须替换为 probe 返回的真实 model 字段。
|
|
79
|
+
node bin/cae.mjs init --auth chatgpt --model "$MODEL_ID" --capabilities capabilities.local.json
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`.cae/` 是新建的隔离控制器目录;已存在时拒绝覆盖。它不是新的 Codex 登录目录。CAE 不打开 `auth.json`;原生 Codex 仍自行处理其正常登录。
|
|
83
|
+
|
|
84
|
+
在明确同意发起真实模型请求后,开两个终端:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# 终端 1:默认仍是 shadow + baseline-only,未接入 Jev。
|
|
88
|
+
node bin/cae.mjs serve --enable-upstream
|
|
89
|
+
|
|
90
|
+
# 终端 2:仅该子进程使用代理,不改日常 Codex 配置。
|
|
91
|
+
node bin/cae.mjs codex --auth chatgpt --
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
ChatGPT 路线已完成上述限定版本的 CLI 与独立桌面实例验收,不能外推到所有客户端版本或普通 ChatGPT 聊天。结构化工具结果的历史仍安全旁路,手动锁档也不越过该保护。出现认证/协议错误时停止接入、保留原版 Codex;不能通过导出 Cookie、拷贝网页凭证或改用 API 付费来假装修复。
|
|
95
|
+
|
|
96
|
+
API 使用者须从初始化起明确选择 `--auth api`,再在自己的终端提供 `OPENAI_API_KEY`。两种路线不能混用,代码会检查。API 请求可能按量计费;此工具不把订阅额度转换成 API 额度。
|
|
97
|
+
|
|
98
|
+
## 启用 Jev
|
|
99
|
+
|
|
100
|
+
建议先执行 [固定合成样例 shadow 验收](docs/JEV_SHADOW_ACCEPTANCE.md):默认只预览,授权后最多 8 次 Jev 请求,不发起 Codex 生成。它用于验证真实判断器;桌面请使用 [Jev shadow 开关](docs/DESKTOP_LAUNCHER.md),下面的磁盘配置步骤用于独立 serve 服务。
|
|
101
|
+
|
|
102
|
+
默认 `judge.kind=baseline` **不是复杂度判断器**,只是接线验收用的固定基准。要接入 Jev:停止服务,在 `.cae/config.json` 将 `judge.kind` 改为 `typesafe`,通过你自己的密钥管理方式设置 `TYPESAFE_API_KEY`,然后显式执行:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
node bin/cae.mjs serve --enable-upstream --enable-jev
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
此时仍从 `shadow` 开始。只有明确切换到 `auto` 才改档:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
node bin/cae.mjs status
|
|
112
|
+
node bin/cae.mjs control auto
|
|
113
|
+
node bin/cae.mjs lock high
|
|
114
|
+
node bin/cae.mjs unlock
|
|
115
|
+
node bin/cae.mjs control off
|
|
116
|
+
node bin/cae.mjs report
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
以上 `high` 必须在你的模型支持集合内。控制是**此 CAE 服务实例级**的,影响其下一次尚未发送的合格请求,不修改正在生成的响应。
|
|
120
|
+
|
|
121
|
+
Jev 调用把有限任务文本发给 TypeSafe,不是本地离线推理;脱敏是尽力处理,不保证消除业务机密。不得把公司代码或敏感任务送入未批准的第三方服务。默认最多 100 次评估/服务进程,重启重置;这是调用次数上限,不是美元预算。取消或超时仍可能已产生服务端费用。
|
|
122
|
+
|
|
123
|
+
## 退出与恢复
|
|
124
|
+
|
|
125
|
+
`control off` 只关闭自动判断,**仍经过代理**。完全恢复:结束这次实验 Codex 进程,停止 CAE 服务,再正常运行原版 `codex` / 官方桌面应用。因为没有写日常配置,不需要回写登录信息。代理进程崩溃不等于自动直连;不承诺不中断地恢复。
|
|
126
|
+
|
|
127
|
+
## 贡献与仓库维护
|
|
128
|
+
|
|
129
|
+
本项目已发布,当前仓库应通过普通 Git 和 Pull Request 继续维护,不要再次运行首次建仓脚本。默认文档语言为英文;请参阅 [文档索引](docs/README.md)、[贡献指南](CONTRIBUTING.md)、[安全说明](SECURITY.md) 和 [发布说明](docs/PUBLISHING.md)。原始中文验收记录保留在文档索引的历史证据部分。
|
|
130
|
+
|
|
131
|
+
## 协议来源与开源边界
|
|
132
|
+
|
|
133
|
+
这是独立实现,没有打包两个上游项目源码或 Codex 二进制;设计来源和固定参考提交见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。本项目代码为 MIT。模型、Jev API、Codex 和账户服务分别受其自身许可与使用条款约束;CAE 不是 OpenAI / TypeSafe 官方产品。
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Provenance and third-party notices
|
|
2
|
+
|
|
3
|
+
This release contains new project code and no vendored Codex, Astra-Ares or Jev Codex Router source or binaries. It does not modify their copyright notices, claim to be an official fork, or relicense external services. No third-party npm dependencies are installed. Node.js and development tooling have their own licenses.
|
|
4
|
+
|
|
5
|
+
Design references inspected on 2026-09-24:
|
|
6
|
+
|
|
7
|
+
| Source | Fixed reference | Design used as inspiration |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| [miuuyy/Astra-Ares](https://github.com/miuuyy/Astra-Ares) | `b2011446d88202329dcdc5163500ca818aba9dbb` | fixed executor identity, bounded generation lease, decision/commit separation, stale-state rejection |
|
|
10
|
+
| [0xNatoshi/jev-codex-router](https://github.com/0xNatoshi/jev-codex-router) | `8701ef788aa8cb0948f299538747fb01029d32b8` | local adapter, small decision projection vs full executor replay, operational bypass, observed-usage reporting |
|
|
11
|
+
|
|
12
|
+
The inspected repositories' top-level licenses are MIT. Astra-Ares also identifies patched OpenAI Codex components as Apache-2.0. Future source imports must preserve the exact applicable licenses/NOTICE and record provenance; these references alone do not grant rights to third-party account services or model weights.
|
|
13
|
+
|
|
14
|
+
Primary protocol references (mutable web documentation, accessed 2026-09-24):
|
|
15
|
+
|
|
16
|
+
- [Codex configuration reference](https://developers.openai.com/codex/config-reference/): custom provider, Responses wire API, environment headers, native auth and WebSocket configuration.
|
|
17
|
+
- [Codex App Server](https://developers.openai.com/codex/app-server): initialize / initialized / model/list; returned effort capabilities.
|
|
18
|
+
- [OpenAI reasoning guide](https://developers.openai.com/api/docs/guides/reasoning): request effort vs mid-conversation configuration updates and their restrictions. This release **does not implement configuration_update**.
|
|
19
|
+
- [TypeSafe API](https://docs.typesafe.ai/api): System One `state` + typed Choice questions, `/v1/systemone`.
|
|
20
|
+
- [TypeSafe language support](https://docs.typesafe.ai): Jev is text-based; real Chinese follow-up performance requires evaluation.
|
|
21
|
+
- [GitHub CLI repository creation](https://cli.github.com/manual/gh_repo_create): explicit public creation from a local source directory.
|
|
22
|
+
|
|
23
|
+
The ChatGPT backend path is an experimental compatibility route, not a promise that third-party proxying is officially supported. Native authentication/transport requirements may make a given client version incompatible. Never repair that by scraping or exporting credentials.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { loadConfig, readLocalToken } from '../src/config.mjs';
|
|
4
|
+
import { codexArgs } from '../src/codex.mjs';
|
|
5
|
+
import { verifyDesktopProvider, desktopControl } from '../src/desktop.mjs';
|
|
6
|
+
import { CaeError } from '../src/util.mjs';
|
|
7
|
+
|
|
8
|
+
async function main() {
|
|
9
|
+
const [configPath, binary, ...input] = process.argv.slice(2);
|
|
10
|
+
if (!configPath || !binary) throw new CaeError('desktop_bridge_arguments');
|
|
11
|
+
const config = loadConfig(configPath);
|
|
12
|
+
let index = 0;
|
|
13
|
+
while (index < input.length) {
|
|
14
|
+
if (['-c', '--config'].includes(input[index]) && index + 1 < input.length) index += 2;
|
|
15
|
+
else if (input[index].startsWith('--config=')) ++index;
|
|
16
|
+
else break;
|
|
17
|
+
}
|
|
18
|
+
const isVersion = input.length === 1 && ['--version', '-V'].includes(input[0]);
|
|
19
|
+
if (!isVersion && input[index] !== 'app-server') throw new CaeError('desktop_bridge_command_unsupported');
|
|
20
|
+
const args = isVersion ? input : codexArgs(config, 'chatgpt', input);
|
|
21
|
+
const env = { ...process.env }; delete env.CODEX_CLI_PATH; delete env.TYPESAFE_API_KEY; delete env.CAE_LOCAL_TOKEN;
|
|
22
|
+
if (!isVersion) {
|
|
23
|
+
await verifyDesktopProvider(binary, args, config);
|
|
24
|
+
const health = await fetch(`http://127.0.0.1:${config.port}/health`, { redirect: 'error',
|
|
25
|
+
signal: AbortSignal.timeout(3000), headers: { 'x-cae-token': readLocalToken(config.tokenFile) } });
|
|
26
|
+
const state = health.ok ? await health.json() : null;
|
|
27
|
+
if (!state?.ok || !state.auditHealthy || state.model !== config.model) throw new CaeError('proxy_health_mismatch');
|
|
28
|
+
await desktopControl(configPath, 'bridge-ready');
|
|
29
|
+
env.CAE_LOCAL_TOKEN = readLocalToken(config.tokenFile);
|
|
30
|
+
}
|
|
31
|
+
const child = spawn(binary, args, { env, stdio: 'inherit' });
|
|
32
|
+
let timer;
|
|
33
|
+
const stop = () => { child.kill('SIGTERM'); timer ??= setTimeout(() => child.kill('SIGKILL'), 1000); timer.unref(); };
|
|
34
|
+
process.once('SIGTERM', stop); process.once('SIGINT', stop);
|
|
35
|
+
child.once('error', () => { console.error('CAE: codex_not_available'); process.exitCode = 1; });
|
|
36
|
+
child.once('exit', code => { clearTimeout(timer); process.off('SIGTERM', stop); process.off('SIGINT', stop); process.exitCode = code ?? 1; });
|
|
37
|
+
}
|
|
38
|
+
main().catch(error => {
|
|
39
|
+
console.error(`CAE: ${error instanceof CaeError ? error.code : 'desktop_bridge_failed'}`);
|
|
40
|
+
process.exitCode = 1;
|
|
41
|
+
});
|
package/bin/cae.mjs
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from 'node:util';
|
|
3
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { resolve } from 'node:path';
|
|
5
|
+
import { randomBytes } from 'node:crypto';
|
|
6
|
+
import { spawn } from 'node:child_process';
|
|
7
|
+
import { defaultConfig, loadConfig, readLocalToken } from '../src/config.mjs';
|
|
8
|
+
import { CaeError } from '../src/util.mjs';
|
|
9
|
+
import { BaselineJudge, TypeSafeJudge } from '../src/judge.mjs';
|
|
10
|
+
import { Audit, report } from '../src/audit.mjs';
|
|
11
|
+
import { startProxy } from '../src/proxy.mjs';
|
|
12
|
+
import { doctor, probeModels, codexArgs } from '../src/codex.mjs';
|
|
13
|
+
import { VERSION } from '../src/version.mjs';
|
|
14
|
+
|
|
15
|
+
const HELP = `Codex Adaptive Effort ${VERSION} (Node >=22.16; no dependencies)
|
|
16
|
+
|
|
17
|
+
cae --version / -V Print installed package version
|
|
18
|
+
cae doctor [--codex PATH] No credentials or network read by CAE
|
|
19
|
+
cae probe [--codex PATH] Native initialize + model/list only
|
|
20
|
+
cae init --model ID --auth chatgpt|api --capabilities FILE [--baseline EFFORT]
|
|
21
|
+
cae init --model ID --auth chatgpt|api --efforts low,medium,high --baseline high
|
|
22
|
+
cae serve --enable-upstream [--enable-jev] Start local proxy (foreground)
|
|
23
|
+
cae status Authenticated local state
|
|
24
|
+
cae control off|shadow|auto Change next unsent request policy
|
|
25
|
+
cae lock high / cae unlock Explicit instance-wide lock
|
|
26
|
+
cae codex --auth chatgpt|api -- [ARGS] One-off launch, no config.toml writes
|
|
27
|
+
cae launch-args --auth chatgpt|api Print non-secret argv for inspection
|
|
28
|
+
cae desktop start --auth chatgpt --enable-upstream [--model ID] [--enable-jev [--allow-jev-auto]]
|
|
29
|
+
cae desktop status / desktop stop Isolated macOS desktop instance
|
|
30
|
+
cae report Observed usage, not savings claims
|
|
31
|
+
|
|
32
|
+
Shared: --config .cae/config.json; init: --dir .cae
|
|
33
|
+
serve Jev requires config judge.kind=typesafe, TYPESAFE_API_KEY and --enable-jev.
|
|
34
|
+
Desktop --enable-jev is process-only, shadow/off only, at most 8 evaluations.
|
|
35
|
+
Add --allow-jev-auto to permit control auto; startup still requires shadow/off.
|
|
36
|
+
Desktop --jev-timeout-ms 1500|2000 overrides only this process's Jev timeout.
|
|
37
|
+
An external upstream requires --enable-upstream and normal Codex auth.
|
|
38
|
+
Default is SHADOW with a baseline-only evaluator, not a complexity classifier.
|
|
39
|
+
`;
|
|
40
|
+
function print(value) { console.log(typeof value === 'string' ? value : JSON.stringify(value, null, 2)); }
|
|
41
|
+
async function localCall(c, path, body) {
|
|
42
|
+
const response = await fetch(`http://127.0.0.1:${c.port}${path}`, {
|
|
43
|
+
method: body ? 'POST' : 'GET', redirect: 'error', signal: AbortSignal.timeout(3000),
|
|
44
|
+
headers: { 'x-cae-token': readLocalToken(c.tokenFile), 'content-type': 'application/json' },
|
|
45
|
+
...(body ? { body: JSON.stringify(body) } : {}),
|
|
46
|
+
});
|
|
47
|
+
if (!response.ok) throw new CaeError(`local_http_${response.status}`);
|
|
48
|
+
return response.json();
|
|
49
|
+
}
|
|
50
|
+
async function main() {
|
|
51
|
+
const input = process.argv.slice(2), dash = input.indexOf('--');
|
|
52
|
+
const passthrough = dash < 0 ? [] : input.slice(dash + 1);
|
|
53
|
+
const { values: v, positionals: p } = parseArgs({ args: dash < 0 ? input : input.slice(0, dash),
|
|
54
|
+
allowPositionals: true, strict: true, options: {
|
|
55
|
+
help: { type: 'boolean', short: 'h' }, version: { type: 'boolean', short: 'V' }, config: { type: 'string', default: '.cae/config.json' },
|
|
56
|
+
dir: { type: 'string', default: '.cae' }, model: { type: 'string' }, efforts: { type: 'string' },
|
|
57
|
+
baseline: { type: 'string' }, auth: { type: 'string' }, capabilities: { type: 'string' },
|
|
58
|
+
codex: { type: 'string', default: 'codex' }, 'enable-upstream': { type: 'boolean' }, 'enable-jev': { type: 'boolean' },
|
|
59
|
+
app: { type: 'string' },
|
|
60
|
+
'allow-jev-auto': { type: 'boolean' },
|
|
61
|
+
'jev-timeout-ms': { type: 'string' },
|
|
62
|
+
} });
|
|
63
|
+
const command = p[0];
|
|
64
|
+
if (v.version) { print(VERSION); return; }
|
|
65
|
+
if (!command || v.help) { print(HELP); return; }
|
|
66
|
+
if (v['allow-jev-auto'] && (command !== 'desktop' || p[1] !== 'start')) throw new CaeError('desktop_auto_start_only');
|
|
67
|
+
if (v['jev-timeout-ms'] !== undefined && (command !== 'desktop' || p[1] !== 'start')) throw new CaeError('desktop_timeout_start_only');
|
|
68
|
+
if (v['jev-timeout-ms'] !== undefined && !['1500', '2000'].includes(v['jev-timeout-ms'])) throw new CaeError('desktop_invalid_jev_timeout');
|
|
69
|
+
if (command === 'desktop') {
|
|
70
|
+
if (p.length !== 2 || passthrough.length) throw new CaeError('desktop_invalid_arguments');
|
|
71
|
+
if (input.some(x => x === '--codex' || x.startsWith('--codex='))) throw new CaeError('desktop_uses_verified_bundled_cli');
|
|
72
|
+
const { startDesktop, desktopControl } = await import('../src/desktop.mjs');
|
|
73
|
+
const explicitConfig = input.some(x => x === '--config' || x.startsWith('--config='));
|
|
74
|
+
const configPath = explicitConfig ? v.config : '.cae/desktop/config.json';
|
|
75
|
+
if (p[1] === 'start') {
|
|
76
|
+
const desktop = await startDesktop({ configPath, model: v.model, baseline: v.baseline, auth: v.auth,
|
|
77
|
+
enableUpstream: v['enable-upstream'], enableJev: v['enable-jev'], allowJevAuto: v['allow-jev-auto'],
|
|
78
|
+
jevTimeoutMs: v['jev-timeout-ms'] === undefined ? undefined : Number(v['jev-timeout-ms']),
|
|
79
|
+
appPath: v.app, onState: print });
|
|
80
|
+
print(await desktop.done); return;
|
|
81
|
+
}
|
|
82
|
+
if (!['status', 'stop'].includes(p[1])) throw new CaeError('desktop_unknown_action');
|
|
83
|
+
print(await desktopControl(configPath, p[1], { timeoutMs: p[1] === 'stop' ? 15000 : 5000 })); return;
|
|
84
|
+
}
|
|
85
|
+
if (command === 'doctor') { print(doctor(v.codex)); return; }
|
|
86
|
+
if (command === 'probe') { print(await probeModels(v.codex)); return; }
|
|
87
|
+
if (command === 'init') {
|
|
88
|
+
if (!v.model || !['api', 'chatgpt'].includes(v.auth)) throw new CaeError('init_requires_model_and_auth');
|
|
89
|
+
let efforts = v.efforts?.split(','), baseline = v.baseline, capabilitySource;
|
|
90
|
+
if (v.capabilities) {
|
|
91
|
+
const data = JSON.parse(readFileSync(v.capabilities, 'utf8'));
|
|
92
|
+
const entry = data.models?.find(m => m.model === v.model);
|
|
93
|
+
if (!entry) throw new CaeError('model_missing_from_capabilities');
|
|
94
|
+
efforts = entry.supportedEfforts; baseline ??= entry.baseline;
|
|
95
|
+
capabilitySource = `${data.source ?? 'provided capture'} at ${data.observedAt ?? 'unknown time'}; refresh after client upgrades`;
|
|
96
|
+
}
|
|
97
|
+
if (!efforts || !baseline) throw new CaeError('init_requires_capabilities_or_efforts_and_baseline');
|
|
98
|
+
const config = defaultConfig(v.model, efforts, baseline); config.upstream.kind = v.auth;
|
|
99
|
+
if (capabilitySource) config.capabilitySource = capabilitySource;
|
|
100
|
+
const dir = resolve(v.dir);
|
|
101
|
+
mkdirSync(dir, { mode: 0o700 }); // EEXIST intentionally refuses to overwrite.
|
|
102
|
+
writeFileSync(resolve(dir, 'local.key'), randomBytes(32).toString('hex') + '\n', { mode: 0o600, flag: 'wx' });
|
|
103
|
+
writeFileSync(resolve(dir, 'config.json'), JSON.stringify(config, null, 2) + '\n', { mode: 0o600, flag: 'wx' });
|
|
104
|
+
print('Created isolated CAE configuration. No Codex configuration or login files were touched.'); return;
|
|
105
|
+
}
|
|
106
|
+
const c = loadConfig(v.config);
|
|
107
|
+
if (command === 'serve') {
|
|
108
|
+
let judge;
|
|
109
|
+
if (c.judge.kind === 'typesafe') {
|
|
110
|
+
if (!v['enable-jev']) throw new CaeError('jev_external_processing_not_enabled');
|
|
111
|
+
judge = new TypeSafeJudge({ apiKey: process.env.TYPESAFE_API_KEY, model: c.judge.model });
|
|
112
|
+
} else judge = new BaselineJudge();
|
|
113
|
+
const audit = new Audit(c.logFile);
|
|
114
|
+
let proxy;
|
|
115
|
+
try { proxy = await startProxy(c, { token: readLocalToken(c.tokenFile), judge,
|
|
116
|
+
emit: record => audit.emit(record), auditHealthy: () => !audit.failed, allowUpstream: v['enable-upstream'] === true }); }
|
|
117
|
+
catch (e) { audit.close(); throw e; }
|
|
118
|
+
print({ listening: `127.0.0.1:${proxy.port}`, mode: c.mode, judge: c.judge.kind,
|
|
119
|
+
upstream: c.upstream.kind, credentialsLogged: false, note: 'Foreground service. Stop and relaunch normal Codex to bypass it.' });
|
|
120
|
+
let stopping = false;
|
|
121
|
+
const stop = async () => { if (stopping) return; stopping = true; await proxy.close(); audit.close(); };
|
|
122
|
+
process.once('SIGINT', stop); process.once('SIGTERM', stop); return;
|
|
123
|
+
}
|
|
124
|
+
if (command === 'status') { print(await localCall(c, '/health')); return; }
|
|
125
|
+
if (command === 'control') { print(await localCall(c, '/control', { mode: p[1] })); return; }
|
|
126
|
+
if (command === 'lock') { print(await localCall(c, '/control', { lockedEffort: p[1] })); return; }
|
|
127
|
+
if (command === 'unlock') { print(await localCall(c, '/control', { lockedEffort: null })); return; }
|
|
128
|
+
if (command === 'report') {
|
|
129
|
+
let text; try { text = readFileSync(c.logFile, 'utf8'); } catch { throw new CaeError('cannot_read_log'); }
|
|
130
|
+
const records = []; let malformedLines = 0;
|
|
131
|
+
for (const line of text.split('\n').filter(Boolean)) { try { records.push(JSON.parse(line)); } catch { ++malformedLines; } }
|
|
132
|
+
print({ ...report(records), malformedLines }); return;
|
|
133
|
+
}
|
|
134
|
+
if (['codex', 'launch-args'].includes(command)) {
|
|
135
|
+
const args = codexArgs(c, v.auth, passthrough);
|
|
136
|
+
if (command === 'launch-args') { print({ command: v.codex, args, requiredEnvironmentNames: ['CAE_LOCAL_TOKEN', ...(v.auth === 'api' ? ['OPENAI_API_KEY'] : [])] }); return; }
|
|
137
|
+
const health = await localCall(c, '/health');
|
|
138
|
+
if (!health.ok || health.model !== c.model) throw new CaeError('proxy_health_mismatch');
|
|
139
|
+
if (v.auth === 'api' && !process.env.OPENAI_API_KEY) throw new CaeError('missing_openai_api_key');
|
|
140
|
+
const env = { ...process.env, CAE_LOCAL_TOKEN: readLocalToken(c.tokenFile) };
|
|
141
|
+
delete env.TYPESAFE_API_KEY;
|
|
142
|
+
const child = spawn(v.codex, args, { env, stdio: 'inherit', shell: false });
|
|
143
|
+
child.once('error', () => { console.error('CAE: codex_not_available'); process.exitCode = 1; });
|
|
144
|
+
child.once('exit', code => { process.exitCode = code ?? 1; }); return;
|
|
145
|
+
}
|
|
146
|
+
throw new CaeError('unknown_command');
|
|
147
|
+
}
|
|
148
|
+
main().catch(error => {
|
|
149
|
+
// Do not echo upstream bodies, environment, argument values or native stderr.
|
|
150
|
+
console.error(`CAE: ${error instanceof CaeError ? error.code : 'command_failed_check_arguments_and_local_paths'}`);
|
|
151
|
+
process.exitCode = 1;
|
|
152
|
+
});
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Experimental desktop launcher
|
|
2
|
+
|
|
3
|
+
The launcher starts an independent instance of the installed Codex desktop application. It is not a packaged plugin, does not control ordinary ChatGPT conversations and does not migrate existing chats.
|
|
4
|
+
|
|
5
|
+
## Requirements and scope
|
|
6
|
+
|
|
7
|
+
The current allowlist is **macOS arm64**, **ChatGPT/Codex desktop 26.924.22138 / build 11645**, and its bundled **codex-cli 0.158.0-alpha.2.1**. Local acceptance used macOS 27.0 and Node v24.16.0. The launcher verifies the official application signature and exact version, queries native capabilities, and checks the effective provider with `initialize` + `config/read`. An application update requires revalidation; CAE does not upgrade, downgrade or replace native binaries.
|
|
8
|
+
|
|
9
|
+
The experimental instance uses its own Electron data directory but shares native Codex home and login. It may show existing projects and chats. **Create a new local Codex chat** in a directory containing only non-sensitive test material. Old chats retain their previous providers; cloud tasks and ordinary ChatGPT chats are not covered.
|
|
10
|
+
|
|
11
|
+
## Start with baseline shadow
|
|
12
|
+
|
|
13
|
+
After [npm installation](NPM.md), replace `node bin/cae.mjs` in this guide with `cae` and use your chosen working directory in every terminal. When running from source, use the repository root. Select a model ID returned by the [native probe](LOCAL_VALIDATION.md):
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
node bin/cae.mjs desktop start --model "$MODEL_ID" --auth chatgpt --enable-upstream
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Keep this terminal running. First launch creates `.cae/desktop/config.json`; later launches reuse it and reject an unexpected model/baseline change. The default is shadow + baseline-only, which does not classify task complexity or call Jev. Starting does not submit a task; sending a task consumes the normal model allowance.
|
|
20
|
+
|
|
21
|
+
In another terminal:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
node bin/cae.mjs desktop status
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Wait for `phase=running`, `effectiveProvider=cae`, `connected=true` and at least one successful bridge check. The output includes the experimental desktop PID and configuration path. The provider display name is `CAE experimental local effort controller`; CAE does not patch the native window title. Automated visual identification was not accepted independently.
|
|
28
|
+
|
|
29
|
+
Custom locations are supported with `--config PATH` and `--app PATH`. Use the same `--config` for start/status/stop. The configuration directory must be private. The default proxy port is 4319; a conflict fails startup without killing another process. Arbitrary CLI replacement via `--codex` is rejected for desktop startup.
|
|
30
|
+
|
|
31
|
+
## Manual controls without Jev
|
|
32
|
+
|
|
33
|
+
For a baseline instance, select only efforts from the actual capability set:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
node bin/cae.mjs control off --config .cae/desktop/config.json
|
|
37
|
+
node bin/cae.mjs lock low --config .cae/desktop/config.json
|
|
38
|
+
node bin/cae.mjs control auto --config .cae/desktop/config.json
|
|
39
|
+
# Send an eligible synthetic text task in the experimental window.
|
|
40
|
+
node bin/cae.mjs control off --config .cae/desktop/config.json
|
|
41
|
+
node bin/cae.mjs unlock --config .cae/desktop/config.json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Controls apply to this CAE instance, not a single chat. Locks affect only eligible auto requests; unsupported history still bypasses adaptation. Controls affect the next unsent request, not a response already being generated.
|
|
45
|
+
|
|
46
|
+
## Enable Jev shadow
|
|
47
|
+
|
|
48
|
+
Stop the old experimental instance first. Supply `TYPESAFE_API_KEY` through your normal environment setup, without putting its value in command arguments or public logs:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
node bin/cae.mjs desktop start --model "$MODEL_ID" --auth chatgpt \
|
|
52
|
+
--enable-upstream --enable-jev
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
This changes the evaluator to TypeSafe only for the current process. It does not persist the evaluator or key. Startup still requires a shadow/off configuration. With this flag alone, `shadowOnly=true`: auto and non-null manual locks are rejected with `shadow_only_control`. Off/shadow switching does not renew the budget.
|
|
56
|
+
|
|
57
|
+
The native CLI, probe and desktop child processes do not inherit the Jev key. Jev receives a bounded text projection; redaction is not a guarantee that business secrets are removed. Use only tasks approved for external processing.
|
|
58
|
+
|
|
59
|
+
Every desktop Jev process permits at most eight evaluations, or a smaller configured call limit. By default, the timeout is the smaller of the configured timeout and 1500 ms. A timeout or cancellation may still incur provider usage. Exhausting the limit records `judge_call_budget` and falls back without retrying or switching providers. Restarting begins a new budget; this is not a spending guarantee.
|
|
60
|
+
|
|
61
|
+
<a id="jev-auto受控实验"></a>
|
|
62
|
+
## Enable a controlled auto trial
|
|
63
|
+
|
|
64
|
+
With explicit authorization to change real request effort, add the separate auto permission:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
node bin/cae.mjs desktop start --model "$MODEL_ID" --auth chatgpt \
|
|
68
|
+
--enable-upstream --enable-jev --allow-jev-auto
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Startup still uses shadow/off. Once running, check `judgeKind=typesafe`, `shadowOnly=false`, `lockedEffort=null`, `judgeCalls=0` and `activeRequests=0`, then switch:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
node bin/cae.mjs control auto --config .cae/desktop/config.json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Invalid decisions, timeouts and exhausted budgets retain the incoming effort; when effort is absent, the configured baseline is used. Other models and unsupported shapes bypass adaptation. The desktop effort selector may continue showing the user's chosen baseline: CAE modifies the outbound request, not that selector.
|
|
78
|
+
|
|
79
|
+
For the recorded installation, `gpt-6-astra` supports medium, low and high. In a new local chat, keep the desktop selection at medium and submit these non-sensitive fixtures one at a time, waiting for completion:
|
|
80
|
+
|
|
81
|
+
1. `Do not use tools. Correct Helo to Hello. Reply only with the corrected string.`
|
|
82
|
+
2. `Do not use tools. Analyze a fictional scheduler: A is cancelled, B starts, and a late callback from A overwrites B's state. Describe the faulty sequence, ownership invariant, and smallest fix.`
|
|
83
|
+
|
|
84
|
+
These English examples are reproduction instructions, not a claim that the original Chinese fixtures were rerun in English. Jev need not recommend low/high. A timeout or unchanged recommendation must be recorded honestly, without automatic retries to obtain a preferred outcome.
|
|
85
|
+
|
|
86
|
+
<a id="可选-2000-ms-实验"></a>
|
|
87
|
+
## Optional 2000 ms timeout experiment
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
node bin/cae.mjs desktop start --model "$MODEL_ID" --auth chatgpt \
|
|
91
|
+
--enable-upstream --enable-jev --allow-jev-auto --jev-timeout-ms 2000
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`--jev-timeout-ms` accepts only 1500 or 2000 and requires `desktop start --enable-jev`. It explicitly replaces the disk timeout for this process, including a smaller disk value. It never writes the configuration. Check `judgeTimeoutMs` in status before switching to auto.
|
|
95
|
+
|
|
96
|
+
The default remains 1500 ms. Restart without the parameter to restore the original disk value subject to that ceiling. The successful real downshift took 665 ms, below either deadline; it does not establish a benefit from increasing the limit. The worst-case timeout wait increases by roughly 500 ms.
|
|
97
|
+
|
|
98
|
+
## Inspect results
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
node bin/cae.mjs desktop status
|
|
102
|
+
node bin/cae.mjs report --config .cae/desktop/config.json
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Reports aggregate an append-only event file and can include earlier instances. For a trial, filter by its time window and correlate local request IDs across `decision`, `request_prepared`, `request_sent` and `upstream_outcome`. A recommendation alone is not an applied change. An applied request setting plus completion is not proof of actual model reasoning allocation or task quality.
|
|
106
|
+
|
|
107
|
+
Jev timings separate observed request creation, send start, body sent, response headers, body completion and validation. They do not independently resolve DNS/TCP/TLS or pure server inference time. Missing fields remain unknown. Do not upload raw event files; publish only reviewed, sanitized summaries.
|
|
108
|
+
|
|
109
|
+
## Stop and recover
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
node bin/cae.mjs control off --config .cae/desktop/config.json
|
|
113
|
+
node bin/cae.mjs desktop stop
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The stop command closes this instance, its tracked children and proxy; success returns `stopped`. Ctrl+C in the startup terminal uses the same cleanup path. Stop interrupts active experimental tasks, so wait for completion when possible. Ordinary desktop instances are not cleanup targets.
|
|
117
|
+
|
|
118
|
+
`off` still uses the proxy. After stop, use the normal official application; no global configuration or login restoration is needed. Forced supervisor death (for example SIGKILL) can leave stale resources and requires manual inspection. CAE does not guess ownership from an old PID, run `killall` or promise automatic direct-routing failover.
|
|
119
|
+
|
|
120
|
+
## Evidence
|
|
121
|
+
|
|
122
|
+
[Current local acceptance](LOCAL_ACCEPTANCE.md) covers the real auto upshift/downshift and fallback. [Initial desktop acceptance](DESKTOP_ACCEPTANCE.md) covers manual controls and cancellation. The [original Chinese launcher record](DESKTOP_LAUNCHER.zh-CN.md) preserves dated startup tests and source hashes; its intermediate pending steps are historical.
|