braintrust 3.14.0 → 3.16.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.
Files changed (42) hide show
  1. package/dev/dist/index.js +655 -1059
  2. package/dev/dist/index.mjs +613 -1017
  3. package/dist/apply-auto-instrumentation.js +176 -186
  4. package/dist/apply-auto-instrumentation.mjs +6 -16
  5. package/dist/auto-instrumentations/bundler/esbuild.cjs +5 -39
  6. package/dist/auto-instrumentations/bundler/esbuild.mjs +1 -1
  7. package/dist/auto-instrumentations/bundler/next.cjs +5 -39
  8. package/dist/auto-instrumentations/bundler/next.mjs +2 -2
  9. package/dist/auto-instrumentations/bundler/rollup.cjs +5 -39
  10. package/dist/auto-instrumentations/bundler/rollup.mjs +1 -1
  11. package/dist/auto-instrumentations/bundler/vite.cjs +5 -39
  12. package/dist/auto-instrumentations/bundler/vite.mjs +1 -1
  13. package/dist/auto-instrumentations/bundler/webpack-loader.cjs +5 -39
  14. package/dist/auto-instrumentations/bundler/webpack.cjs +5 -39
  15. package/dist/auto-instrumentations/bundler/webpack.mjs +2 -2
  16. package/dist/auto-instrumentations/{chunk-OTUQ7KH5.mjs → chunk-CNQ7BUKN.mjs} +1 -1
  17. package/dist/auto-instrumentations/{chunk-XKAAVWT6.mjs → chunk-VXJONZVX.mjs} +5 -39
  18. package/dist/auto-instrumentations/hook.mjs +10 -40
  19. package/dist/browser.d.mts +75 -18
  20. package/dist/browser.d.ts +75 -18
  21. package/dist/browser.js +616 -1042
  22. package/dist/browser.mjs +616 -1042
  23. package/dist/{chunk-NU2GSPHX.mjs → chunk-O4ZIWXO3.mjs} +0 -24
  24. package/dist/{chunk-NKD77KGB.js → chunk-VMBQETG3.js} +0 -24
  25. package/dist/cli.js +614 -1018
  26. package/dist/edge-light.d.mts +1 -1
  27. package/dist/edge-light.d.ts +1 -1
  28. package/dist/edge-light.js +616 -1042
  29. package/dist/edge-light.mjs +616 -1042
  30. package/dist/index.d.mts +75 -18
  31. package/dist/index.d.ts +75 -18
  32. package/dist/index.js +1007 -1409
  33. package/dist/index.mjs +620 -1022
  34. package/dist/instrumentation/index.d.mts +11 -1
  35. package/dist/instrumentation/index.d.ts +11 -1
  36. package/dist/instrumentation/index.js +616 -1016
  37. package/dist/instrumentation/index.mjs +615 -1016
  38. package/dist/workerd.d.mts +1 -1
  39. package/dist/workerd.d.ts +1 -1
  40. package/dist/workerd.js +616 -1042
  41. package/dist/workerd.mjs +616 -1042
  42. package/package.json +1 -1
package/dist/workerd.mjs CHANGED
@@ -3702,7 +3702,7 @@ function btStreamParser() {
3702
3702
  },
3703
3703
  async transform(chunk, controller) {
3704
3704
  if (chunk instanceof Uint8Array) {
3705
- parser.feed(decoder.decode(chunk));
3705
+ parser.feed(decoder.decode(chunk, { stream: true }));
3706
3706
  } else if (typeof chunk === "string") {
3707
3707
  parser.feed(chunk);
3708
3708
  } else {
@@ -3710,6 +3710,10 @@ function btStreamParser() {
3710
3710
  }
3711
3711
  },
3712
3712
  async flush(controller) {
3713
+ const tail = decoder.decode();
3714
+ if (tail) {
3715
+ parser.feed(tail);
3716
+ }
3713
3717
  controller.terminate();
3714
3718
  }
3715
3719
  });
@@ -24039,825 +24043,440 @@ var flueChannels = defineChannels("@flue/runtime", {
24039
24043
  createContext: channel({
24040
24044
  channelName: "createFlueContext",
24041
24045
  kind: "sync-stream"
24042
- }),
24043
- openSession: channel({
24044
- channelName: "Harness.openSession",
24045
- kind: "async"
24046
- }),
24047
- contextEvent: channel({
24048
- channelName: "context.event",
24049
- kind: "sync-stream"
24050
- }),
24051
- prompt: channel({
24052
- channelName: "session.prompt",
24053
- kind: "async"
24054
- }),
24055
- skill: channel({
24056
- channelName: "session.skill",
24057
- kind: "async"
24058
- }),
24059
- task: channel({
24060
- channelName: "session.task",
24061
- kind: "async"
24062
- }),
24063
- compact: channel({
24064
- channelName: "session.compact",
24065
- kind: "async"
24066
24046
  })
24067
24047
  });
24068
24048
 
24069
- // src/wrappers/flue.ts
24070
- var WRAPPED_FLUE_CONTEXT = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-context");
24071
- var WRAPPED_FLUE_HARNESS = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-harness");
24072
- var WRAPPED_FLUE_SESSION = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-session");
24073
- var SUBSCRIBED_FLUE_CONTEXT_EVENTS = /* @__PURE__ */ Symbol.for(
24074
- "braintrust.flue.subscribed-context-events"
24075
- );
24076
- function wrapFlueContext(ctx) {
24077
- if (!isPlausibleFlueContext(ctx)) {
24078
- console.warn("Unsupported Flue context. Not wrapping.");
24079
- return ctx;
24049
+ // src/instrumentation/plugins/flue-plugin.ts
24050
+ var FLUE_AUTO_STATE = /* @__PURE__ */ Symbol.for("braintrust.flue.auto-state");
24051
+ var FLUE_OBSERVE_BRIDGE = /* @__PURE__ */ Symbol.for("braintrust.flue.observe-bridge");
24052
+ var braintrustFlueObserver = (event, ctx) => {
24053
+ getObserveBridge().handle(event, ctx);
24054
+ };
24055
+ var FluePlugin = class extends BasePlugin {
24056
+ onEnable() {
24057
+ this.unsubscribers.push(enableFlueAutoInstrumentation());
24080
24058
  }
24081
- const context = ctx;
24082
- subscribeFlueContextEvents(context, { captureTurnSpans: true });
24083
- return patchFlueContextInPlace(context);
24084
- }
24085
- function patchFlueContextInPlace(ctx) {
24086
- const context = ctx;
24087
- if (context[WRAPPED_FLUE_CONTEXT]) {
24088
- return ctx;
24059
+ onDisable() {
24060
+ for (const unsubscribe of this.unsubscribers) {
24061
+ unsubscribe();
24062
+ }
24063
+ this.unsubscribers = [];
24089
24064
  }
24090
- const originalInit = context.init.bind(context);
24091
- try {
24092
- Object.defineProperty(context, WRAPPED_FLUE_CONTEXT, {
24093
- configurable: false,
24094
- enumerable: false,
24095
- value: true
24096
- });
24097
- Object.defineProperty(context, "init", {
24098
- configurable: true,
24099
- value: async function wrappedFlueInit(options) {
24100
- const harness = await originalInit(options);
24101
- return wrapFlueHarness(harness);
24102
- },
24103
- writable: true
24104
- });
24105
- } catch {
24065
+ };
24066
+ function enableFlueAutoInstrumentation() {
24067
+ const state = getAutoState();
24068
+ state.refCount += 1;
24069
+ if (!state.handlers) {
24070
+ const channel2 = flueChannels.createContext.tracingChannel();
24071
+ const handlers = {
24072
+ end: (event) => {
24073
+ subscribeToFlueContext(event.result, state);
24074
+ }
24075
+ };
24076
+ channel2.subscribe(handlers);
24077
+ state.channel = channel2;
24078
+ state.handlers = handlers;
24106
24079
  }
24107
- return ctx;
24080
+ let released = false;
24081
+ return () => {
24082
+ if (released) {
24083
+ return;
24084
+ }
24085
+ released = true;
24086
+ releaseAutoState(state);
24087
+ };
24108
24088
  }
24109
- function wrapFlueSession(session) {
24110
- if (!isPlausibleFlueSession(session)) {
24111
- console.warn("Unsupported Flue session. Not wrapping.");
24112
- return session;
24089
+ function getAutoState() {
24090
+ const existing = Reflect.get(globalThis, FLUE_AUTO_STATE);
24091
+ if (isAutoState(existing)) {
24092
+ return existing;
24113
24093
  }
24114
- return patchFlueSessionInPlace(session);
24094
+ const state = {
24095
+ contexts: /* @__PURE__ */ new WeakSet(),
24096
+ refCount: 0
24097
+ };
24098
+ Reflect.set(globalThis, FLUE_AUTO_STATE, state);
24099
+ return state;
24115
24100
  }
24116
- function subscribeFlueContextEvents(ctx, options = {}) {
24117
- if (!ctx || typeof ctx !== "object" || typeof ctx.subscribeEvent !== "function") {
24118
- return void 0;
24119
- }
24120
- const context = ctx;
24121
- const captureTurnSpans = options.captureTurnSpans ?? true;
24122
- const existingSubscription = context[SUBSCRIBED_FLUE_CONTEXT_EVENTS];
24123
- if (existingSubscription) {
24124
- if (existingSubscription.captureTurnSpans || !captureTurnSpans) {
24125
- return void 0;
24126
- }
24127
- try {
24128
- existingSubscription.unsubscribe();
24129
- } catch {
24130
- }
24131
- }
24132
- try {
24133
- const unsubscribe = ctx.subscribeEvent((event) => {
24134
- flueChannels.contextEvent.traceSync(() => void 0, {
24135
- arguments: [event],
24136
- captureTurnSpans,
24137
- context: ctx
24138
- });
24139
- });
24140
- if (existingSubscription) {
24141
- existingSubscription.captureTurnSpans = captureTurnSpans;
24142
- existingSubscription.unsubscribe = unsubscribe;
24143
- } else {
24144
- Object.defineProperty(context, SUBSCRIBED_FLUE_CONTEXT_EVENTS, {
24145
- configurable: false,
24146
- enumerable: false,
24147
- value: {
24148
- captureTurnSpans,
24149
- unsubscribe
24150
- }
24151
- });
24152
- }
24153
- return unsubscribe;
24154
- } catch {
24155
- return void 0;
24101
+ function getObserveBridge() {
24102
+ const existing = Reflect.get(globalThis, FLUE_OBSERVE_BRIDGE);
24103
+ if (isFlueObserveBridge(existing)) {
24104
+ return existing;
24156
24105
  }
24106
+ const bridge = new FlueObserveBridge();
24107
+ Reflect.set(globalThis, FLUE_OBSERVE_BRIDGE, bridge);
24108
+ return bridge;
24157
24109
  }
24158
- function wrapFlueHarness(harness) {
24159
- if (!isPlausibleFlueHarness(harness)) {
24160
- return harness;
24161
- }
24162
- const target = harness;
24163
- if (target[WRAPPED_FLUE_HARNESS]) {
24164
- return harness;
24165
- }
24166
- const originalSession = target.session.bind(target);
24167
- try {
24168
- Object.defineProperty(target, WRAPPED_FLUE_HARNESS, {
24169
- configurable: false,
24170
- enumerable: false,
24171
- value: true
24172
- });
24173
- Object.defineProperty(target, "session", {
24174
- configurable: true,
24175
- value: async function wrappedFlueHarnessSession(name, options) {
24176
- const session = await originalSession(name, options);
24177
- return patchFlueSessionInPlace(session);
24178
- },
24179
- writable: true
24180
- });
24181
- const sessions = target.sessions;
24182
- if (sessions && typeof sessions === "object") {
24183
- patchFlueSessionFactory(sessions, "get");
24184
- patchFlueSessionFactory(sessions, "create");
24185
- }
24186
- } catch {
24187
- }
24188
- return harness;
24110
+ function isFlueObserveBridge(value) {
24111
+ return isObjectLike(value) && typeof Reflect.get(value, "handle") === "function" && typeof Reflect.get(value, "reset") === "function";
24189
24112
  }
24190
- function patchFlueSessionInPlace(session) {
24191
- if (session[WRAPPED_FLUE_SESSION]) {
24192
- return session;
24193
- }
24194
- try {
24195
- Object.defineProperty(session, WRAPPED_FLUE_SESSION, {
24196
- configurable: false,
24197
- enumerable: false,
24198
- value: true
24199
- });
24200
- patchCallHandleMethod(session, "prompt", flueChannels.prompt);
24201
- patchCallHandleMethod(session, "skill", flueChannels.skill);
24202
- patchCallHandleMethod(session, "task", flueChannels.task);
24203
- patchCompact(session);
24204
- } catch {
24205
- }
24206
- return session;
24113
+ function isAutoState(value) {
24114
+ return isObjectLike(value) && Reflect.get(value, "contexts") instanceof WeakSet && typeof Reflect.get(value, "refCount") === "number";
24207
24115
  }
24208
- function patchFlueSessionFactory(sessions, method) {
24209
- const original = sessions[method];
24210
- if (typeof original !== "function") {
24116
+ function releaseAutoState(state) {
24117
+ state.refCount -= 1;
24118
+ if (state.refCount > 0) {
24211
24119
  return;
24212
24120
  }
24213
- const bound = original.bind(sessions);
24214
- Object.defineProperty(sessions, method, {
24215
- configurable: true,
24216
- value: async function wrappedFlueSessionFactory(name, options) {
24217
- const session = await bound(name, options);
24218
- return patchFlueSessionInPlace(session);
24219
- },
24220
- writable: true
24221
- });
24222
- }
24223
- function patchCallHandleMethod(session, method, channel2) {
24224
- const original = session[method];
24225
- if (typeof original !== "function") {
24226
- return;
24121
+ try {
24122
+ if (state.channel && state.handlers) {
24123
+ state.channel.unsubscribe(state.handlers);
24124
+ }
24125
+ } finally {
24126
+ Reflect.deleteProperty(globalThis, FLUE_AUTO_STATE);
24227
24127
  }
24228
- const bound = original.bind(session);
24229
- Object.defineProperty(session, method, {
24230
- configurable: true,
24231
- value(input, options) {
24232
- const args = [input, options];
24233
- const { originalResult, traced: traced2 } = traceFlueOperation(channel2, {
24234
- context: {
24235
- arguments: args,
24236
- operation: method,
24237
- session
24238
- },
24239
- run: () => bound(input, options)
24240
- });
24241
- return preserveCallHandle(originalResult, traced2);
24242
- },
24243
- writable: true
24244
- });
24245
24128
  }
24246
- function patchCompact(session) {
24247
- const original = session.compact;
24248
- if (typeof original !== "function") {
24129
+ function subscribeToFlueContext(value, state) {
24130
+ if (!isObservableFlueContext(value) || state.contexts.has(value)) {
24249
24131
  return;
24250
24132
  }
24251
- const bound = original.bind(session);
24252
- Object.defineProperty(session, "compact", {
24253
- configurable: true,
24254
- value() {
24255
- const context = {
24256
- arguments: [],
24257
- operation: "compact",
24258
- session
24259
- };
24260
- return flueChannels.compact.tracePromise(() => bound(), context);
24261
- },
24262
- writable: true
24263
- });
24264
- }
24265
- function traceFlueOperation(channel2, args) {
24266
- const tracingChannel2 = channel2.tracingChannel();
24267
- const context = args.context;
24268
- let originalResult;
24269
- let traced2;
24270
- const run = () => {
24133
+ const ctx = flueContextFromUnknown(value);
24134
+ let released = false;
24135
+ let unsubscribe;
24136
+ const release = () => {
24137
+ if (released) {
24138
+ return;
24139
+ }
24140
+ released = true;
24271
24141
  try {
24272
- originalResult = args.run();
24273
- tracingChannel2.end?.publish(context);
24142
+ unsubscribe?.();
24274
24143
  } catch (error) {
24275
- context.error = normalizeError3(error);
24276
- tracingChannel2.error?.publish(context);
24277
- tracingChannel2.end?.publish(context);
24278
- throw error;
24144
+ logInstrumentationError3("Flue context unsubscribe", error);
24279
24145
  }
24280
- traced2 = Promise.resolve(originalResult).then(
24281
- (result) => {
24282
- context.result = result;
24283
- tracingChannel2.asyncStart?.publish(context);
24284
- tracingChannel2.asyncEnd?.publish(context);
24285
- return result;
24286
- },
24287
- (error) => {
24288
- context.error = normalizeError3(error);
24289
- tracingChannel2.error?.publish(context);
24290
- tracingChannel2.asyncStart?.publish(context);
24291
- tracingChannel2.asyncEnd?.publish(context);
24292
- throw error;
24293
- }
24294
- );
24295
24146
  };
24296
- if (tracingChannel2.start?.runStores) {
24297
- tracingChannel2.start.runStores(context, run);
24298
- } else {
24299
- tracingChannel2.start?.publish(context);
24300
- run();
24147
+ try {
24148
+ unsubscribe = value.subscribeEvent((event) => {
24149
+ if (state.refCount <= 0) {
24150
+ release();
24151
+ return;
24152
+ }
24153
+ braintrustFlueObserver(event, ctx);
24154
+ if (isAutoContextTerminalEvent(event, ctx)) {
24155
+ release();
24156
+ }
24157
+ });
24158
+ state.contexts.add(value);
24159
+ } catch (error) {
24160
+ logInstrumentationError3("Flue context subscription", error);
24301
24161
  }
24302
- return { originalResult, traced: traced2 };
24303
24162
  }
24304
- function normalizeError3(error) {
24305
- return error instanceof Error ? error : new Error(String(error));
24306
- }
24307
- function preserveCallHandle(originalHandle, traced2) {
24308
- if (!isFlueCallHandle(originalHandle)) {
24309
- return traced2;
24163
+ function isAutoContextTerminalEvent(event, ctx) {
24164
+ if (!isObjectLike(event)) {
24165
+ return false;
24310
24166
  }
24311
- const handle = originalHandle;
24312
- const wrapped = {
24313
- get signal() {
24314
- return handle.signal;
24315
- },
24316
- abort(reason) {
24317
- return handle.abort(reason);
24318
- },
24319
- then(onfulfilled, onrejected) {
24320
- return traced2.then(onfulfilled, onrejected);
24321
- }
24322
- };
24323
- return wrapped;
24167
+ const type = Reflect.get(event, "type");
24168
+ if (type === "run_end") {
24169
+ return true;
24170
+ }
24171
+ if (type !== "operation") {
24172
+ return false;
24173
+ }
24174
+ return !ctx?.runId && typeof Reflect.get(event, "runId") !== "string";
24324
24175
  }
24325
- function isPlausibleFlueContext(value) {
24326
- return !!value && typeof value === "object" && typeof value.init === "function";
24176
+ function isObservableFlueContext(value) {
24177
+ return isObjectLike(value) && typeof Reflect.get(value, "subscribeEvent") === "function";
24327
24178
  }
24328
- function isPlausibleFlueHarness(value) {
24329
- return !!value && typeof value === "object" && typeof value.session === "function";
24179
+ function isFlueEvent(event) {
24180
+ const type = Reflect.get(event, "type");
24181
+ return type === "run_start" || type === "run_end" || type === "operation_start" || type === "operation" || type === "turn_request" || type === "turn" || type === "tool_start" || type === "tool_call" || type === "task_start" || type === "task" || type === "compaction_start" || type === "compaction";
24330
24182
  }
24331
- function isPlausibleFlueSession(value) {
24332
- return !!value && typeof value === "object" && typeof value.prompt === "function" && typeof value.skill === "function" && typeof value.task === "function" && typeof value.compact === "function";
24183
+ function flueContextFromUnknown(ctx) {
24184
+ if (!isObjectLike(ctx)) {
24185
+ return void 0;
24186
+ }
24187
+ const id = Reflect.get(ctx, "id");
24188
+ const runId = Reflect.get(ctx, "runId");
24189
+ return {
24190
+ ...typeof id === "string" ? { id } : {},
24191
+ ...typeof runId === "string" ? { runId } : {}
24192
+ };
24333
24193
  }
24334
- function isFlueCallHandle(value) {
24335
- return !!value && typeof value === "object" && typeof value.then === "function" && typeof value.abort === "function" && "signal" in value;
24194
+ function isObjectLike(value) {
24195
+ return typeof value === "object" && value !== null && !Array.isArray(value);
24336
24196
  }
24337
-
24338
- // src/instrumentation/plugins/flue-plugin.ts
24339
- var FluePlugin = class extends BasePlugin {
24340
- activeOperationsById = /* @__PURE__ */ new Map();
24341
- activeOperationsByScope = /* @__PURE__ */ new Map();
24342
- compactionsByScope = /* @__PURE__ */ new Map();
24343
- pendingOperationsByKey = /* @__PURE__ */ new Map();
24197
+ var FlueObserveBridge = class {
24198
+ compactionsByKey = /* @__PURE__ */ new Map();
24199
+ operationsById = /* @__PURE__ */ new Map();
24200
+ runsById = /* @__PURE__ */ new Map();
24201
+ seenEvents = /* @__PURE__ */ new WeakSet();
24344
24202
  tasksById = /* @__PURE__ */ new Map();
24345
- toolsById = /* @__PURE__ */ new Map();
24346
- turnsByScope = /* @__PURE__ */ new Map();
24347
- onEnable() {
24348
- this.subscribeToContextCreation();
24349
- this.subscribeToSessionCreation();
24350
- this.subscribeToContextEvents();
24351
- this.subscribeToSessionOperations();
24352
- }
24353
- onDisable() {
24354
- for (const unsubscribe of this.unsubscribers) {
24355
- unsubscribe();
24203
+ toolsByKey = /* @__PURE__ */ new Map();
24204
+ turnsByKey = /* @__PURE__ */ new Map();
24205
+ handle(event, ctx) {
24206
+ if (!isObjectLike(event) || !isFlueEvent(event)) {
24207
+ return;
24356
24208
  }
24357
- this.unsubscribers = [];
24358
- this.activeOperationsById.clear();
24359
- this.activeOperationsByScope.clear();
24360
- this.compactionsByScope.clear();
24361
- this.pendingOperationsByKey.clear();
24209
+ if (this.seenEvents.has(event)) {
24210
+ return;
24211
+ }
24212
+ this.seenEvents.add(event);
24213
+ try {
24214
+ this.handleEvent(event, flueContextFromUnknown(ctx));
24215
+ } catch (error) {
24216
+ logInstrumentationError3("Flue observe", error);
24217
+ }
24218
+ }
24219
+ reset() {
24220
+ this.compactionsByKey.clear();
24221
+ this.operationsById.clear();
24222
+ this.runsById.clear();
24223
+ this.seenEvents = /* @__PURE__ */ new WeakSet();
24362
24224
  this.tasksById.clear();
24363
- this.toolsById.clear();
24364
- this.turnsByScope.clear();
24225
+ this.toolsByKey.clear();
24226
+ this.turnsByKey.clear();
24365
24227
  }
24366
- subscribeToContextCreation() {
24367
- const channel2 = flueChannels.createContext.tracingChannel();
24368
- const handlers = {
24369
- end: (event) => {
24370
- const ctx = event.result;
24371
- if (!ctx) {
24372
- return;
24373
- }
24374
- subscribeFlueContextEvents(ctx, { captureTurnSpans: false });
24375
- patchFlueContextInPlace(ctx);
24376
- },
24377
- error: () => {
24378
- }
24379
- };
24380
- channel2.subscribe(handlers);
24381
- this.unsubscribers.push(() => {
24382
- channel2.unsubscribe(handlers);
24383
- });
24228
+ handleEvent(event, ctx) {
24229
+ switch (event.type) {
24230
+ case "run_start":
24231
+ this.handleRunStart(event, ctx);
24232
+ return;
24233
+ case "run_end":
24234
+ this.handleRunEnd(event);
24235
+ return;
24236
+ case "operation_start":
24237
+ this.handleOperationStart(event);
24238
+ return;
24239
+ case "operation":
24240
+ this.handleOperation(event);
24241
+ return;
24242
+ case "turn_request":
24243
+ this.handleTurnRequest(event);
24244
+ return;
24245
+ case "turn":
24246
+ this.handleTurn(event);
24247
+ return;
24248
+ case "tool_start":
24249
+ this.handleToolStart(event);
24250
+ return;
24251
+ case "tool_call":
24252
+ this.handleToolCall(event);
24253
+ return;
24254
+ case "task_start":
24255
+ this.handleTaskStart(event);
24256
+ return;
24257
+ case "task":
24258
+ this.handleTask(event);
24259
+ return;
24260
+ case "compaction_start":
24261
+ this.handleCompactionStart(event);
24262
+ return;
24263
+ case "compaction":
24264
+ this.handleCompaction(event);
24265
+ return;
24266
+ default:
24267
+ return;
24268
+ }
24384
24269
  }
24385
- subscribeToSessionCreation() {
24386
- const channel2 = flueChannels.openSession.tracingChannel();
24387
- const handlers = {
24388
- asyncEnd: (event) => {
24389
- if (event.result) {
24390
- patchFlueSessionInPlace(
24391
- event.result
24392
- );
24393
- }
24394
- if (event.harness) {
24395
- wrapFlueHarness(event.harness);
24396
- }
24397
- },
24398
- error: () => {
24399
- }
24270
+ handleRunStart(event, ctx) {
24271
+ if (!event.runId) {
24272
+ return;
24273
+ }
24274
+ const workflowName = event.workflowName ?? event.owner?.workflowName ?? (typeof ctx?.id === "string" ? ctx.id : "unknown");
24275
+ const metadata = {
24276
+ ...extractPayloadMetadata(event.payload),
24277
+ ...extractEventMetadata(event, ctx),
24278
+ ...workflowName ? { "flue.workflow_name": workflowName } : {},
24279
+ provider: "flue"
24400
24280
  };
24401
- channel2.subscribe(handlers);
24402
- this.unsubscribers.push(() => {
24403
- channel2.unsubscribe(handlers);
24281
+ const span = startSpan({
24282
+ name: `workflow:${workflowName}`,
24283
+ spanAttributes: { type: "task" /* TASK */ },
24284
+ startTime: eventTime(event.startedAt ?? event.timestamp),
24285
+ event: {
24286
+ input: event.payload,
24287
+ metadata
24288
+ }
24404
24289
  });
24290
+ this.runsById.set(event.runId, { metadata, span });
24405
24291
  }
24406
- subscribeToSessionOperations() {
24407
- this.subscribeToSessionOperation(flueChannels.prompt);
24408
- this.subscribeToSessionOperation(flueChannels.skill);
24409
- this.subscribeToSessionOperation(flueChannels.task);
24410
- this.subscribeToCompact();
24411
- }
24412
- subscribeToSessionOperation(channel2) {
24413
- const tracingChannel2 = channel2.tracingChannel();
24414
- const states = /* @__PURE__ */ new WeakMap();
24415
- const ensureState2 = (event) => {
24416
- const existing = states.get(event);
24417
- if (existing) {
24418
- return existing;
24419
- }
24420
- const state = this.startOperationState({
24421
- args: event.arguments,
24422
- moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
24423
- operation: event.operation,
24424
- session: event.session
24292
+ handleRunEnd(event) {
24293
+ const state = this.runsById.get(event.runId);
24294
+ this.finishPendingSpansForRun(event);
24295
+ if (state) {
24296
+ safeLog3(state.span, {
24297
+ ...event.isError ? { error: errorToString(event.error) } : {},
24298
+ metadata: {
24299
+ ...state.metadata,
24300
+ ...extractEventMetadata(event),
24301
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24302
+ },
24303
+ metrics: durationMetrics2(event.durationMs),
24304
+ output: event.result
24425
24305
  });
24426
- states.set(event, state);
24427
- return state;
24428
- };
24429
- const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
24430
- tracingChannel2,
24431
- ensureState2
24432
- );
24433
- const handlers = {
24434
- start: (event) => {
24435
- ensureState2(event);
24436
- },
24437
- asyncEnd: (event) => {
24438
- this.endOperationState(states.get(event), event.result);
24439
- states.delete(event);
24440
- },
24441
- error: (event) => {
24442
- const state = states.get(event);
24443
- if (state && event.error) {
24444
- safeLog3(state.span, { error: errorToString(event.error) });
24445
- this.finishOperationState(state);
24446
- }
24447
- states.delete(event);
24448
- }
24449
- };
24450
- tracingChannel2.subscribe(handlers);
24451
- this.unsubscribers.push(() => {
24452
- unbindCurrentSpanStore?.();
24453
- tracingChannel2.unsubscribe(handlers);
24306
+ safeEnd(state.span, eventTime(event.timestamp));
24307
+ this.runsById.delete(event.runId);
24308
+ }
24309
+ void flush().catch((error) => {
24310
+ logInstrumentationError3("Flue flush", error);
24454
24311
  });
24455
24312
  }
24456
- subscribeToCompact() {
24457
- const tracingChannel2 = flueChannels.compact.tracingChannel();
24458
- const states = /* @__PURE__ */ new WeakMap();
24459
- const ensureState2 = (event) => {
24460
- const existing = states.get(event);
24461
- if (existing) {
24462
- return existing;
24463
- }
24464
- const state = this.startOperationState({
24465
- args: [],
24466
- moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
24467
- operation: event.operation,
24468
- session: event.session
24469
- });
24470
- states.set(event, state);
24471
- return state;
24472
- };
24473
- const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
24474
- tracingChannel2,
24475
- ensureState2
24476
- );
24477
- const handlers = {
24478
- start: (event) => {
24479
- ensureState2(event);
24480
- },
24481
- asyncEnd: (event) => {
24482
- this.endOperationState(states.get(event), void 0);
24483
- states.delete(event);
24484
- },
24485
- error: (event) => {
24486
- const state = states.get(event);
24487
- if (state && event.error) {
24488
- safeLog3(state.span, { error: errorToString(event.error) });
24489
- this.finishOperationState(state);
24490
- }
24491
- states.delete(event);
24492
- }
24493
- };
24494
- tracingChannel2.subscribe(handlers);
24495
- this.unsubscribers.push(() => {
24496
- unbindCurrentSpanStore?.();
24497
- tracingChannel2.unsubscribe(handlers);
24498
- });
24499
- }
24500
- subscribeToContextEvents() {
24501
- const channel2 = flueChannels.contextEvent.tracingChannel();
24502
- const handlers = {
24503
- start: (event) => {
24504
- const flueEvent = event.arguments[0];
24505
- if (!flueEvent) {
24506
- return;
24507
- }
24508
- try {
24509
- this.handleFlueEvent(flueEvent, {
24510
- captureTurnSpans: event.captureTurnSpans !== false
24511
- });
24512
- } catch (error) {
24513
- logInstrumentationError3("Flue event", error);
24514
- }
24515
- },
24516
- error: () => {
24517
- }
24518
- };
24519
- channel2.subscribe(handlers);
24520
- this.unsubscribers.push(() => {
24521
- channel2.unsubscribe(handlers);
24522
- });
24523
- }
24524
- bindCurrentSpanStoreToOperationStart(tracingChannel2, ensureState2) {
24525
- const state = _internalGetGlobalState();
24526
- const startChannel = tracingChannel2.start;
24527
- const contextManager = state?.contextManager;
24528
- const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
24529
- if (!currentSpanStore || !startChannel) {
24530
- return void 0;
24531
- }
24532
- startChannel.bindStore(currentSpanStore, (event) => {
24533
- const operationState = ensureState2(event);
24534
- return contextManager.wrapSpanForStore(operationState.span);
24535
- });
24536
- return () => {
24537
- startChannel.unbindStore(currentSpanStore);
24538
- };
24539
- }
24540
- startOperationState(args) {
24541
- const sessionName = getSessionName(args.session);
24542
- const metadata = {
24543
- ...extractOperationInputMetadata(args.operation, args.args),
24544
- ...extractSessionMetadata(args.session),
24545
- "flue.operation": args.operation,
24546
- provider: "flue",
24547
- ...args.moduleVersion ? { "flue.version": args.moduleVersion } : {}
24548
- };
24549
- const span = startSpan({
24550
- name: `flue.session.${args.operation}`,
24551
- spanAttributes: { type: "task" /* TASK */ }
24552
- });
24553
- const state = {
24554
- metadata,
24555
- operation: args.operation,
24556
- sessionName,
24557
- span,
24558
- startTime: getCurrentUnixTimestamp()
24559
- };
24560
- safeLog3(span, {
24561
- input: extractOperationInput(args.operation, args.args),
24562
- metadata
24563
- });
24564
- this.pendingOperationQueue(operationKey(sessionName, args.operation)).push(
24565
- state
24566
- );
24567
- addOperationToScope(
24568
- this.activeOperationsByScope,
24569
- sessionName ?? "unknown",
24570
- state
24571
- );
24572
- return state;
24573
- }
24574
- endOperationState(state, result) {
24575
- if (!state) {
24576
- return;
24577
- }
24578
- const metadata = {
24579
- ...state.metadata,
24580
- ...extractPromptResponseMetadata(result)
24581
- };
24582
- const metrics = {
24583
- ...buildDurationMetrics3(state.startTime),
24584
- ...metricsFromUsage(result?.usage)
24585
- };
24586
- safeLog3(state.span, {
24587
- metadata,
24588
- metrics,
24589
- output: extractOperationOutput(result)
24590
- });
24591
- this.finishCompactionsForOperation(state);
24592
- this.finishOperationState(state);
24593
- }
24594
- finishOperationState(state) {
24595
- removePendingOperation(this.pendingOperationsByKey, state);
24596
- if (state.operationId) {
24597
- this.activeOperationsById.delete(state.operationId);
24598
- }
24599
- removeScopedOperation(this.activeOperationsByScope, state);
24600
- state.span.end();
24601
- }
24602
- handleFlueEvent(event, options) {
24603
- switch (event.type) {
24604
- case "operation_start":
24605
- this.handleOperationStart(event);
24606
- return;
24607
- case "operation":
24608
- this.handleOperation(event);
24609
- return;
24610
- case "text_delta":
24611
- if (!options.captureTurnSpans) {
24612
- return;
24613
- }
24614
- this.ensureTurnState(event).text.push(
24615
- typeof event.text === "string" ? event.text : ""
24616
- );
24617
- return;
24618
- case "thinking_start":
24619
- if (!options.captureTurnSpans) {
24620
- return;
24621
- }
24622
- this.handleThinkingStart(event);
24623
- return;
24624
- case "thinking_delta":
24625
- if (!options.captureTurnSpans) {
24626
- return;
24627
- }
24628
- this.handleThinkingDelta(event);
24629
- return;
24630
- case "thinking_end":
24631
- if (!options.captureTurnSpans) {
24632
- return;
24633
- }
24634
- this.handleThinkingEnd(event);
24635
- return;
24636
- case "turn":
24637
- if (!options.captureTurnSpans) {
24638
- return;
24639
- }
24640
- this.handleTurn(event);
24641
- return;
24642
- case "tool_start":
24643
- this.handleToolStart(event, options);
24644
- return;
24645
- case "tool_call":
24646
- this.handleToolCall(event);
24647
- return;
24648
- case "task_start":
24649
- this.handleTaskStart(event);
24650
- return;
24651
- case "task":
24652
- this.handleTask(event);
24653
- return;
24654
- case "compaction_start":
24655
- this.handleCompactionStart(event);
24656
- return;
24657
- case "compaction":
24658
- this.handleCompaction(event);
24659
- return;
24660
- default:
24661
- return;
24662
- }
24663
- }
24664
24313
  handleOperationStart(event) {
24665
- if (!isInstrumentedOperation(event.operationKind)) {
24666
- return;
24667
- }
24668
- const state = this.takePendingOperationForEvent(event);
24669
- if (!state) {
24314
+ if (!event.operationId || !isInstrumentedOperation(event.operationKind)) {
24670
24315
  return;
24671
24316
  }
24672
- state.operationId = event.operationId;
24673
- this.activeOperationsById.set(event.operationId, state);
24674
- addScopedOperation(this.activeOperationsByScope, event, state);
24675
- state.metadata = {
24676
- ...state.metadata,
24317
+ const metadata = {
24677
24318
  ...extractEventMetadata(event),
24678
- "flue.operation_id": event.operationId
24319
+ "flue.operation": event.operationKind,
24320
+ provider: "flue"
24679
24321
  };
24680
- safeLog3(state.span, { metadata: state.metadata });
24322
+ const parent = this.parentSpanForEvent(event);
24323
+ const span = startFlueSpan(parent, {
24324
+ name: `flue.${event.operationKind}`,
24325
+ spanAttributes: { type: "task" /* TASK */ },
24326
+ startTime: eventTime(event.timestamp),
24327
+ event: { metadata }
24328
+ });
24329
+ this.operationsById.set(event.operationId, { metadata, span });
24681
24330
  }
24682
24331
  handleOperation(event) {
24683
- const state = event.operationId ? this.activeOperationsById.get(event.operationId) : void 0;
24684
- if (!state) {
24332
+ if (!isInstrumentedOperation(event.operationKind)) {
24685
24333
  return;
24686
24334
  }
24335
+ const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
24336
+ const output = operationOutput(event);
24687
24337
  const metadata = {
24688
24338
  ...state.metadata,
24689
24339
  ...extractEventMetadata(event),
24690
- ...typeof event.durationMs === "number" ? { "flue.duration_ms": event.durationMs } : {},
24691
- ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24340
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
24341
+ ...event.usage ? { "flue.usage": event.usage } : {}
24692
24342
  };
24693
- const metrics = metricsFromUsage(event.usage);
24343
+ this.finishPendingChildrenForOperation(event, output);
24694
24344
  safeLog3(state.span, {
24695
- ...event.error ? { error: errorToString(event.error) } : {},
24345
+ ...event.isError ? { error: errorToString(event.error) } : {},
24696
24346
  metadata,
24697
- ...Object.keys(metrics).length ? { metrics } : {}
24347
+ metrics: durationMetrics2(event.durationMs),
24348
+ output
24698
24349
  });
24350
+ safeEnd(state.span, eventTime(event.timestamp));
24351
+ this.operationsById.delete(event.operationId);
24699
24352
  }
24700
- ensureTurnState(event) {
24701
- const scope = scopeKey(event);
24702
- const existing = this.turnsByScope.get(scope);
24703
- if (existing) {
24704
- return existing;
24353
+ handleTurnRequest(event) {
24354
+ const key = turnKey(event);
24355
+ if (!key) {
24356
+ return;
24705
24357
  }
24706
- const parent = this.parentSpanForEvent(event);
24707
24358
  const metadata = {
24708
24359
  ...extractEventMetadata(event),
24709
- provider: "flue"
24360
+ ...event.api ? { "flue.api": event.api } : {},
24361
+ ...event.model ? { model: event.model, "flue.model": event.model } : {},
24362
+ ...event.provider ? { provider: event.provider } : { provider: "flue" },
24363
+ ...event.provider ? { "flue.provider": event.provider } : {},
24364
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
24365
+ ...event.reasoning ? { reasoning: event.reasoning } : {},
24366
+ ...event.input?.systemPrompt ? { "flue.system_prompt": event.input.systemPrompt } : {},
24367
+ ...event.input?.tools ? { tools: event.input.tools } : {}
24710
24368
  };
24369
+ const parent = this.parentSpanForTurn(event);
24711
24370
  const span = startFlueSpan(parent, {
24712
- name: "flue.turn",
24713
- spanAttributes: { type: "llm" /* LLM */ }
24371
+ name: `llm:${event.model ?? event.purpose ?? "unknown"}`,
24372
+ spanAttributes: { type: "llm" /* LLM */ },
24373
+ startTime: eventTime(event.timestamp),
24374
+ event: {
24375
+ input: event.input?.messages,
24376
+ metadata
24377
+ }
24714
24378
  });
24715
- const state = {
24716
- metadata,
24717
- span,
24718
- hasThinking: false,
24719
- startTime: getCurrentUnixTimestamp(),
24720
- text: [],
24721
- thinking: [],
24722
- toolCalls: []
24723
- };
24724
- safeLog3(span, { metadata });
24725
- this.turnsByScope.set(scope, state);
24726
- return state;
24379
+ this.logOperationInput(
24380
+ event.operationId,
24381
+ event.input?.messages ?? event.input
24382
+ );
24383
+ this.turnsByKey.set(key, { metadata, span });
24727
24384
  }
24728
24385
  handleTurn(event) {
24729
- const scope = scopeKey(event);
24730
- const state = this.ensureTurnState(event);
24731
- const text = state.text.join("");
24732
- const reasoning = state.finalThinking ?? state.thinking.join("");
24733
- const outputReasoning = reasoning || (state.hasThinking ? "[reasoning stream present; content unavailable]" : void 0);
24386
+ const key = turnKey(event);
24387
+ if (!key) {
24388
+ return;
24389
+ }
24390
+ const state = this.turnsByKey.get(key) ?? this.startSyntheticTurn(event);
24734
24391
  const metadata = {
24735
24392
  ...state.metadata,
24736
24393
  ...extractEventMetadata(event),
24394
+ ...event.api ? { "flue.api": event.api } : {},
24737
24395
  ...event.model ? { model: event.model, "flue.model": event.model } : {},
24396
+ ...event.provider ? { provider: event.provider } : {},
24397
+ ...event.provider ? { "flue.provider": event.provider } : {},
24398
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
24738
24399
  ...event.stopReason ? { "flue.stop_reason": event.stopReason } : {},
24739
- ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
24740
- provider: "flue"
24400
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24741
24401
  };
24742
24402
  safeLog3(state.span, {
24743
- ...event.error ? { error: errorToString(event.error) } : {},
24403
+ ...event.isError ? { error: errorToString(event.error) } : {},
24744
24404
  metadata,
24745
24405
  metrics: {
24746
- ...durationMsMetrics(event.durationMs),
24406
+ ...durationMetrics2(event.durationMs),
24747
24407
  ...metricsFromUsage(event.usage)
24748
24408
  },
24749
- output: toAssistantOutput(
24750
- text,
24751
- event.stopReason,
24752
- outputReasoning,
24753
- state.toolCalls
24754
- )
24409
+ output: event.output
24755
24410
  });
24756
- state.span.end();
24757
- this.turnsByScope.delete(scope);
24411
+ safeEnd(state.span, eventTime(event.timestamp));
24412
+ this.turnsByKey.delete(key);
24758
24413
  }
24759
- handleThinkingDelta(event) {
24760
- const delta = event.delta;
24761
- if (typeof delta !== "string" || !delta) {
24414
+ handleToolStart(event) {
24415
+ if (!event.toolCallId) {
24762
24416
  return;
24763
24417
  }
24764
- const state = this.ensureTurnState(event);
24765
- state.hasThinking = true;
24766
- state.metadata["flue.thinking"] = true;
24767
- state.thinking.push(delta);
24768
- }
24769
- handleThinkingStart(event) {
24770
- const state = this.ensureTurnState(event);
24771
- state.hasThinking = true;
24772
- state.metadata["flue.thinking"] = true;
24773
- }
24774
- handleThinkingEnd(event) {
24775
- const state = this.ensureTurnState(event);
24776
- state.hasThinking = true;
24777
- state.metadata["flue.thinking"] = true;
24778
- if (typeof event.content === "string" && event.content) {
24779
- state.finalThinking = event.content;
24780
- }
24781
- }
24782
- handleToolStart(event, options) {
24783
- const toolCallId = event.toolCallId;
24784
- if (!toolCallId) {
24785
- return;
24786
- }
24787
- const parent = this.parentSpanForEvent(event);
24788
- const scope = scopeKey(event);
24789
- let turnState = this.turnsByScope.get(scope);
24790
- if (!turnState && parent && options.captureTurnSpans) {
24791
- turnState = this.ensureTurnState(event);
24792
- }
24793
24418
  const metadata = {
24794
24419
  ...extractEventMetadata(event),
24795
24420
  ...event.toolName ? { "flue.tool_name": event.toolName } : {},
24796
- "flue.tool_call_id": toolCallId,
24421
+ "flue.tool_call_id": event.toolCallId,
24797
24422
  provider: "flue"
24798
24423
  };
24424
+ const parent = this.parentSpanForTool(event);
24799
24425
  const span = startFlueSpan(parent, {
24800
- name: `tool: ${event.toolName ?? "unknown"}`,
24801
- spanAttributes: { type: "tool" /* TOOL */ }
24802
- });
24803
- if (turnState) {
24804
- turnState.toolCalls.push({
24805
- args: event.args,
24806
- toolCallId,
24807
- toolName: event.toolName
24808
- });
24809
- }
24810
- safeLog3(span, {
24811
- input: event.args,
24812
- metadata
24813
- });
24814
- this.toolsById.set(toolKey(event), {
24815
- metadata,
24816
- span,
24817
- startTime: getCurrentUnixTimestamp()
24426
+ name: `tool:${event.toolName ?? "unknown"}`,
24427
+ spanAttributes: { type: "tool" /* TOOL */ },
24428
+ startTime: eventTime(event.timestamp),
24429
+ event: {
24430
+ input: event.args,
24431
+ metadata
24432
+ }
24818
24433
  });
24434
+ this.toolsByKey.set(toolKey(event), { metadata, span });
24819
24435
  }
24820
24436
  handleToolCall(event) {
24437
+ if (!event.toolCallId) {
24438
+ return;
24439
+ }
24821
24440
  const key = toolKey(event);
24822
- const state = this.toolsById.get(key) ?? this.startSyntheticToolState(event, event.toolName ?? "unknown");
24441
+ const state = this.toolsByKey.get(key) ?? this.startSyntheticTool(event);
24823
24442
  const metadata = {
24824
24443
  ...state.metadata,
24825
24444
  ...extractEventMetadata(event),
24826
24445
  ...event.toolName ? { "flue.tool_name": event.toolName } : {},
24827
- ...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
24446
+ "flue.tool_call_id": event.toolCallId,
24828
24447
  ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24829
24448
  };
24830
24449
  safeLog3(state.span, {
24831
24450
  ...event.isError ? { error: errorToString(event.result) } : {},
24832
24451
  metadata,
24833
- metrics: durationMsMetrics(event.durationMs),
24452
+ metrics: durationMetrics2(event.durationMs),
24834
24453
  output: event.result
24835
24454
  });
24836
- state.span.end();
24837
- this.toolsById.delete(key);
24455
+ safeEnd(state.span, eventTime(event.timestamp));
24456
+ this.toolsByKey.delete(key);
24838
24457
  }
24839
24458
  handleTaskStart(event) {
24840
- const parent = this.parentSpanForEvent(event);
24459
+ if (!event.taskId) {
24460
+ return;
24461
+ }
24841
24462
  const metadata = {
24842
24463
  ...extractEventMetadata(event),
24843
- ...event.role ? { "flue.role": event.role } : {},
24464
+ ...event.agent ? { "flue.agent": event.agent } : {},
24844
24465
  ...event.cwd ? { "flue.cwd": event.cwd } : {},
24845
24466
  "flue.task_id": event.taskId,
24846
24467
  provider: "flue"
24847
24468
  };
24469
+ const parent = this.parentSpanForEvent(event);
24848
24470
  const span = startFlueSpan(parent, {
24849
- name: "flue.task",
24850
- spanAttributes: { type: "task" /* TASK */ }
24851
- });
24852
- safeLog3(span, {
24853
- input: event.prompt,
24854
- metadata
24855
- });
24856
- this.tasksById.set(event.taskId, {
24857
- metadata,
24858
- span,
24859
- startTime: getCurrentUnixTimestamp()
24471
+ name: event.agent ? `task:${event.agent}` : "flue.task",
24472
+ spanAttributes: { type: "task" /* TASK */ },
24473
+ startTime: eventTime(event.timestamp),
24474
+ event: {
24475
+ input: event.prompt,
24476
+ metadata
24477
+ }
24860
24478
  });
24479
+ this.tasksById.set(event.taskId, { metadata, span });
24861
24480
  }
24862
24481
  handleTask(event) {
24863
24482
  const state = this.tasksById.get(event.taskId);
@@ -24869,426 +24488,372 @@ var FluePlugin = class extends BasePlugin {
24869
24488
  metadata: {
24870
24489
  ...state.metadata,
24871
24490
  ...extractEventMetadata(event),
24491
+ ...event.agent ? { "flue.agent": event.agent } : {},
24872
24492
  ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24873
24493
  },
24874
- metrics: durationMsMetrics(event.durationMs),
24494
+ metrics: durationMetrics2(event.durationMs),
24875
24495
  output: event.result
24876
24496
  });
24877
- state.span.end();
24497
+ safeEnd(state.span, eventTime(event.timestamp));
24878
24498
  this.tasksById.delete(event.taskId);
24879
24499
  }
24880
24500
  handleCompactionStart(event) {
24881
- const operationState = this.operationStateForEvent(event);
24882
- const parent = operationState?.span ?? this.parentSpanForEvent(event);
24501
+ const key = compactionKey(event);
24502
+ const input = {
24503
+ ...event.estimatedTokens !== void 0 ? { estimatedTokens: event.estimatedTokens } : {},
24504
+ ...event.reason ? { reason: event.reason } : {}
24505
+ };
24883
24506
  const metadata = {
24884
24507
  ...extractEventMetadata(event),
24885
24508
  ...event.reason ? { "flue.compaction_reason": event.reason } : {},
24886
24509
  provider: "flue"
24887
24510
  };
24888
- const input = {
24889
- ...typeof event.estimatedTokens === "number" ? { estimatedTokens: event.estimatedTokens } : {},
24890
- ...event.reason ? { reason: event.reason } : {}
24891
- };
24511
+ const parent = this.parentSpanForEvent(event);
24892
24512
  const span = startFlueSpan(parent, {
24893
- name: "flue.compaction",
24894
- spanAttributes: { type: "task" /* TASK */ }
24895
- });
24896
- safeLog3(span, {
24897
- input,
24898
- metadata
24899
- });
24900
- this.compactionsByScope.set(scopeKey(event), {
24901
- input,
24902
- metadata,
24903
- operationState,
24904
- span,
24905
- startTime: getCurrentUnixTimestamp()
24513
+ name: `compaction:${event.reason ?? "unknown"}`,
24514
+ spanAttributes: { type: "task" /* TASK */ },
24515
+ startTime: eventTime(event.timestamp),
24516
+ event: {
24517
+ input,
24518
+ metadata
24519
+ }
24906
24520
  });
24521
+ this.logOperationInput(event.operationId, input);
24522
+ this.compactionsByKey.set(key, { metadata, span });
24907
24523
  }
24908
24524
  handleCompaction(event) {
24909
- const key = scopeKey(event);
24910
- const state = this.compactionsByScope.get(key) ?? this.findCompactionState(event);
24911
- if (!state) {
24912
- return;
24913
- }
24525
+ const key = compactionKey(event);
24526
+ const state = this.compactionsByKey.get(key) ?? this.startSyntheticCompaction(event);
24527
+ const metadata = {
24528
+ ...state.metadata,
24529
+ ...extractEventMetadata(event),
24530
+ ...event.usage ? { "flue.usage": event.usage } : {}
24531
+ };
24914
24532
  safeLog3(state.span, {
24915
- metadata: {
24916
- ...state.metadata,
24917
- ...extractEventMetadata(event),
24918
- ...typeof event.messagesBefore === "number" ? { "flue.messages_before": event.messagesBefore } : {},
24919
- ...typeof event.messagesAfter === "number" ? { "flue.messages_after": event.messagesAfter } : {}
24920
- },
24533
+ metadata,
24921
24534
  metrics: {
24922
- ...durationMsMetrics(event.durationMs),
24923
- ...metricsFromUsage(event.usage)
24535
+ ...durationMetrics2(event.durationMs),
24536
+ ...typeof event.messagesBefore === "number" ? { messages_before: event.messagesBefore } : {},
24537
+ ...typeof event.messagesAfter === "number" ? { messages_after: event.messagesAfter } : {}
24924
24538
  },
24925
24539
  output: {
24926
24540
  messagesAfter: event.messagesAfter,
24927
24541
  messagesBefore: event.messagesBefore
24928
24542
  }
24929
24543
  });
24930
- state.span.end();
24931
- this.deleteCompactionState(state);
24544
+ safeEnd(state.span, eventTime(event.timestamp));
24545
+ this.compactionsByKey.delete(key);
24932
24546
  }
24933
- findCompactionState(event) {
24934
- const operationState = this.operationStateForEvent(event);
24935
- for (const state of this.compactionsByScope.values()) {
24936
- if (operationState && state.operationState === operationState) {
24937
- return state;
24547
+ parentSpanForTurn(event) {
24548
+ if (event.purpose === "compaction" || event.purpose === "compaction_prefix") {
24549
+ const compaction = this.compactionsByKey.get(compactionKey(event));
24550
+ if (compaction) {
24551
+ return compaction.span;
24938
24552
  }
24939
24553
  }
24940
- return void 0;
24554
+ return this.parentSpanForEvent(event);
24941
24555
  }
24942
- finishCompactionsForOperation(operationState) {
24943
- for (const state of [...this.compactionsByScope.values()]) {
24944
- if (state.operationState !== operationState) {
24945
- continue;
24556
+ parentSpanForEvent(event) {
24557
+ const turn = turnKey(event);
24558
+ if (turn) {
24559
+ const turnState = this.turnsByKey.get(turn);
24560
+ if (turnState) {
24561
+ return turnState.span;
24946
24562
  }
24947
- safeLog3(state.span, {
24948
- input: state.input,
24949
- metadata: state.metadata,
24950
- metrics: {
24951
- ...buildDurationMetrics3(state.startTime)
24952
- },
24953
- output: { completed: true }
24954
- });
24955
- state.span.end();
24956
- this.deleteCompactionState(state);
24957
24563
  }
24958
- }
24959
- deleteCompactionState(state) {
24960
- for (const [key, candidate] of this.compactionsByScope) {
24961
- if (candidate !== state) {
24962
- continue;
24564
+ if (event.taskId) {
24565
+ const task = this.tasksById.get(event.taskId);
24566
+ if (task) {
24567
+ return task.span;
24963
24568
  }
24964
- this.compactionsByScope.delete(key);
24965
- return;
24966
24569
  }
24967
- }
24968
- startSyntheticToolState(event, toolName) {
24969
- const parent = this.parentSpanForEvent(event);
24970
- const metadata = {
24971
- ...extractEventMetadata(event),
24972
- ...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
24973
- "flue.tool_name": toolName,
24974
- provider: "flue"
24975
- };
24976
- const span = startFlueSpan(parent, {
24977
- name: `tool: ${toolName}`,
24978
- spanAttributes: { type: "tool" /* TOOL */ }
24979
- });
24980
- safeLog3(span, { metadata });
24981
- return { metadata, span, startTime: getCurrentUnixTimestamp() };
24982
- }
24983
- operationStateForEvent(event) {
24984
24570
  if (event.operationId) {
24985
- const operation = this.activeOperationsById.get(event.operationId) ?? this.promotePendingOperationForEvent(event);
24571
+ const operation = this.operationsById.get(event.operationId);
24986
24572
  if (operation) {
24987
- return operation;
24573
+ return operation.span;
24988
24574
  }
24989
24575
  }
24990
- return this.activeOperationForEventScope(event) ?? this.pendingOperationForEventScope(event);
24576
+ if (event.runId) {
24577
+ return this.runsById.get(event.runId)?.span;
24578
+ }
24579
+ return void 0;
24991
24580
  }
24992
- parentSpanForEvent(event) {
24581
+ parentSpanForTool(event) {
24582
+ if (event.taskId) {
24583
+ const task = this.tasksById.get(event.taskId);
24584
+ if (task) {
24585
+ return task.span;
24586
+ }
24587
+ }
24993
24588
  if (event.operationId) {
24994
- const operation = this.operationStateForEvent(event);
24589
+ const operation = this.operationsById.get(event.operationId);
24995
24590
  if (operation) {
24996
24591
  return operation.span;
24997
24592
  }
24998
24593
  }
24999
- if (event.taskId) {
25000
- return this.tasksById.get(event.taskId)?.span;
24594
+ if (event.runId) {
24595
+ return this.runsById.get(event.runId)?.span;
25001
24596
  }
25002
- return this.operationStateForEvent(event)?.span;
24597
+ return void 0;
25003
24598
  }
25004
- promotePendingOperationForEvent(event) {
25005
- if (!event.operationId) {
25006
- return void 0;
24599
+ logOperationInput(operationId, input) {
24600
+ if (!operationId || input === void 0) {
24601
+ return;
25007
24602
  }
25008
- const scopePrefixes = operationScopePrefixes(event);
25009
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
25010
- if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
24603
+ const operation = this.operationsById.get(operationId);
24604
+ if (!operation || operation.loggedInput) {
24605
+ return;
24606
+ }
24607
+ safeLog3(operation.span, { input });
24608
+ operation.loggedInput = true;
24609
+ }
24610
+ startSyntheticOperation(event) {
24611
+ const metadata = {
24612
+ ...extractEventMetadata(event),
24613
+ "flue.operation": event.operationKind,
24614
+ provider: "flue"
24615
+ };
24616
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
24617
+ name: `flue.${event.operationKind}`,
24618
+ spanAttributes: { type: "task" /* TASK */ },
24619
+ startTime: eventTime(event.timestamp),
24620
+ event: { metadata }
24621
+ });
24622
+ return { metadata, span };
24623
+ }
24624
+ startSyntheticTurn(event) {
24625
+ const metadata = {
24626
+ ...extractEventMetadata(event),
24627
+ ...event.api ? { "flue.api": event.api } : {},
24628
+ ...event.model ? { model: event.model, "flue.model": event.model } : {},
24629
+ ...event.provider ? { provider: event.provider } : { provider: "flue" },
24630
+ ...event.provider ? { "flue.provider": event.provider } : {},
24631
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
24632
+ };
24633
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
24634
+ name: `llm:${event.model ?? event.purpose ?? "unknown"}`,
24635
+ spanAttributes: { type: "llm" /* LLM */ },
24636
+ startTime: eventTime(event.timestamp),
24637
+ event: { metadata }
24638
+ });
24639
+ return { metadata, span };
24640
+ }
24641
+ startSyntheticTool(event) {
24642
+ const metadata = {
24643
+ ...extractEventMetadata(event),
24644
+ ...event.toolName ? { "flue.tool_name": event.toolName } : {},
24645
+ "flue.tool_call_id": event.toolCallId,
24646
+ provider: "flue"
24647
+ };
24648
+ const span = startFlueSpan(this.parentSpanForTool(event), {
24649
+ name: `tool:${event.toolName ?? "unknown"}`,
24650
+ spanAttributes: { type: "tool" /* TOOL */ },
24651
+ startTime: eventTime(event.timestamp),
24652
+ event: { metadata }
24653
+ });
24654
+ return { metadata, span };
24655
+ }
24656
+ startSyntheticCompaction(event) {
24657
+ const metadata = {
24658
+ ...extractEventMetadata(event),
24659
+ provider: "flue"
24660
+ };
24661
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
24662
+ name: "compaction:unknown",
24663
+ spanAttributes: { type: "task" /* TASK */ },
24664
+ startTime: eventTime(event.timestamp),
24665
+ event: { metadata }
24666
+ });
24667
+ return { metadata, span };
24668
+ }
24669
+ finishPendingChildrenForOperation(event, operationOutput2) {
24670
+ const endTime = eventTime(event.timestamp);
24671
+ const usage = event.usage ?? usageFromOperationResult(event.result);
24672
+ const turnEntries = [...this.turnsByKey].filter(
24673
+ ([, state]) => stateMatchesOperation(state, event.operationId)
24674
+ );
24675
+ turnEntries.forEach(([key, state], index) => {
24676
+ const shouldLogOperationOutput = (event.operationKind === "prompt" || event.operationKind === "skill") && index === turnEntries.length - 1 && operationOutput2 !== void 0;
24677
+ safeLog3(state.span, {
24678
+ metadata: state.metadata,
24679
+ metrics: metricsFromUsage(usage),
24680
+ ...shouldLogOperationOutput ? { output: operationOutput2 } : {}
24681
+ });
24682
+ safeEnd(state.span, endTime);
24683
+ this.turnsByKey.delete(key);
24684
+ });
24685
+ for (const [key, state] of this.toolsByKey) {
24686
+ if (!stateMatchesOperation(state, event.operationId)) {
25011
24687
  continue;
25012
24688
  }
25013
- const state = candidateQueue.shift();
25014
- if (!state) {
25015
- return void 0;
24689
+ safeEnd(state.span, endTime);
24690
+ this.toolsByKey.delete(key);
24691
+ }
24692
+ for (const [key, state] of this.tasksById) {
24693
+ if (!stateMatchesOperation(state, event.operationId)) {
24694
+ continue;
25016
24695
  }
25017
- state.operationId = event.operationId;
25018
- this.activeOperationsById.set(event.operationId, state);
25019
- addScopedOperation(this.activeOperationsByScope, event, state);
25020
- state.metadata = {
25021
- ...state.metadata,
25022
- ...extractEventMetadata(event),
25023
- "flue.operation_id": event.operationId
25024
- };
25025
- safeLog3(state.span, { metadata: state.metadata });
25026
- return state;
24696
+ safeEnd(state.span, endTime);
24697
+ this.tasksById.delete(key);
25027
24698
  }
25028
- return void 0;
25029
- }
25030
- activeOperationForEventScope(event) {
25031
- for (const scope of operationScopeNames(event)) {
25032
- const operations = this.activeOperationsByScope.get(scope);
25033
- if (operations?.length) {
25034
- return operations[operations.length - 1];
24699
+ for (const [key, state] of this.compactionsByKey) {
24700
+ if (!stateMatchesOperation(state, event.operationId)) {
24701
+ continue;
25035
24702
  }
24703
+ safeLog3(state.span, {
24704
+ metadata: state.metadata,
24705
+ metrics: durationMetrics2(event.durationMs),
24706
+ output: { completed: true }
24707
+ });
24708
+ safeEnd(state.span, eventTime(event.timestamp));
24709
+ this.compactionsByKey.delete(key);
25036
24710
  }
25037
- return void 0;
25038
24711
  }
25039
- pendingOperationForEventScope(event) {
25040
- const scopePrefixes = operationScopePrefixes(event);
25041
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
25042
- if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
24712
+ finishPendingSpansForRun(event) {
24713
+ const endTime = eventTime(event.timestamp);
24714
+ for (const [key, state] of this.toolsByKey) {
24715
+ if (!stateMatchesRun(state, event.runId)) {
25043
24716
  continue;
25044
24717
  }
25045
- return candidateQueue[0];
24718
+ safeEnd(state.span, endTime);
24719
+ this.toolsByKey.delete(key);
25046
24720
  }
25047
- return void 0;
25048
- }
25049
- takePendingOperationForEvent(event) {
25050
- const key = operationKey(event.session, event.operationKind);
25051
- const queue2 = this.pendingOperationsByKey.get(key);
25052
- if (queue2?.length) {
25053
- return queue2.shift();
24721
+ for (const [key, state] of this.turnsByKey) {
24722
+ if (!stateMatchesRun(state, event.runId)) {
24723
+ continue;
24724
+ }
24725
+ safeEnd(state.span, endTime);
24726
+ this.turnsByKey.delete(key);
25054
24727
  }
25055
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
25056
- if (candidateKey.endsWith(`::${event.operationKind}`) && candidateQueue.length) {
25057
- return candidateQueue.shift();
24728
+ for (const [key, state] of this.tasksById) {
24729
+ if (!stateMatchesRun(state, event.runId)) {
24730
+ continue;
25058
24731
  }
24732
+ safeEnd(state.span, endTime);
24733
+ this.tasksById.delete(key);
25059
24734
  }
25060
- return void 0;
25061
- }
25062
- pendingOperationQueue(key) {
25063
- const existing = this.pendingOperationsByKey.get(key);
25064
- if (existing) {
25065
- return existing;
24735
+ for (const [key, state] of this.compactionsByKey) {
24736
+ if (!stateMatchesRun(state, event.runId)) {
24737
+ continue;
24738
+ }
24739
+ safeLog3(state.span, {
24740
+ metadata: state.metadata,
24741
+ output: { completed: true }
24742
+ });
24743
+ safeEnd(state.span, endTime);
24744
+ this.compactionsByKey.delete(key);
24745
+ }
24746
+ for (const [key, state] of this.operationsById) {
24747
+ if (!stateMatchesRun(state, event.runId)) {
24748
+ continue;
24749
+ }
24750
+ safeLog3(state.span, {
24751
+ metadata: state.metadata,
24752
+ ...state.metadata["flue.operation"] === "compact" ? { output: { completed: true } } : {}
24753
+ });
24754
+ safeEnd(state.span, endTime);
24755
+ this.operationsById.delete(key);
25066
24756
  }
25067
- const queue2 = [];
25068
- this.pendingOperationsByKey.set(key, queue2);
25069
- return queue2;
25070
24757
  }
25071
24758
  };
25072
24759
  function isInstrumentedOperation(operation) {
25073
- return operation === "prompt" || operation === "skill" || operation === "task" || operation === "compact";
25074
- }
25075
- function getSessionName(session) {
25076
- return typeof session?.name === "string" ? session.name : void 0;
25077
- }
25078
- function operationKey(sessionName, operation) {
25079
- return `${sessionName ?? "unknown"}::${operation}`;
25080
- }
25081
- function operationScopePrefixes(event) {
25082
- const scopes = /* @__PURE__ */ new Set();
25083
- for (const scope of operationScopeNames(event)) {
25084
- scopes.add(`${scope}::`);
25085
- }
25086
- return scopes;
24760
+ return operation === "prompt" || operation === "skill" || operation === "compact";
25087
24761
  }
25088
- function operationKeyMatchesScopes(key, scopes) {
25089
- for (const scope of scopes) {
25090
- if (key.startsWith(scope)) {
25091
- return true;
25092
- }
25093
- }
25094
- return false;
25095
- }
25096
- function operationScopeNames(event) {
25097
- const scopes = /* @__PURE__ */ new Set();
25098
- if (event.session) {
25099
- scopes.add(event.session);
25100
- }
25101
- if (event.parentSession) {
25102
- scopes.add(event.parentSession);
25103
- }
25104
- if (!scopes.size) {
25105
- scopes.add("unknown");
25106
- }
25107
- return scopes;
25108
- }
25109
- function addScopedOperation(operationsByScope, event, state) {
25110
- for (const scope of operationScopeNames(event)) {
25111
- addOperationToScope(operationsByScope, scope, state);
25112
- }
25113
- }
25114
- function addOperationToScope(operationsByScope, scope, state) {
25115
- const operations = operationsByScope.get(scope);
25116
- if (operations) {
25117
- if (!operations.includes(state)) {
25118
- operations.push(state);
25119
- }
25120
- } else {
25121
- operationsByScope.set(scope, [state]);
25122
- }
25123
- }
25124
- function removeScopedOperation(operationsByScope, state) {
25125
- for (const [scope, operations] of operationsByScope) {
25126
- const index = operations.indexOf(state);
25127
- if (index === -1) {
25128
- continue;
25129
- }
25130
- operations.splice(index, 1);
25131
- if (operations.length === 0) {
25132
- operationsByScope.delete(scope);
25133
- }
25134
- }
25135
- }
25136
- function removePendingOperation(pendingOperationsByKey, state) {
25137
- for (const [key, queue2] of pendingOperationsByKey) {
25138
- const index = queue2.indexOf(state);
25139
- if (index === -1) {
25140
- continue;
25141
- }
25142
- queue2.splice(index, 1);
25143
- if (queue2.length === 0) {
25144
- pendingOperationsByKey.delete(key);
25145
- }
25146
- return;
25147
- }
25148
- }
25149
- function extractSessionMetadata(session) {
25150
- const sessionName = getSessionName(session);
25151
- return sessionName ? { "flue.session": sessionName } : {};
25152
- }
25153
- function extractEventMetadata(event) {
24762
+ function extractEventMetadata(event, ctx) {
25154
24763
  return {
25155
24764
  ...event.runId ? { "flue.run_id": event.runId } : {},
24765
+ ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
24766
+ ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
25156
24767
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
25157
24768
  ...event.session ? { "flue.session": event.session } : {},
25158
24769
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
25159
24770
  ...event.harness ? { "flue.harness": event.harness } : {},
25160
24771
  ...event.taskId ? { "flue.task_id": event.taskId } : {},
25161
- ...event.operationId ? { "flue.operation_id": event.operationId } : {}
24772
+ ...event.operationId ? { "flue.operation_id": event.operationId } : {},
24773
+ ...event.turnId ? { "flue.turn_id": event.turnId } : {},
24774
+ ...typeof ctx?.id === "string" ? { "flue.context_id": ctx.id } : {},
24775
+ ...typeof ctx?.runId === "string" ? { "flue.context_run_id": ctx.runId } : {}
25162
24776
  };
25163
24777
  }
25164
- function extractOperationInput(operation, args) {
25165
- switch (operation) {
25166
- case "prompt":
25167
- case "task":
25168
- return args[0];
25169
- case "skill":
25170
- return {
25171
- args: getOptionObject(args[1])?.args,
25172
- name: args[0]
25173
- };
25174
- case "compact":
25175
- return void 0;
24778
+ function extractPayloadMetadata(payload) {
24779
+ if (!isObjectLike(payload)) {
24780
+ return {};
25176
24781
  }
24782
+ const metadata = Reflect.get(payload, "metadata");
24783
+ if (!isObjectLike(metadata)) {
24784
+ return {};
24785
+ }
24786
+ return Object.fromEntries(Object.entries(metadata));
25177
24787
  }
25178
- function extractOperationInputMetadata(operation, args) {
25179
- const options = getOptionObject(args[1]);
25180
- return {
25181
- ...operation === "skill" && typeof args[0] === "string" ? { "flue.skill_name": args[0] } : {},
25182
- ...options?.model ? { model: options.model, "flue.model": options.model } : {},
25183
- ...options?.role ? { "flue.role": options.role } : {},
25184
- ...options?.thinkingLevel ? { "flue.thinking_level": options.thinkingLevel } : {},
25185
- ...typeof options?.cwd === "string" ? { "flue.cwd": options.cwd } : {},
25186
- ...Array.isArray(options?.tools) ? {
25187
- "flue.tools_count": options.tools.length,
25188
- tools: summarizeTools(options.tools)
25189
- } : {},
25190
- ...Array.isArray(options?.images) ? { "flue.images_count": options.images.length } : {},
25191
- ...options?.result || options?.schema ? { "flue.result_schema": true } : {}
25192
- };
25193
- }
25194
- function getOptionObject(value) {
25195
- return isObject(value) ? value : void 0;
25196
- }
25197
- function summarizeTools(tools) {
25198
- return tools.flatMap((tool) => {
25199
- if (!isObject(tool)) {
25200
- return [];
25201
- }
25202
- const name = typeof tool.name === "string" ? tool.name : void 0;
25203
- if (!name) {
25204
- return [];
25205
- }
25206
- return [
25207
- {
25208
- function: {
25209
- description: typeof tool.description === "string" ? tool.description : void 0,
25210
- name,
25211
- parameters: tool.parameters
25212
- },
25213
- type: "function"
25214
- }
25215
- ];
25216
- });
24788
+ function operationOutput(event) {
24789
+ if (event.operationKind === "prompt" || event.operationKind === "skill") {
24790
+ return llmResultFromOperationResult(event.result);
24791
+ }
24792
+ return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
25217
24793
  }
25218
- function extractPromptResponseMetadata(result) {
25219
- const modelId = result?.model && typeof result.model.id === "string" ? result.model.id : void 0;
25220
- return modelId ? {
25221
- model: modelId,
25222
- "flue.model": modelId
25223
- } : {};
24794
+ function llmResultFromOperationResult(result) {
24795
+ if (!isObjectLike(result)) {
24796
+ return result;
24797
+ }
24798
+ const text = Reflect.get(result, "text");
24799
+ return text === void 0 ? result : text;
25224
24800
  }
25225
- function extractOperationOutput(result) {
25226
- if (!result) {
24801
+ function usageFromOperationResult(result) {
24802
+ if (!isObjectLike(result)) {
25227
24803
  return void 0;
25228
24804
  }
25229
- if ("data" in result) {
25230
- return result.data;
25231
- }
25232
- if ("text" in result) {
25233
- return result.text;
25234
- }
25235
- return result;
24805
+ return Reflect.get(result, "usage");
25236
24806
  }
25237
24807
  function metricsFromUsage(usage) {
24808
+ if (!isObjectLike(usage)) {
24809
+ return {};
24810
+ }
24811
+ const cacheRead = Reflect.get(usage, "cacheRead");
24812
+ const cacheWrite = Reflect.get(usage, "cacheWrite");
24813
+ const cost = Reflect.get(usage, "cost");
24814
+ const input = Reflect.get(usage, "input");
24815
+ const output = Reflect.get(usage, "output");
24816
+ const totalTokens = Reflect.get(usage, "totalTokens");
24817
+ const totalCost = isObjectLike(cost) ? Reflect.get(cost, "total") : void 0;
25238
24818
  return {
25239
- ...typeof usage?.input === "number" ? { prompt_tokens: usage.input } : {},
25240
- ...typeof usage?.output === "number" ? { completion_tokens: usage.output } : {},
25241
- ...typeof usage?.cacheRead === "number" ? { prompt_cached_tokens: usage.cacheRead } : {},
25242
- ...typeof usage?.cacheWrite === "number" ? { prompt_cache_creation_tokens: usage.cacheWrite } : {},
25243
- ...typeof usage?.totalTokens === "number" ? { tokens: usage.totalTokens } : {},
25244
- ...typeof usage?.cost?.total === "number" ? { estimated_cost: usage.cost.total } : {}
25245
- };
25246
- }
25247
- function buildDurationMetrics3(startTime) {
25248
- return {
25249
- duration_ms: Math.max(0, (getCurrentUnixTimestamp() - startTime) * 1e3)
24819
+ ...typeof input === "number" ? { prompt_tokens: input } : {},
24820
+ ...typeof output === "number" ? { completion_tokens: output } : {},
24821
+ ...typeof cacheRead === "number" ? { prompt_cached_tokens: cacheRead } : {},
24822
+ ...typeof cacheWrite === "number" ? { prompt_cache_creation_tokens: cacheWrite } : {},
24823
+ ...typeof totalTokens === "number" ? { tokens: totalTokens } : {},
24824
+ ...typeof totalCost === "number" ? { estimated_cost: totalCost } : {}
25250
24825
  };
25251
24826
  }
25252
- function durationMsMetrics(durationMs) {
24827
+ function durationMetrics2(durationMs) {
25253
24828
  return typeof durationMs === "number" ? { duration_ms: durationMs } : {};
25254
24829
  }
25255
- function scopeKey(event) {
25256
- if (event.operationId) {
25257
- return `operation:${event.operationId}`;
25258
- }
25259
- if (event.taskId) {
25260
- return `task:${event.taskId}`;
25261
- }
25262
- if (event.session) {
25263
- return `session:${event.session}`;
24830
+ function eventTime(value) {
24831
+ if (typeof value !== "string") {
24832
+ return void 0;
25264
24833
  }
25265
- return "flue:unknown";
24834
+ const timestamp = Date.parse(value);
24835
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
24836
+ }
24837
+ function turnKey(event) {
24838
+ return event.turnId;
25266
24839
  }
25267
24840
  function toolKey(event) {
25268
- return `${scopeKey(event)}::tool:${event.toolCallId ?? "unknown"}`;
24841
+ return `${event.turnId ?? event.operationId ?? event.taskId ?? event.runId ?? "unknown"}:${event.toolCallId ?? "unknown"}`;
25269
24842
  }
25270
- function toAssistantOutput(text, finishReason, reasoning, toolCalls) {
24843
+ function compactionKey(event) {
25271
24844
  return [
25272
- {
25273
- finish_reason: finishReason ?? "stop",
25274
- index: 0,
25275
- message: {
25276
- content: text,
25277
- ...reasoning ? { reasoning } : {},
25278
- role: "assistant",
25279
- ...toolCalls?.length ? {
25280
- tool_calls: toolCalls.map((toolCall) => ({
25281
- function: {
25282
- arguments: toolCall.args === void 0 ? "{}" : JSON.stringify(toolCall.args),
25283
- name: toolCall.toolName ?? "unknown"
25284
- },
25285
- ...toolCall.toolCallId ? { id: toolCall.toolCallId } : {},
25286
- type: "function"
25287
- }))
25288
- } : {}
25289
- }
25290
- }
25291
- ];
24845
+ event.instanceId ?? "",
24846
+ event.runId ?? "",
24847
+ event.session ?? "",
24848
+ event.operationId ?? "",
24849
+ event.taskId ?? ""
24850
+ ].join(":");
24851
+ }
24852
+ function stateMatchesOperation(state, operationId) {
24853
+ return state.metadata["flue.operation_id"] === operationId;
24854
+ }
24855
+ function stateMatchesRun(state, runId) {
24856
+ return state.metadata["flue.run_id"] === runId;
25292
24857
  }
25293
24858
  function startFlueSpan(parent, args) {
25294
24859
  return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
@@ -25300,6 +24865,13 @@ function safeLog3(span, event) {
25300
24865
  logInstrumentationError3("Flue span log", error);
25301
24866
  }
25302
24867
  }
24868
+ function safeEnd(span, endTime) {
24869
+ try {
24870
+ span.end(endTime === void 0 ? void 0 : { endTime });
24871
+ } catch (error) {
24872
+ logInstrumentationError3("Flue span end", error);
24873
+ }
24874
+ }
25303
24875
  function errorToString(error) {
25304
24876
  if (error instanceof Error) {
25305
24877
  return error.message;
@@ -26209,6 +25781,7 @@ __export(exports_exports, {
26209
25781
  LEGACY_CACHED_HEADER: () => LEGACY_CACHED_HEADER,
26210
25782
  LOGS3_OVERFLOW_REFERENCE_TYPE: () => LOGS3_OVERFLOW_REFERENCE_TYPE,
26211
25783
  LazyValue: () => LazyValue,
25784
+ LocalTrace: () => LocalTrace,
26212
25785
  Logger: () => Logger,
26213
25786
  LoginInvalidOrgError: () => LoginInvalidOrgError,
26214
25787
  NOOP_SPAN: () => NOOP_SPAN,
@@ -26234,6 +25807,7 @@ __export(exports_exports, {
26234
25807
  _internalIso: () => isomorph_default,
26235
25808
  _internalSetInitialState: () => _internalSetInitialState,
26236
25809
  addAzureBlobHeaders: () => addAzureBlobHeaders,
25810
+ braintrustFlueObserver: () => braintrustFlueObserver,
26237
25811
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
26238
25812
  buildLocalSummary: () => buildLocalSummary,
26239
25813
  configureInstrumentation: () => configureInstrumentation,
@@ -26313,8 +25887,6 @@ __export(exports_exports, {
26313
25887
  wrapCohere: () => wrapCohere,
26314
25888
  wrapCopilotClient: () => wrapCopilotClient,
26315
25889
  wrapCursorSDK: () => wrapCursorSDK,
26316
- wrapFlueContext: () => wrapFlueContext,
26317
- wrapFlueSession: () => wrapFlueSession,
26318
25890
  wrapGenkit: () => wrapGenkit,
26319
25891
  wrapGoogleADK: () => wrapGoogleADK,
26320
25892
  wrapGoogleGenAI: () => wrapGoogleGenAI,
@@ -26443,6 +26015,7 @@ async function invoke(args) {
26443
26015
  mode,
26444
26016
  schema,
26445
26017
  strict,
26018
+ overrides,
26446
26019
  projectId,
26447
26020
  ...functionIdArgs
26448
26021
  } = args;
@@ -26479,7 +26052,8 @@ async function invoke(args) {
26479
26052
  tags,
26480
26053
  stream,
26481
26054
  mode,
26482
- strict
26055
+ strict,
26056
+ overrides
26483
26057
  };
26484
26058
  const headers = {
26485
26059
  Accept: stream ? "text/event-stream" : "application/json"
@@ -33514,6 +33088,7 @@ export {
33514
33088
  LEGACY_CACHED_HEADER,
33515
33089
  LOGS3_OVERFLOW_REFERENCE_TYPE,
33516
33090
  LazyValue,
33091
+ LocalTrace,
33517
33092
  Logger,
33518
33093
  LoginInvalidOrgError,
33519
33094
  NOOP_SPAN,
@@ -33539,6 +33114,7 @@ export {
33539
33114
  isomorph_default as _internalIso,
33540
33115
  _internalSetInitialState,
33541
33116
  addAzureBlobHeaders,
33117
+ braintrustFlueObserver,
33542
33118
  braintrustStreamChunkSchema,
33543
33119
  buildLocalSummary,
33544
33120
  configureInstrumentation,
@@ -33619,8 +33195,6 @@ export {
33619
33195
  wrapCohere,
33620
33196
  wrapCopilotClient,
33621
33197
  wrapCursorSDK,
33622
- wrapFlueContext,
33623
- wrapFlueSession,
33624
33198
  wrapGenkit,
33625
33199
  wrapGoogleADK,
33626
33200
  wrapGoogleGenAI,