feat(native-llm): route Anthropic API-key models through native runtime#28271
Open
kitlangton wants to merge 5 commits into
Open
feat(native-llm): route Anthropic API-key models through native runtime#28271kitlangton wants to merge 5 commits into
kitlangton wants to merge 5 commits into
Conversation
Widens the native LLM gate beyond OpenAI: Anthropic providers using @ai-sdk/anthropic now stream through @opencode-ai/llm's anthropic-messages protocol. Adds a recorded tool-call test against claude-haiku-4-5.
Replaces the single-call native-{provider}-tool-call recorded tests with
tool-loop scenarios modeled on @opencode-ai/llm's golden suite. Each test
drives two turns through LLM.Service.stream — mirroring how the session
processor drives multi-turn in production — and asserts the model's final
text answer after the tool result is fed back.
Anthropic cassette re-recorded against claude-haiku-4-5. OpenAI and Zen
tests skip until their cassettes are re-recorded (OPENCODE_RECORD_OPENAI_API_KEY
/ OPENCODE_RECORD_CONSOLE_TOKEN + OPENCODE_RECORD_ZEN_ORG_ID).
Collapses three near-duplicate provider blocks (config builder, cassette constant, canRun flag, testEffect call, recorded*Instance) into one PROVIDERS table and a single for-loop registering tests. Uses LLMEvent.is.* type guards and LLMResponse.text() from @opencode-ai/llm instead of hand-rolled Extract<...> + filter().map().join(). Extracts a small toolRoundtrip helper for the assistant tool-call + tool-result follow-up messages. Net -64 lines.
Replaces the global OPENCODE_RECORD_ZEN_API_URL env var with a per-test connection slug (OPENCODE_RECORD_ZEN_CONNECTION). The Zen proxy URL depends on which upstream connection the test routes through, so the slug now lives next to the cassette spec instead of being smuggled through a single URL env var. Records the native Zen cassette against the production console proxy. Re-records the Anthropic cassette in the same pass since the test code shape changed.
- canRecord is now a plain boolean evaluated at module load (consistent with shouldRecord). Env vars don't change after import. - Drop "as const" from the PROVIDERS satisfies — literal keys aren't consumed anywhere; the satisfies alone is enough. - structuredClone instead of JSON.parse(JSON.stringify) for cloneModel. - Inline the trivial single-use locals in recordedNativeLLMLayer.
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.
Summary
@ai-sdk/anthropicnow stream through@opencode-ai/llm'santhropic-messagesprotocol. AI SDK remains the default; native is still opt-in behindOPENCODE_EXPERIMENTAL_NATIVE_LLM/OPENCODE_EXPERIMENTAL.native-request.tsROUTE/DEFAULT_BASE_URLtables) already mapped@ai-sdk/anthropic→anthropic-messages, so the only change tonative-runtime.ts:status()is admitting the new providerID + npm pair.Test plan
bun run typecheckfrompackages/opencode— clean.bun run test test/session/llm-native.test.ts— 9/9 pass.session/native-anthropic-tool-call.jsonagainstclaude-haiku-4-5-20251001; replay run is 3/3 inllm-native-recorded.test.ts.To re-record:
RECORD=true OPENCODE_RECORD_ANTHROPIC_API_KEY=... bun run test test/session/llm-native-recorded.test.ts