Add built-in profile repository wiring

This commit is contained in:
2026-07-04 16:48:18 +00:00
parent 712c6b92b8
commit 32e2433628
34 changed files with 581 additions and 64 deletions

View File

@@ -20,10 +20,10 @@ func TestNewEngineRejectsMissingPromptDir(t *testing.T) {
}
}
func TestNewEngineRejectsMissingProfileDir(t *testing.T) {
func TestNewEngineAcceptsMissingProfileDir(t *testing.T) {
_, err := scriptorium.NewEngine(scriptorium.Config{PromptDir: "./examples/prompts"})
if !errors.Is(err, scriptorium.ErrInvalidConfig) {
t.Fatalf("expected ErrInvalidConfig, got %v", err)
if err != nil {
t.Fatalf("expected missing profile dir to use built-ins, got %v", err)
}
}
@@ -435,6 +435,123 @@ unknown_field: true
}
}
func TestPrepareUsesBuiltInProfileWithoutProfileDir(t *testing.T) {
t.Setenv("OPENROUTER_API_KEY", "test-key")
engine, err := scriptorium.NewEngine(scriptorium.Config{
PromptDir: "./examples/prompts",
SchemaDir: "./examples/schemas",
})
if err != nil {
t.Fatalf("expected engine construction to succeed, got %v", err)
}
prepared, err := engine.Prepare(context.Background(), scriptorium.RunRequest{
PromptID: "generic.markdown_summary",
ProfileID: "mistral-small-3",
Inputs: map[string]scriptorium.ArtifactRef{
"transcript": scriptorium.Inline("Rin opens the gate."),
"glossary": scriptorium.Inline("gate: A guarded passage."),
},
})
if err != nil {
t.Fatalf("expected built-in profile prepare to succeed, got %v", err)
}
if prepared.SelectedProfileID != "mistral-small-3" {
t.Fatalf("unexpected selected profile: %q", prepared.SelectedProfileID)
}
if prepared.EffectiveModelParams.Model != "mistralai/mistral-small-3.2-24b-instruct" {
t.Fatalf("unexpected built-in model: %q", prepared.EffectiveModelParams.Model)
}
}
func TestPromptDefaultProfileCanUseBuiltInProfile(t *testing.T) {
t.Setenv("OPENROUTER_API_KEY", "test-key")
promptDir := t.TempDir()
writePublicPromptFile(t, promptDir, "prompt.builtin.default", "mistral-small-3")
engine, err := scriptorium.NewEngine(scriptorium.Config{PromptDir: promptDir})
if err != nil {
t.Fatalf("expected engine construction to succeed, got %v", err)
}
prepared, err := engine.Prepare(context.Background(), scriptorium.RunRequest{
PromptID: "prompt.builtin.default",
Inputs: map[string]scriptorium.ArtifactRef{
"transcript": scriptorium.Inline("Rin opens the gate."),
},
})
if err != nil {
t.Fatalf("expected built-in default profile prepare to succeed, got %v", err)
}
if prepared.SelectedProfileID != "mistral-small-3" {
t.Fatalf("unexpected selected profile: %q", prepared.SelectedProfileID)
}
}
func TestCustomProfileOverridesBuiltInProfile(t *testing.T) {
t.Setenv("OPENROUTER_API_KEY", "test-key")
profileDir := t.TempDir()
writePublicProfileFile(t, profileDir, "mistral-small-3", "http://localhost:8000/v1", "custom-model")
engine, err := scriptorium.NewEngine(scriptorium.Config{
PromptDir: "./examples/prompts",
ProfileDir: profileDir,
SchemaDir: "./examples/schemas",
})
if err != nil {
t.Fatalf("expected engine construction to succeed, got %v", err)
}
prepared, err := engine.Prepare(context.Background(), scriptorium.RunRequest{
PromptID: "generic.markdown_summary",
ProfileID: "mistral-small-3",
Inputs: map[string]scriptorium.ArtifactRef{
"transcript": scriptorium.Inline("Rin opens the gate."),
"glossary": scriptorium.Inline("gate: A guarded passage."),
},
})
if err != nil {
t.Fatalf("expected custom profile prepare to succeed, got %v", err)
}
if prepared.EffectiveModelParams.Model != "custom-model" {
t.Fatalf("expected custom profile to override built-in, got %q", prepared.EffectiveModelParams.Model)
}
}
func TestMalformedCustomProfileDoesNotFallbackToBuiltIn(t *testing.T) {
t.Setenv("OPENROUTER_API_KEY", "test-key")
profileDir := t.TempDir()
if err := os.WriteFile(filepath.Join(profileDir, "mistral-small-3.yml"), []byte(`
id: mistral-small-3
endpoint: http://localhost:8000/v1
model: custom-model
unexpected: true
`), 0o644); err != nil {
t.Fatal(err)
}
engine, err := scriptorium.NewEngine(scriptorium.Config{
PromptDir: "./examples/prompts",
ProfileDir: profileDir,
SchemaDir: "./examples/schemas",
})
if err != nil {
t.Fatalf("expected engine construction to succeed, got %v", err)
}
_, err = engine.Prepare(context.Background(), scriptorium.RunRequest{
PromptID: "generic.markdown_summary",
ProfileID: "mistral-small-3",
Inputs: map[string]scriptorium.ArtifactRef{
"transcript": scriptorium.Inline("Rin opens the gate."),
"glossary": scriptorium.Inline("gate: A guarded passage."),
},
})
if !errors.Is(err, scriptorium.ErrProfileLoad) {
t.Fatalf("expected custom profile load error, got %v", err)
}
}
func TestExtraParamsTypedNestedValuesAreCopiedAcrossPublicBoundary(t *testing.T) {
fake := &fakeLLMClient{response: &scriptorium.GenerateResponse{Content: "ok"}}
engine := newExampleEngineWithOptions(t, "./examples/schemas", scriptorium.WithLLMClient(fake))
@@ -544,6 +661,38 @@ func exampleConfig(schemaDir string) scriptorium.Config {
}
}
func writePublicPromptFile(t *testing.T, dir, id, defaultProfile string) {
t.Helper()
data := `id: ` + id + `
version: "1.0.0"
default_profile: ` + defaultProfile + `
inputs:
- name: transcript
required: true
messages:
- role: user
content: "Summarize: {{input \"transcript\"}}"
output:
format: text
validation_mode: none
repair_attempts: 0
`
if err := os.WriteFile(filepath.Join(dir, id+".yaml"), []byte(data), 0o644); err != nil {
t.Fatalf("failed to write prompt fixture: %v", err)
}
}
func writePublicProfileFile(t *testing.T, dir, id, endpoint, model string) {
t.Helper()
data := `id: ` + id + `
endpoint: ` + endpoint + `
model: ` + model + `
`
if err := os.WriteFile(filepath.Join(dir, id+".yaml"), []byte(data), 0o644); err != nil {
t.Fatalf("failed to write profile fixture: %v", err)
}
}
type fakeLLMClient struct {
response *scriptorium.GenerateResponse
err error