braintrust 3.26.0 → 3.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dev/dist/index.js +2440 -1067
- package/dev/dist/index.mjs +1644 -271
- package/dist/apply-auto-instrumentation.js +320 -261
- package/dist/apply-auto-instrumentation.mjs +118 -59
- package/dist/auto-instrumentations/bundler/esbuild.cjs +377 -59
- package/dist/auto-instrumentations/bundler/esbuild.mjs +5 -4
- package/dist/auto-instrumentations/bundler/next.cjs +379 -61
- package/dist/auto-instrumentations/bundler/next.mjs +6 -5
- package/dist/auto-instrumentations/bundler/rollup.cjs +377 -59
- package/dist/auto-instrumentations/bundler/rollup.mjs +5 -4
- package/dist/auto-instrumentations/bundler/vite.cjs +406 -60
- package/dist/auto-instrumentations/bundler/vite.mjs +34 -5
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +363 -59
- package/dist/auto-instrumentations/bundler/webpack.cjs +377 -59
- package/dist/auto-instrumentations/bundler/webpack.mjs +6 -5
- package/dist/auto-instrumentations/{chunk-AKKPLXTP.mjs → chunk-2AMDGD65.mjs} +160 -57
- package/dist/auto-instrumentations/{chunk-V5LEODRX.mjs → chunk-BW33ULMW.mjs} +1 -1
- package/dist/auto-instrumentations/{chunk-XYN63IG5.mjs → chunk-I55G56ZL.mjs} +21 -58
- package/dist/auto-instrumentations/{chunk-NRE4QUQR.mjs → chunk-JPUFNW7X.mjs} +140 -0
- package/dist/auto-instrumentations/{chunk-6E22MYSW.mjs → chunk-XEYKUBLY.mjs} +30 -4
- package/dist/auto-instrumentations/{chunk-XZHHE4Y3.mjs → chunk-ZNHTSSGI.mjs} +155 -2
- package/dist/auto-instrumentations/hook.mjs +161 -3
- package/dist/auto-instrumentations/index.cjs +296 -1
- package/dist/auto-instrumentations/index.d.mts +5 -1
- package/dist/auto-instrumentations/index.d.ts +5 -1
- package/dist/auto-instrumentations/index.mjs +6 -2
- package/dist/auto-instrumentations/loader/cjs-patch.cjs +105 -57
- package/dist/auto-instrumentations/loader/cjs-patch.mjs +2 -2
- package/dist/auto-instrumentations/loader/esm-hook.mjs +1 -1
- package/dist/browser.d.mts +57 -5
- package/dist/browser.d.ts +57 -5
- package/dist/browser.js +1855 -285
- package/dist/browser.mjs +1855 -285
- package/dist/{chunk-PN7EWK66.mjs → chunk-CZM5JIQL.mjs} +209 -1
- package/dist/{chunk-VYNNEKSA.js → chunk-MF7NU6BT.js} +216 -8
- package/dist/{chunk-VRZZQPAA.js → chunk-QRHGVBKU.js} +2403 -1220
- package/dist/{chunk-XIZOM2HO.mjs → chunk-YKD22IMR.mjs} +1454 -271
- package/dist/cli.js +1645 -272
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +1855 -285
- package/dist/edge-light.mjs +1855 -285
- package/dist/index.d.mts +57 -5
- package/dist/index.d.ts +57 -5
- package/dist/index.js +600 -413
- package/dist/index.mjs +201 -14
- package/dist/instrumentation/index.d.mts +8 -0
- package/dist/instrumentation/index.d.ts +8 -0
- package/dist/instrumentation/index.js +1839 -466
- package/dist/instrumentation/index.mjs +1839 -466
- package/dist/vitest-evals-reporter.js +45 -43
- package/dist/vitest-evals-reporter.mjs +5 -3
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +1855 -285
- package/dist/workerd.mjs +1855 -285
- package/package.json +1 -1
package/dev/dist/index.mjs
CHANGED
|
@@ -14,8 +14,10 @@ var GLOBAL_INSTRUMENTATION_HOOKS_KEY = "__braintrust_instrumentation_hooks";
|
|
|
14
14
|
var GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION = 1;
|
|
15
15
|
var GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND = "braintrust.global-instrumentation-hooks.registry";
|
|
16
16
|
var GLOBAL_INSTRUMENTATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.hook";
|
|
17
|
+
var GLOBAL_INVOCATION_HOOK_BRAND = "braintrust.global-instrumentation-hooks.invocation-hook";
|
|
17
18
|
var registryBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOKS_REGISTRY_BRAND);
|
|
18
19
|
var hookBrand = Symbol.for(GLOBAL_INSTRUMENTATION_HOOK_BRAND);
|
|
20
|
+
var invocationHookBrand = Symbol.for(GLOBAL_INVOCATION_HOOK_BRAND);
|
|
19
21
|
var errorReporter;
|
|
20
22
|
function setGlobalHookErrorReporter(reporter) {
|
|
21
23
|
const previousReporter = errorReporter;
|
|
@@ -160,12 +162,69 @@ var traceEvents = [
|
|
|
160
162
|
"asyncEnd",
|
|
161
163
|
"error"
|
|
162
164
|
];
|
|
165
|
+
function traceInvocation(hook, operator, target, thisArg, args, additional, callbackIndex = -1) {
|
|
166
|
+
const context = {
|
|
167
|
+
...additional,
|
|
168
|
+
arguments: args,
|
|
169
|
+
self: thisArg
|
|
170
|
+
};
|
|
171
|
+
const invoke2 = () => hook.invoke(target, thisArg, args, additional);
|
|
172
|
+
if (operator === "traceCallback") {
|
|
173
|
+
return hook.traceCallback(invoke2, callbackIndex, context);
|
|
174
|
+
}
|
|
175
|
+
if (operator === "tracePromise") {
|
|
176
|
+
return hook.tracePromise(invoke2, context);
|
|
177
|
+
}
|
|
178
|
+
return hook.traceSync(invoke2, context);
|
|
179
|
+
}
|
|
180
|
+
var InvocationHook = class {
|
|
181
|
+
interceptors = [];
|
|
182
|
+
get hasInterceptors() {
|
|
183
|
+
return this.interceptors.length > 0;
|
|
184
|
+
}
|
|
185
|
+
intercept(interceptor) {
|
|
186
|
+
if (typeof interceptor !== "function") {
|
|
187
|
+
throw new TypeError("interceptor must be a function");
|
|
188
|
+
}
|
|
189
|
+
this.interceptors = [...this.interceptors, interceptor];
|
|
190
|
+
let active = true;
|
|
191
|
+
return () => {
|
|
192
|
+
if (!active) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
active = false;
|
|
196
|
+
const index = this.interceptors.indexOf(interceptor);
|
|
197
|
+
if (index !== -1) {
|
|
198
|
+
this.interceptors = [
|
|
199
|
+
...this.interceptors.slice(0, index),
|
|
200
|
+
...this.interceptors.slice(index + 1)
|
|
201
|
+
];
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
invoke(target, thisArg, args, additional) {
|
|
206
|
+
const interceptors = this.interceptors;
|
|
207
|
+
if (interceptors.length === 0) {
|
|
208
|
+
return Reflect.apply(target, thisArg, args);
|
|
209
|
+
}
|
|
210
|
+
let next = target;
|
|
211
|
+
for (let index = interceptors.length - 1; index >= 0; index -= 1) {
|
|
212
|
+
const interceptor = interceptors[index];
|
|
213
|
+
const downstream = next;
|
|
214
|
+
next = function(...nextArgs) {
|
|
215
|
+
return interceptor(downstream, this, nextArgs, additional);
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
return Reflect.apply(next, thisArg, args);
|
|
219
|
+
}
|
|
220
|
+
};
|
|
163
221
|
var TracingHook = class {
|
|
164
222
|
start;
|
|
165
223
|
end;
|
|
166
224
|
asyncStart;
|
|
167
225
|
asyncEnd;
|
|
168
226
|
error;
|
|
227
|
+
invocationHook = new InvocationHook();
|
|
169
228
|
constructor(nameOrChannels) {
|
|
170
229
|
Object.defineProperty(this, hookBrand, {
|
|
171
230
|
configurable: false,
|
|
@@ -173,6 +232,12 @@ var TracingHook = class {
|
|
|
173
232
|
value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
|
|
174
233
|
writable: false
|
|
175
234
|
});
|
|
235
|
+
Object.defineProperty(this, invocationHookBrand, {
|
|
236
|
+
configurable: false,
|
|
237
|
+
enumerable: false,
|
|
238
|
+
value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
|
|
239
|
+
writable: false
|
|
240
|
+
});
|
|
176
241
|
if (typeof nameOrChannels === "string") {
|
|
177
242
|
this.start = new HookChannel(`tracing:${nameOrChannels}:start`);
|
|
178
243
|
this.end = new HookChannel(`tracing:${nameOrChannels}:end`);
|
|
@@ -190,6 +255,26 @@ var TracingHook = class {
|
|
|
190
255
|
get hasSubscribers() {
|
|
191
256
|
return this.start.hasSubscribers || this.end.hasSubscribers || this.asyncStart.hasSubscribers || this.asyncEnd.hasSubscribers || this.error.hasSubscribers;
|
|
192
257
|
}
|
|
258
|
+
get hasInterceptors() {
|
|
259
|
+
return this.invocationHook.hasInterceptors;
|
|
260
|
+
}
|
|
261
|
+
intercept(interceptor) {
|
|
262
|
+
return this.invocationHook.intercept(interceptor);
|
|
263
|
+
}
|
|
264
|
+
invoke(target, thisArg, args, additional) {
|
|
265
|
+
return this.invocationHook.invoke(target, thisArg, args, additional);
|
|
266
|
+
}
|
|
267
|
+
traceInvocation(operator, target, thisArg, args, additional, callbackIndex = -1) {
|
|
268
|
+
return traceInvocation(
|
|
269
|
+
this,
|
|
270
|
+
operator,
|
|
271
|
+
target,
|
|
272
|
+
thisArg,
|
|
273
|
+
args,
|
|
274
|
+
additional,
|
|
275
|
+
callbackIndex
|
|
276
|
+
);
|
|
277
|
+
}
|
|
193
278
|
subscribe(handlers) {
|
|
194
279
|
for (const eventName of traceEvents) {
|
|
195
280
|
const handler = handlers[eventName];
|
|
@@ -411,6 +496,60 @@ function hasTracingHookShape(value) {
|
|
|
411
496
|
return false;
|
|
412
497
|
}
|
|
413
498
|
}
|
|
499
|
+
function hasInvocationHookShape(value) {
|
|
500
|
+
if (typeof value !== "object" && typeof value !== "function" || value === null) {
|
|
501
|
+
return false;
|
|
502
|
+
}
|
|
503
|
+
try {
|
|
504
|
+
const hook = value;
|
|
505
|
+
return value[invocationHookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && typeof hook.hasInterceptors === "boolean" && typeof hook.intercept === "function" && typeof hook.invoke === "function";
|
|
506
|
+
} catch {
|
|
507
|
+
return false;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
function installInvocationHook(value) {
|
|
511
|
+
const hasInvocationHook = hasInvocationHookShape(value);
|
|
512
|
+
const invocationHook = new InvocationHook();
|
|
513
|
+
try {
|
|
514
|
+
if (!hasInvocationHook) {
|
|
515
|
+
Object.defineProperties(value, {
|
|
516
|
+
[invocationHookBrand]: {
|
|
517
|
+
configurable: false,
|
|
518
|
+
enumerable: false,
|
|
519
|
+
value: GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION,
|
|
520
|
+
writable: false
|
|
521
|
+
},
|
|
522
|
+
hasInterceptors: {
|
|
523
|
+
configurable: false,
|
|
524
|
+
enumerable: false,
|
|
525
|
+
get: () => invocationHook.hasInterceptors
|
|
526
|
+
},
|
|
527
|
+
intercept: {
|
|
528
|
+
configurable: false,
|
|
529
|
+
enumerable: false,
|
|
530
|
+
value: invocationHook.intercept.bind(invocationHook),
|
|
531
|
+
writable: false
|
|
532
|
+
},
|
|
533
|
+
invoke: {
|
|
534
|
+
configurable: false,
|
|
535
|
+
enumerable: false,
|
|
536
|
+
value: invocationHook.invoke.bind(invocationHook),
|
|
537
|
+
writable: false
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
if (typeof value.traceInvocation !== "function") {
|
|
542
|
+
Object.defineProperty(value, "traceInvocation", {
|
|
543
|
+
configurable: false,
|
|
544
|
+
enumerable: false,
|
|
545
|
+
value: traceInvocation.bind(void 0, value),
|
|
546
|
+
writable: false
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
} catch (error) {
|
|
550
|
+
reportError(error);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
414
553
|
function isCompatibleTracingHook(value) {
|
|
415
554
|
try {
|
|
416
555
|
return value[hookBrand] === GLOBAL_INSTRUMENTATION_HOOKS_PROTOCOL_VERSION && hasTracingHookShape(value);
|
|
@@ -497,6 +636,7 @@ function newGlobalTracingChannel(nameOrChannels) {
|
|
|
497
636
|
return inertTracingHook;
|
|
498
637
|
}
|
|
499
638
|
if (isCompatibleTracingHook(existing)) {
|
|
639
|
+
installInvocationHook(existing);
|
|
500
640
|
return existing;
|
|
501
641
|
}
|
|
502
642
|
if (existing !== void 0) {
|
|
@@ -5559,6 +5699,7 @@ var INSTRUMENTATION_NAMES = {
|
|
|
5559
5699
|
CLAUDE_AGENT_SDK: "claude-agent-sdk",
|
|
5560
5700
|
CLOUDFLARE_AI_CHAT: "cloudflare-ai-chat",
|
|
5561
5701
|
CLOUDFLARE_AGENTS: "cloudflare-agents",
|
|
5702
|
+
CLOUDFLARE_THINK: "cloudflare-think",
|
|
5562
5703
|
COHERE: "cohere",
|
|
5563
5704
|
CURSOR_SDK: "cursor-sdk",
|
|
5564
5705
|
EVE: "eve",
|
|
@@ -5573,6 +5714,7 @@ var INSTRUMENTATION_NAMES = {
|
|
|
5573
5714
|
LANGSMITH: "langsmith",
|
|
5574
5715
|
MASTRA: "mastra",
|
|
5575
5716
|
MISTRAL: "mistral",
|
|
5717
|
+
OLLAMA: "ollama",
|
|
5576
5718
|
OPENAI: "openai",
|
|
5577
5719
|
OPENAI_AGENTS: "openai-agents",
|
|
5578
5720
|
OPENAI_CODEX: "openai-codex",
|
|
@@ -5584,7 +5726,7 @@ var INSTRUMENTATION_NAMES = {
|
|
|
5584
5726
|
var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
|
|
5585
5727
|
"braintrust.spanInstrumentationName"
|
|
5586
5728
|
);
|
|
5587
|
-
var SDK_VERSION = true ? "3.
|
|
5729
|
+
var SDK_VERSION = true ? "3.27.0" : "0.0.0";
|
|
5588
5730
|
function withSpanInstrumentationName(args, instrumentationName) {
|
|
5589
5731
|
return {
|
|
5590
5732
|
...args,
|
|
@@ -10905,6 +11047,34 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
10905
11047
|
);
|
|
10906
11048
|
return stream;
|
|
10907
11049
|
}
|
|
11050
|
+
const chunks = [];
|
|
11051
|
+
let completed = false;
|
|
11052
|
+
const notifyCancellation = async () => {
|
|
11053
|
+
try {
|
|
11054
|
+
await (options.onCancel ?? options.onComplete)(chunks);
|
|
11055
|
+
} catch (error) {
|
|
11056
|
+
debugLogger.error("Error in stream cancellation handler:", error);
|
|
11057
|
+
}
|
|
11058
|
+
};
|
|
11059
|
+
const patchAbortIfPresent = () => {
|
|
11060
|
+
try {
|
|
11061
|
+
if ("abort" in stream && typeof stream.abort === "function") {
|
|
11062
|
+
const originalAbort = stream.abort.bind(stream);
|
|
11063
|
+
stream.abort = (...args) => {
|
|
11064
|
+
try {
|
|
11065
|
+
return originalAbort(...args);
|
|
11066
|
+
} finally {
|
|
11067
|
+
if (!completed) {
|
|
11068
|
+
completed = true;
|
|
11069
|
+
void notifyCancellation();
|
|
11070
|
+
}
|
|
11071
|
+
}
|
|
11072
|
+
};
|
|
11073
|
+
}
|
|
11074
|
+
} catch (error) {
|
|
11075
|
+
debugLogger.warn("Failed to patch stream abort method:", error);
|
|
11076
|
+
}
|
|
11077
|
+
};
|
|
10908
11078
|
if (hasAsyncIteratorMethods(stream) && isSelfAsyncIterator(stream)) {
|
|
10909
11079
|
if ("__braintrust_patched_iterator_methods" in stream) {
|
|
10910
11080
|
return stream;
|
|
@@ -10913,8 +11083,6 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
10913
11083
|
const originalNext = stream.next.bind(stream);
|
|
10914
11084
|
const originalReturn = typeof stream.return === "function" ? stream.return.bind(stream) : null;
|
|
10915
11085
|
const originalThrow = typeof stream.throw === "function" ? stream.throw.bind(stream) : null;
|
|
10916
|
-
const chunks = [];
|
|
10917
|
-
let completed = false;
|
|
10918
11086
|
stream.next = async (...args) => {
|
|
10919
11087
|
try {
|
|
10920
11088
|
const result = await runNextWithWrapper(
|
|
@@ -10966,11 +11134,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
10966
11134
|
stream.return = async (...args) => {
|
|
10967
11135
|
if (!completed) {
|
|
10968
11136
|
completed = true;
|
|
10969
|
-
|
|
10970
|
-
await options.onComplete(chunks);
|
|
10971
|
-
} catch (error) {
|
|
10972
|
-
console.error("Error in stream onComplete handler:", error);
|
|
10973
|
-
}
|
|
11137
|
+
await notifyCancellation();
|
|
10974
11138
|
}
|
|
10975
11139
|
return originalReturn(...args);
|
|
10976
11140
|
};
|
|
@@ -10995,6 +11159,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
10995
11159
|
Object.defineProperty(stream, "__braintrust_patched_iterator_methods", {
|
|
10996
11160
|
value: true
|
|
10997
11161
|
});
|
|
11162
|
+
patchAbortIfPresent();
|
|
10998
11163
|
return stream;
|
|
10999
11164
|
} catch (error) {
|
|
11000
11165
|
console.warn("Failed to patch stream iterator methods:", error);
|
|
@@ -11008,8 +11173,6 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
11008
11173
|
const patchedIteratorFn = function() {
|
|
11009
11174
|
const iterator = originalIteratorFn.call(this);
|
|
11010
11175
|
const originalNext = iterator.next.bind(iterator);
|
|
11011
|
-
const chunks = [];
|
|
11012
|
-
let completed = false;
|
|
11013
11176
|
iterator.next = async function(...args) {
|
|
11014
11177
|
try {
|
|
11015
11178
|
const result = await runNextWithWrapper(
|
|
@@ -11062,11 +11225,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
11062
11225
|
iterator.return = async function(...args) {
|
|
11063
11226
|
if (!completed) {
|
|
11064
11227
|
completed = true;
|
|
11065
|
-
|
|
11066
|
-
await options.onComplete(chunks);
|
|
11067
|
-
} catch (error) {
|
|
11068
|
-
console.error("Error in stream onComplete handler:", error);
|
|
11069
|
-
}
|
|
11228
|
+
await notifyCancellation();
|
|
11070
11229
|
}
|
|
11071
11230
|
return originalReturn(...args);
|
|
11072
11231
|
};
|
|
@@ -11095,6 +11254,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
11095
11254
|
value: true
|
|
11096
11255
|
});
|
|
11097
11256
|
stream[Symbol.asyncIterator] = patchedIteratorFn;
|
|
11257
|
+
patchAbortIfPresent();
|
|
11098
11258
|
return stream;
|
|
11099
11259
|
} catch (error) {
|
|
11100
11260
|
console.warn("Failed to patch stream:", error);
|
|
@@ -11843,6 +12003,33 @@ function traceStreamingChannel(channel2, config) {
|
|
|
11843
12003
|
const { span, startTime } = spanData;
|
|
11844
12004
|
if (isAsyncIterable(asyncEndEvent.result)) {
|
|
11845
12005
|
let firstChunkTime;
|
|
12006
|
+
const handleStreamError = (error) => {
|
|
12007
|
+
try {
|
|
12008
|
+
span.log({ error });
|
|
12009
|
+
} catch (loggingError) {
|
|
12010
|
+
debugLogger.error(
|
|
12011
|
+
`Error logging failure for ${channelName}:`,
|
|
12012
|
+
loggingError
|
|
12013
|
+
);
|
|
12014
|
+
}
|
|
12015
|
+
try {
|
|
12016
|
+
span.end();
|
|
12017
|
+
} catch (endingError) {
|
|
12018
|
+
debugLogger.error(
|
|
12019
|
+
`Error ending span for ${channelName}:`,
|
|
12020
|
+
endingError
|
|
12021
|
+
);
|
|
12022
|
+
}
|
|
12023
|
+
states.delete(event);
|
|
12024
|
+
runStreamingErrorHook({
|
|
12025
|
+
channelName,
|
|
12026
|
+
config,
|
|
12027
|
+
error,
|
|
12028
|
+
event: asyncEndEvent,
|
|
12029
|
+
span,
|
|
12030
|
+
startTime
|
|
12031
|
+
});
|
|
12032
|
+
};
|
|
11846
12033
|
patchStreamIfNeeded(asyncEndEvent.result, {
|
|
11847
12034
|
onChunk: () => {
|
|
11848
12035
|
if (firstChunkTime === void 0) {
|
|
@@ -11922,33 +12109,12 @@ function traceStreamingChannel(channel2, config) {
|
|
|
11922
12109
|
});
|
|
11923
12110
|
}
|
|
11924
12111
|
},
|
|
11925
|
-
|
|
11926
|
-
|
|
11927
|
-
|
|
11928
|
-
|
|
11929
|
-
|
|
11930
|
-
|
|
11931
|
-
loggingError
|
|
11932
|
-
);
|
|
11933
|
-
}
|
|
11934
|
-
try {
|
|
11935
|
-
span.end();
|
|
11936
|
-
} catch (endingError) {
|
|
11937
|
-
debugLogger.error(
|
|
11938
|
-
`Error ending span for ${channelName}:`,
|
|
11939
|
-
endingError
|
|
11940
|
-
);
|
|
11941
|
-
}
|
|
11942
|
-
states.delete(event);
|
|
11943
|
-
runStreamingErrorHook({
|
|
11944
|
-
channelName,
|
|
11945
|
-
config,
|
|
11946
|
-
error,
|
|
11947
|
-
event: asyncEndEvent,
|
|
11948
|
-
span,
|
|
11949
|
-
startTime
|
|
11950
|
-
});
|
|
11951
|
-
}
|
|
12112
|
+
onCancel: () => {
|
|
12113
|
+
const error = new Error("Stream cancelled before completion");
|
|
12114
|
+
error.name = "AbortError";
|
|
12115
|
+
handleStreamError(error);
|
|
12116
|
+
},
|
|
12117
|
+
onError: handleStreamError
|
|
11952
12118
|
});
|
|
11953
12119
|
return;
|
|
11954
12120
|
}
|
|
@@ -12336,11 +12502,21 @@ function defineChannels(pkg, channels, options) {
|
|
|
12336
12502
|
const tracingChannel2 = () => isomorph_default.newTracingChannel(
|
|
12337
12503
|
fullChannelName
|
|
12338
12504
|
);
|
|
12505
|
+
const intercept2 = (interceptor) => {
|
|
12506
|
+
const hook = tracingChannel2();
|
|
12507
|
+
return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
|
|
12508
|
+
};
|
|
12509
|
+
};
|
|
12339
12510
|
return [
|
|
12340
12511
|
key,
|
|
12341
12512
|
{
|
|
12342
12513
|
...asyncSpec,
|
|
12343
12514
|
instrumentationName,
|
|
12515
|
+
intercept: intercept2,
|
|
12516
|
+
invoke: (target, thisArg, args, additional) => {
|
|
12517
|
+
const hook = tracingChannel2();
|
|
12518
|
+
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
12519
|
+
},
|
|
12344
12520
|
tracingChannel: tracingChannel2,
|
|
12345
12521
|
tracePromise: (fn, context) => tracingChannel2().tracePromise(
|
|
12346
12522
|
fn,
|
|
@@ -12354,11 +12530,21 @@ function defineChannels(pkg, channels, options) {
|
|
|
12354
12530
|
const tracingChannel = () => isomorph_default.newTracingChannel(
|
|
12355
12531
|
fullChannelName
|
|
12356
12532
|
);
|
|
12533
|
+
const intercept = (interceptor) => {
|
|
12534
|
+
const hook = tracingChannel();
|
|
12535
|
+
return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
|
|
12536
|
+
};
|
|
12537
|
+
};
|
|
12357
12538
|
return [
|
|
12358
12539
|
key,
|
|
12359
12540
|
{
|
|
12360
12541
|
...syncSpec,
|
|
12361
12542
|
instrumentationName,
|
|
12543
|
+
intercept,
|
|
12544
|
+
invoke: (target, thisArg, args, additional) => {
|
|
12545
|
+
const hook = tracingChannel();
|
|
12546
|
+
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
12547
|
+
},
|
|
12362
12548
|
tracingChannel,
|
|
12363
12549
|
traceSync: (fn, context) => tracingChannel().traceSync(
|
|
12364
12550
|
fn,
|
|
@@ -13609,6 +13795,12 @@ function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens =
|
|
|
13609
13795
|
return cacheTokens;
|
|
13610
13796
|
}
|
|
13611
13797
|
|
|
13798
|
+
// src/wrappers/anthropic-session-collector.ts
|
|
13799
|
+
var sessionStreamCollectors = /* @__PURE__ */ new WeakMap();
|
|
13800
|
+
function registerAnthropicSessionStreamCollector(stream, collector) {
|
|
13801
|
+
sessionStreamCollectors.set(stream, collector);
|
|
13802
|
+
}
|
|
13803
|
+
|
|
13612
13804
|
// src/instrumentation/plugins/anthropic-channels.ts
|
|
13613
13805
|
var anthropicChannels = defineChannels(
|
|
13614
13806
|
"@anthropic-ai/sdk",
|
|
@@ -13624,6 +13816,14 @@ var anthropicChannels = defineChannels(
|
|
|
13624
13816
|
betaMessagesToolRunner: channel({
|
|
13625
13817
|
channelName: "beta.messages.toolRunner",
|
|
13626
13818
|
kind: "sync-stream"
|
|
13819
|
+
}),
|
|
13820
|
+
betaSessionsEventsStream: channel({
|
|
13821
|
+
channelName: "beta.sessions.events.stream",
|
|
13822
|
+
kind: "async"
|
|
13823
|
+
}),
|
|
13824
|
+
betaSessionsThreadsEventsStream: channel({
|
|
13825
|
+
channelName: "beta.sessions.threads.events.stream",
|
|
13826
|
+
kind: "async"
|
|
13627
13827
|
})
|
|
13628
13828
|
},
|
|
13629
13829
|
{ instrumentationName: INSTRUMENTATION_NAMES.ANTHROPIC }
|
|
@@ -13637,6 +13837,7 @@ var AnthropicPlugin = class extends BasePlugin {
|
|
|
13637
13837
|
onEnable() {
|
|
13638
13838
|
this.subscribeToAnthropicChannels();
|
|
13639
13839
|
this.subscribeToAnthropicToolRunner();
|
|
13840
|
+
this.subscribeToAnthropicSessionStreams();
|
|
13640
13841
|
}
|
|
13641
13842
|
onDisable() {
|
|
13642
13843
|
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
@@ -13754,7 +13955,411 @@ var AnthropicPlugin = class extends BasePlugin {
|
|
|
13754
13955
|
tracingChannel.unsubscribe(handlers);
|
|
13755
13956
|
});
|
|
13756
13957
|
}
|
|
13958
|
+
subscribeToAnthropicSessionStreams() {
|
|
13959
|
+
this.subscribeToAnthropicSessionStream(
|
|
13960
|
+
anthropicChannels.betaSessionsEventsStream,
|
|
13961
|
+
false
|
|
13962
|
+
);
|
|
13963
|
+
this.subscribeToAnthropicSessionStream(
|
|
13964
|
+
anthropicChannels.betaSessionsThreadsEventsStream,
|
|
13965
|
+
true
|
|
13966
|
+
);
|
|
13967
|
+
}
|
|
13968
|
+
subscribeToAnthropicSessionStream(channel2, isThread) {
|
|
13969
|
+
const tracingChannel = channel2.tracingChannel();
|
|
13970
|
+
const pending = /* @__PURE__ */ new WeakSet();
|
|
13971
|
+
const handlers = {
|
|
13972
|
+
start: (event) => {
|
|
13973
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
13974
|
+
return;
|
|
13975
|
+
}
|
|
13976
|
+
pending.add(event);
|
|
13977
|
+
},
|
|
13978
|
+
asyncEnd: (event) => {
|
|
13979
|
+
if (!pending.delete(event)) {
|
|
13980
|
+
return;
|
|
13981
|
+
}
|
|
13982
|
+
const stream = event.result;
|
|
13983
|
+
if (!isAsyncIterable(stream)) {
|
|
13984
|
+
return;
|
|
13985
|
+
}
|
|
13986
|
+
registerAnthropicSessionStreamCollector(stream, () => {
|
|
13987
|
+
wrapAnthropicSessionEventStream(stream, isThread);
|
|
13988
|
+
});
|
|
13989
|
+
},
|
|
13990
|
+
error: (event) => {
|
|
13991
|
+
pending.delete(event);
|
|
13992
|
+
}
|
|
13993
|
+
};
|
|
13994
|
+
tracingChannel.subscribe(handlers);
|
|
13995
|
+
this.unsubscribers.push(() => tracingChannel.unsubscribe(handlers));
|
|
13996
|
+
}
|
|
13757
13997
|
};
|
|
13998
|
+
function wrapAnthropicSessionEventStream(stream, isThread) {
|
|
13999
|
+
const state = {
|
|
14000
|
+
history: [],
|
|
14001
|
+
isThread,
|
|
14002
|
+
pendingInput: [],
|
|
14003
|
+
seenEventIds: /* @__PURE__ */ new Set()
|
|
14004
|
+
};
|
|
14005
|
+
patchStreamIfNeeded(stream, {
|
|
14006
|
+
onChunk: (event) => handleAnthropicSessionEvent(state, event),
|
|
14007
|
+
onComplete: () => finalizeAnthropicSessionTurn(state),
|
|
14008
|
+
onError: (error) => finalizeAnthropicSessionTurn(state, error)
|
|
14009
|
+
});
|
|
14010
|
+
return stream;
|
|
14011
|
+
}
|
|
14012
|
+
function handleAnthropicSessionEvent(state, event) {
|
|
14013
|
+
try {
|
|
14014
|
+
if (typeof event.id === "string" && event.type !== "event_delta" && state.seenEventIds.has(event.id)) {
|
|
14015
|
+
return;
|
|
14016
|
+
}
|
|
14017
|
+
if (typeof event.id === "string" && event.type !== "event_delta") {
|
|
14018
|
+
state.seenEventIds.add(event.id);
|
|
14019
|
+
}
|
|
14020
|
+
switch (event.type) {
|
|
14021
|
+
case "user.message":
|
|
14022
|
+
case "system.message":
|
|
14023
|
+
recordAnthropicSessionInput(
|
|
14024
|
+
state,
|
|
14025
|
+
event
|
|
14026
|
+
);
|
|
14027
|
+
break;
|
|
14028
|
+
case "session.status_running":
|
|
14029
|
+
if (!state.isThread) {
|
|
14030
|
+
ensureAnthropicSessionTurn(state);
|
|
14031
|
+
}
|
|
14032
|
+
break;
|
|
14033
|
+
case "session.thread_status_running":
|
|
14034
|
+
if (state.isThread) {
|
|
14035
|
+
ensureAnthropicSessionTurn(state);
|
|
14036
|
+
}
|
|
14037
|
+
break;
|
|
14038
|
+
case "span.model_request_start":
|
|
14039
|
+
if (typeof event.id === "string") {
|
|
14040
|
+
startAnthropicSessionModel(state, event.id);
|
|
14041
|
+
}
|
|
14042
|
+
break;
|
|
14043
|
+
case "event_delta":
|
|
14044
|
+
recordAnthropicSessionFirstToken(state, event);
|
|
14045
|
+
break;
|
|
14046
|
+
case "agent.message":
|
|
14047
|
+
recordAnthropicSessionMessage(
|
|
14048
|
+
state,
|
|
14049
|
+
event
|
|
14050
|
+
);
|
|
14051
|
+
break;
|
|
14052
|
+
case "agent.custom_tool_use":
|
|
14053
|
+
case "agent.mcp_tool_use":
|
|
14054
|
+
case "agent.tool_use":
|
|
14055
|
+
startAnthropicSessionTool(state, event);
|
|
14056
|
+
break;
|
|
14057
|
+
case "user.tool_confirmation":
|
|
14058
|
+
recordAnthropicSessionToolConfirmation(state, event);
|
|
14059
|
+
break;
|
|
14060
|
+
case "agent.mcp_tool_result":
|
|
14061
|
+
case "agent.tool_result":
|
|
14062
|
+
case "user.custom_tool_result":
|
|
14063
|
+
case "user.tool_result":
|
|
14064
|
+
finalizeAnthropicSessionTool(
|
|
14065
|
+
state,
|
|
14066
|
+
event
|
|
14067
|
+
);
|
|
14068
|
+
break;
|
|
14069
|
+
case "span.model_request_end":
|
|
14070
|
+
finalizeAnthropicSessionModel(
|
|
14071
|
+
state,
|
|
14072
|
+
event
|
|
14073
|
+
);
|
|
14074
|
+
break;
|
|
14075
|
+
case "session.status_idle":
|
|
14076
|
+
case "session.thread_status_idle": {
|
|
14077
|
+
if (event.type === "session.status_idle" && state.isThread || event.type === "session.thread_status_idle" && !state.isThread) {
|
|
14078
|
+
break;
|
|
14079
|
+
}
|
|
14080
|
+
const stopReason = isObject(event.stop_reason) ? event.stop_reason.type : void 0;
|
|
14081
|
+
if (stopReason === "end_turn") {
|
|
14082
|
+
finalizeAnthropicSessionTurn(state);
|
|
14083
|
+
} else if (stopReason === "retries_exhausted") {
|
|
14084
|
+
finalizeAnthropicSessionTurn(
|
|
14085
|
+
state,
|
|
14086
|
+
"Anthropic session retries exhausted"
|
|
14087
|
+
);
|
|
14088
|
+
}
|
|
14089
|
+
break;
|
|
14090
|
+
}
|
|
14091
|
+
case "session.error":
|
|
14092
|
+
finalizeAnthropicSessionTurn(state, event.error);
|
|
14093
|
+
break;
|
|
14094
|
+
case "session.deleted":
|
|
14095
|
+
case "session.status_terminated":
|
|
14096
|
+
case "session.thread_status_terminated":
|
|
14097
|
+
if (event.type === "session.deleted" || event.type === "session.status_terminated" && !state.isThread || event.type === "session.thread_status_terminated" && state.isThread) {
|
|
14098
|
+
finalizeAnthropicSessionTurn(state);
|
|
14099
|
+
}
|
|
14100
|
+
break;
|
|
14101
|
+
default:
|
|
14102
|
+
break;
|
|
14103
|
+
}
|
|
14104
|
+
} catch (error) {
|
|
14105
|
+
debugLogger.debug("Error processing Anthropic Sessions event:", error);
|
|
14106
|
+
}
|
|
14107
|
+
}
|
|
14108
|
+
function ensureAnthropicSessionTurn(state) {
|
|
14109
|
+
if (state.activeTurn) {
|
|
14110
|
+
return state.activeTurn;
|
|
14111
|
+
}
|
|
14112
|
+
const input = state.pendingInput;
|
|
14113
|
+
state.pendingInput = [];
|
|
14114
|
+
const span = startSpan(
|
|
14115
|
+
withSpanInstrumentationName(
|
|
14116
|
+
{
|
|
14117
|
+
event: {
|
|
14118
|
+
...input.length > 0 ? { input } : {},
|
|
14119
|
+
metadata: { provider: "anthropic" }
|
|
14120
|
+
},
|
|
14121
|
+
name: state.isThread ? "anthropic.beta.sessions.thread.turn" : "anthropic.beta.sessions.turn",
|
|
14122
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
14123
|
+
},
|
|
14124
|
+
INSTRUMENTATION_NAMES.ANTHROPIC
|
|
14125
|
+
)
|
|
14126
|
+
);
|
|
14127
|
+
state.activeTurn = {
|
|
14128
|
+
activeTools: /* @__PURE__ */ new Map(),
|
|
14129
|
+
input: input.slice(),
|
|
14130
|
+
metrics: {},
|
|
14131
|
+
span
|
|
14132
|
+
};
|
|
14133
|
+
return state.activeTurn;
|
|
14134
|
+
}
|
|
14135
|
+
function recordAnthropicSessionInput(state, event) {
|
|
14136
|
+
const content = processAttachmentsInInput(event.content);
|
|
14137
|
+
const message = {
|
|
14138
|
+
role: event.type === "system.message" ? "system" : "user",
|
|
14139
|
+
content
|
|
14140
|
+
};
|
|
14141
|
+
state.history.push(message);
|
|
14142
|
+
if (state.activeTurn) {
|
|
14143
|
+
state.activeTurn.input.push(message);
|
|
14144
|
+
} else {
|
|
14145
|
+
state.pendingInput.push(message);
|
|
14146
|
+
}
|
|
14147
|
+
}
|
|
14148
|
+
function startAnthropicSessionModel(state, startEventId) {
|
|
14149
|
+
const turn = ensureAnthropicSessionTurn(state);
|
|
14150
|
+
if (turn.activeModel) {
|
|
14151
|
+
finalizeAnthropicSessionModelState(state, turn);
|
|
14152
|
+
}
|
|
14153
|
+
const span = withCurrent(
|
|
14154
|
+
turn.span,
|
|
14155
|
+
() => startSpan(
|
|
14156
|
+
withSpanInstrumentationName(
|
|
14157
|
+
{
|
|
14158
|
+
event: {
|
|
14159
|
+
...state.history.length > 0 ? { input: state.history.slice() } : {},
|
|
14160
|
+
metadata: { provider: "anthropic" }
|
|
14161
|
+
},
|
|
14162
|
+
name: "anthropic.messages.create",
|
|
14163
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
14164
|
+
},
|
|
14165
|
+
INSTRUMENTATION_NAMES.ANTHROPIC
|
|
14166
|
+
)
|
|
14167
|
+
)
|
|
14168
|
+
);
|
|
14169
|
+
turn.activeModel = {
|
|
14170
|
+
output: [],
|
|
14171
|
+
span,
|
|
14172
|
+
startEventId,
|
|
14173
|
+
startTime: getCurrentUnixTimestamp()
|
|
14174
|
+
};
|
|
14175
|
+
}
|
|
14176
|
+
function recordAnthropicSessionFirstToken(state, event) {
|
|
14177
|
+
const model = state.activeTurn?.activeModel;
|
|
14178
|
+
if (!model || model.firstTokenTime !== void 0 || !isObject(event.delta) || !isObject(event.delta.content) || typeof event.delta.content.text !== "string") {
|
|
14179
|
+
return;
|
|
14180
|
+
}
|
|
14181
|
+
model.firstTokenTime = getCurrentUnixTimestamp();
|
|
14182
|
+
}
|
|
14183
|
+
function recordAnthropicSessionMessage(state, event) {
|
|
14184
|
+
const turn = ensureAnthropicSessionTurn(state);
|
|
14185
|
+
const content = processAttachmentsInInput(
|
|
14186
|
+
event.content
|
|
14187
|
+
);
|
|
14188
|
+
if (turn.activeModel) {
|
|
14189
|
+
turn.activeModel.output.push(...content);
|
|
14190
|
+
} else {
|
|
14191
|
+
const output = { role: "assistant", content };
|
|
14192
|
+
turn.lastOutput = output;
|
|
14193
|
+
state.history.push(output);
|
|
14194
|
+
}
|
|
14195
|
+
}
|
|
14196
|
+
function startAnthropicSessionTool(state, event) {
|
|
14197
|
+
const turn = ensureAnthropicSessionTurn(state);
|
|
14198
|
+
if (turn.activeModel) {
|
|
14199
|
+
turn.activeModel.output.push({
|
|
14200
|
+
type: "tool_use",
|
|
14201
|
+
id: event.id,
|
|
14202
|
+
name: event.name,
|
|
14203
|
+
input: event.input
|
|
14204
|
+
});
|
|
14205
|
+
}
|
|
14206
|
+
const existing = turn.activeTools.get(event.id);
|
|
14207
|
+
if (existing) {
|
|
14208
|
+
existing.span.end();
|
|
14209
|
+
turn.activeTools.delete(event.id);
|
|
14210
|
+
}
|
|
14211
|
+
const span = withCurrent(
|
|
14212
|
+
turn.span,
|
|
14213
|
+
() => startSpan(
|
|
14214
|
+
withSpanInstrumentationName(
|
|
14215
|
+
{
|
|
14216
|
+
event: { input: event.input },
|
|
14217
|
+
name: event.name,
|
|
14218
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
14219
|
+
},
|
|
14220
|
+
INSTRUMENTATION_NAMES.ANTHROPIC
|
|
14221
|
+
)
|
|
14222
|
+
)
|
|
14223
|
+
);
|
|
14224
|
+
const toolState = {
|
|
14225
|
+
approval: event.evaluated_permission === "allow" ? "approved" : event.evaluated_permission === "deny" ? "denied" : void 0,
|
|
14226
|
+
span
|
|
14227
|
+
};
|
|
14228
|
+
turn.activeTools.set(event.id, toolState);
|
|
14229
|
+
if (toolState.approval === "denied") {
|
|
14230
|
+
finalizeAnthropicSessionToolState(toolState);
|
|
14231
|
+
turn.activeTools.delete(event.id);
|
|
14232
|
+
}
|
|
14233
|
+
}
|
|
14234
|
+
function recordAnthropicSessionToolConfirmation(state, event) {
|
|
14235
|
+
if (typeof event.tool_use_id !== "string" || event.result !== "allow" && event.result !== "deny") {
|
|
14236
|
+
return;
|
|
14237
|
+
}
|
|
14238
|
+
const turn = state.activeTurn;
|
|
14239
|
+
const tool = turn?.activeTools.get(event.tool_use_id);
|
|
14240
|
+
if (!turn || !tool) {
|
|
14241
|
+
return;
|
|
14242
|
+
}
|
|
14243
|
+
tool.approval = event.result === "allow" ? "approved" : "denied";
|
|
14244
|
+
if (tool.approval === "denied") {
|
|
14245
|
+
finalizeAnthropicSessionToolState(tool);
|
|
14246
|
+
turn.activeTools.delete(event.tool_use_id);
|
|
14247
|
+
}
|
|
14248
|
+
}
|
|
14249
|
+
function finalizeAnthropicSessionTool(state, event) {
|
|
14250
|
+
const toolUseId = event.tool_use_id ?? event.mcp_tool_use_id ?? event.custom_tool_use_id;
|
|
14251
|
+
if (!toolUseId) {
|
|
14252
|
+
return;
|
|
14253
|
+
}
|
|
14254
|
+
const content = processAttachmentsInInput(event.content);
|
|
14255
|
+
const turn = state.activeTurn;
|
|
14256
|
+
const tool = turn?.activeTools.get(toolUseId);
|
|
14257
|
+
if (turn && tool) {
|
|
14258
|
+
finalizeAnthropicSessionToolState(tool, event, content);
|
|
14259
|
+
turn.activeTools.delete(toolUseId);
|
|
14260
|
+
}
|
|
14261
|
+
const toolResult = {
|
|
14262
|
+
type: "tool_result",
|
|
14263
|
+
tool_use_id: toolUseId,
|
|
14264
|
+
...content !== void 0 ? { content } : {},
|
|
14265
|
+
...event.is_error === true ? { is_error: true } : {}
|
|
14266
|
+
};
|
|
14267
|
+
state.history.push({
|
|
14268
|
+
role: "user",
|
|
14269
|
+
content: [toolResult]
|
|
14270
|
+
});
|
|
14271
|
+
}
|
|
14272
|
+
function finalizeAnthropicSessionToolState(state, event, content = event?.content) {
|
|
14273
|
+
safeAnthropicSessionLog(state.span, {
|
|
14274
|
+
...event?.is_error === true ? {
|
|
14275
|
+
error: content ?? "Anthropic session tool execution failed"
|
|
14276
|
+
} : {},
|
|
14277
|
+
...state.approval ? { metadata: { tool_approval: state.approval } } : {},
|
|
14278
|
+
...content !== void 0 ? { output: content } : {}
|
|
14279
|
+
});
|
|
14280
|
+
state.span.end();
|
|
14281
|
+
}
|
|
14282
|
+
function finalizeAnthropicSessionModel(state, event) {
|
|
14283
|
+
const turn = state.activeTurn;
|
|
14284
|
+
const model = turn?.activeModel;
|
|
14285
|
+
if (!turn || !model || model.startEventId !== event.model_request_start_id) {
|
|
14286
|
+
return;
|
|
14287
|
+
}
|
|
14288
|
+
finalizeAnthropicSessionModelState(state, turn, event);
|
|
14289
|
+
}
|
|
14290
|
+
function finalizeAnthropicSessionModelState(state, turn, event) {
|
|
14291
|
+
const model = turn.activeModel;
|
|
14292
|
+
if (!model) {
|
|
14293
|
+
return;
|
|
14294
|
+
}
|
|
14295
|
+
turn.activeModel = void 0;
|
|
14296
|
+
const metrics = event ? parseAnthropicSessionModelUsage(event.model_usage) : {};
|
|
14297
|
+
if (model.firstTokenTime !== void 0) {
|
|
14298
|
+
metrics.time_to_first_token = model.firstTokenTime - model.startTime;
|
|
14299
|
+
}
|
|
14300
|
+
const output = model.output.length > 0 ? { role: "assistant", content: model.output } : void 0;
|
|
14301
|
+
safeAnthropicSessionLog(model.span, {
|
|
14302
|
+
...event?.is_error ? { error: "Anthropic session model request failed" } : {},
|
|
14303
|
+
...Object.keys(metrics).length > 0 ? { metrics } : {},
|
|
14304
|
+
...output ? { output } : {}
|
|
14305
|
+
});
|
|
14306
|
+
model.span.end();
|
|
14307
|
+
if (output) {
|
|
14308
|
+
turn.lastOutput = output;
|
|
14309
|
+
state.history.push(output);
|
|
14310
|
+
}
|
|
14311
|
+
for (const key of [
|
|
14312
|
+
"prompt_tokens",
|
|
14313
|
+
"completion_tokens",
|
|
14314
|
+
"tokens",
|
|
14315
|
+
"prompt_cached_tokens",
|
|
14316
|
+
"prompt_cache_creation_tokens"
|
|
14317
|
+
]) {
|
|
14318
|
+
const value = metrics[key];
|
|
14319
|
+
if (typeof value === "number") {
|
|
14320
|
+
turn.metrics[key] = (turn.metrics[key] ?? 0) + value;
|
|
14321
|
+
}
|
|
14322
|
+
}
|
|
14323
|
+
}
|
|
14324
|
+
function parseAnthropicSessionModelUsage(usage) {
|
|
14325
|
+
const finalized = finalizeAnthropicTokens({
|
|
14326
|
+
completion_tokens: usage.output_tokens,
|
|
14327
|
+
prompt_cache_creation_tokens: usage.cache_creation_input_tokens,
|
|
14328
|
+
prompt_cached_tokens: usage.cache_read_input_tokens,
|
|
14329
|
+
prompt_tokens: usage.input_tokens
|
|
14330
|
+
});
|
|
14331
|
+
return Object.fromEntries(
|
|
14332
|
+
Object.entries(finalized).filter(
|
|
14333
|
+
(entry) => entry[1] !== void 0
|
|
14334
|
+
)
|
|
14335
|
+
);
|
|
14336
|
+
}
|
|
14337
|
+
function finalizeAnthropicSessionTurn(state, error) {
|
|
14338
|
+
const turn = state.activeTurn;
|
|
14339
|
+
if (!turn) {
|
|
14340
|
+
return;
|
|
14341
|
+
}
|
|
14342
|
+
state.activeTurn = void 0;
|
|
14343
|
+
finalizeAnthropicSessionModelState(state, turn);
|
|
14344
|
+
for (const tool of turn.activeTools.values()) {
|
|
14345
|
+
finalizeAnthropicSessionToolState(tool);
|
|
14346
|
+
}
|
|
14347
|
+
turn.activeTools.clear();
|
|
14348
|
+
safeAnthropicSessionLog(turn.span, {
|
|
14349
|
+
...error !== void 0 ? { error: error instanceof Error ? error : toLoggedError(error) } : {},
|
|
14350
|
+
...turn.input.length > 0 ? { input: turn.input } : {},
|
|
14351
|
+
...turn.lastOutput ? { output: turn.lastOutput } : {},
|
|
14352
|
+
...Object.keys(turn.metrics).length > 0 ? { metrics: turn.metrics } : {}
|
|
14353
|
+
});
|
|
14354
|
+
turn.span.end();
|
|
14355
|
+
}
|
|
14356
|
+
function safeAnthropicSessionLog(span, event) {
|
|
14357
|
+
try {
|
|
14358
|
+
span.log(event);
|
|
14359
|
+
} catch (error) {
|
|
14360
|
+
debugLogger.debug("Error logging Anthropic Sessions span:", error);
|
|
14361
|
+
}
|
|
14362
|
+
}
|
|
13758
14363
|
function parseMetricsFromUsage2(usage) {
|
|
13759
14364
|
if (!usage) {
|
|
13760
14365
|
return {};
|
|
@@ -15628,6 +16233,29 @@ var harnessAgentChannels = defineChannels(
|
|
|
15628
16233
|
{ instrumentationName: INSTRUMENTATION_NAMES.AI_SDK }
|
|
15629
16234
|
);
|
|
15630
16235
|
|
|
16236
|
+
// src/instrumentation/plugins/cloudflare-think-context.ts
|
|
16237
|
+
var cloudflareThinkSpans = /* @__PURE__ */ new Map();
|
|
16238
|
+
function registerCloudflareThinkSpan(span) {
|
|
16239
|
+
if (span.spanId) {
|
|
16240
|
+
cloudflareThinkSpans.set(span.spanId, span);
|
|
16241
|
+
}
|
|
16242
|
+
}
|
|
16243
|
+
function unregisterCloudflareThinkSpan(span) {
|
|
16244
|
+
if (span.spanId) {
|
|
16245
|
+
cloudflareThinkSpans.delete(span.spanId);
|
|
16246
|
+
}
|
|
16247
|
+
}
|
|
16248
|
+
function currentCloudflareThinkSpan() {
|
|
16249
|
+
const parentSpanIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
|
|
16250
|
+
for (const parentSpanId of parentSpanIds) {
|
|
16251
|
+
const span = cloudflareThinkSpans.get(parentSpanId);
|
|
16252
|
+
if (span) {
|
|
16253
|
+
return span;
|
|
16254
|
+
}
|
|
16255
|
+
}
|
|
16256
|
+
return void 0;
|
|
16257
|
+
}
|
|
16258
|
+
|
|
15631
16259
|
// src/instrumentation/plugins/ai-sdk-plugin.ts
|
|
15632
16260
|
var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
15633
16261
|
// v3
|
|
@@ -15734,6 +16362,7 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15734
16362
|
traceStreamingChannel(aiSDKChannels.streamText, {
|
|
15735
16363
|
name: "streamText",
|
|
15736
16364
|
type: "function" /* FUNCTION */,
|
|
16365
|
+
shouldTrace: () => currentCloudflareThinkSpan() === void 0,
|
|
15737
16366
|
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
15738
16367
|
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
15739
16368
|
result,
|
|
@@ -15754,6 +16383,7 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15754
16383
|
traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
|
|
15755
16384
|
name: "streamText",
|
|
15756
16385
|
type: "function" /* FUNCTION */,
|
|
16386
|
+
shouldTrace: () => currentCloudflareThinkSpan() === void 0,
|
|
15757
16387
|
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
15758
16388
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
15759
16389
|
defaultDenyOutputPaths: denyOutputPaths,
|
|
@@ -16739,6 +17369,23 @@ function prepareAISDKWorkflowAgentStreamInput(params, event, span, defaultDenyOu
|
|
|
16739
17369
|
metadata
|
|
16740
17370
|
};
|
|
16741
17371
|
}
|
|
17372
|
+
function prepareAISDKAgentCallInput(params, event, span, defaultDenyOutputPaths = DEFAULT_DENY_OUTPUT_PATHS) {
|
|
17373
|
+
const { input } = processAISDKWorkflowAgentCallInput(params);
|
|
17374
|
+
const metadata = extractMetadataFromCallParams(params, event.self);
|
|
17375
|
+
const childTracing = prepareAISDKChildTracing(
|
|
17376
|
+
params,
|
|
17377
|
+
event.self,
|
|
17378
|
+
span,
|
|
17379
|
+
defaultDenyOutputPaths,
|
|
17380
|
+
event.aiSDK,
|
|
17381
|
+
{ agentOwner: true }
|
|
17382
|
+
);
|
|
17383
|
+
event.modelWrapped = childTracing.modelWrapped;
|
|
17384
|
+
if (childTracing.cleanup) {
|
|
17385
|
+
event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
|
|
17386
|
+
}
|
|
17387
|
+
return { input, metadata };
|
|
17388
|
+
}
|
|
16742
17389
|
function prepareAISDKEmbedInput(params, self) {
|
|
16743
17390
|
return {
|
|
16744
17391
|
input: { ...params },
|
|
@@ -16762,6 +17409,18 @@ function extractTopLevelAISDKMetrics(result, event, startTime) {
|
|
|
16762
17409
|
}
|
|
16763
17410
|
return metrics;
|
|
16764
17411
|
}
|
|
17412
|
+
async function extractResolvedAISDKTokenMetrics(result) {
|
|
17413
|
+
for (const field of ["totalUsage", "usage"]) {
|
|
17414
|
+
try {
|
|
17415
|
+
const usage = await Promise.resolve(result[field]);
|
|
17416
|
+
if (usage !== void 0) {
|
|
17417
|
+
return extractTokenMetrics({ [field]: usage });
|
|
17418
|
+
}
|
|
17419
|
+
} catch {
|
|
17420
|
+
}
|
|
17421
|
+
}
|
|
17422
|
+
return extractTokenMetrics(result);
|
|
17423
|
+
}
|
|
16765
17424
|
function hasModelChildTracing(event) {
|
|
16766
17425
|
return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
|
|
16767
17426
|
}
|
|
@@ -17579,13 +18238,15 @@ function patchAISDKStreamingResult(args) {
|
|
|
17579
18238
|
const {
|
|
17580
18239
|
defaultDenyOutputPaths,
|
|
17581
18240
|
endEvent,
|
|
18241
|
+
forceTopLevelMetrics,
|
|
17582
18242
|
onComplete,
|
|
17583
18243
|
onCancel,
|
|
17584
18244
|
onError,
|
|
17585
18245
|
result,
|
|
17586
18246
|
resolvePromiseUsage,
|
|
17587
18247
|
span,
|
|
17588
|
-
startTime
|
|
18248
|
+
startTime,
|
|
18249
|
+
transformOutput
|
|
17589
18250
|
} = args;
|
|
17590
18251
|
if (!result || typeof result !== "object") {
|
|
17591
18252
|
return false;
|
|
@@ -17638,8 +18299,8 @@ function patchAISDKStreamingResult(args) {
|
|
|
17638
18299
|
}
|
|
17639
18300
|
outputLogged = true;
|
|
17640
18301
|
try {
|
|
17641
|
-
const metrics = extractTopLevelAISDKMetrics(result, endEvent);
|
|
17642
|
-
if (resolvePromiseUsage) {
|
|
18302
|
+
const metrics = forceTopLevelMetrics ? await extractResolvedAISDKTokenMetrics(result) : extractTopLevelAISDKMetrics(result, endEvent);
|
|
18303
|
+
if (resolvePromiseUsage && !forceTopLevelMetrics) {
|
|
17643
18304
|
try {
|
|
17644
18305
|
const resultRecord2 = result;
|
|
17645
18306
|
const pendingUsage = resultRecord2.totalUsage ?? resultRecord2.usage;
|
|
@@ -17658,10 +18319,11 @@ function patchAISDKStreamingResult(args) {
|
|
|
17658
18319
|
if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
|
|
17659
18320
|
metrics.time_to_first_token = firstChunkTime - startTime;
|
|
17660
18321
|
}
|
|
17661
|
-
const
|
|
18322
|
+
const processedOutput = await processAISDKStreamingOutput(
|
|
17662
18323
|
result,
|
|
17663
18324
|
resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
|
|
17664
18325
|
);
|
|
18326
|
+
const output = transformOutput ? transformOutput(processedOutput) : processedOutput;
|
|
17665
18327
|
const metadata = buildResolvedMetadataPayload(result).metadata;
|
|
17666
18328
|
try {
|
|
17667
18329
|
span.log({
|
|
@@ -20083,6 +20745,295 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
20083
20745
|
}
|
|
20084
20746
|
};
|
|
20085
20747
|
|
|
20748
|
+
// src/instrumentation/plugins/cloudflare-think-channels.ts
|
|
20749
|
+
var cloudflareThinkChannels = defineChannels(
|
|
20750
|
+
"@cloudflare/think",
|
|
20751
|
+
{
|
|
20752
|
+
runInferenceLoop: channel({
|
|
20753
|
+
channelName: "Think.runInferenceLoop",
|
|
20754
|
+
kind: "async"
|
|
20755
|
+
})
|
|
20756
|
+
},
|
|
20757
|
+
{ instrumentationName: INSTRUMENTATION_NAMES.CLOUDFLARE_THINK }
|
|
20758
|
+
);
|
|
20759
|
+
|
|
20760
|
+
// src/instrumentation/plugins/cloudflare-think-plugin.ts
|
|
20761
|
+
var THINK_STATE_ID = /* @__PURE__ */ Symbol.for("braintrust.cloudflare-think.state-id");
|
|
20762
|
+
var CloudflareThinkPlugin = class extends BasePlugin {
|
|
20763
|
+
statesBySpanId = /* @__PURE__ */ new Map();
|
|
20764
|
+
onEnable() {
|
|
20765
|
+
this.subscribeToThinkRuns();
|
|
20766
|
+
this.subscribeToAISDKStreamTextSync();
|
|
20767
|
+
this.subscribeToAISDKStreamTextAsync();
|
|
20768
|
+
}
|
|
20769
|
+
onDisable() {
|
|
20770
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
20771
|
+
unsubscribe();
|
|
20772
|
+
}
|
|
20773
|
+
this.unsubscribers = [];
|
|
20774
|
+
for (const state of this.statesBySpanId.values()) {
|
|
20775
|
+
this.finishState(state);
|
|
20776
|
+
}
|
|
20777
|
+
this.statesBySpanId.clear();
|
|
20778
|
+
}
|
|
20779
|
+
subscribeToThinkRuns() {
|
|
20780
|
+
const channel2 = cloudflareThinkChannels.runInferenceLoop.tracingChannel();
|
|
20781
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
20782
|
+
const state = _internalGetGlobalState();
|
|
20783
|
+
const contextManager = state?.contextManager;
|
|
20784
|
+
const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
20785
|
+
const ensureState2 = (event) => {
|
|
20786
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
20787
|
+
return void 0;
|
|
20788
|
+
}
|
|
20789
|
+
const existing = states.get(event);
|
|
20790
|
+
if (existing) {
|
|
20791
|
+
return existing;
|
|
20792
|
+
}
|
|
20793
|
+
const span = startSpan(
|
|
20794
|
+
withSpanInstrumentationName(
|
|
20795
|
+
{
|
|
20796
|
+
name: "Think.runTurn",
|
|
20797
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
20798
|
+
},
|
|
20799
|
+
INSTRUMENTATION_NAMES.CLOUDFLARE_THINK
|
|
20800
|
+
)
|
|
20801
|
+
);
|
|
20802
|
+
const runState = {
|
|
20803
|
+
aiResultPatched: false,
|
|
20804
|
+
fallbackInput: extractFallbackInput(event.self?.messages),
|
|
20805
|
+
finalized: false,
|
|
20806
|
+
inputLogged: false,
|
|
20807
|
+
span,
|
|
20808
|
+
startTime: getCurrentUnixTimestamp()
|
|
20809
|
+
};
|
|
20810
|
+
const metadata = {
|
|
20811
|
+
braintrust: {
|
|
20812
|
+
integration_name: "cloudflare-think",
|
|
20813
|
+
sdk_language: "typescript"
|
|
20814
|
+
}
|
|
20815
|
+
};
|
|
20816
|
+
if (typeof event.moduleVersion === "string") {
|
|
20817
|
+
metadata["cloudflare_think.version"] = event.moduleVersion;
|
|
20818
|
+
}
|
|
20819
|
+
span.log({ metadata });
|
|
20820
|
+
states.set(event, runState);
|
|
20821
|
+
if (span.spanId) {
|
|
20822
|
+
this.statesBySpanId.set(span.spanId, runState);
|
|
20823
|
+
}
|
|
20824
|
+
registerCloudflareThinkSpan(span);
|
|
20825
|
+
return runState;
|
|
20826
|
+
};
|
|
20827
|
+
if (contextManager && currentSpanStore && channel2.start) {
|
|
20828
|
+
channel2.start.bindStore(currentSpanStore, (event) => {
|
|
20829
|
+
const runState = ensureState2(event);
|
|
20830
|
+
return runState ? contextManager.wrapSpanForStore(runState.span) : currentSpanStore.getStore();
|
|
20831
|
+
});
|
|
20832
|
+
this.unsubscribers.push(
|
|
20833
|
+
() => channel2.start?.unbindStore(currentSpanStore)
|
|
20834
|
+
);
|
|
20835
|
+
}
|
|
20836
|
+
const handlers = {
|
|
20837
|
+
start: (event) => {
|
|
20838
|
+
ensureState2(event);
|
|
20839
|
+
},
|
|
20840
|
+
asyncEnd: (event) => {
|
|
20841
|
+
const runState = states.get(event);
|
|
20842
|
+
states.delete(event);
|
|
20843
|
+
if (!runState || runState.finalized || runState.aiResultPatched) {
|
|
20844
|
+
return;
|
|
20845
|
+
}
|
|
20846
|
+
this.finishState(runState, void 0, event.result);
|
|
20847
|
+
},
|
|
20848
|
+
error: (event) => {
|
|
20849
|
+
const runState = states.get(event);
|
|
20850
|
+
states.delete(event);
|
|
20851
|
+
if (runState) {
|
|
20852
|
+
this.finishState(runState, event.error);
|
|
20853
|
+
}
|
|
20854
|
+
}
|
|
20855
|
+
};
|
|
20856
|
+
channel2.subscribe(handlers);
|
|
20857
|
+
this.unsubscribers.push(() => channel2.unsubscribe(handlers));
|
|
20858
|
+
}
|
|
20859
|
+
subscribeToAISDKStreamTextSync() {
|
|
20860
|
+
const channel2 = aiSDKChannels.streamTextSync.tracingChannel();
|
|
20861
|
+
const handlers = {
|
|
20862
|
+
start: (event) => {
|
|
20863
|
+
this.startAISDKStream(event);
|
|
20864
|
+
},
|
|
20865
|
+
end: (event) => {
|
|
20866
|
+
this.endAISDKStream(event);
|
|
20867
|
+
},
|
|
20868
|
+
error: (event) => {
|
|
20869
|
+
this.errorAISDKStream(event);
|
|
20870
|
+
}
|
|
20871
|
+
};
|
|
20872
|
+
channel2.subscribe(handlers);
|
|
20873
|
+
this.unsubscribers.push(() => channel2.unsubscribe(handlers));
|
|
20874
|
+
}
|
|
20875
|
+
subscribeToAISDKStreamTextAsync() {
|
|
20876
|
+
const channel2 = aiSDKChannels.streamText.tracingChannel();
|
|
20877
|
+
const handlers = {
|
|
20878
|
+
start: (event) => {
|
|
20879
|
+
this.startAISDKStream(event);
|
|
20880
|
+
},
|
|
20881
|
+
asyncEnd: (event) => {
|
|
20882
|
+
this.endAISDKStream(event);
|
|
20883
|
+
},
|
|
20884
|
+
error: (event) => {
|
|
20885
|
+
this.errorAISDKStream(event);
|
|
20886
|
+
}
|
|
20887
|
+
};
|
|
20888
|
+
channel2.subscribe(handlers);
|
|
20889
|
+
this.unsubscribers.push(() => channel2.unsubscribe(handlers));
|
|
20890
|
+
}
|
|
20891
|
+
startAISDKStream(event) {
|
|
20892
|
+
const runState = this.currentState();
|
|
20893
|
+
if (!runState || runState.finalized) {
|
|
20894
|
+
return;
|
|
20895
|
+
}
|
|
20896
|
+
try {
|
|
20897
|
+
const prepared = prepareAISDKAgentCallInput(
|
|
20898
|
+
event.arguments[0],
|
|
20899
|
+
event,
|
|
20900
|
+
runState.span
|
|
20901
|
+
);
|
|
20902
|
+
runState.span.log({
|
|
20903
|
+
input: extractThinkTaskInput(prepared.input),
|
|
20904
|
+
metadata: {
|
|
20905
|
+
...prepared.metadata,
|
|
20906
|
+
braintrust: {
|
|
20907
|
+
integration_name: "cloudflare-think",
|
|
20908
|
+
sdk_language: "typescript"
|
|
20909
|
+
}
|
|
20910
|
+
}
|
|
20911
|
+
});
|
|
20912
|
+
runState.inputLogged = true;
|
|
20913
|
+
runState.aiEvent = event;
|
|
20914
|
+
Reflect.set(event, THINK_STATE_ID, runState.span.spanId);
|
|
20915
|
+
} catch (error) {
|
|
20916
|
+
debugLogger.error(
|
|
20917
|
+
"Error preparing @cloudflare/think AI SDK tracing:",
|
|
20918
|
+
error
|
|
20919
|
+
);
|
|
20920
|
+
}
|
|
20921
|
+
}
|
|
20922
|
+
endAISDKStream(event) {
|
|
20923
|
+
const runState = this.stateForAISDKEvent(event);
|
|
20924
|
+
if (!runState || runState.finalized) {
|
|
20925
|
+
return;
|
|
20926
|
+
}
|
|
20927
|
+
const patched = patchAISDKStreamingResult({
|
|
20928
|
+
defaultDenyOutputPaths: DEFAULT_DENY_OUTPUT_PATHS,
|
|
20929
|
+
endEvent: event,
|
|
20930
|
+
forceTopLevelMetrics: true,
|
|
20931
|
+
onComplete: () => this.releaseState(runState),
|
|
20932
|
+
result: event.result,
|
|
20933
|
+
span: runState.span,
|
|
20934
|
+
startTime: runState.startTime,
|
|
20935
|
+
transformOutput: extractThinkTaskOutput
|
|
20936
|
+
});
|
|
20937
|
+
runState.aiResultPatched = patched;
|
|
20938
|
+
if (!patched) {
|
|
20939
|
+
this.finishState(runState, void 0, event.result);
|
|
20940
|
+
}
|
|
20941
|
+
}
|
|
20942
|
+
errorAISDKStream(event) {
|
|
20943
|
+
const runState = this.stateForAISDKEvent(event);
|
|
20944
|
+
if (runState) {
|
|
20945
|
+
this.finishState(runState, event.error);
|
|
20946
|
+
}
|
|
20947
|
+
}
|
|
20948
|
+
currentState() {
|
|
20949
|
+
const parentIds = _internalGetGlobalState()?.contextManager.getParentSpanIds()?.spanParents ?? [];
|
|
20950
|
+
for (const parentId of parentIds) {
|
|
20951
|
+
const state = this.statesBySpanId.get(parentId);
|
|
20952
|
+
if (state) {
|
|
20953
|
+
return state;
|
|
20954
|
+
}
|
|
20955
|
+
}
|
|
20956
|
+
return void 0;
|
|
20957
|
+
}
|
|
20958
|
+
stateForAISDKEvent(event) {
|
|
20959
|
+
const spanId = Reflect.get(event, THINK_STATE_ID);
|
|
20960
|
+
return typeof spanId === "string" ? this.statesBySpanId.get(spanId) : void 0;
|
|
20961
|
+
}
|
|
20962
|
+
finishState(state, error, output) {
|
|
20963
|
+
if (state.finalized) {
|
|
20964
|
+
return;
|
|
20965
|
+
}
|
|
20966
|
+
state.finalized = true;
|
|
20967
|
+
try {
|
|
20968
|
+
if (!state.inputLogged && state.fallbackInput !== void 0) {
|
|
20969
|
+
state.span.log({ input: state.fallbackInput });
|
|
20970
|
+
}
|
|
20971
|
+
if (error !== void 0) {
|
|
20972
|
+
state.span.log({ error });
|
|
20973
|
+
} else if (output !== void 0) {
|
|
20974
|
+
state.span.log({ output: extractThinkTaskOutput(output) });
|
|
20975
|
+
}
|
|
20976
|
+
finalizeAISDKChildTracing(state.aiEvent);
|
|
20977
|
+
state.span.end();
|
|
20978
|
+
} finally {
|
|
20979
|
+
this.releaseState(state);
|
|
20980
|
+
}
|
|
20981
|
+
}
|
|
20982
|
+
releaseState(state) {
|
|
20983
|
+
state.finalized = true;
|
|
20984
|
+
unregisterCloudflareThinkSpan(state.span);
|
|
20985
|
+
if (state.span.spanId) {
|
|
20986
|
+
this.statesBySpanId.delete(state.span.spanId);
|
|
20987
|
+
}
|
|
20988
|
+
}
|
|
20989
|
+
};
|
|
20990
|
+
function extractFallbackInput(messages) {
|
|
20991
|
+
if (!Array.isArray(messages) || messages.length === 0) {
|
|
20992
|
+
return void 0;
|
|
20993
|
+
}
|
|
20994
|
+
let latestUserIndex = -1;
|
|
20995
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
20996
|
+
if (messages[index]?.role === "user") {
|
|
20997
|
+
latestUserIndex = index;
|
|
20998
|
+
break;
|
|
20999
|
+
}
|
|
21000
|
+
}
|
|
21001
|
+
const selected = latestUserIndex >= 0 ? messages.slice(latestUserIndex) : [];
|
|
21002
|
+
return selected.map((message) => ({
|
|
21003
|
+
role: message.role,
|
|
21004
|
+
content: message.content ?? message.parts
|
|
21005
|
+
}));
|
|
21006
|
+
}
|
|
21007
|
+
function extractThinkTaskOutput(output) {
|
|
21008
|
+
if (!isObject(output)) {
|
|
21009
|
+
return output;
|
|
21010
|
+
}
|
|
21011
|
+
if (typeof output.text === "string") {
|
|
21012
|
+
return { role: "assistant", content: output.text };
|
|
21013
|
+
}
|
|
21014
|
+
if (output.object !== void 0) {
|
|
21015
|
+
return output.object;
|
|
21016
|
+
}
|
|
21017
|
+
return output;
|
|
21018
|
+
}
|
|
21019
|
+
function extractThinkTaskInput(input) {
|
|
21020
|
+
if (!isObject(input)) {
|
|
21021
|
+
return input;
|
|
21022
|
+
}
|
|
21023
|
+
const system = input.instructions ?? input.system;
|
|
21024
|
+
if (Array.isArray(input.messages)) {
|
|
21025
|
+
return system === void 0 ? input.messages : [{ role: "system", content: system }, ...input.messages];
|
|
21026
|
+
}
|
|
21027
|
+
if (Array.isArray(input.prompt)) {
|
|
21028
|
+
return system === void 0 ? input.prompt : [{ role: "system", content: system }, ...input.prompt];
|
|
21029
|
+
}
|
|
21030
|
+
if (typeof input.prompt === "string") {
|
|
21031
|
+
const messages = [{ role: "user", content: input.prompt }];
|
|
21032
|
+
return system === void 0 ? messages : [{ role: "system", content: system }, ...messages];
|
|
21033
|
+
}
|
|
21034
|
+
return input;
|
|
21035
|
+
}
|
|
21036
|
+
|
|
20086
21037
|
// src/instrumentation/plugins/cursor-sdk-channels.ts
|
|
20087
21038
|
var cursorSDKChannels = defineChannels(
|
|
20088
21039
|
"@cursor/sdk",
|
|
@@ -25848,6 +26799,470 @@ function aggregateMistralStreamChunks(chunks) {
|
|
|
25848
26799
|
};
|
|
25849
26800
|
}
|
|
25850
26801
|
|
|
26802
|
+
// src/instrumentation/plugins/ollama-channels.ts
|
|
26803
|
+
var ollamaChannels = defineChannels(
|
|
26804
|
+
"ollama",
|
|
26805
|
+
{
|
|
26806
|
+
chat: channel({
|
|
26807
|
+
channelName: "chat",
|
|
26808
|
+
kind: "async"
|
|
26809
|
+
}),
|
|
26810
|
+
generate: channel({
|
|
26811
|
+
channelName: "generate",
|
|
26812
|
+
kind: "async"
|
|
26813
|
+
}),
|
|
26814
|
+
embed: channel({
|
|
26815
|
+
channelName: "embed",
|
|
26816
|
+
kind: "async"
|
|
26817
|
+
})
|
|
26818
|
+
},
|
|
26819
|
+
{ instrumentationName: INSTRUMENTATION_NAMES.OLLAMA }
|
|
26820
|
+
);
|
|
26821
|
+
|
|
26822
|
+
// src/instrumentation/plugins/ollama-plugin.ts
|
|
26823
|
+
var OllamaPlugin = class extends BasePlugin {
|
|
26824
|
+
onEnable() {
|
|
26825
|
+
this.unsubscribers.push(
|
|
26826
|
+
traceStreamingChannel(ollamaChannels.chat, {
|
|
26827
|
+
name: "ollama.chat",
|
|
26828
|
+
type: "llm" /* LLM */,
|
|
26829
|
+
extractInput: extractOllamaChatInput,
|
|
26830
|
+
extractOutput: (result, event) => extractOllamaChatOutput(
|
|
26831
|
+
result,
|
|
26832
|
+
countOllamaToolCalls(event?.arguments?.[0]?.messages)
|
|
26833
|
+
),
|
|
26834
|
+
extractMetadata: extractOllamaResponseMetadata,
|
|
26835
|
+
extractMetrics: extractOllamaMetrics,
|
|
26836
|
+
aggregateChunks: aggregateOllamaChatChunks
|
|
26837
|
+
}),
|
|
26838
|
+
traceStreamingChannel(ollamaChannels.generate, {
|
|
26839
|
+
name: "ollama.generate",
|
|
26840
|
+
type: "llm" /* LLM */,
|
|
26841
|
+
extractInput: extractOllamaGenerateInput,
|
|
26842
|
+
extractOutput: extractOllamaGenerateOutput,
|
|
26843
|
+
extractMetadata: extractOllamaResponseMetadata,
|
|
26844
|
+
extractMetrics: extractOllamaMetrics,
|
|
26845
|
+
aggregateChunks: aggregateOllamaGenerateChunks
|
|
26846
|
+
}),
|
|
26847
|
+
traceAsyncChannel(ollamaChannels.embed, {
|
|
26848
|
+
name: "ollama.embed",
|
|
26849
|
+
type: "llm" /* LLM */,
|
|
26850
|
+
extractInput: extractOllamaEmbedInput,
|
|
26851
|
+
extractOutput: extractOllamaEmbedOutput,
|
|
26852
|
+
extractMetadata: extractOllamaResponseMetadata,
|
|
26853
|
+
extractMetrics: extractOllamaMetrics
|
|
26854
|
+
})
|
|
26855
|
+
);
|
|
26856
|
+
}
|
|
26857
|
+
onDisable() {
|
|
26858
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
26859
|
+
}
|
|
26860
|
+
};
|
|
26861
|
+
function isNonNegativeNumber(value) {
|
|
26862
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
26863
|
+
}
|
|
26864
|
+
function normalizeFinishReason(response, hasToolCalls = false) {
|
|
26865
|
+
if (hasToolCalls) {
|
|
26866
|
+
return "tool_calls";
|
|
26867
|
+
}
|
|
26868
|
+
return response?.done_reason || "stop";
|
|
26869
|
+
}
|
|
26870
|
+
function stringifyArguments(value) {
|
|
26871
|
+
if (typeof value === "string") {
|
|
26872
|
+
return value;
|
|
26873
|
+
}
|
|
26874
|
+
try {
|
|
26875
|
+
return JSON.stringify(value ?? {});
|
|
26876
|
+
} catch {
|
|
26877
|
+
return String(value);
|
|
26878
|
+
}
|
|
26879
|
+
}
|
|
26880
|
+
function syntheticToolCallId(name, index) {
|
|
26881
|
+
const normalizedName = name.replace(/[^a-zA-Z0-9_-]/g, "_") || "tool";
|
|
26882
|
+
return `ollama_call_${normalizedName}_${index}`;
|
|
26883
|
+
}
|
|
26884
|
+
function normalizeToolCall(toolCall, index) {
|
|
26885
|
+
const name = toolCall.function?.name;
|
|
26886
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
26887
|
+
return void 0;
|
|
26888
|
+
}
|
|
26889
|
+
return {
|
|
26890
|
+
id: typeof toolCall.id === "string" && toolCall.id.length > 0 ? toolCall.id : syntheticToolCallId(name, index),
|
|
26891
|
+
type: "function",
|
|
26892
|
+
function: {
|
|
26893
|
+
name,
|
|
26894
|
+
arguments: stringifyArguments(toolCall.function?.arguments)
|
|
26895
|
+
}
|
|
26896
|
+
};
|
|
26897
|
+
}
|
|
26898
|
+
function normalizeToolCalls(toolCalls, syntheticIdOffset = 0) {
|
|
26899
|
+
if (!Array.isArray(toolCalls)) {
|
|
26900
|
+
return [];
|
|
26901
|
+
}
|
|
26902
|
+
return toolCalls.flatMap((toolCall, index) => {
|
|
26903
|
+
const normalized = normalizeToolCall(toolCall, syntheticIdOffset + index);
|
|
26904
|
+
return normalized ? [normalized] : [];
|
|
26905
|
+
});
|
|
26906
|
+
}
|
|
26907
|
+
function countOllamaToolCalls(messages) {
|
|
26908
|
+
if (!Array.isArray(messages)) {
|
|
26909
|
+
return 0;
|
|
26910
|
+
}
|
|
26911
|
+
return messages.reduce(
|
|
26912
|
+
(count, message) => count + (isObject(message) && Array.isArray(message.tool_calls) ? message.tool_calls.length : 0),
|
|
26913
|
+
0
|
|
26914
|
+
);
|
|
26915
|
+
}
|
|
26916
|
+
function imageBytes(value) {
|
|
26917
|
+
if (value instanceof Uint8Array) {
|
|
26918
|
+
return value;
|
|
26919
|
+
}
|
|
26920
|
+
if (value instanceof ArrayBuffer) {
|
|
26921
|
+
return new Uint8Array(value);
|
|
26922
|
+
}
|
|
26923
|
+
if (typeof value !== "string" || value.startsWith("data:")) {
|
|
26924
|
+
return void 0;
|
|
26925
|
+
}
|
|
26926
|
+
try {
|
|
26927
|
+
const decoded = atob(value.slice(0, 24));
|
|
26928
|
+
return Uint8Array.from(decoded, (character) => character.charCodeAt(0));
|
|
26929
|
+
} catch {
|
|
26930
|
+
return void 0;
|
|
26931
|
+
}
|
|
26932
|
+
}
|
|
26933
|
+
function inferImageMediaType(value) {
|
|
26934
|
+
if (typeof value === "string") {
|
|
26935
|
+
const dataUrlType = value.match(/^data:(image\/[^;]+);base64,/i)?.[1];
|
|
26936
|
+
if (dataUrlType) {
|
|
26937
|
+
return dataUrlType;
|
|
26938
|
+
}
|
|
26939
|
+
}
|
|
26940
|
+
const bytes = imageBytes(value);
|
|
26941
|
+
if (!bytes) {
|
|
26942
|
+
return void 0;
|
|
26943
|
+
}
|
|
26944
|
+
if (bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) {
|
|
26945
|
+
return "image/png";
|
|
26946
|
+
}
|
|
26947
|
+
if (bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) {
|
|
26948
|
+
return "image/jpeg";
|
|
26949
|
+
}
|
|
26950
|
+
const signature = String.fromCharCode(...bytes.slice(0, 12));
|
|
26951
|
+
if (signature.startsWith("GIF87a") || signature.startsWith("GIF89a")) {
|
|
26952
|
+
return "image/gif";
|
|
26953
|
+
}
|
|
26954
|
+
if (signature.startsWith("RIFF") && signature.slice(8, 12) === "WEBP") {
|
|
26955
|
+
return "image/webp";
|
|
26956
|
+
}
|
|
26957
|
+
return void 0;
|
|
26958
|
+
}
|
|
26959
|
+
function normalizeTextAndImages(content, images) {
|
|
26960
|
+
if (!images || images.length === 0) {
|
|
26961
|
+
return { content };
|
|
26962
|
+
}
|
|
26963
|
+
const imageParts = [];
|
|
26964
|
+
const unrecognizedImages = [];
|
|
26965
|
+
for (const image of images) {
|
|
26966
|
+
let localImagePath;
|
|
26967
|
+
let localPathMediaType;
|
|
26968
|
+
if (typeof image === "string" && !/^data:/i.test(image) && !/^https?:\/\//i.test(image)) {
|
|
26969
|
+
const extension = image.match(/\.([a-z0-9]+)$/i)?.[1]?.toLowerCase();
|
|
26970
|
+
const extensionMediaType = {
|
|
26971
|
+
png: "image/png",
|
|
26972
|
+
jpg: "image/jpeg",
|
|
26973
|
+
jpeg: "image/jpeg",
|
|
26974
|
+
gif: "image/gif",
|
|
26975
|
+
webp: "image/webp"
|
|
26976
|
+
}[extension ?? ""];
|
|
26977
|
+
if (extensionMediaType && isomorph_default.statSync) {
|
|
26978
|
+
try {
|
|
26979
|
+
if (isomorph_default.statSync(image).isFile()) {
|
|
26980
|
+
localImagePath = image;
|
|
26981
|
+
localPathMediaType = extensionMediaType;
|
|
26982
|
+
}
|
|
26983
|
+
} catch {
|
|
26984
|
+
}
|
|
26985
|
+
}
|
|
26986
|
+
}
|
|
26987
|
+
const mediaType = localPathMediaType ?? inferImageMediaType(image);
|
|
26988
|
+
if (!mediaType) {
|
|
26989
|
+
unrecognizedImages.push(image);
|
|
26990
|
+
continue;
|
|
26991
|
+
}
|
|
26992
|
+
const processedImage = localImagePath ? new Attachment({
|
|
26993
|
+
data: localImagePath,
|
|
26994
|
+
filename: localImagePath.split(/[\\/]/).at(-1) ?? "image",
|
|
26995
|
+
contentType: mediaType
|
|
26996
|
+
}) : processInputAttachments({
|
|
26997
|
+
type: "image",
|
|
26998
|
+
image,
|
|
26999
|
+
mediaType
|
|
27000
|
+
}).image;
|
|
27001
|
+
imageParts.push({
|
|
27002
|
+
type: "image_url",
|
|
27003
|
+
image_url: { url: processedImage }
|
|
27004
|
+
});
|
|
27005
|
+
}
|
|
27006
|
+
return {
|
|
27007
|
+
content: imageParts.length > 0 ? [...content ? [{ type: "text", text: content }] : [], ...imageParts] : content,
|
|
27008
|
+
...unrecognizedImages.length > 0 ? { unrecognizedImages } : {}
|
|
27009
|
+
};
|
|
27010
|
+
}
|
|
27011
|
+
function normalizeMessage(message, toolCallId, syntheticToolCallIdOffset = 0) {
|
|
27012
|
+
if (typeof message.role !== "string") {
|
|
27013
|
+
return void 0;
|
|
27014
|
+
}
|
|
27015
|
+
const toolCalls = normalizeToolCalls(
|
|
27016
|
+
message.tool_calls,
|
|
27017
|
+
syntheticToolCallIdOffset
|
|
27018
|
+
);
|
|
27019
|
+
if (message.role === "tool") {
|
|
27020
|
+
const toolName = typeof message.tool_name === "string" && message.tool_name.length > 0 ? message.tool_name : "tool";
|
|
27021
|
+
return {
|
|
27022
|
+
role: "tool",
|
|
27023
|
+
tool_call_id: toolCallId ?? syntheticToolCallId(toolName, 0),
|
|
27024
|
+
content: typeof message.content === "string" ? message.content : ""
|
|
27025
|
+
};
|
|
27026
|
+
}
|
|
27027
|
+
const normalizedContent = normalizeTextAndImages(
|
|
27028
|
+
typeof message.content === "string" ? message.content || (toolCalls.length > 0 ? null : "") : toolCalls.length > 0 ? null : "",
|
|
27029
|
+
message.images
|
|
27030
|
+
);
|
|
27031
|
+
return {
|
|
27032
|
+
role: message.role,
|
|
27033
|
+
content: normalizedContent.content,
|
|
27034
|
+
...typeof message.thinking === "string" && message.thinking.length > 0 ? { reasoning: message.thinking } : {},
|
|
27035
|
+
...toolCalls.length > 0 ? { tool_calls: toolCalls } : {},
|
|
27036
|
+
...normalizedContent.unrecognizedImages ? { images: normalizedContent.unrecognizedImages } : {}
|
|
27037
|
+
};
|
|
27038
|
+
}
|
|
27039
|
+
function normalizeMessages(messages) {
|
|
27040
|
+
if (!Array.isArray(messages)) {
|
|
27041
|
+
return [];
|
|
27042
|
+
}
|
|
27043
|
+
const pendingToolCallIds = /* @__PURE__ */ new Map();
|
|
27044
|
+
let syntheticToolCallIdOffset = 0;
|
|
27045
|
+
return messages.flatMap((message) => {
|
|
27046
|
+
if (!isObject(message)) {
|
|
27047
|
+
return [];
|
|
27048
|
+
}
|
|
27049
|
+
const ollamaMessage = message;
|
|
27050
|
+
let toolCallId;
|
|
27051
|
+
if (ollamaMessage.role === "tool") {
|
|
27052
|
+
const toolName = ollamaMessage.tool_name;
|
|
27053
|
+
if (typeof toolName === "string") {
|
|
27054
|
+
toolCallId = pendingToolCallIds.get(toolName)?.shift();
|
|
27055
|
+
}
|
|
27056
|
+
}
|
|
27057
|
+
const normalized = normalizeMessage(
|
|
27058
|
+
ollamaMessage,
|
|
27059
|
+
toolCallId,
|
|
27060
|
+
syntheticToolCallIdOffset
|
|
27061
|
+
);
|
|
27062
|
+
if (Array.isArray(ollamaMessage.tool_calls)) {
|
|
27063
|
+
syntheticToolCallIdOffset += ollamaMessage.tool_calls.length;
|
|
27064
|
+
}
|
|
27065
|
+
if (ollamaMessage.role === "assistant" && normalized) {
|
|
27066
|
+
const toolCalls = Array.isArray(normalized.tool_calls) ? normalized.tool_calls : [];
|
|
27067
|
+
for (const toolCall of toolCalls) {
|
|
27068
|
+
if (!isObject(toolCall) || !isObject(toolCall.function)) {
|
|
27069
|
+
continue;
|
|
27070
|
+
}
|
|
27071
|
+
const name = toolCall.function.name;
|
|
27072
|
+
const id = toolCall.id;
|
|
27073
|
+
if (typeof name === "string" && typeof id === "string") {
|
|
27074
|
+
const ids = pendingToolCallIds.get(name) ?? [];
|
|
27075
|
+
ids.push(id);
|
|
27076
|
+
pendingToolCallIds.set(name, ids);
|
|
27077
|
+
}
|
|
27078
|
+
}
|
|
27079
|
+
}
|
|
27080
|
+
return normalized ? [normalized] : [];
|
|
27081
|
+
});
|
|
27082
|
+
}
|
|
27083
|
+
function normalizeToolDefinition(tool) {
|
|
27084
|
+
const fn = tool.function;
|
|
27085
|
+
if (!fn || typeof fn.name !== "string" || fn.name.length === 0) {
|
|
27086
|
+
return void 0;
|
|
27087
|
+
}
|
|
27088
|
+
return {
|
|
27089
|
+
type: "function",
|
|
27090
|
+
function: {
|
|
27091
|
+
name: fn.name,
|
|
27092
|
+
...typeof fn.description === "string" ? { description: fn.description } : {},
|
|
27093
|
+
...isObject(fn.parameters) ? { parameters: fn.parameters } : {}
|
|
27094
|
+
}
|
|
27095
|
+
};
|
|
27096
|
+
}
|
|
27097
|
+
function extractToolsMetadata(tools) {
|
|
27098
|
+
if (!Array.isArray(tools)) {
|
|
27099
|
+
return {};
|
|
27100
|
+
}
|
|
27101
|
+
const normalized = tools.flatMap((tool) => {
|
|
27102
|
+
if (!isObject(tool)) {
|
|
27103
|
+
return [];
|
|
27104
|
+
}
|
|
27105
|
+
const definition = normalizeToolDefinition(tool);
|
|
27106
|
+
return definition ? [definition] : [];
|
|
27107
|
+
});
|
|
27108
|
+
return normalized.length > 0 ? { tools: normalized } : {};
|
|
27109
|
+
}
|
|
27110
|
+
function extractOptionsMetadata(options) {
|
|
27111
|
+
if (!isObject(options)) {
|
|
27112
|
+
return {};
|
|
27113
|
+
}
|
|
27114
|
+
const metadata = {};
|
|
27115
|
+
const mappings = [
|
|
27116
|
+
["temperature", "temperature"],
|
|
27117
|
+
["top_p", "top_p"],
|
|
27118
|
+
["num_predict", "max_tokens"],
|
|
27119
|
+
["frequency_penalty", "frequency_penalty"],
|
|
27120
|
+
["presence_penalty", "presence_penalty"],
|
|
27121
|
+
["stop", "stop"]
|
|
27122
|
+
];
|
|
27123
|
+
for (const [source, target] of mappings) {
|
|
27124
|
+
if (options[source] !== void 0) {
|
|
27125
|
+
metadata[target] = options[source];
|
|
27126
|
+
}
|
|
27127
|
+
}
|
|
27128
|
+
return metadata;
|
|
27129
|
+
}
|
|
27130
|
+
function extractRequestMetadata(request) {
|
|
27131
|
+
return {
|
|
27132
|
+
provider: "ollama",
|
|
27133
|
+
...typeof request?.model === "string" ? { model: request.model } : {},
|
|
27134
|
+
...extractOptionsMetadata(request?.options),
|
|
27135
|
+
...request?.format !== void 0 ? { response_format: request.format } : {}
|
|
27136
|
+
};
|
|
27137
|
+
}
|
|
27138
|
+
function extractOllamaChatInput([request]) {
|
|
27139
|
+
return {
|
|
27140
|
+
input: normalizeMessages(request.messages),
|
|
27141
|
+
metadata: {
|
|
27142
|
+
...extractRequestMetadata(request),
|
|
27143
|
+
...extractToolsMetadata(request.tools)
|
|
27144
|
+
}
|
|
27145
|
+
};
|
|
27146
|
+
}
|
|
27147
|
+
function extractOllamaGenerateInput([request]) {
|
|
27148
|
+
const normalizedPrompt = normalizeTextAndImages(
|
|
27149
|
+
typeof request.prompt === "string" ? request.prompt : "",
|
|
27150
|
+
Array.isArray(request.images) ? request.images : void 0
|
|
27151
|
+
);
|
|
27152
|
+
const input = [
|
|
27153
|
+
...typeof request.system === "string" ? [{ role: "system", content: request.system }] : [],
|
|
27154
|
+
{
|
|
27155
|
+
role: "user",
|
|
27156
|
+
content: normalizedPrompt.content,
|
|
27157
|
+
...typeof request.suffix === "string" ? { suffix: request.suffix } : {},
|
|
27158
|
+
...normalizedPrompt.unrecognizedImages ? { images: normalizedPrompt.unrecognizedImages } : {}
|
|
27159
|
+
}
|
|
27160
|
+
];
|
|
27161
|
+
return {
|
|
27162
|
+
input,
|
|
27163
|
+
metadata: extractRequestMetadata(request)
|
|
27164
|
+
};
|
|
27165
|
+
}
|
|
27166
|
+
function extractOllamaEmbedInput([request]) {
|
|
27167
|
+
return {
|
|
27168
|
+
input: request.input,
|
|
27169
|
+
metadata: extractRequestMetadata(request)
|
|
27170
|
+
};
|
|
27171
|
+
}
|
|
27172
|
+
function extractOllamaChatOutput(result, syntheticToolCallIdOffset = 0) {
|
|
27173
|
+
if (!isObject(result) || !isObject(result.message)) {
|
|
27174
|
+
return void 0;
|
|
27175
|
+
}
|
|
27176
|
+
const message = normalizeMessage(
|
|
27177
|
+
result.message,
|
|
27178
|
+
void 0,
|
|
27179
|
+
syntheticToolCallIdOffset
|
|
27180
|
+
);
|
|
27181
|
+
if (!message) {
|
|
27182
|
+
return void 0;
|
|
27183
|
+
}
|
|
27184
|
+
const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
|
|
27185
|
+
return [
|
|
27186
|
+
{
|
|
27187
|
+
index: 0,
|
|
27188
|
+
finish_reason: normalizeFinishReason(result, toolCalls.length > 0),
|
|
27189
|
+
message
|
|
27190
|
+
}
|
|
27191
|
+
];
|
|
27192
|
+
}
|
|
27193
|
+
function extractOllamaGenerateOutput(result) {
|
|
27194
|
+
if (!isObject(result) || typeof result.response !== "string") {
|
|
27195
|
+
return void 0;
|
|
27196
|
+
}
|
|
27197
|
+
return [
|
|
27198
|
+
{
|
|
27199
|
+
index: 0,
|
|
27200
|
+
finish_reason: normalizeFinishReason(result),
|
|
27201
|
+
message: {
|
|
27202
|
+
role: "assistant",
|
|
27203
|
+
content: result.response,
|
|
27204
|
+
...typeof result.thinking === "string" && result.thinking.length > 0 ? { reasoning: result.thinking } : {}
|
|
27205
|
+
}
|
|
27206
|
+
}
|
|
27207
|
+
];
|
|
27208
|
+
}
|
|
27209
|
+
function extractOllamaEmbedOutput(result) {
|
|
27210
|
+
const embedding = Array.isArray(result?.embeddings) ? result.embeddings[0] : void 0;
|
|
27211
|
+
return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
|
|
27212
|
+
}
|
|
27213
|
+
function extractOllamaResponseMetadata(result) {
|
|
27214
|
+
return typeof result?.model === "string" ? { model: result.model } : void 0;
|
|
27215
|
+
}
|
|
27216
|
+
function extractOllamaMetrics(result) {
|
|
27217
|
+
const metrics = {};
|
|
27218
|
+
const promptTokens = result?.prompt_eval_count;
|
|
27219
|
+
const completionTokens = result?.eval_count;
|
|
27220
|
+
if (isNonNegativeNumber(promptTokens)) {
|
|
27221
|
+
metrics.prompt_tokens = promptTokens;
|
|
27222
|
+
}
|
|
27223
|
+
if (isNonNegativeNumber(completionTokens)) {
|
|
27224
|
+
metrics.completion_tokens = completionTokens;
|
|
27225
|
+
}
|
|
27226
|
+
if (isNonNegativeNumber(promptTokens) || isNonNegativeNumber(completionTokens)) {
|
|
27227
|
+
metrics.tokens = (isNonNegativeNumber(promptTokens) ? promptTokens : 0) + (isNonNegativeNumber(completionTokens) ? completionTokens : 0);
|
|
27228
|
+
}
|
|
27229
|
+
return metrics;
|
|
27230
|
+
}
|
|
27231
|
+
function aggregateOllamaChatChunks(chunks, _result, event, _startTime) {
|
|
27232
|
+
const last = chunks.at(-1);
|
|
27233
|
+
const message = {
|
|
27234
|
+
role: "assistant",
|
|
27235
|
+
content: chunks.map((chunk) => chunk.message?.content ?? "").join(""),
|
|
27236
|
+
thinking: chunks.map((chunk) => chunk.message?.thinking ?? "").join(""),
|
|
27237
|
+
tool_calls: chunks.flatMap((chunk) => chunk.message?.tool_calls ?? [])
|
|
27238
|
+
};
|
|
27239
|
+
const response = {
|
|
27240
|
+
...last,
|
|
27241
|
+
message
|
|
27242
|
+
};
|
|
27243
|
+
return {
|
|
27244
|
+
output: extractOllamaChatOutput(
|
|
27245
|
+
response,
|
|
27246
|
+
countOllamaToolCalls(event?.arguments?.[0]?.messages)
|
|
27247
|
+
),
|
|
27248
|
+
metrics: extractOllamaMetrics(last ?? {}),
|
|
27249
|
+
metadata: extractOllamaResponseMetadata(last ?? {})
|
|
27250
|
+
};
|
|
27251
|
+
}
|
|
27252
|
+
function aggregateOllamaGenerateChunks(chunks, _result, _event, _startTime) {
|
|
27253
|
+
const last = chunks.at(-1);
|
|
27254
|
+
const response = {
|
|
27255
|
+
...last,
|
|
27256
|
+
response: chunks.map((chunk) => chunk.response ?? "").join(""),
|
|
27257
|
+
thinking: chunks.map((chunk) => chunk.thinking ?? "").join("")
|
|
27258
|
+
};
|
|
27259
|
+
return {
|
|
27260
|
+
output: extractOllamaGenerateOutput(response),
|
|
27261
|
+
metrics: extractOllamaMetrics(last ?? {}),
|
|
27262
|
+
metadata: extractOllamaResponseMetadata(last ?? {})
|
|
27263
|
+
};
|
|
27264
|
+
}
|
|
27265
|
+
|
|
25851
27266
|
// src/instrumentation/plugins/google-adk-channels.ts
|
|
25852
27267
|
var googleADKChannels = defineChannels(
|
|
25853
27268
|
"@google/adk",
|
|
@@ -29601,7 +31016,7 @@ var FlueObserveBridge = class {
|
|
|
29601
31016
|
return;
|
|
29602
31017
|
}
|
|
29603
31018
|
const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
|
|
29604
|
-
const output = operationOutput(event);
|
|
31019
|
+
const output = operationOutput(event) ?? outputFromAgentTurn(state.latestAgentOutput);
|
|
29605
31020
|
const metadata = {
|
|
29606
31021
|
...state.metadata,
|
|
29607
31022
|
...extractEventMetadata(event),
|
|
@@ -29610,7 +31025,7 @@ var FlueObserveBridge = class {
|
|
|
29610
31025
|
};
|
|
29611
31026
|
this.finishPendingChildrenForOperation(event, output);
|
|
29612
31027
|
safeLog3(state.span, {
|
|
29613
|
-
...event.isError ? { error: toLoggedError(event.error) } : {},
|
|
31028
|
+
...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
|
|
29614
31029
|
metadata,
|
|
29615
31030
|
metrics: durationMetrics2(event.durationMs),
|
|
29616
31031
|
output
|
|
@@ -29641,7 +31056,7 @@ var FlueObserveBridge = class {
|
|
|
29641
31056
|
};
|
|
29642
31057
|
const parent = this.parentSpanForTurn(event);
|
|
29643
31058
|
const span = startFlueSpan(parent, {
|
|
29644
|
-
name:
|
|
31059
|
+
name: "flue.turn",
|
|
29645
31060
|
spanAttributes: { type: "llm" /* LLM */ },
|
|
29646
31061
|
startTime: eventTime(event.timestamp),
|
|
29647
31062
|
event: {
|
|
@@ -29685,6 +31100,12 @@ var FlueObserveBridge = class {
|
|
|
29685
31100
|
},
|
|
29686
31101
|
output
|
|
29687
31102
|
});
|
|
31103
|
+
if (event.purpose === "agent" && event.operationId) {
|
|
31104
|
+
const operation = this.operationsById.get(event.operationId);
|
|
31105
|
+
if (operation) {
|
|
31106
|
+
operation.latestAgentOutput = output;
|
|
31107
|
+
}
|
|
31108
|
+
}
|
|
29688
31109
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
29689
31110
|
this.turnsByKey.delete(key);
|
|
29690
31111
|
}
|
|
@@ -29764,7 +31185,7 @@ var FlueObserveBridge = class {
|
|
|
29764
31185
|
return;
|
|
29765
31186
|
}
|
|
29766
31187
|
safeLog3(state.span, {
|
|
29767
|
-
...event.isError ? { error: toLoggedError(event.result) } : {},
|
|
31188
|
+
...event.isError ? { error: toLoggedError(event.errorInfo ?? event.result) } : {},
|
|
29768
31189
|
metadata: {
|
|
29769
31190
|
...state.metadata,
|
|
29770
31191
|
...extractEventMetadata(event),
|
|
@@ -29810,6 +31231,7 @@ var FlueObserveBridge = class {
|
|
|
29810
31231
|
...event.usage ? { "flue.usage": event.usage } : {}
|
|
29811
31232
|
};
|
|
29812
31233
|
safeLog3(state.span, {
|
|
31234
|
+
...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
|
|
29813
31235
|
metadata,
|
|
29814
31236
|
metrics: {
|
|
29815
31237
|
...durationMetrics2(event.durationMs),
|
|
@@ -29914,7 +31336,7 @@ var FlueObserveBridge = class {
|
|
|
29914
31336
|
...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
|
|
29915
31337
|
};
|
|
29916
31338
|
const span = startFlueSpan(this.parentSpanForEvent(event), {
|
|
29917
|
-
name:
|
|
31339
|
+
name: "flue.turn",
|
|
29918
31340
|
spanAttributes: { type: "llm" /* LLM */ },
|
|
29919
31341
|
startTime: eventTime(event.timestamp),
|
|
29920
31342
|
event: { metadata }
|
|
@@ -30046,7 +31468,10 @@ function extractEventMetadata(event, ctx) {
|
|
|
30046
31468
|
return {
|
|
30047
31469
|
...event.runId ? { "flue.run_id": event.runId } : {},
|
|
30048
31470
|
...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
|
|
31471
|
+
...event.submissionId ? { "flue.submission_id": event.submissionId } : {},
|
|
30049
31472
|
...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
|
|
31473
|
+
...event.agentName ? { "flue.agent_name": event.agentName } : {},
|
|
31474
|
+
...event.conversationId ? { "flue.conversation_id": event.conversationId } : {},
|
|
30050
31475
|
...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
|
|
30051
31476
|
...event.session ? { "flue.session": event.session } : {},
|
|
30052
31477
|
...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
|
|
@@ -30075,7 +31500,7 @@ function flueTurnRequestInput(event) {
|
|
|
30075
31500
|
return event.request?.input ?? event.input;
|
|
30076
31501
|
}
|
|
30077
31502
|
function flueTurnRequestModel(event) {
|
|
30078
|
-
return event.request?.model ?? event.model;
|
|
31503
|
+
return event.request?.requestedModel ?? event.request?.model ?? event.model;
|
|
30079
31504
|
}
|
|
30080
31505
|
function flueTurnRequestProvider(event) {
|
|
30081
31506
|
return event.request?.providerName ?? event.provider ?? event.request?.providerId;
|
|
@@ -30084,10 +31509,10 @@ function flueTurnRequestApi(event) {
|
|
|
30084
31509
|
return event.request?.api ?? event.api;
|
|
30085
31510
|
}
|
|
30086
31511
|
function flueTurnRequestReasoning(event) {
|
|
30087
|
-
return event.request?.reasoning ?? event.reasoning;
|
|
31512
|
+
return event.request?.reasoningLevel ?? event.request?.reasoning ?? event.reasoning;
|
|
30088
31513
|
}
|
|
30089
31514
|
function flueTurnModel(event) {
|
|
30090
|
-
return event.request?.model ?? event.model;
|
|
31515
|
+
return event.response?.responseModel ?? event.request?.requestedModel ?? event.request?.model ?? event.model;
|
|
30091
31516
|
}
|
|
30092
31517
|
function flueTurnProvider(event) {
|
|
30093
31518
|
return event.request?.providerName ?? event.provider ?? event.request?.providerId;
|
|
@@ -30102,7 +31527,7 @@ function flueTurnOutput(event) {
|
|
|
30102
31527
|
return event.response?.output ?? event.output;
|
|
30103
31528
|
}
|
|
30104
31529
|
function flueTurnStopReason(event) {
|
|
30105
|
-
return event.response?.stopReason ?? event.stopReason;
|
|
31530
|
+
return event.response?.finishReason ?? event.response?.stopReason ?? event.stopReason;
|
|
30106
31531
|
}
|
|
30107
31532
|
function flueTurnError(event) {
|
|
30108
31533
|
return event.response?.error ?? event.response?.errorInfo?.message ?? event.error;
|
|
@@ -30117,6 +31542,9 @@ function flueToolInput(event) {
|
|
|
30117
31542
|
return event.input;
|
|
30118
31543
|
}
|
|
30119
31544
|
function flueToolOutput(event) {
|
|
31545
|
+
if (Object.hasOwn(event, "effectiveResult")) {
|
|
31546
|
+
return event.effectiveResult;
|
|
31547
|
+
}
|
|
30120
31548
|
return event.output !== void 0 ? event.output : event.result;
|
|
30121
31549
|
}
|
|
30122
31550
|
function flueToolError(event) {
|
|
@@ -30124,10 +31552,36 @@ function flueToolError(event) {
|
|
|
30124
31552
|
}
|
|
30125
31553
|
function operationOutput(event) {
|
|
30126
31554
|
if (event.operationKind === "prompt" || event.operationKind === "skill") {
|
|
30127
|
-
return llmResultFromOperationResult(event.result);
|
|
31555
|
+
return outputFromAgentInvocation(event.agentOutput) ?? llmResultFromOperationResult(event.result);
|
|
30128
31556
|
}
|
|
30129
31557
|
return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
|
|
30130
31558
|
}
|
|
31559
|
+
function outputFromAgentInvocation(output) {
|
|
31560
|
+
if (output?.type === "text") {
|
|
31561
|
+
return output.text;
|
|
31562
|
+
}
|
|
31563
|
+
if (output?.type === "data") {
|
|
31564
|
+
return output.data;
|
|
31565
|
+
}
|
|
31566
|
+
return void 0;
|
|
31567
|
+
}
|
|
31568
|
+
function outputFromAgentTurn(output) {
|
|
31569
|
+
if (!isObjectLike(output)) {
|
|
31570
|
+
return output;
|
|
31571
|
+
}
|
|
31572
|
+
const content = Reflect.get(output, "content");
|
|
31573
|
+
if (!Array.isArray(content)) {
|
|
31574
|
+
return output;
|
|
31575
|
+
}
|
|
31576
|
+
const text = content.flatMap((part) => {
|
|
31577
|
+
if (!isObjectLike(part) || Reflect.get(part, "type") !== "text") {
|
|
31578
|
+
return [];
|
|
31579
|
+
}
|
|
31580
|
+
const value = Reflect.get(part, "text");
|
|
31581
|
+
return typeof value === "string" ? [value] : [];
|
|
31582
|
+
});
|
|
31583
|
+
return text.length > 0 ? text.join("") : output;
|
|
31584
|
+
}
|
|
30131
31585
|
function llmResultFromOperationResult(result) {
|
|
30132
31586
|
if (!isObjectLike(result)) {
|
|
30133
31587
|
return result;
|
|
@@ -30226,7 +31680,7 @@ function safeEnd(span, endTime) {
|
|
|
30226
31680
|
}
|
|
30227
31681
|
}
|
|
30228
31682
|
function logInstrumentationError3(label, error) {
|
|
30229
|
-
|
|
31683
|
+
debugLogger.debug(`Error in ${label} instrumentation:`, error);
|
|
30230
31684
|
}
|
|
30231
31685
|
|
|
30232
31686
|
// src/wrappers/langchain/callback-handler.ts
|
|
@@ -31155,12 +32609,13 @@ var piCodingAgentChannels = defineChannels(
|
|
|
31155
32609
|
);
|
|
31156
32610
|
|
|
31157
32611
|
// src/instrumentation/plugins/pi-coding-agent-plugin.ts
|
|
31158
|
-
var
|
|
32612
|
+
var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
|
|
32613
|
+
var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
|
|
31159
32614
|
var piPromptContextStore;
|
|
31160
32615
|
var PiCodingAgentPlugin = class extends BasePlugin {
|
|
31161
32616
|
activePromptStates = /* @__PURE__ */ new Set();
|
|
31162
32617
|
onEnable() {
|
|
31163
|
-
this.
|
|
32618
|
+
this.interceptPrompt();
|
|
31164
32619
|
}
|
|
31165
32620
|
onDisable() {
|
|
31166
32621
|
for (const unsubscribe of this.unsubscribers) {
|
|
@@ -31168,65 +32623,74 @@ var PiCodingAgentPlugin = class extends BasePlugin {
|
|
|
31168
32623
|
}
|
|
31169
32624
|
this.unsubscribers = [];
|
|
31170
32625
|
for (const state of [...this.activePromptStates]) {
|
|
31171
|
-
|
|
31172
|
-
logInstrumentationError4("Pi Coding Agent disable cleanup", error);
|
|
31173
|
-
});
|
|
32626
|
+
finishPiPromptRun(state);
|
|
31174
32627
|
}
|
|
31175
32628
|
}
|
|
31176
|
-
|
|
31177
|
-
|
|
31178
|
-
|
|
31179
|
-
|
|
31180
|
-
|
|
31181
|
-
|
|
31182
|
-
|
|
31183
|
-
|
|
31184
|
-
|
|
31185
|
-
|
|
31186
|
-
|
|
31187
|
-
|
|
31188
|
-
|
|
31189
|
-
|
|
31190
|
-
|
|
31191
|
-
|
|
31192
|
-
|
|
31193
|
-
|
|
31194
|
-
|
|
31195
|
-
states.delete(event);
|
|
31196
|
-
state.promptCallEnded = true;
|
|
31197
|
-
if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
|
|
31198
|
-
if (!state.sawStreamFn) {
|
|
31199
|
-
state.queued = true;
|
|
31200
|
-
if (!state.streamPatchState.queuedPromptStates.includes(state)) {
|
|
31201
|
-
state.streamPatchState.queuedPromptStates.push(state);
|
|
31202
|
-
}
|
|
32629
|
+
interceptPrompt() {
|
|
32630
|
+
this.unsubscribers.push(
|
|
32631
|
+
piCodingAgentChannels.prompt.intercept(
|
|
32632
|
+
(target, thisArg, args, additional) => {
|
|
32633
|
+
const invokeTarget = () => Reflect.apply(target, thisArg, args);
|
|
32634
|
+
let state;
|
|
32635
|
+
try {
|
|
32636
|
+
state = startPiPromptRun(
|
|
32637
|
+
{
|
|
32638
|
+
...additional,
|
|
32639
|
+
arguments: args,
|
|
32640
|
+
self: thisArg
|
|
32641
|
+
},
|
|
32642
|
+
(finalizedState) => {
|
|
32643
|
+
this.activePromptStates.delete(finalizedState);
|
|
32644
|
+
}
|
|
32645
|
+
);
|
|
32646
|
+
} catch (error) {
|
|
32647
|
+
logInstrumentationError4("Pi Coding Agent prompt start", error);
|
|
31203
32648
|
}
|
|
31204
|
-
|
|
31205
|
-
|
|
31206
|
-
|
|
31207
|
-
|
|
31208
|
-
|
|
31209
|
-
|
|
31210
|
-
|
|
31211
|
-
|
|
32649
|
+
if (!state) {
|
|
32650
|
+
return runWithAutoInstrumentationSuppressed(invokeTarget);
|
|
32651
|
+
}
|
|
32652
|
+
this.activePromptStates.add(state);
|
|
32653
|
+
return promptContextStore().run(
|
|
32654
|
+
state,
|
|
32655
|
+
() => runWithAutoInstrumentationSuppressed(() => {
|
|
32656
|
+
let result;
|
|
32657
|
+
try {
|
|
32658
|
+
result = invokeTarget();
|
|
32659
|
+
} catch (error) {
|
|
32660
|
+
finishPiPromptRun(state, error);
|
|
32661
|
+
throw error;
|
|
32662
|
+
}
|
|
32663
|
+
return Promise.resolve(result).then(
|
|
32664
|
+
(value) => {
|
|
32665
|
+
finishPiPromptCall(state);
|
|
32666
|
+
return value;
|
|
32667
|
+
},
|
|
32668
|
+
(error) => {
|
|
32669
|
+
finishPiPromptRun(state, error);
|
|
32670
|
+
throw error;
|
|
32671
|
+
}
|
|
32672
|
+
);
|
|
32673
|
+
})
|
|
32674
|
+
);
|
|
31212
32675
|
}
|
|
31213
|
-
|
|
31214
|
-
|
|
31215
|
-
}
|
|
31216
|
-
};
|
|
31217
|
-
channel2.subscribe(handlers);
|
|
31218
|
-
this.unsubscribers.push(() => {
|
|
31219
|
-
unbindAutoInstrumentationSuppression?.();
|
|
31220
|
-
channel2.unsubscribe(handlers);
|
|
31221
|
-
});
|
|
32676
|
+
)
|
|
32677
|
+
);
|
|
31222
32678
|
}
|
|
31223
32679
|
};
|
|
32680
|
+
function finishPiPromptCall(state) {
|
|
32681
|
+
state.promptCallEnded = true;
|
|
32682
|
+
if (state.deferCompletionUntilTurnEnd && !state.turnEnded) {
|
|
32683
|
+
return;
|
|
32684
|
+
}
|
|
32685
|
+
finishPiPromptRun(state);
|
|
32686
|
+
}
|
|
31224
32687
|
function startPiPromptRun(event, onFinalize) {
|
|
31225
32688
|
const session = extractSession(event);
|
|
31226
32689
|
const agent = session?.agent;
|
|
31227
32690
|
if (!session || !isPiAgent(agent)) {
|
|
31228
32691
|
return void 0;
|
|
31229
32692
|
}
|
|
32693
|
+
installPiAgentInstrumentation(agent);
|
|
31230
32694
|
const metadata = {
|
|
31231
32695
|
...extractSessionMetadata(session),
|
|
31232
32696
|
...extractPromptOptionsMetadata(event.arguments[1]),
|
|
@@ -31248,9 +32712,7 @@ function startPiPromptRun(event, onFinalize) {
|
|
|
31248
32712
|
INSTRUMENTATION_NAMES.PI_CODING_AGENT
|
|
31249
32713
|
)
|
|
31250
32714
|
);
|
|
31251
|
-
const streamPatchState = installPiStreamPatch(agent);
|
|
31252
32715
|
const options = event.arguments[1];
|
|
31253
|
-
const promptText = event.arguments[0];
|
|
31254
32716
|
const state = {
|
|
31255
32717
|
activeLlmSpans: /* @__PURE__ */ new Set(),
|
|
31256
32718
|
activeToolSpans: /* @__PURE__ */ new Map(),
|
|
@@ -31262,29 +32724,10 @@ function startPiPromptRun(event, onFinalize) {
|
|
|
31262
32724
|
metrics: {},
|
|
31263
32725
|
onFinalize,
|
|
31264
32726
|
promptCallEnded: false,
|
|
31265
|
-
...typeof promptText === "string" ? { promptText } : {},
|
|
31266
|
-
queued: false,
|
|
31267
32727
|
span,
|
|
31268
|
-
sawStreamFn: false,
|
|
31269
32728
|
startTime: getCurrentUnixTimestamp(),
|
|
31270
|
-
streamPatchState,
|
|
31271
32729
|
turnEnded: false
|
|
31272
32730
|
};
|
|
31273
|
-
state.restorePromptContext = enterPiPromptContext(state);
|
|
31274
|
-
streamPatchState.activePromptStates.add(state);
|
|
31275
|
-
try {
|
|
31276
|
-
state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
|
|
31277
|
-
try {
|
|
31278
|
-
await runWithAutoInstrumentationSuppressed(
|
|
31279
|
-
() => handlePiAgentEvent(state, agentEvent)
|
|
31280
|
-
);
|
|
31281
|
-
} catch (error) {
|
|
31282
|
-
logInstrumentationError4("Pi Coding Agent event", error);
|
|
31283
|
-
}
|
|
31284
|
-
});
|
|
31285
|
-
} catch (error) {
|
|
31286
|
-
logInstrumentationError4("Pi Coding Agent event subscription", error);
|
|
31287
|
-
}
|
|
31288
32731
|
return state;
|
|
31289
32732
|
}
|
|
31290
32733
|
function extractSession(event) {
|
|
@@ -31298,111 +32741,55 @@ function promptContextStore() {
|
|
|
31298
32741
|
piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
|
|
31299
32742
|
return piPromptContextStore;
|
|
31300
32743
|
}
|
|
31301
|
-
function currentPromptContextFrames() {
|
|
31302
|
-
return promptContextStore().getStore()?.frames ?? [];
|
|
31303
|
-
}
|
|
31304
32744
|
function currentPiPromptState() {
|
|
31305
|
-
|
|
31306
|
-
|
|
31307
|
-
|
|
31308
|
-
|
|
31309
|
-
|
|
31310
|
-
|
|
31311
|
-
|
|
31312
|
-
|
|
31313
|
-
|
|
31314
|
-
|
|
31315
|
-
|
|
31316
|
-
|
|
31317
|
-
const frames = currentPromptContextFrames().filter(
|
|
31318
|
-
(candidate) => candidate.id !== frame.id
|
|
31319
|
-
);
|
|
31320
|
-
promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
31321
|
-
};
|
|
31322
|
-
}
|
|
31323
|
-
function installPiStreamPatch(agent) {
|
|
31324
|
-
const existing = piStreamPatchStates.get(agent);
|
|
31325
|
-
if (existing) {
|
|
31326
|
-
if (agent.streamFn !== existing.wrappedStreamFn) {
|
|
31327
|
-
debugLogger.debug(
|
|
31328
|
-
"Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
|
|
31329
|
-
);
|
|
31330
|
-
}
|
|
31331
|
-
return existing;
|
|
31332
|
-
}
|
|
31333
|
-
const patchState = {
|
|
31334
|
-
activePromptStates: /* @__PURE__ */ new Set(),
|
|
31335
|
-
agent,
|
|
31336
|
-
originalStreamFn: agent.streamFn,
|
|
31337
|
-
queuedPromptStates: [],
|
|
31338
|
-
wrappedStreamFn: agent.streamFn
|
|
31339
|
-
};
|
|
31340
|
-
patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
|
|
31341
|
-
agent.streamFn = patchState.wrappedStreamFn;
|
|
31342
|
-
piStreamPatchStates.set(agent, patchState);
|
|
31343
|
-
return patchState;
|
|
31344
|
-
}
|
|
31345
|
-
function resolveStreamPromptState(patchState, context) {
|
|
31346
|
-
let lastUserText;
|
|
31347
|
-
if (Array.isArray(context.messages)) {
|
|
31348
|
-
for (let i = context.messages.length - 1; i >= 0; i--) {
|
|
31349
|
-
const message = context.messages[i];
|
|
31350
|
-
if (isPiUserMessage(message)) {
|
|
31351
|
-
if (typeof message.content === "string") {
|
|
31352
|
-
lastUserText = message.content;
|
|
31353
|
-
} else {
|
|
31354
|
-
lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
|
|
31355
|
-
}
|
|
31356
|
-
break;
|
|
31357
|
-
}
|
|
31358
|
-
}
|
|
31359
|
-
}
|
|
31360
|
-
if (lastUserText !== void 0) {
|
|
31361
|
-
const queuedMatch = patchState.queuedPromptStates.find(
|
|
31362
|
-
(state) => state.promptText === lastUserText
|
|
31363
|
-
);
|
|
31364
|
-
if (queuedMatch) {
|
|
31365
|
-
return queuedMatch;
|
|
31366
|
-
}
|
|
31367
|
-
const matches = [...patchState.activePromptStates].filter(
|
|
31368
|
-
(state) => state.promptText === lastUserText
|
|
32745
|
+
return promptContextStore().getStore();
|
|
32746
|
+
}
|
|
32747
|
+
function installPiAgentInstrumentation(agent) {
|
|
32748
|
+
const existing = piAgentPatchStates.get(agent);
|
|
32749
|
+
if (!existing || agent.streamFn !== existing.wrappedStreamFn) {
|
|
32750
|
+
const patchState = {
|
|
32751
|
+
originalStreamFn: agent.streamFn,
|
|
32752
|
+
wrappedStreamFn: agent.streamFn
|
|
32753
|
+
};
|
|
32754
|
+
patchState.wrappedStreamFn = makeInstrumentedStreamFn(
|
|
32755
|
+
agent,
|
|
32756
|
+
patchState.originalStreamFn
|
|
31369
32757
|
);
|
|
31370
|
-
|
|
31371
|
-
|
|
31372
|
-
}
|
|
32758
|
+
agent.streamFn = patchState.wrappedStreamFn;
|
|
32759
|
+
piAgentPatchStates.set(agent, patchState);
|
|
31373
32760
|
}
|
|
31374
|
-
|
|
31375
|
-
|
|
31376
|
-
return contextState;
|
|
32761
|
+
if (piAgentEventSubscriptions.has(agent)) {
|
|
32762
|
+
return;
|
|
31377
32763
|
}
|
|
31378
|
-
|
|
31379
|
-
|
|
32764
|
+
try {
|
|
32765
|
+
agent.subscribe(async (event) => {
|
|
32766
|
+
const state = currentPiPromptState();
|
|
32767
|
+
if (!state || state.agent !== agent || state.finalized) {
|
|
32768
|
+
return;
|
|
32769
|
+
}
|
|
32770
|
+
try {
|
|
32771
|
+
await runWithAutoInstrumentationSuppressed(
|
|
32772
|
+
() => handlePiAgentEvent(state, event)
|
|
32773
|
+
);
|
|
32774
|
+
} catch (error) {
|
|
32775
|
+
logInstrumentationError4("Pi Coding Agent event", error);
|
|
32776
|
+
}
|
|
32777
|
+
});
|
|
32778
|
+
piAgentEventSubscriptions.add(agent);
|
|
32779
|
+
} catch (error) {
|
|
32780
|
+
logInstrumentationError4("Pi Coding Agent event subscription", error);
|
|
31380
32781
|
}
|
|
31381
|
-
return void 0;
|
|
31382
32782
|
}
|
|
31383
|
-
function
|
|
32783
|
+
function makeInstrumentedStreamFn(agent, originalStreamFn) {
|
|
31384
32784
|
return async function instrumentedPiStreamFn(model, context, options) {
|
|
31385
|
-
const
|
|
31386
|
-
|
|
31387
|
-
|
|
31388
|
-
|
|
31389
|
-
context,
|
|
31390
|
-
options
|
|
31391
|
-
]);
|
|
31392
|
-
return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
|
|
32785
|
+
const invokeOriginal = () => Reflect.apply(originalStreamFn, this, [model, context, options]);
|
|
32786
|
+
const state = currentPiPromptState();
|
|
32787
|
+
if (!state || state.agent !== agent || state.finalized) {
|
|
32788
|
+
return invokeOriginal();
|
|
31393
32789
|
}
|
|
31394
|
-
state.sawStreamFn = true;
|
|
31395
|
-
removeQueuedPromptState(state);
|
|
31396
|
-
state.streamPatchState.eventPromptState = state;
|
|
31397
32790
|
const llmState = await startPiLlmSpan(state, model, context, options);
|
|
31398
32791
|
try {
|
|
31399
|
-
const stream = await runWithAutoInstrumentationSuppressed(
|
|
31400
|
-
() => Reflect.apply(patchState.originalStreamFn, this, [
|
|
31401
|
-
model,
|
|
31402
|
-
context,
|
|
31403
|
-
options
|
|
31404
|
-
])
|
|
31405
|
-
);
|
|
32792
|
+
const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
|
|
31406
32793
|
return patchAssistantMessageStream(stream, state, llmState);
|
|
31407
32794
|
} catch (error) {
|
|
31408
32795
|
finishPiLlmSpan(state, llmState, void 0, error);
|
|
@@ -31549,13 +32936,6 @@ async function handlePiAgentEvent(state, event) {
|
|
|
31549
32936
|
if (state.finalized) {
|
|
31550
32937
|
return;
|
|
31551
32938
|
}
|
|
31552
|
-
const eventPromptState = state.streamPatchState.eventPromptState;
|
|
31553
|
-
if (eventPromptState && eventPromptState !== state) {
|
|
31554
|
-
return;
|
|
31555
|
-
}
|
|
31556
|
-
if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
|
|
31557
|
-
return;
|
|
31558
|
-
}
|
|
31559
32939
|
switch (event.type) {
|
|
31560
32940
|
case "message_end":
|
|
31561
32941
|
if (isPiAssistantMessage(event.message)) {
|
|
@@ -31570,11 +32950,8 @@ async function handlePiAgentEvent(state, event) {
|
|
|
31570
32950
|
addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
|
|
31571
32951
|
}
|
|
31572
32952
|
}
|
|
31573
|
-
if (state.streamPatchState.eventPromptState === state) {
|
|
31574
|
-
state.streamPatchState.eventPromptState = void 0;
|
|
31575
|
-
}
|
|
31576
32953
|
if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
|
|
31577
|
-
|
|
32954
|
+
finishPiPromptRun(state);
|
|
31578
32955
|
}
|
|
31579
32956
|
return;
|
|
31580
32957
|
case "tool_execution_start":
|
|
@@ -31647,19 +33024,13 @@ function finishPiToolSpan(state, event) {
|
|
|
31647
33024
|
}
|
|
31648
33025
|
}
|
|
31649
33026
|
}
|
|
31650
|
-
|
|
33027
|
+
function finishPiPromptRun(state, error) {
|
|
31651
33028
|
if (state.finalized) {
|
|
31652
33029
|
return;
|
|
31653
33030
|
}
|
|
31654
33031
|
state.finalized = true;
|
|
31655
33032
|
state.onFinalize?.(state);
|
|
31656
|
-
|
|
31657
|
-
try {
|
|
31658
|
-
state.unsubscribeAgent?.();
|
|
31659
|
-
} catch (unsubscribeError) {
|
|
31660
|
-
logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
|
|
31661
|
-
}
|
|
31662
|
-
await finishOpenLlmSpans(state, error);
|
|
33033
|
+
finishOpenLlmSpans(state, error);
|
|
31663
33034
|
finishOpenToolSpans(state, error);
|
|
31664
33035
|
const metadata = {
|
|
31665
33036
|
...state.metadata,
|
|
@@ -31676,34 +33047,14 @@ async function finalizePiPromptRun(state, error) {
|
|
|
31676
33047
|
output: state.output
|
|
31677
33048
|
});
|
|
31678
33049
|
} finally {
|
|
31679
|
-
|
|
31680
|
-
|
|
31681
|
-
}
|
|
31682
|
-
|
|
31683
|
-
|
|
31684
|
-
patchState.activePromptStates.delete(state);
|
|
31685
|
-
removeQueuedPromptState(state);
|
|
31686
|
-
if (patchState.eventPromptState === state) {
|
|
31687
|
-
patchState.eventPromptState = void 0;
|
|
31688
|
-
}
|
|
31689
|
-
state.restorePromptContext?.();
|
|
31690
|
-
if (patchState.activePromptStates.size > 0) {
|
|
31691
|
-
return;
|
|
31692
|
-
}
|
|
31693
|
-
if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
|
|
31694
|
-
patchState.agent.streamFn = patchState.originalStreamFn;
|
|
31695
|
-
}
|
|
31696
|
-
piStreamPatchStates.delete(patchState.agent);
|
|
31697
|
-
}
|
|
31698
|
-
function removeQueuedPromptState(state) {
|
|
31699
|
-
state.queued = false;
|
|
31700
|
-
const queuedPromptStates = state.streamPatchState.queuedPromptStates;
|
|
31701
|
-
const index = queuedPromptStates.indexOf(state);
|
|
31702
|
-
if (index >= 0) {
|
|
31703
|
-
queuedPromptStates.splice(index, 1);
|
|
33050
|
+
try {
|
|
33051
|
+
state.span.end();
|
|
33052
|
+
} catch (endError) {
|
|
33053
|
+
logInstrumentationError4("Pi Coding Agent prompt end", endError);
|
|
33054
|
+
}
|
|
31704
33055
|
}
|
|
31705
33056
|
}
|
|
31706
|
-
|
|
33057
|
+
function finishOpenLlmSpans(state, error) {
|
|
31707
33058
|
for (const llmState of [...state.activeLlmSpans]) {
|
|
31708
33059
|
finishPiLlmSpan(state, llmState, void 0, error);
|
|
31709
33060
|
}
|
|
@@ -31784,7 +33135,7 @@ function normalizeAssistantMessage(message) {
|
|
|
31784
33135
|
(part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
|
|
31785
33136
|
).join("");
|
|
31786
33137
|
const toolCalls = message.content.flatMap(
|
|
31787
|
-
(part) => part.type === "toolCall" ? [
|
|
33138
|
+
(part) => part.type === "toolCall" ? [normalizeToolCall2(part)] : []
|
|
31788
33139
|
);
|
|
31789
33140
|
return {
|
|
31790
33141
|
role: "assistant",
|
|
@@ -31819,13 +33170,13 @@ function normalizeUserContent(content) {
|
|
|
31819
33170
|
return part;
|
|
31820
33171
|
});
|
|
31821
33172
|
}
|
|
31822
|
-
function
|
|
33173
|
+
function normalizeToolCall2(toolCall) {
|
|
31823
33174
|
return {
|
|
31824
33175
|
id: toolCall.id,
|
|
31825
33176
|
type: "function",
|
|
31826
33177
|
function: {
|
|
31827
33178
|
name: toolCall.name,
|
|
31828
|
-
arguments:
|
|
33179
|
+
arguments: stringifyArguments2(toolCall.arguments)
|
|
31829
33180
|
}
|
|
31830
33181
|
};
|
|
31831
33182
|
}
|
|
@@ -32008,7 +33359,7 @@ function cleanMetrics5(metrics) {
|
|
|
32008
33359
|
}
|
|
32009
33360
|
return cleaned;
|
|
32010
33361
|
}
|
|
32011
|
-
function
|
|
33362
|
+
function stringifyArguments2(value) {
|
|
32012
33363
|
if (typeof value === "string") {
|
|
32013
33364
|
return value;
|
|
32014
33365
|
}
|
|
@@ -33576,6 +34927,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
33576
34927
|
anthropicPlugin = null;
|
|
33577
34928
|
aiSDKPlugin = null;
|
|
33578
34929
|
claudeAgentSDKPlugin = null;
|
|
34930
|
+
cloudflareThinkPlugin = null;
|
|
33579
34931
|
cursorSDKPlugin = null;
|
|
33580
34932
|
openAIAgentsPlugin = null;
|
|
33581
34933
|
googleGenAIPlugin = null;
|
|
@@ -33584,6 +34936,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
33584
34936
|
openRouterPlugin = null;
|
|
33585
34937
|
openRouterAgentPlugin = null;
|
|
33586
34938
|
mistralPlugin = null;
|
|
34939
|
+
ollamaPlugin = null;
|
|
33587
34940
|
googleADKPlugin = null;
|
|
33588
34941
|
coherePlugin = null;
|
|
33589
34942
|
groqPlugin = null;
|
|
@@ -33623,6 +34976,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
33623
34976
|
this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
|
|
33624
34977
|
this.claudeAgentSDKPlugin.enable();
|
|
33625
34978
|
}
|
|
34979
|
+
if (integrations.cloudflareThink !== false) {
|
|
34980
|
+
this.cloudflareThinkPlugin = new CloudflareThinkPlugin();
|
|
34981
|
+
this.cloudflareThinkPlugin.enable();
|
|
34982
|
+
}
|
|
33626
34983
|
if (integrations.cursorSDK !== false && integrations.cursor !== false) {
|
|
33627
34984
|
this.cursorSDKPlugin = new CursorSDKPlugin();
|
|
33628
34985
|
this.cursorSDKPlugin.enable();
|
|
@@ -33653,6 +35010,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
33653
35010
|
this.mistralPlugin = new MistralPlugin();
|
|
33654
35011
|
this.mistralPlugin.enable();
|
|
33655
35012
|
}
|
|
35013
|
+
if (integrations.ollama !== false) {
|
|
35014
|
+
this.ollamaPlugin = new OllamaPlugin();
|
|
35015
|
+
this.ollamaPlugin.enable();
|
|
35016
|
+
}
|
|
33656
35017
|
if (integrations.googleADK !== false) {
|
|
33657
35018
|
this.googleADKPlugin = new GoogleADKPlugin();
|
|
33658
35019
|
this.googleADKPlugin.enable();
|
|
@@ -33729,6 +35090,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
33729
35090
|
this.claudeAgentSDKPlugin.disable();
|
|
33730
35091
|
this.claudeAgentSDKPlugin = null;
|
|
33731
35092
|
}
|
|
35093
|
+
if (this.cloudflareThinkPlugin) {
|
|
35094
|
+
this.cloudflareThinkPlugin.disable();
|
|
35095
|
+
this.cloudflareThinkPlugin = null;
|
|
35096
|
+
}
|
|
33732
35097
|
if (this.cursorSDKPlugin) {
|
|
33733
35098
|
this.cursorSDKPlugin.disable();
|
|
33734
35099
|
this.cursorSDKPlugin = null;
|
|
@@ -33761,6 +35126,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
33761
35126
|
this.mistralPlugin.disable();
|
|
33762
35127
|
this.mistralPlugin = null;
|
|
33763
35128
|
}
|
|
35129
|
+
if (this.ollamaPlugin) {
|
|
35130
|
+
this.ollamaPlugin.disable();
|
|
35131
|
+
this.ollamaPlugin = null;
|
|
35132
|
+
}
|
|
33764
35133
|
if (this.googleADKPlugin) {
|
|
33765
35134
|
this.googleADKPlugin.disable();
|
|
33766
35135
|
this.googleADKPlugin = null;
|
|
@@ -33846,6 +35215,7 @@ var envIntegrationAliases = {
|
|
|
33846
35215
|
cloudflareaichat: "cloudflareAIChat",
|
|
33847
35216
|
"cloudflare-ai-chat": "cloudflareAIChat",
|
|
33848
35217
|
"@cloudflare/ai-chat": "cloudflareAIChat",
|
|
35218
|
+
cloudflarethink: "cloudflareThink",
|
|
33849
35219
|
cursor: "cursor",
|
|
33850
35220
|
"cursor-sdk": "cursorSDK",
|
|
33851
35221
|
cursorsdk: "cursorSDK",
|
|
@@ -33866,6 +35236,7 @@ var envIntegrationAliases = {
|
|
|
33866
35236
|
openrouteragent: "openrouterAgent",
|
|
33867
35237
|
"openrouter-agent": "openrouterAgent",
|
|
33868
35238
|
mistral: "mistral",
|
|
35239
|
+
ollama: "ollama",
|
|
33869
35240
|
googleadk: "googleADK",
|
|
33870
35241
|
"google-adk": "googleADK",
|
|
33871
35242
|
cohere: "cohere",
|
|
@@ -33901,6 +35272,7 @@ function getDefaultInstrumentationIntegrations() {
|
|
|
33901
35272
|
huggingface: true,
|
|
33902
35273
|
claudeAgentSDK: true,
|
|
33903
35274
|
cloudflareAIChat: true,
|
|
35275
|
+
cloudflareThink: true,
|
|
33904
35276
|
cursor: true,
|
|
33905
35277
|
cursorSDK: true,
|
|
33906
35278
|
flue: true,
|
|
@@ -33909,6 +35281,7 @@ function getDefaultInstrumentationIntegrations() {
|
|
|
33909
35281
|
openrouter: true,
|
|
33910
35282
|
openrouterAgent: true,
|
|
33911
35283
|
mistral: true,
|
|
35284
|
+
ollama: true,
|
|
33912
35285
|
cohere: true,
|
|
33913
35286
|
groq: true,
|
|
33914
35287
|
bedrock: true,
|