返回 DeepSeek-Reasonix
stream_eof.go
根目录 / internal / provider / anthropic / stream_eof.go
1 package anthropic
2
3 import (
4 "fmt"
5 "io"
6 "time"
7
8 "reasonix/internal/provider"
9 )
10
11 // streamScanEndError classifies why the SSE scanner stopped. A clean close
12 // after message_delta.stop_reason is a complete terminal: compatible gateways
13 // often omit message_stop, the same way OpenAI-compatible gateways omit [DONE]
14 // after finish_reason. A clean close with no stop_reason stays uncommitted.
15 func streamScanEndError(name string, idleTimeout time.Duration, stalled bool, scanErr error, stopReason string) error {
16 if stalled {
17 err := fmt.Errorf("%s: stream stalled — no data for %s, connection likely dropped", name, idleTimeout)
18 return provider.StreamInterrupt(err, provider.StreamInterruptIdleTimeout)
19 }
20 if scanErr != nil {
21 wrapped := fmt.Errorf("%s: read stream: %w", name, scanErr)
22 if provider.IsConnReset(scanErr) {
23 return provider.StreamInterrupt(wrapped, provider.ClassifyStreamInterrupt(scanErr))
24 }
25 return wrapped
26 }
27 if stopReason != "" {
28 return nil
29 }
30 return provider.StreamInterrupt(
31 fmt.Errorf("%s: stream ended before message_stop: %w", name, io.ErrUnexpectedEOF),
32 provider.StreamInterruptPrematureEOF,
33 )
34 }
35
35 lines GO