bitfab 0.68.0 → 0.68.1

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.
Files changed (53) hide show
  1. package/dist/{autoTrace-BikML0lX.cjs → autoTrace-D3-OZcmR.cjs} +196 -17
  2. package/dist/autoTrace-D3-OZcmR.cjs.map +1 -0
  3. package/dist/{autoTrace-CVt9EDyo.js → autoTrace-ghnojSj9.js} +173 -18
  4. package/dist/autoTrace-ghnojSj9.js.map +1 -0
  5. package/dist/autoTrace.cjs +2 -1
  6. package/dist/autoTrace.d.cts +15 -0
  7. package/dist/autoTrace.d.ts +15 -0
  8. package/dist/autoTrace.js +1 -1
  9. package/dist/{babelPlugin-s8EFjT6e.cjs → babelPlugin-0uOq-j1Q.cjs} +48 -18
  10. package/dist/babelPlugin-0uOq-j1Q.cjs.map +1 -0
  11. package/dist/{babelPlugin-a7ofCoOd.js → babelPlugin-Muq0uuuu.js} +48 -18
  12. package/dist/babelPlugin-Muq0uuuu.js.map +1 -0
  13. package/dist/{http-_cgR_DM2.js → http-f8Rl8oRa.js} +3 -3
  14. package/dist/{http-_cgR_DM2.js.map → http-f8Rl8oRa.js.map} +1 -1
  15. package/dist/{http-psFF1ptn.cjs → http-r1r6injY.cjs} +3 -3
  16. package/dist/{http-psFF1ptn.cjs.map → http-r1r6injY.cjs.map} +1 -1
  17. package/dist/{index-j7SrvOqe.d.cts → index-BQV7zzJx.d.cts} +56 -2
  18. package/dist/{index-j7SrvOqe.d.ts → index-BQV7zzJx.d.ts} +56 -2
  19. package/dist/index.cjs +2 -2
  20. package/dist/index.d.cts +2 -2
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.js +2 -2
  23. package/dist/node.cjs +3 -3
  24. package/dist/node.d.cts +2 -2
  25. package/dist/node.d.ts +2 -2
  26. package/dist/node.js +3 -3
  27. package/dist/registryCommand-Dk4Y1ZgW.js.map +1 -1
  28. package/dist/{src-Dze8o7iU.cjs → src-BYXxPnpE.cjs} +30 -7
  29. package/dist/src-BYXxPnpE.cjs.map +1 -0
  30. package/dist/{src-DyEKM7yn.js → src-Cps3Xs_J.js} +30 -7
  31. package/dist/{src-DyEKM7yn.js.map → src-Cps3Xs_J.js.map} +1 -1
  32. package/dist/transform/babel.cjs +1 -1
  33. package/dist/transform/babel.d.cts +9 -2
  34. package/dist/transform/babel.d.ts +9 -2
  35. package/dist/transform/babel.js +1 -1
  36. package/dist/transform/loaderRuntime.cjs +2 -2
  37. package/dist/transform/loaderRuntime.js +2 -2
  38. package/dist/transform/nodeLoader.js +47 -17
  39. package/dist/transform/nodeLoader.js.map +1 -1
  40. package/dist/transform/swc.cjs +1 -1
  41. package/dist/transform/swc.js +1 -1
  42. package/dist/transform/unplugin.cjs +2 -2
  43. package/dist/transform/unplugin.js +2 -2
  44. package/dist/{transform-DkcFn_tg.js → transform-CAJyLLe2.js} +2 -2
  45. package/dist/{transform-DkcFn_tg.js.map → transform-CAJyLLe2.js.map} +1 -1
  46. package/dist/{transform-BBzrqpVH.cjs → transform-ClCOpCZ2.cjs} +2 -2
  47. package/dist/{transform-BBzrqpVH.cjs.map → transform-ClCOpCZ2.cjs.map} +1 -1
  48. package/package.json +2 -1
  49. package/dist/autoTrace-BikML0lX.cjs.map +0 -1
  50. package/dist/autoTrace-CVt9EDyo.js.map +0 -1
  51. package/dist/babelPlugin-a7ofCoOd.js.map +0 -1
  52. package/dist/babelPlugin-s8EFjT6e.cjs.map +0 -1
  53. package/dist/src-Dze8o7iU.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autoTrace-ghnojSj9.js","names":["target"],"sources":["../src/asyncStorage.ts","../src/captureSuppression.ts","../src/warnOnce.ts","../src/openrouter.ts","../src/autoTrace.ts"],"sourcesContent":["/**\n * Shared AsyncLocalStorage loader.\n *\n * Provides two ways to initialize AsyncLocalStorage:\n *\n * 1. **Synchronous registration** (preferred for Node.js):\n * `asyncStorageNode.ts` calls `registerAsyncLocalStorageClass()` at module\n * evaluation time, so the class is available immediately - no async gap.\n * The `node.ts` entry point imports it before anything else.\n *\n * 2. **Async dynamic import** (fallback for the default entry point):\n * Loads `node:async_hooks` via a bundler-safe dynamic import. This is used\n * by the default `index.ts` entry point so the SDK works in browsers\n * (where the import silently fails) and in Node.js when imported via the\n * default entry point.\n *\n * ## Why the dynamic import looks like this\n *\n * We need to handle three environments:\n *\n * 1. **Pure Node.js** - `import(\"node:async_hooks\")` works natively.\n * 2. **Webpack/Turbopack (Next.js server)** - The bundler processes\n * `import()` calls at build time. The `webpackIgnore` magic comment tells\n * webpack (and turbopack) to emit a native `import()` call instead of\n * trying to resolve it, so Node.js handles it at runtime.\n * 3. **Browsers / Edge** - The `process.versions?.node` guard prevents\n * execution entirely. If it somehow runs, `.catch(() => {})` swallows\n * the failure.\n */\n\nexport interface AsyncLocalStorageLike<T> {\n getStore(): T | undefined\n run<R>(store: T, fn: () => R): R\n}\n\nlet AsyncLocalStorageClass: (new () => AsyncLocalStorageLike<unknown>) | null =\n null\nlet initDone = false\n\n/**\n * Register the AsyncLocalStorage class synchronously.\n *\n * Called by `asyncStorageNode.ts` at module evaluation time so the class\n * is available before any span is created - no async gap, no race condition.\n *\n * Safe to call multiple times; subsequent calls are no-ops.\n */\nexport function registerAsyncLocalStorageClass(\n cls: new () => AsyncLocalStorageLike<unknown>,\n): void {\n if (!AsyncLocalStorageClass) {\n AsyncLocalStorageClass = cls\n }\n initDone = true\n}\n\n/**\n * Assert that AsyncLocalStorage was registered successfully.\n *\n * Called by `node.ts` after importing `asyncStorageNode.ts` to catch\n * import-order bugs at startup rather than silently degrading to the\n * browser fallback (flat spans with no nesting).\n *\n * This should ONLY be called from the Node.js entry point where we\n * know `node:async_hooks` must be available.\n */\nexport function assertAsyncStorageRegistered(): void {\n if (!AsyncLocalStorageClass) {\n console.warn(\n \"Bitfab: AsyncLocalStorage not available - nested span context will not propagate.\",\n )\n }\n}\n\nexport const asyncStorageReady: Promise<void> = (\n typeof process !== \"undefined\" && process.versions?.node\n ? // The join trick hides \"node:async_hooks\" from static analysis so\n // bundlers that ban Node.js built-ins don't fail at build time.\n // webpackIgnore tells webpack/turbopack to emit a native import()\n // so Node.js can resolve the module at runtime.\n import(\n /* webpackIgnore: true */\n [\"node\", \"async_hooks\"].join(\":\")\n )\n .then(\n (mod: {\n AsyncLocalStorage: new () => AsyncLocalStorageLike<unknown>\n }) => {\n registerAsyncLocalStorageClass(mod.AsyncLocalStorage)\n },\n )\n .catch(() => {})\n : Promise.resolve()\n).then(() => {\n initDone = true\n})\n\nexport function isAsyncStorageInitDone(): boolean {\n return initDone\n}\n\nexport function createAsyncLocalStorage<T>(): AsyncLocalStorageLike<T> | null {\n return AsyncLocalStorageClass\n ? (new AsyncLocalStorageClass() as AsyncLocalStorageLike<T>)\n : null\n}\n","interface CaptureSuppressionState {\n depth: number\n}\n\ninterface CaptureSuppressionGlobal {\n __bitfabCaptureSuppressionV1?: CaptureSuppressionState\n}\n\nconst suppressionGlobal = globalThis as unknown as CaptureSuppressionGlobal\nconst suppressionState: CaptureSuppressionState =\n suppressionGlobal.__bitfabCaptureSuppressionV1 ?? { depth: 0 }\nsuppressionGlobal.__bitfabCaptureSuppressionV1 = suppressionState\n\nexport function isCaptureSuppressed(): boolean {\n return suppressionState.depth > 0\n}\n\nexport function runWithCaptureSuppressed<T>(fn: () => T): T {\n suppressionState.depth += 1\n try {\n return fn()\n } finally {\n suppressionState.depth -= 1\n }\n}\n","/**\n * Emit a `console.warn` at most once per distinct `key` for the life of the\n * process.\n *\n * The SDK must NEVER crash a host app, so every failure on the user's path\n * degrades silently (a span is dropped, a call runs untraced, a payload is\n * stubbed). Silent is safe but undebuggable: a user who suddenly has no traces,\n * or sees `<unserializable>` in a span, has no signal as to why. A one-time\n * warning per distinct issue restores that signal without spamming the console\n * from a hot path.\n *\n * Keys should identify the specific degradation (e.g. include the traced\n * function key) so each distinct issue warns once, not just the first one seen.\n */\nconst warned = new Set<string>()\n\nexport function warn(message: string): void {\n try {\n console.warn(`[bitfab] ${message}`)\n } catch {\n // Logging must never crash the host app (e.g. a closed/replaced console).\n }\n}\n\nexport function warnOnce(key: string, message: string): void {\n if (warned.has(key)) {\n return\n }\n warned.add(key)\n warn(message)\n}\n\nexport function writeOnce(\n key: string,\n line: string,\n write: (line: string) => void = console.warn,\n): void {\n if (warned.has(key)) {\n return\n }\n warned.add(key)\n try {\n write(line)\n } catch {}\n}\n\n/** Test-only: clear the dedup set so a warning can fire again. */\nexport function _resetWarnOnce(): void {\n warned.clear()\n}\n","import {\n type AsyncLocalStorageLike,\n createAsyncLocalStorage,\n} from \"./asyncStorage.js\"\n\nexport const OPENROUTER_PROVIDER = \"openrouter\"\n\nconst OPENROUTER_HOSTNAME = \"openrouter.ai\"\nconst OPENROUTER_WATCH_STORAGE_SYMBOL = Symbol.for(\n \"bitfab.openRouterWatchStorage\",\n)\n\ninterface OpenRouterWatch {\n recorded: boolean\n parent: OpenRouterWatch | null\n}\n\ninterface OpenRouterSpan {\n addContext(context: Record<string, unknown>): void\n setPrompt(prompt: string): void\n}\n\nconst completionsRecordedByAutoTrace = new WeakSet<object>()\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null\n}\n\nfunction field(value: unknown, name: string): unknown {\n return isRecord(value) ? value[name] : undefined\n}\n\nfunction numberField(value: unknown, name: string): number | undefined {\n const found = field(value, name)\n return typeof found === \"number\" && Number.isFinite(found) ? found : undefined\n}\n\nfunction nonEmptyString(value: unknown): string | undefined {\n return typeof value === \"string\" && value !== \"\" ? value : undefined\n}\n\nfunction isOpenRouterBaseUrl(baseUrl: unknown): boolean {\n if (typeof baseUrl !== \"string\") {\n return false\n }\n try {\n const host = new URL(baseUrl).hostname\n return (\n host === OPENROUTER_HOSTNAME || host.endsWith(`.${OPENROUTER_HOSTNAME}`)\n )\n } catch {\n return false\n }\n}\n\nexport function isOpenRouterCompletions(receiver: unknown): boolean {\n try {\n return isOpenRouterBaseUrl(field(field(receiver, \"_client\"), \"baseURL\"))\n } catch {\n return false\n }\n}\n\nexport function isStreamingRequest(body: unknown): boolean {\n return field(body, \"stream\") === true\n}\n\nfunction isChatCompletion(value: unknown): boolean {\n return isRecord(value) && Array.isArray(value.choices)\n}\n\nexport function openRouterPrompt(body: unknown): string | undefined {\n const messages = field(body, \"messages\")\n if (!Array.isArray(messages)) {\n return undefined\n }\n const rendered = messages.flatMap((message) => {\n const role = field(message, \"role\")\n if (typeof role !== \"string\") {\n return []\n }\n const content = field(message, \"content\")\n return [\n {\n role,\n content:\n typeof content === \"string\" ? content : JSON.stringify(content),\n },\n ]\n })\n return rendered.length > 0 ? JSON.stringify(rendered) : undefined\n}\n\nexport function openRouterContext(\n body: unknown,\n response: unknown,\n durationMs: number,\n): Record<string, unknown> {\n const usage = field(response, \"usage\")\n const context: Record<string, unknown> = { provider: OPENROUTER_PROVIDER }\n const values: Record<string, unknown> = {\n model:\n nonEmptyString(field(response, \"model\")) ??\n nonEmptyString(field(body, \"model\")),\n upstreamProvider: nonEmptyString(field(response, \"provider\")),\n inputTokens: numberField(usage, \"prompt_tokens\"),\n outputTokens: numberField(usage, \"completion_tokens\"),\n cachedInputTokens: numberField(\n field(usage, \"prompt_tokens_details\"),\n \"cached_tokens\",\n ),\n reasoningTokens: numberField(\n field(usage, \"completion_tokens_details\"),\n \"reasoning_tokens\",\n ),\n costUsd: numberField(usage, \"cost\"),\n }\n for (const [key, value] of Object.entries(values)) {\n if (value !== undefined) {\n context[key] = value\n }\n }\n context.durationMs = durationMs\n return context\n}\n\nfunction recordOpenRouterCompletion(\n span: OpenRouterSpan,\n body: unknown,\n response: unknown,\n durationMs: number,\n): void {\n try {\n const prompt = openRouterPrompt(body)\n if (prompt !== undefined) {\n span.setPrompt(prompt)\n }\n span.addContext(openRouterContext(body, response, durationMs))\n } catch {}\n}\n\nlet openRouterWatchStorage: AsyncLocalStorageLike<OpenRouterWatch> | null = null\n\nfunction watchStorage(): AsyncLocalStorageLike<OpenRouterWatch> | null {\n if (openRouterWatchStorage) {\n return openRouterWatchStorage\n }\n const shared = globalThis as typeof globalThis & Record<symbol, unknown>\n const existing = shared[OPENROUTER_WATCH_STORAGE_SYMBOL] as\n | AsyncLocalStorageLike<OpenRouterWatch>\n | undefined\n openRouterWatchStorage =\n existing ?? createAsyncLocalStorage<OpenRouterWatch>()\n if (openRouterWatchStorage && !existing) {\n shared[OPENROUTER_WATCH_STORAGE_SYMBOL] = openRouterWatchStorage\n }\n return openRouterWatchStorage\n}\n\nexport function watchOpenRouterUsage<T>(fn: () => T): {\n watch: OpenRouterWatch\n result: T\n} {\n const storage = watchStorage()\n const watch: OpenRouterWatch = {\n recorded: false,\n parent: storage?.getStore() ?? null,\n }\n const result = storage ? storage.run(watch, fn) : fn()\n return { watch, result }\n}\n\nfunction markEnclosingWatches(watch: OpenRouterWatch): void {\n for (let current = watch.parent; current; current = current.parent) {\n current.recorded = true\n }\n}\n\nfunction isRecordedByAutoTrace(response: unknown): boolean {\n return isRecord(response) && completionsRecordedByAutoTrace.has(response)\n}\n\nexport function recordWatchedOpenRouterCompletion(\n span: OpenRouterSpan,\n watch: OpenRouterWatch,\n body: unknown,\n response: unknown,\n durationMs: number,\n): void {\n if (watch.recorded || isRecordedByAutoTrace(response)) {\n markEnclosingWatches(watch)\n return\n }\n if (!isChatCompletion(response)) {\n return\n }\n recordOpenRouterCompletion(span, body, response, durationMs)\n completionsRecordedByAutoTrace.add(response as object)\n markEnclosingWatches(watch)\n}\n\nexport function recordAutoTracedOpenRouter<T>(\n invokeFn: () => T,\n body: unknown,\n span: OpenRouterSpan,\n): T {\n const startedAt = Date.now()\n const { watch, result } = watchOpenRouterUsage(invokeFn)\n const settle = (response: unknown): void => {\n recordWatchedOpenRouterCompletion(\n span,\n watch,\n body,\n response,\n Date.now() - startedAt,\n )\n }\n if (result instanceof Promise) {\n return result.then((response) => {\n settle(response)\n return response\n }) as T\n }\n settle(result)\n return result\n}\n","import {\n type AsyncLocalStorageLike,\n createAsyncLocalStorage,\n} from \"./asyncStorage.js\"\nimport { isCaptureSuppressed } from \"./captureSuppression.js\"\nimport { isOpenRouterCompletions, isStreamingRequest } from \"./openrouter.js\"\nimport { warnOnce } from \"./warnOnce.js\"\n\nexport interface AutoTraceFunctionDefinition {\n id: string\n name: string\n file: string\n line: number\n column: number\n async?: boolean\n wrapper?: boolean\n baml?: boolean\n jev?: boolean\n openrouter?: boolean\n}\n\nexport interface AutoTraceNodeConfiguration {\n functionName: string\n name?: string\n type?: \"llm\" | \"agent\" | \"function\" | \"guardrail\" | \"handoff\" | \"custom\"\n defaultType?: boolean\n capture: boolean\n experimentId?: string\n /** @deprecated Use experimentId. */\n testRunId?: string\n mockOnReplay?: boolean\n replayReusable?: boolean\n // biome-ignore lint/suspicious/noExplicitAny: node finalizers receive the configured function's result, whose type is owned by the caller\n finalize?: (result: any) => unknown | Promise<unknown>\n}\n\nexport interface NestedTraceLink {\n traceFunctionKey: string\n traceId?: string\n rootSpanId?: string\n}\n\nexport interface SpanDetails {\n contexts: Record<string, unknown>[]\n prompt?: string\n}\n\nexport interface AutoTraceEntry {\n context: AutoTraceContext\n depth: number\n spanStack: unknown\n}\n\nexport interface AutoTraceContext {\n readonly traceFunctionKey: string\n invoke<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n entry: AutoTraceEntry,\n spanDetails: SpanDetails,\n nodeConfiguration?: AutoTraceNodeConfiguration,\n ): T\n invokeNestedRoot<T>(\n name: string,\n functionName: string,\n inputs: unknown[],\n fn: () => T,\n entry: AutoTraceEntry,\n link: NestedTraceLink | undefined,\n spanDetails: SpanDetails,\n ): T\n}\n\ninterface AutoTraceRootFunction {\n name: string\n entering: boolean\n}\n\ninterface AutoTraceScope {\n entries: readonly AutoTraceEntry[]\n nodeConfiguration?: AutoTraceNodeConfiguration\n rootFunction?: AutoTraceRootFunction\n}\n\ninterface AutoTraceState {\n storage: AsyncLocalStorageLike<AutoTraceScope> | null\n browserScope: AutoTraceScope | undefined\n // Older SDK copies read this field when sharing the process-wide V4 state.\n capturePolicies: WeakMap<object, Map<string, ReadonlySet<string>>>\n activeRoots: number\n}\n\ninterface AutoTraceGlobal {\n __bitfabAutoTraceStateV4?: AutoTraceState\n __bitfab_auto_trace_transformed_v1__?: boolean\n}\n\ninterface AutoTraceAsyncGenerator {\n next(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n return(value?: unknown): Promise<IteratorResult<unknown, unknown>>\n throw(error?: unknown): Promise<IteratorResult<unknown, unknown>>\n [Symbol.asyncIterator](): AutoTraceAsyncGenerator\n}\n\nconst autoTraceGlobal = globalThis as unknown as AutoTraceGlobal\nconst autoTraceState: AutoTraceState =\n autoTraceGlobal.__bitfabAutoTraceStateV4 ?? {\n storage: null,\n browserScope: undefined,\n capturePolicies: new WeakMap(),\n activeRoots: 0,\n }\nautoTraceGlobal.__bitfabAutoTraceStateV4 = autoTraceState\n\nfunction initializeAutoTraceStorage(): void {\n autoTraceState.storage ??= createAsyncLocalStorage<AutoTraceScope>()\n}\n\nfunction runWithAutoTraceScope<T>(scope: AutoTraceScope, fn: () => T): T {\n initializeAutoTraceStorage()\n if (autoTraceState.storage) {\n return autoTraceState.storage.run(scope, fn)\n }\n\n const previous = autoTraceState.browserScope\n autoTraceState.browserScope = scope\n try {\n return fn()\n } finally {\n autoTraceState.browserScope = previous\n }\n}\n\nexport function currentAutoTraceEntries(): readonly AutoTraceEntry[] {\n return currentAutoTraceScope()?.entries ?? []\n}\n\nfunction replaceEntry(\n entries: readonly AutoTraceEntry[],\n previous: AutoTraceEntry,\n updated: AutoTraceEntry,\n): readonly AutoTraceEntry[] {\n return entries.map((entry) => (entry === previous ? updated : entry))\n}\n\nexport function runWithAutoTraceEntry<T>(\n previous: AutoTraceEntry,\n updated: AutoTraceEntry,\n fn: () => T,\n): T {\n const result = runWithAutoTraceScope(\n { entries: replaceEntry(currentAutoTraceEntries(), previous, updated) },\n fn,\n )\n if (isAutoTraceAsyncGenerator(result)) {\n return wrapAutoTraceEntryAsyncGenerator(previous, updated, result) as T\n }\n return result\n}\n\nfunction wrapAutoTraceEntryAsyncGenerator(\n previous: AutoTraceEntry,\n updated: AutoTraceEntry,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceScope(\n { entries: replaceEntry(currentAutoTraceEntries(), previous, updated) },\n () => source[method](value),\n )\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nexport function clearAutoTraceNodeConfiguration<T>(fn: () => T): T {\n return runWithAutoTraceScope({ entries: currentAutoTraceEntries() }, fn)\n}\n\nexport function runWithAutoTraceNodeConfiguration<T>(\n nodeConfiguration: AutoTraceNodeConfiguration,\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope || scope.entries.length === 0) {\n return fn()\n }\n\n const result = runWithAutoTraceScope({ ...scope, nodeConfiguration }, fn)\n if (isAutoTraceAsyncGenerator(result)) {\n return wrapAutoTraceNodeAsyncGenerator(nodeConfiguration, result) as T\n }\n return result\n}\n\nexport function runAsAutoTraceRootFunction<T>(\n functionName: string,\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope || scope.entries.length === 0 || functionName === \"\") {\n return fn()\n }\n const rootFunction: AutoTraceRootFunction = {\n name: functionName,\n entering: true,\n }\n try {\n return runWithAutoTraceScope({ ...scope, rootFunction }, fn)\n } finally {\n rootFunction.entering = false\n }\n}\n\nfunction isRootFunctionEntry(\n scope: AutoTraceScope,\n simpleName: string | undefined,\n): boolean {\n const rootFunction = scope.rootFunction\n if (rootFunction === undefined || !rootFunction.entering) {\n return false\n }\n rootFunction.entering = false\n return rootFunction.name === simpleName\n}\n\nconst SUBTREE_TRACING_DOCS_URL =\n \"https://docs.bitfab.ai/typescript-sdk#experimental-subtree-tracing\"\n\nfunction noteTransformedModule(): void {\n autoTraceGlobal.__bitfab_auto_trace_transformed_v1__ = true\n}\n\nfunction transformInstalled(): boolean {\n return autoTraceGlobal.__bitfab_auto_trace_transformed_v1__ === true\n}\n\nfunction runsOnNode(): boolean {\n return typeof process !== \"undefined\" && Boolean(process.versions?.node)\n}\n\nfunction closeAutoTraceRoot(): void {\n autoTraceState.activeRoots -= 1\n}\n\nfunction settleAutoTraceRoot(context: AutoTraceContext): void {\n closeAutoTraceRoot()\n if (transformInstalled() || !runsOnNode()) {\n return\n }\n warnOnce(\n \"auto-trace-transform-missing\",\n `trace root \"${context.traceFunctionKey}\" recorded only its own span. ` +\n \"No module in this build was compiled by @bitfab/sdk/transform, so calls \" +\n \"beneath the root were not discovered. Add the SDK's transform adapter \" +\n `to the server build: ${SUBTREE_TRACING_DOCS_URL}`,\n )\n}\n\nconst heldRootWork = new WeakMap<AutoTraceContext, Promise<unknown>[]>()\n\nexport function runWithAutoTraceRootContext<T>(\n context: AutoTraceContext,\n spanStack: unknown,\n fn: () => T,\n): T {\n autoTraceState.activeRoots += 1\n const entries = [\n ...currentAutoTraceEntries(),\n { context, depth: 0, spanStack },\n ]\n const held: Promise<unknown>[] = []\n heldRootWork.set(context, held)\n let result: T\n try {\n result = runWithAutoTraceScope({ entries }, fn)\n } catch (error) {\n heldRootWork.delete(context)\n settleAutoTraceRoot(context)\n throw error\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n heldRootWork.delete(context)\n closeAutoTraceRoot()\n return wrapAutoTraceAsyncGenerator(context, spanStack, result) as T\n }\n\n if (result instanceof Promise) {\n return result.then(\n (value) => finishAfterHeldWork(context, held, () => value),\n (error) =>\n finishAfterHeldWork(context, held, () => {\n throw error\n }),\n ) as T\n }\n\n heldRootWork.delete(context)\n settleAutoTraceRoot(context)\n return result\n}\n\nfunction finishAfterHeldWork<T>(\n context: AutoTraceContext,\n held: Promise<unknown>[],\n finish: () => T,\n): T | Promise<T> {\n const pending = held.splice(0)\n if (pending.length === 0) {\n heldRootWork.delete(context)\n settleAutoTraceRoot(context)\n return finish()\n }\n return Promise.all(pending).then(() =>\n finishAfterHeldWork(context, held, finish),\n )\n}\n\nfunction holdAutoTraceRoots(work: Promise<unknown>): void {\n const settled = work.then(\n () => undefined,\n () => undefined,\n )\n for (const entry of currentAutoTraceEntries()) {\n heldRootWork.get(entry.context)?.push(settled)\n }\n}\n\nexport function invokeThroughAutoTraceEntries<T>(\n entries: readonly AutoTraceEntry[],\n step: (entry: AutoTraceEntry, next: () => T) => T,\n fn: () => T,\n): T {\n let run = fn\n for (let index = entries.length - 1; index >= 0; index -= 1) {\n const entry = entries[index] as AutoTraceEntry\n const next = run\n run = () => step(entry, next)\n }\n return run()\n}\n\nfunction isAutoTraceAsyncGenerator(\n value: unknown,\n): value is AutoTraceAsyncGenerator {\n if (value === null || typeof value !== \"object\") {\n return false\n }\n const candidate = value as Record<PropertyKey, unknown>\n return (\n typeof candidate.next === \"function\" &&\n typeof candidate.return === \"function\" &&\n typeof candidate.throw === \"function\" &&\n typeof candidate[Symbol.asyncIterator] === \"function\"\n )\n}\n\nfunction wrapAutoTraceAsyncGenerator(\n context: AutoTraceContext,\n spanStack: unknown,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceRootContext(context, spanStack, () => source[method](value))\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nfunction wrapAutoTraceNodeAsyncGenerator(\n nodeConfiguration: AutoTraceNodeConfiguration,\n source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceNodeConfiguration(nodeConfiguration, () =>\n source[method](value),\n )\n const wrapped: AutoTraceAsyncGenerator = {\n next: (value) => step(\"next\", value),\n return: (value) => step(\"return\", value),\n throw: (error) => step(\"throw\", error),\n [Symbol.asyncIterator]: () => wrapped,\n }\n return wrapped\n}\n\nfunction shareFinalize(\n configuration: AutoTraceNodeConfiguration,\n): AutoTraceNodeConfiguration {\n const finalize = configuration.finalize\n if (finalize === undefined) {\n return configuration\n }\n let settled: Promise<unknown> | undefined\n return {\n ...configuration,\n finalize: (result: unknown) => {\n settled ??= Promise.resolve().then(() => finalize(result))\n return settled\n },\n }\n}\n\nexport function __bitfabAutoSpan<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n): T {\n noteTransformedModule()\n return invokeAsDiscoveredCall(definition, inputs, fn)\n}\n\n/**\n * Record a call the build transform did not wrap as a function, such as a\n * rewritten call site, as if the transform had discovered it. It is internal\n * runtime protocol, not a supported application API.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function invokeAsDiscoveredCall<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope || scope.entries.length === 0 || isCaptureSuppressed()) {\n return fn()\n }\n const nameParts = definition.name.split(\".\")\n const simpleName = nameParts[nameParts.length - 1]\n if (isRootFunctionEntry(scope, simpleName)) {\n return fn()\n }\n const nodeConfiguration =\n simpleName === scope.nodeConfiguration?.functionName\n ? shareFinalize(scope.nodeConfiguration)\n : undefined\n const spanDetails: SpanDetails = { contexts: [] }\n return invokeThroughAutoTraceEntries(\n scope.entries,\n (entry, next) =>\n entry.context.invoke(\n definition,\n inputs,\n next,\n entry,\n spanDetails,\n nodeConfiguration,\n ),\n fn,\n )\n}\n\nconst JEV_METHOD = \"systemOne\"\n\nconst jevDefinitions = new Map<string, AutoTraceFunctionDefinition>()\n\ntype JevReceiver = Record<typeof JEV_METHOD, (...args: unknown[]) => unknown>\n\ntype RecordedCallOutcome = { value: unknown } | { error: unknown }\n\nfunction receiverClassName(receiver: unknown): string | undefined {\n try {\n const name = (receiver as { constructor?: { name?: unknown } }).constructor\n ?.name\n return typeof name === \"string\" && name !== \"\" && name !== \"Object\"\n ? name\n : undefined\n } catch {\n return undefined\n }\n}\n\nfunction invokeRecordedClientCall(\n definition: AutoTraceFunctionDefinition,\n args: unknown[],\n call: () => unknown,\n): unknown {\n let outcome: RecordedCallOutcome | undefined\n const traced = invokeAsDiscoveredCall(definition, args, () => {\n try {\n const value = call()\n outcome = { value }\n return value\n } catch (error) {\n outcome = { error }\n throw error\n }\n })\n if (outcome === undefined) {\n return traced\n }\n if (\"value\" in outcome && traced === outcome.value) {\n return traced\n }\n if (traced instanceof Promise) {\n holdAutoTraceRoots(traced)\n }\n if (\"error\" in outcome) {\n throw outcome.error\n }\n return outcome.value\n}\n\nfunction jevDefinition(receiver: unknown): AutoTraceFunctionDefinition {\n const className = receiverClassName(receiver)\n const name =\n className === undefined ? JEV_METHOD : `${className}.${JEV_METHOD}`\n let definition = jevDefinitions.get(name)\n if (definition === undefined) {\n definition = {\n id: `ts-auto-v1:jev#${name}`,\n name,\n file: \"@typesafe-ai/sdk\",\n line: 0,\n column: 0,\n async: true,\n jev: true,\n }\n jevDefinitions.set(name, definition)\n }\n return definition\n}\n\n/**\n * Call `receiver.systemOne(...args)` from a call site rewritten by the build\n * transform. Beneath an automatic trace root the call is recorded as one `llm`\n * span with Jev's model and token usage, and the client's own returned value\n * is handed back unchanged. Outside a root it is a plain method call.\n *\n * This helper is internal transform/runtime protocol, not a supported\n * application API.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoJev(\n receiver: unknown,\n ...args: unknown[]\n): unknown {\n const target = receiver as JevReceiver\n if (!__bitfabAutoTraceActive()) {\n return target.systemOne(...args)\n }\n return invokeRecordedClientCall(jevDefinition(receiver), args, () =>\n target.systemOne(...args),\n )\n}\n\nconst OPENROUTER_METHOD = \"create\"\n\nconst openRouterDefinitions = new Map<string, AutoTraceFunctionDefinition>()\n\ntype OpenRouterReceiver = Record<\n typeof OPENROUTER_METHOD,\n (...args: unknown[]) => unknown\n>\n\nfunction openRouterDefinition(receiver: unknown): AutoTraceFunctionDefinition {\n const className = receiverClassName(receiver)\n const name =\n className === undefined\n ? OPENROUTER_METHOD\n : `${className}.${OPENROUTER_METHOD}`\n let definition = openRouterDefinitions.get(name)\n if (definition === undefined) {\n definition = {\n id: `ts-auto-v1:openrouter#${name}`,\n name,\n file: \"openai\",\n line: 0,\n column: 0,\n async: true,\n openrouter: true,\n }\n openRouterDefinitions.set(name, definition)\n }\n return definition\n}\n\n/**\n * Call `receiver.create(...args)` from a `.chat.completions.create(...)` call\n * site rewritten by the build transform. Beneath an automatic trace root, when\n * the client's base URL is `openrouter.ai` and the request does not stream,\n * the call is recorded as one `llm` span with the prompt, model, token usage,\n * and the cost OpenRouter reports, and the client's own returned value is\n * handed back unchanged. Otherwise it is a plain method call.\n *\n * This helper is internal transform/runtime protocol, not a supported\n * application API.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoOpenRouter(\n receiver: unknown,\n ...args: unknown[]\n): unknown {\n const target = receiver as OpenRouterReceiver\n if (\n !__bitfabAutoTraceActive() ||\n isStreamingRequest(args[0]) ||\n !isOpenRouterCompletions(receiver)\n ) {\n return target.create(...args)\n }\n return invokeRecordedClientCall(openRouterDefinition(receiver), args, () =>\n target.create(...args),\n )\n}\n\n/**\n * Preserve a function's original call arguments for transform cases where\n * parameter bindings discard them, such as destructured arrow parameters.\n *\n * This helper is internal transform/runtime protocol. The proxy preserves the\n * target's callability, arity, async identity, and non-constructibility while\n * only allocating a trace closure beneath an active automatic trace root.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoWrap<T extends (...args: never[]) => unknown>(\n definition: AutoTraceFunctionDefinition,\n fn: T,\n): T {\n noteTransformedModule()\n if (fn.name === \"\") {\n const nameParts = definition.name.split(\".\")\n const inferredName = nameParts[nameParts.length - 1]\n if (inferredName !== undefined) {\n Object.defineProperty(fn, \"name\", {\n configurable: true,\n value: inferredName,\n })\n }\n }\n\n const target = fn as unknown as (...args: unknown[]) => unknown\n return new Proxy(target, {\n apply(callTarget, thisArg, args) {\n if (!__bitfabAutoTraceActive()) {\n return Reflect.apply(callTarget, thisArg, args)\n }\n return __bitfabAutoSpan(definition, args, () =>\n Reflect.apply(callTarget, thisArg, args),\n )\n },\n }) as unknown as T\n}\n\n/**\n * Return whether the current call is inside an automatic trace root.\n *\n * Build transforms use this before allocating function metadata, captured\n * inputs, or an invocation closure. It is internal transform/runtime protocol,\n * not a supported application API.\n *\n * @experimental The automatic tracing protocol may change.\n */\nexport function __bitfabAutoTraceActive(): boolean {\n if (autoTraceState.activeRoots === 0 || isCaptureSuppressed()) {\n return false\n }\n return currentAutoTraceEntries().length > 0\n}\n\nfunction currentAutoTraceScope(): AutoTraceScope | undefined {\n initializeAutoTraceStorage()\n return autoTraceState.storage?.getStore() ?? autoTraceState.browserScope\n}\n\nexport function _resetAutoTraceTransformDetection(): void {\n autoTraceGlobal.__bitfab_auto_trace_transformed_v1__ = undefined\n}\n"],"mappings":"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"}
@@ -2,8 +2,9 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_autoTrace = require("./autoTrace-BikML0lX.cjs");
5
+ const require_autoTrace = require("./autoTrace-D3-OZcmR.cjs");
6
6
  exports.__bitfabAutoJev = require_autoTrace.__bitfabAutoJev;
7
+ exports.__bitfabAutoOpenRouter = require_autoTrace.__bitfabAutoOpenRouter;
7
8
  exports.__bitfabAutoSpan = require_autoTrace.__bitfabAutoSpan;
8
9
  exports.__bitfabAutoTraceActive = require_autoTrace.__bitfabAutoTraceActive;
9
10
  exports.__bitfabAutoWrap = require_autoTrace.__bitfabAutoWrap;
@@ -9,6 +9,7 @@ export interface AutoTraceFunctionDefinition {
9
9
  wrapper?: boolean;
10
10
  baml?: boolean;
11
11
  jev?: boolean;
12
+ openrouter?: boolean;
12
13
  }
13
14
  export interface AutoTraceNodeConfiguration {
14
15
  functionName: string;
@@ -70,6 +71,20 @@ export declare function invokeAsDiscoveredCall<T>(definition: AutoTraceFunctionD
70
71
  * @experimental The automatic tracing protocol may change.
71
72
  */
72
73
  export declare function __bitfabAutoJev(receiver: unknown, ...args: unknown[]): unknown;
74
+ /**
75
+ * Call `receiver.create(...args)` from a `.chat.completions.create(...)` call
76
+ * site rewritten by the build transform. Beneath an automatic trace root, when
77
+ * the client's base URL is `openrouter.ai` and the request does not stream,
78
+ * the call is recorded as one `llm` span with the prompt, model, token usage,
79
+ * and the cost OpenRouter reports, and the client's own returned value is
80
+ * handed back unchanged. Otherwise it is a plain method call.
81
+ *
82
+ * This helper is internal transform/runtime protocol, not a supported
83
+ * application API.
84
+ *
85
+ * @experimental The automatic tracing protocol may change.
86
+ */
87
+ export declare function __bitfabAutoOpenRouter(receiver: unknown, ...args: unknown[]): unknown;
73
88
  /**
74
89
  * Preserve a function's original call arguments for transform cases where
75
90
  * parameter bindings discard them, such as destructured arrow parameters.
@@ -9,6 +9,7 @@ export interface AutoTraceFunctionDefinition {
9
9
  wrapper?: boolean;
10
10
  baml?: boolean;
11
11
  jev?: boolean;
12
+ openrouter?: boolean;
12
13
  }
13
14
  export interface AutoTraceNodeConfiguration {
14
15
  functionName: string;
@@ -70,6 +71,20 @@ export declare function invokeAsDiscoveredCall<T>(definition: AutoTraceFunctionD
70
71
  * @experimental The automatic tracing protocol may change.
71
72
  */
72
73
  export declare function __bitfabAutoJev(receiver: unknown, ...args: unknown[]): unknown;
74
+ /**
75
+ * Call `receiver.create(...args)` from a `.chat.completions.create(...)` call
76
+ * site rewritten by the build transform. Beneath an automatic trace root, when
77
+ * the client's base URL is `openrouter.ai` and the request does not stream,
78
+ * the call is recorded as one `llm` span with the prompt, model, token usage,
79
+ * and the cost OpenRouter reports, and the client's own returned value is
80
+ * handed back unchanged. Otherwise it is a plain method call.
81
+ *
82
+ * This helper is internal transform/runtime protocol, not a supported
83
+ * application API.
84
+ *
85
+ * @experimental The automatic tracing protocol may change.
86
+ */
87
+ export declare function __bitfabAutoOpenRouter(receiver: unknown, ...args: unknown[]): unknown;
73
88
  /**
74
89
  * Preserve a function's original call arguments for transform cases where
75
90
  * parameter bindings discard them, such as destructured arrow parameters.
package/dist/autoTrace.js CHANGED
@@ -1 +1 @@
1
- export { t as __bitfabAutoJev, n as __bitfabAutoSpan, r as __bitfabAutoTraceActive, i as __bitfabAutoWrap, a as _resetAutoTraceTransformDetection, o as clearAutoTraceNodeConfiguration, s as currentAutoTraceEntries, c as invokeAsDiscoveredCall, l as invokeThroughAutoTraceEntries, u as runAsAutoTraceRootFunction, d as runWithAutoTraceEntry, f as runWithAutoTraceNodeConfiguration, p as runWithAutoTraceRootContext } from "./autoTrace-CVt9EDyo.js";
1
+ export { t as __bitfabAutoJev, n as __bitfabAutoOpenRouter, r as __bitfabAutoSpan, i as __bitfabAutoTraceActive, a as __bitfabAutoWrap, o as _resetAutoTraceTransformDetection, s as clearAutoTraceNodeConfiguration, c as currentAutoTraceEntries, l as invokeAsDiscoveredCall, u as invokeThroughAutoTraceEntries, d as runAsAutoTraceRootFunction, f as runWithAutoTraceEntry, p as runWithAutoTraceNodeConfiguration, m as runWithAutoTraceRootContext } from "./autoTrace-ghnojSj9.js";
@@ -151,10 +151,35 @@ function isRestWrapper(path, types) {
151
151
  const parameters = runtimeParameters(path.node, types);
152
152
  return parameters.length === 1 && types.isRestElement(parameters[0]);
153
153
  }
154
- function jevReceiver(node, types) {
154
+ function isNamedMember(node, name, types) {
155
+ return (types.isMemberExpression(node) || types.isOptionalMemberExpression(node)) && !node.computed && types.isIdentifier(node.property, { name });
156
+ }
157
+ function isChatCompletionsReceiver(receiver, types) {
158
+ return isNamedMember(receiver, "completions", types) && isNamedMember(receiver.object, "chat", types);
159
+ }
160
+ const RECORDED_CLIENT_CALLS = [{
161
+ method: JEV_METHOD,
162
+ runtimeExport: "__bitfabAutoJev",
163
+ identifierHint: "bitfabAutoJev",
164
+ receiverHint: "bitfabJevReceiver",
165
+ matchesReceiver: () => true
166
+ }, {
167
+ method: "create",
168
+ runtimeExport: "__bitfabAutoOpenRouter",
169
+ identifierHint: "bitfabAutoOpenRouter",
170
+ receiverHint: "bitfabOpenRouterReceiver",
171
+ matchesReceiver: isChatCompletionsReceiver
172
+ }];
173
+ function recordedCallTarget(node, types) {
155
174
  const callee = node.callee;
156
- if (!(types.isMemberExpression(callee) || types.isOptionalMemberExpression(callee)) || callee.computed || !types.isIdentifier(callee.property, { name: JEV_METHOD }) || types.isSuper(callee.object)) return null;
157
- return callee.object;
175
+ if (!(types.isMemberExpression(callee) || types.isOptionalMemberExpression(callee)) || callee.computed || !types.isIdentifier(callee.property) || types.isSuper(callee.object)) return null;
176
+ const method = callee.property.name;
177
+ const receiver = callee.object;
178
+ const call = RECORDED_CLIENT_CALLS.find((candidate) => candidate.method === method && candidate.matchesReceiver(receiver, types));
179
+ return call === void 0 ? null : {
180
+ call,
181
+ receiver
182
+ };
158
183
  }
159
184
  function isOptionalChain(node, types) {
160
185
  return types.isOptionalMemberExpression(node) || types.isOptionalCallExpression(node);
@@ -163,29 +188,31 @@ function continuesOptionalChain(path, types) {
163
188
  const parent = path.parent;
164
189
  return types.isOptionalMemberExpression(parent) && parent.object === path.node || types.isOptionalCallExpression(parent) && parent.callee === path.node;
165
190
  }
166
- function rewriteJevCall(path, state, types) {
167
- if (state.skipFile || state.bamlGenerated || !state.jevIdentifier) return;
191
+ function rewriteRecordedClientCall(path, state, types) {
192
+ if (state.skipFile || state.bamlGenerated) return;
168
193
  const node = path.node;
169
- const receiver = jevReceiver(node, types);
170
- if (receiver === null) return;
194
+ const target = recordedCallTarget(node, types);
195
+ const identifier = target === null ? void 0 : state.recordedCallIdentifiers?.get(target.call);
196
+ if (target === null || identifier === void 0) return;
197
+ const { call: recordedCall, receiver } = target;
171
198
  const optionalReceiver = types.isOptionalMemberExpression(node.callee) && node.callee.optional;
172
199
  const optionalMethod = types.isOptionalCallExpression(node) && node.optional;
173
200
  if (types.isOptionalCallExpression(node)) {
174
201
  if (continuesOptionalChain(path, types) || !optionalReceiver && isOptionalChain(receiver, types)) return;
175
202
  }
176
203
  const guarded = optionalReceiver || optionalMethod;
177
- const receiverReference = guarded && !path.scope.isStatic(receiver) ? path.scope.generateDeclaredUidIdentifier("bitfabJevReceiver") : null;
204
+ const receiverReference = guarded && !path.scope.isStatic(receiver) ? path.scope.generateDeclaredUidIdentifier(recordedCall.receiverHint) : null;
178
205
  const receiverValue = () => receiverReference === null ? types.cloneNode(receiver) : types.cloneNode(receiverReference);
179
- const call = types.callExpression(types.cloneNode(state.jevIdentifier), [receiverValue(), ...node.arguments]);
206
+ const call = types.callExpression(types.cloneNode(identifier), [receiverValue(), ...node.arguments]);
180
207
  state.usedRuntime = true;
181
- state.usedJev = true;
208
+ state.usedRecordedCalls?.add(recordedCall);
182
209
  if (!guarded) {
183
210
  path.replaceWith(call);
184
211
  return;
185
212
  }
186
213
  const firstReceiver = receiverReference === null ? types.cloneNode(receiver) : types.assignmentExpression("=", types.cloneNode(receiverReference), receiver);
187
214
  const missing = (value) => types.binaryExpression("==", value, types.nullLiteral());
188
- const methodOf = (value) => types.memberExpression(value, types.identifier(JEV_METHOD));
215
+ const methodOf = (value) => types.memberExpression(value, types.identifier(recordedCall.method));
189
216
  const test = optionalReceiver ? optionalMethod ? types.logicalExpression("||", missing(firstReceiver), missing(methodOf(receiverValue()))) : missing(firstReceiver) : missing(methodOf(firstReceiver));
190
217
  path.replaceWith(types.conditionalExpression(test, types.unaryExpression("void", types.numericLiteral(0)), call));
191
218
  }
@@ -200,12 +227,12 @@ function bitfabBabelPlugin(api) {
200
227
  state.runtimeIdentifier = path.scope.generateUidIdentifier("bitfabAutoSpan");
201
228
  state.activeIdentifier = path.scope.generateUidIdentifier("bitfabAutoTraceActive");
202
229
  state.wrapperIdentifier = path.scope.generateUidIdentifier("bitfabAutoWrap");
203
- state.jevIdentifier = path.scope.generateUidIdentifier("bitfabAutoJev");
230
+ state.recordedCallIdentifiers = new Map(RECORDED_CLIENT_CALLS.map((call) => [call, path.scope.generateUidIdentifier(call.identifierHint)]));
204
231
  state.bamlGenerated = isBamlGeneratedSource(state.file.code ?? "");
205
232
  state.definitions = [];
206
233
  state.usedRuntime = false;
207
234
  state.usedWrapper = false;
208
- state.usedJev = false;
235
+ state.usedRecordedCalls = /* @__PURE__ */ new Set();
209
236
  },
210
237
  exit(path, state) {
211
238
  if (state.skipFile || !state.usedRuntime || !state.runtimeIdentifier || !state.activeIdentifier || !state.wrapperIdentifier) return;
@@ -215,7 +242,10 @@ function bitfabBabelPlugin(api) {
215
242
  types.importSpecifier(state.runtimeIdentifier, types.identifier("__bitfabAutoSpan")),
216
243
  types.importSpecifier(state.activeIdentifier, types.identifier("__bitfabAutoTraceActive")),
217
244
  ...state.usedWrapper ? [types.importSpecifier(state.wrapperIdentifier, types.identifier("__bitfabAutoWrap"))] : [],
218
- ...state.usedJev && state.jevIdentifier ? [types.importSpecifier(state.jevIdentifier, types.identifier("__bitfabAutoJev"))] : []
245
+ ...RECORDED_CLIENT_CALLS.flatMap((call) => {
246
+ const identifier = state.recordedCallIdentifiers?.get(call);
247
+ return state.usedRecordedCalls?.has(call) && identifier ? [types.importSpecifier(identifier, types.identifier(call.runtimeExport))] : [];
248
+ })
219
249
  ], types.stringLiteral(state.opts.runtimeModule ?? "bitfab/auto")),
220
250
  types.variableDeclaration("const", [types.variableDeclarator(types.identifier(AUTO_TRACE_TRANSFORM_MARKER), types.assignmentExpression("=", types.memberExpression(types.identifier("globalThis"), types.identifier(AUTO_TRACE_TRANSFORM_MARKER)), types.booleanLiteral(true)))]),
221
251
  ...state.definitions ?? []
@@ -224,8 +254,8 @@ function bitfabBabelPlugin(api) {
224
254
  },
225
255
  CallExpression: { exit(path, state) {
226
256
  if (state.skipFile) return;
227
- if (jevReceiver(path.node, types) !== null) {
228
- rewriteJevCall(path, state, types);
257
+ if (recordedCallTarget(path.node, types) !== null) {
258
+ rewriteRecordedClientCall(path, state, types);
229
259
  return;
230
260
  }
231
261
  const configuredName = withNodeFunctionName(path, types);
@@ -234,7 +264,7 @@ function bitfabBabelPlugin(api) {
234
264
  path.node.arguments.push(types.stringLiteral(configuredName));
235
265
  } },
236
266
  OptionalCallExpression: { exit(path, state) {
237
- rewriteJevCall(path, state, types);
267
+ rewriteRecordedClientCall(path, state, types);
238
268
  } },
239
269
  Function: { exit(path, state) {
240
270
  const node = path.node;
@@ -308,4 +338,4 @@ Object.defineProperty(exports, "sourceFilename", {
308
338
  }
309
339
  });
310
340
 
311
- //# sourceMappingURL=babelPlugin-s8EFjT6e.cjs.map
341
+ //# sourceMappingURL=babelPlugin-0uOq-j1Q.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"babelPlugin-0uOq-j1Q.cjs","names":[],"sources":["../../bitfab-typescript-transform/src/transformOptions.ts","../../bitfab-typescript-transform/src/babelPlugin.ts"],"sourcesContent":["export interface BitfabTransformOptions {\n /** Module that exports the automatic span runtime. */\n runtimeModule?: string\n /** Working directory removed from generated function IDs. */\n cwd?: string\n /** Return false to leave a file unchanged. */\n include?: (filename: string) => boolean\n}\n\nconst AUTO_TRACE_FUNCTION_ID_VERSION = \"ts-auto-v1\"\nexport const AUTO_TRACE_TRANSFORM_MARKER =\n \"__bitfab_auto_trace_transformed_v1__\"\n\nexport function autoTraceFunctionId(file: string, name: string): string {\n return `${AUTO_TRACE_FUNCTION_ID_VERSION}:${file}#${name}`\n}\n\nexport function sourceFilename(filename: string): string {\n return filename.replace(/\\\\/g, \"/\").split(/[?#]/, 1)[0] ?? \"\"\n}\n\nexport function autoTraceFilename(filename: string, cwd: string): string {\n const normalized = sourceFilename(filename)\n const normalizedCwd = cwd.replace(/\\\\/g, \"/\").replace(/\\/$/, \"\")\n return normalized.startsWith(`${normalizedCwd}/`)\n ? normalized.slice(normalizedCwd.length + 1)\n : normalized\n}\n\nexport function shouldTransformBitfabFile(\n filename: string,\n options: BitfabTransformOptions,\n): boolean {\n if (!filename) {\n return false\n }\n if (options.include && !options.include(filename)) {\n return false\n }\n\n const normalized = sourceFilename(filename)\n const normalizedCwd = options.cwd?.replace(/\\\\/g, \"/\").replace(/\\/$/, \"\")\n const isAbsolute =\n normalized.startsWith(\"/\") || /^[A-Za-z]:\\//.test(normalized)\n if (\n normalizedCwd &&\n isAbsolute &&\n normalized !== normalizedCwd &&\n !normalized.startsWith(`${normalizedCwd}/`)\n ) {\n return false\n }\n return (\n !normalized.includes(\"/node_modules/\") &&\n !normalized.endsWith(\".d.ts\") &&\n /\\.[cm]?[jt]sx?$/.test(normalized)\n )\n}\n","import type { NodePath, PluginObject, PluginPass } from \"@babel/core\"\nimport type * as BabelTypes from \"@babel/types\"\nimport type { BitfabTransformOptions } from \"./transformOptions.js\"\nimport {\n AUTO_TRACE_TRANSFORM_MARKER,\n autoTraceFilename,\n autoTraceFunctionId,\n shouldTransformBitfabFile,\n} from \"./transformOptions.js\"\n\ntype BabelTypesApi = typeof BabelTypes\n\ntype BitfabPluginOptions = BitfabTransformOptions\n\ninterface BitfabPluginState extends PluginPass {\n opts: BitfabPluginOptions\n runtimeIdentifier?: ReturnType<BabelTypesApi[\"identifier\"]>\n activeIdentifier?: ReturnType<BabelTypesApi[\"identifier\"]>\n wrapperIdentifier?: ReturnType<BabelTypesApi[\"identifier\"]>\n recordedCallIdentifiers?: Map<\n RecordedClientCall,\n ReturnType<BabelTypesApi[\"identifier\"]>\n >\n definitions?: Array<ReturnType<BabelTypesApi[\"variableDeclaration\"]>>\n skipFile?: boolean\n bamlGenerated?: boolean\n usedRuntime?: boolean\n usedWrapper?: boolean\n usedRecordedCalls?: Set<RecordedClientCall>\n}\n\ninterface InstrumentedFunction {\n _bitfabInstrumented?: boolean\n}\n\nfunction propertyName(\n node: BabelTypes.Node | null | undefined,\n types: BabelTypesApi,\n): string | null {\n if (types.isIdentifier(node)) {\n return node.name\n }\n if (types.isStringLiteral(node)) {\n return node.value\n }\n return null\n}\n\nfunction functionName(\n path: NodePath<BabelTypes.Function>,\n types: BabelTypesApi,\n): string {\n const node = path.node\n if (types.isFunctionDeclaration(node) || types.isFunctionExpression(node)) {\n if (node.id) {\n return node.id.name\n }\n }\n\n if (\n (types.isClassMethod(node) || types.isObjectMethod(node)) &&\n !node.computed &&\n types.isIdentifier(node.key)\n ) {\n return node.key.name\n }\n\n const parent = path.parentPath?.node\n if (types.isVariableDeclarator(parent)) {\n return propertyName(parent.id, types) ?? \"anonymous\"\n }\n if (types.isObjectProperty(parent) && !parent.computed) {\n return propertyName(parent.key, types) ?? \"anonymous\"\n }\n if (types.isClassProperty(parent) && !parent.computed) {\n const name = propertyName(parent.key, types)\n if (name) {\n return name\n }\n }\n\n const { line, column } = sourcePosition(path)\n return `anonymous-${line}-${column}`\n}\n\nconst JEV_METHOD = \"systemOne\"\n\nfunction isJevMethodDefinition(\n path: NodePath<BabelTypes.Function>,\n types: BabelTypesApi,\n): boolean {\n const parent = path.parentPath?.node\n const isMethod =\n types.isClassMethod(path.node) ||\n types.isObjectMethod(path.node) ||\n types.isObjectProperty(parent) ||\n types.isClassProperty(parent)\n return isMethod && functionName(path, types) === JEV_METHOD\n}\n\nfunction isInstrumentableFunction(\n node: BabelTypes.Function,\n types: BabelTypesApi,\n): boolean {\n if (node.generator || types.isClassPrivateMethod(node)) {\n return false\n }\n return (\n !(types.isClassMethod(node) || types.isObjectMethod(node)) ||\n node.kind === \"method\"\n )\n}\n\nfunction sourcePosition(path: NodePath<BabelTypes.Function>): {\n line: number\n column: number\n} {\n const exportDeclaration = path.parentPath?.isExportDeclaration()\n ? path.parentPath.node\n : undefined\n const start = (exportDeclaration ?? path.node).loc?.start\n return { line: start?.line ?? 0, column: start?.column ?? 0 }\n}\n\nfunction qualifiedFunctionName(\n path: NodePath<BabelTypes.Function>,\n types: BabelTypesApi,\n): string {\n const ownName = functionName(path, types)\n if (ownName.startsWith(\"anonymous-\")) {\n return ownName\n }\n const scopes: string[] = []\n let ancestor: NodePath | null = path.parentPath\n while (ancestor) {\n if (ancestor.isFunction()) {\n if (!isInstrumentableFunction(ancestor.node, types)) {\n ancestor = ancestor.parentPath\n continue\n }\n const name = functionName(\n ancestor as NodePath<BabelTypes.Function>,\n types,\n )\n if (!name.startsWith(\"anonymous-\")) {\n scopes.unshift(name)\n }\n } else if (\n (ancestor.isClassDeclaration() || ancestor.isClassExpression()) &&\n ancestor.node.id\n ) {\n scopes.unshift(ancestor.node.id.name)\n } else if (ancestor.isObjectExpression()) {\n const parent = ancestor.parentPath?.node\n if (types.isVariableDeclarator(parent)) {\n const name = propertyName(parent.id, types)\n if (name) {\n scopes.unshift(name)\n }\n } else if (types.isObjectProperty(parent) && !parent.computed) {\n const name = propertyName(parent.key, types)\n if (name) {\n scopes.unshift(name)\n }\n }\n }\n ancestor = ancestor.parentPath\n }\n return [...scopes, ownName].join(\".\")\n}\n\nfunction isTraceDecoratorRoot(\n path: NodePath<BabelTypes.Function>,\n types: BabelTypesApi,\n): boolean {\n const node = path.node\n const parent = path.parentPath?.node\n const decorated =\n types.isClassMethod(node) || types.isClassPrivateMethod(node)\n ? node\n : types.isClassProperty(parent) && parent.value === node\n ? parent\n : null\n if (!decorated) {\n return false\n }\n\n return (\n decorated.decorators?.some((decorator) => {\n const expression = decorator.expression\n if (!types.isCallExpression(expression)) {\n return false\n }\n const callee = expression.callee\n return (\n types.isMemberExpression(callee) &&\n !callee.computed &&\n types.isIdentifier(callee.property, { name: \"trace\" })\n )\n }) ?? false\n )\n}\n\nfunction withNodeFunctionName(\n path: NodePath<BabelTypes.CallExpression>,\n types: BabelTypesApi,\n): string | null {\n if (path.node.arguments.length > 2) {\n return null\n }\n const callee = path.node.callee\n if (\n !types.isMemberExpression(callee) ||\n callee.computed ||\n !types.isIdentifier(callee.property, { name: \"withNode\" })\n ) {\n return null\n }\n const fn = path.node.arguments[path.node.arguments.length - 1]\n if (types.isIdentifier(fn)) {\n return fn.name\n }\n if (types.isMemberExpression(fn) && !fn.computed) {\n return propertyName(fn.property, types)\n }\n if (types.isFunctionExpression(fn) && fn.id) {\n return fn.id.name\n }\n return null\n}\n\nconst BAML_GENERATED_HEADER = \"This file was generated by BAML\"\nconst BAML_CLIENT_CLASSES = new Set([\"BamlAsyncClient\", \"BamlSyncClient\"])\nconst BAML_OPTIONS_PARAMETER = \"__baml_options__\"\n\nfunction isBamlGeneratedSource(code: string): boolean {\n return code.slice(0, 4096).includes(BAML_GENERATED_HEADER)\n}\n\nfunction isBamlClientMethod(\n path: NodePath<BabelTypes.Function>,\n types: BabelTypesApi,\n): boolean {\n const node = path.node\n if (!types.isClassMethod(node) || node.kind !== \"method\" || node.static) {\n return false\n }\n const classPath = path.parentPath?.parentPath\n if (\n !classPath ||\n !(classPath.isClassDeclaration() || classPath.isClassExpression()) ||\n !classPath.node.id ||\n !BAML_CLIENT_CLASSES.has(classPath.node.id.name)\n ) {\n return false\n }\n const parameters = runtimeParameters(node, types)\n const last = parameters[parameters.length - 1]\n return types.isIdentifier(last, { name: BAML_OPTIONS_PARAMETER })\n}\n\nfunction bamlOptionsDeclaration(\n callerOptions: BabelTypes.Identifier,\n withCollector: BabelTypes.Identifier,\n types: BabelTypesApi,\n): BabelTypes.VariableDeclaration {\n return types.variableDeclaration(\"const\", [\n types.variableDeclarator(\n types.identifier(BAML_OPTIONS_PARAMETER),\n types.conditionalExpression(\n types.binaryExpression(\n \"===\",\n types.cloneNode(withCollector),\n types.identifier(\"undefined\"),\n ),\n types.cloneNode(callerOptions),\n types.callExpression(types.cloneNode(withCollector), [\n types.cloneNode(callerOptions),\n types.memberExpression(\n types.thisExpression(),\n types.identifier(\"bamlOptions\"),\n ),\n ]),\n ),\n ),\n ])\n}\n\nfunction runtimeParameters(\n node: BabelTypes.Function,\n types: BabelTypesApi,\n): BabelTypes.Function[\"params\"] {\n return node.params.filter(\n (parameter) => !types.isIdentifier(parameter, { name: \"this\" }),\n )\n}\n\nfunction parameterInputs(\n path: NodePath<BabelTypes.Function>,\n types: BabelTypesApi,\n): ReturnType<BabelTypesApi[\"arrayExpression\"]> {\n const elements: Array<BabelTypes.Expression | BabelTypes.SpreadElement> = []\n\n for (const [index, parameter] of runtimeParameters(\n path.node,\n types,\n ).entries()) {\n if (!types.isArrowFunctionExpression(path.node)) {\n if (types.isRestElement(parameter)) {\n elements.push(\n types.spreadElement(\n types.callExpression(\n types.memberExpression(\n types.arrayExpression([\n types.spreadElement(types.identifier(\"arguments\")),\n ]),\n types.identifier(\"slice\"),\n ),\n [types.numericLiteral(index)],\n ),\n ),\n )\n } else {\n elements.push(\n types.memberExpression(\n types.identifier(\"arguments\"),\n types.numericLiteral(index),\n true,\n ),\n )\n }\n continue\n }\n\n if (types.isIdentifier(parameter)) {\n elements.push(types.identifier(parameter.name))\n } else if (\n types.isRestElement(parameter) &&\n types.isIdentifier(parameter.argument)\n ) {\n elements.push(\n types.spreadElement(types.identifier(parameter.argument.name)),\n )\n }\n }\n\n return types.arrayExpression(elements)\n}\n\nfunction needsArgumentWrapper(\n path: NodePath<BabelTypes.Function>,\n types: BabelTypesApi,\n): boolean {\n return (\n types.isArrowFunctionExpression(path.node) &&\n path.node.params.some(\n (parameter) =>\n !types.isIdentifier(parameter) &&\n !(\n types.isRestElement(parameter) &&\n types.isIdentifier(parameter.argument)\n ),\n )\n )\n}\n\nfunction isRestWrapper(\n path: NodePath<BabelTypes.Function>,\n types: BabelTypesApi,\n): boolean {\n const parameters = runtimeParameters(path.node, types)\n return parameters.length === 1 && types.isRestElement(parameters[0])\n}\n\ntype RecordedCallNode =\n | BabelTypes.CallExpression\n | BabelTypes.OptionalCallExpression\n\ninterface RecordedClientCall {\n method: string\n runtimeExport: string\n identifierHint: string\n receiverHint: string\n matchesReceiver: (\n receiver: BabelTypes.Expression,\n types: BabelTypesApi,\n ) => boolean\n}\n\nfunction isNamedMember(\n node: BabelTypes.Node,\n name: string,\n types: BabelTypesApi,\n): node is BabelTypes.MemberExpression | BabelTypes.OptionalMemberExpression {\n return (\n (types.isMemberExpression(node) ||\n types.isOptionalMemberExpression(node)) &&\n !node.computed &&\n types.isIdentifier(node.property, { name })\n )\n}\n\nfunction isChatCompletionsReceiver(\n receiver: BabelTypes.Expression,\n types: BabelTypesApi,\n): boolean {\n return (\n isNamedMember(receiver, \"completions\", types) &&\n isNamedMember(receiver.object, \"chat\", types)\n )\n}\n\nconst RECORDED_CLIENT_CALLS: readonly RecordedClientCall[] = [\n {\n method: JEV_METHOD,\n runtimeExport: \"__bitfabAutoJev\",\n identifierHint: \"bitfabAutoJev\",\n receiverHint: \"bitfabJevReceiver\",\n matchesReceiver: () => true,\n },\n {\n method: \"create\",\n runtimeExport: \"__bitfabAutoOpenRouter\",\n identifierHint: \"bitfabAutoOpenRouter\",\n receiverHint: \"bitfabOpenRouterReceiver\",\n matchesReceiver: isChatCompletionsReceiver,\n },\n]\n\nfunction recordedCallTarget(\n node: RecordedCallNode,\n types: BabelTypesApi,\n): { call: RecordedClientCall; receiver: BabelTypes.Expression } | null {\n const callee = node.callee\n if (\n !(\n types.isMemberExpression(callee) ||\n types.isOptionalMemberExpression(callee)\n ) ||\n callee.computed ||\n !types.isIdentifier(callee.property) ||\n types.isSuper(callee.object)\n ) {\n return null\n }\n const method = callee.property.name\n const receiver = callee.object\n const call = RECORDED_CLIENT_CALLS.find(\n (candidate) =>\n candidate.method === method && candidate.matchesReceiver(receiver, types),\n )\n return call === undefined ? null : { call, receiver }\n}\n\nfunction isOptionalChain(node: BabelTypes.Node, types: BabelTypesApi): boolean {\n return (\n types.isOptionalMemberExpression(node) ||\n types.isOptionalCallExpression(node)\n )\n}\n\nfunction continuesOptionalChain(\n path: NodePath<BabelTypes.OptionalCallExpression>,\n types: BabelTypesApi,\n): boolean {\n const parent = path.parent\n return (\n (types.isOptionalMemberExpression(parent) && parent.object === path.node) ||\n (types.isOptionalCallExpression(parent) && parent.callee === path.node)\n )\n}\n\nfunction rewriteRecordedClientCall(\n path: NodePath<RecordedCallNode>,\n state: BitfabPluginState,\n types: BabelTypesApi,\n): void {\n if (state.skipFile || state.bamlGenerated) {\n return\n }\n const node = path.node\n const target = recordedCallTarget(node, types)\n const identifier =\n target === null\n ? undefined\n : state.recordedCallIdentifiers?.get(target.call)\n if (target === null || identifier === undefined) {\n return\n }\n const { call: recordedCall, receiver } = target\n const optionalReceiver =\n types.isOptionalMemberExpression(node.callee) && node.callee.optional\n const optionalMethod = types.isOptionalCallExpression(node) && node.optional\n if (types.isOptionalCallExpression(node)) {\n if (\n continuesOptionalChain(\n path as NodePath<BabelTypes.OptionalCallExpression>,\n types,\n ) ||\n (!optionalReceiver && isOptionalChain(receiver, types))\n ) {\n return\n }\n }\n const guarded = optionalReceiver || optionalMethod\n const receiverReference =\n guarded && !path.scope.isStatic(receiver)\n ? path.scope.generateDeclaredUidIdentifier(recordedCall.receiverHint)\n : null\n const receiverValue = (): BabelTypes.Expression =>\n receiverReference === null\n ? types.cloneNode(receiver)\n : types.cloneNode(receiverReference)\n const call = types.callExpression(types.cloneNode(identifier), [\n receiverValue(),\n ...node.arguments,\n ])\n state.usedRuntime = true\n state.usedRecordedCalls?.add(recordedCall)\n if (!guarded) {\n path.replaceWith(call)\n return\n }\n const firstReceiver =\n receiverReference === null\n ? types.cloneNode(receiver)\n : types.assignmentExpression(\n \"=\",\n types.cloneNode(receiverReference),\n receiver,\n )\n const missing = (value: BabelTypes.Expression): BabelTypes.BinaryExpression =>\n types.binaryExpression(\"==\", value, types.nullLiteral())\n const methodOf = (value: BabelTypes.Expression): BabelTypes.Expression =>\n types.memberExpression(value, types.identifier(recordedCall.method))\n const test = optionalReceiver\n ? optionalMethod\n ? types.logicalExpression(\n \"||\",\n missing(firstReceiver),\n missing(methodOf(receiverValue())),\n )\n : missing(firstReceiver)\n : missing(methodOf(firstReceiver))\n path.replaceWith(\n types.conditionalExpression(\n test,\n types.unaryExpression(\"void\", types.numericLiteral(0)),\n call,\n ),\n )\n}\n\n/**\n * Babel adapter for Bitfab's experimental automatic call-span runtime.\n *\n * @experimental The transform protocol and generated function identities may\n * change before the feature is stable.\n */\nexport default function bitfabBabelPlugin(api: {\n types: BabelTypesApi\n}): PluginObject<BitfabPluginState> {\n const { types } = api\n\n return {\n name: \"bitfab-auto-trace\",\n visitor: {\n Program: {\n enter(path: NodePath<BabelTypes.Program>, state: BitfabPluginState) {\n const filename = state.file.opts.filename ?? \"unknown\"\n state.skipFile =\n !shouldTransformBitfabFile(filename, state.opts) ||\n path.scope.hasBinding(AUTO_TRACE_TRANSFORM_MARKER) ||\n path.node.directives.some(\n (directive) => directive.value.value === \"use client\",\n )\n state.runtimeIdentifier =\n path.scope.generateUidIdentifier(\"bitfabAutoSpan\")\n state.activeIdentifier = path.scope.generateUidIdentifier(\n \"bitfabAutoTraceActive\",\n )\n state.wrapperIdentifier =\n path.scope.generateUidIdentifier(\"bitfabAutoWrap\")\n state.recordedCallIdentifiers = new Map(\n RECORDED_CLIENT_CALLS.map((call) => [\n call,\n path.scope.generateUidIdentifier(call.identifierHint),\n ]),\n )\n state.bamlGenerated = isBamlGeneratedSource(state.file.code ?? \"\")\n state.definitions = []\n state.usedRuntime = false\n state.usedWrapper = false\n state.usedRecordedCalls = new Set()\n },\n exit(path: NodePath<BabelTypes.Program>, state: BitfabPluginState) {\n if (\n state.skipFile ||\n !state.usedRuntime ||\n !state.runtimeIdentifier ||\n !state.activeIdentifier ||\n !state.wrapperIdentifier\n ) {\n return\n }\n\n state.file.metadata[AUTO_TRACE_TRANSFORM_MARKER] = true\n path.unshiftContainer(\"body\", [\n types.importDeclaration(\n [\n types.importSpecifier(\n state.runtimeIdentifier,\n types.identifier(\"__bitfabAutoSpan\"),\n ),\n types.importSpecifier(\n state.activeIdentifier,\n types.identifier(\"__bitfabAutoTraceActive\"),\n ),\n ...(state.usedWrapper\n ? [\n types.importSpecifier(\n state.wrapperIdentifier,\n types.identifier(\"__bitfabAutoWrap\"),\n ),\n ]\n : []),\n ...RECORDED_CLIENT_CALLS.flatMap((call) => {\n const identifier = state.recordedCallIdentifiers?.get(call)\n return state.usedRecordedCalls?.has(call) && identifier\n ? [\n types.importSpecifier(\n identifier,\n types.identifier(call.runtimeExport),\n ),\n ]\n : []\n }),\n ],\n types.stringLiteral(\n state.opts.runtimeModule ?? \"bitfab/auto\",\n ),\n ),\n types.variableDeclaration(\"const\", [\n types.variableDeclarator(\n types.identifier(AUTO_TRACE_TRANSFORM_MARKER),\n types.assignmentExpression(\n \"=\",\n types.memberExpression(\n types.identifier(\"globalThis\"),\n types.identifier(AUTO_TRACE_TRANSFORM_MARKER),\n ),\n types.booleanLiteral(true),\n ),\n ),\n ]),\n ...(state.definitions ?? []),\n ])\n },\n },\n CallExpression: {\n exit(\n path: NodePath<BabelTypes.CallExpression>,\n state: BitfabPluginState,\n ) {\n if (state.skipFile) {\n return\n }\n if (recordedCallTarget(path.node, types) !== null) {\n rewriteRecordedClientCall(path, state, types)\n return\n }\n const configuredName = withNodeFunctionName(path, types)\n if (configuredName === null) {\n return\n }\n if (path.node.arguments.length === 1) {\n path.node.arguments.push(types.identifier(\"undefined\"))\n }\n path.node.arguments.push(types.stringLiteral(configuredName))\n },\n },\n OptionalCallExpression: {\n exit(\n path: NodePath<BabelTypes.OptionalCallExpression>,\n state: BitfabPluginState,\n ) {\n rewriteRecordedClientCall(path, state, types)\n },\n },\n Function: {\n exit(path: NodePath<BabelTypes.Function>, state: BitfabPluginState) {\n const node = path.node as typeof path.node & InstrumentedFunction\n if (\n state.skipFile ||\n node._bitfabInstrumented ||\n !isInstrumentableFunction(node, types) ||\n isTraceDecoratorRoot(path, types) ||\n !state.runtimeIdentifier ||\n !state.activeIdentifier ||\n !state.wrapperIdentifier\n ) {\n return\n }\n const bamlMethod =\n state.bamlGenerated === true && isBamlClientMethod(path, types)\n if (state.bamlGenerated && !bamlMethod) {\n return\n }\n if (isJevMethodDefinition(path, types)) {\n return\n }\n const name = qualifiedFunctionName(path, types)\n if (name.startsWith(\"anonymous-\")) {\n return\n }\n const normalizedFilename = autoTraceFilename(\n state.file.opts.filename ?? \"unknown\",\n state.opts.cwd ?? state.file.opts.cwd ?? process.cwd(),\n )\n const { line, column } = sourcePosition(path)\n const definition = types.objectExpression([\n types.objectProperty(\n types.identifier(\"id\"),\n types.stringLiteral(\n autoTraceFunctionId(normalizedFilename, name),\n ),\n ),\n types.objectProperty(\n types.identifier(\"name\"),\n types.stringLiteral(name),\n ),\n types.objectProperty(\n types.identifier(\"file\"),\n types.stringLiteral(normalizedFilename),\n ),\n types.objectProperty(\n types.identifier(\"line\"),\n types.numericLiteral(line),\n ),\n types.objectProperty(\n types.identifier(\"column\"),\n types.numericLiteral(column),\n ),\n ...(node.async\n ? [\n types.objectProperty(\n types.identifier(\"async\"),\n types.booleanLiteral(true),\n ),\n ]\n : []),\n ...(bamlMethod\n ? [\n types.objectProperty(\n types.identifier(\"baml\"),\n types.booleanLiteral(true),\n ),\n ]\n : []),\n ...(isRestWrapper(path, types)\n ? [\n types.objectProperty(\n types.identifier(\"wrapper\"),\n types.booleanLiteral(true),\n ),\n ]\n : []),\n ])\n const definitionIdentifier = path.scope\n .getProgramParent()\n .generateUidIdentifier(\"bitfabAutoDefinition\")\n state.definitions?.push(\n types.variableDeclaration(\"const\", [\n types.variableDeclarator(definitionIdentifier, definition),\n ]),\n )\n\n if (needsArgumentWrapper(path, types)) {\n node._bitfabInstrumented = true\n path.replaceWith(\n types.callExpression(types.cloneNode(state.wrapperIdentifier), [\n types.cloneNode(definitionIdentifier),\n node as BabelTypes.ArrowFunctionExpression,\n ]),\n )\n state.usedRuntime = true\n state.usedWrapper = true\n return\n }\n\n const originalBody = types.isBlockStatement(node.body)\n ? node.body\n : types.blockStatement([types.returnStatement(node.body)])\n const directives = originalBody.directives\n originalBody.directives = []\n\n const callerOptions = bamlMethod\n ? path.scope.generateUidIdentifier(\"bitfabBamlOptions\")\n : undefined\n const withCollector = bamlMethod\n ? path.scope.generateUidIdentifier(\"bitfabBamlWithCollector\")\n : undefined\n const tracedBody =\n callerOptions && withCollector\n ? types.blockStatement(\n [\n bamlOptionsDeclaration(callerOptions, withCollector, types),\n ...types.cloneNode(originalBody, true).body,\n ],\n [],\n )\n : types.cloneNode(originalBody, true)\n const body = types.blockStatement(\n [\n types.ifStatement(\n types.callExpression(\n types.cloneNode(state.activeIdentifier),\n [],\n ),\n types.blockStatement([\n ...(callerOptions\n ? [\n types.variableDeclaration(\"const\", [\n types.variableDeclarator(\n callerOptions,\n types.identifier(BAML_OPTIONS_PARAMETER),\n ),\n ]),\n ]\n : []),\n types.returnStatement(\n types.callExpression(\n types.cloneNode(state.runtimeIdentifier),\n [\n types.cloneNode(definitionIdentifier),\n parameterInputs(path, types),\n types.arrowFunctionExpression(\n withCollector ? [types.cloneNode(withCollector)] : [],\n tracedBody,\n node.async ?? false,\n ),\n ],\n ),\n ),\n ]),\n ),\n ...originalBody.body,\n ],\n directives,\n )\n node.body = body\n node._bitfabInstrumented = true\n state.usedRuntime = true\n },\n },\n },\n }\n}\n"],"mappings":"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"}
@@ -151,10 +151,35 @@ function isRestWrapper(path, types) {
151
151
  const parameters = runtimeParameters(path.node, types);
152
152
  return parameters.length === 1 && types.isRestElement(parameters[0]);
153
153
  }
154
- function jevReceiver(node, types) {
154
+ function isNamedMember(node, name, types) {
155
+ return (types.isMemberExpression(node) || types.isOptionalMemberExpression(node)) && !node.computed && types.isIdentifier(node.property, { name });
156
+ }
157
+ function isChatCompletionsReceiver(receiver, types) {
158
+ return isNamedMember(receiver, "completions", types) && isNamedMember(receiver.object, "chat", types);
159
+ }
160
+ const RECORDED_CLIENT_CALLS = [{
161
+ method: JEV_METHOD,
162
+ runtimeExport: "__bitfabAutoJev",
163
+ identifierHint: "bitfabAutoJev",
164
+ receiverHint: "bitfabJevReceiver",
165
+ matchesReceiver: () => true
166
+ }, {
167
+ method: "create",
168
+ runtimeExport: "__bitfabAutoOpenRouter",
169
+ identifierHint: "bitfabAutoOpenRouter",
170
+ receiverHint: "bitfabOpenRouterReceiver",
171
+ matchesReceiver: isChatCompletionsReceiver
172
+ }];
173
+ function recordedCallTarget(node, types) {
155
174
  const callee = node.callee;
156
- if (!(types.isMemberExpression(callee) || types.isOptionalMemberExpression(callee)) || callee.computed || !types.isIdentifier(callee.property, { name: JEV_METHOD }) || types.isSuper(callee.object)) return null;
157
- return callee.object;
175
+ if (!(types.isMemberExpression(callee) || types.isOptionalMemberExpression(callee)) || callee.computed || !types.isIdentifier(callee.property) || types.isSuper(callee.object)) return null;
176
+ const method = callee.property.name;
177
+ const receiver = callee.object;
178
+ const call = RECORDED_CLIENT_CALLS.find((candidate) => candidate.method === method && candidate.matchesReceiver(receiver, types));
179
+ return call === void 0 ? null : {
180
+ call,
181
+ receiver
182
+ };
158
183
  }
159
184
  function isOptionalChain(node, types) {
160
185
  return types.isOptionalMemberExpression(node) || types.isOptionalCallExpression(node);
@@ -163,29 +188,31 @@ function continuesOptionalChain(path, types) {
163
188
  const parent = path.parent;
164
189
  return types.isOptionalMemberExpression(parent) && parent.object === path.node || types.isOptionalCallExpression(parent) && parent.callee === path.node;
165
190
  }
166
- function rewriteJevCall(path, state, types) {
167
- if (state.skipFile || state.bamlGenerated || !state.jevIdentifier) return;
191
+ function rewriteRecordedClientCall(path, state, types) {
192
+ if (state.skipFile || state.bamlGenerated) return;
168
193
  const node = path.node;
169
- const receiver = jevReceiver(node, types);
170
- if (receiver === null) return;
194
+ const target = recordedCallTarget(node, types);
195
+ const identifier = target === null ? void 0 : state.recordedCallIdentifiers?.get(target.call);
196
+ if (target === null || identifier === void 0) return;
197
+ const { call: recordedCall, receiver } = target;
171
198
  const optionalReceiver = types.isOptionalMemberExpression(node.callee) && node.callee.optional;
172
199
  const optionalMethod = types.isOptionalCallExpression(node) && node.optional;
173
200
  if (types.isOptionalCallExpression(node)) {
174
201
  if (continuesOptionalChain(path, types) || !optionalReceiver && isOptionalChain(receiver, types)) return;
175
202
  }
176
203
  const guarded = optionalReceiver || optionalMethod;
177
- const receiverReference = guarded && !path.scope.isStatic(receiver) ? path.scope.generateDeclaredUidIdentifier("bitfabJevReceiver") : null;
204
+ const receiverReference = guarded && !path.scope.isStatic(receiver) ? path.scope.generateDeclaredUidIdentifier(recordedCall.receiverHint) : null;
178
205
  const receiverValue = () => receiverReference === null ? types.cloneNode(receiver) : types.cloneNode(receiverReference);
179
- const call = types.callExpression(types.cloneNode(state.jevIdentifier), [receiverValue(), ...node.arguments]);
206
+ const call = types.callExpression(types.cloneNode(identifier), [receiverValue(), ...node.arguments]);
180
207
  state.usedRuntime = true;
181
- state.usedJev = true;
208
+ state.usedRecordedCalls?.add(recordedCall);
182
209
  if (!guarded) {
183
210
  path.replaceWith(call);
184
211
  return;
185
212
  }
186
213
  const firstReceiver = receiverReference === null ? types.cloneNode(receiver) : types.assignmentExpression("=", types.cloneNode(receiverReference), receiver);
187
214
  const missing = (value) => types.binaryExpression("==", value, types.nullLiteral());
188
- const methodOf = (value) => types.memberExpression(value, types.identifier(JEV_METHOD));
215
+ const methodOf = (value) => types.memberExpression(value, types.identifier(recordedCall.method));
189
216
  const test = optionalReceiver ? optionalMethod ? types.logicalExpression("||", missing(firstReceiver), missing(methodOf(receiverValue()))) : missing(firstReceiver) : missing(methodOf(firstReceiver));
190
217
  path.replaceWith(types.conditionalExpression(test, types.unaryExpression("void", types.numericLiteral(0)), call));
191
218
  }
@@ -200,12 +227,12 @@ function bitfabBabelPlugin(api) {
200
227
  state.runtimeIdentifier = path.scope.generateUidIdentifier("bitfabAutoSpan");
201
228
  state.activeIdentifier = path.scope.generateUidIdentifier("bitfabAutoTraceActive");
202
229
  state.wrapperIdentifier = path.scope.generateUidIdentifier("bitfabAutoWrap");
203
- state.jevIdentifier = path.scope.generateUidIdentifier("bitfabAutoJev");
230
+ state.recordedCallIdentifiers = new Map(RECORDED_CLIENT_CALLS.map((call) => [call, path.scope.generateUidIdentifier(call.identifierHint)]));
204
231
  state.bamlGenerated = isBamlGeneratedSource(state.file.code ?? "");
205
232
  state.definitions = [];
206
233
  state.usedRuntime = false;
207
234
  state.usedWrapper = false;
208
- state.usedJev = false;
235
+ state.usedRecordedCalls = /* @__PURE__ */ new Set();
209
236
  },
210
237
  exit(path, state) {
211
238
  if (state.skipFile || !state.usedRuntime || !state.runtimeIdentifier || !state.activeIdentifier || !state.wrapperIdentifier) return;
@@ -215,7 +242,10 @@ function bitfabBabelPlugin(api) {
215
242
  types.importSpecifier(state.runtimeIdentifier, types.identifier("__bitfabAutoSpan")),
216
243
  types.importSpecifier(state.activeIdentifier, types.identifier("__bitfabAutoTraceActive")),
217
244
  ...state.usedWrapper ? [types.importSpecifier(state.wrapperIdentifier, types.identifier("__bitfabAutoWrap"))] : [],
218
- ...state.usedJev && state.jevIdentifier ? [types.importSpecifier(state.jevIdentifier, types.identifier("__bitfabAutoJev"))] : []
245
+ ...RECORDED_CLIENT_CALLS.flatMap((call) => {
246
+ const identifier = state.recordedCallIdentifiers?.get(call);
247
+ return state.usedRecordedCalls?.has(call) && identifier ? [types.importSpecifier(identifier, types.identifier(call.runtimeExport))] : [];
248
+ })
219
249
  ], types.stringLiteral(state.opts.runtimeModule ?? "bitfab/auto")),
220
250
  types.variableDeclaration("const", [types.variableDeclarator(types.identifier(AUTO_TRACE_TRANSFORM_MARKER), types.assignmentExpression("=", types.memberExpression(types.identifier("globalThis"), types.identifier(AUTO_TRACE_TRANSFORM_MARKER)), types.booleanLiteral(true)))]),
221
251
  ...state.definitions ?? []
@@ -224,8 +254,8 @@ function bitfabBabelPlugin(api) {
224
254
  },
225
255
  CallExpression: { exit(path, state) {
226
256
  if (state.skipFile) return;
227
- if (jevReceiver(path.node, types) !== null) {
228
- rewriteJevCall(path, state, types);
257
+ if (recordedCallTarget(path.node, types) !== null) {
258
+ rewriteRecordedClientCall(path, state, types);
229
259
  return;
230
260
  }
231
261
  const configuredName = withNodeFunctionName(path, types);
@@ -234,7 +264,7 @@ function bitfabBabelPlugin(api) {
234
264
  path.node.arguments.push(types.stringLiteral(configuredName));
235
265
  } },
236
266
  OptionalCallExpression: { exit(path, state) {
237
- rewriteJevCall(path, state, types);
267
+ rewriteRecordedClientCall(path, state, types);
238
268
  } },
239
269
  Function: { exit(path, state) {
240
270
  const node = path.node;
@@ -285,4 +315,4 @@ function bitfabBabelPlugin(api) {
285
315
  //#endregion
286
316
  export { sourceFilename as i, AUTO_TRACE_TRANSFORM_MARKER as n, shouldTransformBitfabFile as r, bitfabBabelPlugin as t };
287
317
 
288
- //# sourceMappingURL=babelPlugin-a7ofCoOd.js.map
318
+ //# sourceMappingURL=babelPlugin-Muq0uuuu.js.map