import { type Static } from '@sinclair/typebox'; import { type NotificationMediaType, type QuestionT, type Platform } from './notification.js'; import type { CompanionReceiptState, DeliveryState, OverallState, EvidenceStage } from './status.js'; import type { AnswerVersionView, SessionPresenceView } from './sessions.js'; import { type AffectedOperation, type ClientCapability, type DeviceDerivedStatus, type MachineDerivedStatus, type SupportAssessment, type SupportState } from './compatibility.js'; /** * REST v1 wire contract shared by server, CLI, dashboard, and Companion App. * * This is the one declaration of the served wire. The private contracts * package re-exports it and adds only the shapes clients never exchange, so * a field documented here is a field the server accepts or returns. */ /** * Default for accounts without a persisted preference. The server applies this * value when reading the setting; clients never infer a missing wire field. */ export declare const DEFAULT_AGENT_ACKNOWLEDGEMENT_TEXT_ENABLED = true; /** * Send Delay choices in seconds: the Companion-side hold between pressing send * and an in-app answer, Answer Edit, or Session Note leaving the device. Zero is * "Off". Native notification actions always send immediately. */ export declare const SEND_DELAY_SECONDS_OPTIONS: readonly [0, 3, 5, 10]; export type SendDelaySeconds = (typeof SEND_DELAY_SECONDS_OPTIONS)[number]; export declare const DEFAULT_SEND_DELAY_SECONDS: SendDelaySeconds; export declare const SendDelaySecondsSchema: import("@sinclair/typebox").TUnion[]>; /** * `agent_acknowledgement_text_enabled` is the one account preference over * Agent Acknowledgements, and it governs text only. It applies when the * submitting CLI advertised the acknowledgement job; turning it off drops the * agent's brief written reply, never the receipt itself. * * `send_delay_seconds` is the Account's Send Delay. Servers that predate it * omit the field, which a Companion App reads as "not offered" rather than * inferring a value. */ export declare const AccountPreferences: import("@sinclair/typebox").TObject<{ agent_acknowledgement_text_enabled: import("@sinclair/typebox").TBoolean; send_delay_seconds: import("@sinclair/typebox").TOptional[]>>; }>; export type AccountPreferencesT = Static; export type AccountPreferencesResponse = AccountPreferencesT; /** A partial update: each present field is written; at least one must be present. */ export declare const UpdateAccountPreferencesRequest: import("@sinclair/typebox").TObject<{ agent_acknowledgement_text_enabled: import("@sinclair/typebox").TOptional; send_delay_seconds: import("@sinclair/typebox").TOptional[]>>; }>; export type UpdateAccountPreferencesRequestT = Static; export declare const AccountSoundDefaults: import("@sinclair/typebox").TObject<{ sounds: import("@sinclair/typebox").TObject<{ update: import("@sinclair/typebox").TOptional; question: import("@sinclair/typebox").TOptional; done: import("@sinclair/typebox").TOptional; failed: import("@sinclair/typebox").TOptional; blocked: import("@sinclair/typebox").TOptional; }>; }>; export type AccountSoundDefaultsT = Static; export type AccountSoundDefaultsResponse = AccountSoundDefaultsT; export declare const UpdateAccountSoundDefaultsRequest: import("@sinclair/typebox").TObject<{ sounds: import("@sinclair/typebox").TObject<{ update: import("@sinclair/typebox").TOptional; question: import("@sinclair/typebox").TOptional; done: import("@sinclair/typebox").TOptional; failed: import("@sinclair/typebox").TOptional; blocked: import("@sinclair/typebox").TOptional; }>; }>; export type UpdateAccountSoundDefaultsRequestT = AccountSoundDefaultsT; /** * Stable access state returned to every authenticated client. `active` is * intentionally separate from the reason so later subscription and durable * payment-exemption decisions can extend the source without changing the * no-plan boundary or making Alpha look permanent. */ export declare const ACCESS_STATUSES: readonly ["no_active_plan", "active"]; export type AccountAccessStatus = (typeof ACCESS_STATUSES)[number]; /** Current Alpha source plus explicit slots for later paid V1 sources. */ export declare const ACCESS_REASONS: readonly ["no_active_grant", "alpha_grant", "subscription", "payment_exemption"]; export type AccountAccessReason = (typeof ACCESS_REASONS)[number]; export interface AccountAccessResponse { status: AccountAccessStatus; reason: AccountAccessReason; /** Alpha grants are temporary; future sources may also carry an expiry. */ expires_at: string | null; /** * The account's sign-in email when the server knows it. Used at the * companion-device hop so install/sign-in copy can name the exact address * that must match — never guess, and omit only when the server has none. */ email: string | null; /** * Whether the server has opened public purchase. Decided by the server and * carried on the call every client already makes, because a client that * compiled its own copy of the instant keeps offering the wrong errand to * every install that has not been updated. */ public_v1_cutover: boolean; } export declare const BeginPairingRequest: import("@sinclair/typebox").TObject<{ machine_name: import("@sinclair/typebox").TString; /** SHA-256 hex of the locally generated 256-bit machine secret. */ credential_hash: import("@sinclair/typebox").TString; /** SHA-256 hex of the one-time poll verifier; proves the poller began this pairing. */ poll_verifier_hash: import("@sinclair/typebox").TString; /** SHA-256 hex of the one-time browser confirmation secret. */ confirmation_hash: import("@sinclair/typebox").TString; }>; export type BeginPairingRequestT = Static; export interface BeginPairingResponse { pairing_id: string; /** Short human-checkable code shown in both CLI and approval page. */ code: string; approve_url: string; expires_at: string; poll_interval_seconds: number; } export declare const PollPairingRequest: import("@sinclair/typebox").TObject<{ poll_verifier: import("@sinclair/typebox").TString; }>; export type PollPairingRequestT = Static; /** The initiator explicitly selects Account-email targeting; response is non-enumerating. */ export declare const PairingNotificationRequest: import("@sinclair/typebox").TObject<{ poll_verifier: import("@sinclair/typebox").TString; email: import("@sinclair/typebox").TString; }>; export type PairingNotificationRequestT = Static; /** * Proof carried by every authenticated dashboard pairing operation. The * short code is human-checkable; the high-entropy secret is transported only * in the approval URL fragment and is never sent by a browser GET. */ export declare const PAIRING_CODE_PATTERN_SOURCE = "^[23456789ABCDEFGHJKMNPQRSTUVWXYZ]{3}-[23456789ABCDEFGHJKMNPQRSTUVWXYZ]{3}$"; export declare const PAIRING_CONFIRMATION_SECRET_PATTERN_SOURCE = "^[A-Za-z0-9_-]{43}$"; export declare const PairingProofRequest: import("@sinclair/typebox").TObject<{ code: import("@sinclair/typebox").TString; confirmation_secret: import("@sinclair/typebox").TString; }>; export type PairingProofRequestT = Static; export interface PollPairingResponse { /** * `no_active_plan` is set when the pairing initiator's poll verifier is * valid and the pending handshake has been marked by an authenticated * Request Alpha access errand that proved the approval link. Lookup alone * never sets this status. The CLI should stop polling and surface * `next_action` instead of waiting out the pairing TTL. */ status: 'pending' | 'approved' | 'expired' | 'denied' | 'no_active_plan'; machine_id?: string; /** Present when status is `no_active_plan`; a concrete path to request access. */ next_action?: string; } export declare const ALPHA_ACCESS_DISTRIBUTION_LANES: readonly ["iphone_testflight", "android_firebase"]; export type AlphaAccessDistributionLane = (typeof ALPHA_ACCESS_DISTRIBUTION_LANES)[number]; /** Dashboard Account query key that may preselect one Distribution Lane. */ export declare const ALPHA_ACCESS_LANE_QUERY_PARAM: "distribution_lane"; export declare const AlphaAccessDistributionLaneSchema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"iphone_testflight">, import("@sinclair/typebox").TLiteral<"android_firebase">]>; /** Accept only the two active lanes; unknown or absent values preselect nothing. */ export declare function parseAlphaAccessLaneHint(value: string | null | undefined): AlphaAccessDistributionLane | null; export declare const RequestAlphaAccessRequest: import("@sinclair/typebox").TObject<{ distribution_lanes: import("@sinclair/typebox").TArray, import("@sinclair/typebox").TLiteral<"android_firebase">]>>; pairing: import("@sinclair/typebox").TOptional>; }>; export type RequestAlphaAccessRequestT = Static; export interface AlphaAccessRequestView { status: 'requested'; distribution_lanes: AlphaAccessDistributionLane[]; requested_at: string; updated_at: string; } export interface AlphaAccessRequestResponse { public_v1_cutover: boolean; request: AlphaAccessRequestView | null; } /** * `stopped` means the originating CLI was told this handshake could not * continue and exited without storing a credential. Approving afterwards would * mint an Approved Machine nobody holds, so the browser must neither offer it * nor claim the terminal will pick it up. */ export interface PairingDetailsResponse { pairing_id: string; machine_name: string; code: string; status: 'pending' | 'approved' | 'expired' | 'denied' | 'stopped'; expires_at: string; } export interface MachineSummary { machine_id: string; name: string; status: 'active' | 'revoked'; approved_at: string; revoked_at: string | null; last_seen_at: string | null; cli_version: string | null; capabilities: ClientCapability[]; support: SupportAssessment; support_state: SupportState; derived_status: MachineDerivedStatus; /** Null while this Approved Machine can send. Optional updates never appear here. */ status_message: string | null; } export interface ListMachinesResponse { machines: MachineSummary[]; } export declare const RegisterInstallationRequest: import("@sinclair/typebox").TObject<{ /** Stable random identifier generated once per app installation. */ installation_id: import("@sinclair/typebox").TString; /** Account-local continuity across sign-out; never an authorization token. */ recovery_installation_id: import("@sinclair/typebox").TOptional; platform: import("@sinclair/typebox").TUnion[]>; display_name: import("@sinclair/typebox").TString; /** Marketing version. Inventory only; capabilities remain routing authority. */ app_version: import("@sinclair/typebox").TString; /** Platform build identifier. Inventory only; capabilities remain routing authority. */ app_build: import("@sinclair/typebox").TOptional; os_version: import("@sinclair/typebox").TOptional; /** Named jobs this exact installation can perform. Absent means baseline receive only. */ capabilities: import("@sinclair/typebox").TOptional[]>>>; }>; export type RegisterInstallationRequestT = Static; export interface RegisterInstallationResponse { device_id: string; recovery_installation_id: string; /** Omitted by servers released before compatibility inventory. */ support?: SupportAssessment; } export declare const ApnsRegistrationRequest: import("@sinclair/typebox").TObject<{ provider: import("@sinclair/typebox").TLiteral<"apns">; environment: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"development">, import("@sinclair/typebox").TLiteral<"production">]>; /** Hex APNs device token as handed to the Companion App. */ token: import("@sinclair/typebox").TString; }>; export declare const FcmRegistrationRequest: import("@sinclair/typebox").TObject<{ provider: import("@sinclair/typebox").TLiteral<"fcm">; /** Opaque Firebase Installation ID supplied by the current Android registration path. */ fid: import("@sinclair/typebox").TString; }>; /** * A desktop Companion App receives over its own changes feed, so it registers * no token: the service routes to it while that feed is being read. */ export declare const StreamRegistrationRequest: import("@sinclair/typebox").TObject<{ provider: import("@sinclair/typebox").TLiteral<"stream">; }>; /** Provider-specific registration shapes; only APNs carries an environment. */ export declare const PutRegistrationRequest: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{ provider: import("@sinclair/typebox").TLiteral<"apns">; environment: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"development">, import("@sinclair/typebox").TLiteral<"production">]>; /** Hex APNs device token as handed to the Companion App. */ token: import("@sinclair/typebox").TString; }>, import("@sinclair/typebox").TObject<{ provider: import("@sinclair/typebox").TLiteral<"fcm">; /** Opaque Firebase Installation ID supplied by the current Android registration path. */ fid: import("@sinclair/typebox").TString; }>, import("@sinclair/typebox").TObject<{ provider: import("@sinclair/typebox").TLiteral<"stream">; }>]>; export type PutRegistrationRequestT = Static; export interface PutRegistrationResponse { registration_version: number; } export declare const ReportHealthRequest: import("@sinclair/typebox").TObject<{ permission_status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"authorized">, import("@sinclair/typebox").TLiteral<"provisional">, import("@sinclair/typebox").TLiteral<"denied">, import("@sinclair/typebox").TLiteral<"not_determined">]>; alerts_enabled: import("@sinclair/typebox").TBoolean; }>; export type ReportHealthRequestT = Static; export interface RoutableDevice { device_id: string; display_name: string; platform: Platform; permission_status: string; registration_healthy: boolean; app_version: string; app_build: string | null; os_version: string | null; capabilities: ClientCapability[]; support: SupportAssessment; support_state: SupportState; derived_status: DeviceDerivedStatus; /** Exactly one dashboard status; null means working. */ status_message: string | null; last_seen_at: string | null; } export interface ListDevicesResponse { devices: RoutableDevice[]; } /** Canonical URL-safe Notification Request identity accepted from a client. */ export declare const REQUEST_ID_PATTERN = "^req_[A-Za-z0-9_-]{22,24}$"; export declare const SubmitNotificationRequest: import("@sinclair/typebox").TObject<{ /** Stable caller-generated identity for crash-safe submission replay. */ request_id: import("@sinclair/typebox").TOptional; idempotency_key: import("@sinclair/typebox").TString; draft: import("@sinclair/typebox").TObject<{ schema_version: import("@sinclair/typebox").TLiteral<1>; kind: import("@sinclair/typebox").TOptional[]>>; lifecycle: import("@sinclair/typebox").TOptional[]>; state: import("@sinclair/typebox").TOptional[]>>; retires_request_id: import("@sinclair/typebox").TOptional; }>>; project: import("@sinclair/typebox").TOptional; source: import("@sinclair/typebox").TOptional; session_label: import("@sinclair/typebox").TOptional; session_label_source: import("@sinclair/typebox").TOptional, import("@sinclair/typebox").TLiteral<"semantic">]>>; session_label_previous_source: import("@sinclair/typebox").TOptional>; harness: import("@sinclair/typebox").TOptional; branch: import("@sinclair/typebox").TOptional; worktree: import("@sinclair/typebox").TOptional; }>>; presentation: import("@sinclair/typebox").TObject<{ title: import("@sinclair/typebox").TString; summary: import("@sinclair/typebox").TString; body: import("@sinclair/typebox").TOptional; media: import("@sinclair/typebox").TOptional; }>>>; }>; targets: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{ mode: import("@sinclair/typebox").TLiteral<"all">; }>, import("@sinclair/typebox").TObject<{ mode: import("@sinclair/typebox").TLiteral<"selected">; device_ids: import("@sinclair/typebox").TArray; }>]>; delivery: import("@sinclair/typebox").TObject<{ ttl_seconds: import("@sinclair/typebox").TInteger; collapse_key: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>; }>; reply: import("@sinclair/typebox").TOptional; recommended: import("@sinclair/typebox").TOptional>; }>>>; multi: import("@sinclair/typebox").TOptional; }>>; }>>; platform: import("@sinclair/typebox").TOptional>; badge: import("@sinclair/typebox").TOptional>; thread_id: import("@sinclair/typebox").TOptional>; category: import("@sinclair/typebox").TOptional; interruption_level: import("@sinclair/typebox").TOptional[]>>; relevance_score: import("@sinclair/typebox").TOptional>; target_content_id: import("@sinclair/typebox").TOptional>; custom_data: import("@sinclair/typebox").TOptional>; }>>; macos: import("@sinclair/typebox").TOptional>; badge: import("@sinclair/typebox").TOptional>; thread_id: import("@sinclair/typebox").TOptional>; category: import("@sinclair/typebox").TOptional; interruption_level: import("@sinclair/typebox").TOptional[]>>; relevance_score: import("@sinclair/typebox").TOptional>; target_content_id: import("@sinclair/typebox").TOptional>; custom_data: import("@sinclair/typebox").TOptional>; }>>; android: import("@sinclair/typebox").TOptional>; thread_id: import("@sinclair/typebox").TOptional>; custom_data: import("@sinclair/typebox").TOptional>; }>>; windows: import("@sinclair/typebox").TOptional>; }>>; linux: import("@sinclair/typebox").TOptional>; }>>; }>>; }>; }>; export type SubmitNotificationRequestT = Static; export interface DeliveryOutcome { delivery_id: string; device_id: string; device_name: string; state: DeliveryState; attempts: number; provider_status: number | null; provider_reason: string | null; provider_id: string | null; updated_at: string; } export interface SubmissionWarning { path: string; message: string; code?: 'capability_downgrade' | 'targets_omitted'; affected_operation?: AffectedOperation; device_ids?: string[]; device_names?: string[]; missing_capabilities?: ClientCapability[]; } export interface SubmissionReceipt { request_id: string; /** Committed reply deadline; null when this request did not ask for a reply. */ reply_expires_at: string | null; /** * Immutable snapshot: true only when the question's submitting CLI advertised * that it can perform Agent Acknowledgements. */ agent_acknowledgement_required: boolean; /** * Immutable account-preference snapshot taken when an acknowledgement * obligation is created: true when it must carry text. Otherwise false. */ agent_acknowledgement_text_required: boolean; /** True when idempotency returned a previously accepted request. */ replayed: boolean; overall: OverallState; deliveries: DeliveryOutcome[]; warnings: SubmissionWarning[]; } export interface EvidenceEvent { stage: EvidenceStage; source: string; reason: string | null; attempt: number | null; occurred_at: string; } /** * Derived from the first Companion Receipt event for one Delivery. Unknown * means only that no receipt has been observed; it is not a timeout or failure. */ export interface CompanionReceiptEvidence { state: CompanionReceiptState; observed_at: string | null; /** First companion_received minus first provider_accepted, when both exist. */ latency_ms: number | null; } export interface EvidenceSnapshot { request_id: string; accepted_at: string; overall: OverallState; deliveries: (DeliveryOutcome & { companion_receipt: CompanionReceiptEvidence; events: EvidenceEvent[]; })[]; } export declare const CompanionReceiptRequest: import("@sinclair/typebox").TObject<{ delivery_id: import("@sinclair/typebox").TString; /** * The delivery's own secret, taken from the push payload. Present, it is * the whole authorization and no Auth Session is needed — which is what * keeps Notification Service Extensions out of the keychain. Absent, the * request falls back to a bearer token, so companions installed before the * token existed keep reporting. */ receipt_token: import("@sinclair/typebox").TOptional; }>; export type CompanionReceiptRequestT = Static; /** * One question's answer inside a reply. Choice ids are validated against the * stored draft and rewritten to canonical labels server-side; `text` is the * typed answer, which is always possible even on a choice question (the * "Other" path) and may accompany selections on a multi-select question. * At least one of the two must be present — the server enforces what the * schema cannot say. */ export declare const ReplyAnswer: import("@sinclair/typebox").TObject<{ question_id: import("@sinclair/typebox").TString; choice_ids: import("@sinclair/typebox").TOptional>; text: import("@sinclair/typebox").TOptional; }>; export type ReplyAnswerT = Static; /** An Approved Machine reports a native answer its agent has already read. */ export declare const RecordHarnessAnswerRequest: import("@sinclair/typebox").TObject<{ session_id: import("@sinclair/typebox").TString; /** Persist before sending; retries keep the same key and normalized answers. */ submission_id: import("@sinclair/typebox").TString; answers: import("@sinclair/typebox").TArray>; text: import("@sinclair/typebox").TOptional; }>>; }>; export type RecordHarnessAnswerRequestT = Static; export declare function isRecordHarnessAnswerRequest(value: unknown): value is RecordHarnessAnswerRequestT; export interface RecordHarnessAnswerResponse { status: 'recorded' | 'replayed'; reply_seq: number; answer_version: AnswerVersionView; /** Independent accepted submissions; the agent must reconcile contradictions. */ other_submissions: AnswerVersionView[]; /** All questions have a reported native answer; partial reports never imply this. */ complete: boolean; } export declare const SubmitReplyRequest: import("@sinclair/typebox").TObject<{ delivery_id: import("@sinclair/typebox").TOptional; /** Recovery replies name a Request and the current Device Installation. */ request_id: import("@sinclair/typebox").TOptional; device_id: import("@sinclair/typebox").TOptional; /** Device-generated id; makes outbox retries idempotent. */ client_reply_id: import("@sinclair/typebox").TString; /** * The answers, one per question answered, in question order. The server * resolves each against the stored draft, so a stored reply cannot * disagree with what was actually asked. */ answers: import("@sinclair/typebox").TArray>; text: import("@sinclair/typebox").TOptional; }>>; /** * Which surface the user actually answered from. Native iOS actions, * Android RemoteInput, and each Companion App's in-app composer converge * here. They looked identical once stored, so a regression * in one of them was indistinguishable from a regression in another * without device logs. * * Optional and open: a device that does not send it is not wrong, and an * unknown value is recorded rather than rejected, because rejecting a * reply over a diagnostic field would lose the answer. */ source: import("@sinclair/typebox").TOptional; }>; export type SubmitReplyRequestT = Static; /** The reply surfaces the companions know how to name. */ export declare const REPLY_SOURCES: readonly ["action", "intent", "choice", "remote_input", "app"]; /** One question's answer as stored: canonical ids and labels, server-checked. */ export interface ReplyAnswerView { question_id: string; /** Chosen choice ids, in choice order; empty for a purely typed answer. */ choice_ids: string[]; /** The typed answer, when the user wrote one (the "Other" path). */ text: string | null; } export interface ReplyView { reply_id: string; /** Monotonic cursor within the Notification Request. */ seq: number; /** Null when answered through recovery or the native installation was removed. */ delivery_id: string | null; device_id: string | null; device_name: string; /** Human-readable rendering of the whole reply, assembled server-side. */ text: string; /** The checkable answers, one per question answered. */ answers: ReplyAnswerView[]; /** Which surface it was answered from, when the device said. */ source: string | null; created_at: string; } export interface AgentAcknowledgementView { /** * The agent's brief written reply, or empty when the account turned * acknowledgement text off. Empty text is still a recorded acknowledgement: * it says an agent read the answer. */ text: string; created_at: string; } /** * Optional body of `POST /api/v1/notifications/:request_id/replies/close`. * A capable CLI names why it closes: `deliver` when it collected the answers * and will hand them to the agent, `retire` when the question is being retired * without delivery. The first recorded disposition wins; a later close never * changes it. A close without a body (released CLIs) records none, so answers * collected that way cannot be edited after the window closes. */ export declare const CLOSE_DISPOSITIONS: readonly ["deliver", "retire"]; export type CloseDisposition = (typeof CLOSE_DISPOSITIONS)[number]; export declare const CloseRepliesRequest: import("@sinclair/typebox").TObject<{ disposition: import("@sinclair/typebox").TUnion[]>; }>; export type CloseRepliesRequestT = Static; export interface ListRepliesResponse { request_id: string; /** Null when the Notification Request did not request replies. */ reply_expires_at: string | null; /** True for every request that asked for a reply. */ agent_acknowledgement_required: boolean; /** * Immutable account-preference snapshot recorded at request acceptance: true * when the acknowledgement must carry text. */ agent_acknowledgement_text_required: boolean; /** The one recorded Agent Acknowledgement, or null while none is available. */ agent_acknowledgement: AgentAcknowledgementView | null; replies: ReplyView[]; } /** * Close response when the close carried a disposition. A close without a body * receives exactly `ListRepliesResponse`. */ export interface CloseRepliesResponse extends ListRepliesResponse { /** The stored disposition, which may be an earlier close's rather than this one's. */ close_disposition: CloseDisposition | null; /** * The reply selected for delivery to the agent by a `deliver` close: the * fenced answer a capable writer claims and hands off. Null when the stored * disposition is `retire`, or when the window closed with no reply. */ delivered_reply_seq: number | null; } /** * `POST /api/v1/notifications/:request_id/dismiss` (user auth, server feature * `question_dismiss`; no body). Dismisses an open question: its reply window * closes now, every device retires it silently as expired, and the agent sees * an ordinary window expiry. Idempotent. An answered question, or one whose * window already closed, is left exactly as it was: an answer recorded first * always wins over a dismissal. */ export interface DismissQuestionResponse { request_id: string; /** When the question was dismissed, by this call or an earlier one; null when nothing changed. */ dismissed_at: string | null; } /** Agent-authored follow-up text is kept intentionally smaller than a user reply. */ export declare const AGENT_ACKNOWLEDGEMENT_MAX_LENGTH = 200; /** * The service trims `text` before validation and persistence. When present it * must be non-empty after trimming and no longer than * AGENT_ACKNOWLEDGEMENT_MAX_LENGTH. Omitting it records the acknowledgement * without text, which the service accepts only where the account turned * acknowledgement text off. */ export declare const PutAgentAcknowledgementRequest: import("@sinclair/typebox").TObject<{ /** Both fields are required together when acknowledging a reported native answer. */ reply_seq: import("@sinclair/typebox").TOptional; session_id: import("@sinclair/typebox").TOptional; text: import("@sinclair/typebox").TOptional; }>; export type PutAgentAcknowledgementRequestT = Static; export interface PutAgentAcknowledgementResponse { status: 'recorded' | 'replayed'; agent_acknowledgement: AgentAcknowledgementView; } export interface GetAgentAcknowledgementResponse { request_id: string; /** True for every request that asked for a reply. */ agent_acknowledgement_required: boolean; /** True when the acknowledgement must carry text. */ agent_acknowledgement_text_required: boolean; agent_acknowledgement: AgentAcknowledgementView | null; } export declare const CreateMediaUploadRequest: import("@sinclair/typebox").TObject<{ media_type: import("@sinclair/typebox").TUnion[]>; size_bytes: import("@sinclair/typebox").TInteger; sha256: import("@sinclair/typebox").TString; }>; export type CreateMediaUploadRequestT = Static; export declare const BeginSoundUploadRequest: import("@sinclair/typebox").TObject<{ media_type: import("@sinclair/typebox").TLiteral<"audio/wav">; size_bytes: import("@sinclair/typebox").TInteger; sha256: import("@sinclair/typebox").TString; }>; export type BeginSoundUploadRequestT = Static; export declare const CommitSoundRequest: import("@sinclair/typebox").TObject<{ media_id: import("@sinclair/typebox").TString; name: import("@sinclair/typebox").TString; }>; export type CommitSoundRequestT = Static; export declare const RenameSoundRequest: import("@sinclair/typebox").TObject<{ name: import("@sinclair/typebox").TString; }>; export type RenameSoundRequestT = Static; export interface BeginSoundUploadResponse { media_id: string; upload_url: string; upload_headers: Record; expires_at: string; } export interface SoundView { sound_id: string; name: string; duration_ms: number; content_hash: string; url: string; } export interface ListSoundsResponse { sounds: SoundView[]; } export interface CreateMediaUploadResponse { media_id: string; upload_url: string; /** Headers the client must send with the PUT upload. */ upload_headers: Record; expires_at: string; } export interface FinalizeMediaUploadResponse { media_id: string; /** Storage-provider-observed bytes used for quota accounting. */ size_bytes: number; status: 'ready'; } export interface NotificationContentMediaItem { media_id: string; /** Zero-based collection position; presentation.media order is semantic. */ position: number; media_type: NotificationMediaType; alt: string | null; /** Fresh one-hour signed URL of the original, or null when this item is unavailable. */ url: string | null; /** * Fresh one-hour signed URL of the server-generated WebP preview variant * (longest side 1024px), or null when the asset has no preview. */ preview_url: string | null; /** Oriented pixel width of the original, or null when never decoded. */ width: number | null; /** Oriented pixel height of the original, or null when never decoded. */ height: number | null; } export interface NotificationContentResponse { request_id: string; /** Purpose-written plain text used when the request has no Markdown Body. */ summary: string; /** Standalone focused content, always interpreted as Markdown when present. */ body: string | null; media: NotificationContentMediaItem[]; /** * The reply questions exactly as accepted, choice descriptions included, * or empty for a request that asks nothing. A push leaves the descriptions * out when they do not fit; this is where a Companion App gets them. */ questions: QuestionT[]; } /** Most requests one content batch may name; a Companion App splits a longer list. */ export declare const NOTIFICATION_CONTENT_BATCH_MAX = 50; /** * `POST /api/v1/notifications/content` (user auth; Server Feature * `notification_content_batch`): the content of every named request in one * exchange, so a screen or refresh costs one request rather than one per row. */ export declare const NotificationContentBatchRequest: import("@sinclair/typebox").TObject<{ request_ids: import("@sinclair/typebox").TArray; }>; export type NotificationContentBatchRequestT = Static; export interface NotificationContentBatchResponse { /** Content of each named request this Account still holds, in request order. */ contents: NotificationContentResponse[]; /** * Named requests with no content to return: unknown, another Account's, or * deleted by retention. One case, exactly like the single-request 404. */ missing: string[]; } /** * `POST /api/v1/delivery-content` (no Auth Session): the content of the one * request a Delivery carried, authorized by the Delivery's `content_token` * from the push. This is how a Notification Service Extension, which holds no * session, fetches a Body that did not fit in the push and every image * preview at arrival. The response is a {@link NotificationContentResponse}. */ export declare const DeliveryContentRequest: import("@sinclair/typebox").TObject<{ delivery_id: import("@sinclair/typebox").TString; content_token: import("@sinclair/typebox").TString; }>; export type DeliveryContentRequestT = Static; export declare const UpdateProjectRequest: import("@sinclair/typebox").TObject<{ display_name: import("@sinclair/typebox").TOptional>; }>; export type UpdateProjectRequestT = Static; export interface ProjectView { project_id: string; identifier: string; display_name: string | null; image_media_id: string | null; /** Stable cache identity. Signed URLs are transport capabilities, never cache identity. */ avatar_revision: string; /** Public generated avatar URL, or a short-lived signed URL for custom media. */ image_url: string | null; last_seen_at: string; } export interface ListProjectsResponse { projects: ProjectView[]; } export declare const PutAgentSessionLabelRequest: import("@sinclair/typebox").TObject<{ session_id: import("@sinclair/typebox").TString; label: import("@sinclair/typebox").TString; }>; export type PutAgentSessionLabelRequestT = Static; export interface AgentSessionView { /** Informational CLI-detected harness; omitted by older services or when unknown. */ harness?: string; session_id: string; label: string; renamed_by: 'user' | 'agent'; updated_at: string; } export interface ListAgentSessionsResponse { /** * `presence` is additive: servers that predate Session Presence omit it, * which a Companion App renders exactly like `unknown`. */ agent_sessions: (AgentSessionView & { presence?: SessionPresenceView; })[]; } /** Content-free metadata for an optional compressed log slice. */ export declare const FeedbackLogMeta: import("@sinclair/typebox").TObject<{ readonly encoding: import("@sinclair/typebox").TLiteral<"gzip+base64">; readonly uncompressed_bytes: import("@sinclair/typebox").TInteger; readonly compressed_bytes: import("@sinclair/typebox").TInteger; readonly record_count: import("@sinclair/typebox").TInteger; readonly truncated: import("@sinclair/typebox").TBoolean; readonly since: import("@sinclair/typebox").TString; readonly until: import("@sinclair/typebox").TString; readonly schema_version: import("@sinclair/typebox").TInteger; }>; export type FeedbackLogMetaT = Static; export declare const FeedbackLogAttachment: import("@sinclair/typebox").TObject<{ bytes: import("@sinclair/typebox").TString; encoding: import("@sinclair/typebox").TLiteral<"gzip+base64">; uncompressed_bytes: import("@sinclair/typebox").TInteger; compressed_bytes: import("@sinclair/typebox").TInteger; record_count: import("@sinclair/typebox").TInteger; truncated: import("@sinclair/typebox").TBoolean; since: import("@sinclair/typebox").TString; until: import("@sinclair/typebox").TString; schema_version: import("@sinclair/typebox").TInteger; }>; export type FeedbackLogAttachmentT = Static; export declare const FeedbackClient: import("@sinclair/typebox").TObject<{ cli_version: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>; cli_channel: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"dev">, import("@sinclair/typebox").TLiteral<"prerelease">, import("@sinclair/typebox").TLiteral<"stable">]>; os: import("@sinclair/typebox").TString; node: import("@sinclair/typebox").TString; }>; export type FeedbackClientT = Static; export declare const SubmitFeedbackRequest: import("@sinclair/typebox").TObject<{ message: import("@sinclair/typebox").TString; include_logs: import("@sinclair/typebox").TBoolean; log: import("@sinclair/typebox").TOptional; uncompressed_bytes: import("@sinclair/typebox").TInteger; compressed_bytes: import("@sinclair/typebox").TInteger; record_count: import("@sinclair/typebox").TInteger; truncated: import("@sinclair/typebox").TBoolean; since: import("@sinclair/typebox").TString; until: import("@sinclair/typebox").TString; schema_version: import("@sinclair/typebox").TInteger; }>>; client: import("@sinclair/typebox").TObject<{ cli_version: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNull]>; cli_channel: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"dev">, import("@sinclair/typebox").TLiteral<"prerelease">, import("@sinclair/typebox").TLiteral<"stable">]>; os: import("@sinclair/typebox").TString; node: import("@sinclair/typebox").TString; }>; }>; export type SubmitFeedbackRequestT = Static; export interface SubmitFeedbackResponse { report_id: string; }