Skip to content

feat: align outbound HTTP headers with canonical OpenCode desktop#940

Merged
Astro-Han merged 4 commits into
devfrom
claude/http-identity-alignment
May 27, 2026
Merged

feat: align outbound HTTP headers with canonical OpenCode desktop#940
Astro-Han merged 4 commits into
devfrom
claude/http-identity-alignment

Conversation

@Astro-Han

@Astro-Han Astro-Han commented May 27, 2026

Copy link
Copy Markdown
Owner

Summary

Aligns all outbound HTTP headers with canonical OpenCode desktop client format, solving the Zen free-tier rate-limiting issue. Introduces a central httpIdentity() helper and UPSTREAM_VERSION file as single source of truth for HTTP identity.

Why

Upstream commit 0b8050d453 added checkHeaders + dailyRequestsFallback in the Zen rate limiter. Clients whose headers don't match canonical patterns get routed to a tiny fallback pool. PawWork's Electron default User-Agent (PawWork/2026.5.27) and Installation.USER_AGENT (opencode/prod/0.0.0-prod-*/desktop) both failed this check, causing free-tier users to hit rate limits after ~3 messages.

PawWork is a fork of OpenCode Desktop — the runtime layer IS OpenCode. Aligning outbound headers is correcting an identity mismatch, not spoofing. The Pi Agent + Kimi Code ban incident (May 2026) further validated that third-party clients using distinct identifiers are vulnerable to arbitrary blocking.

Upstream issues anomalyco/opencode#28807 and #28808 had zero response for 5+ days despite maintainer activity. This PR eliminates the dependency on upstream action.

Related Issue

No open issue. #737 (closed) covered the same problem but concluded "wait for upstream"; this PR supersedes that approach with a proactive fix.

Human Review Status

Pending

Review Focus

  1. The httpIdentity() helper covers all outbound paths (Zen LLM, Models API, 3 provider UAs, Account API, Electron fallback)
  2. OPENCODE_HTTP_VERSION / OPENCODE_HTTP_CHANNEL are isolated from global OPENCODE_VERSION / OPENCODE_CHANNEL to avoid side effects on storage paths, diagnostics, and update channels
  3. Electron UA fallback regex handles dev/beta variants (PawWork Dev/, PawWork Beta/)

Risk Notes

  • Upstream could change checkHeaders criteria; build-time pinned version mitigates frequent version churn but may need periodic bumps
  • Non-OpenCode provider UAs (gitlab, cloudflare) also updated to use HTTP_VERSION — intentional full alignment to avoid partial identity fingerprinting
  • UPSTREAM_VERSION file (1.15.10) must be manually updated when syncing upstream

How To Verify

typecheck: 0 errors (CI green)
unit-opencode: 374 provider tests + 19 LLM tests passed
unit-desktop: passed
core installation-version tests: 2 passed
Live test: bun run dev:desktop → free model no longer rate limited after 3+ messages
Network tab: outbound User-Agent shows opencode/latest/1.15.10/desktop

Screenshots or Recordings

N/A — no visible UI changes.

Checklist

  • Type labelenhancement
  • Routing labelsplatform, harness
  • Priority labelP2
  • Human Review Status above is set to Pending, Approved by @<reviewer>, or Not required: <reason>.
  • I linked the related issue, or stated in Summary why there is no issue.
  • I described the review focus and any meaningful risks.
  • I replaced the example block in How To Verify with the real verification steps and the key result for each.
  • I did not introduce unrelated refactors, dependencies, generated files, or file changes beyond the stated scope.
  • (conditional) I manually checked visible UI or copy changes when needed, with screenshots or recordings. No visible UI changed.
  • (conditional) I considered macOS and Windows impact for platform, packaging, updater, signing, paths, shell, or permissions changes. Electron app.userAgentFallback is cross-platform; regex tested against dev/beta/prod app names.
  • (conditional) I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, generated content, or local file changes when relevant. UPSTREAM_VERSION file noted in Risk Notes.
  • I reviewed the final diff for unrelated changes and suspicious dependency changes.
  • I am targeting dev, and my PR title and commit messages use Conventional Commits in English.

Astro-Han added 3 commits May 27, 2026 10:45
Central httpIdentity() function returns canonical OpenCode desktop
headers (User-Agent, x-opencode-client) for all outbound requests to
OpenCode backends. Version is pinned from UPSTREAM_VERSION file at
build time via a new OPENCODE_HTTP_VERSION define, keeping the global
OPENCODE_CHANNEL and OPENCODE_VERSION unchanged for storage, diagnostics,
and update channels.
- Zen LLM opencode branch: add explicit User-Agent from HTTP_USER_AGENT
- Zen LLM non-opencode branch: use HTTP_VERSION instead of VERSION
- Models API fetch: switch to HTTP_USER_AGENT
- gitlab, cloudflare-workers-ai, cloudflare-ai-gateway: use HTTP_VERSION
- Account API: wrap Effect HTTP client with canonical User-Agent via
  HttpClient.mapRequest, covering device auth, token refresh, orgs,
  user, and config endpoints.
- Electron: replace PawWork/ with opencode/ in userAgentFallback to
  prevent identity leakage from renderer/webview requests.
@Astro-Han Astro-Han added enhancement New feature or request task Narrow execution, audit, spike, migration, tracking, or upstream follow-up work labels May 27, 2026
@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR introduces a complete HTTP versioning system that reads an upstream version file, exposes it through build-time injection, and propagates it as User-Agent headers across runtime components. The version flows from UPSTREAM_VERSION → Script.httpVersion → OPENCODE_HTTP_VERSION injection → Installation exports → User-Agent headers in HTTP requests.

Changes

HTTP Versioning Pipeline

Layer / File(s) Summary
Version source and Script export
UPSTREAM_VERSION, packages/script/src/index.ts
UPSTREAM_VERSION file records version 1.15.10; Script module reads and exposes it as httpVersion getter, falling back to VERSION on read failure.
Installation version types and constants
packages/core/src/installation/version.ts
Declares global OPENCODE_HTTP_VERSION constant and exports InstallationHTTPVersion that resolves to trimmed OPENCODE_HTTP_VERSION with fallback to InstallationVersion.
Installation HTTP identity exports
packages/opencode/src/installation/index.ts
Imports InstallationHTTPVersion, exports HTTP_VERSION and HTTP_USER_AGENT constants, adds httpIdentity() function returning User-Agent and x-opencode-client headers.
Build-time constant injection
packages/opencode/script/build.ts, packages/opencode/script/build-node.ts
Both build scripts inject OPENCODE_HTTP_VERSION compile-time constant sourced from Script.httpVersion into generated binaries.
Account HTTP client with User-Agent
packages/opencode/src/account/index.ts
Account layer imports Installation and applies mapRequest to set User-Agent header using Installation.HTTP_USER_AGENT when wiring the HTTP client.
User-Agent header updates across runtime
packages/desktop-electron/src/main/index.ts, packages/opencode/src/provider/models.ts, packages/opencode/src/provider/provider.ts, packages/opencode/src/session/llm.ts
Desktop Electron replaces PawWork/ prefix with opencode/ in user agent fallback; provider models and three custom providers (GitLab, Cloudflare Workers AI, Cloudflare AI Gateway) update User-Agent headers to use HTTP_USER_AGENT or HTTP_VERSION; session LLM conditionally sets User-Agent to HTTP_USER_AGENT for opencode provider or HTTP_VERSION for others.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested labels

P2, upstream, app, platform, desktop

Poem

🐰 A version hops from upstream streams,
Through build scripts and install dreams,
User-Agents now speak as one,
From opencode—the versioning is done! 🚀

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: aligning outbound HTTP headers with canonical OpenCode desktop format to resolve rate-limiting issues.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering all required template sections including Summary, Why, Related Issue, Human Review Status, Review Focus, Risk Notes, How To Verify, and a complete Checklist with honest conditional item markings.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/http-identity-alignment

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.

@github-actions github-actions Bot added platform Electron shell, OS integration, packaging, updater, signing, paths, and permissions harness Model harness, prompts, tool descriptions, and session mechanics P2 Medium priority and removed task Narrow execution, audit, spike, migration, tracking, or upstream follow-up work labels May 27, 2026

@github-actions github-actions 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.

Suggested priority: P2 (includes user-path files (packages/desktop-electron/src/main/index.ts)).

P1/P0 are reserved for maintainer confirmation. Please relabel manually if this is a release blocker, security issue, data-loss risk, or updater/runtime failure.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces OPENCODE_HTTP_VERSION and InstallationHTTPVersion to manage and propagate the upstream HTTP version for outbound requests. It updates user agent strings across several modules (including providers, account services, and LLM sessions) to use this new version. Feedback on the changes includes updating the user agent replacement regex in the Electron main process to correctly handle development mode, and leveraging the newly introduced Installation.httpIdentity() helper in the account service to ensure all canonical headers are consistently applied.

Comment thread packages/desktop-electron/src/main/index.ts Outdated
Comment thread packages/opencode/src/account/index.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/installation/version.ts`:
- Around line 19-22: The exported InstallationHTTPVersion currently returns
OPENCODE_HTTP_VERSION without trimming even though the condition checks trim();
update the ternary to return OPENCODE_HTTP_VERSION.trim() when it's used so
surrounding whitespace doesn't leak into the User-Agent; modify the expression
that defines InstallationHTTPVersion (referencing OPENCODE_HTTP_VERSION and
InstallationVersion) to call trim() on OPENCODE_HTTP_VERSION before returning
it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b14f2725-9c81-471a-9f42-5a2d21c8db1f

📥 Commits

Reviewing files that changed from the base of the PR and between 3bf9407 and 0f61f03.

📒 Files selected for processing (11)
  • UPSTREAM_VERSION
  • packages/core/src/installation/version.ts
  • packages/desktop-electron/src/main/index.ts
  • packages/opencode/script/build-node.ts
  • packages/opencode/script/build.ts
  • packages/opencode/src/account/index.ts
  • packages/opencode/src/installation/index.ts
  • packages/opencode/src/provider/models.ts
  • packages/opencode/src/provider/provider.ts
  • packages/opencode/src/session/llm.ts
  • packages/script/src/index.ts

Comment thread packages/core/src/installation/version.ts
- P2: Account API now uses httpIdentity() (User-Agent + x-opencode-client)
  instead of setting only User-Agent
- P3: InstallationHTTPVersion returns trimmed value to prevent whitespace
  pollution in User-Agent
- Electron UA fallback regex now matches dev/beta variants
  (PawWork Dev/, PawWork Beta/) in addition to PawWork/
@Astro-Han Astro-Han merged commit 4fb99ea into dev May 27, 2026
29 of 31 checks passed
Astro-Han added a commit that referenced this pull request May 27, 2026
Bump PawWork desktop release version to 2026.5.28.

Changes since v2026.5.27:
- feat(ui): fold reasoning into trow block (#948)
- feat: align outbound HTTP headers with canonical OpenCode desktop (#940)
- feat(app): collapse notification settings to single tri-state control (#938)
- fix(ui): track List header surface via --list-surface (#954)
- fix(ui): render tooltip shortcut hints as plain sans glyphs (#955)
- fix(watcher): isolate macOS workspace roots
- fix(session): terminalize stale question blockers
- fix(session): unify transport error classification for stream disconnect recovery (#941)
- test: add route inventory guardrails
- ci: repair electron desktop build + install
@Astro-Han Astro-Han deleted the claude/http-identity-alignment branch June 2, 2026 08:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request harness Model harness, prompts, tool descriptions, and session mechanics P2 Medium priority platform Electron shell, OS integration, packaging, updater, signing, paths, and permissions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant