// GENERATED by scripts/gen_gateway_contracts.py from tui_gateway/contracts — DO NOT EDIT. // Regenerate: .venv/bin/python scripts/gen_gateway_contracts.py // tests/tui_gateway/contracts/test_generated.py fails when this file is stale. /* eslint-disable */ // ── Types ── /** Any method the desktop may route to a named profile (``requestGatewayForProfile`` adds ``profile``). */ export interface ProfileParams { profile?: string | null } /** ``_serialize_usage_model`` — also embedded as ``usage`` in the billing / subscription states, where the fail-open form is a bare ``{available: false}`` (no ``ok``). */ export interface UsageModel { ok?: boolean | null available: boolean status?: string | null plan_name?: string | null renews_at?: string | null renews_display?: string | null subscription_remaining_display?: string | null topup_remaining_display?: string | null total_spendable_display?: string | null has_topup?: boolean | null plan_bar?: UsageBar | null topup_bar?: UsageBar | null } /** ``_serialize_usage_bar``: one bar, magnitudes pre-formatted; ``pct_used`` only for ``plan``. */ export interface UsageBar { kind: UsageBarKind remaining_display: string total_display: string spent_display: string pct_used?: number | null fill_fraction: number } export type UsageBarKind = 'plan' | 'topup' /** ``_serialize_billing_state`` (money as strings); the ``except`` fallback emits only ``ok / logged_in / free_tier / error``, so everything else is optional. */ export interface BillingStateResult { ok: boolean logged_in: boolean free_tier?: boolean free_tier_model?: string | null org_name?: string | null org_slug?: string | null role?: string | null is_admin?: boolean | null can_change_plan?: boolean | null can_charge?: boolean | null balance_usd?: string | null balance_display?: string | null cli_billing_enabled?: boolean | null charge_presets?: string[] | null charge_presets_display?: string[] | null min_usd?: string | null max_usd?: string | null card?: BillingCardInfo | null payment_method?: BillingPaymentMethod | null monthly_cap?: BillingMonthlyCap | null auto_reload?: BillingAutoReload | null portal_url?: string | null error?: string | null usage?: UsageModel | null } export interface BillingCardInfo { brand: string last4: string masked: string display?: string | null resolved_via?: string | null } /** ``_serialize_payment_method``: each kind emits only its own fields (a ``card`` never carries ``email``; ``unknown`` carries what the server called it in ``raw_kind``). */ export interface BillingPaymentMethod { kind: PaymentMethodKind brand?: string | null last4?: string | null wallet?: string | null email?: string | null raw_kind?: string | null resolved_via?: string | null } export type PaymentMethodKind = 'card' | 'link' | 'unknown' export interface BillingMonthlyCap { limit_usd?: string | null limit_display: string spent_this_month_usd?: string | null spent_display: string is_default_ceiling: boolean } export interface BillingAutoReload { enabled: boolean threshold_usd?: string | null threshold_display: string reload_to_usd?: string | null reload_to_display: string card?: BillingAutoReloadCard | null } /** Only ``distinct`` carries the payment-method identity. */ export interface BillingAutoReloadCard { kind: AutoReloadCardKind payment_method_id?: string | null brand?: string | null last4?: string | null } export type AutoReloadCardKind = 'canonical' | 'distinct' | 'none' /** ``_serialize_subscription_state``; the view's fallback emits only ``ok / logged_in / error``. */ export interface SubscriptionStateResult { ok: boolean logged_in: boolean is_admin?: boolean | null can_change_plan?: boolean | null org_name?: string | null org_id?: string | null role?: string | null context?: SubscriptionContext | null current?: CurrentSubscription | null tiers?: SubscriptionTierOption[] | null portal_url?: string | null error?: string | null usage?: UsageModel | null } export type SubscriptionContext = 'personal' | 'team' export interface CurrentSubscription { tier_id?: string | null tier_name?: string | null monthly_credits?: string | null credits_remaining?: string | null cycle_ends_at?: string | null pending_downgrade_tier_name?: string | null pending_downgrade_at?: string | null pending_downgrade_display?: string | null cancel_at_period_end: boolean cancellation_effective_at?: string | null cancellation_effective_display?: string | null } export interface SubscriptionTierOption { tier_id: string name: string tier_order: number dollars_per_month_display: string monthly_credits?: string | null is_current: boolean is_enabled: boolean } export interface SubscriptionPreviewParams { profile?: string | null subscription_type_id?: string | null } /** ``_serialize_subscription_preview`` on success; ``effect`` drives the confirm copy. */ export interface SubscriptionPreviewResult { ok: boolean error?: string | null message?: string | null portal_url?: string | null retry_after?: number | null payload?: Record | null actor?: string | null code?: string | null recovery?: string | null effect?: SubscriptionChangeEffect | null reason?: string | null current_tier_id?: string | null current_tier_name?: string | null target_tier_id?: string | null target_tier_name?: string | null monthly_credits_delta?: string | null amount_due_now_cents?: number | null effective_at?: string | null } export type SubscriptionChangeEffect = 'charge_now' | 'scheduled' | 'no_op' | 'blocked' /** Either a target tier (downgrade / same-price change) or ``cancel`` (period-end cancellation). */ export interface SubscriptionChangeParams { profile?: string | null subscription_type_id?: string | null cancel?: boolean } /** ``_billing_pending_change``: ``message`` + the raw NAS body in ``payload`` on success. */ export interface BillingPendingChangeResult { ok: boolean error?: string | null message?: string | null portal_url?: string | null retry_after?: number | null payload?: Record | null actor?: string | null code?: string | null recovery?: string | null } export interface SubscriptionUpgradeParams { profile?: string | null subscription_type_id?: string | null idempotency_key?: string | null } /** The money route: ``status`` separates a completed upgrade from an SCA / decline that must finish in the portal at ``recovery_url``; ``idempotency_key`` is echoed (also on error) so a retry reuses it. */ export interface SubscriptionUpgradeResult { ok: boolean error?: string | null message?: string | null portal_url?: string | null retry_after?: number | null payload?: Record | null actor?: string | null code?: string | null recovery?: string | null status?: string | null target_tier_name?: string | null recovery_url?: string | null reason?: string | null idempotency_key?: string | null } export interface BillingChargeParams { profile?: string | null amount_usd?: number | string | null idempotency_key?: string | null } /** ``202 {chargeId}`` — money is not confirmed yet; poll ``billing.charge_status``. */ export interface BillingChargeResult { ok: boolean error?: string | null message?: string | null portal_url?: string | null retry_after?: number | null payload?: Record | null actor?: string | null code?: string | null recovery?: string | null charge_id?: string | null idempotency_key?: string | null } export interface BillingChargeStatusParams { profile?: string | null charge_id?: string | null } /** Single status read (pending | settled | failed); the caller drives the poll cadence. */ export interface BillingChargeStatusResult { ok: boolean error?: string | null message?: string | null portal_url?: string | null retry_after?: number | null payload?: Record | null actor?: string | null code?: string | null recovery?: string | null status?: string | null amount_usd?: string | number | null settled_at?: string | null reason?: string | null } export interface BillingAutoReloadParams { profile?: string | null enabled?: boolean threshold?: number | string | null top_up_amount?: number | string | null } /** A write with no success payload beyond ``ok``. */ export interface BillingMutationResult { ok: boolean error?: string | null message?: string | null portal_url?: string | null retry_after?: number | null payload?: Record | null actor?: string | null code?: string | null recovery?: string | null } export interface BillingStepUpParams { profile?: string | null session_id?: string | null } /** ``granted`` false when the server downscopes (also on every error envelope). */ export interface BillingStepUpResult { ok: boolean error?: string | null message?: string | null portal_url?: string | null retry_after?: number | null payload?: Record | null actor?: string | null code?: string | null recovery?: string | null granted?: boolean | null } export interface DelegationStatusResult { active: ActiveSubagent[] paused: boolean max_spawn_depth: number max_concurrent_children: number } /** One live child from ``tools/delegate_tool_registry.py::list_active_subagents`` (the record is extended by the child runner — ``missed_steer`` etc. — so it stays open). */ export interface ActiveSubagent { subagent_id: string parent_id?: string | null depth?: number | null goal?: string | null delegation_id?: string | null model?: string | null started_at?: number | null status?: string | null tool_count?: number | null owner_agent_session_id?: string | null [key: string]: unknown } export interface DelegationPauseParams { profile?: string | null paused?: boolean } export interface DelegationPauseResult { paused: boolean } export interface SubagentSteerParams { session_id: string profile?: string | null subagent_id: string text: string } /** ``queued`` is not ``delivered``: a child past its final tool batch surfaces ``missed_steer``. */ export interface SubagentSteerResult { status: SteerStatus subagent_id: string text: string } export type SteerStatus = 'queued' | 'rejected' export interface HandoffRequestParams { session_id: string profile?: string | null platform: string } export interface HandoffRequestResult { queued: boolean session_key: string platform: string home_name: string } /** Any method addressed at one live session. */ export interface SessionParams { session_id: string profile?: string | null } /** ``state`` is pending | running | completed | failed, or '' when nothing was requested. */ export interface HandoffStateResult { state: string platform: string error: string } export interface HandoffFailParams { session_id: string profile?: string | null error?: string | null } /** ``failed`` false when the watcher already claimed the row; ``state`` is what it is now. */ export interface HandoffFailResult { failed: boolean state: string } /** ``row_id`` is ``messages.id``; a not-yet-persisted live message names ``newest_role`` instead. ``emoji`` null clears; the same emoji again retracts. */ export interface MessageReactParams { session_id: string profile?: string | null row_id?: number | null newest_role?: string | null emoji?: string | null author?: ReactionAuthor | null } export type ReactionAuthor = 'user' | 'agent' export interface MessageReactResult { row_id: number reactions: MessageReaction[] } /** One persisted reaction row (``hermes_state_messages.set_message_reaction``); ``seen`` is stamped once announced. */ export interface MessageReaction { emoji: string author: string at?: number | null seen?: boolean | null [key: string]: unknown } export interface PetCancelParams { profile?: string | null token?: string | null } export interface PetCancelResult { ok: boolean } export interface PetGenerateStatusResult { available: boolean providers: PetGenProvider[] } /** ``agent/pet/generate/imagegen.py::list_sprite_providers`` row. */ export interface PetGenProvider { name: string label: string default: boolean } /** ``prompt`` or a ``referenceImage`` data URL is required (the handler answers 4004 without one). */ export interface PetGenerateParams { profile?: string | null prompt?: string | null referenceImage?: string | null count?: number | null style?: string | null provider?: string | null } export interface PetGenerateResult { ok: boolean token: string drafts: PetDraft[] } export interface PetDraft { index: number dataUri: string } export interface PetHatchParams { profile?: string | null token: string name: string cancelToken?: string | null index?: number | null description?: string | null prompt?: string | null style?: string | null provider?: string | null } /** The hatched pet is installed but NOT active (``pet.select`` adopts, ``pet.remove`` discards). */ export interface PetHatchResult { ok: boolean slug: string displayName: string warnings?: unknown[] pet: PetSpritePayload } export interface PetSpritePayload { slug?: string | null displayName?: string | null mime?: string | null spritesheetBase64?: string | null spritesheetRevision?: string | null frameW?: number | null frameH?: number | null framesPerState?: number | null framesByState?: Record | null framesByRow?: Record | null loopMs?: number | null scale?: number | null stateRows?: string[] | null } export interface ProjectFactsParams { profile?: string | null cwd?: string | null } /** ``facts`` null outside a workspace (or when detection failed). */ export interface ProjectFactsResult { facts?: ProjectFacts | null } /** ``agent/coding_context.py::project_facts_for`` — the system prompt's coding-context detection. */ export interface ProjectFacts { root: string manifests: string[] packageManagers: string[] verifyCommands: string[] contextFiles: string[] } export interface ConnectionOperationParams { profile?: string | null session_id: string op_id: string } /** ``methods_connectors._operation_view``: the operation's full snapshot. */ export interface ConnectionOperationStatus { op_id: string deadline_at: number settled: boolean settled_at?: number | null settled_by?: ConnectionSettleReason | null targets: ConnectionOperationTarget[] } /** ``tools/connectors/contract.py::SettleReason``. */ export type ConnectionSettleReason = 'all_resolved' | 'continue' | 'deadline' | 'interrupt' | 'unavailable' /** ``Target.snapshot``: the link minted up front rides here, never in the model result. ``extra`` keys a leg records (``tools``, ``hint``) are typed here as they appear. */ export interface ConnectionOperationTarget { name: string kind: ConnectionTargetKind action: ConnectionTargetAction state: ConnectionTargetState detail?: string | null connect_url?: string | null attempt?: string | null tools?: string[] | null hint?: string | null } export type ConnectionTargetKind = 'connector' | 'mcp' export type ConnectionTargetAction = 'authorize' | 'connect' | 'enable' | 'install' | 'reconnect' /** ``tools/connectors/contract.py::TargetState``. */ export type ConnectionTargetState = 'pending' | 'initiated' | 'connected' | 'skipped' | 'failed' | 'expired' | 'unavailable' | 'not_connected' export interface ConnectionRespondParams { profile?: string | null session_id: string op_id: string result: ConnectionAnswer } /** The card's answer: per-target outcomes and an optional Continue (``settled_by: "continue"``). Settlement is derived from target states afterwards. */ export interface ConnectionAnswer { targets?: ConnectionAnswerTarget[] settled_by?: ConnectionSettleReason | null } /** One row's answer from the card. ``status`` is what the card observed for that row (``tools/connectors/mcp.py::_OUTCOME_STATES`` maps it onto a target state); ``state`` is the older spelling of the same field and one of the two is present. */ export interface ConnectionAnswerTarget { name: string status?: string | null state?: string | null detail?: string | null tools?: string[] | null [key: string]: unknown } export interface ConnectionRespondResult { status: string settled: boolean } /** ``key`` selects one getter from ``_CONFIG_GETTERS``; ``cwd`` feeds the ``project`` getter, ``session_id`` lets ``reasoning`` / ``fast`` answer with the session's live pin. */ export interface ConfigGetParams { profile?: string | null key: string cwd?: string | null session_id?: string | null } /** Union of every getter's payload: ``value`` for the simple words, ``config`` for ``full``, ``mtime`` / ``mcp_rev`` for the poller, ``model`` / ``provider`` / ``providers`` for ``provider``, ``home`` / ``display`` for ``profile``, ``cwd`` / ``branch`` for ``project``, ``prompt``. */ export interface ConfigGetResult { value?: string | null display?: string | null tool_progress?: string | null model?: string | null provider?: string | null providers?: ConfigProviderRef[] | null home?: string | null cwd?: string | null branch?: string | null config?: Record | null prompt?: string | null mtime?: number | null mcp_rev?: string | null } /** ``hermes_cli/models.py::list_available_providers`` row. */ export interface ConfigProviderRef { id: string label: string aliases?: string[] authenticated?: boolean [key: string]: unknown } /** ``key`` picks the setter (``_CONFIG_SETTERS``, ``details_mode.
``, display toggles); ``value`` is the raw word/string the setter normalises (falsy non-strings are reported back in the error). ``scope`` applies to ``yolo`` / ``reasoning``; ``confirm_expensive_model`` to ``model``. */ export interface ConfigSetParams { profile?: string | null key: string value?: unknown session_id?: string | null scope?: string | null confirm_expensive_model?: boolean } /** ``{key, value}`` plus the setter's extras: model switches add ``warning`` / ``confirm_required`` / ``confirm_message`` / ``scope`` / ``deferred``; ``focus`` adds ``tool_progress``; ``cwd`` adds ``cwd`` / ``branch``; ``personality`` adds ``history_reset`` / ``info``; ``yolo`` reports its ``scope``. ``value`` is a bool only for the display toggles. */ export interface ConfigSetResult { key: string value?: string | boolean | null warning?: string | null confirm_required?: boolean | null confirm_message?: string | null scope?: string | null deferred?: boolean | null tool_progress?: string | null cwd?: string | null branch?: string | null history_reset?: boolean | null info?: SessionLiveInfo | null } /** ``tui_gateway/server.py::_session_info`` — the ``session.info`` event and the ``info`` field of ``session.create`` / ``session.resume`` / ``session.activate`` results. */ export interface SessionLiveInfo { model?: string provider?: string reasoning_effort?: string service_tier?: string fast?: boolean yolo?: boolean approval_mode?: string tools?: Record skills?: Record cwd?: string branch?: string | null project?: ProjectRef | null terminal_backend?: string personality?: string running?: boolean turn_started_at?: number | null title?: string stored_session_id?: string desktop_contract?: number | string | null version?: string release_date?: string update_behind?: unknown | null update_command?: string usage?: Usage | null profile_name?: string | null mcp_servers?: McpServerStatus[] system_prompt?: string | null credential_warning?: string | null lazy?: boolean | null [key: string]: unknown } /** ``tui_gateway/server.py::_project_info_for_cwd``. */ export interface ProjectRef { id: string slug: string name: string primary_path?: string | null } /** ``tui_gateway/server.py::_get_usage`` + ``agent/context_breakdown.py::context_usage_fields``. */ export interface Usage { model?: string input?: number output?: number reasoning?: number prompt?: number completion?: number total?: number calls?: number compressions?: number | null context_used?: number | null context_max?: number | null context_percent?: number | null context_source?: string | null context_estimated?: boolean | null cache_hit_pct?: number | null cache_read?: number | null cache_write?: number | null avg_latency_s?: number | null avg_tps?: number | null active_subagents?: number | null dev_credits_spent_micros?: number | null cost_usd?: number | null cost_status?: string | null [key: string]: unknown } export interface McpServerStatus { name?: string status?: string | null tool_count?: number | null error?: string | null [key: string]: unknown } /** ``provider_configured`` is the loose answer; the boot record's fields (``ready``, ``free_tier``, ``other_providers``, ``inference_provider``) ride along on the launch profile. An unknown ``profile`` answers ``ok=False`` + ``error``. */ export interface SetupStatusResult { provider_configured?: boolean | null ready?: boolean | null free_tier?: boolean | null other_providers?: boolean | null inference_provider?: string | null profile?: string | null ok?: boolean | null error?: string | null } export interface SetupRuntimeCheckParams { profile?: string | null provider?: string | null } /** ``ok=False`` + ``error`` when the resolved model can't be served; ``free_tier`` says the selected route is the welcome host. */ export interface SetupRuntimeCheckResult { ok: boolean provider?: string | null model?: string | null source?: string | null error?: string | null free_tier?: boolean | null profile?: string | null } export interface DiagnosticsShareNousParams { error_context?: string | null extra_files?: Record | null log_lines?: number | null } /** Structured envelope: ``ok=False`` + ``error`` renders inline instead of failing the RPC. */ export interface DiagnosticsShareNousResult { ok: boolean view_url?: string | null upload_id?: string | null expires_at?: string | null error?: string | null } /** ``available`` = an identity exists AND the tier is on; whether inference runs on it is ``setup.runtime_check.free_tier``'s question. */ export interface FreeTierStatusResult { has_guest: boolean enabled: boolean available: boolean notice_pending: boolean model: string label: string } export interface FreeTierProvisionResult { has_guest: boolean enabled: boolean error?: string | null } export interface FreeTierAckNoticeResult { acked: boolean } export interface ModelOptionsParams { profile?: string | null session_id?: string | null explicit_only?: boolean include_unconfigured?: boolean refresh?: boolean } export interface ModelOptionsResult { providers: ModelOptionProvider[] model?: string provider?: string } /** One ``hermes_cli/inventory.py::build_models_payload`` provider row (the union of every field the builder sets; ``pricing_pending`` / ``free_tier_pending`` mark the cached-only path). */ export interface ModelOptionProvider { slug: string name: string models?: string[] total_models?: number | null is_current?: boolean | null is_user_defined?: boolean | null source?: string | null aliases?: string[] | null api_url?: string | null auth_type?: string | null authenticated?: boolean | null key_env?: string | null warning?: string | null featured_models?: string[] | null capabilities?: Record | null pricing?: Record | null pricing_pending?: boolean | null free_tier?: boolean | null free_tier_pending?: boolean | null free_tier_row?: boolean | null unavailable_models?: string[] | null [key: string]: unknown } /** ``hermes_cli/inventory.py::_apply_capabilities``. */ export interface ModelCapabilities { fast: boolean reasoning: boolean can_disable_reasoning?: boolean | null } /** ``hermes_cli/inventory.py::_apply_pricing`` — formatted $/Mtok strings (``""`` unknown, ``"free"``); the sale fields are Nous Portal-only. */ export interface ModelPricing { input: string output: string cache?: string | null free: boolean discount_percent?: number | null was_input?: string | null was_output?: string | null } export interface ConnectorsListParams { profile?: string | null session_id: string } export interface ConnectorsListResult { available: boolean connectors: ConnectorRow[] } /** One ``manage_connections`` status entry after ``connector_ui_payload`` redaction; the connector service owns the closed key set, so unknown metadata passes through. */ export interface ConnectorRow { connector?: string connected?: boolean | null enabled?: boolean | null connectionStatus?: string | null name?: string | null description?: string | null [key: string]: unknown } export interface ConnectorsConnectParams { profile?: string | null session_id: string connectors: string[] reconnect?: boolean } /** The operation the connect opened (or re-minted on): ``tools/connectors/managed.py`` ``_off_desktop_result`` / ``methods_connectors._reissue``. ``status``/``note`` ride along from the tool result when the call ran through ``manage_connections``. */ export interface ConnectorsConnectResult { op_id: string deadline_at: number settled: boolean settled_at?: number | null settled_by?: ConnectionSettleReason | null targets: ConnectionOperationTarget[] status?: string | null note?: string | null } export interface ImageGenerateParams { prompt?: string | null aspect_ratio?: string | null probe?: unknown | null max_bytes?: number | null } /** ``probe`` answers ``{available}`` alone; ``image_data`` (data URL) is omitted when the download failed or exceeded ``max_bytes`` so callers fall back to ``image``. */ export interface ImageGenerateResult { available: boolean success?: boolean | null image?: string | null image_data?: string | null error?: string | null } export interface SessionControlReadParams { profile?: string | null session_id: string } export interface SessionControlReadResult { control: SessionControlSnapshot } /** ``_snapshot_control`` — ``revision`` is a hash of the visible state (``""`` when empty); ``updated_at`` is the newest persisted timestamp (``0`` when none). */ export interface SessionControlSnapshot { goal: GoalSnapshot | null loop: LoopSnapshot | null heartbeat: HeartbeatSnapshot | null revision: string updated_at: number } /** ``methods_session_control.py::_safe_goal_snapshot`` — the frontend-safe GoalState subset. */ export interface GoalSnapshot { title: string status: string turns_used: number max_turns: number contract: GoalContractSnapshot subgoals: string[] gates: GoalGateSnapshot[] created_at?: number | null updated_at?: number | null paused_reason?: string | null last_verdict?: string | null last_reason?: string | null wait_barrier?: WaitBarrierUntil | WaitBarrierTarget | null } /** ``hermes_cli/goals.py::GoalContract.to_dict``. */ export interface GoalContractSnapshot { outcome?: string verification?: string constraints?: string boundaries?: string stop_when?: string } export interface GoalGateSnapshot { command: string timeout_seconds: number max_retries: number attempts: number last_exit_code?: number | null } export interface WaitBarrierUntil { type: 'until' until_at: number reason?: string } export interface WaitBarrierTarget { type: 'session' | 'pid' target: string | number reason?: string } /** ``_safe_loop_snapshot`` — persisted LoopState fields, never its route. */ export interface LoopSnapshot { prompt: string status: string mode: string interval_seconds: number current_delay: number times: number until: string max_ticks: number ticks_fired: number created_at: number last_fired_at: number next_due_at: number awaiting_response: boolean deferred_by_goal: boolean paused_reason?: string | null last_stop_reason?: string | null } export interface HeartbeatSnapshot { prompt: string status: string interval_seconds: number created_at: number last_fired_at: number fire_count: number } /** ``action`` is validated by the handler (unknown / gate actions answer ``4004``), so it stays a string on the wire; ``SessionControlAction`` lists the accepted set. */ export interface SessionControlParams { profile?: string | null session_id: string action: string args?: SessionControlArgs | null } /** ``subgoal.add`` reads ``text``; ``subgoal.remove`` reads the 1-based ``index``. */ export interface SessionControlArgs { text?: string | null index?: number | null } export interface SessionControlResult { control: SessionControlSnapshot dispatch: SessionControlDispatch } /** ``_dispatch_envelope`` — the command result's user-visible envelope, every key always present. */ export interface SessionControlDispatch { type: string | null output: string | null notice: string | null message: string | null display: string | null } export interface VerificationStatusParams { profile?: string | null session_id?: string | null session_key?: string | null cwd?: string | null } export interface VerificationStatusResult { verification: VerificationStatusInfo } /** ``verification_status()``: ``disabled`` / ``not_applicable`` / ``unverified`` / ``stale`` or the latest event's own status; ``root`` and friends only once a workspace was identified. */ export interface VerificationStatusInfo { status: string evidence?: VerificationEvidenceRow | null root?: string | null session_id?: string | null changed_paths?: string[] | null } /** One ``verification_events`` row (``agent/verification_evidence.py``). */ export interface VerificationEvidenceRow { id?: number | null created_at?: string | null session_id?: string | null cwd?: string | null root?: string | null command?: string | null canonical_command?: string | null kind?: string | null scope?: string | null status?: string | null exit_code?: number | null output_summary?: string | null [key: string]: unknown } export interface GroupsCapabilitiesParams { profile?: string | null } export interface GroupsCapabilitiesResult { protocol_version: number driver: boolean persistent_process: boolean authority_gateway_id: string room_link: RoomLinkStatus features: string[] methods: string[] max_log_limit: number } /** ``enabled`` with ``profile``/``catalog``/``endpoint``, or disabled with a ``reason``. */ export interface RoomLinkStatus { enabled: boolean profile?: string | null catalog?: RoomLinkCatalog | null endpoint?: RoomLinkEndpoint | null reason?: string | null } /** ``gateway/hosted_room_peer.py::GatewayRoomCatalog.as_mapping``. */ export interface RoomLinkCatalog { installation_id: string protocol_versions: number[] link_modes: string[] persistent_process: boolean text: boolean attachments: boolean execution_policy: RoomExecutionPolicy catalog_digest: string endpoint?: RoomLinkEndpoint | null } /** ``gateway/hosted_room_execution_policy.py::execution_policy_mapping``. */ export interface RoomExecutionPolicy { version: number target_profile: string enabled_toolsets: string[] approval_mode: string max_iterations: number policy_digest: string } /** ``GatewayRoomCatalog.endpoint_mapping``: ``url``/``transport_security`` when available, ``reason`` when not. */ export interface RoomLinkEndpoint { available: boolean url?: string | null transport_security?: string | null reason?: string | null } export interface GroupsListParams { profile?: string | null include_disbanded?: boolean | null limit?: number | null offset?: number | null } export interface GroupsListResult { rooms: Room[] next_offset?: number | null } /** ``gateway/hosted_rooms.py::_room_from_row`` plus the branch-only keys ``create`` (legacy adoption), ``state`` (``authority_claim``) and ``rename`` (``event``) add. */ export interface Room { room_id: string name: string members: RoomMember[] authority_gateway_id: string authority_epoch: number revision: number created_at: number updated_at: number idempotent?: boolean disbanded_at?: number | null latest_seq?: number | null adopted?: boolean | null claim_event?: RoomEvent | null authority_claim?: RoomEvent | null event?: RoomEvent | null } /** One roster row (``hosted_room_discussion.validate_roster``); legacy rooms may carry pre-normalisation rows, so the set stays open. */ export interface RoomMember { member_id?: string | null profile?: string | null handle?: string | null display_name?: string | null target?: Record | null [key: string]: unknown } /** ``gateway/hosted_rooms.py::_event_from_row``. */ export interface RoomEvent { room_id: string seq: number event_id: string kind: string actor: RoomActor authority_epoch?: number | null payload: Record created_at: number idempotent?: boolean } export interface RoomActor { kind: string id: string } export interface GroupsCreateParams { profile?: string | null room_id: string name: string members: RoomMemberInput[] authority_gateway_id?: string | null } /** A roster row as the client proposes it; ``validate_roster`` owns the exact rules. */ export interface RoomMemberInput { member_id?: string | null profile?: string | null handle?: string | null display_name?: string | null target?: Record | null [key: string]: unknown } export interface GroupsCreateResult { room: Room } export interface GroupsStateParams { profile?: string | null room_id: string include_disbanded?: boolean | null } export interface GroupsStateResult { room: Room driver_status?: RoomDriverStatus | null } /** ``HostedRoomService.status(room_id)``; ``pending_actions`` rows are ``{kind: retry, task_id}`` or the driver's approval action (``kind: approval`` + run/session/approval context). */ export interface RoomDriverStatus { running: boolean working: boolean blocked: boolean counts: Record pending_actions: Record[] peer_routes: PeerRouteStatus[] } export interface PeerRouteStatus { room_id: string member_id: string status: string } export interface GroupsSendParams { profile?: string | null room_id: string event_id?: string | null payload: Record } export interface GroupsSendResult { event: RoomEvent client_event_id?: string | null accepted?: boolean driver_started?: boolean } export interface GroupsRenameParams { profile?: string | null room_id: string event_id: string name: string } export interface GroupsRenameResult { room: Room } export interface GroupsLogParams { profile?: string | null room_id: string since_seq?: number | null limit?: number | null include_disbanded?: boolean | null } /** ``gateway/hosted_rooms.py::read_events`` page — also the ``page`` ``groups.replicate`` ingests. */ export interface GroupsLogResult { events: RoomEvent[] cursor: number latest_seq: number has_more: boolean authority: RoomAuthority } export interface RoomAuthority { gateway_id: string epoch: number } export interface GroupsDisbandParams { profile?: string | null room_id: string cancel_id?: string | null } export interface GroupsDisbandResult { tombstone: RoomTombstone } export interface RoomTombstone { room_id: string disbanded_at: number idempotent: boolean history_expired?: boolean | null event?: RoomEvent | null } export interface GroupsStopParams { profile?: string | null room_id: string cancel_id?: string | null } export interface GroupsStopResult { cancelled: number } export interface GroupsApproveParams { profile?: string | null room_id: string member_id: string task_id: string execution_generation: number choice: ApprovalChoice request_id: string } export type ApprovalChoice = 'once' | 'session' | 'always' | 'deny' /** ``result`` is the local ``approval.respond`` answer or the peer's run-action receipt. */ export interface GroupsApproveResult { approved?: boolean result: Record } export interface GroupsRetryParams { profile?: string | null room_id: string task_id: string } export interface GroupsRetryResult { retried?: boolean task: RoomTaskReceipt } export interface RoomTaskReceipt { room_id: string task_id: string thread_id: string turn_id: string status: string execution_generation: number cancel_generation: number } export interface GroupsReplicateParams { profile?: string | null room_id: string room_name: string members: RoomMemberInput[] page: Record } export interface GroupsReplicateResult { room_id: string stored_seq: number ingested: number authority: RoomAuthority caught_up: boolean } export interface GroupsReplicaStateParams { profile?: string | null room_id: string } export interface GroupsReplicaStateResult { room_id: string name: string members: RoomMember[] authority: RoomAuthority last_seq: number latest_seq: number event_bytes: number created_at: number updated_at: number } export interface GroupsPromoteParams { profile?: string | null room_id: string confirm?: boolean | null reason?: string | null } export interface GroupsPromoteResult { room_id: string authority_gateway_id: string authority_epoch: number previous_gateway_id: string previous_epoch: number claim_seq: number latest_seq: number } export interface GroupsDemoteParams { profile?: string | null room_id: string observed_gateway_id: string observed_epoch: number } export interface GroupsDemoteResult { room_id: string authority_gateway_id: string authority_epoch: number idempotent: boolean } export interface GroupsPeerInviteParams { profile?: string | null room_id?: string | null home_install_id?: string | null authority_gateway_id?: string | null authority_epoch?: number | null member_id?: string | null grant_id?: string | null ttl_seconds?: number | null } export interface GroupsPeerInviteResult { grant: string target_profile: string catalog: RoomLinkCatalog endpoint: RoomLinkEndpoint } export interface GroupsPeerRevokeParams { profile?: string | null grant: string } export interface GroupsPeerRevokeResult { revoked?: boolean } export interface GroupsPeerRegisterParams { profile?: string | null room_id: string member_id: string target_url: string target_profile: string grant: string catalog: Record cancellation_scope_id?: string | null trace_id?: string | null } export interface GroupsPeerRegisterResult { registered?: boolean mode: string transport_security: string target_install_id: string target_profile: string } export interface BotRelayRosterSyncParams { profile?: string | null agents?: RelayAgentRow[] | null } /** A roster row the Desktop pushes (``tools/bot_relay.py::_normalize_roster_row``); invalid rows are dropped server-side, so the shape stays open. */ export interface RelayAgentRow { profile?: string | null handle?: string | null connection_id?: string | null connection_label?: string | null title?: string | null description?: string | null online?: boolean | null [key: string]: unknown } export interface BotRelayRosterSyncResult { count: number } export interface BotRelayOutboxDrainParams { profile?: string | null } export interface BotRelayOutboxDrainResult { envelopes: RelayEnvelope[] } /** ``tools/bot_relay.py::enqueue_envelope``. */ export interface RelayEnvelope { id: string created_at: number from_profile: string from_handle: string target_connection: string target_profile: string target_handle: string message: string [key: string]: unknown } /** ``profile`` here is the TARGET profile on this gateway (also what the desktop route wrapper adds). */ export interface BotRelayDeliverParams { profile: string message: string from_profile?: string | null from_handle?: string | null from_connection?: string | null } export interface BotRelayDeliverResult { reply: string } export interface BotRelayReplyParams { profile?: string | null id: string reply?: string | null error?: string | null reason?: string | null } export interface OkResult { ok?: boolean } export interface BrowserControllerRegisterParams { session_id: string controller_id: string browser_profile_id: string capabilities?: string[] | null protocol_version?: unknown | null principal_id?: string | null } export interface BrowserControllerRegisterResult { scope: ControllerScope } export interface ControllerScope { principal_id: string profile_id: string session_id: string controller_id: string browser_profile_id: string transport_family: string capabilities: string[] } export interface BrowserControllerResultParams { session_id: string command_id: string ok?: unknown | null result?: unknown | null error?: unknown | null } export interface BrowserControllerResultResult { accepted: boolean } /** Every controller call names the session the controller is attached to. */ export interface BrowserControllerParams { session_id: string } export interface BrowserControllerDetachResult { detached?: boolean } export type PingParams = Record export interface PingResult { pong: boolean } export interface GatewayCapabilitiesResult { per_session_exclusive_submit: boolean } /** ``word`` is the token under the cursor (``@`` prefix = context reference); ``cwd`` / ``session_id`` pick the directory the listing resolves against. */ export interface CompletePathParams { profile?: string | null word?: string | null cwd?: string | null session_id?: string | null } export interface CompletionItemsResult { items?: CompletionItem[] } /** One popover row; ``kind`` rides only on slash completions (command vs skill). */ export interface CompletionItem { text: string display?: string meta?: string kind?: string | null } export interface CompleteSlashParams { text?: string | null } /** ``replace_from`` is the column the accepted item replaces from. */ export interface CompleteSlashResult { items?: CompletionItem[] replace_from?: number | null } export interface PasteCollapseParams { text?: string | null } export interface PasteCollapseResult { placeholder: string path: string lines: number } export interface ModelSaveKeyParams { slug: string api_key: string session_id?: string | null } export interface ModelSaveKeyResult { provider: ModelOptionProvider } export interface ModelDisconnectParams { slug: string session_id?: string | null } export interface ModelDisconnectResult { slug: string name: string disconnected: boolean } export interface ProfilesListParams { profile?: string | null include_sessions?: boolean | string | null } /** ``bot_mode_protocol`` tells clients this backend injects the teammate protocol itself. */ export interface ProfilesListResult { profiles?: ProfileRow[] bot_mode_protocol?: boolean } /** One roster row; the session fields are present only with ``include_sessions``. */ export interface ProfileRow { name: string path: string is_default?: boolean model?: string | null provider?: string | null description?: string display_name?: string skill_count?: number last_session?: ProfileSessionPreview | null worker_session?: ProfileWorkerSession | null canonical_session?: ProfileCanonicalSession | null ui_meta_revisions?: Record ui_meta?: Record | null has_avatar?: boolean } /** Newest human-facing session of a profile (``_latest_profile_session_rows``). */ export interface ProfileSessionPreview { id: string title?: string preview?: string started_at?: number last_active?: number message_count?: number } /** Newest kanban/tool worker row, so rosters can show a profile as working. */ export interface ProfileWorkerSession { id: string source?: string title?: string last_active?: number } /** The profile's "Bot Chat" registry row; ``resolved_id`` is the live compression tip. */ export interface ProfileCanonicalSession { id: string resolved_id: string root_title?: string title?: string preview?: string started_at?: number last_active?: number message_count?: number } /** ``clone_from`` omitted = fresh profile + bundled skills; ``mirror_credentials`` defaults on so a headless bot has a provider. */ export interface ProfilesCreateParams { profile?: string | null name: string description?: string | null clone_from?: string | null clone_all?: boolean | string | null clone_channels?: boolean | string | null no_skills?: boolean | string | null no_alias?: boolean | string | null soul?: string | null model?: string | null provider?: string | null share_auth?: boolean | string | null mirror_credentials?: boolean | string | null } export interface ProfilesCreateResult { ok?: boolean name: string path: string soul_written?: boolean model_set?: boolean mirrored: ProfileMirrored } /** What was copied from the launch profile; ``auth`` is ``"shared"`` under ``share_auth``. */ export interface ProfileMirrored { env?: boolean auth?: boolean | 'shared' model_inherited?: boolean voice?: boolean } export interface ProfileNameParams { profile?: string | null name?: string | null } /** Editor snapshot; ``toolsets_pinned`` says whether ``tools.enabled_toolsets`` is explicit. */ export interface ProfilesDescribeResult { name: string description?: string soul?: string model: ProfileModelPin skills?: CapabilityEntry[] toolsets?: ToolsetEntry[] toolsets_pinned?: boolean mcp_servers?: McpServerEntry[] } export interface ProfileModelPin { provider?: string default?: string } export interface CapabilityEntry { name: string enabled?: boolean } export interface ToolsetEntry { name: string enabled?: boolean label?: string description?: string tool_count?: number } export interface McpServerEntry { name: string enabled?: boolean transport?: string } /** Sections are independent; ``ui_meta_expected_revisions`` is a per-key compare-and-swap. */ export interface ProfilesConfigureParams { profile?: string | null name?: string | null ui_meta?: Record | null ui_meta_expected_revisions?: Record | null soul?: string | null description?: string | null model?: string | null provider?: string | null confirm_expensive_model?: boolean | string | null disabled_skills?: string[] | null enabled_toolsets?: string[] | null enabled_mcp_servers?: string[] | null } /** ``confirm_required`` mirrors ``config.set``: a guarded model pick wrote nothing yet. */ export interface ProfilesConfigureResult { ok: boolean applied: ProfilesConfigureApplied confirm_required?: boolean | null confirm_message?: string | null } /** Per-section outcome; only the sections the request carried are present. */ export interface ProfilesConfigureApplied { ui_meta?: boolean | null ui_meta_revisions?: Record | null ui_meta_conflicts?: Record | null soul?: boolean | null description?: boolean | null model?: boolean | null skills?: boolean | null toolsets?: boolean | null mcp_servers?: boolean | null } export interface UiMetaConflict { expected?: unknown actual?: number } /** ``data`` is a data URL or bare base64 (PNG/JPEG/WebP, sniffed); ``clear`` deletes instead. */ export interface ProfilesSetAssetParams { profile?: string | null name?: string | null asset?: string | null data?: string | null clear?: boolean | string | null } export interface ProfilesSetAssetResult { ok?: boolean asset: string size?: number removed?: number | null } export interface ProfilesGetAssetParams { profile?: string | null name?: string | null asset?: string | null } /** Absent is ``found: false``, not an error. */ export interface ProfilesGetAssetResult { found: boolean mime?: string | null size?: number | null data?: string | null } export interface ProfilesRememberOnboardingParams { profile?: string | null answers?: OnboardingAnswers | null } /** ``tui_gateway/onboarding_personalization.py`` — the facts agreed during onboarding. */ export interface OnboardingAnswers { name?: string | null context?: string | null theme?: string | null accent?: string | null layout?: string | null focus?: string[] | null connectors?: string[] | null [key: string]: unknown } export interface ProfilesRememberOnboardingResult { saved?: boolean profile?: string target?: string } export interface VaultListResult { items?: VaultItem[] } /** Metadata-only view (``VaultItemMeta.to_dict`` + ``backend``); never a secret. */ export interface VaultItem { id: string kind: string label: string origin?: string | null created_at?: string identifier?: string | null identifier_type?: string | null has_otp?: boolean | null backend: string } export interface VaultSourcesResult { sources?: VaultSource[] } export interface VaultSource { name: string display_name: string enabled: boolean needs_unlock: boolean unlocked: boolean installed: boolean } export interface VaultSourceSetParams { profile?: string | null name?: string | null enabled?: boolean | null } export interface VaultSourceSetResult { name: string enabled: boolean } /** The master password is consumed by the manager CLI and never stored or logged. */ export interface VaultUnlockParams { profile?: string | null name?: string | null password?: string | null } export interface VaultUnlockResult { name: string unlocked?: boolean } export interface VaultLockParams { profile?: string | null name?: string | null } export interface VaultLockResult { locked?: boolean } /** ``secret`` goes straight into the encrypted store; the result carries only the new id. */ export interface VaultAddParams { profile?: string | null kind?: VaultKind | null label?: string | null origin?: string | null secret?: Record | null } export type VaultKind = 'login' | 'payment' | 'address' export interface VaultAddResult { id: string } export interface VaultRemoveParams { profile?: string | null id?: string | null } export interface VaultRemoveResult { removed: boolean } export interface SessionForeignListParams { profile?: string | null source?: ForeignSource | null offset?: number | null limit?: number | null } export type ForeignSource = 'claude' | 'codex' /** ``unreadable`` counts logs on this page that failed to parse. */ export interface SessionForeignListResult { sessions?: ForeignSessionRow[] next_offset?: number | null host: string unreadable?: number } /** ``hermes_cli/foreign_sessions_browser.py::list_foreign_sessions`` — ``id`` is an opaque handle, never a path. */ export interface ForeignSessionRow { id: string source: ForeignSource label: string title?: string cwd?: string | null mtime: number turn_count?: number excerpt?: string } export interface SessionForeignIdParams { profile?: string | null id?: string | null } /** Bounded to the last 40 turns / 8000 chars each; ``already_imported`` is the local id. */ export interface SessionForeignPreviewResult { messages?: ForeignTurn[] total?: number truncated?: boolean already_imported?: string | null cwd?: string | null } export interface ForeignTurn { role: string content: string } export interface SessionForeignImportResult { session_id: string already_imported?: boolean } /** ``delegations`` is reserved for async delegation records and is currently always empty. */ export interface SubagentListResult { subagents?: SubagentSnapshot[] delegations?: Record[] } /** ``methods_subagents._SUBAGENT_SNAPSHOT_FIELDS`` projection of one live child record. */ export interface SubagentSnapshot { subagent_id: string parent_id?: string | null depth?: number | null goal?: string | null delegation_id?: string | null model?: string | null started_at?: number | null status?: SubagentStatus | null tool_count?: number | null last_tool?: string | null accepting_steer?: boolean | null } /** Lifecycle of one delegated child (``tools/delegate_tool_child_run.py``); ``failed`` / ``error`` / ``timeout`` / ``interrupted`` / ``completed`` are terminal. */ export type SubagentStatus = 'queued' | 'running' | 'completed' | 'failed' | 'error' | 'timeout' | 'interrupted' export interface SubagentIdParams { session_id: string profile?: string | null subagent_id: string } export interface SubagentInterruptResult { found: boolean subagent_id: string } /** ``available`` is false while the child has no live transcript yet (or it was cleaned up). */ export interface SubagentTailResult { subagent_id: string available?: boolean text?: string truncated?: boolean } /** ``methods_projects._projects_payload``: every project (archived included) + the active id. */ export interface ProjectsPayload { projects: ProjectInfo[] active_id?: string | null } /** ``hermes_cli/projects_db.py::Project.to_dict`` — one stored project with its folders. */ export interface ProjectInfo { id: string slug: string name: string description?: string | null icon?: string | null color?: string | null board_slug?: string | null primary_path?: string | null archived?: boolean created_at: number folders?: ProjectFolder[] } /** ``hermes_cli/projects_db.py::ProjectFolder.to_dict``. */ export interface ProjectFolder { path: string label?: string | null is_primary?: boolean added_at?: number | null } /** Any method addressed at one stored project (``5062`` when the id resolves to nothing). */ export interface ProjectIdParams { profile?: string | null id: string } export interface ProjectResult { project: ProjectInfo } /** ``use`` also activates the new project. */ export interface ProjectsCreateParams { profile?: string | null name: string folders?: string[] | null slug?: string | null primary_path?: string | null description?: string | null icon?: string | null color?: string | null board_slug?: string | null use?: boolean } export interface OptionalProjectResult { project?: ProjectInfo | null } /** Absent keys are left untouched; ``''`` clears ``color`` / ``icon``. */ export interface ProjectsUpdateParams { profile?: string | null id: string name?: string | null description?: string | null icon?: string | null color?: string | null board_slug?: string | null } export interface ProjectsAddFolderParams { profile?: string | null id: string path: string label?: string | null is_primary?: boolean } export interface ProjectFolderParams { profile?: string | null id: string path: string } export interface ProjectsArchiveParams { profile?: string | null id: string restore?: boolean } /** No ``id`` (or null) clears the active project. */ export interface ProjectsSetActiveParams { profile?: string | null id?: string | null } export interface ActiveIdResult { active_id?: string | null } /** Absent ``cwd`` resolves the gateway's default completion cwd. */ export interface ProjectsForCwdParams { profile?: string | null cwd?: string | null } export interface ProjectsForCwdResult { project?: ProjectInfo | null cwd: string branch?: string } /** ``scan`` asks the host to walk the policy roots itself (remote-gateway desktop). */ export interface ProjectsDiscoverReposParams { profile?: string | null scan?: boolean } export interface ProjectsDiscoverReposResult { repos: DiscoveredRepo[] discovery_policy?: RepoDiscoveryPolicy | null } /** ``methods_projects._discover_repos_payload`` row: a git root with session totals. */ export interface DiscoveredRepo { root: string label?: string sessions?: number last_active?: number } /** ``methods_projects._repo_discovery_policy`` — the effective ``desktop.repo_scan_*`` config. */ export interface RepoDiscoveryPolicy { enabled: boolean roots: string[] exclude_paths: string[] } /** Repos as ``{root, label}`` objects or bare root strings; entries without a root are skipped. */ export interface ProjectsRecordReposParams { profile?: string | null repos?: (RecordRepoItem | string)[] | null discovery_policy?: RepoDiscoveryPolicyParams | null } export interface RecordRepoItem { root: string label?: string | null } /** The policy the desktop scanned under (short or ``repo_scan_*`` long keys both accepted). */ export interface RepoDiscoveryPolicyParams { enabled?: boolean | null roots?: string[] | null exclude_paths?: string[] | null repo_scan_enabled?: boolean | null repo_scan_roots?: string[] | null repo_scan_exclude_paths?: string[] | null } export interface ProjectsRecordReposResult { repos: DiscoveredRepo[] discovery_policy?: RepoDiscoveryPolicy | null accepted: boolean } export interface ProjectsTreeParams { profile?: string | null preview_limit?: number | null session_limit?: number | null } export interface ProjectsTreeResult { projects: ProjectTreeNode[] active_id?: string | null scoped_session_ids?: string[] } /** ``project_tree._project_node`` — explicit, auto (git root) or the synthetic Home bucket. */ export interface ProjectTreeNode { id: string label: string path?: string | null color?: string | null icon?: string | null isAuto?: boolean isNoProject?: boolean sessionCount?: number lastActive?: number totalTokens?: number totalCostUsd?: number repos?: ProjectTreeRepo[] previewSessions?: ProjectTreeSession[] } export interface ProjectTreeRepo { id: string label: string path?: string | null groups?: ProjectTreeLane[] sessionCount?: number } /** One branch / worktree / kanban lane inside a repo; ``sessions`` is empty unless hydrated. */ export interface ProjectTreeLane { id: string label: string path?: string | null isMain?: boolean isKanban?: boolean sessions?: ProjectTreeSession[] } /** ``methods_projects._project_tree_row`` + ``project_tree.stamp_profile``: the minimal row the sidebar renders, stamped with the profile it belongs to. */ export interface ProjectTreeSession { id: string title?: string | null preview?: string | null source?: string | null model?: string | null started_at?: number | null ended_at?: number | null last_active?: number | null message_count?: number tool_call_count?: number input_tokens?: number output_tokens?: number is_active?: boolean cwd?: string | null git_branch?: string | null git_repo_root?: string | null parent_session_id?: string | null pinned?: boolean | null unread?: boolean | null archived?: boolean | null actual_cost_usd?: number | null estimated_cost_usd?: number | null handoff_platform?: string | null handoff_state?: string | null _lineage_root_id?: string | null _lineage_ids?: string[] | null profile?: string | null [key: string]: unknown } export interface ProjectsProjectSessionsParams { profile?: string | null project_id: string session_limit?: number | null } export interface ProjectsProjectSessionsResult { project?: ProjectTreeNode | null } /** ``knownRevision``: the spritesheet revision the caller already holds (send-once bytes). */ export interface PetInfoParams { profile?: string | null knownRevision?: string | null } /** ``server._pet_sprite_payload`` behind ``enabled``; every sprite field is absent when the pet display is off, ``spritesheetBase64`` is elided when ``spritesheetUnchanged``. */ export interface PetInfoResult { enabled: boolean slug?: string | null displayName?: string | null mime?: string | null spritesheetBase64?: string | null spritesheetRevision?: string | null spritesheetUnchanged?: boolean | null frameW?: number | null frameH?: number | null framesPerState?: number | null framesByState?: Record | null framesByRow?: Record | null loopMs?: number | null scale?: number | null stateRows?: string[] | null [key: string]: unknown } export interface PetInfoMetaResult { enabled: boolean slug?: string | null displayName?: string | null scale?: number | null spritesheetRevision?: string | null } /** ``graphics`` opts into the kitty payload when the TTY speaks it; ``cols`` overrides the width. */ export interface PetCellsParams { profile?: string | null state?: string | null cols?: number | null graphics?: boolean } /** Unicode: ``frames`` is frame → row → cell ``[tr,tg,tb,ta, br,bg,bb,ba]``; kitty (``graphics`` set): ``frames`` are transmit escapes and ``placeholder`` the text grid. */ export interface PetCellsResult { enabled: boolean slug?: string | null displayName?: string | null state?: string | null cols?: number | null frameMs?: number | null frames?: number[][][][] | string[] | null scale?: number | null graphics?: string | null imageId?: number | null color?: string | null rows?: number | null placeholder?: string[] | null } export interface PetGalleryParams { profile?: string | null localOnly?: boolean } export interface PetGalleryResult { enabled: boolean active?: string pets?: PetGalleryEntry[] } export interface PetGalleryEntry { slug: string displayName: string installed: boolean spritesheetUrl?: string curated?: boolean | null generated?: boolean } export interface PetSlugParams { profile?: string | null slug: string } export interface PetSlugResult { ok: boolean slug: string displayName?: string | null } export interface PetRenameParams { profile?: string | null slug: string name: string } export interface PetExportResult { ok: boolean filename: string zipBase64: string } /** ``url``: spritesheet source for a not-yet-installed pet. */ export interface PetThumbParams { profile?: string | null slug: string url?: string | null } export interface PetThumbResult { ok: boolean slug: string dataUri?: string | null } export interface PetScaleParams { profile?: string | null scale?: unknown } export interface PetScaleResult { ok: boolean scale: number } /** ``text`` is normally a string; the relay / hosted paths may hand a structured (parts list) payload, and the busy path renders it. Truncation (rewind / edit / regenerate) needs explicit consent: ``confirm_truncate`` plus one durable target (``truncate_before_row_id`` preferred, ``truncate_before_message_id``, or the legacy ``truncate_before_user_ordinal``). */ export interface PromptSubmitParams { session_id: string profile?: string | null text?: unknown display_kind?: string | null interrupted?: boolean | null queued?: boolean | null surface?: string | null voice_context?: string | null truncate_before_user_ordinal?: number | null truncate_before_row_id?: number | null truncate_before_message_id?: string | null confirm_truncate?: boolean | null confirm_empty_truncate?: boolean | null rebind_survivor_row_ids?: number[] | null } /** ``status`` is absent only on the typed-stop-phrase reply (``voice_stopped``). After a truncation the survivor row ids let the client rebind its cached ``rowId``s (``None`` map entries: drop the cached id). ``turn_isolation`` marks a compute-host dispatch. */ export interface PromptSubmitResult { status?: PromptSubmitStatus | null voice_stopped?: boolean | null survivor_user_row_ids?: (number | null)[] | null survivor_row_id_map?: Record | null turn_isolation?: boolean | null } export type PromptSubmitStatus = 'streaming' | 'queued' | 'steered' | 'redirected' export interface ClipboardPasteParams { session_id: string profile?: string | null } /** ``methods_prompt.py::_attached_image_result``: the image is queued for the next turn. */ export interface AttachedImageResult { name?: string | null width?: number | null height?: number | null token_estimate?: number | null attached: boolean path?: string | null count?: number | null remainder?: string | null text?: string | null bytes?: number | null message?: string | null } export interface ImageAttachParams { session_id: string profile?: string | null path: string } /** ``content_base64`` (or the ``data`` alias) carries the bytes; ``filename`` / ``ext`` only hint the extension — magic bytes decide. */ export interface ImageAttachBytesParams { session_id: string profile?: string | null content_base64?: string | null data?: string | null filename?: string | null ext?: string | null } /** Host ``path`` or base64 ``content_base64`` / ``data``; ``first_page`` / ``last_page`` bound the render (per-call page cap enforced server-side). */ export interface PdfAttachParams { session_id: string profile?: string | null path?: string | null content_base64?: string | null data?: string | null filename?: string | null first_page?: number | null last_page?: number | null } export interface PdfAttachResult { attached: boolean filename: string pages_attached: number pages: PdfPage[] count: number text: string } export interface PdfPage { name?: string | null width?: number | null height?: number | null token_estimate?: number | null path: string page: number } /** ``path`` when the file is gateway-visible, else ``data_url`` carries the bytes; ``name`` labels an uploaded file. */ export interface FileAttachParams { session_id: string profile?: string | null path?: string | null data_url?: string | null name?: string | null } export interface FileAttachResult { attached: boolean name: string path: string ref_path: string ref_text: string uploaded: boolean } export interface ImageDetachParams { session_id: string profile?: string | null path: string } export interface ImageDetachResult { detached: boolean count: number } export interface InputDetectDropParams { session_id: string profile?: string | null text?: string | null } /** ``matched: false`` alone when the text is not a drop; an image drop is queued immediately (``is_image`` + ``count``), a file drop only yields the ``text`` to insert. */ export interface InputDetectDropResult { name?: string | null width?: number | null height?: number | null token_estimate?: number | null matched: boolean is_image?: boolean | null path?: string | null count?: number | null text?: string | null } export interface SideAgentParams { session_id: string profile?: string | null text: string } /** The side agent runs detached; its answer lands on the parent session as an event carrying this ``task_id``. */ export interface TaskIdResult { task_id: string } export interface PreviewRestartParams { session_id: string profile?: string | null url: string cwd?: string | null context?: string | null } export interface ClarifyLockParams { request_id: string question_id: string answer?: unknown profile?: string | null } /** ``remaining`` lists the qids still unanswered; the lock that empties it resolves the request. ``expired``: the wait already ended (timeout / cancel) — not an error. */ export interface ClarifyLockResult { status: ClarifyLockStatus remaining?: string[] | null } export type ClarifyLockStatus = 'ok' | 'expired' export interface RequestAnswerParams { id: string result: Record profile?: string | null } export interface RequestAnswerResult { status: ClarifyLockStatus } export interface ApprovalPendingParams { session_id: string profile?: string | null } export interface ApprovalPendingResult { approvals: PendingApproval[] } /** One unresolved ``tools/approval.py`` gateway queue entry as ``server._approval_request_payload`` renders it (command redacted; ``choices`` precomputed). The key set is owned by the approval tool. */ export interface PendingApproval { request_id?: string | null command?: string | null description?: string | null pattern_key?: string | null pattern_keys?: string[] | null allow_permanent?: boolean | null allow_session?: boolean | null smart_denied?: boolean | null choices?: string[] | null tool_name?: string | null [key: string]: unknown } export interface ApprovalReceivedParams { session_id: string profile?: string | null request_id: string } export interface ApprovalReceivedResult { acknowledged: boolean } /** ``choice`` is one of the offered ``approval`` choices (once / session / always / deny); ``all`` resolves every pending approval, ``request_id`` a specific one, neither the oldest. */ export interface ApprovalRespondParams { session_id: string profile?: string | null choice?: string | null all?: boolean | null request_id?: string | null } export interface ApprovalRespondResult { resolved: number } export interface VoiceToggleParams { action?: VoiceToggleAction profile?: string | null } export type VoiceToggleAction = 'status' | 'on' | 'off' | 'tts' /** ``methods_voice.py::_voice_status_payload`` (+ the requirements probe on ``status``, the spoken stop hint on ``on``). */ export interface VoiceToggleResult { enabled: boolean record_key: string tts: boolean stop_hint?: string | null available?: boolean | null audio_available?: boolean | null stt_available?: boolean | null details?: string | null } export interface VoiceRecordParams { action?: VoiceRecordAction session_id?: string | null profile?: string | null } export type VoiceRecordAction = 'start' | 'stop' export interface VoiceRecordResult { status: VoiceRecordStatus reason?: string | null } export type VoiceRecordStatus = 'recording' | 'stopped' | 'busy' export interface VoiceTtsParams { text: string profile?: string | null } export interface VoiceTtsResult { status: string } /** ``surface`` names the caller ("tui" | "gui"); ``persist`` is the explicit gesture that also flips ``wake_word.enabled`` on; ``client_capture`` asks for PCM streamed via wake.feed. */ export interface WakeStartParams { surface?: string | null persist?: boolean | null client_capture?: boolean | null session_id?: string | null profile?: string | null } /** ``started: false`` carries ``reason`` (unavailable / disabled / disabled_for_surface / owned); ``sample_rate`` / ``frame_length`` describe the PCM frames the armed detector expects. */ export interface WakeStartResult { started: boolean reason?: string | null hint?: string | null phrase?: string | null provider?: string | null owner_surface?: string | null enabled_persisted?: boolean | null capture?: string | null sample_rate?: number | null frame_length?: number | null } export interface WakeStopParams { persist?: boolean | null profile?: string | null } export interface WakeStopResult { reason?: string | null stopped: boolean disabled_persisted: boolean } export interface WakeControlParams { profile?: string | null } export interface WakePauseResult { reason?: string | null paused: boolean } export interface WakeResumeResult { reason?: string | null resumed: boolean } export interface WakeStatusParams { surface?: string | null client_capture?: boolean | null profile?: string | null } /** ``enabled`` is config truth; ``listening`` is this caller's armed detector; ``audio_silent`` means armed but deaf (see ``hint``). */ export interface WakeStatusResult { listening: boolean owned_by_caller: boolean owner_surface?: string | null phrase: string provider: string configured_surface: string input_device: WakeInputDevice available: boolean hint: string enabled: boolean audio_silent: boolean capture: string local_input_available: boolean sample_rate: number frame_length: number } /** ``tools/wake_word.py::_describe_input_device`` — PortAudio diagnostics for the configured mic. */ export interface WakeInputDevice { selector?: number | string | null name?: string | null error?: string | null max_input_channels?: number | null default_samplerate?: number | null hostapi_index?: number | null hostapi?: string | null [key: string]: unknown } /** ``pcm`` (or the ``pcm_b64`` alias): base64 int16 mono little-endian, 16 kHz only. */ export interface WakeFeedParams { pcm?: string | null pcm_b64?: string | null sample_rate?: number | null profile?: string | null } export interface WakeFeedResult { reason?: string | null fed: boolean } export interface SessionCreateParams { profile?: string | null cols?: number | null source?: string | null cwd?: string | null messages?: SeedMessage[] | null parent_session_id?: string | null title?: string | null model?: string | null provider?: string | null reasoning_effort?: string | null fast?: boolean | null close_on_disconnect?: boolean hidden?: boolean room_plumbing?: boolean follow_profile_config?: boolean } /** One create-time transcript row (``session_history._coerce_seed_history``); ``text`` is the legacy alias of ``content``; only ``display_kind: "hidden"`` is accepted from the wire. Clients forward stored rows verbatim (``_row_id``, ``timestamp``, …) and the coercer drops what it does not use, so the row stays open. */ export interface SeedMessage { role: string content?: string | null text?: string | null display_kind?: string | null [key: string]: unknown } export interface SessionCreateResult { session_id: string stored_session_id: string message_count: number messages: TranscriptMessage[] info: SessionLiveInfo } /** One transcript row as the gateway PROJECTS it for renderers (``session_history._project_history``): ``text`` (never ``content``), display-only ``timestamp`` / ``display_kind`` / ``display_metadata``, the durable ``row_id`` rewind targets, and for tool rows ``name`` + ``context`` preview + full ``args``. Assistant detail sidecars (``reasoning``, …) ride as extra keys. */ export interface TranscriptMessage { role: string text?: string | null timestamp?: number | null row_id?: number | null display_kind?: string | null display_metadata?: unknown | null name?: string | null context?: string | null args?: Record | null reasoning?: string | null [key: string]: unknown } /** ``session_id`` is the STORED id (or an exact title); the reply's ``session_id`` is the runtime id. */ export interface SessionResumeParams { session_id: string profile?: string | null cols?: number | null source?: string | null lazy?: boolean defer_history?: boolean omit_messages?: boolean eager_build?: boolean close_on_disconnect?: boolean } export interface SessionResumeResult { session_id: string message_count: number messages: TranscriptMessage[] info: SessionLiveInfo stored_session_id?: string | null resumed?: string | null session_key?: string | null messages_omitted?: boolean | null hydrating?: boolean | null running?: boolean | null turn_started_at?: number | null started_at?: number | null status?: string | null inflight?: InflightTurn | null queued?: QueuedPrompt | null pending_approval?: PendingApproval | null open_requests?: OpenRequestEntry[] | null pending_connection?: ConnectionRequestPayload | null todo_state?: TodoState | null auto_continue?: AutoContinue | null } /** ``session_auto_continue._inflight_snapshot``: the live (or retained failed) turn a reconnecting client rebuilds its bubbles from. */ export interface InflightTurn { assistant?: string streaming?: boolean user?: string corrections?: string[] | null correction_offsets?: number[] | null error?: string | null status?: string | null recoverable?: boolean | null error_surface?: Record | null } export interface QueuedPrompt { user: string } /** One unanswered server→client request (``server_requests.Request.snapshot``); the reconnecting client re-delivers it to its request handlers. */ export interface OpenRequestEntry { id: string method: string params: Record } /** ``ConnectionOperation.request_payload``: opens the card; also the ``pending_connection`` resume snapshot so a client that missed the event restores the card with the server's deadline. */ export interface ConnectionRequestPayload { op_id: string deadline_at: number timeout_seconds: number targets: ConnectionOperationTarget[] tool_call_id?: string | null } /** ``tool_progress._normalize_todo_state``: the authoritative todo snapshot. */ export interface TodoState { todos: Record[] revision: number } /** A crash-interrupted turn was scheduled to continue right after this resume. */ export interface AutoContinue { attempt: number interrupted_at: number } export interface SessionActivateParams { session_id: string profile?: string | null cols?: number | null omit_messages?: boolean } export interface SessionActivateResult { session_id: string message_count: number messages: TranscriptMessage[] info: SessionLiveInfo stored_session_id?: string | null resumed?: string | null session_key?: string | null messages_omitted?: boolean | null hydrating?: boolean | null running?: boolean | null turn_started_at?: number | null started_at?: number | null status?: string | null inflight?: InflightTurn | null queued?: QueuedPrompt | null pending_approval?: PendingApproval | null open_requests?: OpenRequestEntry[] | null pending_connection?: ConnectionRequestPayload | null todo_state?: TodoState | null auto_continue?: AutoContinue | null } export interface SessionListParams { profile?: string | null title?: string | null limit?: number | null include_hidden?: boolean } export interface SessionListResult { sessions: SessionListRow[] } /** ``methods_session._session_row_summary``; ``resolved_id`` only on a title lookup that followed a compression lineage to its tip. */ export interface SessionListRow { id: string resolved_id?: string | null title?: string preview?: string started_at?: number message_count?: number source?: string } export interface SessionMostRecentParams { profile?: string | null } export interface SessionMostRecentResult { session_id: string | null title?: string | null started_at?: number | null source?: string | null } export interface SessionActiveListParams { profile?: string | null current_session_id?: string | null } export interface SessionActiveListResult { sessions: SessionActiveItem[] } /** ``server._session_live_item``. */ export interface SessionActiveItem { current: boolean id: string last_active: number message_count: number model: string preview: string session_key: string started_at: number status: LiveSessionStatus title: string } export type LiveSessionStatus = 'idle' | 'starting' | 'waiting' | 'working' | 'streaming' | 'resuming' /** ``session_id`` is the STORED id. */ export interface SessionDeleteParams { session_id: string profile?: string | null } export interface SessionDeleteResult { deleted: string } export interface SessionTitleParams { session_id: string profile?: string | null title?: string | null } export interface SessionTitleResult { title: string session_key?: string | null pending?: boolean | null } /** ``session_id`` is a live runtime id first, else a stored id / key / title. */ export interface SessionSetHiddenParams { session_id: string hidden?: boolean profile?: string | null } export interface SessionSetHiddenResult { hidden: boolean session_key: string } export interface SessionWorkspaceMoveParams { profile?: string | null session_key: string cwd: string } export interface SessionWorkspaceMoveResult { cwd: string branch?: string | null git_repo_root?: string | null } export interface SessionCwdSetParams { session_id: string profile?: string | null cwd: string } /** The refreshed ``session.info`` view (full agent view, or the lazy shape). */ export interface SessionCwdSetResult { model?: string provider?: string reasoning_effort?: string service_tier?: string fast?: boolean yolo?: boolean approval_mode?: string tools?: Record skills?: Record cwd?: string branch?: string | null project?: ProjectRef | null terminal_backend?: string personality?: string running?: boolean turn_started_at?: number | null title?: string stored_session_id?: string desktop_contract?: number | string | null version?: string release_date?: string update_behind?: unknown | null update_command?: string usage?: Usage | null profile_name?: string | null mcp_servers?: McpServerStatus[] system_prompt?: string | null credential_warning?: string | null lazy?: boolean | null [key: string]: unknown } export interface SessionCloseParams { session_id: string profile?: string | null } export interface SessionCloseResult { closed: boolean } export interface SessionBranchParams { session_id: string profile?: string | null name?: string | null count?: number | null } export interface SessionBranchResult { session_id: string stored_session_id: string title: string parent: string message_count: number messages: TranscriptMessage[] info: SessionLiveInfo } export interface SessionUndoParams { session_id: string profile?: string | null } export interface SessionUndoResult { removed: number } export interface SessionSaveParams { session_id: string profile?: string | null } /** Under turn isolation the compute host's result passes through verbatim. */ export interface SessionSaveResult { file?: string | null [key: string]: unknown } export interface SessionStatusParams { session_id: string profile?: string | null } export interface SessionStatusResult { output: string } export interface SessionHistoryParams { session_id: string profile?: string | null } export interface SessionHistoryResult { count: number messages: TranscriptMessage[] } export interface SessionUsageParams { session_id: string profile?: string | null } export interface SessionUsageResult { model?: string input?: number output?: number reasoning?: number prompt?: number completion?: number total?: number calls?: number compressions?: number | null context_used?: number | null context_max?: number | null context_percent?: number | null context_source?: string | null context_estimated?: boolean | null cache_hit_pct?: number | null cache_read?: number | null cache_write?: number | null avg_latency_s?: number | null avg_tps?: number | null active_subagents?: number | null dev_credits_spent_micros?: number | null cost_usd?: number | null cost_status?: string | null credits_lines?: string[] | null [key: string]: unknown } export interface SessionContextBreakdownParams { session_id: string profile?: string | null } /** ``agent.context_breakdown.compute_session_context_breakdown`` (empty categories before the agent builds). */ export interface SessionContextBreakdownResult { categories: ContextCategory[] context_max: number context_percent: number context_used: number estimated_total: number context_estimated: boolean context_source: string model: string } export interface ContextCategory { color: string id: string label: string tokens: number } export interface SessionCompressParams { session_id: string profile?: string | null focus_topic?: string | null } /** In-process: the before/after summary + replacement transcript. Compute host: its result passes through (hence open) with ``turn_isolation``; a lock held elsewhere answers ``compressed: false``. */ export interface SessionCompressResult { status?: string | null removed?: number | null before_messages?: number | null after_messages?: number | null before_tokens?: number | null after_tokens?: number | null summary?: CompressionSummary | null usage?: Usage | null info?: SessionLiveInfo | null messages?: TranscriptMessage[] | null compressed?: boolean | null lock_held?: boolean | null message?: string | null turn_isolation?: boolean | null host_ack?: Record | null [key: string]: unknown } /** ``agent.manual_compression_feedback.summarize_manual_compression``. */ export interface CompressionSummary { noop?: boolean aborted?: boolean refused_would_grow?: boolean | null fallback_used?: boolean | null headline?: string token_line?: string note?: string | null [key: string]: unknown } export interface SessionInterruptParams { session_id: string profile?: string | null expected_hosted_task_id?: string | null } export interface SessionInterruptResult { status: InterruptStatus interrupted?: boolean | null turn_isolation?: boolean | null } export type InterruptStatus = 'interrupted' | 'not_interrupted' export interface SessionCorrectionParams { session_id: string profile?: string | null text: string } export interface SessionCorrectionResult { status: CorrectionStatus text: string } export type CorrectionStatus = 'queued' | 'redirected' | 'rejected' export interface SpawnTreeSaveParams { profile?: string | null subagents: Record[] session_id?: string | null started_at?: number | null finished_at?: number | null label?: string | null } export interface SpawnTreeSaveResult { path: string session_id: string } export interface SpawnTreeListParams { profile?: string | null session_id?: string | null cross_session?: boolean limit?: number | null } export interface SpawnTreeListResult { entries: SpawnTreeEntry[] } /** Index row (``server._append_spawn_tree_index``) or a legacy file scan. */ export interface SpawnTreeEntry { path: string session_id?: string | null started_at?: number | null finished_at?: number | null label?: string count?: number [key: string]: unknown } export interface SpawnTreeLoadParams { profile?: string | null path: string } /** The snapshot file as written by ``spawn_tree.save`` (open: the file is the contract). */ export interface SpawnTreeLoadResult { session_id?: string | null started_at?: number | null finished_at?: number | null label?: string | null subagents?: Record[] [key: string]: unknown } export interface TerminalResizeParams { session_id: string profile?: string | null cols?: number | null } export interface TerminalResizeResult { cols: number } export interface SessionEventsSinceParams { session_id: string profile?: string | null last_seen?: number | null } export interface SessionEventsSinceResult { events: Record[] latest_seq: number truncated: boolean count: number epoch: string open_requests: OpenRequestEntry[] } export interface SessionEventsStatsParams { profile?: string | null } /** ``event_replay.replay_stats``. */ export interface SessionEventsStatsResult { sessions: number events: number bytes: number max_per_session: number max_bytes_per_session: number max_bytes_process: number } /** Needs a ``template`` or ``instructions`` / ``input``; a live ``session_id`` lends its model. */ export interface LlmOneshotParams { profile?: string | null template?: string | null instructions?: string | null input?: string | null variables?: Record | null task?: string | null temperature?: number | null max_tokens?: number | null session_id?: string | null } export interface LlmOneshotResult { text: string } export interface SystemBatteryParams { profile?: string | null } export interface SystemBatteryResult { available: boolean percent?: number | null plugged?: boolean | null category?: BatteryCategory } /** ``agent/battery.py::battery_category`` colour bucket. */ export type BatteryCategory = 'good' | 'warn' | 'bad' | 'critical' | 'dim' export interface ProcessStopParams { session_id?: string | null profile?: string | null } export interface ProcessStopResult { killed: number } export interface AgentsListParams { profile?: string | null } export interface AgentsListResult { processes?: AgentProcessRow[] } export interface AgentProcessRow { session_id: string command: string status: string uptime: number } export interface ProcessListParams { session_id: string profile?: string | null } export interface ProcessListResult { processes?: ProcessEntry[] } /** ``tools/process_registry.py::list_sessions`` row plus the gateway's ``output_tail``. */ export interface ProcessEntry { session_id: string command?: string cwd?: string | null pid?: number | null owner_task_id?: string | null started_at?: string | null uptime_seconds?: number | null status?: string output_preview?: string output_tail?: string | null session_scoped?: boolean | null watch_patterns?: string[] | null watch_hit?: boolean | null notify_on_complete?: boolean | null exit_code?: number | null detached?: boolean | null [key: string]: unknown } export interface ProcessKillParams { session_id: string process_id: string profile?: string | null } /** ``tools/process_registry.py::kill_process`` snapshot; ``error`` rides on the failure statuses. */ export interface ProcessKillResult { status: ProcessKillStatus session_id?: string | null command?: string | null exit_code?: number | null completion_reason?: string | null termination_source?: string | null output?: string | null error?: string | null [key: string]: unknown } export type ProcessKillStatus = 'killed' | 'already_exited' | 'not_found' | 'error' export interface ShellExecParams { command: string profile?: string | null } export interface ShellExecResult { stdout: string stderr: string code: number } export interface CliExecParams { argv: string[] timeout?: number | null profile?: string | null } export interface CliExecResult { blocked: boolean code: number output: string hint?: string | null } export interface CommandsCatalogParams { session_id?: string | null profile?: string | null } export interface CommandsCatalogResult { pairs?: string[][] sub?: Record canon?: Record commands?: Record categories?: CommandCategory[] skills?: Record skill_count?: number warning?: string } export interface CommandCatalogMeta { argument_mode?: ArgumentMode | null desktop?: string | null } export type ArgumentMode = 'options' | 'text' | 'mixed' export interface CommandCategory { name: string pairs?: string[][] } export interface SkillCatalogEntry { usage?: number origin?: string } export interface CommandResolveParams { name?: string | null profile?: string | null } export interface CommandResolveResult { canonical: string description: string category: string } export interface CommandDispatchParams { name: string arg?: string | null session_id?: string | null profile?: string | null } /** One structured directive: ``exec``/``plugin`` carry ``output``; ``alias`` a ``target``; ``send``/``prefill``/``skill`` a ``message`` (UIs render ``display``, never ``message``). */ export interface CommandDispatchResult { type: DispatchType output?: string | null target?: string | null message?: string | null notice?: string | null display?: string | null name?: string | null status?: string | null } /** ``apps/shared/src/slash.ts::parseCommandDispatch`` branches on this. */ export type DispatchType = 'exec' | 'alias' | 'plugin' | 'send' | 'skill' | 'prefill' export interface SlashExecParams { session_id: string command: string profile?: string | null } /** Plain worker/plugin text in ``output`` (+ ``warning``), or — when the command was rerouted to ``command.dispatch`` — that method's directive fields with ``type`` set. */ export interface SlashExecResult { output?: string | null warning?: string | null type?: DispatchType | null target?: string | null message?: string | null notice?: string | null display?: string | null name?: string | null status?: string | null } export interface InsightsGetParams { days?: number | null profile?: string | null } export interface InsightsGetResult { days: number sessions: number messages: number } export interface ConfigShowParams { profile?: string | null } export interface ConfigShowResult { sections?: ConfigSection[] [key: string]: unknown } export interface ConfigSection { title: string rows?: string[][] } export interface RollbackListParams { session_id: string profile?: string | null } export interface RollbackListResult { enabled: boolean checkpoints?: RollbackCheckpoint[] } export interface RollbackCheckpoint { hash?: string timestamp?: string message?: string } export interface RollbackRestoreParams { session_id: string hash: string file_path?: string | null profile?: string | null } /** ``tools/checkpoint_manager.py::restore`` outcome; ``history_removed`` is added for a full (non-file) restore that also rewound the live transcript. */ export interface RollbackRestoreResult { success: boolean restored_to?: string | null reason?: string | null directory?: string | null file?: string | null restored_files?: string[] | null skipped_user_edits?: string[] | null skipped_oversize?: string[] | null failed_deletes?: string[] | null history_removed?: number | null error?: string | null debug?: unknown | null [key: string]: unknown } export interface RollbackDiffParams { session_id: string hash: string profile?: string | null } export interface RollbackDiffResult { stat?: string diff?: string rendered?: string | null } export interface CronManageParams { action?: CronAction name?: string | null include_disabled?: boolean | string | null schedule?: string | null prompt?: string | null repeat?: number | string | null continuity?: boolean | string | null deliver?: string | null profile?: string | null } export type CronAction = 'list' | 'add' | 'remove' | 'pause' | 'resume' /** Pass-through of ``tools/cronjob_tools.py::cronjob`` JSON: ``list`` → ``jobs``/``count`` (+ ``scoped`` when profile-scoped); ``add`` → the created job's summary + ``job``; ``remove`` → ``removed_job``; ``pause``/``resume`` → ``job``. A tool-level failure lands in ``error``. */ export interface CronManageResult { success?: boolean | null error?: string | null count?: number | null jobs?: CronJobRow[] | null scoped?: string | null gateway_running?: boolean | null warning?: string | null job_id?: string | null name?: string | null skill?: string | null skills?: string[] | null schedule?: string | null repeat?: number | string | null deliver?: string | null next_run_at?: string | null job?: CronJobRow | null message?: string | null guidance?: unknown | null removed_job?: CronRemovedJob | null [key: string]: unknown } /** ``tools/cronjob_job_args.py::_format_job``. */ export interface CronJobRow { job_id: string name?: string skill?: string | null skills?: string[] prompt_preview?: string model?: string | null provider?: string | null base_url?: string | null schedule?: string repeat?: number | string | null deliver?: string | null next_run_at?: string | null last_run_at?: string | null last_status?: string | null last_delivery_error?: string | null last_delivery_unverified?: boolean | null last_fire_error?: string | null last_error?: string | null enabled?: boolean state?: string | null paused_at?: string | null paused_reason?: string | null workdir?: string | null script?: string | null reasoning_effort?: string | null monitor_script?: string | null monitor_url?: string | null monitor_state?: unknown | null no_agent?: boolean | null enabled_toolsets?: string[] | null continuity?: boolean | null context_from?: string[] | null attach_to_session?: boolean | null [key: string]: unknown } export interface CronRemovedJob { id: string name?: string schedule?: string | null } export interface BrowserManageParams { action?: BrowserAction url?: string | null session_id?: string | null profile?: string | null } export type BrowserAction = 'status' | 'connect' | 'disconnect' export interface BrowserManageResult { connected: boolean url?: string | null messages?: string[] | null } /** Handlers that look a live session up with ``_sessions.get(params.get("session_id"))``: an absent / unknown id falls back to the launch profile's config, so it is never required. */ export interface _SessionScoped { session_id?: string | null } export interface ToolsetsListResult { toolsets: ToolsetRow[] } /** One row of ``methods_tools._toolset_rows``; ``tools`` only when the caller asked for them (``tools.list``). */ export interface ToolsetRow { name: string description: string tool_count: number enabled: boolean tools?: string[] | null } export interface ToolsShowResult { sections: ToolShowSection[] total: number } export interface ToolShowSection { name: string tools: ToolShowRow[] } export interface ToolShowRow { name: string description: string } /** ``names`` are toolset keys or ``server:tool`` MCP targets; with ``session_id`` the live session's profile is authoritative and its agent is rebuilt. */ export interface ToolsConfigureParams { action: ToolsAction names: string[] session_id?: string | null profile?: string | null } export type ToolsAction = 'enable' | 'disable' export interface ToolsConfigureResult { changed: string[] enabled_toolsets: string[] info?: SessionLiveInfo | null missing_servers: string[] reset: boolean unknown: string[] } export type ReloadEnvParams = Record export interface ReloadEnvResult { updated: number } /** Without ``confirm`` the handler may answer ``confirm_required`` (per ``approvals.mcp_reload_confirm``); ``always`` persists the opt-out; ``rev`` is the config revision the caller wants loaded (coalescing). */ export interface ReloadMcpParams { session_id?: string | null confirm?: boolean always?: boolean rev?: string | null } export interface ReloadMcpResult { status: ReloadMcpStatus message?: string | null loaded_rev?: string | null coalesced?: boolean | null turn_isolation?: boolean | null host_ack?: unknown | null } export type ReloadMcpStatus = 'confirm_required' | 'reloaded' /** ``query`` is the search text / hub identifier / browse page (digits); ``page`` / ``page_size`` apply to ``browse``. */ export interface SkillsManageParams { profile?: string | null action?: SkillsAction query?: string | null page?: number | null page_size?: number | null } export type SkillsAction = 'list' | 'search' | 'install' | 'browse' | 'inspect' /** Shape follows the action: ``list`` → ``skills`` (category → names); ``search`` → ``results``; ``install`` → ``installed`` + ``name``; ``browse`` → ``items`` + paging; ``inspect`` → ``info``. */ export interface SkillsManageResult { skills?: Record | null results?: SkillHubHit[] | null installed?: boolean | null name?: string | null items?: SkillBrowseItem[] | null page?: number | null total_pages?: number | null total?: number | null info?: SkillInspectInfo | null } export interface SkillHubHit { name: string description: string } /** ``hermes_cli.skills_hub.browse_skills`` row. */ export interface SkillBrowseItem { name?: string description?: string source?: string trust?: string | null identifier?: string | null [key: string]: unknown } /** ``hermes_cli.skills_hub.inspect_skill``; ``{}`` when the identifier resolves nowhere. */ export interface SkillInspectInfo { name?: string | null description?: string | null source?: string | null identifier?: string | null tags?: string[] | null skill_md_preview?: string | null [key: string]: unknown } export type SkillsReloadParams = Record export interface SkillsReloadResult { output: string result: SkillsReloadDiff } /** ``agent.skill_commands.reload_skills``. */ export interface SkillsReloadDiff { added?: SkillCommandRef[] removed?: SkillCommandRef[] unchanged?: string[] total?: number commands?: number [key: string]: unknown } export interface SkillCommandRef { name: string description?: string } export interface LearningFramesParams { cols?: number | null rows?: number | null frames?: number | null } export interface LearningFramesResult { frames: LearningFrame[] legend: LearningLegendItem[] categories: LearningLegendItem[] buckets: LearningBucketRow[] summary: string[] axis: LearningAxis count: number cols: number rows: number } /** ``agent.learning_graph_render.render_graph`` projection; ``grid`` rows are lists of ``[text, styleKey, alpha?, hexOverride?]`` runs. */ export interface LearningFrame { reveal: number date: string visible: number grid: unknown[][] labels?: Record[] } export interface LearningLegendItem { glyph: string label: string style?: string | null color?: string | null } export interface LearningBucketRow { index: number label: string date: string skills: number memories: number total: number category?: string | null color?: string | null nodes: LearningNodeRow[] } export interface LearningNodeRow { id: string glyph: string label: string fullLabel: string meta: string body: string style: string } export interface LearningAxis { start: string end: string } export interface LearningNodeParams { id?: string | null } export interface LearningDetailResult { ok: boolean message?: string | null kind?: string | null id?: string | null label?: string | null content?: string | null } /** ``agent.learning_mutations`` — ``ok: false`` carries the reason in ``message``. */ export interface LearningMutationResult { ok: boolean message?: string | null } export interface LearningEditParams { id?: string | null content?: string | null } export interface McpCatalogResult { servers: McpCatalogEntry[] } export interface McpCatalogEntry { name: string description: string installed: boolean enabled: boolean requires: string[] transport: string } export interface McpServersListResult { servers: McpServerSummary[] } /** ``tui_gateway/mcp_rpc_helpers.summarize_server`` — a server's config without secret values. */ export interface McpServerSummary { name: string transport: string url?: string | null command?: string | null args: string[] env: string[] auth?: string | null oauth_tokens_present?: boolean | null enabled: boolean tools?: unknown | null } export interface McpServersStatusResult { servers: McpServerRuntimeRow[] checked_at: number } /** Safe projection of ``tools.mcp_tool_discovery.get_mcp_status`` rows. */ export interface McpServerRuntimeRow { name: string transport: string tools: number connected: boolean disabled: boolean status: McpRuntimeStatus } export type McpRuntimeStatus = 'connected' | 'disabled' | 'connecting' | 'failed' | 'configured' /** ``preset`` (catalog id) and/or ``config`` (url/command/args/env/headers/auth/tools); a ``bearer_token`` is written to the profile's .env, only the header template persists. */ export interface McpServersAddParams { profile?: string | null name: string preset?: string | null config?: Record | null bearer_token?: string | null } export interface McpServersAddResult { ok: boolean name: string server: McpServerSummary } export interface McpServersSetApiKeyParams { profile?: string | null name: string value: string env_var?: string | null } export interface McpServersSetApiKeyResult { ok: boolean name: string env_var: string server: McpServerSummary } export interface McpServerNameParams { profile?: string | null name: string } /** ``ok: false`` carries ``error``; ``prompts`` / ``resources`` are only counted on success. */ export interface McpServersTestResult { ok: boolean tools: McpProbeTool[] error?: string | null prompts?: number | null resources?: number | null oauth_needed: boolean oauth_tokens_present?: boolean | null } export interface McpProbeTool { name: string description: string } export interface McpServersRemoveResult { ok: boolean removed: boolean } /** With ``client_redirect_uri`` the CLIENT hosts the loopback and relays the code via ``mcp.servers.oauth.callback``. */ export interface McpOauthStartParams { profile?: string | null name: string client_redirect_uri?: string | null } export interface McpOauthStartResult { ok: boolean session_id: string auth_url: string flow: string } /** ``session_id`` is the OAuth flow id returned by ``oauth.start`` (not a gateway session). */ export interface McpOauthFlowParams { profile?: string | null name: string session_id: string } export interface McpOauthPollResult { ok: boolean status: McpOauthPollStatus session_id?: string | null error_message?: string | null auth_url?: string | null tools?: McpProbeTool[] | null } export type McpOauthPollStatus = 'pending' | 'approved' | 'error' export interface McpOauthCancelResult { ok: boolean status?: string | null error_message?: string | null } export interface McpOauthCallbackParams { profile?: string | null name: string session_id: string code?: string | null state?: string | null error?: string | null iss?: string | null } export interface McpOauthCallbackResult { ok: boolean session_id?: string | null error_message?: string | null } export type PluginsListParams = Record export interface PluginsListResult { plugins: LegacyPluginRow[] } export interface LegacyPluginRow { name: string version: string enabled: boolean } /** ``toggle``: ``key``/``name`` + ``enable``; ``install``: ``identifier``/``repo`` or ``catalog_name`` (+ ``force``, ``enable``, ``ref``); ``update``: ``name``. */ export interface PluginsManageParams { profile?: string | null action?: PluginsAction key?: string | null name?: string | null enable?: boolean | null identifier?: string | null repo?: string | null catalog_name?: string | null force?: boolean | null ref?: string | null } export type PluginsAction = 'list' | 'toggle' | 'install' | 'update' /** ``list`` → ``plugins`` + counts; ``toggle`` → ``ok``/``unchanged``/``name``/``plugin``; ``install`` → ``hermes_cli.plugins_cmd.dashboard_install_plugin``'s ok payload; ``update`` → ``ok``/``unchanged``/``sha``. */ export interface PluginsManageResult { plugins?: AgentPluginRow[] | null user_count?: number | null bundled_count?: number | null ok?: boolean | null unchanged?: boolean | null name?: string | null plugin?: AgentPluginRow | null plugin_name?: string | null warnings?: string[] | null missing_env?: string[] | null after_install_path?: string | null enabled?: boolean | null sha?: string | null } /** ``methods_tools._plugin_rows`` + ``plugins_cmd_catalog.catalog_row_fields`` provenance. */ export interface AgentPluginRow { name: string key: string version: string description: string source: string status: string portable: boolean install_dir: string has_desktop_half: boolean catalog_name?: string | null catalog_tier?: string | null installed_sha?: string | null catalog_sha?: string | null update_available?: boolean | null pinned_sha?: string | null } /** Single question: ``question`` / ``choices`` (/ ``multi_select``); batch: ``questions``. ``answers`` rides only on a reconnect replay (locks the server already accepted). */ export interface ClarifyRequestParams { session_id: string question?: string | null choices?: string[] | null multi_select?: boolean | null questions?: ClarifyQuestion[] | null answers?: Record | null } export interface ClarifyQuestion { qid: string question: string choices?: string[] | null multi_select?: boolean } /** Single: ``{answer}`` ('' = skip). Batch: ``{answers}`` for the whole set (early locks go through the ``clarify.lock`` RPC); a response with neither is cancel-all. */ export interface ClarifyResult { answer?: string | null answers?: Record | null } /** ``tui_gateway/server.py::_approval_request_payload`` — the command is redacted server-side. */ export interface ApprovalRequestParams { session_id: string request_id: string command?: string description?: string choices?: ApprovalChoice[] allow_permanent?: boolean | null allow_session?: boolean | null smart_denied?: boolean | null tool_name?: string | null gateway_session_id?: string | null [key: string]: unknown } export interface ApprovalResult { choice: ApprovalChoice all?: boolean | null } /** Original command, redacted server-side before any password-injection rewrite. */ export interface SudoRequestParams { session_id: string command?: string } /** The answer to any one-string prompt (sudo, secret, vault prompts, desktop bridges): ``''`` means skipped / declined. */ export interface ValueResult { value: string } export interface SecretRequestParams { session_id: string env_var: string prompt: string metadata?: Record | null } export interface VaultUnlockRequestParams { session_id: string backend: string display_name: string } export interface VaultSaveLoginRequestParams { session_id: string origin: string site: string } export interface VaultCodeRequestParams { session_id: string site?: string | null hint?: string | null } export interface ReadRangeRequestParams { session_id: string start?: number | null count?: number | null } export interface EmptyRequestParams { session_id: string } /** ``tools/drive_preview_tool.py`` and ``tools/annotate_preview_tool.py`` field sets. */ export interface PreviewActRequestParams { session_id: string action: string ref?: string | null selector?: string | null text?: string | null key?: string | null submit?: boolean | null full?: boolean | null to?: string | null amount?: number | null max?: number | null } /** ``tools/tour_tool.py`` field set. */ export interface TourRequestParams { session_id: string action: string surface?: string | null selector?: string | null title?: string | null text?: string | null side?: string | null steps?: TourStep[] | null step_index?: number | null } export interface TourStep { selector?: string | null title?: string | null text?: string | null side?: string | null [key: string]: unknown } /** ``methods_connectors._connection_update``: one target transition (``target``/``from``/``to``/ ``actor``) or the settlement (none of those), with the full snapshot. */ export interface ConnectionUpdatePayload { op_id: string deadline_at: number settled: boolean settled_at?: number | null settled_by?: ConnectionSettleReason | null targets: ConnectionOperationTarget[] target?: string | null from?: ConnectionTargetState | null to?: ConnectionTargetState | null actor?: ConnectionActor | null detail?: string | null } /** ``tools/connectors/contract.py::Actor``. */ export type ConnectionActor = 'user' | 'renderer_flow' | 'backend_watcher' | 'clock' /** ``tui_gateway/entry.py`` (stdio) / ``tui_gateway/ws.py`` (WebSocket) first frame. */ export interface GatewayReadyPayload { skin: SkinPayload change_events: boolean replay_epoch: string heartbeat?: boolean | null } /** ``tui_gateway/change_watcher.py::resolve_skin`` — the resolved active skin (``HermesSkin``). ``{}`` when the skin engine failed to load. Colour maps are token → colour string. */ export interface SkinPayload { name?: string description?: string colors?: Record light_colors?: Record dark_colors?: Record branding?: Record banner_logo?: string banner_hero?: string tool_prefix?: string help_header?: string [key: string]: unknown } /** ``hermes_cli/free_tier_bootstrap.py::SetupRecord.as_payload``. */ export interface SetupReadyPayload { provider_configured: boolean inference_provider: string free_tier: boolean has_identity: boolean other_providers: boolean error?: string finished_at: number [key: string]: unknown } /** Every ``_emit("error", …)`` site sets exactly ``message``. */ export interface ErrorPayload { message: string } /** ``tui_gateway/model_switch.py`` capability-refresh notice. */ export interface NoticePayload { message: string } /** ``prompt_turn._invoke_agent._stream`` (message.delta: ``text`` + optional ``rendered``), ``agent_callbacks._agent_cbs`` (reasoning.delta / thinking.delta), ``tool_progress._progress_reasoning`` (reasoning.available). ``verbose`` rides only when the session's verbose reasoning mode is on. */ export interface StreamDeltaPayload { text: string rendered?: string | null verbose?: boolean | null } /** ``prompt_turn._interim_assistant_cb`` / ``agent_callbacks`` interim_assistant_callback. */ export interface MessageInterimPayload { text: string already_streamed: boolean } /** ``prompt_turn._complete_turn_payload`` / ``session_auto_continue._emit_terminal_turn_error`` / ``agent_callbacks._mirror_subagent_to_child`` (child watch mirror: ``text`` only) / ``compute_host_bridge`` (``text`` + ``status``). */ export interface MessageCompletePayload { text?: string | unknown usage?: Usage | null status?: TurnStatus | null reasoning?: string | null warning?: string | null response_previewed?: boolean | null billing?: BillingBlock | null failure_reason?: string | null rendered?: string | null error?: string | null recoverable?: boolean | null error_surface?: ErrorSurface | null partial?: boolean | null } /** ``prompt_turn._result_status``. */ export type TurnStatus = 'complete' | 'error' | 'interrupted' /** ``agent/billing_links.py::BillingBlock.to_dict`` (+ ``unverified`` from conversation_loop). */ export interface BillingBlock { provider: string provider_label: string model: string billing_url: string | null is_nous: boolean message: string unverified?: boolean | null } /** ``agent/error_surface.py::_surface`` — advisory {layer, code, retryable} (+ identity, + auth hint). */ export interface ErrorSurface { layer: string code: string retryable: boolean provider?: string | null model?: string | null [key: string]: unknown } /** ``server._status_update`` and the direct emitters (goal / loop / heartbeat / process). */ export interface StatusUpdatePayload { kind: string text: string } /** ``server._start_usage_ticker``. */ export interface SessionUsagePayload { usage: Usage } /** ``prompt_turn._invoke_agent`` ``_on_session_title`` hook. */ export interface SessionTitlePayload { session_id: string title: string } /** ``agent_callbacks`` reaction_callback. */ export interface ReactionPayload { kind: string } /** ``server`` background_review_callback. */ export interface ReviewSummaryPayload { text: string } /** ``tool_progress._on_tool_start`` (+ ``agent_callbacks._mirror_subagent_to_child`` rows with ``preview`` and empty ``args``). ``todos``/``revision`` are NOT set by the emitter; kept optional because tool.start rows may pass through connector redaction unchanged. */ export interface ToolStartPayload { tool_id: string name: string context?: string | null args?: Record | null args_text?: string | null preview?: string | null } /** ``tool_progress._on_tool_complete``; ``todos``/``revision`` merged in for the todo tools. */ export interface ToolCompletePayload { tool_id: string name: string args?: Record | null duration_s?: number | null result?: unknown summary?: string | null result_text?: string | null inline_diff?: string | null todos?: unknown[] | null revision?: number | null } /** ``agent_callbacks`` tool_gen_callback. */ export interface ToolGeneratingPayload { name: string } /** ``tool_progress._progress_output_risk``. */ export interface ToolOutputRiskPayload { tool_id: string name: string risk: string findings: string[] redacted: boolean } /** ``tool_progress._normalize_todo_state`` — full task snapshot. */ export interface TodoUpdatedPayload { todos: unknown[] revision: number } /** ``agent/credits_tracker.py::AgentNotice`` via notice_callback, and ``server._await_agent_ready``'s slow-build notice. ``level``: info | warn | error | success; ``kind``: sticky | ttl | agent. */ export interface NotificationShowPayload { text: string level: string kind: string ttl_ms?: number | null key?: string | null id?: string | null } export interface NotificationClearPayload { key: string } /** ``tools/tip_tool.py``. */ export interface TipShowPayload { selector: string text: string title?: string | null side?: string | null } /** ``server._hydrate_resume_history``. */ export interface SessionResumeProgressPayload { phase: string status: ResumePhaseStatus message_count?: number | null message?: string | null } export type ResumePhaseStatus = 'loading' | 'complete' | 'failed' /** ``session_lifecycle._announce_session_reclaimed`` (broadcast). */ export interface SessionReclaimedPayload { session_id: string stored_session_id: string reason: string } export interface SessionControlUpdatePayload { control: SessionControlSnapshot } /** ``methods_session`` billing.step_up on_verification. */ export interface BillingStepUpVerificationPayload { verification_url: string user_code: string } /** ``methods_prompt._spawn_side_agent``: ``{task_id, **extra, text}``; btw adds ``question``. */ export interface SideAgentCompletePayload { task_id: string text: string question?: string | null } /** ``methods_prompt`` restart body + ``agent_callbacks._preview_restart_callbacks``. */ export interface PreviewRestartProgressPayload { task_id: string text: string level?: string | null } /** ``tool_progress._progress_subagent`` — every ``subagent.*`` frame; identity fields are optional because older emitters omit them and the TUI spawn tree falls back to flat rendering. */ export interface SubagentEventPayload { goal: string task_count: number task_index: number subagent_id?: string | null parent_id?: string | null child_session_id?: string | null delegation_id?: string | null depth?: number | null model?: string | null tool_count?: number | null toolsets?: string[] | null input_tokens?: number | null output_tokens?: number | null reasoning_tokens?: number | null api_calls?: number | null files_read?: string[] | null files_written?: string[] | null output_tail?: SubagentOutputTailEntry[] | null tool_name?: string | null text?: string | null status?: SubagentStatus | null summary?: string | null duration_seconds?: number | null tool_preview?: string | null } /** ``tools/delegate_tool_results.py::_extract_output_tail`` row. */ export interface SubagentOutputTailEntry { tool: string preview: string is_error: boolean } /** ``tool_progress._progress_moa_reference``. */ export interface MoaReferencePayload { label: string text: string index?: number | null count?: number | null } export interface MoaAggregatingPayload { aggregator: string } export interface MoaProgressPayload { label: string refs_done: number refs_total: number } export interface MoaPhasePayload { phase: string refs_done?: number | null refs_total?: number | null aggregator?: string | null } /** ``tools/open_preview_tool.py``. */ export interface PreviewOpenPayload { url: string label?: string } /** ``tools/preview_tool.py`` / ``tools/close_preview_tool.py``; ``url`` '' closes every tab. */ export interface PreviewClosePayload { url?: string } /** ``tools/apply_layout_tool.py``. */ export interface LayoutApplyPayload { preset: string [key: string]: unknown } /** ``tools/focus_pane_tool.py``. */ export interface PaneRevealPayload { pane: string [key: string]: unknown } /** ``tools/react_to_message_tool.py``. */ export interface MessageReactionPayload { row_id: number reactions: MessageReaction[] role: string } /** ``session_notifications`` process_registry.on_output. */ export interface TerminalOutputPayload { process_id: string chunk: string } export interface TerminalClosePayload { process_id: string } /** ``methods_browser`` announce(); ``level``: info | warn | error. */ export interface BrowserProgressPayload { message: string level: string } /** ``gateway/browser_control_broker.py`` FRAME_COMMAND params. */ export interface BrowserControllerCommandPayload { command_id: string action: string arguments: Record controller_id?: string | null browser_profile_id?: string | null tool_call_id?: string | null } /** ``gateway/browser_control_broker.py::_cancel_frame``. */ export interface BrowserControllerCancelPayload { command_id: string tool_call_id?: string | null } /** ``methods_voice._vr_on_status``; states come from the recorder (idle / listening / transcribing …). */ export interface VoiceStatusPayload { state: string } /** ``methods_voice._vr_transcript`` / ``_deliver_fd_transcript`` / typed stop phrase in methods_prompt. */ export interface VoiceTranscriptPayload { text?: string | null stop_phrase?: boolean | null typed?: boolean | null no_speech_limit?: boolean | null } /** ``methods_voice`` wake detector ``_on_detect``. */ export interface WakeDetectedPayload { phrase: string profile?: string | null start_new_session: boolean } /** ``change_watcher._pet_changed_payload`` — ``pet.info.meta``-shaped; ``{enabled: false}`` when off. */ export interface PetChangedPayload { enabled: boolean slug?: string | null displayName?: string | null scale?: number | null spritesheetRevision?: string | null [key: string]: unknown } /** ``methods_session`` pet.generate: token-only init frame, then one per draft. */ export interface PetGenerateProgressPayload { token: string count: number index?: number | null dataUri?: string | null [key: string]: unknown } /** ``methods_session`` pet.hatch ``_on_progress``: ``{event, detail}`` or the parsed row form. */ export interface PetHatchProgressPayload { event: string detail?: string | null state?: string | null done?: string | null total?: string | null [key: string]: unknown } /** ``change_watcher._CHANGE_WATCHES`` payload fn — ``{}`` for every watch except pet.changed. */ export type ChangeSignalPayload = Record export interface RequestCancelPayload { id: string method: string reason: string } // ── Client→server methods ── export interface RpcMethods { /** Registry-wide background process summary for ``/agents``. */ 'agents.list': { params: AgentsListParams; result: AgentsListResult } /** Replay the approvals still waiting on this session (reconnect / polling). */ 'approval.pending': { params: ApprovalPendingParams; result: ApprovalPendingResult } /** Tell the backend the card is on screen, so its timeout clock starts. */ 'approval.received': { params: ApprovalReceivedParams; result: ApprovalReceivedResult } /** Deliver the user's decision on a dangerous command (falls back to durable identity on a stale sid). */ 'approval.respond': { params: ApprovalRespondParams; result: ApprovalRespondResult } /** Enable/disable auto top-up with its threshold and reload amount (billing:manage). */ 'billing.auto_reload': { params: BillingAutoReloadParams; result: BillingMutationResult } /** Start a one-off top-up charge (billing:manage, idempotent). */ 'billing.charge': { params: BillingChargeParams; result: BillingChargeResult } /** Poll one charge by id. */ 'billing.charge_status': { params: BillingChargeStatusParams; result: BillingChargeStatusResult } /** Read-only billing view (no scope); the Nous free tier is answered locally without a portal call. */ 'billing.state': { params: ProfileParams; result: BillingStateResult } /** Run the billing:manage device flow; the URL/code arrive via billing.step_up.verification. */ 'billing.step_up': { params: BillingStepUpParams; result: BillingStepUpResult } /** Deliver a relayed DM into a Bot Chat on this gateway and return the one-turn reply (blocking). */ 'bot_relay.deliver': { params: BotRelayDeliverParams; result: BotRelayDeliverResult } /** Atomically claim every pending cross-connection envelope queued on this gateway. */ 'bot_relay.outbox.drain': { params: BotRelayOutboxDrainParams; result: BotRelayOutboxDrainResult } /** Write a relayed reply and/or typed error for an envelope so the sender-side waiter resolves. */ 'bot_relay.reply': { params: BotRelayReplyParams; result: OkResult } /** Replace this gateway's view of agents on other connections; answers the accepted row count. */ 'bot_relay.roster.sync': { params: BotRelayRosterSyncParams; result: BotRelayRosterSyncResult } /** Hard-detach only the controller owned by this authenticated transport. */ 'browser.controller.detach': { params: BrowserControllerParams; result: BrowserControllerDetachResult } /** Acknowledge a heartbeat only for this transport's own attached controller. */ 'browser.controller.heartbeat': { params: BrowserControllerParams; result: OkResult } /** Attach this connection as the browser controller for one session; fails closed (4403). */ 'browser.controller.register': { params: BrowserControllerRegisterParams; result: BrowserControllerRegisterResult } /** Deliver one command result to the broker; accepted is false for unknown or settled command ids. */ 'browser.controller.result': { params: BrowserControllerResultParams; result: BrowserControllerResultResult } /** Inspect, attach to, or drop the CDP browser the tools use; ``messages`` narrate a connect. */ 'browser.manage': { params: BrowserManageParams; result: BrowserManageResult } /** Lock one answer of a batch clarify request (editable until every question is locked). */ 'clarify.lock': { params: ClarifyLockParams; result: ClarifyLockResult } /** Run ``hermes `` non-interactively and capture its output; ``blocked`` explains a refusal. */ 'cli.exec': { params: CliExecParams; result: CliExecResult } /** Save the host clipboard image into the session and queue it for the next turn. */ 'clipboard.paste': { params: ClipboardPasteParams; result: AttachedImageResult } /** Run a quick/plugin/bundle/skill/built-in slash command and answer a structured directive. */ 'command.dispatch': { params: CommandDispatchParams; result: CommandDispatchResult } /** Canonical registry command for a name or alias. */ 'command.resolve': { params: CommandResolveParams; result: CommandResolveResult } /** Categorized slash metadata (registry, quick, plugin, skill) for completion menus. */ 'commands.catalog': { params: CommandsCatalogParams; result: CommandsCatalogResult } /** Path / @-reference completions for the composer (files, folders, profiles, plugin providers). */ 'complete.path': { params: CompletePathParams; result: CompletionItemsResult } /** Ranked slash-command / skill completions for a ``/`` token. */ 'complete.slash': { params: CompleteSlashParams; result: CompleteSlashResult } /** Read one normalised config value (or the whole effective config) the way the UIs render it. */ 'config.get': { params: ConfigGetParams; result: ConfigGetResult } /** Change one config key (persisted or session-scoped) and read back the normalised value. */ 'config.set': { params: ConfigSetParams; result: ConfigSetResult } /** Masked, display-ready config summary (model / agent / environment rows). */ 'config.show': { params: ConfigShowParams; result: ConfigShowResult } /** Per-target outcomes from the card, and an optional Continue. */ 'connection.respond': { params: ConnectionRespondParams; result: ConnectionRespondResult } /** Start (or re-initiate) authorization for named connectors on the session's connection operation. */ 'connectors.connect': { params: ConnectorsConnectParams; result: ConnectorsConnectResult } /** Connector catalog + connection state for one owned session (``available=False`` when the toolset is off). */ 'connectors.list': { params: ConnectorsListParams; result: ConnectorsListResult } /** The current snapshot of one open operation on an owned session. */ 'connectors.operation.status': { params: ConnectionOperationParams; result: ConnectionOperationStatus } /** List/add/remove/pause/resume cron jobs in the (optionally profile-scoped) cron store. */ 'cron.manage': { params: CronManageParams; result: CronManageResult } /** Block/unblock NEW spawns globally (active children keep running); returns the new state. */ 'delegation.pause': { params: DelegationPauseParams; result: DelegationPauseResult } /** Running subagent tree plus the spawn pause flag and limits. */ 'delegation.status': { params: ProfileParams; result: DelegationStatusResult } /** Upload a force-redacted debug bundle to Nous-internal diagnostics storage. */ 'diagnostics.share_nous': { params: DiagnosticsShareNousParams; result: DiagnosticsShareNousResult } /** Stage a non-image file into the session workspace and hand back its @file: ref. */ 'file.attach': { params: FileAttachParams; result: FileAttachResult } /** Mark the one-time availability notice as shown on the free-tier identity. */ 'free_tier.ack_notice': { params: ProfileParams; result: FreeTierAckNoticeResult } /** Explicit retry of the free-tier identity mint when the boot bootstrap could not create it. */ 'free_tier.provision': { params: ProfileParams; result: FreeTierProvisionResult } /** Pure read of the focused profile's free-tier identity state (no network, no side effects). */ 'free_tier.status': { params: ProfileParams; result: FreeTierStatusResult } /** What THIS build enforces (a client withholds a feature unless advertised). */ 'gateway.capabilities': { params: PingParams; result: GatewayCapabilitiesResult } /** Resolve one exact pending approval raised by a local or peer room member. */ 'groups.approve': { params: GroupsApproveParams; result: GroupsApproveResult } /** Describe the hosted-room protocol implemented by this gateway. */ 'groups.capabilities': { params: GroupsCapabilitiesParams; result: GroupsCapabilitiesResult } /** Create a hosted room idempotently; authority is this gateway's stable install identity. */ 'groups.create': { params: GroupsCreateParams; result: GroupsCreateResult } /** Fence this gateway's stale room authority against a proven newer epoch. */ 'groups.demote': { params: GroupsDemoteParams; result: GroupsDemoteResult } /** Permanently tombstone a hosted room id after stopping its work and revoking peer routes. */ 'groups.disband': { params: GroupsDisbandParams; result: GroupsDisbandResult } /** List rooms hosted by this gateway, most recently changed first. */ 'groups.list': { params: GroupsListParams; result: GroupsListResult } /** A monotonic room-log delta after since_seq, bounded by count and page bytes. */ 'groups.log': { params: GroupsLogParams; result: GroupsLogResult } /** Mint one target-issued room/profile grant for a prospective room home. */ 'groups.peer.invite': { params: GroupsPeerInviteParams; result: GroupsPeerInviteResult } /** Register and probe one scoped peer route on the room home. */ 'groups.peer.register': { params: GroupsPeerRegisterParams; result: GroupsPeerRegisterResult } /** Revoke one target-issued grant using its exact profile scope. */ 'groups.peer.revoke': { params: GroupsPeerRevokeParams; result: GroupsPeerRevokeResult } /** Continue a replicated room on this gateway at epoch + 1; requires confirm=true. */ 'groups.promote': { params: GroupsPromoteParams; result: GroupsPromoteResult } /** Rename one hosted room atomically with its replay event. */ 'groups.rename': { params: GroupsRenameParams; result: GroupsRenameResult } /** The local replica's coverage and authority lineage for one room. */ 'groups.replica_state': { params: GroupsReplicaStateParams; result: GroupsReplicaStateResult } /** Persist one authority-stamped replay page into the local replica store; idempotent. */ 'groups.replicate': { params: GroupsReplicateParams; result: GroupsReplicateResult } /** Retry one indeterminate room task after explicit user confirmation. */ 'groups.retry': { params: GroupsRetryParams; result: GroupsRetryResult } /** Append one inert message.user event idempotently; the actor is server-owned. */ 'groups.send': { params: GroupsSendParams; result: GroupsSendResult } /** One hosted room's replay cursor and fenced authority state, plus live driver status. */ 'groups.state': { params: GroupsStateParams; result: GroupsStateResult } /** Durably cancel queued or running work for one hosted room. */ 'groups.stop': { params: GroupsStopParams; result: GroupsStopResult } /** Fail a not-yet-claimed handoff (client poll timeout); CAS against the watcher. */ 'handoff.fail': { params: HandoffFailParams; result: HandoffFailResult } /** Queue a handoff to a messaging platform's home channel; the gateway watcher claims it. */ 'handoff.request': { params: HandoffRequestParams; result: HandoffRequestResult } /** Poll the handoff row for this session. */ 'handoff.state': { params: SessionParams; result: HandoffStateResult } /** Queue a gateway-visible image file for the next turn. */ 'image.attach': { params: ImageAttachParams; result: AttachedImageResult } /** Queue an image uploaded as base64 (remote client); reply mirrors image.attach. */ 'image.attach_bytes': { params: ImageAttachBytesParams; result: AttachedImageResult } /** Drop a queued image before the turn is sent. */ 'image.detach': { params: ImageDetachParams; result: ImageDetachResult } /** Generate an image through the tool's provider dispatcher and hand the renderer a data URL. */ 'image.generate': { params: ImageGenerateParams; result: ImageGenerateResult } /** Recognise a terminal file drop pasted into the composer and turn it into an attachment. */ 'input.detect_drop': { params: InputDetectDropParams; result: InputDetectDropResult } /** Session/message counts over the last ``days`` for the (optionally scoped) profile store. */ 'insights.get': { params: InsightsGetParams; result: InsightsGetResult } /** Archive a skill (restorable via curator) or remove a memory chunk. */ 'learning.delete': { params: LearningNodeParams; result: LearningMutationResult } /** Node content (SKILL.md or memory chunk) for an edit prefill. */ 'learning.detail': { params: LearningNodeParams; result: LearningDetailResult } /** Rewrite a node's content (SKILL.md or memory chunk). */ 'learning.edit': { params: LearningEditParams; result: LearningMutationResult } /** Pre-render the /journey timeline (frames + legend/summary) so the TUI walks it locally. */ 'learning.frames': { params: LearningFramesParams; result: LearningFramesResult } /** Stateless one-shot LLM completion (titles, ideas) on the session's or the task backend. */ 'llm.oneshot': { params: LlmOneshotParams; result: LlmOneshotResult } /** Curated MCP presets with per-profile installed/enabled state and the env keys each needs. */ 'mcp.catalog': { params: ProfileParams; result: McpCatalogResult } /** Add a server to the profile's config from a catalog preset and/or an explicit config. */ 'mcp.servers.add': { params: McpServersAddParams; result: McpServersAddResult } /** Configured MCP servers for the (scoped) profile, secrets redacted to env-key names. */ 'mcp.servers.list': { params: ProfileParams; result: McpServersListResult } /** Relay a client-captured redirect into a client_redirect_uri flow. */ 'mcp.servers.oauth.callback': { params: McpOauthCallbackParams; result: McpOauthCallbackResult } /** Cancel a flow owned by the resolved profile, waking its callback worker. */ 'mcp.servers.oauth.cancel': { params: McpOauthFlowParams; result: McpOauthCancelResult } /** Poll a flow; approved persists tokens for the profile and returns the probed tools. */ 'mcp.servers.oauth.poll': { params: McpOauthFlowParams; result: McpOauthPollResult } /** Begin a PKCE OAuth flow; the client opens auth_url and polls mcp.servers.oauth.poll. */ 'mcp.servers.oauth.start': { params: McpOauthStartParams; result: McpOauthStartResult } /** Drop a server from the profile's config.yaml. */ 'mcp.servers.remove': { params: McpServerNameParams; result: McpServersRemoveResult } /** Store a credential in the profile's .env and reference it from the server config (header or env). */ 'mcp.servers.set_api_key': { params: McpServersSetApiKeyParams; result: McpServersSetApiKeyResult } /** Cached runtime state per configured server; never connects, probes, or starts auth. */ 'mcp.servers.status': { params: ProfileParams; result: McpServersStatusResult } /** Connect, list tools, disconnect — an OAuth server with no token on disk is reported as not ok. */ 'mcp.servers.test': { params: McpServerNameParams; result: McpServersTestResult } /** Set/clear one author's emoji reaction on a message; returns the row's full reaction list. */ 'message.react': { params: MessageReactParams; result: MessageReactResult } /** Remove every credential (env keys and OAuth state) for a provider. */ 'model.disconnect': { params: ModelDisconnectParams; result: ModelDisconnectResult } /** Provider/model inventory for the picker, layered over the session's live provider when given. */ 'model.options': { params: ModelOptionsParams; result: ModelOptionsResult } /** Save an API key for a provider and return its refreshed inventory row. */ 'model.save_key': { params: ModelSaveKeyParams; result: ModelSaveKeyResult } /** Spill a large paste to a file and hand back the inline placeholder. */ 'paste.collapse': { params: PasteCollapseParams; result: PasteCollapseResult } /** Render a PDF's pages to PNG and queue them as images for the next turn. */ 'pdf.attach': { params: PdfAttachParams; result: PdfAttachResult } /** Stop an in-flight pet generate/hatch by token (idempotent). */ 'pet.cancel': { params: PetCancelParams; result: PetCancelResult } /** Half-block cell frames (or a kitty placement) for one pet state. */ 'pet.cells': { params: PetCellsParams; result: PetCellsResult } /** Turn the pet display off from the desktop picker. */ 'pet.disable': { params: ProfileParams; result: OkResult } /** Export an installed pet as a re-importable .zip. */ 'pet.export': { params: PetSlugParams; result: PetExportResult } /** Petdex gallery + local install state (installed-only offline); localOnly skips the remote manifest. */ 'pet.gallery': { params: PetGalleryParams; result: PetGalleryResult } /** Candidate base looks for a new pet (draft step); drafts also stream via pet.generate.progress. */ 'pet.generate': { params: PetGenerateParams; result: PetGenerateResult } /** Whether pet generation is possible (a reference-capable image backend) and which providers. */ 'pet.generate.status': { params: ProfileParams; result: PetGenerateStatusResult } /** Turn a base draft into a full spritesheet pet; progress streams via pet.hatch.progress. */ 'pet.hatch': { params: PetHatchParams; result: PetHatchResult } /** Active pet for sprite renderers: spritesheet (base64) + frame geometry + state-row taxonomy. */ 'pet.info': { params: PetInfoParams; result: PetInfoResult } /** Cheap active-pet metadata used to avoid full payload refreshes. */ 'pet.info.meta': { params: ProfileParams; result: PetInfoMetaResult } /** Uninstall a pet (delete its directory); if it was active, turn the display off. */ 'pet.remove': { params: PetSlugParams; result: PetSlugResult } /** Rename a pet's display name + realign its slug/dir; follows the active slug in config. */ 'pet.rename': { params: PetRenameParams; result: PetSlugResult } /** Persist display.pet.scale (clamped to engine bounds) from the desktop slider. */ 'pet.scale': { params: PetScaleParams; result: PetScaleResult } /** Adopt a pet: install (if needed) + activate; writes display.pet.* to config. */ 'pet.select': { params: PetSlugParams; result: PetSlugResult } /** Idle-frame PNG data URI for the picker (desktop CSP breaks CDN ). */ 'pet.thumb': { params: PetThumbParams; result: PetThumbResult } /** Cheapest liveness probe; answered on the WS reader thread even while every agent is mid-turn. */ ping: { params: PingParams; result: PingResult } /** Loaded plugin manager entries (legacy flat view); the Plugins Hub uses plugins.manage list. */ 'plugins.list': { params: PluginsListParams; result: PluginsListResult } /** Plugins Hub backend: list installed plugins, toggle, git-install or re-pin a catalog install. */ 'plugins.manage': { params: PluginsManageParams; result: PluginsManageResult } /** Spawn a hidden agent that brings the desktop preview's dev server back up. */ 'preview.restart': { params: PreviewRestartParams; result: TaskIdResult } /** Kill one background process the caller's session owns and return its output snapshot. */ 'process.kill': { params: ProcessKillParams; result: ProcessKillResult } /** Background processes owned by the caller's session (desktop status stack poll). */ 'process.list': { params: ProcessListParams; result: ProcessListResult } /** Kill every background process in the registry (``/stop``), answering the count killed. */ 'process.stop': { params: ProcessStopParams; result: ProcessStopResult } /** Editor Save: apply any subset of a profile's sections and report each one. */ 'profiles.configure': { params: ProfilesConfigureParams; result: ProfilesConfigureResult } /** Create a profile (ws twin of POST /api/profiles), mirroring launch credentials by default. */ 'profiles.create': { params: ProfilesCreateParams; result: ProfilesCreateResult } /** Everything the profile editor shows: soul, model pin, skills, toolsets, MCP servers. */ 'profiles.describe': { params: ProfileNameParams; result: ProfilesDescribeResult } /** A profile asset as a data URL. */ 'profiles.get_asset': { params: ProfilesGetAssetParams; result: ProfilesGetAssetResult } /** Roster of profiles with previews so a client paints without N follow-up calls. */ 'profiles.list': { params: ProfilesListParams; result: ProfilesListResult } /** Write the onboarding facts into the default profile's user memory and confirm they landed. */ 'profiles.remember_onboarding': { params: ProfilesRememberOnboardingParams; result: ProfilesRememberOnboardingResult } /** Store or clear a profile asset (avatar) atomically. */ 'profiles.set_asset': { params: ProfilesSetAssetParams; result: ProfilesSetAssetResult } /** Structured project facts for a cwd so UIs don't re-sniff the workspace. */ 'project.facts': { params: ProjectFactsParams; result: ProjectFactsResult } /** Attach a folder to a project (optionally as its primary path). */ 'projects.add_folder': { params: ProjectsAddFolderParams; result: ProjectResult } /** Archive (or with ``restore`` un-archive) a project; answers the full listing. */ 'projects.archive': { params: ProjectsArchiveParams; result: ProjectsPayload } /** Create a project from a name + folders; duplicate primary paths are refused (5063). */ 'projects.create': { params: ProjectsCreateParams; result: OptionalProjectResult } /** Delete a project and its folders; answers the full listing. */ 'projects.delete': { params: ProjectIdParams; result: ProjectsPayload } /** Repos for the desktop overview: scanned-from-disk (cached) ∪ session-derived. */ 'projects.discover_repos': { params: ProjectsDiscoverReposParams; result: ProjectsDiscoverReposResult } /** Which project (if any) owns a directory, plus the resolved cwd and its git branch. */ 'projects.for_cwd': { params: ProjectsForCwdParams; result: ProjectsForCwdResult } /** One stored project with its folders. */ 'projects.get': { params: ProjectIdParams; result: ProjectResult } /** Every project of the profile (archived included) plus which one is active. */ 'projects.list': { params: ProfileParams; result: ProjectsPayload } /** Fully hydrated lanes for one project, from the same grouping as projects.tree. */ 'projects.project_sessions': { params: ProjectsProjectSessionsParams; result: ProjectsProjectSessionsResult } /** Persist repo roots found by the client's (desktop-side) scan; return the merged list. */ 'projects.record_repos': { params: ProjectsRecordReposParams; result: ProjectsRecordReposResult } /** Detach a folder from a project. */ 'projects.remove_folder': { params: ProjectFolderParams; result: ProjectResult } /** Switch (or clear) the active project for the profile. */ 'projects.set_active': { params: ProjectsSetActiveParams; result: ActiveIdResult } /** Make one attached folder the project's primary path. */ 'projects.set_primary': { params: ProjectFolderParams; result: ProjectResult } /** Project → repo → lane overview with counts and a few preview sessions per project. */ 'projects.tree': { params: ProjectsTreeParams; result: ProjectsTreeResult } /** Patch a project's display fields; answers the refreshed project. */ 'projects.update': { params: ProjectsUpdateParams; result: ProjectResult } /** Run a task on a fresh agent in the background; the answer arrives as background.complete. */ 'prompt.background': { params: SideAgentParams; result: TaskIdResult } /** Side question over a snapshot of the live conversation; the answer arrives as btw.complete. */ 'prompt.btw': { params: SideAgentParams; result: TaskIdResult } /** Send a user turn to a live session; busy sessions queue / steer / redirect instead of refusing. */ 'prompt.submit': { params: PromptSubmitParams; result: PromptSubmitResult } /** Re-read ~/.hermes/.env (CLI /reload parity); built agents keep their pool until /new. */ 'reload.env': { params: ReloadEnvParams; result: ReloadEnvResult } /** Tear down and rediscover MCP servers for every live session (prompt cache is invalidated). */ 'reload.mcp': { params: ReloadMcpParams; result: ReloadMcpResult } /** Answer an open server→client request from a client that never received the frame. */ 'request.answer': { params: RequestAnswerParams; result: RequestAnswerResult } /** Diff between a checkpoint and the working tree, with an ANSI rendering sized to the TUI. */ 'rollback.diff': { params: RollbackDiffParams; result: RollbackDiffResult } /** Checkpoints for the session's cwd; ``enabled: false`` when checkpointing is off. */ 'rollback.list': { params: RollbackListParams; result: RollbackListResult } /** Restore the working tree (or one file) to a checkpoint by hash or 1-based index. */ 'rollback.restore': { params: RollbackRestoreParams; result: RollbackRestoreResult } /** Attach the frontend to a live session without closing the previously focused one. */ 'session.activate': { params: SessionActivateParams; result: SessionActivateResult } /** Live sessions in this process, insertion order (not a DB browser). */ 'session.active_list': { params: SessionActiveListParams; result: SessionActiveListResult } /** Fork a live session into a new stored child that shares the parent's history so far. */ 'session.branch': { params: SessionBranchParams; result: SessionBranchResult } /** Tear down a live session (its stored row stays resumable). */ 'session.close': { params: SessionCloseParams; result: SessionCloseResult } /** Manual /compress of an idle session, optionally focused on a topic. */ 'session.compress': { params: SessionCompressParams; result: SessionCompressResult } /** Cursor-style split of the context window by category. */ 'session.context_breakdown': { params: SessionContextBreakdownParams; result: SessionContextBreakdownResult } /** Run one allowlisted goal / loop / subgoal / heartbeat action and return the exact resulting snapshot. */ 'session.control': { params: SessionControlParams; result: SessionControlResult } /** Stable, allowlisted snapshot of one live session's goal / loop / heartbeat state. */ 'session.control.read': { params: SessionControlReadParams; result: SessionControlReadResult } /** Mint a live session (agent builds after the reply); a DB row appears on the first prompt unless seeded. */ 'session.create': { params: SessionCreateParams; result: SessionCreateResult } /** Change a live, idle session's working directory. */ 'session.cwd.set': { params: SessionCwdSetParams; result: SessionCwdSetResult } /** Delete a stored session + transcripts; refused while it is live here. */ 'session.delete': { params: SessionDeleteParams; result: SessionDeleteResult } /** Replay events after a seq watermark on WS reconnect; truncated means refetch state. */ 'session.events.since': { params: SessionEventsSinceParams; result: SessionEventsSinceResult } /** Replay-buffer occupancy telemetry (ops/debug). */ 'session.events.stats': { params: SessionEventsStatsParams; result: SessionEventsStatsResult } /** Import a foreign session into this profile's history (idempotent per origin). */ 'session.foreign.import': { params: SessionForeignIdParams; result: SessionForeignImportResult } /** One page of Claude Code / Codex sessions found on the serving backend. */ 'session.foreign.list': { params: SessionForeignListParams; result: SessionForeignListResult } /** Preview a foreign session's tail before importing it. */ 'session.foreign.preview': { params: SessionForeignIdParams; result: SessionForeignPreviewResult } /** The durable display transcript (ancestors included, row ids attached). */ 'session.history': { params: SessionHistoryParams; result: SessionHistoryResult } /** Stop the running turn (and streaming TTS); retires the crash-recovery marker. */ 'session.interrupt': { params: SessionInterruptParams; result: SessionInterruptResult } /** Human-facing stored sessions, most recent first (sub-agent / kanban sources denied). */ 'session.list': { params: SessionListParams; result: SessionListResult } /** Most recent human-facing session; errors fold into a null session_id. */ 'session.most_recent': { params: SessionMostRecentParams; result: SessionMostRecentResult } /** Redirect the active turn (queued for the next turn while the agent is still building). */ 'session.redirect': { params: SessionCorrectionParams; result: SessionCorrectionResult } /** Attach to a stored session: reuse it if live here, else lazy / deferred / cold / eager rebuild. */ 'session.resume': { params: SessionResumeParams; result: SessionResumeResult } /** Export the transcript to ~/.hermes/sessions/saved (classic /save). */ 'session.save': { params: SessionSaveParams; result: SessionSaveResult } /** Set/clear hidden (out of the default list, still resumable by its owner) on a session + lineage. */ 'session.set_hidden': { params: SessionSetHiddenParams; result: SessionSetHiddenResult } /** Rendered /status text for the session. */ 'session.status': { params: SessionStatusParams; result: SessionStatusResult } /** Inject text into the next tool result without interrupting the turn. */ 'session.steer': { params: SessionCorrectionParams; result: SessionCorrectionResult } /** Read or set a live session's title; a title set before the row exists is queued. */ 'session.title': { params: SessionTitleParams; result: SessionTitleResult } /** Drop the last user turn (and everything after it) from an idle session. */ 'session.undo': { params: SessionUndoParams; result: SessionUndoResult } /** Token / context / cost counters for the session (+ Nous credit lines when available). */ 'session.usage': { params: SessionUsageParams; result: SessionUsageResult } /** Re-home a stored session's workspace; git identity is replaced and a live agent follows. */ 'session.workspace.move': { params: SessionWorkspaceMoveParams; result: SessionWorkspaceMoveResult } /** Strict provider check through the same runtime resolution the agent uses on session creation. */ 'setup.runtime_check': { params: SetupRuntimeCheckParams; result: SetupRuntimeCheckResult } /** Loose provider check: is ANY provider auth state discoverable for the (launch or named) profile. */ 'setup.status': { params: ProfileParams; result: SetupStatusResult } /** Run a safe (non-dangerous) shell command captured for ``!cmd`` / inline substitution. */ 'shell.exec': { params: ShellExecParams; result: ShellExecResult } /** Skills hub backend: list the profile's skills or search / browse / inspect / install from the hub. */ 'skills.manage': { params: SkillsManageParams; result: SkillsManageResult } /** Re-scan skill dirs; the pre-rendered ``output`` is what /reload-skills prints. */ 'skills.reload': { params: SkillsReloadParams; result: SkillsReloadResult } /** Execute a slash command against the session's slash worker (or a live/plugin shortcut). */ 'slash.exec': { params: SlashExecParams; result: SlashExecResult } /** Saved spawn-tree snapshots, newest first. */ 'spawn_tree.list': { params: SpawnTreeListParams; result: SpawnTreeListResult } /** Read one saved spawn-tree snapshot (path must be under the spawn-trees root). */ 'spawn_tree.load': { params: SpawnTreeLoadParams; result: SpawnTreeLoadResult } /** Persist a finished delegation tree snapshot under the session's spawn-trees dir. */ 'spawn_tree.save': { params: SpawnTreeSaveParams; result: SpawnTreeSaveResult } /** Hard-interrupt one owned child; ``found`` is false when it already finished. */ 'subagent.interrupt': { params: SubagentIdParams; result: SubagentInterruptResult } /** Live children owned by this session (other sessions' children never leak). */ 'subagent.list': { params: SessionParams; result: SubagentListResult } /** Queue steering text into a live delegated child owned by this session. */ 'subagent.steer': { params: SubagentSteerParams; result: SubagentSteerResult } /** Last 16KB of an owned child's live transcript. */ 'subagent.tail': { params: SubagentIdParams; result: SubagentTailResult } /** Schedule a downgrade / same-price change or a period-end cancellation. */ 'subscription.change': { params: SubscriptionChangeParams; result: BillingPendingChangeResult } /** Chargeless quote of what a plan change would do (billing:manage). */ 'subscription.preview': { params: SubscriptionPreviewParams; result: SubscriptionPreviewResult } /** Clear a scheduled downgrade / cancellation (re-enables recurring spend). */ 'subscription.resume': { params: ProfileParams; result: BillingPendingChangeResult } /** Current plan, tier catalog and usage for the picker; fail-open when logged out. */ 'subscription.state': { params: ProfileParams; result: SubscriptionStateResult } /** Prorate, charge and flip the plan (billing:manage, idempotent). */ 'subscription.upgrade': { params: SubscriptionUpgradeParams; result: SubscriptionUpgradeResult } /** Host battery for the status bar; always resolves, ``available: false`` when unreadable. */ 'system.battery': { params: SystemBatteryParams; result: SystemBatteryResult } /** Record the client's column width for server-side rendering. */ 'terminal.resize': { params: TerminalResizeParams; result: TerminalResizeResult } /** Persist a toolset / MCP enable-disable change and rebuild the session agent so it takes effect now. */ 'tools.configure': { params: ToolsConfigureParams; result: ToolsConfigureResult } /** Every toolset with its resolved tool names, flagged against the session's (or config's) enabled set. */ 'tools.list': { params: _SessionScoped; result: ToolsetsListResult } /** The /tools listing grouped by toolset, including tools deferred behind the tool_search bridge. */ 'tools.show': { params: _SessionScoped; result: ToolsShowResult } /** Toolset summaries (no tool names) for the desktop Toolsets tab. */ 'toolsets.list': { params: _SessionScoped; result: ToolsetsListResult } /** Two-bar dollar usage view shared by /usage, /topup and /subscription; fail-open to unavailable. */ 'usage.bars': { params: ProfileParams; result: UsageModel } /** Add a login / payment / address item to the local vault. */ 'vault.add': { params: VaultAddParams; result: VaultAddResult } /** Metadata-only listing across the local vault and every unlocked password manager. */ 'vault.list': { params: ProfileParams; result: VaultListResult } /** Forget a manager's session token (every manager when no name is given). */ 'vault.lock': { params: VaultLockParams; result: VaultLockResult } /** Remove a local vault item by id. */ 'vault.remove': { params: VaultRemoveParams; result: VaultRemoveResult } /** Enable or disable an external password manager (disabling also locks it). */ 'vault.source.set': { params: VaultSourceSetParams; result: VaultSourceSetResult } /** Status of every login source (local vault + detected password managers). */ 'vault.sources': { params: ProfileParams; result: VaultSourcesResult } /** Unlock a password manager for this session with its master password. */ 'vault.unlock': { params: VaultUnlockParams; result: VaultUnlockResult } /** Best known verification evidence for a cwd/session; read-only, never runs checks. */ 'verification.status': { params: VerificationStatusParams; result: VerificationStatusResult } /** VAD-bounded push-to-talk; the transcript arrives as a voice.transcript event. */ 'voice.record': { params: VoiceRecordParams; result: VoiceRecordResult } /** /voice parity: report, flip voice mode on/off, or toggle speech output. */ 'voice.toggle': { params: VoiceToggleParams; result: VoiceToggleResult } /** Speak text through the backend TTS engine (barge-in aware). */ 'voice.tts': { params: VoiceTtsParams; result: VoiceTtsResult } /** Push client-captured PCM into the armed detector (mic-less remote backends). */ 'wake.feed': { params: WakeFeedParams; result: WakeFeedResult } /** Release the mic (e.g. while the desktop's browser captures audio). */ 'wake.pause': { params: WakeControlParams; result: WakePauseResult } /** Reclaim the mic after a pause; no-op if the listener isn't armed. */ 'wake.resume': { params: WakeControlParams; result: WakeResumeResult } /** Arm the wake-word listener for the calling surface; refusals explain why. */ 'wake.start': { params: WakeStartParams; result: WakeStartResult } /** Everything a client needs to draw the wake-word state and decide whether to (re)arm. */ 'wake.status': { params: WakeStatusParams; result: WakeStatusResult } /** Stop this surface's listener; persist also writes wake_word.enabled: false. */ 'wake.stop': { params: WakeStopParams; result: WakeStopResult } } export type RpcMethod = keyof RpcMethods export const RPC_METHODS = [ 'agents.list', 'approval.pending', 'approval.received', 'approval.respond', 'billing.auto_reload', 'billing.charge', 'billing.charge_status', 'billing.state', 'billing.step_up', 'bot_relay.deliver', 'bot_relay.outbox.drain', 'bot_relay.reply', 'bot_relay.roster.sync', 'browser.controller.detach', 'browser.controller.heartbeat', 'browser.controller.register', 'browser.controller.result', 'browser.manage', 'clarify.lock', 'cli.exec', 'clipboard.paste', 'command.dispatch', 'command.resolve', 'commands.catalog', 'complete.path', 'complete.slash', 'config.get', 'config.set', 'config.show', 'connection.respond', 'connectors.connect', 'connectors.list', 'connectors.operation.status', 'cron.manage', 'delegation.pause', 'delegation.status', 'diagnostics.share_nous', 'file.attach', 'free_tier.ack_notice', 'free_tier.provision', 'free_tier.status', 'gateway.capabilities', 'groups.approve', 'groups.capabilities', 'groups.create', 'groups.demote', 'groups.disband', 'groups.list', 'groups.log', 'groups.peer.invite', 'groups.peer.register', 'groups.peer.revoke', 'groups.promote', 'groups.rename', 'groups.replica_state', 'groups.replicate', 'groups.retry', 'groups.send', 'groups.state', 'groups.stop', 'handoff.fail', 'handoff.request', 'handoff.state', 'image.attach', 'image.attach_bytes', 'image.detach', 'image.generate', 'input.detect_drop', 'insights.get', 'learning.delete', 'learning.detail', 'learning.edit', 'learning.frames', 'llm.oneshot', 'mcp.catalog', 'mcp.servers.add', 'mcp.servers.list', 'mcp.servers.oauth.callback', 'mcp.servers.oauth.cancel', 'mcp.servers.oauth.poll', 'mcp.servers.oauth.start', 'mcp.servers.remove', 'mcp.servers.set_api_key', 'mcp.servers.status', 'mcp.servers.test', 'message.react', 'model.disconnect', 'model.options', 'model.save_key', 'paste.collapse', 'pdf.attach', 'pet.cancel', 'pet.cells', 'pet.disable', 'pet.export', 'pet.gallery', 'pet.generate', 'pet.generate.status', 'pet.hatch', 'pet.info', 'pet.info.meta', 'pet.remove', 'pet.rename', 'pet.scale', 'pet.select', 'pet.thumb', 'ping', 'plugins.list', 'plugins.manage', 'preview.restart', 'process.kill', 'process.list', 'process.stop', 'profiles.configure', 'profiles.create', 'profiles.describe', 'profiles.get_asset', 'profiles.list', 'profiles.remember_onboarding', 'profiles.set_asset', 'project.facts', 'projects.add_folder', 'projects.archive', 'projects.create', 'projects.delete', 'projects.discover_repos', 'projects.for_cwd', 'projects.get', 'projects.list', 'projects.project_sessions', 'projects.record_repos', 'projects.remove_folder', 'projects.set_active', 'projects.set_primary', 'projects.tree', 'projects.update', 'prompt.background', 'prompt.btw', 'prompt.submit', 'reload.env', 'reload.mcp', 'request.answer', 'rollback.diff', 'rollback.list', 'rollback.restore', 'session.activate', 'session.active_list', 'session.branch', 'session.close', 'session.compress', 'session.context_breakdown', 'session.control', 'session.control.read', 'session.create', 'session.cwd.set', 'session.delete', 'session.events.since', 'session.events.stats', 'session.foreign.import', 'session.foreign.list', 'session.foreign.preview', 'session.history', 'session.interrupt', 'session.list', 'session.most_recent', 'session.redirect', 'session.resume', 'session.save', 'session.set_hidden', 'session.status', 'session.steer', 'session.title', 'session.undo', 'session.usage', 'session.workspace.move', 'setup.runtime_check', 'setup.status', 'shell.exec', 'skills.manage', 'skills.reload', 'slash.exec', 'spawn_tree.list', 'spawn_tree.load', 'spawn_tree.save', 'subagent.interrupt', 'subagent.list', 'subagent.steer', 'subagent.tail', 'subscription.change', 'subscription.preview', 'subscription.resume', 'subscription.state', 'subscription.upgrade', 'system.battery', 'terminal.resize', 'tools.configure', 'tools.list', 'tools.show', 'toolsets.list', 'usage.bars', 'vault.add', 'vault.list', 'vault.lock', 'vault.remove', 'vault.source.set', 'vault.sources', 'vault.unlock', 'verification.status', 'voice.record', 'voice.toggle', 'voice.tts', 'wake.feed', 'wake.pause', 'wake.resume', 'wake.start', 'wake.status', 'wake.stop' ] as const satisfies readonly RpcMethod[] // ── Server→client requests ── export interface ServerRequestMap { /** A dangerous command awaits the user's decision. */ approval: { params: ApprovalRequestParams; result: ApprovalResult } /** The clarify tool: ask the user one question or a batch. */ clarify: { params: ClarifyRequestParams; result: ClarifyResult } /** Click / type / scroll / annotate inside the in-app browser preview. */ 'preview.act': { params: PreviewActRequestParams; result: ValueResult } /** Read the in-app browser preview's text (JSON text answer). */ 'preview.read': { params: ReadRangeRequestParams; result: ValueResult } /** Masked value for a named env var (skills / setup flows). */ secret: { params: SecretRequestParams; result: ValueResult } /** Masked sudo password for the terminal tool. */ sudo: { params: SudoRequestParams; result: ValueResult } /** Read the visible in-app terminal buffer (JSON text answer). */ 'terminal.read': { params: ReadRangeRequestParams; result: ValueResult } /** Drive a guided tour highlight in the desktop renderer. */ tour: { params: TourRequestParams; result: ValueResult } /** A one-time / 2FA code the user reads from their device. */ 'vault.code': { params: VaultCodeRequestParams; result: ValueResult } /** Save a login for a site the agent is about to fill; the answer is JSON {identifier, password}. */ 'vault.save_login': { params: VaultSaveLoginRequestParams; result: ValueResult } /** Master password to unlock an external password manager for this session. */ 'vault.unlock_prompt': { params: VaultUnlockRequestParams; result: ValueResult } /** Enumerate the native window below the app (JSON text answer). */ 'window.read': { params: EmptyRequestParams; result: ValueResult } } export type ServerRequestMethod = keyof ServerRequestMap export const SERVER_REQUEST_METHODS = [ 'approval', 'clarify', 'preview.act', 'preview.read', 'secret', 'sudo', 'terminal.read', 'tour', 'vault.code', 'vault.save_login', 'vault.unlock_prompt', 'window.read' ] as const satisfies readonly ServerRequestMethod[] // ── Notifications (`event` frames) ── export interface BackendGatewayEventMap { /** Output chunk from an agent-owned background process. */ 'agent.terminal.output': TerminalOutputPayload /** A /background side agent finished. */ 'background.complete': SideAgentCompletePayload /** Device-flow URL + code for the billing scope step-up; the client opens the browser. */ 'billing.step_up.verification': BillingStepUpVerificationPayload /** A bot-relay outbox envelope is queued; drain it. */ 'bot_relay.outbox.pending': ChangeSignalPayload /** Withdraw a pending controller command. */ 'browser.controller.cancel': BrowserControllerCancelPayload /** Dispatch one browser action to the attached controller. */ 'browser.controller.command': BrowserControllerCommandPayload /** Browser (CDP) connect / install progress line. */ 'browser.progress': BrowserProgressPayload /** A /btw side question was answered. */ 'btw.complete': SideAgentCompletePayload /** A connection operation opened on this session; the desktop renders its card. */ 'connection.request': ConnectionRequestPayload /** One transition or the settlement of an open connection operation. */ 'connection.update': ConnectionUpdatePayload /** cron/jobs.json moved; refetch the cron list. */ 'cron.changed': ChangeSignalPayload /** A session-level failure outside a turn (agent init, model switch, compression, resume). */ error: ErrorPayload /** First frame of a connection: the resolved skin, the change-event capability and the replay epoch. */ 'gateway.ready': GatewayReadyPayload /** Apply a named desktop layout preset. */ 'layout.apply': LayoutApplyPayload /** The turn ended: final text, usage and outcome. */ 'message.complete': MessageCompletePayload /** One streamed chunk of the assistant reply. */ 'message.delta': StreamDeltaPayload /** Interim assistant commentary (text beside tool calls) sealed as its own segment. */ 'message.interim': MessageInterimPayload /** The agent reacted to a message; paint it live. */ 'message.reaction': MessageReactionPayload /** A turn began streaming; no payload. */ 'message.start': Record /** The MoA aggregator started. */ 'moa.aggregating': MoaAggregatingPayload /** MoA phase transition (currently only ``aggregator``). */ 'moa.phase': MoaPhasePayload /** MoA reference fan-out progress (n/total). */ 'moa.progress': MoaProgressPayload /** One MoA reference model's output. */ 'moa.reference': MoaReferencePayload /** Informational one-liner for the session (capabilities refreshed). */ notice: NoticePayload /** Withdraw the notice with this key. */ 'notification.clear': NotificationClearPayload /** Show / replace a keyed out-of-band notice (toast or status bar). */ 'notification.show': NotificationShowPayload /** Pairing state moved; refetch pairing. */ 'pairing.changed': ChangeSignalPayload /** Focus / reveal a named desktop pane. */ 'pane.reveal': PaneRevealPayload /** The active pet / its spritesheet changed (watcher). */ 'pet.changed': PetChangedPayload /** Pet base-draft generation progress. */ 'pet.generate.progress': PetGenerateProgressPayload /** Pet hatch (row drawing) progress. */ 'pet.hatch.progress': PetHatchProgressPayload /** gateway_state.json moved; refetch platform status. */ 'platforms.changed': ChangeSignalPayload /** Close the preview pane or one tab. */ 'preview.close': PreviewClosePayload /** Open a URL / file in the desktop preview pane. */ 'preview.open': PreviewOpenPayload /** The hidden preview-restart agent finished. */ 'preview.restart.complete': SideAgentCompletePayload /** Progress line from the preview-restart agent. */ 'preview.restart.progress': PreviewRestartProgressPayload /** Affection reaction detected in the user's message (hearts etc.). */ reaction: ReactionPayload /** A completed reasoning block (non-streaming providers). */ 'reasoning.available': StreamDeltaPayload /** One streamed chunk of the model's reasoning. */ 'reasoning.delta': StreamDeltaPayload /** The backend withdrew an open server→client request; clear the matching card only. */ 'request.cancel': RequestCancelPayload /** Background review of the last turn finished. */ 'review.summary': ReviewSummaryPayload /** Persisted goal / loop / heartbeat state changed. */ 'session.control.update': SessionControlUpdatePayload /** Live session settings snapshot (``server._session_info``); also the ``info`` of create/resume/activate. */ 'session.info': SessionLiveInfo /** The backend reclaimed a live session out from under its clients. */ 'session.reclaimed': SessionReclaimedPayload /** Deferred resume hydration progress. */ 'session.resume_progress': SessionResumeProgressPayload /** Auto-titling renamed the session (``session_id`` is the stored key). */ 'session.title': SessionTitlePayload /** Mid-turn usage tick; message.complete carries the authoritative final usage. */ 'session.usage': SessionUsagePayload /** state.db moved; refetch the session list. */ 'sessions.changed': ChangeSignalPayload /** The free-tier bootstrap finished (broadcast); the desktop's setup gate reads the record. */ 'setup.ready': SetupReadyPayload /** The active skin moved (name switch or live colour edit); repaint from this palette. */ 'skin.changed': SkinPayload /** Transient status line (kind: status, lifecycle, compacting, goal, loop, heartbeat, process, …). */ 'status.update': StatusUpdatePayload /** A child finished (status + observability rollup). */ 'subagent.complete': SubagentEventPayload /** Batched tool-name progress from a child. */ 'subagent.progress': SubagentEventPayload /** delegate_task accepted a child goal (before the child starts). */ 'subagent.spawn_requested': SubagentEventPayload /** A delegated child started running. */ 'subagent.start': SubagentEventPayload /** A child's reasoning chunk. */ 'subagent.thinking': SubagentEventPayload /** A child called a tool. */ 'subagent.tool': SubagentEventPayload /** An agent-owned background process closed. */ 'terminal.close': TerminalClosePayload /** Legacy thinking-text chunk (thinking_callback). */ 'thinking.delta': StreamDeltaPayload /** Point at a desktop element with a one-line tip bubble. */ 'tip.show': TipShowPayload /** Full todo snapshot after a todo tool ran. */ 'todo.updated': TodoUpdatedPayload /** A tool call finished: parsed result, summary, optional diff / todo snapshot. */ 'tool.complete': ToolCompletePayload /** The model is emitting a tool call's arguments. */ 'tool.generating': ToolGeneratingPayload /** Tool output was classified as risky (prompt-injection / secret findings). */ 'tool.output_risk': ToolOutputRiskPayload /** A tool call began (stable id + full args). */ 'tool.start': ToolStartPayload /** Barge-in: the spoken interjection interrupted the turn; no payload. */ 'voice.interrupted': Record /** Voice recorder state changed. */ 'voice.status': VoiceStatusPayload /** A voice capture produced text (or a stop phrase / silence limit). */ 'voice.transcript': VoiceTranscriptPayload /** A wake phrase fired. */ 'wake.detected': WakeDetectedPayload } export type BackendGatewayEventName = keyof BackendGatewayEventMap export const GATEWAY_EVENT_TYPES = [ 'agent.terminal.output', 'background.complete', 'billing.step_up.verification', 'bot_relay.outbox.pending', 'browser.controller.cancel', 'browser.controller.command', 'browser.progress', 'btw.complete', 'connection.request', 'connection.update', 'cron.changed', 'error', 'gateway.ready', 'layout.apply', 'message.complete', 'message.delta', 'message.interim', 'message.reaction', 'message.start', 'moa.aggregating', 'moa.phase', 'moa.progress', 'moa.reference', 'notice', 'notification.clear', 'notification.show', 'pairing.changed', 'pane.reveal', 'pet.changed', 'pet.generate.progress', 'pet.hatch.progress', 'platforms.changed', 'preview.close', 'preview.open', 'preview.restart.complete', 'preview.restart.progress', 'reaction', 'reasoning.available', 'reasoning.delta', 'request.cancel', 'review.summary', 'session.control.update', 'session.info', 'session.reclaimed', 'session.resume_progress', 'session.title', 'session.usage', 'sessions.changed', 'setup.ready', 'skin.changed', 'status.update', 'subagent.complete', 'subagent.progress', 'subagent.spawn_requested', 'subagent.start', 'subagent.thinking', 'subagent.tool', 'terminal.close', 'thinking.delta', 'tip.show', 'todo.updated', 'tool.complete', 'tool.generating', 'tool.output_risk', 'tool.start', 'voice.interrupted', 'voice.status', 'voice.transcript', 'wake.detected' ] as const satisfies readonly BackendGatewayEventName[]