@minniexcode/codex-switch 0.0.9 → 0.0.11

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.
Files changed (51) hide show
  1. package/README.AI.md +52 -13
  2. package/README.CN.md +94 -39
  3. package/README.md +75 -33
  4. package/dist/app/add-provider.js +29 -26
  5. package/dist/app/bridge.js +15 -15
  6. package/dist/app/edit-provider.js +2 -18
  7. package/dist/app/get-status.js +35 -13
  8. package/dist/app/import-providers.js +1 -1
  9. package/dist/app/init-codex.js +13 -14
  10. package/dist/app/list-providers.js +0 -1
  11. package/dist/app/remove-provider.js +1 -1
  12. package/dist/app/run-doctor.js +21 -39
  13. package/dist/app/run-mutation.js +3 -2
  14. package/dist/app/setup-codex.js +30 -18
  15. package/dist/app/show-config.js +1 -5
  16. package/dist/app/switch-provider.js +16 -33
  17. package/dist/cli/output.js +4 -6
  18. package/dist/cli.js +35 -3
  19. package/dist/commands/args.js +2 -2
  20. package/dist/commands/dispatch.js +40 -0
  21. package/dist/commands/handlers.js +202 -84
  22. package/dist/commands/help.js +2 -0
  23. package/dist/commands/registry.js +33 -12
  24. package/dist/domain/backups.js +4 -4
  25. package/dist/domain/config.js +102 -61
  26. package/dist/domain/providers.js +12 -5
  27. package/dist/domain/runtime-state.js +81 -4
  28. package/dist/domain/setup.js +58 -3
  29. package/dist/interaction/add-interactive.js +55 -1
  30. package/dist/interaction/interactive.js +1 -5
  31. package/dist/runtime/copilot-adapter.js +56 -13
  32. package/dist/runtime/copilot-bridge.js +392 -44
  33. package/dist/runtime/copilot-cli.js +142 -0
  34. package/dist/runtime/copilot-installer.js +59 -11
  35. package/dist/runtime/copilot-sdk-loader.js +5 -5
  36. package/dist/storage/auth-repo.js +28 -77
  37. package/dist/storage/backup-repo.js +4 -4
  38. package/dist/storage/codex-paths.js +34 -8
  39. package/dist/storage/config-repo.js +1 -36
  40. package/dist/storage/lock-repo.js +2 -4
  41. package/dist/storage/runtime-state-repo.js +43 -10
  42. package/dist/storage/tool-config-repo.js +111 -0
  43. package/docs/Design/codex-switch-copilot-integration-design.md +517 -0
  44. package/docs/Design/codex-switch-v0.0.10-design.md +669 -0
  45. package/docs/Design/codex-switch-v0.0.11-design.md +824 -0
  46. package/docs/PRD/codex-switch-prd-v0.0.10.md +406 -0
  47. package/docs/PRD/codex-switch-prd-v0.0.11.md +577 -0
  48. package/docs/cli-usage.md +166 -271
  49. package/docs/codex-switch-product-overview.md +2 -2
  50. package/docs/codex-switch-technical-architecture.md +6 -5
  51. package/package.json +1 -1
@@ -0,0 +1,517 @@
1
+ # codex-switch Copilot 接入设计文档
2
+
3
+ ## 文档信息
4
+
5
+ - 文档类型:专项详细设计文档
6
+ - 主题:GitHub Copilot runtime-backed provider integration
7
+ - 适用范围:`0.0.8` 引入后的历史欠账收口与当前实现补齐
8
+ - 目标:把 Copilot 接入补成“首次接入可完成、切换可运行、诊断可解释、文档与代码一致”
9
+ - 关联 PRD:
10
+ - [`../PRD/codex-switch-prd-v0.0.8.md`](../PRD/codex-switch-prd-v0.0.8.md)
11
+ - [`../PRD/codex-switch-prd-v0.0.10.md`](../PRD/codex-switch-prd-v0.0.10.md)
12
+ - 关联历史设计:
13
+ - [`./codex-switch-v0.0.8-design.md`](./codex-switch-v0.0.8-design.md)
14
+ - [`./codex-switch-v0.0.9-design.md`](./codex-switch-v0.0.9-design.md)
15
+
16
+ ## 1. 文档目标
17
+
18
+ 本设计只回答 Copilot 接入这条线上的关键实现问题,并以“实现者无需再补关键决策”为目标,重点收口以下内容:
19
+
20
+ - `add --copilot` 到底要收集哪些输入,哪些字段必须与 direct provider 分开
21
+ - 缺失 SDK 时,何时安装、谁负责安装、安装失败如何报错
22
+ - 缺失 Copilot 登录态时,CLI 是只报错,还是要做交互式引导
23
+ - `switch` 进入 Copilot provider 时,哪些 gate 必须先通过,哪些文件才允许落盘
24
+ - `providers.json`、`config.toml`、`auth.json`、runtime state 各自负责什么,不负责什么
25
+ - `status` / `doctor` 对 Copilot 的诊断边界是什么
26
+ - 测试必须覆盖哪些首次接入和运行态回归场景
27
+
28
+ 本设计不扩展成“通用插件系统设计”或“多 runtime family 设计”。当前只围绕 GitHub Copilot 这一条 runtime-backed provider 路径。
29
+
30
+ ## 2. 当前问题与设计结论
31
+
32
+ ### 2.1 当前问题
33
+
34
+ 仓库当前已经具备以下能力:
35
+
36
+ - `providers.json` 中可保存 `runtime.kind = "copilot-sdk-bridge"` 的 provider
37
+ - `switch` 到 Copilot provider 时会做 SDK probe、Copilot auth probe、bridge 启动与 healthcheck
38
+ - `bridge start|status|stop` 已存在,且具备单实例复用/替换逻辑
39
+ - `status` / `doctor` 已具备一定的 Copilot SDK、auth、bridge 诊断能力
40
+
41
+ 但首次接入路径仍不完整:
42
+
43
+ 1. `add --copilot` 仍然复用了 direct provider 的 interactive add 流程。
44
+ 2. 该流程会把 `API key` 当成必填项,与 Copilot provider 的语义冲突。
45
+ 3. TTY 下同意安装 SDK 后,没有继续进入 Copilot auth readiness 检查与引导。
46
+ 4. 文档中仍有部分旧说法,把 `auth.json` 写成只读检查,或把 Copilot 路径说成“不涉及 auth.json / key 同步”,与当前 direct provider 行为和 Copilot 文件边界表达不一致。
47
+
48
+ ### 2.2 设计结论
49
+
50
+ 本设计固定以下结论:
51
+
52
+ 1. Copilot 接入继续走最小命令面,不新增完整 `copilot` 顶层命令族。
53
+ 2. `add --copilot` 是唯一的 Copilot provider 创建入口,并且必须成为“首次接入闭环”的起点。
54
+ 3. `add --copilot` 的交互输入模型必须与 direct provider 分开,不能再复用 `apiKey` 必填逻辑。
55
+ 4. CLI 负责引导式登录,不负责托管式登录。
56
+ 5. Copilot upstream 登录态只由官方 SDK / 官方工具管理,不写入 managed provider files。
57
+ 6. `switch` 继续是 Copilot runtime gate 的最终权威入口,但 `add --copilot` 也必须在 provider 落盘前确认 SDK 与 auth 已就绪。
58
+
59
+ ## 3. 范围与非范围
60
+
61
+ ### 3.1 In Scope
62
+
63
+ - `add --copilot` 的完整交互与非交互行为
64
+ - SDK lazy install 的命令级接入
65
+ - Copilot auth readiness 检查与交互式引导
66
+ - `switch` 的 Copilot runtime gate 收口
67
+ - Copilot provider 的文件边界和配置投影
68
+ - `status` / `doctor` 的 Copilot 字段与语义收口
69
+ - 与上述行为直接相关的测试与文档一致性修正
70
+
71
+ ### 3.2 Out of Scope
72
+
73
+ - 新增完整 `copilot` 顶层命令族
74
+ - 托管 GitHub token 或 Copilot token
75
+ - 新增后台守护进程产品模型
76
+ - 多实例 managed Copilot bridge 编排
77
+ - 非 Copilot runtime family 的抽象扩展
78
+ - Responses API、Embeddings、图像/音频接口
79
+
80
+ ## 4. 数据边界
81
+
82
+ ### 4.1 `providers.json`
83
+
84
+ `providers.json` 是 Copilot provider 的管理态 SSOT,负责保存:
85
+
86
+ - provider 名称
87
+ - profile 绑定
88
+ - 本地 bridge `apiKey`
89
+ - bridge `baseUrl`
90
+ - runtime 元数据:
91
+ - `kind = "copilot-sdk-bridge"`
92
+ - `upstream = "github-copilot"`
93
+ - `bridgeHost`
94
+ - `bridgePort`
95
+ - `bridgePath = "/v1"`
96
+ - `premiumRequests = true`
97
+ - `authSource = "official-sdk"`
98
+ - `sdkInstallMode = "lazy"`
99
+
100
+ 语义上,Copilot provider 的 `apiKey` 只是本地 bridge shared secret,不是 GitHub token,不是 Copilot upstream 登录凭据。
101
+
102
+ ### 4.2 `config.toml`
103
+
104
+ `config.toml` 是运行态路由投影,负责保存:
105
+
106
+ - 当前 active profile
107
+ - `model_providers.<profile>.base_url`
108
+ - 该 profile 对应的 managed runtime routing
109
+
110
+ 对于 Copilot provider,`base_url` 必须始终投影为 `http://<bridgeHost>:<bridgePort>/v1`。
111
+
112
+ ### 4.3 `auth.json`
113
+
114
+ `auth.json` 的角色必须中性表达:
115
+
116
+ - 对 direct provider:`switch` 会把 `auth_mode = "apikey"` 与 `OPENAI_API_KEY` 写入其中
117
+ - 对 Copilot provider:Copilot upstream 登录态不存这里,bridge secret 也不要求持久化为 GitHub token 形态
118
+ - `status` / `doctor` 只把它当作本地 auth state 文件做存在性、可解析性和元数据检查
119
+
120
+ 本设计明确否定以下旧说法:
121
+
122
+ - `auth.json` 是 Copilot upstream 登录态持久化位置
123
+ - `auth.json` 是所有 provider 的统一 secret mirror
124
+ - Copilot provider 需要向 `auth.json` 写入 GitHub/Copilot token
125
+
126
+ ### 4.4 Runtime State
127
+
128
+ Copilot bridge runtime state 是本地运行态文件,负责保存:
129
+
130
+ - 当前运行中的 provider 名称
131
+ - bridge host / port / base URL
132
+ - 进程状态检查所需的最小元数据
133
+
134
+ 它不属于 managed backup 的强事务边界。
135
+
136
+ ## 5. Copilot Provider Contract
137
+
138
+ ### 5.1 CLI 入口
139
+
140
+ 唯一稳定入口:
141
+
142
+ ```bash
143
+ codexs add <provider> --copilot --profile <name> [--bridge-host <host>] [--bridge-port <port>] [--bridge-api-key <secret>] [--install-copilot-sdk]
144
+ ```
145
+
146
+ ### 5.2 参数语义
147
+
148
+ - `--copilot`
149
+ - 切换到 Copilot provider 模式
150
+ - 与 direct provider 输入模型互斥
151
+ - `--profile`
152
+ - 必填
153
+ - `--api-key`
154
+ - 在 `--copilot` 下明确禁止
155
+ - `--bridge-api-key`
156
+ - 可选
157
+ - 若缺失则自动生成随机本地 secret
158
+ - `--bridge-host`
159
+ - 可选
160
+ - 默认 `127.0.0.1`
161
+ - `--bridge-port`
162
+ - 可选
163
+ - 默认 `41415`
164
+ - 必须为正整数
165
+ - `--install-copilot-sdk`
166
+ - 仅允许在 `add --copilot` 下显式使用
167
+ - 代表非交互安装许可,或 TTY 中跳过二次确认的显式授权
168
+
169
+ ### 5.3 输入模型
170
+
171
+ Copilot add 输入对象与 direct add 输入对象必须拆分:
172
+
173
+ ```ts
174
+ type DirectAddInput = {
175
+ providerName: string;
176
+ profile: string;
177
+ apiKey: string;
178
+ createProfile: boolean;
179
+ model?: string | null;
180
+ baseUrl?: string | null;
181
+ note?: string | null;
182
+ tags: string[];
183
+ };
184
+
185
+ type CopilotAddInput = {
186
+ providerName: string;
187
+ profile: string;
188
+ createProfile: boolean;
189
+ model?: string | null;
190
+ note?: string | null;
191
+ tags: string[];
192
+ bridgeHost?: string | null;
193
+ bridgePort?: number | null;
194
+ bridgeApiKey?: string | null;
195
+ };
196
+ ```
197
+
198
+ Copilot 输入模型里不允许出现 `apiKey: string` 这个“provider secret 必填字段”。
199
+
200
+ ## 6. `add --copilot` 详细设计
201
+
202
+ ### 6.1 总体目标
203
+
204
+ `add --copilot` 必须从“只建记录”升级为“首次接入闭环前置检查入口”。
205
+
206
+ 它的成功含义是:
207
+
208
+ 1. provider 配置有效;
209
+ 2. SDK 已可用;
210
+ 3. Copilot upstream auth 已就绪;
211
+ 4. managed files 已落盘为可切换状态。
212
+
213
+ 它的失败必须尽量发生在 managed file mutation 之前。
214
+
215
+ ### 6.2 非交互行为
216
+
217
+ 非交互或 `--json` 下:
218
+
219
+ - 缺少 `<provider>` 或 `--profile` 时,直接失败
220
+ - 不提示交互问题
221
+ - 若 SDK 缺失且未显式传 `--install-copilot-sdk`,返回 `COPILOT_SDK_INSTALL_REQUIRES_TTY`
222
+ - 若 SDK 安装后 auth 未就绪,返回 `COPILOT_AUTH_REQUIRED`
223
+
224
+ 非交互不会尝试 prompt-based login guidance。
225
+
226
+ ### 6.3 交互行为
227
+
228
+ TTY 下 `add --copilot` 的推荐时序固定为:
229
+
230
+ 1. 解析命令行已有参数
231
+ 2. 检查 Copilot SDK runtime 是否存在
232
+ 3. 若 SDK 缺失:
233
+ - 弹出确认:`The optional Copilot SDK runtime is not installed. Install it now?`
234
+ - 用户确认后立即安装
235
+ - 输出状态行:`Installing Copilot SDK runtime...` / `Copilot SDK runtime installed.`
236
+ 4. 立即 probe Copilot auth readiness
237
+ 5. 若 auth 缺失:
238
+ - 输出状态行:`GitHub Copilot login is required. Starting official copilot login...`
239
+ - 直接在当前终端调用官方 `copilot login`
240
+ - GitHub 的 browser/device-code 体验完全委托给官方 CLI
241
+ 6. 若 `copilot login` 无法启动或退出非零:
242
+ - 输出人工兜底指引,明确手动命令为 `copilot login`
243
+ - 说明 GitHub 官方流程会打开浏览器或显示 verification URL/code
244
+ - 仅提供一次明确的 recheck 路径
245
+ 7. auth readiness 通过后,才进入 Copilot 专用 add prompt
246
+ 8. prompt 完成后,调用 app 层完成 provider 写入与 config projection
247
+
248
+ ### 6.4 Copilot 专用交互采集项
249
+
250
+ Copilot add prompt 至少覆盖:
251
+
252
+ - `Provider name`
253
+ - `Profile`
254
+ - `Model for new profile "<profile>"`,仅当 profile 不存在且需要 create profile 时
255
+ - `Note (optional)`
256
+ - `Tags (optional)`
257
+ - `Bridge host (optional)`,默认值 `127.0.0.1`
258
+ - `Bridge port (optional)`,默认值 `41415`
259
+ - `Bridge API key (optional)`,留空则自动生成
260
+
261
+ 明确禁止:
262
+
263
+ - 提示 `API key`
264
+ - 提示 `Confirm API key`
265
+ - 输出 `API key is required.`
266
+
267
+ ### 6.5 SDK 安装职责
268
+
269
+ 命令层负责 Copilot 首次接入的安装 preflight:
270
+
271
+ - 在 `add --copilot` 路径中,先决定是否允许安装
272
+ - 若允许且当前未安装,则先执行 `installCopilotSdk()`
273
+ - app 层 `addProvider()` 保留二次校验,防止被非 CLI 路径绕过
274
+
275
+ 这样做的原因是:
276
+
277
+ - 命令层能处理 TTY 提示和用户确认
278
+ - app 层仍保留安全兜底,不把安装状态完全信任给调用者
279
+
280
+ ### 6.6 Auth Guidance 职责
281
+
282
+ CLI 采用官方登录 handoff,不采用托管式登录:
283
+
284
+ - `codex-switch` 不写入 GitHub token
285
+ - `codex-switch` 不新增自己的 token storage
286
+ - `codex-switch` 不承诺替代官方登录工具
287
+
288
+ 但它必须负责:
289
+
290
+ - 检测 auth 是否 ready
291
+ - 在 TTY 下启动官方 `copilot login`
292
+ - 启动失败时解释“你现在缺的是 Copilot upstream 登录”,并给出手动命令
293
+ - 允许用户在官方流程完成后返回当前流程并执行一次显式 recheck
294
+
295
+ 标准失败码:
296
+
297
+ - `COPILOT_AUTH_REQUIRED`
298
+
299
+ 标准交互策略:
300
+
301
+ - 输出固定状态行而不是 spinner
302
+ - 默认路径是 run/login/recheck,不是无限 retry loop
303
+ - 用户拒绝 recheck 或 recheck 仍失败时返回 `COPILOT_AUTH_REQUIRED`
304
+
305
+ ### 6.7 文件写入时机
306
+
307
+ 只有以下条件全部满足后,才允许持久化 provider:
308
+
309
+ 1. 输入采集完成
310
+ 2. SDK 已安装或已可探测到
311
+ 3. Copilot auth readiness 通过
312
+
313
+ 持久化时:
314
+
315
+ - Copilot provider 的 `baseUrl` 使用 canonical bridge URL
316
+ - `apiKey` 写入 bridge shared secret
317
+ - 若 profile 不存在且允许 `createProfile`,同步创建 config projection
318
+
319
+ ## 7. `switch` 详细设计
320
+
321
+ ### 7.1 保持现有总体结构
322
+
323
+ `switch` 继续是 Copilot provider 的运行态 gate:
324
+
325
+ 1. 读取 provider
326
+ 2. 校验 runtime config
327
+ 3. probe SDK
328
+ 4. probe Copilot auth
329
+ 5. 启动或复用 bridge
330
+ 6. healthcheck 成功
331
+ 7. 写 managed files
332
+
333
+ ### 7.2 Copilot 与 Direct 的区别
334
+
335
+ direct provider:
336
+
337
+ - 切换 active profile
338
+ - 写 `auth.json.OPENAI_API_KEY`
339
+
340
+ Copilot provider:
341
+
342
+ - 切换 active profile
343
+ - 不写 `OPENAI_API_KEY`
344
+ - 维护 bridge runtime 与 `config.toml` 的 `base_url` 投影
345
+ - 若端口恢复导致实际端口变化,则回写 `providers.json` 与 `config.toml`
346
+
347
+ ### 7.3 失败与清理
348
+
349
+ 若 bridge 是本次新启动的,并且后续 managed file mutation 失败:
350
+
351
+ - 需要做 best-effort `stopCopilotBridge()`
352
+
353
+ 若 bridge 是复用旧健康实例:
354
+
355
+ - 不应因为后续文件写失败而误杀原有实例
356
+
357
+ ## 8. `status` / `doctor` 设计
358
+
359
+ ### 8.1 `status`
360
+
361
+ `status.data` 中 Copilot 相关字段保持以下事实语义:
362
+
363
+ - `copilotSdk`
364
+ - 是否已安装
365
+ - 安装目录
366
+ - 包名
367
+ - 版本
368
+ - `copilotAuth`
369
+ - 官方 SDK session 是否可创建
370
+ - source 固定为 `official-sdk`
371
+ - mode 固定为当前实现使用的 session mode
372
+ - `copilotBridge`
373
+ - 当前 bridge 是否健康
374
+ - 若不健康,失败原因是什么
375
+ - `copilotRuntimeState`
376
+ - 本地 bridge runtime state 的已知内容
377
+
378
+ `status` 不应把这些字段聚合成新的 `health.*` 大结构。
379
+
380
+ ### 8.2 `doctor`
381
+
382
+ `doctor` 对 Copilot 至少要诊断:
383
+
384
+ - `COPILOT_SDK_MISSING`
385
+ - `COPILOT_AUTH_REQUIRED`
386
+ - `BRIDGE_STATE_MISSING`
387
+ - `BRIDGE_STATE_STALE`
388
+ - `PROVIDER_BASE_URL_MISMATCH`
389
+ - `BRIDGE_HEALTHCHECK_FAILED`
390
+
391
+ `doctor` 继续以 `issues[]` 为主输出,不新增第二套并行诊断结构。
392
+
393
+ ### 8.3 诊断边界
394
+
395
+ Copilot 诊断必须清楚区分三个层次:
396
+
397
+ 1. SDK 是否安装
398
+ 2. upstream auth 是否 ready
399
+ 3. local bridge 是否健康
400
+
401
+ 这三层不能混为一种错误。
402
+
403
+ ## 9. 错误模型
404
+
405
+ 本设计固定使用或继续沿用以下错误码:
406
+
407
+ - `INVALID_ARGUMENT`
408
+ - `PROMPT_CANCELLED`
409
+ - `COPILOT_SDK_MISSING`
410
+ - `COPILOT_SDK_INSTALL_FAILED`
411
+ - `COPILOT_SDK_INSTALL_REQUIRES_TTY`
412
+ - `COPILOT_SDK_UNSUPPORTED`
413
+ - `COPILOT_AUTH_REQUIRED`
414
+ - `BRIDGE_PORT_CONFLICT`
415
+ - `BRIDGE_START_FAILED`
416
+ - `BRIDGE_HEALTHCHECK_FAILED`
417
+ - `BRIDGE_STATE_MISSING`
418
+ - `BRIDGE_STATE_STALE`
419
+ - `RUNTIME_PROVIDER_INVALID`
420
+ - `PROVIDER_BASE_URL_MISMATCH`
421
+
422
+ 重点约束:
423
+
424
+ - `COPILOT_AUTH_REQUIRED` 只能表示 upstream auth readiness 不满足
425
+ - 不能拿它表达 SDK 缺失
426
+ - 不能拿它表达 bridge 健康失败
427
+
428
+ ## 10. 代码落点
429
+
430
+ ### 10.1 `src/commands/handlers.ts`
431
+
432
+ 负责:
433
+
434
+ - `add --copilot` 的 CLI 参数约束
435
+ - 交互与非交互分支
436
+ - SDK install preflight
437
+ - auth guidance retry loop
438
+
439
+ ### 10.2 `src/interaction/add-interactive.ts`
440
+
441
+ 负责:
442
+
443
+ - direct add 输入收集
444
+ - Copilot add 输入收集
445
+ - 二者的 UI 文案和必填规则分离
446
+
447
+ ### 10.3 `src/app/add-provider.ts`
448
+
449
+ 负责:
450
+
451
+ - provider record 生成
452
+ - config projection 生成
453
+ - Copilot runtime metadata 归一化
454
+ - SDK 已安装前提下的安全持久化
455
+
456
+ ### 10.4 `src/runtime/*`
457
+
458
+ 负责:
459
+
460
+ - SDK 探测与安装
461
+ - auth readiness probe
462
+ - bridge start / stop / status / healthcheck
463
+
464
+ ## 11. 测试要求
465
+
466
+ ### 11.1 交互测试
467
+
468
+ 必须覆盖:
469
+
470
+ - Copilot add prompt 不再要求 direct API key
471
+ - Copilot add prompt 能采集 bridge host / port / bridge API key
472
+ - Copilot 非交互错误文案与 direct provider 区分
473
+
474
+ ### 11.2 命令测试
475
+
476
+ 必须覆盖:
477
+
478
+ - `add --copilot` 在 SDK 缺失且用户允许安装时,先安装再继续
479
+ - `add --copilot` 在 auth 缺失时进入引导式 retry loop
480
+ - `add --copilot --json` 在 auth 缺失时直接失败,不 prompt
481
+
482
+ ### 11.3 工作流测试
483
+
484
+ 必须覆盖:
485
+
486
+ - `addProvider()` 创建 Copilot provider 后,record 结构正确
487
+ - `switchProvider()` 到 Copilot provider 时启动或复用 bridge
488
+ - Copilot `switch` 不写 `OPENAI_API_KEY`
489
+ - bridge 端口恢复后会回写 provider/config projection
490
+ - 写文件失败时,新启动 bridge 会被清理
491
+
492
+ ### 11.4 文档一致性测试
493
+
494
+ 发布前人工检查至少覆盖:
495
+
496
+ - README
497
+ - README.AI
498
+ - README.CN
499
+ - `docs/cli-usage.md`
500
+ - 产品概览 / 技术架构中与 Copilot 相关的说明
501
+
502
+ 确保不再出现以下冲突:
503
+
504
+ - 把 `auth.json` 说成 Copilot upstream token 存储
505
+ - 把 `auth.json` 写成完全只读且与 direct switch 行为冲突
506
+ - 把 `add --copilot` 描述成还需要 direct provider API key
507
+
508
+ ## 12. 发布完成标准
509
+
510
+ Copilot 接入可以视为“设计与实现完整”的最低标准是:
511
+
512
+ 1. `add --copilot` 在 TTY 下可完成首次接入,不会误要求 direct API key。
513
+ 2. 缺 SDK 时能按许可安装。
514
+ 3. 缺 auth 时能给出可执行的登录引导与 retry。
515
+ 4. `switch` 到 Copilot provider 时能稳定完成 runtime gate。
516
+ 5. `status` / `doctor` 能把 SDK、auth、bridge 三层问题清楚区分。
517
+ 6. 文档对 Copilot 的文件边界和行为边界与代码一致。