Ctrl K
ComunidadGuías…

scripts/smoke-all-providers.mjs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env node
/**
 * Smoke test: hit one call per representative model on every provider, then
 * verify each row landed in ClickHouse with the right cost/service_tier.
 *
 * Each call asks for tiny output (max 5-10 tokens) to keep total cost <$0.10.
 * Reuses the Spanlens key from setup-smoke-test.mjs.
 */

const SPANLENS_KEY = process.env.SPANLENS_KEY
if (!SPANLENS_KEY) {
  console.error('Set SPANLENS_KEY (from setup-smoke-test.mjs output)')
  process.exit(1)
}

const BASE = 'http://localhost:3001'

const TESTS = [
  // ── OpenAI ─────────────────────────────────────────────────────────────────
  { id: 'oa-1', provider: 'openai', model: 'gpt-4o-mini',  desc: 'GPT-4o-mini baseline' },
  { id: 'oa-2', provider: 'openai', model: 'gpt-4o',       desc: 'GPT-4o' },
  { id: 'oa-3', provider: 'openai', model: 'gpt-5-mini',   desc: 'GPT-5 base mini' },
  { id: 'oa-4', provider: 'openai', model: 'gpt-5.5',      desc: 'GPT-5.5 flagship (tier)', extra: { service_tier: 'priority' } },
  // ── Anthropic ──────────────────────────────────────────────────────────────
  { id: 'an-1', provider: 'anthropic', model: 'claude-haiku-4-5',  desc: 'Claude Haiku 4.5' },
  { id: 'an-2', provider: 'anthropic', model: 'claude-sonnet-4-6', desc: 'Claude Sonnet 4.6' },
  { id: 'an-3', provider: 'anthropic', model: 'claude-opus-4-7',   desc: 'Claude Opus 4.7 (flagship)' },
  // ── Gemini ─────────────────────────────────────────────────────────────────
  { id: 'gm-1', provider: 'gemini', model: 'gemini-2.5-flash-lite', desc: 'Gemini 2.5 Flash Lite' },
  { id: 'gm-2', provider: 'gemini', model: 'gemini-2.5-flash',      desc: 'Gemini 2.5 Flash' },
  { id: 'gm-3', provider: 'gemini', model: 'gemini-2.5-pro',        desc: 'Gemini 2.5 Pro (tier)' },
]

async function callOpenAI(t) {
  const body = {
    model: t.model,
    messages: [{ role: 'user', content: `say ${t.id}` }],
    max_tokens: 5,
    ...t.extra,
  }
  const res = await fetch(`${BASE}/proxy/openai/v1/chat/completions`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${SPANLENS_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  })
  return { status: res.status, body: await res.json() }
}

async function callAnthropic(t) {
  const body = {
    model: t.model,
    max_tokens: 10,
    messages: [{ role: 'user', content: `say ${t.id}` }],
  }
  const res = await fetch(`${BASE}/proxy/anthropic/v1/messages`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${SPANLENS_KEY}`,
      'Content-Type': 'application/json',
      'anthropic-version': '2023-06-01',
    },
    body: JSON.stringify(body),
  })
  return { status: res.status, body: await res.json() }
}

async function callGemini(t) {
  const body = {
    contents: [{ parts: [{ text: `say ${t.id}` }] }],
    generationConfig: { maxOutputTokens: 10 },
  }
  const res = await fetch(
    `${BASE}/proxy/gemini/v1beta/models/${t.model}:generateContent`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${SPANLENS_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(body),
    },
  )
  return { status: res.status, body: await res.json() }
}

const callers = {
  openai: callOpenAI,
  anthropic: callAnthropic,
  gemini: callGemini,
}

console.log('── Running calls ─────────────────────────────────────────────')
for (const t of TESTS) {
  try {
    const result = await callers[t.provider](t)
    const ok = result.status === 200
    const errMsg = ok ? '' : ` · ${JSON.stringify(result.body?.error ?? result.body).slice(0, 80)}`
    console.log(`${ok ? '✓' : '✗'} ${t.id.padEnd(5)} ${t.provider.padEnd(10)} ${t.model.padEnd(40)} status=${result.status}${errMsg}`)
  } catch (err) {
    console.log(`✗ ${t.id.padEnd(5)} ${t.provider.padEnd(10)} ${t.model.padEnd(40)} EXCEPTION: ${err.message}`)
  }
  // Tiny pause so CH inserts don't pile up
  await new Promise((r) => setTimeout(r, 200))
}

console.log('\nWaiting 3s for async log writes to ClickHouse…')
await new Promise((r) => setTimeout(r, 3000))
console.log('Done. Run the CH query in the report step.')