openlit 1.10.0 → 1.12.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 (195) hide show
  1. package/README.md +35 -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/__tests__/rule-engine.test.d.ts +1 -0
  10. package/dist/features/__tests__/rule-engine.test.js +146 -0
  11. package/dist/features/__tests__/rule-engine.test.js.map +1 -0
  12. package/dist/features/base.d.ts +2 -0
  13. package/dist/features/base.js +2 -0
  14. package/dist/features/base.js.map +1 -1
  15. package/dist/features/rule-engine.d.ts +6 -0
  16. package/dist/features/rule-engine.js +60 -0
  17. package/dist/features/rule-engine.js.map +1 -0
  18. package/dist/features/vault.js +1 -1
  19. package/dist/features/vault.js.map +1 -1
  20. package/dist/helpers.d.ts +93 -1
  21. package/dist/helpers.js +270 -8
  22. package/dist/helpers.js.map +1 -1
  23. package/dist/index.d.ts +6 -5
  24. package/dist/index.js +95 -50
  25. package/dist/index.js.map +1 -1
  26. package/dist/instrumentation/__tests__/anthropic-wrapper.test.js +215 -27
  27. package/dist/instrumentation/__tests__/anthropic-wrapper.test.js.map +1 -1
  28. package/dist/instrumentation/__tests__/base-wrapper.test.js +19 -23
  29. package/dist/instrumentation/__tests__/base-wrapper.test.js.map +1 -1
  30. package/dist/instrumentation/__tests__/bedrock-trace-comparison.test.d.ts +1 -0
  31. package/dist/instrumentation/__tests__/bedrock-trace-comparison.test.js +422 -0
  32. package/dist/instrumentation/__tests__/bedrock-trace-comparison.test.js.map +1 -0
  33. package/dist/instrumentation/__tests__/chroma-trace-comparison.test.js +1 -1
  34. package/dist/instrumentation/__tests__/chroma-trace-comparison.test.js.map +1 -1
  35. package/dist/instrumentation/__tests__/cohere-wrapper.test.js +150 -25
  36. package/dist/instrumentation/__tests__/cohere-wrapper.test.js.map +1 -1
  37. package/dist/instrumentation/__tests__/google-ai-trace-comparison.test.js +152 -33
  38. package/dist/instrumentation/__tests__/google-ai-trace-comparison.test.js.map +1 -1
  39. package/dist/instrumentation/__tests__/groq-trace-comparison.test.js +391 -45
  40. package/dist/instrumentation/__tests__/groq-trace-comparison.test.js.map +1 -1
  41. package/dist/instrumentation/__tests__/huggingface-trace-comparison.test.d.ts +2 -2
  42. package/dist/instrumentation/__tests__/huggingface-trace-comparison.test.js +323 -31
  43. package/dist/instrumentation/__tests__/huggingface-trace-comparison.test.js.map +1 -1
  44. package/dist/instrumentation/__tests__/langchain-wrapper.test.d.ts +1 -0
  45. package/dist/instrumentation/__tests__/langchain-wrapper.test.js +282 -0
  46. package/dist/instrumentation/__tests__/langchain-wrapper.test.js.map +1 -0
  47. package/dist/instrumentation/__tests__/milvus-trace-comparison.test.js +1 -1
  48. package/dist/instrumentation/__tests__/milvus-trace-comparison.test.js.map +1 -1
  49. package/dist/instrumentation/__tests__/mistral-trace-comparison.test.d.ts +0 -3
  50. package/dist/instrumentation/__tests__/mistral-trace-comparison.test.js +275 -68
  51. package/dist/instrumentation/__tests__/mistral-trace-comparison.test.js.map +1 -1
  52. package/dist/instrumentation/__tests__/openai-wrapper.test.js +7 -9
  53. package/dist/instrumentation/__tests__/openai-wrapper.test.js.map +1 -1
  54. package/dist/instrumentation/__tests__/qdrant-trace-comparison.test.js +1 -1
  55. package/dist/instrumentation/__tests__/qdrant-trace-comparison.test.js.map +1 -1
  56. package/dist/instrumentation/__tests__/replicate-trace-comparison.test.d.ts +2 -1
  57. package/dist/instrumentation/__tests__/replicate-trace-comparison.test.js +209 -21
  58. package/dist/instrumentation/__tests__/replicate-trace-comparison.test.js.map +1 -1
  59. package/dist/instrumentation/__tests__/together-trace-comparison.test.js +231 -51
  60. package/dist/instrumentation/__tests__/together-trace-comparison.test.js.map +1 -1
  61. package/dist/instrumentation/__tests__/vercel-ai-trace-comparison.test.d.ts +8 -0
  62. package/dist/instrumentation/__tests__/vercel-ai-trace-comparison.test.js +446 -0
  63. package/dist/instrumentation/__tests__/vercel-ai-trace-comparison.test.js.map +1 -0
  64. package/dist/instrumentation/anthropic/index.d.ts +2 -3
  65. package/dist/instrumentation/anthropic/index.js.map +1 -1
  66. package/dist/instrumentation/anthropic/wrapper.d.ts +1 -3
  67. package/dist/instrumentation/anthropic/wrapper.js +211 -91
  68. package/dist/instrumentation/anthropic/wrapper.js.map +1 -1
  69. package/dist/instrumentation/azure-ai-inference/index.d.ts +11 -0
  70. package/dist/instrumentation/azure-ai-inference/index.js +76 -0
  71. package/dist/instrumentation/azure-ai-inference/index.js.map +1 -0
  72. package/dist/instrumentation/azure-ai-inference/wrapper.d.ts +42 -0
  73. package/dist/instrumentation/azure-ai-inference/wrapper.js +515 -0
  74. package/dist/instrumentation/azure-ai-inference/wrapper.js.map +1 -0
  75. package/dist/instrumentation/base-wrapper.d.ts +2 -1
  76. package/dist/instrumentation/base-wrapper.js +35 -23
  77. package/dist/instrumentation/base-wrapper.js.map +1 -1
  78. package/dist/instrumentation/bedrock/wrapper.d.ts +21 -3
  79. package/dist/instrumentation/bedrock/wrapper.js +318 -265
  80. package/dist/instrumentation/bedrock/wrapper.js.map +1 -1
  81. package/dist/instrumentation/chroma/wrapper.js +1 -1
  82. package/dist/instrumentation/chroma/wrapper.js.map +1 -1
  83. package/dist/instrumentation/claude-agent-sdk/index.d.ts +23 -0
  84. package/dist/instrumentation/claude-agent-sdk/index.js +83 -0
  85. package/dist/instrumentation/claude-agent-sdk/index.js.map +1 -0
  86. package/dist/instrumentation/claude-agent-sdk/wrapper.d.ts +13 -0
  87. package/dist/instrumentation/claude-agent-sdk/wrapper.js +1031 -0
  88. package/dist/instrumentation/claude-agent-sdk/wrapper.js.map +1 -0
  89. package/dist/instrumentation/cohere/index.d.ts +2 -3
  90. package/dist/instrumentation/cohere/index.js.map +1 -1
  91. package/dist/instrumentation/cohere/wrapper.d.ts +1 -1
  92. package/dist/instrumentation/cohere/wrapper.js +215 -56
  93. package/dist/instrumentation/cohere/wrapper.js.map +1 -1
  94. package/dist/instrumentation/google-adk/index.d.ts +57 -0
  95. package/dist/instrumentation/google-adk/index.js +371 -0
  96. package/dist/instrumentation/google-adk/index.js.map +1 -0
  97. package/dist/instrumentation/google-adk/utils.d.ts +45 -0
  98. package/dist/instrumentation/google-adk/utils.js +663 -0
  99. package/dist/instrumentation/google-adk/utils.js.map +1 -0
  100. package/dist/instrumentation/google-adk/wrapper.d.ts +11 -0
  101. package/dist/instrumentation/google-adk/wrapper.js +391 -0
  102. package/dist/instrumentation/google-adk/wrapper.js.map +1 -0
  103. package/dist/instrumentation/google-ai/wrapper.d.ts +7 -4
  104. package/dist/instrumentation/google-ai/wrapper.js +197 -61
  105. package/dist/instrumentation/google-ai/wrapper.js.map +1 -1
  106. package/dist/instrumentation/groq/wrapper.js +137 -65
  107. package/dist/instrumentation/groq/wrapper.js.map +1 -1
  108. package/dist/instrumentation/huggingface/wrapper.js +241 -39
  109. package/dist/instrumentation/huggingface/wrapper.js.map +1 -1
  110. package/dist/instrumentation/index.d.ts +2 -2
  111. package/dist/instrumentation/index.js +64 -6
  112. package/dist/instrumentation/index.js.map +1 -1
  113. package/dist/instrumentation/langchain/index.d.ts +0 -7
  114. package/dist/instrumentation/langchain/index.js +2 -20
  115. package/dist/instrumentation/langchain/index.js.map +1 -1
  116. package/dist/instrumentation/langchain/wrapper.d.ts +35 -0
  117. package/dist/instrumentation/langchain/wrapper.js +1098 -184
  118. package/dist/instrumentation/langchain/wrapper.js.map +1 -1
  119. package/dist/instrumentation/langgraph/index.d.ts +12 -0
  120. package/dist/instrumentation/langgraph/index.js +99 -0
  121. package/dist/instrumentation/langgraph/index.js.map +1 -0
  122. package/dist/instrumentation/langgraph/wrapper.d.ts +20 -0
  123. package/dist/instrumentation/langgraph/wrapper.js +619 -0
  124. package/dist/instrumentation/langgraph/wrapper.js.map +1 -0
  125. package/dist/instrumentation/llamaindex/index.d.ts +31 -6
  126. package/dist/instrumentation/llamaindex/index.js +180 -61
  127. package/dist/instrumentation/llamaindex/index.js.map +1 -1
  128. package/dist/instrumentation/llamaindex/wrapper.d.ts +15 -3
  129. package/dist/instrumentation/llamaindex/wrapper.js +670 -179
  130. package/dist/instrumentation/llamaindex/wrapper.js.map +1 -1
  131. package/dist/instrumentation/milvus/wrapper.js +1 -1
  132. package/dist/instrumentation/milvus/wrapper.js.map +1 -1
  133. package/dist/instrumentation/mistral/wrapper.js +154 -79
  134. package/dist/instrumentation/mistral/wrapper.js.map +1 -1
  135. package/dist/instrumentation/ollama/index.js +33 -4
  136. package/dist/instrumentation/ollama/index.js.map +1 -1
  137. package/dist/instrumentation/ollama/wrapper.d.ts +28 -2
  138. package/dist/instrumentation/ollama/wrapper.js +432 -48
  139. package/dist/instrumentation/ollama/wrapper.js.map +1 -1
  140. package/dist/instrumentation/openai/index.d.ts +2 -3
  141. package/dist/instrumentation/openai/index.js.map +1 -1
  142. package/dist/instrumentation/openai/wrapper.js +293 -194
  143. package/dist/instrumentation/openai/wrapper.js.map +1 -1
  144. package/dist/instrumentation/openai-agents/index.d.ts +20 -0
  145. package/dist/instrumentation/openai-agents/index.js +174 -0
  146. package/dist/instrumentation/openai-agents/index.js.map +1 -0
  147. package/dist/instrumentation/openai-agents/processor.d.ts +35 -0
  148. package/dist/instrumentation/openai-agents/processor.js +249 -0
  149. package/dist/instrumentation/openai-agents/processor.js.map +1 -0
  150. package/dist/instrumentation/openai-agents/utils.d.ts +20 -0
  151. package/dist/instrumentation/openai-agents/utils.js +624 -0
  152. package/dist/instrumentation/openai-agents/utils.js.map +1 -0
  153. package/dist/instrumentation/pinecone/wrapper.js +2 -2
  154. package/dist/instrumentation/pinecone/wrapper.js.map +1 -1
  155. package/dist/instrumentation/qdrant/wrapper.js +1 -1
  156. package/dist/instrumentation/qdrant/wrapper.js.map +1 -1
  157. package/dist/instrumentation/replicate/wrapper.js +103 -21
  158. package/dist/instrumentation/replicate/wrapper.js.map +1 -1
  159. package/dist/instrumentation/strands/index.d.ts +21 -0
  160. package/dist/instrumentation/strands/index.js +83 -0
  161. package/dist/instrumentation/strands/index.js.map +1 -0
  162. package/dist/instrumentation/strands/processor.d.ts +45 -0
  163. package/dist/instrumentation/strands/processor.js +545 -0
  164. package/dist/instrumentation/strands/processor.js.map +1 -0
  165. package/dist/instrumentation/strands/utils.d.ts +24 -0
  166. package/dist/instrumentation/strands/utils.js +360 -0
  167. package/dist/instrumentation/strands/utils.js.map +1 -0
  168. package/dist/instrumentation/together/wrapper.js +125 -51
  169. package/dist/instrumentation/together/wrapper.js.map +1 -1
  170. package/dist/instrumentation/vercel-ai/wrapper.d.ts +28 -2
  171. package/dist/instrumentation/vercel-ai/wrapper.js +314 -164
  172. package/dist/instrumentation/vercel-ai/wrapper.js.map +1 -1
  173. package/dist/llm/anthropic.js +10 -6
  174. package/dist/llm/anthropic.js.map +1 -1
  175. package/dist/llm/openai.js +9 -5
  176. package/dist/llm/openai.js.map +1 -1
  177. package/dist/otel/__tests__/metrics.test.js +16 -27
  178. package/dist/otel/__tests__/metrics.test.js.map +1 -1
  179. package/dist/otel/events.d.ts +11 -0
  180. package/dist/otel/events.js +74 -0
  181. package/dist/otel/events.js.map +1 -0
  182. package/dist/otel/metrics.d.ts +5 -6
  183. package/dist/otel/metrics.js +66 -48
  184. package/dist/otel/metrics.js.map +1 -1
  185. package/dist/otel/tracing.d.ts +6 -2
  186. package/dist/otel/tracing.js +71 -24
  187. package/dist/otel/tracing.js.map +1 -1
  188. package/dist/otel/utils.d.ts +11 -0
  189. package/dist/otel/utils.js +34 -0
  190. package/dist/otel/utils.js.map +1 -0
  191. package/dist/semantic-convention.d.ts +44 -5
  192. package/dist/semantic-convention.js +51 -8
  193. package/dist/semantic-convention.js.map +1 -1
  194. package/dist/types.d.ts +74 -22
  195. package/package.json +41 -9
@@ -0,0 +1,663 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PassthroughTracer = exports.OPERATION_MAP = exports.adkWorkflowActive = void 0;
7
+ exports.isAdkWorkflowActive = isAdkWorkflowActive;
8
+ exports.getOperationType = getOperationType;
9
+ exports.getSpanKind = getSpanKind;
10
+ exports.generateSpanName = generateSpanName;
11
+ exports.resolveModelString = resolveModelString;
12
+ exports.extractModelName = extractModelName;
13
+ exports.resolveServerInfo = resolveServerInfo;
14
+ exports.setCommonSpanAttributes = setCommonSpanAttributes;
15
+ exports.captureInputMessages = captureInputMessages;
16
+ exports.captureOutputMessages = captureOutputMessages;
17
+ exports.captureEventOutput = captureEventOutput;
18
+ exports.extractTokenUsage = extractTokenUsage;
19
+ exports.enrichLlmSpan = enrichLlmSpan;
20
+ exports.enrichToolSpan = enrichToolSpan;
21
+ exports.enrichMergedToolSpan = enrichMergedToolSpan;
22
+ exports.setRunnerAgentAttributes = setRunnerAgentAttributes;
23
+ exports.setAgentAttributes = setAgentAttributes;
24
+ exports.processGoogleAdkResponse = processGoogleAdkResponse;
25
+ exports.recordGoogleAdkMetrics = recordGoogleAdkMetrics;
26
+ const api_1 = require("@opentelemetry/api");
27
+ const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
28
+ const async_hooks_1 = require("async_hooks");
29
+ const semantic_convention_1 = __importDefault(require("../../semantic-convention"));
30
+ const config_1 = __importDefault(require("../../config"));
31
+ const constant_1 = require("../../constant");
32
+ const helpers_1 = require("../../helpers");
33
+ /**
34
+ * Prevents Runner.run_async from creating a second invoke_agent span
35
+ * when called internally by Runner.run (mirrors Python _ADK_WORKFLOW_ACTIVE).
36
+ */
37
+ exports.adkWorkflowActive = new async_hooks_1.AsyncLocalStorage();
38
+ function isAdkWorkflowActive() {
39
+ return exports.adkWorkflowActive.getStore() === true;
40
+ }
41
+ // ---------------------------------------------------------------------------
42
+ // OTel GenAI operation mapping (mirrors Python OPERATION_MAP)
43
+ // ---------------------------------------------------------------------------
44
+ exports.OPERATION_MAP = {
45
+ agent_init: semantic_convention_1.default.GEN_AI_OPERATION_TYPE_CREATE_AGENT,
46
+ runner_run_async: semantic_convention_1.default.GEN_AI_OPERATION_TYPE_AGENT,
47
+ runner_run: semantic_convention_1.default.GEN_AI_OPERATION_TYPE_AGENT,
48
+ runner_run_live: semantic_convention_1.default.GEN_AI_OPERATION_TYPE_AGENT,
49
+ agent_run_async: semantic_convention_1.default.GEN_AI_OPERATION_TYPE_AGENT,
50
+ };
51
+ const SPAN_KIND_MAP = {
52
+ [semantic_convention_1.default.GEN_AI_OPERATION_TYPE_CREATE_AGENT]: api_1.SpanKind.CLIENT,
53
+ [semantic_convention_1.default.GEN_AI_OPERATION_TYPE_FRAMEWORK]: api_1.SpanKind.INTERNAL,
54
+ [semantic_convention_1.default.GEN_AI_OPERATION_TYPE_AGENT]: api_1.SpanKind.INTERNAL,
55
+ [semantic_convention_1.default.GEN_AI_OPERATION_TYPE_TOOLS]: api_1.SpanKind.INTERNAL,
56
+ [semantic_convention_1.default.GEN_AI_OPERATION_TYPE_CHAT]: api_1.SpanKind.CLIENT,
57
+ };
58
+ function getOperationType(endpoint) {
59
+ return exports.OPERATION_MAP[endpoint] ?? semantic_convention_1.default.GEN_AI_OPERATION_TYPE_AGENT;
60
+ }
61
+ function getSpanKind(operationType) {
62
+ return SPAN_KIND_MAP[operationType] ?? api_1.SpanKind.INTERNAL;
63
+ }
64
+ // ---------------------------------------------------------------------------
65
+ // Span name generation (mirrors Python generate_span_name)
66
+ // ---------------------------------------------------------------------------
67
+ function generateSpanName(endpoint, instance) {
68
+ if (endpoint === 'agent_init') {
69
+ const name = instance?.name ?? 'agent';
70
+ return `create_agent ${name}`;
71
+ }
72
+ if (endpoint === 'runner_run_async' || endpoint === 'runner_run' || endpoint === 'runner_run_live') {
73
+ const appName = instance?.app_name ?? instance?._app_name ?? 'google_adk';
74
+ return `invoke_agent ${appName}`;
75
+ }
76
+ if (endpoint === 'agent_run_async') {
77
+ const name = instance?.name ?? 'agent';
78
+ return `invoke_agent ${name}`;
79
+ }
80
+ return `${getOperationType(endpoint)} ${endpoint}`;
81
+ }
82
+ // ---------------------------------------------------------------------------
83
+ // PassthroughTracer (mirrors Python _PassthroughTracer)
84
+ // ---------------------------------------------------------------------------
85
+ /**
86
+ * Drop-in replacement for ADK's tracer objects. Overrides
87
+ * `startActiveSpan` to yield the current span instead of creating a new one,
88
+ * letting OpenLIT own top-level spans while ADK's code still runs.
89
+ */
90
+ class PassthroughTracer {
91
+ constructor(wrapped) {
92
+ this._wrapped = wrapped;
93
+ }
94
+ startActiveSpan(...args) {
95
+ const fn = args[args.length - 1];
96
+ if (typeof fn === 'function') {
97
+ const currentSpan = api_1.trace.getActiveSpan();
98
+ return fn(currentSpan);
99
+ }
100
+ return undefined;
101
+ }
102
+ startSpan(...args) {
103
+ return this._wrapped.startSpan(...args);
104
+ }
105
+ }
106
+ exports.PassthroughTracer = PassthroughTracer;
107
+ // ---------------------------------------------------------------------------
108
+ // Model extraction (mirrors Python _resolve_model_string / extract_model_name)
109
+ // ---------------------------------------------------------------------------
110
+ function resolveModelString(modelObj) {
111
+ if (typeof modelObj === 'string')
112
+ return modelObj;
113
+ if (!modelObj)
114
+ return null;
115
+ const modelName = modelObj.model_name ?? modelObj.modelName;
116
+ if (typeof modelName === 'string')
117
+ return modelName;
118
+ const inner = modelObj.model;
119
+ if (typeof inner === 'string')
120
+ return inner;
121
+ return null;
122
+ }
123
+ function extractModelName(instance) {
124
+ try {
125
+ const model = instance?.model;
126
+ if (model) {
127
+ const resolved = resolveModelString(model);
128
+ if (resolved)
129
+ return resolved;
130
+ }
131
+ const rootAgent = instance?.agent;
132
+ if (rootAgent)
133
+ return extractModelName(rootAgent);
134
+ }
135
+ catch { /* ignore */ }
136
+ return 'unknown';
137
+ }
138
+ // ---------------------------------------------------------------------------
139
+ // Server address resolution (mirrors Python resolve_server_info)
140
+ // ---------------------------------------------------------------------------
141
+ const PREFIX_TO_PROVIDER = {
142
+ anthropic: 'anthropic',
143
+ claude: 'anthropic',
144
+ openai: 'openai',
145
+ gpt: 'openai',
146
+ mistral: 'mistral_ai',
147
+ cohere: 'cohere',
148
+ };
149
+ function detectProviderFromModelStr(modelStr) {
150
+ if (!modelStr)
151
+ return null;
152
+ const lower = modelStr.toLowerCase();
153
+ const prefix = lower.includes('/') ? lower.split('/')[0] : lower.split('-')[0];
154
+ const providerKey = PREFIX_TO_PROVIDER[prefix];
155
+ if (!providerKey)
156
+ return null;
157
+ const [addr, port] = (0, helpers_1.getServerAddressForProvider)(providerKey);
158
+ if (!addr)
159
+ return null;
160
+ return [addr, port, providerKey];
161
+ }
162
+ function resolveServerInfo(instance, modelName) {
163
+ if (modelName) {
164
+ const detected = detectProviderFromModelStr(modelName);
165
+ if (detected)
166
+ return detected;
167
+ }
168
+ if (instance) {
169
+ try {
170
+ let modelObj = instance.model;
171
+ if (!modelObj) {
172
+ const agent = instance.agent;
173
+ if (agent)
174
+ modelObj = agent.model;
175
+ }
176
+ if (modelObj) {
177
+ const resolved = resolveModelString(modelObj);
178
+ if (resolved) {
179
+ const detected = detectProviderFromModelStr(resolved);
180
+ if (detected)
181
+ return detected;
182
+ }
183
+ }
184
+ }
185
+ catch { /* ignore */ }
186
+ }
187
+ const useVertex = (process.env.GOOGLE_GENAI_USE_VERTEXAI || '').toLowerCase();
188
+ if (useVertex === 'true' || useVertex === '1') {
189
+ const [addr, port] = (0, helpers_1.getServerAddressForProvider)('gcp.vertex_ai');
190
+ return [addr, port, 'gcp.vertex_ai'];
191
+ }
192
+ const [addr, port] = (0, helpers_1.getServerAddressForProvider)('gcp.gemini');
193
+ return [addr, port, 'gcp.gemini'];
194
+ }
195
+ // ---------------------------------------------------------------------------
196
+ // Common span attributes (mirrors Python common_framework_span_attributes)
197
+ // ---------------------------------------------------------------------------
198
+ function setCommonSpanAttributes(span, operationType) {
199
+ span.setAttribute(semantic_conventions_1.ATTR_TELEMETRY_SDK_NAME, constant_1.SDK_NAME);
200
+ span.setAttribute(semantic_convention_1.default.ATTR_DEPLOYMENT_ENVIRONMENT, config_1.default.environment || 'default');
201
+ span.setAttribute(semantic_conventions_1.ATTR_SERVICE_NAME, config_1.default.applicationName || 'default');
202
+ span.setAttribute(semantic_convention_1.default.GEN_AI_SDK_VERSION, constant_1.SDK_VERSION);
203
+ span.setAttribute(semantic_convention_1.default.GEN_AI_OPERATION, operationType);
204
+ span.setAttribute(semantic_convention_1.default.GEN_AI_PROVIDER_NAME_OTEL, semantic_convention_1.default.GEN_AI_SYSTEM_GOOGLE_ADK);
205
+ }
206
+ // ---------------------------------------------------------------------------
207
+ // Content extraction helpers (mirrors Python _extract_parts)
208
+ // ---------------------------------------------------------------------------
209
+ function truncateContent(str, maxLen) {
210
+ const limit = maxLen ?? config_1.default.maxContentLength;
211
+ if (limit && str.length > limit)
212
+ return str.slice(0, limit) + '...';
213
+ return str;
214
+ }
215
+ function extractParts(parts) {
216
+ const textParts = [];
217
+ const toolCalls = [];
218
+ const toolResponses = [];
219
+ for (const part of parts || []) {
220
+ const text = part?.text;
221
+ if (text)
222
+ textParts.push(truncateContent(String(text)));
223
+ const fc = part?.function_call ?? part?.functionCall;
224
+ if (fc) {
225
+ const entry = {
226
+ name: fc.name ?? '',
227
+ id: fc.id ?? '',
228
+ };
229
+ const fcArgs = fc.args;
230
+ if (fcArgs) {
231
+ try {
232
+ entry.arguments = typeof fcArgs === 'object' ? JSON.stringify(fcArgs) : String(fcArgs);
233
+ }
234
+ catch {
235
+ entry.arguments = String(fcArgs);
236
+ }
237
+ }
238
+ toolCalls.push(entry);
239
+ }
240
+ const fr = part?.function_response ?? part?.functionResponse;
241
+ if (fr) {
242
+ const respEntry = {
243
+ name: fr.name ?? '',
244
+ id: fr.id ?? '',
245
+ };
246
+ const frResp = fr.response;
247
+ if (frResp != null) {
248
+ try {
249
+ respEntry.content = typeof frResp === 'object' ? JSON.stringify(frResp) : String(frResp);
250
+ }
251
+ catch {
252
+ respEntry.content = String(frResp);
253
+ }
254
+ }
255
+ toolResponses.push(respEntry);
256
+ }
257
+ }
258
+ return { textParts, toolCalls, toolResponses };
259
+ }
260
+ // ---------------------------------------------------------------------------
261
+ // Input/Output message capture (mirrors Python capture_input_messages / capture_output_messages)
262
+ // ---------------------------------------------------------------------------
263
+ function captureInputMessages(span, llmRequest, captureContent) {
264
+ if (!captureContent)
265
+ return;
266
+ try {
267
+ const contents = llmRequest?.contents;
268
+ if (!contents)
269
+ return;
270
+ const messages = [];
271
+ for (const content of contents.slice(0, 20)) {
272
+ const role = content?.role ?? 'user';
273
+ const rawParts = content?.parts ?? [];
274
+ const { textParts, toolCalls, toolResponses } = extractParts(rawParts);
275
+ const parts = [];
276
+ for (const text of textParts)
277
+ parts.push({ type: 'text', content: text });
278
+ for (const tc of toolCalls) {
279
+ parts.push({ type: 'tool_call', id: tc.id, name: tc.name, arguments: tc.arguments ?? '' });
280
+ }
281
+ for (const tr of toolResponses) {
282
+ parts.push({ type: 'tool_call_response', id: tr.id, response: tr.content ?? '' });
283
+ }
284
+ if (parts.length > 0)
285
+ messages.push({ role: String(role), parts });
286
+ }
287
+ if (messages.length > 0) {
288
+ span.setAttribute(semantic_convention_1.default.GEN_AI_INPUT_MESSAGES, JSON.stringify(messages));
289
+ }
290
+ }
291
+ catch { /* ignore */ }
292
+ }
293
+ function captureOutputMessages(span, llmResponse, captureContent, finishReason = 'stop') {
294
+ if (!captureContent)
295
+ return;
296
+ try {
297
+ const content = llmResponse?.content;
298
+ if (!content)
299
+ return;
300
+ const rawParts = content.parts ?? [];
301
+ const { textParts, toolCalls } = extractParts(rawParts);
302
+ const parts = [];
303
+ for (const text of textParts)
304
+ parts.push({ type: 'text', content: text });
305
+ for (const tc of toolCalls) {
306
+ parts.push({ type: 'tool_call', id: tc.id, name: tc.name, arguments: tc.arguments ?? '' });
307
+ }
308
+ if (parts.length > 0) {
309
+ const messages = [{ role: 'assistant', parts, finish_reason: finishReason }];
310
+ span.setAttribute(semantic_convention_1.default.GEN_AI_OUTPUT_MESSAGES, JSON.stringify(messages));
311
+ }
312
+ }
313
+ catch { /* ignore */ }
314
+ }
315
+ function captureEventOutput(span, event, captureContent) {
316
+ if (!captureContent)
317
+ return;
318
+ try {
319
+ const content = event?.content;
320
+ if (!content)
321
+ return;
322
+ const rawParts = content.parts ?? [];
323
+ const { textParts, toolCalls } = extractParts(rawParts);
324
+ const parts = [];
325
+ for (const text of textParts)
326
+ parts.push({ type: 'text', content: text });
327
+ for (const tc of toolCalls) {
328
+ parts.push({ type: 'tool_call', id: tc.id, name: tc.name, arguments: tc.arguments ?? '' });
329
+ }
330
+ if (parts.length > 0) {
331
+ const messages = [{ role: 'assistant', parts, finish_reason: 'stop' }];
332
+ span.setAttribute(semantic_convention_1.default.GEN_AI_OUTPUT_MESSAGES, JSON.stringify(messages));
333
+ }
334
+ }
335
+ catch { /* ignore */ }
336
+ }
337
+ function extractTokenUsage(llmResponse) {
338
+ try {
339
+ const usage = llmResponse?.usage_metadata ?? llmResponse?.usageMetadata;
340
+ if (!usage)
341
+ return {};
342
+ return {
343
+ inputTokens: usage.prompt_token_count ?? usage.promptTokenCount,
344
+ outputTokens: usage.candidates_token_count ?? usage.candidatesTokenCount,
345
+ reasoningTokens: usage.thoughts_token_count ?? usage.thoughtsTokenCount,
346
+ cachedTokens: usage.cached_content_token_count ?? usage.cachedContentTokenCount,
347
+ totalTokens: usage.total_token_count ?? usage.totalTokenCount,
348
+ };
349
+ }
350
+ catch {
351
+ return {};
352
+ }
353
+ }
354
+ // ---------------------------------------------------------------------------
355
+ // Output type detection (mirrors Python _determine_output_type)
356
+ // ---------------------------------------------------------------------------
357
+ function determineOutputType(llmResponse) {
358
+ try {
359
+ const content = llmResponse?.content;
360
+ if (content) {
361
+ for (const part of (content.parts ?? [])) {
362
+ if (part?.function_call || part?.functionCall)
363
+ return 'tool_calls';
364
+ }
365
+ }
366
+ }
367
+ catch { /* ignore */ }
368
+ return 'text';
369
+ }
370
+ // ---------------------------------------------------------------------------
371
+ // LLM span enrichment (mirrors Python enrich_llm_span)
372
+ // ---------------------------------------------------------------------------
373
+ function enrichLlmSpan(span, llmRequest, llmResponse, captureMessageContent) {
374
+ try {
375
+ const requestModel = llmRequest?.model;
376
+ const modelStr = requestModel ? String(requestModel) : null;
377
+ const [serverAddress, serverPort, providerName] = resolveServerInfo(undefined, modelStr);
378
+ span.setAttribute(semantic_convention_1.default.GEN_AI_OPERATION, semantic_convention_1.default.GEN_AI_OPERATION_TYPE_CHAT);
379
+ span.setAttribute(semantic_convention_1.default.GEN_AI_PROVIDER_NAME_OTEL, providerName);
380
+ span.setAttribute(semantic_convention_1.default.SERVER_ADDRESS, serverAddress);
381
+ span.setAttribute(semantic_convention_1.default.SERVER_PORT, serverPort);
382
+ if (llmRequest) {
383
+ if (modelStr)
384
+ span.setAttribute(semantic_convention_1.default.GEN_AI_REQUEST_MODEL, modelStr);
385
+ const config = llmRequest.config;
386
+ if (config) {
387
+ const temp = config.temperature;
388
+ if (temp != null)
389
+ span.setAttribute(semantic_convention_1.default.GEN_AI_REQUEST_TEMPERATURE, Number(temp));
390
+ const topP = config.top_p ?? config.topP;
391
+ if (topP != null)
392
+ span.setAttribute(semantic_convention_1.default.GEN_AI_REQUEST_TOP_P, Number(topP));
393
+ const maxTokens = config.max_output_tokens ?? config.maxOutputTokens;
394
+ if (maxTokens != null)
395
+ span.setAttribute(semantic_convention_1.default.GEN_AI_REQUEST_MAX_TOKENS, Number(maxTokens));
396
+ }
397
+ if (captureMessageContent) {
398
+ const sysInstr = config?.system_instruction ?? config?.systemInstruction;
399
+ if (sysInstr) {
400
+ const instrText = typeof sysInstr === 'string' ? sysInstr : String(sysInstr);
401
+ span.setAttribute(semantic_convention_1.default.GEN_AI_SYSTEM_INSTRUCTIONS, JSON.stringify([{ type: 'text', content: truncateContent(instrText) }]));
402
+ }
403
+ }
404
+ captureInputMessages(span, llmRequest, captureMessageContent);
405
+ }
406
+ if (llmResponse) {
407
+ const { inputTokens, outputTokens, reasoningTokens, cachedTokens, totalTokens } = extractTokenUsage(llmResponse);
408
+ if (inputTokens != null)
409
+ span.setAttribute(semantic_convention_1.default.GEN_AI_USAGE_INPUT_TOKENS, inputTokens);
410
+ if (outputTokens != null)
411
+ span.setAttribute(semantic_convention_1.default.GEN_AI_USAGE_OUTPUT_TOKENS, outputTokens);
412
+ if (reasoningTokens != null)
413
+ span.setAttribute(semantic_convention_1.default.GEN_AI_USAGE_COMPLETION_TOKENS_DETAILS_REASONING, reasoningTokens);
414
+ if (cachedTokens != null)
415
+ span.setAttribute(semantic_convention_1.default.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, cachedTokens);
416
+ if (totalTokens != null)
417
+ span.setAttribute(semantic_convention_1.default.GEN_AI_USAGE_TOTAL_TOKENS, totalTokens);
418
+ const responseModel = llmResponse.model_version ?? llmResponse.modelVersion;
419
+ if (responseModel)
420
+ span.setAttribute(semantic_convention_1.default.GEN_AI_RESPONSE_MODEL, String(responseModel));
421
+ let frStr = 'stop';
422
+ const finishReason = llmResponse.finish_reason ?? llmResponse.finishReason;
423
+ if (finishReason) {
424
+ try {
425
+ frStr = (typeof finishReason === 'object' && finishReason.value)
426
+ ? String(finishReason.value).toLowerCase()
427
+ : String(finishReason).toLowerCase();
428
+ }
429
+ catch {
430
+ frStr = String(finishReason).toLowerCase();
431
+ }
432
+ span.setAttribute(semantic_convention_1.default.GEN_AI_RESPONSE_FINISH_REASON, [frStr]);
433
+ }
434
+ const responseId = llmResponse.response_id ?? llmResponse.responseId ?? llmResponse.id;
435
+ if (responseId)
436
+ span.setAttribute(semantic_convention_1.default.GEN_AI_RESPONSE_ID, String(responseId));
437
+ const errorCode = llmResponse.error_code ?? llmResponse.errorCode;
438
+ if (errorCode) {
439
+ span.setAttribute(semantic_convention_1.default.ERROR_TYPE, String(errorCode));
440
+ const errorMessage = llmResponse.error_message ?? llmResponse.errorMessage;
441
+ if (errorMessage)
442
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: String(errorMessage) });
443
+ }
444
+ captureOutputMessages(span, llmResponse, captureMessageContent, frStr);
445
+ span.setAttribute(semantic_convention_1.default.GEN_AI_OUTPUT_TYPE, determineOutputType(llmResponse));
446
+ }
447
+ }
448
+ catch { /* ignore */ }
449
+ }
450
+ // ---------------------------------------------------------------------------
451
+ // ADK Event extraction (mirrors Python _extract_from_event / _is_adk_event)
452
+ // ---------------------------------------------------------------------------
453
+ function isAdkEvent(obj) {
454
+ if (!obj)
455
+ return false;
456
+ return (obj.constructor?.name === 'Event') && ('content' in obj);
457
+ }
458
+ function extractFromEvent(eventObj) {
459
+ try {
460
+ const content = eventObj?.content;
461
+ if (!content)
462
+ return [null, null];
463
+ const parts = content.parts;
464
+ if (!parts || parts.length === 0)
465
+ return [null, null];
466
+ const fnResp = parts[0]?.function_response ?? parts[0]?.functionResponse;
467
+ if (!fnResp)
468
+ return [null, null];
469
+ return [fnResp.response ?? null, fnResp.id ?? null];
470
+ }
471
+ catch {
472
+ return [null, null];
473
+ }
474
+ }
475
+ // ---------------------------------------------------------------------------
476
+ // Tool type mapping (mirrors Python _otel_gen_ai_tool_type)
477
+ // ---------------------------------------------------------------------------
478
+ function otelToolType(tool) {
479
+ const name = tool?.constructor?.name ?? '';
480
+ if (name.includes('Function'))
481
+ return 'function';
482
+ if (name.includes('Agent'))
483
+ return 'extension';
484
+ return 'function';
485
+ }
486
+ // ---------------------------------------------------------------------------
487
+ // Tool span enrichment (mirrors Python enrich_tool_span)
488
+ // ---------------------------------------------------------------------------
489
+ function enrichToolSpan(span, tool, functionArgs, functionResponseEvent, captureMessageContent, error) {
490
+ try {
491
+ span.setAttribute(semantic_convention_1.default.GEN_AI_OPERATION, semantic_convention_1.default.GEN_AI_OPERATION_TYPE_TOOLS);
492
+ span.setAttribute(semantic_convention_1.default.GEN_AI_PROVIDER_NAME_OTEL, semantic_convention_1.default.GEN_AI_SYSTEM_GOOGLE_ADK);
493
+ if (tool) {
494
+ const toolName = tool.name ?? tool.constructor?.name ?? 'unknown';
495
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_NAME, String(toolName));
496
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_TYPE, otelToolType(tool));
497
+ const toolDesc = tool.description;
498
+ if (toolDesc)
499
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_DESCRIPTION, truncateContent(String(toolDesc)));
500
+ }
501
+ let responseDict = null;
502
+ let toolCallId = null;
503
+ if (isAdkEvent(functionResponseEvent)) {
504
+ [responseDict, toolCallId] = extractFromEvent(functionResponseEvent);
505
+ }
506
+ else if (typeof functionResponseEvent === 'object' && functionResponseEvent !== null) {
507
+ responseDict = functionResponseEvent;
508
+ toolCallId = functionResponseEvent.id ?? null;
509
+ }
510
+ if (captureMessageContent) {
511
+ if (functionArgs != null) {
512
+ try {
513
+ const argsStr = typeof functionArgs === 'object' ? JSON.stringify(functionArgs) : String(functionArgs);
514
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_CALL_ARGUMENTS, truncateContent(argsStr));
515
+ }
516
+ catch {
517
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_CALL_ARGUMENTS, truncateContent(String(functionArgs)));
518
+ }
519
+ }
520
+ if (responseDict != null) {
521
+ try {
522
+ const resultStr = typeof responseDict === 'object' ? JSON.stringify(responseDict) : String(responseDict);
523
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_CALL_RESULT, truncateContent(resultStr));
524
+ }
525
+ catch {
526
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_CALL_RESULT, truncateContent(String(responseDict)));
527
+ }
528
+ }
529
+ }
530
+ if (toolCallId)
531
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_CALL_ID, String(toolCallId));
532
+ if (error != null) {
533
+ const errorType = error.constructor?.name || '_OTHER';
534
+ span.setAttribute(semantic_convention_1.default.ERROR_TYPE, errorType);
535
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: String(error) });
536
+ }
537
+ }
538
+ catch { /* ignore */ }
539
+ }
540
+ // ---------------------------------------------------------------------------
541
+ // Merged tool span enrichment (mirrors Python enrich_merged_tool_span)
542
+ // ---------------------------------------------------------------------------
543
+ function enrichMergedToolSpan(span, responseEventId, functionResponseEvent, captureMessageContent) {
544
+ try {
545
+ span.setAttribute(semantic_convention_1.default.GEN_AI_OPERATION, semantic_convention_1.default.GEN_AI_OPERATION_TYPE_TOOLS);
546
+ span.setAttribute(semantic_convention_1.default.GEN_AI_PROVIDER_NAME_OTEL, semantic_convention_1.default.GEN_AI_SYSTEM_GOOGLE_ADK);
547
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_NAME, '(merged tools)');
548
+ if (responseEventId)
549
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_CALL_ID, String(responseEventId));
550
+ if (captureMessageContent && functionResponseEvent != null) {
551
+ try {
552
+ const content = functionResponseEvent.content;
553
+ if (content) {
554
+ const parts = content.parts ?? [];
555
+ const toolResults = [];
556
+ for (const part of parts) {
557
+ const fnResp = part?.function_response ?? part?.functionResponse;
558
+ if (fnResp) {
559
+ const entry = {};
560
+ const name = fnResp.name;
561
+ if (name)
562
+ entry.name = String(name);
563
+ const resp = fnResp.response;
564
+ if (resp != null)
565
+ entry.response = resp;
566
+ if (Object.keys(entry).length > 0)
567
+ toolResults.push(entry);
568
+ }
569
+ }
570
+ if (toolResults.length > 0) {
571
+ span.setAttribute(semantic_convention_1.default.GEN_AI_TOOL_CALL_RESULT, truncateContent(JSON.stringify(toolResults)));
572
+ }
573
+ }
574
+ }
575
+ catch { /* ignore */ }
576
+ }
577
+ }
578
+ catch { /* ignore */ }
579
+ }
580
+ // ---------------------------------------------------------------------------
581
+ // Runner/Agent attribute setters (mirrors Python _set_runner_agent_attributes / _set_agent_attributes)
582
+ // ---------------------------------------------------------------------------
583
+ function setRunnerAgentAttributes(span, instance, endpoint) {
584
+ try {
585
+ const appName = instance?.app_name ?? instance?._app_name ?? 'google_adk';
586
+ span.setAttribute(semantic_convention_1.default.GEN_AI_AGENT_NAME, String(appName));
587
+ if (endpoint === 'runner_run_live') {
588
+ span.setAttribute(semantic_convention_1.default.GEN_AI_EXECUTION_MODE, 'live');
589
+ }
590
+ else if (endpoint === 'runner_run') {
591
+ span.setAttribute(semantic_convention_1.default.GEN_AI_EXECUTION_MODE, 'sync');
592
+ }
593
+ else {
594
+ span.setAttribute(semantic_convention_1.default.GEN_AI_EXECUTION_MODE, 'async');
595
+ }
596
+ }
597
+ catch { /* ignore */ }
598
+ }
599
+ function setAgentAttributes(span, instance) {
600
+ try {
601
+ const name = instance?.name;
602
+ if (name)
603
+ span.setAttribute(semantic_convention_1.default.GEN_AI_AGENT_NAME, String(name));
604
+ const description = instance?.description;
605
+ if (description)
606
+ span.setAttribute(semantic_convention_1.default.GEN_AI_AGENT_DESCRIPTION, String(description));
607
+ }
608
+ catch { /* ignore */ }
609
+ }
610
+ // ---------------------------------------------------------------------------
611
+ // Response processing for Runner/Agent spans (mirrors Python process_google_adk_response)
612
+ // ---------------------------------------------------------------------------
613
+ function processGoogleAdkResponse(span, endpoint, instance, startTime, _captureMessageContent) {
614
+ const endTime = Date.now();
615
+ const operationType = getOperationType(endpoint);
616
+ const [serverAddress, serverPort] = resolveServerInfo(instance);
617
+ const requestModel = extractModelName(instance);
618
+ setCommonSpanAttributes(span, operationType);
619
+ if (requestModel && requestModel !== 'unknown') {
620
+ span.setAttribute(semantic_convention_1.default.GEN_AI_REQUEST_MODEL, requestModel);
621
+ }
622
+ if (serverAddress)
623
+ span.setAttribute(semantic_convention_1.default.SERVER_ADDRESS, serverAddress);
624
+ if (serverPort)
625
+ span.setAttribute(semantic_convention_1.default.SERVER_PORT, serverPort);
626
+ if (endpoint === 'runner_run_async' || endpoint === 'runner_run' || endpoint === 'runner_run_live') {
627
+ setRunnerAgentAttributes(span, instance, endpoint);
628
+ }
629
+ else if (endpoint === 'agent_run_async') {
630
+ setAgentAttributes(span, instance);
631
+ }
632
+ span.setAttribute(semantic_convention_1.default.GEN_AI_OUTPUT_TYPE, semantic_convention_1.default.GEN_AI_OUTPUT_TYPE_TEXT);
633
+ span.setAttribute(semantic_convention_1.default.GEN_AI_CLIENT_OPERATION_DURATION, (endTime - startTime) / 1000);
634
+ (0, helpers_1.applyCustomSpanAttributes)(span);
635
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
636
+ }
637
+ // ---------------------------------------------------------------------------
638
+ // Metrics recording (mirrors Python record_google_adk_metrics)
639
+ // ---------------------------------------------------------------------------
640
+ function recordGoogleAdkMetrics(operationType, duration, requestModel, serverAddress, serverPort) {
641
+ try {
642
+ const Metrics = require('../../otel/metrics').default;
643
+ const attributes = {
644
+ [semantic_conventions_1.ATTR_TELEMETRY_SDK_NAME]: constant_1.SDK_NAME,
645
+ [semantic_conventions_1.ATTR_SERVICE_NAME]: config_1.default.applicationName || 'default',
646
+ [semantic_convention_1.default.ATTR_DEPLOYMENT_ENVIRONMENT]: config_1.default.environment || 'default',
647
+ [semantic_convention_1.default.GEN_AI_OPERATION]: operationType,
648
+ [semantic_convention_1.default.GEN_AI_PROVIDER_NAME_OTEL]: semantic_convention_1.default.GEN_AI_SYSTEM_GOOGLE_ADK,
649
+ };
650
+ if (requestModel && requestModel !== 'unknown') {
651
+ attributes[semantic_convention_1.default.GEN_AI_REQUEST_MODEL] = requestModel;
652
+ }
653
+ if (serverAddress)
654
+ attributes[semantic_convention_1.default.SERVER_ADDRESS] = serverAddress;
655
+ if (serverPort)
656
+ attributes[semantic_convention_1.default.SERVER_PORT] = serverPort;
657
+ if (Metrics.genaiClientOperationDuration) {
658
+ Metrics.genaiClientOperationDuration.record(duration, attributes);
659
+ }
660
+ }
661
+ catch { /* ignore */ }
662
+ }
663
+ //# sourceMappingURL=utils.js.map