import type { AddUserProject, AddUserProjectResult, AgentState, AppendBackgroundJobProgress, AppendResearchAgentMessage, AppendResearchAgentMessageResult, AppendResearchTurn, AppendResearchTurnResult, BackgroundJob, BackgroundJobCursor, BackgroundJobDetail, BackgroundJobPage, CancelBackgroundJob, ChannelAgent, ChannelArchiveInput, ChannelArchiveResult, ChannelDecisionCount, ChannelPage, ChannelRecord, ChannelScanCursor, ChannelScanPage, ClaimBackgroundJobs, CommitChannel, CommitResult, CompareNavigationResult, ConfirmResearchWorkspace, ConfirmResearchWorkspaceResult, CreateChannel, CreateResearchWorkspace, CreateResearchWorkspaceResult, CreateWebSession, EnqueueBackgroundJob, FailBackgroundJob, Lease, LinkResearchTurnJob, LinkResearchTurnJobResult, PauseBackgroundJob, PublishChannelDescription, PublishChannelDescriptionResult, PublishInitialResearchReport, PublishInitialResearchReportResult, PutUser, RecordNavigationVisit, RenameChannel, RenameResult, RenewBackgroundJob, ReplaceChannel, RequeueBackgroundJob, ResearchTerminalRecovery, ResearchTurn, ResearchWorkspace, ResearchWorkspaceDetail, ResearchWorkspaceRepositoryList, ResearchWorkspaceSummary, ResetInitialResearchAttempt, ResetInitialResearchAttemptResult, ResumeBackgroundJob, SaveCheckpoint, SessionCredentials, SettleBackgroundJob, StartResearchWorkspace, StartResearchWorkspaceResult, StoredChannel, StoredWebSession, SupersedeBackgroundJob, UpdateAgentContext, UserNavigation, UserNavigationSnapshot, UserProject, UserRecord, } from "./model"; import type { ExperimentStore } from "./experiments"; export interface UserStore { put(user: PutUser): Promise; get(id: string): Promise; } export interface SessionStore { create(session: CreateWebSession): Promise; get(id: string, now: Date): Promise; rotate(id: string, expectedRevision: number, credentials: SessionCredentials): Promise; delete(id: string): Promise; deleteExpired(now: Date): Promise; /** Release all Planner owners; retain only unexpired sessions with encrypted credentials. */ reset( now: Date, lease: Lease, leaseTtlMs: number, ): Promise<{ deleted: number; lease: Lease }>; } export interface NavigationStore { snapshot(userId: string): Promise; projects(userId: string): Promise; firstDocument(userId: string, repositoryIds: string[]): Promise; addProject(input: AddUserProject): Promise; get(userId: string): Promise; setLastDocument( userId: string, documentId: string | undefined, now: Date, ): Promise; setLastDocumentIfCurrent( userId: string, expectedRevision: number | undefined, documentId: string | undefined, now: Date, ): Promise; recordVisit(input: RecordNavigationVisit): Promise; } export interface ChannelStore { /** Creates a top-level channel or one repository-local, non-recursive child. */ create(input: CreateChannel): Promise; get(id: string): Promise; resolve(repositoryId: string, slug: string): Promise; rename(channel: RenameChannel): Promise; archive(input: ChannelArchiveInput): Promise; restore(input: ChannelArchiveInput): Promise; delete(id: string): Promise; publishDescription(input: PublishChannelDescription): Promise; list( repositoryId: string, limit: number, after?: { updatedAt: Date; id: string; }, query?: string, includeArchived?: boolean, ): Promise; scan( repositoryId: string, limit: number, after?: ChannelScanCursor, includeArchived?: boolean, ): Promise; /** Totals the repository's active catalogue: what `list` returns without archived rows. */ unansweredDecisions(repositoryId: string): Promise; /** Current counts for the requested channels that belong to the repository, archived or not. */ unansweredDecisionCounts( repositoryId: string, channelIds: string[], ): Promise; claimAgentOwner(channelId: string, sessionId: string, now: Date): Promise; clearAgentOwner( channelId: string, expectedSessionId: string, expectedGeneration: number, now: Date, ): Promise; updateAgentContext(context: UpdateAgentContext): Promise; readAgent(channelId: string, now: Date): Promise; } export interface CollaborationStore { load(channelId: string, now: Date): Promise; commit(input: CommitChannel): Promise; replace(input: ReplaceChannel): Promise; checkpoint(input: SaveCheckpoint): Promise; } export interface LeaseStore { acquire(name: string, owner: string, ttlMs: number): Promise; renew(lease: Lease, ttlMs: number): Promise; release(lease: Lease): Promise; } export interface BackgroundJobStore { enqueue(input: EnqueueBackgroundJob): Promise<{ job: BackgroundJob; repeated: boolean }>; claim(input: ClaimBackgroundJobs): Promise; renew(input: RenewBackgroundJob): Promise; appendProgress(input: AppendBackgroundJobProgress): Promise; requeue(input: RequeueBackgroundJob): Promise; settle(input: SettleBackgroundJob): Promise; pause(input: PauseBackgroundJob): Promise; resume(input: ResumeBackgroundJob): Promise; fail(input: FailBackgroundJob): Promise; cancel(input: CancelBackgroundJob): Promise; supersede(input: SupersedeBackgroundJob): Promise; list( channelId: string, limit: number, after?: BackgroundJobCursor, ): Promise; get(channelId: string, jobId: string): Promise; } export interface ResearchWorkspaceStore { create(input: CreateResearchWorkspace): Promise; start(input: StartResearchWorkspace): Promise; markReferencePlaced(input: { channelId: string; workspaceId: string; lease: Lease; }): Promise; listReferenceRecovery( limit: number, afterId?: string, channelId?: string, ): Promise; listTerminalRecovery( limit: number, afterId?: string, channelId?: string, ): Promise; confirm(input: ConfirmResearchWorkspace): Promise; appendTurn(input: AppendResearchTurn): Promise; linkJob(input: LinkResearchTurnJob): Promise; resetInitialAttempt( input: ResetInitialResearchAttempt, ): Promise; appendAgentMessage( input: AppendResearchAgentMessage, ): Promise; publishInitialReport( input: PublishInitialResearchReport, ): Promise; list( channelId: string, limit: number, includePlanner?: boolean, ): Promise; listRepository( repositoryId: string, limit: number, includeArchived?: boolean, includePlanner?: boolean, ): Promise; get(channelId: string, workspaceId: string): Promise; findByIdempotencyKey( channelId: string, idempotencyKey: string, ): Promise; /** The workspace in `channelId` whose report became the child document `publishedChannelId`. */ findPublished( channelId: string, publishedChannelId: string, ): Promise; findTurnByJob(channelId: string, jobId: string): Promise; } /** The complete durable boundary. No provider-specific primitive crosses it. */ export interface StorageAdapter { readonly experiments: ExperimentStore; readonly driver: string; readonly users: UserStore; readonly sessions: SessionStore; readonly navigation: NavigationStore; readonly channels: ChannelStore; readonly collaboration: CollaborationStore; readonly leases: LeaseStore; readonly jobs: BackgroundJobStore; readonly research: ResearchWorkspaceStore; migrate(): Promise; health(): Promise; close(): Promise; }