75 lines
2.6 KiB
Go
75 lines
2.6 KiB
Go
package aiprovider
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"github.com/descrybe/descrybe-v2/apps/api/internal/aiaudit"
|
||
|
|
"github.com/descrybe/descrybe-v2/apps/api/internal/processing"
|
||
|
|
"github.com/google/uuid"
|
||
|
|
)
|
||
|
|
|
||
|
|
type optionsStub struct{ withOptions, plain int }
|
||
|
|
|
||
|
|
func (s *optionsStub) Complete(context.Context, string, string) (processing.Completion, error) {
|
||
|
|
s.plain++
|
||
|
|
return processing.Completion{Text: "{}"}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *optionsStub) CompleteWithOptions(context.Context, string, string, processing.CompleteOptions) (processing.Completion, error) {
|
||
|
|
s.withOptions++
|
||
|
|
return processing.Completion{Text: "{}"}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Regression: processing.CompleteOnce prefers CompleterWithOptions and only falls
|
||
|
|
// back to Complete. A wrapper that does not forward the options interface silently
|
||
|
|
// drops MaxTokens / Temperature / ReasoningEffort for every enhance call.
|
||
|
|
func TestAuditingCompleter_forwardsCompleteWithOptions(t *testing.T) {
|
||
|
|
t.Parallel()
|
||
|
|
inner := &optionsStub{}
|
||
|
|
svc := &Service{Audit: &aiaudit.Recorder{}}
|
||
|
|
wrapped := svc.WrapAudit(inner, uuid.New(), RoleProcessing, "internal")
|
||
|
|
|
||
|
|
if _, ok := wrapped.(processing.CompleterWithOptions); !ok {
|
||
|
|
t.Fatal("wrapped completer must still satisfy CompleterWithOptions")
|
||
|
|
}
|
||
|
|
if _, err := processing.CompleteOnce(context.Background(), wrapped, "sys", "user",
|
||
|
|
processing.CompleteOptions{MaxTokens: 1234}); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if inner.withOptions != 1 || inner.plain != 0 {
|
||
|
|
t.Fatalf("options path not forwarded: withOptions=%d plain=%d", inner.withOptions, inner.plain)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// A plain Completer must not gain the options interface just by being wrapped —
|
||
|
|
// that would send options to a client that cannot honour them.
|
||
|
|
func TestAuditingCompleter_plainCompleterStaysPlain(t *testing.T) {
|
||
|
|
t.Parallel()
|
||
|
|
inner := plainStub{}
|
||
|
|
svc := &Service{Audit: &aiaudit.Recorder{}}
|
||
|
|
wrapped := svc.WrapAudit(inner, uuid.New(), RoleProcessing, "internal")
|
||
|
|
if _, ok := wrapped.(processing.CompleterWithOptions); ok {
|
||
|
|
t.Fatal("plain completer must not advertise CompleterWithOptions")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
type plainStub struct{}
|
||
|
|
|
||
|
|
func (plainStub) Complete(context.Context, string, string) (processing.Completion, error) {
|
||
|
|
return processing.Completion{Text: "{}"}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestWrapAudit_noopWhenCaptureOff(t *testing.T) {
|
||
|
|
t.Parallel()
|
||
|
|
inner := plainStub{}
|
||
|
|
var svc *Service
|
||
|
|
if got := svc.WrapAudit(inner, uuid.Nil, RoleProcessing, ""); got != processing.Completer(inner) {
|
||
|
|
t.Fatal("nil service must return the completer untouched")
|
||
|
|
}
|
||
|
|
svc = &Service{}
|
||
|
|
if got := svc.WrapAudit(inner, uuid.Nil, RoleProcessing, ""); got != processing.Completer(inner) {
|
||
|
|
t.Fatal("capture off must return the completer untouched")
|
||
|
|
}
|
||
|
|
}
|