SDK Node (floopy-sdk)
floopy-sdk e o cliente oficial Node/TypeScript do gateway Floopy. Ele envolve o pacote openai por composicao (sem fork, sem reimplementacao) e adiciona metodos tipados para cada endpoint exclusivo do Floopy.
- npm:
floopy-sdk - fonte: github.com/floopy/floopy-sdk-node
- Node minimo:
>=20
Instalacao
Seção intitulada “Instalacao”pnpm add floopy-sdk # ou: npm i floopy-sdk / bun add floopy-sdkQuick start
Seção intitulada “Quick start”import { Floopy } from "floopy-sdk";
const floopy = new Floopy({ apiKey: process.env.FLOOPY_API_KEY!,});
const response = await floopy.chat.completions.create({ model: "gpt-4o", messages: [{ role: "user", content: "Hello from Floopy!" }],});
console.log(response.choices[0]?.message?.content);floopy.chat, floopy.embeddings e floopy.models delegam para um cliente openai pre-configurado para o gateway. Os tipos sao identicos aos do pacote openai.
Floopy options
Seção intitulada “Floopy options”Use options para ativar comportamentos do gateway de forma tipada. Eles viram headers Floopy-* aplicados a toda chamada do cliente:
const floopy = new Floopy({ apiKey: process.env.FLOOPY_API_KEY!, options: { cache: { enabled: true, bucketMaxSize: 3 }, promptId: "cd4249d5-44d5-46c8-8961-9eb3861e1f7e", promptVersion: "1", llmSecurityEnabled: true, },});| Opcao | Header | Funcao |
|---|---|---|
cache.enabled | Floopy-Cache-Enabled | Liga/desliga cache exato + semantico |
cache.bucketMaxSize | Floopy-Cache-Bucket-Max-Size | Tamanho maximo do bucket semantico |
promptId | Floopy-Prompt-Id | Prompt armazenado a resolver |
promptVersion | Floopy-Prompt-Version | Versao fixada do promptId |
llmSecurityEnabled | floopy-llm-security-enabled | Pre-check do firewall LLM |
Override por chamada: cada metodo aceita requestOptions no segundo argumento.
Recursos exclusivos do Floopy
Seção intitulada “Recursos exclusivos do Floopy”Cada um mapeia um endpoint publico /v1/*. Erros sao subclasses de FloopyError.
feedback
Seção intitulada “feedback”const r = await floopy.chat.completions.create({ /* ... */ });await floopy.feedback.submit({ score: 9, useful: true, sessionId: r.id });decisions
Seção intitulada “decisions”const decision = await floopy.decisions.get(requestId);
const page = await floopy.decisions.list({ from, to, limit: 50 });
for await (const d of floopy.decisions.iterate({ from })) { /* uma decisao */ }for await (const p of floopy.decisions.pages({ from })) { /* uma pagina */ }experiments
Seção intitulada “experiments”const exp = await floopy.experiments.create({ name: "cost-vs-quality", variantARoutingRuleId: ruleA, variantBRoutingRuleId: ruleB,});const results = await floopy.experiments.results(exp.id);await floopy.experiments.rollback(exp.id);create e rollback injetam automaticamente o header X-Floopy-Confirm: experiments que o gateway exige.
constraints
Seção intitulada “constraints”const current = await floopy.constraints.get();await floopy.constraints.put({ costLimitMonthlyUsd: 100 });put e full-replace: campos omitidos sao resetados para null.
for await (const row of floopy.export.decisions({ from, to })) { // JSONL streamado, parseado e tipado}
const { rows, trailer } = floopy.export.decisionsWithTrailer({ from, to });for await (const r of rows) { /* ... */ }console.log(trailer.value); // populado apos o iterador terminarevaluations
Seção intitulada “evaluations”const run = await floopy.evaluations.create({ datasetId, model: "gpt-4o" });const status = await floopy.evaluations.get(run.id);const page = await floopy.evaluations.results(run.id, { limit: 100 });await floopy.evaluations.cancel(run.id);routing.explain
Seção intitulada “routing.explain”const explain = await floopy.routing.explain({ model, messages });console.log(explain.wouldSelect, explain.firewallDecision);Apenas para o plano Pro. wouldSelect e null quando o firewall bloquearia a requisicao.
Streaming
Seção intitulada “Streaming”O streaming de chat e delegado ao openai-node e retorna AsyncIterable<ChatCompletionChunk>:
const stream = await floopy.chat.completions.create({ model: "gpt-4o-mini", messages: [{ role: "user", content: "stream a haiku" }], stream: true,});for await (const chunk of stream) { process.stdout.write(chunk.choices[0]?.delta?.content ?? "");}floopy.export.decisions e um iterador async sobre o stream JSONL do gateway, respeitando o trailer.
Tratamento de erros
Seção intitulada “Tratamento de erros”import { FloopyAuthError, FloopyPlanError, FloopyRateLimitError, FloopyValidationError, FloopyServerError,} from "floopy-sdk";
try { await floopy.export.decisions({ from, to });} catch (err) { if (err instanceof FloopyRateLimitError) { await sleep((err.retryAfterSeconds ?? 1) * 1000); } else if (err instanceof FloopyPlanError) { console.error(`Upgrade do plano: feature ${err.feature} nao esta disponivel`); } else throw err;}chat.completions e embeddings lancam subclasses de OpenAI.APIError do SDK upstream.
Self-hosting / base URL custom
Seção intitulada “Self-hosting / base URL custom”const floopy = new Floopy({ apiKey: process.env.FLOOPY_API_KEY!, baseURL: "https://gateway.internal.acme.com/v1",});Roadmap
Seção intitulada “Roadmap”O SDK esta em 0.x enquanto a interface estabiliza. Em breve:
- Helper de React hooks (
floopy-sdk/react). - Entrypoints Edge / Deno.
- Geracao automatica de tipos a partir dos modelos Rust do gateway (hoje os tipos sao escritos a mao e validados por testes).