ai-functions 0.2.19 → 0.4.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.
Files changed (227) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/.turbo/turbo-test.log +105 -0
  3. package/README.md +232 -37
  4. package/TODO.md +138 -0
  5. package/dist/ai-promise.d.ts +219 -0
  6. package/dist/ai-promise.d.ts.map +1 -0
  7. package/dist/ai-promise.js +610 -0
  8. package/dist/ai-promise.js.map +1 -0
  9. package/dist/ai.d.ts +285 -0
  10. package/dist/ai.d.ts.map +1 -0
  11. package/dist/ai.js +842 -0
  12. package/dist/ai.js.map +1 -0
  13. package/dist/batch/anthropic.d.ts +23 -0
  14. package/dist/batch/anthropic.d.ts.map +1 -0
  15. package/dist/batch/anthropic.js +257 -0
  16. package/dist/batch/anthropic.js.map +1 -0
  17. package/dist/batch/bedrock.d.ts +64 -0
  18. package/dist/batch/bedrock.d.ts.map +1 -0
  19. package/dist/batch/bedrock.js +586 -0
  20. package/dist/batch/bedrock.js.map +1 -0
  21. package/dist/batch/cloudflare.d.ts +37 -0
  22. package/dist/batch/cloudflare.d.ts.map +1 -0
  23. package/dist/batch/cloudflare.js +289 -0
  24. package/dist/batch/cloudflare.js.map +1 -0
  25. package/dist/batch/google.d.ts +41 -0
  26. package/dist/batch/google.d.ts.map +1 -0
  27. package/dist/batch/google.js +360 -0
  28. package/dist/batch/google.js.map +1 -0
  29. package/dist/batch/index.d.ts +31 -0
  30. package/dist/batch/index.d.ts.map +1 -0
  31. package/dist/batch/index.js +31 -0
  32. package/dist/batch/index.js.map +1 -0
  33. package/dist/batch/memory.d.ts +44 -0
  34. package/dist/batch/memory.d.ts.map +1 -0
  35. package/dist/batch/memory.js +188 -0
  36. package/dist/batch/memory.js.map +1 -0
  37. package/dist/batch/openai.d.ts +37 -0
  38. package/dist/batch/openai.d.ts.map +1 -0
  39. package/dist/batch/openai.js +403 -0
  40. package/dist/batch/openai.js.map +1 -0
  41. package/dist/batch-map.d.ts +125 -0
  42. package/dist/batch-map.d.ts.map +1 -0
  43. package/dist/batch-map.js +406 -0
  44. package/dist/batch-map.js.map +1 -0
  45. package/dist/batch-queue.d.ts +273 -0
  46. package/dist/batch-queue.d.ts.map +1 -0
  47. package/dist/batch-queue.js +271 -0
  48. package/dist/batch-queue.js.map +1 -0
  49. package/dist/context.d.ts +133 -0
  50. package/dist/context.d.ts.map +1 -0
  51. package/dist/context.js +267 -0
  52. package/dist/context.js.map +1 -0
  53. package/dist/embeddings.d.ts +123 -0
  54. package/dist/embeddings.d.ts.map +1 -0
  55. package/dist/embeddings.js +170 -0
  56. package/dist/embeddings.js.map +1 -0
  57. package/dist/eval/index.d.ts +8 -0
  58. package/dist/eval/index.d.ts.map +1 -0
  59. package/dist/eval/index.js +8 -0
  60. package/dist/eval/index.js.map +1 -0
  61. package/dist/eval/models.d.ts +66 -0
  62. package/dist/eval/models.d.ts.map +1 -0
  63. package/dist/eval/models.js +120 -0
  64. package/dist/eval/models.js.map +1 -0
  65. package/dist/eval/runner.d.ts +64 -0
  66. package/dist/eval/runner.d.ts.map +1 -0
  67. package/dist/eval/runner.js +148 -0
  68. package/dist/eval/runner.js.map +1 -0
  69. package/dist/generate.d.ts +168 -0
  70. package/dist/generate.d.ts.map +1 -0
  71. package/dist/generate.js +174 -0
  72. package/dist/generate.js.map +1 -0
  73. package/dist/index.d.ts +30 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +54 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/primitives.d.ts +292 -0
  78. package/dist/primitives.d.ts.map +1 -0
  79. package/dist/primitives.js +471 -0
  80. package/dist/primitives.js.map +1 -0
  81. package/dist/providers/cloudflare.d.ts +9 -0
  82. package/dist/providers/cloudflare.d.ts.map +1 -0
  83. package/dist/providers/cloudflare.js +9 -0
  84. package/dist/providers/cloudflare.js.map +1 -0
  85. package/dist/providers/index.d.ts +9 -0
  86. package/dist/providers/index.d.ts.map +1 -0
  87. package/dist/providers/index.js +9 -0
  88. package/dist/providers/index.js.map +1 -0
  89. package/dist/schema.d.ts +54 -0
  90. package/dist/schema.d.ts.map +1 -0
  91. package/dist/schema.js +109 -0
  92. package/dist/schema.js.map +1 -0
  93. package/dist/template.d.ts +73 -0
  94. package/dist/template.d.ts.map +1 -0
  95. package/dist/template.js +129 -0
  96. package/dist/template.js.map +1 -0
  97. package/dist/types.d.ts +481 -0
  98. package/dist/types.d.ts.map +1 -0
  99. package/dist/types.js +5 -0
  100. package/dist/types.js.map +1 -0
  101. package/evalite.config.ts +19 -0
  102. package/evals/README.md +212 -0
  103. package/evals/classification.eval.ts +108 -0
  104. package/evals/marketing.eval.ts +370 -0
  105. package/evals/math.eval.ts +94 -0
  106. package/evals/run-evals.ts +166 -0
  107. package/evals/structured-output.eval.ts +143 -0
  108. package/evals/writing.eval.ts +117 -0
  109. package/examples/batch-blog-posts.ts +160 -0
  110. package/package.json +59 -43
  111. package/src/ai-promise.ts +784 -0
  112. package/src/ai.ts +1183 -0
  113. package/src/batch/anthropic.ts +375 -0
  114. package/src/batch/bedrock.ts +801 -0
  115. package/src/batch/cloudflare.ts +421 -0
  116. package/src/batch/google.ts +491 -0
  117. package/src/batch/index.ts +31 -0
  118. package/src/batch/memory.ts +253 -0
  119. package/src/batch/openai.ts +557 -0
  120. package/src/batch-map.ts +534 -0
  121. package/src/batch-queue.ts +493 -0
  122. package/src/context.ts +332 -0
  123. package/src/embeddings.ts +244 -0
  124. package/src/eval/index.ts +8 -0
  125. package/src/eval/models.ts +158 -0
  126. package/src/eval/runner.ts +217 -0
  127. package/src/generate.ts +245 -0
  128. package/src/index.ts +154 -0
  129. package/src/primitives.ts +612 -0
  130. package/src/providers/cloudflare.ts +15 -0
  131. package/src/providers/index.ts +14 -0
  132. package/src/schema.ts +147 -0
  133. package/src/template.ts +209 -0
  134. package/src/types.ts +540 -0
  135. package/test/README.md +105 -0
  136. package/test/ai-proxy.test.ts +192 -0
  137. package/test/async-iterators.test.ts +327 -0
  138. package/test/batch-background.test.ts +482 -0
  139. package/test/batch-blog-posts.test.ts +387 -0
  140. package/test/blog-generation.test.ts +510 -0
  141. package/test/browse-read.test.ts +611 -0
  142. package/test/core-functions.test.ts +694 -0
  143. package/test/decide.test.ts +393 -0
  144. package/test/define.test.ts +274 -0
  145. package/test/e2e-bedrock-manual.ts +163 -0
  146. package/test/e2e-bedrock.test.ts +191 -0
  147. package/test/e2e-flex-gateway.ts +157 -0
  148. package/test/e2e-flex-manual.ts +183 -0
  149. package/test/e2e-flex.test.ts +209 -0
  150. package/test/e2e-google-manual.ts +178 -0
  151. package/test/e2e-google.test.ts +216 -0
  152. package/test/embeddings.test.ts +284 -0
  153. package/test/evals/define-function.eval.test.ts +379 -0
  154. package/test/evals/primitives.eval.test.ts +384 -0
  155. package/test/function-types.test.ts +492 -0
  156. package/test/generate-core.test.ts +319 -0
  157. package/test/generate.test.ts +163 -0
  158. package/test/implicit-batch.test.ts +422 -0
  159. package/test/schema.test.ts +109 -0
  160. package/test/tagged-templates.test.ts +302 -0
  161. package/tsconfig.json +8 -6
  162. package/vitest.config.ts +42 -0
  163. package/LICENSE +0 -21
  164. package/db/cache.ts +0 -6
  165. package/db/mongo.ts +0 -75
  166. package/dist/mjs/db/cache.d.ts +0 -1
  167. package/dist/mjs/db/cache.js +0 -5
  168. package/dist/mjs/db/mongo.d.ts +0 -31
  169. package/dist/mjs/db/mongo.js +0 -48
  170. package/dist/mjs/examples/data.d.ts +0 -1105
  171. package/dist/mjs/examples/data.js +0 -1105
  172. package/dist/mjs/functions/ai.d.ts +0 -20
  173. package/dist/mjs/functions/ai.js +0 -83
  174. package/dist/mjs/functions/ai.test.d.ts +0 -1
  175. package/dist/mjs/functions/ai.test.js +0 -29
  176. package/dist/mjs/functions/gpt.d.ts +0 -4
  177. package/dist/mjs/functions/gpt.js +0 -10
  178. package/dist/mjs/functions/list.d.ts +0 -7
  179. package/dist/mjs/functions/list.js +0 -72
  180. package/dist/mjs/index.d.ts +0 -3
  181. package/dist/mjs/index.js +0 -3
  182. package/dist/mjs/queue/kafka.d.ts +0 -0
  183. package/dist/mjs/queue/kafka.js +0 -1
  184. package/dist/mjs/queue/memory.d.ts +0 -0
  185. package/dist/mjs/queue/memory.js +0 -1
  186. package/dist/mjs/queue/mongo.d.ts +0 -30
  187. package/dist/mjs/queue/mongo.js +0 -42
  188. package/dist/mjs/streams/kafka.d.ts +0 -0
  189. package/dist/mjs/streams/kafka.js +0 -1
  190. package/dist/mjs/streams/memory.d.ts +0 -0
  191. package/dist/mjs/streams/memory.js +0 -1
  192. package/dist/mjs/streams/mongo.d.ts +0 -0
  193. package/dist/mjs/streams/mongo.js +0 -1
  194. package/dist/mjs/streams/types.d.ts +0 -0
  195. package/dist/mjs/streams/types.js +0 -1
  196. package/dist/mjs/types.d.ts +0 -11
  197. package/dist/mjs/types.js +0 -1
  198. package/dist/mjs/utils/completion.d.ts +0 -9
  199. package/dist/mjs/utils/completion.js +0 -20
  200. package/dist/mjs/utils/schema.d.ts +0 -10
  201. package/dist/mjs/utils/schema.js +0 -72
  202. package/dist/mjs/utils/schema.test.d.ts +0 -1
  203. package/dist/mjs/utils/schema.test.js +0 -60
  204. package/dist/mjs/utils/state.d.ts +0 -1
  205. package/dist/mjs/utils/state.js +0 -19
  206. package/examples/data.ts +0 -1105
  207. package/fixup +0 -11
  208. package/functions/ai.test.ts +0 -41
  209. package/functions/ai.ts +0 -115
  210. package/functions/gpt.ts +0 -12
  211. package/functions/list.ts +0 -84
  212. package/index.ts +0 -3
  213. package/queue/kafka.ts +0 -0
  214. package/queue/memory.ts +0 -0
  215. package/queue/mongo.ts +0 -88
  216. package/streams/kafka.ts +0 -0
  217. package/streams/memory.ts +0 -0
  218. package/streams/mongo.ts +0 -0
  219. package/streams/types.ts +0 -0
  220. package/tsconfig-backup.json +0 -105
  221. package/tsconfig-base.json +0 -26
  222. package/tsconfig-cjs.json +0 -8
  223. package/types.ts +0 -12
  224. package/utils/completion.ts +0 -28
  225. package/utils/schema.test.ts +0 -69
  226. package/utils/schema.ts +0 -74
  227. package/utils/state.ts +0 -23
@@ -0,0 +1,493 @@
1
+ /**
2
+ * BatchQueue - Deferred execution queue for batch processing
3
+ *
4
+ * Collects AI operations and submits them to provider batch APIs
5
+ * for cost-effective processing (typically 50% discount, 24hr turnaround).
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * // Create a batch queue
10
+ * const batch = createBatch({ provider: 'openai' })
11
+ *
12
+ * // Add items to the batch (these are deferred, not executed)
13
+ * const titles = await list`10 blog post titles about startups`
14
+ * const posts = titles.map(title => batch.add(write`blog post about ${title}`))
15
+ *
16
+ * // Submit the batch - returns job info
17
+ * const job = await batch.submit()
18
+ * console.log(job.id) // batch_abc123
19
+ *
20
+ * // Poll for results or use webhook
21
+ * const results = await batch.wait()
22
+ * ```
23
+ *
24
+ * @packageDocumentation
25
+ */
26
+
27
+ import type { FunctionOptions } from './template.js'
28
+ import type { SimpleSchema } from './schema.js'
29
+
30
+ // ============================================================================
31
+ // Types
32
+ // ============================================================================
33
+
34
+ /** Batch processing mode */
35
+ export type BatchMode = 'sync' | 'async' | 'background'
36
+
37
+ /** Supported batch providers */
38
+ export type BatchProvider = 'openai' | 'anthropic' | 'google' | 'bedrock' | 'cloudflare'
39
+
40
+ /** Status of a batch job */
41
+ export type BatchStatus =
42
+ | 'pending'
43
+ | 'validating'
44
+ | 'in_progress'
45
+ | 'finalizing'
46
+ | 'completed'
47
+ | 'failed'
48
+ | 'expired'
49
+ | 'cancelling'
50
+ | 'cancelled'
51
+
52
+ /** Individual item in a batch */
53
+ export interface BatchItem<T = unknown> {
54
+ /** Unique ID for this item */
55
+ id: string
56
+ /** The prompt to process */
57
+ prompt: string
58
+ /** Schema for structured output */
59
+ schema?: SimpleSchema
60
+ /** Generation options */
61
+ options?: FunctionOptions
62
+ /** Custom metadata */
63
+ metadata?: Record<string, unknown>
64
+ /** Resolved value (after completion) */
65
+ result?: T
66
+ /** Error if failed */
67
+ error?: string
68
+ /** Status of this item */
69
+ status: 'pending' | 'completed' | 'failed'
70
+ }
71
+
72
+ /** Batch job information */
73
+ export interface BatchJob {
74
+ /** Unique batch ID */
75
+ id: string
76
+ /** Provider this batch was submitted to */
77
+ provider: BatchProvider
78
+ /** Current status */
79
+ status: BatchStatus
80
+ /** Number of items in the batch */
81
+ totalItems: number
82
+ /** Number of completed items */
83
+ completedItems: number
84
+ /** Number of failed items */
85
+ failedItems: number
86
+ /** When the batch was created */
87
+ createdAt: Date
88
+ /** When the batch started processing */
89
+ startedAt?: Date
90
+ /** When the batch completed */
91
+ completedAt?: Date
92
+ /** Expected completion time */
93
+ expiresAt?: Date
94
+ /** Webhook URL for completion notification */
95
+ webhookUrl?: string
96
+ /** Input file ID (for OpenAI) */
97
+ inputFileId?: string
98
+ /** Output file ID (for OpenAI) */
99
+ outputFileId?: string
100
+ /** Error file ID (for OpenAI) */
101
+ errorFileId?: string
102
+ }
103
+
104
+ /** Result of a batch submission */
105
+ export interface BatchSubmitResult {
106
+ job: BatchJob
107
+ /** Promise that resolves when batch is complete */
108
+ completion: Promise<BatchResult[]>
109
+ }
110
+
111
+ /** Result of a single item in the batch */
112
+ export interface BatchResult<T = unknown> {
113
+ /** Item ID */
114
+ id: string
115
+ /** Custom ID if provided */
116
+ customId?: string
117
+ /** Status */
118
+ status: 'completed' | 'failed'
119
+ /** The result (if successful) */
120
+ result?: T
121
+ /** Error message (if failed) */
122
+ error?: string
123
+ /** Token usage */
124
+ usage?: {
125
+ promptTokens: number
126
+ completionTokens: number
127
+ totalTokens: number
128
+ }
129
+ }
130
+
131
+ /** Options for creating a batch queue */
132
+ export interface BatchQueueOptions {
133
+ /** Provider to use for batch processing */
134
+ provider?: BatchProvider
135
+ /** Model to use */
136
+ model?: string
137
+ /** Webhook URL for completion notification */
138
+ webhookUrl?: string
139
+ /** Custom metadata for the batch */
140
+ metadata?: Record<string, unknown>
141
+ /** Maximum items per batch (provider-specific limits) */
142
+ maxItems?: number
143
+ /** Auto-submit when queue reaches maxItems */
144
+ autoSubmit?: boolean
145
+ }
146
+
147
+ // ============================================================================
148
+ // BatchQueue Implementation
149
+ // ============================================================================
150
+
151
+ /**
152
+ * BatchQueue collects AI operations for deferred batch execution
153
+ */
154
+ export class BatchQueue {
155
+ private items: BatchItem[] = []
156
+ private options: BatchQueueOptions
157
+ private idCounter = 0
158
+ private submitted = false
159
+ private job: BatchJob | null = null
160
+
161
+ constructor(options: BatchQueueOptions = {}) {
162
+ this.options = {
163
+ provider: 'openai',
164
+ maxItems: 50000, // OpenAI's limit
165
+ autoSubmit: false,
166
+ ...options,
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Add an item to the batch queue
172
+ * Returns a placeholder that will be resolved after batch completion
173
+ */
174
+ add<T = unknown>(
175
+ prompt: string,
176
+ options?: {
177
+ schema?: SimpleSchema
178
+ options?: FunctionOptions
179
+ customId?: string
180
+ metadata?: Record<string, unknown>
181
+ }
182
+ ): BatchItem<T> {
183
+ if (this.submitted) {
184
+ throw new Error('Cannot add items to a submitted batch')
185
+ }
186
+
187
+ const item: BatchItem<T> = {
188
+ id: options?.customId || `item_${++this.idCounter}`,
189
+ prompt,
190
+ schema: options?.schema,
191
+ options: options?.options,
192
+ metadata: options?.metadata,
193
+ status: 'pending',
194
+ }
195
+
196
+ this.items.push(item as BatchItem)
197
+
198
+ // Auto-submit if we hit the limit
199
+ if (this.options.autoSubmit && this.items.length >= (this.options.maxItems || 50000)) {
200
+ // Fire and forget - user can await the completion promise
201
+ this.submit().catch(console.error)
202
+ }
203
+
204
+ return item
205
+ }
206
+
207
+ /**
208
+ * Get all items in the queue
209
+ */
210
+ getItems(): BatchItem[] {
211
+ return [...this.items]
212
+ }
213
+
214
+ /**
215
+ * Get the number of items in the queue
216
+ */
217
+ get size(): number {
218
+ return this.items.length
219
+ }
220
+
221
+ /**
222
+ * Check if the batch has been submitted
223
+ */
224
+ get isSubmitted(): boolean {
225
+ return this.submitted
226
+ }
227
+
228
+ /**
229
+ * Get the batch job info (after submission)
230
+ */
231
+ getJob(): BatchJob | null {
232
+ return this.job
233
+ }
234
+
235
+ /**
236
+ * Submit the batch to the provider
237
+ */
238
+ async submit(): Promise<BatchSubmitResult> {
239
+ if (this.submitted) {
240
+ throw new Error('Batch has already been submitted')
241
+ }
242
+
243
+ if (this.items.length === 0) {
244
+ throw new Error('Cannot submit empty batch')
245
+ }
246
+
247
+ this.submitted = true
248
+
249
+ // Get the appropriate batch adapter
250
+ const adapter = getBatchAdapter(this.options.provider || 'openai')
251
+
252
+ // Submit the batch
253
+ const result = await adapter.submit(this.items, this.options)
254
+ this.job = result.job
255
+
256
+ // When completion resolves, update item statuses
257
+ result.completion.then((results) => {
258
+ for (const r of results) {
259
+ const item = this.items.find((i) => i.id === r.id)
260
+ if (item) {
261
+ item.status = r.status
262
+ item.result = r.result
263
+ item.error = r.error
264
+ }
265
+ }
266
+ })
267
+
268
+ return result
269
+ }
270
+
271
+ /**
272
+ * Cancel the batch (if supported by provider)
273
+ */
274
+ async cancel(): Promise<void> {
275
+ if (!this.job) {
276
+ throw new Error('Batch has not been submitted')
277
+ }
278
+
279
+ const adapter = getBatchAdapter(this.options.provider || 'openai')
280
+ await adapter.cancel(this.job.id)
281
+ this.job.status = 'cancelling'
282
+ }
283
+
284
+ /**
285
+ * Get the current status of the batch
286
+ */
287
+ async getStatus(): Promise<BatchJob> {
288
+ if (!this.job) {
289
+ throw new Error('Batch has not been submitted')
290
+ }
291
+
292
+ const adapter = getBatchAdapter(this.options.provider || 'openai')
293
+ this.job = await adapter.getStatus(this.job.id)
294
+ return this.job
295
+ }
296
+
297
+ /**
298
+ * Wait for the batch to complete and return results
299
+ */
300
+ async wait(pollInterval = 5000): Promise<BatchResult[]> {
301
+ if (!this.job) {
302
+ throw new Error('Batch has not been submitted')
303
+ }
304
+
305
+ const adapter = getBatchAdapter(this.options.provider || 'openai')
306
+ return adapter.waitForCompletion(this.job.id, pollInterval)
307
+ }
308
+ }
309
+
310
+ // ============================================================================
311
+ // Batch Adapters
312
+ // ============================================================================
313
+
314
+ /**
315
+ * Interface for provider-specific batch implementations
316
+ */
317
+ export interface BatchAdapter {
318
+ /** Submit a batch to the provider */
319
+ submit(items: BatchItem[], options: BatchQueueOptions): Promise<BatchSubmitResult>
320
+ /** Get the status of a batch */
321
+ getStatus(batchId: string): Promise<BatchJob>
322
+ /** Cancel a batch */
323
+ cancel(batchId: string): Promise<void>
324
+ /** Get results of a completed batch */
325
+ getResults(batchId: string): Promise<BatchResult[]>
326
+ /** Wait for batch completion */
327
+ waitForCompletion(batchId: string, pollInterval?: number): Promise<BatchResult[]>
328
+ }
329
+
330
+ /**
331
+ * Interface for flex processing (faster than batch, ~50% discount)
332
+ * Available for OpenAI and AWS Bedrock
333
+ */
334
+ export interface FlexAdapter {
335
+ /**
336
+ * Submit items for flex processing
337
+ * Flex is faster than batch (minutes vs hours) but has same discount
338
+ *
339
+ * @param items - Items to process
340
+ * @param options - Processing options
341
+ * @returns Results (resolves when all items complete)
342
+ */
343
+ submitFlex(items: BatchItem[], options: { model?: string }): Promise<BatchResult[]>
344
+ }
345
+
346
+ // Adapter registry
347
+ const adapters: Record<BatchProvider, BatchAdapter | null> = {
348
+ openai: null,
349
+ anthropic: null,
350
+ google: null,
351
+ bedrock: null,
352
+ cloudflare: null,
353
+ }
354
+
355
+ // Flex adapter registry (only OpenAI and Bedrock support flex)
356
+ const flexAdapters: Record<BatchProvider, FlexAdapter | null> = {
357
+ openai: null,
358
+ anthropic: null,
359
+ google: null,
360
+ bedrock: null,
361
+ cloudflare: null,
362
+ }
363
+
364
+ /**
365
+ * Register a batch adapter for a provider
366
+ */
367
+ export function registerBatchAdapter(provider: BatchProvider, adapter: BatchAdapter): void {
368
+ adapters[provider] = adapter
369
+ }
370
+
371
+ /**
372
+ * Register a flex adapter for a provider
373
+ */
374
+ export function registerFlexAdapter(provider: BatchProvider, adapter: FlexAdapter): void {
375
+ flexAdapters[provider] = adapter
376
+ }
377
+
378
+ /**
379
+ * Get the batch adapter for a provider
380
+ */
381
+ export function getBatchAdapter(provider: BatchProvider): BatchAdapter {
382
+ const adapter = adapters[provider]
383
+ if (!adapter) {
384
+ throw new Error(
385
+ `No batch adapter registered for provider: ${provider}. ` +
386
+ `Import the adapter: import 'ai-functions/batch/${provider}'`
387
+ )
388
+ }
389
+ return adapter
390
+ }
391
+
392
+ /**
393
+ * Get the flex adapter for a provider
394
+ */
395
+ export function getFlexAdapter(provider: BatchProvider): FlexAdapter {
396
+ const adapter = flexAdapters[provider]
397
+ if (!adapter) {
398
+ throw new Error(
399
+ `No flex adapter registered for provider: ${provider}. ` +
400
+ `Flex processing is only available for OpenAI and AWS Bedrock.`
401
+ )
402
+ }
403
+ return adapter
404
+ }
405
+
406
+ /**
407
+ * Check if flex is available for a provider
408
+ */
409
+ export function hasFlexAdapter(provider: BatchProvider): boolean {
410
+ return flexAdapters[provider] !== null
411
+ }
412
+
413
+ // ============================================================================
414
+ // Factory Functions
415
+ // ============================================================================
416
+
417
+ /**
418
+ * Create a new batch queue
419
+ *
420
+ * @example
421
+ * ```ts
422
+ * const batch = createBatch({ provider: 'openai' })
423
+ * batch.add('Write a poem about cats')
424
+ * batch.add('Write a poem about dogs')
425
+ * const { job } = await batch.submit()
426
+ * const results = await batch.wait()
427
+ * ```
428
+ */
429
+ export function createBatch(options?: BatchQueueOptions): BatchQueue {
430
+ return new BatchQueue(options)
431
+ }
432
+
433
+ /**
434
+ * Execute operations in batch mode
435
+ *
436
+ * @example
437
+ * ```ts
438
+ * const results = await withBatch(async (batch) => {
439
+ * const titles = ['TypeScript', 'React', 'Next.js']
440
+ * return titles.map(title => batch.add(`Write a blog post about ${title}`))
441
+ * })
442
+ * ```
443
+ */
444
+ export async function withBatch<T>(
445
+ fn: (batch: BatchQueue) => T[] | Promise<T[]>,
446
+ options?: BatchQueueOptions
447
+ ): Promise<BatchResult<T>[]> {
448
+ const batch = createBatch(options)
449
+ const items = await fn(batch)
450
+ if (batch.size === 0) {
451
+ return []
452
+ }
453
+ const { completion } = await batch.submit()
454
+ return completion as Promise<BatchResult<T>[]>
455
+ }
456
+
457
+ // ============================================================================
458
+ // Deferred Execution Support
459
+ // ============================================================================
460
+
461
+ /** Symbol to mark an AIPromise as batched/deferred */
462
+ export const BATCH_MODE_SYMBOL = Symbol.for('ai-batch-mode')
463
+
464
+ /** Options for deferred execution */
465
+ export interface DeferredOptions extends FunctionOptions {
466
+ /** Batch queue to add to */
467
+ batch?: BatchQueue
468
+ /** Custom ID for this item in the batch */
469
+ customId?: string
470
+ }
471
+
472
+ /**
473
+ * Check if we're in batch mode
474
+ */
475
+ export function isBatchMode(options?: DeferredOptions): boolean {
476
+ return !!options?.batch
477
+ }
478
+
479
+ /**
480
+ * Add an operation to the batch queue instead of executing immediately
481
+ */
482
+ export function deferToBatch<T>(
483
+ batch: BatchQueue,
484
+ prompt: string,
485
+ schema: SimpleSchema | undefined,
486
+ options?: FunctionOptions & { customId?: string }
487
+ ): BatchItem<T> {
488
+ return batch.add<T>(prompt, {
489
+ schema,
490
+ options,
491
+ customId: options?.customId,
492
+ })
493
+ }