Skip to content

feat(workers-ai-provider): add custom fetch option for credentials mode#480

Merged
threepointone merged 1 commit intomainfrom
workers-ai-custom-fetch
Apr 5, 2026
Merged

feat(workers-ai-provider): add custom fetch option for credentials mode#480
threepointone merged 1 commit intomainfrom
workers-ai-custom-fetch

Conversation

@threepointone
Copy link
Copy Markdown
Collaborator

Summary

Adds an optional fetch parameter to workers-ai-provider when using credentials mode (accountId + apiKey). This matches the pattern used by @ai-sdk/openai and @ai-sdk/anthropic, enabling request interception for testing, middleware, and advanced use cases like durable response buffering.

Motivation

The Agents SDK is building a durable response buffer that survives DO eviction during long-running inference calls (RFC #1257). The buffer works by intercepting the provider's HTTP call and routing it through a proxy that persists the streaming response. For OpenAI and Anthropic, this is done via their fetch option. Workers AI lacked this option, requiring a workaround (fake AI binding whose run() routes to the buffer).

With this change, Workers AI in credentials mode supports the same clean pattern:

const model = createWorkersAI({
  accountId: "...",
  apiKey: "...",
  fetch: myCustomFetch  // intercepts all HTTP calls
})("@cf/moonshotai/kimi-k2.5");

Changes

src/index.ts

  • Added fetch?: typeof globalThis.fetch to the credentials branch of WorkersAISettings (not the binding branch — bindings don't use HTTP)
  • Passed fetch through to createRun()
  • TypeScript enforces that fetch can only be used with credentials, not with bindings

src/utils.ts

  • Added fetch? to CreateRunConfig
  • createRun resolves fetchFn = config.fetch ?? globalThis.fetch and uses it for both the main request and the streaming retry fallback
  • createRunBinary is unchanged (used for transcription, separate concern)

test/utils.test.ts

  • Added test: custom fetch is called instead of global fetch
  • Added test: custom fetch is used for the streaming retry fallback path (when a model returns JSON instead of SSE, createRun retries with stream: false — both calls go through the custom fetch)

Type safety

The fetch option is in the credentials branch of the discriminated union, so TypeScript rejects { binding: env.AI, fetch: myFetch } at the type level. This prevents confusion — bindings bypass HTTP entirely, so a custom fetch would have no effect.

Test plan

  • All 38 existing + new tests pass (npx vitest run test/utils.test.ts)
  • Type check passes (npx tsc --noEmit)
  • Custom fetch test verifies globalThis.fetch is NOT called
  • Streaming retry test verifies custom fetch is used for both attempts

Made with Cursor

Expose an optional fetch parameter when using accountId+apiKey credentials so callers can intercept or provide a custom fetch implementation (useful for testing). Pass options.fetch into createRun, use it as fetchFn (falling back to globalThis.fetch), and update run to call fetchFn for normal and retry requests. Added unit tests for custom fetch behavior and a changeset entry documenting the change.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 5, 2026

🦋 Changeset detected

Latest commit: 1c6bdad

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
workers-ai-provider Patch

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

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 5, 2026

Open in StackBlitz

npx https://pkg.pr.new/cloudflare/ai/ai-gateway-provider@480
npx https://pkg.pr.new/cloudflare/ai/@cloudflare/tanstack-ai@480
npx https://pkg.pr.new/cloudflare/ai/workers-ai-provider@480

commit: 1c6bdad

@threepointone threepointone merged commit 19f2fd7 into main Apr 5, 2026
3 checks passed
@threepointone threepointone deleted the workers-ai-custom-fetch branch April 5, 2026 12:33
@github-actions github-actions Bot mentioned this pull request Apr 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant