pareta 0.2.1 → 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/README.md CHANGED
@@ -69,22 +69,11 @@ const res = await client.chat.completions.create({ model: "auto", messages: [...
69
69
  ```
70
70
 
71
71
  This SDK's unique value is everything AROUND that call — evals on your data,
72
- auto metrics, the benchmark catalog, and the dedicated-endpoint control plane.
72
+ auto metrics, and the benchmark catalog.
73
73
 
74
- ## Dedicated endpoints (when you want to pin one model)
75
-
76
- `"auto"` routes per request. When a workload wants one specific open model on
77
- dedicated capacity, deploy it and call it by endpoint id:
78
-
79
- ```ts
80
- const ep = await pa.endpoints.deploy({ task: "invoice-extraction", model: "recommended", wait: true });
81
- const res = await pa.chat.completions.create({ model: ep.id, messages: [...] });
82
-
83
- for (const m of await pa.models.list()) console.log(m.id);
84
- ```
85
-
86
- Discovery (`pa.tasks.match`, `pa.tasks.leaderboard`) tells you which open
87
- models are benchmark-proven for your task and what the frontier baseline costs.
74
+ Discovery (`pa.tasks.match`) tells you whether Pareta has a benchmark-proven
75
+ specialist lane for your workload — describe the task in free text and get
76
+ ranked matching tasks back.
88
77
 
89
78
  ## Auth
90
79
 
package/dist/index.cjs CHANGED
@@ -174,7 +174,7 @@ function parseSSE(reader, opts) {
174
174
  }
175
175
 
176
176
  // src/version.ts
177
- var VERSION = "0.1.0";
177
+ var VERSION = "1.1.0";
178
178
 
179
179
  // src/money.ts
180
180
  var MICRO_PER_CENT = 10000n;
@@ -280,47 +280,6 @@ var ModelList = class extends BaseModel {
280
280
  return this.data[Symbol.iterator]();
281
281
  }
282
282
  };
283
- var Endpoint = class extends BaseModel {
284
- get id() {
285
- return this.raw.id ?? this.raw.name ?? null;
286
- }
287
- get name() {
288
- return this.raw.name ?? null;
289
- }
290
- get model() {
291
- return this.raw.model ?? null;
292
- }
293
- get status() {
294
- return this.raw.status ?? null;
295
- }
296
- // Live list sends camelCase `taskName`; the detail record sends `task`.
297
- get task() {
298
- return this.raw.taskName ?? this.raw.task ?? null;
299
- }
300
- get url() {
301
- return this.raw.url ?? null;
302
- }
303
- get isLive() {
304
- return this.raw.status === "live";
305
- }
306
- /** Structured-extraction endpoints (contract / SEC / ICD …): the system prompt
307
- * the benchmark used. The proxy applies it automatically when you send no
308
- * `system` message (so quality matches the leaderboard by default); returned
309
- * here so you can read it, or override it with your own `system` message.
310
- * `null` when the task has no injectable prompt (see `promptScaffold`). */
311
- get recommendedSystemPrompt() {
312
- return this.raw.recommendedSystemPrompt ?? null;
313
- }
314
- /** Fixed-label classification endpoints: a copy-and-customize `system` prompt
315
- * template. NEVER auto-applied — the categories are yours, not the benchmark's
316
- * — so fill them in and send it as your `system` message. `null` otherwise. */
317
- get promptScaffold() {
318
- return this.raw.promptScaffold ?? null;
319
- }
320
- };
321
- function endpointList(raw) {
322
- return (raw ?? []).map((e) => new Endpoint(e));
323
- }
324
283
  var Task = class extends BaseModel {
325
284
  get id() {
326
285
  return this.raw.id ?? null;
@@ -434,47 +393,6 @@ var EvalResult = class extends BaseModel {
434
393
  return (this.raw.per_item ?? []).map((it) => new EvalItemResult(it));
435
394
  }
436
395
  };
437
- var LeaderboardEntry = class extends BaseModel {
438
- get name() {
439
- return this.raw.name ?? null;
440
- }
441
- get kind() {
442
- return this.raw.kind ?? null;
443
- }
444
- get quality() {
445
- return this.raw.quality ?? null;
446
- }
447
- // Raw integer — sub-cent unit rate, NOT floored (see money.ts).
448
- get costPerRequestMicroUsd() {
449
- return this.raw.cost_per_request_micro_usd ?? null;
450
- }
451
- get contextK() {
452
- return this.raw.context_k ?? null;
453
- }
454
- get runMode() {
455
- return this.raw.run_mode ?? null;
456
- }
457
- };
458
- var Leaderboard = class extends BaseModel {
459
- get taskId() {
460
- return this.raw.task_id ?? null;
461
- }
462
- get metric() {
463
- return this.raw.metric ?? null;
464
- }
465
- get costUnit() {
466
- return this.raw.cost_unit ?? null;
467
- }
468
- get recommended() {
469
- return this.raw.recommended ?? null;
470
- }
471
- get models() {
472
- return (this.raw.models ?? []).map((m) => new LeaderboardEntry(m));
473
- }
474
- get frontier() {
475
- return this.raw.frontier ? new LeaderboardEntry(this.raw.frontier) : null;
476
- }
477
- };
478
396
  var FrontierModel = class extends BaseModel {
479
397
  get id() {
480
398
  return this.raw.id ?? null;
@@ -485,14 +403,11 @@ var FrontierModel = class extends BaseModel {
485
403
  get vision() {
486
404
  return Boolean(this.raw.vision);
487
405
  }
488
- /** Only meaningful when a task was given: it's on that task's leaderboard. */
406
+ /** Only meaningful when a task was given: it has benchmark results on that task. */
489
407
  get benchmarked() {
490
408
  return Boolean(this.raw.benchmarked);
491
409
  }
492
410
  };
493
- function leaderboardFrom(raw) {
494
- return new Leaderboard(raw ?? {});
495
- }
496
411
  function frontierModels(raw) {
497
412
  return (raw?.frontier_models ?? []).map((m) => new FrontierModel(m));
498
413
  }
@@ -530,12 +445,53 @@ var EvalRun = class extends BaseModel {
530
445
  return (this.raw.results ?? []).map((r) => new EvalResult(r));
531
446
  }
532
447
  };
448
+ var RerankResult = class extends BaseModel {
449
+ /** Position of this document in YOUR request's documents array. */
450
+ get index() {
451
+ return Number(this.raw.index ?? -1);
452
+ }
453
+ /** Calibrated P(relevant) in (0, 1) — thresholdable, not just ordinal. */
454
+ get relevanceScore() {
455
+ return Number(this.raw.relevance_score ?? 0);
456
+ }
457
+ };
458
+ var Rerank = class extends BaseModel {
459
+ get results() {
460
+ return (this.raw.results ?? []).map((r) => new RerankResult(r));
461
+ }
462
+ get model() {
463
+ return this.raw.model ?? null;
464
+ }
465
+ get pairs() {
466
+ return this.raw.pairs ?? null;
467
+ }
468
+ /** Map the ranked indices back onto the documents you sent — best first. */
469
+ topDocuments(documents) {
470
+ return this.results.filter((r) => r.index >= 0 && r.index < documents.length).map((r) => documents[r.index]);
471
+ }
472
+ };
473
+ var Embeddings = class extends BaseModel {
474
+ get vectors() {
475
+ const rows = [...this.raw.data ?? []];
476
+ rows.sort((a, b) => Number(a.index ?? 0) - Number(b.index ?? 0));
477
+ return rows.map((r) => r.embedding ?? []);
478
+ }
479
+ get model() {
480
+ return this.raw.model ?? null;
481
+ }
482
+ get promptTokens() {
483
+ return this.raw.usage?.prompt_tokens ?? null;
484
+ }
485
+ get length() {
486
+ return (this.raw.data ?? []).length;
487
+ }
488
+ };
533
489
 
534
490
  // src/resources/chat.ts
535
491
  var PATH = "/v1/chat/completions";
536
492
  function buildBody(params) {
537
493
  const { model, messages, stream, ...extra } = params;
538
- if (!model) throw new ParetaError("model is required (an endpoint id from endpoints.deploy)");
494
+ if (!model) throw new ParetaError('model is required (use "auto")');
539
495
  if (!messages || messages.length === 0) {
540
496
  throw new ParetaError("messages is required and must be non-empty");
541
497
  }
@@ -583,99 +539,19 @@ var Models = class {
583
539
  }
584
540
  };
585
541
 
586
- // src/resources/endpoints.ts
587
- var BASE = "/v1/endpoints";
588
- function buildDeployBody(params) {
589
- const { task, model, name, wait: _wait, ...extra } = params;
590
- if (!task) throw new ParetaError("task is required");
591
- const body = { task, model: model || "recommended", ...extra };
592
- if (name !== void 0) body.name = name;
593
- return body;
594
- }
595
- function endpointFromComplete(data) {
596
- const ep = data && typeof data === "object" ? data.endpoint : null;
597
- return new Endpoint(ep ?? {});
598
- }
599
- function deployError(data) {
600
- const msg = data && typeof data === "object" ? data.message : String(data);
601
- return new ParetaError(`deploy failed: ${msg || "unknown error"}`);
602
- }
603
- var EndpointMetrics = class {
604
- constructor(client, id) {
605
- this.client = client;
606
- this.id = id;
607
- }
608
- client;
609
- id;
610
- performance(params) {
611
- return this.client.request("GET", `${BASE}/${this.id}/performance`, { params });
612
- }
613
- uptime(params) {
614
- return this.client.request("GET", `${BASE}/${this.id}/uptime`, { params });
615
- }
616
- cost(params) {
617
- return this.client.request("GET", `${BASE}/${this.id}/cost`, { params });
618
- }
619
- quality(params) {
620
- return this.client.request("GET", `${BASE}/${this.id}/quality`, { params });
621
- }
622
- activity(params) {
623
- return this.client.request("GET", `${BASE}/${this.id}/activity`, { params });
624
- }
625
- };
626
- var Endpoints = class {
627
- constructor(client) {
628
- this.client = client;
629
- }
630
- client;
631
- deploy(params) {
632
- const body = buildDeployBody(params);
633
- const stream = this.client.stream("POST", BASE, { body, events: true });
634
- if (!params.wait) return stream;
635
- return this.waitForDeploy(stream);
636
- }
637
- async waitForDeploy(stream) {
638
- for await (const ev of stream) {
639
- if (ev.event === "complete") return endpointFromComplete(ev.data);
640
- if (ev.event === "error") throw deployError(ev.data);
641
- }
642
- throw new ParetaError("deploy stream ended without a 'complete' event");
643
- }
644
- list() {
645
- return this.client.request("GET", BASE, { cast: endpointList });
646
- }
647
- retrieve(endpointId) {
648
- return this.client.request("GET", `${BASE}/${endpointId}`, {
649
- cast: (raw) => new Endpoint(raw)
650
- });
651
- }
652
- start(endpointId) {
653
- return this.client.request("POST", `${BASE}/${endpointId}/start`);
654
- }
655
- stop(endpointId) {
656
- return this.client.request("POST", `${BASE}/${endpointId}/stop`);
657
- }
658
- async delete(endpointId) {
659
- await this.client.request("DELETE", `${BASE}/${endpointId}`);
660
- }
661
- metrics(endpointId) {
662
- return new EndpointMetrics(this.client, endpointId);
663
- }
664
- };
665
-
666
542
  // src/resources/tasks.ts
667
- var BASE2 = "/v1/tasks";
543
+ var BASE = "/v1/tasks";
668
544
  var Tasks = class {
669
545
  constructor(client) {
670
546
  this.client = client;
671
547
  }
672
548
  client;
673
549
  list() {
674
- return this.client.request("GET", BASE2, { cast: taskList });
550
+ return this.client.request("GET", BASE, { cast: taskList });
675
551
  }
676
552
  retrieve(taskId, opts = {}) {
677
553
  const params = opts.examplesN !== void 0 ? { examples_n: opts.examplesN } : void 0;
678
- return this.client.request("GET", `${BASE2}/${taskId}`, {
554
+ return this.client.request("GET", `${BASE}/${taskId}`, {
679
555
  params,
680
556
  cast: (raw) => new Task(raw)
681
557
  });
@@ -683,25 +559,15 @@ var Tasks = class {
683
559
  /** Free-text intent → ranked candidate tasks (the Step-0 backend matcher). */
684
560
  match(query, opts = {}) {
685
561
  if (!query || !query.trim()) throw new ParetaError("query is required");
686
- return this.client.request("POST", `${BASE2}/match`, {
562
+ return this.client.request("POST", `${BASE}/match`, {
687
563
  body: { query, top_k: opts.topK ?? 5 },
688
564
  cast: (raw) => new TaskMatch(raw)
689
565
  });
690
566
  }
691
- /** Models ranked by quality/cost for a task (+ recommended + frontier baseline). */
692
- leaderboard(taskId) {
693
- return this.client.request("GET", `${BASE2}/${taskId}/leaderboard`, {
694
- cast: leaderboardFrom
695
- });
696
- }
697
- /** The task's recommended deployable model — what deploy(model:"recommended") resolves to. */
698
- async recommended(taskId) {
699
- return (await this.leaderboard(taskId)).recommended;
700
- }
701
567
  };
702
568
 
703
569
  // src/resources/evals.ts
704
- var BASE3 = "/v1/eval-sets";
570
+ var BASE2 = "/v1/eval-sets";
705
571
  var RUNS = "/v1/eval-runs";
706
572
  var FRONTIER = "/v1/eval/frontier-models";
707
573
  var INLINE_MAX = 5 * 1024 * 1024;
@@ -775,17 +641,17 @@ var EvalSets = class {
775
641
  client;
776
642
  create(params) {
777
643
  const { files, data } = itemsJsonl(params.task, params.items, params.name);
778
- return this.client.request("POST", BASE3, { files, data, cast: evalSetFromCreate });
644
+ return this.client.request("POST", BASE2, { files, data, cast: evalSetFromCreate });
779
645
  }
780
646
  list() {
781
- return this.client.request("GET", BASE3, { cast: evalSetList });
647
+ return this.client.request("GET", BASE2, { cast: evalSetList });
782
648
  }
783
649
  async retrieve(evalSetId) {
784
- const raw = await this.client.request("GET", `${BASE3}/${evalSetId}`);
650
+ const raw = await this.client.request("GET", `${BASE2}/${evalSetId}`);
785
651
  return new EvalSet((raw ?? {}).eval_set ?? {});
786
652
  }
787
653
  async delete(evalSetId) {
788
- await this.client.request("DELETE", `${BASE3}/${evalSetId}`);
654
+ await this.client.request("DELETE", `${BASE2}/${evalSetId}`);
789
655
  }
790
656
  /**
791
657
  * Attach a binary doc (PDF/image) to one row's blob field. Collapses the
@@ -795,14 +661,14 @@ var EvalSets = class {
795
661
  async uploadDocument(evalSetId, file, opts) {
796
662
  const { blob, filename, size, mime } = await toBlob(file, opts.mime);
797
663
  if (size < INLINE_MAX) {
798
- return this.client.request("POST", `${BASE3}/${evalSetId}/attach-blob`, {
664
+ return this.client.request("POST", `${BASE2}/${evalSetId}/attach-blob`, {
799
665
  files: { file: { filename, content: blob, contentType: mime } },
800
666
  data: { idx: String(opts.idx), field_name: opts.fieldName, mime }
801
667
  });
802
668
  }
803
669
  const minted = await this.client.request(
804
670
  "POST",
805
- `${BASE3}/${evalSetId}/blob-upload-url`,
671
+ `${BASE2}/${evalSetId}/blob-upload-url`,
806
672
  { body: { idx: opts.idx, field_name: opts.fieldName, mime, file_size: size } }
807
673
  );
808
674
  const put = await globalThis.fetch(minted.upload_url, {
@@ -814,7 +680,7 @@ var EvalSets = class {
814
680
  if (put.status !== 200 && put.status !== 201) {
815
681
  throw new ParetaError(`blob upload PUT failed: ${put.status}`);
816
682
  }
817
- return this.client.request("POST", `${BASE3}/${evalSetId}/blob-upload-complete`, {
683
+ return this.client.request("POST", `${BASE2}/${evalSetId}/blob-upload-complete`, {
818
684
  body: { idx: opts.idx, field_name: opts.fieldName, storage_uri: minted.storage_uri, mime }
819
685
  });
820
686
  }
@@ -922,9 +788,49 @@ var Auto = class {
922
788
  }
923
789
  };
924
790
 
791
+ // src/resources/retrieval.ts
792
+ function makeRerank(client) {
793
+ return (query, documents, opts = {}) => {
794
+ if (!query || !query.trim()) throw new ParetaError("query is required");
795
+ if (!Array.isArray(documents) || documents.length === 0) {
796
+ throw new ParetaError("documents must be a non-empty array of strings");
797
+ }
798
+ const body = { query, documents };
799
+ if (opts.topN !== void 0) body.top_n = opts.topN;
800
+ return client.request("POST", "/v1/rerank", {
801
+ body,
802
+ cast: (raw) => new Rerank(raw)
803
+ });
804
+ };
805
+ }
806
+ function makeEmbeddings(client) {
807
+ return (input, opts = {}) => {
808
+ const texts = typeof input === "string" ? [input] : input;
809
+ if (!Array.isArray(texts) || texts.length === 0 || texts.some((t) => typeof t !== "string" || !t.trim())) {
810
+ throw new ParetaError("input must be a non-empty string or array of non-empty strings");
811
+ }
812
+ if (opts.inputType !== void 0 && opts.inputType !== "query" && opts.inputType !== "document") {
813
+ throw new ParetaError('inputType must be "query" or "document"');
814
+ }
815
+ const body = { input: texts };
816
+ if (opts.inputType !== void 0) body.input_type = opts.inputType;
817
+ return client.request("POST", "/v1/embeddings", {
818
+ body,
819
+ cast: (raw) => new Embeddings(raw)
820
+ });
821
+ };
822
+ }
823
+
925
824
  // src/client.ts
926
825
  var DEFAULT_BASE_URL = "https://api.pareta.ai";
927
- var DEFAULT_TIMEOUT_MS = 6e4;
826
+ function randomKey() {
827
+ try {
828
+ return globalThis.crypto?.randomUUID?.().replace(/-/g, "") ?? Math.random().toString(36).slice(2) + Date.now().toString(36);
829
+ } catch {
830
+ return Math.random().toString(36).slice(2) + Date.now().toString(36);
831
+ }
832
+ }
833
+ var DEFAULT_TIMEOUT_MS = 6e5;
928
834
  var DEFAULT_MAX_RETRIES = 2;
929
835
  var RETRY_STATUSES = /* @__PURE__ */ new Set([408, 409, 429, 500, 502, 503, 504]);
930
836
  function normalizeBaseURL(url) {
@@ -939,10 +845,13 @@ var Pareta = class _Pareta {
939
845
  // Resource namespaces (assigned in the constructor; filled in slice by slice).
940
846
  chat;
941
847
  models;
942
- endpoints;
943
848
  tasks;
944
849
  evals;
945
850
  auto;
851
+ /** Document reranking (the Retrieval precision lane) — `pa.rerank(query, docs, {topN})`. */
852
+ rerank;
853
+ /** Text embeddings (the Retrieval recall lane) — `pa.embeddings(input, {inputType})`. */
854
+ embeddings;
946
855
  constructor(options = {}) {
947
856
  if (!options.apiKey) {
948
857
  throw new ParetaError(
@@ -960,10 +869,11 @@ var Pareta = class _Pareta {
960
869
  this.fetchImpl = options.fetch ? f : f.bind(globalThis);
961
870
  this.chat = new Chat(this);
962
871
  this.models = new Models(this);
963
- this.endpoints = new Endpoints(this);
964
872
  this.tasks = new Tasks(this);
965
873
  this.evals = new Evals(this);
966
874
  this.auto = new Auto(this);
875
+ this.rerank = makeRerank(this);
876
+ this.embeddings = makeEmbeddings(this);
967
877
  }
968
878
  /** Build from PARETA_API_KEY (+ optional PARETA_BASE_URL); explicit opts win. */
969
879
  static fromEnv(options = {}) {
@@ -1050,6 +960,9 @@ var Pareta = class _Pareta {
1050
960
  const url = this.buildURL(path, params);
1051
961
  const isMultipart = files != null || data != null;
1052
962
  const headers = this.headers({ jsonBody: body != null && !isMultipart });
963
+ if (method.toUpperCase() === "POST" && !headers["Idempotency-Key"]) {
964
+ headers["Idempotency-Key"] = `pareta-js-${randomKey()}`;
965
+ }
1053
966
  let payload;
1054
967
  if (isMultipart) {
1055
968
  payload = this.buildFormData(files, data);
@@ -1091,12 +1004,15 @@ var Pareta = class _Pareta {
1091
1004
  /**
1092
1005
  * Yield parsed SSE objects. Retries ONLY the initial connect/handshake — once
1093
1006
  * bytes are flowing a mid-stream drop raises (re-issuing would re-run a
1094
- * metered generation / re-trigger a deploy). `events:true` → `{event,data}`.
1007
+ * metered generation). `events:true` → `{event,data}`.
1095
1008
  */
1096
1009
  async *stream(method, path, opts = {}) {
1097
1010
  const { body, params, cast, events } = opts;
1098
1011
  const url = this.buildURL(path, params);
1099
1012
  const headers = this.headers({ stream: true, jsonBody: body != null });
1013
+ if (method.toUpperCase() === "POST" && !headers["Idempotency-Key"]) {
1014
+ headers["Idempotency-Key"] = `pareta-js-${randomKey()}`;
1015
+ }
1100
1016
  const payload = body != null ? JSON.stringify(body) : void 0;
1101
1017
  for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
1102
1018
  let started = false;
@@ -1148,8 +1064,7 @@ exports.ChatCompletion = ChatCompletion;
1148
1064
  exports.ChatCompletionChunk = ChatCompletionChunk;
1149
1065
  exports.Choice = Choice;
1150
1066
  exports.ConflictError = ConflictError;
1151
- exports.Endpoint = Endpoint;
1152
- exports.EndpointMetrics = EndpointMetrics;
1067
+ exports.Embeddings = Embeddings;
1153
1068
  exports.EndpointNotReadyError = EndpointNotReadyError;
1154
1069
  exports.EvalItemResult = EvalItemResult;
1155
1070
  exports.EvalResult = EvalResult;
@@ -1159,8 +1074,6 @@ exports.EvalSet = EvalSet;
1159
1074
  exports.EvalSets = EvalSets;
1160
1075
  exports.FrontierModel = FrontierModel;
1161
1076
  exports.InsufficientCreditsError = InsufficientCreditsError;
1162
- exports.Leaderboard = Leaderboard;
1163
- exports.LeaderboardEntry = LeaderboardEntry;
1164
1077
  exports.Message = Message;
1165
1078
  exports.Model = Model;
1166
1079
  exports.ModelList = ModelList;
@@ -1169,6 +1082,8 @@ exports.Pareta = Pareta;
1169
1082
  exports.ParetaError = ParetaError;
1170
1083
  exports.PermissionDeniedError = PermissionDeniedError;
1171
1084
  exports.RateLimitError = RateLimitError;
1085
+ exports.Rerank = Rerank;
1086
+ exports.RerankResult = RerankResult;
1172
1087
  exports.Task = Task;
1173
1088
  exports.TaskMatch = TaskMatch;
1174
1089
  exports.TaskMatchCandidate = TaskMatchCandidate;