Extend prompt execution contract
This commit is contained in:
@@ -3,6 +3,7 @@ package promptexec
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"unicode/utf8"
|
||||
@@ -172,8 +173,8 @@ func TestBoundDiagnosticAndErrorText(t *testing.T) {
|
||||
if bounded[0] != "a<>b" {
|
||||
t.Fatalf("invalid UTF-8 diagnostic = %q, want replacement", bounded[0])
|
||||
}
|
||||
validation := NewValidation(ValidationFailed, "json_schema", "daily.schema.json", values)
|
||||
if len(validation.Diagnostics) != maxValidationDiagnostics || validation.Diagnostics[0] != "a<>b" {
|
||||
validation := NewValidation(ValidationFailed, "json_schema", "daily.schema.json", 2, values)
|
||||
if validation.RepairAttempts != 2 || len(validation.Diagnostics) != maxValidationDiagnostics || validation.Diagnostics[0] != "a<>b" {
|
||||
t.Fatalf("validation = %#v, want bounded diagnostics", validation)
|
||||
}
|
||||
|
||||
@@ -187,8 +188,53 @@ func TestBoundDiagnosticAndErrorText(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerationErrorKeepsProviderDetailsOutOfRoutineFormatting(t *testing.T) {
|
||||
cause := errors.New("provider response must stay hidden")
|
||||
error := NewGenerationError(
|
||||
429,
|
||||
string([]byte{'c', 0xff})+strings.Repeat("界", 300),
|
||||
strings.Repeat("type", 100),
|
||||
string([]byte{'m', 0xff})+strings.Repeat("界", 4_200),
|
||||
cause,
|
||||
)
|
||||
if error.StatusCode() != 429 || error.Category() != Generation || CategoryOf(error) != Generation {
|
||||
t.Fatalf("generation error identity = %#v", error)
|
||||
}
|
||||
if utf8.RuneCountInString(error.ProviderCode()) != 256 || utf8.RuneCountInString(error.ProviderType()) != 256 || utf8.RuneCountInString(error.ProviderMessage()) != 4096 {
|
||||
t.Fatalf("provider detail bounds = %d/%d/%d", utf8.RuneCountInString(error.ProviderCode()), utf8.RuneCountInString(error.ProviderType()), utf8.RuneCountInString(error.ProviderMessage()))
|
||||
}
|
||||
if !utf8.ValidString(error.ProviderCode()) || !utf8.ValidString(error.ProviderType()) || !utf8.ValidString(error.ProviderMessage()) {
|
||||
t.Fatalf("provider details are not valid UTF-8: %#v", error)
|
||||
}
|
||||
if !errors.Is(error, cause) {
|
||||
t.Fatal("errors.Is() = false, want preserved dependency cause")
|
||||
}
|
||||
var owned *Error
|
||||
if !errors.As(error, &owned) || owned.Category() != Generation {
|
||||
t.Fatalf("errors.As(*Error) = %#v, want project-owned generation error", owned)
|
||||
}
|
||||
want := "generation: provider generation failed (HTTP 429)"
|
||||
if error.Error() != want || fmt.Sprintf("%#v", error) != want {
|
||||
t.Fatalf("ordinary formatting = %q / %#v, want %q", error.Error(), error, want)
|
||||
}
|
||||
for _, private := range []string{cause.Error(), error.ProviderCode(), error.ProviderType(), error.ProviderMessage()} {
|
||||
if strings.Contains(error.Error(), private) || strings.Contains(fmt.Sprintf("%#v", error), private) {
|
||||
t.Fatalf("generation error leaks provider detail %q", private)
|
||||
}
|
||||
}
|
||||
|
||||
statusOnly := NewGenerationError(503, "", "", "", nil)
|
||||
if statusOnly.Error() != "generation: provider generation failed (HTTP 503)" {
|
||||
t.Fatalf("status-only error = %q", statusOnly)
|
||||
}
|
||||
var nilError *GenerationError
|
||||
if nilError.StatusCode() != 0 || nilError.ProviderCode() != "" || nilError.ProviderType() != "" || nilError.ProviderMessage() != "" || nilError.Category() != Generation || nilError.Error() != "" || nilError.GoString() != "" || nilError.Unwrap() != nil {
|
||||
t.Fatalf("nil generation error = %#v", nilError)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContractCopiesMutableValues(t *testing.T) {
|
||||
preparation := Preparation{InputHashes: map[string]string{"data_package": "input-hash"}}
|
||||
preparation := Preparation{InputHashes: map[string]string{"data_package": "input-hash"}, Output: OutputContract{RepairAttempts: 3}}
|
||||
preparationDebug := &PreparationDebug{
|
||||
RenderedMessages: []RenderedMessage{{Role: "user", Content: "rendered input"}},
|
||||
StructuredSchema: []byte("schema body"),
|
||||
@@ -196,7 +242,7 @@ func TestContractCopiesMutableValues(t *testing.T) {
|
||||
}
|
||||
execution := Execution{
|
||||
InputHashes: map[string]string{"data_package": "input-hash"},
|
||||
Validation: Validation{Diagnostics: []string{"validation detail"}},
|
||||
Validation: Validation{RepairAttempts: 2, Diagnostics: []string{"validation detail"}},
|
||||
RawOutput: []byte("generated output"),
|
||||
Debug: &ExecutionDebug{
|
||||
RawOutput: []byte("provider output"),
|
||||
@@ -217,13 +263,13 @@ func TestContractCopiesMutableValues(t *testing.T) {
|
||||
execution.Debug.RawOutput[0] = 'x'
|
||||
execution.Debug.ValidationDiagnostics[0] = "changed"
|
||||
|
||||
if preparationCopy.InputHashes["data_package"] != "input-hash" {
|
||||
if preparationCopy.InputHashes["data_package"] != "input-hash" || preparationCopy.Output.RepairAttempts != 3 {
|
||||
t.Fatalf("preparation copy = %#v", preparationCopy)
|
||||
}
|
||||
if debugCopy.RenderedMessages[0].Content != "rendered input" || string(debugCopy.StructuredSchema) != "schema body" || string(debugCopy.ParametersJSON) != `{"temperature":0.2}` {
|
||||
t.Fatalf("preparation debug copy = %#v", debugCopy)
|
||||
}
|
||||
if executionCopy.InputHashes["data_package"] != "input-hash" || executionCopy.Validation.Diagnostics[0] != "validation detail" || string(executionCopy.RawOutput) != "generated output" || string(executionCopy.Debug.RawOutput) != "provider output" || executionCopy.Debug.ValidationDiagnostics[0] != "detailed validation" {
|
||||
if executionCopy.InputHashes["data_package"] != "input-hash" || executionCopy.Validation.RepairAttempts != 2 || executionCopy.Validation.Diagnostics[0] != "validation detail" || string(executionCopy.RawOutput) != "generated output" || string(executionCopy.Debug.RawOutput) != "provider output" || executionCopy.Debug.ValidationDiagnostics[0] != "detailed validation" {
|
||||
t.Fatalf("execution copy = %#v", executionCopy)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user