@chatcode/cco-llm-chatcode-config 0.1.0

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 (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +124 -0
  3. package/README.zh.md +133 -0
  4. package/cordis.patch.yml +4 -0
  5. package/cordis.web.patch.yml +12 -0
  6. package/docs/chatcode-login.md +88 -0
  7. package/docs/chatcode-login.zh.md +179 -0
  8. package/docs/chatcode-models.md +29 -0
  9. package/docs/chatcode-models.zh.md +29 -0
  10. package/docs/chatcode-reporting.md +96 -0
  11. package/docs/chatcode-reporting.zh.md +96 -0
  12. package/docs/decisions/2026-08-31-chatcode-model-source.md +39 -0
  13. package/docs/decisions/2026-08-31-chatcode-model-source.zh.md +39 -0
  14. package/docs/decisions/2026-09-16-actual-model-adapter-routing.md +31 -0
  15. package/docs/decisions/2026-09-16-actual-model-adapter-routing.zh.md +31 -0
  16. package/lib/client.js +469 -0
  17. package/lib/index.d.ts +263 -0
  18. package/lib/index.d.ts.map +1 -0
  19. package/lib/index.js +4873 -0
  20. package/lib/index.js.map +1 -0
  21. package/lib/startup-gate-BaCbWaKH.js +164 -0
  22. package/lib/startup-gate-BaCbWaKH.js.map +1 -0
  23. package/lib/web-startup.d.ts +9 -0
  24. package/lib/web-startup.d.ts.map +1 -0
  25. package/lib/web-startup.js +20 -0
  26. package/lib/web-startup.js.map +1 -0
  27. package/package.json +121 -0
  28. package/vendor/README.md +7 -0
  29. package/vendor/dsh-llm-pi-ai/LICENSE +21 -0
  30. package/vendor/dsh-llm-pi-ai/README.i18n.yaml +6 -0
  31. package/vendor/dsh-llm-pi-ai/README.md +238 -0
  32. package/vendor/dsh-llm-pi-ai/README.zh.md +238 -0
  33. package/vendor/dsh-llm-pi-ai/package.json +65 -0
  34. package/vendor/dsh-llm-pi-ai/src/adapter.ts +434 -0
  35. package/vendor/dsh-llm-pi-ai/src/auth.ts +241 -0
  36. package/vendor/dsh-llm-pi-ai/src/catalog.ts +908 -0
  37. package/vendor/dsh-llm-pi-ai/src/config.ts +478 -0
  38. package/vendor/dsh-llm-pi-ai/src/context.ts +349 -0
  39. package/vendor/dsh-llm-pi-ai/src/discovery.ts +284 -0
  40. package/vendor/dsh-llm-pi-ai/src/index.ts +336 -0
  41. package/vendor/dsh-llm-pi-ai/src/invariant.ts +30 -0
  42. package/vendor/dsh-llm-pi-ai/src/login.ts +161 -0
  43. package/vendor/dsh-llm-pi-ai/src/provider.ts +192 -0
  44. package/vendor/dsh-llm-pi-ai/src/replay.ts +249 -0
  45. package/vendor/dsh-llm-pi-ai/src/stream.ts +232 -0
  46. package/vendor/dsh-llm-pi-ai/tests/adapter.e2e.ts +168 -0
  47. package/vendor/dsh-llm-pi-ai/tests/adapter.spec.ts +1034 -0
  48. package/vendor/dsh-llm-pi-ai/tests/assemble.ts +32 -0
  49. package/vendor/dsh-llm-pi-ai/tests/auth-double.ts +39 -0
  50. package/vendor/dsh-llm-pi-ai/tests/auth.spec.ts +221 -0
  51. package/vendor/dsh-llm-pi-ai/tests/catalog.spec.ts +1220 -0
  52. package/vendor/dsh-llm-pi-ai/tests/config.spec.ts +111 -0
  53. package/vendor/dsh-llm-pi-ai/tests/context.spec.ts +474 -0
  54. package/vendor/dsh-llm-pi-ai/tests/convert.spec.ts +922 -0
  55. package/vendor/dsh-llm-pi-ai/tests/discovery.spec.ts +374 -0
  56. package/vendor/dsh-llm-pi-ai/tests/dynamic-config.spec.ts +241 -0
  57. package/vendor/dsh-llm-pi-ai/tests/fixtures/qr-code.png +0 -0
  58. package/vendor/dsh-llm-pi-ai/tests/loader-composition.spec.ts +244 -0
  59. package/vendor/dsh-llm-pi-ai/tests/login.spec.ts +198 -0
  60. package/vendor/dsh-llm-pi-ai/tests/mock-server.ts +82 -0
  61. package/vendor/dsh-llm-pi-ai/tests/provider-apis.e2e.ts +266 -0
  62. package/vendor/dsh-llm-pi-ai/tests/sdk-options.spec.ts +106 -0
  63. package/vendor/dsh-llm-pi-ai/tsconfig.json +4 -0
  64. package/vendor/dsh-llm-pi-ai/tsconfig.upstream.json +51 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DeepSeek
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.md ADDED
@@ -0,0 +1,124 @@
1
+ ---
2
+ description: "Provide ChatCode models, shared account access, and operations reporting in a ChatCode CLI profile."
3
+ kind: "package-bundle"
4
+ ---
5
+
6
+ # @chatcode/cco-llm-chatcode-config
7
+
8
+ English | [中文](README.zh.md)
9
+
10
+ ## Summary
11
+
12
+ This plugin publishes user-defined, CodingPlan, and optional MAAS model catalogs, provides shared ChatCode account access, and reports committed ChatCode CLI Session activity to ChatCode. User-defined models live in the `llm-chatcode-config` settings section and appear in the conversation model selector. Runtime model credentials stay in the Host process, while the account grant stays in ChatCode CLI credential storage and never reaches Web or TUI clients. Reporting is enabled by default and can be disabled with `reporting.enabled: false`.
13
+
14
+ ## Table of Contents
15
+
16
+ - [Use this package](#use-this-package)
17
+ - [Understand the implementation](#understand-the-implementation)
18
+ - [Further Exploration](#further-exploration)
19
+ - [Model Experience](#model-experience)
20
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
21
+
22
+ -----
23
+
24
+ <a id="use-this-package"></a>
25
+ ## Use this package
26
+
27
+ The sibling-checkout development environment mounts this plugin through the main ChatCode CLI launcher:
28
+
29
+ ```sh
30
+ cd /absolute/path/to/deepseek-harness
31
+ pnpm install
32
+ pnpm cco web
33
+ pnpm cco cli
34
+ ```
35
+
36
+ These source commands require no `chatcode-cli plugin --profile ... add ...`; their automatic patches do not modify profile manifests. Published profiles install the package with `chatcode-cli plugin --profile <name> add @chatcode/cco-llm-chatcode-config`. The Host uses the `CVP_CHATCODE_API_TOKEN` value retained from `yuanjing-wanma-cli` by default; `startupGate.token` in a private patch or `CHATCODE_CVP_CONFIG_TOKEN` in the Host environment overrides it. The independent CVP credential is never sent to Web or TUI clients. The local credential provider serializes updates to one ChatCode grant, so both clients see the same account at their next status query (normally about 2 seconds in Web). In Web, `DSH-better-sidebar` displays the sign-in/out entry. In the integrated CLI, the TUI checks launch availability before account sign-in and Agent/Session creation. `/login` shows the account later, while `/logout` removes its tokens and invalidates pending sign-ins. Published installations can use [`cordis.patch.yml`](cordis.patch.yml) for the Host service and additionally apply [`cordis.web.patch.yml`](cordis.web.patch.yml) to make Web startup depend on that service.
37
+
38
+ Each CLI launch reads `chatcode.cli.isEnabled` from the CVP system-config endpoint before account authentication. A disabled response reads `chatcode.cli.disabled.reason`; malformed responses, authentication failures, and network failures stop startup. TUI offers Retry and Exit. Web prints the corresponding admission message and exits with status 0 before listening or opening a browser. `CHATCODE_CLI_DEGRADE_STARTUP_GATE=1` or `CHATCODE_CLI_NEED_AUTH_YZQ=false` in the legacy `settingsPath` file bypasses this request; the legacy `WANMA_CLI_NEED_AUTH_YZQ=false` key also applies when the ChatCode key is absent. The bypass is evaluated at each launch, independently of `auth.requireLogin`. The default credential is embedded in Host source and can be read by anyone with access to the repository or published Host package.
39
+
40
+ The default browser URL is `https://chatcode.chinaunicom.cn/unicode/#/login?sessionId=…`. The generated `sessionId` is part of the hash-route query and the plugin polls the matching legacy session endpoint until the account completes login. Status queries validate the account; expired or revoked tokens attempt a refresh through the legacy `long/login` endpoint under the ChatCode CLI credential record lock. Temporary network failures preserve the grant and report unavailable verification.
41
+
42
+ See the [shared sign-in guide](docs/chatcode-login.md) ([中文](docs/chatcode-login.zh.md)) for operation and validation. Account sign-in does not replace custom-model API keys or ChatCode CLI's own browser access authentication.
43
+
44
+ When `reporting.enabled` is true and the profile provides the Session service, the same Host plugin saves generated code, synchronizes conversation records, and appends one token-bearing record per model response to ChatCode. Successful code mutations join the response that requested them; ordinary tools create no zero-token records. All requests use the shared ChatCode account. Code enters a durable local outbox before upload; conversation and ChatCode message failures do not change model, tool, or Session outcomes. See [ChatCode operations reporting](docs/chatcode-reporting.md) for transmitted fields, privacy limits, and failure behavior.
45
+
46
+ The `llm-chatcode-config` section in `$CHATCODE_CLI_HOME/settings.yaml` is the runtime source for user-defined models. When that section is absent, the plugin imports `customModels` once from `~/.chatcode-cli/settings.json` and persists the validated array in ChatCode CLI settings. To import another legacy file, put the path override in a separate patch and pass it as `pnpm cco web --patch ./chatcode.override.yml` (or the matching CLI command):
47
+
48
+ ```yaml
49
+ - id: llm-chatcode-config
50
+ config:
51
+ enableMaas: true
52
+ maasEndpoint: https://chatcode.chinaunicom.cn/cvp/wanma/api/v1/cli/maas-models
53
+ settingsPath: C:/path/to/settings.json
54
+ auth:
55
+ loginUrl: https://chatcode.chinaunicom.cn/unicode/#/login
56
+ apiBaseUrl: https://chatcode.chinaunicom.cn
57
+ cvpChatCodeApiUrl: https://chatcode.chinaunicom.cn/cvp
58
+ reporting:
59
+ enabled: true
60
+ codeSave: true
61
+ conversationSync: true
62
+ chatCodeSession: true
63
+ ```
64
+
65
+ MAAS has a different response shape from CodingPlan: the catalog returns model IDs, and the plugin resolves each ID through its private runtime endpoint. `codingPlanEndpoint` and `catalogTimeoutMs` override the CodingPlan address and catalog timeout.
66
+
67
+ The package also ships a browser client bundle. Its **Model configuration** card contains only the MAAS switch; it does not edit the `customModels` array or display CodingPlan and MAAS rows. Edit imported user-defined models in `$CHATCODE_CLI_HOME/settings.yaml`; valid file updates refresh the **自定义模型** conversation-selector group without restarting the Host.
68
+
69
+ -----
70
+
71
+ <a id="understand-the-implementation"></a>
72
+ ## Understand the implementation
73
+
74
+ <details>
75
+ <summary>Implementation internals — click to expand</summary>
76
+
77
+ [`src/managed.ts`](src/managed.ts) separates managed model metadata from request credentials and derives stable private connection routes. [`src/adapter.ts`](src/adapter.ts) exposes the public catalog and selects a request adapter from each route's actual model ID. IDs containing `deepseek`, case-insensitively, use `@deepseek-ai/dsh-llm-deepseek`; all other IDs use the modified pi-ai adapter in [`vendor/dsh-llm-pi-ai/`](vendor/dsh-llm-pi-ai/), whose reachable modules are bundled into `lib/index.js`.
78
+
79
+ DeepSeek routes use the entry protocol, base URL, and API key. Their OpenAI requests send `Authorization: Bearer`, while their Anthropic Messages requests send `x-api-key`. Non-DeepSeek Anthropic routes remain on pi-ai and send `Authorization: Bearer` without `x-api-key`. MiniMax M2 OpenAI requests carry `reasoning_split: true`. Provider-owned attribution headers remain reserved, and pi-ai uses an isolated in-memory credential store.
80
+
81
+ [`src/reporting/`](src/reporting/) projects committed Session events through per-Session queues into generated-code persistence, conversation synchronization, and the ChatCode message chain. The reporter reuses `ChatCodeAuthService`; it adds no client-visible service or second Cordis entry.
82
+
83
+ Managed OpenAI streaming requests explicitly send `Accept: text/event-stream`. This supports forwarding gateways that enforce content negotiation and prevents an HTTP 200 JSON business error from being misreported by the stream parser as a missing `finish_reason`.
84
+
85
+ </details>
86
+
87
+ -----
88
+
89
+ <a id="further-exploration"></a>
90
+ ## Further Exploration
91
+
92
+ - [`docs/chatcode-models.md`](docs/chatcode-models.md) describes the user workflow and source fields.
93
+ - [`docs/chatcode-reporting.md`](docs/chatcode-reporting.md) defines reporting fields, durability, and failure behavior.
94
+ - [`docs/decisions/2026-08-31-chatcode-model-source.md`](docs/decisions/2026-08-31-chatcode-model-source.md) records credential ownership and route identity.
95
+ - [`docs/decisions/2026-09-16-actual-model-adapter-routing.md`](docs/decisions/2026-09-16-actual-model-adapter-routing.md) records adapter selection and authentication consequences.
96
+ - [`vendor/README.md`](vendor/README.md) records the copied adapter source and update rule.
97
+
98
+ -----
99
+
100
+ <a id="model-experience"></a>
101
+ ## Model Experience
102
+
103
+ The model receives the normal ChatCode CLI system prompt, messages, and tools through the selected imported endpoint. CodingPlan entries appear under the `内置模型` group in both the Web selector and the CLI `/model` picker. Configuration paths, labels, and credentials do not enter model messages. The imported context capacity sizes the request context, and the imported output limit becomes the request default and ceiling. DeepSeek-named models expose the native DeepSeek reasoning choices; other imported models retain pi-ai capabilities.
104
+
105
+ ## Known Limitations and Deferred Work
106
+
107
+ <a id="known-limitations-and-deferred-work"></a>
108
+
109
+ - Managed catalog reads are activation snapshots; remount or restart after changing a central catalog. The MAAS switch refreshes its selector group immediately.
110
+ - Imported models declare text input. Non-DeepSeek routes do not expose selectable reasoning effort.
111
+ - One invalid entry, including a duplicate model ID, suppresses the complete imported catalog; the bundle does not publish a partially valid source.
112
+ - The public plugin client extension point adds this package's managed-model configuration card to the native Models page. The card controls MAAS only; user-defined model entries require a settings-file edit, while CodingPlan and MAAS groups remain read-only.
113
+ - The package tracks the copied pi-ai adapter source and the native DeepSeek adapter peer; upgrade either through an explicit compatibility test, and refresh `vendor/` when pi-ai changes.
114
+ - Conversation synchronization has no durable outbox, and ChatCode message requests are not retried when the server may have committed them.
115
+
116
+ <a id="dev-note"></a>
117
+ ### Dev Note
118
+
119
+ <details>
120
+ <summary>Working context for maintainers — click to expand</summary>
121
+
122
+ None.
123
+
124
+ </details>
package/README.zh.md ADDED
@@ -0,0 +1,133 @@
1
+ ---
2
+ description: "为 ChatCode CLI 提供 ChatCode 模型、共用账号访问和运营数据上报。"
3
+ kind: "package-bundle"
4
+ ---
5
+
6
+ # @chatcode/cco-llm-chatcode-config
7
+
8
+ [English](README.md) | 中文
9
+
10
+ ## 概述
11
+
12
+
13
+ 此插件发布用户自定义模型、CodingPlan 与可选 MAAS 模型目录,提供共用 ChatCode 账号访问,并向 ChatCode 上报已提交的 ChatCode CLI Session 活动。用户自定义模型保存在 `llm-chatcode-config` 设置段,并出现在会话模型选择器中。运行时模型凭据只保存在 Host 进程中,账号 grant 保存在 ChatCode CLI 凭据存储中且不会进入 Web 或 TUI 客户端。上报默认开启,可通过 `reporting.enabled: false` 关闭。
14
+
15
+ 启动时还会读取 Coding Plan 运行时模型接口,并在会话模型选择器中发布三个独立分组:`自定义模型`、`内置模型` 和(启用后)`Maas平台`。接口返回的 API Key 只保存在进程内的请求鉴权对象中;模型列表、日志和错误信息不会包含该值。
16
+
17
+
18
+ ## 目录
19
+
20
+ - [使用本包](#use-this-package)
21
+ - [理解实现](#understand-the-implementation)
22
+ - [进一步探索](#further-exploration)
23
+ - [模型体验](#model-experience)
24
+ - [已知限制与后续工作](#known-limitations-and-deferred-work)
25
+
26
+ -----
27
+
28
+ <a id="use-this-package"></a>
29
+ ## 使用本包
30
+
31
+ 当前兄弟目录形式的源码开发环境由 ChatCode CLI 主启动器自动挂载本插件:
32
+
33
+ ```text
34
+ cd /absolute/path/to/deepseek-harness
35
+ pnpm install
36
+ pnpm cco web
37
+ pnpm cco cli
38
+ ```
39
+
40
+ 无需为这两个源码命令执行 `chatcode-cli plugin --profile ... add ...`;自动 patch 不写入 profile 清单。发布 profile 使用 `chatcode-cli plugin --profile <name> add @chatcode/cco-llm-chatcode-config` 安装本包。Host 默认使用从 `yuanjing-wanma-cli` 保留的 `CVP_CHATCODE_API_TOKEN`;私有 patch 中的 `startupGate.token` 或 Host 环境变量 `CHATCODE_CVP_CONFIG_TOKEN` 可覆盖它。独立的 CVP 凭证不会发送给 Web 或 TUI 客户端。ChatCode CLI 本机凭据提供方会串行化同一个 ChatCode grant 的更新,因此两端在下次状态查询时会看到同一账号(Web 通常约 2 秒)。Web 端由 `DSH-better-sidebar` 显示登录/登出入口;TUI 在账号登录和 Agent/Session 创建之前先检查启动许可。`/login` 显示账号,`/logout` 清除本机令牌并使进行中的登录失效。发布安装可使用 [`cordis.patch.yml`](cordis.patch.yml) 挂载 Host 服务,并额外应用 [`cordis.web.patch.yml`](cordis.web.patch.yml) 使 Web 启动等待该服务。
41
+
42
+ 每次 CLI 启动都会在账号鉴权前从 CVP 系统配置接口读取 `chatcode.cli.isEnabled`。禁用时再读取 `chatcode.cli.disabled.reason`;响应无效、配置凭证错误和网络故障都会阻止启动。TUI 提供“重新检测”和“退出”。Web 输出对应的准入提示,以状态码 0 退出,且不会监听端口或打开浏览器。环境变量 `CHATCODE_CLI_DEGRADE_STARTUP_GATE=1` 或旧 `settingsPath` 文件中的 `CHATCODE_CLI_NEED_AUTH_YZQ=false` 会跳过请求;ChatCode 键不存在时也兼容旧键 `WANMA_CLI_NEED_AUTH_YZQ=false`。绕过条件每次启动时独立判断,不等同于 `auth.requireLogin`。默认凭证内置于 Host 源码,拥有仓库或已发布 Host 插件包访问权限的人可以读取它。
43
+
44
+ 默认浏览器地址为 `https://chatcode.chinaunicom.cn/unicode/#/login?sessionId=…`。插件会把每次生成的 `sessionId` 放在 hash 路由查询中,并轮询对应的遗留会话接口直到登录完成。状态查询会检查账号有效性;已过期或被服务端撤销的令牌,会在 ChatCode CLI 凭据记录锁内尝试经由遗留 `long/login` 接口刷新。短时网络故障保留凭据并显示待验证。
45
+
46
+ 完整安装、操作、限制与验收步骤见 [统一登录使用手册](docs/chatcode-login.zh.md)。账号登录不会替换用户自定义模型的 API key,也不替代 ChatCode CLI 浏览器自身的访问认证。
47
+
48
+ 当 `reporting.enabled` 为 true 且 profile 提供 Session 服务时,同一个 Host 插件会保存生成代码、同步会话记录,并按模型 response 向 ChatCode 追加带真实 Token 的记录。成功的代码修改会并入发起工具调用的 response,普通工具不会产生 0 Token 记录。所有请求共用 ChatCode 账号。代码在上传前进入持久化本地 outbox;会话与 ChatCode 消息上报失败不会改变模型、工具或 Session 结果。上传字段、隐私限制与失败行为见 [ChatCode 运营数据上报](docs/chatcode-reporting.zh.md)。
49
+
50
+ `$CHATCODE_CLI_HOME/settings.yaml` 中的 `llm-chatcode-config` 设置段是用户自定义模型的运行时来源。该设置段不存在时,插件会从 `~/.chatcode-cli/settings.json` 一次性导入 `customModels`,校验后写入 ChatCode CLI 设置。通过 `settingsPath` 可以指定其他旧配置文件;已有设置段(包括空数组)不会被旧文件覆盖。
51
+
52
+ ### 中央模型目录与 MAAS
53
+
54
+ 默认会在启动时以 GET 请求读取 `https://chatcode.chinaunicom.cn/cvp/api/cli/v1/model-runtime-configs`,并附加约定的 `encryptApiKey=false`、用户和账号参数。接口条目会使用 `logicalModelId` 作为会话选择 ID、`displayName` 作为显示名、`providerModelId` 作为实际请求模型 ID。只有同时提供协议、HTTP(S) 地址和实际模型 ID 的条目才会出现在可选择列表中,避免展示一个发起会话必然失败的模型。
55
+
56
+ MAAS 默认关闭。开启后,插件先读取 `https://chatcode.chinaunicom.cn/cvp/wanma/api/v1/cli/maas-models`,再对每个模型读取 `/cvp/wanma/api/v1/cli/maas-models/{id}/runtime-config`,仅在获得运行配置后才将模型加入会话选择列表。运行地址和 API Key 始终只保存在 Host 进程中。仅当网关保持相同路径契约时才覆盖目录地址:
57
+
58
+ ```yaml
59
+ - id: llm-chatcode-config
60
+ config:
61
+ auth:
62
+ loginUrl: https://chatcode.chinaunicom.cn/unicode/#/login
63
+ apiBaseUrl: https://chatcode.chinaunicom.cn
64
+ cvpChatCodeApiUrl: https://chatcode.chinaunicom.cn/cvp
65
+ reporting:
66
+ enabled: true
67
+ codeSave: true
68
+ conversationSync: true
69
+ chatCodeSession: true
70
+ enableMaas: true
71
+ maasEndpoint: https://chatcode.chinaunicom.cn/cvp/wanma/api/v1/cli/maas-models
72
+ ```
73
+
74
+ MAAS 目录接口与 Coding Plan 接口的返回结构不同:目录接口返回模型 ID,插件会再按 ID 获取私有运行配置。可用 `codingPlanEndpoint` 和 `catalogTimeoutMs` 覆盖 Coding Plan 地址和读取超时。
75
+
76
+ 本包同时发布浏览器 client bundle,在原生“模型”设置页增加“模型配置”卡片,仅保留 MAAS 开关,不展示 CodingPlan 或 MAAS 模型列表。MAAS 开关会持久化到插件 settings 命名空间,并刷新会话模型选择器中的对应分组。自定义模型的增删改查保留在原生模型页;CodingPlan 和 MAAS 模型列表仅在会话模型选择器中展示。
77
+
78
+ -----
79
+
80
+ <a id="understand-the-implementation"></a>
81
+ ## 理解实现
82
+
83
+ <details>
84
+ <summary>实现内部机制 — 点击展开</summary>
85
+
86
+ [`src/managed.ts`](src/managed.ts)把托管模型元数据与请求凭据分离,并派生稳定的私有连接路由。[`src/adapter.ts`](src/adapter.ts)公开模型目录,并根据各路由的实际模型 ID 选择请求适配器。ID 中只要包含 `deepseek`(不区分大小写)就使用 `@deepseek-ai/dsh-llm-deepseek`;其他 ID 使用 [`vendor/dsh-llm-pi-ai/`](vendor/dsh-llm-pi-ai/)中的已修改 pi-ai 适配器,构建会把其可达模块打包进 `lib/index.js`。
87
+
88
+ DeepSeek 路由使用条目中的协议、基础 URL 和 API key。其 OpenAI 请求发送 `Authorization: Bearer`,Anthropic Messages 请求发送 `x-api-key`。非 DeepSeek 的 Anthropic 路由仍走 pi-ai,发送 `Authorization: Bearer` 且不发送 `x-api-key`。MiniMax M2 OpenAI 请求携带 `reasoning_split: true`。Provider 归属 header 始终为保留字段,pi-ai 使用隔离的内存凭据存储。
89
+
90
+ [`src/reporting/`](src/reporting/)通过各 Session 独立队列投影已提交事件,分别进入生成代码持久化、会话同步和 ChatCode 消息链。reporter 复用 `ChatCodeAuthService`,不增加客户端可见服务或第二个 Cordis 配置行。
91
+
92
+ 托管 OpenAI 流式请求显式发送 `Accept: text/event-stream`。这兼容会严格校验内容协商的转发网关,避免网关以 HTTP 200 返回 JSON 业务错误后被流解析器误报为缺少 `finish_reason`。
93
+
94
+ </details>
95
+
96
+ -----
97
+
98
+ <a id="further-exploration"></a>
99
+ ## 进一步探索
100
+
101
+ - [`docs/chatcode-models.zh.md`](docs/chatcode-models.zh.md)说明用户流程和来源字段。
102
+ - [`docs/chatcode-reporting.zh.md`](docs/chatcode-reporting.zh.md)定义上报字段、持久化与失败行为。
103
+ - [`docs/decisions/2026-08-31-chatcode-model-source.zh.md`](docs/decisions/2026-08-31-chatcode-model-source.zh.md)记录凭据归属和路由身份。
104
+ - [`docs/decisions/2026-09-16-actual-model-adapter-routing.zh.md`](docs/decisions/2026-09-16-actual-model-adapter-routing.zh.md)记录适配器选择及其鉴权影响。
105
+ - [`vendor/README.md`](vendor/README.md)记录复制的适配器源码和更新规则。
106
+
107
+ -----
108
+
109
+ <a id="model-experience"></a>
110
+ ## 模型体验
111
+
112
+ 模型通过所选导入端点接收普通 ChatCode CLI 系统提示、消息和工具。CodingPlan 条目在 Web 选择器和 CLI `/model` 选择器中都显示在「内置模型」分组下。配置路径、标签和凭据不会进入模型消息。导入的上下文容量决定请求上下文大小,导入的输出限制成为请求默认值和上限。DeepSeek 命名模型公开原生 DeepSeek 推理强度,其他导入模型保留 pi-ai 能力。
113
+
114
+ ## 已知限制与后续工作
115
+
116
+ <a id="known-limitations-and-deferred-work"></a>
117
+
118
+ - 中央目录读取为激活快照;更新中央目录后需要重新挂载或重启 profile。MAAS 开关会立即刷新会话选择分组。
119
+ - 导入模型声明文本输入。非 DeepSeek 路由不公开可选推理强度。
120
+ - 任一条目非法(包括模型 ID 重复)都会抑制完整导入目录;bundle 不会发布部分有效的来源。
121
+ - 公共插件 client 扩展点允许本包向原生“模型”页面追加托管模型配置卡片。该卡片只控制 MAAS;用户自定义模型需要编辑设置文件,CodingPlan 与 MAAS 分组保持只读。
122
+ - 包会同时跟踪复制的 pi-ai 适配器源码和原生 DeepSeek 适配器 peer;升级任一实现都必须执行显式兼容性测试,pi-ai 变化时还需刷新 `vendor/`。
123
+ - 会话同步没有持久化 outbox;当服务端可能已经提交时,ChatCode 消息请求不会重试。
124
+
125
+ <a id="dev-note"></a>
126
+ ### 开发备注
127
+
128
+ <details>
129
+ <summary>维护者工作上下文 — 点击展开</summary>
130
+
131
+ 无。
132
+
133
+ </details>
@@ -0,0 +1,4 @@
1
+ # The installed bundle contributes one Host adapter over the profile's LLM service.
2
+ - insert:
3
+ - id: llm-chatcode-config
4
+ name: '@chatcode/cco-llm-chatcode-config'
@@ -0,0 +1,12 @@
1
+ # Web waits for ChatCode launch admission before the HTTP server binds.
2
+ - insert:
3
+ - id: chatcode-web-startup
4
+ name: '@chatcode/cco-llm-chatcode-config/web-startup'
5
+ - id: webserver
6
+ inject: [webStartup, chatcodeStartupReady]
7
+ config:
8
+ host: !!js ctx.webStartup.host ?? '127.0.0.1'
9
+ port: !!js ctx.webStartup.port ?? 3080
10
+ compression: gzip
11
+ compressionLevel: 1
12
+ compressionThresholdBytes: 1024
@@ -0,0 +1,88 @@
1
+ # Shared ChatCode sign-in
2
+
3
+ [中文完整手册](chatcode-login.zh.md)
4
+
5
+ `dsh-llm-chatcode-config` owns authentication. `DSH-better-sidebar` exposes the Web menu, and `dsh-TUI` exposes `/login` and `/logout`. The ChatCode CLI source-checkout launcher applies these local patches automatically; `yuanjing-wanma-cli` remains unchanged and is used only as a reference.
6
+
7
+ ## Install and start
8
+
9
+ Keep `deepseek-harness`, `DSH-better-sidebar`, `dsh-TUI`, and `dsh-llm-chatcode-config` as sibling directories. Build each changed plugin, then install the ChatCode CLI workspace once:
10
+
11
+ ```sh
12
+ cd /absolute/path/to/deepseek-harness
13
+ pnpm install
14
+ ```
15
+
16
+ Do not run `chatcode-cli plugin --profile ... add ...` for these source-linked packages. The workspace launcher applies the sidebar/auth patches to Web and the auth patch to the built-in CLI TUI for the lifetime of each source process. It does not write them into profile manifests. If sibling names or locations change, update both the workspace overrides and launcher paths. Published `@chatcode/chatcode-cli` installations do not use this checkout-only wiring.
17
+
18
+ From separate terminals in the ChatCode CLI checkout:
19
+
20
+ ```sh
21
+ pnpm cco web
22
+ pnpm cco cli
23
+ ```
24
+
25
+ Use the same ChatCode CLI version and credential store for both clients. Both `pnpm cco cli` and `pnpm cco --profile cli` use the workspace launcher and profile `cli`. Do not invoke `apps/cli/src/bin.ts` directly because that low-level entry omits the local overlays. The standalone `dsh-tui` compatibility launcher uses a separate profile and does not receive them. This package develops against the credentials ABI introduced in `0.1.2-alpha.3`; the currently verified host source checkout reports `0.1.3-alpha.2`.
26
+
27
+ ## Operation
28
+
29
+ Open Web using the host's printed launch URL, including its one-time token if provided. While signed out, a full-page ChatCode gate covers the workbench, including the first frame while the Host status is loading. Choose **Sign in to ChatCode**. The external page receives a new UUID in its hash query:
30
+
31
+ ```text
32
+ https://chatcode.chinaunicom.cn/unicode/#/login?sessionId=<generated-uuid>
33
+ ```
34
+
35
+ Keep this parameter. If the popup is blocked, use the explicit external link in the menu. Pending sign-ins can be cancelled; errors/timeouts are visible. The original Web tab remains open. After successful validation and persistence, the plugin attempts to close its popup and focus the original tab. Browser policy, COOP, or manually opened links may require switching tabs yourself; the remote service does not guarantee a redirect to localhost.
36
+
37
+ In the integrated TUI, authentication runs before model resolution and Agent/session creation. A valid shared credential enters directly. Otherwise the CLI opens the browser, prints the one-time URL as a fallback, observes any existing pending attempt, and continues only after remote validation succeeds. Cancellation, failure, or timeout stops startup without creating a session. When a token exists but the internal or remote validation service is unreachable, the gate keeps the credential and offers **Retry validation** and **Exit**. Retry bypasses the same-process automatic-validation guard and immediately makes another request; a continued outage shows the choices again. Exit completes with status 0, creates no empty session, and emits no Loader exception stack. A missing auth bundle or unreadable credential store remains a configuration/storage error. Inside the TUI, `/login` shows the account and can start another login after an explicit logout. `/logout` removes only ChatCode account tokens and invalidates outstanding sign-ins across both clients; it does not log out the remote website's SSO session.
38
+
39
+ ## Persistence and concurrency
40
+
41
+ Both clients must run on the same machine and OS user, with the same `CHATCODE_CLI_HOME` and `credentials-local.path`. The default is `~/.chatcode-cli/.credentials.yaml`; Unix file permissions are `0600`. Containers, remote servers, and other users do not automatically share it.
42
+
43
+ The stable record is `chatcode-auth/default`. Original v1 grants are accepted; new v2 envelopes contain the grant and attempt state. Logout leaves a token-free tombstone so late responses cannot resurrect credentials. Do not delete the whole credentials file, which may contain other providers' keys. No old login credentials are automatically copied from `.chatcode-cli`.
44
+
45
+ The latest persisted login attempt wins. Native credential transactions coordinate validation, token rotation, logout and login commits. Status queries see other processes' writes without waiting for watcher propagation. Each host process validates a persisted token once on its first status read; later presentation polling reuses that result, while an explicit TUI retry forces a new request. Expired/revoked tokens refresh through the legacy long-token endpoint. Rotated credentials survive temporary follow-up validation failures.
46
+
47
+ ## Configuration and scope
48
+
49
+ Defaults require no extra configuration. To override endpoints or timeouts, create a patch and pass it after the automatically inserted patches, for example `pnpm cco web --patch ./chatcode.override.yml`:
50
+
51
+ ```yaml
52
+ - id: llm-chatcode-config
53
+ config:
54
+ auth:
55
+ requireLogin: true
56
+ loginUrl: https://chatcode.chinaunicom.cn/unicode/#/login
57
+ apiBaseUrl: https://chatcode.chinaunicom.cn
58
+ pollIntervalMs: 1000
59
+ pollTimeoutMs: 3600000
60
+ requestTimeoutMs: 5000
61
+ ```
62
+
63
+ Both clients should use identical service URLs. HTTPS is required except for loopback HTTP tests. Poll interval allows 250–60000 ms, login timeout 1000–7200000 ms, and request timeout 1000–60000 ms. Validation/refresh also has a 20-second total network limit to avoid holding the credential lock indefinitely.
64
+
65
+ `requireLogin` defaults to `true`. It enables the Web gate, the pre-Agent TUI startup gate, and a Host `llm/stream` middleware that rejects every provider call with `CHATCODE_LOGIN_REQUIRED` until remote account validation succeeds. Set it to `false` only for a profile that intentionally permits model use without a ChatCode account; manual sign-in remains available. Account sign-in does **not** replace custom-model API keys, create a model catalogue, or grant model credits. User-defined models come from the `llm-chatcode-config` ChatCode CLI settings section, with `~/.chatcode-cli/settings.json` used only for first import. ChatCode CLI browser access authentication remains separate. Tokens never enter the Web/TUI presentation API.
66
+
67
+ ## Validation and troubleshooting
68
+
69
+ Regression coverage includes token validation/refresh, revocation, outage preservation, malformed responses, timeout/cancellation, competing logins, logout versus queued writes, credential-store failures, delayed service activation, native file transactions, popup fallback, stale browser status responses, route fencing, and terminal metadata display.
70
+
71
+ No real external account sign-in was performed. For live acceptance, sign in through one client and verify the account in the other; log out from the other client; then log out while an old browser login is pending and confirm its eventual response cannot restore the account.
72
+
73
+ A real signed-out `pnpm cco cli` launch was also checked: it stopped before the TUI appeared, opened a URL carrying a fresh `sessionId`, and waited for browser completion. The test attempt was then cancelled through the shared auth service, leaving no pending login record.
74
+
75
+ If authentication is absent, confirm the process was launched through the ChatCode CLI checkout's `pnpm cco` script, rebuild the configuration plugin, and run `pnpm install` in the main checkout. If clients disagree, compare user, home, store path and API URLs. If login succeeds but models are missing, inspect the model configuration independently. After a process crash, cancel an abandoned pending attempt with `/logout` before starting another login.
76
+
77
+ Environment findings:
78
+
79
+ - The sidebar lockfile pins official npm tarball URLs, while this workstation's default mirror reports different URLs for two packages. `pnpm --config.registry=https://registry.npmjs.org install --frozen-lockfile` restores dependencies with supply-chain checks retained.
80
+ - Unneeded `@google/genai` and `protobufjs` dependency build scripts are explicitly disabled in the configuration plugin.
81
+ - The original TUI crash came from reading the removed `Session.events` property. Its adapter now prefers `snapshotEvents()` while retaining the old array fallback. Patch-surface and Web-coexistence baselines now include the current host `0.1.3-alpha.2` source and the intentional disabling of the built-in DeepSeek adapter.
82
+
83
+ ### Review results
84
+
85
+ - Configuration plugin: typecheck, build and 345 tests across 14 files passed, including Host denial before provider I/O and release after validated status.
86
+ - Sidebar: typecheck/build and 37 focused account, route, locale, external-link and API tests passed. An additional Host smoke run passed 54 tests and failed one Git-history pagination assertion because this checkout has only one commit, while the test expects five; authentication routes passed.
87
+ - TUI: the full build passed, including current/legacy Session-log compatibility, startup sign-in gating, delayed model-catalog registration, i18n, adapter boundaries, socket injection, patch-surface/Web coexistence, and UI regressions.
88
+ - Persistent profile manifests no longer install the four local packages: Web retains only its existing `dshmarket` dependency, while CLI keeps the shipped TUI bundle name with no profile-local dependency. Automatic config dumps and real source Web/TUI launches passed. A real external account sign-in still requires user credentials.
@@ -0,0 +1,179 @@
1
+ # ChatCode 统一登录使用手册
2
+
3
+ 本功能以 `dsh-llm-chatcode-config` 为鉴权服务,由 `DSH-better-sidebar` 和 `dsh-TUI` 提供入口。`deepseek-harness` 的源码启动脚本自动叠加三个插件,`yuanjing-wanma-cli` 只作参考且没有修改。
4
+
5
+ ## 1. 使用前提与范围
6
+
7
+ - Web 与 TUI 在同一台电脑、同一系统用户下运行,使用相同的 `CHATCODE_CLI_HOME` 和同一个 `credentials-local` 存储路径。默认凭据文件为 `~/.chatcode-cli/.credentials.yaml`,与启动工作目录无关。远程服务器、容器、不同用户不会自动共享本机凭据。
8
+ - 当前源码 checkout 不需要向 profile 安装插件。`pnpm cco web` 自动叠加侧栏与鉴权 patch;`pnpm cco cli` 使用内置 TUI bundle 并自动叠加鉴权 patch。
9
+ - 使用支持原生 `credentials.modifyRecord` 接口的 ChatCode CLI 主机。该接口从本包开发所用的 `0.1.2-alpha.3` 起可用;当前已验证的主库源码版本为 `0.1.3-alpha.2`。不要用系统中旧版全局兼容命令的结果代替主库版本验证。
10
+ - 此功能负责 ChatCode **账号登录与共享**。`customModels` 仍使用各条目自己的 API key,运行时来源是 ChatCode CLI 的 `llm-chatcode-config` 设置段;`~/.chatcode-cli/settings.json` 只用于首次导入。登录成功不会自动获得模型额度、生成模型配置或替换其他提供方的密钥。
11
+ - ChatCode 账号与 ChatCode CLI 本地 Web 访问认证是两层独立机制。首次打开 Web 时仍应使用终端输出的启动链接(可能带一次性 `token`);通过本地访问认证后,页面会在确认 ChatCode 账号有效前保持登录门禁。默认 `auth.requireLogin: true`,配置插件还会在 Host 的 `llm/stream` 官方中间件层阻止所有模型请求,避免绕过 Web/TUI 界面直接调用模型。
12
+
13
+ ## 2. 本地安装和启动
14
+
15
+ 当前目录布局:
16
+
17
+ ```text
18
+ /Users/shiguifeng/IdeaProjects/chonggou/
19
+ deepseek-harness/
20
+ dsh-llm-chatcode-config/
21
+ DSH-better-sidebar/
22
+ dsh-TUI/
23
+ yuanjing-wanma-cli/ # 仅参考
24
+ ```
25
+
26
+ 三个插件通过 `deepseek-harness/pnpm-workspace.yaml` 的相对链接成为源码 CLI 的依赖,主启动器根据启动 profile 注入临时 `--patch`。这些 patch 只存在于本次进程的组合中,不写入 `~/.chatcode-cli/profiles/*/package.json`。修改源码后需要重新构建插件并重启对应进程;仅刷新浏览器不能更新 Host 端服务。
27
+
28
+ 通常在各插件目录执行 `pnpm run build`。配置插件只运行构建;侧栏会生成声明与浏览器包;TUI 会编译并执行自己的兼容性门禁。不要手工编辑 `lib/`。
29
+
30
+ 首次准备或依赖清单变化后,在 `deepseek-harness` 目录执行一次:
31
+
32
+ ```sh
33
+ pnpm install
34
+ ```
35
+
36
+ 无需再执行任何 `chatcode-cli plugin --profile ... add ...`。目录名或相对位置变化时,同时更新 `pnpm-workspace.yaml` 的三个 override 和主启动器的 patch 路径。发布版 `@chatcode/chatcode-cli` 不经过该源码包装器,仍采用官方 profile 安装机制。
37
+
38
+ 在两个终端分别启动:
39
+
40
+ ```sh
41
+ cd /Users/shiguifeng/IdeaProjects/chonggou/deepseek-harness
42
+ pnpm cco web
43
+ ```
44
+
45
+ ```sh
46
+ cd /Users/shiguifeng/IdeaProjects/chonggou/deepseek-harness
47
+ pnpm cco cli
48
+ ```
49
+
50
+ `pnpm cco cli` 与 `pnpm cco --profile cli` 都经过源码包装器并使用 `cli` profile;这是当前项目的 TUI 入口。不要改用 `node --import tsx/esm apps/cli/src/bin.ts ...`,该底层入口不会自动加入本地 patch。独立的 `dsh-tui` 兼容启动器使用另一个 profile,也不包含这里的自动叠加层。
51
+
52
+ ## 3. Web 登录
53
+
54
+ 1. 用启动输出的链接打开本地页面,通常是 `http://127.0.0.1:3080/`。
55
+ 2. 未登录时页面只显示 ChatCode 登录门禁;点击“登录 ChatCode”。登录状态尚未从 Host 返回时也不会短暂放出工作台。
56
+ 3. 插件生成新的 UUID,打开类似下面的外部登录页:
57
+
58
+ ```text
59
+ https://chatcode.chinaunicom.cn/unicode/#/login?sessionId=<本次生成的UUID>
60
+ ```
61
+
62
+ 4. 在该页完成登录。不要复用示例或历史 `sessionId`,也不要删除此参数。
63
+ 5. 本地服务按同一个 sessionId 轮询,拿到令牌后验证账号并写入共享凭据;门禁自动消失,账号菜单随后显示已登录账号。
64
+
65
+ 若浏览器拦截弹窗,点击菜单中的“打开登录页(浏览器未打开时点击)”。该链接明确在外部标签页打开,不会被侧栏浏览器接管。等待期间可选择“取消本次登录”;失败或超时会显示重试提示。
66
+
67
+ 原 ChatCode CLI 页面始终保持打开。检测到本次登录成功后,会尝试关闭由该页打开的登录标签页并恢复焦点;浏览器限制、COOP 或手动打开的备用链接可能使自动关闭/聚焦不可用,此时手动切回原标签页即可,登录态仍会同步。不能仅靠本地插件保证远端网站自动重定向到 `127.0.0.1`,因此没有伪造服务端回调参数,也没有额外启动回调端口。
68
+
69
+ ## 4. TUI 登录和退出
70
+
71
+ 集成版 TUI 在解析模型以及创建/恢复 Agent 和 Session **之前**执行登录门禁:
72
+
73
+ - 凭据有效:直接进入主界面,不重复打开浏览器。
74
+ - 没有有效凭据:自动打开默认浏览器,同时输出可手动访问的一次性登录链接;只有远端验证成功后才继续启动。
75
+ - 已有进行中的登录:等待同一个 sessionId,不创建新的请求。
76
+ - 登录取消、失败或超时:终止本次 CLI 启动,不创建空会话。
77
+ - 凭据中有 token、但内网或远端验证服务暂时不可达:保留原凭据并显示“重新检测 / 退出”。“重新检测”会绕过当前进程的自动验证限制并立即重新请求;若仍不可达会再次显示选项。“退出”以状态码 0 正常结束,不创建空会话,也不输出 Loader 异常堆栈。
78
+ - 鉴权 bundle 未挂载成功或凭据存储不可读:仍视为实际配置/存储错误,终止启动并输出可操作错误。
79
+
80
+ 进入主界面后,`/login` 用于查看当前账号,也可在显式退出后重新发起登录;`/logout` 清除本机共享凭据并使在途请求失效。Host 的 `llm/stream` 中间件仍是第二道门禁,防止其他入口绕过 UI。
81
+
82
+ 退出执行:
83
+
84
+ ```text
85
+ /logout
86
+ ```
87
+
88
+ 此操作清除本机共享 ChatCode 账号的访问令牌、长期令牌等信息,也使进行中的旧登录请求失效。Web 在下次查询时显示未登录。其他提供方的 API key、模型配置、会话以及浏览器网站自己的登录 Cookie 不会因此删除;远端网站可能在下次打开登录页时继续使用其 SSO 会话。
89
+
90
+ ## 5. 同步、续期和并发规则
91
+
92
+ | 场景 | 行为 |
93
+ | --- | --- |
94
+ | TUI 登录,Web 已打开 | Web 下次状态刷新看到相同账号,通常约 2 秒 |
95
+ | Web 登录后启动 TUI | 启动门禁验证通过后直接进入;`/login` 显示该账号 |
96
+ | 本地未过期、服务端已撤销 | 远端校验发现无效后尝试长期令牌续期 |
97
+ | 访问令牌即将过期 | 使用账号名或邮箱及 `longToken` 调用原有 `long/login` 接口 |
98
+ | 网络故障 | 保留凭据,标记“暂时无法验证”,不会误报为已验证登录 |
99
+ | 两端同时点击登录 | 最后持久化的登录请求有效;旧请求不能覆盖新账号 |
100
+ | 任一端退出 | 清除共享令牌,旧的在途登录响应不能重新写回 |
101
+ | 关闭登录发起进程 | 该进程的轮询停止;重新启动后必要时重新登录 |
102
+
103
+ 每个 Host 进程会在首次读取状态时验证一次持久化 token,后续界面轮询复用该结果;TUI 中用户主动选择“重新检测”时会强制发起新请求。已经成功续期但后续校验临时失败时,会保留轮换后的长期令牌,避免丢失续期结果。状态查询使用原生文件事务,绕过跨进程文件监听的短暂缓存延迟。
104
+
105
+ ## 6. 凭据存储与配置
106
+
107
+ 默认路径:
108
+
109
+ ```text
110
+ ~/.chatcode-cli/.credentials.yaml
111
+ ```
112
+
113
+ 由 ChatCode CLI 的 `credentials-local` 服务管理,Unix 下文件权限为 `0600`,创建的目录为 `0700`。插件使用 `chatcode-auth/default` 记录,兼容初版 v1 grant;新格式为带有账号和登录尝试状态的 v2 对象。退出后保留不含令牌的状态记录,用于阻止旧请求回写,因此“记录仍在”不代表仍然登录。不要清空整个凭据文件来退出 ChatCode,文件可能还保存其他提供方的凭据。
114
+
115
+ 不自动复制 `.chatcode-cli` 的旧登录凭据,不修改旧代码库或旧凭据。首次使用本实现请正常登录一次。UI 只接收账号、校验状态和登录尝试信息;令牌不写入浏览器存储,也不输出到 TUI。
116
+
117
+ 默认值无需额外配置。需要覆盖鉴权地址或时限时,新建一个后置 patch 文件并在启动命令中显式传入,例如 `pnpm cco web --patch ./chatcode.override.yml`;源码包装器会先加入插件 patch,再加入该用户 patch:
118
+
119
+ ```yaml
120
+ - id: llm-chatcode-config
121
+ config:
122
+ # 已有自定义 settingsPath 等选项应保留;该 patch 会替换整个 config 块。
123
+ auth:
124
+ # 默认 true:Web 显示强制门禁,TUI 启动前强制登录,Host 阻止所有模型调用。
125
+ requireLogin: true
126
+ loginUrl: https://chatcode.chinaunicom.cn/unicode/#/login
127
+ apiBaseUrl: https://chatcode.chinaunicom.cn
128
+ pollIntervalMs: 1000
129
+ pollTimeoutMs: 3600000
130
+ requestTimeoutMs: 5000
131
+ ```
132
+
133
+ Web 和 TUI 应使用相同服务地址。账号接口要求 HTTPS;仅为本地测试允许 loopback HTTP。支持的数值范围分别为:轮询间隔 250–60000 ms、轮询总时长 1000–7200000 ms、单请求超时 1000–60000 ms。默认等待登录最多 1 小时;账号校验/续期事务总网络等待还受内部 20 秒上限约束,避免长时间占用凭据锁。
134
+
135
+ 仅在确实需要保留一个无需 ChatCode 账号的 profile 时,才为该 profile 显式设置 `requireLogin: false`。该开关同时关闭 Web 强制门禁和 Host 模型调用门禁;账号菜单与 `/login` 仍可用于主动登录。
136
+
137
+ ## 7. 常见问题
138
+
139
+ | 现象 | 检查方法 |
140
+ | --- | --- |
141
+ | 只有侧栏,没有 ChatCode 登录入口 | 必须从主库执行 `pnpm cco web`;检查配置插件已构建且兄弟目录仍为预期名称 |
142
+ | `/login` 提示未挂载插件 | 必须从主库执行 `pnpm cco cli`;不要绕过主启动器直接运行底层 bin |
143
+ | 两端登录状态不一致 | 比较系统用户、`CHATCODE_CLI_HOME`、`credentials-local.path` 和 API 地址;确认两个进程都已更新并重启 |
144
+ | 显示无法读取/写入凭据 | 检查磁盘、文件格式和文件所属用户/权限;不要把凭据内容粘贴到日志或聊天中 |
145
+ | 浏览器未打开 | 使用界面中本次生成的备用链接,保留 sessionId |
146
+ | 显示暂时无法验证 | 检查网络、代理和 ChatCode 服务可用性;恢复后重试状态查询 |
147
+ | 成功登录却没有模型 | 检查 `customModels` 导入配置及对应 API key;账号登录不负责生成它们 |
148
+ | TUI 提示“没有可用的用户模型” | 检查 `$CHATCODE_CLI_HOME/settings.yaml` 中 `llm-chatcode-config.customModels`;仅在该设置段不存在时修复旧 JSON 并重启以重试导入 |
149
+ | 修改源码仍是旧行为 | 插件运行的是构建产物,重新 build 并重启 Host/TUI,随后刷新 Web |
150
+ | Web 仍直接进入工作台 | 确认 `auth.requireLogin` 未设为 `false`,重新构建配置插件与侧栏并从主库重启 `pnpm cco web` |
151
+ | TUI 显示“未挂载 ChatCode 登录插件” | 确认使用主库 `pnpm cco cli` 启动,然后运行主库 `pnpm install` 并重新构建配置插件 |
152
+ | 退出后再次打开网页自动登录 | 远端 SSO Cookie 仍有效;本地 `/logout` 不等于远端网站注销 |
153
+
154
+ ## 8. 本次验证与已知环境限制
155
+
156
+ 本次新增测试使用模拟 ChatCode 响应和临时 ChatCode CLI 凭据目录,覆盖正常登录、账号验证、续期、轮换后缺少 expiry、远端拒绝、断网、取消、超时、重复登录、退出与写入竞争、存储失败、服务延迟挂载、原生文件事务、浏览器弹窗/链接行为和终端状态展示。
157
+
158
+ 已使用当前实际 `web` 和 `cli` profile 做本地启动验收:Web 在无凭据时返回 `required: true` 并显示全屏登录门禁;TUI 会在 Agent/Session 创建前等待登录,验证成功后才进入主界面。没有使用真实账号完成外部网站登录,因此仍需按以下步骤做真实服务验收:
159
+
160
+ 另外已真实执行一次未登录状态下的 `pnpm cco cli`:TUI 主界面没有出现,命令打开了带全新 `sessionId` 的登录地址并等待浏览器完成。随后通过共享鉴权服务取消了该测试请求,凭据中没有遗留 pending 登录状态。
161
+
162
+ 1. 两端从本地已构建插件启动,确认使用同一个凭据存储。
163
+ 2. 清除凭据后启动 TUI,在自动打开的页面完成一次实际登录,Web 刷新后确认账号一致。
164
+ 3. 在 Web 退出,再用 TUI `/login` 确认需要登录。
165
+ 4. Web 发起登录但未完成时,在 TUI `/logout`,随后完成旧页面登录;两端应保持未登录。
166
+ 5. Web 发起新登录并完成,检查正常同步;关闭或切回登录标签页。
167
+
168
+ 构建环境另外发现:
169
+
170
+ - 侧栏锁文件中两个 `@deepseek-ai/dsh-*` ABI 依赖的 tarball 地址为 npm 官方地址,而本机默认镜像的元数据不同。用 `pnpm --config.registry=https://registry.npmjs.org install --frozen-lockfile` 可在保持完整性校验的前提下恢复依赖;未关闭供应链校验。
171
+ - 配置插件显式禁用了不需要的 `@google/genai` 和 `protobufjs` 依赖构建脚本,避免 pnpm 在自动安装时等待这些脚本的授权。
172
+ - TUI 原先直接读取已移除的 `Session.events`,这正是 `events is not iterable` 的原因。适配层现在优先调用 `snapshotEvents()`,并兼容旧版数组。patch-surface 与 Web 共存基线已纳入当前主库 `0.1.3-alpha.2`,并明确记录集成版禁用内置 DeepSeek 适配器。
173
+
174
+ ### 本次验证记录
175
+
176
+ - 配置插件:TypeScript 检查通过,14 个测试文件、345 项测试通过,构建成功;专项用例确认未登录时在任何提供方 I/O 前拒绝模型请求,验证通过后才放行。
177
+ - 侧栏:TypeScript 检查与构建通过;账号界面、Host 登录路由、语言字典、外链与 API 边界共 37 项专项测试通过。额外 Host smoke 中 54 项通过,1 项 Git 历史分页测试因本地 checkout 只有 1 条提交而不满足其固定 5 条提交的断言;登录路由测试通过。
178
+ - TUI:完整构建通过,覆盖 Session 新旧日志 API、启动前登录门禁、模型目录延迟注册、账号/断网/等待/错误展示、i18n、adapter 边界、socket 注入、patch-surface/Web 共存,以及界面回归;原 `events is not iterable` 已消失。
179
+ - profile 持久化清单已清除四条本地安装:Web 只保留原有 `dshmarket`,CLI 不保存本地依赖且保留发行模板的 TUI bundle 名。自动 patch 的配置转储与真实 Web/TUI 启动均通过,外部 ChatCode 账号登录仍需用户凭据验收。
@@ -0,0 +1,29 @@
1
+ # Use ChatCode CLI models
2
+
3
+ English | [中文](chatcode-models.zh.md)
4
+
5
+ Use this guide when ChatCode CLI already has working model connections and you want to select them in the Web or TUI client. The legacy file must contain a `customModels` array with explicit model IDs, base URLs, and API keys. The plugin imports that array into ChatCode CLI settings when its own settings section is absent.
6
+
7
+ In the current sibling-repository setup, do not install this plugin into a profile. Start from the ChatCode CLI checkout; its workspace launcher activates the plugin for both entry points without modifying profile manifests:
8
+
9
+ ```sh
10
+ cd /absolute/path/to/deepseek-harness
11
+ pnpm cco web
12
+ pnpm cco cli
13
+ ```
14
+
15
+ The plugin imports `~/.chatcode-cli/settings.json` into the `llm-chatcode-config` section of `$CHATCODE_CLI_HOME/settings.yaml`. Open the conversation model selector and find the **自定义模型** group. An existing settings section is authoritative, including `customModels: []`, so the legacy file cannot overwrite later edits.
16
+
17
+ The plugin selects the request implementation from the actual provider model ID after resolving the public selection. An ID containing `deepseek`, case-insensitively, uses the native DeepSeek adapter with that entry's protocol, `baseUrl`, and `apiKey`; its Anthropic Messages requests carry `x-api-key`, while its OpenAI requests carry `Authorization: Bearer`. Every other ID uses pi-ai, whose Anthropic path retains `Authorization: Bearer` and does not send `x-api-key`.
18
+
19
+ For another file, create an optional patch and pass it to the source command, for example `pnpm cco web --patch ./chatcode-models.override.yml`. Replace the example with the Host path:
20
+
21
+ ```yaml
22
+ - id: llm-chatcode-config
23
+ config:
24
+ settingsPath: 'C:/Users/Owner/.chatcode-cli/settings.json'
25
+ ```
26
+
27
+ After import, edit `customModels` under `llm-chatcode-config` in `$CHATCODE_CLI_HOME/settings.yaml`; valid updates refresh subsequent model discovery and requests without restarting the Host. A missing legacy file leaves the profile running and retries import on the next start. Any invalid entry rejects the complete settings update; the plugin never publishes only the valid subset. An oversized output cap fails before a provider request. HTTP gateways do not encrypt prompts or credentials; use HTTPS when supported.
28
+
29
+ The [package reference](../README.md) owns protocol mapping, token-limit precedence, route identity, and unsupported settings.