wrapProvider removes file and skill upload support
Description
wrapProvider() removes a provider's files() and skills() methods. Adding language-model middleware makes uploadFile({ api: wrapped }) and uploadSkill({ api: wrapped }) fail, although both work with the original provider.
Expected: wrapping the language models preserves the provider's existing upload APIs.
Actual:
original file: { example: 'file-synthetic' }
original skill: { example: 'skill-synthetic' }
wrapped file: The provider does not support file uploads. Make sure it exposes a files() method.
wrapped skill: The provider does not support skills. Make sure it exposes a skills() method.Both methods are part of ProviderV4, but wrapProvider constructs a new object without forwarding them. customProvider({ fallbackProvider }) preserves them. The same method loss occurs when wrapping createOpenAI(); the reproduction below uses synthetic upload handlers to avoid network calls.
Reproduction
In an empty directory, run npm init -y and npm install [email protected]. Save as repro.mts and run node repro.mts with Node 24. No API key is needed.
import { customProvider, uploadFile, uploadSkill, wrapProvider } from 'ai';
const provider = customProvider({
files: {
specificationVersion: 'v4',
provider: 'example',
uploadFile: async () => ({
providerReference: { example: 'file-synthetic' },
warnings: [],
}),
},
skills: {
specificationVersion: 'v4',
provider: 'example',
uploadSkill: async () => ({
providerReference: { example: 'skill-synthetic' },
warnings: [],
}),
},
});
const wrapped = wrapProvider({
provider,
languageModelMiddleware: { specificationVersion: 'v4' },
});
for (const [name, api] of Object.entries({ original: provider, wrapped })) {
try {
const result = await uploadFile({
api,
data: { type: 'text', text: 'Synthetic example.' },
});
console.log(name, 'file:', result.providerReference);
} catch (error) {
console.log(name, 'file:', error instanceof Error ? error.message : error);
}
try {
const result = await uploadSkill({
api,
files: [{ path: 'SKILL.md', data: { type: 'text', text: 'Synthetic skill.' } }],
});
console.log(name, 'skill:', result.providerReference);
} catch (error) {
console.log(name, 'skill:', error instanceof Error ? error.message : error);
}
}Local regression checks: two failing upload cases and six passing controls, covering direct uploads, fallback providers, language middleware, and providers without upload support. The standalone reproduction also passes strict TypeScript checking.
I used AI assistance to investigate and prepare the reproduction and tests.
AI SDK Version
[email protected], Nodev24.13.0.- The affected wrapProvider source on main is byte-for-byte identical to the inspected
7.0.101checkout. Runtime tests used published[email protected].
Code of Conduct
- I agree to follow this project's Code of Conduct
Source: vercel/ai