import type { EventEmitter } from "events"; import type { IncomingMessage, ServerResponse } from "http"; import type { WebSocket } from "ws"; import type { AgentClient } from "./agent/agent-client"; import type { AgentConfig } from "./agent/agent-config"; import type { ConversationWriter } from "./agent/conversation-writer"; import type { ConversationHandlers } from "./api/handlers/conversations.handlers"; import type { SessionHandlers } from "./api/handlers/sessions.handlers"; import type { ApiDeps } from "./api/types/api-deps"; import { ConversationCache } from "./conversation-cache"; import type { CacheMetadataRepository } from "./db/repositories/cacheMetadata.repository"; import type { ConversationsRepository } from "./db/repositories/conversations.repository"; import type { DevicesRepository } from "./db/repositories/devices.repository"; import type { ManagedSessionsRepository } from "./db/repositories/managed-sessions.repository"; import type { ProjectsRepository } from "./db/repositories/projects.repository"; import type { PushRepository } from "./db/repositories/push.repository"; import type { SessionsRepository } from "./db/repositories/sessions.repository"; import type { RuntimeStore } from "./db/runtime-store"; import type { ExternalTailManager } from "./external-tails"; import type { LiveSessionManager } from "./live-session-manager"; import { type Logger } from "./logger"; import type { ScannerManager } from "./scanner-manager"; import type { Prompt } from "./schemas/prompt.schema"; import type { CacheIntegrityMonitor } from "./services/cache-integrity/cacheIntegrityMonitor"; import type { ConversationWatcher, ConversationWatcherEvents } from "./services/conversations/conversationWatcher"; import type { HostPressureMonitor } from "./services/host-pressure/hostPressure"; import type { PromptRegistry } from "./services/prompts/promptRegistry"; import type { LiveActivityNotifier } from "./services/push/liveActivityNotifier"; import type { WaitingInputNotifier } from "./services/push/waitingInputNotifier"; import type { ReconcileVerdict } from "./services/sessions/reconcileSessions"; import type { SessionStore } from "./session-store"; import type { AskQuestion, PermissionOption, PTYManagerOptions, ServerWarmupState, SessionResponse } from "./types"; import type { WSHub } from "./ws-hub"; /** The permission gate currently open for a session (scraped via OSC 777). */ export type PendingPermission = { prompt?: string; detail?: string; options: PermissionOption[]; cursor?: number; /** Server-owned instance id, minted by handlePermissionChange. */ gateId: string; promptId?: string; /** * The pty-host's occurrence id for this gate, absent on the in-process PTY * path. Instance identity is compared against THIS, never against promptId: * the two were equal by construction until open() started minting a fresh id * for a replayed occurrence held by a terminal record. */ occurrenceId?: string; }; /** The AskUserQuestion card currently broadcast for a session. */ export type PendingQuestion = { toolUseId: string; questions: AskQuestion[]; origin: "pty" | "jsonl"; promptId: string; }; export type ExpiredPendingPromptDeps = { pendingPermission: Map; pendingPermissionKey: Map; pendingQuestions: Map; pendingQuestionKey: Map; sessionSubscribers: Map>; wsHub: Pick; }; export declare function clearExpiredPendingPrompt(deps: ExpiredPendingPromptDeps, prompt: Prompt): void; /** * Everything the ConversationWatcher callbacks read from the server. Thunks * rather than values for anything constructed after the watcher itself * (`externalTailManager`, and `fileWatcher` — which IS the watcher these * callbacks are handed to) or swapped on the instance by tests (`log`, * `broadcastConversationLines`); the same reason ScannerManagerDeps passes * `cache: () => ConversationCache | null`. * * The Maps are the server's own, held by reference: they stay StreamerServer * state and are read directly elsewhere in server.ts. */ export type ConversationWatcherWiringDeps = { sessionFileMap: Map; pendingLineSeqs: Map; scannerManager: ScannerManager; cache: () => ConversationCache | null; log: () => Logger; fileWatcher: () => ConversationWatcher; externalTailManager: () => ExternalTailManager; trackCacheWrite: (task: Promise) => void; processJsonlQuestions: (sessionId: string, lines: string[]) => void; broadcastConversationLines: (sessionId: string, lines: string[], seqs?: (number | null)[] | null) => void; }; /** * The JSONL tail/offset-index/directory callbacks StreamerServer hands to its * ConversationWatcher. * * Extracted from the constructor so watcher work stops editing the server file * (see docs/plans/2026-07-12-server-ts-split.md, PR 7). State stays on the * server: these callbacks only reach it through `deps`. */ export declare function createConversationWatcherEvents(deps: ConversationWatcherWiringDeps): ConversationWatcherEvents; /** * Everything the LiveSessionManager callbacks read from the server. Same thunk * discipline: `sessionHandlers` is constructed after the runner, the repos and * notifiers are bound during listen(), and `log` is swapped by tests. */ export type LiveSessionWiringDeps = { sessionGeometry: Map; sessionStore: SessionStore; wsHub: WSHub; fileWatcher: ConversationWatcher; scannerManager: ScannerManager; sessionStatusBus: EventEmitter; sessionFileMap: Map; sessionSubscribers: Map>; lastAgentChunkAt: Map; terminalSeq: Map; pendingQuestions: Map; pendingQuestionKey: Map; pendingPermission: Map; pendingPermissionKey: Map; promptRegistry: PromptRegistry; contendedSessions: Set; log: () => Logger; sessionHandlers: () => SessionHandlers; managedSessionsRepo: () => ManagedSessionsRepository | null; liveActivityNotifier: () => LiveActivityNotifier | null; waitingInputNotifier: () => WaitingInputNotifier | null; ptyAttachedIds: () => Set; cancelPendingQuestion: (sessionId: string) => void; rememberSelfPtyEnded: (conversationId: string) => void; maybeFireHoldWhenIdle: (session: { id: string; status: string; }) => void; }; /** * The options StreamerServer hands to its LiveSessionManager: terminal/user * output fan-out, gate and question plumbing, and the status funnel that * mirrors every transition into SessionStore, the durable registry, the * scanner index and the push notifiers. * * Extracted from the constructor for the same reason as the watcher events * above; the server keeps every Map and Set these callbacks mutate. */ export declare function createLiveSessionOptions(deps: LiveSessionWiringDeps): PTYManagerOptions; /** * Everything the ApiDeps assembly reads from the server. * * Values where the original literal captured a value (`publicUrl`, * `browseRoot`, and the collaborators built earlier in the constructor); * thunks and arrows everywhere the original used them, which is load-bearing: * the stores open during listen(), `apiKey` changes under rotateApiKey(), and * tests swap `log`/`startGraceTimer`/`broadcastConversationLines` on the * server instance after construction. */ export type ApiDepsWiring = { sessionGeometry: Map; apiKey: () => string; localNoAuth: boolean; logMenubarRequests: boolean; publicUrl: string | null; browseRoot: string | null; browserCors: string | undefined; ptyGracePeriodMs: number; rotateApiKey: ApiDeps["rotateApiKey"]; claudeFlagsConfig: ApiDeps["claudeFlagsConfig"]; featureFlagsConfig: ApiDeps["featureFlagsConfig"]; setClaudeFlagsConfig: ApiDeps["setClaudeFlagsConfig"]; ptyManager: LiveSessionManager; sessionStore: SessionStore; wsHub: WSHub; sessionHandlers: SessionHandlers; conversationHandlers: ConversationHandlers; cache: () => ConversationCache | null; cacheMonitor: () => CacheIntegrityMonitor | null; hostPressureMonitor: () => HostPressureMonitor | null; pushRepo: () => PushRepository | null; liveActivityPushEnabled: () => boolean; expoPushEnabled: () => boolean; expoPushSender: ApiDeps["expoPushSender"]; devicesRepo: () => DevicesRepository | null; projectsRepo: () => ProjectsRepository | null; conversationsRepo: () => ConversationsRepository | null; sessionsRepo: () => SessionsRepository | null; cacheMetadataRepo: () => CacheMetadataRepository | null; runtimeStore: () => RuntimeStore | null; managedSessionsRepo: () => ManagedSessionsRepository | null; sessionVerdicts: () => Map; log: () => Logger; ptyAttachedIds: () => Set; withReconciledLifecycle: (sessions: readonly SessionResponse[]) => readonly SessionResponse[]; currentWarmupState: () => ServerWarmupState | null; addSessionSubscriber: (sessionId: string, ws: WebSocket) => void; removeSessionSubscriber: (sessionId: string, ws: WebSocket) => void; startGraceTimer: (sessionId: string, delayMs: number) => void; armHoldWhenIdle: (sessionId: string) => "held" | "armed" | "no_session"; handleSessionsCount: (res: ServerResponse) => void; applyLiveSessionSetting: (sessionId: string, req: IncomingMessage, res: ServerResponse, setting: "model" | "effort") => Promise; handlePairStart: (res: ServerResponse) => void; handlePairExchange: (req: IncomingMessage, res: ServerResponse) => Promise; handleBrowse: (url: URL, res: ServerResponse) => Promise; handleMkdir: (req: IncomingMessage, res: ServerResponse) => Promise; clientIdToWs: Map; wsToClientId: Map; sessionSubscribers: Map>; terminalSeq: Map; pendingPermission: Map; pendingQuestions: Map; promptRegistry: PromptRegistry; agentClient: AgentClient | null; conversationWriter: ConversationWriter | null; agentConfig: AgentConfig; }; /** * Assemble the dependency bag the Hono app and the WS routes are built from, * including the three WebSocket lifecycle handlers. * * Extracted from the constructor for the same reason as the two factories * above; every key, its order and its target are unchanged. */ export declare function createApiDeps(deps: ApiDepsWiring): ApiDeps; //# sourceMappingURL=server-wiring.d.ts.map