dsh-agy-link 0.4.53 → 0.4.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,196 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.59 (2026-10-16)
4
+
5
+ ### English
6
+
7
+ - **Fix: turns queued for the Windows credential slot could pend forever as invisible zombies, immune to Stop (cardboard-empire incident, 2026-10-16 22:44).**
8
+ - **Incident**: a turn dispatched while another session's 32-minute run held the process-global credential slot never received the release wake-up. The turn sat at `request/context` with no agy process spawned for 30+ minutes; the idle watchdog never armed (it only arms after spawn); Stop did nothing because no wait in the dispatch phase observed the abort signal; and the leaked dispatch held one of the 3 `maxConcurrent` slots, starving later turns of other sessions into the same wedge.
9
+ - **Changes**:
10
+ 1. **`AsyncMutex` rewrite** (`credential-slot.ts`): the promise-chain FIFO could never remove a waiter — an abandoned/aborted one would wedge the whole chain behind it. Now an explicit queue: a cancelled or timed-out waiter is REMOVED and the holder's release wakes the head directly. Cancelling a waiter deliberately does NOT grant the mutex (it is still held).
11
+ 2. **Abort + bounded wait for the slot** (`acquireCredentialSlot`): new `signal` / `dispatchTimeoutMs` resolve-options. Stop now ends a queued dispatch immediately (`AbortedWaitError`); a bounded wait fails visibly (`WaitTimeoutError`) instead of parking silently.
12
+ 3. **Lost-wake-up self-heal**: while queued, a liveness poll (5s) re-checks and takes the mutex directly if it is actually free — the exact failure shape from the incident now self-corrects within seconds even if a wake-up is ever lost again.
13
+ 4. **Dispatch observability**: a 2-minute heartbeat logs the queue state ("dispatch still waiting Nm — X waiter(s), Y holder(s) … press Stop to cancel") so a stuck dispatch is visible in the console instead of a silent spinner.
14
+ 5. **Dispatch retry** (`adapter.ts`): on a hard-cap slot timeout the dispatch releases the concurrency slot, backs off abort-aware (2s→4s→…→15s), and retries (`dispatchRetries`, default 1); exhaustion fails the turn VISIBLY with guidance — never an infinite pending state. Retry is confined to the pre-spawn dispatch phase; a turn that already emitted output is never re-driven.
15
+ 6. **Rate-limit spacing sleep** is now abort-aware (Stop during the 60s window no longer spawns a turn nobody is reading).
16
+ - **Config**: new `dispatchTimeoutMinutes` (default **15** — each attempt waits up to 15 minutes for the slot, so persistence ≈ (1+retries)×15 min before a visible failure; 0 = wait indefinitely, still abort-aware / poll-healed / heartbeat-logged) and `dispatchRetries` (default 1). User-facing entry: `/agy dispatch` (inspect live queue + effective caps), `/agy dispatch <minutes|off>` and `/agy dispatch-retries <n>` — persisted via runtime overrides, effective next turn.
17
+ - **Fix: artificial concurrency limits removed — native agy parallelism restored.**
18
+ - agy is a stateless CLI and handles concurrent processes natively; the only machine-global constraint on Windows is the single credential store, and only when its IDENTITY changes.
19
+ - **Same-account fast path** (`parallelSameAccount`, default **on**): a run whose credential already sits in the slot starts immediately WITHOUT the mutex, so N sessions on one account run truly in parallel (concurrent refreshes on one grant are safe — refresh tokens are not single-use). `/agy parallel <on|off>` toggles it.
20
+ - **Account switches still serialize** (correctness): a secondary waits for same-account runs to drain before swapping the slot, new fast paths are refused while a switch pends, and the switch restores the primary afterwards — the anti-corruption invariants are unchanged and covered by new tests.
21
+ - **`maxConcurrent` default 3 → 0 (unlimited)**: no artificial admission bound; Google rate limits and the pool's cooldowns are the natural regulators. `/agy max-concurrent <n|off>`.
22
+ - **Tests**: mutex cancel-removes-and-wakes-next; timeout keeps the queue flowing; lost-wake-up poll grant; `acquireCredentialSlot` rejects when already aborted, honors Stop while queued, and fails visibly on the bounded wait.
23
+
24
+ ### 中文 (Chinese)
25
+
26
+ - **修复:排队等 Windows 凭据槽位的回合可能永远挂起成隐形僵尸,且 Stop 无法取消(cardboard-empire 事件,2026-10-16 22:44)。**
27
+ - **事件**:一个回合在另一会话 32 分钟长任务持有进程级凭据槽位期间派发,之后永远没有收到释放唤醒。该回合停在 `request/context`,30 多分钟没有拉起任何 agy 进程;空闲看门狗从未武装(只在 spawn 后才武装);按 Stop 无效,因为派发阶段的所有等待都没有观察中止信号;泄漏的派发还占着 3 个 `maxConcurrent` 槽位之一,把其他会话的新回合也拖进同样的卡死。
28
+ - **修改**:
29
+ 1. **重写 `AsyncMutex`**(credential-slot.ts):原来的 promise 链式 FIFO 无法移除等待者——一个被放弃/中止的等待者会把整条链卡死。现在改为显式队列:被取消/超时的等待者会被移除,持有者释放时直接唤醒队头。取消等待者刻意不发放互斥锁(锁仍被持有)。
30
+ 2. **槽位等待支持中止与限时**(`acquireCredentialSlot`):新增 `signal` / `dispatchTimeoutMs` 选项。Stop 现在立即结束排队中的派发(`AbortedWaitError`);限时等待可见地失败(`WaitTimeoutError`),不再静默挂起。
31
+ 3. **丢失唤醒自愈**:排队期间每 5 秒自检一次,发现锁实际空闲就直接取锁——即使唤醒再次丢失,本事件形态也会在数秒内自愈。
32
+ 4. **派发可观测性**:每 2 分钟心跳记录队列状态("dispatch still waiting Nm — X waiter(s), Y holder(s) … press Stop to cancel"),卡死的派发在控制台可见,而不是无声转圈。
33
+ 5. **派发重试**(adapter.ts):槽位硬超时后释放并发槽位、可中止退避(2s→4s→…→15s)并重试(`dispatchRetries`,默认 1);重试耗尽则让回合可见地失败并给出处理指引——绝不无限 pending。重试仅限 spawn 前的派发阶段;已经产出内容的回合绝不重跑。
34
+ 6. **限流退避 sleep** 支持中止(60 秒窗口内的 Stop 不再照常 spawn 一个没人读的回合)。
35
+ - **配置**:新增 `dispatchTimeoutMinutes`(默认 **15** —— 每轮最多等 15 分钟,含重试总坚持 ≈ (1+重试)×15 分钟后可见失败;0 = 无限等待,仍可中止/轮询自愈/心跳可见)与 `dispatchRetries`(默认 1)。用户入口:`/agy dispatch`(查看实时队列与当前配置)、`/agy dispatch <分钟|off>` 与 `/agy dispatch-retries <次数>` —— 经 runtime overrides 持久化,下一回合生效。
36
+ - **修复:移除人为并发限制,恢复 agy 原生并行能力。**
37
+ - agy 是无状态 CLI,天然支持多进程并发;Windows 上唯一的机器级约束是单一凭据库,且仅在**账号身份切换**时才需要互斥。
38
+ - **同账号快路径**(`parallelSameAccount`,默认**开**):凭据已在槽位中的账号立即启动、完全不取互斥锁 —— N 个会话在同一账号上真并行(同一授权的并发 token 刷新是安全的,refresh token 非一次性)。`/agy parallel <on|off>` 开关。
39
+ - **账号切换仍然串行**(正确性):副账号先等同账号 run 全部退出再换槽位;切换等待期间拒绝新的快路径;切换完成后恢复主账号 —— 防腐蚀不变量原样保留,新增测试覆盖。
40
+ - **`maxConcurrent` 默认 3 → 0(不限制)**:移除人为准入上限;Google 速率限制与账号池冷却是天然调节器。`/agy max-concurrent <n|off>`。
41
+ - **测试**:互斥锁取消后移除并唤醒下一个;超时不阻塞队列;丢失唤醒的轮询补偿;`acquireCredentialSlot` 已中止即拒绝、排队中响应 Stop、限时等待可见失败。
42
+
43
+ ## 0.4.58 (2026-10-16)
44
+
45
+ - **Fix: DSH `/goal` loop restart bug (autonomous runs continuing indefinitely instead of marking complete).**
46
+ - **Root Cause**:
47
+ 1. In `src/host/mapper.ts`, whenever an agy run finished with `!ev.ok` (e.g. background EOF/network timeout right as generation finishes), it yielded `{ type: 'finish', reason: { kind: 'stop' } }` and returned early, bypassing the `supportsGoalUpdate` synthetic `update_goal` completion call even when agy generated a full, successful text response. DSH interpreted this as an uncompleted round and scheduled subsequent rounds indefinitely.
48
+ 2. In `src/index.ts`, `sessionGoal` attempted to read `session.events`, but DSH `Session` instances store events in `session.log` / `session.snapshotEvents()`, causing session goal resolution to always return `null`.
49
+ 3. In `src/host/dsh-goal.ts`, `isGoalToolContinuation` only inspected `messages[messages.length - 1]`. When DSH executes `update_goal`, it defers a `<goal_complete>` user notice (`source.kind: 'tool-goal'`), placing the tool result at `messages.length - 2` and causing agy to respawn on the completion notice.
50
+ - **Fix**:
51
+ 1. `EventMapper.map` now unifies the finish path so `update_goal` and `exit_plan_mode` are always dispatched upon successful response generation regardless of trailing transport EOF flags.
52
+ 2. `sessionGoal` queries DSH's live `ctx.goals.get(agent)` in O(1) and falls back to `session.log` / `session.snapshotEvents()`.
53
+ 3. `isGoalToolContinuation` checks the trailing span for `agytc-bridge-goal-`, `source.kind === 'tool-goal'`, and `<goal_complete>`, finishing cleanly without respawning agy.
54
+ 4. Marked `tool-goal` and `<goal_complete>` as synthetic harness messages so they never get treated as human user instructions.
55
+
56
+ - **Fix: real-time 5-hour quota consumption and rolling countdown now accurately display instead of staying frozen at 100% / blank.**
57
+ - **Root Cause**:
58
+ 1. Google's `retrieveUserQuotaSummary` endpoint returns coarse group-level numbers (`gemini-5h: 1.0`), while `fetchAvailableModels` reports the actual per-model 5-hour consumption and active rolling reset time (e.g. `0.70`, reset in 12 minutes). `QuotaService.refreshAccountQuota` gated the per-model tightening behind `else if (familyQuotas[fam]!.remainingFraction === undefined)`, so whenever the coarse summary returned `1.0`, active model usage was completely ignored and the family quota was locked at `100%`.
59
+ 2. In `fetchAvailableModels`, hitting any staging endpoint (`daily-cloudcode-pa`) set `this.preferredEndpointIndex`, causing subsequent `retrieveUserQuotaSummary` calls to target the staging endpoint (which omits Gemini entirely).
60
+ 3. `mergeFallbackFamilyQuota` returned stale `prev` data whenever `prev.remainingFraction` existed, freezing accounts at their 10:04 AM state (`resetTime` in the past), which caused `formatQuotaWindow` to drop the expired timestamp as empty and render no duration at all.
61
+ - **Fix**:
62
+ 1. `fetchAvailableModels` now only sets `preferredEndpointIndex` if the endpoint is the official production endpoint (index 0).
63
+ 2. Active 5-hour model consumption (window <= 6h) now tightens `familyQuotas[fam].remainingFraction` and its `resetTime` even when summary returned a coarse `1.0`.
64
+ 3. Full-quota rows where `resetTime` has expired safely fall back to "已重置 · 可用" instead of a blank row, while active windows display the real rolling countdown (e.g. `↻ 02:50 (4小时 55分钟)`).
65
+
66
+ ## 0.4.57 (2026-10-16)
67
+
68
+ ### English
69
+
70
+ - **Fix: transient network jitter no longer sticky-quarantines healthy accounts as "需重新登录".**
71
+ - **Background**: agy prints the same 939-byte "Authentication required" stderr banner whether the login is really dead OR its keyring auth merely missed its hard 10s window on a flaky network. One afternoon of proxy jitter (2026-10-16) quarantined three healthy accounts on first sight; `setActiveAccount` then refused the quarantined slot with 该账号当前不可用(冷却或需重新登录).
72
+ - **Changes**:
73
+ 1. **Log-evidence classification** (`src/host/agy-log.ts` + `looksLikeAuthVerificationJitter`): the adapter now snapshots agy's per-run `cli-*.log` set before spawning and reads this run's log on an auth-shaped failure. `keyringAuth: timed out after 10s` / `failed to fetch user info` / `userinfo request failed` prove a STORED credential existed and only the network was down — the failure is reclassified NETWORK (retryable, rotates, no quarantine). An authoritative token error (`invalid_grant`…) always wins over jitter. Verified against real logs: the genuine sign-out log contains zero occurrences of every jitter marker.
74
+ 2. **Confirmation-gated quarantine** (`pool.noteAuthFailure`): a bare, non-authoritative "not signed in" banner no longer sets the sticky `authRequired` flag on the first occurrence — it only rotates the account away for the current retry. The flag hardens into a real quarantine on a second consecutive failure with no success in between; a successful run resets the streak. Authoritative OAuth paths (`invalid_grant` from the token endpoint) and the explicit re-login paths still quarantine immediately.
75
+ - **Tests**: classifier fixtures from the real jitter and sign-out logs; log-reader run attribution; single-strike / streak-reset pool semantics; end-to-end `auth-jitter` fake mode ⇒ NETWORK with no flag, bare `auth` banner ⇒ AUTH with no flag on first sight.
76
+
77
+ ### 中文 (Chinese)
78
+
79
+ - **修复:瞬时网络抖动不再把健康账号错误地隔离为"需重新登录"。**
80
+ - **背景**:无论登录是真的失效,还是 keyring 鉴权在抖动网络上没赶上 10 秒硬超时,agy 都会打印同一段 939 字节的 "Authentication required" stderr 横幅。2026-10-16 一个下午的代理抖动就让三个健康账号被一次性隔离;随后 `setActiveAccount` 对被隔离账号直接返回 该账号当前不可用(冷却或需重新登录)。
81
+ - **变更**:
82
+ 1. **基于日志证据的分类**(`src/host/agy-log.ts` + `looksLikeAuthVerificationJitter`):适配器在 spawn 前对 agy 的本次运行日志(`cli-*.log`)做快照,出现鉴权形态失败时读取本次日志。`keyringAuth: timed out after 10s` / `failed to fetch user info` / `userinfo request failed` 证明本地确实存有凭据、只是网络不通 —— 此时失败改判为 NETWORK(可重试、轮转、不隔离)。权威的 token 错误(`invalid_grant` 等)永远优先于抖动证据。已用真实日志验证:真正登出的日志中所有抖动标记出现次数为 0。
83
+ 2. **隔离需二次确认**(`pool.noteAuthFailure`):不带权威证据的裸"未登录"横幅,第一次出现不再直接置粘性 `authRequired` 标记,仅为本次重试轮转走;只有连续两次失败且中间没有成功才升级为真正隔离;一次成功运行即清零计数。权威 OAuth 路径(token 端点返回 `invalid_grant`)与显式重新登录路径仍在首次即隔离。
84
+ - **测试**:取自真实抖动/登出日志的分类器用例;日志读取器的"仅本次运行"归属;单次不隔离/成功清零的池语义;端到端 `auth-jitter` 假模式 ⇒ NETWORK 且无标记,裸 `auth` 横幅 ⇒ AUTH 且首次不隔离。
85
+
86
+ ## 0.4.56 (2026-10-16)
87
+
88
+ ### English
89
+
90
+ - **Feature: Gemini 4 Argon (Pro/Ultra) now shows as its own quota family with its separate weekly limit.**
91
+ - **Background**: Antigravity now grants paid Google AI Pro / Ultra accounts access to **Gemini 4 Argon**, which bills against its OWN weekly quota pool (it does not consume the plain Gemini pool). The backend surfaces this as a dedicated quota group in `retrieveUserQuotaSummary` (display name like "Gemini 4 Argon") and as `gemini-4-argon-low/-medium/-high` model ids in `fetchAvailableModels`.
92
+ - **Changes**:
93
+ 1. Added a new `'argon'` entry to `ModelFamily`; `modelFamilyOf` now classifies any id containing `argon` into it BEFORE the generic `gemini-` gate — previously argon ids folded into the `google` family and their usage silently drained/reported the plain Gemini counter.
94
+ 2. `QuotaService.refreshAccountQuota` detects the Argon quota group (its display name still contains "gemini", so the argon gate must win) and ingests its weekly bucket into `quotas.argon`; argon model-level breakdown follows the same family.
95
+ 3. GUI quota panel: an **Argon** row renders directly under Gemini ONLY when the backend actually returned argon quota data for that account — free plans and accounts without the Argon permission never see an empty Argon panel. Since Argon is a weekly-only counter today, the ghost "5-hour / —" line is suppressed unless the backend reports one.
96
+ 4. `/agy pool` status appends `| Argon N% (weekly)` to the Quota line only for accounts that carry argon data.
97
+ 5. Cross-family auto-failover (`autoFallbackModel`) intentionally does NOT target the argon family: it is a paid-plan-only pool and must not become a silent fallback for exhausted Gemini quota.
98
+ - **Tests**: argon model-id classification; argon summary group lands in `quotas.argon` without clobbering `quotas.google`; accounts without argon access carry no argon entry (row hidden).
99
+
100
+ ### 中文 (Chinese)
101
+
102
+ - **功能:Gemini 4 Argon(Pro/Ultra 专属)现在作为独立的额度家族展示,并显示其单独的周额度。**
103
+ - **背景**:Antigravity 已向付费 Google AI Pro / Ultra 账号开放 **Gemini 4 Argon**,它消耗独立的周额度池(不占用普通 Gemini 额度)。后端在 `retrieveUserQuotaSummary` 中以独立的额度组返回(显示名形如 "Gemini 4 Argon"),并在 `fetchAvailableModels` 中返回 `gemini-4-argon-low/-medium/-high` 模型 ID。
104
+ - **改动**:
105
+ 1. `ModelFamily` 新增 `'argon'`;`modelFamilyOf` 在通用 `gemini-` 前缀判定**之前**优先识别包含 `argon` 的 ID —— 此前 argon 模型会被归入 `google` 家族,其用量会错误地挤占/上报普通 Gemini 计数。
106
+ 2. `QuotaService.refreshAccountQuota` 识别 Argon 额度组(其显示名仍包含 "gemini",因此 argon 判定必须优先)并把周额度桶写入 `quotas.argon`;模型级明细同样按该家族归类。
107
+ 3. GUI 额度面板:仅当后端确实返回了该账号的 argon 额度数据时,才在 Gemini 下方渲染 **Argon** 面板 —— 免费套餐及无 Argon 权限的账号绝不会看到空的 Argon 栏。由于 Argon 目前只有周额度,后端未上报 5 小时窗口时不再显示幽灵的「5 小时额度 —」行。
108
+ 4. `/agy pool` 状态输出仅为携带 argon 数据的账号在 Quota 行尾追加 `| Argon N% (weekly)`。
109
+ 5. 跨家族自动故障转移(`autoFallbackModel`)刻意不指向 argon 家族:它是付费专属额度池,不应在 Gemini 额度耗尽时被静默兜底。
110
+ - **测试**:argon 模型 ID 分类;argon 额度组写入 `quotas.argon` 且不覆盖 `quotas.google`;无 argon 权限的账号不产生 argon 条目(面板隐藏)。
111
+
112
+ ---
113
+
114
+ ## 0.4.55 (2026-10-16)
115
+
116
+ ### English
117
+
118
+ - **Fix: Gemini weekly quota displaying as empty/dash (`—`) after sync.**
119
+ - **Root Cause**: `AGY_ENDPOINTS` placed Google's internal staging endpoint (`https://daily-cloudcode-pa.googleapis.com`) ahead of the official production endpoint (`https://cloudcode-pa.googleapis.com`). While the staging endpoint responds HTTP 200, its `retrieveUserQuotaSummary` output completely omits the `Gemini Models` group (returning only `Claude and GPT models`). Consequently, `QuotaService.fetchQuotaSummary` took the 200 response and locked onto the staging endpoint; `familyQuotas['google']` never received the server's weekly bucket and fell back to model-level 5-hour discovery data (`weeklyFraction: undefined`), resulting in the UI rendering Gemini's weekly quota as `—`.
120
+ - **Resolution**:
121
+ 1. Reordered `AGY_ENDPOINTS` to prioritize the official production endpoint `https://cloudcode-pa.googleapis.com`, matching the official `agy` CLI binary.
122
+ 2. Added a completeness gate in `fetchQuotaSummary`: if an endpoint returns a partial summary that omits the primary `Gemini Models` group, `QuotaService` continues falling through to the remaining endpoints until a complete summary is obtained, rather than locking onto the partial staging response.
123
+ - **Feature/Fix: auto-repair common LLM Mermaid syntax flaws and graceful fallback.**
124
+ - **Auto-repair (`repairMermaidSource`)**: When models produce flowchart/graph diagrams with common pseudo-code syntax flaws (e.g. using `+` to join nodes `A + B --> C + D` instead of `A & B --> C & D`, unquoted subgraph titles with colons/spaces like `subgraph 链条1: 工具打制`, or node labels containing unquoted special characters like `T[人口 > 12]`, `S[私有制: 守罐人]`), the client-side renderer now automatically heals these patterns before passing to Mermaid, enabling diagrams to render successfully without errors.
125
+ - **Graceful fallback for auto-sniffed blocks**: If an unrecognized code block (`代码块`) sniffed as Mermaid fails parsing even after auto-repair, the plugin now silently falls back to displaying it as a normal clean code block without rendering an intrusive `Mermaid render failed:` error banner under it.
126
+
127
+ - **Fix: DSH "Stop generating" (停止生成) button failing in multi-turn tool continuation spans and queues.**
128
+ - **Root Cause**: While single-turn initial spans wired `options.signal` to process termination, tool continuation spans (`detectContinuation(messages) !== null`) and live run debounce rescue invoked `driveSpan` without forwarding `options.signal`. Furthermore, `driveSpanBody` lacked an `abort` event listener, causing the generator to wait indefinitely on `rec.eventsFrom(from)` even when DSH signaled an abort. Similarly, queued requests blocked on `Semaphore.acquire()` did not observe `signal` cancellations.
129
+ - **Resolution**:
130
+ 1. Forwarded `options.signal` across all `driveSpan` callsites (continuation, debounce rescue, and initial span).
131
+ 2. Attached an `abort` listener in `driveSpanBody` that immediately calls `rec.requestAbort?.()`, terminates the underlying `agy` process, pushes `{ type: 'finish', reason: { kind: 'aborted' } }` into the chunk queue, and closes the stream iterator cleanly.
132
+ 3. Added `signal` cancellation support to `Semaphore.acquire(signal)` and burst throttle backoff to release queued requests immediately upon abort.
133
+ - **Fix/Feature: Mermaid rendering swallowing source code, wide layout collapse, and interactive view toggle.**
134
+ - **Root Cause**:
135
+ 1. Language detection in `fenceLang` matched DSH's generic banner text `"代码块"`, erroneously treating explicitly tagged ````mermaid```` blocks as untagged generic blocks.
136
+ 2. Large multi-subgraph flowcharts using Chromium's default `<foreignObject>` HTML labels collapsed into invisible blank boxes when constrained by `max-width: 100%`.
137
+ 3. When Mermaid rendering threw or produced an error SVG, the CSS rule hiding code blocks paired with the suppression of error text resulted in swallowing all content—leaving a completely blank white container.
138
+ - **Resolution**:
139
+ 1. Corrected `fenceLang` to inspect code block classes and attributes before falling back to banner labels.
140
+ 2. Configured Mermaid with `flowchart: { htmlLabels: false }` to render reliable native SVG `<text>` elements, eliminating the Chromium `<foreignObject>` blank-paint bug.
141
+ 3. Added an interactive `查看源码 / 查看图表` toggle button allowing users to switch between the visual diagram and raw Mermaid source code at any time.
142
+ 4. Guarded against swallowed content: when rendering fails, the original code remains 100% visible alongside a subtle warning banner, ensuring source content is never lost.
143
+
144
+ ### 中文 (Chinese)
145
+
146
+ - **修复:DSH 界面中点击「停止生成」在多轮工具调用延续期失效的问题。**
147
+ - **根本原因**:在首轮对话中 `options.signal` 正确绑定了进程终止,但在原生工具镜像调用的后续延续轮次(`detectContinuation` 分支)以及防抖拯救调用中,`driveSpan` 均未向下传递 `options.signal`。此外,`driveSpanBody` 内部没有监听 `signal.abort` 事件,导致用户在 DSH 点击停止时,生成器依旧停在 `eventsFrom` 等待事件流,后台进程未被杀死,界面停止按钮卡住无效。同时跨会话并发信号量 `Semaphore.acquire()` 在排队等待时也未响应取消信号。
148
+ - **解决方案**:
149
+ 1. 在所有 `driveSpan` 调用处(工具延续、防抖拯救、首轮启动)完整传递 `options.signal`。
150
+ 2. 在 `driveSpanBody` 挂载 `abort` 监听器:一旦收到取消信号,立即触发 `rec.requestAbort?.()` 杀死底层 `agy` 进程,向输出队列推送 `{ type: 'finish', reason: { kind: 'aborted' } }` 并安全关闭队列,使 DSH 的流式迭代器瞬间退出。
151
+ 3. 升级 `Semaphore.acquire(signal)` 及并发节流延时,支持在排队中收到 abort 信号时立即退出并清理队列,杜绝无意义挂起。
152
+ - **修复/功能:Mermaid 图表内容被吞、超宽图表缩放空白及源码交互式切换。**
153
+ - **根本原因**:
154
+ 1. `fenceLang` 语言嗅探提取到了 DSH 顶部横幅文本 `"代码块"`,导致显式声明为 ````mermaid```` 的图表被误当成未指定语言的通用块。
155
+ 2. Mermaid 默认使用 HTML `<foreignObject>` 标签渲染文本,在 Chromium / Electron 宿主中遇到多子图超宽流程图(如 >3000px)并应用 `max-width: 100%` 缩放时,极易发生文本排版崩溃或整体空白不渲染的 bug。
156
+ 3. 当 Mermaid 渲染报错或生成空图时,由于隐藏原生代码块的 CSS 规则生效且错误提示被隐藏,导致原始代码和图表全部消失,形成一片空白区域(内容被吞)。
157
+ - **解决方案**:
158
+ 1. 修正 `fenceLang`:优先读取 `code` 标签 class 及属性,忽略无意义的横幅标签 `"代码块"`。
159
+ 2. 优化渲染配置:初始化 Mermaid 时启用 `flowchart: { htmlLabels: false }`,使用原生 SVG `<text>` 渲染节点,彻底规避 Chromium `<foreignObject>` 缩放渲染空白的底层缺陷。
160
+ 3. 增加交互式切换工具栏:在渲染图表右上角提供「查看源码 / 查看图表」按钮,用户可随时一键切换查看 Mermaid 原始 Markdown 代码与可视化图表。
161
+ 4. 兜底保护机制:若渲染异常,确保原始代码块 100% 完整保留可见,并在上方以友好提示条展示,绝不吞没用户和模型的内容。
162
+
163
+ - **修复:点击「同步」后 Gemini 周额度显示为空/短横杠(`—`)的问题。**
164
+ - **根本原因**:`AGY_ENDPOINTS` 此前将 Google 内部预演端点(`https://daily-cloudcode-pa.googleapis.com`)排在官方生产端点(`https://cloudcode-pa.googleapis.com`)之前。虽然预演端点返回 HTTP 200,但其 `retrieveUserQuotaSummary` 响应中完全缺失了 `Gemini Models` 额度组(仅返回了 `Claude and GPT models`)。这导致 `QuotaService.fetchQuotaSummary` 命中 200 后锁定该端点,`familyQuotas['google']` 无法获取到官方周配额桶,只能回退使用单模型 5 小时数据(`weeklyFraction` 始终为 `undefined`),前端进而将 Gemini 的周额度渲染为 `—`。
165
+ - **解决方案**:
166
+ 1. 调整 `AGY_ENDPOINTS` 顺序:优先请求与官方 `agy` CLI 保持一致的官方生产端点 `https://cloudcode-pa.googleapis.com`。
167
+ 2. 增强 `fetchQuotaSummary` 完整性校验门禁:若端点返回的配额摘要缺失了核心的 `Gemini Models` 组,自动顺次下穿到后续端点获取完整摘要,不再过早锁定仅包含第三方模型的残缺响应。
168
+ - **功能/修复:Mermaid 常见大模型语法自动自愈修复与优雅降级。**
169
+ - **语法自动自愈(`repairMermaidSource`)**:针对大模型输出流程图时高频出现的伪代码语法瑕疵(例如材料合成中用加号连接 `A + B --> C + D`、包含冒号的子图未加引号 `subgraph 链条1: 工具打制`、节点文本包含特殊字符未加引号 `T[人口 > 12]`、`S[私有制: 守罐人]` 等),客户端在解析前自动自愈修正,直接成功渲染图表。
170
+ - **自动嗅探代码块优雅降级**:对于未显式标注为 ````mermaid```` 的通用代码块(语言标签为 `代码块` 或未指定),若自愈后仍无法解析,安静降级为普通代码块展示,不再在代码下方直接打印刺眼的 `Mermaid render failed:` 错误文本。
171
+
172
+ ## 0.4.54 (2026-10-16)
173
+
174
+ ### English
175
+
176
+ - **Fix (macOS): complete resolution for recurring modal keychain password prompts.** Older versions (v0.4.41-v0.4.48) accidentally ran `security default-keychain -s <isolated-kc>`, permanently redirecting the user's desktop session `default-keychain`, `login-keychain`, and user search list (`list-keychains -d user`) to a locked per-account keychain under `~/.dsh/agy-accounts/` created with an un-unlockable random passphrase. On modern macOS, `Library/Keychains/login.keychain-db` is also a special-cased filename that SecurityServer associates with the user's OS login password, rejecting empty-passphrase unlocks. The plugin now:
177
+ 1. Automatically detects and repairs hijacked `default-keychain`, `login-keychain`, and `list-keychains` on boot (`repairMacSystemKeychain`), restoring the real user login keychain (`~/Library/Keychains/login.keychain-db`) safely and idempotently.
178
+ 2. Automatically purges legacy un-unlockable isolated keychains (`purgeStaleIsolatedKeychain`), unregistering them from `securityd` and deleting conflicting files so SecurityAgent never raises unanswerable password dialogs.
179
+ - **Feature (Multi-platform): comprehensive cross-platform logic unification.**
180
+ 1. **Unified Terminal Launcher (`openAccountTerminal`)**: Fully unified interactive terminal launching across macOS (AppleScript Terminal.app), Windows (`cmd.exe /c start` with `USERPROFILE` + `HOME` environment and `windowsHide: true`), and Linux (adaptive detection across `xdg-terminal-exec`, `x-terminal-emulator`, `gnome-terminal`, `konsole`, `xfce4-terminal`, `alacritty`, `xterm`).
181
+ 2. **Unified System Proxy Detection (`detectSystemProxy`)**: Automatically discovers system-wide proxy settings for GUI environments where shell env vars are missing—supporting macOS (`scutil --proxy`), Windows Registry (`HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`), Linux desktop (`gsettings` GNOME proxy mode), and fallback environment variables (`ALL_PROXY`, `HTTPS_PROXY`, `HTTP_PROXY`).
182
+ 3. **Cross-Platform Credential Isolation**: Standardized credential boundaries across platforms—Windows Credential Manager targeted isolation, macOS isolated throwaway keychains with auto-repair, and standard Unix file-based isolation.
183
+
184
+ ### 中文 (Chinese)
185
+
186
+ - **修复(macOS):彻底解决钥匙串密码弹窗反复弹出问题。** v0.4.41-v0.4.48 曾调用 `security default-keychain -s <isolated-kc>`,导致用户的桌面会话全局 `default-keychain`、`login-keychain` 以及用户搜索列表被持久化重定向到了 `~/.dsh/agy-accounts/` 下由旧版本生成的随机密码隔离钥匙串中。此外 macOS 的 SecurityServer 会对名为 `login.keychain-db` 的路径做特殊绑定,强制要求系统用户登录密码,导致空密码解锁失败并引发系统 SecurityAgent 弹窗提示输入密码。本次修复:
187
+ 1. 插件启动时自动执行 `repairMacSystemKeychain`:检测并修复被篡改的 `default-keychain`、`login-keychain` 与用户搜索列表,自动恢复为用户真实的登录钥匙串(`~/Library/Keychains/login.keychain-db`),幂等且安全。
188
+ 2. 自动检测并清理历史遗留的无法解锁的废弃钥匙串(`purgeStaleIsolatedKeychain`),从 `securityd` 会话中彻底注销并删除文件,阻断 SecurityAgent 弹出任何死循环密码框。
189
+ - **功能(多平台):全面梳理并实现 Windows、macOS、Linux 跨平台逻辑统一。**
190
+ 1. **多平台统一终端唤醒器(`openAccountTerminal`)**:彻底统一账号登录终端的唤醒逻辑,原生支持 macOS(AppleScript 激活 Terminal.app)、Windows(`cmd.exe /c start` 注入 `USERPROFILE` + `HOME` 隔离目录并设置 `windowsHide: true` 避免控制台闪烁)以及 Linux(自适应探测 `xdg-terminal-exec`、`x-terminal-emulator`、`gnome-terminal`、`konsole`、`xfce4-terminal`、`alacritty`、`xterm` 等各种桌面环境)。
191
+ 2. **多平台系统代理自动感知(`detectSystemProxy`)**:针对 GUI 宿主未继承终端 Shell 代理环境变量的场景,全面支持三端系统级代理自动检测——macOS(`scutil --proxy` 解析 HTTP/HTTPS/SOCKS)、Windows(读取注册表 WinINet Internet Settings 代理设置)、Linux(通过 `gsettings` 读取 GNOME 桌面代理配置)以及标准环境变量兜底。
192
+ 3. **多平台凭据与隔离统一**:规范各端凭据存储边界——Windows 使用 Credential Manager 目标隔离、macOS 使用独立钥匙串配给加自愈防篡改机制、Linux 使用标准 Unix 用户目录隔离。
193
+
3
194
  ## 0.4.53 (2026-10-15)
4
195
 
5
196
  ### English
package/README.md CHANGED
@@ -24,7 +24,7 @@
24
24
 
25
25
  # 中文
26
26
 
27
- 把 **Google Antigravity 模型接入 DeepSeek Harness(DSH)** —— 支持**多账号智能池化轮换**、**官方双 Bucket 配额监控(5小时滚动 + 7天周额度)**、**浏览器免粘贴一键登录**与**浅色/深色主题高对比度自适应**,由官方未修改的 `agy` CLI 驱动,完整支持流式输出、思考折叠(thinking)、原生工具卡片与精确 token 用量。
27
+ 把 **Google Antigravity 模型接入 DeepSeek Harness(DSH)** —— 支持**多账号智能池化轮换**、**官方多 Bucket 配额监控(5小时滚动 + 7天周额度 + Argon 独立周池)**、**浏览器免粘贴一键登录**与**浅色/深色主题高对比度自适应**,由官方未修改的 `agy` CLI 驱动,完整支持流式输出、思考折叠(thinking)、原生工具卡片与精确 token 用量。
28
28
 
29
29
  <p align="center">
30
30
  <img src="./docs/assets/dashboard.png" alt="Antigravity 管理控制台 - 多账号池化与配额监控" width="460" />
@@ -54,11 +54,14 @@
54
54
 
55
55
  - 👥 **多账号池化管理 (Account Pool)**:在 DSH 内添加任意数量的 Google 账号(主账号 + 备用账号群),每个账号拥有独立的 HOME 目录沙箱与凭证隔离。
56
56
  - 🔄 **顺序耗尽故障转移 (Sequential Drain)**:当前账号额度用尽(触发 429 限流或 5h / 周额度耗尽)时,系统**自动平滑接力至下一个可用账号**,对话完全不中断!
57
- - 📊 **官方双 Bucket 配额监控 (Dual-Bucket Quota)**:直接调用 Antigravity 官方专用的 `v1internal:retrieveUserQuotaSummary` 接口,同时展示 **5小时滚动额度** 与 **7天周额度** 真实数据及精准重置倒计时。
57
+ - 🕰 **额度到期优先轮换 (Quota-Expiry-First)**:多个账号可用时,优先切换到**重置窗口最早到期**的账号,把"还剩很久才重置"的额度留给后面,整体池化利用率最大化。
58
+ - 🧠 **网络抖动智能甄别 (Jitter-Safe Auth)**:代理抖动导致的 keyring 鉴权超时会被自动识别为**可重试的网络错误**而非"登录失效"——基于 agy 本次运行日志的 `keyringAuth` 传输证据精准分类,且粘性"需重新登录"隔离需二次确认,健康账号绝不会被误标。
59
+ - 📊 **官方多 Bucket 配额监控 (Multi-Bucket Quota)**:直接调用 Antigravity 官方专用的 `v1internal:retrieveUserQuotaSummary` 接口,同时展示 **5小时滚动额度**、**7天周额度**,以及付费 Pro/Ultra 账号专属的 **Gemini 4 Argon 独立周额度池**(不占用普通 Gemini 池)。
60
+ - 🔀 **手动切换当前账号 (Manual Switch-Active)**:控制台卡片一键「设为当前使用」,即刻把调度指针钉到指定账号。
58
61
  - 🔑 **GUI 内浏览器免粘贴登录 (In-GUI Zero-Paste OAuth)**:点击「➕ 添加账号」自动调起系统浏览器,本地回环监听自动捕获授权凭证,**全程无需手动复制粘贴授权码**。
59
62
  - 🎨 **多主题高对比度自适应 (Light & Dark Themes)**:原生适配 DSH 浅色/深色主题,告别发暗发灰与看不清文字,UI 视觉清晰锐利。
60
- - 🌐 **独立账号网络代理 (Per-Account Proxy)**:支持为每个账号独立绑定 HTTP(S) / SOCKS 代理,避免多账号同 IP 引起风控。
61
- - ⚡ **分模型族独立冷却 (Family-Scoped Cooldown)**:Gemini 与 Claude / GPT-OSS 速率限制独立计算,某个模型族受限不影响其他模型族正常调用。
63
+ - 🌐 **独立账号网络代理 (Per-Account Proxy)**:支持为每个账号独立绑定 HTTP(S) / SOCKS 代理,避免多账号同 IP 引起风控;未显式配置时自动探测系统代理(macOS `scutil` / Windows 注册表 / Linux gsettings)。
64
+ - ⚡ **分模型族独立冷却 (Family-Scoped Cooldown)**:Gemini、Claude、GPT-OSS 与 Argon 的速率限制独立计算,某个模型族受限不影响其他模型族正常调用。
62
65
 
63
66
  ---
64
67
 
@@ -66,20 +69,23 @@
66
69
 
67
70
  | 能力 | 说明 |
68
71
  | ---- | ---- |
69
- | 👥 **多账号池化轮换** | 支持主账号 + 多个备用账号;遇到 429 或配额耗尽自动平滑切换,模型族独立冷却 |
70
- | 📊 **官方双 Bucket 配额监控** | 实时拉取官方端点,同时呈现 **5h 滚动额度** 与 **7d 周额度** 双进度条与倒计时,单模型明细可展开 |
72
+ | 👥 **多账号池化轮换** | 支持主账号 + 多个备用账号;遇到 429 或配额耗尽自动平滑切换,模型族独立冷却,额度到期早的账号优先接班 |
73
+ | 🧠 **抖动安全鉴权 (Jitter-Safe Auth)** | 基于 agy 运行日志的 keyring 传输证据区分"网络抖动"与"真登出",抖动自动按可重试网络错误处理;粘性隔离需二次确认,杜绝误标"需重新登录" |
74
+ | 📊 **官方多 Bucket 配额监控** | 实时拉取官方端点,同时呈现 **5h 滚动额度**、**7d 周额度**与 **Argon 独立周池**(付费 Pro/Ultra)多进度条与倒计时,单模型明细可展开 |
71
75
  | 🔑 **浏览器一键登录** | 点击添加账号自动唤起 Google 授权页,本地回环自动捕获,全程无需复制粘贴任何代码 |
76
+ | 🔀 **手动切换当前账号** | 控制台「设为当前使用」按钮即刻钉住调度指针;顶部徽标始终显示服务器实际调度的账号 |
72
77
  | 🎨 **多主题高对比 UI** | 浅色、深色主题自适应变色,纯矢量 SVG 图标(无 Emoji),字迹清晰不发暗 |
73
- | 🌐 **独立账号代理** | 每个账号支持独立配置 HTTP(S) 代理,隔离 IP 出口 |
74
- | 🔌 **原生模型路由** | 在 DSH 模型配置中注册 `antigravity` 提供方,`/model` 选择器随心切换 Gemini / Claude / GPT-OSS |
78
+ | 🌐 **独立账号代理** | 每个账号支持独立配置 HTTP(S) 代理,隔离 IP 出口;亦可自动探测系统代理 |
79
+ | 🔌 **原生模型路由** | 在 DSH 模型配置中注册 `antigravity` 提供方,`/model` 选择器随心切换 Gemini / Claude / GPT-OSS / Argon |
75
80
  | 🌊 **完整流式映射** | 文本、思考过程(thinking turn)与工具活动均无损映射到 DSH 原生流协议 |
76
81
  | 🃏 **原生工具卡片** | agy 执行的终端命令(`run_command`)、文件修改(inline diff)均以 DSH 原生卡片渲染 |
77
82
  | 🔗 **会话上下文保真** | DSH 会话与 agy 原生会话绑定(`--conversation`),由 agy 管理完整历史,每轮仅发送增量 |
83
+ | 🎯 **DSH 目标与计划集成** | 长任务自动携带 DSH goal / plan 上下文,工具续跑不丢任务状态 |
78
84
  | 📊 **精确 Token 统计** | 输入 / 输出 / 思考 / 缓存读取 token 完整计入 DSH 用量统计,全面适配 1M 上下文 |
79
85
  | 🎛 **顶部控制台徽标** | 顶部栏 `AGY (n)` 徽标一键弹出控制台,直观查看账号池、配额进度条与代理状态 |
80
86
  | 🖼 **图片多模态** | 支持多模态图片传入,自动落盘本地媒体目录并通过 `--add-dir` 安全授权给 agy 查看 |
81
87
  | 🤝 **`agy_ask` 辅助工具** | 允许任意 DSH 模型把单次任务委托给 Antigravity 模型(AskAntigravity 协作模式) |
82
- | ⌨️ **`/agy` 快捷命令族** | `status` / `auth` / `models` / `mode` / `effort` / `workspace` / `clear` / `doctor` / `help` |
88
+ | ⌨️ **`/agy` 快捷命令族** | `status` / `pool` / `auth` / `models` / `mode` / `effort` / `workspace` / `goal` / `session` / `enable-account` / `disable-account` / `clear` / `doctor` / `help` |
83
89
 
84
90
  ---
85
91
 
@@ -144,8 +150,9 @@ dsh plugin --profile web add dsh-agy-link
144
150
 
145
151
  1. **短生命周期进程驱动**:每一轮 DSH 对话启动一个独立的官方 `agy -p --output-format stream-json` 进程,解析 NDJSON 事件流。
146
152
  2. **多账号沙箱机制**:除主账号沿用系统默认 Keychain / HOME 外,所有备用账号在插件私有目录下建立专属 HOME 隔离区,独立写入 agy 格式的标准 OAuth 凭证。
147
- 3. **双 Bucket 官方配额汇总**:插件定时后台静默轮询官方 `v1internal:retrieveUserQuotaSummary`,精准掌控每个账号的 5h 滚动削峰水位与 7d 账号阶梯周额度。
148
- 4. **会话级无缝故障转移**:当遭遇 HTTP 429、额度耗尽或凭证异常时,号池调度器自动标记当前账号家族进入冷却,并无缝将后续请求路由到池内下一个有效账号。
153
+ 3. **多 Bucket 官方配额汇总**:插件定时后台静默轮询官方 `v1internal:retrieveUserQuotaSummary`,精准掌控每个账号的 5h 滚动削峰水位、7d 账号阶梯周额度,以及付费账号的 Argon 独立周池。
154
+ 4. **会话级无缝故障转移**:当遭遇 HTTP 429、额度耗尽或凭证异常时,号池调度器自动标记当前账号家族进入冷却(或按额度到期时间择优轮换),并无缝将后续请求路由到池内下一个有效账号。
155
+ 5. **失败分类与自愈**:错误按 AUTH / NETWORK / RATE_LIMIT / ELIGIBILITY 等精确分类;网络抖动借由 agy 运行日志自动甄别为可重试故障,绝不误伤健康账号的登录状态。
149
156
 
150
157
  ---
151
158
 
@@ -170,7 +177,7 @@ MIT License.
170
177
 
171
178
  # English
172
179
 
173
- Bring **Google Antigravity models into DeepSeek Harness (DSH)** — featuring **Multi-Account Pooling & Automatic Rotation**, **Official Dual-Bucket Quota Tracking (5h Rolling + 7d Weekly)**, **Zero-Paste In-GUI OAuth Login**, and **Theme-Adaptive High-Contrast UI**, powered by the official unmodified `agy` CLI.
180
+ Bring **Google Antigravity models into DeepSeek Harness (DSH)** — featuring **Multi-Account Pooling & Automatic Rotation**, **Official Multi-Bucket Quota Tracking (5h Rolling + 7d Weekly + Argon Weekly Pool)**, **Zero-Paste In-GUI OAuth Login**, and **Theme-Adaptive High-Contrast UI**, powered by the official unmodified `agy` CLI.
174
181
 
175
182
  <p align="center">
176
183
  <img src="./docs/assets/dashboard.png" alt="Antigravity Management Console - Multi-Account Pool & Quota Monitor" width="460" />
@@ -199,11 +206,14 @@ Have multiple Google Antigravity / Gemini accounts? **dsh-agy-link makes multi-a
199
206
 
200
207
  - 👥 **Multi-Account Pooling**: Manage unlimited Google accounts (Primary + Secondary pool) with fully isolated HOME sandbox environments and credentials.
201
208
  - 🔄 **Sequential Drain Failover**: When an account reaches its rate limits (429) or runs out of 5h/weekly quotas, requests **automatically and smoothly fail over to the next available account** without interrupting your conversation!
202
- - 📊 **Official Dual-Bucket Quota Tracking**: Direct integration with Antigravity's official `v1internal:retrieveUserQuotaSummary` endpoint, providing real-time visibility for both **5-Hour Rolling Limit** and **7-Day Weekly Limit** with live countdowns.
209
+ - 🕰 **Quota-Expiry-First Rotation**: With several accounts available, the scheduler prefers the one whose **reset window expires soonest**, maximizing utilization across the whole pool.
210
+ - 🧠 **Jitter-Safe Auth Classification**: A keyring-auth timeout caused by proxy jitter is recognized as a **retryable network error**, not a sign-out — classified from the `keyringAuth` transport evidence in agy's own run log, and sticky "needs re-login" quarantine requires a second confirmation, so healthy accounts are never falsely flagged.
211
+ - 📊 **Official Multi-Bucket Quota Tracking**: Direct integration with Antigravity's official `v1internal:retrieveUserQuotaSummary` endpoint, providing real-time visibility for the **5-Hour Rolling Limit**, the **7-Day Weekly Limit**, and the **Gemini 4 Argon weekly pool** (paid Pro/Ultra accounts, billed separately from the plain Gemini pool).
212
+ - 🔀 **Manual Switch-Active**: One click on "Set active" pins the scheduler pointer to the account you choose.
203
213
  - 🔑 **In-GUI Zero-Paste OAuth**: One-click "Add Account" opens your browser and automatically captures OAuth tokens via local loopback — **no copying and pasting of authorization codes required**.
204
214
  - 🎨 **Theme-Adaptive High-Contrast UI**: Seamlessly adapts to Light and Dark DSH themes with crystal clear typography and crisp contrast.
205
- - 🌐 **Per-Account Proxy**: Configure dedicated HTTP(S) / SOCKS proxy for each individual account to isolate IP addresses.
206
- - ⚡ **Family-Scoped Cooldowns**: Gemini, Claude, and GPT-OSS rate limits are calculated independently, preventing one exhausted model from blocking others.
215
+ - 🌐 **Per-Account Proxy**: Configure dedicated HTTP(S) / SOCKS proxy for each individual account to isolate IP addresses; when unset, the system proxy is auto-detected (macOS `scutil` / Windows registry / Linux gsettings).
216
+ - ⚡ **Family-Scoped Cooldowns**: Gemini, Claude, GPT-OSS, and Argon rate limits are calculated independently, preventing one exhausted model from blocking others.
207
217
 
208
218
  ---
209
219
 
@@ -211,20 +221,23 @@ Have multiple Google Antigravity / Gemini accounts? **dsh-agy-link makes multi-a
211
221
 
212
222
  | Feature | Description |
213
223
  | --- | --- |
214
- | 👥 **Multi-Account Pool** | Primary + unlimited spare accounts with automatic Sequential Drain rotation upon rate limits |
215
- | 📊 **Dual-Bucket Quota HUD** | Real-time dual progress bars for both **5h rolling** and **7d weekly** quota limits with exact reset countdowns |
224
+ | 👥 **Multi-Account Pool** | Primary + unlimited spare accounts with automatic Sequential Drain rotation upon rate limits; quota-expiry-first scheduling |
225
+ | 🧠 **Jitter-Safe Auth** | Distinguishes network jitter from a real sign-out via keyring transport evidence in agy's run log; sticky quarantine requires confirmation — no false "needs re-login" flags |
226
+ | 📊 **Multi-Bucket Quota HUD** | Real-time progress bars for the **5h rolling**, **7d weekly**, and **Argon weekly** (paid Pro/Ultra) pools with exact reset countdowns |
216
227
  | 🔑 **Zero-Paste Browser Login** | Automatic browser-based Google OAuth login with loopback callback handler |
228
+ | 🔀 **Manual Switch-Active** | Pin the scheduler to any account from the console; the header badge always names the server-scheduled account |
217
229
  | 🎨 **Theme-Adaptive UI** | Dynamic light/dark theme switching, pure SVG vector marks (no emojis), high contrast |
218
- | 🌐 **Per-Account Proxy** | Dedicated HTTP(S) proxy per account slot |
219
- | 🔌 **Native Model Routing** | Registers `antigravity` provider in DSH; choose Gemini / Claude / GPT-OSS in `/model` picker |
230
+ | 🌐 **Per-Account Proxy** | Dedicated HTTP(S) proxy per account slot, or auto-detected system proxy |
231
+ | 🔌 **Native Model Routing** | Registers `antigravity` provider in DSH; choose Gemini / Claude / GPT-OSS / Argon in `/model` picker |
220
232
  | 🌊 **Full Streaming Protocol** | Native streaming for text, thinking turn annotations, and tool calls |
221
233
  | 🃏 **Native Tool UI Cards** | Command runs and inline diffs render as clean, native DSH tool cards |
222
234
  | 🔗 **Session Continuity** | Binds DSH sessions to native agy conversations (`--conversation`) for zero-redundancy context |
235
+ | 🎯 **DSH Goal & Plan Integration** | Long-running tasks carry DSH goal / plan context across tool continuations |
223
236
  | 📊 **Accurate Token Metering** | Input, output, thinking, and cacheRead tokens are fully reported to DSH with 1M context support |
224
237
  | 🎛 **Top Header Console Badge** | Click the `AGY (n)` badge in the header to instantly open the management console |
225
238
  | 🖼 **Multimodal Images** | Stages images to local storage and passes safe absolute paths via `--add-dir` |
226
239
  | 🤝 **`agy_ask` Delegation** | Allows other DSH models to delegate subtasks to Antigravity models |
227
- | ⌨️ **`/agy` Commands** | Full command suite: `status`, `auth`, `models`, `mode`, `effort`, `workspace`, `clear`, `doctor`, `help` |
240
+ | ⌨️ **`/agy` Commands** | Full command suite: `status`, `pool`, `auth`, `models`, `mode`, `effort`, `workspace`, `goal`, `session`, `enable-account`, `disable-account`, `clear`, `doctor`, `help` |
228
241
 
229
242
  ---
230
243
 
@@ -273,6 +286,7 @@ dsh plugin --profile web add dsh-agy-link
273
286
  | `defaultEffort` | `DSH_AGY_DEFAULT_EFFORT` | `(model default)` | Thinking budget: `low` / `medium` / `high` |
274
287
  | `hiddenModels` | `DSH_AGY_HIDDEN_MODELS` | `[]` | Model slugs hidden from the `/model` picker (deny-list, newly discovered models stay visible; manage them via the "Model visibility" row in the settings panel) |
275
288
  | `timeoutMs` | `DSH_AGY_TIMEOUT_MS` | `600000` | Activity watchdog timeout in milliseconds |
289
+ | `longToolIdleMinutes` | `DSH_AGY_LONG_TOOL_IDLE_MINUTES` | `240` | Idle budget while a tool step is ACTIVE (minutes); `0` keeps the normal `timeoutMs` budget so wedged tools fail fast |
276
290
  | `workspaceRoot` | `DSH_AGY_WORKSPACE_ROOT` | session cwd | Working directory root |
277
291
 
278
292
  ---