面向 Google Gemini Web 端的用户脚本(UserScript):在页面右下角以可拖拽胶囊展示当前账号的「5 小时窗口」与「7 天周窗口」真实用量,以及基于官方重置时刻实时递减的倒计时。
https://gemini.google.com/*、https://bard.google.com/*--%,也绝不把周额度写进 5H 槽位。localStorage。同步按「静默优先」的顺序逐级尝试,每一级都使用当前登录态:
/usage 时直接读主 DOM,不额外发请求。jSf9Qc 请求,保留 Google 实际使用的参数编码。batchexecute:f.req 的调用参数是 JSON 文本 "[]",不是裸数组;source-path 为当前账号的 /usage。/usage:已知账号前缀时请求 /u/<n>/usage,否则请求裸 /usage,由 Google 解析到默认登录账号。/app 上这次解析属于尽力而为的默认账号归属(待确认);已知前缀的候选如果最终落到别的 /u/<n>/usage,正文一律丢弃。/usage 文本;自动同步永远不会走到这里。自动路径不跳转、不打开可见标签页、不改变地址栏,因此旧版「一闪而过」不会回来。启动后 500ms 自动请求;每 10 秒检查一次,超过 3 分钟未成功更新则补刷。聊天响应结束后 1.8 秒触发,回前台且数据过期时补刷。隐藏页面暂停自动请求,在途请求复用;成功后自动请求至少间隔 10 秒。失败退避 20、40、80、160、180 秒,手动刷新绕过退避。每个请求含响应体读取最多等待 12 秒。后台标签页只在官方 RPC 连续失败、同源 iframe 处于冷却期、且当前没有同步在跑时,于同步开始的同步段(任何 await 之前)预留;连点复用同一次同步,最多产生一个标签页。
响应桶按 period 枚举分流:1 为五小时、2 为每周,未知枚举忽略。严格验证已用比例和官方重置时间,纳秒换算至毫秒;不从重置时刻猜测桶类型。
缓存键为原 v8 键加冒号及账号路径(/u/1 等,无前缀为 default)。旧共享缓存不迁移,以免误读其他账号用量。Google 内部 RPC 可能变更,真实登录态和油猴管理器行为待确认。
helperSync 仅保留为显式调试入口,会新开页面。短期缓存只用于首屏回显;当前页面文本解析与已有结构化字段观察继续保留。
语义约定(全链路唯一口径):状态里的
pct永远是剩余百分比,usedPct是已用百分比。 官方接口给出的通常是「已用比例」(percentageUsed、"34% used"), 所有解析器都必须在这一层完成100 − 已用的换算,显示层不得再做方向假设。
官方 getUsageInfo.pools 的真实形态:
{
"viewer": { "rpcs": { "getUsageInfo": { "pools": [
{ "poolId": "…", "poolType": "GXU_FIVE_HOURLY", "percentageUsed": 0.12,
"gxu": { "windowRefreshesAt": "2026-10-18T09:30:00Z" } },
{ "poolId": "…", "poolType": "GXU_WEEKLY", "percentageUsed": 0.45,
"gxu": { "windowRefreshesAt": "2026-10-24T09:30:00Z" } }
] } } }
}
poolType / pool_id / bucket 等键上出现 GXU_FIVE_HOURLY(或 5H、HOURLY、per_hour、18000)→ 5 小时池;出现 GXU_WEEKLY(或 WEEK、7D、604800)→ 每周池。GXU_* 池枚举(strictPoolKindFromLabel)才被当作结构化数据;宽松标签(session / week / 18000 / 604800)只用于置信度 1 的启发式,且不得在整页 blob 或聊天 RPC 帧上启用。剩余字段 > 已用字段 > 裸 percent:remainingPercent / percentRemaining / availablePct / leftRatio / remainingFraction 等,直接使用;percentageUsed / usedPercent / usagePercent / usedFraction 等,pct = 100 − x;percent / pct / ratio / utilization:官方语义是「已用」,同样取反。fraction / ratio 的按 00 < x ≤ 1 → x × 100 猜测量纲,把 1 同时当成 1% 和 100%(已用 1% 显示成 100%,剩余 100% 显示成 1%)。used / limit 只有在同一个作用域内成对出现且满足 0 ≤ used ≤ limit 时才换算,跨对象拼接视为无效。windowRefreshesAt / refreshesAt / resetAt / expiresAt,兼容 ISO 8601、10/13 位数字串、[秒, 纳秒] 元组、{seconds, nanos} 对象。结构化层与启发式层各跑一遍、按窗口合并:如果服务端只在 pools 里给出周额度,而 5H 仍以元组形式存在于其他字段,5H 依然能被补齐。启发式递归扫描响应数组,用标签和窗口秒数(18000 / 604800)给元组归类。四条关键规则:
used、limit、窗口秒数或计数,方向也无从判定;只有带 % 的文本才会被采信。"100%" 没有方向词,无法区分「剩余 / 已用」;旧版按「已用」解释,于是任意 width:100% 之类的文本都会变成「已用 100%」。元组与 RPC 帧路径只接受带 剩余 / 已用 / used / remaining 方向词的百分比,{…}、<>、width: 等样式或模板片段直接丢弃。/usage 页面(置信度 2)优先按官方页面文本解析百分比与重置提示:
/u/<账号>/usage 页面中的 Current usage 和 Weekly limit 是两个明确的文本分段;每段只读取其中的 N% used 与紧邻的 Resets ...,不再从整页任意数字猜窗口归属。
无前缀页面只从本次会话发往 batchexecute / BardChatUi 的请求路径观察账号,不采信站内链接或 /usage 请求(后者可能落到默认账号)。主动 RPC 仅请求当前账号,不猜测多个账号。静默 GET 与 iframe 在未知前缀时使用裸 /usage——它就是当前登录账号的页面;只有这种「确实不知道前缀」的场景才允许最终路径被解析成 /u/<n>/usage,已知前缀时最终路径必须与候选逐字一致,落到其他账号则丢弃。
主动 RPC 返回时再次验证账号路径,忽略请求期间已切换账号的旧响应。
当前页是 /usage 且 RPC 失败时读取现有页面文本;RPC 全部失败时依次尝试静默 GET 探测与隐藏 iframe,两者都拿不到时才由手动刷新启用后台标签页。
DOMParser 产出的文档不参与布局:innerText 恒为空,textContent 又把相邻块级元素粘成一行(12% usedResets in 2 hrWeekly limit...)。解析前需在块级边界补换行并剔除 script / style 正文,否则按行分段只能读到第一个窗口——这是旧版 GET 探测「只解析出 5H、随后回落开页面」的根因。
例如 1% used 会转换为剩余 99%,2% used 会转换为剩余 98%;Resets at 3:43 PM 与 Resets Oct 23 at 7:43 AM 分别作为 5 小时和每周窗口的官方重置时刻。
只有官方文本分段缺失时,才继续使用 DOM 卡片、进度条和结构化响应作为补缺路径。
按卡片文本解析百分比与重置提示:
100% used / 100% 已用 → 剩余 0%;剩余 34% / 66% remaining 直接使用;没有任何方向词时按官方页面的默认口径「已用」处理——该口径只对可见卡片文本生效,全文切片与结构体一律不许裸百分比。AF_initDataCallback;blob 只用于补齐 DOM 缺失的窗口。parseOfficialResetTextToTimestamp 支持:2026-10-18T09:30:00Z、2026-10-18 09:30、Resets at 5:30 PM、将于明天 14:00 重置、10 月 18 日 20:30(中文日期,未写年份且已过期一天以上时按次年计算);Resets in 3 hr 12 min、4 小时 53 分钟后重置、剩余 2 天 3 小时、あと 45 分。4 小时 53 分钟后重置 → 4h53m;5 小时限额将于 3 小时后重置 → 3h(前面的「5 小时」是窗口标签,不参与);5 小时限额 / 7 天 不产生任何时间戳。remaining = resetAt − Date.now(),每秒重算:3d 05h / 12h 30m02:03:04remaining ≤ 0 时该窗口的百分比与倒计时一并作废(置为未知 --%),不会沿用旧窗口的数字、也不会伪造 100%,同时触发一次同步。| 规则 | 行为 |
|---|---|
| 5H 的重置时刻距今 > 5.5 小时 | 物理上不可能 → 整条 5H 数据作废,不写入状态 |
| 7D 的重置时刻距今 > 7 天 30 分 | 同上 |
| 记录里出现「超出本窗口长度」的重置候选,且没有相符候选 | 该记录属于另一个窗口 → 整条作废(pickResetAt) |
| 记录里有多个相符的重置候选 | 无法确定 → 只放弃倒计时,保留百分比,绝不猜 |
| 低置信度数据试图覆盖 10 分钟内的高置信度数据 | 拒绝写入(结构化 pools / 官方页面优先) |
| 低置信度数据声称「已用 100%」但拿不到任何官方重置时刻 | 判定为扫到了无关的 100% 文本 → 整条丢弃,显示 --%,绝不伪造满载 |
| 缓存中 5H 的重置时刻超出 5.5 小时 | 历史脏缓存 → 启动时直接丢弃 5H |
| 缓存里的窗口已经翻篇 | 旧窗口百分比作废,显示 --% 并等待同步 |
| 两个窗口的剩余百分比 / 重置时刻恰好相同 | 允许(都没用过就是合法情形);串窗只由窗口长度校验拦截,不靠数值巧合 |
pct(剩余)相反,换算只发生在渲染层。prism / spark / orbit / capsule / bolt / none)。点击胶囊头部可轮换,也可在设置抽屉中直接选择;头部是原生 button,支持键盘聚焦。「无」仍保留 16×16 槽位,切换时不会改变宽度。bar / ring / disk / decay / segments / battery / columns / none)。所有图形都绘制在固定 24×14 的进度槽位内,按「已用」比例填充(<50% 翡翠绿、<75% 琥珀金、<90% 炽烈橙、≥90% 崩坏猩红)。.svg 文件,上限 20KB。SVG 经 DOMParser 白名单清洗:移除脚本、事件属性、foreignObject、image 与外部引用,重写内部 id;图片与 SVG 只替换装饰图标,不影响两段进度。background、color、border-radius),单个目标上限 8KB;含 {}、<>、@import、expression() 或 javascript: 的整段拒绝,避免闭合当前规则后改写宿主页面。内置配色通过 --gc-accent、--gc-badge-color、--gc-timer-color、--gc-progress-color 暴露,用户 CSS 设置对应 color 或变量即可覆盖,不需要 !important。4ch、倒计时 8ch 的字宽,切换内置样式、图片或 SVG 都不会改变胶囊整体宽度。自定义 CSS 若修改 width、padding、font-size、margin 等尺寸属性,会按用户声明改变胶囊宽度;需要保持宽度时只改颜色、背景、圆角、阴影等不影响布局的属性。420px 以下统一压缩间距和字号,仍保持宽度一致。localStorage,刷新后恢复。| Key | 用途 |
|---|---|
__gemini_quota_capsule_cfg_v5__ |
装饰图标、5H / 7D 独立进度样式、自定义图片与 SVG、组件 CSS、拖拽位置、调试开关(Key 与旧版一致) |
| 原缓存键 + 冒号 + 账号路径 | 按 /u/n 或 default 隔离;旧共享缓存不迁移 |
__gemini_quota_sync_bridge_v1__ |
后台用量页 → 当前页的单次同步结果(带 nonce,写完即被读取),不作为数据源 |
源码顶部常量:
| 常量 | 默认值 | 说明 |
|---|---|---|
AUTO_SYNC_INTERVAL_MS |
3 分钟 | 数据过期阈值 |
FIVE_HOUR_MS / WEEK_MS |
5h / 7d | 窗口长度,用于重置时间校验 |
RESET_SLACK_MS |
30 分钟 | 允许的服务端/本地时钟抖动 |
FRESH_MS |
10 分钟 | 置信度保护的有效期 |
MAX_CACHE_AGE_MS |
10 分钟 | 缓存允许回显的最大年龄 |
USAGE_FRAME_TIMEOUT_MS |
12 秒 | 静默 GET / 隐藏 iframe 的单次等待上限 |
USAGE_FRAME_BLANK_GRACE_MS |
1.5 秒 | iframe 文档空白时的额外等待,仍空白才判定不可用 |
USAGE_FRAME_RETRY_COOLDOWN_MS |
10 分钟 | 同源 iframe 被判定不可用后的冷却期,避免反复试错 |
USAGE_HELPER_TIMEOUT_MS |
20 秒 | 后台顶层标签页自行解析的上限 |
USAGE_HELPER_WAIT_MS |
30 秒 | 当前页等待后台页回传的上限 |
控制台提供只读出口,便于核对窗口归属:
__gqc.state // 当前 5 小时 / 每周状态(含 confidence、updatedAt)
__gqc.dump() // 状态 + 配置 + 最近 6 帧配额原始响应 + 端点发现环
copy(JSON.stringify(__gqc.dump(), null, 2))
__gqc.probeUsage() // 直连 /usage:状态码、是否被重定向、initData 块数、命中块片段
__gqc.report() // 一键取证:DOM 限额文本 + 端点 + 关键字附近片段
__gqc.sync() // 立即同步一次
__gqc.helperSync() // 单独跑一次后台用量页读取(会新开一个标签页)
__gqc.setDebug(true) // 打开调试日志
probeUsage() 返回 Promise:JSON.stringify(__gqc.probeUsage()) 只会得到 {}(旧版排查时踩过这个坑)。现在它会自动 console.log 结果并留档到 __gqc.lastProbe,直接调用即可。report() 是「官方把数字放在哪」的取证入口:先打开 Gemini 自己的限额/用量弹窗、再发一条消息,然后执行它。返回内容只含关键字附近片段(每帧 ≤2 条、每页 ≤8 行,单条 ≤200 字符),不落整段会话;同时记录 /usage 体检结果、batchexecute 的 rpcId 列表与端点环。__gqc.dump().frames 采集到的配额响应帧,核对服务端字段;仓库内不再保留独立探针脚本。__gqc.dump().frames 只保留命中配额关键字的响应帧(每帧截断 24KB),用于确认服务端字段命名是否再次变化。__gqc.dump().config.icon 只输出 kind 与 imageChars / svgChars,不导出图片或 SVG 正文;排查装饰资源是否真的写入时看这两个字符数。__gqc.dump().endpoints 是端点发现环:最近 24 条 URL 命中 batchexecute / usage / quota / limit 等的请求(只记 URL、状态码与长度),用来确认配额到底由哪个接口返回。__gqc.probeUsage() 是排查「拿不到 5 小时 / 每周用量」的第一步:blocks 为 0 说明页面里没有 AF_initDataCallback(数据只走 XHR),blocks > 0 但 initHit 为 false 说明字段结构与解析器不匹配,此时看 blockHits[].excerpt 就能核对真实字段名。__gqc.dump().diagnostics 是轻量观测计数(只记录数量与 rpcId,不保存正文),用于区分两类完全不同的故障:
| 字段 | 含义 |
|---|---|
batchExecSeen |
拦到 /batchexecute 响应的次数,为 0 说明拦截本身没生效 |
batchFrames |
解析出的 wrb.fr 帧数量 |
quotaHits |
其中被判定为配额帧的数量,长期为 0 说明字段命名/结构变了 |
lastRpcIds |
最近出现过的 rpcId,便于定位真正的配额 RPC |
rejected |
解析拒绝计数:cssLike(样式/模板片段)、barePercent(无方向词裸百分比)、unverifiedFull(无重置时刻的 100% 已用) |
官方 /usage 文本通道的进展(同步时才会增长):
| 字段 | 含义 |
|---|---|
usageFrameAttempts / usageFrameLoads |
隐藏 iframe 的创建次数 / 加载完成次数 |
usageFrameBlocked / usageFrameRedirected / usageFrameTimeout / usageFrameReason |
iframe 是否因空白、跨账号重定向或超时被判为不可用,以及具体原因 |
usageFrameTextLength / usageFrameParsed |
iframe 读到的文本长度 / 是否解析出用量 |
usageRpcId / usageRpcError |
主动 RPC 的 rpcId 与失败原因 |
usageHelperAttempts / usageHelperOK / usageHelperReason |
后台顶层标签页的尝试次数 / 是否成功 / 失败原因 |
usageHelperError |
手动后台标签页最终失败原因(自动同步不会写这一项) |
usagePage |
最近一次静默 GET 的状态码、最终地址、是否重定向、是否同账号;resolvedPrefix 为最终地址里的 /u/<n>,assumedAccount 表示裸 /usage 被解析到默认账号(/app 上待确认) |
同步期间 state.syncPhase 为「静默同步官方用量」,结束清空。失败保留 lastError 并自动退避重试,不自动打开页面。
仓库内有 tests/gemini-quota-capsule-parser.test.js:用 node:vm 把脚本跑在最小伪 DOM 上,覆盖重置时间解析、parseOfficialUsageText 的 5H / 7D 分流与「已用 → 剩余」换算、多账号候选地址顺序,以及后台同步桥的 nonce 与 payload 校验。旧版 tests/gemini-quota-capsule.test.mjs 已在 5579b8d 移除,解析器回归由该文件承载。当前验证方式:
node --check scripts/gemini-quota-capsule.jsnode tests/gemini-quota-capsule-parser.test.jsnode tests/gemini-quota-capsule-layout.test.cjs —— 用 Playwright 在空白页注入脚本(把入口 bootstrap() 换成 createDOM()),穷举 6 种装饰 × 8 种进度 × 3 组用量(0 / 42 / 100),断言胶囊宽度在所有组合下完全一致、两段槽位恒为 24px、装饰与进度节点在数值不变时保持复用。另覆盖两段进度独立选择、320 / 375 / 768px 窗口、每种进度连续 1000 次更新的节点复用与用量变化重绘、双柱独立比例、键盘轮换与重载恢复、旧配置迁移、图片格式与体积校验、SVG 清洗、组件 CSS 的应用 / 拒绝 / 清除 / 刷新后恢复、CSS 变量无需 !important 的覆盖、写入失败回滚、减少动态效果及未知 / 用尽 / 到期 / 同步中状态。缺少 Playwright 时失败,防止未执行却误报通过;本机运行需 $env:GQC_PLAYWRIGHT_MODULE='<playwright 模块目录>',浏览器通道可用 $env:GQC_BROWSER_CHANNEL 指定,默认先试 msedge 再试随包 Chromium。静默同步链路另覆盖五种形态:RPC 正常、RPC 503 时由静默 GET 与隐藏 iframe 兜底、两者都失败时手动后台页、无账号前缀的 /app 直取裸 /usage,以及本地 HTTP 服务产生的真实 302(/u/1/usage → /u/2/usage)跨账号拦截(断言不写状态与缓存);均断言不产生可见标签页、不改变当前地址,探测成功时不再创建 iframe。__gqc._test 直接调用纯函数,例如const t = __gqc._test;
t.pctFromTextWithContext("width:100%;height:100%"); // null(样式文本不参与)
t.pctFromTextWithContext("100%"); // null(结构体里裸百分比不可信)
t.pctFromTextWithContext("100%", { allowBare: true }); // { pct: 0, usedPct: 100 }(官方卡片口径)
t.pctFromTextWithContext("34% used"); // { pct: 66, usedPct: 34 }
t.readMetricFromArrayTuple(["current session", "100%"], "fiveHour", Date.now()); // null
__gqc.dump().diagnostics.rejected 若持续增长,说明拒绝逻辑正在拦截脏数据;blocks / initHit 用于判断官方页面结构是否又变了。真实登录态下的官方字段、RPC 端点与油猴管理器兼容性待确认。 GXU_* / getUsageInfo.pools 的字段命名、jSf9Qc 响应形态和 /usage 页面文本都可能随 Google 更新而变化;本地回归只覆盖解析器与伪 DOM,尚未在真实登录账号与 ScriptCat / Tampermonkey / Violentmonkey 的每种组合中逐一验证。持续显示 --% 时先查看 __gqc.dump().diagnostics 与 __gqc.report()。脚本不得把 spinner 的 aria-valuenow、WIZ 全局文本或无方向百分比当作配额。
当前版本会保留最近几条受限长度的 batchexecute 响应用于诊断,并记录 nonQuotaResponses / responseReadFailures;只有通过结构化字段验证的响应才会写入胶囊。
自动同步为了保持静默,依赖登录态 GET 与隐藏同源 iframe。若 Google 对 /usage 增加跨域限制或强制前端跳转,这两级都会失败,胶囊只显示 --% 与 lastError,此时手动刷新仍可走后台标签页兜底。iframe 会加载一次官方页面,被判定空白后有 10 分钟冷却。
百分比若是无方向词的裸数字(既非 used 也非 remaining),只能按官方页面默认口径「已用」解释;这类来源不会被当成高置信度数据。
窗口翻篇的瞬间会显示 --%,直到下一次同步(≤3 分钟,或点刷新按钮)拿回新窗口的真实数字。
多账号切换后最多等待一个同步周期(≤3 分钟)才会刷新;可点刷新按钮或调用 __gqc.sync()。
bard.google.com 仅为兼容旧链接保留,实际会重定向到 gemini.google.com。
/usage → 隐藏同源 iframe;自动同步不跳转、不打开可见标签页。后台标签页降为手动刷新专属兜底,避免旧版「一闪而过」回归。DOMParser 文本结构:解析前在块级边界补换行并剔除 script / style 正文。此前 innerText 恒为空、textContent 把两个窗口粘成一行,探测只能解析出 5H,随后错误回落到开页面。/usage 可用于 GET 探测、iframe 与手动后台页;它的账号归属由 Google 决定,在 /app 上记为尽力而为的默认账号解析(待确认),只有已知前缀时才能拒绝其他账号路径。前缀观察只采信本次会话的 API 请求,同一文档只认首次观察;解析前仍校验最终路径,已知前缀的候选落到别的账号一律丢弃。usagePageStatus 新增 resolvedPrefix / assumedAccount 诊断;账号前缀扫描改为从最近一次资源请求倒序查找、命中即停,结果不依赖条目顺序;同一文档内冲突的账号索引不会覆盖已记录的前缀。parseHtmlDocument 现在确实剔除 <style> 正文(此前只剔除 <script>,与文档描述不符);未被生产链路使用的 /u/0 ~ /u/3 猜测函数已移除。__gqc.dump().diagnostics 新增 usageFrameAttempts / usageFrameParsed / usageFrameBlocked / usageHelperError 等字段。/app、真实 302 跨账号拦截、/app 裸 /usage 解析到 /u/2 后由 iframe 取数、自动失败后 RPC 恢复时手动预留页自动关闭),均断言不产生可见标签页、不改变地址;真实登录账号与 Google 页面结构仍待确认。f.req 参数形态:调用参数按官方页面与已知实现的形态改为 JSON 文本 "[]"。1.0.1 传裸数组 [] 与协议不一致,是取数失败的首要代码缺陷;服务端对裸数组的具体响应尚未抓包确认。jSf9Qc 时不再把 row[0] 当作有效性判据:该字段的语义随账号与窗口变化,耗尽时可能为 0,旧守卫会丢弃有效行。已用比例接受任意非负有限数并钳制到 100%,同一窗口的重复行取第一条有效值,不再因单个异常行丢弃整包数据。__gqc.dump().diagnostics 新增 usageRpcId 与 usageRpcError,便于区分 HTTP、重定向、账号切换和空用量响应。"[]" 形态、耗尽额度和超额比例;真实登录账号与 Google RPC 变更仍待确认。DOMParser 白名单清洗,移除脚本、事件属性、foreignObject、image 与外部引用,并重写内部 id;图片与 SVG 均只作用于装饰图标。{}、<>、@import、expression()、javascript:。内置配色改由 CSS 变量下发,用户规则无需 !important 即可覆盖。__gemini_quota_capsule_cfg_v5__;旧配置的 styleMode 会同时迁移为 5H 与 7D 的初始进度样式,缺失字段回落到默认值。保存失败时回滚并给出可见提示。segments)、电池(battery)、双柱(columns),与原有横条 / 圆环 / 圆盘 / 崩坏共 7 种。分段用 repeating-linear-gradient 遮罩把两段进度条切成五格,填充比例仍按「已用」精确渲染;电池给进度条描一圈边框、填充即电量;双柱在徽章内用两个 SVG 柱分别表示 5 小时与每周,柱高按「已用」比例。所有形态沿用同一套「已用」口径与颜色阈值(<50% 翡翠绿、<75% 琥珀金、<90% 炽烈橙、≥90% 崩坏猩红)。.gc-inline-track 原先只在横条模式下显示、其余模式 display:none 不占位,切到非横条形态后槽位消失,胶囊整体宽度随之收窄;现改为始终保留槽位,非横条形态只设 visibility:hidden 隐藏图形而不移除布局空间。其二,百分比与倒计时文本长度会随数值变化(0% ↔ 100%、05:30:00 ↔ 3d 12h)而撑宽或收窄,现将 .gc-pill-counter 固定为 4ch、.gc-pill-timer 固定为 8ch 并省略溢出。修复后 7 种形态 × 任意用量下胶囊宽度恒定。INDICATOR_MODES 常量,cycleStyleMode() 与设置面板共用,避免两处列表漂移;左侧徽章由 div 改为原生 button(type=button + aria-label),设置面板按钮补 aria-pressed,可键盘操作。DEFAULT_CONFIG.styleMode 默认值仍为 bar,配置 Key(__gemini_quota_capsule_cfg_v5__)、缓存键(v8)与置信度保护均未改动。/usage 页面点刷新没有任何反应」:旧实现只解析当前页面文本,页面不在 /usage 时找不到额度文本,手动同步静默失败。现在手动刷新且不在 /usage 时,会在点击的同步阶段先占一个后台窗口,探测到可用地址后导航到 /usage#gqc-usage-sync=<nonce>,由该顶层标签页读取官方文本、写回同步桥并在 250ms 后自动关闭;当前页立刻拿到数字,并在同步期间显示「后台读取官方 /usage 页面文本…」。__gemini_quota_sync_bridge_v1__ 传递本次请求结果(nonce 校验,nonce 只写在 hash 上,不污染 /usage 路由),不把 10 分钟缓存当成实时数据;两个标签页写入同一份官方缓存。Current usage / Weekly limit 文本可能不渲染。轮询不再等 load 事件,CSR 文本就绪即取。error 只记诊断,不永久关闭该通道。/app 无账号前缀且四个候选全部探测失败时,不再按 /u/3/usage 之类的猜测地址解析,避免把别的账号额度写进缓存。/u/<n> 前缀时从同源请求路径观察真实账号索引,优先只请求该账号;/usage 探测要求最终路径与候选账号路径完全一致,/u/3/usage 跳到 /u/0/usage 时判为不可用并继续下一个候选,usagePageStatus 增加 sameAccount 诊断字段。about:blank 不再立即永久停用通道:留 USAGE_FRAME_BLANK_GRACE_MS 宽限,仍空白则只结束本轮;宽限后文档不可读(跨源)才判定为站点拒绝嵌入。__gqc.dump() 新增 state.syncPhase 与 usageFrame* / usageHelper* 诊断字段;新增 __gqc.helperSync() 单独触发后台用量页读取;解析器回归测试补充后台同步桥的 URL / nonce / payload 断言。/app 且没有账号前缀时,依次探测有限的登录账号用量路径 /u/0/usage 至 /u/3/usage,避免错误请求无前缀 /usage 后直接放弃官方数据通道。/usage 路径的响应才进入解析;被重定向到其他页面的响应不会被当作用量数据。/usage 页面不存在:GET https://gemini.google.com/usage 会被 302 到 /app(未登录实测)。v0.8.1 之前「官方页面」这条通道从来没有产出过真数据,旧版显示的数字全部来自 WIZ_global_data 的标签启发式。现在同步会先做重定向体检,跳走就停用该通道,不再解析 app 的 blob。probeUsage() 的 {} 是使用姿势问题:它是 async,JSON.stringify(promise) 恒为 {}。现在结果自动 console.log 并留档 __gqc.lastProbe,且新增 redirectedAway / note 字段直接说明通道是否可用。__gqc.report() 取证入口:采样聊天 StreamGenerateContent 响应(旧版在这里直接 return,把最可能的数据源排除在外)、batchexecute 帧、以及页面里含「限额/剩余/用量」的可见行,只保留关键字附近片段,用来定位官方真实的字段名与 rpcId。__gqc.dump().diagnostics 新增 usagePage 体检结果与 quotaSnippets 计数。修掉「5 小时与每周都显示已用 100%」的假数据链路,根因是把无关文本当成了配额:
window.WIZ_global_data(bootstrap 数据 + 聊天 batchexecute 帧)里充斥着 session / week / 样式文本,宽松标签一旦命中,width:100% 这类字符串就被读成「已用 100%」,两个窗口于是同时满载。现在 blob 只作最后兜底,且 RPC 帧与 blob 一律禁用标签启发式。collectStructuredPools 原先用 session / week / 18000 判池,并把结果标成最高置信度,导致假数据压过官方页面。现在元组必须自带 GXU_* 池枚举才算结构化。N% 在结构体里无法区分剩余与已用。现在只有 /usage 的可见卡片文本保留该默认口径,元组、RPC、全文切片一律拒绝裸百分比;{…}、<>、width: 等样式/模板片段整段丢弃。WIZ_global_data 并 return true,官方 /usage 页面永远跑不到;parseUsageDocument 也让 AF_initDataCallback 挡住可见 DOM。现在顺序为「捕获 RPC → /usage SSR → iframe → WIZ 兜底」,DOM 优先于内嵌 blob。--% 而不是假满载);__gqc.dump().diagnostics.rejected 记录被拒绝的原因(cssLike / barePercent / unverifiedFull)。percentageUsed(以及 "100% used" 文案、used/limit 比率)被当成「剩余」直接显示,100% 已用会显示成「剩余 100%」。现在所有解析器统一换算成剩余,状态里同时保留 usedPct。now + 5h,于是 5H 倒计时恒为满窗口、7D 倒计时抓到「5 天」之类的标签数字。现在相对时长必须紧邻「重置 / 剩余 / until」锚点,且只取锚点前那一段。find(Number.isInteger) 会把上限、窗口秒数、请求计数当成用量。现在只有带 % 的文本或具名字段才能产出百分比。__gqc.dump() 新增 diagnostics,用于区分「拦截未生效」与「拦到了但结构变了」。tests/gemini-quota-capsule.test.mjs(15 例,node --test,含一处端到端提交链路校验)。@updateURL(jsDelivr @main)与 @downloadURL(ghfast 代理 raw),此前缺失两者,ScriptCat 只能退回安装地址 raw.githubusercontent.com,该域名在部分网络下超时,导致永远检测不到更新。purge-jsdelivr.yml:推送 main 后主动 purge CDN 缓存并校验 CDN 上的 @version,消除分支最长 12 小时的缓存延迟。pools 解析:按 poolType 精确区分 5H / 7D,作为最高优先级数据源。[秒, 纳秒] 元组、{seconds, nanos} 与含周单位的相对文案。resetAt − now 每秒重算;相对文案以抓取时刻为锚点,不再显示静态字符串。__gqc 调试出口。node --test 回归测试(13 例)与 CI 校验工作流。batchexecute 帧 + /usage 页面双通道同步,四形态指示器。MIT License