CodexBar DeepSeek 提供商接入指南:API Key 余额与 Platform 会话详解
【免费下载链接】CodexBarShow usage stats for OpenAI Codex and Claude Code, without having to login.项目地址: https://gitcode.com/GitHub_Trending/co/CodexBar
本篇指南围绕 CodexBar 仓库中的 DeepSeek 提供商文档 展开,完整讲解其数据源架构:如何用 DeepSeek API Key 读取剩余余额,如何通过 DeepSeek Platform 登录会话(userToken)获取余额与详细用量,以及两者的解析顺序、会话选择策略与菜单展示细节。读完本文,你将掌握 DeepSeek 提供商从配置、认证到数据聚合的完整工作链路,并能在~/.codexbar/config.json与源码层面定位每一环节的实现。
一、数据源总览:API Key 与 Platform 会话双通道
DeepSeek 提供商支持两种凭据来源与两类数据端点:
- 可选 API Key:通过环境变量
DEEPSEEK_API_KEY/DEEPSEEK_KEY提供,或从~/.codexbar/config.json中的 DeepSeek token accounts(API tokens)中选取。 - API Key 余额端点(余额主数据源之一):
GET https://api.deepseek.com/user/balance- 请求头:
Authorization: Bearer <api key>,Accept: application/json - 响应包含
is_available布尔值,以及balance_infos数组,每个币种条目含total_balance、granted_balance、topped_up_balance三个字符串金额字段。
- Platform 会话余额端点(无 API Key 时的余额数据源):
GET https://platform.deepseek.com/api/v0/users/get_user_summary- 请求头:
Authorization: Bearer <platform userToken>,Accept: application/json
- 可选详细用量端点(必须由 Platform 会话认证,API Key 无法访问):
GET https://platform.deepseek.com/api/v0/usage/amount?month=<month>&year=<year>GET https://platform.deepseek.com/api/v0/usage/cost?month=<month>&year=<year>- 请求头:
Authorization: Bearer <platform userToken>,Accept: application/json - 注意:这些是私有仪表盘端点,并非公开文档化的 API,字段结构可能随时变化,CodexBar 的解析器对错误包裹(error envelope)做了容错设计(详见下文解析层说明)。
1.1 余额 API 的响应结构与解析
在 DeepSeekUsageFetcher.swift 中,余额响应被解码为DeepSeekBalanceResponse(字段is_available、balance_infos)与DeepSeekBalanceInfo(currency、total_balance、granted_balance、topped_up_balance)。解析时对每个条目做了三项约束:
- 三个金额字段必须都能转换为
Double,否则抛出parseFailed; - 多币种时优先选择「有正余额的 USD 条目」,其次「任一有正余额的条目」,再其次「USD 条目」;若 API 返回了空的 USD 行,也不会因此隐藏正数的 CNY 余额(对应 CHANGELOG 中 #873 的修复);
- 全部条目为空时,返回一个
isAvailable: false、余额为 0 的占位快照。
1.2 Platform 用户摘要的解析
get_user_summary的响应结构与公开 API 不同:它带有两层错误包裹(顶层code/data与业务层biz_code/biz_data)。解析器(DeepSeekPlatformUserSummaryResponse/DeepSeekPlatformUserSummaryData)在任意一层code/biz_code非 0 时仍尝试保留data,以兼容不稳定 schema;认证错误码40002、40003会被识别为会话失效。业务数据体biz_data由normal_wallets(充值钱包,对应 paid credit)与bonus_wallets(赠送钱包,对应 granted credit)组成,钱包余额同时兼容数字与字符串两种 JSON 编码。
二、Platform 会话:令牌解析顺序与浏览器导入
2.1 userToken 解析顺序
CodexBar 按以下优先级解析 PlatformuserToken:
- 显式提供的
DEEPSEEK_PLATFORM_TOKEN/DEEPSEEK_USER_TOKEN,或从既有配置中保留的旧版providers[].cookieHeader值(兼容回退)。 - 从 Chrome 的
https://platform.deepseek.comlocal-storage 源无提示读取userToken。
旧版配置值作为兼容回退保留,确保升级不会静默抹掉一个可用的浏览器会话。关键的安全设计体现在 DeepSeekSettingsReader.swift 的scopedPlatformToken与profileScope:
- 无作用域(unscoped)的旧版或环境变量令牌永远不会与 API Key 余额组合使用;API 增强(详细用量)要求会话被保存到该凭据作用域下。
- 新的自动导入令牌从不写回 config,只保存在内存中。
2.2 作用域指纹:凭据到浏览器会话的绑定
profileScope(selectedTokenAccountID:apiKey:)使用 CryptoKit 对com.steipete.codexbar.deepseek-profile-scope.v1 + accountScope + apiKey计算 SHA-256,生成形如v1:<hex>的作用域指纹:
- 无 API Key 时使用固定的
browser:v1作用域; - 有 API Key 时,作用域绑定到当前 token account ID(或
environment)与 Key 本身。
因此,更换 Key 或切换账户时,CODEXBAR_DEEPSEEK_PROFILE_SCOPE不匹配,CodexBar 会要求用户重新显式选择浏览器会话,避免静默复用旧会话(profile 选择仅当存储的作用域与期望作用域一致时才被采纳)。选择的 profile ID 持久化的是稳定的浏览器/profile 标识符(如chrome:<profileName>,由canonicalProfileID规范化),而非绝对的主目录路径。
2.3 多 Chrome 配置文件与会话选择策略
DeepSeekPlatformTokenImporter.swift 会检查每个包含可解析userToken的 Chrome profile(importTokens读取 local-storage 条目并抽取 token,extractUserToken支持 JSON 对象、引号包裹字符串与裸字符串,并要求长度 ≥ 20 且不含空白才算合理令牌):
- 被拒绝或已过期的会话会被过滤掉,Settings 中只展示有效会话的 Chrome profile 选择器;
- 无 API Key 且只有一个有效会话时自动选中;有多个有效会话时复用已保存的选择,或询问一次;
- 当 API Key 提供余额时,新变更的 API 凭据必须显式选择会话,之后网站用量才会与余额合并展示;
- 若选中的会话过期,CodexBar 会在切换到其他有效 profile 前询问用户;
- 校验结果有 30 分钟 TTL 的缓存(
DeepSeekPlatformValidationCache),常规刷新不会逐个探测所有 profile;一次临时网络失败也不会抹掉之前已验证的 profile(unavailable 结果回退到 lastKnownStatus)。
三、获取流程:并发请求、有界等待与降级策略
3.1 API Key 路径
入口为DeepSeekProviderDescriptor中的loadAPIUsage,其流程(对应 DeepSeekProviderDescriptor.swift 的loadUsage/loadAutomaticUsage):
- 若启用可选用量且存在作用于当前 Key 的 scoped Platform token,直接
fetchUsage(apiKey, session, true)并发拉取余额与详细用量。 - 否则启动
resolveAutomaticSession任务解析 Chrome 会话,同时并行调用余额端点fetchUsage(apiKey, nil, false)。 - 余额返回后,通过
BoundedTaskJoin等待自动会话解析,最多 5 秒(optionalResolutionJoinGrace);即使本地 Chrome 读取不响应取消,总截止时间仍有界。 - 若可选工作失败或超时,余额与已验证 profile 列表仍然可用,菜单仅提示「详细用量不可用」(
detailedUsageState: .unavailable)。
在 DeepSeekUsageFetcher.swift 的fetchUsage内部,summaryTask与余额请求并发执行,余额成功后会以completedOptionalUsageSummary(join grace 同样为 5 秒)等待摘要任务:成功则状态为.available,超时或失败则.unavailable,若失败原因是invalidPlatformToken则转为.webSessionRequired(提示去 Chrome 登录)。
3.2 Platform 会话路径
无 API Key 时走DeepSeekPlatformFetchStrategy(source 模式web或auto下无 Key 时)。loadPlatformUsage的流程:
- 若存在 scoped token 则直接
fetchPlatformUsage; - 否则解析自动会话(
includePlatformBalance: true,每个候选会话同时校验余额与用量),join grace 为 20 秒(platformResolutionJoinGrace); - 已选中会话优先校验,其余候选会话以 utility 优先级后台刷新,不阻塞主流程;
- 解析超时抛
networkError("Chrome session resolution timed out");选中余额与详细用量都不可用时抛networkError("Chrome session resolution unavailable")。
3.3 多个 API Key 与平台会话的隔离
浏览器派生的详细用量只展示在活动 API Key 账户卡片上,其他账户卡片保持 balance-only,避免网站用量在多个账户间重复统计(相关快照处理见 UsageSnapshot+DeepSeek.swift 与 UsageStore+TokenAccounts.swift 中的preservingDeepSeekPlatformProfiles逻辑)。
四、详细用量:amount/cost 双端点解析与聚合
4.1 并发拉取与月度参数
fetchUsageSummary使用 UTC 公历(en_US_POSIX locale)计算当前month/year,然后通过withThrowingTaskGroup并发请求/usage/amount与/usage/cost两个端点,任一失败都会整体失败。每个请求 15 秒超时;401/403 被视为invalidPlatformToken。
4.2 响应模型与容错解码
DeepSeekUsageCostParser.swift 定义了完整的解码模型:
- amount 响应:
code/msg/data→biz_code/biz_msg/biz_data,biz_data含total(按模型的 usage 数组)与days(按天的模型用量); - cost 响应:
biz_data为数组,首元素含total、days与currency; - usage item 的
type字段被映射为DeepSeekUsageCategory:PROMPT_CACHE_HIT_TOKEN(Cache-hit input)、PROMPT_CACHE_MISS_TOKEN(Cache-miss input)、RESPONSE_TOKEN(Output)、REQUEST(Requests)四类,未知类型直接忽略; - 所有层的
code/biz_code非 0 都会检查是否为认证错误40002/40003,是则抛invalidPlatformToken,否则抛apiError。
4.3 聚合逻辑
解析器将 amount 与 cost 两个来源按「日期 + 模型 + 类别」聚合:
- 今日:从
days中找到今天的记录,汇总非 REQUEST 类别的 token 与 cost,REQUEST 计入请求数; - 本月:只累加
startOfMonth ≤ 日期 ≤ now的记录(UTC); - 分类/模型:从
total汇总各类别 token 与 cost,并找出 token 量最大的模型作为 top model; - 日序列:生成本月每天的
DeepSeekDailyUsage(日期、token 总数、cost、请求数),供菜单中的 current-month token 图表使用。
4.4 菜单展示
在 UsageSnapshot+DeepSeek.swift 的detailSections中,详细用量被渲染为「Detailed usage」小节:
- Today:
<cost> · <tokens> tokens - This month:
<cost> · <tokens> tokens - Requests:本月请求数
- Top model:token 量最大的模型
- 类别明细:Cache-hit input / Cache-miss input / Output 各自的 token 数
- Daily tokens图表:本月每日 token 序列
五、余额展示、状态机与边界行为
5.1 菜单卡片格式
toUsageSnapshot()(DeepSeekUsageFetcher.swift)定义了余额文案规则:
- 余额 > 0 且可用:
$50.00 (Paid: $40.00 / Granted: $10.00)形式(topped_up_balance即 paid,granted_balance即 granted);CNY 使用¥符号,其余币种使用$; - 总余额为 0:显示「add credits at platform.deepseek.com」的充值提示;
- 余额非 0 但
is_available为 false:显示「Balance unavailable for API calls」; - 多币种时优先展示 USD。
5.2 详细用量状态机
DeepSeekDetailedUsageState包含notRequested、available、webSessionRequired、profileSelectionRequired、unavailable五种状态。菜单笔记(usage notes)会据此提示用户:未登录时提示「Sign in to DeepSeek Platform in Chrome for detailed usage.」,需要选 profile 时提示「Select a DeepSeek Chrome profile in Settings.」,其余失败情况显示「Detailed usage unavailable.」;若没有 API Key 且无有效会话,则要求用户在 Chrome 中登录 DeepSeek Platform。
5.3 无会话/无 Key 的兜底
- 没有有效会话时,菜单保留 API Key 余额(若存在);否则提示用户登录;
- 顶层或嵌套的 DeepSeek 错误码
40002、40003一律视为过期会话; - 会话过期时,
invalidPlatformToken会让详细用量状态回退到webSessionRequired。
六、环境变量与配置速查表
| 项 | 名称 | 说明 |
|---|---|---|
| API Key(首选) | DEEPSEEK_API_KEY | 余额端点认证凭据 |
| API Key(别名) | DEEPSEEK_KEY | 兼容别名,apiKeyEnvironmentKeys按序读取 |
| Platform 令牌 | DEEPSEEK_PLATFORM_TOKEN/DEEPSEEK_USER_TOKEN | 详细用量端点认证凭据 |
| 会话 Profile ID | CODEXBAR_DEEPSEEK_PROFILE_ID | 持久化的 Chrome profile 标识符,规范化为chrome:<profileName> |
| 会话作用域 | CODEXBAR_DEEPSEEK_PROFILE_SCOPE | 凭据作用域指纹(v1:<sha256>或browser:v1),绑定会话选择 |
所有环境变量读取都会做引号剥离与空白清理(DeepSeekSettingsReader.value(for:environment:))。token account 的选择会把选中的 Key 注入到抓取环境变量中;未选择账户时回退到DEEPSEEK_API_KEY/DEEPSEEK_KEY(token account 注入与优先级见 UsageStore+TokenAccounts.swift 与 ProviderTokenAccountSelection.swift,CLI 侧由 TokenAccountSupport.swift 承载)。
DeepSeek 没有会话或周窗口——API 不暴露按窗口计算的配额,因此sessionLabel与weeklyLabel均为 "Balance"(见 descriptor 元数据),菜单不展示进度条式的配额窗口,而是以纯文本余额呈现(相关说明见 MenuBarLayoutRenderer.swift 的注释与 CHANGELOG #856)。
七、Provider 激活与设置界面
DeepSeekProviderImplementation.swift 负责 App 侧集成:
- 当存在多个有效 Chrome profile 或状态为
profileSelectionRequired时,Settings 中会出现Chrome profile选择器(picker iddeepseek-chrome-profile),选项只包含有效会话; - 切换 profile 时调用
beginDeepSeekProfileTransition(preservingBalance:)——若 API Key 存在且 source 不是web,则保留余额,仅替换详细用量数据源; setDeepSeekProfileID(见 DeepSeekSettingsStore.swift)会把 profile ID 与对应作用域指纹一起写入providerConfig,作用域与当前 Key 不匹配时选择不生效;- 元数据
defaultEnabled: false、widgetSelectable: false、balanceOnly: true、usesDetailBackedWindow: true;CLI 名为deepseek,别名deep-seek、ds。
八、关键文件索引
| 文件 | 职责 |
|---|---|
| DeepSeekProviderDescriptor.swift | descriptor 定义、fetch 策略选择(api/web/auto)、余额+自动会话组合 |
| DeepSeekUsageFetcher.swift | HTTP 客户端、余额/摘要/平台余额解析、快照构建 |
| DeepSeekUsageCostParser.swift | amount/cost 响应解码、今日/本月/分类/日序列聚合 |
| DeepSeekPlatformTokenImporter.swift | Chrome local-storage 会话导入、校验缓存与选择解析 |
| DeepSeekSettingsReader.swift | 环境变量解析、profile 作用域指纹与选择判定 |
| DeepSeekProviderConfig.swift | config 中 profile ID/scope 的存取与规范化 |
| DeepSeekProviderImplementation.swift | App 侧 provider 激活、Chrome profile 选择器 |
| DeepSeekSettingsStore.swift | SettingsStore 中 profile 选择的读写 |
| UsageSnapshot+DeepSeek.swift | 详细用量降级与 profile 列表保留辅助 |
相关测试覆盖在 Tests/CodexBarTests/DeepSeekUsageFetcherTests.swift(并发与取消、5 秒 join grace、摘要失败降级)、Tests/CodexBarTests/DeepSeekUsageCostParserTests.swift(amount/cost 解析与聚合)、Tests/CodexBarTests/DeepSeekPlatformTokenImporterTests.swift(会话导入与选择)、Tests/CodexBarTests/DeepSeekSettingsReaderTests.swift(环境变量与作用域)、Tests/CodexBarTests/DeepSeekProfileTransitionTests.swift(profile 切换保余额)与 Tests/CodexBarTests/DeepSeekProviderDescriptorTests.swift。若需修改 DeepSeek 余额或详细用量解析、更新 API Key 处理、或记录新的 provider 行为,可直接从上述文件入手。
【免费下载链接】CodexBarShow usage stats for OpenAI Codex and Claude Code, without having to login.项目地址: https://gitcode.com/GitHub_Trending/co/CodexBar
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考