- Chat 接口拒绝 n>1(此前静默丢弃多余 choice),返回 400 结构化错误 - Responses 接口透传 text.format(json_schema / json_object),三种接口协议对齐 - TLS 指纹统一升级到 Chrome_150(internal/httpx.DefaultProfile),与 UA 匹配 - metrics 落盘失败不再静默:Save() 返回错误并打日志,临时文件失败会清理 - GET /api/config 脱敏 admin.password 与 turnstile.api_key(控制台从不展示, 不应随 5s 轮询下发);PUT 改走 ReplaceJSON,先校验后替换、失败回滚 - set_limits / set_turnstile 改指针部分更新:缺字段保持现状,不会把并发、 限流或求解开关按零值清掉 - 读请求体统一 64MB 上限;配置写盘原子替换 + 0600 权限 - main.go 改为 run() 返回退出码:日志落盘、指标落盘、xray 子进程回收全部 挂 defer,任何退出路径(含启动失败)都会执行,杜绝孤儿 xray - proxypool / turnstile / upstream / openai / config / httpx / logbuf 等 逐项补红绿回归测试,新增 14 个测试文件,race 下全绿
56 lines
1.9 KiB
Go
56 lines
1.9 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/nyoungo/dsfree2api/internal/openai"
|
|
)
|
|
|
|
// 回归:Responses API 的 text.format 必须转成提示词里的输出格式约束。
|
|
// 之前 ResponsesRequest 根本不解析 text 字段,客户端指定的 json_schema
|
|
// 被静默丢弃 —— 模型可以随便输出非 JSON,客户端的 schema 校验必炸。
|
|
func TestResponsesTextFormatBecomesPromptConstraint(t *testing.T) {
|
|
body := `{"model":"m","input":"hi",` +
|
|
`"text":{"format":{"type":"json_schema",` +
|
|
`"json_schema":{"name":"addr","schema":{"type":"object",` +
|
|
`"properties":{"city":{"type":"string"}},"required":["city"]}}}}}`
|
|
var req openai.ResponsesRequest
|
|
if err := json.Unmarshal([]byte(body), &req); err != nil {
|
|
t.Fatalf("unmarshal: %v", err)
|
|
}
|
|
if req.Text == nil || req.Text.Format == nil {
|
|
t.Fatalf("text.format 没解析出来: %+v", req.Text)
|
|
}
|
|
|
|
messages, err := openai.ResponsesToMessages(&req)
|
|
if err != nil {
|
|
t.Fatalf("responses to messages: %v", err)
|
|
}
|
|
prompt := openai.BuildPrompt(messages, responsesPromptOptions(&req, nil))
|
|
|
|
if !strings.Contains(prompt, "JSON Schema") {
|
|
t.Fatalf("提示词里没有 schema 约束: %q", prompt)
|
|
}
|
|
if !strings.Contains(prompt, "city") {
|
|
t.Fatalf("提示词里没有 schema 内容: %q", prompt)
|
|
}
|
|
}
|
|
|
|
// 回归:没有 text.format 的请求照常工作,不能凭空多出约束。
|
|
func TestResponsesWithoutTextFormatHasNoConstraint(t *testing.T) {
|
|
var req openai.ResponsesRequest
|
|
if err := json.Unmarshal([]byte(`{"model":"m","input":"hi"}`), &req); err != nil {
|
|
t.Fatalf("unmarshal: %v", err)
|
|
}
|
|
messages, err := openai.ResponsesToMessages(&req)
|
|
if err != nil {
|
|
t.Fatalf("responses to messages: %v", err)
|
|
}
|
|
prompt := openai.BuildPrompt(messages, responsesPromptOptions(&req, nil))
|
|
if strings.Contains(prompt, "JSON Schema") {
|
|
t.Fatalf("没有 text.format 却出现了 schema 约束: %q", prompt)
|
|
}
|
|
}
|