a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
113 lines
3.4 KiB
Go
113 lines
3.4 KiB
Go
package svc
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/zzet/gortex/internal/llm"
|
|
"github.com/zzet/gortex/internal/llm/conversationlog"
|
|
)
|
|
|
|
// fakeGenProvider answers a freeform Generate with a fixed string and
|
|
// (optionally) a usage block, so the sink can be exercised for both the
|
|
// real-usage and estimated paths.
|
|
type fakeGenProvider struct{ usage llm.TokenUsage }
|
|
|
|
func (p *fakeGenProvider) Name() string { return "fakegen" }
|
|
func (p *fakeGenProvider) Close() error { return nil }
|
|
func (p *fakeGenProvider) Complete(_ context.Context, _ llm.CompletionRequest) (llm.CompletionResponse, error) {
|
|
return llm.CompletionResponse{Text: "the answer", Usage: p.usage}, nil
|
|
}
|
|
|
|
func TestService_ConversationLog_Generate(t *testing.T) {
|
|
dir := t.TempDir()
|
|
s := newFakeService(&fakeGenProvider{usage: llm.TokenUsage{InputTokens: 12, OutputTokens: 3}})
|
|
s.SetConversationDir(dir)
|
|
t.Cleanup(func() { _ = s.Close() })
|
|
|
|
ctx := conversationlog.WithMeta(context.Background(), conversationlog.Meta{
|
|
Session: "gen-sess", Repo: "gortex", File: "pkg/x.go", Phase: "main",
|
|
})
|
|
out, err := s.Generate(ctx, "hello", 64)
|
|
if err != nil {
|
|
t.Fatalf("Generate: %v", err)
|
|
}
|
|
if out != "the answer" {
|
|
t.Fatalf("Generate returned %q", out)
|
|
}
|
|
|
|
recs, err := conversationlog.NewReader(dir).LoadSession("gen-sess")
|
|
if err != nil {
|
|
t.Fatalf("LoadSession: %v", err)
|
|
}
|
|
if len(recs) != 1 {
|
|
t.Fatalf("got %d records, want 1", len(recs))
|
|
}
|
|
r := recs[0]
|
|
if r.File != "pkg/x.go" || r.Phase != "main" || r.Repo != "gortex" {
|
|
t.Fatalf("labels not recorded: %+v", r)
|
|
}
|
|
if r.Response != "the answer" {
|
|
t.Fatalf("response not recorded: %q", r.Response)
|
|
}
|
|
if r.InputTokens != 12 || r.OutputTokens != 3 {
|
|
t.Fatalf("real usage not recorded: in=%d out=%d", r.InputTokens, r.OutputTokens)
|
|
}
|
|
if r.Estimated {
|
|
t.Fatal("real usage must not be flagged estimated")
|
|
}
|
|
}
|
|
|
|
func TestService_ConversationLog_RunAgent_OneRecordPerTurn(t *testing.T) {
|
|
dir := t.TempDir()
|
|
// fakeAgentProvider returns no usage → estimated counts.
|
|
s := newFakeService(&fakeAgentProvider{})
|
|
s.SetConversationDir(dir)
|
|
t.Cleanup(func() { _ = s.Close() })
|
|
|
|
ctx := conversationlog.WithMeta(context.Background(), conversationlog.Meta{Session: "agent-sess"})
|
|
ans, err := s.RunAgent(ctx, llm.RunAgentOptions{Question: "find Foo"})
|
|
if err != nil {
|
|
t.Fatalf("RunAgent: %v", err)
|
|
}
|
|
if ans.Answer == "" {
|
|
t.Fatal("agent produced no answer")
|
|
}
|
|
|
|
recs, err := conversationlog.NewReader(dir).LoadSession("agent-sess")
|
|
if err != nil {
|
|
t.Fatalf("LoadSession: %v", err)
|
|
}
|
|
if len(recs) != 1 {
|
|
t.Fatalf("got %d records, want exactly 1 per turn", len(recs))
|
|
}
|
|
if !recs[0].Estimated {
|
|
t.Fatal("a provider without usage must record estimated token counts")
|
|
}
|
|
if recs[0].Response != ans.Answer {
|
|
t.Fatalf("recorded response %q != answer %q", recs[0].Response, ans.Answer)
|
|
}
|
|
}
|
|
|
|
func TestService_ConversationLog_OptInOff_NothingRecorded(t *testing.T) {
|
|
// Default service has no conversation dir → nothing is recorded.
|
|
dir := t.TempDir()
|
|
s := newFakeService(&fakeGenProvider{})
|
|
t.Cleanup(func() { _ = s.Close() })
|
|
if s.ConversationDir() != "" {
|
|
t.Fatal("conversation dir should be off by default")
|
|
}
|
|
|
|
_, err := s.Generate(context.Background(), "hello", 64)
|
|
if err != nil {
|
|
t.Fatalf("Generate: %v", err)
|
|
}
|
|
sessions, err := conversationlog.NewReader(dir).ListSessions()
|
|
if err != nil {
|
|
t.Fatalf("ListSessions: %v", err)
|
|
}
|
|
if len(sessions) != 0 {
|
|
t.Fatalf("opt-in OFF recorded %d sessions, want 0", len(sessions))
|
|
}
|
|
}
|