braintrust 2.2.1-rc.0 → 2.2.1

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.
package/dist/browser.mjs CHANGED
@@ -1928,7 +1928,8 @@ var SpanType = z6.union([
1928
1928
  "automation",
1929
1929
  "facet",
1930
1930
  "preprocessor",
1931
- "classifier"
1931
+ "classifier",
1932
+ "review"
1932
1933
  ]),
1933
1934
  z6.null()
1934
1935
  ]);
@@ -12695,14 +12696,17 @@ function parseToolName(rawToolName) {
12695
12696
  rawToolName
12696
12697
  };
12697
12698
  }
12698
- function createToolTracingHooks(parentSpanExportPromise, activeToolSpans, mcpServers) {
12699
+ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, subAgentSpans, endedSubAgentSpans) {
12699
12700
  const preToolUse = async (input, toolUseID) => {
12700
12701
  if (input.hook_event_name !== "PreToolUse" || !toolUseID) {
12701
12702
  return {};
12702
12703
  }
12704
+ if (input.tool_name === "Task") {
12705
+ return {};
12706
+ }
12703
12707
  const parsed = parseToolName(input.tool_name);
12704
12708
  const mcpMetadata = getMcpServerMetadata(parsed.mcpServer, mcpServers);
12705
- const parentExport = await parentSpanExportPromise;
12709
+ const parentExport = await resolveParentSpan(toolUseID);
12706
12710
  const toolSpan = startSpan({
12707
12711
  name: parsed.displayName,
12708
12712
  spanAttributes: { type: "tool" /* TOOL */ },
@@ -12730,6 +12734,30 @@ function createToolTracingHooks(parentSpanExportPromise, activeToolSpans, mcpSer
12730
12734
  if (input.hook_event_name !== "PostToolUse" || !toolUseID) {
12731
12735
  return {};
12732
12736
  }
12737
+ const subAgentSpan = subAgentSpans.get(toolUseID);
12738
+ if (subAgentSpan) {
12739
+ try {
12740
+ const response = input.tool_response;
12741
+ const metadata = {};
12742
+ if (response?.status) {
12743
+ metadata["claude_agent_sdk.status"] = response.status;
12744
+ }
12745
+ if (response?.totalDurationMs) {
12746
+ metadata["claude_agent_sdk.duration_ms"] = response.totalDurationMs;
12747
+ }
12748
+ if (response?.totalToolUseCount !== void 0) {
12749
+ metadata["claude_agent_sdk.tool_use_count"] = response.totalToolUseCount;
12750
+ }
12751
+ subAgentSpan.log({
12752
+ output: response?.content,
12753
+ metadata
12754
+ });
12755
+ } finally {
12756
+ subAgentSpan.end();
12757
+ endedSubAgentSpans.add(toolUseID);
12758
+ }
12759
+ return {};
12760
+ }
12733
12761
  const toolSpan = activeToolSpans.get(toolUseID);
12734
12762
  if (!toolSpan) {
12735
12763
  return {};
@@ -12746,6 +12774,16 @@ function createToolTracingHooks(parentSpanExportPromise, activeToolSpans, mcpSer
12746
12774
  if (input.hook_event_name !== "PostToolUseFailure" || !toolUseID) {
12747
12775
  return {};
12748
12776
  }
12777
+ const subAgentSpan = subAgentSpans.get(toolUseID);
12778
+ if (subAgentSpan) {
12779
+ try {
12780
+ subAgentSpan.log({ error: input.error });
12781
+ } finally {
12782
+ subAgentSpan.end();
12783
+ endedSubAgentSpans.add(toolUseID);
12784
+ }
12785
+ return {};
12786
+ }
12749
12787
  const toolSpan = activeToolSpans.get(toolUseID);
12750
12788
  if (!toolSpan) {
12751
12789
  return {};
@@ -12770,12 +12808,14 @@ function createToolTracingHooks(parentSpanExportPromise, activeToolSpans, mcpSer
12770
12808
  };
12771
12809
  return { preToolUse, postToolUse, postToolUseFailure };
12772
12810
  }
12773
- function injectTracingHooks(options, parentSpanExportPromise, activeToolSpans) {
12811
+ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, subAgentSpans, endedSubAgentSpans) {
12774
12812
  const mcpServers = options.mcpServers;
12775
12813
  const { preToolUse, postToolUse, postToolUseFailure } = createToolTracingHooks(
12776
- parentSpanExportPromise,
12814
+ resolveParentSpan,
12777
12815
  activeToolSpans,
12778
- mcpServers
12816
+ mcpServers,
12817
+ subAgentSpans,
12818
+ endedSubAgentSpans
12779
12819
  );
12780
12820
  const existingHooks = options.hooks ?? {};
12781
12821
  return {
@@ -12821,18 +12861,45 @@ function filterSerializableOptions(options) {
12821
12861
  }
12822
12862
  return filtered;
12823
12863
  }
12864
+ function isAsyncIterable(value) {
12865
+ return value !== null && value !== void 0 && typeof value[Symbol.asyncIterator] === "function";
12866
+ }
12824
12867
  function wrapClaudeAgentQuery(queryFn, defaultThis) {
12825
12868
  const proxy = new Proxy(queryFn, {
12826
12869
  apply(target, thisArg, argArray) {
12827
12870
  const params = argArray[0] ?? {};
12828
12871
  const { prompt, options = {} } = params;
12872
+ const promptIsAsyncIterable = isAsyncIterable(prompt);
12873
+ let capturedPromptMessages;
12874
+ let promptForQuery = prompt;
12875
+ let promptStarted = false;
12876
+ let resolvePromptDone;
12877
+ const promptDone = new Promise((resolve) => {
12878
+ resolvePromptDone = resolve;
12879
+ });
12880
+ if (promptIsAsyncIterable) {
12881
+ capturedPromptMessages = [];
12882
+ const originalPrompt = prompt;
12883
+ const capturingPrompt = (async function* () {
12884
+ promptStarted = true;
12885
+ try {
12886
+ for await (const msg of originalPrompt) {
12887
+ capturedPromptMessages.push(msg);
12888
+ yield msg;
12889
+ }
12890
+ } finally {
12891
+ resolvePromptDone?.();
12892
+ }
12893
+ })();
12894
+ promptForQuery = capturingPrompt;
12895
+ }
12829
12896
  const span = startSpan({
12830
12897
  name: "Claude Agent",
12831
12898
  spanAttributes: {
12832
12899
  type: "task" /* TASK */
12833
12900
  },
12834
12901
  event: {
12835
- input: typeof prompt === "string" ? prompt : { type: "streaming", description: "AsyncIterable<SDKMessage>" },
12902
+ input: typeof prompt === "string" ? prompt : promptIsAsyncIterable ? void 0 : prompt !== void 0 ? String(prompt) : void 0,
12836
12903
  metadata: filterSerializableOptions(options)
12837
12904
  }
12838
12905
  });
@@ -12843,13 +12910,22 @@ function wrapClaudeAgentQuery(queryFn, defaultThis) {
12843
12910
  let currentMessageStartTime = getCurrentUnixTimestamp();
12844
12911
  const currentMessages = [];
12845
12912
  const createLLMSpan = async () => {
12913
+ const parentToolUseId = currentMessages[0]?.parent_tool_use_id ?? null;
12914
+ let parentSpanExport;
12915
+ if (parentToolUseId) {
12916
+ const subAgentSpan = subAgentSpans.get(parentToolUseId);
12917
+ parentSpanExport = subAgentSpan ? await subAgentSpan.export() : await span.export();
12918
+ } else {
12919
+ parentSpanExport = await span.export();
12920
+ }
12846
12921
  const finalMessageContent = await _createLLMSpanForMessages(
12847
12922
  currentMessages,
12848
12923
  prompt,
12849
12924
  finalResults,
12850
12925
  options,
12851
12926
  currentMessageStartTime,
12852
- await span.export()
12927
+ capturedPromptMessages,
12928
+ parentSpanExport
12853
12929
  );
12854
12930
  if (finalMessageContent) {
12855
12931
  finalResults.push(finalMessageContent);
@@ -12863,12 +12939,34 @@ function wrapClaudeAgentQuery(queryFn, defaultThis) {
12863
12939
  };
12864
12940
  const invocationTarget = thisArg === proxy || thisArg === void 0 ? defaultThis ?? thisArg : thisArg;
12865
12941
  const activeToolSpans = /* @__PURE__ */ new Map();
12942
+ const subAgentSpans = /* @__PURE__ */ new Map();
12943
+ const endedSubAgentSpans = /* @__PURE__ */ new Set();
12944
+ const toolUseToParent = /* @__PURE__ */ new Map();
12945
+ const pendingSubAgentNames = /* @__PURE__ */ new Map();
12946
+ const resolveParentSpan = async (toolUseID) => {
12947
+ const parentToolUseId = toolUseToParent.get(toolUseID);
12948
+ if (parentToolUseId) {
12949
+ const subAgentSpan = subAgentSpans.get(parentToolUseId);
12950
+ if (subAgentSpan) {
12951
+ return subAgentSpan.export();
12952
+ }
12953
+ }
12954
+ return span.export();
12955
+ };
12866
12956
  const optionsWithHooks = injectTracingHooks(
12867
12957
  options,
12868
- span.export(),
12869
- activeToolSpans
12958
+ resolveParentSpan,
12959
+ activeToolSpans,
12960
+ subAgentSpans,
12961
+ endedSubAgentSpans
12870
12962
  );
12871
- const modifiedArgArray = [{ ...params, options: optionsWithHooks }];
12963
+ const modifiedArgArray = [
12964
+ {
12965
+ ...params,
12966
+ ...promptForQuery !== void 0 ? { prompt: promptForQuery } : {},
12967
+ options: optionsWithHooks
12968
+ }
12969
+ ];
12872
12970
  const originalGenerator = withCurrent(
12873
12971
  span,
12874
12972
  () => Reflect.apply(target, invocationTarget, modifiedArgArray)
@@ -12877,6 +12975,41 @@ function wrapClaudeAgentQuery(queryFn, defaultThis) {
12877
12975
  try {
12878
12976
  for await (const message of originalGenerator) {
12879
12977
  const currentTime = getCurrentUnixTimestamp();
12978
+ if (message.type === "assistant" && Array.isArray(message.message?.content)) {
12979
+ const parentToolUseId = message.parent_tool_use_id ?? null;
12980
+ for (const block of message.message.content) {
12981
+ if (block.type === "tool_use" && block.id) {
12982
+ toolUseToParent.set(block.id, parentToolUseId);
12983
+ if (block.name === "Task" && block.input?.subagent_type) {
12984
+ pendingSubAgentNames.set(
12985
+ block.id,
12986
+ block.input.subagent_type
12987
+ );
12988
+ }
12989
+ }
12990
+ }
12991
+ }
12992
+ if ("parent_tool_use_id" in message) {
12993
+ const parentToolUseId = message.parent_tool_use_id;
12994
+ if (parentToolUseId && !subAgentSpans.has(parentToolUseId)) {
12995
+ const agentName = pendingSubAgentNames.get(parentToolUseId);
12996
+ const spanName = agentName ? `Agent: ${agentName}` : "Agent: sub-agent";
12997
+ const parentExport = await span.export();
12998
+ const subAgentSpan = startSpan({
12999
+ name: spanName,
13000
+ spanAttributes: { type: "task" /* TASK */ },
13001
+ event: {
13002
+ metadata: {
13003
+ ...agentName && {
13004
+ "claude_agent_sdk.agent_type": agentName
13005
+ }
13006
+ }
13007
+ },
13008
+ parent: parentExport
13009
+ });
13010
+ subAgentSpans.set(parentToolUseId, subAgentSpan);
13011
+ }
13012
+ }
12880
13013
  const messageId = message.message?.id;
12881
13014
  if (messageId && messageId !== currentMessageId) {
12882
13015
  await createLLMSpan();
@@ -12922,6 +13055,22 @@ function wrapClaudeAgentQuery(queryFn, defaultThis) {
12922
13055
  });
12923
13056
  throw error;
12924
13057
  } finally {
13058
+ for (const [id, subSpan] of subAgentSpans) {
13059
+ if (!endedSubAgentSpans.has(id)) {
13060
+ subSpan.end();
13061
+ }
13062
+ }
13063
+ subAgentSpans.clear();
13064
+ if (capturedPromptMessages) {
13065
+ if (promptStarted) {
13066
+ await promptDone;
13067
+ }
13068
+ if (capturedPromptMessages.length > 0) {
13069
+ span.log({
13070
+ input: _formatCapturedMessages(capturedPromptMessages)
13071
+ });
13072
+ }
13073
+ }
12925
13074
  span.end();
12926
13075
  }
12927
13076
  })();
@@ -12949,14 +13098,25 @@ function wrapClaudeAgentQuery(queryFn, defaultThis) {
12949
13098
  });
12950
13099
  return proxy;
12951
13100
  }
12952
- function _buildLLMInput(prompt, conversationHistory) {
12953
- const promptMessage = typeof prompt === "string" ? { content: prompt, role: "user" } : void 0;
12954
- const inputParts = [
12955
- ...promptMessage ? [promptMessage] : [],
12956
- ...conversationHistory
12957
- ];
13101
+ function _buildLLMInput(prompt, conversationHistory, capturedPromptMessages) {
13102
+ const promptMessages = [];
13103
+ if (typeof prompt === "string") {
13104
+ promptMessages.push({ content: prompt, role: "user" });
13105
+ } else if (capturedPromptMessages && capturedPromptMessages.length > 0) {
13106
+ for (const msg of capturedPromptMessages) {
13107
+ const role = msg.message?.role;
13108
+ const content = msg.message?.content;
13109
+ if (role && content !== void 0) {
13110
+ promptMessages.push({ content, role });
13111
+ }
13112
+ }
13113
+ }
13114
+ const inputParts = [...promptMessages, ...conversationHistory];
12958
13115
  return inputParts.length > 0 ? inputParts : void 0;
12959
13116
  }
13117
+ function _formatCapturedMessages(messages) {
13118
+ return messages.length > 0 ? messages : [];
13119
+ }
12960
13120
  function _extractUsageFromMessage(message) {
12961
13121
  const metrics = {};
12962
13122
  let usage;
@@ -12990,7 +13150,7 @@ function _extractUsageFromMessage(message) {
12990
13150
  }
12991
13151
  return metrics;
12992
13152
  }
12993
- async function _createLLMSpanForMessages(messages, prompt, conversationHistory, options, startTime, parentSpan) {
13153
+ async function _createLLMSpanForMessages(messages, prompt, conversationHistory, options, startTime, capturedPromptMessages, parentSpan) {
12994
13154
  if (messages.length === 0) return void 0;
12995
13155
  const lastMessage = messages[messages.length - 1];
12996
13156
  if (lastMessage.type !== "assistant" || !lastMessage.message?.usage) {
@@ -12998,7 +13158,11 @@ async function _createLLMSpanForMessages(messages, prompt, conversationHistory,
12998
13158
  }
12999
13159
  const model = lastMessage.message.model || options.model;
13000
13160
  const usage = _extractUsageFromMessage(lastMessage);
13001
- const input = _buildLLMInput(prompt, conversationHistory);
13161
+ const input = _buildLLMInput(
13162
+ prompt,
13163
+ conversationHistory,
13164
+ capturedPromptMessages
13165
+ );
13002
13166
  const outputs = messages.map(
13003
13167
  (m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
13004
13168
  ).filter((c) => c !== void 0);
@@ -13755,7 +13919,7 @@ function unescapePath(path) {
13755
13919
  }
13756
13920
  var graph_framework_default = { createGraph };
13757
13921
 
13758
- // ../node_modules/.pnpm/async@3.2.5/node_modules/async/dist/async.mjs
13922
+ // ../node_modules/async/dist/async.mjs
13759
13923
  function initialParams(fn) {
13760
13924
  return function(...args) {
13761
13925
  var callback = args.pop();
@@ -13826,7 +13990,7 @@ function isAsync(fn) {
13826
13990
  function isAsyncGenerator2(fn) {
13827
13991
  return fn[Symbol.toStringTag] === "AsyncGenerator";
13828
13992
  }
13829
- function isAsyncIterable(obj) {
13993
+ function isAsyncIterable2(obj) {
13830
13994
  return typeof obj[Symbol.asyncIterator] === "function";
13831
13995
  }
13832
13996
  function wrapAsync(asyncFn) {
@@ -13880,7 +14044,6 @@ function isArrayLike(value) {
13880
14044
  return value && typeof value.length === "number" && value.length >= 0 && value.length % 1 === 0;
13881
14045
  }
13882
14046
  var breakLoop = {};
13883
- var breakLoop$1 = breakLoop;
13884
14047
  function once(fn) {
13885
14048
  function wrapper(...args) {
13886
14049
  if (fn === null) return;
@@ -13972,7 +14135,7 @@ function asyncEachOfLimit(generator, limit, iteratee, callback) {
13972
14135
  canceled = true;
13973
14136
  return;
13974
14137
  }
13975
- if (result === breakLoop$1 || done && running <= 0) {
14138
+ if (result === breakLoop || done && running <= 0) {
13976
14139
  done = true;
13977
14140
  return callback(null);
13978
14141
  }
@@ -13998,7 +14161,7 @@ var eachOfLimit$2 = (limit) => {
13998
14161
  if (isAsyncGenerator2(obj)) {
13999
14162
  return asyncEachOfLimit(obj, limit, iteratee, callback);
14000
14163
  }
14001
- if (isAsyncIterable(obj)) {
14164
+ if (isAsyncIterable2(obj)) {
14002
14165
  return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback);
14003
14166
  }
14004
14167
  var nextElem = createIterator(obj);
@@ -14015,7 +14178,7 @@ var eachOfLimit$2 = (limit) => {
14015
14178
  } else if (err === false) {
14016
14179
  done = true;
14017
14180
  canceled = true;
14018
- } else if (value === breakLoop$1 || done && running <= 0) {
14181
+ } else if (value === breakLoop || done && running <= 0) {
14019
14182
  done = true;
14020
14183
  return callback(null);
14021
14184
  } else if (!looping) {
@@ -14058,7 +14221,7 @@ function eachOfArrayLike(coll, iteratee, callback) {
14058
14221
  if (canceled === true) return;
14059
14222
  if (err) {
14060
14223
  callback(err);
14061
- } else if (++completed === length || value === breakLoop$1) {
14224
+ } else if (++completed === length || value === breakLoop) {
14062
14225
  callback(null);
14063
14226
  }
14064
14227
  }
@@ -14454,7 +14617,7 @@ function _createTester(check, getResult) {
14454
14617
  if (check(result) && !testResult) {
14455
14618
  testPassed = true;
14456
14619
  testResult = getResult(true, value);
14457
- return callback(null, breakLoop$1);
14620
+ return callback(null, breakLoop);
14458
14621
  }
14459
14622
  callback();
14460
14623
  });
@@ -15232,7 +15395,7 @@ function callEvaluatorData(data) {
15232
15395
  baseExperiment
15233
15396
  };
15234
15397
  }
15235
- function isAsyncIterable2(value) {
15398
+ function isAsyncIterable3(value) {
15236
15399
  return typeof value === "object" && value !== null && typeof value[Symbol.asyncIterator] === "function";
15237
15400
  }
15238
15401
  function isIterable(value) {
@@ -15453,7 +15616,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
15453
15616
  }
15454
15617
  const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
15455
15618
  const dataIterable = (() => {
15456
- if (isAsyncIterable2(resolvedDataResult)) {
15619
+ if (isAsyncIterable3(resolvedDataResult)) {
15457
15620
  return resolvedDataResult;
15458
15621
  }
15459
15622
  if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {