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
@@ -4021,7 +4021,7 @@ function btStreamParser() {
4021
4021
  },
4022
4022
  async transform(chunk, controller) {
4023
4023
  if (chunk instanceof Uint8Array) {
4024
- parser.feed(decoder.decode(chunk));
4024
+ parser.feed(decoder.decode(chunk, { stream: true }));
4025
4025
  } else if (typeof chunk === "string") {
4026
4026
  parser.feed(chunk);
4027
4027
  } else {
@@ -4029,6 +4029,10 @@ function btStreamParser() {
4029
4029
  }
4030
4030
  },
4031
4031
  async flush(controller) {
4032
+ const tail = decoder.decode();
4033
+ if (tail) {
4034
+ parser.feed(tail);
4035
+ }
4032
4036
  controller.terminate();
4033
4037
  }
4034
4038
  });
@@ -23430,803 +23434,440 @@ var flueChannels = defineChannels("@flue/runtime", {
23430
23434
  createContext: channel({
23431
23435
  channelName: "createFlueContext",
23432
23436
  kind: "sync-stream"
23433
- }),
23434
- openSession: channel({
23435
- channelName: "Harness.openSession",
23436
- kind: "async"
23437
- }),
23438
- contextEvent: channel({
23439
- channelName: "context.event",
23440
- kind: "sync-stream"
23441
- }),
23442
- prompt: channel({
23443
- channelName: "session.prompt",
23444
- kind: "async"
23445
- }),
23446
- skill: channel({
23447
- channelName: "session.skill",
23448
- kind: "async"
23449
- }),
23450
- task: channel({
23451
- channelName: "session.task",
23452
- kind: "async"
23453
- }),
23454
- compact: channel({
23455
- channelName: "session.compact",
23456
- kind: "async"
23457
23437
  })
23458
23438
  });
23459
23439
 
23460
- // src/wrappers/flue.ts
23461
- var WRAPPED_FLUE_CONTEXT = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-context");
23462
- var WRAPPED_FLUE_HARNESS = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-harness");
23463
- var WRAPPED_FLUE_SESSION = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-session");
23464
- var SUBSCRIBED_FLUE_CONTEXT_EVENTS = /* @__PURE__ */ Symbol.for(
23465
- "braintrust.flue.subscribed-context-events"
23466
- );
23467
- function patchFlueContextInPlace(ctx) {
23468
- const context = ctx;
23469
- if (context[WRAPPED_FLUE_CONTEXT]) {
23470
- return ctx;
23471
- }
23472
- const originalInit = context.init.bind(context);
23473
- try {
23474
- Object.defineProperty(context, WRAPPED_FLUE_CONTEXT, {
23475
- configurable: false,
23476
- enumerable: false,
23477
- value: true
23478
- });
23479
- Object.defineProperty(context, "init", {
23480
- configurable: true,
23481
- value: async function wrappedFlueInit(options) {
23482
- const harness = await originalInit(options);
23483
- return wrapFlueHarness(harness);
23484
- },
23485
- writable: true
23486
- });
23487
- } catch {
23488
- }
23489
- return ctx;
23490
- }
23491
- function subscribeFlueContextEvents(ctx, options = {}) {
23492
- if (!ctx || typeof ctx !== "object" || typeof ctx.subscribeEvent !== "function") {
23493
- return void 0;
23440
+ // src/instrumentation/plugins/flue-plugin.ts
23441
+ var FLUE_AUTO_STATE = /* @__PURE__ */ Symbol.for("braintrust.flue.auto-state");
23442
+ var FLUE_OBSERVE_BRIDGE = /* @__PURE__ */ Symbol.for("braintrust.flue.observe-bridge");
23443
+ var braintrustFlueObserver = (event, ctx) => {
23444
+ getObserveBridge().handle(event, ctx);
23445
+ };
23446
+ var FluePlugin = class extends BasePlugin {
23447
+ onEnable() {
23448
+ this.unsubscribers.push(enableFlueAutoInstrumentation());
23494
23449
  }
23495
- const context = ctx;
23496
- const captureTurnSpans = options.captureTurnSpans ?? true;
23497
- const existingSubscription = context[SUBSCRIBED_FLUE_CONTEXT_EVENTS];
23498
- if (existingSubscription) {
23499
- if (existingSubscription.captureTurnSpans || !captureTurnSpans) {
23500
- return void 0;
23501
- }
23502
- try {
23503
- existingSubscription.unsubscribe();
23504
- } catch {
23450
+ onDisable() {
23451
+ for (const unsubscribe of this.unsubscribers) {
23452
+ unsubscribe();
23505
23453
  }
23454
+ this.unsubscribers = [];
23506
23455
  }
23507
- try {
23508
- const unsubscribe = ctx.subscribeEvent((event) => {
23509
- flueChannels.contextEvent.traceSync(() => void 0, {
23510
- arguments: [event],
23511
- captureTurnSpans,
23512
- context: ctx
23513
- });
23514
- });
23515
- if (existingSubscription) {
23516
- existingSubscription.captureTurnSpans = captureTurnSpans;
23517
- existingSubscription.unsubscribe = unsubscribe;
23518
- } else {
23519
- Object.defineProperty(context, SUBSCRIBED_FLUE_CONTEXT_EVENTS, {
23520
- configurable: false,
23521
- enumerable: false,
23522
- value: {
23523
- captureTurnSpans,
23524
- unsubscribe
23525
- }
23526
- });
23456
+ };
23457
+ function enableFlueAutoInstrumentation() {
23458
+ const state = getAutoState();
23459
+ state.refCount += 1;
23460
+ if (!state.handlers) {
23461
+ const channel2 = flueChannels.createContext.tracingChannel();
23462
+ const handlers = {
23463
+ end: (event) => {
23464
+ subscribeToFlueContext(event.result, state);
23465
+ }
23466
+ };
23467
+ channel2.subscribe(handlers);
23468
+ state.channel = channel2;
23469
+ state.handlers = handlers;
23470
+ }
23471
+ let released = false;
23472
+ return () => {
23473
+ if (released) {
23474
+ return;
23527
23475
  }
23528
- return unsubscribe;
23529
- } catch {
23530
- return void 0;
23476
+ released = true;
23477
+ releaseAutoState(state);
23478
+ };
23479
+ }
23480
+ function getAutoState() {
23481
+ const existing = Reflect.get(globalThis, FLUE_AUTO_STATE);
23482
+ if (isAutoState(existing)) {
23483
+ return existing;
23531
23484
  }
23485
+ const state = {
23486
+ contexts: /* @__PURE__ */ new WeakSet(),
23487
+ refCount: 0
23488
+ };
23489
+ Reflect.set(globalThis, FLUE_AUTO_STATE, state);
23490
+ return state;
23532
23491
  }
23533
- function wrapFlueHarness(harness) {
23534
- if (!isPlausibleFlueHarness(harness)) {
23535
- return harness;
23492
+ function getObserveBridge() {
23493
+ const existing = Reflect.get(globalThis, FLUE_OBSERVE_BRIDGE);
23494
+ if (isFlueObserveBridge(existing)) {
23495
+ return existing;
23536
23496
  }
23537
- const target = harness;
23538
- if (target[WRAPPED_FLUE_HARNESS]) {
23539
- return harness;
23497
+ const bridge = new FlueObserveBridge();
23498
+ Reflect.set(globalThis, FLUE_OBSERVE_BRIDGE, bridge);
23499
+ return bridge;
23500
+ }
23501
+ function isFlueObserveBridge(value) {
23502
+ return isObjectLike(value) && typeof Reflect.get(value, "handle") === "function" && typeof Reflect.get(value, "reset") === "function";
23503
+ }
23504
+ function isAutoState(value) {
23505
+ return isObjectLike(value) && Reflect.get(value, "contexts") instanceof WeakSet && typeof Reflect.get(value, "refCount") === "number";
23506
+ }
23507
+ function releaseAutoState(state) {
23508
+ state.refCount -= 1;
23509
+ if (state.refCount > 0) {
23510
+ return;
23540
23511
  }
23541
- const originalSession = target.session.bind(target);
23542
23512
  try {
23543
- Object.defineProperty(target, WRAPPED_FLUE_HARNESS, {
23544
- configurable: false,
23545
- enumerable: false,
23546
- value: true
23547
- });
23548
- Object.defineProperty(target, "session", {
23549
- configurable: true,
23550
- value: async function wrappedFlueHarnessSession(name, options) {
23551
- const session = await originalSession(name, options);
23552
- return patchFlueSessionInPlace(session);
23553
- },
23554
- writable: true
23555
- });
23556
- const sessions = target.sessions;
23557
- if (sessions && typeof sessions === "object") {
23558
- patchFlueSessionFactory(sessions, "get");
23559
- patchFlueSessionFactory(sessions, "create");
23513
+ if (state.channel && state.handlers) {
23514
+ state.channel.unsubscribe(state.handlers);
23560
23515
  }
23561
- } catch {
23516
+ } finally {
23517
+ Reflect.deleteProperty(globalThis, FLUE_AUTO_STATE);
23562
23518
  }
23563
- return harness;
23564
23519
  }
23565
- function patchFlueSessionInPlace(session) {
23566
- if (session[WRAPPED_FLUE_SESSION]) {
23567
- return session;
23520
+ function subscribeToFlueContext(value, state) {
23521
+ if (!isObservableFlueContext(value) || state.contexts.has(value)) {
23522
+ return;
23568
23523
  }
23524
+ const ctx = flueContextFromUnknown(value);
23525
+ let released = false;
23526
+ let unsubscribe;
23527
+ const release = () => {
23528
+ if (released) {
23529
+ return;
23530
+ }
23531
+ released = true;
23532
+ try {
23533
+ unsubscribe?.();
23534
+ } catch (error) {
23535
+ logInstrumentationError3("Flue context unsubscribe", error);
23536
+ }
23537
+ };
23569
23538
  try {
23570
- Object.defineProperty(session, WRAPPED_FLUE_SESSION, {
23571
- configurable: false,
23572
- enumerable: false,
23573
- value: true
23539
+ unsubscribe = value.subscribeEvent((event) => {
23540
+ if (state.refCount <= 0) {
23541
+ release();
23542
+ return;
23543
+ }
23544
+ braintrustFlueObserver(event, ctx);
23545
+ if (isAutoContextTerminalEvent(event, ctx)) {
23546
+ release();
23547
+ }
23574
23548
  });
23575
- patchCallHandleMethod(session, "prompt", flueChannels.prompt);
23576
- patchCallHandleMethod(session, "skill", flueChannels.skill);
23577
- patchCallHandleMethod(session, "task", flueChannels.task);
23578
- patchCompact(session);
23579
- } catch {
23549
+ state.contexts.add(value);
23550
+ } catch (error) {
23551
+ logInstrumentationError3("Flue context subscription", error);
23580
23552
  }
23581
- return session;
23582
23553
  }
23583
- function patchFlueSessionFactory(sessions, method) {
23584
- const original = sessions[method];
23585
- if (typeof original !== "function") {
23586
- return;
23554
+ function isAutoContextTerminalEvent(event, ctx) {
23555
+ if (!isObjectLike(event)) {
23556
+ return false;
23587
23557
  }
23588
- const bound = original.bind(sessions);
23589
- Object.defineProperty(sessions, method, {
23590
- configurable: true,
23591
- value: async function wrappedFlueSessionFactory(name, options) {
23592
- const session = await bound(name, options);
23593
- return patchFlueSessionInPlace(session);
23594
- },
23595
- writable: true
23596
- });
23597
- }
23598
- function patchCallHandleMethod(session, method, channel2) {
23599
- const original = session[method];
23600
- if (typeof original !== "function") {
23601
- return;
23558
+ const type = Reflect.get(event, "type");
23559
+ if (type === "run_end") {
23560
+ return true;
23602
23561
  }
23603
- const bound = original.bind(session);
23604
- Object.defineProperty(session, method, {
23605
- configurable: true,
23606
- value(input, options) {
23607
- const args = [input, options];
23608
- const { originalResult, traced: traced2 } = traceFlueOperation(channel2, {
23609
- context: {
23610
- arguments: args,
23611
- operation: method,
23612
- session
23613
- },
23614
- run: () => bound(input, options)
23615
- });
23616
- return preserveCallHandle(originalResult, traced2);
23617
- },
23618
- writable: true
23619
- });
23620
- }
23621
- function patchCompact(session) {
23622
- const original = session.compact;
23623
- if (typeof original !== "function") {
23624
- return;
23562
+ if (type !== "operation") {
23563
+ return false;
23625
23564
  }
23626
- const bound = original.bind(session);
23627
- Object.defineProperty(session, "compact", {
23628
- configurable: true,
23629
- value() {
23630
- const context = {
23631
- arguments: [],
23632
- operation: "compact",
23633
- session
23634
- };
23635
- return flueChannels.compact.tracePromise(() => bound(), context);
23636
- },
23637
- writable: true
23638
- });
23565
+ return !ctx?.runId && typeof Reflect.get(event, "runId") !== "string";
23639
23566
  }
23640
- function traceFlueOperation(channel2, args) {
23641
- const tracingChannel2 = channel2.tracingChannel();
23642
- const context = args.context;
23643
- let originalResult;
23644
- let traced2;
23645
- const run = () => {
23646
- try {
23647
- originalResult = args.run();
23648
- tracingChannel2.end?.publish(context);
23649
- } catch (error) {
23650
- context.error = normalizeError3(error);
23651
- tracingChannel2.error?.publish(context);
23652
- tracingChannel2.end?.publish(context);
23653
- throw error;
23654
- }
23655
- traced2 = Promise.resolve(originalResult).then(
23656
- (result) => {
23657
- context.result = result;
23658
- tracingChannel2.asyncStart?.publish(context);
23659
- tracingChannel2.asyncEnd?.publish(context);
23660
- return result;
23661
- },
23662
- (error) => {
23663
- context.error = normalizeError3(error);
23664
- tracingChannel2.error?.publish(context);
23665
- tracingChannel2.asyncStart?.publish(context);
23666
- tracingChannel2.asyncEnd?.publish(context);
23667
- throw error;
23668
- }
23669
- );
23670
- };
23671
- if (tracingChannel2.start?.runStores) {
23672
- tracingChannel2.start.runStores(context, run);
23673
- } else {
23674
- tracingChannel2.start?.publish(context);
23675
- run();
23676
- }
23677
- return { originalResult, traced: traced2 };
23567
+ function isObservableFlueContext(value) {
23568
+ return isObjectLike(value) && typeof Reflect.get(value, "subscribeEvent") === "function";
23678
23569
  }
23679
- function normalizeError3(error) {
23680
- return error instanceof Error ? error : new Error(String(error));
23570
+ function isFlueEvent(event) {
23571
+ const type = Reflect.get(event, "type");
23572
+ 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";
23681
23573
  }
23682
- function preserveCallHandle(originalHandle, traced2) {
23683
- if (!isFlueCallHandle(originalHandle)) {
23684
- return traced2;
23574
+ function flueContextFromUnknown(ctx) {
23575
+ if (!isObjectLike(ctx)) {
23576
+ return void 0;
23685
23577
  }
23686
- const handle = originalHandle;
23687
- const wrapped = {
23688
- get signal() {
23689
- return handle.signal;
23690
- },
23691
- abort(reason) {
23692
- return handle.abort(reason);
23693
- },
23694
- then(onfulfilled, onrejected) {
23695
- return traced2.then(onfulfilled, onrejected);
23696
- }
23578
+ const id = Reflect.get(ctx, "id");
23579
+ const runId = Reflect.get(ctx, "runId");
23580
+ return {
23581
+ ...typeof id === "string" ? { id } : {},
23582
+ ...typeof runId === "string" ? { runId } : {}
23697
23583
  };
23698
- return wrapped;
23699
- }
23700
- function isPlausibleFlueHarness(value) {
23701
- return !!value && typeof value === "object" && typeof value.session === "function";
23702
23584
  }
23703
- function isFlueCallHandle(value) {
23704
- return !!value && typeof value === "object" && typeof value.then === "function" && typeof value.abort === "function" && "signal" in value;
23585
+ function isObjectLike(value) {
23586
+ return typeof value === "object" && value !== null && !Array.isArray(value);
23705
23587
  }
23706
-
23707
- // src/instrumentation/plugins/flue-plugin.ts
23708
- var FluePlugin = class extends BasePlugin {
23709
- activeOperationsById = /* @__PURE__ */ new Map();
23710
- activeOperationsByScope = /* @__PURE__ */ new Map();
23711
- compactionsByScope = /* @__PURE__ */ new Map();
23712
- pendingOperationsByKey = /* @__PURE__ */ new Map();
23588
+ var FlueObserveBridge = class {
23589
+ compactionsByKey = /* @__PURE__ */ new Map();
23590
+ operationsById = /* @__PURE__ */ new Map();
23591
+ runsById = /* @__PURE__ */ new Map();
23592
+ seenEvents = /* @__PURE__ */ new WeakSet();
23713
23593
  tasksById = /* @__PURE__ */ new Map();
23714
- toolsById = /* @__PURE__ */ new Map();
23715
- turnsByScope = /* @__PURE__ */ new Map();
23716
- onEnable() {
23717
- this.subscribeToContextCreation();
23718
- this.subscribeToSessionCreation();
23719
- this.subscribeToContextEvents();
23720
- this.subscribeToSessionOperations();
23721
- }
23722
- onDisable() {
23723
- for (const unsubscribe of this.unsubscribers) {
23724
- unsubscribe();
23594
+ toolsByKey = /* @__PURE__ */ new Map();
23595
+ turnsByKey = /* @__PURE__ */ new Map();
23596
+ handle(event, ctx) {
23597
+ if (!isObjectLike(event) || !isFlueEvent(event)) {
23598
+ return;
23725
23599
  }
23726
- this.unsubscribers = [];
23727
- this.activeOperationsById.clear();
23728
- this.activeOperationsByScope.clear();
23729
- this.compactionsByScope.clear();
23730
- this.pendingOperationsByKey.clear();
23600
+ if (this.seenEvents.has(event)) {
23601
+ return;
23602
+ }
23603
+ this.seenEvents.add(event);
23604
+ try {
23605
+ this.handleEvent(event, flueContextFromUnknown(ctx));
23606
+ } catch (error) {
23607
+ logInstrumentationError3("Flue observe", error);
23608
+ }
23609
+ }
23610
+ reset() {
23611
+ this.compactionsByKey.clear();
23612
+ this.operationsById.clear();
23613
+ this.runsById.clear();
23614
+ this.seenEvents = /* @__PURE__ */ new WeakSet();
23731
23615
  this.tasksById.clear();
23732
- this.toolsById.clear();
23733
- this.turnsByScope.clear();
23616
+ this.toolsByKey.clear();
23617
+ this.turnsByKey.clear();
23734
23618
  }
23735
- subscribeToContextCreation() {
23736
- const channel2 = flueChannels.createContext.tracingChannel();
23737
- const handlers = {
23738
- end: (event) => {
23739
- const ctx = event.result;
23740
- if (!ctx) {
23741
- return;
23742
- }
23743
- subscribeFlueContextEvents(ctx, { captureTurnSpans: false });
23744
- patchFlueContextInPlace(ctx);
23745
- },
23746
- error: () => {
23747
- }
23748
- };
23749
- channel2.subscribe(handlers);
23750
- this.unsubscribers.push(() => {
23751
- channel2.unsubscribe(handlers);
23752
- });
23619
+ handleEvent(event, ctx) {
23620
+ switch (event.type) {
23621
+ case "run_start":
23622
+ this.handleRunStart(event, ctx);
23623
+ return;
23624
+ case "run_end":
23625
+ this.handleRunEnd(event);
23626
+ return;
23627
+ case "operation_start":
23628
+ this.handleOperationStart(event);
23629
+ return;
23630
+ case "operation":
23631
+ this.handleOperation(event);
23632
+ return;
23633
+ case "turn_request":
23634
+ this.handleTurnRequest(event);
23635
+ return;
23636
+ case "turn":
23637
+ this.handleTurn(event);
23638
+ return;
23639
+ case "tool_start":
23640
+ this.handleToolStart(event);
23641
+ return;
23642
+ case "tool_call":
23643
+ this.handleToolCall(event);
23644
+ return;
23645
+ case "task_start":
23646
+ this.handleTaskStart(event);
23647
+ return;
23648
+ case "task":
23649
+ this.handleTask(event);
23650
+ return;
23651
+ case "compaction_start":
23652
+ this.handleCompactionStart(event);
23653
+ return;
23654
+ case "compaction":
23655
+ this.handleCompaction(event);
23656
+ return;
23657
+ default:
23658
+ return;
23659
+ }
23753
23660
  }
23754
- subscribeToSessionCreation() {
23755
- const channel2 = flueChannels.openSession.tracingChannel();
23756
- const handlers = {
23757
- asyncEnd: (event) => {
23758
- if (event.result) {
23759
- patchFlueSessionInPlace(
23760
- event.result
23761
- );
23762
- }
23763
- if (event.harness) {
23764
- wrapFlueHarness(event.harness);
23765
- }
23766
- },
23767
- error: () => {
23768
- }
23661
+ handleRunStart(event, ctx) {
23662
+ if (!event.runId) {
23663
+ return;
23664
+ }
23665
+ const workflowName = event.workflowName ?? event.owner?.workflowName ?? (typeof ctx?.id === "string" ? ctx.id : "unknown");
23666
+ const metadata = {
23667
+ ...extractPayloadMetadata(event.payload),
23668
+ ...extractEventMetadata(event, ctx),
23669
+ ...workflowName ? { "flue.workflow_name": workflowName } : {},
23670
+ provider: "flue"
23769
23671
  };
23770
- channel2.subscribe(handlers);
23771
- this.unsubscribers.push(() => {
23772
- channel2.unsubscribe(handlers);
23672
+ const span = startSpan({
23673
+ name: `workflow:${workflowName}`,
23674
+ spanAttributes: { type: "task" /* TASK */ },
23675
+ startTime: eventTime(event.startedAt ?? event.timestamp),
23676
+ event: {
23677
+ input: event.payload,
23678
+ metadata
23679
+ }
23773
23680
  });
23681
+ this.runsById.set(event.runId, { metadata, span });
23774
23682
  }
23775
- subscribeToSessionOperations() {
23776
- this.subscribeToSessionOperation(flueChannels.prompt);
23777
- this.subscribeToSessionOperation(flueChannels.skill);
23778
- this.subscribeToSessionOperation(flueChannels.task);
23779
- this.subscribeToCompact();
23780
- }
23781
- subscribeToSessionOperation(channel2) {
23782
- const tracingChannel2 = channel2.tracingChannel();
23783
- const states = /* @__PURE__ */ new WeakMap();
23784
- const ensureState2 = (event) => {
23785
- const existing = states.get(event);
23786
- if (existing) {
23787
- return existing;
23788
- }
23789
- const state = this.startOperationState({
23790
- args: event.arguments,
23791
- moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
23792
- operation: event.operation,
23793
- session: event.session
23683
+ handleRunEnd(event) {
23684
+ const state = this.runsById.get(event.runId);
23685
+ this.finishPendingSpansForRun(event);
23686
+ if (state) {
23687
+ safeLog3(state.span, {
23688
+ ...event.isError ? { error: errorToString(event.error) } : {},
23689
+ metadata: {
23690
+ ...state.metadata,
23691
+ ...extractEventMetadata(event),
23692
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
23693
+ },
23694
+ metrics: durationMetrics2(event.durationMs),
23695
+ output: event.result
23794
23696
  });
23795
- states.set(event, state);
23796
- return state;
23797
- };
23798
- const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
23799
- tracingChannel2,
23800
- ensureState2
23801
- );
23802
- const handlers = {
23803
- start: (event) => {
23804
- ensureState2(event);
23805
- },
23806
- asyncEnd: (event) => {
23807
- this.endOperationState(states.get(event), event.result);
23808
- states.delete(event);
23809
- },
23810
- error: (event) => {
23811
- const state = states.get(event);
23812
- if (state && event.error) {
23813
- safeLog3(state.span, { error: errorToString(event.error) });
23814
- this.finishOperationState(state);
23815
- }
23816
- states.delete(event);
23817
- }
23818
- };
23819
- tracingChannel2.subscribe(handlers);
23820
- this.unsubscribers.push(() => {
23821
- unbindCurrentSpanStore?.();
23822
- tracingChannel2.unsubscribe(handlers);
23697
+ safeEnd(state.span, eventTime(event.timestamp));
23698
+ this.runsById.delete(event.runId);
23699
+ }
23700
+ void flush().catch((error) => {
23701
+ logInstrumentationError3("Flue flush", error);
23823
23702
  });
23824
23703
  }
23825
- subscribeToCompact() {
23826
- const tracingChannel2 = flueChannels.compact.tracingChannel();
23827
- const states = /* @__PURE__ */ new WeakMap();
23828
- const ensureState2 = (event) => {
23829
- const existing = states.get(event);
23830
- if (existing) {
23831
- return existing;
23832
- }
23833
- const state = this.startOperationState({
23834
- args: [],
23835
- moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
23836
- operation: event.operation,
23837
- session: event.session
23838
- });
23839
- states.set(event, state);
23840
- return state;
23841
- };
23842
- const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
23843
- tracingChannel2,
23844
- ensureState2
23845
- );
23846
- const handlers = {
23847
- start: (event) => {
23848
- ensureState2(event);
23849
- },
23850
- asyncEnd: (event) => {
23851
- this.endOperationState(states.get(event), void 0);
23852
- states.delete(event);
23853
- },
23854
- error: (event) => {
23855
- const state = states.get(event);
23856
- if (state && event.error) {
23857
- safeLog3(state.span, { error: errorToString(event.error) });
23858
- this.finishOperationState(state);
23859
- }
23860
- states.delete(event);
23861
- }
23862
- };
23863
- tracingChannel2.subscribe(handlers);
23864
- this.unsubscribers.push(() => {
23865
- unbindCurrentSpanStore?.();
23866
- tracingChannel2.unsubscribe(handlers);
23867
- });
23868
- }
23869
- subscribeToContextEvents() {
23870
- const channel2 = flueChannels.contextEvent.tracingChannel();
23871
- const handlers = {
23872
- start: (event) => {
23873
- const flueEvent = event.arguments[0];
23874
- if (!flueEvent) {
23875
- return;
23876
- }
23877
- try {
23878
- this.handleFlueEvent(flueEvent, {
23879
- captureTurnSpans: event.captureTurnSpans !== false
23880
- });
23881
- } catch (error) {
23882
- logInstrumentationError3("Flue event", error);
23883
- }
23884
- },
23885
- error: () => {
23886
- }
23887
- };
23888
- channel2.subscribe(handlers);
23889
- this.unsubscribers.push(() => {
23890
- channel2.unsubscribe(handlers);
23891
- });
23892
- }
23893
- bindCurrentSpanStoreToOperationStart(tracingChannel2, ensureState2) {
23894
- const state = _internalGetGlobalState();
23895
- const startChannel = tracingChannel2.start;
23896
- const contextManager = state?.contextManager;
23897
- const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
23898
- if (!currentSpanStore || !startChannel) {
23899
- return void 0;
23900
- }
23901
- startChannel.bindStore(currentSpanStore, (event) => {
23902
- const operationState = ensureState2(event);
23903
- return contextManager.wrapSpanForStore(operationState.span);
23904
- });
23905
- return () => {
23906
- startChannel.unbindStore(currentSpanStore);
23907
- };
23908
- }
23909
- startOperationState(args) {
23910
- const sessionName = getSessionName(args.session);
23911
- const metadata = {
23912
- ...extractOperationInputMetadata(args.operation, args.args),
23913
- ...extractSessionMetadata(args.session),
23914
- "flue.operation": args.operation,
23915
- provider: "flue",
23916
- ...args.moduleVersion ? { "flue.version": args.moduleVersion } : {}
23917
- };
23918
- const span = startSpan({
23919
- name: `flue.session.${args.operation}`,
23920
- spanAttributes: { type: "task" /* TASK */ }
23921
- });
23922
- const state = {
23923
- metadata,
23924
- operation: args.operation,
23925
- sessionName,
23926
- span,
23927
- startTime: getCurrentUnixTimestamp()
23928
- };
23929
- safeLog3(span, {
23930
- input: extractOperationInput(args.operation, args.args),
23931
- metadata
23932
- });
23933
- this.pendingOperationQueue(operationKey(sessionName, args.operation)).push(
23934
- state
23935
- );
23936
- addOperationToScope(
23937
- this.activeOperationsByScope,
23938
- sessionName ?? "unknown",
23939
- state
23940
- );
23941
- return state;
23942
- }
23943
- endOperationState(state, result) {
23944
- if (!state) {
23945
- return;
23946
- }
23947
- const metadata = {
23948
- ...state.metadata,
23949
- ...extractPromptResponseMetadata(result)
23950
- };
23951
- const metrics = {
23952
- ...buildDurationMetrics3(state.startTime),
23953
- ...metricsFromUsage(result?.usage)
23954
- };
23955
- safeLog3(state.span, {
23956
- metadata,
23957
- metrics,
23958
- output: extractOperationOutput(result)
23959
- });
23960
- this.finishCompactionsForOperation(state);
23961
- this.finishOperationState(state);
23962
- }
23963
- finishOperationState(state) {
23964
- removePendingOperation(this.pendingOperationsByKey, state);
23965
- if (state.operationId) {
23966
- this.activeOperationsById.delete(state.operationId);
23967
- }
23968
- removeScopedOperation(this.activeOperationsByScope, state);
23969
- state.span.end();
23970
- }
23971
- handleFlueEvent(event, options) {
23972
- switch (event.type) {
23973
- case "operation_start":
23974
- this.handleOperationStart(event);
23975
- return;
23976
- case "operation":
23977
- this.handleOperation(event);
23978
- return;
23979
- case "text_delta":
23980
- if (!options.captureTurnSpans) {
23981
- return;
23982
- }
23983
- this.ensureTurnState(event).text.push(
23984
- typeof event.text === "string" ? event.text : ""
23985
- );
23986
- return;
23987
- case "thinking_start":
23988
- if (!options.captureTurnSpans) {
23989
- return;
23990
- }
23991
- this.handleThinkingStart(event);
23992
- return;
23993
- case "thinking_delta":
23994
- if (!options.captureTurnSpans) {
23995
- return;
23996
- }
23997
- this.handleThinkingDelta(event);
23998
- return;
23999
- case "thinking_end":
24000
- if (!options.captureTurnSpans) {
24001
- return;
24002
- }
24003
- this.handleThinkingEnd(event);
24004
- return;
24005
- case "turn":
24006
- if (!options.captureTurnSpans) {
24007
- return;
24008
- }
24009
- this.handleTurn(event);
24010
- return;
24011
- case "tool_start":
24012
- this.handleToolStart(event, options);
24013
- return;
24014
- case "tool_call":
24015
- this.handleToolCall(event);
24016
- return;
24017
- case "task_start":
24018
- this.handleTaskStart(event);
24019
- return;
24020
- case "task":
24021
- this.handleTask(event);
24022
- return;
24023
- case "compaction_start":
24024
- this.handleCompactionStart(event);
24025
- return;
24026
- case "compaction":
24027
- this.handleCompaction(event);
24028
- return;
24029
- default:
24030
- return;
24031
- }
24032
- }
24033
23704
  handleOperationStart(event) {
24034
- if (!isInstrumentedOperation(event.operationKind)) {
23705
+ if (!event.operationId || !isInstrumentedOperation(event.operationKind)) {
24035
23706
  return;
24036
23707
  }
24037
- const state = this.takePendingOperationForEvent(event);
24038
- if (!state) {
24039
- return;
24040
- }
24041
- state.operationId = event.operationId;
24042
- this.activeOperationsById.set(event.operationId, state);
24043
- addScopedOperation(this.activeOperationsByScope, event, state);
24044
- state.metadata = {
24045
- ...state.metadata,
23708
+ const metadata = {
24046
23709
  ...extractEventMetadata(event),
24047
- "flue.operation_id": event.operationId
23710
+ "flue.operation": event.operationKind,
23711
+ provider: "flue"
24048
23712
  };
24049
- safeLog3(state.span, { metadata: state.metadata });
23713
+ const parent = this.parentSpanForEvent(event);
23714
+ const span = startFlueSpan(parent, {
23715
+ name: `flue.${event.operationKind}`,
23716
+ spanAttributes: { type: "task" /* TASK */ },
23717
+ startTime: eventTime(event.timestamp),
23718
+ event: { metadata }
23719
+ });
23720
+ this.operationsById.set(event.operationId, { metadata, span });
24050
23721
  }
24051
23722
  handleOperation(event) {
24052
- const state = event.operationId ? this.activeOperationsById.get(event.operationId) : void 0;
24053
- if (!state) {
23723
+ if (!isInstrumentedOperation(event.operationKind)) {
24054
23724
  return;
24055
23725
  }
23726
+ const state = this.operationsById.get(event.operationId) ?? this.startSyntheticOperation(event);
23727
+ const output = operationOutput(event);
24056
23728
  const metadata = {
24057
23729
  ...state.metadata,
24058
23730
  ...extractEventMetadata(event),
24059
- ...typeof event.durationMs === "number" ? { "flue.duration_ms": event.durationMs } : {},
24060
- ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
23731
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
23732
+ ...event.usage ? { "flue.usage": event.usage } : {}
24061
23733
  };
24062
- const metrics = metricsFromUsage(event.usage);
23734
+ this.finishPendingChildrenForOperation(event, output);
24063
23735
  safeLog3(state.span, {
24064
- ...event.error ? { error: errorToString(event.error) } : {},
23736
+ ...event.isError ? { error: errorToString(event.error) } : {},
24065
23737
  metadata,
24066
- ...Object.keys(metrics).length ? { metrics } : {}
23738
+ metrics: durationMetrics2(event.durationMs),
23739
+ output
24067
23740
  });
23741
+ safeEnd(state.span, eventTime(event.timestamp));
23742
+ this.operationsById.delete(event.operationId);
24068
23743
  }
24069
- ensureTurnState(event) {
24070
- const scope = scopeKey(event);
24071
- const existing = this.turnsByScope.get(scope);
24072
- if (existing) {
24073
- return existing;
23744
+ handleTurnRequest(event) {
23745
+ const key = turnKey(event);
23746
+ if (!key) {
23747
+ return;
24074
23748
  }
24075
- const parent = this.parentSpanForEvent(event);
24076
23749
  const metadata = {
24077
23750
  ...extractEventMetadata(event),
24078
- provider: "flue"
23751
+ ...event.api ? { "flue.api": event.api } : {},
23752
+ ...event.model ? { model: event.model, "flue.model": event.model } : {},
23753
+ ...event.provider ? { provider: event.provider } : { provider: "flue" },
23754
+ ...event.provider ? { "flue.provider": event.provider } : {},
23755
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
23756
+ ...event.reasoning ? { reasoning: event.reasoning } : {},
23757
+ ...event.input?.systemPrompt ? { "flue.system_prompt": event.input.systemPrompt } : {},
23758
+ ...event.input?.tools ? { tools: event.input.tools } : {}
24079
23759
  };
23760
+ const parent = this.parentSpanForTurn(event);
24080
23761
  const span = startFlueSpan(parent, {
24081
- name: "flue.turn",
24082
- spanAttributes: { type: "llm" /* LLM */ }
23762
+ name: `llm:${event.model ?? event.purpose ?? "unknown"}`,
23763
+ spanAttributes: { type: "llm" /* LLM */ },
23764
+ startTime: eventTime(event.timestamp),
23765
+ event: {
23766
+ input: event.input?.messages,
23767
+ metadata
23768
+ }
24083
23769
  });
24084
- const state = {
24085
- metadata,
24086
- span,
24087
- hasThinking: false,
24088
- startTime: getCurrentUnixTimestamp(),
24089
- text: [],
24090
- thinking: [],
24091
- toolCalls: []
24092
- };
24093
- safeLog3(span, { metadata });
24094
- this.turnsByScope.set(scope, state);
24095
- return state;
23770
+ this.logOperationInput(
23771
+ event.operationId,
23772
+ event.input?.messages ?? event.input
23773
+ );
23774
+ this.turnsByKey.set(key, { metadata, span });
24096
23775
  }
24097
23776
  handleTurn(event) {
24098
- const scope = scopeKey(event);
24099
- const state = this.ensureTurnState(event);
24100
- const text = state.text.join("");
24101
- const reasoning = state.finalThinking ?? state.thinking.join("");
24102
- const outputReasoning = reasoning || (state.hasThinking ? "[reasoning stream present; content unavailable]" : void 0);
23777
+ const key = turnKey(event);
23778
+ if (!key) {
23779
+ return;
23780
+ }
23781
+ const state = this.turnsByKey.get(key) ?? this.startSyntheticTurn(event);
24103
23782
  const metadata = {
24104
23783
  ...state.metadata,
24105
23784
  ...extractEventMetadata(event),
23785
+ ...event.api ? { "flue.api": event.api } : {},
24106
23786
  ...event.model ? { model: event.model, "flue.model": event.model } : {},
23787
+ ...event.provider ? { provider: event.provider } : {},
23788
+ ...event.provider ? { "flue.provider": event.provider } : {},
23789
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
24107
23790
  ...event.stopReason ? { "flue.stop_reason": event.stopReason } : {},
24108
- ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
24109
- provider: "flue"
23791
+ ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24110
23792
  };
24111
23793
  safeLog3(state.span, {
24112
- ...event.error ? { error: errorToString(event.error) } : {},
23794
+ ...event.isError ? { error: errorToString(event.error) } : {},
24113
23795
  metadata,
24114
23796
  metrics: {
24115
- ...durationMsMetrics(event.durationMs),
23797
+ ...durationMetrics2(event.durationMs),
24116
23798
  ...metricsFromUsage(event.usage)
24117
23799
  },
24118
- output: toAssistantOutput(
24119
- text,
24120
- event.stopReason,
24121
- outputReasoning,
24122
- state.toolCalls
24123
- )
23800
+ output: event.output
24124
23801
  });
24125
- state.span.end();
24126
- this.turnsByScope.delete(scope);
24127
- }
24128
- handleThinkingDelta(event) {
24129
- const delta = event.delta;
24130
- if (typeof delta !== "string" || !delta) {
24131
- return;
24132
- }
24133
- const state = this.ensureTurnState(event);
24134
- state.hasThinking = true;
24135
- state.metadata["flue.thinking"] = true;
24136
- state.thinking.push(delta);
24137
- }
24138
- handleThinkingStart(event) {
24139
- const state = this.ensureTurnState(event);
24140
- state.hasThinking = true;
24141
- state.metadata["flue.thinking"] = true;
24142
- }
24143
- handleThinkingEnd(event) {
24144
- const state = this.ensureTurnState(event);
24145
- state.hasThinking = true;
24146
- state.metadata["flue.thinking"] = true;
24147
- if (typeof event.content === "string" && event.content) {
24148
- state.finalThinking = event.content;
24149
- }
23802
+ safeEnd(state.span, eventTime(event.timestamp));
23803
+ this.turnsByKey.delete(key);
24150
23804
  }
24151
- handleToolStart(event, options) {
24152
- const toolCallId = event.toolCallId;
24153
- if (!toolCallId) {
23805
+ handleToolStart(event) {
23806
+ if (!event.toolCallId) {
24154
23807
  return;
24155
23808
  }
24156
- const parent = this.parentSpanForEvent(event);
24157
- const scope = scopeKey(event);
24158
- let turnState = this.turnsByScope.get(scope);
24159
- if (!turnState && parent && options.captureTurnSpans) {
24160
- turnState = this.ensureTurnState(event);
24161
- }
24162
23809
  const metadata = {
24163
23810
  ...extractEventMetadata(event),
24164
23811
  ...event.toolName ? { "flue.tool_name": event.toolName } : {},
24165
- "flue.tool_call_id": toolCallId,
23812
+ "flue.tool_call_id": event.toolCallId,
24166
23813
  provider: "flue"
24167
23814
  };
23815
+ const parent = this.parentSpanForTool(event);
24168
23816
  const span = startFlueSpan(parent, {
24169
- name: `tool: ${event.toolName ?? "unknown"}`,
24170
- spanAttributes: { type: "tool" /* TOOL */ }
24171
- });
24172
- if (turnState) {
24173
- turnState.toolCalls.push({
24174
- args: event.args,
24175
- toolCallId,
24176
- toolName: event.toolName
24177
- });
24178
- }
24179
- safeLog3(span, {
24180
- input: event.args,
24181
- metadata
24182
- });
24183
- this.toolsById.set(toolKey(event), {
24184
- metadata,
24185
- span,
24186
- startTime: getCurrentUnixTimestamp()
23817
+ name: `tool:${event.toolName ?? "unknown"}`,
23818
+ spanAttributes: { type: "tool" /* TOOL */ },
23819
+ startTime: eventTime(event.timestamp),
23820
+ event: {
23821
+ input: event.args,
23822
+ metadata
23823
+ }
24187
23824
  });
23825
+ this.toolsByKey.set(toolKey(event), { metadata, span });
24188
23826
  }
24189
23827
  handleToolCall(event) {
23828
+ if (!event.toolCallId) {
23829
+ return;
23830
+ }
24190
23831
  const key = toolKey(event);
24191
- const state = this.toolsById.get(key) ?? this.startSyntheticToolState(event, event.toolName ?? "unknown");
23832
+ const state = this.toolsByKey.get(key) ?? this.startSyntheticTool(event);
24192
23833
  const metadata = {
24193
23834
  ...state.metadata,
24194
23835
  ...extractEventMetadata(event),
24195
23836
  ...event.toolName ? { "flue.tool_name": event.toolName } : {},
24196
- ...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
23837
+ "flue.tool_call_id": event.toolCallId,
24197
23838
  ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24198
23839
  };
24199
23840
  safeLog3(state.span, {
24200
23841
  ...event.isError ? { error: errorToString(event.result) } : {},
24201
23842
  metadata,
24202
- metrics: durationMsMetrics(event.durationMs),
23843
+ metrics: durationMetrics2(event.durationMs),
24203
23844
  output: event.result
24204
23845
  });
24205
- state.span.end();
24206
- this.toolsById.delete(key);
23846
+ safeEnd(state.span, eventTime(event.timestamp));
23847
+ this.toolsByKey.delete(key);
24207
23848
  }
24208
23849
  handleTaskStart(event) {
24209
- const parent = this.parentSpanForEvent(event);
23850
+ if (!event.taskId) {
23851
+ return;
23852
+ }
24210
23853
  const metadata = {
24211
23854
  ...extractEventMetadata(event),
24212
- ...event.role ? { "flue.role": event.role } : {},
23855
+ ...event.agent ? { "flue.agent": event.agent } : {},
24213
23856
  ...event.cwd ? { "flue.cwd": event.cwd } : {},
24214
23857
  "flue.task_id": event.taskId,
24215
23858
  provider: "flue"
24216
23859
  };
23860
+ const parent = this.parentSpanForEvent(event);
24217
23861
  const span = startFlueSpan(parent, {
24218
- name: "flue.task",
24219
- spanAttributes: { type: "task" /* TASK */ }
24220
- });
24221
- safeLog3(span, {
24222
- input: event.prompt,
24223
- metadata
24224
- });
24225
- this.tasksById.set(event.taskId, {
24226
- metadata,
24227
- span,
24228
- startTime: getCurrentUnixTimestamp()
23862
+ name: event.agent ? `task:${event.agent}` : "flue.task",
23863
+ spanAttributes: { type: "task" /* TASK */ },
23864
+ startTime: eventTime(event.timestamp),
23865
+ event: {
23866
+ input: event.prompt,
23867
+ metadata
23868
+ }
24229
23869
  });
23870
+ this.tasksById.set(event.taskId, { metadata, span });
24230
23871
  }
24231
23872
  handleTask(event) {
24232
23873
  const state = this.tasksById.get(event.taskId);
@@ -24238,426 +23879,372 @@ var FluePlugin = class extends BasePlugin {
24238
23879
  metadata: {
24239
23880
  ...state.metadata,
24240
23881
  ...extractEventMetadata(event),
23882
+ ...event.agent ? { "flue.agent": event.agent } : {},
24241
23883
  ...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
24242
23884
  },
24243
- metrics: durationMsMetrics(event.durationMs),
23885
+ metrics: durationMetrics2(event.durationMs),
24244
23886
  output: event.result
24245
23887
  });
24246
- state.span.end();
23888
+ safeEnd(state.span, eventTime(event.timestamp));
24247
23889
  this.tasksById.delete(event.taskId);
24248
23890
  }
24249
23891
  handleCompactionStart(event) {
24250
- const operationState = this.operationStateForEvent(event);
24251
- const parent = operationState?.span ?? this.parentSpanForEvent(event);
23892
+ const key = compactionKey(event);
23893
+ const input = {
23894
+ ...event.estimatedTokens !== void 0 ? { estimatedTokens: event.estimatedTokens } : {},
23895
+ ...event.reason ? { reason: event.reason } : {}
23896
+ };
24252
23897
  const metadata = {
24253
23898
  ...extractEventMetadata(event),
24254
23899
  ...event.reason ? { "flue.compaction_reason": event.reason } : {},
24255
23900
  provider: "flue"
24256
23901
  };
24257
- const input = {
24258
- ...typeof event.estimatedTokens === "number" ? { estimatedTokens: event.estimatedTokens } : {},
24259
- ...event.reason ? { reason: event.reason } : {}
24260
- };
23902
+ const parent = this.parentSpanForEvent(event);
24261
23903
  const span = startFlueSpan(parent, {
24262
- name: "flue.compaction",
24263
- spanAttributes: { type: "task" /* TASK */ }
24264
- });
24265
- safeLog3(span, {
24266
- input,
24267
- metadata
24268
- });
24269
- this.compactionsByScope.set(scopeKey(event), {
24270
- input,
24271
- metadata,
24272
- operationState,
24273
- span,
24274
- startTime: getCurrentUnixTimestamp()
23904
+ name: `compaction:${event.reason ?? "unknown"}`,
23905
+ spanAttributes: { type: "task" /* TASK */ },
23906
+ startTime: eventTime(event.timestamp),
23907
+ event: {
23908
+ input,
23909
+ metadata
23910
+ }
24275
23911
  });
23912
+ this.logOperationInput(event.operationId, input);
23913
+ this.compactionsByKey.set(key, { metadata, span });
24276
23914
  }
24277
23915
  handleCompaction(event) {
24278
- const key = scopeKey(event);
24279
- const state = this.compactionsByScope.get(key) ?? this.findCompactionState(event);
24280
- if (!state) {
24281
- return;
24282
- }
23916
+ const key = compactionKey(event);
23917
+ const state = this.compactionsByKey.get(key) ?? this.startSyntheticCompaction(event);
23918
+ const metadata = {
23919
+ ...state.metadata,
23920
+ ...extractEventMetadata(event),
23921
+ ...event.usage ? { "flue.usage": event.usage } : {}
23922
+ };
24283
23923
  safeLog3(state.span, {
24284
- metadata: {
24285
- ...state.metadata,
24286
- ...extractEventMetadata(event),
24287
- ...typeof event.messagesBefore === "number" ? { "flue.messages_before": event.messagesBefore } : {},
24288
- ...typeof event.messagesAfter === "number" ? { "flue.messages_after": event.messagesAfter } : {}
24289
- },
23924
+ metadata,
24290
23925
  metrics: {
24291
- ...durationMsMetrics(event.durationMs),
24292
- ...metricsFromUsage(event.usage)
23926
+ ...durationMetrics2(event.durationMs),
23927
+ ...typeof event.messagesBefore === "number" ? { messages_before: event.messagesBefore } : {},
23928
+ ...typeof event.messagesAfter === "number" ? { messages_after: event.messagesAfter } : {}
24293
23929
  },
24294
23930
  output: {
24295
23931
  messagesAfter: event.messagesAfter,
24296
23932
  messagesBefore: event.messagesBefore
24297
23933
  }
24298
23934
  });
24299
- state.span.end();
24300
- this.deleteCompactionState(state);
23935
+ safeEnd(state.span, eventTime(event.timestamp));
23936
+ this.compactionsByKey.delete(key);
24301
23937
  }
24302
- findCompactionState(event) {
24303
- const operationState = this.operationStateForEvent(event);
24304
- for (const state of this.compactionsByScope.values()) {
24305
- if (operationState && state.operationState === operationState) {
24306
- return state;
23938
+ parentSpanForTurn(event) {
23939
+ if (event.purpose === "compaction" || event.purpose === "compaction_prefix") {
23940
+ const compaction = this.compactionsByKey.get(compactionKey(event));
23941
+ if (compaction) {
23942
+ return compaction.span;
24307
23943
  }
24308
23944
  }
24309
- return void 0;
23945
+ return this.parentSpanForEvent(event);
24310
23946
  }
24311
- finishCompactionsForOperation(operationState) {
24312
- for (const state of [...this.compactionsByScope.values()]) {
24313
- if (state.operationState !== operationState) {
24314
- continue;
23947
+ parentSpanForEvent(event) {
23948
+ const turn = turnKey(event);
23949
+ if (turn) {
23950
+ const turnState = this.turnsByKey.get(turn);
23951
+ if (turnState) {
23952
+ return turnState.span;
24315
23953
  }
24316
- safeLog3(state.span, {
24317
- input: state.input,
24318
- metadata: state.metadata,
24319
- metrics: {
24320
- ...buildDurationMetrics3(state.startTime)
24321
- },
24322
- output: { completed: true }
24323
- });
24324
- state.span.end();
24325
- this.deleteCompactionState(state);
24326
23954
  }
24327
- }
24328
- deleteCompactionState(state) {
24329
- for (const [key, candidate] of this.compactionsByScope) {
24330
- if (candidate !== state) {
24331
- continue;
23955
+ if (event.taskId) {
23956
+ const task = this.tasksById.get(event.taskId);
23957
+ if (task) {
23958
+ return task.span;
24332
23959
  }
24333
- this.compactionsByScope.delete(key);
24334
- return;
24335
23960
  }
24336
- }
24337
- startSyntheticToolState(event, toolName) {
24338
- const parent = this.parentSpanForEvent(event);
24339
- const metadata = {
24340
- ...extractEventMetadata(event),
24341
- ...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
24342
- "flue.tool_name": toolName,
24343
- provider: "flue"
24344
- };
24345
- const span = startFlueSpan(parent, {
24346
- name: `tool: ${toolName}`,
24347
- spanAttributes: { type: "tool" /* TOOL */ }
24348
- });
24349
- safeLog3(span, { metadata });
24350
- return { metadata, span, startTime: getCurrentUnixTimestamp() };
24351
- }
24352
- operationStateForEvent(event) {
24353
23961
  if (event.operationId) {
24354
- const operation = this.activeOperationsById.get(event.operationId) ?? this.promotePendingOperationForEvent(event);
23962
+ const operation = this.operationsById.get(event.operationId);
24355
23963
  if (operation) {
24356
- return operation;
23964
+ return operation.span;
24357
23965
  }
24358
23966
  }
24359
- return this.activeOperationForEventScope(event) ?? this.pendingOperationForEventScope(event);
23967
+ if (event.runId) {
23968
+ return this.runsById.get(event.runId)?.span;
23969
+ }
23970
+ return void 0;
24360
23971
  }
24361
- parentSpanForEvent(event) {
23972
+ parentSpanForTool(event) {
23973
+ if (event.taskId) {
23974
+ const task = this.tasksById.get(event.taskId);
23975
+ if (task) {
23976
+ return task.span;
23977
+ }
23978
+ }
24362
23979
  if (event.operationId) {
24363
- const operation = this.operationStateForEvent(event);
23980
+ const operation = this.operationsById.get(event.operationId);
24364
23981
  if (operation) {
24365
23982
  return operation.span;
24366
23983
  }
24367
23984
  }
24368
- if (event.taskId) {
24369
- return this.tasksById.get(event.taskId)?.span;
23985
+ if (event.runId) {
23986
+ return this.runsById.get(event.runId)?.span;
24370
23987
  }
24371
- return this.operationStateForEvent(event)?.span;
23988
+ return void 0;
24372
23989
  }
24373
- promotePendingOperationForEvent(event) {
24374
- if (!event.operationId) {
24375
- return void 0;
23990
+ logOperationInput(operationId, input) {
23991
+ if (!operationId || input === void 0) {
23992
+ return;
24376
23993
  }
24377
- const scopePrefixes = operationScopePrefixes(event);
24378
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
24379
- if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
23994
+ const operation = this.operationsById.get(operationId);
23995
+ if (!operation || operation.loggedInput) {
23996
+ return;
23997
+ }
23998
+ safeLog3(operation.span, { input });
23999
+ operation.loggedInput = true;
24000
+ }
24001
+ startSyntheticOperation(event) {
24002
+ const metadata = {
24003
+ ...extractEventMetadata(event),
24004
+ "flue.operation": event.operationKind,
24005
+ provider: "flue"
24006
+ };
24007
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
24008
+ name: `flue.${event.operationKind}`,
24009
+ spanAttributes: { type: "task" /* TASK */ },
24010
+ startTime: eventTime(event.timestamp),
24011
+ event: { metadata }
24012
+ });
24013
+ return { metadata, span };
24014
+ }
24015
+ startSyntheticTurn(event) {
24016
+ const metadata = {
24017
+ ...extractEventMetadata(event),
24018
+ ...event.api ? { "flue.api": event.api } : {},
24019
+ ...event.model ? { model: event.model, "flue.model": event.model } : {},
24020
+ ...event.provider ? { provider: event.provider } : { provider: "flue" },
24021
+ ...event.provider ? { "flue.provider": event.provider } : {},
24022
+ ...event.purpose ? { "flue.turn_purpose": event.purpose } : {}
24023
+ };
24024
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
24025
+ name: `llm:${event.model ?? event.purpose ?? "unknown"}`,
24026
+ spanAttributes: { type: "llm" /* LLM */ },
24027
+ startTime: eventTime(event.timestamp),
24028
+ event: { metadata }
24029
+ });
24030
+ return { metadata, span };
24031
+ }
24032
+ startSyntheticTool(event) {
24033
+ const metadata = {
24034
+ ...extractEventMetadata(event),
24035
+ ...event.toolName ? { "flue.tool_name": event.toolName } : {},
24036
+ "flue.tool_call_id": event.toolCallId,
24037
+ provider: "flue"
24038
+ };
24039
+ const span = startFlueSpan(this.parentSpanForTool(event), {
24040
+ name: `tool:${event.toolName ?? "unknown"}`,
24041
+ spanAttributes: { type: "tool" /* TOOL */ },
24042
+ startTime: eventTime(event.timestamp),
24043
+ event: { metadata }
24044
+ });
24045
+ return { metadata, span };
24046
+ }
24047
+ startSyntheticCompaction(event) {
24048
+ const metadata = {
24049
+ ...extractEventMetadata(event),
24050
+ provider: "flue"
24051
+ };
24052
+ const span = startFlueSpan(this.parentSpanForEvent(event), {
24053
+ name: "compaction:unknown",
24054
+ spanAttributes: { type: "task" /* TASK */ },
24055
+ startTime: eventTime(event.timestamp),
24056
+ event: { metadata }
24057
+ });
24058
+ return { metadata, span };
24059
+ }
24060
+ finishPendingChildrenForOperation(event, operationOutput2) {
24061
+ const endTime = eventTime(event.timestamp);
24062
+ const usage = event.usage ?? usageFromOperationResult(event.result);
24063
+ const turnEntries = [...this.turnsByKey].filter(
24064
+ ([, state]) => stateMatchesOperation(state, event.operationId)
24065
+ );
24066
+ turnEntries.forEach(([key, state], index) => {
24067
+ const shouldLogOperationOutput = (event.operationKind === "prompt" || event.operationKind === "skill") && index === turnEntries.length - 1 && operationOutput2 !== void 0;
24068
+ safeLog3(state.span, {
24069
+ metadata: state.metadata,
24070
+ metrics: metricsFromUsage(usage),
24071
+ ...shouldLogOperationOutput ? { output: operationOutput2 } : {}
24072
+ });
24073
+ safeEnd(state.span, endTime);
24074
+ this.turnsByKey.delete(key);
24075
+ });
24076
+ for (const [key, state] of this.toolsByKey) {
24077
+ if (!stateMatchesOperation(state, event.operationId)) {
24380
24078
  continue;
24381
24079
  }
24382
- const state = candidateQueue.shift();
24383
- if (!state) {
24384
- return void 0;
24080
+ safeEnd(state.span, endTime);
24081
+ this.toolsByKey.delete(key);
24082
+ }
24083
+ for (const [key, state] of this.tasksById) {
24084
+ if (!stateMatchesOperation(state, event.operationId)) {
24085
+ continue;
24385
24086
  }
24386
- state.operationId = event.operationId;
24387
- this.activeOperationsById.set(event.operationId, state);
24388
- addScopedOperation(this.activeOperationsByScope, event, state);
24389
- state.metadata = {
24390
- ...state.metadata,
24391
- ...extractEventMetadata(event),
24392
- "flue.operation_id": event.operationId
24393
- };
24394
- safeLog3(state.span, { metadata: state.metadata });
24395
- return state;
24087
+ safeEnd(state.span, endTime);
24088
+ this.tasksById.delete(key);
24396
24089
  }
24397
- return void 0;
24398
- }
24399
- activeOperationForEventScope(event) {
24400
- for (const scope of operationScopeNames(event)) {
24401
- const operations = this.activeOperationsByScope.get(scope);
24402
- if (operations?.length) {
24403
- return operations[operations.length - 1];
24090
+ for (const [key, state] of this.compactionsByKey) {
24091
+ if (!stateMatchesOperation(state, event.operationId)) {
24092
+ continue;
24404
24093
  }
24094
+ safeLog3(state.span, {
24095
+ metadata: state.metadata,
24096
+ metrics: durationMetrics2(event.durationMs),
24097
+ output: { completed: true }
24098
+ });
24099
+ safeEnd(state.span, eventTime(event.timestamp));
24100
+ this.compactionsByKey.delete(key);
24405
24101
  }
24406
- return void 0;
24407
24102
  }
24408
- pendingOperationForEventScope(event) {
24409
- const scopePrefixes = operationScopePrefixes(event);
24410
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
24411
- if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
24103
+ finishPendingSpansForRun(event) {
24104
+ const endTime = eventTime(event.timestamp);
24105
+ for (const [key, state] of this.toolsByKey) {
24106
+ if (!stateMatchesRun(state, event.runId)) {
24412
24107
  continue;
24413
24108
  }
24414
- return candidateQueue[0];
24109
+ safeEnd(state.span, endTime);
24110
+ this.toolsByKey.delete(key);
24415
24111
  }
24416
- return void 0;
24417
- }
24418
- takePendingOperationForEvent(event) {
24419
- const key = operationKey(event.session, event.operationKind);
24420
- const queue2 = this.pendingOperationsByKey.get(key);
24421
- if (queue2?.length) {
24422
- return queue2.shift();
24112
+ for (const [key, state] of this.turnsByKey) {
24113
+ if (!stateMatchesRun(state, event.runId)) {
24114
+ continue;
24115
+ }
24116
+ safeEnd(state.span, endTime);
24117
+ this.turnsByKey.delete(key);
24423
24118
  }
24424
- for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
24425
- if (candidateKey.endsWith(`::${event.operationKind}`) && candidateQueue.length) {
24426
- return candidateQueue.shift();
24119
+ for (const [key, state] of this.tasksById) {
24120
+ if (!stateMatchesRun(state, event.runId)) {
24121
+ continue;
24427
24122
  }
24123
+ safeEnd(state.span, endTime);
24124
+ this.tasksById.delete(key);
24428
24125
  }
24429
- return void 0;
24430
- }
24431
- pendingOperationQueue(key) {
24432
- const existing = this.pendingOperationsByKey.get(key);
24433
- if (existing) {
24434
- return existing;
24126
+ for (const [key, state] of this.compactionsByKey) {
24127
+ if (!stateMatchesRun(state, event.runId)) {
24128
+ continue;
24129
+ }
24130
+ safeLog3(state.span, {
24131
+ metadata: state.metadata,
24132
+ output: { completed: true }
24133
+ });
24134
+ safeEnd(state.span, endTime);
24135
+ this.compactionsByKey.delete(key);
24136
+ }
24137
+ for (const [key, state] of this.operationsById) {
24138
+ if (!stateMatchesRun(state, event.runId)) {
24139
+ continue;
24140
+ }
24141
+ safeLog3(state.span, {
24142
+ metadata: state.metadata,
24143
+ ...state.metadata["flue.operation"] === "compact" ? { output: { completed: true } } : {}
24144
+ });
24145
+ safeEnd(state.span, endTime);
24146
+ this.operationsById.delete(key);
24435
24147
  }
24436
- const queue2 = [];
24437
- this.pendingOperationsByKey.set(key, queue2);
24438
- return queue2;
24439
24148
  }
24440
24149
  };
24441
24150
  function isInstrumentedOperation(operation) {
24442
- return operation === "prompt" || operation === "skill" || operation === "task" || operation === "compact";
24443
- }
24444
- function getSessionName(session) {
24445
- return typeof session?.name === "string" ? session.name : void 0;
24151
+ return operation === "prompt" || operation === "skill" || operation === "compact";
24446
24152
  }
24447
- function operationKey(sessionName, operation) {
24448
- return `${sessionName ?? "unknown"}::${operation}`;
24449
- }
24450
- function operationScopePrefixes(event) {
24451
- const scopes = /* @__PURE__ */ new Set();
24452
- for (const scope of operationScopeNames(event)) {
24453
- scopes.add(`${scope}::`);
24454
- }
24455
- return scopes;
24456
- }
24457
- function operationKeyMatchesScopes(key, scopes) {
24458
- for (const scope of scopes) {
24459
- if (key.startsWith(scope)) {
24460
- return true;
24461
- }
24462
- }
24463
- return false;
24464
- }
24465
- function operationScopeNames(event) {
24466
- const scopes = /* @__PURE__ */ new Set();
24467
- if (event.session) {
24468
- scopes.add(event.session);
24469
- }
24470
- if (event.parentSession) {
24471
- scopes.add(event.parentSession);
24472
- }
24473
- if (!scopes.size) {
24474
- scopes.add("unknown");
24475
- }
24476
- return scopes;
24477
- }
24478
- function addScopedOperation(operationsByScope, event, state) {
24479
- for (const scope of operationScopeNames(event)) {
24480
- addOperationToScope(operationsByScope, scope, state);
24481
- }
24482
- }
24483
- function addOperationToScope(operationsByScope, scope, state) {
24484
- const operations = operationsByScope.get(scope);
24485
- if (operations) {
24486
- if (!operations.includes(state)) {
24487
- operations.push(state);
24488
- }
24489
- } else {
24490
- operationsByScope.set(scope, [state]);
24491
- }
24492
- }
24493
- function removeScopedOperation(operationsByScope, state) {
24494
- for (const [scope, operations] of operationsByScope) {
24495
- const index = operations.indexOf(state);
24496
- if (index === -1) {
24497
- continue;
24498
- }
24499
- operations.splice(index, 1);
24500
- if (operations.length === 0) {
24501
- operationsByScope.delete(scope);
24502
- }
24503
- }
24504
- }
24505
- function removePendingOperation(pendingOperationsByKey, state) {
24506
- for (const [key, queue2] of pendingOperationsByKey) {
24507
- const index = queue2.indexOf(state);
24508
- if (index === -1) {
24509
- continue;
24510
- }
24511
- queue2.splice(index, 1);
24512
- if (queue2.length === 0) {
24513
- pendingOperationsByKey.delete(key);
24514
- }
24515
- return;
24516
- }
24517
- }
24518
- function extractSessionMetadata(session) {
24519
- const sessionName = getSessionName(session);
24520
- return sessionName ? { "flue.session": sessionName } : {};
24521
- }
24522
- function extractEventMetadata(event) {
24153
+ function extractEventMetadata(event, ctx) {
24523
24154
  return {
24524
24155
  ...event.runId ? { "flue.run_id": event.runId } : {},
24156
+ ...event.instanceId ? { "flue.instance_id": event.instanceId } : {},
24157
+ ...event.dispatchId ? { "flue.dispatch_id": event.dispatchId } : {},
24525
24158
  ...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
24526
24159
  ...event.session ? { "flue.session": event.session } : {},
24527
24160
  ...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
24528
24161
  ...event.harness ? { "flue.harness": event.harness } : {},
24529
24162
  ...event.taskId ? { "flue.task_id": event.taskId } : {},
24530
- ...event.operationId ? { "flue.operation_id": event.operationId } : {}
24163
+ ...event.operationId ? { "flue.operation_id": event.operationId } : {},
24164
+ ...event.turnId ? { "flue.turn_id": event.turnId } : {},
24165
+ ...typeof ctx?.id === "string" ? { "flue.context_id": ctx.id } : {},
24166
+ ...typeof ctx?.runId === "string" ? { "flue.context_run_id": ctx.runId } : {}
24531
24167
  };
24532
24168
  }
24533
- function extractOperationInput(operation, args) {
24534
- switch (operation) {
24535
- case "prompt":
24536
- case "task":
24537
- return args[0];
24538
- case "skill":
24539
- return {
24540
- args: getOptionObject(args[1])?.args,
24541
- name: args[0]
24542
- };
24543
- case "compact":
24544
- return void 0;
24169
+ function extractPayloadMetadata(payload) {
24170
+ if (!isObjectLike(payload)) {
24171
+ return {};
24545
24172
  }
24173
+ const metadata = Reflect.get(payload, "metadata");
24174
+ if (!isObjectLike(metadata)) {
24175
+ return {};
24176
+ }
24177
+ return Object.fromEntries(Object.entries(metadata));
24546
24178
  }
24547
- function extractOperationInputMetadata(operation, args) {
24548
- const options = getOptionObject(args[1]);
24549
- return {
24550
- ...operation === "skill" && typeof args[0] === "string" ? { "flue.skill_name": args[0] } : {},
24551
- ...options?.model ? { model: options.model, "flue.model": options.model } : {},
24552
- ...options?.role ? { "flue.role": options.role } : {},
24553
- ...options?.thinkingLevel ? { "flue.thinking_level": options.thinkingLevel } : {},
24554
- ...typeof options?.cwd === "string" ? { "flue.cwd": options.cwd } : {},
24555
- ...Array.isArray(options?.tools) ? {
24556
- "flue.tools_count": options.tools.length,
24557
- tools: summarizeTools(options.tools)
24558
- } : {},
24559
- ...Array.isArray(options?.images) ? { "flue.images_count": options.images.length } : {},
24560
- ...options?.result || options?.schema ? { "flue.result_schema": true } : {}
24561
- };
24562
- }
24563
- function getOptionObject(value) {
24564
- return isObject(value) ? value : void 0;
24565
- }
24566
- function summarizeTools(tools) {
24567
- return tools.flatMap((tool) => {
24568
- if (!isObject(tool)) {
24569
- return [];
24570
- }
24571
- const name = typeof tool.name === "string" ? tool.name : void 0;
24572
- if (!name) {
24573
- return [];
24574
- }
24575
- return [
24576
- {
24577
- function: {
24578
- description: typeof tool.description === "string" ? tool.description : void 0,
24579
- name,
24580
- parameters: tool.parameters
24581
- },
24582
- type: "function"
24583
- }
24584
- ];
24585
- });
24179
+ function operationOutput(event) {
24180
+ if (event.operationKind === "prompt" || event.operationKind === "skill") {
24181
+ return llmResultFromOperationResult(event.result);
24182
+ }
24183
+ return event.result ?? (event.operationKind === "compact" ? { completed: true } : void 0);
24586
24184
  }
24587
- function extractPromptResponseMetadata(result) {
24588
- const modelId = result?.model && typeof result.model.id === "string" ? result.model.id : void 0;
24589
- return modelId ? {
24590
- model: modelId,
24591
- "flue.model": modelId
24592
- } : {};
24185
+ function llmResultFromOperationResult(result) {
24186
+ if (!isObjectLike(result)) {
24187
+ return result;
24188
+ }
24189
+ const text = Reflect.get(result, "text");
24190
+ return text === void 0 ? result : text;
24593
24191
  }
24594
- function extractOperationOutput(result) {
24595
- if (!result) {
24192
+ function usageFromOperationResult(result) {
24193
+ if (!isObjectLike(result)) {
24596
24194
  return void 0;
24597
24195
  }
24598
- if ("data" in result) {
24599
- return result.data;
24600
- }
24601
- if ("text" in result) {
24602
- return result.text;
24603
- }
24604
- return result;
24196
+ return Reflect.get(result, "usage");
24605
24197
  }
24606
24198
  function metricsFromUsage(usage) {
24199
+ if (!isObjectLike(usage)) {
24200
+ return {};
24201
+ }
24202
+ const cacheRead = Reflect.get(usage, "cacheRead");
24203
+ const cacheWrite = Reflect.get(usage, "cacheWrite");
24204
+ const cost = Reflect.get(usage, "cost");
24205
+ const input = Reflect.get(usage, "input");
24206
+ const output = Reflect.get(usage, "output");
24207
+ const totalTokens = Reflect.get(usage, "totalTokens");
24208
+ const totalCost = isObjectLike(cost) ? Reflect.get(cost, "total") : void 0;
24607
24209
  return {
24608
- ...typeof usage?.input === "number" ? { prompt_tokens: usage.input } : {},
24609
- ...typeof usage?.output === "number" ? { completion_tokens: usage.output } : {},
24610
- ...typeof usage?.cacheRead === "number" ? { prompt_cached_tokens: usage.cacheRead } : {},
24611
- ...typeof usage?.cacheWrite === "number" ? { prompt_cache_creation_tokens: usage.cacheWrite } : {},
24612
- ...typeof usage?.totalTokens === "number" ? { tokens: usage.totalTokens } : {},
24613
- ...typeof usage?.cost?.total === "number" ? { estimated_cost: usage.cost.total } : {}
24614
- };
24615
- }
24616
- function buildDurationMetrics3(startTime) {
24617
- return {
24618
- duration_ms: Math.max(0, (getCurrentUnixTimestamp() - startTime) * 1e3)
24210
+ ...typeof input === "number" ? { prompt_tokens: input } : {},
24211
+ ...typeof output === "number" ? { completion_tokens: output } : {},
24212
+ ...typeof cacheRead === "number" ? { prompt_cached_tokens: cacheRead } : {},
24213
+ ...typeof cacheWrite === "number" ? { prompt_cache_creation_tokens: cacheWrite } : {},
24214
+ ...typeof totalTokens === "number" ? { tokens: totalTokens } : {},
24215
+ ...typeof totalCost === "number" ? { estimated_cost: totalCost } : {}
24619
24216
  };
24620
24217
  }
24621
- function durationMsMetrics(durationMs) {
24218
+ function durationMetrics2(durationMs) {
24622
24219
  return typeof durationMs === "number" ? { duration_ms: durationMs } : {};
24623
24220
  }
24624
- function scopeKey(event) {
24625
- if (event.operationId) {
24626
- return `operation:${event.operationId}`;
24627
- }
24628
- if (event.taskId) {
24629
- return `task:${event.taskId}`;
24630
- }
24631
- if (event.session) {
24632
- return `session:${event.session}`;
24221
+ function eventTime(value) {
24222
+ if (typeof value !== "string") {
24223
+ return void 0;
24633
24224
  }
24634
- return "flue:unknown";
24225
+ const timestamp = Date.parse(value);
24226
+ return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
24227
+ }
24228
+ function turnKey(event) {
24229
+ return event.turnId;
24635
24230
  }
24636
24231
  function toolKey(event) {
24637
- return `${scopeKey(event)}::tool:${event.toolCallId ?? "unknown"}`;
24232
+ return `${event.turnId ?? event.operationId ?? event.taskId ?? event.runId ?? "unknown"}:${event.toolCallId ?? "unknown"}`;
24638
24233
  }
24639
- function toAssistantOutput(text, finishReason, reasoning, toolCalls) {
24234
+ function compactionKey(event) {
24640
24235
  return [
24641
- {
24642
- finish_reason: finishReason ?? "stop",
24643
- index: 0,
24644
- message: {
24645
- content: text,
24646
- ...reasoning ? { reasoning } : {},
24647
- role: "assistant",
24648
- ...toolCalls?.length ? {
24649
- tool_calls: toolCalls.map((toolCall) => ({
24650
- function: {
24651
- arguments: toolCall.args === void 0 ? "{}" : JSON.stringify(toolCall.args),
24652
- name: toolCall.toolName ?? "unknown"
24653
- },
24654
- ...toolCall.toolCallId ? { id: toolCall.toolCallId } : {},
24655
- type: "function"
24656
- }))
24657
- } : {}
24658
- }
24659
- }
24660
- ];
24236
+ event.instanceId ?? "",
24237
+ event.runId ?? "",
24238
+ event.session ?? "",
24239
+ event.operationId ?? "",
24240
+ event.taskId ?? ""
24241
+ ].join(":");
24242
+ }
24243
+ function stateMatchesOperation(state, operationId) {
24244
+ return state.metadata["flue.operation_id"] === operationId;
24245
+ }
24246
+ function stateMatchesRun(state, runId) {
24247
+ return state.metadata["flue.run_id"] === runId;
24661
24248
  }
24662
24249
  function startFlueSpan(parent, args) {
24663
24250
  return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
@@ -24669,6 +24256,13 @@ function safeLog3(span, event) {
24669
24256
  logInstrumentationError3("Flue span log", error);
24670
24257
  }
24671
24258
  }
24259
+ function safeEnd(span, endTime) {
24260
+ try {
24261
+ span.end(endTime === void 0 ? void 0 : { endTime });
24262
+ } catch (error) {
24263
+ logInstrumentationError3("Flue span end", error);
24264
+ }
24265
+ }
24672
24266
  function errorToString(error) {
24673
24267
  if (error instanceof Error) {
24674
24268
  return error.message;
@@ -26913,6 +26507,7 @@ async function invoke(args) {
26913
26507
  mode,
26914
26508
  schema,
26915
26509
  strict,
26510
+ overrides,
26916
26511
  projectId,
26917
26512
  ...functionIdArgs
26918
26513
  } = args;
@@ -26949,7 +26544,8 @@ async function invoke(args) {
26949
26544
  tags,
26950
26545
  stream,
26951
26546
  mode,
26952
- strict
26547
+ strict,
26548
+ overrides
26953
26549
  };
26954
26550
  const headers = {
26955
26551
  Accept: stream ? "text/event-stream" : "application/json"