Skip to content

fix(executors): let the ambient proxy stand when an OpenCode account has none - #12380

Merged
diegosouzapw merged 2 commits into
cheaper-inference:release/v3.8.51from
pacocartones:fix/opencode-ambient-proxy-context
Sep 2, 2026
Merged

diegosouzapw merged 2 commits into
cheaper-inference:release/v3.8.51from
pacocartones:fix/opencode-ambient-proxy-context

Conversation

@pacocartones

@pacocartones pacocartones commented Sep 1, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • A proxy assigned to an opencode / opencode-go connection in Proxy Management is pinned by the chat handler as the ambient proxy context before the executor runs. OpencodeExecutor only reads per-account proxies from providerSpecificData.accountProxies; an API-key connection has none, so it keeps its single default account and takes the single-account fast path, which wrapped the upstream dispatch in runWithDirectFetchContext(). That direct sentinel makes patchedFetch bypass the ambient context and hit native fetch, so the assigned proxy was discarded and the request egressed from the host IP (403 This model is not available in your country on geoblocked hosts).
  • The fast path now applies the direct pin only when no ambient proxy context exists (new hasAmbientProxyContext() in open-sse/utils/proxyFetch.ts); when the handler already pinned a proxy, the dispatch runs inside it. The rotation loop's nested runWithProxyContext(account.proxy, ...) already inherits the ambient context for a null account proxy and is unchanged; the new test pins both paths.

Related Issues

Validation

  • Change type: provider
  • Focused tests and category gates from the golden path: tests/unit/11894-opencode-ambient-proxy-context.test.ts (RED on the base, GREEN with the fix; mutation-checked) plus 13 neighbouring executor/proxy files (151/151); npm run typecheck:core 0; npm run check:open-sse-typecheck OK; npm run check:changelog-integrity OK
  • npm run lint — repository-wide eslint exit 0 (run with --pass-on-unpruned-suppressions; the literal command reports only pre-existing unused global suppressions on this base)
  • Reconciled with the current active release base release/v3.8.51@158647618; focused checks rerun afterward
  • Production-code changes include a new or updated automated test in this PR
  • SonarQube is temporarily opt-in while the private project has no quota; it is not a PR gate.

Tests Added Or Updated

  • tests/unit/11894-opencode-ambient-proxy-context.test.ts (new): single-account fast path and multi-account rotation path under an ambient proxy, asserting the upstream fetch resolves source: "context" on the ambient proxy port.

Coverage Notes

  • open-sse/executors/opencode.ts fast path and open-sse/utils/proxyFetch.ts hasAmbientProxyContext() are covered by the new test; no coverage moved down.

Reviewer Notes

  • The issue thread points at opencode.ts:590; that call already inherits the ambient context (runWithProxyContext falls back to the current store when proxyConfig is null). The clobber is the runWithDirectFetchContext wrapper on the single-account fast path. The direct pin is kept for connections with no assignment so env-proxy, TLS-fingerprint and direct-timeout behaviour there is unchanged.
  • No behaviour change for connections that configure per-account proxies (accountProxies); they never enter the fast path.

Co-authored-by: @LeonMAG

…has none

A proxy assigned to an `opencode` / `opencode-go` connection in Proxy
Management is resolved by the chat handler and pinned as the ambient
proxy context (`runWithProxyContext(proxyInfo.proxy, ...)`) before the
executor runs. `OpencodeExecutor.execute()` only reads per-account
proxies from `providerSpecificData.accountProxies`; an API-key
connection has none, so it keeps its single default account
(`proxy: null`) and takes the single-account fast path. That path
wrapped the upstream dispatch in `runWithDirectFetchContext()`, whose
direct sentinel makes `patchedFetch` bypass the ambient context and hit
native `fetch` — the assigned proxy was discarded and the request
egressed from the host IP (surfacing as `403 This model is not
available in your country` on geoblocked hosts).

Keep the direct pin only when no ambient proxy context exists
(`hasAmbientProxyContext()`); when the handler already pinned a proxy,
dispatch inside it so the connection-level assignment is honoured. The
rotation loop's nested `runWithProxyContext(account.proxy, ...)` already
inherits the ambient context for a `null` account proxy and is left
unchanged; the new test pins both paths.

Closes cheaper-inference#11894

Co-authored-by: Leon Marcos <leonaniagomez@gmail.com>
@diegosouzapw
diegosouzapw merged commit 70f33e3 into cheaper-inference:release/v3.8.51 Sep 2, 2026
15 of 16 checks passed
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…has none (cheaper-inference#12380)

A proxy assigned to an opencode / opencode-go connection is pinned by the chat handler as the ambient proxy context before the executor runs. OpencodeExecutor only reads per-account proxies from providerSpecificData.accountProxies, so an API-key connection with none took the single-account fast path — which wrapped the dispatch in runWithDirectFetchContext(), and that direct sentinel makes patchedFetch bypass the ambient context and hit native fetch. The assigned proxy was discarded and the request egressed from the host IP, giving `403 This model is not available in your country` on geoblocked hosts. The fast path now applies the direct pin only when no ambient context exists.

Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green.

Thanks @pacocartones.
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.

fix(providers): OpencodeExecutor bypasses global proxy assignments and forces direct connection (proxy: null)

2 participants