import type { NexusAIConfig } from '../types/config.js'; import type { BatchConfig, BatchJobRef, BatchJobResult, BatchJobState, BatchProvider, BatchSubmitRequest } from '../types/batch.js'; import type { DurableOperationHandle, OperationRunnerConfig } from '../types/operations.js'; /** What the batch manager runs on. */ export interface BatchManagerRuntime { /** Persists the operation record, so a submitted batch survives a restart. */ operations?: OperationRunnerConfig; /** Model registry used to price results. */ config?: Pick; } /** * Provider batch tiers behind one operation handle. * * This is the discounted asynchronous path that local `runBatch()` concurrency cannot reach: both * OpenAI and Anthropic charge roughly half for work submitted this way, in exchange for a * completion window measured in hours. The manager submits, polls with backoff, collects results, * and prices them. * * Every call after `submit` takes only a `BatchJobRef`, which is JSON-serializable. That is what * makes `resume()` possible: a worker that did not submit the batch, in a process that has since * restarted, can still collect it. */ export declare class BatchManager { private readonly config; private readonly runtime; private readonly providers; private readonly runner; constructor(config?: BatchConfig, runtime?: BatchManagerRuntime); /** * Registers a provider under a name. Throws for a provider without `submit` and `poll`. Returns * the manager, for chaining. */ registerBatchProvider(name: string, provider: BatchProvider): this; /** Whether a provider is registered. */ hasBatchProvider(name: string): boolean; /** Every registered provider's name. */ listBatchProviders(): string[]; /** * Submits a batch and returns a handle that settles when the provider finishes. * * The handle resolves after the provider completes, which for the discounted tier can be hours * away. Read `handle.id` and persist it, or stream `handle.events()`, rather than blocking a * request on `handle.result()`. */ submit(request: BatchSubmitRequest): Promise>; /** * Attaches to a batch this process did not submit. * * The provider is the source of truth, so a restarted worker only needs the ref it persisted. */ resume(ref: BatchJobRef, options?: Partial): Promise; /** Current provider-side state, without waiting. */ status(ref: BatchJobRef): Promise; /** Cancels a batch. Throws when the provider cannot cancel. */ cancel(ref: BatchJobRef): Promise; private collect; /** * Prices a finished batch at the provider's discounted rate. * * Each item is priced against the model it actually ran on rather than the batch default, because * a mixed batch is legal and averaging would misreport every row. The discount is applied last, * so a provider that changes it only changes one number. */ private price; private resolveProvider; private validate; }