ai-functions 2.1.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (286) hide show
  1. package/.turbo/turbo-build.log +1 -4
  2. package/CHANGELOG.md +68 -1
  3. package/README.md +397 -157
  4. package/dist/ai-promise.d.ts +50 -3
  5. package/dist/ai-promise.d.ts.map +1 -1
  6. package/dist/ai-promise.js +410 -51
  7. package/dist/ai-promise.js.map +1 -1
  8. package/dist/ai-schemas.d.ts +56 -0
  9. package/dist/ai-schemas.d.ts.map +1 -0
  10. package/dist/ai-schemas.js +53 -0
  11. package/dist/ai-schemas.js.map +1 -0
  12. package/dist/ai.d.ts +16 -242
  13. package/dist/ai.d.ts.map +1 -1
  14. package/dist/ai.js +54 -837
  15. package/dist/ai.js.map +1 -1
  16. package/dist/batch/anthropic.d.ts +6 -4
  17. package/dist/batch/anthropic.d.ts.map +1 -1
  18. package/dist/batch/anthropic.js +83 -145
  19. package/dist/batch/anthropic.js.map +1 -1
  20. package/dist/batch/bedrock.d.ts +8 -30
  21. package/dist/batch/bedrock.d.ts.map +1 -1
  22. package/dist/batch/bedrock.js +155 -338
  23. package/dist/batch/bedrock.js.map +1 -1
  24. package/dist/batch/cloudflare.d.ts +8 -20
  25. package/dist/batch/cloudflare.d.ts.map +1 -1
  26. package/dist/batch/cloudflare.js +68 -189
  27. package/dist/batch/cloudflare.js.map +1 -1
  28. package/dist/batch/google.d.ts +6 -20
  29. package/dist/batch/google.d.ts.map +1 -1
  30. package/dist/batch/google.js +70 -238
  31. package/dist/batch/google.js.map +1 -1
  32. package/dist/batch/index.d.ts +4 -1
  33. package/dist/batch/index.d.ts.map +1 -1
  34. package/dist/batch/index.js +4 -1
  35. package/dist/batch/index.js.map +1 -1
  36. package/dist/batch/memory.d.ts +1 -1
  37. package/dist/batch/memory.d.ts.map +1 -1
  38. package/dist/batch/memory.js +14 -10
  39. package/dist/batch/memory.js.map +1 -1
  40. package/dist/batch/openai.d.ts +11 -14
  41. package/dist/batch/openai.d.ts.map +1 -1
  42. package/dist/batch/openai.js +52 -156
  43. package/dist/batch/openai.js.map +1 -1
  44. package/dist/batch/provider.d.ts +111 -0
  45. package/dist/batch/provider.d.ts.map +1 -0
  46. package/dist/batch/provider.js +233 -0
  47. package/dist/batch/provider.js.map +1 -0
  48. package/dist/batch-map.d.ts.map +1 -1
  49. package/dist/batch-map.js +23 -17
  50. package/dist/batch-map.js.map +1 -1
  51. package/dist/batch-queue.d.ts +65 -0
  52. package/dist/batch-queue.d.ts.map +1 -1
  53. package/dist/batch-queue.js +169 -14
  54. package/dist/batch-queue.js.map +1 -1
  55. package/dist/budget.d.ts +272 -0
  56. package/dist/budget.d.ts.map +1 -0
  57. package/dist/budget.js +513 -0
  58. package/dist/budget.js.map +1 -0
  59. package/dist/cache.d.ts +295 -0
  60. package/dist/cache.d.ts.map +1 -0
  61. package/dist/cache.js +433 -0
  62. package/dist/cache.js.map +1 -0
  63. package/dist/context.d.ts +42 -8
  64. package/dist/context.d.ts.map +1 -1
  65. package/dist/context.js +64 -62
  66. package/dist/context.js.map +1 -1
  67. package/dist/digital-objects-registry.d.ts +229 -0
  68. package/dist/digital-objects-registry.d.ts.map +1 -0
  69. package/dist/digital-objects-registry.js +617 -0
  70. package/dist/digital-objects-registry.js.map +1 -0
  71. package/dist/embeddings.d.ts +2 -2
  72. package/dist/embeddings.d.ts.map +1 -1
  73. package/dist/errors.d.ts +22 -0
  74. package/dist/errors.d.ts.map +1 -0
  75. package/dist/errors.js +35 -0
  76. package/dist/errors.js.map +1 -0
  77. package/dist/eval/runner.d.ts +10 -1
  78. package/dist/eval/runner.d.ts.map +1 -1
  79. package/dist/eval/runner.js +41 -35
  80. package/dist/eval/runner.js.map +1 -1
  81. package/dist/eval-log/in-memory.d.ts +34 -0
  82. package/dist/eval-log/in-memory.d.ts.map +1 -0
  83. package/dist/eval-log/in-memory.js +84 -0
  84. package/dist/eval-log/in-memory.js.map +1 -0
  85. package/dist/eval-log/index.d.ts +29 -0
  86. package/dist/eval-log/index.d.ts.map +1 -0
  87. package/dist/eval-log/index.js +39 -0
  88. package/dist/eval-log/index.js.map +1 -0
  89. package/dist/eval-log/types.d.ts +101 -0
  90. package/dist/eval-log/types.d.ts.map +1 -0
  91. package/dist/eval-log/types.js +16 -0
  92. package/dist/eval-log/types.js.map +1 -0
  93. package/dist/function-registry.d.ts +116 -0
  94. package/dist/function-registry.d.ts.map +1 -0
  95. package/dist/function-registry.js +546 -0
  96. package/dist/function-registry.js.map +1 -0
  97. package/dist/generate.d.ts +9 -3
  98. package/dist/generate.d.ts.map +1 -1
  99. package/dist/generate.js +18 -22
  100. package/dist/generate.js.map +1 -1
  101. package/dist/index.d.ts +35 -20
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js +89 -42
  104. package/dist/index.js.map +1 -1
  105. package/dist/logger.d.ts +118 -0
  106. package/dist/logger.d.ts.map +1 -0
  107. package/dist/logger.js +187 -0
  108. package/dist/logger.js.map +1 -0
  109. package/dist/middleware/budget.d.ts +84 -0
  110. package/dist/middleware/budget.d.ts.map +1 -0
  111. package/dist/middleware/budget.js +110 -0
  112. package/dist/middleware/budget.js.map +1 -0
  113. package/dist/middleware/cache.d.ts +103 -0
  114. package/dist/middleware/cache.d.ts.map +1 -0
  115. package/dist/middleware/cache.js +228 -0
  116. package/dist/middleware/cache.js.map +1 -0
  117. package/dist/middleware/embed-cache.d.ts +99 -0
  118. package/dist/middleware/embed-cache.d.ts.map +1 -0
  119. package/dist/middleware/embed-cache.js +128 -0
  120. package/dist/middleware/embed-cache.js.map +1 -0
  121. package/dist/middleware/index.d.ts +11 -0
  122. package/dist/middleware/index.d.ts.map +1 -0
  123. package/dist/middleware/index.js +11 -0
  124. package/dist/middleware/index.js.map +1 -0
  125. package/dist/middleware/trace.d.ts +103 -0
  126. package/dist/middleware/trace.d.ts.map +1 -0
  127. package/dist/middleware/trace.js +176 -0
  128. package/dist/middleware/trace.js.map +1 -0
  129. package/dist/primitives.d.ts +120 -1
  130. package/dist/primitives.d.ts.map +1 -1
  131. package/dist/primitives.js +398 -26
  132. package/dist/primitives.js.map +1 -1
  133. package/dist/retry.d.ts +368 -0
  134. package/dist/retry.d.ts.map +1 -0
  135. package/dist/retry.js +646 -0
  136. package/dist/retry.js.map +1 -0
  137. package/dist/schema.d.ts.map +1 -1
  138. package/dist/schema.js +2 -10
  139. package/dist/schema.js.map +1 -1
  140. package/dist/telemetry.d.ts +128 -0
  141. package/dist/telemetry.d.ts.map +1 -0
  142. package/dist/telemetry.js +285 -0
  143. package/dist/telemetry.js.map +1 -0
  144. package/dist/template.d.ts.map +1 -1
  145. package/dist/template.js +6 -1
  146. package/dist/template.js.map +1 -1
  147. package/dist/tool-orchestration.d.ts +453 -0
  148. package/dist/tool-orchestration.d.ts.map +1 -0
  149. package/dist/tool-orchestration.js +763 -0
  150. package/dist/tool-orchestration.js.map +1 -0
  151. package/dist/type-guards.d.ts +28 -0
  152. package/dist/type-guards.d.ts.map +1 -0
  153. package/dist/type-guards.js +29 -0
  154. package/dist/type-guards.js.map +1 -0
  155. package/dist/types.d.ts +135 -17
  156. package/dist/types.d.ts.map +1 -1
  157. package/dist/types.js +36 -1
  158. package/dist/types.js.map +1 -1
  159. package/dist/wrap-for-v3.d.ts +80 -0
  160. package/dist/wrap-for-v3.d.ts.map +1 -0
  161. package/dist/wrap-for-v3.js +89 -0
  162. package/dist/wrap-for-v3.js.map +1 -0
  163. package/examples/00-quickstart.ts +232 -0
  164. package/examples/01-rag-chatbot.ts +212 -0
  165. package/examples/02-multi-agent-research.ts +290 -0
  166. package/examples/03-email-classification.ts +379 -0
  167. package/examples/04-content-moderation.ts +400 -0
  168. package/examples/05-document-extraction.ts +455 -0
  169. package/examples/06-streaming-chat-nextjs.ts +437 -0
  170. package/examples/07-cloudflare-worker.ts +483 -0
  171. package/examples/08-batch-processing.ts +491 -0
  172. package/examples/09-budget-constrained.ts +527 -0
  173. package/examples/10-tool-orchestration.ts +565 -0
  174. package/examples/11-retry-resilience.ts +403 -0
  175. package/examples/12-caching-strategies.ts +422 -0
  176. package/examples/README.md +145 -0
  177. package/package.json +10 -6
  178. package/src/ai-promise.ts +528 -99
  179. package/src/ai-schemas.ts +122 -0
  180. package/src/ai.ts +69 -1153
  181. package/src/batch/anthropic.ts +96 -161
  182. package/src/batch/bedrock.ts +203 -454
  183. package/src/batch/cloudflare.ts +99 -282
  184. package/src/batch/google.ts +91 -297
  185. package/src/batch/index.ts +4 -1
  186. package/src/batch/memory.ts +15 -10
  187. package/src/batch/openai.ts +65 -193
  188. package/src/batch/provider.ts +336 -0
  189. package/src/batch-map.ts +29 -24
  190. package/src/batch-queue.ts +200 -11
  191. package/src/budget.ts +740 -0
  192. package/src/cache.ts +681 -0
  193. package/src/context.ts +122 -76
  194. package/src/digital-objects-registry.ts +750 -0
  195. package/src/errors.ts +37 -0
  196. package/src/eval/runner.ts +63 -38
  197. package/src/eval-log/in-memory.ts +90 -0
  198. package/src/eval-log/index.ts +46 -0
  199. package/src/eval-log/types.ts +110 -0
  200. package/src/function-registry.ts +671 -0
  201. package/src/generate.ts +33 -33
  202. package/src/index.ts +325 -49
  203. package/src/logger.ts +232 -0
  204. package/src/middleware/budget.ts +171 -0
  205. package/src/middleware/cache.ts +299 -0
  206. package/src/middleware/embed-cache.ts +195 -0
  207. package/src/middleware/index.ts +23 -0
  208. package/src/middleware/trace.ts +248 -0
  209. package/src/primitives.ts +589 -62
  210. package/src/retry.ts +902 -0
  211. package/src/schema.ts +8 -17
  212. package/src/telemetry.ts +403 -0
  213. package/src/template.ts +8 -4
  214. package/src/tool-orchestration.ts +1173 -0
  215. package/src/type-guards.ts +31 -0
  216. package/src/types.ts +164 -25
  217. package/src/wrap-for-v3.ts +105 -0
  218. package/test/ai-promise.test.ts +1080 -0
  219. package/test/ai-proxy.test.ts +1 -1
  220. package/test/backward-compat.test.ts +147 -0
  221. package/test/batch-autosubmit-errors.test.ts +610 -0
  222. package/test/batch-blog-posts.test.ts +87 -129
  223. package/test/budget-tracking.test.ts +800 -0
  224. package/test/cache.test.ts +712 -0
  225. package/test/context-isolation.test.ts +687 -0
  226. package/test/core-functions.test.ts +183 -579
  227. package/test/decide.test.ts +154 -322
  228. package/test/define.test.ts +211 -8
  229. package/test/digital-objects-registry.test.ts +760 -0
  230. package/test/embedding-cache-middleware.test.ts +140 -0
  231. package/test/evals/deterministic.eval.test.ts +376 -0
  232. package/test/generate-core.test.ts +140 -229
  233. package/test/implicit-batch.test.ts +22 -65
  234. package/test/json-parse-error-handling.test.ts +463 -0
  235. package/test/retry-policy-integration.test.ts +117 -0
  236. package/test/retry.test.ts +1016 -0
  237. package/test/schema.test.ts +55 -19
  238. package/test/streaming.test.ts +316 -0
  239. package/test/template.test.ts +1164 -0
  240. package/test/tool-orchestration.test.ts +1040 -0
  241. package/test/wrap-for-v3.test.ts +612 -0
  242. package/vitest.config.js +6 -0
  243. package/vitest.config.ts +20 -0
  244. package/dist/rpc/auth.d.ts +0 -69
  245. package/dist/rpc/auth.d.ts.map +0 -1
  246. package/dist/rpc/auth.js +0 -136
  247. package/dist/rpc/auth.js.map +0 -1
  248. package/dist/rpc/client.d.ts +0 -62
  249. package/dist/rpc/client.d.ts.map +0 -1
  250. package/dist/rpc/client.js +0 -103
  251. package/dist/rpc/client.js.map +0 -1
  252. package/dist/rpc/deferred.d.ts +0 -60
  253. package/dist/rpc/deferred.d.ts.map +0 -1
  254. package/dist/rpc/deferred.js +0 -96
  255. package/dist/rpc/deferred.js.map +0 -1
  256. package/dist/rpc/index.d.ts +0 -22
  257. package/dist/rpc/index.d.ts.map +0 -1
  258. package/dist/rpc/index.js +0 -38
  259. package/dist/rpc/index.js.map +0 -1
  260. package/dist/rpc/local.d.ts +0 -42
  261. package/dist/rpc/local.d.ts.map +0 -1
  262. package/dist/rpc/local.js +0 -50
  263. package/dist/rpc/local.js.map +0 -1
  264. package/dist/rpc/server.d.ts +0 -165
  265. package/dist/rpc/server.d.ts.map +0 -1
  266. package/dist/rpc/server.js +0 -405
  267. package/dist/rpc/server.js.map +0 -1
  268. package/dist/rpc/session.d.ts +0 -32
  269. package/dist/rpc/session.d.ts.map +0 -1
  270. package/dist/rpc/session.js +0 -43
  271. package/dist/rpc/session.js.map +0 -1
  272. package/dist/rpc/transport.d.ts +0 -306
  273. package/dist/rpc/transport.d.ts.map +0 -1
  274. package/dist/rpc/transport.js +0 -731
  275. package/dist/rpc/transport.js.map +0 -1
  276. package/src/batch/anthropic.js +0 -256
  277. package/src/batch/bedrock.js +0 -584
  278. package/src/batch/cloudflare.js +0 -287
  279. package/src/batch/google.js +0 -359
  280. package/src/batch/index.js +0 -30
  281. package/src/batch/memory.js +0 -187
  282. package/src/batch/openai.js +0 -402
  283. package/src/eval/index.js +0 -7
  284. package/src/eval/models.js +0 -119
  285. package/src/eval/runner.js +0 -147
  286. package/test/schema.test.js +0 -96
@@ -26,6 +26,8 @@
26
26
 
27
27
  import type { FunctionOptions } from './template.js'
28
28
  import type { SimpleSchema } from './schema.js'
29
+ import { getLogger } from './logger.js'
30
+ import { policyFor, type BatchTier } from 'language-models'
29
31
 
30
32
  // ============================================================================
31
33
  // Types
@@ -197,6 +199,11 @@ export interface BatchQueueOptions {
197
199
  // BatchQueue Implementation
198
200
  // ============================================================================
199
201
 
202
+ /**
203
+ * Event handler type for BatchQueue events
204
+ */
205
+ export type BatchEventHandler<T = unknown> = (data: T) => void
206
+
200
207
  /**
201
208
  * BatchQueue collects AI operations for deferred batch execution
202
209
  */
@@ -207,6 +214,11 @@ export class BatchQueue {
207
214
  private submitted = false
208
215
  private job: BatchJob | null = null
209
216
 
217
+ // Error handling properties
218
+ private _autoSubmitPromise: Promise<void> | null = null
219
+ private _submissionError: Error | null = null
220
+ private _eventHandlers: Map<string, Set<BatchEventHandler>> = new Map()
221
+
210
222
  constructor(options: BatchQueueOptions = {}) {
211
223
  this.options = {
212
224
  provider: 'openai',
@@ -216,6 +228,95 @@ export class BatchQueue {
216
228
  }
217
229
  }
218
230
 
231
+ /**
232
+ * Subscribe to batch events
233
+ * @param event - Event name ('error', 'partial-failure', 'complete')
234
+ * @param handler - Event handler function
235
+ */
236
+ on<T = unknown>(event: string, handler: BatchEventHandler<T>): void {
237
+ if (!this._eventHandlers.has(event)) {
238
+ this._eventHandlers.set(event, new Set())
239
+ }
240
+ this._eventHandlers.get(event)!.add(handler as BatchEventHandler)
241
+ }
242
+
243
+ /**
244
+ * Unsubscribe from batch events
245
+ */
246
+ off(event: string, handler: BatchEventHandler): void {
247
+ this._eventHandlers.get(event)?.delete(handler)
248
+ }
249
+
250
+ /**
251
+ * Emit an event to all subscribed handlers
252
+ */
253
+ private emit<T>(event: string, data: T): void {
254
+ this._eventHandlers.get(event)?.forEach((handler) => handler(data))
255
+ }
256
+
257
+ /**
258
+ * Get the auto-submit promise (if auto-submit was triggered)
259
+ */
260
+ get autoSubmitPromise(): Promise<void> | undefined {
261
+ return this._autoSubmitPromise ?? undefined
262
+ }
263
+
264
+ /**
265
+ * Get the last submission error (if any)
266
+ */
267
+ get submissionError(): Error | undefined {
268
+ return this._submissionError ?? undefined
269
+ }
270
+
271
+ /**
272
+ * Check if there was a submission error
273
+ */
274
+ get hasSubmissionError(): boolean {
275
+ return this._submissionError !== null
276
+ }
277
+
278
+ /**
279
+ * Await auto-submit completion or failure
280
+ * Returns a promise that resolves when auto-submit completes or rejects on error
281
+ */
282
+ awaitAutoSubmit(): Promise<void> {
283
+ if (!this._autoSubmitPromise) {
284
+ return Promise.resolve()
285
+ }
286
+ return this._autoSubmitPromise
287
+ }
288
+
289
+ /**
290
+ * Get items that failed during batch processing
291
+ */
292
+ getFailedItems(): BatchItem[] {
293
+ return this.items.filter((item) => item.status === 'failed')
294
+ }
295
+
296
+ /**
297
+ * Retry a failed submission
298
+ * Only available after a failed auto-submit
299
+ */
300
+ async retry(): Promise<BatchSubmitResult> {
301
+ if (!this._submissionError) {
302
+ throw new Error('No failed submission to retry')
303
+ }
304
+
305
+ // Reset error state and submitted flag
306
+ this._submissionError = null
307
+ this.submitted = false
308
+
309
+ // Reset item statuses
310
+ for (const item of this.items) {
311
+ if (item.status === 'failed') {
312
+ item.status = 'pending'
313
+ delete item.error
314
+ }
315
+ }
316
+
317
+ return this.submit()
318
+ }
319
+
219
320
  /**
220
321
  * Add an item to the batch queue
221
322
  * Returns a placeholder that will be resolved after batch completion
@@ -236,9 +337,9 @@ export class BatchQueue {
236
337
  const item: BatchItem<T> = {
237
338
  id: options?.customId || `item_${++this.idCounter}`,
238
339
  prompt,
239
- schema: options?.schema,
240
- options: options?.options,
241
- metadata: options?.metadata,
340
+ ...(options?.schema !== undefined && { schema: options.schema }),
341
+ ...(options?.options !== undefined && { options: options.options }),
342
+ ...(options?.metadata !== undefined && { metadata: options.metadata }),
242
343
  status: 'pending',
243
344
  }
244
345
 
@@ -246,8 +347,50 @@ export class BatchQueue {
246
347
 
247
348
  // Auto-submit if we hit the limit
248
349
  if (this.options.autoSubmit && this.items.length >= (this.options.maxItems || 50000)) {
249
- // Fire and forget - user can await the completion promise
250
- this.submit().catch(console.error)
350
+ // Create a trackable promise for auto-submit
351
+ this._autoSubmitPromise = this.submit()
352
+ .then(() => {
353
+ // Success - promise is resolved
354
+ })
355
+ .catch((error: Error) => {
356
+ // Store error and update item statuses
357
+ this._submissionError = error
358
+ this.submitted = false // Reset to allow retry
359
+
360
+ // Update all items to failed status
361
+ for (const item of this.items) {
362
+ if (item.status === 'pending') {
363
+ item.status = 'failed'
364
+ item.error = error.message
365
+ }
366
+ }
367
+
368
+ // Create a synthetic failed job to store error info
369
+ const errorWithMeta = error as Error & {
370
+ status?: number
371
+ headers?: Record<string, string>
372
+ }
373
+ this.job = {
374
+ id: `failed_${Date.now()}`,
375
+ provider: this.options.provider || 'openai',
376
+ status: 'failed',
377
+ totalItems: this.items.length,
378
+ completedItems: 0,
379
+ failedItems: this.items.length,
380
+ createdAt: new Date(),
381
+ // Add rate limit retry info if available
382
+ ...(errorWithMeta.headers?.['retry-after'] && {
383
+ retryAfter: parseInt(errorWithMeta.headers['retry-after'], 10),
384
+ }),
385
+ } as BatchJob & { retryAfter?: number }
386
+
387
+ // Emit error event
388
+ this.emit('error', error)
389
+
390
+ // Log error and re-throw
391
+ getLogger().error('Batch auto-submit failed:', error)
392
+ throw error
393
+ })
251
394
  }
252
395
 
253
396
  return item
@@ -302,16 +445,35 @@ export class BatchQueue {
302
445
  const result = await adapter.submit(this.items, this.options)
303
446
  this.job = result.job
304
447
 
305
- // When completion resolves, update item statuses
448
+ // When completion resolves, update item statuses and check for partial failures
306
449
  result.completion.then((results) => {
450
+ const failedResults: BatchResult[] = []
451
+
307
452
  for (const r of results) {
308
453
  const item = this.items.find((i) => i.id === r.id)
309
454
  if (item) {
310
455
  item.status = r.status
311
- item.result = r.result
312
- item.error = r.error
456
+ if (r.result !== undefined) item.result = r.result
457
+ if (r.error !== undefined) item.error = r.error
458
+
459
+ if (r.status === 'failed') {
460
+ failedResults.push(r)
461
+ }
313
462
  }
314
463
  }
464
+
465
+ // Emit partial-failure event if some items failed
466
+ if (failedResults.length > 0 && failedResults.length < results.length) {
467
+ this.emit('partial-failure', failedResults)
468
+ }
469
+
470
+ // Emit error event if there were any failures
471
+ if (failedResults.length > 0) {
472
+ this.emit('error', new Error(`${failedResults.length} items failed in batch`))
473
+ }
474
+
475
+ // Emit complete event
476
+ this.emit('complete', results)
315
477
  })
316
478
 
317
479
  return result
@@ -496,6 +658,33 @@ export function hasFlexAdapter(provider: BatchProvider): boolean {
496
658
  return flexAdapters[provider] !== null
497
659
  }
498
660
 
661
+ // ============================================================================
662
+ // Tier eligibility (per-model policy)
663
+ // ============================================================================
664
+
665
+ /**
666
+ * List the batch tiers a model is eligible for.
667
+ *
668
+ * Reads `ModelPolicy.batchTier` from `language-models` — this is the per-model
669
+ * policy data, distinct from the runtime adapter registration above.
670
+ *
671
+ * @example
672
+ * ```ts
673
+ * tiersForModel('sonnet') // ['immediate', 'batch']
674
+ * tiersForModel('gpt-4o') // ['immediate', 'flex', 'batch']
675
+ * ```
676
+ */
677
+ export function tiersForModel(alias: string): BatchTier[] {
678
+ return policyFor(alias).batchTier
679
+ }
680
+
681
+ /**
682
+ * Check whether a model is eligible for a given tier.
683
+ */
684
+ export function modelSupportsTier(alias: string, tier: BatchTier): boolean {
685
+ return tiersForModel(alias).includes(tier)
686
+ }
687
+
499
688
  // ============================================================================
500
689
  // Factory Functions
501
690
  // ============================================================================
@@ -590,8 +779,8 @@ export function deferToBatch<T>(
590
779
  options?: FunctionOptions & { customId?: string }
591
780
  ): BatchItem<T> {
592
781
  return batch.add<T>(prompt, {
593
- schema,
594
- options,
595
- customId: options?.customId,
782
+ ...(schema !== undefined && { schema }),
783
+ ...(options !== undefined && { options }),
784
+ ...(options?.customId !== undefined && { customId: options.customId }),
596
785
  })
597
786
  }