@minniexcode/codex-switch 0.0.4 → 0.0.6
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.md +35 -97
- package/dist/app/add-provider.js +40 -3
- package/dist/app/edit-provider.js +76 -3
- package/dist/app/export-providers.js +2 -2
- package/dist/app/get-current-profile.js +1 -1
- package/dist/app/get-status.js +10 -3
- package/dist/app/import-providers.js +47 -3
- package/dist/app/list-backups.js +1 -1
- package/dist/app/list-config-profiles.js +30 -0
- package/dist/app/list-providers.js +1 -1
- package/dist/app/remove-provider.js +35 -3
- package/dist/app/rollback-backup.js +1 -1
- package/dist/app/rollback-latest.js +1 -1
- package/dist/app/run-doctor.js +44 -26
- package/dist/app/run-mutation.js +2 -2
- package/dist/app/setup-codex.js +37 -20
- package/dist/app/show-config.js +34 -0
- package/dist/app/show-provider.js +1 -1
- package/dist/app/switch-provider.js +8 -5
- package/dist/cli/add-interactive.js +7 -106
- package/dist/cli/args.js +5 -126
- package/dist/cli/help.js +5 -276
- package/dist/cli/interactive.js +16 -171
- package/dist/cli/output.js +23 -1
- package/dist/cli/prompt.js +3 -108
- package/dist/cli.js +10 -315
- package/dist/commands/args.js +132 -0
- package/dist/commands/dispatch.js +16 -0
- package/dist/commands/handlers.js +391 -0
- package/dist/commands/help.js +119 -0
- package/dist/commands/registry.js +291 -0
- package/dist/commands/types.js +2 -0
- package/dist/domain/config.js +548 -39
- package/dist/infra/backup-repo.js +8 -208
- package/dist/infra/codex-cli.js +8 -113
- package/dist/infra/codex-discovery.js +3 -41
- package/dist/infra/codex-paths.js +5 -69
- package/dist/infra/config-repo.js +161 -9
- package/dist/infra/fs-utils.js +7 -95
- package/dist/infra/lock-repo.js +3 -97
- package/dist/infra/providers-repo.js +7 -96
- package/dist/interaction/add-interactive.js +108 -0
- package/dist/interaction/interactive.js +216 -0
- package/dist/interaction/prompt.js +110 -0
- package/dist/runtime/codex-cli.js +130 -0
- package/dist/runtime/codex-probe.js +50 -0
- package/dist/runtime/types.js +2 -0
- package/dist/storage/backup-repo.js +210 -0
- package/dist/storage/codex-paths.js +71 -0
- package/dist/storage/config-repo.js +208 -0
- package/dist/storage/fs-utils.js +97 -0
- package/dist/storage/lock-repo.js +99 -0
- package/dist/storage/providers-repo.js +98 -0
- package/docs/Design/codex-switch-v0.0.5-design.md +932 -0
- package/docs/Design/codex-switch-v0.0.6-design.md +708 -0
- package/docs/PRD/codex-switch-prd-v0.0.5-to-v0.1.0.md +340 -0
- package/docs/PRD/codex-switch-prd-v0.1.0.md +215 -291
- package/docs/PRD/codex-switch-prd.md +1 -1
- package/docs/cli-usage.md +2 -1
- package/docs/codex-switch-technical-architecture.md +73 -4
- package/docs/test-report-0.0.5.md +163 -0
- package/docs/testing.md +131 -0
- package/package.json +1 -1
- /package/docs/{codex-switch-v0.0.4-design.md → Design/codex-switch-v0.0.4-design.md} +0 -0
|
@@ -0,0 +1,708 @@
|
|
|
1
|
+
# codex-switch `0.0.6` 设计文档
|
|
2
|
+
|
|
3
|
+
## 文档信息
|
|
4
|
+
|
|
5
|
+
- 文档类型:详细设计文档
|
|
6
|
+
- 适用版本:`0.0.6`
|
|
7
|
+
- 目标范围:`0.0.5 -> 0.0.6`
|
|
8
|
+
- 主对齐 PRD:[`../PRD/codex-switch-prd-v0.1.0.md`](../PRD/codex-switch-prd-v0.1.0.md)
|
|
9
|
+
- 远期边界参考:[`../PRD/codex-switch-prd-v0.0.5-to-v0.1.0.md`](../PRD/codex-switch-prd-v0.0.5-to-v0.1.0.md)
|
|
10
|
+
- 风格基线:[`codex-switch-v0.0.5-design.md`](./codex-switch-v0.0.5-design.md)
|
|
11
|
+
|
|
12
|
+
## 1. 文档目标
|
|
13
|
+
|
|
14
|
+
这份文档回答的是 `0.0.6` 应该怎样落地,而不是继续讨论长期愿景:
|
|
15
|
+
|
|
16
|
+
- `0.0.5` 已经落下来的命令能力哪些必须稳住,哪些边缘行为必须收口
|
|
17
|
+
- `0.0.6` 为什么不是“再加一批新命令”,而是“稳定性 + 模块化”版本
|
|
18
|
+
- 当前 `src/cli.ts`、`src/app/types.ts`、`src/infra/` 的职责混合问题应该怎样拆开
|
|
19
|
+
- 未来第三方 auth / proxy / SDK 相关需求,在本版里只应该沉淀成什么内部扩展契约
|
|
20
|
+
|
|
21
|
+
目标是让实现阶段不再重复拍板“要不要重构”“命令表面怎么统一”“未来集成往哪层放”这些关键问题。
|
|
22
|
+
|
|
23
|
+
## 2. 版本定位与设计原则
|
|
24
|
+
|
|
25
|
+
### 2.1 当前基线
|
|
26
|
+
|
|
27
|
+
当前 `0.0.5` 已具备:
|
|
28
|
+
|
|
29
|
+
- provider registry 管理:`list`、`show`、`add`、`edit`、`remove`
|
|
30
|
+
- 运行态切换:`current`、`switch`
|
|
31
|
+
- 导入导出:`import`、`import --merge`、`export`
|
|
32
|
+
- 初始化与诊断:`setup`、`status`、`doctor`
|
|
33
|
+
- 备份恢复:`backups list`、`rollback`
|
|
34
|
+
- `config show` / `config list-profiles`
|
|
35
|
+
- 统一 JSON envelope
|
|
36
|
+
- 写操作统一走锁、备份、失败回滚
|
|
37
|
+
|
|
38
|
+
当前主要短板已经不再是“缺命令”,而是:
|
|
39
|
+
|
|
40
|
+
- help、参数、TTY 和 `--json` 的行为仍有继续统一的空间
|
|
41
|
+
- `src/cli.ts` 已承担过多解析、分发、交互和异常渲染职责
|
|
42
|
+
- CLI 解析类型与应用层类型混放,层次所有权不清
|
|
43
|
+
- `infra` 同时装文件仓储和外部运行时调用,未来会继续膨胀
|
|
44
|
+
|
|
45
|
+
### 2.2 `0.0.6` 的一句话定义
|
|
46
|
+
|
|
47
|
+
`0.0.6` 的核心不是继续扩张命令面,而是修复 `0.0.5` 的稳定性问题,冻结当前 CLI 公共契约,并把实现收敛为适合继续扩展的显式分层结构。
|
|
48
|
+
|
|
49
|
+
### 2.3 设计原则
|
|
50
|
+
|
|
51
|
+
`0.0.6` 继续沿用现有工程原则:
|
|
52
|
+
|
|
53
|
+
- `CLI First`
|
|
54
|
+
- `Local First`
|
|
55
|
+
- `Safe by Default`
|
|
56
|
+
- `AI Friendly`
|
|
57
|
+
- `Split State Model`
|
|
58
|
+
- `Lightweight Transactions`
|
|
59
|
+
|
|
60
|
+
在此基础上新增三条版本原则:
|
|
61
|
+
|
|
62
|
+
- 不破坏当前 help、命令名和 `--json` envelope
|
|
63
|
+
- 架构重构必须先收口公共契约,再做内部迁移
|
|
64
|
+
- 未来 integration 能力只能挂在独立 runtime / integration 边界,不得重新耦合回 CLI 入口
|
|
65
|
+
|
|
66
|
+
## 3. 范围与边界
|
|
67
|
+
|
|
68
|
+
### 3.1 `0.0.6` 范围内
|
|
69
|
+
|
|
70
|
+
本设计覆盖:
|
|
71
|
+
|
|
72
|
+
- help 文案、参数、TTY 交互、错误语义的一致性修复
|
|
73
|
+
- 命令分发、交互编排、应用用例、存储访问、运行时集成的重新分层
|
|
74
|
+
- `setup` / `add` / `edit` / `remove` / `import` / `export` / `switch` / `rollback` 的稳定性收口
|
|
75
|
+
- `status` / `doctor` / `config show` / `config list-profiles` 的读取稳定性收口
|
|
76
|
+
- 面向未来 auth / proxy / SDK 的内部能力契约
|
|
77
|
+
|
|
78
|
+
### 3.2 明确不在 `0.0.6` 范围内
|
|
79
|
+
|
|
80
|
+
下面这些内容不进入本设计:
|
|
81
|
+
|
|
82
|
+
- 新增大型命令族
|
|
83
|
+
- 真实 Copilot 登录接入
|
|
84
|
+
- 本地代理服务启动、停止、守护与生命周期管理命令
|
|
85
|
+
- 第三方 SDK 安装器或依赖下载体验
|
|
86
|
+
- GUI / TUI / daemon 化
|
|
87
|
+
- 把 `config.toml` 升级为通用配置编辑器
|
|
88
|
+
|
|
89
|
+
### 3.3 数据与公共契约边界
|
|
90
|
+
|
|
91
|
+
`0.0.6` 继续坚持现有公共边界:
|
|
92
|
+
|
|
93
|
+
- `providers.json`:provider registry 的单一事实源
|
|
94
|
+
- `config.toml`:运行态配置投影,继续保持局部受管
|
|
95
|
+
- `auth.json`:认证态运行时文件
|
|
96
|
+
- `backups/` + `latest.json`:恢复态
|
|
97
|
+
- `--json`:顶层 envelope shape 不变
|
|
98
|
+
|
|
99
|
+
本版允许内部文件和模块重组,但不允许用户可见契约漂移。
|
|
100
|
+
|
|
101
|
+
## 4. 当前实现问题盘点
|
|
102
|
+
|
|
103
|
+
### 4.1 `src/cli.ts` 过重
|
|
104
|
+
|
|
105
|
+
当前 `src/cli.ts` 同时承担:
|
|
106
|
+
|
|
107
|
+
- version 输出
|
|
108
|
+
- help 分发
|
|
109
|
+
- 参数分发
|
|
110
|
+
- 交互能力判断
|
|
111
|
+
- 命令调用
|
|
112
|
+
- 异常归一化和最终渲染
|
|
113
|
+
|
|
114
|
+
这意味着任何一个新命令、新交互分支或未来 integration,都容易继续把复杂度堆回单文件入口。
|
|
115
|
+
|
|
116
|
+
### 4.2 CLI 类型落在 `src/app/types.ts`
|
|
117
|
+
|
|
118
|
+
当前 `ParsedArgs`、`CommandContext` 等 CLI 解析与调度类型放在 `src/app/types.ts`,带来两个问题:
|
|
119
|
+
|
|
120
|
+
- 类型所有权不清,CLI 表面层概念混入用例层
|
|
121
|
+
- 后续要拆 command surface 时,应用层会被迫携带 CLI 历史包袱
|
|
122
|
+
|
|
123
|
+
### 4.3 公开命令形态与内部 command key 未正式抽象
|
|
124
|
+
|
|
125
|
+
当前 help 和解析事实上已经存在两套概念:
|
|
126
|
+
|
|
127
|
+
- 公开 CLI 形态:`config show`、`config list-profiles`、`backups list`
|
|
128
|
+
- 内部执行 key:`config-show`、`config-list-profiles`、`backups-list`
|
|
129
|
+
|
|
130
|
+
这套事实目前只散落在 `help.ts` 和 `args.ts` 中,没有被提升成正式抽象,因此 help、参数解析和 dispatch 仍可能出现映射漂移。
|
|
131
|
+
|
|
132
|
+
### 4.4 `src/infra/` 职责过宽
|
|
133
|
+
|
|
134
|
+
当前 `src/infra/` 同时承载:
|
|
135
|
+
|
|
136
|
+
- `providers.json` / `config.toml` / 备份 / 锁 / 路径解析
|
|
137
|
+
- `codex` CLI 调用与可用性检查
|
|
138
|
+
|
|
139
|
+
如果未来 auth adapter、proxy runtime、SDK probe 继续往这里堆,`infra` 会再次变成“什么都放”的兜底目录,边界无法稳定。
|
|
140
|
+
|
|
141
|
+
## 5. `0.0.6` 功能总览
|
|
142
|
+
|
|
143
|
+
`0.0.6` 需要完成四件事:
|
|
144
|
+
|
|
145
|
+
- 巩固现有命令的 help、参数、TTY、错误和回滚行为
|
|
146
|
+
- 把 command surface、interaction、application、storage、runtime 的职责边界显式化
|
|
147
|
+
- 让 `src/cli.ts` 缩回薄入口,只保留 bootstrap 与最终渲染职责
|
|
148
|
+
- 为未来第三方 auth / proxy / SDK 接入预留清晰但非侵入式的 runtime 边界
|
|
149
|
+
|
|
150
|
+
## 6. 目标架构
|
|
151
|
+
|
|
152
|
+
### 6.1 最终结构方向
|
|
153
|
+
|
|
154
|
+
`0.0.6` 设计稿直接锁定目标源码结构为:
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
src/
|
|
158
|
+
cli.ts
|
|
159
|
+
commands/
|
|
160
|
+
interaction/
|
|
161
|
+
application/
|
|
162
|
+
domain/
|
|
163
|
+
storage/
|
|
164
|
+
runtime/
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
说明:
|
|
168
|
+
|
|
169
|
+
- `src/cli.ts` 保留为薄入口,不再承担持续膨胀的业务编排
|
|
170
|
+
- 这不是要求一次性重命名所有文件完成“大爆炸迁移”
|
|
171
|
+
- 这是最终结构方向,迁移允许分阶段完成
|
|
172
|
+
|
|
173
|
+
### 6.2 为什么选择 Hybrid 显式分层
|
|
174
|
+
|
|
175
|
+
`0.0.6` 不采用“所有命令逻辑继续围绕 CLI 文件散开”的路线,也不要求引入过度设计的框架式架构。
|
|
176
|
+
|
|
177
|
+
这里锁定的是一套 Hybrid 分层:
|
|
178
|
+
|
|
179
|
+
- 上层围绕命令表面与交互体验组织
|
|
180
|
+
- 中层围绕应用用例与领域规则组织
|
|
181
|
+
- 下层按持久化与运行时依赖做边界隔离
|
|
182
|
+
|
|
183
|
+
这样既能保留现有 CLI 工程的简单性,也能防止未来第三方集成倒灌回入口层。
|
|
184
|
+
|
|
185
|
+
## 7. 模块职责设计
|
|
186
|
+
|
|
187
|
+
### 7.1 `commands/`
|
|
188
|
+
|
|
189
|
+
`commands/` 是命令表面层,负责:
|
|
190
|
+
|
|
191
|
+
- `parseArgs`
|
|
192
|
+
- help 定义与渲染
|
|
193
|
+
- `CommandId` 与公开 token 映射
|
|
194
|
+
- command registry
|
|
195
|
+
- dispatch orchestration
|
|
196
|
+
- `ParsedCommand` / `CommandExecutionContext` 这类类型归属
|
|
197
|
+
|
|
198
|
+
明确不负责:
|
|
199
|
+
|
|
200
|
+
- 真实文件写入
|
|
201
|
+
- 直接业务事务
|
|
202
|
+
- 终端 prompt 细节实现
|
|
203
|
+
- 第三方 CLI / SDK 调用
|
|
204
|
+
|
|
205
|
+
### 7.2 `interaction/`
|
|
206
|
+
|
|
207
|
+
`interaction/` 是纯交互层,负责:
|
|
208
|
+
|
|
209
|
+
- `PromptRuntime`
|
|
210
|
+
- `canPrompt`
|
|
211
|
+
- provider 选择
|
|
212
|
+
- 危险确认
|
|
213
|
+
- setup 目录选择
|
|
214
|
+
- 渐进式补问
|
|
215
|
+
- 交互取消语义
|
|
216
|
+
|
|
217
|
+
交互层的唯一产物是“已决输入”,而不是文件副作用:
|
|
218
|
+
|
|
219
|
+
- 可以决定 providerName / profile / strategy / confirm 等输入
|
|
220
|
+
- 不直接写 `providers.json`、`config.toml`、`auth.json`
|
|
221
|
+
|
|
222
|
+
### 7.3 `application/`
|
|
223
|
+
|
|
224
|
+
`application/` 是用例编排层,继续保留现有命令 use case 思想,但要求:
|
|
225
|
+
|
|
226
|
+
- 每个 use case 只接收显式参数
|
|
227
|
+
- 不直接依赖终端 IO
|
|
228
|
+
- 不再承载 CLI 解析类型
|
|
229
|
+
- 继续负责双写事务、结果契约和回滚增强
|
|
230
|
+
|
|
231
|
+
它是 command surface 到 storage / runtime / domain 的稳定入口。
|
|
232
|
+
|
|
233
|
+
### 7.4 `domain/`
|
|
234
|
+
|
|
235
|
+
`domain/` 继续保留,但职责要显式收紧为:
|
|
236
|
+
|
|
237
|
+
- provider / config / runtime-state 规则
|
|
238
|
+
- 错误码与纯规则判断
|
|
239
|
+
- 共享 profile、悬空 active profile、一致性 issue 等策略
|
|
240
|
+
|
|
241
|
+
明确不承载:
|
|
242
|
+
|
|
243
|
+
- 命令解析
|
|
244
|
+
- prompt 流程
|
|
245
|
+
- 文件系统访问
|
|
246
|
+
- 外部 CLI / SDK 可用性探测
|
|
247
|
+
|
|
248
|
+
### 7.5 `storage/`
|
|
249
|
+
|
|
250
|
+
`storage/` 从 `infra` 中拆出,职责锁定为:
|
|
251
|
+
|
|
252
|
+
- `providers.json` / `config.toml` / backups / lock / path resolution
|
|
253
|
+
- 原子写入
|
|
254
|
+
- 备份 manifest
|
|
255
|
+
- 文件读取校验
|
|
256
|
+
|
|
257
|
+
明确不承载:
|
|
258
|
+
|
|
259
|
+
- `codex` CLI 调用
|
|
260
|
+
- 第三方 auth / SDK / proxy 调用
|
|
261
|
+
|
|
262
|
+
### 7.6 `runtime/`
|
|
263
|
+
|
|
264
|
+
`runtime/` 从 `infra` 中拆出,职责锁定为:
|
|
265
|
+
|
|
266
|
+
- 当前 `codex` CLI 调用
|
|
267
|
+
- 未来第三方 auth adapter
|
|
268
|
+
- 未来本地 proxy runtime
|
|
269
|
+
- 外部依赖探测与版本 / 可用性检查
|
|
270
|
+
|
|
271
|
+
这层唯一目标是吸收“依赖外部程序或外部集成”的复杂度,而不是承载 provider/config 核心规则。
|
|
272
|
+
|
|
273
|
+
## 8. 内部接口与类型
|
|
274
|
+
|
|
275
|
+
`0.0.6` 不锁未来用户命令,但锁内部契约名称和边界。
|
|
276
|
+
|
|
277
|
+
### 8.1 `CommandId`
|
|
278
|
+
|
|
279
|
+
`CommandId` 表示内部稳定命令标识,和公开 token 序列分离。
|
|
280
|
+
|
|
281
|
+
例如:
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
type CommandId =
|
|
285
|
+
| "config-show"
|
|
286
|
+
| "config-list-profiles"
|
|
287
|
+
| "list"
|
|
288
|
+
| "show"
|
|
289
|
+
| "current"
|
|
290
|
+
| "status"
|
|
291
|
+
| "setup"
|
|
292
|
+
| "edit"
|
|
293
|
+
| "add"
|
|
294
|
+
| "switch"
|
|
295
|
+
| "remove"
|
|
296
|
+
| "import"
|
|
297
|
+
| "export"
|
|
298
|
+
| "backups-list"
|
|
299
|
+
| "doctor"
|
|
300
|
+
| "rollback";
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
设计要求:
|
|
304
|
+
|
|
305
|
+
- 对外命令 token 可以多段
|
|
306
|
+
- 对内 dispatch key 必须稳定单值
|
|
307
|
+
- help、解析、dispatch 和 JSON `command` 字段都应共享同一套命令定义来源
|
|
308
|
+
|
|
309
|
+
### 8.2 `CommandDefinition`
|
|
310
|
+
|
|
311
|
+
`CommandDefinition` 负责描述一条命令的帮助、公开 token、参数规范和处理器绑定。
|
|
312
|
+
|
|
313
|
+
建议内部结构:
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
type CommandDefinition = {
|
|
317
|
+
id: CommandId;
|
|
318
|
+
tokens: string[];
|
|
319
|
+
group: "read" | "write" | "recovery";
|
|
320
|
+
summary: string;
|
|
321
|
+
usage: string[];
|
|
322
|
+
details: string[];
|
|
323
|
+
examples: string[];
|
|
324
|
+
handler: CommandHandler;
|
|
325
|
+
};
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
这样 help 文案、topic 匹配、参数解析和 dispatch 都能共用一份 registry。
|
|
329
|
+
|
|
330
|
+
### 8.3 `CommandHandler`
|
|
331
|
+
|
|
332
|
+
`CommandHandler` 是 command surface 到 application 的统一入口。
|
|
333
|
+
|
|
334
|
+
建议职责:
|
|
335
|
+
|
|
336
|
+
- 接收 `ParsedCommand`
|
|
337
|
+
- 在必要时请求 `InteractiveResolver`
|
|
338
|
+
- 将“已决输入”映射为应用层显式参数
|
|
339
|
+
- 返回稳定 `CommandResult`
|
|
340
|
+
|
|
341
|
+
它不直接做底层文件写入,也不直接操作终端输出。
|
|
342
|
+
|
|
343
|
+
### 8.4 `InteractiveResolver`
|
|
344
|
+
|
|
345
|
+
`InteractiveResolver` 的目标,是把 TTY 条件下的补问与确认从 handler 里拿出去。
|
|
346
|
+
|
|
347
|
+
能力至少包括:
|
|
348
|
+
|
|
349
|
+
- 选择 provider
|
|
350
|
+
- 选择 setup 目录
|
|
351
|
+
- 选择 setup strategy
|
|
352
|
+
- 危险删除确认
|
|
353
|
+
- rollback 确认
|
|
354
|
+
- add / edit 的渐进式缺失字段补问
|
|
355
|
+
|
|
356
|
+
它只产出已决输入或取消结果,不直接调用应用用例。
|
|
357
|
+
|
|
358
|
+
### 8.5 `RuntimeDependencyProbe`
|
|
359
|
+
|
|
360
|
+
`RuntimeDependencyProbe` 负责探测 `codex` CLI 或未来 SDK 是否可用。
|
|
361
|
+
|
|
362
|
+
职责包括:
|
|
363
|
+
|
|
364
|
+
- 可执行文件是否存在
|
|
365
|
+
- 版本是否满足最低要求
|
|
366
|
+
- 环境是否具备调用条件
|
|
367
|
+
- 将失败归一为 runtime/integration 侧错误
|
|
368
|
+
|
|
369
|
+
它不负责 provider/config 规则判断。
|
|
370
|
+
|
|
371
|
+
### 8.6 `AuthRuntimeAdapter` 与 `ProxyRuntimeAdapter`
|
|
372
|
+
|
|
373
|
+
这两个接口在 `0.0.6` 里只定义能力边界,不定义未来命令名。
|
|
374
|
+
|
|
375
|
+
建议能力方向:
|
|
376
|
+
|
|
377
|
+
```ts
|
|
378
|
+
type AuthRuntimeAdapter = {
|
|
379
|
+
probe(): Promise<RuntimeAvailability>;
|
|
380
|
+
readState?(): Promise<unknown>;
|
|
381
|
+
acquire?(): Promise<unknown>;
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
type ProxyRuntimeAdapter = {
|
|
385
|
+
probe(): Promise<RuntimeAvailability>;
|
|
386
|
+
getStatus?(): Promise<unknown>;
|
|
387
|
+
};
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
约束:
|
|
391
|
+
|
|
392
|
+
- 不在 `0.0.6` 里提前承诺 Copilot 用户命令
|
|
393
|
+
- 不在本版里提前锁死 SDK 选型和协议细节
|
|
394
|
+
- 只要求未来集成能以 runtime adapter 形式接入
|
|
395
|
+
|
|
396
|
+
## 9. 命令表面模型
|
|
397
|
+
|
|
398
|
+
### 9.1 公开 CLI 形态
|
|
399
|
+
|
|
400
|
+
公开 CLI 形态继续允许多 token 命令:
|
|
401
|
+
|
|
402
|
+
- `config show`
|
|
403
|
+
- `config list-profiles`
|
|
404
|
+
- `backups list`
|
|
405
|
+
|
|
406
|
+
同时继续保留单 token 命令:
|
|
407
|
+
|
|
408
|
+
- `list`
|
|
409
|
+
- `show`
|
|
410
|
+
- `current`
|
|
411
|
+
- `status`
|
|
412
|
+
- `setup`
|
|
413
|
+
- `edit`
|
|
414
|
+
- `add`
|
|
415
|
+
- `switch`
|
|
416
|
+
- `remove`
|
|
417
|
+
- `import`
|
|
418
|
+
- `export`
|
|
419
|
+
- `doctor`
|
|
420
|
+
- `rollback`
|
|
421
|
+
|
|
422
|
+
### 9.2 内部执行 ID
|
|
423
|
+
|
|
424
|
+
内部执行 ID 继续允许使用稳定 key:
|
|
425
|
+
|
|
426
|
+
- `config-show`
|
|
427
|
+
- `config-list-profiles`
|
|
428
|
+
- `backups-list`
|
|
429
|
+
|
|
430
|
+
这与当前实现事实一致,但在 `0.0.6` 中必须正式化,不再只靠局部 if/else 映射。
|
|
431
|
+
|
|
432
|
+
### 9.3 单一 registry 原则
|
|
433
|
+
|
|
434
|
+
help 文案、参数解析、dispatch 都必须共享同一份 registry,不允许再多处手写映射。
|
|
435
|
+
|
|
436
|
+
禁止继续扩散的形态包括:
|
|
437
|
+
|
|
438
|
+
- `help.ts` 自己维护一套命令名
|
|
439
|
+
- `args.ts` 自己维护一套多 token -> key 映射
|
|
440
|
+
- `cli.ts` 再用 `switch` 补一套分发事实
|
|
441
|
+
|
|
442
|
+
`0.0.6` 的目标是让这三者都从 `CommandDefinition[]` 派生。
|
|
443
|
+
|
|
444
|
+
## 10. 稳定性与错误语义要求
|
|
445
|
+
|
|
446
|
+
### 10.1 help / 参数 / TTY 一致性
|
|
447
|
+
|
|
448
|
+
`0.0.6` 要求显式收口以下行为:
|
|
449
|
+
|
|
450
|
+
- help 文案与真实命令行为一致
|
|
451
|
+
- 默认文本输出与 `--json` 输出语义一致
|
|
452
|
+
- `--json` 一律禁用交互
|
|
453
|
+
- `setup` 在 `0.0.6` 中如果仍依赖 adopt 输入采集,则非交互路径必须显式失败,不允许伪装成“稳定支持但最终必然报错”的半可用状态
|
|
454
|
+
- 非 TTY 一律不进入交互
|
|
455
|
+
- 用户取消 prompt 时不得产生文件写入
|
|
456
|
+
|
|
457
|
+
### 10.2 写命令安全语义
|
|
458
|
+
|
|
459
|
+
所有修改 `providers.json`、`config.toml`、`auth.json` 的命令继续默认遵守:
|
|
460
|
+
|
|
461
|
+
- 单次锁
|
|
462
|
+
- 单次备份
|
|
463
|
+
- 单次失败整体回滚
|
|
464
|
+
|
|
465
|
+
不能接受的状态包括:
|
|
466
|
+
|
|
467
|
+
- `providers.json` 已更新但 `config.toml` 未同步
|
|
468
|
+
- `config.toml` 已更新但 `providers.json` 未同步
|
|
469
|
+
- `auth.json` 或 active profile 留在半切换状态
|
|
470
|
+
|
|
471
|
+
### 10.3 读取稳定性
|
|
472
|
+
|
|
473
|
+
读取命令在 `0.0.6` 至少需要满足:
|
|
474
|
+
|
|
475
|
+
- 历史 workspace 或边缘状态下不轻易崩溃
|
|
476
|
+
- `status` 与 `doctor` 的诊断语义继续对齐
|
|
477
|
+
- `config show` 与 `config list-profiles` 的输出结构稳定
|
|
478
|
+
- 对缺失文件、解析失败和不一致状态给出可预测错误或 warning
|
|
479
|
+
|
|
480
|
+
## 11. 迁移方案
|
|
481
|
+
|
|
482
|
+
### 11.1 Phase 1:抽出 command surface 契约
|
|
483
|
+
|
|
484
|
+
第一阶段目标:
|
|
485
|
+
|
|
486
|
+
- 抽出 command surface 类型和 registry
|
|
487
|
+
- 把 `ParsedArgs`、`CommandContext` 从 `src/app/types.ts` 迁走
|
|
488
|
+
- 明确 `CommandId`、`ParsedCommand`、`CommandExecutionContext` 的所有权
|
|
489
|
+
|
|
490
|
+
这一阶段不追求目录一次性重命名完毕,先解决“谁拥有 CLI 契约”。
|
|
491
|
+
|
|
492
|
+
### 11.2 Phase 2:缩薄 `src/cli.ts`
|
|
493
|
+
|
|
494
|
+
第二阶段目标:
|
|
495
|
+
|
|
496
|
+
- 让 `src/cli.ts` 只保留 bootstrap
|
|
497
|
+
- 只保留 version / help / main / error exit
|
|
498
|
+
- 命令分发和处理器绑定下沉到 `commands/`
|
|
499
|
+
|
|
500
|
+
这一步完成后,入口文件应能稳定维持在薄层。
|
|
501
|
+
|
|
502
|
+
### 11.3 Phase 3:抽离 `interaction/`
|
|
503
|
+
|
|
504
|
+
第三阶段目标:
|
|
505
|
+
|
|
506
|
+
- 把现有 `cli/interactive.ts`、`add-interactive.ts`、`prompt.ts` 收口为独立 `interaction/` 层
|
|
507
|
+
- 把危险确认、补问、目录选择、交互取消统一抽象
|
|
508
|
+
- 避免每个 command handler 再自行散落 prompt 细节
|
|
509
|
+
|
|
510
|
+
### 11.4 Phase 4:拆分 `infra` 为 `storage` 与 `runtime`
|
|
511
|
+
|
|
512
|
+
第四阶段目标:
|
|
513
|
+
|
|
514
|
+
- 先迁 `codex-cli.ts` 一类外部运行时调用到 `runtime/`
|
|
515
|
+
- 把文件读写、锁、备份、路径、仓储收口到 `storage/`
|
|
516
|
+
- 在 runtime 层补齐 capability contracts
|
|
517
|
+
|
|
518
|
+
迁移顺序上先拆运行时入口,再收口未来 probe / adapter 扩展点。
|
|
519
|
+
|
|
520
|
+
### 11.5 Phase 5:测试与文档同步
|
|
521
|
+
|
|
522
|
+
第五阶段目标:
|
|
523
|
+
|
|
524
|
+
- 按新边界收口测试
|
|
525
|
+
- 修正 README / help / 版本同步问题
|
|
526
|
+
- 确认命令行为和公共契约未回归
|
|
527
|
+
|
|
528
|
+
这是收尾阶段,不应被当成可后置省略项。
|
|
529
|
+
|
|
530
|
+
## 12. 关键流程时序
|
|
531
|
+
|
|
532
|
+
### 12.1 顶层 CLI 启动到 command registry dispatch
|
|
533
|
+
|
|
534
|
+
```text
|
|
535
|
+
argv
|
|
536
|
+
-> cli.ts bootstrap
|
|
537
|
+
-> commands.parseArgs
|
|
538
|
+
-> commands.resolveCommandDefinition
|
|
539
|
+
-> commands.dispatch
|
|
540
|
+
-> handler
|
|
541
|
+
-> application use case
|
|
542
|
+
-> output render
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
要求:
|
|
546
|
+
|
|
547
|
+
- 顶层入口不再自行维护命令知识
|
|
548
|
+
- dispatch 以 registry 为单一事实源
|
|
549
|
+
|
|
550
|
+
### 12.2 带交互的写命令:解析到“已决输入”再进入 application
|
|
551
|
+
|
|
552
|
+
```text
|
|
553
|
+
argv
|
|
554
|
+
-> parse command surface
|
|
555
|
+
-> handler checks TTY / --json
|
|
556
|
+
-> interaction resolver collects missing inputs / confirmations
|
|
557
|
+
-> resolved command input
|
|
558
|
+
-> application use case
|
|
559
|
+
-> storage + runtime mutation
|
|
560
|
+
-> result
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
关键点:
|
|
564
|
+
|
|
565
|
+
- 交互发生在 application 之前
|
|
566
|
+
- application 看见的始终是显式参数,而不是 prompt 分支
|
|
567
|
+
|
|
568
|
+
### 12.3 `switch` 的 storage + runtime 事务链路
|
|
569
|
+
|
|
570
|
+
```text
|
|
571
|
+
switch command
|
|
572
|
+
-> resolve provider
|
|
573
|
+
-> application/switch-provider
|
|
574
|
+
-> storage acquire lock
|
|
575
|
+
-> storage create backup
|
|
576
|
+
-> storage update active profile in config.toml
|
|
577
|
+
-> runtime refresh codex auth/login when enabled
|
|
578
|
+
-> success result
|
|
579
|
+
-> on failure rollback config/auth from backup
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
关键约束:
|
|
583
|
+
|
|
584
|
+
- runtime 失败不能污染核心状态
|
|
585
|
+
- rollback 仍由应用层事务编排触发
|
|
586
|
+
|
|
587
|
+
### 12.4 `setup` 的目录发现、策略选择、adopt 输入采集与写入边界
|
|
588
|
+
|
|
589
|
+
```text
|
|
590
|
+
setup command
|
|
591
|
+
-> runtime/storage path candidate discovery
|
|
592
|
+
-> interaction choose directory when needed
|
|
593
|
+
-> read config + providers state
|
|
594
|
+
-> interaction choose strategy and adopt inputs
|
|
595
|
+
-> application/setup-codex
|
|
596
|
+
-> storage mutation under backup
|
|
597
|
+
-> doctor/status style summary output
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
关键边界:
|
|
601
|
+
|
|
602
|
+
- 候选目录选择属于 interaction
|
|
603
|
+
- adopt 规则判断属于 application + domain
|
|
604
|
+
- 真实写入仍由 storage 执行
|
|
605
|
+
|
|
606
|
+
### 12.5 integration-ready 场景:dependency probe / auth adapter 不可用
|
|
607
|
+
|
|
608
|
+
```text
|
|
609
|
+
future integration command or switch extension
|
|
610
|
+
-> handler / application requests runtime probe
|
|
611
|
+
-> runtime dependency probe fails
|
|
612
|
+
-> runtime-layer error normalization
|
|
613
|
+
-> command fails before core mutation
|
|
614
|
+
-> providers/config/auth state unchanged
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
要求:
|
|
618
|
+
|
|
619
|
+
- 失败归因停留在 runtime 层
|
|
620
|
+
- 不把“外部依赖不可用”污染成 provider/config 领域错误
|
|
621
|
+
|
|
622
|
+
## 13. 测试设计
|
|
623
|
+
|
|
624
|
+
### 13.1 总体原则
|
|
625
|
+
|
|
626
|
+
测试继续采用当前 plain Node specs 模式:
|
|
627
|
+
|
|
628
|
+
- 不引入 Jest / Vitest
|
|
629
|
+
- 保留现有 domain / app / cli / dev-sandbox / e2e 五层思路
|
|
630
|
+
- 新测试覆盖围绕 command surface、interaction、runtime 三条新增设计关注点补强
|
|
631
|
+
|
|
632
|
+
### 13.2 Command Surface 覆盖
|
|
633
|
+
|
|
634
|
+
最少覆盖:
|
|
635
|
+
|
|
636
|
+
- 多 token 命令解析:`config show`、`config list-profiles`、`backups list`
|
|
637
|
+
- help topic 到内部 `CommandId` 的映射
|
|
638
|
+
- command registry dispatch
|
|
639
|
+
- `--json` 与 TTY gating
|
|
640
|
+
- version / help / unknown command 的统一入口行为
|
|
641
|
+
|
|
642
|
+
### 13.3 Interaction 覆盖
|
|
643
|
+
|
|
644
|
+
最少覆盖:
|
|
645
|
+
|
|
646
|
+
- 取消 prompt
|
|
647
|
+
- 危险确认拒绝
|
|
648
|
+
- `setup` 多候选目录
|
|
649
|
+
- `add` / `edit` 的渐进式输入补问
|
|
650
|
+
- provider 选择与 rollback 确认
|
|
651
|
+
|
|
652
|
+
### 13.4 Runtime 覆盖
|
|
653
|
+
|
|
654
|
+
最少覆盖:
|
|
655
|
+
|
|
656
|
+
- `codex` CLI 不可用
|
|
657
|
+
- 版本不兼容
|
|
658
|
+
- 未来依赖探测失败的错误归类
|
|
659
|
+
- runtime 失败时不污染 provider/config 核心状态
|
|
660
|
+
|
|
661
|
+
### 13.5 现有主路径回归
|
|
662
|
+
|
|
663
|
+
继续保持 e2e 针对以下路径的真实回归:
|
|
664
|
+
|
|
665
|
+
- `switch`
|
|
666
|
+
- `rollback`
|
|
667
|
+
- `add` / `edit` / `remove`
|
|
668
|
+
- `import` / `export`
|
|
669
|
+
- `config show`
|
|
670
|
+
- `doctor`
|
|
671
|
+
|
|
672
|
+
重点不是补更多命令名,而是证明重构后当前主路径没有回归。
|
|
673
|
+
|
|
674
|
+
## 14. Deferred 到 `0.1.0`
|
|
675
|
+
|
|
676
|
+
下面这些内容明确 deferred,不混入 `0.0.6`:
|
|
677
|
+
|
|
678
|
+
- 真实 Copilot / 第三方 auth 登录流程
|
|
679
|
+
- 本地 proxy 用户命令和生命周期管理
|
|
680
|
+
- 具体 SDK 安装、下载、引导体验
|
|
681
|
+
- 更大的 integration 命令面
|
|
682
|
+
|
|
683
|
+
`0.0.6` 只接受“把边界设计清楚”,不接受“先把未来功能半做进去”。
|
|
684
|
+
|
|
685
|
+
## 15. 验收标准
|
|
686
|
+
|
|
687
|
+
`0.0.6` 设计落地后,至少应满足:
|
|
688
|
+
|
|
689
|
+
- 当前 help 文案与命令行为、参数和危险提示基本一致
|
|
690
|
+
- 现有命令在 TTY / 非交互 / `--json` 模式下行为稳定
|
|
691
|
+
- `src/cli.ts` 不再承担持续膨胀的主调度与交互编排复杂度
|
|
692
|
+
- command surface、interaction、application、storage、runtime 的职责边界比 `0.0.5` 清晰
|
|
693
|
+
- 公开 token 与内部 `CommandId` 的映射被正式收口为单一 registry
|
|
694
|
+
- 写命令继续满足锁、备份、失败回滚语义
|
|
695
|
+
- 读取命令对历史状态和异常状态的处理更稳
|
|
696
|
+
- 为未来第三方 auth / proxy / SDK 接入预留了清楚但非侵入式的 integration-ready 边界
|
|
697
|
+
|
|
698
|
+
验收维度同时包含三类:
|
|
699
|
+
|
|
700
|
+
- 稳定性:当前命令不回归
|
|
701
|
+
- 分层完成度:核心职责边界明确且可迁移
|
|
702
|
+
- integration-ready:未来外部能力有独立 runtime 契约,不反向污染 CLI 与领域层
|
|
703
|
+
|
|
704
|
+
## 16. 结论
|
|
705
|
+
|
|
706
|
+
`0.0.6` 的本质,是把 `codex-switch` 从“命令已基本成形但入口和职责正在持续膨胀”的状态,推进到“公共契约冻结、现有能力稳定、内部边界清晰、可继续承接 integration-ready 演进”的下一阶段。
|
|
707
|
+
|
|
708
|
+
这一步不要求立刻交付 Copilot、proxy 或 SDK 功能;它要求的是,在不破坏当前 CLI 用户面和事务安全模型的前提下,把结构调整到足以支撑下一阶段演进的状态。
|