/** * HQ control-plane command definitions — typed payloads for the commands the * HQ dashboard can enqueue to connected machines (Phase 3+ of the HQ command * center). These are carried over the existing `HqQueuedCommand` wire shape * (`{commandId, type, payload, …}`) whose `type`/`payload` were previously * type-erased. This module gives them a discriminated union for type-safe * dispatch on the client side (Phase 4). * * Security model: `run-command` (raw shell) is gated by a per-token * `control.execute` capability AND an operator opt-in; the other four commands * route through the agent's own decision loop / mailbox and inherit their * existing guardrails. See `docs/plans/hq-command-center-2026-07.md`. * * @module hq/commands */ import type { HqQueuedCommand } from './protocol/fleet.js'; /** HQ_COMMAND_TYPES — the full set of recognized command `type` strings. */ export declare const HQ_COMMAND_TYPES: readonly ['steer', 'btw', 'queue', 'abort', 'spawn', 'broadcast', 'run-command']; export type HqCommandType = (typeof HQ_COMMAND_TYPES)[number]; /** Inject a steer text into a target agent's conversation. */ export interface HqSteerCommand { type: 'steer'; /** Target agent address: a unique id (`leader@`), an alias (`leader`), or `*` for all. */ to: string; subject: string; body: string; priority?: 'low' | 'normal' | 'high'; } /** * Post a non-urgent FYI (`btw`) into a target agent's mailbox. Unlike a steer, * a btw is absorbed as context — it does not demand the agent change course. * Same wire shape as steer; only the emitted mailbox `type` differs. */ export interface HqBtwCommand { type: 'btw'; /** Target agent address: a unique id (`leader@`), an alias (`leader`), or `*` for all. */ to: string; subject: string; body: string; priority?: 'low' | 'normal' | 'high'; } /** * Queue a prompt/note (`queue`) for a target agent. Delivered as a plain * `note` mailbox message the agent picks up before its next step — used when * the prompt should wait its turn rather than steer the current operation. */ export interface HqQueueCommand { type: 'queue'; /** Target agent address: a unique id (`leader@`), an alias (`leader`), or `*` for all. */ to: string; subject: string; body: string; priority?: 'low' | 'normal' | 'high'; } /** Abort a running agent run or fleet. */ export interface HqAbortCommand { type: 'abort'; /** `'leader'` aborts the session leader; a subagentId aborts one agent; `'fleet'` stops all. */ target: 'leader' | 'fleet' | string; } /** Spawn a subagent of the given role. */ export interface HqSpawnCommand { type: 'spawn'; role: string; /** Optional task description for dispatch routing. */ task?: string; maxIterations?: number; } /** Broadcast a mailbox message to all agents on the target's project. */ export interface HqBroadcastCommand { type: 'broadcast'; subject: string; body: string; priority?: 'low' | 'normal' | 'high'; } /** Run a shell command on the target machine. GATED by `control.execute`. */ export interface HqRunCommandCommand { type: 'run-command'; command: string; /** Optional working directory (defaults to the agent's project root). */ cwd?: string; } export type HqCommand = HqSteerCommand | HqBtwCommand | HqQueueCommand | HqAbortCommand | HqSpawnCommand | HqBroadcastCommand | HqRunCommandCommand; /** * Validate that an inbound `HqQueuedCommand` has a recognized `type` and a * minimally well-formed payload. Returns the narrowed command on success, or * `null` when the command should be rejected. * * This is a shape check, not a security gate — capability enforcement happens * at enqueue time (browser token must have `control.enqueue`) and at execute * time (`run-command` requires `control.execute`). */ export declare function validateHqCommand(queued: HqQueuedCommand): HqCommand | null; export interface HqCommandAuditEntry { commandId: string; type: HqCommandType; clientId: string; /** Who enqueued the command (browser token id, or 'anonymous' in open mode). */ enqueuedBy: string; enqueuedAt: string; status: 'queued' | 'delivered' | 'acked'; /** Ack status when the client has responded. */ ackStatus?: 'accepted' | 'completed' | 'failed' | 'rejected'; ackMessage?: string; ackedAt?: string; } /** * In-memory command audit ring. Capped for cheap reads. When an `onPersist` * callback is wired, every record/update also sinks a snapshot of the entry to * the caller's durable store (e.g. HQ's `commands.jsonl`) so history survives * restarts. The ring remains the read path for `/api/commands`. */ export declare class HqCommandAuditLog { private readonly entries; private readonly max; private readonly onPersist?; constructor(max?: number, onPersist?: ((entry: HqCommandAuditEntry) => void) | undefined); record(entry: HqCommandAuditEntry): void; update(commandId: string, patch: Partial): void; get(commandId: string): HqCommandAuditEntry | undefined; /** Update only when the command belongs to the authenticated client. */ updateForClient(commandId: string, clientId: string, patch: Partial): boolean; /** Seed the ring from a durable store on boot (no persist callback fired). */ seed(entries: readonly HqCommandAuditEntry[]): void; recent(limit?: number): HqCommandAuditEntry[]; } //# sourceMappingURL=commands.d.ts.map