UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

89 lines • 4.73 kB
import type { ObserverStore } from '../../observe/store.ts'; import type { NamespaceStore } from '../mount/namespace/store.ts'; import type { JobStore } from '../../shell/job_table/store.ts'; export type WorkspaceFields = Record<string, unknown>; export interface WorkspaceStateStoreOverrides { namespace?: WorkspaceStateStore; observer?: WorkspaceStateStore; workspace?: WorkspaceStateStore; jobs?: WorkspaceStateStore; } /** * Provider for a workspace's whole control-plane state. * * One store, five planes, each scoped by workspace id: namespace nodes * (symlinks, attribute overlays), observer events (command history), * the session table (mount grants, cwd, env), the workspace metadata * record (discovery: which sessions exist, which is the default), and * the jobs (each session's job list and each job's console). Handing two * processes the same store config plus a workspace id gives them the same * workspace state, which is the seam that lets a kernel tier bind a * session-bound mountpoint created by another daemon, and lets any of * them list, wait on and kill a session's jobs. * * The node table and the session table are two NamespaceStores, the * observer keeps its ObserverStore and the jobs their JobStore; this * provider only unifies their construction, connection, and key scoping. Per-group overrides * redirect a plane group to a different provider (e.g. large observer * logs elsewhere while everything else stays on Redis). Sessions and * metadata form one inseparable group: the default-session pointer in * the metadata must never live on a different server than the session * table it points into. */ export declare abstract class WorkspaceStateStore { private readonly namespaceOverride; private readonly observerOverride; private readonly workspaceOverride; private readonly jobsOverride; constructor(overrides?: WorkspaceStateStoreOverrides); /** The namespace plane (nodes) for one workspace. */ namespace(workspaceId: string): NamespaceStore; /** The observer plane (history events) for one workspace. */ observer(workspaceId: string): ObserverStore; /** The session table for one workspace. */ sessions(workspaceId: string): NamespaceStore; /** The job plane (job lists, consoles, leases) for one workspace. */ jobs(workspaceId: string): JobStore; /** Read one workspace's metadata record; null when never written. */ loadMeta(workspaceId: string): Promise<WorkspaceFields | null>; /** * Write the metadata record iff its stored generation matches. * * Same optimistic-concurrency contract as NamespaceStore.casSet: a * missing record (and a legacy record without the field) counts as * generation 0, so create-if-absent is `expectedGeneration = 0`. * Resolves true when the write landed, false on conflict. */ casSetMeta(workspaceId: string, fields: WorkspaceFields, expectedGeneration: number): Promise<boolean>; /** * CAS-write `fields` over the stored record, retrying on conflict. * * Ours-wins content (snapshot restore semantics): each attempt * merges `fields` over the stored record, preserves the stored * `created_at`, bumps the generation, and retries when another * writer got there first. Resolves with the record as written. */ replaceMeta(workspaceId: string, fields: WorkspaceFields): Promise<WorkspaceFields>; /** * Delete everything this store holds for one workspace. * * Deleting a workspace calls this and closing one does not, which is * what lets a daemon's workspaces survive a restart. Each plane is * cleared through its own store, then every provider involved forgets * the workspace (its metadata record and the handles it keeps for the * id), so a workspace created later under the same id starts empty. */ drop(workspaceId: string): Promise<void>; /** Release connections held by this provider and its overrides. */ close(): Promise<void>; private overrides; protected abstract makeNamespace(workspaceId: string): NamespaceStore; protected abstract makeObserver(workspaceId: string): ObserverStore; protected abstract makeSessions(workspaceId: string): NamespaceStore; protected abstract makeJobs(workspaceId: string): JobStore; protected abstract readMeta(workspaceId: string): Promise<WorkspaceFields | null>; protected abstract casWriteMeta(workspaceId: string, fields: WorkspaceFields, expectedGeneration: number): Promise<boolean>; protected abstract forgetSelf(workspaceId: string): Promise<void>; protected abstract closeSelf(): Promise<void>; } //# sourceMappingURL=base.d.ts.map