/** * Offline push dispatch (push-backend-requirements §5): one helper gates every * event hook. Push fires only when the bridge has ZERO connected clients (an * online client renders the event live) and push is ACTIVE — the single * predicate from push/config.ts. Fire-and-forget: send failures warn and never * reach the event path. */ import type { ZcodeAcpServer } from "../server.js"; import { type WeComSender } from "./wecom.js"; export type PushKind = "permission" | "question" | "run" | "task" | "test" | "turn" | "goal" | "compact" | "workflowStage" | "quota"; /** Settled kinds routed through {@link pushSettled} (§5.2 — per-kind switches). */ export type PushSettledKind = Extract; /** * " / " source label for settled pushes. It rides the * leading bracket (never the body — `contentDetail: "minimal"` strips bodies), * replacing the kind prefix whose information the title tail already carries. * TOTAL (never throws): the push path is fire-and-forget by contract, and the * server handle may be a partial object in tests. */ export declare function pushSourceLabel(server: ZcodeAcpServer, acpSid?: string): string; export interface PushEventData { kind: PushKind; title: string; body?: string; /** * Source label (` / `, see {@link pushSourceLabel}). When * present it REPLACES the kind in the leading bracket — `[kind] title` * would duplicate what the title tail already says (e.g. "turn completed"), * and the bracket is the one slot minimal mode never strips. */ label?: string; } /** Test hook: forget the process-wide sender. */ export declare function resetPushSenderForTests(): void; /** Test hook: inject a fake sender (null = inactive). */ export declare function setPushSenderForTests(s: WeComSender | null): void; /** * Render the contracted WeCom text: `[] ` + optional * body line. A `label` replaces the kind in the leading bracket (see * {@link PushEventData.label}). Under `contentDetail: "minimal"` the body * carries no business strings (§4 — content transits Tencent) — the bracket * prefix + title identify the event. */ export declare function renderPushContent(cfg: { contentDetail: "full" | "minimal"; }, data: PushEventData): string; /** §5: the single gated dispatch helper — offline + ACTIVE or nothing. */ export declare function pushIfOffline(server: ZcodeAcpServer, data: PushEventData): void; /** * Stamp a USER-originated action (session/prompt, session/cancel) as bridge * presence — the anchor of {@link pushSettled}'s quiet window. Only real user * entry points may call this: bridge-internal rounds (sandbox allow-restart * continuations, goal-loop rounds) must NOT refresh the stamp, or a settle * minutes after the user left would be misread as "user still at the desk". */ export declare function noteUserActivity(server: ZcodeAcpServer): void; /** * §5.2 settled-event dispatch (turn end / goal loop stop / workflow run / * background task / auto-compact settle): NO client-presence gate — an online * client renders the event live but cannot wake the user's phone, and the * settled event itself IS the "come back" signal. Each kind is individually * switchable via `push.notify.<kind>` (default on); the shared ACTIVE * predicate still applies. * * Quiet window: a settle within `quietMs` (default 30s, 0 disables) of the * last user prompt/cancel is suppressed — the user is still at the desk, the * ping would be noise (a turn that completes seconds after its prompt never * needs a phone). Offline interaction pushes (§5.1) are NOT windowed: they * fire only with zero connected clients, where recency means the connection * DIED, not that the user is watching. */ export declare function pushSettled(server: ZcodeAcpServer, data: PushEventData & { kind: PushSettledKind; }): void; /** * §5.7 quota threshold warnings — WARNING class, not a settle: no client * gate (an online client cannot wake the phone) and NO quiet window — a * threshold crossing happens exactly while the user is burning quota, i.e. * nearly always inside the quiet window, so windowing would silence the * warning precisely when it matters. Gated by `push.notify.quota` (default * on) and the shared ACTIVE predicate like every other kind. Takes no server * handle: quota is account-level, the bracket carries the kind. */ export declare function pushQuotaWarning(data: PushEventData & { kind: "quota"; }): void; /** * Arm the watchdog for one dispatched user-facing ask (permission, * elicitation, AskUserQuestion, plan approval, sandbox grant). Fire-and-forget: * at the kind's delay (see {@link askWatchdogDelayMs}) with the ask still * pending and nothing yet notified, push the same derived payload — clients * connected or not. */ export declare function armAskWatchdog(method: string, params?: unknown, label?: string): void; /** Settle one ask: clear the timer and reset the notification slot once none remain. */ export declare function clearAskWatchdog(): void; /** Test hook: drop the whole watchdog slot (pending count, timer, notified flag). */ export declare function resetAskWatchdogForTests(): void; /** * §5.1: derive the permission/question payload at the zero-clients branch of * `requestAny` (broadcast.ts) — the single hook covering permission requests, * AskUserQuestion, and elicitation. Gated by `notify.ask` (default on); a * dispatched push marks the notification slot so the watchdog does not * duplicate it. */ export declare function pushInteractionIfOffline(server: ZcodeAcpServer, method: string, params?: unknown): void; /** * §7 test push — sends REGARDLESS of client presence (it verifies the channel, * not an offline event). Structured result for the REST route. */ export declare function sendTestPush(title: string): Promise<{ ok: true; sent: number; } | { ok: false; error: "push_disabled" | "send_failed"; message?: string; }>; //# sourceMappingURL=push.d.ts.map