@latitude-data/telemetry 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { z } from 'zod';
2
+ import { ATTR_GEN_AI_OPERATION_NAME, ATTR_GEN_AI_TOOL_CALL_ID, ATTR_GEN_AI_TOOL_TYPE, ATTR_GEN_AI_TOOL_NAME, ATTR_GEN_AI_SYSTEM, ATTR_GEN_AI_RESPONSE_FINISH_REASONS, ATTR_GEN_AI_RESPONSE_MODEL, ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, ATTR_GEN_AI_USAGE_INPUT_TOKENS } from '@opentelemetry/semantic-conventions/incubating';
3
+ import { ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
2
4
  import * as otel from '@opentelemetry/api';
3
5
  import { trace, propagation, context } from '@opentelemetry/api';
4
- import { ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
5
- import { ATTR_GEN_AI_OPERATION_NAME, ATTR_GEN_AI_TOOL_CALL_ID, ATTR_GEN_AI_TOOL_TYPE, ATTR_GEN_AI_TOOL_NAME, ATTR_GEN_AI_SYSTEM, ATTR_GEN_AI_RESPONSE_FINISH_REASONS, ATTR_GEN_AI_RESPONSE_MODEL, ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, ATTR_GEN_AI_USAGE_INPUT_TOKENS } from '@opentelemetry/semantic-conventions/incubating';
6
6
  import { v4 } from 'uuid';
7
7
  import { BaggageSpanProcessor, ALLOW_ALL_BAGGAGE_KEYS } from '@opentelemetry/baggage-span-processor';
8
8
  import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks';
@@ -130,6 +130,15 @@ z.object({
130
130
  isError: z.boolean().optional(),
131
131
  text: z.string().optional(),
132
132
  });
133
+ z.object({
134
+ inputTokens: z.number(),
135
+ outputTokens: z.number(),
136
+ promptTokens: z.number(),
137
+ completionTokens: z.number(),
138
+ totalTokens: z.number(),
139
+ reasoningTokens: z.number(),
140
+ cachedInputTokens: z.number(),
141
+ });
133
142
 
134
143
  var ParameterType;
135
144
  (function (ParameterType) {
@@ -189,7 +198,6 @@ const compositeEvaluationConfiguration = baseEvaluationConfiguration.extend({
189
198
  evaluationUuids: z.array(z.string()),
190
199
  minThreshold: z.number().optional(), // Threshold percentage
191
200
  maxThreshold: z.number().optional(), // Threshold percentage
192
- defaultTarget: z.boolean().optional(), // Default for optimizations and distillations
193
201
  });
194
202
  const compositeEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
195
203
  results: z.record(z.string(), // Evaluation uuid
@@ -256,12 +264,34 @@ const CompositeEvaluationSpecification = {
256
264
  },
257
265
  };
258
266
 
267
+ const selectedContextSchema = z.object({
268
+ messageIndex: z.number().int().nonnegative(),
269
+ contentBlockIndex: z.number().int().nonnegative(),
270
+ contentType: z.enum([
271
+ 'text',
272
+ 'reasoning',
273
+ 'image',
274
+ 'file',
275
+ 'tool-call',
276
+ 'tool-result',
277
+ ]),
278
+ textRange: z
279
+ .object({
280
+ start: z.number().int().nonnegative(),
281
+ end: z.number().int().nonnegative(),
282
+ })
283
+ .optional(),
284
+ selectedText: z.string().optional(),
285
+ toolCallId: z.string().optional(),
286
+ });
259
287
  const humanEvaluationConfiguration = baseEvaluationConfiguration.extend({
260
288
  enableControls: z.boolean().optional(), // UI annotation controls
261
289
  criteria: z.string().optional(),
262
290
  });
263
291
  const humanEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
264
292
  reason: z.string().optional(),
293
+ enrichedReason: z.string().optional(),
294
+ selectedContexts: z.array(selectedContextSchema).optional(),
265
295
  });
266
296
  const humanEvaluationResultError = baseEvaluationResultError.extend({});
267
297
  // BINARY
@@ -539,8 +569,6 @@ z.object({
539
569
  });
540
570
  z.object({
541
571
  evaluateLiveLogs: z.boolean().nullable().optional(),
542
- enableSuggestions: z.boolean().nullable().optional(),
543
- autoApplySuggestions: z.boolean().nullable().optional(),
544
572
  });
545
573
 
546
574
  var LegacyChainEventTypes;
@@ -738,6 +766,7 @@ var LogSources;
738
766
  LogSources["ShadowTest"] = "shadow_test";
739
767
  LogSources["ABTestChallenger"] = "ab_test_challenger";
740
768
  LogSources["User"] = "user";
769
+ LogSources["Optimization"] = "optimization";
741
770
  })(LogSources || (LogSources = {}));
742
771
 
743
772
  var RunSourceGroup;
@@ -748,7 +777,8 @@ var RunSourceGroup;
748
777
  ({
749
778
  [RunSourceGroup.Production]: [
750
779
  LogSources.API,
751
- LogSources.Copilot,
780
+ LogSources.ShadowTest,
781
+ LogSources.ABTestChallenger,
752
782
  LogSources.EmailTrigger,
753
783
  LogSources.IntegrationTrigger,
754
784
  LogSources.ScheduledTrigger,
@@ -777,26 +807,49 @@ var SpanKind;
777
807
  // Note: loosely based on OpenTelemetry GenAI semantic conventions
778
808
  var SpanType;
779
809
  (function (SpanType) {
780
- SpanType["Tool"] = "tool";
781
- SpanType["Completion"] = "completion";
782
- SpanType["Embedding"] = "embedding";
783
- SpanType["Retrieval"] = "retrieval";
784
- SpanType["Reranking"] = "reranking";
785
- SpanType["Http"] = "http";
786
- SpanType["Unknown"] = "unknown";
810
+ // Latitude wrappers
787
811
  SpanType["Prompt"] = "prompt";
788
812
  SpanType["Chat"] = "chat";
789
813
  SpanType["External"] = "external";
790
814
  SpanType["UnresolvedExternal"] = "unresolved_external";
791
- SpanType["Step"] = "step";
815
+ // Added a HTTP span to capture raw HTTP requests and responses when running from Latitude
816
+ SpanType["Http"] = "http";
817
+ // Any known span from supported specifications will be grouped into one of these types
818
+ SpanType["Completion"] = "completion";
819
+ SpanType["Tool"] = "tool";
820
+ SpanType["Embedding"] = "embedding";
821
+ SpanType["Unknown"] = "unknown";
792
822
  })(SpanType || (SpanType = {}));
823
+ [
824
+ SpanType.Prompt,
825
+ SpanType.External,
826
+ SpanType.Chat,
827
+ ];
793
828
  const SPAN_SPECIFICATIONS = {
794
- [SpanType.Tool]: {
795
- name: 'Tool',
796
- description: 'A tool call',
797
- isGenAI: true,
829
+ [SpanType.Prompt]: {
830
+ name: 'Prompt',
831
+ description: 'A prompt span',
832
+ isGenAI: false,
833
+ isHidden: false,
834
+ },
835
+ [SpanType.Chat]: {
836
+ name: 'Chat',
837
+ description: 'A chat continuation span',
838
+ isGenAI: false,
798
839
  isHidden: false,
799
840
  },
841
+ [SpanType.External]: {
842
+ name: 'External',
843
+ description: 'An external capture span',
844
+ isGenAI: false,
845
+ isHidden: false,
846
+ },
847
+ [SpanType.UnresolvedExternal]: {
848
+ name: 'Unresolved External',
849
+ description: 'An external span that needs path resolution before storage',
850
+ isGenAI: false,
851
+ isHidden: true,
852
+ },
800
853
  [SpanType.Completion]: {
801
854
  name: 'Completion',
802
855
  description: 'A completion call',
@@ -809,15 +862,9 @@ const SPAN_SPECIFICATIONS = {
809
862
  isGenAI: true,
810
863
  isHidden: false,
811
864
  },
812
- [SpanType.Retrieval]: {
813
- name: 'Retrieval',
814
- description: 'A retrieval call',
815
- isGenAI: true,
816
- isHidden: false,
817
- },
818
- [SpanType.Reranking]: {
819
- name: 'Reranking',
820
- description: 'A reranking call',
865
+ [SpanType.Tool]: {
866
+ name: 'Tool',
867
+ description: 'A tool call',
821
868
  isGenAI: true,
822
869
  isHidden: false,
823
870
  },
@@ -833,36 +880,6 @@ const SPAN_SPECIFICATIONS = {
833
880
  isGenAI: false,
834
881
  isHidden: true,
835
882
  },
836
- [SpanType.Prompt]: {
837
- name: 'Prompt',
838
- description: 'A prompt span',
839
- isGenAI: false,
840
- isHidden: false,
841
- },
842
- [SpanType.Chat]: {
843
- name: 'Chat',
844
- description: 'A chat continuation span',
845
- isGenAI: false,
846
- isHidden: false,
847
- },
848
- [SpanType.External]: {
849
- name: 'External',
850
- description: 'An external capture span',
851
- isGenAI: false,
852
- isHidden: false,
853
- },
854
- [SpanType.UnresolvedExternal]: {
855
- name: 'Unresolved External',
856
- description: 'An external span that needs path resolution before storage',
857
- isGenAI: false,
858
- isHidden: true,
859
- },
860
- [SpanType.Step]: {
861
- name: 'Step',
862
- description: 'A step span',
863
- isGenAI: false,
864
- isHidden: false,
865
- },
866
883
  };
867
884
  var SpanStatus;
868
885
  (function (SpanStatus) {
@@ -870,6 +887,11 @@ var SpanStatus;
870
887
  SpanStatus["Ok"] = "ok";
871
888
  SpanStatus["Error"] = "error";
872
889
  })(SpanStatus || (SpanStatus = {}));
890
+ new Set([
891
+ SpanType.Prompt,
892
+ SpanType.Chat,
893
+ SpanType.External,
894
+ ]);
873
895
 
874
896
  // Note: Traces are unmaterialized but this context is used to propagate the trace
875
897
  // See www.w3.org/TR/trace-context and w3c.github.io/baggage
@@ -879,6 +901,130 @@ z.object({
879
901
  baggage: z.string().optional(), // <key>=urlencoded(<value>)[,<key>=urlencoded(<value>)]*
880
902
  });
881
903
 
904
+ const ATTRIBUTES = {
905
+ // Custom attributes added and used by Latitude spans (Prompt / External / Chat)
906
+ LATITUDE: {
907
+ type: 'latitude.type',
908
+ documentUuid: 'latitude.document_uuid',
909
+ promptPath: 'latitude.prompt_path',
910
+ commitUuid: 'latitude.commit_uuid',
911
+ documentLogUuid: 'latitude.document_log_uuid',
912
+ projectId: 'latitude.project_id',
913
+ experimentUuid: 'latitude.experiment_uuid',
914
+ source: 'latitude.source',
915
+ externalId: 'latitude.external_id',
916
+ testDeploymentId: 'latitude.test_deployment_id',
917
+ previousTraceId: 'latitude.previous_trace_id',
918
+ // Custom additions to the GenAI semantic conventions (deprecated)
919
+ request: {
920
+ _root: 'gen_ai.request',
921
+ configuration: 'gen_ai.request.configuration',
922
+ template: 'gen_ai.request.template',
923
+ parameters: 'gen_ai.request.parameters',
924
+ messages: 'gen_ai.request.messages'},
925
+ response: {
926
+ _root: 'gen_ai.response',
927
+ messages: 'gen_ai.response.messages',
928
+ },
929
+ usage: {
930
+ promptTokens: 'gen_ai.usage.prompt_tokens',
931
+ cachedTokens: 'gen_ai.usage.cached_tokens',
932
+ reasoningTokens: 'gen_ai.usage.reasoning_tokens',
933
+ completionTokens: 'gen_ai.usage.completion_tokens',
934
+ },
935
+ },
936
+ // Official OpenTelemetry semantic conventions
937
+ OPENTELEMETRY: {
938
+ HTTP: {
939
+ request: {
940
+ url: 'http.request.url',
941
+ body: 'http.request.body',
942
+ header: 'http.request.header',
943
+ method: ATTR_HTTP_REQUEST_METHOD,
944
+ },
945
+ response: {
946
+ body: 'http.response.body',
947
+ header: 'http.response.header',
948
+ statusCode: ATTR_HTTP_RESPONSE_STATUS_CODE,
949
+ },
950
+ },
951
+ // GenAI semantic conventions
952
+ // https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/
953
+ GEN_AI: {
954
+ operation: ATTR_GEN_AI_OPERATION_NAME,
955
+ response: {
956
+ model: ATTR_GEN_AI_RESPONSE_MODEL,
957
+ finishReasons: ATTR_GEN_AI_RESPONSE_FINISH_REASONS,
958
+ },
959
+ usage: {
960
+ inputTokens: ATTR_GEN_AI_USAGE_INPUT_TOKENS,
961
+ outputTokens: ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,
962
+ },
963
+ tool: {
964
+ call: {
965
+ id: ATTR_GEN_AI_TOOL_CALL_ID,
966
+ arguments: 'gen_ai.tool.call.arguments'}},
967
+ _deprecated: {
968
+ system: ATTR_GEN_AI_SYSTEM,
969
+ tool: {
970
+ name: ATTR_GEN_AI_TOOL_NAME,
971
+ type: ATTR_GEN_AI_TOOL_TYPE,
972
+ result: {
973
+ value: 'gen_ai.tool.result.value',
974
+ isError: 'gen_ai.tool.result.is_error',
975
+ },
976
+ },
977
+ prompt: {
978
+ _root: 'gen_ai.prompt',
979
+ index: (promptIndex) => ({
980
+ role: `gen_ai.prompt.${promptIndex}.role`,
981
+ content: `gen_ai.prompt.${promptIndex}.content`, // string or object
982
+ toolCalls: (toolCallIndex) => ({
983
+ id: `gen_ai.prompt.${promptIndex}.tool_calls.${toolCallIndex}.id`,
984
+ name: `gen_ai.prompt.${promptIndex}.tool_calls.${toolCallIndex}.name`,
985
+ arguments: `gen_ai.prompt.${promptIndex}.tool_calls.${toolCallIndex}.arguments`,
986
+ }),
987
+ tool: {
988
+ callId: `gen_ai.prompt.${promptIndex}.tool_call_id`,
989
+ toolName: `gen_ai.prompt.${promptIndex}.tool_name`,
990
+ isError: `gen_ai.prompt.${promptIndex}.is_error`,
991
+ },
992
+ }),
993
+ },
994
+ completion: {
995
+ _root: 'gen_ai.completion',
996
+ index: (completionIndex) => ({
997
+ role: `gen_ai.completion.${completionIndex}.role`,
998
+ content: `gen_ai.completion.${completionIndex}.content`, // string or object
999
+ toolCalls: (toolCallIndex) => ({
1000
+ id: `gen_ai.completion.${completionIndex}.tool_calls.${toolCallIndex}.id`,
1001
+ name: `gen_ai.completion.${completionIndex}.tool_calls.${toolCallIndex}.name`,
1002
+ arguments: `gen_ai.completion.${completionIndex}.tool_calls.${toolCallIndex}.arguments`,
1003
+ }),
1004
+ tool: {
1005
+ callId: `gen_ai.prompt.${completionIndex}.tool_call_id`,
1006
+ toolName: `gen_ai.prompt.${completionIndex}.tool_name`,
1007
+ isError: `gen_ai.prompt.${completionIndex}.is_error`,
1008
+ },
1009
+ }),
1010
+ }},
1011
+ },
1012
+ }};
1013
+ const VALUES = {
1014
+ OPENTELEMETRY: {
1015
+ GEN_AI: {
1016
+ response: {
1017
+ finishReasons: {
1018
+ stop: 'stop',
1019
+ toolCalls: 'tool_calls'},
1020
+ },
1021
+ tool: {
1022
+ type: {
1023
+ function: 'function',
1024
+ },
1025
+ }},
1026
+ }};
1027
+
882
1028
  /* Note: Instrumentation scopes from all language SDKs */
883
1029
  const SCOPE_LATITUDE = 'so.latitude.instrumentation';
884
1030
  var InstrumentationScope;
@@ -907,52 +1053,6 @@ var InstrumentationScope;
907
1053
  InstrumentationScope["Transformers"] = "transformers";
908
1054
  InstrumentationScope["AlephAlpha"] = "alephalpha";
909
1055
  })(InstrumentationScope || (InstrumentationScope = {}));
910
- /* Note: non-standard OpenTelemetry semantic conventions used in Latitude */
911
- const ATTR_LATITUDE = 'latitude';
912
- const ATTR_LATITUDE_TYPE = `${ATTR_LATITUDE}.type`;
913
- const ATTR_LATITUDE_DOCUMENT_UUID = `${ATTR_LATITUDE}.document_uuid`;
914
- const ATTR_LATITUDE_PROMPT_PATH = `${ATTR_LATITUDE}.prompt_path`;
915
- const ATTR_LATITUDE_COMMIT_UUID = `${ATTR_LATITUDE}.commit_uuid`;
916
- const ATTR_LATITUDE_DOCUMENT_LOG_UUID = `${ATTR_LATITUDE}.document_log_uuid`;
917
- const ATTR_LATITUDE_PROJECT_ID = `${ATTR_LATITUDE}.project_id`;
918
- const ATTR_LATITUDE_EXPERIMENT_UUID = `${ATTR_LATITUDE}.experiment_uuid`;
919
- const ATTR_LATITUDE_SOURCE = `${ATTR_LATITUDE}.source`;
920
- const ATTR_LATITUDE_EXTERNAL_ID = `${ATTR_LATITUDE}.external_id`;
921
- const ATTR_LATITUDE_TEST_DEPLOYMENT_ID = `${ATTR_LATITUDE}.test_deployment_id`;
922
- const ATTR_LATITUDE_PREVIOUS_TRACE_ID = `${ATTR_LATITUDE}.previous_trace_id`;
923
- const GEN_AI_TOOL_TYPE_VALUE_FUNCTION = 'function';
924
- const ATTR_GEN_AI_TOOL_CALL_ARGUMENTS = 'gen_ai.tool.call.arguments';
925
- const ATTR_GEN_AI_TOOL_RESULT_VALUE = 'gen_ai.tool.result.value';
926
- const ATTR_GEN_AI_TOOL_RESULT_IS_ERROR = 'gen_ai.tool.result.is_error';
927
- const ATTR_GEN_AI_REQUEST = 'gen_ai.request';
928
- const ATTR_GEN_AI_REQUEST_CONFIGURATION = 'gen_ai.request.configuration';
929
- const ATTR_GEN_AI_REQUEST_TEMPLATE = 'gen_ai.request.template';
930
- const ATTR_GEN_AI_REQUEST_PARAMETERS = 'gen_ai.request.parameters';
931
- const ATTR_GEN_AI_REQUEST_MESSAGES = 'gen_ai.request.messages';
932
- const ATTR_GEN_AI_RESPONSE = 'gen_ai.response';
933
- const ATTR_GEN_AI_RESPONSE_MESSAGES = 'gen_ai.response.messages';
934
- const ATTR_GEN_AI_USAGE_PROMPT_TOKENS = 'gen_ai.usage.prompt_tokens';
935
- const ATTR_GEN_AI_USAGE_CACHED_TOKENS = 'gen_ai.usage.cached_tokens';
936
- const ATTR_GEN_AI_USAGE_REASONING_TOKENS = 'gen_ai.usage.reasoning_tokens'; // prettier-ignore
937
- const ATTR_GEN_AI_USAGE_COMPLETION_TOKENS = 'gen_ai.usage.completion_tokens'; // prettier-ignore
938
- const ATTR_GEN_AI_PROMPTS = 'gen_ai.prompt'; // gen_ai.prompt.{index}.{role/content/...}
939
- const ATTR_GEN_AI_COMPLETIONS = 'gen_ai.completion'; // gen_ai.completion.{index}.{role/content/...}
940
- const ATTR_GEN_AI_MESSAGE_ROLE = 'role';
941
- const ATTR_GEN_AI_MESSAGE_CONTENT = 'content'; // string or object
942
- const ATTR_GEN_AI_MESSAGE_TOOL_NAME = 'tool_name';
943
- const ATTR_GEN_AI_MESSAGE_TOOL_CALL_ID = 'tool_call_id';
944
- const ATTR_GEN_AI_MESSAGE_TOOL_RESULT_IS_ERROR = 'is_error';
945
- const ATTR_GEN_AI_MESSAGE_TOOL_CALLS = 'tool_calls'; // gen_ai.completion.{index}.tool_calls.{index}.{id/name/arguments}
946
- const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ID = 'id';
947
- const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME = 'name';
948
- const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS = 'arguments';
949
- const GEN_AI_RESPONSE_FINISH_REASON_VALUE_STOP = 'stop';
950
- const GEN_AI_RESPONSE_FINISH_REASON_VALUE_TOOL_CALLS = 'tool_calls';
951
- const ATTR_HTTP_REQUEST_URL = 'http.request.url';
952
- const ATTR_HTTP_REQUEST_BODY = 'http.request.body';
953
- const ATTR_HTTP_REQUEST_HEADER = 'http.request.header';
954
- const ATTR_HTTP_RESPONSE_BODY = 'http.response.body';
955
- const ATTR_HTTP_RESPONSE_HEADER = 'http.response.header';
956
1056
  /* Note: Schemas for span ingestion following OpenTelemetry service request specification */
957
1057
  var Otlp;
958
1058
  (function (Otlp) {
@@ -1033,6 +1133,40 @@ var Otlp;
1033
1133
  });
1034
1134
  })(Otlp || (Otlp = {}));
1035
1135
 
1136
+ const MAX_SIMULATION_TURNS = 10;
1137
+ const SimulationSettingsSchema = z.object({
1138
+ simulateToolResponses: z.boolean().optional(),
1139
+ simulatedTools: z.array(z.string()).optional(), // Empty array means all tools are simulated (if simulateToolResponses is true).
1140
+ toolSimulationInstructions: z.string().optional(), // A prompt used to guide and generate the simulation result
1141
+ maxTurns: z.number().min(1).max(MAX_SIMULATION_TURNS).optional(), // The maximum number of turns to simulate. Default is 1, and any greater value will add a new user message to the simulated conversation.
1142
+ });
1143
+
1144
+ var OptimizationEngine;
1145
+ (function (OptimizationEngine) {
1146
+ OptimizationEngine["Identity"] = "identity";
1147
+ OptimizationEngine["Gepa"] = "gepa";
1148
+ })(OptimizationEngine || (OptimizationEngine = {}));
1149
+ const OptimizationBudgetSchema = z.object({
1150
+ time: z.number().min(0).optional(),
1151
+ tokens: z.number().min(0).optional(),
1152
+ });
1153
+ z.object({
1154
+ parameters: z
1155
+ .record(z.string(), z.object({
1156
+ column: z.string().optional(), // Note: corresponding column in the user-provided trainset and testset
1157
+ isPii: z.boolean().optional(),
1158
+ }))
1159
+ .optional(),
1160
+ simulation: SimulationSettingsSchema.optional(),
1161
+ scope: z
1162
+ .object({
1163
+ configuration: z.boolean().optional(),
1164
+ instructions: z.boolean().optional(),
1165
+ })
1166
+ .optional(),
1167
+ budget: OptimizationBudgetSchema.optional(),
1168
+ });
1169
+
1036
1170
  // TODO(tracing): deprecated
1037
1171
  const HEAD_COMMIT = 'live';
1038
1172
  var Providers;
@@ -1178,9 +1312,9 @@ class ManualInstrumentation {
1178
1312
  }
1179
1313
  const span = this.tracer.startSpan(name, {
1180
1314
  attributes: {
1181
- [ATTR_LATITUDE_TYPE]: type,
1315
+ [ATTRIBUTES.LATITUDE.type]: type,
1182
1316
  ...(operation && {
1183
- [ATTR_GEN_AI_OPERATION_NAME]: operation,
1317
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI.operation]: operation,
1184
1318
  }),
1185
1319
  ...(start.attributes || {}),
1186
1320
  },
@@ -1206,15 +1340,15 @@ class ManualInstrumentation {
1206
1340
  try {
1207
1341
  jsonArguments = JSON.stringify(start.call.arguments);
1208
1342
  }
1209
- catch (error) {
1343
+ catch (_error) {
1210
1344
  jsonArguments = '{}';
1211
1345
  }
1212
1346
  const span = this.span(ctx, start.name, SpanType.Tool, {
1213
1347
  attributes: {
1214
- [ATTR_GEN_AI_TOOL_NAME]: start.name,
1215
- [ATTR_GEN_AI_TOOL_TYPE]: GEN_AI_TOOL_TYPE_VALUE_FUNCTION,
1216
- [ATTR_GEN_AI_TOOL_CALL_ID]: start.call.id,
1217
- [ATTR_GEN_AI_TOOL_CALL_ARGUMENTS]: jsonArguments,
1348
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.name]: start.name,
1349
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.type]: VALUES.OPENTELEMETRY.GEN_AI.tool.type.function,
1350
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI.tool.call.id]: start.call.id,
1351
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI.tool.call.arguments]: jsonArguments,
1218
1352
  ...(start.attributes || {}),
1219
1353
  },
1220
1354
  });
@@ -1227,7 +1361,7 @@ class ManualInstrumentation {
1227
1361
  try {
1228
1362
  stringResult = JSON.stringify(end.result.value);
1229
1363
  }
1230
- catch (error) {
1364
+ catch (_error) {
1231
1365
  stringResult = '{}';
1232
1366
  }
1233
1367
  }
@@ -1236,8 +1370,8 @@ class ManualInstrumentation {
1236
1370
  }
1237
1371
  span.end({
1238
1372
  attributes: {
1239
- [ATTR_GEN_AI_TOOL_RESULT_VALUE]: stringResult,
1240
- [ATTR_GEN_AI_TOOL_RESULT_IS_ERROR]: end.result.isError,
1373
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.result.value]: stringResult,
1374
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.result.isError]: end.result.isError,
1241
1375
  ...(end.attributes || {}),
1242
1376
  },
1243
1377
  });
@@ -1245,12 +1379,12 @@ class ManualInstrumentation {
1245
1379
  fail: span.fail,
1246
1380
  };
1247
1381
  }
1248
- attribifyMessageToolCalls(prefix, toolCalls) {
1382
+ attribifyMessageToolCalls(otelMessageField, toolCalls) {
1249
1383
  const attributes = {};
1250
1384
  for (let i = 0; i < toolCalls.length; i++) {
1251
1385
  for (const key in toolCalls[i]) {
1252
1386
  const field = this.toCamelCase(key);
1253
- let value = toolCalls[i][key];
1387
+ const value = toolCalls[i][key];
1254
1388
  if (value === null || value === undefined)
1255
1389
  continue;
1256
1390
  switch (field) {
@@ -1259,28 +1393,29 @@ class ManualInstrumentation {
1259
1393
  case 'toolUseId': {
1260
1394
  if (typeof value !== 'string')
1261
1395
  continue;
1262
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ID}`] = value;
1396
+ attributes[otelMessageField.toolCalls(i).id] = value;
1263
1397
  break;
1264
1398
  }
1265
1399
  case 'name':
1266
1400
  case 'toolName': {
1267
1401
  if (typeof value !== 'string')
1268
1402
  continue;
1269
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME}`] = value;
1403
+ attributes[otelMessageField.toolCalls(i).name] = value;
1270
1404
  break;
1271
1405
  }
1272
1406
  case 'arguments':
1273
1407
  case 'toolArguments':
1274
1408
  case 'input': {
1275
1409
  if (typeof value === 'string') {
1276
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = value;
1410
+ attributes[otelMessageField.toolCalls(i).arguments] = value;
1277
1411
  }
1278
1412
  else {
1279
1413
  try {
1280
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = JSON.stringify(value);
1414
+ attributes[otelMessageField.toolCalls(i).arguments] =
1415
+ JSON.stringify(value);
1281
1416
  }
1282
- catch (error) {
1283
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = '{}';
1417
+ catch (_error) {
1418
+ attributes[otelMessageField.toolCalls(i).arguments] = '{}';
1284
1419
  }
1285
1420
  }
1286
1421
  break;
@@ -1297,8 +1432,9 @@ class ManualInstrumentation {
1297
1432
  continue;
1298
1433
  if (typeof value.arguments !== 'string')
1299
1434
  continue;
1300
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME}`] = value.name;
1301
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = value.arguments;
1435
+ attributes[otelMessageField.toolCalls(i).name] = value.name;
1436
+ attributes[otelMessageField.toolCalls(i).arguments] =
1437
+ value.arguments;
1302
1438
  break;
1303
1439
  }
1304
1440
  }
@@ -1306,18 +1442,16 @@ class ManualInstrumentation {
1306
1442
  }
1307
1443
  return attributes;
1308
1444
  }
1309
- attribifyMessageContent(prefix, content) {
1445
+ attribifyMessageContent(otelMessageField, content) {
1310
1446
  let attributes = {};
1311
1447
  if (typeof content === 'string') {
1312
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] = content;
1313
1448
  return attributes;
1314
1449
  }
1315
1450
  try {
1316
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] =
1317
- JSON.stringify(content);
1451
+ attributes[otelMessageField.content] = JSON.stringify(content);
1318
1452
  }
1319
- catch (error) {
1320
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] = '[]';
1453
+ catch (_error) {
1454
+ attributes[otelMessageField.content] = '[]';
1321
1455
  }
1322
1456
  if (!Array.isArray(content))
1323
1457
  return attributes;
@@ -1337,32 +1471,34 @@ class ManualInstrumentation {
1337
1471
  if (toolCalls.length > 0) {
1338
1472
  attributes = {
1339
1473
  ...attributes,
1340
- ...this.attribifyMessageToolCalls(prefix, toolCalls),
1474
+ ...this.attribifyMessageToolCalls(otelMessageField, toolCalls),
1341
1475
  };
1342
1476
  }
1343
1477
  return attributes;
1344
1478
  }
1345
1479
  attribifyMessages(direction, messages) {
1346
- const prefix = direction === 'input' ? ATTR_GEN_AI_PROMPTS : ATTR_GEN_AI_COMPLETIONS;
1480
+ const otelField = direction === 'input'
1481
+ ? ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.prompt
1482
+ : ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.completion;
1347
1483
  let attributes = {};
1348
1484
  for (let i = 0; i < messages.length; i++) {
1349
1485
  for (const key in messages[i]) {
1350
1486
  const field = this.toCamelCase(key);
1351
- let value = messages[i][key];
1487
+ const value = messages[i][key];
1352
1488
  if (value === null || value === undefined)
1353
1489
  continue;
1354
1490
  switch (field) {
1355
1491
  case 'role': {
1356
1492
  if (typeof value !== 'string')
1357
1493
  continue;
1358
- attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_ROLE}`] = value;
1494
+ attributes[otelField.index(i).role] = value;
1359
1495
  break;
1360
1496
  }
1361
1497
  /* Tool calls for Anthropic and PromptL are in the content */
1362
1498
  case 'content': {
1363
1499
  attributes = {
1364
1500
  ...attributes,
1365
- ...this.attribifyMessageContent(`${prefix}.${i}`, value),
1501
+ ...this.attribifyMessageContent(otelField.index(i), value),
1366
1502
  };
1367
1503
  break;
1368
1504
  }
@@ -1372,7 +1508,7 @@ class ManualInstrumentation {
1372
1508
  continue;
1373
1509
  attributes = {
1374
1510
  ...attributes,
1375
- ...this.attribifyMessageToolCalls(`${prefix}.${i}`, value),
1511
+ ...this.attribifyMessageToolCalls(otelField.index(i), value),
1376
1512
  };
1377
1513
  break;
1378
1514
  }
@@ -1382,22 +1518,20 @@ class ManualInstrumentation {
1382
1518
  case 'toolUseId': {
1383
1519
  if (typeof value !== 'string')
1384
1520
  continue;
1385
- attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALL_ID}`] =
1386
- value;
1521
+ attributes[otelField.index(i).tool.callId] = value;
1387
1522
  break;
1388
1523
  }
1389
1524
  case 'toolName': {
1390
1525
  if (typeof value !== 'string')
1391
1526
  continue;
1392
- attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_NAME}`] =
1393
- value;
1527
+ attributes[otelField.index(i).tool.toolName] = value;
1394
1528
  break;
1395
1529
  }
1396
1530
  // Note: 'toolResult' is 'content' itself
1397
1531
  case 'isError': {
1398
1532
  if (typeof value !== 'boolean')
1399
1533
  continue;
1400
- attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_RESULT_IS_ERROR}`] = value;
1534
+ attributes[otelField.index(i).tool.isError] = value;
1401
1535
  break;
1402
1536
  }
1403
1537
  }
@@ -1406,7 +1540,9 @@ class ManualInstrumentation {
1406
1540
  return attributes;
1407
1541
  }
1408
1542
  attribifyConfiguration(direction, configuration) {
1409
- const prefix = direction === 'input' ? ATTR_GEN_AI_REQUEST : ATTR_GEN_AI_RESPONSE;
1543
+ const prefix = direction === 'input'
1544
+ ? ATTRIBUTES.LATITUDE.request._root
1545
+ : ATTRIBUTES.LATITUDE.response._root;
1410
1546
  const attributes = {};
1411
1547
  for (const key in configuration) {
1412
1548
  const field = this.toSnakeCase(key);
@@ -1417,7 +1553,7 @@ class ManualInstrumentation {
1417
1553
  try {
1418
1554
  value = JSON.stringify(value);
1419
1555
  }
1420
- catch (error) {
1556
+ catch (_error) {
1421
1557
  value = '{}';
1422
1558
  }
1423
1559
  }
@@ -1435,7 +1571,7 @@ class ManualInstrumentation {
1435
1571
  try {
1436
1572
  jsonConfiguration = JSON.stringify(configuration);
1437
1573
  }
1438
- catch (error) {
1574
+ catch (_error) {
1439
1575
  jsonConfiguration = '{}';
1440
1576
  }
1441
1577
  const attrConfiguration = this.attribifyConfiguration('input', configuration);
@@ -1444,21 +1580,21 @@ class ManualInstrumentation {
1444
1580
  try {
1445
1581
  jsonInput = JSON.stringify(input);
1446
1582
  }
1447
- catch (error) {
1583
+ catch (_error) {
1448
1584
  jsonInput = '[]';
1449
1585
  }
1450
1586
  const attrInput = this.attribifyMessages('input', input);
1451
1587
  const span = this.span(ctx, start.name || `${start.provider} / ${start.model}`, SpanType.Completion, {
1452
1588
  attributes: {
1453
- [ATTR_GEN_AI_SYSTEM]: start.provider,
1454
- [ATTR_GEN_AI_REQUEST_CONFIGURATION]: jsonConfiguration,
1589
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.system]: start.provider,
1590
+ [ATTRIBUTES.LATITUDE.request.configuration]: jsonConfiguration,
1455
1591
  ...attrConfiguration,
1456
- [ATTR_GEN_AI_REQUEST_MESSAGES]: jsonInput,
1592
+ [ATTRIBUTES.LATITUDE.request.messages]: jsonInput,
1457
1593
  ...attrInput,
1458
1594
  ...(start.attributes || {}),
1459
- [ATTR_LATITUDE_COMMIT_UUID]: start.versionUuid,
1460
- [ATTR_LATITUDE_DOCUMENT_UUID]: start.promptUuid,
1461
- [ATTR_LATITUDE_EXPERIMENT_UUID]: start.experimentUuid,
1595
+ [ATTRIBUTES.LATITUDE.commitUuid]: start.versionUuid,
1596
+ [ATTRIBUTES.LATITUDE.documentUuid]: start.promptUuid,
1597
+ [ATTRIBUTES.LATITUDE.experimentUuid]: start.experimentUuid,
1462
1598
  },
1463
1599
  });
1464
1600
  return {
@@ -1470,7 +1606,7 @@ class ManualInstrumentation {
1470
1606
  try {
1471
1607
  jsonOutput = JSON.stringify(output);
1472
1608
  }
1473
- catch (error) {
1609
+ catch (_error) {
1474
1610
  jsonOutput = '[]';
1475
1611
  }
1476
1612
  const attrOutput = this.attribifyMessages('output', output);
@@ -1485,16 +1621,18 @@ class ManualInstrumentation {
1485
1621
  const finishReason = end.finishReason ?? '';
1486
1622
  span.end({
1487
1623
  attributes: {
1488
- [ATTR_GEN_AI_RESPONSE_MESSAGES]: jsonOutput,
1624
+ [ATTRIBUTES.LATITUDE.response.messages]: jsonOutput,
1489
1625
  ...attrOutput,
1490
- [ATTR_GEN_AI_USAGE_INPUT_TOKENS]: inputTokens,
1491
- [ATTR_GEN_AI_USAGE_PROMPT_TOKENS]: tokens.prompt,
1492
- [ATTR_GEN_AI_USAGE_CACHED_TOKENS]: tokens.cached,
1493
- [ATTR_GEN_AI_USAGE_REASONING_TOKENS]: tokens.reasoning,
1494
- [ATTR_GEN_AI_USAGE_COMPLETION_TOKENS]: tokens.completion,
1495
- [ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: outputTokens,
1496
- [ATTR_GEN_AI_RESPONSE_MODEL]: start.model,
1497
- [ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [finishReason],
1626
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI.usage.inputTokens]: inputTokens,
1627
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI.usage.outputTokens]: outputTokens,
1628
+ [ATTRIBUTES.LATITUDE.usage.promptTokens]: tokens.prompt,
1629
+ [ATTRIBUTES.LATITUDE.usage.cachedTokens]: tokens.cached,
1630
+ [ATTRIBUTES.LATITUDE.usage.reasoningTokens]: tokens.reasoning,
1631
+ [ATTRIBUTES.LATITUDE.usage.completionTokens]: tokens.completion,
1632
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI.response.model]: start.model,
1633
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI.response.finishReasons]: [
1634
+ finishReason,
1635
+ ],
1498
1636
  ...(end.attributes || {}),
1499
1637
  },
1500
1638
  });
@@ -1505,16 +1643,10 @@ class ManualInstrumentation {
1505
1643
  embedding(ctx, options) {
1506
1644
  return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Embedding].name, SpanType.Embedding, options);
1507
1645
  }
1508
- retrieval(ctx, options) {
1509
- return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Retrieval].name, SpanType.Retrieval, options);
1510
- }
1511
- reranking(ctx, options) {
1512
- return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Reranking].name, SpanType.Reranking, options);
1513
- }
1514
1646
  attribifyHeaders(direction, headers) {
1515
1647
  const prefix = direction === 'request'
1516
- ? ATTR_HTTP_REQUEST_HEADER
1517
- : ATTR_HTTP_RESPONSE_HEADER;
1648
+ ? ATTRIBUTES.OPENTELEMETRY.HTTP.request.header
1649
+ : ATTRIBUTES.OPENTELEMETRY.HTTP.response.header;
1518
1650
  const attributes = {};
1519
1651
  for (const key in headers) {
1520
1652
  const field = this.toKebabCase(key);
@@ -1538,16 +1670,16 @@ class ManualInstrumentation {
1538
1670
  try {
1539
1671
  finalBody = JSON.stringify(start.request.body);
1540
1672
  }
1541
- catch (error) {
1673
+ catch (_error) {
1542
1674
  finalBody = '{}';
1543
1675
  }
1544
1676
  }
1545
1677
  const span = this.span(ctx, start.name || `${method} ${start.request.url}`, SpanType.Http, {
1546
1678
  attributes: {
1547
- [ATTR_HTTP_REQUEST_METHOD]: method,
1548
- [ATTR_HTTP_REQUEST_URL]: start.request.url,
1679
+ [ATTRIBUTES.OPENTELEMETRY.HTTP.request.method]: method,
1680
+ [ATTRIBUTES.OPENTELEMETRY.HTTP.request.url]: start.request.url,
1549
1681
  ...attrHeaders,
1550
- [ATTR_HTTP_REQUEST_BODY]: finalBody,
1682
+ [ATTRIBUTES.OPENTELEMETRY.HTTP.request.body]: finalBody,
1551
1683
  ...(start.attributes || {}),
1552
1684
  },
1553
1685
  });
@@ -1565,15 +1697,15 @@ class ManualInstrumentation {
1565
1697
  try {
1566
1698
  finalBody = JSON.stringify(end.response.body);
1567
1699
  }
1568
- catch (error) {
1700
+ catch (_error) {
1569
1701
  finalBody = '{}';
1570
1702
  }
1571
1703
  }
1572
1704
  span.end({
1573
1705
  attributes: {
1574
- [ATTR_HTTP_RESPONSE_STATUS_CODE]: end.response.status,
1706
+ [ATTRIBUTES.OPENTELEMETRY.HTTP.response.statusCode]: end.response.status,
1575
1707
  ...attrHeaders,
1576
- [ATTR_HTTP_RESPONSE_BODY]: finalBody,
1708
+ [ATTRIBUTES.OPENTELEMETRY.HTTP.response.body]: finalBody,
1577
1709
  ...(end.attributes || {}),
1578
1710
  },
1579
1711
  });
@@ -1586,49 +1718,48 @@ class ManualInstrumentation {
1586
1718
  try {
1587
1719
  jsonParameters = JSON.stringify(parameters || {});
1588
1720
  }
1589
- catch (error) {
1721
+ catch (_error) {
1590
1722
  jsonParameters = '{}';
1591
1723
  }
1592
1724
  const attributes = {
1593
- [ATTR_GEN_AI_REQUEST_TEMPLATE]: template,
1594
- [ATTR_GEN_AI_REQUEST_PARAMETERS]: jsonParameters,
1595
- [ATTR_LATITUDE_COMMIT_UUID]: versionUuid || HEAD_COMMIT,
1596
- [ATTR_LATITUDE_DOCUMENT_UUID]: promptUuid,
1597
- [ATTR_LATITUDE_PROJECT_ID]: projectId,
1598
- [ATTR_LATITUDE_DOCUMENT_LOG_UUID]: documentLogUuid,
1725
+ [ATTRIBUTES.LATITUDE.request.template]: template,
1726
+ [ATTRIBUTES.LATITUDE.request.parameters]: jsonParameters,
1727
+ [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid || HEAD_COMMIT,
1728
+ [ATTRIBUTES.LATITUDE.documentUuid]: promptUuid,
1729
+ [ATTRIBUTES.LATITUDE.projectId]: projectId,
1730
+ [ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
1599
1731
  ...(experimentUuid && {
1600
- [ATTR_LATITUDE_EXPERIMENT_UUID]: experimentUuid,
1732
+ [ATTRIBUTES.LATITUDE.experimentUuid]: experimentUuid,
1601
1733
  }),
1602
1734
  ...(testDeploymentId && {
1603
- [ATTR_LATITUDE_TEST_DEPLOYMENT_ID]: testDeploymentId,
1735
+ [ATTRIBUTES.LATITUDE.testDeploymentId]: testDeploymentId,
1604
1736
  }),
1605
- ...(externalId && { [ATTR_LATITUDE_EXTERNAL_ID]: externalId }),
1606
- ...(source && { [ATTR_LATITUDE_SOURCE]: source }),
1737
+ ...(externalId && { [ATTRIBUTES.LATITUDE.externalId]: externalId }),
1738
+ ...(source && { [ATTRIBUTES.LATITUDE.source]: source }),
1607
1739
  ...(rest.attributes || {}),
1608
1740
  };
1609
1741
  return this.span(ctx, name || `prompt-${promptUuid}`, SpanType.Prompt, {
1610
1742
  attributes,
1611
1743
  });
1612
1744
  }
1613
- step(ctx, options) {
1614
- return this.span(ctx, 'step', SpanType.Step, options);
1615
- }
1616
- chat(ctx, { documentLogUuid, previousTraceId, source, name, ...rest }) {
1745
+ chat(ctx, { documentLogUuid, previousTraceId, source, name, versionUuid, promptUuid, ...rest }) {
1617
1746
  const attributes = {
1618
- [ATTR_LATITUDE_DOCUMENT_LOG_UUID]: documentLogUuid,
1619
- [ATTR_LATITUDE_PREVIOUS_TRACE_ID]: previousTraceId,
1620
- ...(source && { [ATTR_LATITUDE_SOURCE]: source }),
1747
+ [ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
1748
+ [ATTRIBUTES.LATITUDE.previousTraceId]: previousTraceId,
1749
+ ...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
1750
+ ...(promptUuid && { [ATTRIBUTES.LATITUDE.documentUuid]: promptUuid }),
1751
+ ...(source && { [ATTRIBUTES.LATITUDE.source]: source }),
1621
1752
  ...(rest.attributes || {}),
1622
1753
  };
1623
1754
  return this.span(ctx, name || 'chat', SpanType.Chat, { attributes });
1624
1755
  }
1625
1756
  external(ctx, { promptUuid, documentLogUuid, source, versionUuid, externalId, name, ...rest }) {
1626
1757
  const attributes = {
1627
- [ATTR_LATITUDE_DOCUMENT_UUID]: promptUuid,
1628
- [ATTR_LATITUDE_DOCUMENT_LOG_UUID]: documentLogUuid,
1629
- [ATTR_LATITUDE_SOURCE]: source ?? LogSources.API,
1630
- ...(versionUuid && { [ATTR_LATITUDE_COMMIT_UUID]: versionUuid }),
1631
- ...(externalId && { [ATTR_LATITUDE_EXTERNAL_ID]: externalId }),
1758
+ [ATTRIBUTES.LATITUDE.documentUuid]: promptUuid,
1759
+ [ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
1760
+ [ATTRIBUTES.LATITUDE.source]: source ?? LogSources.API,
1761
+ ...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
1762
+ ...(externalId && { [ATTRIBUTES.LATITUDE.externalId]: externalId }),
1632
1763
  ...(rest.attributes || {}),
1633
1764
  };
1634
1765
  return this.span(ctx, name || `external-${promptUuid}`, SpanType.External, {
@@ -1637,11 +1768,11 @@ class ManualInstrumentation {
1637
1768
  }
1638
1769
  unresolvedExternal(ctx, { path, projectId, versionUuid, conversationUuid, name, ...rest }) {
1639
1770
  const attributes = {
1640
- [ATTR_LATITUDE_PROMPT_PATH]: path,
1641
- [ATTR_LATITUDE_PROJECT_ID]: projectId,
1642
- ...(versionUuid && { [ATTR_LATITUDE_COMMIT_UUID]: versionUuid }),
1771
+ [ATTRIBUTES.LATITUDE.promptPath]: path,
1772
+ [ATTRIBUTES.LATITUDE.projectId]: projectId,
1773
+ ...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
1643
1774
  ...(conversationUuid && {
1644
- [ATTR_LATITUDE_DOCUMENT_LOG_UUID]: conversationUuid,
1775
+ [ATTRIBUTES.LATITUDE.documentLogUuid]: conversationUuid,
1645
1776
  }),
1646
1777
  ...(rest.attributes || {}),
1647
1778
  };
@@ -1706,19 +1837,6 @@ class LatitudeInstrumentation {
1706
1837
  $prompt.end();
1707
1838
  return result;
1708
1839
  }
1709
- async wrapRenderStep(fn, ...args) {
1710
- const $step = this.manualTelemetry.step(context.active());
1711
- let result;
1712
- try {
1713
- result = await context.with($step.context, async () => await fn(...args));
1714
- }
1715
- catch (error) {
1716
- $step.fail(error);
1717
- throw error;
1718
- }
1719
- $step.end();
1720
- return result;
1721
- }
1722
1840
  async wrapRenderCompletion(fn, ...args) {
1723
1841
  if (!this.options.completions) {
1724
1842
  return await fn(...args);
@@ -1752,8 +1870,8 @@ class LatitudeInstrumentation {
1752
1870
  completion: completionTokens,
1753
1871
  },
1754
1872
  finishReason: result.toolRequests.length > 0
1755
- ? GEN_AI_RESPONSE_FINISH_REASON_VALUE_TOOL_CALLS
1756
- : GEN_AI_RESPONSE_FINISH_REASON_VALUE_STOP,
1873
+ ? VALUES.OPENTELEMETRY.GEN_AI.response.finishReasons.toolCalls
1874
+ : VALUES.OPENTELEMETRY.GEN_AI.response.finishReasons.stop,
1757
1875
  });
1758
1876
  return result;
1759
1877
  }
@@ -1798,6 +1916,7 @@ var LatitudeErrorCodes;
1798
1916
  LatitudeErrorCodes["NotImplementedError"] = "NotImplementedError";
1799
1917
  LatitudeErrorCodes["PaymentRequiredError"] = "PaymentRequiredError";
1800
1918
  LatitudeErrorCodes["AbortedError"] = "AbortedError";
1919
+ LatitudeErrorCodes["BillingError"] = "BillingError";
1801
1920
  })(LatitudeErrorCodes || (LatitudeErrorCodes = {}));
1802
1921
  // NOTE: If you add a new error code, please add it to the pg enum in models/runErrors.ts
1803
1922
  var RunErrorCodes;
@@ -1877,21 +1996,12 @@ class SpanFactory {
1877
1996
  embedding(options, ctx) {
1878
1997
  return this.telemetry.embedding(ctx ?? context.active(), options);
1879
1998
  }
1880
- retrieval(options, ctx) {
1881
- return this.telemetry.retrieval(ctx ?? context.active(), options);
1882
- }
1883
- reranking(options, ctx) {
1884
- return this.telemetry.reranking(ctx ?? context.active(), options);
1885
- }
1886
1999
  http(options, ctx) {
1887
2000
  return this.telemetry.http(ctx ?? context.active(), options);
1888
2001
  }
1889
2002
  prompt(options, ctx) {
1890
2003
  return this.telemetry.prompt(ctx ?? context.active(), options);
1891
2004
  }
1892
- step(options, ctx) {
1893
- return this.telemetry.step(ctx ?? context.active(), options);
1894
- }
1895
2005
  chat(options, ctx) {
1896
2006
  return this.telemetry.chat(ctx ?? context.active(), options);
1897
2007
  }
@@ -2072,8 +2182,9 @@ class LatitudeTelemetry {
2072
2182
  configureInstrumentation(Instrumentation.Cohere, CohereInstrumentation); // prettier-ignore
2073
2183
  configureInstrumentation(Instrumentation.Langchain, LangChainInstrumentation); // prettier-ignore
2074
2184
  configureInstrumentation(Instrumentation.LlamaIndex, LlamaIndexInstrumentation); // prettier-ignore
2075
- configureInstrumentation(Instrumentation.OpenAI, OpenAIInstrumentation, { enrichTokens: true }); // prettier-ignore
2076
- configureInstrumentation(Instrumentation.TogetherAI, TogetherInstrumentation, { enrichTokens: true }); // prettier-ignore
2185
+ // NOTE: `stream: true` in OpenAI make enrichTokens fail, so disabling.
2186
+ configureInstrumentation(Instrumentation.OpenAI, OpenAIInstrumentation, { enrichTokens: false }); // prettier-ignore
2187
+ configureInstrumentation(Instrumentation.TogetherAI, TogetherInstrumentation, { enrichTokens: false }); // prettier-ignore
2077
2188
  configureInstrumentation(Instrumentation.VertexAI, VertexAIInstrumentation); // prettier-ignore
2078
2189
  }
2079
2190
  async capture(options, fn) {