webaiapi 0.0.0-stage → 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 (205) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +184 -2
  3. package/bin/webapi.mjs +45 -0
  4. package/dist/browser/auth-capture.d.ts +110 -0
  5. package/dist/browser/auth-capture.d.ts.map +1 -0
  6. package/dist/browser/auth-capture.js +487 -0
  7. package/dist/browser/auth-capture.js.map +1 -0
  8. package/dist/browser/credentials.d.ts +102 -0
  9. package/dist/browser/credentials.d.ts.map +1 -0
  10. package/dist/browser/credentials.js +209 -0
  11. package/dist/browser/credentials.js.map +1 -0
  12. package/dist/browser/js-eval.d.ts +44 -0
  13. package/dist/browser/js-eval.d.ts.map +1 -0
  14. package/dist/browser/js-eval.js +20 -0
  15. package/dist/browser/js-eval.js.map +1 -0
  16. package/dist/browser/login-flow.d.ts +171 -0
  17. package/dist/browser/login-flow.d.ts.map +1 -0
  18. package/dist/browser/login-flow.js +606 -0
  19. package/dist/browser/login-flow.js.map +1 -0
  20. package/dist/browser/manager.d.ts +144 -0
  21. package/dist/browser/manager.d.ts.map +1 -0
  22. package/dist/browser/manager.js +586 -0
  23. package/dist/browser/manager.js.map +1 -0
  24. package/dist/browser/platforms.d.ts +96 -0
  25. package/dist/browser/platforms.d.ts.map +1 -0
  26. package/dist/browser/platforms.js +288 -0
  27. package/dist/browser/platforms.js.map +1 -0
  28. package/dist/browser/sse-capture.d.ts +23 -0
  29. package/dist/browser/sse-capture.d.ts.map +1 -0
  30. package/dist/browser/sse-capture.js +199 -0
  31. package/dist/browser/sse-capture.js.map +1 -0
  32. package/dist/browser/stealth.d.ts +12 -0
  33. package/dist/browser/stealth.d.ts.map +1 -0
  34. package/dist/browser/stealth.js +12 -0
  35. package/dist/browser/stealth.js.map +1 -0
  36. package/dist/cli.d.ts +12 -0
  37. package/dist/cli.d.ts.map +1 -0
  38. package/dist/cli.js +441 -0
  39. package/dist/cli.js.map +1 -0
  40. package/dist/config.d.ts +90 -0
  41. package/dist/config.d.ts.map +1 -0
  42. package/dist/config.js +246 -0
  43. package/dist/config.js.map +1 -0
  44. package/dist/controllers/history-db.d.ts +56 -0
  45. package/dist/controllers/history-db.d.ts.map +1 -0
  46. package/dist/controllers/history-db.js +260 -0
  47. package/dist/controllers/history-db.js.map +1 -0
  48. package/dist/controllers/request-pool.d.ts +78 -0
  49. package/dist/controllers/request-pool.d.ts.map +1 -0
  50. package/dist/controllers/request-pool.js +222 -0
  51. package/dist/controllers/request-pool.js.map +1 -0
  52. package/dist/controllers/router.d.ts +172 -0
  53. package/dist/controllers/router.d.ts.map +1 -0
  54. package/dist/controllers/router.js +569 -0
  55. package/dist/controllers/router.js.map +1 -0
  56. package/dist/index.d.ts +72 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +61 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/log/api-logger.d.ts +55 -0
  61. package/dist/log/api-logger.d.ts.map +1 -0
  62. package/dist/log/api-logger.js +264 -0
  63. package/dist/log/api-logger.js.map +1 -0
  64. package/dist/log/debug-logger.d.ts +49 -0
  65. package/dist/log/debug-logger.d.ts.map +1 -0
  66. package/dist/log/debug-logger.js +285 -0
  67. package/dist/log/debug-logger.js.map +1 -0
  68. package/dist/log/logger.d.ts +16 -0
  69. package/dist/log/logger.d.ts.map +1 -0
  70. package/dist/log/logger.js +35 -0
  71. package/dist/log/logger.js.map +1 -0
  72. package/dist/postinstall.d.ts +3 -0
  73. package/dist/postinstall.d.ts.map +1 -0
  74. package/dist/postinstall.js +90 -0
  75. package/dist/postinstall.js.map +1 -0
  76. package/dist/providers/base.d.ts +83 -0
  77. package/dist/providers/base.d.ts.map +1 -0
  78. package/dist/providers/base.js +51 -0
  79. package/dist/providers/base.js.map +1 -0
  80. package/dist/providers/chatglm-dom-extract.d.ts +24 -0
  81. package/dist/providers/chatglm-dom-extract.d.ts.map +1 -0
  82. package/dist/providers/chatglm-dom-extract.js +175 -0
  83. package/dist/providers/chatglm-dom-extract.js.map +1 -0
  84. package/dist/providers/chatglm-dom.d.ts +110 -0
  85. package/dist/providers/chatglm-dom.d.ts.map +1 -0
  86. package/dist/providers/chatglm-dom.js +384 -0
  87. package/dist/providers/chatglm-dom.js.map +1 -0
  88. package/dist/providers/chatglm-sse.d.ts +119 -0
  89. package/dist/providers/chatglm-sse.d.ts.map +1 -0
  90. package/dist/providers/chatglm-sse.js +241 -0
  91. package/dist/providers/chatglm-sse.js.map +1 -0
  92. package/dist/providers/chatglm.d.ts +288 -0
  93. package/dist/providers/chatglm.d.ts.map +1 -0
  94. package/dist/providers/chatglm.js +1631 -0
  95. package/dist/providers/chatglm.js.map +1 -0
  96. package/dist/routes/chat.d.ts +117 -0
  97. package/dist/routes/chat.d.ts.map +1 -0
  98. package/dist/routes/chat.js +1346 -0
  99. package/dist/routes/chat.js.map +1 -0
  100. package/dist/routes/compress.d.ts +142 -0
  101. package/dist/routes/compress.d.ts.map +1 -0
  102. package/dist/routes/compress.js +551 -0
  103. package/dist/routes/compress.js.map +1 -0
  104. package/dist/routes/failover.d.ts +34 -0
  105. package/dist/routes/failover.d.ts.map +1 -0
  106. package/dist/routes/failover.js +221 -0
  107. package/dist/routes/failover.js.map +1 -0
  108. package/dist/routes/helpers.d.ts +174 -0
  109. package/dist/routes/helpers.d.ts.map +1 -0
  110. package/dist/routes/helpers.js +525 -0
  111. package/dist/routes/helpers.js.map +1 -0
  112. package/dist/routes/meta.d.ts +31 -0
  113. package/dist/routes/meta.d.ts.map +1 -0
  114. package/dist/routes/meta.js +184 -0
  115. package/dist/routes/meta.js.map +1 -0
  116. package/dist/routes/sse.d.ts +82 -0
  117. package/dist/routes/sse.d.ts.map +1 -0
  118. package/dist/routes/sse.js +77 -0
  119. package/dist/routes/sse.js.map +1 -0
  120. package/dist/server/app.d.ts +24 -0
  121. package/dist/server/app.d.ts.map +1 -0
  122. package/dist/server/app.js +292 -0
  123. package/dist/server/app.js.map +1 -0
  124. package/dist/server/middleware/api-key.d.ts +61 -0
  125. package/dist/server/middleware/api-key.d.ts.map +1 -0
  126. package/dist/server/middleware/api-key.js +95 -0
  127. package/dist/server/middleware/api-key.js.map +1 -0
  128. package/dist/server/middleware/rate-limit.d.ts +67 -0
  129. package/dist/server/middleware/rate-limit.d.ts.map +1 -0
  130. package/dist/server/middleware/rate-limit.js +134 -0
  131. package/dist/server/middleware/rate-limit.js.map +1 -0
  132. package/dist/server/middleware/timeout.d.ts +34 -0
  133. package/dist/server/middleware/timeout.d.ts.map +1 -0
  134. package/dist/server/middleware/timeout.js +64 -0
  135. package/dist/server/middleware/timeout.js.map +1 -0
  136. package/dist/server/types.d.ts +20 -0
  137. package/dist/server/types.d.ts.map +1 -0
  138. package/dist/server/types.js +2 -0
  139. package/dist/server/types.js.map +1 -0
  140. package/dist/tools/build.d.ts +14 -0
  141. package/dist/tools/build.d.ts.map +1 -0
  142. package/dist/tools/build.js +105 -0
  143. package/dist/tools/build.js.map +1 -0
  144. package/dist/tools/clean.d.ts +32 -0
  145. package/dist/tools/clean.d.ts.map +1 -0
  146. package/dist/tools/clean.js +65 -0
  147. package/dist/tools/clean.js.map +1 -0
  148. package/dist/tools/convert.d.ts +50 -0
  149. package/dist/tools/convert.d.ts.map +1 -0
  150. package/dist/tools/convert.js +289 -0
  151. package/dist/tools/convert.js.map +1 -0
  152. package/dist/tools/names.d.ts +138 -0
  153. package/dist/tools/names.d.ts.map +1 -0
  154. package/dist/tools/names.js +578 -0
  155. package/dist/tools/names.js.map +1 -0
  156. package/dist/tools/parse.d.ts +31 -0
  157. package/dist/tools/parse.d.ts.map +1 -0
  158. package/dist/tools/parse.js +273 -0
  159. package/dist/tools/parse.js.map +1 -0
  160. package/dist/tools/placeholder.d.ts +21 -0
  161. package/dist/tools/placeholder.d.ts.map +1 -0
  162. package/dist/tools/placeholder.js +135 -0
  163. package/dist/tools/placeholder.js.map +1 -0
  164. package/dist/tools/prompts.d.ts +42 -0
  165. package/dist/tools/prompts.d.ts.map +1 -0
  166. package/dist/tools/prompts.js +69 -0
  167. package/dist/tools/prompts.js.map +1 -0
  168. package/dist/tools/protocol.d.ts +58 -0
  169. package/dist/tools/protocol.d.ts.map +1 -0
  170. package/dist/tools/protocol.js +287 -0
  171. package/dist/tools/protocol.js.map +1 -0
  172. package/dist/tools/repair.d.ts +83 -0
  173. package/dist/tools/repair.d.ts.map +1 -0
  174. package/dist/tools/repair.js +510 -0
  175. package/dist/tools/repair.js.map +1 -0
  176. package/dist/tools/workspace.d.ts +40 -0
  177. package/dist/tools/workspace.d.ts.map +1 -0
  178. package/dist/tools/workspace.js +224 -0
  179. package/dist/tools/workspace.js.map +1 -0
  180. package/dist/types/message.d.ts +87 -0
  181. package/dist/types/message.d.ts.map +1 -0
  182. package/dist/types/message.js +85 -0
  183. package/dist/types/message.js.map +1 -0
  184. package/dist/types/openai.d.ts +100 -0
  185. package/dist/types/openai.d.ts.map +1 -0
  186. package/dist/types/openai.js +66 -0
  187. package/dist/types/openai.js.map +1 -0
  188. package/dist/utils/errors.d.ts +82 -0
  189. package/dist/utils/errors.d.ts.map +1 -0
  190. package/dist/utils/errors.js +115 -0
  191. package/dist/utils/errors.js.map +1 -0
  192. package/dist/utils/mutex.d.ts +31 -0
  193. package/dist/utils/mutex.d.ts.map +1 -0
  194. package/dist/utils/mutex.js +61 -0
  195. package/dist/utils/mutex.js.map +1 -0
  196. package/dist/utils/prompt.d.ts +150 -0
  197. package/dist/utils/prompt.d.ts.map +1 -0
  198. package/dist/utils/prompt.js +514 -0
  199. package/dist/utils/prompt.js.map +1 -0
  200. package/dist/utils/text.d.ts +30 -0
  201. package/dist/utils/text.d.ts.map +1 -0
  202. package/dist/utils/text.js +70 -0
  203. package/dist/utils/text.js.map +1 -0
  204. package/package.json +67 -4
  205. package/postinstall.mjs +34 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 webaiapi contributors
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 CHANGED
@@ -1,3 +1,185 @@
1
- # Temporary Holding Version
1
+ # webaiapi(命令名:`webapi`)
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ 把国产 AI 聊天网页(目前支持 **ChatGLM / 智谱清言**)包装成 **OpenAI 兼容 API**。
4
+ 纯浏览器自动化(Playwright Firefox),**不需要 API Key、不需要逆向签名**——你只要在浏览器里登录一次。
5
+
6
+ 用它可以在任何支持 OpenAI 协议的客户端(CodeBuddy、Trae、Cursor、各类 SDK)里,
7
+ 直接使用你的网页端账号额度。
8
+
9
+ ---
10
+
11
+ ## 安装
12
+
13
+ ```bash
14
+ npm i -g webaiapi
15
+ ```
16
+
17
+ 安装时会**自动下载 Playwright Firefox**(约 80MB,只需一次)。
18
+ 若你的环境禁用了安装脚本(`--ignore-scripts`)或被网络策略拦住,
19
+ 手动补一条即可:
20
+
21
+ ```bash
22
+ npx playwright install firefox
23
+ ```
24
+
25
+ 然后登录并捕获凭证(会打开可见的浏览器,你手动登录):
26
+
27
+ ```bash
28
+ webapi login
29
+ ```
30
+
31
+ 不加参数会**交互式**让你选平台(`↑/↓` + 回车,或直接敲编号),随后选「添加账号 / 重新登录」。
32
+ 想跳过菜单就直接给平台名:`webapi login chatglm`。
33
+
34
+ > 不确定环境有没有问题?先跑一次自检:
35
+
36
+ ```bash
37
+ webapi doctor
38
+ ```
39
+
40
+ 它会检查 Node 版本、Firefox 二进制、凭证、端口,并给出可复制的修复命令。
41
+
42
+ > **跳过自动下载**:设 `WEBAIAPI_SKIP_BROWSER_INSTALL=1`(或用 Playwright 自己的
43
+ > `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1`)。CI 里常用。
44
+
45
+ ## 启动
46
+
47
+ ```bash
48
+ webapi start
49
+ ```
50
+
51
+ 服务默认监听 `http://0.0.0.0:8631`,OpenAI 兼容端点在 `/v1`:
52
+
53
+ ```bash
54
+ # 健康检查
55
+ curl -s http://localhost:8631/v1/health
56
+
57
+ # 对话(非流式)
58
+ curl -s -X POST http://localhost:8631/v1/chat/completions \
59
+ -H 'Content-Type: application/json' \
60
+ -d '{"model":"chatglm","messages":[{"role":"user","content":"你好"}]}'
61
+
62
+ # 流式
63
+ curl -N -X POST http://localhost:8631/v1/chat/completions \
64
+ -H 'Content-Type: application/json' \
65
+ -d '{"model":"chatglm","messages":[{"role":"user","content":"你好"}],"stream":true}'
66
+ ```
67
+
68
+ 在客户端里配置基址 `http://localhost:8631/v1`,API Key 随便填(未启用校验时),
69
+ 模型名填 `chatglm` 或 `mix`。
70
+
71
+ ## 命令
72
+
73
+ | 命令 | 说明 |
74
+ |---|---|
75
+ | `webapi start` | 启动服务(前台运行,Ctrl-C 退出) |
76
+ | `webapi doctor` | 自检:Node / Firefox / 凭证 / 端口 |
77
+ | `webapi status` | 运行状态:账号、角色、辅助通道、请求池 |
78
+ | `webapi accounts` | 只看账号与角色(判断「多账号有没有生效」的权威视图) |
79
+ | `webapi health` | 各平台登录状态 |
80
+ | `webapi login [<platform>] [--account <id>]` | 登录并捕获凭证(不给参数则交互式选择平台/账号) |
81
+ | `webapi logout [<platform>] [--account <id>]` | 删除某账号的凭证(不给参数则交互式选择) |
82
+
83
+ 脚本 / CI 里用非交互写法(`--yes` 跳过确认):
84
+
85
+ ```bash
86
+ webapi login chatglm --account acc2 --yes
87
+ webapi logout chatglm --account acc2 --yes
88
+ ```
89
+
90
+ ## 模型
91
+
92
+ | 模型名 | 说明 |
93
+ |---|---|
94
+ | `mix` | 自动选择可用平台(当前即 chatglm) |
95
+ | `chatglm` | 平台名模型,只跨账号、不跨平台 |
96
+ | `glm-4` / `glm-3` | ChatGLM 的具体模型别名 |
97
+
98
+ ## 多账号(可选,但推荐)
99
+
100
+ 加第二个账号后,服务会启用**辅助通道**:压缩历史/工具调用转换等辅助任务
101
+ 会在另一个账号的独立页面上跑,与你的主对话**真正并行**,不再排队。
102
+
103
+ 再跑一次 `webapi login` 选「添加新账号」即可,**账号名会自动从登录身份派生**
104
+ (用户名 → uid),不用自己想名字:
105
+
106
+ ```bash
107
+ webapi login
108
+ # 要登录哪个平台? → ChatGLM (智谱)
109
+ # 这次要做什么? → ➕ 添加新账号
110
+ # ...手动登录另一个账号...
111
+ # ✔ 凭证已保存 账号: alice
112
+ ```
113
+
114
+ 选错了随时可以退:二级菜单里有 `← 返回上一步(重新选平台)`,
115
+ 平台菜单里有 `✗ 退出`;任何时候按 `Esc` / `Ctrl+C` 也会取消。
116
+ (用 `webapi login <platform>` 明确指定平台时,菜单里给的是 `✗ 取消` —— 没有上一步可回。)
117
+
118
+ > ⚠️ **两个账号必须是不同的人。** 系统浏览器很可能还留着上一个账号的登录态,
119
+ > 抓到同一个人时服务会以为「有两个账号」并启用并行,结果两边打同一个账号,
120
+ > 立刻收到「请等待其他对话生成完毕」。所以服务会**校验身份与 Cookie**:
121
+ > - 抓到的和已有账号是同一个登录态 → 提示你选择「更新该账号 / 另存为新账号 / 取消」
122
+ > - 非交互时(脚本)默认**更新原账号**,绝不悄悄多出一个重名账号
123
+
124
+ 用 `webapi accounts` 核对身份与角色分配。主/辅角色**启动时随机分配**以摊平额度消耗;
125
+ 需要钉死时用环境变量:
126
+
127
+ ```bash
128
+ CHATGLM_MAIN_ACCOUNT=acc2 webapi start
129
+ ```
130
+
131
+ ## 配置
132
+
133
+ 放在项目目录的 `.env`,或直接用环境变量:
134
+
135
+ | 变量 | 默认 | 说明 |
136
+ |---|---|---|
137
+ | `API_HOST` / `API_PORT` | `0.0.0.0` / `8631` | 监听地址与端口 |
138
+ | `API_PREFIX` | `/v1` | 路由前缀 |
139
+ | `REQUEST_TIMEOUT` | `300` | 请求超时(秒) |
140
+ | `RATE_LIMIT_ENABLED` | `false` | 是否限流 |
141
+ | `RATE_LIMIT_PER_MINUTE` | `60` | 每客户端每分钟请求数 |
142
+ | `API_KEYS` | 空 | 逗号分隔的密钥列表 |
143
+ | `API_KEY_REQUIRED` | `false` | 是否**强制**校验(配了密钥才生效) |
144
+ | `DEBUG_LOGS` | `false` | 是否写 `~/.ai-api/logs/debug_*.log` |
145
+ | `AUTH_DIR` | `~/.ai-api/auth` | 凭证目录 |
146
+ | `LOG_DIR` | `logs` | 运行日志与 API 记录目录 |
147
+ | `CHATGLM_MAIN_ACCOUNT` | 随机 | 钉死主通道账号 |
148
+ | `BROWSER_HEADLESS` | 见实现 | `true` 时无头运行(服务器部署用) |
149
+ | `WEBAIAPI_SKIP_BROWSER_INSTALL` | — | 设 1 跳过安装期的浏览器下载 |
150
+
151
+ 凭证、历史数据库、调试日志都在 `~/.ai-api/` 下。
152
+
153
+ ## 常见问题
154
+
155
+ **「请求过于频繁,请稍后再试」**
156
+ 多半是**未登录**(访客额度用完了)。重新登录:`webapi login chatglm`。
157
+
158
+ **抓到的账号不是我想登的那个**
159
+ 系统浏览器里往往还留着上一个账号的登录态。先在该页面**退出登录**,再登目标账号。
160
+
161
+ **第一次对话很慢(20s+)**
162
+ 首次需要启动浏览器 + 导航 + 探测登录态。之后同会话会复用页面,
163
+ 准备阶段降到 0~3s。
164
+
165
+ **任务跑一半停了、文件没改**
166
+ 网页端模型有时会「只写计划不调工具」。服务会自动再驱动一轮;
167
+ 若仍反复出现,把任务拆小一点(例如一次只让它改一个文件)。
168
+
169
+ **怎么看到底发生了什么**
170
+ - `logs/api_requests.log` —— 请求/响应**原样记录、不做加工**,每次启动重置
171
+ - `logs/chatglm_sse_last.txt` —— 最近一轮的原始 SSE 报文(排查上游格式变化)
172
+
173
+ ## 开发
174
+
175
+ ```bash
176
+ npm install # 会自动 build(package.json 的 prepare 脚本)
177
+ npm run dev # 直接跑 tsx src/cli.ts,不用先构建
178
+ npm run typecheck
179
+ npm test # 326 个单测
180
+ npm run build # 产出 dist/
181
+ ```
182
+
183
+ ## 许可
184
+
185
+ MIT
package/bin/webapi.mjs ADDED
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `webapi` 的可执行入口(`bin` 指向这里)。
4
+ *
5
+ * ## 为什么不让 `bin` 直接指向 `dist/cli.js`
6
+ * `dist/` 是**构建产物且被 .gitignore 忽略**。全新 clone 之后、或通过
7
+ * `npm i github:<user>/<repo>` 安装时,`dist/` 可能根本不存在。此时若 bin 直接
8
+ * 指向它,用户看到的是 shell 的原始报错:
9
+ *
10
+ * ```
11
+ * /bin/bash: 行 1: /usr/local/bin/webapi: 没有那个文件或目录
12
+ * ```
13
+ *
14
+ * —— 既没说"没构建",也没说该怎么办。(实测确认过。)
15
+ *
16
+ * 所以这里放一个**提交进版本库**的薄入口:它永远存在,`dist/` 缺失时给出
17
+ * 可执行的提示。`bin/` 也是大家约定俗成会去找入口的位置。
18
+ *
19
+ * ## ⚠️ 为什么要显式调用 `runCli()`,而不是只 import
20
+ * `dist/cli.js` 里有一个「是否被直接执行」的守卫(比较 `process.argv[1]` 与
21
+ * `import.meta.url` 的 realpath)。经本文件 import 时,`argv[1]` 是
22
+ * `.../bin/webapi.mjs` 而 `import.meta.url` 是 `.../dist/cli.js` —— **两者不等**,
23
+ * 守卫会判定"不是直接执行"从而**什么都不做**(静默失效,最难查的一类 bug)。
24
+ * 因此这里必须显式调用导出的 `runCli()`。
25
+ */
26
+ import { existsSync } from 'node:fs';
27
+ import { dirname, join } from 'node:path';
28
+ import { fileURLToPath, pathToFileURL } from 'node:url';
29
+
30
+ const here = dirname(fileURLToPath(import.meta.url));
31
+ const cliPath = join(here, '..', 'dist', 'cli.js');
32
+
33
+ if (!existsSync(cliPath)) {
34
+ console.error(
35
+ '[webapi] 还没有构建,找不到 dist/cli.js。\n' +
36
+ ' 请先运行: npm run build\n' +
37
+ ' (若你是 clone 下来做开发的:npm install 会自动构建,\n' +
38
+ ' 该步骤由 package.json 的 `prepare` 脚本触发。)',
39
+ );
40
+ process.exit(1);
41
+ }
42
+
43
+ // 显式调用,不依赖 cli.js 内部的「直接执行」守卫(原因见文件头注释)
44
+ const { runCli } = await import(pathToFileURL(cliPath).href);
45
+ process.exitCode = await runCli();
@@ -0,0 +1,110 @@
1
+ import { type AccountInfo, type AuthRecord } from './credentials.js';
2
+ /** 捕获到的凭证(写入文件的形状)。 */
3
+ export interface CapturedAuth extends AuthRecord {
4
+ cookies?: AuthRecord['cookies'];
5
+ cookie_str?: string;
6
+ bearer?: string;
7
+ user_agent?: string;
8
+ captured_at?: number;
9
+ platform?: string;
10
+ account_info?: AccountInfo;
11
+ sample_requests?: Array<Record<string, unknown>>;
12
+ }
13
+ /**
14
+ * 调用平台 user info API 丰富账号信息(捕获后立即调用)。
15
+ *
16
+ * 失败时返回同步提取的结果({@link extractAccountInfoSync})。
17
+ *
18
+ * ⚠️ `platform === 'chatglm'` **直接短路**:它的 JWT 里已经含用户名,
19
+ * 而调它的 user info API 需要 `x-sign` 签名(我们没有)。
20
+ */
21
+ export declare function fetchAccountInfo(platform: string, auth: AuthRecord): Promise<AccountInfo>;
22
+ export interface AuthCaptureOptions {
23
+ authDir?: string;
24
+ /** 是否无头。凭证捕获**建议 false**(用户需要看到浏览器才能登录)。 */
25
+ headless?: boolean;
26
+ /** 捕获超时(秒)。目前仅用于提示,实际由用户的 Enter 决定。 */
27
+ captureTimeout?: number;
28
+ /** 账号 ID(同平台多账号)。 */
29
+ accountId?: string;
30
+ /**
31
+ * 捕获结束后是否**立即落盘**(默认 `true`)。
32
+ *
33
+ * 交互式流程(`login-flow.ts`)传 `false`:它要先看捕获到的**身份**、
34
+ * 问用户「这份凭证存成哪个账号」,再调 {@link AuthCapture.saveAs} 写。
35
+ * 若照旧立即写,就会先落一个 `__new__<ts>.json` 再改名 —— 中途崩溃会留下
36
+ * 一个「看起来像账号文件」的残骸(`listAccounts` 跳过它,但人肉 ls 会看到)。
37
+ */
38
+ saveOnCapture?: boolean;
39
+ }
40
+ export declare class AuthCapture {
41
+ readonly platform: string;
42
+ private readonly authDir;
43
+ /** 用户传入的 `authDir`(`saveAs()` 重算路径时要原样带上)。 */
44
+ private readonly authDirOption;
45
+ private readonly saveOnCapture;
46
+ private _accountId;
47
+ private _authFile;
48
+ private readonly headless;
49
+ private readonly captureTimeout;
50
+ private apiConfig;
51
+ private browser;
52
+ private context;
53
+ private page;
54
+ readonly capturedAuth: CapturedAuth;
55
+ constructor(platform: string, options?: AuthCaptureOptions);
56
+ /** 当前账号 ID(`saveAs()` 会改写它,调用方不要缓存)。 */
57
+ get accountId(): string;
58
+ /** 当前目标文件路径(随 `saveAs()` 变化)。 */
59
+ get authFile(): string;
60
+ /** 启动浏览器、引导用户登录、抓取凭证并落盘。 */
61
+ capture(): Promise<CapturedAuth>;
62
+ /** 请求回调:抓 bearer / 额外请求头 / 样本请求。 */
63
+ private onRequest;
64
+ /** 抓 cookies 与 User-Agent。 */
65
+ private captureCookiesAndUa;
66
+ /**
67
+ * 保存凭证。
68
+ *
69
+ * 三重保护(避免「重登把另一个账号冲掉」这个最常见的损失):
70
+ * 1. 已有文件先备份为 `.bak`;
71
+ * 2. 先写临时文件再 `rename`(原子替换,中途崩溃不会留下半截 JSON);
72
+ * 3. 权限设为 0600(仅所有者可读写)。
73
+ */
74
+ private saveAuth;
75
+ /**
76
+ * 以指定账号 ID 落盘(交互式流程在「拿到身份、确认账号名」之后调用)。
77
+ *
78
+ * 复用 {@link saveAuth} 的三重保护(备份 `.bak` → 临时文件 → 原子 rename → 0600),
79
+ * 所以覆盖旧账号时同样是安全的。
80
+ *
81
+ * ⚠️ `accountId` 会被**当成文件名**使用,必须校验:它可能来自平台返回的身份
82
+ * 字符串(`slugAccountId` 已经清洗过一道),但这里是最后一道闸 ——
83
+ * 不能让 `../` 之类的东西写出去。
84
+ *
85
+ * @returns 最终写入的文件路径
86
+ */
87
+ saveAs(accountId: string): string;
88
+ /**
89
+ * 账号 ID 能不能当文件名用。
90
+ *
91
+ * 分两档,**不能合并成一条严格正则**:
92
+ * 1. **硬性禁止**:`/` `\` NUL、空串、`.`、`..` —— 这条对「新账号」和
93
+ * 「更新已有账号」都成立(防路径穿越)。
94
+ * 2. **严格字符集**(字母数字 `._-`):只用来约束**新**账号名。
95
+ * 3. **放宽**:名字**已经存在于磁盘**时允许任意其它字符 —— 真实用户目录里
96
+ * 就有 `用户_bFa15b` 这种(早期手工登录留下的),用严格正则会把
97
+ * 「重新登录这个账号」直接判成非法,用户只能删号重登。
98
+ * 安全性由 `listAccounts` 保证:它的值来自 `readdirSync`,是普通文件名。
99
+ */
100
+ private isAcceptableAccountId;
101
+ /** 清理浏览器资源。 */
102
+ private cleanup;
103
+ }
104
+ /**
105
+ * 交互式捕获入口(CLI 的 `login` 命令调用)。
106
+ *
107
+ * @returns 进程退出码(0 成功)
108
+ */
109
+ export declare function capturePlatformAuth(platform: string, accountId?: string): Promise<number>;
110
+ //# sourceMappingURL=auth-capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-capture.d.ts","sourceRoot":"","sources":["../../src/browser/auth-capture.ts"],"names":[],"mappings":"AA2BA,OAAO,EAKL,KAAK,WAAW,EAChB,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAC;AAW1B,uBAAuB;AACvB,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C,OAAO,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,eAAe,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAClD;AAiBD;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAuF/F;AAMD,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uCAAuC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qBAAqB;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,qBAAa,WAAW;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,8CAA8C;IAC9C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IAEnD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IAExC,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IAEnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAExC,OAAO,CAAC,SAAS,CAAqD;IAEtE,OAAO,CAAC,OAAO,CAAwB;IAEvC,OAAO,CAAC,OAAO,CAA+B;IAE9C,OAAO,CAAC,IAAI,CAAqB;IAEjC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAM;IAEzC,YAAY,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,EA8B7D;IAED,wCAAwC;IACxC,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,iCAAiC;IACjC,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,4BAA4B;IACtB,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC,CAqErC;IAED,oCAAoC;YACtB,SAAS;IAsEvB,8BAA8B;YAChB,mBAAmB;IAoBjC;;;;;;;OAOG;IACH,OAAO,CAAC,QAAQ;IA4BhB;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAYhC;IAED;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,qBAAqB;IAQ7B,eAAe;YACD,OAAO;CAYtB;AAMD;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,SAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAmClG"}