import type { IControllerRuntimeId, TControllerResourceKind, TControllerTerminalAgentKind, TControllerTerminalAgentDesiredState, TControllerTerminalAgentLaunchMode, TControllerTerminalAgentFailure, TControllerSessionId, TControllerSessionHarnessId, TControllerLayoutItemRef, TControllerConversationOrigin, TControllerModelChoice, IControllerSessionGroup, TControllerScratchpadUpdater, TControllerIntelligenceStatus, IControllerIntelligenceExchange, IControllerSessionScratchpad, TControllerProjectRemovalBlockedCode, } from '../ts_interfaces/index.js'; import type * as plugins from './plugins.js'; import type { IControllerFlexCleanupEntry } from './classes.managedsessionmodels.js'; export const controllerProjectLimit = 512; export const controllerResourceLimit = 4096; export const controllerResourcesPerProjectLimit = 64; export const controllerTrackedConversationLimit = 4096; export const controllerTrackedConversationsPerProjectLimit = 512; /** Projects fanned out by one cross-project conversation or resource read. */ export const controllerCrossProjectReadFanoutLimit = 64; export const controllerFilesystemIdentityMaximumComponents = 512; export type TControllerFilesystemObjectType = 'directory' | 'file'; export interface IControllerFilesystemIdentityComponent { device: string; inode: string; type: TControllerFilesystemObjectType; } export interface IControllerFilesystemIdentity { /** Ordered filesystem identities from the filesystem root through the target. */ ancestry: IControllerFilesystemIdentityComponent[]; } export interface IControllerProjectFilesystemIdentity extends IControllerFilesystemIdentity {} export interface IControllerPersistedSessionGroup { id: string; name: string; itemIds: TControllerLayoutItemRef[]; } export interface IControllerProjectDocument { /** 16-byte base64url identifier. */ id: string; /** `controller:` owner scope. */ controllerId: string; /** Directory name under the projects root; doubles as display name. */ name: string; /** Absolute resolved path of the project worktree. */ directory: string; /** Legacy projects that could not be verified during migration remain permanently unbound. */ directoryIdentityState: 'bound' | 'unbound'; /** Complete root-to-project filesystem ancestry, present only while bound. */ directoryIdentity?: IControllerProjectFilesystemIdentity; createdAt: Date; /** Durable write-before-cleanup intent; startup resumes this removal. */ removalStartedAt?: Date; /** Exact audited project-removal operation; retained on its tombstone. */ removalOperationId?: string; /** Exact Flex generations authorized only for project-removal cleanup. */ flexCleanupCohort?: IControllerFlexCleanupEntry[]; /** * Set when the pending removal stopped on a deterministic failure, together with * `removalBlockedCode` and `removalBlockedReason`. The removal stays pending; an operator retry * or the next controller start clears the three fields and resumes it. */ removalBlockedAt?: Date; /** Stable machine code of the deterministic failure; present exactly with `removalBlockedAt`. */ removalBlockedCode?: TControllerProjectRemovalBlockedCode; /** Short operator-readable explanation; present exactly with `removalBlockedAt`. */ removalBlockedReason?: string; /** Tombstone: set when the project is deregistered; files stay untouched. */ removedAt?: Date; } export interface IControllerSessionGroupsDocument { /** `${controllerId}:groups` — one persisted sidebar layout per controller. */ id: string; controllerId: string; /** * Literal marker of the controller-wide layout. A required key rather than an absent one, so a * lifted document is recognised positively and the per-project lift can never run twice. */ scope: 'controller'; groups: IControllerPersistedSessionGroup[]; /** Present with revision; both are absent on legacy documents. */ ungroupedItemIds?: TControllerLayoutItemRef[]; /** Present with ungroupedItemIds; legacy documents are interpreted as revision zero. */ revision?: number; } /** * One membership in a resource's attachment set. Cycle-freedom is structural: only a browser may * carry a terminal entry, and a terminal resource may carry session entries only. */ export interface IControllerResourceAttachmentEntryDocument { kind: 'session' | 'terminal'; /** Qualified runtime id for a session entry; the terminal's resource id for a terminal entry. */ id: TControllerSessionId | string; projectId: string; attachedAt: Date; /** Exact managed-session identity; present on session entries. */ sessionIdentityId?: string; /** Fences the exact conversation of a terminal subject across its restarts. */ agentSessionId?: string; } /** Exactly one attachment obligation may be in flight for a resource. */ export interface IControllerPendingResourceAttachment { operationId: string; attachmentRevision: number; op: 'add' | 'remove' | 'replace'; /** The entry being added, or removed; absent only when a remove clears the whole set. */ entry?: IControllerResourceAttachmentEntryDocument; /** Present only for `replace`: the entry the add supersedes. */ replaces?: IControllerResourceAttachmentEntryDocument; requestedAt: Date; } /** * A terminal resource as an attachment subject. The fence is the coding agent's own conversation * id, which survives terminal restarts (`--resume`) and changes only when the conversation does. */ export interface IControllerResourceTerminalTargetDocument { resourceId: string; agentSessionId?: string; } /** * Present only when the terminal root is a controller-owned coding agent rather than a shell. * `desiredState` is an explicit intent written by create, start, stop and natural root exit — and * deliberately never by controller shutdown, so a restart can tell "the user stopped this" from * "the controller went down underneath it". */ export interface IControllerTerminalAgentMetadata { kind: TControllerTerminalAgentKind; /** The agent's own conversation id; stable for the resource lifetime. */ sessionId: string; desiredState: TControllerTerminalAgentDesiredState; /** Consumed by the startup restart loop to stop retrying a permanently broken chat. */ consecutiveFailures: number; launchMode?: TControllerTerminalAgentLaunchMode; lastFailure?: TControllerTerminalAgentFailure; lastFailureMessage?: string; } export interface IControllerTerminalResourceMetadata { command: string; args: string[]; cwd: string; stoppedAt?: Date; lastExitCode?: number; agent?: IControllerTerminalAgentMetadata; } export interface IControllerResourceDocument { /** Random stable public identifier. */ id: string; controllerId: string; projectId: string; kind: TControllerResourceKind; title: string; /** Stable BrowserRuntime attachment authority for the resource lifetime. */ attachmentAuthorityId: string; /** Monotonic fence advanced by every add, remove, or replace across the whole set. */ attachmentRevision: number; /** * The attachment set. Empty means detached. Replaces the single `sessionId`/`terminalTarget` * slot; a build that predates this field rejects documents that carry it (one-way upgrade). */ attachments: IControllerResourceAttachmentEntryDocument[]; /** Write-before-side-effect attachment obligation. */ pendingAttachment?: IControllerPendingResourceAttachment; lifecycle: 'active' | 'retiring' | 'retired'; terminal?: IControllerTerminalResourceMetadata; createdAt: Date; updatedAt: Date; retiringAt?: Date; retiredAt?: Date; /** Reconciliation identity for the newest exact write. */ updateId: string; } export interface IControllerSettingsDocument { /** `controller::settings` — one settings document per controller. */ id: string; controllerId: string; /** At most one default per session harness. */ defaultModels: TControllerModelChoice[]; /** Present only as `true`; absent means permission requests wait for a human. */ autoAcceptPermissions?: true; /** Absent selects Chromium capture; native requires the NVIDIA runtime. */ browserVideoBackend?: 'native'; /** Flex provider connection currently installed into the controller-owned OpenCode runtime. */ selectedOpenCodeProviderConnectionId?: string; /** * Absolute existing directories AGL offers as project locations. Absent on documents written * before standard directories existed and read as an empty list. */ standardProjectDirectories?: string[]; /** * Harness of the conversation started last from the workspace. Absent until one is started, * which is what keeps the new-conversation box from defaulting to a harness nobody chose. */ lastSessionHarnessId?: TControllerSessionHarnessId; } /** * One conversation AGL tracks explicitly, independent of the managed-session identity record * that authorizes access to it. AGL never mirrors harness conversations into this set: it holds * exactly what was created through AGL or opened through the conversation search. */ export interface IControllerTrackedConversationDocument { /** Hash of the complete controller/project/qualified-conversation scope. */ id: string; controllerId: string; projectId: string; harnessId: TControllerSessionId['harnessId']; runtimeId: TControllerSessionId; /** Exact managed-session identity proving durable membership when the entry was written. */ sessionIdentityId: string; origin: TControllerConversationOrigin; trackedAt: Date; /** AGL-level archive. The harness conversation is untouched and keeps its own archive state. */ archivedAt?: Date; /** Last observed title, so the archive view renders without a harness read. */ titleCache?: string; titleCacheAt?: Date; /** Fixed-size reconciliation identity for the newest exact transition. */ updateId: string; } export interface IControllerPersistedIntelligenceExchange { id: string; question: string; status: TControllerIntelligenceStatus; answer?: string; error?: string; model?: string; scratchpadConflict?: true; /** Private admission state, present only while status is running. */ scratchpadRevisionAtAdmission?: number; /** Cleanup obligation retained until the temporary OpenCode session is confirmed deleted. */ temporarySessionId?: string; createdAt: Date; completedAt?: Date; } export interface IControllerSessionStateDocument { /** Hash of the complete controller/project/qualified-session scope. */ id: string; controllerId: string; projectId: string; sessionId: IControllerRuntimeId; scratchpad: { text: string; revision: number; updatedAt?: Date; updatedBy?: TControllerScratchpadUpdater; }; intelligenceExchanges: IControllerPersistedIntelligenceExchange[]; /** Exact FlexHarness project-management state for Flex sessions. */ flexProjectManagement?: plugins.flexharness.TFlexProjectManagementRecord; /** Durable per-session model choice; absent means use the harness default. */ modelChoice?: TControllerModelChoice; /** Exact Flex provider account selected for this session, separate from model identity. */ providerConnectionId?: string; /** Fixed-size reconciliation identity for the newest exact transition. */ updateId: string; /** Content-clearing tombstone; TTL cleanup is best-effort storage maintenance. */ deletedAt?: Date; } export interface IControllerSessionState { scratchpad: IControllerSessionScratchpad; intelligenceExchanges: IControllerIntelligenceExchange[]; modelChoice?: TControllerModelChoice; providerConnectionId?: string; } export interface IControllerIntelligenceAdmission { exchange: IControllerIntelligenceExchange; scratchpadRevision: number; scratchpadText: string; } export interface IControllerInterruptedIntelligenceRecovery { recoveredCount: number; exhaustive: boolean; temporarySessionIds: Array<{ projectId: string; sessionId: IControllerRuntimeId; exchangeId: string; nativeId: string; }>; }