TanStack AI version
@tanstack/ai 0.54.0, @tanstack/ai-openai 0.22.6 (current main)
Framework/Library version
Any (server-side, framework-independent)
Describe the bug and the steps to reproduce it
summarize({ maxLength }) sends no output token cap for any provider reached through openaiCompatible (DeepSeek, Moonshot/Kimi, Together, Fireworks, Qwen, vLLM, and others).
openaiCompatible has no summarize factory. To summarize, you wrap the text adapter in ChatStreamSummarizeAdapter. That wrapper chooses the token key from its own name, using MAX_TOKENS_KEY_BY_ADAPTER in packages/ai/src/activities/summarize/chat-stream-summarize.ts. That map only has first-party names (openai, anthropic, groq, llmgateway, cloudflare, ...). A compatible provider's name is chosen by the user, so it is never in the map:
- With the default name
chat-stream-summarize, the cap is dropped.
- With the provider name, for example
deepseek, the cap is dropped.
- With
openai, the key is max_output_tokens. That is the Responses API key, and the Chat Completions endpoint ignores it.
In each case, the SDK logs a warning and sends the request without max_tokens or max_completion_tokens. Only the prompt asks the model to stay short.
Steps:
import { summarize, ChatStreamSummarizeAdapter } from '@tanstack/ai'
import { openaiCompatible } from '@tanstack/ai-openai/compatible'
const deepseek = openaiCompatible({
name: 'deepseek',
baseURL: 'https://api.deepseek.com/v1',
apiKey: process.env.DEEPSEEK_API_KEY ?? '',
models: ['deepseek-chat'],
})
const adapter = new ChatStreamSummarizeAdapter(
deepseek('deepseek-chat'),
'deepseek-chat',
'deepseek',
)
await summarize({ adapter, text: longText, maxLength: 100 })
Expected: the Chat Completions request body contains an output cap (max_tokens or max_completion_tokens).
Actual: the request body has no output cap. The logger warns maxLength=100 could not be mapped to a provider token key for adapter name "deepseek".
Possible fixes:
- Choose the key from the wrapped adapter's wire API, not from a name. Every Chat Completions adapter on
OpenAIBaseChatCompletionsTextAdapter would get a Chat Completions key. This also removes the need for per-gateway entries such as llmgateway and cloudflare.
- Add a summarize factory to
openaiCompatible, with an optional maxTokensKey setting.
Related: the other openaiCompatible gap, reasoning deltas (delta.reasoning_content / delta.reasoning) that are never surfaced, is tracked in #982 and fixed in #1367.
Your Minimal, Reproducible Example - (Sandbox Highly Recommended)
See the snippet above. Code path: ChatStreamSummarizeAdapter.buildTextOptions, then isKnownMaxTokensAdapter(this.name) and applyMaxLength.
Do you intend to try to help solve this bug with your own PR?
Maybe, I'll investigate and start debugging
TanStack AI version
@tanstack/ai0.54.0,@tanstack/ai-openai0.22.6 (currentmain)Framework/Library version
Any (server-side, framework-independent)
Describe the bug and the steps to reproduce it
summarize({ maxLength })sends no output token cap for any provider reached throughopenaiCompatible(DeepSeek, Moonshot/Kimi, Together, Fireworks, Qwen, vLLM, and others).openaiCompatiblehas no summarize factory. To summarize, you wrap the text adapter inChatStreamSummarizeAdapter. That wrapper chooses the token key from its ownname, usingMAX_TOKENS_KEY_BY_ADAPTERinpackages/ai/src/activities/summarize/chat-stream-summarize.ts. That map only has first-party names (openai,anthropic,groq,llmgateway,cloudflare, ...). A compatible provider's name is chosen by the user, so it is never in the map:chat-stream-summarize, the cap is dropped.deepseek, the cap is dropped.openai, the key ismax_output_tokens. That is the Responses API key, and the Chat Completions endpoint ignores it.In each case, the SDK logs a warning and sends the request without
max_tokensormax_completion_tokens. Only the prompt asks the model to stay short.Steps:
Expected: the Chat Completions request body contains an output cap (
max_tokensormax_completion_tokens).Actual: the request body has no output cap. The logger warns
maxLength=100 could not be mapped to a provider token key for adapter name "deepseek".Possible fixes:
OpenAIBaseChatCompletionsTextAdapterwould get a Chat Completions key. This also removes the need for per-gateway entries such asllmgatewayandcloudflare.openaiCompatible, with an optionalmaxTokensKeysetting.Related: the other
openaiCompatiblegap, reasoning deltas (delta.reasoning_content/delta.reasoning) that are never surfaced, is tracked in #982 and fixed in #1367.Your Minimal, Reproducible Example - (Sandbox Highly Recommended)
See the snippet above. Code path:
ChatStreamSummarizeAdapter.buildTextOptions, thenisKnownMaxTokensAdapter(this.name)andapplyMaxLength.Do you intend to try to help solve this bug with your own PR?
Maybe, I'll investigate and start debugging