export type HerdrAgentState = "idle" | "working" | "blocked"; export interface HerdrPaneEnvironment { paneId: string; binPath: string; /** Herdr's API socket, when the pane environment names one. Its identity is * how a replaced server is detected; absent means replacement is undetectable * and the reporter simply keeps its normal transition-driven behavior. */ socketPath?: string; } export interface HerdrReportProcess { exited: Promise; kill(): void; unref(): void; } export interface HerdrReporterOptions { env?: NodeJS.ProcessEnv; which?: (command: string) => string | null; /** Identity written into the ownership marker. Injectable so the nested-process * case is testable without actually forking. */ pid?: number; /** OS process incarnation probe, injectable for PID-reuse and recovery tests. */ processIncarnation?: (pid: number) => string | undefined; /** Process liveness/incarnation probe, injectable for cross-platform recovery tests. */ processProbe?: (pid: number) => HerdrProcessProbe; spawn?: (command: string[], options: { env: NodeJS.ProcessEnv; stdin: "ignore"; stdout: "ignore"; stderr: "ignore"; }) => HerdrReportProcess; /** Watch for Herdr server replacement. Parameterized so the re-assert path is * testable without a live server; returns a disposer. */ watchServerReplacement?: (socketPath: string, onReplaced: () => void) => () => void; } export type HerdrProcessProbe = { state: "live"; incarnation: string; } | { state: "absent"; } | { state: "unverifiable"; }; /** Session event shape consumed by the reporter. Narrow on purpose: the state * machine is driven only by lifecycle transitions, never by message content. */ export interface HerdrSessionEvent { type: string; toolName?: string; } export interface HerdrReporter { /** Report a new agent state. Deduplicated against the last reported state. */ report(state: HerdrAgentState): void; /** Release this pane's lifecycle authority and stop listening. Idempotent. */ release(): void; /** Current reported state, for tests and diagnostics. */ readonly state: HerdrAgentState | null; /** Scope object for `syncHerdrPaneTitle` so a pane's title re-asserts stay * bound to this reporter. Opaque by design; pass it straight through. */ readonly titleScope: object; } /** * Resolve the pane environment. Returns null unless gjc is demonstrably inside * a Herdr pane AND a herdr binary is resolvable. * * `HERDR_BIN_PATH` is honored first because Herdr sets it for its own panes; * otherwise the binary is resolved from PATH. No home-directory guessing: an * unverified path scavenged from an install layout is a command this process * would execute, and PATH/`HERDR_BIN_PATH` are the trust boundary Herdr itself * documents. * * Also returns null when an ancestor gjc already owns this pane, so a nested * invocation reports nothing at all. */ export declare function resolveHerdrPaneEnvironment(options?: HerdrReporterOptions): HerdrPaneEnvironment | null; /** Build the argv for a state report. Exported for tests. */ export declare function buildHerdrReportArgs(paneId: string, state: HerdrAgentState, seq: number): string[]; /** Build the argv for an authority release. Exported for tests. */ export declare function buildHerdrReleaseArgs(paneId: string, seq: number): string[]; /** * Collapse a session name into a single-line pane title. Control characters are * removed rather than escaped: the value reaches a terminal surface, and a * model-generated session name must never be able to inject escapes. */ export declare function sanitizeHerdrPaneTitle(title: string | undefined): string | undefined; /** Build the argv for a pane title report. Exported for tests. */ export declare function buildHerdrTitleArgs(paneId: string, title: string, seq: number): string[]; /** Build the argv that retracts a previously reported pane title. Exported for tests. */ export declare function buildHerdrClearTitleArgs(paneId: string, seq: number): string[]; /** * Report the current session title for this pane. No-op outside a Herdr pane or * when the session has no usable name, so a pane keeps the last real title * instead of flickering to a placeholder during startup or a rename. */ export declare function syncHerdrPaneTitle(sessionName: string | undefined, options?: HerdrReporterOptions, titleScope?: object): void; export declare function createHerdrReporter(paneEnv: HerdrPaneEnvironment, subscribe: (listener: (event: HerdrSessionEvent) => void) => () => void, options?: HerdrReporterOptions): HerdrReporter; /** * Install the Herdr reporter for a running session. No-op outside a Herdr pane. * Returns the reporter so callers can release it deterministically, or null. */ export declare function installHerdrReporter(subscribe: (listener: (event: HerdrSessionEvent) => void) => () => void, options?: HerdrReporterOptions): HerdrReporter | null;