mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
refactor: seperate security.yml for store keys
This commit is contained in:
@@ -430,7 +430,7 @@ func (s *appState) isActiveModelValid() bool {
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
hasKey := strings.TrimSpace(cfg.APIKey) != "" || strings.TrimSpace(cfg.AuthMethod) == "oauth"
|
||||
hasKey := strings.TrimSpace(cfg.APIKey()) != "" || strings.TrimSpace(cfg.AuthMethod) == "oauth"
|
||||
hasModel := strings.TrimSpace(cfg.Model) != ""
|
||||
return hasKey && hasModel
|
||||
}
|
||||
|
||||
@@ -112,8 +112,8 @@ func refreshChannelMenuFromState(menu *Menu, s *appState) {
|
||||
func (s *appState) telegramForm() tview.Primitive {
|
||||
cfg := &s.config.Channels.Telegram
|
||||
form := baseChannelForm("Telegram", cfg.Enabled, s.makeChannelOnEnabled(&cfg.Enabled))
|
||||
form.AddInputField("Token", cfg.Token, 128, nil, func(text string) {
|
||||
cfg.Token = strings.TrimSpace(text)
|
||||
form.AddInputField("Token", cfg.Token(), 128, nil, func(text string) {
|
||||
cfg.SetToken(strings.TrimSpace(text))
|
||||
})
|
||||
form.AddInputField("Proxy", cfg.Proxy, 128, nil, func(text string) {
|
||||
cfg.Proxy = strings.TrimSpace(text)
|
||||
@@ -125,8 +125,8 @@ func (s *appState) telegramForm() tview.Primitive {
|
||||
func (s *appState) discordForm() tview.Primitive {
|
||||
cfg := &s.config.Channels.Discord
|
||||
form := baseChannelForm("Discord", cfg.Enabled, s.makeChannelOnEnabled(&cfg.Enabled))
|
||||
form.AddInputField("Token", cfg.Token, 128, nil, func(text string) {
|
||||
cfg.Token = strings.TrimSpace(text)
|
||||
form.AddInputField("Token", cfg.Token(), 128, nil, func(text string) {
|
||||
cfg.SetToken(strings.TrimSpace(text))
|
||||
})
|
||||
form.AddCheckbox("Mention Only", cfg.MentionOnly, func(checked bool) {
|
||||
cfg.MentionOnly = checked
|
||||
@@ -141,8 +141,8 @@ func (s *appState) qqForm() tview.Primitive {
|
||||
form.AddInputField("App ID", cfg.AppID, 64, nil, func(text string) {
|
||||
cfg.AppID = strings.TrimSpace(text)
|
||||
})
|
||||
form.AddInputField("App Secret", cfg.AppSecret, 128, nil, func(text string) {
|
||||
cfg.AppSecret = strings.TrimSpace(text)
|
||||
form.AddInputField("App Secret", cfg.AppSecret(), 128, nil, func(text string) {
|
||||
cfg.SetAppSecret(strings.TrimSpace(text))
|
||||
})
|
||||
addAllowFromField(form, &cfg.AllowFrom)
|
||||
return wrapWithBack(form, s)
|
||||
@@ -175,14 +175,14 @@ func (s *appState) feishuForm() tview.Primitive {
|
||||
form.AddInputField("App ID", cfg.AppID, 64, nil, func(text string) {
|
||||
cfg.AppID = strings.TrimSpace(text)
|
||||
})
|
||||
form.AddInputField("App Secret", cfg.AppSecret, 128, nil, func(text string) {
|
||||
cfg.AppSecret = strings.TrimSpace(text)
|
||||
form.AddInputField("App Secret", cfg.AppSecret(), 128, nil, func(text string) {
|
||||
cfg.SetAppSecret(strings.TrimSpace(text))
|
||||
})
|
||||
form.AddInputField("Encrypt Key", cfg.EncryptKey, 128, nil, func(text string) {
|
||||
cfg.EncryptKey = strings.TrimSpace(text)
|
||||
form.AddInputField("Encrypt Key", cfg.EncryptKey(), 128, nil, func(text string) {
|
||||
cfg.SetEncryptKey(strings.TrimSpace(text))
|
||||
})
|
||||
form.AddInputField("Verification Token", cfg.VerificationToken, 128, nil, func(text string) {
|
||||
cfg.VerificationToken = strings.TrimSpace(text)
|
||||
form.AddInputField("Verification Token", cfg.VerificationToken(), 128, nil, func(text string) {
|
||||
cfg.SetVerificationToken(strings.TrimSpace(text))
|
||||
})
|
||||
addAllowFromField(form, &cfg.AllowFrom)
|
||||
return wrapWithBack(form, s)
|
||||
@@ -194,8 +194,8 @@ func (s *appState) dingtalkForm() tview.Primitive {
|
||||
form.AddInputField("Client ID", cfg.ClientID, 64, nil, func(text string) {
|
||||
cfg.ClientID = strings.TrimSpace(text)
|
||||
})
|
||||
form.AddInputField("Client Secret", cfg.ClientSecret, 128, nil, func(text string) {
|
||||
cfg.ClientSecret = strings.TrimSpace(text)
|
||||
form.AddInputField("Client Secret", cfg.ClientSecret(), 128, nil, func(text string) {
|
||||
cfg.SetClientSecret(strings.TrimSpace(text))
|
||||
})
|
||||
addAllowFromField(form, &cfg.AllowFrom)
|
||||
return wrapWithBack(form, s)
|
||||
@@ -204,11 +204,11 @@ func (s *appState) dingtalkForm() tview.Primitive {
|
||||
func (s *appState) slackForm() tview.Primitive {
|
||||
cfg := &s.config.Channels.Slack
|
||||
form := baseChannelForm("Slack", cfg.Enabled, s.makeChannelOnEnabled(&cfg.Enabled))
|
||||
form.AddInputField("Bot Token", cfg.BotToken, 128, nil, func(text string) {
|
||||
cfg.BotToken = strings.TrimSpace(text)
|
||||
form.AddInputField("Bot Token", cfg.BotToken(), 128, nil, func(text string) {
|
||||
cfg.SetBotToken(strings.TrimSpace(text))
|
||||
})
|
||||
form.AddInputField("App Token", cfg.AppToken, 128, nil, func(text string) {
|
||||
cfg.AppToken = strings.TrimSpace(text)
|
||||
form.AddInputField("App Token", cfg.AppToken(), 128, nil, func(text string) {
|
||||
cfg.SetAppToken(strings.TrimSpace(text))
|
||||
})
|
||||
addAllowFromField(form, &cfg.AllowFrom)
|
||||
return wrapWithBack(form, s)
|
||||
@@ -217,11 +217,11 @@ func (s *appState) slackForm() tview.Primitive {
|
||||
func (s *appState) lineForm() tview.Primitive {
|
||||
cfg := &s.config.Channels.LINE
|
||||
form := baseChannelForm("LINE", cfg.Enabled, s.makeChannelOnEnabled(&cfg.Enabled))
|
||||
form.AddInputField("Channel Secret", cfg.ChannelSecret, 128, nil, func(text string) {
|
||||
cfg.ChannelSecret = strings.TrimSpace(text)
|
||||
form.AddInputField("Channel Secret", cfg.ChannelSecret(), 128, nil, func(text string) {
|
||||
cfg.SetChannelSecret(strings.TrimSpace(text))
|
||||
})
|
||||
form.AddInputField("Channel Access Token", cfg.ChannelAccessToken, 128, nil, func(text string) {
|
||||
cfg.ChannelAccessToken = strings.TrimSpace(text)
|
||||
form.AddInputField("Channel Access Token", cfg.ChannelAccessToken(), 128, nil, func(text string) {
|
||||
cfg.SetChannelAccessToken(strings.TrimSpace(text))
|
||||
})
|
||||
form.AddInputField("Webhook Host", cfg.WebhookHost, 64, nil, func(text string) {
|
||||
cfg.WebhookHost = strings.TrimSpace(text)
|
||||
@@ -243,8 +243,8 @@ func (s *appState) matrixForm() tview.Primitive {
|
||||
form.AddInputField("User ID", cfg.UserID, 128, nil, func(text string) {
|
||||
cfg.UserID = strings.TrimSpace(text)
|
||||
})
|
||||
form.AddInputField("Access Token", cfg.AccessToken, 128, nil, func(text string) {
|
||||
cfg.AccessToken = strings.TrimSpace(text)
|
||||
form.AddInputField("Access Token", cfg.AccessToken(), 128, nil, func(text string) {
|
||||
cfg.SetAccessToken(strings.TrimSpace(text))
|
||||
})
|
||||
form.AddInputField("Device ID", cfg.DeviceID, 128, nil, func(text string) {
|
||||
cfg.DeviceID = strings.TrimSpace(text)
|
||||
@@ -262,8 +262,8 @@ func (s *appState) onebotForm() tview.Primitive {
|
||||
form.AddInputField("WS URL", cfg.WSUrl, 128, nil, func(text string) {
|
||||
cfg.WSUrl = strings.TrimSpace(text)
|
||||
})
|
||||
form.AddInputField("Access Token", cfg.AccessToken, 128, nil, func(text string) {
|
||||
cfg.AccessToken = strings.TrimSpace(text)
|
||||
form.AddInputField("Access Token", cfg.AccessToken(), 128, nil, func(text string) {
|
||||
cfg.SetAccessToken(strings.TrimSpace(text))
|
||||
})
|
||||
addIntField(
|
||||
form,
|
||||
@@ -287,11 +287,11 @@ func (s *appState) onebotForm() tview.Primitive {
|
||||
func (s *appState) wecomForm() tview.Primitive {
|
||||
cfg := &s.config.Channels.WeCom
|
||||
form := baseChannelForm("WeCom", cfg.Enabled, s.makeChannelOnEnabled(&cfg.Enabled))
|
||||
form.AddInputField("Token", cfg.Token, 128, nil, func(text string) {
|
||||
cfg.Token = strings.TrimSpace(text)
|
||||
form.AddInputField("Token", cfg.Token(), 128, nil, func(text string) {
|
||||
cfg.SetToken(strings.TrimSpace(text))
|
||||
})
|
||||
form.AddInputField("Encoding AES Key", cfg.EncodingAESKey, 128, nil, func(text string) {
|
||||
cfg.EncodingAESKey = strings.TrimSpace(text)
|
||||
form.AddInputField("Encoding AES Key", cfg.EncodingAESKey(), 128, nil, func(text string) {
|
||||
cfg.SetEncodingAESKey(strings.TrimSpace(text))
|
||||
})
|
||||
form.AddInputField("Webhook URL", cfg.WebhookURL, 128, nil, func(text string) {
|
||||
cfg.WebhookURL = strings.TrimSpace(text)
|
||||
@@ -319,15 +319,15 @@ func (s *appState) wecomAppForm() tview.Primitive {
|
||||
form.AddInputField("Corp ID", cfg.CorpID, 64, nil, func(text string) {
|
||||
cfg.CorpID = strings.TrimSpace(text)
|
||||
})
|
||||
form.AddInputField("Corp Secret", cfg.CorpSecret, 128, nil, func(text string) {
|
||||
cfg.CorpSecret = strings.TrimSpace(text)
|
||||
form.AddInputField("Corp Secret", cfg.CorpSecret(), 128, nil, func(text string) {
|
||||
cfg.SetCorpSecret(strings.TrimSpace(text))
|
||||
})
|
||||
addInt64Field(form, "Agent ID", cfg.AgentID, func(value int64) { cfg.AgentID = value })
|
||||
form.AddInputField("Token", cfg.Token, 128, nil, func(text string) {
|
||||
cfg.Token = strings.TrimSpace(text)
|
||||
form.AddInputField("Token", cfg.Token(), 128, nil, func(text string) {
|
||||
cfg.SetToken(strings.TrimSpace(text))
|
||||
})
|
||||
form.AddInputField("Encoding AES Key", cfg.EncodingAESKey, 128, nil, func(text string) {
|
||||
cfg.EncodingAESKey = strings.TrimSpace(text)
|
||||
form.AddInputField("Encoding AES Key", cfg.EncodingAESKey(), 128, nil, func(text string) {
|
||||
cfg.SetEncodingAESKey(strings.TrimSpace(text))
|
||||
})
|
||||
form.AddInputField("Webhook Host", cfg.WebhookHost, 64, nil, func(text string) {
|
||||
cfg.WebhookHost = strings.TrimSpace(text)
|
||||
|
||||
@@ -49,7 +49,7 @@ func (s *appState) modelMenu() tview.Primitive {
|
||||
Action: func() {
|
||||
newName := s.nextAvailableModelName("new-model")
|
||||
s.addModel(
|
||||
picoclawconfig.ModelConfig{ModelName: newName, Model: "openai/gpt-5.4"},
|
||||
&picoclawconfig.ModelConfig{ModelName: newName, Model: "openai/gpt-5.4"},
|
||||
)
|
||||
s.push(
|
||||
fmt.Sprintf("model-%d", len(s.config.ModelList)-1),
|
||||
@@ -90,7 +90,7 @@ func (s *appState) modelMenu() tview.Primitive {
|
||||
}
|
||||
|
||||
func (s *appState) modelForm(index int) tview.Primitive {
|
||||
model := &s.config.ModelList[index]
|
||||
model := s.config.ModelList[index]
|
||||
form := tview.NewForm()
|
||||
form.SetBorder(true).SetTitle(fmt.Sprintf("Model: %s", model.ModelName))
|
||||
|
||||
@@ -131,8 +131,8 @@ func (s *appState) modelForm(index int) tview.Primitive {
|
||||
refreshModelMenuFromState(menu, s)
|
||||
}
|
||||
})
|
||||
addInput(form, "API Key", model.APIKey, func(value string) {
|
||||
model.APIKey = value
|
||||
addInput(form, "API Key", model.APIKey(), func(value string) {
|
||||
model.SetAPIKey(value)
|
||||
s.dirty = true
|
||||
refreshMainMenuIfPresent(s)
|
||||
if menu, ok := s.menus["model"]; ok {
|
||||
@@ -215,7 +215,7 @@ func addIntInput(form *tview.Form, label string, value int, onChange func(int))
|
||||
})
|
||||
}
|
||||
|
||||
func (s *appState) addModel(model picoclawconfig.ModelConfig) {
|
||||
func (s *appState) addModel(model *picoclawconfig.ModelConfig) {
|
||||
s.config.ModelList = append(s.config.ModelList, model)
|
||||
}
|
||||
|
||||
@@ -236,7 +236,7 @@ func modelStatusColor(valid bool, selected bool) *tcell.Color {
|
||||
return &color
|
||||
}
|
||||
|
||||
func refreshModelMenu(menu *Menu, currentModel string, models []picoclawconfig.ModelConfig) {
|
||||
func refreshModelMenu(menu *Menu, currentModel string, models []*picoclawconfig.ModelConfig) {
|
||||
for i, model := range models {
|
||||
row := i
|
||||
label := fmt.Sprintf("%s (%s)", model.ModelName, model.Model)
|
||||
@@ -291,7 +291,7 @@ func refreshModelMenuFromState(menu *Menu, s *appState) {
|
||||
Action: func() {
|
||||
newName := s.nextAvailableModelName("new-model")
|
||||
s.addModel(
|
||||
picoclawconfig.ModelConfig{ModelName: newName, Model: "openai/gpt-5.4"},
|
||||
&picoclawconfig.ModelConfig{ModelName: newName, Model: "openai/gpt-5.4"},
|
||||
)
|
||||
s.push(fmt.Sprintf("model-%d", len(s.config.ModelList)-1), s.modelForm(len(s.config.ModelList)-1))
|
||||
},
|
||||
@@ -300,8 +300,8 @@ func refreshModelMenuFromState(menu *Menu, s *appState) {
|
||||
menu.applyItems(items)
|
||||
}
|
||||
|
||||
func isModelValid(model picoclawconfig.ModelConfig) bool {
|
||||
hasKey := strings.TrimSpace(model.APIKey) != "" ||
|
||||
func isModelValid(model *picoclawconfig.ModelConfig) bool {
|
||||
hasKey := strings.TrimSpace(model.APIKey()) != "" ||
|
||||
strings.TrimSpace(model.AuthMethod) == "oauth"
|
||||
hasModel := strings.TrimSpace(model.Model) != ""
|
||||
return hasKey && hasModel
|
||||
@@ -343,7 +343,7 @@ func (s *appState) testModel(model *picoclawconfig.ModelConfig) {
|
||||
if model == nil {
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(model.APIKey) == "" {
|
||||
if strings.TrimSpace(model.APIKey()) == "" {
|
||||
s.showMessage("Missing API Key", "Set api_key before testing")
|
||||
return
|
||||
}
|
||||
@@ -375,7 +375,7 @@ func (s *appState) testModel(model *picoclawconfig.ModelConfig) {
|
||||
return
|
||||
}
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
request.Header.Set("Authorization", "Bearer "+strings.TrimSpace(model.APIKey))
|
||||
request.Header.Set("Authorization", "Bearer "+strings.TrimSpace(model.APIKey()))
|
||||
|
||||
resp, err := client.Do(request)
|
||||
if err != nil {
|
||||
|
||||
@@ -68,7 +68,7 @@ func authLoginOpenAI(useDeviceCode bool) error {
|
||||
|
||||
// If no openai in ModelList, add it
|
||||
if !foundOpenAI {
|
||||
appCfg.ModelList = append(appCfg.ModelList, config.ModelConfig{
|
||||
appCfg.ModelList = append(appCfg.ModelList, &config.ModelConfig{
|
||||
ModelName: "gpt-5.4",
|
||||
Model: "openai/gpt-5.4",
|
||||
AuthMethod: "oauth",
|
||||
@@ -139,7 +139,7 @@ func authLoginGoogleAntigravity() error {
|
||||
|
||||
// If no antigravity in ModelList, add it
|
||||
if !foundAntigravity {
|
||||
appCfg.ModelList = append(appCfg.ModelList, config.ModelConfig{
|
||||
appCfg.ModelList = append(appCfg.ModelList, &config.ModelConfig{
|
||||
ModelName: "gemini-flash",
|
||||
Model: "antigravity/gemini-3-flash",
|
||||
AuthMethod: "oauth",
|
||||
@@ -213,7 +213,7 @@ func authLoginAnthropicSetupToken() error {
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
appCfg.ModelList = append(appCfg.ModelList, config.ModelConfig{
|
||||
appCfg.ModelList = append(appCfg.ModelList, &config.ModelConfig{
|
||||
ModelName: defaultAnthropicModel,
|
||||
Model: "anthropic/" + defaultAnthropicModel,
|
||||
AuthMethod: "oauth",
|
||||
@@ -289,7 +289,7 @@ func authLoginPasteToken(provider string) error {
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
appCfg.ModelList = append(appCfg.ModelList, config.ModelConfig{
|
||||
appCfg.ModelList = append(appCfg.ModelList, &config.ModelConfig{
|
||||
ModelName: defaultAnthropicModel,
|
||||
Model: "anthropic/" + defaultAnthropicModel,
|
||||
AuthMethod: "token",
|
||||
@@ -307,7 +307,7 @@ func authLoginPasteToken(provider string) error {
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
appCfg.ModelList = append(appCfg.ModelList, config.ModelConfig{
|
||||
appCfg.ModelList = append(appCfg.ModelList, &config.ModelConfig{
|
||||
ModelName: "gpt-5.4",
|
||||
Model: "openai/gpt-5.4",
|
||||
AuthMethod: "token",
|
||||
|
||||
@@ -81,7 +81,7 @@ func listAvailableModels(cfg *config.Config) {
|
||||
if model.ModelName == defaultModel {
|
||||
marker = "> "
|
||||
}
|
||||
if model.APIKey == "" {
|
||||
if model.APIKey() == "" {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("%s- %s (%s)\n", marker, model.ModelName, model.Model)
|
||||
@@ -92,7 +92,7 @@ func setDefaultModel(configPath string, cfg *config.Config, modelName string) er
|
||||
// Validate that the model exists in model_list
|
||||
modelFound := false
|
||||
for _, model := range cfg.ModelList {
|
||||
if model.APIKey != "" && model.ModelName == modelName {
|
||||
if model.APIKey() != "" && model.ModelName == modelName {
|
||||
modelFound = true
|
||||
break
|
||||
}
|
||||
|
||||
@@ -58,17 +58,24 @@ func TestNewModelCommand(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestShowCurrentModel_WithDefaultModel(t *testing.T) {
|
||||
cfg := &config.Config{
|
||||
cfg := (&config.Config{
|
||||
Agents: config.AgentsConfig{
|
||||
Defaults: config.AgentDefaults{
|
||||
ModelName: "gpt-4",
|
||||
},
|
||||
},
|
||||
ModelList: []config.ModelConfig{
|
||||
{ModelName: "gpt-4", Model: "openai/gpt-4", APIKey: "test"},
|
||||
{ModelName: "claude-3", Model: "anthropic/claude-3", APIKey: "test"},
|
||||
ModelList: []*config.ModelConfig{
|
||||
{ModelName: "gpt-4", Model: "openai/gpt-4"},
|
||||
{ModelName: "claude-3", Model: "anthropic/claude-3"},
|
||||
},
|
||||
}
|
||||
}).WithSecurity(&config.SecurityConfig{ModelList: map[string]config.ModelSecurityEntry{
|
||||
"gpt-4": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
"claude-3": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
}})
|
||||
|
||||
output := captureStdout(func() {
|
||||
showCurrentModel(cfg)
|
||||
@@ -81,16 +88,20 @@ func TestShowCurrentModel_WithDefaultModel(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestShowCurrentModel_NoDefaultModel(t *testing.T) {
|
||||
cfg := &config.Config{
|
||||
cfg := (&config.Config{
|
||||
Agents: config.AgentsConfig{
|
||||
Defaults: config.AgentDefaults{
|
||||
ModelName: "",
|
||||
},
|
||||
},
|
||||
ModelList: []config.ModelConfig{
|
||||
{ModelName: "gpt-4", Model: "openai/gpt-4", APIKey: "test"},
|
||||
ModelList: []*config.ModelConfig{
|
||||
{ModelName: "gpt-4", Model: "openai/gpt-4"},
|
||||
},
|
||||
}
|
||||
}).WithSecurity(&config.SecurityConfig{ModelList: map[string]config.ModelSecurityEntry{
|
||||
"gpt-4": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
}})
|
||||
|
||||
output := captureStdout(func() {
|
||||
showCurrentModel(cfg)
|
||||
@@ -102,7 +113,7 @@ func TestShowCurrentModel_NoDefaultModel(t *testing.T) {
|
||||
|
||||
func TestListAvailableModels_Empty(t *testing.T) {
|
||||
cfg := &config.Config{
|
||||
ModelList: []config.ModelConfig{},
|
||||
ModelList: []*config.ModelConfig{},
|
||||
}
|
||||
|
||||
output := captureStdout(func() {
|
||||
@@ -113,18 +124,25 @@ func TestListAvailableModels_Empty(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestListAvailableModels_WithModels(t *testing.T) {
|
||||
cfg := &config.Config{
|
||||
cfg := (&config.Config{
|
||||
Agents: config.AgentsConfig{
|
||||
Defaults: config.AgentDefaults{
|
||||
ModelName: "gpt-4",
|
||||
},
|
||||
},
|
||||
ModelList: []config.ModelConfig{
|
||||
{ModelName: "gpt-4", Model: "openai/gpt-4", APIKey: "test"},
|
||||
{ModelName: "claude-3", Model: "anthropic/claude-3", APIKey: "test"},
|
||||
{ModelName: "no-key-model", Model: "openai/test", APIKey: ""},
|
||||
ModelList: []*config.ModelConfig{
|
||||
{ModelName: "gpt-4", Model: "openai/gpt-4"},
|
||||
{ModelName: "claude-3", Model: "anthropic/claude-3"},
|
||||
{ModelName: "no-key-model", Model: "openai/test"},
|
||||
},
|
||||
}
|
||||
}).WithSecurity(&config.SecurityConfig{ModelList: map[string]config.ModelSecurityEntry{
|
||||
"gpt-4": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
"claude-3": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
}})
|
||||
|
||||
output := captureStdout(func() {
|
||||
listAvailableModels(cfg)
|
||||
@@ -139,17 +157,24 @@ func TestListAvailableModels_WithModels(t *testing.T) {
|
||||
func TestSetDefaultModel_ValidModel(t *testing.T) {
|
||||
initTest(t)
|
||||
|
||||
cfg := &config.Config{
|
||||
cfg := (&config.Config{
|
||||
Agents: config.AgentsConfig{
|
||||
Defaults: config.AgentDefaults{
|
||||
ModelName: "old-model",
|
||||
},
|
||||
},
|
||||
ModelList: []config.ModelConfig{
|
||||
{ModelName: "new-model", Model: "openai/new-model", APIKey: "test"},
|
||||
{ModelName: "old-model", Model: "openai/old-model", APIKey: "test"},
|
||||
ModelList: []*config.ModelConfig{
|
||||
{ModelName: "new-model", Model: "openai/new-model"},
|
||||
{ModelName: "old-model", Model: "openai/old-model"},
|
||||
},
|
||||
}
|
||||
}).WithSecurity(&config.SecurityConfig{ModelList: map[string]config.ModelSecurityEntry{
|
||||
"new-model": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
"old-model": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
}})
|
||||
|
||||
output := captureStdout(func() {
|
||||
err := setDefaultModel(configPath, cfg, "new-model")
|
||||
@@ -167,16 +192,20 @@ func TestSetDefaultModel_ValidModel(t *testing.T) {
|
||||
func TestSetDefaultModel_InvalidModel(t *testing.T) {
|
||||
initTest(t)
|
||||
|
||||
cfg := &config.Config{
|
||||
cfg := (&config.Config{
|
||||
Agents: config.AgentsConfig{
|
||||
Defaults: config.AgentDefaults{
|
||||
ModelName: "existing-model",
|
||||
},
|
||||
},
|
||||
ModelList: []config.ModelConfig{
|
||||
{ModelName: "existing-model", Model: "openai/existing", APIKey: "test"},
|
||||
ModelList: []*config.ModelConfig{
|
||||
{ModelName: "existing-model", Model: "openai/existing"},
|
||||
},
|
||||
}
|
||||
}).WithSecurity(&config.SecurityConfig{ModelList: map[string]config.ModelSecurityEntry{
|
||||
"existing-model": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
}})
|
||||
|
||||
assert.Error(t, setDefaultModel(configPath, cfg, "nonexistent-model"))
|
||||
}
|
||||
@@ -184,17 +213,24 @@ func TestSetDefaultModel_InvalidModel(t *testing.T) {
|
||||
func TestSetDefaultModel_ModelWithoutAPIKey(t *testing.T) {
|
||||
initTest(t)
|
||||
|
||||
cfg := &config.Config{
|
||||
cfg := (&config.Config{
|
||||
Agents: config.AgentsConfig{
|
||||
Defaults: config.AgentDefaults{
|
||||
ModelName: "existing-model",
|
||||
},
|
||||
},
|
||||
ModelList: []config.ModelConfig{
|
||||
{ModelName: "existing-model", Model: "openai/existing", APIKey: "test"},
|
||||
{ModelName: "no-key-model", Model: "openai/nokey", APIKey: ""},
|
||||
ModelList: []*config.ModelConfig{
|
||||
{ModelName: "existing-model", Model: "openai/existing"},
|
||||
{ModelName: "no-key-model", Model: "openai/nokey"},
|
||||
},
|
||||
}
|
||||
}).WithSecurity(&config.SecurityConfig{ModelList: map[string]config.ModelSecurityEntry{
|
||||
"existing-model": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
"no-key-model": {
|
||||
APIKeys: []string{""},
|
||||
},
|
||||
}})
|
||||
|
||||
assert.Error(t, setDefaultModel(configPath, cfg, "no-key-model"))
|
||||
}
|
||||
@@ -203,16 +239,20 @@ func TestSetDefaultModel_SaveConfigError(t *testing.T) {
|
||||
// Use an invalid path to trigger save error
|
||||
invalidPath := "/nonexistent/directory/config.json"
|
||||
|
||||
cfg := &config.Config{
|
||||
cfg := (&config.Config{
|
||||
Agents: config.AgentsConfig{
|
||||
Defaults: config.AgentDefaults{
|
||||
ModelName: "old-model",
|
||||
},
|
||||
},
|
||||
ModelList: []config.ModelConfig{
|
||||
{ModelName: "new-model", Model: "openai/new-model", APIKey: "test"},
|
||||
ModelList: []*config.ModelConfig{
|
||||
{ModelName: "new-model", Model: "openai/new-model"},
|
||||
},
|
||||
}
|
||||
}).WithSecurity(&config.SecurityConfig{ModelList: map[string]config.ModelSecurityEntry{
|
||||
"new-model": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
}})
|
||||
|
||||
err := setDefaultModel(invalidPath, cfg, "new-model")
|
||||
|
||||
@@ -244,16 +284,20 @@ func TestModelCommandExecution_Show(t *testing.T) {
|
||||
initTest(t)
|
||||
|
||||
// Create a test config
|
||||
cfg := &config.Config{
|
||||
cfg := (&config.Config{
|
||||
Agents: config.AgentsConfig{
|
||||
Defaults: config.AgentDefaults{
|
||||
ModelName: "test-model",
|
||||
},
|
||||
},
|
||||
ModelList: []config.ModelConfig{
|
||||
{ModelName: "test-model", Model: "openai/test", APIKey: "test"},
|
||||
ModelList: []*config.ModelConfig{
|
||||
{ModelName: "test-model", Model: "openai/test"},
|
||||
},
|
||||
}
|
||||
}).WithSecurity(&config.SecurityConfig{ModelList: map[string]config.ModelSecurityEntry{
|
||||
"test-model": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
}})
|
||||
|
||||
err := config.SaveConfig(configPath, cfg)
|
||||
require.NoError(t, err)
|
||||
@@ -271,17 +315,25 @@ func TestModelCommandExecution_Show(t *testing.T) {
|
||||
func TestModelCommandExecution_Set(t *testing.T) {
|
||||
initTest(t)
|
||||
|
||||
cfg := &config.Config{
|
||||
sec := &config.SecurityConfig{ModelList: map[string]config.ModelSecurityEntry{
|
||||
"old-model": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
"new-model": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
}}
|
||||
cfg := (&config.Config{
|
||||
Agents: config.AgentsConfig{
|
||||
Defaults: config.AgentDefaults{
|
||||
ModelName: "old-model",
|
||||
},
|
||||
},
|
||||
ModelList: []config.ModelConfig{
|
||||
{ModelName: "old-model", Model: "openai/old", APIKey: "test"},
|
||||
{ModelName: "new-model", Model: "openai/new", APIKey: "test"},
|
||||
ModelList: []*config.ModelConfig{
|
||||
{ModelName: "old-model", Model: "openai/old"},
|
||||
{ModelName: "new-model", Model: "openai/new"},
|
||||
},
|
||||
}
|
||||
}).WithSecurity(sec)
|
||||
|
||||
err := config.SaveConfig(configPath, cfg)
|
||||
require.NoError(t, err)
|
||||
@@ -305,18 +357,28 @@ func TestModelCommandExecution_TooManyArgs(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestListAvailableModels_MarkerLogic(t *testing.T) {
|
||||
cfg := &config.Config{
|
||||
cfg := (&config.Config{
|
||||
Agents: config.AgentsConfig{
|
||||
Defaults: config.AgentDefaults{
|
||||
ModelName: "middle-model",
|
||||
},
|
||||
},
|
||||
ModelList: []config.ModelConfig{
|
||||
{ModelName: "first-model", Model: "openai/first", APIKey: "test"},
|
||||
{ModelName: "middle-model", Model: "openai/middle", APIKey: "test"},
|
||||
{ModelName: "last-model", Model: "openai/last", APIKey: "test"},
|
||||
ModelList: []*config.ModelConfig{
|
||||
{ModelName: "first-model", Model: "openai/first"},
|
||||
{ModelName: "middle-model", Model: "openai/middle"},
|
||||
{ModelName: "last-model", Model: "openai/last"},
|
||||
},
|
||||
}
|
||||
}).WithSecurity(&config.SecurityConfig{ModelList: map[string]config.ModelSecurityEntry{
|
||||
"first-model": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
"middle-model": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
"last-model": {
|
||||
APIKeys: []string{"test"},
|
||||
},
|
||||
}})
|
||||
|
||||
output := captureStdout(func() {
|
||||
listAvailableModels(cfg)
|
||||
|
||||
@@ -31,7 +31,7 @@ func NewSkillsCommand() *cobra.Command {
|
||||
d.workspace = cfg.WorkspacePath()
|
||||
installer, err := skills.NewSkillInstaller(
|
||||
d.workspace,
|
||||
cfg.Tools.Skills.Github.Token,
|
||||
cfg.Tools.Skills.Github.Token(),
|
||||
cfg.Tools.Skills.Github.Proxy,
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
@@ -64,9 +64,20 @@ func skillsInstallFromRegistry(cfg *config.Config, registryName, slug string) er
|
||||
|
||||
fmt.Printf("Installing skill '%s' from %s registry...\n", slug, registryName)
|
||||
|
||||
clawHubConfig := cfg.Tools.Skills.Registries.ClawHub
|
||||
registryMgr := skills.NewRegistryManagerFromConfig(skills.RegistryConfig{
|
||||
MaxConcurrentSearches: cfg.Tools.Skills.MaxConcurrentSearches,
|
||||
ClawHub: skills.ClawHubConfig(cfg.Tools.Skills.Registries.ClawHub),
|
||||
ClawHub: skills.ClawHubConfig{
|
||||
Enabled: clawHubConfig.Enabled,
|
||||
BaseURL: clawHubConfig.BaseURL,
|
||||
AuthToken: clawHubConfig.AuthToken(),
|
||||
SearchPath: clawHubConfig.SearchPath,
|
||||
SkillsPath: clawHubConfig.SkillsPath,
|
||||
DownloadPath: clawHubConfig.DownloadPath,
|
||||
Timeout: clawHubConfig.Timeout,
|
||||
MaxZipSize: clawHubConfig.MaxZipSize,
|
||||
MaxResponseSize: clawHubConfig.MaxResponseSize,
|
||||
},
|
||||
})
|
||||
|
||||
registry := registryMgr.GetRegistry(registryName)
|
||||
@@ -226,9 +237,20 @@ func skillsSearchCmd(query string) {
|
||||
return
|
||||
}
|
||||
|
||||
clawHubConfig := cfg.Tools.Skills.Registries.ClawHub
|
||||
registryMgr := skills.NewRegistryManagerFromConfig(skills.RegistryConfig{
|
||||
MaxConcurrentSearches: cfg.Tools.Skills.MaxConcurrentSearches,
|
||||
ClawHub: skills.ClawHubConfig(cfg.Tools.Skills.Registries.ClawHub),
|
||||
ClawHub: skills.ClawHubConfig{
|
||||
Enabled: clawHubConfig.Enabled,
|
||||
BaseURL: clawHubConfig.BaseURL,
|
||||
AuthToken: clawHubConfig.AuthToken(),
|
||||
SearchPath: clawHubConfig.SearchPath,
|
||||
SkillsPath: clawHubConfig.SkillsPath,
|
||||
DownloadPath: clawHubConfig.DownloadPath,
|
||||
Timeout: clawHubConfig.Timeout,
|
||||
MaxZipSize: clawHubConfig.MaxZipSize,
|
||||
MaxResponseSize: clawHubConfig.MaxResponseSize,
|
||||
},
|
||||
})
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
|
||||
Reference in New Issue
Block a user