Skip to content

fix(antigravity): fetch quota when the IDE is closed - #236

Merged
Nanako0129 merged 6 commits into
Nanako0129:mainfrom
iF2007:fix/antigravity-cli-quota
Aug 25, 2026
Merged

fix(antigravity): fetch quota when the IDE is closed#236
Nanako0129 merged 6 commits into
Nanako0129:mainfrom
iF2007:fix/antigravity-cli-quota

Conversation

@iF2007

@iF2007 iF2007 commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Problem

When the Antigravity IDE is closed, TokenBar cannot use the local IDE API. The previous OAuth client discovery could also fail to obtain a usable client, leaving the Antigravity card without quota usage.

Fix

This change uses two layers of discovery and retrieval:

  1. Prefer the installed Antigravity IDE artifacts for OAuth client discovery.
  2. When those artifacts do not provide a usable client, discover agy from the inherited process PATH, then from the real macOS login shell using -l -i -c. No Homebrew path or fixed installation directory is assumed. The resolved CLI candidate is cached per process, and non-executable candidates are skipped.

Fetch order remains local IDE API first, then the OAuth remote route. Only a terminal failure from those routes activates the optional CLI fallback. The fallback invokes agy --print /usage --output-format json --print-timeout 30s, validates the structured usage response, and maps its groups/buckets into the existing quota windows. CLI bucket identities are stable agy.<bucket_id>.v1 values, and the fallback is explicitly macOS-only.

agy is optional: IDE OAuth behavior remains available, and the existing error is preserved when neither route can provide usable data.

Result

  • With the IDE closed, TokenBar can display Antigravity quota through OAuth or the agy fallback.
  • If the IDE is not installed, a discoverable agy CLI can provide the quota.
  • Transient/network/429 failures keep the existing transient handling and do not switch data sources.
  • Chat-shaped CLI responses are rejected; they are never treated as quota or retried as a token-consuming probe.
  • No raw CLI output, credentials, or account identifiers are surfaced.

Validation

  • cargo test -p tb_core_ffi antigravity --lib — 34 passed.
  • cargo test --workspace — passed with no failures (1,783 passed; 4 documented ignored tests).
  • cargo clippy --workspace --all-targets — passed; only existing repository warnings remain.
  • make build — passed.
  • make selftest — passed.
  • rustfmt --check --edition 2021 crates/tb_core_ffi/src/agent_antigravity.rs and git diff --check — passed.
  • With the IDE process closed, swift run TokenBar --smoke reported antigravity=4 windows.
  • With an isolated empty GEMINI_CLI_HOME, the IDE-closed smoke still reported Antigravity windows, exercising the CLI fallback.
  • On the current agy 1.1.19, the slash form agy --print /usage --output-format json returned status=SUCCESS, command.name=usage, two groups, and four buckets; generic response/usage fields are ignored by the quota parser, with a regression fixture covering the response-only shape.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fed1e4c31e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/tb_core_ffi/src/agent_antigravity.rs Outdated

@Nanako0129 Nanako0129 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this — the problem is real and the shape of the fix is right. Two layers of discovery with the CLI strictly as a last resort, only after both existing routes have failed, is the correct ordering, and fetch_agy_cli itself is careful: fixed argument array with no shell interpolation, stdin/stderr nulled, kill_on_drop, an outer timeout wrapping the CLI's own, and status/command.name both validated before the payload is trusted. Error strings are fixed rather than echoing CLI output. I have no security concerns with that invocation.

Two things I would like changed before merging, plus a request and a process note.

0. Withdrawn

This section originally argued that a closed-but-installed IDE should already return quota on main, and asked whether this PR describes the wrong failure. That was wrong and I have removed it. We quit Antigravity and checked against a clean main build: the quota does disappear. Your title and problem statement are accurate. I had reasoned from the fall-through in fetch_with without running it, and a code path existing turned out not to mean the route succeeds. Details in the follow-up comment; nothing below depends on it.

1. /bin/sh -l will not see the PATH this PR is looking for

let output = Command::new("/bin/sh")
    .args(["-lc", "command -v -- agy"])

On macOS /bin/sh is bash in POSIX mode, so -l sources /etc/profile and ~/.profile and never touches ~/.zprofile or ~/.zshrc. The default login shell is zsh, and Homebrew's PATH export lands in ~/.zprofile. For the exact population this PR targets — GUI-launched app, IDE not running, agy reachable only from the login shell — this probe returns nothing and the card still shows the OAuth error.

The repo already solved this for the Claude token harvest, and it is our code rather than something you would have to invent:

  • detect_login_shell() (crates/tb_core_ffi/src/agent_usage.rs:3421) resolves the real shell from $SHELL, falling back to Directory Services because launchd leaves $SHELL unset for a GUI app.
  • harvest_shell_env_token_uncached() (:3385) invokes it as ["-l", "-i", "-c", script] (:3392) — the comment there records that -l alone only gets ~/.zprofile, hence the -i.

detect_login_shell is private to agent_usage today, and it is gated #[cfg(target_os = "macos")] while your probe is #[cfg(unix)]. Neither is yours to solve: call it anyway, and I will land the one-line visibility change alongside this PR. macOS-only is the right scope for the Homebrew-under-zsh case regardless.

The same comparison covers two smaller problems in the probe:

fn agy_cli_artifact_candidates() -> Vec<PathBuf> {
    let shell_path = discover_agy_from_login_shell();
    agy_cli_artifact_candidates_from(std::env::var_os("PATH").as_deref(), shell_path)
}
  • It is evaluated eagerly, as an argument, so the shell runs even when PATH already resolves agy.
  • It is uncached. resolve_oauth_client() memoises its half behind a OnceLock, but the fetch_agy_cli half has no equivalent, so it re-runs on every fetch that reaches the fallback. That is a login-shell spawn per minute while the popover is open (DashboardModel.pollAgentUsage ends on RegistryChange.sleep(upTo: 60, ...), DashboardModel.swift:1725) and every 5 minutes from the tray (TrayAnimator.swift:435) — and for the users this PR targets, reaching the fallback is the steady state, not the exception.

Consulting PATH first and memoising the resolved path for the process collapses both.

One thing I am explicitly not asking you to change: the probe uses the blocking std::process::Command rather than tokio::process, but so does everything else in this file — fetch_local_ide runs ps and lsof (and PowerShell on Windows) the same way. That is our pattern, not something you introduced. It is worth a bound here specifically because a login shell is not ps: it executes the user's rc files, which can take seconds or block outright. So the timeout and kill_on_drop matter even though the blocking spawn itself is house style.

2. The fallback re-identifies every card, and card_id embeds positional indices

The bug is the trigger condition:

Err(primary_failure) => match fetch_agy_cli(now).await {

ProviderFetchFailure distinguishes Transient from Terminal, and this fires on both. So a network blip or a 429 on the primary route is enough to switch sources — and because the CLI path mints a different card_id, every Antigravity card changes identity, then changes back on the next successful poll.

In this codebase card_id is identity. Swift matches the persisted selection as <clientId>|<cardId> exactly (WindowCardLoader.selectionKey, Sources/TokenBar/WindowCardLoader.swift:34, which shares its shape with QuotaResolver's canonical selection), and the quota-history series is keyed on it. When identity moves, the user's pinned gauge silently stops resolving and that window's recorded history restarts from nothing — with no visible change to the label to explain it. agent_usage.rs:4897 documents this exact trap for Claude's scoped weekly windows, which deliberately key on the display name rather than scope.model.id for the same reason.

Restricting the fallback to Terminal is the fix for the trigger, and I would do it regardless. But the key shape decides how much damage remains:

let card_id = format!("agy.{group_index}.{bucket_index}.{id}.v1");

id is already in the string, so the indices add nothing except a second way for identity to move — if agy ever reorders its groups or buckets, every card_id shifts.

More importantly, the file already has a convention for this. Every other route resolves to model.{model_id}.v1 when a model id exists, and falls back to a positional row.*.{index}.v1 only when it does not — the local IDE path (row.cli.config), the OAuth models path (row.models), and the OAuth quota-buckets path (row.quota.bucket). So a positional key is already the codebase's degraded branch, not a namespace of its own.

Which means the right shape depends on a fact I do not have: do the agy bucket ids correspond to model ids? If they do, emitting model.{model_id}.v1 makes the fallback identity-transparent — a source switch changes nothing the user can see, which is the outcome we actually want. If they do not, agy.{id}.v1 without the indices is the honest shape, sitting alongside row.cli.config as another "nothing better available" branch.

A request: a redacted payload

Could you paste the output of agy --print /usage --output-format json with anything identifying stripped? Two reasons: it answers the question above, and it would let us add a fixture taken from the real CLI. Right now parse_agy_usage's contract rests on one live run that nothing in the repo can re-check, and the bucket ids in the tests (gemini-weekly, gemini-5h) are hand-authored — so a wire-format change would pass CI and fail in the field.

Minor

  • fetch_agy_cli does not set .creation_flags(CREATE_NO_WINDOW). The Windows PowerShell discovery in this same file does, and without it Windows flashes a console on every fallback.
  • executable_from_path joins the bare name agy with no PATHEXT handling, so the PATH half never resolves agy.exe on Windows. Either complete it or #[cfg] the fallback to Unix so the limitation is explicit rather than silent.
  • agy_cli_artifact_candidates().into_iter().next() uses only the first candidate, and executable_from_path checks is_file() without checking the executable bit — so a non-executable agy earlier on PATH blocks the shell-discovered one instead of falling through to it.

CI

Fork PRs need workflow approval here, so the run was sitting at action_required and the PR showed no checks. It has been approved and CI is green on fed1e4c. Nothing for you to do — noting it so the gate is visible on the PR rather than only in your local run.

Note

Your validation section is unusually complete — exercising the fallback with GEMINI_CLI_HOME pointed at an unavailable credentials directory is exactly the case that would otherwise ship untested. Thanks for that.

@Nanako0129

Copy link
Copy Markdown
Owner

Correction: withdraw §0 of my review. I claimed a closed-but-installed IDE should already return quota on main, and used that to suggest the PR describes the wrong failure. We have since quit Antigravity and checked on a clean main build: the quota does disappear. Your title and problem statement are accurate and mine was not.

The claim came from reading the fall-through in fetch_with and concluding the OAuth route would carry the closed-IDE case. I did not run it before posting, and the code path existing turned out not to mean the route succeeds. That was mine to verify before putting it in front of you, especially as the leading section.

So: please disregard §0 entirely, including the question about whether your install location is the real cause and the suggestion that merging this would mask a discovery bug. None of that is established.

What remains open is narrower and genuinely unknown: why the OAuth route does not carry the closed-IDE case, since it does not depend on the Antigravity process. Two candidates I have already ruled out — discover_client_from_app reads the .app from disk, and gemini_home() resolves from GEMINI_CLI_HOME or ~/.gemini rather than from the running process. I am still looking, and I will report what I find here rather than asking you to chase it.

That does not change the review's substance. §1 and §2 stand on their own reading of this diff and are unaffected: the /bin/sh -l probe still cannot see a brew-installed agy under zsh, and the fallback still re-identifies every card when it fires on a Transient failure. The request for a redacted agy --print /usage --output-format json payload also stands, and is now more useful rather than less.

@Nanako0129

Copy link
Copy Markdown
Owner

Update after digging into this on a machine that has both Antigravity.app and agy installed, @iF2007. Two findings — one is ours to fix, one is a question I cannot answer without you.

We found a bug on our side, separate from this PR

Testing with the IDE installed but not running, the card showed Antigravity OAuth client was not found — which should not happen, because discover_client_from_app reads the .app from disk and does not need the process. Tracing it: scan_client_ids walks backward over token bytes to find the start of a client id, and in a packed 139 MB language_server binary that walk-back absorbs the tail of whatever string sits in front of the id. The numeric head ends up containing letters, valid_client_id rejects it, and the scan returns zero ids even though both real ids are present in the binary (I confirmed the strings are there).

So the OAuth route was silently dead for anyone with the IDE installed — the discovery could not produce a client at all. That is independent of this PR and I will send it as its own fix. It matters here only because it is a second, unrelated reason the Antigravity card can show an OAuth error, and it muddies the "IDE closed" signal.

The part I need your help on: what does agy return for you?

Your PR body says agy --print /usage --output-format json returned 4 valid buckets on agy 1.1.19. I have the same version:

$ agy --version
1.1.19

But that exact command, for me, does not return a usage report — it routes /usage to the model as a chat prompt and returns a completion:

{
  "status": "SUCCESS",
  "response": "It looks like you're looking for information on how to use Antigravity ... How can I help you with your project today?",
  "num_turns": 1,
  "usage": { "input_tokens": 22504, "output_tokens": 1651, "thinking_tokens": 1137, "total_tokens": 24155 }
}

Two problems with this shape, if it is what ships:

  1. parse_agy_usage rejects it. There is no command field, so the command.name == "usage" check fails and the parser returns an error — the card falls back to the original OAuth failure. status is still SUCCESS, so nothing signals that anything went wrong.
  2. It costs the user tokens to measure their tokens. That single call spent ~24k tokens, and the fallback fires on every poll cycle that reaches it.

The quota feature clearly exists in the binary — remaining_fraction, reset_time, and buckets are all present as strings — so I think the difference is in how the usage view is reached, not whether it exists. --print <text> looks like it sends <text> to the model rather than invoking a built-in command.

So, concretely: what invocation produced the 4 buckets for you? Was it --print /usage, or a different subcommand / a TUI path / something in your config? If you can paste the redacted JSON you actually got (structure only, no ids or tokens), that settles both the format question and lets us add a fixture from a real run — right now parse_agy_usage's contract rests on one live capture, and mine and yours disagree.

Nothing above changes my two earlier requests (the /bin/sh -l PATH issue and the Transient-vs-Terminal re-identification) — those stand on the code regardless of how the payload question resolves. I would just rather nail down whether the CLI path returns quota at all before we polish how it is parsed.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 099be6acb0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/tb_core_ffi/src/agent_antigravity.rs Outdated
Comment thread crates/tb_core_ffi/src/agent_antigravity.rs Outdated
@iF2007

iF2007 commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

Review follow-up

Addressed in 38e77ff:

  • §0 is withdrawn; no code change is needed for it.
  • Shell discovery reuses the existing macOS login-shell resolver, runs -l -i -c with a bounded marker-delimited probe, checks the inherited PATH first, and caches the result per process.
  • CLI fallback is restricted to ProviderFetchFailure::Terminal; transient, network, and rate-limit failures retain the existing last-good/transient behavior.
  • CLI bucket identity is now agy.<bucket_id>.v1, so group/bucket ordering cannot reset a selection or quota-history series.
  • The fixture uses the real response shape (two groups and four buckets) while keeping identifiers and values synthetic; no raw payload is stored.
  • The fallback is explicitly macOS-only, matching TokenBar’s supported platform boundary; Windows console/PATHEXT behavior is intentionally not added.
  • Candidate discovery accepts only regular executable files, skips an invalid earlier PATH candidate, and fetch retries each discovered candidate in order.

CLI response shape

On the current agy 1.1.19, the exact slash-form invocation agy --print /usage --output-format json returned status=SUCCESS, command.name=usage, two groups, and four buckets. The response also contains generic response/usage fields; the quota parser ignores those and requires the structured command data. The non-slash form agy --print usage --output-format json returned a model-response shape with no command data, so it is intentionally rejected rather than treated as quota or repeated as a token-consuming probe. If the slash form returns the response-only shape in another environment, that is not a usable quota result and the existing terminal error is preserved.

Verification

  • cargo test -p tb_core_ffi antigravity --lib: 33 passed.
  • cargo test --workspace: 1,782 passed, 4 documented ignored, 0 failed.
  • cargo clippy --workspace --all-targets: passed with existing repository warnings.
  • make build, make selftest, rustfmt check, and git diff --check: passed.
  • With the IDE process closed, swift run TokenBar --smoke reported antigravity=4 windows.
  • With an isolated empty GEMINI_CLI_HOME, the same smoke still reported Antigravity windows, exercising the CLI fallback path.

@iF2007

iF2007 commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up commit 58315c4 adds a regression fixture for the response-only CLI shape discussed above: a SUCCESS payload containing generic response/usage fields but no command.name=usage is rejected as non-quota data. The final focused count is 34/34; cargo test --workspace remains 1,783 passed, 4 documented ignored, 0 failed.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 58315c4c10

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/tb_core_ffi/src/agent_antigravity.rs

@Nanako0129 Nanako0129 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a thorough pass, @iF2007 — the review is resolved in the code, not just answered:

  • Shell discovery reuses detect_login_shell with -l -i, checks the inherited PATH first, caches per process, and now spawns via tokio::process with a bound — which I hadn't asked for but is the right call for a login shell.
  • The fallback is restricted to Terminal, so a transient or rate-limited primary no longer switches sources.
  • card_id is agy.<bucket_id>.v1 with the positional indices gone.
  • macOS-only, executable-file candidates, skip-and-retry — all as described.

I was wrong about the token cost — withdrawing that

My earlier comment claimed agy --print /usage routes to the model and spends ~24k tokens per poll. That does not hold, and you were right. The command is a local built-in that costs nothing — I re-ran the exact invocation your code uses, in the two directories that actually matter:

# an interactive shell in a project dir, and cwd=/ (where a launchd GUI app runs):
$ agy --print /usage --output-format json
{"status":"SUCCESS","command":{"name":"usage","data":{"groups":[...]}},
 "num_turns":0,"usage":{"total_tokens":0},"duration_seconds":0}

num_turns:0, total_tokens:0 — no model turn. The one run that returned the chat shape with a 24k-token turn was the first agy invocation of my session (20s, num_turns:1, a real conversation_id). Re-running the byte-for-byte identical command — same --print-timeout 30s, same /tmp cwd — returns the command shape for free every time since. So the trigger is first-ever invocation, not cwd and not the timeout flag; that first call appears to do real init (download / session warm) during which /usage is sent to the model before the command is registered. The per-poll cost I described isn't real. Sorry for the noise on that.

Worth keeping only as a data point, not a request: on a machine where agy has never run, TokenBar's first poll could hit that one-time init and spend a turn. Your parser already does the safe thing — the chat shape has no command.name=usage, so it's rejected and the existing terminal error is preserved, no bad data — and it's a single occurrence, not per-poll. I wouldn't add anything for it.

Notes

  • detect_login_shell visibility: you made it pub(crate) and call it through crate::agent_usage::detect_login_shell() — the exact one-line change I had staged to land alongside this. Yours supersedes it; I've dropped mine.
  • The scan bug is fixed on main (#242, merged). That's the installed-but-closed case returning OAuth client was not found; it's independent of this PR, but it means the OAuth route now resolves a client for installed users, so this fallback is cleanly the not-installed / not-logged-in path.

From my side there's nothing blocking left — the two earlier requests (/bin/sh PATH and the Terminal restriction) are both resolved. The new commits just need a maintainer to re-approve the workflow so CI runs on them; that's on us.

…-quota

# Conflicts:
#	crates/tb_core_ffi/src/agent_antigravity.rs
@Nanako0129

Copy link
Copy Markdown
Owner

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c9c9a7723e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

executable: &Path,
now: DateTime<Utc>,
) -> Result<Fetched, ProviderFetchFailure> {
let future = tokio::process::Command::new(executable)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve the login-shell environment when launching agy

When agy is found only through the login-shell probe and depends on variables defined there—such as a custom GEMINI_CLI_HOME—this direct spawn inherits TokenBar's GUI environment instead of the shell environment. The fresh follow-up code extracts only the executable path in discover_agy_from_login_shell, so the fallback can find agy but then fail to find the same credentials it uses interactively; invoke it with a bounded captured shell environment or propagate the required variables.

Useful? React with 👍 / 👎.

Comment on lines +738 to +740
let card_id = format!("agy.{id}.v1");
if let Some(window) =
quota_window(label, fraction, reset, now, card_id.clone(), Some(card_id))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Document the new agy quota identity in the canonical KB

This introduces a new provider route with source = "agy" and agy.<bucket_id>.v1 card/window identities, but no canonical knowledge file is updated; docs/knowledge/plans/provider-quota-pace.md still describes Antigravity identities only in terms of model IDs. That leaves the authoritative identity mapping and fallback precedence stale for future selection/history work, so document this bucket mapping in docs/knowledge/.

AGENTS.md reference: AGENTS.md:L22-L24

Useful? React with 👍 / 👎.

@iF2007

iF2007 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

Sync: merged #242's OAuth client scan fix into this branch.

This branch now includes the merged #242 change (fix/antigravity-oauth-client-scan), pulled from main as part of an upstream sync. The new head is 1be4aea (merge of upstream/main).

  • No production-code overlap. fix(antigravity): stop the OAuth client scan from eating a neighbouring string #242's change is confined to scan_client_ids (re-anchor the id on its last hyphen so the greedy walk-back can't absorb a neighbouring string's tail). The CLI-fallback work in this PR never modified scan_client_ids and is orthogonal to it, so the merge was clean in production code — the only conflict was in the tests module, where both sides added independent regression cases, and both are kept.
  • Expected effect: with the installed-but-closed IDE case now resolving a client via the fixed scan, this fallback cleanly covers the remaining not-installed / not-logged-in path, exactly as discussed.

Since the head moved past the previously approved c9c9a77, this needs a CI run / workflow re-approval on the new head. Nothing else changed.

@Nanako0129

Copy link
Copy Markdown
Owner

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: 1be4aea73d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Nanako0129
Nanako0129 merged commit b7645ba into Nanako0129:main Aug 25, 2026
1 check passed
@Nanako0129

Copy link
Copy Markdown
Owner

Merged — thanks @iF2007. Thorough work, and you turned the review around fast: the login-shell reuse, the Terminal-only fallback, and resolving the conflict with #242 yourself all landed cleanly. Appreciated.

Nanako0129 added a commit that referenced this pull request Aug 25, 2026
Replace the stale v1.14.1 override notes with v1.14.2's, covering the
Antigravity "quota when the IDE is closed" work.

`scripts/release_notes.sh` ships `release-notes.override.txt` verbatim to the
Sparkle dialog / appcast / latest.json and `release-notes.override.md` verbatim
as the GitHub Release body, so these files are the source of truth for this
release's notes; DeepSeek generation is skipped when they are present. The
deterministic "Thanks: @…" line (txt) and GitHub's "New Contributors" / "Full
Changelog" tail (md) are still appended automatically from PR authorship, which
credits @iF2007 for #236; the md also carries an explicit per-change credit.

Change set since v1.14.1:
- #236 (@iF2007): fetch Antigravity quota when the IDE is closed or not
  installed — OAuth remote plus an `agy` CLI fallback.
- #242: fix the OAuth client scan absorbing a neighbouring value in the
  installed language_server binary, which returned zero client ids and
  disabled the OAuth route for an installed-but-closed IDE.

No literal <, &, or > in either file, so the appcast CDATA/HTML escaping path
is not exercised.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants