import { type ProjectContext } from '@zhixuan92/multi-model-agent-core'; export type ReserveError = 'project_cap' | 'invalid_cwd' | 'missing_cwd' | 'cwd_not_dir' | 'forbidden_cwd'; type ReserveResult = { ok: true; projectContext: ProjectContext; created: boolean; } | { ok: false; error: ReserveError; message: string; }; interface ProjectRegistryOptions { cap: number; /** * `server.limits.maxContextBlocksPerProject`, applied to each project's store. * * Without this the store fell back to its own hardcoded default, which happened to equal the * CONFIG default — so the setting looked honoured while only one of the two registration paths * respected it. `POST /context-blocks` checks the configured cap and returns 409; the runtime * registers each read-route's terminal block directly (`execution-runtime.ts`), bypassing that * check entirely. Lowering the setting to bound memory therefore did not bound it. */ contextBlocksPerProject?: number; onProjectCreated?: (cwd: string) => void; /** Returns true when the project at this canonical cwd has in-flight work and * must not be evicted. Wired to `ExecutionRegistry.countActive(cwd) > 0` in production. */ isBusy?: (canonicalCwd: string) => boolean; } export declare class ProjectRegistry { private readonly map; private readonly cap; private readonly contextBlocksPerProject?; private readonly onProjectCreated?; private readonly isBusy?; constructor(options: ProjectRegistryOptions); /** Evict the least-recently-active project that is safe to drop — no in-flight * work (`isBusy` false) and no retained context blocks (a caller may still * reference them via contextBlockIds). Returns true if one was evicted. This * keeps the cap from becoming a permanent lockout once `cap` distinct cwds * have been seen over the server's lifetime. */ private evictIdleLRU; /** * Synchronous lookup-or-create with cap enforcement. * * "Reserve" means a slot against `cap` — validating the cwd, evicting an idle project when full, * and creating the context. It used to ALSO bump a `pendingReservations` counter, paired with a * `cancelReservation` that decremented it. Nothing ever read that counter: eviction consults * `isBusy` (wired to live task counts), `/status` reports `activeTasks` from the execution * registry, and the field's own comment said it was not a reliable busy signal. Two production * call sites existed solely to decrement state no decision consulted. */ reserveProject(cwd: string): ReserveResult; /** Look up a project by its canonical cwd. */ get(canonicalCwd: string): ProjectContext | undefined; get size(): number; entries(): IterableIterator<[string, ProjectContext]>; } export {}; //# sourceMappingURL=project-registry.d.ts.map