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/cli.js CHANGED
@@ -1232,7 +1232,7 @@ var require_package = __commonJS({
1232
1232
  "package.json"(exports2, module2) {
1233
1233
  module2.exports = {
1234
1234
  name: "braintrust",
1235
- version: "3.14.0",
1235
+ version: "3.16.0",
1236
1236
  description: "SDK for integrating Braintrust",
1237
1237
  repository: {
1238
1238
  type: "git",
@@ -5204,7 +5204,7 @@ function btStreamParser() {
5204
5204
  },
5205
5205
  async transform(chunk, controller) {
5206
5206
  if (chunk instanceof Uint8Array) {
5207
- parser.feed(decoder.decode(chunk));
5207
+ parser.feed(decoder.decode(chunk, { stream: true }));
5208
5208
  } else if (typeof chunk === "string") {
5209
5209
  parser.feed(chunk);
5210
5210
  } else {
@@ -5212,6 +5212,10 @@ function btStreamParser() {
5212
5212
  }
5213
5213
  },
5214
5214
  async flush(controller) {
5215
+ const tail = decoder.decode();
5216
+ if (tail) {
5217
+ parser.feed(tail);
5218
+ }
5215
5219
  controller.terminate();
5216
5220
  }
5217
5221
  });
@@ -11711,6 +11715,7 @@ async function invoke(args) {
11711
11715
  mode,
11712
11716
  schema,
11713
11717
  strict,
11718
+ overrides,
11714
11719
  projectId,
11715
11720
  ...functionIdArgs
11716
11721
  } = args;
@@ -11747,7 +11752,8 @@ async function invoke(args) {
11747
11752
  tags,
11748
11753
  stream,
11749
11754
  mode,
11750
- strict
11755
+ strict,
11756
+ overrides
11751
11757
  };
11752
11758
  const headers = {
11753
11759
  Accept: stream ? "text/event-stream" : "application/json"
@@ -27680,803 +27686,440 @@ var flueChannels = defineChannels("@flue/runtime", {
27680
27686
  createContext: channel({
27681
27687
  channelName: "createFlueContext",
27682
27688
  kind: "sync-stream"
27683
- }),
27684
- openSession: channel({
27685
- channelName: "Harness.openSession",
27686
- kind: "async"
27687
- }),
27688
- contextEvent: channel({
27689
- channelName: "context.event",
27690
- kind: "sync-stream"
27691
- }),
27692
- prompt: channel({
27693
- channelName: "session.prompt",
27694
- kind: "async"
27695
- }),
27696
- skill: channel({
27697
- channelName: "session.skill",
27698
- kind: "async"
27699
- }),
27700
- task: channel({
27701
- channelName: "session.task",
27702
- kind: "async"
27703
- }),
27704
- compact: channel({
27705
- channelName: "session.compact",
27706
- kind: "async"
27707
27689
  })
27708
27690
  });
27709
27691
 
27710
- // src/wrappers/flue.ts
27711
- var WRAPPED_FLUE_CONTEXT = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-context");
27712
- var WRAPPED_FLUE_HARNESS = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-harness");
27713
- var WRAPPED_FLUE_SESSION = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-session");
27714
- var SUBSCRIBED_FLUE_CONTEXT_EVENTS = /* @__PURE__ */ Symbol.for(
27715
- "braintrust.flue.subscribed-context-events"
27716
- );
27717
- function patchFlueContextInPlace(ctx) {
27718
- const context2 = ctx;
27719
- if (context2[WRAPPED_FLUE_CONTEXT]) {
27720
- return ctx;
27721
- }
27722
- const originalInit = context2.init.bind(context2);
27723
- try {
27724
- Object.defineProperty(context2, WRAPPED_FLUE_CONTEXT, {
27725
- configurable: false,
27726
- enumerable: false,
27727
- value: true
27728
- });
27729
- Object.defineProperty(context2, "init", {
27730
- configurable: true,
27731
- value: async function wrappedFlueInit(options) {
27732
- const harness = await originalInit(options);
27733
- return wrapFlueHarness(harness);
27734
- },
27735
- writable: true
27736
- });
27737
- } catch {
27738
- }
27739
- return ctx;
27740
- }
27741
- function subscribeFlueContextEvents(ctx, options = {}) {
27742
- if (!ctx || typeof ctx !== "object" || typeof ctx.subscribeEvent !== "function") {
27743
- return void 0;
27692
+ // src/instrumentation/plugins/flue-plugin.ts
27693
+ var FLUE_AUTO_STATE = /* @__PURE__ */ Symbol.for("braintrust.flue.auto-state");
27694
+ var FLUE_OBSERVE_BRIDGE = /* @__PURE__ */ Symbol.for("braintrust.flue.observe-bridge");
27695
+ var braintrustFlueObserver = (event, ctx) => {
27696
+ getObserveBridge().handle(event, ctx);
27697
+ };
27698
+ var FluePlugin = class extends BasePlugin {
27699
+ onEnable() {
27700
+ this.unsubscribers.push(enableFlueAutoInstrumentation());
27744
27701
  }
27745
- const context2 = ctx;
27746
- const captureTurnSpans = options.captureTurnSpans ?? true;
27747
- const existingSubscription = context2[SUBSCRIBED_FLUE_CONTEXT_EVENTS];
27748
- if (existingSubscription) {
27749
- if (existingSubscription.captureTurnSpans || !captureTurnSpans) {
27750
- return void 0;
27751
- }
27752
- try {
27753
- existingSubscription.unsubscribe();
27754
- } catch {
27702
+ onDisable() {
27703
+ for (const unsubscribe of this.unsubscribers) {
27704
+ unsubscribe();
27755
27705
  }
27706
+ this.unsubscribers = [];
27756
27707
  }
27757
- try {
27758
- const unsubscribe = ctx.subscribeEvent((event) => {
27759
- flueChannels.contextEvent.traceSync(() => void 0, {
27760
- arguments: [event],
27761
- captureTurnSpans,
27762
- context: ctx
27763
- });
27764
- });
27765
- if (existingSubscription) {
27766
- existingSubscription.captureTurnSpans = captureTurnSpans;
27767
- existingSubscription.unsubscribe = unsubscribe;
27768
- } else {
27769
- Object.defineProperty(context2, SUBSCRIBED_FLUE_CONTEXT_EVENTS, {
27770
- configurable: false,
27771
- enumerable: false,
27772
- value: {
27773
- captureTurnSpans,
27774
- unsubscribe
27775
- }
27776
- });
27708
+ };
27709
+ function enableFlueAutoInstrumentation() {
27710
+ const state = getAutoState();
27711
+ state.refCount += 1;
27712
+ if (!state.handlers) {
27713
+ const channel2 = flueChannels.createContext.tracingChannel();
27714
+ const handlers = {
27715
+ end: (event) => {
27716
+ subscribeToFlueContext(event.result, state);
27717
+ }
27718
+ };
27719
+ channel2.subscribe(handlers);
27720
+ state.channel = channel2;
27721
+ state.handlers = handlers;
27722
+ }
27723
+ let released = false;
27724
+ return () => {
27725
+ if (released) {
27726
+ return;
27777
27727
  }
27778
- return unsubscribe;
27779
- } catch {
27780
- return void 0;
27728
+ released = true;
27729
+ releaseAutoState(state);
27730
+ };
27731
+ }
27732
+ function getAutoState() {
27733
+ const existing = Reflect.get(globalThis, FLUE_AUTO_STATE);
27734
+ if (isAutoState(existing)) {
27735
+ return existing;
27781
27736
  }
27737
+ const state = {
27738
+ contexts: /* @__PURE__ */ new WeakSet(),
27739
+ refCount: 0
27740
+ };
27741
+ Reflect.set(globalThis, FLUE_AUTO_STATE, state);
27742
+ return state;
27782
27743
  }
27783
- function wrapFlueHarness(harness) {
27784
- if (!isPlausibleFlueHarness(harness)) {
27785
- return harness;
27744
+ function getObserveBridge() {
27745
+ const existing = Reflect.get(globalThis, FLUE_OBSERVE_BRIDGE);
27746
+ if (isFlueObserveBridge(existing)) {
27747
+ return existing;
27786
27748
  }
27787
- const target = harness;
27788
- if (target[WRAPPED_FLUE_HARNESS]) {
27789
- return harness;
27749
+ const bridge = new FlueObserveBridge();
27750
+ Reflect.set(globalThis, FLUE_OBSERVE_BRIDGE, bridge);
27751
+ return bridge;
27752
+ }
27753
+ function isFlueObserveBridge(value) {
27754
+ return isObjectLike(value) && typeof Reflect.get(value, "handle") === "function" && typeof Reflect.get(value, "reset") === "function";
27755
+ }
27756
+ function isAutoState(value) {
27757
+ return isObjectLike(value) && Reflect.get(value, "contexts") instanceof WeakSet && typeof Reflect.get(value, "refCount") === "number";
27758
+ }
27759
+ function releaseAutoState(state) {
27760
+ state.refCount -= 1;
27761
+ if (state.refCount > 0) {
27762
+ return;
27790
27763
  }
27791
- const originalSession = target.session.bind(target);
27792
27764
  try {
27793
- Object.defineProperty(target, WRAPPED_FLUE_HARNESS, {
27794
- configurable: false,
27795
- enumerable: false,
27796
- value: true
27797
- });
27798
- Object.defineProperty(target, "session", {
27799
- configurable: true,
27800
- value: async function wrappedFlueHarnessSession(name, options) {
27801
- const session = await originalSession(name, options);
27802
- return patchFlueSessionInPlace(session);
27803
- },
27804
- writable: true
27805
- });
27806
- const sessions = target.sessions;
27807
- if (sessions && typeof sessions === "object") {
27808
- patchFlueSessionFactory(sessions, "get");
27809
- patchFlueSessionFactory(sessions, "create");
27765
+ if (state.channel && state.handlers) {
27766
+ state.channel.unsubscribe(state.handlers);
27810
27767
  }
27811
- } catch {
27768
+ } finally {
27769
+ Reflect.deleteProperty(globalThis, FLUE_AUTO_STATE);
27812
27770
  }
27813
- return harness;
27814
27771
  }
27815
- function patchFlueSessionInPlace(session) {
27816
- if (session[WRAPPED_FLUE_SESSION]) {
27817
- return session;
27772
+ function subscribeToFlueContext(value, state) {
27773
+ if (!isObservableFlueContext(value) || state.contexts.has(value)) {
27774
+ return;
27818
27775
  }
27776
+ const ctx = flueContextFromUnknown(value);
27777
+ let released = false;
27778
+ let unsubscribe;
27779
+ const release = () => {
27780
+ if (released) {
27781
+ return;
27782
+ }
27783
+ released = true;
27784
+ try {
27785
+ unsubscribe?.();
27786
+ } catch (error2) {
27787
+ logInstrumentationError3("Flue context unsubscribe", error2);
27788
+ }
27789
+ };
27819
27790
  try {
27820
- Object.defineProperty(session, WRAPPED_FLUE_SESSION, {
27821
- configurable: false,
27822
- enumerable: false,
27823
- value: true
27791
+ unsubscribe = value.subscribeEvent((event) => {
27792
+ if (state.refCount <= 0) {
27793
+ release();
27794
+ return;
27795
+ }
27796
+ braintrustFlueObserver(event, ctx);
27797
+ if (isAutoContextTerminalEvent(event, ctx)) {
27798
+ release();
27799
+ }
27824
27800
  });
27825
- patchCallHandleMethod(session, "prompt", flueChannels.prompt);
27826
- patchCallHandleMethod(session, "skill", flueChannels.skill);
27827
- patchCallHandleMethod(session, "task", flueChannels.task);
27828
- patchCompact(session);
27829
- } catch {
27801
+ state.contexts.add(value);
27802
+ } catch (error2) {
27803
+ logInstrumentationError3("Flue context subscription", error2);
27830
27804
  }
27831
- return session;
27832
27805
  }
27833
- function patchFlueSessionFactory(sessions, method) {
27834
- const original = sessions[method];
27835
- if (typeof original !== "function") {
27836
- return;
27806
+ function isAutoContextTerminalEvent(event, ctx) {
27807
+ if (!isObjectLike(event)) {
27808
+ return false;
27837
27809
  }
27838
- const bound = original.bind(sessions);
27839
- Object.defineProperty(sessions, method, {
27840
- configurable: true,
27841
- value: async function wrappedFlueSessionFactory(name, options) {
27842
- const session = await bound(name, options);
27843
- return patchFlueSessionInPlace(session);
27844
- },
27845
- writable: true
27846
- });
27847
- }
27848
- function patchCallHandleMethod(session, method, channel2) {
27849
- const original = session[method];
27850
- if (typeof original !== "function") {
27851
- return;
27810
+ const type = Reflect.get(event, "type");
27811
+ if (type === "run_end") {
27812
+ return true;
27852
27813
  }
27853
- const bound = original.bind(session);
27854
- Object.defineProperty(session, method, {
27855
- configurable: true,
27856
- value(input, options) {
27857
- const args = [input, options];
27858
- const { originalResult, traced: traced2 } = traceFlueOperation(channel2, {
27859
- context: {
27860
- arguments: args,
27861
- operation: method,
27862
- session
27863
- },
27864
- run: () => bound(input, options)
27865
- });
27866
- return preserveCallHandle(originalResult, traced2);
27867
- },
27868
- writable: true
27869
- });
27870
- }
27871
- function patchCompact(session) {
27872
- const original = session.compact;
27873
- if (typeof original !== "function") {
27874
- return;
27814
+ if (type !== "operation") {
27815
+ return false;
27875
27816
  }
27876
- const bound = original.bind(session);
27877
- Object.defineProperty(session, "compact", {
27878
- configurable: true,
27879
- value() {
27880
- const context2 = {
27881
- arguments: [],
27882
- operation: "compact",
27883
- session
27884
- };
27885
- return flueChannels.compact.tracePromise(() => bound(), context2);
27886
- },
27887
- writable: true
27888
- });
27817
+ return !ctx?.runId && typeof Reflect.get(event, "runId") !== "string";
27889
27818
  }
27890
- function traceFlueOperation(channel2, args) {
27891
- const tracingChannel2 = channel2.tracingChannel();
27892
- const context2 = args.context;
27893
- let originalResult;
27894
- let traced2;
27895
- const run2 = () => {
27896
- try {
27897
- originalResult = args.run();
27898
- tracingChannel2.end?.publish(context2);
27899
- } catch (error2) {
27900
- context2.error = normalizeError3(error2);
27901
- tracingChannel2.error?.publish(context2);
27902
- tracingChannel2.end?.publish(context2);
27903
- throw error2;
27904
- }
27905
- traced2 = Promise.resolve(originalResult).then(
27906
- (result) => {
27907
- context2.result = result;
27908
- tracingChannel2.asyncStart?.publish(context2);
27909
- tracingChannel2.asyncEnd?.publish(context2);
27910
- return result;
27911
- },
27912
- (error2) => {
27913
- context2.error = normalizeError3(error2);
27914
- tracingChannel2.error?.publish(context2);
27915
- tracingChannel2.asyncStart?.publish(context2);
27916
- tracingChannel2.asyncEnd?.publish(context2);
27917
- throw error2;
27918
- }
27919
- );
27920
- };
27921
- if (tracingChannel2.start?.runStores) {
27922
- tracingChannel2.start.runStores(context2, run2);
27923
- } else {
27924
- tracingChannel2.start?.publish(context2);
27925
- run2();
27926
- }
27927
- return { originalResult, traced: traced2 };
27819
+ function isObservableFlueContext(value) {
27820
+ return isObjectLike(value) && typeof Reflect.get(value, "subscribeEvent") === "function";
27928
27821
  }
27929
- function normalizeError3(error2) {
27930
- return error2 instanceof Error ? error2 : new Error(String(error2));
27822
+ function isFlueEvent(event) {
27823
+ const type = Reflect.get(event, "type");
27824
+ 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";
27931
27825
  }
27932
- function preserveCallHandle(originalHandle, traced2) {
27933
- if (!isFlueCallHandle(originalHandle)) {
27934
- return traced2;
27826
+ function flueContextFromUnknown(ctx) {
27827
+ if (!isObjectLike(ctx)) {
27828
+ return void 0;
27935
27829
  }
27936
- const handle = originalHandle;
27937
- const wrapped = {
27938
- get signal() {
27939
- return handle.signal;
27940
- },
27941
- abort(reason) {
27942
- return handle.abort(reason);
27943
- },
27944
- then(onfulfilled, onrejected) {
27945
- return traced2.then(onfulfilled, onrejected);
27946
- }
27830
+ const id = Reflect.get(ctx, "id");
27831
+ const runId = Reflect.get(ctx, "runId");
27832
+ return {
27833
+ ...typeof id === "string" ? { id } : {},
27834
+ ...typeof runId === "string" ? { runId } : {}
27947
27835
  };
27948
- return wrapped;
27949
27836
  }
27950
- function isPlausibleFlueHarness(value) {
27951
- return !!value && typeof value === "object" && typeof value.session === "function";
27952
- }
27953
- function isFlueCallHandle(value) {
27954
- return !!value && typeof value === "object" && typeof value.then === "function" && typeof value.abort === "function" && "signal" in value;
27837
+ function isObjectLike(value) {
27838
+ return typeof value === "object" && value !== null && !Array.isArray(value);
27955
27839
  }
27956
-
27957
- // src/instrumentation/plugins/flue-plugin.ts
27958
- var FluePlugin = class extends BasePlugin {
27959
- activeOperationsById = /* @__PURE__ */ new Map();
27960
- activeOperationsByScope = /* @__PURE__ */ new Map();
27961
- compactionsByScope = /* @__PURE__ */ new Map();
27962
- pendingOperationsByKey = /* @__PURE__ */ new Map();
27840
+ var FlueObserveBridge = class {
27841
+ compactionsByKey = /* @__PURE__ */ new Map();
27842
+ operationsById = /* @__PURE__ */ new Map();
27843
+ runsById = /* @__PURE__ */ new Map();
27844
+ seenEvents = /* @__PURE__ */ new WeakSet();
27963
27845
  tasksById = /* @__PURE__ */ new Map();
27964
- toolsById = /* @__PURE__ */ new Map();
27965
- turnsByScope = /* @__PURE__ */ new Map();
27966
- onEnable() {
27967
- this.subscribeToContextCreation();
27968
- this.subscribeToSessionCreation();
27969
- this.subscribeToContextEvents();
27970
- this.subscribeToSessionOperations();
27971
- }
27972
- onDisable() {
27973
- for (const unsubscribe of this.unsubscribers) {
27974
- unsubscribe();
27846
+ toolsByKey = /* @__PURE__ */ new Map();
27847
+ turnsByKey = /* @__PURE__ */ new Map();
27848
+ handle(event, ctx) {
27849
+ if (!isObjectLike(event) || !isFlueEvent(event)) {
27850
+ return;
27975
27851
  }
27976
- this.unsubscribers = [];
27977
- this.activeOperationsById.clear();
27978
- this.activeOperationsByScope.clear();
27979
- this.compactionsByScope.clear();
27980
- this.pendingOperationsByKey.clear();
27852
+ if (this.seenEvents.has(event)) {
27853
+ return;
27854
+ }
27855
+ this.seenEvents.add(event);
27856
+ try {
27857
+ this.handleEvent(event, flueContextFromUnknown(ctx));
27858
+ } catch (error2) {
27859
+ logInstrumentationError3("Flue observe", error2);
27860
+ }
27861
+ }
27862
+ reset() {
27863
+ this.compactionsByKey.clear();
27864
+ this.operationsById.clear();
27865
+ this.runsById.clear();
27866
+ this.seenEvents = /* @__PURE__ */ new WeakSet();
27981
27867
  this.tasksById.clear();
27982
- this.toolsById.clear();
27983
- this.turnsByScope.clear();
27868
+ this.toolsByKey.clear();
27869
+ this.turnsByKey.clear();
27984
27870
  }
27985
- subscribeToContextCreation() {
27986
- const channel2 = flueChannels.createContext.tracingChannel();
27987
- const handlers = {
27988
- end: (event) => {
27989
- const ctx = event.result;
27990
- if (!ctx) {
27991
- return;
27992
- }
27993
- subscribeFlueContextEvents(ctx, { captureTurnSpans: false });
27994
- patchFlueContextInPlace(ctx);
27995
- },
27996
- error: () => {
27997
- }
27998
- };
27999
- channel2.subscribe(handlers);
28000
- this.unsubscribers.push(() => {
28001
- channel2.unsubscribe(handlers);
28002
- });
27871
+ handleEvent(event, ctx) {
27872
+ switch (event.type) {
27873
+ case "run_start":
27874
+ this.handleRunStart(event, ctx);
27875
+ return;
27876
+ case "run_end":
27877
+ this.handleRunEnd(event);
27878
+ return;
27879
+ case "operation_start":
27880
+ this.handleOperationStart(event);
27881
+ return;
27882
+ case "operation":
27883
+ this.handleOperation(event);
27884
+ return;
27885
+ case "turn_request":
27886
+ this.handleTurnRequest(event);
27887
+ return;
27888
+ case "turn":
27889
+ this.handleTurn(event);
27890
+ return;
27891
+ case "tool_start":
27892
+ this.handleToolStart(event);
27893
+ return;
27894
+ case "tool_call":
27895
+ this.handleToolCall(event);
27896
+ return;
27897
+ case "task_start":
27898
+ this.handleTaskStart(event);
27899
+ return;
27900
+ case "task":
27901
+ this.handleTask(event);
27902
+ return;
27903
+ case "compaction_start":
27904
+ this.handleCompactionStart(event);
27905
+ return;
27906
+ case "compaction":
27907
+ this.handleCompaction(event);
27908
+ return;
27909
+ default:
27910
+ return;
27911
+ }
28003
27912
  }
28004
- subscribeToSessionCreation() {
28005
- const channel2 = flueChannels.openSession.tracingChannel();
28006
- const handlers = {
28007
- asyncEnd: (event) => {
28008
- if (event.result) {
28009
- patchFlueSessionInPlace(
28010
- event.result
28011
- );
28012
- }
28013
- if (event.harness) {
28014
- wrapFlueHarness(event.harness);
28015
- }
28016
- },
28017
- error: () => {
28018
- }
27913
+ handleRunStart(event, ctx) {
27914
+ if (!event.runId) {
27915
+ return;
27916
+ }
27917
+ const workflowName = event.workflowName ?? event.owner?.workflowName ?? (typeof ctx?.id === "string" ? ctx.id : "unknown");
27918
+ const metadata = {
27919
+ ...extractPayloadMetadata(event.payload),
27920
+ ...extractEventMetadata(event, ctx),
27921
+ ...workflowName ? { "flue.workflow_name": workflowName } : {},
27922
+ provider: "flue"
28019
27923
  };
28020
- channel2.subscribe(handlers);
28021
- this.unsubscribers.push(() => {
28022
- channel2.unsubscribe(handlers);
27924
+ const span = startSpan({
27925
+ name: `workflow:${workflowName}`,
27926
+ spanAttributes: { type: "task" /* TASK */ },
27927
+ startTime: eventTime(event.startedAt ?? event.timestamp),
27928
+ event: {
27929
+ input: event.payload,
27930
+ metadata
27931
+ }
28023
27932
  });
27933
+ this.runsById.set(event.runId, { metadata, span });
28024
27934
  }
28025
- subscribeToSessionOperations() {
28026
- this.subscribeToSessionOperation(flueChannels.prompt);
28027
- this.subscribeToSessionOperation(flueChannels.skill);
28028
- this.subscribeToSessionOperation(flueChannels.task);
28029
- this.subscribeToCompact();
28030
- }
28031
- subscribeToSessionOperation(channel2) {
28032
- const tracingChannel2 = channel2.tracingChannel();
28033
- const states = /* @__PURE__ */ new WeakMap();
28034
- const ensureState2 = (event) => {
28035
- const existing = states.get(event);
28036
- if (existing) {
28037
- return existing;
28038
- }
28039
- const state = this.startOperationState({
28040
- args: event.arguments,
28041
- moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
28042
- operation: event.operation,
28043
- session: event.session
27935
+ handleRunEnd(event) {
27936
+ const state = this.runsById.get(event.runId);
27937
+ this.finishPendingSpansForRun(event);
27938
+ if (state) {
27939
+ safeLog3(state.span, {
27940
+ ...event.isError ? { error: errorToString(event.error) } : {},
27941
+ metadata: {
27942
+ ...state.metadata,
27943
+ ...extractEventMetadata(event),
27944
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
27945
+ },
27946
+ metrics: durationMetrics2(event.durationMs),
27947
+ output: event.result
28044
27948
  });
28045
- states.set(event, state);
28046
- return state;
28047
- };
28048
- const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
28049
- tracingChannel2,
28050
- ensureState2
28051
- );
28052
- const handlers = {
28053
- start: (event) => {
28054
- ensureState2(event);
28055
- },
28056
- asyncEnd: (event) => {
28057
- this.endOperationState(states.get(event), event.result);
28058
- states.delete(event);
28059
- },
28060
- error: (event) => {
28061
- const state = states.get(event);
28062
- if (state && event.error) {
28063
- safeLog3(state.span, { error: errorToString(event.error) });
28064
- this.finishOperationState(state);
28065
- }
28066
- states.delete(event);
28067
- }
28068
- };
28069
- tracingChannel2.subscribe(handlers);
28070
- this.unsubscribers.push(() => {
28071
- unbindCurrentSpanStore?.();
28072
- tracingChannel2.unsubscribe(handlers);
27949
+ safeEnd(state.span, eventTime(event.timestamp));
27950
+ this.runsById.delete(event.runId);
27951
+ }
27952
+ void flush().catch((error2) => {
27953
+ logInstrumentationError3("Flue flush", error2);
28073
27954
  });
28074
27955
  }
28075
- subscribeToCompact() {
28076
- const tracingChannel2 = flueChannels.compact.tracingChannel();
28077
- const states = /* @__PURE__ */ new WeakMap();
28078
- const ensureState2 = (event) => {
28079
- const existing = states.get(event);
28080
- if (existing) {
28081
- return existing;
28082
- }
28083
- const state = this.startOperationState({
28084
- args: [],
28085
- moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
28086
- operation: event.operation,
28087
- session: event.session
28088
- });
28089
- states.set(event, state);
28090
- return state;
28091
- };
28092
- const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
28093
- tracingChannel2,
28094
- ensureState2
28095
- );
28096
- const handlers = {
28097
- start: (event) => {
28098
- ensureState2(event);
28099
- },
28100
- asyncEnd: (event) => {
28101
- this.endOperationState(states.get(event), void 0);
28102
- states.delete(event);
28103
- },
28104
- error: (event) => {
28105
- const state = states.get(event);
28106
- if (state && event.error) {
28107
- safeLog3(state.span, { error: errorToString(event.error) });
28108
- this.finishOperationState(state);
28109
- }
28110
- states.delete(event);
28111
- }
28112
- };
28113
- tracingChannel2.subscribe(handlers);
28114
- this.unsubscribers.push(() => {
28115
- unbindCurrentSpanStore?.();
28116
- tracingChannel2.unsubscribe(handlers);
28117
- });
28118
- }
28119
- subscribeToContextEvents() {
28120
- const channel2 = flueChannels.contextEvent.tracingChannel();
28121
- const handlers = {
28122
- start: (event) => {
28123
- const flueEvent = event.arguments[0];
28124
- if (!flueEvent) {
28125
- return;
28126
- }
28127
- try {
28128
- this.handleFlueEvent(flueEvent, {
28129
- captureTurnSpans: event.captureTurnSpans !== false
28130
- });
28131
- } catch (error2) {
28132
- logInstrumentationError3("Flue event", error2);
28133
- }
28134
- },
28135
- error: () => {
28136
- }
28137
- };
28138
- channel2.subscribe(handlers);
28139
- this.unsubscribers.push(() => {
28140
- channel2.unsubscribe(handlers);
28141
- });
28142
- }
28143
- bindCurrentSpanStoreToOperationStart(tracingChannel2, ensureState2) {
28144
- const state = _internalGetGlobalState();
28145
- const startChannel = tracingChannel2.start;
28146
- const contextManager = state?.contextManager;
28147
- const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
28148
- if (!currentSpanStore || !startChannel) {
28149
- return void 0;
28150
- }
28151
- startChannel.bindStore(currentSpanStore, (event) => {
28152
- const operationState = ensureState2(event);
28153
- return contextManager.wrapSpanForStore(operationState.span);
28154
- });
28155
- return () => {
28156
- startChannel.unbindStore(currentSpanStore);
28157
- };
28158
- }
28159
- startOperationState(args) {
28160
- const sessionName = getSessionName(args.session);
28161
- const metadata = {
28162
- ...extractOperationInputMetadata(args.operation, args.args),
28163
- ...extractSessionMetadata(args.session),
28164
- "flue.operation": args.operation,
28165
- provider: "flue",
28166
- ...args.moduleVersion ? { "flue.version": args.moduleVersion } : {}
28167
- };
28168
- const span = startSpan({
28169
- name: `flue.session.${args.operation}`,
28170
- spanAttributes: { type: "task" /* TASK */ }
28171
- });
28172
- const state = {
28173
- metadata,
28174
- operation: args.operation,
28175
- sessionName,
28176
- span,
28177
- startTime: getCurrentUnixTimestamp()
28178
- };
28179
- safeLog3(span, {
28180
- input: extractOperationInput(args.operation, args.args),
28181
- metadata
28182
- });
28183
- this.pendingOperationQueue(operationKey(sessionName, args.operation)).push(
28184
- state
28185
- );
28186
- addOperationToScope(
28187
- this.activeOperationsByScope,
28188
- sessionName ?? "unknown",
28189
- state
28190
- );
28191
- return state;
28192
- }
28193
- endOperationState(state, result) {
28194
- if (!state) {
28195
- return;
28196
- }
28197
- const metadata = {
28198
- ...state.metadata,
28199
- ...extractPromptResponseMetadata(result)
28200
- };
28201
- const metrics = {
28202
- ...buildDurationMetrics3(state.startTime),
28203
- ...metricsFromUsage(result?.usage)
28204
- };
28205
- safeLog3(state.span, {
28206
- metadata,
28207
- metrics,
28208
- output: extractOperationOutput(result)
28209
- });
28210
- this.finishCompactionsForOperation(state);
28211
- this.finishOperationState(state);
28212
- }
28213
- finishOperationState(state) {
28214
- removePendingOperation(this.pendingOperationsByKey, state);
28215
- if (state.operationId) {
28216
- this.activeOperationsById.delete(state.operationId);
28217
- }
28218
- removeScopedOperation(this.activeOperationsByScope, state);
28219
- state.span.end();
28220
- }
28221
- handleFlueEvent(event, options) {
28222
- switch (event.type) {
28223
- case "operation_start":
28224
- this.handleOperationStart(event);
28225
- return;
28226
- case "operation":
28227
- this.handleOperation(event);
28228
- return;
28229
- case "text_delta":
28230
- if (!options.captureTurnSpans) {
28231
- return;
28232
- }
28233
- this.ensureTurnState(event).text.push(
28234
- typeof event.text === "string" ? event.text : ""
28235
- );
28236
- return;
28237
- case "thinking_start":
28238
- if (!options.captureTurnSpans) {
28239
- return;
28240
- }
28241
- this.handleThinkingStart(event);
28242
- return;
28243
- case "thinking_delta":
28244
- if (!options.captureTurnSpans) {
28245
- return;
28246
- }
28247
- this.handleThinkingDelta(event);
28248
- return;
28249
- case "thinking_end":
28250
- if (!options.captureTurnSpans) {
28251
- return;
28252
- }
28253
- this.handleThinkingEnd(event);
28254
- return;
28255
- case "turn":
28256
- if (!options.captureTurnSpans) {
28257
- return;
28258
- }
28259
- this.handleTurn(event);
28260
- return;
28261
- case "tool_start":
28262
- this.handleToolStart(event, options);
28263
- return;
28264
- case "tool_call":
28265
- this.handleToolCall(event);
28266
- return;
28267
- case "task_start":
28268
- this.handleTaskStart(event);
28269
- return;
28270
- case "task":
28271
- this.handleTask(event);
28272
- return;
28273
- case "compaction_start":
28274
- this.handleCompactionStart(event);
28275
- return;
28276
- case "compaction":
28277
- this.handleCompaction(event);
28278
- return;
28279
- default:
28280
- return;
28281
- }
28282
- }
28283
27956
  handleOperationStart(event) {
28284
- if (!isInstrumentedOperation(event.operationKind)) {
27957
+ if (!event.operationId || !isInstrumentedOperation(event.operationKind)) {
28285
27958
  return;
28286
27959
  }
28287
- const state = this.takePendingOperationForEvent(event);
28288
- if (!state) {
28289
- return;
28290
- }
28291
- state.operationId = event.operationId;
28292
- this.activeOperationsById.set(event.operationId, state);
28293
- addScopedOperation(this.activeOperationsByScope, event, state);
28294
- state.metadata = {
28295
- ...state.metadata,
27960
+ const metadata = {
28296
27961
  ...extractEventMetadata(event),
28297
- "flue.operation_id": event.operationId
27962
+ "flue.operation": event.operationKind,
27963
+ provider: "flue"
28298
27964
  };
28299
- safeLog3(state.span, { metadata: state.metadata });
27965
+ const parent = this.parentSpanForEvent(event);
27966
+ const span = startFlueSpan(parent, {
27967
+ name: `flue.${event.operationKind}`,
27968
+ spanAttributes: { type: "task" /* TASK */ },
27969
+ startTime: eventTime(event.timestamp),
27970
+ event: { metadata }
27971
+ });
27972
+ this.operationsById.set(event.operationId, { metadata, span });
28300
27973
  }
28301
27974
  handleOperation(event) {
28302
- const state = event.operationId ? this.activeOperationsById.get(event.operationId) : void 0;
28303
- if (!state) {
27975
+ if (!isInstrumentedOperation(event.operationKind)) {
28304
27976
  return;
28305
27977
  }
27978
+ const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
27979
+ const output = operationOutput(event);
28306
27980
  const metadata = {
28307
27981
  ...state.metadata,
28308
27982
  ...extractEventMetadata(event),
28309
- ...typeof event.durationMs === "number" ? { "flue.duration_ms": event.durationMs } : {},
28310
- ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
27983
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
27984
+ ...event.usage ? { "flue.usage": event.usage } : {}
28311
27985
  };
28312
- const metrics = metricsFromUsage(event.usage);
27986
+ this.finishPendingChildrenForOperation(event, output);
28313
27987
  safeLog3(state.span, {
28314
- ...event.error ? { error: errorToString(event.error) } : {},
27988
+ ...event.isError ? { error: errorToString(event.error) } : {},
28315
27989
  metadata,
28316
- ...Object.keys(metrics).length ? { metrics } : {}
27990
+ metrics: durationMetrics2(event.durationMs),
27991
+ output
28317
27992
  });
27993
+ safeEnd(state.span, eventTime(event.timestamp));
27994
+ this.operationsById.delete(event.operationId);
28318
27995
  }
28319
- ensureTurnState(event) {
28320
- const scope = scopeKey(event);
28321
- const existing = this.turnsByScope.get(scope);
28322
- if (existing) {
28323
- return existing;
27996
+ handleTurnRequest(event) {
27997
+ const key = turnKey(event);
27998
+ if (!key) {
27999
+ return;
28324
28000
  }
28325
- const parent = this.parentSpanForEvent(event);
28326
28001
  const metadata = {
28327
28002
  ...extractEventMetadata(event),
28328
- provider: "flue"
28003
+ ...event.api ? { "flue.api": event.api } : {},
28004
+ ...event.model ? { model: event.model, "flue.model": event.model } : {},
28005
+ ...event.provider ? { provider: event.provider } : { provider: "flue" },
28006
+ ...event.provider ? { "flue.provider": event.provider } : {},
28007
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
28008
+ ...event.reasoning ? { reasoning: event.reasoning } : {},
28009
+ ...event.input?.systemPrompt ? { "flue.system_prompt": event.input.systemPrompt } : {},
28010
+ ...event.input?.tools ? { tools: event.input.tools } : {}
28329
28011
  };
28012
+ const parent = this.parentSpanForTurn(event);
28330
28013
  const span = startFlueSpan(parent, {
28331
- name: "flue.turn",
28332
- spanAttributes: { type: "llm" /* LLM */ }
28014
+ name: `llm:${event.model ?? event.purpose ?? "unknown"}`,
28015
+ spanAttributes: { type: "llm" /* LLM */ },
28016
+ startTime: eventTime(event.timestamp),
28017
+ event: {
28018
+ input: event.input?.messages,
28019
+ metadata
28020
+ }
28333
28021
  });
28334
- const state = {
28335
- metadata,
28336
- span,
28337
- hasThinking: false,
28338
- startTime: getCurrentUnixTimestamp(),
28339
- text: [],
28340
- thinking: [],
28341
- toolCalls: []
28342
- };
28343
- safeLog3(span, { metadata });
28344
- this.turnsByScope.set(scope, state);
28345
- return state;
28022
+ this.logOperationInput(
28023
+ event.operationId,
28024
+ event.input?.messages ?? event.input
28025
+ );
28026
+ this.turnsByKey.set(key, { metadata, span });
28346
28027
  }
28347
28028
  handleTurn(event) {
28348
- const scope = scopeKey(event);
28349
- const state = this.ensureTurnState(event);
28350
- const text = state.text.join("");
28351
- const reasoning = state.finalThinking ?? state.thinking.join("");
28352
- const outputReasoning = reasoning || (state.hasThinking ? "[reasoning stream present; content unavailable]" : void 0);
28029
+ const key = turnKey(event);
28030
+ if (!key) {
28031
+ return;
28032
+ }
28033
+ const state = this.turnsByKey.get(key) ?? this.startSyntheticTurn(event);
28353
28034
  const metadata = {
28354
28035
  ...state.metadata,
28355
28036
  ...extractEventMetadata(event),
28037
+ ...event.api ? { "flue.api": event.api } : {},
28356
28038
  ...event.model ? { model: event.model, "flue.model": event.model } : {},
28039
+ ...event.provider ? { provider: event.provider } : {},
28040
+ ...event.provider ? { "flue.provider": event.provider } : {},
28041
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
28357
28042
  ...event.stopReason ? { "flue.stop_reason": event.stopReason } : {},
28358
- ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
28359
- provider: "flue"
28043
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
28360
28044
  };
28361
28045
  safeLog3(state.span, {
28362
- ...event.error ? { error: errorToString(event.error) } : {},
28046
+ ...event.isError ? { error: errorToString(event.error) } : {},
28363
28047
  metadata,
28364
28048
  metrics: {
28365
- ...durationMsMetrics(event.durationMs),
28049
+ ...durationMetrics2(event.durationMs),
28366
28050
  ...metricsFromUsage(event.usage)
28367
28051
  },
28368
- output: toAssistantOutput(
28369
- text,
28370
- event.stopReason,
28371
- outputReasoning,
28372
- state.toolCalls
28373
- )
28052
+ output: event.output
28374
28053
  });
28375
- state.span.end();
28376
- this.turnsByScope.delete(scope);
28054
+ safeEnd(state.span, eventTime(event.timestamp));
28055
+ this.turnsByKey.delete(key);
28377
28056
  }
28378
- handleThinkingDelta(event) {
28379
- const delta = event.delta;
28380
- if (typeof delta !== "string" || !delta) {
28057
+ handleToolStart(event) {
28058
+ if (!event.toolCallId) {
28381
28059
  return;
28382
28060
  }
28383
- const state = this.ensureTurnState(event);
28384
- state.hasThinking = true;
28385
- state.metadata["flue.thinking"] = true;
28386
- state.thinking.push(delta);
28387
- }
28388
- handleThinkingStart(event) {
28389
- const state = this.ensureTurnState(event);
28390
- state.hasThinking = true;
28391
- state.metadata["flue.thinking"] = true;
28392
- }
28393
- handleThinkingEnd(event) {
28394
- const state = this.ensureTurnState(event);
28395
- state.hasThinking = true;
28396
- state.metadata["flue.thinking"] = true;
28397
- if (typeof event.content === "string" && event.content) {
28398
- state.finalThinking = event.content;
28399
- }
28400
- }
28401
- handleToolStart(event, options) {
28402
- const toolCallId = event.toolCallId;
28403
- if (!toolCallId) {
28404
- return;
28405
- }
28406
- const parent = this.parentSpanForEvent(event);
28407
- const scope = scopeKey(event);
28408
- let turnState = this.turnsByScope.get(scope);
28409
- if (!turnState && parent && options.captureTurnSpans) {
28410
- turnState = this.ensureTurnState(event);
28411
- }
28412
28061
  const metadata = {
28413
28062
  ...extractEventMetadata(event),
28414
28063
  ...event.toolName ? { "flue.tool_name": event.toolName } : {},
28415
- "flue.tool_call_id": toolCallId,
28064
+ "flue.tool_call_id": event.toolCallId,
28416
28065
  provider: "flue"
28417
28066
  };
28067
+ const parent = this.parentSpanForTool(event);
28418
28068
  const span = startFlueSpan(parent, {
28419
- name: `tool: ${event.toolName ?? "unknown"}`,
28420
- spanAttributes: { type: "tool" /* TOOL */ }
28421
- });
28422
- if (turnState) {
28423
- turnState.toolCalls.push({
28424
- args: event.args,
28425
- toolCallId,
28426
- toolName: event.toolName
28427
- });
28428
- }
28429
- safeLog3(span, {
28430
- input: event.args,
28431
- metadata
28432
- });
28433
- this.toolsById.set(toolKey(event), {
28434
- metadata,
28435
- span,
28436
- startTime: getCurrentUnixTimestamp()
28069
+ name: `tool:${event.toolName ?? "unknown"}`,
28070
+ spanAttributes: { type: "tool" /* TOOL */ },
28071
+ startTime: eventTime(event.timestamp),
28072
+ event: {
28073
+ input: event.args,
28074
+ metadata
28075
+ }
28437
28076
  });
28077
+ this.toolsByKey.set(toolKey(event), { metadata, span });
28438
28078
  }
28439
28079
  handleToolCall(event) {
28080
+ if (!event.toolCallId) {
28081
+ return;
28082
+ }
28440
28083
  const key = toolKey(event);
28441
- const state = this.toolsById.get(key) ?? this.startSyntheticToolState(event, event.toolName ?? "unknown");
28084
+ const state = this.toolsByKey.get(key) ?? this.startSyntheticTool(event);
28442
28085
  const metadata = {
28443
28086
  ...state.metadata,
28444
28087
  ...extractEventMetadata(event),
28445
28088
  ...event.toolName ? { "flue.tool_name": event.toolName } : {},
28446
- ...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
28089
+ "flue.tool_call_id": event.toolCallId,
28447
28090
  ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
28448
28091
  };
28449
28092
  safeLog3(state.span, {
28450
28093
  ...event.isError ? { error: errorToString(event.result) } : {},
28451
28094
  metadata,
28452
- metrics: durationMsMetrics(event.durationMs),
28095
+ metrics: durationMetrics2(event.durationMs),
28453
28096
  output: event.result
28454
28097
  });
28455
- state.span.end();
28456
- this.toolsById.delete(key);
28098
+ safeEnd(state.span, eventTime(event.timestamp));
28099
+ this.toolsByKey.delete(key);
28457
28100
  }
28458
28101
  handleTaskStart(event) {
28459
- const parent = this.parentSpanForEvent(event);
28102
+ if (!event.taskId) {
28103
+ return;
28104
+ }
28460
28105
  const metadata = {
28461
28106
  ...extractEventMetadata(event),
28462
- ...event.role ? { "flue.role": event.role } : {},
28107
+ ...event.agent ? { "flue.agent": event.agent } : {},
28463
28108
  ...event.cwd ? { "flue.cwd": event.cwd } : {},
28464
28109
  "flue.task_id": event.taskId,
28465
28110
  provider: "flue"
28466
28111
  };
28112
+ const parent = this.parentSpanForEvent(event);
28467
28113
  const span = startFlueSpan(parent, {
28468
- name: "flue.task",
28469
- spanAttributes: { type: "task" /* TASK */ }
28470
- });
28471
- safeLog3(span, {
28472
- input: event.prompt,
28473
- metadata
28474
- });
28475
- this.tasksById.set(event.taskId, {
28476
- metadata,
28477
- span,
28478
- startTime: getCurrentUnixTimestamp()
28114
+ name: event.agent ? `task:${event.agent}` : "flue.task",
28115
+ spanAttributes: { type: "task" /* TASK */ },
28116
+ startTime: eventTime(event.timestamp),
28117
+ event: {
28118
+ input: event.prompt,
28119
+ metadata
28120
+ }
28479
28121
  });
28122
+ this.tasksById.set(event.taskId, { metadata, span });
28480
28123
  }
28481
28124
  handleTask(event) {
28482
28125
  const state = this.tasksById.get(event.taskId);
@@ -28488,426 +28131,372 @@ var FluePlugin = class extends BasePlugin {
28488
28131
  metadata: {
28489
28132
  ...state.metadata,
28490
28133
  ...extractEventMetadata(event),
28134
+ ...event.agent ? { "flue.agent": event.agent } : {},
28491
28135
  ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
28492
28136
  },
28493
- metrics: durationMsMetrics(event.durationMs),
28137
+ metrics: durationMetrics2(event.durationMs),
28494
28138
  output: event.result
28495
28139
  });
28496
- state.span.end();
28140
+ safeEnd(state.span, eventTime(event.timestamp));
28497
28141
  this.tasksById.delete(event.taskId);
28498
28142
  }
28499
28143
  handleCompactionStart(event) {
28500
- const operationState = this.operationStateForEvent(event);
28501
- const parent = operationState?.span ?? this.parentSpanForEvent(event);
28144
+ const key = compactionKey(event);
28145
+ const input = {
28146
+ ...event.estimatedTokens !== void 0 ? { estimatedTokens: event.estimatedTokens } : {},
28147
+ ...event.reason ? { reason: event.reason } : {}
28148
+ };
28502
28149
  const metadata = {
28503
28150
  ...extractEventMetadata(event),
28504
28151
  ...event.reason ? { "flue.compaction_reason": event.reason } : {},
28505
28152
  provider: "flue"
28506
28153
  };
28507
- const input = {
28508
- ...typeof event.estimatedTokens === "number" ? { estimatedTokens: event.estimatedTokens } : {},
28509
- ...event.reason ? { reason: event.reason } : {}
28510
- };
28154
+ const parent = this.parentSpanForEvent(event);
28511
28155
  const span = startFlueSpan(parent, {
28512
- name: "flue.compaction",
28513
- spanAttributes: { type: "task" /* TASK */ }
28514
- });
28515
- safeLog3(span, {
28516
- input,
28517
- metadata
28518
- });
28519
- this.compactionsByScope.set(scopeKey(event), {
28520
- input,
28521
- metadata,
28522
- operationState,
28523
- span,
28524
- startTime: getCurrentUnixTimestamp()
28156
+ name: `compaction:${event.reason ?? "unknown"}`,
28157
+ spanAttributes: { type: "task" /* TASK */ },
28158
+ startTime: eventTime(event.timestamp),
28159
+ event: {
28160
+ input,
28161
+ metadata
28162
+ }
28525
28163
  });
28164
+ this.logOperationInput(event.operationId, input);
28165
+ this.compactionsByKey.set(key, { metadata, span });
28526
28166
  }
28527
28167
  handleCompaction(event) {
28528
- const key = scopeKey(event);
28529
- const state = this.compactionsByScope.get(key) ?? this.findCompactionState(event);
28530
- if (!state) {
28531
- return;
28532
- }
28168
+ const key = compactionKey(event);
28169
+ const state = this.compactionsByKey.get(key) ?? this.startSyntheticCompaction(event);
28170
+ const metadata = {
28171
+ ...state.metadata,
28172
+ ...extractEventMetadata(event),
28173
+ ...event.usage ? { "flue.usage": event.usage } : {}
28174
+ };
28533
28175
  safeLog3(state.span, {
28534
- metadata: {
28535
- ...state.metadata,
28536
- ...extractEventMetadata(event),
28537
- ...typeof event.messagesBefore === "number" ? { "flue.messages_before": event.messagesBefore } : {},
28538
- ...typeof event.messagesAfter === "number" ? { "flue.messages_after": event.messagesAfter } : {}
28539
- },
28176
+ metadata,
28540
28177
  metrics: {
28541
- ...durationMsMetrics(event.durationMs),
28542
- ...metricsFromUsage(event.usage)
28178
+ ...durationMetrics2(event.durationMs),
28179
+ ...typeof event.messagesBefore === "number" ? { messages_before: event.messagesBefore } : {},
28180
+ ...typeof event.messagesAfter === "number" ? { messages_after: event.messagesAfter } : {}
28543
28181
  },
28544
28182
  output: {
28545
28183
  messagesAfter: event.messagesAfter,
28546
28184
  messagesBefore: event.messagesBefore
28547
28185
  }
28548
28186
  });
28549
- state.span.end();
28550
- this.deleteCompactionState(state);
28187
+ safeEnd(state.span, eventTime(event.timestamp));
28188
+ this.compactionsByKey.delete(key);
28551
28189
  }
28552
- findCompactionState(event) {
28553
- const operationState = this.operationStateForEvent(event);
28554
- for (const state of this.compactionsByScope.values()) {
28555
- if (operationState && state.operationState === operationState) {
28556
- return state;
28190
+ parentSpanForTurn(event) {
28191
+ if (event.purpose === "compaction" || event.purpose === "compaction_prefix") {
28192
+ const compaction = this.compactionsByKey.get(compactionKey(event));
28193
+ if (compaction) {
28194
+ return compaction.span;
28557
28195
  }
28558
28196
  }
28559
- return void 0;
28197
+ return this.parentSpanForEvent(event);
28560
28198
  }
28561
- finishCompactionsForOperation(operationState) {
28562
- for (const state of [...this.compactionsByScope.values()]) {
28563
- if (state.operationState !== operationState) {
28564
- continue;
28199
+ parentSpanForEvent(event) {
28200
+ const turn = turnKey(event);
28201
+ if (turn) {
28202
+ const turnState = this.turnsByKey.get(turn);
28203
+ if (turnState) {
28204
+ return turnState.span;
28565
28205
  }
28566
- safeLog3(state.span, {
28567
- input: state.input,
28568
- metadata: state.metadata,
28569
- metrics: {
28570
- ...buildDurationMetrics3(state.startTime)
28571
- },
28572
- output: { completed: true }
28573
- });
28574
- state.span.end();
28575
- this.deleteCompactionState(state);
28576
28206
  }
28577
- }
28578
- deleteCompactionState(state) {
28579
- for (const [key, candidate] of this.compactionsByScope) {
28580
- if (candidate !== state) {
28581
- continue;
28207
+ if (event.taskId) {
28208
+ const task = this.tasksById.get(event.taskId);
28209
+ if (task) {
28210
+ return task.span;
28582
28211
  }
28583
- this.compactionsByScope.delete(key);
28584
- return;
28585
28212
  }
28586
- }
28587
- startSyntheticToolState(event, toolName) {
28588
- const parent = this.parentSpanForEvent(event);
28589
- const metadata = {
28590
- ...extractEventMetadata(event),
28591
- ...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
28592
- "flue.tool_name": toolName,
28593
- provider: "flue"
28594
- };
28595
- const span = startFlueSpan(parent, {
28596
- name: `tool: ${toolName}`,
28597
- spanAttributes: { type: "tool" /* TOOL */ }
28598
- });
28599
- safeLog3(span, { metadata });
28600
- return { metadata, span, startTime: getCurrentUnixTimestamp() };
28601
- }
28602
- operationStateForEvent(event) {
28603
28213
  if (event.operationId) {
28604
- const operation = this.activeOperationsById.get(event.operationId) ?? this.promotePendingOperationForEvent(event);
28214
+ const operation = this.operationsById.get(event.operationId);
28605
28215
  if (operation) {
28606
- return operation;
28216
+ return operation.span;
28607
28217
  }
28608
28218
  }
28609
- return this.activeOperationForEventScope(event) ?? this.pendingOperationForEventScope(event);
28219
+ if (event.runId) {
28220
+ return this.runsById.get(event.runId)?.span;
28221
+ }
28222
+ return void 0;
28610
28223
  }
28611
- parentSpanForEvent(event) {
28224
+ parentSpanForTool(event) {
28225
+ if (event.taskId) {
28226
+ const task = this.tasksById.get(event.taskId);
28227
+ if (task) {
28228
+ return task.span;
28229
+ }
28230
+ }
28612
28231
  if (event.operationId) {
28613
- const operation = this.operationStateForEvent(event);
28232
+ const operation = this.operationsById.get(event.operationId);
28614
28233
  if (operation) {
28615
28234
  return operation.span;
28616
28235
  }
28617
28236
  }
28618
- if (event.taskId) {
28619
- return this.tasksById.get(event.taskId)?.span;
28237
+ if (event.runId) {
28238
+ return this.runsById.get(event.runId)?.span;
28620
28239
  }
28621
- return this.operationStateForEvent(event)?.span;
28240
+ return void 0;
28622
28241
  }
28623
- promotePendingOperationForEvent(event) {
28624
- if (!event.operationId) {
28625
- return void 0;
28242
+ logOperationInput(operationId, input) {
28243
+ if (!operationId || input === void 0) {
28244
+ return;
28626
28245
  }
28627
- const scopePrefixes = operationScopePrefixes(event);
28628
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
28629
- if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
28246
+ const operation = this.operationsById.get(operationId);
28247
+ if (!operation || operation.loggedInput) {
28248
+ return;
28249
+ }
28250
+ safeLog3(operation.span, { input });
28251
+ operation.loggedInput = true;
28252
+ }
28253
+ startSyntheticOperation(event) {
28254
+ const metadata = {
28255
+ ...extractEventMetadata(event),
28256
+ "flue.operation": event.operationKind,
28257
+ provider: "flue"
28258
+ };
28259
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
28260
+ name: `flue.${event.operationKind}`,
28261
+ spanAttributes: { type: "task" /* TASK */ },
28262
+ startTime: eventTime(event.timestamp),
28263
+ event: { metadata }
28264
+ });
28265
+ return { metadata, span };
28266
+ }
28267
+ startSyntheticTurn(event) {
28268
+ const metadata = {
28269
+ ...extractEventMetadata(event),
28270
+ ...event.api ? { "flue.api": event.api } : {},
28271
+ ...event.model ? { model: event.model, "flue.model": event.model } : {},
28272
+ ...event.provider ? { provider: event.provider } : { provider: "flue" },
28273
+ ...event.provider ? { "flue.provider": event.provider } : {},
28274
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
28275
+ };
28276
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
28277
+ name: `llm:${event.model ?? event.purpose ?? "unknown"}`,
28278
+ spanAttributes: { type: "llm" /* LLM */ },
28279
+ startTime: eventTime(event.timestamp),
28280
+ event: { metadata }
28281
+ });
28282
+ return { metadata, span };
28283
+ }
28284
+ startSyntheticTool(event) {
28285
+ const metadata = {
28286
+ ...extractEventMetadata(event),
28287
+ ...event.toolName ? { "flue.tool_name": event.toolName } : {},
28288
+ "flue.tool_call_id": event.toolCallId,
28289
+ provider: "flue"
28290
+ };
28291
+ const span = startFlueSpan(this.parentSpanForTool(event), {
28292
+ name: `tool:${event.toolName ?? "unknown"}`,
28293
+ spanAttributes: { type: "tool" /* TOOL */ },
28294
+ startTime: eventTime(event.timestamp),
28295
+ event: { metadata }
28296
+ });
28297
+ return { metadata, span };
28298
+ }
28299
+ startSyntheticCompaction(event) {
28300
+ const metadata = {
28301
+ ...extractEventMetadata(event),
28302
+ provider: "flue"
28303
+ };
28304
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
28305
+ name: "compaction:unknown",
28306
+ spanAttributes: { type: "task" /* TASK */ },
28307
+ startTime: eventTime(event.timestamp),
28308
+ event: { metadata }
28309
+ });
28310
+ return { metadata, span };
28311
+ }
28312
+ finishPendingChildrenForOperation(event, operationOutput2) {
28313
+ const endTime = eventTime(event.timestamp);
28314
+ const usage = event.usage ?? usageFromOperationResult(event.result);
28315
+ const turnEntries = [...this.turnsByKey].filter(
28316
+ ([, state]) => stateMatchesOperation(state, event.operationId)
28317
+ );
28318
+ turnEntries.forEach(([key, state], index) => {
28319
+ const shouldLogOperationOutput = (event.operationKind === "prompt" || event.operationKind === "skill") && index === turnEntries.length - 1 && operationOutput2 !== void 0;
28320
+ safeLog3(state.span, {
28321
+ metadata: state.metadata,
28322
+ metrics: metricsFromUsage(usage),
28323
+ ...shouldLogOperationOutput ? { output: operationOutput2 } : {}
28324
+ });
28325
+ safeEnd(state.span, endTime);
28326
+ this.turnsByKey.delete(key);
28327
+ });
28328
+ for (const [key, state] of this.toolsByKey) {
28329
+ if (!stateMatchesOperation(state, event.operationId)) {
28630
28330
  continue;
28631
28331
  }
28632
- const state = candidateQueue.shift();
28633
- if (!state) {
28634
- return void 0;
28332
+ safeEnd(state.span, endTime);
28333
+ this.toolsByKey.delete(key);
28334
+ }
28335
+ for (const [key, state] of this.tasksById) {
28336
+ if (!stateMatchesOperation(state, event.operationId)) {
28337
+ continue;
28635
28338
  }
28636
- state.operationId = event.operationId;
28637
- this.activeOperationsById.set(event.operationId, state);
28638
- addScopedOperation(this.activeOperationsByScope, event, state);
28639
- state.metadata = {
28640
- ...state.metadata,
28641
- ...extractEventMetadata(event),
28642
- "flue.operation_id": event.operationId
28643
- };
28644
- safeLog3(state.span, { metadata: state.metadata });
28645
- return state;
28339
+ safeEnd(state.span, endTime);
28340
+ this.tasksById.delete(key);
28646
28341
  }
28647
- return void 0;
28648
- }
28649
- activeOperationForEventScope(event) {
28650
- for (const scope of operationScopeNames(event)) {
28651
- const operations = this.activeOperationsByScope.get(scope);
28652
- if (operations?.length) {
28653
- return operations[operations.length - 1];
28342
+ for (const [key, state] of this.compactionsByKey) {
28343
+ if (!stateMatchesOperation(state, event.operationId)) {
28344
+ continue;
28654
28345
  }
28346
+ safeLog3(state.span, {
28347
+ metadata: state.metadata,
28348
+ metrics: durationMetrics2(event.durationMs),
28349
+ output: { completed: true }
28350
+ });
28351
+ safeEnd(state.span, eventTime(event.timestamp));
28352
+ this.compactionsByKey.delete(key);
28655
28353
  }
28656
- return void 0;
28657
28354
  }
28658
- pendingOperationForEventScope(event) {
28659
- const scopePrefixes = operationScopePrefixes(event);
28660
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
28661
- if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
28355
+ finishPendingSpansForRun(event) {
28356
+ const endTime = eventTime(event.timestamp);
28357
+ for (const [key, state] of this.toolsByKey) {
28358
+ if (!stateMatchesRun(state, event.runId)) {
28662
28359
  continue;
28663
28360
  }
28664
- return candidateQueue[0];
28361
+ safeEnd(state.span, endTime);
28362
+ this.toolsByKey.delete(key);
28665
28363
  }
28666
- return void 0;
28667
- }
28668
- takePendingOperationForEvent(event) {
28669
- const key = operationKey(event.session, event.operationKind);
28670
- const queue2 = this.pendingOperationsByKey.get(key);
28671
- if (queue2?.length) {
28672
- return queue2.shift();
28364
+ for (const [key, state] of this.turnsByKey) {
28365
+ if (!stateMatchesRun(state, event.runId)) {
28366
+ continue;
28367
+ }
28368
+ safeEnd(state.span, endTime);
28369
+ this.turnsByKey.delete(key);
28673
28370
  }
28674
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
28675
- if (candidateKey.endsWith(`::${event.operationKind}`) && candidateQueue.length) {
28676
- return candidateQueue.shift();
28371
+ for (const [key, state] of this.tasksById) {
28372
+ if (!stateMatchesRun(state, event.runId)) {
28373
+ continue;
28677
28374
  }
28375
+ safeEnd(state.span, endTime);
28376
+ this.tasksById.delete(key);
28678
28377
  }
28679
- return void 0;
28680
- }
28681
- pendingOperationQueue(key) {
28682
- const existing = this.pendingOperationsByKey.get(key);
28683
- if (existing) {
28684
- return existing;
28378
+ for (const [key, state] of this.compactionsByKey) {
28379
+ if (!stateMatchesRun(state, event.runId)) {
28380
+ continue;
28381
+ }
28382
+ safeLog3(state.span, {
28383
+ metadata: state.metadata,
28384
+ output: { completed: true }
28385
+ });
28386
+ safeEnd(state.span, endTime);
28387
+ this.compactionsByKey.delete(key);
28388
+ }
28389
+ for (const [key, state] of this.operationsById) {
28390
+ if (!stateMatchesRun(state, event.runId)) {
28391
+ continue;
28392
+ }
28393
+ safeLog3(state.span, {
28394
+ metadata: state.metadata,
28395
+ ...state.metadata["flue.operation"] === "compact" ? { output: { completed: true } } : {}
28396
+ });
28397
+ safeEnd(state.span, endTime);
28398
+ this.operationsById.delete(key);
28685
28399
  }
28686
- const queue2 = [];
28687
- this.pendingOperationsByKey.set(key, queue2);
28688
- return queue2;
28689
28400
  }
28690
28401
  };
28691
28402
  function isInstrumentedOperation(operation) {
28692
- return operation === "prompt" || operation === "skill" || operation === "task" || operation === "compact";
28693
- }
28694
- function getSessionName(session) {
28695
- return typeof session?.name === "string" ? session.name : void 0;
28696
- }
28697
- function operationKey(sessionName, operation) {
28698
- return `${sessionName ?? "unknown"}::${operation}`;
28699
- }
28700
- function operationScopePrefixes(event) {
28701
- const scopes = /* @__PURE__ */ new Set();
28702
- for (const scope of operationScopeNames(event)) {
28703
- scopes.add(`${scope}::`);
28704
- }
28705
- return scopes;
28706
- }
28707
- function operationKeyMatchesScopes(key, scopes) {
28708
- for (const scope of scopes) {
28709
- if (key.startsWith(scope)) {
28710
- return true;
28711
- }
28712
- }
28713
- return false;
28714
- }
28715
- function operationScopeNames(event) {
28716
- const scopes = /* @__PURE__ */ new Set();
28717
- if (event.session) {
28718
- scopes.add(event.session);
28719
- }
28720
- if (event.parentSession) {
28721
- scopes.add(event.parentSession);
28722
- }
28723
- if (!scopes.size) {
28724
- scopes.add("unknown");
28725
- }
28726
- return scopes;
28727
- }
28728
- function addScopedOperation(operationsByScope, event, state) {
28729
- for (const scope of operationScopeNames(event)) {
28730
- addOperationToScope(operationsByScope, scope, state);
28731
- }
28732
- }
28733
- function addOperationToScope(operationsByScope, scope, state) {
28734
- const operations = operationsByScope.get(scope);
28735
- if (operations) {
28736
- if (!operations.includes(state)) {
28737
- operations.push(state);
28738
- }
28739
- } else {
28740
- operationsByScope.set(scope, [state]);
28741
- }
28742
- }
28743
- function removeScopedOperation(operationsByScope, state) {
28744
- for (const [scope, operations] of operationsByScope) {
28745
- const index = operations.indexOf(state);
28746
- if (index === -1) {
28747
- continue;
28748
- }
28749
- operations.splice(index, 1);
28750
- if (operations.length === 0) {
28751
- operationsByScope.delete(scope);
28752
- }
28753
- }
28754
- }
28755
- function removePendingOperation(pendingOperationsByKey, state) {
28756
- for (const [key, queue2] of pendingOperationsByKey) {
28757
- const index = queue2.indexOf(state);
28758
- if (index === -1) {
28759
- continue;
28760
- }
28761
- queue2.splice(index, 1);
28762
- if (queue2.length === 0) {
28763
- pendingOperationsByKey.delete(key);
28764
- }
28765
- return;
28766
- }
28767
- }
28768
- function extractSessionMetadata(session) {
28769
- const sessionName = getSessionName(session);
28770
- return sessionName ? { "flue.session": sessionName } : {};
28403
+ return operation === "prompt" || operation === "skill" || operation === "compact";
28771
28404
  }
28772
- function extractEventMetadata(event) {
28405
+ function extractEventMetadata(event, ctx) {
28773
28406
  return {
28774
28407
  ...event.runId ? { "flue.run_id": event.runId } : {},
28408
+ ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
28409
+ ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
28775
28410
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
28776
28411
  ...event.session ? { "flue.session": event.session } : {},
28777
28412
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
28778
28413
  ...event.harness ? { "flue.harness": event.harness } : {},
28779
28414
  ...event.taskId ? { "flue.task_id": event.taskId } : {},
28780
- ...event.operationId ? { "flue.operation_id": event.operationId } : {}
28415
+ ...event.operationId ? { "flue.operation_id": event.operationId } : {},
28416
+ ...event.turnId ? { "flue.turn_id": event.turnId } : {},
28417
+ ...typeof ctx?.id === "string" ? { "flue.context_id": ctx.id } : {},
28418
+ ...typeof ctx?.runId === "string" ? { "flue.context_run_id": ctx.runId } : {}
28781
28419
  };
28782
28420
  }
28783
- function extractOperationInput(operation, args) {
28784
- switch (operation) {
28785
- case "prompt":
28786
- case "task":
28787
- return args[0];
28788
- case "skill":
28789
- return {
28790
- args: getOptionObject(args[1])?.args,
28791
- name: args[0]
28792
- };
28793
- case "compact":
28794
- return void 0;
28421
+ function extractPayloadMetadata(payload) {
28422
+ if (!isObjectLike(payload)) {
28423
+ return {};
28795
28424
  }
28425
+ const metadata = Reflect.get(payload, "metadata");
28426
+ if (!isObjectLike(metadata)) {
28427
+ return {};
28428
+ }
28429
+ return Object.fromEntries(Object.entries(metadata));
28796
28430
  }
28797
- function extractOperationInputMetadata(operation, args) {
28798
- const options = getOptionObject(args[1]);
28799
- return {
28800
- ...operation === "skill" && typeof args[0] === "string" ? { "flue.skill_name": args[0] } : {},
28801
- ...options?.model ? { model: options.model, "flue.model": options.model } : {},
28802
- ...options?.role ? { "flue.role": options.role } : {},
28803
- ...options?.thinkingLevel ? { "flue.thinking_level": options.thinkingLevel } : {},
28804
- ...typeof options?.cwd === "string" ? { "flue.cwd": options.cwd } : {},
28805
- ...Array.isArray(options?.tools) ? {
28806
- "flue.tools_count": options.tools.length,
28807
- tools: summarizeTools(options.tools)
28808
- } : {},
28809
- ...Array.isArray(options?.images) ? { "flue.images_count": options.images.length } : {},
28810
- ...options?.result || options?.schema ? { "flue.result_schema": true } : {}
28811
- };
28812
- }
28813
- function getOptionObject(value) {
28814
- return isObject(value) ? value : void 0;
28815
- }
28816
- function summarizeTools(tools) {
28817
- return tools.flatMap((tool) => {
28818
- if (!isObject(tool)) {
28819
- return [];
28820
- }
28821
- const name = typeof tool.name === "string" ? tool.name : void 0;
28822
- if (!name) {
28823
- return [];
28824
- }
28825
- return [
28826
- {
28827
- function: {
28828
- description: typeof tool.description === "string" ? tool.description : void 0,
28829
- name,
28830
- parameters: tool.parameters
28831
- },
28832
- type: "function"
28833
- }
28834
- ];
28835
- });
28431
+ function operationOutput(event) {
28432
+ if (event.operationKind === "prompt" || event.operationKind === "skill") {
28433
+ return llmResultFromOperationResult(event.result);
28434
+ }
28435
+ return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
28836
28436
  }
28837
- function extractPromptResponseMetadata(result) {
28838
- const modelId = result?.model && typeof result.model.id === "string" ? result.model.id : void 0;
28839
- return modelId ? {
28840
- model: modelId,
28841
- "flue.model": modelId
28842
- } : {};
28437
+ function llmResultFromOperationResult(result) {
28438
+ if (!isObjectLike(result)) {
28439
+ return result;
28440
+ }
28441
+ const text = Reflect.get(result, "text");
28442
+ return text === void 0 ? result : text;
28843
28443
  }
28844
- function extractOperationOutput(result) {
28845
- if (!result) {
28444
+ function usageFromOperationResult(result) {
28445
+ if (!isObjectLike(result)) {
28846
28446
  return void 0;
28847
28447
  }
28848
- if ("data" in result) {
28849
- return result.data;
28850
- }
28851
- if ("text" in result) {
28852
- return result.text;
28853
- }
28854
- return result;
28448
+ return Reflect.get(result, "usage");
28855
28449
  }
28856
28450
  function metricsFromUsage(usage) {
28451
+ if (!isObjectLike(usage)) {
28452
+ return {};
28453
+ }
28454
+ const cacheRead = Reflect.get(usage, "cacheRead");
28455
+ const cacheWrite = Reflect.get(usage, "cacheWrite");
28456
+ const cost = Reflect.get(usage, "cost");
28457
+ const input = Reflect.get(usage, "input");
28458
+ const output = Reflect.get(usage, "output");
28459
+ const totalTokens = Reflect.get(usage, "totalTokens");
28460
+ const totalCost = isObjectLike(cost) ? Reflect.get(cost, "total") : void 0;
28857
28461
  return {
28858
- ...typeof usage?.input === "number" ? { prompt_tokens: usage.input } : {},
28859
- ...typeof usage?.output === "number" ? { completion_tokens: usage.output } : {},
28860
- ...typeof usage?.cacheRead === "number" ? { prompt_cached_tokens: usage.cacheRead } : {},
28861
- ...typeof usage?.cacheWrite === "number" ? { prompt_cache_creation_tokens: usage.cacheWrite } : {},
28862
- ...typeof usage?.totalTokens === "number" ? { tokens: usage.totalTokens } : {},
28863
- ...typeof usage?.cost?.total === "number" ? { estimated_cost: usage.cost.total } : {}
28864
- };
28865
- }
28866
- function buildDurationMetrics3(startTime) {
28867
- return {
28868
- duration_ms: Math.max(0, (getCurrentUnixTimestamp() - startTime) * 1e3)
28462
+ ...typeof input === "number" ? { prompt_tokens: input } : {},
28463
+ ...typeof output === "number" ? { completion_tokens: output } : {},
28464
+ ...typeof cacheRead === "number" ? { prompt_cached_tokens: cacheRead } : {},
28465
+ ...typeof cacheWrite === "number" ? { prompt_cache_creation_tokens: cacheWrite } : {},
28466
+ ...typeof totalTokens === "number" ? { tokens: totalTokens } : {},
28467
+ ...typeof totalCost === "number" ? { estimated_cost: totalCost } : {}
28869
28468
  };
28870
28469
  }
28871
- function durationMsMetrics(durationMs) {
28470
+ function durationMetrics2(durationMs) {
28872
28471
  return typeof durationMs === "number" ? { duration_ms: durationMs } : {};
28873
28472
  }
28874
- function scopeKey(event) {
28875
- if (event.operationId) {
28876
- return `operation:${event.operationId}`;
28877
- }
28878
- if (event.taskId) {
28879
- return `task:${event.taskId}`;
28880
- }
28881
- if (event.session) {
28882
- return `session:${event.session}`;
28473
+ function eventTime(value) {
28474
+ if (typeof value !== "string") {
28475
+ return void 0;
28883
28476
  }
28884
- return "flue:unknown";
28477
+ const timestamp = Date.parse(value);
28478
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
28479
+ }
28480
+ function turnKey(event) {
28481
+ return event.turnId;
28885
28482
  }
28886
28483
  function toolKey(event) {
28887
- return `${scopeKey(event)}::tool:${event.toolCallId ?? "unknown"}`;
28484
+ return `${event.turnId ?? event.operationId ?? event.taskId ?? event.runId ?? "unknown"}:${event.toolCallId ?? "unknown"}`;
28888
28485
  }
28889
- function toAssistantOutput(text, finishReason, reasoning, toolCalls) {
28486
+ function compactionKey(event) {
28890
28487
  return [
28891
- {
28892
- finish_reason: finishReason ?? "stop",
28893
- index: 0,
28894
- message: {
28895
- content: text,
28896
- ...reasoning ? { reasoning } : {},
28897
- role: "assistant",
28898
- ...toolCalls?.length ? {
28899
- tool_calls: toolCalls.map((toolCall) => ({
28900
- function: {
28901
- arguments: toolCall.args === void 0 ? "{}" : JSON.stringify(toolCall.args),
28902
- name: toolCall.toolName ?? "unknown"
28903
- },
28904
- ...toolCall.toolCallId ? { id: toolCall.toolCallId } : {},
28905
- type: "function"
28906
- }))
28907
- } : {}
28908
- }
28909
- }
28910
- ];
28488
+ event.instanceId ?? "",
28489
+ event.runId ?? "",
28490
+ event.session ?? "",
28491
+ event.operationId ?? "",
28492
+ event.taskId ?? ""
28493
+ ].join(":");
28494
+ }
28495
+ function stateMatchesOperation(state, operationId) {
28496
+ return state.metadata["flue.operation_id"] === operationId;
28497
+ }
28498
+ function stateMatchesRun(state, runId) {
28499
+ return state.metadata["flue.run_id"] === runId;
28911
28500
  }
28912
28501
  function startFlueSpan(parent, args) {
28913
28502
  return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
@@ -28919,6 +28508,13 @@ function safeLog3(span, event) {
28919
28508
  logInstrumentationError3("Flue span log", error2);
28920
28509
  }
28921
28510
  }
28511
+ function safeEnd(span, endTime) {
28512
+ try {
28513
+ span.end(endTime === void 0 ? void 0 : { endTime });
28514
+ } catch (error2) {
28515
+ logInstrumentationError3("Flue span end", error2);
28516
+ }
28517
+ }
28922
28518
  function errorToString(error2) {
28923
28519
  if (error2 instanceof Error) {
28924
28520
  return error2.message;