chore: sync upstream dev through 62e4641235#9
Conversation
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 2 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0545e2a64f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| api: createCompatibleApi({ | ||
| protocol: serverSDK.protocol, | ||
| current: serverSDK.currentApi, | ||
| legacy: (next) => serverSDK.createClient({ directory: next ?? directory, throwOnError: true }), | ||
| directory, | ||
| }), |
There was a problem hiding this comment.
Route existing SDK calls through the compatibility layer
When the detected protocol is v2, this adds a compatible api beside the existing SDK, but the existing client/createClient surface remains the legacy @opencode-ai/sdk client that current app code already uses. Call sites such as prompt submission (sdk().client.session.promptAsync) and session bootstrap (serverSDK.client.session.list) do not read this new api property, so a v2-only server still receives legacy /session/... requests instead of /api/..., preventing sessions from being loaded or prompted unless those callers are migrated or the exposed client is made compatible.
Useful? React with 👍 / 👎.
| return { id: event.id, type: "question.replied", properties: event.data, current: event } as ServerEvent | ||
| if (event.type === "question.v2.rejected") | ||
| return { id: event.id, type: "question.rejected", properties: event.data, current: event } as ServerEvent | ||
| return { id: event.id, type: event.type, properties: event.data, current: event } as ServerEvent |
There was a problem hiding this comment.
Convert current deltas before emitting them
For the v2 event stream, current events like session.text.delta, session.reasoning.delta, and session.tool.input.delta are emitted with those same type names here. The downstream session reducers only apply the legacy message.part.delta/message.part.updated shapes, and the coalescer still emits the unhandled session.*.delta type after concatenating, so live streamed text/reasoning/tool input from v2 servers is dropped until some later full snapshot or reload. Map these current delta events to the legacy part-delta/update shape or add reducer handlers before emitting them.
Useful? React with 👍 / 👎.
| const current = await probe(server, fetch, "/api/health").catch(() => undefined) | ||
| if (current && "pid" in current && typeof current.pid === "number") return "v2" | ||
| if (current && "healthy" in current && current.healthy === true) return "v1" |
There was a problem hiding this comment.
Treat pid-less
/api/health responses as v2
When /global/health is unavailable, a v2 server generated from this repo's Protocol currently answers /api/health with just { healthy: true } (packages/protocol/src/groups/health.ts defines no pid), but this probe classifies that exact response as v1. That sends the new event transport and compatibility layer down the legacy endpoint path against current servers, so recognize a successful /api/health response as v2 or use another discriminator that matches the actual schema.
Useful? React with 👍 / 👎.
| return { id: event.id, type: "question.replied", properties: event.data, current: event } as ServerEvent | ||
| if (event.type === "question.v2.rejected") | ||
| return { id: event.id, type: "question.rejected", properties: event.data, current: event } as ServerEvent | ||
| return { id: event.id, type: event.type, properties: event.data, current: event } as ServerEvent |
There was a problem hiding this comment.
Adapt v2 session deletion payloads before dispatch
When the current event stream emits the v2 session.deleted event, its payload can be just { sessionID } rather than the legacy { info } shape. Passing it through unchanged makes the existing session reducers read properties.info.id, so deleting a session from a v2 server can throw during event handling instead of removing it from the UI; translate this event to the legacy shape or update the reducers before dispatching it.
Useful? React with 👍 / 👎.
Summary
devthrough62e4641235d7847dadc60da37cca8a023dd54fc1.fork-only push invariants.
Review
5c8d584c45abcafad7bd1127a9d22b7de2bcaf8f0545e2a64f9b7c33595d855b72929901c5f9424e542ba88602fix(provider): select prompt cache keys by SDK (fix(provider): select prompt cache keys by SDK anomalyco/opencode#38424)fada1a538ffix(provider): serialize Mistral prompt cache keys (fix(provider): serialize Mistral prompt cache keys anomalyco/opencode#38448)92cede0541chore: update nix node_modules hashese45210c6d2chore(app): vendor v2 promise client (chore(app): vendor v2 promise client anomalyco/opencode#38467)84c79c1399chore: update nix node_modules hashesd03e0c5e54feat(app): add dual-server compatibility (feat(app): add dual-server compatibility anomalyco/opencode#38462)347510a73bchore: generatee59ba24b80feat(app): support current event transport (feat(app): support current event transport anomalyco/opencode#38464)62e4641235chore: generatebun.lockonly (both-sides lockfile changes). Resolved by takingthe fork's lockfile and running
bun installto add upstream's newdependencies while preserving existing version resolutions (notably
storybook-solidjs-vite@10.1.1andstorybook@10.4.1). The other 5 overlapfiles (
package.json,packages/core/package.json,packages/desktop/src/main/server.ts,packages/opencode/package.json,packages/session-ui/package.json) auto-merged cleanly with zero conflicts.Scope
The 9 incoming commits add:
server-compat.tsandserver-protocol.tsmodules that detect whether the connected server speaksthe v1 legacy API (
/global/health) or the v2 current API (/api/health),and adapt event transport and API calls accordingly. Adds a vendored
@opencode-ai/clientpromise client (opencode-ai-client-1.17.13.tgz).server-sdk.tsxto supportboth legacy SSE events and current transport events, with delta coalescing
for text/reasoning/tool/compaction streams. Removes the old heartbeat
timeout mechanism.
provider/transform.tsto select cache keys based on SDK npm package ratherthan provider ID, with correct property names per SDK (
promptCacheKeyvsprompt_cache_key). AddssdkKey()mappings for 11 additional providers.promptCacheKeysupportto
@ai-sdk/mistral@3.0.34via a vendored patch, bumps from3.0.27.chorecommits.Fork overlap files auto-merged without conflict. The fork's isolated sidecar
env, desktop health-check, and dependency version changes are in different code
regions from the upstream additions.
Validation
FORKandUPSTREAMare bothancestors of candidate), clean tree, diff-check passed (only upstream's
patch file has trailing-whitespace warnings), remote
mainunchanged.linux-ci-20260723T150932Z-0545e2a64f-package2, resultPASS (all 10 stages: environment, static, dependencies, focused,
typecheck, lint, broad-tests [208 httpapi pass/0 fail], builds, desktop-build,
package-linux).
storybook-solidjs-vite@10.1.1andstorybook@10.4.1preserved; Storybook build passes. An initial candidate with a full lockfile
regeneration resolved to
10.6.0/10.5.2, which failed Storybook build(
Could not detect Solid version— a Bun workspace resolution bug in thenewer storybook-solidjs-vite). Resolved by preserving the fork's lockfile as
base and incrementally adding upstream's new dependencies.
opencode-classicv1.18.4, maintainerLogicLyra, no AppImage.prior PRs; QEMU CPU
version 2.5+has no AVX, Electron 42.3.3 GPU SIGILL).Changed files are server protocol logic, provider transforms, and docs — no
Electron/GPU initialization impact. Not a code defect.
opencode-classic-desktop-linux-amd64.deb(127 MB)opencode-classic-desktop-linux-x86_64.rpm(109 MB)latest-linux.ymlNo published versions on GitHub(expected before firststable release);
bun audit9 pre-existing transitive-dep CVEs (tar,brace-expansion, sharp, fast-uri, axios, js-yaml) in build/docs tooling,
identical to prior PRs, treated as advisory-only.
runtime visual gate (VM AVX limitation).
No tag, release, publication, direct
mainpush, or write to the officialupstream repository occurred. Please review and merge this PR on GitHub using
a merge commit.