11import { describe , expect , it } from "vitest" ;
22import { detectZaiEndpoint } from "./zai-endpoint-detect.js" ;
33
4- function makeFetch ( map : Record < string , { status : number ; body ?: unknown } > ) {
5- return ( async ( url : string ) => {
6- const entry = map [ url ] ;
4+ type FetchResponse = { status : number ; body ?: unknown } ;
5+
6+ function makeFetch ( map : Record < string , FetchResponse > ) {
7+ return ( async ( url : string , init ?: RequestInit ) => {
8+ const rawBody = typeof init ?. body === "string" ? JSON . parse ( init . body ) : null ;
9+ const entry = map [ `${ url } ::${ rawBody ?. model ?? "" } ` ] ?? map [ url ] ;
710 if ( ! entry ) {
8- throw new Error ( `unexpected url: ${ url } ` ) ;
11+ throw new Error ( `unexpected url: ${ url } model= ${ String ( rawBody ?. model ?? "" ) } ` ) ;
912 }
1013 const json = entry . body ?? { } ;
1114 return new Response ( JSON . stringify ( json ) , {
@@ -18,39 +21,71 @@ function makeFetch(map: Record<string, { status: number; body?: unknown }>) {
1821describe ( "detectZaiEndpoint" , ( ) => {
1922 it ( "resolves preferred/fallback endpoints and null when probes fail" , async ( ) => {
2023 const scenarios : Array < {
24+ endpoint ?: "global" | "cn" | "coding-global" | "coding-cn" ;
2125 responses : Record < string , { status : number ; body ?: unknown } > ;
2226 expected : { endpoint : string ; modelId : string } | null ;
2327 } > = [
2428 {
2529 responses : {
26- "https://api.z.ai/api/paas/v4/chat/completions" : { status : 200 } ,
30+ "https://api.z.ai/api/paas/v4/chat/completions::glm-5 " : { status : 200 } ,
2731 } ,
2832 expected : { endpoint : "global" , modelId : "glm-5" } ,
2933 } ,
3034 {
3135 responses : {
32- "https://api.z.ai/api/paas/v4/chat/completions" : {
36+ "https://api.z.ai/api/paas/v4/chat/completions::glm-5 " : {
3337 status : 404 ,
3438 body : { error : { message : "not found" } } ,
3539 } ,
36- "https://open.bigmodel.cn/api/paas/v4/chat/completions" : { status : 200 } ,
40+ "https://open.bigmodel.cn/api/paas/v4/chat/completions::glm-5 " : { status : 200 } ,
3741 } ,
3842 expected : { endpoint : "cn" , modelId : "glm-5" } ,
3943 } ,
4044 {
4145 responses : {
42- "https://api.z.ai/api/paas/v4/chat/completions" : { status : 404 } ,
43- "https://open.bigmodel.cn/api/paas/v4/chat/completions" : { status : 404 } ,
44- "https://api.z.ai/api/coding/paas/v4/chat/completions" : { status : 200 } ,
46+ "https://api.z.ai/api/paas/v4/chat/completions::glm-5" : { status : 404 } ,
47+ "https://open.bigmodel.cn/api/paas/v4/chat/completions::glm-5" : { status : 404 } ,
48+ "https://api.z.ai/api/coding/paas/v4/chat/completions::glm-5" : { status : 200 } ,
49+ } ,
50+ expected : { endpoint : "coding-global" , modelId : "glm-5" } ,
51+ } ,
52+ {
53+ endpoint : "coding-global" ,
54+ responses : {
55+ "https://api.z.ai/api/coding/paas/v4/chat/completions::glm-5" : {
56+ status : 404 ,
57+ body : { error : { message : "glm-5 unavailable" } } ,
58+ } ,
59+ "https://api.z.ai/api/coding/paas/v4/chat/completions::glm-4.7" : { status : 200 } ,
4560 } ,
4661 expected : { endpoint : "coding-global" , modelId : "glm-4.7" } ,
4762 } ,
63+ {
64+ endpoint : "coding-cn" ,
65+ responses : {
66+ "https://open.bigmodel.cn/api/coding/paas/v4/chat/completions::glm-5" : { status : 200 } ,
67+ } ,
68+ expected : { endpoint : "coding-cn" , modelId : "glm-5" } ,
69+ } ,
70+ {
71+ endpoint : "coding-cn" ,
72+ responses : {
73+ "https://open.bigmodel.cn/api/coding/paas/v4/chat/completions::glm-5" : {
74+ status : 404 ,
75+ body : { error : { message : "glm-5 unavailable" } } ,
76+ } ,
77+ "https://open.bigmodel.cn/api/coding/paas/v4/chat/completions::glm-4.7" : { status : 200 } ,
78+ } ,
79+ expected : { endpoint : "coding-cn" , modelId : "glm-4.7" } ,
80+ } ,
4881 {
4982 responses : {
50- "https://api.z.ai/api/paas/v4/chat/completions" : { status : 401 } ,
51- "https://open.bigmodel.cn/api/paas/v4/chat/completions" : { status : 401 } ,
52- "https://api.z.ai/api/coding/paas/v4/chat/completions" : { status : 401 } ,
53- "https://open.bigmodel.cn/api/coding/paas/v4/chat/completions" : { status : 401 } ,
83+ "https://api.z.ai/api/paas/v4/chat/completions::glm-5" : { status : 401 } ,
84+ "https://open.bigmodel.cn/api/paas/v4/chat/completions::glm-5" : { status : 401 } ,
85+ "https://api.z.ai/api/coding/paas/v4/chat/completions::glm-5" : { status : 401 } ,
86+ "https://api.z.ai/api/coding/paas/v4/chat/completions::glm-4.7" : { status : 401 } ,
87+ "https://open.bigmodel.cn/api/coding/paas/v4/chat/completions::glm-5" : { status : 401 } ,
88+ "https://open.bigmodel.cn/api/coding/paas/v4/chat/completions::glm-4.7" : { status : 401 } ,
5489 } ,
5590 expected : null ,
5691 } ,
@@ -59,6 +94,7 @@ describe("detectZaiEndpoint", () => {
5994 for ( const scenario of scenarios ) {
6095 const detected = await detectZaiEndpoint ( {
6196 apiKey : "sk-test" , // pragma: allowlist secret
97+ ...( scenario . endpoint ? { endpoint : scenario . endpoint } : { } ) ,
6298 fetchFn : makeFetch ( scenario . responses ) ,
6399 } ) ;
64100
0 commit comments