bitfab 0.21.1 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-75LZO6JS.js → chunk-4SLFC266.js} +154 -24
- package/dist/chunk-4SLFC266.js.map +1 -0
- package/dist/index.cjs +154 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +141 -20
- package/dist/index.d.ts +141 -20
- package/dist/index.js +3 -1
- package/dist/node.cjs +154 -23
- 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 +3 -1
- package/dist/node.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-75LZO6JS.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -486,6 +486,7 @@ __export(index_exports, {
|
|
|
486
486
|
BitfabFunction: () => BitfabFunction,
|
|
487
487
|
BitfabLangChainCallbackHandler: () => BitfabLangGraphCallbackHandler,
|
|
488
488
|
BitfabLangGraphCallbackHandler: () => BitfabLangGraphCallbackHandler,
|
|
489
|
+
BitfabOpenAIAgentHandler: () => BitfabOpenAIAgentHandler,
|
|
489
490
|
BitfabOpenAITracingProcessor: () => BitfabOpenAITracingProcessor,
|
|
490
491
|
DEFAULT_SERVICE_URL: () => DEFAULT_SERVICE_URL,
|
|
491
492
|
ReplayEnvironment: () => ReplayEnvironment,
|
|
@@ -499,7 +500,7 @@ __export(index_exports, {
|
|
|
499
500
|
module.exports = __toCommonJS(index_exports);
|
|
500
501
|
|
|
501
502
|
// src/version.generated.ts
|
|
502
|
-
var __version__ = "0.
|
|
503
|
+
var __version__ = "0.22.0";
|
|
503
504
|
|
|
504
505
|
// src/constants.ts
|
|
505
506
|
var DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
@@ -970,6 +971,13 @@ var BitfabClaudeAgentHandler = class {
|
|
|
970
971
|
this.currentLlmHistorySnapshot = [];
|
|
971
972
|
// Subagent tracking
|
|
972
973
|
this.activeSubagentSpans = /* @__PURE__ */ new Map();
|
|
974
|
+
// Synthetic root span (handler-only replay). When an `input` is supplied to
|
|
975
|
+
// wrapQuery/wrapResponse, the handler emits a root `agent` span carrying that
|
|
976
|
+
// input, so a handler-instrumented run is replayable WITHOUT an enclosing
|
|
977
|
+
// withSpan — matching the LangGraph handler, which records the graph input as
|
|
978
|
+
// its root. The prompt is not present anywhere in the message stream, so it
|
|
979
|
+
// must be handed in explicitly.
|
|
980
|
+
this.hasRootInput = false;
|
|
973
981
|
this.httpClient = new HttpClient({
|
|
974
982
|
apiKey: config.apiKey,
|
|
975
983
|
serviceUrl: config.serviceUrl ?? DEFAULT_SERVICE_URL,
|
|
@@ -1004,7 +1012,30 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1004
1012
|
return subagentSpanId;
|
|
1005
1013
|
}
|
|
1006
1014
|
}
|
|
1007
|
-
return this.
|
|
1015
|
+
return this.rootSpanId ?? this.activeContext?.spanId ?? null;
|
|
1016
|
+
}
|
|
1017
|
+
// Emit the synthetic root `agent` span once, before any child spans. No-op
|
|
1018
|
+
// unless an `input` was supplied AND there is no enclosing withSpan (in which
|
|
1019
|
+
// case that outer span is already the replayable root).
|
|
1020
|
+
maybeStartRootSpan() {
|
|
1021
|
+
if (!this.hasRootInput || this.rootSpanId !== null) {
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
this.ensureTrace();
|
|
1025
|
+
if (this.activeContext !== null) {
|
|
1026
|
+
return;
|
|
1027
|
+
}
|
|
1028
|
+
const spanId = crypto.randomUUID();
|
|
1029
|
+
this.startSpan(spanId, this.traceFunctionKey, "agent", this.rootInput, null);
|
|
1030
|
+
this.rootSpanId = spanId;
|
|
1031
|
+
}
|
|
1032
|
+
completeRootSpan() {
|
|
1033
|
+
if (this.rootSpanId === null) {
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
const spanId = this.rootSpanId;
|
|
1037
|
+
this.rootSpanId = null;
|
|
1038
|
+
this.completeSpan(spanId, this.rootOutput);
|
|
1008
1039
|
}
|
|
1009
1040
|
// ── span helpers ─────────────────────────────────────────────
|
|
1010
1041
|
startSpan(spanId, name, spanType, inputData, parentId) {
|
|
@@ -1200,26 +1231,53 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1200
1231
|
return options;
|
|
1201
1232
|
}
|
|
1202
1233
|
/**
|
|
1203
|
-
* Wrap
|
|
1234
|
+
* Wrap any Claude Agent SDK message stream to capture LLM turns.
|
|
1235
|
+
*
|
|
1236
|
+
* Yields every message unchanged while capturing assistant message
|
|
1237
|
+
* content as LLM turn spans. Kept for naming symmetry with the Python
|
|
1238
|
+
* SDK's `wrapResponse` (which wraps `ClaudeSDKClient.receiveResponse()`);
|
|
1239
|
+
* in TypeScript, prefer `wrapQuery` around `query()`.
|
|
1204
1240
|
*
|
|
1205
|
-
*
|
|
1206
|
-
*
|
|
1241
|
+
* Pass `{ input }` (the prompt) to record a replayable root span — see
|
|
1242
|
+
* `wrapQuery`.
|
|
1207
1243
|
*/
|
|
1208
|
-
async *wrapResponse(stream) {
|
|
1244
|
+
async *wrapResponse(stream, opts) {
|
|
1245
|
+
this.setRootInput(opts);
|
|
1209
1246
|
yield* this.processStream(stream);
|
|
1210
1247
|
}
|
|
1211
1248
|
/**
|
|
1212
1249
|
* Wrap a `query()` async iterator to capture LLM turns.
|
|
1213
1250
|
*
|
|
1214
|
-
*
|
|
1215
|
-
*
|
|
1251
|
+
* Tool and subagent spans are captured separately via the hooks injected
|
|
1252
|
+
* by `instrumentOptions` into the `options` passed to `query()`.
|
|
1253
|
+
*
|
|
1254
|
+
* Pass `{ input }` — the prompt (or the serializable args that produced it)
|
|
1255
|
+
* — to make a handler-only run replayable: the handler records a root `agent`
|
|
1256
|
+
* span with that input, so `replay(key, fn)` can re-feed it. Omit it only
|
|
1257
|
+
* when an enclosing `withSpan` already supplies the replayable root.
|
|
1258
|
+
*
|
|
1259
|
+
* ```typescript
|
|
1260
|
+
* handler.wrapQuery(query({ prompt, options }), { input: prompt })
|
|
1261
|
+
* ```
|
|
1216
1262
|
*/
|
|
1217
|
-
async *wrapQuery(stream) {
|
|
1263
|
+
async *wrapQuery(stream, opts) {
|
|
1264
|
+
this.setRootInput(opts);
|
|
1218
1265
|
yield* this.processStream(stream);
|
|
1219
1266
|
}
|
|
1267
|
+
setRootInput(opts) {
|
|
1268
|
+
if (opts && opts.input !== void 0) {
|
|
1269
|
+
this.hasRootInput = true;
|
|
1270
|
+
this.rootInput = opts.input;
|
|
1271
|
+
} else {
|
|
1272
|
+
this.hasRootInput = false;
|
|
1273
|
+
this.rootInput = void 0;
|
|
1274
|
+
}
|
|
1275
|
+
this.rootOutput = void 0;
|
|
1276
|
+
}
|
|
1220
1277
|
// ── stream processing ────────────────────────────────────────
|
|
1221
1278
|
async *processStream(stream) {
|
|
1222
1279
|
try {
|
|
1280
|
+
this.maybeStartRootSpan();
|
|
1223
1281
|
for await (const message of stream) {
|
|
1224
1282
|
try {
|
|
1225
1283
|
this.processMessage(message);
|
|
@@ -1230,6 +1288,7 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1230
1288
|
} finally {
|
|
1231
1289
|
try {
|
|
1232
1290
|
this.flushLlmTurn();
|
|
1291
|
+
this.completeRootSpan();
|
|
1233
1292
|
this.sendTraceCompletion();
|
|
1234
1293
|
} catch {
|
|
1235
1294
|
}
|
|
@@ -1237,18 +1296,19 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1237
1296
|
}
|
|
1238
1297
|
}
|
|
1239
1298
|
processMessage(message) {
|
|
1240
|
-
const typeName = message.
|
|
1241
|
-
if (typeName === "
|
|
1299
|
+
const typeName = message.type;
|
|
1300
|
+
if (typeName === "assistant") {
|
|
1242
1301
|
this.handleAssistantMessage(message);
|
|
1243
|
-
} else if (typeName === "
|
|
1302
|
+
} else if (typeName === "user") {
|
|
1244
1303
|
this.handleUserMessage(message);
|
|
1245
|
-
} else if (typeName === "
|
|
1304
|
+
} else if (typeName === "result") {
|
|
1246
1305
|
this.handleResultMessage(message);
|
|
1247
1306
|
}
|
|
1248
1307
|
}
|
|
1249
1308
|
handleAssistantMessage(message) {
|
|
1250
1309
|
this.ensureTrace();
|
|
1251
|
-
const
|
|
1310
|
+
const inner = message.message ?? {};
|
|
1311
|
+
const messageId = inner.id ?? message.uuid;
|
|
1252
1312
|
if (messageId !== this.currentLlmMessageId) {
|
|
1253
1313
|
this.flushLlmTurn();
|
|
1254
1314
|
this.conversationHistory.push(...this.pendingMessages);
|
|
@@ -1256,26 +1316,27 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1256
1316
|
this.currentLlmSpanId = crypto.randomUUID();
|
|
1257
1317
|
this.currentLlmMessageId = messageId ?? null;
|
|
1258
1318
|
this.currentLlmContent = [];
|
|
1259
|
-
this.currentLlmModel =
|
|
1319
|
+
this.currentLlmModel = inner.model ?? null;
|
|
1260
1320
|
this.currentLlmUsage = {};
|
|
1261
1321
|
this.currentLlmStartedAt = nowIso();
|
|
1262
1322
|
this.currentLlmHistorySnapshot = [...this.conversationHistory];
|
|
1263
1323
|
}
|
|
1264
|
-
const content =
|
|
1324
|
+
const content = inner.content;
|
|
1265
1325
|
if (Array.isArray(content)) {
|
|
1266
1326
|
this.currentLlmContent.push(...extractContentBlocks(content));
|
|
1267
1327
|
}
|
|
1268
|
-
const usage = extractUsage(
|
|
1328
|
+
const usage = extractUsage(inner);
|
|
1269
1329
|
if (Object.keys(usage).length > 0) {
|
|
1270
1330
|
Object.assign(this.currentLlmUsage, usage);
|
|
1271
1331
|
}
|
|
1272
|
-
const model =
|
|
1332
|
+
const model = inner.model;
|
|
1273
1333
|
if (model) {
|
|
1274
1334
|
this.currentLlmModel = model;
|
|
1275
1335
|
}
|
|
1276
1336
|
}
|
|
1277
1337
|
handleUserMessage(message) {
|
|
1278
|
-
const
|
|
1338
|
+
const inner = message.message ?? {};
|
|
1339
|
+
const content = inner.content;
|
|
1279
1340
|
const toolUseResult = message.tool_use_result;
|
|
1280
1341
|
if (toolUseResult !== void 0) {
|
|
1281
1342
|
this.pendingMessages.push({
|
|
@@ -1292,6 +1353,10 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1292
1353
|
}
|
|
1293
1354
|
handleResultMessage(message) {
|
|
1294
1355
|
this.flushLlmTurn();
|
|
1356
|
+
if (message.result !== void 0) {
|
|
1357
|
+
this.rootOutput = message.result;
|
|
1358
|
+
}
|
|
1359
|
+
this.completeRootSpan();
|
|
1295
1360
|
const metadata = {};
|
|
1296
1361
|
for (const attr of [
|
|
1297
1362
|
"num_turns",
|
|
@@ -1355,6 +1420,9 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1355
1420
|
this.runToSpan.clear();
|
|
1356
1421
|
this.traceId = null;
|
|
1357
1422
|
this.rootSpanId = null;
|
|
1423
|
+
this.hasRootInput = false;
|
|
1424
|
+
this.rootInput = void 0;
|
|
1425
|
+
this.rootOutput = void 0;
|
|
1358
1426
|
this.activeContext = null;
|
|
1359
1427
|
this.traceStartedAt = null;
|
|
1360
1428
|
this.conversationHistory = [];
|
|
@@ -2214,6 +2282,39 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2214
2282
|
}
|
|
2215
2283
|
};
|
|
2216
2284
|
|
|
2285
|
+
// src/openaiAgentSdk.ts
|
|
2286
|
+
var BitfabOpenAIAgentHandler = class {
|
|
2287
|
+
constructor(config) {
|
|
2288
|
+
this.traceFunctionKey = config.traceFunctionKey;
|
|
2289
|
+
this.withSpanFn = config.withSpan;
|
|
2290
|
+
}
|
|
2291
|
+
async wrapRun(agent, input, options) {
|
|
2292
|
+
const { run } = await import("@openai/agents");
|
|
2293
|
+
const isStreaming = options?.stream === true;
|
|
2294
|
+
const finalize = async (result) => {
|
|
2295
|
+
const res = result;
|
|
2296
|
+
if (isStreaming && res?.completed) {
|
|
2297
|
+
try {
|
|
2298
|
+
await res.completed;
|
|
2299
|
+
} catch {
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
return res?.finalOutput;
|
|
2303
|
+
};
|
|
2304
|
+
const options_ = { type: "agent", finalize };
|
|
2305
|
+
const traced = this.withSpanFn(
|
|
2306
|
+
this.traceFunctionKey,
|
|
2307
|
+
options_,
|
|
2308
|
+
(agentInput) => run(
|
|
2309
|
+
agent,
|
|
2310
|
+
agentInput,
|
|
2311
|
+
options
|
|
2312
|
+
)
|
|
2313
|
+
);
|
|
2314
|
+
return traced(input);
|
|
2315
|
+
}
|
|
2316
|
+
};
|
|
2317
|
+
|
|
2217
2318
|
// src/client.ts
|
|
2218
2319
|
init_replayContext();
|
|
2219
2320
|
|
|
@@ -2907,6 +3008,34 @@ var Bitfab = class {
|
|
|
2907
3008
|
}
|
|
2908
3009
|
});
|
|
2909
3010
|
}
|
|
3011
|
+
/**
|
|
3012
|
+
* Get an OpenAI Agents SDK handler that records a replayable root span.
|
|
3013
|
+
*
|
|
3014
|
+
* The processor from {@link getOpenAiTracingProcessor} captures everything
|
|
3015
|
+
* inside a run (LLM calls, tools, handoffs) but never sees the caller's
|
|
3016
|
+
* input, so a processor-only run records an empty-input root and is not
|
|
3017
|
+
* replayable. This handler's `wrapRun` is a drop-in for `run()` that opens a
|
|
3018
|
+
* `withSpan` root carrying the input and final output; the processor's spans
|
|
3019
|
+
* nest beneath it. Register the processor once at startup, then call
|
|
3020
|
+
* `handler.wrapRun(agent, input)` in place of `run(agent, input)`.
|
|
3021
|
+
*
|
|
3022
|
+
* ```typescript
|
|
3023
|
+
* import { addTraceProcessor, Agent, run } from "@openai/agents";
|
|
3024
|
+
*
|
|
3025
|
+
* addTraceProcessor(client.getOpenAiTracingProcessor());
|
|
3026
|
+
* const handler = client.getOpenAiAgentHandler("research-topic");
|
|
3027
|
+
* const result = await handler.wrapRun(agent, "Find X");
|
|
3028
|
+
* ```
|
|
3029
|
+
*
|
|
3030
|
+
* @param traceFunctionKey - Groups traces under this key in Bitfab
|
|
3031
|
+
* @returns A BitfabOpenAIAgentHandler configured for this client
|
|
3032
|
+
*/
|
|
3033
|
+
getOpenAiAgentHandler(traceFunctionKey) {
|
|
3034
|
+
return new BitfabOpenAIAgentHandler({
|
|
3035
|
+
traceFunctionKey,
|
|
3036
|
+
withSpan: this.withSpan.bind(this)
|
|
3037
|
+
});
|
|
3038
|
+
}
|
|
2910
3039
|
/**
|
|
2911
3040
|
* Get a LangGraph/LangChain callback handler for tracing.
|
|
2912
3041
|
*
|
|
@@ -2960,14 +3089,15 @@ var Bitfab = class {
|
|
|
2960
3089
|
* execution as Bitfab spans with proper parent-child hierarchy.
|
|
2961
3090
|
*
|
|
2962
3091
|
* ```typescript
|
|
3092
|
+
* import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
3093
|
+
*
|
|
2963
3094
|
* const handler = client.getClaudeAgentHandler("my-agent");
|
|
2964
3095
|
* const options = handler.instrumentOptions({
|
|
2965
3096
|
* model: "claude-sonnet-4-5-...",
|
|
2966
3097
|
* });
|
|
2967
|
-
* const
|
|
2968
|
-
*
|
|
2969
|
-
*
|
|
2970
|
-
* for await (const msg of handler.wrapResponse(sdkClient.receiveResponse())) {
|
|
3098
|
+
* for await (const msg of handler.wrapQuery(
|
|
3099
|
+
* query({ prompt: "Do something", options })
|
|
3100
|
+
* )) {
|
|
2971
3101
|
* // process messages
|
|
2972
3102
|
* }
|
|
2973
3103
|
* ```
|
|
@@ -3656,6 +3786,7 @@ var finalizers = {
|
|
|
3656
3786
|
BitfabFunction,
|
|
3657
3787
|
BitfabLangChainCallbackHandler,
|
|
3658
3788
|
BitfabLangGraphCallbackHandler,
|
|
3789
|
+
BitfabOpenAIAgentHandler,
|
|
3659
3790
|
BitfabOpenAITracingProcessor,
|
|
3660
3791
|
DEFAULT_SERVICE_URL,
|
|
3661
3792
|
ReplayEnvironment,
|