import { type Conversation } from "@threadbase-sh/scanner"; import type { ConversationCache } from "./conversation-cache"; import type { CacheMetadataRepository } from "./db/repositories/cacheMetadata.repository"; import type { ConversationsRepository } from "./db/repositories/conversations.repository"; import type { ManagedSessionsRepository } from "./db/repositories/managed-sessions.repository"; import type { ProjectsRepository } from "./db/repositories/projects.repository"; import type { SessionsRepository } from "./db/repositories/sessions.repository"; import type { LiveSessionManager } from "./live-session-manager"; import type { ScannerManager } from "./scanner-manager"; import type { ConversationWatcher } from "./services/conversations/conversationWatcher"; import type { SessionStore } from "./session-store"; import type { WSHub } from "./ws-hub"; /** * How long a transcript watcher keeps waiting for the file its provider will * write. Not a measured number: it arrived as `// give up after 2 minutes` in * 76cdf9f2, when these watchers existed to re-key a placeholder session id to * the real UUID — a mechanism that no longer exists. It survives only as a * bound on an abandoned session's watch, and it is deliberately measured from * the user's first turn rather than from the spawn, because that turn is what * causes the file to exist. Both watchers re-arm it per turn and neither applies * it before the first one. See the notes in watchForJsonl/watchForCodexRollout. */ export declare const TRANSCRIPT_WATCH_DEADLINE_MS = 120000; /** * Everything SessionWatchers reads from the server. Collaborators constructed * once in the server constructor are passed by reference; the ones opened * during listen() (and rebound by the integrity monitor's reset-and-rescan) are * thunks, for the same reason ApiDeps passes `cache: () => ConversationCache | null`. * * `broadcastConversationLines` / `findConversationByUuid` / `ptyAttachedIds` * stay late-bound calls back into the server rather than moved code: they are * server methods with their own dependencies (and tests spy on them). */ export type SessionWatchersDeps = { ptyManager: LiveSessionManager; sessionStore: SessionStore; wsHub: WSHub; fileWatcher: ConversationWatcher; /** sessionId → JSONL filePath. Owned by the server; mutated in place here. */ sessionFileMap: Map; scannerManager: ScannerManager; codexRoots: string[]; /** Cursor project roots (`~/.cursor/projects`); empty disables Cursor binding. */ cursorRoots: string[]; cache: () => ConversationCache | null; projectsRepo: () => ProjectsRepository | null; conversationsRepo: () => ConversationsRepository | null; sessionsRepo: () => SessionsRepository | null; cacheMetadataRepo: () => CacheMetadataRepository | null; managedSessionsRepo: () => ManagedSessionsRepository | null; findConversationByUuid: (uuid: string) => Promise; broadcastConversationLines: (sessionId: string, lines: string[], seqs?: (number | null)[] | null) => void; ptyAttachedIds: () => Set; }; /** * Binds a live session to the transcript file its provider writes: finds the * JSONL (Claude), rollout (Codex), or agent-transcripts run (Cursor), starts * the tail watcher, replays whatever was written before the watcher attached, * and links the session to its project. * * Extracted from StreamerServer so watcher work stops editing the server file * (see docs/plans/2026-07-12-server-ts-split.md, PR 5). */ export declare class SessionWatchers { private deps; private log; constructor(deps: SessionWatchersDeps); linkSessionToProject(sessionId: string, projectPath: string, filePath: string): void; watchConversationFile(sessionId: string, historyId?: string): Promise; readFirstLineSessionId(filePath: string): string | null; watchForJsonl(sessionId: string, projectPath: string): void; watchForCodexRollout(sessionId: string, projectPath: string): void; watchForCursorTranscript(sessionId: string, projectPath: string): void; } //# sourceMappingURL=session-watchers.d.ts.map