batchwork 1.2.1 → 1.3.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
@@ -88,13 +88,100 @@ for (const r of results) {
88
88
  }
89
89
  ```
90
90
 
91
- Batch image generation is available for **OpenAI** (`/v1/images/generations`, e.g. `gpt-image-2`), **Google Gemini** image models (e.g. `gemini-2.5-flash-image`), and **xAI** (`/v1/images/generations`, e.g. `grok-imagine-image-quality`); other providers throw a clear error. Generation only — image editing, video, and Google's Imagen models aren't batch-supported, and Together AI's batch API is chat/audio only. OpenAI and Google return inline base64 on `image.data`; xAI batch returns signed `image.url`s that **expire ~1h** after completion, so download them promptly.
91
+ Batch image generation is available for **OpenAI** (`/v1/images/generations`, e.g. `gpt-image-2`), **Google Gemini** image models (e.g. `gemini-3.1-flash-image`), and **xAI** (`/v1/images/generations`, e.g. `grok-imagine-image-quality`); other providers throw a clear error. Google's Imagen models aren't batch-supported, and Together AI's batch API is chat/audio only. OpenAI and Google return inline base64 on `image.data`; xAI batch returns signed `image.url`s that **expire ~1h** after completion, so download them promptly.
92
+
93
+ Image **editing** works too, on OpenAI and xAI, via `batch.images.edit()` (`batch.images.create()` is an alias of `batch.images()`). Source images are passed as JSON references — uploaded `fileId`s (OpenAI) or hosted `imageUrl`s — with an optional `mask` on OpenAI:
94
+
95
+ ```ts
96
+ const job = await batch.images.edit({
97
+ model: openai.image("gpt-image-2"),
98
+ requests: [
99
+ {
100
+ customId: "a",
101
+ prompt: "Make the bicycle blue.",
102
+ images: [{ imageUrl: "https://example.com/bicycle.png" }],
103
+ },
104
+ ],
105
+ });
106
+ ```
107
+
108
+ ## Videos
109
+
110
+ Generate videos in bulk — pass a video model and `prompt`s, and get signed video URLs back on `result.videos`:
111
+
112
+ ```ts
113
+ import { batch } from "batchwork";
114
+ import { xai } from "@ai-sdk/xai";
115
+
116
+ const job = await batch.videos({
117
+ model: xai.video("grok-imagine-video"),
118
+ requests: [
119
+ { customId: "a", prompt: "A red bicycle rolling downhill.", duration: 5 },
120
+ ],
121
+ });
122
+
123
+ const results = await job.wait().then(() => job.collect());
124
+ for (const r of results) {
125
+ console.log(r.customId, r.videos?.[0]?.url);
126
+ }
127
+ ```
128
+
129
+ Batch video generation is available for **xAI** (Grok Imagine via `/v1/videos/generations`, plus editing and extension through `providerOptions.xai`); other providers throw a clear error — OpenAI's Videos API (Sora) is deprecated (shutting down September 2026) and Google's Veo models aren't batch-supported. Results are signed URLs that **expire ~1h** after completion, so download them promptly.
130
+
131
+ ## Transcriptions
132
+
133
+ Transcribe audio in bulk — pass a transcription model and hosted audio URLs, and get transcripts back on `result.text`:
134
+
135
+ ```ts
136
+ import { batch } from "batchwork";
137
+ import { groq } from "@ai-sdk/groq";
138
+
139
+ const job = await batch.transcriptions({
140
+ model: groq.transcription("whisper-large-v3"),
141
+ requests: [
142
+ { customId: "a", audioUrl: "https://example.com/interview.wav" },
143
+ { customId: "b", audioUrl: "https://example.com/standup.mp3" },
144
+ ],
145
+ });
146
+
147
+ const results = await job.wait().then(() => job.collect());
148
+ for (const r of results) {
149
+ console.log(r.customId, r.text);
150
+ }
151
+ ```
152
+
153
+ Batch transcription is available for **Groq** (`whisper-large-v3`, audio by `url`), **Mistral** (Voxtral models, e.g. `"mistral/voxtral-mini-latest"`, audio by `file_url`), and **Together AI** (Whisper models, e.g. `"together/openai/whisper-large-v3"`, audio by `file`); other providers throw a clear error — OpenAI's batch API doesn't accept its audio endpoints. Batch audio endpoints take **hosted URLs only** (no file uploads), so each `audioUrl` must stay reachable while the batch processes. Request `timestampGranularities: ["segment"]` to also get timestamped spans on `result.segments`.
154
+
155
+ `batch.translations()` runs Whisper's **translate** task instead — audio in any language, English text out — on **Groq** (`whisper-large-v3` only) and **Together AI**, with the same request shape minus `language`.
156
+
157
+ ## Moderations
158
+
159
+ Moderate content in bulk — pass a moderation model and texts (or image URLs, OpenAI omni moderation only), and get verdicts back on `result.moderation`:
160
+
161
+ ```ts
162
+ import { batch } from "batchwork";
163
+
164
+ const job = await batch.moderations({
165
+ model: "openai/omni-moderation-latest",
166
+ requests: [
167
+ { customId: "a", value: "What a lovely day for a picnic." },
168
+ { customId: "b", value: "…user-generated content…" },
169
+ ],
170
+ });
171
+
172
+ const results = await job.wait().then(() => job.collect());
173
+ for (const r of results) {
174
+ console.log(r.customId, r.moderation?.flagged, r.moderation?.categories);
175
+ }
176
+ ```
177
+
178
+ Batch moderation is available for **OpenAI** (`omni-moderation-latest`, text + images) and **Mistral** (`mistral-moderation-latest`, text-only); other providers throw a clear error. Models are passed as `"provider/model"` strings (the AI SDK has no moderation model type). Category names are provider-native; `flagged` is the provider's own flag (OpenAI) or "any category flagged" (Mistral).
92
179
 
93
180
  ## Features
94
181
 
95
182
  - **One API, many providers** — OpenAI, Anthropic, Google Gemini, Groq, Mistral, Together AI, and xAI.
96
183
  - **AI SDK native** — author requests in the familiar `generateText` shape.
97
- - **Chat, embeddings & images** — `batch()` for completions, `batch.embeddings()` for vectors, `batch.images()` for image generation.
184
+ - **Chat, embeddings, images, video, audio & moderation** — `batch()` for completions, `batch.embeddings()` for vectors, `batch.images()` for image generation, `batch.videos()` for video generation, `batch.transcriptions()` for audio transcription, `batch.moderations()` for content moderation.
98
185
  - **~50% cheaper** — every request runs against the provider's batch window.
99
186
  - **Normalized results** — unified status, text, usage, and error types regardless of provider.
100
187
  - **Server-ready** — optional layers for managed polling, unified webhooks, and Next.js route handlers.
package/dist/batch.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { BatchJob } from "./job";
2
- import type { BatchEmbeddingsOptions, BatchImageOptions, BatchOptions, BatchRef, BatchResult } from "./types";
2
+ import type { BatchEmbeddingsOptions, BatchImageEditOptions, BatchImageOptions, BatchModerationOptions, BatchOptions, BatchRef, BatchResult, BatchTranscriptionOptions, BatchTranslationOptions, BatchVideoOptions } from "./types";
3
3
  /**
4
4
  * Submit a batch of text/chat requests to the model's provider and return a
5
5
  * handle. Reachable as both `batch()` (shorthand) and `batch.text()`.
@@ -50,6 +50,103 @@ declare const submitEmbeddings: (options: BatchEmbeddingsOptions) => Promise<Bat
50
50
  * }
51
51
  */
52
52
  declare const submitImages: (options: BatchImageOptions) => Promise<BatchJob>;
53
+ /**
54
+ * Submit a batch of image-edit requests to the model's provider and return a
55
+ * handle. Each request's `prompt` is applied to its source `images` (uploaded
56
+ * file ids or hosted URLs — batch bodies are JSON, so raw uploads aren't
57
+ * possible), producing edited images on `result.images`, correlated by
58
+ * `customId` via {@link BatchJob.results}. Supported for OpenAI and xAI; other
59
+ * providers throw {@link UnsupportedProviderError}.
60
+ *
61
+ * @example
62
+ * const job = await batch.images.edit({
63
+ * model: openai.image("gpt-image-2"),
64
+ * requests: [
65
+ * {
66
+ * customId: "a",
67
+ * prompt: "Make the bicycle blue.",
68
+ * images: [{ imageUrl: "https://example.com/bicycle.png" }],
69
+ * },
70
+ * ],
71
+ * });
72
+ * const results = await job.wait().then(() => job.collect());
73
+ */
74
+ declare const submitImageEdits: (options: BatchImageEditOptions) => Promise<BatchJob>;
75
+ /**
76
+ * Submit a batch of moderation requests to the model's provider and return a
77
+ * handle. Each request's `value` (and/or `imageUrls`, OpenAI omni moderation
78
+ * only) produces one verdict on `result.moderation`, correlated by `customId`
79
+ * via {@link BatchJob.results}. Supported for OpenAI and Mistral; other
80
+ * providers throw {@link UnsupportedProviderError}. Pass the model as a
81
+ * `"provider/model"` string — the AI SDK has no moderation model type.
82
+ *
83
+ * @example
84
+ * const job = await batch.moderations({
85
+ * model: "openai/omni-moderation-latest",
86
+ * requests: [{ customId: "a", value: "…user-generated content…" }],
87
+ * });
88
+ * const results = await job.wait().then(() => job.collect());
89
+ * for (const r of results) {
90
+ * console.log(r.customId, r.moderation?.flagged);
91
+ * }
92
+ */
93
+ declare const submitModerations: (options: BatchModerationOptions) => Promise<BatchJob>;
94
+ /**
95
+ * Submit a batch of audio-transcription requests to the model's provider and
96
+ * return a handle. Each request's `audioUrl` (a hosted audio file — batch
97
+ * audio endpoints accept URLs, not file uploads) produces one transcript,
98
+ * correlated by `customId` via {@link BatchJob.results}. Supported for Groq
99
+ * and Mistral; other providers throw {@link UnsupportedProviderError}.
100
+ *
101
+ * @example
102
+ * const job = await batch.transcriptions({
103
+ * model: groq.transcription("whisper-large-v3"),
104
+ * requests: [{ customId: "a", audioUrl: "https://example.com/call.wav" }],
105
+ * });
106
+ * const results = await job.wait().then(() => job.collect());
107
+ * for (const r of results) {
108
+ * console.log(r.customId, r.text);
109
+ * }
110
+ */
111
+ declare const submitTranscriptions: (options: BatchTranscriptionOptions) => Promise<BatchJob>;
112
+ /**
113
+ * Submit a batch of video-generation requests to the model's provider and
114
+ * return a handle. Each request's `prompt` produces one video, correlated by
115
+ * `customId` via {@link BatchJob.results}. Supported for xAI (Grok Imagine);
116
+ * other providers throw {@link UnsupportedProviderError} — OpenAI's Videos API
117
+ * (Sora) is deprecated and Google's Veo models are not batch-compatible.
118
+ *
119
+ * Results come back as signed URLs on `result.videos` that **expire ~1h**
120
+ * after completion — download promptly.
121
+ *
122
+ * @example
123
+ * const job = await batch.videos({
124
+ * model: xai.video("grok-imagine-video"),
125
+ * requests: [{ customId: "a", prompt: "A red bicycle rolling downhill." }],
126
+ * });
127
+ * const results = await job.wait().then(() => job.collect());
128
+ * for (const r of results) {
129
+ * console.log(r.customId, r.videos?.[0]?.url);
130
+ * }
131
+ */
132
+ declare const submitVideos: (options: BatchVideoOptions) => Promise<BatchJob>;
133
+ /**
134
+ * Submit a batch of audio-translation requests (Whisper's translate task —
135
+ * audio in any language, English text out) and return a handle. Mirrors
136
+ * {@link batch.transcriptions} minus `language`: each request's `audioUrl`
137
+ * produces one English transcript on `result.text`, correlated by `customId`.
138
+ * Supported for Groq and Together; other providers throw
139
+ * {@link UnsupportedProviderError} — Mistral batches transcriptions but not
140
+ * translations.
141
+ *
142
+ * @example
143
+ * const job = await batch.translations({
144
+ * model: groq.transcription("whisper-large-v3"),
145
+ * requests: [{ customId: "a", audioUrl: "https://example.com/french.wav" }],
146
+ * });
147
+ * const results = await job.wait().then(() => job.collect());
148
+ */
149
+ declare const submitTranslations: (options: BatchTranslationOptions) => Promise<BatchJob>;
53
150
  /**
54
151
  * Submit a batch of requests and return a {@link BatchJob} handle.
55
152
  *
@@ -58,7 +155,12 @@ declare const submitImages: (options: BatchImageOptions) => Promise<BatchJob>;
58
155
  *
59
156
  * - `batch()` / {@link batch.text} — text & chat completions
60
157
  * - {@link batch.embeddings} — embedding vectors
61
- * - {@link batch.images} — image generation
158
+ * - {@link batch.images} / {@link batch.images.create} — image generation
159
+ * - {@link batch.images.edit} — image editing
160
+ * - {@link batch.transcriptions} — audio transcription
161
+ * - {@link batch.translations} — audio translation to English
162
+ * - {@link batch.moderations} — content moderation
163
+ * - {@link batch.videos} — video generation
62
164
  *
63
165
  * @example
64
166
  * const job = await batch({
@@ -69,10 +171,27 @@ declare const submitImages: (options: BatchImageOptions) => Promise<BatchJob>;
69
171
  export declare const batch: typeof submitText & {
70
172
  /** Submit a batch of embedding requests. */
71
173
  embeddings: typeof submitEmbeddings;
72
- /** Submit a batch of image-generation requests. */
73
- images: typeof submitImages;
174
+ /**
175
+ * Submit a batch of image-generation requests. Also exposes
176
+ * {@link batch.images.create} (an alias of calling it directly) and
177
+ * {@link batch.images.edit} for editing existing images.
178
+ */
179
+ images: typeof submitImages & {
180
+ /** Submit a batch of image-generation requests. Equivalent to `batch.images()`. */
181
+ create: typeof submitImages;
182
+ /** Submit a batch of image-edit requests. */
183
+ edit: typeof submitImageEdits;
184
+ };
185
+ /** Submit a batch of moderation requests. */
186
+ moderations: typeof submitModerations;
74
187
  /** Submit a batch of text/chat requests. Equivalent to calling `batch()`. */
75
188
  text: typeof submitText;
189
+ /** Submit a batch of audio-transcription requests. */
190
+ transcriptions: typeof submitTranscriptions;
191
+ /** Submit a batch of audio-translation (to English) requests. */
192
+ translations: typeof submitTranslations;
193
+ /** Submit a batch of video-generation requests. */
194
+ videos: typeof submitVideos;
76
195
  };
77
196
  /**
78
197
  * @deprecated Use {@link batch.embeddings} instead. Kept as a standalone alias
@@ -1 +1 @@
1
- {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAUjC,OAAO,KAAK,EACV,sBAAsB,EACtB,iBAAiB,EACjB,YAAY,EAEZ,QAAQ,EACR,WAAW,EAEZ,MAAM,SAAS,CAAC;AAsBjB;;;;;;;;;;;;;;GAcG;AACH,QAAA,MAAM,UAAU,YAAmB,YAAY,KAAG,OAAO,CAAC,QAAQ,CA2BjE,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,gBAAgB,YACX,sBAAsB,KAC9B,OAAO,CAAC,QAAQ,CA6BlB,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,YAAY,YAAmB,iBAAiB,KAAG,OAAO,CAAC,QAAQ,CA8BxE,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,KAAK;IAChB,4CAA4C;;IAE5C,mDAAmD;;IAEnD,6EAA6E;;CAE7E,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,eAAe,yBAAmB,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,WAAW,qBAAe,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,QAAQ,QAAe,QAAQ,KAAG,OAAO,CAAC,QAAQ,CAK9D,CAAC;AAEF,uEAAuE;AACvE,eAAO,MAAM,eAAe,QAAS,QAAQ,KAAG,cAAc,CAAC,WAAW,CAGzE,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,WAAW,QAAe,QAAQ,KAAG,OAAO,CAAC,IAAI,CAG7D,CAAC"}
1
+ {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAoBjC,OAAO,KAAK,EACV,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,YAAY,EAEZ,QAAQ,EACR,WAAW,EACX,yBAAyB,EACzB,uBAAuB,EACvB,iBAAiB,EAElB,MAAM,SAAS,CAAC;AAsBjB;;;;;;;;;;;;;;GAcG;AACH,QAAA,MAAM,UAAU,YAAmB,YAAY,KAAG,OAAO,CAAC,QAAQ,CA2BjE,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,gBAAgB,YACX,sBAAsB,KAC9B,OAAO,CAAC,QAAQ,CA6BlB,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,YAAY,YAAmB,iBAAiB,KAAG,OAAO,CAAC,QAAQ,CA8BxE,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,QAAA,MAAM,gBAAgB,YACX,qBAAqB,KAC7B,OAAO,CAAC,QAAQ,CA6BlB,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,iBAAiB,YACZ,sBAAsB,KAC9B,OAAO,CAAC,QAAQ,CAwBlB,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,QAAA,MAAM,oBAAoB,YACf,yBAAyB,KACjC,OAAO,CAAC,QAAQ,CA6BlB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,QAAA,MAAM,YAAY,YAAmB,iBAAiB,KAAG,OAAO,CAAC,QAAQ,CA8BxE,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,kBAAkB,YACb,uBAAuB,KAC/B,OAAO,CAAC,QAAQ,CA6BlB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,KAAK;IAChB,4CAA4C;;IAE5C;;;;OAIG;;QAED,mFAAmF;;QAEnF,6CAA6C;;;IAG/C,6CAA6C;;IAE7C,6EAA6E;;IAE7E,sDAAsD;;IAEtD,iEAAiE;;IAEjE,mDAAmD;;CAEnD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,eAAe,yBAAmB,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,WAAW,qBAAe,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,QAAQ,QAAe,QAAQ,KAAG,OAAO,CAAC,QAAQ,CAK9D,CAAC;AAEF,uEAAuE;AACvE,eAAO,MAAM,eAAe,QAAS,QAAQ,KAAG,cAAc,CAAC,WAAW,CAGzE,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,WAAW,QAAe,QAAQ,KAAG,OAAO,CAAC,IAAI,CAG7D,CAAC"}
package/dist/body.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { ResolvedBatchLimits } from "./limits";
2
2
  import type { ResolvedModel } from "./model";
3
- import type { BatchDefaults, BatchEmbeddingRequest, BatchImageDefaults, BatchImageRequest, BatchLimits, BatchRequest, ProviderCredentials } from "./types";
3
+ import type { BatchDefaults, BatchEmbeddingRequest, BatchImageDefaults, BatchImageEditDefaults, BatchImageEditRequest, BatchImageRequest, BatchLimits, BatchModerationRequest, BatchRequest, BatchTranscriptionDefaults, BatchTranscriptionRequest, BatchTranslationDefaults, BatchTranslationRequest, BatchVideoDefaults, BatchVideoRequest, ProviderCredentials } from "./types";
4
4
  /** A provider request body derived from a single batch item. */
5
5
  export interface BuiltRequest {
6
6
  /** The serialized provider request body (becomes the batch line). */
@@ -23,6 +23,23 @@ export declare const buildRequestBodies: (resolved: ResolvedModel, requests: rea
23
23
  * single embedding (`input: [value]`), correlated by `customId`.
24
24
  */
25
25
  export declare const buildEmbeddingBodies: (resolved: ResolvedModel, requests: readonly BatchEmbeddingRequest[], credentials: ProviderCredentials, rawLimits?: BatchLimits | ResolvedBatchLimits) => Promise<BuiltRequest[]>;
26
+ /**
27
+ * Build provider moderation request bodies for every batch item. Each item
28
+ * maps to a single moderation verdict, correlated by `customId`.
29
+ */
30
+ export declare const buildModerationBodies: (resolved: ResolvedModel, requests: readonly BatchModerationRequest[], rawLimits?: BatchLimits | ResolvedBatchLimits) => BuiltRequest[];
31
+ /**
32
+ * Build provider transcription request bodies for every batch item. Each item
33
+ * maps to a single transcription of a hosted audio URL, correlated by
34
+ * `customId`.
35
+ */
36
+ export declare const buildTranscriptionBodies: (resolved: ResolvedModel, requests: readonly BatchTranscriptionRequest[], defaults: BatchTranscriptionDefaults | undefined, rawLimits?: BatchLimits | ResolvedBatchLimits) => BuiltRequest[];
37
+ /**
38
+ * Build provider audio-translation request bodies for every batch item. The
39
+ * body shape is identical to transcription (minus `language` — the output is
40
+ * always English); only the endpoint differs.
41
+ */
42
+ export declare const buildTranslationBodies: (resolved: ResolvedModel, requests: readonly BatchTranslationRequest[], defaults: BatchTranslationDefaults | undefined, rawLimits?: BatchLimits | ResolvedBatchLimits) => BuiltRequest[];
26
43
  /**
27
44
  * Derive provider image-generation request bodies for every batch item by
28
45
  * running each through the AI SDK `generateImage` with a capturing `fetch`.
@@ -30,4 +47,16 @@ export declare const buildEmbeddingBodies: (resolved: ResolvedModel, requests: r
30
47
  * single image-generation call, correlated by `customId`.
31
48
  */
32
49
  export declare const buildImageBodies: (resolved: ResolvedModel, requests: readonly BatchImageRequest[], defaults: BatchImageDefaults | undefined, credentials: ProviderCredentials, rawLimits?: BatchLimits | ResolvedBatchLimits) => Promise<BuiltRequest[]>;
50
+ /**
51
+ * Build provider image-edit request bodies for every batch item. Each item
52
+ * maps to a single edit call, correlated by `customId`.
53
+ */
54
+ export declare const buildImageEditBodies: (resolved: ResolvedModel, requests: readonly BatchImageEditRequest[], defaults: BatchImageEditDefaults | undefined, rawLimits?: BatchLimits | ResolvedBatchLimits) => BuiltRequest[];
55
+ /**
56
+ * Derive provider video-generation request bodies for every batch item by
57
+ * running each through the AI SDK `generateVideo` with a capturing `fetch`.
58
+ * Mirrors {@link buildRequestBodies} for the video endpoints; each item maps to
59
+ * a single video job, correlated by `customId`.
60
+ */
61
+ export declare const buildVideoBodies: (resolved: ResolvedModel, requests: readonly BatchVideoRequest[], defaults: BatchVideoDefaults | undefined, credentials: ProviderCredentials, rawLimits?: BatchLimits | ResolvedBatchLimits) => Promise<BuiltRequest[]>;
33
62
  //# sourceMappingURL=body.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"body.d.ts","sourceRoot":"","sources":["../src/body.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAMpD,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,KAAK,EACV,aAAa,EACb,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,YAAY,EACZ,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAIjB,gEAAgE;AAChE,MAAM,WAAW,YAAY;IAC3B,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAgOD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,aACnB,aAAa,YACb,SAAS,YAAY,EAAE,YACvB,aAAa,GAAG,SAAS,eACtB,mBAAmB,cACpB,WAAW,GAAG,mBAAmB,KAC5C,OAAO,CAAC,YAAY,EAAE,CA4BxB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,aACrB,aAAa,YACb,SAAS,qBAAqB,EAAE,eAC7B,mBAAmB,cACpB,WAAW,GAAG,mBAAmB,KAC5C,OAAO,CAAC,YAAY,EAAE,CAgCxB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,aACjB,aAAa,YACb,SAAS,iBAAiB,EAAE,YAC5B,kBAAkB,GAAG,SAAS,eAC3B,mBAAmB,cACpB,WAAW,GAAG,mBAAmB,KAC5C,OAAO,CAAC,YAAY,EAAE,CAgCxB,CAAC"}
1
+ {"version":3,"file":"body.d.ts","sourceRoot":"","sources":["../src/body.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAUpD,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,KAAK,EACV,aAAa,EACb,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EAErB,iBAAiB,EACjB,WAAW,EACX,sBAAsB,EACtB,YAAY,EACZ,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,EACxB,uBAAuB,EACvB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EAEpB,MAAM,SAAS,CAAC;AAIjB,gEAAgE;AAChE,MAAM,WAAW,YAAY;IAC3B,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAgOD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,aACnB,aAAa,YACb,SAAS,YAAY,EAAE,YACvB,aAAa,GAAG,SAAS,eACtB,mBAAmB,cACpB,WAAW,GAAG,mBAAmB,KAC5C,OAAO,CAAC,YAAY,EAAE,CA4BxB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,aACrB,aAAa,YACb,SAAS,qBAAqB,EAAE,eAC7B,mBAAmB,cACpB,WAAW,GAAG,mBAAmB,KAC5C,OAAO,CAAC,YAAY,EAAE,CAgCxB,CAAC;AAyDF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,aACtB,aAAa,YACb,SAAS,sBAAsB,EAAE,cAC/B,WAAW,GAAG,mBAAmB,KAC5C,YAAY,EAgBd,CAAC;AA0FF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,aACzB,aAAa,YACb,SAAS,yBAAyB,EAAE,YACpC,0BAA0B,GAAG,SAAS,cACpC,WAAW,GAAG,mBAAmB,KAC5C,YAAY,EAOZ,CAAC;AAEJ;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,aACvB,aAAa,YACb,SAAS,uBAAuB,EAAE,YAClC,wBAAwB,GAAG,SAAS,cAClC,WAAW,GAAG,mBAAmB,KAC5C,YAAY,EAOZ,CAAC;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,aACjB,aAAa,YACb,SAAS,iBAAiB,EAAE,YAC5B,kBAAkB,GAAG,SAAS,eAC3B,mBAAmB,cACpB,WAAW,GAAG,mBAAmB,KAC5C,OAAO,CAAC,YAAY,EAAE,CAgCxB,CAAC;AAmEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,aACrB,aAAa,YACb,SAAS,qBAAqB,EAAE,YAChC,sBAAsB,GAAG,SAAS,cAChC,WAAW,GAAG,mBAAmB,KAC5C,YAAY,EAoBd,CAAC;AAiCF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,aACjB,aAAa,YACb,SAAS,iBAAiB,EAAE,YAC5B,kBAAkB,GAAG,SAAS,eAC3B,mBAAmB,cACpB,WAAW,GAAG,mBAAmB,KAC5C,OAAO,CAAC,YAAY,EAAE,CAgCxB,CAAC"}
@@ -2,7 +2,7 @@ import {
2
2
  BatchworkError,
3
3
  getAdapter,
4
4
  isTerminalStatus
5
- } from "./chunk-jvrfwjwq.js";
5
+ } from "./chunk-gwa0dkhj.js";
6
6
 
7
7
  // src/server/events.ts
8
8
  var EVENT_BY_STATUS = {
@@ -402,4 +402,4 @@ var createMemoryStore = () => {
402
402
  export { toEvent, signWebhook, verifyWebhook, verifyBatchWebhook, createBatchPoller, createMemoryStore };
403
403
 
404
404
  //# debugId=F1B4BA11C9A6AE3364756E2164756E21
405
- //# sourceMappingURL=chunk-c7hzcpdy.js.map
405
+ //# sourceMappingURL=chunk-9cwfwzm4.js.map
@@ -777,7 +777,26 @@ var textFromBody = (body) => {
777
777
  return content;
778
778
  }
779
779
  }
780
- return asString(obj.output_text);
780
+ return asString(obj.output_text) ?? asString(obj.text);
781
+ };
782
+ var segmentsFromBody = (body) => {
783
+ const obj = asRecord(body);
784
+ if (asString(obj.text) === undefined) {
785
+ return;
786
+ }
787
+ const segments = [];
788
+ for (const item of asArray(obj.segments)) {
789
+ const segment = asRecord(item);
790
+ const text = asString(segment.text);
791
+ if (text !== undefined) {
792
+ segments.push({
793
+ endSecond: asNumber(segment.end),
794
+ startSecond: asNumber(segment.start),
795
+ text
796
+ });
797
+ }
798
+ }
799
+ return segments.length > 0 ? segments : undefined;
781
800
  };
782
801
  var embeddingFromBody = (body) => {
783
802
  const data = asArray(asRecord(body).data);
@@ -798,6 +817,31 @@ var imagesFromBody = (body) => {
798
817
  }
799
818
  return images.length > 0 ? images : undefined;
800
819
  };
820
+ var moderationFromBody = (body) => {
821
+ const results3 = asArray(asRecord(body).results);
822
+ if (results3.length === 0) {
823
+ return;
824
+ }
825
+ const first = asRecord(results3[0]);
826
+ const categories = {};
827
+ for (const [key, value] of Object.entries(asRecord(first.categories))) {
828
+ if (typeof value === "boolean") {
829
+ categories[key] = value;
830
+ }
831
+ }
832
+ if (Object.keys(categories).length === 0) {
833
+ return;
834
+ }
835
+ const categoryScores = {};
836
+ for (const [key, value] of Object.entries(asRecord(first.category_scores))) {
837
+ const score = asNumber(value);
838
+ if (score !== undefined) {
839
+ categoryScores[key] = score;
840
+ }
841
+ }
842
+ const flagged = typeof first.flagged === "boolean" ? first.flagged : Object.values(categories).some(Boolean);
843
+ return { categories, categoryScores, flagged };
844
+ };
801
845
  var usageFromBody = (body) => {
802
846
  const usage = asRecord(asRecord(body).usage);
803
847
  const inputTokens = asNumber(usage.prompt_tokens) ?? asNumber(usage.input_tokens);
@@ -840,7 +884,9 @@ var normalizeOpenAIResult = (line) => {
840
884
  customId,
841
885
  embedding: embeddingFromBody(response.body),
842
886
  images: imagesFromBody(response.body),
887
+ moderation: moderationFromBody(response.body),
843
888
  response: response.body,
889
+ segments: segmentsFromBody(response.body),
844
890
  status: "succeeded",
845
891
  text: textFromBody(response.body),
846
892
  usage: usageFromBody(response.body)
@@ -932,7 +978,11 @@ var createOpenAICompatibleAdapter = (config) => {
932
978
  const jsonl = encodeJsonl(input.built.map((item) => {
933
979
  const body = omit(item.body, "stream");
934
980
  if (lineFormat === "body-only") {
935
- return { body, custom_id: item.customId };
981
+ return {
982
+ body,
983
+ custom_id: item.customId,
984
+ ...config.lineExtras?.(endpoint)
985
+ };
936
986
  }
937
987
  return {
938
988
  body,
@@ -1232,6 +1282,7 @@ var togetherAdapter = createOpenAICompatibleAdapter({
1232
1282
  baseUrl: "https://api.together.xyz/v1",
1233
1283
  filePurpose: "batch-api",
1234
1284
  id: "together",
1285
+ lineExtras: (endpoint) => endpoint.startsWith("/v1/audio/") ? { method: "FILE" } : undefined,
1235
1286
  lineFormat: "body-only",
1236
1287
  uploadFile: uploadTogetherFile
1237
1288
  });
@@ -1303,6 +1354,25 @@ var imagesFromXaiCompletion = (completion) => {
1303
1354
  }
1304
1355
  return images.length > 0 ? images : undefined;
1305
1356
  };
1357
+ var videosFromXaiCompletion = (completion) => {
1358
+ const obj = asRecord(completion);
1359
+ const entries = asArray(obj.data);
1360
+ const sources = entries.length > 0 ? entries : [obj];
1361
+ const videos = [];
1362
+ for (const source of sources) {
1363
+ const record = asRecord(source);
1364
+ const video = asRecord(record.video);
1365
+ const url = asString(video.url) ?? asString(record.url);
1366
+ if (url) {
1367
+ const duration = asNumber(video.duration) ?? asNumber(record.duration);
1368
+ videos.push({
1369
+ ...duration === undefined ? {} : { durationSeconds: duration },
1370
+ url
1371
+ });
1372
+ }
1373
+ }
1374
+ return videos.length > 0 ? videos : undefined;
1375
+ };
1306
1376
  var normalizeResult3 = (item) => {
1307
1377
  const obj = asRecord(item);
1308
1378
  const customId = asString(obj.batch_request_id) ?? "";
@@ -1321,10 +1391,12 @@ var normalizeResult3 = (item) => {
1321
1391
  };
1322
1392
  }
1323
1393
  const response = asRecord(batchResult.response);
1394
+ const [opKey] = Object.keys(response);
1324
1395
  const completion = response.chat_get_completion ?? Object.values(response)[0];
1396
+ const isVideo = response.chat_get_completion === undefined && opKey !== undefined && opKey.includes("video");
1325
1397
  return {
1326
1398
  customId,
1327
- images: imagesFromXaiCompletion(completion),
1399
+ ...isVideo ? { videos: videosFromXaiCompletion(completion) } : { images: imagesFromXaiCompletion(completion) },
1328
1400
  response: completion,
1329
1401
  status: "succeeded",
1330
1402
  text: textFromBody(completion),
@@ -1337,7 +1409,7 @@ var submit4 = async (input) => {
1337
1409
  body: omit(item.body, "stream"),
1338
1410
  custom_id: item.customId,
1339
1411
  method: "POST",
1340
- url: input.endpoint
1412
+ url: item.endpoint || input.endpoint
1341
1413
  })), { label: "batch upload JSONL", maxBytes: limits.maxUploadBytes });
1342
1414
  const inputFileId = await uploadInputFile(jsonl, baseUrl4(input.credentials), authHeaders2(input.credentials), { purpose: null });
1343
1415
  const raw = await requestJson(`${baseUrl4(input.credentials)}/batches`, {
@@ -1403,5 +1475,5 @@ var getAdapter = (provider) => adapters[provider];
1403
1475
 
1404
1476
  export { BatchworkError, UnsupportedProviderError, MissingDependencyError, resolveBatchLimits, assertByteLength, mapWithConcurrency, isTerminalStatus, BatchJob, getAdapter };
1405
1477
 
1406
- //# debugId=032D6B4F83FC26F964756E2164756E21
1407
- //# sourceMappingURL=chunk-jvrfwjwq.js.map
1478
+ //# debugId=4C939B96519322C164756E2164756E21
1479
+ //# sourceMappingURL=chunk-gwa0dkhj.js.map