dsh-oauth-login 0.2.4

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/INSTALL.md +59 -0
  2. package/INSTALL.zh.md +45 -0
  3. package/LICENSE +201 -0
  4. package/README.en.md +104 -0
  5. package/README.md +104 -0
  6. package/README.zh.md +3 -0
  7. package/SECURITY.md +33 -0
  8. package/cordis.patch.yml +5 -0
  9. package/docs/network-proxy.md +45 -0
  10. package/docs/openrouter-sync.md +84 -0
  11. package/docs/screenshots/01-providers-signed-out.png +0 -0
  12. package/docs/screenshots/03-copilot-signing-in.png +0 -0
  13. package/docs/screenshots/04-mixed-live-states.png +0 -0
  14. package/docs/screenshots/05-copilot-sign-in.gif +0 -0
  15. package/docs/screenshots/06-cli-status-store.png +0 -0
  16. package/lib/bin.d.ts +5 -0
  17. package/lib/bin.js +2132 -0
  18. package/lib/client.js +1915 -0
  19. package/lib/client.js.map +1 -0
  20. package/lib/index.d.ts +482 -0
  21. package/lib/index.js +3105 -0
  22. package/lib/invariant.d.ts +7 -0
  23. package/lib/invariant.js +8 -0
  24. package/package.json +180 -0
  25. package/src/adapter.ts +207 -0
  26. package/src/auth-routes.ts +654 -0
  27. package/src/auth.ts +76 -0
  28. package/src/bin.ts +185 -0
  29. package/src/catalog.ts +129 -0
  30. package/src/client/OpenRouterSyncStatus.tsx +66 -0
  31. package/src/client/PiLoginSettings.tsx +470 -0
  32. package/src/client/ProxySettings.tsx +123 -0
  33. package/src/client/SearchableModelSelect.tsx +595 -0
  34. package/src/client/draft-input.ts +12 -0
  35. package/src/client/index.tsx +71 -0
  36. package/src/client/locales.ts +176 -0
  37. package/src/client/login-input-copy.ts +34 -0
  38. package/src/client/login-window.ts +24 -0
  39. package/src/client/model-filter.ts +45 -0
  40. package/src/client/openrouter-store.ts +122 -0
  41. package/src/client/proxy-draft.ts +57 -0
  42. package/src/extra-models.ts +201 -0
  43. package/src/hosted-capture.ts +41 -0
  44. package/src/hosted-images.ts +154 -0
  45. package/src/http.ts +241 -0
  46. package/src/ids.ts +17 -0
  47. package/src/index.ts +183 -0
  48. package/src/invariant.ts +12 -0
  49. package/src/model-error-hint.ts +98 -0
  50. package/src/native-tools.ts +442 -0
  51. package/src/oauth-refresh.ts +49 -0
  52. package/src/openrouter-catalog.ts +245 -0
  53. package/src/openrouter-free.ts +76 -0
  54. package/src/openrouter-models.ts +155 -0
  55. package/src/openrouter-types.ts +40 -0
  56. package/src/plugin-config.ts +30 -0
  57. package/src/provider.ts +137 -0
  58. package/src/proxy-config.ts +61 -0
  59. package/src/proxy-store.ts +45 -0
  60. package/src/proxy-transport.ts +220 -0
  61. package/src/redact.ts +22 -0
  62. package/src/responses-tap.ts +97 -0
  63. package/src/session.ts +104 -0
  64. package/src/store.ts +234 -0
package/INSTALL.md ADDED
@@ -0,0 +1,59 @@
1
+ # Install dsh-oauth-login
2
+
3
+ [中文](INSTALL.zh.md). Product pages: [README.md](README.md) (中文), [README.en.md](README.en.md).
4
+
5
+ Stock DeepSeek Harness **0.1.5-rc.3** users install with official `dsh` and **pnpm**:
6
+
7
+ ```sh
8
+ dsh plugin --profile web add github:aa2246740/dsh-oauth-login
9
+ ```
10
+
11
+ If `dsh` is not on PATH:
12
+
13
+ ```sh
14
+ npx @deepseek-ai/dsh plugin --profile web add github:aa2246740/dsh-oauth-login
15
+ ```
16
+
17
+ That `github:` spec works because the package declares `dsh.bundle.patch` and
18
+ commits built `lib/`. Official add runs pnpm in `$DSH_HOME/profiles/web` and
19
+ appends the package to `dsh.profile.bundles`. Then restart that Host and reload
20
+ the page. You do not need Creator Mode or a second toolchain.
21
+
22
+ Use `file:` only when editing a local clone. Keep the prefix. A bare
23
+ `./dsh-oauth-login` becomes a symlink, while this plugin intentionally resolves
24
+ its DSH runtime peer dependencies from the profile; the `file:` install copies
25
+ the package into that resolution tree.
26
+
27
+ ```sh
28
+ git clone https://github.com/aa2246740/dsh-oauth-login.git
29
+ dsh plugin --profile web add file:./dsh-oauth-login
30
+ ```
31
+
32
+ Settings → **Subscription Login**. Existing DSH installs keep the old filename as a one-time DSH migration source and never touch Pi Agent auth.
33
+
34
+ ```sh
35
+ dsh plugin --profile web exec dsh-oauth-login login openai-codex
36
+ dsh plugin --profile web exec dsh-oauth-login login zai-coding-cn
37
+ dsh plugin --profile web exec dsh-oauth-login status
38
+ dsh plugin --profile web exec dsh-oauth-login logout openai-codex
39
+ ```
40
+
41
+ For Zhipu GLM Coding Plan, the command opens the official Plan page and asks
42
+ for its API key locally. The plugin never reads your browser session.
43
+
44
+ After upgrading the server plugin and restarting DSH once, open Settings →
45
+ Subscription Login → Network proxy. Configure HTTP and WebSocket independently.
46
+ The address defaults to `http://127.0.0.1`, with the port left empty. An enabled
47
+ channel with an explicit address and port overrides automatic discovery; an
48
+ enabled channel with the default address and no port preserves it without
49
+ implicitly selecting port 80; a disabled channel connects
50
+ directly. Use an HTTP(S) CONNECT or mixed proxy, not a SOCKS-only port. UI saves
51
+ apply to new requests without another restart. Restart DSH when changing the
52
+ environment variables inherited at launch. See [details](docs/network-proxy.md).
53
+
54
+ Uninstall:
55
+
56
+ ```sh
57
+ dsh plugin --profile web exec dsh-oauth-login logout
58
+ dsh plugin --profile web remove dsh-oauth-login
59
+ ```
package/INSTALL.zh.md ADDED
@@ -0,0 +1,45 @@
1
+ # 安装 dsh-oauth-login
2
+
3
+ [English](INSTALL.md)。说明和截图在 [README.md](README.md),英文在 [README.en.md](README.en.md)。
4
+
5
+ 官方 DeepSeek Harness **0.1.5-rc.3** 用户用官方 `dsh` 和 **pnpm** 安装:
6
+
7
+ ```sh
8
+ dsh plugin --profile web add github:aa2246740/dsh-oauth-login
9
+ ```
10
+
11
+ 没有 `dsh` 时:
12
+
13
+ ```sh
14
+ npx @deepseek-ai/dsh plugin --profile web add github:aa2246740/dsh-oauth-login
15
+ ```
16
+
17
+ 这条 `github:` 命令能装上,是因为包装了 `dsh.bundle.patch`,并且仓库提交了编好的 `lib/`。官方 add 在 `$DSH_HOME/profiles/web` 里跑 pnpm,再把这个包装进 `dsh.profile.bundles`。装完重启这个 Host,刷新页面。不需要 Creator Mode,也不需要另装一套工具。
18
+
19
+ 本机改源码时再用 `file:`,并且必须保留前缀。直接写 `./dsh-oauth-login` 会变成符号链接;本插件有意从 profile 复用 DSH 运行时的 peer dependency,因此必须使用 `file:` 副本,才能正确解析依赖。
20
+
21
+ ```sh
22
+ git clone https://github.com/aa2246740/dsh-oauth-login.git
23
+ dsh plugin --profile web add file:./dsh-oauth-login
24
+ ```
25
+
26
+ 设置 → **订阅登录**。旧版 DSH 文件只作为一次性迁移来源,不会读取或修改 Pi Agent 的登录文件。
27
+
28
+ ```sh
29
+ dsh plugin --profile web exec dsh-oauth-login login openai-codex
30
+ dsh plugin --profile web exec dsh-oauth-login login zai-coding-cn
31
+ dsh plugin --profile web exec dsh-oauth-login status
32
+ dsh plugin --profile web exec dsh-oauth-login logout openai-codex
33
+ ```
34
+
35
+ 智谱 GLM Coding Plan 会打开官方套餐页,再在本机提示你输入 API Key;
36
+ 插件不会读取你的浏览器登录状态。
37
+
38
+ 升级服务端插件后先重启一次 DSH,再进入「设置 → 订阅登录 → 网络代理」。HTTP 与 WebSocket 可以独立配置,地址默认填入 `http://127.0.0.1`,端口留空。开启并填写端口时优先使用该代理;默认地址且端口留空时沿用自动发现,不会默认使用 80 端口;关闭时直接连接。请使用 HTTP(S) CONNECT / 混合代理端口,不能填纯 SOCKS 端口。页面保存后用于新请求,不需要再次重启;改变启动时继承的环境变量则需要重启。详见[网络代理与恢复机制](docs/network-proxy.md)。
39
+
40
+ 卸载:
41
+
42
+ ```sh
43
+ dsh plugin --profile web exec dsh-oauth-login logout
44
+ dsh plugin --profile web remove dsh-oauth-login
45
+ ```
package/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/README.en.md ADDED
@@ -0,0 +1,104 @@
1
+ # dsh-oauth-login
2
+
3
+ [中文](README.md) | English
4
+
5
+ ```sh
6
+ dsh plugin --profile web add github:aa2246740/dsh-oauth-login
7
+ ```
8
+
9
+ You need official `dsh` on PATH (or `npx @deepseek-ai/dsh`) and **pnpm**. Then restart that Host and reload the page. `dsh plugin add` writes the profile. It does not hot-load a running Host.
10
+
11
+ OAuth login for ChatGPT, Claude, Grok, Copilot, OpenRouter, and Kimi on [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness), plus Zhipu GLM Coding Plan via its official plan API key. Credentials go only to `$DSH_HOME/.dsh-oauth-auth.json`.
12
+
13
+ Official `codex login`, Claude Code, `grok` CLI, and Pi Agent `~/.pi/agent/auth.json` are not read or written.
14
+
15
+ The UI is **Settings → 订阅登录**.
16
+
17
+ ![Provider list signed out](docs/screenshots/01-providers-signed-out.png)
18
+
19
+ ![Copilot waiting for authorization](docs/screenshots/05-copilot-sign-in.gif)
20
+
21
+ ![Copilot waiting on a device code](docs/screenshots/03-copilot-signing-in.png)
22
+
23
+ ![Mixed signed-in state](docs/screenshots/04-mixed-live-states.png)
24
+
25
+ ![CLI status reads the DSH store](docs/screenshots/06-cli-status-store.png)
26
+
27
+ ## Install
28
+
29
+ Node 22.19+ and official DeepSeek Harness **0.1.5-rc.3** (`@deepseek-ai/dsh@0.1.5-rc.3`, tag `dsh-v0.1.5-rc.3`).
30
+
31
+ That `github:` command works because this package declares `dsh.bundle.patch` and commits built `lib/`. Official `dsh plugin add` runs pnpm in `$DSH_HOME/profiles/web` and appends this package to `dsh.profile.bundles`. You do not need Creator Mode or a second toolchain.
32
+
33
+ If `dsh` is not on PATH:
34
+
35
+ ```sh
36
+ npx @deepseek-ai/dsh plugin --profile web add github:aa2246740/dsh-oauth-login
37
+ ```
38
+
39
+ Use `file:` only when you are editing a local clone (do not drop the prefix):
40
+
41
+ ```sh
42
+ git clone https://github.com/aa2246740/dsh-oauth-login.git
43
+ dsh plugin --profile web add file:./dsh-oauth-login
44
+ ```
45
+
46
+ Keep the `file:` prefix. A bare `./dsh-oauth-login` becomes a symlink and peer dependencies will not resolve.
47
+
48
+ Open **Settings → 订阅登录**. Pick a `pi-…` route in chat.
49
+
50
+ ```sh
51
+ dsh plugin --profile web exec dsh-oauth-login login openai-codex
52
+ dsh plugin --profile web exec dsh-oauth-login login xai
53
+ dsh plugin --profile web exec dsh-oauth-login login zai-coding-cn
54
+ dsh plugin --profile web exec dsh-oauth-login status
55
+ ```
56
+
57
+ `status` does not print tokens. Legacy `.pi-login-auth.json` is renamed on the next write.
58
+
59
+ ## Providers
60
+
61
+ | Settings | Harness route | Pi provider | Credential |
62
+ |---|---|---|---|
63
+ | ChatGPT Codex | `pi-openai-codex` | `openai-codex` | OAuth |
64
+ | Claude Pro/Max | `pi-anthropic` | `anthropic` | OAuth |
65
+ | xAI Grok | `pi-xai` | `xai` | OAuth |
66
+ | GitHub Copilot | `pi-github-copilot` | `github-copilot` | OAuth |
67
+ | OpenRouter | `pi-openrouter` | `openrouter` | OAuth |
68
+ | Kimi For Coding | `pi-kimi-coding` | `kimi-coding` | OAuth |
69
+ | Zhipu GLM Coding Plan | `pi-zai-coding-cn` | `zai-coding-cn` | Plan API key |
70
+
71
+ Radius is not implemented.
72
+
73
+ OpenRouter pulls the official catalog after OAuth and refreshes about every 15 minutes while signed in. The model menu can filter free models. The catalog cache is `$DSH_HOME/.dsh-oauth-openrouter-models.json` and holds no credentials. See [OpenRouter model sync](docs/openrouter-sync.md).
74
+
75
+ Zhipu **连接套餐** opens the official [Coding Plan page](https://bigmodel.cn/coding-plan/personal/overview). Paste the key back into DSH. The API is `https://open.bigmodel.cn/api/coding/paas/v4`. BigModel cookies are not read. From 0.2.1 the list includes both `glm-5.3` and `glm-5.3-flash`.
76
+
77
+ Do not paste this auth file, API keys, callback URLs, codes, or tokens into public issues. Private reports: [SECURITY.md](SECURITY.md).
78
+
79
+ ## Hosted search and images
80
+
81
+ On these routes the plugin removes DSH `web_search` / `web_fetch` and attaches the vendor tools:
82
+
83
+ | Route | Hosted tools |
84
+ |---|---|
85
+ | `pi-xai` | `web_search`, `x_search`, `image_generation` |
86
+ | `pi-openai-codex` | `web_search`, `image_generation` |
87
+ | `pi-anthropic` | `web_search_20250305` |
88
+
89
+ Copilot, OpenRouter, Kimi, and Zhipu do not get hosted tools. To keep DSH search:
90
+
91
+ ```yaml
92
+ - id: llm-oauth-login
93
+ name: dsh-oauth-login
94
+ config:
95
+ nativeTools: false
96
+ ```
97
+
98
+ `nativeImage: false` keeps search and drops image generation.
99
+
100
+ Chat retries use official `dsh-llm-retry`. HTTP 429 is not the same as quota exhaustion. **Settings → 订阅登录 → 网络代理** affects only this plugin.
101
+
102
+ ## License
103
+
104
+ Apache-2.0. See [LICENSE](LICENSE).
package/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # dsh-oauth-login
2
+
3
+ 中文 | [English](README.en.md)
4
+
5
+ ```sh
6
+ dsh plugin --profile web add github:aa2246740/dsh-oauth-login
7
+ ```
8
+
9
+ PATH 上需要官方 `dsh`(没有的话用 `npx @deepseek-ai/dsh`)和 **pnpm**。装完重启这个 Host,刷新页面。`dsh plugin add` 只写 profile,不会热挂正在跑的 Host。
10
+
11
+ 把 ChatGPT、Claude、Grok、Copilot、OpenRouter、Kimi 的 OAuth 登录和智谱 GLM Coding Plan 接到 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)。凭据只写 `$DSH_HOME/.dsh-oauth-auth.json`。
12
+
13
+ 厂商公开 OAuth 就按其流程登录。智谱用官方 Coding Plan API Key。官方 `codex login`、Claude Code、`grok` CLI、Pi Agent 的 `~/.pi/agent/auth.json`,这里不读也不写。
14
+
15
+ 入口在 **设置 → 订阅登录**。
16
+
17
+ ![设置里的厂商列表](docs/screenshots/01-providers-signed-out.png)
18
+
19
+ ![Copilot 等待授权](docs/screenshots/05-copilot-sign-in.gif)
20
+
21
+ ![Copilot 正在等授权码](docs/screenshots/03-copilot-signing-in.png)
22
+
23
+ ![混合登录状态](docs/screenshots/04-mixed-live-states.png)
24
+
25
+ ![CLI status 读的是 DSH 这份 store](docs/screenshots/06-cli-status-store.png)
26
+
27
+ ## 安装
28
+
29
+ 需要 Node 22.19+,以及能跑起来的官方 DeepSeek Harness **0.1.5-rc.3**(`@deepseek-ai/dsh@0.1.5-rc.3`,tag `dsh-v0.1.5-rc.3`)。
30
+
31
+ 这条 `github:` 命令能装上,是因为包装了 `dsh.bundle.patch`,并且仓库提交了编好的 `lib/`。官方 `dsh plugin add` 在 `$DSH_HOME/profiles/web` 里跑 pnpm,再把这个包装进 `dsh.profile.bundles`。不需要 Creator Mode,也不需要另装一套工具。
32
+
33
+ 没有 `dsh` 时:
34
+
35
+ ```sh
36
+ npx @deepseek-ai/dsh plugin --profile web add github:aa2246740/dsh-oauth-login
37
+ ```
38
+
39
+ 本机改源码时再用 `file:`(不要写成裸的 `./`):
40
+
41
+ ```sh
42
+ git clone https://github.com/aa2246740/dsh-oauth-login.git
43
+ dsh plugin --profile web add file:./dsh-oauth-login
44
+ ```
45
+
46
+ `file:` 前缀必须留着。写成 `./dsh-oauth-login` 会被装成符号链接,peer 依赖解析不到。
47
+
48
+ 打开 **设置 → 订阅登录**。对话里选 `pi-…` 路由。
49
+
50
+ ```sh
51
+ dsh plugin --profile web exec dsh-oauth-login login openai-codex
52
+ dsh plugin --profile web exec dsh-oauth-login login xai
53
+ dsh plugin --profile web exec dsh-oauth-login login zai-coding-cn
54
+ dsh plugin --profile web exec dsh-oauth-login status
55
+ ```
56
+
57
+ `status` 不打印 token。旧版 `.pi-login-auth.json` 只在下次写入时迁到新文件名。
58
+
59
+ ## 支持哪些登录
60
+
61
+ | 设置页 | Harness 路由 | Pi provider | 凭据方式 |
62
+ |---|---|---|---|
63
+ | ChatGPT Codex | `pi-openai-codex` | `openai-codex` | OAuth |
64
+ | Claude Pro/Max | `pi-anthropic` | `anthropic` | OAuth |
65
+ | xAI Grok | `pi-xai` | `xai` | OAuth |
66
+ | GitHub Copilot | `pi-github-copilot` | `github-copilot` | OAuth |
67
+ | OpenRouter | `pi-openrouter` | `openrouter` | OAuth |
68
+ | Kimi For Coding | `pi-kimi-coding` | `kimi-coding` | OAuth |
69
+ | 智谱 GLM Coding Plan | `pi-zai-coding-cn` | `zai-coding-cn` | Plan API Key |
70
+
71
+ Radius 没做。
72
+
73
+ OpenRouter 登录成功后拉官方模型目录,已登录时大约每 15 分钟同步一次。模型菜单可以筛「仅免费」。目录缓存在 `$DSH_HOME/.dsh-oauth-openrouter-models.json`,不含凭据。细节见 [OpenRouter 模型同步](docs/openrouter-sync.md)。
74
+
75
+ 智谱点「连接套餐」会打开官方 [Coding Plan 个人页](https://bigmodel.cn/coding-plan/personal/overview),把 Key 贴回本机 DSH。接口是 `https://open.bigmodel.cn/api/coding/paas/v4`。插件不读 BigModel Cookie。从 0.2.1 起同时提供 `glm-5.3` 和 `glm-5.3-flash`。
76
+
77
+ 不要把这份登录文件、API Key、回调 URL、授权码或 token 贴到公开 Issue。私下报告见 [SECURITY.md](SECURITY.md)。
78
+
79
+ ## 厂商自己的搜索和出图
80
+
81
+ 这些路由上,插件会拿掉 DSH 的 `web_search` / `web_fetch`,改挂厂商自己的工具:
82
+
83
+ | 路由 | Hosted tools |
84
+ |---|---|
85
+ | `pi-xai` | `web_search`、`x_search`、`image_generation` |
86
+ | `pi-openai-codex` | `web_search`、`image_generation` |
87
+ | `pi-anthropic` | `web_search_20250305` |
88
+
89
+ Copilot、OpenRouter、Kimi、智谱不挂 hosted tool。要继续用 DSH 自己的搜索:
90
+
91
+ ```yaml
92
+ - id: llm-oauth-login
93
+ name: dsh-oauth-login
94
+ config:
95
+ nativeTools: false
96
+ ```
97
+
98
+ `nativeImage: false` 只留搜索,去掉出图。
99
+
100
+ Chat 失败重试走官方 `dsh-llm-retry`。429 不等于额度耗尽。设置 → 订阅登录 → 网络代理只影响本插件。
101
+
102
+ ## 许可
103
+
104
+ Apache-2.0。见 [LICENSE](LICENSE)。
package/README.zh.md ADDED
@@ -0,0 +1,3 @@
1
+ # dsh-oauth-login
2
+
3
+ 中文说明已并入 [README.md](README.md)。English is in [README.en.md](README.en.md).
package/SECURITY.md ADDED
@@ -0,0 +1,33 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a vulnerability
4
+
5
+ Please use GitHub's private vulnerability reporting for this repository:
6
+
7
+ 1. Open the repository's **Security** tab.
8
+ 2. Choose **Report a vulnerability**.
9
+ 3. Include reproduction steps without including real credentials.
10
+
11
+ Do not open a public issue containing OAuth callback URLs, authorization codes,
12
+ access or refresh tokens, API keys, cookies, or the contents of
13
+ `$DSH_HOME/.dsh-oauth-auth.json`.
14
+
15
+ ## Security boundaries
16
+
17
+ - DSH owns a separate OAuth grant and never reads or writes Pi Agent or official
18
+ CLI auth files.
19
+ - Stored credentials are restricted to the current operating-system user.
20
+ - Local proxy candidates must pass a credential-free HTTP CONNECT probe before
21
+ use. OAuth payloads remain protected by end-to-end TLS.
22
+ - Explicit HTTP and WebSocket proxy settings apply only inside this plugin's
23
+ request scope. A disabled channel connects directly; a failed explicit proxy
24
+ does not silently fall back to direct access. Loopback callbacks bypass proxies.
25
+ - The proxy settings API accepts same-origin, loopback requests on a literal
26
+ localhost/loopback Host, requires JSON for writes, and uses revision checks.
27
+ URLs containing proxy credentials, paths, queries, or fragments are rejected.
28
+ Settings are written atomically with mode 0600 to a separate file; the OAuth
29
+ credential document is not modified. TLS verification is never disabled.
30
+ - Authorization URLs are restricted to the provider hosts declared by the
31
+ installed Pi AI provider catalog.
32
+
33
+ The `0.1.x` line receives security fixes while it is the latest release line.
@@ -0,0 +1,5 @@
1
+ # Pi-native OAuth routes. Does not replace catalog API-key routes and never
2
+ # shares official CLI files (~/.codex, ~/.grok, ~/.claude).
3
+ - insert:
4
+ - id: llm-oauth-login
5
+ name: dsh-oauth-login
@@ -0,0 +1,45 @@
1
+ # 网络代理与 Codex 恢复
2
+
3
+ ## 本机代理端口 45678 怎么填
4
+
5
+ 先确认 45678 是代理应用的 **HTTP 或混合端口**,而不是纯 SOCKS、控制接口或订阅端口。
6
+
7
+ 两项地址均默认填入 `http://127.0.0.1`,端口为空;使用本机代理时只需填写端口。端口栏的“例如 45678”只是提示,不是已保存的值。默认地址且端口留空时继续自动发现代理,不会误连到 80 端口;已有的显式地址和端口不被默认值覆盖。
8
+
9
+ | 设置项 | 建议值 |
10
+ |---|---|
11
+ | HTTP 使用代理 | 开启 |
12
+ | HTTP 地址 / 端口 | `http://127.0.0.1` / `45678` |
13
+ | WebSocket 使用代理 | 开启 |
14
+ | WebSocket 地址 / 端口 | `http://127.0.0.1` / `45678` |
15
+
16
+ 这两个地址写的是本地代理入口,不是模型 API,也不是 `ws://` 或 `wss://` 地址。WSS 经 HTTP CONNECT 建立隧道后,仍使用 TLS 连接模型服务器。HTTP 项负责登录、令牌刷新、HTTP 模型请求和 SSE;WS 项负责模型 WebSocket 连接。代理应用还必须把实际 API 域名送到可用的出口,并允许 CONNECT / WebSocket 长连接。
17
+
18
+ **开启 WS 代理不等于取消五次重试。** 正确选路后,第一次连接成功就不重试;代理节点断流、TLS/握手失败、网络切换或服务端故障仍可能触发恢复。如果发生 SSE 降级,HTTP 项也必须有可用的网络路径。
19
+
20
+ ## 不改 DSH 核心
21
+
22
+ 实现全部位于外部 `dsh-oauth-login` 插件。它使用 Undici 的公开 dispatcher 接口和 AsyncLocalStorage 区分插件请求中的 HTTP / WS;不改 DSH 核心文件、Pi AI 文件、全局代理环境变量或 OAuth 凭据文件。插件之外的请求继续交给原 dispatcher。
23
+
24
+ 页面设置单独存入凭据文件旁的 `.dsh-oauth-proxy.json`,权限 0600。没有新文件时,两项都沿用旧的自动发现流程。开关关闭意味着该协议直连;开关开启、默认地址且端口留空(或两栏均清空)意味着允许自动发现,不代表一定找到代理。自定义地址须填写端口,也可粘贴完整的带端口代理 URL。显式地址优先于旧环境变量;错误地址会明确失败,不会偷偷改走直连。
25
+
26
+ UI 保存影响新请求。正在进行的调用使用开始时取得的配置完成。WS 配置变化后,通过 Pi AI 的公开连接清理接口关闭旧会话连接,不重置 SSE 降级标记。已有降级会话继续使用 SSE;新会话才重新尝试 WS。首次安装这版服务端代码仍需要受控重启 DSH。
27
+
28
+ ## 重试与降级分别由谁负责
29
+
30
+ 这里是 DSH 经 Pi AI 调用 Codex 服务,不是替换官方 Codex CLI 的网络实现。保持 DSH 的默认预算:首次调用失败后最多再重试五次,使用原有退避与取消规则。Pi 的单次调用仍是 `maxRetries: 0`,不叠加第二层重试。
31
+
32
+ Pi AI 0.82.1 已有 `auto` 传输恢复:首个 WS 事件前失败,可以在同一次 SDK 调用中转 SSE;首个事件后发生传输故障,会给当前会话记下 SSE 降级状态,下一次调用使用 SSE。原来的缺口是 DSH 没把裸 `WebSocket error` 当作可重试故障,于是下一次调用根本没有发生。
33
+
34
+ 插件现在只把 Codex 路由的裸 `WebSocket error`,以及关闭码 1000、1001、1005、1006、1011、1012、1013 对应的明确错误改为 `TRANSPORT`。协议、消息过大、策略拒绝及未知错误不据此扩大重试范围。直接 `stream` 和正常 Agent 使用的 `prepareCall().stream` 都覆盖,保持同一会话 ID 和已准备的请求快照。
35
+
36
+ 不会强制 WS 重试五次才降级,也没有专门改成两次。认证、额度和用户取消不应被包装成网络故障。网络错误恢复也不能回放已经执行的工具。
37
+
38
+ ## 已覆盖的验证
39
+
40
+ - `npm run check`:类型检查、插件回归和客户端/服务端构建。
41
+ - `tests/http.spec.ts`:使用两个本机 CONNECT 代理、真实 HTTPS/WSS 和受信任的测试证书,验证四种开关组合、独立端口、环境变量覆盖、并发隔离、回调直连、错误地址不直连、保存不打断已有请求。没有关闭 TLS 验证。
42
+ - `node scripts/verify-network-recovery.mjs <harness-root> [result.json]`:真实 Harness Agent Loop、构建后的插件和真实 Pi Codex SDK,仅替换网络事件。覆盖首事件前后故障、默认五次预算、SSE 降级状态、连接缓存更新、取消、认证失败、丢弃失败文本和工具只执行一次。
43
+ - `node scripts/verify-network-settings-ui.mjs <output-directory>`:在已有 Harness 开发环境中使用 React DOM 和 `~/.codex/playwright-runtime` 的固定浏览器。测试真实设置组件与构建后的 API,覆盖保存/重新加载、冲突保护、输入校验、账户加载失败和明暗/窄屏显示。不是现用 DSH 的安装验收。
44
+
45
+ 这些检查不读取真实 OAuth 密钥,不调用真实模型,也不证明某个用户的代理节点或上游服务此刻可用。安装后仍需核对实际 Host 加载版本,再做一次经用户允许的真实调用。