121 lines
3.3 KiB
Go
121 lines
3.3 KiB
Go
package processing
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestFormatOpenAIHTTPError_preservesUsefulHints(t *testing.T) {
|
|
t.Parallel()
|
|
cases := []struct {
|
|
status int
|
|
err *openAIErrorBody
|
|
want string
|
|
}{
|
|
{
|
|
status: 400,
|
|
err: &openAIErrorBody{
|
|
Message: "Unsupported parameter: 'temperature' does not support 0.2 with this model. Only the default (1) value is supported.",
|
|
Type: "invalid_request_error",
|
|
Code: "unsupported_value",
|
|
Param: "temperature",
|
|
},
|
|
want: "model rejects custom temperature",
|
|
},
|
|
{
|
|
status: 400,
|
|
err: &openAIErrorBody{
|
|
Message: "Unsupported parameter: 'max_tokens' is not supported with this model. Use 'max_completion_tokens' instead.",
|
|
Param: "max_tokens",
|
|
},
|
|
want: "model requires completion-token budget",
|
|
},
|
|
{
|
|
status: 404,
|
|
err: &openAIErrorBody{
|
|
Message: "The model `gpt-5.6-luna` does not exist or you do not have access to it.",
|
|
Code: "model_not_found",
|
|
},
|
|
want: "model not found or API key lacks access",
|
|
},
|
|
{
|
|
status: 400,
|
|
err: &openAIErrorBody{
|
|
Message: "Unsupported parameter: 'max_tokens' is not supported with this model.",
|
|
Param: "max_tokens",
|
|
Code: "unsupported_parameter",
|
|
},
|
|
want: "model rejects legacy token cap",
|
|
},
|
|
{
|
|
status: 429,
|
|
err: &openAIErrorBody{
|
|
Message: "You exceeded your current quota, please check your plan and billing details.",
|
|
Type: "insufficient_quota",
|
|
Code: "insufficient_quota",
|
|
},
|
|
want: "API billing/quota empty",
|
|
},
|
|
{
|
|
status: 429,
|
|
err: &openAIErrorBody{
|
|
Message: "Rate limit reached for requests",
|
|
Code: "rate_limit_exceeded",
|
|
},
|
|
want: "AI provider rate limited",
|
|
},
|
|
{
|
|
status: 401,
|
|
err: &openAIErrorBody{
|
|
Message: "Incorrect API key provided: sk-proj-REDACTED",
|
|
Code: "invalid_api_key",
|
|
},
|
|
want: "AI provider rejected the API key",
|
|
},
|
|
{
|
|
status: 400,
|
|
err: &openAIErrorBody{
|
|
Message: "something obscure mentioning gpt-5.6-luna",
|
|
Type: "invalid_request_error",
|
|
Code: "invalid_request_error",
|
|
Param: "messages",
|
|
},
|
|
want: "provider http 400 (invalid_request_error param=messages)",
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
got := formatOpenAIHTTPError(tc.status, tc.err)
|
|
if !strings.Contains(strings.ToLower(got), strings.ToLower(tc.want)) {
|
|
t.Fatalf("status=%d got=%q want contains %q", tc.status, got, tc.want)
|
|
}
|
|
if strings.Contains(got, "sk-") || strings.Contains(got, "gpt-5.6-luna") {
|
|
t.Fatalf("leaked secret or model id: %q", got)
|
|
}
|
|
safe := TruncateError(errString(got))
|
|
if safe == "processing_failed" {
|
|
t.Fatalf("TruncateError wiped useful hint: in=%q", got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestOpenAIErrorIsRetryableRateLimit(t *testing.T) {
|
|
t.Parallel()
|
|
if openAIErrorIsRetryableRateLimit(&openAIErrorBody{Code: "insufficient_quota", Type: "insufficient_quota"}) {
|
|
t.Fatal("quota must not retry")
|
|
}
|
|
if !openAIErrorIsRetryableRateLimit(&openAIErrorBody{Code: "rate_limit_exceeded"}) {
|
|
t.Fatal("true rate limit should retry")
|
|
}
|
|
if openAIErrorIsRetryableRateLimit(nil) {
|
|
t.Fatal("nil 429 body must not auto-retry")
|
|
}
|
|
}
|
|
|
|
func TestProbeCompleteOptions(t *testing.T) {
|
|
t.Parallel()
|
|
opts := ProbeCompleteOptions()
|
|
if opts.MaxTokens != 64 || opts.ReasoningEffort != "none" {
|
|
t.Fatalf("%+v", opts)
|
|
}
|
|
}
|