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/browser.mjs CHANGED
@@ -3705,7 +3705,7 @@ function btStreamParser() {
3705
3705
  },
3706
3706
  async transform(chunk, controller) {
3707
3707
  if (chunk instanceof Uint8Array) {
3708
- parser.feed(decoder.decode(chunk));
3708
+ parser.feed(decoder.decode(chunk, { stream: true }));
3709
3709
  } else if (typeof chunk === "string") {
3710
3710
  parser.feed(chunk);
3711
3711
  } else {
@@ -3713,6 +3713,10 @@ function btStreamParser() {
3713
3713
  }
3714
3714
  },
3715
3715
  async flush(controller) {
3716
+ const tail = decoder.decode();
3717
+ if (tail) {
3718
+ parser.feed(tail);
3719
+ }
3716
3720
  controller.terminate();
3717
3721
  }
3718
3722
  });
@@ -23919,825 +23923,440 @@ var flueChannels = defineChannels("@flue/runtime", {
23919
23923
  createContext: channel({
23920
23924
  channelName: "createFlueContext",
23921
23925
  kind: "sync-stream"
23922
- }),
23923
- openSession: channel({
23924
- channelName: "Harness.openSession",
23925
- kind: "async"
23926
- }),
23927
- contextEvent: channel({
23928
- channelName: "context.event",
23929
- kind: "sync-stream"
23930
- }),
23931
- prompt: channel({
23932
- channelName: "session.prompt",
23933
- kind: "async"
23934
- }),
23935
- skill: channel({
23936
- channelName: "session.skill",
23937
- kind: "async"
23938
- }),
23939
- task: channel({
23940
- channelName: "session.task",
23941
- kind: "async"
23942
- }),
23943
- compact: channel({
23944
- channelName: "session.compact",
23945
- kind: "async"
23946
23926
  })
23947
23927
  });
23948
23928
 
23949
- // src/wrappers/flue.ts
23950
- var WRAPPED_FLUE_CONTEXT = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-context");
23951
- var WRAPPED_FLUE_HARNESS = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-harness");
23952
- var WRAPPED_FLUE_SESSION = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-session");
23953
- var SUBSCRIBED_FLUE_CONTEXT_EVENTS = /* @__PURE__ */ Symbol.for(
23954
- "braintrust.flue.subscribed-context-events"
23955
- );
23956
- function wrapFlueContext(ctx) {
23957
- if (!isPlausibleFlueContext(ctx)) {
23958
- console.warn("Unsupported Flue context. Not wrapping.");
23959
- return ctx;
23929
+ // src/instrumentation/plugins/flue-plugin.ts
23930
+ var FLUE_AUTO_STATE = /* @__PURE__ */ Symbol.for("braintrust.flue.auto-state");
23931
+ var FLUE_OBSERVE_BRIDGE = /* @__PURE__ */ Symbol.for("braintrust.flue.observe-bridge");
23932
+ var braintrustFlueObserver = (event, ctx) => {
23933
+ getObserveBridge().handle(event, ctx);
23934
+ };
23935
+ var FluePlugin = class extends BasePlugin {
23936
+ onEnable() {
23937
+ this.unsubscribers.push(enableFlueAutoInstrumentation());
23960
23938
  }
23961
- const context = ctx;
23962
- subscribeFlueContextEvents(context, { captureTurnSpans: true });
23963
- return patchFlueContextInPlace(context);
23964
- }
23965
- function patchFlueContextInPlace(ctx) {
23966
- const context = ctx;
23967
- if (context[WRAPPED_FLUE_CONTEXT]) {
23968
- return ctx;
23939
+ onDisable() {
23940
+ for (const unsubscribe of this.unsubscribers) {
23941
+ unsubscribe();
23942
+ }
23943
+ this.unsubscribers = [];
23969
23944
  }
23970
- const originalInit = context.init.bind(context);
23971
- try {
23972
- Object.defineProperty(context, WRAPPED_FLUE_CONTEXT, {
23973
- configurable: false,
23974
- enumerable: false,
23975
- value: true
23976
- });
23977
- Object.defineProperty(context, "init", {
23978
- configurable: true,
23979
- value: async function wrappedFlueInit(options) {
23980
- const harness = await originalInit(options);
23981
- return wrapFlueHarness(harness);
23982
- },
23983
- writable: true
23984
- });
23985
- } catch {
23945
+ };
23946
+ function enableFlueAutoInstrumentation() {
23947
+ const state = getAutoState();
23948
+ state.refCount += 1;
23949
+ if (!state.handlers) {
23950
+ const channel2 = flueChannels.createContext.tracingChannel();
23951
+ const handlers = {
23952
+ end: (event) => {
23953
+ subscribeToFlueContext(event.result, state);
23954
+ }
23955
+ };
23956
+ channel2.subscribe(handlers);
23957
+ state.channel = channel2;
23958
+ state.handlers = handlers;
23986
23959
  }
23987
- return ctx;
23960
+ let released = false;
23961
+ return () => {
23962
+ if (released) {
23963
+ return;
23964
+ }
23965
+ released = true;
23966
+ releaseAutoState(state);
23967
+ };
23988
23968
  }
23989
- function wrapFlueSession(session) {
23990
- if (!isPlausibleFlueSession(session)) {
23991
- console.warn("Unsupported Flue session. Not wrapping.");
23992
- return session;
23969
+ function getAutoState() {
23970
+ const existing = Reflect.get(globalThis, FLUE_AUTO_STATE);
23971
+ if (isAutoState(existing)) {
23972
+ return existing;
23993
23973
  }
23994
- return patchFlueSessionInPlace(session);
23974
+ const state = {
23975
+ contexts: /* @__PURE__ */ new WeakSet(),
23976
+ refCount: 0
23977
+ };
23978
+ Reflect.set(globalThis, FLUE_AUTO_STATE, state);
23979
+ return state;
23995
23980
  }
23996
- function subscribeFlueContextEvents(ctx, options = {}) {
23997
- if (!ctx || typeof ctx !== "object" || typeof ctx.subscribeEvent !== "function") {
23998
- return void 0;
23999
- }
24000
- const context = ctx;
24001
- const captureTurnSpans = options.captureTurnSpans ?? true;
24002
- const existingSubscription = context[SUBSCRIBED_FLUE_CONTEXT_EVENTS];
24003
- if (existingSubscription) {
24004
- if (existingSubscription.captureTurnSpans || !captureTurnSpans) {
24005
- return void 0;
24006
- }
24007
- try {
24008
- existingSubscription.unsubscribe();
24009
- } catch {
24010
- }
24011
- }
24012
- try {
24013
- const unsubscribe = ctx.subscribeEvent((event) => {
24014
- flueChannels.contextEvent.traceSync(() => void 0, {
24015
- arguments: [event],
24016
- captureTurnSpans,
24017
- context: ctx
24018
- });
24019
- });
24020
- if (existingSubscription) {
24021
- existingSubscription.captureTurnSpans = captureTurnSpans;
24022
- existingSubscription.unsubscribe = unsubscribe;
24023
- } else {
24024
- Object.defineProperty(context, SUBSCRIBED_FLUE_CONTEXT_EVENTS, {
24025
- configurable: false,
24026
- enumerable: false,
24027
- value: {
24028
- captureTurnSpans,
24029
- unsubscribe
24030
- }
24031
- });
24032
- }
24033
- return unsubscribe;
24034
- } catch {
24035
- return void 0;
23981
+ function getObserveBridge() {
23982
+ const existing = Reflect.get(globalThis, FLUE_OBSERVE_BRIDGE);
23983
+ if (isFlueObserveBridge(existing)) {
23984
+ return existing;
24036
23985
  }
23986
+ const bridge = new FlueObserveBridge();
23987
+ Reflect.set(globalThis, FLUE_OBSERVE_BRIDGE, bridge);
23988
+ return bridge;
24037
23989
  }
24038
- function wrapFlueHarness(harness) {
24039
- if (!isPlausibleFlueHarness(harness)) {
24040
- return harness;
24041
- }
24042
- const target = harness;
24043
- if (target[WRAPPED_FLUE_HARNESS]) {
24044
- return harness;
24045
- }
24046
- const originalSession = target.session.bind(target);
24047
- try {
24048
- Object.defineProperty(target, WRAPPED_FLUE_HARNESS, {
24049
- configurable: false,
24050
- enumerable: false,
24051
- value: true
24052
- });
24053
- Object.defineProperty(target, "session", {
24054
- configurable: true,
24055
- value: async function wrappedFlueHarnessSession(name, options) {
24056
- const session = await originalSession(name, options);
24057
- return patchFlueSessionInPlace(session);
24058
- },
24059
- writable: true
24060
- });
24061
- const sessions = target.sessions;
24062
- if (sessions && typeof sessions === "object") {
24063
- patchFlueSessionFactory(sessions, "get");
24064
- patchFlueSessionFactory(sessions, "create");
24065
- }
24066
- } catch {
24067
- }
24068
- return harness;
23990
+ function isFlueObserveBridge(value) {
23991
+ return isObjectLike(value) && typeof Reflect.get(value, "handle") === "function" && typeof Reflect.get(value, "reset") === "function";
24069
23992
  }
24070
- function patchFlueSessionInPlace(session) {
24071
- if (session[WRAPPED_FLUE_SESSION]) {
24072
- return session;
24073
- }
24074
- try {
24075
- Object.defineProperty(session, WRAPPED_FLUE_SESSION, {
24076
- configurable: false,
24077
- enumerable: false,
24078
- value: true
24079
- });
24080
- patchCallHandleMethod(session, "prompt", flueChannels.prompt);
24081
- patchCallHandleMethod(session, "skill", flueChannels.skill);
24082
- patchCallHandleMethod(session, "task", flueChannels.task);
24083
- patchCompact(session);
24084
- } catch {
24085
- }
24086
- return session;
23993
+ function isAutoState(value) {
23994
+ return isObjectLike(value) && Reflect.get(value, "contexts") instanceof WeakSet && typeof Reflect.get(value, "refCount") === "number";
24087
23995
  }
24088
- function patchFlueSessionFactory(sessions, method) {
24089
- const original = sessions[method];
24090
- if (typeof original !== "function") {
23996
+ function releaseAutoState(state) {
23997
+ state.refCount -= 1;
23998
+ if (state.refCount > 0) {
24091
23999
  return;
24092
24000
  }
24093
- const bound = original.bind(sessions);
24094
- Object.defineProperty(sessions, method, {
24095
- configurable: true,
24096
- value: async function wrappedFlueSessionFactory(name, options) {
24097
- const session = await bound(name, options);
24098
- return patchFlueSessionInPlace(session);
24099
- },
24100
- writable: true
24101
- });
24102
- }
24103
- function patchCallHandleMethod(session, method, channel2) {
24104
- const original = session[method];
24105
- if (typeof original !== "function") {
24106
- return;
24001
+ try {
24002
+ if (state.channel && state.handlers) {
24003
+ state.channel.unsubscribe(state.handlers);
24004
+ }
24005
+ } finally {
24006
+ Reflect.deleteProperty(globalThis, FLUE_AUTO_STATE);
24107
24007
  }
24108
- const bound = original.bind(session);
24109
- Object.defineProperty(session, method, {
24110
- configurable: true,
24111
- value(input, options) {
24112
- const args = [input, options];
24113
- const { originalResult, traced: traced2 } = traceFlueOperation(channel2, {
24114
- context: {
24115
- arguments: args,
24116
- operation: method,
24117
- session
24118
- },
24119
- run: () => bound(input, options)
24120
- });
24121
- return preserveCallHandle(originalResult, traced2);
24122
- },
24123
- writable: true
24124
- });
24125
24008
  }
24126
- function patchCompact(session) {
24127
- const original = session.compact;
24128
- if (typeof original !== "function") {
24009
+ function subscribeToFlueContext(value, state) {
24010
+ if (!isObservableFlueContext(value) || state.contexts.has(value)) {
24129
24011
  return;
24130
24012
  }
24131
- const bound = original.bind(session);
24132
- Object.defineProperty(session, "compact", {
24133
- configurable: true,
24134
- value() {
24135
- const context = {
24136
- arguments: [],
24137
- operation: "compact",
24138
- session
24139
- };
24140
- return flueChannels.compact.tracePromise(() => bound(), context);
24141
- },
24142
- writable: true
24143
- });
24144
- }
24145
- function traceFlueOperation(channel2, args) {
24146
- const tracingChannel2 = channel2.tracingChannel();
24147
- const context = args.context;
24148
- let originalResult;
24149
- let traced2;
24150
- const run = () => {
24013
+ const ctx = flueContextFromUnknown(value);
24014
+ let released = false;
24015
+ let unsubscribe;
24016
+ const release = () => {
24017
+ if (released) {
24018
+ return;
24019
+ }
24020
+ released = true;
24151
24021
  try {
24152
- originalResult = args.run();
24153
- tracingChannel2.end?.publish(context);
24022
+ unsubscribe?.();
24154
24023
  } catch (error) {
24155
- context.error = normalizeError3(error);
24156
- tracingChannel2.error?.publish(context);
24157
- tracingChannel2.end?.publish(context);
24158
- throw error;
24024
+ logInstrumentationError3("Flue context unsubscribe", error);
24159
24025
  }
24160
- traced2 = Promise.resolve(originalResult).then(
24161
- (result) => {
24162
- context.result = result;
24163
- tracingChannel2.asyncStart?.publish(context);
24164
- tracingChannel2.asyncEnd?.publish(context);
24165
- return result;
24166
- },
24167
- (error) => {
24168
- context.error = normalizeError3(error);
24169
- tracingChannel2.error?.publish(context);
24170
- tracingChannel2.asyncStart?.publish(context);
24171
- tracingChannel2.asyncEnd?.publish(context);
24172
- throw error;
24173
- }
24174
- );
24175
24026
  };
24176
- if (tracingChannel2.start?.runStores) {
24177
- tracingChannel2.start.runStores(context, run);
24178
- } else {
24179
- tracingChannel2.start?.publish(context);
24180
- run();
24027
+ try {
24028
+ unsubscribe = value.subscribeEvent((event) => {
24029
+ if (state.refCount <= 0) {
24030
+ release();
24031
+ return;
24032
+ }
24033
+ braintrustFlueObserver(event, ctx);
24034
+ if (isAutoContextTerminalEvent(event, ctx)) {
24035
+ release();
24036
+ }
24037
+ });
24038
+ state.contexts.add(value);
24039
+ } catch (error) {
24040
+ logInstrumentationError3("Flue context subscription", error);
24181
24041
  }
24182
- return { originalResult, traced: traced2 };
24183
24042
  }
24184
- function normalizeError3(error) {
24185
- return error instanceof Error ? error : new Error(String(error));
24186
- }
24187
- function preserveCallHandle(originalHandle, traced2) {
24188
- if (!isFlueCallHandle(originalHandle)) {
24189
- return traced2;
24043
+ function isAutoContextTerminalEvent(event, ctx) {
24044
+ if (!isObjectLike(event)) {
24045
+ return false;
24190
24046
  }
24191
- const handle = originalHandle;
24192
- const wrapped = {
24193
- get signal() {
24194
- return handle.signal;
24195
- },
24196
- abort(reason) {
24197
- return handle.abort(reason);
24198
- },
24199
- then(onfulfilled, onrejected) {
24200
- return traced2.then(onfulfilled, onrejected);
24201
- }
24202
- };
24203
- return wrapped;
24047
+ const type = Reflect.get(event, "type");
24048
+ if (type === "run_end") {
24049
+ return true;
24050
+ }
24051
+ if (type !== "operation") {
24052
+ return false;
24053
+ }
24054
+ return !ctx?.runId && typeof Reflect.get(event, "runId") !== "string";
24204
24055
  }
24205
- function isPlausibleFlueContext(value) {
24206
- return !!value && typeof value === "object" && typeof value.init === "function";
24056
+ function isObservableFlueContext(value) {
24057
+ return isObjectLike(value) && typeof Reflect.get(value, "subscribeEvent") === "function";
24207
24058
  }
24208
- function isPlausibleFlueHarness(value) {
24209
- return !!value && typeof value === "object" && typeof value.session === "function";
24059
+ function isFlueEvent(event) {
24060
+ const type = Reflect.get(event, "type");
24061
+ 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";
24210
24062
  }
24211
- function isPlausibleFlueSession(value) {
24212
- return !!value && typeof value === "object" && typeof value.prompt === "function" && typeof value.skill === "function" && typeof value.task === "function" && typeof value.compact === "function";
24063
+ function flueContextFromUnknown(ctx) {
24064
+ if (!isObjectLike(ctx)) {
24065
+ return void 0;
24066
+ }
24067
+ const id = Reflect.get(ctx, "id");
24068
+ const runId = Reflect.get(ctx, "runId");
24069
+ return {
24070
+ ...typeof id === "string" ? { id } : {},
24071
+ ...typeof runId === "string" ? { runId } : {}
24072
+ };
24213
24073
  }
24214
- function isFlueCallHandle(value) {
24215
- return !!value && typeof value === "object" && typeof value.then === "function" && typeof value.abort === "function" && "signal" in value;
24074
+ function isObjectLike(value) {
24075
+ return typeof value === "object" && value !== null && !Array.isArray(value);
24216
24076
  }
24217
-
24218
- // src/instrumentation/plugins/flue-plugin.ts
24219
- var FluePlugin = class extends BasePlugin {
24220
- activeOperationsById = /* @__PURE__ */ new Map();
24221
- activeOperationsByScope = /* @__PURE__ */ new Map();
24222
- compactionsByScope = /* @__PURE__ */ new Map();
24223
- pendingOperationsByKey = /* @__PURE__ */ new Map();
24077
+ var FlueObserveBridge = class {
24078
+ compactionsByKey = /* @__PURE__ */ new Map();
24079
+ operationsById = /* @__PURE__ */ new Map();
24080
+ runsById = /* @__PURE__ */ new Map();
24081
+ seenEvents = /* @__PURE__ */ new WeakSet();
24224
24082
  tasksById = /* @__PURE__ */ new Map();
24225
- toolsById = /* @__PURE__ */ new Map();
24226
- turnsByScope = /* @__PURE__ */ new Map();
24227
- onEnable() {
24228
- this.subscribeToContextCreation();
24229
- this.subscribeToSessionCreation();
24230
- this.subscribeToContextEvents();
24231
- this.subscribeToSessionOperations();
24232
- }
24233
- onDisable() {
24234
- for (const unsubscribe of this.unsubscribers) {
24235
- unsubscribe();
24083
+ toolsByKey = /* @__PURE__ */ new Map();
24084
+ turnsByKey = /* @__PURE__ */ new Map();
24085
+ handle(event, ctx) {
24086
+ if (!isObjectLike(event) || !isFlueEvent(event)) {
24087
+ return;
24236
24088
  }
24237
- this.unsubscribers = [];
24238
- this.activeOperationsById.clear();
24239
- this.activeOperationsByScope.clear();
24240
- this.compactionsByScope.clear();
24241
- this.pendingOperationsByKey.clear();
24089
+ if (this.seenEvents.has(event)) {
24090
+ return;
24091
+ }
24092
+ this.seenEvents.add(event);
24093
+ try {
24094
+ this.handleEvent(event, flueContextFromUnknown(ctx));
24095
+ } catch (error) {
24096
+ logInstrumentationError3("Flue observe", error);
24097
+ }
24098
+ }
24099
+ reset() {
24100
+ this.compactionsByKey.clear();
24101
+ this.operationsById.clear();
24102
+ this.runsById.clear();
24103
+ this.seenEvents = /* @__PURE__ */ new WeakSet();
24242
24104
  this.tasksById.clear();
24243
- this.toolsById.clear();
24244
- this.turnsByScope.clear();
24105
+ this.toolsByKey.clear();
24106
+ this.turnsByKey.clear();
24245
24107
  }
24246
- subscribeToContextCreation() {
24247
- const channel2 = flueChannels.createContext.tracingChannel();
24248
- const handlers = {
24249
- end: (event) => {
24250
- const ctx = event.result;
24251
- if (!ctx) {
24252
- return;
24253
- }
24254
- subscribeFlueContextEvents(ctx, { captureTurnSpans: false });
24255
- patchFlueContextInPlace(ctx);
24256
- },
24257
- error: () => {
24258
- }
24259
- };
24260
- channel2.subscribe(handlers);
24261
- this.unsubscribers.push(() => {
24262
- channel2.unsubscribe(handlers);
24263
- });
24108
+ handleEvent(event, ctx) {
24109
+ switch (event.type) {
24110
+ case "run_start":
24111
+ this.handleRunStart(event, ctx);
24112
+ return;
24113
+ case "run_end":
24114
+ this.handleRunEnd(event);
24115
+ return;
24116
+ case "operation_start":
24117
+ this.handleOperationStart(event);
24118
+ return;
24119
+ case "operation":
24120
+ this.handleOperation(event);
24121
+ return;
24122
+ case "turn_request":
24123
+ this.handleTurnRequest(event);
24124
+ return;
24125
+ case "turn":
24126
+ this.handleTurn(event);
24127
+ return;
24128
+ case "tool_start":
24129
+ this.handleToolStart(event);
24130
+ return;
24131
+ case "tool_call":
24132
+ this.handleToolCall(event);
24133
+ return;
24134
+ case "task_start":
24135
+ this.handleTaskStart(event);
24136
+ return;
24137
+ case "task":
24138
+ this.handleTask(event);
24139
+ return;
24140
+ case "compaction_start":
24141
+ this.handleCompactionStart(event);
24142
+ return;
24143
+ case "compaction":
24144
+ this.handleCompaction(event);
24145
+ return;
24146
+ default:
24147
+ return;
24148
+ }
24264
24149
  }
24265
- subscribeToSessionCreation() {
24266
- const channel2 = flueChannels.openSession.tracingChannel();
24267
- const handlers = {
24268
- asyncEnd: (event) => {
24269
- if (event.result) {
24270
- patchFlueSessionInPlace(
24271
- event.result
24272
- );
24273
- }
24274
- if (event.harness) {
24275
- wrapFlueHarness(event.harness);
24276
- }
24277
- },
24278
- error: () => {
24279
- }
24150
+ handleRunStart(event, ctx) {
24151
+ if (!event.runId) {
24152
+ return;
24153
+ }
24154
+ const workflowName = event.workflowName ?? event.owner?.workflowName ?? (typeof ctx?.id === "string" ? ctx.id : "unknown");
24155
+ const metadata = {
24156
+ ...extractPayloadMetadata(event.payload),
24157
+ ...extractEventMetadata(event, ctx),
24158
+ ...workflowName ? { "flue.workflow_name": workflowName } : {},
24159
+ provider: "flue"
24280
24160
  };
24281
- channel2.subscribe(handlers);
24282
- this.unsubscribers.push(() => {
24283
- channel2.unsubscribe(handlers);
24161
+ const span = startSpan({
24162
+ name: `workflow:${workflowName}`,
24163
+ spanAttributes: { type: "task" /* TASK */ },
24164
+ startTime: eventTime(event.startedAt ?? event.timestamp),
24165
+ event: {
24166
+ input: event.payload,
24167
+ metadata
24168
+ }
24284
24169
  });
24170
+ this.runsById.set(event.runId, { metadata, span });
24285
24171
  }
24286
- subscribeToSessionOperations() {
24287
- this.subscribeToSessionOperation(flueChannels.prompt);
24288
- this.subscribeToSessionOperation(flueChannels.skill);
24289
- this.subscribeToSessionOperation(flueChannels.task);
24290
- this.subscribeToCompact();
24291
- }
24292
- subscribeToSessionOperation(channel2) {
24293
- const tracingChannel2 = channel2.tracingChannel();
24294
- const states = /* @__PURE__ */ new WeakMap();
24295
- const ensureState2 = (event) => {
24296
- const existing = states.get(event);
24297
- if (existing) {
24298
- return existing;
24299
- }
24300
- const state = this.startOperationState({
24301
- args: event.arguments,
24302
- moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
24303
- operation: event.operation,
24304
- session: event.session
24172
+ handleRunEnd(event) {
24173
+ const state = this.runsById.get(event.runId);
24174
+ this.finishPendingSpansForRun(event);
24175
+ if (state) {
24176
+ safeLog3(state.span, {
24177
+ ...event.isError ? { error: errorToString(event.error) } : {},
24178
+ metadata: {
24179
+ ...state.metadata,
24180
+ ...extractEventMetadata(event),
24181
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24182
+ },
24183
+ metrics: durationMetrics2(event.durationMs),
24184
+ output: event.result
24305
24185
  });
24306
- states.set(event, state);
24307
- return state;
24308
- };
24309
- const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
24310
- tracingChannel2,
24311
- ensureState2
24312
- );
24313
- const handlers = {
24314
- start: (event) => {
24315
- ensureState2(event);
24316
- },
24317
- asyncEnd: (event) => {
24318
- this.endOperationState(states.get(event), event.result);
24319
- states.delete(event);
24320
- },
24321
- error: (event) => {
24322
- const state = states.get(event);
24323
- if (state && event.error) {
24324
- safeLog3(state.span, { error: errorToString(event.error) });
24325
- this.finishOperationState(state);
24326
- }
24327
- states.delete(event);
24328
- }
24329
- };
24330
- tracingChannel2.subscribe(handlers);
24331
- this.unsubscribers.push(() => {
24332
- unbindCurrentSpanStore?.();
24333
- tracingChannel2.unsubscribe(handlers);
24186
+ safeEnd(state.span, eventTime(event.timestamp));
24187
+ this.runsById.delete(event.runId);
24188
+ }
24189
+ void flush().catch((error) => {
24190
+ logInstrumentationError3("Flue flush", error);
24334
24191
  });
24335
24192
  }
24336
- subscribeToCompact() {
24337
- const tracingChannel2 = flueChannels.compact.tracingChannel();
24338
- const states = /* @__PURE__ */ new WeakMap();
24339
- const ensureState2 = (event) => {
24340
- const existing = states.get(event);
24341
- if (existing) {
24342
- return existing;
24343
- }
24344
- const state = this.startOperationState({
24345
- args: [],
24346
- moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
24347
- operation: event.operation,
24348
- session: event.session
24349
- });
24350
- states.set(event, state);
24351
- return state;
24352
- };
24353
- const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
24354
- tracingChannel2,
24355
- ensureState2
24356
- );
24357
- const handlers = {
24358
- start: (event) => {
24359
- ensureState2(event);
24360
- },
24361
- asyncEnd: (event) => {
24362
- this.endOperationState(states.get(event), void 0);
24363
- states.delete(event);
24364
- },
24365
- error: (event) => {
24366
- const state = states.get(event);
24367
- if (state && event.error) {
24368
- safeLog3(state.span, { error: errorToString(event.error) });
24369
- this.finishOperationState(state);
24370
- }
24371
- states.delete(event);
24372
- }
24373
- };
24374
- tracingChannel2.subscribe(handlers);
24375
- this.unsubscribers.push(() => {
24376
- unbindCurrentSpanStore?.();
24377
- tracingChannel2.unsubscribe(handlers);
24378
- });
24379
- }
24380
- subscribeToContextEvents() {
24381
- const channel2 = flueChannels.contextEvent.tracingChannel();
24382
- const handlers = {
24383
- start: (event) => {
24384
- const flueEvent = event.arguments[0];
24385
- if (!flueEvent) {
24386
- return;
24387
- }
24388
- try {
24389
- this.handleFlueEvent(flueEvent, {
24390
- captureTurnSpans: event.captureTurnSpans !== false
24391
- });
24392
- } catch (error) {
24393
- logInstrumentationError3("Flue event", error);
24394
- }
24395
- },
24396
- error: () => {
24397
- }
24398
- };
24399
- channel2.subscribe(handlers);
24400
- this.unsubscribers.push(() => {
24401
- channel2.unsubscribe(handlers);
24402
- });
24403
- }
24404
- bindCurrentSpanStoreToOperationStart(tracingChannel2, ensureState2) {
24405
- const state = _internalGetGlobalState();
24406
- const startChannel = tracingChannel2.start;
24407
- const contextManager = state?.contextManager;
24408
- const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
24409
- if (!currentSpanStore || !startChannel) {
24410
- return void 0;
24411
- }
24412
- startChannel.bindStore(currentSpanStore, (event) => {
24413
- const operationState = ensureState2(event);
24414
- return contextManager.wrapSpanForStore(operationState.span);
24415
- });
24416
- return () => {
24417
- startChannel.unbindStore(currentSpanStore);
24418
- };
24419
- }
24420
- startOperationState(args) {
24421
- const sessionName = getSessionName(args.session);
24422
- const metadata = {
24423
- ...extractOperationInputMetadata(args.operation, args.args),
24424
- ...extractSessionMetadata(args.session),
24425
- "flue.operation": args.operation,
24426
- provider: "flue",
24427
- ...args.moduleVersion ? { "flue.version": args.moduleVersion } : {}
24428
- };
24429
- const span = startSpan({
24430
- name: `flue.session.${args.operation}`,
24431
- spanAttributes: { type: "task" /* TASK */ }
24432
- });
24433
- const state = {
24434
- metadata,
24435
- operation: args.operation,
24436
- sessionName,
24437
- span,
24438
- startTime: getCurrentUnixTimestamp()
24439
- };
24440
- safeLog3(span, {
24441
- input: extractOperationInput(args.operation, args.args),
24442
- metadata
24443
- });
24444
- this.pendingOperationQueue(operationKey(sessionName, args.operation)).push(
24445
- state
24446
- );
24447
- addOperationToScope(
24448
- this.activeOperationsByScope,
24449
- sessionName ?? "unknown",
24450
- state
24451
- );
24452
- return state;
24453
- }
24454
- endOperationState(state, result) {
24455
- if (!state) {
24456
- return;
24457
- }
24458
- const metadata = {
24459
- ...state.metadata,
24460
- ...extractPromptResponseMetadata(result)
24461
- };
24462
- const metrics = {
24463
- ...buildDurationMetrics3(state.startTime),
24464
- ...metricsFromUsage(result?.usage)
24465
- };
24466
- safeLog3(state.span, {
24467
- metadata,
24468
- metrics,
24469
- output: extractOperationOutput(result)
24470
- });
24471
- this.finishCompactionsForOperation(state);
24472
- this.finishOperationState(state);
24473
- }
24474
- finishOperationState(state) {
24475
- removePendingOperation(this.pendingOperationsByKey, state);
24476
- if (state.operationId) {
24477
- this.activeOperationsById.delete(state.operationId);
24478
- }
24479
- removeScopedOperation(this.activeOperationsByScope, state);
24480
- state.span.end();
24481
- }
24482
- handleFlueEvent(event, options) {
24483
- switch (event.type) {
24484
- case "operation_start":
24485
- this.handleOperationStart(event);
24486
- return;
24487
- case "operation":
24488
- this.handleOperation(event);
24489
- return;
24490
- case "text_delta":
24491
- if (!options.captureTurnSpans) {
24492
- return;
24493
- }
24494
- this.ensureTurnState(event).text.push(
24495
- typeof event.text === "string" ? event.text : ""
24496
- );
24497
- return;
24498
- case "thinking_start":
24499
- if (!options.captureTurnSpans) {
24500
- return;
24501
- }
24502
- this.handleThinkingStart(event);
24503
- return;
24504
- case "thinking_delta":
24505
- if (!options.captureTurnSpans) {
24506
- return;
24507
- }
24508
- this.handleThinkingDelta(event);
24509
- return;
24510
- case "thinking_end":
24511
- if (!options.captureTurnSpans) {
24512
- return;
24513
- }
24514
- this.handleThinkingEnd(event);
24515
- return;
24516
- case "turn":
24517
- if (!options.captureTurnSpans) {
24518
- return;
24519
- }
24520
- this.handleTurn(event);
24521
- return;
24522
- case "tool_start":
24523
- this.handleToolStart(event, options);
24524
- return;
24525
- case "tool_call":
24526
- this.handleToolCall(event);
24527
- return;
24528
- case "task_start":
24529
- this.handleTaskStart(event);
24530
- return;
24531
- case "task":
24532
- this.handleTask(event);
24533
- return;
24534
- case "compaction_start":
24535
- this.handleCompactionStart(event);
24536
- return;
24537
- case "compaction":
24538
- this.handleCompaction(event);
24539
- return;
24540
- default:
24541
- return;
24542
- }
24543
- }
24544
24193
  handleOperationStart(event) {
24545
- if (!isInstrumentedOperation(event.operationKind)) {
24546
- return;
24547
- }
24548
- const state = this.takePendingOperationForEvent(event);
24549
- if (!state) {
24194
+ if (!event.operationId || !isInstrumentedOperation(event.operationKind)) {
24550
24195
  return;
24551
24196
  }
24552
- state.operationId = event.operationId;
24553
- this.activeOperationsById.set(event.operationId, state);
24554
- addScopedOperation(this.activeOperationsByScope, event, state);
24555
- state.metadata = {
24556
- ...state.metadata,
24197
+ const metadata = {
24557
24198
  ...extractEventMetadata(event),
24558
- "flue.operation_id": event.operationId
24199
+ "flue.operation": event.operationKind,
24200
+ provider: "flue"
24559
24201
  };
24560
- safeLog3(state.span, { metadata: state.metadata });
24202
+ const parent = this.parentSpanForEvent(event);
24203
+ const span = startFlueSpan(parent, {
24204
+ name: `flue.${event.operationKind}`,
24205
+ spanAttributes: { type: "task" /* TASK */ },
24206
+ startTime: eventTime(event.timestamp),
24207
+ event: { metadata }
24208
+ });
24209
+ this.operationsById.set(event.operationId, { metadata, span });
24561
24210
  }
24562
24211
  handleOperation(event) {
24563
- const state = event.operationId ? this.activeOperationsById.get(event.operationId) : void 0;
24564
- if (!state) {
24212
+ if (!isInstrumentedOperation(event.operationKind)) {
24565
24213
  return;
24566
24214
  }
24215
+ const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
24216
+ const output = operationOutput(event);
24567
24217
  const metadata = {
24568
24218
  ...state.metadata,
24569
24219
  ...extractEventMetadata(event),
24570
- ...typeof event.durationMs === "number" ? { "flue.duration_ms": event.durationMs } : {},
24571
- ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24220
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
24221
+ ...event.usage ? { "flue.usage": event.usage } : {}
24572
24222
  };
24573
- const metrics = metricsFromUsage(event.usage);
24223
+ this.finishPendingChildrenForOperation(event, output);
24574
24224
  safeLog3(state.span, {
24575
- ...event.error ? { error: errorToString(event.error) } : {},
24225
+ ...event.isError ? { error: errorToString(event.error) } : {},
24576
24226
  metadata,
24577
- ...Object.keys(metrics).length ? { metrics } : {}
24227
+ metrics: durationMetrics2(event.durationMs),
24228
+ output
24578
24229
  });
24230
+ safeEnd(state.span, eventTime(event.timestamp));
24231
+ this.operationsById.delete(event.operationId);
24579
24232
  }
24580
- ensureTurnState(event) {
24581
- const scope = scopeKey(event);
24582
- const existing = this.turnsByScope.get(scope);
24583
- if (existing) {
24584
- return existing;
24233
+ handleTurnRequest(event) {
24234
+ const key = turnKey(event);
24235
+ if (!key) {
24236
+ return;
24585
24237
  }
24586
- const parent = this.parentSpanForEvent(event);
24587
24238
  const metadata = {
24588
24239
  ...extractEventMetadata(event),
24589
- provider: "flue"
24240
+ ...event.api ? { "flue.api": event.api } : {},
24241
+ ...event.model ? { model: event.model, "flue.model": event.model } : {},
24242
+ ...event.provider ? { provider: event.provider } : { provider: "flue" },
24243
+ ...event.provider ? { "flue.provider": event.provider } : {},
24244
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
24245
+ ...event.reasoning ? { reasoning: event.reasoning } : {},
24246
+ ...event.input?.systemPrompt ? { "flue.system_prompt": event.input.systemPrompt } : {},
24247
+ ...event.input?.tools ? { tools: event.input.tools } : {}
24590
24248
  };
24249
+ const parent = this.parentSpanForTurn(event);
24591
24250
  const span = startFlueSpan(parent, {
24592
- name: "flue.turn",
24593
- spanAttributes: { type: "llm" /* LLM */ }
24251
+ name: `llm:${event.model ?? event.purpose ?? "unknown"}`,
24252
+ spanAttributes: { type: "llm" /* LLM */ },
24253
+ startTime: eventTime(event.timestamp),
24254
+ event: {
24255
+ input: event.input?.messages,
24256
+ metadata
24257
+ }
24594
24258
  });
24595
- const state = {
24596
- metadata,
24597
- span,
24598
- hasThinking: false,
24599
- startTime: getCurrentUnixTimestamp(),
24600
- text: [],
24601
- thinking: [],
24602
- toolCalls: []
24603
- };
24604
- safeLog3(span, { metadata });
24605
- this.turnsByScope.set(scope, state);
24606
- return state;
24259
+ this.logOperationInput(
24260
+ event.operationId,
24261
+ event.input?.messages ?? event.input
24262
+ );
24263
+ this.turnsByKey.set(key, { metadata, span });
24607
24264
  }
24608
24265
  handleTurn(event) {
24609
- const scope = scopeKey(event);
24610
- const state = this.ensureTurnState(event);
24611
- const text = state.text.join("");
24612
- const reasoning = state.finalThinking ?? state.thinking.join("");
24613
- const outputReasoning = reasoning || (state.hasThinking ? "[reasoning stream present; content unavailable]" : void 0);
24266
+ const key = turnKey(event);
24267
+ if (!key) {
24268
+ return;
24269
+ }
24270
+ const state = this.turnsByKey.get(key) ?? this.startSyntheticTurn(event);
24614
24271
  const metadata = {
24615
24272
  ...state.metadata,
24616
24273
  ...extractEventMetadata(event),
24274
+ ...event.api ? { "flue.api": event.api } : {},
24617
24275
  ...event.model ? { model: event.model, "flue.model": event.model } : {},
24276
+ ...event.provider ? { provider: event.provider } : {},
24277
+ ...event.provider ? { "flue.provider": event.provider } : {},
24278
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
24618
24279
  ...event.stopReason ? { "flue.stop_reason": event.stopReason } : {},
24619
- ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
24620
- provider: "flue"
24280
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24621
24281
  };
24622
24282
  safeLog3(state.span, {
24623
- ...event.error ? { error: errorToString(event.error) } : {},
24283
+ ...event.isError ? { error: errorToString(event.error) } : {},
24624
24284
  metadata,
24625
24285
  metrics: {
24626
- ...durationMsMetrics(event.durationMs),
24286
+ ...durationMetrics2(event.durationMs),
24627
24287
  ...metricsFromUsage(event.usage)
24628
24288
  },
24629
- output: toAssistantOutput(
24630
- text,
24631
- event.stopReason,
24632
- outputReasoning,
24633
- state.toolCalls
24634
- )
24289
+ output: event.output
24635
24290
  });
24636
- state.span.end();
24637
- this.turnsByScope.delete(scope);
24291
+ safeEnd(state.span, eventTime(event.timestamp));
24292
+ this.turnsByKey.delete(key);
24638
24293
  }
24639
- handleThinkingDelta(event) {
24640
- const delta = event.delta;
24641
- if (typeof delta !== "string" || !delta) {
24294
+ handleToolStart(event) {
24295
+ if (!event.toolCallId) {
24642
24296
  return;
24643
24297
  }
24644
- const state = this.ensureTurnState(event);
24645
- state.hasThinking = true;
24646
- state.metadata["flue.thinking"] = true;
24647
- state.thinking.push(delta);
24648
- }
24649
- handleThinkingStart(event) {
24650
- const state = this.ensureTurnState(event);
24651
- state.hasThinking = true;
24652
- state.metadata["flue.thinking"] = true;
24653
- }
24654
- handleThinkingEnd(event) {
24655
- const state = this.ensureTurnState(event);
24656
- state.hasThinking = true;
24657
- state.metadata["flue.thinking"] = true;
24658
- if (typeof event.content === "string" && event.content) {
24659
- state.finalThinking = event.content;
24660
- }
24661
- }
24662
- handleToolStart(event, options) {
24663
- const toolCallId = event.toolCallId;
24664
- if (!toolCallId) {
24665
- return;
24666
- }
24667
- const parent = this.parentSpanForEvent(event);
24668
- const scope = scopeKey(event);
24669
- let turnState = this.turnsByScope.get(scope);
24670
- if (!turnState && parent && options.captureTurnSpans) {
24671
- turnState = this.ensureTurnState(event);
24672
- }
24673
24298
  const metadata = {
24674
24299
  ...extractEventMetadata(event),
24675
24300
  ...event.toolName ? { "flue.tool_name": event.toolName } : {},
24676
- "flue.tool_call_id": toolCallId,
24301
+ "flue.tool_call_id": event.toolCallId,
24677
24302
  provider: "flue"
24678
24303
  };
24304
+ const parent = this.parentSpanForTool(event);
24679
24305
  const span = startFlueSpan(parent, {
24680
- name: `tool: ${event.toolName ?? "unknown"}`,
24681
- spanAttributes: { type: "tool" /* TOOL */ }
24682
- });
24683
- if (turnState) {
24684
- turnState.toolCalls.push({
24685
- args: event.args,
24686
- toolCallId,
24687
- toolName: event.toolName
24688
- });
24689
- }
24690
- safeLog3(span, {
24691
- input: event.args,
24692
- metadata
24693
- });
24694
- this.toolsById.set(toolKey(event), {
24695
- metadata,
24696
- span,
24697
- startTime: getCurrentUnixTimestamp()
24306
+ name: `tool:${event.toolName ?? "unknown"}`,
24307
+ spanAttributes: { type: "tool" /* TOOL */ },
24308
+ startTime: eventTime(event.timestamp),
24309
+ event: {
24310
+ input: event.args,
24311
+ metadata
24312
+ }
24698
24313
  });
24314
+ this.toolsByKey.set(toolKey(event), { metadata, span });
24699
24315
  }
24700
24316
  handleToolCall(event) {
24317
+ if (!event.toolCallId) {
24318
+ return;
24319
+ }
24701
24320
  const key = toolKey(event);
24702
- const state = this.toolsById.get(key) ?? this.startSyntheticToolState(event, event.toolName ?? "unknown");
24321
+ const state = this.toolsByKey.get(key) ?? this.startSyntheticTool(event);
24703
24322
  const metadata = {
24704
24323
  ...state.metadata,
24705
24324
  ...extractEventMetadata(event),
24706
24325
  ...event.toolName ? { "flue.tool_name": event.toolName } : {},
24707
- ...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
24326
+ "flue.tool_call_id": event.toolCallId,
24708
24327
  ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24709
24328
  };
24710
24329
  safeLog3(state.span, {
24711
24330
  ...event.isError ? { error: errorToString(event.result) } : {},
24712
24331
  metadata,
24713
- metrics: durationMsMetrics(event.durationMs),
24332
+ metrics: durationMetrics2(event.durationMs),
24714
24333
  output: event.result
24715
24334
  });
24716
- state.span.end();
24717
- this.toolsById.delete(key);
24335
+ safeEnd(state.span, eventTime(event.timestamp));
24336
+ this.toolsByKey.delete(key);
24718
24337
  }
24719
24338
  handleTaskStart(event) {
24720
- const parent = this.parentSpanForEvent(event);
24339
+ if (!event.taskId) {
24340
+ return;
24341
+ }
24721
24342
  const metadata = {
24722
24343
  ...extractEventMetadata(event),
24723
- ...event.role ? { "flue.role": event.role } : {},
24344
+ ...event.agent ? { "flue.agent": event.agent } : {},
24724
24345
  ...event.cwd ? { "flue.cwd": event.cwd } : {},
24725
24346
  "flue.task_id": event.taskId,
24726
24347
  provider: "flue"
24727
24348
  };
24349
+ const parent = this.parentSpanForEvent(event);
24728
24350
  const span = startFlueSpan(parent, {
24729
- name: "flue.task",
24730
- spanAttributes: { type: "task" /* TASK */ }
24731
- });
24732
- safeLog3(span, {
24733
- input: event.prompt,
24734
- metadata
24735
- });
24736
- this.tasksById.set(event.taskId, {
24737
- metadata,
24738
- span,
24739
- startTime: getCurrentUnixTimestamp()
24351
+ name: event.agent ? `task:${event.agent}` : "flue.task",
24352
+ spanAttributes: { type: "task" /* TASK */ },
24353
+ startTime: eventTime(event.timestamp),
24354
+ event: {
24355
+ input: event.prompt,
24356
+ metadata
24357
+ }
24740
24358
  });
24359
+ this.tasksById.set(event.taskId, { metadata, span });
24741
24360
  }
24742
24361
  handleTask(event) {
24743
24362
  const state = this.tasksById.get(event.taskId);
@@ -24749,426 +24368,372 @@ var FluePlugin = class extends BasePlugin {
24749
24368
  metadata: {
24750
24369
  ...state.metadata,
24751
24370
  ...extractEventMetadata(event),
24371
+ ...event.agent ? { "flue.agent": event.agent } : {},
24752
24372
  ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24753
24373
  },
24754
- metrics: durationMsMetrics(event.durationMs),
24374
+ metrics: durationMetrics2(event.durationMs),
24755
24375
  output: event.result
24756
24376
  });
24757
- state.span.end();
24377
+ safeEnd(state.span, eventTime(event.timestamp));
24758
24378
  this.tasksById.delete(event.taskId);
24759
24379
  }
24760
24380
  handleCompactionStart(event) {
24761
- const operationState = this.operationStateForEvent(event);
24762
- const parent = operationState?.span ?? this.parentSpanForEvent(event);
24381
+ const key = compactionKey(event);
24382
+ const input = {
24383
+ ...event.estimatedTokens !== void 0 ? { estimatedTokens: event.estimatedTokens } : {},
24384
+ ...event.reason ? { reason: event.reason } : {}
24385
+ };
24763
24386
  const metadata = {
24764
24387
  ...extractEventMetadata(event),
24765
24388
  ...event.reason ? { "flue.compaction_reason": event.reason } : {},
24766
24389
  provider: "flue"
24767
24390
  };
24768
- const input = {
24769
- ...typeof event.estimatedTokens === "number" ? { estimatedTokens: event.estimatedTokens } : {},
24770
- ...event.reason ? { reason: event.reason } : {}
24771
- };
24391
+ const parent = this.parentSpanForEvent(event);
24772
24392
  const span = startFlueSpan(parent, {
24773
- name: "flue.compaction",
24774
- spanAttributes: { type: "task" /* TASK */ }
24775
- });
24776
- safeLog3(span, {
24777
- input,
24778
- metadata
24779
- });
24780
- this.compactionsByScope.set(scopeKey(event), {
24781
- input,
24782
- metadata,
24783
- operationState,
24784
- span,
24785
- startTime: getCurrentUnixTimestamp()
24393
+ name: `compaction:${event.reason ?? "unknown"}`,
24394
+ spanAttributes: { type: "task" /* TASK */ },
24395
+ startTime: eventTime(event.timestamp),
24396
+ event: {
24397
+ input,
24398
+ metadata
24399
+ }
24786
24400
  });
24401
+ this.logOperationInput(event.operationId, input);
24402
+ this.compactionsByKey.set(key, { metadata, span });
24787
24403
  }
24788
24404
  handleCompaction(event) {
24789
- const key = scopeKey(event);
24790
- const state = this.compactionsByScope.get(key) ?? this.findCompactionState(event);
24791
- if (!state) {
24792
- return;
24793
- }
24405
+ const key = compactionKey(event);
24406
+ const state = this.compactionsByKey.get(key) ?? this.startSyntheticCompaction(event);
24407
+ const metadata = {
24408
+ ...state.metadata,
24409
+ ...extractEventMetadata(event),
24410
+ ...event.usage ? { "flue.usage": event.usage } : {}
24411
+ };
24794
24412
  safeLog3(state.span, {
24795
- metadata: {
24796
- ...state.metadata,
24797
- ...extractEventMetadata(event),
24798
- ...typeof event.messagesBefore === "number" ? { "flue.messages_before": event.messagesBefore } : {},
24799
- ...typeof event.messagesAfter === "number" ? { "flue.messages_after": event.messagesAfter } : {}
24800
- },
24413
+ metadata,
24801
24414
  metrics: {
24802
- ...durationMsMetrics(event.durationMs),
24803
- ...metricsFromUsage(event.usage)
24415
+ ...durationMetrics2(event.durationMs),
24416
+ ...typeof event.messagesBefore === "number" ? { messages_before: event.messagesBefore } : {},
24417
+ ...typeof event.messagesAfter === "number" ? { messages_after: event.messagesAfter } : {}
24804
24418
  },
24805
24419
  output: {
24806
24420
  messagesAfter: event.messagesAfter,
24807
24421
  messagesBefore: event.messagesBefore
24808
24422
  }
24809
24423
  });
24810
- state.span.end();
24811
- this.deleteCompactionState(state);
24424
+ safeEnd(state.span, eventTime(event.timestamp));
24425
+ this.compactionsByKey.delete(key);
24812
24426
  }
24813
- findCompactionState(event) {
24814
- const operationState = this.operationStateForEvent(event);
24815
- for (const state of this.compactionsByScope.values()) {
24816
- if (operationState && state.operationState === operationState) {
24817
- return state;
24427
+ parentSpanForTurn(event) {
24428
+ if (event.purpose === "compaction" || event.purpose === "compaction_prefix") {
24429
+ const compaction = this.compactionsByKey.get(compactionKey(event));
24430
+ if (compaction) {
24431
+ return compaction.span;
24818
24432
  }
24819
24433
  }
24820
- return void 0;
24434
+ return this.parentSpanForEvent(event);
24821
24435
  }
24822
- finishCompactionsForOperation(operationState) {
24823
- for (const state of [...this.compactionsByScope.values()]) {
24824
- if (state.operationState !== operationState) {
24825
- continue;
24436
+ parentSpanForEvent(event) {
24437
+ const turn = turnKey(event);
24438
+ if (turn) {
24439
+ const turnState = this.turnsByKey.get(turn);
24440
+ if (turnState) {
24441
+ return turnState.span;
24826
24442
  }
24827
- safeLog3(state.span, {
24828
- input: state.input,
24829
- metadata: state.metadata,
24830
- metrics: {
24831
- ...buildDurationMetrics3(state.startTime)
24832
- },
24833
- output: { completed: true }
24834
- });
24835
- state.span.end();
24836
- this.deleteCompactionState(state);
24837
24443
  }
24838
- }
24839
- deleteCompactionState(state) {
24840
- for (const [key, candidate] of this.compactionsByScope) {
24841
- if (candidate !== state) {
24842
- continue;
24444
+ if (event.taskId) {
24445
+ const task = this.tasksById.get(event.taskId);
24446
+ if (task) {
24447
+ return task.span;
24843
24448
  }
24844
- this.compactionsByScope.delete(key);
24845
- return;
24846
24449
  }
24847
- }
24848
- startSyntheticToolState(event, toolName) {
24849
- const parent = this.parentSpanForEvent(event);
24850
- const metadata = {
24851
- ...extractEventMetadata(event),
24852
- ...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
24853
- "flue.tool_name": toolName,
24854
- provider: "flue"
24855
- };
24856
- const span = startFlueSpan(parent, {
24857
- name: `tool: ${toolName}`,
24858
- spanAttributes: { type: "tool" /* TOOL */ }
24859
- });
24860
- safeLog3(span, { metadata });
24861
- return { metadata, span, startTime: getCurrentUnixTimestamp() };
24862
- }
24863
- operationStateForEvent(event) {
24864
24450
  if (event.operationId) {
24865
- const operation = this.activeOperationsById.get(event.operationId) ?? this.promotePendingOperationForEvent(event);
24451
+ const operation = this.operationsById.get(event.operationId);
24866
24452
  if (operation) {
24867
- return operation;
24453
+ return operation.span;
24868
24454
  }
24869
24455
  }
24870
- return this.activeOperationForEventScope(event) ?? this.pendingOperationForEventScope(event);
24456
+ if (event.runId) {
24457
+ return this.runsById.get(event.runId)?.span;
24458
+ }
24459
+ return void 0;
24871
24460
  }
24872
- parentSpanForEvent(event) {
24461
+ parentSpanForTool(event) {
24462
+ if (event.taskId) {
24463
+ const task = this.tasksById.get(event.taskId);
24464
+ if (task) {
24465
+ return task.span;
24466
+ }
24467
+ }
24873
24468
  if (event.operationId) {
24874
- const operation = this.operationStateForEvent(event);
24469
+ const operation = this.operationsById.get(event.operationId);
24875
24470
  if (operation) {
24876
24471
  return operation.span;
24877
24472
  }
24878
24473
  }
24879
- if (event.taskId) {
24880
- return this.tasksById.get(event.taskId)?.span;
24474
+ if (event.runId) {
24475
+ return this.runsById.get(event.runId)?.span;
24881
24476
  }
24882
- return this.operationStateForEvent(event)?.span;
24477
+ return void 0;
24883
24478
  }
24884
- promotePendingOperationForEvent(event) {
24885
- if (!event.operationId) {
24886
- return void 0;
24479
+ logOperationInput(operationId, input) {
24480
+ if (!operationId || input === void 0) {
24481
+ return;
24887
24482
  }
24888
- const scopePrefixes = operationScopePrefixes(event);
24889
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
24890
- if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
24483
+ const operation = this.operationsById.get(operationId);
24484
+ if (!operation || operation.loggedInput) {
24485
+ return;
24486
+ }
24487
+ safeLog3(operation.span, { input });
24488
+ operation.loggedInput = true;
24489
+ }
24490
+ startSyntheticOperation(event) {
24491
+ const metadata = {
24492
+ ...extractEventMetadata(event),
24493
+ "flue.operation": event.operationKind,
24494
+ provider: "flue"
24495
+ };
24496
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
24497
+ name: `flue.${event.operationKind}`,
24498
+ spanAttributes: { type: "task" /* TASK */ },
24499
+ startTime: eventTime(event.timestamp),
24500
+ event: { metadata }
24501
+ });
24502
+ return { metadata, span };
24503
+ }
24504
+ startSyntheticTurn(event) {
24505
+ const metadata = {
24506
+ ...extractEventMetadata(event),
24507
+ ...event.api ? { "flue.api": event.api } : {},
24508
+ ...event.model ? { model: event.model, "flue.model": event.model } : {},
24509
+ ...event.provider ? { provider: event.provider } : { provider: "flue" },
24510
+ ...event.provider ? { "flue.provider": event.provider } : {},
24511
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
24512
+ };
24513
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
24514
+ name: `llm:${event.model ?? event.purpose ?? "unknown"}`,
24515
+ spanAttributes: { type: "llm" /* LLM */ },
24516
+ startTime: eventTime(event.timestamp),
24517
+ event: { metadata }
24518
+ });
24519
+ return { metadata, span };
24520
+ }
24521
+ startSyntheticTool(event) {
24522
+ const metadata = {
24523
+ ...extractEventMetadata(event),
24524
+ ...event.toolName ? { "flue.tool_name": event.toolName } : {},
24525
+ "flue.tool_call_id": event.toolCallId,
24526
+ provider: "flue"
24527
+ };
24528
+ const span = startFlueSpan(this.parentSpanForTool(event), {
24529
+ name: `tool:${event.toolName ?? "unknown"}`,
24530
+ spanAttributes: { type: "tool" /* TOOL */ },
24531
+ startTime: eventTime(event.timestamp),
24532
+ event: { metadata }
24533
+ });
24534
+ return { metadata, span };
24535
+ }
24536
+ startSyntheticCompaction(event) {
24537
+ const metadata = {
24538
+ ...extractEventMetadata(event),
24539
+ provider: "flue"
24540
+ };
24541
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
24542
+ name: "compaction:unknown",
24543
+ spanAttributes: { type: "task" /* TASK */ },
24544
+ startTime: eventTime(event.timestamp),
24545
+ event: { metadata }
24546
+ });
24547
+ return { metadata, span };
24548
+ }
24549
+ finishPendingChildrenForOperation(event, operationOutput2) {
24550
+ const endTime = eventTime(event.timestamp);
24551
+ const usage = event.usage ?? usageFromOperationResult(event.result);
24552
+ const turnEntries = [...this.turnsByKey].filter(
24553
+ ([, state]) => stateMatchesOperation(state, event.operationId)
24554
+ );
24555
+ turnEntries.forEach(([key, state], index) => {
24556
+ const shouldLogOperationOutput = (event.operationKind === "prompt" || event.operationKind === "skill") && index === turnEntries.length - 1 && operationOutput2 !== void 0;
24557
+ safeLog3(state.span, {
24558
+ metadata: state.metadata,
24559
+ metrics: metricsFromUsage(usage),
24560
+ ...shouldLogOperationOutput ? { output: operationOutput2 } : {}
24561
+ });
24562
+ safeEnd(state.span, endTime);
24563
+ this.turnsByKey.delete(key);
24564
+ });
24565
+ for (const [key, state] of this.toolsByKey) {
24566
+ if (!stateMatchesOperation(state, event.operationId)) {
24891
24567
  continue;
24892
24568
  }
24893
- const state = candidateQueue.shift();
24894
- if (!state) {
24895
- return void 0;
24569
+ safeEnd(state.span, endTime);
24570
+ this.toolsByKey.delete(key);
24571
+ }
24572
+ for (const [key, state] of this.tasksById) {
24573
+ if (!stateMatchesOperation(state, event.operationId)) {
24574
+ continue;
24896
24575
  }
24897
- state.operationId = event.operationId;
24898
- this.activeOperationsById.set(event.operationId, state);
24899
- addScopedOperation(this.activeOperationsByScope, event, state);
24900
- state.metadata = {
24901
- ...state.metadata,
24902
- ...extractEventMetadata(event),
24903
- "flue.operation_id": event.operationId
24904
- };
24905
- safeLog3(state.span, { metadata: state.metadata });
24906
- return state;
24576
+ safeEnd(state.span, endTime);
24577
+ this.tasksById.delete(key);
24907
24578
  }
24908
- return void 0;
24909
- }
24910
- activeOperationForEventScope(event) {
24911
- for (const scope of operationScopeNames(event)) {
24912
- const operations = this.activeOperationsByScope.get(scope);
24913
- if (operations?.length) {
24914
- return operations[operations.length - 1];
24579
+ for (const [key, state] of this.compactionsByKey) {
24580
+ if (!stateMatchesOperation(state, event.operationId)) {
24581
+ continue;
24915
24582
  }
24583
+ safeLog3(state.span, {
24584
+ metadata: state.metadata,
24585
+ metrics: durationMetrics2(event.durationMs),
24586
+ output: { completed: true }
24587
+ });
24588
+ safeEnd(state.span, eventTime(event.timestamp));
24589
+ this.compactionsByKey.delete(key);
24916
24590
  }
24917
- return void 0;
24918
24591
  }
24919
- pendingOperationForEventScope(event) {
24920
- const scopePrefixes = operationScopePrefixes(event);
24921
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
24922
- if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
24592
+ finishPendingSpansForRun(event) {
24593
+ const endTime = eventTime(event.timestamp);
24594
+ for (const [key, state] of this.toolsByKey) {
24595
+ if (!stateMatchesRun(state, event.runId)) {
24923
24596
  continue;
24924
24597
  }
24925
- return candidateQueue[0];
24598
+ safeEnd(state.span, endTime);
24599
+ this.toolsByKey.delete(key);
24926
24600
  }
24927
- return void 0;
24928
- }
24929
- takePendingOperationForEvent(event) {
24930
- const key = operationKey(event.session, event.operationKind);
24931
- const queue2 = this.pendingOperationsByKey.get(key);
24932
- if (queue2?.length) {
24933
- return queue2.shift();
24601
+ for (const [key, state] of this.turnsByKey) {
24602
+ if (!stateMatchesRun(state, event.runId)) {
24603
+ continue;
24604
+ }
24605
+ safeEnd(state.span, endTime);
24606
+ this.turnsByKey.delete(key);
24934
24607
  }
24935
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
24936
- if (candidateKey.endsWith(`::${event.operationKind}`) && candidateQueue.length) {
24937
- return candidateQueue.shift();
24608
+ for (const [key, state] of this.tasksById) {
24609
+ if (!stateMatchesRun(state, event.runId)) {
24610
+ continue;
24938
24611
  }
24612
+ safeEnd(state.span, endTime);
24613
+ this.tasksById.delete(key);
24939
24614
  }
24940
- return void 0;
24941
- }
24942
- pendingOperationQueue(key) {
24943
- const existing = this.pendingOperationsByKey.get(key);
24944
- if (existing) {
24945
- return existing;
24615
+ for (const [key, state] of this.compactionsByKey) {
24616
+ if (!stateMatchesRun(state, event.runId)) {
24617
+ continue;
24618
+ }
24619
+ safeLog3(state.span, {
24620
+ metadata: state.metadata,
24621
+ output: { completed: true }
24622
+ });
24623
+ safeEnd(state.span, endTime);
24624
+ this.compactionsByKey.delete(key);
24625
+ }
24626
+ for (const [key, state] of this.operationsById) {
24627
+ if (!stateMatchesRun(state, event.runId)) {
24628
+ continue;
24629
+ }
24630
+ safeLog3(state.span, {
24631
+ metadata: state.metadata,
24632
+ ...state.metadata["flue.operation"] === "compact" ? { output: { completed: true } } : {}
24633
+ });
24634
+ safeEnd(state.span, endTime);
24635
+ this.operationsById.delete(key);
24946
24636
  }
24947
- const queue2 = [];
24948
- this.pendingOperationsByKey.set(key, queue2);
24949
- return queue2;
24950
24637
  }
24951
24638
  };
24952
24639
  function isInstrumentedOperation(operation) {
24953
- return operation === "prompt" || operation === "skill" || operation === "task" || operation === "compact";
24954
- }
24955
- function getSessionName(session) {
24956
- return typeof session?.name === "string" ? session.name : void 0;
24957
- }
24958
- function operationKey(sessionName, operation) {
24959
- return `${sessionName ?? "unknown"}::${operation}`;
24960
- }
24961
- function operationScopePrefixes(event) {
24962
- const scopes = /* @__PURE__ */ new Set();
24963
- for (const scope of operationScopeNames(event)) {
24964
- scopes.add(`${scope}::`);
24965
- }
24966
- return scopes;
24640
+ return operation === "prompt" || operation === "skill" || operation === "compact";
24967
24641
  }
24968
- function operationKeyMatchesScopes(key, scopes) {
24969
- for (const scope of scopes) {
24970
- if (key.startsWith(scope)) {
24971
- return true;
24972
- }
24973
- }
24974
- return false;
24975
- }
24976
- function operationScopeNames(event) {
24977
- const scopes = /* @__PURE__ */ new Set();
24978
- if (event.session) {
24979
- scopes.add(event.session);
24980
- }
24981
- if (event.parentSession) {
24982
- scopes.add(event.parentSession);
24983
- }
24984
- if (!scopes.size) {
24985
- scopes.add("unknown");
24986
- }
24987
- return scopes;
24988
- }
24989
- function addScopedOperation(operationsByScope, event, state) {
24990
- for (const scope of operationScopeNames(event)) {
24991
- addOperationToScope(operationsByScope, scope, state);
24992
- }
24993
- }
24994
- function addOperationToScope(operationsByScope, scope, state) {
24995
- const operations = operationsByScope.get(scope);
24996
- if (operations) {
24997
- if (!operations.includes(state)) {
24998
- operations.push(state);
24999
- }
25000
- } else {
25001
- operationsByScope.set(scope, [state]);
25002
- }
25003
- }
25004
- function removeScopedOperation(operationsByScope, state) {
25005
- for (const [scope, operations] of operationsByScope) {
25006
- const index = operations.indexOf(state);
25007
- if (index === -1) {
25008
- continue;
25009
- }
25010
- operations.splice(index, 1);
25011
- if (operations.length === 0) {
25012
- operationsByScope.delete(scope);
25013
- }
25014
- }
25015
- }
25016
- function removePendingOperation(pendingOperationsByKey, state) {
25017
- for (const [key, queue2] of pendingOperationsByKey) {
25018
- const index = queue2.indexOf(state);
25019
- if (index === -1) {
25020
- continue;
25021
- }
25022
- queue2.splice(index, 1);
25023
- if (queue2.length === 0) {
25024
- pendingOperationsByKey.delete(key);
25025
- }
25026
- return;
25027
- }
25028
- }
25029
- function extractSessionMetadata(session) {
25030
- const sessionName = getSessionName(session);
25031
- return sessionName ? { "flue.session": sessionName } : {};
25032
- }
25033
- function extractEventMetadata(event) {
24642
+ function extractEventMetadata(event, ctx) {
25034
24643
  return {
25035
24644
  ...event.runId ? { "flue.run_id": event.runId } : {},
24645
+ ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
24646
+ ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
25036
24647
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
25037
24648
  ...event.session ? { "flue.session": event.session } : {},
25038
24649
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
25039
24650
  ...event.harness ? { "flue.harness": event.harness } : {},
25040
24651
  ...event.taskId ? { "flue.task_id": event.taskId } : {},
25041
- ...event.operationId ? { "flue.operation_id": event.operationId } : {}
24652
+ ...event.operationId ? { "flue.operation_id": event.operationId } : {},
24653
+ ...event.turnId ? { "flue.turn_id": event.turnId } : {},
24654
+ ...typeof ctx?.id === "string" ? { "flue.context_id": ctx.id } : {},
24655
+ ...typeof ctx?.runId === "string" ? { "flue.context_run_id": ctx.runId } : {}
25042
24656
  };
25043
24657
  }
25044
- function extractOperationInput(operation, args) {
25045
- switch (operation) {
25046
- case "prompt":
25047
- case "task":
25048
- return args[0];
25049
- case "skill":
25050
- return {
25051
- args: getOptionObject(args[1])?.args,
25052
- name: args[0]
25053
- };
25054
- case "compact":
25055
- return void 0;
24658
+ function extractPayloadMetadata(payload) {
24659
+ if (!isObjectLike(payload)) {
24660
+ return {};
25056
24661
  }
24662
+ const metadata = Reflect.get(payload, "metadata");
24663
+ if (!isObjectLike(metadata)) {
24664
+ return {};
24665
+ }
24666
+ return Object.fromEntries(Object.entries(metadata));
25057
24667
  }
25058
- function extractOperationInputMetadata(operation, args) {
25059
- const options = getOptionObject(args[1]);
25060
- return {
25061
- ...operation === "skill" && typeof args[0] === "string" ? { "flue.skill_name": args[0] } : {},
25062
- ...options?.model ? { model: options.model, "flue.model": options.model } : {},
25063
- ...options?.role ? { "flue.role": options.role } : {},
25064
- ...options?.thinkingLevel ? { "flue.thinking_level": options.thinkingLevel } : {},
25065
- ...typeof options?.cwd === "string" ? { "flue.cwd": options.cwd } : {},
25066
- ...Array.isArray(options?.tools) ? {
25067
- "flue.tools_count": options.tools.length,
25068
- tools: summarizeTools(options.tools)
25069
- } : {},
25070
- ...Array.isArray(options?.images) ? { "flue.images_count": options.images.length } : {},
25071
- ...options?.result || options?.schema ? { "flue.result_schema": true } : {}
25072
- };
25073
- }
25074
- function getOptionObject(value) {
25075
- return isObject(value) ? value : void 0;
25076
- }
25077
- function summarizeTools(tools) {
25078
- return tools.flatMap((tool) => {
25079
- if (!isObject(tool)) {
25080
- return [];
25081
- }
25082
- const name = typeof tool.name === "string" ? tool.name : void 0;
25083
- if (!name) {
25084
- return [];
25085
- }
25086
- return [
25087
- {
25088
- function: {
25089
- description: typeof tool.description === "string" ? tool.description : void 0,
25090
- name,
25091
- parameters: tool.parameters
25092
- },
25093
- type: "function"
25094
- }
25095
- ];
25096
- });
24668
+ function operationOutput(event) {
24669
+ if (event.operationKind === "prompt" || event.operationKind === "skill") {
24670
+ return llmResultFromOperationResult(event.result);
24671
+ }
24672
+ return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
25097
24673
  }
25098
- function extractPromptResponseMetadata(result) {
25099
- const modelId = result?.model && typeof result.model.id === "string" ? result.model.id : void 0;
25100
- return modelId ? {
25101
- model: modelId,
25102
- "flue.model": modelId
25103
- } : {};
24674
+ function llmResultFromOperationResult(result) {
24675
+ if (!isObjectLike(result)) {
24676
+ return result;
24677
+ }
24678
+ const text = Reflect.get(result, "text");
24679
+ return text === void 0 ? result : text;
25104
24680
  }
25105
- function extractOperationOutput(result) {
25106
- if (!result) {
24681
+ function usageFromOperationResult(result) {
24682
+ if (!isObjectLike(result)) {
25107
24683
  return void 0;
25108
24684
  }
25109
- if ("data" in result) {
25110
- return result.data;
25111
- }
25112
- if ("text" in result) {
25113
- return result.text;
25114
- }
25115
- return result;
24685
+ return Reflect.get(result, "usage");
25116
24686
  }
25117
24687
  function metricsFromUsage(usage) {
24688
+ if (!isObjectLike(usage)) {
24689
+ return {};
24690
+ }
24691
+ const cacheRead = Reflect.get(usage, "cacheRead");
24692
+ const cacheWrite = Reflect.get(usage, "cacheWrite");
24693
+ const cost = Reflect.get(usage, "cost");
24694
+ const input = Reflect.get(usage, "input");
24695
+ const output = Reflect.get(usage, "output");
24696
+ const totalTokens = Reflect.get(usage, "totalTokens");
24697
+ const totalCost = isObjectLike(cost) ? Reflect.get(cost, "total") : void 0;
25118
24698
  return {
25119
- ...typeof usage?.input === "number" ? { prompt_tokens: usage.input } : {},
25120
- ...typeof usage?.output === "number" ? { completion_tokens: usage.output } : {},
25121
- ...typeof usage?.cacheRead === "number" ? { prompt_cached_tokens: usage.cacheRead } : {},
25122
- ...typeof usage?.cacheWrite === "number" ? { prompt_cache_creation_tokens: usage.cacheWrite } : {},
25123
- ...typeof usage?.totalTokens === "number" ? { tokens: usage.totalTokens } : {},
25124
- ...typeof usage?.cost?.total === "number" ? { estimated_cost: usage.cost.total } : {}
25125
- };
25126
- }
25127
- function buildDurationMetrics3(startTime) {
25128
- return {
25129
- duration_ms: Math.max(0, (getCurrentUnixTimestamp() - startTime) * 1e3)
24699
+ ...typeof input === "number" ? { prompt_tokens: input } : {},
24700
+ ...typeof output === "number" ? { completion_tokens: output } : {},
24701
+ ...typeof cacheRead === "number" ? { prompt_cached_tokens: cacheRead } : {},
24702
+ ...typeof cacheWrite === "number" ? { prompt_cache_creation_tokens: cacheWrite } : {},
24703
+ ...typeof totalTokens === "number" ? { tokens: totalTokens } : {},
24704
+ ...typeof totalCost === "number" ? { estimated_cost: totalCost } : {}
25130
24705
  };
25131
24706
  }
25132
- function durationMsMetrics(durationMs) {
24707
+ function durationMetrics2(durationMs) {
25133
24708
  return typeof durationMs === "number" ? { duration_ms: durationMs } : {};
25134
24709
  }
25135
- function scopeKey(event) {
25136
- if (event.operationId) {
25137
- return `operation:${event.operationId}`;
25138
- }
25139
- if (event.taskId) {
25140
- return `task:${event.taskId}`;
25141
- }
25142
- if (event.session) {
25143
- return `session:${event.session}`;
24710
+ function eventTime(value) {
24711
+ if (typeof value !== "string") {
24712
+ return void 0;
25144
24713
  }
25145
- return "flue:unknown";
24714
+ const timestamp = Date.parse(value);
24715
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
24716
+ }
24717
+ function turnKey(event) {
24718
+ return event.turnId;
25146
24719
  }
25147
24720
  function toolKey(event) {
25148
- return `${scopeKey(event)}::tool:${event.toolCallId ?? "unknown"}`;
24721
+ return `${event.turnId ?? event.operationId ?? event.taskId ?? event.runId ?? "unknown"}:${event.toolCallId ?? "unknown"}`;
25149
24722
  }
25150
- function toAssistantOutput(text, finishReason, reasoning, toolCalls) {
24723
+ function compactionKey(event) {
25151
24724
  return [
25152
- {
25153
- finish_reason: finishReason ?? "stop",
25154
- index: 0,
25155
- message: {
25156
- content: text,
25157
- ...reasoning ? { reasoning } : {},
25158
- role: "assistant",
25159
- ...toolCalls?.length ? {
25160
- tool_calls: toolCalls.map((toolCall) => ({
25161
- function: {
25162
- arguments: toolCall.args === void 0 ? "{}" : JSON.stringify(toolCall.args),
25163
- name: toolCall.toolName ?? "unknown"
25164
- },
25165
- ...toolCall.toolCallId ? { id: toolCall.toolCallId } : {},
25166
- type: "function"
25167
- }))
25168
- } : {}
25169
- }
25170
- }
25171
- ];
24725
+ event.instanceId ?? "",
24726
+ event.runId ?? "",
24727
+ event.session ?? "",
24728
+ event.operationId ?? "",
24729
+ event.taskId ?? ""
24730
+ ].join(":");
24731
+ }
24732
+ function stateMatchesOperation(state, operationId) {
24733
+ return state.metadata["flue.operation_id"] === operationId;
24734
+ }
24735
+ function stateMatchesRun(state, runId) {
24736
+ return state.metadata["flue.run_id"] === runId;
25172
24737
  }
25173
24738
  function startFlueSpan(parent, args) {
25174
24739
  return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
@@ -25180,6 +24745,13 @@ function safeLog3(span, event) {
25180
24745
  logInstrumentationError3("Flue span log", error);
25181
24746
  }
25182
24747
  }
24748
+ function safeEnd(span, endTime) {
24749
+ try {
24750
+ span.end(endTime === void 0 ? void 0 : { endTime });
24751
+ } catch (error) {
24752
+ logInstrumentationError3("Flue span end", error);
24753
+ }
24754
+ }
25183
24755
  function errorToString(error) {
25184
24756
  if (error instanceof Error) {
25185
24757
  return error.message;
@@ -26174,6 +25746,7 @@ __export(exports_exports, {
26174
25746
  LEGACY_CACHED_HEADER: () => LEGACY_CACHED_HEADER,
26175
25747
  LOGS3_OVERFLOW_REFERENCE_TYPE: () => LOGS3_OVERFLOW_REFERENCE_TYPE,
26176
25748
  LazyValue: () => LazyValue,
25749
+ LocalTrace: () => LocalTrace,
26177
25750
  Logger: () => Logger,
26178
25751
  LoginInvalidOrgError: () => LoginInvalidOrgError,
26179
25752
  NOOP_SPAN: () => NOOP_SPAN,
@@ -26199,6 +25772,7 @@ __export(exports_exports, {
26199
25772
  _internalIso: () => isomorph_default,
26200
25773
  _internalSetInitialState: () => _internalSetInitialState,
26201
25774
  addAzureBlobHeaders: () => addAzureBlobHeaders,
25775
+ braintrustFlueObserver: () => braintrustFlueObserver,
26202
25776
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
26203
25777
  buildLocalSummary: () => buildLocalSummary,
26204
25778
  configureInstrumentation: () => configureInstrumentation,
@@ -26278,8 +25852,6 @@ __export(exports_exports, {
26278
25852
  wrapCohere: () => wrapCohere,
26279
25853
  wrapCopilotClient: () => wrapCopilotClient,
26280
25854
  wrapCursorSDK: () => wrapCursorSDK,
26281
- wrapFlueContext: () => wrapFlueContext,
26282
- wrapFlueSession: () => wrapFlueSession,
26283
25855
  wrapGenkit: () => wrapGenkit,
26284
25856
  wrapGoogleADK: () => wrapGoogleADK,
26285
25857
  wrapGoogleGenAI: () => wrapGoogleGenAI,
@@ -26408,6 +25980,7 @@ async function invoke(args) {
26408
25980
  mode,
26409
25981
  schema,
26410
25982
  strict,
25983
+ overrides,
26411
25984
  projectId,
26412
25985
  ...functionIdArgs
26413
25986
  } = args;
@@ -26444,7 +26017,8 @@ async function invoke(args) {
26444
26017
  tags,
26445
26018
  stream,
26446
26019
  mode,
26447
- strict
26020
+ strict,
26021
+ overrides
26448
26022
  };
26449
26023
  const headers = {
26450
26024
  Accept: stream ? "text/event-stream" : "application/json"
@@ -33479,6 +33053,7 @@ export {
33479
33053
  LEGACY_CACHED_HEADER,
33480
33054
  LOGS3_OVERFLOW_REFERENCE_TYPE,
33481
33055
  LazyValue,
33056
+ LocalTrace,
33482
33057
  Logger,
33483
33058
  LoginInvalidOrgError,
33484
33059
  NOOP_SPAN,
@@ -33504,6 +33079,7 @@ export {
33504
33079
  isomorph_default as _internalIso,
33505
33080
  _internalSetInitialState,
33506
33081
  addAzureBlobHeaders,
33082
+ braintrustFlueObserver,
33507
33083
  braintrustStreamChunkSchema,
33508
33084
  buildLocalSummary,
33509
33085
  configureInstrumentation,
@@ -33584,8 +33160,6 @@ export {
33584
33160
  wrapCohere,
33585
33161
  wrapCopilotClient,
33586
33162
  wrapCursorSDK,
33587
- wrapFlueContext,
33588
- wrapFlueSession,
33589
33163
  wrapGenkit,
33590
33164
  wrapGoogleADK,
33591
33165
  wrapGoogleGenAI,