Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
package platformsettings
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestValidAIRole(t *testing.T) {
|
||||
for _, role := range AIRoles {
|
||||
if !ValidAIRole(role) {
|
||||
t.Fatalf("%q should be valid", role)
|
||||
}
|
||||
}
|
||||
if ValidAIRole("embeddings") {
|
||||
t.Fatal("embeddings alias is not a stored role key")
|
||||
}
|
||||
if ValidAIRole("") {
|
||||
t.Fatal("empty role should be invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublicAIConfigs_masksSecret(t *testing.T) {
|
||||
key := DeriveKey("test-ai-config-secret-material", "fallback")
|
||||
plain := "sk-live-super-secret-key"
|
||||
enc, err := EncryptSecret(key, plain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
svc := &Service{Key: key}
|
||||
doc := storedDoc{
|
||||
AIConfigs: map[string]aiConfigStored{
|
||||
AIRoleSupport: {
|
||||
Provider: "openai",
|
||||
BaseURL: "https://api.openai.com/v1",
|
||||
Model: "gpt-4o-mini",
|
||||
APIKeyEnc: enc,
|
||||
APIKeyLast4: last4(plain),
|
||||
Enabled: true,
|
||||
Extras: map[string]string{"temperature": "0.2"},
|
||||
},
|
||||
},
|
||||
}
|
||||
view := svc.publicAIConfigs(doc)
|
||||
if len(view) != len(AIRoles) {
|
||||
t.Fatalf("expected %d roles, got %d", len(AIRoles), len(view))
|
||||
}
|
||||
got := view[AIRoleSupport]
|
||||
if got.APIKeyMasked == "" || strings.Contains(got.APIKeyMasked, "super-secret") {
|
||||
t.Fatalf("api key not masked: %+v", got)
|
||||
}
|
||||
if got.HasAPIKey != true || got.APIKeyLast4 != last4(plain) {
|
||||
t.Fatalf("unexpected mask meta: %+v", got)
|
||||
}
|
||||
if got.Extras["temperature"] != "0.2" {
|
||||
t.Fatalf("extras: %+v", got.Extras)
|
||||
}
|
||||
if view[AIRoleDocsAPI].Role != AIRoleDocsAPI {
|
||||
t.Fatalf("missing empty role stub: %+v", view[AIRoleDocsAPI])
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublicAIConfigs_processingFallsBackToOpenAI(t *testing.T) {
|
||||
key := DeriveKey("test-ai-config-secret-material", "fallback")
|
||||
plain := "sk-legacy-abcdef12"
|
||||
enc, err := EncryptSecret(key, plain)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
svc := &Service{Key: key}
|
||||
doc := storedDoc{
|
||||
OpenAI: openaiStored{
|
||||
BaseURL: "https://example.test/v1",
|
||||
Model: "gpt-test",
|
||||
APIKeyEnc: enc,
|
||||
APIKeyLast4: last4(plain),
|
||||
},
|
||||
}
|
||||
view := svc.publicAIConfigs(doc)
|
||||
got := view[AIRoleProcessing]
|
||||
if !got.HasAPIKey || got.Source != SourceDB || got.Model != "gpt-test" {
|
||||
t.Fatalf("processing fallback: %+v", got)
|
||||
}
|
||||
if strings.Contains(got.APIKeyMasked, "legacy") {
|
||||
t.Fatalf("leaked key: %q", got.APIKeyMasked)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveAIConfig_envFallback(t *testing.T) {
|
||||
svc := NewService(nil, EnvConfig{
|
||||
OpenAIAPIKey: "env-key-1234",
|
||||
OpenAIBaseURL: "https://api.openai.com/v1",
|
||||
OpenAIModel: "gpt-4o",
|
||||
})
|
||||
got, err := svc.ResolveAIConfig(context.Background(), AIRoleProcessing)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got.APIKey != "env-key-1234" || got.Source != SourceEnv || !got.Enabled {
|
||||
t.Fatalf("got %+v", got)
|
||||
}
|
||||
support, err := svc.ResolveAIConfig(context.Background(), AIRoleSupport)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if support.APIKey != "" || support.Source != SourceNone {
|
||||
t.Fatalf("support should not use openai env: %+v", support)
|
||||
}
|
||||
vec, err := svc.ResolveAIConfig(context.Background(), AIRoleVectorization)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if vec.APIKey != "env-key-1234" || vec.Source != SourceEnv || vec.Model == "" {
|
||||
t.Fatalf("vectorization env fallback: %+v", vec)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPatchAIExtras(t *testing.T) {
|
||||
var extras map[string]string
|
||||
val := "1536"
|
||||
if err := patchAIExtras(&extras, map[string]*string{"dimensions": &val}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if extras["dimensions"] != "1536" {
|
||||
t.Fatalf("got %#v", extras)
|
||||
}
|
||||
if err := patchAIExtras(&extras, map[string]*string{"dimensions": nil}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if extras != nil {
|
||||
t.Fatalf("expected nil after delete, got %#v", extras)
|
||||
}
|
||||
if err := patchAIExtras(&extras, map[string]*string{"": &val}); err == nil {
|
||||
t.Fatal("expected empty key error")
|
||||
}
|
||||
if err := patchAIExtras(&extras, map[string]*string{"bad key": &val}); err == nil {
|
||||
t.Fatal("expected whitespace key error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPatchAIConfig_keepsSecretWhenOmitted(t *testing.T) {
|
||||
key := DeriveKey("test-ai-config-secret-material", "fallback")
|
||||
enc, err := EncryptSecret(key, "keep-me-secret")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
svc := &Service{Key: key}
|
||||
st := aiConfigStored{APIKeyEnc: enc, APIKeyLast4: last4("keep-me-secret"), Provider: "openai"}
|
||||
model := "new-model"
|
||||
if err := svc.patchAIConfig(&st, AIConfigUpdate{Model: &model}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if st.APIKeyEnc != enc || st.Model != "new-model" {
|
||||
t.Fatalf("unexpected state: %+v", st)
|
||||
}
|
||||
empty := ""
|
||||
if err := svc.patchAIConfig(&st, AIConfigUpdate{APIKey: &empty}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if st.APIKeyEnc != enc {
|
||||
t.Fatal("empty api_key should keep existing")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user