@lmnr-ai/lmnr 0.8.28 → 0.8.30

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.
@@ -174,11 +174,34 @@ type Event = {
174
174
  //#endregion
175
175
  //#region ../client/dist/index.d.cts
176
176
  //#region src/resources/index.d.ts
177
+ /**
178
+ * Unified auth for every resource. A discriminated union so a single object
179
+ * drives both the URL prefix and the request headers:
180
+ *
181
+ * - `apiKey` → project API key (SDK / app surfaces). Routes to `/v1/*`,
182
+ * Bearer is the project key, no `x-lmnr-project-id` header.
183
+ * - `userToken` → BetterAuth user access JWT (the CLI user-token surface).
184
+ * Routes to `/v1/cli/*`, Bearer is the JWT, carries the target project in
185
+ * the `x-lmnr-project-id` header.
186
+ */
187
+ type LaminarAuth = {
188
+ type: "apiKey";
189
+ key: string;
190
+ } | {
191
+ type: "userToken";
192
+ token: string;
193
+ projectId: string;
194
+ };
177
195
  declare class BaseResource {
178
196
  protected readonly baseHttpUrl: string;
179
- protected readonly projectApiKey: string;
180
- constructor(baseHttpUrl: string, projectApiKey: string);
197
+ protected readonly auth: LaminarAuth;
198
+ /** The bearer credential, regardless of auth type (project key or user JWT). */
199
+ protected readonly credential: string;
200
+ constructor(baseHttpUrl: string, auth: LaminarAuth);
201
+ /** API path prefix: `/v1/cli` for CLI user-token auth, `/v1` otherwise. */
202
+ protected get apiPrefix(): string;
181
203
  protected headers(): {
204
+ "x-lmnr-project-id"?: string | undefined;
182
205
  Authorization: string;
183
206
  "Content-Type": string;
184
207
  Accept: string;
@@ -187,7 +210,7 @@ declare class BaseResource {
187
210
  } //#endregion
188
211
  //#region src/resources/browser-events.d.ts
189
212
  declare class BrowserEventsResource extends BaseResource {
190
- constructor(baseHttpUrl: string, projectApiKey: string);
213
+ constructor(baseHttpUrl: string, auth: LaminarAuth);
191
214
  send({
192
215
  sessionId,
193
216
  traceId,
@@ -198,9 +221,30 @@ declare class BrowserEventsResource extends BaseResource {
198
221
  events: Record<string, any>[];
199
222
  }): Promise<void>;
200
223
  } //#endregion
224
+ //#region src/resources/cli.d.ts
225
+ interface CliProject {
226
+ id: string;
227
+ name: string;
228
+ workspaceId: string;
229
+ workspaceName: string;
230
+ }
231
+ /**
232
+ * User-scoped CLI endpoints that don't target a specific project. Authed by the
233
+ * BetterAuth user JWT (the `credential`); deliberately does NOT send an
234
+ * `x-lmnr-project-id` header (these routes are project discovery, pre-selection).
235
+ *
236
+ * Discovery exception: this resource always hits `/v1/cli/projects` with the
237
+ * bare bearer and overrides `BaseResource.headers()`/`apiPrefix`, so it works
238
+ * even when constructed with a `userToken` auth that has no real project id yet.
239
+ */
240
+ declare class CliResource extends BaseResource {
241
+ constructor(baseHttpUrl: string, auth: LaminarAuth);
242
+ /** Workspaces + projects the authenticated user can access. */
243
+ listProjects(): Promise<CliProject[]>;
244
+ } //#endregion
201
245
  //#region src/resources/datasets.d.ts
202
246
  declare class DatasetsResource extends BaseResource {
203
- constructor(baseHttpUrl: string, projectApiKey: string);
247
+ constructor(baseHttpUrl: string, auth: LaminarAuth);
204
248
  /**
205
249
  * List all datasets.
206
250
  *
@@ -262,7 +306,7 @@ declare class DatasetsResource extends BaseResource {
262
306
  } //#endregion
263
307
  //#region src/resources/evals.d.ts
264
308
  declare class EvalsResource extends BaseResource {
265
- constructor(baseHttpUrl: string, projectApiKey: string);
309
+ constructor(baseHttpUrl: string, auth: LaminarAuth);
266
310
  /**
267
311
  * Initialize an evaluation.
268
312
  *
@@ -393,7 +437,7 @@ type ScoreOptions = {
393
437
  * Resource for creating evaluator scores
394
438
  */
395
439
  declare class EvaluatorsResource extends BaseResource {
396
- constructor(baseHttpUrl: string, projectApiKey: string);
440
+ constructor(baseHttpUrl: string, auth: LaminarAuth);
397
441
  /**
398
442
  * Create a score for a span or trace
399
443
  *
@@ -444,7 +488,7 @@ type CacheOutcome = {
444
488
  kind: "live";
445
489
  };
446
490
  declare class RolloutSessionsResource extends BaseResource {
447
- constructor(baseHttpUrl: string, projectApiKey: string);
491
+ constructor(baseHttpUrl: string, auth: LaminarAuth);
448
492
  /**
449
493
  * Idempotently register (upsert) a debug session on the backend, keyed on the
450
494
  * SDK-supplied session id. The backend stores the row so the session is
@@ -506,13 +550,13 @@ declare class RolloutSessionsResource extends BaseResource {
506
550
  } //#endregion
507
551
  //#region src/resources/sql.d.ts
508
552
  declare class SqlResource extends BaseResource {
509
- constructor(baseHttpUrl: string, projectApiKey: string);
553
+ constructor(baseHttpUrl: string, auth: LaminarAuth);
510
554
  query(sql: string, parameters?: Record<string, any>): Promise<Array<Record<string, any>>>;
511
555
  } //#endregion
512
556
  //#region src/resources/tags.d.ts
513
557
  declare class TagsResource extends BaseResource {
514
558
  /** Resource for tagging traces. */
515
- constructor(baseHttpUrl: string, projectApiKey: string);
559
+ constructor(baseHttpUrl: string, auth: LaminarAuth);
516
560
  /**
517
561
  * Tag a trace with a list of tags. Note that the trace must be ended before
518
562
  * tagging it. You may want to call `await Laminar.flush()` after the trace
@@ -550,7 +594,7 @@ declare class TagsResource extends BaseResource {
550
594
  //#region src/resources/traces.d.ts
551
595
  declare class TracesResource extends BaseResource {
552
596
  /** Resource for post-factum operations on existing traces. */
553
- constructor(baseHttpUrl: string, projectApiKey: string);
597
+ constructor(baseHttpUrl: string, auth: LaminarAuth);
554
598
  /**
555
599
  * Push a metadata patch to an existing trace.
556
600
  *
@@ -608,8 +652,9 @@ declare class TracesResource extends BaseResource {
608
652
  //#region src/index.d.ts
609
653
  declare class LaminarClient {
610
654
  private baseUrl;
611
- private projectApiKey;
655
+ private auth;
612
656
  private _browserEvents;
657
+ private _cli;
613
658
  private _datasets;
614
659
  private _evals;
615
660
  private _evaluators;
@@ -619,14 +664,45 @@ declare class LaminarClient {
619
664
  private _traces;
620
665
  constructor({
621
666
  baseUrl,
667
+ port,
668
+ auth,
622
669
  projectApiKey,
623
- port
670
+ cliUserProjectId
624
671
  }?: {
625
672
  baseUrl?: string;
626
- projectApiKey?: string;
627
673
  port?: number;
674
+ /**
675
+ * Unified auth. A discriminated union that drives both the URL prefix and
676
+ * the request headers:
677
+ * - `{ type: "apiKey", key }` → project key, `/v1/*`.
678
+ * - `{ type: "userToken", token, projectId }` → user JWT, `/v1/cli/*` with
679
+ * `x-lmnr-project-id`.
680
+ * When omitted, the legacy `projectApiKey` / `cliUserProjectId` fields (or
681
+ * `LMNR_PROJECT_API_KEY`) are normalized into this union.
682
+ */
683
+ auth?: LaminarAuth;
684
+ /**
685
+ * @deprecated Pass `auth: { type: "apiKey", key }` instead. Kept for
686
+ * backward compatibility — normalized into the unified `auth` union.
687
+ */
688
+ projectApiKey?: string;
689
+ /**
690
+ * @deprecated Pass `auth: { type: "userToken", token, projectId }` instead.
691
+ * Kept for backward compatibility: when set, the legacy `projectApiKey` is
692
+ * treated as a user JWT and routes to `/v1/cli/*` with this project id.
693
+ */
694
+ cliUserProjectId?: string;
628
695
  });
696
+ /**
697
+ * Normalize the constructor's auth inputs into a {@link LaminarAuth} union.
698
+ * Precedence: an explicit `auth` wins; otherwise the legacy
699
+ * `projectApiKey` (+ optional `cliUserProjectId`) is mapped — a present
700
+ * `cliUserProjectId` selects the user-token surface, otherwise the project
701
+ * key surface. Falls back to `LMNR_PROJECT_API_KEY` as a project key.
702
+ */
703
+ private static normalizeAuth;
629
704
  get browserEvents(): BrowserEventsResource;
705
+ get cli(): CliResource;
630
706
  get datasets(): DatasetsResource;
631
707
  get evals(): EvalsResource;
632
708
  get evaluators(): EvaluatorsResource;
@@ -31159,4 +31235,4 @@ declare function evaluate<D, T, O>({
31159
31235
  }: EvaluationConstructorProps<D, T, O>): Promise<EvaluationRunResult | undefined>;
31160
31236
  //#endregion
31161
31237
  export { TracingLevel as S, MaskInputOptions as _, HumanEvaluator as a, SpanType as b, InitializeOptions as c, LaminarClient as d, Dataset as f, LaminarSpanContext as g, Event as h, EvaluatorFunctionReturn as i, EvaluationDataset as l, EvaluationDatapointDatasetLink as m, Evaluation as n, evaluate as o, EvaluationDatapoint as p, EvaluatorFunction as r, StringUUID as s, Datapoint as t, LaminarDataset as u, PushDatapointsResponse as v, TraceType as x, SessionRecordingOptions as y };
31162
- //# sourceMappingURL=evaluations-Cs-tqViJ.d.mts.map
31238
+ //# sourceMappingURL=evaluations-fF1Y_olL.d.mts.map
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk-BN4qSVkS.cjs");
3
3
  const require_utils = require("./utils-C_Pf3r64.cjs");
4
- const require_dist = require("./dist-BWFjum5L.cjs");
4
+ const require_dist = require("./dist-Cyli7uVF.cjs");
5
5
  const require_consts = require("./consts-Cx9iKRmq.cjs");
6
6
  let _opentelemetry_api = require("@opentelemetry/api");
7
7
  let _opentelemetry_context_async_hooks = require("@opentelemetry/context-async-hooks");
@@ -5627,16 +5627,18 @@ const buildHeaders = (existing) => {
5627
5627
  * Read `laminar-span-context` (preferred) or `traceparent` (fallback) from
5628
5628
  * Temporal headers and push the restored context onto Laminar's ALS stack.
5629
5629
  *
5630
- * Returns the restored `LaminarSpanContext` or `undefined` if headers contain
5631
- * no usable trace context.
5630
+ * Returns the restored context (Laminar + OTel) or `undefined` if headers
5631
+ * contain no usable trace context.
5632
5632
  */
5633
5633
  const restoreContextFromHeaders = (headers) => {
5634
5634
  if (!headers) return void 0;
5635
5635
  const laminarRaw = decodePayload(headers[require_consts.LAMINAR_SPAN_CONTEXT_HEADER]);
5636
5636
  if (laminarRaw) try {
5637
5637
  const ctx = require_utils.deserializeLaminarSpanContext(laminarRaw);
5638
- pushLaminarContext(ctx);
5639
- return ctx;
5638
+ return {
5639
+ laminarCtx: ctx,
5640
+ otelContext: pushLaminarContext(ctx)
5641
+ };
5640
5642
  } catch (e) {
5641
5643
  logger$8.warn(`[Laminar] Could not restore ${require_consts.LAMINAR_SPAN_CONTEXT_HEADER}: ${require_utils.errorMessage(e)}`);
5642
5644
  }
@@ -5651,15 +5653,20 @@ const restoreContextFromHeaders = (headers) => {
5651
5653
  spanId: require_utils.otelSpanIdToUUID(spanHex),
5652
5654
  isRemote: true
5653
5655
  };
5654
- pushLaminarContext(ctx);
5655
- return ctx;
5656
+ return {
5657
+ laminarCtx: ctx,
5658
+ otelContext: pushLaminarContext(ctx)
5659
+ };
5656
5660
  } catch (e) {
5657
5661
  logger$8.warn(`[Laminar] Could not restore traceparent: ${require_utils.errorMessage(e)}`);
5658
5662
  }
5659
5663
  }
5660
5664
  }
5661
5665
  };
5662
- /** Push a LaminarSpanContext onto the Laminar ALS stack as a remote parent. */
5666
+ /**
5667
+ * Push a LaminarSpanContext onto the Laminar ALS stack as a remote parent and
5668
+ * return the enriched OTel `Context` that was pushed.
5669
+ */
5663
5670
  const pushLaminarContext = (laminarCtx) => {
5664
5671
  const otelCtx = require_utils.tryToOtelSpanContext(laminarCtx);
5665
5672
  otelCtx.isRemote = true;
@@ -5668,6 +5675,7 @@ const pushLaminarContext = (laminarCtx) => {
5668
5675
  const base = _opentelemetry_api.trace.setSpan(_opentelemetry_api.ROOT_CONTEXT, _opentelemetry_api.trace.wrapSpanContext(otelCtx));
5669
5676
  const enriched = LaminarContextManager.setRawAssociationProperties(laminarCtx, base);
5670
5677
  LaminarContextManager.pushContext(enriched);
5678
+ return enriched;
5671
5679
  };
5672
5680
  //#endregion
5673
5681
  //#region src/opentelemetry-lib/instrumentation/temporal/interceptors.ts
@@ -5815,12 +5823,13 @@ var ActivityClientInterceptor = class {
5815
5823
  var ActivityInboundInterceptor = class {
5816
5824
  constructor(options = {}, activityContext) {
5817
5825
  this.execute = async (input, next) => LaminarContextManager.runWithIsolatedContext([_opentelemetry_api.ROOT_CONTEXT], async () => {
5818
- const restoredCtx = restoreContextFromHeaders(input.headers);
5819
- if (!this.createActivitySpan || !restoredCtx) return next(input);
5826
+ const restored = restoreContextFromHeaders(input.headers);
5827
+ if (!restored) return next(input);
5828
+ if (!this.createActivitySpan) return _opentelemetry_api.context.with(restored.otelContext, () => next(input));
5820
5829
  const activityName = this.activityType ?? "temporal.activity";
5821
5830
  const span = Laminar.startSpan({
5822
5831
  name: activityName,
5823
- parentSpanContext: restoredCtx,
5832
+ parentSpanContext: restored.laminarCtx,
5824
5833
  input: this.recordActivityArgs ? input.args : void 0
5825
5834
  });
5826
5835
  return Laminar.withSpan(span, async () => {
@@ -8101,7 +8110,7 @@ const applyUsage = (attributes, usage) => {
8101
8110
  };
8102
8111
  const standardizedPromptToMessages = (event) => {
8103
8112
  const messages = [];
8104
- const sys = event.system;
8113
+ const sys = event.instructions || event.system;
8105
8114
  if (typeof sys === "string" && sys.length > 0) messages.push({
8106
8115
  role: "system",
8107
8116
  content: sys
@@ -8241,7 +8250,7 @@ var LaminarAiSdkTelemetry = class {
8241
8250
  if (typeof event.functionId === "string") span.setAttribute("ai.functionId", event.functionId);
8242
8251
  if (event.operationId === "ai.embed" || event.operationId === "ai.embedMany" || event.operationId === "ai.rerank") span.setAttribute(require_utils.SPAN_TYPE, "LLM");
8243
8252
  if (this.recordInputs) {
8244
- if (Array.isArray(event.messages) || event.system !== void 0) applyPromptMessages(span, event);
8253
+ if (Array.isArray(event.messages) || event.system !== void 0 || event.instructions !== void 0) applyPromptMessages(span, event);
8245
8254
  else if (event.value !== void 0) span.setAttribute(require_utils.SPAN_INPUT, serializeJSON$1(event.value));
8246
8255
  else if (event.query !== void 0 || event.documents !== void 0) span.setAttribute(require_utils.SPAN_INPUT, serializeJSON$1({
8247
8256
  query: event.query,
@@ -8257,6 +8266,7 @@ var LaminarAiSdkTelemetry = class {
8257
8266
  });
8258
8267
  };
8259
8268
  this.onStepStart = (event) => {
8269
+ if (!this.createStepSpan) return;
8260
8270
  const callId = event?.callId;
8261
8271
  const stepNumber = event?.stepNumber ?? 0;
8262
8272
  if (!callId) return;
@@ -8277,9 +8287,9 @@ var LaminarAiSdkTelemetry = class {
8277
8287
  const callId = event?.callId;
8278
8288
  if (!callId) return;
8279
8289
  const step = this.findLatestStep(callId);
8290
+ const stepNumber = step?.stepNumber ?? event?.stepNumber ?? 0;
8280
8291
  const parentCtx = step?.ctx ?? this.operationByCallId.get(callId)?.ctx;
8281
8292
  if (!parentCtx) return;
8282
- const stepNumber = step?.stepNumber ?? 0;
8283
8293
  const span = getTracer().startSpan(`ai.llm ${event.provider ?? ""}:${event.modelId ?? ""}`, { kind: _opentelemetry_api.SpanKind.CLIENT }, parentCtx);
8284
8294
  span.setAttribute(require_utils.SPAN_TYPE, "LLM");
8285
8295
  applyRequestModelAttributes(span, event);
@@ -8293,7 +8303,7 @@ var LaminarAiSdkTelemetry = class {
8293
8303
  this.onLanguageModelCallEnd = (event) => {
8294
8304
  const callId = event?.callId;
8295
8305
  if (!callId) return;
8296
- const stepNumber = this.findLatestStep(callId)?.stepNumber ?? 0;
8306
+ const stepNumber = this.findLatestStep(callId)?.stepNumber ?? event?.stepNumber ?? 0;
8297
8307
  const llm = this.llmByKey.get(stepKey(callId, stepNumber));
8298
8308
  if (!llm) return;
8299
8309
  const span = llm.span;
@@ -8343,8 +8353,6 @@ var LaminarAiSdkTelemetry = class {
8343
8353
  const stepNumber = event?.stepNumber ?? 0;
8344
8354
  if (!callId) return;
8345
8355
  const key = stepKey(callId, stepNumber);
8346
- const step = this.stepByKey.get(key);
8347
- if (!step) return;
8348
8356
  const llm = this.llmByKey.get(key);
8349
8357
  if (llm) {
8350
8358
  if (this.recordOutputs && llm.textDeltas.length > 0) {
@@ -8355,6 +8363,8 @@ var LaminarAiSdkTelemetry = class {
8355
8363
  removeActiveLlmSpan(llm.span);
8356
8364
  this.llmByKey.delete(key);
8357
8365
  }
8366
+ const step = this.stepByKey.get(key);
8367
+ if (!step) return;
8358
8368
  applyUsageToSpan(step.span, event.usage);
8359
8369
  if (typeof event.finishReason === "string") applyFinishReason(step.span, event.finishReason);
8360
8370
  if (this.recordOutputs) {
@@ -8563,6 +8573,7 @@ var LaminarAiSdkTelemetry = class {
8563
8573
  };
8564
8574
  this.recordInputs = options.recordInputs ?? true;
8565
8575
  this.recordOutputs = options.recordOutputs ?? true;
8576
+ this.createStepSpan = options.createStepSpan ?? false;
8566
8577
  }
8567
8578
  /** End child spans, end the operation span, and clean up both maps. */
8568
8579
  closeOperation(callId, op) {