@langfuse/core 4.0.0-beta.4 → 4.0.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -32,6 +32,7 @@ __export(index_exports, {
32
32
  LangfuseAPIClient: () => LangfuseAPIClient,
33
33
  LangfuseAPIError: () => LangfuseAPIError,
34
34
  LangfuseAPITimeoutError: () => LangfuseAPITimeoutError,
35
+ LangfuseMedia: () => LangfuseMedia,
35
36
  LangfuseOtelSpanAttributes: () => LangfuseOtelSpanAttributes,
36
37
  LogLevel: () => LogLevel,
37
38
  Logger: () => Logger,
@@ -47,6 +48,10 @@ __export(index_exports, {
47
48
  ServiceUnavailableError: () => ServiceUnavailableError,
48
49
  UnauthorizedError: () => UnauthorizedError,
49
50
  annotationQueues: () => annotationQueues_exports,
51
+ base64Decode: () => base64Decode,
52
+ base64Encode: () => base64Encode,
53
+ base64ToBytes: () => base64ToBytes,
54
+ bytesToBase64: () => bytesToBase64,
50
55
  comments: () => comments_exports,
51
56
  commons: () => commons_exports,
52
57
  configureGlobalLogger: () => configureGlobalLogger,
@@ -76,7 +81,6 @@ __export(index_exports, {
76
81
  scoreV2: () => scoreV2_exports,
77
82
  sessions: () => sessions_exports,
78
83
  trace: () => trace_exports,
79
- uint8ArrayToBase64: () => uint8ArrayToBase64,
80
84
  utils: () => utils_exports
81
85
  });
82
86
  module.exports = __toCommonJS(index_exports);
@@ -112,14 +116,29 @@ function safeSetTimeout(fn, timeout) {
112
116
  }
113
117
  return t;
114
118
  }
115
- function uint8ArrayToBase64(arr) {
119
+ function base64ToBytes(base64) {
120
+ const binString = atob(base64);
121
+ return Uint8Array.from(binString, (m) => m.codePointAt(0));
122
+ }
123
+ function bytesToBase64(bytes) {
124
+ const binString = Array.from(bytes, (byte) => String.fromCharCode(byte)).join(
125
+ ""
126
+ );
127
+ return btoa(binString);
128
+ }
129
+ function base64Encode(input) {
116
130
  if (typeof Buffer !== "undefined") {
117
- return Buffer.from(arr).toString("base64");
131
+ return Buffer.from(input, "utf8").toString("base64");
118
132
  }
119
- if (typeof btoa !== "undefined") {
120
- return btoa(String.fromCharCode(...arr));
133
+ const bytes = new TextEncoder().encode(input);
134
+ return bytesToBase64(bytes);
135
+ }
136
+ function base64Decode(input) {
137
+ if (typeof Buffer !== "undefined") {
138
+ return Buffer.from(input, "base64").toString("utf8");
121
139
  }
122
- throw new Error("Base64 encoding not available");
140
+ const bytes = base64ToBytes(input);
141
+ return new TextDecoder().decode(bytes);
123
142
  }
124
143
 
125
144
  // src/logger/index.ts
@@ -297,7 +316,7 @@ var resetGlobalLogger = () => {
297
316
  // package.json
298
317
  var package_default = {
299
318
  name: "@langfuse/core",
300
- version: "4.0.0-beta.4",
319
+ version: "4.0.0-beta.6",
301
320
  description: "Core functions and utilities for Langfuse packages",
302
321
  type: "module",
303
322
  sideEffects: false,
@@ -1364,26 +1383,26 @@ function trimSlashes(str) {
1364
1383
  }
1365
1384
 
1366
1385
  // src/api/core/base64.ts
1367
- function base64ToBytes(base64) {
1386
+ function base64ToBytes2(base64) {
1368
1387
  const binString = atob(base64);
1369
1388
  return Uint8Array.from(binString, (m) => m.codePointAt(0));
1370
1389
  }
1371
- function bytesToBase64(bytes) {
1390
+ function bytesToBase642(bytes) {
1372
1391
  const binString = String.fromCodePoint(...bytes);
1373
1392
  return btoa(binString);
1374
1393
  }
1375
- function base64Encode(input) {
1394
+ function base64Encode2(input) {
1376
1395
  if (typeof Buffer !== "undefined") {
1377
1396
  return Buffer.from(input, "utf8").toString("base64");
1378
1397
  }
1379
1398
  const bytes = new TextEncoder().encode(input);
1380
- return bytesToBase64(bytes);
1399
+ return bytesToBase642(bytes);
1381
1400
  }
1382
- function base64Decode(input) {
1401
+ function base64Decode2(input) {
1383
1402
  if (typeof Buffer !== "undefined") {
1384
1403
  return Buffer.from(input, "base64").toString("utf8");
1385
1404
  }
1386
- const bytes = base64ToBytes(input);
1405
+ const bytes = base64ToBytes2(input);
1387
1406
  return new TextDecoder().decode(bytes);
1388
1407
  }
1389
1408
 
@@ -1394,12 +1413,12 @@ var BasicAuth = {
1394
1413
  if (basicAuth == null) {
1395
1414
  return void 0;
1396
1415
  }
1397
- const token = base64Encode(`${basicAuth.username}:${basicAuth.password}`);
1416
+ const token = base64Encode2(`${basicAuth.username}:${basicAuth.password}`);
1398
1417
  return `Basic ${token}`;
1399
1418
  },
1400
1419
  fromAuthorizationHeader: (header) => {
1401
1420
  const credentials = header.replace(BASIC_AUTH_HEADER_PREFIX, "");
1402
- const decoded = base64Decode(credentials);
1421
+ const decoded = base64Decode2(credentials);
1403
1422
  const [username, password] = decoded.split(":", 2);
1404
1423
  if (username == null || password == null) {
1405
1424
  throw new Error("Invalid basic auth");
@@ -9626,6 +9645,168 @@ var LangfuseAPIClient = class {
9626
9645
  return (_a2 = this._trace) != null ? _a2 : this._trace = new Trace(this._options);
9627
9646
  }
9628
9647
  };
9648
+
9649
+ // src/media.ts
9650
+ var LangfuseMedia = class {
9651
+ /**
9652
+ * Creates a new LangfuseMedia instance.
9653
+ *
9654
+ * @param params - Media parameters specifying the source and content
9655
+ *
9656
+ * @example
9657
+ * ```typescript
9658
+ * // Create from base64 data URI
9659
+ * const media = new LangfuseMedia({
9660
+ * source: "base64_data_uri",
9661
+ * base64DataUri: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ..."
9662
+ * });
9663
+ * ```
9664
+ */
9665
+ constructor(params) {
9666
+ const { source } = params;
9667
+ this._source = source;
9668
+ if (source === "base64_data_uri") {
9669
+ const [contentBytesParsed, contentTypeParsed] = this.parseBase64DataUri(
9670
+ params.base64DataUri
9671
+ );
9672
+ this._contentBytes = contentBytesParsed;
9673
+ this._contentType = contentTypeParsed;
9674
+ } else {
9675
+ this._contentBytes = params.contentBytes;
9676
+ this._contentType = params.contentType;
9677
+ }
9678
+ }
9679
+ /**
9680
+ * Parses a base64 data URI to extract content bytes and type.
9681
+ *
9682
+ * @param data - The base64 data URI string
9683
+ * @returns Tuple of [contentBytes, contentType] or [undefined, undefined] on error
9684
+ * @private
9685
+ */
9686
+ parseBase64DataUri(data) {
9687
+ try {
9688
+ if (!data || typeof data !== "string") {
9689
+ throw new Error("Data URI is not a string");
9690
+ }
9691
+ if (!data.startsWith("data:")) {
9692
+ throw new Error("Data URI does not start with 'data:'");
9693
+ }
9694
+ const [header, actualData] = data.slice(5).split(",", 2);
9695
+ if (!header || !actualData) {
9696
+ throw new Error("Invalid URI");
9697
+ }
9698
+ const headerParts = header.split(";");
9699
+ if (!headerParts.includes("base64")) {
9700
+ throw new Error("Data is not base64 encoded");
9701
+ }
9702
+ const contentType = headerParts[0];
9703
+ if (!contentType) {
9704
+ throw new Error("Content type is empty");
9705
+ }
9706
+ return [base64ToBytes(actualData), contentType];
9707
+ } catch (error) {
9708
+ getGlobalLogger().error("Error parsing base64 data URI", error);
9709
+ return [void 0, void 0];
9710
+ }
9711
+ }
9712
+ /**
9713
+ * Gets a unique identifier for this media based on its content hash.
9714
+ *
9715
+ * The ID is derived from the first 22 characters of the URL-safe base64-encoded
9716
+ * SHA-256 hash of the content.
9717
+ *
9718
+ * @returns The unique media ID, or null if hash generation failed
9719
+ *
9720
+ * @example
9721
+ * ```typescript
9722
+ * const media = new LangfuseMedia({...});
9723
+ * console.log(media.id); // "A1B2C3D4E5F6G7H8I9J0K1"
9724
+ * ```
9725
+ */
9726
+ async getId() {
9727
+ const contentSha256Hash = await this.getSha256Hash();
9728
+ if (!contentSha256Hash) return null;
9729
+ const urlSafeContentHash = contentSha256Hash.replaceAll("+", "-").replaceAll("/", "_");
9730
+ return urlSafeContentHash.slice(0, 22);
9731
+ }
9732
+ /**
9733
+ * Gets the length of the media content in bytes.
9734
+ *
9735
+ * @returns The content length in bytes, or undefined if no content is available
9736
+ */
9737
+ get contentLength() {
9738
+ var _a2;
9739
+ return (_a2 = this._contentBytes) == null ? void 0 : _a2.length;
9740
+ }
9741
+ /**
9742
+ * Gets the SHA-256 hash of the media content.
9743
+ *
9744
+ * The hash is used for content integrity verification and generating unique media IDs.
9745
+ * Returns undefined if crypto is not available or hash generation fails.
9746
+ *
9747
+ * @returns The base64-encoded SHA-256 hash, or undefined if unavailable
9748
+ */
9749
+ async getSha256Hash() {
9750
+ if (!this._contentBytes) {
9751
+ return void 0;
9752
+ }
9753
+ try {
9754
+ const hash = await crypto.subtle.digest("SHA-256", this._contentBytes);
9755
+ return bytesToBase64(new Uint8Array(hash));
9756
+ } catch (error) {
9757
+ getGlobalLogger().warn(
9758
+ "[Langfuse] Failed to generate SHA-256 hash for media content:",
9759
+ error
9760
+ );
9761
+ return void 0;
9762
+ }
9763
+ }
9764
+ /**
9765
+ * Gets the media reference tag for embedding in trace data.
9766
+ *
9767
+ * The tag format is: `@@@langfuseMedia:type=<contentType>|id=<mediaId>|source=<source>@@@`
9768
+ * This tag can be embedded in trace attributes and will be replaced with actual
9769
+ * media content when the trace is viewed in Langfuse.
9770
+ *
9771
+ * @returns The media reference tag, or null if required data is missing
9772
+ *
9773
+ * @example
9774
+ * ```typescript
9775
+ * const media = new LangfuseMedia({...});
9776
+ * console.log(media.tag);
9777
+ * // "@@@langfuseMedia:type=image/png|id=A1B2C3D4E5F6G7H8I9J0K1|source=base64_data_uri@@@"
9778
+ * ```
9779
+ */
9780
+ async getTag() {
9781
+ const id = await this.getId();
9782
+ if (!this._contentType || !this._source || !id) return null;
9783
+ return `@@@langfuseMedia:type=${this._contentType}|id=${id}|source=${this._source}@@@`;
9784
+ }
9785
+ /**
9786
+ * Gets the media content as a base64 data URI.
9787
+ *
9788
+ * @returns The complete data URI string, or null if no content is available
9789
+ *
9790
+ * @example
9791
+ * ```typescript
9792
+ * const media = new LangfuseMedia({...});
9793
+ * console.log(media.base64DataUri);
9794
+ * // "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB..."
9795
+ * ```
9796
+ */
9797
+ get base64DataUri() {
9798
+ if (!this._contentBytes) return null;
9799
+ return `data:${this._contentType};base64,${bytesToBase64(this._contentBytes)}`;
9800
+ }
9801
+ /**
9802
+ * Serializes the media to JSON (returns the base64 data URI).
9803
+ *
9804
+ * @returns The base64 data URI, or null if no content is available
9805
+ */
9806
+ toJSON() {
9807
+ return this.base64DataUri;
9808
+ }
9809
+ };
9629
9810
  // Annotate the CommonJS export names for ESM import in node:
9630
9811
  0 && (module.exports = {
9631
9812
  AccessDeniedError,
@@ -9640,6 +9821,7 @@ var LangfuseAPIClient = class {
9640
9821
  LangfuseAPIClient,
9641
9822
  LangfuseAPIError,
9642
9823
  LangfuseAPITimeoutError,
9824
+ LangfuseMedia,
9643
9825
  LangfuseOtelSpanAttributes,
9644
9826
  LogLevel,
9645
9827
  Logger,
@@ -9655,6 +9837,10 @@ var LangfuseAPIClient = class {
9655
9837
  ServiceUnavailableError,
9656
9838
  UnauthorizedError,
9657
9839
  annotationQueues,
9840
+ base64Decode,
9841
+ base64Encode,
9842
+ base64ToBytes,
9843
+ bytesToBase64,
9658
9844
  comments,
9659
9845
  commons,
9660
9846
  configureGlobalLogger,
@@ -9684,7 +9870,6 @@ var LangfuseAPIClient = class {
9684
9870
  scoreV2,
9685
9871
  sessions,
9686
9872
  trace,
9687
- uint8ArrayToBase64,
9688
9873
  utils
9689
9874
  });
9690
9875
  //# sourceMappingURL=index.cjs.map