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/index.mjs CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  openRouterChannels,
27
27
  patchTracingChannel,
28
28
  readDisabledInstrumentationEnvConfig
29
- } from "./chunk-NU2GSPHX.mjs";
29
+ } from "./chunk-O4ZIWXO3.mjs";
30
30
 
31
31
  // src/node/config.ts
32
32
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -3854,7 +3854,7 @@ function btStreamParser() {
3854
3854
  },
3855
3855
  async transform(chunk, controller) {
3856
3856
  if (chunk instanceof Uint8Array) {
3857
- parser.feed(decoder.decode(chunk));
3857
+ parser.feed(decoder.decode(chunk, { stream: true }));
3858
3858
  } else if (typeof chunk === "string") {
3859
3859
  parser.feed(chunk);
3860
3860
  } else {
@@ -3862,6 +3862,10 @@ function btStreamParser() {
3862
3862
  }
3863
3863
  },
3864
3864
  async flush(controller) {
3865
+ const tail = decoder.decode();
3866
+ if (tail) {
3867
+ parser.feed(tail);
3868
+ }
3865
3869
  controller.terminate();
3866
3870
  }
3867
3871
  });
@@ -23598,798 +23602,437 @@ var GitHubCopilotPlugin = class extends BasePlugin {
23598
23602
  }
23599
23603
  };
23600
23604
 
23601
- // src/wrappers/flue.ts
23602
- var WRAPPED_FLUE_CONTEXT = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-context");
23603
- var WRAPPED_FLUE_HARNESS = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-harness");
23604
- var WRAPPED_FLUE_SESSION = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-session");
23605
- var SUBSCRIBED_FLUE_CONTEXT_EVENTS = /* @__PURE__ */ Symbol.for(
23606
- "braintrust.flue.subscribed-context-events"
23607
- );
23608
- function wrapFlueContext(ctx) {
23609
- if (!isPlausibleFlueContext(ctx)) {
23610
- console.warn("Unsupported Flue context. Not wrapping.");
23611
- return ctx;
23605
+ // src/instrumentation/plugins/flue-plugin.ts
23606
+ var FLUE_AUTO_STATE = /* @__PURE__ */ Symbol.for("braintrust.flue.auto-state");
23607
+ var FLUE_OBSERVE_BRIDGE = /* @__PURE__ */ Symbol.for("braintrust.flue.observe-bridge");
23608
+ var braintrustFlueObserver = (event, ctx) => {
23609
+ getObserveBridge().handle(event, ctx);
23610
+ };
23611
+ var FluePlugin = class extends BasePlugin {
23612
+ onEnable() {
23613
+ this.unsubscribers.push(enableFlueAutoInstrumentation());
23612
23614
  }
23613
- const context = ctx;
23614
- subscribeFlueContextEvents(context, { captureTurnSpans: true });
23615
- return patchFlueContextInPlace(context);
23616
- }
23617
- function patchFlueContextInPlace(ctx) {
23618
- const context = ctx;
23619
- if (context[WRAPPED_FLUE_CONTEXT]) {
23620
- return ctx;
23615
+ onDisable() {
23616
+ for (const unsubscribe of this.unsubscribers) {
23617
+ unsubscribe();
23618
+ }
23619
+ this.unsubscribers = [];
23621
23620
  }
23622
- const originalInit = context.init.bind(context);
23623
- try {
23624
- Object.defineProperty(context, WRAPPED_FLUE_CONTEXT, {
23625
- configurable: false,
23626
- enumerable: false,
23627
- value: true
23628
- });
23629
- Object.defineProperty(context, "init", {
23630
- configurable: true,
23631
- value: async function wrappedFlueInit(options) {
23632
- const harness = await originalInit(options);
23633
- return wrapFlueHarness(harness);
23634
- },
23635
- writable: true
23636
- });
23637
- } catch {
23621
+ };
23622
+ function enableFlueAutoInstrumentation() {
23623
+ const state = getAutoState();
23624
+ state.refCount += 1;
23625
+ if (!state.handlers) {
23626
+ const channel = flueChannels.createContext.tracingChannel();
23627
+ const handlers = {
23628
+ end: (event) => {
23629
+ subscribeToFlueContext(event.result, state);
23630
+ }
23631
+ };
23632
+ channel.subscribe(handlers);
23633
+ state.channel = channel;
23634
+ state.handlers = handlers;
23638
23635
  }
23639
- return ctx;
23636
+ let released = false;
23637
+ return () => {
23638
+ if (released) {
23639
+ return;
23640
+ }
23641
+ released = true;
23642
+ releaseAutoState(state);
23643
+ };
23640
23644
  }
23641
- function wrapFlueSession(session) {
23642
- if (!isPlausibleFlueSession(session)) {
23643
- console.warn("Unsupported Flue session. Not wrapping.");
23644
- return session;
23645
+ function getAutoState() {
23646
+ const existing = Reflect.get(globalThis, FLUE_AUTO_STATE);
23647
+ if (isAutoState(existing)) {
23648
+ return existing;
23645
23649
  }
23646
- return patchFlueSessionInPlace(session);
23650
+ const state = {
23651
+ contexts: /* @__PURE__ */ new WeakSet(),
23652
+ refCount: 0
23653
+ };
23654
+ Reflect.set(globalThis, FLUE_AUTO_STATE, state);
23655
+ return state;
23647
23656
  }
23648
- function subscribeFlueContextEvents(ctx, options = {}) {
23649
- if (!ctx || typeof ctx !== "object" || typeof ctx.subscribeEvent !== "function") {
23650
- return void 0;
23651
- }
23652
- const context = ctx;
23653
- const captureTurnSpans = options.captureTurnSpans ?? true;
23654
- const existingSubscription = context[SUBSCRIBED_FLUE_CONTEXT_EVENTS];
23655
- if (existingSubscription) {
23656
- if (existingSubscription.captureTurnSpans || !captureTurnSpans) {
23657
- return void 0;
23658
- }
23659
- try {
23660
- existingSubscription.unsubscribe();
23661
- } catch {
23662
- }
23663
- }
23664
- try {
23665
- const unsubscribe = ctx.subscribeEvent((event) => {
23666
- flueChannels.contextEvent.traceSync(() => void 0, {
23667
- arguments: [event],
23668
- captureTurnSpans,
23669
- context: ctx
23670
- });
23671
- });
23672
- if (existingSubscription) {
23673
- existingSubscription.captureTurnSpans = captureTurnSpans;
23674
- existingSubscription.unsubscribe = unsubscribe;
23675
- } else {
23676
- Object.defineProperty(context, SUBSCRIBED_FLUE_CONTEXT_EVENTS, {
23677
- configurable: false,
23678
- enumerable: false,
23679
- value: {
23680
- captureTurnSpans,
23681
- unsubscribe
23682
- }
23683
- });
23684
- }
23685
- return unsubscribe;
23686
- } catch {
23687
- return void 0;
23657
+ function getObserveBridge() {
23658
+ const existing = Reflect.get(globalThis, FLUE_OBSERVE_BRIDGE);
23659
+ if (isFlueObserveBridge(existing)) {
23660
+ return existing;
23688
23661
  }
23662
+ const bridge = new FlueObserveBridge();
23663
+ Reflect.set(globalThis, FLUE_OBSERVE_BRIDGE, bridge);
23664
+ return bridge;
23689
23665
  }
23690
- function wrapFlueHarness(harness) {
23691
- if (!isPlausibleFlueHarness(harness)) {
23692
- return harness;
23693
- }
23694
- const target = harness;
23695
- if (target[WRAPPED_FLUE_HARNESS]) {
23696
- return harness;
23697
- }
23698
- const originalSession = target.session.bind(target);
23699
- try {
23700
- Object.defineProperty(target, WRAPPED_FLUE_HARNESS, {
23701
- configurable: false,
23702
- enumerable: false,
23703
- value: true
23704
- });
23705
- Object.defineProperty(target, "session", {
23706
- configurable: true,
23707
- value: async function wrappedFlueHarnessSession(name, options) {
23708
- const session = await originalSession(name, options);
23709
- return patchFlueSessionInPlace(session);
23710
- },
23711
- writable: true
23712
- });
23713
- const sessions = target.sessions;
23714
- if (sessions && typeof sessions === "object") {
23715
- patchFlueSessionFactory(sessions, "get");
23716
- patchFlueSessionFactory(sessions, "create");
23717
- }
23718
- } catch {
23719
- }
23720
- return harness;
23666
+ function isFlueObserveBridge(value) {
23667
+ return isObjectLike(value) && typeof Reflect.get(value, "handle") === "function" && typeof Reflect.get(value, "reset") === "function";
23721
23668
  }
23722
- function patchFlueSessionInPlace(session) {
23723
- if (session[WRAPPED_FLUE_SESSION]) {
23724
- return session;
23725
- }
23726
- try {
23727
- Object.defineProperty(session, WRAPPED_FLUE_SESSION, {
23728
- configurable: false,
23729
- enumerable: false,
23730
- value: true
23731
- });
23732
- patchCallHandleMethod(session, "prompt", flueChannels.prompt);
23733
- patchCallHandleMethod(session, "skill", flueChannels.skill);
23734
- patchCallHandleMethod(session, "task", flueChannels.task);
23735
- patchCompact(session);
23736
- } catch {
23737
- }
23738
- return session;
23669
+ function isAutoState(value) {
23670
+ return isObjectLike(value) && Reflect.get(value, "contexts") instanceof WeakSet && typeof Reflect.get(value, "refCount") === "number";
23739
23671
  }
23740
- function patchFlueSessionFactory(sessions, method) {
23741
- const original = sessions[method];
23742
- if (typeof original !== "function") {
23672
+ function releaseAutoState(state) {
23673
+ state.refCount -= 1;
23674
+ if (state.refCount > 0) {
23743
23675
  return;
23744
23676
  }
23745
- const bound = original.bind(sessions);
23746
- Object.defineProperty(sessions, method, {
23747
- configurable: true,
23748
- value: async function wrappedFlueSessionFactory(name, options) {
23749
- const session = await bound(name, options);
23750
- return patchFlueSessionInPlace(session);
23751
- },
23752
- writable: true
23753
- });
23754
- }
23755
- function patchCallHandleMethod(session, method, channel) {
23756
- const original = session[method];
23757
- if (typeof original !== "function") {
23758
- return;
23677
+ try {
23678
+ if (state.channel && state.handlers) {
23679
+ state.channel.unsubscribe(state.handlers);
23680
+ }
23681
+ } finally {
23682
+ Reflect.deleteProperty(globalThis, FLUE_AUTO_STATE);
23759
23683
  }
23760
- const bound = original.bind(session);
23761
- Object.defineProperty(session, method, {
23762
- configurable: true,
23763
- value(input, options) {
23764
- const args = [input, options];
23765
- const { originalResult, traced: traced2 } = traceFlueOperation(channel, {
23766
- context: {
23767
- arguments: args,
23768
- operation: method,
23769
- session
23770
- },
23771
- run: () => bound(input, options)
23772
- });
23773
- return preserveCallHandle(originalResult, traced2);
23774
- },
23775
- writable: true
23776
- });
23777
23684
  }
23778
- function patchCompact(session) {
23779
- const original = session.compact;
23780
- if (typeof original !== "function") {
23685
+ function subscribeToFlueContext(value, state) {
23686
+ if (!isObservableFlueContext(value) || state.contexts.has(value)) {
23781
23687
  return;
23782
23688
  }
23783
- const bound = original.bind(session);
23784
- Object.defineProperty(session, "compact", {
23785
- configurable: true,
23786
- value() {
23787
- const context = {
23788
- arguments: [],
23789
- operation: "compact",
23790
- session
23791
- };
23792
- return flueChannels.compact.tracePromise(() => bound(), context);
23793
- },
23794
- writable: true
23795
- });
23796
- }
23797
- function traceFlueOperation(channel, args) {
23798
- const tracingChannel2 = channel.tracingChannel();
23799
- const context = args.context;
23800
- let originalResult;
23801
- let traced2;
23802
- const run = () => {
23689
+ const ctx = flueContextFromUnknown(value);
23690
+ let released = false;
23691
+ let unsubscribe;
23692
+ const release = () => {
23693
+ if (released) {
23694
+ return;
23695
+ }
23696
+ released = true;
23803
23697
  try {
23804
- originalResult = args.run();
23805
- tracingChannel2.end?.publish(context);
23698
+ unsubscribe?.();
23806
23699
  } catch (error) {
23807
- context.error = normalizeError3(error);
23808
- tracingChannel2.error?.publish(context);
23809
- tracingChannel2.end?.publish(context);
23810
- throw error;
23700
+ logInstrumentationError3("Flue context unsubscribe", error);
23811
23701
  }
23812
- traced2 = Promise.resolve(originalResult).then(
23813
- (result) => {
23814
- context.result = result;
23815
- tracingChannel2.asyncStart?.publish(context);
23816
- tracingChannel2.asyncEnd?.publish(context);
23817
- return result;
23818
- },
23819
- (error) => {
23820
- context.error = normalizeError3(error);
23821
- tracingChannel2.error?.publish(context);
23822
- tracingChannel2.asyncStart?.publish(context);
23823
- tracingChannel2.asyncEnd?.publish(context);
23824
- throw error;
23825
- }
23826
- );
23827
23702
  };
23828
- if (tracingChannel2.start?.runStores) {
23829
- tracingChannel2.start.runStores(context, run);
23830
- } else {
23831
- tracingChannel2.start?.publish(context);
23832
- run();
23703
+ try {
23704
+ unsubscribe = value.subscribeEvent((event) => {
23705
+ if (state.refCount <= 0) {
23706
+ release();
23707
+ return;
23708
+ }
23709
+ braintrustFlueObserver(event, ctx);
23710
+ if (isAutoContextTerminalEvent(event, ctx)) {
23711
+ release();
23712
+ }
23713
+ });
23714
+ state.contexts.add(value);
23715
+ } catch (error) {
23716
+ logInstrumentationError3("Flue context subscription", error);
23833
23717
  }
23834
- return { originalResult, traced: traced2 };
23835
- }
23836
- function normalizeError3(error) {
23837
- return error instanceof Error ? error : new Error(String(error));
23838
23718
  }
23839
- function preserveCallHandle(originalHandle, traced2) {
23840
- if (!isFlueCallHandle(originalHandle)) {
23841
- return traced2;
23719
+ function isAutoContextTerminalEvent(event, ctx) {
23720
+ if (!isObjectLike(event)) {
23721
+ return false;
23842
23722
  }
23843
- const handle = originalHandle;
23844
- const wrapped = {
23845
- get signal() {
23846
- return handle.signal;
23847
- },
23848
- abort(reason) {
23849
- return handle.abort(reason);
23850
- },
23851
- then(onfulfilled, onrejected) {
23852
- return traced2.then(onfulfilled, onrejected);
23853
- }
23854
- };
23855
- return wrapped;
23723
+ const type = Reflect.get(event, "type");
23724
+ if (type === "run_end") {
23725
+ return true;
23726
+ }
23727
+ if (type !== "operation") {
23728
+ return false;
23729
+ }
23730
+ return !ctx?.runId && typeof Reflect.get(event, "runId") !== "string";
23856
23731
  }
23857
- function isPlausibleFlueContext(value) {
23858
- return !!value && typeof value === "object" && typeof value.init === "function";
23732
+ function isObservableFlueContext(value) {
23733
+ return isObjectLike(value) && typeof Reflect.get(value, "subscribeEvent") === "function";
23859
23734
  }
23860
- function isPlausibleFlueHarness(value) {
23861
- return !!value && typeof value === "object" && typeof value.session === "function";
23735
+ function isFlueEvent(event) {
23736
+ const type = Reflect.get(event, "type");
23737
+ 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";
23862
23738
  }
23863
- function isPlausibleFlueSession(value) {
23864
- return !!value && typeof value === "object" && typeof value.prompt === "function" && typeof value.skill === "function" && typeof value.task === "function" && typeof value.compact === "function";
23739
+ function flueContextFromUnknown(ctx) {
23740
+ if (!isObjectLike(ctx)) {
23741
+ return void 0;
23742
+ }
23743
+ const id = Reflect.get(ctx, "id");
23744
+ const runId = Reflect.get(ctx, "runId");
23745
+ return {
23746
+ ...typeof id === "string" ? { id } : {},
23747
+ ...typeof runId === "string" ? { runId } : {}
23748
+ };
23865
23749
  }
23866
- function isFlueCallHandle(value) {
23867
- return !!value && typeof value === "object" && typeof value.then === "function" && typeof value.abort === "function" && "signal" in value;
23750
+ function isObjectLike(value) {
23751
+ return typeof value === "object" && value !== null && !Array.isArray(value);
23868
23752
  }
23869
-
23870
- // src/instrumentation/plugins/flue-plugin.ts
23871
- var FluePlugin = class extends BasePlugin {
23872
- activeOperationsById = /* @__PURE__ */ new Map();
23873
- activeOperationsByScope = /* @__PURE__ */ new Map();
23874
- compactionsByScope = /* @__PURE__ */ new Map();
23875
- pendingOperationsByKey = /* @__PURE__ */ new Map();
23753
+ var FlueObserveBridge = class {
23754
+ compactionsByKey = /* @__PURE__ */ new Map();
23755
+ operationsById = /* @__PURE__ */ new Map();
23756
+ runsById = /* @__PURE__ */ new Map();
23757
+ seenEvents = /* @__PURE__ */ new WeakSet();
23876
23758
  tasksById = /* @__PURE__ */ new Map();
23877
- toolsById = /* @__PURE__ */ new Map();
23878
- turnsByScope = /* @__PURE__ */ new Map();
23879
- onEnable() {
23880
- this.subscribeToContextCreation();
23881
- this.subscribeToSessionCreation();
23882
- this.subscribeToContextEvents();
23883
- this.subscribeToSessionOperations();
23884
- }
23885
- onDisable() {
23886
- for (const unsubscribe of this.unsubscribers) {
23887
- unsubscribe();
23759
+ toolsByKey = /* @__PURE__ */ new Map();
23760
+ turnsByKey = /* @__PURE__ */ new Map();
23761
+ handle(event, ctx) {
23762
+ if (!isObjectLike(event) || !isFlueEvent(event)) {
23763
+ return;
23888
23764
  }
23889
- this.unsubscribers = [];
23890
- this.activeOperationsById.clear();
23891
- this.activeOperationsByScope.clear();
23892
- this.compactionsByScope.clear();
23893
- this.pendingOperationsByKey.clear();
23765
+ if (this.seenEvents.has(event)) {
23766
+ return;
23767
+ }
23768
+ this.seenEvents.add(event);
23769
+ try {
23770
+ this.handleEvent(event, flueContextFromUnknown(ctx));
23771
+ } catch (error) {
23772
+ logInstrumentationError3("Flue observe", error);
23773
+ }
23774
+ }
23775
+ reset() {
23776
+ this.compactionsByKey.clear();
23777
+ this.operationsById.clear();
23778
+ this.runsById.clear();
23779
+ this.seenEvents = /* @__PURE__ */ new WeakSet();
23894
23780
  this.tasksById.clear();
23895
- this.toolsById.clear();
23896
- this.turnsByScope.clear();
23781
+ this.toolsByKey.clear();
23782
+ this.turnsByKey.clear();
23897
23783
  }
23898
- subscribeToContextCreation() {
23899
- const channel = flueChannels.createContext.tracingChannel();
23900
- const handlers = {
23901
- end: (event) => {
23902
- const ctx = event.result;
23903
- if (!ctx) {
23904
- return;
23905
- }
23906
- subscribeFlueContextEvents(ctx, { captureTurnSpans: false });
23907
- patchFlueContextInPlace(ctx);
23908
- },
23909
- error: () => {
23910
- }
23911
- };
23912
- channel.subscribe(handlers);
23913
- this.unsubscribers.push(() => {
23914
- channel.unsubscribe(handlers);
23915
- });
23784
+ handleEvent(event, ctx) {
23785
+ switch (event.type) {
23786
+ case "run_start":
23787
+ this.handleRunStart(event, ctx);
23788
+ return;
23789
+ case "run_end":
23790
+ this.handleRunEnd(event);
23791
+ return;
23792
+ case "operation_start":
23793
+ this.handleOperationStart(event);
23794
+ return;
23795
+ case "operation":
23796
+ this.handleOperation(event);
23797
+ return;
23798
+ case "turn_request":
23799
+ this.handleTurnRequest(event);
23800
+ return;
23801
+ case "turn":
23802
+ this.handleTurn(event);
23803
+ return;
23804
+ case "tool_start":
23805
+ this.handleToolStart(event);
23806
+ return;
23807
+ case "tool_call":
23808
+ this.handleToolCall(event);
23809
+ return;
23810
+ case "task_start":
23811
+ this.handleTaskStart(event);
23812
+ return;
23813
+ case "task":
23814
+ this.handleTask(event);
23815
+ return;
23816
+ case "compaction_start":
23817
+ this.handleCompactionStart(event);
23818
+ return;
23819
+ case "compaction":
23820
+ this.handleCompaction(event);
23821
+ return;
23822
+ default:
23823
+ return;
23824
+ }
23916
23825
  }
23917
- subscribeToSessionCreation() {
23918
- const channel = flueChannels.openSession.tracingChannel();
23919
- const handlers = {
23920
- asyncEnd: (event) => {
23921
- if (event.result) {
23922
- patchFlueSessionInPlace(
23923
- event.result
23924
- );
23925
- }
23926
- if (event.harness) {
23927
- wrapFlueHarness(event.harness);
23928
- }
23929
- },
23930
- error: () => {
23931
- }
23826
+ handleRunStart(event, ctx) {
23827
+ if (!event.runId) {
23828
+ return;
23829
+ }
23830
+ const workflowName = event.workflowName ?? event.owner?.workflowName ?? (typeof ctx?.id === "string" ? ctx.id : "unknown");
23831
+ const metadata = {
23832
+ ...extractPayloadMetadata(event.payload),
23833
+ ...extractEventMetadata(event, ctx),
23834
+ ...workflowName ? { "flue.workflow_name": workflowName } : {},
23835
+ provider: "flue"
23932
23836
  };
23933
- channel.subscribe(handlers);
23934
- this.unsubscribers.push(() => {
23935
- channel.unsubscribe(handlers);
23837
+ const span = startSpan({
23838
+ name: `workflow:${workflowName}`,
23839
+ spanAttributes: { type: "task" /* TASK */ },
23840
+ startTime: eventTime(event.startedAt ?? event.timestamp),
23841
+ event: {
23842
+ input: event.payload,
23843
+ metadata
23844
+ }
23936
23845
  });
23846
+ this.runsById.set(event.runId, { metadata, span });
23937
23847
  }
23938
- subscribeToSessionOperations() {
23939
- this.subscribeToSessionOperation(flueChannels.prompt);
23940
- this.subscribeToSessionOperation(flueChannels.skill);
23941
- this.subscribeToSessionOperation(flueChannels.task);
23942
- this.subscribeToCompact();
23943
- }
23944
- subscribeToSessionOperation(channel) {
23945
- const tracingChannel2 = channel.tracingChannel();
23946
- const states = /* @__PURE__ */ new WeakMap();
23947
- const ensureState2 = (event) => {
23948
- const existing = states.get(event);
23949
- if (existing) {
23950
- return existing;
23951
- }
23952
- const state = this.startOperationState({
23953
- args: event.arguments,
23954
- moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
23955
- operation: event.operation,
23956
- session: event.session
23848
+ handleRunEnd(event) {
23849
+ const state = this.runsById.get(event.runId);
23850
+ this.finishPendingSpansForRun(event);
23851
+ if (state) {
23852
+ safeLog3(state.span, {
23853
+ ...event.isError ? { error: errorToString(event.error) } : {},
23854
+ metadata: {
23855
+ ...state.metadata,
23856
+ ...extractEventMetadata(event),
23857
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
23858
+ },
23859
+ metrics: durationMetrics2(event.durationMs),
23860
+ output: event.result
23957
23861
  });
23958
- states.set(event, state);
23959
- return state;
23960
- };
23961
- const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
23962
- tracingChannel2,
23963
- ensureState2
23964
- );
23965
- const handlers = {
23966
- start: (event) => {
23967
- ensureState2(event);
23968
- },
23969
- asyncEnd: (event) => {
23970
- this.endOperationState(states.get(event), event.result);
23971
- states.delete(event);
23972
- },
23973
- error: (event) => {
23974
- const state = states.get(event);
23975
- if (state && event.error) {
23976
- safeLog3(state.span, { error: errorToString(event.error) });
23977
- this.finishOperationState(state);
23978
- }
23979
- states.delete(event);
23980
- }
23981
- };
23982
- tracingChannel2.subscribe(handlers);
23983
- this.unsubscribers.push(() => {
23984
- unbindCurrentSpanStore?.();
23985
- tracingChannel2.unsubscribe(handlers);
23862
+ safeEnd(state.span, eventTime(event.timestamp));
23863
+ this.runsById.delete(event.runId);
23864
+ }
23865
+ void flush().catch((error) => {
23866
+ logInstrumentationError3("Flue flush", error);
23986
23867
  });
23987
23868
  }
23988
- subscribeToCompact() {
23989
- const tracingChannel2 = flueChannels.compact.tracingChannel();
23990
- const states = /* @__PURE__ */ new WeakMap();
23991
- const ensureState2 = (event) => {
23992
- const existing = states.get(event);
23993
- if (existing) {
23994
- return existing;
23995
- }
23996
- const state = this.startOperationState({
23997
- args: [],
23998
- moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
23999
- operation: event.operation,
24000
- session: event.session
24001
- });
24002
- states.set(event, state);
24003
- return state;
23869
+ handleOperationStart(event) {
23870
+ if (!event.operationId || !isInstrumentedOperation(event.operationKind)) {
23871
+ return;
23872
+ }
23873
+ const metadata = {
23874
+ ...extractEventMetadata(event),
23875
+ "flue.operation": event.operationKind,
23876
+ provider: "flue"
24004
23877
  };
24005
- const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
24006
- tracingChannel2,
24007
- ensureState2
24008
- );
24009
- const handlers = {
24010
- start: (event) => {
24011
- ensureState2(event);
24012
- },
24013
- asyncEnd: (event) => {
24014
- this.endOperationState(states.get(event), void 0);
24015
- states.delete(event);
24016
- },
24017
- error: (event) => {
24018
- const state = states.get(event);
24019
- if (state && event.error) {
24020
- safeLog3(state.span, { error: errorToString(event.error) });
24021
- this.finishOperationState(state);
24022
- }
24023
- states.delete(event);
24024
- }
24025
- };
24026
- tracingChannel2.subscribe(handlers);
24027
- this.unsubscribers.push(() => {
24028
- unbindCurrentSpanStore?.();
24029
- tracingChannel2.unsubscribe(handlers);
24030
- });
24031
- }
24032
- subscribeToContextEvents() {
24033
- const channel = flueChannels.contextEvent.tracingChannel();
24034
- const handlers = {
24035
- start: (event) => {
24036
- const flueEvent = event.arguments[0];
24037
- if (!flueEvent) {
24038
- return;
24039
- }
24040
- try {
24041
- this.handleFlueEvent(flueEvent, {
24042
- captureTurnSpans: event.captureTurnSpans !== false
24043
- });
24044
- } catch (error) {
24045
- logInstrumentationError3("Flue event", error);
24046
- }
24047
- },
24048
- error: () => {
24049
- }
24050
- };
24051
- channel.subscribe(handlers);
24052
- this.unsubscribers.push(() => {
24053
- channel.unsubscribe(handlers);
24054
- });
24055
- }
24056
- bindCurrentSpanStoreToOperationStart(tracingChannel2, ensureState2) {
24057
- const state = _internalGetGlobalState();
24058
- const startChannel = tracingChannel2.start;
24059
- const contextManager = state?.contextManager;
24060
- const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
24061
- if (!currentSpanStore || !startChannel) {
24062
- return void 0;
24063
- }
24064
- startChannel.bindStore(currentSpanStore, (event) => {
24065
- const operationState = ensureState2(event);
24066
- return contextManager.wrapSpanForStore(operationState.span);
24067
- });
24068
- return () => {
24069
- startChannel.unbindStore(currentSpanStore);
24070
- };
24071
- }
24072
- startOperationState(args) {
24073
- const sessionName = getSessionName(args.session);
24074
- const metadata = {
24075
- ...extractOperationInputMetadata(args.operation, args.args),
24076
- ...extractSessionMetadata(args.session),
24077
- "flue.operation": args.operation,
24078
- provider: "flue",
24079
- ...args.moduleVersion ? { "flue.version": args.moduleVersion } : {}
24080
- };
24081
- const span = startSpan({
24082
- name: `flue.session.${args.operation}`,
24083
- spanAttributes: { type: "task" /* TASK */ }
24084
- });
24085
- const state = {
24086
- metadata,
24087
- operation: args.operation,
24088
- sessionName,
24089
- span,
24090
- startTime: getCurrentUnixTimestamp()
24091
- };
24092
- safeLog3(span, {
24093
- input: extractOperationInput(args.operation, args.args),
24094
- metadata
24095
- });
24096
- this.pendingOperationQueue(operationKey(sessionName, args.operation)).push(
24097
- state
24098
- );
24099
- addOperationToScope(
24100
- this.activeOperationsByScope,
24101
- sessionName ?? "unknown",
24102
- state
24103
- );
24104
- return state;
24105
- }
24106
- endOperationState(state, result) {
24107
- if (!state) {
24108
- return;
24109
- }
24110
- const metadata = {
24111
- ...state.metadata,
24112
- ...extractPromptResponseMetadata(result)
24113
- };
24114
- const metrics = {
24115
- ...buildDurationMetrics3(state.startTime),
24116
- ...metricsFromUsage(result?.usage)
24117
- };
24118
- safeLog3(state.span, {
24119
- metadata,
24120
- metrics,
24121
- output: extractOperationOutput(result)
23878
+ const parent = this.parentSpanForEvent(event);
23879
+ const span = startFlueSpan(parent, {
23880
+ name: `flue.${event.operationKind}`,
23881
+ spanAttributes: { type: "task" /* TASK */ },
23882
+ startTime: eventTime(event.timestamp),
23883
+ event: { metadata }
24122
23884
  });
24123
- this.finishCompactionsForOperation(state);
24124
- this.finishOperationState(state);
24125
- }
24126
- finishOperationState(state) {
24127
- removePendingOperation(this.pendingOperationsByKey, state);
24128
- if (state.operationId) {
24129
- this.activeOperationsById.delete(state.operationId);
24130
- }
24131
- removeScopedOperation(this.activeOperationsByScope, state);
24132
- state.span.end();
24133
- }
24134
- handleFlueEvent(event, options) {
24135
- switch (event.type) {
24136
- case "operation_start":
24137
- this.handleOperationStart(event);
24138
- return;
24139
- case "operation":
24140
- this.handleOperation(event);
24141
- return;
24142
- case "text_delta":
24143
- if (!options.captureTurnSpans) {
24144
- return;
24145
- }
24146
- this.ensureTurnState(event).text.push(
24147
- typeof event.text === "string" ? event.text : ""
24148
- );
24149
- return;
24150
- case "thinking_start":
24151
- if (!options.captureTurnSpans) {
24152
- return;
24153
- }
24154
- this.handleThinkingStart(event);
24155
- return;
24156
- case "thinking_delta":
24157
- if (!options.captureTurnSpans) {
24158
- return;
24159
- }
24160
- this.handleThinkingDelta(event);
24161
- return;
24162
- case "thinking_end":
24163
- if (!options.captureTurnSpans) {
24164
- return;
24165
- }
24166
- this.handleThinkingEnd(event);
24167
- return;
24168
- case "turn":
24169
- if (!options.captureTurnSpans) {
24170
- return;
24171
- }
24172
- this.handleTurn(event);
24173
- return;
24174
- case "tool_start":
24175
- this.handleToolStart(event, options);
24176
- return;
24177
- case "tool_call":
24178
- this.handleToolCall(event);
24179
- return;
24180
- case "task_start":
24181
- this.handleTaskStart(event);
24182
- return;
24183
- case "task":
24184
- this.handleTask(event);
24185
- return;
24186
- case "compaction_start":
24187
- this.handleCompactionStart(event);
24188
- return;
24189
- case "compaction":
24190
- this.handleCompaction(event);
24191
- return;
24192
- default:
24193
- return;
24194
- }
24195
- }
24196
- handleOperationStart(event) {
24197
- if (!isInstrumentedOperation(event.operationKind)) {
24198
- return;
24199
- }
24200
- const state = this.takePendingOperationForEvent(event);
24201
- if (!state) {
24202
- return;
24203
- }
24204
- state.operationId = event.operationId;
24205
- this.activeOperationsById.set(event.operationId, state);
24206
- addScopedOperation(this.activeOperationsByScope, event, state);
24207
- state.metadata = {
24208
- ...state.metadata,
24209
- ...extractEventMetadata(event),
24210
- "flue.operation_id": event.operationId
24211
- };
24212
- safeLog3(state.span, { metadata: state.metadata });
23885
+ this.operationsById.set(event.operationId, { metadata, span });
24213
23886
  }
24214
23887
  handleOperation(event) {
24215
- const state = event.operationId ? this.activeOperationsById.get(event.operationId) : void 0;
24216
- if (!state) {
23888
+ if (!isInstrumentedOperation(event.operationKind)) {
24217
23889
  return;
24218
23890
  }
23891
+ const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
23892
+ const output = operationOutput(event);
24219
23893
  const metadata = {
24220
23894
  ...state.metadata,
24221
23895
  ...extractEventMetadata(event),
24222
- ...typeof event.durationMs === "number" ? { "flue.duration_ms": event.durationMs } : {},
24223
- ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
23896
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
23897
+ ...event.usage ? { "flue.usage": event.usage } : {}
24224
23898
  };
24225
- const metrics = metricsFromUsage(event.usage);
23899
+ this.finishPendingChildrenForOperation(event, output);
24226
23900
  safeLog3(state.span, {
24227
- ...event.error ? { error: errorToString(event.error) } : {},
23901
+ ...event.isError ? { error: errorToString(event.error) } : {},
24228
23902
  metadata,
24229
- ...Object.keys(metrics).length ? { metrics } : {}
23903
+ metrics: durationMetrics2(event.durationMs),
23904
+ output
24230
23905
  });
23906
+ safeEnd(state.span, eventTime(event.timestamp));
23907
+ this.operationsById.delete(event.operationId);
24231
23908
  }
24232
- ensureTurnState(event) {
24233
- const scope = scopeKey(event);
24234
- const existing = this.turnsByScope.get(scope);
24235
- if (existing) {
24236
- return existing;
23909
+ handleTurnRequest(event) {
23910
+ const key = turnKey(event);
23911
+ if (!key) {
23912
+ return;
24237
23913
  }
24238
- const parent = this.parentSpanForEvent(event);
24239
23914
  const metadata = {
24240
23915
  ...extractEventMetadata(event),
24241
- provider: "flue"
23916
+ ...event.api ? { "flue.api": event.api } : {},
23917
+ ...event.model ? { model: event.model, "flue.model": event.model } : {},
23918
+ ...event.provider ? { provider: event.provider } : { provider: "flue" },
23919
+ ...event.provider ? { "flue.provider": event.provider } : {},
23920
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
23921
+ ...event.reasoning ? { reasoning: event.reasoning } : {},
23922
+ ...event.input?.systemPrompt ? { "flue.system_prompt": event.input.systemPrompt } : {},
23923
+ ...event.input?.tools ? { tools: event.input.tools } : {}
24242
23924
  };
23925
+ const parent = this.parentSpanForTurn(event);
24243
23926
  const span = startFlueSpan(parent, {
24244
- name: "flue.turn",
24245
- spanAttributes: { type: "llm" /* LLM */ }
23927
+ name: `llm:${event.model ?? event.purpose ?? "unknown"}`,
23928
+ spanAttributes: { type: "llm" /* LLM */ },
23929
+ startTime: eventTime(event.timestamp),
23930
+ event: {
23931
+ input: event.input?.messages,
23932
+ metadata
23933
+ }
24246
23934
  });
24247
- const state = {
24248
- metadata,
24249
- span,
24250
- hasThinking: false,
24251
- startTime: getCurrentUnixTimestamp(),
24252
- text: [],
24253
- thinking: [],
24254
- toolCalls: []
24255
- };
24256
- safeLog3(span, { metadata });
24257
- this.turnsByScope.set(scope, state);
24258
- return state;
23935
+ this.logOperationInput(
23936
+ event.operationId,
23937
+ event.input?.messages ?? event.input
23938
+ );
23939
+ this.turnsByKey.set(key, { metadata, span });
24259
23940
  }
24260
23941
  handleTurn(event) {
24261
- const scope = scopeKey(event);
24262
- const state = this.ensureTurnState(event);
24263
- const text = state.text.join("");
24264
- const reasoning = state.finalThinking ?? state.thinking.join("");
24265
- const outputReasoning = reasoning || (state.hasThinking ? "[reasoning stream present; content unavailable]" : void 0);
23942
+ const key = turnKey(event);
23943
+ if (!key) {
23944
+ return;
23945
+ }
23946
+ const state = this.turnsByKey.get(key) ?? this.startSyntheticTurn(event);
24266
23947
  const metadata = {
24267
23948
  ...state.metadata,
24268
23949
  ...extractEventMetadata(event),
23950
+ ...event.api ? { "flue.api": event.api } : {},
24269
23951
  ...event.model ? { model: event.model, "flue.model": event.model } : {},
23952
+ ...event.provider ? { provider: event.provider } : {},
23953
+ ...event.provider ? { "flue.provider": event.provider } : {},
23954
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
24270
23955
  ...event.stopReason ? { "flue.stop_reason": event.stopReason } : {},
24271
- ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
24272
- provider: "flue"
23956
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24273
23957
  };
24274
23958
  safeLog3(state.span, {
24275
- ...event.error ? { error: errorToString(event.error) } : {},
23959
+ ...event.isError ? { error: errorToString(event.error) } : {},
24276
23960
  metadata,
24277
23961
  metrics: {
24278
- ...durationMsMetrics(event.durationMs),
23962
+ ...durationMetrics2(event.durationMs),
24279
23963
  ...metricsFromUsage(event.usage)
24280
23964
  },
24281
- output: toAssistantOutput(
24282
- text,
24283
- event.stopReason,
24284
- outputReasoning,
24285
- state.toolCalls
24286
- )
23965
+ output: event.output
24287
23966
  });
24288
- state.span.end();
24289
- this.turnsByScope.delete(scope);
23967
+ safeEnd(state.span, eventTime(event.timestamp));
23968
+ this.turnsByKey.delete(key);
24290
23969
  }
24291
- handleThinkingDelta(event) {
24292
- const delta = event.delta;
24293
- if (typeof delta !== "string" || !delta) {
23970
+ handleToolStart(event) {
23971
+ if (!event.toolCallId) {
24294
23972
  return;
24295
23973
  }
24296
- const state = this.ensureTurnState(event);
24297
- state.hasThinking = true;
24298
- state.metadata["flue.thinking"] = true;
24299
- state.thinking.push(delta);
24300
- }
24301
- handleThinkingStart(event) {
24302
- const state = this.ensureTurnState(event);
24303
- state.hasThinking = true;
24304
- state.metadata["flue.thinking"] = true;
24305
- }
24306
- handleThinkingEnd(event) {
24307
- const state = this.ensureTurnState(event);
24308
- state.hasThinking = true;
24309
- state.metadata["flue.thinking"] = true;
24310
- if (typeof event.content === "string" && event.content) {
24311
- state.finalThinking = event.content;
24312
- }
24313
- }
24314
- handleToolStart(event, options) {
24315
- const toolCallId = event.toolCallId;
24316
- if (!toolCallId) {
24317
- return;
24318
- }
24319
- const parent = this.parentSpanForEvent(event);
24320
- const scope = scopeKey(event);
24321
- let turnState = this.turnsByScope.get(scope);
24322
- if (!turnState && parent && options.captureTurnSpans) {
24323
- turnState = this.ensureTurnState(event);
24324
- }
24325
23974
  const metadata = {
24326
23975
  ...extractEventMetadata(event),
24327
23976
  ...event.toolName ? { "flue.tool_name": event.toolName } : {},
24328
- "flue.tool_call_id": toolCallId,
23977
+ "flue.tool_call_id": event.toolCallId,
24329
23978
  provider: "flue"
24330
23979
  };
23980
+ const parent = this.parentSpanForTool(event);
24331
23981
  const span = startFlueSpan(parent, {
24332
- name: `tool: ${event.toolName ?? "unknown"}`,
24333
- spanAttributes: { type: "tool" /* TOOL */ }
24334
- });
24335
- if (turnState) {
24336
- turnState.toolCalls.push({
24337
- args: event.args,
24338
- toolCallId,
24339
- toolName: event.toolName
24340
- });
24341
- }
24342
- safeLog3(span, {
24343
- input: event.args,
24344
- metadata
24345
- });
24346
- this.toolsById.set(toolKey(event), {
24347
- metadata,
24348
- span,
24349
- startTime: getCurrentUnixTimestamp()
23982
+ name: `tool:${event.toolName ?? "unknown"}`,
23983
+ spanAttributes: { type: "tool" /* TOOL */ },
23984
+ startTime: eventTime(event.timestamp),
23985
+ event: {
23986
+ input: event.args,
23987
+ metadata
23988
+ }
24350
23989
  });
23990
+ this.toolsByKey.set(toolKey(event), { metadata, span });
24351
23991
  }
24352
23992
  handleToolCall(event) {
23993
+ if (!event.toolCallId) {
23994
+ return;
23995
+ }
24353
23996
  const key = toolKey(event);
24354
- const state = this.toolsById.get(key) ?? this.startSyntheticToolState(event, event.toolName ?? "unknown");
23997
+ const state = this.toolsByKey.get(key) ?? this.startSyntheticTool(event);
24355
23998
  const metadata = {
24356
23999
  ...state.metadata,
24357
24000
  ...extractEventMetadata(event),
24358
24001
  ...event.toolName ? { "flue.tool_name": event.toolName } : {},
24359
- ...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
24002
+ "flue.tool_call_id": event.toolCallId,
24360
24003
  ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24361
24004
  };
24362
24005
  safeLog3(state.span, {
24363
24006
  ...event.isError ? { error: errorToString(event.result) } : {},
24364
24007
  metadata,
24365
- metrics: durationMsMetrics(event.durationMs),
24008
+ metrics: durationMetrics2(event.durationMs),
24366
24009
  output: event.result
24367
24010
  });
24368
- state.span.end();
24369
- this.toolsById.delete(key);
24011
+ safeEnd(state.span, eventTime(event.timestamp));
24012
+ this.toolsByKey.delete(key);
24370
24013
  }
24371
24014
  handleTaskStart(event) {
24372
- const parent = this.parentSpanForEvent(event);
24015
+ if (!event.taskId) {
24016
+ return;
24017
+ }
24373
24018
  const metadata = {
24374
24019
  ...extractEventMetadata(event),
24375
- ...event.role ? { "flue.role": event.role } : {},
24020
+ ...event.agent ? { "flue.agent": event.agent } : {},
24376
24021
  ...event.cwd ? { "flue.cwd": event.cwd } : {},
24377
24022
  "flue.task_id": event.taskId,
24378
24023
  provider: "flue"
24379
24024
  };
24025
+ const parent = this.parentSpanForEvent(event);
24380
24026
  const span = startFlueSpan(parent, {
24381
- name: "flue.task",
24382
- spanAttributes: { type: "task" /* TASK */ }
24383
- });
24384
- safeLog3(span, {
24385
- input: event.prompt,
24386
- metadata
24387
- });
24388
- this.tasksById.set(event.taskId, {
24389
- metadata,
24390
- span,
24391
- startTime: getCurrentUnixTimestamp()
24027
+ name: event.agent ? `task:${event.agent}` : "flue.task",
24028
+ spanAttributes: { type: "task" /* TASK */ },
24029
+ startTime: eventTime(event.timestamp),
24030
+ event: {
24031
+ input: event.prompt,
24032
+ metadata
24033
+ }
24392
24034
  });
24035
+ this.tasksById.set(event.taskId, { metadata, span });
24393
24036
  }
24394
24037
  handleTask(event) {
24395
24038
  const state = this.tasksById.get(event.taskId);
@@ -24401,426 +24044,372 @@ var FluePlugin = class extends BasePlugin {
24401
24044
  metadata: {
24402
24045
  ...state.metadata,
24403
24046
  ...extractEventMetadata(event),
24047
+ ...event.agent ? { "flue.agent": event.agent } : {},
24404
24048
  ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24405
24049
  },
24406
- metrics: durationMsMetrics(event.durationMs),
24050
+ metrics: durationMetrics2(event.durationMs),
24407
24051
  output: event.result
24408
24052
  });
24409
- state.span.end();
24053
+ safeEnd(state.span, eventTime(event.timestamp));
24410
24054
  this.tasksById.delete(event.taskId);
24411
24055
  }
24412
24056
  handleCompactionStart(event) {
24413
- const operationState = this.operationStateForEvent(event);
24414
- const parent = operationState?.span ?? this.parentSpanForEvent(event);
24057
+ const key = compactionKey(event);
24058
+ const input = {
24059
+ ...event.estimatedTokens !== void 0 ? { estimatedTokens: event.estimatedTokens } : {},
24060
+ ...event.reason ? { reason: event.reason } : {}
24061
+ };
24415
24062
  const metadata = {
24416
24063
  ...extractEventMetadata(event),
24417
24064
  ...event.reason ? { "flue.compaction_reason": event.reason } : {},
24418
24065
  provider: "flue"
24419
24066
  };
24420
- const input = {
24421
- ...typeof event.estimatedTokens === "number" ? { estimatedTokens: event.estimatedTokens } : {},
24422
- ...event.reason ? { reason: event.reason } : {}
24423
- };
24067
+ const parent = this.parentSpanForEvent(event);
24424
24068
  const span = startFlueSpan(parent, {
24425
- name: "flue.compaction",
24426
- spanAttributes: { type: "task" /* TASK */ }
24427
- });
24428
- safeLog3(span, {
24429
- input,
24430
- metadata
24431
- });
24432
- this.compactionsByScope.set(scopeKey(event), {
24433
- input,
24434
- metadata,
24435
- operationState,
24436
- span,
24437
- startTime: getCurrentUnixTimestamp()
24069
+ name: `compaction:${event.reason ?? "unknown"}`,
24070
+ spanAttributes: { type: "task" /* TASK */ },
24071
+ startTime: eventTime(event.timestamp),
24072
+ event: {
24073
+ input,
24074
+ metadata
24075
+ }
24438
24076
  });
24077
+ this.logOperationInput(event.operationId, input);
24078
+ this.compactionsByKey.set(key, { metadata, span });
24439
24079
  }
24440
24080
  handleCompaction(event) {
24441
- const key = scopeKey(event);
24442
- const state = this.compactionsByScope.get(key) ?? this.findCompactionState(event);
24443
- if (!state) {
24444
- return;
24445
- }
24081
+ const key = compactionKey(event);
24082
+ const state = this.compactionsByKey.get(key) ?? this.startSyntheticCompaction(event);
24083
+ const metadata = {
24084
+ ...state.metadata,
24085
+ ...extractEventMetadata(event),
24086
+ ...event.usage ? { "flue.usage": event.usage } : {}
24087
+ };
24446
24088
  safeLog3(state.span, {
24447
- metadata: {
24448
- ...state.metadata,
24449
- ...extractEventMetadata(event),
24450
- ...typeof event.messagesBefore === "number" ? { "flue.messages_before": event.messagesBefore } : {},
24451
- ...typeof event.messagesAfter === "number" ? { "flue.messages_after": event.messagesAfter } : {}
24452
- },
24089
+ metadata,
24453
24090
  metrics: {
24454
- ...durationMsMetrics(event.durationMs),
24455
- ...metricsFromUsage(event.usage)
24091
+ ...durationMetrics2(event.durationMs),
24092
+ ...typeof event.messagesBefore === "number" ? { messages_before: event.messagesBefore } : {},
24093
+ ...typeof event.messagesAfter === "number" ? { messages_after: event.messagesAfter } : {}
24456
24094
  },
24457
24095
  output: {
24458
24096
  messagesAfter: event.messagesAfter,
24459
24097
  messagesBefore: event.messagesBefore
24460
24098
  }
24461
24099
  });
24462
- state.span.end();
24463
- this.deleteCompactionState(state);
24100
+ safeEnd(state.span, eventTime(event.timestamp));
24101
+ this.compactionsByKey.delete(key);
24464
24102
  }
24465
- findCompactionState(event) {
24466
- const operationState = this.operationStateForEvent(event);
24467
- for (const state of this.compactionsByScope.values()) {
24468
- if (operationState && state.operationState === operationState) {
24469
- return state;
24103
+ parentSpanForTurn(event) {
24104
+ if (event.purpose === "compaction" || event.purpose === "compaction_prefix") {
24105
+ const compaction = this.compactionsByKey.get(compactionKey(event));
24106
+ if (compaction) {
24107
+ return compaction.span;
24470
24108
  }
24471
24109
  }
24472
- return void 0;
24110
+ return this.parentSpanForEvent(event);
24473
24111
  }
24474
- finishCompactionsForOperation(operationState) {
24475
- for (const state of [...this.compactionsByScope.values()]) {
24476
- if (state.operationState !== operationState) {
24477
- continue;
24112
+ parentSpanForEvent(event) {
24113
+ const turn = turnKey(event);
24114
+ if (turn) {
24115
+ const turnState = this.turnsByKey.get(turn);
24116
+ if (turnState) {
24117
+ return turnState.span;
24478
24118
  }
24479
- safeLog3(state.span, {
24480
- input: state.input,
24481
- metadata: state.metadata,
24482
- metrics: {
24483
- ...buildDurationMetrics3(state.startTime)
24484
- },
24485
- output: { completed: true }
24486
- });
24487
- state.span.end();
24488
- this.deleteCompactionState(state);
24489
24119
  }
24490
- }
24491
- deleteCompactionState(state) {
24492
- for (const [key, candidate] of this.compactionsByScope) {
24493
- if (candidate !== state) {
24494
- continue;
24120
+ if (event.taskId) {
24121
+ const task = this.tasksById.get(event.taskId);
24122
+ if (task) {
24123
+ return task.span;
24495
24124
  }
24496
- this.compactionsByScope.delete(key);
24497
- return;
24498
24125
  }
24499
- }
24500
- startSyntheticToolState(event, toolName) {
24501
- const parent = this.parentSpanForEvent(event);
24502
- const metadata = {
24503
- ...extractEventMetadata(event),
24504
- ...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
24505
- "flue.tool_name": toolName,
24506
- provider: "flue"
24507
- };
24508
- const span = startFlueSpan(parent, {
24509
- name: `tool: ${toolName}`,
24510
- spanAttributes: { type: "tool" /* TOOL */ }
24511
- });
24512
- safeLog3(span, { metadata });
24513
- return { metadata, span, startTime: getCurrentUnixTimestamp() };
24514
- }
24515
- operationStateForEvent(event) {
24516
24126
  if (event.operationId) {
24517
- const operation = this.activeOperationsById.get(event.operationId) ?? this.promotePendingOperationForEvent(event);
24127
+ const operation = this.operationsById.get(event.operationId);
24518
24128
  if (operation) {
24519
- return operation;
24129
+ return operation.span;
24520
24130
  }
24521
24131
  }
24522
- return this.activeOperationForEventScope(event) ?? this.pendingOperationForEventScope(event);
24132
+ if (event.runId) {
24133
+ return this.runsById.get(event.runId)?.span;
24134
+ }
24135
+ return void 0;
24523
24136
  }
24524
- parentSpanForEvent(event) {
24137
+ parentSpanForTool(event) {
24138
+ if (event.taskId) {
24139
+ const task = this.tasksById.get(event.taskId);
24140
+ if (task) {
24141
+ return task.span;
24142
+ }
24143
+ }
24525
24144
  if (event.operationId) {
24526
- const operation = this.operationStateForEvent(event);
24145
+ const operation = this.operationsById.get(event.operationId);
24527
24146
  if (operation) {
24528
24147
  return operation.span;
24529
24148
  }
24530
24149
  }
24531
- if (event.taskId) {
24532
- return this.tasksById.get(event.taskId)?.span;
24150
+ if (event.runId) {
24151
+ return this.runsById.get(event.runId)?.span;
24533
24152
  }
24534
- return this.operationStateForEvent(event)?.span;
24153
+ return void 0;
24535
24154
  }
24536
- promotePendingOperationForEvent(event) {
24537
- if (!event.operationId) {
24538
- return void 0;
24155
+ logOperationInput(operationId, input) {
24156
+ if (!operationId || input === void 0) {
24157
+ return;
24539
24158
  }
24540
- const scopePrefixes = operationScopePrefixes(event);
24541
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
24542
- if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
24159
+ const operation = this.operationsById.get(operationId);
24160
+ if (!operation || operation.loggedInput) {
24161
+ return;
24162
+ }
24163
+ safeLog3(operation.span, { input });
24164
+ operation.loggedInput = true;
24165
+ }
24166
+ startSyntheticOperation(event) {
24167
+ const metadata = {
24168
+ ...extractEventMetadata(event),
24169
+ "flue.operation": event.operationKind,
24170
+ provider: "flue"
24171
+ };
24172
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
24173
+ name: `flue.${event.operationKind}`,
24174
+ spanAttributes: { type: "task" /* TASK */ },
24175
+ startTime: eventTime(event.timestamp),
24176
+ event: { metadata }
24177
+ });
24178
+ return { metadata, span };
24179
+ }
24180
+ startSyntheticTurn(event) {
24181
+ const metadata = {
24182
+ ...extractEventMetadata(event),
24183
+ ...event.api ? { "flue.api": event.api } : {},
24184
+ ...event.model ? { model: event.model, "flue.model": event.model } : {},
24185
+ ...event.provider ? { provider: event.provider } : { provider: "flue" },
24186
+ ...event.provider ? { "flue.provider": event.provider } : {},
24187
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
24188
+ };
24189
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
24190
+ name: `llm:${event.model ?? event.purpose ?? "unknown"}`,
24191
+ spanAttributes: { type: "llm" /* LLM */ },
24192
+ startTime: eventTime(event.timestamp),
24193
+ event: { metadata }
24194
+ });
24195
+ return { metadata, span };
24196
+ }
24197
+ startSyntheticTool(event) {
24198
+ const metadata = {
24199
+ ...extractEventMetadata(event),
24200
+ ...event.toolName ? { "flue.tool_name": event.toolName } : {},
24201
+ "flue.tool_call_id": event.toolCallId,
24202
+ provider: "flue"
24203
+ };
24204
+ const span = startFlueSpan(this.parentSpanForTool(event), {
24205
+ name: `tool:${event.toolName ?? "unknown"}`,
24206
+ spanAttributes: { type: "tool" /* TOOL */ },
24207
+ startTime: eventTime(event.timestamp),
24208
+ event: { metadata }
24209
+ });
24210
+ return { metadata, span };
24211
+ }
24212
+ startSyntheticCompaction(event) {
24213
+ const metadata = {
24214
+ ...extractEventMetadata(event),
24215
+ provider: "flue"
24216
+ };
24217
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
24218
+ name: "compaction:unknown",
24219
+ spanAttributes: { type: "task" /* TASK */ },
24220
+ startTime: eventTime(event.timestamp),
24221
+ event: { metadata }
24222
+ });
24223
+ return { metadata, span };
24224
+ }
24225
+ finishPendingChildrenForOperation(event, operationOutput2) {
24226
+ const endTime = eventTime(event.timestamp);
24227
+ const usage = event.usage ?? usageFromOperationResult(event.result);
24228
+ const turnEntries = [...this.turnsByKey].filter(
24229
+ ([, state]) => stateMatchesOperation(state, event.operationId)
24230
+ );
24231
+ turnEntries.forEach(([key, state], index) => {
24232
+ const shouldLogOperationOutput = (event.operationKind === "prompt" || event.operationKind === "skill") && index === turnEntries.length - 1 && operationOutput2 !== void 0;
24233
+ safeLog3(state.span, {
24234
+ metadata: state.metadata,
24235
+ metrics: metricsFromUsage(usage),
24236
+ ...shouldLogOperationOutput ? { output: operationOutput2 } : {}
24237
+ });
24238
+ safeEnd(state.span, endTime);
24239
+ this.turnsByKey.delete(key);
24240
+ });
24241
+ for (const [key, state] of this.toolsByKey) {
24242
+ if (!stateMatchesOperation(state, event.operationId)) {
24543
24243
  continue;
24544
24244
  }
24545
- const state = candidateQueue.shift();
24546
- if (!state) {
24547
- return void 0;
24245
+ safeEnd(state.span, endTime);
24246
+ this.toolsByKey.delete(key);
24247
+ }
24248
+ for (const [key, state] of this.tasksById) {
24249
+ if (!stateMatchesOperation(state, event.operationId)) {
24250
+ continue;
24548
24251
  }
24549
- state.operationId = event.operationId;
24550
- this.activeOperationsById.set(event.operationId, state);
24551
- addScopedOperation(this.activeOperationsByScope, event, state);
24552
- state.metadata = {
24553
- ...state.metadata,
24554
- ...extractEventMetadata(event),
24555
- "flue.operation_id": event.operationId
24556
- };
24557
- safeLog3(state.span, { metadata: state.metadata });
24558
- return state;
24252
+ safeEnd(state.span, endTime);
24253
+ this.tasksById.delete(key);
24559
24254
  }
24560
- return void 0;
24561
- }
24562
- activeOperationForEventScope(event) {
24563
- for (const scope of operationScopeNames(event)) {
24564
- const operations = this.activeOperationsByScope.get(scope);
24565
- if (operations?.length) {
24566
- return operations[operations.length - 1];
24255
+ for (const [key, state] of this.compactionsByKey) {
24256
+ if (!stateMatchesOperation(state, event.operationId)) {
24257
+ continue;
24567
24258
  }
24259
+ safeLog3(state.span, {
24260
+ metadata: state.metadata,
24261
+ metrics: durationMetrics2(event.durationMs),
24262
+ output: { completed: true }
24263
+ });
24264
+ safeEnd(state.span, eventTime(event.timestamp));
24265
+ this.compactionsByKey.delete(key);
24568
24266
  }
24569
- return void 0;
24570
24267
  }
24571
- pendingOperationForEventScope(event) {
24572
- const scopePrefixes = operationScopePrefixes(event);
24573
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
24574
- if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
24268
+ finishPendingSpansForRun(event) {
24269
+ const endTime = eventTime(event.timestamp);
24270
+ for (const [key, state] of this.toolsByKey) {
24271
+ if (!stateMatchesRun(state, event.runId)) {
24575
24272
  continue;
24576
24273
  }
24577
- return candidateQueue[0];
24274
+ safeEnd(state.span, endTime);
24275
+ this.toolsByKey.delete(key);
24578
24276
  }
24579
- return void 0;
24580
- }
24581
- takePendingOperationForEvent(event) {
24582
- const key = operationKey(event.session, event.operationKind);
24583
- const queue2 = this.pendingOperationsByKey.get(key);
24584
- if (queue2?.length) {
24585
- return queue2.shift();
24277
+ for (const [key, state] of this.turnsByKey) {
24278
+ if (!stateMatchesRun(state, event.runId)) {
24279
+ continue;
24280
+ }
24281
+ safeEnd(state.span, endTime);
24282
+ this.turnsByKey.delete(key);
24586
24283
  }
24587
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
24588
- if (candidateKey.endsWith(`::${event.operationKind}`) && candidateQueue.length) {
24589
- return candidateQueue.shift();
24284
+ for (const [key, state] of this.tasksById) {
24285
+ if (!stateMatchesRun(state, event.runId)) {
24286
+ continue;
24590
24287
  }
24288
+ safeEnd(state.span, endTime);
24289
+ this.tasksById.delete(key);
24591
24290
  }
24592
- return void 0;
24593
- }
24594
- pendingOperationQueue(key) {
24595
- const existing = this.pendingOperationsByKey.get(key);
24596
- if (existing) {
24597
- return existing;
24291
+ for (const [key, state] of this.compactionsByKey) {
24292
+ if (!stateMatchesRun(state, event.runId)) {
24293
+ continue;
24294
+ }
24295
+ safeLog3(state.span, {
24296
+ metadata: state.metadata,
24297
+ output: { completed: true }
24298
+ });
24299
+ safeEnd(state.span, endTime);
24300
+ this.compactionsByKey.delete(key);
24301
+ }
24302
+ for (const [key, state] of this.operationsById) {
24303
+ if (!stateMatchesRun(state, event.runId)) {
24304
+ continue;
24305
+ }
24306
+ safeLog3(state.span, {
24307
+ metadata: state.metadata,
24308
+ ...state.metadata["flue.operation"] === "compact" ? { output: { completed: true } } : {}
24309
+ });
24310
+ safeEnd(state.span, endTime);
24311
+ this.operationsById.delete(key);
24598
24312
  }
24599
- const queue2 = [];
24600
- this.pendingOperationsByKey.set(key, queue2);
24601
- return queue2;
24602
24313
  }
24603
24314
  };
24604
24315
  function isInstrumentedOperation(operation) {
24605
- return operation === "prompt" || operation === "skill" || operation === "task" || operation === "compact";
24606
- }
24607
- function getSessionName(session) {
24608
- return typeof session?.name === "string" ? session.name : void 0;
24609
- }
24610
- function operationKey(sessionName, operation) {
24611
- return `${sessionName ?? "unknown"}::${operation}`;
24612
- }
24613
- function operationScopePrefixes(event) {
24614
- const scopes = /* @__PURE__ */ new Set();
24615
- for (const scope of operationScopeNames(event)) {
24616
- scopes.add(`${scope}::`);
24617
- }
24618
- return scopes;
24619
- }
24620
- function operationKeyMatchesScopes(key, scopes) {
24621
- for (const scope of scopes) {
24622
- if (key.startsWith(scope)) {
24623
- return true;
24624
- }
24625
- }
24626
- return false;
24627
- }
24628
- function operationScopeNames(event) {
24629
- const scopes = /* @__PURE__ */ new Set();
24630
- if (event.session) {
24631
- scopes.add(event.session);
24632
- }
24633
- if (event.parentSession) {
24634
- scopes.add(event.parentSession);
24635
- }
24636
- if (!scopes.size) {
24637
- scopes.add("unknown");
24638
- }
24639
- return scopes;
24640
- }
24641
- function addScopedOperation(operationsByScope, event, state) {
24642
- for (const scope of operationScopeNames(event)) {
24643
- addOperationToScope(operationsByScope, scope, state);
24644
- }
24645
- }
24646
- function addOperationToScope(operationsByScope, scope, state) {
24647
- const operations = operationsByScope.get(scope);
24648
- if (operations) {
24649
- if (!operations.includes(state)) {
24650
- operations.push(state);
24651
- }
24652
- } else {
24653
- operationsByScope.set(scope, [state]);
24654
- }
24655
- }
24656
- function removeScopedOperation(operationsByScope, state) {
24657
- for (const [scope, operations] of operationsByScope) {
24658
- const index = operations.indexOf(state);
24659
- if (index === -1) {
24660
- continue;
24661
- }
24662
- operations.splice(index, 1);
24663
- if (operations.length === 0) {
24664
- operationsByScope.delete(scope);
24665
- }
24666
- }
24316
+ return operation === "prompt" || operation === "skill" || operation === "compact";
24667
24317
  }
24668
- function removePendingOperation(pendingOperationsByKey, state) {
24669
- for (const [key, queue2] of pendingOperationsByKey) {
24670
- const index = queue2.indexOf(state);
24671
- if (index === -1) {
24672
- continue;
24673
- }
24674
- queue2.splice(index, 1);
24675
- if (queue2.length === 0) {
24676
- pendingOperationsByKey.delete(key);
24677
- }
24678
- return;
24679
- }
24680
- }
24681
- function extractSessionMetadata(session) {
24682
- const sessionName = getSessionName(session);
24683
- return sessionName ? { "flue.session": sessionName } : {};
24684
- }
24685
- function extractEventMetadata(event) {
24318
+ function extractEventMetadata(event, ctx) {
24686
24319
  return {
24687
24320
  ...event.runId ? { "flue.run_id": event.runId } : {},
24321
+ ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
24322
+ ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
24688
24323
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
24689
24324
  ...event.session ? { "flue.session": event.session } : {},
24690
24325
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
24691
24326
  ...event.harness ? { "flue.harness": event.harness } : {},
24692
24327
  ...event.taskId ? { "flue.task_id": event.taskId } : {},
24693
- ...event.operationId ? { "flue.operation_id": event.operationId } : {}
24328
+ ...event.operationId ? { "flue.operation_id": event.operationId } : {},
24329
+ ...event.turnId ? { "flue.turn_id": event.turnId } : {},
24330
+ ...typeof ctx?.id === "string" ? { "flue.context_id": ctx.id } : {},
24331
+ ...typeof ctx?.runId === "string" ? { "flue.context_run_id": ctx.runId } : {}
24694
24332
  };
24695
24333
  }
24696
- function extractOperationInput(operation, args) {
24697
- switch (operation) {
24698
- case "prompt":
24699
- case "task":
24700
- return args[0];
24701
- case "skill":
24702
- return {
24703
- args: getOptionObject(args[1])?.args,
24704
- name: args[0]
24705
- };
24706
- case "compact":
24707
- return void 0;
24334
+ function extractPayloadMetadata(payload) {
24335
+ if (!isObjectLike(payload)) {
24336
+ return {};
24708
24337
  }
24338
+ const metadata = Reflect.get(payload, "metadata");
24339
+ if (!isObjectLike(metadata)) {
24340
+ return {};
24341
+ }
24342
+ return Object.fromEntries(Object.entries(metadata));
24709
24343
  }
24710
- function extractOperationInputMetadata(operation, args) {
24711
- const options = getOptionObject(args[1]);
24712
- return {
24713
- ...operation === "skill" && typeof args[0] === "string" ? { "flue.skill_name": args[0] } : {},
24714
- ...options?.model ? { model: options.model, "flue.model": options.model } : {},
24715
- ...options?.role ? { "flue.role": options.role } : {},
24716
- ...options?.thinkingLevel ? { "flue.thinking_level": options.thinkingLevel } : {},
24717
- ...typeof options?.cwd === "string" ? { "flue.cwd": options.cwd } : {},
24718
- ...Array.isArray(options?.tools) ? {
24719
- "flue.tools_count": options.tools.length,
24720
- tools: summarizeTools(options.tools)
24721
- } : {},
24722
- ...Array.isArray(options?.images) ? { "flue.images_count": options.images.length } : {},
24723
- ...options?.result || options?.schema ? { "flue.result_schema": true } : {}
24724
- };
24725
- }
24726
- function getOptionObject(value) {
24727
- return isObject(value) ? value : void 0;
24728
- }
24729
- function summarizeTools(tools) {
24730
- return tools.flatMap((tool) => {
24731
- if (!isObject(tool)) {
24732
- return [];
24733
- }
24734
- const name = typeof tool.name === "string" ? tool.name : void 0;
24735
- if (!name) {
24736
- return [];
24737
- }
24738
- return [
24739
- {
24740
- function: {
24741
- description: typeof tool.description === "string" ? tool.description : void 0,
24742
- name,
24743
- parameters: tool.parameters
24744
- },
24745
- type: "function"
24746
- }
24747
- ];
24748
- });
24344
+ function operationOutput(event) {
24345
+ if (event.operationKind === "prompt" || event.operationKind === "skill") {
24346
+ return llmResultFromOperationResult(event.result);
24347
+ }
24348
+ return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
24749
24349
  }
24750
- function extractPromptResponseMetadata(result) {
24751
- const modelId = result?.model && typeof result.model.id === "string" ? result.model.id : void 0;
24752
- return modelId ? {
24753
- model: modelId,
24754
- "flue.model": modelId
24755
- } : {};
24350
+ function llmResultFromOperationResult(result) {
24351
+ if (!isObjectLike(result)) {
24352
+ return result;
24353
+ }
24354
+ const text = Reflect.get(result, "text");
24355
+ return text === void 0 ? result : text;
24756
24356
  }
24757
- function extractOperationOutput(result) {
24758
- if (!result) {
24357
+ function usageFromOperationResult(result) {
24358
+ if (!isObjectLike(result)) {
24759
24359
  return void 0;
24760
24360
  }
24761
- if ("data" in result) {
24762
- return result.data;
24763
- }
24764
- if ("text" in result) {
24765
- return result.text;
24766
- }
24767
- return result;
24361
+ return Reflect.get(result, "usage");
24768
24362
  }
24769
24363
  function metricsFromUsage(usage) {
24364
+ if (!isObjectLike(usage)) {
24365
+ return {};
24366
+ }
24367
+ const cacheRead = Reflect.get(usage, "cacheRead");
24368
+ const cacheWrite = Reflect.get(usage, "cacheWrite");
24369
+ const cost = Reflect.get(usage, "cost");
24370
+ const input = Reflect.get(usage, "input");
24371
+ const output = Reflect.get(usage, "output");
24372
+ const totalTokens = Reflect.get(usage, "totalTokens");
24373
+ const totalCost = isObjectLike(cost) ? Reflect.get(cost, "total") : void 0;
24770
24374
  return {
24771
- ...typeof usage?.input === "number" ? { prompt_tokens: usage.input } : {},
24772
- ...typeof usage?.output === "number" ? { completion_tokens: usage.output } : {},
24773
- ...typeof usage?.cacheRead === "number" ? { prompt_cached_tokens: usage.cacheRead } : {},
24774
- ...typeof usage?.cacheWrite === "number" ? { prompt_cache_creation_tokens: usage.cacheWrite } : {},
24775
- ...typeof usage?.totalTokens === "number" ? { tokens: usage.totalTokens } : {},
24776
- ...typeof usage?.cost?.total === "number" ? { estimated_cost: usage.cost.total } : {}
24777
- };
24778
- }
24779
- function buildDurationMetrics3(startTime) {
24780
- return {
24781
- duration_ms: Math.max(0, (getCurrentUnixTimestamp() - startTime) * 1e3)
24375
+ ...typeof input === "number" ? { prompt_tokens: input } : {},
24376
+ ...typeof output === "number" ? { completion_tokens: output } : {},
24377
+ ...typeof cacheRead === "number" ? { prompt_cached_tokens: cacheRead } : {},
24378
+ ...typeof cacheWrite === "number" ? { prompt_cache_creation_tokens: cacheWrite } : {},
24379
+ ...typeof totalTokens === "number" ? { tokens: totalTokens } : {},
24380
+ ...typeof totalCost === "number" ? { estimated_cost: totalCost } : {}
24782
24381
  };
24783
24382
  }
24784
- function durationMsMetrics(durationMs) {
24383
+ function durationMetrics2(durationMs) {
24785
24384
  return typeof durationMs === "number" ? { duration_ms: durationMs } : {};
24786
24385
  }
24787
- function scopeKey(event) {
24788
- if (event.operationId) {
24789
- return `operation:${event.operationId}`;
24790
- }
24791
- if (event.taskId) {
24792
- return `task:${event.taskId}`;
24793
- }
24794
- if (event.session) {
24795
- return `session:${event.session}`;
24386
+ function eventTime(value) {
24387
+ if (typeof value !== "string") {
24388
+ return void 0;
24796
24389
  }
24797
- return "flue:unknown";
24390
+ const timestamp = Date.parse(value);
24391
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
24392
+ }
24393
+ function turnKey(event) {
24394
+ return event.turnId;
24798
24395
  }
24799
24396
  function toolKey(event) {
24800
- return `${scopeKey(event)}::tool:${event.toolCallId ?? "unknown"}`;
24397
+ return `${event.turnId ?? event.operationId ?? event.taskId ?? event.runId ?? "unknown"}:${event.toolCallId ?? "unknown"}`;
24801
24398
  }
24802
- function toAssistantOutput(text, finishReason, reasoning, toolCalls) {
24399
+ function compactionKey(event) {
24803
24400
  return [
24804
- {
24805
- finish_reason: finishReason ?? "stop",
24806
- index: 0,
24807
- message: {
24808
- content: text,
24809
- ...reasoning ? { reasoning } : {},
24810
- role: "assistant",
24811
- ...toolCalls?.length ? {
24812
- tool_calls: toolCalls.map((toolCall) => ({
24813
- function: {
24814
- arguments: toolCall.args === void 0 ? "{}" : JSON.stringify(toolCall.args),
24815
- name: toolCall.toolName ?? "unknown"
24816
- },
24817
- ...toolCall.toolCallId ? { id: toolCall.toolCallId } : {},
24818
- type: "function"
24819
- }))
24820
- } : {}
24821
- }
24822
- }
24823
- ];
24401
+ event.instanceId ?? "",
24402
+ event.runId ?? "",
24403
+ event.session ?? "",
24404
+ event.operationId ?? "",
24405
+ event.taskId ?? ""
24406
+ ].join(":");
24407
+ }
24408
+ function stateMatchesOperation(state, operationId) {
24409
+ return state.metadata["flue.operation_id"] === operationId;
24410
+ }
24411
+ function stateMatchesRun(state, runId) {
24412
+ return state.metadata["flue.run_id"] === runId;
24824
24413
  }
24825
24414
  function startFlueSpan(parent, args) {
24826
24415
  return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
@@ -24832,6 +24421,13 @@ function safeLog3(span, event) {
24832
24421
  logInstrumentationError3("Flue span log", error);
24833
24422
  }
24834
24423
  }
24424
+ function safeEnd(span, endTime) {
24425
+ try {
24426
+ span.end(endTime === void 0 ? void 0 : { endTime });
24427
+ } catch (error) {
24428
+ logInstrumentationError3("Flue span end", error);
24429
+ }
24430
+ }
24835
24431
  function errorToString(error) {
24836
24432
  if (error instanceof Error) {
24837
24433
  return error.message;
@@ -25888,6 +25484,7 @@ __export(exports_exports, {
25888
25484
  LEGACY_CACHED_HEADER: () => LEGACY_CACHED_HEADER,
25889
25485
  LOGS3_OVERFLOW_REFERENCE_TYPE: () => LOGS3_OVERFLOW_REFERENCE_TYPE,
25890
25486
  LazyValue: () => LazyValue,
25487
+ LocalTrace: () => LocalTrace,
25891
25488
  Logger: () => Logger,
25892
25489
  LoginInvalidOrgError: () => LoginInvalidOrgError,
25893
25490
  NOOP_SPAN: () => NOOP_SPAN,
@@ -25913,6 +25510,7 @@ __export(exports_exports, {
25913
25510
  _internalIso: () => isomorph_default,
25914
25511
  _internalSetInitialState: () => _internalSetInitialState,
25915
25512
  addAzureBlobHeaders: () => addAzureBlobHeaders,
25513
+ braintrustFlueObserver: () => braintrustFlueObserver,
25916
25514
  braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
25917
25515
  buildLocalSummary: () => buildLocalSummary,
25918
25516
  configureInstrumentation: () => configureInstrumentation,
@@ -25992,8 +25590,6 @@ __export(exports_exports, {
25992
25590
  wrapCohere: () => wrapCohere,
25993
25591
  wrapCopilotClient: () => wrapCopilotClient,
25994
25592
  wrapCursorSDK: () => wrapCursorSDK,
25995
- wrapFlueContext: () => wrapFlueContext,
25996
- wrapFlueSession: () => wrapFlueSession,
25997
25593
  wrapGenkit: () => wrapGenkit,
25998
25594
  wrapGoogleADK: () => wrapGoogleADK,
25999
25595
  wrapGoogleGenAI: () => wrapGoogleGenAI,
@@ -26122,6 +25718,7 @@ async function invoke(args) {
26122
25718
  mode,
26123
25719
  schema,
26124
25720
  strict,
25721
+ overrides,
26125
25722
  projectId,
26126
25723
  ...functionIdArgs
26127
25724
  } = args;
@@ -26158,7 +25755,8 @@ async function invoke(args) {
26158
25755
  tags,
26159
25756
  stream,
26160
25757
  mode,
26161
- strict
25758
+ strict,
25759
+ overrides
26162
25760
  };
26163
25761
  const headers = {
26164
25762
  Accept: stream ? "text/event-stream" : "application/json"
@@ -32998,6 +32596,7 @@ export {
32998
32596
  LEGACY_CACHED_HEADER,
32999
32597
  LOGS3_OVERFLOW_REFERENCE_TYPE,
33000
32598
  LazyValue,
32599
+ LocalTrace,
33001
32600
  Logger,
33002
32601
  LoginInvalidOrgError,
33003
32602
  NOOP_SPAN,
@@ -33023,6 +32622,7 @@ export {
33023
32622
  isomorph_default as _internalIso,
33024
32623
  _internalSetInitialState,
33025
32624
  addAzureBlobHeaders,
32625
+ braintrustFlueObserver,
33026
32626
  braintrustStreamChunkSchema,
33027
32627
  buildLocalSummary,
33028
32628
  configureInstrumentation,
@@ -33103,8 +32703,6 @@ export {
33103
32703
  wrapCohere,
33104
32704
  wrapCopilotClient,
33105
32705
  wrapCursorSDK,
33106
- wrapFlueContext,
33107
- wrapFlueSession,
33108
32706
  wrapGenkit,
33109
32707
  wrapGoogleADK,
33110
32708
  wrapGoogleGenAI,