bitfab 0.9.2

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/baml.ts","../src/tracing.ts","../src/client.ts"],"sourcesContent":["/**\n * BAML execution utilities for the Bitfab TypeScript SDK.\n * This module provides functions to execute BAML prompts dynamically on the client side.\n */\n\ntype BamlModule = typeof import(\"@boundaryml/baml\")\n\nlet cachedBaml: BamlModule | null = null\n\nasync function loadBaml(): Promise<BamlModule> {\n if (cachedBaml) {\n return cachedBaml\n }\n try {\n cachedBaml = await import(\"@boundaryml/baml\")\n return cachedBaml\n } catch {\n throw new Error(\n \"@boundaryml/baml is required for Bitfab.call(). Install it with: npm install @boundaryml/baml\",\n )\n }\n}\n\n/**\n * Provider definition from the server.\n */\nexport interface ProviderDefinition {\n provider: string\n apiKeyEnv: string\n models: Array<{\n model: string\n description: string\n }>\n}\n\n/**\n * Result of a BAML function execution with raw collector data.\n */\nexport interface BamlExecutionResult {\n /** The parsed result of the function */\n result: unknown\n /** Raw collector data for the server to parse */\n rawCollector: Record<string, unknown> | null\n}\n\n/**\n * Capitalize first letter of a string.\n */\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1)\n}\n\n/**\n * Convert provider name to PascalCase.\n * e.g., \"openai\" -> \"OpenAI\", \"anthropic\" -> \"Anthropic\"\n */\nfunction formatProvider(provider: string): string {\n const providerMap: Record<string, string> = {\n openai: \"OpenAI\",\n anthropic: \"Anthropic\",\n google: \"Google\",\n }\n return providerMap[provider] ?? capitalize(provider)\n}\n\n/**\n * Convert a model name to a valid BAML identifier part.\n * e.g., \"gpt-5-mini\" -> \"GPT5_mini\", \"gpt-4.1\" -> \"GPT4_1\"\n */\nfunction formatModel(model: string): string {\n return model\n .replace(/^gpt-/, \"GPT\") // gpt- prefix -> GPT\n .replace(/\\./g, \"_\") // dots -> underscore\n .replace(/-/g, \"_\") // hyphens -> underscore\n}\n\n/**\n * Generate the BAML client name from provider and model.\n * e.g., \"openai\" + \"gpt-4.1-mini\" -> \"OpenAI_GPT4_1_mini\"\n */\nexport function getClientName(provider: string, model: string): string {\n return `${formatProvider(provider)}_${formatModel(model)}`\n}\n\n/**\n * Generates BAML client definition strings.\n * BamlRuntime.fromFiles requires clients to be defined in source for parsing.\n */\nfunction generateClientDefinitions(providers: ProviderDefinition[]): string {\n const definitions: string[] = []\n\n for (const providerDef of providers) {\n for (const model of providerDef.models) {\n const clientName = getClientName(providerDef.provider, model.model)\n definitions.push(`client<llm> ${clientName} {\n provider ${providerDef.provider}\n options {\n model \"${model.model}\"\n api_key env.${providerDef.apiKeyEnv}\n }\n}`)\n }\n }\n\n return definitions.join(\"\\n\\n\")\n}\n\n/**\n * Prepends the default client definitions to a BAML source if it doesn't already define them.\n */\nfunction withDefaultClients(\n bamlSource: string,\n providers: ProviderDefinition[],\n): string {\n const hasDefaultClient = bamlSource.includes(\"client<llm> OpenAI_\")\n if (hasDefaultClient) {\n return bamlSource\n }\n const defaultClients = generateClientDefinitions(providers)\n return `${defaultClients}\\n\\n${bamlSource}`\n}\n\n/**\n * Extracts the first function name from BAML source code.\n */\nfunction extractFunctionName(bamlSource: string): string | null {\n const match = bamlSource.match(/function\\s+(\\w+)\\s*\\(/)\n return match?.[1] ?? null\n}\n\n/**\n * Parameter type information extracted from BAML function signature.\n */\nexport interface BamlParameterType {\n name: string\n type: string\n isOptional: boolean\n}\n\n/**\n * Extracts function parameter names and types from BAML source code.\n * Used to properly coerce inputs based on expected types.\n */\nexport function extractFunctionParameters(\n bamlSource: string,\n): BamlParameterType[] {\n const functionMatch = bamlSource.match(/function\\s+\\w+\\s*\\(([^)]*)\\)\\s*->/)\n if (!functionMatch) {\n return []\n }\n\n const paramsString = functionMatch[1].trim()\n if (!paramsString) {\n return []\n }\n\n const params: BamlParameterType[] = []\n const paramParts = splitParameters(paramsString)\n\n for (const part of paramParts) {\n const trimmed = part.trim()\n if (!trimmed) {\n continue\n }\n\n const paramMatch = trimmed.match(/^(\\w+)\\s*:\\s*(.+)$/)\n if (paramMatch) {\n const name = paramMatch[1]\n let type = paramMatch[2].trim()\n const isOptional = type.endsWith(\"?\")\n if (isOptional) {\n type = type.slice(0, -1)\n }\n params.push({ name, type, isOptional })\n }\n }\n\n return params\n}\n\n/**\n * Split parameter string by commas, respecting nested angle brackets.\n */\nfunction splitParameters(paramsString: string): string[] {\n const parts: string[] = []\n let current = \"\"\n let depth = 0\n\n for (const char of paramsString) {\n if (char === \"<\") {\n depth++\n current += char\n } else if (char === \">\") {\n depth--\n current += char\n } else if (char === \",\" && depth === 0) {\n parts.push(current)\n current = \"\"\n } else {\n current += char\n }\n }\n\n if (current.trim()) {\n parts.push(current)\n }\n\n return parts\n}\n\n/**\n * Coerce a single string value to the expected BAML type.\n * Returns the coerced value, or the original string if coercion fails.\n */\nfunction coerceToType(value: string, expectedType: string): unknown {\n // String type - keep as is\n if (expectedType === \"string\") {\n return value\n }\n\n // Integer type\n if (expectedType === \"int\") {\n const parsed = Number.parseInt(value, 10)\n if (!Number.isNaN(parsed)) {\n return parsed\n }\n return value\n }\n\n // Float type\n if (expectedType === \"float\") {\n const parsed = Number.parseFloat(value)\n if (!Number.isNaN(parsed)) {\n return parsed\n }\n return value\n }\n\n // Boolean type\n if (expectedType === \"bool\") {\n const lower = value.toLowerCase()\n if (lower === \"true\") {\n return true\n }\n if (lower === \"false\") {\n return false\n }\n return value\n }\n\n // Array types (e.g., string[], int[])\n if (expectedType.endsWith(\"[]\")) {\n try {\n const parsed = JSON.parse(value)\n if (Array.isArray(parsed)) {\n return parsed\n }\n } catch {\n // Not valid JSON array\n }\n return value\n }\n\n // Complex types (objects, classes, maps) - try JSON parse\n try {\n return JSON.parse(value)\n } catch {\n return value\n }\n}\n\n/**\n * Coerces input values from strings to their appropriate types based on expected BAML types.\n * Actively coerces to the expected type (int, float, bool, etc.) rather than just avoiding\n * unintended conversions.\n */\nfunction coerceInputs(\n inputs: Record<string, unknown>,\n expectedTypes: Map<string, string>,\n): Record<string, unknown> {\n const coerced: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(inputs)) {\n if (typeof value === \"string\") {\n const expectedType = expectedTypes.get(key)\n\n if (expectedType) {\n coerced[key] = coerceToType(value, expectedType)\n } else {\n // No expected type info - keep as string\n coerced[key] = value\n }\n } else {\n coerced[key] = value\n }\n }\n\n return coerced\n}\n\n/**\n * Recursively convert an object to a JSON-serializable structure.\n * Similar to Python's _obj_to_dict function.\n */\nfunction objToDict(obj: unknown, depth = 0, maxDepth = 5): unknown {\n if (depth > maxDepth) {\n return `<max depth reached: ${typeof obj}>`\n }\n\n // Handle primitives\n if (\n obj === null ||\n obj === undefined ||\n typeof obj === \"string\" ||\n typeof obj === \"number\" ||\n typeof obj === \"boolean\"\n ) {\n return obj\n }\n\n // Handle arrays\n if (Array.isArray(obj)) {\n return obj.map((item) => objToDict(item, depth + 1, maxDepth))\n }\n\n // Handle plain objects and class instances\n if (typeof obj === \"object\") {\n const result: Record<string, unknown> = {}\n\n // Add type information for non-plain objects\n if (obj.constructor && obj.constructor.name !== \"Object\") {\n result.__type__ = obj.constructor.name\n }\n\n // Extract all enumerable properties\n for (const key of Object.keys(obj)) {\n if (key.startsWith(\"_\")) {\n continue // Skip private properties\n }\n\n try {\n const value = (obj as Record<string, unknown>)[key]\n\n // Skip functions\n if (typeof value === \"function\") {\n continue\n }\n\n result[key] = objToDict(value, depth + 1, maxDepth)\n } catch (error) {\n result[key] =\n `<error: ${error instanceof Error ? error.message : String(error)}>`\n }\n }\n\n // Also try to get non-enumerable properties from the prototype\n // This helps capture getters and computed properties\n try {\n const proto = Object.getPrototypeOf(obj)\n if (proto && proto !== Object.prototype) {\n const descriptors = Object.getOwnPropertyDescriptors(proto)\n for (const [key, descriptor] of Object.entries(descriptors)) {\n if (key.startsWith(\"_\") || key === \"constructor\" || key in result) {\n continue\n }\n\n // Try to get the value if it has a getter\n if (descriptor.get) {\n try {\n const value = (obj as Record<string, unknown>)[key]\n if (typeof value !== \"function\") {\n result[key] = objToDict(value, depth + 1, maxDepth)\n }\n } catch {\n // Getter might throw or be inaccessible\n }\n }\n }\n }\n } catch {\n // Prototype inspection might fail\n }\n\n return result\n }\n\n // Fallback for other types\n return String(obj)\n}\n\n/**\n * Serialize the BAML Collector to a JSON-serializable structure.\n * Recursively extracts all properties from the Collector for server-side parsing.\n */\nfunction serializeCollector(\n collector: unknown,\n): Record<string, unknown> | null {\n try {\n return objToDict(collector, 0, 5) as Record<string, unknown>\n } catch (_error) {\n // Silently ignore serialization failures\n return null\n }\n}\n\n/**\n * Allowed environment variable keys for LLM providers.\n * Only these keys will be passed to the BAML runtime.\n */\nconst ALLOWED_ENV_KEYS = [\"OPENAI_API_KEY\"] as const\n\n/**\n * Type for allowed environment variables.\n * Only OPENAI_API_KEY is currently supported.\n */\nexport type AllowedEnvVars = {\n OPENAI_API_KEY?: string\n}\n\n/**\n * Filters environment variables to only include allowed keys.\n * This prevents accidentally passing sensitive environment variables to the BAML runtime.\n */\nfunction filterEnvVars(envVars: AllowedEnvVars): Record<string, string> {\n const filtered: Record<string, string> = {}\n for (const key of ALLOWED_ENV_KEYS) {\n const value = envVars[key]\n if (value) {\n filtered[key] = value\n }\n }\n return filtered\n}\n\n/**\n * Runs the BAML function with the given inputs using the BAML runtime directly.\n * No file generation or subprocess spawning needed.\n *\n * @param bamlSource - The BAML source code containing the function\n * @param inputs - Named arguments to pass to the function\n * @param providers - Available provider definitions\n * @param envVars - Environment variables for API keys (only OPENAI_API_KEY is allowed)\n * @returns The result and execution metadata of the BAML function call\n */\nexport async function runFunctionWithBaml(\n bamlSource: string,\n inputs: Record<string, unknown>,\n providers: ProviderDefinition[],\n envVars: AllowedEnvVars,\n): Promise<BamlExecutionResult> {\n const { BamlRuntime, Collector } = await loadBaml()\n\n // Extract function name from the BAML source\n const functionName = extractFunctionName(bamlSource)\n if (!functionName) {\n throw new Error(\"No function found in BAML source\")\n }\n\n // Add default client definitions (runtime needs them for parsing)\n const fullSource = withDefaultClients(bamlSource, providers)\n\n // Filter env vars to only allowed keys\n const filteredEnvVars = filterEnvVars(envVars)\n\n // Create runtime from source with env vars\n const runtime = BamlRuntime.fromFiles(\n \"/tmp/baml_runtime\",\n { \"source.baml\": fullSource },\n filteredEnvVars,\n )\n\n // Create context manager\n const ctx = runtime.createContextManager()\n\n // Create collector to capture execution metadata\n const collector = new Collector(\"bitfab-collector\")\n\n // Extract expected parameter types from BAML source\n const params = extractFunctionParameters(bamlSource)\n const expectedTypes = new Map(params.map((p) => [p.name, p.type]))\n\n // Coerce inputs from strings to proper types based on BAML signature\n const args = coerceInputs(inputs, expectedTypes)\n\n // Call the function with collector\n const functionResult = await runtime.callFunction(\n functionName,\n args,\n ctx,\n null, // TypeBuilder\n null, // ClientRegistry\n [collector], // Collectors - capture execution data\n {}, // Tags\n filteredEnvVars,\n )\n\n if (!functionResult.isOk()) {\n throw new Error(\"BAML function execution failed\")\n }\n\n // Serialize the collector to a dict for the server to parse\n const rawCollector = serializeCollector(collector)\n\n return {\n result: functionResult.parsed(false),\n rawCollector,\n }\n}\n","/**\n * Tracing utilities for external trace submission to Bitfab.\n *\n * This module provides utilities for sending external traces (e.g., from OpenAI API calls)\n * to Bitfab for monitoring and analysis.\n */\n\nimport type { Span, Trace } from \"@openai/agents\"\nimport { DEFAULT_SERVICE_URL } from \"./constants.js\"\nimport { HttpClient } from \"./http.js\"\n\nexport interface TraceResponse {\n traceId: string\n status: \"success\"\n}\n\nexport interface ActiveSpanContext {\n traceId: string\n spanId: string\n}\n\n/**\n * TracingProcessor interface from OpenAI Agents SDK v0.3.7\n */\nexport interface TracingProcessor {\n onTraceStart(trace: Trace): Promise<void>\n onTraceEnd(trace: Trace): Promise<void>\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n onSpanStart(span: Span<any>): Promise<void>\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n onSpanEnd(span: Span<any>): Promise<void>\n forceFlush(): Promise<void>\n shutdown(timeout?: number): Promise<void>\n}\n\n/**\n * Tracing processor for OpenAI Agents SDK integration.\n *\n * Implements the TracingProcessor interface from the OpenAI Agents SDK to\n * automatically capture traces and spans and send them to Bitfab for\n * monitoring and analysis.\n *\n * Example usage:\n * ```typescript\n * import { Bitfab } from '@goharvest/bitfab';\n * import { addTraceProcessor } from '@openai/agents';\n *\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n * const processor = client.getOpenAiTracingProcessor();\n * addTraceProcessor(processor);\n * ```\n */\nexport class BitfabOpenAITracingProcessor implements TracingProcessor {\n private readonly httpClient: HttpClient\n private activeTraces: Record<string, Trace> = {}\n private readonly getActiveSpanContext: (() => ActiveSpanContext | null) | null\n private activeSpanMappings: Record<string, ActiveSpanContext> = {}\n\n /**\n * Initialize the tracing processor.\n *\n * @param config - Configuration options\n */\n constructor(config: {\n apiKey?: string\n serviceUrl?: string\n timeout?: number\n getActiveSpanContext?: () => ActiveSpanContext | null\n }) {\n this.httpClient = new HttpClient({\n apiKey: config.apiKey,\n serviceUrl: config.serviceUrl ?? DEFAULT_SERVICE_URL,\n timeout: config.timeout ?? 10000,\n })\n this.getActiveSpanContext = config.getActiveSpanContext ?? null\n }\n\n /**\n * Called when a trace is started.\n * If there's an active withSpan context, the trace ID is remapped to the\n * outer trace and sent to pre-create the external_traces row on the server.\n */\n async onTraceStart(trace: Trace): Promise<void> {\n this.activeTraces[trace.traceId] = trace\n\n const activeContext = this.getActiveSpanContext?.()\n if (activeContext) {\n this.activeSpanMappings[trace.traceId] = activeContext\n }\n\n this.sendTrace(trace, activeContext ? { id: activeContext.traceId } : {})\n }\n\n /**\n * Called when a trace is ended.\n * If mapped to a withSpan trace, sends with remapped ID and completed=false\n * since the parent withSpan handles completion.\n */\n async onTraceEnd(trace: Trace): Promise<void> {\n const mapping = this.activeSpanMappings[trace.traceId]\n\n this.sendTrace(\n trace,\n mapping ? { id: mapping.traceId } : { completed: true },\n )\n\n delete this.activeSpanMappings[trace.traceId]\n delete this.activeTraces[trace.traceId]\n }\n\n /**\n * Called when a span is started.\n */\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n async onSpanStart(span: Span<any>): Promise<void> {\n // Send the span to Bitfab (fire-and-forget)\n this.sendSpan(span)\n }\n\n /**\n * Called when a span is ended.\n *\n * Send all spans to Bitfab for complete trace capture.\n */\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n async onSpanEnd(span: Span<any>): Promise<void> {\n // Send the span to Bitfab again to capture updates (fire-and-forget)\n this.sendSpan(span)\n }\n\n /**\n * Called when a trace is being flushed.\n */\n async forceFlush(): Promise<void> {\n // No buffering, so nothing to flush\n }\n\n /**\n * Called when the trace processor is shutting down.\n */\n async shutdown(_timeout?: number): Promise<void> {\n this.activeTraces = {}\n this.activeSpanMappings = {}\n }\n\n /**\n * Send trace to Bitfab API (fire-and-forget).\n * When traceIdOverride is provided, the trace ID is remapped to link\n * the OpenAI trace into an outer withSpan trace.\n */\n private sendTrace(\n trace: Trace,\n overrides: { completed?: boolean; id?: string } = {},\n ): void {\n try {\n const { completed, ...traceOverrides } = overrides\n const traceData = trace.toJSON() as Record<string, unknown>\n Object.assign(traceData, traceOverrides)\n\n this.httpClient.sendExternalTrace({\n type: \"openai\",\n source: \"typescript-sdk-openai-tracing\",\n externalTrace: traceData,\n completed: completed ?? false,\n })\n } catch {\n // Silently ignore — never crash the host app\n }\n }\n\n /**\n * Export span to JSON object, collecting any errors.\n */\n private exportSpan(\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n span: Span<any>,\n ): [Record<string, unknown>, Array<{ step: string; error: string }>] {\n const errors: Array<{ step: string; error: string }> = []\n let serializedSpan: Record<string, unknown>\n\n try {\n const jsonResult = span.toJSON()\n if (typeof jsonResult !== \"object\" || jsonResult === null) {\n errors.push({\n step: \"span.toJSON()\",\n error: `Returned unexpected type: ${typeof jsonResult}`,\n })\n serializedSpan = {}\n } else {\n serializedSpan = jsonResult as Record<string, unknown>\n }\n } catch (error) {\n errors.push({\n step: \"span.toJSON()\",\n error: error instanceof Error ? error.message : String(error),\n })\n serializedSpan = {}\n }\n\n if (!serializedSpan.span_data) {\n serializedSpan.span_data = {} as Record<string, unknown>\n }\n\n return [serializedSpan, errors]\n }\n\n /**\n * Extract and add input/response to serialized span, updating errors list.\n */\n private extractSpanInputResponse(\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n span: Span<any>,\n serializedSpan: Record<string, unknown>,\n errors: Array<{ step: string; error: string }>,\n ): void {\n const spanData = serializedSpan.span_data as Record<string, unknown>\n\n try {\n spanData.input = span.spanData?._input || []\n } catch (error) {\n errors.push({\n step: \"access_input\",\n error: error instanceof Error ? error.message : String(error),\n })\n }\n\n try {\n spanData.response = span.spanData?._response || null\n } catch (error) {\n errors.push({\n step: \"access_response\",\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n\n /**\n * If the span's trace is mapped to a withSpan trace, rewrite trace_id and parent_id.\n */\n private applySpanOverrides(\n serializedSpan: Record<string, unknown>,\n traceId: string,\n ): void {\n const mapping = this.activeSpanMappings[traceId]\n if (mapping) {\n serializedSpan.trace_id = mapping.traceId\n if (!serializedSpan.parent_id) {\n serializedSpan.parent_id = mapping.spanId\n }\n }\n }\n\n /**\n * Build span payload for the external spans API.\n */\n private buildSpanPayload(\n serializedSpan: Record<string, unknown>,\n errors: Array<{ step: string; error: string }>,\n ): Record<string, unknown> {\n const payload: Record<string, unknown> = {\n type: \"openai\",\n source: \"typescript-sdk-openai-tracing\",\n sourceTraceId: serializedSpan.trace_id ?? \"unknown\",\n rawSpan: serializedSpan,\n }\n\n if (errors.length > 0) {\n payload.errors = errors\n }\n\n return payload\n }\n\n /**\n * Send span to Bitfab API (fire-and-forget).\n * If the span belongs to a trace mapped to a withSpan trace, the trace_id\n * and parent_id are rewritten to link the span into the withSpan tree.\n */\n private sendSpan(\n // biome-ignore lint/suspicious/noExplicitAny: OpenAI Agents SDK uses any for span data\n span: Span<any>,\n ): void {\n const errors: Array<{ step: string; error: string }> = []\n const [serializedSpan, exportErrors] = this.exportSpan(span)\n errors.push(...exportErrors)\n\n this.extractSpanInputResponse(span, serializedSpan, errors)\n\n this.applySpanOverrides(serializedSpan, span.traceId ?? \"\")\n\n const payload = this.buildSpanPayload(serializedSpan, errors)\n\n this.httpClient.sendExternalSpan(payload)\n }\n}\n","/**\n * Bitfab client for provider-based API calls.\n */\n\nimport {\n type AsyncLocalStorageLike,\n asyncStorageReady,\n createAsyncLocalStorage,\n isAsyncStorageInitDone,\n} from \"./asyncStorage.js\"\nimport {\n type AllowedEnvVars,\n type ProviderDefinition,\n runFunctionWithBaml,\n} from \"./baml.js\"\nimport { DEFAULT_SERVICE_URL } from \"./constants.js\"\nimport { BitfabError, HttpClient } from \"./http.js\"\nimport { getReplayContext } from \"./replayContext.js\"\nimport { serializeValue } from \"./serialize.js\"\nimport { BitfabOpenAITracingProcessor } from \"./tracing.js\"\n\n// Context entry for addContext calls - each entry is an object with multiple key-value pairs\ntype ContextEntry = Record<string, unknown>\n\n// Trace state for tracking trace-level data\ninterface TraceState {\n traceId: string\n sessionId?: string\n metadata?: Record<string, unknown>\n contexts: ContextEntry[]\n startedAt: string\n}\n\n// Span context for tracking nested spans\ninterface SpanContext {\n traceId: string\n spanId: string\n contexts: ContextEntry[]\n prompt?: string\n}\n\n// Global map to track active trace states\nconst activeTraceStates = new Map<string, TraceState>()\nconst pendingSpanPromises = new Map<string, Promise<unknown>[]>()\n\nlet asyncLocalStorage: AsyncLocalStorageLike<SpanContext[]> | null = null\n\nconst asyncLocalStorageReady: Promise<void> = asyncStorageReady.then(() => {\n asyncLocalStorage = createAsyncLocalStorage<SpanContext[]>()\n})\n\n// Browser fallback: a single module-level stack shared across all async\n// execution chains. Works correctly for synchronous nesting and sequential\n// async nesting (the common browser cases), but breaks when multiple\n// independent spans are in-flight concurrently (e.g. Promise.all with\n// separate withSpan calls). In that scenario, whichever span resumes last\n// overwrites the shared stack, so inner spans may see the wrong parent.\n//\n// Node.js avoids this via AsyncLocalStorage, which gives each async chain\n// its own isolated copy of the stack.\n//\n// Potential future fixes:\n// - TC39 AsyncContext proposal (stage 2) would provide AsyncLocalStorage\n// semantics natively in all JS environments, including browsers.\n// https://github.com/tc39/proposal-async-context\n// - Zone.js could work today but is ~50KB, monkey-patches Promise/setTimeout/\n// fetch/etc., and can conflict with frameworks like React. Too invasive for\n// an SDK dependency.\nlet browserSpanStack: SpanContext[] = []\n\nfunction getSpanStack(): SpanContext[] {\n if (asyncLocalStorage) {\n return asyncLocalStorage.getStore() ?? []\n }\n return browserSpanStack\n}\n\nfunction runWithSpanStack<T>(stack: SpanContext[], fn: () => T): T {\n if (asyncLocalStorage) {\n return asyncLocalStorage.run(stack, fn)\n }\n // Browser fallback: save/restore the stack around the function call.\n // This is correct for sequential async but not for concurrent async —\n // see the browserSpanStack comment above for details.\n const previousStack = browserSpanStack\n browserSpanStack = stack\n try {\n const result = fn()\n if (result instanceof Promise) {\n return result.finally(() => {\n browserSpanStack = previousStack\n }) as T\n }\n browserSpanStack = previousStack\n return result\n } catch (error) {\n browserSpanStack = previousStack\n throw error\n }\n}\n\n// --- BAML Collector support for wrapBAML ---\n\ntype CollectorConstructor = new (name: string) => unknown\n\nlet cachedCollectorClass: CollectorConstructor | null | undefined\n\n/** @internal Reset the cached Collector class — for testing only. */\nexport function _resetCollectorCache(): void {\n cachedCollectorClass = undefined\n}\n\n/** @internal Inject a mock Collector class — for testing only. */\nexport function _setCollectorCache(cls: CollectorConstructor | null): void {\n cachedCollectorClass = cls\n}\n\nasync function loadCollectorClass(): Promise<CollectorConstructor | null> {\n if (cachedCollectorClass !== undefined) {\n return cachedCollectorClass\n }\n try {\n const baml = await import(\"@boundaryml/baml\")\n cachedCollectorClass = baml.Collector as CollectorConstructor\n return cachedCollectorClass\n } catch {\n cachedCollectorClass = null\n return null\n }\n}\n\n// Typed accessors for the BAML Collector's internal structure.\n// Uses defensive access since these are untyped objects from the BAML runtime.\n\ninterface CollectorCall {\n selected?: boolean\n clientName?: string\n provider?: string\n usage?: {\n inputTokens?: number\n outputTokens?: number\n cachedInputTokens?: number\n }\n httpRequest?: {\n url?: string\n body?: { json: () => Record<string, unknown> | null }\n }\n}\n\ninterface CollectorLog {\n calls?: CollectorCall[]\n timing?: { durationMs?: number }\n}\n\ninterface CollectorLike {\n last?: CollectorLog | null\n usage?: {\n inputTokens?: number\n outputTokens?: number\n cachedInputTokens?: number\n }\n}\n\nfunction extractPromptFromCollector(collector: unknown): string | null {\n try {\n const c = collector as CollectorLike\n const calls = c?.last?.calls ?? []\n const selectedCall = calls.find((call) => call.selected) ?? calls[0]\n if (!selectedCall?.httpRequest?.body) {\n return null\n }\n const body = selectedCall.httpRequest.body.json()\n if (!body || typeof body !== \"object\") {\n return null\n }\n const messages = body.messages\n if (!Array.isArray(messages) || messages.length === 0) {\n return null\n }\n const rendered = (messages as Record<string, unknown>[])\n .filter(\n (msg): msg is { role: string; content: unknown } =>\n typeof msg === \"object\" &&\n msg !== null &&\n \"role\" in msg &&\n typeof (msg as { role: unknown }).role === \"string\",\n )\n .map((msg) => ({\n role: msg.role,\n content:\n typeof msg.content === \"string\"\n ? msg.content\n : JSON.stringify(msg.content),\n }))\n if (rendered.length > 0) {\n return JSON.stringify(rendered)\n }\n return null\n } catch {\n return null\n }\n}\n\nfunction extractContextFromCollector(\n collector: unknown,\n): Record<string, unknown> | null {\n try {\n const c = collector as CollectorLike\n const calls = c?.last?.calls ?? []\n const selectedCall = calls.find((call) => call.selected) ?? calls[0]\n const usage = c?.usage\n\n const context: Record<string, unknown> = {}\n if (selectedCall?.provider) {\n context.provider = selectedCall.provider\n }\n\n // Extract model from HTTP request body (OpenAI/Anthropic) or URL (Vertex AI)\n const body = selectedCall?.httpRequest?.body?.json()\n if (body && typeof body === \"object\" && typeof body.model === \"string\") {\n context.model = body.model\n } else {\n const url = selectedCall?.httpRequest?.url\n if (url) {\n const match = url.match(/\\/models\\/([^/:]+)/)\n if (match?.[1]) {\n context.model = match[1]\n }\n }\n }\n\n const inputTokens =\n usage?.inputTokens ?? selectedCall?.usage?.inputTokens ?? null\n const outputTokens =\n usage?.outputTokens ?? selectedCall?.usage?.outputTokens ?? null\n if (inputTokens !== null) {\n context.inputTokens = inputTokens\n }\n if (outputTokens !== null) {\n context.outputTokens = outputTokens\n }\n\n const durationMs = c?.last?.timing?.durationMs ?? null\n if (durationMs !== null) {\n context.durationMs = durationMs\n }\n\n return Object.keys(context).length > 0 ? context : null\n } catch {\n return null\n }\n}\n\n/**\n * Options for wrapBAML.\n */\nexport interface WrapBAMLOptions {\n /** Called after each BAML invocation with the Collector instance. */\n onCollector?: (collector: unknown) => void\n}\n\n/**\n * A function returned by wrapBAML that exposes the BAML collector from the last call.\n */\nexport interface WrappedBamlFn<TArgs extends unknown[], TReturn> {\n (...args: TArgs): Promise<TReturn>\n /** The BAML Collector instance from the most recent call. `null` before the first call or if @boundaryml/baml is unavailable. */\n collector: unknown | null\n}\n\n/**\n * A handle to the current active span, allowing context to be added.\n */\nexport interface CurrentSpan {\n /** The trace ID for the current span. */\n readonly traceId: string\n /**\n * Add a context entry to this span. Each call appends to the contexts array.\n * Context entries are stored in span_data.contexts as [{key, value}, ...].\n */\n addContext(context: Record<string, unknown>): void\n /**\n * Set the prompt for this span. Stored in span_data.prompt.\n * Calling multiple times overwrites the previous value.\n */\n setPrompt(prompt: string): void\n}\n\n/**\n * A handle to the current active trace, allowing trace-level context to be set.\n */\nexport interface CurrentTrace {\n /**\n * Set the session ID for this trace. Stored in the database session_id column.\n */\n setSessionId(sessionId: string): void\n /**\n * Set metadata for this trace. Stored in rawData.metadata.\n * Subsequent calls merge with existing metadata, with later values taking precedence.\n */\n setMetadata(metadata: Record<string, unknown>): void\n /**\n * Add a context entry to this trace. Each call appends to the contexts array.\n * Context entries are stored in rawData.contexts as [{key, value}, ...].\n */\n addContext(context: Record<string, unknown>): void\n}\n\n// No-op implementations for when called outside a span context\nconst noOpSpan: CurrentSpan = {\n traceId: \"\",\n addContext(): void {\n // No-op\n },\n setPrompt(): void {\n // No-op\n },\n}\n\nconst noOpTrace: CurrentTrace = {\n setSessionId(): void {\n // No-op\n },\n setMetadata(): void {\n // No-op\n },\n addContext(): void {\n // No-op\n },\n}\n\n/**\n * Get a handle to the current active span.\n *\n * Call this from inside a traced function (wrapped with `withSpan`) to get\n * a span handle that allows adding context at runtime.\n *\n * Returns a no-op object if called outside of a span context (methods do nothing).\n */\nexport function getCurrentSpan(): CurrentSpan {\n const stack = getSpanStack()\n const current = stack[stack.length - 1]\n if (!current) {\n return noOpSpan\n }\n return {\n traceId: current.traceId,\n addContext(context: Record<string, unknown>): void {\n try {\n if (typeof context !== \"object\" || context === null) {\n return\n }\n // Push the entire context object as one entry\n current.contexts.push(context)\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n setPrompt(prompt: string): void {\n try {\n if (typeof prompt !== \"string\") {\n return\n }\n current.prompt = prompt\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n }\n}\n\n/**\n * Get a handle to the current active trace.\n *\n * Call this from inside a traced function (wrapped with `withSpan`) to get\n * a trace handle that allows setting trace-level context at runtime.\n *\n * Returns a no-op object if called outside of a span context (methods do nothing).\n */\nexport function getCurrentTrace(): CurrentTrace {\n const stack = getSpanStack()\n const current = stack[stack.length - 1]\n if (!current) {\n return noOpTrace\n }\n\n const traceId = current.traceId\n\n const getOrCreateTraceState = (): TraceState => {\n let traceState = activeTraceStates.get(traceId)\n if (!traceState) {\n traceState = {\n traceId,\n startedAt: new Date().toISOString(),\n contexts: [],\n }\n activeTraceStates.set(traceId, traceState)\n }\n return traceState\n }\n\n return {\n setSessionId(sessionId: string): void {\n try {\n const traceState = getOrCreateTraceState()\n traceState.sessionId = sessionId\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n setMetadata(metadata: Record<string, unknown>): void {\n try {\n if (typeof metadata !== \"object\" || metadata === null) {\n return\n }\n const traceState = getOrCreateTraceState()\n traceState.metadata = { ...traceState.metadata, ...metadata }\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n addContext(context: Record<string, unknown>): void {\n try {\n if (typeof context !== \"object\" || context === null) {\n return\n }\n const traceState = getOrCreateTraceState()\n // Push the entire context object as one entry\n traceState.contexts.push(context)\n } catch {\n // Silently ignore - never crash the host app\n }\n },\n }\n}\n\nexport interface BitfabConfig {\n /** The API key for Bitfab API authentication. When undefined or empty, tracing is disabled. */\n apiKey?: string\n /** The base URL for the Bitfab API (default: https://bitfab.ai) */\n serviceUrl?: string\n /** Request timeout in milliseconds (default: 120000) */\n timeout?: number\n /** Environment variables for LLM provider API keys (only OPENAI_API_KEY is supported) */\n envVars?: AllowedEnvVars\n /** Whether the client is enabled. Defaults to true. When false, withSpan returns the original function unwrapped. */\n enabled?: boolean\n /** The generated BAML client instance (e.g., `b` from your baml_client). Used by wrapBAML() when no explicit client is passed. */\n bamlClient?: unknown\n}\n\n/**\n * Span types matching the backend enum.\n * - llm: LLM API calls\n * - agent: Autonomous orchestrators\n * - function: Tool implementations\n * - guardrail: Safety/validation checks\n * - handoff: Agent-to-agent transfers\n * - custom: Application-specific tracing (default)\n */\nexport type SpanType =\n | \"llm\"\n | \"agent\"\n | \"function\"\n | \"guardrail\"\n | \"handoff\"\n | \"custom\"\n\n/**\n * Options for configuring span behavior.\n */\nexport interface SpanOptions {\n /**\n * The name of the span. Defaults to the function name if available,\n * otherwise falls back to the trace function key.\n */\n name?: string\n /**\n * The type of span. Defaults to \"custom\" if not specified.\n */\n type?: SpanType\n}\n\ninterface FunctionVersionResponse {\n id: string\n name: string\n versionId: string\n versionNumber: number | null\n prompt: string\n providers: ProviderDefinition[]\n}\n\n// Re-export BitfabError for backwards compatibility\nexport { BitfabError }\n\n/**\n * Client for making provider-based API calls via BAML.\n */\nexport class Bitfab {\n private readonly apiKey: string | undefined\n private readonly serviceUrl: string\n private readonly timeout: number\n private readonly envVars: AllowedEnvVars\n private readonly enabled: boolean\n private readonly httpClient: HttpClient\n private readonly bamlClient: unknown\n\n /**\n * Initialize the Bitfab client.\n *\n * @param config - Configuration options for the client\n */\n constructor(config: BitfabConfig) {\n this.apiKey = config.apiKey\n this.serviceUrl = config.serviceUrl ?? DEFAULT_SERVICE_URL\n this.timeout = config.timeout ?? 120000\n this.envVars = config.envVars ?? {}\n const enabled = config.enabled ?? true\n if (enabled && (!config.apiKey || config.apiKey.trim() === \"\")) {\n console.warn(\n \"Bitfab: apiKey is empty — tracing is disabled. Provide a valid API key to enable tracing.\",\n )\n this.enabled = false\n } else {\n this.enabled = enabled\n }\n this.bamlClient = config.bamlClient ?? null\n this.httpClient = new HttpClient({\n apiKey: this.apiKey,\n serviceUrl: this.serviceUrl,\n timeout: this.timeout,\n })\n }\n\n /**\n * Fetch the function with its current version and BAML prompt from the server.\n *\n * @param methodName - The name of the method to fetch\n * @returns The function with current version, BAML prompt, and provider definitions\n * @throws {BitfabError} If the function is not found or an error occurs\n */\n private async fetchFunctionVersion(\n methodName: string,\n ): Promise<FunctionVersionResponse> {\n const result =\n await this.httpClient.lookupFunction<FunctionVersionResponse>(methodName)\n\n // Check if function was not found\n if (result.id === null) {\n throw new BitfabError(\n `Function \"${methodName}\" not found. Create it at: ${this.serviceUrl}/functions`,\n \"/functions\",\n )\n }\n\n // Check if function has no prompt\n if (!result.prompt) {\n throw new BitfabError(\n `Function \"${methodName}\" has no prompt configured. Add one at: ${this.serviceUrl}/functions/${result.id}`,\n `/functions/${result.id}`,\n )\n }\n\n return result\n }\n\n /**\n * Call a method with the given named arguments via BAML execution.\n *\n * @param methodName - The name of the method to call\n * @param inputs - Named arguments to pass to the method\n * @returns The result of the BAML function execution\n * @throws {BitfabError} If service_url is not set, or if an error occurs\n */\n async call<T = unknown>(\n methodName: string,\n inputs: Record<string, unknown> = {},\n ): Promise<T> {\n try {\n const functionVersion = await this.fetchFunctionVersion(methodName)\n const executionResult = await runFunctionWithBaml(\n functionVersion.prompt,\n inputs,\n functionVersion.providers,\n this.envVars,\n )\n\n // Create trace for the local execution\n const resultStr =\n typeof executionResult.result === \"string\"\n ? executionResult.result\n : JSON.stringify(executionResult.result)\n\n // Create trace in background so user doesn't have to wait\n this.httpClient.sendInternalTrace(functionVersion.id, {\n result: resultStr,\n source: \"typescript-sdk\",\n ...(Object.keys(inputs).length > 0 && { inputs }),\n ...(executionResult.rawCollector != null && {\n rawCollector: executionResult.rawCollector,\n }),\n })\n\n return executionResult.result as T\n } catch (error) {\n if (error instanceof BitfabError) {\n throw error\n }\n if (error instanceof Error) {\n throw new BitfabError(error.message)\n }\n throw new BitfabError(\"Unknown error occurred during local execution\")\n }\n }\n\n /**\n * Get a tracing processor for OpenAI Agents SDK integration.\n *\n * This processor automatically captures traces and spans from the OpenAI Agents SDK\n * and sends them to Bitfab for monitoring and analysis.\n *\n * Example usage:\n * ```typescript\n * import { addTraceProcessor } from '@openai/agents';\n *\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n * const processor = client.getOpenAiTracingProcessor();\n * addTraceProcessor(processor);\n * ```\n *\n * @returns A BitfabOpenAITracingProcessor instance configured for this client\n */\n getOpenAiTracingProcessor() {\n return new BitfabOpenAITracingProcessor({\n apiKey: this.apiKey,\n serviceUrl: this.serviceUrl,\n getActiveSpanContext: () => {\n const stack = getSpanStack()\n return stack[stack.length - 1] ?? null\n },\n })\n }\n\n /**\n * Wrap a BAML client method to automatically capture prompt and LLM metadata.\n *\n * Creates a BAML Collector, calls the method through a tracked client,\n * then extracts rendered messages and token usage — calling setPrompt()\n * and addContext() on the current span automatically.\n *\n * The BAML client can be provided in the constructor or passed explicitly:\n *\n * ```typescript\n * // Option 1: bamlClient in constructor (use wrapBAML with just the method)\n * const client = new Bitfab({ apiKey: 'your-api-key', bamlClient: b });\n * const traced = client.withSpan('classify', { type: 'llm' },\n * client.wrapBAML(b.ClassifyText)\n * );\n *\n * // Option 2: pass bamlClient at call site\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n * const traced = client.withSpan('classify', { type: 'llm' },\n * client.wrapBAML(b, b.ClassifyText)\n * );\n * ```\n *\n * @param methodOrClient - Either a BAML method (uses constructor bamlClient) or the BAML client instance\n * @param maybeMethodOrOptions - The BAML method when the first argument is a client, or WrapBAMLOptions when the first argument is the method\n * @param maybeOptions - WrapBAMLOptions when using the two-argument (client, method) form\n * @returns An async function with the same signature that instruments the BAML call\n */\n wrapBAML<TArgs extends unknown[], TReturn>(\n methodOrClient: unknown,\n maybeMethodOrOptions?:\n | ((...args: TArgs) => Promise<TReturn>)\n | WrapBAMLOptions,\n maybeOptions?: WrapBAMLOptions,\n ): WrappedBamlFn<TArgs, TReturn> {\n let bamlClient: unknown\n let method: (...args: TArgs) => Promise<TReturn>\n let options: WrapBAMLOptions | undefined\n\n if (typeof maybeMethodOrOptions === \"function\") {\n bamlClient = methodOrClient\n method = maybeMethodOrOptions\n options = maybeOptions\n } else {\n bamlClient = this.bamlClient\n method = methodOrClient as (...args: TArgs) => Promise<TReturn>\n options = maybeMethodOrOptions as WrapBAMLOptions | undefined\n if (!bamlClient) {\n throw new BitfabError(\n \"bamlClient is required for wrapBAML. Pass it in the constructor or as the first argument.\",\n )\n }\n }\n\n const methodName = method.name\n if (!methodName) {\n throw new BitfabError(\n \"wrapBAML requires a named function (e.g., b.ClassifyText).\",\n )\n }\n\n // Warm the Collector class cache so it's ready by the time the wrapper is called\n loadCollectorClass()\n\n const wrappedFn = async (...args: TArgs): Promise<TReturn> => {\n const CollectorClass = await loadCollectorClass()\n if (!CollectorClass) {\n // @boundaryml/baml not available — call method directly as fallback\n wrappedFn.collector = null\n return await (\n bamlClient as Record<string, (...a: TArgs) => Promise<TReturn>>\n )[methodName](...args)\n }\n\n const collector = new CollectorClass(\"bitfab-baml-tracing\")\n const trackedClient = (\n bamlClient as { withOptions: (opts: unknown) => unknown }\n ).withOptions({ collector })\n const trackedMethod = (\n trackedClient as Record<string, (...a: TArgs) => Promise<TReturn>>\n )[methodName]\n const result = await trackedMethod.bind(\n trackedClient as Record<string, unknown>,\n )(...args)\n\n wrappedFn.collector = collector\n\n try {\n const prompt = extractPromptFromCollector(collector)\n if (prompt) {\n getCurrentSpan().setPrompt(prompt)\n }\n const metadata = extractContextFromCollector(collector)\n if (metadata) {\n getCurrentSpan().addContext(metadata)\n }\n } catch {\n // Never crash the host app\n }\n\n try {\n options?.onCollector?.(collector)\n } catch {\n // Never crash the host app\n }\n\n return result\n }\n\n wrappedFn.collector = null as unknown | null\n\n return wrappedFn\n }\n\n /**\n * Wrap a function to automatically create a span for its inputs and outputs.\n *\n * The wrapped function behaves identically to the original, but sends\n * span data to Bitfab in the background after each call.\n *\n * Example usage:\n * ```typescript\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n *\n * async function processOrder(orderId: string, items: string[]): Promise<{ total: number }> {\n * // ... process order\n * return { total: 100 };\n * }\n *\n * // Basic usage (defaults to \"custom\" span type)\n * const tracedProcessOrder = client.withSpan('order-processing', processOrder);\n *\n * // With explicit span type\n * const tracedProcessOrder = client.withSpan('order-processing', { type: 'function' }, processOrder);\n *\n * // Call the wrapped function normally\n * const result = await tracedProcessOrder('order-123', ['item-1', 'item-2']);\n * // Span is automatically sent to Bitfab\n * ```\n *\n * @param traceFunctionKey - A string identifier for grouping spans (e.g., 'order-processing', 'user-auth')\n * @param optionsOrFn - Either SpanOptions or the function to wrap\n * @param maybeFn - The function to wrap if options were provided\n * @returns A wrapped function with the same signature that creates spans for inputs and outputs\n */\n withSpan<TArgs extends unknown[], TReturn>(\n traceFunctionKey: string,\n optionsOrFn: SpanOptions | ((...args: TArgs) => TReturn),\n maybeFn?: (...args: TArgs) => TReturn,\n ): (...args: TArgs) => TReturn {\n if (!this.enabled) {\n const fn = typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn!\n return fn\n }\n\n // Handle overloaded signature\n const options: SpanOptions =\n typeof optionsOrFn === \"function\" ? {} : optionsOrFn\n const fn: (...args: TArgs) => TReturn =\n typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn!\n const self = this\n\n const wrappedFn = function (this: unknown, ...args: TArgs): TReturn {\n // Defer until AsyncLocalStorage init completes. In Node.js, the\n // dynamic import resolves in one microtask; in browsers, the init\n // resolves immediately to a no-op. The `asyncLocalStorageInitDone`\n // flag prevents an infinite loop when AsyncLocalStorage is\n // unavailable (browsers).\n if (!asyncLocalStorage && !isAsyncStorageInitDone()) {\n return asyncLocalStorageReady.then(() =>\n wrappedFn.apply(this, args),\n ) as unknown as TReturn\n }\n\n // Get current span stack to determine trace context\n const currentStack = getSpanStack()\n const parentContext = currentStack[currentStack.length - 1]\n\n // Generate trace ID (new if root, inherit if nested)\n const traceId = parentContext?.traceId ?? crypto.randomUUID()\n const spanId = crypto.randomUUID()\n const parentSpanId = parentContext?.spanId ?? null\n const isRootSpan = parentSpanId === null\n\n // Create new context for this span with empty contexts array\n const newContext: SpanContext = { traceId, spanId, contexts: [] }\n const newStack = [...currentStack, newContext]\n\n // Capture inputs and start time\n const inputs = args\n const startedAt = new Date().toISOString()\n\n // Register trace state for root spans\n if (isRootSpan && !activeTraceStates.has(traceId)) {\n activeTraceStates.set(traceId, {\n traceId,\n startedAt,\n contexts: [],\n })\n pendingSpanPromises.set(traceId, [])\n }\n\n // Shared span parameters\n const functionName = fn.name !== \"\" ? fn.name : undefined\n const baseSpanParams = {\n traceFunctionKey,\n functionName,\n spanName: options.name ?? functionName ?? traceFunctionKey,\n traceId,\n spanId,\n parentSpanId,\n inputs,\n startedAt,\n spanType: options.type ?? \"custom\",\n }\n\n // Helper to send span and (for root spans) await all pending spans\n // before sending the trace completion signal.\n // Wrapped in try/catch so span errors never crash the host app.\n const sendSpan = async (params: { result: unknown; error?: string }) => {\n try {\n const endedAt = new Date().toISOString()\n const replayCtx = getReplayContext()\n const spanPromise = self.sendWrapperSpan({\n ...baseSpanParams,\n ...params,\n contexts: newContext.contexts,\n prompt: newContext.prompt,\n endedAt,\n ...(replayCtx?.testRunId && { testRunId: replayCtx.testRunId }),\n ...(replayCtx?.inputSourceSpanId && {\n inputSourceSpanId: replayCtx.inputSourceSpanId,\n }),\n })\n\n // For root spans, await all pending span requests then send trace completion\n if (isRootSpan) {\n const pending = pendingSpanPromises.get(traceId) ?? []\n pending.push(spanPromise)\n await Promise.race([\n Promise.allSettled(pending),\n new Promise((resolve) => setTimeout(resolve, 5000)),\n ])\n pendingSpanPromises.delete(traceId)\n\n const traceState = activeTraceStates.get(traceId)\n self.sendTraceCompletion({\n traceFunctionKey,\n traceId,\n startedAt: traceState?.startedAt ?? startedAt,\n endedAt,\n sessionId: traceState?.sessionId,\n metadata: traceState?.metadata,\n contexts: traceState?.contexts ?? [],\n })\n activeTraceStates.delete(traceId)\n } else {\n // Non-root spans: track the promise for the root to await later\n const pending = pendingSpanPromises.get(traceId)\n if (pending) {\n pending.push(spanPromise)\n } else {\n pendingSpanPromises.set(traceId, [spanPromise])\n }\n }\n } catch {\n // Silently ignore — user's result/exception takes priority\n }\n }\n\n // Execute function within new span context\n const executeWithContext = (): TReturn => {\n const result = fn(...args)\n\n // Check if result is a Promise (async function)\n if (result instanceof Promise) {\n return result\n .then((resolvedResult) => {\n void sendSpan({ result: resolvedResult })\n return resolvedResult\n })\n .catch((error: unknown) => {\n void sendSpan({\n result: undefined,\n error: error instanceof Error ? error.message : String(error),\n })\n throw error\n }) as TReturn\n }\n\n // Sync function - create span in background\n void sendSpan({ result })\n return result\n }\n\n return runWithSpanStack(newStack, executeWithContext)\n }\n return wrappedFn\n }\n\n /**\n * Get a function wrapper for a specific trace function key.\n *\n * This provides a fluent API alternative to calling withSpan directly,\n * allowing you to bind the traceFunctionKey once and wrap multiple functions.\n *\n * Example usage:\n * ```typescript\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n *\n * const orderFunc = client.getFunction('order-processing');\n * const tracedProcessOrder = orderFunc.withSpan(processOrder);\n * const tracedValidateOrder = orderFunc.withSpan(validateOrder);\n * ```\n *\n * @param traceFunctionKey - A string identifier for grouping spans\n * @returns A BitfabFunction instance for wrapping functions\n */\n getFunction(traceFunctionKey: string): BitfabFunction {\n return new BitfabFunction(this, traceFunctionKey)\n }\n\n /**\n * Send trace completion when a root span ends.\n * Internal method to record trace completion with end time.\n * Fire-and-forget - sends to externalTraces endpoint via httpClient.\n */\n private sendTraceCompletion(params: {\n traceFunctionKey: string\n traceId: string\n startedAt: string\n endedAt: string\n sessionId?: string\n metadata?: Record<string, unknown>\n contexts?: ContextEntry[]\n }): void {\n // Build the raw trace object for the externalTraces endpoint\n const rawTrace: Record<string, unknown> = {\n id: params.traceId,\n started_at: params.startedAt,\n ended_at: params.endedAt,\n workflow_name: params.traceFunctionKey,\n }\n\n // Add optional fields to rawData\n if (params.metadata && Object.keys(params.metadata).length > 0) {\n rawTrace.metadata = params.metadata\n }\n if (params.contexts && params.contexts.length > 0) {\n rawTrace.contexts = params.contexts\n }\n\n this.httpClient.sendExternalTrace({\n type: \"sdk-function\",\n source: \"typescript-sdk-function\",\n traceFunctionKey: params.traceFunctionKey,\n externalTrace: rawTrace,\n completed: true,\n ...(params.sessionId && { sessionId: params.sessionId }),\n })\n }\n\n /**\n * Send a wrapper span from function execution.\n * Internal method to record spans when using withSpan.\n * Fire-and-forget - sends to externalSpans endpoint via httpClient.\n */\n private sendWrapperSpan(params: {\n traceFunctionKey: string\n functionName?: string\n spanName: string\n traceId: string\n spanId: string\n parentSpanId: string | null\n inputs?: unknown[]\n result: unknown\n error?: string\n startedAt: string\n endedAt: string\n spanType: SpanType\n contexts?: ContextEntry[]\n prompt?: string\n testRunId?: string\n inputSourceSpanId?: string\n }): Promise<unknown> {\n // Serialize inputs and result with superjson for type preservation\n const serializedInputs = serializeValue(params.inputs)\n const serializedResult = serializeValue(params.result)\n\n // Format as an external span with the wrapper format\n const externalSpan: Record<string, unknown> = {\n id: params.spanId,\n trace_id: params.traceId,\n started_at: params.startedAt,\n ended_at: params.endedAt,\n span_data: {\n name: params.spanName,\n type: params.spanType,\n input: serializedInputs.json,\n output: serializedResult.json,\n // Include superjson meta for type preservation\n ...(serializedInputs.meta !== undefined && {\n input_meta: serializedInputs.meta,\n }),\n ...(serializedResult.meta !== undefined && {\n output_meta: serializedResult.meta,\n }),\n ...(params.functionName !== undefined && {\n function_name: params.functionName,\n }),\n ...(params.error !== undefined && { error: params.error }),\n ...(params.contexts &&\n params.contexts.length > 0 && {\n contexts: params.contexts,\n }),\n ...(params.prompt !== undefined && { prompt: params.prompt }),\n },\n }\n\n // Add parent_id for nested spans\n if (params.parentSpanId) {\n externalSpan.parent_id = params.parentSpanId\n }\n if (params.inputSourceSpanId) {\n externalSpan.input_source_span_id = params.inputSourceSpanId\n }\n\n return this.httpClient.sendExternalSpan({\n type: \"sdk-function\",\n source: \"typescript-sdk-function\",\n sourceTraceId: params.traceId,\n traceFunctionKey: params.traceFunctionKey,\n rawSpan: externalSpan,\n ...(params.testRunId && { testRunId: params.testRunId }),\n })\n }\n\n /**\n * Replay historical traces through a function and create a test run.\n *\n * Fetches the last N traces for the given trace function key, re-runs each\n * through the provided function, and returns comparison data.\n *\n * The function must have been wrapped with `withSpan` — replay injects\n * `testRunId` via async context so new spans are linked to the test run.\n *\n * @param traceFunctionKey - The trace function key to replay\n * @param fn - The function to replay (must be the return value of `withSpan`)\n * @param options - Optional replay options (limit, traceIds)\n * @returns ReplayResult with items, testRunId, and testRunUrl\n */\n async replay<TReturn>(\n traceFunctionKey: string,\n // biome-ignore lint/suspicious/noExplicitAny: replay deserializes inputs from historical data — typed args would be incorrect\n fn: (...args: any[]) => TReturn | Promise<TReturn>,\n options?: { limit?: number; traceIds?: string[]; maxConcurrency?: number },\n ): Promise<{\n items: Array<{\n input: unknown[]\n result: TReturn | undefined\n originalOutput: unknown\n error: string | null\n }>\n testRunId: string\n testRunUrl: string\n }> {\n const { replay: doReplay } = await import(\"./replay.js\")\n return doReplay(\n this.httpClient,\n this.serviceUrl,\n traceFunctionKey,\n fn,\n options,\n )\n }\n}\n\n/**\n * Represents a Bitfab function that can wrap user functions for tracing.\n *\n * This provides a fluent API for binding a traceFunctionKey once and\n * then wrapping multiple functions with that key.\n *\n * Example usage:\n * ```typescript\n * const client = new Bitfab({ apiKey: 'your-api-key' });\n *\n * const orderFunc = client.getFunction('order-processing');\n * const tracedProcessOrder = orderFunc.withSpan(processOrder);\n * const tracedValidateOrder = orderFunc.withSpan(validateOrder);\n * ```\n */\nexport class BitfabFunction {\n constructor(\n private readonly client: Bitfab,\n private readonly traceFunctionKey: string,\n ) {}\n\n /**\n * Wrap a function to automatically create a span for its inputs and outputs.\n *\n * The wrapped function behaves identically to the original, but sends\n * span data to Bitfab in the background after each call.\n *\n * Example usage:\n * ```typescript\n * const orderFunc = client.getFunction('order-processing');\n *\n * // Basic usage (defaults to \"custom\" span type)\n * const tracedProcessOrder = orderFunc.withSpan(processOrder);\n *\n * // With explicit span type\n * const tracedProcessOrder = orderFunc.withSpan({ type: 'function' }, processOrder);\n * ```\n *\n * @param optionsOrFn - Either SpanOptions or the function to wrap\n * @param maybeFn - The function to wrap if options were provided\n * @returns A wrapped function with the same signature that creates spans\n */\n withSpan<TArgs extends unknown[], TReturn>(\n optionsOrFn: SpanOptions | ((...args: TArgs) => TReturn),\n maybeFn?: (...args: TArgs) => TReturn,\n ): (...args: TArgs) => TReturn {\n // Handle overloaded signature\n const options: SpanOptions =\n typeof optionsOrFn === \"function\" ? {} : optionsOrFn\n const fn: (...args: TArgs) => TReturn =\n typeof optionsOrFn === \"function\" ? optionsOrFn : maybeFn!\n\n return this.client.withSpan(this.traceFunctionKey, options, fn)\n }\n\n /**\n * Wrap a BAML client method to automatically capture prompt and LLM metadata.\n * Delegates to the parent client's wrapBAML method.\n *\n * @param methodOrClient - Either a BAML method (uses constructor bamlClient) or the BAML client instance\n * @param maybeMethodOrOptions - The BAML method when the first argument is a client, or WrapBAMLOptions when the first argument is the method\n * @param maybeOptions - WrapBAMLOptions when using the two-argument (client, method) form\n * @returns An async function with the same signature that instruments the BAML call\n */\n wrapBAML<TArgs extends unknown[], TReturn>(\n methodOrClient: unknown,\n maybeMethodOrOptions?:\n | ((...args: TArgs) => Promise<TReturn>)\n | WrapBAMLOptions,\n maybeOptions?: WrapBAMLOptions,\n ): WrappedBamlFn<TArgs, TReturn> {\n return this.client.wrapBAML(\n methodOrClient,\n maybeMethodOrOptions,\n maybeOptions,\n )\n }\n}\n"],"mappings":"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","names":["fn"]}