vibe-proxy/backend/sdk/cliproxy/service_codex_executor_binding_test.go
2026-08-24 00:10:41 +02:00

237 lines
7.5 KiB
Go

package cliproxy
import (
"context"
"testing"
"github.com/router-for-me/CLIProxyAPI/v7/internal/pluginhost"
"github.com/router-for-me/CLIProxyAPI/v7/internal/runtime/executor"
"github.com/router-for-me/CLIProxyAPI/v7/internal/watcher"
sdkAuth "github.com/router-for-me/CLIProxyAPI/v7/sdk/auth"
coreauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"
"github.com/router-for-me/CLIProxyAPI/v7/sdk/config"
sdktranslator "github.com/router-for-me/CLIProxyAPI/v7/sdk/translator"
)
func TestEnsureExecutorsForAuth_CodexDoesNotReplaceInNormalMode(t *testing.T) {
service := &Service{
cfg: &config.Config{},
coreManager: coreauth.NewManager(nil, nil, nil),
}
auth := &coreauth.Auth{
ID: "codex-auth-1",
Provider: "codex",
Status: coreauth.StatusActive,
}
service.ensureExecutorsForAuth(auth)
firstExecutor, okFirst := service.coreManager.Executor("codex")
if !okFirst || firstExecutor == nil {
t.Fatal("expected codex executor after first bind")
}
service.ensureExecutorsForAuth(auth)
secondExecutor, okSecond := service.coreManager.Executor("codex")
if !okSecond || secondExecutor == nil {
t.Fatal("expected codex executor after second bind")
}
if firstExecutor != secondExecutor {
t.Fatal("expected codex executor to stay unchanged in normal mode")
}
}
func TestEnsureExecutorsForAuthWithMode_CodexForceReplace(t *testing.T) {
service := &Service{
cfg: &config.Config{},
coreManager: coreauth.NewManager(nil, nil, nil),
}
auth := &coreauth.Auth{
ID: "codex-auth-2",
Provider: "codex",
Status: coreauth.StatusActive,
}
service.ensureExecutorsForAuth(auth)
firstExecutor, okFirst := service.coreManager.Executor("codex")
if !okFirst || firstExecutor == nil {
t.Fatal("expected codex executor after first bind")
}
service.ensureExecutorsForAuthWithMode(auth, true)
secondExecutor, okSecond := service.coreManager.Executor("codex")
if !okSecond || secondExecutor == nil {
t.Fatal("expected codex executor after forced rebind")
}
if firstExecutor == secondExecutor {
t.Fatal("expected codex executor replacement in force mode")
}
}
func TestSyncPluginModelRuntime_UnrelatedAuthDoesNotReplaceWebsocketExecutor(t *testing.T) {
testCases := []struct {
name string
provider string
homeEnabled bool
}{
{name: "codex standard mode", provider: "codex"},
{name: "codex home mode", provider: "codex", homeEnabled: true},
{name: "xai standard mode", provider: "xai"},
{name: "xai home mode", provider: "xai", homeEnabled: true},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
cfg := &config.Config{}
cfg.Home.Enabled = tt.homeEnabled
service := &Service{
cfg: cfg,
coreManager: coreauth.NewManager(nil, nil, nil),
pluginHost: pluginhost.New(),
}
providerAuth := &coreauth.Auth{
ID: tt.provider + "-auth",
Provider: tt.provider,
Status: coreauth.StatusActive,
}
unrelatedAuth := &coreauth.Auth{
ID: "unrelated-auth",
Provider: "claude",
Status: coreauth.StatusActive,
}
t.Cleanup(func() {
GlobalModelRegistry().UnregisterClient(providerAuth.ID)
GlobalModelRegistry().UnregisterClient(unrelatedAuth.ID)
sdkAuth.RegisterPluginAuthParser(nil)
sdktranslator.SetPluginHooks(nil)
})
if _, errRegister := service.coreManager.Register(ctx, providerAuth); errRegister != nil {
t.Fatalf("register %s auth: %v", tt.provider, errRegister)
}
if _, errRegister := service.coreManager.Register(ctx, unrelatedAuth); errRegister != nil {
t.Fatalf("register unrelated auth: %v", errRegister)
}
service.ensureExecutorsForAuth(providerAuth)
firstExecutor, okFirst := service.coreManager.Executor(tt.provider)
if !okFirst || firstExecutor == nil {
t.Fatalf("expected %s executor before plugin model sync", tt.provider)
}
updatedAuth := unrelatedAuth.Clone()
updatedAuth.Label = "updated unrelated auth"
service.handleAuthUpdate(ctx, watcher.AuthUpdate{
Action: watcher.AuthUpdateActionModify,
ID: updatedAuth.ID,
Auth: updatedAuth,
})
secondExecutor, okSecond := service.coreManager.Executor(tt.provider)
if !okSecond || secondExecutor == nil {
t.Fatalf("expected %s executor after plugin model sync", tt.provider)
}
if firstExecutor != secondExecutor {
t.Fatalf("expected unrelated auth sync to preserve the %s executor", tt.provider)
}
})
}
}
func TestEnsureExecutorsForAuth_XAIDoesNotReplaceInNormalMode(t *testing.T) {
service := &Service{
cfg: &config.Config{},
coreManager: coreauth.NewManager(nil, nil, nil),
}
auth := &coreauth.Auth{
ID: "xai-auth-1",
Provider: "xai",
Status: coreauth.StatusActive,
}
service.ensureExecutorsForAuth(auth)
firstExecutor, okFirst := service.coreManager.Executor("xai")
if !okFirst || firstExecutor == nil {
t.Fatal("expected xai executor after first bind")
}
if _, isXAIAutoExecutor := firstExecutor.(*executor.XAIAutoExecutor); !isXAIAutoExecutor {
t.Fatalf("xai executor type = %T, want *executor.XAIAutoExecutor", firstExecutor)
}
service.ensureExecutorsForAuth(auth)
secondExecutor, okSecond := service.coreManager.Executor("xai")
if !okSecond || secondExecutor == nil {
t.Fatal("expected xai executor after second bind")
}
if firstExecutor != secondExecutor {
t.Fatal("expected xai executor to stay unchanged in normal mode")
}
}
func TestEnsureExecutorsForAuthWithMode_XAIForceReplace(t *testing.T) {
service := &Service{
cfg: &config.Config{},
coreManager: coreauth.NewManager(nil, nil, nil),
}
auth := &coreauth.Auth{
ID: "xai-auth-2",
Provider: "xai",
Status: coreauth.StatusActive,
}
service.ensureExecutorsForAuth(auth)
firstExecutor, okFirst := service.coreManager.Executor("xai")
if !okFirst || firstExecutor == nil {
t.Fatal("expected xai executor after first bind")
}
service.ensureExecutorsForAuthWithMode(auth, true)
secondExecutor, okSecond := service.coreManager.Executor("xai")
if !okSecond || secondExecutor == nil {
t.Fatal("expected xai executor after forced rebind")
}
if firstExecutor == secondExecutor {
t.Fatal("expected xai executor replacement in force mode")
}
if _, isXAIAutoExecutor := secondExecutor.(*executor.XAIAutoExecutor); !isXAIAutoExecutor {
t.Fatalf("xai executor type = %T, want *executor.XAIAutoExecutor", secondExecutor)
}
}
func TestEnsureExecutorsForAuth_XAIReplacesExecutorAfterConfigUpdate(t *testing.T) {
service := &Service{
cfg: &config.Config{},
coreManager: coreauth.NewManager(nil, nil, nil),
pluginHost: pluginhost.New(),
}
t.Cleanup(func() {
sdkAuth.RegisterPluginAuthParser(nil)
sdktranslator.SetPluginHooks(nil)
})
auth := &coreauth.Auth{
ID: "xai-auth-config-update",
Provider: "xai",
Status: coreauth.StatusActive,
}
service.ensureExecutorsForAuth(auth)
firstExecutor, okFirst := service.coreManager.Executor("xai")
if !okFirst || firstExecutor == nil {
t.Fatal("expected xai executor before config update")
}
service.applyWatcherConfigUpdate(&config.Config{})
service.ensureExecutorsForAuth(auth)
secondExecutor, okSecond := service.coreManager.Executor("xai")
if !okSecond || secondExecutor == nil {
t.Fatal("expected xai executor after config update")
}
if firstExecutor == secondExecutor {
t.Fatal("expected stale xai executor replacement after config update")
}
if _, isXAIAutoExecutor := secondExecutor.(*executor.XAIAutoExecutor); !isXAIAutoExecutor {
t.Fatalf("xai executor type = %T, want *executor.XAIAutoExecutor", secondExecutor)
}
}