@latitude-data/telemetry 1.0.3 → 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.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
2
  import * as otel from '@opentelemetry/api';
3
- import { propagation, trace, context } from '@opentelemetry/api';
3
+ import { trace, propagation, context } from '@opentelemetry/api';
4
4
  import { ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
5
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';
@@ -12,14 +12,13 @@ import { registerInstrumentations } from '@opentelemetry/instrumentation';
12
12
  import { Resource } from '@opentelemetry/resources';
13
13
  import { NodeTracerProvider, SimpleSpanProcessor, BatchSpanProcessor } from '@opentelemetry/sdk-trace-node';
14
14
  import { AnthropicInstrumentation } from '@traceloop/instrumentation-anthropic';
15
- import { AzureOpenAIInstrumentation } from '@traceloop/instrumentation-azure';
16
15
  import { BedrockInstrumentation } from '@traceloop/instrumentation-bedrock';
17
16
  import { CohereInstrumentation } from '@traceloop/instrumentation-cohere';
18
17
  import { LangChainInstrumentation } from '@traceloop/instrumentation-langchain';
19
18
  import { LlamaIndexInstrumentation } from '@traceloop/instrumentation-llamaindex';
20
19
  import { OpenAIInstrumentation } from '@traceloop/instrumentation-openai';
21
20
  import { TogetherInstrumentation } from '@traceloop/instrumentation-together';
22
- import { VertexAIInstrumentation, AIPlatformInstrumentation } from '@traceloop/instrumentation-vertexai';
21
+ import { AIPlatformInstrumentation, VertexAIInstrumentation } from '@traceloop/instrumentation-vertexai';
23
22
 
24
23
  class RedactSpanProcessor {
25
24
  options;
@@ -76,6 +75,7 @@ const DEFAULT_REDACT_SPAN_PROCESSOR = () => new RedactSpanProcessor({
76
75
  attributes: [
77
76
  /^.*auth.*$/i,
78
77
  /^.*authorization.*$/i,
78
+ /^(?!gen_ai\.).*usage.*$/i,
79
79
  /^(?!gen_ai\.).*token.*$/i,
80
80
  /^.*secret.*$/i,
81
81
  /^.*key.*$/i,
@@ -118,289 +118,6 @@ function GET_GATEWAY_BASE_URL() {
118
118
  }
119
119
  const env = { GATEWAY_BASE_URL: GET_GATEWAY_BASE_URL() };
120
120
 
121
- var SegmentSource;
122
- (function (SegmentSource) {
123
- SegmentSource["API"] = "api";
124
- SegmentSource["AgentAsTool"] = "agent_as_tool";
125
- SegmentSource["Copilot"] = "copilot";
126
- SegmentSource["EmailTrigger"] = "email_trigger";
127
- SegmentSource["Evaluation"] = "evaluation";
128
- SegmentSource["Experiment"] = "experiment";
129
- SegmentSource["Playground"] = "playground";
130
- SegmentSource["ScheduledTrigger"] = "scheduled_trigger";
131
- SegmentSource["IntegrationTrigger"] = "integration_trigger";
132
- SegmentSource["SharedPrompt"] = "shared_prompt";
133
- SegmentSource["User"] = "user";
134
- })(SegmentSource || (SegmentSource = {}));
135
- var SegmentType;
136
- (function (SegmentType) {
137
- SegmentType["Document"] = "document";
138
- SegmentType["Step"] = "step";
139
- })(SegmentType || (SegmentType = {}));
140
- const SEGMENT_SPECIFICATIONS = {
141
- [SegmentType.Document]: {
142
- name: 'Prompt',
143
- description: 'A prompt',
144
- },
145
- [SegmentType.Step]: {
146
- name: 'Step',
147
- description: 'A step in a prompt',
148
- },
149
- };
150
- const baseSegmentBaggageSchema = z.object({
151
- id: z.string(),
152
- parentId: z.string().optional(),
153
- source: z.nativeEnum(SegmentSource),
154
- });
155
- z.discriminatedUnion('type', [
156
- baseSegmentBaggageSchema.extend({
157
- type: z.literal(SegmentType.Document),
158
- data: z.object({
159
- logUuid: z.string().optional(), // TODO(tracing): temporal related log, remove when observability is ready
160
- commitUuid: z.string(),
161
- documentUuid: z.string(),
162
- experimentUuid: z.string().optional(),
163
- externalId: z.string().optional(),
164
- }),
165
- }),
166
- baseSegmentBaggageSchema.extend({
167
- type: z.literal(SegmentType.Step),
168
- data: z.undefined().optional(),
169
- }),
170
- ]);
171
-
172
- var SpanKind;
173
- (function (SpanKind) {
174
- SpanKind["Internal"] = "internal";
175
- SpanKind["Server"] = "server";
176
- SpanKind["Client"] = "client";
177
- SpanKind["Producer"] = "producer";
178
- SpanKind["Consumer"] = "consumer";
179
- })(SpanKind || (SpanKind = {}));
180
- // Note: loosely based on OpenTelemetry GenAI semantic conventions
181
- var SpanType;
182
- (function (SpanType) {
183
- SpanType["Tool"] = "tool";
184
- SpanType["Completion"] = "completion";
185
- SpanType["Embedding"] = "embedding";
186
- SpanType["Retrieval"] = "retrieval";
187
- SpanType["Reranking"] = "reranking";
188
- SpanType["Http"] = "http";
189
- SpanType["Segment"] = "segment";
190
- SpanType["Unknown"] = "unknown";
191
- })(SpanType || (SpanType = {}));
192
- const SPAN_SPECIFICATIONS = {
193
- [SpanType.Tool]: {
194
- name: 'Tool',
195
- description: 'A tool call',
196
- isGenAI: true,
197
- isHidden: false,
198
- },
199
- [SpanType.Completion]: {
200
- name: 'Completion',
201
- description: 'A completion call',
202
- isGenAI: true,
203
- isHidden: false,
204
- },
205
- [SpanType.Embedding]: {
206
- name: 'Embedding',
207
- description: 'An embedding call',
208
- isGenAI: true,
209
- isHidden: false,
210
- },
211
- [SpanType.Retrieval]: {
212
- name: 'Retrieval',
213
- description: 'A retrieval call',
214
- isGenAI: true,
215
- isHidden: false,
216
- },
217
- [SpanType.Reranking]: {
218
- name: 'Reranking',
219
- description: 'A reranking call',
220
- isGenAI: true,
221
- isHidden: false,
222
- },
223
- [SpanType.Http]: {
224
- name: 'HTTP',
225
- description: 'An HTTP request',
226
- isGenAI: false,
227
- isHidden: true,
228
- },
229
- [SpanType.Segment]: {
230
- name: 'Segment',
231
- description: 'A (partial) segment of a trace',
232
- isGenAI: false,
233
- isHidden: false,
234
- },
235
- [SpanType.Unknown]: {
236
- name: 'Unknown',
237
- description: 'An unknown span',
238
- isGenAI: false,
239
- isHidden: true,
240
- },
241
- };
242
- var SpanStatus;
243
- (function (SpanStatus) {
244
- SpanStatus["Unset"] = "unset";
245
- SpanStatus["Ok"] = "ok";
246
- SpanStatus["Error"] = "error";
247
- })(SpanStatus || (SpanStatus = {}));
248
-
249
- // Note: Traces are unmaterialized but this context is used to propagate the trace
250
- // See www.w3.org/TR/trace-context and w3c.github.io/baggage
251
- z.object({
252
- traceparent: z.string(), // <version>-<trace-id>-<span-id>-<trace-flags>
253
- tracestate: z.string().optional(), // <key>=urlencoded(<value>)[,<key>=urlencoded(<value>)]*
254
- baggage: z.string().optional(), // <key>=urlencoded(<value>)[,<key>=urlencoded(<value>)]*
255
- });
256
-
257
- /* Note: Instrumentation scopes from all language SDKs */
258
- const SCOPE_LATITUDE = 'so.latitude.instrumentation';
259
- var InstrumentationScope;
260
- (function (InstrumentationScope) {
261
- InstrumentationScope["Manual"] = "manual";
262
- InstrumentationScope["Latitude"] = "latitude";
263
- InstrumentationScope["OpenAI"] = "openai";
264
- InstrumentationScope["Anthropic"] = "anthropic";
265
- InstrumentationScope["AzureOpenAI"] = "azure";
266
- InstrumentationScope["VercelAI"] = "vercelai";
267
- InstrumentationScope["VertexAI"] = "vertexai";
268
- InstrumentationScope["AIPlatform"] = "aiplatform";
269
- InstrumentationScope["MistralAI"] = "mistralai";
270
- InstrumentationScope["Bedrock"] = "bedrock";
271
- InstrumentationScope["Sagemaker"] = "sagemaker";
272
- InstrumentationScope["TogetherAI"] = "togetherai";
273
- InstrumentationScope["Replicate"] = "replicate";
274
- InstrumentationScope["Groq"] = "groq";
275
- InstrumentationScope["Cohere"] = "cohere";
276
- InstrumentationScope["LiteLLM"] = "litellm";
277
- InstrumentationScope["Langchain"] = "langchain";
278
- InstrumentationScope["LlamaIndex"] = "llamaindex";
279
- InstrumentationScope["DSPy"] = "dspy";
280
- InstrumentationScope["Haystack"] = "haystack";
281
- InstrumentationScope["Ollama"] = "ollama";
282
- InstrumentationScope["Transformers"] = "transformers";
283
- InstrumentationScope["AlephAlpha"] = "alephalpha";
284
- })(InstrumentationScope || (InstrumentationScope = {}));
285
- /* Note: non-standard OpenTelemetry semantic conventions used in Latitude */
286
- const ATTR_LATITUDE = 'latitude';
287
- const ATTR_LATITUDE_TYPE = `${ATTR_LATITUDE}.type`;
288
- const ATTR_LATITUDE_SEGMENT_ID = `${ATTR_LATITUDE}.segment.id`;
289
- const ATTR_LATITUDE_SEGMENT_PARENT_ID = `${ATTR_LATITUDE}.segment.parent_id`;
290
- const ATTR_LATITUDE_SEGMENTS = `${ATTR_LATITUDE}.segments`;
291
- const GEN_AI_TOOL_TYPE_VALUE_FUNCTION = 'function';
292
- const ATTR_GEN_AI_TOOL_CALL_ARGUMENTS = 'gen_ai.tool.call.arguments';
293
- const ATTR_GEN_AI_TOOL_RESULT_VALUE = 'gen_ai.tool.result.value';
294
- const ATTR_GEN_AI_TOOL_RESULT_IS_ERROR = 'gen_ai.tool.result.is_error';
295
- const ATTR_GEN_AI_REQUEST = 'gen_ai.request';
296
- const ATTR_GEN_AI_REQUEST_CONFIGURATION = 'gen_ai.request.configuration';
297
- const ATTR_GEN_AI_REQUEST_TEMPLATE = 'gen_ai.request.template';
298
- const ATTR_GEN_AI_REQUEST_PARAMETERS = 'gen_ai.request.parameters';
299
- const ATTR_GEN_AI_REQUEST_MESSAGES = 'gen_ai.request.messages';
300
- const ATTR_GEN_AI_RESPONSE = 'gen_ai.response';
301
- const ATTR_GEN_AI_RESPONSE_MESSAGES = 'gen_ai.response.messages';
302
- const ATTR_GEN_AI_USAGE_PROMPT_TOKENS = 'gen_ai.usage.prompt_tokens';
303
- const ATTR_GEN_AI_USAGE_CACHED_TOKENS = 'gen_ai.usage.cached_tokens';
304
- const ATTR_GEN_AI_USAGE_REASONING_TOKENS = 'gen_ai.usage.reasoning_tokens'; // prettier-ignore
305
- const ATTR_GEN_AI_USAGE_COMPLETION_TOKENS = 'gen_ai.usage.completion_tokens'; // prettier-ignore
306
- const ATTR_GEN_AI_PROMPTS = 'gen_ai.prompt'; // gen_ai.prompt.{index}.{role/content/...}
307
- const ATTR_GEN_AI_COMPLETIONS = 'gen_ai.completion'; // gen_ai.completion.{index}.{role/content/...}
308
- const ATTR_GEN_AI_MESSAGE_ROLE = 'role';
309
- const ATTR_GEN_AI_MESSAGE_CONTENT = 'content'; // string or object
310
- const ATTR_GEN_AI_MESSAGE_TOOL_NAME = 'tool_name';
311
- const ATTR_GEN_AI_MESSAGE_TOOL_CALL_ID = 'tool_call_id';
312
- const ATTR_GEN_AI_MESSAGE_TOOL_RESULT_IS_ERROR = 'is_error';
313
- const ATTR_GEN_AI_MESSAGE_TOOL_CALLS = 'tool_calls'; // gen_ai.completion.{index}.tool_calls.{index}.{id/name/arguments}
314
- const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ID = 'id';
315
- const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_NAME = 'name';
316
- const ATTR_GEN_AI_MESSAGE_TOOL_CALLS_ARGUMENTS = 'arguments';
317
- const GEN_AI_RESPONSE_FINISH_REASON_VALUE_STOP = 'stop';
318
- const GEN_AI_RESPONSE_FINISH_REASON_VALUE_TOOL_CALLS = 'tool_calls';
319
- const ATTR_HTTP_REQUEST_URL = 'http.request.url';
320
- const ATTR_HTTP_REQUEST_BODY = 'http.request.body';
321
- const ATTR_HTTP_REQUEST_HEADER = 'http.request.header';
322
- const ATTR_HTTP_RESPONSE_BODY = 'http.response.body';
323
- const ATTR_HTTP_RESPONSE_HEADER = 'http.response.header';
324
- /* Note: Schemas for span ingestion following OpenTelemetry service request specification */
325
- var Otlp;
326
- (function (Otlp) {
327
- Otlp.attributeValueSchema = z.object({
328
- stringValue: z.string().optional(),
329
- intValue: z.number().optional(),
330
- boolValue: z.boolean().optional(),
331
- arrayValue: z
332
- .object({
333
- values: z.array(z.object({
334
- stringValue: z.string().optional(),
335
- intValue: z.number().optional(),
336
- boolValue: z.boolean().optional(),
337
- })),
338
- })
339
- .optional(),
340
- });
341
- Otlp.attributeSchema = z.object({
342
- key: z.string(),
343
- value: Otlp.attributeValueSchema,
344
- });
345
- Otlp.eventSchema = z.object({
346
- name: z.string(),
347
- timeUnixNano: z.string(),
348
- attributes: z.array(Otlp.attributeSchema).optional(),
349
- });
350
- Otlp.linkSchema = z.object({
351
- traceId: z.string(),
352
- spanId: z.string(),
353
- attributes: z.array(Otlp.attributeSchema).optional(),
354
- });
355
- (function (StatusCode) {
356
- StatusCode[StatusCode["Unset"] = 0] = "Unset";
357
- StatusCode[StatusCode["Ok"] = 1] = "Ok";
358
- StatusCode[StatusCode["Error"] = 2] = "Error";
359
- })(Otlp.StatusCode || (Otlp.StatusCode = {}));
360
- Otlp.statusSchema = z.object({
361
- code: z.number(),
362
- message: z.string().optional(),
363
- });
364
- (function (SpanKind) {
365
- SpanKind[SpanKind["Internal"] = 0] = "Internal";
366
- SpanKind[SpanKind["Server"] = 1] = "Server";
367
- SpanKind[SpanKind["Client"] = 2] = "Client";
368
- SpanKind[SpanKind["Producer"] = 3] = "Producer";
369
- SpanKind[SpanKind["Consumer"] = 4] = "Consumer";
370
- })(Otlp.SpanKind || (Otlp.SpanKind = {}));
371
- Otlp.spanSchema = z.object({
372
- traceId: z.string(),
373
- spanId: z.string(),
374
- parentSpanId: z.string().optional(),
375
- name: z.string(),
376
- kind: z.number(),
377
- startTimeUnixNano: z.string(),
378
- endTimeUnixNano: z.string(),
379
- status: Otlp.statusSchema.optional(),
380
- events: z.array(Otlp.eventSchema).optional(),
381
- links: z.array(Otlp.linkSchema).optional(),
382
- attributes: z.array(Otlp.attributeSchema).optional(),
383
- });
384
- Otlp.scopeSchema = z.object({
385
- name: z.string(),
386
- version: z.string().optional(),
387
- });
388
- Otlp.scopeSpanSchema = z.object({
389
- scope: Otlp.scopeSchema,
390
- spans: z.array(Otlp.spanSchema),
391
- });
392
- Otlp.resourceSchema = z.object({
393
- attributes: z.array(Otlp.attributeSchema),
394
- });
395
- Otlp.resourceSpanSchema = z.object({
396
- resource: Otlp.resourceSchema,
397
- scopeSpans: z.array(Otlp.scopeSpanSchema),
398
- });
399
- Otlp.serviceRequestSchema = z.object({
400
- resourceSpans: z.array(Otlp.resourceSpanSchema),
401
- });
402
- })(Otlp || (Otlp = {}));
403
-
404
121
  var StreamEventTypes;
405
122
  (function (StreamEventTypes) {
406
123
  StreamEventTypes["Latitude"] = "latitude-event";
@@ -425,17 +142,27 @@ var LatitudeTool;
425
142
  LatitudeTool["RunCode"] = "code";
426
143
  LatitudeTool["WebSearch"] = "search";
427
144
  LatitudeTool["WebExtract"] = "extract";
145
+ LatitudeTool["Think"] = "think";
146
+ LatitudeTool["TODO"] = "todo";
428
147
  })(LatitudeTool || (LatitudeTool = {}));
429
148
  var LatitudeToolInternalName;
430
149
  (function (LatitudeToolInternalName) {
431
150
  LatitudeToolInternalName["RunCode"] = "lat_tool_run_code";
432
151
  LatitudeToolInternalName["WebSearch"] = "lat_tool_web_search";
433
152
  LatitudeToolInternalName["WebExtract"] = "lat_tool_web_extract";
153
+ LatitudeToolInternalName["Think"] = "think";
154
+ LatitudeToolInternalName["TODO"] = "todo_write";
434
155
  })(LatitudeToolInternalName || (LatitudeToolInternalName = {}));
156
+ [
157
+ LatitudeTool.Think,
158
+ LatitudeTool.TODO,
159
+ ];
435
160
 
436
161
  const actualOutputConfiguration = z.object({
437
162
  messageSelection: z.enum(['last', 'all']), // Which assistant messages to select
438
- contentFilter: z.enum(['text', 'image', 'file', 'tool_call']).optional(),
163
+ contentFilter: z
164
+ .enum(['text', 'reasoning', 'image', 'file', 'tool_call'])
165
+ .optional(),
439
166
  parsingFormat: z.enum(['string', 'json']),
440
167
  fieldAccessor: z.string().optional(), // Field accessor to get the output from if it's a key-value format
441
168
  });
@@ -445,11 +172,11 @@ const expectedOutputConfiguration = z.object({
445
172
  });
446
173
  const baseEvaluationConfiguration = z.object({
447
174
  reverseScale: z.boolean(), // If true, lower is better, otherwise, higher is better
448
- actualOutput: actualOutputConfiguration.optional(), // Optional for backwards compatibility
449
- expectedOutput: expectedOutputConfiguration.optional(), // Optional for backwards compatibility
175
+ actualOutput: actualOutputConfiguration,
176
+ expectedOutput: expectedOutputConfiguration.optional(),
450
177
  });
451
178
  const baseEvaluationResultMetadata = z.object({
452
- // Configuration snapshot is defined in every metric specification
179
+ // configuration: Configuration snapshot is defined in every metric specification
453
180
  actualOutput: z.string(),
454
181
  expectedOutput: z.string().optional(),
455
182
  datasetLabel: z.string().optional(),
@@ -458,7 +185,79 @@ const baseEvaluationResultError = z.object({
458
185
  message: z.string(),
459
186
  });
460
187
 
188
+ const compositeEvaluationConfiguration = baseEvaluationConfiguration.extend({
189
+ evaluationUuids: z.array(z.string()),
190
+ minThreshold: z.number().optional(), // Threshold percentage
191
+ maxThreshold: z.number().optional(), // Threshold percentage
192
+ defaultTarget: z.boolean().optional(), // Default for optimizations and distillations
193
+ });
194
+ const compositeEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
195
+ results: z.record(z.string(), // Evaluation uuid
196
+ z.object({
197
+ uuid: z.string(), // Result uuid (for side effects)
198
+ name: z.string(), // Evaluation name
199
+ score: z.number(), // Normalized score
200
+ reason: z.string(),
201
+ passed: z.boolean(),
202
+ })),
203
+ });
204
+ const compositeEvaluationResultError = baseEvaluationResultError.extend({
205
+ errors: z
206
+ .record(z.string(), // Evaluation uuid
207
+ z.object({
208
+ uuid: z.string(), // Result uuid (for side effects)
209
+ name: z.string(), // Evaluation name
210
+ message: z.string(),
211
+ }))
212
+ .optional(),
213
+ });
214
+ // AVERAGE
215
+ const compositeEvaluationAverageConfiguration = compositeEvaluationConfiguration.extend({});
216
+ compositeEvaluationResultMetadata.extend({
217
+ configuration: compositeEvaluationAverageConfiguration,
218
+ });
219
+ compositeEvaluationResultError.extend({});
220
+ const CompositeEvaluationAverageSpecification = {
221
+ };
222
+ // WEIGHTED
223
+ const compositeEvaluationWeightedConfiguration = compositeEvaluationConfiguration.extend({
224
+ weights: z.record(z.string(), // Evaluation uuid
225
+ z.number()),
226
+ });
227
+ compositeEvaluationResultMetadata.extend({
228
+ configuration: compositeEvaluationWeightedConfiguration,
229
+ });
230
+ compositeEvaluationResultError.extend({});
231
+ const CompositeEvaluationWeightedSpecification = {
232
+ };
233
+ // CUSTOM
234
+ const compositeEvaluationCustomConfiguration = compositeEvaluationConfiguration.extend({
235
+ formula: z.string(),
236
+ });
237
+ compositeEvaluationResultMetadata.extend({
238
+ configuration: compositeEvaluationCustomConfiguration,
239
+ });
240
+ compositeEvaluationResultError.extend({});
241
+ const CompositeEvaluationCustomSpecification = {
242
+ };
243
+ /* ------------------------------------------------------------------------- */
244
+ var CompositeEvaluationMetric;
245
+ (function (CompositeEvaluationMetric) {
246
+ CompositeEvaluationMetric["Average"] = "average";
247
+ CompositeEvaluationMetric["Weighted"] = "weighted";
248
+ CompositeEvaluationMetric["Custom"] = "custom";
249
+ })(CompositeEvaluationMetric || (CompositeEvaluationMetric = {}));
250
+ const CompositeEvaluationSpecification = {
251
+ // prettier-ignore
252
+ metrics: {
253
+ [CompositeEvaluationMetric.Average]: CompositeEvaluationAverageSpecification,
254
+ [CompositeEvaluationMetric.Weighted]: CompositeEvaluationWeightedSpecification,
255
+ [CompositeEvaluationMetric.Custom]: CompositeEvaluationCustomSpecification,
256
+ },
257
+ };
258
+
461
259
  const humanEvaluationConfiguration = baseEvaluationConfiguration.extend({
260
+ enableControls: z.boolean().optional(), // UI annotation controls
462
261
  criteria: z.string().optional(),
463
262
  });
464
263
  const humanEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
@@ -599,7 +398,9 @@ const LlmEvaluationSpecification = {
599
398
  };
600
399
 
601
400
  const ruleEvaluationConfiguration = baseEvaluationConfiguration.extend({});
602
- const ruleEvaluationResultMetadata = baseEvaluationResultMetadata.extend({});
401
+ const ruleEvaluationResultMetadata = baseEvaluationResultMetadata.extend({
402
+ reason: z.string().optional(),
403
+ });
603
404
  const ruleEvaluationResultError = baseEvaluationResultError.extend({});
604
405
  // EXACT MATCH
605
406
  const ruleEvaluationExactMatchConfiguration = ruleEvaluationConfiguration.extend({
@@ -709,12 +510,14 @@ var EvaluationType;
709
510
  EvaluationType["Rule"] = "rule";
710
511
  EvaluationType["Llm"] = "llm";
711
512
  EvaluationType["Human"] = "human";
513
+ EvaluationType["Composite"] = "composite";
712
514
  })(EvaluationType || (EvaluationType = {}));
713
- const EvaluationTypeSchema = z.nativeEnum(EvaluationType);
515
+ const EvaluationTypeSchema = z.enum(EvaluationType);
714
516
  const EvaluationMetricSchema = z.union([
715
- z.nativeEnum(RuleEvaluationMetric),
716
- z.nativeEnum(LlmEvaluationMetric),
717
- z.nativeEnum(HumanEvaluationMetric),
517
+ z.enum(RuleEvaluationMetric),
518
+ z.enum(LlmEvaluationMetric),
519
+ z.enum(HumanEvaluationMetric),
520
+ z.enum(CompositeEvaluationMetric),
718
521
  ]);
719
522
  const EvaluationConfigurationSchema = z.custom();
720
523
  // prettier-ignore
@@ -725,6 +528,7 @@ z.custom();
725
528
  [EvaluationType.Rule]: RuleEvaluationSpecification,
726
529
  [EvaluationType.Llm]: LlmEvaluationSpecification,
727
530
  [EvaluationType.Human]: HumanEvaluationSpecification,
531
+ [EvaluationType.Composite]: CompositeEvaluationSpecification,
728
532
  });
729
533
  z.object({
730
534
  name: z.string(),
@@ -738,7 +542,6 @@ z.object({
738
542
  enableSuggestions: z.boolean().nullable().optional(),
739
543
  autoApplySuggestions: z.boolean().nullable().optional(),
740
544
  });
741
- Object.values(SegmentSource).filter((source) => source !== SegmentSource.Evaluation && source !== SegmentSource.Experiment);
742
545
 
743
546
  var LegacyChainEventTypes;
744
547
  (function (LegacyChainEventTypes) {
@@ -759,17 +562,71 @@ var ChainEventTypes;
759
562
  ChainEventTypes["StepCompleted"] = "step-completed";
760
563
  ChainEventTypes["StepStarted"] = "step-started";
761
564
  ChainEventTypes["ToolCompleted"] = "tool-completed";
762
- ChainEventTypes["ToolsRequested"] = "tools-requested";
763
565
  ChainEventTypes["ToolResult"] = "tool-result";
764
566
  ChainEventTypes["ToolsStarted"] = "tools-started";
765
567
  })(ChainEventTypes || (ChainEventTypes = {}));
766
568
 
569
+ z.object({
570
+ name: z.string(),
571
+ provider: z.string(),
572
+ model: z.string(),
573
+ temperature: z.number(),
574
+ });
575
+ // Experiment ran from a dataset
576
+ const experimentDatasetSourceSchema = z.object({
577
+ source: z.literal('dataset'),
578
+ datasetId: z.number(),
579
+ fromRow: z.number(),
580
+ toRow: z.number(),
581
+ datasetLabels: z.record(z.string(), z.string()),
582
+ parametersMap: z.record(z.string(), z.number()),
583
+ });
584
+ // Experiment ran from last logs (from commit and creation time of experiment)
585
+ const experimentLogsSourceSchema = z.object({
586
+ source: z.literal('logs'),
587
+ count: z.number(),
588
+ });
589
+ // Experiment ran with manual parameters (currently only used for prompts with no parameters)
590
+ const experimentManualSourceSchema = z.object({
591
+ source: z.literal('manual'),
592
+ count: z.number(),
593
+ parametersMap: z.record(z.string(), z.number()),
594
+ });
595
+ z.discriminatedUnion('source', [
596
+ experimentDatasetSourceSchema,
597
+ experimentLogsSourceSchema,
598
+ experimentManualSourceSchema,
599
+ ]);
600
+
601
+ var QuotaType;
602
+ (function (QuotaType) {
603
+ QuotaType["Seats"] = "seats";
604
+ QuotaType["Runs"] = "runs";
605
+ QuotaType["Credits"] = "credits";
606
+ })(QuotaType || (QuotaType = {}));
607
+ var GrantSource;
608
+ (function (GrantSource) {
609
+ GrantSource["System"] = "system";
610
+ GrantSource["Subscription"] = "subscription";
611
+ GrantSource["Purchase"] = "purchase";
612
+ GrantSource["Reward"] = "reward";
613
+ GrantSource["Promocode"] = "promocode";
614
+ })(GrantSource || (GrantSource = {}));
615
+
616
+ var ModifiedDocumentType;
617
+ (function (ModifiedDocumentType) {
618
+ ModifiedDocumentType["Created"] = "created";
619
+ ModifiedDocumentType["Updated"] = "updated";
620
+ ModifiedDocumentType["UpdatedPath"] = "updated_path";
621
+ ModifiedDocumentType["Deleted"] = "deleted";
622
+ })(ModifiedDocumentType || (ModifiedDocumentType = {}));
623
+
767
624
  var IntegrationType;
768
625
  (function (IntegrationType) {
769
626
  IntegrationType["Latitude"] = "latitude";
770
627
  IntegrationType["ExternalMCP"] = "custom_mcp";
771
- IntegrationType["HostedMCP"] = "mcp_server";
772
628
  IntegrationType["Pipedream"] = "pipedream";
629
+ IntegrationType["HostedMCP"] = "mcp_server";
773
630
  })(IntegrationType || (IntegrationType = {}));
774
631
  var HostedIntegrationType;
775
632
  (function (HostedIntegrationType) {
@@ -866,13 +723,40 @@ var HostedIntegrationType;
866
723
  // Loops = 'loops', // Does not exist
867
724
  })(HostedIntegrationType || (HostedIntegrationType = {}));
868
725
 
869
- // TODO(evalsv2): Remove
870
- var EvaluationResultableType;
871
- (function (EvaluationResultableType) {
872
- EvaluationResultableType["Boolean"] = "evaluation_resultable_booleans";
873
- EvaluationResultableType["Text"] = "evaluation_resultable_texts";
874
- EvaluationResultableType["Number"] = "evaluation_resultable_numbers";
875
- })(EvaluationResultableType || (EvaluationResultableType = {}));
726
+ var LogSources;
727
+ (function (LogSources) {
728
+ LogSources["API"] = "api";
729
+ LogSources["AgentAsTool"] = "agent_as_tool";
730
+ LogSources["Copilot"] = "copilot";
731
+ LogSources["EmailTrigger"] = "email_trigger";
732
+ LogSources["Evaluation"] = "evaluation";
733
+ LogSources["Experiment"] = "experiment";
734
+ LogSources["IntegrationTrigger"] = "integration_trigger";
735
+ LogSources["Playground"] = "playground";
736
+ LogSources["ScheduledTrigger"] = "scheduled_trigger";
737
+ LogSources["SharedPrompt"] = "shared_prompt";
738
+ LogSources["ShadowTest"] = "shadow_test";
739
+ LogSources["ABTestChallenger"] = "ab_test_challenger";
740
+ LogSources["User"] = "user";
741
+ })(LogSources || (LogSources = {}));
742
+
743
+ var RunSourceGroup;
744
+ (function (RunSourceGroup) {
745
+ RunSourceGroup["Production"] = "production";
746
+ RunSourceGroup["Playground"] = "playground";
747
+ })(RunSourceGroup || (RunSourceGroup = {}));
748
+ ({
749
+ [RunSourceGroup.Production]: [
750
+ LogSources.API,
751
+ LogSources.Copilot,
752
+ LogSources.EmailTrigger,
753
+ LogSources.IntegrationTrigger,
754
+ LogSources.ScheduledTrigger,
755
+ LogSources.SharedPrompt,
756
+ LogSources.User,
757
+ ],
758
+ [RunSourceGroup.Playground]: [LogSources.Playground, LogSources.Experiment],
759
+ });
876
760
 
877
761
  var MessageRole;
878
762
  (function (MessageRole) {
@@ -882,13 +766,272 @@ var MessageRole;
882
766
  MessageRole["tool"] = "tool";
883
767
  })(MessageRole || (MessageRole = {}));
884
768
 
885
- var ModifiedDocumentType;
886
- (function (ModifiedDocumentType) {
887
- ModifiedDocumentType["Created"] = "created";
888
- ModifiedDocumentType["Updated"] = "updated";
889
- ModifiedDocumentType["UpdatedPath"] = "updated_path";
890
- ModifiedDocumentType["Deleted"] = "deleted";
891
- })(ModifiedDocumentType || (ModifiedDocumentType = {}));
769
+ var SpanKind;
770
+ (function (SpanKind) {
771
+ SpanKind["Internal"] = "internal";
772
+ SpanKind["Server"] = "server";
773
+ SpanKind["Client"] = "client";
774
+ SpanKind["Producer"] = "producer";
775
+ SpanKind["Consumer"] = "consumer";
776
+ })(SpanKind || (SpanKind = {}));
777
+ // Note: loosely based on OpenTelemetry GenAI semantic conventions
778
+ var SpanType;
779
+ (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";
787
+ SpanType["Prompt"] = "prompt";
788
+ SpanType["Chat"] = "chat";
789
+ SpanType["External"] = "external";
790
+ SpanType["UnresolvedExternal"] = "unresolved_external";
791
+ SpanType["Step"] = "step";
792
+ })(SpanType || (SpanType = {}));
793
+ const SPAN_SPECIFICATIONS = {
794
+ [SpanType.Tool]: {
795
+ name: 'Tool',
796
+ description: 'A tool call',
797
+ isGenAI: true,
798
+ isHidden: false,
799
+ },
800
+ [SpanType.Completion]: {
801
+ name: 'Completion',
802
+ description: 'A completion call',
803
+ isGenAI: true,
804
+ isHidden: false,
805
+ },
806
+ [SpanType.Embedding]: {
807
+ name: 'Embedding',
808
+ description: 'An embedding call',
809
+ isGenAI: true,
810
+ isHidden: false,
811
+ },
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',
821
+ isGenAI: true,
822
+ isHidden: false,
823
+ },
824
+ [SpanType.Http]: {
825
+ name: 'HTTP',
826
+ description: 'An HTTP request',
827
+ isGenAI: false,
828
+ isHidden: true,
829
+ },
830
+ [SpanType.Unknown]: {
831
+ name: 'Unknown',
832
+ description: 'An unknown span',
833
+ isGenAI: false,
834
+ isHidden: true,
835
+ },
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
+ };
867
+ var SpanStatus;
868
+ (function (SpanStatus) {
869
+ SpanStatus["Unset"] = "unset";
870
+ SpanStatus["Ok"] = "ok";
871
+ SpanStatus["Error"] = "error";
872
+ })(SpanStatus || (SpanStatus = {}));
873
+
874
+ // Note: Traces are unmaterialized but this context is used to propagate the trace
875
+ // See www.w3.org/TR/trace-context and w3c.github.io/baggage
876
+ z.object({
877
+ traceparent: z.string(), // <version>-<trace-id>-<span-id>-<trace-flags>
878
+ tracestate: z.string().optional(), // <key>=urlencoded(<value>)[,<key>=urlencoded(<value>)]*
879
+ baggage: z.string().optional(), // <key>=urlencoded(<value>)[,<key>=urlencoded(<value>)]*
880
+ });
881
+
882
+ /* Note: Instrumentation scopes from all language SDKs */
883
+ const SCOPE_LATITUDE = 'so.latitude.instrumentation';
884
+ var InstrumentationScope;
885
+ (function (InstrumentationScope) {
886
+ InstrumentationScope["Manual"] = "manual";
887
+ InstrumentationScope["Latitude"] = "latitude";
888
+ InstrumentationScope["OpenAI"] = "openai";
889
+ InstrumentationScope["Anthropic"] = "anthropic";
890
+ InstrumentationScope["AzureOpenAI"] = "azure";
891
+ InstrumentationScope["VercelAI"] = "vercelai";
892
+ InstrumentationScope["VertexAI"] = "vertexai";
893
+ InstrumentationScope["AIPlatform"] = "aiplatform";
894
+ InstrumentationScope["MistralAI"] = "mistralai";
895
+ InstrumentationScope["Bedrock"] = "bedrock";
896
+ InstrumentationScope["Sagemaker"] = "sagemaker";
897
+ InstrumentationScope["TogetherAI"] = "togetherai";
898
+ InstrumentationScope["Replicate"] = "replicate";
899
+ InstrumentationScope["Groq"] = "groq";
900
+ InstrumentationScope["Cohere"] = "cohere";
901
+ InstrumentationScope["LiteLLM"] = "litellm";
902
+ InstrumentationScope["Langchain"] = "langchain";
903
+ InstrumentationScope["LlamaIndex"] = "llamaindex";
904
+ InstrumentationScope["DSPy"] = "dspy";
905
+ InstrumentationScope["Haystack"] = "haystack";
906
+ InstrumentationScope["Ollama"] = "ollama";
907
+ InstrumentationScope["Transformers"] = "transformers";
908
+ InstrumentationScope["AlephAlpha"] = "alephalpha";
909
+ })(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
+ /* Note: Schemas for span ingestion following OpenTelemetry service request specification */
957
+ var Otlp;
958
+ (function (Otlp) {
959
+ Otlp.attributeValueSchema = z.object({
960
+ stringValue: z.string().optional(),
961
+ intValue: z.number().optional(),
962
+ boolValue: z.boolean().optional(),
963
+ arrayValue: z
964
+ .object({
965
+ values: z.array(z.object({
966
+ stringValue: z.string().optional(),
967
+ intValue: z.number().optional(),
968
+ boolValue: z.boolean().optional(),
969
+ })),
970
+ })
971
+ .optional(),
972
+ });
973
+ Otlp.attributeSchema = z.object({
974
+ key: z.string(),
975
+ value: Otlp.attributeValueSchema,
976
+ });
977
+ Otlp.eventSchema = z.object({
978
+ name: z.string(),
979
+ timeUnixNano: z.string(),
980
+ attributes: z.array(Otlp.attributeSchema).optional(),
981
+ });
982
+ Otlp.linkSchema = z.object({
983
+ traceId: z.string(),
984
+ spanId: z.string(),
985
+ attributes: z.array(Otlp.attributeSchema).optional(),
986
+ });
987
+ (function (StatusCode) {
988
+ StatusCode[StatusCode["Unset"] = 0] = "Unset";
989
+ StatusCode[StatusCode["Ok"] = 1] = "Ok";
990
+ StatusCode[StatusCode["Error"] = 2] = "Error";
991
+ })(Otlp.StatusCode || (Otlp.StatusCode = {}));
992
+ Otlp.statusSchema = z.object({
993
+ code: z.number(),
994
+ message: z.string().optional(),
995
+ });
996
+ (function (SpanKind) {
997
+ SpanKind[SpanKind["Internal"] = 0] = "Internal";
998
+ SpanKind[SpanKind["Server"] = 1] = "Server";
999
+ SpanKind[SpanKind["Client"] = 2] = "Client";
1000
+ SpanKind[SpanKind["Producer"] = 3] = "Producer";
1001
+ SpanKind[SpanKind["Consumer"] = 4] = "Consumer";
1002
+ })(Otlp.SpanKind || (Otlp.SpanKind = {}));
1003
+ Otlp.spanSchema = z.object({
1004
+ traceId: z.string(),
1005
+ spanId: z.string(),
1006
+ parentSpanId: z.string().optional(),
1007
+ name: z.string(),
1008
+ kind: z.number(),
1009
+ startTimeUnixNano: z.string(),
1010
+ endTimeUnixNano: z.string(),
1011
+ status: Otlp.statusSchema.optional(),
1012
+ events: z.array(Otlp.eventSchema).optional(),
1013
+ links: z.array(Otlp.linkSchema).optional(),
1014
+ attributes: z.array(Otlp.attributeSchema).optional(),
1015
+ });
1016
+ Otlp.scopeSchema = z.object({
1017
+ name: z.string(),
1018
+ version: z.string().optional(),
1019
+ });
1020
+ Otlp.scopeSpanSchema = z.object({
1021
+ scope: Otlp.scopeSchema,
1022
+ spans: z.array(Otlp.spanSchema),
1023
+ });
1024
+ Otlp.resourceSchema = z.object({
1025
+ attributes: z.array(Otlp.attributeSchema),
1026
+ });
1027
+ Otlp.resourceSpanSchema = z.object({
1028
+ resource: Otlp.resourceSchema,
1029
+ scopeSpans: z.array(Otlp.scopeSpanSchema),
1030
+ });
1031
+ Otlp.serviceRequestSchema = z.object({
1032
+ resourceSpans: z.array(Otlp.resourceSpanSchema),
1033
+ });
1034
+ })(Otlp || (Otlp = {}));
892
1035
 
893
1036
  // TODO(tracing): deprecated
894
1037
  const HEAD_COMMIT = 'live';
@@ -919,6 +1062,12 @@ var DocumentTriggerType;
919
1062
  DocumentTriggerType["Scheduled"] = "scheduled";
920
1063
  DocumentTriggerType["Integration"] = "integration";
921
1064
  })(DocumentTriggerType || (DocumentTriggerType = {}));
1065
+ var DocumentTriggerStatus;
1066
+ (function (DocumentTriggerStatus) {
1067
+ DocumentTriggerStatus["Pending"] = "pending";
1068
+ DocumentTriggerStatus["Deployed"] = "deployed";
1069
+ DocumentTriggerStatus["Deprecated"] = "deprecated";
1070
+ })(DocumentTriggerStatus || (DocumentTriggerStatus = {}));
922
1071
  var DocumentTriggerParameters;
923
1072
  (function (DocumentTriggerParameters) {
924
1073
  DocumentTriggerParameters["SenderEmail"] = "senderEmail";
@@ -927,14 +1076,13 @@ var DocumentTriggerParameters;
927
1076
  DocumentTriggerParameters["Body"] = "body";
928
1077
  DocumentTriggerParameters["Attachments"] = "attachments";
929
1078
  })(DocumentTriggerParameters || (DocumentTriggerParameters = {}));
1079
+ const DOCUMENT_PATH_REGEXP = /^([\w-]+\/)*([\w-.])+$/;
930
1080
 
931
1081
  class ManualInstrumentation {
932
1082
  enabled;
933
- source;
934
1083
  tracer;
935
- constructor(source, tracer) {
1084
+ constructor(tracer) {
936
1085
  this.enabled = false;
937
- this.source = source;
938
1086
  this.tracer = tracer;
939
1087
  }
940
1088
  isEnabled() {
@@ -946,95 +1094,34 @@ class ManualInstrumentation {
946
1094
  disable() {
947
1095
  this.enabled = false;
948
1096
  }
949
- baggage(ctx) {
950
- if ('traceparent' in ctx) {
951
- ctx = propagation.extract(otel.ROOT_CONTEXT, ctx);
1097
+ resume(ctx) {
1098
+ const parts = ctx.traceparent.split('-');
1099
+ if (parts.length !== 4) {
1100
+ return otel.ROOT_CONTEXT;
952
1101
  }
953
- const baggage = Object.fromEntries(propagation.getBaggage(ctx)?.getAllEntries() || []);
954
- if (!(ATTR_LATITUDE_SEGMENT_ID in baggage) ||
955
- !(ATTR_LATITUDE_SEGMENTS in baggage)) {
956
- return undefined;
1102
+ const [, traceId, spanId, flags] = parts;
1103
+ if (!traceId || !spanId) {
1104
+ return otel.ROOT_CONTEXT;
957
1105
  }
958
- const segment = {
959
- id: baggage[ATTR_LATITUDE_SEGMENT_ID].value,
960
- parentId: baggage[ATTR_LATITUDE_SEGMENT_PARENT_ID]?.value,
1106
+ const spanContext = {
1107
+ traceId,
1108
+ spanId,
1109
+ traceFlags: parseInt(flags ?? '01', 16),
1110
+ isRemote: true,
961
1111
  };
962
- let segments = [];
963
- try {
964
- segments = JSON.parse(baggage[ATTR_LATITUDE_SEGMENTS].value);
965
- }
966
- catch (error) {
967
- return undefined;
968
- }
969
- if (segments.length < 1) {
970
- return undefined;
971
- }
972
- return { segment, segments };
973
- }
974
- setBaggage(ctx, baggage, extra) {
975
- let parent = Object.fromEntries(propagation.getBaggage(ctx)?.getAllEntries() || []);
976
- parent = Object.fromEntries(Object.entries(parent).filter(([attribute]) => attribute !== ATTR_LATITUDE_SEGMENT_ID &&
977
- attribute !== ATTR_LATITUDE_SEGMENT_PARENT_ID &&
978
- attribute !== ATTR_LATITUDE_SEGMENTS));
979
- if (!baggage) {
980
- const payload = propagation.createBaggage({ ...parent, ...(extra || {}) });
981
- return propagation.setBaggage(ctx, payload);
982
- }
983
- let jsonSegments = '';
984
- try {
985
- jsonSegments = JSON.stringify(baggage.segments);
986
- }
987
- catch (error) {
988
- jsonSegments = '[]';
989
- }
990
- const payload = propagation.createBaggage({
991
- ...parent,
992
- [ATTR_LATITUDE_SEGMENT_ID]: { value: baggage.segment.id },
993
- ...(baggage.segment.parentId && {
994
- [ATTR_LATITUDE_SEGMENT_PARENT_ID]: { value: baggage.segment.parentId },
995
- }),
996
- [ATTR_LATITUDE_SEGMENTS]: { value: jsonSegments },
997
- ...(extra || {}),
998
- });
999
- return propagation.setBaggage(ctx, payload);
1000
- }
1001
- pause(ctx) {
1002
- const baggage = this.baggage(ctx);
1003
- if (baggage) {
1004
- baggage.segments.at(-1).paused = true;
1112
+ let context = trace.setSpanContext(otel.ROOT_CONTEXT, spanContext);
1113
+ if (ctx.baggage) {
1114
+ const baggageEntries = {};
1115
+ for (const pair of ctx.baggage.split(',')) {
1116
+ const [key, value] = pair.split('=');
1117
+ if (key && value) {
1118
+ baggageEntries[key] = { value: decodeURIComponent(value) };
1119
+ }
1120
+ }
1121
+ const baggage = propagation.createBaggage(baggageEntries);
1122
+ context = propagation.setBaggage(context, baggage);
1005
1123
  }
1006
- ctx = this.setBaggage(ctx, baggage);
1007
- let carrier = {};
1008
- propagation.inject(ctx, carrier);
1009
- return carrier;
1010
- }
1011
- resume(ctx) {
1012
- return propagation.extract(otel.ROOT_CONTEXT, ctx);
1013
- }
1014
- restored(ctx) {
1015
- const baggage = this.baggage(ctx);
1016
- return !baggage?.segments.some((segment) => segment.paused);
1017
- }
1018
- restore(ctx) {
1019
- let baggage = this.baggage(ctx);
1020
- if (!baggage)
1021
- return ctx;
1022
- const segments = baggage.segments;
1023
- while (segments.at(-1)?.paused)
1024
- segments.pop();
1025
- const segment = segments.at(-1);
1026
- if (!segment)
1027
- return otel.ROOT_CONTEXT;
1028
- baggage = {
1029
- segment: { id: segment.id, parentId: segment.parentId },
1030
- segments: segments,
1031
- };
1032
- ctx = this.setBaggage(ctx, baggage);
1033
- let carrier = {};
1034
- propagation.inject(ctx, carrier);
1035
- carrier.traceparent = segment.traceparent;
1036
- carrier.tracestate = segment.tracestate;
1037
- return this.resume(carrier);
1124
+ return context;
1038
1125
  }
1039
1126
  capitalize(str) {
1040
1127
  if (str.length === 0)
@@ -1341,7 +1428,7 @@ class ManualInstrumentation {
1341
1428
  completion(ctx, options) {
1342
1429
  const start = options;
1343
1430
  const configuration = {
1344
- ...start.configuration,
1431
+ ...(start.configuration ?? {}),
1345
1432
  model: start.model,
1346
1433
  };
1347
1434
  let jsonConfiguration = '';
@@ -1352,14 +1439,15 @@ class ManualInstrumentation {
1352
1439
  jsonConfiguration = '{}';
1353
1440
  }
1354
1441
  const attrConfiguration = this.attribifyConfiguration('input', configuration);
1442
+ const input = start.input ?? [];
1355
1443
  let jsonInput = '';
1356
1444
  try {
1357
- jsonInput = JSON.stringify(start.input);
1445
+ jsonInput = JSON.stringify(input);
1358
1446
  }
1359
1447
  catch (error) {
1360
1448
  jsonInput = '[]';
1361
1449
  }
1362
- const attrInput = this.attribifyMessages('input', start.input);
1450
+ const attrInput = this.attribifyMessages('input', input);
1363
1451
  const span = this.span(ctx, start.name || `${start.provider} / ${start.model}`, SpanType.Completion, {
1364
1452
  attributes: {
1365
1453
  [ATTR_GEN_AI_SYSTEM]: start.provider,
@@ -1368,34 +1456,45 @@ class ManualInstrumentation {
1368
1456
  [ATTR_GEN_AI_REQUEST_MESSAGES]: jsonInput,
1369
1457
  ...attrInput,
1370
1458
  ...(start.attributes || {}),
1459
+ [ATTR_LATITUDE_COMMIT_UUID]: start.versionUuid,
1460
+ [ATTR_LATITUDE_DOCUMENT_UUID]: start.promptUuid,
1461
+ [ATTR_LATITUDE_EXPERIMENT_UUID]: start.experimentUuid,
1371
1462
  },
1372
1463
  });
1373
1464
  return {
1374
1465
  context: span.context,
1375
1466
  end: (options) => {
1376
- const end = options;
1467
+ const end = options ?? {};
1468
+ const output = end.output ?? [];
1377
1469
  let jsonOutput = '';
1378
1470
  try {
1379
- jsonOutput = JSON.stringify(end.output);
1471
+ jsonOutput = JSON.stringify(output);
1380
1472
  }
1381
1473
  catch (error) {
1382
1474
  jsonOutput = '[]';
1383
1475
  }
1384
- const attrOutput = this.attribifyMessages('output', end.output);
1385
- const inputTokens = end.tokens.prompt + end.tokens.cached;
1386
- const outputTokens = end.tokens.reasoning + end.tokens.completion;
1476
+ const attrOutput = this.attribifyMessages('output', output);
1477
+ const tokens = {
1478
+ prompt: end.tokens?.prompt ?? 0,
1479
+ cached: end.tokens?.cached ?? 0,
1480
+ reasoning: end.tokens?.reasoning ?? 0,
1481
+ completion: end.tokens?.completion ?? 0,
1482
+ };
1483
+ const inputTokens = tokens.prompt + tokens.cached;
1484
+ const outputTokens = tokens.reasoning + tokens.completion;
1485
+ const finishReason = end.finishReason ?? '';
1387
1486
  span.end({
1388
1487
  attributes: {
1389
1488
  [ATTR_GEN_AI_RESPONSE_MESSAGES]: jsonOutput,
1390
1489
  ...attrOutput,
1391
1490
  [ATTR_GEN_AI_USAGE_INPUT_TOKENS]: inputTokens,
1392
- [ATTR_GEN_AI_USAGE_PROMPT_TOKENS]: end.tokens.prompt,
1393
- [ATTR_GEN_AI_USAGE_CACHED_TOKENS]: end.tokens.cached,
1394
- [ATTR_GEN_AI_USAGE_REASONING_TOKENS]: end.tokens.reasoning,
1395
- [ATTR_GEN_AI_USAGE_COMPLETION_TOKENS]: end.tokens.completion,
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,
1396
1495
  [ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: outputTokens,
1397
1496
  [ATTR_GEN_AI_RESPONSE_MODEL]: start.model,
1398
- [ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [end.finishReason],
1497
+ [ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [finishReason],
1399
1498
  ...(end.attributes || {}),
1400
1499
  },
1401
1500
  });
@@ -1482,49 +1581,7 @@ class ManualInstrumentation {
1482
1581
  fail: span.fail,
1483
1582
  };
1484
1583
  }
1485
- segment(ctx, type, data, options) {
1486
- options = options || {};
1487
- let baggage = this.baggage(ctx);
1488
- const parent = baggage?.segments.at(-1);
1489
- const segments = baggage?.segments || [];
1490
- segments.push({
1491
- ...{
1492
- id: options._internal?.id || v4(),
1493
- ...(parent?.id && { parentId: parent.id }),
1494
- source: options._internal?.source || parent?.source || this.source,
1495
- type: type,
1496
- data: data,
1497
- },
1498
- traceparent: 'undefined',
1499
- tracestate: undefined,
1500
- });
1501
- const segment = segments.at(-1);
1502
- baggage = {
1503
- segment: { id: segment.id, parentId: segment.parentId },
1504
- segments: segments,
1505
- };
1506
- ctx = this.setBaggage(ctx, baggage, options.baggage);
1507
- // Dummy wrapper to force the same trace and carry on some segment attributes
1508
- const span = this.span(ctx, SEGMENT_SPECIFICATIONS[type].name, SpanType.Segment, { attributes: options.attributes });
1509
- let carrier = {};
1510
- propagation.inject(span.context, carrier);
1511
- baggage.segments.at(-1).traceparent = carrier.traceparent;
1512
- baggage.segments.at(-1).tracestate = carrier.tracestate;
1513
- // Fix current segment span segments attribute now that we know the trace
1514
- trace
1515
- .getSpan(span.context)
1516
- .setAttribute(ATTR_LATITUDE_SEGMENTS, JSON.stringify(baggage.segments));
1517
- ctx = this.setBaggage(span.context, baggage, options.baggage);
1518
- return { context: ctx, end: span.end, fail: span.fail };
1519
- }
1520
- prompt(ctx, { logUuid, versionUuid, promptUuid, experimentUuid, externalId, template, parameters, ...rest }) {
1521
- const baggage = {
1522
- ...(logUuid && { logUuid }), // TODO(tracing): temporal related log, remove when observability is ready
1523
- commitUuid: versionUuid || HEAD_COMMIT,
1524
- documentUuid: promptUuid,
1525
- ...(experimentUuid && { experimentUuid }),
1526
- ...(externalId && { externalId }),
1527
- };
1584
+ prompt(ctx, { documentLogUuid, versionUuid, promptUuid, projectId, experimentUuid, testDeploymentId, externalId, template, parameters, name, source, ...rest }) {
1528
1585
  let jsonParameters = '';
1529
1586
  try {
1530
1587
  jsonParameters = JSON.stringify(parameters || {});
@@ -1535,34 +1592,79 @@ class ManualInstrumentation {
1535
1592
  const attributes = {
1536
1593
  [ATTR_GEN_AI_REQUEST_TEMPLATE]: template,
1537
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,
1599
+ ...(experimentUuid && {
1600
+ [ATTR_LATITUDE_EXPERIMENT_UUID]: experimentUuid,
1601
+ }),
1602
+ ...(testDeploymentId && {
1603
+ [ATTR_LATITUDE_TEST_DEPLOYMENT_ID]: testDeploymentId,
1604
+ }),
1605
+ ...(externalId && { [ATTR_LATITUDE_EXTERNAL_ID]: externalId }),
1606
+ ...(source && { [ATTR_LATITUDE_SOURCE]: source }),
1538
1607
  ...(rest.attributes || {}),
1539
1608
  };
1540
- return this.segment(ctx, SegmentType.Document, baggage, {
1541
- ...rest,
1609
+ return this.span(ctx, name || `prompt-${promptUuid}`, SpanType.Prompt, {
1542
1610
  attributes,
1543
1611
  });
1544
1612
  }
1545
1613
  step(ctx, options) {
1546
- return this.segment(ctx, SegmentType.Step, undefined, options);
1614
+ return this.span(ctx, 'step', SpanType.Step, options);
1615
+ }
1616
+ chat(ctx, { documentLogUuid, previousTraceId, source, name, ...rest }) {
1617
+ const attributes = {
1618
+ [ATTR_LATITUDE_DOCUMENT_LOG_UUID]: documentLogUuid,
1619
+ [ATTR_LATITUDE_PREVIOUS_TRACE_ID]: previousTraceId,
1620
+ ...(source && { [ATTR_LATITUDE_SOURCE]: source }),
1621
+ ...(rest.attributes || {}),
1622
+ };
1623
+ return this.span(ctx, name || 'chat', SpanType.Chat, { attributes });
1624
+ }
1625
+ external(ctx, { promptUuid, documentLogUuid, source, versionUuid, externalId, name, ...rest }) {
1626
+ 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 }),
1632
+ ...(rest.attributes || {}),
1633
+ };
1634
+ return this.span(ctx, name || `external-${promptUuid}`, SpanType.External, {
1635
+ attributes,
1636
+ });
1637
+ }
1638
+ unresolvedExternal(ctx, { path, projectId, versionUuid, conversationUuid, name, ...rest }) {
1639
+ const attributes = {
1640
+ [ATTR_LATITUDE_PROMPT_PATH]: path,
1641
+ [ATTR_LATITUDE_PROJECT_ID]: projectId,
1642
+ ...(versionUuid && { [ATTR_LATITUDE_COMMIT_UUID]: versionUuid }),
1643
+ ...(conversationUuid && {
1644
+ [ATTR_LATITUDE_DOCUMENT_LOG_UUID]: conversationUuid,
1645
+ }),
1646
+ ...(rest.attributes || {}),
1647
+ };
1648
+ return this.span(ctx, name || `capture-${path}`, SpanType.UnresolvedExternal, { attributes });
1547
1649
  }
1548
1650
  }
1549
1651
 
1550
1652
  class LatitudeInstrumentation {
1551
1653
  options;
1552
- telemetry;
1553
- constructor(source, tracer, options) {
1554
- this.telemetry = new ManualInstrumentation(source, tracer);
1654
+ manualTelemetry;
1655
+ constructor(tracer, options) {
1656
+ this.manualTelemetry = new ManualInstrumentation(tracer);
1555
1657
  this.options = options;
1556
1658
  }
1557
1659
  isEnabled() {
1558
- return this.telemetry.isEnabled();
1660
+ return this.manualTelemetry.isEnabled();
1559
1661
  }
1560
1662
  enable() {
1561
1663
  this.options.module.instrument(this);
1562
- this.telemetry.enable();
1664
+ this.manualTelemetry.enable();
1563
1665
  }
1564
1666
  disable() {
1565
- this.telemetry.disable();
1667
+ this.manualTelemetry.disable();
1566
1668
  this.options.module.uninstrument();
1567
1669
  }
1568
1670
  countTokens(messages) {
@@ -1586,7 +1688,8 @@ class LatitudeInstrumentation {
1586
1688
  }
1587
1689
  async wrapRenderChain(fn, ...args) {
1588
1690
  const { prompt, parameters } = args[0];
1589
- const $prompt = this.telemetry.prompt(context.active(), {
1691
+ const $prompt = this.manualTelemetry.prompt(context.active(), {
1692
+ documentLogUuid: v4(),
1590
1693
  versionUuid: prompt.versionUuid,
1591
1694
  promptUuid: prompt.uuid,
1592
1695
  template: prompt.content,
@@ -1604,7 +1707,7 @@ class LatitudeInstrumentation {
1604
1707
  return result;
1605
1708
  }
1606
1709
  async wrapRenderStep(fn, ...args) {
1607
- const $step = this.telemetry.step(context.active());
1710
+ const $step = this.manualTelemetry.step(context.active());
1608
1711
  let result;
1609
1712
  try {
1610
1713
  result = await context.with($step.context, async () => await fn(...args));
@@ -1622,7 +1725,7 @@ class LatitudeInstrumentation {
1622
1725
  }
1623
1726
  const { provider, config, messages } = args[0];
1624
1727
  const model = config.model || 'unknown';
1625
- const $completion = this.telemetry.completion(context.active(), {
1728
+ const $completion = this.manualTelemetry.completion(context.active(), {
1626
1729
  name: `${provider} / ${model}`,
1627
1730
  provider: provider,
1628
1731
  model: model,
@@ -1656,7 +1759,7 @@ class LatitudeInstrumentation {
1656
1759
  }
1657
1760
  async wrapRenderTool(fn, ...args) {
1658
1761
  const { toolRequest } = args[0];
1659
- const $tool = this.telemetry.tool(context.active(), {
1762
+ const $tool = this.manualTelemetry.tool(context.active(), {
1660
1763
  name: toolRequest.toolName,
1661
1764
  call: {
1662
1765
  id: toolRequest.toolCallId,
@@ -1681,10 +1784,165 @@ class LatitudeInstrumentation {
1681
1784
  }
1682
1785
  }
1683
1786
 
1787
+ var LatitudeErrorCodes;
1788
+ (function (LatitudeErrorCodes) {
1789
+ LatitudeErrorCodes["UnexpectedError"] = "UnexpectedError";
1790
+ LatitudeErrorCodes["OverloadedError"] = "OverloadedError";
1791
+ LatitudeErrorCodes["RateLimitError"] = "RateLimitError";
1792
+ LatitudeErrorCodes["UnauthorizedError"] = "UnauthorizedError";
1793
+ LatitudeErrorCodes["ForbiddenError"] = "ForbiddenError";
1794
+ LatitudeErrorCodes["BadRequestError"] = "BadRequestError";
1795
+ LatitudeErrorCodes["NotFoundError"] = "NotFoundError";
1796
+ LatitudeErrorCodes["ConflictError"] = "ConflictError";
1797
+ LatitudeErrorCodes["UnprocessableEntityError"] = "UnprocessableEntityError";
1798
+ LatitudeErrorCodes["NotImplementedError"] = "NotImplementedError";
1799
+ LatitudeErrorCodes["PaymentRequiredError"] = "PaymentRequiredError";
1800
+ LatitudeErrorCodes["AbortedError"] = "AbortedError";
1801
+ })(LatitudeErrorCodes || (LatitudeErrorCodes = {}));
1802
+ // NOTE: If you add a new error code, please add it to the pg enum in models/runErrors.ts
1803
+ var RunErrorCodes;
1804
+ (function (RunErrorCodes) {
1805
+ RunErrorCodes["AIProviderConfigError"] = "ai_provider_config_error";
1806
+ RunErrorCodes["AIRunError"] = "ai_run_error";
1807
+ RunErrorCodes["ChainCompileError"] = "chain_compile_error";
1808
+ RunErrorCodes["DefaultProviderExceededQuota"] = "default_provider_exceeded_quota_error";
1809
+ RunErrorCodes["DefaultProviderInvalidModel"] = "default_provider_invalid_model_error";
1810
+ RunErrorCodes["DocumentConfigError"] = "document_config_error";
1811
+ RunErrorCodes["ErrorGeneratingMockToolResult"] = "error_generating_mock_tool_result";
1812
+ RunErrorCodes["FailedToWakeUpIntegrationError"] = "failed_to_wake_up_integration_error";
1813
+ RunErrorCodes["InvalidResponseFormatError"] = "invalid_response_format_error";
1814
+ RunErrorCodes["MaxStepCountExceededError"] = "max_step_count_exceeded_error";
1815
+ RunErrorCodes["MissingProvider"] = "missing_provider_error";
1816
+ RunErrorCodes["RateLimit"] = "rate_limit_error";
1817
+ RunErrorCodes["Unknown"] = "unknown_error";
1818
+ RunErrorCodes["UnsupportedProviderResponseTypeError"] = "unsupported_provider_response_type_error";
1819
+ RunErrorCodes["PaymentRequiredError"] = "payment_required_error";
1820
+ RunErrorCodes["AbortError"] = "abort_error";
1821
+ // DEPRECATED, but do not delete
1822
+ RunErrorCodes["EvaluationRunMissingProviderLogError"] = "ev_run_missing_provider_log_error";
1823
+ RunErrorCodes["EvaluationRunMissingWorkspaceError"] = "ev_run_missing_workspace_error";
1824
+ RunErrorCodes["EvaluationRunResponseJsonFormatError"] = "ev_run_response_json_format_error";
1825
+ RunErrorCodes["EvaluationRunUnsupportedResultTypeError"] = "ev_run_unsupported_result_type_error";
1826
+ })(RunErrorCodes || (RunErrorCodes = {}));
1827
+ var ApiErrorCodes;
1828
+ (function (ApiErrorCodes) {
1829
+ ApiErrorCodes["HTTPException"] = "http_exception";
1830
+ ApiErrorCodes["InternalServerError"] = "internal_server_error";
1831
+ })(ApiErrorCodes || (ApiErrorCodes = {}));
1832
+
1833
+ class LatitudeError extends Error {
1834
+ statusCode = 500;
1835
+ name = LatitudeErrorCodes.UnexpectedError;
1836
+ headers = {};
1837
+ details;
1838
+ constructor(message, details, status, name) {
1839
+ super(message);
1840
+ this.details = details ?? {};
1841
+ this.statusCode = status ?? this.statusCode;
1842
+ this.name = name ?? this.constructor.name;
1843
+ }
1844
+ serialize() {
1845
+ return {
1846
+ name: this.name,
1847
+ code: this.name,
1848
+ status: this.statusCode,
1849
+ message: this.message,
1850
+ details: this.details,
1851
+ };
1852
+ }
1853
+ static deserialize(json) {
1854
+ return new LatitudeError(json.message, json.details, json.status, json.name);
1855
+ }
1856
+ }
1857
+ class BadRequestError extends LatitudeError {
1858
+ statusCode = 400;
1859
+ name = LatitudeErrorCodes.BadRequestError;
1860
+ }
1861
+
1684
1862
  const TRACES_URL = `${env.GATEWAY_BASE_URL}/api/v3/traces`;
1685
1863
  const SERVICE_NAME = process.env.npm_package_name || 'unknown';
1686
1864
  const SCOPE_VERSION = process.env.npm_package_version || 'unknown';
1687
1865
  const BACKGROUND = () => otel.ROOT_CONTEXT;
1866
+ class SpanFactory {
1867
+ telemetry;
1868
+ constructor(telemetry) {
1869
+ this.telemetry = telemetry;
1870
+ }
1871
+ tool(options, ctx) {
1872
+ return this.telemetry.tool(ctx ?? context.active(), options);
1873
+ }
1874
+ completion(options, ctx) {
1875
+ return this.telemetry.completion(ctx ?? context.active(), options);
1876
+ }
1877
+ embedding(options, ctx) {
1878
+ return this.telemetry.embedding(ctx ?? context.active(), options);
1879
+ }
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
+ http(options, ctx) {
1887
+ return this.telemetry.http(ctx ?? context.active(), options);
1888
+ }
1889
+ prompt(options, ctx) {
1890
+ return this.telemetry.prompt(ctx ?? context.active(), options);
1891
+ }
1892
+ step(options, ctx) {
1893
+ return this.telemetry.step(ctx ?? context.active(), options);
1894
+ }
1895
+ chat(options, ctx) {
1896
+ return this.telemetry.chat(ctx ?? context.active(), options);
1897
+ }
1898
+ external(options, ctx) {
1899
+ return this.telemetry.external(ctx ?? context.active(), options);
1900
+ }
1901
+ }
1902
+ class ContextManager {
1903
+ telemetry;
1904
+ constructor(telemetry) {
1905
+ this.telemetry = telemetry;
1906
+ }
1907
+ resume(ctx) {
1908
+ return this.telemetry.resume(ctx);
1909
+ }
1910
+ active() {
1911
+ return context.active();
1912
+ }
1913
+ }
1914
+ class InstrumentationManager {
1915
+ instrumentations;
1916
+ constructor(instrumentations) {
1917
+ this.instrumentations = instrumentations;
1918
+ }
1919
+ enable() {
1920
+ this.instrumentations.forEach((instrumentation) => {
1921
+ if (!instrumentation.isEnabled())
1922
+ instrumentation.enable();
1923
+ });
1924
+ }
1925
+ disable() {
1926
+ this.instrumentations.forEach((instrumentation) => {
1927
+ if (instrumentation.isEnabled())
1928
+ instrumentation.disable();
1929
+ });
1930
+ }
1931
+ }
1932
+ class TracerManager {
1933
+ nodeProvider;
1934
+ scopeVersion;
1935
+ constructor(nodeProvider, scopeVersion) {
1936
+ this.nodeProvider = nodeProvider;
1937
+ this.scopeVersion = scopeVersion;
1938
+ }
1939
+ get(scope) {
1940
+ return this.provider(scope).getTracer('');
1941
+ }
1942
+ provider(scope) {
1943
+ return new ScopedTracerProvider(`${SCOPE_LATITUDE}.${scope}`, this.scopeVersion, this.nodeProvider);
1944
+ }
1945
+ }
1688
1946
  class ScopedTracerProvider {
1689
1947
  scope;
1690
1948
  version;
@@ -1709,24 +1967,26 @@ const DEFAULT_SPAN_EXPORTER = (apiKey) => new OTLPTraceExporter({
1709
1967
  // Note: Only exporting typescript instrumentations
1710
1968
  var Instrumentation;
1711
1969
  (function (Instrumentation) {
1712
- Instrumentation["Latitude"] = "latitude";
1713
- Instrumentation["OpenAI"] = "openai";
1714
1970
  Instrumentation["Anthropic"] = "anthropic";
1715
- Instrumentation["AzureOpenAI"] = "azure";
1716
- Instrumentation["VercelAI"] = "vercelai";
1717
- Instrumentation["VertexAI"] = "vertexai";
1718
1971
  Instrumentation["AIPlatform"] = "aiplatform";
1719
1972
  Instrumentation["Bedrock"] = "bedrock";
1720
- Instrumentation["TogetherAI"] = "togetherai";
1721
1973
  Instrumentation["Cohere"] = "cohere";
1722
1974
  Instrumentation["Langchain"] = "langchain";
1975
+ Instrumentation["Latitude"] = "latitude";
1723
1976
  Instrumentation["LlamaIndex"] = "llamaindex";
1977
+ Instrumentation["OpenAI"] = "openai";
1978
+ Instrumentation["TogetherAI"] = "togetherai";
1979
+ Instrumentation["VertexAI"] = "vertexai";
1724
1980
  })(Instrumentation || (Instrumentation = {}));
1725
1981
  class LatitudeTelemetry {
1726
1982
  options;
1727
- provider;
1728
- telemetry;
1729
- instrumentations;
1983
+ nodeProvider;
1984
+ manualInstrumentation;
1985
+ instrumentationsList;
1986
+ span;
1987
+ context;
1988
+ instrumentation;
1989
+ tracer;
1730
1990
  constructor(apiKey, options) {
1731
1991
  this.options = options || {};
1732
1992
  if (!this.options.exporter) {
@@ -1740,234 +2000,100 @@ class LatitudeTelemetry {
1740
2000
  new W3CBaggagePropagator(),
1741
2001
  ],
1742
2002
  }));
1743
- this.provider = new NodeTracerProvider({
2003
+ this.nodeProvider = new NodeTracerProvider({
1744
2004
  resource: new Resource({ [ATTR_SERVICE_NAME]: SERVICE_NAME }),
1745
2005
  });
1746
2006
  // Note: important, must run before the exporter span processors
1747
- this.provider.addSpanProcessor(new BaggageSpanProcessor(ALLOW_ALL_BAGGAGE_KEYS));
2007
+ this.nodeProvider.addSpanProcessor(new BaggageSpanProcessor(ALLOW_ALL_BAGGAGE_KEYS));
1748
2008
  if (this.options.processors) {
1749
2009
  this.options.processors.forEach((processor) => {
1750
- this.provider.addSpanProcessor(processor);
2010
+ this.nodeProvider.addSpanProcessor(processor);
1751
2011
  });
1752
2012
  }
1753
2013
  else {
1754
- this.provider.addSpanProcessor(DEFAULT_REDACT_SPAN_PROCESSOR());
2014
+ this.nodeProvider.addSpanProcessor(DEFAULT_REDACT_SPAN_PROCESSOR());
1755
2015
  }
1756
2016
  if (this.options.disableBatch) {
1757
- this.provider.addSpanProcessor(new SimpleSpanProcessor(this.options.exporter));
2017
+ this.nodeProvider.addSpanProcessor(new SimpleSpanProcessor(this.options.exporter));
1758
2018
  }
1759
2019
  else {
1760
- this.provider.addSpanProcessor(new BatchSpanProcessor(this.options.exporter));
2020
+ this.nodeProvider.addSpanProcessor(new BatchSpanProcessor(this.options.exporter));
1761
2021
  }
1762
- this.provider.register();
2022
+ this.nodeProvider.register();
1763
2023
  process.on('SIGTERM', async () => this.shutdown);
1764
2024
  process.on('SIGINT', async () => this.shutdown);
1765
- this.telemetry = null;
1766
- this.instrumentations = [];
2025
+ this.manualInstrumentation = null;
2026
+ this.instrumentationsList = [];
2027
+ this.tracer = new TracerManager(this.nodeProvider, SCOPE_VERSION);
1767
2028
  this.initInstrumentations();
1768
- this.instrument();
2029
+ this.instrumentation = new InstrumentationManager(this.instrumentationsList);
2030
+ this.instrumentation.enable();
2031
+ this.span = new SpanFactory(this.manualInstrumentation);
2032
+ this.context = new ContextManager(this.manualInstrumentation);
1769
2033
  }
1770
2034
  async flush() {
1771
- await this.provider.forceFlush();
2035
+ await this.nodeProvider.forceFlush();
1772
2036
  await this.options.exporter.forceFlush?.();
1773
2037
  }
1774
2038
  async shutdown() {
1775
2039
  await this.flush();
1776
- await this.provider.shutdown();
2040
+ await this.nodeProvider.shutdown();
1777
2041
  await this.options.exporter.shutdown?.();
1778
2042
  }
1779
- tracerProvider(instrumentation) {
1780
- return new ScopedTracerProvider(`${SCOPE_LATITUDE}.${instrumentation}`, SCOPE_VERSION, this.provider);
1781
- }
1782
- tracer(instrumentation) {
1783
- return this.tracerProvider(instrumentation).getTracer('');
1784
- }
1785
2043
  // TODO(tracing): auto instrument outgoing HTTP requests
1786
2044
  initInstrumentations() {
1787
- this.instrumentations = [];
1788
- const tracer = this.tracer(InstrumentationScope.Manual);
1789
- this.telemetry = new ManualInstrumentation(SegmentSource.API, tracer);
1790
- this.instrumentations.push(this.telemetry);
2045
+ this.instrumentationsList = [];
2046
+ const tracer = this.tracer.get(InstrumentationScope.Manual);
2047
+ this.manualInstrumentation = new ManualInstrumentation(tracer);
2048
+ this.instrumentationsList.push(this.manualInstrumentation);
1791
2049
  const latitude = this.options.instrumentations?.latitude;
1792
2050
  if (latitude) {
1793
- const tracer = this.tracer(Instrumentation.Latitude);
1794
- const instrumentation = new LatitudeInstrumentation(SegmentSource.API, tracer, typeof latitude === 'object' ? latitude : { module: latitude });
1795
- this.instrumentations.push(instrumentation);
1796
- }
1797
- const openai = this.options.instrumentations?.openai;
1798
- if (openai) {
1799
- const provider = this.tracerProvider(Instrumentation.OpenAI);
1800
- const instrumentation = new OpenAIInstrumentation({ enrichTokens: true });
1801
- instrumentation.setTracerProvider(provider);
1802
- instrumentation.manuallyInstrument(openai);
1803
- registerInstrumentations({
1804
- instrumentations: [instrumentation],
1805
- tracerProvider: provider,
1806
- });
1807
- this.instrumentations.push(instrumentation);
1808
- }
1809
- const anthropic = this.options.instrumentations?.anthropic;
1810
- if (anthropic) {
1811
- const provider = this.tracerProvider(Instrumentation.Anthropic);
1812
- const instrumentation = new AnthropicInstrumentation();
1813
- instrumentation.setTracerProvider(provider);
1814
- instrumentation.manuallyInstrument(anthropic);
1815
- registerInstrumentations({
1816
- instrumentations: [instrumentation],
1817
- tracerProvider: provider,
1818
- });
1819
- this.instrumentations.push(instrumentation);
1820
- }
1821
- const azure = this.options.instrumentations?.azure;
1822
- if (azure) {
1823
- const provider = this.tracerProvider(Instrumentation.AzureOpenAI);
1824
- const instrumentation = new AzureOpenAIInstrumentation();
1825
- instrumentation.setTracerProvider(provider);
1826
- instrumentation.manuallyInstrument(azure);
1827
- registerInstrumentations({
1828
- instrumentations: [instrumentation],
1829
- tracerProvider: provider,
1830
- });
1831
- this.instrumentations.push(instrumentation);
1832
- }
1833
- const vertexai = this.options.instrumentations?.vertexai;
1834
- if (vertexai) {
1835
- const provider = this.tracerProvider(Instrumentation.VertexAI);
1836
- const instrumentation = new VertexAIInstrumentation();
1837
- instrumentation.setTracerProvider(provider);
1838
- instrumentation.manuallyInstrument(vertexai);
1839
- registerInstrumentations({
1840
- instrumentations: [instrumentation],
1841
- tracerProvider: provider,
1842
- });
1843
- this.instrumentations.push(instrumentation);
1844
- }
1845
- const aiplatform = this.options.instrumentations?.aiplatform;
1846
- if (aiplatform) {
1847
- const provider = this.tracerProvider(Instrumentation.AIPlatform);
1848
- const instrumentation = new AIPlatformInstrumentation();
1849
- instrumentation.setTracerProvider(provider);
1850
- instrumentation.manuallyInstrument(aiplatform);
1851
- registerInstrumentations({
1852
- instrumentations: [instrumentation],
1853
- tracerProvider: provider,
1854
- });
1855
- this.instrumentations.push(instrumentation);
1856
- }
1857
- const bedrock = this.options.instrumentations?.bedrock;
1858
- if (bedrock) {
1859
- const provider = this.tracerProvider(Instrumentation.Bedrock);
1860
- const instrumentation = new BedrockInstrumentation();
1861
- instrumentation.setTracerProvider(provider);
1862
- instrumentation.manuallyInstrument(bedrock);
1863
- registerInstrumentations({
1864
- instrumentations: [instrumentation],
1865
- tracerProvider: provider,
1866
- });
1867
- this.instrumentations.push(instrumentation);
2051
+ const tracer = this.tracer.get(Instrumentation.Latitude);
2052
+ const instrumentation = new LatitudeInstrumentation(tracer, typeof latitude === 'object' ? latitude : { module: latitude });
2053
+ this.instrumentationsList.push(instrumentation);
1868
2054
  }
1869
- const togetherai = this.options.instrumentations?.togetherai;
1870
- if (togetherai) {
1871
- const provider = this.tracerProvider(Instrumentation.TogetherAI);
1872
- const instrumentation = new TogetherInstrumentation({
1873
- enrichTokens: true,
1874
- });
2055
+ const configureInstrumentation = (instrumentationType, InstrumentationConstructor, instrumentationOptions) => {
2056
+ const providerPkg = this.options.instrumentations?.[instrumentationType];
2057
+ const provider = this.tracer.provider(instrumentationType);
2058
+ const instrumentation = new InstrumentationConstructor(instrumentationOptions); // prettier-ignore
1875
2059
  instrumentation.setTracerProvider(provider);
1876
- instrumentation.manuallyInstrument(togetherai);
2060
+ if (providerPkg) {
2061
+ instrumentation.manuallyInstrument(providerPkg);
2062
+ }
1877
2063
  registerInstrumentations({
1878
2064
  instrumentations: [instrumentation],
1879
2065
  tracerProvider: provider,
1880
2066
  });
1881
- this.instrumentations.push(instrumentation);
2067
+ this.instrumentationsList.push(instrumentation);
2068
+ };
2069
+ configureInstrumentation(Instrumentation.Anthropic, AnthropicInstrumentation); // prettier-ignore
2070
+ configureInstrumentation(Instrumentation.AIPlatform, AIPlatformInstrumentation); // prettier-ignore
2071
+ configureInstrumentation(Instrumentation.Bedrock, BedrockInstrumentation); // prettier-ignore
2072
+ configureInstrumentation(Instrumentation.Cohere, CohereInstrumentation); // prettier-ignore
2073
+ configureInstrumentation(Instrumentation.Langchain, LangChainInstrumentation); // prettier-ignore
2074
+ configureInstrumentation(Instrumentation.LlamaIndex, LlamaIndexInstrumentation); // prettier-ignore
2075
+ configureInstrumentation(Instrumentation.OpenAI, OpenAIInstrumentation, { enrichTokens: true }); // prettier-ignore
2076
+ configureInstrumentation(Instrumentation.TogetherAI, TogetherInstrumentation, { enrichTokens: true }); // prettier-ignore
2077
+ configureInstrumentation(Instrumentation.VertexAI, VertexAIInstrumentation); // prettier-ignore
2078
+ }
2079
+ async capture(options, fn) {
2080
+ if (!DOCUMENT_PATH_REGEXP.test(options.path)) {
2081
+ throw new BadRequestError("Invalid path, no spaces. Only letters, numbers, '.', '-' and '_'");
1882
2082
  }
1883
- const cohere = this.options.instrumentations?.cohere;
1884
- if (cohere) {
1885
- const provider = this.tracerProvider(Instrumentation.Cohere);
1886
- const instrumentation = new CohereInstrumentation();
1887
- instrumentation.setTracerProvider(provider);
1888
- instrumentation.manuallyInstrument(cohere);
1889
- registerInstrumentations({
1890
- instrumentations: [instrumentation],
1891
- tracerProvider: provider,
1892
- });
1893
- this.instrumentations.push(instrumentation);
2083
+ const span = this.manualInstrumentation.unresolvedExternal(otel.ROOT_CONTEXT, options);
2084
+ try {
2085
+ const result = await context.with(span.context, () => fn(span.context));
2086
+ span.end();
2087
+ return result;
1894
2088
  }
1895
- const langchain = this.options.instrumentations?.langchain;
1896
- if (langchain) {
1897
- const provider = this.tracerProvider(Instrumentation.Langchain);
1898
- const instrumentation = new LangChainInstrumentation();
1899
- instrumentation.setTracerProvider(provider);
1900
- instrumentation.manuallyInstrument(langchain);
1901
- registerInstrumentations({
1902
- instrumentations: [instrumentation],
1903
- tracerProvider: provider,
1904
- });
1905
- this.instrumentations.push(instrumentation);
2089
+ catch (error) {
2090
+ span.fail(error);
2091
+ throw error;
1906
2092
  }
1907
- const llamaindex = this.options.instrumentations?.llamaindex;
1908
- if (llamaindex) {
1909
- const provider = this.tracerProvider(Instrumentation.LlamaIndex);
1910
- const instrumentation = new LlamaIndexInstrumentation();
1911
- instrumentation.setTracerProvider(provider);
1912
- instrumentation.manuallyInstrument(llamaindex);
1913
- registerInstrumentations({
1914
- instrumentations: [instrumentation],
1915
- tracerProvider: provider,
1916
- });
1917
- this.instrumentations.push(instrumentation);
2093
+ finally {
2094
+ await this.flush();
1918
2095
  }
1919
2096
  }
1920
- instrument() {
1921
- this.instrumentations.forEach((instrumentation) => {
1922
- if (!instrumentation.isEnabled())
1923
- instrumentation.enable();
1924
- });
1925
- }
1926
- uninstrument() {
1927
- this.instrumentations.forEach((instrumentation) => {
1928
- if (instrumentation.isEnabled())
1929
- instrumentation.disable();
1930
- });
1931
- }
1932
- baggage(ctx) {
1933
- return this.telemetry.baggage(ctx);
1934
- }
1935
- pause(ctx) {
1936
- return this.telemetry.pause(ctx);
1937
- }
1938
- resume(ctx) {
1939
- return this.telemetry.resume(ctx);
1940
- }
1941
- restored(ctx) {
1942
- return this.telemetry.restored(ctx);
1943
- }
1944
- restore(ctx) {
1945
- return this.telemetry.restore(ctx);
1946
- }
1947
- tool(ctx, options) {
1948
- return this.telemetry.tool(ctx, options);
1949
- }
1950
- completion(ctx, options) {
1951
- return this.telemetry.completion(ctx, options);
1952
- }
1953
- embedding(ctx, options) {
1954
- return this.telemetry.embedding(ctx, options);
1955
- }
1956
- retrieval(ctx, options) {
1957
- return this.telemetry.retrieval(ctx, options);
1958
- }
1959
- reranking(ctx, options) {
1960
- return this.telemetry.reranking(ctx, options);
1961
- }
1962
- http(ctx, options) {
1963
- return this.telemetry.http(ctx, options);
1964
- }
1965
- prompt(ctx, options) {
1966
- return this.telemetry.prompt(ctx, options);
1967
- }
1968
- step(ctx, options) {
1969
- return this.telemetry.step(ctx, options);
1970
- }
1971
2097
  }
1972
2098
 
1973
2099
  export { BACKGROUND, DEFAULT_REDACT_SPAN_PROCESSOR, DEFAULT_SPAN_EXPORTER, Instrumentation, LatitudeTelemetry, RedactSpanProcessor };