This repository was archived by the owner on Apr 26, 2026. It is now read-only.
Upgrade to AI SDK v3 spec, fix hanging thinking indicator, add --effort support#12
Open
Aptul9 wants to merge 3 commits into
Open
Upgrade to AI SDK v3 spec, fix hanging thinking indicator, add --effort support#12Aptul9 wants to merge 3 commits into
Aptul9 wants to merge 3 commits into
Conversation
- Upgrade specificationVersion from v2 to v3, eliminating the compatibility layer that caused the thinking indicator to hang in OpenCode. - Return usage in V3 format (nested objects with total/cacheRead/etc) fixing the 'usage2.inputTokens.total' crash in AI SDK v6. - Filter empty text blocks in message builder to prevent 'cache_control cannot be set for empty text blocks' API errors. - Return empty stream when no user content is available, preventing API errors on follow-up calls with empty messages. - Always use finishReason 'stop' since the CLI executes all tools internally and returns complete results. - Add --effort flag passthrough: reads effort level from OpenCode variant selection and passes it to the Claude CLI. - Upgrade @ai-sdk/provider to 3.0.8 and @ai-sdk/provider-utils to 4.0.23 for V3 type support.
CLI returns input_tokens as non-cached count only, while cacheRead and cacheWrite are separate. OpenCode expects inputTokens.total to include all input tokens (cached + non-cached), then subtracts cache internally. Pass total = input + cacheRead + cacheWrite so OpenCode's subtraction produces the correct non-cached count instead of going negative. Also populate noCache field with the raw non-cached input count.
- Emit text-start/delta/end per CLI text block instead of one pair for the entire turn. Each text block is saved immediately by OpenCode as a separate part, preventing loss when the stream is aborted before the result event arrives. - Add providerExecuted flag to tool-input-start events so OpenCode does not re-loop looking for unresolved tool calls. - Use last iteration token counts from CLI usage instead of cumulative totals across all internal tool-use iterations — prevents inflated context counters and premature compaction. - Add 5s result fallback timer: if the CLI emits a final text block but never sends a result event, the stream closes gracefully after 5 seconds with accumulated content. - On abort signal, start grace period instead of closing immediately, allowing in-flight CLI messages to be processed. - Fix Copilot review comments: re-enable DTS generation, remove unused LanguageModelV3StreamPart import, remove ai from runtime dependencies. - Remove file-based trace logging.
Closed
9 tasks
17 tasks
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Summary
Core fixes required to make the plugin work correctly under AI SDK v6 / OpenCode v1.4.3, plus
--effortflag passthrough. This PR is the V3 migration split out from the previous larger PR per maintainer request.AI SDK v3 spec migration
specificationVersionfromv2tov3, eliminating the V2-to-V3 compatibility layer in AI SDK v6 that caused the thinking indicator to hang indefinitely in OpenCodetotal/cacheRead/cacheWrite/reasoning) — fixes theusage2.inputTokens.totalcrash under AI SDK v6 / OpenCode v1.4.3cache_control cannot be set for empty text blocksAPI errorsfinishReason: "stop"since the CLI executes all tools internally and returns complete results — prevents the AI SDK agentic loop from making unnecessary follow-up calls@ai-sdk/providerto3.0.8and@ai-sdk/provider-utilsto4.0.23Effort flag passthrough
--effortflag passthrough: reads effort level from OpenCode thinking variant selection and passes it to the Claude CLI via--effort <level>Stream event fixes
text-start/text-delta/text-endfor each CLI text block instead of a single pair for the entire turn. Each text block is saved immediately by OpenCode as a separate part, preventing loss of the final response text when the stream is aborted before theresultevent arrives from the CLI.providerExecutedflag totool-input-startevents so OpenCode marks CLI-executed tools correctly and does not re-loop looking for unresolved tool calls.usage.iterations[-1]from CLI result instead of cumulative totals across all internal tool-use iterations — prevents inflated context counters (e.g. 780k instead of 80k) and premature compaction.total = input + cacheRead + cacheWriteso the OpenCode UI does not display negative values.resultevent, the stream closes gracefully after 5 seconds with accumulated content.LanguageModelV3StreamPartimport, removeaifrom runtime dependencies.OpenCode config example with thinking variants
{ "provider": { "claude-code": { "npm": "opencode-claude-code-plugin", "models": { "sonnet": { "name": "Claude Code Sonnet", "limit": { "context": 1000000, "output": 64000 }, "capabilities": { "reasoning": true, "toolcall": true }, "variants": { "low": { "thinking": { "type": "adaptive" }, "effort": "low" }, "medium": { "thinking": { "type": "adaptive" }, "effort": "medium" }, "high": { "thinking": { "type": "adaptive" }, "effort": "high" }, "max": { "thinking": { "type": "adaptive" }, "effort": "max" } } } } } } }Test plan
streamText+fullStream(correct event ordering)maxSteps: 5(no unnecessary follow-up steps)Follow-ups
Two independent follow-up PRs split from the previous combined submission:
.jsonlsessions into the OpenCode DB