- Home
- Plugins
- Models & Providers
- dsh-claude-subscription
dsh-claude-subscription
lornwolf/dsh-claude-subscription
Adds a Claude Pro/Max subscription model provider with OAuth login, multiple accounts, quota reporting and a settings panel. Requests are sent with the Claude Code client identity, and quota reporting uses an experimental endpoint.
Install
dsh plugin --profile web add github:lornwolf/dsh-claude-subscriptionREADME
dsh-claude-subscription
在 DeepSeek Harness 里直接使用 Claude Pro / Max 订阅。
它做什么
| 能力 | 状态 | 说明 |
|---|---|---|
| 订阅 OAuth 登录 | ✅ | Claude Code 同一条授权通道(PKCE,claude.ai/oauth/authorize),不读 ~/.claude |
| 模型直接可选 | ✅ | 注册 anthropic 路由,模型目录来自 pi-ai 的 anthropic 目录(17 个 chat 模型) |
| 多账号 | ✅ | 一个凭据记录存数组;刷新和切换/增删/清空共用 vault 事务队列,切换会等待刷新结束 |
| 客户端伪装 | ✅ | UA / x-app / anthropic-beta / system[0] 身份句 / 去掉浏览器专属头 |
| 额度 | ⚠️ 实验 | 调 Claude Code /usage 用的 api/oauth/usage,字段以服务端返回为准 |
| 系统提示与工具 | ✅ 修补 | pi-ai 1.1.0 的 anthropic 分支不读 context.systemPrompt/context.tools,本插件把两者物化进首条 system 消息,否则请求里既没 system 也没 tools |
| 设置页 | ✅ | 左侧「Claude 订阅」分区:登录、粘贴授权码、真实账号名与计划、额度卡片、切账号、看模型与指纹 |
安装
dsh plugin --profile desktop add file:./vendor/dsh-claude-subscription-0.1.4.tgz
或在 profile 的 package.json 里加依赖与 bundle 后重启宿主。
Claude 5 及以上:精简系统提示
~/.dsh/prompt-inject.md 如果存在,宿主会把它拼进系统提示最前面。实测:
| 模型 | 带注入段的请求 |
|---|---|
claude-fable-5-1 / claude-opus-5 / claude-sonnet-5 等 5+ | 被 Anthropic 生成前拦截:violative cyber content |
claude-sonnet-4-6 / claude-opus-4-8 等 4.x 及更早 | 正常 |
| DeepSeek / GPT 路线 | 不受影响(不过那道分类器) |
所以插件对 Claude 5+ 的请求改用精简系统提示:只发「Claude Code 身份句 + 一段中性工程助手设定 + ~/.dsh/AGENTS.md(截断 4KB)」,不再发送 DSH 的整段系统提示(其中可能夹着注入段)。工具表由 tools 字段单独发送,不受影响。
为什么不是"剔除注入段":实测 DSH 拼装时会重写注入的首行(<|im_start|>system:<project_instructions> 被拆成两行),注入内容也不是文件原文的逐字拷贝,且它与 harness 提示拼成同一段文本 —— 按原文做子串切分既容易失配、也可能误删整段系统提示。精简模式是确定性的。
- 4.x 及更早的 Claude、DeepSeek、ChatGPT:完全不受影响,系统提示原样发送
- 开关:
config.modernClaudeMode("minimal"默认 /"strip-inject"只剔除注入段)、config.sanitizeModernClaude: false关闭、config.injectFile指定注入文件 - 诊断:默认把每次 5+ 请求的 system 摘要写入
~/.dsh/state/claude-subscription/last-request.json(可用config.diagnostics: false关闭) - 正文过滤:
lib/text-filter.js在流式文本里删掉模型手写的<invoke …>…</invoke>工具语法(config.filterNarration: false可关闭),工具结果卡片不受影响;完整的<invoke>调用块会转成真正的工具调用执行,调用之后的正文整块丢弃(那是模型在拿到工具结果前凭空写的结论,例如「联网工具全都没返回,没法下结论」) - 空回复兜底:
lib/empty-response.js。Claude 5+ 偶发返回「只有 thinking、没有正文和工具调用」的 end_turn,DSH 的判空只看content.length === 0,会把它当成正常完成、界面停在白屏。这里先缓冲首轮事件,确认产出再放行;确实为空就原样重发一次,两次都空则抛出明确的PI_AI_ERROR - thinking 签名:
lib/fingerprint.js的stripReasoning在出站前丢掉 assistant 历史里的 reasoning 块。签名绑定的是模型原始内容,而我们会剥掉<invoke>、追加合成 tool_use,签名必然失效;实测服务端对失效前缀的回应就是那条空回复,而不带 thinking 块的请求被正常接受(服务端对thinking.type.disabled与thinking.adaptive.block_binding都回 400,前者不支持、后者是未知字段)
设置页(左侧「Claude 订阅」)
lib/client.js 往设置面板的 settings.section 槽注册一个分区:登录按钮、授权链接与授权码输入、账号列表(切换/移除)、额度、模型清单、当前指纹。浏览器只拿到状态与授权链接,凭据与网络请求都留在宿主进程。
宿主侧由 lib/rpc.js 在 connection.fetch 上挂 /api/claude-subscription/* 八个端点(status / login / login/submit / login/cancel / logout / quota / accounts/select / accounts/remove),信封走 DSH 既有的 {rpcId, method, payload} → {type: "server-response", rpcId, result}。
需要
ui-settings处于启用状态才有设置面板可挂;有的部署把它关掉了,那时用下面的工具同样能完成登录。
工具(会话里直接说人话即可)
| 工具 | 用途 |
|---|---|
claude_subscription_status | 登录状态、账号列表、可用模型、当前指纹 |
claude_subscription_login | 取授权链接(copy_code 默认,或 browser 起 53692 回调) |
claude_subscription_login_submit | 提交授权页给出的 code#state |
claude_subscription_account_select / _remove | 多账号切换 / 移除 |
claude_subscription_logout | 清空本地账号 |
claude_subscription_quota | 查额度窗口与重置时间 |
伪装层怎么工作
lib/context.js + lib/fingerprint.js,全部在请求离开本机前完成,不依赖宿主文件补丁——即使宿主里的 pi-ai 被改写或升级,这里在运行期仍会重新补回。
- 请求头:
user-agent: claude-cli/2.1.280 (external, cli)、x-app: cli、anthropic-beta补齐claude-code-20250219+oauth-2025-04-20;删掉anthropic-dangerous-direct-browser-access(浏览器 SDK 才会带,官方 CLI 不发)与残留x-api-key(订阅只认 Bearer)。 - 请求体:
system[0]固定为You are Claude Code, Anthropic's official CLI for Claude.,宿主自己的提示词接在后面;幂等,不会重复插。 - 工具表:关掉
supportsMidConvoSystemMessages/supportsMidConvoToolChanges两条 compat,避免 pi-ai 在请求里塞__pi_deferred_placeholder__占位工具,让每个请求只带一份固定工具表(与 Claude Code 一致)。
刻意没有做的指纹项:工具名按 Claude Code 的大小写重命名(要在流里反解回来,容易把工具调用搞坏)、metadata.user_id(格式拿不准,默认关闭,可在 config 里打开)。
配置
apply(ctx, config) 接受:
- id: claude-subscription
name: 'dsh-claude-subscription'
config:
displayName: Claude 订阅
identity:
userAgent: claude-cli/2.1.280 (external, cli)
appHeader: cli
dropBrowserHeaders: true
dropSdkHeaders: false # 打开后连 x-stainless-* 也删
metadataUserId: null # 填字符串则带上 metadata.user_id
0.1.4 设置页额度 RPC 修复
- 设置页
quota端点原来调用了两个根本没导入的标识符(readResolvedSubscriptionUsage、summarizeUsage,只有export … from的再导出,不产生本地绑定),每次点击都抛ReferenceError。改为走readAccountSubscriptionUsage():带accountId、窗口、额外用量与抓取时间,上游原始 payload 不回传浏览器。 - RPC 失败信封补上
error.details: {}。宿主客户端parseConnectionResponse要求details是对象,缺了会抛connection: invalid server-response failure,把真实错误吞掉——面板只剩一句看不懂的连接错误,这正是「点查询额度没反应」的观感来源。 - 新增两条测试:宿主冒烟里跑一次真实
quotaRPC(断言accountId、两个窗口、无raw),以及 RPC 失败信封形状测试。
0.1.3 设置面板:真实账号名、额度卡片、字体统一
- 账号名来自
api/oauth/profile(displayName / email / plan / organization),由 status RPC 在缓存过期时刷新并写回 vault;默认占位名(Claude 1)会被真实名字替换,用户自己起的备注名不动。 - 面板不再显示 vault 内部 id(
claude-mv…);账号行只显示名字、邮箱与计划。 - 额度改成卡片式:窗口名、剩余百分比、进度条、剩余与重置时间;面板打开时自动读一次额度(每个账号一次)。不再输出
pre纯文本。 - 面板所有文字(含客户端指纹区)统一沿用宿主默认字体;只有百分比数字用
font-variant-numeric: tabular-nums保证对齐。 - 账号资料刷新失败时显示缓存并给出一行提示,不会让面板空掉。
- 新增/更新设置面板测试,覆盖自动读额度、账号切换丢弃旧额度、无内部 id 与字体断言。
0.1.2 修复宿主归一化后的工具与思考历史
- 实际 DSH 会先调用
Models.normalizeContext,将工具表放进首条 system 的toolsAdded。精简模式现仅替换该消息的文字,保留工具增删与其他元数据,避免出站tools: []。 stripReasoning同时移除 Harness 的reasoning和 pi-ai 的thinking历史块(包括携带签名或 redacted 标记的 thinking),而非只匹配一种字段名;不伪造或改写签名。- 新增真实
Models.streamSimple → normalizeContext → minimal → provider整链路离线测试,覆盖 Fable 5 工具表、原生/XML 调用后的结果回放及思考签名清理。 - 用真实订阅和隔离工具夹具跑过两轮:首轮调用
read,第二轮收到夹具结果并正常输出标记。
0.1.1 认证与可靠性修复
- OAuth 使用插件自己的
lib/oauth.js,独立生成 state 与 PKCE verifier,保留 browser / copy_code 两种方式及现有凭据格式;结构化授权结果严格校验唯一 code/state。裸授权码保留兼容支持。 - 账号刷新与切换/新增/删除/清空共用同一 vault 的事务队列;多个 store 共享同一 vault 时有效,不是跨进程锁。损坏的存储报错并保留原值。
- 登录默认 10 分钟总期限;提交默认 120 秒,超时会取消后台任务;取消旧登录不会清掉新登录。设置页取消按钮现在实际调用宿主取消接口。
- 额度请求先解析/刷新授权,30 秒网络超时并禁止重定向;RPC、工具错误不回显服务端正文或未知异常详情。
- 订阅请求仅接受 OAuth token 和官方 API origin,最终 Authorization 由插件持有;出站日志不再记录 HTTP 错误正文。
- 新增离线并发、OAuth、登录、RPC/额度和真实 SDK 请求契约测试。
npm test运行测试;真实 SDK 契约测试需能解析 pi-ai,或设置PI_AI_PACKAGE_ROOT为只读包根目录。指定包根却加载失败会使测试失败;没有可解析 SDK 时明确显示跳过。 - 保留
anthropic路由名、既有请求身份与正文过滤行为;此次不迁移已有会话、不扩展模型计费能力。
已知边界
- 额度接口未在真实订阅上验证过;失败只影响额度工具,不影响对话。
- 请求体结构与 Claude Code 不完全一致(工具定义、thinking 配置来自 DSH 与 pi-ai),这是第三方接入的固有差异;本插件只保证客户端身份这一层可辨别特征与官方一致。
- 订阅走的是计划额度,不是 API 计费;账号能否用、能用多少由 Anthropic 侧决定。
Related plugins
dsh-our-free-model
ebony-vinyl/dsh-our-free-model
dsh-routing-suite
yjh051108/dsh-routing-suite
dsh-workbuddy-connect
corrinehu/dsh-workbuddy-connect
dsh-connect-workbuddy
dingminhua/dsh-connect-workbuddy