1 line
25 KiB
JSON
1 line
25 KiB
JSON
{"repo": "bigfatsea/vmr", "files": {"internal/adapter/anthropic/anthropic_test.go": {"c2c6df744386811c0d2f7dd28dbe002831dcf723": {"t": 1785746085.9987402, "n": 4528, "h": "eae3327500c91cbf", "c": "// Ver 2026-07-07, by Fable 5\npackage anthropic\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"testing\"\n\n\t\"vmr/internal/core\"\n)\n\nfunc TestBuildRequest(t *testing.T) {\n\traw := []byte(`{\"model\":\"claude\",\"max_tokens\":16,\"stream\":true,\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}],\"future_param\":1}`)\n\tep := &core.Endpoint{Provider: \"p\", BaseURL: \"https://api.deepseek.com/anthropic/v1/\", APIKey: \"sk-1\", Model: \"deepseek-v4-pro\"}\n\tep.FullURL = Anthropic{}.ResolveURL(ep.BaseURL)\n\n\treq, outBody, err := Anthropic{}.BuildRequest(context.Background(), ep, &core.CanonicalRequest{Model: \"claude\", Stream: true, Raw: raw})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(outBody) == 0 {\n\t\tt.Fatal(\"BuildRequest returned empty outbound body\")\n\t}\n\tif req.URL.String() != \"https://api.deepseek.com/anthropic/v1/messages\" {\n\t\tt.Errorf(\"url: %s\", req.URL)\n\t}\n\tif got := req.Header.Get(\"x-api-key\"); got != \"sk-1\" {\n\t\tt.Errorf(\"x-api-key: %q\", got)\n\t}\n\t// The client sent no anthropic-version, and BuildRequest must not\n\t// invent one — omitting it is what a direct connection would see too.\n\tif got := req.Header.Get(\"anthropic-version\"); got != \"\" {\n\t\tt.Errorf(\"anthropic-version should be left unset when the client omits it, got %q\", got)\n\t}\n\tvar m map[string]json.RawMessage\n\tbody, _ := req.GetBody()\n\tif err := json.NewDecoder(body).Decode(&m); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar model string\n\tjson.Unmarshal(m[\"model\"], &model)\n\tif model != \"deepseek-v4-pro\" {\n\t\tt.Errorf(\"model not rewritten: %q\", model)\n\t}\n\tif string(m[\"future_param\"]) != \"1\" || string(m[\"max_tokens\"]) != \"16\" {\n\t\tt.Error(\"unknown/other fields mangled\")\n\t}\n}\n\nfunc TestBuildRequestForwardsProtocolHeaders(t *testing.T) {\n\thdr := http.Header{}\n\thdr.Set(\"anthropic-version\", \"2024-10-22\")\n\thdr.Set(\"anthropic-beta\", \"context-1m-2025-08-07\")\n\tep := &core.Endpoint{Provider: \"p\", BaseURL: \"https://x.example/v1\", APIKey: \"k\", Model: \"m\"}\n\tep.FullURL = Anthropic{}.ResolveURL(ep.BaseURL)\n\treq, _, err := Anthropic{}.BuildRequest(context.Background(), ep,\n\t\t&core.CanonicalRequest{Model: \"vm\", Raw: []byte(`{\"model\":\"vm\"}`), Header: hdr})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif got := req.Header.Get(\"anthropic-version\"); got != \"2024-10-22\" {\n\t\tt.Errorf(\"version not forwarded: %q\", got)\n\t}\n\tif got := req.Header.Get(\"anthropic-beta\"); got != \"context-1m-2025-08-07\" {\n\t\tt.Errorf(\"beta not forwarded: %q\", got)\n\t}\n}\n\n// TestBuildRequestAppliesRoleMap closes the gap between classify_test.go's\n// coverage of RewriteRoles itself and its actual wiring into BuildRequest.\nfunc TestBuildRequestAppliesRoleMap(t *testing.T) {\n\traw := []byte(`{\"model\":\"vm\",\"messages\":[{\"role\":\"developer\",\"content\":\"be helpful\"},{\"role\":\"user\",\"content\":\"hi\"}]}`)\n\tep := &core.Endpoint{Provider: \"p\", BaseURL: \"https://x.example/v1\", APIKey: \"k\", Model: \"m\", RoleMap: map[string]string{\"developer\": \"system\"}}\n\tep.FullURL = Anthropic{}.ResolveURL(ep.BaseURL)\n\n\t_, outBody, err := Anthropic{}.BuildRequest(context.Background(), ep, &core.CanonicalRequest{Model: \"vm\", Raw: raw})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !bytes.Contains(outBody, []byte(`\"role\":\"system\"`)) {\n\t\tt.Errorf(\"developer role not remapped: %s\", outBody)\n\t}\n\tif bytes.Contains(outBody, []byte(`\"developer\"`)) {\n\t\tt.Errorf(\"developer role still present: %s\", outBody)\n\t}\n}\n\nfunc TestClassifyError(t *testing.T) {\n\tcases := []struct {\n\t\tstatus int\n\t\tbody string\n\t\twant core.ErrorClass\n\t}{\n\t\t{400, `{\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"message\":\"max_tokens required\"}}`, core.ErrClient},\n\t\t// DeepSeek anthropic endpoint, live-captured wording for a wrong model name:\n\t\t{400, `{\"error\":{\"message\":\"The supported API model names are deepseek-v4-pro or deepseek-v4-flash, but you passed no-such.\"}}`, core.ErrEndpoint},\n\t\t{401, `{\"type\":\"error\",\"error\":{\"type\":\"authentication_error\",\"message\":\"login fail\"}}`, core.ErrAuth},\n\t\t{404, `{\"type\":\"error\",\"error\":{\"type\":\"not_found_error\",\"message\":\"model not found\"}}`, core.ErrEndpoint},\n\t\t{429, `{\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"slow down\"}}`, core.ErrRateLimit},\n\t\t{500, `{}`, core.ErrTransient},\n\t\t{529, `{\"type\":\"error\",\"error\":{\"type\":\"overloaded_error\",\"message\":\"Overloaded\"}}`, core.ErrTransient},\n\t}\n\tfor _, c := range cases {\n\t\tif got := (Anthropic{}).ClassifyError(c.status, []byte(c.body)); got != c.want {\n\t\t\tt.Errorf(\"status=%d body=%s: got %v want %v\", c.status, c.body, got, c.want)\n\t\t}\n\t}\n}\n\nfunc TestProtocol(t *testing.T) {\n\tif (Anthropic{}).Protocol() != \"anthropic\" {\n\t\tt.Error(\"protocol\")\n\t}\n}\n"}, "0713eea0734bed76c18fc46d8a47c173e9e86e49": {"t": 1785759764.6395805, "n": 4528, "h": "eae3327500c91cbf", "c": "// Ver 2026-07-07, by Fable 5\npackage anthropic\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"testing\"\n\n\t\"vmr/internal/core\"\n)\n\nfunc TestBuildRequest(t *testing.T) {\n\traw := []byte(`{\"model\":\"claude\",\"max_tokens\":16,\"stream\":true,\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}],\"future_param\":1}`)\n\tep := &core.Endpoint{Provider: \"p\", BaseURL: \"https://api.deepseek.com/anthropic/v1/\", APIKey: \"sk-1\", Model: \"deepseek-v4-pro\"}\n\tep.FullURL = Anthropic{}.ResolveURL(ep.BaseURL)\n\n\treq, outBody, err := Anthropic{}.BuildRequest(context.Background(), ep, &core.CanonicalRequest{Model: \"claude\", Stream: true, Raw: raw})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(outBody) == 0 {\n\t\tt.Fatal(\"BuildRequest returned empty outbound body\")\n\t}\n\tif req.URL.String() != \"https://api.deepseek.com/anthropic/v1/messages\" {\n\t\tt.Errorf(\"url: %s\", req.URL)\n\t}\n\tif got := req.Header.Get(\"x-api-key\"); got != \"sk-1\" {\n\t\tt.Errorf(\"x-api-key: %q\", got)\n\t}\n\t// The client sent no anthropic-version, and BuildRequest must not\n\t// invent one — omitting it is what a direct connection would see too.\n\tif got := req.Header.Get(\"anthropic-version\"); got != \"\" {\n\t\tt.Errorf(\"anthropic-version should be left unset when the client omits it, got %q\", got)\n\t}\n\tvar m map[string]json.RawMessage\n\tbody, _ := req.GetBody()\n\tif err := json.NewDecoder(body).Decode(&m); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar model string\n\tjson.Unmarshal(m[\"model\"], &model)\n\tif model != \"deepseek-v4-pro\" {\n\t\tt.Errorf(\"model not rewritten: %q\", model)\n\t}\n\tif string(m[\"future_param\"]) != \"1\" || string(m[\"max_tokens\"]) != \"16\" {\n\t\tt.Error(\"unknown/other fields mangled\")\n\t}\n}\n\nfunc TestBuildRequestForwardsProtocolHeaders(t *testing.T) {\n\thdr := http.Header{}\n\thdr.Set(\"anthropic-version\", \"2024-10-22\")\n\thdr.Set(\"anthropic-beta\", \"context-1m-2025-08-07\")\n\tep := &core.Endpoint{Provider: \"p\", BaseURL: \"https://x.example/v1\", APIKey: \"k\", Model: \"m\"}\n\tep.FullURL = Anthropic{}.ResolveURL(ep.BaseURL)\n\treq, _, err := Anthropic{}.BuildRequest(context.Background(), ep,\n\t\t&core.CanonicalRequest{Model: \"vm\", Raw: []byte(`{\"model\":\"vm\"}`), Header: hdr})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif got := req.Header.Get(\"anthropic-version\"); got != \"2024-10-22\" {\n\t\tt.Errorf(\"version not forwarded: %q\", got)\n\t}\n\tif got := req.Header.Get(\"anthropic-beta\"); got != \"context-1m-2025-08-07\" {\n\t\tt.Errorf(\"beta not forwarded: %q\", got)\n\t}\n}\n\n// TestBuildRequestAppliesRoleMap closes the gap between classify_test.go's\n// coverage of RewriteRoles itself and its actual wiring into BuildRequest.\nfunc TestBuildRequestAppliesRoleMap(t *testing.T) {\n\traw := []byte(`{\"model\":\"vm\",\"messages\":[{\"role\":\"developer\",\"content\":\"be helpful\"},{\"role\":\"user\",\"content\":\"hi\"}]}`)\n\tep := &core.Endpoint{Provider: \"p\", BaseURL: \"https://x.example/v1\", APIKey: \"k\", Model: \"m\", RoleMap: map[string]string{\"developer\": \"system\"}}\n\tep.FullURL = Anthropic{}.ResolveURL(ep.BaseURL)\n\n\t_, outBody, err := Anthropic{}.BuildRequest(context.Background(), ep, &core.CanonicalRequest{Model: \"vm\", Raw: raw})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !bytes.Contains(outBody, []byte(`\"role\":\"system\"`)) {\n\t\tt.Errorf(\"developer role not remapped: %s\", outBody)\n\t}\n\tif bytes.Contains(outBody, []byte(`\"developer\"`)) {\n\t\tt.Errorf(\"developer role still present: %s\", outBody)\n\t}\n}\n\nfunc TestClassifyError(t *testing.T) {\n\tcases := []struct {\n\t\tstatus int\n\t\tbody string\n\t\twant core.ErrorClass\n\t}{\n\t\t{400, `{\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"message\":\"max_tokens required\"}}`, core.ErrClient},\n\t\t// DeepSeek anthropic endpoint, live-captured wording for a wrong model name:\n\t\t{400, `{\"error\":{\"message\":\"The supported API model names are deepseek-v4-pro or deepseek-v4-flash, but you passed no-such.\"}}`, core.ErrEndpoint},\n\t\t{401, `{\"type\":\"error\",\"error\":{\"type\":\"authentication_error\",\"message\":\"login fail\"}}`, core.ErrAuth},\n\t\t{404, `{\"type\":\"error\",\"error\":{\"type\":\"not_found_error\",\"message\":\"model not found\"}}`, core.ErrEndpoint},\n\t\t{429, `{\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"slow down\"}}`, core.ErrRateLimit},\n\t\t{500, `{}`, core.ErrTransient},\n\t\t{529, `{\"type\":\"error\",\"error\":{\"type\":\"overloaded_error\",\"message\":\"Overloaded\"}}`, core.ErrTransient},\n\t}\n\tfor _, c := range cases {\n\t\tif got := (Anthropic{}).ClassifyError(c.status, []byte(c.body)); got != c.want {\n\t\t\tt.Errorf(\"status=%d body=%s: got %v want %v\", c.status, c.body, got, c.want)\n\t\t}\n\t}\n}\n\nfunc TestProtocol(t *testing.T) {\n\tif (Anthropic{}).Protocol() != \"anthropic\" {\n\t\tt.Error(\"protocol\")\n\t}\n}\n"}, "1c96f45772f0e7ab19ce1e249b31fa6d766bc5d0": {"t": 1785759766.089111, "n": 3614, "h": "0d91c2f7b06e1fc1", "c": "// Ver 2026-07-07, by Fable 5\npackage anthropic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"testing\"\n\n\t\"vmr/internal/core\"\n)\n\nfunc TestBuildRequest(t *testing.T) {\n\traw := []byte(`{\"model\":\"claude\",\"max_tokens\":16,\"stream\":true,\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}],\"future_param\":1}`)\n\tep := &core.Endpoint{Provider: \"p\", BaseURL: \"https://api.deepseek.com/anthropic/v1/\", APIKey: \"sk-1\", Model: \"deepseek-v4-pro\"}\n\tep.FullURL = Anthropic{}.ResolveURL(ep.BaseURL)\n\n\treq, outBody, err := Anthropic{}.BuildRequest(context.Background(), ep, &core.CanonicalRequest{Model: \"claude\", Stream: true, Raw: raw})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(outBody) == 0 {\n\t\tt.Fatal(\"BuildRequest returned empty outbound body\")\n\t}\n\tif req.URL.String() != \"https://api.deepseek.com/anthropic/v1/messages\" {\n\t\tt.Errorf(\"url: %s\", req.URL)\n\t}\n\tif got := req.Header.Get(\"x-api-key\"); got != \"sk-1\" {\n\t\tt.Errorf(\"x-api-key: %q\", got)\n\t}\n\t// The client sent no anthropic-version, and BuildRequest must not\n\t// invent one — omitting it is what a direct connection would see too.\n\tif got := req.Header.Get(\"anthropic-version\"); got != \"\" {\n\t\tt.Errorf(\"anthropic-version should be left unset when the client omits it, got %q\", got)\n\t}\n\tvar m map[string]json.RawMessage\n\tbody, _ := req.GetBody()\n\tif err := json.NewDecoder(body).Decode(&m); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar model string\n\tjson.Unmarshal(m[\"model\"], &model)\n\tif model != \"deepseek-v4-pro\" {\n\t\tt.Errorf(\"model not rewritten: %q\", model)\n\t}\n\tif string(m[\"future_param\"]) != \"1\" || string(m[\"max_tokens\"]) != \"16\" {\n\t\tt.Error(\"unknown/other fields mangled\")\n\t}\n}\n\nfunc TestBuildRequestForwardsProtocolHeaders(t *testing.T) {\n\thdr := http.Header{}\n\thdr.Set(\"anthropic-version\", \"2024-10-22\")\n\thdr.Set(\"anthropic-beta\", \"context-1m-2025-08-07\")\n\tep := &core.Endpoint{Provider: \"p\", BaseURL: \"https://x.example/v1\", APIKey: \"k\", Model: \"m\"}\n\tep.FullURL = Anthropic{}.ResolveURL(ep.BaseURL)\n\treq, _, err := Anthropic{}.BuildRequest(context.Background(), ep,\n\t\t&core.CanonicalRequest{Model: \"vm\", Raw: []byte(`{\"model\":\"vm\"}`), Header: hdr})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif got := req.Header.Get(\"anthropic-version\"); got != \"2024-10-22\" {\n\t\tt.Errorf(\"version not forwarded: %q\", got)\n\t}\n\tif got := req.Header.Get(\"anthropic-beta\"); got != \"context-1m-2025-08-07\" {\n\t\tt.Errorf(\"beta not forwarded: %q\", got)\n\t}\n}\n\nfunc TestClassifyError(t *testing.T) {\n\tcases := []struct {\n\t\tstatus int\n\t\tbody string\n\t\twant core.ErrorClass\n\t}{\n\t\t{400, `{\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"message\":\"max_tokens required\"}}`, core.ErrClient},\n\t\t// DeepSeek anthropic endpoint, live-captured wording for a wrong model name:\n\t\t{400, `{\"error\":{\"message\":\"The supported API model names are deepseek-v4-pro or deepseek-v4-flash, but you passed no-such.\"}}`, core.ErrEndpoint},\n\t\t{401, `{\"type\":\"error\",\"error\":{\"type\":\"authentication_error\",\"message\":\"login fail\"}}`, core.ErrAuth},\n\t\t{404, `{\"type\":\"error\",\"error\":{\"type\":\"not_found_error\",\"message\":\"model not found\"}}`, core.ErrEndpoint},\n\t\t{429, `{\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"slow down\"}}`, core.ErrRateLimit},\n\t\t{500, `{}`, core.ErrTransient},\n\t\t{529, `{\"type\":\"error\",\"error\":{\"type\":\"overloaded_error\",\"message\":\"Overloaded\"}}`, core.ErrTransient},\n\t}\n\tfor _, c := range cases {\n\t\tif got := (Anthropic{}).ClassifyError(c.status, []byte(c.body)); got != c.want {\n\t\t\tt.Errorf(\"status=%d body=%s: got %v want %v\", c.status, c.body, got, c.want)\n\t\t}\n\t}\n}\n\nfunc TestProtocol(t *testing.T) {\n\tif (Anthropic{}).Protocol() != \"anthropic\" {\n\t\tt.Error(\"protocol\")\n\t}\n}\n"}, "7b1932a91970d3acf9df76592f3280a7f817d441": {"t": 1785759767.436736, "n": 3516, "h": "c797812c9846e557", "c": "// Ver 2026-07-07, by Fable 5\npackage anthropic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"testing\"\n\n\t\"vmr/internal/core\"\n)\n\nfunc TestBuildRequest(t *testing.T) {\n\traw := []byte(`{\"model\":\"claude\",\"max_tokens\":16,\"stream\":true,\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}],\"future_param\":1}`)\n\tep := &core.Endpoint{Provider: \"p\", BaseURL: \"https://api.deepseek.com/anthropic/v1/\", APIKey: \"sk-1\", Model: \"deepseek-v4-pro\"}\n\n\treq, outBody, err := Anthropic{}.BuildRequest(context.Background(), ep, &core.CanonicalRequest{Model: \"claude\", Stream: true, Raw: raw})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(outBody) == 0 {\n\t\tt.Fatal(\"BuildRequest returned empty outbound body\")\n\t}\n\tif req.URL.String() != \"https://api.deepseek.com/anthropic/v1/messages\" {\n\t\tt.Errorf(\"url: %s\", req.URL)\n\t}\n\tif got := req.Header.Get(\"x-api-key\"); got != \"sk-1\" {\n\t\tt.Errorf(\"x-api-key: %q\", got)\n\t}\n\t// The client sent no anthropic-version, and BuildRequest must not\n\t// invent one — omitting it is what a direct connection would see too.\n\tif got := req.Header.Get(\"anthropic-version\"); got != \"\" {\n\t\tt.Errorf(\"anthropic-version should be left unset when the client omits it, got %q\", got)\n\t}\n\tvar m map[string]json.RawMessage\n\tbody, _ := req.GetBody()\n\tif err := json.NewDecoder(body).Decode(&m); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar model string\n\tjson.Unmarshal(m[\"model\"], &model)\n\tif model != \"deepseek-v4-pro\" {\n\t\tt.Errorf(\"model not rewritten: %q\", model)\n\t}\n\tif string(m[\"future_param\"]) != \"1\" || string(m[\"max_tokens\"]) != \"16\" {\n\t\tt.Error(\"unknown/other fields mangled\")\n\t}\n}\n\nfunc TestBuildRequestForwardsProtocolHeaders(t *testing.T) {\n\thdr := http.Header{}\n\thdr.Set(\"anthropic-version\", \"2024-10-22\")\n\thdr.Set(\"anthropic-beta\", \"context-1m-2025-08-07\")\n\tep := &core.Endpoint{Provider: \"p\", BaseURL: \"https://x.example/v1\", APIKey: \"k\", Model: \"m\"}\n\treq, _, err := Anthropic{}.BuildRequest(context.Background(), ep,\n\t\t&core.CanonicalRequest{Model: \"vm\", Raw: []byte(`{\"model\":\"vm\"}`), Header: hdr})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif got := req.Header.Get(\"anthropic-version\"); got != \"2024-10-22\" {\n\t\tt.Errorf(\"version not forwarded: %q\", got)\n\t}\n\tif got := req.Header.Get(\"anthropic-beta\"); got != \"context-1m-2025-08-07\" {\n\t\tt.Errorf(\"beta not forwarded: %q\", got)\n\t}\n}\n\nfunc TestClassifyError(t *testing.T) {\n\tcases := []struct {\n\t\tstatus int\n\t\tbody string\n\t\twant core.ErrorClass\n\t}{\n\t\t{400, `{\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"message\":\"max_tokens required\"}}`, core.ErrClient},\n\t\t// DeepSeek anthropic endpoint, live-captured wording for a wrong model name:\n\t\t{400, `{\"error\":{\"message\":\"The supported API model names are deepseek-v4-pro or deepseek-v4-flash, but you passed no-such.\"}}`, core.ErrEndpoint},\n\t\t{401, `{\"type\":\"error\",\"error\":{\"type\":\"authentication_error\",\"message\":\"login fail\"}}`, core.ErrAuth},\n\t\t{404, `{\"type\":\"error\",\"error\":{\"type\":\"not_found_error\",\"message\":\"model not found\"}}`, core.ErrEndpoint},\n\t\t{429, `{\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"slow down\"}}`, core.ErrRateLimit},\n\t\t{500, `{}`, core.ErrTransient},\n\t\t{529, `{\"type\":\"error\",\"error\":{\"type\":\"overloaded_error\",\"message\":\"Overloaded\"}}`, core.ErrTransient},\n\t}\n\tfor _, c := range cases {\n\t\tif got := (Anthropic{}).ClassifyError(c.status, []byte(c.body)); got != c.want {\n\t\t\tt.Errorf(\"status=%d body=%s: got %v want %v\", c.status, c.body, got, c.want)\n\t\t}\n\t}\n}\n\nfunc TestProtocol(t *testing.T) {\n\tif (Anthropic{}).Protocol() != \"anthropic\" {\n\t\tt.Error(\"protocol\")\n\t}\n}\n"}, "2d972e103903796177187bb414ef25087dd36638": {"t": 1785759768.754936, "n": 3334, "h": "de9083147cdb34a5", "c": "// Ver 2026-07-07, by Fable 5\npackage anthropic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"testing\"\n\n\t\"vmr/internal/core\"\n)\n\nfunc TestBuildRequest(t *testing.T) {\n\traw := []byte(`{\"model\":\"claude\",\"max_tokens\":16,\"stream\":true,\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}],\"future_param\":1}`)\n\tep := &core.Endpoint{Provider: \"p\", BaseURL: \"https://api.deepseek.com/anthropic/v1/\", APIKey: \"sk-1\", Model: \"deepseek-v4-pro\"}\n\n\treq, outBody, err := Anthropic{}.BuildRequest(context.Background(), ep, &core.CanonicalRequest{Model: \"claude\", Stream: true, Raw: raw})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(outBody) == 0 {\n\t\tt.Fatal(\"BuildRequest returned empty outbound body\")\n\t}\n\tif req.URL.String() != \"https://api.deepseek.com/anthropic/v1/messages\" {\n\t\tt.Errorf(\"url: %s\", req.URL)\n\t}\n\tif got := req.Header.Get(\"x-api-key\"); got != \"sk-1\" {\n\t\tt.Errorf(\"x-api-key: %q\", got)\n\t}\n\tif got := req.Header.Get(\"anthropic-version\"); got != \"2023-06-01\" {\n\t\tt.Errorf(\"default version: %q\", got)\n\t}\n\tvar m map[string]json.RawMessage\n\tbody, _ := req.GetBody()\n\tif err := json.NewDecoder(body).Decode(&m); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar model string\n\tjson.Unmarshal(m[\"model\"], &model)\n\tif model != \"deepseek-v4-pro\" {\n\t\tt.Errorf(\"model not rewritten: %q\", model)\n\t}\n\tif string(m[\"future_param\"]) != \"1\" || string(m[\"max_tokens\"]) != \"16\" {\n\t\tt.Error(\"unknown/other fields mangled\")\n\t}\n}\n\nfunc TestBuildRequestForwardsProtocolHeaders(t *testing.T) {\n\thdr := http.Header{}\n\thdr.Set(\"anthropic-version\", \"2024-10-22\")\n\thdr.Set(\"anthropic-beta\", \"context-1m-2025-08-07\")\n\tep := &core.Endpoint{Provider: \"p\", BaseURL: \"https://x.example/v1\", APIKey: \"k\", Model: \"m\"}\n\treq, _, err := Anthropic{}.BuildRequest(context.Background(), ep,\n\t\t&core.CanonicalRequest{Model: \"vm\", Raw: []byte(`{\"model\":\"vm\"}`), Header: hdr})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif got := req.Header.Get(\"anthropic-version\"); got != \"2024-10-22\" {\n\t\tt.Errorf(\"version not forwarded: %q\", got)\n\t}\n\tif got := req.Header.Get(\"anthropic-beta\"); got != \"context-1m-2025-08-07\" {\n\t\tt.Errorf(\"beta not forwarded: %q\", got)\n\t}\n}\n\nfunc TestClassifyError(t *testing.T) {\n\tcases := []struct {\n\t\tstatus int\n\t\tbody string\n\t\twant core.ErrorClass\n\t}{\n\t\t{400, `{\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"message\":\"max_tokens required\"}}`, core.ErrClient},\n\t\t// DeepSeek anthropic endpoint, live-captured wording for a wrong model name:\n\t\t{400, `{\"error\":{\"message\":\"The supported API model names are deepseek-v4-pro or deepseek-v4-flash, but you passed no-such.\"}}`, core.ErrEndpoint},\n\t\t{401, `{\"type\":\"error\",\"error\":{\"type\":\"authentication_error\",\"message\":\"login fail\"}}`, core.ErrAuth},\n\t\t{404, `{\"type\":\"error\",\"error\":{\"type\":\"not_found_error\",\"message\":\"model not found\"}}`, core.ErrEndpoint},\n\t\t{429, `{\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"slow down\"}}`, core.ErrRateLimit},\n\t\t{500, `{}`, core.ErrTransient},\n\t\t{529, `{\"type\":\"error\",\"error\":{\"type\":\"overloaded_error\",\"message\":\"Overloaded\"}}`, core.ErrTransient},\n\t}\n\tfor _, c := range cases {\n\t\tif got := (Anthropic{}).ClassifyError(c.status, []byte(c.body)); got != c.want {\n\t\t\tt.Errorf(\"status=%d body=%s: got %v want %v\", c.status, c.body, got, c.want)\n\t\t}\n\t}\n}\n\nfunc TestProtocol(t *testing.T) {\n\tif (Anthropic{}).Protocol() != \"anthropic\" {\n\t\tt.Error(\"protocol\")\n\t}\n}\n"}, "df038c9eca16884d7a8550856902f716731b668f": {"t": 1785759770.176902, "n": 3240, "h": "8497619f4beae06c", "c": "// Ver 2026-07-07, by Fable 5\npackage anthropic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"testing\"\n\n\t\"vmr/internal/core\"\n)\n\nfunc TestBuildRequest(t *testing.T) {\n\traw := []byte(`{\"model\":\"claude\",\"max_tokens\":16,\"stream\":true,\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}],\"future_param\":1}`)\n\tep := &core.Endpoint{Provider: \"p\", BaseURL: \"https://api.deepseek.com/anthropic/v1/\", APIKey: \"sk-1\", Model: \"deepseek-v4-pro\"}\n\n\treq, err := Anthropic{}.BuildRequest(context.Background(), ep, &core.CanonicalRequest{Model: \"claude\", Stream: true, Raw: raw})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif req.URL.String() != \"https://api.deepseek.com/anthropic/v1/messages\" {\n\t\tt.Errorf(\"url: %s\", req.URL)\n\t}\n\tif got := req.Header.Get(\"x-api-key\"); got != \"sk-1\" {\n\t\tt.Errorf(\"x-api-key: %q\", got)\n\t}\n\tif got := req.Header.Get(\"anthropic-version\"); got != \"2023-06-01\" {\n\t\tt.Errorf(\"default version: %q\", got)\n\t}\n\tvar m map[string]json.RawMessage\n\tbody, _ := req.GetBody()\n\tif err := json.NewDecoder(body).Decode(&m); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar model string\n\tjson.Unmarshal(m[\"model\"], &model)\n\tif model != \"deepseek-v4-pro\" {\n\t\tt.Errorf(\"model not rewritten: %q\", model)\n\t}\n\tif string(m[\"future_param\"]) != \"1\" || string(m[\"max_tokens\"]) != \"16\" {\n\t\tt.Error(\"unknown/other fields mangled\")\n\t}\n}\n\nfunc TestBuildRequestForwardsProtocolHeaders(t *testing.T) {\n\thdr := http.Header{}\n\thdr.Set(\"anthropic-version\", \"2024-10-22\")\n\thdr.Set(\"anthropic-beta\", \"context-1m-2025-08-07\")\n\tep := &core.Endpoint{Provider: \"p\", BaseURL: \"https://x.example/v1\", APIKey: \"k\", Model: \"m\"}\n\treq, err := Anthropic{}.BuildRequest(context.Background(), ep,\n\t\t&core.CanonicalRequest{Model: \"vm\", Raw: []byte(`{\"model\":\"vm\"}`), Header: hdr})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif got := req.Header.Get(\"anthropic-version\"); got != \"2024-10-22\" {\n\t\tt.Errorf(\"version not forwarded: %q\", got)\n\t}\n\tif got := req.Header.Get(\"anthropic-beta\"); got != \"context-1m-2025-08-07\" {\n\t\tt.Errorf(\"beta not forwarded: %q\", got)\n\t}\n}\n\nfunc TestClassifyError(t *testing.T) {\n\tcases := []struct {\n\t\tstatus int\n\t\tbody string\n\t\twant core.ErrorClass\n\t}{\n\t\t{400, `{\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"message\":\"max_tokens required\"}}`, core.ErrClient},\n\t\t// DeepSeek anthropic endpoint, live-captured wording for a wrong model name:\n\t\t{400, `{\"error\":{\"message\":\"The supported API model names are deepseek-v4-pro or deepseek-v4-flash, but you passed no-such.\"}}`, core.ErrEndpoint},\n\t\t{401, `{\"type\":\"error\",\"error\":{\"type\":\"authentication_error\",\"message\":\"login fail\"}}`, core.ErrAuth},\n\t\t{404, `{\"type\":\"error\",\"error\":{\"type\":\"not_found_error\",\"message\":\"model not found\"}}`, core.ErrEndpoint},\n\t\t{429, `{\"type\":\"error\",\"error\":{\"type\":\"rate_limit_error\",\"message\":\"slow down\"}}`, core.ErrRateLimit},\n\t\t{500, `{}`, core.ErrTransient},\n\t\t{529, `{\"type\":\"error\",\"error\":{\"type\":\"overloaded_error\",\"message\":\"Overloaded\"}}`, core.ErrTransient},\n\t}\n\tfor _, c := range cases {\n\t\tif got := (Anthropic{}).ClassifyError(c.status, []byte(c.body)); got != c.want {\n\t\t\tt.Errorf(\"status=%d body=%s: got %v want %v\", c.status, c.body, got, c.want)\n\t\t}\n\t}\n}\n\nfunc TestProtocol(t *testing.T) {\n\tif (Anthropic{}).Protocol() != \"anthropic\" {\n\t\tt.Error(\"protocol\")\n\t}\n}\n"}}}} |