@bitfab/sdk 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
|
@@ -484,6 +484,7 @@ __export(node_exports, {
|
|
|
484
484
|
BitfabFunction: () => BitfabFunction,
|
|
485
485
|
BitfabLangChainCallbackHandler: () => BitfabLangGraphCallbackHandler,
|
|
486
486
|
BitfabLangGraphCallbackHandler: () => BitfabLangGraphCallbackHandler,
|
|
487
|
+
BitfabOpenAIAgentHandler: () => BitfabOpenAIAgentHandler,
|
|
487
488
|
BitfabOpenAITracingProcessor: () => BitfabOpenAITracingProcessor,
|
|
488
489
|
DEFAULT_SERVICE_URL: () => DEFAULT_SERVICE_URL,
|
|
489
490
|
ReplayEnvironment: () => ReplayEnvironment,
|
|
@@ -504,7 +505,7 @@ registerAsyncLocalStorageClass(
|
|
|
504
505
|
);
|
|
505
506
|
|
|
506
507
|
// src/version.generated.ts
|
|
507
|
-
var __version__ = "0.
|
|
508
|
+
var __version__ = "0.22.0";
|
|
508
509
|
|
|
509
510
|
// src/constants.ts
|
|
510
511
|
var DEFAULT_SERVICE_URL = "https://bitfab.ai";
|
|
@@ -975,6 +976,13 @@ var BitfabClaudeAgentHandler = class {
|
|
|
975
976
|
this.currentLlmHistorySnapshot = [];
|
|
976
977
|
// Subagent tracking
|
|
977
978
|
this.activeSubagentSpans = /* @__PURE__ */ new Map();
|
|
979
|
+
// Synthetic root span (handler-only replay). When an `input` is supplied to
|
|
980
|
+
// wrapQuery/wrapResponse, the handler emits a root `agent` span carrying that
|
|
981
|
+
// input, so a handler-instrumented run is replayable WITHOUT an enclosing
|
|
982
|
+
// withSpan — matching the LangGraph handler, which records the graph input as
|
|
983
|
+
// its root. The prompt is not present anywhere in the message stream, so it
|
|
984
|
+
// must be handed in explicitly.
|
|
985
|
+
this.hasRootInput = false;
|
|
978
986
|
this.httpClient = new HttpClient({
|
|
979
987
|
apiKey: config.apiKey,
|
|
980
988
|
serviceUrl: config.serviceUrl ?? DEFAULT_SERVICE_URL,
|
|
@@ -1009,7 +1017,30 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1009
1017
|
return subagentSpanId;
|
|
1010
1018
|
}
|
|
1011
1019
|
}
|
|
1012
|
-
return this.
|
|
1020
|
+
return this.rootSpanId ?? this.activeContext?.spanId ?? null;
|
|
1021
|
+
}
|
|
1022
|
+
// Emit the synthetic root `agent` span once, before any child spans. No-op
|
|
1023
|
+
// unless an `input` was supplied AND there is no enclosing withSpan (in which
|
|
1024
|
+
// case that outer span is already the replayable root).
|
|
1025
|
+
maybeStartRootSpan() {
|
|
1026
|
+
if (!this.hasRootInput || this.rootSpanId !== null) {
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
1029
|
+
this.ensureTrace();
|
|
1030
|
+
if (this.activeContext !== null) {
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
const spanId = crypto.randomUUID();
|
|
1034
|
+
this.startSpan(spanId, this.traceFunctionKey, "agent", this.rootInput, null);
|
|
1035
|
+
this.rootSpanId = spanId;
|
|
1036
|
+
}
|
|
1037
|
+
completeRootSpan() {
|
|
1038
|
+
if (this.rootSpanId === null) {
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
const spanId = this.rootSpanId;
|
|
1042
|
+
this.rootSpanId = null;
|
|
1043
|
+
this.completeSpan(spanId, this.rootOutput);
|
|
1013
1044
|
}
|
|
1014
1045
|
// ── span helpers ─────────────────────────────────────────────
|
|
1015
1046
|
startSpan(spanId, name, spanType, inputData, parentId) {
|
|
@@ -1205,26 +1236,53 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1205
1236
|
return options;
|
|
1206
1237
|
}
|
|
1207
1238
|
/**
|
|
1208
|
-
* Wrap
|
|
1239
|
+
* Wrap any Claude Agent SDK message stream to capture LLM turns.
|
|
1240
|
+
*
|
|
1241
|
+
* Yields every message unchanged while capturing assistant message
|
|
1242
|
+
* content as LLM turn spans. Kept for naming symmetry with the Python
|
|
1243
|
+
* SDK's `wrapResponse` (which wraps `ClaudeSDKClient.receiveResponse()`);
|
|
1244
|
+
* in TypeScript, prefer `wrapQuery` around `query()`.
|
|
1209
1245
|
*
|
|
1210
|
-
*
|
|
1211
|
-
*
|
|
1246
|
+
* Pass `{ input }` (the prompt) to record a replayable root span — see
|
|
1247
|
+
* `wrapQuery`.
|
|
1212
1248
|
*/
|
|
1213
|
-
async *wrapResponse(stream) {
|
|
1249
|
+
async *wrapResponse(stream, opts) {
|
|
1250
|
+
this.setRootInput(opts);
|
|
1214
1251
|
yield* this.processStream(stream);
|
|
1215
1252
|
}
|
|
1216
1253
|
/**
|
|
1217
1254
|
* Wrap a `query()` async iterator to capture LLM turns.
|
|
1218
1255
|
*
|
|
1219
|
-
*
|
|
1220
|
-
*
|
|
1256
|
+
* Tool and subagent spans are captured separately via the hooks injected
|
|
1257
|
+
* by `instrumentOptions` into the `options` passed to `query()`.
|
|
1258
|
+
*
|
|
1259
|
+
* Pass `{ input }` — the prompt (or the serializable args that produced it)
|
|
1260
|
+
* — to make a handler-only run replayable: the handler records a root `agent`
|
|
1261
|
+
* span with that input, so `replay(key, fn)` can re-feed it. Omit it only
|
|
1262
|
+
* when an enclosing `withSpan` already supplies the replayable root.
|
|
1263
|
+
*
|
|
1264
|
+
* ```typescript
|
|
1265
|
+
* handler.wrapQuery(query({ prompt, options }), { input: prompt })
|
|
1266
|
+
* ```
|
|
1221
1267
|
*/
|
|
1222
|
-
async *wrapQuery(stream) {
|
|
1268
|
+
async *wrapQuery(stream, opts) {
|
|
1269
|
+
this.setRootInput(opts);
|
|
1223
1270
|
yield* this.processStream(stream);
|
|
1224
1271
|
}
|
|
1272
|
+
setRootInput(opts) {
|
|
1273
|
+
if (opts && opts.input !== void 0) {
|
|
1274
|
+
this.hasRootInput = true;
|
|
1275
|
+
this.rootInput = opts.input;
|
|
1276
|
+
} else {
|
|
1277
|
+
this.hasRootInput = false;
|
|
1278
|
+
this.rootInput = void 0;
|
|
1279
|
+
}
|
|
1280
|
+
this.rootOutput = void 0;
|
|
1281
|
+
}
|
|
1225
1282
|
// ── stream processing ────────────────────────────────────────
|
|
1226
1283
|
async *processStream(stream) {
|
|
1227
1284
|
try {
|
|
1285
|
+
this.maybeStartRootSpan();
|
|
1228
1286
|
for await (const message of stream) {
|
|
1229
1287
|
try {
|
|
1230
1288
|
this.processMessage(message);
|
|
@@ -1235,6 +1293,7 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1235
1293
|
} finally {
|
|
1236
1294
|
try {
|
|
1237
1295
|
this.flushLlmTurn();
|
|
1296
|
+
this.completeRootSpan();
|
|
1238
1297
|
this.sendTraceCompletion();
|
|
1239
1298
|
} catch {
|
|
1240
1299
|
}
|
|
@@ -1242,18 +1301,19 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1242
1301
|
}
|
|
1243
1302
|
}
|
|
1244
1303
|
processMessage(message) {
|
|
1245
|
-
const typeName = message.
|
|
1246
|
-
if (typeName === "
|
|
1304
|
+
const typeName = message.type;
|
|
1305
|
+
if (typeName === "assistant") {
|
|
1247
1306
|
this.handleAssistantMessage(message);
|
|
1248
|
-
} else if (typeName === "
|
|
1307
|
+
} else if (typeName === "user") {
|
|
1249
1308
|
this.handleUserMessage(message);
|
|
1250
|
-
} else if (typeName === "
|
|
1309
|
+
} else if (typeName === "result") {
|
|
1251
1310
|
this.handleResultMessage(message);
|
|
1252
1311
|
}
|
|
1253
1312
|
}
|
|
1254
1313
|
handleAssistantMessage(message) {
|
|
1255
1314
|
this.ensureTrace();
|
|
1256
|
-
const
|
|
1315
|
+
const inner = message.message ?? {};
|
|
1316
|
+
const messageId = inner.id ?? message.uuid;
|
|
1257
1317
|
if (messageId !== this.currentLlmMessageId) {
|
|
1258
1318
|
this.flushLlmTurn();
|
|
1259
1319
|
this.conversationHistory.push(...this.pendingMessages);
|
|
@@ -1261,26 +1321,27 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1261
1321
|
this.currentLlmSpanId = crypto.randomUUID();
|
|
1262
1322
|
this.currentLlmMessageId = messageId ?? null;
|
|
1263
1323
|
this.currentLlmContent = [];
|
|
1264
|
-
this.currentLlmModel =
|
|
1324
|
+
this.currentLlmModel = inner.model ?? null;
|
|
1265
1325
|
this.currentLlmUsage = {};
|
|
1266
1326
|
this.currentLlmStartedAt = nowIso();
|
|
1267
1327
|
this.currentLlmHistorySnapshot = [...this.conversationHistory];
|
|
1268
1328
|
}
|
|
1269
|
-
const content =
|
|
1329
|
+
const content = inner.content;
|
|
1270
1330
|
if (Array.isArray(content)) {
|
|
1271
1331
|
this.currentLlmContent.push(...extractContentBlocks(content));
|
|
1272
1332
|
}
|
|
1273
|
-
const usage = extractUsage(
|
|
1333
|
+
const usage = extractUsage(inner);
|
|
1274
1334
|
if (Object.keys(usage).length > 0) {
|
|
1275
1335
|
Object.assign(this.currentLlmUsage, usage);
|
|
1276
1336
|
}
|
|
1277
|
-
const model =
|
|
1337
|
+
const model = inner.model;
|
|
1278
1338
|
if (model) {
|
|
1279
1339
|
this.currentLlmModel = model;
|
|
1280
1340
|
}
|
|
1281
1341
|
}
|
|
1282
1342
|
handleUserMessage(message) {
|
|
1283
|
-
const
|
|
1343
|
+
const inner = message.message ?? {};
|
|
1344
|
+
const content = inner.content;
|
|
1284
1345
|
const toolUseResult = message.tool_use_result;
|
|
1285
1346
|
if (toolUseResult !== void 0) {
|
|
1286
1347
|
this.pendingMessages.push({
|
|
@@ -1297,6 +1358,10 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1297
1358
|
}
|
|
1298
1359
|
handleResultMessage(message) {
|
|
1299
1360
|
this.flushLlmTurn();
|
|
1361
|
+
if (message.result !== void 0) {
|
|
1362
|
+
this.rootOutput = message.result;
|
|
1363
|
+
}
|
|
1364
|
+
this.completeRootSpan();
|
|
1300
1365
|
const metadata = {};
|
|
1301
1366
|
for (const attr of [
|
|
1302
1367
|
"num_turns",
|
|
@@ -1360,6 +1425,9 @@ var BitfabClaudeAgentHandler = class {
|
|
|
1360
1425
|
this.runToSpan.clear();
|
|
1361
1426
|
this.traceId = null;
|
|
1362
1427
|
this.rootSpanId = null;
|
|
1428
|
+
this.hasRootInput = false;
|
|
1429
|
+
this.rootInput = void 0;
|
|
1430
|
+
this.rootOutput = void 0;
|
|
1363
1431
|
this.activeContext = null;
|
|
1364
1432
|
this.traceStartedAt = null;
|
|
1365
1433
|
this.conversationHistory = [];
|
|
@@ -2219,6 +2287,39 @@ var BitfabLangGraphCallbackHandler = class {
|
|
|
2219
2287
|
}
|
|
2220
2288
|
};
|
|
2221
2289
|
|
|
2290
|
+
// src/openaiAgentSdk.ts
|
|
2291
|
+
var BitfabOpenAIAgentHandler = class {
|
|
2292
|
+
constructor(config) {
|
|
2293
|
+
this.traceFunctionKey = config.traceFunctionKey;
|
|
2294
|
+
this.withSpanFn = config.withSpan;
|
|
2295
|
+
}
|
|
2296
|
+
async wrapRun(agent, input, options) {
|
|
2297
|
+
const { run } = await import("@openai/agents");
|
|
2298
|
+
const isStreaming = options?.stream === true;
|
|
2299
|
+
const finalize = async (result) => {
|
|
2300
|
+
const res = result;
|
|
2301
|
+
if (isStreaming && res?.completed) {
|
|
2302
|
+
try {
|
|
2303
|
+
await res.completed;
|
|
2304
|
+
} catch {
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
return res?.finalOutput;
|
|
2308
|
+
};
|
|
2309
|
+
const options_ = { type: "agent", finalize };
|
|
2310
|
+
const traced = this.withSpanFn(
|
|
2311
|
+
this.traceFunctionKey,
|
|
2312
|
+
options_,
|
|
2313
|
+
(agentInput) => run(
|
|
2314
|
+
agent,
|
|
2315
|
+
agentInput,
|
|
2316
|
+
options
|
|
2317
|
+
)
|
|
2318
|
+
);
|
|
2319
|
+
return traced(input);
|
|
2320
|
+
}
|
|
2321
|
+
};
|
|
2322
|
+
|
|
2222
2323
|
// src/client.ts
|
|
2223
2324
|
init_replayContext();
|
|
2224
2325
|
|
|
@@ -2912,6 +3013,34 @@ var Bitfab = class {
|
|
|
2912
3013
|
}
|
|
2913
3014
|
});
|
|
2914
3015
|
}
|
|
3016
|
+
/**
|
|
3017
|
+
* Get an OpenAI Agents SDK handler that records a replayable root span.
|
|
3018
|
+
*
|
|
3019
|
+
* The processor from {@link getOpenAiTracingProcessor} captures everything
|
|
3020
|
+
* inside a run (LLM calls, tools, handoffs) but never sees the caller's
|
|
3021
|
+
* input, so a processor-only run records an empty-input root and is not
|
|
3022
|
+
* replayable. This handler's `wrapRun` is a drop-in for `run()` that opens a
|
|
3023
|
+
* `withSpan` root carrying the input and final output; the processor's spans
|
|
3024
|
+
* nest beneath it. Register the processor once at startup, then call
|
|
3025
|
+
* `handler.wrapRun(agent, input)` in place of `run(agent, input)`.
|
|
3026
|
+
*
|
|
3027
|
+
* ```typescript
|
|
3028
|
+
* import { addTraceProcessor, Agent, run } from "@openai/agents";
|
|
3029
|
+
*
|
|
3030
|
+
* addTraceProcessor(client.getOpenAiTracingProcessor());
|
|
3031
|
+
* const handler = client.getOpenAiAgentHandler("research-topic");
|
|
3032
|
+
* const result = await handler.wrapRun(agent, "Find X");
|
|
3033
|
+
* ```
|
|
3034
|
+
*
|
|
3035
|
+
* @param traceFunctionKey - Groups traces under this key in Bitfab
|
|
3036
|
+
* @returns A BitfabOpenAIAgentHandler configured for this client
|
|
3037
|
+
*/
|
|
3038
|
+
getOpenAiAgentHandler(traceFunctionKey) {
|
|
3039
|
+
return new BitfabOpenAIAgentHandler({
|
|
3040
|
+
traceFunctionKey,
|
|
3041
|
+
withSpan: this.withSpan.bind(this)
|
|
3042
|
+
});
|
|
3043
|
+
}
|
|
2915
3044
|
/**
|
|
2916
3045
|
* Get a LangGraph/LangChain callback handler for tracing.
|
|
2917
3046
|
*
|
|
@@ -2965,14 +3094,15 @@ var Bitfab = class {
|
|
|
2965
3094
|
* execution as Bitfab spans with proper parent-child hierarchy.
|
|
2966
3095
|
*
|
|
2967
3096
|
* ```typescript
|
|
3097
|
+
* import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
3098
|
+
*
|
|
2968
3099
|
* const handler = client.getClaudeAgentHandler("my-agent");
|
|
2969
3100
|
* const options = handler.instrumentOptions({
|
|
2970
3101
|
* model: "claude-sonnet-4-5-...",
|
|
2971
3102
|
* });
|
|
2972
|
-
* const
|
|
2973
|
-
*
|
|
2974
|
-
*
|
|
2975
|
-
* for await (const msg of handler.wrapResponse(sdkClient.receiveResponse())) {
|
|
3103
|
+
* for await (const msg of handler.wrapQuery(
|
|
3104
|
+
* query({ prompt: "Do something", options })
|
|
3105
|
+
* )) {
|
|
2976
3106
|
* // process messages
|
|
2977
3107
|
* }
|
|
2978
3108
|
* ```
|
|
@@ -3665,6 +3795,7 @@ assertAsyncStorageRegistered();
|
|
|
3665
3795
|
BitfabFunction,
|
|
3666
3796
|
BitfabLangChainCallbackHandler,
|
|
3667
3797
|
BitfabLangGraphCallbackHandler,
|
|
3798
|
+
BitfabOpenAIAgentHandler,
|
|
3668
3799
|
BitfabOpenAITracingProcessor,
|
|
3669
3800
|
DEFAULT_SERVICE_URL,
|
|
3670
3801
|
ReplayEnvironment,
|