fix(t126): 萃取引擎/金鑰改每帳號一份——多帳號不再互相覆蓋
leo:「2 個 CF 帳號一個填 gemma4 一個填 Mistral,daemon 會用誰的?別人也加就會有一樣的疑問」 實證:金鑰只有機器層一份 ⇒ 後連的覆蓋前一個。 修:AccountConfig 加 Extractor/GeminiAPIKey/LLMModel;帳號層優先、空值繼承機器層; 既有 config 遷移(頂層金鑰複製到各帳號,冪等);連線只寫該帳號不覆蓋機器層; 托盤帳號標題顯示「· Gemini」/「· Claude」(一眼看出誰用誰)。 三模組 go test 全綠(總管親跑)。(實作=子 CC;驗證+commit=總管)
This commit is contained in:
+101
-14
@@ -468,20 +468,10 @@ func TestAddOrUpdateAccountPreservesMachineLayer(t *testing.T) {
|
||||
LLMModel: "gemma-4-31b-it",
|
||||
CardIngestWF: "rag_ingest_card",
|
||||
}
|
||||
resp := &daemonConfigResp{
|
||||
Success: true,
|
||||
Config: struct {
|
||||
CypherURL string `json:"cypher_url"`
|
||||
Namespace string `json:"namespace"`
|
||||
Library string `json:"library"`
|
||||
Extractor string `json:"extractor"`
|
||||
Email string `json:"email"`
|
||||
InstanceName string `json:"instance_name"`
|
||||
}{
|
||||
CypherURL: "https://new.workers.dev",
|
||||
Namespace: "newns",
|
||||
},
|
||||
}
|
||||
resp := &daemonConfigResp{Success: true}
|
||||
resp.Config.CypherURL = "https://new.workers.dev"
|
||||
resp.Config.Namespace = "newns"
|
||||
|
||||
addOrUpdateAccount(cfg, resp)
|
||||
if cfg.GeminiAPIKey != "AIzaSy-existing-key" {
|
||||
t.Errorf("GeminiAPIKey 被清空:got %q", cfg.GeminiAPIKey)
|
||||
@@ -493,3 +483,100 @@ func TestAddOrUpdateAccountPreservesMachineLayer(t *testing.T) {
|
||||
t.Errorf("CardIngestWF 被清空:got %q", cfg.CardIngestWF)
|
||||
}
|
||||
}
|
||||
|
||||
// ── t126:每帳號獨立引擎設定 ──────────────────────────────────────────────────
|
||||
|
||||
// t126①:accountEngineLabel 依帳號或 defaultExtractor 顯示引擎名(帳號層優先)。
|
||||
func TestAccountEngineLabel(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
acc accountCfg
|
||||
defaultEx string
|
||||
want string
|
||||
}{
|
||||
{"帳號有gemma", accountCfg{Extractor: "gemma"}, "", " · Gemini"},
|
||||
{"帳號有claude", accountCfg{Extractor: "claude"}, "", " · Claude"},
|
||||
{"帳號空退回default-gemma", accountCfg{}, "gemma", " · Gemini"},
|
||||
{"帳號空退回default-claude", accountCfg{}, "claude", " · Claude"},
|
||||
{"兩者皆空無標籤", accountCfg{}, "", ""},
|
||||
{"帳號層優先於default", accountCfg{Extractor: "gemma"}, "claude", " · Gemini"},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
got := accountEngineLabel(c.acc, c.defaultEx)
|
||||
if got != c.want {
|
||||
t.Errorf("accountEngineLabel(%+v, %q) = %q, want %q", c.acc, c.defaultEx, got, c.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// t126②:addOrUpdateAccount 把 extractor/key 寫進帳號層,機器層不被覆蓋。
|
||||
func TestAddOrUpdateAccount_WritesExtractorToAccountLayer(t *testing.T) {
|
||||
cfg := &directConfig{
|
||||
Extractor: "claude", // 機器層原有值
|
||||
GeminiAPIKey: "machine-key", // 機器層原有值
|
||||
}
|
||||
resp := &daemonConfigResp{Success: true}
|
||||
resp.Config.CypherURL = "https://new.workers.dev"
|
||||
resp.Config.Namespace = "ns1"
|
||||
resp.Config.Extractor = "gemma"
|
||||
resp.Config.GeminiAPIKey = "account-key"
|
||||
resp.Config.LLMModel = "gemma-4-31b-it"
|
||||
|
||||
isNew := addOrUpdateAccount(cfg, resp)
|
||||
if !isNew {
|
||||
t.Error("應為新帳號")
|
||||
}
|
||||
if len(cfg.Accounts) == 0 {
|
||||
t.Fatal("應新增帳號")
|
||||
}
|
||||
// 帳號層應有新值
|
||||
if cfg.Accounts[0].Extractor != "gemma" {
|
||||
t.Errorf("帳號層 Extractor 錯:got %q", cfg.Accounts[0].Extractor)
|
||||
}
|
||||
if cfg.Accounts[0].GeminiAPIKey != "account-key" {
|
||||
t.Errorf("帳號層 GeminiAPIKey 錯:got %q", cfg.Accounts[0].GeminiAPIKey)
|
||||
}
|
||||
if cfg.Accounts[0].LLMModel != "gemma-4-31b-it" {
|
||||
t.Errorf("帳號層 LLMModel 錯:got %q", cfg.Accounts[0].LLMModel)
|
||||
}
|
||||
// 機器層不應被覆蓋
|
||||
if cfg.Extractor != "claude" {
|
||||
t.Errorf("機器層 Extractor 不應被覆蓋,got %q", cfg.Extractor)
|
||||
}
|
||||
if cfg.GeminiAPIKey != "machine-key" {
|
||||
t.Errorf("機器層 GeminiAPIKey 不應被覆蓋,got %q", cfg.GeminiAPIKey)
|
||||
}
|
||||
}
|
||||
|
||||
// t126③:同 host 更新帳號時 extractor 也寫帳號層。
|
||||
func TestAddOrUpdateAccount_UpdateWritesExtractorToAccountLayer(t *testing.T) {
|
||||
cfg := &directConfig{
|
||||
Extractor: "claude", // 機器層
|
||||
Accounts: []accountCfg{{
|
||||
CypherURL: "https://inst.workers.dev",
|
||||
Namespace: "ns1",
|
||||
}},
|
||||
}
|
||||
resp := &daemonConfigResp{Success: true}
|
||||
resp.Config.CypherURL = "https://inst.workers.dev"
|
||||
resp.Config.Namespace = "ns1"
|
||||
resp.Config.Extractor = "gemma"
|
||||
resp.Config.GeminiAPIKey = "per-account-key"
|
||||
|
||||
isNew := addOrUpdateAccount(cfg, resp)
|
||||
if isNew {
|
||||
t.Error("同 host 應為更新(回 false)")
|
||||
}
|
||||
if cfg.Accounts[0].Extractor != "gemma" {
|
||||
t.Errorf("帳號層 Extractor 應更新,got %q", cfg.Accounts[0].Extractor)
|
||||
}
|
||||
if cfg.Accounts[0].GeminiAPIKey != "per-account-key" {
|
||||
t.Errorf("帳號層 GeminiAPIKey 應更新,got %q", cfg.Accounts[0].GeminiAPIKey)
|
||||
}
|
||||
// 機器層不變
|
||||
if cfg.Extractor != "claude" {
|
||||
t.Errorf("機器層 Extractor 不應被覆蓋,got %q", cfg.Extractor)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user