Repository navigation
feat(ai, openai-base): add wrapFetch to chat(), onConfig, and the text adapters - #1680
Conversation
…t adapters A wrapper gets the next fetch and gives back a new one, so a caller can change the URL, headers, request, or response of each model call. The middleware wrapper chains inside the chat() wrapper and lasts for one call. The openai-base adapters wrap the fetch that the adapter gave its client. Anthropic, Mistral, Ollama, and OpenRouter build a per-call client with the wrapped fetch.
🦋 Changeset detectedLatest commit: 40d06a0 The changes in this PR will be included in the next version bump. This PR includes changesets to release 51 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (16)
🚧 Files skipped from review as they are similar to previous changes (4)
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 3 remain after this review. 📝 WalkthroughWalkthroughThe pull request adds ChangesPer-call fetch wrapping
Priority: ➖ Normal Estimated code review effort: 4 (Complex) | ~60 minutes Change: Feature Sequence Diagram(s)sequenceDiagram
participant TextEngine
participant ChatMiddleware
participant TextAdapter
participant ConfiguredFetch
TextEngine->>ChatMiddleware: Apply onConfig wrapper
ChatMiddleware->>TextEngine: Return composed config
TextEngine->>TextAdapter: Pass wrapper to model call
TextAdapter->>ConfiguredFetch: Send request through wrapped fetch
Merge Risk: ⚪ Minimal · up to No concrete merge-blocking regression is established. The change is ready to merge after normal checks. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
|
View your CI Pipeline Execution ↗ for commit 40d06a0
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-byteplus
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-cloudflare
@tanstack/ai-code-mode
@tanstack/ai-code-mode-snippets
@tanstack/ai-codex
@tanstack/ai-cohere
@tanstack/ai-compaction
@tanstack/ai-devtools-core
@tanstack/ai-durable-stream
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-grok-build
@tanstack/ai-groq
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-daytona
@tanstack/ai-isolate-e2b
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-isolate-quickjs-bun
@tanstack/ai-llmgateway
@tanstack/ai-lovable
@tanstack/ai-mcp
@tanstack/ai-memory
@tanstack/ai-mistral
@tanstack/ai-octane
@tanstack/ai-ollama
@tanstack/ai-ollaya
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@tanstack/ai-perplexity
@tanstack/ai-persistence
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-reactor
@tanstack/ai-remix
@tanstack/ai-sandbox
@tanstack/ai-sandbox-blaxel
@tanstack/ai-sandbox-boxd
@tanstack/ai-sandbox-cloudflare
@tanstack/ai-sandbox-daytona
@tanstack/ai-sandbox-docker
@tanstack/ai-sandbox-e2b
@tanstack/ai-sandbox-local-process
@tanstack/ai-sandbox-railway
@tanstack/ai-sandbox-sprites
@tanstack/ai-sandbox-upstash-box
@tanstack/ai-sandbox-vercel
@tanstack/ai-skills
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-typesafe
@tanstack/ai-utils
@tanstack/ai-vercel-gateway
@tanstack/ai-vertex
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/ai-worldlabs
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
@tanstack/svelte-ai-devtools
commit: |
Coverage✅ Coverage held across 66 compared package(s). Each package is measured twice in this job — on this PR and on its merge-base with
|
# Conflicts: # packages/ai-anthropic/src/adapters/text.ts
# Conflicts: # packages/ai-anthropic/src/adapters/text.ts
You can now change the HTTP requests of a model call without building your own client.
wrapFetchtakes the nextfetchand returns a new one, so it can add headers, change the URL, log, or read the response. Set it onchat(), or return it from a middlewareonConfigfor one call. Wrappers chain.This PR is split out of #1555.
🎯 Changes
@tanstack/ai:wrapFetchonchat(), onChatMiddlewareConfig, and onTextOptions, typed by the newFetchWrappertype.mergeConfigstep in the middleware runner chains a middleware wrapper inside the earlier ones, so it does not replace them.openai-base: both base adapters wrap the fetch that the adapter gave its client. They do not read a private SDK field. This covers OpenAI, the OpenAI-compatible adapters, Grok, Groq, BytePlus, LLM Gateway, Lovable, Vercel AI Gateway, Cloudflare REST, and the Bedrock Chat Completions and Responses APIs.main) works through theopenai-basepath. The SDK'swithOptionscopy keepsapiVersion, so Azure needs no override. Two Azure cases intests/wrap-fetch-wire.test.tsguard this.compact(), and the Copilot and Codex recipes.mainat39e23c0b. The merge fixes a conflict in the Anthropic constructor with feat(ai-anthropic): choose the credential kind with auth, and read the environment only in anthropicText #1688. The adapter keeps theauthsetup from feat(ai-anthropic): choose the credential kind with auth, and read the environment only in anthropicText #1688 and stores the SDK client forwrapFetch. A new test checks thatauth: 'bearer'stays on the per-call client:Authorization: Bearer, and nox-api-key.wrapFetchrow and a new "Change the HTTP requests of a call" section inadvanced/middleware.md.@tanstack/aiandopenai-base, patch for 8 adapter packages.✅ Checklist
pnpm run test:pr, or these tests do not apply to this pull request.docs/for this change, or this change is not user-facing.pnpm changeset), or this PR does not change a published package.🚀 Release Impact
Testing
Commands run
vitest runafter the merge withmain(39e23c0b):ai2102,openai-base284,ai-openai359,ai-anthropic224,ai-mistral72,ai-ollama61,ai-openrouter266,ai-bedrock124,ai-cloudflare27,ai-grok158,ai-groq41,ai-byteplus299,ai-llmgateway16,ai-lovable52,ai-vercel-gateway39. All pass, andtscis clean in each of these packages.wrapFetchwire test passes in all 14 packages that send requests through it.test:typesandtest:oxlintin all 15 changed packages: both pass.pnpm test:docs: no broken links.pnpm test:prand the E2E suite. CI runs them.Manual test
pnpm --dir packages/ai exec vitest run tests/wrap-fetch.test.ts.chat()wrapper sees each call.pnpm --dir packages/ai-mistral exec vitest run tests/wrap-fetch-wire.test.ts.How this PR makes testing easy
wrap-fetch-wire.spec.ts, with routeapi.wrap-fetch-wire.ts. It checks that the request to aimock carries thex-wrap-fetchheader that the wrapper added.Risk / rollback
wrapFetchis not set. The requests do not change.openai-baseconstructors now passoptions.fetchalong. A third-party subclass that does not pass its own fetch gets the global fetch wrapped.To undo, revert this PR.
Public API change
Before
// build your own client with a custom fetch, per adapterAfter
Summary by CodeRabbit
wrapFetchsupport for adding request headers, logging, and modifying HTTP requests for supported model adapters.wrapFetch; behavior varies by provider.