cortico-provider-deepseek-web
v0.6.1
Published
DeepSeek Web (chat.deepseek.com) as a Cortico provider: chat and image understanding through the browser web session, no API key and no local proxy process
Maintainers
Readme
cortico-provider-deepseek-web
用浏览器里的 DeepSeek 网页会话直接驱动 Cortico / Coopanion,不需要在本地或服务器上再跑一个反代进程。
协议实现移植自 FreeDeepseekAPI(MIT),改写成 Cortico provider 扩展。
先说钱的事
「这软件不是免费开源吗,怎么跟肥鱼聊个天还要花钱啊?」
软件确实免费。但脑子不免费——模型跑在别人家的显卡上,按 token 收电费。
打个比方:Coopanion 是锅,模型是菜。锅白送你,菜得自己买。
这个插件的用处就是把菜钱省掉:它不用 API Key,走的是你浏览器里那个 DeepSeek 网页账号—— 网页版本来就不按 token 收费。所以装了它,跟肥鱼唠嗑不产生 API 账单。
代价写在明面上,不藏:
- 走的是 DeepSeek 的非公开接口,账号有被限制的风险(所以打了
unofficial-api标签); - 网页版不报 token 用量,费用记录是空的——反正也没花钱;
- 上游改接口,就得跟着改。
想彻底不操心?那就走官方 API(Coo Pet Provider 配 DeepSeek 官方端点),花钱买心安。
两条路各有各的账,自己算。
能力与边界
| 能力 | 状态 |
|---|---|
| 纯文字对话(流式、深度思考开/关) | ✅ |
| 识图 | ✅ 上传 → 轮询 → ref_file_ids,按内容 hash 缓存 |
| 工具调用 | ⚠️ 提示词模拟(网页版没有原生 function calling),默认全开,可收窄 |
| 报 token 用量 / 计费 | ❌ 网页版不给 usage,费用记录为空 |
安装
在 Coopanion 的「扩展」页搜索 cortico-provider-deepseek-web 安装,或在扩展目录里:
corepack pnpm add cortico-provider-deepseek-web装完重启进程(ESM 模块缓存不支持运行中换代码)。
登录
点端点页的「登录」→「自动登录」。 它会:
- 起一个独立配置的浏览器(Edge 优先,其次 Chrome),不碰你日常浏览器的 cookie;
- 你在那个窗口里登录 DeepSeek;
- 它自己从
localStorage['userToken']与 cookie 里取凭证,先验活再落盘; - 面板实时显示每一步,成功后显示账号指纹(token 的 sha 前 8 位,不显示原值)。
凭证写到:
<部署根>/providers/<端点名>/deepseek-auth.json新建端点时的坑(已自动处理):在「还没保存」的端点上登录时,凭证会先落在
providers/draft/里;保存成正式端点后目录变了,凭证会留在草稿里。扩展在端点首次加载时 会自动把草稿里的凭证(和浏览器 profile)接管过来,并在日志里写明。 更稳的做法仍然是:先把端点保存好,再在它上面登录。
没有 Edge/Chrome,或自动流程失败时,可以点「粘贴 cURL」兜底:在 chat.deepseek.com 按 F12 →
Network → 右键任一请求 → Copy as cURL,整段粘进去。
自动登录依赖系统的浏览器路径:Windows 上验证过;macOS / Linux 只做了路径兜底,没有实测。 对不上时用「粘贴 cURL」,对话本身在三个平台都能用。
也可以手工放文件:
{
"token": "...",
"cookie": "ds_session_id=...; smidV2=...; HWWAFSESID=...",
"deviceId": "...",
"wasmUrl": "https://fe-static.deepseek.com/chat/static/sha3_wasm_bg.<hash>.wasm"
}hif_dliq / hif_leim 可选,缺了不影响(实测)。wasmUrl 随网页版本变化;登录失效时通常先表现为
「取不到 PoW 挑战」。
端点建议
| 字段 | 建议 |
|---|---|
| baseUrl | https://chat.deepseek.com |
| 模型 | deepseek-chat(默认)或开深度思考 |
| 思考档位 | 只有「关 / 开」;网页版没有强度参数 |
| 上下文窗口 | 本扩展不上报,需要时手填。猜一个数字会让 Core 按错误上限裁剪历史 |
| 多模态 | 默认开 |
| 工具 | 留空 = 全开;none = 纯对话;a,b,c = 只放行这三个 |
工具调用是怎么工作的(以及它为什么会飘)
网页版的补全接口只收一段文本,没有 tools 字段。所以工具只能靠提示词模拟:
- 把工具说明压成短清单,放在 prompt 最前面;
- 要求模型在要调用时只输出一行
{"tool_call":{"name":...,"arguments":{...}}}; - 从回答里把调用抠出来(容错五种格式),不是调用就原样当文本。
这带来一个固有风险:模型有两条路表达同一句话——输出调用信封,或者直接说人话。 原生 function calling 里只有前者,这里两条都通,所以是概率性的。
缓解措施:
- 每轮追加一句
[Tool reminder]:完整说明书在会话开头,几万字之前;不补这句,模型会逐渐 偏离协议(这是反代作者的 issue #30,我们踩过同一个坑)。 - 正文先缓冲再判定:首字符是
{或<就先攒着,收尾时判断,不是调用就原样交出去,一个字不丢。 - 解析失败不静默:宁可当文本,也不假装「模型没说话」。
如果所在的世界只显示工具输出(比如桌宠只画 pet_say 的气泡,看不见消息正文),
那么模型一旦飘回纯文本,表现就是「它回了但你看不到」。这时可以在端点配置里收窄工具,
或直接换有原生 function calling 的上游。
上下文
容量由 Cortico 的 Core 用 token 记账(hardTokens = 窗口 − 单轮生成上限),本扩展不另立一套账。
另外两层是 DeepSeek 网页版自己的限制,抄自反代:
| 层 | 阈值 | 超了怎么办 | |---|---|---| | 单次请求 prompt | 80,000 字符 | 截掉中间,保留头 35% / 尾 65% | | 单条 chat 累积 | 240,000 字符 | 换一条新 chat |
历史里的工具回执截到 500 字、助手回复截到 2,000 字——网页版一轮能拉回几千字事件正文, 不截的话十几万字很快就把 prompt 挤爆,模型随后开始不守协议。
会话桥按「已知前缀 + 新增尾巴」判断续接:能续就只发增量(实测每轮 100~200 字), 历史被 Core 改写(handoff / 压缩)时重建 chat,那一轮要重发完整上下文。
防风控
网页端会拦自动化调用。下面几条是抄 dsh-deepseek-web-login 的实测结论(Apache-2.0),都做成端点配置项:
| 措施 | 默认 | 为什么 | |---|---|---| | 请求串行 | 始终 | 同一账号同时只能生成一条;实测两个窗口并发不到 6 分钟就触发 1 天临时封禁 | | 请求间隔 | 2~4 秒随机 | 固定间隔方差≈0,统计上就是最明显的「定时器特征」 | | 滚动窗口 | 30 分钟最多 20 次 | 间隔管不了「连着几十分钟不停发」;超过就长休 60~180 秒 | | 长任务保护 | 连续 15 次后长休 | 同上;「连续」以「空闲超过 10 分钟」为界 | | 图片引用上限 | 24 份 | 上游对单次图片条目数有上限(实测 40~52),超了整轮被拒、且该会话此后每轮都失败 | | 重建时删旧会话 | 始终 | 别在账号里堆废弃的 chat |
⚠️ 这些调整降低被识别为自动化的概率,不构成「不会被封」的保证。 逆向网页端本身违反服务条款, 风险是「判罚多严」而不是「会不会被抓到」。稳定优先请用官方 API。
传输通道
上面这些都在「请求怎么发」之外。请求本身由谁发出,才是更硬的一层:
| 指标 | Node 的 fetch(默认) | 真实浏览器 | |
|---|---|---|---|
| JA3 指纹 | d67b0948… | 8595b97a… | 完全不同 |
| HTTP/2 指纹 | 无(只走 HTTP/1.1) | 52d84b11… | 一眼能看出来 |
| 请求头 | 7 个 | 16 个 | 少 sec-ch-ua / sec-fetch-* / priority |
(scripts/probe-fingerprint.ts 与 scripts/probe-inpage.ts 可复现,本机实测。)
UA 能伪装,TLS 不能。 所以端点里有一个「传输通道」选项:
| 值 | 行为 |
|---|---|
| off(默认) | 只用 Node,和 0.4.x 完全一致 |
| auto | 浏览器在就用,不在退回 Node 并告警(面板会标红) |
| on | 只用浏览器;不可用就报错,不静默降级 |
打开后端点页的「传输通道」面板可以一键启停,并显示当前实际用的是哪条路。
实现上没有重写框架的传输层:流式补全把 transport.url 指向一个只监听 127.0.0.1 的
回环代理,由 chat.deepseek.com 页面里的 fetch 发出;建会话 / 挑战 / 上传 / 轮询走同一个
Http 接缝。框架 generate() 的重试退避、四档超时、计量、SSE 装配全部保留。
第一次开启不需要重新登录:扩展会把 deepseek-auth.json 里的 cookie 灌进独立 profile
(<端点目录>/browser-profile),之后由浏览器自己维持会话;重新登录后也会自动同步过去。
代价:多一个 Edge/Chrome 进程(约 150~300MB),冷启动 2~3 秒,会弹出一个浏览器窗口
(这个窗口就是发送方,关掉它通道就断了)。每个端点各起一个浏览器——不同账号之间不共享
profile。profile 会随使用变大;登录态出问题时,把 browser-profile 整个删掉重登即可。
冷却与错误分类
失败之后最糟的做法是继续重试。账号级失败会被记下来,冷却期内一个请求都不发:
| 上游反应 | 冷却 | 用户看到什么 |
|---|---|---|
| 429(限流) | Retry-After,封顶 30 分钟 | 「被上游限流了,21:39 之后恢复」 |
| 401 / 403(登录失效) | 10 分钟 | 「登录已失效,到端点页重新登录」 |
| 403 且正文带验证码文案 | 30 分钟 | 「上游要求人机验证,去浏览器过一次」 |
| 5xx | 不冷却 | 「上游临时故障,稍后重试」 |
| 内容过长 | 不冷却 | 「开一个新会话,或删掉更早的对话」 |
冷却状态写在 <端点目录>/account-health.json,重启后仍然生效;一次成功立刻清零。
端点页的「传输通道」面板里有倒计时和「解除冷却」。
一个不太直观的设计:所有补全请求都经过本地回环代理(Node 模式也一样)。因为框架的
generate() 收到 429 会按 Retry-After 睡几分钟再重试,用户看到的是「发了没反应」。
代理把 429 改写成 409 直接结束,并把 Retry-After 交给冷却逻辑。
已知限制
- 依赖 DeepSeek 的私有网页接口,上游随时可能改;改了就报明确错误,不静默重试。
- 账号风控:这是用自己的账号走非公开接口,存在被限制的风险。介意的话请用官方 API。
- 网页版不报 token 用量,
usage为空、不产生费用记录。 - 同一账号共用限流;本扩展不做并发。
- 自动登录在 Windows 上验证过;macOS / Linux 只做了浏览器路径兜底,没有实测。
- 工具调用是提示词模拟,会飘(见上)。
- 浏览器通道需要本机有 Edge 或 Chrome;
<端点目录>/browser-profile里存着登录态, 敏感级别等同deepseek-auth.json,别提交到仓库。 - 浏览器通道下 PoW 仍在 Node 里算——它不影响网络指纹,所以没必要搬进页面。
开发
src/
index.ts ProviderModule(入口)+ 登录面板的 invoke
client.ts respond():三步握手 + 复用框架 generate()
assembly.ts DeepSeek SSE 分片 → 标准 Responses 事件
session.ts 会话桥(续接 / 重建 / 累积上限)
prompt.ts Cortico 请求 → 单个 prompt;预算截断
tools.ts 工具说明书、每轮提醒、调用解析
images.ts 图片上传 / 轮询 / 缓存
pow.ts SHA3 工作量证明(WASM 运行时下载并按 URL 缓存)
auth.ts 凭证加载与请求头
models.ts 模型别名表
browser-signin.ts 用 CDP 驱动独立浏览器抓凭证
signin.ts 登录状态机(自动 / 粘贴两条路)
http.ts 传输接缝:Http 类型 + 默认 Node 实现
cdp/
client.ts CDP 连接(发送 + 事件分发)
browser.ts 浏览器启动 / 复用 / 关闭
page.ts 页面桥:注入脚本、流式回传、cookie 播种
proxy.ts 回环代理(generate() 的注入点)
headers.ts 禁止请求头清洗
index.ts BrowserChannel:模式、状态、生命周期
webui/client.ts 端点页的登录面板
webui/transport.ts 端点页的传输通道面板pnpm typecheck # 服务端 + 面板两套
pnpm test # 139 项
pnpm build:web # 面板 bundle → dist/webui.js
pnpm check:publish # 官方 dry-mount + describe 一致性 + 发布前清单真机验证(会起一个独立浏览器窗口,不碰日常浏览器;需要端点目录里已有 deepseek-auth.json):
pnpm exec tsx scripts/verify-cdp.ts # 文字两轮 + 增量续接
pnpm exec tsx scripts/verify-cdp-image.ts # 识图(multipart 在页面里重建)
pnpm exec tsx scripts/verify-cdp-abort.ts # 中断是否真的传到浏览器
pnpm exec tsx scripts/verify-cooldown.ts # 冷却期内是否真的不发请求
pnpm exec tsx scripts/probe-fingerprint.ts # 指纹对比(Node vs 同机浏览器)DS_TRANSPORT=node 可以让 verify-cdp.ts 走 Node 通道跑同一套用例。
_reference/ 下是移植时参考的原始源码,不参与打包,也不进 npm。
许可
MIT。协议实现移植自 FreeDeepseekAPI(MIT)。 防风控参数与若干实测结论来自 dsh-deepseek-web-login(Apache-2.0)。
后续(未实现)
- 文档上传:现在只放
image/*。网页版还支持 pdf / docx / xlsx / pptx / txt,走同一个 上传接口,泛化一下就能让桌宠读文件。 - 登录态主动探活:现在靠请求失败来发现过期;可以定时发一个最轻的 PoW 挑战提前发现。
- 账号库:多个账号轮换分散风险。与传输层正交,等前面几项稳定后再谈。
