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/node.cjs
CHANGED
|
@@ -493,6 +493,7 @@ __export(node_exports, {
|
|
|
493
493
|
BitfabFunction: () => BitfabFunction,
|
|
494
494
|
BitfabLangChainCallbackHandler: () => BitfabLangGraphCallbackHandler,
|
|
495
495
|
BitfabLangGraphCallbackHandler: () => BitfabLangGraphCallbackHandler,
|
|
496
|
+
BitfabOpenAIAgentHandler: () => BitfabOpenAIAgentHandler,
|
|
496
497
|
BitfabOpenAITracingProcessor: () => BitfabOpenAITracingProcessor,
|
|
497
498
|
DEFAULT_SERVICE_URL: () => DEFAULT_SERVICE_URL,
|
|
498
499
|
ReplayEnvironment: () => ReplayEnvironment,
|
|
@@ -513,7 +514,7 @@ registerAsyncLocalStorageClass(
|
|
|
513
514
|
);
|
|
514
515
|
|
|
515
516
|
// src/version.generated.ts
|
|
516
|
-
var __version__ = "0.
|
|
517
|
+
var __version__ = "0.22.0";
|
|
517
518
|
|
|
518
519
|
// src/constants.ts
|
|
519
520
|
var DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
@@ -984,6 +985,13 @@ var BitfabClaudeAgentHandler = class {
|
|
|
984
985
|
this.currentLlmHistorySnapshot = [];
|
|
985
986
|
// Subagent tracking
|
|
986
987
|
this.activeSubagentSpans = /* @__PURE__ */ new Map();
|
|
988
|
+
// Synthetic root span (handler-only replay). When an `input` is supplied to
|
|
989
|
+
// wrapQuery/wrapResponse, the handler emits a root `agent` span carrying that
|
|
990
|
+
// input, so a handler-instrumented run is replayable WITHOUT an enclosing
|
|
991
|
+
// withSpan — matching the LangGraph handler, which records the graph input as
|
|
992
|
+
// its root. The prompt is not present anywhere in the message stream, so it
|
|
993
|
+
// must be handed in explicitly.
|
|
994
|
+
this.hasRootInput = false;
|
|
987
995
|
this.httpClient = new HttpClient({
|
|
988
996
|
apiKey: config.apiKey,
|
|
989
997
|
serviceUrl: config.serviceUrl ?? DEFAULT_SERVICE_URL,
|
|
@@ -1018,7 +1026,30 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1018
1026
|
return subagentSpanId;
|
|
1019
1027
|
}
|
|
1020
1028
|
}
|
|
1021
|
-
return this.
|
|
1029
|
+
return this.rootSpanId ?? this.activeContext?.spanId ?? null;
|
|
1030
|
+
}
|
|
1031
|
+
// Emit the synthetic root `agent` span once, before any child spans. No-op
|
|
1032
|
+
// unless an `input` was supplied AND there is no enclosing withSpan (in which
|
|
1033
|
+
// case that outer span is already the replayable root).
|
|
1034
|
+
maybeStartRootSpan() {
|
|
1035
|
+
if (!this.hasRootInput || this.rootSpanId !== null) {
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
this.ensureTrace();
|
|
1039
|
+
if (this.activeContext !== null) {
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
const spanId = crypto.randomUUID();
|
|
1043
|
+
this.startSpan(spanId, this.traceFunctionKey, "agent", this.rootInput, null);
|
|
1044
|
+
this.rootSpanId = spanId;
|
|
1045
|
+
}
|
|
1046
|
+
completeRootSpan() {
|
|
1047
|
+
if (this.rootSpanId === null) {
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
const spanId = this.rootSpanId;
|
|
1051
|
+
this.rootSpanId = null;
|
|
1052
|
+
this.completeSpan(spanId, this.rootOutput);
|
|
1022
1053
|
}
|
|
1023
1054
|
// ── span helpers ─────────────────────────────────────────────
|
|
1024
1055
|
startSpan(spanId, name, spanType, inputData, parentId) {
|
|
@@ -1214,26 +1245,53 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1214
1245
|
return options;
|
|
1215
1246
|
}
|
|
1216
1247
|
/**
|
|
1217
|
-
* Wrap
|
|
1248
|
+
* Wrap any Claude Agent SDK message stream to capture LLM turns.
|
|
1249
|
+
*
|
|
1250
|
+
* Yields every message unchanged while capturing assistant message
|
|
1251
|
+
* content as LLM turn spans. Kept for naming symmetry with the Python
|
|
1252
|
+
* SDK's `wrapResponse` (which wraps `ClaudeSDKClient.receiveResponse()`);
|
|
1253
|
+
* in TypeScript, prefer `wrapQuery` around `query()`.
|
|
1218
1254
|
*
|
|
1219
|
-
*
|
|
1220
|
-
*
|
|
1255
|
+
* Pass `{ input }` (the prompt) to record a replayable root span — see
|
|
1256
|
+
* `wrapQuery`.
|
|
1221
1257
|
*/
|
|
1222
|
-
async *wrapResponse(stream) {
|
|
1258
|
+
async *wrapResponse(stream, opts) {
|
|
1259
|
+
this.setRootInput(opts);
|
|
1223
1260
|
yield* this.processStream(stream);
|
|
1224
1261
|
}
|
|
1225
1262
|
/**
|
|
1226
1263
|
* Wrap a `query()` async iterator to capture LLM turns.
|
|
1227
1264
|
*
|
|
1228
|
-
*
|
|
1229
|
-
*
|
|
1265
|
+
* Tool and subagent spans are captured separately via the hooks injected
|
|
1266
|
+
* by `instrumentOptions` into the `options` passed to `query()`.
|
|
1267
|
+
*
|
|
1268
|
+
* Pass `{ input }` — the prompt (or the serializable args that produced it)
|
|
1269
|
+
* — to make a handler-only run replayable: the handler records a root `agent`
|
|
1270
|
+
* span with that input, so `replay(key, fn)` can re-feed it. Omit it only
|
|
1271
|
+
* when an enclosing `withSpan` already supplies the replayable root.
|
|
1272
|
+
*
|
|
1273
|
+
* ```typescript
|
|
1274
|
+
* handler.wrapQuery(query({ prompt, options }), { input: prompt })
|
|
1275
|
+
* ```
|
|
1230
1276
|
*/
|
|
1231
|
-
async *wrapQuery(stream) {
|
|
1277
|
+
async *wrapQuery(stream, opts) {
|
|
1278
|
+
this.setRootInput(opts);
|
|
1232
1279
|
yield* this.processStream(stream);
|
|
1233
1280
|
}
|
|
1281
|
+
setRootInput(opts) {
|
|
1282
|
+
if (opts && opts.input !== void 0) {
|
|
1283
|
+
this.hasRootInput = true;
|
|
1284
|
+
this.rootInput = opts.input;
|
|
1285
|
+
} else {
|
|
1286
|
+
this.hasRootInput = false;
|
|
1287
|
+
this.rootInput = void 0;
|
|
1288
|
+
}
|
|
1289
|
+
this.rootOutput = void 0;
|
|
1290
|
+
}
|
|
1234
1291
|
// ── stream processing ────────────────────────────────────────
|
|
1235
1292
|
async *processStream(stream) {
|
|
1236
1293
|
try {
|
|
1294
|
+
this.maybeStartRootSpan();
|
|
1237
1295
|
for await (const message of stream) {
|
|
1238
1296
|
try {
|
|
1239
1297
|
this.processMessage(message);
|
|
@@ -1244,6 +1302,7 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1244
1302
|
} finally {
|
|
1245
1303
|
try {
|
|
1246
1304
|
this.flushLlmTurn();
|
|
1305
|
+
this.completeRootSpan();
|
|
1247
1306
|
this.sendTraceCompletion();
|
|
1248
1307
|
} catch {
|
|
1249
1308
|
}
|
|
@@ -1251,18 +1310,19 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1251
1310
|
}
|
|
1252
1311
|
}
|
|
1253
1312
|
processMessage(message) {
|
|
1254
|
-
const typeName = message.
|
|
1255
|
-
if (typeName === "
|
|
1313
|
+
const typeName = message.type;
|
|
1314
|
+
if (typeName === "assistant") {
|
|
1256
1315
|
this.handleAssistantMessage(message);
|
|
1257
|
-
} else if (typeName === "
|
|
1316
|
+
} else if (typeName === "user") {
|
|
1258
1317
|
this.handleUserMessage(message);
|
|
1259
|
-
} else if (typeName === "
|
|
1318
|
+
} else if (typeName === "result") {
|
|
1260
1319
|
this.handleResultMessage(message);
|
|
1261
1320
|
}
|
|
1262
1321
|
}
|
|
1263
1322
|
handleAssistantMessage(message) {
|
|
1264
1323
|
this.ensureTrace();
|
|
1265
|
-
const
|
|
1324
|
+
const inner = message.message ?? {};
|
|
1325
|
+
const messageId = inner.id ?? message.uuid;
|
|
1266
1326
|
if (messageId !== this.currentLlmMessageId) {
|
|
1267
1327
|
this.flushLlmTurn();
|
|
1268
1328
|
this.conversationHistory.push(...this.pendingMessages);
|
|
@@ -1270,26 +1330,27 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1270
1330
|
this.currentLlmSpanId = crypto.randomUUID();
|
|
1271
1331
|
this.currentLlmMessageId = messageId ?? null;
|
|
1272
1332
|
this.currentLlmContent = [];
|
|
1273
|
-
this.currentLlmModel =
|
|
1333
|
+
this.currentLlmModel = inner.model ?? null;
|
|
1274
1334
|
this.currentLlmUsage = {};
|
|
1275
1335
|
this.currentLlmStartedAt = nowIso();
|
|
1276
1336
|
this.currentLlmHistorySnapshot = [...this.conversationHistory];
|
|
1277
1337
|
}
|
|
1278
|
-
const content =
|
|
1338
|
+
const content = inner.content;
|
|
1279
1339
|
if (Array.isArray(content)) {
|
|
1280
1340
|
this.currentLlmContent.push(...extractContentBlocks(content));
|
|
1281
1341
|
}
|
|
1282
|
-
const usage = extractUsage(
|
|
1342
|
+
const usage = extractUsage(inner);
|
|
1283
1343
|
if (Object.keys(usage).length > 0) {
|
|
1284
1344
|
Object.assign(this.currentLlmUsage, usage);
|
|
1285
1345
|
}
|
|
1286
|
-
const model =
|
|
1346
|
+
const model = inner.model;
|
|
1287
1347
|
if (model) {
|
|
1288
1348
|
this.currentLlmModel = model;
|
|
1289
1349
|
}
|
|
1290
1350
|
}
|
|
1291
1351
|
handleUserMessage(message) {
|
|
1292
|
-
const
|
|
1352
|
+
const inner = message.message ?? {};
|
|
1353
|
+
const content = inner.content;
|
|
1293
1354
|
const toolUseResult = message.tool_use_result;
|
|
1294
1355
|
if (toolUseResult !== void 0) {
|
|
1295
1356
|
this.pendingMessages.push({
|
|
@@ -1306,6 +1367,10 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1306
1367
|
}
|
|
1307
1368
|
handleResultMessage(message) {
|
|
1308
1369
|
this.flushLlmTurn();
|
|
1370
|
+
if (message.result !== void 0) {
|
|
1371
|
+
this.rootOutput = message.result;
|
|
1372
|
+
}
|
|
1373
|
+
this.completeRootSpan();
|
|
1309
1374
|
const metadata = {};
|
|
1310
1375
|
for (const attr of [
|
|
1311
1376
|
"num_turns",
|
|
@@ -1369,6 +1434,9 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1369
1434
|
this.runToSpan.clear();
|
|
1370
1435
|
this.traceId = null;
|
|
1371
1436
|
this.rootSpanId = null;
|
|
1437
|
+
this.hasRootInput = false;
|
|
1438
|
+
this.rootInput = void 0;
|
|
1439
|
+
this.rootOutput = void 0;
|
|
1372
1440
|
this.activeContext = null;
|
|
1373
1441
|
this.traceStartedAt = null;
|
|
1374
1442
|
this.conversationHistory = [];
|
|
@@ -2228,6 +2296,39 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2228
2296
|
}
|
|
2229
2297
|
};
|
|
2230
2298
|
|
|
2299
|
+
// src/openaiAgentSdk.ts
|
|
2300
|
+
var BitfabOpenAIAgentHandler = class {
|
|
2301
|
+
constructor(config) {
|
|
2302
|
+
this.traceFunctionKey = config.traceFunctionKey;
|
|
2303
|
+
this.withSpanFn = config.withSpan;
|
|
2304
|
+
}
|
|
2305
|
+
async wrapRun(agent, input, options) {
|
|
2306
|
+
const { run } = await import("@openai/agents");
|
|
2307
|
+
const isStreaming = options?.stream === true;
|
|
2308
|
+
const finalize = async (result) => {
|
|
2309
|
+
const res = result;
|
|
2310
|
+
if (isStreaming && res?.completed) {
|
|
2311
|
+
try {
|
|
2312
|
+
await res.completed;
|
|
2313
|
+
} catch {
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
return res?.finalOutput;
|
|
2317
|
+
};
|
|
2318
|
+
const options_ = { type: "agent", finalize };
|
|
2319
|
+
const traced = this.withSpanFn(
|
|
2320
|
+
this.traceFunctionKey,
|
|
2321
|
+
options_,
|
|
2322
|
+
(agentInput) => run(
|
|
2323
|
+
agent,
|
|
2324
|
+
agentInput,
|
|
2325
|
+
options
|
|
2326
|
+
)
|
|
2327
|
+
);
|
|
2328
|
+
return traced(input);
|
|
2329
|
+
}
|
|
2330
|
+
};
|
|
2331
|
+
|
|
2231
2332
|
// src/client.ts
|
|
2232
2333
|
init_replayContext();
|
|
2233
2334
|
|
|
@@ -2921,6 +3022,34 @@ var Bitfab = class {
|
|
|
2921
3022
|
}
|
|
2922
3023
|
});
|
|
2923
3024
|
}
|
|
3025
|
+
/**
|
|
3026
|
+
* Get an OpenAI Agents SDK handler that records a replayable root span.
|
|
3027
|
+
*
|
|
3028
|
+
* The processor from {@link getOpenAiTracingProcessor} captures everything
|
|
3029
|
+
* inside a run (LLM calls, tools, handoffs) but never sees the caller's
|
|
3030
|
+
* input, so a processor-only run records an empty-input root and is not
|
|
3031
|
+
* replayable. This handler's `wrapRun` is a drop-in for `run()` that opens a
|
|
3032
|
+
* `withSpan` root carrying the input and final output; the processor's spans
|
|
3033
|
+
* nest beneath it. Register the processor once at startup, then call
|
|
3034
|
+
* `handler.wrapRun(agent, input)` in place of `run(agent, input)`.
|
|
3035
|
+
*
|
|
3036
|
+
* ```typescript
|
|
3037
|
+
* import { addTraceProcessor, Agent, run } from "@openai/agents";
|
|
3038
|
+
*
|
|
3039
|
+
* addTraceProcessor(client.getOpenAiTracingProcessor());
|
|
3040
|
+
* const handler = client.getOpenAiAgentHandler("research-topic");
|
|
3041
|
+
* const result = await handler.wrapRun(agent, "Find X");
|
|
3042
|
+
* ```
|
|
3043
|
+
*
|
|
3044
|
+
* @param traceFunctionKey - Groups traces under this key in Bitfab
|
|
3045
|
+
* @returns A BitfabOpenAIAgentHandler configured for this client
|
|
3046
|
+
*/
|
|
3047
|
+
getOpenAiAgentHandler(traceFunctionKey) {
|
|
3048
|
+
return new BitfabOpenAIAgentHandler({
|
|
3049
|
+
traceFunctionKey,
|
|
3050
|
+
withSpan: this.withSpan.bind(this)
|
|
3051
|
+
});
|
|
3052
|
+
}
|
|
2924
3053
|
/**
|
|
2925
3054
|
* Get a LangGraph/LangChain callback handler for tracing.
|
|
2926
3055
|
*
|
|
@@ -2974,14 +3103,15 @@ var Bitfab = class {
|
|
|
2974
3103
|
* execution as Bitfab spans with proper parent-child hierarchy.
|
|
2975
3104
|
*
|
|
2976
3105
|
* ```typescript
|
|
3106
|
+
* import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
3107
|
+
*
|
|
2977
3108
|
* const handler = client.getClaudeAgentHandler("my-agent");
|
|
2978
3109
|
* const options = handler.instrumentOptions({
|
|
2979
3110
|
* model: "claude-sonnet-4-5-...",
|
|
2980
3111
|
* });
|
|
2981
|
-
* const
|
|
2982
|
-
*
|
|
2983
|
-
*
|
|
2984
|
-
* for await (const msg of handler.wrapResponse(sdkClient.receiveResponse())) {
|
|
3112
|
+
* for await (const msg of handler.wrapQuery(
|
|
3113
|
+
* query({ prompt: "Do something", options })
|
|
3114
|
+
* )) {
|
|
2985
3115
|
* // process messages
|
|
2986
3116
|
* }
|
|
2987
3117
|
* ```
|
|
@@ -3674,6 +3804,7 @@ assertAsyncStorageRegistered();
|
|
|
3674
3804
|
BitfabFunction,
|
|
3675
3805
|
BitfabLangChainCallbackHandler,
|
|
3676
3806
|
BitfabLangGraphCallbackHandler,
|
|
3807
|
+
BitfabOpenAIAgentHandler,
|
|
3677
3808
|
BitfabOpenAITracingProcessor,
|
|
3678
3809
|
DEFAULT_SERVICE_URL,
|
|
3679
3810
|
ReplayEnvironment,
|