@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.cjs CHANGED
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  var zod = require('zod');
4
- var otel = require('@opentelemetry/api');
5
- var semanticConventions = require('@opentelemetry/semantic-conventions');
6
4
  var incubating = require('@opentelemetry/semantic-conventions/incubating');
5
+ var semanticConventions = require('@opentelemetry/semantic-conventions');
6
+ var otel = require('@opentelemetry/api');
7
7
  var uuid = require('uuid');
8
8
  var baggageSpanProcessor = require('@opentelemetry/baggage-span-processor');
9
9
  var contextAsyncHooks = require('@opentelemetry/context-async-hooks');
@@ -150,6 +150,15 @@ zod.z.object({
150
150
  isError: zod.z.boolean().optional(),
151
151
  text: zod.z.string().optional(),
152
152
  });
153
+ zod.z.object({
154
+ inputTokens: zod.z.number(),
155
+ outputTokens: zod.z.number(),
156
+ promptTokens: zod.z.number(),
157
+ completionTokens: zod.z.number(),
158
+ totalTokens: zod.z.number(),
159
+ reasoningTokens: zod.z.number(),
160
+ cachedInputTokens: zod.z.number(),
161
+ });
153
162
 
154
163
  var ParameterType;
155
164
  (function (ParameterType) {
@@ -209,7 +218,6 @@ const compositeEvaluationConfiguration = baseEvaluationConfiguration.extend({
209
218
  evaluationUuids: zod.z.array(zod.z.string()),
210
219
  minThreshold: zod.z.number().optional(), // Threshold percentage
211
220
  maxThreshold: zod.z.number().optional(), // Threshold percentage
212
- defaultTarget: zod.z.boolean().optional(), // Default for optimizations and distillations
213
221
  });
214
222
  const compositeEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
215
223
  results: zod.z.record(zod.z.string(), // Evaluation uuid
@@ -276,12 +284,34 @@ const CompositeEvaluationSpecification = {
276
284
  },
277
285
  };
278
286
 
287
+ const selectedContextSchema = zod.z.object({
288
+ messageIndex: zod.z.number().int().nonnegative(),
289
+ contentBlockIndex: zod.z.number().int().nonnegative(),
290
+ contentType: zod.z.enum([
291
+ 'text',
292
+ 'reasoning',
293
+ 'image',
294
+ 'file',
295
+ 'tool-call',
296
+ 'tool-result',
297
+ ]),
298
+ textRange: zod.z
299
+ .object({
300
+ start: zod.z.number().int().nonnegative(),
301
+ end: zod.z.number().int().nonnegative(),
302
+ })
303
+ .optional(),
304
+ selectedText: zod.z.string().optional(),
305
+ toolCallId: zod.z.string().optional(),
306
+ });
279
307
  const humanEvaluationConfiguration = baseEvaluationConfiguration.extend({
280
308
  enableControls: zod.z.boolean().optional(), // UI annotation controls
281
309
  criteria: zod.z.string().optional(),
282
310
  });
283
311
  const humanEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
284
312
  reason: zod.z.string().optional(),
313
+ enrichedReason: zod.z.string().optional(),
314
+ selectedContexts: zod.z.array(selectedContextSchema).optional(),
285
315
  });
286
316
  const humanEvaluationResultError = baseEvaluationResultError.extend({});
287
317
  // BINARY
@@ -559,8 +589,6 @@ zod.z.object({
559
589
  });
560
590
  zod.z.object({
561
591
  evaluateLiveLogs: zod.z.boolean().nullable().optional(),
562
- enableSuggestions: zod.z.boolean().nullable().optional(),
563
- autoApplySuggestions: zod.z.boolean().nullable().optional(),
564
592
  });
565
593
 
566
594
  var LegacyChainEventTypes;
@@ -758,6 +786,7 @@ var LogSources;
758
786
  LogSources["ShadowTest"] = "shadow_test";
759
787
  LogSources["ABTestChallenger"] = "ab_test_challenger";
760
788
  LogSources["User"] = "user";
789
+ LogSources["Optimization"] = "optimization";
761
790
  })(LogSources || (LogSources = {}));
762
791
 
763
792
  var RunSourceGroup;
@@ -768,7 +797,8 @@ var RunSourceGroup;
768
797
  ({
769
798
  [RunSourceGroup.Production]: [
770
799
  LogSources.API,
771
- LogSources.Copilot,
800
+ LogSources.ShadowTest,
801
+ LogSources.ABTestChallenger,
772
802
  LogSources.EmailTrigger,
773
803
  LogSources.IntegrationTrigger,
774
804
  LogSources.ScheduledTrigger,
@@ -797,26 +827,49 @@ var SpanKind;
797
827
  // Note: loosely based on OpenTelemetry GenAI semantic conventions
798
828
  var SpanType;
799
829
  (function (SpanType) {
800
- SpanType["Tool"] = "tool";
801
- SpanType["Completion"] = "completion";
802
- SpanType["Embedding"] = "embedding";
803
- SpanType["Retrieval"] = "retrieval";
804
- SpanType["Reranking"] = "reranking";
805
- SpanType["Http"] = "http";
806
- SpanType["Unknown"] = "unknown";
830
+ // Latitude wrappers
807
831
  SpanType["Prompt"] = "prompt";
808
832
  SpanType["Chat"] = "chat";
809
833
  SpanType["External"] = "external";
810
834
  SpanType["UnresolvedExternal"] = "unresolved_external";
811
- SpanType["Step"] = "step";
835
+ // Added a HTTP span to capture raw HTTP requests and responses when running from Latitude
836
+ SpanType["Http"] = "http";
837
+ // Any known span from supported specifications will be grouped into one of these types
838
+ SpanType["Completion"] = "completion";
839
+ SpanType["Tool"] = "tool";
840
+ SpanType["Embedding"] = "embedding";
841
+ SpanType["Unknown"] = "unknown";
812
842
  })(SpanType || (SpanType = {}));
843
+ [
844
+ SpanType.Prompt,
845
+ SpanType.External,
846
+ SpanType.Chat,
847
+ ];
813
848
  const SPAN_SPECIFICATIONS = {
814
- [SpanType.Tool]: {
815
- name: 'Tool',
816
- description: 'A tool call',
817
- isGenAI: true,
849
+ [SpanType.Prompt]: {
850
+ name: 'Prompt',
851
+ description: 'A prompt span',
852
+ isGenAI: false,
853
+ isHidden: false,
854
+ },
855
+ [SpanType.Chat]: {
856
+ name: 'Chat',
857
+ description: 'A chat continuation span',
858
+ isGenAI: false,
818
859
  isHidden: false,
819
860
  },
861
+ [SpanType.External]: {
862
+ name: 'External',
863
+ description: 'An external capture span',
864
+ isGenAI: false,
865
+ isHidden: false,
866
+ },
867
+ [SpanType.UnresolvedExternal]: {
868
+ name: 'Unresolved External',
869
+ description: 'An external span that needs path resolution before storage',
870
+ isGenAI: false,
871
+ isHidden: true,
872
+ },
820
873
  [SpanType.Completion]: {
821
874
  name: 'Completion',
822
875
  description: 'A completion call',
@@ -829,15 +882,9 @@ const SPAN_SPECIFICATIONS = {
829
882
  isGenAI: true,
830
883
  isHidden: false,
831
884
  },
832
- [SpanType.Retrieval]: {
833
- name: 'Retrieval',
834
- description: 'A retrieval call',
835
- isGenAI: true,
836
- isHidden: false,
837
- },
838
- [SpanType.Reranking]: {
839
- name: 'Reranking',
840
- description: 'A reranking call',
885
+ [SpanType.Tool]: {
886
+ name: 'Tool',
887
+ description: 'A tool call',
841
888
  isGenAI: true,
842
889
  isHidden: false,
843
890
  },
@@ -853,36 +900,6 @@ const SPAN_SPECIFICATIONS = {
853
900
  isGenAI: false,
854
901
  isHidden: true,
855
902
  },
856
- [SpanType.Prompt]: {
857
- name: 'Prompt',
858
- description: 'A prompt span',
859
- isGenAI: false,
860
- isHidden: false,
861
- },
862
- [SpanType.Chat]: {
863
- name: 'Chat',
864
- description: 'A chat continuation span',
865
- isGenAI: false,
866
- isHidden: false,
867
- },
868
- [SpanType.External]: {
869
- name: 'External',
870
- description: 'An external capture span',
871
- isGenAI: false,
872
- isHidden: false,
873
- },
874
- [SpanType.UnresolvedExternal]: {
875
- name: 'Unresolved External',
876
- description: 'An external span that needs path resolution before storage',
877
- isGenAI: false,
878
- isHidden: true,
879
- },
880
- [SpanType.Step]: {
881
- name: 'Step',
882
- description: 'A step span',
883
- isGenAI: false,
884
- isHidden: false,
885
- },
886
903
  };
887
904
  var SpanStatus;
888
905
  (function (SpanStatus) {
@@ -890,6 +907,11 @@ var SpanStatus;
890
907
  SpanStatus["Ok"] = "ok";
891
908
  SpanStatus["Error"] = "error";
892
909
  })(SpanStatus || (SpanStatus = {}));
910
+ new Set([
911
+ SpanType.Prompt,
912
+ SpanType.Chat,
913
+ SpanType.External,
914
+ ]);
893
915
 
894
916
  // Note: Traces are unmaterialized but this context is used to propagate the trace
895
917
  // See www.w3.org/TR/trace-context and w3c.github.io/baggage
@@ -899,6 +921,130 @@ zod.z.object({
899
921
  baggage: zod.z.string().optional(), // <key>=urlencoded(<value>)[,<key>=urlencoded(<value>)]*
900
922
  });
901
923
 
924
+ const ATTRIBUTES = {
925
+ // Custom attributes added and used by Latitude spans (Prompt / External / Chat)
926
+ LATITUDE: {
927
+ type: 'latitude.type',
928
+ documentUuid: 'latitude.document_uuid',
929
+ promptPath: 'latitude.prompt_path',
930
+ commitUuid: 'latitude.commit_uuid',
931
+ documentLogUuid: 'latitude.document_log_uuid',
932
+ projectId: 'latitude.project_id',
933
+ experimentUuid: 'latitude.experiment_uuid',
934
+ source: 'latitude.source',
935
+ externalId: 'latitude.external_id',
936
+ testDeploymentId: 'latitude.test_deployment_id',
937
+ previousTraceId: 'latitude.previous_trace_id',
938
+ // Custom additions to the GenAI semantic conventions (deprecated)
939
+ request: {
940
+ _root: 'gen_ai.request',
941
+ configuration: 'gen_ai.request.configuration',
942
+ template: 'gen_ai.request.template',
943
+ parameters: 'gen_ai.request.parameters',
944
+ messages: 'gen_ai.request.messages'},
945
+ response: {
946
+ _root: 'gen_ai.response',
947
+ messages: 'gen_ai.response.messages',
948
+ },
949
+ usage: {
950
+ promptTokens: 'gen_ai.usage.prompt_tokens',
951
+ cachedTokens: 'gen_ai.usage.cached_tokens',
952
+ reasoningTokens: 'gen_ai.usage.reasoning_tokens',
953
+ completionTokens: 'gen_ai.usage.completion_tokens',
954
+ },
955
+ },
956
+ // Official OpenTelemetry semantic conventions
957
+ OPENTELEMETRY: {
958
+ HTTP: {
959
+ request: {
960
+ url: 'http.request.url',
961
+ body: 'http.request.body',
962
+ header: 'http.request.header',
963
+ method: semanticConventions.ATTR_HTTP_REQUEST_METHOD,
964
+ },
965
+ response: {
966
+ body: 'http.response.body',
967
+ header: 'http.response.header',
968
+ statusCode: semanticConventions.ATTR_HTTP_RESPONSE_STATUS_CODE,
969
+ },
970
+ },
971
+ // GenAI semantic conventions
972
+ // https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/
973
+ GEN_AI: {
974
+ operation: incubating.ATTR_GEN_AI_OPERATION_NAME,
975
+ response: {
976
+ model: incubating.ATTR_GEN_AI_RESPONSE_MODEL,
977
+ finishReasons: incubating.ATTR_GEN_AI_RESPONSE_FINISH_REASONS,
978
+ },
979
+ usage: {
980
+ inputTokens: incubating.ATTR_GEN_AI_USAGE_INPUT_TOKENS,
981
+ outputTokens: incubating.ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,
982
+ },
983
+ tool: {
984
+ call: {
985
+ id: incubating.ATTR_GEN_AI_TOOL_CALL_ID,
986
+ arguments: 'gen_ai.tool.call.arguments'}},
987
+ _deprecated: {
988
+ system: incubating.ATTR_GEN_AI_SYSTEM,
989
+ tool: {
990
+ name: incubating.ATTR_GEN_AI_TOOL_NAME,
991
+ type: incubating.ATTR_GEN_AI_TOOL_TYPE,
992
+ result: {
993
+ value: 'gen_ai.tool.result.value',
994
+ isError: 'gen_ai.tool.result.is_error',
995
+ },
996
+ },
997
+ prompt: {
998
+ _root: 'gen_ai.prompt',
999
+ index: (promptIndex) => ({
1000
+ role: `gen_ai.prompt.${promptIndex}.role`,
1001
+ content: `gen_ai.prompt.${promptIndex}.content`, // string or object
1002
+ toolCalls: (toolCallIndex) => ({
1003
+ id: `gen_ai.prompt.${promptIndex}.tool_calls.${toolCallIndex}.id`,
1004
+ name: `gen_ai.prompt.${promptIndex}.tool_calls.${toolCallIndex}.name`,
1005
+ arguments: `gen_ai.prompt.${promptIndex}.tool_calls.${toolCallIndex}.arguments`,
1006
+ }),
1007
+ tool: {
1008
+ callId: `gen_ai.prompt.${promptIndex}.tool_call_id`,
1009
+ toolName: `gen_ai.prompt.${promptIndex}.tool_name`,
1010
+ isError: `gen_ai.prompt.${promptIndex}.is_error`,
1011
+ },
1012
+ }),
1013
+ },
1014
+ completion: {
1015
+ _root: 'gen_ai.completion',
1016
+ index: (completionIndex) => ({
1017
+ role: `gen_ai.completion.${completionIndex}.role`,
1018
+ content: `gen_ai.completion.${completionIndex}.content`, // string or object
1019
+ toolCalls: (toolCallIndex) => ({
1020
+ id: `gen_ai.completion.${completionIndex}.tool_calls.${toolCallIndex}.id`,
1021
+ name: `gen_ai.completion.${completionIndex}.tool_calls.${toolCallIndex}.name`,
1022
+ arguments: `gen_ai.completion.${completionIndex}.tool_calls.${toolCallIndex}.arguments`,
1023
+ }),
1024
+ tool: {
1025
+ callId: `gen_ai.prompt.${completionIndex}.tool_call_id`,
1026
+ toolName: `gen_ai.prompt.${completionIndex}.tool_name`,
1027
+ isError: `gen_ai.prompt.${completionIndex}.is_error`,
1028
+ },
1029
+ }),
1030
+ }},
1031
+ },
1032
+ }};
1033
+ const VALUES = {
1034
+ OPENTELEMETRY: {
1035
+ GEN_AI: {
1036
+ response: {
1037
+ finishReasons: {
1038
+ stop: 'stop',
1039
+ toolCalls: 'tool_calls'},
1040
+ },
1041
+ tool: {
1042
+ type: {
1043
+ function: 'function',
1044
+ },
1045
+ }},
1046
+ }};
1047
+
902
1048
  /* Note: Instrumentation scopes from all language SDKs */
903
1049
  const SCOPE_LATITUDE = 'so.latitude.instrumentation';
904
1050
  var InstrumentationScope;
@@ -927,52 +1073,6 @@ var InstrumentationScope;
927
1073
  InstrumentationScope["Transformers"] = "transformers";
928
1074
  InstrumentationScope["AlephAlpha"] = "alephalpha";
929
1075
  })(InstrumentationScope || (InstrumentationScope = {}));
930
- /* Note: non-standard OpenTelemetry semantic conventions used in Latitude */
931
- const ATTR_LATITUDE = 'latitude';
932
- const ATTR_LATITUDE_TYPE = `${ATTR_LATITUDE}.type`;
933
- const ATTR_LATITUDE_DOCUMENT_UUID = `${ATTR_LATITUDE}.document_uuid`;
934
- const ATTR_LATITUDE_PROMPT_PATH = `${ATTR_LATITUDE}.prompt_path`;
935
- const ATTR_LATITUDE_COMMIT_UUID = `${ATTR_LATITUDE}.commit_uuid`;
936
- const ATTR_LATITUDE_DOCUMENT_LOG_UUID = `${ATTR_LATITUDE}.document_log_uuid`;
937
- const ATTR_LATITUDE_PROJECT_ID = `${ATTR_LATITUDE}.project_id`;
938
- const ATTR_LATITUDE_EXPERIMENT_UUID = `${ATTR_LATITUDE}.experiment_uuid`;
939
- const ATTR_LATITUDE_SOURCE = `${ATTR_LATITUDE}.source`;
940
- const ATTR_LATITUDE_EXTERNAL_ID = `${ATTR_LATITUDE}.external_id`;
941
- const ATTR_LATITUDE_TEST_DEPLOYMENT_ID = `${ATTR_LATITUDE}.test_deployment_id`;
942
- const ATTR_LATITUDE_PREVIOUS_TRACE_ID = `${ATTR_LATITUDE}.previous_trace_id`;
943
- const GEN_AI_TOOL_TYPE_VALUE_FUNCTION = 'function';
944
- const ATTR_GEN_AI_TOOL_CALL_ARGUMENTS = 'gen_ai.tool.call.arguments';
945
- const ATTR_GEN_AI_TOOL_RESULT_VALUE = 'gen_ai.tool.result.value';
946
- const ATTR_GEN_AI_TOOL_RESULT_IS_ERROR = 'gen_ai.tool.result.is_error';
947
- const ATTR_GEN_AI_REQUEST = 'gen_ai.request';
948
- const ATTR_GEN_AI_REQUEST_CONFIGURATION = 'gen_ai.request.configuration';
949
- const ATTR_GEN_AI_REQUEST_TEMPLATE = 'gen_ai.request.template';
950
- const ATTR_GEN_AI_REQUEST_PARAMETERS = 'gen_ai.request.parameters';
951
- const ATTR_GEN_AI_REQUEST_MESSAGES = 'gen_ai.request.messages';
952
- const ATTR_GEN_AI_RESPONSE = 'gen_ai.response';
953
- const ATTR_GEN_AI_RESPONSE_MESSAGES = 'gen_ai.response.messages';
954
- const ATTR_GEN_AI_USAGE_PROMPT_TOKENS = 'gen_ai.usage.prompt_tokens';
955
- const ATTR_GEN_AI_USAGE_CACHED_TOKENS = 'gen_ai.usage.cached_tokens';
956
- const ATTR_GEN_AI_USAGE_REASONING_TOKENS = 'gen_ai.usage.reasoning_tokens'; // prettier-ignore
957
- const ATTR_GEN_AI_USAGE_COMPLETION_TOKENS = 'gen_ai.usage.completion_tokens'; // prettier-ignore
958
- const ATTR_GEN_AI_PROMPTS = 'gen_ai.prompt'; // gen_ai.prompt.{index}.{role/content/...}
959
- const ATTR_GEN_AI_COMPLETIONS = 'gen_ai.completion'; // gen_ai.completion.{index}.{role/content/...}
960
- const ATTR_GEN_AI_MESSAGE_ROLE = 'role';
961
- const ATTR_GEN_AI_MESSAGE_CONTENT = 'content'; // string or object
962
- const ATTR_GEN_AI_MESSAGE_TOOL_NAME = 'tool_name';
963
- const ATTR_GEN_AI_MESSAGE_TOOL_CALL_ID = 'tool_call_id';
964
- const ATTR_GEN_AI_MESSAGE_TOOL_RESULT_IS_ERROR = 'is_error';
965
- const ATTR_GEN_AI_MESSAGE_TOOL_CALLS = 'tool_calls'; // gen_ai.completion.{index}.tool_calls.{index}.{id/name/arguments}
966
- const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ID = 'id';
967
- const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME = 'name';
968
- const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS = 'arguments';
969
- const GEN_AI_RESPONSE_FINISH_REASON_VALUE_STOP = 'stop';
970
- const GEN_AI_RESPONSE_FINISH_REASON_VALUE_TOOL_CALLS = 'tool_calls';
971
- const ATTR_HTTP_REQUEST_URL = 'http.request.url';
972
- const ATTR_HTTP_REQUEST_BODY = 'http.request.body';
973
- const ATTR_HTTP_REQUEST_HEADER = 'http.request.header';
974
- const ATTR_HTTP_RESPONSE_BODY = 'http.response.body';
975
- const ATTR_HTTP_RESPONSE_HEADER = 'http.response.header';
976
1076
  /* Note: Schemas for span ingestion following OpenTelemetry service request specification */
977
1077
  var Otlp;
978
1078
  (function (Otlp) {
@@ -1053,6 +1153,40 @@ var Otlp;
1053
1153
  });
1054
1154
  })(Otlp || (Otlp = {}));
1055
1155
 
1156
+ const MAX_SIMULATION_TURNS = 10;
1157
+ const SimulationSettingsSchema = zod.z.object({
1158
+ simulateToolResponses: zod.z.boolean().optional(),
1159
+ simulatedTools: zod.z.array(zod.z.string()).optional(), // Empty array means all tools are simulated (if simulateToolResponses is true).
1160
+ toolSimulationInstructions: zod.z.string().optional(), // A prompt used to guide and generate the simulation result
1161
+ maxTurns: zod.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.
1162
+ });
1163
+
1164
+ var OptimizationEngine;
1165
+ (function (OptimizationEngine) {
1166
+ OptimizationEngine["Identity"] = "identity";
1167
+ OptimizationEngine["Gepa"] = "gepa";
1168
+ })(OptimizationEngine || (OptimizationEngine = {}));
1169
+ const OptimizationBudgetSchema = zod.z.object({
1170
+ time: zod.z.number().min(0).optional(),
1171
+ tokens: zod.z.number().min(0).optional(),
1172
+ });
1173
+ zod.z.object({
1174
+ parameters: zod.z
1175
+ .record(zod.z.string(), zod.z.object({
1176
+ column: zod.z.string().optional(), // Note: corresponding column in the user-provided trainset and testset
1177
+ isPii: zod.z.boolean().optional(),
1178
+ }))
1179
+ .optional(),
1180
+ simulation: SimulationSettingsSchema.optional(),
1181
+ scope: zod.z
1182
+ .object({
1183
+ configuration: zod.z.boolean().optional(),
1184
+ instructions: zod.z.boolean().optional(),
1185
+ })
1186
+ .optional(),
1187
+ budget: OptimizationBudgetSchema.optional(),
1188
+ });
1189
+
1056
1190
  // TODO(tracing): deprecated
1057
1191
  const HEAD_COMMIT = 'live';
1058
1192
  var Providers;
@@ -1198,9 +1332,9 @@ class ManualInstrumentation {
1198
1332
  }
1199
1333
  const span = this.tracer.startSpan(name, {
1200
1334
  attributes: {
1201
- [ATTR_LATITUDE_TYPE]: type,
1335
+ [ATTRIBUTES.LATITUDE.type]: type,
1202
1336
  ...(operation && {
1203
- [incubating.ATTR_GEN_AI_OPERATION_NAME]: operation,
1337
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI.operation]: operation,
1204
1338
  }),
1205
1339
  ...(start.attributes || {}),
1206
1340
  },
@@ -1226,15 +1360,15 @@ class ManualInstrumentation {
1226
1360
  try {
1227
1361
  jsonArguments = JSON.stringify(start.call.arguments);
1228
1362
  }
1229
- catch (error) {
1363
+ catch (_error) {
1230
1364
  jsonArguments = '{}';
1231
1365
  }
1232
1366
  const span = this.span(ctx, start.name, SpanType.Tool, {
1233
1367
  attributes: {
1234
- [incubating.ATTR_GEN_AI_TOOL_NAME]: start.name,
1235
- [incubating.ATTR_GEN_AI_TOOL_TYPE]: GEN_AI_TOOL_TYPE_VALUE_FUNCTION,
1236
- [incubating.ATTR_GEN_AI_TOOL_CALL_ID]: start.call.id,
1237
- [ATTR_GEN_AI_TOOL_CALL_ARGUMENTS]: jsonArguments,
1368
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.name]: start.name,
1369
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.type]: VALUES.OPENTELEMETRY.GEN_AI.tool.type.function,
1370
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI.tool.call.id]: start.call.id,
1371
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI.tool.call.arguments]: jsonArguments,
1238
1372
  ...(start.attributes || {}),
1239
1373
  },
1240
1374
  });
@@ -1247,7 +1381,7 @@ class ManualInstrumentation {
1247
1381
  try {
1248
1382
  stringResult = JSON.stringify(end.result.value);
1249
1383
  }
1250
- catch (error) {
1384
+ catch (_error) {
1251
1385
  stringResult = '{}';
1252
1386
  }
1253
1387
  }
@@ -1256,8 +1390,8 @@ class ManualInstrumentation {
1256
1390
  }
1257
1391
  span.end({
1258
1392
  attributes: {
1259
- [ATTR_GEN_AI_TOOL_RESULT_VALUE]: stringResult,
1260
- [ATTR_GEN_AI_TOOL_RESULT_IS_ERROR]: end.result.isError,
1393
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.result.value]: stringResult,
1394
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.tool.result.isError]: end.result.isError,
1261
1395
  ...(end.attributes || {}),
1262
1396
  },
1263
1397
  });
@@ -1265,12 +1399,12 @@ class ManualInstrumentation {
1265
1399
  fail: span.fail,
1266
1400
  };
1267
1401
  }
1268
- attribifyMessageToolCalls(prefix, toolCalls) {
1402
+ attribifyMessageToolCalls(otelMessageField, toolCalls) {
1269
1403
  const attributes = {};
1270
1404
  for (let i = 0; i < toolCalls.length; i++) {
1271
1405
  for (const key in toolCalls[i]) {
1272
1406
  const field = this.toCamelCase(key);
1273
- let value = toolCalls[i][key];
1407
+ const value = toolCalls[i][key];
1274
1408
  if (value === null || value === undefined)
1275
1409
  continue;
1276
1410
  switch (field) {
@@ -1279,28 +1413,29 @@ class ManualInstrumentation {
1279
1413
  case 'toolUseId': {
1280
1414
  if (typeof value !== 'string')
1281
1415
  continue;
1282
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ID}`] = value;
1416
+ attributes[otelMessageField.toolCalls(i).id] = value;
1283
1417
  break;
1284
1418
  }
1285
1419
  case 'name':
1286
1420
  case 'toolName': {
1287
1421
  if (typeof value !== 'string')
1288
1422
  continue;
1289
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME}`] = value;
1423
+ attributes[otelMessageField.toolCalls(i).name] = value;
1290
1424
  break;
1291
1425
  }
1292
1426
  case 'arguments':
1293
1427
  case 'toolArguments':
1294
1428
  case 'input': {
1295
1429
  if (typeof value === 'string') {
1296
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = value;
1430
+ attributes[otelMessageField.toolCalls(i).arguments] = value;
1297
1431
  }
1298
1432
  else {
1299
1433
  try {
1300
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = JSON.stringify(value);
1434
+ attributes[otelMessageField.toolCalls(i).arguments] =
1435
+ JSON.stringify(value);
1301
1436
  }
1302
- catch (error) {
1303
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = '{}';
1437
+ catch (_error) {
1438
+ attributes[otelMessageField.toolCalls(i).arguments] = '{}';
1304
1439
  }
1305
1440
  }
1306
1441
  break;
@@ -1317,8 +1452,9 @@ class ManualInstrumentation {
1317
1452
  continue;
1318
1453
  if (typeof value.arguments !== 'string')
1319
1454
  continue;
1320
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME}`] = value.name;
1321
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS}`] = value.arguments;
1455
+ attributes[otelMessageField.toolCalls(i).name] = value.name;
1456
+ attributes[otelMessageField.toolCalls(i).arguments] =
1457
+ value.arguments;
1322
1458
  break;
1323
1459
  }
1324
1460
  }
@@ -1326,18 +1462,16 @@ class ManualInstrumentation {
1326
1462
  }
1327
1463
  return attributes;
1328
1464
  }
1329
- attribifyMessageContent(prefix, content) {
1465
+ attribifyMessageContent(otelMessageField, content) {
1330
1466
  let attributes = {};
1331
1467
  if (typeof content === 'string') {
1332
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] = content;
1333
1468
  return attributes;
1334
1469
  }
1335
1470
  try {
1336
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] =
1337
- JSON.stringify(content);
1471
+ attributes[otelMessageField.content] = JSON.stringify(content);
1338
1472
  }
1339
- catch (error) {
1340
- attributes[`${prefix}.${ATTR_GEN_AI_MESSAGE_CONTENT}`] = '[]';
1473
+ catch (_error) {
1474
+ attributes[otelMessageField.content] = '[]';
1341
1475
  }
1342
1476
  if (!Array.isArray(content))
1343
1477
  return attributes;
@@ -1357,32 +1491,34 @@ class ManualInstrumentation {
1357
1491
  if (toolCalls.length > 0) {
1358
1492
  attributes = {
1359
1493
  ...attributes,
1360
- ...this.attribifyMessageToolCalls(prefix, toolCalls),
1494
+ ...this.attribifyMessageToolCalls(otelMessageField, toolCalls),
1361
1495
  };
1362
1496
  }
1363
1497
  return attributes;
1364
1498
  }
1365
1499
  attribifyMessages(direction, messages) {
1366
- const prefix = direction === 'input' ? ATTR_GEN_AI_PROMPTS : ATTR_GEN_AI_COMPLETIONS;
1500
+ const otelField = direction === 'input'
1501
+ ? ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.prompt
1502
+ : ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.completion;
1367
1503
  let attributes = {};
1368
1504
  for (let i = 0; i < messages.length; i++) {
1369
1505
  for (const key in messages[i]) {
1370
1506
  const field = this.toCamelCase(key);
1371
- let value = messages[i][key];
1507
+ const value = messages[i][key];
1372
1508
  if (value === null || value === undefined)
1373
1509
  continue;
1374
1510
  switch (field) {
1375
1511
  case 'role': {
1376
1512
  if (typeof value !== 'string')
1377
1513
  continue;
1378
- attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_ROLE}`] = value;
1514
+ attributes[otelField.index(i).role] = value;
1379
1515
  break;
1380
1516
  }
1381
1517
  /* Tool calls for Anthropic and PromptL are in the content */
1382
1518
  case 'content': {
1383
1519
  attributes = {
1384
1520
  ...attributes,
1385
- ...this.attribifyMessageContent(`${prefix}.${i}`, value),
1521
+ ...this.attribifyMessageContent(otelField.index(i), value),
1386
1522
  };
1387
1523
  break;
1388
1524
  }
@@ -1392,7 +1528,7 @@ class ManualInstrumentation {
1392
1528
  continue;
1393
1529
  attributes = {
1394
1530
  ...attributes,
1395
- ...this.attribifyMessageToolCalls(`${prefix}.${i}`, value),
1531
+ ...this.attribifyMessageToolCalls(otelField.index(i), value),
1396
1532
  };
1397
1533
  break;
1398
1534
  }
@@ -1402,22 +1538,20 @@ class ManualInstrumentation {
1402
1538
  case 'toolUseId': {
1403
1539
  if (typeof value !== 'string')
1404
1540
  continue;
1405
- attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_CALL_ID}`] =
1406
- value;
1541
+ attributes[otelField.index(i).tool.callId] = value;
1407
1542
  break;
1408
1543
  }
1409
1544
  case 'toolName': {
1410
1545
  if (typeof value !== 'string')
1411
1546
  continue;
1412
- attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_NAME}`] =
1413
- value;
1547
+ attributes[otelField.index(i).tool.toolName] = value;
1414
1548
  break;
1415
1549
  }
1416
1550
  // Note: 'toolResult' is 'content' itself
1417
1551
  case 'isError': {
1418
1552
  if (typeof value !== 'boolean')
1419
1553
  continue;
1420
- attributes[`${prefix}.${i}.${ATTR_GEN_AI_MESSAGE_TOOL_RESULT_IS_ERROR}`] = value;
1554
+ attributes[otelField.index(i).tool.isError] = value;
1421
1555
  break;
1422
1556
  }
1423
1557
  }
@@ -1426,7 +1560,9 @@ class ManualInstrumentation {
1426
1560
  return attributes;
1427
1561
  }
1428
1562
  attribifyConfiguration(direction, configuration) {
1429
- const prefix = direction === 'input' ? ATTR_GEN_AI_REQUEST : ATTR_GEN_AI_RESPONSE;
1563
+ const prefix = direction === 'input'
1564
+ ? ATTRIBUTES.LATITUDE.request._root
1565
+ : ATTRIBUTES.LATITUDE.response._root;
1430
1566
  const attributes = {};
1431
1567
  for (const key in configuration) {
1432
1568
  const field = this.toSnakeCase(key);
@@ -1437,7 +1573,7 @@ class ManualInstrumentation {
1437
1573
  try {
1438
1574
  value = JSON.stringify(value);
1439
1575
  }
1440
- catch (error) {
1576
+ catch (_error) {
1441
1577
  value = '{}';
1442
1578
  }
1443
1579
  }
@@ -1455,7 +1591,7 @@ class ManualInstrumentation {
1455
1591
  try {
1456
1592
  jsonConfiguration = JSON.stringify(configuration);
1457
1593
  }
1458
- catch (error) {
1594
+ catch (_error) {
1459
1595
  jsonConfiguration = '{}';
1460
1596
  }
1461
1597
  const attrConfiguration = this.attribifyConfiguration('input', configuration);
@@ -1464,21 +1600,21 @@ class ManualInstrumentation {
1464
1600
  try {
1465
1601
  jsonInput = JSON.stringify(input);
1466
1602
  }
1467
- catch (error) {
1603
+ catch (_error) {
1468
1604
  jsonInput = '[]';
1469
1605
  }
1470
1606
  const attrInput = this.attribifyMessages('input', input);
1471
1607
  const span = this.span(ctx, start.name || `${start.provider} / ${start.model}`, SpanType.Completion, {
1472
1608
  attributes: {
1473
- [incubating.ATTR_GEN_AI_SYSTEM]: start.provider,
1474
- [ATTR_GEN_AI_REQUEST_CONFIGURATION]: jsonConfiguration,
1609
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI._deprecated.system]: start.provider,
1610
+ [ATTRIBUTES.LATITUDE.request.configuration]: jsonConfiguration,
1475
1611
  ...attrConfiguration,
1476
- [ATTR_GEN_AI_REQUEST_MESSAGES]: jsonInput,
1612
+ [ATTRIBUTES.LATITUDE.request.messages]: jsonInput,
1477
1613
  ...attrInput,
1478
1614
  ...(start.attributes || {}),
1479
- [ATTR_LATITUDE_COMMIT_UUID]: start.versionUuid,
1480
- [ATTR_LATITUDE_DOCUMENT_UUID]: start.promptUuid,
1481
- [ATTR_LATITUDE_EXPERIMENT_UUID]: start.experimentUuid,
1615
+ [ATTRIBUTES.LATITUDE.commitUuid]: start.versionUuid,
1616
+ [ATTRIBUTES.LATITUDE.documentUuid]: start.promptUuid,
1617
+ [ATTRIBUTES.LATITUDE.experimentUuid]: start.experimentUuid,
1482
1618
  },
1483
1619
  });
1484
1620
  return {
@@ -1490,7 +1626,7 @@ class ManualInstrumentation {
1490
1626
  try {
1491
1627
  jsonOutput = JSON.stringify(output);
1492
1628
  }
1493
- catch (error) {
1629
+ catch (_error) {
1494
1630
  jsonOutput = '[]';
1495
1631
  }
1496
1632
  const attrOutput = this.attribifyMessages('output', output);
@@ -1505,16 +1641,18 @@ class ManualInstrumentation {
1505
1641
  const finishReason = end.finishReason ?? '';
1506
1642
  span.end({
1507
1643
  attributes: {
1508
- [ATTR_GEN_AI_RESPONSE_MESSAGES]: jsonOutput,
1644
+ [ATTRIBUTES.LATITUDE.response.messages]: jsonOutput,
1509
1645
  ...attrOutput,
1510
- [incubating.ATTR_GEN_AI_USAGE_INPUT_TOKENS]: inputTokens,
1511
- [ATTR_GEN_AI_USAGE_PROMPT_TOKENS]: tokens.prompt,
1512
- [ATTR_GEN_AI_USAGE_CACHED_TOKENS]: tokens.cached,
1513
- [ATTR_GEN_AI_USAGE_REASONING_TOKENS]: tokens.reasoning,
1514
- [ATTR_GEN_AI_USAGE_COMPLETION_TOKENS]: tokens.completion,
1515
- [incubating.ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: outputTokens,
1516
- [incubating.ATTR_GEN_AI_RESPONSE_MODEL]: start.model,
1517
- [incubating.ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [finishReason],
1646
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI.usage.inputTokens]: inputTokens,
1647
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI.usage.outputTokens]: outputTokens,
1648
+ [ATTRIBUTES.LATITUDE.usage.promptTokens]: tokens.prompt,
1649
+ [ATTRIBUTES.LATITUDE.usage.cachedTokens]: tokens.cached,
1650
+ [ATTRIBUTES.LATITUDE.usage.reasoningTokens]: tokens.reasoning,
1651
+ [ATTRIBUTES.LATITUDE.usage.completionTokens]: tokens.completion,
1652
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI.response.model]: start.model,
1653
+ [ATTRIBUTES.OPENTELEMETRY.GEN_AI.response.finishReasons]: [
1654
+ finishReason,
1655
+ ],
1518
1656
  ...(end.attributes || {}),
1519
1657
  },
1520
1658
  });
@@ -1525,16 +1663,10 @@ class ManualInstrumentation {
1525
1663
  embedding(ctx, options) {
1526
1664
  return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Embedding].name, SpanType.Embedding, options);
1527
1665
  }
1528
- retrieval(ctx, options) {
1529
- return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Retrieval].name, SpanType.Retrieval, options);
1530
- }
1531
- reranking(ctx, options) {
1532
- return this.span(ctx, options?.name || SPAN_SPECIFICATIONS[SpanType.Reranking].name, SpanType.Reranking, options);
1533
- }
1534
1666
  attribifyHeaders(direction, headers) {
1535
1667
  const prefix = direction === 'request'
1536
- ? ATTR_HTTP_REQUEST_HEADER
1537
- : ATTR_HTTP_RESPONSE_HEADER;
1668
+ ? ATTRIBUTES.OPENTELEMETRY.HTTP.request.header
1669
+ : ATTRIBUTES.OPENTELEMETRY.HTTP.response.header;
1538
1670
  const attributes = {};
1539
1671
  for (const key in headers) {
1540
1672
  const field = this.toKebabCase(key);
@@ -1558,16 +1690,16 @@ class ManualInstrumentation {
1558
1690
  try {
1559
1691
  finalBody = JSON.stringify(start.request.body);
1560
1692
  }
1561
- catch (error) {
1693
+ catch (_error) {
1562
1694
  finalBody = '{}';
1563
1695
  }
1564
1696
  }
1565
1697
  const span = this.span(ctx, start.name || `${method} ${start.request.url}`, SpanType.Http, {
1566
1698
  attributes: {
1567
- [semanticConventions.ATTR_HTTP_REQUEST_METHOD]: method,
1568
- [ATTR_HTTP_REQUEST_URL]: start.request.url,
1699
+ [ATTRIBUTES.OPENTELEMETRY.HTTP.request.method]: method,
1700
+ [ATTRIBUTES.OPENTELEMETRY.HTTP.request.url]: start.request.url,
1569
1701
  ...attrHeaders,
1570
- [ATTR_HTTP_REQUEST_BODY]: finalBody,
1702
+ [ATTRIBUTES.OPENTELEMETRY.HTTP.request.body]: finalBody,
1571
1703
  ...(start.attributes || {}),
1572
1704
  },
1573
1705
  });
@@ -1585,15 +1717,15 @@ class ManualInstrumentation {
1585
1717
  try {
1586
1718
  finalBody = JSON.stringify(end.response.body);
1587
1719
  }
1588
- catch (error) {
1720
+ catch (_error) {
1589
1721
  finalBody = '{}';
1590
1722
  }
1591
1723
  }
1592
1724
  span.end({
1593
1725
  attributes: {
1594
- [semanticConventions.ATTR_HTTP_RESPONSE_STATUS_CODE]: end.response.status,
1726
+ [ATTRIBUTES.OPENTELEMETRY.HTTP.response.statusCode]: end.response.status,
1595
1727
  ...attrHeaders,
1596
- [ATTR_HTTP_RESPONSE_BODY]: finalBody,
1728
+ [ATTRIBUTES.OPENTELEMETRY.HTTP.response.body]: finalBody,
1597
1729
  ...(end.attributes || {}),
1598
1730
  },
1599
1731
  });
@@ -1606,49 +1738,48 @@ class ManualInstrumentation {
1606
1738
  try {
1607
1739
  jsonParameters = JSON.stringify(parameters || {});
1608
1740
  }
1609
- catch (error) {
1741
+ catch (_error) {
1610
1742
  jsonParameters = '{}';
1611
1743
  }
1612
1744
  const attributes = {
1613
- [ATTR_GEN_AI_REQUEST_TEMPLATE]: template,
1614
- [ATTR_GEN_AI_REQUEST_PARAMETERS]: jsonParameters,
1615
- [ATTR_LATITUDE_COMMIT_UUID]: versionUuid || HEAD_COMMIT,
1616
- [ATTR_LATITUDE_DOCUMENT_UUID]: promptUuid,
1617
- [ATTR_LATITUDE_PROJECT_ID]: projectId,
1618
- [ATTR_LATITUDE_DOCUMENT_LOG_UUID]: documentLogUuid,
1745
+ [ATTRIBUTES.LATITUDE.request.template]: template,
1746
+ [ATTRIBUTES.LATITUDE.request.parameters]: jsonParameters,
1747
+ [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid || HEAD_COMMIT,
1748
+ [ATTRIBUTES.LATITUDE.documentUuid]: promptUuid,
1749
+ [ATTRIBUTES.LATITUDE.projectId]: projectId,
1750
+ [ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
1619
1751
  ...(experimentUuid && {
1620
- [ATTR_LATITUDE_EXPERIMENT_UUID]: experimentUuid,
1752
+ [ATTRIBUTES.LATITUDE.experimentUuid]: experimentUuid,
1621
1753
  }),
1622
1754
  ...(testDeploymentId && {
1623
- [ATTR_LATITUDE_TEST_DEPLOYMENT_ID]: testDeploymentId,
1755
+ [ATTRIBUTES.LATITUDE.testDeploymentId]: testDeploymentId,
1624
1756
  }),
1625
- ...(externalId && { [ATTR_LATITUDE_EXTERNAL_ID]: externalId }),
1626
- ...(source && { [ATTR_LATITUDE_SOURCE]: source }),
1757
+ ...(externalId && { [ATTRIBUTES.LATITUDE.externalId]: externalId }),
1758
+ ...(source && { [ATTRIBUTES.LATITUDE.source]: source }),
1627
1759
  ...(rest.attributes || {}),
1628
1760
  };
1629
1761
  return this.span(ctx, name || `prompt-${promptUuid}`, SpanType.Prompt, {
1630
1762
  attributes,
1631
1763
  });
1632
1764
  }
1633
- step(ctx, options) {
1634
- return this.span(ctx, 'step', SpanType.Step, options);
1635
- }
1636
- chat(ctx, { documentLogUuid, previousTraceId, source, name, ...rest }) {
1765
+ chat(ctx, { documentLogUuid, previousTraceId, source, name, versionUuid, promptUuid, ...rest }) {
1637
1766
  const attributes = {
1638
- [ATTR_LATITUDE_DOCUMENT_LOG_UUID]: documentLogUuid,
1639
- [ATTR_LATITUDE_PREVIOUS_TRACE_ID]: previousTraceId,
1640
- ...(source && { [ATTR_LATITUDE_SOURCE]: source }),
1767
+ [ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
1768
+ [ATTRIBUTES.LATITUDE.previousTraceId]: previousTraceId,
1769
+ ...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
1770
+ ...(promptUuid && { [ATTRIBUTES.LATITUDE.documentUuid]: promptUuid }),
1771
+ ...(source && { [ATTRIBUTES.LATITUDE.source]: source }),
1641
1772
  ...(rest.attributes || {}),
1642
1773
  };
1643
1774
  return this.span(ctx, name || 'chat', SpanType.Chat, { attributes });
1644
1775
  }
1645
1776
  external(ctx, { promptUuid, documentLogUuid, source, versionUuid, externalId, name, ...rest }) {
1646
1777
  const attributes = {
1647
- [ATTR_LATITUDE_DOCUMENT_UUID]: promptUuid,
1648
- [ATTR_LATITUDE_DOCUMENT_LOG_UUID]: documentLogUuid,
1649
- [ATTR_LATITUDE_SOURCE]: source ?? LogSources.API,
1650
- ...(versionUuid && { [ATTR_LATITUDE_COMMIT_UUID]: versionUuid }),
1651
- ...(externalId && { [ATTR_LATITUDE_EXTERNAL_ID]: externalId }),
1778
+ [ATTRIBUTES.LATITUDE.documentUuid]: promptUuid,
1779
+ [ATTRIBUTES.LATITUDE.documentLogUuid]: documentLogUuid,
1780
+ [ATTRIBUTES.LATITUDE.source]: source ?? LogSources.API,
1781
+ ...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
1782
+ ...(externalId && { [ATTRIBUTES.LATITUDE.externalId]: externalId }),
1652
1783
  ...(rest.attributes || {}),
1653
1784
  };
1654
1785
  return this.span(ctx, name || `external-${promptUuid}`, SpanType.External, {
@@ -1657,11 +1788,11 @@ class ManualInstrumentation {
1657
1788
  }
1658
1789
  unresolvedExternal(ctx, { path, projectId, versionUuid, conversationUuid, name, ...rest }) {
1659
1790
  const attributes = {
1660
- [ATTR_LATITUDE_PROMPT_PATH]: path,
1661
- [ATTR_LATITUDE_PROJECT_ID]: projectId,
1662
- ...(versionUuid && { [ATTR_LATITUDE_COMMIT_UUID]: versionUuid }),
1791
+ [ATTRIBUTES.LATITUDE.promptPath]: path,
1792
+ [ATTRIBUTES.LATITUDE.projectId]: projectId,
1793
+ ...(versionUuid && { [ATTRIBUTES.LATITUDE.commitUuid]: versionUuid }),
1663
1794
  ...(conversationUuid && {
1664
- [ATTR_LATITUDE_DOCUMENT_LOG_UUID]: conversationUuid,
1795
+ [ATTRIBUTES.LATITUDE.documentLogUuid]: conversationUuid,
1665
1796
  }),
1666
1797
  ...(rest.attributes || {}),
1667
1798
  };
@@ -1726,19 +1857,6 @@ class LatitudeInstrumentation {
1726
1857
  $prompt.end();
1727
1858
  return result;
1728
1859
  }
1729
- async wrapRenderStep(fn, ...args) {
1730
- const $step = this.manualTelemetry.step(otel.context.active());
1731
- let result;
1732
- try {
1733
- result = await otel.context.with($step.context, async () => await fn(...args));
1734
- }
1735
- catch (error) {
1736
- $step.fail(error);
1737
- throw error;
1738
- }
1739
- $step.end();
1740
- return result;
1741
- }
1742
1860
  async wrapRenderCompletion(fn, ...args) {
1743
1861
  if (!this.options.completions) {
1744
1862
  return await fn(...args);
@@ -1772,8 +1890,8 @@ class LatitudeInstrumentation {
1772
1890
  completion: completionTokens,
1773
1891
  },
1774
1892
  finishReason: result.toolRequests.length > 0
1775
- ? GEN_AI_RESPONSE_FINISH_REASON_VALUE_TOOL_CALLS
1776
- : GEN_AI_RESPONSE_FINISH_REASON_VALUE_STOP,
1893
+ ? VALUES.OPENTELEMETRY.GEN_AI.response.finishReasons.toolCalls
1894
+ : VALUES.OPENTELEMETRY.GEN_AI.response.finishReasons.stop,
1777
1895
  });
1778
1896
  return result;
1779
1897
  }
@@ -1818,6 +1936,7 @@ var LatitudeErrorCodes;
1818
1936
  LatitudeErrorCodes["NotImplementedError"] = "NotImplementedError";
1819
1937
  LatitudeErrorCodes["PaymentRequiredError"] = "PaymentRequiredError";
1820
1938
  LatitudeErrorCodes["AbortedError"] = "AbortedError";
1939
+ LatitudeErrorCodes["BillingError"] = "BillingError";
1821
1940
  })(LatitudeErrorCodes || (LatitudeErrorCodes = {}));
1822
1941
  // NOTE: If you add a new error code, please add it to the pg enum in models/runErrors.ts
1823
1942
  var RunErrorCodes;
@@ -1897,21 +2016,12 @@ class SpanFactory {
1897
2016
  embedding(options, ctx) {
1898
2017
  return this.telemetry.embedding(ctx ?? otel.context.active(), options);
1899
2018
  }
1900
- retrieval(options, ctx) {
1901
- return this.telemetry.retrieval(ctx ?? otel.context.active(), options);
1902
- }
1903
- reranking(options, ctx) {
1904
- return this.telemetry.reranking(ctx ?? otel.context.active(), options);
1905
- }
1906
2019
  http(options, ctx) {
1907
2020
  return this.telemetry.http(ctx ?? otel.context.active(), options);
1908
2021
  }
1909
2022
  prompt(options, ctx) {
1910
2023
  return this.telemetry.prompt(ctx ?? otel.context.active(), options);
1911
2024
  }
1912
- step(options, ctx) {
1913
- return this.telemetry.step(ctx ?? otel.context.active(), options);
1914
- }
1915
2025
  chat(options, ctx) {
1916
2026
  return this.telemetry.chat(ctx ?? otel.context.active(), options);
1917
2027
  }
@@ -2092,8 +2202,9 @@ class LatitudeTelemetry {
2092
2202
  configureInstrumentation(exports.Instrumentation.Cohere, instrumentationCohere.CohereInstrumentation); // prettier-ignore
2093
2203
  configureInstrumentation(exports.Instrumentation.Langchain, instrumentationLangchain.LangChainInstrumentation); // prettier-ignore
2094
2204
  configureInstrumentation(exports.Instrumentation.LlamaIndex, instrumentationLlamaindex.LlamaIndexInstrumentation); // prettier-ignore
2095
- configureInstrumentation(exports.Instrumentation.OpenAI, instrumentationOpenai.OpenAIInstrumentation, { enrichTokens: true }); // prettier-ignore
2096
- configureInstrumentation(exports.Instrumentation.TogetherAI, instrumentationTogether.TogetherInstrumentation, { enrichTokens: true }); // prettier-ignore
2205
+ // NOTE: `stream: true` in OpenAI make enrichTokens fail, so disabling.
2206
+ configureInstrumentation(exports.Instrumentation.OpenAI, instrumentationOpenai.OpenAIInstrumentation, { enrichTokens: false }); // prettier-ignore
2207
+ configureInstrumentation(exports.Instrumentation.TogetherAI, instrumentationTogether.TogetherInstrumentation, { enrichTokens: false }); // prettier-ignore
2097
2208
  configureInstrumentation(exports.Instrumentation.VertexAI, instrumentationVertexai.VertexAIInstrumentation); // prettier-ignore
2098
2209
  }
2099
2210
  async capture(options, fn) {