@lmnr-ai/client 0.8.54 → 0.8.55

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
@@ -29,7 +29,7 @@ let pino_pretty = require("pino-pretty");
29
29
  let uuid = require("uuid");
30
30
  let _lmnr_ai_types = require("@lmnr-ai/types");
31
31
  // package.json
32
- var version = "0.8.54";
32
+ var version = "0.8.55";
33
33
  // src/version.ts
34
34
  function getLangVersion() {
35
35
  if (typeof process !== "undefined" && process.versions && process.versions.node) return `node-${process.versions.node}`;
@@ -59,6 +59,20 @@ var BaseResource = class {
59
59
  const errorMsg = await response.text();
60
60
  throw new Error(`${response.status} ${errorMsg}`);
61
61
  }
62
+ /**
63
+ * For routes that answer errors as `{error: "<message>"}` with user-facing
64
+ * text: raise that message instead of the raw JSON body, falling back to the
65
+ * body when it isn't that shape (a proxy error page, a plain-text 413).
66
+ */
67
+ async handleErrorMessage(response) {
68
+ const body = await response.text();
69
+ let message = body;
70
+ try {
71
+ const parsed = JSON.parse(body);
72
+ if (typeof parsed?.error === "string" && parsed.error.length > 0) message = parsed.error;
73
+ } catch {}
74
+ throw new Error(`${response.status} ${message}`);
75
+ }
62
76
  };
63
77
  // src/resources/browser-events.ts
64
78
  var BrowserEventsResource = class extends BaseResource {
@@ -616,6 +630,90 @@ var EvaluatorsResource = class extends BaseResource {
616
630
  if (!response.ok) await this.handleError(response);
617
631
  }
618
632
  };
633
+ // src/resources/hosted-evals.ts
634
+ /**
635
+ * Hosted evals: Harbor evals with trials in Laminar-managed sandboxes.
636
+ *
637
+ * - Images: `missingLayers` / `uploadLayer` / `createImage` push an image built
638
+ * locally (layers named by their `diff_id`); trials start from it.
639
+ * - Remote runs: `upload` the `.tar.gz` of the evals folder, then `startRun`
640
+ * to orchestrate it in a Laminar sandbox. Results land in the project as
641
+ * regular evaluations; v0 returns no run status.
642
+ */
643
+ var HostedEvalsResource = class extends BaseResource {
644
+ constructor(baseHttpUrl, auth) {
645
+ super(baseHttpUrl, auth);
646
+ }
647
+ /** The image layers (by `diff_id`) the project hasn't uploaded yet. */
648
+ async missingLayers(diffIds) {
649
+ const response = await fetch(this.url("/images/layers/missing"), {
650
+ method: "POST",
651
+ headers: this.headers(),
652
+ body: JSON.stringify({ diffIds })
653
+ });
654
+ if (!response.ok) await this.handleErrorMessage(response);
655
+ return (await response.json()).missing;
656
+ }
657
+ /**
658
+ * Upload one image layer, gzip-compressed. `diffId` is the digest of its
659
+ * uncompressed tar, as listed in the image config's `rootfs.diff_ids`.
660
+ */
661
+ async uploadLayer(diffId, gzipped) {
662
+ const response = await fetch(this.url(`/images/layers/${diffId}`), {
663
+ method: "PUT",
664
+ headers: {
665
+ ...this.headers(),
666
+ "Content-Type": "application/gzip"
667
+ },
668
+ body: gzipped,
669
+ duplex: "half"
670
+ });
671
+ if (!response.ok) await this.handleErrorMessage(response);
672
+ return await response.json();
673
+ }
674
+ /**
675
+ * Push the image described by `config` (its config JSON, byte for byte) once
676
+ * its layers are uploaded. Returns the manifest digest trials start from.
677
+ */
678
+ async createImage(config) {
679
+ const response = await fetch(this.url("/images"), {
680
+ method: "POST",
681
+ headers: this.headers(),
682
+ body: JSON.stringify({ config })
683
+ });
684
+ if (!response.ok) await this.handleErrorMessage(response);
685
+ return await response.json();
686
+ }
687
+ /**
688
+ * Upload a `.tar.gz` of the `evals/` folder's contents (suites at the archive
689
+ * root). Sent as the raw request body; the server caps it at 1 GiB.
690
+ */
691
+ async upload(archive) {
692
+ const response = await fetch(this.url("/uploads"), {
693
+ method: "POST",
694
+ headers: {
695
+ ...this.headers(),
696
+ "Content-Type": "application/gzip"
697
+ },
698
+ body: archive
699
+ });
700
+ if (!response.ok) await this.handleErrorMessage(response);
701
+ return await response.json();
702
+ }
703
+ /** Start a remote run. Returns once its orchestrator sandbox has started. */
704
+ async startRun(options) {
705
+ const response = await fetch(this.url("/runs"), {
706
+ method: "POST",
707
+ headers: this.headers(),
708
+ body: JSON.stringify(options)
709
+ });
710
+ if (!response.ok) await this.handleErrorMessage(response);
711
+ return await response.json();
712
+ }
713
+ url(path) {
714
+ return `${this.baseHttpUrl}${this.apiPrefix}/hosted-evals${path}`;
715
+ }
716
+ };
619
717
  // src/resources/llm-profiles.ts
620
718
  /**
621
719
  * Workspace LLM profile CRUD over the CLI user-token surface
@@ -627,27 +725,13 @@ var LlmProfilesResource = class extends BaseResource {
627
725
  constructor(baseHttpUrl, auth) {
628
726
  super(baseHttpUrl, auth);
629
727
  }
630
- /**
631
- * Errors come back as `{error: string}` (matches the signals surface) with
632
- * user-facing text, so unwrap the envelope before raising rather than
633
- * showing the raw JSON body.
634
- */
635
- async raiseLlmProfileError(response) {
636
- const body = await response.text();
637
- let message = body;
638
- try {
639
- const parsed = JSON.parse(body);
640
- if (typeof parsed?.error === "string" && parsed.error.length > 0) message = parsed.error;
641
- } catch {}
642
- throw new Error(`${response.status} ${message}`);
643
- }
644
728
  async request(method, path, body) {
645
729
  const response = await fetch(`${this.baseHttpUrl}${this.apiPrefix}/llm-profiles${path}`, {
646
730
  method,
647
731
  headers: this.headers(),
648
732
  ...body !== void 0 ? { body: JSON.stringify(body) } : {}
649
733
  });
650
- if (!response.ok) await this.raiseLlmProfileError(response);
734
+ if (!response.ok) await this.handleErrorMessage(response);
651
735
  return response;
652
736
  }
653
737
  /**
@@ -865,34 +949,22 @@ var RolloutSessionsResource = class extends BaseResource {
865
949
  }
866
950
  };
867
951
  // src/resources/signals.ts
868
- /** Signals CRUD over the CLI user-token surface (`/v1/cli/signals`). */
952
+ /**
953
+ * Signals CRUD over the CLI user-token surface (`/v1/cli/signals`). Errors come
954
+ * back as `{error}` with user-facing text (e.g. "A signal named X already
955
+ * exists in this project"), raised verbatim by `handleErrorMessage`.
956
+ */
869
957
  var SignalsResource = class extends BaseResource {
870
958
  constructor(baseHttpUrl, auth) {
871
959
  super(baseHttpUrl, auth);
872
960
  }
873
- /**
874
- * Every signal route answers errors as `{ error: "<message>" }`, and those
875
- * messages are written to be shown to the user verbatim (e.g. "A signal named
876
- * X already exists in this project"). The shared `handleError` would surface
877
- * the raw JSON body, so unwrap the envelope here and fall back to it when the
878
- * body isn't the expected shape.
879
- */
880
- async raiseSignalError(response) {
881
- const body = await response.text();
882
- let message = body;
883
- try {
884
- const parsed = JSON.parse(body);
885
- if (typeof parsed?.error === "string" && parsed.error.length > 0) message = parsed.error;
886
- } catch {}
887
- throw new Error(`${response.status} ${message}`);
888
- }
889
961
  async list(name) {
890
962
  const query = name ? `?${new URLSearchParams({ name }).toString()}` : "";
891
963
  const response = await fetch(`${this.baseHttpUrl}${this.apiPrefix}/signals${query}`, {
892
964
  method: "GET",
893
965
  headers: this.headers()
894
966
  });
895
- if (!response.ok) await this.raiseSignalError(response);
967
+ if (!response.ok) await this.handleErrorMessage(response);
896
968
  const body = await response.json();
897
969
  return Array.isArray(body?.signals) ? body.signals : [];
898
970
  }
@@ -901,7 +973,7 @@ var SignalsResource = class extends BaseResource {
901
973
  method: "GET",
902
974
  headers: this.headers()
903
975
  });
904
- if (!response.ok) await this.raiseSignalError(response);
976
+ if (!response.ok) await this.handleErrorMessage(response);
905
977
  return response.json();
906
978
  }
907
979
  /**
@@ -915,7 +987,7 @@ var SignalsResource = class extends BaseResource {
915
987
  method: "GET",
916
988
  headers: this.headers()
917
989
  });
918
- if (!response.ok) await this.raiseSignalError(response);
990
+ if (!response.ok) await this.handleErrorMessage(response);
919
991
  const body = await response.json();
920
992
  return Array.isArray(body?.versions) ? body.versions : [];
921
993
  }
@@ -925,7 +997,7 @@ var SignalsResource = class extends BaseResource {
925
997
  headers: this.headers(),
926
998
  body: JSON.stringify(options)
927
999
  });
928
- if (!response.ok) await this.raiseSignalError(response);
1000
+ if (!response.ok) await this.handleErrorMessage(response);
929
1001
  return response.json();
930
1002
  }
931
1003
  /**
@@ -939,7 +1011,7 @@ var SignalsResource = class extends BaseResource {
939
1011
  headers: this.headers(),
940
1012
  body: JSON.stringify(options)
941
1013
  });
942
- if (!response.ok) await this.raiseSignalError(response);
1014
+ if (!response.ok) await this.handleErrorMessage(response);
943
1015
  return response.json();
944
1016
  }
945
1017
  /** Deletes the signal, its triggers, its alerts, and its ClickHouse events. */
@@ -948,7 +1020,7 @@ var SignalsResource = class extends BaseResource {
948
1020
  method: "DELETE",
949
1021
  headers: this.headers()
950
1022
  });
951
- if (!response.ok) await this.raiseSignalError(response);
1023
+ if (!response.ok) await this.handleErrorMessage(response);
952
1024
  return response.json();
953
1025
  }
954
1026
  /**
@@ -962,7 +1034,7 @@ var SignalsResource = class extends BaseResource {
962
1034
  headers: this.headers(),
963
1035
  body: JSON.stringify({ traceIds })
964
1036
  });
965
- if (!response.ok) await this.raiseSignalError(response);
1037
+ if (!response.ok) await this.handleErrorMessage(response);
966
1038
  return response.json();
967
1039
  }
968
1040
  };
@@ -1147,6 +1219,7 @@ var LaminarClient = class LaminarClient {
1147
1219
  this._datasets = new DatasetsResource(this.baseUrl, this.auth);
1148
1220
  this._evals = new EvalsResource(this.baseUrl, this.auth);
1149
1221
  this._evaluators = new EvaluatorsResource(this.baseUrl, this.auth);
1222
+ this._hostedEvals = new HostedEvalsResource(this.baseUrl, this.auth);
1150
1223
  this._llmProfiles = new LlmProfilesResource(this.baseUrl, this.auth);
1151
1224
  this._rolloutSessions = new RolloutSessionsResource(this.baseUrl, this.auth);
1152
1225
  this._signals = new SignalsResource(this.baseUrl, this.auth);
@@ -1218,6 +1291,9 @@ var LaminarClient = class LaminarClient {
1218
1291
  get evaluators() {
1219
1292
  return this._evaluators;
1220
1293
  }
1294
+ get hostedEvals() {
1295
+ return this._hostedEvals;
1296
+ }
1221
1297
  get llmProfiles() {
1222
1298
  return this._llmProfiles;
1223
1299
  }