{
  "cases": [
    {
      "expected": {
        "ok": {
          "bundle": false,
          "profiles": [
            {
              "apiKey": "sk-1",
              "baseUrl": "https://api.deepseek.com/v1",
              "model": "deepseek-flash",
              "modelFallback": false,
              "name": "DeepSeek",
              "protocol": "openai_compatible",
              "rawProvider": "openai"
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":{\"name\":\"DeepSeek\",\"provider\":\"openai\",\"baseURL\":\"https://api.deepseek.com/v1\",\"apiKey\":\"sk-1\",\"model\":\"deepseek-flash\"}}"
      },
      "name": "规范单条"
    },
    {
      "expected": {
        "ok": {
          "bundle": false,
          "profiles": [
            {
              "apiKey": "k",
              "baseUrl": "https://a/v1",
              "model": "m",
              "modelFallback": false,
              "name": "x",
              "protocol": "openai_compatible",
              "rawProvider": ""
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":{\"name\":\"x\",\"baseUrl\":\"https://a/v1\",\"apiKey\":\"k\",\"model\":\"m\"}}"
      },
      "name": "字段别名 baseUrl"
    },
    {
      "expected": {
        "ok": {
          "bundle": false,
          "profiles": [
            {
              "apiKey": "k",
              "baseUrl": "https://a/v1",
              "model": "m",
              "modelFallback": false,
              "name": "x",
              "protocol": "openai_compatible",
              "rawProvider": ""
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":{\"name\":\"x\",\"base_url\":\"https://a/v1\",\"api_key\":\"k\",\"model\":\"m\"}}"
      },
      "name": "字段别名 base_url / api_key"
    },
    {
      "expected": {
        "ok": {
          "bundle": false,
          "profiles": [
            {
              "apiKey": "sk-1",
              "baseUrl": "https://a/v1",
              "model": "deepseek-flash",
              "modelFallback": true,
              "name": "x",
              "protocol": "openai_compatible",
              "rawProvider": ""
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":{\"name\":\"x\",\"baseURL\":\"https://a/v1\",\"apiKey\":\"sk-1\"}}"
      },
      "name": "没给 model：用兜底值"
    },
    {
      "expected": {
        "ok": {
          "bundle": false,
          "profiles": [
            {
              "apiKey": "sk-x",
              "baseUrl": "https://relay.example.com",
              "model": "claude-opus-5",
              "modelFallback": false,
              "name": "中转",
              "protocol": "anthropic",
              "rawProvider": "anthropic"
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":{\"name\":\"中转\",\"provider\":\"anthropic\",\"baseURL\":\"https://relay.example.com\",\"apiKey\":\"sk-x\",\"model\":\"claude-opus-5\"}}"
      },
      "name": "Anthropic 只填主机名"
    },
    {
      "expected": {
        "ok": {
          "bundle": false,
          "profiles": [
            {
              "apiKey": "k",
              "baseUrl": "https://a",
              "model": "claude-sonnet-5",
              "modelFallback": false,
              "name": "x",
              "protocol": "anthropic",
              "rawProvider": "custom"
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":{\"name\":\"x\",\"provider\":\"custom\",\"baseURL\":\"https://a\",\"apiKey\":\"k\",\"model\":\"claude-sonnet-5\"}}"
      },
      "name": "model 名推断 Anthropic"
    },
    {
      "expected": {
        "ok": {
          "bundle": true,
          "profiles": [
            {
              "apiKey": "k1",
              "baseUrl": "https://api.deepseek.com/v1",
              "model": "deepseek-flash",
              "modelFallback": false,
              "name": "a",
              "protocol": "openai_compatible",
              "rawProvider": "deepseek"
            },
            {
              "apiKey": "k2",
              "baseUrl": "https://api.anthropic.com/v1",
              "model": "claude-opus-5",
              "modelFallback": false,
              "name": "b",
              "protocol": "anthropic",
              "rawProvider": "anthropic"
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile.bundle\",\"v\":1,\"data\":{\"profiles\":[{\"name\":\"a\",\"provider\":\"deepseek\",\"baseURL\":\"https://api.deepseek.com/v1\",\"apiKey\":\"k1\",\"model\":\"deepseek-flash\"},{\"name\":\"b\",\"provider\":\"anthropic\",\"baseUrl\":\"https://api.anthropic.com/v1\",\"apiKey\":\"k2\",\"model\":\"claude-opus-5\"}]}}"
      },
      "name": "规范打包"
    },
    {
      "expected": {
        "ok": {
          "bundle": true,
          "profiles": [
            {
              "apiKey": "sk-ds",
              "baseUrl": "https://api.deepseek.com/v1",
              "model": "deepseek-flash",
              "modelFallback": false,
              "name": "DeepSeek",
              "protocol": "openai_compatible",
              "rawProvider": "deepseek"
            }
          ],
          "skipped": 1
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile.bundle\",\"v\":1,\"data\":{\"api_profiles\":[{\"name\":\"登录\",\"auth_type\":\"oauth\",\"model\":\"gpt-6\"},{\"name\":\"DeepSeek\",\"provider\":\"deepseek\",\"api_key\":\"sk-ds\",\"base_url\":\"https://api.deepseek.com/v1\",\"model\":\"deepseek-flash\",\"auth_type\":\"api_key\"}]}}"
      },
      "name": "打包：OAuth 条目跳过"
    },
    {
      "expected": {
        "error": {
          "code": "empty_bundle",
          "skipped": 1
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile.bundle\",\"v\":1,\"data\":{\"api_profiles\":[{\"name\":\"x\",\"auth_type\":\"oauth\"}]}}"
      },
      "name": "打包：全是 OAuth"
    },
    {
      "expected": {
        "error": {
          "code": "unsupported_version",
          "found": 99,
          "supported": 1
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":99,\"data\":{\"model\":\"m\"}}"
      },
      "name": "更高版本"
    },
    {
      "expected": {
        "error": {
          "code": "not_ai_profile",
          "found": ""
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"hello\":\"world\"}"
      },
      "name": "不是 ai.profile"
    },
    {
      "expected": {
        "error": {
          "code": "empty"
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": ""
      },
      "name": "空内容"
    },
    {
      "expected": {
        "error": {
          "code": "empty"
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "  \n\t "
      },
      "name": "只有空白"
    },
    {
      "expected": {
        "error": {
          "code": "invalid_json",
          "detail": "expected value at line 1 column 1"
        }
      },
      "fn": "parse_profiles",
      "ignore": [
        "error.detail"
      ],
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "kind: ai.profile"
      },
      "name": "不是 JSON"
    },
    {
      "expected": {
        "error": {
          "code": "invalid_json",
          "detail": "顶层必须是 JSON 对象"
        }
      },
      "fn": "parse_profiles",
      "ignore": [
        "error.detail"
      ],
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "[1, 2]"
      },
      "name": "JSON 但不是对象"
    },
    {
      "expected": {
        "error": {
          "code": "unsupported_version",
          "found": 99,
          "supported": 1
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"something.else\",\"v\":99}"
      },
      "name": "版本先于 kind 检查"
    },
    {
      "expected": {
        "error": {
          "code": "missing_data"
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":\"x\"}"
      },
      "name": "data 不是对象"
    },
    {
      "expected": {
        "ok": {
          "bundle": false,
          "profiles": [
            {
              "apiKey": "k",
              "baseUrl": "https://a/v1",
              "model": "deepseek-flash",
              "modelFallback": true,
              "name": "x",
              "protocol": "openai_compatible",
              "rawProvider": ""
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":{\"name\":\"x\",\"baseURL\":\"https://a/v1\",\"apiKey\":\"k\",\"model\":\"\"}}"
      },
      "name": "model 为空串：等同没给"
    },
    {
      "expected": {
        "ok": {
          "bundle": false,
          "profiles": [
            {
              "apiKey": "k",
              "baseUrl": "https://a/v1",
              "model": "m",
              "modelFallback": false,
              "name": "x",
              "protocol": "openai_compatible",
              "rawProvider": ""
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":{\"name\":\"  x  \",\"baseURL\":\"  https://a/v1  \",\"apiKey\":\"  k  \",\"model\":\"  m  \"}}"
      },
      "name": "字段两端空白"
    },
    {
      "expected": {
        "error": {
          "code": "empty_bundle",
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile.bundle\",\"v\":1,\"data\":{}}"
      },
      "name": "打包缺 profiles 字段"
    },
    {
      "expected": {
        "error": {
          "code": "invalid_json",
          "detail": "顶层必须是 JSON 对象"
        }
      },
      "fn": "parse_profiles",
      "ignore": [
        "error.detail"
      ],
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "[\"ai.profile\",1,{\"name\":\"x\",\"baseURL\":\"https://a/v1\",\"apiKey\":\"k\",\"model\":\"m\"}]"
      },
      "name": "信封写成数组（按字段顺序）"
    },
    {
      "expected": {
        "error": {
          "code": "invalid_json",
          "detail": "invalid type: string \"1\", expected u32"
        }
      },
      "fn": "parse_profiles",
      "ignore": [
        "error.detail"
      ],
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":\"1\",\"data\":{}}"
      },
      "name": "v 写成字符串"
    },
    {
      "expected": {
        "ok": {
          "bundle": false,
          "profiles": [
            {
              "apiKey": "k",
              "baseUrl": "https://a/v1",
              "model": "m",
              "modelFallback": false,
              "name": "x",
              "protocol": "openai_compatible",
              "rawProvider": ""
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"data\":{\"name\":\"x\",\"baseURL\":\"https://a/v1\",\"apiKey\":\"k\",\"model\":\"m\"}}"
      },
      "name": "v 缺失：按当前版本处理"
    },
    {
      "expected": {
        "error": {
          "code": "invalid_json",
          "detail": "duplicate field `baseURL`"
        }
      },
      "fn": "parse_profiles",
      "ignore": [
        "error.detail"
      ],
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":{\"name\":\"x\",\"baseURL\":\"https://a/v1\",\"base_url\":\"https://b/v1\",\"apiKey\":\"k\",\"model\":\"m\"}}"
      },
      "name": "同一字段的别名同时出现"
    },
    {
      "expected": {
        "error": {
          "code": "invalid_json",
          "detail": "duplicate field `profiles`"
        }
      },
      "fn": "parse_profiles",
      "ignore": [
        "error.detail"
      ],
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile.bundle\",\"v\":1,\"data\":{\"profiles\":[{\"name\":\"a\",\"baseURL\":\"https://a/v1\",\"apiKey\":\"k\",\"model\":\"m\"}],\"api_profiles\":[{\"name\":\"b\",\"baseURL\":\"https://b/v1\",\"apiKey\":\"k\",\"model\":\"m\"}]}}"
      },
      "name": "打包里 profiles 与 api_profiles 同时出现"
    },
    {
      "expected": {
        "ok": {
          "bundle": false,
          "profiles": [
            {
              "apiKey": "k",
              "baseUrl": "https://a/v1",
              "model": "m",
              "modelFallback": false,
              "name": "x",
              "protocol": "openai_compatible",
              "rawProvider": ""
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":{\"name\":\"x\",\"baseURL\":\"https://a/v1\",\"apiKey\":\"k\",\"model\":\"m\",\"auth_type\":\"oauth\"}}"
      },
      "name": "单条带 auth_type: oauth（跳过规则只对打包生效）"
    },
    {
      "expected": {
        "error": {
          "code": "invalid_json",
          "detail": "invalid type: integer `123`, expected a string"
        }
      },
      "fn": "parse_profiles",
      "ignore": [
        "error.detail"
      ],
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":{\"name\":123,\"baseURL\":\"https://a/v1\"}}"
      },
      "name": "字段类型不对（name 是数字）"
    },
    {
      "expected": {
        "ok": {
          "bundle": false,
          "profiles": [
            {
              "apiKey": "k",
              "baseUrl": "https://a",
              "model": "m",
              "modelFallback": false,
              "name": "x",
              "protocol": "anthropic",
              "rawProvider": ""
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":{\"name\":\"x\",\"baseURL\":\"https://a\",\"apiKey\":\"k\",\"model\":\"m\",\"hints\":{\"tool_id\":\"claude-code\"}}}"
      },
      "name": "hints 里的 tool_id 别名"
    },
    {
      "expected": {
        "error": {
          "code": "invalid_json",
          "detail": "invalid type: string \"x\", expected a sequence"
        }
      },
      "fn": "parse_profiles",
      "ignore": [
        "error.detail"
      ],
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile.bundle\",\"v\":1,\"data\":{\"profiles\":\"x\"}}"
      },
      "name": "打包的 profiles 不是数组"
    },
    {
      "expected": {
        "error": {
          "code": "invalid_json",
          "detail": "invalid type: string \"x\", expected struct BundleData"
        }
      },
      "fn": "parse_profiles",
      "ignore": [
        "error.detail"
      ],
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile.bundle\",\"v\":1,\"data\":\"x\"}"
      },
      "name": "打包的 data 不是对象"
    },
    {
      "expected": {
        "error": {
          "code": "invalid_json",
          "detail": "invalid type: integer `123`, expected a string"
        }
      },
      "fn": "parse_profiles",
      "ignore": [
        "error.detail"
      ],
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile.bundle\",\"v\":1,\"data\":{\"profiles\":[{\"name\":\"a\",\"baseURL\":\"https://a/v1\",\"apiKey\":\"k\",\"model\":\"m\"},{\"name\":123}]}}"
      },
      "name": "打包里某一条字段类型不对：整个打包失败"
    },
    {
      "expected": {
        "ok": {
          "bundle": true,
          "profiles": [
            {
              "apiKey": "k",
              "baseUrl": "https://a/v1",
              "model": "m",
              "modelFallback": false,
              "name": "a",
              "protocol": "openai_compatible",
              "rawProvider": ""
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile.bundle\",\"v\":1,\"data\":{\"profiles\":[1,{\"name\":\"a\",\"baseURL\":\"https://a/v1\",\"apiKey\":\"k\",\"model\":\"m\"}]}}"
      },
      "name": "打包里有不是对象的条目"
    },
    {
      "expected": {
        "ok": {
          "bundle": false,
          "profiles": [
            {
              "apiKey": "k",
              "baseUrl": "https://a/v1",
              "model": "claude-opus-5",
              "modelFallback": true,
              "name": "x",
              "protocol": "openai_compatible",
              "rawProvider": ""
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "claude-opus-5",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":{\"name\":\"x\",\"baseURL\":\"https://a/v1\",\"apiKey\":\"k\"}}"
      },
      "name": "推断协议只看原始 model，不看兜底值"
    },
    {
      "expected": {
        "ok": {
          "bundle": false,
          "profiles": [
            {
              "apiKey": "k",
              "baseUrl": "https://a",
              "model": "m",
              "modelFallback": false,
              "name": "x",
              "protocol": "anthropic",
              "rawProvider": ""
            }
          ],
          "skipped": 0
        }
      },
      "fn": "parse_profiles",
      "input": {
        "defaultModel": "deepseek-flash",
        "text": "{\"kind\":\"ai.profile\",\"v\":1,\"data\":{\"name\":\"x\",\"baseURL\":\"https://a\",\"apiKey\":\"k\",\"model\":\"m\",\"hints\":{\"toolId\":\"claude-code\"}}}"
      },
      "name": "toolId 提示也参与推断"
    },
    {
      "expected": {
        "data": {
          "apiKey": "sk-示例",
          "baseURL": "https://api.deepseek.com/v1",
          "model": "some-model",
          "name": "示例",
          "provider": "openai"
        },
        "kind": "ai.profile",
        "v": 1
      },
      "fn": "to_profile",
      "input": {
        "apiKey": "sk-示例",
        "baseUrl": "https://api.deepseek.com/v1",
        "model": "some-model",
        "name": "示例",
        "protocol": "openai_compatible"
      }
    },
    {
      "expected": {
        "data": {
          "apiKey": "sk-示例",
          "baseURL": "https://api.anthropic.com/v1",
          "model": "some-model",
          "name": "示例",
          "provider": "anthropic"
        },
        "kind": "ai.profile",
        "v": 1
      },
      "fn": "to_profile",
      "input": {
        "apiKey": "sk-示例",
        "baseUrl": "https://api.anthropic.com/v1",
        "model": "some-model",
        "name": "示例",
        "protocol": "anthropic"
      }
    },
    {
      "expected": {
        "data": {
          "apiKey": "sk-示例",
          "baseURL": "https://api.deepseek.com/v1",
          "model": "",
          "name": "示例",
          "provider": "openai"
        },
        "kind": "ai.profile",
        "v": 1
      },
      "fn": "to_profile",
      "input": {
        "apiKey": "sk-示例",
        "baseUrl": "https://api.deepseek.com/v1",
        "model": "",
        "name": "示例",
        "protocol": "openai_compatible"
      }
    }
  ],
  "crateVersion": "0.1.2",
  "description": "parse_profiles 检查顺序：① 去两端空白后为空 → empty；② 不是合法 JSON、或顶层不是对象（数组也不行）→ invalid_json；③ 信封字段类型不对 → invalid_json：kind 须为字符串（缺失当空串）、v 须为非负整数（缺失当 1；写成字符串 \"1\" 也不行）；④ v 大于 1 → unsupported_version（先于 kind 检查）；⑤ kind 既不是 ai.profile 也不是 ai.profile.bundle → not_ai_profile（found 为读到的 kind，缺失为空串）；⑥ data 缺失 → missing_data；单条的 data 不是对象 → missing_data，打包的 data 不是对象 → invalid_json。invalid_json 的 detail 是自由文本，用例里标了 ignore。单条：data 的字段 name、provider、model 与下列别名都须是字符串（缺失当空串），类型不对 → invalid_json：baseURL / baseUrl / base_url、apiKey / api_key、toolId / tool_id、authType / auth_type；hints 为对象，其中 toolId / tool_id。🔴 同一字段的多个别名同时出现（如 baseURL 与 base_url）→ invalid_json，不做优先级选择。各字段去两端空白；model 去空白后为空 → 用 defaultModel（去空白）并标 modelFallback: true。协议推断（看原始 model，不看兜底值；「小写」均指 ASCII 小写）：provider 小写后含 anthropic 或 claude → anthropic；否则 model 小写后以 claude- 开头 → anthropic；否则 toolId（hints.toolId 非空时用它，否则用顶层 toolId）小写后含 claude 或 anthropic → anthropic；其余 → openai_compatible。rawProvider 为去空白的原始 provider。单条信封里的 authType 不起作用（跳过规则只对打包生效）。打包：data 里取 profiles（或别名 api_profiles；两者同时出现 → invalid_json；缺失当空数组；不是数组 → invalid_json）。逐条：不是对象的条目静默丢弃、不计数；是对象但字段类型不对 → **整个打包** invalid_json；authType 为 oauth（不区分大小写）的跳过并计入 skipped；其余按单条规则解析。一条都没剩 → empty_bundle（skipped 为跳过数）。to_profile：输入原样写入（不去空白），只产出规范写法 {kind: ai.profile, v: 1, data: {name, provider, baseURL, apiKey, model}}；provider 为 anthropic（Anthropic 协议）或 openai（其余）；model 为空也照样输出空串字段。格式规范见 https://ai-profile.ruoyi.plus/api/protocol",
  "generatedBy": "cargo xtask gen-spec（期望值由 Rust 参考实现算出，请勿手改）",
  "specVersion": 1,
  "title": "ai.profile 解析与生成"
}
