Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

openai-base: a Responses max_output_tokens cutoff ends as RUN_ERROR without usage instead of finishReason 'length'

Đang mở Phù hợp với người mới
#1,916 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

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:

https://github.com/TanStack/ai/blob/ae976552710726b13b524c307c1b5bbe78478eb0/packages/openai-base/src/adapters/responses-text.ts#L1748-L1806

So with the Responses adapter:

  • the run ends in onError, not onFinish, right after the partial text the user has already seen;
  • onUsage never fires, although the provider billed the tokens;
  • finishReason: 'length' never appears, so untilFinishReason(['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:

https://github.com/TanStack/ai/blob/ae976552710726b13b524c307c1b5bbe78478eb0/packages/openai-base/src/adapters/responses-text.ts#L2442-L2473

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

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. 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.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của TanStack/ai

Tất cả issue của TanStack/ai

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.