/** * Direct Z.ai API test - standalone runner */ import { createProxyServer } from "../src/proxy-server.js"; const ZAI_KEY = process.env.ZAI_API_KEY; if (!ZAI_KEY) { console.error("Error: ZAI_API_KEY environment variable is not set"); console.log("\nUsage: ZAI_API_KEY=your_key bun tests/zai-direct-test.ts"); process.exit(1); } console.log("=== Z.ai Handler Test ==="); console.log(`API Key: ${ZAI_KEY.slice(0, 8)}...${ZAI_KEY.slice(-4)}`); // Test 1: Direct Z.ai API call async function testDirectApi() { console.log("\n[Test 1] Direct Z.ai API call..."); const response = await fetch("https://api.z.ai/api/coding/paas/v4/chat/completions", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${ZAI_KEY}`, }, body: JSON.stringify({ model: "glm-4.6", max_tokens: 100, stream: true, messages: [ { role: "user", content: "Say 'Hello from GLM!' and nothing else." } ] }) }); if (!response.ok) { const error = await response.text(); console.error(`❌ API Error (${response.status}):`, error); return false; } console.log("✓ Response status:", response.status); console.log("✓ Content-Type:", response.headers.get("content-type")); const reader = response.body!.getReader(); const decoder = new TextDecoder(); let output = ""; let textContent = ""; while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value, { stream: true }); output += chunk; // Extract content from SSE const lines = chunk.split("\n"); for (const line of lines) { if (line.startsWith("data: ") && !line.includes("[DONE]")) { try { const data = JSON.parse(line.slice(6)); const content = data.choices?.[0]?.delta?.content; if (content) textContent += content; } catch {} } } } console.log("✓ Response text:", textContent || "(streaming response received)"); return true; } // Test 2: Through Claudish proxy async function testThroughProxy() { console.log("\n[Test 2] Through Claudish proxy..."); const proxy = await createProxyServer(3458, undefined, "z-ai/glm-4.6"); console.log(`✓ Proxy started at ${proxy.url}`); try { const response = await fetch(`${proxy.url}/v1/messages`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model: "z-ai/glm-4.6", max_tokens: 100, messages: [{ role: "user", content: "Say 'Hello through proxy!' and nothing else." }] }) }); if (!response.ok) { const error = await response.text(); console.error(`❌ Proxy Error (${response.status}):`, error); return false; } console.log("✓ Response status:", response.status); const reader = response.body!.getReader(); const decoder = new TextDecoder(); let output = ""; let textContent = ""; let hasMessageStart = false; let hasMessageStop = false; while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value, { stream: true }); output += chunk; if (chunk.includes("message_start")) hasMessageStart = true; if (chunk.includes("message_stop")) hasMessageStop = true; // Extract text from Claude format const textMatches = chunk.matchAll(/"text_delta".*?"text":\s*"([^"]*)"/g); for (const match of textMatches) { textContent += match[1].replace(/\\n/g, "\n"); } } console.log("✓ Message start:", hasMessageStart ? "Yes" : "No"); console.log("✓ Message stop:", hasMessageStop ? "Yes" : "No"); console.log("✓ Response text:", textContent || "(content received)"); return hasMessageStart && hasMessageStop; } finally { await proxy.shutdown(); console.log("✓ Proxy shutdown"); } } // Run tests (async () => { let success = true; const directOk = await testDirectApi(); if (!directOk) { console.log("\n❌ Direct API test failed, skipping proxy test"); success = false; } else { const proxyOk = await testThroughProxy(); if (!proxyOk) success = false; } console.log("\n" + "=".repeat(30)); console.log(success ? "✓ All tests passed!" : "❌ Some tests failed"); process.exit(success ? 0 : 1); })();