UNPKG

@traceprompt/node

Version:

Client-side encrypted, audit-ready logging for LLM applications

105 lines (93 loc) 2.84 kB
import { fetch } from "undici"; import { ConfigManager } from "../config"; import { retry } from "../utils/retry"; import { log } from "../utils/logger"; type HttpMethod = "POST" | "PUT" | "PATCH"; interface PostOptions { path: string; body: unknown; method?: HttpMethod; retries?: number; headers?: Record<string, string>; } export const Transport = { async post( path: string, body: unknown, retries = 5, headers?: Record<string, string> ): Promise<void> { await sendJson({ path, body, retries, method: "POST", headers }); }, }; async function sendJson(opts: PostOptions): Promise<void> { const { ingestUrl, apiKey } = ConfigManager.cfg; const url = new URL(opts.path, ingestUrl).toString(); const extra = opts.headers ?? {}; log.verbose(`Sending request to ${opts.path}`, { url: url, method: opts.method ?? "POST", retries: opts.retries ?? 5, hasBody: !!opts.body, }); await retry( async () => { const res = await fetch(url, { method: opts.method ?? "POST", headers: { "content-type": "application/json", "user-agent": "traceprompt-sdk/0.1.0", "x-api-key": apiKey, ...extra, }, body: JSON.stringify(opts.body), }); if (res.status >= 400) { const msg = await res.text(); const errorMessage = `HTTP ${res.status} - ${msg}`; if (res.status >= 500) { log.warn(`Server error (will retry): ${errorMessage}`, { status: res.status, url: url, response: msg, }); } else if (res.status === 429) { log.warn(`Rate limited (will retry): ${errorMessage}`, { status: res.status, url: url, response: msg, }); } else if (res.status === 401 || res.status === 403) { log.error(`Authentication/authorization error: ${errorMessage}`, { status: res.status, url: url, response: msg, hint: "Check your API key and organization permissions", }); } else { log.error(`Client error: ${errorMessage}`, { status: res.status, url: url, response: msg, }); } throw new Error(`Traceprompt: ${errorMessage}`); } log.debug(`Request successful`, { status: res.status, url: url, }); }, opts.retries ?? 5, 250, (error: unknown, attempt: number) => { log.verbose(`Request attempt ${attempt} failed, retrying...`, { error: error instanceof Error ? error.message : String(error), attempt: attempt, maxRetries: opts.retries ?? 5, url: url, }); } ); log.verbose(`Request completed successfully`, { url: url }); }