import { type TelegramChannelRole } from './instructions.js'; /** Task 1516 — the dispatcher's operator-provenance marker, present only on a * scheduled inject. A local copy of the shape (this package never cross-imports * platform/ui). Kept byte-identical to the whatsapp/webchat twins. */ export interface ScheduleProvenance { accountId: string; eventId: string; authoredBy: string[]; createdByTool: string | null; dispatchedAt: string; } /** * Task 1516 — render the dispatcher's operator-provenance as a platform-verified * preamble. Every value is dispatcher-stamped (an inbound message cannot produce * this block), so the grounding treats a turn opening with it as an authorised * standing automation. Copy stays operator-clean (no task numbers, repo paths, or * em-dashes). Byte-identical to the whatsapp/webchat twins. */ export declare function composeScheduleMarker(pv: ScheduleProvenance): string; export interface InboundPayload { /** The telegram conversation key this payload is for. */ key: string; /** The operator's typed message, verbatim — multi-line content is preserved. */ text: string; /** Per-message id, for dedup/observability. */ messageId: string; /** Task 1378 — the inbound's origin: 'user' (a real telegram message) or * 'schedule' (a synthetic inbound injected by the scheduler). Carried only * into the turn's structured log line. Absent on legacy frames = 'user'. */ source?: 'user' | 'schedule'; /** Task 1486 — the account's active standing-rules block (already formatted as * `## Standing rules`), fetched and attached by the gateway. Prepended above * `## Context` for ADMIN turns only; a public visitor never receives it. * Absent/blank when the account has no active rules. */ standingRules?: string; /** Task 1516 — the dispatcher's operator-provenance marker on a scheduled * inject; rendered above `## Context` (and above the rules block) for ADMIN * turns only. Absent on a real inbound. */ scheduleProvenance?: ScheduleProvenance; } /** The composed content the agent receives, plus the inner payload's byte * length for the observability line. */ export interface ComposedInbound { content: string; payloadBytes: number; } /** Frame an ADMIN inbound as `## Context` (the typed message) then * `## Instruction` (the routing + capability-denial directive), so the * directive rides every turn. PUBLIC stays plain: the public reader echoes the * visitor's own inbound back to them, so wrapping it would leak the internal * directive to the visitor. `payloadBytes` is the inner message length, * excluding any wrapper — matching the WhatsApp `[reframe]` semantics. */ export declare function composeContent(p: InboundPayload, role: TelegramChannelRole): ComposedInbound; /** Defence in depth: this server serves exactly one key. Even though the * gateway only streams that key's messages, refuse anything else before it * reaches the session. */ export declare function acceptsKey(myKey: string, p: { key: string; }): boolean; /** Build the body for POST /tg-channel/reply. The reply tool exposes only * `text` to the model; the key is the server's fixed key (from spawn env), * never trusted from the model, so a compromised turn cannot redirect a reply * to a different conversation. */ export declare function buildReplyPostBody(myKey: string, text: string): { key: string; text: string; }; /** Build the body for POST /tg-channel/received — the receipt ack the channel * server sends after it has emitted a drained inbound to the agent, so the * gateway marks it delivered instead of sweeping it as drain-undelivered. The * key is the server's fixed key, never model-supplied. */ export declare function buildReceivedPostBody(myKey: string, messageId: string): { key: string; messageId: string; }; /** * Build the body for POST /tg-channel/turn-end — the turn-end decision the * channel server posts once per turn. `key` + `sessionId` are the server's fixed * values (spawn env), never model-supplied. `replied` is whether a telegram * reply tool_use occurred in the turn. `interactive` is true when the triggering * inbound was a real person (source !== 'schedule'). `finalText` is the trimmed, * outbound-guarded end-turn assistant text — the interactive delivery fallback * restored in Task 1539: for an interactive turn the gateway force-sends it when * non-empty (delivered=fallback), covering a turn that never called reply AND the * ack-then-plain-text shape. A scheduled turn ships an empty `finalText` and * stays silent, mirroring the WhatsApp twin. */ export declare function buildTurnEndPostBody(myKey: string, sessionId: string, replied: boolean, interactive: boolean, finalText: string): { key: string; sessionId: string; replied: boolean; interactive: boolean; finalText: string; }; /** Retry an idempotent POST until it is accepted or the attempt cap is * reached. `attempt` returns whether the POST was accepted; the helper * returns on the first acceptance, otherwise sleeps `delayMs` and retries, * up to `attempts` total. `sleep` is injected so tests run without real * timers. */ export declare function postWithRetry(attempt: () => Promise, opts: { attempts: number; delayMs: number; sleep: (ms: number) => Promise; }): Promise; /** Map a non-OK /tg-channel/reply response into an actionable MCP error string. * Falls back to the bare status when the body carries no usable reason. (No * terminal/logged-out branch — there is no external transport to log out of.) */ export declare function buildReplyError(status: number, body: unknown): string; export declare const INTERNAL_LEAK_PATTERNS: { name: string; re: RegExp; }[]; export interface Redaction { pattern: string; match: string; } export declare function redactInternalLeaks(text: string): { clean: string; redactions: Redaction[]; }; //# sourceMappingURL=notification.d.ts.map