@uselemma/tracing 3.0.3 → 4.0.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/client.js ADDED
@@ -0,0 +1,660 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Lemma = exports.TraceHandle = exports.TraceContext = exports.NoopSpanHandle = exports.SpanHandle = void 0;
4
+ exports.active = active;
5
+ const node_async_hooks_1 = require("node:async_hooks");
6
+ const debug_mode_1 = require("./debug-mode");
7
+ const activeTrace = new node_async_hooks_1.AsyncLocalStorage();
8
+ function required(value, envName) {
9
+ if (value?.trim())
10
+ return value.trim();
11
+ throw new Error(`@uselemma/tracing: Missing ${envName}`);
12
+ }
13
+ function iso(value) {
14
+ if (value == null)
15
+ return value;
16
+ return value instanceof Date ? value.toISOString() : value;
17
+ }
18
+ function errorMessage(error) {
19
+ if (error == null)
20
+ return null;
21
+ return error instanceof Error ? error.message : String(error);
22
+ }
23
+ function timestampMs(value) {
24
+ if (value == null)
25
+ return null;
26
+ const ms = value instanceof Date ? value.getTime() : new Date(value).getTime();
27
+ return Number.isFinite(ms) ? ms : null;
28
+ }
29
+ function elapsedMs(start, end) {
30
+ const startMs = timestampMs(start);
31
+ const endMs = timestampMs(end);
32
+ if (startMs == null || endMs == null)
33
+ return undefined;
34
+ return Math.max(0, endMs - startMs);
35
+ }
36
+ function serializeAttribute(value) {
37
+ if (value == null)
38
+ return value;
39
+ if (typeof value === "string" ||
40
+ typeof value === "number" ||
41
+ typeof value === "boolean")
42
+ return value;
43
+ try {
44
+ return JSON.stringify(value);
45
+ }
46
+ catch {
47
+ return String(value);
48
+ }
49
+ }
50
+ function addDefined(attributes, key, value) {
51
+ if (value !== undefined)
52
+ attributes[key] = value;
53
+ }
54
+ function flattenMessage(attributes, prefix, message) {
55
+ if (message && typeof message === "object" && !Array.isArray(message)) {
56
+ for (const [key, value] of Object.entries(message)) {
57
+ addDefined(attributes, `${prefix}.message.${key}`, serializeAttribute(value));
58
+ }
59
+ return;
60
+ }
61
+ addDefined(attributes, `${prefix}.message.content`, serializeAttribute(message));
62
+ }
63
+ function flattenDocument(attributes, prefix, document) {
64
+ if (document && typeof document === "object" && !Array.isArray(document)) {
65
+ for (const [key, value] of Object.entries(document)) {
66
+ addDefined(attributes, `${prefix}.document.${key}`, serializeAttribute(value));
67
+ }
68
+ return;
69
+ }
70
+ addDefined(attributes, `${prefix}.document.content`, serializeAttribute(document));
71
+ }
72
+ function contractAttributes(options) {
73
+ const attributes = {};
74
+ addDefined(attributes, "input.mime_type", options.inputMimeType);
75
+ addDefined(attributes, "output.mime_type", options.outputMimeType);
76
+ addDefined(attributes, "llm.model_name", options.llmModelName ?? options.model);
77
+ addDefined(attributes, "llm.provider", options.llmProvider);
78
+ addDefined(attributes, "llm.system", options.llmSystem);
79
+ addDefined(attributes, "llm.invocation_parameters", serializeAttribute(options.llmInvocationParameters));
80
+ addDefined(attributes, "llm.tools", serializeAttribute(options.llmTools));
81
+ addDefined(attributes, "llm.token_count.prompt", options.llmTokenCountPrompt ?? options.usage?.inputTokens);
82
+ addDefined(attributes, "llm.token_count.completion", options.llmTokenCountCompletion ?? options.usage?.outputTokens);
83
+ addDefined(attributes, "llm.token_count.total", options.llmTokenCountTotal);
84
+ addDefined(attributes, "llm.prompt_template.template", options.llmPromptTemplate);
85
+ addDefined(attributes, "llm.prompt_template.variables", serializeAttribute(options.llmPromptTemplateVariables));
86
+ addDefined(attributes, "llm.prompt_template.version", options.llmPromptTemplateVersion);
87
+ addDefined(attributes, "tool.description", options.toolDescription);
88
+ addDefined(attributes, "tool.parameters", serializeAttribute(options.toolParameters));
89
+ addDefined(attributes, "embedding.model_name", options.embeddingModelName);
90
+ addDefined(attributes, "embedding.invocation_parameters", serializeAttribute(options.embeddingInvocationParameters));
91
+ addDefined(attributes, "embedding.embeddings", serializeAttribute(options.embeddingEmbeddings));
92
+ addDefined(attributes, "reranker.model_name", options.rerankerModelName);
93
+ options.llmInputMessages?.forEach((message, index) => {
94
+ flattenMessage(attributes, `llm.input_messages.${index}`, message);
95
+ });
96
+ options.llmOutputMessages?.forEach((message, index) => {
97
+ flattenMessage(attributes, `llm.output_messages.${index}`, message);
98
+ });
99
+ options.retrievalDocuments?.forEach((document, index) => {
100
+ flattenDocument(attributes, `retrieval.documents.${index}`, document);
101
+ });
102
+ options.rerankerInputDocuments?.forEach((document, index) => {
103
+ flattenDocument(attributes, `reranker.input_documents.${index}`, document);
104
+ });
105
+ options.rerankerOutputDocuments?.forEach((document, index) => {
106
+ flattenDocument(attributes, `reranker.output_documents.${index}`, document);
107
+ });
108
+ return attributes;
109
+ }
110
+ function spanAttributes(options) {
111
+ const attributes = {
112
+ ...(options.attributes ?? {}),
113
+ ...contractAttributes(options),
114
+ };
115
+ return Object.keys(attributes).length > 0 ? attributes : undefined;
116
+ }
117
+ function normalizeSpan(options, fallbackType) {
118
+ const startedAt = options.startedAt ?? new Date();
119
+ const endedAt = options.endedAt ?? new Date();
120
+ return {
121
+ id: options.id,
122
+ parent_id: options.parentId ?? options.parentSpanId,
123
+ name: options.name,
124
+ type: options.type ?? fallbackType,
125
+ input: options.input,
126
+ output: options.output,
127
+ metadata: options.metadata,
128
+ attributes: spanAttributes(options),
129
+ started_at: iso(startedAt) ?? new Date().toISOString(),
130
+ ended_at: iso(endedAt) ?? new Date().toISOString(),
131
+ duration_ms: options.durationMs,
132
+ status: options.status ?? (options.error ? "ERROR" : undefined),
133
+ error: errorMessage(options.error),
134
+ model: options.model,
135
+ usage: options.usage
136
+ ? {
137
+ input_tokens: options.usage.inputTokens,
138
+ output_tokens: options.usage.outputTokens,
139
+ }
140
+ : undefined,
141
+ tool_name: options.toolName,
142
+ };
143
+ }
144
+ function warnNoop(message) {
145
+ console.warn(`@uselemma/tracing: ${message}`);
146
+ }
147
+ function isTraceEndOptions(value) {
148
+ return (typeof value === "object" &&
149
+ value !== null &&
150
+ ("output" in value || "durationMs" in value));
151
+ }
152
+ class SpanHandle {
153
+ trace;
154
+ options;
155
+ id;
156
+ ended = false;
157
+ payload;
158
+ constructor(trace, options, payload) {
159
+ this.trace = trace;
160
+ this.options = options;
161
+ this.id = options.id ?? crypto.randomUUID();
162
+ this.payload =
163
+ payload ??
164
+ this.trace.addSpan({
165
+ ...this.options,
166
+ id: this.id,
167
+ startedAt: this.options.startedAt ?? new Date(),
168
+ endedAt: this.options.endedAt ?? null,
169
+ });
170
+ }
171
+ end(options = {}) {
172
+ if (this.ended)
173
+ return;
174
+ this.ended = true;
175
+ Object.assign(this.payload, normalizeSpan({
176
+ ...this.options,
177
+ ...options,
178
+ id: this.id,
179
+ startedAt: this.options.startedAt,
180
+ endedAt: options.endedAt ?? new Date(),
181
+ }, this.options.type ?? "span"));
182
+ this.trace.changed();
183
+ }
184
+ startSpan(options) {
185
+ const spanOptions = typeof options === "string" ? { name: options } : options;
186
+ return this.trace.startSpan({
187
+ ...spanOptions,
188
+ parentId: spanOptions.parentId ?? this.id,
189
+ });
190
+ }
191
+ startGeneration(options) {
192
+ const generationOptions = typeof options === "string" ? { name: options } : options;
193
+ return this.trace.startGeneration({
194
+ ...generationOptions,
195
+ parentId: generationOptions.parentId ?? this.id,
196
+ });
197
+ }
198
+ startTool(options) {
199
+ const toolOptions = typeof options === "string" ? { name: options } : options;
200
+ return this.trace.startTool({
201
+ ...toolOptions,
202
+ parentId: toolOptions.parentId ?? this.id,
203
+ });
204
+ }
205
+ recordSpan(options) {
206
+ const spanOptions = typeof options === "string" ? { name: options } : options;
207
+ return this.trace.recordSpan({
208
+ ...spanOptions,
209
+ parentId: spanOptions.parentId ?? this.id,
210
+ });
211
+ }
212
+ recordGeneration(options) {
213
+ const generationOptions = typeof options === "string" ? { name: options } : options;
214
+ this.trace.recordGeneration({
215
+ ...generationOptions,
216
+ parentId: generationOptions.parentId ?? this.id,
217
+ });
218
+ }
219
+ recordTool(options) {
220
+ const toolOptions = typeof options === "string" ? { name: options } : options;
221
+ this.trace.recordTool({
222
+ ...toolOptions,
223
+ parentId: toolOptions.parentId ?? this.id,
224
+ });
225
+ }
226
+ span(options) {
227
+ return typeof options === "string"
228
+ ? this.startSpan(options)
229
+ : this.recordSpan(options);
230
+ }
231
+ /** @deprecated Use recordGeneration() or startGeneration(). */
232
+ generation(options) {
233
+ this.recordGeneration(options);
234
+ }
235
+ /** @deprecated Use recordTool() or startTool(). */
236
+ tool(options) {
237
+ this.recordTool(options);
238
+ }
239
+ }
240
+ exports.SpanHandle = SpanHandle;
241
+ class NoopSpanHandle {
242
+ id = "";
243
+ end() { }
244
+ startSpan() {
245
+ return this;
246
+ }
247
+ startGeneration() {
248
+ return this;
249
+ }
250
+ startTool() {
251
+ return this;
252
+ }
253
+ recordSpan() {
254
+ return this;
255
+ }
256
+ recordGeneration() { }
257
+ recordTool() { }
258
+ span() {
259
+ return this;
260
+ }
261
+ generation() { }
262
+ tool() { }
263
+ }
264
+ exports.NoopSpanHandle = NoopSpanHandle;
265
+ class TraceContext {
266
+ options;
267
+ onChange;
268
+ spans = [];
269
+ traceOutput;
270
+ traceError = null;
271
+ id;
272
+ constructor(options, onChange) {
273
+ this.options = options;
274
+ this.onChange = onChange;
275
+ this.options.name ??= "trace";
276
+ this.options.id ??= crypto.randomUUID();
277
+ this.id = this.options.id;
278
+ this.traceOutput = options.output;
279
+ }
280
+ input(value) {
281
+ this.options.input = value;
282
+ this.changed();
283
+ }
284
+ output(value) {
285
+ this.traceOutput = value;
286
+ this.changed();
287
+ }
288
+ duration(durationMs) {
289
+ this.options.durationMs = durationMs;
290
+ this.changed();
291
+ }
292
+ fail(error) {
293
+ this.traceError = errorMessage(error);
294
+ this.changed();
295
+ }
296
+ changed() {
297
+ this.onChange?.();
298
+ }
299
+ setChangeHandler(onChange) {
300
+ this.onChange = onChange;
301
+ }
302
+ addSpan(options) {
303
+ const span = normalizeSpan(options, "span");
304
+ this.spans.push(span);
305
+ this.changed();
306
+ return span;
307
+ }
308
+ recordSpan(options) {
309
+ if (typeof options === "string") {
310
+ return this.startSpan({ name: options });
311
+ }
312
+ const spanId = options.id ?? crypto.randomUUID();
313
+ const span = this.addSpan({ ...options, id: spanId });
314
+ const handle = new SpanHandle(this, {
315
+ ...options,
316
+ id: spanId,
317
+ startedAt: span.started_at,
318
+ endedAt: span.ended_at,
319
+ }, span);
320
+ handle.end({ endedAt: span.ended_at ?? new Date() });
321
+ return handle;
322
+ }
323
+ recordGeneration(options) {
324
+ const generationOptions = typeof options === "string" ? { name: options } : options;
325
+ this.spans.push(normalizeSpan({ ...generationOptions, type: "generation" }, "generation"));
326
+ this.changed();
327
+ }
328
+ recordTool(options) {
329
+ const toolOptions = typeof options === "string" ? { name: options } : options;
330
+ this.spans.push(normalizeSpan({ ...toolOptions, type: "tool" }, "tool"));
331
+ this.changed();
332
+ }
333
+ startSpan(options) {
334
+ const spanOptions = typeof options === "string" ? { name: options } : options;
335
+ return new SpanHandle(this, {
336
+ ...spanOptions,
337
+ id: spanOptions.id ?? crypto.randomUUID(),
338
+ startedAt: spanOptions.startedAt ?? new Date(),
339
+ });
340
+ }
341
+ startGeneration(options) {
342
+ return this.startSpan({ ...options, type: "generation" });
343
+ }
344
+ startTool(options) {
345
+ return this.startSpan({ ...options, type: "tool" });
346
+ }
347
+ span(options) {
348
+ return typeof options === "string"
349
+ ? this.startSpan(options)
350
+ : this.recordSpan(options);
351
+ }
352
+ /** @deprecated Use recordGeneration() or startGeneration(). */
353
+ generation(options) {
354
+ this.recordGeneration(options);
355
+ }
356
+ /** @deprecated Use recordTool() or startTool(). */
357
+ tool(options) {
358
+ this.recordTool(options);
359
+ }
360
+ toPayload(projectId, startedAt, endedAt, replace = false) {
361
+ return {
362
+ project_id: projectId,
363
+ trace: {
364
+ id: this.options.id,
365
+ name: this.options.name ?? "trace",
366
+ input: this.options.input,
367
+ output: this.traceOutput,
368
+ metadata: this.options.metadata,
369
+ thread_id: this.options.threadId,
370
+ user_id: this.options.userId,
371
+ environment: this.options.environment,
372
+ started_at: startedAt.toISOString(),
373
+ ended_at: endedAt.toISOString(),
374
+ duration_ms: this.options.durationMs ?? elapsedMs(startedAt, endedAt),
375
+ status: this.traceError ? "ERROR" : undefined,
376
+ error: this.traceError,
377
+ spans: this.spans,
378
+ },
379
+ replace,
380
+ };
381
+ }
382
+ }
383
+ exports.TraceContext = TraceContext;
384
+ class TraceHandle extends TraceContext {
385
+ flushFn;
386
+ startedAt;
387
+ flushTimer;
388
+ flushPromise = Promise.resolve();
389
+ constructor(options, flushFn, startedAt = new Date()) {
390
+ super(options);
391
+ this.flushFn = flushFn;
392
+ this.startedAt = startedAt;
393
+ this.setChangeHandler(() => this.scheduleFlush());
394
+ this.scheduleFlush();
395
+ }
396
+ flush() {
397
+ if (this.flushTimer) {
398
+ clearTimeout(this.flushTimer);
399
+ this.flushTimer = undefined;
400
+ }
401
+ const endedAt = new Date();
402
+ this.flushPromise = this.flushPromise.then(() => this.flushFn(this, this.startedAt, endedAt));
403
+ return this.flushPromise;
404
+ }
405
+ async end(outputOrOptions) {
406
+ if (isTraceEndOptions(outputOrOptions)) {
407
+ if ("output" in outputOrOptions) {
408
+ this.output(outputOrOptions.output);
409
+ }
410
+ if (outputOrOptions.durationMs != null) {
411
+ this.duration(outputOrOptions.durationMs);
412
+ }
413
+ }
414
+ else if (arguments.length > 0) {
415
+ this.output(outputOrOptions);
416
+ }
417
+ await this.flush();
418
+ }
419
+ scheduleFlush() {
420
+ if (this.flushTimer)
421
+ return;
422
+ this.flushTimer = setTimeout(() => {
423
+ this.flushTimer = undefined;
424
+ void this.flush().catch(() => {
425
+ // Surface delivery failures to callers that await flush/end.
426
+ });
427
+ }, 0);
428
+ }
429
+ }
430
+ exports.TraceHandle = TraceHandle;
431
+ class Lemma {
432
+ apiKey;
433
+ projectId;
434
+ baseUrl;
435
+ fetchImpl;
436
+ traces = new Map();
437
+ constructor(options = {}) {
438
+ this.apiKey = required(options.apiKey ?? process.env.LEMMA_API_KEY, "LEMMA_API_KEY");
439
+ this.projectId = required(options.projectId ?? process.env.LEMMA_PROJECT_ID, "LEMMA_PROJECT_ID");
440
+ this.baseUrl = (options.baseUrl ?? "https://api.uselemma.ai").replace(/\/+$/, "");
441
+ this.fetchImpl = options.fetch ?? fetch;
442
+ }
443
+ trace(options = {}, fn) {
444
+ const traceOptions = typeof options === "string" ? { name: options } : options;
445
+ if (!fn) {
446
+ const handle = new TraceHandle(traceOptions, (trace, startedAt, endedAt) => this.flushTrace(trace, startedAt, endedAt, true));
447
+ this.traces.set(handle.id, handle);
448
+ (0, debug_mode_1.lemmaDebug)("client", "trace handle created", {
449
+ traceId: handle.id,
450
+ name: traceOptions.name ?? "trace",
451
+ });
452
+ return handle;
453
+ }
454
+ const context = new TraceContext(traceOptions);
455
+ const startedAt = new Date();
456
+ (0, debug_mode_1.lemmaDebug)("client", "trace started", {
457
+ traceId: context.id,
458
+ name: traceOptions.name ?? "trace",
459
+ });
460
+ return (async () => {
461
+ try {
462
+ const result = await activeTrace.run(context, () => fn(context));
463
+ if (traceOptions.output === undefined) {
464
+ context.output(result);
465
+ }
466
+ await this.flushTrace(context, startedAt, new Date());
467
+ return result;
468
+ }
469
+ catch (error) {
470
+ context.fail(error);
471
+ await this.flushTrace(context, startedAt, new Date());
472
+ throw error;
473
+ }
474
+ })();
475
+ }
476
+ recordSpan(options) {
477
+ if (typeof options === "string") {
478
+ return active().recordSpan(options);
479
+ }
480
+ const context = this.detachedTraceFor(options.traceId, "span");
481
+ if (!context)
482
+ return new NoopSpanHandle();
483
+ const { traceId: _traceId, parentSpanId, parentId, ...spanOptions } = options;
484
+ if (parentId && !parentSpanId) {
485
+ warnNoop("span has a parent, but parentSpanId was not provided; skipping span");
486
+ return new NoopSpanHandle();
487
+ }
488
+ return context.recordSpan({
489
+ name: "span",
490
+ ...spanOptions,
491
+ parentId: parentSpanId ?? null,
492
+ });
493
+ }
494
+ recordGeneration(options) {
495
+ if (typeof options === "string") {
496
+ active().recordGeneration(options);
497
+ return;
498
+ }
499
+ const context = this.detachedTraceFor(options.traceId, "generation");
500
+ if (!context)
501
+ return;
502
+ const { traceId: _traceId, parentSpanId, parentId, ...generationOptions } = options;
503
+ if (parentId && !parentSpanId) {
504
+ warnNoop("generation has a parent, but parentSpanId was not provided; skipping generation");
505
+ return;
506
+ }
507
+ context.recordGeneration({
508
+ name: "generation",
509
+ ...generationOptions,
510
+ parentId: parentSpanId ?? null,
511
+ });
512
+ }
513
+ recordTool(options) {
514
+ if (typeof options === "string") {
515
+ active().recordTool(options);
516
+ return;
517
+ }
518
+ const context = this.detachedTraceFor(options.traceId, "tool");
519
+ if (!context)
520
+ return;
521
+ const { traceId: _traceId, parentSpanId, parentId, ...toolOptions } = options;
522
+ if (parentId && !parentSpanId) {
523
+ warnNoop("tool has a parent, but parentSpanId was not provided; skipping tool");
524
+ return;
525
+ }
526
+ context.recordTool({
527
+ name: "tool",
528
+ ...toolOptions,
529
+ parentId: parentSpanId ?? null,
530
+ });
531
+ }
532
+ startSpan(options) {
533
+ if ("traceId" in options) {
534
+ const context = this.detachedTraceFor(options.traceId, "span");
535
+ if (!context)
536
+ return new NoopSpanHandle();
537
+ const { traceId: _traceId, parentSpanId, parentId, ...spanOptions } = options;
538
+ if (parentId && !parentSpanId) {
539
+ warnNoop("span has a parent, but parentSpanId was not provided; skipping span");
540
+ return new NoopSpanHandle();
541
+ }
542
+ return context.startSpan({
543
+ name: "span",
544
+ ...spanOptions,
545
+ parentId: parentSpanId ?? null,
546
+ });
547
+ }
548
+ return active().startSpan(options);
549
+ }
550
+ startGeneration(options) {
551
+ if ("traceId" in options) {
552
+ const context = this.detachedTraceFor(options.traceId, "generation");
553
+ if (!context)
554
+ return new NoopSpanHandle();
555
+ const { traceId: _traceId, parentSpanId, parentId, ...generationOptions } = options;
556
+ if (parentId && !parentSpanId) {
557
+ warnNoop("generation has a parent, but parentSpanId was not provided; skipping generation");
558
+ return new NoopSpanHandle();
559
+ }
560
+ return context.startGeneration({
561
+ name: "generation",
562
+ ...generationOptions,
563
+ parentId: parentSpanId ?? null,
564
+ });
565
+ }
566
+ return active().startGeneration(options);
567
+ }
568
+ startTool(options) {
569
+ if ("traceId" in options) {
570
+ const context = this.detachedTraceFor(options.traceId, "tool");
571
+ if (!context)
572
+ return new NoopSpanHandle();
573
+ const { traceId: _traceId, parentSpanId, parentId, ...toolOptions } = options;
574
+ if (parentId && !parentSpanId) {
575
+ warnNoop("tool has a parent, but parentSpanId was not provided; skipping tool");
576
+ return new NoopSpanHandle();
577
+ }
578
+ return context.startTool({
579
+ name: "tool",
580
+ ...toolOptions,
581
+ parentId: parentSpanId ?? null,
582
+ });
583
+ }
584
+ return active().startTool(options);
585
+ }
586
+ /** @deprecated Use startSpan() or recordSpan(). */
587
+ span(options) {
588
+ return typeof options === "string"
589
+ ? active().startSpan({ name: options })
590
+ : this.recordSpan(options);
591
+ }
592
+ /** @deprecated Use recordGeneration() or startGeneration(). */
593
+ generation(options) {
594
+ this.recordGeneration(options);
595
+ }
596
+ /** @deprecated Use recordTool() or startTool(). */
597
+ tool(options) {
598
+ this.recordTool(options);
599
+ }
600
+ traceFor(traceId) {
601
+ const trace = this.traces.get(traceId);
602
+ if (!trace) {
603
+ throw new Error(`@uselemma/tracing: unknown trace id "${traceId}"`);
604
+ }
605
+ return trace;
606
+ }
607
+ detachedTraceFor(traceId, kind) {
608
+ if (!traceId) {
609
+ warnNoop(`${kind} handle requires traceId; skipping ${kind}`);
610
+ return null;
611
+ }
612
+ const trace = this.traces.get(traceId);
613
+ if (!trace) {
614
+ warnNoop(`unknown trace id "${traceId}"; skipping ${kind}`);
615
+ return null;
616
+ }
617
+ return trace;
618
+ }
619
+ async flushTrace(context, startedAt, endedAt, replace = false) {
620
+ const payload = context.toPayload(this.projectId, startedAt, endedAt, replace);
621
+ const url = `${this.baseUrl}/traces/ingest`;
622
+ (0, debug_mode_1.lemmaDebug)("client", "sending trace", {
623
+ traceId: payload.trace.id,
624
+ name: payload.trace.name,
625
+ spanCount: payload.trace.spans.length,
626
+ url,
627
+ replace,
628
+ });
629
+ const response = await this.fetchImpl(url, {
630
+ method: "POST",
631
+ headers: {
632
+ Authorization: `Bearer ${this.apiKey}`,
633
+ "Content-Type": "application/json",
634
+ },
635
+ body: JSON.stringify(payload),
636
+ });
637
+ if (!response.ok) {
638
+ const body = await response.text().catch(() => "");
639
+ (0, debug_mode_1.lemmaDebug)("client", "trace ingest failed", {
640
+ traceId: payload.trace.id,
641
+ status: response.status,
642
+ body,
643
+ });
644
+ throw new Error(`@uselemma/tracing: failed to ingest trace (${response.status})${body ? `: ${body}` : ""}`);
645
+ }
646
+ (0, debug_mode_1.lemmaDebug)("client", "trace sent", {
647
+ traceId: payload.trace.id,
648
+ status: response.status,
649
+ });
650
+ }
651
+ }
652
+ exports.Lemma = Lemma;
653
+ function active() {
654
+ const trace = activeTrace.getStore();
655
+ if (!trace) {
656
+ throw new Error("@uselemma/tracing: no active trace context");
657
+ }
658
+ return trace;
659
+ }
660
+ //# sourceMappingURL=client.js.map