Skip to content

fix(cli): stale squad roster + Antigravity auth failures get the re-auth bubble - #1023

Merged
edgar-durand merged 3 commits into
mainfrom
fix/squad-roster-and-agy-reauth
Nov 6, 2026
Merged

edgar-durand merged 3 commits into
mainfrom
fix/squad-roster-and-agy-reauth

Conversation

@edgar-durand

@edgar-durand edgar-durand commented Nov 6, 2026 •

Copy link
Copy Markdown
Collaborator

Two bugs found in the live Antigravity e2e (dev CodeAgent Box, 2026-11-06):

  1. Stale squad roster (codeagent-p1ch). The roster is fetched once at session start. A user who links an agent mid-session and @-routes to it got Unknown agent 'antigravity' — not in your squad. and the turn was answered by the current agent (Claude). routeSquadTask now re-fetches the roster once on a miss (on demand, no timers) and only refuses if it is still absent.
  2. Antigravity auth failures (codeagent-6bg9). Captured live: with an invalid key agy streams only ⚠ Agent execution terminated due to error. and ends with end_turn; nothing on stderr. The cause is only in agy's own log (~/.gemini/antigravity-cli/log/acp-server-*.log: Error 400 … API key not valid … reason:API_KEY_INVALID). The completed-reply classifier for antigravity now reads the tail of that log (entries since the turn started) → re-auth bubble + reportCredentialInvalid for credential errors, the generic honest failure frame otherwise. Tokens are redacted in any logged line.

Tests: new start-task-routing cases + antigravity-reply-failure (behaviour) + antigravity/reply-failure (unit), each failing before the fix.

🤖 Generated with Claude Code


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.

edgar-ph and others added 3 commits November 6, 2026 15:12
The squad roster is fetched once at session start (and after a switch or
route), so an agent the user links AFTER the session started is missing from
the cached copy. Live on the dev CodeAgent Box (2026-11-06): the user linked
Antigravity mid-session, sent a start_task routed to `antigravity`, and the
CLI logged "start_task routing to antigravity failed: Unknown agent
'antigravity' — not in your squad." — the turn was then answered by Claude.

routeSquadTask now re-fetches the roster ONCE, on demand, when the target is
absent from the cached roster, and only refuses if it is still absent. No
timers or polling. SquadState owns the fetch (refreshRoster), so the runner's
existing refresh points reuse the same path.

Bead: codeagent-p1ch

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d reply

agy (`agy acp`) does not report a provider/auth failure as a JSON-RPC error.
It streams "⚠ Agent execution terminated due to error." plus the provider's
message as a normal agent_message_chunk and then ends the turn with a clean
end_turn. None of the throw/exit failure paths (failureBubble,
reportCredentialInvalid) see that, so with an invalid API key (observed when
agy was added: the turn fails with text including "API key not valid") the
raw agy text was rendered as the agent's reply, the user got no re-auth
bubble, and Profile › Agents kept showing the credential as CONNECTED.

An antigravity classifyCompletedReply hook now classifies such a reply:
- banner + a Google credential failure (API key not valid / API_KEY_INVALID /
  expired key, UNAUTHENTICATED / invalid authentication credentials,
  invalid_grant / token expired or revoked) -> the standard re-auth bubble +
  reportCredentialInvalid, the same path as Claude's "Not logged in" reply;
- banner without an auth cause -> the honest generic TURN_FAILURE_MESSAGE,
  credential untouched.
It requires agy's own banner and a reply of at most 1000 characters, so a
substantive reply that merely discusses an API-key error is never
misclassified. The Agent Pack path (completedReplyFailureBubble) honours the
same classification.

Bead: codeagent-6bg9

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first classifier (da221b5) looked for the credential cause in the
reply text. A live capture on a CodeAgent Box (agy 1.5.2, `agy acp`,
GEMINI_API_KEY = an invalid key, 2026-11-06) shows agy never streams it:
the ONLY text is the agent_message_chunk "⚠ Agent execution terminated due
to error.", session/prompt resolves {"stopReason":"end_turn"}, and stderr
is empty. The cause is only in agy's log,
~/.gemini/antigravity-cli/log/acp-server-<ts>-<pid>.log:

  E1106 18:16:15.662983 233 errorreport.go:247] agent executor error:
  generating and executing: Error 400, Message: API key not valid. ...
  Status: INVALID_ARGUMENT, Details: [... reason:API_KEY_INVALID ...]

So an invalid key still got the generic frame and the credential was
never flagged. On a banner reply the classifier now (after the cheap
reply-text check) reads the last 16 KB of the newest acp-server log under
the agy process's HOME (the current agent env), keeps only E/F entries
stamped since the turn started, and returns auth_failed when one names a
credential failure (API_KEY_INVALID / API key not valid / expired key,
UNAUTHENTICATED / 401, invalid_grant / token expired or revoked,
PERMISSION_DENIED with a key/token reason). Otherwise, or with no log,
the generic honest frame. The matched entry is logged with Google API
keys and OAuth tokens redacted.

An expired-and-unrefreshable OAuth token or a missing credential fails
earlier, at session/new (-32000 "Authentication required"), on the
existing startup path; this covers a credential that goes bad
mid-session.

Bead: codeagent-6bg9

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@edgar-durand
edgar-durand merged commit 4fb820a into main Nov 6, 2026
13 checks passed
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