Extend the openRouterCost projection with a per-step priced-cost map keyed by turn:step so surfaces can render spend without re-pricing, and have the Trajectory view read it through the framework useProjection seat: each priced assistant step shows its USD cost on the request boundary chip and in the inspector summary, while unpriced steps stay blank. Also fix a pre-existing exactOptionalPropertyTypes error in extractCacheRates that the host typecheck surfaced.
4.4 KiB
@deepseek-ai/dsh-openrouter-usage
English | 中文
OpenRouter 花费追踪:一个提供账户余额的 Typert Remote 网关,加上 openRouterCost 会话投影——后者用 OpenRouter 的模型定价表为日志中的 token 用量计价。
在无法解析到 OPENROUTER_API_KEY(即 OpenRouter LLM 路由所用的同一个凭证)时,本包处于惰性状态:无 key 意味着不发起请求、定价表为空(因此每个 step 都保持未计价)、余额为空。
配置
- id: openrouter-usage
name: '@deepseek-ai/dsh-openrouter-usage'
config:
apiKeyEnv: OPENROUTER_API_KEY
baseURL: https://openrouter.ai/api/v1
syncEnabled: true
pricingRefreshMs: 21600000
balanceRefreshMs: 60000
| Key | 默认值 | 含义 |
|---|---|---|
apiKeyEnv |
OPENROUTER_API_KEY |
每次刷新解析的凭证引用。 |
baseURL |
https://openrouter.ai/api/v1 |
OpenRouter API 根;会拼接 /credits、/models 与 /auth/key。 |
syncEnabled |
true |
是否运行周期性的定价/余额刷新。 |
pricingRefreshMs |
21600000(6 小时) |
定价表刷新间隔(毫秒)。 |
balanceRefreshMs |
60000(60 秒) |
余额刷新间隔(毫秒)。 |
key 经凭证边界(ctx.credentials)解析,并以后端环境作为回退,方式与 dsh-web-search-deepseek 一致。
服务契约
ctx.openRouterUsage 是一个 Typert Remote 网关。snapshot() 方法返回最近一次成功的余额快照的副本:balanceUsd 是来自 GET /credits 的可用余额(total_credits 减去已花费的 total_usage,即 OpenRouter 仪表盘展示的数字),外加来自 GET /auth/key 的 label 与月度 usageTokens/limitTokens 预算、isFreeTier 与 updatedAt 时间戳。在任何成功获取之前,它返回一个全 null 的记录;一次失败的刷新会保留上一次已知快照并记录日志。同一个 key 还会从 GET /models 刷新模型定价表(USD 每 token 的 pricing.prompt/completion,以及 flat 的 request 费用,若 API 披露时还有可选的 input_cache_read/input_cache_write)。
openRouterCost 投影会按定价表折叠每个会话日志中的 token 用量(assistant/chunk 的 usage 与 assistant/message 的 usage,按 step 去重)。归属优先采用已组装消息自身的 provider/model;仅有 chunk 的(失败)step 则按最新的 request/context 路由计价。非 openrouter provider 上的 step 不属于本域,不会改变任何值;模型没有对应定价条目的 OpenRouter step 会计作未知(未计价)step。投影的 steps 视图字段以 ${turn}:${step} 为键记录每个已计价 step 的美元成本,便于按 step 展示花费而无需重复计价;未计价的 step 不在该映射中。
扩展点
Web 界面读取 openRouterCost 投影并通过客户端组装调用余额 Remote(ctx.remote.openRouterUsage.snapshot());组件栈由 dsh-client-ui-openrouter-usage 提供。网关不需要任何 session 或 agent 接线——一切都依托持久全量日志投影与一次缓存的请求。
模型体验
OpenRouter 花费与余额读数
模型看到什么
什么也看不到。花费与余额只是面向客户端的只读模型:两者都不会进入模型请求、工具 schema 或任何提示词。agent 循环保持不变。
Token 影响
不会产生模型 token。计价的数字来自 assistant/message 与 assistant/chunk 事件中早已记录的用量。
KV Cache 影响
无;因为花费只是对既有用量事件的投影,而非新的模型可见输入,KV cache 不受影响。
已知限制与暂缓事项
- 估算,而非逐条计费——花费是
tokens × 模型定价,不是 OpenRouter 逐条 generation 的计费。generation id 并未持久记录,且 pi-ai 适配器丢弃了usage.cost,因此投影是根据 token 数重建花费的。free tier 与促销定价可能与模型表有出入。 - 计价以折叠时刻为准——投影在单元格折叠时使用当时的模型表计价。刷新定价只会影响其后折叠的单元格;已折叠的历史保持此前的数值。
- 逐 token 近似——当 API 未披露单独的 cache 费率时,cache 读/写回退到 prompt 费率;flat 的 request 费用每个 step 记一次。账单可能相差不到一分钱。
- 无设置卡片——本插件只通过 cordis.yml 暴露配置;设置项界面推迟实现。