100 lines
3.2 KiB
Go
100 lines
3.2 KiB
Go
package usecase
|
|
|
|
import (
|
|
"context"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"gitea.maximumdirect.net/eric/scriptorium/internal/artifact"
|
|
"gitea.maximumdirect.net/eric/scriptorium/internal/domain"
|
|
"gitea.maximumdirect.net/eric/scriptorium/internal/profile"
|
|
"gitea.maximumdirect.net/eric/scriptorium/internal/prompt"
|
|
"gitea.maximumdirect.net/eric/scriptorium/internal/validate"
|
|
)
|
|
|
|
type integrationLLM struct{}
|
|
|
|
func (f *integrationLLM) Generate(ctx context.Context, req domain.GenerateRequest) (*domain.GenerateResponse, error) {
|
|
return &domain.GenerateResponse{
|
|
Content: `{"summary":"Party discovered a captive scout beneath the tower.","events":[{"title":"Scout found in cellar","type":"discovery","notes":"Scout requested rescue from goblin raiders."}]}`,
|
|
Usage: domain.TokenUsage{
|
|
PromptTokens: 42,
|
|
CompletionTokens: 36,
|
|
TotalTokens: 78,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func TestRunnerIntegrationWithProfilesFixturesAndValidation(t *testing.T) {
|
|
root, err := filepath.Abs(filepath.Join("..", ".."))
|
|
if err != nil {
|
|
t.Fatalf("failed to resolve repo root: %v", err)
|
|
}
|
|
|
|
profilesDir := filepath.Join(root, "profiles")
|
|
schemasDir := filepath.Join(root, "schemas")
|
|
fixturesDir := filepath.Join(root, "examples", "fixtures")
|
|
|
|
runner := NewRunner(
|
|
profile.NewFilesystemRepository(profilesDir),
|
|
artifact.NewCompositeReader(),
|
|
prompt.NewGoRenderer(),
|
|
&integrationLLM{},
|
|
validate.NewStandardValidator(schemasDir),
|
|
)
|
|
|
|
res, err := runner.Run(context.Background(), domain.RunRequest{
|
|
ProfileID: "generic.structured_events",
|
|
Inputs: map[string]domain.ArtifactRef{
|
|
"transcript": {
|
|
Type: domain.ArtifactRefFile,
|
|
URI: filepath.Join(fixturesDir, "transcript.md"),
|
|
},
|
|
"glossary": {
|
|
Type: domain.ArtifactRefFile,
|
|
URI: filepath.Join(fixturesDir, "glossary.yml"),
|
|
},
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("expected no error, got %v", err)
|
|
}
|
|
|
|
if res.ProfileID != "generic.structured_events" {
|
|
t.Fatalf("unexpected profile id: %q", res.ProfileID)
|
|
}
|
|
if res.ProfileVersion != "1.0.0" {
|
|
t.Fatalf("unexpected profile version: %q", res.ProfileVersion)
|
|
}
|
|
if res.Validation.Status != domain.ValidationPassed {
|
|
t.Fatalf("expected passed validation, got %q", res.Validation.Status)
|
|
}
|
|
if res.Validation.Mode != domain.ValidationJSONSchema {
|
|
t.Fatalf("expected json_schema mode, got %q", res.Validation.Mode)
|
|
}
|
|
if res.Artifact.ContentType != "application/json" {
|
|
t.Fatalf("expected application/json output, got %q", res.Artifact.ContentType)
|
|
}
|
|
if len(res.RawOutput) == 0 {
|
|
t.Fatal("expected raw output to be preserved")
|
|
}
|
|
if res.PromptHash == "" {
|
|
t.Fatal("expected non-empty prompt hash")
|
|
}
|
|
if len(res.InputHashes) != 2 {
|
|
t.Fatalf("expected two input hashes, got %d", len(res.InputHashes))
|
|
}
|
|
if res.InputHashes["transcript"] == "" || res.InputHashes["glossary"] == "" {
|
|
t.Fatalf("expected both input hashes to be set, got %#v", res.InputHashes)
|
|
}
|
|
if res.Usage.TotalTokens != 78 {
|
|
t.Fatalf("expected usage from fake llm, got %+v", res.Usage)
|
|
}
|
|
if res.StartTime.IsZero() || res.EndTime.IsZero() {
|
|
t.Fatal("expected start/end timestamps")
|
|
}
|
|
if res.EndTime.Before(res.StartTime) {
|
|
t.Fatalf("expected end >= start, got start=%v end=%v", res.StartTime, res.EndTime)
|
|
}
|
|
}
|