bitfab 0.38.5 → 0.38.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/autoTrace.cjs +8 -1
- package/dist/autoTrace.cjs.map +1 -1
- package/dist/autoTrace.d.cts +2 -2
- package/dist/autoTrace.d.ts +2 -2
- package/dist/autoTrace.js +1 -1
- package/dist/{chunk-ZXJ3VQLF.js → chunk-2OJZPS6C.js} +2 -2
- package/dist/{chunk-ZXJ3VQLF.js.map → chunk-2OJZPS6C.js.map} +1 -1
- package/dist/{chunk-LQDCJPVV.js → chunk-DXM6GTLL.js} +313 -8
- package/dist/chunk-DXM6GTLL.js.map +1 -0
- package/dist/{chunk-J47KPS77.js → chunk-ZUD7OFYB.js} +9 -2
- package/dist/{chunk-J47KPS77.js.map → chunk-ZUD7OFYB.js.map} +1 -1
- package/dist/index.cjs +324 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +104 -6
- package/dist/index.d.ts +104 -6
- package/dist/index.js +5 -3
- package/dist/node.cjs +324 -9
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +5 -3
- package/dist/node.js.map +1 -1
- package/dist/{replay-HTVEYGC5.js → replay-KDIILV5R.js} +2 -2
- package/package.json +11 -1
- package/dist/chunk-LQDCJPVV.js.map +0 -1
- /package/dist/{replay-HTVEYGC5.js.map → replay-KDIILV5R.js.map} +0 -0
|
@@ -155,11 +155,18 @@ function currentAutoTraceScope() {
|
|
|
155
155
|
}
|
|
156
156
|
function __setBitfabAutoTraceCapturePolicy(client, traceFunctionKey, functionIds) {
|
|
157
157
|
const policies = autoTraceState.capturePolicies.get(client) ?? /* @__PURE__ */ new Map();
|
|
158
|
+
if (functionIds === void 0) {
|
|
159
|
+
policies.delete(traceFunctionKey);
|
|
160
|
+
if (policies.size === 0) {
|
|
161
|
+
autoTraceState.capturePolicies.delete(client);
|
|
162
|
+
}
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
158
165
|
policies.set(traceFunctionKey, new Set(functionIds));
|
|
159
166
|
autoTraceState.capturePolicies.set(client, policies);
|
|
160
167
|
}
|
|
161
168
|
function getAutoTraceCapturePolicy(client, traceFunctionKey) {
|
|
162
|
-
return autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey)
|
|
169
|
+
return autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey);
|
|
163
170
|
}
|
|
164
171
|
|
|
165
172
|
export {
|
|
@@ -172,4 +179,4 @@ export {
|
|
|
172
179
|
__setBitfabAutoTraceCapturePolicy,
|
|
173
180
|
getAutoTraceCapturePolicy
|
|
174
181
|
};
|
|
175
|
-
//# sourceMappingURL=chunk-
|
|
182
|
+
//# sourceMappingURL=chunk-ZUD7OFYB.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/autoTrace.ts"],"sourcesContent":["import {\n type AsyncLocalStorageLike,\n createAsyncLocalStorage,\n} from \"./asyncStorage.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}\n\nexport interface AutoTraceNodeConfiguration {\n functionName: string\n name?: string\n type?: \"llm\" | \"agent\" | \"function\" | \"guardrail\" | \"handoff\" | \"custom\"\n capture: boolean\n testRunId?: string\n mockOnReplay?: 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 AutoTraceContext {\n invoke<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n depth: number,\n nodeConfiguration?: AutoTraceNodeConfiguration,\n ): T\n}\n\ninterface AutoTraceScope {\n context: AutoTraceContext\n depth: number\n nodeConfiguration?: AutoTraceNodeConfiguration\n}\n\ninterface AutoTraceState {\n storage: AsyncLocalStorageLike<AutoTraceScope> | null\n browserScope: AutoTraceScope | undefined\n capturePolicies: WeakMap<object, Map<string, ReadonlySet<string>>>\n activeRoots: number\n}\n\ninterface AutoTraceGlobal {\n __bitfabAutoTraceStateV3?: AutoTraceState\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.__bitfabAutoTraceStateV3 ?? {\n storage: null,\n browserScope: undefined,\n capturePolicies: new WeakMap(),\n activeRoots: 0,\n }\nautoTraceGlobal.__bitfabAutoTraceStateV3 = autoTraceState\n\nfunction initializeAutoTraceStorage(): void {\n autoTraceState.storage ??= createAsyncLocalStorage<AutoTraceScope>()\n}\n\nexport function runWithAutoTraceContext<T>(\n context: AutoTraceContext,\n fn: () => T,\n depth = 0,\n): T {\n initializeAutoTraceStorage()\n const scope = { context, depth }\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 runWithAutoTraceNodeConfiguration<T>(\n nodeConfiguration: AutoTraceNodeConfiguration,\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope) {\n return fn()\n }\n\n const configuredScope = { ...scope, nodeConfiguration }\n let result: T\n if (autoTraceState.storage) {\n result = autoTraceState.storage.run(configuredScope, fn)\n } else {\n const previous = autoTraceState.browserScope\n autoTraceState.browserScope = configuredScope\n try {\n result = fn()\n } finally {\n autoTraceState.browserScope = previous\n }\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n return wrapAutoTraceNodeAsyncGenerator(nodeConfiguration, result) as T\n }\n return result\n}\n\nexport function runWithAutoTraceRootContext<T>(\n context: AutoTraceContext,\n fn: () => T,\n): T {\n autoTraceState.activeRoots += 1\n let result: T\n try {\n result = runWithAutoTraceContext(context, fn)\n } catch (error) {\n autoTraceState.activeRoots -= 1\n throw error\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n autoTraceState.activeRoots -= 1\n return wrapAutoTraceAsyncGenerator(context, result) as T\n }\n\n if (result instanceof Promise) {\n return result.finally(() => {\n autoTraceState.activeRoots -= 1\n }) as T\n }\n\n autoTraceState.activeRoots -= 1\n return result\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 source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceRootContext(context, () => 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\nexport function __bitfabAutoSpan<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope) {\n return fn()\n }\n const nameParts = definition.name.split(\".\")\n const simpleName = nameParts[nameParts.length - 1]\n const nodeConfiguration =\n simpleName === scope.nodeConfiguration?.functionName\n ? scope.nodeConfiguration\n : undefined\n return scope.context.invoke(\n definition,\n inputs,\n fn,\n scope.depth,\n nodeConfiguration,\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 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) {\n return false\n }\n return currentAutoTraceScope() !== undefined\n}\n\nfunction currentAutoTraceScope(): AutoTraceScope | undefined {\n initializeAutoTraceStorage()\n return autoTraceState.storage?.getStore() ?? autoTraceState.browserScope\n}\n\nexport function __setBitfabAutoTraceCapturePolicy(\n client: object,\n traceFunctionKey: string,\n functionIds: Iterable<string>,\n): void {\n const policies = autoTraceState.capturePolicies.get(client) ?? new Map()\n policies.set(traceFunctionKey, new Set(functionIds))\n autoTraceState.capturePolicies.set(client, policies)\n}\n\nexport function getAutoTraceCapturePolicy(\n client: object,\n traceFunctionKey: string,\n): ReadonlySet<string> {\n return (\n autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey) ??\n new Set()\n )\n}\n"],"mappings":";;;;;AA4DA,IAAM,kBAAkB;AACxB,IAAM,iBACJ,gBAAgB,4BAA4B;AAAA,EAC1C,SAAS;AAAA,EACT,cAAc;AAAA,EACd,iBAAiB,oBAAI,QAAQ;AAAA,EAC7B,aAAa;AACf;AACF,gBAAgB,2BAA2B;AAE3C,SAAS,6BAAmC;AAC1C,iBAAe,YAAf,eAAe,UAAY,wBAAwC;AACrE;AAEO,SAAS,wBACd,SACA,IACA,QAAQ,GACL;AACH,6BAA2B;AAC3B,QAAM,QAAQ,EAAE,SAAS,MAAM;AAC/B,MAAI,eAAe,SAAS;AAC1B,WAAO,eAAe,QAAQ,IAAI,OAAO,EAAE;AAAA,EAC7C;AAEA,QAAM,WAAW,eAAe;AAChC,iBAAe,eAAe;AAC9B,MAAI;AACF,WAAO,GAAG;AAAA,EACZ,UAAE;AACA,mBAAe,eAAe;AAAA,EAChC;AACF;AAEO,SAAS,kCACd,mBACA,IACG;AACH,QAAM,QAAQ,sBAAsB;AACpC,MAAI,CAAC,OAAO;AACV,WAAO,GAAG;AAAA,EACZ;AAEA,QAAM,kBAAkB,EAAE,GAAG,OAAO,kBAAkB;AACtD,MAAI;AACJ,MAAI,eAAe,SAAS;AAC1B,aAAS,eAAe,QAAQ,IAAI,iBAAiB,EAAE;AAAA,EACzD,OAAO;AACL,UAAM,WAAW,eAAe;AAChC,mBAAe,eAAe;AAC9B,QAAI;AACF,eAAS,GAAG;AAAA,IACd,UAAE;AACA,qBAAe,eAAe;AAAA,IAChC;AAAA,EACF;AAEA,MAAI,0BAA0B,MAAM,GAAG;AACrC,WAAO,gCAAgC,mBAAmB,MAAM;AAAA,EAClE;AACA,SAAO;AACT;AAEO,SAAS,4BACd,SACA,IACG;AACH,iBAAe,eAAe;AAC9B,MAAI;AACJ,MAAI;AACF,aAAS,wBAAwB,SAAS,EAAE;AAAA,EAC9C,SAAS,OAAO;AACd,mBAAe,eAAe;AAC9B,UAAM;AAAA,EACR;AAEA,MAAI,0BAA0B,MAAM,GAAG;AACrC,mBAAe,eAAe;AAC9B,WAAO,4BAA4B,SAAS,MAAM;AAAA,EACpD;AAEA,MAAI,kBAAkB,SAAS;AAC7B,WAAO,OAAO,QAAQ,MAAM;AAC1B,qBAAe,eAAe;AAAA,IAChC,CAAC;AAAA,EACH;AAEA,iBAAe,eAAe;AAC9B,SAAO;AACT;AAEA,SAAS,0BACP,OACkC;AAClC,MAAI,UAAU,QAAQ,OAAO,UAAU,UAAU;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,YAAY;AAClB,SACE,OAAO,UAAU,SAAS,cAC1B,OAAO,UAAU,WAAW,cAC5B,OAAO,UAAU,UAAU,cAC3B,OAAO,UAAU,OAAO,aAAa,MAAM;AAE/C;AAEA,SAAS,4BACP,SACA,QACyB;AACzB,QAAM,OAAO,CACX,QACA,UAEA,4BAA4B,SAAS,MAAM,OAAO,MAAM,EAAE,KAAK,CAAC;AAClE,QAAM,UAAmC;AAAA,IACvC,MAAM,CAAC,UAAU,KAAK,QAAQ,KAAK;AAAA,IACnC,QAAQ,CAAC,UAAU,KAAK,UAAU,KAAK;AAAA,IACvC,OAAO,CAAC,UAAU,KAAK,SAAS,KAAK;AAAA,IACrC,CAAC,OAAO,aAAa,GAAG,MAAM;AAAA,EAChC;AACA,SAAO;AACT;AAEA,SAAS,gCACP,mBACA,QACyB;AACzB,QAAM,OAAO,CACX,QACA,UAEA;AAAA,IAAkC;AAAA,IAAmB,MACnD,OAAO,MAAM,EAAE,KAAK;AAAA,EACtB;AACF,QAAM,UAAmC;AAAA,IACvC,MAAM,CAAC,UAAU,KAAK,QAAQ,KAAK;AAAA,IACnC,QAAQ,CAAC,UAAU,KAAK,UAAU,KAAK;AAAA,IACvC,OAAO,CAAC,UAAU,KAAK,SAAS,KAAK;AAAA,IACrC,CAAC,OAAO,aAAa,GAAG,MAAM;AAAA,EAChC;AACA,SAAO;AACT;AAEO,SAAS,iBACd,YACA,QACA,IACG;AACH,QAAM,QAAQ,sBAAsB;AACpC,MAAI,CAAC,OAAO;AACV,WAAO,GAAG;AAAA,EACZ;AACA,QAAM,YAAY,WAAW,KAAK,MAAM,GAAG;AAC3C,QAAM,aAAa,UAAU,UAAU,SAAS,CAAC;AACjD,QAAM,oBACJ,eAAe,MAAM,mBAAmB,eACpC,MAAM,oBACN;AACN,SAAO,MAAM,QAAQ;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN;AAAA,EACF;AACF;AAYO,SAAS,iBACd,YACA,IACG;AACH,MAAI,GAAG,SAAS,IAAI;AAClB,UAAM,YAAY,WAAW,KAAK,MAAM,GAAG;AAC3C,UAAM,eAAe,UAAU,UAAU,SAAS,CAAC;AACnD,QAAI,iBAAiB,QAAW;AAC9B,aAAO,eAAe,IAAI,QAAQ;AAAA,QAChC,cAAc;AAAA,QACd,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,SAAS;AACf,SAAO,IAAI,MAAM,QAAQ;AAAA,IACvB,MAAM,YAAY,SAAS,MAAM;AAC/B,UAAI,CAAC,wBAAwB,GAAG;AAC9B,eAAO,QAAQ,MAAM,YAAY,SAAS,IAAI;AAAA,MAChD;AACA,aAAO;AAAA,QAAiB;AAAA,QAAY;AAAA,QAAM,MACxC,QAAQ,MAAM,YAAY,SAAS,IAAI;AAAA,MACzC;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAWO,SAAS,0BAAmC;AACjD,MAAI,eAAe,gBAAgB,GAAG;AACpC,WAAO;AAAA,EACT;AACA,SAAO,sBAAsB,MAAM;AACrC;AAEA,SAAS,wBAAoD;AAC3D,6BAA2B;AAC3B,SAAO,eAAe,SAAS,SAAS,KAAK,eAAe;AAC9D;AAEO,SAAS,kCACd,QACA,kBACA,aACM;AACN,QAAM,WAAW,eAAe,gBAAgB,IAAI,MAAM,KAAK,oBAAI,IAAI;AACvE,WAAS,IAAI,kBAAkB,IAAI,IAAI,WAAW,CAAC;AACnD,iBAAe,gBAAgB,IAAI,QAAQ,QAAQ;AACrD;AAEO,SAAS,0BACd,QACA,kBACqB;AACrB,SACE,eAAe,gBAAgB,IAAI,MAAM,GAAG,IAAI,gBAAgB,KAChE,oBAAI,IAAI;AAEZ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/autoTrace.ts"],"sourcesContent":["import {\n type AsyncLocalStorageLike,\n createAsyncLocalStorage,\n} from \"./asyncStorage.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}\n\nexport interface AutoTraceNodeConfiguration {\n functionName: string\n name?: string\n type?: \"llm\" | \"agent\" | \"function\" | \"guardrail\" | \"handoff\" | \"custom\"\n capture: boolean\n testRunId?: string\n mockOnReplay?: 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 AutoTraceContext {\n invoke<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n depth: number,\n nodeConfiguration?: AutoTraceNodeConfiguration,\n ): T\n}\n\ninterface AutoTraceScope {\n context: AutoTraceContext\n depth: number\n nodeConfiguration?: AutoTraceNodeConfiguration\n}\n\ninterface AutoTraceState {\n storage: AsyncLocalStorageLike<AutoTraceScope> | null\n browserScope: AutoTraceScope | undefined\n capturePolicies: WeakMap<object, Map<string, ReadonlySet<string>>>\n activeRoots: number\n}\n\ninterface AutoTraceGlobal {\n __bitfabAutoTraceStateV3?: AutoTraceState\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.__bitfabAutoTraceStateV3 ?? {\n storage: null,\n browserScope: undefined,\n capturePolicies: new WeakMap(),\n activeRoots: 0,\n }\nautoTraceGlobal.__bitfabAutoTraceStateV3 = autoTraceState\n\nfunction initializeAutoTraceStorage(): void {\n autoTraceState.storage ??= createAsyncLocalStorage<AutoTraceScope>()\n}\n\nexport function runWithAutoTraceContext<T>(\n context: AutoTraceContext,\n fn: () => T,\n depth = 0,\n): T {\n initializeAutoTraceStorage()\n const scope = { context, depth }\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 runWithAutoTraceNodeConfiguration<T>(\n nodeConfiguration: AutoTraceNodeConfiguration,\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope) {\n return fn()\n }\n\n const configuredScope = { ...scope, nodeConfiguration }\n let result: T\n if (autoTraceState.storage) {\n result = autoTraceState.storage.run(configuredScope, fn)\n } else {\n const previous = autoTraceState.browserScope\n autoTraceState.browserScope = configuredScope\n try {\n result = fn()\n } finally {\n autoTraceState.browserScope = previous\n }\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n return wrapAutoTraceNodeAsyncGenerator(nodeConfiguration, result) as T\n }\n return result\n}\n\nexport function runWithAutoTraceRootContext<T>(\n context: AutoTraceContext,\n fn: () => T,\n): T {\n autoTraceState.activeRoots += 1\n let result: T\n try {\n result = runWithAutoTraceContext(context, fn)\n } catch (error) {\n autoTraceState.activeRoots -= 1\n throw error\n }\n\n if (isAutoTraceAsyncGenerator(result)) {\n autoTraceState.activeRoots -= 1\n return wrapAutoTraceAsyncGenerator(context, result) as T\n }\n\n if (result instanceof Promise) {\n return result.finally(() => {\n autoTraceState.activeRoots -= 1\n }) as T\n }\n\n autoTraceState.activeRoots -= 1\n return result\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 source: AutoTraceAsyncGenerator,\n): AutoTraceAsyncGenerator {\n const step = (\n method: \"next\" | \"return\" | \"throw\",\n value?: unknown,\n ): Promise<IteratorResult<unknown, unknown>> =>\n runWithAutoTraceRootContext(context, () => 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\nexport function __bitfabAutoSpan<T>(\n definition: AutoTraceFunctionDefinition,\n inputs: unknown[],\n fn: () => T,\n): T {\n const scope = currentAutoTraceScope()\n if (!scope) {\n return fn()\n }\n const nameParts = definition.name.split(\".\")\n const simpleName = nameParts[nameParts.length - 1]\n const nodeConfiguration =\n simpleName === scope.nodeConfiguration?.functionName\n ? scope.nodeConfiguration\n : undefined\n return scope.context.invoke(\n definition,\n inputs,\n fn,\n scope.depth,\n nodeConfiguration,\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 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) {\n return false\n }\n return currentAutoTraceScope() !== undefined\n}\n\nfunction currentAutoTraceScope(): AutoTraceScope | undefined {\n initializeAutoTraceStorage()\n return autoTraceState.storage?.getStore() ?? autoTraceState.browserScope\n}\n\nexport function __setBitfabAutoTraceCapturePolicy(\n client: object,\n traceFunctionKey: string,\n functionIds: Iterable<string> | undefined,\n): void {\n const policies = autoTraceState.capturePolicies.get(client) ?? new Map()\n if (functionIds === undefined) {\n policies.delete(traceFunctionKey)\n if (policies.size === 0) {\n autoTraceState.capturePolicies.delete(client)\n }\n return\n }\n policies.set(traceFunctionKey, new Set(functionIds))\n autoTraceState.capturePolicies.set(client, policies)\n}\n\nexport function getAutoTraceCapturePolicy(\n client: object,\n traceFunctionKey: string,\n): ReadonlySet<string> | undefined {\n return autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey)\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -51,7 +51,7 @@ var __version__, __packageName__;
|
|
|
51
51
|
var init_version_generated = __esm({
|
|
52
52
|
"src/version.generated.ts"() {
|
|
53
53
|
"use strict";
|
|
54
|
-
__version__ = "0.38.
|
|
54
|
+
__version__ = "0.38.7";
|
|
55
55
|
__packageName__ = "bitfab";
|
|
56
56
|
}
|
|
57
57
|
});
|
|
@@ -507,8 +507,8 @@ function encodePayloadBody(payload) {
|
|
|
507
507
|
const marker = { error: `payload_serialize_failed: ${message}` };
|
|
508
508
|
return { body: JSON.stringify(marker), dropped, value: marker };
|
|
509
509
|
}
|
|
510
|
-
const
|
|
511
|
-
if (dropped.length > 0 &&
|
|
510
|
+
const isRecord2 = typeof sanitized === "object" && sanitized !== null && !Array.isArray(sanitized);
|
|
511
|
+
if (dropped.length > 0 && isRecord2) {
|
|
512
512
|
const obj = sanitized;
|
|
513
513
|
const existing = Array.isArray(obj.errors) ? obj.errors : [];
|
|
514
514
|
obj.errors = [
|
|
@@ -525,7 +525,7 @@ function encodePayloadBody(payload) {
|
|
|
525
525
|
return {
|
|
526
526
|
body: JSON.stringify(sanitized),
|
|
527
527
|
dropped,
|
|
528
|
-
value:
|
|
528
|
+
value: isRecord2 ? sanitized : void 0
|
|
529
529
|
};
|
|
530
530
|
}
|
|
531
531
|
}
|
|
@@ -3141,6 +3141,7 @@ __export(index_exports, {
|
|
|
3141
3141
|
BitfabFunction: () => BitfabFunction,
|
|
3142
3142
|
BitfabLangChainCallbackHandler: () => BitfabLangGraphCallbackHandler,
|
|
3143
3143
|
BitfabLangGraphCallbackHandler: () => BitfabLangGraphCallbackHandler,
|
|
3144
|
+
BitfabLangGraphIntegration: () => BitfabLangGraphIntegration,
|
|
3144
3145
|
BitfabOpenAIAgentHandler: () => BitfabOpenAIAgentHandler,
|
|
3145
3146
|
BitfabOpenAITracingProcessor: () => BitfabOpenAITracingProcessor,
|
|
3146
3147
|
BitfabVercelAiHandler: () => BitfabVercelAiHandler,
|
|
@@ -3889,11 +3890,18 @@ function currentAutoTraceScope() {
|
|
|
3889
3890
|
}
|
|
3890
3891
|
function __setBitfabAutoTraceCapturePolicy(client, traceFunctionKey, functionIds) {
|
|
3891
3892
|
const policies = autoTraceState.capturePolicies.get(client) ?? /* @__PURE__ */ new Map();
|
|
3893
|
+
if (functionIds === void 0) {
|
|
3894
|
+
policies.delete(traceFunctionKey);
|
|
3895
|
+
if (policies.size === 0) {
|
|
3896
|
+
autoTraceState.capturePolicies.delete(client);
|
|
3897
|
+
}
|
|
3898
|
+
return;
|
|
3899
|
+
}
|
|
3892
3900
|
policies.set(traceFunctionKey, new Set(functionIds));
|
|
3893
3901
|
autoTraceState.capturePolicies.set(client, policies);
|
|
3894
3902
|
}
|
|
3895
3903
|
function getAutoTraceCapturePolicy(client, traceFunctionKey) {
|
|
3896
|
-
return autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey)
|
|
3904
|
+
return autoTraceState.capturePolicies.get(client)?.get(traceFunctionKey);
|
|
3897
3905
|
}
|
|
3898
3906
|
|
|
3899
3907
|
// src/optionalPeer.ts
|
|
@@ -4458,6 +4466,7 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
4458
4466
|
});
|
|
4459
4467
|
this.traceFunctionKey = config.traceFunctionKey;
|
|
4460
4468
|
this.getActiveSpanContext = config.getActiveSpanContext ?? null;
|
|
4469
|
+
this.captureTools = config.captureTools ?? true;
|
|
4461
4470
|
}
|
|
4462
4471
|
/**
|
|
4463
4472
|
* Flush and release the span transport this handler started. A no-op when
|
|
@@ -4766,6 +4775,9 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
4766
4775
|
}
|
|
4767
4776
|
// ── tool callbacks ────────────────────────────────────────────
|
|
4768
4777
|
async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName) {
|
|
4778
|
+
if (!this.captureTools) {
|
|
4779
|
+
return;
|
|
4780
|
+
}
|
|
4769
4781
|
try {
|
|
4770
4782
|
const serialized = tool ?? {};
|
|
4771
4783
|
const name = runName ?? serialized.name ?? "tool";
|
|
@@ -4782,12 +4794,18 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
4782
4794
|
}
|
|
4783
4795
|
}
|
|
4784
4796
|
async handleToolEnd(output, runId) {
|
|
4797
|
+
if (!this.captureTools) {
|
|
4798
|
+
return;
|
|
4799
|
+
}
|
|
4785
4800
|
try {
|
|
4786
4801
|
this.completeSpan(runId, output);
|
|
4787
4802
|
} catch {
|
|
4788
4803
|
}
|
|
4789
4804
|
}
|
|
4790
4805
|
async handleToolError(error, runId) {
|
|
4806
|
+
if (!this.captureTools) {
|
|
4807
|
+
return;
|
|
4808
|
+
}
|
|
4791
4809
|
try {
|
|
4792
4810
|
this.completeSpan(
|
|
4793
4811
|
runId,
|
|
@@ -4832,6 +4850,258 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
4832
4850
|
}
|
|
4833
4851
|
};
|
|
4834
4852
|
|
|
4853
|
+
// src/langgraphIntegration.ts
|
|
4854
|
+
init_http();
|
|
4855
|
+
init_replayContext();
|
|
4856
|
+
var TOOL_RESULT_TAG = "__bitfabLangGraphToolResult";
|
|
4857
|
+
function isRecord(value) {
|
|
4858
|
+
return typeof value === "object" && value !== null;
|
|
4859
|
+
}
|
|
4860
|
+
function isToolMessage(value) {
|
|
4861
|
+
return isRecord(value) && value.lc_direct_tool_output === true && value.type === "tool" && (typeof value.content === "string" || Array.isArray(value.content));
|
|
4862
|
+
}
|
|
4863
|
+
function isCommand(value) {
|
|
4864
|
+
return isRecord(value) && value.lg_name === "Command";
|
|
4865
|
+
}
|
|
4866
|
+
function encodeNested(value) {
|
|
4867
|
+
if (isToolMessage(value) || isCommand(value)) {
|
|
4868
|
+
return encodeNativeToolResult(value);
|
|
4869
|
+
}
|
|
4870
|
+
if (Array.isArray(value)) {
|
|
4871
|
+
return value.map(encodeNested);
|
|
4872
|
+
}
|
|
4873
|
+
if (isRecord(value)) {
|
|
4874
|
+
return Object.fromEntries(
|
|
4875
|
+
Object.entries(value).map(([key, entry]) => [key, encodeNested(entry)])
|
|
4876
|
+
);
|
|
4877
|
+
}
|
|
4878
|
+
return value;
|
|
4879
|
+
}
|
|
4880
|
+
function encodeNativeToolResult(value) {
|
|
4881
|
+
if (isToolMessage(value)) {
|
|
4882
|
+
return {
|
|
4883
|
+
[TOOL_RESULT_TAG]: "tool-message",
|
|
4884
|
+
content: value.content,
|
|
4885
|
+
name: typeof value.name === "string" ? value.name : void 0,
|
|
4886
|
+
id: typeof value.id === "string" ? value.id : void 0,
|
|
4887
|
+
status: value.status === "success" || value.status === "error" ? value.status : void 0,
|
|
4888
|
+
artifact: encodeNested(value.artifact),
|
|
4889
|
+
metadata: encodeNested(value.metadata),
|
|
4890
|
+
additionalKwargs: encodeNested(value.additional_kwargs),
|
|
4891
|
+
responseMetadata: encodeNested(value.response_metadata)
|
|
4892
|
+
};
|
|
4893
|
+
}
|
|
4894
|
+
return {
|
|
4895
|
+
[TOOL_RESULT_TAG]: "command",
|
|
4896
|
+
graph: isRecord(value) && typeof value.graph === "string" ? value.graph : void 0,
|
|
4897
|
+
update: isRecord(value) ? encodeNested(value.update) : void 0,
|
|
4898
|
+
resume: isRecord(value) ? encodeNested(value.resume) : void 0,
|
|
4899
|
+
goto: isRecord(value) ? encodeNested(value.goto) : void 0
|
|
4900
|
+
};
|
|
4901
|
+
}
|
|
4902
|
+
function finalizeToolResult(value) {
|
|
4903
|
+
return isToolMessage(value) || isCommand(value) ? encodeNativeToolResult(value) : value;
|
|
4904
|
+
}
|
|
4905
|
+
function isEncodedToolResult(value) {
|
|
4906
|
+
return isRecord(value) && typeof value[TOOL_RESULT_TAG] === "string";
|
|
4907
|
+
}
|
|
4908
|
+
async function loadLangChainCore() {
|
|
4909
|
+
try {
|
|
4910
|
+
return await importOptionalPeer([
|
|
4911
|
+
"@langchain",
|
|
4912
|
+
"core",
|
|
4913
|
+
"messages"
|
|
4914
|
+
]);
|
|
4915
|
+
} catch {
|
|
4916
|
+
throw new BitfabError(
|
|
4917
|
+
"LangGraph tool replay requires @langchain/core. Install @langchain/langgraph before using getLangGraphIntegration().",
|
|
4918
|
+
"https://docs.bitfab.ai/frameworks/langgraph"
|
|
4919
|
+
);
|
|
4920
|
+
}
|
|
4921
|
+
}
|
|
4922
|
+
async function loadLangGraph() {
|
|
4923
|
+
try {
|
|
4924
|
+
return await importOptionalPeer([
|
|
4925
|
+
"@langchain",
|
|
4926
|
+
"langgraph"
|
|
4927
|
+
]);
|
|
4928
|
+
} catch {
|
|
4929
|
+
throw new BitfabError(
|
|
4930
|
+
"Replaying a LangGraph Command requires @langchain/langgraph.",
|
|
4931
|
+
"https://docs.bitfab.ai/frameworks/langgraph"
|
|
4932
|
+
);
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4935
|
+
async function reviveNested(value, toolCallId) {
|
|
4936
|
+
if (isEncodedToolResult(value)) {
|
|
4937
|
+
return reviveToolResult(value, toolCallId);
|
|
4938
|
+
}
|
|
4939
|
+
if (Array.isArray(value)) {
|
|
4940
|
+
return Promise.all(value.map((entry) => reviveNested(entry, toolCallId)));
|
|
4941
|
+
}
|
|
4942
|
+
if (isRecord(value)) {
|
|
4943
|
+
const entries = await Promise.all(
|
|
4944
|
+
Object.entries(value).map(async ([key, entry]) => [
|
|
4945
|
+
key,
|
|
4946
|
+
await reviveNested(entry, toolCallId)
|
|
4947
|
+
])
|
|
4948
|
+
);
|
|
4949
|
+
return Object.fromEntries(entries);
|
|
4950
|
+
}
|
|
4951
|
+
return value;
|
|
4952
|
+
}
|
|
4953
|
+
async function reviveToolResult(value, toolCallId) {
|
|
4954
|
+
if (value[TOOL_RESULT_TAG] === "tool-message") {
|
|
4955
|
+
const { ToolMessage } = await loadLangChainCore();
|
|
4956
|
+
return new ToolMessage({
|
|
4957
|
+
content: value.content,
|
|
4958
|
+
tool_call_id: toolCallId,
|
|
4959
|
+
...typeof value.name === "string" && { name: value.name },
|
|
4960
|
+
...typeof value.id === "string" && { id: value.id },
|
|
4961
|
+
...(value.status === "success" || value.status === "error") && {
|
|
4962
|
+
status: value.status
|
|
4963
|
+
},
|
|
4964
|
+
...value.artifact !== void 0 && {
|
|
4965
|
+
artifact: await reviveNested(value.artifact, toolCallId)
|
|
4966
|
+
},
|
|
4967
|
+
...isRecord(value.metadata) && {
|
|
4968
|
+
metadata: await reviveNested(value.metadata, toolCallId)
|
|
4969
|
+
},
|
|
4970
|
+
...isRecord(value.additionalKwargs) && {
|
|
4971
|
+
additional_kwargs: await reviveNested(
|
|
4972
|
+
value.additionalKwargs,
|
|
4973
|
+
toolCallId
|
|
4974
|
+
)
|
|
4975
|
+
},
|
|
4976
|
+
...isRecord(value.responseMetadata) && {
|
|
4977
|
+
response_metadata: await reviveNested(
|
|
4978
|
+
value.responseMetadata,
|
|
4979
|
+
toolCallId
|
|
4980
|
+
)
|
|
4981
|
+
}
|
|
4982
|
+
});
|
|
4983
|
+
}
|
|
4984
|
+
const { Command } = await loadLangGraph();
|
|
4985
|
+
return new Command({
|
|
4986
|
+
...typeof value.graph === "string" && { graph: value.graph },
|
|
4987
|
+
...value.update !== void 0 && {
|
|
4988
|
+
update: await reviveNested(value.update, toolCallId)
|
|
4989
|
+
},
|
|
4990
|
+
...value.resume !== void 0 && {
|
|
4991
|
+
resume: await reviveNested(value.resume, toolCallId)
|
|
4992
|
+
},
|
|
4993
|
+
...value.goto !== void 0 && {
|
|
4994
|
+
goto: await reviveNested(value.goto, toolCallId)
|
|
4995
|
+
}
|
|
4996
|
+
});
|
|
4997
|
+
}
|
|
4998
|
+
var BitfabLangGraphIntegration = class {
|
|
4999
|
+
constructor(config) {
|
|
5000
|
+
this.client = config.client;
|
|
5001
|
+
this.traceFunctionKey = config.traceFunctionKey;
|
|
5002
|
+
this.callbackHandler = config.callbackHandler;
|
|
5003
|
+
this.mockToolsOnReplay = config.options?.mockToolsOnReplay ?? true;
|
|
5004
|
+
}
|
|
5005
|
+
/**
|
|
5006
|
+
* Wrap tools before passing the same returned array to both
|
|
5007
|
+
* `model.bindTools()` and `new ToolNode()`. Each invocation becomes an
|
|
5008
|
+
* independently mockable child span.
|
|
5009
|
+
*/
|
|
5010
|
+
wrapTools(tools) {
|
|
5011
|
+
return tools.map((tool) => this.wrapTool(tool));
|
|
5012
|
+
}
|
|
5013
|
+
/**
|
|
5014
|
+
* Create the normal graph entry point. The returned function adds Bitfab's
|
|
5015
|
+
* callback handler, preserves invocation config, and records only the graph
|
|
5016
|
+
* input as the replayable root input.
|
|
5017
|
+
*
|
|
5018
|
+
* @experimental This API may change before it is stable.
|
|
5019
|
+
*/
|
|
5020
|
+
createInvoker(graph) {
|
|
5021
|
+
const configuredGraph = graph.withConfig({
|
|
5022
|
+
callbacks: [this.callbackHandler]
|
|
5023
|
+
});
|
|
5024
|
+
return (input, config) => {
|
|
5025
|
+
const invoke = this.wrapInvoke(
|
|
5026
|
+
(rootInput) => configuredGraph.invoke(rootInput, config)
|
|
5027
|
+
);
|
|
5028
|
+
return invoke(input);
|
|
5029
|
+
};
|
|
5030
|
+
}
|
|
5031
|
+
wrapTool(tool) {
|
|
5032
|
+
const toolName = tool.name;
|
|
5033
|
+
if (typeof toolName !== "string" || toolName.length === 0) {
|
|
5034
|
+
throw new BitfabError(
|
|
5035
|
+
"LangGraph replayable tools must have a name.",
|
|
5036
|
+
"https://docs.bitfab.ai/frameworks/langgraph"
|
|
5037
|
+
);
|
|
5038
|
+
}
|
|
5039
|
+
const mockToolsOnReplay = this.mockToolsOnReplay;
|
|
5040
|
+
const shouldMock = typeof mockToolsOnReplay === "boolean" ? mockToolsOnReplay : mockToolsOnReplay.includes(toolName);
|
|
5041
|
+
const originalInvoke = tool.invoke.bind(tool);
|
|
5042
|
+
return new Proxy(tool, {
|
|
5043
|
+
get: (target, property) => {
|
|
5044
|
+
if (property === "invoke") {
|
|
5045
|
+
return async (input, ...rest) => {
|
|
5046
|
+
const toolCallId = isRecord(input) && typeof input.id === "string" ? input.id : "";
|
|
5047
|
+
const args = isRecord(input) && "args" in input ? input.args : input;
|
|
5048
|
+
this.assertReplayToolResultExists(toolName, shouldMock);
|
|
5049
|
+
const execute = this.client.withSpan(
|
|
5050
|
+
this.traceFunctionKey,
|
|
5051
|
+
{
|
|
5052
|
+
name: toolName,
|
|
5053
|
+
type: "function",
|
|
5054
|
+
captureWhen: "nested",
|
|
5055
|
+
mockOnReplay: shouldMock,
|
|
5056
|
+
finalize: finalizeToolResult
|
|
5057
|
+
},
|
|
5058
|
+
async (_args) => await originalInvoke(input, ...rest)
|
|
5059
|
+
);
|
|
5060
|
+
const result = await execute(args);
|
|
5061
|
+
return isEncodedToolResult(result) ? await reviveToolResult(result, toolCallId) : result;
|
|
5062
|
+
};
|
|
5063
|
+
}
|
|
5064
|
+
const value = Reflect.get(target, property, target);
|
|
5065
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
5066
|
+
}
|
|
5067
|
+
});
|
|
5068
|
+
}
|
|
5069
|
+
assertReplayToolResultExists(toolName, shouldMock) {
|
|
5070
|
+
const replayContext = getReplayContext();
|
|
5071
|
+
if (!replayContext?.mockTree) {
|
|
5072
|
+
return;
|
|
5073
|
+
}
|
|
5074
|
+
const counterKey = `${this.traceFunctionKey}:${toolName}`;
|
|
5075
|
+
const callIndex = replayContext.callCounters?.get(counterKey) ?? 0;
|
|
5076
|
+
const mockSpan = replayContext.mockTree.spans.get(
|
|
5077
|
+
`${counterKey}:${callIndex}`
|
|
5078
|
+
);
|
|
5079
|
+
const hasMatchingOverride = replayContext.mockOverrides?.some(
|
|
5080
|
+
(override) => override.match({
|
|
5081
|
+
traceFunctionKey: this.traceFunctionKey,
|
|
5082
|
+
spanName: toolName,
|
|
5083
|
+
type: "function",
|
|
5084
|
+
originalSpanId: mockSpan?.sourceSpanId
|
|
5085
|
+
})
|
|
5086
|
+
);
|
|
5087
|
+
const expectsRecordedOutput = replayContext.mockStrategy === "all" || replayContext.mockStrategy === "marked" && shouldMock;
|
|
5088
|
+
if (hasMatchingOverride !== true && expectsRecordedOutput && !mockSpan) {
|
|
5089
|
+
throw new BitfabError(
|
|
5090
|
+
`No recorded LangGraph tool result for "${toolName}" at call ${callIndex + 1}; refusing to execute the live tool during replay.`,
|
|
5091
|
+
"https://docs.bitfab.ai/frameworks/langgraph"
|
|
5092
|
+
);
|
|
5093
|
+
}
|
|
5094
|
+
}
|
|
5095
|
+
/** Wrap the function that invokes the compiled graph as the replay root. */
|
|
5096
|
+
wrapInvoke(fn) {
|
|
5097
|
+
return this.client.withSpan(
|
|
5098
|
+
this.traceFunctionKey,
|
|
5099
|
+
{ name: this.traceFunctionKey, type: "agent" },
|
|
5100
|
+
fn
|
|
5101
|
+
);
|
|
5102
|
+
}
|
|
5103
|
+
};
|
|
5104
|
+
|
|
4835
5105
|
// src/client.ts
|
|
4836
5106
|
init_mockOverride();
|
|
4837
5107
|
|
|
@@ -5682,8 +5952,9 @@ var Bitfab = class {
|
|
|
5682
5952
|
* Decorate a class method as an automatically expanded trace root.
|
|
5683
5953
|
*
|
|
5684
5954
|
* Build instrumentation turns repository functions called beneath this
|
|
5685
|
-
* method into nested spans
|
|
5686
|
-
*
|
|
5955
|
+
* method into nested spans that capture inputs, outputs, and errors by
|
|
5956
|
+
* default. A confirmed capture policy can narrow rich capture to selected
|
|
5957
|
+
* function IDs.
|
|
5687
5958
|
* Without a compatible build transform, this still records the decorated
|
|
5688
5959
|
* method as a normal rich root span but cannot discover child calls.
|
|
5689
5960
|
*
|
|
@@ -5893,7 +6164,7 @@ var Bitfab = class {
|
|
|
5893
6164
|
type: nodeConfiguration?.type ?? "function",
|
|
5894
6165
|
captureWhen: "nested",
|
|
5895
6166
|
functionId: definition.id,
|
|
5896
|
-
captureContent: nodeConfiguration !== void 0 || capturePolicy.has(definition.id),
|
|
6167
|
+
captureContent: nodeConfiguration !== void 0 || capturePolicy === void 0 || capturePolicy.has(definition.id),
|
|
5897
6168
|
autoTraceDefinition: definition,
|
|
5898
6169
|
...nodeConfiguration?.testRunId !== void 0 && {
|
|
5899
6170
|
testRunId: nodeConfiguration.testRunId
|
|
@@ -5958,7 +6229,11 @@ var Bitfab = class {
|
|
|
5958
6229
|
const functionIds = Array.isArray(policy.functionIds) ? policy.functionIds.filter(
|
|
5959
6230
|
(id) => typeof id === "string" && id.startsWith(`${AUTO_TRACE_PROTOCOL}:`)
|
|
5960
6231
|
).slice(0, DEFAULT_AUTO_TRACE_MAX_SPANS) : [];
|
|
5961
|
-
__setBitfabAutoTraceCapturePolicy(
|
|
6232
|
+
__setBitfabAutoTraceCapturePolicy(
|
|
6233
|
+
this,
|
|
6234
|
+
traceFunctionKey,
|
|
6235
|
+
policy.revision === null ? void 0 : functionIds
|
|
6236
|
+
);
|
|
5962
6237
|
state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_REFRESH_MS;
|
|
5963
6238
|
}).catch(() => {
|
|
5964
6239
|
state.refreshAfter = Date.now() + AUTO_TRACE_POLICY_RETRY_MS;
|
|
@@ -6217,6 +6492,37 @@ var Bitfab = class {
|
|
|
6217
6492
|
getLangChainCallbackHandler(traceFunctionKey) {
|
|
6218
6493
|
return this.getLangGraphCallbackHandler(traceFunctionKey);
|
|
6219
6494
|
}
|
|
6495
|
+
/**
|
|
6496
|
+
* Get the first-class LangGraph integration for tracing and replaying tools
|
|
6497
|
+
* executed by `ToolNode`.
|
|
6498
|
+
*
|
|
6499
|
+
* The integration combines `wrapTools()` for per-tool replay interception
|
|
6500
|
+
* with `createInvoker()` for a callback-configured replayable graph entry
|
|
6501
|
+
* point. Lower-level callback and root wrappers remain available.
|
|
6502
|
+
*
|
|
6503
|
+
* @param traceFunctionKey - Groups traces under this key in Bitfab
|
|
6504
|
+
* @param options - Controls which tools are marked for replay mocking
|
|
6505
|
+
* @experimental This API may change before it is stable.
|
|
6506
|
+
*/
|
|
6507
|
+
getLangGraphIntegration(traceFunctionKey, options) {
|
|
6508
|
+
const callbackHandler = new BitfabLangGraphCallbackHandler({
|
|
6509
|
+
apiKey: this.resolveApiKey(),
|
|
6510
|
+
traceFunctionKey,
|
|
6511
|
+
serviceUrl: this.serviceUrl,
|
|
6512
|
+
getActiveSpanContext: () => {
|
|
6513
|
+
const stack = getSpanStack();
|
|
6514
|
+
return stack[stack.length - 1] ?? null;
|
|
6515
|
+
},
|
|
6516
|
+
captureTools: false,
|
|
6517
|
+
_httpClient: this.httpClient
|
|
6518
|
+
});
|
|
6519
|
+
return new BitfabLangGraphIntegration({
|
|
6520
|
+
client: this,
|
|
6521
|
+
traceFunctionKey,
|
|
6522
|
+
callbackHandler,
|
|
6523
|
+
options
|
|
6524
|
+
});
|
|
6525
|
+
}
|
|
6220
6526
|
/**
|
|
6221
6527
|
* Get a Claude Agent SDK handler for tracing.
|
|
6222
6528
|
*
|
|
@@ -7247,6 +7553,14 @@ var BitfabFunction = class {
|
|
|
7247
7553
|
getLangChainCallbackHandler() {
|
|
7248
7554
|
return this.client.getLangChainCallbackHandler(this.traceFunctionKey);
|
|
7249
7555
|
}
|
|
7556
|
+
/**
|
|
7557
|
+
* Get the first-class LangGraph tool replay integration bound to this key.
|
|
7558
|
+
*
|
|
7559
|
+
* @experimental This API may change before it is stable.
|
|
7560
|
+
*/
|
|
7561
|
+
getLangGraphIntegration(options) {
|
|
7562
|
+
return this.client.getLangGraphIntegration(this.traceFunctionKey, options);
|
|
7563
|
+
}
|
|
7250
7564
|
/**
|
|
7251
7565
|
* Wrap a BAML client method to automatically capture prompt and LLM metadata.
|
|
7252
7566
|
* Delegates to the parent client's wrapBAML method.
|
|
@@ -7342,6 +7656,7 @@ function defineReplayRegistry(registry) {
|
|
|
7342
7656
|
BitfabFunction,
|
|
7343
7657
|
BitfabLangChainCallbackHandler,
|
|
7344
7658
|
BitfabLangGraphCallbackHandler,
|
|
7659
|
+
BitfabLangGraphIntegration,
|
|
7345
7660
|
BitfabOpenAIAgentHandler,
|
|
7346
7661
|
BitfabOpenAITracingProcessor,
|
|
7347
7662
|
BitfabVercelAiHandler,
|