@bitfab/sdk 0.75.0 → 0.76.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 (58) hide show
  1. package/dist/{autoTrace-kHOBg49M.js → autoTrace-BgN0zCQf.js} +565 -69
  2. package/dist/autoTrace-BgN0zCQf.js.map +1 -0
  3. package/dist/{autoTrace-DPWV1Xzr.cjs → autoTrace-pZKu5Nk2.cjs} +612 -68
  4. package/dist/autoTrace-pZKu5Nk2.cjs.map +1 -0
  5. package/dist/autoTrace.cjs +2 -1
  6. package/dist/autoTrace.d.cts +20 -24
  7. package/dist/autoTrace.d.ts +20 -24
  8. package/dist/autoTrace.js +1 -1
  9. package/dist/{babelPlugin-C0Im6AZ2.cjs → babelPlugin-BpEeVvk4.cjs} +73 -25
  10. package/dist/babelPlugin-BpEeVvk4.cjs.map +1 -0
  11. package/dist/{babelPlugin-hS2Hb2vt.js → babelPlugin-PgjdBuQe.js} +73 -25
  12. package/dist/babelPlugin-PgjdBuQe.js.map +1 -0
  13. package/dist/{http-Cotx6kLL.js → http-DS1QjBvx.js} +3 -3
  14. package/dist/{http-Cotx6kLL.js.map → http-DS1QjBvx.js.map} +1 -1
  15. package/dist/{http-BkL24D7v.cjs → http-ykHGNcju.cjs} +3 -3
  16. package/dist/{http-BkL24D7v.cjs.map → http-ykHGNcju.cjs.map} +1 -1
  17. package/dist/{index-V6ECPulQ.d.cts → index-BYv4DSsY.d.cts} +286 -17
  18. package/dist/{index-V6ECPulQ.d.ts → index-BYv4DSsY.d.ts} +286 -17
  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-DdE8cNOX.js → registryCommand-D1VgfJjC.js} +341 -46
  28. package/dist/registryCommand-D1VgfJjC.js.map +1 -0
  29. package/dist/replayCli.js +1 -1
  30. package/dist/seedCli.js +1 -1
  31. package/dist/{src-CrV0INwT.js → src-BJjbR3Nq.js} +72 -34
  32. package/dist/src-BJjbR3Nq.js.map +1 -0
  33. package/dist/{src-BJ5a-chk.cjs → src-CLkegn-P.cjs} +78 -40
  34. package/dist/src-CLkegn-P.cjs.map +1 -0
  35. package/dist/transform/babel.cjs +1 -1
  36. package/dist/transform/babel.d.cts +2 -9
  37. package/dist/transform/babel.d.ts +2 -9
  38. package/dist/transform/babel.js +1 -1
  39. package/dist/transform/loaderRuntime.cjs +2 -2
  40. package/dist/transform/loaderRuntime.js +2 -2
  41. package/dist/transform/nodeLoader.js +72 -24
  42. package/dist/transform/nodeLoader.js.map +1 -1
  43. package/dist/transform/swc.cjs +1 -1
  44. package/dist/transform/swc.js +1 -1
  45. package/dist/transform/unplugin.cjs +2 -2
  46. package/dist/transform/unplugin.js +2 -2
  47. package/dist/{transform-BL1fJW-C.js → transform-BhazCKOg.js} +2 -2
  48. package/dist/{transform-BL1fJW-C.js.map → transform-BhazCKOg.js.map} +1 -1
  49. package/dist/{transform-C4H7TKW-.cjs → transform-Cdg7CSbP.cjs} +2 -2
  50. package/dist/{transform-C4H7TKW-.cjs.map → transform-Cdg7CSbP.cjs.map} +1 -1
  51. package/package.json +1 -1
  52. package/dist/autoTrace-DPWV1Xzr.cjs.map +0 -1
  53. package/dist/autoTrace-kHOBg49M.js.map +0 -1
  54. package/dist/babelPlugin-C0Im6AZ2.cjs.map +0 -1
  55. package/dist/babelPlugin-hS2Hb2vt.js.map +0 -1
  56. package/dist/registryCommand-DdE8cNOX.js.map +0 -1
  57. package/dist/src-BJ5a-chk.cjs.map +0 -1
  58. package/dist/src-CrV0INwT.js.map +0 -1
@@ -101,6 +101,32 @@ function unscopedRuns() {
101
101
  shared[UNSCOPED_RUNS_SYMBOL] = created;
102
102
  return created;
103
103
  }
104
+ function scopedIterator(runStorage, iterator) {
105
+ const scope = { recordedByHandler: false };
106
+ const inScope = (step) => runStorage.run(scope, step);
107
+ return {
108
+ next: (...args) => inScope(() => iterator.next(...args)),
109
+ return: (value) => inScope(() => iterator.return === void 0 ? Promise.resolve({
110
+ done: true,
111
+ value
112
+ }) : iterator.return(value)),
113
+ throw: (error) => inScope(() => iterator.throw === void 0 ? Promise.reject(error) : iterator.throw(error)),
114
+ [Symbol.asyncIterator]() {
115
+ return this;
116
+ }
117
+ };
118
+ }
119
+ function scopeStreamIterator(prototype) {
120
+ const original = prototype._streamIterator;
121
+ if (typeof original !== "function" || original[SCOPED_GENERATE_SYMBOL]) return;
122
+ const scoped = function(...args) {
123
+ const runStorage = storage();
124
+ const iterator = original.apply(this, args);
125
+ return runStorage ? scopedIterator(runStorage, iterator) : iterator;
126
+ };
127
+ scoped[SCOPED_GENERATE_SYMBOL] = true;
128
+ prototype._streamIterator = scoped;
129
+ }
104
130
  function scopeGenerate(prototype) {
105
131
  const original = prototype.generate;
106
132
  if (typeof original !== "function" || original[SCOPED_GENERATE_SYMBOL]) return;
@@ -115,7 +141,10 @@ function scopeGenerate(prototype) {
115
141
  async function scopeModelClass(specifierParts, name) {
116
142
  try {
117
143
  const modelClass = (await importOptionalPeer(specifierParts))[name];
118
- if (modelClass?.prototype) scopeGenerate(modelClass.prototype);
144
+ if (modelClass?.prototype) {
145
+ scopeGenerate(modelClass.prototype);
146
+ scopeStreamIterator(modelClass.prototype);
147
+ }
119
148
  } catch {}
120
149
  }
121
150
  function installLangChainRunScopes() {
@@ -202,9 +231,25 @@ function openAiAgentsModelCallOpen() {
202
231
  return currentOpenAiAgentsSpans().some((span) => typeof span.traceId === "string" && typeof span.spanId === "string" && state.bitfabTraceIds.has(span.traceId) && MODEL_CALL_SPAN_TYPES.has(String(span.spanData?.type)) && !state.endedSpanIds.get(span.traceId)?.has(span.spanId));
203
232
  }
204
233
  //#endregion
234
+ //#region src/streamFinalizationError.ts
235
+ var StreamFinalizationError = class extends Error {
236
+ constructor(message, output) {
237
+ super(message);
238
+ this.output = output;
239
+ this.name = "StreamFinalizationError";
240
+ }
241
+ };
242
+ //#endregion
205
243
  //#region src/clientCalls.ts
206
244
  const OPENROUTER_HOSTNAME = "openrouter.ai";
207
245
  const CLIENT_CALL_WATCH_STORAGE_SYMBOL = Symbol.for("bitfab.clientCallWatchStorage");
246
+ const RESPONSE_DONE_EVENTS = [
247
+ "response.completed",
248
+ "response.incomplete",
249
+ "response.failed"
250
+ ];
251
+ const TRANSCRIPT_DONE_EVENT = "transcript.text.done";
252
+ const STREAM_END_EVENT = "end";
208
253
  const responsesRecordedByAutoTrace = /* @__PURE__ */ new WeakSet();
209
254
  function isRecord(value) {
210
255
  return typeof value === "object" && value !== null;
@@ -219,11 +264,8 @@ function numberField(value, name) {
219
264
  function nonEmptyString(value) {
220
265
  return typeof value === "string" && value !== "" ? value : void 0;
221
266
  }
222
- function presentFields(base, values, durationMs) {
223
- const context = { ...base };
224
- for (const [key, value] of Object.entries(values)) if (value !== void 0) context[key] = value;
225
- context.durationMs = durationMs;
226
- return context;
267
+ function presentFields(values) {
268
+ return Object.fromEntries(Object.entries(values).filter(([, value]) => value !== void 0));
227
269
  }
228
270
  function sumOfPresent(values) {
229
271
  const present = values.filter((value) => value !== void 0);
@@ -242,9 +284,41 @@ function roleEntries(items) {
242
284
  }];
243
285
  });
244
286
  }
287
+ function isNil(value) {
288
+ return value === void 0 || value === null;
289
+ }
290
+ function isBlank(content) {
291
+ return isNil(content) || content === "" || Array.isArray(content) && content.length === 0;
292
+ }
293
+ function systemEntry(content) {
294
+ return isBlank(content) ? [] : [{
295
+ role: "system",
296
+ content: textOf(content)
297
+ }];
298
+ }
299
+ function userEntries(content) {
300
+ if (isBlank(content)) return [];
301
+ if (Array.isArray(content) && content.every((item) => typeof item === "string")) return content.map((item) => ({
302
+ role: "user",
303
+ content: item
304
+ }));
305
+ return [{
306
+ role: "user",
307
+ content: textOf(content)
308
+ }];
309
+ }
245
310
  function renderedPrompt(entries) {
246
311
  return entries.length > 0 ? JSON.stringify(entries) : void 0;
247
312
  }
313
+ function modelOf(body, response) {
314
+ return nonEmptyString(field(response, "model")) ?? nonEmptyString(field(body, "model"));
315
+ }
316
+ function lastMatching(items, matches) {
317
+ for (let index = items.length - 1; index >= 0; index -= 1) if (matches(items[index])) return items[index];
318
+ }
319
+ function lastWith(events, name) {
320
+ return lastMatching(events, (event) => !isNil(field(event, name)));
321
+ }
248
322
  function clientOf(receiver) {
249
323
  try {
250
324
  return field(receiver, "_client");
@@ -271,51 +345,143 @@ function isOpenRouterBaseUrl(baseUrl) {
271
345
  return false;
272
346
  }
273
347
  }
274
- function isOpenRouterCompletions(receiver) {
348
+ function isOpenRouterResource(receiver) {
275
349
  try {
276
350
  return isOpenRouterBaseUrl(field(clientOf(receiver), "baseURL"));
277
351
  } catch {
278
352
  return false;
279
353
  }
280
354
  }
281
- function isAnthropicMessages(receiver) {
282
- return typeof clientClassStatic(receiver, "HUMAN_PROMPT") === "string";
355
+ function isAnthropicResource(receiver) {
356
+ return typeof clientClassStatic(receiver, "AnthropicError") === "function" || typeof clientClassStatic(receiver, "HUMAN_PROMPT") === "string";
283
357
  }
284
- function isOpenAIResponses(receiver) {
358
+ function isOpenAIResource(receiver) {
285
359
  return typeof clientClassStatic(receiver, "OpenAI") === "function";
286
360
  }
287
- function isStreamingRequest(body) {
288
- return field(body, "stream") === true;
361
+ function isGeminiModels(receiver) {
362
+ try {
363
+ return isRecord(receiver) && isRecord(receiver.apiClient) && typeof receiver.generateContent === "function" && typeof receiver.generateContentStream === "function";
364
+ } catch {
365
+ return false;
366
+ }
367
+ }
368
+ function isChatCompletion(response) {
369
+ return isRecord(response) && Array.isArray(response.choices);
289
370
  }
290
- function openRouterPrompt(body) {
371
+ function chatCompletionPrompt(body) {
291
372
  const messages = field(body, "messages");
292
373
  return Array.isArray(messages) ? renderedPrompt(roleEntries(messages)) : void 0;
293
374
  }
294
- function openRouterContext(body, response, durationMs) {
375
+ function chatCompletionUsage(body, response) {
295
376
  const usage = field(response, "usage");
296
- return presentFields({ provider: "openrouter" }, {
297
- model: nonEmptyString(field(response, "model")) ?? nonEmptyString(field(body, "model")),
377
+ return {
378
+ model: modelOf(body, response),
298
379
  upstreamProvider: nonEmptyString(field(response, "provider")),
299
380
  inputTokens: numberField(usage, "prompt_tokens"),
300
381
  outputTokens: numberField(usage, "completion_tokens"),
301
382
  cachedInputTokens: numberField(field(usage, "prompt_tokens_details"), "cached_tokens"),
302
383
  reasoningTokens: numberField(field(usage, "completion_tokens_details"), "reasoning_tokens"),
303
384
  costUsd: numberField(usage, "cost")
304
- }, durationMs);
385
+ };
386
+ }
387
+ function chatToolCalls(chunks) {
388
+ const slots = /* @__PURE__ */ new Map();
389
+ for (const chunk of chunks) {
390
+ const toolCalls = field(field(firstChoice(chunk), "delta"), "tool_calls");
391
+ if (!Array.isArray(toolCalls)) continue;
392
+ for (const toolCall of toolCalls) {
393
+ const index = numberField(toolCall, "index") ?? 0;
394
+ const slot = slots.get(index) ?? { arguments: "" };
395
+ const fn = field(toolCall, "function");
396
+ const name = nonEmptyString(field(fn, "name"));
397
+ const args = nonEmptyString(field(fn, "arguments"));
398
+ slots.set(index, {
399
+ name: name ?? slot.name,
400
+ arguments: slot.arguments + (args ?? "")
401
+ });
402
+ }
403
+ }
404
+ return [...slots.entries()].sort(([left], [right]) => left - right).map(([, slot]) => ({
405
+ type: "function",
406
+ function: {
407
+ name: slot.name,
408
+ arguments: slot.arguments
409
+ }
410
+ }));
411
+ }
412
+ function firstChoice(chunk) {
413
+ const choices = field(chunk, "choices");
414
+ return Array.isArray(choices) ? choices[0] : void 0;
415
+ }
416
+ function chatStreamSummary(chunks) {
417
+ if (chunks.length === 0) return;
418
+ const last = lastWith(chunks, "usage") ?? chunks[chunks.length - 1];
419
+ const text = chunks.map((chunk) => field(field(firstChoice(chunk), "delta"), "content")).filter((content) => typeof content === "string").join("");
420
+ const finishReason = lastMatching(chunks.map((chunk) => field(firstChoice(chunk), "finish_reason")), (reason) => typeof reason === "string");
421
+ const toolCalls = chatToolCalls(chunks);
422
+ return {
423
+ object: "chat.completion",
424
+ model: field(last, "model"),
425
+ provider: field(last, "provider"),
426
+ choices: [{
427
+ index: 0,
428
+ message: {
429
+ role: "assistant",
430
+ content: text,
431
+ ...toolCalls.length > 0 && { tool_calls: toolCalls }
432
+ },
433
+ finish_reason: finishReason ?? null
434
+ }],
435
+ usage: field(last, "usage")
436
+ };
437
+ }
438
+ function isEmbeddingList(response) {
439
+ return field(response, "object") === "list" && Array.isArray(field(response, "data"));
440
+ }
441
+ function embeddingPrompt(body) {
442
+ return renderedPrompt(userEntries(field(body, "input")));
443
+ }
444
+ function embeddingUsage(body, response) {
445
+ const usage = field(response, "usage");
446
+ const inputTokens = numberField(usage, "prompt_tokens");
447
+ return {
448
+ model: modelOf(body, response),
449
+ upstreamProvider: nonEmptyString(field(response, "provider")),
450
+ inputTokens,
451
+ outputTokens: inputTokens === void 0 ? void 0 : 0,
452
+ costUsd: numberField(usage, "cost")
453
+ };
454
+ }
455
+ function isTranscription(response) {
456
+ return typeof field(response, "text") === "string";
457
+ }
458
+ function transcriptionPrompt(body) {
459
+ return renderedPrompt(userEntries(field(body, "prompt")));
460
+ }
461
+ function transcriptionUsage(body, response) {
462
+ const usage = field(response, "usage");
463
+ return {
464
+ model: modelOf(body, response),
465
+ inputTokens: numberField(usage, "input_tokens"),
466
+ outputTokens: numberField(usage, "output_tokens"),
467
+ audioSeconds: numberField(usage, "seconds")
468
+ };
469
+ }
470
+ function transcriptionStreamSummary(events) {
471
+ return lastMatching(events, (event) => field(event, "type") === TRANSCRIPT_DONE_EVENT);
472
+ }
473
+ function isAnthropicMessage(response) {
474
+ return field(response, "type") === "message" && Array.isArray(field(response, "content"));
305
475
  }
306
476
  function anthropicPrompt(body) {
307
- const system = field(body, "system");
308
477
  const messages = field(body, "messages");
309
- return renderedPrompt([...system === void 0 || system === null ? [] : [{
310
- role: "system",
311
- content: textOf(system)
312
- }], ...Array.isArray(messages) ? roleEntries(messages) : []]);
478
+ return renderedPrompt([...systemEntry(field(body, "system")), ...Array.isArray(messages) ? roleEntries(messages) : []]);
313
479
  }
314
- function anthropicContext(body, response, durationMs) {
480
+ function anthropicUsage(body, response) {
315
481
  const usage = field(response, "usage");
316
482
  const cacheRead = numberField(usage, "cache_read_input_tokens");
317
- return presentFields({ provider: "anthropic" }, {
318
- model: nonEmptyString(field(response, "model")) ?? nonEmptyString(field(body, "model")),
483
+ return {
484
+ model: modelOf(body, response),
319
485
  inputTokens: sumOfPresent([
320
486
  numberField(usage, "input_tokens"),
321
487
  cacheRead,
@@ -323,16 +489,48 @@ function anthropicContext(body, response, durationMs) {
323
489
  ]),
324
490
  outputTokens: numberField(usage, "output_tokens"),
325
491
  cachedInputTokens: cacheRead
326
- }, durationMs);
492
+ };
493
+ }
494
+ function anthropicStreamSummary(events) {
495
+ const message = field(events.find((event) => field(event, "type") === "message_start"), "message");
496
+ if (!isRecord(message)) return;
497
+ let usage = { ...isRecord(message.usage) ? message.usage : {} };
498
+ let stopReason = null;
499
+ const text = [];
500
+ for (const event of events) {
501
+ const type = field(event, "type");
502
+ if (type === "message_delta") {
503
+ const deltaUsage = field(event, "usage");
504
+ usage = {
505
+ ...usage,
506
+ ...isRecord(deltaUsage) ? presentFields(deltaUsage) : {}
507
+ };
508
+ stopReason = field(field(event, "delta"), "stop_reason") ?? stopReason;
509
+ }
510
+ if (type === "content_block_delta") {
511
+ const deltaText = field(field(event, "delta"), "text");
512
+ if (typeof deltaText === "string") text.push(deltaText);
513
+ }
514
+ }
515
+ return {
516
+ type: "message",
517
+ role: "assistant",
518
+ model: message.model,
519
+ content: [{
520
+ type: "text",
521
+ text: text.join("")
522
+ }],
523
+ stop_reason: stopReason,
524
+ usage
525
+ };
526
+ }
527
+ function isOpenAIResponse(response) {
528
+ return field(response, "object") === "response";
327
529
  }
328
530
  function openAIResponsesPrompt(body) {
329
- const instructions = field(body, "instructions");
330
531
  const input = field(body, "input");
331
532
  return renderedPrompt([
332
- ...typeof instructions === "string" ? [{
333
- role: "system",
334
- content: instructions
335
- }] : [],
533
+ ...systemEntry(field(body, "instructions")),
336
534
  ...typeof input === "string" ? [{
337
535
  role: "user",
338
536
  content: input
@@ -340,54 +538,201 @@ function openAIResponsesPrompt(body) {
340
538
  ...Array.isArray(input) ? roleEntries(input) : []
341
539
  ]);
342
540
  }
343
- function openAIResponsesContext(body, response, durationMs) {
541
+ function openAIResponsesUsage(body, response) {
344
542
  const usage = field(response, "usage");
345
- return presentFields({ provider: "openai" }, {
346
- model: nonEmptyString(field(response, "model")) ?? nonEmptyString(field(body, "model")),
543
+ return {
544
+ model: modelOf(body, response),
347
545
  inputTokens: numberField(usage, "input_tokens"),
348
546
  outputTokens: numberField(usage, "output_tokens"),
349
547
  cachedInputTokens: numberField(field(usage, "input_tokens_details"), "cached_tokens"),
350
548
  reasoningTokens: numberField(field(usage, "output_tokens_details"), "reasoning_tokens"),
351
549
  costUsd: numberField(usage, "cost")
352
- }, durationMs);
550
+ };
551
+ }
552
+ function openAIResponsesStreamSummary(events) {
553
+ return field(lastMatching(events, (event) => RESPONSE_DONE_EVENTS.some((type) => field(event, "type") === type)), "response");
554
+ }
555
+ function isGeminiResponse(response) {
556
+ return field(response, "usageMetadata") !== void 0 || Array.isArray(field(response, "candidates"));
557
+ }
558
+ function geminiContentText(content) {
559
+ if (isNil(content)) return;
560
+ if (typeof content === "string") return content;
561
+ const parts = field(content, "parts");
562
+ if (Array.isArray(parts)) {
563
+ const texts = parts.map((part) => field(part, "text"));
564
+ if (texts.every((text) => typeof text === "string")) return texts.join("");
565
+ }
566
+ const text = field(content, "text");
567
+ return typeof text === "string" ? text : textOf(content);
568
+ }
569
+ function geminiEntries(contents) {
570
+ if (isNil(contents)) return [];
571
+ return (Array.isArray(contents) ? contents : [contents]).map((item) => ({
572
+ role: nonEmptyString(field(item, "role")) ?? "user",
573
+ content: geminiContentText(item) ?? ""
574
+ }));
575
+ }
576
+ function geminiPrompt(body) {
577
+ return renderedPrompt([...systemEntry(geminiContentText(field(field(body, "config"), "systemInstruction"))), ...geminiEntries(field(body, "contents"))]);
578
+ }
579
+ function geminiModel(body, response) {
580
+ const model = nonEmptyString(field(response, "modelVersion")) ?? nonEmptyString(field(body, "model"));
581
+ return model === void 0 ? void 0 : model.slice(model.lastIndexOf("/") + 1);
582
+ }
583
+ function geminiUsage(body, response) {
584
+ const usage = field(response, "usageMetadata");
585
+ const thoughts = numberField(usage, "thoughtsTokenCount");
586
+ return {
587
+ model: geminiModel(body, response),
588
+ inputTokens: sumOfPresent([numberField(usage, "promptTokenCount"), numberField(usage, "toolUsePromptTokenCount")]),
589
+ outputTokens: sumOfPresent([numberField(usage, "candidatesTokenCount"), thoughts]),
590
+ cachedInputTokens: numberField(usage, "cachedContentTokenCount"),
591
+ reasoningTokens: thoughts
592
+ };
593
+ }
594
+ function geminiChunkText(chunk) {
595
+ const candidates = field(chunk, "candidates");
596
+ return Array.isArray(candidates) ? geminiContentText(field(candidates[0], "content")) ?? "" : "";
597
+ }
598
+ function geminiStreamSummary(chunks) {
599
+ if (chunks.length === 0) return;
600
+ const last = lastWith(chunks, "usageMetadata") ?? chunks[chunks.length - 1];
601
+ return {
602
+ modelVersion: field(last, "modelVersion"),
603
+ text: chunks.map(geminiChunkText).join(""),
604
+ usageMetadata: field(last, "usageMetadata")
605
+ };
353
606
  }
354
607
  const OPENROUTER = {
355
608
  key: "openrouter",
609
+ provider: "openrouter",
356
610
  library: "openai",
357
- matchesReceiver: isOpenRouterCompletions,
358
- isResponse: (response) => isRecord(response) && Array.isArray(response.choices),
359
- prompt: openRouterPrompt,
360
- context: openRouterContext
611
+ endpoint: "chat.completions",
612
+ methods: ["create", "parse"],
613
+ streamMethods: ["stream"],
614
+ streamEvents: ["chunk"],
615
+ spanMethods: { stream: "create" },
616
+ matchesReceiver: isOpenRouterResource,
617
+ isResponse: isChatCompletion,
618
+ prompt: chatCompletionPrompt,
619
+ usage: chatCompletionUsage,
620
+ streamSummary: chatStreamSummary
621
+ };
622
+ const OPENAI_CHAT = {
623
+ ...OPENROUTER,
624
+ key: "openai-chat",
625
+ provider: "openai",
626
+ matchesReceiver: isOpenAIResource
627
+ };
628
+ const OPENROUTER_EMBEDDINGS = {
629
+ key: "openrouter-embeddings",
630
+ provider: "openrouter",
631
+ library: "openai",
632
+ endpoint: "embeddings",
633
+ methods: ["create"],
634
+ streamMethods: [],
635
+ streamEvents: [],
636
+ matchesReceiver: isOpenRouterResource,
637
+ isResponse: isEmbeddingList,
638
+ prompt: embeddingPrompt,
639
+ usage: embeddingUsage
640
+ };
641
+ const OPENAI_EMBEDDINGS = {
642
+ ...OPENROUTER_EMBEDDINGS,
643
+ key: "openai-embeddings",
644
+ provider: "openai",
645
+ matchesReceiver: isOpenAIResource
646
+ };
647
+ const OPENAI_TRANSCRIPTIONS = {
648
+ key: "openai-transcriptions",
649
+ provider: "openai",
650
+ library: "openai",
651
+ endpoint: "audio.transcriptions",
652
+ methods: ["create"],
653
+ streamMethods: [],
654
+ streamEvents: [],
655
+ matchesReceiver: isOpenAIResource,
656
+ isResponse: isTranscription,
657
+ prompt: transcriptionPrompt,
658
+ usage: transcriptionUsage,
659
+ streamSummary: transcriptionStreamSummary
361
660
  };
362
661
  const ANTHROPIC = {
363
662
  key: "anthropic",
663
+ provider: "anthropic",
364
664
  library: "@anthropic-ai/sdk",
365
- matchesReceiver: isAnthropicMessages,
366
- isResponse: (response) => field(response, "type") === "message" && Array.isArray(field(response, "content")),
665
+ endpoint: "messages",
666
+ methods: ["create", "parse"],
667
+ streamMethods: ["stream"],
668
+ streamEvents: ["streamEvent"],
669
+ matchesReceiver: isAnthropicResource,
670
+ isResponse: isAnthropicMessage,
367
671
  prompt: anthropicPrompt,
368
- context: anthropicContext
672
+ usage: anthropicUsage,
673
+ streamSummary: anthropicStreamSummary
369
674
  };
370
675
  const OPENAI_RESPONSES = {
371
676
  key: "openai-responses",
677
+ provider: "openai",
372
678
  library: "openai",
373
- matchesReceiver: isOpenAIResponses,
374
- isResponse: (response) => field(response, "object") === "response",
679
+ endpoint: "responses",
680
+ methods: ["create", "parse"],
681
+ streamMethods: ["stream"],
682
+ streamEvents: RESPONSE_DONE_EVENTS,
683
+ spanMethods: { stream: "create" },
684
+ matchesReceiver: isOpenAIResource,
685
+ isResponse: isOpenAIResponse,
375
686
  prompt: openAIResponsesPrompt,
376
- context: openAIResponsesContext
687
+ usage: openAIResponsesUsage,
688
+ streamSummary: openAIResponsesStreamSummary
689
+ };
690
+ const GEMINI = {
691
+ key: "gemini",
692
+ provider: "gemini",
693
+ library: "@google/genai",
694
+ endpoint: "models",
695
+ methods: ["generateContent"],
696
+ streamMethods: ["generateContentStream"],
697
+ streamEvents: [],
698
+ matchesReceiver: isGeminiModels,
699
+ isResponse: isGeminiResponse,
700
+ prompt: geminiPrompt,
701
+ usage: geminiUsage,
702
+ streamSummary: geminiStreamSummary
377
703
  };
378
- const CLIENT_CALL_PROVIDERS = new Map([
704
+ const CLIENT_CALL_PROVIDERS = [
379
705
  OPENROUTER,
706
+ OPENAI_CHAT,
707
+ OPENROUTER_EMBEDDINGS,
708
+ OPENAI_EMBEDDINGS,
709
+ OPENAI_TRANSCRIPTIONS,
380
710
  ANTHROPIC,
381
- OPENAI_RESPONSES
382
- ].map((provider) => [provider.key, provider]));
711
+ OPENAI_RESPONSES,
712
+ GEMINI
713
+ ];
714
+ const CLIENT_CALL_PROVIDERS_BY_KEY = new Map(CLIENT_CALL_PROVIDERS.map((provider) => [provider.key, provider]));
383
715
  function clientCallProvider(key) {
384
- return key === void 0 ? void 0 : CLIENT_CALL_PROVIDERS.get(key);
716
+ return key === void 0 ? void 0 : CLIENT_CALL_PROVIDERS_BY_KEY.get(key);
717
+ }
718
+ function providerForClientCall(endpoint, method, receiver) {
719
+ return CLIENT_CALL_PROVIDERS.find((provider) => provider.endpoint === endpoint && (provider.methods.includes(method) || provider.streamMethods.includes(method)) && provider.matchesReceiver(receiver));
720
+ }
721
+ function clientCallStreams(provider, method, body) {
722
+ return provider.streamMethods.includes(method) || field(body, "stream") === true;
723
+ }
724
+ function clientCallContext(provider, body, response, durationMs) {
725
+ return {
726
+ provider: provider.provider,
727
+ ...presentFields(provider.usage(body, response)),
728
+ durationMs
729
+ };
385
730
  }
386
731
  function recordClientCall(provider, span, body, response, durationMs) {
387
732
  try {
388
733
  const prompt = provider.prompt(body);
389
734
  if (prompt !== void 0) span.setPrompt(prompt);
390
- span.addContext(provider.context(body, response, durationMs));
735
+ span.addContext(clientCallContext(provider, body, response, durationMs));
391
736
  } catch {}
392
737
  }
393
738
  let clientCallWatchStorage = null;
@@ -413,6 +758,12 @@ function watchClientCall(fn) {
413
758
  function markEnclosingWatches(watch) {
414
759
  for (let current = watch.parent; current; current = current.parent) current.recorded = true;
415
760
  }
761
+ function markCurrentWatches() {
762
+ markEnclosingWatches({
763
+ recorded: true,
764
+ parent: watchStorage()?.getStore() ?? null
765
+ });
766
+ }
416
767
  function frameworkRecordsClientCall() {
417
768
  return langChainHandlerRecordsCall() || openAiAgentsModelCallOpen();
418
769
  }
@@ -442,6 +793,147 @@ function recordAutoTracedClientCall(provider, invokeFn, body, span) {
442
793
  settle(result);
443
794
  return result;
444
795
  }
796
+ function isThenable(value) {
797
+ return isRecord(value) && typeof value.then === "function";
798
+ }
799
+ function isIteratorStream(value) {
800
+ return isRecord(value) && typeof value.iterator === "function";
801
+ }
802
+ function isEventStream(value) {
803
+ return isRecord(value) && typeof value.on === "function";
804
+ }
805
+ function isAsyncIterator(value) {
806
+ return isRecord(value) && typeof value.next === "function";
807
+ }
808
+ function errorText(error) {
809
+ return error instanceof Error ? error.message : String(error);
810
+ }
811
+ const streamRecordingsByCall = /* @__PURE__ */ new WeakMap();
812
+ const droppedStreams = typeof FinalizationRegistry === "function" ? new FinalizationRegistry((recording) => recording.finish(void 0)) : void 0;
813
+ function sharedClientCallStreamRecording(call, provider, body) {
814
+ let recording = streamRecordingsByCall.get(call);
815
+ if (recording === void 0) {
816
+ recording = new ClientCallStreamRecording(provider, body);
817
+ streamRecordingsByCall.set(call, recording);
818
+ }
819
+ return recording;
820
+ }
821
+ var ClientCallStreamRecording = class {
822
+ constructor(provider, body) {
823
+ this.provider = provider;
824
+ this.body = body;
825
+ this.events = [];
826
+ this.startedAt = Date.now();
827
+ this.finished = false;
828
+ this.observing = false;
829
+ this.resolveDone = () => {};
830
+ this.rejectDone = () => {};
831
+ this.done = new Promise((resolve, reject) => {
832
+ this.resolveDone = resolve;
833
+ this.rejectDone = reject;
834
+ });
835
+ this.done.catch(() => {});
836
+ }
837
+ start(span, invokeFn) {
838
+ this.span ?? (this.span = span);
839
+ markCurrentWatches();
840
+ let result;
841
+ try {
842
+ result = invokeFn();
843
+ } catch (error) {
844
+ this.finish(error);
845
+ throw error;
846
+ }
847
+ if (this.observing) return result;
848
+ this.observing = true;
849
+ if (isThenable(result)) result.then((stream) => this.observe(stream), (error) => this.finish(error));
850
+ else this.observe(result);
851
+ return result;
852
+ }
853
+ observe(stream) {
854
+ if (isRecord(stream)) droppedStreams?.register(stream, this);
855
+ try {
856
+ if (isIteratorStream(stream)) {
857
+ const iterator = stream.iterator;
858
+ stream.iterator = () => this.observed(iterator.call(stream));
859
+ return;
860
+ }
861
+ if (isEventStream(stream)) {
862
+ for (const name of this.provider.streamEvents) stream.on(name, (event) => {
863
+ this.events.push(event);
864
+ });
865
+ stream.on(STREAM_END_EVENT, () => {
866
+ this.finish(stream.errored === true && stream.aborted !== true ? /* @__PURE__ */ new Error("The stream failed") : void 0);
867
+ });
868
+ return;
869
+ }
870
+ if (isAsyncIterator(stream)) {
871
+ const observed = this.observed({
872
+ next: stream.next.bind(stream),
873
+ return: stream.return?.bind(stream),
874
+ throw: stream.throw?.bind(stream)
875
+ });
876
+ stream.next = observed.next;
877
+ stream.return = observed.return;
878
+ stream.throw = observed.throw;
879
+ return;
880
+ }
881
+ } catch {}
882
+ this.finish(void 0);
883
+ }
884
+ observed(iterator) {
885
+ const next = async (...args) => {
886
+ try {
887
+ const result = await iterator.next(...args);
888
+ if (result.done === true) this.finish(void 0);
889
+ else this.events.push(result.value);
890
+ return result;
891
+ } catch (error) {
892
+ this.finish(error);
893
+ throw error;
894
+ }
895
+ };
896
+ const end = async (value) => {
897
+ try {
898
+ return iterator.return === void 0 ? {
899
+ done: true,
900
+ value
901
+ } : await iterator.return(value);
902
+ } finally {
903
+ this.finish(void 0);
904
+ }
905
+ };
906
+ const fail = async (error) => {
907
+ try {
908
+ if (iterator.throw === void 0) throw error;
909
+ return await iterator.throw(error);
910
+ } catch (raised) {
911
+ this.finish(raised);
912
+ throw raised;
913
+ }
914
+ };
915
+ const observed = {
916
+ next,
917
+ return: end,
918
+ throw: fail,
919
+ [Symbol.asyncIterator]: () => observed
920
+ };
921
+ return observed;
922
+ }
923
+ finish(error) {
924
+ if (this.finished) return;
925
+ this.finished = true;
926
+ let summary;
927
+ try {
928
+ summary = this.events.length === 0 ? void 0 : this.provider.streamSummary?.(this.events);
929
+ const prompt = this.provider.prompt(this.body);
930
+ if (prompt !== void 0) this.span?.setPrompt(prompt);
931
+ if (!isNil(summary)) this.span?.addContext(clientCallContext(this.provider, this.body, summary, Date.now() - this.startedAt));
932
+ } catch {}
933
+ if (error === void 0) this.resolveDone(summary);
934
+ else this.rejectDone(new StreamFinalizationError(errorText(error), summary));
935
+ }
936
+ };
445
937
  //#endregion
446
938
  //#region src/autoTrace.ts
447
939
  const autoTraceGlobal = globalThis;
@@ -676,11 +1168,13 @@ function invokeRecordedClientCall(definition, args, call) {
676
1168
  throw error;
677
1169
  }
678
1170
  });
679
- if (outcome === void 0) return traced;
680
- if ("value" in outcome && traced === outcome.value) return traced;
1171
+ const settled = outcome;
1172
+ outcome = void 0;
1173
+ if (settled === void 0) return traced;
1174
+ if ("value" in settled && traced === settled.value) return traced;
681
1175
  if (traced instanceof Promise) holdAutoTraceRoots(traced);
682
- if ("error" in outcome) throw outcome.error;
683
- return outcome.value;
1176
+ if ("error" in settled) throw settled.error;
1177
+ return settled.value;
684
1178
  }
685
1179
  function jevDefinition(receiver) {
686
1180
  const className = receiverClassName(receiver);
@@ -705,40 +1199,42 @@ function __bitfabAutoJev(receiver, ...args) {
705
1199
  if (!__bitfabAutoTraceActive()) return target.systemOne(...args);
706
1200
  return invokeRecordedClientCall(jevDefinition(receiver), args, () => target.systemOne(...args));
707
1201
  }
708
- const CLIENT_CALL_METHOD = "create";
709
1202
  const clientCallDefinitions = /* @__PURE__ */ new Map();
710
- function clientCallDefinition(provider, receiver) {
1203
+ function clientCallDefinition(provider, receiver, method) {
711
1204
  const className = receiverClassName(receiver);
712
- const name = className === void 0 ? CLIENT_CALL_METHOD : `${className}.${CLIENT_CALL_METHOD}`;
713
- const id = `ts-auto-v1:${provider.key}#${name}`;
1205
+ const qualified = (methodName) => className === void 0 ? methodName : `${className}.${methodName}`;
1206
+ const id = `ts-auto-v1:${provider.key}#${qualified(method)}`;
714
1207
  let definition = clientCallDefinitions.get(id);
715
1208
  if (definition === void 0) {
716
1209
  definition = {
717
1210
  id,
718
- name,
1211
+ name: qualified(provider.spanMethods?.[method] ?? method),
719
1212
  file: provider.library,
720
1213
  line: 0,
721
1214
  column: 0,
722
1215
  async: true,
723
- clientCall: provider.key
1216
+ clientCall: provider.key,
1217
+ clientCallMethod: method
724
1218
  };
725
1219
  clientCallDefinitions.set(id, definition);
726
1220
  }
727
1221
  return definition;
728
1222
  }
729
- function invokeClientCall(provider, receiver, args) {
730
- const target = receiver;
731
- if (!__bitfabAutoTraceActive() || isStreamingRequest(args[0]) || !provider.matchesReceiver(receiver) || frameworkRecordsClientCall()) return target.create(...args);
732
- return invokeRecordedClientCall(clientCallDefinition(provider, receiver), args, () => target.create(...args));
1223
+ function __bitfabAutoClientCall(endpoint, receiver, method, ...args) {
1224
+ const call = () => Reflect.apply(receiver[method], receiver, args);
1225
+ if (!__bitfabAutoTraceActive()) return call();
1226
+ const provider = providerForClientCall(endpoint, method, receiver);
1227
+ if (provider === void 0 || clientCallStreams(provider, method, args[0]) && provider.streamSummary === void 0 || frameworkRecordsClientCall()) return call();
1228
+ return invokeRecordedClientCall(clientCallDefinition(provider, receiver, method), args, call);
733
1229
  }
734
1230
  function __bitfabAutoOpenRouter(receiver, ...args) {
735
- return invokeClientCall(OPENROUTER, receiver, args);
1231
+ return __bitfabAutoClientCall("chat.completions", receiver, "create", ...args);
736
1232
  }
737
1233
  function __bitfabAutoAnthropic(receiver, ...args) {
738
- return invokeClientCall(ANTHROPIC, receiver, args);
1234
+ return __bitfabAutoClientCall("messages", receiver, "create", ...args);
739
1235
  }
740
1236
  function __bitfabAutoOpenAIResponses(receiver, ...args) {
741
- return invokeClientCall(OPENAI_RESPONSES, receiver, args);
1237
+ return __bitfabAutoClientCall("responses", receiver, "create", ...args);
742
1238
  }
743
1239
  function __bitfabAutoWrap(definition, fn) {
744
1240
  noteTransformedModule();
@@ -767,6 +1263,6 @@ function _resetAutoTraceTransformDetection() {
767
1263
  autoTraceGlobal.__bitfab_auto_trace_transformed_v1__ = void 0;
768
1264
  }
769
1265
  //#endregion
770
- export { unmapOpenAiAgentsTrace as A, asyncStorageReady as B, recordAutoTracedClientCall as C, mapOpenAiAgentsTrace as D, endOpenAiAgentsSpan as E, warnOnce as F, isAsyncStorageInitDone as H, writeOnce as I, isCaptureSuppressed as L, installLangChainRunScopes as M, markLangChainRunRecorded as N, openAiAgentsParentSpanId as O, warn as P, runWithCaptureSuppressed as R, frameworkRecordsClientCall as S, watchClientCall as T, registerAsyncLocalStorageClass as U, createAsyncLocalStorage as V, runWithAutoTraceRootContext as _, __bitfabAutoSpan as a, OPENROUTER as b, _resetAutoTraceTransformDetection as c, invokeAsDiscoveredCall as d, invokeThroughAutoTraceEntries as f, runWithAutoTraceNodeConfiguration as g, runWithAutoTraceFramesAt as h, __bitfabAutoOpenRouter as i, forgetLangChainRun as j, openAiAgentsSpanChain as k, clearAutoTraceNodeConfiguration as l, runWithAutoTraceEntry as m, __bitfabAutoJev as n, __bitfabAutoTraceActive as o, runAsAutoTraceRootFunction as p, __bitfabAutoOpenAIResponses as r, __bitfabAutoWrap as s, __bitfabAutoAnthropic as t, currentAutoTraceEntries as u, ANTHROPIC as v, recordWatchedClientCall as w, clientCallProvider as x, OPENAI_RESPONSES as y, assertAsyncStorageRegistered as z };
1266
+ export { recordWatchedClientCall as A, installLangChainRunScopes as B, OPENAI_RESPONSES as C, clientCallStreams as D, clientCallProvider as E, mapOpenAiAgentsTrace as F, isCaptureSuppressed as G, warn as H, openAiAgentsParentSpanId as I, asyncStorageReady as J, runWithCaptureSuppressed as K, openAiAgentsSpanChain as L, watchClientCall as M, StreamFinalizationError as N, frameworkRecordsClientCall as O, endOpenAiAgentsSpan as P, unmapOpenAiAgentsTrace as R, OPENAI_EMBEDDINGS as S, OPENROUTER as T, warnOnce as U, markLangChainRunRecorded as V, writeOnce as W, isAsyncStorageInitDone as X, createAsyncLocalStorage as Y, registerAsyncLocalStorageClass as Z, runWithAutoTraceNodeConfiguration as _, __bitfabAutoOpenRouter as a, GEMINI as b, __bitfabAutoWrap as c, currentAutoTraceEntries as d, invokeAsDiscoveredCall as f, runWithAutoTraceFramesAt as g, runWithAutoTraceEntry as h, __bitfabAutoOpenAIResponses as i, sharedClientCallStreamRecording as j, recordAutoTracedClientCall as k, _resetAutoTraceTransformDetection as l, runAsAutoTraceRootFunction as m, __bitfabAutoClientCall as n, __bitfabAutoSpan as o, invokeThroughAutoTraceEntries as p, assertAsyncStorageRegistered as q, __bitfabAutoJev as r, __bitfabAutoTraceActive as s, __bitfabAutoAnthropic as t, clearAutoTraceNodeConfiguration as u, runWithAutoTraceRootContext as v, OPENAI_TRANSCRIPTIONS as w, OPENAI_CHAT as x, ANTHROPIC as y, forgetLangChainRun as z };
771
1267
 
772
- //# sourceMappingURL=autoTrace-kHOBg49M.js.map
1268
+ //# sourceMappingURL=autoTrace-BgN0zCQf.js.map