Skip to content

feat: readable Google errors, 401 retry-once, locked token cache, label quoting#3

Merged
mabry1985 merged 1 commit into
mainfrom
feat/error-quality
Jul 3, 2026
Merged

feat: readable Google errors, 401 retry-once, locked token cache, label quoting#3
mabry1985 merged 1 commit into
mainfrom
feat/error-quality

Conversation

@mabry1985

Copy link
Copy Markdown
Contributor

Agent-facing error quality + auth robustness.

What

  • Google's message, not a status code: request() / get_access_token() raise GoogleError with the JSON error body's error.message / error_description — the agent sees "403: Request had insufficient authentication scopes." instead of a bare HTTPStatusError. invalid_grant on refresh adds a reconnect hint pointing at the Google panel.
  • 401 retry-once: a data-call 401 (token revoked / expired early) invalidates the cached access token and retries once with a fresh one — then gives up loudly. Cached-token revocation previously failed every call until natural expiry.
  • Thread-safe token cache: tools run on worker threads; the cache is now lock-guarded (network refresh stays outside the lock — a rare duplicate refresh is harmless).
  • Label quoting: gmail_list_unread("Priority Inbox") used to become label:Priority + Inbox free-text; now label:"Priority Inbox".

Test

38 passed (5 new: scope-error surfacing, invalid_grant readability, 401-retry-success, 401-give-up, label quoting), ruff clean, host-free.

🤖 Generated with Claude Code

…el quoting

- auth.request/get_access_token now raise GoogleError carrying Google's own JSON
  error message ('insufficient authentication scopes' beats a bare 403); the token
  endpoint's invalid_grant hints at reconnecting from the Google panel
- a 401 on a data call invalidates the cached access token and retries once with a
  fresh one (revoked/early-expired token), then gives up loudly
- token cache is lock-guarded (tools run on worker threads); network refresh stays
  outside the lock
- gmail_list_unread quotes the label so multi-word labels don't split into
  label:Priority + free-text Inbox

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@protoquinn

protoquinn Bot commented Jul 3, 2026

Copy link
Copy Markdown

👀 Quinn is reviewing — verdict (PASS / WARN / FAIL) + findings to follow.

@mabry1985 mabry1985 merged commit 33f2d20 into main Jul 3, 2026
1 check passed
@mabry1985 mabry1985 deleted the feat/error-quality branch July 3, 2026 08:44

@protoquinn protoquinn 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.

QA Audit — PR #3 | feat: readable Google errors, 401 retry-once, locked token cache, label quoting

VERDICT: WARN (CI pending — re-evaluate on terminal green)


CI Status

  • test: in_progress ⏳

Diff Review

  • auth.py: Thread-safe token cache via _CACHE_LOCK; network refresh outside lock (correct). 401 on data call invalidates cache and retries once with fresh token.
  • auth.py: _error_detail() extracts Google's message from both API (error.message) and OAuth (error_description) JSON formats with sensible fallbacks; length-capped at 300 chars.
  • auth.py: request() replaces raise_for_status() with explicit GoogleError carrying Google's message + status code. Retry loop (for attempt in (1,2)) is tight and correct.
  • __init__.py: Label quoting strips embedded quotes then wraps in double-quotes, fixing multi-word Gmail label queries (e.g., "Priority Inbox").
  • Tests: 5 new tests cover error surfacing, invalid_grant readability, 401 retry, 401 give-up, and label quoting. No regressions.

Observations

  • LOW: clawpatch structural review unavailable (repo not in project registry); manual review completed — no structural concerns.
  • LOW: diff truncated at 231 lines; full 401-retry test bodies not visible but passing per in-progress CI.

— Quinn, QA Engineer

@protoquinn

protoquinn Bot commented Jul 3, 2026

Copy link
Copy Markdown

Submitted COMMENT review on protoLabsAI/google-plugin#3.

@mabry1985 mabry1985 mentioned this pull request Jul 3, 2026
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.

1 participant