/** * Shared Inference Scheduler (3.0.0 foundation). * * Central admission authority for physical inference slots. It controls WHEN a * model request may run; it is NOT the model provider and never reimplements * provider protocol/stream handling. Scheduling/admission is kept separate from * provider protocol handling. * * Cross-process coordination: the scheduler mutates a durable per-resource * ledger (see InferenceQueueStore). Two OS processes sharing the same ledger * cannot each believe they own all physical slots. Slot acquisition is a * temporary fenced lease; it is never durable agent ownership. * * Determinism: with the same queued requests, priorities, dependency metadata, * controlled clock, and capacity, admission order is deterministic * (effective-priority desc, then enqueue time, then request id). */ import type { InferenceQueueStore } from "./inference-queue.js"; import type { AcquireInferenceOutcome, AdmittedInference, EnqueueInferenceOutcome, InferenceAdmissionStatus, InferencePriority, InferenceRecoveryReport, InferenceRequestDependency, InferenceRequestLease, ReleaseInferenceOutcome, RenewInferenceOutcome, SharedInferenceResource, SharedInferenceSchedulerStatus } from "./types.js"; export interface SharedInferenceSchedulerOptions { store: InferenceQueueStore; now?: () => number; sleep?: (ms: number) => Promise; /** Lease lifetime for an admitted slot (default 10 minutes). */ leaseDurationMs?: number; leaseIdFactory?: () => string; requestIdFactory?: () => string; /** Stable control-plane owner identity (default host+UUID, never PID). */ ownerId?: string; /** Poll cadence while waiting for cross-process admission. */ waitPollMs?: number; /** Optional queue-wait deadline (0 = unbounded). */ queueWaitTimeoutMs?: number; /** Deterministic priority policy knobs. */ interactiveBoost?: number; verificationBoost?: number; dependencyWeight?: number; dependencyCap?: number; agingIntervalMs?: number; agingWeight?: number; } export declare function isInferenceRequestLeaseActive(lease: InferenceRequestLease, now: number): boolean; export declare class SharedInferenceScheduler { private readonly _store; private readonly _resources; private readonly _now; private readonly _sleep; private readonly _leaseDurationMs; private readonly _leaseIdFactory; private readonly _requestIdFactory; private readonly _ownerId; private readonly _waitPollMs; private readonly _queueWaitTimeoutMs; private readonly _interactiveBoost; private readonly _verificationBoost; private readonly _dependencyWeight; private readonly _dependencyCap; private readonly _agingIntervalMs; private readonly _agingWeight; private _avoidableIdleSinceMs?; private _avoidableIdleTotalMs; constructor(options: SharedInferenceSchedulerOptions); get ownerId(): string; get store(): InferenceQueueStore; /** Register (or refresh) a shared resource and ensure its ledger exists. */ registerResource(resource: SharedInferenceResource): Promise; /** Resolve the shared resource a model targets, or undefined (non-shared path). */ resourceFor(model: { provider: string; id: string; }): SharedInferenceResource | undefined; listResources(): SharedInferenceResource[]; /** * Non-blocking enqueue (or immediate admit) of an inference request. This is * the single authority for turning a request into either an admitted lease or * a durable queued entry; `acquire` composes it with a bounded wait loop. * The admission service uses `enqueue` + `admissionStatus` to expose a * request/wait protocol to remote clients without duplicating the algorithm. */ enqueue(input: { logicalAgentId: string; resource: SharedInferenceResource; model: { provider: string; id: string; }; inferenceRequestId?: string; missionId?: string; assignmentId?: string; executionId?: string; priority?: InferencePriority; dependency?: InferenceRequestDependency; estimatedInputTokens?: number; maxOutputTokens?: number; }): Promise; /** Pollable admission state for a request owned by this scheduler instance. */ admissionStatus(inferenceRequestId: string, options?: { ownerId?: string; }): Promise; /** Renew an active lease (keeps long-running generations from expiring mid-stream). */ renew(admitted: AdmittedInference, options?: { now?: number; }): Promise; /** * Request an inference slot. If capacity is available the request is admitted * immediately; otherwise it is durably queued and the caller waits (bounded * poll, abortable, queue-timeout aware) until admission, cancellation, or * timeout. */ acquire(input: { logicalAgentId: string; resource: SharedInferenceResource; model: { provider: string; id: string; }; inferenceRequestId?: string; missionId?: string; assignmentId?: string; executionId?: string; priority?: InferencePriority; dependency?: InferenceRequestDependency; estimatedInputTokens?: number; maxOutputTokens?: number; signal?: AbortSignal; queueWaitTimeoutMs?: number; }): Promise; private _buildRequest; private _enqueueOrAdmit; /** Release an admitted slot and promote queued work. Fenced by lease identity. */ release(admitted: AdmittedInference, outcome: { state: "COMPLETED" | "FAILED" | "CANCELLED" | "INTERRUPTED"; usage?: { input?: number; output?: number; }; errorMessage?: string; }): Promise; /** Cancel a queued (or locally-owned running) request. Queued requests never consume a slot afterward. */ cancel(inferenceRequestId: string): Promise<{ status: "cancelled" | "not_found" | "running"; inferenceRequestId: string; }>; /** Reconcile expired RUNNING leases after a scheduler/process restart. Never fabricates completion. */ recover(options?: { now?: number; }): Promise; status(): Promise; /** Deterministic avoidable-idle observation: queue non-empty + free slot + no admission. */ private _observeAvoidableIdle; private _toAdmitted; private _admittedFrom; private _admitInto; /** Sort the queue deterministically and promote up to free capacity. */ private _promoteQueued; /** Keep running[i].lease.slot === i. */ private _normalizeSlots; private _sortedQueue; private _compare; private _breakdown; private _requestStatus; } //# sourceMappingURL=scheduler.d.ts.map