Skip to content

feat: add HTTP/HTTPS proxy support for all API traffic#301

Open
aaronsewall wants to merge 9 commits intoNoeFabris:devfrom
aaronsewall:proxy
Open

feat: add HTTP/HTTPS proxy support for all API traffic#301
aaronsewall wants to merge 9 commits intoNoeFabris:devfrom
aaronsewall:proxy

Conversation

@aaronsewall
Copy link
Contributor

@aaronsewall aaronsewall commented Jan 28, 2026

  • Add fetchWithProxy() utility using https-proxy-agent
  • Thread proxyUrl through all fetch call sites (token refresh, project context, quota, search)
  • Save proxy URL from ANTIGRAVITY_LOGIN_PROXY env during login
  • Store proxyUrl per-account in antigravity-accounts.json
  • Add docs/PROXY.md with configuration guide
  • Update README with proxy quick start section

Supports: http://host:port, http://user:pass@host:port, https://host:port
Note: SOCKS5 proxies are NOT supported

- Add fetchWithProxy() utility using https-proxy-agent
- Thread proxyUrl through all fetch call sites (token refresh, project context, quota, search)
- Save proxy URL from ANTIGRAVITY_LOGIN_PROXY env during login
- Store proxyUrl per-account in antigravity-accounts.json
- Add docs/PROXY.md with configuration guide
- Update README with proxy quick start section

Supports: http://host:port, http://user:pass@host:port, https://host:port
Note: SOCKS5 proxies are NOT supported
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 28, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector
Copy link

To use Codex here, create an environment for this repo.

@aaronsewall
Copy link
Contributor Author

@codex

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 28, 2026

Greptile Overview

Greptile Summary

This PR adds comprehensive HTTP/HTTPS proxy support for all API traffic in the Antigravity authentication plugin. The implementation threads proxy URLs through OAuth login, token refresh, project discovery, quota checks, search tools, and all API requests.

Key changes:

  • Added fetchWithProxy() utility using undici's ProxyAgent with connection pooling and LRU eviction
  • Proxy URL captured from ANTIGRAVITY_LOGIN_PROXY env var during login and persisted per-account
  • All network calls (fetch) replaced with fetchWithProxy() that accepts optional proxyUrl parameter
  • Proxy agents cached in a Map with MAX_AGENT_CACHE_SIZE=50 limit and disposal support
  • Comprehensive documentation in docs/PROXY.md and README quick start

Architecture:
The proxy flows through the entire request lifecycle: login → token storage → token refresh → project context → API calls. Each account can have its own proxy, enabling per-account IP isolation. The implementation correctly fails hard (no fallback to direct connection) when a proxy is configured but fails.

Issues found:

  • Proxy clearing not supported: Once a proxy is set on an account, logging in without ANTIGRAVITY_LOGIN_PROXY won't clear it due to undefined fallback logic on line 423 of src/plugin.ts. Users cannot remove proxies without manually editing JSON.
  • Previous review comments about documentation inconsistencies were already noted.

Confidence Score: 4/5

  • Safe to merge with one logical issue that prevents proxy removal
  • Core proxy implementation is solid with proper caching, disposal, and comprehensive test coverage. All API traffic correctly routes through proxy. The proxy clearing issue is a usability limitation rather than a critical bug, but should be addressed for completeness.
  • Pay attention to src/plugin.ts:423 - proxy fallback logic prevents clearing proxies once set

Important Files Changed

Filename Overview
src/plugin/proxy.ts Implements proxy agent caching with LRU eviction and proper disposal. Review feedback addressed.
src/plugin.ts Threads proxy through all API calls. Proxy fallback prevents clearing once set.
src/plugin/token.ts Proxy parameter added to refreshAccessToken, properly threaded through token refresh flow.
src/plugin/search.ts Google search requests now use proxy via fetchWithProxy wrapper.
src/antigravity/oauth.ts OAuth token exchange and userinfo requests now use ANTIGRAVITY_LOGIN_PROXY env var.
README.md Proxy quick start documentation added. References non-existent EXAMPLE_PROXY_CONFIG.md (already noted).
docs/PROXY.md Comprehensive proxy configuration guide. Model name inconsistency noted in previous review.

Sequence Diagram

sequenceDiagram
    participant User
    participant CLI as OpenCode CLI
    participant Plugin as Antigravity Plugin
    participant ProxyModule as proxy.ts
    participant ProxyAgent as undici ProxyAgent
    participant Proxy as HTTP Proxy
    participant GoogleAPI as Google APIs

    Note over User,GoogleAPI: OAuth Login Flow with Proxy
    User->>CLI: ANTIGRAVITY_LOGIN_PROXY=http://proxy:8080<br/>opencode auth login
    CLI->>Plugin: Login command
    Plugin->>ProxyModule: fetchWithProxy(token endpoint, ..., proxyUrl)
    ProxyModule->>ProxyModule: getProxyAgent(proxyUrl)
    ProxyModule->>ProxyAgent: new ProxyAgent({uri: proxyUrl})
    ProxyAgent-->>ProxyModule: agent
    ProxyModule->>ProxyModule: Cache agent in agentCache Map
    ProxyModule->>ProxyAgent: undiciFetch(url, {dispatcher: agent})
    ProxyAgent->>Proxy: CONNECT to oauth2.googleapis.com
    Proxy->>GoogleAPI: Forward token exchange request
    GoogleAPI-->>Proxy: Access token + refresh token
    Proxy-->>ProxyAgent: Response
    ProxyAgent-->>Plugin: OAuth tokens
    Plugin->>Plugin: Save proxyUrl to antigravity-accounts.json

    Note over User,GoogleAPI: API Request Flow with Cached Proxy
    User->>CLI: opencode run "Hello" --model=google/claude-sonnet-4-5
    CLI->>Plugin: Request
    Plugin->>Plugin: Load account (with proxyUrl)
    Plugin->>ProxyModule: fetchWithProxy(API endpoint, ..., account.proxyUrl)
    ProxyModule->>ProxyModule: getProxyAgent(account.proxyUrl)
    ProxyModule->>ProxyModule: Return cached agent from agentCache
    ProxyModule->>ProxyAgent: undiciFetch(url, {dispatcher: agent})
    ProxyAgent->>Proxy: Reuse connection to proxy
    Proxy->>GoogleAPI: Forward API request
    GoogleAPI-->>Proxy: Streaming response
    Proxy-->>ProxyAgent: Stream
    ProxyAgent-->>Plugin: Response stream
    Plugin-->>User: Stream output

    Note over User,GoogleAPI: All Traffic Routes Through Proxy
    Plugin->>ProxyModule: Token refresh (account.proxyUrl)
    Plugin->>ProxyModule: Project discovery (account.proxyUrl)
    Plugin->>ProxyModule: Quota checks (account.proxyUrl)
    Plugin->>ProxyModule: Search tool (account.proxyUrl)
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

5 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 28, 2026

Additional Comments (1)

src/plugin/accounts.ts
proxyUrl is missing from the account mapping in saveToDisk(). The proxy configuration will not persist across application restarts, even though it's saved during login in plugin.ts:345. Add proxyUrl: a.proxyUrl to the mapped account object.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugin/accounts.ts
Line: 762:775

Comment:
`proxyUrl` is missing from the account mapping in `saveToDisk()`. The proxy configuration will not persist across application restarts, even though it's saved during login in `plugin.ts:345`. Add `proxyUrl: a.proxyUrl` to the mapped account object.

How can I resolve this? If you propose a fix, please make it concise.

Copy link

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

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: 8f2fa57280

ℹ️ 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".

proxyUrl was missing from saveToDisk() mapping and constructor hydration,
causing proxy config to be lost on restart and all API calls to bypass proxy.
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

4 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

aaronsewall and others added 4 commits January 28, 2026 13:54
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Signed-off-by: Aaron Sewall <[email protected]>
Request objects were accepted but properties (method, headers, body) were
silently lost. All call sites pass strings, so narrowing the type prevents
future misuse. Removed test for Request input since it's no longer valid.
Resolve conflicts to keep both proxy support and new quota caching features.
Added proxyUrl parameter to fetchGeminiCliQuota for parallel quota fetching.
Signed-off-by: Aaron Sewall <[email protected]>
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

6 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@aaronsewall aaronsewall reopened this Jan 30, 2026
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Signed-off-by: Aaron Sewall <[email protected]>
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

7 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 30, 2026

Additional Comments (1)

src/plugin/quota.ts
proxy not used for token refresh and project context during quota checks

Both refreshAccessToken() and ensureProjectContext() are missing the account.proxyUrl parameter. This means quota checks will bypass the configured proxy for authentication and project discovery, even though the actual quota API calls (lines 345-347) correctly use the proxy.

Add account.proxyUrl as the 4th parameter to refreshAccessToken() on line 329, and as the 2nd parameter to ensureProjectContext() on line 336.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugin/quota.ts
Line: 329:336

Comment:
proxy not used for token refresh and project context during quota checks

Both `refreshAccessToken()` and `ensureProjectContext()` are missing the `account.proxyUrl` parameter. This means quota checks will bypass the configured proxy for authentication and project discovery, even though the actual quota API calls (lines 345-347) correctly use the proxy.

Add `account.proxyUrl` as the 4th parameter to `refreshAccessToken()` on line 329, and as the 2nd parameter to `ensureProjectContext()` on line 336.

How can I resolve this? If you propose a fix, please make it concise.

Signed-off-by: Aaron Sewall <[email protected]>
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

5 files reviewed, 4 comments

Edit Code Review Agent Settings | Greptile

- Add MAX_AGENT_CACHE_SIZE (50) with LRU eviction to prevent unbounded growth
- Add disposeProxyAgent() for explicit cleanup when accounts are removed
- Fix proxyUrl clearing logic: use explicit undefined check instead of ??
  (allows removing proxy by setting empty string, not treated as falsy)
- Pass account.proxyUrl to refreshAccessToken() and ensureProjectContext()
  in quota checks to ensure proxy is used for all auth operations
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

7 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

refreshToken: parts.refreshToken,
projectId: parts.projectId ?? existing.projectId,
managedProjectId: parts.managedProjectId ?? existing.managedProjectId,
proxyUrl: proxyUrl !== undefined ? proxyUrl : existing.proxyUrl,
Copy link
Contributor

Choose a reason for hiding this comment

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

proxy cannot be cleared once set - undefined falls back to existing proxy

if user logs in without ANTIGRAVITY_LOGIN_PROXY after previously setting a proxy, the old proxy persists. empty string ("") would also be falsy and fall back.

to enable proxy clearing, distinguish between "not provided" vs "explicitly cleared":

Suggested change
proxyUrl: proxyUrl !== undefined ? proxyUrl : existing.proxyUrl,
proxyUrl: proxyUrl !== undefined ? proxyUrl : existing.proxyUrl,

could become:

// Use null to explicitly clear proxy
proxyUrl: proxyUrl !== undefined ? (proxyUrl || null) : existing.proxyUrl,

then users could clear with ANTIGRAVITY_LOGIN_PROXY="" opencode auth login

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugin.ts
Line: 423:423

Comment:
proxy cannot be cleared once set - `undefined` falls back to existing proxy

if user logs in without `ANTIGRAVITY_LOGIN_PROXY` after previously setting a proxy, the old proxy persists. empty string (`""`) would also be falsy and fall back.

to enable proxy clearing, distinguish between "not provided" vs "explicitly cleared":

```suggestion
      proxyUrl: proxyUrl !== undefined ? proxyUrl : existing.proxyUrl,
```

could become:

```
// Use null to explicitly clear proxy
proxyUrl: proxyUrl !== undefined ? (proxyUrl || null) : existing.proxyUrl,
```

then users could clear with `ANTIGRAVITY_LOGIN_PROXY="" opencode auth login`

How can I resolve this? If you propose a fix, please make it concise.

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