import { type TmuxApi } from "../team/tmux.js"; /** * Strip ANSI escape sequences (OSC, CSI, and single-char Fe) from pane text. * The OSC branch is bounded — it stops at the next BEL or ESC and tolerates a * missing terminator (capture-pane can truncate mid-sequence) so it never * greedily consumes real output between two sequences. */ export declare function stripAnsi(input: string): string; export interface OnlineOptions { host?: string; port?: number; timeoutMs?: number; } /** Low-level reachability probe: resolves true if a TCP connection opens. */ export type Connector = (host: string, port: number, timeoutMs: number) => Promise; /** * Returns true when the host appears to have internet connectivity. Defaults * to a TCP probe of 1.1.1.1:443; overridable via env or options for tests and * restricted networks. * * Note: this confirms reachability of the probe host only, not that Copilot's * upstream (GitHub / model API) is reachable. It is a coarse "are we online" * gate, not a Copilot health check. */ export declare function checkOnline(opts?: OnlineOptions, connect?: Connector): Promise; export interface CommsDeps { /** tmux API (defaults to the real one). */ tmux?: TmuxApi; /** internet reachability check (defaults to {@link checkOnline}). */ isOnline?: () => Promise; /** sleep used by polling loops (injectable for tests). */ sleep?: (ms: number) => Promise; } export interface StatusResult { ok: true; session: string; /** tmux session exists ("on"). */ exists: boolean; /** internet reachable. */ online: boolean; /** pane shows an idle prompt (ready for input). */ ready: boolean; /** pane shows an active task in progress. */ busy: boolean; /** set when the pane existed but its contents could not be read. */ error?: string; } export declare function commsStatus(session: string, deps?: CommsDeps): Promise; export interface SendResult { ok: boolean; session?: string; /** true if the text was observed in the pane before Enter was pressed. */ confirmed?: boolean; /** true if the prompt was observed to leave the input buffer (actually submitted). */ submitted?: boolean; error?: string; } export interface SendOptions { /** send even when the pane shows an active task in progress. */ force?: boolean; } /** * Send a prompt into the Copilot pane. Refuses unless the session exists AND * the host is online. Sends the text literally, then presses Enter and * verifies the prompt actually left the input buffer (returns ok:false if it * could not be submitted). * * Before pressing Enter it confirms the text landed in the input buffer by * comparing pane captures (a delta check, so prompt text already present in * scrollback can't false-confirm). Copilot CLI (>=1.0.61) can absorb a C-m * that arrives immediately after a bracketed paste, leaving the prompt * buffered and unsent; so after Enter we verify the input line cleared and * re-send Enter up to twice if it did not. Submission is detected by the input * line emptying or the host going busy, so a successful send is never * double-submitted. */ export declare function commsSend(session: string, text: string, deps?: CommsDeps, opts?: SendOptions): Promise; export interface RecvOptions { /** number of trailing pane lines to capture (default 80). */ lines?: number; /** poll until the pane returns to an idle prompt before capturing. */ wait?: boolean; /** max time to wait when `wait` is set (default 30000ms). */ timeoutMs?: number; /** poll interval when `wait` is set (default 500ms). */ pollMs?: number; } export interface RecvResult { ok: boolean; session?: string; text?: string; /** true if `wait` gave up before the pane became ready (text may be mid-generation). */ timedOut?: boolean; error?: string; } /** Read Copilot's latest pane output back (ANSI-stripped). */ export declare function commsRecv(session: string, deps?: CommsDeps, opts?: RecvOptions): Promise; /** * Best-effort isolation of the output that appeared *after* a baseline capture. * tmux scrollback has no reliable delimiters, so this uses an order-preserving * multiset diff: lines present in `after` but not already accounted for in * `before` are treated as new, with leading/trailing blank or prompt-only lines * trimmed. It is a heuristic — not a guaranteed exact reply boundary. */ export declare function newOutputSince(before: string, after: string): string; export interface AskOptions extends SendOptions { /** trailing pane lines to consider (default 200). */ lines?: number; /** max time to wait for Copilot to go idle (default 30000ms). */ timeoutMs?: number; /** poll interval while waiting (default 500ms). */ pollMs?: number; } export interface AskResult extends RecvResult { /** whether the prompt was actually sent. */ sent: boolean; } /** * Send a prompt and return only Copilot's new reply: snapshot the pane, send * (with the same on/online/busy guards as {@link commsSend}), wait until the * pane goes idle, then diff against the snapshot via {@link newOutputSince}. */ export declare function commsAsk(session: string, text: string, deps?: CommsDeps, opts?: AskOptions): Promise;