fix(irc): resolve merge conflicts with latest main

This commit is contained in:
Alix-007 2026-03-13 08:25:39 +08:00
parent 8ddffaa3f3
commit ba83a5d256

View file

@ -1,126 +1,126 @@
package api package api
import ( import (
"bytes" "bytes"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"reflect" "reflect"
"testing" "testing"
"github.com/sipeed/picoclaw/pkg/config" "github.com/sipeed/picoclaw/pkg/config"
) )
func TestHandleUpdateConfig_PreservesExecAllowRemoteDefaultWhenOmitted(t *testing.T) { func TestHandleUpdateConfig_PreservesExecAllowRemoteDefaultWhenOmitted(t *testing.T) {
configPath, cleanup := setupOAuthTestEnv(t) configPath, cleanup := setupOAuthTestEnv(t)
defer cleanup() defer cleanup()
h := NewHandler(configPath) h := NewHandler(configPath)
mux := http.NewServeMux() mux := http.NewServeMux()
h.RegisterRoutes(mux) h.RegisterRoutes(mux)
req := httptest.NewRequest(http.MethodPut, "/api/config", bytes.NewBufferString(`{ req := httptest.NewRequest(http.MethodPut, "/api/config", bytes.NewBufferString(`{
"agents": { "agents": {
"defaults": { "defaults": {
"workspace": "~/.picoclaw/workspace" "workspace": "~/.picoclaw/workspace"
} }
}, },
"model_list": [ "model_list": [
{ {
"model_name": "custom-default", "model_name": "custom-default",
"model": "openai/gpt-4o", "model": "openai/gpt-4o",
"api_key": "sk-default" "api_key": "sk-default"
} }
] ]
}`)) }`))
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req) mux.ServeHTTP(rec, req)
if rec.Code != http.StatusOK { if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want %d, body=%s", rec.Code, http.StatusOK, rec.Body.String()) t.Fatalf("status = %d, want %d, body=%s", rec.Code, http.StatusOK, rec.Body.String())
} }
cfg, err := config.LoadConfig(configPath) cfg, err := config.LoadConfig(configPath)
if err != nil { if err != nil {
t.Fatalf("LoadConfig() error = %v", err) t.Fatalf("LoadConfig() error = %v", err)
} }
if !cfg.Tools.Exec.AllowRemote { if !cfg.Tools.Exec.AllowRemote {
t.Fatal("tools.exec.allow_remote should remain true when omitted from PUT /api/config") t.Fatal("tools.exec.allow_remote should remain true when omitted from PUT /api/config")
} }
} }
func TestHandleUpdateConfig_DoesNotInheritDefaultModelFields(t *testing.T) { func TestHandleUpdateConfig_DoesNotInheritDefaultModelFields(t *testing.T) {
configPath, cleanup := setupOAuthTestEnv(t) configPath, cleanup := setupOAuthTestEnv(t)
defer cleanup() defer cleanup()
h := NewHandler(configPath) h := NewHandler(configPath)
mux := http.NewServeMux() mux := http.NewServeMux()
h.RegisterRoutes(mux) h.RegisterRoutes(mux)
req := httptest.NewRequest(http.MethodPut, "/api/config", bytes.NewBufferString(`{ req := httptest.NewRequest(http.MethodPut, "/api/config", bytes.NewBufferString(`{
"agents": { "agents": {
"defaults": { "defaults": {
"workspace": "~/.picoclaw/workspace" "workspace": "~/.picoclaw/workspace"
} }
}, },
"model_list": [ "model_list": [
{ {
"model_name": "custom-default", "model_name": "custom-default",
"model": "openai/gpt-4o", "model": "openai/gpt-4o",
"api_key": "sk-default" "api_key": "sk-default"
} }
] ]
}`)) }`))
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req) mux.ServeHTTP(rec, req)
if rec.Code != http.StatusOK { if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want %d, body=%s", rec.Code, http.StatusOK, rec.Body.String()) t.Fatalf("status = %d, want %d, body=%s", rec.Code, http.StatusOK, rec.Body.String())
} }
cfg, err := config.LoadConfig(configPath) cfg, err := config.LoadConfig(configPath)
if err != nil { if err != nil {
t.Fatalf("LoadConfig() error = %v", err) t.Fatalf("LoadConfig() error = %v", err)
} }
if got := cfg.ModelList[0].APIBase; got != "" { if got := cfg.ModelList[0].APIBase; got != "" {
t.Fatalf("model_list[0].api_base = %q, want empty string", got) t.Fatalf("model_list[0].api_base = %q, want empty string", got)
} }
} }
func TestHandlePatchConfig_AcceptsFlexibleStringSliceString(t *testing.T) { func TestHandlePatchConfig_AcceptsFlexibleStringSliceString(t *testing.T) {
configPath, cleanup := setupOAuthTestEnv(t) configPath, cleanup := setupOAuthTestEnv(t)
defer cleanup() defer cleanup()
h := NewHandler(configPath) h := NewHandler(configPath)
mux := http.NewServeMux() mux := http.NewServeMux()
h.RegisterRoutes(mux) h.RegisterRoutes(mux)
req := httptest.NewRequest(http.MethodPatch, "/api/config", bytes.NewBufferString(`{ req := httptest.NewRequest(http.MethodPatch, "/api/config", bytes.NewBufferString(`{
"channels": { "channels": {
"irc": { "irc": {
"enabled": true, "enabled": true,
"server": "irc.example.com:6667", "server": "irc.example.com:6667",
"nick": "testbot", "nick": "testbot",
"channels": "general, #opsdev" "channels": "general, #opsdev"
} }
} }
}`)) }`))
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req) mux.ServeHTTP(rec, req)
if rec.Code != http.StatusOK { if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want %d, body=%s", rec.Code, http.StatusOK, rec.Body.String()) t.Fatalf("status = %d, want %d, body=%s", rec.Code, http.StatusOK, rec.Body.String())
} }
cfg, err := config.LoadConfig(configPath) cfg, err := config.LoadConfig(configPath)
if err != nil { if err != nil {
t.Fatalf("LoadConfig() error = %v", err) t.Fatalf("LoadConfig() error = %v", err)
} }
want := config.FlexibleStringSlice{"general", "#ops", "dev"} want := config.FlexibleStringSlice{"general", "#ops", "dev"}
if !reflect.DeepEqual(cfg.Channels.IRC.Channels, want) { if !reflect.DeepEqual(cfg.Channels.IRC.Channels, want) {
t.Fatalf("channels.irc.channels = %#v, want %#v", cfg.Channels.IRC.Channels, want) t.Fatalf("channels.irc.channels = %#v, want %#v", cfg.Channels.IRC.Channels, want)
} }
} }