返回 DeepSeek-Reasonix
provider_probe.go
根目录 / internal / boot / provider_probe.go
1 package boot
2
3 import (
4 "context"
5 "fmt"
6 "strings"
7 "time"
8
9 "reasonix/internal/config"
10 "reasonix/internal/netclient"
11 "reasonix/internal/provider"
12 )
13
14 const providerProbeTimeout = 20 * time.Second
15
16 // ProbeProviderConnection performs a request-local, tool-free chat probe. The
17 // supplied credential is frozen into entry and is never persisted or exported
18 // to the process environment.
19 func ProbeProviderConnection(ctx context.Context, entry config.ProviderEntry, key string, proxy netclient.ProxySpec) error {
20 if ctx == nil {
21 ctx = context.Background()
22 }
23 ctx, cancel := context.WithTimeout(ctx, providerProbeTimeout)
24 defer cancel()
25 if strings.TrimSpace(key) != "" {
26 entry = entry.WithAPIKeyForProbe(key)
27 }
28 client, err := NewProviderWithProxy(&entry, proxy)
29 if err != nil {
30 return err
31 }
32 chunks, err := client.Stream(ctx, provider.Request{
33 Messages: []provider.Message{{Role: provider.RoleUser, Content: "Reply with OK."}},
34 MaxTokens: 16,
35 })
36 if err != nil {
37 return err
38 }
39 for {
40 select {
41 case <-ctx.Done():
42 return ctx.Err()
43 case chunk, open := <-chunks:
44 if !open {
45 return fmt.Errorf("provider closed the connection without a response")
46 }
47 if chunk.Err != nil {
48 return chunk.Err
49 }
50 if chunk.Type == provider.ChunkText && strings.TrimSpace(chunk.Text) != "" {
51 return nil
52 }
53 if chunk.Type == provider.ChunkDone {
54 return nil
55 }
56 }
57 }
58 }
59
59 lines GO