@minniexcode/codex-switch 0.0.8 → 0.0.10
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/README.AI.md +5 -3
- package/README.CN.md +25 -3
- package/README.md +3 -2
- package/dist/app/add-provider.js +1 -12
- package/dist/app/bridge.js +295 -0
- package/dist/app/edit-provider.js +1 -17
- package/dist/app/get-status.js +32 -2
- package/dist/app/list-providers.js +0 -1
- package/dist/app/run-doctor.js +45 -38
- package/dist/app/setup-codex.js +27 -17
- package/dist/app/show-config.js +1 -5
- package/dist/app/switch-provider.js +33 -20
- package/dist/cli/output.js +4 -6
- package/dist/cli.js +1 -1
- package/dist/commands/handlers.js +223 -39
- package/dist/commands/help.js +1 -0
- package/dist/commands/registry.js +48 -4
- package/dist/domain/config.js +4 -68
- package/dist/domain/providers.js +0 -5
- package/dist/domain/runtime-state.js +2 -1
- package/dist/domain/setup.js +58 -3
- package/dist/interaction/add-interactive.js +55 -1
- package/dist/interaction/interactive.js +1 -5
- package/dist/runtime/copilot-adapter.js +44 -1
- package/dist/runtime/copilot-bridge-worker.js +1 -1
- package/dist/runtime/copilot-bridge.js +60 -19
- package/dist/runtime/copilot-cli.js +70 -0
- package/dist/runtime/copilot-installer.js +49 -2
- package/dist/storage/auth-repo.js +28 -77
- package/dist/storage/config-repo.js +1 -36
- package/dist/storage/runtime-state-repo.js +32 -0
- package/docs/Design/codex-switch-copilot-integration-design.md +517 -0
- package/docs/Design/codex-switch-v0.0.10-design.md +669 -0
- package/docs/Design/codex-switch-v0.0.9-design.md +182 -0
- package/docs/PRD/codex-switch-prd-v0.0.10.md +406 -0
- package/docs/PRD/codex-switch-prd-v0.0.9.md +166 -0
- package/docs/Tests/testing-bridge-v0.0.9.md +367 -0
- package/docs/cli-usage.md +38 -14
- package/docs/codex-switch-product-overview.md +2 -2
- package/docs/codex-switch-technical-architecture.md +6 -5
- package/package.json +1 -1
- /package/docs/{test-report-0.0.5.md → Tests/test-report-0.0.5.md} +0 -0
- /package/docs/{test-report-0.0.7.md → Tests/test-report-0.0.7.md} +0 -0
- /package/docs/{testing.md → Tests/testing.md} +0 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# codex-switch `0.0.9` PRD
|
|
2
|
+
|
|
3
|
+
## 文档信息
|
|
4
|
+
|
|
5
|
+
- 状态:Active PRD
|
|
6
|
+
- 产品名:`codex-switch`
|
|
7
|
+
- CLI 命令名:`codexs`
|
|
8
|
+
- 当前基线版本:`0.0.8`
|
|
9
|
+
- 目标版本:`0.0.9`
|
|
10
|
+
- 文档定位:定义 `0.0.8 -> 0.0.9` 的直接需求范围
|
|
11
|
+
- 关联设计文档:`../Design/codex-switch-v0.0.9-design.md`(待产出)
|
|
12
|
+
- 关联上一版设计:[`../Design/codex-switch-v0.0.8-design.md`](../Design/codex-switch-v0.0.8-design.md)
|
|
13
|
+
|
|
14
|
+
## 一句话定义
|
|
15
|
+
|
|
16
|
+
`0.0.9` 的目标,是把 GitHub Copilot 的本地 bridge 从“切换时临时可用”收敛成“可按需自动拉起、可手动管理、可诊断恢复”的稳定运行态能力。
|
|
17
|
+
|
|
18
|
+
## In Scope
|
|
19
|
+
|
|
20
|
+
- 官方 `@github/copilot-sdk`
|
|
21
|
+
- 本地 Node/TypeScript bridge
|
|
22
|
+
- detached 用户态 bridge 守护进程
|
|
23
|
+
- `switch` 的 bridge 自动启动 / 复用
|
|
24
|
+
- `bridge start`
|
|
25
|
+
- `bridge stop`
|
|
26
|
+
- `bridge status`
|
|
27
|
+
- 单实例 bridge 生命周期管理
|
|
28
|
+
- 5 位数 bridge 端口默认策略
|
|
29
|
+
- 端口冲突自动探测与自动换端口
|
|
30
|
+
- runtime state manifest 的持久化与诊断
|
|
31
|
+
- `status` / `doctor` 的 bridge 生命周期诊断
|
|
32
|
+
- direct provider 回归稳定性
|
|
33
|
+
|
|
34
|
+
## Out of Scope
|
|
35
|
+
|
|
36
|
+
- 开机自启动
|
|
37
|
+
- 登录自启动
|
|
38
|
+
- Windows Service / 系统服务注册
|
|
39
|
+
- 多实例 bridge 编排
|
|
40
|
+
- 非官方 SDK
|
|
41
|
+
- 独立 GUI / TUI
|
|
42
|
+
- Responses API、Embeddings、图像/音频接口
|
|
43
|
+
- 持久化 GitHub token 到 `providers.json` / `auth.json`
|
|
44
|
+
|
|
45
|
+
## 运行形态
|
|
46
|
+
|
|
47
|
+
- bridge 是由 `codex-switch` 启动和管理的本地后台进程
|
|
48
|
+
- bridge 不是系统服务,也不注册开机或登录自动启动项
|
|
49
|
+
- `switch` 到 Copilot provider 时,bridge 应自动启动或复用
|
|
50
|
+
- 用户也可以通过 `bridge` 命令族手动启动、停止和查看状态
|
|
51
|
+
- `0.0.9` 的“守护进程”语义仅指 detached 用户态后台进程,不等同于 OS service
|
|
52
|
+
|
|
53
|
+
## 命令面
|
|
54
|
+
|
|
55
|
+
新增命令:
|
|
56
|
+
|
|
57
|
+
- `codexs bridge start [provider]`
|
|
58
|
+
- `codexs bridge stop [provider]`
|
|
59
|
+
- `codexs bridge status [provider]`
|
|
60
|
+
|
|
61
|
+
命令规则:
|
|
62
|
+
|
|
63
|
+
- `bridge` 命令族只服务于 Copilot runtime-backed provider
|
|
64
|
+
- `provider` 可显式传入;未传入时优先使用当前 active provider
|
|
65
|
+
- 如果未传入且当前 active provider 不是 Copilot provider:
|
|
66
|
+
- TTY 下允许交互选择目标 Copilot provider
|
|
67
|
+
- 非交互或 `--json` 下必须明确失败
|
|
68
|
+
- `bridge start` 必须先完成:
|
|
69
|
+
- provider 解析
|
|
70
|
+
- runtime 配置校验
|
|
71
|
+
- SDK probe
|
|
72
|
+
- Copilot auth state 校验
|
|
73
|
+
- bridge 启动或复用
|
|
74
|
+
- healthcheck
|
|
75
|
+
- `bridge stop` 只停止当前受管 bridge 进程并清理 runtime state manifest,不修改 provider registry
|
|
76
|
+
- `bridge status` 返回 runtime state、provider 绑定关系、healthcheck 结果与异常原因
|
|
77
|
+
|
|
78
|
+
## 生命周期规则
|
|
79
|
+
|
|
80
|
+
- `add --copilot` 只负责创建 provider 和可选安装 SDK,不负责启动 bridge
|
|
81
|
+
- `switch <copilot-provider>` 仍然是最常见的自动启动入口
|
|
82
|
+
- `bridge start` 与 `switch` 共享同一套 bridge 启动与复用逻辑
|
|
83
|
+
- 同一时刻只允许一个 bridge 实例处于受管运行状态
|
|
84
|
+
- 如果 bridge 已为同一 provider 运行且健康,则 `bridge start` 和 `switch` 都直接复用
|
|
85
|
+
- 如果已有 bridge 为另一 Copilot provider 运行:
|
|
86
|
+
- `bridge start <new-provider>` 先停止旧实例,再启动新实例
|
|
87
|
+
- `switch <new-provider>` 也遵守同样的单实例替换规则
|
|
88
|
+
- `bridge stop` 应该是幂等的:bridge 已停止时不报致命错误
|
|
89
|
+
|
|
90
|
+
## 端口策略
|
|
91
|
+
|
|
92
|
+
- `--bridge-host` 默认 `127.0.0.1`
|
|
93
|
+
- `--bridge-port` 默认值必须是 5 位数端口
|
|
94
|
+
- Copilot provider 的默认端口不再使用 `4141`
|
|
95
|
+
- 如果 provider 指定端口已被占用:
|
|
96
|
+
- bridge 启动阶段必须自动检测冲突
|
|
97
|
+
- 自动选择新的可用 5 位数端口
|
|
98
|
+
- 自动更新 provider 的 runtime 配置和对应 `baseUrl`
|
|
99
|
+
- 自动保持 `config.toml` runtime projection 与 provider 配置一致
|
|
100
|
+
- 自动换端口后的新端口必须持久化,避免下一次启动再次撞到旧端口
|
|
101
|
+
- 端口自动切换只允许在 Copilot bridge provider 路径发生,不能影响 direct provider
|
|
102
|
+
|
|
103
|
+
## 依赖策略
|
|
104
|
+
|
|
105
|
+
- `@github/copilot-sdk` 继续不进入 core CLI 默认依赖
|
|
106
|
+
- 命中 Copilot 路径时才 probe SDK
|
|
107
|
+
- SDK 自动安装仍然只允许发生在 `add --copilot`
|
|
108
|
+
- `bridge start`、`switch`、`status`、`doctor` 都不能隐式安装 SDK
|
|
109
|
+
- `bridge start` 在 SDK 缺失时必须明确失败,并提示回到 `add --copilot --install-copilot-sdk`
|
|
110
|
+
- SDK 运行前提仍然是用户本机已具备可用的 GitHub Copilot CLI / login 状态,`codex-switch` 不托管这部分登录数据
|
|
111
|
+
|
|
112
|
+
## 数据边界
|
|
113
|
+
|
|
114
|
+
- `providers.json` 保存 Copilot provider、bridge host/port、`baseUrl` 与 shared secret
|
|
115
|
+
- `config.toml` 保存 Copilot provider 对应的 runtime `base_url` 与 `env_key`
|
|
116
|
+
- `auth.json` 只保存 Codex 到本地 bridge 的 shared secret
|
|
117
|
+
- runtime state manifest 保存当前 bridge 进程状态、provider 绑定、最后健康检查时间
|
|
118
|
+
- runtime state manifest 不进入 managed backup 事务
|
|
119
|
+
- GitHub/Copilot 上游认证状态仍然只由官方 SDK 管理,不进入受管 registry
|
|
120
|
+
|
|
121
|
+
## 错误语义
|
|
122
|
+
|
|
123
|
+
`0.0.9` 继续稳定并收敛以下错误码:
|
|
124
|
+
|
|
125
|
+
- `COPILOT_SDK_MISSING`
|
|
126
|
+
- `COPILOT_SDK_INSTALL_FAILED`
|
|
127
|
+
- `COPILOT_SDK_INSTALL_REQUIRES_TTY`
|
|
128
|
+
- `COPILOT_SDK_UNSUPPORTED`
|
|
129
|
+
- `COPILOT_AUTH_REQUIRED`
|
|
130
|
+
- `COPILOT_PREMIUM_UNAVAILABLE`
|
|
131
|
+
- `BRIDGE_PORT_CONFLICT`
|
|
132
|
+
- `BRIDGE_START_FAILED`
|
|
133
|
+
- `BRIDGE_HEALTHCHECK_FAILED`
|
|
134
|
+
- `RUNTIME_PROVIDER_INVALID`
|
|
135
|
+
- `PROVIDER_BASE_URL_MISMATCH`
|
|
136
|
+
|
|
137
|
+
新增要求:
|
|
138
|
+
|
|
139
|
+
- `bridge start`、`switch`、`bridge status` 对同一类 bridge 失败应尽量映射到同一类错误码
|
|
140
|
+
- 端口冲突在自动恢复成功时不应向上冒泡为致命失败
|
|
141
|
+
- 只有在无法找到可用端口或无法持久化新端口时,才允许保留 `BRIDGE_PORT_CONFLICT` 失败
|
|
142
|
+
|
|
143
|
+
## 验收标准
|
|
144
|
+
|
|
145
|
+
- `add --copilot` 可以创建 Copilot provider,并写入 5 位数默认端口
|
|
146
|
+
- `switch` 到 Copilot provider 时完成 `probe -> auth check -> start or reuse bridge -> healthcheck -> config/auth write`
|
|
147
|
+
- `codexs bridge start [provider]` 可以手动启动或复用 bridge
|
|
148
|
+
- `codexs bridge stop [provider]` 可以手动停止当前 bridge,并清理 runtime state
|
|
149
|
+
- `codexs bridge status [provider]` 可以给出 bridge 是否运行、绑定哪个 provider、端口是多少、是否健康
|
|
150
|
+
- 当 bridge 目标端口被占用时,系统会自动切换到新的可用 5 位数端口,并持久化该变更
|
|
151
|
+
- direct provider 不经过 Copilot 特有的 runtime gate
|
|
152
|
+
- `status` / `doctor` 能诊断 SDK 缺失、认证缺失、bridge 不健康、stale runtime state、runtime base_url 漂移
|
|
153
|
+
|
|
154
|
+
## 测试重点
|
|
155
|
+
|
|
156
|
+
- `bridge start/stop/status` 参数解析与帮助文案
|
|
157
|
+
- 省略 provider 时的 active provider 解析路径
|
|
158
|
+
- TTY 下的 Copilot provider 交互选择路径
|
|
159
|
+
- 非交互下目标 provider 不明确时的失败路径
|
|
160
|
+
- 单实例 bridge 的复用路径
|
|
161
|
+
- 单实例 bridge 的替换路径
|
|
162
|
+
- `switch` 与 `bridge start` 共享生命周期逻辑的回归
|
|
163
|
+
- 端口占用时的自动换端口与持久化
|
|
164
|
+
- stale runtime state 的诊断与清理
|
|
165
|
+
- `bridge stop` 幂等性
|
|
166
|
+
- direct provider 回归
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
# `0.0.9` Bridge Automated Testing Guide
|
|
2
|
+
|
|
3
|
+
This document defines the automated test strategy for the `0.0.9` Copilot bridge release.
|
|
4
|
+
|
|
5
|
+
## Goal
|
|
6
|
+
|
|
7
|
+
The release must prove that the managed Copilot bridge can:
|
|
8
|
+
|
|
9
|
+
- resolve the correct provider target
|
|
10
|
+
- start, stop, and report status through the public CLI surface
|
|
11
|
+
- reuse one healthy instance for the same provider
|
|
12
|
+
- replace an existing managed instance for a different provider
|
|
13
|
+
- recover from preferred-port conflicts using another 5-digit port
|
|
14
|
+
- persist recovered ports into `providers.json` and `config.toml`
|
|
15
|
+
- clean up newly started workers when persistence fails
|
|
16
|
+
- surface stale runtime-state diagnostics through `status` and `doctor`
|
|
17
|
+
|
|
18
|
+
## Test Layers
|
|
19
|
+
|
|
20
|
+
Bridge coverage is intentionally split across four layers.
|
|
21
|
+
|
|
22
|
+
### 1. Runtime Layer
|
|
23
|
+
|
|
24
|
+
File: `tests/runtime.spec.js`
|
|
25
|
+
|
|
26
|
+
Use this layer for low-level worker/runtime behaviors:
|
|
27
|
+
|
|
28
|
+
- bridge HTTP health endpoint behavior
|
|
29
|
+
- worker fallback defaults
|
|
30
|
+
- port conflict recovery
|
|
31
|
+
- single-instance replacement at the runtime-state layer
|
|
32
|
+
- direct `probeCopilotBridgeRuntime()` status behavior
|
|
33
|
+
|
|
34
|
+
### 2. Workflow Layer
|
|
35
|
+
|
|
36
|
+
File: `tests/workflows.spec.js`
|
|
37
|
+
|
|
38
|
+
Use this layer for app use cases and filesystem side effects:
|
|
39
|
+
|
|
40
|
+
- `startBridge`
|
|
41
|
+
- `stopBridge`
|
|
42
|
+
- `statusBridge`
|
|
43
|
+
- `switchProvider`
|
|
44
|
+
- `runDoctor`
|
|
45
|
+
- persistence and rollback behavior
|
|
46
|
+
|
|
47
|
+
### 3. Command Layer
|
|
48
|
+
|
|
49
|
+
File: `tests/commands.spec.js`
|
|
50
|
+
|
|
51
|
+
Use this layer for registry, argument parsing, and dispatch wiring:
|
|
52
|
+
|
|
53
|
+
- nested command parsing
|
|
54
|
+
- help text
|
|
55
|
+
- `executeCommand()` dispatch for `bridge start|stop|status`
|
|
56
|
+
- mismatch-guard and unresolved-target error contracts
|
|
57
|
+
|
|
58
|
+
### 4. Built CLI Layer
|
|
59
|
+
|
|
60
|
+
File: `tests/cli-e2e.spec.js`
|
|
61
|
+
|
|
62
|
+
Use this layer only for a small number of user-visible end-to-end checks:
|
|
63
|
+
|
|
64
|
+
- `bridge start --json`
|
|
65
|
+
- `bridge status --json`
|
|
66
|
+
- `bridge stop --json`
|
|
67
|
+
- stable JSON error envelopes for bridge failures
|
|
68
|
+
|
|
69
|
+
## Shared Fixtures And Helpers
|
|
70
|
+
|
|
71
|
+
### Existing helpers
|
|
72
|
+
|
|
73
|
+
- `tests/helpers.js`
|
|
74
|
+
- `makeSandboxCopy()`
|
|
75
|
+
- `makeEmptyCodexDir()`
|
|
76
|
+
- `runBuiltCli()`
|
|
77
|
+
- `runJsonCli()`
|
|
78
|
+
- `tests/workflows.spec.js`
|
|
79
|
+
- `makeFixture()`
|
|
80
|
+
- `withCodexAvailable()`
|
|
81
|
+
- `withFakeCopilotSdk()`
|
|
82
|
+
- `getFreePort()`
|
|
83
|
+
- `requestJson()`
|
|
84
|
+
- `tests/commands.spec.js`
|
|
85
|
+
- `makeTempCodexDir()`
|
|
86
|
+
- `writeBridgeFixture()`
|
|
87
|
+
- `withFakeCopilotSdk()`
|
|
88
|
+
|
|
89
|
+
### Environment hooks
|
|
90
|
+
|
|
91
|
+
Mock bridge-oriented tests should continue to use:
|
|
92
|
+
|
|
93
|
+
- `CODEX_SWITCH_COPILOT_RUNTIME_DIR`
|
|
94
|
+
- `CODEX_SWITCH_RUNTIME_STATE_DIR`
|
|
95
|
+
|
|
96
|
+
These keep SDK loading and runtime-state persistence isolated inside temporary directories.
|
|
97
|
+
|
|
98
|
+
## Required Automated Coverage
|
|
99
|
+
|
|
100
|
+
### Runtime tests
|
|
101
|
+
|
|
102
|
+
Required scenarios:
|
|
103
|
+
|
|
104
|
+
- healthy in-process bridge serves `/healthz`
|
|
105
|
+
- worker fallback port remains `41415`
|
|
106
|
+
- `ensureCopilotBridge()` reuses a healthy worker for the same provider
|
|
107
|
+
- `ensureCopilotBridge()` replaces a different managed provider instance
|
|
108
|
+
- `ensureCopilotBridge()` recovers from preferred-port conflicts
|
|
109
|
+
- `ensureCopilotBridge()` reports startup failures with `BRIDGE_START_FAILED`
|
|
110
|
+
|
|
111
|
+
Recommended additions when extending runtime coverage:
|
|
112
|
+
|
|
113
|
+
- `probeCopilotBridgeRuntime()` with missing state
|
|
114
|
+
- `probeCopilotBridgeRuntime()` with stale state and no active Copilot provider
|
|
115
|
+
- `probeCopilotBridgeRuntime()` with base URL mismatch
|
|
116
|
+
- `probeCopilotBridgeRuntime()` with failed healthcheck
|
|
117
|
+
|
|
118
|
+
### Workflow tests
|
|
119
|
+
|
|
120
|
+
Required scenarios:
|
|
121
|
+
|
|
122
|
+
- explicit `bridge start|status|stop`
|
|
123
|
+
- `bridge stop` idempotency without runtime state
|
|
124
|
+
- recovered-port persistence into `providers.json` and `config.toml`
|
|
125
|
+
- cleanup when recovered-port persistence fails for a newly started worker
|
|
126
|
+
- cleanup when recovered-port persistence fails after replacing a previous worker
|
|
127
|
+
- providers rollback when config projection update fails
|
|
128
|
+
- stale runtime-state surfaced by `status` and `doctor` while a direct provider is active
|
|
129
|
+
- `switchProvider()` keeps bridge cleanup semantics on failure
|
|
130
|
+
|
|
131
|
+
Recommended additions when extending workflow coverage:
|
|
132
|
+
|
|
133
|
+
- active-provider bridge target resolution without explicit provider argument
|
|
134
|
+
- sole Copilot provider resolution without explicit provider argument
|
|
135
|
+
- explicit mismatch guard for `bridge stop`
|
|
136
|
+
- explicit mismatch guard for `bridge status`
|
|
137
|
+
- `BRIDGE_TARGET_UNRESOLVED` for non-interactive multi-provider ambiguity
|
|
138
|
+
|
|
139
|
+
### Command tests
|
|
140
|
+
|
|
141
|
+
Required scenarios:
|
|
142
|
+
|
|
143
|
+
- nested `bridge` command parsing
|
|
144
|
+
- bridge help text rendering
|
|
145
|
+
- `executeCommand()` dispatches `bridge start|status|stop`
|
|
146
|
+
|
|
147
|
+
Recommended additions when extending command coverage:
|
|
148
|
+
|
|
149
|
+
- `executeCommand()` mismatch guard for `bridge stop`
|
|
150
|
+
- `executeCommand()` mismatch guard for `bridge status`
|
|
151
|
+
- `executeCommand()` unresolved target failures
|
|
152
|
+
|
|
153
|
+
### Built CLI tests
|
|
154
|
+
|
|
155
|
+
Required scenarios:
|
|
156
|
+
|
|
157
|
+
- `bridge start|status|stop` through the built CLI entrypoint
|
|
158
|
+
- read-command JSON envelope remains stable while `doctor` now may report multiple issue codes
|
|
159
|
+
|
|
160
|
+
Recommended additions when extending CLI coverage:
|
|
161
|
+
|
|
162
|
+
- `bridge status` stale runtime-state envelope
|
|
163
|
+
- `bridge start` unresolved-target envelope
|
|
164
|
+
|
|
165
|
+
## Fast Execution Order
|
|
166
|
+
|
|
167
|
+
When time is limited, implement and verify tests in this order:
|
|
168
|
+
|
|
169
|
+
1. `tests/commands.spec.js`
|
|
170
|
+
2. `tests/workflows.spec.js`
|
|
171
|
+
3. `tests/cli-e2e.spec.js`
|
|
172
|
+
4. `tests/runtime.spec.js`
|
|
173
|
+
|
|
174
|
+
This order catches the highest-value regressions first:
|
|
175
|
+
|
|
176
|
+
- wiring regressions
|
|
177
|
+
- persistence/cleanup regressions
|
|
178
|
+
- user-visible CLI regressions
|
|
179
|
+
- low-level runtime regressions
|
|
180
|
+
|
|
181
|
+
## Running The Suite
|
|
182
|
+
|
|
183
|
+
Build and run all tests:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
npm test
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
This runs:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
npm run build
|
|
193
|
+
node tests/run-tests.js
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Release Gate For `0.0.9`
|
|
197
|
+
|
|
198
|
+
Treat bridge automation as release-ready only when all of the following are true:
|
|
199
|
+
|
|
200
|
+
- `commands`, `runtime`, `workflows`, and `cli-e2e` all pass
|
|
201
|
+
- `bridge start|stop|status` are covered at both app and CLI layers
|
|
202
|
+
- single-instance reuse and replacement are covered
|
|
203
|
+
- recovered-port persistence and cleanup failure paths are covered
|
|
204
|
+
- stale runtime-state diagnostics are covered in both `status` and `doctor`
|
|
205
|
+
|
|
206
|
+
## Remaining Manual Smoke Checks
|
|
207
|
+
|
|
208
|
+
Automated coverage does not replace a final real-environment smoke pass.
|
|
209
|
+
|
|
210
|
+
Before shipping, still run a logged-in Copilot smoke check for:
|
|
211
|
+
|
|
212
|
+
- real `bridge start`
|
|
213
|
+
- real `bridge status`
|
|
214
|
+
- one real request through `/v1/chat/completions`
|
|
215
|
+
- real `bridge stop`
|
|
216
|
+
- real `switch <copilot-provider>` reuse/replacement behavior
|
|
217
|
+
|
|
218
|
+
## Minimal Manual Smoke Checklist
|
|
219
|
+
|
|
220
|
+
Use this short checklist after the automated suite passes and after you have logged into Copilot in the real target environment.
|
|
221
|
+
|
|
222
|
+
### Preconditions
|
|
223
|
+
|
|
224
|
+
- run from the repository root
|
|
225
|
+
- use the real Codex directory you intend to validate
|
|
226
|
+
- ensure the target Copilot provider already exists in `providers.json`
|
|
227
|
+
- ensure the optional Copilot SDK is installed
|
|
228
|
+
- ensure you are logged into Copilot before starting the live smoke pass
|
|
229
|
+
|
|
230
|
+
Suggested placeholder values:
|
|
231
|
+
|
|
232
|
+
- `<CODEX_DIR>`: your real Codex directory
|
|
233
|
+
- `<COPILOT_PROVIDER>`: the Copilot-backed provider name you want to validate
|
|
234
|
+
|
|
235
|
+
### 1. Confirm the automated gate is still green
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
npm test
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Expected result:
|
|
242
|
+
|
|
243
|
+
- build succeeds
|
|
244
|
+
- all automated suites pass
|
|
245
|
+
|
|
246
|
+
### 2. Start the real managed bridge
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
node dist/cli.js bridge start <COPILOT_PROVIDER> --json --codex-dir <CODEX_DIR>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Expected result:
|
|
253
|
+
|
|
254
|
+
- command exits successfully
|
|
255
|
+
- JSON payload reports the requested provider
|
|
256
|
+
- payload includes `host`, `port`, and `baseUrl`
|
|
257
|
+
- `reused` is `false` on the first successful start unless a healthy matching bridge is already running
|
|
258
|
+
|
|
259
|
+
### 3. Confirm bridge status
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
node dist/cli.js bridge status <COPILOT_PROVIDER> --json --codex-dir <CODEX_DIR>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Expected result:
|
|
266
|
+
|
|
267
|
+
- command exits successfully
|
|
268
|
+
- `health.ok` is `true`
|
|
269
|
+
- `active` is `true`
|
|
270
|
+
- `matches` is `true`
|
|
271
|
+
|
|
272
|
+
### 4. Send one real request through the bridge
|
|
273
|
+
|
|
274
|
+
Use the `baseUrl` and API key from the selected provider record. Replace `<BRIDGE_BASE_URL>` and `<BRIDGE_API_KEY>` with real values from your environment.
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
curl -sS <BRIDGE_BASE_URL>/chat/completions \
|
|
278
|
+
-H "Content-Type: application/json" \
|
|
279
|
+
-H "Authorization: Bearer <BRIDGE_API_KEY>" \
|
|
280
|
+
-d "{\"model\":\"gpt-4o-mini\",\"messages\":[{\"role\":\"user\",\"content\":\"Reply with the single word OK.\"}]}"
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Expected result:
|
|
284
|
+
|
|
285
|
+
- HTTP request succeeds
|
|
286
|
+
- response contains a completion payload
|
|
287
|
+
- model output proves the request reached the live bridge successfully
|
|
288
|
+
|
|
289
|
+
If your shell or environment prefers the OpenAI-style path, validate the same request against:
|
|
290
|
+
|
|
291
|
+
```text
|
|
292
|
+
<BRIDGE_BASE_URL>/chat/completions
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### 5. Verify same-provider reuse
|
|
296
|
+
|
|
297
|
+
Run the start command again:
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
node dist/cli.js bridge start <COPILOT_PROVIDER> --json --codex-dir <CODEX_DIR>
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Expected result:
|
|
304
|
+
|
|
305
|
+
- command exits successfully
|
|
306
|
+
- `reused` is `true`
|
|
307
|
+
- reported `port` remains stable
|
|
308
|
+
|
|
309
|
+
### 6. Verify switch reuse or replacement behavior
|
|
310
|
+
|
|
311
|
+
Run a real switch into the Copilot provider:
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
node dist/cli.js switch <COPILOT_PROVIDER> --json --codex-dir <CODEX_DIR>
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
Expected result:
|
|
318
|
+
|
|
319
|
+
- command exits successfully
|
|
320
|
+
- provider/profile switch succeeds
|
|
321
|
+
- if the same healthy bridge is already running, it is reused
|
|
322
|
+
- if another managed bridge instance was active, it is replaced cleanly
|
|
323
|
+
|
|
324
|
+
If you have a second Copilot provider available, also validate explicit replacement:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
node dist/cli.js bridge start <SECOND_COPILOT_PROVIDER> --json --codex-dir <CODEX_DIR>
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Expected result:
|
|
331
|
+
|
|
332
|
+
- previous managed instance is replaced
|
|
333
|
+
- status for the new provider is healthy
|
|
334
|
+
- no stale runtime-state mismatch is left behind
|
|
335
|
+
|
|
336
|
+
### 7. Stop the managed bridge
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
node dist/cli.js bridge stop <COPILOT_PROVIDER> --json --codex-dir <CODEX_DIR>
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Expected result:
|
|
343
|
+
|
|
344
|
+
- command exits successfully
|
|
345
|
+
- payload reports `stopped: true`
|
|
346
|
+
|
|
347
|
+
### 8. Confirm shutdown state
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
node dist/cli.js bridge status <COPILOT_PROVIDER> --json --codex-dir <CODEX_DIR>
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
Expected result:
|
|
354
|
+
|
|
355
|
+
- command may either report inactive bridge health or a missing runtime state, depending on the exact environment state
|
|
356
|
+
- it must not falsely report a healthy active managed bridge after stop
|
|
357
|
+
|
|
358
|
+
### Manual Pass Criteria
|
|
359
|
+
|
|
360
|
+
Treat the live smoke pass as complete only when all of the following are true:
|
|
361
|
+
|
|
362
|
+
- `bridge start` succeeds in a logged-in real environment
|
|
363
|
+
- `bridge status` reports a healthy active bridge
|
|
364
|
+
- one real request succeeds through the bridge
|
|
365
|
+
- repeated `bridge start` reuses the same healthy instance
|
|
366
|
+
- `switch <copilot-provider>` preserves expected reuse/replacement behavior
|
|
367
|
+
- `bridge stop` shuts the managed instance down cleanly
|
package/docs/cli-usage.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# codex-switch CLI Usage
|
|
2
2
|
|
|
3
|
-
本文档详细介绍 `codex-switch` 在 `0.0.
|
|
3
|
+
本文档详细介绍 `codex-switch` 在 `0.0.10` 版本中的命令、参数、交互规则和典型使用方式。
|
|
4
4
|
|
|
5
5
|
可执行命令名:
|
|
6
6
|
|
|
@@ -260,9 +260,9 @@ codexs migrate --merge --codex-dir ./.tmp-codex
|
|
|
260
260
|
行为说明:
|
|
261
261
|
|
|
262
262
|
- 读取 `config.toml` 中已有 profile
|
|
263
|
-
- 仅 adopt 已具备 `model`、`model_provider` 且能解析到匹配 `model_providers.*.base_url`
|
|
263
|
+
- 仅 adopt 已具备 `model`、`model_provider` 且能解析到匹配 `model_providers.*.base_url` 的 unmanaged profile
|
|
264
264
|
- 收集每个 profile 对应的 provider 记录
|
|
265
|
-
-
|
|
265
|
+
- 保持现有受管备份、锁和 post-run `doctor` 流程,不重写 `auth.json`
|
|
266
266
|
|
|
267
267
|
交互模式:
|
|
268
268
|
|
|
@@ -291,14 +291,15 @@ codexs setup
|
|
|
291
291
|
|
|
292
292
|
### 5.4 `add`
|
|
293
293
|
|
|
294
|
-
新增一个 provider
|
|
294
|
+
新增一个 provider。`add` 当前同时支持 direct provider 和 Copilot bridge provider 两条路径。
|
|
295
295
|
|
|
296
296
|
```bash
|
|
297
297
|
codexs add <provider> --profile <name> --api-key <key> [--base-url <url>] [--note <text>] [--tag <tag> ...]
|
|
298
|
-
codexs add
|
|
298
|
+
codexs add <provider> --copilot --profile <name> [--bridge-host <host>] [--bridge-port <port>] [--bridge-api-key <secret>] [--install-copilot-sdk]
|
|
299
|
+
codexs add
|
|
299
300
|
```
|
|
300
301
|
|
|
301
|
-
示例:
|
|
302
|
+
direct provider 示例:
|
|
302
303
|
|
|
303
304
|
```bash
|
|
304
305
|
codexs add packycode --profile packycode --api-key sk-xxx
|
|
@@ -306,7 +307,14 @@ codexs add packycode --profile packycode --api-key sk-xxx --tag paid --tag daily
|
|
|
306
307
|
codexs add
|
|
307
308
|
```
|
|
308
309
|
|
|
309
|
-
|
|
310
|
+
Copilot provider 示例:
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
codexs add copilot-main --copilot --profile copilot-main --install-copilot-sdk
|
|
314
|
+
codexs add copilot-main --copilot --profile copilot-main --bridge-port 41415 --bridge-api-key local-secret
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
direct provider 字段说明:
|
|
310
318
|
|
|
311
319
|
- `provider`:provider 名称,也是后续 `switch/show/edit/remove` 的标识
|
|
312
320
|
- `--profile`:写入到 `config.toml` 的 profile 名称
|
|
@@ -315,16 +323,31 @@ codexs add
|
|
|
315
323
|
- `--note`:备注
|
|
316
324
|
- `--tag`:标签,可重复传多次
|
|
317
325
|
|
|
326
|
+
Copilot provider 字段说明:
|
|
327
|
+
|
|
328
|
+
- `--copilot`:切换到 Copilot provider 模式
|
|
329
|
+
- `--profile`:必填
|
|
330
|
+
- `--api-key`:在 `--copilot` 下禁止使用;Copilot 不接收 direct provider API key
|
|
331
|
+
- `--bridge-host`:本地 bridge host,默认 `127.0.0.1`
|
|
332
|
+
- `--bridge-port`:本地 bridge port,默认 `41415`
|
|
333
|
+
- `--bridge-api-key`:本地 bridge shared secret;留空时自动生成
|
|
334
|
+
- `--install-copilot-sdk`:允许在首次接入时安装可选 Copilot SDK runtime
|
|
335
|
+
|
|
318
336
|
交互模式:
|
|
319
337
|
|
|
320
|
-
-
|
|
321
|
-
-
|
|
322
|
-
-
|
|
323
|
-
-
|
|
338
|
+
- direct provider 缺少 `provider`、`profile`、`apiKey` 时,会在 TTY 中补问
|
|
339
|
+
- direct provider 的 API key 隐藏输入会做二次确认
|
|
340
|
+
- Copilot provider 会先做固定 preflight:检查 SDK、必要时立即安装、检查 GitHub Copilot 登录态、必要时执行官方 `copilot login`,全部通过后才进入专用输入流
|
|
341
|
+
- Copilot provider 的专用输入流只采集 provider/profile/model、note/tags 和 bridge 参数
|
|
342
|
+
- Copilot provider 不会提示 `API key`、`Confirm API key` 或输出 `API key is required.`
|
|
343
|
+
- 若官方 `copilot login` 无法启动,会回退为人工提示:运行 `copilot login`,完成 GitHub 官方 device/browser 流程后执行一次明确 recheck
|
|
344
|
+
- `add --copilot --json` 永远不会启动登录流程;若 auth 未就绪,直接返回 `COPILOT_AUTH_REQUIRED`,并提示手动运行 `copilot login`
|
|
324
345
|
|
|
325
346
|
非交互模式:
|
|
326
347
|
|
|
327
|
-
- 必须显式传入所有必填字段
|
|
348
|
+
- direct provider 必须显式传入所有必填字段
|
|
349
|
+
- `add --copilot` 必须显式传入 `<provider>` 和 `--profile`
|
|
350
|
+
- `add --copilot --json` 不会进入任何 prompt;若 SDK 缺失且未传 `--install-copilot-sdk`,直接失败;若 auth 未就绪,也直接返回 `COPILOT_AUTH_REQUIRED`
|
|
328
351
|
|
|
329
352
|
### 5.5 `edit`
|
|
330
353
|
|
|
@@ -377,8 +400,9 @@ codexs switch
|
|
|
377
400
|
|
|
378
401
|
- 根据 `providers.json` 找到目标 provider
|
|
379
402
|
- 更新相关运行态配置
|
|
380
|
-
-
|
|
381
|
-
-
|
|
403
|
+
- direct provider 会切换当前 active profile,并将 `auth.json` 重写为 `auth_mode = "apikey"` 和 `OPENAI_API_KEY = <provider.apiKey>`
|
|
404
|
+
- Copilot bridge provider 不写 `OPENAI_API_KEY`,而是维护本地 bridge 路由
|
|
405
|
+
- 备份 `config.toml`,并在 direct provider 切换时一并备份 `auth.json`
|
|
382
406
|
|
|
383
407
|
交互模式:
|
|
384
408
|
|
|
@@ -150,7 +150,7 @@ MVP 的能力范围主要包括:
|
|
|
150
150
|
|
|
151
151
|
- `config.toml` 是主配置文件
|
|
152
152
|
- `providers.json` 是 `codex-switch` 自身维护的 provider 清单
|
|
153
|
-
- `auth.json`
|
|
153
|
+
- `auth.json` 是当前 active direct provider 的认证投影文件;切换 direct provider 时会刷新 `OPENAI_API_KEY`
|
|
154
154
|
- `backups/` 用于保存历史备份
|
|
155
155
|
|
|
156
156
|
产品不会要求用户先理解全部内部实现,只暴露统一的命令接口。
|
|
@@ -167,7 +167,7 @@ MVP 的能力范围主要包括:
|
|
|
167
167
|
|
|
168
168
|
### 场景 3:切换到目标 provider
|
|
169
169
|
|
|
170
|
-
|
|
170
|
+
用户执行切换命令后,工具会完成校验、备份、修改运行态配置,并在 direct provider 场景下同步 `auth.json`。
|
|
171
171
|
|
|
172
172
|
### 场景 4:出现异常时恢复
|
|
173
173
|
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
- `Low Coupling`
|
|
99
99
|
- 参数解析、业务编排、文件访问、错误模型彼此解耦
|
|
100
100
|
- `Split State Model`
|
|
101
|
-
|
|
101
|
+
- `providers.json` 是管理态事实源,`config.toml` 是运行态路由文件,`auth.json` 是 direct provider 的认证投影
|
|
102
102
|
- `Lightweight Transactions`
|
|
103
103
|
- 单次写操作要有锁、备份、回滚边界
|
|
104
104
|
|
|
@@ -125,7 +125,8 @@ Infrastructure 层
|
|
|
125
125
|
当前实现还明确区分三类状态对象:
|
|
126
126
|
|
|
127
127
|
- 管理态单一事实源:`providers.json`
|
|
128
|
-
-
|
|
128
|
+
- 运行态路由:`config.toml`
|
|
129
|
+
- 当前 active direct provider 的认证投影:`auth.json`
|
|
129
130
|
- 回滚态:`backups/latest.json` 和对应 manifest
|
|
130
131
|
|
|
131
132
|
这意味着未来即使引入 GUI / MCP / HTTP 适配层,核心同步目标仍然是 runtime files,而不是把 runtime files 本身当成长期管理数据库。
|
|
@@ -555,13 +556,13 @@ scripts/
|
|
|
555
556
|
- 深度解析 profile 内部更多字段
|
|
556
557
|
- 管理 base URL 或模型等 profile 内容
|
|
557
558
|
|
|
558
|
-
|
|
559
|
+
它在当前架构里是 direct provider 的认证投影文件,不承担 provider 选择职责,也不作为 provider registry 的事实源。
|
|
559
560
|
|
|
560
561
|
### 5.3 `auth.json`
|
|
561
562
|
|
|
562
563
|
当前实现不直接建模其内部字段,但它有明确架构角色:
|
|
563
564
|
|
|
564
|
-
-
|
|
565
|
+
- 属于 direct provider 的认证投影
|
|
565
566
|
- 在存在时纳入备份与回滚
|
|
566
567
|
- 不是 provider registry 的事实源
|
|
567
568
|
|
|
@@ -622,7 +623,7 @@ scripts/
|
|
|
622
623
|
6. 校验 provider 对应的 `profile` 在配置中存在
|
|
623
624
|
7. 创建备份:
|
|
624
625
|
- `config.toml`
|
|
625
|
-
|
|
626
|
+
- `auth.json` 仅在历史备份清单已包含时由 rollback 兼容恢复
|
|
626
627
|
8. 更新顶层 `profile`
|
|
627
628
|
9. 如果未传 `--no-login`,执行 `codex login --with-api-key`
|
|
628
629
|
10. 成功后把这次备份记录为 `latest.json`
|