import { type RoostEvent } from "./events.js"; import type { JobRow } from "./protocol.js"; export declare const CONCIERGE_NAME = "concierge"; /** The job's env says which role the pi extension plays. */ export declare const CONCIERGE_ROLE_ENV = "ROOST_ROLE"; export interface ConciergeConfig { model: string; thinking: string; /** Wakes (digests and heartbeats) an hour at most; events beyond that wait for the next wake. */ wakesPerHour: number; /** A wake even when nothing happened, so a stuck fleet is noticed: `every 15m`, or `off`. */ heartbeat: string; /** It stops being woken once its sessions' cost today reaches this (0: no limit). */ dailyBudgetUsd: number; /** * M45: may it answer a session's question in the user's place? `never` (it suggests; * the user answers), `routine` (proceed/confirm, the obvious default, what is in the * fleet; anything irreversible escalates), `always` (whatever it can; irreversible * questions still escalate). The start; `/concierge answer` changes it for good. */ answer: ConciergeAnswer; /** M45: may it start, stop and restart sessions (`hub_dispatch`, `hub_stop`, `hub_respawn`)? */ act: boolean; } export type ConciergeAnswer = "never" | "routine" | "always"; export declare const CONCIERGE_ANSWERS: readonly ConciergeAnswer[]; /** The policy in force: the setting, until `/concierge answer` or `act` changed it. */ export interface ConciergePolicy { answer: ConciergeAnswer; act: boolean; } export declare const CONCIERGE_DEFAULTS: ConciergeConfig; /** What a session is told when the user undoes an answer the concierge gave it. */ export declare const undoText: (answer: string) => string; /** The `concierge` key of roost.json (user config only), with the defaults for what it leaves out. */ export declare function conciergeFrom(raw: unknown): ConciergeConfig | undefined; /** The heartbeat's interval in ms, or null for `off`. */ export declare function heartbeatMs(c: ConciergeConfig): number | null; /** One line per session, as the concierge sees the fleet. */ export declare function fleetLine(r: JobRow, now?: number): string; /** M46: a standing order: a rule in the user's words the concierge keeps; on a clock, when `when` is set. */ export interface StandingOrder { id: number; text: string; /** M39's vocabulary (`every 30m`, `daily 18:00`, `weekdays 09:00`, `cron "…"`), or null: applied when its condition shows. */ when: string | null; by: "user" | "concierge"; at: number; /** When the concierge last said it applied it, and how often (a clock order's due times move `nextAt` only). */ lastAt: number | null; nextAt: number | null; count: number; } import { type BoardTask } from "./board.js"; export declare const ORDER_MAX = 50; export declare const ORDER_TEXT_MAX = 500; /** One line for an order: `#3 daily 18:00 · say what finished and what is blocked (applied ×2, 1h ago)`. */ export declare function orderLine(o: StandingOrder, now?: number): string; export type WakeWhy = "events" | "heartbeat" | "order"; export interface DigestInput { why: WakeWhy; events: RoostEvent[]; /** The fleet, the concierge's own row left out. */ rows: JobRow[]; sinceAt: number | null; now?: number; /** M46: the standing orders it keeps, and the ones on a clock that are due now. */ orders?: StandingOrder[]; due?: StandingOrder[]; /** M47: the task board (every task; the digest shows the ones not done). */ board?: BoardTask[]; } /** * What the concierge is woken with: the events since its last wake, one line each, and * the fleet as it stands. Wrapped so the model (and the transcript) can tell it from a * peer's message; it carries no instruction the system prompt does not already give. */ export declare function digestText(d: DigestInput): string; /** The concierge's system prompt: what it is, what it may do (the policy in force), how to behave. */ export declare function conciergeSystemPrompt(c: ConciergePolicy): string; /** The hub's one-line view of the concierge. */ export interface ConciergeStatus { on: boolean; id: string | null; /** The job's state, when it has one (null: no job yet). */ state: JobRow["state"] | null; live: boolean; model: string | null; /** Wakes in the last hour, and when it was last woken. */ wakesLastHour: number; lastWakeAt: number | null; /** Events it has not been woken with yet (its own left out): a wake is due, or held. */ behind: number; /** What it spent today, and the budget that stops it. */ costToday: number; budget: number; overBudget: boolean; /** The last thing it told the user (hub_notify). */ notice: { kind: "info" | "need"; text: string; at: number; } | null; /** M45: the policy in force (the setting, or what `/concierge answer|act` set). */ policy: ConciergePolicy; /** M46: how many standing orders it keeps. */ orders: number; /** M45: the last answer it gave a session in the user's place, if any; `undone` once the user withdrew it. */ answered: { id: string; name: string; text: string; at: number; undone: boolean; } | null; /** Its last answer to a question from the hub (`? …`). */ answer: { text: string; at: number; } | null; }