Repository navigation
Add Hermes, Antigravity, Z.ai, Ollama Cloud, MiniMax, OpenRouter, and DeepSeek to the agents panel - #14039
Add Hermes, Antigravity, Z.ai, Ollama Cloud, MiniMax, OpenRouter, and DeepSeek to the agents panel#14039dhh wants to merge 19 commits into
Conversation
Co-authored-by: Scott Cashman <scottc2789@gmail.com>
Profile discovery follows #6647 by Mustafa Okur. Drops the --write mode, reports the week's tokens by day like the other collectors, and lists Hermes in the panel's defaults, README, and the manual. Co-authored-by: Mustafa Okur <mustafaokur2005@gmail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add the omarchy-agent-usage-antigravity collector to monitor Google Antigravity usage alongside the other agents in the agents bar panel. Authoritative subscription tier and quota limits (rolling 5-hour session, weekly limits, and scoped 3P model allowances) are probed from the Google Cloud Code API via Secret Service keyring credentials with rolling local history estimation as fallback.
The record shares the id omarchy-default-agent and omarchy-agent use for the CLI. Limits now come only from Google's quota answer, kept from the last good check and marked stale (limitsStale, limitsFetchedAt) after a failed one, instead of being estimated from prompt counts. The plan is no longer assumed to be Pro, and transcript steps without reported usage no longer get estimated tokens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Felipe Mayer <mayer.felipe@outlook.com>
Limits kept from an earlier check after a failed one now carry limitsStale and limitsFetchedAt, so the panel dims them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ship omarchy-agent-usage-ollama, which reads the account's 5-hour session and 7-day weekly limits from Ollama's usage endpoint and local token stats from pi and omp sessions on the ollama-cloud provider.
Ollama's usage endpoint names no reset times, and the epoch-aligned windows the collector computed were an unproven guess, so the limits now carry none. Limits kept after a failed check carry limitsStale and limitsFetchedAt, a record without local stats no longer claims some, and the manual mentions Ollama Cloud. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The collector part of #9597: the Token Plan's 5-hour and weekly quota from MiniMax's API, with the key from MINIMAX_API_KEY, mmx, or opencode.
A failed check now keeps the last good limits, marked with limitsStale and limitsFetchedAt, instead of dropping them. Without a key the record has no plan, so the panel skips it. Help text no longer points at the mmx CLI, which Omarchy doesn't install, and the manual mentions MiniMax. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A failed /key lookup no longer throws away the token stats and balance: the last good key-limit meter stays, marked with limitsStale and limitsFetchedAt. limit_reset names a period (daily, weekly, monthly), not a time, so it labels the meter instead of filling resetsAt. Without a key the record has no plan, so the panel skips it. The manual mentions OpenRouter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Counts shared DeepSeek days once and keeps refreshes quiet.
The record claimed to be ready with a Prepaid plan for everyone, which put a DeepSeek section in every panel. Ready and the plan now follow the key. The test no longer reaches DeepSeek when DEEPSEEK_API_KEY is set, and the manual mentions DeepSeek. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A server stalling on headers or body raised TimeoutError past the OpenRouterError handlers, so the record went blank instead of keeping its stats and last key-limit meter and asking for a retry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A management key without an inference key returned an empty record before /activity was asked. Now either key collects: the management key alone brings the 30-day history and the balance, with no key-limit meter, since that belongs to an inference key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The cached scan was reused by age alone, so just after midnight yesterday's tokens showed as today's, and a changed modelPrefix kept showing excluded models for up to 15 minutes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
During an outage the fallback republished cached windows even after they had reset, so an exhausted session could stay on screen. Windows past their reset are now dropped; open ones and those without a reset time stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
| if kept and not force and time.time() - fetched_at / 1000 < PROBE_REUSE_SECONDS: | ||
| result.update(limits=kept, live=True) | ||
| return result |
There was a problem hiding this comment.
Limits leak across accounts If a user switches Antigravity accounts and opens the panel within 60 seconds, this code shows the previous account’s quota and plan as fresh without checking the new account. Z.ai and Ollama also reuse limits across keys; MiniMax and OpenRouter can show another account’s limits when a probe fails. The cache needs to distinguish the credential or account that produced each result.
| for path in paths: | ||
| try: | ||
| scan(path, totals, today, week) | ||
| read += 1 | ||
| except sqlite3.Error: | ||
| status = "Hermes state unreadable" |
There was a problem hiding this comment.
Failed scans leave partial totals If a Hermes profile database fails a query after earlier queries have added counts, the error is caught but those counts remain. When another profile scans successfully, the panel receives a mix of complete and partial results, so its session and prompt totals are wrong. Merge a profile’s counts only after its entire scan succeeds.
| if fallback: | ||
| result["limits"] = fallback |
There was a problem hiding this comment.
Expired quotas remain visible If Ollama’s usage endpoint stays unavailable past a five-hour or weekly rollover, this fallback keeps showing the previous window’s percentage because the cached limits have no reset time or age limit. The panel may display that old quota indefinitely, even though it is dimmed. OpenRouter’s cached key-limit meter has the same problem. Bound how long these cached meters can stand in for current limits.
| # mkstemp opens at 0600; these caches were world-readable before. | ||
| tmp.chmod(0o644) | ||
| tmp.replace(path) |
There was a problem hiding this comment.
Activity caches become world-readable This changes the Ollama session cache from owner-only mode to
0644; the Z.ai and OpenRouter cache writers do the same. If the home and cache directories are traversable, another local user can read cached model names, activity dates, and token counts. Keeping these usage caches owner-readable avoids that disclosure. How this was verified: The session-statistics writer stores activity summaries in a cache file and explicitly changes that file’s mode to 0644.
There was a problem hiding this comment.
Thanks for bringing this in, @dhh!
This is specifically about bin/omarchy-agent-usage-agy, carried over from my #11989. Some later fixes didn’t make it into this version.
My final revision, f008cf6, uses version-gated CLI quota checks, removes quota caching to avoid cross-account reuse, preserves unused Claude/GPT allowances, and merges history/transcript prompt counts.
Could you carry over the final bin/omarchy-agent-usage-antigravity implementation and its regression tests, adapting the collector id to agy?
That should also address the Antigravity portion of Greptile’s account-switch finding.
|
Heads up on Running the collector against real Root CauseAntigravity's In Python: parsed = datetime.fromisoformat('0001-01-01 00:00:00+00:00')
parsed.astimezone() # In UTC-5 (or any negative offset), rolls into year 0000 -> OverflowErrorRecommended FixIn def local_day(value):
try:
parsed = parse_time(value)
if not parsed or parsed.year < 1970:
return ""
return parsed.astimezone().date().isoformat()
except (ValueError, OverflowError):
return "" |
|
+1 to @ChaseC-130's report on $ TZ=America/New_York python3 -c "from datetime import datetime; datetime.fromisoformat('0001-01-01 00:00:00+00:00').astimezone()"
OverflowError: date value out of rangeNothing catches the error between def local_day(value):
parsed = parse_time(value)
if not parsed or parsed.year < 1970:
return ""
try:
return parsed.astimezone().date().isoformat()
except (OverflowError, ValueError, OSError):
return ""A smaller point: the Ollama, Z.ai and OpenRouter cache writers Also +1 to @steph4n-gh's request to carry over the final Antigravity revision (f008cf6). It drops the quota cache, which also covers the Antigravity part of Greptile's account-switch finding. |
|
The Antigravity part of this PR is split out in #14704, rebased onto current |
…agents panel PR Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
The icons above look good to me.
https://api-docs.deepseek.com/img/logo-mark-dark.svg
https://api-docs.deepseek.com/img/logo-mark-light.svg
Brings in seven community collectors for the agents panel, each as its author's commit followed by adaptations to the current panel and record contract.
state.db, now honoringHERMES_HOMEand every named profileagy)loadCodeAssist/retrieveUserQuotaSummary, with the token from the keyringglm-*/activityAPIAdaptations
limitsStale/limitsFetchedAt, so the panel dims them with their age, like Claude and Grok. Cached windows past their reset are dropped, and day-bound caches are only reused on their day.agy, matching the default-agent id; dropped the limits invented from prompt counts, the assumed plan, the made-up token counts, and its Panel.qml change.mmxinstall, the Setup menu entry, and the migration.limit_resetlabels the meter's period instead of posing as a reset time, read timeouts fall back to local stats and the last meter, and a management key alone is enough for history and balance.recentDayscarries tokens like the other collectors, and the--writemode is gone.Not verified
The collectors were only run against fakes and with
--help, never against the real services or anyone's credentials. The Antigravity endpoint and keyring entry, and the Ollama, MiniMax, Z.ai, DeepSeek, and OpenRouter response shapes, come from the original PRs. The panel wasn't checked visually with these records.Tests
Each collector's tests, plus new ones for stale limits, skipped records,
HERMES_HOMEand profiles, OpenRouter timeouts and management-only keys, Ollama's day-bound cache, and MiniMax's reset windows. All agent tests and./test/clipass, apart fromvscode generated theme references current theme file, which fails the same way onquattro. Reviewed withcodex review --base quattro; its four findings are fixed.🤖 Generated with Claude Code