@fallom/trace 0.2.16 → 0.2.18

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/index.mjs CHANGED
@@ -41,7 +41,7 @@ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
41
41
  // node_modules/@opentelemetry/resources/build/esm/Resource.js
42
42
  import { diag } from "@opentelemetry/api";
43
43
 
44
- // node_modules/@opentelemetry/semantic-conventions/build/esm/resource/SemanticResourceAttributes.js
44
+ // node_modules/@opentelemetry/resources/node_modules/@opentelemetry/semantic-conventions/build/esm/resource/SemanticResourceAttributes.js
45
45
  var SemanticResourceAttributes = {
46
46
  /**
47
47
  * Name of the cloud provider.
@@ -1056,6 +1056,54 @@ function clearPromptContext() {
1056
1056
  promptContext = null;
1057
1057
  }
1058
1058
 
1059
+ // src/trace/wrappers/shared-utils.ts
1060
+ function sanitizeMetadataOnly(key, value) {
1061
+ const contentKeys = [
1062
+ "text",
1063
+ "content",
1064
+ "message",
1065
+ "messages",
1066
+ "object",
1067
+ "prompt",
1068
+ "system",
1069
+ "input",
1070
+ "output",
1071
+ "response",
1072
+ "toolCalls",
1073
+ "toolResults",
1074
+ "steps",
1075
+ "reasoning",
1076
+ "rawResponse",
1077
+ "rawCall",
1078
+ "body",
1079
+ "candidates",
1080
+ "parts"
1081
+ ];
1082
+ if (contentKeys.includes(key)) {
1083
+ if (typeof value === "string") {
1084
+ return `[content omitted: ${value.length} chars]`;
1085
+ }
1086
+ if (Array.isArray(value)) {
1087
+ return `[content omitted: ${value.length} items]`;
1088
+ }
1089
+ if (typeof value === "object" && value !== null) {
1090
+ return "[content omitted]";
1091
+ }
1092
+ }
1093
+ if (typeof value === "string") {
1094
+ if (value.startsWith("data:image/")) {
1095
+ return "[base64 image omitted]";
1096
+ }
1097
+ if (value.length > 1e3) {
1098
+ return `[large string omitted: ${value.length} chars]`;
1099
+ }
1100
+ }
1101
+ if (value instanceof Uint8Array || value && value.type === "Buffer") {
1102
+ return "[binary data omitted]";
1103
+ }
1104
+ return value;
1105
+ }
1106
+
1059
1107
  // src/trace/wrappers/openai.ts
1060
1108
  function wrapOpenAI(client, sessionCtx) {
1061
1109
  const originalCreate = client.chat.completions.create.bind(
@@ -1103,6 +1151,13 @@ function wrapOpenAI(client, sessionCtx) {
1103
1151
  if (response?.usage) {
1104
1152
  attributes["fallom.raw.usage"] = JSON.stringify(response.usage);
1105
1153
  }
1154
+ try {
1155
+ attributes["fallom.raw.metadata"] = JSON.stringify(
1156
+ response,
1157
+ sanitizeMetadataOnly
1158
+ );
1159
+ } catch {
1160
+ }
1106
1161
  const waterfallTimings = {
1107
1162
  requestStart: 0,
1108
1163
  requestEnd: endTime - startTime,
@@ -1229,6 +1284,13 @@ function wrapAnthropic(client, sessionCtx) {
1229
1284
  if (response?.usage) {
1230
1285
  attributes["fallom.raw.usage"] = JSON.stringify(response.usage);
1231
1286
  }
1287
+ try {
1288
+ attributes["fallom.raw.metadata"] = JSON.stringify(
1289
+ response,
1290
+ sanitizeMetadataOnly
1291
+ );
1292
+ } catch {
1293
+ }
1232
1294
  const waterfallTimings = {
1233
1295
  requestStart: 0,
1234
1296
  requestEnd: endTime - startTime,
@@ -1349,6 +1411,13 @@ function wrapGoogleAI(model, sessionCtx) {
1349
1411
  if (result?.usageMetadata) {
1350
1412
  attributes["fallom.raw.usage"] = JSON.stringify(result.usageMetadata);
1351
1413
  }
1414
+ try {
1415
+ attributes["fallom.raw.metadata"] = JSON.stringify(
1416
+ result,
1417
+ sanitizeMetadataOnly
1418
+ );
1419
+ } catch {
1420
+ }
1352
1421
  const waterfallTimings = {
1353
1422
  requestStart: 0,
1354
1423
  requestEnd: endTime - startTime,
@@ -1498,20 +1567,36 @@ function createGenerateTextWrapper(aiModule, sessionCtx, debug = false) {
1498
1567
  tools: params?.tools ? Object.keys(params.tools) : void 0,
1499
1568
  maxSteps: params?.maxSteps
1500
1569
  });
1501
- const mapToolCall = (tc) => ({
1502
- toolCallId: tc?.toolCallId,
1503
- toolName: tc?.toolName,
1504
- args: tc?.args ?? tc?.input,
1505
- // v4: args, v5: input
1506
- type: tc?.type
1507
- });
1508
- const mapToolResult = (tr) => ({
1509
- toolCallId: tr?.toolCallId,
1510
- toolName: tr?.toolName,
1511
- result: tr?.result ?? tr?.output,
1512
- // v4: result, v5: output
1513
- type: tr?.type
1514
- });
1570
+ const mapToolCall = (tc) => {
1571
+ let args2 = tc?.args ?? tc?.input;
1572
+ if (args2 === void 0 && tc) {
1573
+ const { type, toolCallId, toolName, providerExecuted, dynamic, invalid, error, providerMetadata, ...rest } = tc;
1574
+ if (Object.keys(rest).length > 0) {
1575
+ args2 = rest;
1576
+ }
1577
+ }
1578
+ return {
1579
+ toolCallId: tc?.toolCallId,
1580
+ toolName: tc?.toolName,
1581
+ args: args2,
1582
+ type: tc?.type
1583
+ };
1584
+ };
1585
+ const mapToolResult = (tr) => {
1586
+ let result2 = tr?.result ?? tr?.output;
1587
+ if (result2 === void 0 && tr) {
1588
+ const { type, toolCallId, toolName, ...rest } = tr;
1589
+ if (Object.keys(rest).length > 0) {
1590
+ result2 = rest;
1591
+ }
1592
+ }
1593
+ return {
1594
+ toolCallId: tr?.toolCallId,
1595
+ toolName: tr?.toolName,
1596
+ result: result2,
1597
+ type: tr?.type
1598
+ };
1599
+ };
1515
1600
  attributes["fallom.raw.response"] = JSON.stringify({
1516
1601
  text: result?.text,
1517
1602
  finishReason: result?.finishReason,
@@ -1545,6 +1630,13 @@ function createGenerateTextWrapper(aiModule, sessionCtx, debug = false) {
1545
1630
  result.experimental_providerMetadata
1546
1631
  );
1547
1632
  }
1633
+ try {
1634
+ attributes["fallom.raw.metadata"] = JSON.stringify(
1635
+ result,
1636
+ sanitizeMetadataOnly
1637
+ );
1638
+ } catch {
1639
+ }
1548
1640
  const totalDurationMs = endTime - startTime;
1549
1641
  const sortedToolTimings = Array.from(toolTimings.values()).sort(
1550
1642
  (a, b) => a.startTime - b.startTime
@@ -1717,7 +1809,9 @@ function createStreamTextWrapper(aiModule, sessionCtx, debug = false) {
1717
1809
  let wrappedParams = params;
1718
1810
  if (params.tools && typeof params.tools === "object") {
1719
1811
  const wrappedTools = {};
1720
- for (const [toolName, tool] of Object.entries(params.tools)) {
1812
+ for (const [toolName, tool] of Object.entries(
1813
+ params.tools
1814
+ )) {
1721
1815
  if (tool && typeof tool.execute === "function") {
1722
1816
  const originalExecute = tool.execute;
1723
1817
  wrappedTools[toolName] = {
@@ -1800,10 +1894,54 @@ function createStreamTextWrapper(aiModule, sessionCtx, debug = false) {
1800
1894
  "\u{1F50D} [Fallom Debug] streamText toolCalls:",
1801
1895
  JSON.stringify(toolCalls, null, 2)
1802
1896
  );
1897
+ if (toolCalls?.[0]) {
1898
+ console.log(
1899
+ "\u{1F50D} [Fallom Debug] streamText toolCalls[0] keys:",
1900
+ Object.keys(toolCalls[0])
1901
+ );
1902
+ console.log(
1903
+ "\u{1F50D} [Fallom Debug] streamText toolCalls[0] full:",
1904
+ JSON.stringify(
1905
+ toolCalls[0],
1906
+ Object.getOwnPropertyNames(toolCalls[0]),
1907
+ 2
1908
+ )
1909
+ );
1910
+ }
1803
1911
  console.log(
1804
1912
  "\u{1F50D} [Fallom Debug] streamText steps count:",
1805
1913
  steps?.length
1806
1914
  );
1915
+ if (steps?.[0]?.toolCalls?.[0]) {
1916
+ const tc = steps[0].toolCalls[0];
1917
+ console.log(
1918
+ "\u{1F50D} [Fallom Debug] steps[0].toolCalls[0] keys:",
1919
+ Object.keys(tc)
1920
+ );
1921
+ console.log(
1922
+ "\u{1F50D} [Fallom Debug] steps[0].toolCalls[0].args (v4):",
1923
+ tc.args
1924
+ );
1925
+ console.log(
1926
+ "\u{1F50D} [Fallom Debug] steps[0].toolCalls[0].input (v5):",
1927
+ tc.input
1928
+ );
1929
+ }
1930
+ if (steps?.[0]?.toolResults?.[0]) {
1931
+ const tr = steps[0].toolResults[0];
1932
+ console.log(
1933
+ "\u{1F50D} [Fallom Debug] steps[0].toolResults[0] keys:",
1934
+ Object.keys(tr)
1935
+ );
1936
+ console.log(
1937
+ "\u{1F50D} [Fallom Debug] steps[0].toolResults[0].result (v4):",
1938
+ typeof tr.result === "string" ? tr.result.slice(0, 200) : tr.result
1939
+ );
1940
+ console.log(
1941
+ "\u{1F50D} [Fallom Debug] steps[0].toolResults[0].output (v5):",
1942
+ typeof tr.output === "string" ? tr.output.slice(0, 200) : tr.output
1943
+ );
1944
+ }
1807
1945
  }
1808
1946
  let providerMetadata = result?.experimental_providerMetadata;
1809
1947
  if (providerMetadata && typeof providerMetadata.then === "function") {
@@ -1819,20 +1957,46 @@ function createStreamTextWrapper(aiModule, sessionCtx, debug = false) {
1819
1957
  "fallom.is_streaming": true
1820
1958
  };
1821
1959
  if (captureContent2) {
1822
- const mapToolCall = (tc) => ({
1823
- toolCallId: tc?.toolCallId,
1824
- toolName: tc?.toolName,
1825
- args: tc?.args ?? tc?.input,
1826
- // v4: args, v5: input
1827
- type: tc?.type
1828
- });
1829
- const mapToolResult = (tr) => ({
1830
- toolCallId: tr?.toolCallId,
1831
- toolName: tr?.toolName,
1832
- result: tr?.result ?? tr?.output,
1833
- // v4: result, v5: output
1834
- type: tr?.type
1835
- });
1960
+ const mapToolCall = (tc) => {
1961
+ let args2 = tc?.args ?? tc?.input;
1962
+ if (args2 === void 0 && tc) {
1963
+ const {
1964
+ type,
1965
+ toolCallId,
1966
+ toolName,
1967
+ providerExecuted,
1968
+ dynamic,
1969
+ invalid,
1970
+ error,
1971
+ providerMetadata: providerMetadata2,
1972
+ ...rest
1973
+ } = tc;
1974
+ if (Object.keys(rest).length > 0) {
1975
+ args2 = rest;
1976
+ }
1977
+ }
1978
+ return {
1979
+ toolCallId: tc?.toolCallId,
1980
+ toolName: tc?.toolName,
1981
+ args: args2,
1982
+ type: tc?.type
1983
+ };
1984
+ };
1985
+ const mapToolResult = (tr) => {
1986
+ let result2 = tr?.result ?? tr?.output;
1987
+ if (result2 === void 0 && tr) {
1988
+ const { type, toolCallId, toolName, ...rest } = tr;
1989
+ if (Object.keys(rest).length > 0) {
1990
+ result2 = rest;
1991
+ }
1992
+ }
1993
+ return {
1994
+ toolCallId: tr?.toolCallId,
1995
+ toolName: tr?.toolName,
1996
+ result: result2,
1997
+ type: tr?.type
1998
+ };
1999
+ };
1836
2000
  attributes["fallom.raw.request"] = JSON.stringify({
1837
2001
  prompt: params?.prompt,
1838
2002
  messages: params?.messages,
@@ -1873,6 +2037,13 @@ function createStreamTextWrapper(aiModule, sessionCtx, debug = false) {
1873
2037
  if (firstTokenTime) {
1874
2038
  attributes["fallom.time_to_first_token_ms"] = firstTokenTime - startTime;
1875
2039
  }
2040
+ try {
2041
+ attributes["fallom.raw.metadata"] = JSON.stringify(
2042
+ result,
2043
+ sanitizeMetadataOnly
2044
+ );
2045
+ } catch {
2046
+ }
1876
2047
  const totalDurationMs = endTime - startTime;
1877
2048
  const sortedToolTimings = Array.from(toolTimings.values()).sort(
1878
2049
  (a, b) => a.startTime - b.startTime
@@ -1897,8 +2068,12 @@ function createStreamTextWrapper(aiModule, sessionCtx, debug = false) {
1897
2068
  });
1898
2069
  }
1899
2070
  if (sortedToolTimings.length > 0) {
1900
- const firstToolStart = Math.min(...sortedToolTimings.map((t) => t.startTime));
1901
- const lastToolEnd = Math.max(...sortedToolTimings.map((t) => t.endTime));
2071
+ const firstToolStart = Math.min(
2072
+ ...sortedToolTimings.map((t) => t.startTime)
2073
+ );
2074
+ const lastToolEnd = Math.max(
2075
+ ...sortedToolTimings.map((t) => t.endTime)
2076
+ );
1902
2077
  if (firstToolStart > 10) {
1903
2078
  waterfallTimings.phases.push({
1904
2079
  type: "llm",
@@ -2078,6 +2253,10 @@ function createGenerateObjectWrapper(aiModule, sessionCtx, debug = false) {
2078
2253
  result.experimental_providerMetadata
2079
2254
  );
2080
2255
  }
2256
+ try {
2257
+ attributes["fallom.raw.metadata"] = JSON.stringify(result, sanitizeMetadataOnly);
2258
+ } catch {
2259
+ }
2081
2260
  const promptCtx = getPromptContext();
2082
2261
  sendTrace({
2083
2262
  config_key: ctx.configKey,
@@ -2197,6 +2376,10 @@ function createStreamObjectWrapper(aiModule, sessionCtx, debug = false) {
2197
2376
  if (providerMetadata) {
2198
2377
  attributes["fallom.raw.providerMetadata"] = JSON.stringify(providerMetadata);
2199
2378
  }
2379
+ try {
2380
+ attributes["fallom.raw.metadata"] = JSON.stringify(result, sanitizeMetadataOnly);
2381
+ } catch {
2382
+ }
2200
2383
  const promptCtx = getPromptContext();
2201
2384
  sendTrace({
2202
2385
  config_key: ctx.configKey,
@@ -2293,6 +2476,13 @@ function wrapMastraAgent(agent, sessionCtx) {
2293
2476
  attributes["fallom.raw.request"] = JSON.stringify(input);
2294
2477
  attributes["fallom.raw.response"] = JSON.stringify(result);
2295
2478
  }
2479
+ try {
2480
+ attributes["fallom.raw.metadata"] = JSON.stringify(
2481
+ result,
2482
+ sanitizeMetadataOnly
2483
+ );
2484
+ } catch {
2485
+ }
2296
2486
  sendTrace({
2297
2487
  config_key: ctx.configKey,
2298
2488
  session_id: ctx.sessionId,
@@ -0,0 +1,8 @@
1
+ import {
2
+ get,
3
+ init
4
+ } from "./chunk-KFD5AQ7V.mjs";
5
+ export {
6
+ get,
7
+ init
8
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fallom/trace",
3
- "version": "0.2.16",
3
+ "version": "0.2.18",
4
4
  "description": "Model A/B testing and tracing for LLM applications. Zero latency, production-ready.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",