@cetusai/sdk 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/LICENSE +21 -0
- package/README.md +409 -0
- package/dist/index.cjs +910 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +518 -0
- package/dist/index.d.ts +518 -0
- package/dist/index.mjs +880 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.15_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","../src/errors.ts","../src/index.ts","../src/client.ts","../src/utils/cost.ts","../src/utils/id.ts","../src/utils/retry.ts","../src/utils/queue.ts","../src/guardrail.ts","../src/middleware/openai.ts","../src/middleware/anthropic.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import type { SonglinesErrorCode } from \"./types.js\";\n\n/**\n * Base error class for all Songlines SDK errors.\n *\n * The SDK never throws — all errors are surfaced via the `onError` callback\n * configured on the client. This class is provided for type-safe error handling\n * in the callback.\n */\nexport class SonglinesError extends Error {\n readonly code: SonglinesErrorCode;\n readonly statusCode: number | undefined;\n readonly retryable: boolean;\n\n constructor(\n message: string,\n code: SonglinesErrorCode,\n options?: {\n statusCode?: number;\n retryable?: boolean;\n cause?: unknown;\n }\n ) {\n super(message, { cause: options?.cause });\n this.name = \"SonglinesError\";\n this.code = code;\n this.statusCode = options?.statusCode !== undefined ? options.statusCode : undefined;\n this.retryable = options?.retryable ?? false;\n }\n}\n\nexport class InvalidConfigError extends SonglinesError {\n constructor(message: string) {\n super(message, \"INVALID_CONFIG\", { retryable: false });\n this.name = \"InvalidConfigError\";\n }\n}\n\nexport class InvalidApiKeyError extends SonglinesError {\n constructor() {\n super(\n \"Invalid or revoked API key. Check your SONGLINES_API_KEY environment variable.\",\n \"INVALID_API_KEY\",\n { statusCode: 401, retryable: false }\n );\n this.name = \"InvalidApiKeyError\";\n }\n}\n\nexport class NetworkError extends SonglinesError {\n constructor(message: string, cause?: unknown) {\n super(message, \"NETWORK_ERROR\", { retryable: true, cause });\n this.name = \"NetworkError\";\n }\n}\n\nexport class TimeoutError extends SonglinesError {\n constructor(timeoutMs: number) {\n super(\n `Request timed out after ${timeoutMs}ms`,\n \"TIMEOUT\",\n { retryable: true }\n );\n this.name = \"TimeoutError\";\n }\n}\n\nexport class RateLimitedError extends SonglinesError {\n readonly retryAfterMs: number | undefined;\n\n constructor(retryAfterMs?: number) {\n super(\n retryAfterMs\n ? `Rate limited. Retry after ${retryAfterMs}ms.`\n : \"Rate limited by the Songlines API.\",\n \"RATE_LIMITED\",\n { statusCode: 429, retryable: true }\n );\n this.name = \"RateLimitedError\";\n this.retryAfterMs = retryAfterMs !== undefined ? retryAfterMs : undefined;\n }\n}\n\nexport class ServerError extends SonglinesError {\n constructor(statusCode: number, body?: string) {\n super(\n `Songlines API returned ${statusCode}${body ? `: ${body}` : \"\"}`,\n \"SERVER_ERROR\",\n { statusCode, retryable: statusCode >= 500 }\n );\n this.name = \"ServerError\";\n }\n}\n\nexport class QueueOverflowError extends SonglinesError {\n readonly droppedCount: number;\n\n constructor(droppedCount: number) {\n super(\n `Event queue is full. Dropped ${droppedCount} event(s). Check network connectivity.`,\n \"QUEUE_OVERFLOW\",\n { retryable: false }\n );\n this.name = \"QueueOverflowError\";\n this.droppedCount = droppedCount;\n }\n}\n\nexport class PartialFailureError extends SonglinesError {\n readonly accepted: number;\n readonly failed: number;\n readonly failedIds: string[];\n\n constructor(accepted: number, failed: number, failedIds: string[]) {\n super(\n `Partial ingest failure: ${accepted} accepted, ${failed} failed.`,\n \"PARTIAL_FAILURE\",\n { retryable: false }\n );\n this.name = \"PartialFailureError\";\n this.accepted = accepted;\n this.failed = failed;\n this.failedIds = failedIds;\n }\n}\n","/**\n * @songlines/sdk\n *\n * Official SDK for Songlines Control — AI observability, cost attribution,\n * and governance for enterprise workloads.\n *\n * @example\n * ```typescript\n * import { SonglinesClient } from \"@songlines/sdk\";\n *\n * const songlines = new SonglinesClient({\n * apiKey: process.env.SONGLINES_API_KEY!,\n * });\n *\n * await songlines.trackAIRequest({\n * model: \"gpt-4o\",\n * provider: \"openai\",\n * workflow: \"invoice-processor\",\n * inputTokens: 1200,\n * outputTokens: 400,\n * latencyMs: 1840,\n * });\n * ```\n *\n * @see https://www.songlinesai.com/docs/sdk\n */\n\n// ── Core client ───────────────────────────────────────────────────────────────\nexport { SonglinesClient } from \"./client.js\";\n\n// ── Types ─────────────────────────────────────────────────────────────────────\nexport type {\n SonglinesClientConfig,\n TrackAIRequestParams,\n WrapOptions,\n Environment,\n RequestStatus,\n IngestEvent,\n IngestResponse,\n IngestResult,\n IngestError,\n SonglinesErrorCode,\n} from \"./types.js\";\n\n// ── Errors ────────────────────────────────────────────────────────────────────\nexport {\n SonglinesError,\n InvalidConfigError,\n InvalidApiKeyError,\n NetworkError,\n TimeoutError,\n RateLimitedError,\n ServerError,\n QueueOverflowError,\n PartialFailureError,\n} from \"./errors.js\";\n\n// ── Guardrail / Enforce path (v0.2.0) ───────────────────────────────────────\nexport { GuardrailBlockedError } from \"./guardrail.js\";\nexport type {\n GuardrailDecision,\n PolicyAction,\n GuardrailViolation,\n GuardrailResult,\n EvaluateGuardrailParams,\n} from \"./guardrail.js\";\n\n// ── Middleware ────────────────────────────────────────────────────────────────\nexport { wrapOpenAI } from \"./middleware/openai.js\";\nexport { wrapAnthropic } from \"./middleware/anthropic.js\";\n\n// ── Utilities (public) ────────────────────────────────────────────────────────\nexport { estimateCost, getModelRates } from \"./utils/cost.js\";\n","import {\n InvalidConfigError,\n InvalidApiKeyError,\n NetworkError,\n TimeoutError,\n RateLimitedError,\n ServerError,\n PartialFailureError,\n SonglinesError,\n} from \"./errors.js\";\nimport type {\n SonglinesClientConfig,\n TrackAIRequestParams,\n IngestEvent,\n IngestResponse,\n Environment,\n} from \"./types.js\";\nimport { estimateCost } from \"./utils/cost.js\";\nimport { generateId } from \"./utils/id.js\";\nimport { withRetry } from \"./utils/retry.js\";\nimport { BatchQueue } from \"./utils/queue.js\";\nimport { evaluateGuardrailImpl } from \"./guardrail.js\";\nimport type { EvaluateGuardrailParams, GuardrailResult } from \"./guardrail.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.songlinesai.com\";\nconst DEFAULT_BATCH_SIZE = 10;\nconst DEFAULT_FLUSH_INTERVAL_MS = 5_000;\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_RETRIES = 3;\nconst MAX_QUEUE_SIZE = 1_000;\n\n/**\n * Songlines Control SDK client.\n *\n * Instruments AI workloads with a single `trackAIRequest()` call per LLM\n * invocation. All telemetry is batched and sent asynchronously — the SDK\n * never blocks or slows down your AI calls.\n *\n * @example\n * ```typescript\n * import { SonglinesClient } from \"@songlines/sdk\";\n *\n * const songlines = new SonglinesClient({\n * apiKey: process.env.SONGLINES_API_KEY!,\n * });\n *\n * // After every LLM call:\n * await songlines.trackAIRequest({\n * model: \"gpt-4o\",\n * provider: \"openai\",\n * workflow: \"invoice-processor\",\n * inputTokens: response.usage.prompt_tokens,\n * outputTokens: response.usage.completion_tokens,\n * latencyMs: Date.now() - startTime,\n * });\n * ```\n */\nexport class SonglinesClient {\n private readonly config: Required<Omit<SonglinesClientConfig, \"onError\">> & {\n onError: (error: SonglinesError) => void;\n };\n private readonly queue: BatchQueue;\n\n constructor(config: SonglinesClientConfig) {\n // ── Validate config ────────────────────────────────────────────────────────\n if (!config.apiKey || typeof config.apiKey !== \"string\") {\n throw new InvalidConfigError(\n \"apiKey is required. Set SONGLINES_API_KEY in your environment and pass it as apiKey.\"\n );\n }\n if (config.apiKey.trim().length === 0) {\n throw new InvalidConfigError(\"apiKey must not be empty.\");\n }\n if (config.batchSize !== undefined && (config.batchSize < 1 || config.batchSize > 100)) {\n throw new InvalidConfigError(\"batchSize must be between 1 and 100.\");\n }\n if (config.flushIntervalMs !== undefined && config.flushIntervalMs < 100) {\n throw new InvalidConfigError(\"flushIntervalMs must be at least 100ms.\");\n }\n if (config.retries !== undefined && (config.retries < 0 || config.retries > 10)) {\n throw new InvalidConfigError(\"retries must be between 0 and 10.\");\n }\n\n this.config = {\n apiKey: config.apiKey.trim(),\n baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\"),\n environment: config.environment ?? \"production\",\n batchSize: config.batchSize ?? DEFAULT_BATCH_SIZE,\n flushIntervalMs: config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS,\n timeout: config.timeout ?? DEFAULT_TIMEOUT_MS,\n retries: config.retries ?? DEFAULT_RETRIES,\n onError: config.onError ?? (() => {}),\n debug: config.debug ?? false,\n };\n\n this.queue = new BatchQueue({\n batchSize: this.config.batchSize,\n flushIntervalMs: this.config.flushIntervalMs,\n maxQueueSize: MAX_QUEUE_SIZE,\n onError: this.config.onError,\n flush: (events) => this.sendBatch(events),\n debug: this.config.debug,\n });\n }\n\n // ── Public API ───────────────────────────────────────────────────────────────\n\n /**\n * Records an AI request event. The event is queued immediately and sent\n * asynchronously — this method returns as soon as the event is enqueued.\n *\n * The returned Promise resolves when the event has been enqueued (not when\n * it has been sent). Use `flush()` if you need confirmation of delivery.\n */\n async trackAIRequest(params: TrackAIRequestParams): Promise<void> {\n const event = this.buildEvent(params);\n this.queue.push(event);\n }\n\n /**\n * Forces an immediate flush of all queued events to the API.\n * Resolves when the flush completes (successfully or not).\n */\n async flush(): Promise<void> {\n await this.queue.flushNow();\n }\n\n /**\n * Flushes all remaining events and shuts down the background timer.\n * Call this during graceful shutdown (e.g. in a `process.on(\"SIGTERM\")` handler).\n *\n * @example\n * ```typescript\n * process.on(\"SIGTERM\", async () => {\n * await songlines.shutdown();\n * process.exit(0);\n * });\n * ```\n */\n async shutdown(): Promise<void> {\n await this.queue.shutdown();\n }\n\n /**\n * Evaluates a prompt against all active Songlines policies in real time.\n *\n * This method uses the **Songlines Gateway / Enforce** path, which is\n * distinct from `trackAIRequest()`. Call it *before* sending the prompt\n * to an LLM to enforce policies inline.\n *\n * @returns A `GuardrailResult` with `decision`, `violations`, and optionally\n * a `modifiedInput` (when a redaction policy fires).\n *\n * @example\n * ```typescript\n * const result = await songlines.evaluateGuardrail({\n * prompt: userMessage,\n * model: \"gpt-4o\",\n * workflow: \"customer-support\",\n * });\n *\n * if (result.decision === \"block\") {\n * return { error: \"Request blocked by policy\", violations: result.violations };\n * }\n *\n * const promptToSend = result.modifiedInput ?? userMessage;\n * const response = await openai.chat.completions.create({ ... });\n * ```\n */\n async evaluateGuardrail(params: EvaluateGuardrailParams): Promise<GuardrailResult> {\n return evaluateGuardrailImpl(params, {\n baseUrl: this.config.baseUrl,\n apiKey: this.config.apiKey,\n timeout: this.config.timeout,\n onError: this.config.onError,\n });\n }\n\n // ── Internal ─────────────────────────────────────────────────────────────────\n\n /**\n * Converts TrackAIRequestParams into the wire format expected by /api/ingest.\n */\n private buildEvent(params: TrackAIRequestParams): IngestEvent {\n const requestId = params.requestId ?? generateId();\n\n // Estimate cost if not provided\n const cost = params.cost ?? estimateCost({\n model: params.model,\n inputTokens: params.inputTokens,\n outputTokens: params.outputTokens,\n });\n\n const event: IngestEvent = {\n request_id: requestId,\n model: params.model,\n input_tokens: params.inputTokens,\n output_tokens: params.outputTokens,\n environment: this.config.environment as Environment,\n status: params.status ?? \"success\",\n };\n\n // Optional fields — only include if provided to keep payload minimal\n if (params.provider !== undefined) event.provider = params.provider;\n if (params.workflow !== undefined) event.workflow = params.workflow;\n if (params.step !== undefined) event.step = params.step;\n if (params.agentId !== undefined) event.agent_id = params.agentId;\n if (params.user !== undefined) event.user = params.user;\n if (params.latencyMs !== undefined) event.latency_ms = params.latencyMs;\n if (params.errorMessage !== undefined) event.error_message = params.errorMessage;\n if (params.timestamp !== undefined) {\n event.timestamp = params.timestamp.toISOString();\n }\n\n return event;\n }\n\n /**\n * Sends a batch of events to POST /api/ingest.\n * Called by the BatchQueue — never called directly.\n */\n private async sendBatch(events: IngestEvent[]): Promise<void> {\n const url = `${this.config.baseUrl}/api/ingest`;\n const body = events.length === 1 ? events[0] : { events };\n\n await withRetry(\n () => this.httpPost(url, body),\n {\n maxAttempts: this.config.retries + 1,\n onRetry: (attempt, delayMs, error) => {\n if (this.config.debug) {\n console.debug(\n `[Songlines SDK] Retry ${attempt} in ${delayMs}ms after: ${String(error)}`\n );\n }\n },\n }\n );\n }\n\n /**\n * Performs a single HTTP POST with timeout and error classification.\n */\n private async httpPost(url: string, body: unknown): Promise<void> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.config.timeout);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${this.config.apiKey}`,\n \"User-Agent\": \"@songlines/sdk/0.1.0\",\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new TimeoutError(this.config.timeout);\n }\n throw new NetworkError(`Failed to reach ${url}: ${String(err)}`, err);\n } finally {\n clearTimeout(timer);\n }\n\n // ── Classify response ────────────────────────────────────────────────────\n if (response.status === 401) {\n throw new InvalidApiKeyError();\n }\n\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"Retry-After\");\n const retryAfterMs = retryAfter ? parseInt(retryAfter, 10) * 1000 : undefined;\n throw new RateLimitedError(retryAfterMs);\n }\n\n if (response.status >= 500) {\n const text = await response.text().catch(() => \"\");\n throw new ServerError(response.status, text);\n }\n\n if (!response.ok && response.status !== 207) {\n const text = await response.text().catch(() => \"\");\n throw new ServerError(response.status, text);\n }\n\n // ── Parse response ────────────────────────────────────────────────────────\n const data = await response.json() as IngestResponse;\n\n if (data.failed > 0 && data.errors) {\n const failedIds = data.errors.map((e) => e.request_id);\n this.config.onError(new PartialFailureError(data.accepted, data.failed, failedIds));\n }\n }\n}\n","/**\n * Client-side cost estimation.\n *\n * Provides approximate USD costs based on publicly available per-million-token\n * pricing. Actual costs may differ due to batch discounts, enterprise agreements,\n * or provider pricing changes.\n *\n * Rates are per 1,000,000 tokens (input / output) in USD.\n * Last updated: June 2026.\n */\n\ninterface ModelRates {\n /** Cost per 1M input tokens in USD */\n input: number;\n /** Cost per 1M output tokens in USD */\n output: number;\n}\n\n// ── Model rate table ──────────────────────────────────────────────────────────\n// Keys are lowercase model name prefixes. Matched with startsWith() so\n// \"gpt-4o-2024-11-20\" matches the \"gpt-4o\" entry.\n\nconst MODEL_RATES: Record<string, ModelRates> = {\n // OpenAI\n \"gpt-4o-mini\": { input: 0.15, output: 0.60 },\n \"gpt-4o\": { input: 2.50, output: 10.00 },\n \"gpt-4-turbo\": { input: 10.00, output: 30.00 },\n \"gpt-4\": { input: 30.00, output: 60.00 },\n \"gpt-3.5-turbo\": { input: 0.50, output: 1.50 },\n \"o1-mini\": { input: 3.00, output: 12.00 },\n \"o1\": { input: 15.00, output: 60.00 },\n \"o3-mini\": { input: 1.10, output: 4.40 },\n \"o3\": { input: 10.00, output: 40.00 },\n \"o4-mini\": { input: 1.10, output: 4.40 },\n\n // Anthropic\n \"claude-3-5-haiku\": { input: 0.80, output: 4.00 },\n \"claude-3-5-sonnet\": { input: 3.00, output: 15.00 },\n \"claude-3-7-sonnet\": { input: 3.00, output: 15.00 },\n \"claude-3-opus\": { input: 15.00, output: 75.00 },\n \"claude-3-haiku\": { input: 0.25, output: 1.25 },\n \"claude-3-sonnet\": { input: 3.00, output: 15.00 },\n\n // Google\n \"gemini-2.0-flash\": { input: 0.10, output: 0.40 },\n \"gemini-2.5-flash\": { input: 0.15, output: 0.60 },\n \"gemini-2.5-pro\": { input: 1.25, output: 10.00 },\n \"gemini-1.5-flash\": { input: 0.075, output: 0.30 },\n \"gemini-1.5-pro\": { input: 1.25, output: 5.00 },\n\n // Mistral\n \"mistral-large\": { input: 2.00, output: 6.00 },\n \"mistral-small\": { input: 0.20, output: 0.60 },\n \"mistral-nemo\": { input: 0.15, output: 0.15 },\n \"codestral\": { input: 0.20, output: 0.60 },\n\n // Meta (via Groq / Together / Bedrock)\n \"llama-3.3-70b\": { input: 0.59, output: 0.79 },\n \"llama-3.1-405b\": { input: 2.70, output: 2.70 },\n \"llama-3.1-70b\": { input: 0.59, output: 0.79 },\n \"llama-3.1-8b\": { input: 0.05, output: 0.08 },\n\n // AWS Bedrock (Nova)\n \"amazon.nova-pro\": { input: 0.80, output: 3.20 },\n \"amazon.nova-lite\": { input: 0.06, output: 0.24 },\n \"amazon.nova-micro\": { input: 0.035, output: 0.14 },\n\n // Cohere\n \"command-r-plus\": { input: 2.50, output: 10.00 },\n \"command-r\": { input: 0.15, output: 0.60 },\n\n // DeepSeek\n \"deepseek-chat\": { input: 0.27, output: 1.10 },\n \"deepseek-reasoner\": { input: 0.55, output: 2.19 },\n};\n\n// ── Fallback rate for unknown models ─────────────────────────────────────────\nconst FALLBACK_RATES: ModelRates = { input: 1.00, output: 3.00 };\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\nexport interface CostEstimateParams {\n model: string;\n inputTokens: number;\n outputTokens: number;\n}\n\n/**\n * Estimates the USD cost of an AI request based on public model pricing.\n *\n * @returns Estimated cost in USD, rounded to 8 decimal places.\n * Returns 0 if token counts are 0.\n */\nexport function estimateCost({ model, inputTokens, outputTokens }: CostEstimateParams): number {\n if (inputTokens === 0 && outputTokens === 0) return 0;\n\n const normalised = model.toLowerCase().trim();\n const rates = findRates(normalised);\n\n const inputCost = (inputTokens / 1_000_000) * rates.input;\n const outputCost = (outputTokens / 1_000_000) * rates.output;\n\n return Math.round((inputCost + outputCost) * 1e8) / 1e8;\n}\n\n/**\n * Returns the rates for a model, using prefix matching.\n * Falls back to FALLBACK_RATES for unknown models.\n */\nexport function findRates(normalisedModel: string): ModelRates {\n // Exact match first\n if (normalisedModel in MODEL_RATES) {\n return MODEL_RATES[normalisedModel] as ModelRates;\n }\n\n // Prefix match — longest prefix wins\n let bestMatch = \"\";\n for (const key of Object.keys(MODEL_RATES)) {\n if (normalisedModel.startsWith(key) && key.length > bestMatch.length) {\n bestMatch = key;\n }\n }\n\n return bestMatch ? (MODEL_RATES[bestMatch] as ModelRates) : FALLBACK_RATES;\n}\n\n/**\n * Returns the known rate table. Useful for displaying pricing information.\n */\nexport function getModelRates(): Readonly<Record<string, ModelRates>> {\n return MODEL_RATES;\n}\n","/**\n * UUID v4 generator — zero external dependencies.\n * Uses Node.js crypto.randomUUID() when available (Node ≥ 14.17),\n * falls back to a manual implementation for older environments.\n */\nexport function generateId(): string {\n // Node.js 14.17+ / modern browsers\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n\n // Fallback: manual UUID v4\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n","import { SonglinesError } from \"../errors.js\";\n\nexport interface RetryOptions {\n /** Maximum number of attempts (including the first). @default 3 */\n maxAttempts?: number;\n /** Base delay in milliseconds. @default 500 */\n baseDelayMs?: number;\n /** Maximum delay cap in milliseconds. @default 30000 */\n maxDelayMs?: number;\n /** Jitter factor 0–1. Applied as ±factor * delay. @default 0.2 */\n jitter?: number;\n /** Called before each retry with the attempt number and delay. */\n onRetry?: (attempt: number, delayMs: number, error: unknown) => void;\n}\n\n/**\n * Executes `fn` with exponential backoff retries.\n *\n * Only retries if the thrown error is a `SonglinesError` with `retryable: true`,\n * or if it is a generic network-level error (no status code).\n *\n * @throws The last error if all attempts are exhausted.\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {}\n): Promise<T> {\n const {\n maxAttempts = 3,\n baseDelayMs = 500,\n maxDelayMs = 30_000,\n jitter = 0.2,\n onRetry,\n } = options;\n\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n\n // Do not retry non-retryable SDK errors\n if (err instanceof SonglinesError && !err.retryable) {\n throw err;\n }\n\n // Do not retry on the last attempt\n if (attempt === maxAttempts) {\n break;\n }\n\n const delay = computeDelay(attempt, baseDelayMs, maxDelayMs, jitter);\n onRetry?.(attempt, delay, err);\n await sleep(delay);\n }\n }\n\n throw lastError;\n}\n\n/**\n * Computes the delay for a given attempt using exponential backoff with jitter.\n *\n * delay = min(baseDelay * 2^(attempt-1), maxDelay) * (1 ± jitter)\n */\nexport function computeDelay(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number,\n jitter: number\n): number {\n const exponential = baseDelayMs * Math.pow(2, attempt - 1);\n const capped = Math.min(exponential, maxDelayMs);\n const jitterRange = capped * jitter;\n const jitterOffset = (Math.random() * 2 - 1) * jitterRange;\n return Math.max(0, Math.round(capped + jitterOffset));\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { QueueOverflowError, SonglinesError, NetworkError } from \"../errors.js\";\nimport type { IngestEvent } from \"../types.js\";\n\nexport type FlushFn = (events: IngestEvent[]) => Promise<void>;\n\nexport interface QueueOptions {\n /** Maximum events before auto-flush. @default 10 */\n batchSize: number;\n /** Maximum ms before auto-flush. @default 5000 */\n flushIntervalMs: number;\n /** Maximum events held in memory before dropping. @default 1000 */\n maxQueueSize: number;\n /** Called when events are dropped or flush fails after all retries. */\n onError: (error: SonglinesError) => void;\n /** Flush function — sends a batch to the API. */\n flush: FlushFn;\n /** When true, logs to console.debug. */\n debug: boolean;\n}\n\n/**\n * In-memory async batch queue for telemetry events.\n *\n * Events are pushed immediately and flushed either when the batch reaches\n * `batchSize` or when `flushIntervalMs` elapses — whichever comes first.\n *\n * The queue is capped at `maxQueueSize`. Events pushed beyond the cap are\n * dropped and reported via `onError`.\n *\n * All flush operations are fire-and-forget from the caller's perspective.\n * The `shutdown()` method performs a synchronous final flush.\n */\nexport class BatchQueue {\n private readonly queue: IngestEvent[] = [];\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private flushing = false;\n private readonly opts: QueueOptions;\n\n constructor(opts: QueueOptions) {\n this.opts = opts;\n this.scheduleFlush();\n }\n\n /**\n * Pushes an event onto the queue. Triggers an immediate flush if the\n * batch size threshold is reached.\n */\n push(event: IngestEvent): void {\n if (this.queue.length >= this.opts.maxQueueSize) {\n this.opts.onError(new QueueOverflowError(1));\n this.log(`Queue overflow — dropped event ${event.request_id}`);\n return;\n }\n\n this.queue.push(event);\n this.log(`Queued event ${event.request_id} (queue size: ${this.queue.length})`);\n\n if (this.queue.length >= this.opts.batchSize) {\n this.log(`Batch size reached (${this.opts.batchSize}) — flushing immediately`);\n void this.flushNow();\n }\n }\n\n /**\n * Flushes all queued events immediately.\n * Safe to call multiple times concurrently — subsequent calls wait for the\n * in-flight flush to complete before starting their own.\n */\n async flushNow(): Promise<void> {\n if (this.queue.length === 0) return;\n\n // Drain the queue atomically\n const batch = this.queue.splice(0, this.queue.length);\n this.log(`Flushing batch of ${batch.length} event(s)`);\n\n try {\n await this.opts.flush(batch);\n this.log(`Flush successful — ${batch.length} event(s) accepted`);\n } catch (err) {\n // Events are already removed from the queue — they are dropped on failure\n this.log(`Flush failed — ${batch.length} event(s) dropped: ${String(err)}`);\n // Surface the error via the onError callback so callers can observe failures\n if (err instanceof SonglinesError) {\n this.opts.onError(err);\n } else {\n this.opts.onError(new NetworkError(String(err), err));\n }\n }\n }\n\n /**\n * Cancels the periodic timer, flushes remaining events, and marks the queue\n * as shut down. No further events should be pushed after calling this.\n */\n async shutdown(): Promise<void> {\n this.cancelTimer();\n await this.flushNow();\n this.log(\"Queue shut down\");\n }\n\n // ── Private ─────────────────────────────────────────────────────────────────\n\n private scheduleFlush(): void {\n this.cancelTimer();\n this.flushTimer = setTimeout(() => {\n void this.flushNow().finally(() => this.scheduleFlush());\n }, this.opts.flushIntervalMs);\n\n // Ensure the timer does not prevent Node.js from exiting\n if (this.flushTimer.unref) {\n this.flushTimer.unref();\n }\n }\n\n private cancelTimer(): void {\n if (this.flushTimer !== null) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n }\n\n private log(message: string): void {\n if (this.opts.debug) {\n console.debug(`[Songlines SDK] ${message}`);\n }\n }\n\n /** Exposed for testing only. */\n get _queueLength(): number {\n return this.queue.length;\n }\n}\n","/**\n * @songlines/sdk — Guardrail Evaluation (v0.2.0)\n *\n * Provides real-time policy evaluation via the Songlines Gateway API.\n * Call evaluateGuardrail() before sending a prompt to an LLM to enforce\n * policies inline — blocking, redacting, or alerting as configured.\n *\n * Architecture note: This feature uses the Songlines Gateway / Enforce path,\n * which is distinct from the Control Ingest API used by trackAIRequest().\n * The Gateway sits inline in the request path; the Control Ingest API\n * receives telemetry after the model response.\n */\n\nimport type { SonglinesError } from \"./errors.js\";\n\n// ── Public types ──────────────────────────────────────────────────────────────\n\n/** The outcome of a guardrail evaluation. */\nexport type GuardrailDecision = \"allow\" | \"block\" | \"modify\";\n\n/** The action configured on the policy that triggered this violation. */\nexport type PolicyAction = \"block\" | \"alert\" | \"redact\" | \"log\";\n\n/** A single policy violation detected during evaluation. */\nexport interface GuardrailViolation {\n /** Internal policy identifier. */\n policyId: string;\n /** Human-readable policy name. */\n policyName: string;\n /** The action the policy is configured to take. */\n action: PolicyAction;\n /** Human-readable reason for the violation. */\n reason: string;\n /** The field that triggered the violation (e.g. \"prompt\", \"model\", \"workflow\"). */\n field: string;\n}\n\n/** The result of a guardrail evaluation. */\nexport interface GuardrailResult {\n /** The overall decision: allow, block, or modify. */\n decision: GuardrailDecision;\n /** All violations detected across all evaluated policies. */\n violations: GuardrailViolation[];\n /**\n * The modified prompt to send to the LLM.\n * Only present when `decision === \"modify\"` (e.g. PII redaction).\n * Use this instead of the original prompt when decision is \"modify\".\n */\n modifiedInput?: string;\n /** Evaluation latency in milliseconds. */\n latencyMs: number;\n /** Unique identifier for this evaluation (for audit correlation). */\n evaluationId: string;\n}\n\n/** Parameters for evaluateGuardrail(). */\nexport interface EvaluateGuardrailParams {\n /**\n * The prompt text to evaluate. This is the only content sent to the\n * Gateway — it is evaluated against policies and then discarded.\n * It is never stored in the Songlines platform.\n */\n prompt: string;\n /**\n * The model identifier the prompt will be sent to.\n * Used for model allowlist/denylist policy evaluation.\n */\n model: string;\n /**\n * The logical workflow or feature name.\n * Used for workflow-scoped policy evaluation.\n */\n workflow?: string;\n /**\n * The provider name (e.g. \"openai\", \"anthropic\", \"azure-openai\").\n * Used for provider-level policy enforcement.\n */\n provider?: string;\n /**\n * When true, throws a GuardrailBlockedError if the decision is \"block\".\n * When false (default), returns the result and lets the caller decide.\n * @default false\n */\n throwOnBlock?: boolean;\n}\n\n// ── Error ─────────────────────────────────────────────────────────────────────\n\n/**\n * Thrown by evaluateGuardrail() when `throwOnBlock: true` and the\n * guardrail returns `decision: \"block\"`.\n *\n * The full GuardrailResult is available on the `result` property.\n */\nexport class GuardrailBlockedError extends Error {\n readonly result: GuardrailResult;\n\n constructor(result: GuardrailResult) {\n const reasons = result.violations.map((v) => v.reason).join(\"; \");\n super(`Guardrail blocked request: ${reasons}`);\n this.name = \"GuardrailBlockedError\";\n this.result = result;\n }\n}\n\n// ── Internal API response shape ───────────────────────────────────────────────\n\nexport interface GuardrailApiResponse {\n decision: GuardrailDecision;\n violations: Array<{\n policy_id: string;\n policy_name: string;\n action: PolicyAction;\n reason: string;\n field: string;\n }>;\n modified_input?: string;\n latency_ms: number;\n evaluation_id: string;\n}\n\n// ── evaluateGuardrail implementation ─────────────────────────────────────────\n\nexport type EvaluateGuardrailFn = (\n params: EvaluateGuardrailParams,\n config: {\n baseUrl: string;\n apiKey: string;\n timeout: number;\n onError: (error: SonglinesError) => void;\n }\n) => Promise<GuardrailResult>;\n\nexport const evaluateGuardrailImpl: EvaluateGuardrailFn = async (\n params,\n config\n) => {\n const { NetworkError, ServerError, InvalidApiKeyError } = await import(\"./errors.js\");\n\n const url = `${config.baseUrl}/api/guardrail/evaluate`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), config.timeout);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": `Bearer ${config.apiKey}`,\n \"User-Agent\": \"@songlines/sdk/0.2.0\",\n },\n body: JSON.stringify({\n prompt: params.prompt,\n model: params.model,\n workflow: params.workflow,\n provider: params.provider,\n }),\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof Error && err.name === \"AbortError\") {\n const { TimeoutError } = await import(\"./errors.js\");\n throw new TimeoutError(config.timeout);\n }\n throw new NetworkError(`Failed to reach ${url}: ${String(err)}`, err);\n } finally {\n clearTimeout(timer);\n }\n\n if (response.status === 401) {\n throw new InvalidApiKeyError();\n }\n\n if (response.status >= 500) {\n const text = await response.text().catch(() => \"\");\n throw new ServerError(response.status, text);\n }\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new ServerError(response.status, text);\n }\n\n const data = await response.json() as GuardrailApiResponse;\n\n const result: GuardrailResult = {\n decision: data.decision,\n violations: data.violations.map((v) => ({\n policyId: v.policy_id,\n policyName: v.policy_name,\n action: v.action,\n reason: v.reason,\n field: v.field,\n })),\n latencyMs: data.latency_ms,\n evaluationId: data.evaluation_id,\n };\n\n if (data.modified_input !== undefined) {\n result.modifiedInput = data.modified_input;\n }\n\n if (params.throwOnBlock && result.decision === \"block\") {\n throw new GuardrailBlockedError(result);\n }\n\n return result;\n};\n","/**\n * OpenAI SDK wrapper for Songlines Control.\n *\n * Wraps an OpenAI client instance so that every `chat.completions.create()`\n * and `completions.create()` call is automatically instrumented with telemetry.\n *\n * Prompt and completion text are NEVER captured — only metadata\n * (model, tokens, latency, cost) is sent to the Songlines ingest API.\n *\n * @example\n * ```typescript\n * import OpenAI from \"openai\";\n * import { SonglinesClient } from \"@songlines/sdk\";\n *\n * const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });\n * const songlines = new SonglinesClient({ apiKey: process.env.SONGLINES_API_KEY! });\n *\n * const instrumentedOpenAI = songlines.wrapOpenAI(openai, {\n * workflow: \"invoice-processor\",\n * });\n *\n * // All calls through instrumentedOpenAI are automatically tracked\n * const response = await instrumentedOpenAI.chat.completions.create({\n * model: \"gpt-4o\",\n * messages: [{ role: \"user\", content: \"Hello\" }],\n * });\n * ```\n */\n\nimport { generateId } from \"../utils/id.js\";\nimport type { SonglinesClient } from \"../client.js\";\nimport type { WrapOptions } from \"../types.js\";\n\n// ── Type stubs for OpenAI SDK (peer dependency) ───────────────────────────────\n// We use minimal structural typing so the wrapper works with any OpenAI SDK\n// version ≥4 without importing the package directly in the core bundle.\n\ninterface OpenAIUsage {\n prompt_tokens?: number;\n completion_tokens?: number;\n}\n\ninterface ChatCompletionParams {\n model: string;\n stream?: boolean | null;\n [key: string]: unknown;\n}\n\ninterface ChatCompletionResponse {\n usage?: OpenAIUsage;\n [key: string]: unknown;\n}\n\ninterface CompletionParams {\n model: string;\n stream?: boolean | null;\n [key: string]: unknown;\n}\n\ninterface CompletionResponse {\n usage?: OpenAIUsage;\n [key: string]: unknown;\n}\n\n// ── Wrapper implementation ────────────────────────────────────────────────────\n\n/**\n * Wraps an OpenAI client to automatically track all LLM calls.\n * Returns a Proxy that is type-compatible with the original client.\n */\nexport function wrapOpenAI<T extends object>(\n client: T,\n songlines: SonglinesClient,\n defaults: WrapOptions = {}\n): T {\n return new Proxy(client, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n\n if (prop === \"chat\" && typeof value === \"object\" && value !== null) {\n return wrapChat(value as object, songlines, defaults);\n }\n\n if (prop === \"completions\" && typeof value === \"object\" && value !== null) {\n return wrapLegacyCompletions(value as object, songlines, defaults);\n }\n\n return value;\n },\n });\n}\n\nfunction wrapChat<T extends object>(\n chat: T,\n songlines: SonglinesClient,\n defaults: WrapOptions\n): T {\n return new Proxy(chat, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n\n if (prop === \"completions\" && typeof value === \"object\" && value !== null) {\n return wrapChatCompletions(value as object, songlines, defaults);\n }\n\n return value;\n },\n });\n}\n\nfunction wrapChatCompletions<T extends object>(\n completions: T,\n songlines: SonglinesClient,\n defaults: WrapOptions\n): T {\n return new Proxy(completions, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n\n if (prop === \"create\") {\n return async (params: ChatCompletionParams, options?: unknown) => {\n // Streaming responses cannot have usage extracted synchronously —\n // we track them with 0 tokens and note the stream flag.\n if (params.stream === true) {\n const requestId = generateId();\n const start = Date.now();\n const stream = await (value as Function).call(target, params, options);\n // Fire-and-forget with estimated 0 tokens (streaming usage not available)\n void songlines.trackAIRequest({\n requestId,\n model: params.model,\n provider: \"openai\",\n inputTokens: 0,\n outputTokens: 0,\n latencyMs: Date.now() - start,\n status: \"success\",\n metadata: { streaming: true },\n ...defaults,\n });\n return stream;\n }\n\n const requestId = generateId();\n const start = Date.now();\n\n let response: ChatCompletionResponse;\n let status: \"success\" | \"error\" = \"success\";\n let errorMessage: string | undefined;\n\n try {\n response = await (value as Function).call(target, params, options);\n } catch (err) {\n status = \"error\";\n errorMessage = err instanceof Error ? err.message : String(err);\n // Re-throw so the caller sees the original error\n void songlines.trackAIRequest({\n requestId,\n model: params.model,\n provider: \"openai\",\n inputTokens: 0,\n outputTokens: 0,\n latencyMs: Date.now() - start,\n status: \"error\",\n errorMessage,\n ...defaults,\n });\n throw err;\n }\n\n const latencyMs = Date.now() - start;\n\n void songlines.trackAIRequest({\n requestId,\n model: params.model,\n provider: \"openai\",\n inputTokens: response.usage?.prompt_tokens ?? 0,\n outputTokens: response.usage?.completion_tokens ?? 0,\n latencyMs,\n status,\n ...defaults,\n });\n\n return response;\n };\n }\n\n return value;\n },\n });\n}\n\nfunction wrapLegacyCompletions<T extends object>(\n completions: T,\n songlines: SonglinesClient,\n defaults: WrapOptions\n): T {\n return new Proxy(completions, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n\n if (prop === \"create\") {\n return async (params: CompletionParams, options?: unknown) => {\n if (params.stream === true) {\n return (value as Function).call(target, params, options);\n }\n\n const requestId = generateId();\n const start = Date.now();\n\n let response: CompletionResponse;\n try {\n response = await (value as Function).call(target, params, options);\n } catch (err) {\n void songlines.trackAIRequest({\n requestId,\n model: params.model,\n provider: \"openai\",\n inputTokens: 0,\n outputTokens: 0,\n latencyMs: Date.now() - start,\n status: \"error\",\n errorMessage: err instanceof Error ? err.message : String(err),\n ...defaults,\n });\n throw err;\n }\n\n void songlines.trackAIRequest({\n requestId,\n model: params.model,\n provider: \"openai\",\n inputTokens: response.usage?.prompt_tokens ?? 0,\n outputTokens: response.usage?.completion_tokens ?? 0,\n latencyMs: Date.now() - start,\n status: \"success\",\n ...defaults,\n });\n\n return response;\n };\n }\n\n return value;\n },\n });\n}\n","/**\n * Anthropic SDK wrapper for Songlines Control.\n *\n * Wraps an Anthropic client instance so that every `messages.create()` call\n * is automatically instrumented with telemetry.\n *\n * Prompt and completion text are NEVER captured — only metadata\n * (model, tokens, latency, cost) is sent to the Songlines ingest API.\n *\n * @example\n * ```typescript\n * import Anthropic from \"@anthropic-ai/sdk\";\n * import { SonglinesClient } from \"@songlines/sdk\";\n *\n * const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });\n * const songlines = new SonglinesClient({ apiKey: process.env.SONGLINES_API_KEY! });\n *\n * const instrumentedAnthropic = songlines.wrapAnthropic(anthropic, {\n * workflow: \"document-review\",\n * });\n *\n * const response = await instrumentedAnthropic.messages.create({\n * model: \"claude-3-5-sonnet-20241022\",\n * max_tokens: 1024,\n * messages: [{ role: \"user\", content: \"Hello\" }],\n * });\n * ```\n */\n\nimport { generateId } from \"../utils/id.js\";\nimport type { SonglinesClient } from \"../client.js\";\nimport type { WrapOptions } from \"../types.js\";\n\n// ── Type stubs for Anthropic SDK (peer dependency) ────────────────────────────\n\ninterface AnthropicUsage {\n input_tokens?: number;\n output_tokens?: number;\n}\n\ninterface MessageParams {\n model: string;\n stream?: boolean;\n [key: string]: unknown;\n}\n\ninterface MessageResponse {\n usage?: AnthropicUsage;\n [key: string]: unknown;\n}\n\n// ── Wrapper implementation ────────────────────────────────────────────────────\n\n/**\n * Wraps an Anthropic client to automatically track all `messages.create()` calls.\n */\nexport function wrapAnthropic<T extends object>(\n client: T,\n songlines: SonglinesClient,\n defaults: WrapOptions = {}\n): T {\n return new Proxy(client, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n\n if (prop === \"messages\" && typeof value === \"object\" && value !== null) {\n return wrapMessages(value as object, songlines, defaults);\n }\n\n return value;\n },\n });\n}\n\nfunction wrapMessages<T extends object>(\n messages: T,\n songlines: SonglinesClient,\n defaults: WrapOptions\n): T {\n return new Proxy(messages, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n\n if (prop === \"create\") {\n return async (params: MessageParams, options?: unknown) => {\n // Streaming: track with 0 tokens\n if (params.stream === true) {\n const requestId = generateId();\n const start = Date.now();\n const stream = await (value as Function).call(target, params, options);\n void songlines.trackAIRequest({\n requestId,\n model: params.model,\n provider: \"anthropic\",\n inputTokens: 0,\n outputTokens: 0,\n latencyMs: Date.now() - start,\n status: \"success\",\n metadata: { streaming: true },\n ...defaults,\n });\n return stream;\n }\n\n const requestId = generateId();\n const start = Date.now();\n\n let response: MessageResponse;\n try {\n response = await (value as Function).call(target, params, options);\n } catch (err) {\n void songlines.trackAIRequest({\n requestId,\n model: params.model,\n provider: \"anthropic\",\n inputTokens: 0,\n outputTokens: 0,\n latencyMs: Date.now() - start,\n status: \"error\",\n errorMessage: err instanceof Error ? err.message : String(err),\n ...defaults,\n });\n throw err;\n }\n\n void songlines.trackAIRequest({\n requestId,\n model: params.model,\n provider: \"anthropic\",\n inputTokens: response.usage?.input_tokens ?? 0,\n outputTokens: response.usage?.output_tokens ?? 0,\n latencyMs: Date.now() - start,\n status: \"success\",\n ...defaults,\n });\n\n return response;\n };\n }\n\n return value;\n },\n });\n}\n"],"mappings":"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","names":["NetworkError","ServerError","InvalidApiKeyError","TimeoutError","requestId","start","requestId","start"]}
|