dsh-deepseek-web-login 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-deepseek-web-login",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Unofficial DSH plugin: use chat.deepseek.com web models as a DSH LLM provider (browser login capture + PoW solving + SSE streaming + prompting-based tool calls), provider route deepseek-web",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -0,0 +1,232 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * 面板预览 —— 从 `src/client/index.ts` 抽出样式表,套进一份静态 DOM 快照,
4
+ * 生成可直接用浏览器打开的「浅色 / 深色」双栏预览。
5
+ *
6
+ * 用途:改面板 UI 时不必启动 DSH 就能看到真实效果。样式**每次从源码现读**,
7
+ * 所以预览不会跟源码漂移(不存在"两份真相")。
8
+ *
9
+ * node tools/panel-preview.mjs [输出路径]
10
+ *
11
+ * 默认输出到系统临时目录,打印出绝对路径。
12
+ * 注意:DOM 快照是手写的**结构代表**(覆盖面板里出现的每一类元素),
13
+ * 不是真实渲染结果 —— 它服务于"看排版/间距/状态",不负责验证功能。
14
+ */
15
+ import { readFileSync, writeFileSync } from 'node:fs'
16
+ import { dirname, join, resolve } from 'node:path'
17
+ import { fileURLToPath } from 'node:url'
18
+ import { tmpdir } from 'node:os'
19
+
20
+ const ROOT = dirname(dirname(fileURLToPath(import.meta.url)))
21
+ const src = readFileSync(join(ROOT, 'src', 'client', 'index.ts'), 'utf8')
22
+
23
+ const styleMatch = src.match(/const styles = `([\s\S]*?)`/)
24
+ if (!styleMatch) {
25
+ console.error('未能从 src/client/index.ts 抽出 styles 常量(正则没匹配上,检查它是否被改名/改写成非模板字符串)')
26
+ process.exit(1)
27
+ }
28
+ const styles = styleMatch[1]
29
+
30
+ // 暗色兜底变量藏在 prefers-color-scheme 里;预览需要手动应用到右栏,所以提出来复用。
31
+ const darkMatch = styles.match(/@media \(prefers-color-scheme:dark\)\{\s*\.dsw-page\{([^}]*)\}\s*\}/)
32
+ if (!darkMatch) {
33
+ console.error('未找到 prefers-color-scheme 的暗色兜底段')
34
+ process.exit(1)
35
+ }
36
+ const darkVars = darkMatch[1].trim()
37
+
38
+ /** 模拟宿主令牌 —— 预览用。真实值由 DSH 注入,这里只求观感接近。 */
39
+ const hostLight = `
40
+ --dsw-alias-label-primary:#1f2329;--dsw-alias-label-secondary:#5c636e;--dsw-alias-label-tertiary:#8f96a3;
41
+ --dsw-alias-bg-layer-1:#f4f5f7;--dsw-alias-bg-layer-2:#ffffff;
42
+ --dsw-alias-border-l1:#e7e9ed;--dsw-alias-border-l2:#d5d8de;
43
+ --dsw-alias-interactive-bg-hover:rgba(15,23,42,.055);
44
+ --dsw-alias-markdown-code-block:#f2f3f5;
45
+ --dsw-alias-brand-primary:#4a6cf7;--dsw-alias-state-success-primary:#159a55;
46
+ --dsw-alias-state-warn-label:#a06a00;--dsw-alias-state-error-primary:#d93a2b;`
47
+
48
+ const hostDark = `
49
+ --dsw-alias-label-primary:#e9eaec;--dsw-alias-label-secondary:#a8aeb8;--dsw-alias-label-tertiary:#767d88;
50
+ --dsw-alias-bg-layer-1:#1d1d1f;--dsw-alias-bg-layer-2:#262628;
51
+ --dsw-alias-border-l1:#333438;--dsw-alias-border-l2:#424347;
52
+ --dsw-alias-interactive-bg-hover:rgba(255,255,255,.07);
53
+ --dsw-alias-markdown-code-block:#1a1a1c;
54
+ --dsw-alias-brand-primary:#5b7cfa;--dsw-alias-state-success-primary:#3fbf76;
55
+ --dsw-alias-state-warn-label:#d8a13a;--dsw-alias-state-error-primary:#f0665a;`
56
+
57
+ const kv = (...pairs) =>
58
+ `<div class="dsw-kv">${pairs.map(([k, v]) => `<div class="k">${k}</div><div>${v}</div>`).join('')}</div>`
59
+
60
+ const spark = `<svg class="dsw-spark" viewBox="0 0 320 40" preserveAspectRatio="none">${Array.from(
61
+ { length: 40 },
62
+ (_, i) => `<rect x="${i * 8}" y="${40 - (8 + ((i * 7) % 26))}" width="5" height="${8 + ((i * 7) % 26)}"${i % 11 === 3 ? ' class="bad"' : i % 5 === 0 ? ' class="on"' : ''}></rect>`
63
+ ).join('')}</svg>`
64
+
65
+ /** DOM 快照 —— 覆盖面板里出现的每一类元素,顺序贴近真实页面。 */
66
+ const demo = `
67
+ <div class="dsw-page">
68
+ <h1 class="dsw-title">DeepSeek 网页登录(免费模型)</h1>
69
+ <p class="dsw-sub">用 <span class="dsw-nobreak">chat.deepseek.com</span> 网页版登录态驱动 DSH agent —— 不需要 API Key。provider 路由:<span class="dsw-nobreak">deepseek-web</span></p>
70
+
71
+ <div class="dsw-alert ok">已保存「请求间隔」设置</div>
72
+
73
+ <div class="dsw-tabs">
74
+ <button class="dsw-tab active">账号</button><button class="dsw-tab">模型</button>
75
+ <button class="dsw-tab">防风控</button><button class="dsw-tab">传输层</button>
76
+ <button class="dsw-tab">上下文</button><button class="dsw-tab">关于</button>
77
+ </div>
78
+
79
+ <div class="dsw-subtabs">
80
+ <button class="dsw-subtab active">登录</button><button class="dsw-subtab">账号库</button>
81
+ </div>
82
+
83
+ <div class="dsw-card">
84
+ <div class="dsw-cardhead">登录状态 <span class="dsw-badge on">已捕获(未校验)</span></div>
85
+ ${kv(
86
+ ['适配器注册', '✅ deepseek-web 已注册到 llm'],
87
+ ['账号', '143******@qq.com'],
88
+ ['捕获时间', '2026/9/11 11:08:35'],
89
+ ['凭证来源', '浏览器登录捕获(token + cookie + 指纹头,登录态通常更耐久)'],
90
+ ['Cookie', '✅ 已捕获'],
91
+ ['指纹头', '未捕获 —— 同上,已实测可用'],
92
+ ['token 长度', '64 字符'],
93
+ ['服务端校验', '通过']
94
+ )}
95
+ <div class="dsw-row" style="margin-top:10px">
96
+ <button class="dsw-btn">用 Microsoft Edge 登录</button>
97
+ <button class="dsw-btn ghost">用我的默认浏览器登录</button>
98
+ <button class="dsw-btn ghost">从已登录窗口恢复</button>
99
+ </div>
100
+ <div class="dsw-row" style="margin-top:8px"><button class="dsw-btn ghost">刷新状态</button></div>
101
+ <p class="dsw-hint">「用我的默认浏览器登录」= 用系统浏览器打开 chat.deepseek.com(网页端若提示「使用环境异常」,走这条)。外部浏览器的登录态插件抓不到,要用 F12 控制台取 token 粘到下面那张卡。</p>
102
+ </div>
103
+
104
+ <div class="dsw-card">
105
+ <div class="dsw-cardhead">当前账号</div>
106
+ ${kv(['账号', '143******@qq.com'], ['登录时间', '2026/9/11 11:08:35'])}
107
+ <div class="dsw-row" style="margin-top:10px">
108
+ <button class="dsw-btn danger armed">确认退出?</button>
109
+ <button class="dsw-btn ghost" disabled>退出并登录其它账号</button>
110
+ </div>
111
+ <p class="dsw-hint">退出会同时清除本地凭证与浏览器分区里的 chat.deepseek.com 登录态。</p>
112
+ </div>
113
+
114
+ <div class="dsw-card">
115
+ <div class="dsw-cardhead">账号库 <span class="dsw-badge off">3 个账号</span></div>
116
+ <div class="dsw-grouphead">
117
+ <span class="gtoggle">▾</span><span class="gname">工作</span><span class="gcount">2</span>
118
+ <span class="gspacer"></span><button class="dsw-btn ghost">改名</button><button class="dsw-btn ghost">删除组</button>
119
+ </div>
120
+ <div class="dsw-accounts">
121
+ <div class="dsw-account active">
122
+ <div class="dsw-account-main">
123
+ <div class="dsw-account-title">143******@qq.com <span class="dsw-badge on">当前</span><span class="dsw-badge off">限流至 21:30</span></div>
124
+ <div class="dsw-account-meta">捕获于 2026/9/11 11:08 · 今日 164 次调用</div>
125
+ </div>
126
+ <div class="dsw-account-actions">
127
+ <button class="dsw-btn ghost">重登</button><button class="dsw-btn ghost">校验</button>
128
+ <select class="dsw-groupsel"><option>工作</option><option>未分组</option></select>
129
+ <button class="dsw-btn danger">删除</button>
130
+ </div>
131
+ </div>
132
+ <div class="dsw-account grouped">
133
+ <div class="dsw-account-main">
134
+ <div class="dsw-account-title">199******@163.com <span class="dsw-badge err">已失效</span></div>
135
+ <div class="dsw-account-meta">捕获于 2026/9/10 22:41 · 未校验</div>
136
+ <div class="dsw-account-fix">
137
+ <input class="dsw-labelinput" placeholder="备注名(如:备用号)">
138
+ <button class="dsw-btn ghost">保存备注</button>
139
+ </div>
140
+ </div>
141
+ </div>
142
+ </div>
143
+ <div class="dsw-row" style="margin-top:10px">
144
+ <button class="dsw-btn ghost">导出账号库</button><button class="dsw-btn ghost">导入账号库</button>
145
+ </div>
146
+ </div>
147
+
148
+ <div class="dsw-card">
149
+ <div class="dsw-cardhead">请求节流</div>
150
+ <div class="dsw-gate-row">
151
+ <label class="dsw-switch"><input type="checkbox"><span class="dsw-switch-track"></span><span>允许并发生成</span></label>
152
+ <label class="dsw-switch"><input type="checkbox" checked><span class="dsw-switch-track"></span><span>退出时清理网页端会话</span></label>
153
+ </div>
154
+ <div class="dsw-gate-row">
155
+ <span class="dsw-gate-label">请求间隔</span>
156
+ <div class="dsw-range-pair">
157
+ <input type="range" class="dsw-range" value="30"><input type="range" class="dsw-range" value="60">
158
+ </div>
159
+ <span class="dsw-gate-pair-value">2~4 秒</span>
160
+ </div>
161
+ <div class="dsw-gate-row">
162
+ <span class="dsw-gate-label">长休阈值</span>
163
+ <input type="range" class="dsw-range" value="15"><span class="dsw-gate-value">15 次</span>
164
+ </div>
165
+ <div class="dsw-gate-row">
166
+ <span class="dsw-gate-label">图片上限</span>
167
+ <input type="range" class="dsw-range" value="24"><span class="dsw-gate-value">24 份</span>
168
+ </div>
169
+ <div class="dsw-row">
170
+ <button class="dsw-btn ghost dsw-preset active">保守</button>
171
+ <button class="dsw-btn ghost dsw-preset">均衡</button>
172
+ <button class="dsw-btn ghost dsw-preset">激进</button>
173
+ </div>
174
+ <p class="dsw-gate-msg">当前:每 2~4 秒发一个请求,连续 15 次后休息 30~90 秒。</p>
175
+ </div>
176
+
177
+ <div class="dsw-card">
178
+ <div class="dsw-cardhead">调用台账</div>
179
+ ${spark}
180
+ ${kv(['今日调用', '164 次'], ['今日 tokens', '1042.8 万'], ['失败', '3 次'])}
181
+ </div>
182
+
183
+ <div class="dsw-card">
184
+ <div class="dsw-cardhead">手动粘贴 Token(可选路径)</div>
185
+ <textarea class="dsw-area" placeholder="粘贴 token(纯字符串或 JSON 均可)"></textarea>
186
+ <div class="dsw-row" style="margin-top:8px">
187
+ <button class="dsw-btn">校验并保存</button><button class="dsw-btn ghost">清空</button>
188
+ </div>
189
+ <div class="dsw-msg err">凭证校验失败:invalid token(HTTP 401)</div>
190
+ </div>
191
+
192
+ <div class="dsw-card">
193
+ <div class="dsw-cardhead">数据位置</div>
194
+ <div class="dsw-kv">
195
+ <div class="k">配置</div><div class="dsw-path">C:\\Users\\29436\\.dsh\\web-login\\gate.json</div>
196
+ <div class="k">账号库</div><div class="dsw-path">C:\\Users\\29436\\.dsh\\web-login\\accounts.json</div>
197
+ </div>
198
+ <code class="dsw-code">dsh plugin add ./dsh-deepseek-web-login-0.2.1.tgz</code>
199
+ </div>
200
+ </div>`
201
+
202
+ const html = `<!doctype html>
203
+ <html lang="zh-CN">
204
+ <head>
205
+ <meta charset="utf-8">
206
+ <meta name="viewport" content="width=device-width,initial-scale=1">
207
+ <title>DSH 面板预览 · 浅色 / 深色</title>
208
+ <style>
209
+ html,body{margin:0;padding:0}
210
+ body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif}
211
+ .wrap{display:grid;grid-template-columns:1fr 1fr;min-height:100vh}
212
+ .col{padding:20px 26px 80px}
213
+ .col.light{background:#eceef2}
214
+ .col.dark{background:#141416}
215
+ .col > .tag{font-size:11px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;margin:0 0 14px;color:#8b93a3}
216
+ ${styles}
217
+ .col.light .dsw-page{${hostLight}}
218
+ .col.dark .dsw-page{${hostDark}${darkVars}}
219
+ .col.dark .dsw-title,.col.dark .dsw-cardhead{color:var(--fg)}
220
+ </style>
221
+ </head>
222
+ <body>
223
+ <div class="wrap">
224
+ <section class="col light"><p class="tag">Light</p>${demo}</section>
225
+ <section class="col dark"><p class="tag">Dark</p>${demo}</section>
226
+ </div>
227
+ </body>
228
+ </html>`
229
+
230
+ const out = resolve(process.argv[2] ?? join(tmpdir(), 'dsh-panel-preview.html'))
231
+ writeFileSync(out, html, 'utf8')
232
+ console.log(out)