claudish/tests/zai-direct-test.ts

150 lines
4.3 KiB
TypeScript
Raw Normal View History

/**
* 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);
})();