1
0

feat: 重构配置生命周期为 Authoring/Normalized/Resolved 三层

将变量替换和 expect 简写展开统一放入 Normalized 阶段,
运行时 AJV 使用 Normalized schema,导出 schema 面向 Authoring Config。

主要变更:
- 新增 normalizer.ts 实现 normalizeAuthoringConfig()
- 拆分 Authoring/Normalized 双 schema,checker 接口支持 authoring/normalized 片段
- config-loader 流程:normalize → Normalized AJV → semantic → resolve
- validator 兼容层自动分派 raw/normalized expect 形态
- 删除 rawExpect,store.expect 列写入 null
- Authoring schema 对 integer/boolean/enum 字段接受变量引用
- 修复 DB/HTTP validate 入口守卫和 LLM options integer 变量引用
- 优化 compact() 避免 undefined 覆盖隐患
- 移除 content.ts 恒为 true 的前置条件
- 同步 5 个主规范并归档 change
This commit is contained in:
2026-05-22 14:00:47 +08:00
parent 6e53c8130d
commit cf847ccd7a
56 changed files with 1717 additions and 656 deletions

View File

@@ -14,8 +14,16 @@
"type": "object",
"properties": {
"maxConcurrentChecks": {
"minimum": 1,
"type": "integer"
"anyOf": [
{
"minimum": 1,
"type": "integer"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
}
}
@@ -33,9 +41,17 @@
"type": "string"
},
"port": {
"maximum": 65535,
"minimum": 0,
"type": "integer"
"anyOf": [
{
"maximum": 65535,
"minimum": 0,
"type": "integer"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
}
},
@@ -50,27 +66,35 @@
"level": {
"anyOf": [
{
"const": "trace",
"type": "string"
"anyOf": [
{
"const": "trace",
"type": "string"
},
{
"const": "debug",
"type": "string"
},
{
"const": "info",
"type": "string"
},
{
"const": "warn",
"type": "string"
},
{
"const": "error",
"type": "string"
},
{
"const": "fatal",
"type": "string"
}
]
},
{
"const": "debug",
"type": "string"
},
{
"const": "info",
"type": "string"
},
{
"const": "warn",
"type": "string"
},
{
"const": "error",
"type": "string"
},
{
"const": "fatal",
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
@@ -84,27 +108,35 @@
"level": {
"anyOf": [
{
"const": "trace",
"type": "string"
"anyOf": [
{
"const": "trace",
"type": "string"
},
{
"const": "debug",
"type": "string"
},
{
"const": "info",
"type": "string"
},
{
"const": "warn",
"type": "string"
},
{
"const": "error",
"type": "string"
},
{
"const": "fatal",
"type": "string"
}
]
},
{
"const": "debug",
"type": "string"
},
{
"const": "info",
"type": "string"
},
{
"const": "warn",
"type": "string"
},
{
"const": "error",
"type": "string"
},
{
"const": "fatal",
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
@@ -120,22 +152,38 @@
"frequency": {
"anyOf": [
{
"const": "hourly",
"type": "string"
"anyOf": [
{
"const": "hourly",
"type": "string"
},
{
"const": "daily",
"type": "string"
},
{
"const": "weekly",
"type": "string"
}
]
},
{
"const": "daily",
"type": "string"
},
{
"const": "weekly",
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"maxFiles": {
"minimum": 1,
"type": "integer"
"anyOf": [
{
"minimum": 1,
"type": "integer"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"size": {
"anyOf": [
@@ -155,27 +203,35 @@
"level": {
"anyOf": [
{
"const": "trace",
"type": "string"
"anyOf": [
{
"const": "trace",
"type": "string"
},
{
"const": "debug",
"type": "string"
},
{
"const": "info",
"type": "string"
},
{
"const": "warn",
"type": "string"
},
{
"const": "error",
"type": "string"
},
{
"const": "fatal",
"type": "string"
}
]
},
{
"const": "debug",
"type": "string"
},
{
"const": "info",
"type": "string"
},
{
"const": "warn",
"type": "string"
},
{
"const": "error",
"type": "string"
},
{
"const": "fatal",
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
@@ -216,8 +272,16 @@
"type": "null"
},
{
"maxLength": 500,
"type": "string"
"anyOf": [
{
"maxLength": 500,
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
]
},
@@ -656,9 +720,17 @@
"type": "null"
},
{
"maxLength": 30,
"minLength": 1,
"type": "string"
"anyOf": [
{
"maxLength": 30,
"minLength": 1,
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
]
},
@@ -681,12 +753,28 @@
},
"headers": {
"additionalProperties": {
"type": "string"
"anyOf": [
{
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"type": "object"
},
"ignoreSSL": {
"type": "boolean"
"anyOf": [
{
"type": "boolean"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"maxBodyBytes": {
"anyOf": [
@@ -700,37 +788,53 @@
]
},
"maxRedirects": {
"minimum": 0,
"type": "integer"
"anyOf": [
{
"minimum": 0,
"type": "integer"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"method": {
"anyOf": [
{
"const": "DELETE",
"type": "string"
"anyOf": [
{
"const": "DELETE",
"type": "string"
},
{
"const": "GET",
"type": "string"
},
{
"const": "HEAD",
"type": "string"
},
{
"const": "OPTIONS",
"type": "string"
},
{
"const": "PATCH",
"type": "string"
},
{
"const": "POST",
"type": "string"
},
{
"const": "PUT",
"type": "string"
}
]
},
{
"const": "GET",
"type": "string"
},
{
"const": "HEAD",
"type": "string"
},
{
"const": "OPTIONS",
"type": "string"
},
{
"const": "PATCH",
"type": "string"
},
{
"const": "POST",
"type": "string"
},
{
"const": "PUT",
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
@@ -758,8 +862,16 @@
"type": "null"
},
{
"maxLength": 500,
"type": "string"
"anyOf": [
{
"maxLength": 500,
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
]
},
@@ -1353,9 +1465,17 @@
"type": "null"
},
{
"maxLength": 30,
"minLength": 1,
"type": "string"
"anyOf": [
{
"maxLength": 30,
"minLength": 1,
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
]
},
@@ -1422,8 +1542,16 @@
"type": "null"
},
{
"maxLength": 500,
"type": "string"
"anyOf": [
{
"maxLength": 500,
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
]
},
@@ -1924,9 +2052,17 @@
"type": "null"
},
{
"maxLength": 30,
"minLength": 1,
"type": "string"
"anyOf": [
{
"maxLength": 30,
"minLength": 1,
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
]
},
@@ -1971,8 +2107,16 @@
"type": "null"
},
{
"maxLength": 500,
"type": "string"
"anyOf": [
{
"maxLength": 500,
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
]
},
@@ -2224,7 +2368,15 @@
}
},
"connected": {
"type": "boolean"
"anyOf": [
{
"type": "boolean"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"durationMs": {
"anyOf": [
@@ -2320,9 +2472,17 @@
"type": "null"
},
{
"maxLength": 30,
"minLength": 1,
"type": "string"
"anyOf": [
{
"maxLength": 30,
"minLength": 1,
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
]
},
@@ -2361,12 +2521,28 @@
]
},
"port": {
"maximum": 65535,
"minimum": 1,
"type": "integer"
"anyOf": [
{
"maximum": 65535,
"minimum": 1,
"type": "integer"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"readBanner": {
"type": "boolean"
"anyOf": [
{
"type": "boolean"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
}
}
@@ -2387,8 +2563,16 @@
"type": "null"
},
{
"maxLength": 500,
"type": "string"
"anyOf": [
{
"maxLength": 500,
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
]
},
@@ -2397,7 +2581,15 @@
"type": "object",
"properties": {
"alive": {
"type": "boolean"
"anyOf": [
{
"type": "boolean"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"avgLatencyMs": {
"anyOf": [
@@ -2718,9 +2910,17 @@
"type": "null"
},
{
"maxLength": 30,
"minLength": 1,
"type": "string"
"anyOf": [
{
"maxLength": 30,
"minLength": 1,
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
]
},
@@ -2739,18 +2939,34 @@
],
"properties": {
"count": {
"maximum": 100,
"minimum": 1,
"type": "integer"
"anyOf": [
{
"maximum": 100,
"minimum": 1,
"type": "integer"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"host": {
"minLength": 1,
"type": "string"
},
"packetSize": {
"maximum": 65500,
"minimum": 1,
"type": "integer"
"anyOf": [
{
"maximum": 65500,
"minimum": 1,
"type": "integer"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
}
}
@@ -2771,8 +2987,16 @@
"type": "null"
},
{
"maxLength": 500,
"type": "string"
"anyOf": [
{
"maxLength": 500,
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
]
},
@@ -2856,7 +3080,15 @@
]
},
"responded": {
"type": "boolean"
"anyOf": [
{
"type": "boolean"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"response": {
"type": "array",
@@ -3345,9 +3577,17 @@
"type": "null"
},
{
"maxLength": 30,
"minLength": 1,
"type": "string"
"anyOf": [
{
"maxLength": 30,
"minLength": 1,
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
]
},
@@ -3369,15 +3609,23 @@
"encoding": {
"anyOf": [
{
"const": "text",
"type": "string"
"anyOf": [
{
"const": "text",
"type": "string"
},
{
"const": "hex",
"type": "string"
},
{
"const": "base64",
"type": "string"
}
]
},
{
"const": "hex",
"type": "string"
},
{
"const": "base64",
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
@@ -3401,22 +3649,38 @@
"type": "string"
},
"port": {
"maximum": 65535,
"minimum": 1,
"type": "integer"
"anyOf": [
{
"maximum": 65535,
"minimum": 1,
"type": "integer"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"responseEncoding": {
"anyOf": [
{
"const": "text",
"type": "string"
"anyOf": [
{
"const": "text",
"type": "string"
},
{
"const": "hex",
"type": "string"
},
{
"const": "base64",
"type": "string"
}
]
},
{
"const": "hex",
"type": "string"
},
{
"const": "base64",
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
@@ -3440,8 +3704,16 @@
"type": "null"
},
{
"maxLength": 500,
"type": "string"
"anyOf": [
{
"maxLength": 500,
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
]
},
@@ -4016,7 +4288,15 @@
"type": "object",
"properties": {
"completed": {
"type": "boolean"
"anyOf": [
{
"type": "boolean"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"firstTokenMs": {
"anyOf": [
@@ -4345,9 +4625,17 @@
"type": "null"
},
{
"maxLength": 30,
"minLength": 1,
"type": "string"
"anyOf": [
{
"maxLength": 30,
"minLength": 1,
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
}
]
},
@@ -4373,12 +4661,28 @@
},
"headers": {
"additionalProperties": {
"type": "string"
"anyOf": [
{
"type": "string"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"type": "object"
},
"ignoreSSL": {
"type": "boolean"
"anyOf": [
{
"type": "boolean"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"key": {
"type": "string"
@@ -4386,11 +4690,19 @@
"mode": {
"anyOf": [
{
"const": "http",
"type": "string"
"anyOf": [
{
"const": "http",
"type": "string"
},
{
"const": "stream",
"type": "string"
}
]
},
{
"const": "stream",
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
@@ -4407,8 +4719,16 @@
"type": "number"
},
"maxOutputTokens": {
"minimum": 1,
"type": "integer"
"anyOf": [
{
"minimum": 1,
"type": "integer"
},
{
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]
},
"presencePenalty": {
"type": "number"
@@ -4440,15 +4760,23 @@
"provider": {
"anyOf": [
{
"const": "openai",
"type": "string"
"anyOf": [
{
"const": "openai",
"type": "string"
},
{
"const": "openai-responses",
"type": "string"
},
{
"const": "anthropic",
"type": "string"
}
]
},
{
"const": "openai-responses",
"type": "string"
},
{
"const": "anthropic",
"pattern": "^\\$\\{[^}]+\\}$",
"type": "string"
}
]