batchwork 1.1.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/README.md +32 -4
- package/dist/batch.d.ts +23 -21
- package/dist/batch.d.ts.map +1 -1
- package/dist/body.d.ts +8 -1
- package/dist/body.d.ts.map +1 -1
- package/dist/{chunk-d0g9wsxq.js → chunk-3yqs6x71.js} +2 -2
- package/dist/{chunk-yzjd83s9.js → chunk-bjkbtj1q.js} +107 -10
- package/dist/chunk-bjkbtj1q.js.map +12 -0
- package/dist/{chunk-xtk2ycy6.js → chunk-h2he3d16.js} +49 -2
- package/dist/{chunk-xtk2ycy6.js.map → chunk-h2he3d16.js.map} +5 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/model.d.ts +17 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/next/index.js +3 -3
- package/dist/providers/google.d.ts.map +1 -1
- package/dist/providers/shared.d.ts +7 -1
- package/dist/providers/shared.d.ts.map +1 -1
- package/dist/providers/xai.d.ts.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/types.d.ts +49 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-yzjd83s9.js.map +0 -12
- /package/dist/{chunk-d0g9wsxq.js.map → chunk-3yqs6x71.js.map} +0 -0
package/README.md
CHANGED
|
@@ -46,11 +46,11 @@ Author requests in the same `generateText` shape you already use, pass the AI SD
|
|
|
46
46
|
Batch embeddings work the same way — pass a text embedding model and `value`s, and get one vector per request back on `result.embedding`:
|
|
47
47
|
|
|
48
48
|
```ts
|
|
49
|
-
import {
|
|
49
|
+
import { batch } from "batchwork";
|
|
50
50
|
import { openai } from "@ai-sdk/openai";
|
|
51
51
|
|
|
52
|
-
const job = await
|
|
53
|
-
model: openai.
|
|
52
|
+
const job = await batch.embeddings({
|
|
53
|
+
model: openai.embeddingModel("text-embedding-3-small"),
|
|
54
54
|
requests: [
|
|
55
55
|
{ customId: "a", value: "The quick brown fox." },
|
|
56
56
|
{ customId: "b", value: "A lazy dog sleeps." },
|
|
@@ -65,11 +65,39 @@ for (const r of results) {
|
|
|
65
65
|
|
|
66
66
|
Batch embeddings are available for **OpenAI, Mistral, and Google Gemini** — the providers whose batch API accepts embeddings. The rest throw a clear error: Anthropic, Groq, and xAI have no embedding model, and Together AI's batch API doesn't accept the embeddings endpoint.
|
|
67
67
|
|
|
68
|
+
## Images
|
|
69
|
+
|
|
70
|
+
Generate images in bulk — pass an image model and `prompt`s, and get base64 images back on `result.images`:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import { batch } from "batchwork";
|
|
74
|
+
import { openai } from "@ai-sdk/openai";
|
|
75
|
+
|
|
76
|
+
const job = await batch.images({
|
|
77
|
+
model: openai.image("gpt-image-2"),
|
|
78
|
+
requests: [
|
|
79
|
+
{ customId: "a", prompt: "A red bicycle against a brick wall." },
|
|
80
|
+
{ customId: "b", prompt: "A watercolor painting of a sleeping cat." },
|
|
81
|
+
],
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const results = await job.wait().then(() => job.collect());
|
|
85
|
+
for (const r of results) {
|
|
86
|
+
for (const image of r.images ?? []) {
|
|
87
|
+
// Inline base64 (`image.data` + `image.mediaType`), or a hosted
|
|
88
|
+
// `image.url` for providers that return one (e.g. xAI batch).
|
|
89
|
+
console.log(r.customId, image.mediaType ?? image.url);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
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.
|
|
95
|
+
|
|
68
96
|
## Features
|
|
69
97
|
|
|
70
98
|
- **One API, many providers** — OpenAI, Anthropic, Google Gemini, Groq, Mistral, Together AI, and xAI.
|
|
71
99
|
- **AI SDK native** — author requests in the familiar `generateText` shape.
|
|
72
|
-
- **Chat &
|
|
100
|
+
- **Chat, embeddings & images** — `batch()` for completions, `batch.embeddings()` for vectors, `batch.images()` for image generation.
|
|
73
101
|
- **~50% cheaper** — every request runs against the provider's batch window.
|
|
74
102
|
- **Normalized results** — unified status, text, usage, and error types regardless of provider.
|
|
75
103
|
- **Server-ready** — optional layers for managed polling, unified webhooks, and Next.js route handlers.
|
package/dist/batch.d.ts
CHANGED
|
@@ -1,37 +1,39 @@
|
|
|
1
1
|
import { BatchJob } from "./job";
|
|
2
|
-
import type { BatchEmbeddingsOptions, BatchOptions, BatchRef, BatchResult } from "./types";
|
|
2
|
+
import type { BatchEmbeddingsOptions, BatchImageOptions, BatchOptions, BatchRef, BatchResult } from "./types";
|
|
3
3
|
/**
|
|
4
|
-
* Submit a batch of requests
|
|
4
|
+
* Submit a batch of requests and return a {@link BatchJob} handle.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Callable directly as a shorthand for text/chat batches, with one method per
|
|
7
|
+
* modality:
|
|
8
|
+
*
|
|
9
|
+
* - `batch()` / {@link batch.text} — text & chat completions
|
|
10
|
+
* - {@link batch.embeddings} — embedding vectors
|
|
11
|
+
* - {@link batch.images} — image generation
|
|
9
12
|
*
|
|
10
13
|
* @example
|
|
11
14
|
* const job = await batch({
|
|
12
15
|
* model: openai("gpt-5.5"),
|
|
13
16
|
* requests: [{ customId: "a", prompt: "Say hi" }],
|
|
14
17
|
* });
|
|
15
|
-
* const results = await job.wait().then(() => job.collect());
|
|
16
18
|
*/
|
|
17
|
-
export declare const batch: (options: BatchOptions) => Promise<BatchJob
|
|
19
|
+
export declare const batch: ((options: BatchOptions) => Promise<BatchJob>) & {
|
|
20
|
+
/** Submit a batch of embedding requests. */
|
|
21
|
+
embeddings: (options: BatchEmbeddingsOptions) => Promise<BatchJob>;
|
|
22
|
+
/** Submit a batch of image-generation requests. */
|
|
23
|
+
images: (options: BatchImageOptions) => Promise<BatchJob>;
|
|
24
|
+
/** Submit a batch of text/chat requests. Equivalent to calling `batch()`. */
|
|
25
|
+
text: (options: BatchOptions) => Promise<BatchJob>;
|
|
26
|
+
};
|
|
18
27
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* via {@link BatchJob.results}. Supported for OpenAI, Mistral, Together, and
|
|
22
|
-
* Google; other providers throw {@link UnsupportedProviderError}.
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* const job = await batchEmbeddings({
|
|
26
|
-
* model: openai.textEmbeddingModel("text-embedding-3-small"),
|
|
27
|
-
* requests: [{ customId: "a", value: "hello world" }],
|
|
28
|
-
* });
|
|
29
|
-
* const results = await job.wait().then(() => job.collect());
|
|
30
|
-
* for (const r of results) {
|
|
31
|
-
* console.log(r.customId, r.embedding?.length);
|
|
32
|
-
* }
|
|
28
|
+
* @deprecated Use {@link batch.embeddings} instead. Kept as a standalone alias
|
|
29
|
+
* for backward compatibility; it will be removed in a future major.
|
|
33
30
|
*/
|
|
34
31
|
export declare const batchEmbeddings: (options: BatchEmbeddingsOptions) => Promise<BatchJob>;
|
|
32
|
+
/**
|
|
33
|
+
* @deprecated Use {@link batch.images} instead. Kept as a standalone alias for
|
|
34
|
+
* backward compatibility; it will be removed in a future major.
|
|
35
|
+
*/
|
|
36
|
+
export declare const batchImages: (options: BatchImageOptions) => Promise<BatchJob>;
|
|
35
37
|
/**
|
|
36
38
|
* Rehydrate a {@link BatchJob} for an existing batch id (e.g. one persisted
|
|
37
39
|
* after submission). Identify the provider with `provider` or `model`.
|
package/dist/batch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"
|
|
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;AAiKjB;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,KAAK,aA9IiB,YAAY,KAAG,OAAO,CAAC,QAAQ,CAAC;IA+IjE,4CAA4C;0BAjGnC,sBAAsB,KAC9B,OAAO,CAAC,QAAQ,CAAC;IAkGlB,mDAAmD;sBAnDhB,iBAAiB,KAAG,OAAO,CAAC,QAAQ,CAAC;IAqDxE,6EAA6E;oBAnJ5C,YAAY,KAAG,OAAO,CAAC,QAAQ,CAAC;CAqJjE,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,eAAe,YA7GjB,sBAAsB,KAC9B,OAAO,CAAC,QAAQ,CA4G4B,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,WAAW,YAnEa,iBAAiB,KAAG,OAAO,CAAC,QAAQ,CAmElC,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, BatchLimits, BatchRequest, ProviderCredentials } from "./types";
|
|
3
|
+
import type { BatchDefaults, BatchEmbeddingRequest, BatchImageDefaults, BatchImageRequest, BatchLimits, BatchRequest, 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,4 +23,11 @@ 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
|
+
* Derive provider image-generation request bodies for every batch item by
|
|
28
|
+
* running each through the AI SDK `generateImage` with a capturing `fetch`.
|
|
29
|
+
* Mirrors {@link buildRequestBodies} for the image endpoint; each item maps to a
|
|
30
|
+
* single image-generation call, correlated by `customId`.
|
|
31
|
+
*/
|
|
32
|
+
export declare const buildImageBodies: (resolved: ResolvedModel, requests: readonly BatchImageRequest[], defaults: BatchImageDefaults | undefined, credentials: ProviderCredentials, rawLimits?: BatchLimits | ResolvedBatchLimits) => Promise<BuiltRequest[]>;
|
|
26
33
|
//# sourceMappingURL=body.d.ts.map
|
package/dist/body.d.ts.map
CHANGED
|
@@ -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;
|
|
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;AAYF;;;;;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-
|
|
5
|
+
} from "./chunk-h2he3d16.js";
|
|
6
6
|
|
|
7
7
|
// src/server/events.ts
|
|
8
8
|
var EVENT_BY_STATUS = {
|
|
@@ -372,4 +372,4 @@ var createMemoryStore = () => {
|
|
|
372
372
|
export { toEvent, signWebhook, verifyWebhook, verifyBatchWebhook, createBatchPoller, createMemoryStore };
|
|
373
373
|
|
|
374
374
|
//# debugId=BAF36CF27957AA5864756E2164756E21
|
|
375
|
-
//# sourceMappingURL=chunk-
|
|
375
|
+
//# sourceMappingURL=chunk-3yqs6x71.js.map
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
getAdapter,
|
|
8
8
|
mapWithConcurrency,
|
|
9
9
|
resolveBatchLimits
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-h2he3d16.js";
|
|
11
11
|
import {
|
|
12
12
|
__require
|
|
13
13
|
} from "./chunk-v0bahtg2.js";
|
|
@@ -184,24 +184,55 @@ var createCaptureEmbeddingModel = async (resolved, credentials, fetchImpl) => {
|
|
|
184
184
|
switch (resolved.provider) {
|
|
185
185
|
case "openai": {
|
|
186
186
|
const { createOpenAI } = await loadProvider("openai");
|
|
187
|
-
return createOpenAI(settings).
|
|
187
|
+
return createOpenAI(settings).embeddingModel(resolved.modelId);
|
|
188
188
|
}
|
|
189
189
|
case "mistral": {
|
|
190
190
|
const { createMistral } = await loadProvider("mistral");
|
|
191
|
-
return createMistral(settings).
|
|
191
|
+
return createMistral(settings).embeddingModel(resolved.modelId);
|
|
192
192
|
}
|
|
193
193
|
case "google": {
|
|
194
194
|
const { createGoogleGenerativeAI } = await loadProvider("google");
|
|
195
|
-
return createGoogleGenerativeAI(settings).
|
|
195
|
+
return createGoogleGenerativeAI(settings).embeddingModel(resolved.modelId);
|
|
196
196
|
}
|
|
197
197
|
default: {
|
|
198
198
|
throw unsupportedEmbeddingProvider(resolved.provider);
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
};
|
|
202
|
+
var IMAGE_PROVIDERS = new Set([
|
|
203
|
+
"google",
|
|
204
|
+
"openai",
|
|
205
|
+
"xai"
|
|
206
|
+
]);
|
|
207
|
+
var unsupportedImageProvider = (provider) => new UnsupportedProviderError(provider, `batchwork: provider "${provider}" does not offer batch image generation. Image batches are supported for: openai, google, xai.`);
|
|
208
|
+
var createCaptureImageModel = async (resolved, credentials, fetchImpl) => {
|
|
209
|
+
const settings = {
|
|
210
|
+
apiKey: credentials.apiKey ?? CAPTURE_API_KEY,
|
|
211
|
+
baseURL: credentials.baseURL,
|
|
212
|
+
fetch: fetchImpl,
|
|
213
|
+
headers: credentials.headers
|
|
214
|
+
};
|
|
215
|
+
switch (resolved.provider) {
|
|
216
|
+
case "openai": {
|
|
217
|
+
const { createOpenAI } = await loadProvider("openai");
|
|
218
|
+
return createOpenAI(settings).image(resolved.modelId);
|
|
219
|
+
}
|
|
220
|
+
case "google": {
|
|
221
|
+
const { createGoogleGenerativeAI } = await loadProvider("google");
|
|
222
|
+
return createGoogleGenerativeAI(settings).image(resolved.modelId);
|
|
223
|
+
}
|
|
224
|
+
case "xai": {
|
|
225
|
+
const { createXai } = await loadProvider("xai");
|
|
226
|
+
return createXai(settings).image(resolved.modelId);
|
|
227
|
+
}
|
|
228
|
+
default: {
|
|
229
|
+
throw unsupportedImageProvider(resolved.provider);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
};
|
|
202
233
|
|
|
203
234
|
// src/body.ts
|
|
204
|
-
import { embed, generateText } from "ai";
|
|
235
|
+
import { embed, generateImage, generateText } from "ai";
|
|
205
236
|
var MAX_CAUSE_DEPTH = 10;
|
|
206
237
|
|
|
207
238
|
class CaptureSignalError extends Error {
|
|
@@ -309,6 +340,24 @@ var captureEmbeddingOne = async (model, request, customId, maxRequestBytes) => {
|
|
|
309
340
|
}
|
|
310
341
|
throw new BatchworkError("batchwork: the request was not intercepted while building the embedding body.");
|
|
311
342
|
};
|
|
343
|
+
var captureImageOne = async (model, request, customId, maxRequestBytes) => {
|
|
344
|
+
try {
|
|
345
|
+
await generateImage({
|
|
346
|
+
aspectRatio: request.aspectRatio,
|
|
347
|
+
maxImagesPerCall: request.n,
|
|
348
|
+
maxRetries: 0,
|
|
349
|
+
model,
|
|
350
|
+
n: request.n,
|
|
351
|
+
prompt: request.prompt,
|
|
352
|
+
providerOptions: request.providerOptions,
|
|
353
|
+
seed: request.seed,
|
|
354
|
+
size: request.size
|
|
355
|
+
});
|
|
356
|
+
} catch (error) {
|
|
357
|
+
return bodyFromCapture(error, customId, maxRequestBytes);
|
|
358
|
+
}
|
|
359
|
+
throw new BatchworkError("batchwork: the request was not intercepted while building the image body.");
|
|
360
|
+
};
|
|
312
361
|
var assignCustomIds = (requests) => {
|
|
313
362
|
const seen = new Set;
|
|
314
363
|
return requests.map((request, index) => {
|
|
@@ -346,6 +395,25 @@ var buildEmbeddingBodies = async (resolved, requests, credentials, rawLimits) =>
|
|
|
346
395
|
return built;
|
|
347
396
|
});
|
|
348
397
|
};
|
|
398
|
+
var mergeImageDefaults = (request, defaults) => {
|
|
399
|
+
if (!defaults) {
|
|
400
|
+
return request;
|
|
401
|
+
}
|
|
402
|
+
return { ...defaults, ...request };
|
|
403
|
+
};
|
|
404
|
+
var buildImageBodies = async (resolved, requests, defaults, credentials, rawLimits) => {
|
|
405
|
+
const limits = resolveBatchLimits(rawLimits);
|
|
406
|
+
if (requests.length > limits.maxRequests) {
|
|
407
|
+
throw new BatchworkError(`batchwork: requests length ${requests.length} exceeds the ${limits.maxRequests} request limit.`);
|
|
408
|
+
}
|
|
409
|
+
const model = await createCaptureImageModel(resolved, credentials, captureFetch);
|
|
410
|
+
const items = assignCustomIds(requests);
|
|
411
|
+
return await mapWithConcurrency(items, limits.captureConcurrency, async (item) => {
|
|
412
|
+
const built = await captureImageOne(model, mergeImageDefaults(item.request, defaults), item.customId, limits.maxRequestBytes);
|
|
413
|
+
assertByteLength(`request "${item.customId}"`, JSON.stringify(built.body), limits.maxRequestBytes);
|
|
414
|
+
return built;
|
|
415
|
+
});
|
|
416
|
+
};
|
|
349
417
|
|
|
350
418
|
// src/batch.ts
|
|
351
419
|
var pickCredentials = (source) => ({
|
|
@@ -362,7 +430,7 @@ var providerFromRef = (ref) => {
|
|
|
362
430
|
}
|
|
363
431
|
throw new BatchworkError("batchwork: provide `provider` or `model` to identify the batch.");
|
|
364
432
|
};
|
|
365
|
-
var
|
|
433
|
+
var submitText = async (options) => {
|
|
366
434
|
if (options.requests.length === 0) {
|
|
367
435
|
throw new BatchworkError("batchwork: `requests` must not be empty.");
|
|
368
436
|
}
|
|
@@ -381,7 +449,7 @@ var batch = async (options) => {
|
|
|
381
449
|
});
|
|
382
450
|
return new BatchJob(adapter, credentials, snapshot);
|
|
383
451
|
};
|
|
384
|
-
var
|
|
452
|
+
var submitEmbeddings = async (options) => {
|
|
385
453
|
if (options.requests.length === 0) {
|
|
386
454
|
throw new BatchworkError("batchwork: `requests` must not be empty.");
|
|
387
455
|
}
|
|
@@ -403,6 +471,35 @@ var batchEmbeddings = async (options) => {
|
|
|
403
471
|
});
|
|
404
472
|
return new BatchJob(adapter, credentials, snapshot);
|
|
405
473
|
};
|
|
474
|
+
var submitImages = async (options) => {
|
|
475
|
+
if (options.requests.length === 0) {
|
|
476
|
+
throw new BatchworkError("batchwork: `requests` must not be empty.");
|
|
477
|
+
}
|
|
478
|
+
const resolved = resolveModel(options.model);
|
|
479
|
+
if (!IMAGE_PROVIDERS.has(resolved.provider)) {
|
|
480
|
+
throw unsupportedImageProvider(resolved.provider);
|
|
481
|
+
}
|
|
482
|
+
const credentials = pickCredentials(options);
|
|
483
|
+
const limits = resolveBatchLimits(options.limits);
|
|
484
|
+
const adapter = getAdapter(resolved.provider);
|
|
485
|
+
const built = await buildImageBodies(resolved, options.requests, options.defaults, credentials, limits);
|
|
486
|
+
const snapshot = await adapter.submit({
|
|
487
|
+
built,
|
|
488
|
+
credentials,
|
|
489
|
+
endpoint: built[0]?.endpoint ?? "",
|
|
490
|
+
limits,
|
|
491
|
+
metadata: options.metadata,
|
|
492
|
+
modelId: resolved.modelId
|
|
493
|
+
});
|
|
494
|
+
return new BatchJob(adapter, credentials, snapshot);
|
|
495
|
+
};
|
|
496
|
+
var batch = Object.assign(submitText, {
|
|
497
|
+
embeddings: submitEmbeddings,
|
|
498
|
+
images: submitImages,
|
|
499
|
+
text: submitText
|
|
500
|
+
});
|
|
501
|
+
var batchEmbeddings = submitEmbeddings;
|
|
502
|
+
var batchImages = submitImages;
|
|
406
503
|
var getBatch = async (ref) => {
|
|
407
504
|
const adapter = getAdapter(providerFromRef(ref));
|
|
408
505
|
const credentials = pickCredentials(ref);
|
|
@@ -418,7 +515,7 @@ var cancelBatch = async (ref) => {
|
|
|
418
515
|
await adapter.cancel(ref.id, pickCredentials(ref));
|
|
419
516
|
};
|
|
420
517
|
|
|
421
|
-
export { resolveModel, batch, batchEmbeddings, getBatch, getBatchResults, cancelBatch };
|
|
518
|
+
export { resolveModel, batch, batchEmbeddings, batchImages, getBatch, getBatchResults, cancelBatch };
|
|
422
519
|
|
|
423
|
-
//# debugId=
|
|
424
|
-
//# sourceMappingURL=chunk-
|
|
520
|
+
//# debugId=21B5A5E0E7FCF0AE64756E2164756E21
|
|
521
|
+
//# sourceMappingURL=chunk-bjkbtj1q.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/model.ts", "../src/body.ts", "../src/batch.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type * as AnthropicModule from \"@ai-sdk/anthropic\";\nimport type * as GoogleModule from \"@ai-sdk/google\";\nimport type * as GroqModule from \"@ai-sdk/groq\";\nimport type * as MistralModule from \"@ai-sdk/mistral\";\nimport type * as OpenAIModule from \"@ai-sdk/openai\";\nimport type * as TogetherModule from \"@ai-sdk/togetherai\";\nimport type * as XaiModule from \"@ai-sdk/xai\";\nimport type { EmbeddingModel, ImageModel, LanguageModel } from \"ai\";\n\nimport { MissingDependencyError, UnsupportedProviderError } from \"./errors\";\nimport type { BatchProvider, ProviderCredentials } from \"./types\";\n\n/** A fetch implementation compatible with the AI SDK provider `fetch` option. */\nexport type CapturingFetch = typeof globalThis.fetch;\n\n/** OpenAI exposes several request shapes; we mirror the one the model implies. */\nexport type OpenAIModelKind = \"chat\" | \"responses\" | \"completion\";\n\nexport interface ResolvedModel {\n /** Relevant for OpenAI; other providers always use a single chat endpoint. */\n kind: OpenAIModelKind;\n modelId: string;\n provider: BatchProvider;\n}\n\n/**\n * Placeholder API key used only when building request bodies. Body building\n * intercepts the request before it is sent, so no real credential is needed —\n * but the provider refuses to construct a model without one.\n */\nconst CAPTURE_API_KEY = \"batchwork-capture\";\n\n/** The optional `@ai-sdk/*` package backing each provider. */\nconst PACKAGE_BY_PROVIDER: Record<\n BatchProvider,\n { label: string; specifier: string }\n> = {\n anthropic: { label: \"Anthropic\", specifier: \"@ai-sdk/anthropic\" },\n google: { label: \"Google Gemini\", specifier: \"@ai-sdk/google\" },\n groq: { label: \"Groq\", specifier: \"@ai-sdk/groq\" },\n mistral: { label: \"Mistral\", specifier: \"@ai-sdk/mistral\" },\n openai: { label: \"OpenAI\", specifier: \"@ai-sdk/openai\" },\n together: { label: \"Together AI\", specifier: \"@ai-sdk/togetherai\" },\n xai: { label: \"xAI\", specifier: \"@ai-sdk/xai\" },\n};\n\n/**\n * AI SDK provider id prefixes (the part before the first `.` in `model.provider`)\n * mapped to batch providers.\n */\nconst PROVIDER_BY_FAMILY: Record<string, BatchProvider> = {\n anthropic: \"anthropic\",\n google: \"google\",\n groq: \"groq\",\n mistral: \"mistral\",\n openai: \"openai\",\n together: \"together\",\n togetherai: \"together\",\n xai: \"xai\",\n};\n\n/** Aliases accepted in the `\"provider/model\"` string form. */\nconst PROVIDER_BY_ALIAS: Record<string, BatchProvider> = {\n ...PROVIDER_BY_FAMILY,\n gemini: \"google\",\n};\n\nconst splitOnce = (value: string, separator: string): [string, string] => {\n const index = value.indexOf(separator);\n if (index === -1) {\n return [value, \"\"];\n }\n return [value.slice(0, index), value.slice(index + separator.length)];\n};\n\nconst openaiKind = (suffix: string): OpenAIModelKind => {\n if (suffix === \"responses\") {\n return \"responses\";\n }\n if (suffix === \"completion\") {\n return \"completion\";\n }\n // Default to chat completions: the most widely supported batch endpoint.\n return \"chat\";\n};\n\n/** Resolve a `\"provider/model\"` string into a provider + model id. */\nconst resolveModelString = (value: string): ResolvedModel => {\n const [providerId, modelId] = splitOnce(value, \"/\");\n if (modelId === \"\") {\n throw new UnsupportedProviderError(value);\n }\n const provider = PROVIDER_BY_ALIAS[providerId];\n if (!provider) {\n throw new UnsupportedProviderError(providerId);\n }\n return { kind: \"chat\", modelId, provider };\n};\n\n/**\n * Resolve any AI SDK `model` (a `\"provider/model\"` string or a provider model\n * object such as `openai(\"gpt-5.5\")`) to a provider + model id + request\n * shape. Gateway/registry model objects whose `modelId` is itself\n * `\"provider/model\"` are also handled.\n */\nexport const resolveModel = (\n model: LanguageModel | EmbeddingModel | ImageModel\n): ResolvedModel => {\n if (typeof model === \"string\") {\n return resolveModelString(model);\n }\n\n const [family, suffix] = splitOnce(model.provider, \".\");\n const provider = PROVIDER_BY_FAMILY[family];\n if (provider === \"openai\") {\n return { kind: openaiKind(suffix), modelId: model.modelId, provider };\n }\n if (provider) {\n return { kind: \"chat\", modelId: model.modelId, provider };\n }\n // Gateway/registry providers carry the real target in the model id.\n if (model.modelId.includes(\"/\")) {\n return resolveModelString(model.modelId);\n }\n throw new UnsupportedProviderError(model.provider);\n};\n\nconst importProvider = (provider: BatchProvider): Promise<unknown> => {\n switch (provider) {\n case \"anthropic\": {\n return import(\"@ai-sdk/anthropic\");\n }\n case \"google\": {\n return import(\"@ai-sdk/google\");\n }\n case \"groq\": {\n return import(\"@ai-sdk/groq\");\n }\n case \"mistral\": {\n return import(\"@ai-sdk/mistral\");\n }\n case \"openai\": {\n return import(\"@ai-sdk/openai\");\n }\n case \"together\": {\n return import(\"@ai-sdk/togetherai\");\n }\n case \"xai\": {\n return import(\"@ai-sdk/xai\");\n }\n default: {\n return Promise.reject(new UnsupportedProviderError(provider));\n }\n }\n};\n\n/**\n * Import the `@ai-sdk/*` package for a provider, translating a missing optional\n * dependency into a `MissingDependencyError`. The importer is injectable (like\n * the capturing `fetch`) so tests can drive the failure paths without\n * uninstalling a package. Exported for testing; not part of the public API.\n */\nexport const loadProvider = async <T>(\n provider: BatchProvider,\n load: (target: BatchProvider) => Promise<unknown> = importProvider\n): Promise<T> => {\n try {\n return (await load(provider)) as T;\n } catch (error) {\n if (error instanceof UnsupportedProviderError) {\n throw error;\n }\n const { specifier, label } = PACKAGE_BY_PROVIDER[provider];\n throw new MissingDependencyError(specifier, label);\n }\n};\n\n/**\n * Construct an AI SDK model wired to a capturing `fetch`, used to derive the\n * provider request body for each batch item without making a network call.\n */\nexport const createCaptureModel = async (\n resolved: ResolvedModel,\n credentials: ProviderCredentials,\n fetchImpl: CapturingFetch\n): Promise<LanguageModel> => {\n const settings = {\n apiKey: credentials.apiKey ?? CAPTURE_API_KEY,\n baseURL: credentials.baseURL,\n fetch: fetchImpl,\n headers: credentials.headers,\n };\n\n switch (resolved.provider) {\n case \"openai\": {\n const { createOpenAI } =\n await loadProvider<typeof OpenAIModule>(\"openai\");\n const provider = createOpenAI(settings);\n if (resolved.kind === \"responses\") {\n return provider.responses(resolved.modelId);\n }\n if (resolved.kind === \"completion\") {\n return provider.completion(resolved.modelId);\n }\n return provider.chat(resolved.modelId);\n }\n case \"anthropic\": {\n const { createAnthropic } =\n await loadProvider<typeof AnthropicModule>(\"anthropic\");\n return createAnthropic(settings).messages(resolved.modelId);\n }\n case \"groq\": {\n const { createGroq } = await loadProvider<typeof GroqModule>(\"groq\");\n return createGroq(settings).languageModel(resolved.modelId);\n }\n case \"mistral\": {\n const { createMistral } =\n await loadProvider<typeof MistralModule>(\"mistral\");\n return createMistral(settings).languageModel(resolved.modelId);\n }\n case \"google\": {\n const { createGoogleGenerativeAI } =\n await loadProvider<typeof GoogleModule>(\"google\");\n return createGoogleGenerativeAI(settings).languageModel(resolved.modelId);\n }\n case \"xai\": {\n const { createXai } = await loadProvider<typeof XaiModule>(\"xai\");\n return createXai(settings).languageModel(resolved.modelId);\n }\n case \"together\": {\n const { createTogetherAI } =\n await loadProvider<typeof TogetherModule>(\"together\");\n return createTogetherAI(settings).languageModel(resolved.modelId);\n }\n default: {\n throw new UnsupportedProviderError(resolved.provider);\n }\n }\n};\n\n/**\n * Providers whose batch API accepts embeddings. Together is excluded: it exposes\n * an embedding model, but its batch endpoint rejects `/v1/embeddings`. Anthropic,\n * Groq, and xAI have no embedding model at all.\n */\nexport const EMBEDDING_PROVIDERS = new Set<BatchProvider>([\n \"google\",\n \"mistral\",\n \"openai\",\n]);\n\nexport const unsupportedEmbeddingProvider = (\n provider: BatchProvider\n): UnsupportedProviderError =>\n new UnsupportedProviderError(\n provider,\n `batchwork: provider \"${provider}\" does not offer batch embeddings. Embeddings are supported for: openai, mistral, google.`\n );\n\n/**\n * Construct an AI SDK text embedding model wired to a capturing `fetch`, used to\n * derive the provider embedding request body for each batch item without making\n * a network call. Throws for providers without an embedding model.\n */\nexport const createCaptureEmbeddingModel = async (\n resolved: ResolvedModel,\n credentials: ProviderCredentials,\n fetchImpl: CapturingFetch\n): Promise<EmbeddingModel> => {\n const settings = {\n apiKey: credentials.apiKey ?? CAPTURE_API_KEY,\n baseURL: credentials.baseURL,\n fetch: fetchImpl,\n headers: credentials.headers,\n };\n\n switch (resolved.provider) {\n case \"openai\": {\n const { createOpenAI } =\n await loadProvider<typeof OpenAIModule>(\"openai\");\n return createOpenAI(settings).embeddingModel(resolved.modelId);\n }\n case \"mistral\": {\n const { createMistral } =\n await loadProvider<typeof MistralModule>(\"mistral\");\n return createMistral(settings).embeddingModel(resolved.modelId);\n }\n case \"google\": {\n const { createGoogleGenerativeAI } =\n await loadProvider<typeof GoogleModule>(\"google\");\n return createGoogleGenerativeAI(settings).embeddingModel(\n resolved.modelId\n );\n }\n default: {\n throw unsupportedEmbeddingProvider(resolved.provider);\n }\n }\n};\n\n/**\n * Providers whose batch API accepts image generation. OpenAI and xAI expose\n * `/v1/images/generations` as a batch endpoint; Google runs Gemini image models\n * through `:batchGenerateContent`. Imagen (Google `:predict`) is not\n * batch-supported, Together's batch API is chat/audio only, and Anthropic, Groq,\n * and Mistral have no image model.\n */\nexport const IMAGE_PROVIDERS = new Set<BatchProvider>([\n \"google\",\n \"openai\",\n \"xai\",\n]);\n\nexport const unsupportedImageProvider = (\n provider: BatchProvider\n): UnsupportedProviderError =>\n new UnsupportedProviderError(\n provider,\n `batchwork: provider \"${provider}\" does not offer batch image generation. Image batches are supported for: openai, google, xai.`\n );\n\n/**\n * Construct an AI SDK image model wired to a capturing `fetch`, used to derive\n * the provider image-generation request body for each batch item without making\n * a network call. Throws for providers without batch image support.\n */\nexport const createCaptureImageModel = async (\n resolved: ResolvedModel,\n credentials: ProviderCredentials,\n fetchImpl: CapturingFetch\n): Promise<ImageModel> => {\n const settings = {\n apiKey: credentials.apiKey ?? CAPTURE_API_KEY,\n baseURL: credentials.baseURL,\n fetch: fetchImpl,\n headers: credentials.headers,\n };\n\n switch (resolved.provider) {\n case \"openai\": {\n const { createOpenAI } =\n await loadProvider<typeof OpenAIModule>(\"openai\");\n return createOpenAI(settings).image(resolved.modelId);\n }\n case \"google\": {\n const { createGoogleGenerativeAI } =\n await loadProvider<typeof GoogleModule>(\"google\");\n return createGoogleGenerativeAI(settings).image(resolved.modelId);\n }\n case \"xai\": {\n const { createXai } = await loadProvider<typeof XaiModule>(\"xai\");\n return createXai(settings).image(resolved.modelId);\n }\n default: {\n throw unsupportedImageProvider(resolved.provider);\n }\n }\n};\n",
|
|
6
|
+
"import { embed, generateImage, generateText } from \"ai\";\nimport type { EmbeddingModel, ImageModel, LanguageModel } from \"ai\";\n\nimport { BatchworkError } from \"./errors\";\nimport {\n assertByteLength,\n mapWithConcurrency,\n resolveBatchLimits,\n} from \"./limits\";\nimport type { ResolvedBatchLimits } from \"./limits\";\nimport {\n createCaptureEmbeddingModel,\n createCaptureImageModel,\n createCaptureModel,\n} from \"./model\";\nimport type { CapturingFetch, ResolvedModel } from \"./model\";\nimport type {\n BatchDefaults,\n BatchEmbeddingRequest,\n BatchImageDefaults,\n BatchImageRequest,\n BatchLimits,\n BatchRequest,\n ProviderCredentials,\n} from \"./types\";\n\ntype GenerateTextInput = Parameters<typeof generateText>[0];\n\n/** A provider request body derived from a single batch item. */\nexport interface BuiltRequest {\n /** The serialized provider request body (becomes the batch line). */\n body: Record<string, unknown>;\n customId: string;\n /** API endpoint path the model targets, e.g. `/v1/chat/completions`. */\n endpoint: string;\n}\n\nconst MAX_CAUSE_DEPTH = 10;\n\n/**\n * Thrown by the capturing `fetch` to abort the request after its body has been\n * serialized. The body travels inside the error (not shared state), so capture\n * is correct even under concurrency.\n */\nclass CaptureSignalError extends Error {\n readonly url: string;\n readonly rawBody: string;\n\n constructor(url: string, rawBody: string) {\n super(\"batchwork:capture\");\n this.name = \"CaptureSignalError\";\n this.url = url;\n this.rawBody = rawBody;\n }\n}\n\nconst resolveUrl = (input: string | URL | Request): string => {\n if (typeof input === \"string\") {\n return input;\n }\n if (input instanceof URL) {\n return input.toString();\n }\n return input.url;\n};\n\nconst extractBody = (init?: RequestInit): string => {\n const body = init?.body;\n if (typeof body === \"string\") {\n return body;\n }\n if (body instanceof Uint8Array) {\n return new TextDecoder().decode(body);\n }\n throw new BatchworkError(\n \"batchwork: unable to read the provider request body during capture.\"\n );\n};\n\n// `CapturingFetch` is `typeof fetch`, whose shape varies by runtime types (e.g.\n// Bun adds a required `preconnect` method). We only ever call it as a plain\n// fetch, so cast the bare implementation rather than stub the extra members.\nconst captureFetch = ((input: string | URL | Request, init?: RequestInit) =>\n Promise.reject(\n new CaptureSignalError(resolveUrl(input), extractBody(init))\n )) as unknown as CapturingFetch;\n\nconst findCapture = (error: unknown): CaptureSignalError | undefined => {\n let current: unknown = error;\n let depth = 0;\n while (current && depth < MAX_CAUSE_DEPTH) {\n if (current instanceof CaptureSignalError) {\n return current;\n }\n current = (current as { cause?: unknown }).cause;\n depth += 1;\n }\n};\n\nconst endpointFromUrl = (url: string): string => {\n try {\n return new URL(url).pathname;\n } catch {\n return url;\n }\n};\n\nconst mergeDefaults = (\n request: BatchRequest,\n defaults: BatchDefaults | undefined\n): BatchRequest => {\n if (!defaults) {\n return request;\n }\n return { ...defaults, ...request };\n};\n\n/**\n * Map a batch request to AI SDK `generateText` input. Fields are listed\n * explicitly so `customId` never leaks into the provider request.\n */\nconst toGenerateInput = (\n model: LanguageModel,\n request: BatchRequest\n): GenerateTextInput =>\n // `prompt`/`messages` form a discriminated union in the AI SDK types; we\n // pass both keys and let `generateText` validate the XOR at runtime.\n ({\n frequencyPenalty: request.frequencyPenalty,\n maxOutputTokens: request.maxOutputTokens,\n maxRetries: 0,\n messages: request.messages,\n model,\n presencePenalty: request.presencePenalty,\n prompt: request.prompt,\n providerOptions: request.providerOptions,\n seed: request.seed,\n stopSequences: request.stopSequences,\n system: request.system,\n temperature: request.temperature,\n toolChoice: request.toolChoice,\n tools: request.tools,\n topK: request.topK,\n topP: request.topP,\n }) as GenerateTextInput;\n\n/**\n * Turn a thrown capture into a {@link BuiltRequest}. A genuine failure (one that\n * never reached the capturing `fetch`, e.g. an invalid prompt) is rethrown.\n */\nconst bodyFromCapture = (\n error: unknown,\n customId: string,\n maxRequestBytes: number\n): BuiltRequest => {\n const capture = findCapture(error);\n if (capture) {\n assertByteLength(`request \"${customId}\"`, capture.rawBody, maxRequestBytes);\n return {\n body: JSON.parse(capture.rawBody) as Record<string, unknown>,\n customId,\n endpoint: endpointFromUrl(capture.url),\n };\n }\n throw error;\n};\n\nconst captureOne = async (\n model: LanguageModel,\n request: BatchRequest,\n customId: string,\n maxRequestBytes: number\n): Promise<BuiltRequest> => {\n try {\n await generateText(toGenerateInput(model, request));\n } catch (error) {\n return bodyFromCapture(error, customId, maxRequestBytes);\n }\n throw new BatchworkError(\n \"batchwork: the request was not intercepted while building the batch body.\"\n );\n};\n\nconst captureEmbeddingOne = async (\n model: EmbeddingModel,\n request: BatchEmbeddingRequest,\n customId: string,\n maxRequestBytes: number\n): Promise<BuiltRequest> => {\n try {\n // `maxRetries: 0` is load-bearing: with retries enabled the capture error\n // is wrapped in a `RetryError` (under `.errors`, not `.cause`) and\n // `findCapture`'s cause walk would miss it.\n await embed({\n maxRetries: 0,\n model,\n providerOptions: request.providerOptions,\n value: request.value,\n });\n } catch (error) {\n return bodyFromCapture(error, customId, maxRequestBytes);\n }\n throw new BatchworkError(\n \"batchwork: the request was not intercepted while building the embedding body.\"\n );\n};\n\nconst captureImageOne = async (\n model: ImageModel,\n request: BatchImageRequest,\n customId: string,\n maxRequestBytes: number\n): Promise<BuiltRequest> => {\n try {\n await generateImage({\n aspectRatio: request.aspectRatio,\n // `maxImagesPerCall: n` forces a single `doGenerate` call so the captured\n // body carries the requested `n` rather than a fanned-out per-call count.\n maxImagesPerCall: request.n,\n // `maxRetries: 0` is load-bearing: with retries enabled the capture error\n // is wrapped in a `RetryError` (under `.errors`, not `.cause`) and\n // `findCapture`'s cause walk would miss it.\n maxRetries: 0,\n model,\n n: request.n,\n prompt: request.prompt,\n providerOptions: request.providerOptions,\n seed: request.seed,\n size: request.size,\n });\n } catch (error) {\n return bodyFromCapture(error, customId, maxRequestBytes);\n }\n throw new BatchworkError(\n \"batchwork: the request was not intercepted while building the image body.\"\n );\n};\n\n/**\n * Assign and validate a unique `customId` for each request (sequentially, so\n * duplicates are reported deterministically before bodies are captured in\n * parallel). Auto-generates `request-{index}` when omitted.\n */\nconst assignCustomIds = <T extends { customId?: string }>(\n requests: readonly T[]\n): { customId: string; request: T }[] => {\n const seen = new Set<string>();\n return requests.map((request, index) => {\n const customId = request.customId ?? `request-${index}`;\n if (seen.has(customId)) {\n throw new BatchworkError(\n `batchwork: duplicate customId \"${customId}\". customId values must be unique within a batch.`\n );\n }\n seen.add(customId);\n return { customId, request };\n });\n};\n\n/**\n * Derive provider request bodies for every batch item by running each through\n * the AI SDK with a capturing `fetch`. This reuses the AI SDK's full message,\n * tool, and multimodal conversion, so the body matches what `generateText`\n * would send — minus the network call.\n */\nexport const buildRequestBodies = async (\n resolved: ResolvedModel,\n requests: readonly BatchRequest[],\n defaults: BatchDefaults | undefined,\n credentials: ProviderCredentials,\n rawLimits?: BatchLimits | ResolvedBatchLimits\n): Promise<BuiltRequest[]> => {\n const limits = resolveBatchLimits(rawLimits);\n if (requests.length > limits.maxRequests) {\n throw new BatchworkError(\n `batchwork: requests length ${requests.length} exceeds the ${limits.maxRequests} request limit.`\n );\n }\n const model = await createCaptureModel(resolved, credentials, captureFetch);\n const items = assignCustomIds(requests);\n\n return await mapWithConcurrency(\n items,\n limits.captureConcurrency,\n async (item) => {\n const built = await captureOne(\n model,\n mergeDefaults(item.request, defaults),\n item.customId,\n limits.maxRequestBytes\n );\n assertByteLength(\n `request \"${item.customId}\"`,\n JSON.stringify(built.body),\n limits.maxRequestBytes\n );\n return built;\n }\n );\n};\n\n/**\n * Derive provider embedding request bodies for every batch item by running each\n * through the AI SDK `embed` with a capturing `fetch`. Mirrors\n * {@link buildRequestBodies} for the embedding endpoint; each item maps to a\n * single embedding (`input: [value]`), correlated by `customId`.\n */\nexport const buildEmbeddingBodies = async (\n resolved: ResolvedModel,\n requests: readonly BatchEmbeddingRequest[],\n credentials: ProviderCredentials,\n rawLimits?: BatchLimits | ResolvedBatchLimits\n): Promise<BuiltRequest[]> => {\n const limits = resolveBatchLimits(rawLimits);\n if (requests.length > limits.maxRequests) {\n throw new BatchworkError(\n `batchwork: requests length ${requests.length} exceeds the ${limits.maxRequests} request limit.`\n );\n }\n const model = await createCaptureEmbeddingModel(\n resolved,\n credentials,\n captureFetch\n );\n const items = assignCustomIds(requests);\n\n return await mapWithConcurrency(\n items,\n limits.captureConcurrency,\n async (item) => {\n const built = await captureEmbeddingOne(\n model,\n item.request,\n item.customId,\n limits.maxRequestBytes\n );\n assertByteLength(\n `request \"${item.customId}\"`,\n JSON.stringify(built.body),\n limits.maxRequestBytes\n );\n return built;\n }\n );\n};\n\nconst mergeImageDefaults = (\n request: BatchImageRequest,\n defaults: BatchImageDefaults | undefined\n): BatchImageRequest => {\n if (!defaults) {\n return request;\n }\n return { ...defaults, ...request };\n};\n\n/**\n * Derive provider image-generation request bodies for every batch item by\n * running each through the AI SDK `generateImage` with a capturing `fetch`.\n * Mirrors {@link buildRequestBodies} for the image endpoint; each item maps to a\n * single image-generation call, correlated by `customId`.\n */\nexport const buildImageBodies = async (\n resolved: ResolvedModel,\n requests: readonly BatchImageRequest[],\n defaults: BatchImageDefaults | undefined,\n credentials: ProviderCredentials,\n rawLimits?: BatchLimits | ResolvedBatchLimits\n): Promise<BuiltRequest[]> => {\n const limits = resolveBatchLimits(rawLimits);\n if (requests.length > limits.maxRequests) {\n throw new BatchworkError(\n `batchwork: requests length ${requests.length} exceeds the ${limits.maxRequests} request limit.`\n );\n }\n const model = await createCaptureImageModel(\n resolved,\n credentials,\n captureFetch\n );\n const items = assignCustomIds(requests);\n\n return await mapWithConcurrency(\n items,\n limits.captureConcurrency,\n async (item) => {\n const built = await captureImageOne(\n model,\n mergeImageDefaults(item.request, defaults),\n item.customId,\n limits.maxRequestBytes\n );\n assertByteLength(\n `request \"${item.customId}\"`,\n JSON.stringify(built.body),\n limits.maxRequestBytes\n );\n return built;\n }\n );\n};\n",
|
|
7
|
+
"import {\n buildEmbeddingBodies,\n buildImageBodies,\n buildRequestBodies,\n} from \"./body\";\nimport { BatchworkError } from \"./errors\";\nimport { BatchJob } from \"./job\";\nimport { resolveBatchLimits } from \"./limits\";\nimport {\n EMBEDDING_PROVIDERS,\n IMAGE_PROVIDERS,\n resolveModel,\n unsupportedEmbeddingProvider,\n unsupportedImageProvider,\n} from \"./model\";\nimport { getAdapter } from \"./providers\";\nimport type {\n BatchEmbeddingsOptions,\n BatchImageOptions,\n BatchOptions,\n BatchProvider,\n BatchRef,\n BatchResult,\n ProviderCredentials,\n} from \"./types\";\n\nconst pickCredentials = (source: ProviderCredentials): ProviderCredentials => ({\n apiKey: source.apiKey,\n baseURL: source.baseURL,\n headers: source.headers,\n});\n\nconst providerFromRef = (ref: BatchRef): BatchProvider => {\n if (ref.provider) {\n return ref.provider;\n }\n if (ref.model !== undefined) {\n return resolveModel(ref.model).provider;\n }\n throw new BatchworkError(\n \"batchwork: provide `provider` or `model` to identify the batch.\"\n );\n};\n\n/**\n * Submit a batch of text/chat requests to the model's provider and return a\n * handle. Reachable as both `batch()` (shorthand) and `batch.text()`.\n *\n * Resolves immediately once the batch is accepted — it does not wait for\n * processing. Use the returned {@link BatchJob} to poll, wait, or stream\n * results.\n *\n * @example\n * const job = await batch({\n * model: openai(\"gpt-5.5\"),\n * requests: [{ customId: \"a\", prompt: \"Say hi\" }],\n * });\n * const results = await job.wait().then(() => job.collect());\n */\nconst submitText = async (options: BatchOptions): Promise<BatchJob> => {\n if (options.requests.length === 0) {\n throw new BatchworkError(\"batchwork: `requests` must not be empty.\");\n }\n\n const resolved = resolveModel(options.model);\n const credentials = pickCredentials(options);\n const limits = resolveBatchLimits(options.limits);\n const adapter = getAdapter(resolved.provider);\n\n const built = await buildRequestBodies(\n resolved,\n options.requests,\n options.defaults,\n credentials,\n limits\n );\n const snapshot = await adapter.submit({\n built,\n credentials,\n endpoint: built[0]?.endpoint ?? \"\",\n limits,\n metadata: options.metadata,\n modelId: resolved.modelId,\n });\n\n return new BatchJob(adapter, credentials, snapshot);\n};\n\n/**\n * Submit a batch of embedding requests to the model's provider and return a\n * handle. Each request's `value` produces one vector, correlated by `customId`\n * via {@link BatchJob.results}. Supported for OpenAI, Mistral, Together, and\n * Google; other providers throw {@link UnsupportedProviderError}.\n *\n * @example\n * const job = await batch.embeddings({\n * model: openai.embeddingModel(\"text-embedding-3-small\"),\n * requests: [{ customId: \"a\", value: \"hello world\" }],\n * });\n * const results = await job.wait().then(() => job.collect());\n * for (const r of results) {\n * console.log(r.customId, r.embedding?.length);\n * }\n */\nconst submitEmbeddings = async (\n options: BatchEmbeddingsOptions\n): Promise<BatchJob> => {\n if (options.requests.length === 0) {\n throw new BatchworkError(\"batchwork: `requests` must not be empty.\");\n }\n\n const resolved = resolveModel(options.model);\n if (!EMBEDDING_PROVIDERS.has(resolved.provider)) {\n throw unsupportedEmbeddingProvider(resolved.provider);\n }\n const credentials = pickCredentials(options);\n const limits = resolveBatchLimits(options.limits);\n const adapter = getAdapter(resolved.provider);\n\n const built = await buildEmbeddingBodies(\n resolved,\n options.requests,\n credentials,\n limits\n );\n const snapshot = await adapter.submit({\n built,\n credentials,\n endpoint: built[0]?.endpoint ?? \"\",\n limits,\n metadata: options.metadata,\n modelId: resolved.modelId,\n });\n\n return new BatchJob(adapter, credentials, snapshot);\n};\n\n/**\n * Submit a batch of image-generation requests to the model's provider and\n * return a handle. Each request's `prompt` produces one or more images,\n * correlated by `customId` via {@link BatchJob.results}. Supported for OpenAI\n * and Google; other providers throw {@link UnsupportedProviderError}.\n *\n * @example\n * const job = await batch.images({\n * model: openai.image(\"gpt-image-2\"),\n * requests: [{ customId: \"a\", prompt: \"a red bicycle\" }],\n * });\n * const results = await job.wait().then(() => job.collect());\n * for (const r of results) {\n * console.log(r.customId, r.images?.length);\n * }\n */\nconst submitImages = async (options: BatchImageOptions): Promise<BatchJob> => {\n if (options.requests.length === 0) {\n throw new BatchworkError(\"batchwork: `requests` must not be empty.\");\n }\n\n const resolved = resolveModel(options.model);\n if (!IMAGE_PROVIDERS.has(resolved.provider)) {\n throw unsupportedImageProvider(resolved.provider);\n }\n const credentials = pickCredentials(options);\n const limits = resolveBatchLimits(options.limits);\n const adapter = getAdapter(resolved.provider);\n\n const built = await buildImageBodies(\n resolved,\n options.requests,\n options.defaults,\n credentials,\n limits\n );\n const snapshot = await adapter.submit({\n built,\n credentials,\n endpoint: built[0]?.endpoint ?? \"\",\n limits,\n metadata: options.metadata,\n modelId: resolved.modelId,\n });\n\n return new BatchJob(adapter, credentials, snapshot);\n};\n\n/**\n * Submit a batch of requests and return a {@link BatchJob} handle.\n *\n * Callable directly as a shorthand for text/chat batches, with one method per\n * modality:\n *\n * - `batch()` / {@link batch.text} — text & chat completions\n * - {@link batch.embeddings} — embedding vectors\n * - {@link batch.images} — image generation\n *\n * @example\n * const job = await batch({\n * model: openai(\"gpt-5.5\"),\n * requests: [{ customId: \"a\", prompt: \"Say hi\" }],\n * });\n */\nexport const batch = Object.assign(submitText, {\n /** Submit a batch of embedding requests. */\n embeddings: submitEmbeddings,\n /** Submit a batch of image-generation requests. */\n images: submitImages,\n /** Submit a batch of text/chat requests. Equivalent to calling `batch()`. */\n text: submitText,\n});\n\n/**\n * @deprecated Use {@link batch.embeddings} instead. Kept as a standalone alias\n * for backward compatibility; it will be removed in a future major.\n */\nexport const batchEmbeddings = submitEmbeddings;\n\n/**\n * @deprecated Use {@link batch.images} instead. Kept as a standalone alias for\n * backward compatibility; it will be removed in a future major.\n */\nexport const batchImages = submitImages;\n\n/**\n * Rehydrate a {@link BatchJob} for an existing batch id (e.g. one persisted\n * after submission). Identify the provider with `provider` or `model`.\n */\nexport const getBatch = async (ref: BatchRef): Promise<BatchJob> => {\n const adapter = getAdapter(providerFromRef(ref));\n const credentials = pickCredentials(ref);\n const snapshot = await adapter.retrieve(ref.id, credentials);\n return new BatchJob(adapter, credentials, snapshot);\n};\n\n/** Stream the results of an existing batch by id, without a handle. */\nexport const getBatchResults = (ref: BatchRef): AsyncGenerator<BatchResult> => {\n const adapter = getAdapter(providerFromRef(ref));\n return adapter.results(ref.id, pickCredentials(ref));\n};\n\n/** Request cancellation of an existing batch by id. */\nexport const cancelBatch = async (ref: BatchRef): Promise<void> => {\n const adapter = getAdapter(providerFromRef(ref));\n await adapter.cancel(ref.id, pickCredentials(ref));\n};\n"
|
|
8
|
+
],
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "21B5A5E0E7FCF0AE64756E2164756E21",
|
|
11
|
+
"names": []
|
|
12
|
+
}
|
|
@@ -611,6 +611,20 @@ var textFromResponse = (response) => {
|
|
|
611
611
|
return text.length > 0 ? text : undefined;
|
|
612
612
|
};
|
|
613
613
|
var embeddingFromResponse = (response) => asNumberArray(asRecord(asRecord(response).embedding).values);
|
|
614
|
+
var imagesFromResponse = (response) => {
|
|
615
|
+
const candidate = asRecord(asArray(asRecord(response).candidates)[0]);
|
|
616
|
+
const images = [];
|
|
617
|
+
for (const part of asArray(asRecord(candidate.content).parts)) {
|
|
618
|
+
const partObj = asRecord(part);
|
|
619
|
+
const inline = asRecord(partObj.inlineData ?? partObj.inline_data);
|
|
620
|
+
const data = asString(inline.data);
|
|
621
|
+
const mediaType = asString(inline.mimeType) ?? asString(inline.mime_type);
|
|
622
|
+
if (data && mediaType?.startsWith("image/")) {
|
|
623
|
+
images.push({ data, mediaType });
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
return images.length > 0 ? images : undefined;
|
|
627
|
+
};
|
|
614
628
|
var usageFromResponse = (response) => {
|
|
615
629
|
const usage = asRecord(asRecord(response).usageMetadata);
|
|
616
630
|
const inputTokens = asNumber(usage.promptTokenCount);
|
|
@@ -644,6 +658,7 @@ var normalizeResult2 = (item) => {
|
|
|
644
658
|
return {
|
|
645
659
|
customId,
|
|
646
660
|
embedding: embeddingFromResponse(obj.response),
|
|
661
|
+
images: imagesFromResponse(obj.response),
|
|
647
662
|
response: obj.response,
|
|
648
663
|
status: "succeeded",
|
|
649
664
|
text: textFromResponse(obj.response),
|
|
@@ -762,6 +777,18 @@ var embeddingFromBody = (body) => {
|
|
|
762
777
|
}
|
|
763
778
|
return asNumberArray(asRecord(data[0]).embedding);
|
|
764
779
|
};
|
|
780
|
+
var imagesFromBody = (body) => {
|
|
781
|
+
const obj = asRecord(body);
|
|
782
|
+
const mediaType = `image/${asString(obj.output_format) ?? "png"}`;
|
|
783
|
+
const images = [];
|
|
784
|
+
for (const item of asArray(obj.data)) {
|
|
785
|
+
const b64 = asString(asRecord(item).b64_json);
|
|
786
|
+
if (b64) {
|
|
787
|
+
images.push({ data: b64, mediaType });
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
return images.length > 0 ? images : undefined;
|
|
791
|
+
};
|
|
765
792
|
var usageFromBody = (body) => {
|
|
766
793
|
const usage = asRecord(asRecord(body).usage);
|
|
767
794
|
const inputTokens = asNumber(usage.prompt_tokens) ?? asNumber(usage.input_tokens);
|
|
@@ -803,6 +830,7 @@ var normalizeOpenAIResult = (line) => {
|
|
|
803
830
|
return {
|
|
804
831
|
customId,
|
|
805
832
|
embedding: embeddingFromBody(response.body),
|
|
833
|
+
images: imagesFromBody(response.body),
|
|
806
834
|
response: response.body,
|
|
807
835
|
status: "succeeded",
|
|
808
836
|
text: textFromBody(response.body),
|
|
@@ -1216,6 +1244,24 @@ var normalizeSnapshot5 = (raw) => {
|
|
|
1216
1244
|
status: deriveStatus(state)
|
|
1217
1245
|
};
|
|
1218
1246
|
};
|
|
1247
|
+
var imagesFromXaiCompletion = (completion) => {
|
|
1248
|
+
const obj = asRecord(completion);
|
|
1249
|
+
const entries = asArray(obj.data);
|
|
1250
|
+
const sources = entries.length > 0 ? entries : [obj];
|
|
1251
|
+
const images = [];
|
|
1252
|
+
for (const source of sources) {
|
|
1253
|
+
const record = asRecord(source);
|
|
1254
|
+
const data = asString(record.base64) ?? asString(record.b64_json);
|
|
1255
|
+
const url = asString(record.url);
|
|
1256
|
+
if (data || url) {
|
|
1257
|
+
images.push({
|
|
1258
|
+
...data ? { data } : {},
|
|
1259
|
+
...url ? { url } : {}
|
|
1260
|
+
});
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
return images.length > 0 ? images : undefined;
|
|
1264
|
+
};
|
|
1219
1265
|
var normalizeResult3 = (item) => {
|
|
1220
1266
|
const obj = asRecord(item);
|
|
1221
1267
|
const customId = asString(obj.batch_request_id) ?? "";
|
|
@@ -1237,6 +1283,7 @@ var normalizeResult3 = (item) => {
|
|
|
1237
1283
|
const completion = response.chat_get_completion ?? Object.values(response)[0];
|
|
1238
1284
|
return {
|
|
1239
1285
|
customId,
|
|
1286
|
+
images: imagesFromXaiCompletion(completion),
|
|
1240
1287
|
response: completion,
|
|
1241
1288
|
status: "succeeded",
|
|
1242
1289
|
text: textFromBody(completion),
|
|
@@ -1315,5 +1362,5 @@ var getAdapter = (provider) => adapters[provider];
|
|
|
1315
1362
|
|
|
1316
1363
|
export { BatchworkError, UnsupportedProviderError, MissingDependencyError, resolveBatchLimits, assertByteLength, mapWithConcurrency, isTerminalStatus, BatchJob, getAdapter };
|
|
1317
1364
|
|
|
1318
|
-
//# debugId=
|
|
1319
|
-
//# sourceMappingURL=chunk-
|
|
1365
|
+
//# debugId=308C7FBEE03E10E564756E2164756E21
|
|
1366
|
+
//# sourceMappingURL=chunk-h2he3d16.js.map
|