package client import ( "context" "net/http" "sync" "time" "ds2api/internal/auth" "ds2api/internal/config" dsprotocol "ds2api/internal/deepseek/protocol" trans "ds2api/internal/deepseek/transport" "ds2api/internal/devcapture" "ds2api/internal/util" "ds2api/internal/deepseek/hif" ) // intFrom is a package-internal alias for the shared util version. var intFrom = util.IntFrom type Client struct { Store *config.Store Auth *auth.Resolver capture *devcapture.Store regular trans.Doer stream trans.Doer fallback *http.Client fallbackS *http.Client maxRetries int hifPoller *hif.HIFPoller proxyClientsMu sync.RWMutex proxyClients map[string]requestClients } func NewClient(store *config.Store, resolver *auth.Resolver) *Client { c := &Client{ Store: store, Auth: resolver, capture: devcapture.Global(), maxRetries: 3, proxyClients: map[string]requestClients{}, } platform := "android" if store != nil { platform = store.PlatformMode() } dsprotocol.ApplyPlatform(platform) snap := store.Snapshot() dsprotocol.ApplyVersionOverrides( snap.Platform.AndroidVersion, snap.Platform.WebVersion, snap.Platform.AndroidAPILevel, ) c.regular = trans.NewWithPlatform(60*time.Second, platform) c.stream = trans.NewWithPlatform(0, platform) c.fallback = trans.NewFallbackClientWithPlatform(60*time.Second, nil, platform) c.fallbackS = trans.NewFallbackClientWithPlatform(0, nil, platform) if platform == "web" { c.hifPoller = hif.NewHIFPoller() c.hifPoller.Start() } return c } // RefreshTransport recreates the transport clients based on the current platform mode. func (c *Client) RefreshTransport() { platform := c.Store.PlatformMode() c.regular = trans.NewWithPlatform(60*time.Second, platform) c.stream = trans.NewWithPlatform(0, platform) c.fallback = trans.NewFallbackClientWithPlatform(60*time.Second, nil, platform) c.fallbackS = trans.NewFallbackClientWithPlatform(0, nil, platform) c.proxyClientsMu.Lock() c.proxyClients = map[string]requestClients{} c.proxyClientsMu.Unlock() } // SetPlatform switches the client to the given platform ("android" or "web"), // updating protocol constants, transport clients, and the HIF poller. func (c *Client) SetPlatform(platform string) { dsprotocol.ApplyPlatform(platform) snap := c.Store.Snapshot() dsprotocol.ApplyVersionOverrides( snap.Platform.AndroidVersion, snap.Platform.WebVersion, snap.Platform.AndroidAPILevel, ) c.RefreshTransport() if platform == "web" && c.hifPoller == nil { c.hifPoller = hif.NewHIFPoller() c.hifPoller.Start() } else if platform != "web" && c.hifPoller != nil { c.hifPoller.Stop() c.hifPoller = nil } } // getHIFHeaders returns the current HIF headers from the poller, if active. func (c *Client) getHIFHeaders() map[string]string { if c.hifPoller == nil { return nil } return c.hifPoller.GetHeaders() } // PreloadPow 保留兼容接口,纯 Go 实现无需预加载。 func (c *Client) PreloadPow(_ context.Context) error { return nil }