package client import ( "bytes" "context" dsprotocol "ds2api/internal/deepseek/protocol" "encoding/json" "net/http" "ds2api/internal/auth" "ds2api/internal/config" trans "ds2api/internal/deepseek/transport" ) func (c *Client) CallCompletion(ctx context.Context, a *auth.RequestAuth, payload map[string]any, powResp string, maxAttempts int) (*http.Response, error) { _ = maxAttempts clients := c.requestClientsForAuth(ctx, a) headers := c.authHeaders(a.DeepSeekToken) headers["x-ds-pow-response"] = powResp captureSession := c.capture.Start("deepseek_completion", dsprotocol.DeepSeekCompletionURL, a.AccountID, payload) resp, err := c.streamPostOnce(ctx, clients.stream, dsprotocol.DeepSeekCompletionURL, headers, payload) if err != nil { return nil, err } if captureSession != nil { resp.Body = captureSession.WrapBody(resp.Body, resp.StatusCode) } if resp.StatusCode == http.StatusOK { resp = c.wrapCompletionWithAutoContinue(ctx, a, payload, powResp, resp) } return resp, nil } func (c *Client) streamPost(ctx context.Context, doer trans.Doer, url string, headers map[string]string, payload any) (*http.Response, error) { return c.streamPostWithFallback(ctx, doer, url, headers, payload, true) } func (c *Client) streamPostOnce(ctx context.Context, doer trans.Doer, url string, headers map[string]string, payload any) (*http.Response, error) { return c.streamPostWithFallback(ctx, doer, url, headers, payload, false) } func (c *Client) streamPostWithFallback(ctx context.Context, doer trans.Doer, url string, headers map[string]string, payload any, allowFallback bool) (*http.Response, error) { b, err := json.Marshal(payload) if err != nil { return nil, err } headers = c.jsonHeaders(headers) clients := c.requestClientsFromContext(ctx) req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(b)) if err != nil { return nil, err } for k, v := range headers { req.Header.Set(k, v) } resp, err := doer.Do(req) if err != nil { if allowFallback { config.Logger.Warn("[deepseek] fingerprint stream request failed, fallback to std transport", "url", url, "error", err) req2, reqErr := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(b)) if reqErr != nil { return nil, reqErr } for k, v := range headers { req2.Header.Set(k, v) } return clients.fallbackS.Do(req2) } return nil, err } return resp, nil }