chore: 初始化 eightbf-analysis-go(对齐 Java 会商作业服务)
Go 实现 /api/v1/analysis 契约、Demo/Live Worker、DeerFlow SSE;含设计文档与冒烟脚本。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
commit
0c45b86d67
29 files changed
+3789
No files matched your search
@@ -0,0 +1,72 @@
|
||||
package deerflow
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.gozeros.com/wsk/eightbf-analysis-go/internal/config"
|
||||
)
|
||||
|
||||
// Auth 向 DeerFlow 换 Bearer,过期前复用。
|
||||
type Auth struct {
|
||||
cfg config.Config
|
||||
mu sync.Mutex
|
||||
token string
|
||||
expiresAt time.Time
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
func NewAuth(cfg config.Config) *Auth {
|
||||
return &Auth{
|
||||
cfg: cfg,
|
||||
httpClient: &http.Client{Timeout: 30 * time.Second},
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Auth) BearerToken() (string, error) {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
now := time.Now()
|
||||
if a.token != "" && a.expiresAt.After(now.Add(2*time.Minute)) {
|
||||
return a.token, nil
|
||||
}
|
||||
body, _ := json.Marshal(map[string]string{
|
||||
"username": a.cfg.DeerFlowUser,
|
||||
"password": a.cfg.DeerFlowPassword,
|
||||
})
|
||||
req, err := http.NewRequest(http.MethodPost, a.cfg.DeerFlowBaseURL+"/api/v1/auth/login/username", bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
resp, err := a.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
raw, _ := io.ReadAll(resp.Body)
|
||||
if resp.StatusCode >= 400 {
|
||||
return "", fmt.Errorf("DeerFlow 登录失败 HTTP %d: %s", resp.StatusCode, string(raw))
|
||||
}
|
||||
var parsed struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
}
|
||||
if err := json.Unmarshal(raw, &parsed); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if parsed.AccessToken == "" {
|
||||
return "", fmt.Errorf("DeerFlow 登录响应无 access_token")
|
||||
}
|
||||
if parsed.ExpiresIn <= 0 {
|
||||
parsed.ExpiresIn = 3600
|
||||
}
|
||||
a.token = parsed.AccessToken
|
||||
a.expiresAt = now.Add(time.Duration(parsed.ExpiresIn) * time.Second)
|
||||
return a.token, nil
|
||||
}
|
||||
Reference in new issue
Block a user