braintrust 3.6.0 → 3.7.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.
- package/dev/dist/index.js +2692 -1472
- package/dev/dist/index.mjs +2616 -1396
- package/dist/auto-instrumentations/bundler/esbuild.cjs +46 -21
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/rollup.cjs +46 -21
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +46 -21
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +952 -0
- package/dist/auto-instrumentations/bundler/webpack-loader.d.ts +53 -0
- package/dist/auto-instrumentations/bundler/webpack.cjs +46 -21
- package/dist/auto-instrumentations/bundler/webpack.mjs +2 -2
- package/dist/auto-instrumentations/{chunk-WOUC73KB.mjs → chunk-NY4CGTN6.mjs} +1 -1
- package/dist/auto-instrumentations/{chunk-F7WAXFNM.mjs → chunk-YCKND42U.mjs} +46 -21
- package/dist/auto-instrumentations/hook.mjs +77 -26
- package/dist/auto-instrumentations/index.cjs +46 -21
- package/dist/auto-instrumentations/index.mjs +1 -1
- package/dist/browser.d.mts +8 -30
- package/dist/browser.d.ts +8 -30
- package/dist/browser.js +5051 -6344
- package/dist/browser.mjs +5051 -6344
- package/dist/cli.js +2622 -1398
- package/dist/edge-light.js +9456 -10773
- package/dist/edge-light.mjs +9456 -10773
- package/dist/index.d.mts +8 -30
- package/dist/index.d.ts +8 -30
- package/dist/index.js +5078 -6371
- package/dist/index.mjs +4870 -6163
- package/dist/instrumentation/index.js +2491 -1319
- package/dist/instrumentation/index.mjs +2491 -1319
- package/dist/workerd.js +9456 -10773
- package/dist/workerd.mjs +9456 -10773
- package/package.json +6 -2
package/dev/dist/index.mjs
CHANGED
|
@@ -24,25 +24,51 @@ function patchTracingChannel(tracingChannelFn) {
|
|
|
24
24
|
if (TracingChannel.prototype.tracePromise) {
|
|
25
25
|
TracingChannel.prototype.tracePromise = function(fn, context = {}, thisArg, ...args) {
|
|
26
26
|
const { start, end, asyncStart, asyncEnd, error } = this;
|
|
27
|
-
function
|
|
27
|
+
function publishRejected(err) {
|
|
28
28
|
context.error = err;
|
|
29
29
|
error?.publish(context);
|
|
30
30
|
asyncStart?.publish(context);
|
|
31
31
|
asyncEnd?.publish(context);
|
|
32
|
-
return Promise.reject(err);
|
|
33
32
|
}
|
|
34
|
-
function
|
|
33
|
+
function publishResolved(result) {
|
|
35
34
|
context.result = result;
|
|
36
35
|
asyncStart?.publish(context);
|
|
37
36
|
asyncEnd?.publish(context);
|
|
38
|
-
return result;
|
|
39
37
|
}
|
|
40
38
|
return start.runStores(context, () => {
|
|
41
39
|
try {
|
|
42
40
|
const result = Reflect.apply(fn, thisArg, args);
|
|
43
41
|
end?.publish(context);
|
|
44
42
|
if (result && (typeof result === "object" || typeof result === "function") && typeof result.then === "function") {
|
|
45
|
-
|
|
43
|
+
if (result.constructor === Promise) {
|
|
44
|
+
return result.then(
|
|
45
|
+
(res) => {
|
|
46
|
+
publishResolved(res);
|
|
47
|
+
return res;
|
|
48
|
+
},
|
|
49
|
+
(err) => {
|
|
50
|
+
publishRejected(err);
|
|
51
|
+
return Promise.reject(err);
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
void result.then(
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
57
|
+
(resolved) => {
|
|
58
|
+
try {
|
|
59
|
+
publishResolved(resolved);
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
64
|
+
(err) => {
|
|
65
|
+
try {
|
|
66
|
+
publishRejected(err);
|
|
67
|
+
} catch {
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
return result;
|
|
46
72
|
}
|
|
47
73
|
context.result = result;
|
|
48
74
|
asyncStart?.publish(context);
|
|
@@ -139,7 +165,7 @@ var DefaultTracingChannel = class {
|
|
|
139
165
|
}
|
|
140
166
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
141
167
|
tracePromise(fn, _message, thisArg, ...args) {
|
|
142
|
-
return
|
|
168
|
+
return fn.apply(thisArg, args);
|
|
143
169
|
}
|
|
144
170
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
145
171
|
traceCallback(fn, _position, _message, thisArg, ...args) {
|
|
@@ -159,6 +185,7 @@ var iso = {
|
|
|
159
185
|
processOn: (_0, _1) => {
|
|
160
186
|
},
|
|
161
187
|
basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
|
|
188
|
+
// eslint-disable-next-line no-restricted-properties -- preserving intentional console usage.
|
|
162
189
|
writeln: (text) => console.log(text)
|
|
163
190
|
};
|
|
164
191
|
var isomorph_default = iso;
|
|
@@ -1855,6 +1882,15 @@ var InternalAbortError = class extends Error {
|
|
|
1855
1882
|
this.name = "InternalAbortError";
|
|
1856
1883
|
}
|
|
1857
1884
|
};
|
|
1885
|
+
function filterFrom(record, keys) {
|
|
1886
|
+
const out = {};
|
|
1887
|
+
for (const k of Object.keys(record)) {
|
|
1888
|
+
if (!keys.includes(k)) {
|
|
1889
|
+
out[k] = record[k];
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
return out;
|
|
1893
|
+
}
|
|
1858
1894
|
|
|
1859
1895
|
// src/generated_types.ts
|
|
1860
1896
|
import { z as z6 } from "zod/v3";
|
|
@@ -8848,7 +8884,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
8848
8884
|
if (!completed) {
|
|
8849
8885
|
completed = true;
|
|
8850
8886
|
try {
|
|
8851
|
-
options.onComplete(chunks);
|
|
8887
|
+
await options.onComplete(chunks);
|
|
8852
8888
|
} catch (error) {
|
|
8853
8889
|
console.error("Error in stream onComplete handler:", error);
|
|
8854
8890
|
}
|
|
@@ -8860,7 +8896,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
8860
8896
|
chunks.push(chunk);
|
|
8861
8897
|
if (options.onChunk) {
|
|
8862
8898
|
try {
|
|
8863
|
-
options.onChunk(chunk);
|
|
8899
|
+
await options.onChunk(chunk);
|
|
8864
8900
|
} catch (error) {
|
|
8865
8901
|
console.error("Error in stream onChunk handler:", error);
|
|
8866
8902
|
}
|
|
@@ -8873,7 +8909,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
8873
8909
|
completed = true;
|
|
8874
8910
|
if (options.onError) {
|
|
8875
8911
|
try {
|
|
8876
|
-
options.onError(
|
|
8912
|
+
await options.onError(
|
|
8877
8913
|
error instanceof Error ? error : new Error(String(error)),
|
|
8878
8914
|
chunks
|
|
8879
8915
|
);
|
|
@@ -8891,7 +8927,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
8891
8927
|
if (!completed) {
|
|
8892
8928
|
completed = true;
|
|
8893
8929
|
try {
|
|
8894
|
-
options.onComplete(chunks);
|
|
8930
|
+
await options.onComplete(chunks);
|
|
8895
8931
|
} catch (error) {
|
|
8896
8932
|
console.error("Error in stream onComplete handler:", error);
|
|
8897
8933
|
}
|
|
@@ -8908,7 +8944,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
8908
8944
|
const error = rawError instanceof Error ? rawError : new Error(String(rawError));
|
|
8909
8945
|
if (options.onError) {
|
|
8910
8946
|
try {
|
|
8911
|
-
options.onError(error, chunks);
|
|
8947
|
+
await options.onError(error, chunks);
|
|
8912
8948
|
} catch (handlerError) {
|
|
8913
8949
|
console.error("Error in stream onError handler:", handlerError);
|
|
8914
8950
|
}
|
|
@@ -9617,51 +9653,28 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
9617
9653
|
}
|
|
9618
9654
|
const { span, startTime } = spanData;
|
|
9619
9655
|
const endEvent = event;
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
|
|
9623
|
-
|
|
9624
|
-
|
|
9625
|
-
|
|
9626
|
-
|
|
9627
|
-
|
|
9628
|
-
|
|
9629
|
-
|
|
9630
|
-
|
|
9631
|
-
|
|
9632
|
-
|
|
9633
|
-
return;
|
|
9634
|
-
}
|
|
9635
|
-
let first = true;
|
|
9636
|
-
stream.on("chunk", () => {
|
|
9637
|
-
if (first) {
|
|
9638
|
-
span.log({
|
|
9639
|
-
metrics: {
|
|
9640
|
-
time_to_first_token: getCurrentUnixTimestamp() - startTime
|
|
9641
|
-
}
|
|
9642
|
-
});
|
|
9643
|
-
first = false;
|
|
9644
|
-
}
|
|
9645
|
-
});
|
|
9646
|
-
stream.on("chatCompletion", (completion) => {
|
|
9647
|
-
try {
|
|
9648
|
-
if (hasChoices(completion)) {
|
|
9649
|
-
span.log({
|
|
9650
|
-
output: completion.choices
|
|
9651
|
-
});
|
|
9652
|
-
}
|
|
9653
|
-
} catch (error) {
|
|
9654
|
-
console.error(
|
|
9655
|
-
`Error extracting chatCompletion for ${channelName}:`,
|
|
9656
|
-
error
|
|
9657
|
-
);
|
|
9656
|
+
const handleResolvedResult = (result) => {
|
|
9657
|
+
const resolvedEndEvent = {
|
|
9658
|
+
...endEvent,
|
|
9659
|
+
result
|
|
9660
|
+
};
|
|
9661
|
+
if (config.patchResult?.({
|
|
9662
|
+
channelName,
|
|
9663
|
+
endEvent: resolvedEndEvent,
|
|
9664
|
+
result,
|
|
9665
|
+
span,
|
|
9666
|
+
startTime
|
|
9667
|
+
})) {
|
|
9668
|
+
return;
|
|
9658
9669
|
}
|
|
9659
|
-
|
|
9660
|
-
|
|
9661
|
-
|
|
9670
|
+
const stream = result;
|
|
9671
|
+
if (!isSyncStreamLike(stream)) {
|
|
9672
|
+
span.end();
|
|
9673
|
+
states.delete(event);
|
|
9662
9674
|
return;
|
|
9663
9675
|
}
|
|
9664
|
-
|
|
9676
|
+
let first = true;
|
|
9677
|
+
stream.on("chunk", () => {
|
|
9665
9678
|
if (first) {
|
|
9666
9679
|
span.log({
|
|
9667
9680
|
metrics: {
|
|
@@ -9670,25 +9683,55 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
9670
9683
|
});
|
|
9671
9684
|
first = false;
|
|
9672
9685
|
}
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9686
|
+
});
|
|
9687
|
+
stream.on("chatCompletion", (completion) => {
|
|
9688
|
+
try {
|
|
9689
|
+
if (hasChoices(completion)) {
|
|
9690
|
+
span.log({
|
|
9691
|
+
output: completion.choices
|
|
9692
|
+
});
|
|
9693
|
+
}
|
|
9694
|
+
} catch (error) {
|
|
9695
|
+
console.error(
|
|
9696
|
+
`Error extracting chatCompletion for ${channelName}:`,
|
|
9697
|
+
error
|
|
9698
|
+
);
|
|
9676
9699
|
}
|
|
9677
|
-
} catch (error) {
|
|
9678
|
-
console.error(`Error extracting event for ${channelName}:`, error);
|
|
9679
|
-
}
|
|
9680
|
-
});
|
|
9681
|
-
stream.on("end", () => {
|
|
9682
|
-
span.end();
|
|
9683
|
-
states.delete(event);
|
|
9684
|
-
});
|
|
9685
|
-
stream.on("error", (error) => {
|
|
9686
|
-
span.log({
|
|
9687
|
-
error: error.message
|
|
9688
9700
|
});
|
|
9689
|
-
|
|
9690
|
-
|
|
9691
|
-
|
|
9701
|
+
stream.on("event", (streamEvent) => {
|
|
9702
|
+
if (!config.extractFromEvent) {
|
|
9703
|
+
return;
|
|
9704
|
+
}
|
|
9705
|
+
try {
|
|
9706
|
+
if (first) {
|
|
9707
|
+
span.log({
|
|
9708
|
+
metrics: {
|
|
9709
|
+
time_to_first_token: getCurrentUnixTimestamp() - startTime
|
|
9710
|
+
}
|
|
9711
|
+
});
|
|
9712
|
+
first = false;
|
|
9713
|
+
}
|
|
9714
|
+
const extracted = config.extractFromEvent(streamEvent);
|
|
9715
|
+
if (extracted && Object.keys(extracted).length > 0) {
|
|
9716
|
+
span.log(extracted);
|
|
9717
|
+
}
|
|
9718
|
+
} catch (error) {
|
|
9719
|
+
console.error(`Error extracting event for ${channelName}:`, error);
|
|
9720
|
+
}
|
|
9721
|
+
});
|
|
9722
|
+
stream.on("end", () => {
|
|
9723
|
+
span.end();
|
|
9724
|
+
states.delete(event);
|
|
9725
|
+
});
|
|
9726
|
+
stream.on("error", (error) => {
|
|
9727
|
+
span.log({
|
|
9728
|
+
error: error.message
|
|
9729
|
+
});
|
|
9730
|
+
span.end();
|
|
9731
|
+
states.delete(event);
|
|
9732
|
+
});
|
|
9733
|
+
};
|
|
9734
|
+
handleResolvedResult(endEvent.result);
|
|
9692
9735
|
},
|
|
9693
9736
|
error: (event) => {
|
|
9694
9737
|
logErrorAndEnd(states, event);
|
|
@@ -10468,7 +10511,7 @@ var AnthropicPlugin = class extends BasePlugin {
|
|
|
10468
10511
|
this.unsubscribers.push(
|
|
10469
10512
|
traceStreamingChannel(anthropicChannels.betaMessagesCreate, {
|
|
10470
10513
|
...anthropicConfig,
|
|
10471
|
-
name: "anthropic.
|
|
10514
|
+
name: "anthropic.messages.create"
|
|
10472
10515
|
})
|
|
10473
10516
|
);
|
|
10474
10517
|
}
|
|
@@ -10491,9 +10534,12 @@ function parseMetricsFromUsage2(usage) {
|
|
|
10491
10534
|
return metrics;
|
|
10492
10535
|
}
|
|
10493
10536
|
function aggregateAnthropicStreamChunks(chunks) {
|
|
10494
|
-
const
|
|
10537
|
+
const fallbackTextDeltas = [];
|
|
10538
|
+
const contentBlocks = {};
|
|
10539
|
+
const contentBlockDeltas = {};
|
|
10495
10540
|
let metrics = {};
|
|
10496
10541
|
let metadata = {};
|
|
10542
|
+
let role;
|
|
10497
10543
|
for (const event of chunks) {
|
|
10498
10544
|
switch (event?.type) {
|
|
10499
10545
|
case "message_start":
|
|
@@ -10501,15 +10547,55 @@ function aggregateAnthropicStreamChunks(chunks) {
|
|
|
10501
10547
|
const initialMetrics = parseMetricsFromUsage2(event.message.usage);
|
|
10502
10548
|
metrics = { ...metrics, ...initialMetrics };
|
|
10503
10549
|
}
|
|
10550
|
+
if (typeof event.message?.role === "string") {
|
|
10551
|
+
role = event.message.role;
|
|
10552
|
+
}
|
|
10553
|
+
break;
|
|
10554
|
+
case "content_block_start":
|
|
10555
|
+
if (event.content_block) {
|
|
10556
|
+
contentBlocks[event.index] = event.content_block;
|
|
10557
|
+
contentBlockDeltas[event.index] = { textDeltas: [], citations: [] };
|
|
10558
|
+
}
|
|
10504
10559
|
break;
|
|
10505
|
-
case "content_block_delta":
|
|
10506
|
-
|
|
10507
|
-
|
|
10560
|
+
case "content_block_delta": {
|
|
10561
|
+
const acc = contentBlockDeltas[event.index];
|
|
10562
|
+
const delta = event.delta;
|
|
10563
|
+
if (!delta) break;
|
|
10564
|
+
if (delta.type === "text_delta" && "text" in delta) {
|
|
10565
|
+
const text = delta.text;
|
|
10508
10566
|
if (text) {
|
|
10509
|
-
|
|
10567
|
+
if (acc !== void 0) {
|
|
10568
|
+
acc.textDeltas.push(text);
|
|
10569
|
+
} else {
|
|
10570
|
+
fallbackTextDeltas.push(text);
|
|
10571
|
+
}
|
|
10572
|
+
}
|
|
10573
|
+
} else if (delta.type === "input_json_delta" && "partial_json" in delta) {
|
|
10574
|
+
const partialJson = delta.partial_json;
|
|
10575
|
+
if (partialJson && acc !== void 0) {
|
|
10576
|
+
acc.textDeltas.push(partialJson);
|
|
10577
|
+
}
|
|
10578
|
+
} else if (delta.type === "thinking_delta" && "thinking" in delta) {
|
|
10579
|
+
const thinking = delta.thinking;
|
|
10580
|
+
if (thinking && acc !== void 0) {
|
|
10581
|
+
acc.textDeltas.push(thinking);
|
|
10582
|
+
}
|
|
10583
|
+
} else if (delta.type === "citations_delta" && "citation" in delta) {
|
|
10584
|
+
const citation = delta.citation;
|
|
10585
|
+
if (citation && acc !== void 0) {
|
|
10586
|
+
acc.citations.push(citation);
|
|
10510
10587
|
}
|
|
10511
10588
|
}
|
|
10512
10589
|
break;
|
|
10590
|
+
}
|
|
10591
|
+
case "content_block_stop":
|
|
10592
|
+
finalizeContentBlock(
|
|
10593
|
+
event.index,
|
|
10594
|
+
contentBlocks,
|
|
10595
|
+
contentBlockDeltas,
|
|
10596
|
+
fallbackTextDeltas
|
|
10597
|
+
);
|
|
10598
|
+
break;
|
|
10513
10599
|
case "message_delta":
|
|
10514
10600
|
if (event.usage) {
|
|
10515
10601
|
const finalMetrics = parseMetricsFromUsage2(event.usage);
|
|
@@ -10521,7 +10607,21 @@ function aggregateAnthropicStreamChunks(chunks) {
|
|
|
10521
10607
|
break;
|
|
10522
10608
|
}
|
|
10523
10609
|
}
|
|
10524
|
-
const
|
|
10610
|
+
const orderedContent = Object.entries(contentBlocks).map(([index, block]) => ({
|
|
10611
|
+
block,
|
|
10612
|
+
index: Number(index)
|
|
10613
|
+
})).filter(({ block }) => block !== void 0).sort((left, right) => left.index - right.index).map(({ block }) => block);
|
|
10614
|
+
let output = fallbackTextDeltas.join("");
|
|
10615
|
+
if (orderedContent.length > 0) {
|
|
10616
|
+
if (orderedContent.every(isTextContentBlock) && orderedContent.every((block) => !block.citations?.length)) {
|
|
10617
|
+
output = orderedContent.map((block) => block.text).join("");
|
|
10618
|
+
} else {
|
|
10619
|
+
output = {
|
|
10620
|
+
...role ? { role } : {},
|
|
10621
|
+
content: orderedContent
|
|
10622
|
+
};
|
|
10623
|
+
}
|
|
10624
|
+
}
|
|
10525
10625
|
const finalized = finalizeAnthropicTokens(metrics);
|
|
10526
10626
|
const filteredMetrics = Object.fromEntries(
|
|
10527
10627
|
Object.entries(finalized).filter(
|
|
@@ -10534,6 +10634,61 @@ function aggregateAnthropicStreamChunks(chunks) {
|
|
|
10534
10634
|
metadata
|
|
10535
10635
|
};
|
|
10536
10636
|
}
|
|
10637
|
+
function finalizeContentBlock(index, contentBlocks, contentBlockDeltas, fallbackTextDeltas) {
|
|
10638
|
+
const contentBlock = contentBlocks[index];
|
|
10639
|
+
if (!contentBlock) {
|
|
10640
|
+
return;
|
|
10641
|
+
}
|
|
10642
|
+
const acc = contentBlockDeltas[index];
|
|
10643
|
+
const text = acc?.textDeltas.join("") ?? "";
|
|
10644
|
+
if (isToolUseContentBlock(contentBlock)) {
|
|
10645
|
+
if (!text) {
|
|
10646
|
+
return;
|
|
10647
|
+
}
|
|
10648
|
+
try {
|
|
10649
|
+
contentBlocks[index] = {
|
|
10650
|
+
...contentBlock,
|
|
10651
|
+
input: JSON.parse(text)
|
|
10652
|
+
};
|
|
10653
|
+
} catch {
|
|
10654
|
+
fallbackTextDeltas.push(text);
|
|
10655
|
+
delete contentBlocks[index];
|
|
10656
|
+
}
|
|
10657
|
+
return;
|
|
10658
|
+
}
|
|
10659
|
+
if (isTextContentBlock(contentBlock)) {
|
|
10660
|
+
if (!text) {
|
|
10661
|
+
delete contentBlocks[index];
|
|
10662
|
+
return;
|
|
10663
|
+
}
|
|
10664
|
+
const updated = { ...contentBlock, text };
|
|
10665
|
+
if (acc?.citations.length) {
|
|
10666
|
+
updated.citations = acc.citations;
|
|
10667
|
+
}
|
|
10668
|
+
contentBlocks[index] = updated;
|
|
10669
|
+
return;
|
|
10670
|
+
}
|
|
10671
|
+
if (isThinkingContentBlock(contentBlock)) {
|
|
10672
|
+
if (!text) {
|
|
10673
|
+
delete contentBlocks[index];
|
|
10674
|
+
return;
|
|
10675
|
+
}
|
|
10676
|
+
contentBlocks[index] = {
|
|
10677
|
+
...contentBlock,
|
|
10678
|
+
thinking: text
|
|
10679
|
+
};
|
|
10680
|
+
return;
|
|
10681
|
+
}
|
|
10682
|
+
}
|
|
10683
|
+
function isTextContentBlock(contentBlock) {
|
|
10684
|
+
return contentBlock.type === "text";
|
|
10685
|
+
}
|
|
10686
|
+
function isToolUseContentBlock(contentBlock) {
|
|
10687
|
+
return contentBlock.type === "tool_use";
|
|
10688
|
+
}
|
|
10689
|
+
function isThinkingContentBlock(contentBlock) {
|
|
10690
|
+
return contentBlock.type === "thinking";
|
|
10691
|
+
}
|
|
10537
10692
|
function isAnthropicBase64ContentBlock(input) {
|
|
10538
10693
|
return (input.type === "image" || input.type === "document") && isObject(input.source) && input.source.type === "base64";
|
|
10539
10694
|
}
|
|
@@ -10588,15 +10743,6 @@ function coalesceInput(messages, system) {
|
|
|
10588
10743
|
}
|
|
10589
10744
|
return input;
|
|
10590
10745
|
}
|
|
10591
|
-
function filterFrom(obj, fieldsToRemove) {
|
|
10592
|
-
const result = {};
|
|
10593
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
10594
|
-
if (!fieldsToRemove.includes(key)) {
|
|
10595
|
-
result[key] = value;
|
|
10596
|
-
}
|
|
10597
|
-
}
|
|
10598
|
-
return result;
|
|
10599
|
-
}
|
|
10600
10746
|
|
|
10601
10747
|
// src/wrappers/ai-sdk/normalize-logged-output.ts
|
|
10602
10748
|
var REMOVE_NORMALIZED_VALUE = Symbol("braintrust.ai-sdk.remove-normalized");
|
|
@@ -10710,10 +10856,6 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
10710
10856
|
channelName: "streamText",
|
|
10711
10857
|
kind: "async"
|
|
10712
10858
|
}),
|
|
10713
|
-
streamTextSync: channel({
|
|
10714
|
-
channelName: "streamText.sync",
|
|
10715
|
-
kind: "sync-stream"
|
|
10716
|
-
}),
|
|
10717
10859
|
generateObject: channel({
|
|
10718
10860
|
channelName: "generateObject",
|
|
10719
10861
|
kind: "async"
|
|
@@ -10722,10 +10864,6 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
10722
10864
|
channelName: "streamObject",
|
|
10723
10865
|
kind: "async"
|
|
10724
10866
|
}),
|
|
10725
|
-
streamObjectSync: channel({
|
|
10726
|
-
channelName: "streamObject.sync",
|
|
10727
|
-
kind: "sync-stream"
|
|
10728
|
-
}),
|
|
10729
10867
|
agentGenerate: channel({
|
|
10730
10868
|
channelName: "Agent.generate",
|
|
10731
10869
|
kind: "async"
|
|
@@ -10761,6 +10899,9 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
|
10761
10899
|
];
|
|
10762
10900
|
var AUTO_PATCHED_MODEL = Symbol.for("braintrust.ai-sdk.auto-patched-model");
|
|
10763
10901
|
var AUTO_PATCHED_TOOL = Symbol.for("braintrust.ai-sdk.auto-patched-tool");
|
|
10902
|
+
var RUNTIME_DENY_OUTPUT_PATHS = Symbol.for(
|
|
10903
|
+
"braintrust.ai-sdk.deny-output-paths"
|
|
10904
|
+
);
|
|
10764
10905
|
var AISDKPlugin = class extends BasePlugin {
|
|
10765
10906
|
config;
|
|
10766
10907
|
constructor(config = {}) {
|
|
@@ -10782,7 +10923,10 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
10782
10923
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
10783
10924
|
extractOutput: (result, endEvent) => {
|
|
10784
10925
|
finalizeAISDKChildTracing(endEvent);
|
|
10785
|
-
return processAISDKOutput(
|
|
10926
|
+
return processAISDKOutput(
|
|
10927
|
+
result,
|
|
10928
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
10929
|
+
);
|
|
10786
10930
|
},
|
|
10787
10931
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
10788
10932
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -10793,25 +10937,14 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
10793
10937
|
name: "streamText",
|
|
10794
10938
|
type: "llm" /* LLM */,
|
|
10795
10939
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
10796
|
-
extractOutput: (result) => processAISDKOutput(
|
|
10940
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
10941
|
+
result,
|
|
10942
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
10943
|
+
),
|
|
10797
10944
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
10798
10945
|
aggregateChunks: aggregateAISDKChunks,
|
|
10799
10946
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
10800
|
-
denyOutputPaths,
|
|
10801
|
-
endEvent,
|
|
10802
|
-
result,
|
|
10803
|
-
span,
|
|
10804
|
-
startTime
|
|
10805
|
-
})
|
|
10806
|
-
})
|
|
10807
|
-
);
|
|
10808
|
-
this.unsubscribers.push(
|
|
10809
|
-
traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
|
|
10810
|
-
name: "streamText",
|
|
10811
|
-
type: "llm" /* LLM */,
|
|
10812
|
-
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
10813
|
-
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
10814
|
-
denyOutputPaths,
|
|
10947
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
10815
10948
|
endEvent,
|
|
10816
10949
|
result,
|
|
10817
10950
|
span,
|
|
@@ -10826,7 +10959,10 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
10826
10959
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
10827
10960
|
extractOutput: (result, endEvent) => {
|
|
10828
10961
|
finalizeAISDKChildTracing(endEvent);
|
|
10829
|
-
return processAISDKOutput(
|
|
10962
|
+
return processAISDKOutput(
|
|
10963
|
+
result,
|
|
10964
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
10965
|
+
);
|
|
10830
10966
|
},
|
|
10831
10967
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
10832
10968
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -10837,25 +10973,14 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
10837
10973
|
name: "streamObject",
|
|
10838
10974
|
type: "llm" /* LLM */,
|
|
10839
10975
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
10840
|
-
extractOutput: (result) => processAISDKOutput(
|
|
10976
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
10977
|
+
result,
|
|
10978
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
10979
|
+
),
|
|
10841
10980
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
10842
10981
|
aggregateChunks: aggregateAISDKChunks,
|
|
10843
10982
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
10844
|
-
denyOutputPaths,
|
|
10845
|
-
endEvent,
|
|
10846
|
-
result,
|
|
10847
|
-
span,
|
|
10848
|
-
startTime
|
|
10849
|
-
})
|
|
10850
|
-
})
|
|
10851
|
-
);
|
|
10852
|
-
this.unsubscribers.push(
|
|
10853
|
-
traceSyncStreamChannel(aiSDKChannels.streamObjectSync, {
|
|
10854
|
-
name: "streamObject",
|
|
10855
|
-
type: "llm" /* LLM */,
|
|
10856
|
-
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
10857
|
-
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
10858
|
-
denyOutputPaths,
|
|
10983
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
10859
10984
|
endEvent,
|
|
10860
10985
|
result,
|
|
10861
10986
|
span,
|
|
@@ -10870,7 +10995,10 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
10870
10995
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
10871
10996
|
extractOutput: (result, endEvent) => {
|
|
10872
10997
|
finalizeAISDKChildTracing(endEvent);
|
|
10873
|
-
return processAISDKOutput(
|
|
10998
|
+
return processAISDKOutput(
|
|
10999
|
+
result,
|
|
11000
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
11001
|
+
);
|
|
10874
11002
|
},
|
|
10875
11003
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
10876
11004
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -10881,11 +11009,14 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
10881
11009
|
name: "Agent.stream",
|
|
10882
11010
|
type: "llm" /* LLM */,
|
|
10883
11011
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
10884
|
-
extractOutput: (result) => processAISDKOutput(
|
|
11012
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
11013
|
+
result,
|
|
11014
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
11015
|
+
),
|
|
10885
11016
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
10886
11017
|
aggregateChunks: aggregateAISDKChunks,
|
|
10887
11018
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
10888
|
-
denyOutputPaths,
|
|
11019
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
10889
11020
|
endEvent,
|
|
10890
11021
|
result,
|
|
10891
11022
|
span,
|
|
@@ -10900,7 +11031,10 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
10900
11031
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
10901
11032
|
extractOutput: (result, endEvent) => {
|
|
10902
11033
|
finalizeAISDKChildTracing(endEvent);
|
|
10903
|
-
return processAISDKOutput(
|
|
11034
|
+
return processAISDKOutput(
|
|
11035
|
+
result,
|
|
11036
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
11037
|
+
);
|
|
10904
11038
|
},
|
|
10905
11039
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
10906
11040
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -10911,11 +11045,14 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
10911
11045
|
name: "ToolLoopAgent.stream",
|
|
10912
11046
|
type: "llm" /* LLM */,
|
|
10913
11047
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
10914
|
-
extractOutput: (result) => processAISDKOutput(
|
|
11048
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
11049
|
+
result,
|
|
11050
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
11051
|
+
),
|
|
10915
11052
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
10916
11053
|
aggregateChunks: aggregateAISDKChunks,
|
|
10917
11054
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
10918
|
-
denyOutputPaths,
|
|
11055
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
10919
11056
|
endEvent,
|
|
10920
11057
|
result,
|
|
10921
11058
|
span,
|
|
@@ -10925,77 +11062,375 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
10925
11062
|
);
|
|
10926
11063
|
}
|
|
10927
11064
|
};
|
|
10928
|
-
function
|
|
10929
|
-
if (
|
|
10930
|
-
|
|
10931
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
10932
|
-
return input;
|
|
11065
|
+
function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
11066
|
+
if (Array.isArray(event?.denyOutputPaths)) {
|
|
11067
|
+
return event.denyOutputPaths;
|
|
10933
11068
|
}
|
|
10934
|
-
const
|
|
10935
|
-
|
|
10936
|
-
|
|
10937
|
-
function prepareAISDKInput(params, event, span, denyOutputPaths) {
|
|
10938
|
-
const input = processAISDKInput(params);
|
|
10939
|
-
const metadata = extractMetadataFromParams(params, event.self);
|
|
10940
|
-
const childTracing = prepareAISDKChildTracing(
|
|
10941
|
-
params,
|
|
10942
|
-
event.self,
|
|
10943
|
-
span,
|
|
10944
|
-
denyOutputPaths
|
|
10945
|
-
);
|
|
10946
|
-
event.__braintrust_ai_sdk_model_wrapped = childTracing.modelWrapped;
|
|
10947
|
-
if (childTracing.cleanup) {
|
|
10948
|
-
event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
|
|
11069
|
+
const firstArgument = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
11070
|
+
if (!firstArgument || typeof firstArgument !== "object") {
|
|
11071
|
+
return defaultDenyOutputPaths;
|
|
10949
11072
|
}
|
|
10950
|
-
|
|
10951
|
-
|
|
10952
|
-
|
|
10953
|
-
};
|
|
10954
|
-
}
|
|
10955
|
-
function extractTopLevelAISDKMetrics(result, event, startTime) {
|
|
10956
|
-
const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics(result);
|
|
10957
|
-
if (startTime) {
|
|
10958
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
11073
|
+
const runtimeDenyOutputPaths = firstArgument[RUNTIME_DENY_OUTPUT_PATHS];
|
|
11074
|
+
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path2) => typeof path2 === "string")) {
|
|
11075
|
+
return runtimeDenyOutputPaths;
|
|
10959
11076
|
}
|
|
10960
|
-
return
|
|
10961
|
-
}
|
|
10962
|
-
function hasModelChildTracing(event) {
|
|
10963
|
-
return event?.__braintrust_ai_sdk_model_wrapped === true;
|
|
11077
|
+
return defaultDenyOutputPaths;
|
|
10964
11078
|
}
|
|
10965
|
-
|
|
10966
|
-
|
|
10967
|
-
|
|
10968
|
-
|
|
10969
|
-
|
|
10970
|
-
|
|
10971
|
-
}
|
|
10972
|
-
|
|
10973
|
-
|
|
10974
|
-
|
|
10975
|
-
|
|
10976
|
-
if (model) {
|
|
10977
|
-
metadata.model = model;
|
|
11079
|
+
var isZodSchema2 = (value) => {
|
|
11080
|
+
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
11081
|
+
};
|
|
11082
|
+
var serializeZodSchema2 = (schema) => {
|
|
11083
|
+
try {
|
|
11084
|
+
return zodToJsonSchema(schema);
|
|
11085
|
+
} catch {
|
|
11086
|
+
return {
|
|
11087
|
+
type: "object",
|
|
11088
|
+
description: "Zod schema (conversion failed)"
|
|
11089
|
+
};
|
|
10978
11090
|
}
|
|
10979
|
-
|
|
10980
|
-
|
|
11091
|
+
};
|
|
11092
|
+
var isOutputObject = (value) => {
|
|
11093
|
+
if (value == null || typeof value !== "object") {
|
|
11094
|
+
return false;
|
|
10981
11095
|
}
|
|
10982
|
-
const
|
|
10983
|
-
if (
|
|
10984
|
-
|
|
11096
|
+
const output = value;
|
|
11097
|
+
if (!("responseFormat" in output)) {
|
|
11098
|
+
return false;
|
|
10985
11099
|
}
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
10989
|
-
|
|
10990
|
-
|
|
10991
|
-
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
|
|
10996
|
-
|
|
11100
|
+
if (output.type === "object" || output.type === "text") {
|
|
11101
|
+
return true;
|
|
11102
|
+
}
|
|
11103
|
+
if (typeof output.responseFormat === "function" || typeof output.responseFormat === "object") {
|
|
11104
|
+
return true;
|
|
11105
|
+
}
|
|
11106
|
+
return false;
|
|
11107
|
+
};
|
|
11108
|
+
var serializeOutputObject = (output, model) => {
|
|
11109
|
+
try {
|
|
11110
|
+
const result = {
|
|
11111
|
+
response_format: null
|
|
11112
|
+
};
|
|
11113
|
+
if (output.type) {
|
|
11114
|
+
result.type = output.type;
|
|
11115
|
+
}
|
|
11116
|
+
let responseFormat;
|
|
11117
|
+
if (typeof output.responseFormat === "function") {
|
|
11118
|
+
const mockModelForSchema = {
|
|
11119
|
+
supportsStructuredOutputs: true,
|
|
11120
|
+
...model && typeof model === "object" ? model : {}
|
|
11121
|
+
};
|
|
11122
|
+
responseFormat = output.responseFormat({ model: mockModelForSchema });
|
|
11123
|
+
} else if (output.responseFormat != null && typeof output.responseFormat === "object") {
|
|
11124
|
+
responseFormat = output.responseFormat;
|
|
11125
|
+
}
|
|
11126
|
+
if (responseFormat) {
|
|
11127
|
+
if (typeof responseFormat.then === "function") {
|
|
11128
|
+
result.response_format = Promise.resolve(responseFormat).then(
|
|
11129
|
+
(resolved) => {
|
|
11130
|
+
if (resolved.schema && isZodSchema2(resolved.schema)) {
|
|
11131
|
+
return {
|
|
11132
|
+
...resolved,
|
|
11133
|
+
schema: serializeZodSchema2(resolved.schema)
|
|
11134
|
+
};
|
|
11135
|
+
}
|
|
11136
|
+
return resolved;
|
|
11137
|
+
}
|
|
11138
|
+
);
|
|
11139
|
+
} else {
|
|
11140
|
+
const syncResponseFormat = responseFormat;
|
|
11141
|
+
if (syncResponseFormat.schema && isZodSchema2(syncResponseFormat.schema)) {
|
|
11142
|
+
responseFormat = {
|
|
11143
|
+
...syncResponseFormat,
|
|
11144
|
+
schema: serializeZodSchema2(syncResponseFormat.schema)
|
|
11145
|
+
};
|
|
11146
|
+
}
|
|
11147
|
+
result.response_format = responseFormat;
|
|
11148
|
+
}
|
|
10997
11149
|
}
|
|
10998
|
-
|
|
11150
|
+
return result;
|
|
11151
|
+
} catch {
|
|
11152
|
+
return {
|
|
11153
|
+
response_format: null
|
|
11154
|
+
};
|
|
11155
|
+
}
|
|
11156
|
+
};
|
|
11157
|
+
var processInputAttachmentsSync = (input) => {
|
|
11158
|
+
if (!input) return { input };
|
|
11159
|
+
const processed = { ...input };
|
|
11160
|
+
if (input.messages && Array.isArray(input.messages)) {
|
|
11161
|
+
processed.messages = input.messages.map(processMessage);
|
|
11162
|
+
}
|
|
11163
|
+
if (input.prompt && typeof input.prompt === "object") {
|
|
11164
|
+
if (Array.isArray(input.prompt)) {
|
|
11165
|
+
processed.prompt = input.prompt.map(processMessage);
|
|
11166
|
+
} else {
|
|
11167
|
+
processed.prompt = processPromptContent(input.prompt);
|
|
11168
|
+
}
|
|
11169
|
+
}
|
|
11170
|
+
if (input.schema && isZodSchema2(input.schema)) {
|
|
11171
|
+
processed.schema = serializeZodSchema2(input.schema);
|
|
11172
|
+
}
|
|
11173
|
+
if (input.callOptionsSchema && isZodSchema2(input.callOptionsSchema)) {
|
|
11174
|
+
processed.callOptionsSchema = serializeZodSchema2(input.callOptionsSchema);
|
|
11175
|
+
}
|
|
11176
|
+
if (input.tools) {
|
|
11177
|
+
processed.tools = serializeAISDKToolsForLogging(input.tools);
|
|
11178
|
+
}
|
|
11179
|
+
let outputPromise;
|
|
11180
|
+
if (input.output && isOutputObject(input.output)) {
|
|
11181
|
+
const serialized = serializeOutputObject(input.output, input.model);
|
|
11182
|
+
if (serialized.response_format && typeof serialized.response_format.then === "function") {
|
|
11183
|
+
processed.output = { ...serialized, response_format: {} };
|
|
11184
|
+
outputPromise = serialized.response_format.then(
|
|
11185
|
+
(resolvedFormat) => ({
|
|
11186
|
+
output: { ...serialized, response_format: resolvedFormat }
|
|
11187
|
+
})
|
|
11188
|
+
);
|
|
11189
|
+
} else {
|
|
11190
|
+
processed.output = serialized;
|
|
11191
|
+
}
|
|
11192
|
+
}
|
|
11193
|
+
if ("prepareCall" in processed && typeof processed.prepareCall === "function") {
|
|
11194
|
+
processed.prepareCall = "[Function]";
|
|
11195
|
+
}
|
|
11196
|
+
return { input: processed, outputPromise };
|
|
11197
|
+
};
|
|
11198
|
+
var processMessage = (message) => {
|
|
11199
|
+
if (!message || typeof message !== "object") return message;
|
|
11200
|
+
if (Array.isArray(message.content)) {
|
|
11201
|
+
return {
|
|
11202
|
+
...message,
|
|
11203
|
+
content: message.content.map(processContentPart)
|
|
11204
|
+
};
|
|
11205
|
+
}
|
|
11206
|
+
if (typeof message.content === "object" && message.content !== null) {
|
|
11207
|
+
return {
|
|
11208
|
+
...message,
|
|
11209
|
+
content: processContentPart(message.content)
|
|
11210
|
+
};
|
|
11211
|
+
}
|
|
11212
|
+
return message;
|
|
11213
|
+
};
|
|
11214
|
+
var processPromptContent = (prompt) => {
|
|
11215
|
+
if (Array.isArray(prompt)) {
|
|
11216
|
+
return prompt.map(processContentPart);
|
|
11217
|
+
}
|
|
11218
|
+
if (prompt.content) {
|
|
11219
|
+
if (Array.isArray(prompt.content)) {
|
|
11220
|
+
return {
|
|
11221
|
+
...prompt,
|
|
11222
|
+
content: prompt.content.map(processContentPart)
|
|
11223
|
+
};
|
|
11224
|
+
} else if (typeof prompt.content === "object") {
|
|
11225
|
+
return {
|
|
11226
|
+
...prompt,
|
|
11227
|
+
content: processContentPart(prompt.content)
|
|
11228
|
+
};
|
|
11229
|
+
}
|
|
11230
|
+
}
|
|
11231
|
+
return prompt;
|
|
11232
|
+
};
|
|
11233
|
+
var processContentPart = (part) => {
|
|
11234
|
+
if (!part || typeof part !== "object") return part;
|
|
11235
|
+
try {
|
|
11236
|
+
if (part.type === "image" && part.image) {
|
|
11237
|
+
const imageAttachment = convertImageToAttachment(
|
|
11238
|
+
part.image,
|
|
11239
|
+
part.mimeType || part.mediaType
|
|
11240
|
+
);
|
|
11241
|
+
if (imageAttachment) {
|
|
11242
|
+
return {
|
|
11243
|
+
...part,
|
|
11244
|
+
image: imageAttachment
|
|
11245
|
+
};
|
|
11246
|
+
}
|
|
11247
|
+
}
|
|
11248
|
+
if (part.type === "file" && part.data && (part.mimeType || part.mediaType)) {
|
|
11249
|
+
const fileAttachment = convertDataToAttachment(
|
|
11250
|
+
part.data,
|
|
11251
|
+
part.mimeType || part.mediaType,
|
|
11252
|
+
part.name || part.filename
|
|
11253
|
+
);
|
|
11254
|
+
if (fileAttachment) {
|
|
11255
|
+
return {
|
|
11256
|
+
...part,
|
|
11257
|
+
data: fileAttachment
|
|
11258
|
+
};
|
|
11259
|
+
}
|
|
11260
|
+
}
|
|
11261
|
+
if (part.type === "image_url" && part.image_url) {
|
|
11262
|
+
if (typeof part.image_url === "object" && part.image_url.url) {
|
|
11263
|
+
const imageAttachment = convertImageToAttachment(part.image_url.url);
|
|
11264
|
+
if (imageAttachment) {
|
|
11265
|
+
return {
|
|
11266
|
+
...part,
|
|
11267
|
+
image_url: {
|
|
11268
|
+
...part.image_url,
|
|
11269
|
+
url: imageAttachment
|
|
11270
|
+
}
|
|
11271
|
+
};
|
|
11272
|
+
}
|
|
11273
|
+
}
|
|
11274
|
+
}
|
|
11275
|
+
} catch (error) {
|
|
11276
|
+
console.warn("Error processing content part:", error);
|
|
11277
|
+
}
|
|
11278
|
+
return part;
|
|
11279
|
+
};
|
|
11280
|
+
var convertImageToAttachment = (image, explicitMimeType) => {
|
|
11281
|
+
try {
|
|
11282
|
+
if (typeof image === "string" && image.startsWith("data:")) {
|
|
11283
|
+
const [mimeTypeSection, base64Data] = image.split(",");
|
|
11284
|
+
const mimeType = mimeTypeSection.match(/data:(.*?);/)?.[1];
|
|
11285
|
+
if (mimeType && base64Data) {
|
|
11286
|
+
const blob = convertDataToBlob(base64Data, mimeType);
|
|
11287
|
+
if (blob) {
|
|
11288
|
+
return new Attachment({
|
|
11289
|
+
data: blob,
|
|
11290
|
+
filename: `image.${getExtensionFromMediaType(mimeType)}`,
|
|
11291
|
+
contentType: mimeType
|
|
11292
|
+
});
|
|
11293
|
+
}
|
|
11294
|
+
}
|
|
11295
|
+
}
|
|
11296
|
+
if (explicitMimeType) {
|
|
11297
|
+
if (image instanceof Uint8Array) {
|
|
11298
|
+
return new Attachment({
|
|
11299
|
+
data: new Blob([image], { type: explicitMimeType }),
|
|
11300
|
+
filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
|
|
11301
|
+
contentType: explicitMimeType
|
|
11302
|
+
});
|
|
11303
|
+
}
|
|
11304
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
|
|
11305
|
+
return new Attachment({
|
|
11306
|
+
data: new Blob([image], { type: explicitMimeType }),
|
|
11307
|
+
filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
|
|
11308
|
+
contentType: explicitMimeType
|
|
11309
|
+
});
|
|
11310
|
+
}
|
|
11311
|
+
}
|
|
11312
|
+
if (image instanceof Blob && image.type) {
|
|
11313
|
+
return new Attachment({
|
|
11314
|
+
data: image,
|
|
11315
|
+
filename: `image.${getExtensionFromMediaType(image.type)}`,
|
|
11316
|
+
contentType: image.type
|
|
11317
|
+
});
|
|
11318
|
+
}
|
|
11319
|
+
if (image instanceof Attachment) {
|
|
11320
|
+
return image;
|
|
11321
|
+
}
|
|
11322
|
+
} catch (error) {
|
|
11323
|
+
console.warn("Error converting image to attachment:", error);
|
|
11324
|
+
}
|
|
11325
|
+
return null;
|
|
11326
|
+
};
|
|
11327
|
+
var convertDataToAttachment = (data, mimeType, filename) => {
|
|
11328
|
+
if (!mimeType) return null;
|
|
11329
|
+
try {
|
|
11330
|
+
let blob = null;
|
|
11331
|
+
if (typeof data === "string" && data.startsWith("data:")) {
|
|
11332
|
+
const [, base64Data] = data.split(",");
|
|
11333
|
+
if (base64Data) {
|
|
11334
|
+
blob = convertDataToBlob(base64Data, mimeType);
|
|
11335
|
+
}
|
|
11336
|
+
} else if (typeof data === "string" && data.length > 0) {
|
|
11337
|
+
blob = convertDataToBlob(data, mimeType);
|
|
11338
|
+
} else if (data instanceof Uint8Array) {
|
|
11339
|
+
blob = new Blob([data], { type: mimeType });
|
|
11340
|
+
} else if (typeof Buffer !== "undefined" && Buffer.isBuffer(data)) {
|
|
11341
|
+
blob = new Blob([data], { type: mimeType });
|
|
11342
|
+
} else if (data instanceof Blob) {
|
|
11343
|
+
blob = data;
|
|
11344
|
+
}
|
|
11345
|
+
if (blob) {
|
|
11346
|
+
return new Attachment({
|
|
11347
|
+
data: blob,
|
|
11348
|
+
filename: filename || `file.${getExtensionFromMediaType(mimeType)}`,
|
|
11349
|
+
contentType: mimeType
|
|
11350
|
+
});
|
|
11351
|
+
}
|
|
11352
|
+
} catch (error) {
|
|
11353
|
+
console.warn("Error converting data to attachment:", error);
|
|
11354
|
+
}
|
|
11355
|
+
return null;
|
|
11356
|
+
};
|
|
11357
|
+
function processAISDKInput(params) {
|
|
11358
|
+
return processInputAttachmentsSync(params);
|
|
11359
|
+
}
|
|
11360
|
+
function prepareAISDKInput(params, event, span, defaultDenyOutputPaths) {
|
|
11361
|
+
const { input, outputPromise } = processAISDKInput(params);
|
|
11362
|
+
if (outputPromise && input && typeof input === "object") {
|
|
11363
|
+
outputPromise.then((resolvedData) => {
|
|
11364
|
+
span.log({
|
|
11365
|
+
input: {
|
|
11366
|
+
...input,
|
|
11367
|
+
...resolvedData
|
|
11368
|
+
}
|
|
11369
|
+
});
|
|
11370
|
+
}).catch(() => {
|
|
11371
|
+
});
|
|
11372
|
+
}
|
|
11373
|
+
const metadata = extractMetadataFromParams(params, event.self);
|
|
11374
|
+
const childTracing = prepareAISDKChildTracing(
|
|
11375
|
+
params,
|
|
11376
|
+
event.self,
|
|
11377
|
+
span,
|
|
11378
|
+
defaultDenyOutputPaths,
|
|
11379
|
+
event.aiSDK
|
|
11380
|
+
);
|
|
11381
|
+
event.modelWrapped = childTracing.modelWrapped;
|
|
11382
|
+
if (childTracing.cleanup) {
|
|
11383
|
+
event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
|
|
11384
|
+
}
|
|
11385
|
+
return {
|
|
11386
|
+
input,
|
|
11387
|
+
metadata
|
|
11388
|
+
};
|
|
11389
|
+
}
|
|
11390
|
+
function extractTopLevelAISDKMetrics(result, event, startTime) {
|
|
11391
|
+
const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics(result);
|
|
11392
|
+
if (startTime) {
|
|
11393
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
11394
|
+
}
|
|
11395
|
+
return metrics;
|
|
11396
|
+
}
|
|
11397
|
+
function hasModelChildTracing(event) {
|
|
11398
|
+
return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
|
|
11399
|
+
}
|
|
11400
|
+
function extractMetadataFromParams(params, self) {
|
|
11401
|
+
const metadata = {
|
|
11402
|
+
braintrust: {
|
|
11403
|
+
integration_name: "ai-sdk",
|
|
11404
|
+
sdk_language: "typescript"
|
|
11405
|
+
}
|
|
11406
|
+
};
|
|
11407
|
+
const agentModel = self && typeof self === "object" && "model" in self && self.model ? self.model : self && typeof self === "object" && "settings" in self && self.settings?.model ? self.settings?.model : void 0;
|
|
11408
|
+
const { model, provider } = serializeModelWithProvider(
|
|
11409
|
+
params.model ?? agentModel
|
|
11410
|
+
);
|
|
11411
|
+
if (model) {
|
|
11412
|
+
metadata.model = model;
|
|
11413
|
+
}
|
|
11414
|
+
if (provider) {
|
|
11415
|
+
metadata.provider = provider;
|
|
11416
|
+
}
|
|
11417
|
+
const tools = serializeAISDKToolsForLogging(params.tools);
|
|
11418
|
+
if (tools) {
|
|
11419
|
+
metadata.tools = tools;
|
|
11420
|
+
}
|
|
11421
|
+
return metadata;
|
|
11422
|
+
}
|
|
11423
|
+
function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK) {
|
|
11424
|
+
const cleanup = [];
|
|
11425
|
+
const patchedModels = /* @__PURE__ */ new WeakSet();
|
|
11426
|
+
const patchedTools = /* @__PURE__ */ new WeakSet();
|
|
11427
|
+
let modelWrapped = false;
|
|
11428
|
+
const patchModel = (model) => {
|
|
11429
|
+
const resolvedModel = resolveAISDKModel(model, aiSDK);
|
|
11430
|
+
if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function" || patchedModels.has(resolvedModel) || resolvedModel[AUTO_PATCHED_MODEL]) {
|
|
11431
|
+
return resolvedModel;
|
|
11432
|
+
}
|
|
11433
|
+
patchedModels.add(resolvedModel);
|
|
10999
11434
|
resolvedModel[AUTO_PATCHED_MODEL] = true;
|
|
11000
11435
|
modelWrapped = true;
|
|
11001
11436
|
const originalDoGenerate = resolvedModel.doGenerate;
|
|
@@ -11022,7 +11457,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
11022
11457
|
type: "llm" /* LLM */
|
|
11023
11458
|
},
|
|
11024
11459
|
event: {
|
|
11025
|
-
input: processAISDKInput(options),
|
|
11460
|
+
input: processAISDKInput(options).input,
|
|
11026
11461
|
metadata: baseMetadata
|
|
11027
11462
|
}
|
|
11028
11463
|
}
|
|
@@ -11036,7 +11471,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
11036
11471
|
type: "llm" /* LLM */
|
|
11037
11472
|
},
|
|
11038
11473
|
event: {
|
|
11039
|
-
input: processAISDKInput(options),
|
|
11474
|
+
input: processAISDKInput(options).input,
|
|
11040
11475
|
metadata: baseMetadata
|
|
11041
11476
|
}
|
|
11042
11477
|
});
|
|
@@ -11044,6 +11479,8 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
11044
11479
|
span,
|
|
11045
11480
|
() => Reflect.apply(originalDoStream, resolvedModel, [options])
|
|
11046
11481
|
);
|
|
11482
|
+
const streamStartTime = getCurrentUnixTimestamp();
|
|
11483
|
+
let firstChunkTime;
|
|
11047
11484
|
const output = {};
|
|
11048
11485
|
let text = "";
|
|
11049
11486
|
let reasoning = "";
|
|
@@ -11051,6 +11488,9 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
11051
11488
|
let object = void 0;
|
|
11052
11489
|
const transformStream = new TransformStream({
|
|
11053
11490
|
transform(chunk, controller) {
|
|
11491
|
+
if (firstChunkTime === void 0) {
|
|
11492
|
+
firstChunkTime = getCurrentUnixTimestamp();
|
|
11493
|
+
}
|
|
11054
11494
|
switch (chunk.type) {
|
|
11055
11495
|
case "text-delta":
|
|
11056
11496
|
text += extractTextDelta(chunk);
|
|
@@ -11091,12 +11531,19 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
11091
11531
|
if (object !== void 0) {
|
|
11092
11532
|
output.object = object;
|
|
11093
11533
|
}
|
|
11534
|
+
const metrics = extractTokenMetrics(output);
|
|
11535
|
+
if (firstChunkTime !== void 0) {
|
|
11536
|
+
metrics.time_to_first_token = Math.max(
|
|
11537
|
+
firstChunkTime - streamStartTime,
|
|
11538
|
+
1e-6
|
|
11539
|
+
);
|
|
11540
|
+
}
|
|
11094
11541
|
span.log({
|
|
11095
11542
|
output: processAISDKOutput(
|
|
11096
11543
|
output,
|
|
11097
11544
|
denyOutputPaths
|
|
11098
11545
|
),
|
|
11099
|
-
metrics
|
|
11546
|
+
metrics,
|
|
11100
11547
|
...buildResolvedMetadataPayload(output)
|
|
11101
11548
|
});
|
|
11102
11549
|
span.end();
|
|
@@ -11118,6 +11565,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
11118
11565
|
}
|
|
11119
11566
|
delete resolvedModel[AUTO_PATCHED_MODEL];
|
|
11120
11567
|
});
|
|
11568
|
+
return resolvedModel;
|
|
11121
11569
|
};
|
|
11122
11570
|
const patchTool = (tool, name) => {
|
|
11123
11571
|
if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool) || tool[AUTO_PATCHED_TOOL]) {
|
|
@@ -11190,17 +11638,26 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
11190
11638
|
}
|
|
11191
11639
|
};
|
|
11192
11640
|
if (params && typeof params === "object") {
|
|
11193
|
-
patchModel(params.model);
|
|
11641
|
+
const patchedParamModel = patchModel(params.model);
|
|
11642
|
+
if (typeof params.model === "string" && patchedParamModel && typeof patchedParamModel === "object") {
|
|
11643
|
+
params.model = patchedParamModel;
|
|
11644
|
+
}
|
|
11194
11645
|
patchTools(params.tools);
|
|
11195
11646
|
}
|
|
11196
11647
|
if (self && typeof self === "object") {
|
|
11197
11648
|
const selfRecord = self;
|
|
11198
11649
|
if (selfRecord.model !== void 0) {
|
|
11199
|
-
patchModel(selfRecord.model);
|
|
11650
|
+
const patchedSelfModel = patchModel(selfRecord.model);
|
|
11651
|
+
if (typeof selfRecord.model === "string" && patchedSelfModel && typeof patchedSelfModel === "object") {
|
|
11652
|
+
selfRecord.model = patchedSelfModel;
|
|
11653
|
+
}
|
|
11200
11654
|
}
|
|
11201
11655
|
if (selfRecord.settings && typeof selfRecord.settings === "object") {
|
|
11202
11656
|
if (selfRecord.settings.model !== void 0) {
|
|
11203
|
-
patchModel(selfRecord.settings.model);
|
|
11657
|
+
const patchedSettingsModel = patchModel(selfRecord.settings.model);
|
|
11658
|
+
if (typeof selfRecord.settings.model === "string" && patchedSettingsModel && typeof patchedSettingsModel === "object") {
|
|
11659
|
+
selfRecord.settings.model = patchedSettingsModel;
|
|
11660
|
+
}
|
|
11204
11661
|
}
|
|
11205
11662
|
if (selfRecord.settings.tools !== void 0) {
|
|
11206
11663
|
patchTools(selfRecord.settings.tools);
|
|
@@ -11224,63 +11681,173 @@ function finalizeAISDKChildTracing(event) {
|
|
|
11224
11681
|
}
|
|
11225
11682
|
}
|
|
11226
11683
|
function patchAISDKStreamingResult(args) {
|
|
11227
|
-
const {
|
|
11684
|
+
const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
|
|
11228
11685
|
if (!result || typeof result !== "object") {
|
|
11229
11686
|
return false;
|
|
11230
11687
|
}
|
|
11231
11688
|
const resultRecord = result;
|
|
11232
|
-
|
|
11689
|
+
attachKnownResultPromiseHandlers(resultRecord);
|
|
11690
|
+
if (isReadableStreamLike(resultRecord.baseStream)) {
|
|
11691
|
+
let firstChunkTime2;
|
|
11692
|
+
const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
|
|
11693
|
+
new TransformStream({
|
|
11694
|
+
transform(chunk, controller) {
|
|
11695
|
+
if (firstChunkTime2 === void 0) {
|
|
11696
|
+
firstChunkTime2 = getCurrentUnixTimestamp();
|
|
11697
|
+
}
|
|
11698
|
+
controller.enqueue(chunk);
|
|
11699
|
+
},
|
|
11700
|
+
async flush() {
|
|
11701
|
+
const metrics = extractTopLevelAISDKMetrics(result, endEvent);
|
|
11702
|
+
if (metrics.time_to_first_token === void 0 && firstChunkTime2 !== void 0) {
|
|
11703
|
+
metrics.time_to_first_token = firstChunkTime2 - startTime;
|
|
11704
|
+
}
|
|
11705
|
+
const output = await processAISDKStreamingOutput(
|
|
11706
|
+
result,
|
|
11707
|
+
resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
|
|
11708
|
+
);
|
|
11709
|
+
const metadata = buildResolvedMetadataPayload(result).metadata;
|
|
11710
|
+
span.log({
|
|
11711
|
+
output,
|
|
11712
|
+
...metadata ? { metadata } : {},
|
|
11713
|
+
metrics
|
|
11714
|
+
});
|
|
11715
|
+
finalizeAISDKChildTracing(endEvent);
|
|
11716
|
+
span.end();
|
|
11717
|
+
}
|
|
11718
|
+
})
|
|
11719
|
+
);
|
|
11720
|
+
Object.defineProperty(resultRecord, "baseStream", {
|
|
11721
|
+
configurable: true,
|
|
11722
|
+
enumerable: true,
|
|
11723
|
+
value: wrappedBaseStream,
|
|
11724
|
+
writable: true
|
|
11725
|
+
});
|
|
11726
|
+
return true;
|
|
11727
|
+
}
|
|
11728
|
+
const streamField = findAsyncIterableField(resultRecord, [
|
|
11729
|
+
"partialObjectStream",
|
|
11730
|
+
"textStream",
|
|
11731
|
+
"fullStream",
|
|
11732
|
+
"stream"
|
|
11733
|
+
]);
|
|
11734
|
+
if (!streamField) {
|
|
11233
11735
|
return false;
|
|
11234
11736
|
}
|
|
11235
11737
|
let firstChunkTime;
|
|
11236
|
-
const
|
|
11237
|
-
|
|
11238
|
-
|
|
11239
|
-
|
|
11240
|
-
firstChunkTime = getCurrentUnixTimestamp();
|
|
11241
|
-
}
|
|
11242
|
-
controller.enqueue(chunk);
|
|
11243
|
-
},
|
|
11244
|
-
async flush() {
|
|
11245
|
-
const metrics = extractTopLevelAISDKMetrics(result, endEvent);
|
|
11246
|
-
if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
|
|
11247
|
-
metrics.time_to_first_token = firstChunkTime - startTime;
|
|
11248
|
-
}
|
|
11249
|
-
const output = await processAISDKStreamingOutput(
|
|
11250
|
-
result,
|
|
11251
|
-
denyOutputPaths
|
|
11252
|
-
);
|
|
11253
|
-
const metadata = buildResolvedMetadataPayload(result).metadata;
|
|
11254
|
-
span.log({
|
|
11255
|
-
output,
|
|
11256
|
-
...metadata ? { metadata } : {},
|
|
11257
|
-
metrics
|
|
11258
|
-
});
|
|
11259
|
-
finalizeAISDKChildTracing(endEvent);
|
|
11260
|
-
span.end();
|
|
11738
|
+
const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
|
|
11739
|
+
onChunk: () => {
|
|
11740
|
+
if (firstChunkTime === void 0) {
|
|
11741
|
+
firstChunkTime = getCurrentUnixTimestamp();
|
|
11261
11742
|
}
|
|
11262
|
-
}
|
|
11263
|
-
|
|
11264
|
-
|
|
11743
|
+
},
|
|
11744
|
+
onComplete: async () => {
|
|
11745
|
+
const metrics = extractTopLevelAISDKMetrics(result, endEvent);
|
|
11746
|
+
if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
|
|
11747
|
+
metrics.time_to_first_token = firstChunkTime - startTime;
|
|
11748
|
+
}
|
|
11749
|
+
const output = await processAISDKStreamingOutput(
|
|
11750
|
+
result,
|
|
11751
|
+
resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
|
|
11752
|
+
);
|
|
11753
|
+
const metadata = buildResolvedMetadataPayload(result).metadata;
|
|
11754
|
+
span.log({
|
|
11755
|
+
output,
|
|
11756
|
+
...metadata ? { metadata } : {},
|
|
11757
|
+
metrics
|
|
11758
|
+
});
|
|
11759
|
+
finalizeAISDKChildTracing(endEvent);
|
|
11760
|
+
span.end();
|
|
11761
|
+
},
|
|
11762
|
+
onError: (error) => {
|
|
11763
|
+
span.log({
|
|
11764
|
+
error: error.message
|
|
11765
|
+
});
|
|
11766
|
+
finalizeAISDKChildTracing(endEvent);
|
|
11767
|
+
span.end();
|
|
11768
|
+
}
|
|
11769
|
+
});
|
|
11770
|
+
Object.defineProperty(resultRecord, streamField.field, {
|
|
11265
11771
|
configurable: true,
|
|
11266
11772
|
enumerable: true,
|
|
11267
|
-
value:
|
|
11773
|
+
value: wrappedStream,
|
|
11268
11774
|
writable: true
|
|
11269
11775
|
});
|
|
11270
11776
|
return true;
|
|
11271
11777
|
}
|
|
11778
|
+
function attachKnownResultPromiseHandlers(result) {
|
|
11779
|
+
const promiseLikeFields = [
|
|
11780
|
+
"content",
|
|
11781
|
+
"text",
|
|
11782
|
+
"object",
|
|
11783
|
+
"finishReason",
|
|
11784
|
+
"usage",
|
|
11785
|
+
"totalUsage",
|
|
11786
|
+
"steps"
|
|
11787
|
+
];
|
|
11788
|
+
for (const field of promiseLikeFields) {
|
|
11789
|
+
try {
|
|
11790
|
+
if (!(field in result)) {
|
|
11791
|
+
continue;
|
|
11792
|
+
}
|
|
11793
|
+
const value = result[field];
|
|
11794
|
+
if (isPromiseLike(value)) {
|
|
11795
|
+
void Promise.resolve(value).catch(() => {
|
|
11796
|
+
});
|
|
11797
|
+
}
|
|
11798
|
+
} catch {
|
|
11799
|
+
}
|
|
11800
|
+
}
|
|
11801
|
+
}
|
|
11272
11802
|
function isReadableStreamLike(value) {
|
|
11273
11803
|
return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
|
|
11274
11804
|
}
|
|
11805
|
+
function isAsyncIterableLike(value) {
|
|
11806
|
+
return value != null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
|
|
11807
|
+
}
|
|
11808
|
+
function findAsyncIterableField(result, candidateFields) {
|
|
11809
|
+
for (const field of candidateFields) {
|
|
11810
|
+
try {
|
|
11811
|
+
const stream = result[field];
|
|
11812
|
+
if (isAsyncIterableLike(stream)) {
|
|
11813
|
+
return { field, stream };
|
|
11814
|
+
}
|
|
11815
|
+
} catch {
|
|
11816
|
+
}
|
|
11817
|
+
}
|
|
11818
|
+
return null;
|
|
11819
|
+
}
|
|
11820
|
+
function createPatchedAsyncIterable(stream, hooks) {
|
|
11821
|
+
return {
|
|
11822
|
+
async *[Symbol.asyncIterator]() {
|
|
11823
|
+
try {
|
|
11824
|
+
for await (const chunk of stream) {
|
|
11825
|
+
hooks.onChunk(chunk);
|
|
11826
|
+
yield chunk;
|
|
11827
|
+
}
|
|
11828
|
+
await hooks.onComplete();
|
|
11829
|
+
} catch (error) {
|
|
11830
|
+
hooks.onError(
|
|
11831
|
+
error instanceof Error ? error : new Error(String(error))
|
|
11832
|
+
);
|
|
11833
|
+
throw error;
|
|
11834
|
+
}
|
|
11835
|
+
}
|
|
11836
|
+
};
|
|
11837
|
+
}
|
|
11275
11838
|
async function processAISDKStreamingOutput(result, denyOutputPaths) {
|
|
11276
11839
|
const output = processAISDKOutput(result, denyOutputPaths);
|
|
11277
11840
|
if (!output || typeof output !== "object") {
|
|
11278
11841
|
return output;
|
|
11279
11842
|
}
|
|
11280
11843
|
const outputRecord = output;
|
|
11844
|
+
const isObjectStreamingResult = result != null && typeof result === "object" && "partialObjectStream" in result;
|
|
11281
11845
|
try {
|
|
11282
|
-
if ("text" in result
|
|
11283
|
-
|
|
11846
|
+
if (!isObjectStreamingResult && "text" in result) {
|
|
11847
|
+
const resolvedText = await Promise.resolve(result.text);
|
|
11848
|
+
if (typeof resolvedText === "string") {
|
|
11849
|
+
outputRecord.text = resolvedText;
|
|
11850
|
+
}
|
|
11284
11851
|
}
|
|
11285
11852
|
} catch {
|
|
11286
11853
|
}
|
|
@@ -11293,6 +11860,15 @@ async function processAISDKStreamingOutput(result, denyOutputPaths) {
|
|
|
11293
11860
|
}
|
|
11294
11861
|
} catch {
|
|
11295
11862
|
}
|
|
11863
|
+
try {
|
|
11864
|
+
if ("finishReason" in result) {
|
|
11865
|
+
const resolvedFinishReason = await Promise.resolve(result.finishReason);
|
|
11866
|
+
if (resolvedFinishReason !== void 0) {
|
|
11867
|
+
outputRecord.finishReason = resolvedFinishReason;
|
|
11868
|
+
}
|
|
11869
|
+
}
|
|
11870
|
+
} catch {
|
|
11871
|
+
}
|
|
11296
11872
|
return outputRecord;
|
|
11297
11873
|
}
|
|
11298
11874
|
function buildAISDKChildMetadata(model) {
|
|
@@ -11315,16 +11891,25 @@ function buildResolvedMetadataPayload(result) {
|
|
|
11315
11891
|
if (gatewayInfo?.model) {
|
|
11316
11892
|
metadata.model = gatewayInfo.model;
|
|
11317
11893
|
}
|
|
11318
|
-
|
|
11319
|
-
|
|
11894
|
+
let finishReason;
|
|
11895
|
+
try {
|
|
11896
|
+
finishReason = result.finishReason;
|
|
11897
|
+
} catch {
|
|
11898
|
+
finishReason = void 0;
|
|
11899
|
+
}
|
|
11900
|
+
if (isPromiseLike(finishReason)) {
|
|
11901
|
+
void Promise.resolve(finishReason).catch(() => {
|
|
11902
|
+
});
|
|
11903
|
+
} else if (finishReason !== void 0) {
|
|
11904
|
+
metadata.finish_reason = finishReason;
|
|
11320
11905
|
}
|
|
11321
11906
|
return Object.keys(metadata).length > 0 ? { metadata } : {};
|
|
11322
11907
|
}
|
|
11323
|
-
function resolveAISDKModel(model) {
|
|
11908
|
+
function resolveAISDKModel(model, aiSDK) {
|
|
11324
11909
|
if (typeof model !== "string") {
|
|
11325
11910
|
return model;
|
|
11326
11911
|
}
|
|
11327
|
-
const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? null;
|
|
11912
|
+
const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? aiSDK?.gateway ?? null;
|
|
11328
11913
|
if (provider && typeof provider.languageModel === "function") {
|
|
11329
11914
|
return provider.languageModel(model);
|
|
11330
11915
|
}
|
|
@@ -11347,15 +11932,15 @@ function processAISDKOutput(output, denyOutputPaths) {
|
|
|
11347
11932
|
}
|
|
11348
11933
|
function extractTokenMetrics(result) {
|
|
11349
11934
|
const metrics = {};
|
|
11350
|
-
let usage
|
|
11351
|
-
|
|
11352
|
-
|
|
11353
|
-
|
|
11354
|
-
|
|
11355
|
-
|
|
11356
|
-
|
|
11357
|
-
|
|
11358
|
-
|
|
11935
|
+
let usage;
|
|
11936
|
+
const totalUsageValue = safeResultFieldRead(result, "totalUsage");
|
|
11937
|
+
if (totalUsageValue !== void 0 && !isPromiseLike(totalUsageValue)) {
|
|
11938
|
+
usage = totalUsageValue;
|
|
11939
|
+
}
|
|
11940
|
+
if (!usage) {
|
|
11941
|
+
const usageValue = safeResultFieldRead(result, "usage");
|
|
11942
|
+
if (usageValue !== void 0 && !isPromiseLike(usageValue)) {
|
|
11943
|
+
usage = usageValue;
|
|
11359
11944
|
}
|
|
11360
11945
|
}
|
|
11361
11946
|
if (!usage) {
|
|
@@ -11393,25 +11978,45 @@ function extractTokenMetrics(result) {
|
|
|
11393
11978
|
}
|
|
11394
11979
|
return metrics;
|
|
11395
11980
|
}
|
|
11396
|
-
function
|
|
11397
|
-
|
|
11398
|
-
|
|
11399
|
-
|
|
11400
|
-
|
|
11401
|
-
|
|
11402
|
-
|
|
11403
|
-
|
|
11404
|
-
|
|
11405
|
-
|
|
11406
|
-
}
|
|
11407
|
-
|
|
11408
|
-
|
|
11981
|
+
function safeResultFieldRead(result, field) {
|
|
11982
|
+
return safeSerializableFieldRead(result, field);
|
|
11983
|
+
}
|
|
11984
|
+
function safeSerializableFieldRead(obj, field) {
|
|
11985
|
+
try {
|
|
11986
|
+
const value = obj?.[field];
|
|
11987
|
+
if (isPromiseLike(value)) {
|
|
11988
|
+
void Promise.resolve(value).catch(() => {
|
|
11989
|
+
});
|
|
11990
|
+
return void 0;
|
|
11991
|
+
}
|
|
11992
|
+
return value;
|
|
11993
|
+
} catch {
|
|
11994
|
+
return void 0;
|
|
11995
|
+
}
|
|
11996
|
+
}
|
|
11997
|
+
function aggregateAISDKChunks(chunks, _result, endEvent) {
|
|
11998
|
+
const lastChunk = chunks[chunks.length - 1];
|
|
11999
|
+
const output = {};
|
|
12000
|
+
let metrics = {};
|
|
12001
|
+
let metadata;
|
|
12002
|
+
if (lastChunk) {
|
|
12003
|
+
metrics = hasModelChildTracing(endEvent) ? {} : extractTokenMetrics(lastChunk);
|
|
12004
|
+
metadata = buildResolvedMetadataPayload(lastChunk).metadata;
|
|
12005
|
+
const text = safeSerializableFieldRead(lastChunk, "text");
|
|
12006
|
+
if (text !== void 0) {
|
|
12007
|
+
output.text = text;
|
|
11409
12008
|
}
|
|
11410
|
-
|
|
11411
|
-
|
|
12009
|
+
const objectValue = safeSerializableFieldRead(lastChunk, "object");
|
|
12010
|
+
if (objectValue !== void 0) {
|
|
12011
|
+
output.object = objectValue;
|
|
11412
12012
|
}
|
|
11413
|
-
|
|
11414
|
-
|
|
12013
|
+
const finishReason = safeSerializableFieldRead(lastChunk, "finishReason");
|
|
12014
|
+
if (finishReason !== void 0) {
|
|
12015
|
+
output.finishReason = finishReason;
|
|
12016
|
+
}
|
|
12017
|
+
const toolCalls = safeSerializableFieldRead(lastChunk, "toolCalls");
|
|
12018
|
+
if (toolCalls !== void 0) {
|
|
12019
|
+
output.toolCalls = toolCalls;
|
|
11415
12020
|
}
|
|
11416
12021
|
}
|
|
11417
12022
|
finalizeAISDKChildTracing(endEvent);
|
|
@@ -11420,6 +12025,7 @@ function aggregateAISDKChunks(chunks, _result, endEvent) {
|
|
|
11420
12025
|
function extractGetterValues(obj) {
|
|
11421
12026
|
const getterValues = {};
|
|
11422
12027
|
const getterNames = [
|
|
12028
|
+
"content",
|
|
11423
12029
|
"text",
|
|
11424
12030
|
"object",
|
|
11425
12031
|
"finishReason",
|
|
@@ -11435,8 +12041,17 @@ function extractGetterValues(obj) {
|
|
|
11435
12041
|
];
|
|
11436
12042
|
for (const name of getterNames) {
|
|
11437
12043
|
try {
|
|
11438
|
-
if (obj
|
|
11439
|
-
|
|
12044
|
+
if (!obj || !(name in obj)) {
|
|
12045
|
+
continue;
|
|
12046
|
+
}
|
|
12047
|
+
const value = obj[name];
|
|
12048
|
+
if (isPromiseLike(value)) {
|
|
12049
|
+
void Promise.resolve(value).catch(() => {
|
|
12050
|
+
});
|
|
12051
|
+
continue;
|
|
12052
|
+
}
|
|
12053
|
+
if (isSerializableOutputValue(value)) {
|
|
12054
|
+
getterValues[name] = value;
|
|
11440
12055
|
}
|
|
11441
12056
|
} catch {
|
|
11442
12057
|
}
|
|
@@ -11458,6 +12073,11 @@ function extractSerializableOutputFields(output) {
|
|
|
11458
12073
|
for (const name of directFieldNames) {
|
|
11459
12074
|
try {
|
|
11460
12075
|
const value = output?.[name];
|
|
12076
|
+
if (isPromiseLike(value)) {
|
|
12077
|
+
void Promise.resolve(value).catch(() => {
|
|
12078
|
+
});
|
|
12079
|
+
continue;
|
|
12080
|
+
}
|
|
11461
12081
|
if (isSerializableOutputValue(value)) {
|
|
11462
12082
|
serialized[name] = value;
|
|
11463
12083
|
}
|
|
@@ -11469,6 +12089,9 @@ function extractSerializableOutputFields(output) {
|
|
|
11469
12089
|
...extractGetterValues(output)
|
|
11470
12090
|
};
|
|
11471
12091
|
}
|
|
12092
|
+
function isPromiseLike(value) {
|
|
12093
|
+
return value != null && typeof value === "object" && typeof value.then === "function";
|
|
12094
|
+
}
|
|
11472
12095
|
function isSerializableOutputValue(value) {
|
|
11473
12096
|
if (typeof value === "function") {
|
|
11474
12097
|
return false;
|
|
@@ -11510,8 +12133,9 @@ function parseGatewayModelString(modelString) {
|
|
|
11510
12133
|
return { model: modelString };
|
|
11511
12134
|
}
|
|
11512
12135
|
function extractGatewayRoutingInfo(result) {
|
|
11513
|
-
|
|
11514
|
-
|
|
12136
|
+
const steps = safeSerializableFieldRead(result, "steps");
|
|
12137
|
+
if (Array.isArray(steps) && steps.length > 0) {
|
|
12138
|
+
const routing2 = steps[0]?.providerMetadata?.gateway?.routing;
|
|
11515
12139
|
if (routing2) {
|
|
11516
12140
|
return {
|
|
11517
12141
|
provider: routing2.resolvedProvider || routing2.finalProvider,
|
|
@@ -11519,7 +12143,11 @@ function extractGatewayRoutingInfo(result) {
|
|
|
11519
12143
|
};
|
|
11520
12144
|
}
|
|
11521
12145
|
}
|
|
11522
|
-
const
|
|
12146
|
+
const providerMetadata = safeSerializableFieldRead(
|
|
12147
|
+
result,
|
|
12148
|
+
"providerMetadata"
|
|
12149
|
+
);
|
|
12150
|
+
const routing = providerMetadata?.gateway?.routing;
|
|
11523
12151
|
if (routing) {
|
|
11524
12152
|
return {
|
|
11525
12153
|
provider: routing.resolvedProvider || routing.finalProvider,
|
|
@@ -11529,10 +12157,11 @@ function extractGatewayRoutingInfo(result) {
|
|
|
11529
12157
|
return null;
|
|
11530
12158
|
}
|
|
11531
12159
|
function extractCostFromResult(result) {
|
|
11532
|
-
|
|
12160
|
+
const steps = safeSerializableFieldRead(result, "steps");
|
|
12161
|
+
if (Array.isArray(steps) && steps.length > 0) {
|
|
11533
12162
|
let totalCost = 0;
|
|
11534
12163
|
let foundCost = false;
|
|
11535
|
-
for (const step of
|
|
12164
|
+
for (const step of steps) {
|
|
11536
12165
|
const gateway2 = step?.providerMetadata?.gateway;
|
|
11537
12166
|
const stepCost = parseGatewayCost(gateway2?.cost) || parseGatewayCost(gateway2?.marketCost);
|
|
11538
12167
|
if (stepCost !== void 0 && stepCost > 0) {
|
|
@@ -11544,7 +12173,11 @@ function extractCostFromResult(result) {
|
|
|
11544
12173
|
return totalCost;
|
|
11545
12174
|
}
|
|
11546
12175
|
}
|
|
11547
|
-
const
|
|
12176
|
+
const providerMetadata = safeSerializableFieldRead(
|
|
12177
|
+
result,
|
|
12178
|
+
"providerMetadata"
|
|
12179
|
+
);
|
|
12180
|
+
const gateway = providerMetadata?.gateway;
|
|
11548
12181
|
const directCost = parseGatewayCost(gateway?.cost) || parseGatewayCost(gateway?.marketCost);
|
|
11549
12182
|
if (directCost !== void 0 && directCost > 0) {
|
|
11550
12183
|
return directCost;
|
|
@@ -11656,12 +12289,15 @@ var claudeAgentSDKChannels = defineChannels(
|
|
|
11656
12289
|
{
|
|
11657
12290
|
query: channel({
|
|
11658
12291
|
channelName: "query",
|
|
11659
|
-
kind: "
|
|
12292
|
+
kind: "sync-stream"
|
|
11660
12293
|
})
|
|
11661
12294
|
}
|
|
11662
12295
|
);
|
|
11663
12296
|
|
|
11664
12297
|
// src/instrumentation/plugins/claude-agent-sdk-plugin.ts
|
|
12298
|
+
function isSubAgentToolName(toolName) {
|
|
12299
|
+
return toolName === "Agent" || toolName === "Task";
|
|
12300
|
+
}
|
|
11665
12301
|
function filterSerializableOptions(options) {
|
|
11666
12302
|
const allowedKeys = [
|
|
11667
12303
|
"model",
|
|
@@ -11715,34 +12351,50 @@ function extractUsageFromMessage(message) {
|
|
|
11715
12351
|
const cacheReadTokens = getNumberProperty(usage, "cache_read_input_tokens") || 0;
|
|
11716
12352
|
const cacheCreationTokens = getNumberProperty(usage, "cache_creation_input_tokens") || 0;
|
|
11717
12353
|
if (cacheReadTokens > 0 || cacheCreationTokens > 0) {
|
|
11718
|
-
|
|
11719
|
-
|
|
11720
|
-
cacheCreationTokens
|
|
12354
|
+
Object.assign(
|
|
12355
|
+
metrics,
|
|
12356
|
+
extractAnthropicCacheTokens(cacheReadTokens, cacheCreationTokens)
|
|
11721
12357
|
);
|
|
11722
|
-
Object.assign(metrics, cacheTokens);
|
|
11723
12358
|
}
|
|
11724
12359
|
if (Object.keys(metrics).length > 0) {
|
|
11725
12360
|
Object.assign(metrics, finalizeAnthropicTokens(metrics));
|
|
11726
12361
|
}
|
|
11727
12362
|
return metrics;
|
|
11728
12363
|
}
|
|
11729
|
-
function buildLLMInput(prompt, conversationHistory) {
|
|
11730
|
-
const
|
|
11731
|
-
|
|
11732
|
-
|
|
11733
|
-
|
|
11734
|
-
|
|
12364
|
+
function buildLLMInput(prompt, conversationHistory, capturedPromptMessages) {
|
|
12365
|
+
const promptMessages = [];
|
|
12366
|
+
if (typeof prompt === "string") {
|
|
12367
|
+
promptMessages.push({ content: prompt, role: "user" });
|
|
12368
|
+
} else if (capturedPromptMessages && capturedPromptMessages.length > 0) {
|
|
12369
|
+
for (const msg of capturedPromptMessages) {
|
|
12370
|
+
const role = msg.message?.role;
|
|
12371
|
+
const content = msg.message?.content;
|
|
12372
|
+
if (role && content !== void 0) {
|
|
12373
|
+
promptMessages.push({ content, role });
|
|
12374
|
+
}
|
|
12375
|
+
}
|
|
12376
|
+
}
|
|
12377
|
+
const inputParts = [...promptMessages, ...conversationHistory];
|
|
11735
12378
|
return inputParts.length > 0 ? inputParts : void 0;
|
|
11736
12379
|
}
|
|
11737
|
-
|
|
11738
|
-
|
|
12380
|
+
function formatCapturedMessages(messages) {
|
|
12381
|
+
return messages.length > 0 ? messages : [];
|
|
12382
|
+
}
|
|
12383
|
+
async function createLLMSpanForMessages(messages, prompt, conversationHistory, options, startTime, capturedPromptMessages, parentSpan) {
|
|
12384
|
+
if (messages.length === 0) {
|
|
12385
|
+
return void 0;
|
|
12386
|
+
}
|
|
11739
12387
|
const lastMessage = messages[messages.length - 1];
|
|
11740
12388
|
if (lastMessage.type !== "assistant" || !lastMessage.message?.usage) {
|
|
11741
12389
|
return void 0;
|
|
11742
12390
|
}
|
|
11743
12391
|
const model = lastMessage.message.model || options.model;
|
|
11744
12392
|
const usage = extractUsageFromMessage(lastMessage);
|
|
11745
|
-
const input = buildLLMInput(
|
|
12393
|
+
const input = buildLLMInput(
|
|
12394
|
+
prompt,
|
|
12395
|
+
conversationHistory,
|
|
12396
|
+
capturedPromptMessages
|
|
12397
|
+
);
|
|
11746
12398
|
const outputs = messages.map(
|
|
11747
12399
|
(m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
|
|
11748
12400
|
).filter(
|
|
@@ -11750,21 +12402,359 @@ async function createLLMSpanForMessages(messages, prompt, conversationHistory, o
|
|
|
11750
12402
|
);
|
|
11751
12403
|
const span = startSpan({
|
|
11752
12404
|
name: "anthropic.messages.create",
|
|
12405
|
+
parent: parentSpan,
|
|
11753
12406
|
spanAttributes: {
|
|
11754
12407
|
type: "llm" /* LLM */
|
|
11755
12408
|
},
|
|
11756
|
-
startTime
|
|
11757
|
-
parent: parentSpan
|
|
12409
|
+
startTime
|
|
11758
12410
|
});
|
|
11759
12411
|
span.log({
|
|
11760
12412
|
input,
|
|
11761
|
-
output: outputs,
|
|
11762
12413
|
metadata: model ? { model } : void 0,
|
|
11763
|
-
metrics: usage
|
|
12414
|
+
metrics: usage,
|
|
12415
|
+
output: outputs
|
|
11764
12416
|
});
|
|
11765
12417
|
await span.end();
|
|
11766
12418
|
return lastMessage.message?.content && lastMessage.message?.role ? { content: lastMessage.message.content, role: lastMessage.message.role } : void 0;
|
|
11767
12419
|
}
|
|
12420
|
+
function getMcpServerMetadata(serverName, mcpServers) {
|
|
12421
|
+
if (!serverName || !mcpServers) {
|
|
12422
|
+
return {};
|
|
12423
|
+
}
|
|
12424
|
+
const serverConfig = mcpServers[serverName];
|
|
12425
|
+
if (!serverConfig) {
|
|
12426
|
+
return {};
|
|
12427
|
+
}
|
|
12428
|
+
const metadata = {};
|
|
12429
|
+
if (serverConfig.type) {
|
|
12430
|
+
metadata["mcp.type"] = serverConfig.type;
|
|
12431
|
+
} else if (typeof serverConfig === "object" && "transport" in serverConfig) {
|
|
12432
|
+
metadata["mcp.type"] = "sdk";
|
|
12433
|
+
}
|
|
12434
|
+
if (serverConfig.url) {
|
|
12435
|
+
metadata["mcp.url"] = serverConfig.url;
|
|
12436
|
+
}
|
|
12437
|
+
if (serverConfig.command) {
|
|
12438
|
+
metadata["mcp.command"] = serverConfig.command;
|
|
12439
|
+
if (serverConfig.args) {
|
|
12440
|
+
metadata["mcp.args"] = serverConfig.args.join(" ");
|
|
12441
|
+
}
|
|
12442
|
+
}
|
|
12443
|
+
return metadata;
|
|
12444
|
+
}
|
|
12445
|
+
function parseToolName(rawToolName) {
|
|
12446
|
+
const mcpMatch = rawToolName.match(/^mcp__([^_]+)__(.+)$/);
|
|
12447
|
+
if (mcpMatch) {
|
|
12448
|
+
const [, mcpServer, toolName] = mcpMatch;
|
|
12449
|
+
return {
|
|
12450
|
+
displayName: `tool: ${mcpServer}/${toolName}`,
|
|
12451
|
+
mcpServer,
|
|
12452
|
+
rawToolName,
|
|
12453
|
+
toolName
|
|
12454
|
+
};
|
|
12455
|
+
}
|
|
12456
|
+
return {
|
|
12457
|
+
displayName: `tool: ${rawToolName}`,
|
|
12458
|
+
rawToolName,
|
|
12459
|
+
toolName: rawToolName
|
|
12460
|
+
};
|
|
12461
|
+
}
|
|
12462
|
+
function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, subAgentSpans, endedSubAgentSpans) {
|
|
12463
|
+
const preToolUse = async (input, toolUseID) => {
|
|
12464
|
+
if (input.hook_event_name !== "PreToolUse" || !toolUseID) {
|
|
12465
|
+
return {};
|
|
12466
|
+
}
|
|
12467
|
+
if (isSubAgentToolName(input.tool_name)) {
|
|
12468
|
+
return {};
|
|
12469
|
+
}
|
|
12470
|
+
const parsed = parseToolName(input.tool_name);
|
|
12471
|
+
const toolSpan = startSpan({
|
|
12472
|
+
event: {
|
|
12473
|
+
input: input.tool_input,
|
|
12474
|
+
metadata: {
|
|
12475
|
+
"claude_agent_sdk.cwd": input.cwd,
|
|
12476
|
+
"claude_agent_sdk.raw_tool_name": parsed.rawToolName,
|
|
12477
|
+
"claude_agent_sdk.session_id": input.session_id,
|
|
12478
|
+
"gen_ai.tool.call.id": toolUseID,
|
|
12479
|
+
"gen_ai.tool.name": parsed.toolName,
|
|
12480
|
+
...parsed.mcpServer && { "mcp.server": parsed.mcpServer },
|
|
12481
|
+
...getMcpServerMetadata(parsed.mcpServer, mcpServers)
|
|
12482
|
+
}
|
|
12483
|
+
},
|
|
12484
|
+
name: parsed.displayName,
|
|
12485
|
+
parent: await resolveParentSpan(toolUseID),
|
|
12486
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
12487
|
+
});
|
|
12488
|
+
activeToolSpans.set(toolUseID, toolSpan);
|
|
12489
|
+
return {};
|
|
12490
|
+
};
|
|
12491
|
+
const postToolUse = async (input, toolUseID) => {
|
|
12492
|
+
if (input.hook_event_name !== "PostToolUse" || !toolUseID) {
|
|
12493
|
+
return {};
|
|
12494
|
+
}
|
|
12495
|
+
const subAgentSpan = subAgentSpans.get(toolUseID);
|
|
12496
|
+
if (subAgentSpan) {
|
|
12497
|
+
try {
|
|
12498
|
+
const response = input.tool_response;
|
|
12499
|
+
const metadata = {};
|
|
12500
|
+
if (response?.status) {
|
|
12501
|
+
metadata["claude_agent_sdk.status"] = response.status;
|
|
12502
|
+
}
|
|
12503
|
+
if (response?.totalDurationMs) {
|
|
12504
|
+
metadata["claude_agent_sdk.duration_ms"] = response.totalDurationMs;
|
|
12505
|
+
}
|
|
12506
|
+
if (response?.totalToolUseCount !== void 0) {
|
|
12507
|
+
metadata["claude_agent_sdk.tool_use_count"] = response.totalToolUseCount;
|
|
12508
|
+
}
|
|
12509
|
+
subAgentSpan.log({
|
|
12510
|
+
metadata,
|
|
12511
|
+
output: response?.content
|
|
12512
|
+
});
|
|
12513
|
+
} finally {
|
|
12514
|
+
subAgentSpan.end();
|
|
12515
|
+
endedSubAgentSpans.add(toolUseID);
|
|
12516
|
+
}
|
|
12517
|
+
return {};
|
|
12518
|
+
}
|
|
12519
|
+
const toolSpan = activeToolSpans.get(toolUseID);
|
|
12520
|
+
if (!toolSpan) {
|
|
12521
|
+
return {};
|
|
12522
|
+
}
|
|
12523
|
+
try {
|
|
12524
|
+
toolSpan.log({ output: input.tool_response });
|
|
12525
|
+
} finally {
|
|
12526
|
+
toolSpan.end();
|
|
12527
|
+
activeToolSpans.delete(toolUseID);
|
|
12528
|
+
}
|
|
12529
|
+
return {};
|
|
12530
|
+
};
|
|
12531
|
+
const postToolUseFailure = async (input, toolUseID) => {
|
|
12532
|
+
if (input.hook_event_name !== "PostToolUseFailure" || !toolUseID) {
|
|
12533
|
+
return {};
|
|
12534
|
+
}
|
|
12535
|
+
const subAgentSpan = subAgentSpans.get(toolUseID);
|
|
12536
|
+
if (subAgentSpan) {
|
|
12537
|
+
try {
|
|
12538
|
+
subAgentSpan.log({ error: input.error });
|
|
12539
|
+
} finally {
|
|
12540
|
+
subAgentSpan.end();
|
|
12541
|
+
endedSubAgentSpans.add(toolUseID);
|
|
12542
|
+
}
|
|
12543
|
+
return {};
|
|
12544
|
+
}
|
|
12545
|
+
const toolSpan = activeToolSpans.get(toolUseID);
|
|
12546
|
+
if (!toolSpan) {
|
|
12547
|
+
return {};
|
|
12548
|
+
}
|
|
12549
|
+
const parsed = parseToolName(input.tool_name);
|
|
12550
|
+
try {
|
|
12551
|
+
toolSpan.log({
|
|
12552
|
+
error: input.error,
|
|
12553
|
+
metadata: {
|
|
12554
|
+
"claude_agent_sdk.is_interrupt": input.is_interrupt,
|
|
12555
|
+
"claude_agent_sdk.session_id": input.session_id,
|
|
12556
|
+
"gen_ai.tool.call.id": toolUseID,
|
|
12557
|
+
"gen_ai.tool.name": parsed.toolName,
|
|
12558
|
+
...parsed.mcpServer && { "mcp.server": parsed.mcpServer }
|
|
12559
|
+
}
|
|
12560
|
+
});
|
|
12561
|
+
} finally {
|
|
12562
|
+
toolSpan.end();
|
|
12563
|
+
activeToolSpans.delete(toolUseID);
|
|
12564
|
+
}
|
|
12565
|
+
return {};
|
|
12566
|
+
};
|
|
12567
|
+
return { postToolUse, postToolUseFailure, preToolUse };
|
|
12568
|
+
}
|
|
12569
|
+
function injectTracingHooks(options, resolveParentSpan, activeToolSpans, subAgentSpans, endedSubAgentSpans) {
|
|
12570
|
+
const { preToolUse, postToolUse, postToolUseFailure } = createToolTracingHooks(
|
|
12571
|
+
resolveParentSpan,
|
|
12572
|
+
activeToolSpans,
|
|
12573
|
+
options.mcpServers,
|
|
12574
|
+
subAgentSpans,
|
|
12575
|
+
endedSubAgentSpans
|
|
12576
|
+
);
|
|
12577
|
+
const existingHooks = options.hooks ?? {};
|
|
12578
|
+
return {
|
|
12579
|
+
...options,
|
|
12580
|
+
hooks: {
|
|
12581
|
+
...existingHooks,
|
|
12582
|
+
PostToolUse: [
|
|
12583
|
+
...existingHooks.PostToolUse ?? [],
|
|
12584
|
+
{ hooks: [postToolUse] }
|
|
12585
|
+
],
|
|
12586
|
+
PostToolUseFailure: [
|
|
12587
|
+
...existingHooks.PostToolUseFailure ?? [],
|
|
12588
|
+
{
|
|
12589
|
+
hooks: [postToolUseFailure]
|
|
12590
|
+
}
|
|
12591
|
+
],
|
|
12592
|
+
PreToolUse: [
|
|
12593
|
+
...existingHooks.PreToolUse ?? [],
|
|
12594
|
+
{ hooks: [preToolUse] }
|
|
12595
|
+
]
|
|
12596
|
+
}
|
|
12597
|
+
};
|
|
12598
|
+
}
|
|
12599
|
+
async function finalizeCurrentMessageGroup(state) {
|
|
12600
|
+
if (state.currentMessages.length === 0) {
|
|
12601
|
+
return;
|
|
12602
|
+
}
|
|
12603
|
+
const parentToolUseId = state.currentMessages[0]?.parent_tool_use_id ?? null;
|
|
12604
|
+
let parentSpan = await state.span.export();
|
|
12605
|
+
if (parentToolUseId) {
|
|
12606
|
+
const subAgentSpan = state.subAgentSpans.get(parentToolUseId);
|
|
12607
|
+
if (subAgentSpan) {
|
|
12608
|
+
parentSpan = await subAgentSpan.export();
|
|
12609
|
+
}
|
|
12610
|
+
}
|
|
12611
|
+
const finalMessage = await createLLMSpanForMessages(
|
|
12612
|
+
state.currentMessages,
|
|
12613
|
+
state.originalPrompt,
|
|
12614
|
+
state.finalResults,
|
|
12615
|
+
state.options,
|
|
12616
|
+
state.currentMessageStartTime,
|
|
12617
|
+
state.capturedPromptMessages,
|
|
12618
|
+
parentSpan
|
|
12619
|
+
);
|
|
12620
|
+
if (finalMessage) {
|
|
12621
|
+
state.finalResults.push(finalMessage);
|
|
12622
|
+
}
|
|
12623
|
+
const lastMessage = state.currentMessages[state.currentMessages.length - 1];
|
|
12624
|
+
if (lastMessage?.message?.usage) {
|
|
12625
|
+
state.accumulatedOutputTokens += getNumberProperty(lastMessage.message.usage, "output_tokens") || 0;
|
|
12626
|
+
}
|
|
12627
|
+
state.currentMessages.length = 0;
|
|
12628
|
+
}
|
|
12629
|
+
function maybeTrackToolUseContext(state, message) {
|
|
12630
|
+
if (message.type !== "assistant" || !Array.isArray(message.message?.content)) {
|
|
12631
|
+
return;
|
|
12632
|
+
}
|
|
12633
|
+
const parentToolUseId = message.parent_tool_use_id ?? null;
|
|
12634
|
+
for (const block of message.message.content) {
|
|
12635
|
+
if (typeof block !== "object" || block === null || !("type" in block) || block.type !== "tool_use" || !("id" in block) || typeof block.id !== "string") {
|
|
12636
|
+
continue;
|
|
12637
|
+
}
|
|
12638
|
+
state.toolUseToParent.set(block.id, parentToolUseId);
|
|
12639
|
+
if (block.name === "Task" && typeof block.input === "object" && block.input !== null && "subagent_type" in block.input && typeof block.input.subagent_type === "string") {
|
|
12640
|
+
state.pendingSubAgentNames.set(block.id, block.input.subagent_type);
|
|
12641
|
+
}
|
|
12642
|
+
}
|
|
12643
|
+
}
|
|
12644
|
+
async function maybeStartSubAgentSpan(state, message) {
|
|
12645
|
+
if (!("parent_tool_use_id" in message)) {
|
|
12646
|
+
return;
|
|
12647
|
+
}
|
|
12648
|
+
const parentToolUseId = message.parent_tool_use_id;
|
|
12649
|
+
if (!parentToolUseId) {
|
|
12650
|
+
return;
|
|
12651
|
+
}
|
|
12652
|
+
await ensureSubAgentSpan(
|
|
12653
|
+
state.pendingSubAgentNames,
|
|
12654
|
+
state.span,
|
|
12655
|
+
state.subAgentSpans,
|
|
12656
|
+
parentToolUseId
|
|
12657
|
+
);
|
|
12658
|
+
}
|
|
12659
|
+
async function ensureSubAgentSpan(pendingSubAgentNames, rootSpan, subAgentSpans, parentToolUseId) {
|
|
12660
|
+
const existingSpan = subAgentSpans.get(parentToolUseId);
|
|
12661
|
+
if (existingSpan) {
|
|
12662
|
+
return existingSpan;
|
|
12663
|
+
}
|
|
12664
|
+
const agentName = pendingSubAgentNames.get(parentToolUseId);
|
|
12665
|
+
const spanName = agentName ? `Agent: ${agentName}` : "Agent: sub-agent";
|
|
12666
|
+
const subAgentSpan = startSpan({
|
|
12667
|
+
event: {
|
|
12668
|
+
metadata: {
|
|
12669
|
+
...agentName && { "claude_agent_sdk.agent_type": agentName }
|
|
12670
|
+
}
|
|
12671
|
+
},
|
|
12672
|
+
name: spanName,
|
|
12673
|
+
parent: await rootSpan.export(),
|
|
12674
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
12675
|
+
});
|
|
12676
|
+
subAgentSpans.set(parentToolUseId, subAgentSpan);
|
|
12677
|
+
return subAgentSpan;
|
|
12678
|
+
}
|
|
12679
|
+
async function handleStreamMessage(state, message) {
|
|
12680
|
+
maybeTrackToolUseContext(state, message);
|
|
12681
|
+
await maybeStartSubAgentSpan(state, message);
|
|
12682
|
+
const messageId = message.message?.id;
|
|
12683
|
+
if (messageId && messageId !== state.currentMessageId) {
|
|
12684
|
+
await finalizeCurrentMessageGroup(state);
|
|
12685
|
+
state.currentMessageId = messageId;
|
|
12686
|
+
state.currentMessageStartTime = getCurrentUnixTimestamp();
|
|
12687
|
+
}
|
|
12688
|
+
if (message.type === "assistant" && message.message?.usage) {
|
|
12689
|
+
state.currentMessages.push(message);
|
|
12690
|
+
}
|
|
12691
|
+
if (message.type !== "result" || !message.usage) {
|
|
12692
|
+
return;
|
|
12693
|
+
}
|
|
12694
|
+
const finalUsageMetrics = extractUsageFromMessage(message);
|
|
12695
|
+
if (state.currentMessages.length > 0 && finalUsageMetrics.completion_tokens !== void 0) {
|
|
12696
|
+
const lastMessage = state.currentMessages[state.currentMessages.length - 1];
|
|
12697
|
+
if (lastMessage?.message?.usage) {
|
|
12698
|
+
const adjustedTokens = finalUsageMetrics.completion_tokens - state.accumulatedOutputTokens;
|
|
12699
|
+
if (adjustedTokens >= 0) {
|
|
12700
|
+
lastMessage.message.usage.output_tokens = adjustedTokens;
|
|
12701
|
+
}
|
|
12702
|
+
const resultUsage = message.usage;
|
|
12703
|
+
if (resultUsage && typeof resultUsage === "object") {
|
|
12704
|
+
const cacheReadTokens = getNumberProperty(
|
|
12705
|
+
resultUsage,
|
|
12706
|
+
"cache_read_input_tokens"
|
|
12707
|
+
);
|
|
12708
|
+
if (cacheReadTokens !== void 0) {
|
|
12709
|
+
lastMessage.message.usage.cache_read_input_tokens = cacheReadTokens;
|
|
12710
|
+
}
|
|
12711
|
+
const cacheCreationTokens = getNumberProperty(
|
|
12712
|
+
resultUsage,
|
|
12713
|
+
"cache_creation_input_tokens"
|
|
12714
|
+
);
|
|
12715
|
+
if (cacheCreationTokens !== void 0) {
|
|
12716
|
+
lastMessage.message.usage.cache_creation_input_tokens = cacheCreationTokens;
|
|
12717
|
+
}
|
|
12718
|
+
}
|
|
12719
|
+
}
|
|
12720
|
+
}
|
|
12721
|
+
const metadata = {};
|
|
12722
|
+
if (message.num_turns !== void 0) {
|
|
12723
|
+
metadata.num_turns = message.num_turns;
|
|
12724
|
+
}
|
|
12725
|
+
if (message.session_id !== void 0) {
|
|
12726
|
+
metadata.session_id = message.session_id;
|
|
12727
|
+
}
|
|
12728
|
+
if (Object.keys(metadata).length > 0) {
|
|
12729
|
+
state.span.log({ metadata });
|
|
12730
|
+
}
|
|
12731
|
+
}
|
|
12732
|
+
async function finalizeQuerySpan(state) {
|
|
12733
|
+
try {
|
|
12734
|
+
await finalizeCurrentMessageGroup(state);
|
|
12735
|
+
state.span.log({
|
|
12736
|
+
output: state.finalResults.length > 0 ? state.finalResults[state.finalResults.length - 1] : void 0
|
|
12737
|
+
});
|
|
12738
|
+
if (state.capturedPromptMessages) {
|
|
12739
|
+
if (state.promptStarted()) {
|
|
12740
|
+
await state.promptDone;
|
|
12741
|
+
}
|
|
12742
|
+
if (state.capturedPromptMessages.length > 0) {
|
|
12743
|
+
state.span.log({
|
|
12744
|
+
input: formatCapturedMessages(state.capturedPromptMessages)
|
|
12745
|
+
});
|
|
12746
|
+
}
|
|
12747
|
+
}
|
|
12748
|
+
} finally {
|
|
12749
|
+
for (const [id, subAgentSpan] of state.subAgentSpans) {
|
|
12750
|
+
if (!state.endedSubAgentSpans.has(id)) {
|
|
12751
|
+
subAgentSpan.end();
|
|
12752
|
+
}
|
|
12753
|
+
}
|
|
12754
|
+
state.subAgentSpans.clear();
|
|
12755
|
+
state.span.end();
|
|
12756
|
+
}
|
|
12757
|
+
}
|
|
11768
12758
|
var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
11769
12759
|
onEnable() {
|
|
11770
12760
|
this.subscribeToQuery();
|
|
@@ -11775,19 +12765,36 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
11775
12765
|
}
|
|
11776
12766
|
this.unsubscribers = [];
|
|
11777
12767
|
}
|
|
11778
|
-
/**
|
|
11779
|
-
* Subscribe to the query channel for agent interactions.
|
|
11780
|
-
* Handles streaming responses and traces both the top-level agent task
|
|
11781
|
-
* and individual LLM calls.
|
|
11782
|
-
*/
|
|
11783
12768
|
subscribeToQuery() {
|
|
11784
12769
|
const channel2 = claudeAgentSDKChannels.query.tracingChannel();
|
|
11785
12770
|
const spans = /* @__PURE__ */ new WeakMap();
|
|
11786
12771
|
const handlers = {
|
|
11787
12772
|
start: (event) => {
|
|
11788
|
-
const params = event.arguments[0];
|
|
11789
|
-
const
|
|
11790
|
-
const options = params
|
|
12773
|
+
const params = event.arguments[0] ?? {};
|
|
12774
|
+
const originalPrompt = params.prompt;
|
|
12775
|
+
const options = params.options ?? {};
|
|
12776
|
+
const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
|
|
12777
|
+
let promptStarted = false;
|
|
12778
|
+
let capturedPromptMessages;
|
|
12779
|
+
let resolvePromptDone;
|
|
12780
|
+
const promptDone = new Promise((resolve) => {
|
|
12781
|
+
resolvePromptDone = resolve;
|
|
12782
|
+
});
|
|
12783
|
+
if (promptIsAsyncIterable) {
|
|
12784
|
+
capturedPromptMessages = [];
|
|
12785
|
+
const promptStream = originalPrompt;
|
|
12786
|
+
params.prompt = (async function* () {
|
|
12787
|
+
promptStarted = true;
|
|
12788
|
+
try {
|
|
12789
|
+
for await (const message of promptStream) {
|
|
12790
|
+
capturedPromptMessages.push(message);
|
|
12791
|
+
yield message;
|
|
12792
|
+
}
|
|
12793
|
+
} finally {
|
|
12794
|
+
resolvePromptDone?.();
|
|
12795
|
+
}
|
|
12796
|
+
})();
|
|
12797
|
+
}
|
|
11791
12798
|
const span = startSpan({
|
|
11792
12799
|
name: "Claude Agent",
|
|
11793
12800
|
spanAttributes: {
|
|
@@ -11797,163 +12804,111 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
11797
12804
|
const startTime = getCurrentUnixTimestamp();
|
|
11798
12805
|
try {
|
|
11799
12806
|
span.log({
|
|
11800
|
-
input: typeof
|
|
11801
|
-
type: "streaming",
|
|
11802
|
-
description: "AsyncIterable<ClaudeAgentSDKMessage>"
|
|
11803
|
-
},
|
|
12807
|
+
input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
|
|
11804
12808
|
metadata: filterSerializableOptions(options)
|
|
11805
12809
|
});
|
|
11806
12810
|
} catch (error) {
|
|
11807
12811
|
console.error("Error extracting input for Claude Agent SDK:", error);
|
|
11808
12812
|
}
|
|
12813
|
+
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
12814
|
+
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
12815
|
+
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
12816
|
+
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
12817
|
+
const pendingSubAgentNames = /* @__PURE__ */ new Map();
|
|
12818
|
+
const optionsWithHooks = injectTracingHooks(
|
|
12819
|
+
options,
|
|
12820
|
+
async (toolUseID) => {
|
|
12821
|
+
const parentToolUseId = toolUseToParent.get(toolUseID);
|
|
12822
|
+
if (parentToolUseId) {
|
|
12823
|
+
const subAgentSpan = await ensureSubAgentSpan(
|
|
12824
|
+
pendingSubAgentNames,
|
|
12825
|
+
span,
|
|
12826
|
+
subAgentSpans,
|
|
12827
|
+
parentToolUseId
|
|
12828
|
+
);
|
|
12829
|
+
return subAgentSpan.export();
|
|
12830
|
+
}
|
|
12831
|
+
return span.export();
|
|
12832
|
+
},
|
|
12833
|
+
activeToolSpans,
|
|
12834
|
+
subAgentSpans,
|
|
12835
|
+
endedSubAgentSpans
|
|
12836
|
+
);
|
|
12837
|
+
params.options = optionsWithHooks;
|
|
12838
|
+
event.arguments[0] = params;
|
|
11809
12839
|
spans.set(event, {
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
currentMessages: [],
|
|
12840
|
+
accumulatedOutputTokens: 0,
|
|
12841
|
+
activeToolSpans,
|
|
12842
|
+
capturedPromptMessages,
|
|
11814
12843
|
currentMessageId: void 0,
|
|
11815
12844
|
currentMessageStartTime: startTime,
|
|
11816
|
-
|
|
12845
|
+
currentMessages: [],
|
|
12846
|
+
endedSubAgentSpans,
|
|
12847
|
+
finalResults: [],
|
|
12848
|
+
options: optionsWithHooks,
|
|
12849
|
+
originalPrompt,
|
|
12850
|
+
pendingSubAgentNames,
|
|
12851
|
+
processing: Promise.resolve(),
|
|
12852
|
+
promptDone,
|
|
12853
|
+
promptStarted: () => promptStarted,
|
|
12854
|
+
span,
|
|
12855
|
+
subAgentSpans,
|
|
12856
|
+
toolUseToParent
|
|
11817
12857
|
});
|
|
11818
12858
|
},
|
|
11819
|
-
|
|
11820
|
-
const
|
|
11821
|
-
if (!
|
|
12859
|
+
end: (event) => {
|
|
12860
|
+
const state = spans.get(event);
|
|
12861
|
+
if (!state) {
|
|
11822
12862
|
return;
|
|
11823
12863
|
}
|
|
11824
12864
|
const eventResult = event.result;
|
|
11825
12865
|
if (eventResult === void 0) {
|
|
11826
|
-
|
|
12866
|
+
state.span.end();
|
|
11827
12867
|
spans.delete(event);
|
|
11828
12868
|
return;
|
|
11829
12869
|
}
|
|
11830
12870
|
if (isAsyncIterable(eventResult)) {
|
|
11831
12871
|
patchStreamIfNeeded(eventResult, {
|
|
11832
|
-
onChunk:
|
|
11833
|
-
|
|
11834
|
-
|
|
11835
|
-
const prompt = params?.prompt;
|
|
11836
|
-
const options = params?.options ?? {};
|
|
11837
|
-
const messageId = message.message?.id;
|
|
11838
|
-
if (messageId && messageId !== spanData.currentMessageId) {
|
|
11839
|
-
if (spanData.currentMessages.length > 0) {
|
|
11840
|
-
const finalMessage = await createLLMSpanForMessages(
|
|
11841
|
-
spanData.currentMessages,
|
|
11842
|
-
prompt,
|
|
11843
|
-
spanData.conversationHistory,
|
|
11844
|
-
options,
|
|
11845
|
-
spanData.currentMessageStartTime,
|
|
11846
|
-
await spanData.span.export()
|
|
11847
|
-
);
|
|
11848
|
-
if (finalMessage) {
|
|
11849
|
-
spanData.conversationHistory.push(finalMessage);
|
|
11850
|
-
}
|
|
11851
|
-
const lastMessage = spanData.currentMessages[spanData.currentMessages.length - 1];
|
|
11852
|
-
if (lastMessage?.message?.usage) {
|
|
11853
|
-
const outputTokens = getNumberProperty(
|
|
11854
|
-
lastMessage.message.usage,
|
|
11855
|
-
"output_tokens"
|
|
11856
|
-
) || 0;
|
|
11857
|
-
spanData.accumulatedOutputTokens += outputTokens;
|
|
11858
|
-
}
|
|
11859
|
-
spanData.currentMessages = [];
|
|
11860
|
-
}
|
|
11861
|
-
spanData.currentMessageId = messageId;
|
|
11862
|
-
spanData.currentMessageStartTime = currentTime;
|
|
11863
|
-
}
|
|
11864
|
-
if (message.type === "assistant" && message.message?.usage) {
|
|
11865
|
-
spanData.currentMessages.push(message);
|
|
11866
|
-
}
|
|
11867
|
-
if (message.type === "result" && message.usage) {
|
|
11868
|
-
const finalUsageMetrics = extractUsageFromMessage(message);
|
|
11869
|
-
if (spanData.currentMessages.length > 0 && finalUsageMetrics.completion_tokens !== void 0) {
|
|
11870
|
-
const lastMessage = spanData.currentMessages[spanData.currentMessages.length - 1];
|
|
11871
|
-
if (lastMessage?.message?.usage) {
|
|
11872
|
-
const adjustedTokens = finalUsageMetrics.completion_tokens - spanData.accumulatedOutputTokens;
|
|
11873
|
-
if (adjustedTokens >= 0) {
|
|
11874
|
-
lastMessage.message.usage.output_tokens = adjustedTokens;
|
|
11875
|
-
}
|
|
11876
|
-
}
|
|
11877
|
-
}
|
|
11878
|
-
const result_metadata = {};
|
|
11879
|
-
if (message.num_turns !== void 0) {
|
|
11880
|
-
result_metadata.num_turns = message.num_turns;
|
|
11881
|
-
}
|
|
11882
|
-
if (message.session_id !== void 0) {
|
|
11883
|
-
result_metadata.session_id = message.session_id;
|
|
11884
|
-
}
|
|
11885
|
-
if (Object.keys(result_metadata).length > 0) {
|
|
11886
|
-
spanData.span.log({
|
|
11887
|
-
metadata: result_metadata
|
|
11888
|
-
});
|
|
11889
|
-
}
|
|
11890
|
-
}
|
|
11891
|
-
},
|
|
11892
|
-
onComplete: async () => {
|
|
11893
|
-
try {
|
|
11894
|
-
const params = event.arguments[0];
|
|
11895
|
-
const prompt = params?.prompt;
|
|
11896
|
-
const options = params?.options ?? {};
|
|
11897
|
-
if (spanData.currentMessages.length > 0) {
|
|
11898
|
-
const finalMessage = await createLLMSpanForMessages(
|
|
11899
|
-
spanData.currentMessages,
|
|
11900
|
-
prompt,
|
|
11901
|
-
spanData.conversationHistory,
|
|
11902
|
-
options,
|
|
11903
|
-
spanData.currentMessageStartTime,
|
|
11904
|
-
await spanData.span.export()
|
|
11905
|
-
);
|
|
11906
|
-
if (finalMessage) {
|
|
11907
|
-
spanData.conversationHistory.push(finalMessage);
|
|
11908
|
-
}
|
|
11909
|
-
}
|
|
11910
|
-
spanData.span.log({
|
|
11911
|
-
output: spanData.conversationHistory.length > 0 ? spanData.conversationHistory[spanData.conversationHistory.length - 1] : void 0
|
|
11912
|
-
});
|
|
11913
|
-
} catch (error) {
|
|
12872
|
+
onChunk: (message) => {
|
|
12873
|
+
maybeTrackToolUseContext(state, message);
|
|
12874
|
+
state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
|
|
11914
12875
|
console.error(
|
|
11915
|
-
"Error
|
|
12876
|
+
"Error processing Claude Agent SDK stream chunk:",
|
|
11916
12877
|
error
|
|
11917
12878
|
);
|
|
11918
|
-
}
|
|
11919
|
-
spanData.span.end();
|
|
11920
|
-
spans.delete(event);
|
|
11921
|
-
}
|
|
12879
|
+
});
|
|
11922
12880
|
},
|
|
11923
|
-
|
|
11924
|
-
|
|
12881
|
+
onComplete: () => state.processing.then(() => finalizeQuerySpan(state)).finally(() => {
|
|
12882
|
+
spans.delete(event);
|
|
12883
|
+
}),
|
|
12884
|
+
onError: (error) => state.processing.then(() => {
|
|
12885
|
+
state.span.log({
|
|
11925
12886
|
error: error.message
|
|
11926
12887
|
});
|
|
11927
|
-
|
|
12888
|
+
}).then(() => finalizeQuerySpan(state)).finally(() => {
|
|
11928
12889
|
spans.delete(event);
|
|
11929
|
-
}
|
|
12890
|
+
})
|
|
11930
12891
|
});
|
|
11931
|
-
|
|
11932
|
-
|
|
11933
|
-
|
|
11934
|
-
|
|
11935
|
-
|
|
11936
|
-
|
|
11937
|
-
|
|
11938
|
-
|
|
11939
|
-
|
|
11940
|
-
);
|
|
11941
|
-
} finally {
|
|
11942
|
-
spanData.span.end();
|
|
11943
|
-
spans.delete(event);
|
|
11944
|
-
}
|
|
12892
|
+
return;
|
|
12893
|
+
}
|
|
12894
|
+
try {
|
|
12895
|
+
state.span.log({ output: eventResult });
|
|
12896
|
+
} catch (error) {
|
|
12897
|
+
console.error("Error extracting output for Claude Agent SDK:", error);
|
|
12898
|
+
} finally {
|
|
12899
|
+
state.span.end();
|
|
12900
|
+
spans.delete(event);
|
|
11945
12901
|
}
|
|
11946
12902
|
},
|
|
11947
12903
|
error: (event) => {
|
|
11948
|
-
const
|
|
11949
|
-
if (!
|
|
12904
|
+
const state = spans.get(event);
|
|
12905
|
+
if (!state || !event.error) {
|
|
11950
12906
|
return;
|
|
11951
12907
|
}
|
|
11952
|
-
|
|
11953
|
-
span.log({
|
|
12908
|
+
state.span.log({
|
|
11954
12909
|
error: event.error.message
|
|
11955
12910
|
});
|
|
11956
|
-
span.end();
|
|
12911
|
+
state.span.end();
|
|
11957
12912
|
spans.delete(event);
|
|
11958
12913
|
}
|
|
11959
12914
|
};
|
|
@@ -11977,6 +12932,18 @@ var googleGenAIChannels = defineChannels("@google/genai", {
|
|
|
11977
12932
|
});
|
|
11978
12933
|
|
|
11979
12934
|
// src/instrumentation/plugins/google-genai-plugin.ts
|
|
12935
|
+
var GOOGLE_GENAI_INTERNAL_CONTEXT = {
|
|
12936
|
+
caller_filename: "<node-internal>",
|
|
12937
|
+
caller_functionname: "<node-internal>",
|
|
12938
|
+
caller_lineno: 0
|
|
12939
|
+
};
|
|
12940
|
+
function createWrapperParityEvent(args) {
|
|
12941
|
+
return {
|
|
12942
|
+
context: GOOGLE_GENAI_INTERNAL_CONTEXT,
|
|
12943
|
+
input: args.input,
|
|
12944
|
+
metadata: args.metadata
|
|
12945
|
+
};
|
|
12946
|
+
}
|
|
11980
12947
|
var GoogleGenAIPlugin = class extends BasePlugin {
|
|
11981
12948
|
onEnable() {
|
|
11982
12949
|
this.subscribeToGoogleGenAIChannels();
|
|
@@ -11985,51 +12952,283 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
11985
12952
|
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
11986
12953
|
}
|
|
11987
12954
|
subscribeToGoogleGenAIChannels() {
|
|
11988
|
-
this.
|
|
11989
|
-
|
|
11990
|
-
|
|
11991
|
-
|
|
11992
|
-
|
|
12955
|
+
this.subscribeToGenerateContentChannel();
|
|
12956
|
+
this.subscribeToGenerateContentStreamChannel();
|
|
12957
|
+
}
|
|
12958
|
+
subscribeToGenerateContentChannel() {
|
|
12959
|
+
const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
|
|
12960
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
12961
|
+
const unbindCurrentSpanStore = bindCurrentSpanStoreToStart2(
|
|
12962
|
+
tracingChannel2,
|
|
12963
|
+
states,
|
|
12964
|
+
(event) => {
|
|
12965
|
+
const params = event.arguments[0];
|
|
12966
|
+
const input = serializeInput(params);
|
|
12967
|
+
const metadata = extractMetadata(params);
|
|
12968
|
+
const span = startSpan({
|
|
12969
|
+
name: "generate_content",
|
|
12970
|
+
spanAttributes: {
|
|
12971
|
+
type: "llm" /* LLM */
|
|
12972
|
+
},
|
|
12973
|
+
event: createWrapperParityEvent({ input, metadata })
|
|
12974
|
+
});
|
|
12975
|
+
return {
|
|
12976
|
+
span,
|
|
12977
|
+
startTime: getCurrentUnixTimestamp()
|
|
12978
|
+
};
|
|
12979
|
+
}
|
|
12980
|
+
);
|
|
12981
|
+
const handlers = {
|
|
12982
|
+
start: (event) => {
|
|
12983
|
+
ensureSpanState(states, event, () => {
|
|
12984
|
+
const params = event.arguments[0];
|
|
11993
12985
|
const input = serializeInput(params);
|
|
11994
12986
|
const metadata = extractMetadata(params);
|
|
12987
|
+
const span = startSpan({
|
|
12988
|
+
name: "generate_content",
|
|
12989
|
+
spanAttributes: {
|
|
12990
|
+
type: "llm" /* LLM */
|
|
12991
|
+
},
|
|
12992
|
+
event: createWrapperParityEvent({ input, metadata })
|
|
12993
|
+
});
|
|
11995
12994
|
return {
|
|
11996
|
-
|
|
11997
|
-
|
|
12995
|
+
span,
|
|
12996
|
+
startTime: getCurrentUnixTimestamp()
|
|
11998
12997
|
};
|
|
11999
|
-
}
|
|
12000
|
-
|
|
12001
|
-
|
|
12002
|
-
|
|
12003
|
-
|
|
12004
|
-
return
|
|
12998
|
+
});
|
|
12999
|
+
},
|
|
13000
|
+
asyncEnd: (event) => {
|
|
13001
|
+
const spanState = states.get(event);
|
|
13002
|
+
if (!spanState) {
|
|
13003
|
+
return;
|
|
12005
13004
|
}
|
|
12006
|
-
|
|
12007
|
-
|
|
12008
|
-
|
|
12009
|
-
|
|
12010
|
-
|
|
12011
|
-
|
|
12012
|
-
|
|
12013
|
-
|
|
12014
|
-
|
|
12015
|
-
|
|
12016
|
-
|
|
12017
|
-
|
|
12018
|
-
|
|
12019
|
-
},
|
|
12020
|
-
extractOutput: (result) => {
|
|
12021
|
-
return result;
|
|
12022
|
-
},
|
|
12023
|
-
extractMetrics: () => {
|
|
12024
|
-
return {};
|
|
12025
|
-
},
|
|
12026
|
-
aggregateChunks: (chunks, _result, _endEvent, startTime) => {
|
|
12027
|
-
return aggregateGenerateContentChunks(chunks, startTime);
|
|
13005
|
+
try {
|
|
13006
|
+
spanState.span.log({
|
|
13007
|
+
metrics: cleanMetrics(
|
|
13008
|
+
extractGenerateContentMetrics(
|
|
13009
|
+
event.result,
|
|
13010
|
+
spanState.startTime
|
|
13011
|
+
)
|
|
13012
|
+
),
|
|
13013
|
+
output: event.result
|
|
13014
|
+
});
|
|
13015
|
+
} finally {
|
|
13016
|
+
spanState.span.end();
|
|
13017
|
+
states.delete(event);
|
|
12028
13018
|
}
|
|
12029
|
-
}
|
|
12030
|
-
|
|
13019
|
+
},
|
|
13020
|
+
error: (event) => {
|
|
13021
|
+
logErrorAndEndSpan(states, event);
|
|
13022
|
+
}
|
|
13023
|
+
};
|
|
13024
|
+
tracingChannel2.subscribe(handlers);
|
|
13025
|
+
this.unsubscribers.push(() => {
|
|
13026
|
+
unbindCurrentSpanStore?.();
|
|
13027
|
+
tracingChannel2.unsubscribe(handlers);
|
|
13028
|
+
});
|
|
13029
|
+
}
|
|
13030
|
+
subscribeToGenerateContentStreamChannel() {
|
|
13031
|
+
const tracingChannel2 = googleGenAIChannels.generateContentStream.tracingChannel();
|
|
13032
|
+
const handlers = {
|
|
13033
|
+
start: (event) => {
|
|
13034
|
+
const streamEvent = event;
|
|
13035
|
+
const params = event.arguments[0];
|
|
13036
|
+
streamEvent.googleGenAIInput = serializeInput(params);
|
|
13037
|
+
streamEvent.googleGenAIMetadata = extractMetadata(params);
|
|
13038
|
+
streamEvent.googleGenAIStartTime = getCurrentUnixTimestamp();
|
|
13039
|
+
},
|
|
13040
|
+
asyncEnd: (event) => {
|
|
13041
|
+
const streamEvent = event;
|
|
13042
|
+
patchGoogleGenAIStreamingResult({
|
|
13043
|
+
input: streamEvent.googleGenAIInput,
|
|
13044
|
+
metadata: streamEvent.googleGenAIMetadata,
|
|
13045
|
+
startTime: streamEvent.googleGenAIStartTime,
|
|
13046
|
+
result: streamEvent.result
|
|
13047
|
+
});
|
|
13048
|
+
},
|
|
13049
|
+
error: () => {
|
|
13050
|
+
}
|
|
13051
|
+
};
|
|
13052
|
+
tracingChannel2.subscribe(handlers);
|
|
13053
|
+
this.unsubscribers.push(() => {
|
|
13054
|
+
tracingChannel2.unsubscribe(handlers);
|
|
13055
|
+
});
|
|
12031
13056
|
}
|
|
12032
13057
|
};
|
|
13058
|
+
function ensureSpanState(states, event, create) {
|
|
13059
|
+
const existing = states.get(event);
|
|
13060
|
+
if (existing) {
|
|
13061
|
+
return existing;
|
|
13062
|
+
}
|
|
13063
|
+
const created = create();
|
|
13064
|
+
states.set(event, created);
|
|
13065
|
+
return created;
|
|
13066
|
+
}
|
|
13067
|
+
function bindCurrentSpanStoreToStart2(tracingChannel2, states, create) {
|
|
13068
|
+
const state = _internalGetGlobalState();
|
|
13069
|
+
const startChannel = tracingChannel2.start;
|
|
13070
|
+
const currentSpanStore = state?.contextManager ? state.contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
13071
|
+
if (!startChannel?.bindStore || !currentSpanStore) {
|
|
13072
|
+
return void 0;
|
|
13073
|
+
}
|
|
13074
|
+
startChannel.bindStore(
|
|
13075
|
+
currentSpanStore,
|
|
13076
|
+
(event) => ensureSpanState(
|
|
13077
|
+
states,
|
|
13078
|
+
event,
|
|
13079
|
+
() => create(event)
|
|
13080
|
+
).span
|
|
13081
|
+
);
|
|
13082
|
+
return () => {
|
|
13083
|
+
startChannel.unbindStore?.(currentSpanStore);
|
|
13084
|
+
};
|
|
13085
|
+
}
|
|
13086
|
+
function logErrorAndEndSpan(states, event) {
|
|
13087
|
+
const spanState = states.get(event);
|
|
13088
|
+
if (!spanState) {
|
|
13089
|
+
return;
|
|
13090
|
+
}
|
|
13091
|
+
spanState.span.log({
|
|
13092
|
+
error: event.error.message
|
|
13093
|
+
});
|
|
13094
|
+
spanState.span.end();
|
|
13095
|
+
states.delete(event);
|
|
13096
|
+
}
|
|
13097
|
+
function patchGoogleGenAIStreamingResult(args) {
|
|
13098
|
+
const { input, metadata, result, startTime } = args;
|
|
13099
|
+
if (!input || !metadata || !result || typeof result !== "object" || typeof result.next !== "function") {
|
|
13100
|
+
return false;
|
|
13101
|
+
}
|
|
13102
|
+
const chunks = [];
|
|
13103
|
+
let firstTokenTime = null;
|
|
13104
|
+
let finalized = false;
|
|
13105
|
+
let span = null;
|
|
13106
|
+
const requestStartTime = startTime ?? getCurrentUnixTimestamp();
|
|
13107
|
+
const ensureSpan = () => {
|
|
13108
|
+
if (!span) {
|
|
13109
|
+
span = startSpan({
|
|
13110
|
+
name: "generate_content_stream",
|
|
13111
|
+
spanAttributes: {
|
|
13112
|
+
type: "llm" /* LLM */
|
|
13113
|
+
},
|
|
13114
|
+
event: {
|
|
13115
|
+
input,
|
|
13116
|
+
metadata
|
|
13117
|
+
}
|
|
13118
|
+
});
|
|
13119
|
+
}
|
|
13120
|
+
return span;
|
|
13121
|
+
};
|
|
13122
|
+
const finalize = (options) => {
|
|
13123
|
+
if (finalized || !span) {
|
|
13124
|
+
return;
|
|
13125
|
+
}
|
|
13126
|
+
finalized = true;
|
|
13127
|
+
if (options.result) {
|
|
13128
|
+
const { end, ...metricsWithoutEnd } = options.result.metrics;
|
|
13129
|
+
span.log({
|
|
13130
|
+
metrics: cleanMetrics(metricsWithoutEnd),
|
|
13131
|
+
output: options.result.aggregated
|
|
13132
|
+
});
|
|
13133
|
+
span.end(typeof end === "number" ? { endTime: end } : void 0);
|
|
13134
|
+
return;
|
|
13135
|
+
}
|
|
13136
|
+
if (options.error !== void 0) {
|
|
13137
|
+
span.log({
|
|
13138
|
+
error: options.error instanceof Error ? options.error.message : String(options.error)
|
|
13139
|
+
});
|
|
13140
|
+
}
|
|
13141
|
+
span.end();
|
|
13142
|
+
};
|
|
13143
|
+
const patchIterator = (iterator) => {
|
|
13144
|
+
if (typeof iterator !== "object" || iterator === null || "__braintrustGoogleGenAIPatched" in iterator) {
|
|
13145
|
+
return iterator;
|
|
13146
|
+
}
|
|
13147
|
+
const iteratorRecord = iterator;
|
|
13148
|
+
const originalNext = typeof iteratorRecord.next === "function" ? iteratorRecord.next.bind(iterator) : void 0;
|
|
13149
|
+
const originalReturn = typeof iteratorRecord.return === "function" ? iteratorRecord.return.bind(iterator) : void 0;
|
|
13150
|
+
const originalThrow = typeof iteratorRecord.throw === "function" ? iteratorRecord.throw.bind(iterator) : void 0;
|
|
13151
|
+
const asyncIteratorMethod = iteratorRecord[Symbol.asyncIterator];
|
|
13152
|
+
const originalAsyncIterator = typeof asyncIteratorMethod === "function" ? asyncIteratorMethod.bind(iterator) : void 0;
|
|
13153
|
+
Object.defineProperty(iteratorRecord, "__braintrustGoogleGenAIPatched", {
|
|
13154
|
+
configurable: true,
|
|
13155
|
+
enumerable: false,
|
|
13156
|
+
value: true,
|
|
13157
|
+
writable: false
|
|
13158
|
+
});
|
|
13159
|
+
if (originalNext) {
|
|
13160
|
+
iteratorRecord.next = async (...nextArgs) => {
|
|
13161
|
+
ensureSpan();
|
|
13162
|
+
try {
|
|
13163
|
+
const nextResult = await originalNext(
|
|
13164
|
+
...nextArgs
|
|
13165
|
+
);
|
|
13166
|
+
if (!nextResult.done && nextResult.value) {
|
|
13167
|
+
if (firstTokenTime === null) {
|
|
13168
|
+
firstTokenTime = getCurrentUnixTimestamp();
|
|
13169
|
+
}
|
|
13170
|
+
chunks.push(nextResult.value);
|
|
13171
|
+
}
|
|
13172
|
+
if (nextResult.done) {
|
|
13173
|
+
finalize({
|
|
13174
|
+
result: aggregateGenerateContentChunks(
|
|
13175
|
+
chunks,
|
|
13176
|
+
requestStartTime,
|
|
13177
|
+
firstTokenTime
|
|
13178
|
+
)
|
|
13179
|
+
});
|
|
13180
|
+
}
|
|
13181
|
+
return nextResult;
|
|
13182
|
+
} catch (error) {
|
|
13183
|
+
finalize({ error });
|
|
13184
|
+
throw error;
|
|
13185
|
+
}
|
|
13186
|
+
};
|
|
13187
|
+
}
|
|
13188
|
+
if (originalReturn) {
|
|
13189
|
+
iteratorRecord.return = async (...returnArgs) => {
|
|
13190
|
+
ensureSpan();
|
|
13191
|
+
try {
|
|
13192
|
+
return await originalReturn(
|
|
13193
|
+
...returnArgs
|
|
13194
|
+
);
|
|
13195
|
+
} finally {
|
|
13196
|
+
if (chunks.length > 0) {
|
|
13197
|
+
finalize({
|
|
13198
|
+
result: aggregateGenerateContentChunks(
|
|
13199
|
+
chunks,
|
|
13200
|
+
requestStartTime,
|
|
13201
|
+
firstTokenTime
|
|
13202
|
+
)
|
|
13203
|
+
});
|
|
13204
|
+
} else {
|
|
13205
|
+
finalize({});
|
|
13206
|
+
}
|
|
13207
|
+
}
|
|
13208
|
+
};
|
|
13209
|
+
}
|
|
13210
|
+
if (originalThrow) {
|
|
13211
|
+
iteratorRecord.throw = async (...throwArgs) => {
|
|
13212
|
+
ensureSpan();
|
|
13213
|
+
try {
|
|
13214
|
+
return await originalThrow(
|
|
13215
|
+
...throwArgs
|
|
13216
|
+
);
|
|
13217
|
+
} catch (error) {
|
|
13218
|
+
finalize({ error });
|
|
13219
|
+
throw error;
|
|
13220
|
+
}
|
|
13221
|
+
};
|
|
13222
|
+
}
|
|
13223
|
+
iteratorRecord[Symbol.asyncIterator] = () => {
|
|
13224
|
+
const asyncIterator = originalAsyncIterator ? originalAsyncIterator() : iterator;
|
|
13225
|
+
return patchIterator(asyncIterator);
|
|
13226
|
+
};
|
|
13227
|
+
return iterator;
|
|
13228
|
+
};
|
|
13229
|
+
patchIterator(result);
|
|
13230
|
+
return true;
|
|
13231
|
+
}
|
|
12033
13232
|
function serializeInput(params) {
|
|
12034
13233
|
const input = {
|
|
12035
13234
|
model: params.model,
|
|
@@ -12038,11 +13237,13 @@ function serializeInput(params) {
|
|
|
12038
13237
|
if (params.config) {
|
|
12039
13238
|
const config = tryToDict(params.config);
|
|
12040
13239
|
if (config) {
|
|
12041
|
-
const
|
|
12042
|
-
|
|
12043
|
-
|
|
12044
|
-
|
|
12045
|
-
|
|
13240
|
+
const filteredConfig = {};
|
|
13241
|
+
Object.keys(config).forEach((key) => {
|
|
13242
|
+
if (key !== "tools") {
|
|
13243
|
+
filteredConfig[key] = config[key];
|
|
13244
|
+
}
|
|
13245
|
+
});
|
|
13246
|
+
input.config = filteredConfig;
|
|
12046
13247
|
}
|
|
12047
13248
|
}
|
|
12048
13249
|
return input;
|
|
@@ -12129,12 +13330,18 @@ function extractMetadata(params) {
|
|
|
12129
13330
|
});
|
|
12130
13331
|
}
|
|
12131
13332
|
}
|
|
13333
|
+
const tools = serializeTools(params);
|
|
13334
|
+
if (tools) {
|
|
13335
|
+
metadata.tools = tools;
|
|
13336
|
+
}
|
|
12132
13337
|
return metadata;
|
|
12133
13338
|
}
|
|
12134
13339
|
function extractGenerateContentMetrics(response, startTime) {
|
|
12135
13340
|
const metrics = {};
|
|
12136
|
-
if (startTime) {
|
|
13341
|
+
if (startTime !== void 0) {
|
|
12137
13342
|
const end = getCurrentUnixTimestamp();
|
|
13343
|
+
metrics.start = startTime;
|
|
13344
|
+
metrics.end = end;
|
|
12138
13345
|
metrics.duration = end - startTime;
|
|
12139
13346
|
}
|
|
12140
13347
|
if (response?.usageMetadata) {
|
|
@@ -12159,19 +13366,18 @@ function populateUsageMetrics(metrics, usage) {
|
|
|
12159
13366
|
metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
|
|
12160
13367
|
}
|
|
12161
13368
|
}
|
|
12162
|
-
function aggregateGenerateContentChunks(chunks, startTime) {
|
|
12163
|
-
const
|
|
12164
|
-
|
|
12165
|
-
|
|
12166
|
-
|
|
12167
|
-
|
|
12168
|
-
|
|
12169
|
-
if (
|
|
12170
|
-
firstTokenTime = getCurrentUnixTimestamp();
|
|
13369
|
+
function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
13370
|
+
const end = getCurrentUnixTimestamp();
|
|
13371
|
+
const metrics = {
|
|
13372
|
+
start: startTime,
|
|
13373
|
+
end,
|
|
13374
|
+
duration: end - startTime
|
|
13375
|
+
};
|
|
13376
|
+
if (firstTokenTime !== null) {
|
|
12171
13377
|
metrics.time_to_first_token = firstTokenTime - startTime;
|
|
12172
13378
|
}
|
|
12173
13379
|
if (chunks.length === 0) {
|
|
12174
|
-
return {
|
|
13380
|
+
return { aggregated: {}, metrics };
|
|
12175
13381
|
}
|
|
12176
13382
|
let text = "";
|
|
12177
13383
|
let thoughtText = "";
|
|
@@ -12207,7 +13413,7 @@ function aggregateGenerateContentChunks(chunks, startTime) {
|
|
|
12207
13413
|
}
|
|
12208
13414
|
}
|
|
12209
13415
|
}
|
|
12210
|
-
const
|
|
13416
|
+
const aggregated = {};
|
|
12211
13417
|
const parts = [];
|
|
12212
13418
|
if (thoughtText) {
|
|
12213
13419
|
parts.push({ text: thoughtText, thought: true });
|
|
@@ -12233,16 +13439,25 @@ function aggregateGenerateContentChunks(chunks, startTime) {
|
|
|
12233
13439
|
}
|
|
12234
13440
|
candidates.push(candidateDict);
|
|
12235
13441
|
}
|
|
12236
|
-
|
|
13442
|
+
aggregated.candidates = candidates;
|
|
12237
13443
|
}
|
|
12238
13444
|
if (usageMetadata) {
|
|
12239
|
-
|
|
13445
|
+
aggregated.usageMetadata = usageMetadata;
|
|
12240
13446
|
populateUsageMetrics(metrics, usageMetadata);
|
|
12241
13447
|
}
|
|
12242
13448
|
if (text) {
|
|
12243
|
-
|
|
13449
|
+
aggregated.text = text;
|
|
13450
|
+
}
|
|
13451
|
+
return { aggregated, metrics };
|
|
13452
|
+
}
|
|
13453
|
+
function cleanMetrics(metrics) {
|
|
13454
|
+
const cleaned = {};
|
|
13455
|
+
for (const [key, value] of Object.entries(metrics)) {
|
|
13456
|
+
if (value !== null && value !== void 0) {
|
|
13457
|
+
cleaned[key] = value;
|
|
13458
|
+
}
|
|
12244
13459
|
}
|
|
12245
|
-
return
|
|
13460
|
+
return cleaned;
|
|
12246
13461
|
}
|
|
12247
13462
|
function tryToDict(obj) {
|
|
12248
13463
|
if (obj === null || obj === void 0) {
|
|
@@ -12276,895 +13491,535 @@ var openRouterChannels = defineChannels("@openrouter/sdk", {
|
|
|
12276
13491
|
channelName: "callModel",
|
|
12277
13492
|
kind: "sync-stream"
|
|
12278
13493
|
}),
|
|
13494
|
+
callModelTurn: channel({
|
|
13495
|
+
channelName: "callModel.turn",
|
|
13496
|
+
kind: "async"
|
|
13497
|
+
}),
|
|
12279
13498
|
toolExecute: channel({
|
|
12280
13499
|
channelName: "tool.execute",
|
|
12281
13500
|
kind: "async"
|
|
12282
13501
|
})
|
|
12283
13502
|
});
|
|
12284
13503
|
|
|
12285
|
-
// src/openrouter-
|
|
12286
|
-
var
|
|
12287
|
-
|
|
12288
|
-
|
|
12289
|
-
completionTokens: "completion_tokens",
|
|
12290
|
-
outputTokens: "completion_tokens",
|
|
12291
|
-
totalTokens: "tokens",
|
|
12292
|
-
prompt_tokens: "prompt_tokens",
|
|
12293
|
-
input_tokens: "prompt_tokens",
|
|
12294
|
-
completion_tokens: "completion_tokens",
|
|
12295
|
-
output_tokens: "completion_tokens",
|
|
12296
|
-
total_tokens: "tokens"
|
|
12297
|
-
};
|
|
12298
|
-
var TOKEN_DETAIL_PREFIX_MAP = {
|
|
12299
|
-
promptTokensDetails: "prompt",
|
|
12300
|
-
inputTokensDetails: "prompt",
|
|
12301
|
-
completionTokensDetails: "completion",
|
|
12302
|
-
outputTokensDetails: "completion",
|
|
12303
|
-
costDetails: "cost",
|
|
12304
|
-
prompt_tokens_details: "prompt",
|
|
12305
|
-
input_tokens_details: "prompt",
|
|
12306
|
-
completion_tokens_details: "completion",
|
|
12307
|
-
output_tokens_details: "completion",
|
|
12308
|
-
cost_details: "cost"
|
|
12309
|
-
};
|
|
12310
|
-
function camelToSnake(value) {
|
|
12311
|
-
return value.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
|
|
12312
|
-
}
|
|
12313
|
-
function parseOpenRouterMetricsFromUsage(usage) {
|
|
12314
|
-
if (!isObject(usage)) {
|
|
12315
|
-
return {};
|
|
12316
|
-
}
|
|
12317
|
-
const metrics = {};
|
|
12318
|
-
for (const [name, value] of Object.entries(usage)) {
|
|
12319
|
-
if (typeof value === "number") {
|
|
12320
|
-
metrics[TOKEN_NAME_MAP2[name] || camelToSnake(name)] = value;
|
|
12321
|
-
continue;
|
|
12322
|
-
}
|
|
12323
|
-
if (!isObject(value)) {
|
|
12324
|
-
continue;
|
|
12325
|
-
}
|
|
12326
|
-
const prefix = TOKEN_DETAIL_PREFIX_MAP[name];
|
|
12327
|
-
if (!prefix) {
|
|
12328
|
-
continue;
|
|
12329
|
-
}
|
|
12330
|
-
for (const [nestedName, nestedValue] of Object.entries(value)) {
|
|
12331
|
-
if (typeof nestedValue !== "number") {
|
|
12332
|
-
continue;
|
|
12333
|
-
}
|
|
12334
|
-
metrics[`${prefix}_${camelToSnake(nestedName)}`] = nestedValue;
|
|
12335
|
-
}
|
|
12336
|
-
}
|
|
12337
|
-
return metrics;
|
|
12338
|
-
}
|
|
12339
|
-
function extractOpenRouterUsageMetadata(usage) {
|
|
12340
|
-
if (!isObject(usage)) {
|
|
12341
|
-
return void 0;
|
|
12342
|
-
}
|
|
12343
|
-
const metadata = {};
|
|
12344
|
-
if (typeof usage.isByok === "boolean") {
|
|
12345
|
-
metadata.is_byok = usage.isByok;
|
|
12346
|
-
} else if (typeof usage.is_byok === "boolean") {
|
|
12347
|
-
metadata.is_byok = usage.is_byok;
|
|
12348
|
-
}
|
|
12349
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
12350
|
-
}
|
|
12351
|
-
|
|
12352
|
-
// src/openrouter-logging.ts
|
|
12353
|
-
var OMITTED_OPENROUTER_KEYS = /* @__PURE__ */ new Set([
|
|
12354
|
-
"execute",
|
|
12355
|
-
"render",
|
|
12356
|
-
"nextTurnParams",
|
|
12357
|
-
"requireApproval"
|
|
12358
|
-
]);
|
|
12359
|
-
function parseOpenRouterModelString(model) {
|
|
12360
|
-
if (typeof model !== "string") {
|
|
12361
|
-
return { model };
|
|
12362
|
-
}
|
|
12363
|
-
const slashIndex = model.indexOf("/");
|
|
12364
|
-
if (slashIndex > 0 && slashIndex < model.length - 1) {
|
|
12365
|
-
return {
|
|
12366
|
-
provider: model.substring(0, slashIndex),
|
|
12367
|
-
model: model.substring(slashIndex + 1)
|
|
12368
|
-
};
|
|
12369
|
-
}
|
|
12370
|
-
return { model };
|
|
12371
|
-
}
|
|
12372
|
-
function isZodSchema2(value) {
|
|
12373
|
-
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
12374
|
-
}
|
|
12375
|
-
function serializeZodSchema2(schema) {
|
|
12376
|
-
try {
|
|
12377
|
-
return zodToJsonSchema(schema);
|
|
12378
|
-
} catch {
|
|
12379
|
-
return {
|
|
12380
|
-
type: "object",
|
|
12381
|
-
description: "Zod schema (conversion failed)"
|
|
12382
|
-
};
|
|
13504
|
+
// src/instrumentation/plugins/openrouter-plugin.ts
|
|
13505
|
+
var OpenRouterPlugin = class extends BasePlugin {
|
|
13506
|
+
onEnable() {
|
|
13507
|
+
this.subscribeToOpenRouterChannels();
|
|
12383
13508
|
}
|
|
12384
|
-
|
|
12385
|
-
|
|
12386
|
-
if (!isObject(tool)) {
|
|
12387
|
-
return tool;
|
|
13509
|
+
onDisable() {
|
|
13510
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
12388
13511
|
}
|
|
12389
|
-
|
|
12390
|
-
|
|
12391
|
-
|
|
12392
|
-
|
|
12393
|
-
|
|
12394
|
-
|
|
12395
|
-
|
|
12396
|
-
|
|
12397
|
-
|
|
12398
|
-
|
|
12399
|
-
|
|
12400
|
-
|
|
12401
|
-
|
|
12402
|
-
|
|
12403
|
-
|
|
12404
|
-
|
|
12405
|
-
|
|
12406
|
-
|
|
12407
|
-
}
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
|
|
12412
|
-
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
|
|
12416
|
-
|
|
12417
|
-
}
|
|
12418
|
-
if (!isObject(value)) {
|
|
12419
|
-
return value;
|
|
12420
|
-
}
|
|
12421
|
-
const sanitized = {};
|
|
12422
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
12423
|
-
if (OMITTED_OPENROUTER_KEYS.has(key)) {
|
|
12424
|
-
continue;
|
|
12425
|
-
}
|
|
12426
|
-
if (key === "tools" && Array.isArray(entry)) {
|
|
12427
|
-
sanitized.tools = serializeOpenRouterToolsForLogging(entry);
|
|
12428
|
-
continue;
|
|
12429
|
-
}
|
|
12430
|
-
sanitized[key] = sanitizeOpenRouterLoggedValue(entry);
|
|
12431
|
-
}
|
|
12432
|
-
return sanitized;
|
|
12433
|
-
}
|
|
12434
|
-
function buildOpenRouterMetadata(metadata, httpReferer, xTitle) {
|
|
12435
|
-
const sanitized = sanitizeOpenRouterLoggedValue(metadata);
|
|
12436
|
-
const metadataRecord = isObject(sanitized) ? sanitized : {};
|
|
12437
|
-
const { model, provider: providerRouting, ...rest } = metadataRecord;
|
|
12438
|
-
const normalizedModel = parseOpenRouterModelString(model);
|
|
12439
|
-
return {
|
|
12440
|
-
...rest,
|
|
12441
|
-
...normalizedModel.model !== void 0 ? { model: normalizedModel.model } : {},
|
|
12442
|
-
...providerRouting !== void 0 ? { providerRouting } : {},
|
|
12443
|
-
...httpReferer !== void 0 ? { httpReferer } : {},
|
|
12444
|
-
...xTitle !== void 0 ? { xTitle } : {},
|
|
12445
|
-
provider: normalizedModel.provider || "openrouter"
|
|
12446
|
-
};
|
|
12447
|
-
}
|
|
12448
|
-
function buildOpenRouterEmbeddingMetadata(metadata, httpReferer, xTitle) {
|
|
12449
|
-
const normalized = buildOpenRouterMetadata(metadata, httpReferer, xTitle);
|
|
12450
|
-
return typeof normalized.model === "string" ? {
|
|
12451
|
-
...normalized,
|
|
12452
|
-
embedding_model: normalized.model
|
|
12453
|
-
} : normalized;
|
|
12454
|
-
}
|
|
12455
|
-
function extractOpenRouterCallModelInput(request) {
|
|
12456
|
-
return isObject(request) && "input" in request ? sanitizeOpenRouterLoggedValue(request.input) : void 0;
|
|
12457
|
-
}
|
|
12458
|
-
function extractOpenRouterCallModelMetadata(request) {
|
|
12459
|
-
if (!isObject(request)) {
|
|
12460
|
-
return { provider: "openrouter" };
|
|
12461
|
-
}
|
|
12462
|
-
const { input: _input, ...metadata } = request;
|
|
12463
|
-
return buildOpenRouterMetadata(metadata, void 0, void 0);
|
|
12464
|
-
}
|
|
12465
|
-
function extractOpenRouterResponseMetadata(result) {
|
|
12466
|
-
if (!isObject(result)) {
|
|
12467
|
-
return void 0;
|
|
12468
|
-
}
|
|
12469
|
-
const { output: _output, data: _data, usage, ...metadata } = result;
|
|
12470
|
-
const sanitized = sanitizeOpenRouterLoggedValue(metadata);
|
|
12471
|
-
const metadataRecord = isObject(sanitized) ? sanitized : {};
|
|
12472
|
-
const { model, provider, ...rest } = metadataRecord;
|
|
12473
|
-
const normalizedModel = parseOpenRouterModelString(model);
|
|
12474
|
-
const normalizedProvider = (typeof provider === "string" ? provider : void 0) || normalizedModel.provider;
|
|
12475
|
-
const usageMetadata = extractOpenRouterUsageMetadata(usage);
|
|
12476
|
-
const combined = {
|
|
12477
|
-
...rest,
|
|
12478
|
-
...normalizedModel.model !== void 0 ? { model: normalizedModel.model } : {},
|
|
12479
|
-
...usageMetadata || {},
|
|
12480
|
-
...normalizedProvider !== void 0 ? { provider: normalizedProvider } : {}
|
|
12481
|
-
};
|
|
12482
|
-
return Object.keys(combined).length > 0 ? combined : void 0;
|
|
12483
|
-
}
|
|
12484
|
-
function extractOpenRouterResponseOutput(response, fallbackOutput) {
|
|
12485
|
-
if (isObject(response) && "output" in response && response.output !== void 0) {
|
|
12486
|
-
return sanitizeOpenRouterLoggedValue(response.output);
|
|
12487
|
-
}
|
|
12488
|
-
if (fallbackOutput !== void 0) {
|
|
12489
|
-
return sanitizeOpenRouterLoggedValue(fallbackOutput);
|
|
12490
|
-
}
|
|
12491
|
-
return void 0;
|
|
12492
|
-
}
|
|
12493
|
-
|
|
12494
|
-
// src/openrouter-tool-wrapping.ts
|
|
12495
|
-
var OPENROUTER_WRAPPED_TOOL = Symbol("braintrust.openrouter.wrappedTool");
|
|
12496
|
-
var OPENROUTER_WRAPPED_CALL_MODEL_RESULT = Symbol(
|
|
12497
|
-
"braintrust.openrouter.wrappedCallModelResult"
|
|
12498
|
-
);
|
|
12499
|
-
var OPENROUTER_CALL_MODEL_STREAM_METHODS = [
|
|
12500
|
-
"getFullResponsesStream",
|
|
12501
|
-
"getItemsStream",
|
|
12502
|
-
"getNewMessagesStream",
|
|
12503
|
-
"getReasoningStream",
|
|
12504
|
-
"getTextStream",
|
|
12505
|
-
"getToolCallsStream",
|
|
12506
|
-
"getToolStream"
|
|
12507
|
-
];
|
|
12508
|
-
var OPENROUTER_CALL_MODEL_CONTEXT_METHODS = [
|
|
12509
|
-
"cancel",
|
|
12510
|
-
"getPendingToolCalls",
|
|
12511
|
-
"getState",
|
|
12512
|
-
"getToolCalls",
|
|
12513
|
-
"requiresApproval"
|
|
12514
|
-
];
|
|
12515
|
-
function patchOpenRouterCallModelRequestTools(request) {
|
|
12516
|
-
if (!Array.isArray(request.tools) || request.tools.length === 0) {
|
|
12517
|
-
return void 0;
|
|
12518
|
-
}
|
|
12519
|
-
const originalTools = request.tools;
|
|
12520
|
-
const wrappedTools = originalTools.map((tool) => wrapOpenRouterTool(tool));
|
|
12521
|
-
const didPatch = wrappedTools.some(
|
|
12522
|
-
(tool, index) => tool !== originalTools[index]
|
|
12523
|
-
);
|
|
12524
|
-
if (!didPatch) {
|
|
12525
|
-
return void 0;
|
|
12526
|
-
}
|
|
12527
|
-
request.tools = wrappedTools;
|
|
12528
|
-
return () => {
|
|
12529
|
-
request.tools = originalTools;
|
|
12530
|
-
};
|
|
12531
|
-
}
|
|
12532
|
-
function patchOpenRouterCallModelResult(span, result, request) {
|
|
12533
|
-
if (!isObject(result) || isWrappedCallModelResult(result)) {
|
|
12534
|
-
return false;
|
|
12535
|
-
}
|
|
12536
|
-
const resultLike = result;
|
|
12537
|
-
const hasInstrumentableMethod = typeof resultLike.getResponse === "function" || typeof resultLike.getText === "function" || OPENROUTER_CALL_MODEL_STREAM_METHODS.some(
|
|
12538
|
-
(methodName) => typeof resultLike[methodName] === "function"
|
|
12539
|
-
);
|
|
12540
|
-
if (!hasInstrumentableMethod) {
|
|
12541
|
-
return false;
|
|
12542
|
-
}
|
|
12543
|
-
Object.defineProperty(resultLike, OPENROUTER_WRAPPED_CALL_MODEL_RESULT, {
|
|
12544
|
-
value: true,
|
|
12545
|
-
enumerable: false,
|
|
12546
|
-
configurable: false
|
|
12547
|
-
});
|
|
12548
|
-
const originalGetResponse = typeof resultLike.getResponse === "function" ? resultLike.getResponse.bind(resultLike) : void 0;
|
|
12549
|
-
const originalGetInitialResponse = typeof resultLike.getInitialResponse === "function" ? resultLike.getInitialResponse.bind(resultLike) : void 0;
|
|
12550
|
-
const originalMakeFollowupRequest = typeof resultLike.makeFollowupRequest === "function" ? resultLike.makeFollowupRequest.bind(resultLike) : void 0;
|
|
12551
|
-
let ended = false;
|
|
12552
|
-
let tracedTurnCount = 0;
|
|
12553
|
-
const endSpanWithResult = async (response, fallbackOutput) => {
|
|
12554
|
-
if (ended) {
|
|
12555
|
-
return;
|
|
12556
|
-
}
|
|
12557
|
-
ended = true;
|
|
12558
|
-
const finalResponse = getFinalOpenRouterCallModelResponse(
|
|
12559
|
-
resultLike,
|
|
12560
|
-
response
|
|
13512
|
+
subscribeToOpenRouterChannels() {
|
|
13513
|
+
this.unsubscribers.push(
|
|
13514
|
+
traceStreamingChannel(openRouterChannels.chatSend, {
|
|
13515
|
+
name: "openrouter.chat.send",
|
|
13516
|
+
type: "llm" /* LLM */,
|
|
13517
|
+
extractInput: (args) => {
|
|
13518
|
+
const request = getOpenRouterRequestArg(args);
|
|
13519
|
+
const chatGenerationParams = isObject(request?.chatGenerationParams) ? request.chatGenerationParams : {};
|
|
13520
|
+
const httpReferer = request?.httpReferer;
|
|
13521
|
+
const xTitle = request?.xTitle;
|
|
13522
|
+
const { messages, ...metadata } = chatGenerationParams;
|
|
13523
|
+
return {
|
|
13524
|
+
input: messages,
|
|
13525
|
+
metadata: buildOpenRouterMetadata(metadata, httpReferer, xTitle)
|
|
13526
|
+
};
|
|
13527
|
+
},
|
|
13528
|
+
extractOutput: (result) => {
|
|
13529
|
+
return isObject(result) ? result.choices : void 0;
|
|
13530
|
+
},
|
|
13531
|
+
extractMetrics: (result, startTime) => {
|
|
13532
|
+
const metrics = parseOpenRouterMetricsFromUsage(result?.usage);
|
|
13533
|
+
if (startTime) {
|
|
13534
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
13535
|
+
}
|
|
13536
|
+
return metrics;
|
|
13537
|
+
},
|
|
13538
|
+
aggregateChunks: aggregateOpenRouterChatChunks
|
|
13539
|
+
})
|
|
12561
13540
|
);
|
|
12562
|
-
|
|
12563
|
-
|
|
12564
|
-
|
|
12565
|
-
|
|
12566
|
-
|
|
12567
|
-
|
|
12568
|
-
|
|
12569
|
-
|
|
12570
|
-
|
|
12571
|
-
|
|
12572
|
-
|
|
12573
|
-
|
|
12574
|
-
|
|
12575
|
-
|
|
12576
|
-
|
|
12577
|
-
|
|
12578
|
-
|
|
12579
|
-
|
|
12580
|
-
|
|
12581
|
-
|
|
12582
|
-
|
|
12583
|
-
|
|
12584
|
-
|
|
12585
|
-
|
|
12586
|
-
|
|
12587
|
-
|
|
12588
|
-
|
|
12589
|
-
|
|
12590
|
-
|
|
12591
|
-
|
|
12592
|
-
|
|
12593
|
-
|
|
12594
|
-
|
|
12595
|
-
|
|
12596
|
-
return;
|
|
12597
|
-
}
|
|
12598
|
-
try {
|
|
12599
|
-
await endSpanWithResult(await originalGetResponse(), fallbackOutput);
|
|
12600
|
-
} catch {
|
|
12601
|
-
await endSpanWithResult(void 0, fallbackOutput);
|
|
12602
|
-
}
|
|
12603
|
-
};
|
|
12604
|
-
if (originalGetResponse) {
|
|
12605
|
-
resultLike.getResponse = async (...args) => {
|
|
12606
|
-
return await withCurrent(span, async () => {
|
|
12607
|
-
try {
|
|
12608
|
-
const response = await originalGetResponse(...args);
|
|
12609
|
-
await endSpanWithResult(response);
|
|
12610
|
-
return response;
|
|
12611
|
-
} catch (error) {
|
|
12612
|
-
endSpanWithError(error);
|
|
12613
|
-
throw error;
|
|
12614
|
-
}
|
|
12615
|
-
});
|
|
12616
|
-
};
|
|
12617
|
-
}
|
|
12618
|
-
if (typeof resultLike.getText === "function") {
|
|
12619
|
-
const originalGetText = resultLike.getText.bind(resultLike);
|
|
12620
|
-
resultLike.getText = async (...args) => {
|
|
12621
|
-
return await withCurrent(span, async () => {
|
|
12622
|
-
try {
|
|
12623
|
-
const text = await originalGetText(...args);
|
|
12624
|
-
await finalizeFromResponse(text);
|
|
12625
|
-
return text;
|
|
12626
|
-
} catch (error) {
|
|
12627
|
-
endSpanWithError(error);
|
|
12628
|
-
throw error;
|
|
13541
|
+
this.unsubscribers.push(
|
|
13542
|
+
traceAsyncChannel(openRouterChannels.embeddingsGenerate, {
|
|
13543
|
+
name: "openrouter.embeddings.generate",
|
|
13544
|
+
type: "llm" /* LLM */,
|
|
13545
|
+
extractInput: (args) => {
|
|
13546
|
+
const request = getOpenRouterRequestArg(args);
|
|
13547
|
+
const requestBody = isObject(request?.requestBody) ? request.requestBody : {};
|
|
13548
|
+
const httpReferer = request?.httpReferer;
|
|
13549
|
+
const xTitle = request?.xTitle;
|
|
13550
|
+
const { input, ...metadata } = requestBody;
|
|
13551
|
+
return {
|
|
13552
|
+
input,
|
|
13553
|
+
metadata: buildOpenRouterEmbeddingMetadata(
|
|
13554
|
+
metadata,
|
|
13555
|
+
httpReferer,
|
|
13556
|
+
xTitle
|
|
13557
|
+
)
|
|
13558
|
+
};
|
|
13559
|
+
},
|
|
13560
|
+
extractOutput: (result) => {
|
|
13561
|
+
if (!isObject(result)) {
|
|
13562
|
+
return void 0;
|
|
13563
|
+
}
|
|
13564
|
+
const embedding = result.data?.[0]?.embedding;
|
|
13565
|
+
return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
|
|
13566
|
+
},
|
|
13567
|
+
extractMetadata: (result) => {
|
|
13568
|
+
if (!isObject(result)) {
|
|
13569
|
+
return void 0;
|
|
13570
|
+
}
|
|
13571
|
+
return extractOpenRouterResponseMetadata(result);
|
|
13572
|
+
},
|
|
13573
|
+
extractMetrics: (result) => {
|
|
13574
|
+
return isObject(result) ? parseOpenRouterMetricsFromUsage(result.usage) : {};
|
|
12629
13575
|
}
|
|
12630
|
-
})
|
|
12631
|
-
|
|
12632
|
-
|
|
12633
|
-
|
|
12634
|
-
|
|
12635
|
-
|
|
12636
|
-
|
|
12637
|
-
|
|
12638
|
-
|
|
12639
|
-
|
|
12640
|
-
|
|
12641
|
-
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
|
|
12646
|
-
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
|
|
12653
|
-
|
|
12654
|
-
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
|
|
12658
|
-
|
|
12659
|
-
|
|
12660
|
-
|
|
12661
|
-
|
|
12662
|
-
|
|
12663
|
-
|
|
12664
|
-
|
|
12665
|
-
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
12669
|
-
|
|
12670
|
-
|
|
12671
|
-
|
|
12672
|
-
|
|
12673
|
-
|
|
12674
|
-
|
|
12675
|
-
const childSpan = startOpenRouterCallModelTurnSpan({
|
|
12676
|
-
request: resolvedRequest,
|
|
12677
|
-
step: tracedTurnCount + 1,
|
|
12678
|
-
stepType: tracedTurnCount === 0 ? "initial" : "continue"
|
|
12679
|
-
});
|
|
12680
|
-
return await withCurrent(childSpan, async () => {
|
|
12681
|
-
try {
|
|
12682
|
-
const response = await originalGetInitialResponse(...args);
|
|
12683
|
-
tracedTurnCount++;
|
|
12684
|
-
finishOpenRouterCallModelTurnSpan({
|
|
12685
|
-
response,
|
|
12686
|
-
step: tracedTurnCount,
|
|
12687
|
-
stepType: tracedTurnCount === 1 ? "initial" : "continue",
|
|
12688
|
-
span: childSpan
|
|
12689
|
-
});
|
|
12690
|
-
return response;
|
|
12691
|
-
} catch (error) {
|
|
12692
|
-
childSpan.log({
|
|
12693
|
-
error: normalizeError(error).message
|
|
13576
|
+
})
|
|
13577
|
+
);
|
|
13578
|
+
this.unsubscribers.push(
|
|
13579
|
+
traceStreamingChannel(openRouterChannels.betaResponsesSend, {
|
|
13580
|
+
name: "openrouter.beta.responses.send",
|
|
13581
|
+
type: "llm" /* LLM */,
|
|
13582
|
+
extractInput: (args) => {
|
|
13583
|
+
const request = getOpenRouterRequestArg(args);
|
|
13584
|
+
const openResponsesRequest = isObject(request?.openResponsesRequest) ? request.openResponsesRequest : {};
|
|
13585
|
+
const httpReferer = request?.httpReferer;
|
|
13586
|
+
const xTitle = request?.xTitle;
|
|
13587
|
+
const { input, ...metadata } = openResponsesRequest;
|
|
13588
|
+
return {
|
|
13589
|
+
input,
|
|
13590
|
+
metadata: buildOpenRouterMetadata(metadata, httpReferer, xTitle)
|
|
13591
|
+
};
|
|
13592
|
+
},
|
|
13593
|
+
extractOutput: (result) => extractOpenRouterResponseOutput(result),
|
|
13594
|
+
extractMetadata: (result) => extractOpenRouterResponseMetadata(result),
|
|
13595
|
+
extractMetrics: (result, startTime) => {
|
|
13596
|
+
const metrics = parseOpenRouterMetricsFromUsage(result?.usage);
|
|
13597
|
+
if (startTime) {
|
|
13598
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
13599
|
+
}
|
|
13600
|
+
return metrics;
|
|
13601
|
+
},
|
|
13602
|
+
aggregateChunks: aggregateOpenRouterResponseStreamEvents
|
|
13603
|
+
})
|
|
13604
|
+
);
|
|
13605
|
+
this.unsubscribers.push(
|
|
13606
|
+
traceSyncStreamChannel(openRouterChannels.callModel, {
|
|
13607
|
+
name: "openrouter.callModel",
|
|
13608
|
+
type: "llm" /* LLM */,
|
|
13609
|
+
extractInput: (args) => {
|
|
13610
|
+
const request = getOpenRouterCallModelRequestArg(args);
|
|
13611
|
+
return {
|
|
13612
|
+
input: request ? extractOpenRouterCallModelInput(request) : void 0,
|
|
13613
|
+
metadata: request ? extractOpenRouterCallModelMetadata(request) : { provider: "openrouter" }
|
|
13614
|
+
};
|
|
13615
|
+
},
|
|
13616
|
+
patchResult: ({ endEvent, result, span }) => {
|
|
13617
|
+
return patchOpenRouterCallModelResult({
|
|
13618
|
+
request: getOpenRouterCallModelRequestArg(endEvent.arguments),
|
|
13619
|
+
result,
|
|
13620
|
+
span
|
|
12694
13621
|
});
|
|
12695
|
-
childSpan.end();
|
|
12696
|
-
throw error;
|
|
12697
13622
|
}
|
|
12698
|
-
})
|
|
12699
|
-
|
|
12700
|
-
|
|
12701
|
-
|
|
12702
|
-
|
|
12703
|
-
|
|
12704
|
-
|
|
12705
|
-
|
|
12706
|
-
|
|
12707
|
-
|
|
12708
|
-
|
|
12709
|
-
|
|
12710
|
-
|
|
12711
|
-
|
|
12712
|
-
|
|
12713
|
-
|
|
12714
|
-
|
|
12715
|
-
|
|
12716
|
-
|
|
12717
|
-
|
|
12718
|
-
|
|
12719
|
-
|
|
12720
|
-
|
|
12721
|
-
|
|
12722
|
-
|
|
12723
|
-
|
|
12724
|
-
|
|
12725
|
-
|
|
12726
|
-
|
|
12727
|
-
|
|
12728
|
-
|
|
12729
|
-
|
|
12730
|
-
|
|
12731
|
-
|
|
12732
|
-
|
|
13623
|
+
})
|
|
13624
|
+
);
|
|
13625
|
+
this.unsubscribers.push(
|
|
13626
|
+
traceAsyncChannel(openRouterChannels.callModelTurn, {
|
|
13627
|
+
name: "openrouter.beta.responses.send",
|
|
13628
|
+
type: "llm" /* LLM */,
|
|
13629
|
+
extractInput: (args, event) => {
|
|
13630
|
+
const request = getOpenRouterCallModelRequestArg(args);
|
|
13631
|
+
const metadata = request ? extractOpenRouterCallModelMetadata(request) : { provider: "openrouter" };
|
|
13632
|
+
if (isObject(metadata) && "tools" in metadata) {
|
|
13633
|
+
delete metadata.tools;
|
|
13634
|
+
}
|
|
13635
|
+
return {
|
|
13636
|
+
input: request ? extractOpenRouterCallModelInput(request) : void 0,
|
|
13637
|
+
metadata: {
|
|
13638
|
+
...metadata,
|
|
13639
|
+
step: event.step,
|
|
13640
|
+
step_type: event.stepType
|
|
13641
|
+
}
|
|
13642
|
+
};
|
|
13643
|
+
},
|
|
13644
|
+
extractOutput: (result) => extractOpenRouterResponseOutput(result),
|
|
13645
|
+
extractMetadata: (result, event) => {
|
|
13646
|
+
if (!isObject(result)) {
|
|
13647
|
+
return {
|
|
13648
|
+
step: event?.step,
|
|
13649
|
+
step_type: event?.stepType
|
|
13650
|
+
};
|
|
13651
|
+
}
|
|
13652
|
+
return {
|
|
13653
|
+
...extractOpenRouterResponseMetadata(result) || {},
|
|
13654
|
+
...event?.step !== void 0 ? { step: event.step } : {},
|
|
13655
|
+
...event?.stepType ? { step_type: event.stepType } : {}
|
|
13656
|
+
};
|
|
13657
|
+
},
|
|
13658
|
+
extractMetrics: (result) => isObject(result) ? parseOpenRouterMetricsFromUsage(result.usage) : {}
|
|
13659
|
+
})
|
|
13660
|
+
);
|
|
13661
|
+
this.unsubscribers.push(
|
|
13662
|
+
traceStreamingChannel(openRouterChannels.toolExecute, {
|
|
13663
|
+
name: "openrouter.tool",
|
|
13664
|
+
type: "tool" /* TOOL */,
|
|
13665
|
+
extractInput: (args, event) => ({
|
|
13666
|
+
input: args[0],
|
|
13667
|
+
metadata: {
|
|
13668
|
+
provider: "openrouter",
|
|
13669
|
+
tool_name: event.toolName,
|
|
13670
|
+
...event.toolCallId ? { tool_call_id: event.toolCallId } : {}
|
|
13671
|
+
}
|
|
13672
|
+
}),
|
|
13673
|
+
extractOutput: (result) => result,
|
|
13674
|
+
extractMetrics: () => ({}),
|
|
13675
|
+
aggregateChunks: (chunks) => ({
|
|
13676
|
+
output: chunks.length > 0 ? chunks[chunks.length - 1] : void 0,
|
|
13677
|
+
metrics: {}
|
|
13678
|
+
})
|
|
13679
|
+
})
|
|
13680
|
+
);
|
|
13681
|
+
const callModelChannel = openRouterChannels.callModel.tracingChannel();
|
|
13682
|
+
const callModelHandlers = {
|
|
13683
|
+
start: (event) => {
|
|
13684
|
+
const request = getOpenRouterCallModelRequestArg(event.arguments);
|
|
13685
|
+
if (!request) {
|
|
13686
|
+
return;
|
|
12733
13687
|
}
|
|
12734
|
-
|
|
13688
|
+
patchOpenRouterCallModelRequestTools(request);
|
|
13689
|
+
}
|
|
12735
13690
|
};
|
|
13691
|
+
callModelChannel.subscribe(callModelHandlers);
|
|
13692
|
+
this.unsubscribers.push(() => {
|
|
13693
|
+
callModelChannel.unsubscribe(callModelHandlers);
|
|
13694
|
+
});
|
|
12736
13695
|
}
|
|
12737
|
-
|
|
12738
|
-
|
|
12739
|
-
|
|
12740
|
-
|
|
12741
|
-
return tool;
|
|
12742
|
-
}
|
|
12743
|
-
const toolName = tool.function.name || "tool";
|
|
12744
|
-
const originalExecute = tool.function.execute;
|
|
12745
|
-
const wrappedTool = {
|
|
12746
|
-
...tool,
|
|
12747
|
-
function: {
|
|
12748
|
-
...tool.function,
|
|
12749
|
-
execute(...args) {
|
|
12750
|
-
return traceToolExecution({
|
|
12751
|
-
args,
|
|
12752
|
-
execute: () => Reflect.apply(originalExecute, this, args),
|
|
12753
|
-
toolCallId: getToolCallId(args[1]),
|
|
12754
|
-
toolName
|
|
12755
|
-
});
|
|
12756
|
-
}
|
|
12757
|
-
}
|
|
12758
|
-
};
|
|
12759
|
-
Object.defineProperty(wrappedTool, OPENROUTER_WRAPPED_TOOL, {
|
|
12760
|
-
value: true,
|
|
12761
|
-
enumerable: false,
|
|
12762
|
-
configurable: false
|
|
12763
|
-
});
|
|
12764
|
-
return wrappedTool;
|
|
12765
|
-
}
|
|
12766
|
-
function isWrappedTool(tool) {
|
|
12767
|
-
return Boolean(tool[OPENROUTER_WRAPPED_TOOL]);
|
|
12768
|
-
}
|
|
12769
|
-
function isWrappedCallModelResult(value) {
|
|
12770
|
-
return Boolean(
|
|
12771
|
-
isObject(value) && value[OPENROUTER_WRAPPED_CALL_MODEL_RESULT]
|
|
12772
|
-
);
|
|
12773
|
-
}
|
|
12774
|
-
function traceToolExecution(args) {
|
|
12775
|
-
const tracingChannel2 = openRouterChannels.toolExecute.tracingChannel();
|
|
12776
|
-
const input = args.args.length > 0 ? args.args[0] : void 0;
|
|
12777
|
-
const event = {
|
|
12778
|
-
arguments: [input],
|
|
12779
|
-
span_info: {
|
|
12780
|
-
name: args.toolName
|
|
12781
|
-
},
|
|
12782
|
-
toolCallId: args.toolCallId,
|
|
12783
|
-
toolName: args.toolName
|
|
12784
|
-
};
|
|
12785
|
-
tracingChannel2.start.publish(event);
|
|
12786
|
-
try {
|
|
12787
|
-
const result = args.execute();
|
|
12788
|
-
return publishToolResult(tracingChannel2, event, result);
|
|
12789
|
-
} catch (error) {
|
|
12790
|
-
event.error = normalizeError(error);
|
|
12791
|
-
tracingChannel2.error.publish(event);
|
|
12792
|
-
throw error;
|
|
13696
|
+
};
|
|
13697
|
+
function normalizeArgs(args) {
|
|
13698
|
+
if (Array.isArray(args)) {
|
|
13699
|
+
return args;
|
|
12793
13700
|
}
|
|
12794
|
-
|
|
12795
|
-
|
|
12796
|
-
if (isPromiseLike(result)) {
|
|
12797
|
-
return result.then(
|
|
12798
|
-
(resolved) => {
|
|
12799
|
-
event.result = resolved;
|
|
12800
|
-
tracingChannel2.asyncEnd.publish(event);
|
|
12801
|
-
return resolved;
|
|
12802
|
-
},
|
|
12803
|
-
(error) => {
|
|
12804
|
-
event.error = normalizeError(error);
|
|
12805
|
-
tracingChannel2.error.publish(event);
|
|
12806
|
-
throw error;
|
|
12807
|
-
}
|
|
12808
|
-
);
|
|
13701
|
+
if (isArrayLike(args)) {
|
|
13702
|
+
return Array.from(args);
|
|
12809
13703
|
}
|
|
12810
|
-
|
|
12811
|
-
tracingChannel2.asyncEnd.publish(event);
|
|
12812
|
-
return result;
|
|
12813
|
-
}
|
|
12814
|
-
function getToolCallId(context) {
|
|
12815
|
-
const toolContext = context;
|
|
12816
|
-
return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
|
|
13704
|
+
return [args];
|
|
12817
13705
|
}
|
|
12818
|
-
function
|
|
12819
|
-
|
|
12820
|
-
...extractOpenRouterResponseMetadata(response) || {},
|
|
12821
|
-
...turnCount !== void 0 ? { turn_count: turnCount } : {}
|
|
12822
|
-
};
|
|
12823
|
-
return Object.keys(combined).length > 0 ? combined : void 0;
|
|
13706
|
+
function isArrayLike(value) {
|
|
13707
|
+
return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
|
|
12824
13708
|
}
|
|
12825
|
-
function
|
|
12826
|
-
|
|
12827
|
-
|
|
13709
|
+
function getOpenRouterRequestArg(args) {
|
|
13710
|
+
const normalizedArgs = normalizeArgs(args);
|
|
13711
|
+
const keyedCandidate = normalizedArgs.find(
|
|
13712
|
+
(arg) => isObject(arg) && ("chatGenerationParams" in arg || "requestBody" in arg || "openResponsesRequest" in arg)
|
|
13713
|
+
);
|
|
13714
|
+
if (isObject(keyedCandidate)) {
|
|
13715
|
+
return keyedCandidate;
|
|
12828
13716
|
}
|
|
12829
|
-
|
|
13717
|
+
const firstObjectArg = normalizedArgs.find((arg) => isObject(arg));
|
|
13718
|
+
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
12830
13719
|
}
|
|
12831
|
-
function
|
|
12832
|
-
|
|
12833
|
-
|
|
12834
|
-
}
|
|
12835
|
-
return result.allToolExecutionRounds.filter((round) => isObject(round)).map((round) => ({
|
|
12836
|
-
response: isObject(round.response) ? round.response : void 0,
|
|
12837
|
-
round: typeof round.round === "number" ? round.round : void 0,
|
|
12838
|
-
toolResults: Array.isArray(round.toolResults) ? round.toolResults : []
|
|
12839
|
-
})).filter((round) => round.response !== void 0);
|
|
13720
|
+
function getOpenRouterCallModelRequestArg(args) {
|
|
13721
|
+
const firstObjectArg = normalizeArgs(args).find((arg) => isObject(arg));
|
|
13722
|
+
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
12840
13723
|
}
|
|
12841
|
-
|
|
13724
|
+
var TOKEN_NAME_MAP2 = {
|
|
13725
|
+
promptTokens: "prompt_tokens",
|
|
13726
|
+
inputTokens: "prompt_tokens",
|
|
13727
|
+
completionTokens: "completion_tokens",
|
|
13728
|
+
outputTokens: "completion_tokens",
|
|
13729
|
+
totalTokens: "tokens",
|
|
13730
|
+
prompt_tokens: "prompt_tokens",
|
|
13731
|
+
input_tokens: "prompt_tokens",
|
|
13732
|
+
completion_tokens: "completion_tokens",
|
|
13733
|
+
output_tokens: "completion_tokens",
|
|
13734
|
+
total_tokens: "tokens"
|
|
13735
|
+
};
|
|
13736
|
+
var TOKEN_DETAIL_PREFIX_MAP = {
|
|
13737
|
+
promptTokensDetails: "prompt",
|
|
13738
|
+
inputTokensDetails: "prompt",
|
|
13739
|
+
completionTokensDetails: "completion",
|
|
13740
|
+
outputTokensDetails: "completion",
|
|
13741
|
+
costDetails: "cost",
|
|
13742
|
+
prompt_tokens_details: "prompt",
|
|
13743
|
+
input_tokens_details: "prompt",
|
|
13744
|
+
completion_tokens_details: "completion",
|
|
13745
|
+
output_tokens_details: "completion",
|
|
13746
|
+
cost_details: "cost"
|
|
13747
|
+
};
|
|
13748
|
+
function camelToSnake(value) {
|
|
13749
|
+
return value.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
|
|
13750
|
+
}
|
|
13751
|
+
function parseOpenRouterMetricsFromUsage(usage) {
|
|
13752
|
+
if (!isObject(usage)) {
|
|
13753
|
+
return {};
|
|
13754
|
+
}
|
|
12842
13755
|
const metrics = {};
|
|
12843
|
-
const
|
|
12844
|
-
|
|
12845
|
-
|
|
12846
|
-
|
|
12847
|
-
|
|
12848
|
-
|
|
12849
|
-
|
|
12850
|
-
|
|
13756
|
+
for (const [name, value] of Object.entries(usage)) {
|
|
13757
|
+
if (typeof value === "number") {
|
|
13758
|
+
metrics[TOKEN_NAME_MAP2[name] || camelToSnake(name)] = value;
|
|
13759
|
+
continue;
|
|
13760
|
+
}
|
|
13761
|
+
if (!isObject(value)) {
|
|
13762
|
+
continue;
|
|
13763
|
+
}
|
|
13764
|
+
const prefix = TOKEN_DETAIL_PREFIX_MAP[name];
|
|
13765
|
+
if (!prefix) {
|
|
13766
|
+
continue;
|
|
13767
|
+
}
|
|
13768
|
+
for (const [nestedName, nestedValue] of Object.entries(value)) {
|
|
13769
|
+
if (typeof nestedValue !== "number") {
|
|
13770
|
+
continue;
|
|
13771
|
+
}
|
|
13772
|
+
metrics[`${prefix}_${camelToSnake(nestedName)}`] = nestedValue;
|
|
12851
13773
|
}
|
|
12852
13774
|
}
|
|
12853
13775
|
return metrics;
|
|
12854
13776
|
}
|
|
12855
|
-
function
|
|
12856
|
-
|
|
12857
|
-
|
|
12858
|
-
|
|
12859
|
-
|
|
12860
|
-
)
|
|
13777
|
+
function extractOpenRouterUsageMetadata(usage) {
|
|
13778
|
+
if (!isObject(usage)) {
|
|
13779
|
+
return void 0;
|
|
13780
|
+
}
|
|
13781
|
+
const metadata = {};
|
|
13782
|
+
if (typeof usage.isByok === "boolean") {
|
|
13783
|
+
metadata.is_byok = usage.isByok;
|
|
13784
|
+
} else if (typeof usage.is_byok === "boolean") {
|
|
13785
|
+
metadata.is_byok = usage.is_byok;
|
|
13786
|
+
}
|
|
13787
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
12861
13788
|
}
|
|
12862
|
-
|
|
12863
|
-
|
|
12864
|
-
|
|
12865
|
-
|
|
12866
|
-
|
|
13789
|
+
var OMITTED_OPENROUTER_KEYS = /* @__PURE__ */ new Set([
|
|
13790
|
+
"execute",
|
|
13791
|
+
"render",
|
|
13792
|
+
"nextTurnParams",
|
|
13793
|
+
"requireApproval"
|
|
13794
|
+
]);
|
|
13795
|
+
function parseOpenRouterModelString(model) {
|
|
13796
|
+
if (typeof model !== "string") {
|
|
13797
|
+
return { model };
|
|
12867
13798
|
}
|
|
12868
|
-
|
|
12869
|
-
|
|
12870
|
-
|
|
12871
|
-
|
|
12872
|
-
|
|
12873
|
-
|
|
12874
|
-
|
|
12875
|
-
|
|
12876
|
-
...metadata,
|
|
12877
|
-
step: args.step,
|
|
12878
|
-
step_type: args.stepType
|
|
12879
|
-
}
|
|
12880
|
-
}
|
|
12881
|
-
});
|
|
13799
|
+
const slashIndex = model.indexOf("/");
|
|
13800
|
+
if (slashIndex > 0 && slashIndex < model.length - 1) {
|
|
13801
|
+
return {
|
|
13802
|
+
provider: model.substring(0, slashIndex),
|
|
13803
|
+
model: model.substring(slashIndex + 1)
|
|
13804
|
+
};
|
|
13805
|
+
}
|
|
13806
|
+
return { model };
|
|
12882
13807
|
}
|
|
12883
|
-
function
|
|
12884
|
-
|
|
12885
|
-
|
|
12886
|
-
|
|
13808
|
+
function isZodSchema3(value) {
|
|
13809
|
+
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
13810
|
+
}
|
|
13811
|
+
function serializeZodSchema3(schema) {
|
|
13812
|
+
try {
|
|
13813
|
+
return zodToJsonSchema(schema);
|
|
13814
|
+
} catch {
|
|
13815
|
+
return {
|
|
13816
|
+
type: "object",
|
|
13817
|
+
description: "Zod schema (conversion failed)"
|
|
13818
|
+
};
|
|
12887
13819
|
}
|
|
12888
|
-
args.span.log({
|
|
12889
|
-
output: extractOpenRouterResponseOutput(args.response),
|
|
12890
|
-
...extractOpenRouterResponseMetadata(args.response) ? {
|
|
12891
|
-
metadata: {
|
|
12892
|
-
...extractOpenRouterResponseMetadata(args.response),
|
|
12893
|
-
...args.step !== void 0 ? { step: args.step } : {},
|
|
12894
|
-
...args.stepType ? { step_type: args.stepType } : {}
|
|
12895
|
-
}
|
|
12896
|
-
} : {},
|
|
12897
|
-
metrics: parseOpenRouterMetricsFromUsage(args.response.usage)
|
|
12898
|
-
});
|
|
12899
|
-
args.span.end();
|
|
12900
13820
|
}
|
|
12901
|
-
function
|
|
12902
|
-
if (isObject(
|
|
12903
|
-
return
|
|
13821
|
+
function serializeOpenRouterTool(tool) {
|
|
13822
|
+
if (!isObject(tool)) {
|
|
13823
|
+
return tool;
|
|
12904
13824
|
}
|
|
12905
|
-
|
|
13825
|
+
const serialized = {};
|
|
13826
|
+
for (const [key, value] of Object.entries(tool)) {
|
|
13827
|
+
if (OMITTED_OPENROUTER_KEYS.has(key)) {
|
|
13828
|
+
continue;
|
|
13829
|
+
}
|
|
13830
|
+
if (key === "function" && isObject(value)) {
|
|
13831
|
+
serialized.function = sanitizeOpenRouterLoggedValue(value);
|
|
13832
|
+
continue;
|
|
13833
|
+
}
|
|
13834
|
+
serialized[key] = sanitizeOpenRouterLoggedValue(value);
|
|
13835
|
+
}
|
|
13836
|
+
return serialized;
|
|
12906
13837
|
}
|
|
12907
|
-
function
|
|
12908
|
-
if (!
|
|
13838
|
+
function serializeOpenRouterToolsForLogging(tools) {
|
|
13839
|
+
if (!Array.isArray(tools)) {
|
|
12909
13840
|
return void 0;
|
|
12910
13841
|
}
|
|
12911
|
-
return
|
|
12912
|
-
...request,
|
|
12913
|
-
input: buildNextOpenRouterCallModelInput(
|
|
12914
|
-
extractOpenRouterCallModelInput(request),
|
|
12915
|
-
isObject(currentResponse) ? currentResponse : {},
|
|
12916
|
-
toolResults
|
|
12917
|
-
),
|
|
12918
|
-
stream: false
|
|
12919
|
-
};
|
|
13842
|
+
return tools.map((tool) => serializeOpenRouterTool(tool));
|
|
12920
13843
|
}
|
|
12921
|
-
function
|
|
12922
|
-
|
|
12923
|
-
|
|
12924
|
-
|
|
12925
|
-
|
|
12926
|
-
|
|
12927
|
-
|
|
12928
|
-
|
|
12929
|
-
|
|
12930
|
-
|
|
12931
|
-
|
|
12932
|
-
|
|
12933
|
-
|
|
12934
|
-
|
|
12935
|
-
|
|
12936
|
-
|
|
12937
|
-
|
|
12938
|
-
|
|
12939
|
-
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
},
|
|
12943
|
-
return(value) {
|
|
12944
|
-
if (typeof iterator.return !== "function") {
|
|
12945
|
-
return args.finalize().then(() => ({
|
|
12946
|
-
done: true,
|
|
12947
|
-
value
|
|
12948
|
-
}));
|
|
12949
|
-
}
|
|
12950
|
-
return withCurrent(args.span, () => iterator.return(value)).then(
|
|
12951
|
-
async (result) => {
|
|
12952
|
-
await args.finalize();
|
|
12953
|
-
return result;
|
|
12954
|
-
},
|
|
12955
|
-
(error) => {
|
|
12956
|
-
args.onError(error);
|
|
12957
|
-
throw error;
|
|
12958
|
-
}
|
|
12959
|
-
);
|
|
12960
|
-
},
|
|
12961
|
-
throw(error) {
|
|
12962
|
-
args.onError(error);
|
|
12963
|
-
if (typeof iterator.throw !== "function") {
|
|
12964
|
-
return Promise.reject(error);
|
|
12965
|
-
}
|
|
12966
|
-
return withCurrent(args.span, () => iterator.throw(error));
|
|
12967
|
-
},
|
|
12968
|
-
[Symbol.asyncIterator]() {
|
|
12969
|
-
return this;
|
|
12970
|
-
}
|
|
12971
|
-
};
|
|
13844
|
+
function sanitizeOpenRouterLoggedValue(value) {
|
|
13845
|
+
if (isZodSchema3(value)) {
|
|
13846
|
+
return serializeZodSchema3(value);
|
|
13847
|
+
}
|
|
13848
|
+
if (typeof value === "function") {
|
|
13849
|
+
return "[Function]";
|
|
13850
|
+
}
|
|
13851
|
+
if (Array.isArray(value)) {
|
|
13852
|
+
return value.map((entry) => sanitizeOpenRouterLoggedValue(entry));
|
|
13853
|
+
}
|
|
13854
|
+
if (!isObject(value)) {
|
|
13855
|
+
return value;
|
|
13856
|
+
}
|
|
13857
|
+
const sanitized = {};
|
|
13858
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
13859
|
+
if (OMITTED_OPENROUTER_KEYS.has(key)) {
|
|
13860
|
+
continue;
|
|
13861
|
+
}
|
|
13862
|
+
if (key === "tools" && Array.isArray(entry)) {
|
|
13863
|
+
sanitized.tools = serializeOpenRouterToolsForLogging(entry);
|
|
13864
|
+
continue;
|
|
12972
13865
|
}
|
|
13866
|
+
sanitized[key] = sanitizeOpenRouterLoggedValue(entry);
|
|
13867
|
+
}
|
|
13868
|
+
return sanitized;
|
|
13869
|
+
}
|
|
13870
|
+
function buildOpenRouterMetadata(metadata, httpReferer, xTitle) {
|
|
13871
|
+
const sanitized = sanitizeOpenRouterLoggedValue(metadata);
|
|
13872
|
+
const metadataRecord = isObject(sanitized) ? sanitized : {};
|
|
13873
|
+
const { model, provider: providerRouting, ...rest } = metadataRecord;
|
|
13874
|
+
const normalizedModel = parseOpenRouterModelString(model);
|
|
13875
|
+
return {
|
|
13876
|
+
...rest,
|
|
13877
|
+
...normalizedModel.model !== void 0 ? { model: normalizedModel.model } : {},
|
|
13878
|
+
...providerRouting !== void 0 ? { providerRouting } : {},
|
|
13879
|
+
...httpReferer !== void 0 ? { httpReferer } : {},
|
|
13880
|
+
...xTitle !== void 0 ? { xTitle } : {},
|
|
13881
|
+
provider: normalizedModel.provider || "openrouter"
|
|
12973
13882
|
};
|
|
12974
13883
|
}
|
|
12975
|
-
function
|
|
12976
|
-
|
|
13884
|
+
function buildOpenRouterEmbeddingMetadata(metadata, httpReferer, xTitle) {
|
|
13885
|
+
const normalized = buildOpenRouterMetadata(metadata, httpReferer, xTitle);
|
|
13886
|
+
return typeof normalized.model === "string" ? {
|
|
13887
|
+
...normalized,
|
|
13888
|
+
embedding_model: normalized.model
|
|
13889
|
+
} : normalized;
|
|
12977
13890
|
}
|
|
12978
|
-
function
|
|
12979
|
-
return
|
|
13891
|
+
function extractOpenRouterCallModelInput(request) {
|
|
13892
|
+
return isObject(request) && "input" in request ? sanitizeOpenRouterLoggedValue(request.input) : void 0;
|
|
12980
13893
|
}
|
|
12981
|
-
function
|
|
12982
|
-
|
|
13894
|
+
function extractOpenRouterCallModelMetadata(request) {
|
|
13895
|
+
if (!isObject(request)) {
|
|
13896
|
+
return { provider: "openrouter" };
|
|
13897
|
+
}
|
|
13898
|
+
const { input: _input, ...metadata } = request;
|
|
13899
|
+
return buildOpenRouterMetadata(metadata, void 0, void 0);
|
|
12983
13900
|
}
|
|
12984
|
-
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
onEnable() {
|
|
12988
|
-
this.subscribeToOpenRouterChannels();
|
|
13901
|
+
function extractOpenRouterResponseMetadata(result) {
|
|
13902
|
+
if (!isObject(result)) {
|
|
13903
|
+
return void 0;
|
|
12989
13904
|
}
|
|
12990
|
-
|
|
12991
|
-
|
|
13905
|
+
const { output: _output, data: _data, usage, ...metadata } = result;
|
|
13906
|
+
const sanitized = sanitizeOpenRouterLoggedValue(metadata);
|
|
13907
|
+
const metadataRecord = isObject(sanitized) ? sanitized : {};
|
|
13908
|
+
const { model, provider, ...rest } = metadataRecord;
|
|
13909
|
+
const normalizedModel = parseOpenRouterModelString(model);
|
|
13910
|
+
const normalizedProvider = (typeof provider === "string" ? provider : void 0) || normalizedModel.provider;
|
|
13911
|
+
const usageMetadata = extractOpenRouterUsageMetadata(usage);
|
|
13912
|
+
const combined = {
|
|
13913
|
+
...rest,
|
|
13914
|
+
...normalizedModel.model !== void 0 ? { model: normalizedModel.model } : {},
|
|
13915
|
+
...usageMetadata || {},
|
|
13916
|
+
...normalizedProvider !== void 0 ? { provider: normalizedProvider } : {}
|
|
13917
|
+
};
|
|
13918
|
+
return Object.keys(combined).length > 0 ? combined : void 0;
|
|
13919
|
+
}
|
|
13920
|
+
function extractOpenRouterResponseOutput(response, fallbackOutput) {
|
|
13921
|
+
if (isObject(response) && "output" in response && response.output !== void 0) {
|
|
13922
|
+
return sanitizeOpenRouterLoggedValue(response.output);
|
|
12992
13923
|
}
|
|
12993
|
-
|
|
12994
|
-
|
|
12995
|
-
traceStreamingChannel(openRouterChannels.chatSend, {
|
|
12996
|
-
name: "openrouter.chat.send",
|
|
12997
|
-
type: "llm" /* LLM */,
|
|
12998
|
-
extractInput: (args) => {
|
|
12999
|
-
const request = getOpenRouterRequestArg(args);
|
|
13000
|
-
const chatGenerationParams = isObject(request?.chatGenerationParams) ? request.chatGenerationParams : {};
|
|
13001
|
-
const httpReferer = request?.httpReferer;
|
|
13002
|
-
const xTitle = request?.xTitle;
|
|
13003
|
-
const { messages, ...metadata } = chatGenerationParams;
|
|
13004
|
-
return {
|
|
13005
|
-
input: messages,
|
|
13006
|
-
metadata: buildOpenRouterMetadata(metadata, httpReferer, xTitle)
|
|
13007
|
-
};
|
|
13008
|
-
},
|
|
13009
|
-
extractOutput: (result) => {
|
|
13010
|
-
return isObject(result) ? result.choices : void 0;
|
|
13011
|
-
},
|
|
13012
|
-
extractMetrics: (result, startTime) => {
|
|
13013
|
-
const metrics = parseOpenRouterMetricsFromUsage(result?.usage);
|
|
13014
|
-
if (startTime) {
|
|
13015
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
13016
|
-
}
|
|
13017
|
-
return metrics;
|
|
13018
|
-
},
|
|
13019
|
-
aggregateChunks: aggregateOpenRouterChatChunks
|
|
13020
|
-
})
|
|
13021
|
-
);
|
|
13022
|
-
this.unsubscribers.push(
|
|
13023
|
-
traceAsyncChannel(openRouterChannels.embeddingsGenerate, {
|
|
13024
|
-
name: "openrouter.embeddings.generate",
|
|
13025
|
-
type: "llm" /* LLM */,
|
|
13026
|
-
extractInput: (args) => {
|
|
13027
|
-
const request = getOpenRouterRequestArg(args);
|
|
13028
|
-
const requestBody = isObject(request?.requestBody) ? request.requestBody : {};
|
|
13029
|
-
const httpReferer = request?.httpReferer;
|
|
13030
|
-
const xTitle = request?.xTitle;
|
|
13031
|
-
const { input, ...metadata } = requestBody;
|
|
13032
|
-
return {
|
|
13033
|
-
input,
|
|
13034
|
-
metadata: buildOpenRouterEmbeddingMetadata(
|
|
13035
|
-
metadata,
|
|
13036
|
-
httpReferer,
|
|
13037
|
-
xTitle
|
|
13038
|
-
)
|
|
13039
|
-
};
|
|
13040
|
-
},
|
|
13041
|
-
extractOutput: (result) => {
|
|
13042
|
-
if (!isObject(result)) {
|
|
13043
|
-
return void 0;
|
|
13044
|
-
}
|
|
13045
|
-
const embedding = result.data?.[0]?.embedding;
|
|
13046
|
-
return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
|
|
13047
|
-
},
|
|
13048
|
-
extractMetadata: (result) => {
|
|
13049
|
-
if (!isObject(result)) {
|
|
13050
|
-
return void 0;
|
|
13051
|
-
}
|
|
13052
|
-
return extractOpenRouterResponseMetadata(result);
|
|
13053
|
-
},
|
|
13054
|
-
extractMetrics: (result) => {
|
|
13055
|
-
return isObject(result) ? parseOpenRouterMetricsFromUsage(result.usage) : {};
|
|
13056
|
-
}
|
|
13057
|
-
})
|
|
13058
|
-
);
|
|
13059
|
-
this.unsubscribers.push(
|
|
13060
|
-
traceStreamingChannel(openRouterChannels.betaResponsesSend, {
|
|
13061
|
-
name: "openrouter.beta.responses.send",
|
|
13062
|
-
type: "llm" /* LLM */,
|
|
13063
|
-
extractInput: (args) => {
|
|
13064
|
-
const request = getOpenRouterRequestArg(args);
|
|
13065
|
-
const openResponsesRequest = isObject(request?.openResponsesRequest) ? request.openResponsesRequest : {};
|
|
13066
|
-
const httpReferer = request?.httpReferer;
|
|
13067
|
-
const xTitle = request?.xTitle;
|
|
13068
|
-
const { input, ...metadata } = openResponsesRequest;
|
|
13069
|
-
return {
|
|
13070
|
-
input,
|
|
13071
|
-
metadata: buildOpenRouterMetadata(metadata, httpReferer, xTitle)
|
|
13072
|
-
};
|
|
13073
|
-
},
|
|
13074
|
-
extractOutput: (result) => extractOpenRouterResponseOutput(result),
|
|
13075
|
-
extractMetadata: (result) => extractOpenRouterResponseMetadata(result),
|
|
13076
|
-
extractMetrics: (result, startTime) => {
|
|
13077
|
-
const metrics = parseOpenRouterMetricsFromUsage(result?.usage);
|
|
13078
|
-
if (startTime) {
|
|
13079
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
13080
|
-
}
|
|
13081
|
-
return metrics;
|
|
13082
|
-
},
|
|
13083
|
-
aggregateChunks: aggregateOpenRouterResponseStreamEvents
|
|
13084
|
-
})
|
|
13085
|
-
);
|
|
13086
|
-
this.unsubscribers.push(
|
|
13087
|
-
traceSyncStreamChannel(openRouterChannels.callModel, {
|
|
13088
|
-
name: "openrouter.callModel",
|
|
13089
|
-
type: "llm" /* LLM */,
|
|
13090
|
-
extractInput: (args) => {
|
|
13091
|
-
const request = getOpenRouterCallModelRequestArg(args);
|
|
13092
|
-
return {
|
|
13093
|
-
input: request ? extractOpenRouterCallModelInput(request) : void 0,
|
|
13094
|
-
metadata: request ? extractOpenRouterCallModelMetadata(request) : { provider: "openrouter" }
|
|
13095
|
-
};
|
|
13096
|
-
},
|
|
13097
|
-
patchResult: ({ endEvent, result, span }) => {
|
|
13098
|
-
return patchOpenRouterCallModelResult(
|
|
13099
|
-
span,
|
|
13100
|
-
result,
|
|
13101
|
-
getOpenRouterCallModelRequestArg(endEvent.arguments)
|
|
13102
|
-
);
|
|
13103
|
-
}
|
|
13104
|
-
})
|
|
13105
|
-
);
|
|
13106
|
-
this.unsubscribers.push(
|
|
13107
|
-
traceStreamingChannel(openRouterChannels.toolExecute, {
|
|
13108
|
-
name: "openrouter.tool",
|
|
13109
|
-
type: "tool" /* TOOL */,
|
|
13110
|
-
extractInput: (args, event) => ({
|
|
13111
|
-
input: args[0],
|
|
13112
|
-
metadata: {
|
|
13113
|
-
provider: "openrouter",
|
|
13114
|
-
tool_name: event.toolName,
|
|
13115
|
-
...event.toolCallId ? { tool_call_id: event.toolCallId } : {}
|
|
13116
|
-
}
|
|
13117
|
-
}),
|
|
13118
|
-
extractOutput: (result) => result,
|
|
13119
|
-
extractMetrics: () => ({}),
|
|
13120
|
-
aggregateChunks: (chunks) => ({
|
|
13121
|
-
output: chunks.length > 0 ? chunks[chunks.length - 1] : void 0,
|
|
13122
|
-
metrics: {}
|
|
13123
|
-
})
|
|
13124
|
-
})
|
|
13125
|
-
);
|
|
13126
|
-
const callModelChannel = openRouterChannels.callModel.tracingChannel();
|
|
13127
|
-
const callModelHandlers = {
|
|
13128
|
-
start: (event) => {
|
|
13129
|
-
const request = getOpenRouterCallModelRequestArg(event.arguments);
|
|
13130
|
-
if (!request) {
|
|
13131
|
-
return;
|
|
13132
|
-
}
|
|
13133
|
-
patchOpenRouterCallModelRequestTools(request);
|
|
13134
|
-
}
|
|
13135
|
-
};
|
|
13136
|
-
callModelChannel.subscribe(callModelHandlers);
|
|
13137
|
-
this.unsubscribers.push(() => {
|
|
13138
|
-
callModelChannel.unsubscribe(callModelHandlers);
|
|
13139
|
-
});
|
|
13924
|
+
if (fallbackOutput !== void 0) {
|
|
13925
|
+
return sanitizeOpenRouterLoggedValue(fallbackOutput);
|
|
13140
13926
|
}
|
|
13141
|
-
|
|
13142
|
-
|
|
13143
|
-
|
|
13144
|
-
|
|
13927
|
+
return void 0;
|
|
13928
|
+
}
|
|
13929
|
+
var OPENROUTER_WRAPPED_TOOL = Symbol("braintrust.openrouter.wrappedTool");
|
|
13930
|
+
function patchOpenRouterCallModelRequestTools(request) {
|
|
13931
|
+
if (!Array.isArray(request.tools) || request.tools.length === 0) {
|
|
13932
|
+
return void 0;
|
|
13145
13933
|
}
|
|
13146
|
-
|
|
13147
|
-
|
|
13934
|
+
const originalTools = request.tools;
|
|
13935
|
+
const wrappedTools = originalTools.map((tool) => wrapOpenRouterTool(tool));
|
|
13936
|
+
const didPatch = wrappedTools.some(
|
|
13937
|
+
(tool, index) => tool !== originalTools[index]
|
|
13938
|
+
);
|
|
13939
|
+
if (!didPatch) {
|
|
13940
|
+
return void 0;
|
|
13941
|
+
}
|
|
13942
|
+
request.tools = wrappedTools;
|
|
13943
|
+
return () => {
|
|
13944
|
+
request.tools = originalTools;
|
|
13945
|
+
};
|
|
13946
|
+
}
|
|
13947
|
+
function wrapOpenRouterTool(tool) {
|
|
13948
|
+
if (isWrappedTool(tool) || !tool.function || typeof tool.function !== "object" || typeof tool.function.execute !== "function") {
|
|
13949
|
+
return tool;
|
|
13950
|
+
}
|
|
13951
|
+
const toolName = tool.function.name || "tool";
|
|
13952
|
+
const originalExecute = tool.function.execute;
|
|
13953
|
+
const wrappedTool = {
|
|
13954
|
+
...tool,
|
|
13955
|
+
function: {
|
|
13956
|
+
...tool.function,
|
|
13957
|
+
execute(...args) {
|
|
13958
|
+
return traceToolExecution({
|
|
13959
|
+
args,
|
|
13960
|
+
execute: () => Reflect.apply(originalExecute, this, args),
|
|
13961
|
+
toolCallId: getToolCallId(args[1]),
|
|
13962
|
+
toolName
|
|
13963
|
+
});
|
|
13964
|
+
}
|
|
13965
|
+
}
|
|
13966
|
+
};
|
|
13967
|
+
Object.defineProperty(wrappedTool, OPENROUTER_WRAPPED_TOOL, {
|
|
13968
|
+
value: true,
|
|
13969
|
+
enumerable: false,
|
|
13970
|
+
configurable: false
|
|
13971
|
+
});
|
|
13972
|
+
return wrappedTool;
|
|
13973
|
+
}
|
|
13974
|
+
function isWrappedTool(tool) {
|
|
13975
|
+
return Boolean(tool[OPENROUTER_WRAPPED_TOOL]);
|
|
13976
|
+
}
|
|
13977
|
+
function traceToolExecution(args) {
|
|
13978
|
+
const tracingChannel2 = openRouterChannels.toolExecute.tracingChannel();
|
|
13979
|
+
const input = args.args.length > 0 ? args.args[0] : void 0;
|
|
13980
|
+
const event = {
|
|
13981
|
+
arguments: [input],
|
|
13982
|
+
span_info: {
|
|
13983
|
+
name: args.toolName
|
|
13984
|
+
},
|
|
13985
|
+
toolCallId: args.toolCallId,
|
|
13986
|
+
toolName: args.toolName
|
|
13987
|
+
};
|
|
13988
|
+
tracingChannel2.start.publish(event);
|
|
13989
|
+
try {
|
|
13990
|
+
const result = args.execute();
|
|
13991
|
+
return publishToolResult(tracingChannel2, event, result);
|
|
13992
|
+
} catch (error) {
|
|
13993
|
+
event.error = normalizeError(error);
|
|
13994
|
+
tracingChannel2.error.publish(event);
|
|
13995
|
+
throw error;
|
|
13148
13996
|
}
|
|
13149
|
-
return [args];
|
|
13150
|
-
}
|
|
13151
|
-
function isArrayLike(value) {
|
|
13152
|
-
return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
|
|
13153
13997
|
}
|
|
13154
|
-
function
|
|
13155
|
-
|
|
13156
|
-
|
|
13157
|
-
|
|
13158
|
-
|
|
13159
|
-
|
|
13160
|
-
|
|
13998
|
+
function publishToolResult(tracingChannel2, event, result) {
|
|
13999
|
+
if (isPromiseLike2(result)) {
|
|
14000
|
+
return result.then(
|
|
14001
|
+
(resolved) => {
|
|
14002
|
+
event.result = resolved;
|
|
14003
|
+
tracingChannel2.asyncEnd.publish(event);
|
|
14004
|
+
return resolved;
|
|
14005
|
+
},
|
|
14006
|
+
(error) => {
|
|
14007
|
+
event.error = normalizeError(error);
|
|
14008
|
+
tracingChannel2.error.publish(event);
|
|
14009
|
+
throw error;
|
|
14010
|
+
}
|
|
14011
|
+
);
|
|
13161
14012
|
}
|
|
13162
|
-
|
|
13163
|
-
|
|
14013
|
+
event.result = result;
|
|
14014
|
+
tracingChannel2.asyncEnd.publish(event);
|
|
14015
|
+
return result;
|
|
13164
14016
|
}
|
|
13165
|
-
function
|
|
13166
|
-
const
|
|
13167
|
-
return
|
|
14017
|
+
function getToolCallId(context) {
|
|
14018
|
+
const toolContext = context;
|
|
14019
|
+
return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
|
|
14020
|
+
}
|
|
14021
|
+
function isPromiseLike2(value) {
|
|
14022
|
+
return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
|
|
13168
14023
|
}
|
|
13169
14024
|
function aggregateOpenRouterChatChunks(chunks) {
|
|
13170
14025
|
let role;
|
|
@@ -13185,95 +14040,438 @@ function aggregateOpenRouterChatChunks(chunks) {
|
|
|
13185
14040
|
}
|
|
13186
14041
|
continue;
|
|
13187
14042
|
}
|
|
13188
|
-
if (!role && delta.role) {
|
|
13189
|
-
role = delta.role;
|
|
13190
|
-
}
|
|
13191
|
-
if (typeof delta.content === "string") {
|
|
13192
|
-
content += delta.content;
|
|
13193
|
-
}
|
|
13194
|
-
const choiceFinishReason = choice?.finishReason ?? choice?.finish_reason ?? void 0;
|
|
13195
|
-
const deltaFinishReason = delta.finishReason ?? delta.finish_reason ?? void 0;
|
|
13196
|
-
if (choiceFinishReason !== void 0) {
|
|
13197
|
-
finishReason = choiceFinishReason;
|
|
13198
|
-
} else if (deltaFinishReason !== void 0) {
|
|
13199
|
-
finishReason = deltaFinishReason;
|
|
13200
|
-
}
|
|
13201
|
-
const toolCallDeltas = Array.isArray(delta.toolCalls) ? delta.toolCalls : Array.isArray(delta.tool_calls) ? delta.tool_calls : void 0;
|
|
13202
|
-
if (!toolCallDeltas) {
|
|
14043
|
+
if (!role && delta.role) {
|
|
14044
|
+
role = delta.role;
|
|
14045
|
+
}
|
|
14046
|
+
if (typeof delta.content === "string") {
|
|
14047
|
+
content += delta.content;
|
|
14048
|
+
}
|
|
14049
|
+
const choiceFinishReason = choice?.finishReason ?? choice?.finish_reason ?? void 0;
|
|
14050
|
+
const deltaFinishReason = delta.finishReason ?? delta.finish_reason ?? void 0;
|
|
14051
|
+
if (choiceFinishReason !== void 0) {
|
|
14052
|
+
finishReason = choiceFinishReason;
|
|
14053
|
+
} else if (deltaFinishReason !== void 0) {
|
|
14054
|
+
finishReason = deltaFinishReason;
|
|
14055
|
+
}
|
|
14056
|
+
const toolCallDeltas = Array.isArray(delta.toolCalls) ? delta.toolCalls : Array.isArray(delta.tool_calls) ? delta.tool_calls : void 0;
|
|
14057
|
+
if (!toolCallDeltas) {
|
|
14058
|
+
continue;
|
|
14059
|
+
}
|
|
14060
|
+
for (const toolDelta of toolCallDeltas) {
|
|
14061
|
+
if (!toolDelta?.function) {
|
|
14062
|
+
continue;
|
|
14063
|
+
}
|
|
14064
|
+
const toolIndex = toolDelta.index ?? 0;
|
|
14065
|
+
const existingToolCall = toolCalls?.[toolIndex];
|
|
14066
|
+
if (!existingToolCall || toolDelta.id && existingToolCall.id !== void 0 && existingToolCall.id !== toolDelta.id) {
|
|
14067
|
+
const nextToolCalls = [...toolCalls || []];
|
|
14068
|
+
nextToolCalls[toolIndex] = {
|
|
14069
|
+
index: toolIndex,
|
|
14070
|
+
id: toolDelta.id,
|
|
14071
|
+
type: toolDelta.type,
|
|
14072
|
+
function: {
|
|
14073
|
+
name: toolDelta.function.name,
|
|
14074
|
+
arguments: toolDelta.function.arguments || ""
|
|
14075
|
+
}
|
|
14076
|
+
};
|
|
14077
|
+
toolCalls = nextToolCalls;
|
|
14078
|
+
continue;
|
|
14079
|
+
}
|
|
14080
|
+
const current = existingToolCall;
|
|
14081
|
+
if (toolDelta.id && !current.id) {
|
|
14082
|
+
current.id = toolDelta.id;
|
|
14083
|
+
}
|
|
14084
|
+
if (toolDelta.type && !current.type) {
|
|
14085
|
+
current.type = toolDelta.type;
|
|
14086
|
+
}
|
|
14087
|
+
if (toolDelta.function.name && !current.function.name) {
|
|
14088
|
+
current.function.name = toolDelta.function.name;
|
|
14089
|
+
}
|
|
14090
|
+
current.function.arguments += toolDelta.function.arguments || "";
|
|
14091
|
+
}
|
|
14092
|
+
}
|
|
14093
|
+
return {
|
|
14094
|
+
output: [
|
|
14095
|
+
{
|
|
14096
|
+
index: 0,
|
|
14097
|
+
message: {
|
|
14098
|
+
role,
|
|
14099
|
+
content: content || void 0,
|
|
14100
|
+
...toolCalls ? { tool_calls: toolCalls } : {}
|
|
14101
|
+
},
|
|
14102
|
+
logprobs: null,
|
|
14103
|
+
finish_reason: finishReason
|
|
14104
|
+
}
|
|
14105
|
+
],
|
|
14106
|
+
metrics
|
|
14107
|
+
};
|
|
14108
|
+
}
|
|
14109
|
+
function aggregateOpenRouterResponseStreamEvents(chunks) {
|
|
14110
|
+
let finalResponse;
|
|
14111
|
+
for (const chunk of chunks) {
|
|
14112
|
+
const response = chunk?.response;
|
|
14113
|
+
if (!response) {
|
|
14114
|
+
continue;
|
|
14115
|
+
}
|
|
14116
|
+
if (chunk.type === "response.completed" || chunk.type === "response.incomplete" || chunk.type === "response.failed") {
|
|
14117
|
+
finalResponse = response;
|
|
14118
|
+
}
|
|
14119
|
+
}
|
|
14120
|
+
if (!finalResponse) {
|
|
14121
|
+
return {
|
|
14122
|
+
output: void 0,
|
|
14123
|
+
metrics: {}
|
|
14124
|
+
};
|
|
14125
|
+
}
|
|
14126
|
+
return {
|
|
14127
|
+
output: extractOpenRouterResponseOutput(finalResponse),
|
|
14128
|
+
metrics: parseOpenRouterMetricsFromUsage(finalResponse.usage),
|
|
14129
|
+
...extractOpenRouterResponseMetadata(finalResponse) ? { metadata: extractOpenRouterResponseMetadata(finalResponse) } : {}
|
|
14130
|
+
};
|
|
14131
|
+
}
|
|
14132
|
+
var OPENROUTER_WRAPPED_CALL_MODEL_RESULT = Symbol(
|
|
14133
|
+
"braintrust.openrouter.wrappedCallModelResult"
|
|
14134
|
+
);
|
|
14135
|
+
var OPENROUTER_CALL_MODEL_STREAM_METHODS = [
|
|
14136
|
+
"getFullResponsesStream",
|
|
14137
|
+
"getItemsStream",
|
|
14138
|
+
"getNewMessagesStream",
|
|
14139
|
+
"getReasoningStream",
|
|
14140
|
+
"getTextStream",
|
|
14141
|
+
"getToolCallsStream",
|
|
14142
|
+
"getToolStream"
|
|
14143
|
+
];
|
|
14144
|
+
var OPENROUTER_CALL_MODEL_CONTEXT_METHODS = [
|
|
14145
|
+
"cancel",
|
|
14146
|
+
"getPendingToolCalls",
|
|
14147
|
+
"getState",
|
|
14148
|
+
"getToolCalls",
|
|
14149
|
+
"requiresApproval"
|
|
14150
|
+
];
|
|
14151
|
+
function patchOpenRouterCallModelResult(args) {
|
|
14152
|
+
const { request, result, span } = args;
|
|
14153
|
+
if (!isObject(result) || isWrappedCallModelResult(result)) {
|
|
14154
|
+
return false;
|
|
14155
|
+
}
|
|
14156
|
+
const resultLike = result;
|
|
14157
|
+
const hasInstrumentableMethod = typeof resultLike.getResponse === "function" || typeof resultLike.getText === "function" || OPENROUTER_CALL_MODEL_STREAM_METHODS.some(
|
|
14158
|
+
(methodName) => typeof resultLike[methodName] === "function"
|
|
14159
|
+
);
|
|
14160
|
+
if (!hasInstrumentableMethod) {
|
|
14161
|
+
return false;
|
|
14162
|
+
}
|
|
14163
|
+
Object.defineProperty(resultLike, OPENROUTER_WRAPPED_CALL_MODEL_RESULT, {
|
|
14164
|
+
value: true,
|
|
14165
|
+
enumerable: false,
|
|
14166
|
+
configurable: false
|
|
14167
|
+
});
|
|
14168
|
+
const originalGetResponse = typeof resultLike.getResponse === "function" ? resultLike.getResponse.bind(resultLike) : void 0;
|
|
14169
|
+
const originalGetInitialResponse = typeof resultLike.getInitialResponse === "function" ? resultLike.getInitialResponse.bind(resultLike) : void 0;
|
|
14170
|
+
const originalMakeFollowupRequest = typeof resultLike.makeFollowupRequest === "function" ? resultLike.makeFollowupRequest.bind(resultLike) : void 0;
|
|
14171
|
+
let ended = false;
|
|
14172
|
+
let tracedTurnCount = 0;
|
|
14173
|
+
const endSpanWithResult = async (response, fallbackOutput) => {
|
|
14174
|
+
if (ended) {
|
|
14175
|
+
return;
|
|
14176
|
+
}
|
|
14177
|
+
ended = true;
|
|
14178
|
+
const finalResponse = getFinalOpenRouterCallModelResponse(
|
|
14179
|
+
resultLike,
|
|
14180
|
+
response
|
|
14181
|
+
);
|
|
14182
|
+
if (finalResponse) {
|
|
14183
|
+
const rounds = getOpenRouterCallModelRounds(resultLike);
|
|
14184
|
+
const metadata = extractOpenRouterCallModelResultMetadata(
|
|
14185
|
+
finalResponse,
|
|
14186
|
+
rounds.length + 1
|
|
14187
|
+
);
|
|
14188
|
+
span.log({
|
|
14189
|
+
output: extractOpenRouterResponseOutput(finalResponse, fallbackOutput),
|
|
14190
|
+
...metadata ? { metadata } : {},
|
|
14191
|
+
metrics: aggregateOpenRouterCallModelMetrics(rounds, finalResponse)
|
|
14192
|
+
});
|
|
14193
|
+
span.end();
|
|
14194
|
+
return;
|
|
14195
|
+
}
|
|
14196
|
+
if (fallbackOutput !== void 0) {
|
|
14197
|
+
span.log({
|
|
14198
|
+
output: fallbackOutput
|
|
14199
|
+
});
|
|
14200
|
+
}
|
|
14201
|
+
span.end();
|
|
14202
|
+
};
|
|
14203
|
+
const endSpanWithError = (error) => {
|
|
14204
|
+
if (ended) {
|
|
14205
|
+
return;
|
|
14206
|
+
}
|
|
14207
|
+
ended = true;
|
|
14208
|
+
span.log({
|
|
14209
|
+
error: normalizeError(error).message
|
|
14210
|
+
});
|
|
14211
|
+
span.end();
|
|
14212
|
+
};
|
|
14213
|
+
const finalizeFromResponse = async (fallbackOutput) => {
|
|
14214
|
+
if (!originalGetResponse) {
|
|
14215
|
+
await endSpanWithResult(void 0, fallbackOutput);
|
|
14216
|
+
return;
|
|
14217
|
+
}
|
|
14218
|
+
try {
|
|
14219
|
+
await endSpanWithResult(await originalGetResponse(), fallbackOutput);
|
|
14220
|
+
} catch {
|
|
14221
|
+
await endSpanWithResult(void 0, fallbackOutput);
|
|
14222
|
+
}
|
|
14223
|
+
};
|
|
14224
|
+
if (originalGetResponse) {
|
|
14225
|
+
resultLike.getResponse = async (...args2) => {
|
|
14226
|
+
return await withCurrent(span, async () => {
|
|
14227
|
+
try {
|
|
14228
|
+
const response = await originalGetResponse(...args2);
|
|
14229
|
+
await endSpanWithResult(response);
|
|
14230
|
+
return response;
|
|
14231
|
+
} catch (error) {
|
|
14232
|
+
endSpanWithError(error);
|
|
14233
|
+
throw error;
|
|
14234
|
+
}
|
|
14235
|
+
});
|
|
14236
|
+
};
|
|
14237
|
+
}
|
|
14238
|
+
if (typeof resultLike.getText === "function") {
|
|
14239
|
+
const originalGetText = resultLike.getText.bind(resultLike);
|
|
14240
|
+
resultLike.getText = async (...args2) => {
|
|
14241
|
+
return await withCurrent(span, async () => {
|
|
14242
|
+
try {
|
|
14243
|
+
const text = await originalGetText(...args2);
|
|
14244
|
+
await finalizeFromResponse(text);
|
|
14245
|
+
return text;
|
|
14246
|
+
} catch (error) {
|
|
14247
|
+
endSpanWithError(error);
|
|
14248
|
+
throw error;
|
|
14249
|
+
}
|
|
14250
|
+
});
|
|
14251
|
+
};
|
|
14252
|
+
}
|
|
14253
|
+
for (const methodName of OPENROUTER_CALL_MODEL_CONTEXT_METHODS) {
|
|
14254
|
+
if (typeof resultLike[methodName] !== "function") {
|
|
14255
|
+
continue;
|
|
14256
|
+
}
|
|
14257
|
+
const originalMethod = resultLike[methodName];
|
|
14258
|
+
resultLike[methodName] = async (...args2) => {
|
|
14259
|
+
return await withCurrent(span, async () => {
|
|
14260
|
+
return await originalMethod.apply(resultLike, args2);
|
|
14261
|
+
});
|
|
14262
|
+
};
|
|
14263
|
+
}
|
|
14264
|
+
for (const methodName of OPENROUTER_CALL_MODEL_STREAM_METHODS) {
|
|
14265
|
+
if (typeof resultLike[methodName] !== "function") {
|
|
13203
14266
|
continue;
|
|
13204
14267
|
}
|
|
13205
|
-
|
|
13206
|
-
|
|
13207
|
-
|
|
13208
|
-
|
|
13209
|
-
|
|
13210
|
-
|
|
13211
|
-
if (!
|
|
13212
|
-
|
|
13213
|
-
nextToolCalls[toolIndex] = {
|
|
13214
|
-
index: toolIndex,
|
|
13215
|
-
id: toolDelta.id,
|
|
13216
|
-
type: toolDelta.type,
|
|
13217
|
-
function: {
|
|
13218
|
-
name: toolDelta.function.name,
|
|
13219
|
-
arguments: toolDelta.function.arguments || ""
|
|
13220
|
-
}
|
|
13221
|
-
};
|
|
13222
|
-
toolCalls = nextToolCalls;
|
|
13223
|
-
continue;
|
|
13224
|
-
}
|
|
13225
|
-
const current = existingToolCall;
|
|
13226
|
-
if (toolDelta.id && !current.id) {
|
|
13227
|
-
current.id = toolDelta.id;
|
|
13228
|
-
}
|
|
13229
|
-
if (toolDelta.type && !current.type) {
|
|
13230
|
-
current.type = toolDelta.type;
|
|
14268
|
+
const originalMethod = resultLike[methodName];
|
|
14269
|
+
resultLike[methodName] = (...args2) => {
|
|
14270
|
+
const stream = withCurrent(
|
|
14271
|
+
span,
|
|
14272
|
+
() => originalMethod.apply(resultLike, args2)
|
|
14273
|
+
);
|
|
14274
|
+
if (!isAsyncIterable2(stream)) {
|
|
14275
|
+
return stream;
|
|
13231
14276
|
}
|
|
13232
|
-
|
|
13233
|
-
|
|
14277
|
+
return wrapAsyncIterableWithSpan({
|
|
14278
|
+
finalize: finalizeFromResponse,
|
|
14279
|
+
iteratorFactory: () => stream[Symbol.asyncIterator](),
|
|
14280
|
+
onError: endSpanWithError,
|
|
14281
|
+
span
|
|
14282
|
+
});
|
|
14283
|
+
};
|
|
14284
|
+
}
|
|
14285
|
+
if (originalGetInitialResponse) {
|
|
14286
|
+
let initialTurnTraced = false;
|
|
14287
|
+
resultLike.getInitialResponse = async (...args2) => {
|
|
14288
|
+
if (initialTurnTraced) {
|
|
14289
|
+
return await withCurrent(span, async () => {
|
|
14290
|
+
return await originalGetInitialResponse(...args2);
|
|
14291
|
+
});
|
|
13234
14292
|
}
|
|
13235
|
-
|
|
13236
|
-
|
|
14293
|
+
initialTurnTraced = true;
|
|
14294
|
+
const step = tracedTurnCount + 1;
|
|
14295
|
+
const stepType = tracedTurnCount === 0 ? "initial" : "continue";
|
|
14296
|
+
const response = await traceOpenRouterCallModelTurn({
|
|
14297
|
+
fn: async () => {
|
|
14298
|
+
const nextResponse = await originalGetInitialResponse(...args2);
|
|
14299
|
+
tracedTurnCount++;
|
|
14300
|
+
return nextResponse;
|
|
14301
|
+
},
|
|
14302
|
+
parentSpan: span,
|
|
14303
|
+
request: getOpenRouterResolvedRequest(resultLike, request),
|
|
14304
|
+
step,
|
|
14305
|
+
stepType
|
|
14306
|
+
});
|
|
14307
|
+
return response;
|
|
14308
|
+
};
|
|
13237
14309
|
}
|
|
13238
|
-
|
|
13239
|
-
|
|
13240
|
-
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
|
|
14310
|
+
if (originalMakeFollowupRequest) {
|
|
14311
|
+
resultLike.makeFollowupRequest = async (...args2) => {
|
|
14312
|
+
const currentResponse = args2[0];
|
|
14313
|
+
const toolResults = Array.isArray(args2[1]) ? args2[1] : [];
|
|
14314
|
+
const step = tracedTurnCount + 1;
|
|
14315
|
+
const response = await traceOpenRouterCallModelTurn({
|
|
14316
|
+
fn: async () => {
|
|
14317
|
+
const nextResponse = await originalMakeFollowupRequest(...args2);
|
|
14318
|
+
tracedTurnCount++;
|
|
14319
|
+
return nextResponse;
|
|
13246
14320
|
},
|
|
13247
|
-
|
|
13248
|
-
|
|
13249
|
-
|
|
13250
|
-
|
|
13251
|
-
|
|
14321
|
+
parentSpan: span,
|
|
14322
|
+
request: buildOpenRouterFollowupRequest(
|
|
14323
|
+
getOpenRouterResolvedRequest(resultLike, request),
|
|
14324
|
+
currentResponse,
|
|
14325
|
+
toolResults
|
|
14326
|
+
),
|
|
14327
|
+
step,
|
|
14328
|
+
stepType: "continue"
|
|
14329
|
+
});
|
|
14330
|
+
return response;
|
|
14331
|
+
};
|
|
14332
|
+
}
|
|
14333
|
+
return true;
|
|
14334
|
+
}
|
|
14335
|
+
async function traceOpenRouterCallModelTurn(args) {
|
|
14336
|
+
const context = {
|
|
14337
|
+
arguments: [args.request],
|
|
14338
|
+
step: args.step,
|
|
14339
|
+
stepType: args.stepType
|
|
13252
14340
|
};
|
|
14341
|
+
return await withCurrent(
|
|
14342
|
+
args.parentSpan,
|
|
14343
|
+
() => openRouterChannels.callModelTurn.tracePromise(args.fn, context)
|
|
14344
|
+
);
|
|
13253
14345
|
}
|
|
13254
|
-
function
|
|
13255
|
-
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
|
|
13259
|
-
|
|
13260
|
-
|
|
13261
|
-
|
|
13262
|
-
|
|
14346
|
+
function isWrappedCallModelResult(value) {
|
|
14347
|
+
return Boolean(
|
|
14348
|
+
isObject(value) && value[OPENROUTER_WRAPPED_CALL_MODEL_RESULT]
|
|
14349
|
+
);
|
|
14350
|
+
}
|
|
14351
|
+
function extractOpenRouterCallModelResultMetadata(response, turnCount) {
|
|
14352
|
+
const combined = {
|
|
14353
|
+
...extractOpenRouterResponseMetadata(response) || {},
|
|
14354
|
+
...turnCount !== void 0 ? { turn_count: turnCount } : {}
|
|
14355
|
+
};
|
|
14356
|
+
return Object.keys(combined).length > 0 ? combined : void 0;
|
|
14357
|
+
}
|
|
14358
|
+
function getFinalOpenRouterCallModelResponse(result, response) {
|
|
14359
|
+
if (isObject(response)) {
|
|
14360
|
+
return response;
|
|
14361
|
+
}
|
|
14362
|
+
return isObject(result.finalResponse) ? result.finalResponse : void 0;
|
|
14363
|
+
}
|
|
14364
|
+
function getOpenRouterCallModelRounds(result) {
|
|
14365
|
+
if (!Array.isArray(result.allToolExecutionRounds)) {
|
|
14366
|
+
return [];
|
|
14367
|
+
}
|
|
14368
|
+
return result.allToolExecutionRounds.filter((round) => isObject(round)).map((round) => ({
|
|
14369
|
+
response: isObject(round.response) ? round.response : void 0,
|
|
14370
|
+
round: typeof round.round === "number" ? round.round : void 0,
|
|
14371
|
+
toolResults: Array.isArray(round.toolResults) ? round.toolResults : []
|
|
14372
|
+
})).filter((round) => round.response !== void 0);
|
|
14373
|
+
}
|
|
14374
|
+
function aggregateOpenRouterCallModelMetrics(rounds, finalResponse) {
|
|
14375
|
+
const metrics = {};
|
|
14376
|
+
const responses = [
|
|
14377
|
+
...rounds.map((round) => round.response).filter(isObject),
|
|
14378
|
+
finalResponse
|
|
14379
|
+
];
|
|
14380
|
+
for (const response of responses) {
|
|
14381
|
+
const responseMetrics = parseOpenRouterMetricsFromUsage(response.usage);
|
|
14382
|
+
for (const [name, value] of Object.entries(responseMetrics)) {
|
|
14383
|
+
metrics[name] = (metrics[name] || 0) + value;
|
|
13263
14384
|
}
|
|
13264
14385
|
}
|
|
13265
|
-
|
|
13266
|
-
|
|
13267
|
-
|
|
13268
|
-
|
|
13269
|
-
|
|
14386
|
+
return metrics;
|
|
14387
|
+
}
|
|
14388
|
+
function buildNextOpenRouterCallModelInput(currentInput, response, toolResults) {
|
|
14389
|
+
const normalizedInput = Array.isArray(currentInput) ? [...currentInput] : currentInput === void 0 ? [] : [currentInput];
|
|
14390
|
+
const responseOutput = Array.isArray(response.output) ? response.output : response.output === void 0 ? [] : [response.output];
|
|
14391
|
+
return [...normalizedInput, ...responseOutput, ...toolResults].map(
|
|
14392
|
+
(entry) => sanitizeOpenRouterLoggedValue(entry)
|
|
14393
|
+
);
|
|
14394
|
+
}
|
|
14395
|
+
function getOpenRouterResolvedRequest(result, request) {
|
|
14396
|
+
if (isObject(result.resolvedRequest)) {
|
|
14397
|
+
return result.resolvedRequest;
|
|
14398
|
+
}
|
|
14399
|
+
return request;
|
|
14400
|
+
}
|
|
14401
|
+
function buildOpenRouterFollowupRequest(request, currentResponse, toolResults) {
|
|
14402
|
+
if (!request) {
|
|
14403
|
+
return void 0;
|
|
13270
14404
|
}
|
|
13271
14405
|
return {
|
|
13272
|
-
|
|
13273
|
-
|
|
13274
|
-
|
|
14406
|
+
...request,
|
|
14407
|
+
input: buildNextOpenRouterCallModelInput(
|
|
14408
|
+
extractOpenRouterCallModelInput(request),
|
|
14409
|
+
isObject(currentResponse) ? currentResponse : {},
|
|
14410
|
+
toolResults
|
|
14411
|
+
),
|
|
14412
|
+
stream: false
|
|
14413
|
+
};
|
|
14414
|
+
}
|
|
14415
|
+
function wrapAsyncIterableWithSpan(args) {
|
|
14416
|
+
return {
|
|
14417
|
+
[Symbol.asyncIterator]() {
|
|
14418
|
+
const iterator = args.iteratorFactory();
|
|
14419
|
+
return {
|
|
14420
|
+
next(value) {
|
|
14421
|
+
return withCurrent(
|
|
14422
|
+
args.span,
|
|
14423
|
+
() => value === void 0 ? iterator.next() : iterator.next(value)
|
|
14424
|
+
).then(
|
|
14425
|
+
async (result) => {
|
|
14426
|
+
if (result.done) {
|
|
14427
|
+
await args.finalize();
|
|
14428
|
+
}
|
|
14429
|
+
return result;
|
|
14430
|
+
},
|
|
14431
|
+
(error) => {
|
|
14432
|
+
args.onError(error);
|
|
14433
|
+
throw error;
|
|
14434
|
+
}
|
|
14435
|
+
);
|
|
14436
|
+
},
|
|
14437
|
+
return(value) {
|
|
14438
|
+
if (typeof iterator.return !== "function") {
|
|
14439
|
+
return args.finalize().then(() => ({
|
|
14440
|
+
done: true,
|
|
14441
|
+
value
|
|
14442
|
+
}));
|
|
14443
|
+
}
|
|
14444
|
+
return withCurrent(args.span, () => iterator.return(value)).then(
|
|
14445
|
+
async (result) => {
|
|
14446
|
+
await args.finalize();
|
|
14447
|
+
return result;
|
|
14448
|
+
},
|
|
14449
|
+
(error) => {
|
|
14450
|
+
args.onError(error);
|
|
14451
|
+
throw error;
|
|
14452
|
+
}
|
|
14453
|
+
);
|
|
14454
|
+
},
|
|
14455
|
+
throw(error) {
|
|
14456
|
+
args.onError(error);
|
|
14457
|
+
if (typeof iterator.throw !== "function") {
|
|
14458
|
+
return Promise.reject(error);
|
|
14459
|
+
}
|
|
14460
|
+
return withCurrent(args.span, () => iterator.throw(error));
|
|
14461
|
+
},
|
|
14462
|
+
[Symbol.asyncIterator]() {
|
|
14463
|
+
return this;
|
|
14464
|
+
}
|
|
14465
|
+
};
|
|
14466
|
+
}
|
|
13275
14467
|
};
|
|
13276
14468
|
}
|
|
14469
|
+
function isAsyncIterable2(value) {
|
|
14470
|
+
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
14471
|
+
}
|
|
14472
|
+
function normalizeError(error) {
|
|
14473
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
14474
|
+
}
|
|
13277
14475
|
|
|
13278
14476
|
// src/instrumentation/braintrust-plugin.ts
|
|
13279
14477
|
var BraintrustPlugin = class extends BasePlugin {
|
|
@@ -14996,7 +16194,28 @@ function validateParametersWithJsonSchema(parameters, schema) {
|
|
|
14996
16194
|
}).join(", ");
|
|
14997
16195
|
throw Error(`Invalid parameters: ${errorMessages}`);
|
|
14998
16196
|
}
|
|
14999
|
-
return parameters;
|
|
16197
|
+
return rehydrateRemoteParameters(parameters, schema);
|
|
16198
|
+
}
|
|
16199
|
+
function rehydrateRemoteParameters(parameters, schema) {
|
|
16200
|
+
const schemaProperties = schema.properties;
|
|
16201
|
+
if (typeof schemaProperties !== "object" || schemaProperties === null) {
|
|
16202
|
+
return parameters;
|
|
16203
|
+
}
|
|
16204
|
+
return Object.fromEntries(
|
|
16205
|
+
Object.entries(parameters).map(([name, value]) => {
|
|
16206
|
+
const propertySchema = Reflect.get(schemaProperties, name);
|
|
16207
|
+
if (typeof propertySchema !== "object" || propertySchema === null) {
|
|
16208
|
+
return [name, value];
|
|
16209
|
+
}
|
|
16210
|
+
if (Reflect.get(propertySchema, "x-bt-type") === "prompt") {
|
|
16211
|
+
return [
|
|
16212
|
+
name,
|
|
16213
|
+
Prompt2.fromPromptData(name, PromptData.parse(value))
|
|
16214
|
+
];
|
|
16215
|
+
}
|
|
16216
|
+
return [name, value];
|
|
16217
|
+
})
|
|
16218
|
+
);
|
|
15000
16219
|
}
|
|
15001
16220
|
|
|
15002
16221
|
// src/framework.ts
|
|
@@ -16231,7 +17450,8 @@ var ScorerBuilder = class {
|
|
|
16231
17450
|
type: "llm_classifier",
|
|
16232
17451
|
use_cot: opts.useCot,
|
|
16233
17452
|
choice_scores: opts.choiceScores
|
|
16234
|
-
}
|
|
17453
|
+
},
|
|
17454
|
+
...opts.templateFormat ? { template_format: opts.templateFormat } : {}
|
|
16235
17455
|
};
|
|
16236
17456
|
const codePrompt = new CodePrompt(
|
|
16237
17457
|
this.project,
|