import { type VisualAuthority, type VisualDiagnostic, type VisualEvent, type VisualFreezeReason, type VisualHandoff, type VisualResponse, type VisualSessionDescriptor, type VisualSessionRequest, type VisualTerminationReason } from './protocol.js'; import { type WorkspaceSource } from '../../compiler.js'; import { type CanvasGraph } from '../../graph-projection.js'; export declare const VISUAL_SESSION_MARKER_FORMAT: 'yarramate/visual-session-marker/v1'; /** * Upper bound on how many orphaned sessions one `start` prunes. Cleanup runs on * the critical path of a new session, so a directory full of orphans must cost * a bounded amount of work; the remainder is collected by the next start. */ export declare const VISUAL_SESSION_PRUNE_LIMIT = 64; /** * Whether a journaled event requires an agent turn. Navigation is journaled for * context but only interrupts the agent when the browser marked it as needing * attention. The runtime shares this definition rather than restating it, so * the queue the server bounds and the events recovery replays cannot diverge. */ export declare const isActionableVisualEvent: (event: VisualEvent) => boolean; export interface VisualSessionPaths { readonly root: string; readonly marker: string; readonly descriptor: string; readonly journal: string; } export interface SessionDependencies { readonly baseDir: string; readonly now: () => Date; readonly randomBytes: (size: number) => Buffer; } /** * What the runtime needs to mint one terminal event. It is the same clock and * the same random source the session was created with, so a test drives the * closing record exactly as it drives every other one. */ export type TerminalEventDependencies = Omit; /** * The only session state that outlives the runtime process. Recovery never * resumes the server or the compiler, so the marker carries the session * identity, its age for pruning, and the authority label the handoff must * report — and deliberately not the candidate model or the compiler vector. */ export interface VisualSessionMarker { readonly format: typeof VISUAL_SESSION_MARKER_FORMAT; readonly id: string; readonly createdAt: string; readonly authority: VisualAuthority; } export interface VisualSessionCreated { readonly paths: VisualSessionPaths; readonly browserToken: string; readonly agentToken: string; } export interface VisualAppendAccepted { readonly ok: true; readonly lastSequence: number; readonly transcriptBytes: number; readonly duplicate: boolean; } export interface VisualAppendRejected { readonly ok: false; readonly freeze?: VisualFreezeReason; readonly diagnostics: readonly VisualDiagnostic[]; } export type VisualAppendResult = VisualAppendAccepted | VisualAppendRejected; /** * The one place `VisualSessionPaths` is constructed. Every field stays a * native filesystem path — the form `fs`/`path` APIs, the in-process state * maps keyed by `paths.journal`, and directory cleanup all need — because * this is consumed as a filesystem path far more often than it is ever * serialized. The few sites that write one of these fields into a * schema-checked wire document encode it there, with `toWireFileUri`, rather * than here. */ export declare const visualSessionPaths: (root: string) => VisualSessionPaths; export declare const createVisualSession: (request: VisualSessionRequest, deps: SessionDependencies) => Promise; /** * Publishes the agent's entry point into a live session. The descriptor is the * only file that carries the agent capability, so it is written with the same * private write-then-rename every other session document uses, and only after * the marker confirms the descriptor describes this session and no other. */ export declare const writeVisualSessionDescriptor: (paths: VisualSessionPaths, descriptor: VisualSessionDescriptor) => Promise; export declare const appendVisualEvent: (paths: VisualSessionPaths, event: VisualEvent) => Promise; export declare const appendVisualResponse: (paths: VisualSessionPaths, response: VisualResponse) => Promise; /** * Journals the one record that closes a session, and answers with the record a * session already has. Every terminal cause — a reviewer's End, a failed child, * a browser that never came back, a cancellation, a restart collecting what a * dead runtime left — converges here, so a session ends exactly once no matter * how many of them fire. */ export declare const appendTerminalEvent: (paths: VisualSessionPaths, reason: VisualTerminationReason, deps: TerminalEventDependencies) => Promise; export declare const readActionableEventsAfter: (paths: VisualSessionPaths, sequence: number) => Promise; export declare const recoverVisualSession: (paths: VisualSessionPaths, includeTranscript?: boolean) => Promise; export type VisualModelGraphResult = { readonly ok: true; readonly graph: CanvasGraph; } | { readonly ok: false; readonly diagnostics: readonly VisualDiagnostic[]; }; /** * Builds the `graph` a session's `VisualModel` renders, from the workspace's * own source documents. This is the whole construction step a visual session * needs at start: no subprocess, no staged candidate directory, no on-disk * pointer file — `compileWorkspaceWithProfileContext` and * `projectGraphForCanvas` are both pure, synchronous functions over this * repo's native compiler, so the caller assembles the result directly into * the full `VisualModel` (format, authority, initialView, sourceDigests, * graph) without any session-store I/O. * * A compile failure here is not a runtime defect — it is exactly the * diagnostic-shaped rejection the browser already expects, so the workspace * compiler's own diagnostics are returned unchanged rather than resynthesised. * `Diagnostic` (compiler.ts) and `VisualDiagnostic` (protocol-contract.ts) * already share one shape: severity, code, message, path, pointer, line, * column. */ export declare const buildVisualModelGraph: (sources: readonly WorkspaceSource[]) => VisualModelGraphResult; /** * Recovers the handoff and only then deletes the session, so cleanup can never * be the step that loses confirmed state. Returns `undefined` when the session * is already gone, which makes a repeated stop idempotent, and when a previous * cleanup already took the journal: there is no handoff left to recover, and * refusing would strand a marked directory that only this call will remove. */ export declare const removeVisualSession: (paths: VisualSessionPaths, includeTranscript?: boolean) => Promise; /** * Removes orphaned sessions a previous runtime left behind. Only directories * carrying a marker that names them are touched, and never more than `limit` * per pass; the least recently active go first. * * Staleness is measured against what the session last wrote, not against the * marker's creation time: a conversation that has run for two days is the * working case, and deleting it under a live runtime would destroy the * transcript the agent is still appending to. */ export declare const pruneStaleVisualSessions: (baseDir: string, now: Date, limit?: number) => Promise;