openai-base: a Responses max_output_tokens cutoff ends as RUN_ERROR without usage instead of finishReason 'length'
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 74/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- typescript
- Lĩnh vực
- backend-api-design
Hướng nghiên cứu
Bắt đầu ở packages/openai-base/src/adapters/responses-text.ts, so sánh cách xử lý response.incomplete gần các dòng 1748–1806 với cách ánh xạ response.completed gần các dòng 2442–2473. Kiểm tra các bài kiểm thử của adapter cho sự kiện kết thúc, usage và finish reasons. Công việc hoàn tất khi các lý do chưa hoàn tất đã biết kết thúc với usage và lý do được ánh xạ, còn các phản hồi thất bại hoặc có lý do không xác định vẫn là lỗi.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
What happens
When a Responses stream hits max_output_tokens, it ends with response.incomplete (status: "incomplete", incomplete_details.reason: "max_output_tokens"), and that event carries the response's usage. The Responses adapter in @tanstack/openai-base turns it into RUN_ERROR (message: "max_output_tokens", code: "incomplete") and drops the usage:
So with the Responses adapter:
- the run ends in
onError, notonFinish, right after the partial text the user has already seen; onUsagenever fires, although the provider billed the tokens;finishReason: 'length'never appears, sountilFinishReason(['length'])and the core stop-on-length path (#1874) never see a capped answer.
The response.completed branch already maps incomplete_details.reason (max_output_tokens → length, content_filter → content_filter), "mirroring the chat-completions adapter". A capped response does not arrive as response.completed, so that mapping is not reached for it:
The Chat Completions adapter reports the same cutoff as RUN_FINISHED with usage and finishReason: 'length'.
Repro
@tanstack/ai 1.0.0, @tanstack/openai-base 1.0.0, @tanstack/ai-vercel-gateway 1.0.0, server-side chat() on Node 24
for await (const chunk of chat({
adapter: createVercelGatewayText('openai/gpt-4.1-nano', key), // Responses API by default
messages: [{ role: 'user', content: 'Count from 1 to 300, separated by commas.' }],
threadId: 'repro',
modelOptions: { max_output_tokens: 16 },
middleware: [{ name: 'probe', onUsage, onFinish, onError }],
})) {
if (chunk.type === 'RUN_FINISHED' || chunk.type === 'RUN_ERROR') console.log(chunk)
}
| Adapter | Terminal chunk | onUsage |
Terminal hook |
|---|---|---|---|
| Responses (default) | RUN_ERROR { message: 'max_output_tokens', code: 'incomplete' } |
not called | onError |
Chat Completions (api: 'chat', max_tokens: 16) |
RUN_FINISHED, usage 19 / 16 |
called once | onFinish, finishReason: 'length' |
On the Responses adapter the chunks arrive as RUN_STARTED, TEXT_MESSAGE_START, TEXT_MESSAGE_CONTENT (62 characters), TEXT_MESSAGE_END, RUN_ERROR. anthropic/claude-sonnet-5.5 gives the same RUN_ERROR. A direct POST https://ai-gateway.vercel.sh/v1/responses with stream: true and max_output_tokens: 16 ends like this for both models (gpt-4.1-nano shown):
{
"type": "response.incomplete",
"response": {
"status": "incomplete",
"incomplete_details": { "reason": "max_output_tokens" },
"usage": { "input_tokens": 19, "output_tokens": 16, "…": "…" }
}
}
The openai SDK types describe response.incomplete as "An event that is emitted when a response finishes as incomplete", with incomplete_details.reason one of max_output_tokens, max_messages, content_filter, steered.
Expected
response.incomplete with incomplete_details.reason max_output_tokens or content_filter ends the run the way the Chat Completions adapter does: RUN_FINISHED with the response's usage and finishReason: 'length' or 'content_filter'. response.failed, and an incomplete response without a known reason, stay RUN_ERROR.
Why
We stop our agent loop with untilFinishReason(['length']) and record usage per model call. On the Responses adapter, a capped answer shows the user an error after a partial answer, and its tokens are not recorded.
- Ngôn ngữ chính
- TypeScript
- Star
- 3.2k
- Fork
- 372
- Merge trung bình
- 1 ngày 14 giờ
- Pull request đã merge (30 ngày)
- 241
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của TanStack/ai
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 55/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 57/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Durable resume through withPersistence never fills ctx.inputResponse for mcp_input interruptsCó thể đã có người làm @tombeckenham đã nhận 4 ngày trước. Đang mởwaiting-on: maintainer
TanStack/ai#1885 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
ai, ai-persistence: a nested subagent that waits runs again from the start under withPersistenceCó thể đã có người làm @tombeckenham đã nhận 5 ngày trước. Đang mởwaiting-on: maintainer
TanStack/ai#1878 · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
Issue tương tự
-
Plugin: sheet music can't be scrolled by hand before playbackCó thể đã có người làm @snakajima đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
receptron/jinglescript#51 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
Maintainer thường phản hồi trong vòng 9 ngày
-
clawsweeper:needs-maintainer-review clawsweeper:needs-product-decision clawsweeper:no-new-fix-pr clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster P3
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
openclaw/openclaw#186424 · 1 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
chore(worker): five module header comments describe the code from before later issues changed itĐang mởarea:dev U2-later
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
bentleypark/aiwatch#1824 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Pal-AI-Lab/Coopanion#469 ·
Maintainer thường phản hồi trong vòng 1 ngày