package models import ( "context" "encoding/json" "io" "net/http" "strings" "testing" "time" "git.cin.su/m/Assistant/contracts/capability" "git.cin.su/m/Assistant/contracts/cognitive" ) type captureRoundTripper struct { authorization string body []byte } func TestOpenAICompatibleLocalAdapterUsesConfiguredTimeout(t *testing.T) { adapter, err := NewOpenAICompatibleLocalAdapterWithAPIKeyAndTimeout("http://gateway/v1", "", &captureRoundTripper{}, 47*time.Second) if err != nil { t.Fatal(err) } if adapter.client.Timeout != 47*time.Second { t.Fatalf("unexpected client timeout: %s", adapter.client.Timeout) } } func TestOpenAICompatibleLocalAdapterRejectsNonPositiveTimeout(t *testing.T) { if _, err := NewOpenAICompatibleLocalAdapterWithAPIKeyAndTimeout("http://gateway/v1", "", nil, 0); err == nil { t.Fatal("expected non-positive timeout to be rejected") } } func (t *captureRoundTripper) RoundTrip(request *http.Request) (*http.Response, error) { t.authorization = request.Header.Get("Authorization") if request.Body != nil { t.body, _ = io.ReadAll(request.Body) } body := `{"data":[]}` if strings.HasSuffix(request.URL.Path, "/chat/completions") { body = `{"choices":[{"finish_reason":"stop","message":{"role":"assistant","content":"ok"}}],"usage":{"prompt_tokens":1,"completion_tokens":1}}` } return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader(body)), Header: make(http.Header), Request: request}, nil } func TestOpenAICompatibleLocalAdapterUsesResolvedAPIKey(t *testing.T) { transport := &captureRoundTripper{} adapter, err := NewOpenAICompatibleLocalAdapterWithAPIKey("http://gateway/v1", "resolved-key", transport) if err != nil { t.Fatal(err) } _, _ = adapter.Discover(context.Background()) if transport.authorization != "Bearer resolved-key" { t.Fatalf("unexpected authorization header: %q", transport.authorization) } } func TestOpenAICompatibleLocalAdapterDoesNotSendAuthorizationWithoutKey(t *testing.T) { transport := &captureRoundTripper{} adapter, err := NewOpenAICompatibleLocalAdapter("http://gateway/v1", transport) if err != nil { t.Fatal(err) } _, _ = adapter.Discover(context.Background()) if transport.authorization != "" { t.Fatalf("unexpected authorization header") } } func TestOpenAICompatibleLocalAdapterDisablesTemplateThinkingForBoundedAdvisory(t *testing.T) { transport := &captureRoundTripper{} adapter, err := NewOpenAICompatibleLocalAdapter("http://gateway/v1", transport) if err != nil { t.Fatal(err) } _, err = adapter.Advise(context.Background(), cognitive.AdvisoryRequest{Version: cognitive.CreatorAdvisoryV1, RequestID: "request-1", ActorID: "actor", PrincipalID: "principal", ScopeID: "scope", Message: "help", Locale: "ru-RU", MaxOutputBytes: 256, ProviderBindingID: "binding-1", ProviderBindingRevision: 1, ProviderInstanceID: "provider-1", ModelDescriptorID: "model-1", ProviderModelID: capability.ProviderModelID("medium-model")}) if err != nil { t.Fatal(err) } var payload struct { ChatTemplateKwargs struct { EnableThinking bool `json:"enable_thinking"` } `json:"chat_template_kwargs"` } if err := json.Unmarshal(transport.body, &payload); err != nil { t.Fatal(err) } if payload.ChatTemplateKwargs.EnableThinking { t.Fatal("expected bounded advisory to disable template thinking") } }