openlit 1.11.0 → 1.13.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 (192) hide show
  1. package/README.md +1 -1
  2. package/dist/config.d.ts +12 -4
  3. package/dist/config.js +7 -17
  4. package/dist/config.js.map +1 -1
  5. package/dist/evals/llm/anthropic.js +10 -6
  6. package/dist/evals/llm/anthropic.js.map +1 -1
  7. package/dist/evals/llm/openai.js +9 -5
  8. package/dist/evals/llm/openai.js.map +1 -1
  9. package/dist/features/vault.js +1 -1
  10. package/dist/features/vault.js.map +1 -1
  11. package/dist/helpers.d.ts +93 -1
  12. package/dist/helpers.js +271 -8
  13. package/dist/helpers.js.map +1 -1
  14. package/dist/index.d.ts +6 -5
  15. package/dist/index.js +95 -50
  16. package/dist/index.js.map +1 -1
  17. package/dist/instrumentation/__tests__/anthropic-wrapper.test.js +215 -27
  18. package/dist/instrumentation/__tests__/anthropic-wrapper.test.js.map +1 -1
  19. package/dist/instrumentation/__tests__/base-wrapper.test.js +19 -23
  20. package/dist/instrumentation/__tests__/base-wrapper.test.js.map +1 -1
  21. package/dist/instrumentation/__tests__/bedrock-trace-comparison.test.d.ts +1 -0
  22. package/dist/instrumentation/__tests__/bedrock-trace-comparison.test.js +422 -0
  23. package/dist/instrumentation/__tests__/bedrock-trace-comparison.test.js.map +1 -0
  24. package/dist/instrumentation/__tests__/chroma-trace-comparison.test.js +1 -1
  25. package/dist/instrumentation/__tests__/chroma-trace-comparison.test.js.map +1 -1
  26. package/dist/instrumentation/__tests__/cohere-wrapper.test.js +150 -25
  27. package/dist/instrumentation/__tests__/cohere-wrapper.test.js.map +1 -1
  28. package/dist/instrumentation/__tests__/google-ai-trace-comparison.test.js +152 -33
  29. package/dist/instrumentation/__tests__/google-ai-trace-comparison.test.js.map +1 -1
  30. package/dist/instrumentation/__tests__/groq-trace-comparison.test.js +391 -45
  31. package/dist/instrumentation/__tests__/groq-trace-comparison.test.js.map +1 -1
  32. package/dist/instrumentation/__tests__/huggingface-trace-comparison.test.d.ts +2 -2
  33. package/dist/instrumentation/__tests__/huggingface-trace-comparison.test.js +323 -31
  34. package/dist/instrumentation/__tests__/huggingface-trace-comparison.test.js.map +1 -1
  35. package/dist/instrumentation/__tests__/langchain-wrapper.test.d.ts +1 -0
  36. package/dist/instrumentation/__tests__/langchain-wrapper.test.js +282 -0
  37. package/dist/instrumentation/__tests__/langchain-wrapper.test.js.map +1 -0
  38. package/dist/instrumentation/__tests__/milvus-trace-comparison.test.js +1 -1
  39. package/dist/instrumentation/__tests__/milvus-trace-comparison.test.js.map +1 -1
  40. package/dist/instrumentation/__tests__/mistral-trace-comparison.test.d.ts +0 -3
  41. package/dist/instrumentation/__tests__/mistral-trace-comparison.test.js +275 -68
  42. package/dist/instrumentation/__tests__/mistral-trace-comparison.test.js.map +1 -1
  43. package/dist/instrumentation/__tests__/openai-wrapper.test.js +7 -9
  44. package/dist/instrumentation/__tests__/openai-wrapper.test.js.map +1 -1
  45. package/dist/instrumentation/__tests__/qdrant-trace-comparison.test.js +1 -1
  46. package/dist/instrumentation/__tests__/qdrant-trace-comparison.test.js.map +1 -1
  47. package/dist/instrumentation/__tests__/replicate-trace-comparison.test.d.ts +2 -1
  48. package/dist/instrumentation/__tests__/replicate-trace-comparison.test.js +209 -21
  49. package/dist/instrumentation/__tests__/replicate-trace-comparison.test.js.map +1 -1
  50. package/dist/instrumentation/__tests__/together-trace-comparison.test.js +231 -51
  51. package/dist/instrumentation/__tests__/together-trace-comparison.test.js.map +1 -1
  52. package/dist/instrumentation/__tests__/vercel-ai-trace-comparison.test.d.ts +8 -0
  53. package/dist/instrumentation/__tests__/vercel-ai-trace-comparison.test.js +446 -0
  54. package/dist/instrumentation/__tests__/vercel-ai-trace-comparison.test.js.map +1 -0
  55. package/dist/instrumentation/anthropic/index.d.ts +2 -3
  56. package/dist/instrumentation/anthropic/index.js.map +1 -1
  57. package/dist/instrumentation/anthropic/wrapper.d.ts +1 -3
  58. package/dist/instrumentation/anthropic/wrapper.js +211 -91
  59. package/dist/instrumentation/anthropic/wrapper.js.map +1 -1
  60. package/dist/instrumentation/azure-ai-inference/index.d.ts +11 -0
  61. package/dist/instrumentation/azure-ai-inference/index.js +76 -0
  62. package/dist/instrumentation/azure-ai-inference/index.js.map +1 -0
  63. package/dist/instrumentation/azure-ai-inference/wrapper.d.ts +42 -0
  64. package/dist/instrumentation/azure-ai-inference/wrapper.js +515 -0
  65. package/dist/instrumentation/azure-ai-inference/wrapper.js.map +1 -0
  66. package/dist/instrumentation/base-wrapper.d.ts +2 -1
  67. package/dist/instrumentation/base-wrapper.js +35 -23
  68. package/dist/instrumentation/base-wrapper.js.map +1 -1
  69. package/dist/instrumentation/bedrock/wrapper.d.ts +21 -3
  70. package/dist/instrumentation/bedrock/wrapper.js +318 -265
  71. package/dist/instrumentation/bedrock/wrapper.js.map +1 -1
  72. package/dist/instrumentation/chroma/wrapper.js +1 -1
  73. package/dist/instrumentation/chroma/wrapper.js.map +1 -1
  74. package/dist/instrumentation/claude-agent-sdk/index.d.ts +23 -0
  75. package/dist/instrumentation/claude-agent-sdk/index.js +83 -0
  76. package/dist/instrumentation/claude-agent-sdk/index.js.map +1 -0
  77. package/dist/instrumentation/claude-agent-sdk/wrapper.d.ts +13 -0
  78. package/dist/instrumentation/claude-agent-sdk/wrapper.js +1031 -0
  79. package/dist/instrumentation/claude-agent-sdk/wrapper.js.map +1 -0
  80. package/dist/instrumentation/cohere/index.d.ts +2 -3
  81. package/dist/instrumentation/cohere/index.js.map +1 -1
  82. package/dist/instrumentation/cohere/wrapper.d.ts +1 -1
  83. package/dist/instrumentation/cohere/wrapper.js +215 -56
  84. package/dist/instrumentation/cohere/wrapper.js.map +1 -1
  85. package/dist/instrumentation/cursor-sdk/index.d.ts +21 -0
  86. package/dist/instrumentation/cursor-sdk/index.js +58 -0
  87. package/dist/instrumentation/cursor-sdk/index.js.map +1 -0
  88. package/dist/instrumentation/cursor-sdk/wrapper.d.ts +17 -0
  89. package/dist/instrumentation/cursor-sdk/wrapper.js +689 -0
  90. package/dist/instrumentation/cursor-sdk/wrapper.js.map +1 -0
  91. package/dist/instrumentation/google-adk/index.d.ts +57 -0
  92. package/dist/instrumentation/google-adk/index.js +371 -0
  93. package/dist/instrumentation/google-adk/index.js.map +1 -0
  94. package/dist/instrumentation/google-adk/utils.d.ts +45 -0
  95. package/dist/instrumentation/google-adk/utils.js +663 -0
  96. package/dist/instrumentation/google-adk/utils.js.map +1 -0
  97. package/dist/instrumentation/google-adk/wrapper.d.ts +11 -0
  98. package/dist/instrumentation/google-adk/wrapper.js +391 -0
  99. package/dist/instrumentation/google-adk/wrapper.js.map +1 -0
  100. package/dist/instrumentation/google-ai/wrapper.d.ts +7 -4
  101. package/dist/instrumentation/google-ai/wrapper.js +197 -61
  102. package/dist/instrumentation/google-ai/wrapper.js.map +1 -1
  103. package/dist/instrumentation/groq/wrapper.js +137 -65
  104. package/dist/instrumentation/groq/wrapper.js.map +1 -1
  105. package/dist/instrumentation/huggingface/wrapper.js +241 -39
  106. package/dist/instrumentation/huggingface/wrapper.js.map +1 -1
  107. package/dist/instrumentation/index.d.ts +2 -2
  108. package/dist/instrumentation/index.js +66 -6
  109. package/dist/instrumentation/index.js.map +1 -1
  110. package/dist/instrumentation/langchain/index.d.ts +0 -7
  111. package/dist/instrumentation/langchain/index.js +2 -20
  112. package/dist/instrumentation/langchain/index.js.map +1 -1
  113. package/dist/instrumentation/langchain/wrapper.d.ts +35 -0
  114. package/dist/instrumentation/langchain/wrapper.js +1098 -184
  115. package/dist/instrumentation/langchain/wrapper.js.map +1 -1
  116. package/dist/instrumentation/langgraph/index.d.ts +12 -0
  117. package/dist/instrumentation/langgraph/index.js +99 -0
  118. package/dist/instrumentation/langgraph/index.js.map +1 -0
  119. package/dist/instrumentation/langgraph/wrapper.d.ts +20 -0
  120. package/dist/instrumentation/langgraph/wrapper.js +619 -0
  121. package/dist/instrumentation/langgraph/wrapper.js.map +1 -0
  122. package/dist/instrumentation/llamaindex/index.d.ts +31 -6
  123. package/dist/instrumentation/llamaindex/index.js +180 -61
  124. package/dist/instrumentation/llamaindex/index.js.map +1 -1
  125. package/dist/instrumentation/llamaindex/wrapper.d.ts +15 -3
  126. package/dist/instrumentation/llamaindex/wrapper.js +670 -179
  127. package/dist/instrumentation/llamaindex/wrapper.js.map +1 -1
  128. package/dist/instrumentation/milvus/wrapper.js +1 -1
  129. package/dist/instrumentation/milvus/wrapper.js.map +1 -1
  130. package/dist/instrumentation/mistral/wrapper.js +154 -79
  131. package/dist/instrumentation/mistral/wrapper.js.map +1 -1
  132. package/dist/instrumentation/ollama/index.js +33 -4
  133. package/dist/instrumentation/ollama/index.js.map +1 -1
  134. package/dist/instrumentation/ollama/wrapper.d.ts +28 -2
  135. package/dist/instrumentation/ollama/wrapper.js +432 -48
  136. package/dist/instrumentation/ollama/wrapper.js.map +1 -1
  137. package/dist/instrumentation/openai/index.d.ts +2 -3
  138. package/dist/instrumentation/openai/index.js.map +1 -1
  139. package/dist/instrumentation/openai/wrapper.js +293 -194
  140. package/dist/instrumentation/openai/wrapper.js.map +1 -1
  141. package/dist/instrumentation/openai-agents/index.d.ts +20 -0
  142. package/dist/instrumentation/openai-agents/index.js +174 -0
  143. package/dist/instrumentation/openai-agents/index.js.map +1 -0
  144. package/dist/instrumentation/openai-agents/processor.d.ts +35 -0
  145. package/dist/instrumentation/openai-agents/processor.js +249 -0
  146. package/dist/instrumentation/openai-agents/processor.js.map +1 -0
  147. package/dist/instrumentation/openai-agents/utils.d.ts +20 -0
  148. package/dist/instrumentation/openai-agents/utils.js +624 -0
  149. package/dist/instrumentation/openai-agents/utils.js.map +1 -0
  150. package/dist/instrumentation/pinecone/wrapper.js +2 -2
  151. package/dist/instrumentation/pinecone/wrapper.js.map +1 -1
  152. package/dist/instrumentation/qdrant/wrapper.js +1 -1
  153. package/dist/instrumentation/qdrant/wrapper.js.map +1 -1
  154. package/dist/instrumentation/replicate/wrapper.js +103 -21
  155. package/dist/instrumentation/replicate/wrapper.js.map +1 -1
  156. package/dist/instrumentation/strands/index.d.ts +21 -0
  157. package/dist/instrumentation/strands/index.js +83 -0
  158. package/dist/instrumentation/strands/index.js.map +1 -0
  159. package/dist/instrumentation/strands/processor.d.ts +45 -0
  160. package/dist/instrumentation/strands/processor.js +545 -0
  161. package/dist/instrumentation/strands/processor.js.map +1 -0
  162. package/dist/instrumentation/strands/utils.d.ts +24 -0
  163. package/dist/instrumentation/strands/utils.js +360 -0
  164. package/dist/instrumentation/strands/utils.js.map +1 -0
  165. package/dist/instrumentation/together/wrapper.js +125 -51
  166. package/dist/instrumentation/together/wrapper.js.map +1 -1
  167. package/dist/instrumentation/vercel-ai/wrapper.d.ts +28 -2
  168. package/dist/instrumentation/vercel-ai/wrapper.js +314 -164
  169. package/dist/instrumentation/vercel-ai/wrapper.js.map +1 -1
  170. package/dist/llm/anthropic.js +10 -6
  171. package/dist/llm/anthropic.js.map +1 -1
  172. package/dist/llm/openai.js +9 -5
  173. package/dist/llm/openai.js.map +1 -1
  174. package/dist/otel/__tests__/metrics.test.js +16 -27
  175. package/dist/otel/__tests__/metrics.test.js.map +1 -1
  176. package/dist/otel/events.d.ts +11 -0
  177. package/dist/otel/events.js +74 -0
  178. package/dist/otel/events.js.map +1 -0
  179. package/dist/otel/metrics.d.ts +5 -6
  180. package/dist/otel/metrics.js +66 -48
  181. package/dist/otel/metrics.js.map +1 -1
  182. package/dist/otel/tracing.d.ts +6 -2
  183. package/dist/otel/tracing.js +71 -24
  184. package/dist/otel/tracing.js.map +1 -1
  185. package/dist/otel/utils.d.ts +11 -0
  186. package/dist/otel/utils.js +34 -0
  187. package/dist/otel/utils.js.map +1 -0
  188. package/dist/semantic-convention.d.ts +49 -5
  189. package/dist/semantic-convention.js +56 -8
  190. package/dist/semantic-convention.js.map +1 -1
  191. package/dist/types.d.ts +58 -22
  192. package/package.json +41 -9
@@ -0,0 +1,689 @@
1
+ "use strict";
2
+ /**
3
+ * Cursor SDK wrapper -- OTel GenAI semantic convention compliant.
4
+ *
5
+ * Wraps Agent.create(), Agent.resume(), and agent.send()
6
+ * to produce `create_agent`, `invoke_agent`, and `execute_tool` spans.
7
+ *
8
+ * Agent.prompt() is NOT wrapped separately -- it internally calls
9
+ * create() + send(), so the patched versions handle it automatically
10
+ * without producing duplicate spans.
11
+ *
12
+ * Token usage is captured via onDelta injection (TurnEndedUpdate).
13
+ * Tool call spans are created from SDKMessage stream events.
14
+ * The `system` stream event provides resolved model and tool definitions.
15
+ */
16
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ var desc = Object.getOwnPropertyDescriptor(m, k);
19
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
20
+ desc = { enumerable: true, get: function() { return m[k]; } };
21
+ }
22
+ Object.defineProperty(o, k2, desc);
23
+ }) : (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ o[k2] = m[k];
26
+ }));
27
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
28
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
29
+ }) : function(o, v) {
30
+ o["default"] = v;
31
+ });
32
+ var __importStar = (this && this.__importStar) || (function () {
33
+ var ownKeys = function(o) {
34
+ ownKeys = Object.getOwnPropertyNames || function (o) {
35
+ var ar = [];
36
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
37
+ return ar;
38
+ };
39
+ return ownKeys(o);
40
+ };
41
+ return function (mod) {
42
+ if (mod && mod.__esModule) return mod;
43
+ var result = {};
44
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
45
+ __setModuleDefault(result, mod);
46
+ return result;
47
+ };
48
+ })();
49
+ var __importDefault = (this && this.__importDefault) || function (mod) {
50
+ return (mod && mod.__esModule) ? mod : { "default": mod };
51
+ };
52
+ Object.defineProperty(exports, "__esModule", { value: true });
53
+ exports.patchAgentCreate = patchAgentCreate;
54
+ exports.patchAgentResume = patchAgentResume;
55
+ const api_1 = require("@opentelemetry/api");
56
+ const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
57
+ const semantic_convention_1 = __importDefault(require("../../semantic-convention"));
58
+ const config_1 = __importDefault(require("../../config"));
59
+ const helpers_1 = __importStar(require("../../helpers"));
60
+ const constant_1 = require("../../constant");
61
+ const metrics_1 = __importDefault(require("../../otel/metrics"));
62
+ // ---------------------------------------------------------------------------
63
+ // Constants
64
+ // ---------------------------------------------------------------------------
65
+ const [SERVER_ADDRESS, SERVER_PORT] = (0, helpers_1.getServerAddressForProvider)('cursor');
66
+ const CURSOR_STATUS_TO_FINISH_REASON = {
67
+ finished: 'stop',
68
+ error: 'error',
69
+ cancelled: 'cancelled',
70
+ };
71
+ // ---------------------------------------------------------------------------
72
+ // Agent creation registry -- links invoke_agent back to create_agent
73
+ // ---------------------------------------------------------------------------
74
+ class AgentCreationRegistry {
75
+ constructor() {
76
+ this._contexts = new WeakMap();
77
+ }
78
+ register(agent, spanContext) {
79
+ this._contexts.set(agent, spanContext);
80
+ }
81
+ get(agent) {
82
+ return this._contexts.get(agent);
83
+ }
84
+ }
85
+ const agentRegistry = new AgentCreationRegistry();
86
+ // ---------------------------------------------------------------------------
87
+ // Helpers
88
+ // ---------------------------------------------------------------------------
89
+ function truncateContent(content) {
90
+ const maxLen = config_1.default.maxContentLength;
91
+ if (maxLen != null && maxLen > 0 && content.length > maxLen) {
92
+ return content.slice(0, maxLen);
93
+ }
94
+ return content;
95
+ }
96
+ function mapRunStatusToFinishReason(status) {
97
+ if (!status)
98
+ return 'stop';
99
+ return CURSOR_STATUS_TO_FINISH_REASON[status] || status;
100
+ }
101
+ function resolveAgentName(options) {
102
+ if (!options)
103
+ return null;
104
+ const name = options.name;
105
+ if (name && typeof name === 'string' && name.trim())
106
+ return name.trim();
107
+ return null;
108
+ }
109
+ function resolveModelId(options) {
110
+ if (!options?.model)
111
+ return null;
112
+ const model = options.model;
113
+ if (typeof model === 'string')
114
+ return model;
115
+ if (typeof model === 'object' && model.id)
116
+ return String(model.id);
117
+ return null;
118
+ }
119
+ function setCommonSpanAttributes(span) {
120
+ span.setAttribute(semantic_conventions_1.ATTR_TELEMETRY_SDK_NAME, constant_1.SDK_NAME);
121
+ span.setAttribute(semantic_convention_1.default.ATTR_DEPLOYMENT_ENVIRONMENT, config_1.default.environment ?? 'default');
122
+ span.setAttribute(semantic_conventions_1.ATTR_SERVICE_NAME, config_1.default.applicationName ?? 'default');
123
+ span.setAttribute(semantic_convention_1.default.GEN_AI_SDK_VERSION, constant_1.SDK_VERSION);
124
+ span.setAttribute(semantic_convention_1.default.SERVER_ADDRESS, SERVER_ADDRESS);
125
+ span.setAttribute(semantic_convention_1.default.SERVER_PORT, SERVER_PORT);
126
+ }
127
+ // ---------------------------------------------------------------------------
128
+ // Tool span tracker -- manages in-flight execute_tool spans from stream
129
+ // ---------------------------------------------------------------------------
130
+ class ToolSpanTracker {
131
+ constructor(tracer, parentSpan, captureContent) {
132
+ this._inFlight = new Map();
133
+ this._tracer = tracer;
134
+ this._parentSpan = parentSpan;
135
+ this._captureContent = captureContent;
136
+ }
137
+ startTool(toolName, callId, args) {
138
+ const spanName = `${semantic_convention_1.default.GEN_AI_OPERATION_TYPE_TOOLS} ${toolName}`;
139
+ const parentCtx = api_1.trace.setSpan(api_1.context.active(), this._parentSpan);
140
+ const span = this._tracer.startSpan(spanName, {
141
+ kind: api_1.SpanKind.INTERNAL,
142
+ attributes: {
143
+ [semantic_convention_1.default.GEN_AI_OPERATION]: semantic_convention_1.default.GEN_AI_OPERATION_TYPE_TOOLS,
144
+ [semantic_convention_1.default.GEN_AI_PROVIDER_NAME_OTEL]: semantic_convention_1.default.GEN_AI_SYSTEM_CURSOR,
145
+ },
146
+ }, parentCtx);
147
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_NAME, toolName);
148
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_CALL_ID, callId);
149
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_TYPE_OTEL, 'extension');
150
+ setCommonSpanAttributes(span);
151
+ if (this._captureContent && args != null) {
152
+ try {
153
+ const argsStr = typeof args === 'string' ? args : JSON.stringify(args);
154
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_CALL_ARGUMENTS, truncateContent(argsStr));
155
+ }
156
+ catch { /* ignore */ }
157
+ }
158
+ (0, helpers_1.applyCustomSpanAttributes)(span);
159
+ this._inFlight.set(callId, span);
160
+ }
161
+ endTool(callId, result, isError = false) {
162
+ const span = this._inFlight.get(callId);
163
+ if (!span)
164
+ return;
165
+ this._inFlight.delete(callId);
166
+ if (isError) {
167
+ span.setAttribute(semantic_convention_1.default.ERROR_TYPE, 'ToolExecutionError');
168
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: 'tool execution failed' });
169
+ }
170
+ else {
171
+ if (this._captureContent && result != null) {
172
+ try {
173
+ const resultStr = typeof result === 'string' ? result : JSON.stringify(result);
174
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_CALL_RESULT, truncateContent(resultStr));
175
+ }
176
+ catch { /* ignore */ }
177
+ }
178
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
179
+ }
180
+ span.end();
181
+ }
182
+ endAll() {
183
+ for (const [, span] of this._inFlight) {
184
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
185
+ span.end();
186
+ }
187
+ this._inFlight.clear();
188
+ }
189
+ }
190
+ function processStreamEvent(event, toolTracker, state) {
191
+ if (!event || !event.type)
192
+ return;
193
+ if (!state.runId && event.run_id) {
194
+ state.runId = event.run_id;
195
+ }
196
+ switch (event.type) {
197
+ case 'system': {
198
+ if (event.model) {
199
+ const modelId = typeof event.model === 'string' ? event.model : event.model?.id;
200
+ if (modelId)
201
+ state.resolvedModel = String(modelId);
202
+ }
203
+ if (Array.isArray(event.tools) && event.tools.length > 0) {
204
+ state.toolDefinitions = event.tools.map(String);
205
+ }
206
+ break;
207
+ }
208
+ case 'tool_call': {
209
+ const callId = event.call_id;
210
+ const toolName = event.name || 'unknown';
211
+ const status = event.status;
212
+ if (status === 'running') {
213
+ toolTracker.startTool(toolName, callId, event.args);
214
+ state.toolCalls.push({ name: toolName, callId, args: event.args });
215
+ }
216
+ else if (status === 'completed') {
217
+ toolTracker.endTool(callId, event.result, false);
218
+ const tc = state.toolCalls.find(t => t.callId === callId);
219
+ if (tc)
220
+ tc.result = event.result;
221
+ }
222
+ else if (status === 'error') {
223
+ toolTracker.endTool(callId, event.result, true);
224
+ }
225
+ break;
226
+ }
227
+ case 'assistant': {
228
+ if (state.firstContentTimeMs === null) {
229
+ state.firstContentTimeMs = Date.now();
230
+ }
231
+ const content = event.message?.content;
232
+ if (Array.isArray(content)) {
233
+ for (const block of content) {
234
+ if (block.type === 'text' && block.text) {
235
+ state.assistantText += block.text;
236
+ }
237
+ }
238
+ }
239
+ break;
240
+ }
241
+ case 'thinking': {
242
+ if (state.firstContentTimeMs === null) {
243
+ state.firstContentTimeMs = Date.now();
244
+ }
245
+ if (event.text) {
246
+ state.thinkingText += event.text;
247
+ }
248
+ break;
249
+ }
250
+ }
251
+ }
252
+ // ---------------------------------------------------------------------------
253
+ // Build OTel input/output messages
254
+ // ---------------------------------------------------------------------------
255
+ function buildInputMessages(message) {
256
+ try {
257
+ if (typeof message === 'string') {
258
+ return JSON.stringify([{
259
+ role: 'user',
260
+ parts: [{ type: 'text', content: truncateContent(message) }],
261
+ }]);
262
+ }
263
+ const parts = [];
264
+ if (message?.text) {
265
+ parts.push({ type: 'text', content: truncateContent(message.text) });
266
+ }
267
+ if (Array.isArray(message?.images)) {
268
+ for (const img of message.images) {
269
+ parts.push({ type: 'image', mimeType: img.mimeType || 'image/png' });
270
+ }
271
+ }
272
+ if (parts.length === 0)
273
+ return null;
274
+ return JSON.stringify([{ role: 'user', parts }]);
275
+ }
276
+ catch {
277
+ return null;
278
+ }
279
+ }
280
+ function buildOutputMessages(state, finishReason) {
281
+ try {
282
+ const parts = [];
283
+ if (state.assistantText) {
284
+ parts.push({ type: 'text', content: truncateContent(state.assistantText) });
285
+ }
286
+ if (state.thinkingText) {
287
+ parts.push({ type: 'reasoning', content: truncateContent(state.thinkingText) });
288
+ }
289
+ for (const tc of state.toolCalls) {
290
+ const toolPart = {
291
+ type: 'tool_call',
292
+ id: tc.callId,
293
+ name: tc.name,
294
+ };
295
+ if (tc.args != null) {
296
+ toolPart.arguments = typeof tc.args === 'object' ? tc.args : {};
297
+ }
298
+ parts.push(toolPart);
299
+ }
300
+ if (parts.length === 0)
301
+ return null;
302
+ return JSON.stringify([{ role: 'assistant', parts, finish_reason: finishReason }]);
303
+ }
304
+ catch {
305
+ return null;
306
+ }
307
+ }
308
+ // ---------------------------------------------------------------------------
309
+ // Emit inference event for invoke_agent spans
310
+ // ---------------------------------------------------------------------------
311
+ function emitInvokeAgentEvent(span, agentId, model, responseModel, finishReason, inputTokens, outputTokens, inputMessagesJson, outputMessagesJson) {
312
+ if (config_1.default.disableEvents)
313
+ return;
314
+ try {
315
+ const attributes = {
316
+ [semantic_convention_1.default.GEN_AI_OPERATION]: semantic_convention_1.default.GEN_AI_OPERATION_TYPE_AGENT,
317
+ [semantic_convention_1.default.GEN_AI_PROVIDER_NAME_OTEL]: semantic_convention_1.default.GEN_AI_SYSTEM_CURSOR,
318
+ [semantic_convention_1.default.SERVER_ADDRESS]: SERVER_ADDRESS,
319
+ [semantic_convention_1.default.SERVER_PORT]: SERVER_PORT,
320
+ };
321
+ if (model)
322
+ attributes[semantic_convention_1.default.GEN_AI_REQUEST_MODEL] = model;
323
+ if (responseModel)
324
+ attributes[semantic_convention_1.default.GEN_AI_RESPONSE_MODEL] = responseModel;
325
+ if (agentId)
326
+ attributes[semantic_convention_1.default.GEN_AI_CONVERSATION_ID] = agentId;
327
+ if (finishReason)
328
+ attributes[semantic_convention_1.default.GEN_AI_RESPONSE_FINISH_REASON] = [finishReason];
329
+ if (inputTokens)
330
+ attributes[semantic_convention_1.default.GEN_AI_USAGE_INPUT_TOKENS] = inputTokens;
331
+ if (outputTokens)
332
+ attributes[semantic_convention_1.default.GEN_AI_USAGE_OUTPUT_TOKENS] = outputTokens;
333
+ if (inputMessagesJson != null) {
334
+ attributes[semantic_convention_1.default.GEN_AI_INPUT_MESSAGES] = inputMessagesJson;
335
+ }
336
+ if (outputMessagesJson != null) {
337
+ attributes[semantic_convention_1.default.GEN_AI_OUTPUT_MESSAGES] = outputMessagesJson;
338
+ }
339
+ helpers_1.default.emitInferenceEvent(span, attributes);
340
+ }
341
+ catch { /* swallow */ }
342
+ }
343
+ // ---------------------------------------------------------------------------
344
+ // Record metrics for invoke_agent spans
345
+ // ---------------------------------------------------------------------------
346
+ function recordInvokeAgentMetrics(model, inputTokens, outputTokens, cost, duration, errorType) {
347
+ if (config_1.default.disableMetrics)
348
+ return;
349
+ try {
350
+ const attributes = {
351
+ [semantic_conventions_1.ATTR_TELEMETRY_SDK_NAME]: constant_1.SDK_NAME,
352
+ [semantic_conventions_1.ATTR_SERVICE_NAME]: config_1.default.applicationName ?? 'default',
353
+ [semantic_convention_1.default.ATTR_DEPLOYMENT_ENVIRONMENT]: config_1.default.environment ?? 'default',
354
+ [semantic_convention_1.default.GEN_AI_PROVIDER_NAME_OTEL]: semantic_convention_1.default.GEN_AI_SYSTEM_CURSOR,
355
+ [semantic_convention_1.default.GEN_AI_OPERATION]: semantic_convention_1.default.GEN_AI_OPERATION_TYPE_AGENT,
356
+ [semantic_convention_1.default.SERVER_ADDRESS]: SERVER_ADDRESS,
357
+ [semantic_convention_1.default.SERVER_PORT]: SERVER_PORT,
358
+ };
359
+ if (model)
360
+ attributes[semantic_convention_1.default.GEN_AI_REQUEST_MODEL] = model;
361
+ if (errorType)
362
+ attributes[semantic_convention_1.default.ERROR_TYPE] = errorType;
363
+ if (metrics_1.default.genaiClientOperationDuration) {
364
+ metrics_1.default.genaiClientOperationDuration.record(duration, attributes);
365
+ }
366
+ if (inputTokens && metrics_1.default.genaiClientUsageTokens) {
367
+ metrics_1.default.genaiClientUsageTokens.record(inputTokens, {
368
+ ...attributes,
369
+ [semantic_convention_1.default.GEN_AI_TOKEN_TYPE]: semantic_convention_1.default.GEN_AI_TOKEN_TYPE_INPUT,
370
+ });
371
+ }
372
+ if (outputTokens && metrics_1.default.genaiClientUsageTokens) {
373
+ metrics_1.default.genaiClientUsageTokens.record(outputTokens, {
374
+ ...attributes,
375
+ [semantic_convention_1.default.GEN_AI_TOKEN_TYPE]: semantic_convention_1.default.GEN_AI_TOKEN_TYPE_OUTPUT,
376
+ });
377
+ }
378
+ if (cost && metrics_1.default.genaiCost) {
379
+ metrics_1.default.genaiCost.record(cost, attributes);
380
+ }
381
+ }
382
+ catch { /* swallow */ }
383
+ }
384
+ // ---------------------------------------------------------------------------
385
+ // wrapSend -- wraps agent.send() to produce invoke_agent spans
386
+ // ---------------------------------------------------------------------------
387
+ function wrapSend(tracer, originalSend, agentId, agentName, modelId) {
388
+ return function wrappedSend(message, options) {
389
+ const captureContent = config_1.default.captureMessageContent ?? true;
390
+ const displayName = agentName || agentId;
391
+ const spanName = `${semantic_convention_1.default.GEN_AI_OPERATION_TYPE_AGENT} ${displayName}`;
392
+ const requestModel = modelId || resolveModelId(options) || 'unknown';
393
+ const creationSpanCtx = agentRegistry.get(this);
394
+ const links = [];
395
+ if (creationSpanCtx) {
396
+ links.push({ context: creationSpanCtx });
397
+ }
398
+ // Start invoke_agent in the same trace as create_agent by using its
399
+ // span context as parent. This keeps both spans in one trace while
400
+ // the span link provides explicit correlation.
401
+ let parentCtx = api_1.context.active();
402
+ if (creationSpanCtx) {
403
+ const remoteSpan = api_1.trace.wrapSpanContext(creationSpanCtx);
404
+ parentCtx = api_1.trace.setSpan(parentCtx, remoteSpan);
405
+ }
406
+ const span = tracer.startSpan(spanName, {
407
+ kind: api_1.SpanKind.CLIENT,
408
+ attributes: {
409
+ [semantic_convention_1.default.GEN_AI_OPERATION]: semantic_convention_1.default.GEN_AI_OPERATION_TYPE_AGENT,
410
+ [semantic_convention_1.default.GEN_AI_PROVIDER_NAME_OTEL]: semantic_convention_1.default.GEN_AI_SYSTEM_CURSOR,
411
+ [semantic_convention_1.default.GEN_AI_REQUEST_MODEL]: requestModel,
412
+ [semantic_convention_1.default.SERVER_ADDRESS]: SERVER_ADDRESS,
413
+ [semantic_convention_1.default.SERVER_PORT]: SERVER_PORT,
414
+ },
415
+ links,
416
+ }, parentCtx);
417
+ setCommonSpanAttributes(span);
418
+ span.setAttribute(semantic_convention_1.default.GEN_AI_AGENT_ID, agentId);
419
+ span.setAttribute(semantic_convention_1.default.GEN_AI_CONVERSATION_ID, agentId);
420
+ if (agentName)
421
+ span.setAttribute(semantic_convention_1.default.GEN_AI_AGENT_NAME, agentName);
422
+ if (captureContent) {
423
+ const inputJson = buildInputMessages(message);
424
+ if (inputJson)
425
+ span.setAttribute(semantic_convention_1.default.GEN_AI_INPUT_MESSAGES, inputJson);
426
+ }
427
+ (0, helpers_1.applyCustomSpanAttributes)(span);
428
+ const startTime = Date.now() / 1000;
429
+ const startTimeMs = Date.now();
430
+ const usage = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 };
431
+ const toolTracker = new ToolSpanTracker(tracer, span, captureContent);
432
+ const streamState = {
433
+ assistantText: '',
434
+ thinkingText: '',
435
+ toolCalls: [],
436
+ resolvedModel: null,
437
+ toolDefinitions: null,
438
+ runId: null,
439
+ firstContentTimeMs: null,
440
+ };
441
+ const userOnDelta = options?.onDelta;
442
+ const mergedOptions = { ...options };
443
+ mergedOptions.onDelta = async (args) => {
444
+ try {
445
+ const update = args?.update;
446
+ if (update?.type === 'turn-ended' && update.usage) {
447
+ usage.inputTokens += update.usage.inputTokens || 0;
448
+ usage.outputTokens += update.usage.outputTokens || 0;
449
+ usage.cacheReadTokens += update.usage.cacheReadTokens || 0;
450
+ usage.cacheWriteTokens += update.usage.cacheWriteTokens || 0;
451
+ }
452
+ }
453
+ catch { /* swallow */ }
454
+ if (userOnDelta) {
455
+ return userOnDelta(args);
456
+ }
457
+ };
458
+ const spanContext = api_1.trace.setSpan(api_1.context.active(), span);
459
+ (0, helpers_1.setFrameworkLlmActive)();
460
+ let runPromise;
461
+ try {
462
+ runPromise = api_1.context.with(spanContext, () => {
463
+ return originalSend.call(this, message, mergedOptions);
464
+ });
465
+ }
466
+ catch (e) {
467
+ (0, helpers_1.resetFrameworkLlmActive)();
468
+ helpers_1.default.handleException(span, e);
469
+ span.end();
470
+ throw e;
471
+ }
472
+ return runPromise.then((run) => {
473
+ return createRunProxy(run, tracer, span, startTime, startTimeMs, usage, toolTracker, streamState, captureContent, agentId, agentName, requestModel, message);
474
+ }).catch((e) => {
475
+ (0, helpers_1.resetFrameworkLlmActive)();
476
+ helpers_1.default.handleException(span, e);
477
+ recordInvokeAgentMetrics(requestModel, 0, 0, 0, (Date.now() / 1000) - startTime, e?.constructor?.name || '_OTHER');
478
+ span.end();
479
+ throw e;
480
+ });
481
+ };
482
+ }
483
+ // ---------------------------------------------------------------------------
484
+ // createRunProxy -- proxies the Run to intercept stream() and wait()
485
+ // ---------------------------------------------------------------------------
486
+ function createRunProxy(run, tracer, span, startTime, startTimeMs, usage, toolTracker, streamState, captureContent, agentId, agentName, requestModel, message) {
487
+ let finalized = false;
488
+ let isStreamMode = false;
489
+ const finalizeSpan = (result, error) => {
490
+ if (finalized)
491
+ return;
492
+ finalized = true;
493
+ (0, helpers_1.resetFrameworkLlmActive)();
494
+ toolTracker.endAll();
495
+ const duration = (Date.now() / 1000) - startTime;
496
+ const status = result?.status || run.status || 'finished';
497
+ const finishReason = mapRunStatusToFinishReason(status);
498
+ const responseModel = streamState.resolvedModel || result?.model?.id || run.model?.id || null;
499
+ const durationMs = result?.durationMs || run.durationMs;
500
+ if (responseModel)
501
+ span.setAttribute(semantic_convention_1.default.GEN_AI_RESPONSE_MODEL, responseModel);
502
+ span.setAttribute(semantic_convention_1.default.GEN_AI_RESPONSE_FINISH_REASON, [finishReason]);
503
+ const runId = streamState.runId || run.id;
504
+ if (runId)
505
+ span.setAttribute(semantic_convention_1.default.GEN_AI_RESPONSE_ID, runId);
506
+ if (isStreamMode) {
507
+ span.setAttribute(semantic_convention_1.default.GEN_AI_REQUEST_STREAM, true);
508
+ }
509
+ if (usage.inputTokens)
510
+ span.setAttribute(semantic_convention_1.default.GEN_AI_USAGE_INPUT_TOKENS, usage.inputTokens);
511
+ if (usage.outputTokens)
512
+ span.setAttribute(semantic_convention_1.default.GEN_AI_USAGE_OUTPUT_TOKENS, usage.outputTokens);
513
+ if (usage.cacheReadTokens)
514
+ span.setAttribute(semantic_convention_1.default.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, usage.cacheReadTokens);
515
+ if (usage.cacheWriteTokens)
516
+ span.setAttribute(semantic_convention_1.default.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, usage.cacheWriteTokens);
517
+ const effectiveDuration = durationMs ? durationMs / 1000 : duration;
518
+ span.setAttribute(semantic_convention_1.default.GEN_AI_CLIENT_OPERATION_DURATION, effectiveDuration);
519
+ if (isStreamMode && streamState.firstContentTimeMs !== null) {
520
+ const ttft = (streamState.firstContentTimeMs - startTimeMs) / 1000;
521
+ span.setAttribute(semantic_convention_1.default.GEN_AI_RESPONSE_TIME_TO_FIRST_CHUNK, ttft);
522
+ }
523
+ if (streamState.toolDefinitions && streamState.toolDefinitions.length > 0) {
524
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_DEFINITIONS, JSON.stringify(streamState.toolDefinitions));
525
+ }
526
+ const pricingInfo = config_1.default.pricingInfo || {};
527
+ const effectiveModel = responseModel || requestModel;
528
+ const cost = effectiveModel
529
+ ? helpers_1.default.getChatModelCost(effectiveModel, pricingInfo, usage.inputTokens, usage.outputTokens)
530
+ : 0;
531
+ if (cost)
532
+ span.setAttribute(semantic_convention_1.default.GEN_AI_USAGE_COST, cost);
533
+ let outputMessagesJson = null;
534
+ if (captureContent) {
535
+ const resultText = result?.result || run.result;
536
+ if (resultText && !streamState.assistantText) {
537
+ streamState.assistantText = resultText;
538
+ }
539
+ outputMessagesJson = buildOutputMessages(streamState, finishReason);
540
+ if (outputMessagesJson) {
541
+ span.setAttribute(semantic_convention_1.default.GEN_AI_OUTPUT_MESSAGES, outputMessagesJson);
542
+ }
543
+ }
544
+ if (error) {
545
+ helpers_1.default.handleException(span, error instanceof Error ? error : new Error(String(error)));
546
+ }
547
+ else if (status === 'error') {
548
+ span.setAttribute(semantic_convention_1.default.ERROR_TYPE, 'AgentError');
549
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: result?.result || 'agent error' });
550
+ }
551
+ else {
552
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
553
+ }
554
+ const inputMessagesJson = captureContent ? buildInputMessages(message) : null;
555
+ emitInvokeAgentEvent(span, agentId, requestModel, responseModel, finishReason, usage.inputTokens, usage.outputTokens, inputMessagesJson, outputMessagesJson);
556
+ recordInvokeAgentMetrics(requestModel, usage.inputTokens, usage.outputTokens, cost, duration, error ? (error.constructor?.name || '_OTHER') : (status === 'error' ? 'AgentError' : undefined));
557
+ span.end();
558
+ };
559
+ return new Proxy(run, {
560
+ get(target, prop, receiver) {
561
+ if (prop === 'stream') {
562
+ const originalStream = target.stream;
563
+ if (typeof originalStream !== 'function')
564
+ return originalStream;
565
+ return function (...streamArgs) {
566
+ isStreamMode = true;
567
+ const generator = originalStream.apply(target, streamArgs);
568
+ return wrapAsyncGenerator(generator, toolTracker, streamState, finalizeSpan);
569
+ };
570
+ }
571
+ if (prop === 'wait') {
572
+ const originalWait = target.wait;
573
+ if (typeof originalWait !== 'function')
574
+ return originalWait;
575
+ return function (...waitArgs) {
576
+ return originalWait.apply(target, waitArgs).then((result) => {
577
+ finalizeSpan(result);
578
+ return result;
579
+ }).catch((e) => {
580
+ finalizeSpan(undefined, e);
581
+ throw e;
582
+ });
583
+ };
584
+ }
585
+ if (prop === 'cancel') {
586
+ const originalCancel = target.cancel;
587
+ if (typeof originalCancel !== 'function')
588
+ return originalCancel;
589
+ return function (...cancelArgs) {
590
+ return originalCancel.apply(target, cancelArgs).then((result) => {
591
+ finalizeSpan({ status: 'cancelled' });
592
+ return result;
593
+ });
594
+ };
595
+ }
596
+ return Reflect.get(target, prop, receiver);
597
+ },
598
+ });
599
+ }
600
+ // ---------------------------------------------------------------------------
601
+ // wrapAsyncGenerator -- wraps run.stream() to intercept SDKMessage events
602
+ // ---------------------------------------------------------------------------
603
+ async function* wrapAsyncGenerator(generator, toolTracker, streamState, finalizeSpan) {
604
+ try {
605
+ for await (const event of generator) {
606
+ try {
607
+ processStreamEvent(event, toolTracker, streamState);
608
+ }
609
+ catch { /* swallow processing errors */ }
610
+ yield event;
611
+ }
612
+ finalizeSpan();
613
+ }
614
+ catch (e) {
615
+ finalizeSpan(undefined, e);
616
+ throw e;
617
+ }
618
+ }
619
+ // ---------------------------------------------------------------------------
620
+ // patchAgentCreate -- wraps Agent.create() for create_agent spans
621
+ // ---------------------------------------------------------------------------
622
+ function patchAgentCreate(tracer) {
623
+ return (originalCreate) => {
624
+ return async function wrappedCreate(options) {
625
+ const agentName = resolveAgentName(options);
626
+ const modelId = resolveModelId(options);
627
+ const displayName = agentName || 'cursor-agent';
628
+ const spanName = `${semantic_convention_1.default.GEN_AI_OPERATION_TYPE_CREATE_AGENT} ${displayName}`;
629
+ const span = tracer.startSpan(spanName, {
630
+ kind: api_1.SpanKind.CLIENT,
631
+ attributes: {
632
+ [semantic_convention_1.default.GEN_AI_OPERATION]: semantic_convention_1.default.GEN_AI_OPERATION_TYPE_CREATE_AGENT,
633
+ [semantic_convention_1.default.GEN_AI_PROVIDER_NAME_OTEL]: semantic_convention_1.default.GEN_AI_SYSTEM_CURSOR,
634
+ [semantic_convention_1.default.SERVER_ADDRESS]: SERVER_ADDRESS,
635
+ [semantic_convention_1.default.SERVER_PORT]: SERVER_PORT,
636
+ },
637
+ });
638
+ setCommonSpanAttributes(span);
639
+ if (agentName)
640
+ span.setAttribute(semantic_convention_1.default.GEN_AI_AGENT_NAME, agentName);
641
+ if (modelId)
642
+ span.setAttribute(semantic_convention_1.default.GEN_AI_REQUEST_MODEL, modelId);
643
+ (0, helpers_1.applyCustomSpanAttributes)(span);
644
+ try {
645
+ const agent = await originalCreate.call(this, options);
646
+ const agentId = agent.agentId;
647
+ if (agentId) {
648
+ span.setAttribute(semantic_convention_1.default.GEN_AI_AGENT_ID, agentId);
649
+ }
650
+ agentRegistry.register(agent, span.spanContext());
651
+ const resolvedModel = agent.model?.id || modelId;
652
+ if (resolvedModel)
653
+ span.setAttribute(semantic_convention_1.default.GEN_AI_RESPONSE_MODEL, resolvedModel);
654
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
655
+ span.end();
656
+ if (typeof agent.send === 'function') {
657
+ const originalAgentSend = agent.send.bind(agent);
658
+ agent.send = wrapSend(tracer, originalAgentSend, agentId, agentName, resolvedModel);
659
+ }
660
+ return agent;
661
+ }
662
+ catch (e) {
663
+ helpers_1.default.handleException(span, e);
664
+ span.end();
665
+ throw e;
666
+ }
667
+ };
668
+ };
669
+ }
670
+ // ---------------------------------------------------------------------------
671
+ // patchAgentResume -- wraps Agent.resume() to patch send() on resumed agents
672
+ // ---------------------------------------------------------------------------
673
+ function patchAgentResume(tracer) {
674
+ return (originalResume) => {
675
+ return async function wrappedResume(agentId, options) {
676
+ const agentName = resolveAgentName(options);
677
+ const modelId = resolveModelId(options);
678
+ const agent = await originalResume.call(this, agentId, options);
679
+ const resolvedAgentId = agent.agentId || agentId;
680
+ const resolvedModel = agent.model?.id || modelId;
681
+ if (typeof agent.send === 'function') {
682
+ const originalAgentSend = agent.send.bind(agent);
683
+ agent.send = wrapSend(tracer, originalAgentSend, resolvedAgentId, agentName, resolvedModel);
684
+ }
685
+ return agent;
686
+ };
687
+ };
688
+ }
689
+ //# sourceMappingURL=wrapper.js.map