braintrust 3.7.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 +1859 -1338
- package/dev/dist/index.mjs +1774 -1253
- package/dist/auto-instrumentations/bundler/esbuild.cjs +12 -15
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/rollup.cjs +12 -15
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +12 -15
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +12 -15
- package/dist/auto-instrumentations/bundler/webpack.cjs +12 -15
- package/dist/auto-instrumentations/bundler/webpack.mjs +2 -2
- package/dist/auto-instrumentations/{chunk-ZK2IYER2.mjs → chunk-NY4CGTN6.mjs} +1 -1
- package/dist/auto-instrumentations/{chunk-AKEXR4AL.mjs → chunk-YCKND42U.mjs} +12 -15
- package/dist/auto-instrumentations/hook.mjs +12 -15
- package/dist/auto-instrumentations/index.cjs +12 -15
- 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 +4836 -6828
- package/dist/browser.mjs +4836 -6828
- package/dist/cli.js +1507 -986
- package/dist/edge-light.js +9173 -11163
- package/dist/edge-light.mjs +9173 -11163
- package/dist/index.d.mts +8 -30
- package/dist/index.d.ts +8 -30
- package/dist/index.js +4747 -6739
- package/dist/index.mjs +4748 -6740
- package/dist/instrumentation/index.js +1735 -1236
- package/dist/instrumentation/index.mjs +1735 -1236
- package/dist/workerd.js +9173 -11163
- package/dist/workerd.mjs +9173 -11163
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1232,7 +1232,7 @@ var require_package = __commonJS({
|
|
|
1232
1232
|
"package.json"(exports2, module2) {
|
|
1233
1233
|
module2.exports = {
|
|
1234
1234
|
name: "braintrust",
|
|
1235
|
-
version: "3.7.
|
|
1235
|
+
version: "3.7.1",
|
|
1236
1236
|
description: "SDK for integrating Braintrust",
|
|
1237
1237
|
repository: {
|
|
1238
1238
|
type: "git",
|
|
@@ -1425,7 +1425,7 @@ var require_package = __commonJS({
|
|
|
1425
1425
|
typescript: "5.4.4",
|
|
1426
1426
|
vite: "^6.4.1",
|
|
1427
1427
|
"vite-tsconfig-paths": "^4.3.2",
|
|
1428
|
-
vitest: "^4.1.
|
|
1428
|
+
vitest: "^4.1.2",
|
|
1429
1429
|
webpack: "^5.97.1",
|
|
1430
1430
|
zod: "^3.25.34"
|
|
1431
1431
|
},
|
|
@@ -1561,7 +1561,7 @@ var DefaultTracingChannel = class {
|
|
|
1561
1561
|
}
|
|
1562
1562
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1563
1563
|
tracePromise(fn, _message, thisArg, ...args) {
|
|
1564
|
-
return
|
|
1564
|
+
return fn.apply(thisArg, args);
|
|
1565
1565
|
}
|
|
1566
1566
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1567
1567
|
traceCallback(fn, _position, _message, thisArg, ...args) {
|
|
@@ -1581,6 +1581,7 @@ var iso = {
|
|
|
1581
1581
|
processOn: (_0, _1) => {
|
|
1582
1582
|
},
|
|
1583
1583
|
basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
|
|
1584
|
+
// eslint-disable-next-line no-restricted-properties -- preserving intentional console usage.
|
|
1584
1585
|
writeln: (text) => console.log(text)
|
|
1585
1586
|
};
|
|
1586
1587
|
var isomorph_default = iso;
|
|
@@ -3072,6 +3073,15 @@ var InternalAbortError = class extends Error {
|
|
|
3072
3073
|
this.name = "InternalAbortError";
|
|
3073
3074
|
}
|
|
3074
3075
|
};
|
|
3076
|
+
function filterFrom(record, keys) {
|
|
3077
|
+
const out = {};
|
|
3078
|
+
for (const k of Object.keys(record)) {
|
|
3079
|
+
if (!keys.includes(k)) {
|
|
3080
|
+
out[k] = record[k];
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
return out;
|
|
3084
|
+
}
|
|
3075
3085
|
|
|
3076
3086
|
// src/generated_types.ts
|
|
3077
3087
|
var import_v36 = require("zod/v3");
|
|
@@ -11599,7 +11609,28 @@ function validateParametersWithJsonSchema(parameters, schema) {
|
|
|
11599
11609
|
}).join(", ");
|
|
11600
11610
|
throw Error(`Invalid parameters: ${errorMessages}`);
|
|
11601
11611
|
}
|
|
11602
|
-
return parameters;
|
|
11612
|
+
return rehydrateRemoteParameters(parameters, schema);
|
|
11613
|
+
}
|
|
11614
|
+
function rehydrateRemoteParameters(parameters, schema) {
|
|
11615
|
+
const schemaProperties = schema.properties;
|
|
11616
|
+
if (typeof schemaProperties !== "object" || schemaProperties === null) {
|
|
11617
|
+
return parameters;
|
|
11618
|
+
}
|
|
11619
|
+
return Object.fromEntries(
|
|
11620
|
+
Object.entries(parameters).map(([name, value]) => {
|
|
11621
|
+
const propertySchema = Reflect.get(schemaProperties, name);
|
|
11622
|
+
if (typeof propertySchema !== "object" || propertySchema === null) {
|
|
11623
|
+
return [name, value];
|
|
11624
|
+
}
|
|
11625
|
+
if (Reflect.get(propertySchema, "x-bt-type") === "prompt") {
|
|
11626
|
+
return [
|
|
11627
|
+
name,
|
|
11628
|
+
Prompt2.fromPromptData(name, PromptData.parse(value))
|
|
11629
|
+
];
|
|
11630
|
+
}
|
|
11631
|
+
return [name, value];
|
|
11632
|
+
})
|
|
11633
|
+
);
|
|
11603
11634
|
}
|
|
11604
11635
|
|
|
11605
11636
|
// src/framework.ts
|
|
@@ -12947,7 +12978,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
12947
12978
|
if (!completed) {
|
|
12948
12979
|
completed = true;
|
|
12949
12980
|
try {
|
|
12950
|
-
options.onComplete(chunks);
|
|
12981
|
+
await options.onComplete(chunks);
|
|
12951
12982
|
} catch (error2) {
|
|
12952
12983
|
console.error("Error in stream onComplete handler:", error2);
|
|
12953
12984
|
}
|
|
@@ -12959,7 +12990,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
12959
12990
|
chunks.push(chunk);
|
|
12960
12991
|
if (options.onChunk) {
|
|
12961
12992
|
try {
|
|
12962
|
-
options.onChunk(chunk);
|
|
12993
|
+
await options.onChunk(chunk);
|
|
12963
12994
|
} catch (error2) {
|
|
12964
12995
|
console.error("Error in stream onChunk handler:", error2);
|
|
12965
12996
|
}
|
|
@@ -12972,7 +13003,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
12972
13003
|
completed = true;
|
|
12973
13004
|
if (options.onError) {
|
|
12974
13005
|
try {
|
|
12975
|
-
options.onError(
|
|
13006
|
+
await options.onError(
|
|
12976
13007
|
error2 instanceof Error ? error2 : new Error(String(error2)),
|
|
12977
13008
|
chunks
|
|
12978
13009
|
);
|
|
@@ -12990,7 +13021,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
12990
13021
|
if (!completed) {
|
|
12991
13022
|
completed = true;
|
|
12992
13023
|
try {
|
|
12993
|
-
options.onComplete(chunks);
|
|
13024
|
+
await options.onComplete(chunks);
|
|
12994
13025
|
} catch (error2) {
|
|
12995
13026
|
console.error("Error in stream onComplete handler:", error2);
|
|
12996
13027
|
}
|
|
@@ -13007,7 +13038,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
13007
13038
|
const error2 = rawError instanceof Error ? rawError : new Error(String(rawError));
|
|
13008
13039
|
if (options.onError) {
|
|
13009
13040
|
try {
|
|
13010
|
-
options.onError(error2, chunks);
|
|
13041
|
+
await options.onError(error2, chunks);
|
|
13011
13042
|
} catch (handlerError) {
|
|
13012
13043
|
console.error("Error in stream onError handler:", handlerError);
|
|
13013
13044
|
}
|
|
@@ -13716,51 +13747,28 @@ function traceSyncStreamChannel(channel2, config3) {
|
|
|
13716
13747
|
}
|
|
13717
13748
|
const { span, startTime } = spanData;
|
|
13718
13749
|
const endEvent = event;
|
|
13719
|
-
|
|
13720
|
-
|
|
13721
|
-
|
|
13722
|
-
|
|
13723
|
-
|
|
13724
|
-
|
|
13725
|
-
|
|
13726
|
-
|
|
13727
|
-
|
|
13728
|
-
|
|
13729
|
-
|
|
13730
|
-
|
|
13731
|
-
|
|
13732
|
-
return;
|
|
13733
|
-
}
|
|
13734
|
-
let first = true;
|
|
13735
|
-
stream.on("chunk", () => {
|
|
13736
|
-
if (first) {
|
|
13737
|
-
span.log({
|
|
13738
|
-
metrics: {
|
|
13739
|
-
time_to_first_token: getCurrentUnixTimestamp() - startTime
|
|
13740
|
-
}
|
|
13741
|
-
});
|
|
13742
|
-
first = false;
|
|
13743
|
-
}
|
|
13744
|
-
});
|
|
13745
|
-
stream.on("chatCompletion", (completion) => {
|
|
13746
|
-
try {
|
|
13747
|
-
if (hasChoices(completion)) {
|
|
13748
|
-
span.log({
|
|
13749
|
-
output: completion.choices
|
|
13750
|
-
});
|
|
13751
|
-
}
|
|
13752
|
-
} catch (error2) {
|
|
13753
|
-
console.error(
|
|
13754
|
-
`Error extracting chatCompletion for ${channelName}:`,
|
|
13755
|
-
error2
|
|
13756
|
-
);
|
|
13750
|
+
const handleResolvedResult = (result) => {
|
|
13751
|
+
const resolvedEndEvent = {
|
|
13752
|
+
...endEvent,
|
|
13753
|
+
result
|
|
13754
|
+
};
|
|
13755
|
+
if (config3.patchResult?.({
|
|
13756
|
+
channelName,
|
|
13757
|
+
endEvent: resolvedEndEvent,
|
|
13758
|
+
result,
|
|
13759
|
+
span,
|
|
13760
|
+
startTime
|
|
13761
|
+
})) {
|
|
13762
|
+
return;
|
|
13757
13763
|
}
|
|
13758
|
-
|
|
13759
|
-
|
|
13760
|
-
|
|
13764
|
+
const stream = result;
|
|
13765
|
+
if (!isSyncStreamLike(stream)) {
|
|
13766
|
+
span.end();
|
|
13767
|
+
states.delete(event);
|
|
13761
13768
|
return;
|
|
13762
13769
|
}
|
|
13763
|
-
|
|
13770
|
+
let first = true;
|
|
13771
|
+
stream.on("chunk", () => {
|
|
13764
13772
|
if (first) {
|
|
13765
13773
|
span.log({
|
|
13766
13774
|
metrics: {
|
|
@@ -13769,25 +13777,55 @@ function traceSyncStreamChannel(channel2, config3) {
|
|
|
13769
13777
|
});
|
|
13770
13778
|
first = false;
|
|
13771
13779
|
}
|
|
13772
|
-
|
|
13773
|
-
|
|
13774
|
-
|
|
13780
|
+
});
|
|
13781
|
+
stream.on("chatCompletion", (completion) => {
|
|
13782
|
+
try {
|
|
13783
|
+
if (hasChoices(completion)) {
|
|
13784
|
+
span.log({
|
|
13785
|
+
output: completion.choices
|
|
13786
|
+
});
|
|
13787
|
+
}
|
|
13788
|
+
} catch (error2) {
|
|
13789
|
+
console.error(
|
|
13790
|
+
`Error extracting chatCompletion for ${channelName}:`,
|
|
13791
|
+
error2
|
|
13792
|
+
);
|
|
13775
13793
|
}
|
|
13776
|
-
} catch (error2) {
|
|
13777
|
-
console.error(`Error extracting event for ${channelName}:`, error2);
|
|
13778
|
-
}
|
|
13779
|
-
});
|
|
13780
|
-
stream.on("end", () => {
|
|
13781
|
-
span.end();
|
|
13782
|
-
states.delete(event);
|
|
13783
|
-
});
|
|
13784
|
-
stream.on("error", (error2) => {
|
|
13785
|
-
span.log({
|
|
13786
|
-
error: error2.message
|
|
13787
13794
|
});
|
|
13788
|
-
|
|
13789
|
-
|
|
13790
|
-
|
|
13795
|
+
stream.on("event", (streamEvent) => {
|
|
13796
|
+
if (!config3.extractFromEvent) {
|
|
13797
|
+
return;
|
|
13798
|
+
}
|
|
13799
|
+
try {
|
|
13800
|
+
if (first) {
|
|
13801
|
+
span.log({
|
|
13802
|
+
metrics: {
|
|
13803
|
+
time_to_first_token: getCurrentUnixTimestamp() - startTime
|
|
13804
|
+
}
|
|
13805
|
+
});
|
|
13806
|
+
first = false;
|
|
13807
|
+
}
|
|
13808
|
+
const extracted = config3.extractFromEvent(streamEvent);
|
|
13809
|
+
if (extracted && Object.keys(extracted).length > 0) {
|
|
13810
|
+
span.log(extracted);
|
|
13811
|
+
}
|
|
13812
|
+
} catch (error2) {
|
|
13813
|
+
console.error(`Error extracting event for ${channelName}:`, error2);
|
|
13814
|
+
}
|
|
13815
|
+
});
|
|
13816
|
+
stream.on("end", () => {
|
|
13817
|
+
span.end();
|
|
13818
|
+
states.delete(event);
|
|
13819
|
+
});
|
|
13820
|
+
stream.on("error", (error2) => {
|
|
13821
|
+
span.log({
|
|
13822
|
+
error: error2.message
|
|
13823
|
+
});
|
|
13824
|
+
span.end();
|
|
13825
|
+
states.delete(event);
|
|
13826
|
+
});
|
|
13827
|
+
};
|
|
13828
|
+
handleResolvedResult(endEvent.result);
|
|
13791
13829
|
},
|
|
13792
13830
|
error: (event) => {
|
|
13793
13831
|
logErrorAndEnd(states, event);
|
|
@@ -14610,28 +14648,40 @@ function aggregateAnthropicStreamChunks(chunks) {
|
|
|
14610
14648
|
case "content_block_start":
|
|
14611
14649
|
if (event.content_block) {
|
|
14612
14650
|
contentBlocks[event.index] = event.content_block;
|
|
14613
|
-
contentBlockDeltas[event.index] = [];
|
|
14651
|
+
contentBlockDeltas[event.index] = { textDeltas: [], citations: [] };
|
|
14614
14652
|
}
|
|
14615
14653
|
break;
|
|
14616
|
-
case "content_block_delta":
|
|
14617
|
-
|
|
14618
|
-
|
|
14654
|
+
case "content_block_delta": {
|
|
14655
|
+
const acc = contentBlockDeltas[event.index];
|
|
14656
|
+
const delta = event.delta;
|
|
14657
|
+
if (!delta) break;
|
|
14658
|
+
if (delta.type === "text_delta" && "text" in delta) {
|
|
14659
|
+
const text = delta.text;
|
|
14619
14660
|
if (text) {
|
|
14620
|
-
if (
|
|
14621
|
-
|
|
14622
|
-
contentBlockDeltas[event.index].push(text);
|
|
14661
|
+
if (acc !== void 0) {
|
|
14662
|
+
acc.textDeltas.push(text);
|
|
14623
14663
|
} else {
|
|
14624
14664
|
fallbackTextDeltas.push(text);
|
|
14625
14665
|
}
|
|
14626
14666
|
}
|
|
14627
|
-
} else if (
|
|
14628
|
-
const partialJson =
|
|
14629
|
-
if (partialJson) {
|
|
14630
|
-
|
|
14631
|
-
|
|
14667
|
+
} else if (delta.type === "input_json_delta" && "partial_json" in delta) {
|
|
14668
|
+
const partialJson = delta.partial_json;
|
|
14669
|
+
if (partialJson && acc !== void 0) {
|
|
14670
|
+
acc.textDeltas.push(partialJson);
|
|
14671
|
+
}
|
|
14672
|
+
} else if (delta.type === "thinking_delta" && "thinking" in delta) {
|
|
14673
|
+
const thinking = delta.thinking;
|
|
14674
|
+
if (thinking && acc !== void 0) {
|
|
14675
|
+
acc.textDeltas.push(thinking);
|
|
14676
|
+
}
|
|
14677
|
+
} else if (delta.type === "citations_delta" && "citation" in delta) {
|
|
14678
|
+
const citation = delta.citation;
|
|
14679
|
+
if (citation && acc !== void 0) {
|
|
14680
|
+
acc.citations.push(citation);
|
|
14632
14681
|
}
|
|
14633
14682
|
}
|
|
14634
14683
|
break;
|
|
14684
|
+
}
|
|
14635
14685
|
case "content_block_stop":
|
|
14636
14686
|
finalizeContentBlock(
|
|
14637
14687
|
event.index,
|
|
@@ -14657,7 +14707,7 @@ function aggregateAnthropicStreamChunks(chunks) {
|
|
|
14657
14707
|
})).filter(({ block }) => block !== void 0).sort((left, right) => left.index - right.index).map(({ block }) => block);
|
|
14658
14708
|
let output = fallbackTextDeltas.join("");
|
|
14659
14709
|
if (orderedContent.length > 0) {
|
|
14660
|
-
if (orderedContent.every(isTextContentBlock)) {
|
|
14710
|
+
if (orderedContent.every(isTextContentBlock) && orderedContent.every((block) => !block.citations?.length)) {
|
|
14661
14711
|
output = orderedContent.map((block) => block.text).join("");
|
|
14662
14712
|
} else {
|
|
14663
14713
|
output = {
|
|
@@ -14683,7 +14733,8 @@ function finalizeContentBlock(index, contentBlocks, contentBlockDeltas, fallback
|
|
|
14683
14733
|
if (!contentBlock) {
|
|
14684
14734
|
return;
|
|
14685
14735
|
}
|
|
14686
|
-
const
|
|
14736
|
+
const acc = contentBlockDeltas[index];
|
|
14737
|
+
const text = acc?.textDeltas.join("") ?? "";
|
|
14687
14738
|
if (isToolUseContentBlock(contentBlock)) {
|
|
14688
14739
|
if (!text) {
|
|
14689
14740
|
return;
|
|
@@ -14700,20 +14751,28 @@ function finalizeContentBlock(index, contentBlocks, contentBlockDeltas, fallback
|
|
|
14700
14751
|
return;
|
|
14701
14752
|
}
|
|
14702
14753
|
if (isTextContentBlock(contentBlock)) {
|
|
14754
|
+
if (!text) {
|
|
14755
|
+
delete contentBlocks[index];
|
|
14756
|
+
return;
|
|
14757
|
+
}
|
|
14758
|
+
const updated = { ...contentBlock, text };
|
|
14759
|
+
if (acc?.citations.length) {
|
|
14760
|
+
updated.citations = acc.citations;
|
|
14761
|
+
}
|
|
14762
|
+
contentBlocks[index] = updated;
|
|
14763
|
+
return;
|
|
14764
|
+
}
|
|
14765
|
+
if (isThinkingContentBlock(contentBlock)) {
|
|
14703
14766
|
if (!text) {
|
|
14704
14767
|
delete contentBlocks[index];
|
|
14705
14768
|
return;
|
|
14706
14769
|
}
|
|
14707
14770
|
contentBlocks[index] = {
|
|
14708
14771
|
...contentBlock,
|
|
14709
|
-
text
|
|
14772
|
+
thinking: text
|
|
14710
14773
|
};
|
|
14711
14774
|
return;
|
|
14712
14775
|
}
|
|
14713
|
-
if (text) {
|
|
14714
|
-
fallbackTextDeltas.push(text);
|
|
14715
|
-
}
|
|
14716
|
-
delete contentBlocks[index];
|
|
14717
14776
|
}
|
|
14718
14777
|
function isTextContentBlock(contentBlock) {
|
|
14719
14778
|
return contentBlock.type === "text";
|
|
@@ -14721,6 +14780,9 @@ function isTextContentBlock(contentBlock) {
|
|
|
14721
14780
|
function isToolUseContentBlock(contentBlock) {
|
|
14722
14781
|
return contentBlock.type === "tool_use";
|
|
14723
14782
|
}
|
|
14783
|
+
function isThinkingContentBlock(contentBlock) {
|
|
14784
|
+
return contentBlock.type === "thinking";
|
|
14785
|
+
}
|
|
14724
14786
|
function isAnthropicBase64ContentBlock(input) {
|
|
14725
14787
|
return (input.type === "image" || input.type === "document") && isObject(input.source) && input.source.type === "base64";
|
|
14726
14788
|
}
|
|
@@ -14775,15 +14837,6 @@ function coalesceInput(messages, system) {
|
|
|
14775
14837
|
}
|
|
14776
14838
|
return input;
|
|
14777
14839
|
}
|
|
14778
|
-
function filterFrom(obj, fieldsToRemove) {
|
|
14779
|
-
const result = {};
|
|
14780
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
14781
|
-
if (!fieldsToRemove.includes(key)) {
|
|
14782
|
-
result[key] = value;
|
|
14783
|
-
}
|
|
14784
|
-
}
|
|
14785
|
-
return result;
|
|
14786
|
-
}
|
|
14787
14840
|
|
|
14788
14841
|
// src/wrappers/ai-sdk/normalize-logged-output.ts
|
|
14789
14842
|
var REMOVE_NORMALIZED_VALUE = Symbol("braintrust.ai-sdk.remove-normalized");
|
|
@@ -14897,10 +14950,6 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
14897
14950
|
channelName: "streamText",
|
|
14898
14951
|
kind: "async"
|
|
14899
14952
|
}),
|
|
14900
|
-
streamTextSync: channel({
|
|
14901
|
-
channelName: "streamText.sync",
|
|
14902
|
-
kind: "sync-stream"
|
|
14903
|
-
}),
|
|
14904
14953
|
generateObject: channel({
|
|
14905
14954
|
channelName: "generateObject",
|
|
14906
14955
|
kind: "async"
|
|
@@ -14909,10 +14958,6 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
14909
14958
|
channelName: "streamObject",
|
|
14910
14959
|
kind: "async"
|
|
14911
14960
|
}),
|
|
14912
|
-
streamObjectSync: channel({
|
|
14913
|
-
channelName: "streamObject.sync",
|
|
14914
|
-
kind: "sync-stream"
|
|
14915
|
-
}),
|
|
14916
14961
|
agentGenerate: channel({
|
|
14917
14962
|
channelName: "Agent.generate",
|
|
14918
14963
|
kind: "async"
|
|
@@ -14948,6 +14993,9 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
|
14948
14993
|
];
|
|
14949
14994
|
var AUTO_PATCHED_MODEL = Symbol.for("braintrust.ai-sdk.auto-patched-model");
|
|
14950
14995
|
var AUTO_PATCHED_TOOL = Symbol.for("braintrust.ai-sdk.auto-patched-tool");
|
|
14996
|
+
var RUNTIME_DENY_OUTPUT_PATHS = Symbol.for(
|
|
14997
|
+
"braintrust.ai-sdk.deny-output-paths"
|
|
14998
|
+
);
|
|
14951
14999
|
var AISDKPlugin = class extends BasePlugin {
|
|
14952
15000
|
config;
|
|
14953
15001
|
constructor(config3 = {}) {
|
|
@@ -14969,7 +15017,10 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
14969
15017
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
14970
15018
|
extractOutput: (result, endEvent) => {
|
|
14971
15019
|
finalizeAISDKChildTracing(endEvent);
|
|
14972
|
-
return processAISDKOutput(
|
|
15020
|
+
return processAISDKOutput(
|
|
15021
|
+
result,
|
|
15022
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15023
|
+
);
|
|
14973
15024
|
},
|
|
14974
15025
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
14975
15026
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -14980,25 +15031,14 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
14980
15031
|
name: "streamText",
|
|
14981
15032
|
type: "llm" /* LLM */,
|
|
14982
15033
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
14983
|
-
extractOutput: (result) => processAISDKOutput(
|
|
15034
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
15035
|
+
result,
|
|
15036
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15037
|
+
),
|
|
14984
15038
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
14985
15039
|
aggregateChunks: aggregateAISDKChunks,
|
|
14986
15040
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
14987
|
-
denyOutputPaths,
|
|
14988
|
-
endEvent,
|
|
14989
|
-
result,
|
|
14990
|
-
span,
|
|
14991
|
-
startTime
|
|
14992
|
-
})
|
|
14993
|
-
})
|
|
14994
|
-
);
|
|
14995
|
-
this.unsubscribers.push(
|
|
14996
|
-
traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
|
|
14997
|
-
name: "streamText",
|
|
14998
|
-
type: "llm" /* LLM */,
|
|
14999
|
-
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
15000
|
-
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
15001
|
-
denyOutputPaths,
|
|
15041
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
15002
15042
|
endEvent,
|
|
15003
15043
|
result,
|
|
15004
15044
|
span,
|
|
@@ -15013,7 +15053,10 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15013
15053
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
15014
15054
|
extractOutput: (result, endEvent) => {
|
|
15015
15055
|
finalizeAISDKChildTracing(endEvent);
|
|
15016
|
-
return processAISDKOutput(
|
|
15056
|
+
return processAISDKOutput(
|
|
15057
|
+
result,
|
|
15058
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15059
|
+
);
|
|
15017
15060
|
},
|
|
15018
15061
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
15019
15062
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -15024,25 +15067,14 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15024
15067
|
name: "streamObject",
|
|
15025
15068
|
type: "llm" /* LLM */,
|
|
15026
15069
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
15027
|
-
extractOutput: (result) => processAISDKOutput(
|
|
15070
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
15071
|
+
result,
|
|
15072
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15073
|
+
),
|
|
15028
15074
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
15029
15075
|
aggregateChunks: aggregateAISDKChunks,
|
|
15030
15076
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
15031
|
-
denyOutputPaths,
|
|
15032
|
-
endEvent,
|
|
15033
|
-
result,
|
|
15034
|
-
span,
|
|
15035
|
-
startTime
|
|
15036
|
-
})
|
|
15037
|
-
})
|
|
15038
|
-
);
|
|
15039
|
-
this.unsubscribers.push(
|
|
15040
|
-
traceSyncStreamChannel(aiSDKChannels.streamObjectSync, {
|
|
15041
|
-
name: "streamObject",
|
|
15042
|
-
type: "llm" /* LLM */,
|
|
15043
|
-
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
15044
|
-
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
15045
|
-
denyOutputPaths,
|
|
15077
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
15046
15078
|
endEvent,
|
|
15047
15079
|
result,
|
|
15048
15080
|
span,
|
|
@@ -15057,7 +15089,10 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15057
15089
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
15058
15090
|
extractOutput: (result, endEvent) => {
|
|
15059
15091
|
finalizeAISDKChildTracing(endEvent);
|
|
15060
|
-
return processAISDKOutput(
|
|
15092
|
+
return processAISDKOutput(
|
|
15093
|
+
result,
|
|
15094
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15095
|
+
);
|
|
15061
15096
|
},
|
|
15062
15097
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
15063
15098
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -15068,11 +15103,14 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15068
15103
|
name: "Agent.stream",
|
|
15069
15104
|
type: "llm" /* LLM */,
|
|
15070
15105
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
15071
|
-
extractOutput: (result) => processAISDKOutput(
|
|
15106
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
15107
|
+
result,
|
|
15108
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15109
|
+
),
|
|
15072
15110
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
15073
15111
|
aggregateChunks: aggregateAISDKChunks,
|
|
15074
15112
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
15075
|
-
denyOutputPaths,
|
|
15113
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
15076
15114
|
endEvent,
|
|
15077
15115
|
result,
|
|
15078
15116
|
span,
|
|
@@ -15087,7 +15125,10 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15087
15125
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
15088
15126
|
extractOutput: (result, endEvent) => {
|
|
15089
15127
|
finalizeAISDKChildTracing(endEvent);
|
|
15090
|
-
return processAISDKOutput(
|
|
15128
|
+
return processAISDKOutput(
|
|
15129
|
+
result,
|
|
15130
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15131
|
+
);
|
|
15091
15132
|
},
|
|
15092
15133
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
15093
15134
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -15098,11 +15139,14 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15098
15139
|
name: "ToolLoopAgent.stream",
|
|
15099
15140
|
type: "llm" /* LLM */,
|
|
15100
15141
|
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
15101
|
-
extractOutput: (result) => processAISDKOutput(
|
|
15142
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
15143
|
+
result,
|
|
15144
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15145
|
+
),
|
|
15102
15146
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
15103
15147
|
aggregateChunks: aggregateAISDKChunks,
|
|
15104
15148
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
15105
|
-
denyOutputPaths,
|
|
15149
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
15106
15150
|
endEvent,
|
|
15107
15151
|
result,
|
|
15108
15152
|
span,
|
|
@@ -15112,85 +15156,383 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15112
15156
|
);
|
|
15113
15157
|
}
|
|
15114
15158
|
};
|
|
15115
|
-
function
|
|
15116
|
-
if (
|
|
15117
|
-
|
|
15118
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
15119
|
-
return input;
|
|
15159
|
+
function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
15160
|
+
if (Array.isArray(event?.denyOutputPaths)) {
|
|
15161
|
+
return event.denyOutputPaths;
|
|
15120
15162
|
}
|
|
15121
|
-
const
|
|
15122
|
-
|
|
15123
|
-
|
|
15124
|
-
function prepareAISDKInput(params, event, span, denyOutputPaths) {
|
|
15125
|
-
const input = processAISDKInput(params);
|
|
15126
|
-
const metadata = extractMetadataFromParams(params, event.self);
|
|
15127
|
-
const childTracing = prepareAISDKChildTracing(
|
|
15128
|
-
params,
|
|
15129
|
-
event.self,
|
|
15130
|
-
span,
|
|
15131
|
-
denyOutputPaths
|
|
15132
|
-
);
|
|
15133
|
-
event.__braintrust_ai_sdk_model_wrapped = childTracing.modelWrapped;
|
|
15134
|
-
if (childTracing.cleanup) {
|
|
15135
|
-
event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
|
|
15163
|
+
const firstArgument = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
15164
|
+
if (!firstArgument || typeof firstArgument !== "object") {
|
|
15165
|
+
return defaultDenyOutputPaths;
|
|
15136
15166
|
}
|
|
15137
|
-
|
|
15138
|
-
|
|
15139
|
-
|
|
15140
|
-
};
|
|
15141
|
-
}
|
|
15142
|
-
function extractTopLevelAISDKMetrics(result, event, startTime) {
|
|
15143
|
-
const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics(result);
|
|
15144
|
-
if (startTime) {
|
|
15145
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
15167
|
+
const runtimeDenyOutputPaths = firstArgument[RUNTIME_DENY_OUTPUT_PATHS];
|
|
15168
|
+
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path8) => typeof path8 === "string")) {
|
|
15169
|
+
return runtimeDenyOutputPaths;
|
|
15146
15170
|
}
|
|
15147
|
-
return
|
|
15171
|
+
return defaultDenyOutputPaths;
|
|
15148
15172
|
}
|
|
15149
|
-
|
|
15150
|
-
return
|
|
15151
|
-
}
|
|
15152
|
-
|
|
15153
|
-
|
|
15154
|
-
|
|
15155
|
-
|
|
15156
|
-
|
|
15173
|
+
var isZodSchema2 = (value) => {
|
|
15174
|
+
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
15175
|
+
};
|
|
15176
|
+
var serializeZodSchema2 = (schema) => {
|
|
15177
|
+
try {
|
|
15178
|
+
return zodToJsonSchema(schema);
|
|
15179
|
+
} catch {
|
|
15180
|
+
return {
|
|
15181
|
+
type: "object",
|
|
15182
|
+
description: "Zod schema (conversion failed)"
|
|
15183
|
+
};
|
|
15184
|
+
}
|
|
15185
|
+
};
|
|
15186
|
+
var isOutputObject = (value) => {
|
|
15187
|
+
if (value == null || typeof value !== "object") {
|
|
15188
|
+
return false;
|
|
15189
|
+
}
|
|
15190
|
+
const output = value;
|
|
15191
|
+
if (!("responseFormat" in output)) {
|
|
15192
|
+
return false;
|
|
15193
|
+
}
|
|
15194
|
+
if (output.type === "object" || output.type === "text") {
|
|
15195
|
+
return true;
|
|
15196
|
+
}
|
|
15197
|
+
if (typeof output.responseFormat === "function" || typeof output.responseFormat === "object") {
|
|
15198
|
+
return true;
|
|
15199
|
+
}
|
|
15200
|
+
return false;
|
|
15201
|
+
};
|
|
15202
|
+
var serializeOutputObject = (output, model) => {
|
|
15203
|
+
try {
|
|
15204
|
+
const result = {
|
|
15205
|
+
response_format: null
|
|
15206
|
+
};
|
|
15207
|
+
if (output.type) {
|
|
15208
|
+
result.type = output.type;
|
|
15209
|
+
}
|
|
15210
|
+
let responseFormat;
|
|
15211
|
+
if (typeof output.responseFormat === "function") {
|
|
15212
|
+
const mockModelForSchema = {
|
|
15213
|
+
supportsStructuredOutputs: true,
|
|
15214
|
+
...model && typeof model === "object" ? model : {}
|
|
15215
|
+
};
|
|
15216
|
+
responseFormat = output.responseFormat({ model: mockModelForSchema });
|
|
15217
|
+
} else if (output.responseFormat != null && typeof output.responseFormat === "object") {
|
|
15218
|
+
responseFormat = output.responseFormat;
|
|
15219
|
+
}
|
|
15220
|
+
if (responseFormat) {
|
|
15221
|
+
if (typeof responseFormat.then === "function") {
|
|
15222
|
+
result.response_format = Promise.resolve(responseFormat).then(
|
|
15223
|
+
(resolved) => {
|
|
15224
|
+
if (resolved.schema && isZodSchema2(resolved.schema)) {
|
|
15225
|
+
return {
|
|
15226
|
+
...resolved,
|
|
15227
|
+
schema: serializeZodSchema2(resolved.schema)
|
|
15228
|
+
};
|
|
15229
|
+
}
|
|
15230
|
+
return resolved;
|
|
15231
|
+
}
|
|
15232
|
+
);
|
|
15233
|
+
} else {
|
|
15234
|
+
const syncResponseFormat = responseFormat;
|
|
15235
|
+
if (syncResponseFormat.schema && isZodSchema2(syncResponseFormat.schema)) {
|
|
15236
|
+
responseFormat = {
|
|
15237
|
+
...syncResponseFormat,
|
|
15238
|
+
schema: serializeZodSchema2(syncResponseFormat.schema)
|
|
15239
|
+
};
|
|
15240
|
+
}
|
|
15241
|
+
result.response_format = responseFormat;
|
|
15242
|
+
}
|
|
15157
15243
|
}
|
|
15158
|
-
|
|
15159
|
-
|
|
15160
|
-
|
|
15161
|
-
|
|
15162
|
-
|
|
15163
|
-
if (model) {
|
|
15164
|
-
metadata.model = model;
|
|
15244
|
+
return result;
|
|
15245
|
+
} catch {
|
|
15246
|
+
return {
|
|
15247
|
+
response_format: null
|
|
15248
|
+
};
|
|
15165
15249
|
}
|
|
15166
|
-
|
|
15167
|
-
|
|
15250
|
+
};
|
|
15251
|
+
var processInputAttachmentsSync = (input) => {
|
|
15252
|
+
if (!input) return { input };
|
|
15253
|
+
const processed = { ...input };
|
|
15254
|
+
if (input.messages && Array.isArray(input.messages)) {
|
|
15255
|
+
processed.messages = input.messages.map(processMessage);
|
|
15256
|
+
}
|
|
15257
|
+
if (input.prompt && typeof input.prompt === "object") {
|
|
15258
|
+
if (Array.isArray(input.prompt)) {
|
|
15259
|
+
processed.prompt = input.prompt.map(processMessage);
|
|
15260
|
+
} else {
|
|
15261
|
+
processed.prompt = processPromptContent(input.prompt);
|
|
15262
|
+
}
|
|
15168
15263
|
}
|
|
15169
|
-
|
|
15170
|
-
|
|
15171
|
-
metadata.tools = tools;
|
|
15264
|
+
if (input.schema && isZodSchema2(input.schema)) {
|
|
15265
|
+
processed.schema = serializeZodSchema2(input.schema);
|
|
15172
15266
|
}
|
|
15173
|
-
|
|
15174
|
-
|
|
15175
|
-
|
|
15176
|
-
|
|
15177
|
-
|
|
15178
|
-
|
|
15179
|
-
let
|
|
15180
|
-
|
|
15181
|
-
const
|
|
15182
|
-
if (
|
|
15183
|
-
|
|
15267
|
+
if (input.callOptionsSchema && isZodSchema2(input.callOptionsSchema)) {
|
|
15268
|
+
processed.callOptionsSchema = serializeZodSchema2(input.callOptionsSchema);
|
|
15269
|
+
}
|
|
15270
|
+
if (input.tools) {
|
|
15271
|
+
processed.tools = serializeAISDKToolsForLogging(input.tools);
|
|
15272
|
+
}
|
|
15273
|
+
let outputPromise;
|
|
15274
|
+
if (input.output && isOutputObject(input.output)) {
|
|
15275
|
+
const serialized = serializeOutputObject(input.output, input.model);
|
|
15276
|
+
if (serialized.response_format && typeof serialized.response_format.then === "function") {
|
|
15277
|
+
processed.output = { ...serialized, response_format: {} };
|
|
15278
|
+
outputPromise = serialized.response_format.then(
|
|
15279
|
+
(resolvedFormat) => ({
|
|
15280
|
+
output: { ...serialized, response_format: resolvedFormat }
|
|
15281
|
+
})
|
|
15282
|
+
);
|
|
15283
|
+
} else {
|
|
15284
|
+
processed.output = serialized;
|
|
15184
15285
|
}
|
|
15185
|
-
|
|
15186
|
-
|
|
15187
|
-
|
|
15188
|
-
|
|
15189
|
-
|
|
15190
|
-
|
|
15191
|
-
|
|
15192
|
-
|
|
15193
|
-
|
|
15286
|
+
}
|
|
15287
|
+
if ("prepareCall" in processed && typeof processed.prepareCall === "function") {
|
|
15288
|
+
processed.prepareCall = "[Function]";
|
|
15289
|
+
}
|
|
15290
|
+
return { input: processed, outputPromise };
|
|
15291
|
+
};
|
|
15292
|
+
var processMessage = (message) => {
|
|
15293
|
+
if (!message || typeof message !== "object") return message;
|
|
15294
|
+
if (Array.isArray(message.content)) {
|
|
15295
|
+
return {
|
|
15296
|
+
...message,
|
|
15297
|
+
content: message.content.map(processContentPart)
|
|
15298
|
+
};
|
|
15299
|
+
}
|
|
15300
|
+
if (typeof message.content === "object" && message.content !== null) {
|
|
15301
|
+
return {
|
|
15302
|
+
...message,
|
|
15303
|
+
content: processContentPart(message.content)
|
|
15304
|
+
};
|
|
15305
|
+
}
|
|
15306
|
+
return message;
|
|
15307
|
+
};
|
|
15308
|
+
var processPromptContent = (prompt) => {
|
|
15309
|
+
if (Array.isArray(prompt)) {
|
|
15310
|
+
return prompt.map(processContentPart);
|
|
15311
|
+
}
|
|
15312
|
+
if (prompt.content) {
|
|
15313
|
+
if (Array.isArray(prompt.content)) {
|
|
15314
|
+
return {
|
|
15315
|
+
...prompt,
|
|
15316
|
+
content: prompt.content.map(processContentPart)
|
|
15317
|
+
};
|
|
15318
|
+
} else if (typeof prompt.content === "object") {
|
|
15319
|
+
return {
|
|
15320
|
+
...prompt,
|
|
15321
|
+
content: processContentPart(prompt.content)
|
|
15322
|
+
};
|
|
15323
|
+
}
|
|
15324
|
+
}
|
|
15325
|
+
return prompt;
|
|
15326
|
+
};
|
|
15327
|
+
var processContentPart = (part) => {
|
|
15328
|
+
if (!part || typeof part !== "object") return part;
|
|
15329
|
+
try {
|
|
15330
|
+
if (part.type === "image" && part.image) {
|
|
15331
|
+
const imageAttachment = convertImageToAttachment(
|
|
15332
|
+
part.image,
|
|
15333
|
+
part.mimeType || part.mediaType
|
|
15334
|
+
);
|
|
15335
|
+
if (imageAttachment) {
|
|
15336
|
+
return {
|
|
15337
|
+
...part,
|
|
15338
|
+
image: imageAttachment
|
|
15339
|
+
};
|
|
15340
|
+
}
|
|
15341
|
+
}
|
|
15342
|
+
if (part.type === "file" && part.data && (part.mimeType || part.mediaType)) {
|
|
15343
|
+
const fileAttachment = convertDataToAttachment(
|
|
15344
|
+
part.data,
|
|
15345
|
+
part.mimeType || part.mediaType,
|
|
15346
|
+
part.name || part.filename
|
|
15347
|
+
);
|
|
15348
|
+
if (fileAttachment) {
|
|
15349
|
+
return {
|
|
15350
|
+
...part,
|
|
15351
|
+
data: fileAttachment
|
|
15352
|
+
};
|
|
15353
|
+
}
|
|
15354
|
+
}
|
|
15355
|
+
if (part.type === "image_url" && part.image_url) {
|
|
15356
|
+
if (typeof part.image_url === "object" && part.image_url.url) {
|
|
15357
|
+
const imageAttachment = convertImageToAttachment(part.image_url.url);
|
|
15358
|
+
if (imageAttachment) {
|
|
15359
|
+
return {
|
|
15360
|
+
...part,
|
|
15361
|
+
image_url: {
|
|
15362
|
+
...part.image_url,
|
|
15363
|
+
url: imageAttachment
|
|
15364
|
+
}
|
|
15365
|
+
};
|
|
15366
|
+
}
|
|
15367
|
+
}
|
|
15368
|
+
}
|
|
15369
|
+
} catch (error2) {
|
|
15370
|
+
console.warn("Error processing content part:", error2);
|
|
15371
|
+
}
|
|
15372
|
+
return part;
|
|
15373
|
+
};
|
|
15374
|
+
var convertImageToAttachment = (image, explicitMimeType) => {
|
|
15375
|
+
try {
|
|
15376
|
+
if (typeof image === "string" && image.startsWith("data:")) {
|
|
15377
|
+
const [mimeTypeSection, base64Data] = image.split(",");
|
|
15378
|
+
const mimeType = mimeTypeSection.match(/data:(.*?);/)?.[1];
|
|
15379
|
+
if (mimeType && base64Data) {
|
|
15380
|
+
const blob = convertDataToBlob(base64Data, mimeType);
|
|
15381
|
+
if (blob) {
|
|
15382
|
+
return new Attachment({
|
|
15383
|
+
data: blob,
|
|
15384
|
+
filename: `image.${getExtensionFromMediaType(mimeType)}`,
|
|
15385
|
+
contentType: mimeType
|
|
15386
|
+
});
|
|
15387
|
+
}
|
|
15388
|
+
}
|
|
15389
|
+
}
|
|
15390
|
+
if (explicitMimeType) {
|
|
15391
|
+
if (image instanceof Uint8Array) {
|
|
15392
|
+
return new Attachment({
|
|
15393
|
+
data: new Blob([image], { type: explicitMimeType }),
|
|
15394
|
+
filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
|
|
15395
|
+
contentType: explicitMimeType
|
|
15396
|
+
});
|
|
15397
|
+
}
|
|
15398
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
|
|
15399
|
+
return new Attachment({
|
|
15400
|
+
data: new Blob([image], { type: explicitMimeType }),
|
|
15401
|
+
filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
|
|
15402
|
+
contentType: explicitMimeType
|
|
15403
|
+
});
|
|
15404
|
+
}
|
|
15405
|
+
}
|
|
15406
|
+
if (image instanceof Blob && image.type) {
|
|
15407
|
+
return new Attachment({
|
|
15408
|
+
data: image,
|
|
15409
|
+
filename: `image.${getExtensionFromMediaType(image.type)}`,
|
|
15410
|
+
contentType: image.type
|
|
15411
|
+
});
|
|
15412
|
+
}
|
|
15413
|
+
if (image instanceof Attachment) {
|
|
15414
|
+
return image;
|
|
15415
|
+
}
|
|
15416
|
+
} catch (error2) {
|
|
15417
|
+
console.warn("Error converting image to attachment:", error2);
|
|
15418
|
+
}
|
|
15419
|
+
return null;
|
|
15420
|
+
};
|
|
15421
|
+
var convertDataToAttachment = (data, mimeType, filename) => {
|
|
15422
|
+
if (!mimeType) return null;
|
|
15423
|
+
try {
|
|
15424
|
+
let blob = null;
|
|
15425
|
+
if (typeof data === "string" && data.startsWith("data:")) {
|
|
15426
|
+
const [, base64Data] = data.split(",");
|
|
15427
|
+
if (base64Data) {
|
|
15428
|
+
blob = convertDataToBlob(base64Data, mimeType);
|
|
15429
|
+
}
|
|
15430
|
+
} else if (typeof data === "string" && data.length > 0) {
|
|
15431
|
+
blob = convertDataToBlob(data, mimeType);
|
|
15432
|
+
} else if (data instanceof Uint8Array) {
|
|
15433
|
+
blob = new Blob([data], { type: mimeType });
|
|
15434
|
+
} else if (typeof Buffer !== "undefined" && Buffer.isBuffer(data)) {
|
|
15435
|
+
blob = new Blob([data], { type: mimeType });
|
|
15436
|
+
} else if (data instanceof Blob) {
|
|
15437
|
+
blob = data;
|
|
15438
|
+
}
|
|
15439
|
+
if (blob) {
|
|
15440
|
+
return new Attachment({
|
|
15441
|
+
data: blob,
|
|
15442
|
+
filename: filename || `file.${getExtensionFromMediaType(mimeType)}`,
|
|
15443
|
+
contentType: mimeType
|
|
15444
|
+
});
|
|
15445
|
+
}
|
|
15446
|
+
} catch (error2) {
|
|
15447
|
+
console.warn("Error converting data to attachment:", error2);
|
|
15448
|
+
}
|
|
15449
|
+
return null;
|
|
15450
|
+
};
|
|
15451
|
+
function processAISDKInput(params) {
|
|
15452
|
+
return processInputAttachmentsSync(params);
|
|
15453
|
+
}
|
|
15454
|
+
function prepareAISDKInput(params, event, span, defaultDenyOutputPaths) {
|
|
15455
|
+
const { input, outputPromise } = processAISDKInput(params);
|
|
15456
|
+
if (outputPromise && input && typeof input === "object") {
|
|
15457
|
+
outputPromise.then((resolvedData) => {
|
|
15458
|
+
span.log({
|
|
15459
|
+
input: {
|
|
15460
|
+
...input,
|
|
15461
|
+
...resolvedData
|
|
15462
|
+
}
|
|
15463
|
+
});
|
|
15464
|
+
}).catch(() => {
|
|
15465
|
+
});
|
|
15466
|
+
}
|
|
15467
|
+
const metadata = extractMetadataFromParams(params, event.self);
|
|
15468
|
+
const childTracing = prepareAISDKChildTracing(
|
|
15469
|
+
params,
|
|
15470
|
+
event.self,
|
|
15471
|
+
span,
|
|
15472
|
+
defaultDenyOutputPaths,
|
|
15473
|
+
event.aiSDK
|
|
15474
|
+
);
|
|
15475
|
+
event.modelWrapped = childTracing.modelWrapped;
|
|
15476
|
+
if (childTracing.cleanup) {
|
|
15477
|
+
event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
|
|
15478
|
+
}
|
|
15479
|
+
return {
|
|
15480
|
+
input,
|
|
15481
|
+
metadata
|
|
15482
|
+
};
|
|
15483
|
+
}
|
|
15484
|
+
function extractTopLevelAISDKMetrics(result, event, startTime) {
|
|
15485
|
+
const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics(result);
|
|
15486
|
+
if (startTime) {
|
|
15487
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
15488
|
+
}
|
|
15489
|
+
return metrics;
|
|
15490
|
+
}
|
|
15491
|
+
function hasModelChildTracing(event) {
|
|
15492
|
+
return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
|
|
15493
|
+
}
|
|
15494
|
+
function extractMetadataFromParams(params, self) {
|
|
15495
|
+
const metadata = {
|
|
15496
|
+
braintrust: {
|
|
15497
|
+
integration_name: "ai-sdk",
|
|
15498
|
+
sdk_language: "typescript"
|
|
15499
|
+
}
|
|
15500
|
+
};
|
|
15501
|
+
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;
|
|
15502
|
+
const { model, provider } = serializeModelWithProvider(
|
|
15503
|
+
params.model ?? agentModel
|
|
15504
|
+
);
|
|
15505
|
+
if (model) {
|
|
15506
|
+
metadata.model = model;
|
|
15507
|
+
}
|
|
15508
|
+
if (provider) {
|
|
15509
|
+
metadata.provider = provider;
|
|
15510
|
+
}
|
|
15511
|
+
const tools = serializeAISDKToolsForLogging(params.tools);
|
|
15512
|
+
if (tools) {
|
|
15513
|
+
metadata.tools = tools;
|
|
15514
|
+
}
|
|
15515
|
+
return metadata;
|
|
15516
|
+
}
|
|
15517
|
+
function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK) {
|
|
15518
|
+
const cleanup = [];
|
|
15519
|
+
const patchedModels = /* @__PURE__ */ new WeakSet();
|
|
15520
|
+
const patchedTools = /* @__PURE__ */ new WeakSet();
|
|
15521
|
+
let modelWrapped = false;
|
|
15522
|
+
const patchModel = (model) => {
|
|
15523
|
+
const resolvedModel = resolveAISDKModel(model, aiSDK);
|
|
15524
|
+
if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function" || patchedModels.has(resolvedModel) || resolvedModel[AUTO_PATCHED_MODEL]) {
|
|
15525
|
+
return resolvedModel;
|
|
15526
|
+
}
|
|
15527
|
+
patchedModels.add(resolvedModel);
|
|
15528
|
+
resolvedModel[AUTO_PATCHED_MODEL] = true;
|
|
15529
|
+
modelWrapped = true;
|
|
15530
|
+
const originalDoGenerate = resolvedModel.doGenerate;
|
|
15531
|
+
const originalDoStream = resolvedModel.doStream;
|
|
15532
|
+
const baseMetadata = buildAISDKChildMetadata(resolvedModel);
|
|
15533
|
+
resolvedModel.doGenerate = async function doGeneratePatched(options) {
|
|
15534
|
+
return parentSpan.traced(
|
|
15535
|
+
async (span) => {
|
|
15194
15536
|
const result = await Reflect.apply(
|
|
15195
15537
|
originalDoGenerate,
|
|
15196
15538
|
resolvedModel,
|
|
@@ -15209,7 +15551,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
15209
15551
|
type: "llm" /* LLM */
|
|
15210
15552
|
},
|
|
15211
15553
|
event: {
|
|
15212
|
-
input: processAISDKInput(options),
|
|
15554
|
+
input: processAISDKInput(options).input,
|
|
15213
15555
|
metadata: baseMetadata
|
|
15214
15556
|
}
|
|
15215
15557
|
}
|
|
@@ -15223,7 +15565,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
15223
15565
|
type: "llm" /* LLM */
|
|
15224
15566
|
},
|
|
15225
15567
|
event: {
|
|
15226
|
-
input: processAISDKInput(options),
|
|
15568
|
+
input: processAISDKInput(options).input,
|
|
15227
15569
|
metadata: baseMetadata
|
|
15228
15570
|
}
|
|
15229
15571
|
});
|
|
@@ -15231,6 +15573,8 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
15231
15573
|
span,
|
|
15232
15574
|
() => Reflect.apply(originalDoStream, resolvedModel, [options])
|
|
15233
15575
|
);
|
|
15576
|
+
const streamStartTime = getCurrentUnixTimestamp();
|
|
15577
|
+
let firstChunkTime;
|
|
15234
15578
|
const output = {};
|
|
15235
15579
|
let text = "";
|
|
15236
15580
|
let reasoning = "";
|
|
@@ -15238,6 +15582,9 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
15238
15582
|
let object = void 0;
|
|
15239
15583
|
const transformStream = new TransformStream({
|
|
15240
15584
|
transform(chunk, controller) {
|
|
15585
|
+
if (firstChunkTime === void 0) {
|
|
15586
|
+
firstChunkTime = getCurrentUnixTimestamp();
|
|
15587
|
+
}
|
|
15241
15588
|
switch (chunk.type) {
|
|
15242
15589
|
case "text-delta":
|
|
15243
15590
|
text += extractTextDelta(chunk);
|
|
@@ -15278,12 +15625,19 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
15278
15625
|
if (object !== void 0) {
|
|
15279
15626
|
output.object = object;
|
|
15280
15627
|
}
|
|
15628
|
+
const metrics = extractTokenMetrics(output);
|
|
15629
|
+
if (firstChunkTime !== void 0) {
|
|
15630
|
+
metrics.time_to_first_token = Math.max(
|
|
15631
|
+
firstChunkTime - streamStartTime,
|
|
15632
|
+
1e-6
|
|
15633
|
+
);
|
|
15634
|
+
}
|
|
15281
15635
|
span.log({
|
|
15282
15636
|
output: processAISDKOutput(
|
|
15283
15637
|
output,
|
|
15284
15638
|
denyOutputPaths
|
|
15285
15639
|
),
|
|
15286
|
-
metrics
|
|
15640
|
+
metrics,
|
|
15287
15641
|
...buildResolvedMetadataPayload(output)
|
|
15288
15642
|
});
|
|
15289
15643
|
span.end();
|
|
@@ -15305,6 +15659,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
15305
15659
|
}
|
|
15306
15660
|
delete resolvedModel[AUTO_PATCHED_MODEL];
|
|
15307
15661
|
});
|
|
15662
|
+
return resolvedModel;
|
|
15308
15663
|
};
|
|
15309
15664
|
const patchTool = (tool, name) => {
|
|
15310
15665
|
if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool) || tool[AUTO_PATCHED_TOOL]) {
|
|
@@ -15377,17 +15732,26 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
15377
15732
|
}
|
|
15378
15733
|
};
|
|
15379
15734
|
if (params && typeof params === "object") {
|
|
15380
|
-
patchModel(params.model);
|
|
15735
|
+
const patchedParamModel = patchModel(params.model);
|
|
15736
|
+
if (typeof params.model === "string" && patchedParamModel && typeof patchedParamModel === "object") {
|
|
15737
|
+
params.model = patchedParamModel;
|
|
15738
|
+
}
|
|
15381
15739
|
patchTools(params.tools);
|
|
15382
15740
|
}
|
|
15383
15741
|
if (self && typeof self === "object") {
|
|
15384
15742
|
const selfRecord = self;
|
|
15385
15743
|
if (selfRecord.model !== void 0) {
|
|
15386
|
-
patchModel(selfRecord.model);
|
|
15744
|
+
const patchedSelfModel = patchModel(selfRecord.model);
|
|
15745
|
+
if (typeof selfRecord.model === "string" && patchedSelfModel && typeof patchedSelfModel === "object") {
|
|
15746
|
+
selfRecord.model = patchedSelfModel;
|
|
15747
|
+
}
|
|
15387
15748
|
}
|
|
15388
15749
|
if (selfRecord.settings && typeof selfRecord.settings === "object") {
|
|
15389
15750
|
if (selfRecord.settings.model !== void 0) {
|
|
15390
|
-
patchModel(selfRecord.settings.model);
|
|
15751
|
+
const patchedSettingsModel = patchModel(selfRecord.settings.model);
|
|
15752
|
+
if (typeof selfRecord.settings.model === "string" && patchedSettingsModel && typeof patchedSettingsModel === "object") {
|
|
15753
|
+
selfRecord.settings.model = patchedSettingsModel;
|
|
15754
|
+
}
|
|
15391
15755
|
}
|
|
15392
15756
|
if (selfRecord.settings.tools !== void 0) {
|
|
15393
15757
|
patchTools(selfRecord.settings.tools);
|
|
@@ -15411,63 +15775,173 @@ function finalizeAISDKChildTracing(event) {
|
|
|
15411
15775
|
}
|
|
15412
15776
|
}
|
|
15413
15777
|
function patchAISDKStreamingResult(args) {
|
|
15414
|
-
const {
|
|
15778
|
+
const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
|
|
15415
15779
|
if (!result || typeof result !== "object") {
|
|
15416
15780
|
return false;
|
|
15417
15781
|
}
|
|
15418
15782
|
const resultRecord = result;
|
|
15419
|
-
|
|
15783
|
+
attachKnownResultPromiseHandlers(resultRecord);
|
|
15784
|
+
if (isReadableStreamLike(resultRecord.baseStream)) {
|
|
15785
|
+
let firstChunkTime2;
|
|
15786
|
+
const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
|
|
15787
|
+
new TransformStream({
|
|
15788
|
+
transform(chunk, controller) {
|
|
15789
|
+
if (firstChunkTime2 === void 0) {
|
|
15790
|
+
firstChunkTime2 = getCurrentUnixTimestamp();
|
|
15791
|
+
}
|
|
15792
|
+
controller.enqueue(chunk);
|
|
15793
|
+
},
|
|
15794
|
+
async flush() {
|
|
15795
|
+
const metrics = extractTopLevelAISDKMetrics(result, endEvent);
|
|
15796
|
+
if (metrics.time_to_first_token === void 0 && firstChunkTime2 !== void 0) {
|
|
15797
|
+
metrics.time_to_first_token = firstChunkTime2 - startTime;
|
|
15798
|
+
}
|
|
15799
|
+
const output = await processAISDKStreamingOutput(
|
|
15800
|
+
result,
|
|
15801
|
+
resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
|
|
15802
|
+
);
|
|
15803
|
+
const metadata = buildResolvedMetadataPayload(result).metadata;
|
|
15804
|
+
span.log({
|
|
15805
|
+
output,
|
|
15806
|
+
...metadata ? { metadata } : {},
|
|
15807
|
+
metrics
|
|
15808
|
+
});
|
|
15809
|
+
finalizeAISDKChildTracing(endEvent);
|
|
15810
|
+
span.end();
|
|
15811
|
+
}
|
|
15812
|
+
})
|
|
15813
|
+
);
|
|
15814
|
+
Object.defineProperty(resultRecord, "baseStream", {
|
|
15815
|
+
configurable: true,
|
|
15816
|
+
enumerable: true,
|
|
15817
|
+
value: wrappedBaseStream,
|
|
15818
|
+
writable: true
|
|
15819
|
+
});
|
|
15820
|
+
return true;
|
|
15821
|
+
}
|
|
15822
|
+
const streamField = findAsyncIterableField(resultRecord, [
|
|
15823
|
+
"partialObjectStream",
|
|
15824
|
+
"textStream",
|
|
15825
|
+
"fullStream",
|
|
15826
|
+
"stream"
|
|
15827
|
+
]);
|
|
15828
|
+
if (!streamField) {
|
|
15420
15829
|
return false;
|
|
15421
15830
|
}
|
|
15422
15831
|
let firstChunkTime;
|
|
15423
|
-
const
|
|
15424
|
-
|
|
15425
|
-
|
|
15426
|
-
|
|
15427
|
-
firstChunkTime = getCurrentUnixTimestamp();
|
|
15428
|
-
}
|
|
15429
|
-
controller.enqueue(chunk);
|
|
15430
|
-
},
|
|
15431
|
-
async flush() {
|
|
15432
|
-
const metrics = extractTopLevelAISDKMetrics(result, endEvent);
|
|
15433
|
-
if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
|
|
15434
|
-
metrics.time_to_first_token = firstChunkTime - startTime;
|
|
15435
|
-
}
|
|
15436
|
-
const output = await processAISDKStreamingOutput(
|
|
15437
|
-
result,
|
|
15438
|
-
denyOutputPaths
|
|
15439
|
-
);
|
|
15440
|
-
const metadata = buildResolvedMetadataPayload(result).metadata;
|
|
15441
|
-
span.log({
|
|
15442
|
-
output,
|
|
15443
|
-
...metadata ? { metadata } : {},
|
|
15444
|
-
metrics
|
|
15445
|
-
});
|
|
15446
|
-
finalizeAISDKChildTracing(endEvent);
|
|
15447
|
-
span.end();
|
|
15832
|
+
const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
|
|
15833
|
+
onChunk: () => {
|
|
15834
|
+
if (firstChunkTime === void 0) {
|
|
15835
|
+
firstChunkTime = getCurrentUnixTimestamp();
|
|
15448
15836
|
}
|
|
15449
|
-
}
|
|
15450
|
-
|
|
15451
|
-
|
|
15837
|
+
},
|
|
15838
|
+
onComplete: async () => {
|
|
15839
|
+
const metrics = extractTopLevelAISDKMetrics(result, endEvent);
|
|
15840
|
+
if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
|
|
15841
|
+
metrics.time_to_first_token = firstChunkTime - startTime;
|
|
15842
|
+
}
|
|
15843
|
+
const output = await processAISDKStreamingOutput(
|
|
15844
|
+
result,
|
|
15845
|
+
resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
|
|
15846
|
+
);
|
|
15847
|
+
const metadata = buildResolvedMetadataPayload(result).metadata;
|
|
15848
|
+
span.log({
|
|
15849
|
+
output,
|
|
15850
|
+
...metadata ? { metadata } : {},
|
|
15851
|
+
metrics
|
|
15852
|
+
});
|
|
15853
|
+
finalizeAISDKChildTracing(endEvent);
|
|
15854
|
+
span.end();
|
|
15855
|
+
},
|
|
15856
|
+
onError: (error2) => {
|
|
15857
|
+
span.log({
|
|
15858
|
+
error: error2.message
|
|
15859
|
+
});
|
|
15860
|
+
finalizeAISDKChildTracing(endEvent);
|
|
15861
|
+
span.end();
|
|
15862
|
+
}
|
|
15863
|
+
});
|
|
15864
|
+
Object.defineProperty(resultRecord, streamField.field, {
|
|
15452
15865
|
configurable: true,
|
|
15453
15866
|
enumerable: true,
|
|
15454
|
-
value:
|
|
15867
|
+
value: wrappedStream,
|
|
15455
15868
|
writable: true
|
|
15456
15869
|
});
|
|
15457
15870
|
return true;
|
|
15458
15871
|
}
|
|
15872
|
+
function attachKnownResultPromiseHandlers(result) {
|
|
15873
|
+
const promiseLikeFields = [
|
|
15874
|
+
"content",
|
|
15875
|
+
"text",
|
|
15876
|
+
"object",
|
|
15877
|
+
"finishReason",
|
|
15878
|
+
"usage",
|
|
15879
|
+
"totalUsage",
|
|
15880
|
+
"steps"
|
|
15881
|
+
];
|
|
15882
|
+
for (const field of promiseLikeFields) {
|
|
15883
|
+
try {
|
|
15884
|
+
if (!(field in result)) {
|
|
15885
|
+
continue;
|
|
15886
|
+
}
|
|
15887
|
+
const value = result[field];
|
|
15888
|
+
if (isPromiseLike(value)) {
|
|
15889
|
+
void Promise.resolve(value).catch(() => {
|
|
15890
|
+
});
|
|
15891
|
+
}
|
|
15892
|
+
} catch {
|
|
15893
|
+
}
|
|
15894
|
+
}
|
|
15895
|
+
}
|
|
15459
15896
|
function isReadableStreamLike(value) {
|
|
15460
15897
|
return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
|
|
15461
15898
|
}
|
|
15899
|
+
function isAsyncIterableLike(value) {
|
|
15900
|
+
return value != null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
|
|
15901
|
+
}
|
|
15902
|
+
function findAsyncIterableField(result, candidateFields) {
|
|
15903
|
+
for (const field of candidateFields) {
|
|
15904
|
+
try {
|
|
15905
|
+
const stream = result[field];
|
|
15906
|
+
if (isAsyncIterableLike(stream)) {
|
|
15907
|
+
return { field, stream };
|
|
15908
|
+
}
|
|
15909
|
+
} catch {
|
|
15910
|
+
}
|
|
15911
|
+
}
|
|
15912
|
+
return null;
|
|
15913
|
+
}
|
|
15914
|
+
function createPatchedAsyncIterable(stream, hooks) {
|
|
15915
|
+
return {
|
|
15916
|
+
async *[Symbol.asyncIterator]() {
|
|
15917
|
+
try {
|
|
15918
|
+
for await (const chunk of stream) {
|
|
15919
|
+
hooks.onChunk(chunk);
|
|
15920
|
+
yield chunk;
|
|
15921
|
+
}
|
|
15922
|
+
await hooks.onComplete();
|
|
15923
|
+
} catch (error2) {
|
|
15924
|
+
hooks.onError(
|
|
15925
|
+
error2 instanceof Error ? error2 : new Error(String(error2))
|
|
15926
|
+
);
|
|
15927
|
+
throw error2;
|
|
15928
|
+
}
|
|
15929
|
+
}
|
|
15930
|
+
};
|
|
15931
|
+
}
|
|
15462
15932
|
async function processAISDKStreamingOutput(result, denyOutputPaths) {
|
|
15463
15933
|
const output = processAISDKOutput(result, denyOutputPaths);
|
|
15464
15934
|
if (!output || typeof output !== "object") {
|
|
15465
15935
|
return output;
|
|
15466
15936
|
}
|
|
15467
15937
|
const outputRecord = output;
|
|
15938
|
+
const isObjectStreamingResult = result != null && typeof result === "object" && "partialObjectStream" in result;
|
|
15468
15939
|
try {
|
|
15469
|
-
if ("text" in result
|
|
15470
|
-
|
|
15940
|
+
if (!isObjectStreamingResult && "text" in result) {
|
|
15941
|
+
const resolvedText = await Promise.resolve(result.text);
|
|
15942
|
+
if (typeof resolvedText === "string") {
|
|
15943
|
+
outputRecord.text = resolvedText;
|
|
15944
|
+
}
|
|
15471
15945
|
}
|
|
15472
15946
|
} catch {
|
|
15473
15947
|
}
|
|
@@ -15480,6 +15954,15 @@ async function processAISDKStreamingOutput(result, denyOutputPaths) {
|
|
|
15480
15954
|
}
|
|
15481
15955
|
} catch {
|
|
15482
15956
|
}
|
|
15957
|
+
try {
|
|
15958
|
+
if ("finishReason" in result) {
|
|
15959
|
+
const resolvedFinishReason = await Promise.resolve(result.finishReason);
|
|
15960
|
+
if (resolvedFinishReason !== void 0) {
|
|
15961
|
+
outputRecord.finishReason = resolvedFinishReason;
|
|
15962
|
+
}
|
|
15963
|
+
}
|
|
15964
|
+
} catch {
|
|
15965
|
+
}
|
|
15483
15966
|
return outputRecord;
|
|
15484
15967
|
}
|
|
15485
15968
|
function buildAISDKChildMetadata(model) {
|
|
@@ -15502,16 +15985,25 @@ function buildResolvedMetadataPayload(result) {
|
|
|
15502
15985
|
if (gatewayInfo?.model) {
|
|
15503
15986
|
metadata.model = gatewayInfo.model;
|
|
15504
15987
|
}
|
|
15505
|
-
|
|
15506
|
-
|
|
15988
|
+
let finishReason;
|
|
15989
|
+
try {
|
|
15990
|
+
finishReason = result.finishReason;
|
|
15991
|
+
} catch {
|
|
15992
|
+
finishReason = void 0;
|
|
15993
|
+
}
|
|
15994
|
+
if (isPromiseLike(finishReason)) {
|
|
15995
|
+
void Promise.resolve(finishReason).catch(() => {
|
|
15996
|
+
});
|
|
15997
|
+
} else if (finishReason !== void 0) {
|
|
15998
|
+
metadata.finish_reason = finishReason;
|
|
15507
15999
|
}
|
|
15508
16000
|
return Object.keys(metadata).length > 0 ? { metadata } : {};
|
|
15509
16001
|
}
|
|
15510
|
-
function resolveAISDKModel(model) {
|
|
16002
|
+
function resolveAISDKModel(model, aiSDK) {
|
|
15511
16003
|
if (typeof model !== "string") {
|
|
15512
16004
|
return model;
|
|
15513
16005
|
}
|
|
15514
|
-
const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? null;
|
|
16006
|
+
const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? aiSDK?.gateway ?? null;
|
|
15515
16007
|
if (provider && typeof provider.languageModel === "function") {
|
|
15516
16008
|
return provider.languageModel(model);
|
|
15517
16009
|
}
|
|
@@ -15534,15 +16026,15 @@ function processAISDKOutput(output, denyOutputPaths) {
|
|
|
15534
16026
|
}
|
|
15535
16027
|
function extractTokenMetrics(result) {
|
|
15536
16028
|
const metrics = {};
|
|
15537
|
-
let usage
|
|
15538
|
-
|
|
15539
|
-
|
|
15540
|
-
|
|
15541
|
-
|
|
15542
|
-
|
|
15543
|
-
|
|
15544
|
-
|
|
15545
|
-
|
|
16029
|
+
let usage;
|
|
16030
|
+
const totalUsageValue = safeResultFieldRead(result, "totalUsage");
|
|
16031
|
+
if (totalUsageValue !== void 0 && !isPromiseLike(totalUsageValue)) {
|
|
16032
|
+
usage = totalUsageValue;
|
|
16033
|
+
}
|
|
16034
|
+
if (!usage) {
|
|
16035
|
+
const usageValue = safeResultFieldRead(result, "usage");
|
|
16036
|
+
if (usageValue !== void 0 && !isPromiseLike(usageValue)) {
|
|
16037
|
+
usage = usageValue;
|
|
15546
16038
|
}
|
|
15547
16039
|
}
|
|
15548
16040
|
if (!usage) {
|
|
@@ -15580,6 +16072,22 @@ function extractTokenMetrics(result) {
|
|
|
15580
16072
|
}
|
|
15581
16073
|
return metrics;
|
|
15582
16074
|
}
|
|
16075
|
+
function safeResultFieldRead(result, field) {
|
|
16076
|
+
return safeSerializableFieldRead(result, field);
|
|
16077
|
+
}
|
|
16078
|
+
function safeSerializableFieldRead(obj, field) {
|
|
16079
|
+
try {
|
|
16080
|
+
const value = obj?.[field];
|
|
16081
|
+
if (isPromiseLike(value)) {
|
|
16082
|
+
void Promise.resolve(value).catch(() => {
|
|
16083
|
+
});
|
|
16084
|
+
return void 0;
|
|
16085
|
+
}
|
|
16086
|
+
return value;
|
|
16087
|
+
} catch {
|
|
16088
|
+
return void 0;
|
|
16089
|
+
}
|
|
16090
|
+
}
|
|
15583
16091
|
function aggregateAISDKChunks(chunks, _result, endEvent) {
|
|
15584
16092
|
const lastChunk = chunks[chunks.length - 1];
|
|
15585
16093
|
const output = {};
|
|
@@ -15588,17 +16096,21 @@ function aggregateAISDKChunks(chunks, _result, endEvent) {
|
|
|
15588
16096
|
if (lastChunk) {
|
|
15589
16097
|
metrics = hasModelChildTracing(endEvent) ? {} : extractTokenMetrics(lastChunk);
|
|
15590
16098
|
metadata = buildResolvedMetadataPayload(lastChunk).metadata;
|
|
15591
|
-
|
|
15592
|
-
|
|
16099
|
+
const text = safeSerializableFieldRead(lastChunk, "text");
|
|
16100
|
+
if (text !== void 0) {
|
|
16101
|
+
output.text = text;
|
|
15593
16102
|
}
|
|
15594
|
-
|
|
15595
|
-
|
|
16103
|
+
const objectValue = safeSerializableFieldRead(lastChunk, "object");
|
|
16104
|
+
if (objectValue !== void 0) {
|
|
16105
|
+
output.object = objectValue;
|
|
15596
16106
|
}
|
|
15597
|
-
|
|
15598
|
-
|
|
16107
|
+
const finishReason = safeSerializableFieldRead(lastChunk, "finishReason");
|
|
16108
|
+
if (finishReason !== void 0) {
|
|
16109
|
+
output.finishReason = finishReason;
|
|
15599
16110
|
}
|
|
15600
|
-
|
|
15601
|
-
|
|
16111
|
+
const toolCalls = safeSerializableFieldRead(lastChunk, "toolCalls");
|
|
16112
|
+
if (toolCalls !== void 0) {
|
|
16113
|
+
output.toolCalls = toolCalls;
|
|
15602
16114
|
}
|
|
15603
16115
|
}
|
|
15604
16116
|
finalizeAISDKChildTracing(endEvent);
|
|
@@ -15607,6 +16119,7 @@ function aggregateAISDKChunks(chunks, _result, endEvent) {
|
|
|
15607
16119
|
function extractGetterValues(obj) {
|
|
15608
16120
|
const getterValues = {};
|
|
15609
16121
|
const getterNames = [
|
|
16122
|
+
"content",
|
|
15610
16123
|
"text",
|
|
15611
16124
|
"object",
|
|
15612
16125
|
"finishReason",
|
|
@@ -15622,8 +16135,17 @@ function extractGetterValues(obj) {
|
|
|
15622
16135
|
];
|
|
15623
16136
|
for (const name of getterNames) {
|
|
15624
16137
|
try {
|
|
15625
|
-
if (obj
|
|
15626
|
-
|
|
16138
|
+
if (!obj || !(name in obj)) {
|
|
16139
|
+
continue;
|
|
16140
|
+
}
|
|
16141
|
+
const value = obj[name];
|
|
16142
|
+
if (isPromiseLike(value)) {
|
|
16143
|
+
void Promise.resolve(value).catch(() => {
|
|
16144
|
+
});
|
|
16145
|
+
continue;
|
|
16146
|
+
}
|
|
16147
|
+
if (isSerializableOutputValue(value)) {
|
|
16148
|
+
getterValues[name] = value;
|
|
15627
16149
|
}
|
|
15628
16150
|
} catch {
|
|
15629
16151
|
}
|
|
@@ -15645,6 +16167,11 @@ function extractSerializableOutputFields(output) {
|
|
|
15645
16167
|
for (const name of directFieldNames) {
|
|
15646
16168
|
try {
|
|
15647
16169
|
const value = output?.[name];
|
|
16170
|
+
if (isPromiseLike(value)) {
|
|
16171
|
+
void Promise.resolve(value).catch(() => {
|
|
16172
|
+
});
|
|
16173
|
+
continue;
|
|
16174
|
+
}
|
|
15648
16175
|
if (isSerializableOutputValue(value)) {
|
|
15649
16176
|
serialized[name] = value;
|
|
15650
16177
|
}
|
|
@@ -15656,6 +16183,9 @@ function extractSerializableOutputFields(output) {
|
|
|
15656
16183
|
...extractGetterValues(output)
|
|
15657
16184
|
};
|
|
15658
16185
|
}
|
|
16186
|
+
function isPromiseLike(value) {
|
|
16187
|
+
return value != null && typeof value === "object" && typeof value.then === "function";
|
|
16188
|
+
}
|
|
15659
16189
|
function isSerializableOutputValue(value) {
|
|
15660
16190
|
if (typeof value === "function") {
|
|
15661
16191
|
return false;
|
|
@@ -15697,8 +16227,9 @@ function parseGatewayModelString(modelString) {
|
|
|
15697
16227
|
return { model: modelString };
|
|
15698
16228
|
}
|
|
15699
16229
|
function extractGatewayRoutingInfo(result) {
|
|
15700
|
-
|
|
15701
|
-
|
|
16230
|
+
const steps = safeSerializableFieldRead(result, "steps");
|
|
16231
|
+
if (Array.isArray(steps) && steps.length > 0) {
|
|
16232
|
+
const routing2 = steps[0]?.providerMetadata?.gateway?.routing;
|
|
15702
16233
|
if (routing2) {
|
|
15703
16234
|
return {
|
|
15704
16235
|
provider: routing2.resolvedProvider || routing2.finalProvider,
|
|
@@ -15706,7 +16237,11 @@ function extractGatewayRoutingInfo(result) {
|
|
|
15706
16237
|
};
|
|
15707
16238
|
}
|
|
15708
16239
|
}
|
|
15709
|
-
const
|
|
16240
|
+
const providerMetadata = safeSerializableFieldRead(
|
|
16241
|
+
result,
|
|
16242
|
+
"providerMetadata"
|
|
16243
|
+
);
|
|
16244
|
+
const routing = providerMetadata?.gateway?.routing;
|
|
15710
16245
|
if (routing) {
|
|
15711
16246
|
return {
|
|
15712
16247
|
provider: routing.resolvedProvider || routing.finalProvider,
|
|
@@ -15716,10 +16251,11 @@ function extractGatewayRoutingInfo(result) {
|
|
|
15716
16251
|
return null;
|
|
15717
16252
|
}
|
|
15718
16253
|
function extractCostFromResult(result) {
|
|
15719
|
-
|
|
16254
|
+
const steps = safeSerializableFieldRead(result, "steps");
|
|
16255
|
+
if (Array.isArray(steps) && steps.length > 0) {
|
|
15720
16256
|
let totalCost = 0;
|
|
15721
16257
|
let foundCost = false;
|
|
15722
|
-
for (const step of
|
|
16258
|
+
for (const step of steps) {
|
|
15723
16259
|
const gateway2 = step?.providerMetadata?.gateway;
|
|
15724
16260
|
const stepCost = parseGatewayCost(gateway2?.cost) || parseGatewayCost(gateway2?.marketCost);
|
|
15725
16261
|
if (stepCost !== void 0 && stepCost > 0) {
|
|
@@ -15731,7 +16267,11 @@ function extractCostFromResult(result) {
|
|
|
15731
16267
|
return totalCost;
|
|
15732
16268
|
}
|
|
15733
16269
|
}
|
|
15734
|
-
const
|
|
16270
|
+
const providerMetadata = safeSerializableFieldRead(
|
|
16271
|
+
result,
|
|
16272
|
+
"providerMetadata"
|
|
16273
|
+
);
|
|
16274
|
+
const gateway = providerMetadata?.gateway;
|
|
15735
16275
|
const directCost = parseGatewayCost(gateway?.cost) || parseGatewayCost(gateway?.marketCost);
|
|
15736
16276
|
if (directCost !== void 0 && directCost > 0) {
|
|
15737
16277
|
return directCost;
|
|
@@ -16432,20 +16972,16 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16432
16972
|
);
|
|
16433
16973
|
});
|
|
16434
16974
|
},
|
|
16435
|
-
onComplete: () => {
|
|
16436
|
-
|
|
16437
|
-
|
|
16438
|
-
|
|
16439
|
-
|
|
16440
|
-
|
|
16441
|
-
void state.processing.then(() => {
|
|
16442
|
-
state.span.log({
|
|
16443
|
-
error: error2.message
|
|
16444
|
-
});
|
|
16445
|
-
}).then(() => finalizeQuerySpan(state)).finally(() => {
|
|
16446
|
-
spans.delete(event);
|
|
16975
|
+
onComplete: () => state.processing.then(() => finalizeQuerySpan(state)).finally(() => {
|
|
16976
|
+
spans.delete(event);
|
|
16977
|
+
}),
|
|
16978
|
+
onError: (error2) => state.processing.then(() => {
|
|
16979
|
+
state.span.log({
|
|
16980
|
+
error: error2.message
|
|
16447
16981
|
});
|
|
16448
|
-
}
|
|
16982
|
+
}).then(() => finalizeQuerySpan(state)).finally(() => {
|
|
16983
|
+
spans.delete(event);
|
|
16984
|
+
})
|
|
16449
16985
|
});
|
|
16450
16986
|
return;
|
|
16451
16987
|
}
|
|
@@ -16593,12 +17129,14 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
16593
17129
|
const params = event.arguments[0];
|
|
16594
17130
|
streamEvent.googleGenAIInput = serializeInput(params);
|
|
16595
17131
|
streamEvent.googleGenAIMetadata = extractMetadata(params);
|
|
17132
|
+
streamEvent.googleGenAIStartTime = getCurrentUnixTimestamp();
|
|
16596
17133
|
},
|
|
16597
17134
|
asyncEnd: (event) => {
|
|
16598
17135
|
const streamEvent = event;
|
|
16599
17136
|
patchGoogleGenAIStreamingResult({
|
|
16600
17137
|
input: streamEvent.googleGenAIInput,
|
|
16601
17138
|
metadata: streamEvent.googleGenAIMetadata,
|
|
17139
|
+
startTime: streamEvent.googleGenAIStartTime,
|
|
16602
17140
|
result: streamEvent.result
|
|
16603
17141
|
});
|
|
16604
17142
|
},
|
|
@@ -16651,7 +17189,7 @@ function logErrorAndEndSpan(states, event) {
|
|
|
16651
17189
|
states.delete(event);
|
|
16652
17190
|
}
|
|
16653
17191
|
function patchGoogleGenAIStreamingResult(args) {
|
|
16654
|
-
const { input, metadata, result } = args;
|
|
17192
|
+
const { input, metadata, result, startTime } = args;
|
|
16655
17193
|
if (!input || !metadata || !result || typeof result !== "object" || typeof result.next !== "function") {
|
|
16656
17194
|
return false;
|
|
16657
17195
|
}
|
|
@@ -16659,7 +17197,7 @@ function patchGoogleGenAIStreamingResult(args) {
|
|
|
16659
17197
|
let firstTokenTime = null;
|
|
16660
17198
|
let finalized = false;
|
|
16661
17199
|
let span = null;
|
|
16662
|
-
|
|
17200
|
+
const requestStartTime = startTime ?? getCurrentUnixTimestamp();
|
|
16663
17201
|
const ensureSpan = () => {
|
|
16664
17202
|
if (!span) {
|
|
16665
17203
|
span = startSpan({
|
|
@@ -16672,7 +17210,6 @@ function patchGoogleGenAIStreamingResult(args) {
|
|
|
16672
17210
|
metadata
|
|
16673
17211
|
}
|
|
16674
17212
|
});
|
|
16675
|
-
startTime = getCurrentUnixTimestamp();
|
|
16676
17213
|
}
|
|
16677
17214
|
return span;
|
|
16678
17215
|
};
|
|
@@ -16726,11 +17263,11 @@ function patchGoogleGenAIStreamingResult(args) {
|
|
|
16726
17263
|
}
|
|
16727
17264
|
chunks.push(nextResult.value);
|
|
16728
17265
|
}
|
|
16729
|
-
if (nextResult.done
|
|
17266
|
+
if (nextResult.done) {
|
|
16730
17267
|
finalize({
|
|
16731
17268
|
result: aggregateGenerateContentChunks(
|
|
16732
17269
|
chunks,
|
|
16733
|
-
|
|
17270
|
+
requestStartTime,
|
|
16734
17271
|
firstTokenTime
|
|
16735
17272
|
)
|
|
16736
17273
|
});
|
|
@@ -16750,13 +17287,13 @@ function patchGoogleGenAIStreamingResult(args) {
|
|
|
16750
17287
|
...returnArgs
|
|
16751
17288
|
);
|
|
16752
17289
|
} finally {
|
|
16753
|
-
if (
|
|
17290
|
+
if (chunks.length > 0) {
|
|
16754
17291
|
finalize({
|
|
16755
|
-
result:
|
|
17292
|
+
result: aggregateGenerateContentChunks(
|
|
16756
17293
|
chunks,
|
|
16757
|
-
|
|
17294
|
+
requestStartTime,
|
|
16758
17295
|
firstTokenTime
|
|
16759
|
-
)
|
|
17296
|
+
)
|
|
16760
17297
|
});
|
|
16761
17298
|
} else {
|
|
16762
17299
|
finalize({});
|
|
@@ -17048,13 +17585,236 @@ var openRouterChannels = defineChannels("@openrouter/sdk", {
|
|
|
17048
17585
|
channelName: "callModel",
|
|
17049
17586
|
kind: "sync-stream"
|
|
17050
17587
|
}),
|
|
17588
|
+
callModelTurn: channel({
|
|
17589
|
+
channelName: "callModel.turn",
|
|
17590
|
+
kind: "async"
|
|
17591
|
+
}),
|
|
17051
17592
|
toolExecute: channel({
|
|
17052
17593
|
channelName: "tool.execute",
|
|
17053
17594
|
kind: "async"
|
|
17054
17595
|
})
|
|
17055
17596
|
});
|
|
17056
17597
|
|
|
17057
|
-
// src/openrouter-
|
|
17598
|
+
// src/instrumentation/plugins/openrouter-plugin.ts
|
|
17599
|
+
var OpenRouterPlugin = class extends BasePlugin {
|
|
17600
|
+
onEnable() {
|
|
17601
|
+
this.subscribeToOpenRouterChannels();
|
|
17602
|
+
}
|
|
17603
|
+
onDisable() {
|
|
17604
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
17605
|
+
}
|
|
17606
|
+
subscribeToOpenRouterChannels() {
|
|
17607
|
+
this.unsubscribers.push(
|
|
17608
|
+
traceStreamingChannel(openRouterChannels.chatSend, {
|
|
17609
|
+
name: "openrouter.chat.send",
|
|
17610
|
+
type: "llm" /* LLM */,
|
|
17611
|
+
extractInput: (args) => {
|
|
17612
|
+
const request = getOpenRouterRequestArg(args);
|
|
17613
|
+
const chatGenerationParams = isObject(request?.chatGenerationParams) ? request.chatGenerationParams : {};
|
|
17614
|
+
const httpReferer = request?.httpReferer;
|
|
17615
|
+
const xTitle = request?.xTitle;
|
|
17616
|
+
const { messages, ...metadata } = chatGenerationParams;
|
|
17617
|
+
return {
|
|
17618
|
+
input: messages,
|
|
17619
|
+
metadata: buildOpenRouterMetadata(metadata, httpReferer, xTitle)
|
|
17620
|
+
};
|
|
17621
|
+
},
|
|
17622
|
+
extractOutput: (result) => {
|
|
17623
|
+
return isObject(result) ? result.choices : void 0;
|
|
17624
|
+
},
|
|
17625
|
+
extractMetrics: (result, startTime) => {
|
|
17626
|
+
const metrics = parseOpenRouterMetricsFromUsage(result?.usage);
|
|
17627
|
+
if (startTime) {
|
|
17628
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
17629
|
+
}
|
|
17630
|
+
return metrics;
|
|
17631
|
+
},
|
|
17632
|
+
aggregateChunks: aggregateOpenRouterChatChunks
|
|
17633
|
+
})
|
|
17634
|
+
);
|
|
17635
|
+
this.unsubscribers.push(
|
|
17636
|
+
traceAsyncChannel(openRouterChannels.embeddingsGenerate, {
|
|
17637
|
+
name: "openrouter.embeddings.generate",
|
|
17638
|
+
type: "llm" /* LLM */,
|
|
17639
|
+
extractInput: (args) => {
|
|
17640
|
+
const request = getOpenRouterRequestArg(args);
|
|
17641
|
+
const requestBody = isObject(request?.requestBody) ? request.requestBody : {};
|
|
17642
|
+
const httpReferer = request?.httpReferer;
|
|
17643
|
+
const xTitle = request?.xTitle;
|
|
17644
|
+
const { input, ...metadata } = requestBody;
|
|
17645
|
+
return {
|
|
17646
|
+
input,
|
|
17647
|
+
metadata: buildOpenRouterEmbeddingMetadata(
|
|
17648
|
+
metadata,
|
|
17649
|
+
httpReferer,
|
|
17650
|
+
xTitle
|
|
17651
|
+
)
|
|
17652
|
+
};
|
|
17653
|
+
},
|
|
17654
|
+
extractOutput: (result) => {
|
|
17655
|
+
if (!isObject(result)) {
|
|
17656
|
+
return void 0;
|
|
17657
|
+
}
|
|
17658
|
+
const embedding = result.data?.[0]?.embedding;
|
|
17659
|
+
return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
|
|
17660
|
+
},
|
|
17661
|
+
extractMetadata: (result) => {
|
|
17662
|
+
if (!isObject(result)) {
|
|
17663
|
+
return void 0;
|
|
17664
|
+
}
|
|
17665
|
+
return extractOpenRouterResponseMetadata(result);
|
|
17666
|
+
},
|
|
17667
|
+
extractMetrics: (result) => {
|
|
17668
|
+
return isObject(result) ? parseOpenRouterMetricsFromUsage(result.usage) : {};
|
|
17669
|
+
}
|
|
17670
|
+
})
|
|
17671
|
+
);
|
|
17672
|
+
this.unsubscribers.push(
|
|
17673
|
+
traceStreamingChannel(openRouterChannels.betaResponsesSend, {
|
|
17674
|
+
name: "openrouter.beta.responses.send",
|
|
17675
|
+
type: "llm" /* LLM */,
|
|
17676
|
+
extractInput: (args) => {
|
|
17677
|
+
const request = getOpenRouterRequestArg(args);
|
|
17678
|
+
const openResponsesRequest = isObject(request?.openResponsesRequest) ? request.openResponsesRequest : {};
|
|
17679
|
+
const httpReferer = request?.httpReferer;
|
|
17680
|
+
const xTitle = request?.xTitle;
|
|
17681
|
+
const { input, ...metadata } = openResponsesRequest;
|
|
17682
|
+
return {
|
|
17683
|
+
input,
|
|
17684
|
+
metadata: buildOpenRouterMetadata(metadata, httpReferer, xTitle)
|
|
17685
|
+
};
|
|
17686
|
+
},
|
|
17687
|
+
extractOutput: (result) => extractOpenRouterResponseOutput(result),
|
|
17688
|
+
extractMetadata: (result) => extractOpenRouterResponseMetadata(result),
|
|
17689
|
+
extractMetrics: (result, startTime) => {
|
|
17690
|
+
const metrics = parseOpenRouterMetricsFromUsage(result?.usage);
|
|
17691
|
+
if (startTime) {
|
|
17692
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
17693
|
+
}
|
|
17694
|
+
return metrics;
|
|
17695
|
+
},
|
|
17696
|
+
aggregateChunks: aggregateOpenRouterResponseStreamEvents
|
|
17697
|
+
})
|
|
17698
|
+
);
|
|
17699
|
+
this.unsubscribers.push(
|
|
17700
|
+
traceSyncStreamChannel(openRouterChannels.callModel, {
|
|
17701
|
+
name: "openrouter.callModel",
|
|
17702
|
+
type: "llm" /* LLM */,
|
|
17703
|
+
extractInput: (args) => {
|
|
17704
|
+
const request = getOpenRouterCallModelRequestArg(args);
|
|
17705
|
+
return {
|
|
17706
|
+
input: request ? extractOpenRouterCallModelInput(request) : void 0,
|
|
17707
|
+
metadata: request ? extractOpenRouterCallModelMetadata(request) : { provider: "openrouter" }
|
|
17708
|
+
};
|
|
17709
|
+
},
|
|
17710
|
+
patchResult: ({ endEvent, result, span }) => {
|
|
17711
|
+
return patchOpenRouterCallModelResult({
|
|
17712
|
+
request: getOpenRouterCallModelRequestArg(endEvent.arguments),
|
|
17713
|
+
result,
|
|
17714
|
+
span
|
|
17715
|
+
});
|
|
17716
|
+
}
|
|
17717
|
+
})
|
|
17718
|
+
);
|
|
17719
|
+
this.unsubscribers.push(
|
|
17720
|
+
traceAsyncChannel(openRouterChannels.callModelTurn, {
|
|
17721
|
+
name: "openrouter.beta.responses.send",
|
|
17722
|
+
type: "llm" /* LLM */,
|
|
17723
|
+
extractInput: (args, event) => {
|
|
17724
|
+
const request = getOpenRouterCallModelRequestArg(args);
|
|
17725
|
+
const metadata = request ? extractOpenRouterCallModelMetadata(request) : { provider: "openrouter" };
|
|
17726
|
+
if (isObject(metadata) && "tools" in metadata) {
|
|
17727
|
+
delete metadata.tools;
|
|
17728
|
+
}
|
|
17729
|
+
return {
|
|
17730
|
+
input: request ? extractOpenRouterCallModelInput(request) : void 0,
|
|
17731
|
+
metadata: {
|
|
17732
|
+
...metadata,
|
|
17733
|
+
step: event.step,
|
|
17734
|
+
step_type: event.stepType
|
|
17735
|
+
}
|
|
17736
|
+
};
|
|
17737
|
+
},
|
|
17738
|
+
extractOutput: (result) => extractOpenRouterResponseOutput(result),
|
|
17739
|
+
extractMetadata: (result, event) => {
|
|
17740
|
+
if (!isObject(result)) {
|
|
17741
|
+
return {
|
|
17742
|
+
step: event?.step,
|
|
17743
|
+
step_type: event?.stepType
|
|
17744
|
+
};
|
|
17745
|
+
}
|
|
17746
|
+
return {
|
|
17747
|
+
...extractOpenRouterResponseMetadata(result) || {},
|
|
17748
|
+
...event?.step !== void 0 ? { step: event.step } : {},
|
|
17749
|
+
...event?.stepType ? { step_type: event.stepType } : {}
|
|
17750
|
+
};
|
|
17751
|
+
},
|
|
17752
|
+
extractMetrics: (result) => isObject(result) ? parseOpenRouterMetricsFromUsage(result.usage) : {}
|
|
17753
|
+
})
|
|
17754
|
+
);
|
|
17755
|
+
this.unsubscribers.push(
|
|
17756
|
+
traceStreamingChannel(openRouterChannels.toolExecute, {
|
|
17757
|
+
name: "openrouter.tool",
|
|
17758
|
+
type: "tool" /* TOOL */,
|
|
17759
|
+
extractInput: (args, event) => ({
|
|
17760
|
+
input: args[0],
|
|
17761
|
+
metadata: {
|
|
17762
|
+
provider: "openrouter",
|
|
17763
|
+
tool_name: event.toolName,
|
|
17764
|
+
...event.toolCallId ? { tool_call_id: event.toolCallId } : {}
|
|
17765
|
+
}
|
|
17766
|
+
}),
|
|
17767
|
+
extractOutput: (result) => result,
|
|
17768
|
+
extractMetrics: () => ({}),
|
|
17769
|
+
aggregateChunks: (chunks) => ({
|
|
17770
|
+
output: chunks.length > 0 ? chunks[chunks.length - 1] : void 0,
|
|
17771
|
+
metrics: {}
|
|
17772
|
+
})
|
|
17773
|
+
})
|
|
17774
|
+
);
|
|
17775
|
+
const callModelChannel = openRouterChannels.callModel.tracingChannel();
|
|
17776
|
+
const callModelHandlers = {
|
|
17777
|
+
start: (event) => {
|
|
17778
|
+
const request = getOpenRouterCallModelRequestArg(event.arguments);
|
|
17779
|
+
if (!request) {
|
|
17780
|
+
return;
|
|
17781
|
+
}
|
|
17782
|
+
patchOpenRouterCallModelRequestTools(request);
|
|
17783
|
+
}
|
|
17784
|
+
};
|
|
17785
|
+
callModelChannel.subscribe(callModelHandlers);
|
|
17786
|
+
this.unsubscribers.push(() => {
|
|
17787
|
+
callModelChannel.unsubscribe(callModelHandlers);
|
|
17788
|
+
});
|
|
17789
|
+
}
|
|
17790
|
+
};
|
|
17791
|
+
function normalizeArgs(args) {
|
|
17792
|
+
if (Array.isArray(args)) {
|
|
17793
|
+
return args;
|
|
17794
|
+
}
|
|
17795
|
+
if (isArrayLike2(args)) {
|
|
17796
|
+
return Array.from(args);
|
|
17797
|
+
}
|
|
17798
|
+
return [args];
|
|
17799
|
+
}
|
|
17800
|
+
function isArrayLike2(value) {
|
|
17801
|
+
return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
|
|
17802
|
+
}
|
|
17803
|
+
function getOpenRouterRequestArg(args) {
|
|
17804
|
+
const normalizedArgs = normalizeArgs(args);
|
|
17805
|
+
const keyedCandidate = normalizedArgs.find(
|
|
17806
|
+
(arg) => isObject(arg) && ("chatGenerationParams" in arg || "requestBody" in arg || "openResponsesRequest" in arg)
|
|
17807
|
+
);
|
|
17808
|
+
if (isObject(keyedCandidate)) {
|
|
17809
|
+
return keyedCandidate;
|
|
17810
|
+
}
|
|
17811
|
+
const firstObjectArg = normalizedArgs.find((arg) => isObject(arg));
|
|
17812
|
+
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
17813
|
+
}
|
|
17814
|
+
function getOpenRouterCallModelRequestArg(args) {
|
|
17815
|
+
const firstObjectArg = normalizeArgs(args).find((arg) => isObject(arg));
|
|
17816
|
+
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
17817
|
+
}
|
|
17058
17818
|
var TOKEN_NAME_MAP2 = {
|
|
17059
17819
|
promptTokens: "prompt_tokens",
|
|
17060
17820
|
inputTokens: "prompt_tokens",
|
|
@@ -17120,8 +17880,6 @@ function extractOpenRouterUsageMetadata(usage) {
|
|
|
17120
17880
|
}
|
|
17121
17881
|
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
17122
17882
|
}
|
|
17123
|
-
|
|
17124
|
-
// src/openrouter-logging.ts
|
|
17125
17883
|
var OMITTED_OPENROUTER_KEYS = /* @__PURE__ */ new Set([
|
|
17126
17884
|
"execute",
|
|
17127
17885
|
"render",
|
|
@@ -17141,10 +17899,10 @@ function parseOpenRouterModelString(model) {
|
|
|
17141
17899
|
}
|
|
17142
17900
|
return { model };
|
|
17143
17901
|
}
|
|
17144
|
-
function
|
|
17902
|
+
function isZodSchema3(value) {
|
|
17145
17903
|
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
17146
17904
|
}
|
|
17147
|
-
function
|
|
17905
|
+
function serializeZodSchema3(schema) {
|
|
17148
17906
|
try {
|
|
17149
17907
|
return zodToJsonSchema(schema);
|
|
17150
17908
|
} catch {
|
|
@@ -17178,8 +17936,8 @@ function serializeOpenRouterToolsForLogging(tools) {
|
|
|
17178
17936
|
return tools.map((tool) => serializeOpenRouterTool(tool));
|
|
17179
17937
|
}
|
|
17180
17938
|
function sanitizeOpenRouterLoggedValue(value) {
|
|
17181
|
-
if (
|
|
17182
|
-
return
|
|
17939
|
+
if (isZodSchema3(value)) {
|
|
17940
|
+
return serializeZodSchema3(value);
|
|
17183
17941
|
}
|
|
17184
17942
|
if (typeof value === "function") {
|
|
17185
17943
|
return "[Function]";
|
|
@@ -17262,28 +18020,7 @@ function extractOpenRouterResponseOutput(response, fallbackOutput) {
|
|
|
17262
18020
|
}
|
|
17263
18021
|
return void 0;
|
|
17264
18022
|
}
|
|
17265
|
-
|
|
17266
|
-
// src/openrouter-tool-wrapping.ts
|
|
17267
18023
|
var OPENROUTER_WRAPPED_TOOL = Symbol("braintrust.openrouter.wrappedTool");
|
|
17268
|
-
var OPENROUTER_WRAPPED_CALL_MODEL_RESULT = Symbol(
|
|
17269
|
-
"braintrust.openrouter.wrappedCallModelResult"
|
|
17270
|
-
);
|
|
17271
|
-
var OPENROUTER_CALL_MODEL_STREAM_METHODS = [
|
|
17272
|
-
"getFullResponsesStream",
|
|
17273
|
-
"getItemsStream",
|
|
17274
|
-
"getNewMessagesStream",
|
|
17275
|
-
"getReasoningStream",
|
|
17276
|
-
"getTextStream",
|
|
17277
|
-
"getToolCallsStream",
|
|
17278
|
-
"getToolStream"
|
|
17279
|
-
];
|
|
17280
|
-
var OPENROUTER_CALL_MODEL_CONTEXT_METHODS = [
|
|
17281
|
-
"cancel",
|
|
17282
|
-
"getPendingToolCalls",
|
|
17283
|
-
"getState",
|
|
17284
|
-
"getToolCalls",
|
|
17285
|
-
"requiresApproval"
|
|
17286
|
-
];
|
|
17287
18024
|
function patchOpenRouterCallModelRequestTools(request) {
|
|
17288
18025
|
if (!Array.isArray(request.tools) || request.tools.length === 0) {
|
|
17289
18026
|
return void 0;
|
|
@@ -17301,21 +18038,226 @@ function patchOpenRouterCallModelRequestTools(request) {
|
|
|
17301
18038
|
request.tools = originalTools;
|
|
17302
18039
|
};
|
|
17303
18040
|
}
|
|
17304
|
-
function
|
|
17305
|
-
if (
|
|
17306
|
-
return
|
|
17307
|
-
}
|
|
17308
|
-
const resultLike = result;
|
|
17309
|
-
const hasInstrumentableMethod = typeof resultLike.getResponse === "function" || typeof resultLike.getText === "function" || OPENROUTER_CALL_MODEL_STREAM_METHODS.some(
|
|
17310
|
-
(methodName) => typeof resultLike[methodName] === "function"
|
|
17311
|
-
);
|
|
17312
|
-
if (!hasInstrumentableMethod) {
|
|
17313
|
-
return false;
|
|
18041
|
+
function wrapOpenRouterTool(tool) {
|
|
18042
|
+
if (isWrappedTool(tool) || !tool.function || typeof tool.function !== "object" || typeof tool.function.execute !== "function") {
|
|
18043
|
+
return tool;
|
|
17314
18044
|
}
|
|
17315
|
-
|
|
17316
|
-
|
|
17317
|
-
|
|
17318
|
-
|
|
18045
|
+
const toolName = tool.function.name || "tool";
|
|
18046
|
+
const originalExecute = tool.function.execute;
|
|
18047
|
+
const wrappedTool = {
|
|
18048
|
+
...tool,
|
|
18049
|
+
function: {
|
|
18050
|
+
...tool.function,
|
|
18051
|
+
execute(...args) {
|
|
18052
|
+
return traceToolExecution({
|
|
18053
|
+
args,
|
|
18054
|
+
execute: () => Reflect.apply(originalExecute, this, args),
|
|
18055
|
+
toolCallId: getToolCallId(args[1]),
|
|
18056
|
+
toolName
|
|
18057
|
+
});
|
|
18058
|
+
}
|
|
18059
|
+
}
|
|
18060
|
+
};
|
|
18061
|
+
Object.defineProperty(wrappedTool, OPENROUTER_WRAPPED_TOOL, {
|
|
18062
|
+
value: true,
|
|
18063
|
+
enumerable: false,
|
|
18064
|
+
configurable: false
|
|
18065
|
+
});
|
|
18066
|
+
return wrappedTool;
|
|
18067
|
+
}
|
|
18068
|
+
function isWrappedTool(tool) {
|
|
18069
|
+
return Boolean(tool[OPENROUTER_WRAPPED_TOOL]);
|
|
18070
|
+
}
|
|
18071
|
+
function traceToolExecution(args) {
|
|
18072
|
+
const tracingChannel2 = openRouterChannels.toolExecute.tracingChannel();
|
|
18073
|
+
const input = args.args.length > 0 ? args.args[0] : void 0;
|
|
18074
|
+
const event = {
|
|
18075
|
+
arguments: [input],
|
|
18076
|
+
span_info: {
|
|
18077
|
+
name: args.toolName
|
|
18078
|
+
},
|
|
18079
|
+
toolCallId: args.toolCallId,
|
|
18080
|
+
toolName: args.toolName
|
|
18081
|
+
};
|
|
18082
|
+
tracingChannel2.start.publish(event);
|
|
18083
|
+
try {
|
|
18084
|
+
const result = args.execute();
|
|
18085
|
+
return publishToolResult(tracingChannel2, event, result);
|
|
18086
|
+
} catch (error2) {
|
|
18087
|
+
event.error = normalizeError(error2);
|
|
18088
|
+
tracingChannel2.error.publish(event);
|
|
18089
|
+
throw error2;
|
|
18090
|
+
}
|
|
18091
|
+
}
|
|
18092
|
+
function publishToolResult(tracingChannel2, event, result) {
|
|
18093
|
+
if (isPromiseLike2(result)) {
|
|
18094
|
+
return result.then(
|
|
18095
|
+
(resolved) => {
|
|
18096
|
+
event.result = resolved;
|
|
18097
|
+
tracingChannel2.asyncEnd.publish(event);
|
|
18098
|
+
return resolved;
|
|
18099
|
+
},
|
|
18100
|
+
(error2) => {
|
|
18101
|
+
event.error = normalizeError(error2);
|
|
18102
|
+
tracingChannel2.error.publish(event);
|
|
18103
|
+
throw error2;
|
|
18104
|
+
}
|
|
18105
|
+
);
|
|
18106
|
+
}
|
|
18107
|
+
event.result = result;
|
|
18108
|
+
tracingChannel2.asyncEnd.publish(event);
|
|
18109
|
+
return result;
|
|
18110
|
+
}
|
|
18111
|
+
function getToolCallId(context2) {
|
|
18112
|
+
const toolContext = context2;
|
|
18113
|
+
return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
|
|
18114
|
+
}
|
|
18115
|
+
function isPromiseLike2(value) {
|
|
18116
|
+
return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
|
|
18117
|
+
}
|
|
18118
|
+
function aggregateOpenRouterChatChunks(chunks) {
|
|
18119
|
+
let role;
|
|
18120
|
+
let content = "";
|
|
18121
|
+
let toolCalls;
|
|
18122
|
+
let finishReason;
|
|
18123
|
+
let metrics = {};
|
|
18124
|
+
for (const chunk of chunks) {
|
|
18125
|
+
metrics = {
|
|
18126
|
+
...metrics,
|
|
18127
|
+
...parseOpenRouterMetricsFromUsage(chunk?.usage)
|
|
18128
|
+
};
|
|
18129
|
+
const choice = chunk?.choices?.[0];
|
|
18130
|
+
const delta = choice?.delta;
|
|
18131
|
+
if (!delta) {
|
|
18132
|
+
if (choice?.finish_reason !== void 0) {
|
|
18133
|
+
finishReason = choice.finish_reason;
|
|
18134
|
+
}
|
|
18135
|
+
continue;
|
|
18136
|
+
}
|
|
18137
|
+
if (!role && delta.role) {
|
|
18138
|
+
role = delta.role;
|
|
18139
|
+
}
|
|
18140
|
+
if (typeof delta.content === "string") {
|
|
18141
|
+
content += delta.content;
|
|
18142
|
+
}
|
|
18143
|
+
const choiceFinishReason = choice?.finishReason ?? choice?.finish_reason ?? void 0;
|
|
18144
|
+
const deltaFinishReason = delta.finishReason ?? delta.finish_reason ?? void 0;
|
|
18145
|
+
if (choiceFinishReason !== void 0) {
|
|
18146
|
+
finishReason = choiceFinishReason;
|
|
18147
|
+
} else if (deltaFinishReason !== void 0) {
|
|
18148
|
+
finishReason = deltaFinishReason;
|
|
18149
|
+
}
|
|
18150
|
+
const toolCallDeltas = Array.isArray(delta.toolCalls) ? delta.toolCalls : Array.isArray(delta.tool_calls) ? delta.tool_calls : void 0;
|
|
18151
|
+
if (!toolCallDeltas) {
|
|
18152
|
+
continue;
|
|
18153
|
+
}
|
|
18154
|
+
for (const toolDelta of toolCallDeltas) {
|
|
18155
|
+
if (!toolDelta?.function) {
|
|
18156
|
+
continue;
|
|
18157
|
+
}
|
|
18158
|
+
const toolIndex = toolDelta.index ?? 0;
|
|
18159
|
+
const existingToolCall = toolCalls?.[toolIndex];
|
|
18160
|
+
if (!existingToolCall || toolDelta.id && existingToolCall.id !== void 0 && existingToolCall.id !== toolDelta.id) {
|
|
18161
|
+
const nextToolCalls = [...toolCalls || []];
|
|
18162
|
+
nextToolCalls[toolIndex] = {
|
|
18163
|
+
index: toolIndex,
|
|
18164
|
+
id: toolDelta.id,
|
|
18165
|
+
type: toolDelta.type,
|
|
18166
|
+
function: {
|
|
18167
|
+
name: toolDelta.function.name,
|
|
18168
|
+
arguments: toolDelta.function.arguments || ""
|
|
18169
|
+
}
|
|
18170
|
+
};
|
|
18171
|
+
toolCalls = nextToolCalls;
|
|
18172
|
+
continue;
|
|
18173
|
+
}
|
|
18174
|
+
const current = existingToolCall;
|
|
18175
|
+
if (toolDelta.id && !current.id) {
|
|
18176
|
+
current.id = toolDelta.id;
|
|
18177
|
+
}
|
|
18178
|
+
if (toolDelta.type && !current.type) {
|
|
18179
|
+
current.type = toolDelta.type;
|
|
18180
|
+
}
|
|
18181
|
+
if (toolDelta.function.name && !current.function.name) {
|
|
18182
|
+
current.function.name = toolDelta.function.name;
|
|
18183
|
+
}
|
|
18184
|
+
current.function.arguments += toolDelta.function.arguments || "";
|
|
18185
|
+
}
|
|
18186
|
+
}
|
|
18187
|
+
return {
|
|
18188
|
+
output: [
|
|
18189
|
+
{
|
|
18190
|
+
index: 0,
|
|
18191
|
+
message: {
|
|
18192
|
+
role,
|
|
18193
|
+
content: content || void 0,
|
|
18194
|
+
...toolCalls ? { tool_calls: toolCalls } : {}
|
|
18195
|
+
},
|
|
18196
|
+
logprobs: null,
|
|
18197
|
+
finish_reason: finishReason
|
|
18198
|
+
}
|
|
18199
|
+
],
|
|
18200
|
+
metrics
|
|
18201
|
+
};
|
|
18202
|
+
}
|
|
18203
|
+
function aggregateOpenRouterResponseStreamEvents(chunks) {
|
|
18204
|
+
let finalResponse;
|
|
18205
|
+
for (const chunk of chunks) {
|
|
18206
|
+
const response = chunk?.response;
|
|
18207
|
+
if (!response) {
|
|
18208
|
+
continue;
|
|
18209
|
+
}
|
|
18210
|
+
if (chunk.type === "response.completed" || chunk.type === "response.incomplete" || chunk.type === "response.failed") {
|
|
18211
|
+
finalResponse = response;
|
|
18212
|
+
}
|
|
18213
|
+
}
|
|
18214
|
+
if (!finalResponse) {
|
|
18215
|
+
return {
|
|
18216
|
+
output: void 0,
|
|
18217
|
+
metrics: {}
|
|
18218
|
+
};
|
|
18219
|
+
}
|
|
18220
|
+
return {
|
|
18221
|
+
output: extractOpenRouterResponseOutput(finalResponse),
|
|
18222
|
+
metrics: parseOpenRouterMetricsFromUsage(finalResponse.usage),
|
|
18223
|
+
...extractOpenRouterResponseMetadata(finalResponse) ? { metadata: extractOpenRouterResponseMetadata(finalResponse) } : {}
|
|
18224
|
+
};
|
|
18225
|
+
}
|
|
18226
|
+
var OPENROUTER_WRAPPED_CALL_MODEL_RESULT = Symbol(
|
|
18227
|
+
"braintrust.openrouter.wrappedCallModelResult"
|
|
18228
|
+
);
|
|
18229
|
+
var OPENROUTER_CALL_MODEL_STREAM_METHODS = [
|
|
18230
|
+
"getFullResponsesStream",
|
|
18231
|
+
"getItemsStream",
|
|
18232
|
+
"getNewMessagesStream",
|
|
18233
|
+
"getReasoningStream",
|
|
18234
|
+
"getTextStream",
|
|
18235
|
+
"getToolCallsStream",
|
|
18236
|
+
"getToolStream"
|
|
18237
|
+
];
|
|
18238
|
+
var OPENROUTER_CALL_MODEL_CONTEXT_METHODS = [
|
|
18239
|
+
"cancel",
|
|
18240
|
+
"getPendingToolCalls",
|
|
18241
|
+
"getState",
|
|
18242
|
+
"getToolCalls",
|
|
18243
|
+
"requiresApproval"
|
|
18244
|
+
];
|
|
18245
|
+
function patchOpenRouterCallModelResult(args) {
|
|
18246
|
+
const { request, result, span } = args;
|
|
18247
|
+
if (!isObject(result) || isWrappedCallModelResult(result)) {
|
|
18248
|
+
return false;
|
|
18249
|
+
}
|
|
18250
|
+
const resultLike = result;
|
|
18251
|
+
const hasInstrumentableMethod = typeof resultLike.getResponse === "function" || typeof resultLike.getText === "function" || OPENROUTER_CALL_MODEL_STREAM_METHODS.some(
|
|
18252
|
+
(methodName) => typeof resultLike[methodName] === "function"
|
|
18253
|
+
);
|
|
18254
|
+
if (!hasInstrumentableMethod) {
|
|
18255
|
+
return false;
|
|
18256
|
+
}
|
|
18257
|
+
Object.defineProperty(resultLike, OPENROUTER_WRAPPED_CALL_MODEL_RESULT, {
|
|
18258
|
+
value: true,
|
|
18259
|
+
enumerable: false,
|
|
18260
|
+
configurable: false
|
|
17319
18261
|
});
|
|
17320
18262
|
const originalGetResponse = typeof resultLike.getResponse === "function" ? resultLike.getResponse.bind(resultLike) : void 0;
|
|
17321
18263
|
const originalGetInitialResponse = typeof resultLike.getInitialResponse === "function" ? resultLike.getInitialResponse.bind(resultLike) : void 0;
|
|
@@ -17374,10 +18316,10 @@ function patchOpenRouterCallModelResult(span, result, request) {
|
|
|
17374
18316
|
}
|
|
17375
18317
|
};
|
|
17376
18318
|
if (originalGetResponse) {
|
|
17377
|
-
resultLike.getResponse = async (...
|
|
18319
|
+
resultLike.getResponse = async (...args2) => {
|
|
17378
18320
|
return await withCurrent(span, async () => {
|
|
17379
18321
|
try {
|
|
17380
|
-
const response = await originalGetResponse(...
|
|
18322
|
+
const response = await originalGetResponse(...args2);
|
|
17381
18323
|
await endSpanWithResult(response);
|
|
17382
18324
|
return response;
|
|
17383
18325
|
} catch (error2) {
|
|
@@ -17389,663 +18331,241 @@ function patchOpenRouterCallModelResult(span, result, request) {
|
|
|
17389
18331
|
}
|
|
17390
18332
|
if (typeof resultLike.getText === "function") {
|
|
17391
18333
|
const originalGetText = resultLike.getText.bind(resultLike);
|
|
17392
|
-
resultLike.getText = async (...
|
|
18334
|
+
resultLike.getText = async (...args2) => {
|
|
17393
18335
|
return await withCurrent(span, async () => {
|
|
17394
18336
|
try {
|
|
17395
|
-
const text = await originalGetText(...
|
|
18337
|
+
const text = await originalGetText(...args2);
|
|
17396
18338
|
await finalizeFromResponse(text);
|
|
17397
|
-
return text;
|
|
17398
|
-
} catch (error2) {
|
|
17399
|
-
endSpanWithError(error2);
|
|
17400
|
-
throw error2;
|
|
17401
|
-
}
|
|
17402
|
-
});
|
|
17403
|
-
};
|
|
17404
|
-
}
|
|
17405
|
-
for (const methodName of OPENROUTER_CALL_MODEL_CONTEXT_METHODS) {
|
|
17406
|
-
if (typeof resultLike[methodName] !== "function") {
|
|
17407
|
-
continue;
|
|
17408
|
-
}
|
|
17409
|
-
const originalMethod = resultLike[methodName];
|
|
17410
|
-
resultLike[methodName] = async (...args) => {
|
|
17411
|
-
return await withCurrent(span, async () => {
|
|
17412
|
-
return await originalMethod.apply(resultLike, args);
|
|
17413
|
-
});
|
|
17414
|
-
};
|
|
17415
|
-
}
|
|
17416
|
-
for (const methodName of OPENROUTER_CALL_MODEL_STREAM_METHODS) {
|
|
17417
|
-
if (typeof resultLike[methodName] !== "function") {
|
|
17418
|
-
continue;
|
|
17419
|
-
}
|
|
17420
|
-
const originalMethod = resultLike[methodName];
|
|
17421
|
-
resultLike[methodName] = (...args) => {
|
|
17422
|
-
const stream = withCurrent(
|
|
17423
|
-
span,
|
|
17424
|
-
() => originalMethod.apply(resultLike, args)
|
|
17425
|
-
);
|
|
17426
|
-
if (!isAsyncIterable4(stream)) {
|
|
17427
|
-
return stream;
|
|
17428
|
-
}
|
|
17429
|
-
return wrapAsyncIterableWithSpan({
|
|
17430
|
-
finalize: finalizeFromResponse,
|
|
17431
|
-
iteratorFactory: () => stream[Symbol.asyncIterator](),
|
|
17432
|
-
onError: endSpanWithError,
|
|
17433
|
-
span
|
|
17434
|
-
});
|
|
17435
|
-
};
|
|
17436
|
-
}
|
|
17437
|
-
if (originalGetInitialResponse) {
|
|
17438
|
-
let initialTurnTraced = false;
|
|
17439
|
-
resultLike.getInitialResponse = async (...args) => {
|
|
17440
|
-
if (initialTurnTraced) {
|
|
17441
|
-
return await withCurrent(span, async () => {
|
|
17442
|
-
return await originalGetInitialResponse(...args);
|
|
17443
|
-
});
|
|
17444
|
-
}
|
|
17445
|
-
initialTurnTraced = true;
|
|
17446
|
-
const resolvedRequest = getOpenRouterResolvedRequest(resultLike, request);
|
|
17447
|
-
const childSpan = startOpenRouterCallModelTurnSpan({
|
|
17448
|
-
request: resolvedRequest,
|
|
17449
|
-
step: tracedTurnCount + 1,
|
|
17450
|
-
stepType: tracedTurnCount === 0 ? "initial" : "continue"
|
|
17451
|
-
});
|
|
17452
|
-
return await withCurrent(childSpan, async () => {
|
|
17453
|
-
try {
|
|
17454
|
-
const response = await originalGetInitialResponse(...args);
|
|
17455
|
-
tracedTurnCount++;
|
|
17456
|
-
finishOpenRouterCallModelTurnSpan({
|
|
17457
|
-
response,
|
|
17458
|
-
step: tracedTurnCount,
|
|
17459
|
-
stepType: tracedTurnCount === 1 ? "initial" : "continue",
|
|
17460
|
-
span: childSpan
|
|
17461
|
-
});
|
|
17462
|
-
return response;
|
|
17463
|
-
} catch (error2) {
|
|
17464
|
-
childSpan.log({
|
|
17465
|
-
error: normalizeError(error2).message
|
|
17466
|
-
});
|
|
17467
|
-
childSpan.end();
|
|
17468
|
-
throw error2;
|
|
17469
|
-
}
|
|
17470
|
-
});
|
|
17471
|
-
};
|
|
17472
|
-
}
|
|
17473
|
-
if (originalMakeFollowupRequest) {
|
|
17474
|
-
resultLike.makeFollowupRequest = async (...args) => {
|
|
17475
|
-
const currentResponse = args[0];
|
|
17476
|
-
const toolResults = Array.isArray(args[1]) ? args[1] : [];
|
|
17477
|
-
const resolvedRequest = getOpenRouterResolvedRequest(resultLike, request);
|
|
17478
|
-
const followupRequest = buildOpenRouterFollowupRequest(
|
|
17479
|
-
resolvedRequest,
|
|
17480
|
-
currentResponse,
|
|
17481
|
-
toolResults
|
|
17482
|
-
);
|
|
17483
|
-
const childSpan = startOpenRouterCallModelTurnSpan({
|
|
17484
|
-
request: followupRequest,
|
|
17485
|
-
step: tracedTurnCount + 1,
|
|
17486
|
-
stepType: "continue"
|
|
17487
|
-
});
|
|
17488
|
-
return await withCurrent(childSpan, async () => {
|
|
17489
|
-
try {
|
|
17490
|
-
const response = await originalMakeFollowupRequest(...args);
|
|
17491
|
-
tracedTurnCount++;
|
|
17492
|
-
finishOpenRouterCallModelTurnSpan({
|
|
17493
|
-
response,
|
|
17494
|
-
step: tracedTurnCount,
|
|
17495
|
-
stepType: "continue",
|
|
17496
|
-
span: childSpan
|
|
17497
|
-
});
|
|
17498
|
-
return response;
|
|
17499
|
-
} catch (error2) {
|
|
17500
|
-
childSpan.log({
|
|
17501
|
-
error: normalizeError(error2).message
|
|
17502
|
-
});
|
|
17503
|
-
childSpan.end();
|
|
17504
|
-
throw error2;
|
|
17505
|
-
}
|
|
17506
|
-
});
|
|
17507
|
-
};
|
|
17508
|
-
}
|
|
17509
|
-
return true;
|
|
17510
|
-
}
|
|
17511
|
-
function wrapOpenRouterTool(tool) {
|
|
17512
|
-
if (isWrappedTool(tool) || !tool.function || typeof tool.function !== "object" || typeof tool.function.execute !== "function") {
|
|
17513
|
-
return tool;
|
|
17514
|
-
}
|
|
17515
|
-
const toolName = tool.function.name || "tool";
|
|
17516
|
-
const originalExecute = tool.function.execute;
|
|
17517
|
-
const wrappedTool = {
|
|
17518
|
-
...tool,
|
|
17519
|
-
function: {
|
|
17520
|
-
...tool.function,
|
|
17521
|
-
execute(...args) {
|
|
17522
|
-
return traceToolExecution({
|
|
17523
|
-
args,
|
|
17524
|
-
execute: () => Reflect.apply(originalExecute, this, args),
|
|
17525
|
-
toolCallId: getToolCallId(args[1]),
|
|
17526
|
-
toolName
|
|
17527
|
-
});
|
|
17528
|
-
}
|
|
17529
|
-
}
|
|
17530
|
-
};
|
|
17531
|
-
Object.defineProperty(wrappedTool, OPENROUTER_WRAPPED_TOOL, {
|
|
17532
|
-
value: true,
|
|
17533
|
-
enumerable: false,
|
|
17534
|
-
configurable: false
|
|
17535
|
-
});
|
|
17536
|
-
return wrappedTool;
|
|
17537
|
-
}
|
|
17538
|
-
function isWrappedTool(tool) {
|
|
17539
|
-
return Boolean(tool[OPENROUTER_WRAPPED_TOOL]);
|
|
17540
|
-
}
|
|
17541
|
-
function isWrappedCallModelResult(value) {
|
|
17542
|
-
return Boolean(
|
|
17543
|
-
isObject(value) && value[OPENROUTER_WRAPPED_CALL_MODEL_RESULT]
|
|
17544
|
-
);
|
|
17545
|
-
}
|
|
17546
|
-
function traceToolExecution(args) {
|
|
17547
|
-
const tracingChannel2 = openRouterChannels.toolExecute.tracingChannel();
|
|
17548
|
-
const input = args.args.length > 0 ? args.args[0] : void 0;
|
|
17549
|
-
const event = {
|
|
17550
|
-
arguments: [input],
|
|
17551
|
-
span_info: {
|
|
17552
|
-
name: args.toolName
|
|
17553
|
-
},
|
|
17554
|
-
toolCallId: args.toolCallId,
|
|
17555
|
-
toolName: args.toolName
|
|
17556
|
-
};
|
|
17557
|
-
tracingChannel2.start.publish(event);
|
|
17558
|
-
try {
|
|
17559
|
-
const result = args.execute();
|
|
17560
|
-
return publishToolResult(tracingChannel2, event, result);
|
|
17561
|
-
} catch (error2) {
|
|
17562
|
-
event.error = normalizeError(error2);
|
|
17563
|
-
tracingChannel2.error.publish(event);
|
|
17564
|
-
throw error2;
|
|
17565
|
-
}
|
|
17566
|
-
}
|
|
17567
|
-
function publishToolResult(tracingChannel2, event, result) {
|
|
17568
|
-
if (isPromiseLike(result)) {
|
|
17569
|
-
return result.then(
|
|
17570
|
-
(resolved) => {
|
|
17571
|
-
event.result = resolved;
|
|
17572
|
-
tracingChannel2.asyncEnd.publish(event);
|
|
17573
|
-
return resolved;
|
|
17574
|
-
},
|
|
17575
|
-
(error2) => {
|
|
17576
|
-
event.error = normalizeError(error2);
|
|
17577
|
-
tracingChannel2.error.publish(event);
|
|
17578
|
-
throw error2;
|
|
17579
|
-
}
|
|
17580
|
-
);
|
|
17581
|
-
}
|
|
17582
|
-
event.result = result;
|
|
17583
|
-
tracingChannel2.asyncEnd.publish(event);
|
|
17584
|
-
return result;
|
|
17585
|
-
}
|
|
17586
|
-
function getToolCallId(context2) {
|
|
17587
|
-
const toolContext = context2;
|
|
17588
|
-
return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
|
|
17589
|
-
}
|
|
17590
|
-
function extractOpenRouterCallModelResultMetadata(response, turnCount) {
|
|
17591
|
-
const combined = {
|
|
17592
|
-
...extractOpenRouterResponseMetadata(response) || {},
|
|
17593
|
-
...turnCount !== void 0 ? { turn_count: turnCount } : {}
|
|
17594
|
-
};
|
|
17595
|
-
return Object.keys(combined).length > 0 ? combined : void 0;
|
|
17596
|
-
}
|
|
17597
|
-
function getFinalOpenRouterCallModelResponse(result, response) {
|
|
17598
|
-
if (isObject(response)) {
|
|
17599
|
-
return response;
|
|
17600
|
-
}
|
|
17601
|
-
return isObject(result.finalResponse) ? result.finalResponse : void 0;
|
|
17602
|
-
}
|
|
17603
|
-
function getOpenRouterCallModelRounds(result) {
|
|
17604
|
-
if (!Array.isArray(result.allToolExecutionRounds)) {
|
|
17605
|
-
return [];
|
|
17606
|
-
}
|
|
17607
|
-
return result.allToolExecutionRounds.filter((round) => isObject(round)).map((round) => ({
|
|
17608
|
-
response: isObject(round.response) ? round.response : void 0,
|
|
17609
|
-
round: typeof round.round === "number" ? round.round : void 0,
|
|
17610
|
-
toolResults: Array.isArray(round.toolResults) ? round.toolResults : []
|
|
17611
|
-
})).filter((round) => round.response !== void 0);
|
|
17612
|
-
}
|
|
17613
|
-
function aggregateOpenRouterCallModelMetrics(rounds, finalResponse) {
|
|
17614
|
-
const metrics = {};
|
|
17615
|
-
const responses = [
|
|
17616
|
-
...rounds.map((round) => round.response).filter(isObject),
|
|
17617
|
-
finalResponse
|
|
17618
|
-
];
|
|
17619
|
-
for (const response of responses) {
|
|
17620
|
-
const responseMetrics = parseOpenRouterMetricsFromUsage(response.usage);
|
|
17621
|
-
for (const [name, value] of Object.entries(responseMetrics)) {
|
|
17622
|
-
metrics[name] = (metrics[name] || 0) + value;
|
|
17623
|
-
}
|
|
17624
|
-
}
|
|
17625
|
-
return metrics;
|
|
17626
|
-
}
|
|
17627
|
-
function buildNextOpenRouterCallModelInput(currentInput, response, toolResults) {
|
|
17628
|
-
const normalizedInput = Array.isArray(currentInput) ? [...currentInput] : currentInput === void 0 ? [] : [currentInput];
|
|
17629
|
-
const responseOutput = Array.isArray(response.output) ? response.output : response.output === void 0 ? [] : [response.output];
|
|
17630
|
-
return [...normalizedInput, ...responseOutput, ...toolResults].map(
|
|
17631
|
-
(entry) => sanitizeOpenRouterLoggedValue(entry)
|
|
17632
|
-
);
|
|
17633
|
-
}
|
|
17634
|
-
function startOpenRouterCallModelTurnSpan(args) {
|
|
17635
|
-
const requestRecord = isObject(args.request) ? args.request : void 0;
|
|
17636
|
-
const metadata = requestRecord ? extractOpenRouterCallModelMetadata(requestRecord) : { provider: "openrouter" };
|
|
17637
|
-
if (isObject(metadata) && "tools" in metadata) {
|
|
17638
|
-
delete metadata.tools;
|
|
17639
|
-
}
|
|
17640
|
-
return startSpan({
|
|
17641
|
-
name: "openrouter.beta.responses.send",
|
|
17642
|
-
spanAttributes: {
|
|
17643
|
-
type: "llm" /* LLM */
|
|
17644
|
-
},
|
|
17645
|
-
event: {
|
|
17646
|
-
input: requestRecord ? extractOpenRouterCallModelInput(requestRecord) : void 0,
|
|
17647
|
-
metadata: {
|
|
17648
|
-
...metadata,
|
|
17649
|
-
step: args.step,
|
|
17650
|
-
step_type: args.stepType
|
|
17651
|
-
}
|
|
17652
|
-
}
|
|
17653
|
-
});
|
|
17654
|
-
}
|
|
17655
|
-
function finishOpenRouterCallModelTurnSpan(args) {
|
|
17656
|
-
if (!isObject(args.response)) {
|
|
17657
|
-
args.span.end();
|
|
17658
|
-
return;
|
|
17659
|
-
}
|
|
17660
|
-
args.span.log({
|
|
17661
|
-
output: extractOpenRouterResponseOutput(args.response),
|
|
17662
|
-
...extractOpenRouterResponseMetadata(args.response) ? {
|
|
17663
|
-
metadata: {
|
|
17664
|
-
...extractOpenRouterResponseMetadata(args.response),
|
|
17665
|
-
...args.step !== void 0 ? { step: args.step } : {},
|
|
17666
|
-
...args.stepType ? { step_type: args.stepType } : {}
|
|
17667
|
-
}
|
|
17668
|
-
} : {},
|
|
17669
|
-
metrics: parseOpenRouterMetricsFromUsage(args.response.usage)
|
|
17670
|
-
});
|
|
17671
|
-
args.span.end();
|
|
17672
|
-
}
|
|
17673
|
-
function getOpenRouterResolvedRequest(result, request) {
|
|
17674
|
-
if (isObject(result.resolvedRequest)) {
|
|
17675
|
-
return result.resolvedRequest;
|
|
17676
|
-
}
|
|
17677
|
-
return request;
|
|
17678
|
-
}
|
|
17679
|
-
function buildOpenRouterFollowupRequest(request, currentResponse, toolResults) {
|
|
17680
|
-
if (!request) {
|
|
17681
|
-
return void 0;
|
|
17682
|
-
}
|
|
17683
|
-
return {
|
|
17684
|
-
...request,
|
|
17685
|
-
input: buildNextOpenRouterCallModelInput(
|
|
17686
|
-
extractOpenRouterCallModelInput(request),
|
|
17687
|
-
isObject(currentResponse) ? currentResponse : {},
|
|
17688
|
-
toolResults
|
|
17689
|
-
),
|
|
17690
|
-
stream: false
|
|
17691
|
-
};
|
|
17692
|
-
}
|
|
17693
|
-
function wrapAsyncIterableWithSpan(args) {
|
|
17694
|
-
return {
|
|
17695
|
-
[Symbol.asyncIterator]() {
|
|
17696
|
-
const iterator = args.iteratorFactory();
|
|
17697
|
-
return {
|
|
17698
|
-
next(value) {
|
|
17699
|
-
return withCurrent(
|
|
17700
|
-
args.span,
|
|
17701
|
-
() => value === void 0 ? iterator.next() : iterator.next(value)
|
|
17702
|
-
).then(
|
|
17703
|
-
async (result) => {
|
|
17704
|
-
if (result.done) {
|
|
17705
|
-
await args.finalize();
|
|
17706
|
-
}
|
|
17707
|
-
return result;
|
|
17708
|
-
},
|
|
17709
|
-
(error2) => {
|
|
17710
|
-
args.onError(error2);
|
|
17711
|
-
throw error2;
|
|
17712
|
-
}
|
|
17713
|
-
);
|
|
17714
|
-
},
|
|
17715
|
-
return(value) {
|
|
17716
|
-
if (typeof iterator.return !== "function") {
|
|
17717
|
-
return args.finalize().then(() => ({
|
|
17718
|
-
done: true,
|
|
17719
|
-
value
|
|
17720
|
-
}));
|
|
17721
|
-
}
|
|
17722
|
-
return withCurrent(args.span, () => iterator.return(value)).then(
|
|
17723
|
-
async (result) => {
|
|
17724
|
-
await args.finalize();
|
|
17725
|
-
return result;
|
|
17726
|
-
},
|
|
17727
|
-
(error2) => {
|
|
17728
|
-
args.onError(error2);
|
|
17729
|
-
throw error2;
|
|
17730
|
-
}
|
|
17731
|
-
);
|
|
17732
|
-
},
|
|
17733
|
-
throw(error2) {
|
|
17734
|
-
args.onError(error2);
|
|
17735
|
-
if (typeof iterator.throw !== "function") {
|
|
17736
|
-
return Promise.reject(error2);
|
|
17737
|
-
}
|
|
17738
|
-
return withCurrent(args.span, () => iterator.throw(error2));
|
|
17739
|
-
},
|
|
17740
|
-
[Symbol.asyncIterator]() {
|
|
17741
|
-
return this;
|
|
17742
|
-
}
|
|
17743
|
-
};
|
|
17744
|
-
}
|
|
17745
|
-
};
|
|
17746
|
-
}
|
|
17747
|
-
function isAsyncIterable4(value) {
|
|
17748
|
-
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
17749
|
-
}
|
|
17750
|
-
function isPromiseLike(value) {
|
|
17751
|
-
return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
|
|
17752
|
-
}
|
|
17753
|
-
function normalizeError(error2) {
|
|
17754
|
-
return error2 instanceof Error ? error2 : new Error(String(error2));
|
|
17755
|
-
}
|
|
17756
|
-
|
|
17757
|
-
// src/instrumentation/plugins/openrouter-plugin.ts
|
|
17758
|
-
var OpenRouterPlugin = class extends BasePlugin {
|
|
17759
|
-
onEnable() {
|
|
17760
|
-
this.subscribeToOpenRouterChannels();
|
|
17761
|
-
}
|
|
17762
|
-
onDisable() {
|
|
17763
|
-
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
17764
|
-
}
|
|
17765
|
-
subscribeToOpenRouterChannels() {
|
|
17766
|
-
this.unsubscribers.push(
|
|
17767
|
-
traceStreamingChannel(openRouterChannels.chatSend, {
|
|
17768
|
-
name: "openrouter.chat.send",
|
|
17769
|
-
type: "llm" /* LLM */,
|
|
17770
|
-
extractInput: (args) => {
|
|
17771
|
-
const request = getOpenRouterRequestArg(args);
|
|
17772
|
-
const chatGenerationParams = isObject(request?.chatGenerationParams) ? request.chatGenerationParams : {};
|
|
17773
|
-
const httpReferer = request?.httpReferer;
|
|
17774
|
-
const xTitle = request?.xTitle;
|
|
17775
|
-
const { messages, ...metadata } = chatGenerationParams;
|
|
17776
|
-
return {
|
|
17777
|
-
input: messages,
|
|
17778
|
-
metadata: buildOpenRouterMetadata(metadata, httpReferer, xTitle)
|
|
17779
|
-
};
|
|
17780
|
-
},
|
|
17781
|
-
extractOutput: (result) => {
|
|
17782
|
-
return isObject(result) ? result.choices : void 0;
|
|
17783
|
-
},
|
|
17784
|
-
extractMetrics: (result, startTime) => {
|
|
17785
|
-
const metrics = parseOpenRouterMetricsFromUsage(result?.usage);
|
|
17786
|
-
if (startTime) {
|
|
17787
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
17788
|
-
}
|
|
17789
|
-
return metrics;
|
|
17790
|
-
},
|
|
17791
|
-
aggregateChunks: aggregateOpenRouterChatChunks
|
|
17792
|
-
})
|
|
17793
|
-
);
|
|
17794
|
-
this.unsubscribers.push(
|
|
17795
|
-
traceAsyncChannel(openRouterChannels.embeddingsGenerate, {
|
|
17796
|
-
name: "openrouter.embeddings.generate",
|
|
17797
|
-
type: "llm" /* LLM */,
|
|
17798
|
-
extractInput: (args) => {
|
|
17799
|
-
const request = getOpenRouterRequestArg(args);
|
|
17800
|
-
const requestBody = isObject(request?.requestBody) ? request.requestBody : {};
|
|
17801
|
-
const httpReferer = request?.httpReferer;
|
|
17802
|
-
const xTitle = request?.xTitle;
|
|
17803
|
-
const { input, ...metadata } = requestBody;
|
|
17804
|
-
return {
|
|
17805
|
-
input,
|
|
17806
|
-
metadata: buildOpenRouterEmbeddingMetadata(
|
|
17807
|
-
metadata,
|
|
17808
|
-
httpReferer,
|
|
17809
|
-
xTitle
|
|
17810
|
-
)
|
|
17811
|
-
};
|
|
17812
|
-
},
|
|
17813
|
-
extractOutput: (result) => {
|
|
17814
|
-
if (!isObject(result)) {
|
|
17815
|
-
return void 0;
|
|
17816
|
-
}
|
|
17817
|
-
const embedding = result.data?.[0]?.embedding;
|
|
17818
|
-
return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
|
|
17819
|
-
},
|
|
17820
|
-
extractMetadata: (result) => {
|
|
17821
|
-
if (!isObject(result)) {
|
|
17822
|
-
return void 0;
|
|
17823
|
-
}
|
|
17824
|
-
return extractOpenRouterResponseMetadata(result);
|
|
17825
|
-
},
|
|
17826
|
-
extractMetrics: (result) => {
|
|
17827
|
-
return isObject(result) ? parseOpenRouterMetricsFromUsage(result.usage) : {};
|
|
17828
|
-
}
|
|
17829
|
-
})
|
|
17830
|
-
);
|
|
17831
|
-
this.unsubscribers.push(
|
|
17832
|
-
traceStreamingChannel(openRouterChannels.betaResponsesSend, {
|
|
17833
|
-
name: "openrouter.beta.responses.send",
|
|
17834
|
-
type: "llm" /* LLM */,
|
|
17835
|
-
extractInput: (args) => {
|
|
17836
|
-
const request = getOpenRouterRequestArg(args);
|
|
17837
|
-
const openResponsesRequest = isObject(request?.openResponsesRequest) ? request.openResponsesRequest : {};
|
|
17838
|
-
const httpReferer = request?.httpReferer;
|
|
17839
|
-
const xTitle = request?.xTitle;
|
|
17840
|
-
const { input, ...metadata } = openResponsesRequest;
|
|
17841
|
-
return {
|
|
17842
|
-
input,
|
|
17843
|
-
metadata: buildOpenRouterMetadata(metadata, httpReferer, xTitle)
|
|
17844
|
-
};
|
|
17845
|
-
},
|
|
17846
|
-
extractOutput: (result) => extractOpenRouterResponseOutput(result),
|
|
17847
|
-
extractMetadata: (result) => extractOpenRouterResponseMetadata(result),
|
|
17848
|
-
extractMetrics: (result, startTime) => {
|
|
17849
|
-
const metrics = parseOpenRouterMetricsFromUsage(result?.usage);
|
|
17850
|
-
if (startTime) {
|
|
17851
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
17852
|
-
}
|
|
17853
|
-
return metrics;
|
|
17854
|
-
},
|
|
17855
|
-
aggregateChunks: aggregateOpenRouterResponseStreamEvents
|
|
17856
|
-
})
|
|
17857
|
-
);
|
|
17858
|
-
this.unsubscribers.push(
|
|
17859
|
-
traceSyncStreamChannel(openRouterChannels.callModel, {
|
|
17860
|
-
name: "openrouter.callModel",
|
|
17861
|
-
type: "llm" /* LLM */,
|
|
17862
|
-
extractInput: (args) => {
|
|
17863
|
-
const request = getOpenRouterCallModelRequestArg(args);
|
|
17864
|
-
return {
|
|
17865
|
-
input: request ? extractOpenRouterCallModelInput(request) : void 0,
|
|
17866
|
-
metadata: request ? extractOpenRouterCallModelMetadata(request) : { provider: "openrouter" }
|
|
17867
|
-
};
|
|
17868
|
-
},
|
|
17869
|
-
patchResult: ({ endEvent, result, span }) => {
|
|
17870
|
-
return patchOpenRouterCallModelResult(
|
|
17871
|
-
span,
|
|
17872
|
-
result,
|
|
17873
|
-
getOpenRouterCallModelRequestArg(endEvent.arguments)
|
|
17874
|
-
);
|
|
17875
|
-
}
|
|
17876
|
-
})
|
|
17877
|
-
);
|
|
17878
|
-
this.unsubscribers.push(
|
|
17879
|
-
traceStreamingChannel(openRouterChannels.toolExecute, {
|
|
17880
|
-
name: "openrouter.tool",
|
|
17881
|
-
type: "tool" /* TOOL */,
|
|
17882
|
-
extractInput: (args, event) => ({
|
|
17883
|
-
input: args[0],
|
|
17884
|
-
metadata: {
|
|
17885
|
-
provider: "openrouter",
|
|
17886
|
-
tool_name: event.toolName,
|
|
17887
|
-
...event.toolCallId ? { tool_call_id: event.toolCallId } : {}
|
|
17888
|
-
}
|
|
17889
|
-
}),
|
|
17890
|
-
extractOutput: (result) => result,
|
|
17891
|
-
extractMetrics: () => ({}),
|
|
17892
|
-
aggregateChunks: (chunks) => ({
|
|
17893
|
-
output: chunks.length > 0 ? chunks[chunks.length - 1] : void 0,
|
|
17894
|
-
metrics: {}
|
|
17895
|
-
})
|
|
17896
|
-
})
|
|
17897
|
-
);
|
|
17898
|
-
const callModelChannel = openRouterChannels.callModel.tracingChannel();
|
|
17899
|
-
const callModelHandlers = {
|
|
17900
|
-
start: (event) => {
|
|
17901
|
-
const request = getOpenRouterCallModelRequestArg(event.arguments);
|
|
17902
|
-
if (!request) {
|
|
17903
|
-
return;
|
|
17904
|
-
}
|
|
17905
|
-
patchOpenRouterCallModelRequestTools(request);
|
|
17906
|
-
}
|
|
17907
|
-
};
|
|
17908
|
-
callModelChannel.subscribe(callModelHandlers);
|
|
17909
|
-
this.unsubscribers.push(() => {
|
|
17910
|
-
callModelChannel.unsubscribe(callModelHandlers);
|
|
17911
|
-
});
|
|
17912
|
-
}
|
|
17913
|
-
};
|
|
17914
|
-
function normalizeArgs(args) {
|
|
17915
|
-
if (Array.isArray(args)) {
|
|
17916
|
-
return args;
|
|
17917
|
-
}
|
|
17918
|
-
if (isArrayLike2(args)) {
|
|
17919
|
-
return Array.from(args);
|
|
17920
|
-
}
|
|
17921
|
-
return [args];
|
|
17922
|
-
}
|
|
17923
|
-
function isArrayLike2(value) {
|
|
17924
|
-
return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
|
|
17925
|
-
}
|
|
17926
|
-
function getOpenRouterRequestArg(args) {
|
|
17927
|
-
const normalizedArgs = normalizeArgs(args);
|
|
17928
|
-
const keyedCandidate = normalizedArgs.find(
|
|
17929
|
-
(arg) => isObject(arg) && ("chatGenerationParams" in arg || "requestBody" in arg || "openResponsesRequest" in arg)
|
|
17930
|
-
);
|
|
17931
|
-
if (isObject(keyedCandidate)) {
|
|
17932
|
-
return keyedCandidate;
|
|
17933
|
-
}
|
|
17934
|
-
const firstObjectArg = normalizedArgs.find((arg) => isObject(arg));
|
|
17935
|
-
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
17936
|
-
}
|
|
17937
|
-
function getOpenRouterCallModelRequestArg(args) {
|
|
17938
|
-
const firstObjectArg = normalizeArgs(args).find((arg) => isObject(arg));
|
|
17939
|
-
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
17940
|
-
}
|
|
17941
|
-
function aggregateOpenRouterChatChunks(chunks) {
|
|
17942
|
-
let role;
|
|
17943
|
-
let content = "";
|
|
17944
|
-
let toolCalls;
|
|
17945
|
-
let finishReason;
|
|
17946
|
-
let metrics = {};
|
|
17947
|
-
for (const chunk of chunks) {
|
|
17948
|
-
metrics = {
|
|
17949
|
-
...metrics,
|
|
17950
|
-
...parseOpenRouterMetricsFromUsage(chunk?.usage)
|
|
18339
|
+
return text;
|
|
18340
|
+
} catch (error2) {
|
|
18341
|
+
endSpanWithError(error2);
|
|
18342
|
+
throw error2;
|
|
18343
|
+
}
|
|
18344
|
+
});
|
|
17951
18345
|
};
|
|
17952
|
-
|
|
17953
|
-
|
|
17954
|
-
if (
|
|
17955
|
-
if (choice?.finish_reason !== void 0) {
|
|
17956
|
-
finishReason = choice.finish_reason;
|
|
17957
|
-
}
|
|
18346
|
+
}
|
|
18347
|
+
for (const methodName of OPENROUTER_CALL_MODEL_CONTEXT_METHODS) {
|
|
18348
|
+
if (typeof resultLike[methodName] !== "function") {
|
|
17958
18349
|
continue;
|
|
17959
18350
|
}
|
|
17960
|
-
|
|
17961
|
-
|
|
17962
|
-
|
|
17963
|
-
|
|
17964
|
-
|
|
17965
|
-
}
|
|
17966
|
-
|
|
17967
|
-
|
|
17968
|
-
if (
|
|
17969
|
-
finishReason = choiceFinishReason;
|
|
17970
|
-
} else if (deltaFinishReason !== void 0) {
|
|
17971
|
-
finishReason = deltaFinishReason;
|
|
17972
|
-
}
|
|
17973
|
-
const toolCallDeltas = Array.isArray(delta.toolCalls) ? delta.toolCalls : Array.isArray(delta.tool_calls) ? delta.tool_calls : void 0;
|
|
17974
|
-
if (!toolCallDeltas) {
|
|
18351
|
+
const originalMethod = resultLike[methodName];
|
|
18352
|
+
resultLike[methodName] = async (...args2) => {
|
|
18353
|
+
return await withCurrent(span, async () => {
|
|
18354
|
+
return await originalMethod.apply(resultLike, args2);
|
|
18355
|
+
});
|
|
18356
|
+
};
|
|
18357
|
+
}
|
|
18358
|
+
for (const methodName of OPENROUTER_CALL_MODEL_STREAM_METHODS) {
|
|
18359
|
+
if (typeof resultLike[methodName] !== "function") {
|
|
17975
18360
|
continue;
|
|
17976
18361
|
}
|
|
17977
|
-
|
|
17978
|
-
|
|
17979
|
-
|
|
17980
|
-
|
|
17981
|
-
|
|
17982
|
-
|
|
17983
|
-
if (!
|
|
17984
|
-
|
|
17985
|
-
nextToolCalls[toolIndex] = {
|
|
17986
|
-
index: toolIndex,
|
|
17987
|
-
id: toolDelta.id,
|
|
17988
|
-
type: toolDelta.type,
|
|
17989
|
-
function: {
|
|
17990
|
-
name: toolDelta.function.name,
|
|
17991
|
-
arguments: toolDelta.function.arguments || ""
|
|
17992
|
-
}
|
|
17993
|
-
};
|
|
17994
|
-
toolCalls = nextToolCalls;
|
|
17995
|
-
continue;
|
|
17996
|
-
}
|
|
17997
|
-
const current = existingToolCall;
|
|
17998
|
-
if (toolDelta.id && !current.id) {
|
|
17999
|
-
current.id = toolDelta.id;
|
|
18000
|
-
}
|
|
18001
|
-
if (toolDelta.type && !current.type) {
|
|
18002
|
-
current.type = toolDelta.type;
|
|
18362
|
+
const originalMethod = resultLike[methodName];
|
|
18363
|
+
resultLike[methodName] = (...args2) => {
|
|
18364
|
+
const stream = withCurrent(
|
|
18365
|
+
span,
|
|
18366
|
+
() => originalMethod.apply(resultLike, args2)
|
|
18367
|
+
);
|
|
18368
|
+
if (!isAsyncIterable4(stream)) {
|
|
18369
|
+
return stream;
|
|
18003
18370
|
}
|
|
18004
|
-
|
|
18005
|
-
|
|
18371
|
+
return wrapAsyncIterableWithSpan({
|
|
18372
|
+
finalize: finalizeFromResponse,
|
|
18373
|
+
iteratorFactory: () => stream[Symbol.asyncIterator](),
|
|
18374
|
+
onError: endSpanWithError,
|
|
18375
|
+
span
|
|
18376
|
+
});
|
|
18377
|
+
};
|
|
18378
|
+
}
|
|
18379
|
+
if (originalGetInitialResponse) {
|
|
18380
|
+
let initialTurnTraced = false;
|
|
18381
|
+
resultLike.getInitialResponse = async (...args2) => {
|
|
18382
|
+
if (initialTurnTraced) {
|
|
18383
|
+
return await withCurrent(span, async () => {
|
|
18384
|
+
return await originalGetInitialResponse(...args2);
|
|
18385
|
+
});
|
|
18006
18386
|
}
|
|
18007
|
-
|
|
18008
|
-
|
|
18387
|
+
initialTurnTraced = true;
|
|
18388
|
+
const step = tracedTurnCount + 1;
|
|
18389
|
+
const stepType = tracedTurnCount === 0 ? "initial" : "continue";
|
|
18390
|
+
const response = await traceOpenRouterCallModelTurn({
|
|
18391
|
+
fn: async () => {
|
|
18392
|
+
const nextResponse = await originalGetInitialResponse(...args2);
|
|
18393
|
+
tracedTurnCount++;
|
|
18394
|
+
return nextResponse;
|
|
18395
|
+
},
|
|
18396
|
+
parentSpan: span,
|
|
18397
|
+
request: getOpenRouterResolvedRequest(resultLike, request),
|
|
18398
|
+
step,
|
|
18399
|
+
stepType
|
|
18400
|
+
});
|
|
18401
|
+
return response;
|
|
18402
|
+
};
|
|
18009
18403
|
}
|
|
18010
|
-
|
|
18011
|
-
|
|
18012
|
-
|
|
18013
|
-
|
|
18014
|
-
|
|
18015
|
-
|
|
18016
|
-
|
|
18017
|
-
|
|
18404
|
+
if (originalMakeFollowupRequest) {
|
|
18405
|
+
resultLike.makeFollowupRequest = async (...args2) => {
|
|
18406
|
+
const currentResponse = args2[0];
|
|
18407
|
+
const toolResults = Array.isArray(args2[1]) ? args2[1] : [];
|
|
18408
|
+
const step = tracedTurnCount + 1;
|
|
18409
|
+
const response = await traceOpenRouterCallModelTurn({
|
|
18410
|
+
fn: async () => {
|
|
18411
|
+
const nextResponse = await originalMakeFollowupRequest(...args2);
|
|
18412
|
+
tracedTurnCount++;
|
|
18413
|
+
return nextResponse;
|
|
18018
18414
|
},
|
|
18019
|
-
|
|
18020
|
-
|
|
18021
|
-
|
|
18022
|
-
|
|
18023
|
-
|
|
18415
|
+
parentSpan: span,
|
|
18416
|
+
request: buildOpenRouterFollowupRequest(
|
|
18417
|
+
getOpenRouterResolvedRequest(resultLike, request),
|
|
18418
|
+
currentResponse,
|
|
18419
|
+
toolResults
|
|
18420
|
+
),
|
|
18421
|
+
step,
|
|
18422
|
+
stepType: "continue"
|
|
18423
|
+
});
|
|
18424
|
+
return response;
|
|
18425
|
+
};
|
|
18426
|
+
}
|
|
18427
|
+
return true;
|
|
18428
|
+
}
|
|
18429
|
+
async function traceOpenRouterCallModelTurn(args) {
|
|
18430
|
+
const context2 = {
|
|
18431
|
+
arguments: [args.request],
|
|
18432
|
+
step: args.step,
|
|
18433
|
+
stepType: args.stepType
|
|
18024
18434
|
};
|
|
18435
|
+
return await withCurrent(
|
|
18436
|
+
args.parentSpan,
|
|
18437
|
+
() => openRouterChannels.callModelTurn.tracePromise(args.fn, context2)
|
|
18438
|
+
);
|
|
18025
18439
|
}
|
|
18026
|
-
function
|
|
18027
|
-
|
|
18028
|
-
|
|
18029
|
-
|
|
18030
|
-
|
|
18031
|
-
|
|
18032
|
-
|
|
18033
|
-
|
|
18034
|
-
|
|
18440
|
+
function isWrappedCallModelResult(value) {
|
|
18441
|
+
return Boolean(
|
|
18442
|
+
isObject(value) && value[OPENROUTER_WRAPPED_CALL_MODEL_RESULT]
|
|
18443
|
+
);
|
|
18444
|
+
}
|
|
18445
|
+
function extractOpenRouterCallModelResultMetadata(response, turnCount) {
|
|
18446
|
+
const combined = {
|
|
18447
|
+
...extractOpenRouterResponseMetadata(response) || {},
|
|
18448
|
+
...turnCount !== void 0 ? { turn_count: turnCount } : {}
|
|
18449
|
+
};
|
|
18450
|
+
return Object.keys(combined).length > 0 ? combined : void 0;
|
|
18451
|
+
}
|
|
18452
|
+
function getFinalOpenRouterCallModelResponse(result, response) {
|
|
18453
|
+
if (isObject(response)) {
|
|
18454
|
+
return response;
|
|
18455
|
+
}
|
|
18456
|
+
return isObject(result.finalResponse) ? result.finalResponse : void 0;
|
|
18457
|
+
}
|
|
18458
|
+
function getOpenRouterCallModelRounds(result) {
|
|
18459
|
+
if (!Array.isArray(result.allToolExecutionRounds)) {
|
|
18460
|
+
return [];
|
|
18461
|
+
}
|
|
18462
|
+
return result.allToolExecutionRounds.filter((round) => isObject(round)).map((round) => ({
|
|
18463
|
+
response: isObject(round.response) ? round.response : void 0,
|
|
18464
|
+
round: typeof round.round === "number" ? round.round : void 0,
|
|
18465
|
+
toolResults: Array.isArray(round.toolResults) ? round.toolResults : []
|
|
18466
|
+
})).filter((round) => round.response !== void 0);
|
|
18467
|
+
}
|
|
18468
|
+
function aggregateOpenRouterCallModelMetrics(rounds, finalResponse) {
|
|
18469
|
+
const metrics = {};
|
|
18470
|
+
const responses = [
|
|
18471
|
+
...rounds.map((round) => round.response).filter(isObject),
|
|
18472
|
+
finalResponse
|
|
18473
|
+
];
|
|
18474
|
+
for (const response of responses) {
|
|
18475
|
+
const responseMetrics = parseOpenRouterMetricsFromUsage(response.usage);
|
|
18476
|
+
for (const [name, value] of Object.entries(responseMetrics)) {
|
|
18477
|
+
metrics[name] = (metrics[name] || 0) + value;
|
|
18035
18478
|
}
|
|
18036
18479
|
}
|
|
18037
|
-
|
|
18038
|
-
|
|
18039
|
-
|
|
18040
|
-
|
|
18041
|
-
|
|
18480
|
+
return metrics;
|
|
18481
|
+
}
|
|
18482
|
+
function buildNextOpenRouterCallModelInput(currentInput, response, toolResults) {
|
|
18483
|
+
const normalizedInput = Array.isArray(currentInput) ? [...currentInput] : currentInput === void 0 ? [] : [currentInput];
|
|
18484
|
+
const responseOutput = Array.isArray(response.output) ? response.output : response.output === void 0 ? [] : [response.output];
|
|
18485
|
+
return [...normalizedInput, ...responseOutput, ...toolResults].map(
|
|
18486
|
+
(entry) => sanitizeOpenRouterLoggedValue(entry)
|
|
18487
|
+
);
|
|
18488
|
+
}
|
|
18489
|
+
function getOpenRouterResolvedRequest(result, request) {
|
|
18490
|
+
if (isObject(result.resolvedRequest)) {
|
|
18491
|
+
return result.resolvedRequest;
|
|
18492
|
+
}
|
|
18493
|
+
return request;
|
|
18494
|
+
}
|
|
18495
|
+
function buildOpenRouterFollowupRequest(request, currentResponse, toolResults) {
|
|
18496
|
+
if (!request) {
|
|
18497
|
+
return void 0;
|
|
18042
18498
|
}
|
|
18043
18499
|
return {
|
|
18044
|
-
|
|
18045
|
-
|
|
18046
|
-
|
|
18500
|
+
...request,
|
|
18501
|
+
input: buildNextOpenRouterCallModelInput(
|
|
18502
|
+
extractOpenRouterCallModelInput(request),
|
|
18503
|
+
isObject(currentResponse) ? currentResponse : {},
|
|
18504
|
+
toolResults
|
|
18505
|
+
),
|
|
18506
|
+
stream: false
|
|
18507
|
+
};
|
|
18508
|
+
}
|
|
18509
|
+
function wrapAsyncIterableWithSpan(args) {
|
|
18510
|
+
return {
|
|
18511
|
+
[Symbol.asyncIterator]() {
|
|
18512
|
+
const iterator = args.iteratorFactory();
|
|
18513
|
+
return {
|
|
18514
|
+
next(value) {
|
|
18515
|
+
return withCurrent(
|
|
18516
|
+
args.span,
|
|
18517
|
+
() => value === void 0 ? iterator.next() : iterator.next(value)
|
|
18518
|
+
).then(
|
|
18519
|
+
async (result) => {
|
|
18520
|
+
if (result.done) {
|
|
18521
|
+
await args.finalize();
|
|
18522
|
+
}
|
|
18523
|
+
return result;
|
|
18524
|
+
},
|
|
18525
|
+
(error2) => {
|
|
18526
|
+
args.onError(error2);
|
|
18527
|
+
throw error2;
|
|
18528
|
+
}
|
|
18529
|
+
);
|
|
18530
|
+
},
|
|
18531
|
+
return(value) {
|
|
18532
|
+
if (typeof iterator.return !== "function") {
|
|
18533
|
+
return args.finalize().then(() => ({
|
|
18534
|
+
done: true,
|
|
18535
|
+
value
|
|
18536
|
+
}));
|
|
18537
|
+
}
|
|
18538
|
+
return withCurrent(args.span, () => iterator.return(value)).then(
|
|
18539
|
+
async (result) => {
|
|
18540
|
+
await args.finalize();
|
|
18541
|
+
return result;
|
|
18542
|
+
},
|
|
18543
|
+
(error2) => {
|
|
18544
|
+
args.onError(error2);
|
|
18545
|
+
throw error2;
|
|
18546
|
+
}
|
|
18547
|
+
);
|
|
18548
|
+
},
|
|
18549
|
+
throw(error2) {
|
|
18550
|
+
args.onError(error2);
|
|
18551
|
+
if (typeof iterator.throw !== "function") {
|
|
18552
|
+
return Promise.reject(error2);
|
|
18553
|
+
}
|
|
18554
|
+
return withCurrent(args.span, () => iterator.throw(error2));
|
|
18555
|
+
},
|
|
18556
|
+
[Symbol.asyncIterator]() {
|
|
18557
|
+
return this;
|
|
18558
|
+
}
|
|
18559
|
+
};
|
|
18560
|
+
}
|
|
18047
18561
|
};
|
|
18048
18562
|
}
|
|
18563
|
+
function isAsyncIterable4(value) {
|
|
18564
|
+
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
18565
|
+
}
|
|
18566
|
+
function normalizeError(error2) {
|
|
18567
|
+
return error2 instanceof Error ? error2 : new Error(String(error2));
|
|
18568
|
+
}
|
|
18049
18569
|
|
|
18050
18570
|
// src/instrumentation/braintrust-plugin.ts
|
|
18051
18571
|
var BraintrustPlugin = class extends BasePlugin {
|
|
@@ -18654,7 +19174,8 @@ var ScorerBuilder = class {
|
|
|
18654
19174
|
type: "llm_classifier",
|
|
18655
19175
|
use_cot: opts.useCot,
|
|
18656
19176
|
choice_scores: opts.choiceScores
|
|
18657
|
-
}
|
|
19177
|
+
},
|
|
19178
|
+
...opts.templateFormat ? { template_format: opts.templateFormat } : {}
|
|
18658
19179
|
};
|
|
18659
19180
|
const codePrompt = new CodePrompt(
|
|
18660
19181
|
this.project,
|