pareta 1.0.0 → 1.2.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/index.d.cts CHANGED
@@ -142,6 +142,51 @@ declare class EvalRun extends BaseModel {
142
142
  get cost(): string;
143
143
  get results(): EvalResult[];
144
144
  }
145
+ /** One row of `Rerank.results` — a document's position + calibrated score. */
146
+ declare class RerankResult extends BaseModel {
147
+ /** Position of this document in YOUR request's documents array. */
148
+ get index(): number;
149
+ /** Calibrated P(relevant) in (0, 1) — thresholdable, not just ordinal. */
150
+ get relevanceScore(): number;
151
+ }
152
+ /** Result of `pa.rerank(...)`: `.results` ordered most-relevant-first;
153
+ * `.pairs` is the number of documents scored (the metered unit). */
154
+ declare class Rerank extends BaseModel {
155
+ get results(): RerankResult[];
156
+ get model(): string | null;
157
+ get pairs(): number | null;
158
+ /** Map the ranked indices back onto the documents you sent — best first. */
159
+ topDocuments(documents: string[]): string[];
160
+ }
161
+ /** Result of `pa.embeddings(...)`: unit-normalized vectors in input order
162
+ * (cosine similarity is a plain dot product); `.promptTokens` is metered. */
163
+ declare class Embeddings extends BaseModel {
164
+ get vectors(): number[][];
165
+ get model(): string | null;
166
+ get promptTokens(): number | null;
167
+ get length(): number;
168
+ }
169
+ /** Speech-to-text result from `audio.transcriptions(...)`. `.durationS` is
170
+ * the metered input audio length (per minute). */
171
+ declare class Transcription extends BaseModel {
172
+ get text(): string | null;
173
+ get language(): string | null;
174
+ get durationS(): number | null;
175
+ toString(): string;
176
+ }
177
+ /** Text-to-speech result from `audio.speech(...)`. `.audio` is decoded
178
+ * bytes; `.durationS` is the metered output audio length (per minute). */
179
+ declare class Speech extends BaseModel {
180
+ /** The synthesized audio, base64-decoded to raw bytes. */
181
+ get audio(): Uint8Array;
182
+ get audioBase64(): string | null;
183
+ get sampleRate(): number | null;
184
+ get durationS(): number | null;
185
+ /** Container/codec of the returned audio (e.g. "wav"). */
186
+ get format(): string | null;
187
+ /** Write the decoded audio to `path` (Node only — lazy node:fs). */
188
+ save(path: string): Promise<this>;
189
+ }
145
190
 
146
191
  /**
147
192
  * `client.chat.completions` — OpenAI-compatible chat completions.
@@ -366,6 +411,75 @@ declare class Auto {
366
411
  }): Promise<FrontierComparison>;
367
412
  }
368
413
 
414
+ /**
415
+ * `pa.audio` — the Speech capability lanes (ASR + TTS), TS parity with the
416
+ * Python SDK's `client.audio`.
417
+ *
418
+ * Dedicated routes, not `chat.completions`:
419
+ * POST /v1/audio/transcriptions {audio_base64, language?} -> {text, language, duration_s}
420
+ * POST /v1/audio/speech {text, voice?} -> {audio_base64, sample_rate, duration_s, format}
421
+ *
422
+ * Both are metered PER MINUTE of audio (input duration for ASR, output
423
+ * duration for TTS). You never pick a serving model — Pareta resolves the
424
+ * lane, exactly as `model:"auto"` does for chat.
425
+ *
426
+ * Audio input follows the evals FileInput convention: a string is a FILE
427
+ * PATH (read via lazy node:fs — browser/edge bundles stay clean);
428
+ * Blob/ArrayBuffer/Uint8Array are raw bytes; `{ base64 }` passes
429
+ * pre-encoded audio through untouched.
430
+ */
431
+
432
+ type AudioInput = string | Blob | ArrayBuffer | Uint8Array | {
433
+ base64: string;
434
+ };
435
+ interface TranscriptionOptions {
436
+ /** Optional ISO language hint (omit to auto-detect). */
437
+ language?: string;
438
+ }
439
+ interface SpeechOptions {
440
+ /** Optional voice id (omit for the default voice). */
441
+ voice?: string;
442
+ }
443
+ declare class Audio {
444
+ private readonly client;
445
+ constructor(client: Transport);
446
+ /** Speech-to-text (the `asr` lane). `audio` is a file path, raw bytes, a
447
+ * Blob, or `{ base64 }`. Metered per minute of input audio. */
448
+ transcriptions(audio: AudioInput, opts?: TranscriptionOptions): Promise<Transcription>;
449
+ /** Text-to-speech (the `tts` lane). Returns a `Speech` whose `.audio` is
450
+ * decoded bytes (`.save(path)` writes a file in Node). Metered per minute
451
+ * of output audio. */
452
+ speech(text: string, opts?: SpeechOptions): Promise<Speech>;
453
+ }
454
+
455
+ /**
456
+ * `pa.rerank(...)` + `pa.embeddings(...)` — the Retrieval capability lanes
457
+ * (the RAG stack: embeddings for recall, reranking for precision).
458
+ *
459
+ * Both are dedicated routes, not `chat.completions`:
460
+ * POST /v1/rerank {query, documents[], top_n?} -> ordered
461
+ * {index, relevance_score} rows (calibrated P(relevant))
462
+ * POST /v1/embeddings {input[], input_type?} -> unit-normalized vectors
463
+ *
464
+ * Rerank is metered per document scored; embeddings per input token. You never
465
+ * pick a serving model — Pareta resolves the lane (`pareta-rerank-1` / `bge-1`),
466
+ * exactly as `model:"auto"` does for chat.
467
+ *
468
+ * Exposed as callable client fields (`pa.rerank(...)`) rather than resource
469
+ * objects — call-parity with the Python SDK, and neither lane has sub-methods.
470
+ */
471
+
472
+ interface RerankOptions {
473
+ /** Truncate the response to the best N (all documents are still scored and metered). */
474
+ topN?: number;
475
+ }
476
+ type RerankFn = (query: string, documents: string[], opts?: RerankOptions) => Promise<Rerank>;
477
+ interface EmbeddingsOptions {
478
+ /** `"query"` embeds a retrieval QUERY (asymmetric); default embeds documents raw. */
479
+ inputType?: "query" | "document";
480
+ }
481
+ type EmbeddingsFn = (input: string | string[], opts?: EmbeddingsOptions) => Promise<Embeddings>;
482
+
369
483
  /**
370
484
  * The `Pareta` client — one class (no sync/async split; JS is Promise-only).
371
485
  * A faithful port of the Python `_client.py` transport: header construction,
@@ -420,6 +534,12 @@ declare class Pareta implements Transport {
420
534
  readonly tasks: Tasks;
421
535
  readonly evals: Evals;
422
536
  readonly auto: Auto;
537
+ /** The Speech lanes — `pa.audio.transcriptions(...)` (ASR) + `pa.audio.speech(...)` (TTS). */
538
+ readonly audio: Audio;
539
+ /** Document reranking (the Retrieval precision lane) — `pa.rerank(query, docs, {topN})`. */
540
+ readonly rerank: RerankFn;
541
+ /** Text embeddings (the Retrieval recall lane) — `pa.embeddings(input, {inputType})`. */
542
+ readonly embeddings: EmbeddingsFn;
423
543
  constructor(options?: ParetaOptions);
424
544
  /** Build from PARETA_API_KEY (+ optional PARETA_BASE_URL); explicit opts win. */
425
545
  static fromEnv(options?: ParetaOptions): Pareta;
@@ -443,7 +563,7 @@ declare class Pareta implements Transport {
443
563
  stream<T = unknown>(method: string, path: string, opts?: StreamOptions): AsyncGenerator<T>;
444
564
  }
445
565
 
446
- declare const VERSION = "1.0.0";
566
+ declare const VERSION = "1.2.0";
447
567
 
448
568
  /**
449
569
  * Typed error hierarchy for the Pareta SDK — a faithful port of the Python
@@ -535,4 +655,4 @@ declare class EndpointNotReadyError extends APIStatusError {
535
655
  constructor(message: string, init: APIStatusErrorInit);
536
656
  }
537
657
 
538
- export { APIConnectionError, APIStatusError, APITimeoutError, AuthenticationError, BadRequestError, BaseModel, ChatCompletion, ChatCompletionChunk, type ChatCompletionCreateParams, type ChatMessage, Choice, ConflictError, EndpointNotReadyError, type ErrorDetail, EvalItemResult, EvalResult, EvalRun, type EvalRunCreateParams, EvalRuns, EvalSet, EvalSets, type FileInput, type FilePart, FrontierModel, type FrontierSpec, InsufficientCreditsError, Message, Model, ModelList, NotFoundError, Pareta, ParetaError, type ParetaOptions, PermissionDeniedError, RateLimitError, type SSEEvent, Task, TaskMatch, TaskMatchCandidate, type Transport, Usage, VERSION, type ValidationErrorItem };
658
+ export { APIConnectionError, APIStatusError, APITimeoutError, Audio, type AudioInput, AuthenticationError, BadRequestError, BaseModel, ChatCompletion, ChatCompletionChunk, type ChatCompletionCreateParams, type ChatMessage, Choice, ConflictError, Embeddings, type EmbeddingsFn, type EmbeddingsOptions, EndpointNotReadyError, type ErrorDetail, EvalItemResult, EvalResult, EvalRun, type EvalRunCreateParams, EvalRuns, EvalSet, EvalSets, type FileInput, type FilePart, FrontierModel, type FrontierSpec, InsufficientCreditsError, Message, Model, ModelList, NotFoundError, Pareta, ParetaError, type ParetaOptions, PermissionDeniedError, RateLimitError, Rerank, type RerankFn, type RerankOptions, RerankResult, type SSEEvent, Speech, type SpeechOptions, Task, TaskMatch, TaskMatchCandidate, Transcription, type TranscriptionOptions, type Transport, Usage, VERSION, type ValidationErrorItem };
package/dist/index.d.ts CHANGED
@@ -142,6 +142,51 @@ declare class EvalRun extends BaseModel {
142
142
  get cost(): string;
143
143
  get results(): EvalResult[];
144
144
  }
145
+ /** One row of `Rerank.results` — a document's position + calibrated score. */
146
+ declare class RerankResult extends BaseModel {
147
+ /** Position of this document in YOUR request's documents array. */
148
+ get index(): number;
149
+ /** Calibrated P(relevant) in (0, 1) — thresholdable, not just ordinal. */
150
+ get relevanceScore(): number;
151
+ }
152
+ /** Result of `pa.rerank(...)`: `.results` ordered most-relevant-first;
153
+ * `.pairs` is the number of documents scored (the metered unit). */
154
+ declare class Rerank extends BaseModel {
155
+ get results(): RerankResult[];
156
+ get model(): string | null;
157
+ get pairs(): number | null;
158
+ /** Map the ranked indices back onto the documents you sent — best first. */
159
+ topDocuments(documents: string[]): string[];
160
+ }
161
+ /** Result of `pa.embeddings(...)`: unit-normalized vectors in input order
162
+ * (cosine similarity is a plain dot product); `.promptTokens` is metered. */
163
+ declare class Embeddings extends BaseModel {
164
+ get vectors(): number[][];
165
+ get model(): string | null;
166
+ get promptTokens(): number | null;
167
+ get length(): number;
168
+ }
169
+ /** Speech-to-text result from `audio.transcriptions(...)`. `.durationS` is
170
+ * the metered input audio length (per minute). */
171
+ declare class Transcription extends BaseModel {
172
+ get text(): string | null;
173
+ get language(): string | null;
174
+ get durationS(): number | null;
175
+ toString(): string;
176
+ }
177
+ /** Text-to-speech result from `audio.speech(...)`. `.audio` is decoded
178
+ * bytes; `.durationS` is the metered output audio length (per minute). */
179
+ declare class Speech extends BaseModel {
180
+ /** The synthesized audio, base64-decoded to raw bytes. */
181
+ get audio(): Uint8Array;
182
+ get audioBase64(): string | null;
183
+ get sampleRate(): number | null;
184
+ get durationS(): number | null;
185
+ /** Container/codec of the returned audio (e.g. "wav"). */
186
+ get format(): string | null;
187
+ /** Write the decoded audio to `path` (Node only — lazy node:fs). */
188
+ save(path: string): Promise<this>;
189
+ }
145
190
 
146
191
  /**
147
192
  * `client.chat.completions` — OpenAI-compatible chat completions.
@@ -366,6 +411,75 @@ declare class Auto {
366
411
  }): Promise<FrontierComparison>;
367
412
  }
368
413
 
414
+ /**
415
+ * `pa.audio` — the Speech capability lanes (ASR + TTS), TS parity with the
416
+ * Python SDK's `client.audio`.
417
+ *
418
+ * Dedicated routes, not `chat.completions`:
419
+ * POST /v1/audio/transcriptions {audio_base64, language?} -> {text, language, duration_s}
420
+ * POST /v1/audio/speech {text, voice?} -> {audio_base64, sample_rate, duration_s, format}
421
+ *
422
+ * Both are metered PER MINUTE of audio (input duration for ASR, output
423
+ * duration for TTS). You never pick a serving model — Pareta resolves the
424
+ * lane, exactly as `model:"auto"` does for chat.
425
+ *
426
+ * Audio input follows the evals FileInput convention: a string is a FILE
427
+ * PATH (read via lazy node:fs — browser/edge bundles stay clean);
428
+ * Blob/ArrayBuffer/Uint8Array are raw bytes; `{ base64 }` passes
429
+ * pre-encoded audio through untouched.
430
+ */
431
+
432
+ type AudioInput = string | Blob | ArrayBuffer | Uint8Array | {
433
+ base64: string;
434
+ };
435
+ interface TranscriptionOptions {
436
+ /** Optional ISO language hint (omit to auto-detect). */
437
+ language?: string;
438
+ }
439
+ interface SpeechOptions {
440
+ /** Optional voice id (omit for the default voice). */
441
+ voice?: string;
442
+ }
443
+ declare class Audio {
444
+ private readonly client;
445
+ constructor(client: Transport);
446
+ /** Speech-to-text (the `asr` lane). `audio` is a file path, raw bytes, a
447
+ * Blob, or `{ base64 }`. Metered per minute of input audio. */
448
+ transcriptions(audio: AudioInput, opts?: TranscriptionOptions): Promise<Transcription>;
449
+ /** Text-to-speech (the `tts` lane). Returns a `Speech` whose `.audio` is
450
+ * decoded bytes (`.save(path)` writes a file in Node). Metered per minute
451
+ * of output audio. */
452
+ speech(text: string, opts?: SpeechOptions): Promise<Speech>;
453
+ }
454
+
455
+ /**
456
+ * `pa.rerank(...)` + `pa.embeddings(...)` — the Retrieval capability lanes
457
+ * (the RAG stack: embeddings for recall, reranking for precision).
458
+ *
459
+ * Both are dedicated routes, not `chat.completions`:
460
+ * POST /v1/rerank {query, documents[], top_n?} -> ordered
461
+ * {index, relevance_score} rows (calibrated P(relevant))
462
+ * POST /v1/embeddings {input[], input_type?} -> unit-normalized vectors
463
+ *
464
+ * Rerank is metered per document scored; embeddings per input token. You never
465
+ * pick a serving model — Pareta resolves the lane (`pareta-rerank-1` / `bge-1`),
466
+ * exactly as `model:"auto"` does for chat.
467
+ *
468
+ * Exposed as callable client fields (`pa.rerank(...)`) rather than resource
469
+ * objects — call-parity with the Python SDK, and neither lane has sub-methods.
470
+ */
471
+
472
+ interface RerankOptions {
473
+ /** Truncate the response to the best N (all documents are still scored and metered). */
474
+ topN?: number;
475
+ }
476
+ type RerankFn = (query: string, documents: string[], opts?: RerankOptions) => Promise<Rerank>;
477
+ interface EmbeddingsOptions {
478
+ /** `"query"` embeds a retrieval QUERY (asymmetric); default embeds documents raw. */
479
+ inputType?: "query" | "document";
480
+ }
481
+ type EmbeddingsFn = (input: string | string[], opts?: EmbeddingsOptions) => Promise<Embeddings>;
482
+
369
483
  /**
370
484
  * The `Pareta` client — one class (no sync/async split; JS is Promise-only).
371
485
  * A faithful port of the Python `_client.py` transport: header construction,
@@ -420,6 +534,12 @@ declare class Pareta implements Transport {
420
534
  readonly tasks: Tasks;
421
535
  readonly evals: Evals;
422
536
  readonly auto: Auto;
537
+ /** The Speech lanes — `pa.audio.transcriptions(...)` (ASR) + `pa.audio.speech(...)` (TTS). */
538
+ readonly audio: Audio;
539
+ /** Document reranking (the Retrieval precision lane) — `pa.rerank(query, docs, {topN})`. */
540
+ readonly rerank: RerankFn;
541
+ /** Text embeddings (the Retrieval recall lane) — `pa.embeddings(input, {inputType})`. */
542
+ readonly embeddings: EmbeddingsFn;
423
543
  constructor(options?: ParetaOptions);
424
544
  /** Build from PARETA_API_KEY (+ optional PARETA_BASE_URL); explicit opts win. */
425
545
  static fromEnv(options?: ParetaOptions): Pareta;
@@ -443,7 +563,7 @@ declare class Pareta implements Transport {
443
563
  stream<T = unknown>(method: string, path: string, opts?: StreamOptions): AsyncGenerator<T>;
444
564
  }
445
565
 
446
- declare const VERSION = "1.0.0";
566
+ declare const VERSION = "1.2.0";
447
567
 
448
568
  /**
449
569
  * Typed error hierarchy for the Pareta SDK — a faithful port of the Python
@@ -535,4 +655,4 @@ declare class EndpointNotReadyError extends APIStatusError {
535
655
  constructor(message: string, init: APIStatusErrorInit);
536
656
  }
537
657
 
538
- export { APIConnectionError, APIStatusError, APITimeoutError, AuthenticationError, BadRequestError, BaseModel, ChatCompletion, ChatCompletionChunk, type ChatCompletionCreateParams, type ChatMessage, Choice, ConflictError, EndpointNotReadyError, type ErrorDetail, EvalItemResult, EvalResult, EvalRun, type EvalRunCreateParams, EvalRuns, EvalSet, EvalSets, type FileInput, type FilePart, FrontierModel, type FrontierSpec, InsufficientCreditsError, Message, Model, ModelList, NotFoundError, Pareta, ParetaError, type ParetaOptions, PermissionDeniedError, RateLimitError, type SSEEvent, Task, TaskMatch, TaskMatchCandidate, type Transport, Usage, VERSION, type ValidationErrorItem };
658
+ export { APIConnectionError, APIStatusError, APITimeoutError, Audio, type AudioInput, AuthenticationError, BadRequestError, BaseModel, ChatCompletion, ChatCompletionChunk, type ChatCompletionCreateParams, type ChatMessage, Choice, ConflictError, Embeddings, type EmbeddingsFn, type EmbeddingsOptions, EndpointNotReadyError, type ErrorDetail, EvalItemResult, EvalResult, EvalRun, type EvalRunCreateParams, EvalRuns, EvalSet, EvalSets, type FileInput, type FilePart, FrontierModel, type FrontierSpec, InsufficientCreditsError, Message, Model, ModelList, NotFoundError, Pareta, ParetaError, type ParetaOptions, PermissionDeniedError, RateLimitError, Rerank, type RerankFn, type RerankOptions, RerankResult, type SSEEvent, Speech, type SpeechOptions, Task, TaskMatch, TaskMatchCandidate, Transcription, type TranscriptionOptions, type Transport, Usage, VERSION, type ValidationErrorItem };
package/dist/index.mjs CHANGED
@@ -172,7 +172,7 @@ function parseSSE(reader, opts) {
172
172
  }
173
173
 
174
174
  // src/version.ts
175
- var VERSION = "1.0.0";
175
+ var VERSION = "1.2.0";
176
176
 
177
177
  // src/money.ts
178
178
  var MICRO_PER_CENT = 10000n;
@@ -443,6 +443,94 @@ var EvalRun = class extends BaseModel {
443
443
  return (this.raw.results ?? []).map((r) => new EvalResult(r));
444
444
  }
445
445
  };
446
+ var RerankResult = class extends BaseModel {
447
+ /** Position of this document in YOUR request's documents array. */
448
+ get index() {
449
+ return Number(this.raw.index ?? -1);
450
+ }
451
+ /** Calibrated P(relevant) in (0, 1) — thresholdable, not just ordinal. */
452
+ get relevanceScore() {
453
+ return Number(this.raw.relevance_score ?? 0);
454
+ }
455
+ };
456
+ var Rerank = class extends BaseModel {
457
+ get results() {
458
+ return (this.raw.results ?? []).map((r) => new RerankResult(r));
459
+ }
460
+ get model() {
461
+ return this.raw.model ?? null;
462
+ }
463
+ get pairs() {
464
+ return this.raw.pairs ?? null;
465
+ }
466
+ /** Map the ranked indices back onto the documents you sent — best first. */
467
+ topDocuments(documents) {
468
+ return this.results.filter((r) => r.index >= 0 && r.index < documents.length).map((r) => documents[r.index]);
469
+ }
470
+ };
471
+ var Embeddings = class extends BaseModel {
472
+ get vectors() {
473
+ const rows = [...this.raw.data ?? []];
474
+ rows.sort((a, b) => Number(a.index ?? 0) - Number(b.index ?? 0));
475
+ return rows.map((r) => r.embedding ?? []);
476
+ }
477
+ get model() {
478
+ return this.raw.model ?? null;
479
+ }
480
+ get promptTokens() {
481
+ return this.raw.usage?.prompt_tokens ?? null;
482
+ }
483
+ get length() {
484
+ return (this.raw.data ?? []).length;
485
+ }
486
+ };
487
+ function base64ToBytes(b64) {
488
+ if (typeof Buffer !== "undefined") return new Uint8Array(Buffer.from(b64, "base64"));
489
+ const bin = atob(b64);
490
+ const bytes = new Uint8Array(bin.length);
491
+ for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
492
+ return bytes;
493
+ }
494
+ var Transcription = class extends BaseModel {
495
+ get text() {
496
+ return this.raw.text ?? null;
497
+ }
498
+ get language() {
499
+ return this.raw.language ?? null;
500
+ }
501
+ get durationS() {
502
+ return this.raw.duration_s ?? null;
503
+ }
504
+ toString() {
505
+ return this.text ?? "";
506
+ }
507
+ };
508
+ var Speech = class extends BaseModel {
509
+ /** The synthesized audio, base64-decoded to raw bytes. */
510
+ get audio() {
511
+ const b64 = this.raw.audio_base64 || "";
512
+ return b64 ? base64ToBytes(b64) : new Uint8Array(0);
513
+ }
514
+ get audioBase64() {
515
+ return this.raw.audio_base64 ?? null;
516
+ }
517
+ get sampleRate() {
518
+ return this.raw.sample_rate ?? null;
519
+ }
520
+ get durationS() {
521
+ return this.raw.duration_s ?? null;
522
+ }
523
+ /** Container/codec of the returned audio (e.g. "wav"). */
524
+ get format() {
525
+ return this.raw.format ?? null;
526
+ }
527
+ /** Write the decoded audio to `path` (Node only — lazy node:fs). */
528
+ async save(path) {
529
+ const { writeFile } = await import('fs/promises');
530
+ await writeFile(path, this.audio);
531
+ return this;
532
+ }
533
+ };
446
534
 
447
535
  // src/resources/chat.ts
448
536
  var PATH = "/v1/chat/completions";
@@ -745,6 +833,93 @@ var Auto = class {
745
833
  }
746
834
  };
747
835
 
836
+ // src/resources/audio.ts
837
+ var BASE3 = "/v1/audio";
838
+ function bytesToBase64(bytes) {
839
+ if (typeof Buffer !== "undefined") return Buffer.from(bytes).toString("base64");
840
+ let bin = "";
841
+ const CHUNK = 32768;
842
+ for (let i = 0; i < bytes.length; i += CHUNK) {
843
+ bin += String.fromCharCode(...bytes.subarray(i, i + CHUNK));
844
+ }
845
+ return btoa(bin);
846
+ }
847
+ async function toBase64(audio) {
848
+ if (typeof audio === "string") {
849
+ const { readFile } = await import('fs/promises');
850
+ return bytesToBase64(new Uint8Array(await readFile(audio)));
851
+ }
852
+ if (typeof audio === "object" && audio !== null && "base64" in audio) {
853
+ if (!audio.base64 || !audio.base64.trim()) throw new ParetaError("audio.base64 is empty");
854
+ return audio.base64;
855
+ }
856
+ if (audio instanceof Blob) return bytesToBase64(new Uint8Array(await audio.arrayBuffer()));
857
+ const bytes = audio instanceof Uint8Array ? audio : new Uint8Array(audio);
858
+ if (bytes.byteLength === 0) throw new ParetaError("audio is empty");
859
+ return bytesToBase64(bytes);
860
+ }
861
+ var Audio = class {
862
+ constructor(client) {
863
+ this.client = client;
864
+ }
865
+ client;
866
+ /** Speech-to-text (the `asr` lane). `audio` is a file path, raw bytes, a
867
+ * Blob, or `{ base64 }`. Metered per minute of input audio. */
868
+ async transcriptions(audio, opts = {}) {
869
+ const body = { audio_base64: await toBase64(audio) };
870
+ if (opts.language) body.language = opts.language;
871
+ return this.client.request("POST", `${BASE3}/transcriptions`, {
872
+ body,
873
+ cast: (raw) => new Transcription(raw)
874
+ });
875
+ }
876
+ /** Text-to-speech (the `tts` lane). Returns a `Speech` whose `.audio` is
877
+ * decoded bytes (`.save(path)` writes a file in Node). Metered per minute
878
+ * of output audio. */
879
+ speech(text, opts = {}) {
880
+ if (!text || !text.trim()) throw new ParetaError("text is required");
881
+ const body = { text };
882
+ if (opts.voice) body.voice = opts.voice;
883
+ return this.client.request("POST", `${BASE3}/speech`, {
884
+ body,
885
+ cast: (raw) => new Speech(raw)
886
+ });
887
+ }
888
+ };
889
+
890
+ // src/resources/retrieval.ts
891
+ function makeRerank(client) {
892
+ return (query, documents, opts = {}) => {
893
+ if (!query || !query.trim()) throw new ParetaError("query is required");
894
+ if (!Array.isArray(documents) || documents.length === 0) {
895
+ throw new ParetaError("documents must be a non-empty array of strings");
896
+ }
897
+ const body = { query, documents };
898
+ if (opts.topN !== void 0) body.top_n = opts.topN;
899
+ return client.request("POST", "/v1/rerank", {
900
+ body,
901
+ cast: (raw) => new Rerank(raw)
902
+ });
903
+ };
904
+ }
905
+ function makeEmbeddings(client) {
906
+ return (input, opts = {}) => {
907
+ const texts = typeof input === "string" ? [input] : input;
908
+ if (!Array.isArray(texts) || texts.length === 0 || texts.some((t) => typeof t !== "string" || !t.trim())) {
909
+ throw new ParetaError("input must be a non-empty string or array of non-empty strings");
910
+ }
911
+ if (opts.inputType !== void 0 && opts.inputType !== "query" && opts.inputType !== "document") {
912
+ throw new ParetaError('inputType must be "query" or "document"');
913
+ }
914
+ const body = { input: texts };
915
+ if (opts.inputType !== void 0) body.input_type = opts.inputType;
916
+ return client.request("POST", "/v1/embeddings", {
917
+ body,
918
+ cast: (raw) => new Embeddings(raw)
919
+ });
920
+ };
921
+ }
922
+
748
923
  // src/client.ts
749
924
  var DEFAULT_BASE_URL = "https://api.pareta.ai";
750
925
  function randomKey() {
@@ -772,6 +947,12 @@ var Pareta = class _Pareta {
772
947
  tasks;
773
948
  evals;
774
949
  auto;
950
+ /** The Speech lanes — `pa.audio.transcriptions(...)` (ASR) + `pa.audio.speech(...)` (TTS). */
951
+ audio;
952
+ /** Document reranking (the Retrieval precision lane) — `pa.rerank(query, docs, {topN})`. */
953
+ rerank;
954
+ /** Text embeddings (the Retrieval recall lane) — `pa.embeddings(input, {inputType})`. */
955
+ embeddings;
775
956
  constructor(options = {}) {
776
957
  if (!options.apiKey) {
777
958
  throw new ParetaError(
@@ -792,6 +973,9 @@ var Pareta = class _Pareta {
792
973
  this.tasks = new Tasks(this);
793
974
  this.evals = new Evals(this);
794
975
  this.auto = new Auto(this);
976
+ this.audio = new Audio(this);
977
+ this.rerank = makeRerank(this);
978
+ this.embeddings = makeEmbeddings(this);
795
979
  }
796
980
  /** Build from PARETA_API_KEY (+ optional PARETA_BASE_URL); explicit opts win. */
797
981
  static fromEnv(options = {}) {
@@ -972,6 +1156,6 @@ var Pareta = class _Pareta {
972
1156
  }
973
1157
  };
974
1158
 
975
- export { APIConnectionError, APIStatusError, APITimeoutError, AuthenticationError, BadRequestError, BaseModel, ChatCompletion, ChatCompletionChunk, Choice, ConflictError, EndpointNotReadyError, EvalItemResult, EvalResult, EvalRun, EvalRuns, EvalSet, EvalSets, FrontierModel, InsufficientCreditsError, Message, Model, ModelList, NotFoundError, Pareta, ParetaError, PermissionDeniedError, RateLimitError, Task, TaskMatch, TaskMatchCandidate, Usage, VERSION };
1159
+ export { APIConnectionError, APIStatusError, APITimeoutError, Audio, AuthenticationError, BadRequestError, BaseModel, ChatCompletion, ChatCompletionChunk, Choice, ConflictError, Embeddings, EndpointNotReadyError, EvalItemResult, EvalResult, EvalRun, EvalRuns, EvalSet, EvalSets, FrontierModel, InsufficientCreditsError, Message, Model, ModelList, NotFoundError, Pareta, ParetaError, PermissionDeniedError, RateLimitError, Rerank, RerankResult, Speech, Task, TaskMatch, TaskMatchCandidate, Transcription, Usage, VERSION };
976
1160
  //# sourceMappingURL=index.mjs.map
977
1161
  //# sourceMappingURL=index.mjs.map