#!/usr/bin/env node /** * 真实 API smoke —— 对 Gemini 与一个 OpenAI 兼容厂商(volcengine / openrouter)各发一次真实 chat。 * env 有对应 key 才跑,否则 SKIP。任一断言失败即 process.exit(1)。 * * env:GEMINI_API_KEY(+可选 GEMINI_BASE_URL)、VOLCENGINE_API_KEY(+可选 VOLCENGINE_BASE_URL)、 * OPENROUTER_API_KEY(+可选 OPENROUTER_BASE_URL)。无 key 的 provider 跳过。 * * 结构参照 apps/visual-game-server/tools/scenarios/waitlist-e2e(真实链路 + 生成报告)。 */ import { createLLM, createStaticKeyProvider } from '../../src/index.js' /** @type {Array<{ provider:string, envKey:string, envBase:string, model:string }>} */ const TARGETS = [ { provider: 'gemini', envKey: 'GEMINI_API_KEY', envBase: 'GEMINI_BASE_URL', model: process.env.GEMINI_MODEL ?? 'gemini-2.5-flash' }, { provider: 'volcengine', envKey: 'VOLCENGINE_API_KEY', envBase: 'VOLCENGINE_BASE_URL', model: process.env.VOLCENGINE_MODEL ?? 'doubao-pro-32k' }, { provider: 'openrouter', envKey: 'OPENROUTER_API_KEY', envBase: 'OPENROUTER_BASE_URL', model: process.env.OPENROUTER_MODEL ?? 'google/gemini-2.5-flash' }, ] /** @param {{ provider:string, model:string, apiKey:string, baseUrl?:string }} cfg */ async function smokeOne({ provider, model, apiKey, baseUrl }) { const llm = createLLM({ provider, model, keyProvider: createStaticKeyProvider({ api_key: apiKey, base_url: baseUrl }), }) const r = await llm.chat({ messages: [{ role: 'user', content: 'Reply with the single word: ok' }] }) if (typeof r.content !== 'string' || r.content.length === 0) { throw new Error(`[${provider}] empty content`) } if (!(r.usage.total_tokens > 0)) { throw new Error(`[${provider}] usage.total_tokens not > 0`) } return r } async function main() { const lines = [] let ran = 0 let failed = 0 for (const t of TARGETS) { const apiKey = process.env[t.envKey] if (!apiKey) { lines.push(`- ${t.provider} (${t.model}): SKIP (no ${t.envKey})`) continue } ran += 1 try { const r = await smokeOne({ provider: t.provider, model: t.model, apiKey, baseUrl: process.env[t.envBase] }) const snip = r.content.slice(0, 40).replace(/\n/g, ' ') lines.push(`- ${t.provider} (${t.model}): PASS content="${snip}" usage.total_tokens=${r.usage.total_tokens}`) } catch (err) { failed += 1 lines.push(`- ${t.provider} (${t.model}): FAIL ${err?.reason ?? ''} ${String(err?.message ?? err)}`) } } console.log('# llm-provider-smoke') console.log(lines.join('\n')) console.log(`\nran=${ran} failed=${failed}`) if (failed > 0) process.exit(1) } main()