87 lines
2.2 KiB
Go
87 lines
2.2 KiB
Go
package handlers
|
||
|
||
import (
|
||
"encoding/json"
|
||
"net/http"
|
||
"strings"
|
||
|
||
"trade/web/internal/store"
|
||
)
|
||
|
||
type llmConfigReq struct {
|
||
BaseURL string `json:"base_url"`
|
||
APIKey string `json:"api_key"`
|
||
Model string `json:"model"`
|
||
}
|
||
|
||
type llmConfigResp struct {
|
||
BaseURL string `json:"base_url"`
|
||
APIKey string `json:"api_key"` // 脱敏:仅显示首尾
|
||
Model string `json:"model"`
|
||
HasAPIKey bool `json:"has_api_key"` // 前端据此判断是否已配置
|
||
}
|
||
|
||
// maskKey 将 sk-abc123xyz 脱敏为 sk-a...xyz。
|
||
func maskKey(key string) string {
|
||
if len(key) <= 8 {
|
||
return strings.Repeat("*", len(key))
|
||
}
|
||
return key[:4] + "..." + key[len(key)-4:]
|
||
}
|
||
|
||
// GetLLMConfig 返回当前 LLM 配置(API Key 脱敏)。
|
||
func (d *Deps) GetLLMConfig(w http.ResponseWriter, r *http.Request) {
|
||
cfg, err := d.Futures.GetLLMConfig()
|
||
if err != nil {
|
||
writeErr(w, http.StatusInternalServerError, err.Error())
|
||
return
|
||
}
|
||
resp := llmConfigResp{
|
||
BaseURL: cfg.BaseURL,
|
||
Model: cfg.Model,
|
||
HasAPIKey: cfg.APIKey != "",
|
||
}
|
||
if cfg.APIKey != "" {
|
||
resp.APIKey = maskKey(cfg.APIKey)
|
||
}
|
||
writeJSON(w, http.StatusOK, resp)
|
||
}
|
||
|
||
// SaveLLMConfig 保存 LLM 配置。api_key 为脱敏占位时保留原值。
|
||
func (d *Deps) SaveLLMConfig(w http.ResponseWriter, r *http.Request) {
|
||
var req llmConfigReq
|
||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||
writeErr(w, http.StatusBadRequest, "invalid json")
|
||
return
|
||
}
|
||
req.BaseURL = strings.TrimSpace(req.BaseURL)
|
||
req.Model = strings.TrimSpace(req.Model)
|
||
if req.BaseURL == "" {
|
||
req.BaseURL = "https://api.deepseek.com/v1"
|
||
}
|
||
if req.Model == "" {
|
||
req.Model = "deepseek-chat"
|
||
}
|
||
|
||
// 如果前端传的是脱敏值(含 ...),说明未修改 Key,保留旧值
|
||
if strings.Contains(req.APIKey, "...") {
|
||
old, err := d.Futures.GetLLMConfig()
|
||
if err != nil {
|
||
writeErr(w, http.StatusInternalServerError, err.Error())
|
||
return
|
||
}
|
||
req.APIKey = old.APIKey
|
||
}
|
||
|
||
cfg := &store.LLMConfig{
|
||
BaseURL: req.BaseURL,
|
||
APIKey: req.APIKey,
|
||
Model: req.Model,
|
||
}
|
||
if err := d.Futures.SaveLLMConfig(cfg); err != nil {
|
||
writeErr(w, http.StatusInternalServerError, err.Error())
|
||
return
|
||
}
|
||
writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
|
||
}
|