promptlayer 1.0.60 → 1.1.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 (37) hide show
  1. package/README.md +9 -0
  2. package/dist/esm/chunk-SWBNW72U.js +2 -0
  3. package/dist/esm/chunk-SWBNW72U.js.map +1 -0
  4. package/dist/esm/index.js +2 -2
  5. package/dist/esm/index.js.map +1 -1
  6. package/dist/esm/openai-agents.js +3 -0
  7. package/dist/esm/openai-agents.js.map +1 -0
  8. package/dist/index.d.mts +229 -9
  9. package/dist/index.d.ts +229 -9
  10. package/dist/index.js +2 -2
  11. package/dist/index.js.map +1 -1
  12. package/dist/openai-agents.d.mts +42 -0
  13. package/dist/openai-agents.d.ts +42 -0
  14. package/dist/openai-agents.js +3 -0
  15. package/dist/openai-agents.js.map +1 -0
  16. package/package.json +24 -3
  17. package/src/integrations/openai-agents/helpers.test.ts +254 -0
  18. package/src/integrations/openai-agents/ids.ts +27 -0
  19. package/src/integrations/openai-agents/index.ts +8 -0
  20. package/src/integrations/openai-agents/instrumentation.test.ts +46 -0
  21. package/src/integrations/openai-agents/instrumentation.ts +47 -0
  22. package/src/integrations/openai-agents/mapping.ts +714 -0
  23. package/src/integrations/openai-agents/otlp-json.ts +120 -0
  24. package/src/integrations/openai-agents/processor.test.ts +509 -0
  25. package/src/integrations/openai-agents/processor.ts +388 -0
  26. package/src/integrations/openai-agents/time.ts +56 -0
  27. package/src/integrations/openai-agents/types.ts +49 -0
  28. package/src/integrations/openai-agents/url.ts +9 -0
  29. package/src/openai-agents.ts +1 -0
  30. package/src/types.ts +302 -9
  31. package/src/utils/blueprint-builder.test.ts +727 -0
  32. package/src/utils/blueprint-builder.ts +957 -126
  33. package/src/utils/streaming.test.ts +498 -0
  34. package/src/utils/streaming.ts +471 -43
  35. package/src/utils/utils.ts +4 -0
  36. package/tsup.config.ts +4 -1
  37. package/vitest.config.ts +3 -0
@@ -0,0 +1,714 @@
1
+ import { SDK_VERSION } from "@/utils/utils";
2
+ import type {
3
+ Span as AgentsSpan,
4
+ SpanData,
5
+ Trace as AgentsTrace,
6
+ } from "@openai/agents";
7
+ import type { AttributeValue } from "@/integrations/openai-agents/types";
8
+
9
+ const SPAN_KIND_INTERNAL = 1;
10
+ const SPAN_KIND_CLIENT = 3;
11
+
12
+ type AttributeMap = Record<string, AttributeValue>;
13
+ type NormalizedMessage = Record<string, AttributeValue>;
14
+ type NormalizedToolCall = {
15
+ id: string;
16
+ type: "tool_call";
17
+ name: string;
18
+ arguments: AttributeValue;
19
+ };
20
+
21
+ const isPlainObject = (value: unknown): value is Record<string, unknown> => {
22
+ return typeof value === "object" && value !== null && !Array.isArray(value);
23
+ };
24
+
25
+ const isScalar = (value: unknown): value is string | number | boolean => {
26
+ return (
27
+ typeof value === "string" ||
28
+ typeof value === "number" ||
29
+ typeof value === "boolean"
30
+ );
31
+ };
32
+
33
+ const sanitizeKey = (key: string): string => {
34
+ return key.replace(/[^a-zA-Z0-9_.-]/g, "_");
35
+ };
36
+
37
+ const toJsonable = (value: unknown): AttributeValue => {
38
+ if (
39
+ value === null ||
40
+ typeof value === "string" ||
41
+ typeof value === "number" ||
42
+ typeof value === "boolean"
43
+ ) {
44
+ return value;
45
+ }
46
+
47
+ if (Array.isArray(value)) {
48
+ return value.map((item) => toJsonable(item));
49
+ }
50
+
51
+ if (isPlainObject(value)) {
52
+ return Object.fromEntries(
53
+ Object.entries(value).map(([key, item]) => [key, toJsonable(item)])
54
+ );
55
+ }
56
+
57
+ return String(value);
58
+ };
59
+
60
+ const stableStringify = (value: unknown): string => {
61
+ const normalize = (input: unknown): unknown => {
62
+ if (Array.isArray(input)) {
63
+ return input.map((item) => normalize(item));
64
+ }
65
+
66
+ if (isPlainObject(input)) {
67
+ return Object.keys(input)
68
+ .sort()
69
+ .reduce<Record<string, unknown>>((acc, key) => {
70
+ acc[key] = normalize(input[key]);
71
+ return acc;
72
+ }, {});
73
+ }
74
+
75
+ return input;
76
+ };
77
+
78
+ return JSON.stringify(normalize(toJsonable(value)));
79
+ };
80
+
81
+ const setStringAttr = (attrs: AttributeMap, key: string, value: unknown) => {
82
+ if (value !== undefined && value !== null && value !== "") {
83
+ attrs[key] = String(value);
84
+ }
85
+ };
86
+
87
+ const setNumberAttr = (attrs: AttributeMap, key: string, value: unknown) => {
88
+ if (value !== undefined && value !== null && value !== "") {
89
+ const numericValue = Number(value);
90
+ if (!Number.isNaN(numericValue)) {
91
+ attrs[key] = numericValue;
92
+ }
93
+ }
94
+ };
95
+
96
+ const setJsonAttr = (
97
+ attrs: AttributeMap,
98
+ key: string,
99
+ value: unknown,
100
+ includeRawPayloads: boolean
101
+ ) => {
102
+ if (includeRawPayloads && value !== undefined && value !== null) {
103
+ attrs[key] = stableStringify(value);
104
+ }
105
+ };
106
+
107
+ const flattenIndexedMessages = (
108
+ prefix: string,
109
+ messages: NormalizedMessage[],
110
+ attrs: AttributeMap
111
+ ) => {
112
+ messages.forEach((message, index) => {
113
+ Object.entries(message).forEach(([key, value]) => {
114
+ attrs[`${prefix}.${index}.${key}`] = isScalar(value)
115
+ ? value
116
+ : stableStringify(value);
117
+ });
118
+ });
119
+ };
120
+
121
+ const normalizeToolCalls = (toolCalls: unknown): NormalizedToolCall[] => {
122
+ if (!Array.isArray(toolCalls)) {
123
+ return [];
124
+ }
125
+
126
+ return toolCalls
127
+ .map((call) => {
128
+ if (!isPlainObject(call)) {
129
+ return null;
130
+ }
131
+
132
+ const functionData = isPlainObject(call.function) ? call.function : null;
133
+ const name = functionData?.name ?? call.name ?? "tool";
134
+ let argumentsValue =
135
+ functionData?.arguments ?? call.arguments ?? {};
136
+
137
+ if (typeof argumentsValue === "string") {
138
+ try {
139
+ argumentsValue = JSON.parse(argumentsValue);
140
+ } catch {
141
+ argumentsValue = argumentsValue;
142
+ }
143
+ }
144
+
145
+ return {
146
+ id: String(call.id ?? ""),
147
+ type: "tool_call",
148
+ name: String(name),
149
+ arguments: toJsonable(argumentsValue),
150
+ };
151
+ })
152
+ .filter((call): call is NormalizedToolCall => call !== null);
153
+ };
154
+
155
+ const getCallId = (item: Record<string, unknown>): string | undefined => {
156
+ const value = item.call_id ?? item.callId ?? item.id;
157
+ return value !== undefined && value !== null ? String(value) : undefined;
158
+ };
159
+
160
+ const normalizeToolOutputContent = (output: unknown): string | undefined => {
161
+ if (output === undefined || output === null) {
162
+ return undefined;
163
+ }
164
+
165
+ if (typeof output === "string") {
166
+ return output;
167
+ }
168
+
169
+ if (Array.isArray(output)) {
170
+ const textContent = extractTextContent(output);
171
+ return textContent ?? stableStringify(output);
172
+ }
173
+
174
+ if (isPlainObject(output)) {
175
+ const textContent = extractTextContent([output]);
176
+ return textContent ?? stableStringify(output);
177
+ }
178
+
179
+ const textContent = extractTextContent(output);
180
+ if (textContent !== undefined) {
181
+ return textContent;
182
+ }
183
+
184
+ return stableStringify(output);
185
+ };
186
+
187
+ const normalizeToolCallMessage = (
188
+ item: Record<string, unknown>
189
+ ): NormalizedMessage | null => {
190
+ let argumentsValue = item.arguments ?? {};
191
+ if (typeof argumentsValue === "string") {
192
+ try {
193
+ argumentsValue = JSON.parse(argumentsValue);
194
+ } catch {
195
+ argumentsValue = argumentsValue;
196
+ }
197
+ }
198
+
199
+ return {
200
+ role: "assistant",
201
+ tool_calls: [
202
+ {
203
+ id: getCallId(item) ?? "",
204
+ type: "tool_call",
205
+ name: String(item.name ?? "tool"),
206
+ arguments: toJsonable(argumentsValue),
207
+ },
208
+ ],
209
+ };
210
+ };
211
+
212
+ const normalizeToolResultMessage = (
213
+ item: Record<string, unknown>,
214
+ outputOverride?: unknown
215
+ ): NormalizedMessage | null => {
216
+ const toolCallId = getCallId(item);
217
+ const content = normalizeToolOutputContent(
218
+ outputOverride ?? item.output ?? item.content
219
+ );
220
+
221
+ if (!toolCallId && !content) {
222
+ return null;
223
+ }
224
+
225
+ const message: NormalizedMessage = {
226
+ role: "tool",
227
+ };
228
+
229
+ if (toolCallId) {
230
+ message.tool_call_id = toolCallId;
231
+ }
232
+
233
+ if (content !== undefined) {
234
+ message.content = content;
235
+ }
236
+
237
+ return message;
238
+ };
239
+
240
+ function extractTextContent(content: unknown): string | undefined {
241
+ if (content === undefined || content === null) {
242
+ return undefined;
243
+ }
244
+
245
+ if (typeof content === "string") {
246
+ return content;
247
+ }
248
+
249
+ if (Array.isArray(content)) {
250
+ const textParts = content
251
+ .map((part) => {
252
+ if (!isPlainObject(part)) {
253
+ return null;
254
+ }
255
+
256
+ const partType = part.type;
257
+ if (
258
+ partType === "text" ||
259
+ partType === "input_text" ||
260
+ partType === "output_text"
261
+ ) {
262
+ const text = part.text ?? part.content;
263
+ return text !== undefined && text !== null ? String(text) : null;
264
+ }
265
+
266
+ return null;
267
+ })
268
+ .filter((part): part is string => part !== null);
269
+
270
+ return textParts.length > 0 ? textParts.join("\n") : undefined;
271
+ }
272
+
273
+ return String(content);
274
+ }
275
+
276
+ export const normalizeMessages = (items: unknown): NormalizedMessage[] => {
277
+ if (!Array.isArray(items)) {
278
+ return [];
279
+ }
280
+
281
+ return items
282
+ .map((item) => {
283
+ if (!isPlainObject(item)) {
284
+ return null;
285
+ }
286
+
287
+ const normalized: NormalizedMessage = {};
288
+ if (item.role !== undefined) {
289
+ normalized.role = String(item.role);
290
+ }
291
+
292
+ const content = extractTextContent(item.content);
293
+ if (content) {
294
+ normalized.content = content;
295
+ }
296
+
297
+ const toolCalls = normalizeToolCalls(item.tool_calls);
298
+ if (toolCalls.length > 0) {
299
+ normalized.tool_calls = toolCalls;
300
+ }
301
+
302
+ if (item.tool_call_id) {
303
+ normalized.tool_call_id = String(item.tool_call_id);
304
+ }
305
+
306
+ return Object.keys(normalized).length > 0 ? normalized : null;
307
+ })
308
+ .filter((message): message is NormalizedMessage => message !== null);
309
+ };
310
+
311
+ const normalizeResponseMessage = (
312
+ item: Record<string, unknown>
313
+ ): NormalizedMessage | null => {
314
+ const message: NormalizedMessage = {};
315
+ const role = item.role;
316
+ const content = extractTextContent(item.content);
317
+ const toolCalls = normalizeToolCalls(item.tool_calls);
318
+
319
+ if (role !== undefined && role !== null) {
320
+ message.role = String(role);
321
+ } else if (content || toolCalls.length > 0) {
322
+ message.role = "assistant";
323
+ }
324
+
325
+ if (content) {
326
+ message.content = content;
327
+ }
328
+
329
+ if (toolCalls.length > 0) {
330
+ message.tool_calls = toolCalls;
331
+ }
332
+
333
+ if (item.tool_call_id) {
334
+ message.tool_call_id = String(item.tool_call_id);
335
+ }
336
+
337
+ return Object.keys(message).length > 0 ? message : null;
338
+ };
339
+
340
+ const RAW_TOOL_CALL_ITEM_TYPES = new Set([
341
+ "function_call",
342
+ "computer_call",
343
+ "shell_call",
344
+ "apply_patch_call",
345
+ "custom_tool_call",
346
+ "mcp_call",
347
+ ]);
348
+
349
+ const RAW_TOOL_RESULT_ITEM_TYPES = new Set([
350
+ "function_call_output",
351
+ "function_call_result",
352
+ "computer_call_output",
353
+ "computer_call_result",
354
+ "shell_call_output",
355
+ "apply_patch_call_output",
356
+ "custom_tool_call_output",
357
+ ]);
358
+
359
+ export const normalizeResponseItems = (items: unknown): NormalizedMessage[] => {
360
+ if (typeof items === "string") {
361
+ return [{ role: "user", content: items }];
362
+ }
363
+
364
+ if (!Array.isArray(items)) {
365
+ return [];
366
+ }
367
+
368
+ return items
369
+ .flatMap((item) => {
370
+ if (!isPlainObject(item)) {
371
+ return [];
372
+ }
373
+
374
+ if (item.type === "message_output_item" && isPlainObject(item.rawItem)) {
375
+ const message = normalizeResponseMessage(item.rawItem);
376
+ return message ? [message] : [];
377
+ }
378
+
379
+ if (item.type === "tool_call_item" && isPlainObject(item.rawItem)) {
380
+ const message = normalizeToolCallMessage(item.rawItem);
381
+ return message ? [message] : [];
382
+ }
383
+
384
+ if (item.type === "tool_call_output_item" && isPlainObject(item.rawItem)) {
385
+ const message = normalizeToolResultMessage(item.rawItem, item.output);
386
+ return message ? [message] : [];
387
+ }
388
+
389
+ if (typeof item.type === "string" && RAW_TOOL_CALL_ITEM_TYPES.has(item.type)) {
390
+ const message = normalizeToolCallMessage(item);
391
+ return message ? [message] : [];
392
+ }
393
+
394
+ if (
395
+ typeof item.type === "string" &&
396
+ RAW_TOOL_RESULT_ITEM_TYPES.has(item.type)
397
+ ) {
398
+ const message = normalizeToolResultMessage(item);
399
+ return message ? [message] : [];
400
+ }
401
+
402
+ const message = normalizeResponseMessage(item);
403
+ return message ? [message] : [];
404
+ })
405
+ .filter((message): message is NormalizedMessage => message !== null);
406
+ };
407
+
408
+ const applyUsageAttributes = (attrs: AttributeMap, usage: unknown) => {
409
+ if (!isPlainObject(usage)) {
410
+ return;
411
+ }
412
+
413
+ setNumberAttr(
414
+ attrs,
415
+ "gen_ai.usage.input_tokens",
416
+ usage.input_tokens ?? usage.prompt_tokens
417
+ );
418
+ setNumberAttr(
419
+ attrs,
420
+ "gen_ai.usage.output_tokens",
421
+ usage.output_tokens ?? usage.completion_tokens
422
+ );
423
+ };
424
+
425
+ const generationAttributes = (
426
+ spanData: Extract<SpanData, { type: "generation" }>,
427
+ includeRawPayloads: boolean
428
+ ): AttributeMap => {
429
+ const attrs: AttributeMap = {
430
+ "gen_ai.provider.name": "openai.responses",
431
+ };
432
+
433
+ setStringAttr(attrs, "gen_ai.request.model", spanData.model);
434
+ applyUsageAttributes(attrs, spanData.usage);
435
+ flattenIndexedMessages("gen_ai.prompt", normalizeMessages(spanData.input), attrs);
436
+ flattenIndexedMessages(
437
+ "gen_ai.completion",
438
+ normalizeMessages(spanData.output),
439
+ attrs
440
+ );
441
+ setJsonAttr(
442
+ attrs,
443
+ "openai_agents.model_config_json",
444
+ spanData.model_config,
445
+ includeRawPayloads
446
+ );
447
+ setJsonAttr(
448
+ attrs,
449
+ "openai_agents.generation.raw_input_json",
450
+ spanData.input,
451
+ includeRawPayloads
452
+ );
453
+ setJsonAttr(
454
+ attrs,
455
+ "openai_agents.generation.raw_output_json",
456
+ spanData.output,
457
+ includeRawPayloads
458
+ );
459
+
460
+ return attrs;
461
+ };
462
+
463
+ const responseAttributes = (
464
+ spanData: Extract<SpanData, { type: "response" }>,
465
+ includeRawPayloads: boolean
466
+ ): AttributeMap => {
467
+ const attrs: AttributeMap = {
468
+ "gen_ai.provider.name": "openai.responses",
469
+ };
470
+ const responseObject = isPlainObject(spanData._response) ? spanData._response : {};
471
+ const usage =
472
+ isPlainObject(responseObject.usage) ? responseObject.usage : undefined;
473
+
474
+ setStringAttr(
475
+ attrs,
476
+ "gen_ai.request.model",
477
+ responseObject.model
478
+ );
479
+ setStringAttr(
480
+ attrs,
481
+ "gen_ai.response.model",
482
+ responseObject.model
483
+ );
484
+ setStringAttr(
485
+ attrs,
486
+ "gen_ai.response.id",
487
+ spanData.response_id ?? responseObject.id ?? responseObject.response_id
488
+ );
489
+ applyUsageAttributes(attrs, usage);
490
+ flattenIndexedMessages(
491
+ "gen_ai.prompt",
492
+ normalizeResponseItems(spanData._input ?? responseObject.input),
493
+ attrs
494
+ );
495
+ flattenIndexedMessages(
496
+ "gen_ai.completion",
497
+ normalizeResponseItems(responseObject.output),
498
+ attrs
499
+ );
500
+ setJsonAttr(
501
+ attrs,
502
+ "openai_agents.response.raw_json",
503
+ responseObject,
504
+ includeRawPayloads
505
+ );
506
+ setStringAttr(
507
+ attrs,
508
+ "openai_agents.response.object",
509
+ responseObject.object
510
+ );
511
+
512
+ return attrs;
513
+ };
514
+
515
+ const functionAttributes = (
516
+ spanData: Extract<SpanData, { type: "function" }>,
517
+ includeRawPayloads: boolean
518
+ ): AttributeMap => {
519
+ const attrs: AttributeMap = {
520
+ node_type: "CODE_EXECUTION",
521
+ tool_name: spanData.name,
522
+ "openai_agents.function.name": spanData.name,
523
+ };
524
+
525
+ setStringAttr(attrs, "function_input", spanData.input);
526
+ setStringAttr(attrs, "function_output", spanData.output);
527
+ setStringAttr(attrs, "openai_agents.function.input", spanData.input);
528
+ setStringAttr(attrs, "openai_agents.function.output", spanData.output);
529
+ setJsonAttr(
530
+ attrs,
531
+ "openai_agents.function.mcp_data_json",
532
+ spanData.mcp_data,
533
+ includeRawPayloads
534
+ );
535
+
536
+ return attrs;
537
+ };
538
+
539
+ const agentAttributes = (
540
+ spanData: Extract<SpanData, { type: "agent" }>,
541
+ includeRawPayloads: boolean
542
+ ): AttributeMap => {
543
+ const attrs: AttributeMap = {
544
+ "openai_agents.agent.name": spanData.name,
545
+ };
546
+
547
+ setStringAttr(attrs, "openai_agents.agent.output_type", spanData.output_type);
548
+ setJsonAttr(
549
+ attrs,
550
+ "openai_agents.agent.handoffs_json",
551
+ spanData.handoffs,
552
+ includeRawPayloads
553
+ );
554
+ setJsonAttr(
555
+ attrs,
556
+ "openai_agents.agent.tools_json",
557
+ spanData.tools,
558
+ includeRawPayloads
559
+ );
560
+
561
+ return attrs;
562
+ };
563
+
564
+ const handoffAttributes = (
565
+ spanData: Extract<SpanData, { type: "handoff" }>
566
+ ): AttributeMap => {
567
+ const attrs: AttributeMap = {};
568
+ setStringAttr(attrs, "openai_agents.handoff.from_agent", spanData.from_agent);
569
+ setStringAttr(attrs, "openai_agents.handoff.to_agent", spanData.to_agent);
570
+ return attrs;
571
+ };
572
+
573
+ const guardrailAttributes = (
574
+ spanData: Extract<SpanData, { type: "guardrail" }>
575
+ ): AttributeMap => {
576
+ return {
577
+ "openai_agents.guardrail.name": spanData.name,
578
+ "openai_agents.guardrail.triggered": spanData.triggered,
579
+ };
580
+ };
581
+
582
+ const customAttributes = (
583
+ spanData: Extract<SpanData, { type: "custom" }>,
584
+ includeRawPayloads: boolean
585
+ ): AttributeMap => {
586
+ const attrs: AttributeMap = {
587
+ "openai_agents.custom.name": spanData.name,
588
+ };
589
+ setJsonAttr(
590
+ attrs,
591
+ "openai_agents.custom.data_json",
592
+ spanData.data,
593
+ includeRawPayloads
594
+ );
595
+ return attrs;
596
+ };
597
+
598
+ const rawSpanDataAttributes = (
599
+ spanData: SpanData,
600
+ includeRawPayloads: boolean
601
+ ): AttributeMap => {
602
+ if (!includeRawPayloads) {
603
+ return {};
604
+ }
605
+
606
+ return {
607
+ "openai_agents.raw_json": stableStringify(spanData),
608
+ };
609
+ };
610
+
611
+ export const telemetrySourceVersion = (): string => {
612
+ return SDK_VERSION;
613
+ };
614
+
615
+ export const spanKindFor = (span: Pick<AgentsSpan<any>, "spanData">): number => {
616
+ return span.spanData.type === "generation" || span.spanData.type === "response"
617
+ ? SPAN_KIND_CLIENT
618
+ : SPAN_KIND_INTERNAL;
619
+ };
620
+
621
+ export const spanNameFor = (span: Pick<AgentsSpan<any>, "spanData">): string => {
622
+ switch (span.spanData.type) {
623
+ case "function":
624
+ return `Function: ${span.spanData.name}`;
625
+ case "agent":
626
+ return `Agent: ${span.spanData.name}`;
627
+ case "guardrail":
628
+ return `Guardrail: ${span.spanData.name}`;
629
+ case "custom":
630
+ return String(span.spanData.name);
631
+ default:
632
+ return span.spanData.type
633
+ .split("_")
634
+ .map((part: string) => part.charAt(0).toUpperCase() + part.slice(1))
635
+ .join(" ");
636
+ }
637
+ };
638
+
639
+ export const baseTraceAttributes = (
640
+ trace: Pick<AgentsTrace, "traceId" | "name" | "groupId" | "metadata">,
641
+ includeRawPayloads: boolean
642
+ ): AttributeMap => {
643
+ const attrs: AttributeMap = {
644
+ "promptlayer.telemetry.source": "openai-agents-js",
645
+ "promptlayer.telemetry.source_version": telemetrySourceVersion(),
646
+ "openai_agents.trace_id_original": trace.traceId,
647
+ "openai_agents.workflow_name": trace.name,
648
+ };
649
+
650
+ if (trace.groupId) {
651
+ attrs["openai_agents.group_id"] = trace.groupId;
652
+ }
653
+
654
+ if (isPlainObject(trace.metadata)) {
655
+ Object.entries(trace.metadata).forEach(([key, value]) => {
656
+ if (isScalar(value)) {
657
+ attrs[`openai_agents.metadata.${sanitizeKey(key)}`] = value;
658
+ }
659
+ });
660
+ setJsonAttr(
661
+ attrs,
662
+ "openai_agents.metadata_json",
663
+ trace.metadata,
664
+ includeRawPayloads
665
+ );
666
+ }
667
+
668
+ return attrs;
669
+ };
670
+
671
+ export const baseSpanAttributes = (
672
+ span: Pick<AgentsSpan<any>, "spanId" | "parentId" | "spanData">
673
+ ): AttributeMap => {
674
+ const attrs: AttributeMap = {
675
+ "promptlayer.telemetry.source": "openai-agents-js",
676
+ "promptlayer.telemetry.source_version": telemetrySourceVersion(),
677
+ "openai_agents.span_id_original": span.spanId,
678
+ "openai_agents.span_type": span.spanData.type,
679
+ };
680
+
681
+ if (span.parentId) {
682
+ attrs["openai_agents.parent_id_original"] = span.parentId;
683
+ }
684
+
685
+ return attrs;
686
+ };
687
+
688
+ export const spanDataAttributes = (
689
+ spanData: SpanData,
690
+ includeRawPayloads: boolean
691
+ ): AttributeMap => {
692
+ switch (spanData.type) {
693
+ case "generation":
694
+ return generationAttributes(spanData, includeRawPayloads);
695
+ case "response":
696
+ return responseAttributes(spanData, includeRawPayloads);
697
+ case "function":
698
+ return functionAttributes(spanData, includeRawPayloads);
699
+ case "agent":
700
+ return agentAttributes(spanData, includeRawPayloads);
701
+ case "handoff":
702
+ return handoffAttributes(spanData);
703
+ case "guardrail":
704
+ return guardrailAttributes(spanData);
705
+ case "custom":
706
+ return customAttributes(spanData, includeRawPayloads);
707
+ default:
708
+ return rawSpanDataAttributes(spanData, includeRawPayloads);
709
+ }
710
+ };
711
+
712
+ export const OTLP_STATUS_CODE_UNSET = 0;
713
+ export const OTLP_STATUS_CODE_OK = 1;
714
+ export const OTLP_STATUS_CODE_ERROR = 2;