import { z } from 'zod'; /** * Forward Deployed Agent Engineer — daemon-side port of the canonical message * contract (epic #2098, child #4). * * SOURCE OF TRUTH: packages/backend/src/lib/engineer-contract.ts (child #1). * This file is a type-port (agentbrowser → tinynoodle precedent, sanctioned by * the source file's own header): the backend is on zod v3, this package on * zod v4, so the schemas are re-declared here rather than imported. The * envelope is versioned via `v`; contract.test.ts round-trips fixtures * serialized by the backend schemas so drift fails a test instead of a * customer engagement. */ export declare const ENGINEER_METADATA_EVENT_TYPE = "agentcard_engineer_v1"; /** Max serialized-envelope size to also inline as a ```json block in Slack. */ export declare const ENVELOPE_INLINE_LIMIT = 2800; export declare const snippetSchema: z.ZodObject<{ language: z.ZodString; content: z.ZodString; path: z.ZodOptional; }, z.core.$strip>; export declare const issueReportBodySchema: z.ZodObject<{ title: z.ZodString; summary: z.ZodString; environment: z.ZodEnum<{ sandbox: "sandbox"; production: "production"; }>; error: z.ZodOptional; http_status: z.ZodOptional; request_id: z.ZodOptional; }, z.core.$strip>>; context: z.ZodOptional; endpoint: z.ZodOptional; org_client_id: z.ZodOptional; agent: z.ZodOptional>; }, z.core.$strip>>; snippets: z.ZodOptional; }, z.core.$strip>>>; }, z.core.$strip>; export type IssueReportBody = z.infer; export declare const questionBodySchema: z.ZodObject<{ text: z.ZodString; snippets: z.ZodOptional; }, z.core.$strip>>>; }, z.core.$strip>; export type QuestionBody = z.infer; export declare const answerBodySchema: z.ZodObject<{ text: z.ZodString; references: z.ZodOptional>; snippets: z.ZodOptional; }, z.core.$strip>>>; }, z.core.$strip>; export declare const proposalBodySchema: z.ZodObject<{ summary: z.ZodString; instruction: z.ZodString; changes: z.ZodOptional>>; risk: z.ZodEnum<{ high: "high"; low: "low"; medium: "medium"; }>; }, z.core.$strip>; export type ProposalBody = z.infer; export declare const statusBodySchema: z.ZodObject<{ state: z.ZodString; detail: z.ZodOptional; }, z.core.$strip>; /** Daemon-reported record of a human Accept press (acceptance criterion 3). */ export declare const acceptReceiptBodySchema: z.ZodObject<{ proposal_id: z.ZodString; accepted_by_slack_user_id: z.ZodString; accepted_at: z.ZodString; }, z.core.$strip>; export declare const systemBodySchema: z.ZodObject<{ event: z.ZodString; detail: z.ZodOptional; }, z.core.$strip>; /** * Connectivity handshake. `handshake` is sent by the customer daemon on connect * (customer→us); the support agent replies with a canned `handshake_ack` * (us→customer) to confirm the bridge is live. Both carry just a human-readable * greeting `text`; there is no side effect beyond proving the two bots can * reach each other in the channel. */ export declare const handshakeBodySchema: z.ZodObject<{ text: z.ZodString; }, z.core.$strip>; export type HandshakeBody = z.infer; export declare const engineerEnvelopeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{ kind: z.ZodLiteral<"issue_report">; body: z.ZodObject<{ title: z.ZodString; summary: z.ZodString; environment: z.ZodEnum<{ sandbox: "sandbox"; production: "production"; }>; error: z.ZodOptional; http_status: z.ZodOptional; request_id: z.ZodOptional; }, z.core.$strip>>; context: z.ZodOptional; endpoint: z.ZodOptional; org_client_id: z.ZodOptional; agent: z.ZodOptional>; }, z.core.$strip>>; snippets: z.ZodOptional; }, z.core.$strip>>>; }, z.core.$strip>; v: z.ZodLiteral<1>; id: z.ZodString; engagement_id: z.ZodString; ts: z.ZodString; sender: z.ZodEnum<{ support_agent: "support_agent"; customer_daemon: "customer_daemon"; }>; in_reply_to: z.ZodOptional; thread_ref: z.ZodOptional; }, z.core.$strip>, z.ZodObject<{ kind: z.ZodLiteral<"question">; body: z.ZodObject<{ text: z.ZodString; snippets: z.ZodOptional; }, z.core.$strip>>>; }, z.core.$strip>; v: z.ZodLiteral<1>; id: z.ZodString; engagement_id: z.ZodString; ts: z.ZodString; sender: z.ZodEnum<{ support_agent: "support_agent"; customer_daemon: "customer_daemon"; }>; in_reply_to: z.ZodOptional; thread_ref: z.ZodOptional; }, z.core.$strip>, z.ZodObject<{ kind: z.ZodLiteral<"answer">; body: z.ZodObject<{ text: z.ZodString; references: z.ZodOptional>; snippets: z.ZodOptional; }, z.core.$strip>>>; }, z.core.$strip>; v: z.ZodLiteral<1>; id: z.ZodString; engagement_id: z.ZodString; ts: z.ZodString; sender: z.ZodEnum<{ support_agent: "support_agent"; customer_daemon: "customer_daemon"; }>; in_reply_to: z.ZodOptional; thread_ref: z.ZodOptional; }, z.core.$strip>, z.ZodObject<{ kind: z.ZodLiteral<"proposal">; body: z.ZodObject<{ summary: z.ZodString; instruction: z.ZodString; changes: z.ZodOptional>>; risk: z.ZodEnum<{ high: "high"; low: "low"; medium: "medium"; }>; }, z.core.$strip>; v: z.ZodLiteral<1>; id: z.ZodString; engagement_id: z.ZodString; ts: z.ZodString; sender: z.ZodEnum<{ support_agent: "support_agent"; customer_daemon: "customer_daemon"; }>; in_reply_to: z.ZodOptional; thread_ref: z.ZodOptional; }, z.core.$strip>, z.ZodObject<{ kind: z.ZodLiteral<"status">; body: z.ZodObject<{ state: z.ZodString; detail: z.ZodOptional; }, z.core.$strip>; v: z.ZodLiteral<1>; id: z.ZodString; engagement_id: z.ZodString; ts: z.ZodString; sender: z.ZodEnum<{ support_agent: "support_agent"; customer_daemon: "customer_daemon"; }>; in_reply_to: z.ZodOptional; thread_ref: z.ZodOptional; }, z.core.$strip>, z.ZodObject<{ kind: z.ZodLiteral<"accept_receipt">; body: z.ZodObject<{ proposal_id: z.ZodString; accepted_by_slack_user_id: z.ZodString; accepted_at: z.ZodString; }, z.core.$strip>; v: z.ZodLiteral<1>; id: z.ZodString; engagement_id: z.ZodString; ts: z.ZodString; sender: z.ZodEnum<{ support_agent: "support_agent"; customer_daemon: "customer_daemon"; }>; in_reply_to: z.ZodOptional; thread_ref: z.ZodOptional; }, z.core.$strip>, z.ZodObject<{ kind: z.ZodLiteral<"system">; body: z.ZodObject<{ event: z.ZodString; detail: z.ZodOptional; }, z.core.$strip>; v: z.ZodLiteral<1>; id: z.ZodString; engagement_id: z.ZodString; ts: z.ZodString; sender: z.ZodEnum<{ support_agent: "support_agent"; customer_daemon: "customer_daemon"; }>; in_reply_to: z.ZodOptional; thread_ref: z.ZodOptional; }, z.core.$strip>, z.ZodObject<{ kind: z.ZodLiteral<"handshake">; body: z.ZodObject<{ text: z.ZodString; }, z.core.$strip>; v: z.ZodLiteral<1>; id: z.ZodString; engagement_id: z.ZodString; ts: z.ZodString; sender: z.ZodEnum<{ support_agent: "support_agent"; customer_daemon: "customer_daemon"; }>; in_reply_to: z.ZodOptional; thread_ref: z.ZodOptional; }, z.core.$strip>, z.ZodObject<{ kind: z.ZodLiteral<"handshake_ack">; body: z.ZodObject<{ text: z.ZodString; }, z.core.$strip>; v: z.ZodLiteral<1>; id: z.ZodString; engagement_id: z.ZodString; ts: z.ZodString; sender: z.ZodEnum<{ support_agent: "support_agent"; customer_daemon: "customer_daemon"; }>; in_reply_to: z.ZodOptional; thread_ref: z.ZodOptional; }, z.core.$strip>], "kind">; export type EngineerEnvelope = z.infer; export type EngineerEnvelopeKind = EngineerEnvelope['kind']; /** Valid envelope id charset — mirrors the relay's ENVELOPE_ID_RE. */ export declare const ENVELOPE_ID_RE: RegExp; export interface EngineerSlackMetadata { event_type: typeof ENGINEER_METADATA_EVENT_TYPE; event_payload: { envelope_id: string; engagement_id: string; kind: EngineerEnvelopeKind; sender: EngineerEnvelope['sender']; }; } export declare function buildSlackMetadata(envelope: EngineerEnvelope): EngineerSlackMetadata; /** Daemon-handled (customer app, Socket Mode) button action ids — T1 contract. */ export declare const DAEMON_BUTTON_ACTION_IDS: readonly ["engineer_accept", "engineer_decline"]; export type DaemonButtonActionId = (typeof DAEMON_BUTTON_ACTION_IDS)[number]; export declare const engineerButtonValueSchema: z.ZodObject<{ engagementId: z.ZodString; messageId: z.ZodString; }, z.core.$strip>; export type EngineerButtonValue = z.infer; /** Parse a button `value` payload; null on any malformed input (never throws). */ export declare function parseEngineerButtonValue(raw: unknown): EngineerButtonValue | null; /** * THE sender-authentication primitive (verbatim from the backend contract). * The daemon processes a channel message as a command ONLY when the message's * Slack sender is exactly the paired bot's user id (`ourBotUserId` from * GET /engineer/daemon/engagement). Everything else — humans included — is * context, never commands. Deterministic — no heuristics. */ export declare function isFromPairedBot(msg: { user?: string | null; bot_id?: string | null; }, pairedBotUserId: string): boolean; export type SlackBlock = Record; /** * Standard Block Kit blocks for an envelope: kind header, human-readable * summary, and — when it fits — the full envelope in a ```json fenced block * for no-roundtrip agent consumption. Button rows are appended by the poster. */ /** * One-line channel headline: the SHORT text posted at the top level, with the * full detail (renderEnvelopeBlocks) posted as a threaded reply underneath. * Keeps the channel scannable — a reader sees one line per exchange and opens * the thread for the error body, the JSON, and the replies. */ export declare function envelopeHeadline(envelope: EngineerEnvelope): string; export declare function renderEnvelopeBlocks(envelope: EngineerEnvelope): SlackBlock[]; /** Actions row carrying the daemon's Accept/Decline buttons (T1 button contract). */ export declare function acceptDeclineBlock(value: EngineerButtonValue): SlackBlock; /** * Mint a fresh envelope id. Exported so `engineer ask` can PRE-mint the id of * the question it spools (T7): the daemon then ledgers the question under that * exact id, and the support agent's answer threads back via `in_reply_to` — * which is what the ask command blocks on. Idempotent relay ledgering on the * id makes a re-spooled question with the same id a dedupe, not a duplicate. */ export declare function makeEnvelopeId(): string; /** Build a fresh daemon-sent envelope (sender is always customer_daemon here). */ export declare function makeDaemonEnvelope(engagementId: string, kind: K, body: Extract['body'], opts?: { id?: string; inReplyTo?: string; threadRef?: string; }): EngineerEnvelope; //# sourceMappingURL=contract.d.ts.map