import type { BoardTask } from "./board.js"; import { type ArgsOf, type Event, type HelloArgs, type HelloResult, type Op, type ResultOf, type WorkerReport } from "./protocol.js"; /** A delivered reply or agent item (M9 adds the kind). */ export type DeliverItem = Pick, "seq" | "text" | "kind" | "from" | "relation" | "mode">; export interface JobIdentity { id: string; token: string; socket: string; } /** * Set in a worker's environment by the PTY host. The token is removed from the * environment once read (M9), so a /reload finds the identity kept in this process. */ export declare function jobIdentity(env?: NodeJS.ProcessEnv): JobIdentity | undefined; /** * Sends the latest report, one request at a time, reconnecting after daemon * restarts; never throws. State changes go out at once, row text at most * every SUMMARY_INTERVAL_MS. */ export declare class Reporter { private client; private latest; private sent; private sentAt; private urgentPending; private timer; private dueAt; private inflight; private retryMs; /** M22: after a failed request nothing goes out before this (not even a state change). */ private backoffUntil; private closed; private job; private onDeliver; /** Row text and context use alone go out at most this often (tests shorten it). */ private intervalMs; /** M31: said on every new connection before the first report. */ private hello; /** M31: what the daemon answered (undefined: no answer yet, or a daemon from before M31). */ daemonHello: HelloResult | undefined; constructor(job: JobIdentity, onDeliver?: (item: DeliverItem) => void, intervalMs?: number, hello?: HelloArgs); /** `urgent`: send now even when only the row text changed (a model summary). */ update(report: WorkerReport, urgent?: boolean): void; /** Send what is pending (bounded wait), then disconnect. */ close(): Promise; private drain; private schedule; private send; /** Tell the daemon a reply reached pi; best effort, a lost ack means a resend that is deduplicated. */ ack(seq: number, exact?: boolean): void; /** * M9: a request on this worker's own connection, which the daemon knows as this job * once a report went through on it. */ call(op: O, args: ArgsOf): Promise>; private request; } /** M31: a reply as an agent sees it: once each, in order, acked when its handler returns. */ export interface AgentReply { seq: number; text: string; /** "steer": join the work under way; "followUp" or absent: after it. */ mode?: "steer" | "followUp"; } /** M31: the report an agent gives; what it leaves out is filled in (a full snapshot goes). */ export type AgentReport = Partial & Pick; export interface RoostAgentOptions { name: string; version?: string; /** What it can do (docs/protocol.md); "report" and "replies" are assumed. */ capabilities?: string[]; /** A user's reply; acked once this returns (or its promise settles). */ onReply?: (reply: AgentReply) => void | Promise; /** Defaults to this process's environment. */ env?: NodeJS.ProcessEnv; } /** * M31: the agent side of the protocol for an agent other than pi, in a few calls: * * const agent = RoostAgent.fromEnv({ name: "my-agent", onReply: (r) => work(r.text) }); * agent?.report({ state: "working", summary: "reading the code" }); * * fromEnv gives undefined outside a roost job. Replies are handed over one at a time, in * seq order, never twice (the daemon resends unacked ones after a reconnect). */ export declare class RoostAgent { private reporter; /** Highest seq handed to the handler, and highest whose handler has returned (acked). */ private handled; private completed; private queue; private onReply; /** M35: where the last finished seq is kept, so a restarted agent does not redo a reply whose ack was lost. */ private mark; private constructor(); static fromEnv(o: RoostAgentOptions): RoostAgent | undefined; /** Its state now; sent at once when the state changed, the row text at most every few seconds. */ report(r: AgentReport): void; /** The daemon's hello answer, once connected (undefined before, or from a daemon before M31). */ get daemon(): HelloResult | undefined; /** Send what is pending, then disconnect. */ close(): Promise; /** M47: any op of the protocol (docs/protocol.md), as this job: answered, or refused by the daemon (an Error with its message). */ call(op: O, args: ArgsOf): Promise>; /** The board, every task (open, claimed, done, dropped), oldest first. */ tasks(): Promise; /** Take an open task: this job holds it until taskDone or releaseTask. Refused when another live session holds it (conflict), when it waits on tasks not done (blocked), or when it is done or dropped. */ claimTask(id: number): Promise; /** Mark the task this job holds done, with its result; tasks that waited on it become claimable. */ taskDone(id: number, result?: string): Promise; /** Give the task this job holds back to the board (open again). */ releaseTask(id: number): Promise; /** Put a task on the board for any session; after: task ids it waits on. */ addTask(title: string, opts?: { detail?: string; after?: number[]; }): Promise; private deliver; }