feat: opencode v2 server support with v1 compatibility - #209
Open
bluetoe-99 wants to merge 1 commit into
Open
bluetoe-99 wants to merge 1 commit into
bluetoe-99 wants to merge 1 commit into
Conversation
opencode 2.x replaced the HTTP API: routes moved under /api/, the SSE envelope
changed from {"payload":{id,type,properties}} to {id,type,data}, message/part
payloads were renamed (Session.Info, Message.Info, UserMessage/AssistantMessage),
and question prompts became server-side forms. `npm install -g opencode-ai` still
installs the 1.x line (1.18.32 as of 2026-09-24), so a client has to speak both
APIs.
v2 client (src/lib/sdk.ts, src/lib/v2-shape.ts):
- /api/... endpoints, the v2 message shapes, interrupt, staged revert, session diff
- SSE via /api/event; the question tool arrives as a form nested under data.form on
form.created - reading it flat silently dropped every prompt
- session-scoped permission and form replies
v1 client (src/lib/sdk-v1.ts, src/lib/api-detect.ts):
- the transport main already ships, restored unchanged (sessions, prompts, abort,
revert, diff, questions, permissions, agents, commands, providers, file browsing)
- a connect-time probe classifies the server by response content type: unknown
routes on both server generations answer 200 text/html through the web SPA, so
status codes cannot discriminate. /api/info JSON means v2, /global/health JSON
means v1; api + serverVersion are recorded on the connection and createClient()
dispatches on them
Message UI:
- selection and copying rework around MessageTextSheet: Select text / Edit are
header buttons and the sheet renders the whole message (text, reasoning, tool
input/result/error, files) in a plain ScrollView where native selection works,
with Copy all as the whole-message fallback. The bubble has no press at all: a
press whose movement stays inside its bounds is kept by the touchable, which
opened the message menu mid-scroll.
- inline selection is iOS-only for user message text, message error text, code
lines and diff lines: selectable <Text> inside FlatList rows is the Android bug
(react-native#46999, still open) that Markdown.tsx already works around.
ToolCallCard, ReasoningBlock, ErrorBoundary and Markdown.tsx are unchanged.
- wide code and diff lines wrap instead of scrolling sideways; CodeBlock's Copy
still hands the clipboard the original string, so pasted code is byte-identical
- keyboard avoidance via react-native-keyboard-controller, including system-bar
insets, so the composer is never hidden behind the keyboard; SSE reconnects on
app foreground
Verified against live servers: opencode 2.0.16 (v2 endpoints, and the question path
replayed from a captured form.created stream) and opencode 1.18.32 (`opencode
serve`: health, project, path, session create/list/update/delete/abort/messages,
agents, commands, questions, permissions, providers, and the wrapped {"payload":...}
event stream through the existing unwrap in stores/events.ts).
docs/v2-api-map.md records the verified API maps, event schemas and probe behaviour
for both server generations.
Signed-off-by: bluetoe-99 <102478736+bluetoe-99@users.noreply.github.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Fixes #194 (Android: chat input hidden behind keyboard).
Fixes #205 (opencode2 support?).
Fixes #156 (Unable to see the input box — same composer-behind-keyboard report as #194).
Adds opencode v2 server support while keeping every opencode 1.x (≤ 1.18.x) server working.
npm install -g opencode-aistill installs the 1.x line (latest= 1.18.32 as of 2026-09-25), so both APIs are common in the wild and the client now speaks whichever the server speaks.v2 (
src/lib/sdk.ts,src/lib/v2-shape.ts)/api/...endpoints, the v2 SSE envelope ({id, type, data}), the renamed message/part shapes, interrupt, staged revert, session diff.questiontool arrives as a server-side form nested underdata.formonform.created. Reading it flat silently dropped every prompt, so questions never appeared in the app.v1 (
src/lib/sdk-v1.ts,src/lib/api-detect.ts)The transport
mainalready ships, restored unchanged (sessions, prompts, abort, revert, diff, questions, permissions, agents, commands, providers, file browsing). A connect-time probe classifies the server by response content type — never status code, because unknown routes on both server generations fall through to the web SPA with200 text/html:GET /api/info200 application/json, or401unauthenticated200 text/html(SPA)GET /global/health200 text/html(SPA)200 application/json{healthy, version}The detected
apiandserverVersionare stored on the connection, reused across screens, and invalidated when the URL changes;createClient()dispatches on them.Selection and copying
MessageTextSheet+src/lib/message-text.ts: Select text and Edit are header buttons, and the sheet renders the whole message (text, reasoning, tool input/result/error, files) in a plain ScrollView where native selection actually works, with Copy all as the whole-message fallback. The bubble itself has no press at all: a press whose movement stays inside its bounds is kept by the touchable, which is what opened the message menu mid-scroll.selectable<Text>insideFlatListrows is react-native#46999 (still open, no linked PR) andMarkdown.tsxalready works around it.ToolCallCard,ReasoningBlock,ErrorBoundaryandMarkdown.tsxare unchanged.CodeBlock's Copy still hands the clipboard the original string, so pasted code is byte-identical to what the server sent.react-native-keyboard-controller, including system-bar insets, so the composer is never hidden behind the keyboard (Android: chat input hidden behind keyboard #194); the SSE stream reconnects on app foreground.Screenshots
Wrapped code block with the header buttons and the reasoning block:
Composer visible above the keyboard (#194):
Select text sheet with Copy all:
Verification
form.createdstream.opencode serveon 1.18.32 — health, project, path, session create/list/update/delete/abort/messages, agents, commands, questions, permissions, providers, and the wrapped{"payload": ...}event stream through the existing unwrap instores/events.ts.tsc --noEmitclean;npm test363/363, including new suites for the probe classifier, the v2 shape translator, message-text assembly, and two component regression files.docs/v2-api-map.mdrecords the verified API maps, event schemas and probe behaviour for both server generations.Notes
react-native-keyboard-controller(its transitivereact-native-is-edge-to-edgeis already in the lock).android/is untouched because CI runsexpo prebuild.DCO signed off.