import { type ManagerReply } from "../lib/control.js"; import { type ConnectFlags } from "../lib/connect.js"; /** The console's control coordinates: the same `ConnectFlags` triple the CLI's control commands * resolve from. `space` is the one the console is currently watching. */ export type ControlCtx = ConnectFlags; /** The manager ops the console drives, each with the instrument profile the matching CLI command * mints and whether the op names a seat (a targeted op resolves seat locality first, so it is * served by the manager actually hosting the seat). */ declare const OPS: { readonly status: { readonly profile: "control-caller-privileged"; readonly targeted: true; }; readonly start: { readonly profile: "control-caller-privileged"; readonly targeted: false; readonly timeoutMs: 40000; }; readonly purge: { readonly profile: "control-caller-admin"; readonly targeted: false; }; readonly stop: { readonly profile: "control-caller-admin"; readonly targeted: true; }; }; export type ControlOp = keyof typeof OPS; /** Delete one channel: its retained history (a filtered purge) and its registry entry, through * core's `clearChannel`, the operation the web dashboard's delete button runs, with the same * per-action authority: a static-auth mesh mints a one-shot `channel-purger` credential from the * resolved mesh's seed, a user mesh asks for a `channel-purger` view (a fresh ledger check per * click), an open mesh connects bare. No manager involved. The name must be the one the mesh * uses, concrete and valid: a wildcard is refused (it would purge channels the operator did not * name) and a name the wire would rewrite is refused rather than quietly rewritten. */ export declare function deleteChannel(ctx: ControlCtx, channel: string): Promise<{ ok: true; purged: number; } | { ok: false; error: string; }>; /** One managed-agent row as the manager's `ps` / `inspect` answer it (the fields the console reads). */ export interface ManagedRow { name: string; id: string; role?: string; agent: string; mode: string; status: string; uptimeMs: number; mesh: string; model?: string; } /** One control call. A targeted op names its seat in `args.name`; the alias is resolved to the * incarnation triple inside `askManager` (the manager's `inspect` read), so the wire never carries * a name as a target. Reach is `owner` on a user mesh (the bearer's one path; the manager decides * by ledger scope) and `any` on a static or open mesh (the admin instrument's cross-agent row). */ export declare function control(ctx: ControlCtx, op: ControlOp, args?: Record): Promise; /** The managed rows of every reachable manager in the space: the `cotal ps` read. * * `rows` is the merged list, `silent` the instances that did not answer, `failed` the reachable * instances that answered with an error, and `answered` the rows attributed to the instance that * served them. The attribution is what makes a partial answer * usable: a caller holding state across polls can replace exactly the instances that spoke and * keep only what a silent one last said, which neither a merged list nor a flat rebuild allows. * `cotal ps` prints a silent instance rather than dropping it, and the console must not be the * one surface that quietly answers a narrower question than the one asked. */ export type PsReply = { ok: true; rows: ManagedRow[]; silent: string[]; failed: { instanceId: string; error: string; }[]; answered: { instanceId: string; rows: ManagedRow[]; }[]; } | { ok: false; error: string; }; /** Fold one ps answer into the rows held per manager instance, which is the only shape that can * both DROP a despawned seat and KEEP a quiet manager's seats. * * An instance that answered has its rows replaced wholesale, so a seat it no longer lists is gone * on that tick. An instance that was asked and stayed silent keeps what it last said, because a * seat is not gone just because nobody could be reached to ask about it. An instance that is * neither has left the registry, and its rows leave with it. * * A flat merge across instances cannot express the first of those: it can add and overwrite but * never delete, so one silent registration, which can persist indefinitely when a manager's host * dies without deregistering, would freeze every other manager's seats in place forever. A flat * rebuild is the opposite error, emptying a quiet manager's seats off the display. */ export declare function foldManagedRows(prev: Map, reply: { answered: { instanceId: string; rows: ManagedRow[]; }[]; silent: string[]; }): Map; /** The per-instance rows flattened to the id-keyed harness facts the roster and detail card read. */ export declare function managedById(byInstance: Map): Map; /** What one tick did, so a caller (and a test) can tell the three apart. */ export type PollOutcome = "applied" | "skipped" | "stopped"; /** The managed-row poll, SINGLE FLIGHT. One read may outlast the interval that scheduled it: the * scatter alone budgets a service resolve, a gather and a reconcile, and the resolve and mint in * front of it are additional. Left unguarded, two reads overlap and are applied in COMPLETION * order rather than request order, so an older answer can land after a newer one and restore the * very rows the newer one retired. That is the fold's own guarantee undone one layer up, and no * test of the fold can see it. * * A tick while a read is in flight is therefore skipped outright rather than queued: the state is * a snapshot of the whole space, so a skipped tick loses nothing that the next one will not carry, * and skipping also bounds how much control traffic a slow mesh can accumulate. Being single * flight is also what keeps a STALE FAILURE from stopping the poll after a newer success, since * there can be no newer success in flight to race. * * Stopping on a failed read is deliberate and reported by the caller: an open mesh with no * supervisor must not knock every tick. */ export declare function createManagedPoller(read: () => Promise, on: { rows(flat: Map): void; partial(silent: string[], failed: { instanceId: string; error: string; }[]): void; stopped(error: string): void; }): { tick(): Promise; }; export declare function controlPs(ctx: ControlCtx): Promise; export {}; //# sourceMappingURL=control.d.ts.map