// 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_account / error``, so everything else is optional. */
export interface BillingStateResult {
  ok: boolean
  logged_in: boolean
  free_tier_account?: 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
  keep_going_on_credits?: boolean | null
  portal_url?: string | null
  error?: string | null
  usage?: UsageModel | null
  plan_usage?: PlanUsage | 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'
/** ``hermes_cli/model_picker_usage.py::PickerUsage.to_payload`` — usage-window plan chrome. */
export interface PlanUsage {
  kind: string
  plan?: string | null
  gauges?: PlanUsageGauge[]
  top_tier_model_ids?: string[]
  featured_model_ids?: string[]
  paused_reason?: string | null
  credits_pay?: boolean | null
}
/** One server allowance on ``ModelOptionProvider.plan_usage``, in the server's order. ``label`` is the server's id (``day`` / ``week`` / ``month`` / ``top_tier`` have client words; any other id shows ``title``). ``scope``: which models a full one stops (``all`` / ``top_tier``). */
export interface PlanUsageGauge {
  label: string
  left_fraction: number
  style: string
  resets_at_ms?: number | null
  scope?: string
  title?: string
}
/** ``_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
  plan_usage?: PlanUsage | 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<string, unknown> | 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<string, unknown> | 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<string, unknown> | 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<string, unknown> | 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<string, unknown> | 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<string, unknown> | null
  actor?: string | null
  code?: string | null
  recovery?: string | null
}
export interface BillingKeepGoingOnCreditsParams {
  profile?: string | null
  enabled?: boolean
}
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<string, unknown> | 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<string, number> | null
  framesByRow?: Record<string, number> | 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[]
}
/** ``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<string, unknown> | 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.<section>``, 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
  reasoning_effort_wire?: string
  service_tier?: string
  fast?: boolean
  yolo?: boolean
  approval_mode?: string
  tools?: Record<string, string[]>
  skills?: Record<string, string[]>
  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
  plan_gauge?: PlanGauge | null
  [key: string]: unknown
}
/** ``gateway/session_usage.py::plan_gauge``: a window plan's allowance for the status bar. */
export interface PlanGauge {
  id: string
  label: string
  used_bp: number
  resets_at_ms?: number | null
}
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_account``, ``free_tier_route``, ``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_account?: boolean | null
  free_tier_route?: boolean | null
  other_providers?: boolean | null
  inference_provider?: string | null
  profile?: string | null
  ok?: boolean | null
  error?: string | null
  error_code?: string | null
  retryable?: boolean | null
  retry_after?: number | null
}
export interface SetupRuntimeCheckParams {
  profile?: string | null
  provider?: string | null
}
/** ``ok=False`` + ``error`` when the resolved model can't be served; ``free_tier_route`` 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_route?: boolean | null
  profile?: string | null
}
export interface DiagnosticsShareNousParams {
  error_context?: string | null
  extra_files?: Record<string, string> | 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_route``'s question. */
export interface FreeTierStatusResult {
  has_guest: boolean
  enabled: boolean
  available: boolean
  notice_pending: boolean
  model: string
  label: string
  error?: string | null
  error_code?: string | null
  retryable?: boolean | null
  retry_after?: number | null
  challenge?: FreeTierChallengePayload | null
  nudge_due_in?: number | null
  connector_nudge_due_in?: number | null
}
/** ``hermes_cli/anon_challenge.py::BrowserChallenge.as_payload``: the ``free_tier.challenge`` event, and ``free_tier.status``'s ``challenge`` field for a client that connected after it. */
export interface FreeTierChallengePayload {
  type: 'browser'
  url: string
  required: boolean
  expires_in: number
  message: string
  attempt?: number
  [key: string]: unknown
}
export interface FreeTierChallengeResultParams {
  profile?: string | null
  url: string
  attempt?: number
  outcome: 'done' | 'failed' | 'closed' | 'timeout' | 'refused' | 'error' | 'unsupported'
}
export interface FreeTierChallengeResult {
  accepted: boolean
}
export interface FreeTierProvisionResult {
  has_guest: boolean
  enabled: boolean
  error?: string | null
  error_code?: string | null
  retryable?: boolean | null
  retry_after?: number | null
}
export interface FreeTierAckNoticeResult {
  acked: boolean
}
export interface FreeTierClaimNudgeParams {
  profile?: string | null
  kind?: 'trial' | 'connector'
}
export interface FreeTierClaimNudgeResult {
  claimed: boolean
}
/** The focused profile's ``telemetry.shared_metrics`` opt-ins. ``send`` is never true while ``enabled`` is false; ``decided`` = either key is written in config.yaml (the shipped defaults are not an answer) and it is not a ``reask``: an "off" from before the type-ahead fix, offered once more with the reason. */
export interface SharedMetricsConsentResult {
  enabled: boolean
  send: boolean
  decided: boolean
  reask?: boolean
}
/** ``send`` is ignored unless ``enabled``; ``first_run`` marks the Desktop first-run answer. */
export interface SharedMetricsSetParams {
  profile?: string | null
  enabled: boolean
  send?: boolean
  first_run?: boolean
}
/** ``command`` is the raw typed name (no leading ``/``, no args); the backend canonicalizes it against the published registry. ``session_id`` scopes the count to that session's profile. */
export interface SharedMetricsSlashCommandParams {
  profile?: string | null
  command: string
  session_id?: string | null
}
export interface SharedMetricsSlashCommandResult {
  ok: boolean
}
/** ``elapsed_ms`` = the client's own launch (TUI process start / Desktop app start) to ready (TUI gateway ready / Desktop backend attached), measured once per launch by the client. The client names its surface because a Desktop may attach to a URL/cloud backend where ``HERMES_DESKTOP`` is unset; without it the backend falls back to its own client detection. ``launch_id`` is an opaque per-launch token the backend latches on (never recorded), so a reconnect re-sending the same launch counts once while a new launch counts again. */
export interface SharedMetricsStartupLatencyParams {
  profile?: string | null
  elapsed_ms: number
  surface?: 'desktop_attach' | 'tui' | null
  launch_id?: string | null
}
export interface SharedMetricsStartupLatencyResult {
  ok: boolean
}
/** One Desktop PACKAGED self-update (electron-updater / App Installer / Store). Source-checkout hand-offs run ``hermes update`` and are counted from its receipt, never here. Raw words; the backend buckets them: ``outcome`` success|failed|noop|refused, ``failed_stage`` download|verify|apply|restart, ``mechanism`` the updater strategy kind, ``duration_ms`` wall time, ``from_commit_date`` the updated-from build's commit time (epoch seconds) when known. */
export interface SharedMetricsUpdateRunParams {
  profile?: string | null
  outcome: string
  failed_stage?: string | null
  mechanism?: string | null
  duration_ms?: number | null
  from_commit_date?: number | null
}
export interface SharedMetricsUpdateRunResult {
  ok: boolean
}
/** ``area`` is a Desktop surface id (``command_palette``, ``terminal_pane``, ``settings_<view>`` …); the backend collapses anything outside its closed set to ``other``. */
export interface SharedMetricsDesktopFeatureUseParams {
  profile?: string | null
  area: string
}
export interface OkResult {
  ok?: boolean
}
/** ``kind`` notice_dismissed|error_toast|renderer_crash|backend_disconnect|slow_frame; ``detail`` a closed code-defined word for that kind (notice id, error category, crash reason, drop reason, frame duration bucket), never message text. */
export interface SharedMetricsDesktopFrictionParams {
  profile?: string | null
  kind: string
  detail: string
}
/** ``step`` a Desktop first-run step id; ``event`` reached|completed|abandoned. */
export interface SharedMetricsDesktopOnboardingParams {
  profile?: string | null
  step: string
  event: string
}
/** ``signal`` quick_close|cancelled|setting_off_default|rage_click|undo|feature_disabled; ``target`` a closed code-defined id for that signal (area, flow, action, undo path, feature toggle); ``setting`` a config key for setting_off_default only (the value is never sent — the backend compares it to the default). */
export interface SharedMetricsDesktopDislikeParams {
  profile?: string | null
  signal: string
  target?: string
  setting?: string | null
}
/** One finished UTC day of Desktop use, aggregated on the client. ``day`` (YYYY-MM-DD) only latches a resend and is never recorded; the raw counts are bucketed by the backend. */
export interface SharedMetricsDesktopDailyParams {
  profile?: string | null
  day: string
  bot_count?: number
  modes?: SharedMetricsDesktopModeDay[]
  actions?: SharedMetricsDesktopActionDay[]
}
export interface SharedMetricsDesktopModeDay {
  mode: 'bots' | 'sessions'
  active_ms?: number
  messages_sent?: number
}
export interface SharedMetricsDesktopActionDay {
  action: string
  via: 'click' | 'menu' | 'palette' | 'shortcut'
  count: number
}
export interface SharedMetricsDesktopDailyResult {
  recorded: 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<string, ModelCapabilities> | null
  pricing?: Record<string, ModelPricing> | null
  pricing_pending?: boolean | null
  free_tier?: boolean | null
  free_tier_pending?: boolean | null
  free_tier_row?: boolean | null
  unavailable_models?: string[] | null
  plan_usage?: PlanUsage | null
  usage_levels?: Record<string, string> | null
  limit?: ProviderLimit | null
  usage?: ProviderUsage | null
  [key: string]: unknown
}
/** ``hermes_cli/inventory.py::_apply_capabilities``. */
export interface ModelCapabilities {
  fast: boolean
  ultrafast?: 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
}
/** ``hermes_cli/inventory.py::_apply_limits`` — ``account``: the whole login is rate-limited until ``resets_at`` (ISO, absent when unknown); ``models``: only these models are, each until its time. */
export interface ProviderLimit {
  scope: 'account' | 'models'
  resets_at?: string | null
  models?: Record<string, string> | null
}
/** ``hermes_cli/inventory.py::_apply_usage`` — the provider's subscription usage, from cache. Multi-entry credential pools carry ``accounts`` (one row per account; the legacy ``windows`` stays EMPTY there — a provider-wide percentage across different logins would be fabricated). Single-account providers keep the legacy ``windows`` gauge. */
export interface ProviderUsage {
  windows?: ProviderUsageWindow[]
  accounts?: ProviderUsageAccount[] | null
}
/** One subscription usage window (``agent/account_usage.py::AccountUsageWindow``): e.g. the 5-hour session or the weekly cap, with how much of it is spent and when it rolls over (ISO). ``scope``: ``account`` — exhausting the window exhausts the whole login (Codex session/weekly, so a limited account's resets_at must wait for it); ``model`` — the window caps only one model family (Anthropic Opus/Sonnet weekly) and can never imply the account itself is out of quota. */
export interface ProviderUsageWindow {
  label: string
  used_percent: number
  resets_at?: string | null
  scope?: 'account' | 'model'
}
/** One account of a provider's credential pool (``hermes_cli/inventory.py::_pool_usage_accounts``). ``id`` is a stable non-secret account identity (never a key or URL); ``label`` may be empty (UI falls back to a localized "Account N"). ``windows`` is empty while the account's usage is not yet known — state carries the meaning, never a fabricated gauge. ``state``: ``ready`` — live quota below the cap (numeric windows present); ``limited`` — a live credential-wide cooldown or exhausted account-scoped quota windows; ``unknown`` — no live numeric windows (failed/empty fetch, stale snapshot, provider without a usage API); ``unavailable`` — DEAD auth row (kept visible, never a quota row). ``resets_at``: for a limited account, the LATEST of its exhausted account-scoped windows (or a live cooldown when later); ``None`` when unknown (the frontend renders its own advisory, e.g. the earliest limited sibling). */
export interface ProviderUsageAccount {
  id: string
  label?: string
  windows?: ProviderUsageWindow[]
  state: 'ready' | 'limited' | 'unknown' | 'unavailable'
  resets_at?: 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 ConnectionOperationParams {
  profile?: string | null
  owner: SessionOwner | AccountOwner
  op_id: string
}
export interface SessionOwner {
  type: 'session'
  session_id: string
}
export interface AccountOwner {
  type: 'account'
}
/** ``methods_connectors._operation_view``: the operation's full snapshot. */
export interface ConnectionOperationStatus {
  op_id: string
  seq: number
  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'
/** ``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
  resolved?: boolean | null
  detail?: string | null
  instructions?: string | null
  discovery_error?: string | null
  connect_url?: string | null
  connection_id?: string | null
  alias?: string | null
  attempt?: string | null
  required_env?: ConnectionTargetEnvField[] | null
  tools?: string[] | null
  hint?: string | null
  display?: string | null
  description?: string | null
  tier?: CatalogTier | null
  platforms?: string[] | null
  repo?: string | null
  sha?: string | null
  subdir?: string | null
  scan?: CatalogScan | null
  requires_hermes?: string | null
  has_desktop_half?: boolean | null
  target_profile?: string | null
  app_state?: CatalogAppState | null
  skill?: string | null
  phase?: InstallPhase | null
  approved?: CatalogApproved | null
  enabled?: boolean | null
  missing_env?: string[] | null
  server_errors?: CatalogServerError[] | null
  already_installed?: boolean | null
}
export type ConnectionTargetKind = 'connector' | 'mcp' | 'plugin' | 'skill'
export type ConnectionTargetAction = 'authorize' | 'connect' | 'enable' | 'install' | 'reconnect'
/** ``tools/connectors/contract.py::TargetState``. */
export type ConnectionTargetState = 'pending' | 'initiated' | 'connected' | 'skipped' | 'failed' | 'expired' | 'not_connected'
/** One credential an MCP install still needs; the card renders a field per entry and sends the values back with the approval. */
export interface ConnectionTargetEnvField {
  name: string
  required: boolean
  secret: boolean
  default: string
  prompt?: string | null
}
export type CatalogTier = 'official' | 'verified' | 'community'
/** The catalog's security scan of the pinned commit; read-only on the card. */
export interface CatalogScan {
  status: CatalogScanStatus
  summary: string
}
export type CatalogScanStatus = 'passed' | 'warnings' | 'failed'
/** The desktop app a catalog plugin drives, from its ``hermes_platform`` declaration. */
export type CatalogAppState = 'present' | 'missing_app' | 'app_not_running' | 'unknown'
/** The slow steps of an install, as ids; the desktop catalog card words them in its own language. */
export type InstallPhase = 'downloading' | 'python_packages' | 'loading_tools'
/** The non-secret Advanced choices the user approved on a catalog row; a Try again after the operation settled repeats them. */
export interface CatalogApproved {
  force: boolean
  enable: boolean
  ref?: string | null
}
/** An MCP server an installed plugin brought that did not connect, with the raw reason. */
export interface CatalogServerError {
  name: string
  error: string
}
export interface ConnectionWakeResult {
  status: 'ok'
}
export interface ConnectionRespondParams {
  profile?: string | null
  owner: SessionOwner | AccountOwner
  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
  said?: string | null
}
/** One row's answer from the card. ``env`` carries the credential values an install asked for through ``required_env``. */
export interface ConnectionAnswerTarget {
  name: string
  status: ConnectionAnswerStatus
  detail?: string | null
  env?: Record<string, string> | null
}
/** What the card says about one row: ``tools/connectors/mcp.py::apply_answer``. */
export type ConnectionAnswerStatus = 'approved' | 'skipped'
export interface ConnectionRespondResult {
  status: 'ok'
  settled: boolean
}
export interface ConnectorsListParams {
  profile?: string | null
  owner: SessionOwner | AccountOwner
}
export interface ConnectorsListResult {
  available: boolean
  connectors: ConnectorRow[]
}
export interface ConnectorRow {
  connector: string
  enabled: boolean
  connected: boolean
  connection_status: 'pending' | 'active' | 'failed' | 'expired' | 'revoked' | 'inactive' | null
  status_reason: string | null
  gateway_disabled_tools: string[]
}
export interface ConnectorsConnectParams {
  profile?: string | null
  owner: SessionOwner | AccountOwner
  connectors: string[]
  reconnect?: boolean
  alias?: string | null
  connection_id?: string | null
}
/** ``methods_connectors._reissue`` / ``managed._off_desktop_result``: the operation the connect opened; ``status``/``note`` ride along from the tool result. */
export interface ConnectorsConnectResult {
  op_id: string
  seq: number
  deadline_at: number
  settled: boolean
  settled_at?: number | null
  settled_by?: ConnectionSettleReason | null
  targets: ConnectionOperationTarget[]
  status?: 'initiated' | 'settled' | null
  note?: string | null
}
export interface ConnectorToolsParams {
  profile?: string | null
  slug: string
  refresh?: boolean
}
export interface ConnectorToolsResult {
  connector: string
  toolkit_version: string
  etag: string
  fetched_at: number
  source: ConnectorToolsSource
  stale: boolean
  tools: ConnectorToolRow[]
}
export type ConnectorToolsSource = 'cache' | 'network' | 'revalidated'
export interface ConnectorToolRow {
  slug: string
  name: string
  description: string
  facet: ConnectorToolFacet
  hints: string[]
  categories: string[]
  no_auth: boolean
  deprecated: boolean
}
export type ConnectorToolFacet = 'read' | 'write' | 'destructive' | 'unclassified'
export interface ConnectorsCatalogResult {
  connectors: ConnectorCatalogRow[]
}
export interface ConnectorCatalogRow {
  slug: string
  name: string
  description: string
  category: string
  logo_url?: string | null
}
export interface ConnectorAccountsParams {
  profile?: string | null
  connector?: string | null
}
export interface ConnectorAccountsResult {
  accounts: ConnectorAccountRow[]
}
export interface ConnectorAccountRow {
  connection_id: string
  connector: string
  status: ConnectorAccountStatus
  status_reason?: string | null
  label: string
  alias?: string | null
  active: boolean
  disabled?: boolean
  created_at: string
  updated_at: string
}
export type ConnectorAccountStatus = 'pending' | 'active' | 'failed' | 'expired' | 'revoked' | 'inactive'
export interface ConnectorAccountsRemoveParams {
  profile?: string | null
  connection_id: string
}
export interface ConnectorAccountsRemoveResult {
  connection_id: string
  connector: string
  status: 'removed'
}
export interface ConnectorAccountsRenameParams {
  profile?: string | null
  connection_id: string
  alias: string
}
export interface ConnectorPolicyGetResult {
  layers: ConnectorPolicyLayer[]
  effective: ConnectorPolicyEffectiveUnrestricted | ConnectorPolicyEffectiveDenyAll | ConnectorPolicyEffectiveAllow | ConnectorPolicyEffectiveDeny
}
export interface ConnectorPolicyLayer {
  kind: ConnectorPolicyLayerKind
  revision: string
  body: ConnectorPolicyUnrestrictedBody | ConnectorPolicyDenyAllBody | ConnectorPolicyAllowBody | ConnectorPolicyDenyBody
}
export type ConnectorPolicyLayerKind = 'org' | 'role' | 'member'
export interface ConnectorPolicyUnrestrictedBody {
  mode: 'unrestricted'
}
export interface ConnectorPolicyDenyAllBody {
  mode: 'deny-all'
}
export interface ConnectorPolicyAllowBody {
  mode: 'allow'
  connectors: string[]
  tools: Record<string, string[]>
  tags?: ConnectorPolicyTags | null
}
export interface ConnectorPolicyTags {
  enable?: string[] | null
  disable?: string[] | null
}
export interface ConnectorPolicyDenyBody {
  mode: 'deny'
  disabled_connectors: string[]
  tools: Record<string, string[]>
  tags?: ConnectorPolicyTags | null
}
export interface ConnectorPolicyEffectiveUnrestricted {
  version: 1
  revision: string
  issued_at_ms: number
  mode: 'unrestricted'
}
export interface ConnectorPolicyEffectiveDenyAll {
  version: 1
  revision: string
  issued_at_ms: number
  mode: 'deny-all'
}
export interface ConnectorPolicyEffectiveAllow {
  version: 1
  revision: string
  issued_at_ms: number
  mode: 'allow'
  connectors: string[]
  tools: Record<string, string[]>
  tags?: ConnectorPolicyTags | null
}
export interface ConnectorPolicyEffectiveDeny {
  version: 1
  revision: string
  issued_at_ms: number
  mode: 'deny'
  disabled_connectors: string[]
  tools: Record<string, string[]>
  tags?: ConnectorPolicyTags | null
}
export interface ConnectorPolicySetParams {
  profile?: string | null
  change: ToolsChange | ConnectorChange
  expected_revision: string
}
export interface ToolsChange {
  type: 'tools'
  connector: string
  disabled_tools: string[]
}
export interface ConnectorChange {
  type: 'connector'
  connector: string
  enabled: boolean
}
export interface ConnectorPolicySetResult {
  revision: string
  effective: ConnectorPolicyEffectiveUnrestricted | ConnectorPolicyEffectiveDenyAll | ConnectorPolicyEffectiveAllow | ConnectorPolicyEffectiveDeny
}
/** ``tools/bot_desktop/runtime.py::DesktopStatus`` plus the lease and the profile it speaks for. */
export interface DisplayStatus {
  profile: string
  supported: boolean
  installed: boolean
  missing: string[]
  running: boolean
  pid?: number | null
  display?: string | null
  socket?: string | null
  geometry: string
  install_command?: string | null
  browser?: string | null
  blocker?: string | null
  memory_available_mb?: number | null
  memory_limit_mb?: number | null
  placement?: string
  image_switch?: DisplayImageSwitch | null
  lease: DisplayLease
  profile_key: string
}
/** A persisted Docker sandbox kept on the previous default image; the user decides the switch. */
export interface DisplayImageSwitch {
  current_image: string
  target_image: string
  containers: number
}
/** ``tools/bot_desktop/lease.py::Lease`` as clients may see it: the holder's viewer id is a capability and never leaves the gateway; ``viewer_hash`` lets the holder recognise itself. */
export interface DisplayLease {
  holder: LeaseHolder
  viewer_id?: null
  viewer_hash?: string | null
  since: number
  epoch: number
  reason?: string
}
export type LeaseHolder = 'agent' | 'human'
/** ``data_url`` is null while the screen is stopped or while a human holds the lease (``suppressed``): the frame may show what they are typing. */
export interface DisplayThumbnailResult {
  data_url?: string | null
  suppressed?: string | null
}
export interface DisplayStopParams {
  profile?: string | null
  force?: boolean | null
}
export interface DisplayStopResult {
  profile: string
  supported: boolean
  installed: boolean
  missing: string[]
  running: boolean
  pid?: number | null
  display?: string | null
  socket?: string | null
  geometry: string
  install_command?: string | null
  browser?: string | null
  blocker?: string | null
  memory_available_mb?: number | null
  memory_limit_mb?: number | null
  placement?: string
  image_switch?: DisplayImageSwitch | null
  lease: DisplayLease
  profile_key: string
  stopped: boolean
}
export interface DisplayObserveParams {
  profile?: string | null
  viewer_id?: string | null
}
export interface DisplayObserveResult {
  profile: string
  supported: boolean
  installed: boolean
  missing: string[]
  running: boolean
  pid?: number | null
  display?: string | null
  socket?: string | null
  geometry: string
  install_command?: string | null
  browser?: string | null
  blocker?: string | null
  memory_available_mb?: number | null
  memory_limit_mb?: number | null
  placement?: string
  image_switch?: DisplayImageSwitch | null
  lease: DisplayLease
  profile_key: string
  ticket: string
  path: string
  viewer_id: string
}
export interface DisplaySwitchSandboxImageParams {
  profile?: string | null
  approve?: boolean
}
export interface DisplaySwitchSandboxImageResult {
  profile: string
  supported: boolean
  installed: boolean
  missing: string[]
  running: boolean
  pid?: number | null
  display?: string | null
  socket?: string | null
  geometry: string
  install_command?: string | null
  browser?: string | null
  blocker?: string | null
  memory_available_mb?: number | null
  memory_limit_mb?: number | null
  placement?: string
  image_switch?: DisplayImageSwitch | null
  lease: DisplayLease
  profile_key: string
  docker_image: string
}
export interface DisplayInstallResult {
  started: boolean
  command?: string | null
  profile_key: string
}
export interface DisplayLeaseAcquireParams {
  profile?: string | null
  viewer_id: string
  reason?: string | null
}
export interface DisplayLeaseResult {
  lease: DisplayLease
}
export interface DisplayLeaseReleaseParams {
  profile?: string | null
  viewer_id?: string | null
  force?: boolean | null
}
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
  seatable_profiles?: string[] | null
}
/** ``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<string, unknown> | 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<string, unknown>
  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<string, unknown> | 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). ``member_activity`` lists live tasks in admission order (absent from older gateways). */
export interface RoomDriverStatus {
  running: boolean
  working: boolean
  blocked: boolean
  counts: Record<string, number>
  pending_actions: Record<string, unknown>[]
  member_activity?: RoomMemberActivity[]
  peer_routes: PeerRouteStatus[]
}
/** One live room task: ``status`` is ``queued``, ``running`` or ``stopping``. */
export interface RoomMemberActivity {
  member_id: string
  status: string
}
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<string, unknown>
}
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<string, unknown>
}
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<string, unknown>
}
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<string, unknown>
  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 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 interface I18nLanguagesResult {
  languages: LanguageOption[]
}
/** ``agent.i18n_languages.language_options`` row. ``source`` is ``bundled``, ``overlay`` or ``plugin:<name>`` — the highest layer that supplies the language. */
export interface LanguageOption {
  id: string
  endonym: string
  rtl: boolean
  source: string
}
export interface I18nCatalogParams {
  profile?: string | null
  lang: string
  surface?: LocaleSurface
}
export type LocaleSurface = 'core' | 'tui' | 'desktop'
/** ``messages`` is ONLY the pack + user-overlay layer for that surface (flat dotted keys); the client merges it over its bundled ``en``/``<lang>``. ``lang`` is the canonical id the request resolved to (``pt-BR`` → ``pt-br``; an unknown id resolves to ``en`` with an empty layer). */
export interface I18nCatalogResult {
  lang: string
  surface: LocaleSurface
  messages: Record<string, string>
}
export type PingParams = Record<string, never>
export interface PingResult {
  pong: boolean
}
export interface GatewayCapabilitiesResult {
  per_session_exclusive_submit: boolean
}
export interface ClientCapabilitiesParams {
  server_requests?: boolean
  desktop_local?: boolean
}
export interface ClientCapabilitiesResult {
  server_requests: string[]
  declines_not_shown?: boolean
}
/** Client→server method params / server→client request params. Unknown keys are rejected. */
export type Params = Record<string, never>
/** ``machine_kind`` is ``Spark``, ``Mac``, ``PC`` or ``computer``. ``nvidia_platform`` is ``products.nvidia_platform()``: ``rtx_spark``, ``dgx_spark``, ``discrete`` or null. ``locale`` is the OS account's first UI language, null when the OS has none. */
export interface MachineFactsResult {
  machine: MachineInfo
  machine_kind: string
  has_nvidia_gpu: boolean
  nvidia_platform?: 'rtx_spark' | 'dgx_spark' | 'discrete' | null
  locale?: string | null
}
/** Measured hardware; a key that was not measured is absent. */
export interface MachineInfo {
  os_family?: string | null
  os_release?: string | null
  native_arch?: string | null
  cpu_model?: string | null
  ram_gb?: number | null
  gpu_class?: string | null
  vendor?: string | null
  wsl?: boolean | null
  container?: boolean | null
}
/** ``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
}
/** ``session_id`` binds skill completions to that session's profile and workspace (project skills); ``profile`` scopes a session-less request (a new-chat draft). */
export interface CompleteSlashParams {
  text?: string | null
  session_id?: string | null
  profile?: 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; ``install_id`` (as on ``/api/status``) names the machine that answered. */
export interface ProfilesListResult {
  profiles?: ProfileRow[]
  bot_mode_protocol?: boolean
  install_id?: string
}
/** 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
  previous_names?: string[]
  last_session?: ProfileSessionPreview | null
  worker_session?: ProfileWorkerSession | null
  canonical_session?: ProfileCanonicalSession | null
  ui_meta_revisions?: Record<string, number>
  ui_meta?: Record<string, unknown> | 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
  live_message_count?: number | null
}
/** 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
  live_message_count?: number | null
}
/** ``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<string, unknown> | null
  ui_meta_expected_revisions?: Record<string, number> | 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<string, number> | null
  ui_meta_conflicts?: Record<string, UiMetaConflict> | 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
}
/** ``assume_fresh``: the unpackaged desktop's ``--fresh-install`` launch; the backend treats this machine as one that never used Hermes. Packaged builds never send it. */
export interface OnboardingStateParams {
  assume_fresh?: boolean
}
/** ``run``: onboarding opens on this launch (root config ``onboarding.run``, else a machine that never used Hermes). ``eligible``: this is the desktop's local backend and the welcome trial or a configured provider can carry the first chat. ``session_id``: the stored id of the onboarding chat still in progress, so a relaunch reopens it; ``run_id``: that run's id, which ``onboarding.ended`` names. */
export interface OnboardingRunStateResult {
  run: boolean
  eligible: boolean
  session_id?: string | null
  run_id?: string | null
}
/** ``mark_profile_offered`` also latches ``onboarding.seen.profile_build_offered`` in the root config, so the first chat after onboarding gets the plain intro instead of the profile offer. */
export interface OnboardingSetRunParams {
  run: boolean
  mark_profile_offered?: boolean
}
/** ``rerun``: start a new onboarding chat even when one is in progress (Settings, Run onboarding again; it never claims the welcome trial). ``fresh_launch``: the app's once-per-launch start; a run the app was closed on does not count, so its chat is deleted and the run starts over. ``facts_source``: whether the backend runs on the user's own computer. ``locale``: the desktop's UI language, preferred over the backend OS locale. ``assume_fresh``: as on ``onboarding.state``. A new run on a first install claims the welcome trial before its chat exists; a failed claim is error 5079 and leaves no guest and no chat. A claim that is blocked (another install took the trial) with no trial or provider to run on is error 5080 and opens no chat. */
export interface OnboardingStartParams {
  rerun?: boolean
  fresh_launch?: boolean
  assume_fresh?: boolean
  facts_source?: OnboardingFactsSource
  locale?: string | null
}
export type OnboardingFactsSource = 'local' | 'remote'
/** ``session_id`` is the runtime id the client attaches to; ``resumed`` is true when an onboarding chat already in progress was reopened instead of a new one started. ``run_id`` names the run in ``onboarding.ended``. */
export interface OnboardingStartResult {
  session_id: string
  stored_session_id: string
  resumed: boolean
  run_id: string
}
export interface OnboardingSkipParams {
  session_id: string
  profile?: string | null
}
export interface OnboardingSkipResult {
  skipped: boolean
}
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<string, unknown> | 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``: recently failed async delegation tasks for the session (durable store), newest first. */
export interface SubagentListResult {
  subagents?: SubagentSnapshot[]
  delegations?: FailedDelegation[]
}
/** ``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'
/** ``async_delegation.failed_delegations_for_session`` row: one failed task of an async delegation. */
export interface FailedDelegation {
  delegation_id: string
  task_index?: number
  status: string
  goal?: string
  error?: string | null
  dispatched_at?: number | null
  completed_at?: number | null
}
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[]
  sessionIds?: string[]
}
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
  isGit?: 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
  continuation_kind?: 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<string, number> | null
  framesByRow?: Record<string, number> | 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
  voice_turn?: boolean | null
  title_preview?: 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
  confirm_deep_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
  user_row_id?: number | null
  survivor_user_row_ids?: (number | null)[] | null
  survivor_row_id_map?: Record<string, number | null> | null
  turn_isolation?: boolean | null
  admission_id?: string | null
  forwarded?: 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<string, unknown>
  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
  cwd_explicit?: boolean | 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
  service_tier?: string | null
  close_on_disconnect?: boolean
  hidden?: boolean
  room_plumbing?: boolean
  follow_profile_config?: boolean
  idempotency_key?: string | null
}
/** 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``, display-only ``timestamp`` / ``display_kind`` / ``display_metadata``, the durable ``row_id`` rewind targets, and for tool rows raw ``content``, ``tool_call_id``, ``name``, ``context`` and ``args``. Assistant detail sidecars (``reasoning``, …) ride as extra keys. */
export interface TranscriptMessage {
  role: string
  text?: string | null
  content?: unknown | null
  tool_call_id?: 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<string, unknown> | null
  labels?: ToolLabel[] | null
  reasoning?: string | null
  [key: string]: unknown
}
/** ``tools.tool_labels.ToolLabel`` — what one call executed through the tool_search bridge is, in words. Clients render ``text`` (or ``app``/``action`` in their own columns) and never parse the tool name themselves. */
export interface ToolLabel {
  kind: ToolLabelKind
  app: string
  action: string
  emoji: string
  text: string
  name: string
  preview?: string
}
/** Which surface one inner call of a bridged ``tool_call`` runs on. */
export type ToolLabelKind = 'connector' | 'mcp' | 'tool'
export interface SessionBranchStoredParams {
  profile?: string | null
  parent_session_id: string
  cols?: number | null
  source?: string | null
  cwd?: string | null
  idempotency_key?: string | null
}
export interface SessionBranchStoredResult {
  session_id: string
  stored_session_id: string
  message_count: number
  messages_omitted: boolean
  info: SessionLiveInfo
}
/** ``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
  inline_images?: 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
  display_kind?: string | null
  display_metadata?: Record<string, unknown> | null
  corrections?: string[] | null
  correction_offsets?: number[] | null
  error?: string | null
  status?: string | null
  recoverable?: boolean | null
  error_surface?: Record<string, unknown> | 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<string, unknown>
}
/** ``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
  seq: number
  deadline_at: number
  timeout_seconds: number
  targets: ConnectionOperationTarget[]
  tool_call_id?: string | null
  display?: ConnectionDisplay | null
}
/** ``manage_connections`` action ``display``: the directory card, with these slugs pinned as Suggested. */
export interface ConnectionDisplay {
  suggested: string[]
}
/** ``tool_progress._normalize_todo_state``: the authoritative todo snapshot. */
export interface TodoState {
  todos: Record<string, unknown>[]
  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
  live_message_count?: number | null
  source?: string
  _lineage_root_id?: string | null
}
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
  source?: string | null
  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
}
/** ``session_id`` (or its ``session_key`` alias) is a live runtime id first, else a stored id / key / title. */
export interface SessionArchiveParams {
  session_id?: string | null
  session_key?: string | null
  archived?: boolean
  profile?: string | null
}
export interface SessionArchiveResult {
  archived: 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
  reasoning_effort_wire?: string
  service_tier?: string
  fast?: boolean
  yolo?: boolean
  approval_mode?: string
  tools?: Record<string, string[]>
  skills?: Record<string, string[]>
  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
  messages?: string[]
}
export interface SessionBranchParams {
  session_id: string
  profile?: string | null
  name?: string | null
  count?: number | null
  idempotency_key?: string | null
}
export interface SessionBranchResult {
  session_id: string
  stored_session_id: string
  title: string
  parent: string
  message_count: number
  messages: TranscriptMessage[]
  info: SessionLiveInfo
}
export interface SessionBranchWholeParams {
  session_id: string
  profile?: string | null
  name?: string | null
  idempotency_key?: string | null
}
export interface SessionBranchWholeResult {
  session_id: string
  stored_session_id: string
  title: string
  parent: string
  message_count: number
  messages_omitted: boolean
  info: SessionLiveInfo
}
export interface SessionUndoParams {
  session_id: string
  profile?: string | null
  intent?: UndoIntent | null
}
export type UndoIntent = 'retry' | 'undo'
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
  plan_gauge?: PlanGauge | null
  credits_lines?: string[] | null
  credits_usage_window?: boolean | 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) plus the per-file context manifest (empty until the agent exists). */
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
  context_files?: ContextFileSource[]
}
export interface ContextCategory {
  color: string
  id: string
  label: string
  tokens: number
}
/** One row of ``agent.context_file_sources.list_context_file_sources``. */
export interface ContextFileSource {
  label: string
  path: string
  chars: number
  est_tokens: number
  loaded: boolean
  status: string
}
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<string, unknown> | 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<string, unknown>[]
  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<string, unknown>[]
  [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
  replay_epoch?: string | null
}
export interface SessionEventsSinceResult {
  events: Record<string, unknown>[]
  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<string, unknown> | 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
  delegations?: 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
  exited_at?: number | null
  started_epoch?: number | null
  completion_reason?: string | 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<string, string[]>
  canon?: Record<string, string>
  commands?: Record<string, CommandCatalogMeta>
  categories?: CommandCategory[]
  skills?: Record<string, SkillCatalogEntry>
  skill_count?: number
  warning?: string
  plugin_discovery_error?: string
  plugin_commands?: Record<string, string>
}
export interface CommandCatalogMeta {
  argument_mode?: ArgumentMode | null
  desktop?: string | null
  desktop_subcommands?: 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
  all?: boolean | 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?: string[] | 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
  enabled?: boolean | null
  session_id?: string | null
  profile?: string | null
}
export type BrowserAction = 'status' | 'connect' | 'disconnect' | 'use'
export interface BrowserManageResult {
  connected: boolean
  url?: string | null
  messages?: string[] | null
  browser_use?: boolean | 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[]
}
/** The shared owner serves ``/reload`` for one session the caller controls (``session_id``). */
export interface ReloadEnvParams {
  session_id?: string | null
  profile?: string | null
}
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
}
/** ``session``: what the calling local session's MCP servers did (a new policy generation, nothing to change, or deferred while a turn runs or waits); ``unavailable``: configured servers that did not connect beside what did apply; ``session_servers``: the MCP servers that session's committed policy runs. */
export interface ReloadMcpResult {
  status: ReloadMcpStatus
  message?: string | null
  loaded_rev?: string | null
  coalesced?: boolean | null
  turn_isolation?: boolean | null
  host_ack?: unknown | null
  session?: ReloadMcpSession | null
  unavailable?: string[] | null
  session_servers?: string[] | null
}
export type ReloadMcpStatus = 'confirm_required' | 'reloaded'
export type ReloadMcpSession = 'applied' | 'unchanged' | 'busy'
/** ``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<string, string[]> | 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
}
/** ``session_id`` binds the rescan to that session's profile and workspace (project skills); ``profile`` scopes a session-less rescan. */
export interface SkillsReloadParams {
  session_id?: string | null
  profile?: string | null
}
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<string, unknown>[]
}
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
  connector_slug?: string | null
  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
  source: McpServerSource
  plugin?: string | null
}
export type McpServerSource = 'config' | 'plugin'
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
  source: McpServerSource
  plugin?: string | null
}
export type McpRuntimeStatus = 'connected' | 'disabled' | 'connecting' | 'failed' | 'lazy' | '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<string, unknown> | 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<string, never>
export interface PluginsListResult {
  plugins: LegacyPluginRow[]
  toolsets?: PluginToolsetRow[] | null
  portable_mcp_servers?: string[] | null
}
export interface LegacyPluginRow {
  name: string
  version: string
  enabled: boolean
  key?: string | null
  tools?: number | null
  hooks?: number | null
  commands?: number | null
  error?: string | null
}
export interface PluginToolsetRow {
  key: string
  label: string
  description: string
}
/** ``toggle``: ``key``/``name`` + ``enable``; ``install``: ``identifier``/``repo`` or ``catalog_name`` (+ ``force``, ``enable``, ``ref``); ``update``: ``name`` (+ ``accept_capabilities`` to apply a re-pin that widened the plugin after the user confirmed the ``delta``, + ``force`` to apply an update whose security scan returned caution after the user saw the findings); ``remove``: ``name`` (user installs only); ``settings``: ``key`` + ``values`` (``{setting_key: value}``, non-secret schema keys only); ``presence``: ``names`` (catalog names, answered in that order). */
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
  accept_capabilities?: boolean | null
  values?: Record<string, unknown> | null
  names?: string[] | null
}
export type PluginsAction = 'list' | 'toggle' | 'install' | 'update' | 'remove' | 'settings' | 'onboarding' | 'presence'
/** ``list`` → ``plugins`` + counts; ``toggle`` → ``ok``/``unchanged``/``restart_required``/``name`` (the canonical key written)/``plugin``; ``install`` → ``hermes_cli.plugins_cmd.dashboard_install_plugin``'s ok payload; ``toggle``/``install``/``update`` that loaded a plugin also carry ``gateway_reloaded`` (the running gateway picked it up and re-wired its handlers) and ``activation`` — the honest split of what is live now vs deferred, so ``restart_required`` is True only when no gateway answered; ``update`` → ``ok``/``unchanged``/``sha``, or ``ok=false`` + ``consent_required`` with the ``delta`` (``{surface: [added...]}``) / ``delta_lines`` a widened pin adds — nothing changed until the client retries with ``accept_capabilities`` — or ``ok=false`` + ``scan_blocked`` with ``scan_verdict`` / ``scan_findings`` (retry a caution verdict with ``force``); ``remove`` → ``ok``/``name`` plus ``cleared_memory_provider`` when the removed plugin was the live ``memory.provider``. */
export interface PluginsManageResult {
  plugins?: AgentPluginRow[] | null
  user_count?: number | null
  bundled_count?: number | null
  ok?: boolean | null
  unchanged?: boolean | null
  restart_required?: boolean | null
  gateway_reloaded?: boolean | null
  activation?: PluginActivation | null
  cleared_memory_provider?: boolean | null
  name?: string | null
  plugin?: AgentPluginRow | null
  plugin_name?: string | null
  warnings?: string[] | null
  missing_env?: string[] | null
  python_dependencies?: string[] | null
  known_issues?: string[] | null
  after_install_path?: string | null
  enabled?: boolean | null
  sha?: string | null
  consent_required?: boolean | null
  delta?: Record<string, string[]> | null
  delta_lines?: string[] | null
  scan_blocked?: boolean | null
  scan_verdict?: string | null
  scan_findings?: PluginScanFinding[] | null
  error?: string | null
  written?: string[] | null
  onboarding?: OnboardingCatalogPlugin[] | null
  presence?: CatalogPluginPresence[] | 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
  servers: PluginServerRow[]
  catalog_name?: string | null
  catalog_tier?: string | null
  installed_sha?: string | null
  catalog_sha?: string | null
  catalog_version?: string | null
  update_available?: boolean | null
  update_target?: string | null
  pinned_sha?: string | null
  settings_schema?: PluginSettingField[] | null
}
export interface PluginServerRow {
  name: string
  state: PluginServerState
  sentence: string
}
export type PluginServerState = 'connected' | 'app_not_running' | 'hermes_not_connected' | 'endpoint_unavailable' | 'no_interactive_session' | 'version_too_old' | 'missing_app' | 'unsupported_gpu' | 'unknown'
/** One ``config_schema`` key of a plugin manifest, rendered by the Plugins hub (``hermes_cli.plugins_settings.plugin_settings_fields``). ``secret`` fields carry no value: ``env`` names the ``.env`` variable and ``has_value`` whether it is set. */
export interface PluginSettingField {
  key: string
  type: PluginSettingFieldType
  label: string
  description: string
  required: boolean
  value?: unknown | null
  default?: unknown | null
  choices?: string[] | null
  env?: string | null
  has_value?: boolean | null
}
export type PluginSettingFieldType = 'string' | 'number' | 'boolean' | 'enum' | 'secret' | 'json'
/** What a plugin loaded mid-run does NOW vs later (``hermes_cli.plugins_activation``). ``activated_now`` kinds (``{kind: [names]}``): ``gateway_commands`` (slash names), ``locales`` (``<lang>.<surface>`` language-pack layers), ``gateway_transforms`` / ``hooks`` (hook names), ``callbacks`` (platforms / ``slack:<action_id>``) — live in the running gateway once it reloaded (``gateway_reloaded``). ``live_now``: the plugin's MCP servers (connected, with their tools, or the error) and skills, usable in every open chat of the profile from its next turn — the chats also get a note listing them. ``deferred`` kinds: ``tools`` (Python tool names) and ``prompt`` (section ids) apply from the next session. */
export interface PluginActivation {
  name: string
  key: string
  activated_now?: Record<string, string[]>
  live_now?: PluginLiveNow | null
  deferred?: Record<string, string[]>
}
export interface PluginLiveNow {
  mcp_servers?: PluginLiveServer[]
  skills?: PluginLiveSkill[]
}
/** One plugin MCP server connected at activation: its callable tool names, or the reason it did not connect. */
export interface PluginLiveServer {
  name: string
  connected: boolean
  tools?: string[]
  error?: string | null
}
/** One plugin skill usable now through ``skill_view`` (qualified ``<plugin>:<skill>``). */
export interface PluginLiveSkill {
  name: string
  description?: string
}
/** One security-scan finding (``tools.plugin_guard``) on a plugin tree the scan blocked. */
export interface PluginScanFinding {
  pattern_id: string
  severity: string
  category: string
  file: string
  line: number
  description: string
}
/** A catalog plugin curated for the onboarding card (``onboarding: true``) that this OS runs. ``app_state`` is the pinned ``plugin.json`` declaration judged on this host; ``sentence`` names what is missing (empty when present or unknown). */
export interface OnboardingCatalogPlugin {
  name: string
  title: string
  description: string
  tier: CatalogTier
  platforms: string[]
  app_state: CatalogAppState
  sentence: string
}
/** A named catalog plugin this OS runs. ``state`` is the pinned ``plugin.json`` app declaration judged on this host; ``sentence`` names what is missing (empty when present or unknown); ``disclosure`` is the catalog description's ``Disclosure:`` sentence (empty when it has none). */
export interface CatalogPluginPresence {
  name: string
  title: string
  state: CatalogAppState
  sentence: string
  disclosure: string
}
export interface PluginCatalogLookupParams {
  profile?: string | null
  name: string
}
/** ``found`` carries ``entry``. ``unknown`` covers a name the catalog doesn't list and one it removed; ``unavailable`` means neither the live catalog nor the in-tree fallback could be read. */
export interface PluginCatalogLookupResult {
  status: PluginCatalogLookupStatus
  entry?: PluginCatalogLookupEntry | null
}
export type PluginCatalogLookupStatus = 'found' | 'invalid_name' | 'unknown' | 'unavailable'
/** The fields an install needs: the same ones the embedded catalog picker posts on a pick. */
export interface PluginCatalogLookupEntry {
  name: string
  repo: string
  sha: string
  subdir: string
  tier?: string
}
export interface CanonicalShellExecParams {
  session_id: string
  command: string
  profile?: string | null
}
export interface PromptReceiptParams {
  session_id: string
  admission_id: string
  include_result?: boolean | null
}
/** ``result`` / ``usage``: the structured turn result committed at settlement, only with ``include_result`` on a terminal admission that saved one. */
export interface PromptReceiptResult {
  admission_id: string
  ref: CanonicalSessionRef
  sequence: number
  status: 'queued' | 'started' | 'unknown' | 'terminal'
  outcome: string | null
  authority_epoch: number
  execution_generation: number | null
  result?: unknown | null
  usage?: Record<string, unknown> | null
}
export interface CanonicalSessionRef {
  profile_id: string
  session_id: string
}
export interface PromptCancelParams {
  session_id: string
  admission_id: string
}
/** ``gateway/session_contract.py::AdmissionReceipt`` as ``dataclasses.asdict`` sends it. */
export interface AdmissionStatus {
  admission_id: string
  ref: CanonicalSessionRef
  sequence: number
  status: 'queued' | 'started' | 'unknown' | 'terminal'
  outcome: string | null
  authority_epoch: number
  execution_generation: number | null
}
export interface PromptResolveUnknownParams {
  session_id: string
  admission_id: string
  execution_generation: number
}
/** ``operation`` + ``payload`` are validated by ``hermes_state_mutations.validate_action``; ``expected_generation`` is required for delete/rewind/reset/branch/model/compress/reasoning/workspace. ``reasoning`` (``{effort}``) and ``workspace`` (``{cwd}``, refused ``session_busy`` mid-turn) rewrite the session's frozen policy: session-scope ``/reasoning`` and Desktop's Move to project. ``edit_policy`` (``{policy}``: ask / workspace_session / session) is an ACP session's edit approval (main's ACP modes). */
export interface SessionMutateParams {
  session_id: string
  request_id: string
  expected_revision: number
  operation: string
  payload: Record<string, unknown>
  expected_generation?: number | null
}
/** The committed mutation receipt plus the operation's projection (``title``, ``archived``, ``branched_session_id``, compress ``status``/``lines``, …). ``revision`` is absent only on a read-only compress preview. */
export interface SessionMutateResult {
  session_id: string
  operation: string
  revision?: number | null
  [key: string]: unknown
}
/** Exactly one of ``filters`` (``SessionDB.prune_sessions`` keyword filters, as ``hermes sessions prune`` builds them) or ``never_active_days`` (``--never-active``). */
export interface SessionPruneParams {
  filters?: Record<string, unknown> | null
  never_active_days?: number | null
}
export interface SessionPruneResult {
  deleted: number
  routing_deleted?: number | null
  skipped?: number | null
}
export interface CommandObserveParams {
  session_id: string
  name: string
  arg?: string | null
  profile?: string | null
}
export interface CommandObserveResult {
  queued: boolean
}
export interface CanonicalSessionInfoParams {
  session_id: string
}
/** ``gateway/session_local_inventory.py::snapshot_info``: ``local_session_info`` + the inventory. */
export interface CanonicalSessionInfo {
  provider?: string | null
  tools?: Record<string, string[]> | null
  skills?: Record<string, string[]> | null
  mcp_servers?: McpServerStatus[] | null
  version?: string | null
  release_date?: string | null
  update_behind?: unknown | null
  update_command?: string | null
  branch?: string | null
  project?: ProjectRef | null
  system_prompt?: string | null
  context_length?: number | null
  enabled_toolsets?: string[] | null
  tool_availability?: Record<string, unknown> | null
  tool_availability_warnings?: string[] | null
  browser_backend_notice?: string | null
  unknown_toolsets?: string[] | null
  source: string
  model?: string | null
  lazy: boolean
  profile_id: string
  desktop_protocol: string
  profile_name: string
  cwd?: string | null
  edit_approval_policy?: 'ask' | 'workspace_session' | 'session' | null
  launch_request?: Record<string, unknown> | null
  reasoning_effort?: string | null
  reasoning_effort_wire?: string | null
  service_tier?: string | null
  fast?: boolean | null
  title?: string | null
  started_at?: number | null
  last_active_at?: number | null
  yolo?: boolean | null
  api_mode?: string | null
  tool_count?: number | null
  credential_hint?: string | null
  config_warning?: string | null
  [key: string]: unknown
}
export interface SessionStatsParams {
  session_id: string
}
/** ``gateway/session_usage.py::usage_stats``: session-cumulative counters (the agent's ``session_*``), context / compressor figures, rolling latency and throughput, rate-limit state, live subagents. */
export interface SessionStats {
  input_tokens: number
  output_tokens: number
  cache_read_tokens: number
  cache_write_tokens: number
  prompt_tokens: number
  completion_tokens: number
  total_tokens: number
  reasoning_tokens: number
  api_calls: number
  last_prompt_tokens: number
  context_tokens: number
  context_length?: number | null
  config_context_length?: number | null
  context_source?: string | null
  compression_count: number
  avg_latency_s?: number | null
  tokens_per_s?: number | null
  last_turn_tokens: number
  rate_limit?: Record<string, unknown> | null
  active_subagents: number
  model: string
  provider: string
  fallback_model?: string | null
  plan_gauge?: PlanGauge | null
}
export interface RollbackSessionDiffParams {
  session_id: string
  profile?: string | null
}
/** ``gateway/session_tui_ops.py::_session_diff``: ``CheckpointManager.session_diff`` under the session's frozen checkpoint policy (``enabled: false`` when that policy does not checkpoint). ``diff`` is bounded to fit one frame; ``diff_lines`` counts the whole body. */
export interface RollbackSessionDiffResult {
  enabled: boolean
  success?: boolean
  stat?: string
  diff?: string
  diff_lines?: number
  empty?: boolean
  error?: string | null
}
/** ``format``: json (default) / md / markdown / html / snapshot (``normalize_save_format``). */
export interface SessionExportParams {
  session_id: string
  profile?: string | null
  format?: string
  redact?: boolean
}
/** ``gateway/session_tui_ops.py::export_session``: the rendered ``/save`` body and its default file name. The client writes it (the gateway may be remote); nothing is written on the host. */
export interface SessionExportResult {
  format: string
  filename: string
  content: string
}
export interface SessionAutomationParams {
  session_id: string
  kind: 'goal' | 'loop' | 'heartbeat'
  call: string
  args?: unknown[] | null
  kwargs?: Record<string, unknown> | null
}
/** ``gateway/session_viewer_automation.py``: the manager's persisted state after the call (its own JSON, ``null`` when none) and the call's value, or the refusal main's manager raised. */
export interface SessionAutomationResult {
  state: string | null
  value?: unknown | null
  error?: Record<string, string> | null
}
export interface SessionDetachParams {
  session_id: string
  subscription_id: string
  end_reason?: string | null
}
export interface SessionDetachResult {
  session_id: string
  subscription_id: string
  detached: boolean
}
export type RuntimeDescribeParams = Record<string, never>
export interface RuntimeDescribeResult {
  instance_id: string
  profile_id: string
  authority_epoch: number
  capabilities: string[]
  session_create: SessionCreateDescriptor
  skin?: SkinPayload | null
}
export interface SessionCreateDescriptor {
  sources: string[]
  parameters: string[]
}
/** ``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<string, string>
  light_colors?: Record<string, string>
  dark_colors?: Record<string, string>
  branding?: Record<string, string>
  banner_logo?: string
  banner_hero?: string
  tool_prefix?: string
  help_header?: string
  [key: string]: unknown
}
export interface ClarifyRespondParams {
  session_id: string
  execution_generation: number
  prompt_id: string
  answer: string
}
export interface PromptResponseResult {
  status: 'resolved' | 'already_resolved'
  prompt_id: string
}
export interface CronRunParams {
  job_id: string
  request_id: string
  extra_prompt: string | null
}
export interface CronSubmitResult {
  session_id: string
  admission_id: string
}
/** ``result`` is the ``run_job`` tuple once terminal; ``recover`` adds the frozen ``job`` and answers ``status='missing'`` for a firing that was never admitted. */
export interface CronStatusResult {
  status: string
  result: unknown[] | null
  job_flags?: Record<string, unknown> | null
  job?: Record<string, unknown> | null
  [key: string]: unknown
}
export interface CronAdmissionParams {
  session_id: string
  admission_id: string
}
export interface CronCancelResult {
  ok: boolean
}
export interface KanbanRunParams {
  board: string
  task_id: string
  run_id: number
  claim_lock: string
  db?: string | null
}
export interface KanbanRunResult {
  session_id: string
  receipt: AdmissionStatus
}
export interface A2aForwardParams {
  agent: string
  tenant: string
  peer: string
  context_id: string
  input_id: string
  text: string
}
export interface A2aForwardResult {
  admission_id: string
  ref: CanonicalSessionRef
  sequence: number
  status: 'queued' | 'started' | 'unknown' | 'terminal'
  outcome: string | null
  authority_epoch: number
  execution_generation: number | null
  session_id: string
  result: unknown | null
}
export interface WorkerRegisterParams {
  profile_id: string
  session_id: string
  execution_id: string
  generation: number
  pid: number
  birth: number
  secret: string
  kind: string
}
/** A ``worker_executions`` row without its adoption digest. */
export interface WorkerExecution {
  execution_id: string
  session_id: string
  kind: string
  owner_epoch: number
  generation: number
  status: string
  last_sequence: number
  [key: string]: unknown
}
/** The producer claim every worker verb proves (``gateway/session_worker.py::_SCOPE``). */
export interface WorkerScopeParams {
  profile_id: string
  session_id: string
  execution_id: string
  generation: number
  pid: number
  birth: number
  secret: string
}
export interface WorkerPersistParams {
  profile_id: string
  session_id: string
  execution_id: string
  generation: number
  pid: number
  birth: number
  secret: string
  epoch: number
  sequence: number
  operation: string
  payload: Record<string, unknown>
}
/** The operation's durable receipt (``message_id`` for an append, delegation results, …). */
export type WorkerPersistResult = Record<string, unknown>
export interface GroupsAttachmentUploadParams {
  profile?: string | null
  room_id: string
  upload_id: string
  kind: string
  name: string
  mime: string
  data_base64: string
}
export interface RoomAttachment {
  attachment_id: string
  kind: string
  name: string
  size: number
  mime: string
  sha256: string
  state: string
  created_at: number
  idempotent: boolean
  event_id?: string | null
  [key: string]: unknown
}
export interface GroupsAttachmentDownloadParams {
  profile?: string | null
  room_id: string
  event_id: string
  attachment_id: string
}
export interface RoomAttachmentBytes {
  attachment_id: string
  kind: string
  name: string
  size: number
  mime: string
  sha256: string
  state: string
  created_at: number
  idempotent: boolean
  event_id?: string | null
  data_base64: string
  [key: string]: unknown
}
export interface GroupsDiscardParams {
  profile?: string | null
  room_id: string
  member_id: string
  task_id: string
  execution_generation: number
}
export interface GroupsDiscardResult {
  discarded?: boolean
  task: RoomTaskReceipt
}
export interface CanonicalCreateParams {
  profile?: string | null
  request_id?: string | null
  source?: 'cli' | 'tui' | 'gui' | 'acp' | 'tool' | 'oneshot'
  cwd?: string | null
  row_cwd?: string | null
  model?: string | null
  provider?: string | null
  base_url?: string | null
  api_key?: string | null
  toolsets?: string[] | null
  reasoning?: string | null
  max_turns?: number | string | null
  ignore_rules?: boolean
  yolo?: boolean
  safe_mode?: boolean
  ignore_user_config?: boolean
  skills?: string[] | null
  checkpoints?: boolean
  accept_hooks?: boolean
  pass_session_id?: boolean
  editor?: Record<string, unknown> | null
  title?: string | null
  hidden?: boolean
  follow_profile_config?: boolean | null
  service_tier?: string | null
  cwd_explicit?: boolean | null
  run_budget?: number | null
  verbose?: boolean
  client_env?: Record<string, string> | null
}
export interface CanonicalSnapshot {
  session_id: string
  stored_session_id: string
  messages: TranscriptMessage[]
  display_messages?: TranscriptMessage[] | null
  message_count: number
  running: boolean
  authority_epoch: number
  replay_epoch: string
  last_sequence: number
  subscription_id: string
  revision: number
  execution_generation: number
  pending: CanonicalPendingAdmission[]
  prompts: CanonicalPendingPrompt[]
  info: CanonicalSnapshotInfo
  pending_connection?: ConnectionRequestPayload | null
  todo_state?: TodoState | null
}
export interface CanonicalPendingAdmission {
  admission_id: string
  ref: CanonicalSessionRef
  sequence: number
  status: 'queued' | 'started' | 'unknown' | 'terminal'
  outcome: string | null
  authority_epoch: number
  execution_generation: number | null
  input_id: string
  text: string
  controls?: ('steer' | 'replace')[] | null
  steering?: boolean | null
}
export interface CanonicalPendingPrompt {
  kind: 'approval' | 'clarify'
  prompt_id: string
  execution_generation: number
  choices: string[]
  command?: string | null
  description?: string | null
  edit?: Record<string, unknown> | null
  question?: string | null
  multi_select?: boolean | null
  timeout_s?: number | null
}
export interface CanonicalSnapshotInfo {
  provider?: string | null
  tools?: Record<string, string[]> | null
  skills?: Record<string, string[]> | null
  mcp_servers?: McpServerStatus[] | null
  version?: string | null
  release_date?: string | null
  update_behind?: unknown | null
  update_command?: string | null
  branch?: string | null
  project?: ProjectRef | null
  system_prompt?: string | null
  context_length?: number | null
  enabled_toolsets?: string[] | null
  tool_availability?: Record<string, unknown> | null
  tool_availability_warnings?: string[] | null
  browser_backend_notice?: string | null
  unknown_toolsets?: string[] | null
  desktop_protocol: 'hermes-gateway-v1'
  source?: string | null
  model?: string | null
  lazy?: boolean | null
  profile_id?: string | null
  profile_name?: string | null
  cwd?: string | null
  edit_approval_policy?: 'ask' | 'workspace_session' | 'session' | null
  launch_request?: Record<string, unknown> | null
  reasoning_effort?: string | null
  reasoning_effort_wire?: string | null
  service_tier?: string | null
  fast?: boolean | null
  title?: string | null
  started_at?: number | null
  last_active_at?: number | null
  yolo?: boolean | null
  api_mode?: string | null
  tool_count?: number | null
  credential_hint?: string | null
  config_warning?: string | null
}
export interface CanonicalResumeParams {
  profile?: string | null
  session_id?: string
  title?: string | null
  latest?: 'cli' | 'tui' | null
  workspace?: string | null
  source?: string | null
  editor?: Record<string, unknown> | null
  api_key?: string | null
  defer_history?: boolean
  omit_messages?: boolean
  cols?: number | null
  display_projection?: boolean
}
export interface CanonicalListParams {
  profile?: string | null
  scope?: 'live' | 'stored'
  limit?: number
  title?: string | null
  include_hidden?: boolean
}
export interface CanonicalListResult {
  sessions: CanonicalSessionListRow[]
  scope: 'stored' | 'live'
}
export interface CanonicalSessionListRow {
  session_id: string
  id: string
  title: string
  source: string | null
  started_at: number | null
  message_count: number
  running: boolean
  model?: string | null
  resolved_id?: string | null
  root_title?: string | null
}
export interface CanonicalControlParams {
  profile?: string | null
  session_id: string
  execution_generation: number
}
export interface CanonicalSessionHandle {
  ref: CanonicalSessionRef
  instance_id: string
  authority_epoch: number
  revision: number
  execution_generation: number
  execution_state: 'idle' | 'running' | 'waiting' | 'unknown' | 'terminal'
}
export interface CanonicalCorrectionParams {
  profile?: string | null
  session_id: string
  execution_generation: number
  text: string
}
/** ``session.steer`` / ``session.redirect``: the correction verdict, or ``{voice_stopped: true}`` when the busy-time text was a bare stop phrase that ended the LOCAL voice chat. */
export type CanonicalCorrectionResult = CanonicalCorrectionAck | CanonicalVoiceStopped
export interface CanonicalCorrectionAck {
  status: 'queued' | 'redirected' | 'rejected'
  text: string
  execution_generation: number
  authority_epoch: number
  delivered?: false | null
}
/** A bare stop phrase typed while the session's voice chat is on: the chat ended, nothing was admitted (TUI-26). */
export interface CanonicalVoiceStopped {
  voice_stopped: true
}
export interface CanonicalEventsParams {
  profile?: string | null
  session_id: string
  last_sequence?: number
  last_seen?: number
  replay_epoch?: string | null
}
export interface CanonicalEventsResult {
  events: CanonicalReplayEvent[]
  latest_seq: number
  last_sequence: number
  epoch: string
  replay_epoch: string
  truncated: boolean
  snapshot_required: boolean
  count: number
}
export interface CanonicalReplayEvent {
  type: string
  session_id: string
  payload: Record<string, unknown>
  replay_epoch: string
  seq: number
  authority_epoch?: number | null
  execution_generation?: number | null
  admission_id?: string | null
}
export interface CanonicalSubmitParams {
  profile?: string | null
  session_id: string
  text: string
  submission_id?: string | null
  input_id?: string | null
  queued?: boolean
  attachments?: CanonicalAttachment[] | null
  finite?: boolean
  unattended?: boolean
  surface?: string | null
  voice_context?: string | null
  interrupted?: boolean
  voice_turn?: boolean
  display_kind?: 'hidden' | null
  title_preview?: string | null
  turn_author?: CanonicalTurnAuthor | null
  api_text?: string | null
  model_override?: CanonicalModelOverride | null
  clarify_batch?: boolean
}
export interface CanonicalAttachment {
  path: string
  mime: string
}
export interface CanonicalTurnAuthor {
  id?: string | null
  name?: string | null
  is_bot?: boolean
  origin?: string | null
}
export interface CanonicalModelOverride {
  model: string
  provider?: string | null
  reasoning?: string | null
}
/** ``prompt.submit``: the admission receipt, or ``{voice_stopped: true}``. */
export type CanonicalSubmitResult = AdmissionStatus | CanonicalVoiceStopped
export interface CanonicalApprovalParams {
  profile?: string | null
  session_id: string
  execution_generation: number
  prompt_id: string
  choice: string
}
export interface CanonicalSteerQueuedParams {
  profile?: string | null
  session_id: string
  admission_id: string
}
/** The edited prompt: admitted as a NEW admission (``submission_id``) at the FIFO tail. */
export interface CanonicalReplaceQueuedParams {
  profile?: string | null
  session_id: string
  admission_id: string
  submission_id: string
  text: string
  attachments?: CanonicalAttachment[] | null
  display_kind?: 'hidden' | null
  title_preview?: string | null
}
export interface CanonicalConfigGetResult {
  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<string, unknown> | null
  prompt?: string | null
  mtime?: number | null
  mcp_rev?: string | null
  key?: string | null
  scope?: string | null
}
/** Session controls (``busy`` / ``verbose`` / ``yolo`` / ``show_reasoning`` / ``service_tier``, which need ``session_id``) and the TUI's profile preferences (``gateway/session_tui_config.py``; ``session_id`` optional). ``model`` is recognised only to be refused with ``use_session_mutation_model``: a model pick is the revision-fenced ``session.mutate`` operation, never a config write. */
export interface CanonicalConfigSetParams {
  profile?: string | null
  session_id?: string | null
  key: string
  value?: unknown
  confirm_expensive_model?: boolean | null
  scope?: 'session' | 'global' | null
}
export interface CanonicalProfilesParams {
  profile?: string | null
  include_sessions?: boolean
}
export interface CanonicalProfilesResult {
  profiles: CanonicalProfileRow[]
  bot_mode_protocol?: boolean
  install_id?: string
}
export interface CanonicalProfileRow {
  name: string
  path: string
  is_default?: boolean
  model?: string | null
  provider?: string | null
  description?: string
  display_name?: string
  skill_count?: number
  previous_names?: string[]
  last_session?: ProfileCanonicalSession | null
  worker_session?: ProfileWorkerSession | null
  canonical_session?: ProfileCanonicalSession | null
  ui_meta_revisions?: Record<string, number>
  ui_meta?: Record<string, unknown> | null
  has_avatar?: boolean
}
export interface CanonicalAttachedImageResult {
  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
  mime: string
}
export interface CanonicalRoomAttemptParams {
  profile?: string | null
  room_id: string
  member_id: string
  task_id: string
  execution_generation: number
}
export interface CanonicalRoomCreateParams {
  profile?: string | null
  room_id: string
  name: string
  members: RoomMemberInput[]
}
export interface CanonicalRoomApproveParams {
  profile?: string | null
  room_id: string
  member_id: string
  task_id: string
  execution_generation: number
  choice: 'once' | 'deny'
  request_id: string
}
export interface CanonicalBotDeliverParams {
  profile?: string | null
  message: string
  id: string
  session_id?: string | null
  author?: Record<string, unknown> | null
  notification_category?: string | null
}
/** A delivery's receipt. It names its admission, unless ``refused``: the FIFO refused the delivery before anything was committed (``gateway/session_bot.py``), a terminal ``failed`` receipt with no admission that the relay settles as the sender's answer. */
export interface CanonicalBotDeliverResult {
  status: string
  delivery_id: string
  profile_home: string
  session_id: string
  admission_id?: string | null
  refused?: true | null
  message: string
  reply?: string | null
  retry_admission_id?: string | null
  error?: string | null
  reason?: string | null
}
/** ``answers`` rides only on a reconnect replay (locks the server already accepted; null = skipped). */
export interface ClarifyRequestParams {
  session_id: string
  questions: ClarifyQuestion[]
  answers?: Record<string, string | null> | null
}
export interface ClarifyQuestion {
  qid: string
  question: string
  choices?: string[] | null
  multi_select?: boolean
}
/** ``{answers}`` for the whole set (early locks go through the ``clarify.lock`` RPC); a response without ``answers`` is cancel-all. ``outcome`` (optional): how the viewer's own panel ended, as main's classic CLI reports it (``timed_out`` keeps the answers locked before its deadline). */
export interface ClarifyResult {
  answers?: Record<string, string | null> | null
  outcome?: 'submitted' | 'timed_out' | 'cancelled' | null
}
/** ``card`` is the beat's data (``agent/onboarding_flow.py::BEATS``): name, theme, connectors and plugins have their own shape; layout, tour and build carry ``options``. ``tool_call_id`` is the setup_beat call the card belongs to: only that transcript row draws it. */
export interface SetupBeatRequestParams {
  session_id: string
  beat: SetupBeat
  question?: string | null
  tool_call_id?: string | null
  card: SetupNameCard | SetupThemeCard | SetupOptionsCard | SetupConnectorsCard | SetupPluginsCard
}
export type SetupBeat = 'name' | 'theme' | 'layout' | 'connectors' | 'plugins' | 'tour' | 'build'
export interface SetupNameCard {
  suggested?: string | null
}
export interface SetupThemeCard {
  picker: string
}
export interface SetupOptionsCard {
  options: SetupOption[]
}
export interface SetupOption {
  id: string
  label: string
}
export interface SetupConnectorsCard {
  suggested: string[]
}
export interface SetupPluginsCard {
  plugins: string[]
}
/** ``answer`` holds the shown beat's picks; ids must be one of the card's options (the backend rejects any other answer). ``said`` is composer text typed while the name card waited: the name. ``wrote_instead``: the user sent a message instead of answering; the backend ends the turn and the client sends that message as the next one. A response with none of these, or none within 300 s, closes the card unanswered. */
export interface SetupBeatResult {
  answer?: SetupNameAnswer | SetupThemeAnswer | SetupLayoutAnswer | SetupConnectorsAnswer | SetupPluginsAnswer | SetupTourAnswer | SetupBuildAnswer | null
  said?: string | null
  wrote_instead?: boolean
}
export interface SetupNameAnswer {
  name: string
}
export interface SetupThemeAnswer {
  accent?: string | null
  mode?: string | null
}
export interface SetupLayoutAnswer {
  layout: string
}
export interface SetupConnectorsAnswer {
  connected: string[]
  newly_connected?: string[]
}
export interface SetupPluginsAnswer {
  installed: string[]
  label?: string | null
}
export interface SetupTourAnswer {
  tour: string
  label?: string | null
}
export interface SetupBuildAnswer {
  build: string
  label?: string | 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<string, unknown> | 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
  allow_shortcut?: boolean | 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
  preset?: TourPreset | null
}
export interface TourStep {
  selector?: string | null
  title?: string | null
  text?: string | null
  side?: string | null
  [key: string]: unknown
}
/** Which built-in tour ``start`` without steps runs. */
export type TourPreset = 'quick' | 'full'
/** ``tools/set_theme_tool.py`` values; accent is a swatch id, ``theme`` or ``#rrggbb``. */
export interface ThemeApplyRequestParams {
  session_id: string
  accent?: string | null
  mode?: ThemeMode | null
  layout?: string | null
}
export type ThemeMode = 'light' | 'dark' | 'system'
export interface ThemePickRequestParams {
  session_id: string
  picker: ThemePicker
}
export type ThemePicker = 'accent' | 'layout'
/** ``picked`` once the user chose (already applied); ``cancelled`` when the card was dismissed. A response with neither is a cancel. */
export interface ThemePickResult {
  picked?: ThemeValues | null
  said?: string | null
  cancelled?: boolean | null
}
/** What the renderer applied. ``accent`` is a swatch id, ``custom:#rrggbb``, or null for the theme's own. */
export interface ThemeValues {
  accent?: string | null
  mode?: ThemeMode | null
  layout?: string | null
}
export interface DisplayInstallSudoParams {
  session_id: string
  profile_key: string
}
/** ``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
  seq: number
  deadline_at: number
  settled: boolean
  settled_at?: number | null
  settled_by?: ConnectionSettleReason | null
  targets: ConnectionOperationTarget[]
  owner: SessionOwner | AccountOwner
  target?: string | null
  from?: ConnectionTargetState | null
  to?: ConnectionTargetState | null
  actor?: ConnectionActor | null
  detail?: string | null
}
/** ``tools/connectors/contract.py::Actor``. */
export type ConnectionActor = 'user' | 'backend_watcher' | 'clock'
export interface RequestCancelPayload {
  id: string
  method: string
  reason: string
}
export interface DisplayStatusPayload {
  profile: string
  supported: boolean
  installed: boolean
  missing: string[]
  running: boolean
  pid?: number | null
  display?: string | null
  socket?: string | null
  geometry: string
  install_command?: string | null
  browser?: string | null
  blocker?: string | null
  memory_available_mb?: number | null
  memory_limit_mb?: number | null
  placement?: string
  image_switch?: DisplayImageSwitch | null
  lease: DisplayLease
  profile_key: string
}
export interface DisplayLeasePayload {
  profile_key: string
  lease: DisplayLease
}
export interface DisplayInstallLogPayload {
  profile_key: string
  line: string
}
export interface DisplayInstallDonePayload {
  profile_key: string
  code: number
  status: DisplayStatus
}
/** ``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
  session_authority?: boolean | null
}
/** ``agent/onboarding_record.py::_transition``: the run ``run_id`` stopped being in progress. ``stored_session_id`` is its chat at the compression tip. ``done``: the first-task card was answered; ``skipped``: Skip setup; ``replaced``: a rerun opened a new run; ``deleted``: its chat was deleted. */
export interface OnboardingEndedPayload {
  run_id: string
  stored_session_id: string
  outcome: OnboardingOutcome
}
export type OnboardingOutcome = 'done' | 'skipped' | 'replaced' | 'deleted'
/** ``hermes_cli/free_tier_bootstrap.py::SetupRecord.as_payload``. */
export interface SetupReadyPayload {
  provider_configured: boolean
  inference_provider: string
  free_tier_account: boolean
  free_tier_route: boolean
  has_identity: boolean
  other_providers: boolean
  error?: string
  error_code?: string | null
  retryable?: boolean | null
  retry_after?: number | null
  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
}
/** ``message.start``. Empty from the TUI gateway's emitters and for an ordinary admission; ``gateway/session_authority._stamp_claim`` adds an automation admission's async-result card (``session_automation.admission_display``: a background-process completion) and its model text, so a viewer that did not submit the turn paints the same header the submitter would. */
export interface MessageStartPayload {
  display_kind?: string | null
  display_text?: string | null
  notification_category?: string | null
  text?: string | null
}
/** ``message.delta``. A session-authority local-viewer turn also publishes ``text: null``: the reply segment boundary (the agent's ``stream_delta_callback(None)``, before tool lines) that closes the classic CLI's reply box. Every other viewer ignores an empty chunk. */
export interface MessageDeltaPayload {
  text: string | null
  rendered?: string | null
  verbose?: boolean | null
}
/** ``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
  response_reused?: boolean | null
  response_transformed?: 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
  persisted_turn?: PersistedTurn | 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, + ``resets_at`` epoch seconds when the provider named when its limit lifts, + ``usage_limit`` on a usage-window plan's limit). */
export interface ErrorSurface {
  layer: string
  code: string
  retryable: boolean
  provider?: string | null
  model?: string | null
  resets_at?: number | null
  usage_limit?: UsageLimit | null
  [key: string]: unknown
}
/** ``agent/plan_limits.py::LimitHit`` — a usage-window plan's limit: what ran out, when it resets, and the one-click ways on (switch to a recommended model, use / add credits). */
export interface UsageLimit {
  gauge_id: string
  scope: string
  limit_name: string
  resets_at_ms?: number | null
  message: string
  suggestions?: UsageLimitSuggestion[]
  credits?: UsageLimitCredits | null
  current_model?: string
}
/** ``agent/plan_limits.py::ModelSuggestion`` — a recommended model that still works past the limit. */
export interface UsageLimitSuggestion {
  model: string
  label: string
  note: string
  provider?: string
}
/** ``agent/plan_limits.py::CreditsOption`` — ``use_credits`` (turn on Keep going), ``add_credits``, or ``add_credits_and_keep_going`` (both: Keep going is off and there is no balance). */
export interface UsageLimitCredits {
  action: string
}
/** Committed SQLite row addresses for the agent's current-turn suffix. Missing ids are unproven, never negative acknowledgements. ``complete`` permits retiring the whole local turn only when the original turn boundary, every row and final body are still accounted for; compaction, redirects and partial writes conservatively leave it false. Row ids are scoped to the owning profile's store, as in ``SessionMessage.row_id``. */
export interface PersistedTurn {
  row_ids: number[]
  complete: boolean
  user_row_id?: number | null
  final_assistant_row_id?: number | null
  user_row_ids?: number[] | null
  submission_id?: string | null
}
/** ``server._status_update`` and the direct emitters (goal / loop / heartbeat / process). */
export interface StatusUpdatePayload {
  kind: string
  text: string
}
/** ``usage``: the status-bar view (``server._get_usage``), sent by the embedded backend's ticker (``server._start_usage_ticker``) and by a canonical local viewer's gateway after every API call and at turn end (``gateway/session_usage.py::usage_frame``). Read this. Deprecated: the top-level session-cumulative counters (``usage_stats``, the ``session.stats`` dict) that the gateway frame also carries. They are kept for existing readers; new readers use ``usage``, or ``session.stats`` for the raw counters. The embedded ticker never sends them. */
export interface SessionUsagePayload {
  usage?: Usage | null
  input_tokens?: number | null
  output_tokens?: number | null
  cache_read_tokens?: number | null
  cache_write_tokens?: number | null
  prompt_tokens?: number | null
  completion_tokens?: number | null
  total_tokens?: number | null
  reasoning_tokens?: number | null
  api_calls?: number | null
  last_prompt_tokens?: number | null
  context_tokens?: number | null
  context_length?: number | null
  config_context_length?: number | null
  context_source?: string | null
  compression_count?: number | null
  avg_latency_s?: number | null
  tokens_per_s?: number | null
  last_turn_tokens?: number | null
  rate_limit?: Record<string, unknown> | null
  active_subagents?: number | null
  model?: string | null
  provider?: string | null
  fallback_model?: string | null
  plan_gauge?: PlanGauge | null
}
/** ``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
}
/** A session-authority local-viewer turn: one line the agent printed through ``_print_fn`` (subagent completion, compaction, errors, budget notices), which main's classic CLI rendered through ``_agent_status_print``. */
export interface AgentPrintPayload {
  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<string, unknown> | null
  args_text?: string | null
  preview?: string | null
  labels?: ToolLabel[] | null
}
/** ``tool_progress._on_tool_complete``; ``todos``/``revision`` merged in for the todo tools. */
export interface ToolCompletePayload {
  tool_id: string
  name: string
  args?: Record<string, unknown> | null
  duration_s?: number | null
  result?: unknown
  summary?: string | null
  result_text?: string | null
  inline_diff?: string | null
  todos?: unknown[] | null
  revision?: number | null
  labels?: ToolLabel[] | 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
}
/** ``agent.tool_progress_relay.tool_progress_payload`` — an MCP server's ``notifications/progress`` for a running call, throttled to one per 500 ms per call. */
export interface ToolProgressPayload {
  tool_id: string
  name: string
  progress: number
  total?: number | null
  percent?: number | null
  message?: string | null
}
/** ``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. ``detail``: the full text behind a short ``text`` (the low-disk auto-prune question): Desktop shows it in the toast's expandable body, the Ink TUI prints it into the transcript. */
export interface NotificationShowPayload {
  text: string
  level: string
  kind: string
  ttl_ms?: number | null
  key?: string | null
  id?: string | null
  detail?: 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
}
/** ``session_lifecycle._announce_cancelled_gateway_approvals`` (broadcast). One frame for every pending approval dropped by an interrupt / reap / teardown (#106678) — the deny-resolve is silent without it, so a reconnecting client's prompt looks lost rather than cancelled. ``cancelled_count`` is the number of dropped entries; ``request_ids`` omits empty/missing ids, so the two can disagree when an entry has no request_id. */
export interface ApprovalCancelledPayload {
  session_id: string
  stored_session_id: string
  reason: string
  cancelled_count: number
  request_ids: 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/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<string, unknown>
  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`` voice.record ``on_partial`` — live STT text so far (``stt.streaming``). */
export interface VoicePartialPayload {
  text: 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<string, unknown>
export type ConnectorErrorReason = 'INVALID_PARAMS' | 'NOT_OWNER' | 'UNSUPPORTED_RUNTIME' | 'CONNECTOR_REQUEST_FAILED' | 'INVALID_CONNECTOR_RESPONSE' | 'UNKNOWN_TARGET' | 'LINK_STILL_VALID' | 'REISSUE_REFUSED' | 'UNKNOWN_OPERATION' | 'INVALID_ANSWER' | 'NEEDS_NOUS_AUTH' | 'CONNECTOR_NOT_FOUND' | 'TOOLS_UNAVAILABLE' | 'CONNECTORS_UNAVAILABLE' | 'CATALOG_UNAVAILABLE' | 'ACCOUNTS_UNAVAILABLE' | 'CONNECTION_NOT_FOUND' | 'POLICY_UNAVAILABLE' | 'POLICY_CONFLICT' | 'FORBIDDEN_SCOPE' | 'ORG_REQUIRED' | 'ORG_ACCESS_DENIED' | 'INVALID_POLICY' | 'ALIAS_TAKEN'

// ── 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 }
  /** Window plans: turn 'Keep going on credits' on/off (billing:manage). */
  'billing.keep_going_on_credits': { params: BillingKeepGoingOnCreditsParams; result: BillingMutationResult }
  /** 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, or switch Browser Use mode (``use``, applies to new sessions); ``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 <argv>`` non-interactively and capture its output; ``blocked`` explains a refusal. */
  'cli.exec': { params: CliExecParams; result: CliExecResult }
  /** What the calling client handles, sent once per connection (after gateway.ready); returns the server→client request methods this backend may send. */
  'client.capabilities': { params: ClientCapabilitiesParams; result: ClientCapabilitiesResult }
  /** 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 }
  /** The scoped member's hosted connector accounts, optionally filtered by connector slug. */
  'connectors.accounts': { params: ConnectorAccountsParams; result: ConnectorAccountsResult }
  /** Remove one hosted connector account owned by the scoped member. */
  'connectors.accounts.remove': { params: ConnectorAccountsRemoveParams; result: ConnectorAccountsRemoveResult }
  /** Name or rename one hosted connector account owned by the scoped member. */
  'connectors.accounts.rename': { params: ConnectorAccountsRenameParams; result: ConnectorAccountRow }
  /** The hosted connector catalog available to the scoped member. */
  'connectors.catalog': { params: ProfileParams; result: ConnectorsCatalogResult }
  /** Start or re-initiate authorization for named connectors on a session or account operation. */
  'connectors.connect': { params: ConnectorsConnectParams; result: ConnectorsConnectResult }
  /** Connector catalog + connection state for one session or profile account owner. */
  'connectors.list': { params: ConnectorsListParams; result: ConnectorsListResult }
  /** The current snapshot of one open session or account operation. */
  'connectors.operation.status': { params: ConnectionOperationParams; result: ConnectionOperationStatus }
  /** The browser leg came back (hermes://connections/done): read the accounts now, not at the next tick. */
  'connectors.operation.wake': { params: ConnectionOperationParams; result: ConnectionWakeResult }
  /** Policy layers for the scoped member, from organization to member scope. */
  'connectors.policy.get': { params: ProfileParams; result: ConnectorPolicyGetResult }
  /** Apply one scoped member connector or tool-list policy change. */
  'connectors.policy.set': { params: ConnectorPolicySetParams; result: ConnectorPolicySetResult }
  /** The scoped profile's cached or current tool list for one connector. */
  'connectors.tools': { params: ConnectorToolsParams; result: ConnectorToolsResult }
  /** 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 }
  /** Run the distro package install on the gateway host; progress streams as display.install.log/.done. */
  'display.install': { params: ProfileParams; result: DisplayInstallResult }
  /** Take over: the human named by a viewer id this connection minted controls the screen. */
  'display.lease.acquire': { params: DisplayLeaseAcquireParams; result: DisplayLeaseResult }
  /** Hand back. Without a viewer id the release is refused while a human holds unless force. */
  'display.lease.release': { params: DisplayLeaseReleaseParams; result: DisplayLeaseResult }
  /** Mint a single-use ticket for /api/display/ws and the server-minted viewer id for this connection. */
  'display.observe': { params: DisplayObserveParams; result: DisplayObserveResult }
  /** Start this profile's Xvnc + Xfce (idempotent); blocks until the display is published. */
  'display.start': { params: ProfileParams; result: DisplayStatus }
  /** Runtime + lease snapshot for this profile's screen. */
  'display.status': { params: ProfileParams; result: DisplayStatus }
  /** Stop the screen. Refused (5300, code viewer_mismatch) while a human holds unless force. */
  'display.stop': { params: DisplayStopParams; result: DisplayStopResult }
  /** Decide the pending default sandbox image switch for this profile; refused when none is pending. */
  'display.switchSandboxImage': { params: DisplaySwitchSandboxImageParams; result: DisplaySwitchSandboxImageResult }
  /** One JPEG grab of the bot's screen; read-only, never changes the lease. */
  'display.thumbnail': { params: ProfileParams; result: DisplayThumbnailResult }
  /** 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 }
  /** Report a browser window outcome for the matching pending attempt; mint remains authoritative. */
  'free_tier.challenge_result': { params: FreeTierChallengeResultParams; result: FreeTierChallengeResult }
  /** Claim the due sign-in offer; true for exactly one caller each time an offer comes due. */
  'free_tier.claim_nudge': { params: FreeTierClaimNudgeParams; result: FreeTierClaimNudgeResult }
  /** 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 }
  /** Pack + overlay messages for one language and surface; the renderer merges them over its bundled catalog. */
  'i18n.catalog': { params: I18nCatalogParams; result: I18nCatalogResult }
  /** Every language some layer supplies (bundled ∪ user overlay ∪ plugin packs), en first. */
  'i18n.languages': { params: ProfileParams; result: I18nLanguagesResult }
  /** 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 }
  /** Facts about the machine running this backend and its OS account, for the desktop first run. */
  'machine.facts': { params: Params; result: MachineFactsResult }
  /** 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 }
  /** Write onboarding.run in the root profile's config.yaml; answers the new state. */
  'onboarding.set_run': { params: OnboardingSetRunParams; result: OnboardingRunStateResult }
  /** Skip setup: end the session's onboarding run and close the card that waits. */
  'onboarding.skip': { params: OnboardingSkipParams; result: OnboardingSkipResult }
  /** Open the onboarding chat in the default profile: create it, write its run record and play the opening. */
  'onboarding.start': { params: OnboardingStartParams; result: OnboardingStartResult }
  /** Whether desktop first-run onboarding is due, and the chat in progress; reads the root profile's config. */
  'onboarding.state': { params: OnboardingStateParams; result: OnboardingRunStateResult }
  /** 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 <img>). */
  '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 }
  /** One curated plugin-catalog entry by name, from the backend's live catalog (cached, with the in-tree fallback and kill list); backs hermes://plugin/install?catalog= deep links. */
  'plugins.catalog.lookup': { params: PluginCatalogLookupParams; result: PluginCatalogLookupResult }
  /** 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, re-pin a catalog install, or remove a user 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 }
  /** ``/stop``: on the shared owner, kill the background processes ``session_id`` owns (required); a standalone sidecar kills every process it holds. Answers 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 }
  /** 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 }
  /** Set/clear archived (soft-hide, messages kept) on a session + lineage; Desktop PATCH parity. */
  'session.archive': { params: SessionArchiveParams; result: SessionArchiveResult }
  /** Fork a live session into a new stored child that shares the parent's history so far. */
  'session.branch': { params: SessionBranchParams; result: SessionBranchResult }
  /** Whole-session branch of a stored parent: the owning backend reads and copies the transcript, which never crosses the wire (a separate method so an older gateway fails loudly, not with an empty branch). */
  'session.branch_stored': { params: SessionBranchStoredParams; result: SessionBranchStoredResult }
  /** session.branch of the whole history without echoing the copied transcript back. */
  'session.branch_whole': { params: SessionBranchWholeParams; result: SessionBranchWholeResult }
  /** 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 }
  /** Record one finished Desktop day (mode use + button presses); recorded=false keeps it for a retry. */
  'shared_metrics.desktop_daily': { params: SharedMetricsDesktopDailyParams; result: SharedMetricsDesktopDailyResult }
  /** Count one Desktop dislike signal (fire-and-forget; capped per signal per day; a no-op unless on). */
  'shared_metrics.desktop_dislike': { params: SharedMetricsDesktopDislikeParams; result: OkResult }
  /** Count one Desktop area used today (fire-and-forget; once per area per UTC day; a no-op unless on). */
  'shared_metrics.desktop_feature_use': { params: SharedMetricsDesktopFeatureUseParams; result: OkResult }
  /** Count one Desktop friction event (fire-and-forget; capped per day; a no-op unless on). */
  'shared_metrics.desktop_friction': { params: SharedMetricsDesktopFrictionParams; result: OkResult }
  /** Count one Desktop first-run step transition (fire-and-forget; once per step+event; a no-op unless on). */
  'shared_metrics.desktop_onboarding': { params: SharedMetricsDesktopOnboardingParams; result: OkResult }
  /** Write both shared-metrics opt-ins at once (send requires collection) and reconcile consent windows. */
  'shared_metrics.set': { params: SharedMetricsSetParams; result: SharedMetricsConsentResult }
  /** Count one user-typed slash command (fire-and-forget; a no-op unless shared metrics are on). */
  'shared_metrics.slash_command': { params: SharedMetricsSlashCommandParams; result: SharedMetricsSlashCommandResult }
  /** Record one client launch-to-ready latency (fire-and-forget; a no-op unless shared metrics are on). */
  'shared_metrics.startup_latency': { params: SharedMetricsStartupLatencyParams; result: SharedMetricsStartupLatencyResult }
  /** Pure read of the focused profile's shared-metrics opt-ins (collection, upload, answered). */
  'shared_metrics.status': { params: ProfileParams; result: SharedMetricsConsentResult }
  /** Count one Desktop packaged self-update outcome (fire-and-forget; a no-op unless shared metrics are on). */
  'shared_metrics.update_run': { params: SharedMetricsUpdateRunParams; result: SharedMetricsUpdateRunResult }
  /** 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.keep_going_on_credits',
  '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',
  'client.capabilities',
  'clipboard.paste',
  'command.dispatch',
  'command.resolve',
  'commands.catalog',
  'complete.path',
  'complete.slash',
  'config.get',
  'config.set',
  'config.show',
  'connection.respond',
  'connectors.accounts',
  'connectors.accounts.remove',
  'connectors.accounts.rename',
  'connectors.catalog',
  'connectors.connect',
  'connectors.list',
  'connectors.operation.status',
  'connectors.operation.wake',
  'connectors.policy.get',
  'connectors.policy.set',
  'connectors.tools',
  'cron.manage',
  'delegation.pause',
  'delegation.status',
  'diagnostics.share_nous',
  'display.install',
  'display.lease.acquire',
  'display.lease.release',
  'display.observe',
  'display.start',
  'display.status',
  'display.stop',
  'display.switchSandboxImage',
  'display.thumbnail',
  'file.attach',
  'free_tier.ack_notice',
  'free_tier.challenge_result',
  'free_tier.claim_nudge',
  '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',
  'i18n.catalog',
  'i18n.languages',
  'image.attach',
  'image.attach_bytes',
  'image.detach',
  'image.generate',
  'input.detect_drop',
  'insights.get',
  'learning.delete',
  'learning.detail',
  'learning.edit',
  'learning.frames',
  'llm.oneshot',
  'machine.facts',
  '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',
  'onboarding.set_run',
  'onboarding.skip',
  'onboarding.start',
  'onboarding.state',
  '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.catalog.lookup',
  'plugins.list',
  'plugins.manage',
  'preview.restart',
  'process.kill',
  'process.list',
  'process.stop',
  'profiles.configure',
  'profiles.create',
  'profiles.describe',
  'profiles.get_asset',
  'profiles.list',
  '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.archive',
  'session.branch',
  'session.branch_stored',
  'session.branch_whole',
  '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',
  'shared_metrics.desktop_daily',
  'shared_metrics.desktop_dislike',
  'shared_metrics.desktop_feature_use',
  'shared_metrics.desktop_friction',
  'shared_metrics.desktop_onboarding',
  'shared_metrics.set',
  'shared_metrics.slash_command',
  'shared_metrics.startup_latency',
  'shared_metrics.status',
  'shared_metrics.update_run',
  '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[]

// ── Canonical (hermes-gateway-v1) methods only the session authority serves ──
export interface CanonicalRpcMethods {
  /** Forward one A2A input into the conversation its identity tuple names. */
  'a2a.forward': { params: A2aForwardParams; result: A2aForwardResult }
  'approval.respond': { params: CanonicalApprovalParams; result: PromptResponseResult }
  'bot_relay.deliver': { params: CanonicalBotDeliverParams; result: CanonicalBotDeliverResult }
  'bot_relay.settle': { params: CanonicalBotDeliverParams; result: CanonicalBotDeliverResult }
  /** Lock one answer of the owner's batch clarify request (editable until every question is locked); only a viewer attached to that session with session:respond may lock. */
  'clarify.lock': { params: ClarifyLockParams; result: ClarifyLockResult }
  /** Generation-fenced answer to a pending clarify prompt (empty answer = skipped). */
  'clarify.respond': { params: ClarifyRespondParams; result: PromptResponseResult }
  /** Fire-only: a recognized command the classic CLI or the TUI runs itself; the gateway fires `pre_command` for it in the session's profile after replying (`queued` false: not fired). */
  'command.observe': { params: CommandObserveParams; result: CommandObserveResult }
  'config.get': { params: ConfigGetParams; result: CanonicalConfigGetResult }
  'config.set': { params: CanonicalConfigSetParams; result: ConfigSetResult }
  /** Cancel a queued cron admission or latch cancellation on a started one. */
  'cron.cancel': { params: CronAdmissionParams; result: CronCancelResult }
  /** Re-observe a firing after a scheduler restart (same request identity). */
  'cron.recover': { params: CronRunParams; result: CronStatusResult }
  /** Status and, once terminal, the result of one cron admission. */
  'cron.status': { params: CronAdmissionParams; result: CronStatusResult }
  /** Admit one cron firing into the owning profile's durable FIFO. */
  'cron.submit': { params: CronRunParams; result: CronSubmitResult }
  'groups.approve': { params: CanonicalRoomApproveParams; result: GroupsApproveResult }
  /** Read one committed attachment for a live room viewer. */
  'groups.attachment.download': { params: GroupsAttachmentDownloadParams; result: RoomAttachmentBytes }
  /** Store one attachment for a later groups.send manifest (idempotent per upload_id). */
  'groups.attachment.upload': { params: GroupsAttachmentUploadParams; result: RoomAttachment }
  'groups.create': { params: CanonicalRoomCreateParams; result: GroupsCreateResult }
  /** Discard one indeterminate room task after explicit user confirmation. */
  'groups.discard': { params: GroupsDiscardParams; result: GroupsDiscardResult }
  'groups.retry': { params: CanonicalRoomAttemptParams; result: GroupsRetryResult }
  'image.attach_bytes': { params: ImageAttachBytesParams; result: CanonicalAttachedImageResult }
  /** Native-owner only: admit the dispatcher's current claim on a kanban task. */
  'kanban.run': { params: KanbanRunParams; result: KanbanRunResult }
  'profiles.list': { params: CanonicalProfilesParams; result: CanonicalProfilesResult }
  /** Retire a still-queued admission; a started one is unaffected. */
  'prompt.cancel': { params: PromptCancelParams; result: AdmissionStatus }
  /** Current receipt of one admission the caller submitted (or controls). */
  'prompt.receipt': { params: PromptReceiptParams; result: PromptReceiptResult }
  /** Cancel a still-queued admission and admit the edited prompt as a new admission at the back of the FIFO, in one write bound to the replaced admission. Refusals: admission_started, admission_conflict (the submission_id replaced another admission), queue_full, unsupported_control, not_found. */
  'prompt.replace_queued': { params: CanonicalReplaceQueuedParams; result: AdmissionStatus }
  /** Acknowledge a turn lost across an owner restart; the FIFO behind it resumes. Never requeues the lost input. */
  'prompt.resolve_unknown': { params: PromptResolveUnknownParams; result: AdmissionStatus }
  /** Hand a still-queued admission's text to the running turn's agent as a steer. The admission reads 'started' with that turn (pending snapshots mark it 'steering') and never runs on its own; it settles terminal 'steered' when the turn completes with its text, else 'interrupted' (its completion frame says 'cancelled', as an interrupted turn's does); a text the turn never consumed goes back to its queue place. Refusals: admission_started, session_idle, steer_unavailable (no agent to take it: the admission stays queued), unsupported_control, not_found. */
  'prompt.steer_queued': { params: CanonicalSteerQueuedParams; result: AdmissionStatus }
  'prompt.submit': { params: CanonicalSubmitParams; result: CanonicalSubmitResult }
  /** The classic CLI's /diff session: everything changed since the session's earliest retained checkpoint, as data for its terminal renderer. */
  'rollback.session_diff': { params: RollbackSessionDiffParams; result: RollbackSessionDiffResult }
  /** Owner identity and the canonical capabilities a client may rely on. */
  'runtime.describe': { params: RuntimeDescribeParams; result: RuntimeDescribeResult }
  /** The classic CLI's /goal, /subgoal, /loop, /heartbeat manager calls (state writes, the goal judge, quality gates), run by the owner on the session's row. */
  'session.automation': { params: SessionAutomationParams; result: SessionAutomationResult }
  'session.create': { params: CanonicalCreateParams; result: CanonicalSnapshot }
  /** Drop this connection's subscription; a stale subscription id answers detached=false. end_reason (snake_case): the viewer is closing the conversation; the last viewer leaving an idle local session ends its row with that reason. */
  'session.detach': { params: SessionDetachParams; result: SessionDetachResult }
  'session.events.since': { params: CanonicalEventsParams; result: CanonicalEventsResult }
  /** The /save transcript rendered for the client to write (the gateway writes nothing). */
  'session.export': { params: SessionExportParams; result: SessionExportResult }
  /** Frozen launch policy projection of one local session. */
  'session.info': { params: CanonicalSessionInfoParams; result: CanonicalSessionInfo }
  'session.interrupt': { params: CanonicalControlParams; result: CanonicalSessionHandle }
  'session.list': { params: CanonicalListParams; result: CanonicalListResult }
  /** Revision-fenced, retry-idempotent session edit (rename, archive, sidebar, branch, delete, rewind, reset, model, reasoning, workspace, edit_policy, compress, import). */
  'session.mutate': { params: SessionMutateParams; result: SessionMutateResult }
  /** Local operator only: the owner deletes the ended sessions `hermes sessions prune` selected, skipping busy sessions and retained reset owners. */
  'session.prune': { params: SessionPruneParams; result: SessionPruneResult }
  'session.redirect': { params: CanonicalCorrectionParams; result: CanonicalCorrectionResult }
  'session.resume': { params: CanonicalResumeParams; result: CanonicalSnapshot }
  /** The session.usage dict on demand: what main's classic CLI read off its agent. */
  'session.stats': { params: SessionStatsParams; result: SessionStats }
  'session.steer': { params: CanonicalCorrectionParams; result: CanonicalCorrectionResult }
  /** Ink ``!cmd`` / ``{!cmd}`` on the shared owner: one safe command for a local session, in its frozen launch cwd (``gateway/session_shell.py``). */
  'shell.exec': { params: CanonicalShellExecParams; result: ShellExecResult }
  /** Adopt a registered execution after verifying the live producer claim. */
  'worker.adopt': { params: WorkerScopeParams; result: WorkerExecution }
  /** Sequence-fenced typed persistence write from an adopted worker. */
  'worker.persist': { params: WorkerPersistParams; result: WorkerPersistResult }
  /** Register a compute worker execution on an idle session. */
  'worker.register': { params: WorkerRegisterParams; result: WorkerExecution }
}
export type CanonicalRpcMethod = keyof CanonicalRpcMethods
export const CANONICAL_RPC_METHODS = [
  'a2a.forward',
  'approval.respond',
  'bot_relay.deliver',
  'bot_relay.settle',
  'clarify.lock',
  'clarify.respond',
  'command.observe',
  'config.get',
  'config.set',
  'cron.cancel',
  'cron.recover',
  'cron.status',
  'cron.submit',
  'groups.approve',
  'groups.attachment.download',
  'groups.attachment.upload',
  'groups.create',
  'groups.discard',
  'groups.retry',
  'image.attach_bytes',
  'kanban.run',
  'profiles.list',
  'prompt.cancel',
  'prompt.receipt',
  'prompt.replace_queued',
  'prompt.resolve_unknown',
  'prompt.steer_queued',
  'prompt.submit',
  'rollback.session_diff',
  'runtime.describe',
  'session.automation',
  'session.create',
  'session.detach',
  'session.events.since',
  'session.export',
  'session.info',
  'session.interrupt',
  'session.list',
  'session.mutate',
  'session.prune',
  'session.redirect',
  'session.resume',
  'session.stats',
  'session.steer',
  'shell.exec',
  'worker.adopt',
  'worker.persist',
  'worker.register'
] as const satisfies readonly CanonicalRpcMethod[]

// ── 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 1-5 questions. */
  clarify: { params: ClarifyRequestParams; result: ClarifyResult }
  /** Masked sudo password for the Bot Screen package install; app-level (empty session). */
  'display.install.sudo': { params: DisplayInstallSudoParams; result: ValueResult }
  /** 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 }
  /** The onboarding chat's card for one beat; blocks setup_beat until answered (300 s). */
  setup_beat: { params: SetupBeatRequestParams; result: SetupBeatResult }
  /** 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 }
  /** Apply set_theme values in the window showing the session (JSON text answer). */
  'theme.apply': { params: ThemeApplyRequestParams; result: ValueResult }
  /** Show an accent or layout picker card in the chat and wait for the pick. */
  'theme.pick': { params: ThemePickRequestParams; result: ThemePickResult }
  /** 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',
  'display.install.sudo',
  'preview.act',
  'preview.read',
  'secret',
  'setup_beat',
  'sudo',
  'terminal.read',
  'theme.apply',
  'theme.pick',
  'tour',
  'vault.code',
  'vault.save_login',
  'vault.unlock_prompt',
  'window.read'
] as const satisfies readonly ServerRequestMethod[]

// ── Notifications (`event` frames) ──
export interface BackendGatewayEventMap {
  /** A status line the agent printed during a local viewer's turn. */
  'agent.print': AgentPrintPayload
  /** Output chunk from an agent-owned background process. */
  'agent.terminal.output': TerminalOutputPayload
  /** Pending gateway approvals were dropped by interrupt/reap/teardown; the wait resolved as deny (not a user refusal). */
  'approval.cancelled': ApprovalCancelledPayload
  /** 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
  /** The install ended (0 ok, -1 cancelled, -2 no sudo: the command to run by hand was streamed). */
  'display.install.done': DisplayInstallDonePayload
  /** One line of package-manager output. */
  'display.install.log': DisplayInstallLogPayload
  /** The takeover lease changed hands; every client repaints. */
  'display.lease': DisplayLeasePayload
  /** This profile's screen started or stopped (also for transitions made outside hermes serve). */
  'display.status': DisplayStatusPayload
  /** A session-level failure outside a turn (agent init, model switch, compression, resume). */
  error: ErrorPayload
  /** The account service wants a browser challenge cleared before the free-tier token exchange (broadcast); the desktop loads ``url`` in a hidden window. */
  'free_tier.challenge': FreeTierChallengePayload
  /** First frame of a connection: the resolved skin, the change-event capability and the replay epoch. */
  'gateway.ready': GatewayReadyPayload
  /** The turn ended: final text, usage and outcome. */
  'message.complete': MessageCompletePayload
  /** One streamed chunk of the assistant reply (null text: segment boundary). */
  'message.delta': MessageDeltaPayload
  /** 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; an automation turn carries its async-result card. */
  'message.start': MessageStartPayload
  /** 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
  /** A first-run onboarding run ended; sent to every connected window. */
  'onboarding.ended': OnboardingEndedPayload
  /** 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
  /** projects.db moved; refetch the project list + tree. */
  'projects.changed': ChangeSignalPayload
  /** 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
  /** A skill root moved (installed/removed elsewhere); refetch commands.catalog from the gateway. */
  'skills.changed': ChangeSignalPayload
  /** 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
  /** Live progress of a running tool call (MCP notifications/progress). */
  'tool.progress': ToolProgressPayload
  /** A tool call began (stable id + full args). */
  'tool.start': ToolStartPayload
  /** Barge-in: the spoken interjection interrupted the turn; no payload. */
  'voice.interrupted': Record<string, never>
  /** Live STT text so far while the user is still speaking. */
  'voice.partial': VoicePartialPayload
  /** 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.print',
  'agent.terminal.output',
  'approval.cancelled',
  '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',
  'display.install.done',
  'display.install.log',
  'display.lease',
  'display.status',
  'error',
  'free_tier.challenge',
  'gateway.ready',
  'message.complete',
  'message.delta',
  'message.interim',
  'message.reaction',
  'message.start',
  'moa.aggregating',
  'moa.phase',
  'moa.progress',
  'moa.reference',
  'notice',
  'notification.clear',
  'notification.show',
  'onboarding.ended',
  'pairing.changed',
  'pane.reveal',
  'pet.changed',
  'pet.generate.progress',
  'pet.hatch.progress',
  'platforms.changed',
  'preview.close',
  'preview.open',
  'preview.restart.complete',
  'preview.restart.progress',
  'projects.changed',
  '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',
  'skills.changed',
  '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.progress',
  'tool.start',
  'voice.interrupted',
  'voice.partial',
  'voice.status',
  'voice.transcript',
  'wake.detected'
] as const satisfies readonly BackendGatewayEventName[]
