batchwork 1.4.0 → 1.4.1

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.
@@ -4,8 +4,8 @@ import {
4
4
  signWebhook,
5
5
  verifyBatchWebhook,
6
6
  verifyWebhook
7
- } from "../chunk-ka9d4t6v.js";
8
- import"../chunk-vy4w8mpb.js";
7
+ } from "../chunk-mathjpg6.js";
8
+ import"../chunk-n50t31ca.js";
9
9
  import"../chunk-v0bahtg2.js";
10
10
  export {
11
11
  verifyWebhook,
@@ -1 +1 @@
1
- {"version":3,"file":"poller.d.ts","sourceRoot":"","sources":["../../src/server/poller.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,WAAW,EACX,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAGlB,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAExD,6EAA6E;AAC7E,MAAM,MAAM,kBAAkB,GAC1B,mBAAmB,GACnB,CAAC,CAAC,QAAQ,EAAE,aAAa,KAAK,mBAAmB,CAAC,CAAC;AAEvD;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAC3B,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,aAAa,KACpB,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAErE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,UAAU,CAAC;IAClB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,8DAA8D;IAC9D,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,6EAA6E;IAC7E,kBAAkB,CAAC,EAAE,mBAAmB,CAAC;IACzC;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1D;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,6EAA6E;IAC7E,MAAM,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,oBAAoB;IACnC,qDAAqD;IACrD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7E,IAAI,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;IAChC,OAAO,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,oBAAoB,EAAE,CACpB,OAAO,EAAE,oBAAoB,KAC1B,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC9C;AAqLD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,YAAa,kBAAkB,KAAG,WAiI/D,CAAC"}
1
+ {"version":3,"file":"poller.d.ts","sourceRoot":"","sources":["../../src/server/poller.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,WAAW,EACX,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAGlB,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAExD,6EAA6E;AAC7E,MAAM,MAAM,kBAAkB,GAC1B,mBAAmB,GACnB,CAAC,CAAC,QAAQ,EAAE,aAAa,KAAK,mBAAmB,CAAC,CAAC;AAEvD;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAC3B,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,aAAa,KACpB,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAErE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,UAAU,CAAC;IAClB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,8DAA8D;IAC9D,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,6EAA6E;IAC7E,kBAAkB,CAAC,EAAE,mBAAmB,CAAC;IACzC;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1D;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,6EAA6E;IAC7E,MAAM,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,oBAAoB;IACnC,qDAAqD;IACrD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7E,IAAI,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;IAChC,OAAO,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,oBAAoB,EAAE,CACpB,OAAO,EAAE,oBAAoB,KAC1B,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC9C;AAsGD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,YAAa,kBAAkB,KAAG,WAiI/D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../../src/server/signing.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAWjD,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,CACN,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,KACR,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;IACtE,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC9D;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AA8ID,0EAA0E;AAC1E,eAAO,MAAM,WAAW,WACd,MAAM,MACV,MAAM,QACJ,MAAM,oBACM,MAAM,KACvB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQhC,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,YACf,OAAO,UACR,MAAM,YACJ,oBAAoB,KAC7B,OAAO,CAAC,eAAe,CA8CzB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,YACpB,OAAO,UACR,MAAM,YACJ,oBAAoB,KAC7B,OAAO,CAAC,iBAAiB,CAG3B,CAAC"}
1
+ {"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../../src/server/signing.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAoBjD,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,CACN,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,KACR,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;IACtE,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC9D;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AA2FD,0EAA0E;AAC1E,eAAO,MAAM,WAAW,WACd,MAAM,MACV,MAAM,QACJ,MAAM,oBACM,MAAM,KACvB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAahC,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,YACf,OAAO,UACR,MAAM,YACJ,oBAAoB,KAC7B,OAAO,CAAC,eAAe,CAgDzB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,YACpB,OAAO,UACR,MAAM,YACJ,oBAAoB,KAC7B,OAAO,CAAC,iBAAiB,CAG3B,CAAC"}
package/dist/util.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  /** Small, defensive helpers for reading loosely-typed provider JSON. */
2
+ /** Linear-time trailing-slash trim; a `/\/+$/` regex is polynomial (ReDoS). */
3
+ export declare const trimTrailingSlashes: (value: string) => string;
2
4
  export declare const asRecord: (value: unknown) => Record<string, unknown>;
3
5
  export declare const asString: (value: unknown) => string | undefined;
4
6
  export declare const asNumber: (value: unknown) => number | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,wEAAwE;AAExE,eAAO,MAAM,QAAQ,UAAW,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAK/D,CAAC;AAEF,eAAO,MAAM,QAAQ,UAAW,OAAO,KAAG,MAAM,GAAG,SACJ,CAAC;AAEhD,eAAO,MAAM,QAAQ,UAAW,OAAO,KAAG,MAAM,GAAG,SACJ,CAAC;AAEhD,eAAO,MAAM,OAAO,UAAW,OAAO,KAAG,OAAO,EACb,CAAC;AAEpC,oFAAoF;AACpF,eAAO,MAAM,aAAa,UAAW,OAAO,KAAG,MAAM,EAAE,GAAG,SAQzD,CAAC;AAEF,oDAAoD;AACpD,eAAO,MAAM,IAAI,QACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,OACvB,MAAM,KACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAQxB,CAAC;AAQF,4EAA4E;AAC5E,eAAO,MAAM,MAAM,UAAW,OAAO,KAAG,IAAI,GAAG,SAO9C,CAAC"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,wEAAwE;AAExE,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,UAAW,MAAM,KAAG,MAMnD,CAAC;AAEF,eAAO,MAAM,QAAQ,UAAW,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAK/D,CAAC;AAEF,eAAO,MAAM,QAAQ,UAAW,OAAO,KAAG,MAAM,GAAG,SACJ,CAAC;AAEhD,eAAO,MAAM,QAAQ,UAAW,OAAO,KAAG,MAAM,GAAG,SACJ,CAAC;AAEhD,eAAO,MAAM,OAAO,UAAW,OAAO,KAAG,OAAO,EACb,CAAC;AAEpC,oFAAoF;AACpF,eAAO,MAAM,aAAa,UAAW,OAAO,KAAG,MAAM,EAAE,GAAG,SAQzD,CAAC;AAEF,oDAAoD;AACpD,eAAO,MAAM,IAAI,QACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,OACvB,MAAM,KACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAQxB,CAAC;AAQF,4EAA4E;AAC5E,eAAO,MAAM,MAAM,UAAW,OAAO,KAAG,IAAI,GAAG,SAO9C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "batchwork",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "Unified batch API for AI providers — low-cost LLM batch processing at scale.",
5
5
  "keywords": [
6
6
  "ai",
@@ -63,7 +63,10 @@
63
63
  "test:live": "bun test --env-file=.env.local ./live"
64
64
  },
65
65
  "dependencies": {
66
- "ai": "^7.0.15"
66
+ "ai": "^7.0.15",
67
+ "ipaddr.js": "^2.5.0",
68
+ "p-map": "^7.0.6",
69
+ "standardwebhooks": "^1.0.0"
67
70
  },
68
71
  "devDependencies": {
69
72
  "@ai-sdk/anthropic": "^4.0.8",
@@ -1,12 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/model.ts", "../src/body.ts", "../src/batch.ts"],
4
- "sourcesContent": [
5
- "import type { createAnthropic } from \"@ai-sdk/anthropic\";\nimport type { createAzure } from \"@ai-sdk/azure\";\nimport type { createGoogleGenerativeAI } from \"@ai-sdk/google\";\nimport type { createGroq } from \"@ai-sdk/groq\";\nimport type { createMistral } from \"@ai-sdk/mistral\";\nimport type { createOpenAI } from \"@ai-sdk/openai\";\nimport type { createTogetherAI } from \"@ai-sdk/togetherai\";\nimport type { createXai } from \"@ai-sdk/xai\";\nimport type {\n EmbeddingModel,\n ImageModel,\n LanguageModel,\n TranscriptionModel,\n} from \"ai\";\n\nimport { MissingDependencyError, UnsupportedProviderError } from \"./errors\";\nimport type { BatchProvider, ProviderCredentials, VideoModel } from \"./types\";\n\n/** The shape `loadProvider` expects from each optional `@ai-sdk/*` package. */\ninterface AnthropicModule {\n createAnthropic: typeof createAnthropic;\n}\ninterface AzureModule {\n createAzure: typeof createAzure;\n}\ninterface GoogleModule {\n createGoogleGenerativeAI: typeof createGoogleGenerativeAI;\n}\ninterface GroqModule {\n createGroq: typeof createGroq;\n}\ninterface MistralModule {\n createMistral: typeof createMistral;\n}\ninterface OpenAIModule {\n createOpenAI: typeof createOpenAI;\n}\ninterface TogetherModule {\n createTogetherAI: typeof createTogetherAI;\n}\ninterface XaiModule {\n createXai: typeof createXai;\n}\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\nconst azureCaptureBaseUrl = (\n baseURL: string | undefined\n): string | undefined => {\n if (!baseURL) {\n return;\n }\n const normalized = baseURL.replace(/\\/+$/u, \"\");\n try {\n if (new URL(normalized).hostname.endsWith(\".openai.azure.com\")) {\n // The AI SDK appends `/v1` itself, so it wants the `/openai` root —\n // accept the bare resource URL, `/openai`, or `/openai/v1` forms.\n const root = normalized.replace(/\\/v1$/u, \"\");\n return root.endsWith(\"/openai\") ? root : `${root}/openai`;\n }\n } catch {\n // Let the provider report malformed URLs with its normal error.\n }\n return normalized;\n};\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 azure: { label: \"Azure OpenAI\", specifier: \"@ai-sdk/azure\" },\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 azure: \"azure\",\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:\n | LanguageModel\n | EmbeddingModel\n | ImageModel\n | TranscriptionModel\n | VideoModel\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\" || provider === \"azure\") {\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 \"azure\": {\n return import(\"@ai-sdk/azure\");\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 } = await loadProvider<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 \"azure\": {\n const { createAzure } = await loadProvider<AzureModule>(\"azure\");\n const provider = createAzure({\n ...settings,\n // Batchwork documents Azure base URLs as the API root ending in\n // `/openai/v1`; the AI SDK expects the Azure root before `/v1`.\n baseURL: azureCaptureBaseUrl(credentials.baseURL),\n });\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<AnthropicModule>(\"anthropic\");\n return createAnthropic(settings).messages(resolved.modelId);\n }\n case \"groq\": {\n const { createGroq } = await loadProvider<GroqModule>(\"groq\");\n return createGroq(settings).languageModel(resolved.modelId);\n }\n case \"mistral\": {\n const { createMistral } = await loadProvider<MistralModule>(\"mistral\");\n return createMistral(settings).languageModel(resolved.modelId);\n }\n case \"google\": {\n const { createGoogleGenerativeAI } =\n await loadProvider<GoogleModule>(\"google\");\n return createGoogleGenerativeAI(settings).languageModel(resolved.modelId);\n }\n case \"xai\": {\n const { createXai } = await loadProvider<XaiModule>(\"xai\");\n return createXai(settings).languageModel(resolved.modelId);\n }\n case \"together\": {\n const { createTogetherAI } =\n await loadProvider<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 } = await loadProvider<OpenAIModule>(\"openai\");\n return createOpenAI(settings).embeddingModel(resolved.modelId);\n }\n case \"mistral\": {\n const { createMistral } = await loadProvider<MistralModule>(\"mistral\");\n return createMistral(settings).embeddingModel(resolved.modelId);\n }\n case \"google\": {\n const { createGoogleGenerativeAI } =\n await loadProvider<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 editing. OpenAI and xAI both expose\n * `/v1/images/edits` as a batch endpoint (JSON bodies with asset references —\n * OpenAI takes uploaded file ids or image URLs plus an optional mask; xAI\n * takes image URLs only). Google's Gemini batch has no edit endpoint.\n */\nexport const IMAGE_EDIT_PROVIDERS = new Set<BatchProvider>([\"openai\", \"xai\"]);\n\nexport const unsupportedImageEditProvider = (\n provider: BatchProvider\n): UnsupportedProviderError =>\n new UnsupportedProviderError(\n provider,\n `batchwork: provider \"${provider}\" does not offer batch image editing. Image edits are supported for: openai, xai.`\n );\n\n/**\n * Providers whose batch API accepts video generation. xAI exposes\n * `/v1/videos/generations` (plus `/edits` and `/extensions`) as batch\n * endpoints for Grok Imagine. OpenAI's Videos API (Sora) is deprecated and\n * shuts down 2026-09-24, so it is deliberately not supported; Google's Veo\n * models are not batch-compatible.\n */\nexport const VIDEO_PROVIDERS = new Set<BatchProvider>([\"xai\"]);\n\nexport const unsupportedVideoProvider = (\n provider: BatchProvider\n): UnsupportedProviderError =>\n new UnsupportedProviderError(\n provider,\n `batchwork: provider \"${provider}\" does not offer batch video generation. Videos are supported for: xai.`\n );\n\n/**\n * Construct an AI SDK video model wired to a capturing `fetch`, used to derive\n * the provider video request body for each batch item without making a network\n * call. Throws for providers without batch video support.\n */\nexport const createCaptureVideoModel = async (\n resolved: ResolvedModel,\n credentials: ProviderCredentials,\n fetchImpl: CapturingFetch\n): Promise<VideoModel> => {\n if (resolved.provider !== \"xai\") {\n throw unsupportedVideoProvider(resolved.provider);\n }\n const { createXai } = await loadProvider<XaiModule>(\"xai\");\n return createXai({\n apiKey: credentials.apiKey ?? CAPTURE_API_KEY,\n baseURL: credentials.baseURL,\n fetch: fetchImpl,\n headers: credentials.headers,\n }).video(resolved.modelId);\n};\n\n/**\n * Providers whose batch API accepts audio translation (Whisper's\n * translate-to-English task). Groq and Together expose\n * `/v1/audio/translations` as a batch endpoint; Mistral batches\n * transcriptions but not translations.\n */\nexport const TRANSLATION_PROVIDERS = new Set<BatchProvider>([\n \"groq\",\n \"together\",\n]);\n\nexport const unsupportedTranslationProvider = (\n provider: BatchProvider\n): UnsupportedProviderError =>\n new UnsupportedProviderError(\n provider,\n `batchwork: provider \"${provider}\" does not offer batch translation. Translations are supported for: groq, together.`\n );\n\n/**\n * Providers whose batch API accepts moderation. OpenAI exposes\n * `/v1/moderations` as a batch endpoint (omni moderation, text + images);\n * Mistral runs its moderation models through the same batch job flow\n * (text-only). No other provider has a standalone moderation API.\n */\nexport const MODERATION_PROVIDERS = new Set<BatchProvider>([\n \"mistral\",\n \"openai\",\n]);\n\nexport const unsupportedModerationProvider = (\n provider: BatchProvider\n): UnsupportedProviderError =>\n new UnsupportedProviderError(\n provider,\n `batchwork: provider \"${provider}\" does not offer batch moderation. Moderations are supported for: openai, mistral.`\n );\n\n/**\n * Providers whose batch API accepts audio transcription. Groq, Mistral, and\n * Together expose `/v1/audio/transcriptions` as a batch endpoint; OpenAI's\n * batch API does not accept audio endpoints, and the remaining providers have\n * no standalone transcription API.\n */\nexport const TRANSCRIPTION_PROVIDERS = new Set<BatchProvider>([\n \"groq\",\n \"mistral\",\n \"together\",\n]);\n\nexport const unsupportedTranscriptionProvider = (\n provider: BatchProvider\n): UnsupportedProviderError =>\n new UnsupportedProviderError(\n provider,\n `batchwork: provider \"${provider}\" does not offer batch transcription. Transcriptions are supported for: groq, mistral, together.`\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 } = await loadProvider<OpenAIModule>(\"openai\");\n return createOpenAI(settings).image(resolved.modelId);\n }\n case \"google\": {\n const { createGoogleGenerativeAI } =\n await loadProvider<GoogleModule>(\"google\");\n return createGoogleGenerativeAI(settings).image(resolved.modelId);\n }\n case \"xai\": {\n const { createXai } = await loadProvider<XaiModule>(\"xai\");\n return createXai(settings).image(resolved.modelId);\n }\n default: {\n throw unsupportedImageProvider(resolved.provider);\n }\n }\n};\n",
6
- "import {\n embed,\n experimental_generateVideo,\n generateImage,\n generateText,\n} 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 createCaptureVideoModel,\n unsupportedImageEditProvider,\n unsupportedModerationProvider,\n unsupportedTranscriptionProvider,\n} from \"./model\";\nimport type { CapturingFetch, ResolvedModel } from \"./model\";\nimport type {\n BatchDefaults,\n BatchEmbeddingRequest,\n BatchImageDefaults,\n BatchImageEditDefaults,\n BatchImageEditRequest,\n BatchImageRef,\n BatchImageRequest,\n BatchLimits,\n BatchModerationRequest,\n BatchRequest,\n BatchTranscriptionDefaults,\n BatchTranscriptionRequest,\n BatchTranslationDefaults,\n BatchTranslationRequest,\n BatchVideoDefaults,\n BatchVideoRequest,\n ProviderCredentials,\n VideoModel,\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 = <Request extends object>(\n request: Request,\n defaults: NoInfer<Partial<Request>> | undefined\n): Request => {\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 MODERATION_ENDPOINT = \"/v1/moderations\";\n\n/**\n * Build the moderation `input`: a bare string for text, or the OpenAI omni\n * moderation content-part array when images are involved.\n */\nconst moderationInput = (request: BatchModerationRequest): unknown => {\n const imageUrls = request.imageUrls ?? [];\n if (imageUrls.length === 0) {\n return request.value;\n }\n return [\n ...(request.value === undefined\n ? []\n : [{ text: request.value, type: \"text\" }]),\n ...imageUrls.map((url) => ({ image_url: { url }, type: \"image_url\" })),\n ];\n};\n\n/**\n * Build the provider moderation body directly — the AI SDK has no moderation\n * call to capture. Both providers take `{ input }`; OpenAI carries the model\n * per line, Mistral on the job.\n */\nconst moderationBody = (\n resolved: ResolvedModel,\n request: BatchModerationRequest,\n customId: string\n): Record<string, unknown> => {\n if (request.value === undefined && !request.imageUrls?.length) {\n throw new BatchworkError(\n `batchwork: moderation request \"${customId}\" needs \\`value\\` or \\`imageUrls\\`.`\n );\n }\n const options = request.providerOptions?.[resolved.provider];\n if (resolved.provider === \"openai\") {\n return {\n input: moderationInput(request),\n model: resolved.modelId,\n ...options,\n };\n }\n if (resolved.provider === \"mistral\") {\n if (request.imageUrls?.length) {\n throw new BatchworkError(\n `batchwork: moderation request \"${customId}\" has \\`imageUrls\\`, but Mistral moderation is text-only.`\n );\n }\n // `model` is included for uniformity; the Mistral adapter strips it from\n // each line and sets it on the job instead.\n return { input: request.value, model: resolved.modelId, ...options };\n }\n throw unsupportedModerationProvider(resolved.provider);\n};\n\n/**\n * Build provider moderation request bodies for every batch item. Each item\n * maps to a single moderation verdict, correlated by `customId`.\n */\nexport const buildModerationBodies = (\n resolved: ResolvedModel,\n requests: readonly BatchModerationRequest[],\n rawLimits?: BatchLimits | ResolvedBatchLimits\n): 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 return assignCustomIds(requests).map((item) => {\n const body = moderationBody(resolved, item.request, item.customId);\n assertByteLength(\n `request \"${item.customId}\"`,\n JSON.stringify(body),\n limits.maxRequestBytes\n );\n return { body, customId: item.customId, endpoint: MODERATION_ENDPOINT };\n });\n};\n\nconst TRANSCRIPTION_ENDPOINT = \"/v1/audio/transcriptions\";\n\n/**\n * Build the provider transcription body directly. Batch audio endpoints take\n * JSON with a hosted audio URL — unlike the synchronous transcription APIs\n * (and the AI SDK's `transcribe`), which upload the file as multipart form\n * data — so there is no SDK call to capture.\n */\nconst transcriptionBody = (\n resolved: ResolvedModel,\n request: BatchTranscriptionRequest\n): Record<string, unknown> => {\n const options = request.providerOptions?.[resolved.provider];\n if (resolved.provider === \"groq\") {\n return {\n model: resolved.modelId,\n url: request.audioUrl,\n ...(request.language ? { language: request.language } : {}),\n // Timestamps require the verbose response shape; providerOptions can\n // still override `response_format` since it spreads last.\n ...(request.timestampGranularities\n ? {\n response_format: \"verbose_json\",\n timestamp_granularities: request.timestampGranularities,\n }\n : {}),\n ...options,\n };\n }\n if (resolved.provider === \"mistral\") {\n // `model` is included for uniformity; the Mistral adapter strips it from\n // each line and sets it on the job instead.\n return {\n file_url: request.audioUrl,\n model: resolved.modelId,\n ...(request.language ? { language: request.language } : {}),\n ...(request.timestampGranularities\n ? { timestamp_granularities: request.timestampGranularities }\n : {}),\n ...options,\n };\n }\n if (resolved.provider === \"together\") {\n // Together's audio batch lines carry the hosted URL in `file`; extra\n // fields pass through to the underlying transcription API.\n return {\n file: request.audioUrl,\n model: resolved.modelId,\n ...(request.language ? { language: request.language } : {}),\n ...(request.timestampGranularities\n ? {\n response_format: \"verbose_json\",\n timestamp_granularities: request.timestampGranularities,\n }\n : {}),\n ...options,\n };\n }\n throw unsupportedTranscriptionProvider(resolved.provider);\n};\n\nconst buildAudioBodies = (\n resolved: ResolvedModel,\n requests: readonly BatchTranscriptionRequest[],\n defaults: BatchTranscriptionDefaults | undefined,\n endpoint: string,\n rawLimits?: BatchLimits | ResolvedBatchLimits\n): 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 return assignCustomIds(requests).map((item) => {\n const body = transcriptionBody(\n resolved,\n mergeDefaults(item.request, defaults)\n );\n assertByteLength(\n `request \"${item.customId}\"`,\n JSON.stringify(body),\n limits.maxRequestBytes\n );\n return { body, customId: item.customId, endpoint };\n });\n};\n\n/**\n * Build provider transcription request bodies for every batch item. Each item\n * maps to a single transcription of a hosted audio URL, correlated by\n * `customId`.\n */\nexport const buildTranscriptionBodies = (\n resolved: ResolvedModel,\n requests: readonly BatchTranscriptionRequest[],\n defaults: BatchTranscriptionDefaults | undefined,\n rawLimits?: BatchLimits | ResolvedBatchLimits\n): BuiltRequest[] =>\n buildAudioBodies(\n resolved,\n requests,\n defaults,\n TRANSCRIPTION_ENDPOINT,\n rawLimits\n );\n\n/**\n * Build provider audio-translation request bodies for every batch item. The\n * body shape is identical to transcription (minus `language` — the output is\n * always English); only the endpoint differs.\n */\nexport const buildTranslationBodies = (\n resolved: ResolvedModel,\n requests: readonly BatchTranslationRequest[],\n defaults: BatchTranslationDefaults | undefined,\n rawLimits?: BatchLimits | ResolvedBatchLimits\n): BuiltRequest[] =>\n buildAudioBodies(\n resolved,\n requests,\n defaults,\n \"/v1/audio/translations\",\n rawLimits\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 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\nconst IMAGE_EDIT_ENDPOINT = \"/v1/images/edits\";\n\nconst openaiImageRef = (ref: BatchImageRef): Record<string, string> =>\n \"fileId\" in ref ? { file_id: ref.fileId } : { image_url: ref.imageUrl };\n\n/**\n * Build the provider image-edit body directly — the AI SDK's `generateImage`\n * has no way to pass input images, so there is no call to capture. Both\n * providers take JSON with asset references: OpenAI `{ images: [{ file_id |\n * image_url }], mask? }`, xAI `{ image: { url } }` (URLs only, no masks).\n */\nconst imageEditBody = (\n resolved: ResolvedModel,\n request: BatchImageEditRequest,\n customId: string\n): Record<string, unknown> => {\n if (request.images.length === 0) {\n throw new BatchworkError(\n `batchwork: image-edit request \"${customId}\" needs at least one entry in \\`images\\`.`\n );\n }\n const options = request.providerOptions?.[resolved.provider];\n if (resolved.provider === \"openai\") {\n return {\n images: request.images.map(openaiImageRef),\n model: resolved.modelId,\n prompt: request.prompt,\n ...(request.mask ? { mask: openaiImageRef(request.mask) } : {}),\n ...(request.n === undefined ? {} : { n: request.n }),\n ...(request.size ? { size: request.size } : {}),\n ...options,\n };\n }\n if (resolved.provider === \"xai\") {\n if (request.mask) {\n throw new BatchworkError(\n `batchwork: image-edit request \"${customId}\" has a \\`mask\\`, but xAI image edits do not support masks.`\n );\n }\n if (request.size) {\n throw new BatchworkError(\n `batchwork: image-edit request \"${customId}\" has \\`size\\`, but xAI image edits take \\`providerOptions.xai.aspect_ratio\\` instead.`\n );\n }\n const urls = request.images.map((ref) => {\n if (\"fileId\" in ref) {\n throw new BatchworkError(\n `batchwork: image-edit request \"${customId}\" uses a \\`fileId\\` reference, but xAI image edits accept image URLs only.`\n );\n }\n return ref.imageUrl;\n });\n return {\n model: resolved.modelId,\n prompt: request.prompt,\n ...(urls.length === 1\n ? { image: { url: urls[0] } }\n : { images: urls.map((url) => ({ url })) }),\n ...(request.n === undefined ? {} : { n: request.n }),\n ...options,\n };\n }\n throw unsupportedImageEditProvider(resolved.provider);\n};\n\n/**\n * Build provider image-edit request bodies for every batch item. Each item\n * maps to a single edit call, correlated by `customId`.\n */\nexport const buildImageEditBodies = (\n resolved: ResolvedModel,\n requests: readonly BatchImageEditRequest[],\n defaults: BatchImageEditDefaults | undefined,\n rawLimits?: BatchLimits | ResolvedBatchLimits\n): 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 return assignCustomIds(requests).map((item) => {\n const body = imageEditBody(\n resolved,\n mergeDefaults(item.request, defaults),\n item.customId\n );\n assertByteLength(\n `request \"${item.customId}\"`,\n JSON.stringify(body),\n limits.maxRequestBytes\n );\n return { body, customId: item.customId, endpoint: IMAGE_EDIT_ENDPOINT };\n });\n};\n\nconst captureVideoOne = async (\n model: VideoModel,\n request: BatchVideoRequest,\n customId: string,\n maxRequestBytes: number\n): Promise<BuiltRequest> => {\n try {\n // The provider's first network call is the JSON job-creation POST (polling\n // only starts afterwards), so the capturing `fetch` intercepts the exact\n // body a batch line needs. Edit/extend modes (via `providerOptions`) are\n // captured against their own endpoints, which xAI batch also accepts.\n await experimental_generateVideo({\n aspectRatio: request.aspectRatio,\n duration: request.duration,\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 prompt: request.prompt,\n providerOptions: request.providerOptions,\n resolution: request.resolution,\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 video body.\"\n );\n};\n\n/**\n * Derive provider video-generation request bodies for every batch item by\n * running each through the AI SDK `generateVideo` with a capturing `fetch`.\n * Mirrors {@link buildRequestBodies} for the video endpoints; each item maps to\n * a single video job, correlated by `customId`.\n */\nexport const buildVideoBodies = async (\n resolved: ResolvedModel,\n requests: readonly BatchVideoRequest[],\n defaults: BatchVideoDefaults | 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 createCaptureVideoModel(\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 captureVideoOne(\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",
7
- "import {\n buildEmbeddingBodies,\n buildImageBodies,\n buildImageEditBodies,\n buildModerationBodies,\n buildRequestBodies,\n buildTranscriptionBodies,\n buildTranslationBodies,\n buildVideoBodies,\n} from \"./body\";\nimport { BatchworkError } from \"./errors\";\nimport { BatchJob } from \"./job\";\nimport { resolveBatchLimits } from \"./limits\";\nimport {\n EMBEDDING_PROVIDERS,\n IMAGE_EDIT_PROVIDERS,\n IMAGE_PROVIDERS,\n MODERATION_PROVIDERS,\n resolveModel,\n TRANSCRIPTION_PROVIDERS,\n TRANSLATION_PROVIDERS,\n unsupportedEmbeddingProvider,\n unsupportedImageEditProvider,\n unsupportedImageProvider,\n unsupportedModerationProvider,\n unsupportedTranscriptionProvider,\n unsupportedTranslationProvider,\n unsupportedVideoProvider,\n VIDEO_PROVIDERS,\n} from \"./model\";\nimport { getAdapter } from \"./providers\";\nimport type {\n BatchEmbeddingsOptions,\n BatchImageEditOptions,\n BatchImageOptions,\n BatchModerationOptions,\n BatchOptions,\n BatchProvider,\n BatchRef,\n BatchResult,\n BatchTranscriptionOptions,\n BatchTranslationOptions,\n BatchVideoOptions,\n ProviderCredentials,\n} from \"./types\";\n\nconst EMPTY_REQUESTS_MESSAGE = \"batchwork: `requests` must not be empty.\";\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(EMPTY_REQUESTS_MESSAGE);\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(EMPTY_REQUESTS_MESSAGE);\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(EMPTY_REQUESTS_MESSAGE);\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 image-edit requests to the model's provider and return a\n * handle. Each request's `prompt` is applied to its source `images` (uploaded\n * file ids or hosted URLs — batch bodies are JSON, so raw uploads aren't\n * possible), producing edited images on `result.images`, correlated by\n * `customId` via {@link BatchJob.results}. Supported for OpenAI and xAI; other\n * providers throw {@link UnsupportedProviderError}.\n *\n * @example\n * const job = await batch.images.edit({\n * model: openai.image(\"gpt-image-2\"),\n * requests: [\n * {\n * customId: \"a\",\n * prompt: \"Make the bicycle blue.\",\n * images: [{ imageUrl: \"https://example.com/bicycle.png\" }],\n * },\n * ],\n * });\n * const results = await job.wait().then(() => job.collect());\n */\nconst submitImageEdits = async (\n options: BatchImageEditOptions\n): Promise<BatchJob> => {\n if (options.requests.length === 0) {\n throw new BatchworkError(EMPTY_REQUESTS_MESSAGE);\n }\n\n const resolved = resolveModel(options.model);\n if (!IMAGE_EDIT_PROVIDERS.has(resolved.provider)) {\n throw unsupportedImageEditProvider(resolved.provider);\n }\n const credentials = pickCredentials(options);\n const limits = resolveBatchLimits(options.limits);\n const adapter = getAdapter(resolved.provider);\n\n const built = buildImageEditBodies(\n resolved,\n options.requests,\n options.defaults,\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 moderation requests to the model's provider and return a\n * handle. Each request's `value` (and/or `imageUrls`, OpenAI omni moderation\n * only) produces one verdict on `result.moderation`, correlated by `customId`\n * via {@link BatchJob.results}. Supported for OpenAI and Mistral; other\n * providers throw {@link UnsupportedProviderError}. Pass the model as a\n * `\"provider/model\"` string — the AI SDK has no moderation model type.\n *\n * @example\n * const job = await batch.moderations({\n * model: \"openai/omni-moderation-latest\",\n * requests: [{ customId: \"a\", value: \"…user-generated content…\" }],\n * });\n * const results = await job.wait().then(() => job.collect());\n * for (const r of results) {\n * console.log(r.customId, r.moderation?.flagged);\n * }\n */\nconst submitModerations = async (\n options: BatchModerationOptions\n): Promise<BatchJob> => {\n if (options.requests.length === 0) {\n throw new BatchworkError(EMPTY_REQUESTS_MESSAGE);\n }\n\n const resolved = resolveModel(options.model);\n if (!MODERATION_PROVIDERS.has(resolved.provider)) {\n throw unsupportedModerationProvider(resolved.provider);\n }\n const credentials = pickCredentials(options);\n const limits = resolveBatchLimits(options.limits);\n const adapter = getAdapter(resolved.provider);\n\n const built = buildModerationBodies(resolved, options.requests, limits);\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 audio-transcription requests to the model's provider and\n * return a handle. Each request's `audioUrl` (a hosted audio file — batch\n * audio endpoints accept URLs, not file uploads) produces one transcript,\n * correlated by `customId` via {@link BatchJob.results}. Supported for Groq\n * and Mistral; other providers throw {@link UnsupportedProviderError}.\n *\n * @example\n * const job = await batch.transcriptions({\n * model: groq.transcription(\"whisper-large-v3\"),\n * requests: [{ customId: \"a\", audioUrl: \"https://example.com/call.wav\" }],\n * });\n * const results = await job.wait().then(() => job.collect());\n * for (const r of results) {\n * console.log(r.customId, r.text);\n * }\n */\nconst submitTranscriptions = async (\n options: BatchTranscriptionOptions\n): Promise<BatchJob> => {\n if (options.requests.length === 0) {\n throw new BatchworkError(EMPTY_REQUESTS_MESSAGE);\n }\n\n const resolved = resolveModel(options.model);\n if (!TRANSCRIPTION_PROVIDERS.has(resolved.provider)) {\n throw unsupportedTranscriptionProvider(resolved.provider);\n }\n const credentials = pickCredentials(options);\n const limits = resolveBatchLimits(options.limits);\n const adapter = getAdapter(resolved.provider);\n\n const built = buildTranscriptionBodies(\n resolved,\n options.requests,\n options.defaults,\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 video-generation requests to the model's provider and\n * return a handle. Each request's `prompt` produces one video, correlated by\n * `customId` via {@link BatchJob.results}. Supported for xAI (Grok Imagine);\n * other providers throw {@link UnsupportedProviderError} — OpenAI's Videos API\n * (Sora) is deprecated and Google's Veo models are not batch-compatible.\n *\n * Results come back as signed URLs on `result.videos` that **expire ~1h**\n * after completion — download promptly.\n *\n * @example\n * const job = await batch.videos({\n * model: xai.video(\"grok-imagine-video\"),\n * requests: [{ customId: \"a\", prompt: \"A red bicycle rolling downhill.\" }],\n * });\n * const results = await job.wait().then(() => job.collect());\n * for (const r of results) {\n * console.log(r.customId, r.videos?.[0]?.url);\n * }\n */\nconst submitVideos = async (options: BatchVideoOptions): Promise<BatchJob> => {\n if (options.requests.length === 0) {\n throw new BatchworkError(EMPTY_REQUESTS_MESSAGE);\n }\n\n const resolved = resolveModel(options.model);\n if (!VIDEO_PROVIDERS.has(resolved.provider)) {\n throw unsupportedVideoProvider(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 buildVideoBodies(\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 audio-translation requests (Whisper's translate task —\n * audio in any language, English text out) and return a handle. Mirrors\n * {@link batch.transcriptions} minus `language`: each request's `audioUrl`\n * produces one English transcript on `result.text`, correlated by `customId`.\n * Supported for Groq and Together; other providers throw\n * {@link UnsupportedProviderError} — Mistral batches transcriptions but not\n * translations.\n *\n * @example\n * const job = await batch.translations({\n * model: groq.transcription(\"whisper-large-v3\"),\n * requests: [{ customId: \"a\", audioUrl: \"https://example.com/french.wav\" }],\n * });\n * const results = await job.wait().then(() => job.collect());\n */\nconst submitTranslations = async (\n options: BatchTranslationOptions\n): Promise<BatchJob> => {\n if (options.requests.length === 0) {\n throw new BatchworkError(EMPTY_REQUESTS_MESSAGE);\n }\n\n const resolved = resolveModel(options.model);\n if (!TRANSLATION_PROVIDERS.has(resolved.provider)) {\n throw unsupportedTranslationProvider(resolved.provider);\n }\n const credentials = pickCredentials(options);\n const limits = resolveBatchLimits(options.limits);\n const adapter = getAdapter(resolved.provider);\n\n const built = buildTranslationBodies(\n resolved,\n options.requests,\n options.defaults,\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} / {@link batch.images.create} — image generation\n * - {@link batch.images.edit} — image editing\n * - {@link batch.transcriptions} — audio transcription\n * - {@link batch.translations} — audio translation to English\n * - {@link batch.moderations} — content moderation\n * - {@link batch.videos} — video 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 /**\n * Submit a batch of image-generation requests. Also exposes\n * {@link batch.images.create} (an alias of calling it directly) and\n * {@link batch.images.edit} for editing existing images.\n */\n images: Object.assign(submitImages, {\n /** Submit a batch of image-generation requests. Equivalent to `batch.images()`. */\n create: submitImages,\n /** Submit a batch of image-edit requests. */\n edit: submitImageEdits,\n }),\n /** Submit a batch of moderation requests. */\n moderations: submitModerations,\n /** Submit a batch of text/chat requests. Equivalent to calling `batch()`. */\n text: submitText,\n /** Submit a batch of audio-transcription requests. */\n transcriptions: submitTranscriptions,\n /** Submit a batch of audio-translation (to English) requests. */\n translations: submitTranslations,\n /** Submit a batch of video-generation requests. */\n videos: submitVideos,\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": "1B451ACF41BE2A3C64756E2164756E21",
11
- "names": []
12
- }
@@ -1,13 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/server/events.ts", "../src/server/signing.ts", "../src/server/poller.ts", "../src/server/store.ts"],
4
- "sourcesContent": [
5
- "import type { BatchProvider, BatchSnapshot, BatchStatus } from \"../types\";\nimport type { BatchWebhookEvent, BatchWebhookEventType } from \"./types\";\n\nconst EVENT_BY_STATUS: Partial<Record<BatchStatus, BatchWebhookEventType>> = {\n cancelled: \"batch.cancelled\",\n completed: \"batch.completed\",\n expired: \"batch.expired\",\n failed: \"batch.failed\",\n};\n\n/** Map a terminal snapshot to the unified webhook event batchwork delivers. */\nexport const toEvent = (\n provider: BatchProvider,\n snapshot: BatchSnapshot\n): BatchWebhookEvent => ({\n completedAt: snapshot.completedAt?.toISOString(),\n createdAt: snapshot.createdAt?.toISOString(),\n id: snapshot.id,\n provider,\n requestCounts: snapshot.requestCounts,\n type: EVENT_BY_STATUS[snapshot.status] ?? \"batch.completed\",\n});\n",
6
- "import { BatchworkError } from \"../errors\";\nimport type { BatchWebhookEvent } from \"./types\";\n\n// Standard Webhooks-style HMAC-SHA256 signing, compatible with OpenAI's webhook\n// signatures (so the same verifier handles inbound OpenAI events and batchwork's\n// own outbound deliveries). Uses Web Crypto so it runs on edge runtimes.\n\nconst SIGNATURE_VERSION = \"v1\";\nconst TOLERANCE_SECONDS = 300;\nconst SECRET_PREFIX = \"whsec_\";\nconst encoder = new TextEncoder();\n\nexport interface WebhookReplayStore {\n claim?: (\n id: string,\n expiresAt: number,\n now: number\n ) => boolean | Promise<boolean>;\n get: (id: string) => number | Promise<number | undefined> | undefined;\n set: (id: string, expiresAt: number) => Promise<void> | void;\n}\n\nexport interface VerifyWebhookOptions {\n replayStore?: WebhookReplayStore;\n}\n\nconst replayCache = new Map<string, number>();\nconst replayLocks = new WeakMap<\n WebhookReplayStore,\n Map<string, Promise<void>>\n>();\n\nconst pruneReplayCache = (now: number): void => {\n for (const [id, expiresAt] of replayCache) {\n if (expiresAt <= now) {\n replayCache.delete(id);\n }\n }\n};\n\nconst defaultReplayStore: WebhookReplayStore = {\n claim: (id, expiresAt, now) => {\n pruneReplayCache(now);\n const existing = replayCache.get(id);\n if (existing && existing > now) {\n return false;\n }\n replayCache.set(id, expiresAt);\n return true;\n },\n get: (id) => replayCache.get(id),\n set: (id, expiresAt) => {\n replayCache.set(id, expiresAt);\n },\n};\n\nconst withReplayLock = async <Result>(\n store: WebhookReplayStore,\n id: string,\n task: () => Promise<Result>\n): Promise<Result> => {\n let locks = replayLocks.get(store);\n if (!locks) {\n locks = new Map();\n replayLocks.set(store, locks);\n }\n\n const previous = locks.get(id);\n let release!: () => void;\n // oxlint-disable-next-line promise/avoid-new -- a per-id lock needs a deferred release signal.\n const current = new Promise<void>((resolve) => {\n release = resolve;\n });\n locks.set(id, current);\n\n if (previous) {\n await previous;\n }\n try {\n return await task();\n } finally {\n release();\n if (locks.get(id) === current) {\n locks.delete(id);\n }\n }\n};\n\nconst base64ToBytes = (value: string): Uint8Array<ArrayBuffer> =>\n Uint8Array.from(atob(value), (char) => char.codePointAt(0) ?? 0);\n\nconst bytesToBase64 = (bytes: Uint8Array): string => {\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCodePoint(byte);\n }\n return btoa(binary);\n};\n\nconst importKey = (secret: string): Promise<CryptoKey> => {\n const raw = secret.startsWith(SECRET_PREFIX)\n ? base64ToBytes(secret.slice(SECRET_PREFIX.length))\n : encoder.encode(secret);\n return crypto.subtle.importKey(\n \"raw\",\n raw,\n { hash: \"SHA-256\", name: \"HMAC\" },\n false,\n [\"sign\", \"verify\"]\n );\n};\n\nconst signContent = async (\n secret: string,\n content: string\n): Promise<string> => {\n const key = await importKey(secret);\n const signature = await crypto.subtle.sign(\n \"HMAC\",\n key,\n encoder.encode(content)\n );\n return bytesToBase64(new Uint8Array(signature));\n};\n\nconst verifyContent = async (\n secret: string,\n content: string,\n signature: string\n): Promise<boolean> => {\n const key = await importKey(secret);\n return crypto.subtle.verify(\n \"HMAC\",\n key,\n base64ToBytes(signature),\n encoder.encode(content)\n );\n};\n\nconst rememberWebhookId = async (\n id: string,\n timestamp: number,\n now: number,\n store: WebhookReplayStore\n): Promise<void> => {\n const expiresAt = timestamp + TOLERANCE_SECONDS;\n if (store.claim) {\n const claimed = await store.claim(id, expiresAt, now);\n if (!claimed) {\n throw new BatchworkError(\"batchwork: webhook replay detected.\");\n }\n return;\n }\n\n await withReplayLock(store, id, async () => {\n if (store === defaultReplayStore) {\n pruneReplayCache(now);\n }\n const existing = await store.get(id);\n if (existing && existing > now) {\n throw new BatchworkError(\"batchwork: webhook replay detected.\");\n }\n await store.set(id, expiresAt);\n });\n};\n\n/** Build Standard Webhooks signature headers for an outbound delivery. */\nexport const signWebhook = async (\n secret: string,\n id: string,\n body: string,\n timestampSeconds: number\n): Promise<Record<string, string>> => {\n const timestamp = Math.floor(timestampSeconds).toString();\n const signature = await signContent(secret, `${id}.${timestamp}.${body}`);\n return {\n \"webhook-id\": id,\n \"webhook-signature\": `${SIGNATURE_VERSION},${signature}`,\n \"webhook-timestamp\": timestamp,\n };\n};\n\nexport interface VerifiedWebhook {\n id: string;\n timestamp: number;\n body: string;\n}\n\n/**\n * Verify a Standard Webhooks-signed request and return its raw body. Throws if\n * headers are missing, the timestamp is outside tolerance, or no signature\n * matches. Consumes the request body.\n */\nexport const verifyWebhook = async (\n request: Request,\n secret: string,\n options?: VerifyWebhookOptions\n): Promise<VerifiedWebhook> => {\n const id = request.headers.get(\"webhook-id\");\n const timestamp = request.headers.get(\"webhook-timestamp\");\n const signatureHeader = request.headers.get(\"webhook-signature\");\n if (!(id && timestamp && signatureHeader)) {\n throw new BatchworkError(\"batchwork: missing webhook signature headers.\");\n }\n\n const seconds = Number(timestamp);\n const now = Date.now() / 1000;\n if (\n !Number.isFinite(seconds) ||\n Math.abs(now - seconds) > TOLERANCE_SECONDS\n ) {\n throw new BatchworkError(\"batchwork: webhook timestamp outside tolerance.\");\n }\n\n const body = await request.text();\n const content = `${id}.${timestamp}.${body}`;\n const signatures = signatureHeader.split(\" \").map((part) => {\n const comma = part.indexOf(\",\");\n return comma === -1 ? part : part.slice(comma + 1);\n });\n\n let valid = false;\n for (const signature of signatures) {\n // oxlint-disable-next-line no-await-in-loop -- usually a single signature.\n if (await verifyContent(secret, content, signature)) {\n valid = true;\n break;\n }\n }\n if (!valid) {\n throw new BatchworkError(\n \"batchwork: webhook signature verification failed.\"\n );\n }\n\n await rememberWebhookId(\n id,\n seconds,\n now,\n options?.replayStore ?? defaultReplayStore\n );\n\n return { body, id, timestamp: seconds };\n};\n\n/**\n * Verify and parse a batchwork webhook on your receiving endpoint. Returns the\n * unified {@link BatchWebhookEvent}.\n */\nexport const verifyBatchWebhook = async (\n request: Request,\n secret: string,\n options?: VerifyWebhookOptions\n): Promise<BatchWebhookEvent> => {\n const { body } = await verifyWebhook(request, secret, options);\n return JSON.parse(body) as BatchWebhookEvent;\n};\n",
7
- "import { BatchworkError } from \"../errors\";\nimport { isTerminalStatus } from \"../job\";\nimport { getAdapter } from \"../providers\";\nimport type {\n BatchProvider,\n BatchSnapshot,\n BatchStatus,\n ProviderCredentials,\n} from \"../types\";\nimport { toEvent } from \"./events\";\nimport { signWebhook, verifyWebhook } from \"./signing\";\nimport type { BatchStore, TrackedBatch } from \"./types\";\n\n/** Credentials for polling: a fixed config, or one resolved per provider. */\nexport type CredentialResolver =\n | ProviderCredentials\n | ((provider: BatchProvider) => ProviderCredentials);\n\n/**\n * Handles a batch reaching a terminal status. Replaces the default signed\n * webhook delivery — e.g. to invoke a callback instead (see `batchwork/next`).\n */\nexport type CompletionSink = (\n record: TrackedBatch,\n snapshot: BatchSnapshot\n) => Promise<void>;\n\nexport type WebhookUrlValidator = (url: URL) => void | Promise<void>;\n\nexport interface BatchPollerOptions {\n store: BatchStore;\n /** Falls back to provider env vars (e.g. `OPENAI_API_KEY`) when omitted. */\n credentials?: CredentialResolver;\n /** Replaces signed-webhook delivery when a batch finishes. */\n onComplete?: CompletionSink;\n /** Override the default webhook URL policy with an application allowlist. */\n validateWebhookUrl?: WebhookUrlValidator;\n /**\n * Called when processing a single batch throws during `tick`. When provided,\n * the tick reports the error and continues to the next batch; when omitted,\n * the error propagates out of `tick`.\n */\n onError?: (record: TrackedBatch, error: unknown) => void;\n}\n\nexport interface TrackTarget {\n id: string;\n provider: BatchProvider;\n status?: BatchStatus;\n}\n\nexport interface TrackOptions {\n /** Where to POST the completion webhook. Omit for callback-based delivery. */\n webhookUrl?: string;\n /** Signs the outbound webhook (Standard Webhooks HMAC) when provided. */\n secret?: string;\n}\n\nexport interface TickResult {\n checked: number;\n delivered: string[];\n /** Batches whose processing threw this tick (only when `onError` is set). */\n failed?: { id: string; error: string }[];\n}\n\nexport interface OpenAIWebhookOptions {\n /** The OpenAI webhook signing secret (`whsec_…`). */\n signingSecret: string;\n}\n\nexport interface BatchPoller {\n track: (target: TrackTarget, options: TrackOptions) => Promise<TrackedBatch>;\n tick: () => Promise<TickResult>;\n deliver: (record: TrackedBatch, snapshot: BatchSnapshot) => Promise<void>;\n openaiWebhookHandler: (\n options: OpenAIWebhookOptions\n ) => (request: Request) => Promise<Response>;\n}\n\nconst parseIpv4 = (host: string): number[] | undefined => {\n if (!/^\\d{1,3}(?:\\.\\d{1,3}){3}$/u.test(host)) {\n return;\n }\n const parts = host.split(\".\").map(Number);\n const valid = parts.every(\n (part) => Number.isInteger(part) && part >= 0 && part <= 255\n );\n return valid ? parts : undefined;\n};\n\nconst isPrivateIpv4 = (parts: number[]): boolean => {\n const [a = 0, b = 0] = parts;\n if (a === 0 || a === 10 || a === 127 || a >= 224) {\n return true;\n }\n switch (a) {\n case 100: {\n return b >= 64 && b <= 127;\n }\n case 169: {\n return b === 254;\n }\n case 172: {\n return b >= 16 && b <= 31;\n }\n case 192: {\n return b === 168;\n }\n case 198: {\n return b === 18 || b === 19;\n }\n default: {\n return false;\n }\n }\n};\n\nconst isHextet = (value: number): boolean =>\n Number.isInteger(value) && value >= 0 && value <= 65_535;\n\nconst parseIpv4MappedIpv6 = (host: string): number[] | undefined => {\n const normalized = host.replace(/^\\[/u, \"\").replace(/\\]$/u, \"\").toLowerCase();\n if (!normalized.startsWith(\"::ffff:\")) {\n return;\n }\n\n const suffix = normalized.slice(\"::ffff:\".length);\n const dotted = parseIpv4(suffix);\n if (dotted) {\n return dotted;\n }\n\n const [high, low, extra] = suffix.split(\":\");\n if (!(high && low) || extra !== undefined) {\n return;\n }\n const highBits = Number.parseInt(high, 16);\n const lowBits = Number.parseInt(low, 16);\n if (!(isHextet(highBits) && isHextet(lowBits))) {\n return;\n }\n return [\n Math.floor(highBits / 256),\n highBits % 256,\n Math.floor(lowBits / 256),\n lowBits % 256,\n ];\n};\n\nconst isPrivateIpv6 = (host: string): boolean => {\n const normalized = host.replace(/^\\[/u, \"\").replace(/\\]$/u, \"\").toLowerCase();\n // Only an IPv6 literal can be a private address, and one always contains a\n // colon — guard so a bare DNS name like `fc2.com` is not mistaken for `fc00::/7`.\n if (!normalized.includes(\":\")) {\n return false;\n }\n if (normalized === \"::\" || normalized === \"::1\") {\n return true;\n }\n return (\n normalized.startsWith(\"fc\") ||\n normalized.startsWith(\"fd\") ||\n normalized.startsWith(\"fe80:\")\n );\n};\n\n/** Whether a hostname points at localhost or a private network. */\nconst isPrivateHost = (host: string): boolean => {\n if (\n host === \"localhost\" ||\n host.endsWith(\".localhost\") ||\n host.endsWith(\".local\")\n ) {\n return true;\n }\n const ipv4 = parseIpv4(host) ?? parseIpv4MappedIpv6(host);\n return (ipv4 ? isPrivateIpv4(ipv4) : false) || isPrivateIpv6(host);\n};\n\nconst isRedirectStatus = (status: number): boolean =>\n status >= 300 && status < 400;\n\nconst assertSafeWebhookUrl: WebhookUrlValidator = (url) => {\n if (url.protocol !== \"https:\") {\n throw new BatchworkError(\"batchwork: webhookUrl must use https.\");\n }\n if (url.username || url.password) {\n throw new BatchworkError(\n \"batchwork: webhookUrl must not include credentials.\"\n );\n }\n\n if (isPrivateHost(url.hostname.toLowerCase())) {\n throw new BatchworkError(\n \"batchwork: webhookUrl must not target localhost or private networks.\"\n );\n }\n};\n\nconst validateWebhookUrl = async (\n rawUrl: string,\n validator: WebhookUrlValidator\n): Promise<string> => {\n let url: URL;\n try {\n url = new URL(rawUrl);\n } catch (error) {\n throw new BatchworkError(\"batchwork: webhookUrl must be a valid URL.\", {\n cause: error,\n });\n }\n await validator(url);\n return url.toString();\n};\n\n/** The default completion sink: POST a signed webhook to the tracked URL. */\nconst createWebhookSink =\n (validator: WebhookUrlValidator): CompletionSink =>\n async (record, snapshot) => {\n if (!record.webhookUrl) {\n throw new BatchworkError(\n \"batchwork: tracked batch has no webhookUrl to deliver to.\"\n );\n }\n const webhookUrl = await validateWebhookUrl(record.webhookUrl, validator);\n const body = JSON.stringify(toEvent(record.provider, snapshot));\n const headers: Record<string, string> = {\n \"content-type\": \"application/json\",\n };\n if (record.webhookSecret) {\n Object.assign(\n headers,\n await signWebhook(\n record.webhookSecret,\n record.id,\n body,\n Date.now() / 1000\n )\n );\n }\n const response = await fetch(webhookUrl, {\n body,\n headers,\n method: \"POST\",\n redirect: \"manual\",\n });\n if (isRedirectStatus(response.status)) {\n throw new BatchworkError(\n `batchwork: webhook delivery to ${webhookUrl} redirected (${response.status}).`\n );\n }\n if (!response.ok) {\n throw new BatchworkError(\n `batchwork: webhook delivery to ${webhookUrl} failed (${response.status}).`\n );\n }\n };\n\n/**\n * Create a managed poller: register submitted batches with `track`, then run\n * `tick` on a schedule (cron) to poll open batches and deliver one unified,\n * signed webhook per batch when it finishes. For OpenAI, mount\n * `openaiWebhookHandler` to skip polling and react to native webhooks instead.\n */\nexport const createBatchPoller = (options: BatchPollerOptions): BatchPoller => {\n const resolveCredentials = (provider: BatchProvider): ProviderCredentials => {\n if (typeof options.credentials === \"function\") {\n return options.credentials(provider);\n }\n return options.credentials ?? {};\n };\n\n const webhookUrlValidator =\n options.validateWebhookUrl ?? assertSafeWebhookUrl;\n const sink = options.onComplete ?? createWebhookSink(webhookUrlValidator);\n\n const deliver = async (\n record: TrackedBatch,\n snapshot: BatchSnapshot\n ): Promise<void> => {\n // Run the side effect before marking delivered: if it throws, the record\n // stays pending and is retried on the next tick (at-least-once delivery).\n await sink(record, snapshot);\n await options.store.set({\n ...record,\n deliveredAt: new Date().toISOString(),\n status: snapshot.status,\n });\n };\n\n const track = async (\n target: TrackTarget,\n opts: TrackOptions\n ): Promise<TrackedBatch> => {\n const webhookUrl =\n opts.webhookUrl && !options.onComplete\n ? await validateWebhookUrl(opts.webhookUrl, webhookUrlValidator)\n : opts.webhookUrl;\n const record: TrackedBatch = {\n createdAt: new Date().toISOString(),\n id: target.id,\n provider: target.provider,\n status: target.status ?? \"in_progress\",\n webhookSecret: opts.secret,\n webhookUrl,\n };\n await options.store.set(record);\n return record;\n };\n\n const process = async (\n record: TrackedBatch,\n delivered: string[]\n ): Promise<void> => {\n const adapter = getAdapter(record.provider);\n const snapshot = await adapter.retrieve(\n record.id,\n resolveCredentials(record.provider)\n );\n if (isTerminalStatus(snapshot.status)) {\n await deliver(record, snapshot);\n delivered.push(record.id);\n } else if (snapshot.status !== record.status) {\n await options.store.set({ ...record, status: snapshot.status });\n }\n };\n\n const tick = async (): Promise<TickResult> => {\n const pending = await options.store.list({ delivered: false });\n const delivered: string[] = [];\n const failed: { id: string; error: string }[] = [];\n for (const record of pending) {\n // oxlint-disable-next-line no-await-in-loop -- batches are polled serially\n // to avoid hammering provider rate limits; deliver before the next.\n try {\n // oxlint-disable-next-line no-await-in-loop, react-doctor/async-await-in-loop -- see above.\n await process(record, delivered);\n } catch (error) {\n // Without an `onError` handler, preserve the propagate-the-throw\n // behavior; with one, report and continue so a single failing batch\n // can't starve the rest of the queue. Either way the record stays\n // pending (it was never marked delivered) and retries next tick.\n if (!options.onError) {\n throw error;\n }\n options.onError(record, error);\n failed.push({\n error: error instanceof Error ? error.message : String(error),\n id: record.id,\n });\n }\n }\n return failed.length > 0\n ? { checked: pending.length, delivered, failed }\n : { checked: pending.length, delivered };\n };\n\n const openaiWebhookHandler =\n (config: OpenAIWebhookOptions) =>\n async (request: Request): Promise<Response> => {\n let verified: { body: string };\n try {\n verified = await verifyWebhook(request, config.signingSecret);\n } catch {\n return new Response(\"invalid signature\", { status: 400 });\n }\n\n const payload = JSON.parse(verified.body) as {\n type?: string;\n data?: { id?: string };\n };\n if (!payload.type?.startsWith(\"batch.\")) {\n return new Response(\"ignored\", { status: 202 });\n }\n const id = payload.data?.id;\n if (!id) {\n return new Response(\"missing batch id\", { status: 400 });\n }\n const record = await options.store.get(id);\n if (!record || record.deliveredAt) {\n return new Response(\"ok\", { status: 200 });\n }\n const snapshot = await getAdapter(\"openai\").retrieve(\n id,\n resolveCredentials(\"openai\")\n );\n if (isTerminalStatus(snapshot.status)) {\n await deliver(record, snapshot);\n }\n return new Response(\"ok\", { status: 200 });\n };\n\n return { deliver, openaiWebhookHandler, tick, track };\n};\n",
8
- "import type { BatchStore, TrackedBatch } from \"./types\";\n\n/** An in-memory `BatchStore`. Suitable for development and single-process use. */\nexport const createMemoryStore = (): BatchStore => {\n const records = new Map<string, TrackedBatch>();\n\n return {\n delete: (id) => {\n records.delete(id);\n return Promise.resolve();\n },\n get: (id) => Promise.resolve(records.get(id) ?? null),\n list: (filter) => {\n const all = [...records.values()];\n if (filter?.delivered === undefined) {\n return Promise.resolve(all);\n }\n const { delivered } = filter;\n return Promise.resolve(\n all.filter((record) => (record.deliveredAt !== undefined) === delivered)\n );\n },\n set: (record) => {\n records.set(record.id, record);\n return Promise.resolve();\n },\n };\n};\n"
9
- ],
10
- "mappings": "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",
11
- "debugId": "F1B4BA11C9A6AE3364756E2164756E21",
12
- "names": []
13
- }