@sentry/core 10.50.0 → 10.51.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 (188) hide show
  1. package/build/cjs/client.js +27 -3
  2. package/build/cjs/client.js.map +1 -1
  3. package/build/cjs/envelope.js +4 -1
  4. package/build/cjs/envelope.js.map +1 -1
  5. package/build/cjs/index.js +10 -5
  6. package/build/cjs/index.js.map +1 -1
  7. package/build/cjs/instrument/console.js +3 -1
  8. package/build/cjs/instrument/console.js.map +1 -1
  9. package/build/cjs/instrument/fetch.js +6 -2
  10. package/build/cjs/instrument/fetch.js.map +1 -1
  11. package/build/cjs/instrument/handlers.js +11 -1
  12. package/build/cjs/instrument/handlers.js.map +1 -1
  13. package/build/cjs/integrations/console.js +3 -1
  14. package/build/cjs/integrations/console.js.map +1 -1
  15. package/build/cjs/integrations/extraerrordata.js +2 -2
  16. package/build/cjs/integrations/extraerrordata.js.map +1 -1
  17. package/build/cjs/integrations/postgresjs.js +10 -1
  18. package/build/cjs/integrations/postgresjs.js.map +1 -1
  19. package/build/cjs/integrations/requestdata.js +9 -5
  20. package/build/cjs/integrations/requestdata.js.map +1 -1
  21. package/build/cjs/integrations/supabase.js +39 -12
  22. package/build/cjs/integrations/supabase.js.map +1 -1
  23. package/build/cjs/logs/console-integration.js +3 -1
  24. package/build/cjs/logs/console-integration.js.map +1 -1
  25. package/build/cjs/server-runtime-client.js +20 -2
  26. package/build/cjs/server-runtime-client.js.map +1 -1
  27. package/build/cjs/tracing/ai/gen-ai-attributes.js +6 -0
  28. package/build/cjs/tracing/ai/gen-ai-attributes.js.map +1 -1
  29. package/build/cjs/tracing/idleSpan.js +7 -1
  30. package/build/cjs/tracing/idleSpan.js.map +1 -1
  31. package/build/cjs/tracing/langchain/index.js +43 -8
  32. package/build/cjs/tracing/langchain/index.js.map +1 -1
  33. package/build/cjs/tracing/langchain/utils.js +44 -10
  34. package/build/cjs/tracing/langchain/utils.js.map +1 -1
  35. package/build/cjs/tracing/langgraph/index.js +105 -2
  36. package/build/cjs/tracing/langgraph/index.js.map +1 -1
  37. package/build/cjs/tracing/langgraph/utils.js +168 -0
  38. package/build/cjs/tracing/langgraph/utils.js.map +1 -1
  39. package/build/cjs/tracing/spans/captureSpan.js +125 -0
  40. package/build/cjs/tracing/spans/captureSpan.js.map +1 -1
  41. package/build/cjs/tracing/spans/envelope.js +13 -3
  42. package/build/cjs/tracing/spans/envelope.js.map +1 -1
  43. package/build/cjs/tracing/trace.js +1 -0
  44. package/build/cjs/tracing/trace.js.map +1 -1
  45. package/build/cjs/trpc.js +2 -3
  46. package/build/cjs/trpc.js.map +1 -1
  47. package/build/cjs/utils/isSentryRequestUrl.js +9 -1
  48. package/build/cjs/utils/isSentryRequestUrl.js.map +1 -1
  49. package/build/cjs/utils/normalizationHints.js +38 -0
  50. package/build/cjs/utils/normalizationHints.js.map +1 -0
  51. package/build/cjs/utils/normalize.js +7 -11
  52. package/build/cjs/utils/normalize.js.map +1 -1
  53. package/build/cjs/utils/object.js +1 -1
  54. package/build/cjs/utils/object.js.map +1 -1
  55. package/build/cjs/utils/request.js +63 -12
  56. package/build/cjs/utils/request.js.map +1 -1
  57. package/build/cjs/utils/should-ignore-span.js +27 -8
  58. package/build/cjs/utils/should-ignore-span.js.map +1 -1
  59. package/build/cjs/utils/version.js +1 -1
  60. package/build/esm/client.js +27 -3
  61. package/build/esm/client.js.map +1 -1
  62. package/build/esm/envelope.js +4 -1
  63. package/build/esm/envelope.js.map +1 -1
  64. package/build/esm/index.js +3 -2
  65. package/build/esm/index.js.map +1 -1
  66. package/build/esm/instrument/console.js +3 -1
  67. package/build/esm/instrument/console.js.map +1 -1
  68. package/build/esm/instrument/fetch.js +6 -2
  69. package/build/esm/instrument/fetch.js.map +1 -1
  70. package/build/esm/instrument/handlers.js +11 -1
  71. package/build/esm/instrument/handlers.js.map +1 -1
  72. package/build/esm/integrations/console.js +3 -1
  73. package/build/esm/integrations/console.js.map +1 -1
  74. package/build/esm/integrations/extraerrordata.js +2 -2
  75. package/build/esm/integrations/extraerrordata.js.map +1 -1
  76. package/build/esm/integrations/postgresjs.js +10 -1
  77. package/build/esm/integrations/postgresjs.js.map +1 -1
  78. package/build/esm/integrations/requestdata.js +9 -5
  79. package/build/esm/integrations/requestdata.js.map +1 -1
  80. package/build/esm/integrations/supabase.js +39 -12
  81. package/build/esm/integrations/supabase.js.map +1 -1
  82. package/build/esm/logs/console-integration.js +3 -1
  83. package/build/esm/logs/console-integration.js.map +1 -1
  84. package/build/esm/package.json +1 -1
  85. package/build/esm/server-runtime-client.js +20 -2
  86. package/build/esm/server-runtime-client.js.map +1 -1
  87. package/build/esm/tracing/ai/gen-ai-attributes.js +6 -1
  88. package/build/esm/tracing/ai/gen-ai-attributes.js.map +1 -1
  89. package/build/esm/tracing/idleSpan.js +7 -1
  90. package/build/esm/tracing/idleSpan.js.map +1 -1
  91. package/build/esm/tracing/langchain/index.js +45 -10
  92. package/build/esm/tracing/langchain/index.js.map +1 -1
  93. package/build/esm/tracing/langchain/utils.js +44 -12
  94. package/build/esm/tracing/langchain/utils.js.map +1 -1
  95. package/build/esm/tracing/langgraph/index.js +107 -5
  96. package/build/esm/tracing/langgraph/index.js.map +1 -1
  97. package/build/esm/tracing/langgraph/utils.js +166 -2
  98. package/build/esm/tracing/langgraph/utils.js.map +1 -1
  99. package/build/esm/tracing/spans/captureSpan.js +126 -2
  100. package/build/esm/tracing/spans/captureSpan.js.map +1 -1
  101. package/build/esm/tracing/spans/envelope.js +13 -3
  102. package/build/esm/tracing/spans/envelope.js.map +1 -1
  103. package/build/esm/tracing/trace.js +1 -0
  104. package/build/esm/tracing/trace.js.map +1 -1
  105. package/build/esm/trpc.js +2 -3
  106. package/build/esm/trpc.js.map +1 -1
  107. package/build/esm/utils/isSentryRequestUrl.js +9 -1
  108. package/build/esm/utils/isSentryRequestUrl.js.map +1 -1
  109. package/build/esm/utils/normalizationHints.js +33 -0
  110. package/build/esm/utils/normalizationHints.js.map +1 -0
  111. package/build/esm/utils/normalize.js +7 -11
  112. package/build/esm/utils/normalize.js.map +1 -1
  113. package/build/esm/utils/object.js +1 -1
  114. package/build/esm/utils/object.js.map +1 -1
  115. package/build/esm/utils/request.js +63 -12
  116. package/build/esm/utils/request.js.map +1 -1
  117. package/build/esm/utils/should-ignore-span.js +27 -8
  118. package/build/esm/utils/should-ignore-span.js.map +1 -1
  119. package/build/esm/utils/version.js +1 -1
  120. package/build/types/client.d.ts +12 -1
  121. package/build/types/client.d.ts.map +1 -1
  122. package/build/types/envelope.d.ts.map +1 -1
  123. package/build/types/index.d.ts +4 -2
  124. package/build/types/index.d.ts.map +1 -1
  125. package/build/types/instrument/console.d.ts +2 -1
  126. package/build/types/instrument/console.d.ts.map +1 -1
  127. package/build/types/instrument/fetch.d.ts +4 -2
  128. package/build/types/instrument/fetch.d.ts.map +1 -1
  129. package/build/types/instrument/handlers.d.ts +2 -2
  130. package/build/types/instrument/handlers.d.ts.map +1 -1
  131. package/build/types/integrations/console.d.ts.map +1 -1
  132. package/build/types/integrations/postgresjs.d.ts.map +1 -1
  133. package/build/types/integrations/supabase.d.ts.map +1 -1
  134. package/build/types/logs/console-integration.d.ts.map +1 -1
  135. package/build/types/server-runtime-client.d.ts +5 -0
  136. package/build/types/server-runtime-client.d.ts.map +1 -1
  137. package/build/types/tracing/idleSpan.d.ts.map +1 -1
  138. package/build/types/tracing/langchain/index.d.ts.map +1 -1
  139. package/build/types/tracing/langchain/types.d.ts +8 -0
  140. package/build/types/tracing/langchain/types.d.ts.map +1 -1
  141. package/build/types/tracing/langchain/utils.d.ts +2 -0
  142. package/build/types/tracing/langchain/utils.d.ts.map +1 -1
  143. package/build/types/tracing/langgraph/index.d.ts +4 -0
  144. package/build/types/tracing/langgraph/index.d.ts.map +1 -1
  145. package/build/types/tracing/langgraph/utils.d.ts +18 -2
  146. package/build/types/tracing/langgraph/utils.d.ts.map +1 -1
  147. package/build/types/tracing/spans/captureSpan.d.ts +10 -0
  148. package/build/types/tracing/spans/captureSpan.d.ts.map +1 -1
  149. package/build/types/tracing/spans/envelope.d.ts.map +1 -1
  150. package/build/types/trpc.d.ts.map +1 -1
  151. package/build/types/types-hoist/feedback/config.d.ts +20 -0
  152. package/build/types/types-hoist/feedback/config.d.ts.map +1 -1
  153. package/build/types/types-hoist/feedback/index.d.ts +2 -2
  154. package/build/types/types-hoist/feedback/index.d.ts.map +1 -1
  155. package/build/types/types-hoist/feedback/sendFeedback.d.ts +3 -0
  156. package/build/types/types-hoist/feedback/sendFeedback.d.ts.map +1 -1
  157. package/build/types/types-hoist/options.d.ts +37 -2
  158. package/build/types/types-hoist/options.d.ts.map +1 -1
  159. package/build/types/types-hoist/span.d.ts +5 -0
  160. package/build/types/types-hoist/span.d.ts.map +1 -1
  161. package/build/types/utils/normalizationHints.d.ts +9 -0
  162. package/build/types/utils/normalizationHints.d.ts.map +1 -0
  163. package/build/types/utils/normalize.d.ts.map +1 -1
  164. package/build/types/utils/object.d.ts +1 -1
  165. package/build/types/utils/object.d.ts.map +1 -1
  166. package/build/types/utils/request.d.ts.map +1 -1
  167. package/build/types/utils/should-ignore-span.d.ts +3 -1
  168. package/build/types/utils/should-ignore-span.d.ts.map +1 -1
  169. package/build/types-ts3.8/client.d.ts +12 -1
  170. package/build/types-ts3.8/index.d.ts +4 -2
  171. package/build/types-ts3.8/instrument/console.d.ts +2 -1
  172. package/build/types-ts3.8/instrument/fetch.d.ts +4 -2
  173. package/build/types-ts3.8/instrument/handlers.d.ts +2 -2
  174. package/build/types-ts3.8/server-runtime-client.d.ts +5 -0
  175. package/build/types-ts3.8/tracing/langchain/types.d.ts +8 -0
  176. package/build/types-ts3.8/tracing/langchain/utils.d.ts +2 -0
  177. package/build/types-ts3.8/tracing/langgraph/index.d.ts +4 -0
  178. package/build/types-ts3.8/tracing/langgraph/utils.d.ts +18 -2
  179. package/build/types-ts3.8/tracing/spans/captureSpan.d.ts +10 -0
  180. package/build/types-ts3.8/types-hoist/feedback/config.d.ts +20 -0
  181. package/build/types-ts3.8/types-hoist/feedback/index.d.ts +2 -2
  182. package/build/types-ts3.8/types-hoist/feedback/sendFeedback.d.ts +3 -0
  183. package/build/types-ts3.8/types-hoist/options.d.ts +37 -2
  184. package/build/types-ts3.8/types-hoist/span.d.ts +5 -0
  185. package/build/types-ts3.8/utils/normalizationHints.d.ts +9 -0
  186. package/build/types-ts3.8/utils/object.d.ts +1 -1
  187. package/build/types-ts3.8/utils/should-ignore-span.d.ts +3 -1
  188. package/package.json +1 -1
@@ -6,10 +6,15 @@ const spanstatus = require('../spanstatus.js');
6
6
  const trace = require('../trace.js');
7
7
  const genAiAttributes = require('../ai/gen-ai-attributes.js');
8
8
  const utils = require('../ai/utils.js');
9
+ const index = require('../langchain/index.js');
9
10
  const utils$2 = require('../langchain/utils.js');
10
11
  const constants = require('./constants.js');
11
12
  const utils$1 = require('./utils.js');
12
13
 
14
+ let _insideCreateReactAgent = false;
15
+
16
+ const SENTRY_PATCHED = '__sentry_patched__';
17
+
13
18
  /**
14
19
  * Instruments StateGraph's compile method to create spans for agent creation and invocation
15
20
  *
@@ -22,8 +27,19 @@ function instrumentStateGraphCompile(
22
27
  originalCompile,
23
28
  options,
24
29
  ) {
25
- return new Proxy(originalCompile, {
30
+ if (Object.prototype.hasOwnProperty.call(originalCompile, SENTRY_PATCHED)) {
31
+ return originalCompile;
32
+ }
33
+
34
+ const sentryHandler = index.createLangChainCallbackHandler(options);
35
+
36
+ const wrapped = new Proxy(originalCompile, {
26
37
  apply(target, thisArg, args) {
38
+ // Skip when called from within createReactAgent to avoid duplicate instrumentation
39
+ if (_insideCreateReactAgent) {
40
+ return Reflect.apply(target, thisArg, args);
41
+ }
42
+
27
43
  return trace.startSpan(
28
44
  {
29
45
  op: 'gen_ai.create_agent',
@@ -53,6 +69,8 @@ function instrumentStateGraphCompile(
53
69
  compiledGraph,
54
70
  compileOptions,
55
71
  options,
72
+ undefined,
73
+ sentryHandler,
56
74
  ) ;
57
75
  }
58
76
 
@@ -71,6 +89,9 @@ function instrumentStateGraphCompile(
71
89
  );
72
90
  },
73
91
  }) ;
92
+
93
+ Object.defineProperty(wrapped, SENTRY_PATCHED, { value: true, enumerable: false });
94
+ return wrapped;
74
95
  }
75
96
 
76
97
  /**
@@ -83,9 +104,12 @@ function instrumentCompiledGraphInvoke(
83
104
  graphInstance,
84
105
  compileOptions,
85
106
  options,
107
+ llm,
108
+ sentryCallbackHandler,
86
109
  ) {
87
110
  return new Proxy(originalInvoke, {
88
111
  apply(target, thisArg, args) {
112
+ const modelName = llm?.modelName ?? llm?.model;
89
113
  return trace.startSpan(
90
114
  {
91
115
  op: 'gen_ai.invoke_agent',
@@ -106,6 +130,10 @@ function instrumentCompiledGraphInvoke(
106
130
  span.updateName(`invoke_agent ${graphName}`);
107
131
  }
108
132
 
133
+ if (modelName) {
134
+ span.setAttribute(genAiAttributes.GEN_AI_REQUEST_MODEL_ATTRIBUTE, modelName);
135
+ }
136
+
109
137
  // Extract thread_id from the config (second argument)
110
138
  // LangGraph uses config.configurable.thread_id for conversation/session linking
111
139
  const config = args.length > 1 ? (args[1] ) : undefined;
@@ -115,6 +143,21 @@ function instrumentCompiledGraphInvoke(
115
143
  span.setAttribute(genAiAttributes.GEN_AI_CONVERSATION_ID_ATTRIBUTE, threadId);
116
144
  }
117
145
 
146
+ // Inject callback handler and agent name into invoke config
147
+ if (sentryCallbackHandler) {
148
+ const invokeConfig = (args[1] ?? {}) ;
149
+ args[1] = invokeConfig;
150
+
151
+ const existingMetadata = (invokeConfig.metadata ?? {}) ;
152
+ invokeConfig.metadata = {
153
+ ...existingMetadata,
154
+ __sentry_langgraph__: true,
155
+ ...(typeof graphName === 'string' ? { lc_agent_name: graphName } : {}),
156
+ };
157
+
158
+ invokeConfig.callbacks = utils$1.mergeSentryCallback(invokeConfig.callbacks, sentryCallbackHandler);
159
+ }
160
+
118
161
  // Extract available tools from the graph instance
119
162
  const tools = utils$1.extractToolsFromCompiledGraph(graphInstance);
120
163
  if (tools) {
@@ -148,7 +191,6 @@ function instrumentCompiledGraphInvoke(
148
191
  // Call original invoke
149
192
  const result = await Reflect.apply(target, thisArg, args);
150
193
 
151
- // Set response attributes
152
194
  if (recordOutputs) {
153
195
  utils$1.setResponseAttributes(span, inputMessages ?? null, result);
154
196
  }
@@ -170,6 +212,66 @@ function instrumentCompiledGraphInvoke(
170
212
  }) ;
171
213
  }
172
214
 
215
+ /**
216
+ * Instruments createReactAgent to create invoke_agent and execute_tool spans.
217
+ */
218
+ function instrumentCreateReactAgent(
219
+ originalCreateReactAgent,
220
+ options,
221
+ ) {
222
+ if (Object.prototype.hasOwnProperty.call(originalCreateReactAgent, SENTRY_PATCHED)) {
223
+ return originalCreateReactAgent;
224
+ }
225
+
226
+ const resolvedOptions = utils.resolveAIRecordingOptions(options);
227
+ const sentryHandler = index.createLangChainCallbackHandler(resolvedOptions);
228
+
229
+ const wrapped = new Proxy(originalCreateReactAgent, {
230
+ apply(target, thisArg, args) {
231
+ const llm = utils$1.extractLLMFromParams(args);
232
+ const agentName = utils$1.extractAgentNameFromParams(args);
233
+
234
+ // Wrap tools with execute_tool spans (direct access gives us name, type, description)
235
+ const params = args[0] ;
236
+ if (params && Array.isArray(params.tools) && params.tools.length > 0) {
237
+ utils$1.wrapToolsWithSpans(params.tools, resolvedOptions, agentName ?? undefined);
238
+ }
239
+
240
+ // Suppress StateGraph.compile instrumentation inside createReactAgent
241
+ _insideCreateReactAgent = true;
242
+ let compiledGraph;
243
+ try {
244
+ compiledGraph = Reflect.apply(target, thisArg, args);
245
+ } finally {
246
+ _insideCreateReactAgent = false;
247
+ }
248
+
249
+ // Wrap invoke() on the returned compiled graph
250
+ const originalInvoke = compiledGraph.invoke;
251
+ if (originalInvoke && typeof originalInvoke === 'function') {
252
+ const compileOptions = {};
253
+ if (agentName) {
254
+ compileOptions.name = agentName;
255
+ }
256
+
257
+ compiledGraph.invoke = instrumentCompiledGraphInvoke(
258
+ originalInvoke.bind(compiledGraph) ,
259
+ compiledGraph,
260
+ compileOptions,
261
+ resolvedOptions,
262
+ llm,
263
+ sentryHandler,
264
+ ) ;
265
+ }
266
+
267
+ return compiledGraph;
268
+ },
269
+ }) ;
270
+
271
+ Object.defineProperty(wrapped, SENTRY_PATCHED, { value: true, enumerable: false });
272
+ return wrapped;
273
+ }
274
+
173
275
  /**
174
276
  * Directly instruments a StateGraph instance to add tracing spans
175
277
  *
@@ -203,6 +305,7 @@ function instrumentLangGraph(
203
305
  return stateGraph;
204
306
  }
205
307
 
308
+ exports.instrumentCreateReactAgent = instrumentCreateReactAgent;
206
309
  exports.instrumentLangGraph = instrumentLangGraph;
207
310
  exports.instrumentStateGraphCompile = instrumentStateGraphCompile;
208
311
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/tracing/langgraph/index.ts"],"sourcesContent":["import { captureException } from '../../exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport {\n GEN_AI_AGENT_NAME_ATTRIBUTE,\n GEN_AI_CONVERSATION_ID_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE,\n GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE,\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_PIPELINE_NAME_ATTRIBUTE,\n GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE,\n GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport {\n extractSystemInstructions,\n getJsonString,\n getTruncatedJsonString,\n resolveAIRecordingOptions,\n shouldEnableTruncation,\n} from '../ai/utils';\nimport type { LangChainMessage } from '../langchain/types';\nimport { normalizeLangChainMessages } from '../langchain/utils';\nimport { startSpan } from '../trace';\nimport { LANGGRAPH_ORIGIN } from './constants';\nimport type { CompiledGraph, LangGraphOptions } from './types';\nimport { extractToolsFromCompiledGraph, setResponseAttributes } from './utils';\n\n/**\n * Instruments StateGraph's compile method to create spans for agent creation and invocation\n *\n * Wraps the compile() method to:\n * - Create a `gen_ai.create_agent` span when compile() is called\n * - Automatically wrap the invoke() method on the returned compiled graph with a `gen_ai.invoke_agent` span\n *\n */\nexport function instrumentStateGraphCompile(\n originalCompile: (...args: unknown[]) => CompiledGraph,\n options: LangGraphOptions,\n): (...args: unknown[]) => CompiledGraph {\n return new Proxy(originalCompile, {\n apply(target, thisArg, args: unknown[]): CompiledGraph {\n return startSpan(\n {\n op: 'gen_ai.create_agent',\n name: 'create_agent',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGGRAPH_ORIGIN,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.create_agent',\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'create_agent',\n },\n },\n span => {\n try {\n const compiledGraph = Reflect.apply(target, thisArg, args);\n const compileOptions = args.length > 0 ? (args[0] as Record<string, unknown>) : {};\n\n // Extract graph name\n if (compileOptions?.name && typeof compileOptions.name === 'string') {\n span.setAttribute(GEN_AI_AGENT_NAME_ATTRIBUTE, compileOptions.name);\n span.updateName(`create_agent ${compileOptions.name}`);\n }\n\n // Instrument agent invoke method on the compiled graph\n const originalInvoke = compiledGraph.invoke;\n if (originalInvoke && typeof originalInvoke === 'function') {\n compiledGraph.invoke = instrumentCompiledGraphInvoke(\n originalInvoke.bind(compiledGraph) as (...args: unknown[]) => Promise<unknown>,\n compiledGraph,\n compileOptions,\n options,\n ) as typeof originalInvoke;\n }\n\n return compiledGraph;\n } catch (error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.langgraph.error',\n },\n });\n throw error;\n }\n },\n );\n },\n }) as (...args: unknown[]) => CompiledGraph;\n}\n\n/**\n * Instruments CompiledGraph's invoke method to create spans for agent invocation\n *\n * Creates a `gen_ai.invoke_agent` span when invoke() is called\n */\nfunction instrumentCompiledGraphInvoke(\n originalInvoke: (...args: unknown[]) => Promise<unknown>,\n graphInstance: CompiledGraph,\n compileOptions: Record<string, unknown>,\n options: LangGraphOptions,\n): (...args: unknown[]) => Promise<unknown> {\n return new Proxy(originalInvoke, {\n apply(target, thisArg, args: unknown[]): Promise<unknown> {\n return startSpan(\n {\n op: 'gen_ai.invoke_agent',\n name: 'invoke_agent',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGGRAPH_ORIGIN,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE,\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'invoke_agent',\n },\n },\n async span => {\n try {\n const graphName = compileOptions?.name;\n\n if (graphName && typeof graphName === 'string') {\n span.setAttribute(GEN_AI_PIPELINE_NAME_ATTRIBUTE, graphName);\n span.setAttribute(GEN_AI_AGENT_NAME_ATTRIBUTE, graphName);\n span.updateName(`invoke_agent ${graphName}`);\n }\n\n // Extract thread_id from the config (second argument)\n // LangGraph uses config.configurable.thread_id for conversation/session linking\n const config = args.length > 1 ? (args[1] as Record<string, unknown> | undefined) : undefined;\n const configurable = config?.configurable as Record<string, unknown> | undefined;\n const threadId = configurable?.thread_id;\n if (threadId && typeof threadId === 'string') {\n span.setAttribute(GEN_AI_CONVERSATION_ID_ATTRIBUTE, threadId);\n }\n\n // Extract available tools from the graph instance\n const tools = extractToolsFromCompiledGraph(graphInstance);\n if (tools) {\n span.setAttribute(GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, JSON.stringify(tools));\n }\n\n // Parse input messages\n const recordInputs = options.recordInputs;\n const recordOutputs = options.recordOutputs;\n const inputMessages =\n args.length > 0 ? ((args[0] as { messages?: LangChainMessage[] } | null)?.messages ?? []) : [];\n\n if (inputMessages && recordInputs) {\n const normalizedMessages = normalizeLangChainMessages(inputMessages);\n const { systemInstructions, filteredMessages } = extractSystemInstructions(normalizedMessages);\n\n if (systemInstructions) {\n span.setAttribute(GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, systemInstructions);\n }\n\n const enableTruncation = shouldEnableTruncation(options.enableTruncation);\n const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0;\n span.setAttributes({\n [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: enableTruncation\n ? getTruncatedJsonString(filteredMessages)\n : getJsonString(filteredMessages),\n [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength,\n });\n }\n\n // Call original invoke\n const result = await Reflect.apply(target, thisArg, args);\n\n // Set response attributes\n if (recordOutputs) {\n setResponseAttributes(span, inputMessages ?? null, result);\n }\n\n return result;\n } catch (error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.langgraph.error',\n },\n });\n throw error;\n }\n },\n );\n },\n }) as (...args: unknown[]) => Promise<unknown>;\n}\n\n/**\n * Directly instruments a StateGraph instance to add tracing spans\n *\n * This function can be used to manually instrument LangGraph StateGraph instances\n * in environments where automatic instrumentation is not available or desired.\n *\n * @param stateGraph - The StateGraph instance to instrument\n * @param options - Optional configuration for recording inputs/outputs\n *\n * @example\n * ```typescript\n * import { instrumentLangGraph } from '@sentry/cloudflare';\n * import { StateGraph } from '@langchain/langgraph';\n *\n * const graph = new StateGraph(MessagesAnnotation)\n * .addNode('agent', mockLlm)\n * .addEdge(START, 'agent')\n * .addEdge('agent', END);\n *\n * instrumentLangGraph(graph, { recordInputs: true, recordOutputs: true });\n * const compiled = graph.compile({ name: 'my_agent' });\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function instrumentLangGraph<T extends { compile: (...args: any[]) => any }>(\n stateGraph: T,\n options?: LangGraphOptions,\n): T {\n stateGraph.compile = instrumentStateGraphCompile(stateGraph.compile, resolveAIRecordingOptions(options));\n\n return stateGraph;\n}\n"],"names":["startSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","LANGGRAPH_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_OP","GEN_AI_OPERATION_NAME_ATTRIBUTE","GEN_AI_AGENT_NAME_ATTRIBUTE","SPAN_STATUS_ERROR","captureException","GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE","GEN_AI_PIPELINE_NAME_ATTRIBUTE","GEN_AI_CONVERSATION_ID_ATTRIBUTE","extractToolsFromCompiledGraph","GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE","normalizeLangChainMessages","extractSystemInstructions","GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE","shouldEnableTruncation","GEN_AI_INPUT_MESSAGES_ATTRIBUTE","getTruncatedJsonString","getJsonString","GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE","setResponseAttributes","resolveAIRecordingOptions"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/tracing/langgraph/index.ts"],"sourcesContent":["import { captureException } from '../../exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport {\n GEN_AI_AGENT_NAME_ATTRIBUTE,\n GEN_AI_CONVERSATION_ID_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ATTRIBUTE,\n GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE,\n GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE,\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_PIPELINE_NAME_ATTRIBUTE,\n GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE,\n GEN_AI_REQUEST_MODEL_ATTRIBUTE,\n GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport {\n extractSystemInstructions,\n getJsonString,\n getTruncatedJsonString,\n resolveAIRecordingOptions,\n shouldEnableTruncation,\n} from '../ai/utils';\nimport { createLangChainCallbackHandler } from '../langchain';\nimport type { BaseChatModel, LangChainMessage } from '../langchain/types';\nimport { normalizeLangChainMessages } from '../langchain/utils';\nimport { startSpan } from '../trace';\nimport { LANGGRAPH_ORIGIN } from './constants';\nimport type { CompiledGraph, LangGraphOptions } from './types';\nimport {\n extractAgentNameFromParams,\n extractLLMFromParams,\n extractToolsFromCompiledGraph,\n mergeSentryCallback,\n setResponseAttributes,\n wrapToolsWithSpans,\n} from './utils';\n\nlet _insideCreateReactAgent = false;\n\nconst SENTRY_PATCHED = '__sentry_patched__';\n\n/**\n * Instruments StateGraph's compile method to create spans for agent creation and invocation\n *\n * Wraps the compile() method to:\n * - Create a `gen_ai.create_agent` span when compile() is called\n * - Automatically wrap the invoke() method on the returned compiled graph with a `gen_ai.invoke_agent` span\n *\n */\nexport function instrumentStateGraphCompile(\n originalCompile: (...args: unknown[]) => CompiledGraph,\n options: LangGraphOptions,\n): (...args: unknown[]) => CompiledGraph {\n if (Object.prototype.hasOwnProperty.call(originalCompile, SENTRY_PATCHED)) {\n return originalCompile;\n }\n\n const sentryHandler = createLangChainCallbackHandler(options);\n\n const wrapped = new Proxy(originalCompile, {\n apply(target, thisArg, args: unknown[]): CompiledGraph {\n // Skip when called from within createReactAgent to avoid duplicate instrumentation\n if (_insideCreateReactAgent) {\n return Reflect.apply(target, thisArg, args);\n }\n\n return startSpan(\n {\n op: 'gen_ai.create_agent',\n name: 'create_agent',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGGRAPH_ORIGIN,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'gen_ai.create_agent',\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'create_agent',\n },\n },\n span => {\n try {\n const compiledGraph = Reflect.apply(target, thisArg, args);\n const compileOptions = args.length > 0 ? (args[0] as Record<string, unknown>) : {};\n\n // Extract graph name\n if (compileOptions?.name && typeof compileOptions.name === 'string') {\n span.setAttribute(GEN_AI_AGENT_NAME_ATTRIBUTE, compileOptions.name);\n span.updateName(`create_agent ${compileOptions.name}`);\n }\n\n // Instrument agent invoke method on the compiled graph\n const originalInvoke = compiledGraph.invoke;\n if (originalInvoke && typeof originalInvoke === 'function') {\n compiledGraph.invoke = instrumentCompiledGraphInvoke(\n originalInvoke.bind(compiledGraph) as (...args: unknown[]) => Promise<unknown>,\n compiledGraph,\n compileOptions,\n options,\n undefined,\n sentryHandler,\n ) as typeof originalInvoke;\n }\n\n return compiledGraph;\n } catch (error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.langgraph.error',\n },\n });\n throw error;\n }\n },\n );\n },\n }) as (...args: unknown[]) => CompiledGraph;\n\n Object.defineProperty(wrapped, SENTRY_PATCHED, { value: true, enumerable: false });\n return wrapped;\n}\n\n/**\n * Instruments CompiledGraph's invoke method to create spans for agent invocation\n *\n * Creates a `gen_ai.invoke_agent` span when invoke() is called\n */\nfunction instrumentCompiledGraphInvoke(\n originalInvoke: (...args: unknown[]) => Promise<unknown>,\n graphInstance: CompiledGraph,\n compileOptions: Record<string, unknown>,\n options: LangGraphOptions,\n llm?: BaseChatModel | null,\n sentryCallbackHandler?: unknown,\n): (...args: unknown[]) => Promise<unknown> {\n return new Proxy(originalInvoke, {\n apply(target, thisArg, args: unknown[]): Promise<unknown> {\n const modelName = llm?.modelName ?? llm?.model;\n return startSpan(\n {\n op: 'gen_ai.invoke_agent',\n name: 'invoke_agent',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGGRAPH_ORIGIN,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE,\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'invoke_agent',\n },\n },\n async span => {\n try {\n const graphName = compileOptions?.name;\n\n if (graphName && typeof graphName === 'string') {\n span.setAttribute(GEN_AI_PIPELINE_NAME_ATTRIBUTE, graphName);\n span.setAttribute(GEN_AI_AGENT_NAME_ATTRIBUTE, graphName);\n span.updateName(`invoke_agent ${graphName}`);\n }\n\n if (modelName) {\n span.setAttribute(GEN_AI_REQUEST_MODEL_ATTRIBUTE, modelName);\n }\n\n // Extract thread_id from the config (second argument)\n // LangGraph uses config.configurable.thread_id for conversation/session linking\n const config = args.length > 1 ? (args[1] as Record<string, unknown> | undefined) : undefined;\n const configurable = config?.configurable as Record<string, unknown> | undefined;\n const threadId = configurable?.thread_id;\n if (threadId && typeof threadId === 'string') {\n span.setAttribute(GEN_AI_CONVERSATION_ID_ATTRIBUTE, threadId);\n }\n\n // Inject callback handler and agent name into invoke config\n if (sentryCallbackHandler) {\n const invokeConfig = (args[1] ?? {}) as Record<string, unknown>;\n args[1] = invokeConfig;\n\n const existingMetadata = (invokeConfig.metadata ?? {}) as Record<string, unknown>;\n invokeConfig.metadata = {\n ...existingMetadata,\n __sentry_langgraph__: true,\n ...(typeof graphName === 'string' ? { lc_agent_name: graphName } : {}),\n };\n\n invokeConfig.callbacks = mergeSentryCallback(invokeConfig.callbacks, sentryCallbackHandler);\n }\n\n // Extract available tools from the graph instance\n const tools = extractToolsFromCompiledGraph(graphInstance);\n if (tools) {\n span.setAttribute(GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE, JSON.stringify(tools));\n }\n\n // Parse input messages\n const recordInputs = options.recordInputs;\n const recordOutputs = options.recordOutputs;\n const inputMessages =\n args.length > 0 ? ((args[0] as { messages?: LangChainMessage[] } | null)?.messages ?? []) : [];\n\n if (inputMessages && recordInputs) {\n const normalizedMessages = normalizeLangChainMessages(inputMessages);\n const { systemInstructions, filteredMessages } = extractSystemInstructions(normalizedMessages);\n\n if (systemInstructions) {\n span.setAttribute(GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE, systemInstructions);\n }\n\n const enableTruncation = shouldEnableTruncation(options.enableTruncation);\n const filteredLength = Array.isArray(filteredMessages) ? filteredMessages.length : 0;\n span.setAttributes({\n [GEN_AI_INPUT_MESSAGES_ATTRIBUTE]: enableTruncation\n ? getTruncatedJsonString(filteredMessages)\n : getJsonString(filteredMessages),\n [GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE]: filteredLength,\n });\n }\n\n // Call original invoke\n const result = await Reflect.apply(target, thisArg, args);\n\n if (recordOutputs) {\n setResponseAttributes(span, inputMessages ?? null, result);\n }\n\n return result;\n } catch (error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.langgraph.error',\n },\n });\n throw error;\n }\n },\n );\n },\n }) as (...args: unknown[]) => Promise<unknown>;\n}\n\n/**\n * Instruments createReactAgent to create invoke_agent and execute_tool spans.\n */\nexport function instrumentCreateReactAgent(\n originalCreateReactAgent: (...args: unknown[]) => CompiledGraph,\n options?: LangGraphOptions,\n): (...args: unknown[]) => CompiledGraph {\n if (Object.prototype.hasOwnProperty.call(originalCreateReactAgent, SENTRY_PATCHED)) {\n return originalCreateReactAgent;\n }\n\n const resolvedOptions = resolveAIRecordingOptions(options);\n const sentryHandler = createLangChainCallbackHandler(resolvedOptions);\n\n const wrapped = new Proxy(originalCreateReactAgent, {\n apply(target, thisArg, args: unknown[]): CompiledGraph {\n const llm = extractLLMFromParams(args);\n const agentName = extractAgentNameFromParams(args);\n\n // Wrap tools with execute_tool spans (direct access gives us name, type, description)\n const params = args[0] as Record<string, unknown> | undefined;\n if (params && Array.isArray(params.tools) && params.tools.length > 0) {\n wrapToolsWithSpans(params.tools, resolvedOptions, agentName ?? undefined);\n }\n\n // Suppress StateGraph.compile instrumentation inside createReactAgent\n _insideCreateReactAgent = true;\n let compiledGraph: CompiledGraph;\n try {\n compiledGraph = Reflect.apply(target, thisArg, args);\n } finally {\n _insideCreateReactAgent = false;\n }\n\n // Wrap invoke() on the returned compiled graph\n const originalInvoke = compiledGraph.invoke;\n if (originalInvoke && typeof originalInvoke === 'function') {\n const compileOptions: Record<string, unknown> = {};\n if (agentName) {\n compileOptions.name = agentName;\n }\n\n compiledGraph.invoke = instrumentCompiledGraphInvoke(\n originalInvoke.bind(compiledGraph) as (...args: unknown[]) => Promise<unknown>,\n compiledGraph,\n compileOptions,\n resolvedOptions,\n llm,\n sentryHandler,\n ) as typeof originalInvoke;\n }\n\n return compiledGraph;\n },\n }) as (...args: unknown[]) => CompiledGraph;\n\n Object.defineProperty(wrapped, SENTRY_PATCHED, { value: true, enumerable: false });\n return wrapped;\n}\n\n/**\n * Directly instruments a StateGraph instance to add tracing spans\n *\n * This function can be used to manually instrument LangGraph StateGraph instances\n * in environments where automatic instrumentation is not available or desired.\n *\n * @param stateGraph - The StateGraph instance to instrument\n * @param options - Optional configuration for recording inputs/outputs\n *\n * @example\n * ```typescript\n * import { instrumentLangGraph } from '@sentry/cloudflare';\n * import { StateGraph } from '@langchain/langgraph';\n *\n * const graph = new StateGraph(MessagesAnnotation)\n * .addNode('agent', mockLlm)\n * .addEdge(START, 'agent')\n * .addEdge('agent', END);\n *\n * instrumentLangGraph(graph, { recordInputs: true, recordOutputs: true });\n * const compiled = graph.compile({ name: 'my_agent' });\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function instrumentLangGraph<T extends { compile: (...args: any[]) => any }>(\n stateGraph: T,\n options?: LangGraphOptions,\n): T {\n stateGraph.compile = instrumentStateGraphCompile(stateGraph.compile, resolveAIRecordingOptions(options));\n\n return stateGraph;\n}\n"],"names":["createLangChainCallbackHandler","startSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","LANGGRAPH_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_OP","GEN_AI_OPERATION_NAME_ATTRIBUTE","GEN_AI_AGENT_NAME_ATTRIBUTE","SPAN_STATUS_ERROR","captureException","GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE","GEN_AI_PIPELINE_NAME_ATTRIBUTE","GEN_AI_REQUEST_MODEL_ATTRIBUTE","GEN_AI_CONVERSATION_ID_ATTRIBUTE","mergeSentryCallback","extractToolsFromCompiledGraph","GEN_AI_REQUEST_AVAILABLE_TOOLS_ATTRIBUTE","normalizeLangChainMessages","extractSystemInstructions","GEN_AI_SYSTEM_INSTRUCTIONS_ATTRIBUTE","shouldEnableTruncation","GEN_AI_INPUT_MESSAGES_ATTRIBUTE","getTruncatedJsonString","getJsonString","GEN_AI_INPUT_MESSAGES_ORIGINAL_LENGTH_ATTRIBUTE","setResponseAttributes","resolveAIRecordingOptions","extractLLMFromParams","extractAgentNameFromParams","wrapToolsWithSpans"],"mappings":";;;;;;;;;;;;;AAqCA,IAAI,uBAAA,GAA0B,KAAK;;AAEnC,MAAM,cAAA,GAAiB,oBAAoB;;AAE3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,2BAA2B;AAC3C,EAAE,eAAe;AACjB,EAAE,OAAO;AACT,EAAyC;AACzC,EAAE,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,eAAe,EAAE,cAAc,CAAC,EAAE;AAC7E,IAAI,OAAO,eAAe;AAC1B,EAAE;;AAEF,EAAE,MAAM,aAAA,GAAgBA,oCAA8B,CAAC,OAAO,CAAC;;AAE/D,EAAE,MAAM,OAAA,GAAU,IAAI,KAAK,CAAC,eAAe,EAAE;AAC7C,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAA4B;AAC3D;AACA,MAAM,IAAI,uBAAuB,EAAE;AACnC,QAAQ,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;AACnD,MAAM;;AAEN,MAAM,OAAOC,eAAS;AACtB,QAAQ;AACR,UAAU,EAAE,EAAE,qBAAqB;AACnC,UAAU,IAAI,EAAE,cAAc;AAC9B,UAAU,UAAU,EAAE;AACtB,YAAY,CAACC,mDAAgC,GAAGC,0BAAgB;AAChE,YAAY,CAACC,+CAA4B,GAAG,qBAAqB;AACjE,YAAY,CAACC,+CAA+B,GAAG,cAAc;AAC7D,WAAW;AACX,SAAS;AACT,QAAQ,QAAQ;AAChB,UAAU,IAAI;AACd,YAAY,MAAM,aAAA,GAAgB,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;AACtE,YAAY,MAAM,cAAA,GAAiB,IAAI,CAAC,SAAS,CAAA,IAAK,IAAI,CAAC,CAAC,MAAgC,EAAE;;AAE9F;AACA,YAAY,IAAI,cAAc,EAAE,IAAA,IAAQ,OAAO,cAAc,CAAC,IAAA,KAAS,QAAQ,EAAE;AACjF,cAAc,IAAI,CAAC,YAAY,CAACC,2CAA2B,EAAE,cAAc,CAAC,IAAI,CAAC;AACjF,cAAc,IAAI,CAAC,UAAU,CAAC,CAAC,aAAa,EAAE,cAAc,CAAC,IAAI,CAAC,CAAA,CAAA;AACA,YAAA;;AAEA;AACA,YAAA,MAAA,cAAA,GAAA,aAAA,CAAA,MAAA;AACA,YAAA,IAAA,cAAA,IAAA,OAAA,cAAA,KAAA,UAAA,EAAA;AACA,cAAA,aAAA,CAAA,MAAA,GAAA,6BAAA;AACA,gBAAA,cAAA,CAAA,IAAA,CAAA,aAAA,CAAA;AACA,gBAAA,aAAA;AACA,gBAAA,cAAA;AACA,gBAAA,OAAA;AACA,gBAAA,SAAA;AACA,gBAAA,aAAA;AACA,eAAA;AACA,YAAA;;AAEA,YAAA,OAAA,aAAA;AACA,UAAA,CAAA,CAAA,OAAA,KAAA,EAAA;AACA,YAAA,IAAA,CAAA,SAAA,CAAA,EAAA,IAAA,EAAAC,4BAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,CAAA;AACA,YAAAC,yBAAA,CAAA,KAAA,EAAA;AACA,cAAA,SAAA,EAAA;AACA,gBAAA,OAAA,EAAA,KAAA;AACA,gBAAA,IAAA,EAAA,yBAAA;AACA,eAAA;AACA,aAAA,CAAA;AACA,YAAA,MAAA,KAAA;AACA,UAAA;AACA,QAAA,CAAA;AACA,OAAA;AACA,IAAA,CAAA;AACA,GAAA,CAAA;;AAEA,EAAA,MAAA,CAAA,cAAA,CAAA,OAAA,EAAA,cAAA,EAAA,EAAA,KAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,CAAA;AACA,EAAA,OAAA,OAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,SAAA,6BAAA;AACA,EAAA,cAAA;AACA,EAAA,aAAA;AACA,EAAA,cAAA;AACA,EAAA,OAAA;AACA,EAAA,GAAA;AACA,EAAA,qBAAA;AACA,EAAA;AACA,EAAA,OAAA,IAAA,KAAA,CAAA,cAAA,EAAA;AACA,IAAA,KAAA,CAAA,MAAA,EAAA,OAAA,EAAA,IAAA,EAAA;AACA,MAAA,MAAA,SAAA,GAAA,GAAA,EAAA,SAAA,IAAA,GAAA,EAAA,KAAA;AACA,MAAA,OAAAP,eAAA;AACA,QAAA;AACA,UAAA,EAAA,EAAA,qBAAA;AACA,UAAA,IAAA,EAAA,cAAA;AACA,UAAA,UAAA,EAAA;AACA,YAAA,CAAAC,mDAAA,GAAAC,0BAAA;AACA,YAAA,CAAAC,+CAAA,GAAAK,uDAAA;AACA,YAAA,CAAAJ,+CAAA,GAAA,cAAA;AACA,WAAA;AACA,SAAA;AACA,QAAA,MAAA,IAAA,IAAA;AACA,UAAA,IAAA;AACA,YAAA,MAAA,SAAA,GAAA,cAAA,EAAA,IAAA;;AAEA,YAAA,IAAA,SAAA,IAAA,OAAA,SAAA,KAAA,QAAA,EAAA;AACA,cAAA,IAAA,CAAA,YAAA,CAAAK,8CAAA,EAAA,SAAA,CAAA;AACA,cAAA,IAAA,CAAA,YAAA,CAAAJ,2CAAA,EAAA,SAAA,CAAA;AACA,cAAA,IAAA,CAAA,UAAA,CAAA,CAAA,aAAA,EAAA,SAAA,CAAA,CAAA,CAAA;AACA,YAAA;;AAEA,YAAA,IAAA,SAAA,EAAA;AACA,cAAA,IAAA,CAAA,YAAA,CAAAK,8CAAA,EAAA,SAAA,CAAA;AACA,YAAA;;AAEA;AACA;AACA,YAAA,MAAA,MAAA,GAAA,IAAA,CAAA,MAAA,GAAA,CAAA,IAAA,IAAA,CAAA,CAAA,CAAA,KAAA,SAAA;AACA,YAAA,MAAA,YAAA,GAAA,MAAA,EAAA,YAAA;AACA,YAAA,MAAA,QAAA,GAAA,YAAA,EAAA,SAAA;AACA,YAAA,IAAA,QAAA,IAAA,OAAA,QAAA,KAAA,QAAA,EAAA;AACA,cAAA,IAAA,CAAA,YAAA,CAAAC,gDAAA,EAAA,QAAA,CAAA;AACA,YAAA;;AAEA;AACA,YAAA,IAAA,qBAAA,EAAA;AACA,cAAA,MAAA,YAAA,IAAA,IAAA,CAAA,CAAA,CAAA,IAAA,EAAA,CAAA;AACA,cAAA,IAAA,CAAA,CAAA,CAAA,GAAA,YAAA;;AAEA,cAAA,MAAA,gBAAA,IAAA,YAAA,CAAA,QAAA,IAAA,EAAA,CAAA;AACA,cAAA,YAAA,CAAA,QAAA,GAAA;AACA,gBAAA,GAAA,gBAAA;AACA,gBAAA,oBAAA,EAAA,IAAA;AACA,gBAAA,IAAA,OAAA,SAAA,KAAA,QAAA,GAAA,EAAA,aAAA,EAAA,SAAA,EAAA,GAAA,EAAA,CAAA;AACA,eAAA;;AAEA,cAAA,YAAA,CAAA,SAAA,GAAAC,2BAAA,CAAA,YAAA,CAAA,SAAA,EAAA,qBAAA,CAAA;AACA,YAAA;;AAEA;AACA,YAAA,MAAA,KAAA,GAAAC,qCAAA,CAAA,aAAA,CAAA;AACA,YAAA,IAAA,KAAA,EAAA;AACA,cAAA,IAAA,CAAA,YAAA,CAAAC,wDAAA,EAAA,IAAA,CAAA,SAAA,CAAA,KAAA,CAAA,CAAA;AACA,YAAA;;AAEA;AACA,YAAA,MAAA,YAAA,GAAA,OAAA,CAAA,YAAA;AACA,YAAA,MAAA,aAAA,GAAA,OAAA,CAAA,aAAA;AACA,YAAA,MAAA,aAAA;AACA,cAAA,IAAA,CAAA,MAAA,GAAA,CAAA,IAAA,CAAA,IAAA,CAAA,CAAA,CAAA,IAAA,QAAA,IAAA,EAAA,IAAA,EAAA;;AAEA,YAAA,IAAA,aAAA,IAAA,YAAA,EAAA;AACA,cAAA,MAAA,kBAAA,GAAAC,kCAAA,CAAA,aAAA,CAAA;AACA,cAAA,MAAA,EAAA,kBAAA,EAAA,gBAAA,EAAA,GAAAC,+BAAA,CAAA,kBAAA,CAAA;;AAEA,cAAA,IAAA,kBAAA,EAAA;AACA,gBAAA,IAAA,CAAA,YAAA,CAAAC,oDAAA,EAAA,kBAAA,CAAA;AACA,cAAA;;AAEA,cAAA,MAAA,gBAAA,GAAAC,4BAAA,CAAA,OAAA,CAAA,gBAAA,CAAA;AACA,cAAA,MAAA,cAAA,GAAA,KAAA,CAAA,OAAA,CAAA,gBAAA,CAAA,GAAA,gBAAA,CAAA,MAAA,GAAA,CAAA;AACA,cAAA,IAAA,CAAA,aAAA,CAAA;AACA,gBAAA,CAAAC,+CAAA,GAAA;AACA,oBAAAC,4BAAA,CAAA,gBAAA;AACA,oBAAAC,mBAAA,CAAA,gBAAA,CAAA;AACA,gBAAA,CAAAC,+DAAA,GAAA,cAAA;AACA,eAAA,CAAA;AACA,YAAA;;AAEA;AACA,YAAA,MAAA,MAAA,GAAA,MAAA,OAAA,CAAA,KAAA,CAAA,MAAA,EAAA,OAAA,EAAA,IAAA,CAAA;;AAEA,YAAA,IAAA,aAAA,EAAA;AACA,cAAAC,6BAAA,CAAA,IAAA,EAAA,aAAA,IAAA,IAAA,EAAA,MAAA,CAAA;AACA,YAAA;;AAEA,YAAA,OAAA,MAAA;AACA,UAAA,CAAA,CAAA,OAAA,KAAA,EAAA;AACA,YAAA,IAAA,CAAA,SAAA,CAAA,EAAA,IAAA,EAAAjB,4BAAA,EAAA,OAAA,EAAA,gBAAA,EAAA,CAAA;AACA,YAAAC,yBAAA,CAAA,KAAA,EAAA;AACA,cAAA,SAAA,EAAA;AACA,gBAAA,OAAA,EAAA,KAAA;AACA,gBAAA,IAAA,EAAA,yBAAA;AACA,eAAA;AACA,aAAA,CAAA;AACA,YAAA,MAAA,KAAA;AACA,UAAA;AACA,QAAA,CAAA;AACA,OAAA;AACA,IAAA,CAAA;AACA,GAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA,SAAA,0BAAA;AACA,EAAA,wBAAA;AACA,EAAA,OAAA;AACA,EAAA;AACA,EAAA,IAAA,MAAA,CAAA,SAAA,CAAA,cAAA,CAAA,IAAA,CAAA,wBAAA,EAAA,cAAA,CAAA,EAAA;AACA,IAAA,OAAA,wBAAA;AACA,EAAA;;AAEA,EAAA,MAAA,eAAA,GAAAiB,+BAAA,CAAA,OAAA,CAAA;AACA,EAAA,MAAA,aAAA,GAAAzB,oCAAA,CAAA,eAAA,CAAA;;AAEA,EAAA,MAAA,OAAA,GAAA,IAAA,KAAA,CAAA,wBAAA,EAAA;AACA,IAAA,KAAA,CAAA,MAAA,EAAA,OAAA,EAAA,IAAA,EAAA;AACA,MAAA,MAAA,GAAA,GAAA0B,4BAAA,CAAA,IAAA,CAAA;AACA,MAAA,MAAA,SAAA,GAAAC,kCAAA,CAAA,IAAA,CAAA;;AAEA;AACA,MAAA,MAAA,MAAA,GAAA,IAAA,CAAA,CAAA,CAAA;AACA,MAAA,IAAA,MAAA,IAAA,KAAA,CAAA,OAAA,CAAA,MAAA,CAAA,KAAA,CAAA,IAAA,MAAA,CAAA,KAAA,CAAA,MAAA,GAAA,CAAA,EAAA;AACA,QAAAC,0BAAA,CAAA,MAAA,CAAA,KAAA,EAAA,eAAA,EAAA,SAAA,IAAA,SAAA,CAAA;AACA,MAAA;;AAEA;AACA,MAAA,uBAAA,GAAA,IAAA;AACA,MAAA,IAAA,aAAA;AACA,MAAA,IAAA;AACA,QAAA,aAAA,GAAA,OAAA,CAAA,KAAA,CAAA,MAAA,EAAA,OAAA,EAAA,IAAA,CAAA;AACA,MAAA,CAAA,SAAA;AACA,QAAA,uBAAA,GAAA,KAAA;AACA,MAAA;;AAEA;AACA,MAAA,MAAA,cAAA,GAAA,aAAA,CAAA,MAAA;AACA,MAAA,IAAA,cAAA,IAAA,OAAA,cAAA,KAAA,UAAA,EAAA;AACA,QAAA,MAAA,cAAA,GAAA,EAAA;AACA,QAAA,IAAA,SAAA,EAAA;AACA,UAAA,cAAA,CAAA,IAAA,GAAA,SAAA;AACA,QAAA;;AAEA,QAAA,aAAA,CAAA,MAAA,GAAA,6BAAA;AACA,UAAA,cAAA,CAAA,IAAA,CAAA,aAAA,CAAA;AACA,UAAA,aAAA;AACA,UAAA,cAAA;AACA,UAAA,eAAA;AACA,UAAA,GAAA;AACA,UAAA,aAAA;AACA,SAAA;AACA,MAAA;;AAEA,MAAA,OAAA,aAAA;AACA,IAAA,CAAA;AACA,GAAA,CAAA;;AAEA,EAAA,MAAA,CAAA,cAAA,CAAA,OAAA,EAAA,cAAA,EAAA,EAAA,KAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,CAAA;AACA,EAAA,OAAA,OAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAA,mBAAA;AACA,EAAA,UAAA;AACA,EAAA,OAAA;AACA,EAAA;AACA,EAAA,UAAA,CAAA,OAAA,GAAA,2BAAA,CAAA,UAAA,CAAA,OAAA,EAAAH,+BAAA,CAAA,OAAA,CAAA,CAAA;;AAEA,EAAA,OAAA,UAAA;AACA;;;;;;"}
@@ -1,7 +1,147 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
+ const _exports = require('../../exports.js');
4
+ const semanticAttributes = require('../../semanticAttributes.js');
5
+ const spanstatus = require('../spanstatus.js');
6
+ const trace = require('../trace.js');
3
7
  const genAiAttributes = require('../ai/gen-ai-attributes.js');
4
8
  const utils = require('../langchain/utils.js');
9
+ const constants = require('./constants.js');
10
+
11
+ /**
12
+ * Extract LLM model object from createReactAgent params
13
+ */
14
+ function extractLLMFromParams(args) {
15
+ const arg = args[0];
16
+ if (typeof arg !== 'object' || !arg || !('llm' in arg) || !arg.llm || typeof arg.llm !== 'object') {
17
+ return null;
18
+ }
19
+ const llm = arg.llm ;
20
+ if (typeof llm.modelName !== 'string' && typeof llm.model !== 'string') {
21
+ return null;
22
+ }
23
+ return llm;
24
+ }
25
+
26
+ /**
27
+ * Extract agent name from createReactAgent params
28
+ */
29
+ function extractAgentNameFromParams(args) {
30
+ const arg = args[0];
31
+ if (typeof arg === 'object' && !!arg && 'name' in arg && typeof arg.name === 'string') {
32
+ return arg.name;
33
+ }
34
+ return null;
35
+ }
36
+
37
+ /**
38
+ * Wraps an array of LangChain tools so each invocation creates a gen_ai.execute_tool span.
39
+ *
40
+ * Wraps each tool's invoke() method in place. A marker prevents double-wrapping.
41
+ */
42
+ function wrapToolsWithSpans(tools, options, agentName) {
43
+ const SENTRY_WRAPPED = '__sentry_tool_wrapped__';
44
+
45
+ for (const tool of tools) {
46
+ if (!tool || typeof tool !== 'object') {
47
+ continue;
48
+ }
49
+
50
+ const t = tool ;
51
+ const originalInvoke = t.invoke;
52
+ if (typeof originalInvoke !== 'function' || Object.prototype.hasOwnProperty.call(t, SENTRY_WRAPPED)) {
53
+ continue;
54
+ }
55
+
56
+ const toolName = typeof t.name === 'string' ? t.name : 'unknown_tool';
57
+ const toolDescription = typeof t.description === 'string' ? t.description : undefined;
58
+
59
+ const wrappedInvoke = new Proxy(originalInvoke , {
60
+ apply(target, thisArg, args) {
61
+ const spanAttributes = {
62
+ [semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: constants.LANGGRAPH_ORIGIN,
63
+ [semanticAttributes.SEMANTIC_ATTRIBUTE_SENTRY_OP]: genAiAttributes.GEN_AI_EXECUTE_TOOL_OPERATION_ATTRIBUTE,
64
+ [genAiAttributes.GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'execute_tool',
65
+ [genAiAttributes.GEN_AI_TOOL_NAME_ATTRIBUTE]: toolName,
66
+ [genAiAttributes.GEN_AI_TOOL_TYPE_ATTRIBUTE]: 'function',
67
+ };
68
+
69
+ // Read agent name from LangChain's propagated config metadata at call time,
70
+ // so shared tools get the correct agent name for each invocation
71
+ const callConfig = args[1] ;
72
+ const callAgentName = (callConfig?.metadata )?.lc_agent_name ?? agentName;
73
+ if (typeof callAgentName === 'string') {
74
+ spanAttributes[genAiAttributes.GEN_AI_AGENT_NAME_ATTRIBUTE] = callAgentName;
75
+ }
76
+
77
+ if (toolDescription) {
78
+ spanAttributes[genAiAttributes.GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE] = toolDescription;
79
+ }
80
+
81
+ // LangGraph ToolNode passes { name, args, id, type: "tool_call" }
82
+ const input = args[0] ;
83
+ if (typeof input === 'object' && !!input) {
84
+ if ('id' in input && typeof input.id === 'string') {
85
+ spanAttributes[genAiAttributes.GEN_AI_TOOL_CALL_ID_ATTRIBUTE] = input.id;
86
+ }
87
+
88
+ if (options.recordInputs) {
89
+ const toolArgs = 'args' in input && typeof input.args === 'object' ? input.args : input;
90
+ try {
91
+ spanAttributes[genAiAttributes.GEN_AI_TOOL_INPUT_ATTRIBUTE] = JSON.stringify(toolArgs);
92
+ } catch {
93
+ // skip if not serializable
94
+ }
95
+ }
96
+ }
97
+
98
+ return trace.startSpan(
99
+ {
100
+ op: genAiAttributes.GEN_AI_EXECUTE_TOOL_OPERATION_ATTRIBUTE,
101
+ name: `execute_tool ${toolName}`,
102
+ attributes: spanAttributes,
103
+ },
104
+ async span => {
105
+ try {
106
+ const result = await Reflect.apply(target, thisArg, args);
107
+
108
+ if (options.recordOutputs) {
109
+ try {
110
+ // ToolMessage objects wrap the result in .content
111
+ const resultObj = result ;
112
+ const content =
113
+ resultObj && typeof resultObj === 'object' && 'content' in resultObj ? resultObj.content : result;
114
+ span.setAttribute(
115
+ genAiAttributes.GEN_AI_TOOL_OUTPUT_ATTRIBUTE,
116
+ typeof content === 'string' ? content : JSON.stringify(content),
117
+ );
118
+ } catch {
119
+ // skip if not serializable
120
+ }
121
+ }
122
+
123
+ return result;
124
+ } catch (error) {
125
+ span.setStatus({ code: spanstatus.SPAN_STATUS_ERROR, message: 'internal_error' });
126
+ _exports.captureException(error, {
127
+ mechanism: {
128
+ handled: false,
129
+ type: 'auto.ai.langgraph.error',
130
+ },
131
+ });
132
+ throw error;
133
+ }
134
+ },
135
+ );
136
+ },
137
+ });
138
+
139
+ t.invoke = wrappedInvoke;
140
+ Object.defineProperty(t, SENTRY_WRAPPED, { value: true, enumerable: false });
141
+ }
142
+
143
+ return tools;
144
+ }
5
145
 
6
146
  /**
7
147
  * Extract tool calls from messages
@@ -175,9 +315,37 @@ function setResponseAttributes(span, inputMessages, result) {
175
315
  }
176
316
  }
177
317
 
318
+ /** Merge `sentryHandler` into a langchain `callbacks` value (`BaseCallbackHandler[]` or `BaseCallbackManager`). */
319
+ function mergeSentryCallback(existing, sentryHandler) {
320
+ if (!existing) {
321
+ return [sentryHandler];
322
+ }
323
+
324
+ if (Array.isArray(existing)) {
325
+ if (existing.includes(sentryHandler)) {
326
+ return existing;
327
+ }
328
+ return [...existing, sentryHandler];
329
+ }
330
+
331
+ const manager = existing ;
332
+ if (typeof manager.addHandler === 'function') {
333
+ const alreadyAdded = Array.isArray(manager.handlers) && manager.handlers.includes(sentryHandler);
334
+ if (!alreadyAdded) {
335
+ manager.addHandler(sentryHandler);
336
+ }
337
+ }
338
+
339
+ return existing;
340
+ }
341
+
342
+ exports.extractAgentNameFromParams = extractAgentNameFromParams;
343
+ exports.extractLLMFromParams = extractLLMFromParams;
178
344
  exports.extractModelMetadata = extractModelMetadata;
179
345
  exports.extractTokenUsageFromMessage = extractTokenUsageFromMessage;
180
346
  exports.extractToolCalls = extractToolCalls;
181
347
  exports.extractToolsFromCompiledGraph = extractToolsFromCompiledGraph;
348
+ exports.mergeSentryCallback = mergeSentryCallback;
182
349
  exports.setResponseAttributes = setResponseAttributes;
350
+ exports.wrapToolsWithSpans = wrapToolsWithSpans;
183
351
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../../src/tracing/langgraph/utils.ts"],"sourcesContent":["import type { Span } from '../../types-hoist/span';\nimport {\n GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE,\n GEN_AI_RESPONSE_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_TEXT_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport type { LangChainMessage } from '../langchain/types';\nimport { normalizeLangChainMessages } from '../langchain/utils';\nimport type { CompiledGraph, LangGraphTool } from './types';\n\n/**\n * Extract tool calls from messages\n */\nexport function extractToolCalls(messages: Array<Record<string, unknown>> | null): unknown[] | null {\n if (!messages || messages.length === 0) {\n return null;\n }\n\n const toolCalls: unknown[] = [];\n\n for (const message of messages) {\n if (message && typeof message === 'object') {\n const msgToolCalls = message.tool_calls;\n if (msgToolCalls && Array.isArray(msgToolCalls)) {\n toolCalls.push(...msgToolCalls);\n }\n }\n }\n\n return toolCalls.length > 0 ? toolCalls : null;\n}\n\n/**\n * Extract token usage from a message's usage_metadata or response_metadata\n * Returns token counts without setting span attributes\n */\nexport function extractTokenUsageFromMessage(message: LangChainMessage): {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n} {\n const msg = message as Record<string, unknown>;\n let inputTokens = 0;\n let outputTokens = 0;\n let totalTokens = 0;\n\n // Extract from usage_metadata (newer format)\n if (msg.usage_metadata && typeof msg.usage_metadata === 'object') {\n const usage = msg.usage_metadata as Record<string, unknown>;\n if (typeof usage.input_tokens === 'number') {\n inputTokens = usage.input_tokens;\n }\n if (typeof usage.output_tokens === 'number') {\n outputTokens = usage.output_tokens;\n }\n if (typeof usage.total_tokens === 'number') {\n totalTokens = usage.total_tokens;\n }\n return { inputTokens, outputTokens, totalTokens };\n }\n\n // Fallback: Extract from response_metadata.tokenUsage\n if (msg.response_metadata && typeof msg.response_metadata === 'object') {\n const metadata = msg.response_metadata as Record<string, unknown>;\n if (metadata.tokenUsage && typeof metadata.tokenUsage === 'object') {\n const tokenUsage = metadata.tokenUsage as Record<string, unknown>;\n if (typeof tokenUsage.promptTokens === 'number') {\n inputTokens = tokenUsage.promptTokens;\n }\n if (typeof tokenUsage.completionTokens === 'number') {\n outputTokens = tokenUsage.completionTokens;\n }\n if (typeof tokenUsage.totalTokens === 'number') {\n totalTokens = tokenUsage.totalTokens;\n }\n }\n }\n\n return { inputTokens, outputTokens, totalTokens };\n}\n\n/**\n * Extract model and finish reason from a message's response_metadata\n */\nexport function extractModelMetadata(span: Span, message: LangChainMessage): void {\n const msg = message as Record<string, unknown>;\n\n if (msg.response_metadata && typeof msg.response_metadata === 'object') {\n const metadata = msg.response_metadata as Record<string, unknown>;\n\n if (metadata.model_name && typeof metadata.model_name === 'string') {\n span.setAttribute(GEN_AI_RESPONSE_MODEL_ATTRIBUTE, metadata.model_name);\n }\n\n if (metadata.finish_reason && typeof metadata.finish_reason === 'string') {\n span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE, [metadata.finish_reason]);\n }\n }\n}\n\n/**\n * Extract tools from compiled graph structure\n *\n * Tools are stored in: compiledGraph.builder.nodes.tools.runnable.tools\n */\nexport function extractToolsFromCompiledGraph(compiledGraph: CompiledGraph): unknown[] | null {\n if (!compiledGraph.builder?.nodes?.tools?.runnable?.tools) {\n return null;\n }\n\n const tools = compiledGraph.builder?.nodes?.tools?.runnable?.tools;\n\n if (!tools || !Array.isArray(tools) || tools.length === 0) {\n return null;\n }\n\n // Extract name, description, and schema from each tool's lc_kwargs\n return tools.map((tool: LangGraphTool) => ({\n name: tool.lc_kwargs?.name,\n description: tool.lc_kwargs?.description,\n schema: tool.lc_kwargs?.schema,\n }));\n}\n\n/**\n * Set response attributes on the span\n */\nexport function setResponseAttributes(span: Span, inputMessages: LangChainMessage[] | null, result: unknown): void {\n // Extract messages from result\n const resultObj = result as { messages?: LangChainMessage[] } | undefined;\n const outputMessages = resultObj?.messages;\n\n if (!outputMessages || !Array.isArray(outputMessages)) {\n return;\n }\n\n // Get new messages (delta between input and output)\n const inputCount = inputMessages?.length ?? 0;\n const newMessages = outputMessages.length > inputCount ? outputMessages.slice(inputCount) : [];\n\n if (newMessages.length === 0) {\n return;\n }\n\n // Extract and set tool calls from new messages BEFORE normalization\n // (normalization strips tool_calls, so we need to extract them first)\n const toolCalls = extractToolCalls(newMessages as Array<Record<string, unknown>>);\n if (toolCalls) {\n span.setAttribute(GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE, JSON.stringify(toolCalls));\n }\n\n // Normalize the new messages\n const normalizedNewMessages = normalizeLangChainMessages(newMessages);\n span.setAttribute(GEN_AI_RESPONSE_TEXT_ATTRIBUTE, JSON.stringify(normalizedNewMessages));\n\n // Accumulate token usage across all messages\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalTokens = 0;\n\n // Extract metadata from messages\n for (const message of newMessages) {\n // Accumulate token usage\n const tokens = extractTokenUsageFromMessage(message);\n totalInputTokens += tokens.inputTokens;\n totalOutputTokens += tokens.outputTokens;\n totalTokens += tokens.totalTokens;\n\n // Extract model metadata (last message's metadata wins for model/finish_reason)\n extractModelMetadata(span, message);\n }\n\n // Set accumulated token usage on span\n if (totalInputTokens > 0) {\n span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE, totalInputTokens);\n }\n if (totalOutputTokens > 0) {\n span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE, totalOutputTokens);\n }\n if (totalTokens > 0) {\n span.setAttribute(GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE, totalTokens);\n }\n}\n"],"names":["GEN_AI_RESPONSE_MODEL_ATTRIBUTE","GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE","GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE","normalizeLangChainMessages","GEN_AI_RESPONSE_TEXT_ATTRIBUTE","GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE"],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["../../../../src/tracing/langgraph/utils.ts"],"sourcesContent":["import { captureException } from '../../exports';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes';\nimport { SPAN_STATUS_ERROR } from '../../tracing';\nimport type { Span, SpanAttributes } from '../../types-hoist/span';\nimport {\n GEN_AI_AGENT_NAME_ATTRIBUTE,\n GEN_AI_EXECUTE_TOOL_OPERATION_ATTRIBUTE,\n GEN_AI_OPERATION_NAME_ATTRIBUTE,\n GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE,\n GEN_AI_RESPONSE_MODEL_ATTRIBUTE,\n GEN_AI_RESPONSE_TEXT_ATTRIBUTE,\n GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE,\n GEN_AI_TOOL_CALL_ID_ATTRIBUTE,\n GEN_AI_TOOL_INPUT_ATTRIBUTE,\n GEN_AI_TOOL_OUTPUT_ATTRIBUTE,\n GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE,\n GEN_AI_TOOL_NAME_ATTRIBUTE,\n GEN_AI_TOOL_TYPE_ATTRIBUTE,\n GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE,\n GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE,\n} from '../ai/gen-ai-attributes';\nimport type { BaseChatModel, LangChainMessage } from '../langchain/types';\nimport { normalizeLangChainMessages } from '../langchain/utils';\nimport { startSpan } from '../trace';\nimport { LANGGRAPH_ORIGIN } from './constants';\nimport type { CompiledGraph, LangGraphOptions, LangGraphTool } from './types';\n\n/**\n * Extract LLM model object from createReactAgent params\n */\nexport function extractLLMFromParams(args: unknown[]): BaseChatModel | null {\n const arg = args[0];\n if (typeof arg !== 'object' || !arg || !('llm' in arg) || !arg.llm || typeof arg.llm !== 'object') {\n return null;\n }\n const llm = arg.llm as BaseChatModel;\n if (typeof llm.modelName !== 'string' && typeof llm.model !== 'string') {\n return null;\n }\n return llm;\n}\n\n/**\n * Extract agent name from createReactAgent params\n */\nexport function extractAgentNameFromParams(args: unknown[]): string | null {\n const arg = args[0];\n if (typeof arg === 'object' && !!arg && 'name' in arg && typeof arg.name === 'string') {\n return arg.name;\n }\n return null;\n}\n\n/**\n * Wraps an array of LangChain tools so each invocation creates a gen_ai.execute_tool span.\n *\n * Wraps each tool's invoke() method in place. A marker prevents double-wrapping.\n */\nexport function wrapToolsWithSpans(tools: unknown[], options: LangGraphOptions, agentName?: string): unknown[] {\n const SENTRY_WRAPPED = '__sentry_tool_wrapped__';\n\n for (const tool of tools) {\n if (!tool || typeof tool !== 'object') {\n continue;\n }\n\n const t = tool as Record<string, unknown>;\n const originalInvoke = t.invoke;\n if (typeof originalInvoke !== 'function' || Object.prototype.hasOwnProperty.call(t, SENTRY_WRAPPED)) {\n continue;\n }\n\n const toolName = typeof t.name === 'string' ? t.name : 'unknown_tool';\n const toolDescription = typeof t.description === 'string' ? t.description : undefined;\n\n const wrappedInvoke = new Proxy(originalInvoke as (...args: unknown[]) => unknown, {\n apply(target, thisArg, args: unknown[]): unknown {\n const spanAttributes: SpanAttributes = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: LANGGRAPH_ORIGIN,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: GEN_AI_EXECUTE_TOOL_OPERATION_ATTRIBUTE,\n [GEN_AI_OPERATION_NAME_ATTRIBUTE]: 'execute_tool',\n [GEN_AI_TOOL_NAME_ATTRIBUTE]: toolName,\n [GEN_AI_TOOL_TYPE_ATTRIBUTE]: 'function',\n };\n\n // Read agent name from LangChain's propagated config metadata at call time,\n // so shared tools get the correct agent name for each invocation\n const callConfig = args[1] as Record<string, unknown> | undefined;\n const callAgentName = (callConfig?.metadata as Record<string, unknown>)?.lc_agent_name ?? agentName;\n if (typeof callAgentName === 'string') {\n spanAttributes[GEN_AI_AGENT_NAME_ATTRIBUTE] = callAgentName;\n }\n\n if (toolDescription) {\n spanAttributes[GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE] = toolDescription;\n }\n\n // LangGraph ToolNode passes { name, args, id, type: \"tool_call\" }\n const input = args[0] as Record<string, unknown> | undefined;\n if (typeof input === 'object' && !!input) {\n if ('id' in input && typeof input.id === 'string') {\n spanAttributes[GEN_AI_TOOL_CALL_ID_ATTRIBUTE] = input.id;\n }\n\n if (options.recordInputs) {\n const toolArgs = 'args' in input && typeof input.args === 'object' ? input.args : input;\n try {\n spanAttributes[GEN_AI_TOOL_INPUT_ATTRIBUTE] = JSON.stringify(toolArgs);\n } catch {\n // skip if not serializable\n }\n }\n }\n\n return startSpan(\n {\n op: GEN_AI_EXECUTE_TOOL_OPERATION_ATTRIBUTE,\n name: `execute_tool ${toolName}`,\n attributes: spanAttributes,\n },\n async span => {\n try {\n const result = await Reflect.apply(target, thisArg, args);\n\n if (options.recordOutputs) {\n try {\n // ToolMessage objects wrap the result in .content\n const resultObj = result as Record<string, unknown> | undefined;\n const content =\n resultObj && typeof resultObj === 'object' && 'content' in resultObj ? resultObj.content : result;\n span.setAttribute(\n GEN_AI_TOOL_OUTPUT_ATTRIBUTE,\n typeof content === 'string' ? content : JSON.stringify(content),\n );\n } catch {\n // skip if not serializable\n }\n }\n\n return result;\n } catch (error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureException(error, {\n mechanism: {\n handled: false,\n type: 'auto.ai.langgraph.error',\n },\n });\n throw error;\n }\n },\n );\n },\n });\n\n t.invoke = wrappedInvoke;\n Object.defineProperty(t, SENTRY_WRAPPED, { value: true, enumerable: false });\n }\n\n return tools;\n}\n\n/**\n * Extract tool calls from messages\n */\nexport function extractToolCalls(messages: Array<Record<string, unknown>> | null): unknown[] | null {\n if (!messages || messages.length === 0) {\n return null;\n }\n\n const toolCalls: unknown[] = [];\n\n for (const message of messages) {\n if (message && typeof message === 'object') {\n const msgToolCalls = message.tool_calls;\n if (msgToolCalls && Array.isArray(msgToolCalls)) {\n toolCalls.push(...msgToolCalls);\n }\n }\n }\n\n return toolCalls.length > 0 ? toolCalls : null;\n}\n\n/**\n * Extract token usage from a message's usage_metadata or response_metadata\n * Returns token counts without setting span attributes\n */\nexport function extractTokenUsageFromMessage(message: LangChainMessage): {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n} {\n const msg = message as Record<string, unknown>;\n let inputTokens = 0;\n let outputTokens = 0;\n let totalTokens = 0;\n\n // Extract from usage_metadata (newer format)\n if (msg.usage_metadata && typeof msg.usage_metadata === 'object') {\n const usage = msg.usage_metadata as Record<string, unknown>;\n if (typeof usage.input_tokens === 'number') {\n inputTokens = usage.input_tokens;\n }\n if (typeof usage.output_tokens === 'number') {\n outputTokens = usage.output_tokens;\n }\n if (typeof usage.total_tokens === 'number') {\n totalTokens = usage.total_tokens;\n }\n return { inputTokens, outputTokens, totalTokens };\n }\n\n // Fallback: Extract from response_metadata.tokenUsage\n if (msg.response_metadata && typeof msg.response_metadata === 'object') {\n const metadata = msg.response_metadata as Record<string, unknown>;\n if (metadata.tokenUsage && typeof metadata.tokenUsage === 'object') {\n const tokenUsage = metadata.tokenUsage as Record<string, unknown>;\n if (typeof tokenUsage.promptTokens === 'number') {\n inputTokens = tokenUsage.promptTokens;\n }\n if (typeof tokenUsage.completionTokens === 'number') {\n outputTokens = tokenUsage.completionTokens;\n }\n if (typeof tokenUsage.totalTokens === 'number') {\n totalTokens = tokenUsage.totalTokens;\n }\n }\n }\n\n return { inputTokens, outputTokens, totalTokens };\n}\n\n/**\n * Extract model and finish reason from a message's response_metadata\n */\nexport function extractModelMetadata(span: Span, message: LangChainMessage): void {\n const msg = message as Record<string, unknown>;\n\n if (msg.response_metadata && typeof msg.response_metadata === 'object') {\n const metadata = msg.response_metadata as Record<string, unknown>;\n\n if (metadata.model_name && typeof metadata.model_name === 'string') {\n span.setAttribute(GEN_AI_RESPONSE_MODEL_ATTRIBUTE, metadata.model_name);\n }\n\n if (metadata.finish_reason && typeof metadata.finish_reason === 'string') {\n span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE, [metadata.finish_reason]);\n }\n }\n}\n\n/**\n * Extract tools from compiled graph structure\n *\n * Tools are stored in: compiledGraph.builder.nodes.tools.runnable.tools\n */\nexport function extractToolsFromCompiledGraph(compiledGraph: CompiledGraph): unknown[] | null {\n if (!compiledGraph.builder?.nodes?.tools?.runnable?.tools) {\n return null;\n }\n\n const tools = compiledGraph.builder?.nodes?.tools?.runnable?.tools;\n\n if (!tools || !Array.isArray(tools) || tools.length === 0) {\n return null;\n }\n\n // Extract name, description, and schema from each tool's lc_kwargs\n return tools.map((tool: LangGraphTool) => ({\n name: tool.lc_kwargs?.name,\n description: tool.lc_kwargs?.description,\n schema: tool.lc_kwargs?.schema,\n }));\n}\n\n/**\n * Set response attributes on the span\n */\nexport function setResponseAttributes(span: Span, inputMessages: LangChainMessage[] | null, result: unknown): void {\n // Extract messages from result\n const resultObj = result as { messages?: LangChainMessage[] } | undefined;\n const outputMessages = resultObj?.messages;\n\n if (!outputMessages || !Array.isArray(outputMessages)) {\n return;\n }\n\n // Get new messages (delta between input and output)\n const inputCount = inputMessages?.length ?? 0;\n const newMessages = outputMessages.length > inputCount ? outputMessages.slice(inputCount) : [];\n\n if (newMessages.length === 0) {\n return;\n }\n\n // Extract and set tool calls from new messages BEFORE normalization\n // (normalization strips tool_calls, so we need to extract them first)\n const toolCalls = extractToolCalls(newMessages as Array<Record<string, unknown>>);\n if (toolCalls) {\n span.setAttribute(GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE, JSON.stringify(toolCalls));\n }\n\n // Normalize the new messages\n const normalizedNewMessages = normalizeLangChainMessages(newMessages);\n span.setAttribute(GEN_AI_RESPONSE_TEXT_ATTRIBUTE, JSON.stringify(normalizedNewMessages));\n\n // Accumulate token usage across all messages\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalTokens = 0;\n\n // Extract metadata from messages\n for (const message of newMessages) {\n // Accumulate token usage\n const tokens = extractTokenUsageFromMessage(message);\n totalInputTokens += tokens.inputTokens;\n totalOutputTokens += tokens.outputTokens;\n totalTokens += tokens.totalTokens;\n\n // Extract model metadata (last message's metadata wins for model/finish_reason)\n extractModelMetadata(span, message);\n }\n\n // Set accumulated token usage on span\n if (totalInputTokens > 0) {\n span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE, totalInputTokens);\n }\n if (totalOutputTokens > 0) {\n span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE, totalOutputTokens);\n }\n if (totalTokens > 0) {\n span.setAttribute(GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE, totalTokens);\n }\n}\n\n/** Merge `sentryHandler` into a langchain `callbacks` value (`BaseCallbackHandler[]` or `BaseCallbackManager`). */\nexport function mergeSentryCallback(existing: unknown, sentryHandler: unknown): unknown {\n if (!existing) {\n return [sentryHandler];\n }\n\n if (Array.isArray(existing)) {\n if (existing.includes(sentryHandler)) {\n return existing;\n }\n return [...existing, sentryHandler];\n }\n\n const manager = existing as { addHandler?: (h: unknown) => void; handlers?: unknown[] };\n if (typeof manager.addHandler === 'function') {\n const alreadyAdded = Array.isArray(manager.handlers) && manager.handlers.includes(sentryHandler);\n if (!alreadyAdded) {\n manager.addHandler(sentryHandler);\n }\n }\n\n return existing;\n}\n"],"names":["SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","LANGGRAPH_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_OP","GEN_AI_EXECUTE_TOOL_OPERATION_ATTRIBUTE","GEN_AI_OPERATION_NAME_ATTRIBUTE","GEN_AI_TOOL_NAME_ATTRIBUTE","GEN_AI_TOOL_TYPE_ATTRIBUTE","GEN_AI_AGENT_NAME_ATTRIBUTE","GEN_AI_TOOL_DESCRIPTION_ATTRIBUTE","GEN_AI_TOOL_CALL_ID_ATTRIBUTE","GEN_AI_TOOL_INPUT_ATTRIBUTE","startSpan","GEN_AI_TOOL_OUTPUT_ATTRIBUTE","SPAN_STATUS_ERROR","captureException","GEN_AI_RESPONSE_MODEL_ATTRIBUTE","GEN_AI_RESPONSE_FINISH_REASONS_ATTRIBUTE","GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE","normalizeLangChainMessages","GEN_AI_RESPONSE_TEXT_ATTRIBUTE","GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE","GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE"],"mappings":"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"}