dsh-ollama-quota
Discovereddsh-ollama-quota — 侧边栏 Ollama 云配额进度条
在 dsh web 侧边栏底部(设置上方)展示 Ollama 云配额:会话 / 每周两个用量百分比进度条 + 各自重置倒计时 + 手工刷新按钮。会话结束(含心跳/webhook 后台会话)自动刷新。
工作原理
侧边栏渲染(sidebar.footer.action 槽位)
→ client 60s 轮询 RPC /dsh-ollama-quota(手工刷新传 {force:true})
→ host 读 OLLAMA_COOKIE(env → ~/.dsh/.credentials.yaml)
→ GET https://ollama.com/settings(Cookie 认证,纯 SSR HTML,正则解析)
→ 返回 { sessionPct, weeklyPct, sessionReqs, weeklyReqs, sessionResetAt, weeklyResetAt }
↓ 页面通道失败时回落
→ 读 OLLAMA_API_KEY → GET https://ollama.com/api/usage(只剩请求计数,百分比为 null)
- 凭据只在 host 端,浏览器只拿到计算后的百分比,永不下发 cookie / key
- 缓存:用量数据 TTL 5 分钟;重置时间每次 RPC 实时计算(不缓存)
- 会话结束刷新:监听
agent/turn-stopping(任何 agent 轮结束,含心跳/webhook 会话)→ debounce 30 秒再查——ollama 服务端用量统计有延迟,立即查会拿到旧数据;30 秒节流兜底 API 频率
⚠️ 上游 API 变更(2026-10-07)—— 为什么改走 /settings
Ollama 官方把 /api/usage 的百分比字段下线了:返回体不再有
limits.session.usage / limits.weekly.usage(原来的 0–1 比例),只剩 totals.request_count
和按天的 buckets。于是本插件原先的 toPct(session.usage) 恒为 null,
侧边栏进度条静默失效(不报错,只是没值),历史快照的百分比字段也跟着写 null。
网页端 /settings 仍显示真实百分比,所以数据源改成页面优先:
| 通道 | 认证 | 能拿到 |
|---|---|---|
ollama.com/settings(首选) | OLLAMA_COOKIE | 会话/每周真实百分比 + 各模型请求数 + 页面权威的重置时刻 |
ollama.com/api/usage(回落) | OLLAMA_API_KEY | 仅请求计数(百分比为 null,如实标注降级) |
页面是纯 SSR HTML,数据写在标签属性/文本里,不需要执行 JS:
<span class="text-sm "> 2.2% used </span>
<div ... aria-label="Session usage 2.2% used" style="width: 2.2%;">
<button data-usage-segment data-model="deepseek-v4.1-flash" data-requests="93">
<div ... data-time="2026-10-08T14:00:00Z"> Resets in 23 minutes.
⚠️ cookie 失效的判据不能只看状态码
__Secure-session 是会话凭据,失效后 /settings 跳登录页,但 HTTP 仍是 200。
判据只能是「页面里读不到 % used」⇒ fetchFromPage() 返回 null ⇒
走回落通道并在日志里标注 degraded。绝不能静默返回空值。
⚠️ cookie 读取:值的正则会截断
OLLAMA_COOKIE 形如 aid=…; __Secure-session=…(含 "; ")。
读凭据的正则必须吃到行尾(["']?(.+?)["']?\s*$),用 [^\s]+ 会在第一个空格处断开,
只剩前半段,页面认证失败。
展示内容
- 会话进度条:5 小时滚动窗口用量 % + 重置倒计时
- 每周进度条:7 天滚动窗口用量 % + 重置倒计时
- 颜色:<60% 蓝
#4f8cff,60-80% 橙#f5a524,>80% 红#e5484d(固定色值,不依赖主题变量) - 手工刷新:标题右侧 ↻ 按钮,force 绕过缓存直接调 API
- 历史趋势:标题右侧 📈 按钮,展开近 7 天每日快照(日期 / 每周 % / 相对前一日 Δ / 周请求数),再点收起
- 收起模式:侧边栏 rail 时只显示状态圆点(按每周用量着色)
每日快照落盘(历史趋势数据源)
每次真实查询 ollama.com usage API 成功(启动刷新 / 会话结束刷新 / 手工刷新,均受 30 秒节流 + 5 分钟缓存保护),host 端自动追加一条采样到 $DSH_HOME/ollama-quota-history.json:
{"version":1,"samples":[{"t":1787924080188,"date":"2026-08-28","week":"2026-08-24","sessionPct":6.6,"weeklyPct":12.9,"sessionReqs":289,"weeklyReqs":3101}]}
date:北京时区日期(快照聚合口径);week:所属 Ollama 周窗口的 UTC 周一日期(周一 08:00 北京重置)- 去重:与最后一条采样同日且百分比完全相同 → 跳过(值没变不刷历史);上限 20000 条,超出截掉最老一半
- 原子写:tmp + rename,进程中断不会写坏文件
- history RPC:
/dsh-ollama-quotaendpointhistory,参数{days}(1-90,默认 7),返回按北京日期聚合的每天最后一条采样(日终值),按日期升序 - 只落真实值:心跳 agent 复述的 HEARTBEAT.md 示例值(
每周 25.1%)不经过本插件,不会污染历史
重置时间
优先级:页面给的权威值 > 本地锚点自算。
- 每周:页面返回
2026-10-12T00:00:00Z= 周一 00:00 UTC(北京周一 08:00) ⇒ 与本地锚点(1970-01-05 00:00 UTC,即WEEK_ANCHOR_MS = 345600000)一致 ✅ - 会话:⚠️ 本地锚点假设已被证伪。页面给出的会话重置是
2026-10-08T14:00:00Z, 而50400 % 18000 = 14400 ≠ 0—— 并不对齐「UTC 整 5 小时」。 原实现18000 - (nowSec % 18000)的锚点前提不成立,倒计时可能有偏差。
⇒ 现在 resetInfo() 只作兜底:页面能给出 data-time 时一律用页面的值,
并在 RPC 层用它反算 sessionResetInSec / weeklyResetInSec,保证两组字段一致。
client 端基于 host 返回的 resetAt 本地每 30 秒 tick 倒计时,不额外调接口。
待查:会话窗口的真实锚点规则(可能是「首次请求起 5 小时」而非 epoch 对齐)。 页面每次都给权威值,所以不影响展示;但兜底逻辑的注释里留着这个疑点,别当它是对的。
目录
dsh-ollama-quota/
├── index.js # host 插件:API key 加载 + 缓存 + RPC(/dsh-ollama-quota)
├── client.js # 浏览器 bundle:sidebar.footer.action 进度条
├── docs/
│ └── daily-allowance-idea.md # 「每日可用量」想法存档(2026-09-29 暂缓,未实现)
├── cordis.patch.yml
└── package.json
暂缓的想法(未实现)
| 想法 | 状态 | 存档 |
|---|---|---|
| 「每日可用量」 —— 按每周剩余量算每天能用多少 | 2026-09-29 暂缓 | docs/daily-allowance-idea.md |
暂缓原因:均分预算天然不准 —— 实测一周消费"前松后紧" (周一 2.1% → 周日 66.6%),所以"每天 N%"在周初毫无约束力、到周中突然报警。 它是平均参考线,不是硬上限,做成告警必然误报。
存档里保留了完整的需求、约束(Ollama 没有「天」维度,按天数字全靠差分)、 三种可选语义、四个待定项,以及最小实现路径 —— 将来想捡起来不必重推。
技术要点(踩过的坑)
sidebar.footer.action容器是display:flex——组件必须flex:1 + minWidth:0 + width:100%才撑满侧边栏,否则进度条轨道被压成 0 宽(表现为"没占满、没进度条")- 别用
--dsw-alias-brand-primary做填充色——它链式引用--dsh-boot-brand,暗色主题下解析为近黑#0f1115,进度条会变黑;且变量"存在"时 fallback 不生效。固定色值最稳 - client.js 改动刷新页面即生效(动态 serve
/plugins/<id>/client.js);host 端 index.js 改动需重启:launchctl kickstart -k system/com.dsh.web - usage 按 token 算不按次数算:长会话上下文大,每次调用消耗多;"晚上消耗快"是使用集中 + 滚动窗口 + 长上下文的叠加,非服务端问题
- inject 需含
"webServer"(dsh 0.1.5 起严格检查):漏了报cannot get property "webServer" without inject,插件加载失败(2026-09-10 踩过) - 验证:
bash ~/.dsh/scripts/verify-plugin.sh dsh-ollama-quota(最小 profile 起实例验证插件树)
Comments
Loading…