import { fetchPeers, type BrokerPeer } from './peerBroker.js'; export { fetchPeers, type BrokerPeer }; /** * The daemon's host identity for presence + command targeting. Defaults to * os.hostname() but is overridable via DECIBEL_PRESENCE_HOST — needed where the * OS hostname isn't a stable/unique daemon identity (containers with shared * hostnames, or two daemons on one machine, e.g. a rolling restart or a test * harness). target_host on hq.agent_commands matches this, so it must be the same * value the presence writer stamps. Shared by the dispatcher (agentCommands.ts). */ export declare function resolveHost(): string; export declare function serviceClient(): import("@supabase/supabase-js").SupabaseClient | null; export type DbClient = NonNullable>; export declare function resolveProjectId(client: DbClient, cwd: string): Promise; /** * Derive the DURABLE address for a session. * * Must be stable across restarts, so anything process-scoped is disqualified: * not the session key, not a PID, not a TTY. The claude-peers broker id looks * stable but is not — it carries a random suffix (`decibel-hq-nby9`), so a * restart would silently mint a second agent and split the thread history. * * Repo identity + runtime is the stable pair: the same checkout on the same * runtime is the same logical agent, session after session. * * DELIBERATELY NOT caller-supplied. `reg.agent` is an untrusted display label * from a local process, and a local caller that could name its own durable * address could claim an EXISTING agent's name — resolve_agent_session picks * the most recently seen session, so a frequent heartbeater would capture that * agent's inbound mail. That is the principal-not-label gap (EPIC-0007) which * Ben accepted as risk for EPIC-0037; accepting it is not a reason to widen it. * An operator can still set the name explicitly via DECIBEL_AGENT_NAME, which * is daemon-scoped env (trusted) rather than per-request payload. */ export declare function deriveAgentName(input: { gitRoot?: string | null; cwd?: string | null; runtime: string; host: string; }): string; /** * Resolve (or create) the durable hq.agents row for `name` and return its id. * * Returns null rather than throwing when the table is absent — this ships * BEFORE decibel-hq applies the post-office migration, and presence writing * must keep working untouched in the meantime. When the migration lands the * same code starts populating agent_id with no redeploy. * * `runtime` is written as a self-declared LABEL only. HQ's schema comment is * explicit that it is never a trust signal, so nothing here gates on it. */ export declare function resolveAgentId(client: DbClient, name: string, runtime: string): Promise; /** Test seam: drop memoised ids so a test can observe a fresh resolve. */ export declare function __resetAgentIdCache(): void; export interface AgentRosterEntry { id: string; name: string; runtime: string; role: string | null; capabilities: string[]; /** Durable lifecycle from hq.agents: 'active' | 'retired'. NOT liveness. */ status: string; /** Liveness: does a live session currently resolve for this agent? */ online: boolean; /** The session a message would be delivered into right now, or null. */ session_key: string | null; last_seen_at: string | null; } /** * The agents.list roster: hq.agents LEFT JOIN liveness. * * The roster is the DURABLE agents, each annotated with whether a live session * resolves. An agent that exists but is offline MUST appear, marked offline, * rather than vanish — a roster built from live sessions would silently drop * exactly the agent you are trying and failing to reach, which is the same * failure class as addressing a dead session. * * Two queries and a join in memory rather than one call to * hq.resolve_agent_session per agent, which would be N round trips to render * one board. * * CLOCK CAVEAT, and it is why this is a DISPLAY path only: the cutoff below is * computed from the daemon's clock, while resolve_agent_session uses the * database's now(). Skew between them can disagree at the 60s boundary. The * authoritative answer at DELIVERY time is HQ's function, never this. Do not * route a message using this roster's `online`. * * Returns null (not an empty roster) when the table is absent, so a caller can * distinguish "no agents" from "post office not deployed yet". */ export declare function listAgentRoster(client: DbClient): Promise; export interface LocalAgentRegistration { session_key: string; runtime: string; agent?: string | null; cwd?: string | null; summary?: string | null; meta?: Record; status?: 'active' | 'ended'; } /** Strip control chars/null bytes and cap length. Empty-after-clean → null. */ export declare function sanitizeText(s: string | null | undefined, maxLen: number): string | null; /** * Flatten meta to display-safe primitives: strings cleaned + capped, numbers/ * booleans/null kept, nested objects/arrays dropped (HQ typeof-guards numeric * meta and renders strings as text). If the result still exceeds META_MAX_BYTES, * drop it entirely — the caller re-adds the trusted last_action_at. */ export declare function sanitizeMeta(meta: Record | undefined): Record; /** * Upsert a local-runtime session into hq.agent_sessions (register or heartbeat). * Returns true on success, false if Supabase is unconfigured or the write failed. * Reuses the presence writer's org config + cwd→project resolution. */ export declare function writeLocalAgentSession(reg: LocalAgentRegistration): Promise; /** Start the presence writer loop. Returns a stop function. No-ops if Supabase unconfigured. */ export declare function startPresenceWriter(): () => void; //# sourceMappingURL=agentPresence.d.ts.map